From 931bc0d91639f8fbf336332aa443705004ecf61d Mon Sep 17 00:00:00 2001 From: Yuval Shaia Date: Wed, 6 Sep 2017 13:15:50 +0300 Subject: IB: Move PCI dependency from root KConfig to HW's KConfigs No reason to have dependency on PCI for the entire infiniband stack so move it to KConfig of only the drivers that actually using PCI. Signed-off-by: Yuval Shaia Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rdmavt/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/infiniband/sw') diff --git a/drivers/infiniband/sw/rdmavt/Kconfig b/drivers/infiniband/sw/rdmavt/Kconfig index fdd001ce13d8..2b5513da7e83 100644 --- a/drivers/infiniband/sw/rdmavt/Kconfig +++ b/drivers/infiniband/sw/rdmavt/Kconfig @@ -1,6 +1,7 @@ config INFINIBAND_RDMAVT tristate "RDMA verbs transport library" depends on 64BIT + depends on PCI select DMA_VIRT_OPS ---help--- This is a common software verbs provider for RDMA networks. -- cgit v1.2.3 From 4831ca9e4a8e48cb27e0a792f73250390827a228 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 8 Sep 2017 15:37:45 +0100 Subject: IB/rxe: check for allocation failure on elem The allocation for elem may fail (especially because we're using GFP_ATOMIC) so best to check for a null return. This fixes a potential null pointer dereference when assigning elem->pool. Detected by CoverityScan CID#1357507 ("Dereference null return value") Fixes: 8700e3e7c485 ("Soft RoCE driver") Signed-off-by: Colin Ian King Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rxe/rxe_pool.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/infiniband/sw') diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c index c1b5f38f31a5..3b4916680018 100644 --- a/drivers/infiniband/sw/rxe/rxe_pool.c +++ b/drivers/infiniband/sw/rxe/rxe_pool.c @@ -404,6 +404,8 @@ void *rxe_alloc(struct rxe_pool *pool) elem = kmem_cache_zalloc(pool_cache(pool), (pool->flags & RXE_POOL_ATOMIC) ? GFP_ATOMIC : GFP_KERNEL); + if (!elem) + return NULL; elem->pool = pool; kref_init(&elem->ref_cnt); -- cgit v1.2.3 From 6b9f8970cd30929cb6b372fa44fa66da9e59c650 Mon Sep 17 00:00:00 2001 From: Doug Ledford Date: Mon, 9 Oct 2017 09:11:32 -0400 Subject: IB/rxe: put the pool on allocation failure If the allocation of elem fails, it is not sufficient to simply check for NULL and return. We need to also put our reference on the pool or else we will leave the pool with a permanent ref count and we will never be able to free it. Fixes: 4831ca9e4a8e ("IB/rxe: check for allocation failure on elem") Suggested-by: Leon Romanovsky Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rxe/rxe_pool.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/infiniband/sw') diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c index 3b4916680018..b4a8acc7bb7d 100644 --- a/drivers/infiniband/sw/rxe/rxe_pool.c +++ b/drivers/infiniband/sw/rxe/rxe_pool.c @@ -394,23 +394,25 @@ void *rxe_alloc(struct rxe_pool *pool) kref_get(&pool->rxe->ref_cnt); - if (atomic_inc_return(&pool->num_elem) > pool->max_elem) { - atomic_dec(&pool->num_elem); - rxe_dev_put(pool->rxe); - rxe_pool_put(pool); - return NULL; - } + if (atomic_inc_return(&pool->num_elem) > pool->max_elem) + goto out_put_pool; elem = kmem_cache_zalloc(pool_cache(pool), (pool->flags & RXE_POOL_ATOMIC) ? GFP_ATOMIC : GFP_KERNEL); if (!elem) - return NULL; + goto out_put_pool; elem->pool = pool; kref_init(&elem->ref_cnt); return elem; + +out_put_pool: + atomic_dec(&pool->num_elem); + rxe_dev_put(pool->rxe); + rxe_pool_put(pool); + return NULL; } void rxe_elem_release(struct kref *kref) -- cgit v1.2.3 From 2caaa2335b3d3b3a750308baa8677454e5cf3ada Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 11 Oct 2017 10:49:23 -0700 Subject: RDMA/rdmavt: Suppress gcc 7 fall-through complaints Avoid that gcc 7 reports the following warning when building with W=1: warning: this statement may fall through [-Wimplicit-fallthrough=] Signed-off-by: Bart Van Assche Reviewed-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rdmavt/qp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/infiniband/sw') diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 22df09ae809e..efcff7056496 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -807,6 +807,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, if (init_attr->port_num == 0 || init_attr->port_num > ibpd->device->phys_port_cnt) return ERR_PTR(-EINVAL); + /* fall through */ case IB_QPT_UC: case IB_QPT_RC: case IB_QPT_UD: -- cgit v1.2.3 From ea6ee93b4033089b6b22b693da3354359555dc69 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 11 Oct 2017 10:49:24 -0700 Subject: RDMA/rxe: Suppress gcc 7 fall-through complaints Avoid that gcc 7 reports the following warning when building with W=1: warning: this statement may fall through [-Wimplicit-fallthrough=] Signed-off-by: Bart Van Assche Reviewed-by: Leon Romanovsky Cc: Moni Shoua Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rxe/rxe_comp.c | 4 ++-- drivers/infiniband/sw/rxe/rxe_task.c | 2 +- drivers/infiniband/sw/rxe/rxe_verbs.c | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/infiniband/sw') diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c index 9eb12c2e3c74..ff64875e3d15 100644 --- a/drivers/infiniband/sw/rxe/rxe_comp.c +++ b/drivers/infiniband/sw/rxe/rxe_comp.c @@ -270,8 +270,8 @@ static inline enum comp_state check_ack(struct rxe_qp *qp, if ((syn & AETH_TYPE_MASK) != AETH_ACK) return COMPST_ERROR; - /* Fall through (IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE - * doesn't have an AETH) + /* fall through */ + /* (IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE doesn't have an AETH) */ case IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE: if (wqe->wr.opcode != IB_WR_RDMA_READ && diff --git a/drivers/infiniband/sw/rxe/rxe_task.c b/drivers/infiniband/sw/rxe/rxe_task.c index ea3810b29273..08f05ac5f5d5 100644 --- a/drivers/infiniband/sw/rxe/rxe_task.c +++ b/drivers/infiniband/sw/rxe/rxe_task.c @@ -71,7 +71,7 @@ void rxe_do_task(unsigned long data) case TASK_STATE_BUSY: task->state = TASK_STATE_ARMED; - /* fall through to */ + /* fall through */ case TASK_STATE_ARMED: spin_unlock_irqrestore(&task->state_lock, flags); return; diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index 0b362f49a10a..ff77f4f66970 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -644,6 +644,7 @@ static void init_send_wr(struct rxe_qp *qp, struct rxe_send_wr *wr, switch (wr->opcode) { case IB_WR_RDMA_WRITE_WITH_IMM: wr->ex.imm_data = ibwr->ex.imm_data; + /* fall through */ case IB_WR_RDMA_READ: case IB_WR_RDMA_WRITE: wr->wr.rdma.remote_addr = rdma_wr(ibwr)->remote_addr; -- cgit v1.2.3 From f9586abfa333143d67e3362dfb2a19ae45d82441 Mon Sep 17 00:00:00 2001 From: Alex Estrin Date: Mon, 9 Oct 2017 12:38:33 -0700 Subject: IB/rdmavt: Don't wait for resources in QP reset Per the IBTA spec, QP destroy shall fail if the QP is attached to multicast groups, although the spec is silent on modify_qp to reset state. It implies that ULP must deregister QP from all mcast groups for destroy to succeed. The faulty patch "IB/ipoib: Update broadcast object if PKey value was changed in index 0" exposed two issues in rdmavt: 1. Rvt QP reset waits for qp references to go to zero. This will hang if QP is attached to multicast groups. 2. The mcast group detach will fail for a QP in reset state therefore preventing ULP from correcting the issue. This patch moves the reference count wait to the the destroy QP path and allows a QP mcast detach to work in the reset state. Reviewed-by: Mike Marciniszyn Signed-off-by: Alex Estrin Signed-off-by: Dennis Dalessandro Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rdmavt/mcast.c | 2 +- drivers/infiniband/sw/rdmavt/qp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/infiniband/sw') diff --git a/drivers/infiniband/sw/rdmavt/mcast.c b/drivers/infiniband/sw/rdmavt/mcast.c index 1f12b69a0d07..b3a38c5e4cad 100644 --- a/drivers/infiniband/sw/rdmavt/mcast.c +++ b/drivers/infiniband/sw/rdmavt/mcast.c @@ -351,7 +351,7 @@ int rvt_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) int last = 0; int ret = 0; - if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET) + if (ibqp->qp_num <= 1) return -EINVAL; spin_lock_irq(&ibp->lock); diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 22df09ae809e..367c78618019 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -717,7 +717,6 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp, /* take qp out the hash and wait for it to be unused */ rvt_remove_qp(rdi, qp); - wait_event(qp->wait, !atomic_read(&qp->refcount)); /* grab the lock b/c it was locked at call time */ spin_lock_irq(&qp->r_lock); @@ -1443,6 +1442,7 @@ int rvt_destroy_qp(struct ib_qp *ibqp) spin_unlock(&qp->s_hlock); spin_unlock_irq(&qp->r_lock); + wait_event(qp->wait, !atomic_read(&qp->refcount)); /* qpn is now available for use again */ rvt_free_qpn(&rdi->qp_dev->qpn_table, qp->ibqp.qp_num); -- cgit v1.2.3 From a2930e5c44951902b63f61aa3d65f4312744de39 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 16 Oct 2017 15:51:13 -0700 Subject: IB/rdmavt: Convert timers to use timer_setup() In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly. setup_timer() was already being called before the open-coded init_timer() and .data assignment. These are removed as well. Cc: Dennis Dalessandro Cc: Doug Ledford Cc: Sean Hefty Cc: Hal Rosenstock Cc: linux-rdma@vger.kernel.org Signed-off-by: Kees Cook Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rdmavt/qp.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/infiniband/sw') diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 22df09ae809e..74f85194db31 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -57,7 +57,7 @@ #include "vt.h" #include "trace.h" -static void rvt_rc_timeout(unsigned long arg); +static void rvt_rc_timeout(struct timer_list *t); /* * Convert the AETH RNR timeout code into the number of microseconds. @@ -845,7 +845,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, goto bail_qp; } /* initialize timers needed for rc qp */ - setup_timer(&qp->s_timer, rvt_rc_timeout, (unsigned long)qp); + timer_setup(&qp->s_timer, rvt_rc_timeout, 0); hrtimer_init(&qp->s_rnr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); qp->s_rnr_timer.function = rvt_rc_rnr_retry; @@ -894,8 +894,6 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, atomic_set(&qp->refcount, 0); atomic_set(&qp->local_ops_pending, 0); init_waitqueue_head(&qp->wait); - init_timer(&qp->s_timer); - qp->s_timer.data = (unsigned long)qp; INIT_LIST_HEAD(&qp->rspwait); qp->state = IB_QPS_RESET; qp->s_wq = swq; @@ -2132,9 +2130,9 @@ EXPORT_SYMBOL(rvt_del_timers_sync); /** * This is called from s_timer for missing responses. */ -static void rvt_rc_timeout(unsigned long arg) +static void rvt_rc_timeout(struct timer_list *t) { - struct rvt_qp *qp = (struct rvt_qp *)arg; + struct rvt_qp *qp = from_timer(qp, t, s_timer); struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device); unsigned long flags; -- cgit v1.2.3 From 3bfbea747353c2b40b48784b70e782ca5352f18c Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 24 Oct 2017 03:28:27 -0700 Subject: IB/rxe: Convert timers to use timer_setup() In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly. Cc: Moni Shoua Cc: Doug Ledford Cc: Sean Hefty Cc: Hal Rosenstock Cc: linux-rdma@vger.kernel.org Signed-off-by: Kees Cook Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rxe/rxe_comp.c | 4 ++-- drivers/infiniband/sw/rxe/rxe_loc.h | 4 ++-- drivers/infiniband/sw/rxe/rxe_qp.c | 4 ++-- drivers/infiniband/sw/rxe/rxe_req.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/infiniband/sw') diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c index ff64875e3d15..6cdc40ed8a9f 100644 --- a/drivers/infiniband/sw/rxe/rxe_comp.c +++ b/drivers/infiniband/sw/rxe/rxe_comp.c @@ -136,9 +136,9 @@ static enum ib_wc_opcode wr_to_wc_opcode(enum ib_wr_opcode opcode) } } -void retransmit_timer(unsigned long data) +void retransmit_timer(struct timer_list *t) { - struct rxe_qp *qp = (struct rxe_qp *)data; + struct rxe_qp *qp = from_timer(qp, t, retrans_timer); if (qp->valid) { qp->comp.timeout = 1; diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h index 77b3ed0df936..d7472a442a2c 100644 --- a/drivers/infiniband/sw/rxe/rxe_loc.h +++ b/drivers/infiniband/sw/rxe/rxe_loc.h @@ -218,8 +218,8 @@ static inline void rxe_advance_resp_resource(struct rxe_qp *qp) qp->resp.res_head = 0; } -void retransmit_timer(unsigned long data); -void rnr_nak_timer(unsigned long data); +void retransmit_timer(struct timer_list *t); +void rnr_nak_timer(struct timer_list *t); /* rxe_srq.c */ #define IB_SRQ_INIT_MASK (~IB_SRQ_LIMIT) diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c index 00bda9380a2e..4469592b839d 100644 --- a/drivers/infiniband/sw/rxe/rxe_qp.c +++ b/drivers/infiniband/sw/rxe/rxe_qp.c @@ -275,8 +275,8 @@ static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp, qp->qp_timeout_jiffies = 0; /* Can't be set for UD/UC in modify_qp */ if (init->qp_type == IB_QPT_RC) { - setup_timer(&qp->rnr_nak_timer, rnr_nak_timer, (unsigned long)qp); - setup_timer(&qp->retrans_timer, retransmit_timer, (unsigned long)qp); + timer_setup(&qp->rnr_nak_timer, rnr_nak_timer, 0); + timer_setup(&qp->retrans_timer, retransmit_timer, 0); } return 0; } diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c index d84222f9d5d2..26a7f923045b 100644 --- a/drivers/infiniband/sw/rxe/rxe_req.c +++ b/drivers/infiniband/sw/rxe/rxe_req.c @@ -118,9 +118,9 @@ static void req_retry(struct rxe_qp *qp) } } -void rnr_nak_timer(unsigned long data) +void rnr_nak_timer(struct timer_list *t) { - struct rxe_qp *qp = (struct rxe_qp *)data; + struct rxe_qp *qp = from_timer(qp, t, rnr_nak_timer); pr_debug("qp#%d rnr nak timer fired\n", qp_num(qp)); rxe_run_task(&qp->req.task, 1); -- cgit v1.2.3 From 3192c53e5affe767472176197b83c9bc0b1e459d Mon Sep 17 00:00:00 2001 From: Thomas Bogendoerfer Date: Tue, 31 Oct 2017 11:16:46 +0100 Subject: IB/rxe: don't crash, if allocation of crc algorithm failed Following crash happens, if crc algorithm couldn't be allocated: [ 1087.989072] rdma_rxe: loaded [ 1097.855397] PCLMULQDQ-NI instructions are not detected. [ 1097.901220] rdma_rxe: failed to allocate crc algorithmi err:-2 [ 1097.901248] BUG: unable to handle kernel [ 1097.901249] NULL pointer dereference [ 1097.901250] at 0000000000000046 [...] Reason is that rxe->tfm is assigned the error return, which will then be used for crypto_free_shash() in rxe_cleanup. Fix by using a temporary variable and assigning it rxe->tfm after allocation succeeded. Fixes: cee2688e3cd6 ("IB/rxe: Offload CRC calculation when possible") Signed-off-by: Thomas Bogendoerfer Reviewed-by: Leon Romanovsky Acked-by: Moni Shoua Signed-off-by: Doug Ledford --- drivers/infiniband/sw/rxe/rxe_verbs.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/infiniband/sw') diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index ff77f4f66970..d03002b9d84d 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -1192,6 +1192,7 @@ int rxe_register_device(struct rxe_dev *rxe) int err; int i; struct ib_device *dev = &rxe->ib_dev; + struct crypto_shash *tfm; strlcpy(dev->name, "rxe%d", IB_DEVICE_NAME_MAX); strlcpy(dev->node_desc, "rxe", sizeof(dev->node_desc)); @@ -1289,12 +1290,13 @@ int rxe_register_device(struct rxe_dev *rxe) dev->get_hw_stats = rxe_ib_get_hw_stats; dev->alloc_hw_stats = rxe_ib_alloc_hw_stats; - rxe->tfm = crypto_alloc_shash("crc32", 0, 0); - if (IS_ERR(rxe->tfm)) { + tfm = crypto_alloc_shash("crc32", 0, 0); + if (IS_ERR(tfm)) { pr_err("failed to allocate crc algorithm err:%ld\n", - PTR_ERR(rxe->tfm)); - return PTR_ERR(rxe->tfm); + PTR_ERR(tfm)); + return PTR_ERR(tfm); } + rxe->tfm = tfm; err = ib_register_device(dev, NULL); if (err) { -- cgit v1.2.3