Commit abe03080 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull infiniband/rdma fixes from Roland Dreier:
 - Fixes for the newly merged mlx5 hardware driver
 - Stack info leak fixes from Dan Carpenter
 - Fixes for pkey table handling with SR-IOV
 - A few other small things

* tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  IPoIB: Fix pkey change flow for virtualization environments
  IPoIB: Make sure child devices use valid/proper pkeys
  IB/core: Create QP1 using the pkey index which contains the default pkey
  mlx5_core: Variable may be used uninitialized
  mlx5_core: Implement new initialization sequence
  mlx5_core: Fix use after free in mlx5_cmd_comp_handler()
  IB/mlx5: Fix stack info leak in mlx5_ib_alloc_ucontext()
  IB/mlx5: Fix error return code in init_one()
  IB/mlx4: Use default pkey when creating tunnel QPs
  RDMA/cma: Only call cma_save_ib_info() for CM REQs
  RDMA/cma: Fix accessing invalid private data for UD
  RDMA/cma: Fix gcc warning
  Revert "RDMA/nes: Fix compilation error when nes_debug is enabled"
  IB/qib: Add err_decode() call for ring dump
  RDMA/cxgb3: Fix stack info leak in iwch_create_cq()
  RDMA/nes: Fix info leaks in nes_create_qp() and nes_create_cq()
  RDMA/ocrdma: Fix several stack info leaks
  RDMA/cxgb4: Fix stack info leak in c4iw_create_qp()
  RDMA/ocrdma: Remove unused include
