From: Greg Kroah-Hartman Date: Fri, 14 Apr 2017 09:25:33 +0000 (+0200) Subject: 3.18 patches X-Git-Tag: v4.10.11~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=890d5b486082bf153acce25d148adbee5db59045;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18 patches --- diff --git a/queue-3.18/net-mlx4_core-fix-racy-cq-completion-queue-free.patch b/queue-3.18/net-mlx4_core-fix-racy-cq-completion-queue-free.patch new file mode 100644 index 00000000000..3ee1a16e4fe --- /dev/null +++ b/queue-3.18/net-mlx4_core-fix-racy-cq-completion-queue-free.patch @@ -0,0 +1,151 @@ +From 291c566a28910614ce42d0ffe82196eddd6346f4 Mon Sep 17 00:00:00 2001 +From: Jack Morgenstein +Date: Mon, 16 Jan 2017 18:31:37 +0200 +Subject: net/mlx4_core: Fix racy CQ (Completion Queue) free + +From: Jack Morgenstein + +commit 291c566a28910614ce42d0ffe82196eddd6346f4 upstream. + +In function mlx4_cq_completion() and mlx4_cq_event(), the +radix_tree_lookup requires a rcu_read_lock. +This is mandatory: if another core frees the CQ, it could +run the radix_tree_node_rcu_free() call_rcu() callback while +its being used by the radix tree lookup function. + +Additionally, in function mlx4_cq_event(), since we are adding +the rcu lock around the radix-tree lookup, we no longer need to take +the spinlock. Also, the synchronize_irq() call for the async event +eliminates the need for incrementing the cq reference count in +mlx4_cq_event(). + +Other changes: +1. In function mlx4_cq_free(), replace spin_lock_irq with spin_lock: + we no longer take this spinlock in the interrupt context. + The spinlock here, therefore, simply protects against different + threads simultaneously invoking mlx4_cq_free() for different cq's. + +2. In function mlx4_cq_free(), we move the radix tree delete to before + the synchronize_irq() calls. This guarantees that we will not + access this cq during any subsequent interrupts, and therefore can + safely free the CQ after the synchronize_irq calls. The rcu_read_lock + in the interrupt handlers only needs to protect against corrupting the + radix tree; the interrupt handlers may access the cq outside the + rcu_read_lock due to the synchronize_irq calls which protect against + premature freeing of the cq. + +3. In function mlx4_cq_event(), we change the mlx_warn message to mlx4_dbg. + +4. We leave the cq reference count mechanism in place, because it is + still needed for the cq completion tasklet mechanism. + +Fixes: 6d90aa5cf17b ("net/mlx4_core: Make sure there are no pending async events when freeing CQ") +Fixes: 225c7b1feef1 ("IB/mlx4: Add a driver Mellanox ConnectX InfiniBand adapters") +Signed-off-by: Jack Morgenstein +Signed-off-by: Matan Barak +Signed-off-by: Tariq Toukan +Signed-off-by: David S. Miller +Signed-off-by: Sumit Semwal +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/mellanox/mlx4/cq.c | 38 ++++++++++++++++---------------- + 1 file changed, 20 insertions(+), 18 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/cq.c ++++ b/drivers/net/ethernet/mellanox/mlx4/cq.c +@@ -56,13 +56,19 @@ void mlx4_cq_completion(struct mlx4_dev + { + struct mlx4_cq *cq; + ++ rcu_read_lock(); + cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree, + cqn & (dev->caps.num_cqs - 1)); ++ rcu_read_unlock(); ++ + if (!cq) { + mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn); + return; + } + ++ /* Acessing the CQ outside of rcu_read_lock is safe, because ++ * the CQ is freed only after interrupt handling is completed. ++ */ + ++cq->arm_sn; + + cq->comp(cq); +@@ -73,23 +79,19 @@ void mlx4_cq_event(struct mlx4_dev *dev, + struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table; + struct mlx4_cq *cq; + +- spin_lock(&cq_table->lock); +- ++ rcu_read_lock(); + cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1)); +- if (cq) +- atomic_inc(&cq->refcount); +- +- spin_unlock(&cq_table->lock); ++ rcu_read_unlock(); + + if (!cq) { +- mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn); ++ mlx4_dbg(dev, "Async event for bogus CQ %08x\n", cqn); + return; + } + ++ /* Acessing the CQ outside of rcu_read_lock is safe, because ++ * the CQ is freed only after interrupt handling is completed. ++ */ + cq->event(cq, event_type); +- +- if (atomic_dec_and_test(&cq->refcount)) +- complete(&cq->free); + } + + static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, +@@ -256,9 +258,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, + if (err) + return err; + +- spin_lock_irq(&cq_table->lock); ++ spin_lock(&cq_table->lock); + err = radix_tree_insert(&cq_table->tree, cq->cqn, cq); +- spin_unlock_irq(&cq_table->lock); ++ spin_unlock(&cq_table->lock); + if (err) + goto err_icm; + +@@ -297,9 +299,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, + return 0; + + err_radix: +- spin_lock_irq(&cq_table->lock); ++ spin_lock(&cq_table->lock); + radix_tree_delete(&cq_table->tree, cq->cqn); +- spin_unlock_irq(&cq_table->lock); ++ spin_unlock(&cq_table->lock); + + err_icm: + mlx4_cq_free_icm(dev, cq->cqn); +@@ -314,16 +316,16 @@ void mlx4_cq_free(struct mlx4_dev *dev, + struct mlx4_cq_table *cq_table = &priv->cq_table; + int err; + ++ spin_lock(&cq_table->lock); ++ radix_tree_delete(&cq_table->tree, cq->cqn); ++ spin_unlock(&cq_table->lock); ++ + err = mlx4_HW2SW_CQ(dev, NULL, cq->cqn); + if (err) + mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn); + + synchronize_irq(priv->eq_table.eq[cq->vector].irq); + +- spin_lock_irq(&cq_table->lock); +- radix_tree_delete(&cq_table->tree, cq->cqn); +- spin_unlock_irq(&cq_table->lock); +- + if (atomic_dec_and_test(&cq->refcount)) + complete(&cq->free); + wait_for_completion(&cq->free); diff --git a/queue-3.18/net-mlx4_core-fix-when-to-save-some-qp-context-flags-for-dynamic-vst-to-vgt-transitions.patch b/queue-3.18/net-mlx4_core-fix-when-to-save-some-qp-context-flags-for-dynamic-vst-to-vgt-transitions.patch new file mode 100644 index 00000000000..a4755519690 --- /dev/null +++ b/queue-3.18/net-mlx4_core-fix-when-to-save-some-qp-context-flags-for-dynamic-vst-to-vgt-transitions.patch @@ -0,0 +1,58 @@ +From 7c3945bc2073554bb2ecf983e073dee686679c53 Mon Sep 17 00:00:00 2001 +From: Jack Morgenstein +Date: Mon, 16 Jan 2017 18:31:38 +0200 +Subject: net/mlx4_core: Fix when to save some qp context flags for dynamic VST to VGT transitions + +From: Jack Morgenstein + +commit 7c3945bc2073554bb2ecf983e073dee686679c53 upstream. + +Save the qp context flags byte containing the flag disabling vlan stripping +in the RESET to INIT qp transition, rather than in the INIT to RTR +transition. Per the firmware spec, the flags in this byte are active +in the RESET to INIT transition. + +As a result of saving the flags in the incorrect qp transition, when +switching dynamically from VGT to VST and back to VGT, the vlan +remained stripped (as is required for VST) and did not return to +not-stripped (as is required for VGT). + +Fixes: f0f829bf42cd ("net/mlx4_core: Add immediate activate for VGT->VST->VGT") +Signed-off-by: Jack Morgenstein +Signed-off-by: Tariq Toukan +Signed-off-by: David S. Miller +Signed-off-by: Sumit Semwal +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c ++++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +@@ -2769,6 +2769,9 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4 + put_res(dev, slave, srqn, RES_SRQ); + qp->srq = srq; + } ++ ++ /* Save param3 for dynamic changes from VST back to VGT */ ++ qp->param3 = qpc->param3; + put_res(dev, slave, rcqn, RES_CQ); + put_res(dev, slave, mtt_base, RES_MTT); + res_end_move(dev, slave, RES_QP, qpn); +@@ -3531,7 +3534,6 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4 + int qpn = vhcr->in_modifier & 0x7fffff; + struct res_qp *qp; + u8 orig_sched_queue; +- __be32 orig_param3 = qpc->param3; + u8 orig_vlan_control = qpc->pri_path.vlan_control; + u8 orig_fvl_rx = qpc->pri_path.fvl_rx; + u8 orig_pri_path_fl = qpc->pri_path.fl; +@@ -3572,7 +3574,6 @@ out: + */ + if (!err) { + qp->sched_queue = orig_sched_queue; +- qp->param3 = orig_param3; + qp->vlan_control = orig_vlan_control; + qp->fvl_rx = orig_fvl_rx; + qp->pri_path_fl = orig_pri_path_fl; diff --git a/queue-3.18/net-mlx4_en-fix-bad-wqe-issue.patch b/queue-3.18/net-mlx4_en-fix-bad-wqe-issue.patch new file mode 100644 index 00000000000..a7b96e0d33e --- /dev/null +++ b/queue-3.18/net-mlx4_en-fix-bad-wqe-issue.patch @@ -0,0 +1,42 @@ +From 6496bbf0ec481966ef9ffe5b6660d8d1b55c60cc Mon Sep 17 00:00:00 2001 +From: Eugenia Emantayev +Date: Thu, 29 Dec 2016 18:37:10 +0200 +Subject: net/mlx4_en: Fix bad WQE issue + +From: Eugenia Emantayev + +commit 6496bbf0ec481966ef9ffe5b6660d8d1b55c60cc upstream. + +Single send WQE in RX buffer should be stamped with software +ownership in order to prevent the flow of QP in error in FW +once UPDATE_QP is called. + +Fixes: 9f519f68cfff ('mlx4_en: Not using Shared Receive Queues') +Signed-off-by: Eugenia Emantayev +Signed-off-by: Tariq Toukan +Signed-off-by: David S. Miller +Signed-off-by: Sumit Semwal +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/mellanox/mlx4/en_rx.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c +@@ -438,8 +438,14 @@ int mlx4_en_activate_rx_rings(struct mlx + ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn; + + ring->stride = stride; +- if (ring->stride <= TXBB_SIZE) ++ if (ring->stride <= TXBB_SIZE) { ++ /* Stamp first unused send wqe */ ++ __be32 *ptr = (__be32 *)ring->buf; ++ __be32 stamp = cpu_to_be32(1 << STAMP_SHIFT); ++ *ptr = stamp; ++ /* Move pointer to start of rx section */ + ring->buf += TXBB_SIZE; ++ } + + ring->log_stride = ffs(ring->stride) - 1; + ring->buf_size = ring->size * ring->stride; diff --git a/queue-3.18/series b/queue-3.18/series index 14266e20100..688911e4c83 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -108,3 +108,7 @@ l2tp-avoid-use-after-free-caused-by-l2tp_ip_backlog_recv.patch net-don-t-call-strlen-on-the-user-buffer-in-packet_bind_spkt.patch dccp-unlock-sock-before-calling-sk_free.patch net-packet-fix-overflow-in-check-for-priv-area-size.patch +usb-hub-wait-for-connection-to-be-reestablished-after-port-reset.patch +net-mlx4_en-fix-bad-wqe-issue.patch +net-mlx4_core-fix-racy-cq-completion-queue-free.patch +net-mlx4_core-fix-when-to-save-some-qp-context-flags-for-dynamic-vst-to-vgt-transitions.patch diff --git a/queue-3.18/usb-hub-wait-for-connection-to-be-reestablished-after-port-reset.patch b/queue-3.18/usb-hub-wait-for-connection-to-be-reestablished-after-port-reset.patch new file mode 100644 index 00000000000..2e4d4fc6a6a --- /dev/null +++ b/queue-3.18/usb-hub-wait-for-connection-to-be-reestablished-after-port-reset.patch @@ -0,0 +1,65 @@ +From 22547c4cc4fe20698a6a85a55b8788859134b8e4 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Thu, 1 Dec 2016 13:49:59 -0800 +Subject: usb: hub: Wait for connection to be reestablished after port reset + +From: Guenter Roeck + +commit 22547c4cc4fe20698a6a85a55b8788859134b8e4 upstream. + +On a system with a defective USB device connected to an USB hub, +an endless sequence of port connect events was observed. The sequence +of events as observed is as follows: + +- Port reports connected event (port status=USB_PORT_STAT_CONNECTION). +- Event handler debounces port and resets it by calling hub_port_reset(). +- hub_port_reset() calls hub_port_wait_reset() to wait for the reset + to complete. +- The reset completes, but USB_PORT_STAT_CONNECTION is not immediately + set in the port status register. +- hub_port_wait_reset() returns -ENOTCONN. +- Port initialization sequence is aborted. +- A few milliseconds later, the port again reports a connected event, + and the sequence repeats. + +This continues either forever or, randomly, stops if the connection +is already re-established when the port status is read. It results in +a high rate of udev events. This in turn destabilizes userspace since +the above sequence holds the device mutex pretty much continuously +and prevents userspace from actually reading the device status. + +To prevent the problem from happening, let's wait for the connection +to be re-established after a port reset. If the device was actually +disconnected, the code will still return an error, but it will do so +only after the long reset timeout. + +Cc: Douglas Anderson +Signed-off-by: Guenter Roeck +Acked-by: Alan Stern +Signed-off-by: Sumit Semwal +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2616,8 +2616,15 @@ static int hub_port_wait_reset(struct us + if (ret < 0) + return ret; + +- /* The port state is unknown until the reset completes. */ +- if (!(portstatus & USB_PORT_STAT_RESET)) ++ /* ++ * The port state is unknown until the reset completes. ++ * ++ * On top of that, some chips may require additional time ++ * to re-establish a connection after the reset is complete, ++ * so also wait for the connection to be re-established. ++ */ ++ if (!(portstatus & USB_PORT_STAT_RESET) && ++ (portstatus & USB_PORT_STAT_CONNECTION)) + break; + + /* switch to the long delay after two short delay failures */