Commit 51ce5f33 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma

Pull rdma fixes from Doug Ledford:

 "I had thought at the time of the last pull request that there wouldn't
  be much more to go, but several things just kept trickling in over the
  last week.

  Instead of just the six patches to bnxt_re that I had anticipated,
  there are another five IPoIB patches, two qedr patches, and a few
  other miscellaneous patches.

  The bnxt_re patches are more lines of diff than I like to submit this
  late in the game. That's mostly because of the first two patches in
  the series of six. I almost dropped them just because of the lines of
  churn, but on a close review, a lot of the churn came from removing
  duplicated code sections and consolidating them into callable
  routines. I felt like this made the number of lines of change more
  acceptable, and they address problems, so I left them. The remainder
  of the patches are all small, well contained, and well understood.

  These have passed 0day testing, but have not been submitted to
  linux-next (but a local merge test with your current master was
  without any conflicts).

  Summary:

   - A fix for fix eea40b8f ("infiniband: call ipv6 route lookup via
     the stub interface")

   - Six patches against bnxt_re...the first two are considerably larger
     than I would like, but as they address real issues I went ahead and
     submitted them (it also helped that a good deal of the churn was
     removing code repeated in multiple places and consolidating it to
     one common function)

   - Two fixes against qedr that just came in

   - One fix against rxe that took a few revisions to get right plus
     time to get the proper reviews

   - Five late breaking IPoIB fixes

   - One late cxgb4 fix"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma:
  rdma/cxgb4: Fix memory leaks during module exit
  IB/ipoib: Fix memory leak in create child syscall
  IB/ipoib: Fix access to un-initialized napi struct
  IB/ipoib: Delete napi in device uninit default
  IB/ipoib: Limit call to free rdma_netdev for capable devices
  IB/ipoib: Fix memory leaks for child interfaces priv
  rxe: Fix a sleep-in-atomic bug in post_one_send
  RDMA/qedr: Add 64KB PAGE_SIZE support to user-space queues
  RDMA/qedr: Initialize byte_len in WC of READ and SEND commands
  RDMA/bnxt_re: Remove FMR support
  RDMA/bnxt_re: Fix RQE posting logic
  RDMA/bnxt_re: Add HW workaround for avoiding stall for UD QPs
  RDMA/bnxt_re: Dereg MR in FW before freeing the fast_reg_page_list
  RDMA/bnxt_re: HW workarounds for handling specific conditions
  RDMA/bnxt_re: Fixing the Control path command and response handling
  IB/addr: Fix setting source address in addr6_resolve()
parents f69d64de d4702645
...@@ -449,12 +449,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, ...@@ -449,12 +449,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
return ret; return ret;
rt = (struct rt6_info *)dst; rt = (struct rt6_info *)dst;
if (ipv6_addr_any(&fl6.saddr)) { if (ipv6_addr_any(&src_in->sin6_addr)) {
ret = ipv6_dev_get_saddr(addr->net, ip6_dst_idev(dst)->dev,
&fl6.daddr, 0, &fl6.saddr);
if (ret)
goto put;
src_in->sin6_family = AF_INET6; src_in->sin6_family = AF_INET6;
src_in->sin6_addr = fl6.saddr; src_in->sin6_addr = fl6.saddr;
} }
...@@ -471,9 +466,6 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, ...@@ -471,9 +466,6 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
*pdst = dst; *pdst = dst;
return 0; return 0;
put:
dst_release(dst);
return ret;
} }
#else #else
static int addr6_resolve(struct sockaddr_in6 *src_in, static int addr6_resolve(struct sockaddr_in6 *src_in,
......
...@@ -56,6 +56,10 @@ ...@@ -56,6 +56,10 @@
#define BNXT_RE_MAX_SRQC_COUNT (64 * 1024) #define BNXT_RE_MAX_SRQC_COUNT (64 * 1024)
#define BNXT_RE_MAX_CQ_COUNT (64 * 1024) #define BNXT_RE_MAX_CQ_COUNT (64 * 1024)
#define BNXT_RE_UD_QP_HW_STALL 0x400000
#define BNXT_RE_RQ_WQE_THRESHOLD 32
struct bnxt_re_work { struct bnxt_re_work {
struct work_struct work; struct work_struct work;
unsigned long event; unsigned long event;
......
...@@ -61,6 +61,48 @@ ...@@ -61,6 +61,48 @@
#include "ib_verbs.h" #include "ib_verbs.h"
#include <rdma/bnxt_re-abi.h> #include <rdma/bnxt_re-abi.h>
static int __from_ib_access_flags(int iflags)
{
int qflags = 0;
if (iflags & IB_ACCESS_LOCAL_WRITE)
qflags |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
if (iflags & IB_ACCESS_REMOTE_READ)
qflags |= BNXT_QPLIB_ACCESS_REMOTE_READ;
if (iflags & IB_ACCESS_REMOTE_WRITE)
qflags |= BNXT_QPLIB_ACCESS_REMOTE_WRITE;
if (iflags & IB_ACCESS_REMOTE_ATOMIC)
qflags |= BNXT_QPLIB_ACCESS_REMOTE_ATOMIC;
if (iflags & IB_ACCESS_MW_BIND)
qflags |= BNXT_QPLIB_ACCESS_MW_BIND;
if (iflags & IB_ZERO_BASED)
qflags |= BNXT_QPLIB_ACCESS_ZERO_BASED;
if (iflags & IB_ACCESS_ON_DEMAND)
qflags |= BNXT_QPLIB_ACCESS_ON_DEMAND;
return qflags;
};
static enum ib_access_flags __to_ib_access_flags(int qflags)
{
enum ib_access_flags iflags = 0;
if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE)
iflags |= IB_ACCESS_LOCAL_WRITE;
if (qflags & BNXT_QPLIB_ACCESS_REMOTE_WRITE)
iflags |= IB_ACCESS_REMOTE_WRITE;
if (qflags & BNXT_QPLIB_ACCESS_REMOTE_READ)
iflags |= IB_ACCESS_REMOTE_READ;
if (qflags & BNXT_QPLIB_ACCESS_REMOTE_ATOMIC)
iflags |= IB_ACCESS_REMOTE_ATOMIC;
if (qflags & BNXT_QPLIB_ACCESS_MW_BIND)
iflags |= IB_ACCESS_MW_BIND;
if (qflags & BNXT_QPLIB_ACCESS_ZERO_BASED)
iflags |= IB_ZERO_BASED;
if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND)
iflags |= IB_ACCESS_ON_DEMAND;
return iflags;
};
static int bnxt_re_build_sgl(struct ib_sge *ib_sg_list, static int bnxt_re_build_sgl(struct ib_sge *ib_sg_list,
struct bnxt_qplib_sge *sg_list, int num) struct bnxt_qplib_sge *sg_list, int num)
{ {
...@@ -149,8 +191,8 @@ int bnxt_re_query_device(struct ib_device *ibdev, ...@@ -149,8 +191,8 @@ int bnxt_re_query_device(struct ib_device *ibdev,
ib_attr->max_total_mcast_qp_attach = 0; ib_attr->max_total_mcast_qp_attach = 0;
ib_attr->max_ah = dev_attr->max_ah; ib_attr->max_ah = dev_attr->max_ah;
ib_attr->max_fmr = dev_attr->max_fmr; ib_attr->max_fmr = 0;
ib_attr->max_map_per_fmr = 1; /* ? */ ib_attr->max_map_per_fmr = 0;
ib_attr->max_srq = dev_attr->max_srq; ib_attr->max_srq = dev_attr->max_srq;
ib_attr->max_srq_wr = dev_attr->max_srq_wqes; ib_attr->max_srq_wr = dev_attr->max_srq_wqes;
...@@ -410,6 +452,158 @@ enum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev, ...@@ -410,6 +452,158 @@ enum rdma_link_layer bnxt_re_get_link_layer(struct ib_device *ibdev,
return IB_LINK_LAYER_ETHERNET; return IB_LINK_LAYER_ETHERNET;
} }
#define BNXT_RE_FENCE_PBL_SIZE DIV_ROUND_UP(BNXT_RE_FENCE_BYTES, PAGE_SIZE)
static void bnxt_re_create_fence_wqe(struct bnxt_re_pd *pd)
{
struct bnxt_re_fence_data *fence = &pd->fence;
struct ib_mr *ib_mr = &fence->mr->ib_mr;
struct bnxt_qplib_swqe *wqe = &fence->bind_wqe;
memset(wqe, 0, sizeof(*wqe));
wqe->type = BNXT_QPLIB_SWQE_TYPE_BIND_MW;
wqe->wr_id = BNXT_QPLIB_FENCE_WRID;
wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_SIGNAL_COMP;
wqe->flags |= BNXT_QPLIB_SWQE_FLAGS_UC_FENCE;
wqe->bind.zero_based = false;
wqe->bind.parent_l_key = ib_mr->lkey;
wqe->bind.va = (u64)(unsigned long)fence->va;
wqe->bind.length = fence->size;
wqe->bind.access_cntl = __from_ib_access_flags(IB_ACCESS_REMOTE_READ);
wqe->bind.mw_type = SQ_BIND_MW_TYPE_TYPE1;
/* Save the initial rkey in fence structure for now;
* wqe->bind.r_key will be set at (re)bind time.
*/
fence->bind_rkey = ib_inc_rkey(fence->mw->rkey);
}
static int bnxt_re_bind_fence_mw(struct bnxt_qplib_qp *qplib_qp)
{
struct bnxt_re_qp *qp = container_of(qplib_qp, struct bnxt_re_qp,
qplib_qp);
struct ib_pd *ib_pd = qp->ib_qp.pd;
struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
struct bnxt_re_fence_data *fence = &pd->fence;
struct bnxt_qplib_swqe *fence_wqe = &fence->bind_wqe;
struct bnxt_qplib_swqe wqe;
int rc;
memcpy(&wqe, fence_wqe, sizeof(wqe));
wqe.bind.r_key = fence->bind_rkey;
fence->bind_rkey = ib_inc_rkey(fence->bind_rkey);
dev_dbg(rdev_to_dev(qp->rdev),
"Posting bind fence-WQE: rkey: %#x QP: %d PD: %p\n",
wqe.bind.r_key, qp->qplib_qp.id, pd);
rc = bnxt_qplib_post_send(&qp->qplib_qp, &wqe);
if (rc) {
dev_err(rdev_to_dev(qp->rdev), "Failed to bind fence-WQE\n");
return rc;
}
bnxt_qplib_post_send_db(&qp->qplib_qp);
return rc;
}
static void bnxt_re_destroy_fence_mr(struct bnxt_re_pd *pd)
{
struct bnxt_re_fence_data *fence = &pd->fence;
struct bnxt_re_dev *rdev = pd->rdev;
struct device *dev = &rdev->en_dev->pdev->dev;
struct bnxt_re_mr *mr = fence->mr;
if (fence->mw) {
bnxt_re_dealloc_mw(fence->mw);
fence->mw = NULL;
}
if (mr) {
if (mr->ib_mr.rkey)
bnxt_qplib_dereg_mrw(&rdev->qplib_res, &mr->qplib_mr,
true);
if (mr->ib_mr.lkey)
bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
kfree(mr);
fence->mr = NULL;
}
if (fence->dma_addr) {
dma_unmap_single(dev, fence->dma_addr, BNXT_RE_FENCE_BYTES,
DMA_BIDIRECTIONAL);
fence->dma_addr = 0;
}
}
static int bnxt_re_create_fence_mr(struct bnxt_re_pd *pd)
{
int mr_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_MW_BIND;
struct bnxt_re_fence_data *fence = &pd->fence;
struct bnxt_re_dev *rdev = pd->rdev;
struct device *dev = &rdev->en_dev->pdev->dev;
struct bnxt_re_mr *mr = NULL;
dma_addr_t dma_addr = 0;
struct ib_mw *mw;
u64 pbl_tbl;
int rc;
dma_addr = dma_map_single(dev, fence->va, BNXT_RE_FENCE_BYTES,
DMA_BIDIRECTIONAL);
rc = dma_mapping_error(dev, dma_addr);
if (rc) {
dev_err(rdev_to_dev(rdev), "Failed to dma-map fence-MR-mem\n");
rc = -EIO;
fence->dma_addr = 0;
goto fail;
}
fence->dma_addr = dma_addr;
/* Allocate a MR */
mr = kzalloc(sizeof(*mr), GFP_KERNEL);
if (!mr) {
rc = -ENOMEM;
goto fail;
}
fence->mr = mr;
mr->rdev = rdev;
mr->qplib_mr.pd = &pd->qplib_pd;
mr->qplib_mr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR;
mr->qplib_mr.flags = __from_ib_access_flags(mr_access_flags);
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mr->qplib_mr);
if (rc) {
dev_err(rdev_to_dev(rdev), "Failed to alloc fence-HW-MR\n");
goto fail;
}
/* Register MR */
mr->ib_mr.lkey = mr->qplib_mr.lkey;
mr->qplib_mr.va = (u64)(unsigned long)fence->va;
mr->qplib_mr.total_size = BNXT_RE_FENCE_BYTES;
pbl_tbl = dma_addr;
rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &mr->qplib_mr, &pbl_tbl,
BNXT_RE_FENCE_PBL_SIZE, false);
if (rc) {
dev_err(rdev_to_dev(rdev), "Failed to register fence-MR\n");
goto fail;
}
mr->ib_mr.rkey = mr->qplib_mr.rkey;
/* Create a fence MW only for kernel consumers */
mw = bnxt_re_alloc_mw(&pd->ib_pd, IB_MW_TYPE_1, NULL);
if (!mw) {
dev_err(rdev_to_dev(rdev),
"Failed to create fence-MW for PD: %p\n", pd);
rc = -EINVAL;
goto fail;
}
fence->mw = mw;
bnxt_re_create_fence_wqe(pd);
return 0;
fail:
bnxt_re_destroy_fence_mr(pd);
return rc;
}
/* Protection Domains */ /* Protection Domains */
int bnxt_re_dealloc_pd(struct ib_pd *ib_pd) int bnxt_re_dealloc_pd(struct ib_pd *ib_pd)
{ {
...@@ -417,6 +611,7 @@ int bnxt_re_dealloc_pd(struct ib_pd *ib_pd) ...@@ -417,6 +611,7 @@ int bnxt_re_dealloc_pd(struct ib_pd *ib_pd)
struct bnxt_re_dev *rdev = pd->rdev; struct bnxt_re_dev *rdev = pd->rdev;
int rc; int rc;
bnxt_re_destroy_fence_mr(pd);
if (ib_pd->uobject && pd->dpi.dbr) { if (ib_pd->uobject && pd->dpi.dbr) {
struct ib_ucontext *ib_uctx = ib_pd->uobject->context; struct ib_ucontext *ib_uctx = ib_pd->uobject->context;
struct bnxt_re_ucontext *ucntx; struct bnxt_re_ucontext *ucntx;
...@@ -498,6 +693,10 @@ struct ib_pd *bnxt_re_alloc_pd(struct ib_device *ibdev, ...@@ -498,6 +693,10 @@ struct ib_pd *bnxt_re_alloc_pd(struct ib_device *ibdev,
} }
} }
if (!udata)
if (bnxt_re_create_fence_mr(pd))
dev_warn(rdev_to_dev(rdev),
"Failed to create Fence-MR\n");
return &pd->ib_pd; return &pd->ib_pd;
dbfail: dbfail:
(void)bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl, (void)bnxt_qplib_dealloc_pd(&rdev->qplib_res, &rdev->qplib_res.pd_tbl,
...@@ -849,12 +1048,16 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp ...@@ -849,12 +1048,16 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp
/* Shadow QP SQ depth should be same as QP1 RQ depth */ /* Shadow QP SQ depth should be same as QP1 RQ depth */
qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe; qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe;
qp->qplib_qp.sq.max_sge = 2; qp->qplib_qp.sq.max_sge = 2;
/* Q full delta can be 1 since it is internal QP */
qp->qplib_qp.sq.q_full_delta = 1;
qp->qplib_qp.scq = qp1_qp->scq; qp->qplib_qp.scq = qp1_qp->scq;
qp->qplib_qp.rcq = qp1_qp->rcq; qp->qplib_qp.rcq = qp1_qp->rcq;
qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe; qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe;
qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge; qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge;
/* Q full delta can be 1 since it is internal QP */
qp->qplib_qp.rq.q_full_delta = 1;
qp->qplib_qp.mtu = qp1_qp->mtu; qp->qplib_qp.mtu = qp1_qp->mtu;
...@@ -917,10 +1120,6 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd, ...@@ -917,10 +1120,6 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
qp->qplib_qp.sig_type = ((qp_init_attr->sq_sig_type == qp->qplib_qp.sig_type = ((qp_init_attr->sq_sig_type ==
IB_SIGNAL_ALL_WR) ? true : false); IB_SIGNAL_ALL_WR) ? true : false);
entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr + 1);
qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
dev_attr->max_qp_wqes + 1);
qp->qplib_qp.sq.max_sge = qp_init_attr->cap.max_send_sge; qp->qplib_qp.sq.max_sge = qp_init_attr->cap.max_send_sge;
if (qp->qplib_qp.sq.max_sge > dev_attr->max_qp_sges) if (qp->qplib_qp.sq.max_sge > dev_attr->max_qp_sges)
qp->qplib_qp.sq.max_sge = dev_attr->max_qp_sges; qp->qplib_qp.sq.max_sge = dev_attr->max_qp_sges;
...@@ -959,6 +1158,9 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd, ...@@ -959,6 +1158,9 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
qp->qplib_qp.rq.max_wqe = min_t(u32, entries, qp->qplib_qp.rq.max_wqe = min_t(u32, entries,
dev_attr->max_qp_wqes + 1); dev_attr->max_qp_wqes + 1);
qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
qp_init_attr->cap.max_recv_wr;
qp->qplib_qp.rq.max_sge = qp_init_attr->cap.max_recv_sge; qp->qplib_qp.rq.max_sge = qp_init_attr->cap.max_recv_sge;
if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges) if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges)
qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges; qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
...@@ -967,6 +1169,12 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd, ...@@ -967,6 +1169,12 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
qp->qplib_qp.mtu = ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu)); qp->qplib_qp.mtu = ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
if (qp_init_attr->qp_type == IB_QPT_GSI) { if (qp_init_attr->qp_type == IB_QPT_GSI) {
/* Allocate 1 more than what's provided */
entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr + 1);
qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
dev_attr->max_qp_wqes + 1);
qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe -
qp_init_attr->cap.max_send_wr;
qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges; qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges) if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges)
qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges; qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
...@@ -1006,6 +1214,22 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd, ...@@ -1006,6 +1214,22 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
} }
} else { } else {
/* Allocate 128 + 1 more than what's provided */
entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr +
BNXT_QPLIB_RESERVED_QP_WRS + 1);
qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
dev_attr->max_qp_wqes +
BNXT_QPLIB_RESERVED_QP_WRS + 1);
qp->qplib_qp.sq.q_full_delta = BNXT_QPLIB_RESERVED_QP_WRS + 1;
/*
* Reserving one slot for Phantom WQE. Application can
* post one extra entry in this case. But allowing this to avoid
* unexpected Queue full condition
*/
qp->qplib_qp.sq.q_full_delta -= 1;
qp->qplib_qp.max_rd_atomic = dev_attr->max_qp_rd_atom; qp->qplib_qp.max_rd_atomic = dev_attr->max_qp_rd_atom;
qp->qplib_qp.max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom; qp->qplib_qp.max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom;
if (udata) { if (udata) {
...@@ -1025,6 +1249,7 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd, ...@@ -1025,6 +1249,7 @@ struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
qp->ib_qp.qp_num = qp->qplib_qp.id; qp->ib_qp.qp_num = qp->qplib_qp.id;
spin_lock_init(&qp->sq_lock); spin_lock_init(&qp->sq_lock);
spin_lock_init(&qp->rq_lock);
if (udata) { if (udata) {
struct bnxt_re_qp_resp resp; struct bnxt_re_qp_resp resp;
...@@ -1129,48 +1354,6 @@ static enum ib_mtu __to_ib_mtu(u32 mtu) ...@@ -1129,48 +1354,6 @@ static enum ib_mtu __to_ib_mtu(u32 mtu)
} }
} }
static int __from_ib_access_flags(int iflags)
{
int qflags = 0;
if (iflags & IB_ACCESS_LOCAL_WRITE)
qflags |= BNXT_QPLIB_ACCESS_LOCAL_WRITE;
if (iflags & IB_ACCESS_REMOTE_READ)
qflags |= BNXT_QPLIB_ACCESS_REMOTE_READ;
if (iflags & IB_ACCESS_REMOTE_WRITE)
qflags |= BNXT_QPLIB_ACCESS_REMOTE_WRITE;
if (iflags & IB_ACCESS_REMOTE_ATOMIC)
qflags |= BNXT_QPLIB_ACCESS_REMOTE_ATOMIC;
if (iflags & IB_ACCESS_MW_BIND)
qflags |= BNXT_QPLIB_ACCESS_MW_BIND;
if (iflags & IB_ZERO_BASED)
qflags |= BNXT_QPLIB_ACCESS_ZERO_BASED;
if (iflags & IB_ACCESS_ON_DEMAND)
qflags |= BNXT_QPLIB_ACCESS_ON_DEMAND;
return qflags;
};
static enum ib_access_flags __to_ib_access_flags(int qflags)
{
enum ib_access_flags iflags = 0;
if (qflags & BNXT_QPLIB_ACCESS_LOCAL_WRITE)
iflags |= IB_ACCESS_LOCAL_WRITE;
if (qflags & BNXT_QPLIB_ACCESS_REMOTE_WRITE)
iflags |= IB_ACCESS_REMOTE_WRITE;
if (qflags & BNXT_QPLIB_ACCESS_REMOTE_READ)
iflags |= IB_ACCESS_REMOTE_READ;
if (qflags & BNXT_QPLIB_ACCESS_REMOTE_ATOMIC)
iflags |= IB_ACCESS_REMOTE_ATOMIC;
if (qflags & BNXT_QPLIB_ACCESS_MW_BIND)
iflags |= IB_ACCESS_MW_BIND;
if (qflags & BNXT_QPLIB_ACCESS_ZERO_BASED)
iflags |= IB_ZERO_BASED;
if (qflags & BNXT_QPLIB_ACCESS_ON_DEMAND)
iflags |= IB_ACCESS_ON_DEMAND;
return iflags;
};
static int bnxt_re_modify_shadow_qp(struct bnxt_re_dev *rdev, static int bnxt_re_modify_shadow_qp(struct bnxt_re_dev *rdev,
struct bnxt_re_qp *qp1_qp, struct bnxt_re_qp *qp1_qp,
int qp_attr_mask) int qp_attr_mask)
...@@ -1378,11 +1561,21 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr, ...@@ -1378,11 +1561,21 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
entries = roundup_pow_of_two(qp_attr->cap.max_send_wr); entries = roundup_pow_of_two(qp_attr->cap.max_send_wr);
qp->qplib_qp.sq.max_wqe = min_t(u32, entries, qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
dev_attr->max_qp_wqes + 1); dev_attr->max_qp_wqes + 1);
qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe -
qp_attr->cap.max_send_wr;
/*
* Reserving one slot for Phantom WQE. Some application can
* post one extra entry in this case. Allowing this to avoid
* unexpected Queue full condition
*/
qp->qplib_qp.sq.q_full_delta -= 1;
qp->qplib_qp.sq.max_sge = qp_attr->cap.max_send_sge; qp->qplib_qp.sq.max_sge = qp_attr->cap.max_send_sge;
if (qp->qplib_qp.rq.max_wqe) { if (qp->qplib_qp.rq.max_wqe) {
entries = roundup_pow_of_two(qp_attr->cap.max_recv_wr); entries = roundup_pow_of_two(qp_attr->cap.max_recv_wr);
qp->qplib_qp.rq.max_wqe = qp->qplib_qp.rq.max_wqe =
min_t(u32, entries, dev_attr->max_qp_wqes + 1); min_t(u32, entries, dev_attr->max_qp_wqes + 1);
qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
qp_attr->cap.max_recv_wr;
qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge; qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge;
} else { } else {
/* SRQ was used prior, just ignore the RQ caps */ /* SRQ was used prior, just ignore the RQ caps */
...@@ -1883,6 +2076,22 @@ static int bnxt_re_copy_wr_payload(struct bnxt_re_dev *rdev, ...@@ -1883,6 +2076,22 @@ static int bnxt_re_copy_wr_payload(struct bnxt_re_dev *rdev,
return payload_sz; return payload_sz;
} }
static void bnxt_ud_qp_hw_stall_workaround(struct bnxt_re_qp *qp)
{
if ((qp->ib_qp.qp_type == IB_QPT_UD ||
qp->ib_qp.qp_type == IB_QPT_GSI ||
qp->ib_qp.qp_type == IB_QPT_RAW_ETHERTYPE) &&
qp->qplib_qp.wqe_cnt == BNXT_RE_UD_QP_HW_STALL) {
int qp_attr_mask;
struct ib_qp_attr qp_attr;
qp_attr_mask = IB_QP_STATE;
qp_attr.qp_state = IB_QPS_RTS;
bnxt_re_modify_qp(&qp->ib_qp, &qp_attr, qp_attr_mask, NULL);
qp->qplib_qp.wqe_cnt = 0;
}
}
static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev, static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev,
struct bnxt_re_qp *qp, struct bnxt_re_qp *qp,
struct ib_send_wr *wr) struct ib_send_wr *wr)
...@@ -1928,6 +2137,7 @@ static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev, ...@@ -1928,6 +2137,7 @@ static int bnxt_re_post_send_shadow_qp(struct bnxt_re_dev *rdev,
wr = wr->next; wr = wr->next;
} }
bnxt_qplib_post_send_db(&qp->qplib_qp); bnxt_qplib_post_send_db(&qp->qplib_qp);
bnxt_ud_qp_hw_stall_workaround(qp);
spin_unlock_irqrestore(&qp->sq_lock, flags); spin_unlock_irqrestore(&qp->sq_lock, flags);
return rc; return rc;
} }
...@@ -2024,6 +2234,7 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, struct ib_send_wr *wr, ...@@ -2024,6 +2234,7 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, struct ib_send_wr *wr,
wr = wr->next; wr = wr->next;
} }
bnxt_qplib_post_send_db(&qp->qplib_qp); bnxt_qplib_post_send_db(&qp->qplib_qp);
bnxt_ud_qp_hw_stall_workaround(qp);
spin_unlock_irqrestore(&qp->sq_lock, flags); spin_unlock_irqrestore(&qp->sq_lock, flags);
return rc; return rc;
...@@ -2071,7 +2282,10 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, struct ib_recv_wr *wr, ...@@ -2071,7 +2282,10 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, struct ib_recv_wr *wr,
struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp); struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
struct bnxt_qplib_swqe wqe; struct bnxt_qplib_swqe wqe;
int rc = 0, payload_sz = 0; int rc = 0, payload_sz = 0;
unsigned long flags;
u32 count = 0;
spin_lock_irqsave(&qp->rq_lock, flags);
while (wr) { while (wr) {
/* House keeping */ /* House keeping */
memset(&wqe, 0, sizeof(wqe)); memset(&wqe, 0, sizeof(wqe));
...@@ -2100,9 +2314,21 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, struct ib_recv_wr *wr, ...@@ -2100,9 +2314,21 @@ int bnxt_re_post_recv(struct ib_qp *ib_qp, struct ib_recv_wr *wr,
*bad_wr = wr; *bad_wr = wr;
break; break;
} }
/* Ring DB if the RQEs posted reaches a threshold value */
if (++count >= BNXT_RE_RQ_WQE_THRESHOLD) {
bnxt_qplib_post_recv_db(&qp->qplib_qp);
count = 0;
}
wr = wr->next; wr = wr->next;
} }
if (count)
bnxt_qplib_post_recv_db(&qp->qplib_qp); bnxt_qplib_post_recv_db(&qp->qplib_qp);
spin_unlock_irqrestore(&qp->rq_lock, flags);
return rc; return rc;
} }
...@@ -2643,12 +2869,36 @@ static void bnxt_re_process_res_ud_wc(struct ib_wc *wc, ...@@ -2643,12 +2869,36 @@ static void bnxt_re_process_res_ud_wc(struct ib_wc *wc,
wc->opcode = IB_WC_RECV_RDMA_WITH_IMM; wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
} }
static int send_phantom_wqe(struct bnxt_re_qp *qp)
{
struct bnxt_qplib_qp *lib_qp = &qp->qplib_qp;
unsigned long flags;
int rc = 0;
spin_lock_irqsave(&qp->sq_lock, flags);
rc = bnxt_re_bind_fence_mw(lib_qp);
if (!rc) {
lib_qp->sq.phantom_wqe_cnt++;
dev_dbg(&lib_qp->sq.hwq.pdev->dev,
"qp %#x sq->prod %#x sw_prod %#x phantom_wqe_cnt %d\n",
lib_qp->id, lib_qp->sq.hwq.prod,
HWQ_CMP(lib_qp->sq.hwq.prod, &lib_qp->sq.hwq),
lib_qp->sq.phantom_wqe_cnt);
}
spin_unlock_irqrestore(&qp->sq_lock, flags);
return rc;
}
int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc) int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
{ {
struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq); struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
struct bnxt_re_qp *qp; struct bnxt_re_qp *qp;
struct bnxt_qplib_cqe *cqe; struct bnxt_qplib_cqe *cqe;
int i, ncqe, budget; int i, ncqe, budget;
struct bnxt_qplib_q *sq;
struct bnxt_qplib_qp *lib_qp;
u32 tbl_idx; u32 tbl_idx;
struct bnxt_re_sqp_entries *sqp_entry = NULL; struct bnxt_re_sqp_entries *sqp_entry = NULL;
unsigned long flags; unsigned long flags;
...@@ -2661,7 +2911,21 @@ int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc) ...@@ -2661,7 +2911,21 @@ int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
} }
cqe = &cq->cql[0]; cqe = &cq->cql[0];
while (budget) { while (budget) {
ncqe = bnxt_qplib_poll_cq(&cq->qplib_cq, cqe, budget); lib_qp = NULL;
ncqe = bnxt_qplib_poll_cq(&cq->qplib_cq, cqe, budget, &lib_qp);
if (lib_qp) {
sq = &lib_qp->sq;
if (sq->send_phantom) {
qp = container_of(lib_qp,
struct bnxt_re_qp, qplib_qp);
if (send_phantom_wqe(qp) == -ENOMEM)
dev_err(rdev_to_dev(cq->rdev),
"Phantom failed! Scheduled to send again\n");
else
sq->send_phantom = false;
}
}
if (!ncqe) if (!ncqe)
break; break;
...@@ -2822,6 +3086,12 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr) ...@@ -2822,6 +3086,12 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr)
struct bnxt_re_dev *rdev = mr->rdev; struct bnxt_re_dev *rdev = mr->rdev;
int rc; int rc;
rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
if (rc) {
dev_err(rdev_to_dev(rdev), "Dereg MR failed: %#x\n", rc);
return rc;
}
if (mr->npages && mr->pages) { if (mr->npages && mr->pages) {
rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res, rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res,
&mr->qplib_frpl); &mr->qplib_frpl);
...@@ -2829,8 +3099,6 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr) ...@@ -2829,8 +3099,6 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr)
mr->npages = 0; mr->npages = 0;
mr->pages = NULL; mr->pages = NULL;
} }
rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
if (!IS_ERR_OR_NULL(mr->ib_umem)) if (!IS_ERR_OR_NULL(mr->ib_umem))
ib_umem_release(mr->ib_umem); ib_umem_release(mr->ib_umem);
...@@ -2914,97 +3182,52 @@ struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type, ...@@ -2914,97 +3182,52 @@ struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type type,
return ERR_PTR(rc); return ERR_PTR(rc);
} }
/* Fast Memory Regions */ struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
struct ib_fmr *bnxt_re_alloc_fmr(struct ib_pd *ib_pd, int mr_access_flags, struct ib_udata *udata)
struct ib_fmr_attr *fmr_attr)
{ {
struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd); struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
struct bnxt_re_dev *rdev = pd->rdev; struct bnxt_re_dev *rdev = pd->rdev;
struct bnxt_re_fmr *fmr; struct bnxt_re_mw *mw;
int rc; int rc;
if (fmr_attr->max_pages > MAX_PBL_LVL_2_PGS || mw = kzalloc(sizeof(*mw), GFP_KERNEL);
fmr_attr->max_maps > rdev->dev_attr.max_map_per_fmr) { if (!mw)
dev_err(rdev_to_dev(rdev), "Allocate FMR exceeded Max limit");
return ERR_PTR(-ENOMEM);
}
fmr = kzalloc(sizeof(*fmr), GFP_KERNEL);
if (!fmr)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
mw->rdev = rdev;
mw->qplib_mw.pd = &pd->qplib_pd;
fmr->rdev = rdev; mw->qplib_mw.type = (type == IB_MW_TYPE_1 ?
fmr->qplib_fmr.pd = &pd->qplib_pd; CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1 :
fmr->qplib_fmr.type = CMDQ_ALLOCATE_MRW_MRW_FLAGS_PMR; CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B);
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &mw->qplib_mw);
rc = bnxt_qplib_alloc_mrw(&rdev->qplib_res, &fmr->qplib_fmr); if (rc) {
if (rc) dev_err(rdev_to_dev(rdev), "Allocate MW failed!");
goto fail; goto fail;
}
mw->ib_mw.rkey = mw->qplib_mw.rkey;
fmr->qplib_fmr.flags = __from_ib_access_flags(mr_access_flags); atomic_inc(&rdev->mw_count);
fmr->ib_fmr.lkey = fmr->qplib_fmr.lkey; return &mw->ib_mw;
fmr->ib_fmr.rkey = fmr->ib_fmr.lkey;
atomic_inc(&rdev->mr_count);
return &fmr->ib_fmr;
fail: fail:
kfree(fmr); kfree(mw);
return ERR_PTR(rc); return ERR_PTR(rc);
} }
int bnxt_re_map_phys_fmr(struct ib_fmr *ib_fmr, u64 *page_list, int list_len, int bnxt_re_dealloc_mw(struct ib_mw *ib_mw)
u64 iova)
{ {
struct bnxt_re_fmr *fmr = container_of(ib_fmr, struct bnxt_re_fmr, struct bnxt_re_mw *mw = container_of(ib_mw, struct bnxt_re_mw, ib_mw);
ib_fmr); struct bnxt_re_dev *rdev = mw->rdev;
struct bnxt_re_dev *rdev = fmr->rdev;
int rc; int rc;
fmr->qplib_fmr.va = iova; rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mw->qplib_mw);
fmr->qplib_fmr.total_size = list_len * PAGE_SIZE; if (rc) {
dev_err(rdev_to_dev(rdev), "Free MW failed: %#x\n", rc);
rc = bnxt_qplib_reg_mr(&rdev->qplib_res, &fmr->qplib_fmr, page_list,
list_len, true);
if (rc)
dev_err(rdev_to_dev(rdev), "Failed to map FMR for lkey = 0x%x!",
fmr->ib_fmr.lkey);
return rc; return rc;
}
int bnxt_re_unmap_fmr(struct list_head *fmr_list)
{
struct bnxt_re_dev *rdev;
struct bnxt_re_fmr *fmr;
struct ib_fmr *ib_fmr;
int rc = 0;
/* Validate each FMRs inside the fmr_list */
list_for_each_entry(ib_fmr, fmr_list, list) {
fmr = container_of(ib_fmr, struct bnxt_re_fmr, ib_fmr);
rdev = fmr->rdev;
if (rdev) {
rc = bnxt_qplib_dereg_mrw(&rdev->qplib_res,
&fmr->qplib_fmr, true);
if (rc)
break;
}
} }
return rc;
}
int bnxt_re_dealloc_fmr(struct ib_fmr *ib_fmr)
{
struct bnxt_re_fmr *fmr = container_of(ib_fmr, struct bnxt_re_fmr,
ib_fmr);
struct bnxt_re_dev *rdev = fmr->rdev;
int rc;
rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &fmr->qplib_fmr); kfree(mw);
if (rc) atomic_dec(&rdev->mw_count);
dev_err(rdev_to_dev(rdev), "Failed to free FMR");
kfree(fmr);
atomic_dec(&rdev->mr_count);
return rc; return rc;
} }
......
...@@ -44,11 +44,23 @@ struct bnxt_re_gid_ctx { ...@@ -44,11 +44,23 @@ struct bnxt_re_gid_ctx {
u32 refcnt; u32 refcnt;
}; };
#define BNXT_RE_FENCE_BYTES 64
struct bnxt_re_fence_data {
u32 size;
u8 va[BNXT_RE_FENCE_BYTES];
dma_addr_t dma_addr;
struct bnxt_re_mr *mr;
struct ib_mw *mw;
struct bnxt_qplib_swqe bind_wqe;
u32 bind_rkey;
};
struct bnxt_re_pd { struct bnxt_re_pd {
struct bnxt_re_dev *rdev; struct bnxt_re_dev *rdev;
struct ib_pd ib_pd; struct ib_pd ib_pd;
struct bnxt_qplib_pd qplib_pd; struct bnxt_qplib_pd qplib_pd;
struct bnxt_qplib_dpi dpi; struct bnxt_qplib_dpi dpi;
struct bnxt_re_fence_data fence;
}; };
struct bnxt_re_ah { struct bnxt_re_ah {
...@@ -62,6 +74,7 @@ struct bnxt_re_qp { ...@@ -62,6 +74,7 @@ struct bnxt_re_qp {
struct bnxt_re_dev *rdev; struct bnxt_re_dev *rdev;
struct ib_qp ib_qp; struct ib_qp ib_qp;
spinlock_t sq_lock; /* protect sq */ spinlock_t sq_lock; /* protect sq */
spinlock_t rq_lock; /* protect rq */
struct bnxt_qplib_qp qplib_qp; struct bnxt_qplib_qp qplib_qp;
struct ib_umem *sumem; struct ib_umem *sumem;
struct ib_umem *rumem; struct ib_umem *rumem;
...@@ -181,12 +194,9 @@ int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents, ...@@ -181,12 +194,9 @@ int bnxt_re_map_mr_sg(struct ib_mr *ib_mr, struct scatterlist *sg, int sg_nents,
struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type mr_type, struct ib_mr *bnxt_re_alloc_mr(struct ib_pd *ib_pd, enum ib_mr_type mr_type,
u32 max_num_sg); u32 max_num_sg);
int bnxt_re_dereg_mr(struct ib_mr *mr); int bnxt_re_dereg_mr(struct ib_mr *mr);
struct ib_fmr *bnxt_re_alloc_fmr(struct ib_pd *pd, int mr_access_flags, struct ib_mw *bnxt_re_alloc_mw(struct ib_pd *ib_pd, enum ib_mw_type type,
struct ib_fmr_attr *fmr_attr); struct ib_udata *udata);
int bnxt_re_map_phys_fmr(struct ib_fmr *fmr, u64 *page_list, int list_len, int bnxt_re_dealloc_mw(struct ib_mw *mw);
u64 iova);
int bnxt_re_unmap_fmr(struct list_head *fmr_list);
int bnxt_re_dealloc_fmr(struct ib_fmr *fmr);
struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
u64 virt_addr, int mr_access_flags, u64 virt_addr, int mr_access_flags,
struct ib_udata *udata); struct ib_udata *udata);
......
...@@ -507,10 +507,6 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev) ...@@ -507,10 +507,6 @@ static int bnxt_re_register_ib(struct bnxt_re_dev *rdev)
ibdev->dereg_mr = bnxt_re_dereg_mr; ibdev->dereg_mr = bnxt_re_dereg_mr;
ibdev->alloc_mr = bnxt_re_alloc_mr; ibdev->alloc_mr = bnxt_re_alloc_mr;
ibdev->map_mr_sg = bnxt_re_map_mr_sg; ibdev->map_mr_sg = bnxt_re_map_mr_sg;
ibdev->alloc_fmr = bnxt_re_alloc_fmr;
ibdev->map_phys_fmr = bnxt_re_map_phys_fmr;
ibdev->unmap_fmr = bnxt_re_unmap_fmr;
ibdev->dealloc_fmr = bnxt_re_dealloc_fmr;
ibdev->reg_user_mr = bnxt_re_reg_user_mr; ibdev->reg_user_mr = bnxt_re_reg_user_mr;
ibdev->alloc_ucontext = bnxt_re_alloc_ucontext; ibdev->alloc_ucontext = bnxt_re_alloc_ucontext;
......
...@@ -284,7 +284,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) ...@@ -284,7 +284,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_create_qp1 req; struct cmdq_create_qp1 req;
struct creq_create_qp1_resp *resp; struct creq_create_qp1_resp resp;
struct bnxt_qplib_pbl *pbl; struct bnxt_qplib_pbl *pbl;
struct bnxt_qplib_q *sq = &qp->sq; struct bnxt_qplib_q *sq = &qp->sq;
struct bnxt_qplib_q *rq = &qp->rq; struct bnxt_qplib_q *rq = &qp->rq;
...@@ -394,31 +394,12 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) ...@@ -394,31 +394,12 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
req.pd_id = cpu_to_le32(qp->pd->id); req.pd_id = cpu_to_le32(qp->pd->id);
resp = (struct creq_create_qp1_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 0);
NULL, 0); if (rc)
if (!resp) {
dev_err(&res->pdev->dev, "QPLIB: FP: CREATE_QP1 send failed");
rc = -EINVAL;
goto fail;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP1 timed out");
rc = -ETIMEDOUT;
goto fail;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP1 failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
rc = -EINVAL;
goto fail; goto fail;
}
qp->id = le32_to_cpu(resp->xid); qp->id = le32_to_cpu(resp.xid);
qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET; qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET;
sq->flush_in_progress = false; sq->flush_in_progress = false;
rq->flush_in_progress = false; rq->flush_in_progress = false;
...@@ -442,7 +423,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) ...@@ -442,7 +423,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct sq_send *hw_sq_send_hdr, **hw_sq_send_ptr; struct sq_send *hw_sq_send_hdr, **hw_sq_send_ptr;
struct cmdq_create_qp req; struct cmdq_create_qp req;
struct creq_create_qp_resp *resp; struct creq_create_qp_resp resp;
struct bnxt_qplib_pbl *pbl; struct bnxt_qplib_pbl *pbl;
struct sq_psn_search **psn_search_ptr; struct sq_psn_search **psn_search_ptr;
unsigned long int psn_search, poff = 0; unsigned long int psn_search, poff = 0;
...@@ -627,31 +608,12 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) ...@@ -627,31 +608,12 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
} }
req.pd_id = cpu_to_le32(qp->pd->id); req.pd_id = cpu_to_le32(qp->pd->id);
resp = (struct creq_create_qp_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 0);
NULL, 0); if (rc)
if (!resp) {
dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP send failed");
rc = -EINVAL;
goto fail;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP timed out");
rc = -ETIMEDOUT;
goto fail;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_QP failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
rc = -EINVAL;
goto fail; goto fail;
}
qp->id = le32_to_cpu(resp->xid); qp->id = le32_to_cpu(resp.xid);
qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET; qp->cur_qp_state = CMDQ_MODIFY_QP_NEW_STATE_RESET;
sq->flush_in_progress = false; sq->flush_in_progress = false;
rq->flush_in_progress = false; rq->flush_in_progress = false;
...@@ -769,10 +731,11 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) ...@@ -769,10 +731,11 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_modify_qp req; struct cmdq_modify_qp req;
struct creq_modify_qp_resp *resp; struct creq_modify_qp_resp resp;
u16 cmd_flags = 0, pkey; u16 cmd_flags = 0, pkey;
u32 temp32[4]; u32 temp32[4];
u32 bmask; u32 bmask;
int rc;
RCFW_CMD_PREP(req, MODIFY_QP, cmd_flags); RCFW_CMD_PREP(req, MODIFY_QP, cmd_flags);
...@@ -862,27 +825,10 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) ...@@ -862,27 +825,10 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
req.vlan_pcp_vlan_dei_vlan_id = cpu_to_le16(qp->vlan_id); req.vlan_pcp_vlan_dei_vlan_id = cpu_to_le16(qp->vlan_id);
resp = (struct creq_modify_qp_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 0);
NULL, 0); if (rc)
if (!resp) { return rc;
dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: FP: MODIFY_QP failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
qp->cur_qp_state = qp->state; qp->cur_qp_state = qp->state;
return 0; return 0;
} }
...@@ -891,37 +837,26 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) ...@@ -891,37 +837,26 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_query_qp req; struct cmdq_query_qp req;
struct creq_query_qp_resp *resp; struct creq_query_qp_resp resp;
struct bnxt_qplib_rcfw_sbuf *sbuf;
struct creq_query_qp_resp_sb *sb; struct creq_query_qp_resp_sb *sb;
u16 cmd_flags = 0; u16 cmd_flags = 0;
u32 temp32[4]; u32 temp32[4];
int i; int i, rc = 0;
RCFW_CMD_PREP(req, QUERY_QP, cmd_flags); RCFW_CMD_PREP(req, QUERY_QP, cmd_flags);
sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
if (!sbuf)
return -ENOMEM;
sb = sbuf->sb;
req.qp_cid = cpu_to_le32(qp->id); req.qp_cid = cpu_to_le32(qp->id);
req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
resp = (struct creq_query_qp_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)sbuf, 0);
(void **)&sb, 0); if (rc)
if (!resp) { goto bail;
dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: FP: QUERY_QP failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
/* Extract the context from the side buffer */ /* Extract the context from the side buffer */
qp->state = sb->en_sqd_async_notify_state & qp->state = sb->en_sqd_async_notify_state &
CREQ_QUERY_QP_RESP_SB_STATE_MASK; CREQ_QUERY_QP_RESP_SB_STATE_MASK;
...@@ -976,7 +911,9 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) ...@@ -976,7 +911,9 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
qp->dest_qpn = le32_to_cpu(sb->dest_qp_id); qp->dest_qpn = le32_to_cpu(sb->dest_qp_id);
memcpy(qp->smac, sb->src_mac, 6); memcpy(qp->smac, sb->src_mac, 6);
qp->vlan_id = le16_to_cpu(sb->vlan_pcp_vlan_dei_vlan_id); qp->vlan_id = le16_to_cpu(sb->vlan_pcp_vlan_dei_vlan_id);
return 0; bail:
bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
return rc;
} }
static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp) static void __clean_cq(struct bnxt_qplib_cq *cq, u64 qp)
...@@ -1021,34 +958,18 @@ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res, ...@@ -1021,34 +958,18 @@ int bnxt_qplib_destroy_qp(struct bnxt_qplib_res *res,
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_destroy_qp req; struct cmdq_destroy_qp req;
struct creq_destroy_qp_resp *resp; struct creq_destroy_qp_resp resp;
unsigned long flags; unsigned long flags;
u16 cmd_flags = 0; u16 cmd_flags = 0;
int rc;
RCFW_CMD_PREP(req, DESTROY_QP, cmd_flags); RCFW_CMD_PREP(req, DESTROY_QP, cmd_flags);
req.qp_cid = cpu_to_le32(qp->id); req.qp_cid = cpu_to_le32(qp->id);
resp = (struct creq_destroy_qp_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 0);
NULL, 0); if (rc)
if (!resp) { return rc;
dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_QP failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
/* Must walk the associated CQs to nullified the QP ptr */ /* Must walk the associated CQs to nullified the QP ptr */
spin_lock_irqsave(&qp->scq->hwq.lock, flags); spin_lock_irqsave(&qp->scq->hwq.lock, flags);
...@@ -1162,8 +1083,12 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, ...@@ -1162,8 +1083,12 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
rc = -EINVAL; rc = -EINVAL;
goto done; goto done;
} }
if (HWQ_CMP((sq->hwq.prod + 1), &sq->hwq) ==
HWQ_CMP(sq->hwq.cons, &sq->hwq)) { if (bnxt_qplib_queue_full(sq)) {
dev_err(&sq->hwq.pdev->dev,
"QPLIB: prod = %#x cons = %#x qdepth = %#x delta = %#x",
sq->hwq.prod, sq->hwq.cons, sq->hwq.max_elements,
sq->q_full_delta);
rc = -ENOMEM; rc = -ENOMEM;
goto done; goto done;
} }
...@@ -1373,6 +1298,9 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, ...@@ -1373,6 +1298,9 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp,
} }
sq->hwq.prod++; sq->hwq.prod++;
qp->wqe_cnt++;
done: done:
return rc; return rc;
} }
...@@ -1411,8 +1339,7 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp, ...@@ -1411,8 +1339,7 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp,
rc = -EINVAL; rc = -EINVAL;
goto done; goto done;
} }
if (HWQ_CMP((rq->hwq.prod + 1), &rq->hwq) == if (bnxt_qplib_queue_full(rq)) {
HWQ_CMP(rq->hwq.cons, &rq->hwq)) {
dev_err(&rq->hwq.pdev->dev, dev_err(&rq->hwq.pdev->dev,
"QPLIB: FP: QP (0x%x) RQ is full!", qp->id); "QPLIB: FP: QP (0x%x) RQ is full!", qp->id);
rc = -EINVAL; rc = -EINVAL;
...@@ -1483,7 +1410,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) ...@@ -1483,7 +1410,7 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_create_cq req; struct cmdq_create_cq req;
struct creq_create_cq_resp *resp; struct creq_create_cq_resp resp;
struct bnxt_qplib_pbl *pbl; struct bnxt_qplib_pbl *pbl;
u16 cmd_flags = 0; u16 cmd_flags = 0;
int rc; int rc;
...@@ -1525,30 +1452,12 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) ...@@ -1525,30 +1452,12 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
(cq->cnq_hw_ring_id & CMDQ_CREATE_CQ_CNQ_ID_MASK) << (cq->cnq_hw_ring_id & CMDQ_CREATE_CQ_CNQ_ID_MASK) <<
CMDQ_CREATE_CQ_CNQ_ID_SFT); CMDQ_CREATE_CQ_CNQ_ID_SFT);
resp = (struct creq_create_cq_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 0);
NULL, 0); if (rc)
if (!resp) {
dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ timed out");
rc = -ETIMEDOUT;
goto fail;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: FP: CREATE_CQ failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
rc = -EINVAL;
goto fail; goto fail;
}
cq->id = le32_to_cpu(resp->xid); cq->id = le32_to_cpu(resp.xid);
cq->dbr_base = res->dpi_tbl.dbr_bar_reg_iomem; cq->dbr_base = res->dpi_tbl.dbr_bar_reg_iomem;
cq->period = BNXT_QPLIB_QUEUE_START_PERIOD; cq->period = BNXT_QPLIB_QUEUE_START_PERIOD;
init_waitqueue_head(&cq->waitq); init_waitqueue_head(&cq->waitq);
...@@ -1566,33 +1475,17 @@ int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) ...@@ -1566,33 +1475,17 @@ int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_destroy_cq req; struct cmdq_destroy_cq req;
struct creq_destroy_cq_resp *resp; struct creq_destroy_cq_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
int rc;
RCFW_CMD_PREP(req, DESTROY_CQ, cmd_flags); RCFW_CMD_PREP(req, DESTROY_CQ, cmd_flags);
req.cq_cid = cpu_to_le32(cq->id); req.cq_cid = cpu_to_le32(cq->id);
resp = (struct creq_destroy_cq_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 0);
NULL, 0); if (rc)
if (!resp) { return rc;
dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: FP: DESTROY_CQ failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
bnxt_qplib_free_hwq(res->pdev, &cq->hwq); bnxt_qplib_free_hwq(res->pdev, &cq->hwq);
return 0; return 0;
} }
...@@ -1664,14 +1557,113 @@ static int __flush_rq(struct bnxt_qplib_q *rq, struct bnxt_qplib_qp *qp, ...@@ -1664,14 +1557,113 @@ static int __flush_rq(struct bnxt_qplib_q *rq, struct bnxt_qplib_qp *qp,
return rc; return rc;
} }
/* Note: SQE is valid from sw_sq_cons up to cqe_sq_cons (exclusive)
* CQE is track from sw_cq_cons to max_element but valid only if VALID=1
*/
static int do_wa9060(struct bnxt_qplib_qp *qp, struct bnxt_qplib_cq *cq,
u32 cq_cons, u32 sw_sq_cons, u32 cqe_sq_cons)
{
struct bnxt_qplib_q *sq = &qp->sq;
struct bnxt_qplib_swq *swq;
u32 peek_sw_cq_cons, peek_raw_cq_cons, peek_sq_cons_idx;
struct cq_base *peek_hwcqe, **peek_hw_cqe_ptr;
struct cq_req *peek_req_hwcqe;
struct bnxt_qplib_qp *peek_qp;
struct bnxt_qplib_q *peek_sq;
int i, rc = 0;
/* Normal mode */
/* Check for the psn_search marking before completing */
swq = &sq->swq[sw_sq_cons];
if (swq->psn_search &&
le32_to_cpu(swq->psn_search->flags_next_psn) & 0x80000000) {
/* Unmark */
swq->psn_search->flags_next_psn = cpu_to_le32
(le32_to_cpu(swq->psn_search->flags_next_psn)
& ~0x80000000);
dev_dbg(&cq->hwq.pdev->dev,
"FP: Process Req cq_cons=0x%x qp=0x%x sq cons sw=0x%x cqe=0x%x marked!\n",
cq_cons, qp->id, sw_sq_cons, cqe_sq_cons);
sq->condition = true;
sq->send_phantom = true;
/* TODO: Only ARM if the previous SQE is ARMALL */
bnxt_qplib_arm_cq(cq, DBR_DBR_TYPE_CQ_ARMALL);
rc = -EAGAIN;
goto out;
}
if (sq->condition) {
/* Peek at the completions */
peek_raw_cq_cons = cq->hwq.cons;
peek_sw_cq_cons = cq_cons;
i = cq->hwq.max_elements;
while (i--) {
peek_sw_cq_cons = HWQ_CMP((peek_sw_cq_cons), &cq->hwq);
peek_hw_cqe_ptr = (struct cq_base **)cq->hwq.pbl_ptr;
peek_hwcqe = &peek_hw_cqe_ptr[CQE_PG(peek_sw_cq_cons)]
[CQE_IDX(peek_sw_cq_cons)];
/* If the next hwcqe is VALID */
if (CQE_CMP_VALID(peek_hwcqe, peek_raw_cq_cons,
cq->hwq.max_elements)) {
/* If the next hwcqe is a REQ */
if ((peek_hwcqe->cqe_type_toggle &
CQ_BASE_CQE_TYPE_MASK) ==
CQ_BASE_CQE_TYPE_REQ) {
peek_req_hwcqe = (struct cq_req *)
peek_hwcqe;
peek_qp = (struct bnxt_qplib_qp *)
((unsigned long)
le64_to_cpu
(peek_req_hwcqe->qp_handle));
peek_sq = &peek_qp->sq;
peek_sq_cons_idx = HWQ_CMP(le16_to_cpu(
peek_req_hwcqe->sq_cons_idx) - 1
, &sq->hwq);
/* If the hwcqe's sq's wr_id matches */
if (peek_sq == sq &&
sq->swq[peek_sq_cons_idx].wr_id ==
BNXT_QPLIB_FENCE_WRID) {
/*
* Unbreak only if the phantom
* comes back
*/
dev_dbg(&cq->hwq.pdev->dev,
"FP:Got Phantom CQE");
sq->condition = false;
sq->single = true;
rc = 0;
goto out;
}
}
/* Valid but not the phantom, so keep looping */
} else {
/* Not valid yet, just exit and wait */
rc = -EINVAL;
goto out;
}
peek_sw_cq_cons++;
peek_raw_cq_cons++;
}
dev_err(&cq->hwq.pdev->dev,
"Should not have come here! cq_cons=0x%x qp=0x%x sq cons sw=0x%x hw=0x%x",
cq_cons, qp->id, sw_sq_cons, cqe_sq_cons);
rc = -EINVAL;
}
out:
return rc;
}
static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
struct cq_req *hwcqe, struct cq_req *hwcqe,
struct bnxt_qplib_cqe **pcqe, int *budget) struct bnxt_qplib_cqe **pcqe, int *budget,
u32 cq_cons, struct bnxt_qplib_qp **lib_qp)
{ {
struct bnxt_qplib_qp *qp; struct bnxt_qplib_qp *qp;
struct bnxt_qplib_q *sq; struct bnxt_qplib_q *sq;
struct bnxt_qplib_cqe *cqe; struct bnxt_qplib_cqe *cqe;
u32 sw_cons, cqe_cons; u32 sw_sq_cons, cqe_sq_cons;
struct bnxt_qplib_swq *swq;
int rc = 0; int rc = 0;
qp = (struct bnxt_qplib_qp *)((unsigned long) qp = (struct bnxt_qplib_qp *)((unsigned long)
...@@ -1683,13 +1675,13 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, ...@@ -1683,13 +1675,13 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
} }
sq = &qp->sq; sq = &qp->sq;
cqe_cons = HWQ_CMP(le16_to_cpu(hwcqe->sq_cons_idx), &sq->hwq); cqe_sq_cons = HWQ_CMP(le16_to_cpu(hwcqe->sq_cons_idx), &sq->hwq);
if (cqe_cons > sq->hwq.max_elements) { if (cqe_sq_cons > sq->hwq.max_elements) {
dev_err(&cq->hwq.pdev->dev, dev_err(&cq->hwq.pdev->dev,
"QPLIB: FP: CQ Process req reported "); "QPLIB: FP: CQ Process req reported ");
dev_err(&cq->hwq.pdev->dev, dev_err(&cq->hwq.pdev->dev,
"QPLIB: sq_cons_idx 0x%x which exceeded max 0x%x", "QPLIB: sq_cons_idx 0x%x which exceeded max 0x%x",
cqe_cons, sq->hwq.max_elements); cqe_sq_cons, sq->hwq.max_elements);
return -EINVAL; return -EINVAL;
} }
/* If we were in the middle of flushing the SQ, continue */ /* If we were in the middle of flushing the SQ, continue */
...@@ -1698,53 +1690,74 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, ...@@ -1698,53 +1690,74 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
/* Require to walk the sq's swq to fabricate CQEs for all previously /* Require to walk the sq's swq to fabricate CQEs for all previously
* signaled SWQEs due to CQE aggregation from the current sq cons * signaled SWQEs due to CQE aggregation from the current sq cons
* to the cqe_cons * to the cqe_sq_cons
*/ */
cqe = *pcqe; cqe = *pcqe;
while (*budget) { while (*budget) {
sw_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq); sw_sq_cons = HWQ_CMP(sq->hwq.cons, &sq->hwq);
if (sw_cons == cqe_cons) if (sw_sq_cons == cqe_sq_cons)
/* Done */
break; break;
swq = &sq->swq[sw_sq_cons];
memset(cqe, 0, sizeof(*cqe)); memset(cqe, 0, sizeof(*cqe));
cqe->opcode = CQ_BASE_CQE_TYPE_REQ; cqe->opcode = CQ_BASE_CQE_TYPE_REQ;
cqe->qp_handle = (u64)(unsigned long)qp; cqe->qp_handle = (u64)(unsigned long)qp;
cqe->src_qp = qp->id; cqe->src_qp = qp->id;
cqe->wr_id = sq->swq[sw_cons].wr_id; cqe->wr_id = swq->wr_id;
cqe->type = sq->swq[sw_cons].type; if (cqe->wr_id == BNXT_QPLIB_FENCE_WRID)
goto skip;
cqe->type = swq->type;
/* For the last CQE, check for status. For errors, regardless /* For the last CQE, check for status. For errors, regardless
* of the request being signaled or not, it must complete with * of the request being signaled or not, it must complete with
* the hwcqe error status * the hwcqe error status
*/ */
if (HWQ_CMP((sw_cons + 1), &sq->hwq) == cqe_cons && if (HWQ_CMP((sw_sq_cons + 1), &sq->hwq) == cqe_sq_cons &&
hwcqe->status != CQ_REQ_STATUS_OK) { hwcqe->status != CQ_REQ_STATUS_OK) {
cqe->status = hwcqe->status; cqe->status = hwcqe->status;
dev_err(&cq->hwq.pdev->dev, dev_err(&cq->hwq.pdev->dev,
"QPLIB: FP: CQ Processed Req "); "QPLIB: FP: CQ Processed Req ");
dev_err(&cq->hwq.pdev->dev, dev_err(&cq->hwq.pdev->dev,
"QPLIB: wr_id[%d] = 0x%llx with status 0x%x", "QPLIB: wr_id[%d] = 0x%llx with status 0x%x",
sw_cons, cqe->wr_id, cqe->status); sw_sq_cons, cqe->wr_id, cqe->status);
cqe++; cqe++;
(*budget)--; (*budget)--;
sq->flush_in_progress = true; sq->flush_in_progress = true;
/* Must block new posting of SQ and RQ */ /* Must block new posting of SQ and RQ */
qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR; qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR;
sq->condition = false;
sq->single = false;
} else { } else {
if (sq->swq[sw_cons].flags & if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) {
SQ_SEND_FLAGS_SIGNAL_COMP) { /* Before we complete, do WA 9060 */
if (do_wa9060(qp, cq, cq_cons, sw_sq_cons,
cqe_sq_cons)) {
*lib_qp = qp;
goto out;
}
cqe->status = CQ_REQ_STATUS_OK; cqe->status = CQ_REQ_STATUS_OK;
cqe++; cqe++;
(*budget)--; (*budget)--;
} }
} }
skip:
sq->hwq.cons++; sq->hwq.cons++;
if (sq->single)
break;
} }
out:
*pcqe = cqe; *pcqe = cqe;
if (!*budget && HWQ_CMP(sq->hwq.cons, &sq->hwq) != cqe_cons) { if (HWQ_CMP(sq->hwq.cons, &sq->hwq) != cqe_sq_cons) {
/* Out of budget */ /* Out of budget */
rc = -EAGAIN; rc = -EAGAIN;
goto done; goto done;
} }
/*
* Back to normal completion mode only after it has completed all of
* the WC for this CQE
*/
sq->single = false;
if (!sq->flush_in_progress) if (!sq->flush_in_progress)
goto done; goto done;
flush: flush:
...@@ -2074,7 +2087,7 @@ static int bnxt_qplib_cq_process_cutoff(struct bnxt_qplib_cq *cq, ...@@ -2074,7 +2087,7 @@ static int bnxt_qplib_cq_process_cutoff(struct bnxt_qplib_cq *cq,
} }
int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe, int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
int num_cqes) int num_cqes, struct bnxt_qplib_qp **lib_qp)
{ {
struct cq_base *hw_cqe, **hw_cqe_ptr; struct cq_base *hw_cqe, **hw_cqe_ptr;
unsigned long flags; unsigned long flags;
...@@ -2099,7 +2112,8 @@ int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe, ...@@ -2099,7 +2112,8 @@ int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
case CQ_BASE_CQE_TYPE_REQ: case CQ_BASE_CQE_TYPE_REQ:
rc = bnxt_qplib_cq_process_req(cq, rc = bnxt_qplib_cq_process_req(cq,
(struct cq_req *)hw_cqe, (struct cq_req *)hw_cqe,
&cqe, &budget); &cqe, &budget,
sw_cons, lib_qp);
break; break;
case CQ_BASE_CQE_TYPE_RES_RC: case CQ_BASE_CQE_TYPE_RES_RC:
rc = bnxt_qplib_cq_process_res_rc(cq, rc = bnxt_qplib_cq_process_res_rc(cq,
......
...@@ -88,6 +88,7 @@ struct bnxt_qplib_swq { ...@@ -88,6 +88,7 @@ struct bnxt_qplib_swq {
struct bnxt_qplib_swqe { struct bnxt_qplib_swqe {
/* General */ /* General */
#define BNXT_QPLIB_FENCE_WRID 0x46454E43 /* "FENC" */
u64 wr_id; u64 wr_id;
u8 reqs_type; u8 reqs_type;
u8 type; u8 type;
...@@ -216,9 +217,16 @@ struct bnxt_qplib_q { ...@@ -216,9 +217,16 @@ struct bnxt_qplib_q {
struct scatterlist *sglist; struct scatterlist *sglist;
u32 nmap; u32 nmap;
u32 max_wqe; u32 max_wqe;
u16 q_full_delta;
u16 max_sge; u16 max_sge;
u32 psn; u32 psn;
bool flush_in_progress; bool flush_in_progress;
bool condition;
bool single;
bool send_phantom;
u32 phantom_wqe_cnt;
u32 phantom_cqe_cnt;
u32 next_cq_cons;
}; };
struct bnxt_qplib_qp { struct bnxt_qplib_qp {
...@@ -242,6 +250,7 @@ struct bnxt_qplib_qp { ...@@ -242,6 +250,7 @@ struct bnxt_qplib_qp {
u8 timeout; u8 timeout;
u8 retry_cnt; u8 retry_cnt;
u8 rnr_retry; u8 rnr_retry;
u64 wqe_cnt;
u32 min_rnr_timer; u32 min_rnr_timer;
u32 max_rd_atomic; u32 max_rd_atomic;
u32 max_dest_rd_atomic; u32 max_dest_rd_atomic;
...@@ -301,6 +310,13 @@ struct bnxt_qplib_qp { ...@@ -301,6 +310,13 @@ struct bnxt_qplib_qp {
(!!((hdr)->cqe_type_toggle & CQ_BASE_TOGGLE) == \ (!!((hdr)->cqe_type_toggle & CQ_BASE_TOGGLE) == \
!((raw_cons) & (cp_bit))) !((raw_cons) & (cp_bit)))
static inline bool bnxt_qplib_queue_full(struct bnxt_qplib_q *qplib_q)
{
return HWQ_CMP((qplib_q->hwq.prod + qplib_q->q_full_delta),
&qplib_q->hwq) == HWQ_CMP(qplib_q->hwq.cons,
&qplib_q->hwq);
}
struct bnxt_qplib_cqe { struct bnxt_qplib_cqe {
u8 status; u8 status;
u8 type; u8 type;
...@@ -432,7 +448,7 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp, ...@@ -432,7 +448,7 @@ int bnxt_qplib_post_recv(struct bnxt_qplib_qp *qp,
int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq); int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq);
int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq); int bnxt_qplib_destroy_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq);
int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe, int bnxt_qplib_poll_cq(struct bnxt_qplib_cq *cq, struct bnxt_qplib_cqe *cqe,
int num); int num, struct bnxt_qplib_qp **qp);
void bnxt_qplib_req_notify_cq(struct bnxt_qplib_cq *cq, u32 arm_type); void bnxt_qplib_req_notify_cq(struct bnxt_qplib_cq *cq, u32 arm_type);
void bnxt_qplib_free_nq(struct bnxt_qplib_nq *nq); void bnxt_qplib_free_nq(struct bnxt_qplib_nq *nq);
int bnxt_qplib_alloc_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq); int bnxt_qplib_alloc_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq);
......
...@@ -39,72 +39,55 @@ ...@@ -39,72 +39,55 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/delay.h>
#include "roce_hsi.h" #include "roce_hsi.h"
#include "qplib_res.h" #include "qplib_res.h"
#include "qplib_rcfw.h" #include "qplib_rcfw.h"
static void bnxt_qplib_service_creq(unsigned long data); static void bnxt_qplib_service_creq(unsigned long data);
/* Hardware communication channel */ /* Hardware communication channel */
int bnxt_qplib_rcfw_wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie) static int __wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
{ {
u16 cbit; u16 cbit;
int rc; int rc;
cookie &= RCFW_MAX_COOKIE_VALUE;
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD; cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
if (!test_bit(cbit, rcfw->cmdq_bitmap))
dev_warn(&rcfw->pdev->dev,
"QPLIB: CMD bit %d for cookie 0x%x is not set?",
cbit, cookie);
rc = wait_event_timeout(rcfw->waitq, rc = wait_event_timeout(rcfw->waitq,
!test_bit(cbit, rcfw->cmdq_bitmap), !test_bit(cbit, rcfw->cmdq_bitmap),
msecs_to_jiffies(RCFW_CMD_WAIT_TIME_MS)); msecs_to_jiffies(RCFW_CMD_WAIT_TIME_MS));
if (!rc) { return rc ? 0 : -ETIMEDOUT;
dev_warn(&rcfw->pdev->dev,
"QPLIB: Bono Error: timeout %d msec, msg {0x%x}\n",
RCFW_CMD_WAIT_TIME_MS, cookie);
}
return rc;
}; };
int bnxt_qplib_rcfw_block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie) static int __block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie)
{ {
u32 count = -1; u32 count = RCFW_BLOCKED_CMD_WAIT_COUNT;
u16 cbit; u16 cbit;
cookie &= RCFW_MAX_COOKIE_VALUE;
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD; cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
if (!test_bit(cbit, rcfw->cmdq_bitmap)) if (!test_bit(cbit, rcfw->cmdq_bitmap))
goto done; goto done;
do { do {
mdelay(1); /* 1m sec */
bnxt_qplib_service_creq((unsigned long)rcfw); bnxt_qplib_service_creq((unsigned long)rcfw);
} while (test_bit(cbit, rcfw->cmdq_bitmap) && --count); } while (test_bit(cbit, rcfw->cmdq_bitmap) && --count);
done: done:
return count; return count ? 0 : -ETIMEDOUT;
}; };
void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, static int __send_message(struct bnxt_qplib_rcfw *rcfw, struct cmdq_base *req,
struct cmdq_base *req, void **crsbe, struct creq_base *resp, void *sb, u8 is_block)
u8 is_block)
{ {
struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
struct bnxt_qplib_cmdqe *cmdqe, **cmdq_ptr; struct bnxt_qplib_cmdqe *cmdqe, **cmdq_ptr;
struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq; struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
struct bnxt_qplib_hwq *crsb = &rcfw->crsb; struct bnxt_qplib_crsq *crsqe;
struct bnxt_qplib_crsqe *crsqe = NULL;
struct bnxt_qplib_crsbe **crsb_ptr;
u32 sw_prod, cmdq_prod; u32 sw_prod, cmdq_prod;
u8 retry_cnt = 0xFF;
dma_addr_t dma_addr;
unsigned long flags; unsigned long flags;
u32 size, opcode; u32 size, opcode;
u16 cookie, cbit; u16 cookie, cbit;
int pg, idx; int pg, idx;
u8 *preq; u8 *preq;
retry:
opcode = req->opcode; opcode = req->opcode;
if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) && if (!test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
(opcode != CMDQ_BASE_OPCODE_QUERY_FUNC && (opcode != CMDQ_BASE_OPCODE_QUERY_FUNC &&
...@@ -112,63 +95,50 @@ void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, ...@@ -112,63 +95,50 @@ void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
dev_err(&rcfw->pdev->dev, dev_err(&rcfw->pdev->dev,
"QPLIB: RCFW not initialized, reject opcode 0x%x", "QPLIB: RCFW not initialized, reject opcode 0x%x",
opcode); opcode);
return NULL; return -EINVAL;
} }
if (test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) && if (test_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags) &&
opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) { opcode == CMDQ_BASE_OPCODE_INITIALIZE_FW) {
dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!"); dev_err(&rcfw->pdev->dev, "QPLIB: RCFW already initialized!");
return NULL; return -EINVAL;
} }
/* Cmdq are in 16-byte units, each request can consume 1 or more /* Cmdq are in 16-byte units, each request can consume 1 or more
* cmdqe * cmdqe
*/ */
spin_lock_irqsave(&cmdq->lock, flags); spin_lock_irqsave(&cmdq->lock, flags);
if (req->cmd_size > cmdq->max_elements - if (req->cmd_size >= HWQ_FREE_SLOTS(cmdq)) {
((HWQ_CMP(cmdq->prod, cmdq) - HWQ_CMP(cmdq->cons, cmdq)) &
(cmdq->max_elements - 1))) {
dev_err(&rcfw->pdev->dev, "QPLIB: RCFW: CMDQ is full!"); dev_err(&rcfw->pdev->dev, "QPLIB: RCFW: CMDQ is full!");
spin_unlock_irqrestore(&cmdq->lock, flags); spin_unlock_irqrestore(&cmdq->lock, flags);
return -EAGAIN;
if (!retry_cnt--)
return NULL;
goto retry;
} }
retry_cnt = 0xFF;
cookie = atomic_inc_return(&rcfw->seq_num) & RCFW_MAX_COOKIE_VALUE; cookie = rcfw->seq_num & RCFW_MAX_COOKIE_VALUE;
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD; cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
if (is_block) if (is_block)
cookie |= RCFW_CMD_IS_BLOCKING; cookie |= RCFW_CMD_IS_BLOCKING;
set_bit(cbit, rcfw->cmdq_bitmap);
req->cookie = cpu_to_le16(cookie); req->cookie = cpu_to_le16(cookie);
if (test_and_set_bit(cbit, rcfw->cmdq_bitmap)) { crsqe = &rcfw->crsqe_tbl[cbit];
dev_err(&rcfw->pdev->dev, if (crsqe->resp) {
"QPLIB: RCFW MAX outstanding cmd reached!");
atomic_dec(&rcfw->seq_num);
spin_unlock_irqrestore(&cmdq->lock, flags); spin_unlock_irqrestore(&cmdq->lock, flags);
return -EBUSY;
if (!retry_cnt--)
return NULL;
goto retry;
} }
/* Reserve a resp buffer slot if requested */ memset(resp, 0, sizeof(*resp));
if (req->resp_size && crsbe) { crsqe->resp = (struct creq_qp_event *)resp;
spin_lock(&crsb->lock); crsqe->resp->cookie = req->cookie;
sw_prod = HWQ_CMP(crsb->prod, crsb); crsqe->req_size = req->cmd_size;
crsb_ptr = (struct bnxt_qplib_crsbe **)crsb->pbl_ptr; if (req->resp_size && sb) {
*crsbe = (void *)&crsb_ptr[get_crsb_pg(sw_prod)] struct bnxt_qplib_rcfw_sbuf *sbuf = sb;
[get_crsb_idx(sw_prod)];
bnxt_qplib_crsb_dma_next(crsb->pbl_dma_ptr, sw_prod, &dma_addr); req->resp_addr = cpu_to_le64(sbuf->dma_addr);
req->resp_addr = cpu_to_le64(dma_addr); req->resp_size = (sbuf->size + BNXT_QPLIB_CMDQE_UNITS - 1) /
crsb->prod++;
spin_unlock(&crsb->lock);
req->resp_size = (sizeof(struct bnxt_qplib_crsbe) +
BNXT_QPLIB_CMDQE_UNITS - 1) /
BNXT_QPLIB_CMDQE_UNITS; BNXT_QPLIB_CMDQE_UNITS;
} }
cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr; cmdq_ptr = (struct bnxt_qplib_cmdqe **)cmdq->pbl_ptr;
preq = (u8 *)req; preq = (u8 *)req;
size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS; size = req->cmd_size * BNXT_QPLIB_CMDQE_UNITS;
...@@ -190,23 +160,24 @@ void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, ...@@ -190,23 +160,24 @@ void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
preq += min_t(u32, size, sizeof(*cmdqe)); preq += min_t(u32, size, sizeof(*cmdqe));
size -= min_t(u32, size, sizeof(*cmdqe)); size -= min_t(u32, size, sizeof(*cmdqe));
cmdq->prod++; cmdq->prod++;
rcfw->seq_num++;
} while (size > 0); } while (size > 0);
rcfw->seq_num++;
cmdq_prod = cmdq->prod; cmdq_prod = cmdq->prod;
if (rcfw->flags & FIRMWARE_FIRST_FLAG) { if (rcfw->flags & FIRMWARE_FIRST_FLAG) {
/* The very first doorbell write is required to set this flag /* The very first doorbell write
* which prompts the FW to reset its internal pointers * is required to set this flag
* which prompts the FW to reset
* its internal pointers
*/ */
cmdq_prod |= FIRMWARE_FIRST_FLAG; cmdq_prod |= FIRMWARE_FIRST_FLAG;
rcfw->flags &= ~FIRMWARE_FIRST_FLAG; rcfw->flags &= ~FIRMWARE_FIRST_FLAG;
} }
sw_prod = HWQ_CMP(crsq->prod, crsq);
crsqe = &crsq->crsq[sw_prod];
memset(crsqe, 0, sizeof(*crsqe));
crsq->prod++;
crsqe->req_size = req->cmd_size;
/* ring CMDQ DB */ /* ring CMDQ DB */
wmb();
writel(cmdq_prod, rcfw->cmdq_bar_reg_iomem + writel(cmdq_prod, rcfw->cmdq_bar_reg_iomem +
rcfw->cmdq_bar_reg_prod_off); rcfw->cmdq_bar_reg_prod_off);
writel(RCFW_CMDQ_TRIG_VAL, rcfw->cmdq_bar_reg_iomem + writel(RCFW_CMDQ_TRIG_VAL, rcfw->cmdq_bar_reg_iomem +
...@@ -214,9 +185,56 @@ void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, ...@@ -214,9 +185,56 @@ void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
done: done:
spin_unlock_irqrestore(&cmdq->lock, flags); spin_unlock_irqrestore(&cmdq->lock, flags);
/* Return the CREQ response pointer */ /* Return the CREQ response pointer */
return crsqe ? &crsqe->qp_event : NULL; return 0;
} }
int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
struct cmdq_base *req,
struct creq_base *resp,
void *sb, u8 is_block)
{
struct creq_qp_event *evnt = (struct creq_qp_event *)resp;
u16 cookie;
u8 opcode, retry_cnt = 0xFF;
int rc = 0;
do {
opcode = req->opcode;
rc = __send_message(rcfw, req, resp, sb, is_block);
cookie = le16_to_cpu(req->cookie) & RCFW_MAX_COOKIE_VALUE;
if (!rc)
break;
if (!retry_cnt || (rc != -EAGAIN && rc != -EBUSY)) {
/* send failed */
dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x send failed",
cookie, opcode);
return rc;
}
is_block ? mdelay(1) : usleep_range(500, 1000);
} while (retry_cnt--);
if (is_block)
rc = __block_for_resp(rcfw, cookie);
else
rc = __wait_for_resp(rcfw, cookie);
if (rc) {
/* timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x timedout (%d)msec",
cookie, opcode, RCFW_CMD_WAIT_TIME_MS);
return rc;
}
if (evnt->status) {
/* failed with status */
dev_err(&rcfw->pdev->dev, "QPLIB: cmdq[%#x]=%#x status %#x",
cookie, opcode, evnt->status);
rc = -EFAULT;
}
return rc;
}
/* Completions */ /* Completions */
static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw, static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
struct creq_func_event *func_event) struct creq_func_event *func_event)
...@@ -260,12 +278,12 @@ static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw, ...@@ -260,12 +278,12 @@ static int bnxt_qplib_process_func_event(struct bnxt_qplib_rcfw *rcfw,
static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
struct creq_qp_event *qp_event) struct creq_qp_event *qp_event)
{ {
struct bnxt_qplib_crsq *crsq = &rcfw->crsq;
struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq; struct bnxt_qplib_hwq *cmdq = &rcfw->cmdq;
struct bnxt_qplib_crsqe *crsqe; struct bnxt_qplib_crsq *crsqe;
u16 cbit, cookie, blocked = 0;
unsigned long flags; unsigned long flags;
u32 sw_cons; u16 cbit, blocked = 0;
u16 cookie;
__le16 mcookie;
switch (qp_event->event) { switch (qp_event->event) {
case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION: case CREQ_QP_EVENT_EVENT_QP_ERROR_NOTIFICATION:
...@@ -275,24 +293,31 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, ...@@ -275,24 +293,31 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw,
default: default:
/* Command Response */ /* Command Response */
spin_lock_irqsave(&cmdq->lock, flags); spin_lock_irqsave(&cmdq->lock, flags);
sw_cons = HWQ_CMP(crsq->cons, crsq); cookie = le16_to_cpu(qp_event->cookie);
crsqe = &crsq->crsq[sw_cons]; mcookie = qp_event->cookie;
crsq->cons++;
memcpy(&crsqe->qp_event, qp_event, sizeof(crsqe->qp_event));
cookie = le16_to_cpu(crsqe->qp_event.cookie);
blocked = cookie & RCFW_CMD_IS_BLOCKING; blocked = cookie & RCFW_CMD_IS_BLOCKING;
cookie &= RCFW_MAX_COOKIE_VALUE; cookie &= RCFW_MAX_COOKIE_VALUE;
cbit = cookie % RCFW_MAX_OUTSTANDING_CMD; cbit = cookie % RCFW_MAX_OUTSTANDING_CMD;
crsqe = &rcfw->crsqe_tbl[cbit];
if (crsqe->resp &&
crsqe->resp->cookie == mcookie) {
memcpy(crsqe->resp, qp_event, sizeof(*qp_event));
crsqe->resp = NULL;
} else {
dev_err(&rcfw->pdev->dev,
"QPLIB: CMD %s resp->cookie = %#x, evnt->cookie = %#x",
crsqe->resp ? "mismatch" : "collision",
crsqe->resp ? crsqe->resp->cookie : 0, mcookie);
}
if (!test_and_clear_bit(cbit, rcfw->cmdq_bitmap)) if (!test_and_clear_bit(cbit, rcfw->cmdq_bitmap))
dev_warn(&rcfw->pdev->dev, dev_warn(&rcfw->pdev->dev,
"QPLIB: CMD bit %d was not requested", cbit); "QPLIB: CMD bit %d was not requested", cbit);
cmdq->cons += crsqe->req_size; cmdq->cons += crsqe->req_size;
spin_unlock_irqrestore(&cmdq->lock, flags); crsqe->req_size = 0;
if (!blocked) if (!blocked)
wake_up(&rcfw->waitq); wake_up(&rcfw->waitq);
break; spin_unlock_irqrestore(&cmdq->lock, flags);
} }
return 0; return 0;
} }
...@@ -305,12 +330,12 @@ static void bnxt_qplib_service_creq(unsigned long data) ...@@ -305,12 +330,12 @@ static void bnxt_qplib_service_creq(unsigned long data)
struct creq_base *creqe, **creq_ptr; struct creq_base *creqe, **creq_ptr;
u32 sw_cons, raw_cons; u32 sw_cons, raw_cons;
unsigned long flags; unsigned long flags;
u32 type; u32 type, budget = CREQ_ENTRY_POLL_BUDGET;
/* Service the CREQ until empty */ /* Service the CREQ until budget is over */
spin_lock_irqsave(&creq->lock, flags); spin_lock_irqsave(&creq->lock, flags);
raw_cons = creq->cons; raw_cons = creq->cons;
while (1) { while (budget > 0) {
sw_cons = HWQ_CMP(raw_cons, creq); sw_cons = HWQ_CMP(raw_cons, creq);
creq_ptr = (struct creq_base **)creq->pbl_ptr; creq_ptr = (struct creq_base **)creq->pbl_ptr;
creqe = &creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)]; creqe = &creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)];
...@@ -320,15 +345,9 @@ static void bnxt_qplib_service_creq(unsigned long data) ...@@ -320,15 +345,9 @@ static void bnxt_qplib_service_creq(unsigned long data)
type = creqe->type & CREQ_BASE_TYPE_MASK; type = creqe->type & CREQ_BASE_TYPE_MASK;
switch (type) { switch (type) {
case CREQ_BASE_TYPE_QP_EVENT: case CREQ_BASE_TYPE_QP_EVENT:
if (!bnxt_qplib_process_qp_event bnxt_qplib_process_qp_event
(rcfw, (struct creq_qp_event *)creqe)) (rcfw, (struct creq_qp_event *)creqe);
rcfw->creq_qp_event_processed++; rcfw->creq_qp_event_processed++;
else {
dev_warn(&rcfw->pdev->dev, "QPLIB: crsqe with");
dev_warn(&rcfw->pdev->dev,
"QPLIB: type = 0x%x not handled",
type);
}
break; break;
case CREQ_BASE_TYPE_FUNC_EVENT: case CREQ_BASE_TYPE_FUNC_EVENT:
if (!bnxt_qplib_process_func_event if (!bnxt_qplib_process_func_event
...@@ -346,7 +365,9 @@ static void bnxt_qplib_service_creq(unsigned long data) ...@@ -346,7 +365,9 @@ static void bnxt_qplib_service_creq(unsigned long data)
break; break;
} }
raw_cons++; raw_cons++;
budget--;
} }
if (creq->cons != raw_cons) { if (creq->cons != raw_cons) {
creq->cons = raw_cons; creq->cons = raw_cons;
CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, raw_cons, CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, raw_cons,
...@@ -375,23 +396,16 @@ static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance) ...@@ -375,23 +396,16 @@ static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance)
/* RCFW */ /* RCFW */
int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw) int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw)
{ {
struct creq_deinitialize_fw_resp *resp;
struct cmdq_deinitialize_fw req; struct cmdq_deinitialize_fw req;
struct creq_deinitialize_fw_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
int rc;
RCFW_CMD_PREP(req, DEINITIALIZE_FW, cmd_flags); RCFW_CMD_PREP(req, DEINITIALIZE_FW, cmd_flags);
resp = (struct creq_deinitialize_fw_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
NULL, 0); NULL, 0);
if (!resp) if (rc)
return -EINVAL; return rc;
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie)))
return -ETIMEDOUT;
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie))
return -EFAULT;
clear_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags); clear_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
return 0; return 0;
...@@ -417,9 +431,10 @@ static int __get_pbl_pg_idx(struct bnxt_qplib_pbl *pbl) ...@@ -417,9 +431,10 @@ static int __get_pbl_pg_idx(struct bnxt_qplib_pbl *pbl)
int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw, int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_ctx *ctx, int is_virtfn) struct bnxt_qplib_ctx *ctx, int is_virtfn)
{ {
struct creq_initialize_fw_resp *resp;
struct cmdq_initialize_fw req; struct cmdq_initialize_fw req;
struct creq_initialize_fw_resp resp;
u16 cmd_flags = 0, level; u16 cmd_flags = 0, level;
int rc;
RCFW_CMD_PREP(req, INITIALIZE_FW, cmd_flags); RCFW_CMD_PREP(req, INITIALIZE_FW, cmd_flags);
...@@ -482,37 +497,19 @@ int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw, ...@@ -482,37 +497,19 @@ int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
skip_ctx_setup: skip_ctx_setup:
req.stat_ctx_id = cpu_to_le32(ctx->stats.fw_id); req.stat_ctx_id = cpu_to_le32(ctx->stats.fw_id);
resp = (struct creq_initialize_fw_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
NULL, 0); NULL, 0);
if (!resp) { if (rc)
dev_err(&rcfw->pdev->dev, return rc;
"QPLIB: RCFW: INITIALIZE_FW send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev,
"QPLIB: RCFW: INITIALIZE_FW timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev,
"QPLIB: RCFW: INITIALIZE_FW failed");
return -EINVAL;
}
set_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags); set_bit(FIRMWARE_INITIALIZED_FLAG, &rcfw->flags);
return 0; return 0;
} }
void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw) void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
{ {
bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->crsb); kfree(rcfw->crsqe_tbl);
kfree(rcfw->crsq.crsq);
bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->cmdq); bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->cmdq);
bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->creq); bnxt_qplib_free_hwq(rcfw->pdev, &rcfw->creq);
rcfw->pdev = NULL; rcfw->pdev = NULL;
} }
...@@ -539,21 +536,11 @@ int bnxt_qplib_alloc_rcfw_channel(struct pci_dev *pdev, ...@@ -539,21 +536,11 @@ int bnxt_qplib_alloc_rcfw_channel(struct pci_dev *pdev,
goto fail; goto fail;
} }
rcfw->crsq.max_elements = rcfw->cmdq.max_elements; rcfw->crsqe_tbl = kcalloc(rcfw->cmdq.max_elements,
rcfw->crsq.crsq = kcalloc(rcfw->crsq.max_elements, sizeof(*rcfw->crsqe_tbl), GFP_KERNEL);
sizeof(*rcfw->crsq.crsq), GFP_KERNEL); if (!rcfw->crsqe_tbl)
if (!rcfw->crsq.crsq)
goto fail; goto fail;
rcfw->crsb.max_elements = BNXT_QPLIB_CRSBE_MAX_CNT;
if (bnxt_qplib_alloc_init_hwq(rcfw->pdev, &rcfw->crsb, NULL, 0,
&rcfw->crsb.max_elements,
BNXT_QPLIB_CRSBE_UNITS, 0, PAGE_SIZE,
HWQ_TYPE_CTX)) {
dev_err(&rcfw->pdev->dev,
"QPLIB: HW channel CRSB allocation failed");
goto fail;
}
return 0; return 0;
fail: fail:
...@@ -606,7 +593,7 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev, ...@@ -606,7 +593,7 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
int rc; int rc;
/* General */ /* General */
atomic_set(&rcfw->seq_num, 0); rcfw->seq_num = 0;
rcfw->flags = FIRMWARE_FIRST_FLAG; rcfw->flags = FIRMWARE_FIRST_FLAG;
bmap_size = BITS_TO_LONGS(RCFW_MAX_OUTSTANDING_CMD * bmap_size = BITS_TO_LONGS(RCFW_MAX_OUTSTANDING_CMD *
sizeof(unsigned long)); sizeof(unsigned long));
...@@ -636,10 +623,6 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev, ...@@ -636,10 +623,6 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
rcfw->cmdq_bar_reg_trig_off = RCFW_COMM_TRIG_OFFSET; rcfw->cmdq_bar_reg_trig_off = RCFW_COMM_TRIG_OFFSET;
/* CRSQ */
rcfw->crsq.prod = 0;
rcfw->crsq.cons = 0;
/* CREQ */ /* CREQ */
rcfw->creq_bar_reg = RCFW_COMM_CONS_PCI_BAR_REGION; rcfw->creq_bar_reg = RCFW_COMM_CONS_PCI_BAR_REGION;
res_base = pci_resource_start(pdev, rcfw->creq_bar_reg); res_base = pci_resource_start(pdev, rcfw->creq_bar_reg);
...@@ -692,3 +675,34 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev, ...@@ -692,3 +675,34 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
__iowrite32_copy(rcfw->cmdq_bar_reg_iomem, &init, sizeof(init) / 4); __iowrite32_copy(rcfw->cmdq_bar_reg_iomem, &init, sizeof(init) / 4);
return 0; return 0;
} }
struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
struct bnxt_qplib_rcfw *rcfw,
u32 size)
{
struct bnxt_qplib_rcfw_sbuf *sbuf;
sbuf = kzalloc(sizeof(*sbuf), GFP_ATOMIC);
if (!sbuf)
return NULL;
sbuf->size = size;
sbuf->sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf->size,
&sbuf->dma_addr, GFP_ATOMIC);
if (!sbuf->sb)
goto bail;
return sbuf;
bail:
kfree(sbuf);
return NULL;
}
void bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_rcfw_sbuf *sbuf)
{
if (sbuf->sb)
dma_free_coherent(&rcfw->pdev->dev, sbuf->size,
sbuf->sb, sbuf->dma_addr);
kfree(sbuf);
}
...@@ -73,6 +73,7 @@ ...@@ -73,6 +73,7 @@
#define RCFW_MAX_OUTSTANDING_CMD BNXT_QPLIB_CMDQE_MAX_CNT #define RCFW_MAX_OUTSTANDING_CMD BNXT_QPLIB_CMDQE_MAX_CNT
#define RCFW_MAX_COOKIE_VALUE 0x7FFF #define RCFW_MAX_COOKIE_VALUE 0x7FFF
#define RCFW_CMD_IS_BLOCKING 0x8000 #define RCFW_CMD_IS_BLOCKING 0x8000
#define RCFW_BLOCKED_CMD_WAIT_COUNT 0x4E20
/* Cmdq contains a fix number of a 16-Byte slots */ /* Cmdq contains a fix number of a 16-Byte slots */
struct bnxt_qplib_cmdqe { struct bnxt_qplib_cmdqe {
...@@ -94,32 +95,6 @@ struct bnxt_qplib_crsbe { ...@@ -94,32 +95,6 @@ struct bnxt_qplib_crsbe {
u8 data[1024]; u8 data[1024];
}; };
/* CRSQ SB */
#define BNXT_QPLIB_CRSBE_MAX_CNT 4
#define BNXT_QPLIB_CRSBE_UNITS sizeof(struct bnxt_qplib_crsbe)
#define BNXT_QPLIB_CRSBE_CNT_PER_PG (PAGE_SIZE / BNXT_QPLIB_CRSBE_UNITS)
#define MAX_CRSB_IDX (BNXT_QPLIB_CRSBE_MAX_CNT - 1)
#define MAX_CRSB_IDX_PER_PG (BNXT_QPLIB_CRSBE_CNT_PER_PG - 1)
static inline u32 get_crsb_pg(u32 val)
{
return (val & ~MAX_CRSB_IDX_PER_PG) / BNXT_QPLIB_CRSBE_CNT_PER_PG;
}
static inline u32 get_crsb_idx(u32 val)
{
return val & MAX_CRSB_IDX_PER_PG;
}
static inline void bnxt_qplib_crsb_dma_next(dma_addr_t *pg_map_arr,
u32 prod, dma_addr_t *dma_addr)
{
*dma_addr = pg_map_arr[(prod) / BNXT_QPLIB_CRSBE_CNT_PER_PG];
*dma_addr += ((prod) % BNXT_QPLIB_CRSBE_CNT_PER_PG) *
BNXT_QPLIB_CRSBE_UNITS;
}
/* CREQ */ /* CREQ */
/* Allocate 1 per QP for async error notification for now */ /* Allocate 1 per QP for async error notification for now */
#define BNXT_QPLIB_CREQE_MAX_CNT (64 * 1024) #define BNXT_QPLIB_CREQE_MAX_CNT (64 * 1024)
...@@ -158,17 +133,19 @@ static inline u32 get_creq_idx(u32 val) ...@@ -158,17 +133,19 @@ static inline u32 get_creq_idx(u32 val)
#define CREQ_DB(db, raw_cons, cp_bit) \ #define CREQ_DB(db, raw_cons, cp_bit) \
writel(CREQ_DB_CP_FLAGS | ((raw_cons) & ((cp_bit) - 1)), db) writel(CREQ_DB_CP_FLAGS | ((raw_cons) & ((cp_bit) - 1)), db)
#define CREQ_ENTRY_POLL_BUDGET 0x100
/* HWQ */ /* HWQ */
struct bnxt_qplib_crsqe {
struct creq_qp_event qp_event; struct bnxt_qplib_crsq {
struct creq_qp_event *resp;
u32 req_size; u32 req_size;
}; };
struct bnxt_qplib_crsq { struct bnxt_qplib_rcfw_sbuf {
struct bnxt_qplib_crsqe *crsq; void *sb;
u32 prod; dma_addr_t dma_addr;
u32 cons; u32 size;
u32 max_elements;
}; };
/* RCFW Communication Channels */ /* RCFW Communication Channels */
...@@ -185,7 +162,7 @@ struct bnxt_qplib_rcfw { ...@@ -185,7 +162,7 @@ struct bnxt_qplib_rcfw {
wait_queue_head_t waitq; wait_queue_head_t waitq;
int (*aeq_handler)(struct bnxt_qplib_rcfw *, int (*aeq_handler)(struct bnxt_qplib_rcfw *,
struct creq_func_event *); struct creq_func_event *);
atomic_t seq_num; u32 seq_num;
/* Bar region info */ /* Bar region info */
void __iomem *cmdq_bar_reg_iomem; void __iomem *cmdq_bar_reg_iomem;
...@@ -203,8 +180,7 @@ struct bnxt_qplib_rcfw { ...@@ -203,8 +180,7 @@ struct bnxt_qplib_rcfw {
/* Actual Cmd and Resp Queues */ /* Actual Cmd and Resp Queues */
struct bnxt_qplib_hwq cmdq; struct bnxt_qplib_hwq cmdq;
struct bnxt_qplib_crsq crsq; struct bnxt_qplib_crsq *crsqe_tbl;
struct bnxt_qplib_hwq crsb;
}; };
void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw); void bnxt_qplib_free_rcfw_channel(struct bnxt_qplib_rcfw *rcfw);
...@@ -219,11 +195,14 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev, ...@@ -219,11 +195,14 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev,
(struct bnxt_qplib_rcfw *, (struct bnxt_qplib_rcfw *,
struct creq_func_event *)); struct creq_func_event *));
int bnxt_qplib_rcfw_block_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie); struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
int bnxt_qplib_rcfw_wait_for_resp(struct bnxt_qplib_rcfw *rcfw, u16 cookie); struct bnxt_qplib_rcfw *rcfw,
void *bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw, u32 size);
struct cmdq_base *req, void **crsbe, void bnxt_qplib_rcfw_free_sbuf(struct bnxt_qplib_rcfw *rcfw,
u8 is_block); struct bnxt_qplib_rcfw_sbuf *sbuf);
int bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
struct cmdq_base *req, struct creq_base *resp,
void *sbuf, u8 is_block);
int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw); int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw);
int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw, int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
......
...@@ -48,6 +48,10 @@ extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero; ...@@ -48,6 +48,10 @@ extern const struct bnxt_qplib_gid bnxt_qplib_gid_zero;
#define HWQ_CMP(idx, hwq) ((idx) & ((hwq)->max_elements - 1)) #define HWQ_CMP(idx, hwq) ((idx) & ((hwq)->max_elements - 1))
#define HWQ_FREE_SLOTS(hwq) (hwq->max_elements - \
((HWQ_CMP(hwq->prod, hwq)\
- HWQ_CMP(hwq->cons, hwq))\
& (hwq->max_elements - 1)))
enum bnxt_qplib_hwq_type { enum bnxt_qplib_hwq_type {
HWQ_TYPE_CTX, HWQ_TYPE_CTX,
HWQ_TYPE_QUEUE, HWQ_TYPE_QUEUE,
......
...@@ -55,37 +55,30 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, ...@@ -55,37 +55,30 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_dev_attr *attr) struct bnxt_qplib_dev_attr *attr)
{ {
struct cmdq_query_func req; struct cmdq_query_func req;
struct creq_query_func_resp *resp; struct creq_query_func_resp resp;
struct bnxt_qplib_rcfw_sbuf *sbuf;
struct creq_query_func_resp_sb *sb; struct creq_query_func_resp_sb *sb;
u16 cmd_flags = 0; u16 cmd_flags = 0;
u32 temp; u32 temp;
u8 *tqm_alloc; u8 *tqm_alloc;
int i; int i, rc = 0;
RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags); RCFW_CMD_PREP(req, QUERY_FUNC, cmd_flags);
req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS; sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
resp = (struct creq_query_func_resp *) if (!sbuf) {
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void **)&sb,
0);
if (!resp) {
dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: SP: QUERY_FUNC failed ");
dev_err(&rcfw->pdev->dev, dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x", "QPLIB: SP: QUERY_FUNC alloc side buffer failed");
resp->status, le16_to_cpu(req.cookie), return -ENOMEM;
le16_to_cpu(resp->cookie));
return -EINVAL;
} }
sb = sbuf->sb;
req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
(void *)sbuf, 0);
if (rc)
goto bail;
/* Extract the context from the side buffer */ /* Extract the context from the side buffer */
attr->max_qp = le32_to_cpu(sb->max_qp); attr->max_qp = le32_to_cpu(sb->max_qp);
attr->max_qp_rd_atom = attr->max_qp_rd_atom =
...@@ -95,6 +88,11 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, ...@@ -95,6 +88,11 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ? sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom; BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom;
attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr); attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr);
/*
* 128 WQEs needs to be reserved for the HW (8916). Prevent
* reporting the max number
*/
attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS;
attr->max_qp_sges = sb->max_sge; attr->max_qp_sges = sb->max_sge;
attr->max_cq = le32_to_cpu(sb->max_cq); attr->max_cq = le32_to_cpu(sb->max_cq);
attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); attr->max_cq_wqes = le32_to_cpu(sb->max_cqe);
...@@ -130,7 +128,10 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw, ...@@ -130,7 +128,10 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc); attr->tqm_alloc_reqs[i * 4 + 2] = *(++tqm_alloc);
attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc); attr->tqm_alloc_reqs[i * 4 + 3] = *(++tqm_alloc);
} }
return 0;
bail:
bnxt_qplib_rcfw_free_sbuf(rcfw, sbuf);
return rc;
} }
/* SGID */ /* SGID */
...@@ -178,8 +179,9 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -178,8 +179,9 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
/* Remove GID from the SGID table */ /* Remove GID from the SGID table */
if (update) { if (update) {
struct cmdq_delete_gid req; struct cmdq_delete_gid req;
struct creq_delete_gid_resp *resp; struct creq_delete_gid_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
int rc;
RCFW_CMD_PREP(req, DELETE_GID, cmd_flags); RCFW_CMD_PREP(req, DELETE_GID, cmd_flags);
if (sgid_tbl->hw_id[index] == 0xFFFF) { if (sgid_tbl->hw_id[index] == 0xFFFF) {
...@@ -188,31 +190,10 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -188,31 +190,10 @@ int bnxt_qplib_del_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
return -EINVAL; return -EINVAL;
} }
req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]); req.gid_index = cpu_to_le16(sgid_tbl->hw_id[index]);
resp = (struct creq_delete_gid_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL, (void *)&resp, NULL, 0);
0); if (rc)
if (!resp) { return rc;
dev_err(&res->pdev->dev,
"QPLIB: SP: DELETE_GID send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw,
le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&res->pdev->dev,
"QPLIB: SP: DELETE_GID timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&res->pdev->dev,
"QPLIB: SP: DELETE_GID failed ");
dev_err(&res->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
} }
memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero, memcpy(&sgid_tbl->tbl[index], &bnxt_qplib_gid_zero,
sizeof(bnxt_qplib_gid_zero)); sizeof(bnxt_qplib_gid_zero));
...@@ -234,7 +215,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -234,7 +215,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
struct bnxt_qplib_res, struct bnxt_qplib_res,
sgid_tbl); sgid_tbl);
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
int i, free_idx, rc = 0; int i, free_idx;
if (!sgid_tbl) { if (!sgid_tbl) {
dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated"); dev_err(&res->pdev->dev, "QPLIB: SGID table not allocated");
...@@ -266,10 +247,11 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -266,10 +247,11 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
} }
if (update) { if (update) {
struct cmdq_add_gid req; struct cmdq_add_gid req;
struct creq_add_gid_resp *resp; struct creq_add_gid_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
u32 temp32[4]; u32 temp32[4];
u16 temp16[3]; u16 temp16[3];
int rc;
RCFW_CMD_PREP(req, ADD_GID, cmd_flags); RCFW_CMD_PREP(req, ADD_GID, cmd_flags);
...@@ -290,31 +272,11 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -290,31 +272,11 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
req.src_mac[1] = cpu_to_be16(temp16[1]); req.src_mac[1] = cpu_to_be16(temp16[1]);
req.src_mac[2] = cpu_to_be16(temp16[2]); req.src_mac[2] = cpu_to_be16(temp16[2]);
resp = (struct creq_add_gid_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 0);
NULL, 0); if (rc)
if (!resp) { return rc;
dev_err(&res->pdev->dev, sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp.xid);
"QPLIB: SP: ADD_GID send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw,
le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&res->pdev->dev,
"QPIB: SP: ADD_GID timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&res->pdev->dev, "QPLIB: SP: ADD_GID failed ");
dev_err(&res->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
sgid_tbl->hw_id[free_idx] = le32_to_cpu(resp->xid);
} }
/* Add GID to the sgid_tbl */ /* Add GID to the sgid_tbl */
memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid)); memcpy(&sgid_tbl->tbl[free_idx], gid, sizeof(*gid));
...@@ -325,7 +287,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl, ...@@ -325,7 +287,7 @@ int bnxt_qplib_add_sgid(struct bnxt_qplib_sgid_tbl *sgid_tbl,
*index = free_idx; *index = free_idx;
/* unlock */ /* unlock */
return rc; return 0;
} }
/* pkeys */ /* pkeys */
...@@ -422,10 +384,11 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) ...@@ -422,10 +384,11 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_create_ah req; struct cmdq_create_ah req;
struct creq_create_ah_resp *resp; struct creq_create_ah_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
u32 temp32[4]; u32 temp32[4];
u16 temp16[3]; u16 temp16[3];
int rc;
RCFW_CMD_PREP(req, CREATE_AH, cmd_flags); RCFW_CMD_PREP(req, CREATE_AH, cmd_flags);
...@@ -450,28 +413,12 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) ...@@ -450,28 +413,12 @@ int bnxt_qplib_create_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
req.dest_mac[1] = cpu_to_le16(temp16[1]); req.dest_mac[1] = cpu_to_le16(temp16[1]);
req.dest_mac[2] = cpu_to_le16(temp16[2]); req.dest_mac[2] = cpu_to_le16(temp16[2]);
resp = (struct creq_create_ah_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
NULL, 1); NULL, 1);
if (!resp) { if (rc)
dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH send failed"); return rc;
return -EINVAL;
} ah->id = le32_to_cpu(resp.xid);
if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: SP: CREATE_AH failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
ah->id = le32_to_cpu(resp->xid);
return 0; return 0;
} }
...@@ -479,35 +426,19 @@ int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah) ...@@ -479,35 +426,19 @@ int bnxt_qplib_destroy_ah(struct bnxt_qplib_res *res, struct bnxt_qplib_ah *ah)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_destroy_ah req; struct cmdq_destroy_ah req;
struct creq_destroy_ah_resp *resp; struct creq_destroy_ah_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
int rc;
/* Clean up the AH table in the device */ /* Clean up the AH table in the device */
RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags); RCFW_CMD_PREP(req, DESTROY_AH, cmd_flags);
req.ah_cid = cpu_to_le32(ah->id); req.ah_cid = cpu_to_le32(ah->id);
resp = (struct creq_destroy_ah_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
NULL, 1); NULL, 1);
if (!resp) { if (rc)
dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH send failed"); return rc;
return -EINVAL;
}
if (!bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: SP: DESTROY_AH failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
return 0; return 0;
} }
...@@ -516,8 +447,9 @@ int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) ...@@ -516,8 +447,9 @@ int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_deallocate_key req; struct cmdq_deallocate_key req;
struct creq_deallocate_key_resp *resp; struct creq_deallocate_key_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
int rc;
if (mrw->lkey == 0xFFFFFFFF) { if (mrw->lkey == 0xFFFFFFFF) {
dev_info(&res->pdev->dev, dev_info(&res->pdev->dev,
...@@ -536,27 +468,11 @@ int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) ...@@ -536,27 +468,11 @@ int bnxt_qplib_free_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
else else
req.key = cpu_to_le32(mrw->lkey); req.key = cpu_to_le32(mrw->lkey);
resp = (struct creq_deallocate_key_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
NULL, 0); NULL, 0);
if (!resp) { if (rc)
dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR send failed"); return rc;
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&res->pdev->dev, "QPLIB: SP: FREE_MR failed ");
dev_err(&res->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
/* Free the qplib's MRW memory */ /* Free the qplib's MRW memory */
if (mrw->hwq.max_elements) if (mrw->hwq.max_elements)
bnxt_qplib_free_hwq(res->pdev, &mrw->hwq); bnxt_qplib_free_hwq(res->pdev, &mrw->hwq);
...@@ -568,9 +484,10 @@ int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) ...@@ -568,9 +484,10 @@ int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_allocate_mrw req; struct cmdq_allocate_mrw req;
struct creq_allocate_mrw_resp *resp; struct creq_allocate_mrw_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
unsigned long tmp; unsigned long tmp;
int rc;
RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags); RCFW_CMD_PREP(req, ALLOCATE_MRW, cmd_flags);
...@@ -584,33 +501,17 @@ int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw) ...@@ -584,33 +501,17 @@ int bnxt_qplib_alloc_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw)
tmp = (unsigned long)mrw; tmp = (unsigned long)mrw;
req.mrw_handle = cpu_to_le64(tmp); req.mrw_handle = cpu_to_le64(tmp);
resp = (struct creq_allocate_mrw_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, 0);
NULL, 0); if (rc)
if (!resp) { return rc;
dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW send failed");
return -EINVAL;
}
if (!bnxt_qplib_rcfw_wait_for_resp(rcfw, le16_to_cpu(req.cookie))) {
/* Cmd timed out */
dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: SP: ALLOC_MRW failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) || if ((mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE1) ||
(mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) || (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2A) ||
(mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B)) (mrw->type == CMDQ_ALLOCATE_MRW_MRW_FLAGS_MW_TYPE2B))
mrw->rkey = le32_to_cpu(resp->xid); mrw->rkey = le32_to_cpu(resp.xid);
else else
mrw->lkey = le32_to_cpu(resp->xid); mrw->lkey = le32_to_cpu(resp.xid);
return 0; return 0;
} }
...@@ -619,40 +520,17 @@ int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw, ...@@ -619,40 +520,17 @@ int bnxt_qplib_dereg_mrw(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mrw,
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_deregister_mr req; struct cmdq_deregister_mr req;
struct creq_deregister_mr_resp *resp; struct creq_deregister_mr_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
int rc; int rc;
RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags); RCFW_CMD_PREP(req, DEREGISTER_MR, cmd_flags);
req.lkey = cpu_to_le32(mrw->lkey); req.lkey = cpu_to_le32(mrw->lkey);
resp = (struct creq_deregister_mr_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, block);
NULL, block); if (rc)
if (!resp) { return rc;
dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR send failed");
return -EINVAL;
}
if (block)
rc = bnxt_qplib_rcfw_block_for_resp(rcfw,
le16_to_cpu(req.cookie));
else
rc = bnxt_qplib_rcfw_wait_for_resp(rcfw,
le16_to_cpu(req.cookie));
if (!rc) {
/* Cmd timed out */
dev_err(&res->pdev->dev, "QPLIB: SP: DEREG_MR timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&rcfw->pdev->dev, "QPLIB: SP: DEREG_MR failed ");
dev_err(&rcfw->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
/* Free the qplib's MR memory */ /* Free the qplib's MR memory */
if (mrw->hwq.max_elements) { if (mrw->hwq.max_elements) {
...@@ -669,7 +547,7 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, ...@@ -669,7 +547,7 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_register_mr req; struct cmdq_register_mr req;
struct creq_register_mr_resp *resp; struct creq_register_mr_resp resp;
u16 cmd_flags = 0, level; u16 cmd_flags = 0, level;
int pg_ptrs, pages, i, rc; int pg_ptrs, pages, i, rc;
dma_addr_t **pbl_ptr; dma_addr_t **pbl_ptr;
...@@ -730,36 +608,11 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, ...@@ -730,36 +608,11 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr,
req.key = cpu_to_le32(mr->lkey); req.key = cpu_to_le32(mr->lkey);
req.mr_size = cpu_to_le64(mr->total_size); req.mr_size = cpu_to_le64(mr->total_size);
resp = (struct creq_register_mr_resp *) rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp, NULL, block);
NULL, block); if (rc)
if (!resp) {
dev_err(&res->pdev->dev, "SP: REG_MR send failed");
rc = -EINVAL;
goto fail;
}
if (block)
rc = bnxt_qplib_rcfw_block_for_resp(rcfw,
le16_to_cpu(req.cookie));
else
rc = bnxt_qplib_rcfw_wait_for_resp(rcfw,
le16_to_cpu(req.cookie));
if (!rc) {
/* Cmd timed out */
dev_err(&res->pdev->dev, "SP: REG_MR timed out");
rc = -ETIMEDOUT;
goto fail; goto fail;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&res->pdev->dev, "QPLIB: SP: REG_MR failed ");
dev_err(&res->pdev->dev,
"QPLIB: SP: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
rc = -EINVAL;
goto fail;
}
return 0; return 0;
fail: fail:
...@@ -804,35 +657,15 @@ int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids) ...@@ -804,35 +657,15 @@ int bnxt_qplib_map_tc2cos(struct bnxt_qplib_res *res, u16 *cids)
{ {
struct bnxt_qplib_rcfw *rcfw = res->rcfw; struct bnxt_qplib_rcfw *rcfw = res->rcfw;
struct cmdq_map_tc_to_cos req; struct cmdq_map_tc_to_cos req;
struct creq_map_tc_to_cos_resp *resp; struct creq_map_tc_to_cos_resp resp;
u16 cmd_flags = 0; u16 cmd_flags = 0;
int tleft; int rc = 0;
RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags); RCFW_CMD_PREP(req, MAP_TC_TO_COS, cmd_flags);
req.cos0 = cpu_to_le16(cids[0]); req.cos0 = cpu_to_le16(cids[0]);
req.cos1 = cpu_to_le16(cids[1]); req.cos1 = cpu_to_le16(cids[1]);
resp = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, NULL, 0); rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req,
if (!resp) { (void *)&resp, NULL, 0);
dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS send failed");
return -EINVAL;
}
tleft = bnxt_qplib_rcfw_block_for_resp(rcfw, le16_to_cpu(req.cookie));
if (!tleft) {
dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS timed out");
return -ETIMEDOUT;
}
if (resp->status ||
le16_to_cpu(resp->cookie) != le16_to_cpu(req.cookie)) {
dev_err(&res->pdev->dev, "QPLIB: SP: MAP_TC2COS failed ");
dev_err(&res->pdev->dev,
"QPLIB: with status 0x%x cmdq 0x%x resp 0x%x",
resp->status, le16_to_cpu(req.cookie),
le16_to_cpu(resp->cookie));
return -EINVAL;
}
return 0; return 0;
} }
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#ifndef __BNXT_QPLIB_SP_H__ #ifndef __BNXT_QPLIB_SP_H__
#define __BNXT_QPLIB_SP_H__ #define __BNXT_QPLIB_SP_H__
#define BNXT_QPLIB_RESERVED_QP_WRS 128
struct bnxt_qplib_dev_attr { struct bnxt_qplib_dev_attr {
char fw_ver[32]; char fw_ver[32];
u16 max_sgid; u16 max_sgid;
......
...@@ -767,7 +767,7 @@ void c4iw_release_dev_ucontext(struct c4iw_rdev *rdev, ...@@ -767,7 +767,7 @@ void c4iw_release_dev_ucontext(struct c4iw_rdev *rdev,
kfree(entry); kfree(entry);
} }
list_for_each_safe(pos, nxt, &uctx->qpids) { list_for_each_safe(pos, nxt, &uctx->cqids) {
entry = list_entry(pos, struct c4iw_qid_list, entry); entry = list_entry(pos, struct c4iw_qid_list, entry);
list_del_init(&entry->entry); list_del_init(&entry->entry);
kfree(entry); kfree(entry);
...@@ -880,13 +880,15 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev) ...@@ -880,13 +880,15 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
rdev->free_workq = create_singlethread_workqueue("iw_cxgb4_free"); rdev->free_workq = create_singlethread_workqueue("iw_cxgb4_free");
if (!rdev->free_workq) { if (!rdev->free_workq) {
err = -ENOMEM; err = -ENOMEM;
goto err_free_status_page; goto err_free_status_page_and_wr_log;
} }
rdev->status_page->db_off = 0; rdev->status_page->db_off = 0;
return 0; return 0;
err_free_status_page: err_free_status_page_and_wr_log:
if (c4iw_wr_log && rdev->wr_log)
kfree(rdev->wr_log);
free_page((unsigned long)rdev->status_page); free_page((unsigned long)rdev->status_page);
destroy_ocqp_pool: destroy_ocqp_pool:
c4iw_ocqp_pool_destroy(rdev); c4iw_ocqp_pool_destroy(rdev);
...@@ -903,9 +905,11 @@ static void c4iw_rdev_close(struct c4iw_rdev *rdev) ...@@ -903,9 +905,11 @@ static void c4iw_rdev_close(struct c4iw_rdev *rdev)
{ {
destroy_workqueue(rdev->free_workq); destroy_workqueue(rdev->free_workq);
kfree(rdev->wr_log); kfree(rdev->wr_log);
c4iw_release_dev_ucontext(rdev, &rdev->uctx);
free_page((unsigned long)rdev->status_page); free_page((unsigned long)rdev->status_page);
c4iw_pblpool_destroy(rdev); c4iw_pblpool_destroy(rdev);
c4iw_rqtpool_destroy(rdev); c4iw_rqtpool_destroy(rdev);
c4iw_ocqp_pool_destroy(rdev);
c4iw_destroy_resource(&rdev->resource); c4iw_destroy_resource(&rdev->resource);
} }
......
...@@ -3692,8 +3692,10 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev) ...@@ -3692,8 +3692,10 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status; dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
dev->ib_dev.get_port_immutable = mlx5_port_immutable; dev->ib_dev.get_port_immutable = mlx5_port_immutable;
dev->ib_dev.get_dev_fw_str = get_dev_fw_str; dev->ib_dev.get_dev_fw_str = get_dev_fw_str;
if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) {
dev->ib_dev.alloc_rdma_netdev = mlx5_ib_alloc_rdma_netdev; dev->ib_dev.alloc_rdma_netdev = mlx5_ib_alloc_rdma_netdev;
dev->ib_dev.free_rdma_netdev = mlx5_ib_free_rdma_netdev; dev->ib_dev.free_rdma_netdev = mlx5_ib_free_rdma_netdev;
}
if (mlx5_core_is_pf(mdev)) { if (mlx5_core_is_pf(mdev)) {
dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config; dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config;
dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state; dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state;
......
...@@ -60,6 +60,9 @@ ...@@ -60,6 +60,9 @@
#define QEDR_CQ_MAGIC_NUMBER (0x11223344) #define QEDR_CQ_MAGIC_NUMBER (0x11223344)
#define FW_PAGE_SIZE (RDMA_RING_PAGE_SIZE)
#define FW_PAGE_SHIFT (12)
struct qedr_dev; struct qedr_dev;
struct qedr_cnq { struct qedr_cnq {
......
...@@ -653,14 +653,15 @@ static int qedr_prepare_pbl_tbl(struct qedr_dev *dev, ...@@ -653,14 +653,15 @@ static int qedr_prepare_pbl_tbl(struct qedr_dev *dev,
static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem, static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem,
struct qedr_pbl *pbl, struct qedr_pbl *pbl,
struct qedr_pbl_info *pbl_info) struct qedr_pbl_info *pbl_info, u32 pg_shift)
{ {
int shift, pg_cnt, pages, pbe_cnt, total_num_pbes = 0; int shift, pg_cnt, pages, pbe_cnt, total_num_pbes = 0;
u32 fw_pg_cnt, fw_pg_per_umem_pg;
struct qedr_pbl *pbl_tbl; struct qedr_pbl *pbl_tbl;
struct scatterlist *sg; struct scatterlist *sg;
struct regpair *pbe; struct regpair *pbe;
u64 pg_addr;
int entry; int entry;
u32 addr;
if (!pbl_info->num_pbes) if (!pbl_info->num_pbes)
return; return;
...@@ -683,15 +684,17 @@ static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem, ...@@ -683,15 +684,17 @@ static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem,
shift = umem->page_shift; shift = umem->page_shift;
fw_pg_per_umem_pg = BIT(umem->page_shift - pg_shift);
for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) { for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
pages = sg_dma_len(sg) >> shift; pages = sg_dma_len(sg) >> shift;
pg_addr = sg_dma_address(sg);
for (pg_cnt = 0; pg_cnt < pages; pg_cnt++) { for (pg_cnt = 0; pg_cnt < pages; pg_cnt++) {
/* store the page address in pbe */ for (fw_pg_cnt = 0; fw_pg_cnt < fw_pg_per_umem_pg;) {
pbe->lo = cpu_to_le32(sg_dma_address(sg) + pbe->lo = cpu_to_le32(pg_addr);
(pg_cnt << shift)); pbe->hi = cpu_to_le32(upper_32_bits(pg_addr));
addr = upper_32_bits(sg_dma_address(sg) +
(pg_cnt << shift)); pg_addr += BIT(pg_shift);
pbe->hi = cpu_to_le32(addr);
pbe_cnt++; pbe_cnt++;
total_num_pbes++; total_num_pbes++;
pbe++; pbe++;
...@@ -702,11 +705,15 @@ static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem, ...@@ -702,11 +705,15 @@ static void qedr_populate_pbls(struct qedr_dev *dev, struct ib_umem *umem,
/* If the given pbl is full storing the pbes, /* If the given pbl is full storing the pbes,
* move to next pbl. * move to next pbl.
*/ */
if (pbe_cnt == (pbl_info->pbl_size / sizeof(u64))) { if (pbe_cnt ==
(pbl_info->pbl_size / sizeof(u64))) {
pbl_tbl++; pbl_tbl++;
pbe = (struct regpair *)pbl_tbl->va; pbe = (struct regpair *)pbl_tbl->va;
pbe_cnt = 0; pbe_cnt = 0;
} }
fw_pg_cnt++;
}
} }
} }
} }
...@@ -754,7 +761,7 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx, ...@@ -754,7 +761,7 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
u64 buf_addr, size_t buf_len, u64 buf_addr, size_t buf_len,
int access, int dmasync) int access, int dmasync)
{ {
int page_cnt; u32 fw_pages;
int rc; int rc;
q->buf_addr = buf_addr; q->buf_addr = buf_addr;
...@@ -766,8 +773,10 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx, ...@@ -766,8 +773,10 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
return PTR_ERR(q->umem); return PTR_ERR(q->umem);
} }
page_cnt = ib_umem_page_count(q->umem); fw_pages = ib_umem_page_count(q->umem) <<
rc = qedr_prepare_pbl_tbl(dev, &q->pbl_info, page_cnt, 0); (q->umem->page_shift - FW_PAGE_SHIFT);
rc = qedr_prepare_pbl_tbl(dev, &q->pbl_info, fw_pages, 0);
if (rc) if (rc)
goto err0; goto err0;
...@@ -777,7 +786,8 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx, ...@@ -777,7 +786,8 @@ static inline int qedr_init_user_queue(struct ib_ucontext *ib_ctx,
goto err0; goto err0;
} }
qedr_populate_pbls(dev, q->umem, q->pbl_tbl, &q->pbl_info); qedr_populate_pbls(dev, q->umem, q->pbl_tbl, &q->pbl_info,
FW_PAGE_SHIFT);
return 0; return 0;
...@@ -2226,7 +2236,7 @@ struct ib_mr *qedr_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len, ...@@ -2226,7 +2236,7 @@ struct ib_mr *qedr_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 len,
goto err1; goto err1;
qedr_populate_pbls(dev, mr->umem, mr->info.pbl_table, qedr_populate_pbls(dev, mr->umem, mr->info.pbl_table,
&mr->info.pbl_info); &mr->info.pbl_info, mr->umem->page_shift);
rc = dev->ops->rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid); rc = dev->ops->rdma_alloc_tid(dev->rdma_ctx, &mr->hw_mr.itid);
if (rc) { if (rc) {
...@@ -3209,6 +3219,10 @@ static int process_req(struct qedr_dev *dev, struct qedr_qp *qp, ...@@ -3209,6 +3219,10 @@ static int process_req(struct qedr_dev *dev, struct qedr_qp *qp,
case IB_WC_REG_MR: case IB_WC_REG_MR:
qp->wqe_wr_id[qp->sq.cons].mr->info.completed++; qp->wqe_wr_id[qp->sq.cons].mr->info.completed++;
break; break;
case IB_WC_RDMA_READ:
case IB_WC_SEND:
wc->byte_len = qp->wqe_wr_id[qp->sq.cons].bytes_len;
break;
default: default:
break; break;
} }
......
...@@ -740,11 +740,6 @@ static int init_send_wqe(struct rxe_qp *qp, struct ib_send_wr *ibwr, ...@@ -740,11 +740,6 @@ static int init_send_wqe(struct rxe_qp *qp, struct ib_send_wr *ibwr,
sge = ibwr->sg_list; sge = ibwr->sg_list;
for (i = 0; i < num_sge; i++, sge++) { for (i = 0; i < num_sge; i++, sge++) {
if (qp->is_user && copy_from_user(p, (__user void *)
(uintptr_t)sge->addr, sge->length))
return -EFAULT;
else if (!qp->is_user)
memcpy(p, (void *)(uintptr_t)sge->addr, memcpy(p, (void *)(uintptr_t)sge->addr,
sge->length); sge->length);
......
...@@ -863,7 +863,6 @@ int ipoib_ib_dev_open(struct net_device *dev) ...@@ -863,7 +863,6 @@ int ipoib_ib_dev_open(struct net_device *dev)
set_bit(IPOIB_STOP_REAPER, &priv->flags); set_bit(IPOIB_STOP_REAPER, &priv->flags);
cancel_delayed_work(&priv->ah_reap_task); cancel_delayed_work(&priv->ah_reap_task);
set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
napi_enable(&priv->napi);
ipoib_ib_dev_stop(dev); ipoib_ib_dev_stop(dev);
return -1; return -1;
} }
......
...@@ -1596,6 +1596,8 @@ static void ipoib_dev_uninit_default(struct net_device *dev) ...@@ -1596,6 +1596,8 @@ static void ipoib_dev_uninit_default(struct net_device *dev)
ipoib_transport_dev_cleanup(dev); ipoib_transport_dev_cleanup(dev);
netif_napi_del(&priv->napi);
ipoib_cm_dev_cleanup(dev); ipoib_cm_dev_cleanup(dev);
kfree(priv->rx_ring); kfree(priv->rx_ring);
...@@ -1649,6 +1651,7 @@ static int ipoib_dev_init_default(struct net_device *dev) ...@@ -1649,6 +1651,7 @@ static int ipoib_dev_init_default(struct net_device *dev)
kfree(priv->rx_ring); kfree(priv->rx_ring);
out: out:
netif_napi_del(&priv->napi);
return -ENOMEM; return -ENOMEM;
} }
...@@ -2237,6 +2240,7 @@ static struct net_device *ipoib_add_port(const char *format, ...@@ -2237,6 +2240,7 @@ static struct net_device *ipoib_add_port(const char *format,
device_init_failed: device_init_failed:
free_netdev(priv->dev); free_netdev(priv->dev);
kfree(priv);
alloc_mem_failed: alloc_mem_failed:
return ERR_PTR(result); return ERR_PTR(result);
...@@ -2277,7 +2281,7 @@ static void ipoib_add_one(struct ib_device *device) ...@@ -2277,7 +2281,7 @@ static void ipoib_add_one(struct ib_device *device)
static void ipoib_remove_one(struct ib_device *device, void *client_data) static void ipoib_remove_one(struct ib_device *device, void *client_data)
{ {
struct ipoib_dev_priv *priv, *tmp; struct ipoib_dev_priv *priv, *tmp, *cpriv, *tcpriv;
struct list_head *dev_list = client_data; struct list_head *dev_list = client_data;
if (!dev_list) if (!dev_list)
...@@ -2300,7 +2304,14 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data) ...@@ -2300,7 +2304,14 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
flush_workqueue(priv->wq); flush_workqueue(priv->wq);
unregister_netdev(priv->dev); unregister_netdev(priv->dev);
if (device->free_rdma_netdev)
device->free_rdma_netdev(priv->dev);
else
free_netdev(priv->dev); free_netdev(priv->dev);
list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list)
kfree(cpriv);
kfree(priv); kfree(priv);
} }
......
...@@ -133,13 +133,13 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) ...@@ -133,13 +133,13 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
snprintf(intf_name, sizeof intf_name, "%s.%04x", snprintf(intf_name, sizeof intf_name, "%s.%04x",
ppriv->dev->name, pkey); ppriv->dev->name, pkey);
if (!rtnl_trylock())
return restart_syscall();
priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name); priv = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
if (!rtnl_trylock())
return restart_syscall();
down_write(&ppriv->vlan_rwsem); down_write(&ppriv->vlan_rwsem);
/* /*
...@@ -167,8 +167,10 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) ...@@ -167,8 +167,10 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
rtnl_unlock(); rtnl_unlock();
if (result) if (result) {
free_netdev(priv->dev); free_netdev(priv->dev);
kfree(priv);
}
return result; return result;
} }
...@@ -209,6 +211,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) ...@@ -209,6 +211,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
if (dev) { if (dev) {
free_netdev(dev); free_netdev(dev);
kfree(priv);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment