From: Greg Kroah-Hartman Date: Wed, 5 Oct 2016 15:39:41 +0000 (+0200) Subject: 4.7-stable patches X-Git-Tag: v4.8.1~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=937cd4b4175a730444537c9f4f346c739a16fc8d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.7-stable patches added patches: aio-mark-aio-pseudo-fs-noexec.patch ath10k-fix-get-rx_status-from-htt-context.patch batman-adv-remove-unused-callback-from-batadv_algo_ops-struct.patch ceph-do-not-modify-fi-frag-in-need_reset_readdir.patch dm-log-writes-fix-bug-with-too-large-bios.patch ib-core-fix-use-after-free-in-send_leave-function.patch ib-ipoib-don-t-allow-mc-joins-during-light-mc-flush.patch ib-ipoib-fix-memory-corruption-in-ipoib-cm-mode-connect-flow.patch ib-mlx4-fix-code-indentation-in-qp1-mad-flow.patch ib-mlx4-fix-incorrect-mc-join-state-bit-masking-on-sr-iov.patch ib-mlx4-use-correct-subnet-prefix-in-qp1-mads-under-sr-iov.patch ib-mlx5-enable-mad_ifc-commands-for-ib-ports-only.patch ib-mlx5-set-source-mac-address-in-fte.patch regmap-rbtree-avoid-overlapping-nodes.patch scsi-ses-use-scsi_is_sas_rphy-instead-of-is_sas_attached.patch tpm_crb-drop-struct-resource-res-from-struct-crb_priv.patch tpm_crb-fix-mapping-of-the-buffers.patch --- diff --git a/queue-4.7/aio-mark-aio-pseudo-fs-noexec.patch b/queue-4.7/aio-mark-aio-pseudo-fs-noexec.patch new file mode 100644 index 00000000000..9d9f8cd30af --- /dev/null +++ b/queue-4.7/aio-mark-aio-pseudo-fs-noexec.patch @@ -0,0 +1,67 @@ +From 22f6b4d34fcf039c63a94e7670e0da24f8575a5a Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Fri, 16 Sep 2016 00:31:22 +0200 +Subject: aio: mark AIO pseudo-fs noexec + +From: Jann Horn + +commit 22f6b4d34fcf039c63a94e7670e0da24f8575a5a upstream. + +This ensures that do_mmap() won't implicitly make AIO memory mappings +executable if the READ_IMPLIES_EXEC personality flag is set. Such +behavior is problematic because the security_mmap_file LSM hook doesn't +catch this case, potentially permitting an attacker to bypass a W^X +policy enforced by SELinux. + +I have tested the patch on my machine. + +To test the behavior, compile and run this: + + #define _GNU_SOURCE + #include + #include + #include + #include + #include + #include + #include + + int main(void) { + personality(READ_IMPLIES_EXEC); + aio_context_t ctx = 0; + if (syscall(__NR_io_setup, 1, &ctx)) + err(1, "io_setup"); + + char cmd[1000]; + sprintf(cmd, "cat /proc/%d/maps | grep -F '/[aio]'", + (int)getpid()); + system(cmd); + return 0; + } + +In the output, "rw-s" is good, "rwxs" is bad. + +Signed-off-by: Jann Horn +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/aio.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -239,7 +239,12 @@ static struct dentry *aio_mount(struct f + static const struct dentry_operations ops = { + .d_dname = simple_dname, + }; +- return mount_pseudo(fs_type, "aio:", NULL, &ops, AIO_RING_MAGIC); ++ struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, &ops, ++ AIO_RING_MAGIC); ++ ++ if (!IS_ERR(root)) ++ root->d_sb->s_iflags |= SB_I_NOEXEC; ++ return root; + } + + /* aio_setup diff --git a/queue-4.7/ath10k-fix-get-rx_status-from-htt-context.patch b/queue-4.7/ath10k-fix-get-rx_status-from-htt-context.patch new file mode 100644 index 00000000000..e35ce441498 --- /dev/null +++ b/queue-4.7/ath10k-fix-get-rx_status-from-htt-context.patch @@ -0,0 +1,75 @@ +From 237e15dfd5d651868726111c3a9d828bec700490 Mon Sep 17 00:00:00 2001 +From: Ashok Raj Nagarajan +Date: Fri, 19 Aug 2016 13:37:37 +0300 +Subject: ath10k: fix get rx_status from htt context + +From: Ashok Raj Nagarajan + +commit 237e15dfd5d651868726111c3a9d828bec700490 upstream. + +On handling amsdu on rx path, get the rx_status from htt context. Without this +fix, we are seeing warnings when running DBDC traffic like this. + +WARNING: CPU: 0 PID: 0 at net/mac80211/rx.c:4105 ieee80211_rx_napi+0x88/0x7d8 [mac80211]() + +[ 1715.878248] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 3.18.21 #1 +[ 1715.878273] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) +[ 1715.878293] [] (show_stack) from [] (dump_stack+0x70/0xbc) +[ 1715.878315] [] (dump_stack) from [] (warn_slowpath_common+0x64/0x88) +[ 1715.878339] [] (warn_slowpath_common) from [] (warn_slowpath_null+0x18/0x20) +[ 1715.878395] [] (warn_slowpath_null) from [] (ieee80211_rx_napi+0x88/0x7d8 [mac80211]) +[ 1715.878474] [] (ieee80211_rx_napi [mac80211]) from [] (ath10k_htt_t2h_msg_handler+0xb48/0xbfc [ath10k_core]) +[ 1715.878535] [] (ath10k_htt_t2h_msg_handler [ath10k_core]) from [] (ath10k_htt_t2h_msg_handler+0xbf8/0xbfc [ath10k_core]) +[ 1715.878597] [] (ath10k_htt_t2h_msg_handler [ath10k_core]) from [] (ath10k_htt_txrx_compl_task+0xa54/0x1170 [ath10k_core]) +[ 1715.878639] [] (ath10k_htt_txrx_compl_task [ath10k_core]) from [] (tasklet_action+0xb4/0x130) +[ 1715.878659] [] (tasklet_action) from [] (__do_softirq+0xe0/0x210) +[ 1715.878678] [] (__do_softirq) from [] (irq_exit+0x84/0xe0) +[ 1715.878700] [] (irq_exit) from [] (__handle_domain_irq+0x98/0xd0) +[ 1715.878722] [] (__handle_domain_irq) from [] (gic_handle_irq+0x38/0x5c) +[ 1715.878741] [] (gic_handle_irq) from [] (__irq_svc+0x40/0x74) +[ 1715.878753] Exception stack(0xc05f9f50 to 0xc05f9f98) +[ 1715.878767] 9f40: ffffffed 00000000 00399e1e c000a220 +[ 1715.878786] 9f60: 00000000 c05f6780 c05f8000 00000000 c05f5db8 ffffffed c05f8000 c04d1980 +[ 1715.878802] 9f80: 00000000 c05f9f98 c0018110 c0018114 60000013 ffffffff +[ 1715.878822] [] (__irq_svc) from [] (arch_cpu_idle+0x2c/0x50) +[ 1715.878844] [] (arch_cpu_idle) from [] (cpu_startup_entry+0x108/0x234) +[ 1715.878866] [] (cpu_startup_entry) from [] (start_kernel+0x33c/0x3b8) +[ 1715.878879] ---[ end trace 6d5e1cc0fef8ed6a ]--- +[ 1715.878899] ------------[ cut here ]------------ + +Fixes: 18235664e7f9 ("ath10k: cleanup amsdu processing for rx indication") +Signed-off-by: Ashok Raj Nagarajan +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath10k/htt_rx.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -1524,7 +1524,7 @@ static void ath10k_htt_rx_h_filter(struc + static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) + { + struct ath10k *ar = htt->ar; +- static struct ieee80211_rx_status rx_status; ++ struct ieee80211_rx_status *rx_status = &htt->rx_status; + struct sk_buff_head amsdu; + int ret; + +@@ -1548,11 +1548,11 @@ static int ath10k_htt_rx_handle_amsdu(st + return ret; + } + +- ath10k_htt_rx_h_ppdu(ar, &amsdu, &rx_status, 0xffff); ++ ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); + ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0); +- ath10k_htt_rx_h_filter(ar, &amsdu, &rx_status); +- ath10k_htt_rx_h_mpdu(ar, &amsdu, &rx_status); +- ath10k_htt_rx_h_deliver(ar, &amsdu, &rx_status); ++ ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); ++ ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); ++ ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); + + return 0; + } diff --git a/queue-4.7/batman-adv-remove-unused-callback-from-batadv_algo_ops-struct.patch b/queue-4.7/batman-adv-remove-unused-callback-from-batadv_algo_ops-struct.patch new file mode 100644 index 00000000000..4ad56dec0c9 --- /dev/null +++ b/queue-4.7/batman-adv-remove-unused-callback-from-batadv_algo_ops-struct.patch @@ -0,0 +1,61 @@ +From d9f179877e50ae2681fe7b0b83e0d9f63b6165ad Mon Sep 17 00:00:00 2001 +From: Marek Lindner +Date: Mon, 2 May 2016 21:58:50 +0800 +Subject: batman-adv: remove unused callback from batadv_algo_ops struct + +From: Marek Lindner + +commit d9f179877e50ae2681fe7b0b83e0d9f63b6165ad upstream. + +Signed-off-by: Marek Lindner +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman + +--- + net/batman-adv/originator.c | 5 ----- + net/batman-adv/types.h | 3 --- + 2 files changed, 8 deletions(-) + +--- a/net/batman-adv/originator.c ++++ b/net/batman-adv/originator.c +@@ -251,10 +251,8 @@ static void batadv_neigh_node_release(st + struct hlist_node *node_tmp; + struct batadv_neigh_node *neigh_node; + struct batadv_neigh_ifinfo *neigh_ifinfo; +- struct batadv_algo_ops *bao; + + neigh_node = container_of(ref, struct batadv_neigh_node, refcount); +- bao = neigh_node->orig_node->bat_priv->bat_algo_ops; + + hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, + &neigh_node->ifinfo_list, list) { +@@ -263,9 +261,6 @@ static void batadv_neigh_node_release(st + + batadv_hardif_neigh_put(neigh_node->hardif_neigh); + +- if (bao->bat_neigh_free) +- bao->bat_neigh_free(neigh_node); +- + batadv_hardif_put(neigh_node->if_incoming); + + kfree_rcu(neigh_node, rcu); +--- a/net/batman-adv/types.h ++++ b/net/batman-adv/types.h +@@ -1284,8 +1284,6 @@ struct batadv_forw_packet { + * better than neigh2 for their respective outgoing interface from the metric + * prospective + * @bat_neigh_print: print the single hop neighbor list (optional) +- * @bat_neigh_free: free the resources allocated by the routing algorithm for a +- * neigh_node object + * @bat_orig_print: print the originator table (optional) + * @bat_orig_free: free the resources allocated by the routing algorithm for an + * orig_node object +@@ -1316,7 +1314,6 @@ struct batadv_algo_ops { + struct batadv_neigh_node *neigh2, + struct batadv_hard_iface *if_outgoing2); + void (*bat_neigh_print)(struct batadv_priv *priv, struct seq_file *seq); +- void (*bat_neigh_free)(struct batadv_neigh_node *neigh); + /* orig_node handling API */ + void (*bat_orig_print)(struct batadv_priv *priv, struct seq_file *seq, + struct batadv_hard_iface *hard_iface); diff --git a/queue-4.7/ceph-do-not-modify-fi-frag-in-need_reset_readdir.patch b/queue-4.7/ceph-do-not-modify-fi-frag-in-need_reset_readdir.patch new file mode 100644 index 00000000000..1c35346f4be --- /dev/null +++ b/queue-4.7/ceph-do-not-modify-fi-frag-in-need_reset_readdir.patch @@ -0,0 +1,52 @@ +From 0f5aa88a7bb28b73253fb42b3df8202142769f39 Mon Sep 17 00:00:00 2001 +From: Nicolas Iooss +Date: Sun, 28 Aug 2016 18:47:12 +0200 +Subject: ceph: do not modify fi->frag in need_reset_readdir() + +From: Nicolas Iooss + +commit 0f5aa88a7bb28b73253fb42b3df8202142769f39 upstream. + +Commit f3c4ebe65ea1 ("ceph: using hash value to compose dentry offset") +modified "if (fpos_frag(new_pos) != fi->frag)" to "if (fi->frag |= +fpos_frag(new_pos))" in need_reset_readdir(), thus replacing a +comparison operator with an assignment one. + +This looks like a typo which is reported by clang when building the +kernel with some warning flags: + + fs/ceph/dir.c:600:22: error: using the result of an assignment as a + condition without parentheses [-Werror,-Wparentheses] + } else if (fi->frag |= fpos_frag(new_pos)) { + ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ + fs/ceph/dir.c:600:22: note: place parentheses around the assignment + to silence this warning + } else if (fi->frag |= fpos_frag(new_pos)) { + ^ + ( ) + fs/ceph/dir.c:600:22: note: use '!=' to turn this compound + assignment into an inequality comparison + } else if (fi->frag |= fpos_frag(new_pos)) { + ^~ + != + +Fixes: f3c4ebe65ea1 ("ceph: using hash value to compose dentry offset") +Signed-off-by: Nicolas Iooss +Signed-off-by: Ilya Dryomov +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ceph/dir.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ceph/dir.c ++++ b/fs/ceph/dir.c +@@ -597,7 +597,7 @@ static bool need_reset_readdir(struct ce + if (is_hash_order(new_pos)) { + /* no need to reset last_name for a forward seek when + * dentries are sotred in hash order */ +- } else if (fi->frag |= fpos_frag(new_pos)) { ++ } else if (fi->frag != fpos_frag(new_pos)) { + return true; + } + rinfo = fi->last_readdir ? &fi->last_readdir->r_reply_info : NULL; diff --git a/queue-4.7/dm-log-writes-fix-bug-with-too-large-bios.patch b/queue-4.7/dm-log-writes-fix-bug-with-too-large-bios.patch new file mode 100644 index 00000000000..8188f9c9ed1 --- /dev/null +++ b/queue-4.7/dm-log-writes-fix-bug-with-too-large-bios.patch @@ -0,0 +1,49 @@ +From 7efb367320f56fc4d549875b6f3a6940018ef2e5 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Tue, 30 Aug 2016 16:20:55 -0400 +Subject: dm log writes: fix bug with too large bios + +From: Mikulas Patocka + +commit 7efb367320f56fc4d549875b6f3a6940018ef2e5 upstream. + +bio_alloc() can allocate a bio with at most BIO_MAX_PAGES (256) vector +entries. However, the incoming bio may have more vector entries if it +was allocated by other means. For example, bcache submits bios with +more than BIO_MAX_PAGES entries. This results in bio_alloc() failure. + +To avoid the failure, change the code so that it allocates bio with at +most BIO_MAX_PAGES entries. If the incoming bio has more entries, +bio_add_page() will fail and a new bio will be allocated - the code that +handles bio_add_page() failure already exists in the dm-log-writes +target. + +Signed-off-by: Mikulas Patocka +Reviewed-by: Josef Bacik +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-log-writes.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/md/dm-log-writes.c ++++ b/drivers/md/dm-log-writes.c +@@ -259,7 +259,7 @@ static int log_one_block(struct log_writ + sector++; + + atomic_inc(&lc->io_blocks); +- bio = bio_alloc(GFP_KERNEL, block->vec_cnt); ++ bio = bio_alloc(GFP_KERNEL, min(block->vec_cnt, BIO_MAX_PAGES)); + if (!bio) { + DMERR("Couldn't alloc log bio"); + goto error; +@@ -280,7 +280,7 @@ static int log_one_block(struct log_writ + if (ret != block->vecs[i].bv_len) { + atomic_inc(&lc->io_blocks); + submit_bio(WRITE, bio); +- bio = bio_alloc(GFP_KERNEL, block->vec_cnt - i); ++ bio = bio_alloc(GFP_KERNEL, min(block->vec_cnt - i, BIO_MAX_PAGES)); + if (!bio) { + DMERR("Couldn't alloc log bio"); + goto error; diff --git a/queue-4.7/ib-core-fix-use-after-free-in-send_leave-function.patch b/queue-4.7/ib-core-fix-use-after-free-in-send_leave-function.patch new file mode 100644 index 00000000000..4949f314f74 --- /dev/null +++ b/queue-4.7/ib-core-fix-use-after-free-in-send_leave-function.patch @@ -0,0 +1,63 @@ +From 68c6bcdd8bd00394c234b915ab9b97c74104130c Mon Sep 17 00:00:00 2001 +From: Erez Shitrit +Date: Sun, 28 Aug 2016 10:58:30 +0300 +Subject: IB/core: Fix use after free in send_leave function + +From: Erez Shitrit + +commit 68c6bcdd8bd00394c234b915ab9b97c74104130c upstream. + +The function send_leave sets the member: group->query_id +(group->query_id = ret) after calling the sa_query, but leave_handler +can be executed before the setting and it might delete the group object, +and will get a memory corruption. + +Additionally, this patch gets rid of group->query_id variable which is +not used. + +Fixes: faec2f7b96b5 ('IB/sa: Track multicast join/leave requests') +Signed-off-by: Erez Shitrit +Signed-off-by: Leon Romanovsky +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/core/multicast.c | 13 ++----------- + 1 file changed, 2 insertions(+), 11 deletions(-) + +--- a/drivers/infiniband/core/multicast.c ++++ b/drivers/infiniband/core/multicast.c +@@ -118,7 +118,6 @@ struct mcast_group { + atomic_t refcount; + enum mcast_group_state state; + struct ib_sa_query *query; +- int query_id; + u16 pkey_index; + u8 leave_state; + int retries; +@@ -352,11 +351,7 @@ static int send_join(struct mcast_group + member->multicast.comp_mask, + 3000, GFP_KERNEL, join_handler, group, + &group->query); +- if (ret >= 0) { +- group->query_id = ret; +- ret = 0; +- } +- return ret; ++ return (ret > 0) ? 0 : ret; + } + + static int send_leave(struct mcast_group *group, u8 leave_state) +@@ -376,11 +371,7 @@ static int send_leave(struct mcast_group + IB_SA_MCMEMBER_REC_JOIN_STATE, + 3000, GFP_KERNEL, leave_handler, + group, &group->query); +- if (ret >= 0) { +- group->query_id = ret; +- ret = 0; +- } +- return ret; ++ return (ret > 0) ? 0 : ret; + } + + static void join_group(struct mcast_group *group, struct mcast_member *member, diff --git a/queue-4.7/ib-ipoib-don-t-allow-mc-joins-during-light-mc-flush.patch b/queue-4.7/ib-ipoib-don-t-allow-mc-joins-during-light-mc-flush.patch new file mode 100644 index 00000000000..c44d18e102c --- /dev/null +++ b/queue-4.7/ib-ipoib-don-t-allow-mc-joins-during-light-mc-flush.patch @@ -0,0 +1,84 @@ +From 344bacca8cd811809fc33a249f2738ab757d327f Mon Sep 17 00:00:00 2001 +From: Alex Vesker +Date: Mon, 12 Sep 2016 09:55:28 +0300 +Subject: IB/ipoib: Don't allow MC joins during light MC flush + +From: Alex Vesker + +commit 344bacca8cd811809fc33a249f2738ab757d327f upstream. + +This fix solves a race between light flush and on the fly joins. +Light flush doesn't set the device to down and unset IPOIB_OPER_UP +flag, this means that if while flushing we have a MC join in progress +and the QP was attached to BC MGID we can have a mismatches when +re-attaching a QP to the BC MGID. + +The light flush would set the broadcast group to NULL causing an on +the fly join to rejoin and reattach to the BC MCG as well as adding +the BC MGID to the multicast list. The flush process would later on +remove the BC MGID and detach it from the QP. On the next flush +the BC MGID is present in the multicast list but not found when trying +to detach it because of the previous double attach and single detach. + +[18332.714265] ------------[ cut here ]------------ +[18332.717775] WARNING: CPU: 6 PID: 3767 at drivers/infiniband/core/verbs.c:280 ib_dealloc_pd+0xff/0x120 [ib_core] +... +[18332.775198] Hardware name: Red Hat KVM, BIOS Bochs 01/01/2011 +[18332.779411] 0000000000000000 ffff8800b50dfbb0 ffffffff813fed47 0000000000000000 +[18332.784960] 0000000000000000 ffff8800b50dfbf0 ffffffff8109add1 0000011832f58300 +[18332.790547] ffff880226a596c0 ffff880032482000 ffff880032482830 ffff880226a59280 +[18332.796199] Call Trace: +[18332.798015] [] dump_stack+0x63/0x8c +[18332.801831] [] __warn+0xd1/0xf0 +[18332.805403] [] warn_slowpath_null+0x1d/0x20 +[18332.809706] [] ib_dealloc_pd+0xff/0x120 [ib_core] +[18332.814384] [] ipoib_transport_dev_cleanup+0xfc/0x1d0 [ib_ipoib] +[18332.820031] [] ipoib_ib_dev_cleanup+0x98/0x110 [ib_ipoib] +[18332.825220] [] ipoib_dev_cleanup+0x2d8/0x550 [ib_ipoib] +[18332.830290] [] ipoib_uninit+0x2f/0x40 [ib_ipoib] +[18332.834911] [] rollback_registered_many+0x1aa/0x2c0 +[18332.839741] [] rollback_registered+0x31/0x40 +[18332.844091] [] unregister_netdevice_queue+0x48/0x80 +[18332.848880] [] ipoib_vlan_delete+0x1fb/0x290 [ib_ipoib] +[18332.853848] [] delete_child+0x7d/0xf0 [ib_ipoib] +[18332.858474] [] dev_attr_store+0x18/0x30 +[18332.862510] [] sysfs_kf_write+0x3a/0x50 +[18332.866349] [] kernfs_fop_write+0x120/0x170 +[18332.870471] [] __vfs_write+0x28/0xe0 +[18332.874152] [] ? percpu_down_read+0x1f/0x50 +[18332.878274] [] vfs_write+0xa2/0x1a0 +[18332.881896] [] SyS_write+0x46/0xa0 +[18332.885632] [] do_syscall_64+0x57/0xb0 +[18332.889709] [] entry_SYSCALL64_slow_path+0x25/0x25 +[18332.894727] ---[ end trace 09ebbe31f831ef17 ]--- + +Fixes: ee1e2c82c245 ("IPoIB: Refresh paths instead of flushing them on SM change events") +Signed-off-by: Alex Vesker +Signed-off-by: Leon Romanovsky +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/ulp/ipoib/ipoib_ib.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c +@@ -1161,8 +1161,17 @@ static void __ipoib_ib_dev_flush(struct + } + + if (level == IPOIB_FLUSH_LIGHT) { ++ int oper_up; + ipoib_mark_paths_invalid(dev); ++ /* Set IPoIB operation as down to prevent races between: ++ * the flush flow which leaves MCG and on the fly joins ++ * which can happen during that time. mcast restart task ++ * should deal with join requests we missed. ++ */ ++ oper_up = test_and_clear_bit(IPOIB_FLAG_OPER_UP, &priv->flags); + ipoib_mcast_dev_flush(dev); ++ if (oper_up) ++ set_bit(IPOIB_FLAG_OPER_UP, &priv->flags); + ipoib_flush_ah(dev); + } + diff --git a/queue-4.7/ib-ipoib-fix-memory-corruption-in-ipoib-cm-mode-connect-flow.patch b/queue-4.7/ib-ipoib-fix-memory-corruption-in-ipoib-cm-mode-connect-flow.patch new file mode 100644 index 00000000000..e7ad186cfa4 --- /dev/null +++ b/queue-4.7/ib-ipoib-fix-memory-corruption-in-ipoib-cm-mode-connect-flow.patch @@ -0,0 +1,111 @@ +From 546481c2816ea3c061ee9d5658eb48070f69212e Mon Sep 17 00:00:00 2001 +From: Erez Shitrit +Date: Sun, 28 Aug 2016 10:58:31 +0300 +Subject: IB/ipoib: Fix memory corruption in ipoib cm mode connect flow + +From: Erez Shitrit + +commit 546481c2816ea3c061ee9d5658eb48070f69212e upstream. + +When a new CM connection is being requested, ipoib driver copies data +from the path pointer in the CM/tx object, the path object might be +invalid at the point and memory corruption will happened later when now +the CM driver will try using that data. + +The next scenario demonstrates it: + neigh_add_path --> ipoib_cm_create_tx --> + queue_work (pointer to path is in the cm/tx struct) + #while the work is still in the queue, + #the port goes down and causes the ipoib_flush_paths: + ipoib_flush_paths --> path_free --> kfree(path) + #at this point the work scheduled starts. + ipoib_cm_tx_start --> copy from the (invalid)path pointer: + (memcpy(&pathrec, &p->path->pathrec, sizeof pathrec);) + -> memory corruption. + +To fix that the driver now starts the CM/tx connection only if that +specific path exists in the general paths database. +This check is protected with the relevant locks, and uses the gid from +the neigh member in the CM/tx object which is valid according to the ref +count that was taken by the CM/tx. + +Fixes: 839fcaba35 ('IPoIB: Connected mode experimental support') +Signed-off-by: Erez Shitrit +Signed-off-by: Leon Romanovsky +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/ulp/ipoib/ipoib.h | 1 + + drivers/infiniband/ulp/ipoib/ipoib_cm.c | 16 ++++++++++++++++ + drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- + 3 files changed, 18 insertions(+), 1 deletion(-) + +--- a/drivers/infiniband/ulp/ipoib/ipoib.h ++++ b/drivers/infiniband/ulp/ipoib/ipoib.h +@@ -478,6 +478,7 @@ void ipoib_send(struct net_device *dev, + struct ipoib_ah *address, u32 qpn); + void ipoib_reap_ah(struct work_struct *work); + ++struct ipoib_path *__path_find(struct net_device *dev, void *gid); + void ipoib_mark_paths_invalid(struct net_device *dev); + void ipoib_flush_paths(struct net_device *dev); + int ipoib_check_sm_sendonly_fullmember_support(struct ipoib_dev_priv *priv); +--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c +@@ -1318,6 +1318,8 @@ void ipoib_cm_destroy_tx(struct ipoib_cm + } + } + ++#define QPN_AND_OPTIONS_OFFSET 4 ++ + static void ipoib_cm_tx_start(struct work_struct *work) + { + struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv, +@@ -1326,6 +1328,7 @@ static void ipoib_cm_tx_start(struct wor + struct ipoib_neigh *neigh; + struct ipoib_cm_tx *p; + unsigned long flags; ++ struct ipoib_path *path; + int ret; + + struct ib_sa_path_rec pathrec; +@@ -1338,7 +1341,19 @@ static void ipoib_cm_tx_start(struct wor + p = list_entry(priv->cm.start_list.next, typeof(*p), list); + list_del_init(&p->list); + neigh = p->neigh; ++ + qpn = IPOIB_QPN(neigh->daddr); ++ /* ++ * As long as the search is with these 2 locks, ++ * path existence indicates its validity. ++ */ ++ path = __path_find(dev, neigh->daddr + QPN_AND_OPTIONS_OFFSET); ++ if (!path) { ++ pr_info("%s ignore not valid path %pI6\n", ++ __func__, ++ neigh->daddr + QPN_AND_OPTIONS_OFFSET); ++ goto free_neigh; ++ } + memcpy(&pathrec, &p->path->pathrec, sizeof pathrec); + + spin_unlock_irqrestore(&priv->lock, flags); +@@ -1350,6 +1365,7 @@ static void ipoib_cm_tx_start(struct wor + spin_lock_irqsave(&priv->lock, flags); + + if (ret) { ++free_neigh: + neigh = p->neigh; + if (neigh) { + neigh->cm = NULL; +--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c +@@ -485,7 +485,7 @@ int ipoib_set_mode(struct net_device *de + return -EINVAL; + } + +-static struct ipoib_path *__path_find(struct net_device *dev, void *gid) ++struct ipoib_path *__path_find(struct net_device *dev, void *gid) + { + struct ipoib_dev_priv *priv = netdev_priv(dev); + struct rb_node *n = priv->path_tree.rb_node; diff --git a/queue-4.7/ib-mlx4-fix-code-indentation-in-qp1-mad-flow.patch b/queue-4.7/ib-mlx4-fix-code-indentation-in-qp1-mad-flow.patch new file mode 100644 index 00000000000..0e002a26e51 --- /dev/null +++ b/queue-4.7/ib-mlx4-fix-code-indentation-in-qp1-mad-flow.patch @@ -0,0 +1,69 @@ +From baa0be7026e2f7d1d40bfd45909044169e9e3c68 Mon Sep 17 00:00:00 2001 +From: Jack Morgenstein +Date: Mon, 12 Sep 2016 19:16:19 +0300 +Subject: IB/mlx4: Fix code indentation in QP1 MAD flow + +From: Jack Morgenstein + +commit baa0be7026e2f7d1d40bfd45909044169e9e3c68 upstream. + +The indentation in the QP1 GRH flow in procedure build_mlx_header is +really confusing. Fix it, in preparation for a commit which touches +this code. + +Fixes: 1ffeb2eb8be9 ("IB/mlx4: SR-IOV IB context objects and proxy/tunnel SQP support") +Signed-off-by: Jack Morgenstein +Signed-off-by: Leon Romanovsky +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/mlx4/qp.c | 36 +++++++++++++++++++----------------- + 1 file changed, 19 insertions(+), 17 deletions(-) + +--- a/drivers/infiniband/hw/mlx4/qp.c ++++ b/drivers/infiniband/hw/mlx4/qp.c +@@ -2492,24 +2492,26 @@ static int build_mlx_header(struct mlx4_ + sqp->ud_header.grh.flow_label = + ah->av.ib.sl_tclass_flowlabel & cpu_to_be32(0xfffff); + sqp->ud_header.grh.hop_limit = ah->av.ib.hop_limit; +- if (is_eth) ++ if (is_eth) { + memcpy(sqp->ud_header.grh.source_gid.raw, sgid.raw, 16); +- else { +- if (mlx4_is_mfunc(to_mdev(ib_dev)->dev)) { +- /* When multi-function is enabled, the ib_core gid +- * indexes don't necessarily match the hw ones, so +- * we must use our own cache */ +- sqp->ud_header.grh.source_gid.global.subnet_prefix = +- to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1]. +- subnet_prefix; +- sqp->ud_header.grh.source_gid.global.interface_id = +- to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1]. +- guid_cache[ah->av.ib.gid_index]; +- } else +- ib_get_cached_gid(ib_dev, +- be32_to_cpu(ah->av.ib.port_pd) >> 24, +- ah->av.ib.gid_index, +- &sqp->ud_header.grh.source_gid, NULL); ++ } else { ++ if (mlx4_is_mfunc(to_mdev(ib_dev)->dev)) { ++ /* When multi-function is enabled, the ib_core gid ++ * indexes don't necessarily match the hw ones, so ++ * we must use our own cache ++ */ ++ sqp->ud_header.grh.source_gid.global.subnet_prefix = ++ to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1]. ++ subnet_prefix; ++ sqp->ud_header.grh.source_gid.global.interface_id = ++ to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1]. ++ guid_cache[ah->av.ib.gid_index]; ++ } else { ++ ib_get_cached_gid(ib_dev, ++ be32_to_cpu(ah->av.ib.port_pd) >> 24, ++ ah->av.ib.gid_index, ++ &sqp->ud_header.grh.source_gid, NULL); ++ } + } + memcpy(sqp->ud_header.grh.destination_gid.raw, + ah->av.ib.dgid, 16); diff --git a/queue-4.7/ib-mlx4-fix-incorrect-mc-join-state-bit-masking-on-sr-iov.patch b/queue-4.7/ib-mlx4-fix-incorrect-mc-join-state-bit-masking-on-sr-iov.patch new file mode 100644 index 00000000000..464827693c1 --- /dev/null +++ b/queue-4.7/ib-mlx4-fix-incorrect-mc-join-state-bit-masking-on-sr-iov.patch @@ -0,0 +1,79 @@ +From e5ac40cd66c2f3cd11bc5edc658f012661b16347 Mon Sep 17 00:00:00 2001 +From: Alex Vesker +Date: Mon, 12 Sep 2016 19:16:18 +0300 +Subject: IB/mlx4: Fix incorrect MC join state bit-masking on SR-IOV + +From: Alex Vesker + +commit e5ac40cd66c2f3cd11bc5edc658f012661b16347 upstream. + +Because of an incorrect bit-masking done on the join state bits, when +handling a join request we failed to detect a difference between the +group join state and the request join state when joining as send only +full member (0x8). This caused the MC join request not to be sent. +This issue is relevant only when SRIOV is enabled and SM supports +send only full member. + +This fix separates scope bits and join states bits a nibble each. + +Fixes: b9c5d6a64358 ('IB/mlx4: Add multicast group (MCG) paravirtualization for SR-IOV') +Signed-off-by: Alex Vesker +Signed-off-by: Leon Romanovsky +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/mlx4/mcg.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/infiniband/hw/mlx4/mcg.c ++++ b/drivers/infiniband/hw/mlx4/mcg.c +@@ -489,7 +489,7 @@ static u8 get_leave_state(struct mcast_g + if (!group->members[i]) + leave_state |= (1 << i); + +- return leave_state & (group->rec.scope_join_state & 7); ++ return leave_state & (group->rec.scope_join_state & 0xf); + } + + static int join_group(struct mcast_group *group, int slave, u8 join_mask) +@@ -564,8 +564,8 @@ static void mlx4_ib_mcg_timeout_handler( + } else + mcg_warn_group(group, "DRIVER BUG\n"); + } else if (group->state == MCAST_LEAVE_SENT) { +- if (group->rec.scope_join_state & 7) +- group->rec.scope_join_state &= 0xf8; ++ if (group->rec.scope_join_state & 0xf) ++ group->rec.scope_join_state &= 0xf0; + group->state = MCAST_IDLE; + mutex_unlock(&group->lock); + if (release_group(group, 1)) +@@ -605,7 +605,7 @@ static int handle_leave_req(struct mcast + static int handle_join_req(struct mcast_group *group, u8 join_mask, + struct mcast_req *req) + { +- u8 group_join_state = group->rec.scope_join_state & 7; ++ u8 group_join_state = group->rec.scope_join_state & 0xf; + int ref = 0; + u16 status; + struct ib_sa_mcmember_data *sa_data = (struct ib_sa_mcmember_data *)req->sa_mad.data; +@@ -690,8 +690,8 @@ static void mlx4_ib_mcg_work_handler(str + u8 cur_join_state; + + resp_join_state = ((struct ib_sa_mcmember_data *) +- group->response_sa_mad.data)->scope_join_state & 7; +- cur_join_state = group->rec.scope_join_state & 7; ++ group->response_sa_mad.data)->scope_join_state & 0xf; ++ cur_join_state = group->rec.scope_join_state & 0xf; + + if (method == IB_MGMT_METHOD_GET_RESP) { + /* successfull join */ +@@ -710,7 +710,7 @@ process_requests: + req = list_first_entry(&group->pending_list, struct mcast_req, + group_list); + sa_data = (struct ib_sa_mcmember_data *)req->sa_mad.data; +- req_join_state = sa_data->scope_join_state & 0x7; ++ req_join_state = sa_data->scope_join_state & 0xf; + + /* For a leave request, we will immediately answer the VF, and + * update our internal counters. The actual leave will be sent diff --git a/queue-4.7/ib-mlx4-use-correct-subnet-prefix-in-qp1-mads-under-sr-iov.patch b/queue-4.7/ib-mlx4-use-correct-subnet-prefix-in-qp1-mads-under-sr-iov.patch new file mode 100644 index 00000000000..546f1019a58 --- /dev/null +++ b/queue-4.7/ib-mlx4-use-correct-subnet-prefix-in-qp1-mads-under-sr-iov.patch @@ -0,0 +1,116 @@ +From 8ec07bf8a8b57d6c58927a16a0a22c0115cf2855 Mon Sep 17 00:00:00 2001 +From: Jack Morgenstein +Date: Mon, 12 Sep 2016 19:16:20 +0300 +Subject: IB/mlx4: Use correct subnet-prefix in QP1 mads under SR-IOV + +From: Jack Morgenstein + +commit 8ec07bf8a8b57d6c58927a16a0a22c0115cf2855 upstream. + +When sending QP1 MAD packets which use a GRH, the source GID +(which consists of the 64-bit subnet prefix, and the 64 bit port GUID) +must be included in the packet GRH. + +For SR-IOV, a GID cache is used, since the source GID needs to be the +slave's source GID, and not the Hypervisor's GID. This cache also +included a subnet_prefix. Unfortunately, the subnet_prefix field in +the cache was never initialized (to the default subnet prefix 0xfe80::0). +As a result, this field remained all zeroes. Therefore, when SR-IOV +was active, all QP1 packets which included a GRH had a source GID +subnet prefix of all-zeroes. + +However, the subnet-prefix should initially be 0xfe80::0 (the default +subnet prefix). In addition, if OpenSM modifies a port's subnet prefix, +the new subnet prefix must be used in the GRH when sending QP1 packets. +To fix this we now initialize the subnet prefix in the SR-IOV GID cache +to the default subnet prefix. We update the cached value if/when OpenSM +modifies the port's subnet prefix. We take this cached value when sending +QP1 packets when SR-IOV is active. + +Note that the value is stored as an atomic64. This eliminates any need +for locking when the subnet prefix is being updated. + +Note also that we depend on the FW generating the "port management change" +event for tracking subnet-prefix changes performed by OpenSM. If running +early FW (before 2.9.4630), subnet prefix changes will not be tracked (but +the default subnet prefix still will be stored in the cache; therefore +users who do not modify the subnet prefix will not have a problem). +IF there is a need for such tracking also for early FW, we will add that +capability in a subsequent patch. + +Fixes: 1ffeb2eb8be9 ("IB/mlx4: SR-IOV IB context objects and proxy/tunnel SQP support") +Signed-off-by: Jack Morgenstein +Signed-off-by: Leon Romanovsky +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/mlx4/mad.c | 23 +++++++++++++++++++++++ + drivers/infiniband/hw/mlx4/mlx4_ib.h | 2 +- + drivers/infiniband/hw/mlx4/qp.c | 5 +++-- + 3 files changed, 27 insertions(+), 3 deletions(-) + +--- a/drivers/infiniband/hw/mlx4/mad.c ++++ b/drivers/infiniband/hw/mlx4/mad.c +@@ -1128,6 +1128,27 @@ void handle_port_mgmt_change_event(struc + + /* Generate GUID changed event */ + if (changed_attr & MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK) { ++ if (mlx4_is_master(dev->dev)) { ++ union ib_gid gid; ++ int err = 0; ++ ++ if (!eqe->event.port_mgmt_change.params.port_info.gid_prefix) ++ err = __mlx4_ib_query_gid(&dev->ib_dev, port, 0, &gid, 1); ++ else ++ gid.global.subnet_prefix = ++ eqe->event.port_mgmt_change.params.port_info.gid_prefix; ++ if (err) { ++ pr_warn("Could not change QP1 subnet prefix for port %d: query_gid error (%d)\n", ++ port, err); ++ } else { ++ pr_debug("Changing QP1 subnet prefix for port %d. old=0x%llx. new=0x%llx\n", ++ port, ++ (u64)atomic64_read(&dev->sriov.demux[port - 1].subnet_prefix), ++ be64_to_cpu(gid.global.subnet_prefix)); ++ atomic64_set(&dev->sriov.demux[port - 1].subnet_prefix, ++ be64_to_cpu(gid.global.subnet_prefix)); ++ } ++ } + mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE); + /*if master, notify all slaves*/ + if (mlx4_is_master(dev->dev)) +@@ -2202,6 +2223,8 @@ int mlx4_ib_init_sriov(struct mlx4_ib_de + if (err) + goto demux_err; + dev->sriov.demux[i].guid_cache[0] = gid.global.interface_id; ++ atomic64_set(&dev->sriov.demux[i].subnet_prefix, ++ be64_to_cpu(gid.global.subnet_prefix)); + err = alloc_pv_object(dev, mlx4_master_func_num(dev->dev), i + 1, + &dev->sriov.sqps[i]); + if (err) +--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h ++++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h +@@ -448,7 +448,7 @@ struct mlx4_ib_demux_ctx { + struct workqueue_struct *wq; + struct workqueue_struct *ud_wq; + spinlock_t ud_lock; +- __be64 subnet_prefix; ++ atomic64_t subnet_prefix; + __be64 guid_cache[128]; + struct mlx4_ib_dev *dev; + /* the following lock protects both mcg_table and mcg_mgid0_list */ +--- a/drivers/infiniband/hw/mlx4/qp.c ++++ b/drivers/infiniband/hw/mlx4/qp.c +@@ -2501,8 +2501,9 @@ static int build_mlx_header(struct mlx4_ + * we must use our own cache + */ + sqp->ud_header.grh.source_gid.global.subnet_prefix = +- to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1]. +- subnet_prefix; ++ cpu_to_be64(atomic64_read(&(to_mdev(ib_dev)->sriov. ++ demux[sqp->qp.port - 1]. ++ subnet_prefix))); + sqp->ud_header.grh.source_gid.global.interface_id = + to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1]. + guid_cache[ah->av.ib.gid_index]; diff --git a/queue-4.7/ib-mlx5-enable-mad_ifc-commands-for-ib-ports-only.patch b/queue-4.7/ib-mlx5-enable-mad_ifc-commands-for-ib-ports-only.patch new file mode 100644 index 00000000000..dffe8c2a36b --- /dev/null +++ b/queue-4.7/ib-mlx5-enable-mad_ifc-commands-for-ib-ports-only.patch @@ -0,0 +1,36 @@ +From 7fae6655a0c897875bd34501ec092232b526d3e4 Mon Sep 17 00:00:00 2001 +From: Noa Osherovich +Date: Mon, 12 Sep 2016 19:16:23 +0300 +Subject: IB/mlx5: Enable MAD_IFC commands for IB ports only + +From: Noa Osherovich + +commit 7fae6655a0c897875bd34501ec092232b526d3e4 upstream. + +MAD_IFC command is supported only for physical functions (PF) +and when physical port is IB. The proposed fix enforces it. + +Fixes: d603c809ef91 ("IB/mlx5: Fix decision on using MAD_IFC") +Reported-by: David Chang +Signed-off-by: Noa Osherovich +Signed-off-by: Leon Romanovsky +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/mlx5/main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -287,7 +287,9 @@ __be16 mlx5_get_roce_udp_sport(struct ml + + static int mlx5_use_mad_ifc(struct mlx5_ib_dev *dev) + { +- return !MLX5_CAP_GEN(dev->mdev, ib_virt); ++ if (MLX5_CAP_GEN(dev->mdev, port_type) == MLX5_CAP_PORT_TYPE_IB) ++ return !MLX5_CAP_GEN(dev->mdev, ib_virt); ++ return 0; + } + + enum { diff --git a/queue-4.7/ib-mlx5-set-source-mac-address-in-fte.patch b/queue-4.7/ib-mlx5-set-source-mac-address-in-fte.patch new file mode 100644 index 00000000000..5dd05527338 --- /dev/null +++ b/queue-4.7/ib-mlx5-set-source-mac-address-in-fte.patch @@ -0,0 +1,38 @@ +From ee3da804ad1b1dd4c766199a6e8443542b0aaaef Mon Sep 17 00:00:00 2001 +From: Maor Gottlieb +Date: Mon, 12 Sep 2016 19:16:24 +0300 +Subject: IB/mlx5: Set source mac address in FTE + +From: Maor Gottlieb + +commit ee3da804ad1b1dd4c766199a6e8443542b0aaaef upstream. + +Set the source mac address in the FTE when L2 specification +is provided. + +Fixes: 038d2ef87572 ('IB/mlx5: Add flow steering support') +Signed-off-by: Maor Gottlieb +Signed-off-by: Leon Romanovsky +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/mlx5/main.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -1277,6 +1277,13 @@ static int parse_flow_attr(u32 *match_c, + dmac_47_16), + ib_spec->eth.val.dst_mac); + ++ ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c, ++ smac_47_16), ++ ib_spec->eth.mask.src_mac); ++ ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v, ++ smac_47_16), ++ ib_spec->eth.val.src_mac); ++ + if (ib_spec->eth.mask.vlan_tag) { + MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, + vlan_tag, 1); diff --git a/queue-4.7/regmap-rbtree-avoid-overlapping-nodes.patch b/queue-4.7/regmap-rbtree-avoid-overlapping-nodes.patch new file mode 100644 index 00000000000..0dae80a3099 --- /dev/null +++ b/queue-4.7/regmap-rbtree-avoid-overlapping-nodes.patch @@ -0,0 +1,118 @@ +From 1bc8da4e143c0fd8807e061a66d91d5972601ab1 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Thu, 4 Aug 2016 17:22:16 +0200 +Subject: regmap: rbtree: Avoid overlapping nodes + +From: Lars-Peter Clausen + +commit 1bc8da4e143c0fd8807e061a66d91d5972601ab1 upstream. + +When searching for a suitable node that should be used for inserting a new +register, which does not fall within the range of any existing node, we not +only looks for nodes which are directly adjacent to the new register, but +for nodes within a certain proximity. This is done to avoid creating lots +of small nodes with just a few registers spacing in between, which would +increase memory usage as well as tree traversal time. + +This means there might be multiple node candidates which fall within the +proximity range of the new register. If we choose the first node we +encounter, under certain register insertion patterns it is possible to end +up with overlapping ranges. This will break order in the rbtree and can +cause the cached register value to become corrupted. + +E.g. take the simplified example where the proximity range is 2 and the +register insertion sequence is 1, 4, 2, 3, 5. + * Insert of register 1 creates a new node, this is the root of the rbtree + * Insert of register 4 creates a new node, which is inserted to the right + of the root. + * Insert of register 2 gets inserted to the first node + * Insert of register 3 gets inserted to the first node + * Insert of register 5 also gets inserted into the first node since + this is the first node encountered and it is within the proximity range. + Now there are two overlapping nodes. + +To avoid this always choose the node that is closest to the new register. +This will ensure that nodes will not overlap. The tree traversal is still +done as a binary search, we just don't stop at the first node found. So the +complexity of the algorithm stays within the same order. + +Ideally if a new register is in the range of two adjacent blocks those +blocks should be merged, but that is a much more invasive change and left +for later. + +The issue was initially introduced in commit 472fdec7380c ("regmap: rbtree: +Reduce number of nodes, take 2"), but became much more exposed by commit +6399aea629b0 ("regmap: rbtree: When adding a reg do a bsearch for target +node") which changed the order in which nodes are looked-up. + +Fixes: 6399aea629b0 ("regmap: rbtree: When adding a reg do a bsearch for target node") +Signed-off-by: Lars-Peter Clausen +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/regmap/regcache-rbtree.c | 38 +++++++++++++++++++++++++--------- + 1 file changed, 28 insertions(+), 10 deletions(-) + +--- a/drivers/base/regmap/regcache-rbtree.c ++++ b/drivers/base/regmap/regcache-rbtree.c +@@ -404,6 +404,7 @@ static int regcache_rbtree_write(struct + unsigned int new_base_reg, new_top_reg; + unsigned int min, max; + unsigned int max_dist; ++ unsigned int dist, best_dist = UINT_MAX; + + max_dist = map->reg_stride * sizeof(*rbnode_tmp) / + map->cache_word_size; +@@ -423,24 +424,41 @@ static int regcache_rbtree_write(struct + &base_reg, &top_reg); + + if (base_reg <= max && top_reg >= min) { +- new_base_reg = min(reg, base_reg); +- new_top_reg = max(reg, top_reg); +- } else { +- if (max < base_reg) +- node = node->rb_left; ++ if (reg < base_reg) ++ dist = base_reg - reg; ++ else if (reg > top_reg) ++ dist = reg - top_reg; + else +- node = node->rb_right; +- +- continue; ++ dist = 0; ++ if (dist < best_dist) { ++ rbnode = rbnode_tmp; ++ best_dist = dist; ++ new_base_reg = min(reg, base_reg); ++ new_top_reg = max(reg, top_reg); ++ } + } + +- ret = regcache_rbtree_insert_to_block(map, rbnode_tmp, ++ /* ++ * Keep looking, we want to choose the closest block, ++ * otherwise we might end up creating overlapping ++ * blocks, which breaks the rbtree. ++ */ ++ if (reg < base_reg) ++ node = node->rb_left; ++ else if (reg > top_reg) ++ node = node->rb_right; ++ else ++ break; ++ } ++ ++ if (rbnode) { ++ ret = regcache_rbtree_insert_to_block(map, rbnode, + new_base_reg, + new_top_reg, reg, + value); + if (ret) + return ret; +- rbtree_ctx->cached_rbnode = rbnode_tmp; ++ rbtree_ctx->cached_rbnode = rbnode; + return 0; + } + diff --git a/queue-4.7/scsi-ses-use-scsi_is_sas_rphy-instead-of-is_sas_attached.patch b/queue-4.7/scsi-ses-use-scsi_is_sas_rphy-instead-of-is_sas_attached.patch new file mode 100644 index 00000000000..d213cb3938a --- /dev/null +++ b/queue-4.7/scsi-ses-use-scsi_is_sas_rphy-instead-of-is_sas_attached.patch @@ -0,0 +1,36 @@ +From 835831c57e9b0cccc24e96a812542875471d75b5 Mon Sep 17 00:00:00 2001 +From: Johannes Thumshirn +Date: Wed, 17 Aug 2016 11:46:17 +0200 +Subject: scsi: ses: use scsi_is_sas_rphy instead of is_sas_attached + +From: Johannes Thumshirn + +commit 835831c57e9b0cccc24e96a812542875471d75b5 upstream. + +Use scsi_is_sas_rphy() instead of is_sas_attached() to decide whether we +should obtain the SAS address from a scsi device or not. This will +prevent us from tripping on the BUG_ON() in sas_sdev_to_rdev() if the +rphy isn't attached to the SAS transport class, like it is with hpsa's +logical devices. + +Fixes: 3f8d6f2a0 ('ses: fix discovery of SATA devices in SAS enclosures') +Signed-off-by: Johannes Thumshirn +Reviewed-by: James E.J. Bottomley +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/ses.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/scsi/ses.c ++++ b/drivers/scsi/ses.c +@@ -587,7 +587,7 @@ static void ses_match_to_enclosure(struc + + ses_enclosure_data_process(edev, to_scsi_device(edev->edev.parent), 0); + +- if (is_sas_attached(sdev)) ++ if (scsi_is_sas_rphy(&sdev->sdev_gendev)) + efd.addr = sas_get_address(sdev); + + if (efd.addr) { diff --git a/queue-4.7/series b/queue-4.7/series index 11200fb1718..5f4d31b83b6 100644 --- a/queue-4.7/series +++ b/queue-4.7/series @@ -114,3 +114,20 @@ pnfs-flexfiles-fix-layoutstat-periodic-reporting.patch lib-test_hash.c-fix-warning-in-preprocessor-symbol-evaluation.patch dmaengine-at_xdmac-fix-to-pass-correct-device-identity-to-free_irq.patch kvm-nvmx-postpone-vmcs-changes-on-msr_ia32_apicbase-write.patch +ceph-do-not-modify-fi-frag-in-need_reset_readdir.patch +ib-ipoib-fix-memory-corruption-in-ipoib-cm-mode-connect-flow.patch +ath10k-fix-get-rx_status-from-htt-context.patch +ib-core-fix-use-after-free-in-send_leave-function.patch +regmap-rbtree-avoid-overlapping-nodes.patch +scsi-ses-use-scsi_is_sas_rphy-instead-of-is_sas_attached.patch +ib-ipoib-don-t-allow-mc-joins-during-light-mc-flush.patch +ib-mlx4-fix-incorrect-mc-join-state-bit-masking-on-sr-iov.patch +ib-mlx4-fix-code-indentation-in-qp1-mad-flow.patch +ib-mlx4-use-correct-subnet-prefix-in-qp1-mads-under-sr-iov.patch +ib-mlx5-enable-mad_ifc-commands-for-ib-ports-only.patch +ib-mlx5-set-source-mac-address-in-fte.patch +batman-adv-remove-unused-callback-from-batadv_algo_ops-struct.patch +tpm_crb-drop-struct-resource-res-from-struct-crb_priv.patch +tpm_crb-fix-mapping-of-the-buffers.patch +aio-mark-aio-pseudo-fs-noexec.patch +dm-log-writes-fix-bug-with-too-large-bios.patch diff --git a/queue-4.7/tpm_crb-drop-struct-resource-res-from-struct-crb_priv.patch b/queue-4.7/tpm_crb-drop-struct-resource-res-from-struct-crb_priv.patch new file mode 100644 index 00000000000..d3aab5cbd21 --- /dev/null +++ b/queue-4.7/tpm_crb-drop-struct-resource-res-from-struct-crb_priv.patch @@ -0,0 +1,118 @@ +From 14ddfbf488a0223b19abf7e4634e6e676a91a12d Mon Sep 17 00:00:00 2001 +From: Jarkko Sakkinen +Date: Tue, 15 Mar 2016 21:41:40 +0200 +Subject: tpm_crb: drop struct resource res from struct crb_priv + +From: Jarkko Sakkinen + +commit 14ddfbf488a0223b19abf7e4634e6e676a91a12d upstream. + +The iomem resource is needed only temporarily so it is better to pass +it on instead of storing it permanently. Named the variable as io_res +so that the code better documents itself. + +Signed-off-by: Jarkko Sakkinen +Reviewed-by: Stefan Berger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tpm/tpm_crb.c | 29 ++++++++++++++++------------- + 1 file changed, 16 insertions(+), 13 deletions(-) + +--- a/drivers/char/tpm/tpm_crb.c ++++ b/drivers/char/tpm/tpm_crb.c +@@ -77,7 +77,6 @@ enum crb_flags { + + struct crb_priv { + unsigned int flags; +- struct resource res; + void __iomem *iobase; + struct crb_control_area __iomem *cca; + u8 __iomem *cmd; +@@ -224,19 +223,19 @@ static int crb_init(struct acpi_device * + + static int crb_check_resource(struct acpi_resource *ares, void *data) + { +- struct crb_priv *priv = data; ++ struct resource *io_res = data; + struct resource res; + + if (acpi_dev_resource_memory(ares, &res)) { +- priv->res = res; +- priv->res.name = NULL; ++ *io_res = res; ++ io_res->name = NULL; + } + + return 1; + } + + static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv, +- u64 start, u32 size) ++ struct resource *io_res, u64 start, u32 size) + { + struct resource new_res = { + .start = start, +@@ -248,50 +247,54 @@ static void __iomem *crb_map_res(struct + if (start != new_res.start) + return (void __iomem *) ERR_PTR(-EINVAL); + +- if (!resource_contains(&priv->res, &new_res)) ++ if (!resource_contains(io_res, &new_res)) + return devm_ioremap_resource(dev, &new_res); + +- return priv->iobase + (new_res.start - priv->res.start); ++ return priv->iobase + (new_res.start - io_res->start); + } + + static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, + struct acpi_table_tpm2 *buf) + { + struct list_head resources; ++ struct resource io_res; + struct device *dev = &device->dev; + u64 pa; + int ret; + + INIT_LIST_HEAD(&resources); + ret = acpi_dev_get_resources(device, &resources, crb_check_resource, +- priv); ++ &io_res); + if (ret < 0) + return ret; + acpi_dev_free_resource_list(&resources); + +- if (resource_type(&priv->res) != IORESOURCE_MEM) { ++ if (resource_type(&io_res) != IORESOURCE_MEM) { + dev_err(dev, + FW_BUG "TPM2 ACPI table does not define a memory resource\n"); + return -EINVAL; + } + +- priv->iobase = devm_ioremap_resource(dev, &priv->res); ++ priv->iobase = devm_ioremap_resource(dev, &io_res); + if (IS_ERR(priv->iobase)) + return PTR_ERR(priv->iobase); + +- priv->cca = crb_map_res(dev, priv, buf->control_address, 0x1000); ++ priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address, ++ 0x1000); + if (IS_ERR(priv->cca)) + return PTR_ERR(priv->cca); + + pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) | + (u64) ioread32(&priv->cca->cmd_pa_low); +- priv->cmd = crb_map_res(dev, priv, pa, ioread32(&priv->cca->cmd_size)); ++ priv->cmd = crb_map_res(dev, priv, &io_res, pa, ++ ioread32(&priv->cca->cmd_size)); + if (IS_ERR(priv->cmd)) + return PTR_ERR(priv->cmd); + + memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); + pa = le64_to_cpu(pa); +- priv->rsp = crb_map_res(dev, priv, pa, ioread32(&priv->cca->rsp_size)); ++ priv->rsp = crb_map_res(dev, priv, &io_res, pa, ++ ioread32(&priv->cca->rsp_size)); + return PTR_ERR_OR_ZERO(priv->rsp); + } + diff --git a/queue-4.7/tpm_crb-fix-mapping-of-the-buffers.patch b/queue-4.7/tpm_crb-fix-mapping-of-the-buffers.patch new file mode 100644 index 00000000000..c2cca0969b4 --- /dev/null +++ b/queue-4.7/tpm_crb-fix-mapping-of-the-buffers.patch @@ -0,0 +1,98 @@ +From 422eac3f7deae34dbaffd08e03e27f37a5394a56 Mon Sep 17 00:00:00 2001 +From: Jarkko Sakkinen +Date: Tue, 19 Apr 2016 12:54:18 +0300 +Subject: tpm_crb: fix mapping of the buffers + +From: Jarkko Sakkinen + +commit 422eac3f7deae34dbaffd08e03e27f37a5394a56 upstream. + +On my Lenovo x250 the following situation occurs: + +[18697.813871] tpm_crb MSFT0101:00: can't request region for resource +[mem 0xacdff080-0xacdfffff] + +The mapping of the control area overlaps the mapping of the command +buffer. The control area is mapped over page, which is not right. It +should mapped over sizeof(struct crb_control_area). + +Fixing this issue unmasks another issue. Command and response buffers +can overlap and they do interleave on this machine. According to the PTP +specification the overlapping means that they are mapped to the same +buffer. + +The commit has been also on a Haswell NUC where things worked before +applying this fix so that the both code paths for response buffer +initialization are tested. + +Cc: stable@vger.kernel.org +Fixes: 1bd047be37d9 ("tpm_crb: Use devm_ioremap_resource") +Signed-off-by: Jarkko Sakkinen +Reviewed-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tpm/tpm_crb.c | 39 ++++++++++++++++++++++++++++----------- + 1 file changed, 28 insertions(+), 11 deletions(-) + +--- a/drivers/char/tpm/tpm_crb.c ++++ b/drivers/char/tpm/tpm_crb.c +@@ -259,7 +259,10 @@ static int crb_map_io(struct acpi_device + struct list_head resources; + struct resource io_res; + struct device *dev = &device->dev; +- u64 pa; ++ u64 cmd_pa; ++ u32 cmd_size; ++ u64 rsp_pa; ++ u32 rsp_size; + int ret; + + INIT_LIST_HEAD(&resources); +@@ -280,22 +283,36 @@ static int crb_map_io(struct acpi_device + return PTR_ERR(priv->iobase); + + priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address, +- 0x1000); ++ sizeof(struct crb_control_area)); + if (IS_ERR(priv->cca)) + return PTR_ERR(priv->cca); + +- pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) | +- (u64) ioread32(&priv->cca->cmd_pa_low); +- priv->cmd = crb_map_res(dev, priv, &io_res, pa, +- ioread32(&priv->cca->cmd_size)); ++ cmd_pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) | ++ (u64) ioread32(&priv->cca->cmd_pa_low); ++ cmd_size = ioread32(&priv->cca->cmd_size); ++ priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size); + if (IS_ERR(priv->cmd)) + return PTR_ERR(priv->cmd); + +- memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); +- pa = le64_to_cpu(pa); +- priv->rsp = crb_map_res(dev, priv, &io_res, pa, +- ioread32(&priv->cca->rsp_size)); +- return PTR_ERR_OR_ZERO(priv->rsp); ++ memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8); ++ rsp_pa = le64_to_cpu(rsp_pa); ++ rsp_size = ioread32(&priv->cca->rsp_size); ++ ++ if (cmd_pa != rsp_pa) { ++ priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size); ++ return PTR_ERR_OR_ZERO(priv->rsp); ++ } ++ ++ /* According to the PTP specification, overlapping command and response ++ * buffer sizes must be identical. ++ */ ++ if (cmd_size != rsp_size) { ++ dev_err(dev, FW_BUG "overlapping command and response buffer sizes are not identical"); ++ return -EINVAL; ++ } ++ ++ priv->rsp = priv->cmd; ++ return 0; + } + + static int crb_acpi_add(struct acpi_device *device)