parents 1cb39a6c 569935db
...@@ -423,7 +423,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) ...@@ -423,7 +423,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
struct sockaddr_ib *addr; struct sockaddr_ib *addr;
union ib_gid gid, sgid, *dgid; union ib_gid gid, sgid, *dgid;
u16 pkey, index; u16 pkey, index;
u8 port, p; u8 p;
int i; int i;
cma_dev = NULL; cma_dev = NULL;
...@@ -443,7 +443,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) ...@@ -443,7 +443,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
if (!memcmp(&gid, dgid, sizeof(gid))) { if (!memcmp(&gid, dgid, sizeof(gid))) {
cma_dev = cur_dev; cma_dev = cur_dev;
sgid = gid; sgid = gid;
port = p; id_priv->id.port_num = p;
goto found; goto found;
} }
...@@ -451,7 +451,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) ...@@ -451,7 +451,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
dgid->global.subnet_prefix)) { dgid->global.subnet_prefix)) {
cma_dev = cur_dev; cma_dev = cur_dev;
sgid = gid; sgid = gid;
port = p; id_priv->id.port_num = p;
} }
} }
} }
...@@ -462,7 +462,6 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) ...@@ -462,7 +462,6 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
found: found:
cma_attach_to_dev(id_priv, cma_dev); cma_attach_to_dev(id_priv, cma_dev);
id_priv->id.port_num = port;
addr = (struct sockaddr_ib *) cma_src_addr(id_priv); addr = (struct sockaddr_ib *) cma_src_addr(id_priv);
memcpy(&addr->sib_addr, &sgid, sizeof sgid); memcpy(&addr->sib_addr, &sgid, sizeof sgid);
cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr); cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr);
...@@ -880,7 +879,8 @@ static int cma_save_net_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id ...@@ -880,7 +879,8 @@ static int cma_save_net_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id
{ {
struct cma_hdr *hdr; struct cma_hdr *hdr;
if (listen_id->route.addr.src_addr.ss_family == AF_IB) { if ((listen_id->route.addr.src_addr.ss_family == AF_IB) &&
(ib_event->event == IB_CM_REQ_RECEIVED)) {
cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path); cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path);
return 0; return 0;
} }
...@@ -2677,29 +2677,32 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, ...@@ -2677,29 +2677,32 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
{ {
struct ib_cm_sidr_req_param req; struct ib_cm_sidr_req_param req;
struct ib_cm_id *id; struct ib_cm_id *id;
void *private_data;
int offset, ret; int offset, ret;
memset(&req, 0, sizeof req);
offset = cma_user_data_offset(id_priv); offset = cma_user_data_offset(id_priv);
req.private_data_len = offset + conn_param->private_data_len; req.private_data_len = offset + conn_param->private_data_len;
if (req.private_data_len < conn_param->private_data_len) if (req.private_data_len < conn_param->private_data_len)
return -EINVAL; return -EINVAL;
if (req.private_data_len) { if (req.private_data_len) {
req.private_data = kzalloc(req.private_data_len, GFP_ATOMIC); private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
if (!req.private_data) if (!private_data)
return -ENOMEM; return -ENOMEM;
} else { } else {
req.private_data = NULL; private_data = NULL;
} }
if (conn_param->private_data && conn_param->private_data_len) if (conn_param->private_data && conn_param->private_data_len)
memcpy((void *) req.private_data + offset, memcpy(private_data + offset, conn_param->private_data,
conn_param->private_data, conn_param->private_data_len); conn_param->private_data_len);
if (req.private_data) { if (private_data) {
ret = cma_format_hdr((void *) req.private_data, id_priv); ret = cma_format_hdr(private_data, id_priv);
if (ret) if (ret)
goto out; goto out;
req.private_data = private_data;
} }
id = ib_create_cm_id(id_priv->id.device, cma_sidr_rep_handler, id = ib_create_cm_id(id_priv->id.device, cma_sidr_rep_handler,
...@@ -2721,7 +2724,7 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv, ...@@ -2721,7 +2724,7 @@ static int cma_resolve_ib_udp(struct rdma_id_private *id_priv,
id_priv->cm_id.ib = NULL; id_priv->cm_id.ib = NULL;
} }
out: out:
kfree(req.private_data); kfree(private_data);
return ret; return ret;
} }
......
...@@ -2663,6 +2663,7 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv) ...@@ -2663,6 +2663,7 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
int ret, i; int ret, i;
struct ib_qp_attr *attr; struct ib_qp_attr *attr;
struct ib_qp *qp; struct ib_qp *qp;
u16 pkey_index;
attr = kmalloc(sizeof *attr, GFP_KERNEL); attr = kmalloc(sizeof *attr, GFP_KERNEL);
if (!attr) { if (!attr) {
...@@ -2670,6 +2671,11 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv) ...@@ -2670,6 +2671,11 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
return -ENOMEM; return -ENOMEM;
} }
ret = ib_find_pkey(port_priv->device, port_priv->port_num,
IB_DEFAULT_PKEY_FULL, &pkey_index);
if (ret)
pkey_index = 0;
for (i = 0; i < IB_MAD_QPS_CORE; i++) { for (i = 0; i < IB_MAD_QPS_CORE; i++) {
qp = port_priv->qp_info[i].qp; qp = port_priv->qp_info[i].qp;
if (!qp) if (!qp)
...@@ -2680,7 +2686,7 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv) ...@@ -2680,7 +2686,7 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
* one is needed for the Reset to Init transition * one is needed for the Reset to Init transition
*/ */
attr->qp_state = IB_QPS_INIT; attr->qp_state = IB_QPS_INIT;
attr->pkey_index = 0; attr->pkey_index = pkey_index;
attr->qkey = (qp->qp_num == 0) ? 0 : IB_QP1_QKEY; attr->qkey = (qp->qp_num == 0) ? 0 : IB_QP1_QKEY;
ret = ib_modify_qp(qp, attr, IB_QP_STATE | ret = ib_modify_qp(qp, attr, IB_QP_STATE |
IB_QP_PKEY_INDEX | IB_QP_QKEY); IB_QP_PKEY_INDEX | IB_QP_QKEY);
......
...@@ -226,6 +226,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve ...@@ -226,6 +226,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
mm->len = PAGE_ALIGN(((1UL << uresp.size_log2) + 1) * mm->len = PAGE_ALIGN(((1UL << uresp.size_log2) + 1) *
sizeof(struct t3_cqe)); sizeof(struct t3_cqe));
uresp.memsize = mm->len; uresp.memsize = mm->len;
uresp.reserved = 0;
resplen = sizeof uresp; resplen = sizeof uresp;
} }
if (ib_copy_to_udata(udata, &uresp, resplen)) { if (ib_copy_to_udata(udata, &uresp, resplen)) {
......
...@@ -1657,6 +1657,8 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, ...@@ -1657,6 +1657,8 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
if (mm5) { if (mm5) {
uresp.ma_sync_key = ucontext->key; uresp.ma_sync_key = ucontext->key;
ucontext->key += PAGE_SIZE; ucontext->key += PAGE_SIZE;
} else {
uresp.ma_sync_key = 0;
} }
uresp.sq_key = ucontext->key; uresp.sq_key = ucontext->key;
ucontext->key += PAGE_SIZE; ucontext->key += PAGE_SIZE;
......
...@@ -1511,8 +1511,14 @@ static int create_pv_sqp(struct mlx4_ib_demux_pv_ctx *ctx, ...@@ -1511,8 +1511,14 @@ static int create_pv_sqp(struct mlx4_ib_demux_pv_ctx *ctx,
memset(&attr, 0, sizeof attr); memset(&attr, 0, sizeof attr);
attr.qp_state = IB_QPS_INIT; attr.qp_state = IB_QPS_INIT;
attr.pkey_index = ret = 0;
to_mdev(ctx->ib_dev)->pkeys.virt2phys_pkey[ctx->slave][ctx->port - 1][0]; if (create_tun)
ret = find_slave_port_pkey_ix(to_mdev(ctx->ib_dev), ctx->slave,
ctx->port, IB_DEFAULT_PKEY_FULL,
&attr.pkey_index);
if (ret || !create_tun)
attr.pkey_index =
to_mdev(ctx->ib_dev)->pkeys.virt2phys_pkey[ctx->slave][ctx->port - 1][0];
attr.qkey = IB_QP1_QKEY; attr.qkey = IB_QP1_QKEY;
attr.port_num = ctx->port; attr.port_num = ctx->port;
ret = ib_modify_qp(tun_qp->qp, &attr, qp_attr_mask_INIT); ret = ib_modify_qp(tun_qp->qp, &attr, qp_attr_mask_INIT);
......
...@@ -619,7 +619,8 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, ...@@ -619,7 +619,8 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
resp.tot_uuars = req.total_num_uuars; resp.tot_uuars = req.total_num_uuars;
resp.num_ports = dev->mdev.caps.num_ports; resp.num_ports = dev->mdev.caps.num_ports;
err = ib_copy_to_udata(udata, &resp, sizeof(resp)); err = ib_copy_to_udata(udata, &resp,
sizeof(resp) - sizeof(resp.reserved));
if (err) if (err)
goto out_uars; goto out_uars;
...@@ -1426,7 +1427,8 @@ static int init_one(struct pci_dev *pdev, ...@@ -1426,7 +1427,8 @@ static int init_one(struct pci_dev *pdev,
if (err) if (err)
goto err_eqs; goto err_eqs;
if (ib_register_device(&dev->ib_dev, NULL)) err = ib_register_device(&dev->ib_dev, NULL);
if (err)
goto err_rsrc; goto err_rsrc;
err = create_umr_res(dev); err = create_umr_res(dev);
...@@ -1434,8 +1436,9 @@ static int init_one(struct pci_dev *pdev, ...@@ -1434,8 +1436,9 @@ static int init_one(struct pci_dev *pdev,
goto err_dev; goto err_dev;
for (i = 0; i < ARRAY_SIZE(mlx5_class_attributes); i++) { for (i = 0; i < ARRAY_SIZE(mlx5_class_attributes); i++) {
if (device_create_file(&dev->ib_dev.dev, err = device_create_file(&dev->ib_dev.dev,
mlx5_class_attributes[i])) mlx5_class_attributes[i]);
if (err)
goto err_umrc; goto err_umrc;
} }
......
...@@ -199,7 +199,7 @@ static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap, ...@@ -199,7 +199,7 @@ static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap,
static int sq_overhead(enum ib_qp_type qp_type) static int sq_overhead(enum ib_qp_type qp_type)
{ {
int size; int size = 0;
switch (qp_type) { switch (qp_type) {
case IB_QPT_XRC_INI: case IB_QPT_XRC_INI:
......
...@@ -3570,10 +3570,10 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, ...@@ -3570,10 +3570,10 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT; tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT; iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
nes_debug(NES_DBG_AEQ, "aeid = 0x%04X, qp-cq id = %d, aeqe = %p," nes_debug(NES_DBG_AEQ, "aeid = 0x%04X, qp-cq id = %d, aeqe = %p,"
" Tcp state = %d, iWARP state = %d\n", " Tcp state = %s, iWARP state = %s\n",
async_event_id, async_event_id,
le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe,
tcp_state, iwarp_state); nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);
aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]); aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
if (aeq_info & NES_AEQE_QP) { if (aeq_info & NES_AEQE_QP) {
......
...@@ -1384,6 +1384,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, ...@@ -1384,6 +1384,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
if (ibpd->uobject) { if (ibpd->uobject) {
uresp.mmap_sq_db_index = nesqp->mmap_sq_db_index; uresp.mmap_sq_db_index = nesqp->mmap_sq_db_index;
uresp.mmap_rq_db_index = 0;
uresp.actual_sq_size = sq_size; uresp.actual_sq_size = sq_size;
uresp.actual_rq_size = rq_size; uresp.actual_rq_size = rq_size;
uresp.qp_id = nesqp->hwqp.qp_id; uresp.qp_id = nesqp->hwqp.qp_id;
...@@ -1767,7 +1768,7 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, ...@@ -1767,7 +1768,7 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
resp.cq_id = nescq->hw_cq.cq_number; resp.cq_id = nescq->hw_cq.cq_number;
resp.cq_size = nescq->hw_cq.cq_size; resp.cq_size = nescq->hw_cq.cq_size;
resp.mmap_db_index = 0; resp.mmap_db_index = 0;
if (ib_copy_to_udata(udata, &resp, sizeof resp)) { if (ib_copy_to_udata(udata, &resp, sizeof resp - sizeof resp.reserved)) {
nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num); nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
kfree(nescq); kfree(nescq);
return ERR_PTR(-EFAULT); return ERR_PTR(-EFAULT);
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <net/netevent.h> #include <net/netevent.h>
#include <rdma/ib_addr.h> #include <rdma/ib_addr.h>
#include <rdma/ib_cache.h>
#include "ocrdma.h" #include "ocrdma.h"
#include "ocrdma_verbs.h" #include "ocrdma_verbs.h"
......
...@@ -242,6 +242,7 @@ struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *ibdev, ...@@ -242,6 +242,7 @@ struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *ibdev,
memset(ctx->ah_tbl.va, 0, map_len); memset(ctx->ah_tbl.va, 0, map_len);
ctx->ah_tbl.len = map_len; ctx->ah_tbl.len = map_len;
memset(&resp, 0, sizeof(resp));
resp.ah_tbl_len = ctx->ah_tbl.len; resp.ah_tbl_len = ctx->ah_tbl.len;
resp.ah_tbl_page = ctx->ah_tbl.pa; resp.ah_tbl_page = ctx->ah_tbl.pa;
...@@ -253,7 +254,6 @@ struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *ibdev, ...@@ -253,7 +254,6 @@ struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *ibdev,
resp.wqe_size = dev->attr.wqe_size; resp.wqe_size = dev->attr.wqe_size;
resp.rqe_size = dev->attr.rqe_size; resp.rqe_size = dev->attr.rqe_size;
resp.dpp_wqe_size = dev->attr.wqe_size; resp.dpp_wqe_size = dev->attr.wqe_size;
resp.rsvd = 0;
memcpy(resp.fw_ver, dev->attr.fw_ver, sizeof(resp.fw_ver)); memcpy(resp.fw_ver, dev->attr.fw_ver, sizeof(resp.fw_ver));
status = ib_copy_to_udata(udata, &resp, sizeof(resp)); status = ib_copy_to_udata(udata, &resp, sizeof(resp));
...@@ -338,6 +338,7 @@ static int ocrdma_copy_pd_uresp(struct ocrdma_pd *pd, ...@@ -338,6 +338,7 @@ static int ocrdma_copy_pd_uresp(struct ocrdma_pd *pd,
struct ocrdma_alloc_pd_uresp rsp; struct ocrdma_alloc_pd_uresp rsp;
struct ocrdma_ucontext *uctx = get_ocrdma_ucontext(ib_ctx); struct ocrdma_ucontext *uctx = get_ocrdma_ucontext(ib_ctx);
memset(&rsp, 0, sizeof(rsp));
rsp.id = pd->id; rsp.id = pd->id;
rsp.dpp_enabled = pd->dpp_enabled; rsp.dpp_enabled = pd->dpp_enabled;
db_page_addr = pd->dev->nic_info.unmapped_db + db_page_addr = pd->dev->nic_info.unmapped_db +
...@@ -692,6 +693,7 @@ static int ocrdma_copy_cq_uresp(struct ocrdma_cq *cq, struct ib_udata *udata, ...@@ -692,6 +693,7 @@ static int ocrdma_copy_cq_uresp(struct ocrdma_cq *cq, struct ib_udata *udata,
struct ocrdma_ucontext *uctx; struct ocrdma_ucontext *uctx;
struct ocrdma_create_cq_uresp uresp; struct ocrdma_create_cq_uresp uresp;
memset(&uresp, 0, sizeof(uresp));
uresp.cq_id = cq->id; uresp.cq_id = cq->id;
uresp.page_size = cq->len; uresp.page_size = cq->len;
uresp.num_pages = 1; uresp.num_pages = 1;
...@@ -1460,6 +1462,7 @@ static int ocrdma_copy_srq_uresp(struct ocrdma_srq *srq, struct ib_udata *udata) ...@@ -1460,6 +1462,7 @@ static int ocrdma_copy_srq_uresp(struct ocrdma_srq *srq, struct ib_udata *udata)
int status; int status;
struct ocrdma_create_srq_uresp uresp; struct ocrdma_create_srq_uresp uresp;
memset(&uresp, 0, sizeof(uresp));
uresp.rq_dbid = srq->rq.dbid; uresp.rq_dbid = srq->rq.dbid;
uresp.num_rq_pages = 1; uresp.num_rq_pages = 1;
uresp.rq_page_addr[0] = srq->rq.pa; uresp.rq_page_addr[0] = srq->rq.pa;
......
...@@ -1596,6 +1596,8 @@ static void sdma_7322_p_errors(struct qib_pportdata *ppd, u64 errs) ...@@ -1596,6 +1596,8 @@ static void sdma_7322_p_errors(struct qib_pportdata *ppd, u64 errs)
struct qib_devdata *dd = ppd->dd; struct qib_devdata *dd = ppd->dd;
errs &= QIB_E_P_SDMAERRS; errs &= QIB_E_P_SDMAERRS;
err_decode(ppd->cpspec->sdmamsgbuf, sizeof(ppd->cpspec->sdmamsgbuf),
errs, qib_7322p_error_msgs);
if (errs & QIB_E_P_SDMAUNEXPDATA) if (errs & QIB_E_P_SDMAUNEXPDATA)
qib_dev_err(dd, "IB%u:%u SDmaUnexpData\n", dd->unit, qib_dev_err(dd, "IB%u:%u SDmaUnexpData\n", dd->unit,
......
...@@ -717,7 +717,7 @@ void dump_sdma_state(struct qib_pportdata *ppd) ...@@ -717,7 +717,7 @@ void dump_sdma_state(struct qib_pportdata *ppd)
struct qib_sdma_txreq *txp, *txpnext; struct qib_sdma_txreq *txp, *txpnext;
__le64 *descqp; __le64 *descqp;
u64 desc[2]; u64 desc[2];
dma_addr_t addr; u64 addr;
u16 gen, dwlen, dwoffset; u16 gen, dwlen, dwoffset;
u16 head, tail, cnt; u16 head, tail, cnt;
......
...@@ -932,12 +932,47 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port) ...@@ -932,12 +932,47 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
return 0; return 0;
} }
/*
* Takes whatever value which is in pkey index 0 and updates priv->pkey
* returns 0 if the pkey value was changed.
*/
static inline int update_parent_pkey(struct ipoib_dev_priv *priv)
{
int result;
u16 prev_pkey;
prev_pkey = priv->pkey;
result = ib_query_pkey(priv->ca, priv->port, 0, &priv->pkey);
if (result) {
ipoib_warn(priv, "ib_query_pkey port %d failed (ret = %d)\n",
priv->port, result);
return result;
}
priv->pkey |= 0x8000;
if (prev_pkey != priv->pkey) {
ipoib_dbg(priv, "pkey changed from 0x%x to 0x%x\n",
prev_pkey, priv->pkey);
/*
* Update the pkey in the broadcast address, while making sure to set
* the full membership bit, so that we join the right broadcast group.
*/
priv->dev->broadcast[8] = priv->pkey >> 8;
priv->dev->broadcast[9] = priv->pkey & 0xff;
return 0;
}
return 1;
}
static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
enum ipoib_flush_level level) enum ipoib_flush_level level)
{ {
struct ipoib_dev_priv *cpriv; struct ipoib_dev_priv *cpriv;
struct net_device *dev = priv->dev; struct net_device *dev = priv->dev;
u16 new_index; u16 new_index;
int result;
mutex_lock(&priv->vlan_mutex); mutex_lock(&priv->vlan_mutex);
...@@ -951,6 +986,10 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, ...@@ -951,6 +986,10 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
mutex_unlock(&priv->vlan_mutex); mutex_unlock(&priv->vlan_mutex);
if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) { if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) {
/* for non-child devices must check/update the pkey value here */
if (level == IPOIB_FLUSH_HEAVY &&
!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags))
update_parent_pkey(priv);
ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n"); ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");
return; return;
} }
...@@ -961,21 +1000,32 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, ...@@ -961,21 +1000,32 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
} }
if (level == IPOIB_FLUSH_HEAVY) { if (level == IPOIB_FLUSH_HEAVY) {
if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) { /* child devices chase their origin pkey value, while non-child
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); * (parent) devices should always takes what present in pkey index 0
ipoib_ib_dev_down(dev, 0); */
ipoib_ib_dev_stop(dev, 0); if (test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
if (ipoib_pkey_dev_delay_open(dev)) if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) {
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
ipoib_ib_dev_down(dev, 0);
ipoib_ib_dev_stop(dev, 0);
if (ipoib_pkey_dev_delay_open(dev))
return;
}
/* restart QP only if P_Key index is changed */
if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
new_index == priv->pkey_index) {
ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
return; return;
}
priv->pkey_index = new_index;
} else {
result = update_parent_pkey(priv);
/* restart QP only if P_Key value changed */
if (result) {
ipoib_dbg(priv, "Not flushing - P_Key value not changed.\n");
return;
}
} }
/* restart QP only if P_Key index is changed */
if (test_and_set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags) &&
new_index == priv->pkey_index) {
ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
return;
}
priv->pkey_index = new_index;
} }
if (level == IPOIB_FLUSH_LIGHT) { if (level == IPOIB_FLUSH_LIGHT) {
......
...@@ -1461,7 +1461,7 @@ static ssize_t create_child(struct device *dev, ...@@ -1461,7 +1461,7 @@ static ssize_t create_child(struct device *dev,
if (sscanf(buf, "%i", &pkey) != 1) if (sscanf(buf, "%i", &pkey) != 1)
return -EINVAL; return -EINVAL;
if (pkey < 0 || pkey > 0xffff) if (pkey <= 0 || pkey > 0xffff || pkey == 0x8000)
return -EINVAL; return -EINVAL;
/* /*
......
...@@ -119,6 +119,15 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, ...@@ -119,6 +119,15 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
} else } else
child_pkey = nla_get_u16(data[IFLA_IPOIB_PKEY]); child_pkey = nla_get_u16(data[IFLA_IPOIB_PKEY]);
if (child_pkey == 0 || child_pkey == 0x8000)
return -EINVAL;
/*
* Set the full membership bit, so that we join the right
* broadcast group, etc.
*/
child_pkey |= 0x8000;
err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD); err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD);
if (!err && data) if (!err && data)
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include "mlx5_core.h" #include "mlx5_core.h"
enum { enum {
CMD_IF_REV = 3, CMD_IF_REV = 4,
}; };
enum { enum {
...@@ -282,6 +282,12 @@ const char *mlx5_command_str(int command) ...@@ -282,6 +282,12 @@ const char *mlx5_command_str(int command)
case MLX5_CMD_OP_TEARDOWN_HCA: case MLX5_CMD_OP_TEARDOWN_HCA:
return "TEARDOWN_HCA"; return "TEARDOWN_HCA";
case MLX5_CMD_OP_ENABLE_HCA:
return "MLX5_CMD_OP_ENABLE_HCA";
case MLX5_CMD_OP_DISABLE_HCA:
return "MLX5_CMD_OP_DISABLE_HCA";
case MLX5_CMD_OP_QUERY_PAGES: case MLX5_CMD_OP_QUERY_PAGES:
return "QUERY_PAGES"; return "QUERY_PAGES";
......
...@@ -249,6 +249,44 @@ static int set_hca_ctrl(struct mlx5_core_dev *dev) ...@@ -249,6 +249,44 @@ static int set_hca_ctrl(struct mlx5_core_dev *dev)
return err; return err;
} }
static int mlx5_core_enable_hca(struct mlx5_core_dev *dev)
{
int err;
struct mlx5_enable_hca_mbox_in in;
struct mlx5_enable_hca_mbox_out out;
memset(&in, 0, sizeof(in));
memset(&out, 0, sizeof(out));
in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ENABLE_HCA);
err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
if (err)
return err;
if (out.hdr.status)
return mlx5_cmd_status_to_err(&out.hdr);
return 0;
}
static int mlx5_core_disable_hca(struct mlx5_core_dev *dev)
{
int err;
struct mlx5_disable_hca_mbox_in in;
struct mlx5_disable_hca_mbox_out out;
memset(&in, 0, sizeof(in));
memset(&out, 0, sizeof(out));
in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DISABLE_HCA);
err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
if (err)
return err;
if (out.hdr.status)
return mlx5_cmd_status_to_err(&out.hdr);
return 0;
}
int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev) int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
{ {
struct mlx5_priv *priv = &dev->priv; struct mlx5_priv *priv = &dev->priv;
...@@ -304,28 +342,41 @@ int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev) ...@@ -304,28 +342,41 @@ int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
} }
mlx5_pagealloc_init(dev); mlx5_pagealloc_init(dev);
err = mlx5_core_enable_hca(dev);
if (err) {
dev_err(&pdev->dev, "enable hca failed\n");
goto err_pagealloc_cleanup;
}
err = mlx5_satisfy_startup_pages(dev, 1);
if (err) {
dev_err(&pdev->dev, "failed to allocate boot pages\n");
goto err_disable_hca;
}
err = set_hca_ctrl(dev); err = set_hca_ctrl(dev);
if (err) { if (err) {
dev_err(&pdev->dev, "set_hca_ctrl failed\n"); dev_err(&pdev->dev, "set_hca_ctrl failed\n");
goto err_pagealloc_cleanup; goto reclaim_boot_pages;
} }
err = handle_hca_cap(dev); err = handle_hca_cap(dev);
if (err) { if (err) {
dev_err(&pdev->dev, "handle_hca_cap failed\n"); dev_err(&pdev->dev, "handle_hca_cap failed\n");
goto err_pagealloc_cleanup; goto reclaim_boot_pages;
} }
err = mlx5_satisfy_startup_pages(dev); err = mlx5_satisfy_startup_pages(dev, 0);
if (err) { if (err) {
dev_err(&pdev->dev, "failed to allocate startup pages\n"); dev_err(&pdev->dev, "failed to allocate init pages\n");
goto err_pagealloc_cleanup; goto reclaim_boot_pages;
} }
err = mlx5_pagealloc_start(dev); err = mlx5_pagealloc_start(dev);
if (err) { if (err) {
dev_err(&pdev->dev, "mlx5_pagealloc_start failed\n"); dev_err(&pdev->dev, "mlx5_pagealloc_start failed\n");
goto err_reclaim_pages; goto reclaim_boot_pages;
} }
err = mlx5_cmd_init_hca(dev); err = mlx5_cmd_init_hca(dev);
...@@ -396,9 +447,12 @@ int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev) ...@@ -396,9 +447,12 @@ int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
err_pagealloc_stop: err_pagealloc_stop:
mlx5_pagealloc_stop(dev); mlx5_pagealloc_stop(dev);
err_reclaim_pages: reclaim_boot_pages:
mlx5_reclaim_startup_pages(dev); mlx5_reclaim_startup_pages(dev);
err_disable_hca:
mlx5_core_disable_hca(dev);
err_pagealloc_cleanup: err_pagealloc_cleanup:
mlx5_pagealloc_cleanup(dev); mlx5_pagealloc_cleanup(dev);
mlx5_cmd_cleanup(dev); mlx5_cmd_cleanup(dev);
...@@ -434,6 +488,7 @@ void mlx5_dev_cleanup(struct mlx5_core_dev *dev) ...@@ -434,6 +488,7 @@ void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
mlx5_cmd_teardown_hca(dev); mlx5_cmd_teardown_hca(dev);
mlx5_pagealloc_stop(dev); mlx5_pagealloc_stop(dev);
mlx5_reclaim_startup_pages(dev); mlx5_reclaim_startup_pages(dev);
mlx5_core_disable_hca(dev);
mlx5_pagealloc_cleanup(dev); mlx5_pagealloc_cleanup(dev);
mlx5_cmd_cleanup(dev); mlx5_cmd_cleanup(dev);
iounmap(dev->iseg); iounmap(dev->iseg);
......
...@@ -64,7 +64,7 @@ struct mlx5_query_pages_inbox { ...@@ -64,7 +64,7 @@ struct mlx5_query_pages_inbox {
struct mlx5_query_pages_outbox { struct mlx5_query_pages_outbox {
struct mlx5_outbox_hdr hdr; struct mlx5_outbox_hdr hdr;
u8 reserved[2]; __be16 num_boot_pages;
__be16 func_id; __be16 func_id;
__be16 init_pages; __be16 init_pages;
__be16 num_pages; __be16 num_pages;
...@@ -146,7 +146,7 @@ static struct page *remove_page(struct mlx5_core_dev *dev, u64 addr) ...@@ -146,7 +146,7 @@ static struct page *remove_page(struct mlx5_core_dev *dev, u64 addr)
} }
static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id, static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
s16 *pages, s16 *init_pages) s16 *pages, s16 *init_pages, u16 *boot_pages)
{ {
struct mlx5_query_pages_inbox in; struct mlx5_query_pages_inbox in;
struct mlx5_query_pages_outbox out; struct mlx5_query_pages_outbox out;
...@@ -164,8 +164,13 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id, ...@@ -164,8 +164,13 @@ static int mlx5_cmd_query_pages(struct mlx5_core_dev *dev, u16 *func_id,
if (pages) if (pages)
*pages = be16_to_cpu(out.num_pages); *pages = be16_to_cpu(out.num_pages);
if (init_pages) if (init_pages)
*init_pages = be16_to_cpu(out.init_pages); *init_pages = be16_to_cpu(out.init_pages);
if (boot_pages)
*boot_pages = be16_to_cpu(out.num_boot_pages);
*func_id = be16_to_cpu(out.func_id); *func_id = be16_to_cpu(out.func_id);
return err; return err;
...@@ -357,19 +362,22 @@ void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, ...@@ -357,19 +362,22 @@ void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id,
queue_work(dev->priv.pg_wq, &req->work); queue_work(dev->priv.pg_wq, &req->work);
} }
int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev) int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot)
{ {
u16 uninitialized_var(boot_pages);
s16 uninitialized_var(init_pages); s16 uninitialized_var(init_pages);
u16 uninitialized_var(func_id); u16 uninitialized_var(func_id);
int err; int err;
err = mlx5_cmd_query_pages(dev, &func_id, NULL, &init_pages); err = mlx5_cmd_query_pages(dev, &func_id, NULL, &init_pages,
&boot_pages);
if (err) if (err)
return err; return err;
mlx5_core_dbg(dev, "requested %d init pages for func_id 0x%x\n", init_pages, func_id);
return give_pages(dev, func_id, init_pages, 0); mlx5_core_dbg(dev, "requested %d init pages and %d boot pages for func_id 0x%x\n",
init_pages, boot_pages, func_id);
return give_pages(dev, func_id, boot ? boot_pages : init_pages, 0);
} }
static int optimal_reclaimed_pages(void) static int optimal_reclaimed_pages(void)
......
...@@ -690,6 +690,26 @@ struct mlx5_query_cq_mbox_out { ...@@ -690,6 +690,26 @@ struct mlx5_query_cq_mbox_out {
__be64 pas[0]; __be64 pas[0];
}; };
struct mlx5_enable_hca_mbox_in {
struct mlx5_inbox_hdr hdr;
u8 rsvd[8];
};
struct mlx5_enable_hca_mbox_out {
struct mlx5_outbox_hdr hdr;
u8 rsvd[8];
};
struct mlx5_disable_hca_mbox_in {
struct mlx5_inbox_hdr hdr;
u8 rsvd[8];
};
struct mlx5_disable_hca_mbox_out {
struct mlx5_outbox_hdr hdr;
u8 rsvd[8];
};
struct mlx5_eq_context { struct mlx5_eq_context {
u8 status; u8 status;
u8 ec_oi; u8 ec_oi;
......
...@@ -101,6 +101,8 @@ enum { ...@@ -101,6 +101,8 @@ enum {
MLX5_CMD_OP_QUERY_ADAPTER = 0x101, MLX5_CMD_OP_QUERY_ADAPTER = 0x101,
MLX5_CMD_OP_INIT_HCA = 0x102, MLX5_CMD_OP_INIT_HCA = 0x102,
MLX5_CMD_OP_TEARDOWN_HCA = 0x103, MLX5_CMD_OP_TEARDOWN_HCA = 0x103,
MLX5_CMD_OP_ENABLE_HCA = 0x104,
MLX5_CMD_OP_DISABLE_HCA = 0x105,
MLX5_CMD_OP_QUERY_PAGES = 0x107, MLX5_CMD_OP_QUERY_PAGES = 0x107,
MLX5_CMD_OP_MANAGE_PAGES = 0x108, MLX5_CMD_OP_MANAGE_PAGES = 0x108,
MLX5_CMD_OP_SET_HCA_CAP = 0x109, MLX5_CMD_OP_SET_HCA_CAP = 0x109,
...@@ -690,7 +692,7 @@ int mlx5_pagealloc_start(struct mlx5_core_dev *dev); ...@@ -690,7 +692,7 @@ int mlx5_pagealloc_start(struct mlx5_core_dev *dev);
void mlx5_pagealloc_stop(struct mlx5_core_dev *dev); void mlx5_pagealloc_stop(struct mlx5_core_dev *dev);
void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id, void mlx5_core_req_pages_handler(struct mlx5_core_dev *dev, u16 func_id,
s16 npages); s16 npages);
int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev); int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot);
int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev); int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev);
void mlx5_register_debugfs(void); void mlx5_register_debugfs(void);
void mlx5_unregister_debugfs(void); void mlx5_unregister_debugfs(void);
......
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