--- /dev/null
+From 5556e7e6d30e8e9b5ee51b0e5edd526ee80e5e36 Mon Sep 17 00:00:00 2001
+From: Tyler Hicks <tyhicks@canonical.com>
+Date: Wed, 5 Aug 2015 11:26:36 -0500
+Subject: eCryptfs: Invalidate dcache entries when lower i_nlink is zero
+
+From: Tyler Hicks <tyhicks@canonical.com>
+
+commit 5556e7e6d30e8e9b5ee51b0e5edd526ee80e5e36 upstream.
+
+Consider eCryptfs dcache entries to be stale when the corresponding
+lower inode's i_nlink count is zero. This solves a problem caused by the
+lower inode being directly modified, without going through the eCryptfs
+mount, leaving stale eCryptfs dentries cached and the eCryptfs inode's
+i_nlink count not being cleared.
+
+Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
+Reported-by: Richard Weinberger <richard@nod.at>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ecryptfs/dentry.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/fs/ecryptfs/dentry.c
++++ b/fs/ecryptfs/dentry.c
+@@ -45,20 +45,20 @@
+ static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
+ {
+ struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+- int rc;
+-
+- if (!(lower_dentry->d_flags & DCACHE_OP_REVALIDATE))
+- return 1;
++ int rc = 1;
+
+ if (flags & LOOKUP_RCU)
+ return -ECHILD;
+
+- rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
++ if (lower_dentry->d_flags & DCACHE_OP_REVALIDATE)
++ rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
++
+ if (d_really_is_positive(dentry)) {
+- struct inode *lower_inode =
+- ecryptfs_inode_to_lower(d_inode(dentry));
++ struct inode *inode = d_inode(dentry);
+
+- fsstack_copy_attr_all(d_inode(dentry), lower_inode);
++ fsstack_copy_attr_all(inode, ecryptfs_inode_to_lower(inode));
++ if (!inode->i_nlink)
++ return 0;
+ }
+ return rc;
+ }
--- /dev/null
+From b4cc0efea4f0bfa2477c56af406cfcf3d3e58680 Mon Sep 17 00:00:00 2001
+From: Hin-Tak Leung <htl10@users.sourceforge.net>
+Date: Wed, 9 Sep 2015 15:38:07 -0700
+Subject: hfs: fix B-tree corruption after insertion at position 0
+
+From: Hin-Tak Leung <htl10@users.sourceforge.net>
+
+commit b4cc0efea4f0bfa2477c56af406cfcf3d3e58680 upstream.
+
+Fix B-tree corruption when a new record is inserted at position 0 in the
+node in hfs_brec_insert().
+
+This is an identical change to the corresponding hfs b-tree code to Sergei
+Antonov's "hfsplus: fix B-tree corruption after insertion at position 0",
+to keep similar code paths in the hfs and hfsplus drivers in sync, where
+appropriate.
+
+Signed-off-by: Hin-Tak Leung <htl10@users.sourceforge.net>
+Cc: Sergei Antonov <saproj@gmail.com>
+Cc: Joe Perches <joe@perches.com>
+Reviewed-by: Vyacheslav Dubeyko <slava@dubeyko.com>
+Cc: Anton Altaparmakov <anton@tuxera.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Christoph Hellwig <hch@infradead.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/hfs/brec.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/fs/hfs/brec.c
++++ b/fs/hfs/brec.c
+@@ -131,13 +131,16 @@ skip:
+ hfs_bnode_write(node, entry, data_off + key_len, entry_len);
+ hfs_bnode_dump(node);
+
+- if (new_node) {
+- /* update parent key if we inserted a key
+- * at the start of the first node
+- */
+- if (!rec && new_node != node)
+- hfs_brec_update_parent(fd);
++ /*
++ * update parent key if we inserted a key
++ * at the start of the node and it is not the new node
++ */
++ if (!rec && new_node != node) {
++ hfs_bnode_read_key(node, fd->search_key, data_off + size);
++ hfs_brec_update_parent(fd);
++ }
+
++ if (new_node) {
+ hfs_bnode_put(fd->bnode);
+ if (!new_node->parent) {
+ hfs_btree_inc_height(tree);
+@@ -166,9 +169,6 @@ skip:
+ goto again;
+ }
+
+- if (!rec)
+- hfs_brec_update_parent(fd);
+-
+ return 0;
+ }
+
+@@ -366,6 +366,8 @@ again:
+ if (IS_ERR(parent))
+ return PTR_ERR(parent);
+ __hfs_brec_find(parent, fd);
++ if (fd->record < 0)
++ return -ENOENT;
+ hfs_bnode_dump(parent);
+ rec = fd->record;
+
--- /dev/null
+From 7cb74be6fd827e314f81df3c5889b87e4c87c569 Mon Sep 17 00:00:00 2001
+From: Hin-Tak Leung <htl10@users.sourceforge.net>
+Date: Wed, 9 Sep 2015 15:38:04 -0700
+Subject: hfs,hfsplus: cache pages correctly between bnode_create and bnode_free
+
+From: Hin-Tak Leung <htl10@users.sourceforge.net>
+
+commit 7cb74be6fd827e314f81df3c5889b87e4c87c569 upstream.
+
+Pages looked up by __hfs_bnode_create() (called by hfs_bnode_create() and
+hfs_bnode_find() for finding or creating pages corresponding to an inode)
+are immediately kmap()'ed and used (both read and write) and kunmap()'ed,
+and should not be page_cache_release()'ed until hfs_bnode_free().
+
+This patch fixes a problem I first saw in July 2012: merely running "du"
+on a large hfsplus-mounted directory a few times on a reasonably loaded
+system would get the hfsplus driver all confused and complaining about
+B-tree inconsistencies, and generates a "BUG: Bad page state". Most
+recently, I can generate this problem on up-to-date Fedora 22 with shipped
+kernel 4.0.5, by running "du /" (="/" + "/home" + "/mnt" + other smaller
+mounts) and "du /mnt" simultaneously on two windows, where /mnt is a
+lightly-used QEMU VM image of the full Mac OS X 10.9:
+
+$ df -i / /home /mnt
+Filesystem Inodes IUsed IFree IUse% Mounted on
+/dev/mapper/fedora-root 3276800 551665 2725135 17% /
+/dev/mapper/fedora-home 52879360 716221 52163139 2% /home
+/dev/nbd0p2 4294967295 1387818 4293579477 1% /mnt
+
+After applying the patch, I was able to run "du /" (60+ times) and "du
+/mnt" (150+ times) continuously and simultaneously for 6+ hours.
+
+There are many reports of the hfsplus driver getting confused under load
+and generating "BUG: Bad page state" or other similar issues over the
+years. [1]
+
+The unpatched code [2] has always been wrong since it entered the kernel
+tree. The only reason why it gets away with it is that the
+kmap/memcpy/kunmap follow very quickly after the page_cache_release() so
+the kernel has not had a chance to reuse the memory for something else,
+most of the time.
+
+The current RW driver appears to have followed the design and development
+of the earlier read-only hfsplus driver [3], where-by version 0.1 (Dec
+2001) had a B-tree node-centric approach to
+read_cache_page()/page_cache_release() per bnode_get()/bnode_put(),
+migrating towards version 0.2 (June 2002) of caching and releasing pages
+per inode extents. When the current RW code first entered the kernel [2]
+in 2005, there was an REF_PAGES conditional (and "//" commented out code)
+to switch between B-node centric paging to inode-centric paging. There
+was a mistake with the direction of one of the REF_PAGES conditionals in
+__hfs_bnode_create(). In a subsequent "remove debug code" commit [4], the
+read_cache_page()/page_cache_release() per bnode_get()/bnode_put() were
+removed, but a page_cache_release() was mistakenly left in (propagating
+the "REF_PAGES <-> !REF_PAGE" mistake), and the commented-out
+page_cache_release() in bnode_release() (which should be spanned by
+!REF_PAGES) was never enabled.
+
+References:
+[1]:
+Michael Fox, Apr 2013
+http://www.spinics.net/lists/linux-fsdevel/msg63807.html
+("hfsplus volume suddenly inaccessable after 'hfs: recoff %d too large'")
+
+Sasha Levin, Feb 2015
+http://lkml.org/lkml/2015/2/20/85 ("use after free")
+
+https://bugs.launchpad.net/ubuntu/+source/linux/+bug/740814
+https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1027887
+https://bugzilla.kernel.org/show_bug.cgi?id=42342
+https://bugzilla.kernel.org/show_bug.cgi?id=63841
+https://bugzilla.kernel.org/show_bug.cgi?id=78761
+
+[2]:
+http://git.kernel.org/cgit/linux/kernel/git/tglx/history.git/commit/\
+fs/hfs/bnode.c?id=d1081202f1d0ee35ab0beb490da4b65d4bc763db
+commit d1081202f1d0ee35ab0beb490da4b65d4bc763db
+Author: Andrew Morton <akpm@osdl.org>
+Date: Wed Feb 25 16:17:36 2004 -0800
+
+ [PATCH] HFS rewrite
+
+http://git.kernel.org/cgit/linux/kernel/git/tglx/history.git/commit/\
+fs/hfsplus/bnode.c?id=91556682e0bf004d98a529bf829d339abb98bbbd
+
+commit 91556682e0bf004d98a529bf829d339abb98bbbd
+Author: Andrew Morton <akpm@osdl.org>
+Date: Wed Feb 25 16:17:48 2004 -0800
+
+ [PATCH] HFS+ support
+
+[3]:
+http://sourceforge.net/projects/linux-hfsplus/
+
+http://sourceforge.net/projects/linux-hfsplus/files/Linux%202.4.x%20patch/hfsplus%200.1/
+http://sourceforge.net/projects/linux-hfsplus/files/Linux%202.4.x%20patch/hfsplus%200.2/
+
+http://linux-hfsplus.cvs.sourceforge.net/viewvc/linux-hfsplus/linux/\
+fs/hfsplus/bnode.c?r1=1.4&r2=1.5
+
+Date: Thu Jun 6 09:45:14 2002 +0000
+Use buffer cache instead of page cache in bnode.c. Cache inode extents.
+
+[4]:
+http://git.kernel.org/cgit/linux/kernel/git/\
+stable/linux-stable.git/commit/?id=a5e3985fa014029eb6795664c704953720cc7f7d
+
+commit a5e3985fa014029eb6795664c704953720cc7f7d
+Author: Roman Zippel <zippel@linux-m68k.org>
+Date: Tue Sep 6 15:18:47 2005 -0700
+
+[PATCH] hfs: remove debug code
+
+Signed-off-by: Hin-Tak Leung <htl10@users.sourceforge.net>
+Signed-off-by: Sergei Antonov <saproj@gmail.com>
+Reviewed-by: Anton Altaparmakov <anton@tuxera.com>
+Reported-by: Sasha Levin <sasha.levin@oracle.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Christoph Hellwig <hch@infradead.org>
+Cc: Vyacheslav Dubeyko <slava@dubeyko.com>
+Cc: Sougata Santra <sougata@tuxera.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/hfs/bnode.c | 9 ++++-----
+ fs/hfsplus/bnode.c | 3 ---
+ 2 files changed, 4 insertions(+), 8 deletions(-)
+
+--- a/fs/hfs/bnode.c
++++ b/fs/hfs/bnode.c
+@@ -288,7 +288,6 @@ static struct hfs_bnode *__hfs_bnode_cre
+ page_cache_release(page);
+ goto fail;
+ }
+- page_cache_release(page);
+ node->page[i] = page;
+ }
+
+@@ -398,11 +397,11 @@ node_error:
+
+ void hfs_bnode_free(struct hfs_bnode *node)
+ {
+- //int i;
++ int i;
+
+- //for (i = 0; i < node->tree->pages_per_bnode; i++)
+- // if (node->page[i])
+- // page_cache_release(node->page[i]);
++ for (i = 0; i < node->tree->pages_per_bnode; i++)
++ if (node->page[i])
++ page_cache_release(node->page[i]);
+ kfree(node);
+ }
+
+--- a/fs/hfsplus/bnode.c
++++ b/fs/hfsplus/bnode.c
+@@ -454,7 +454,6 @@ static struct hfs_bnode *__hfs_bnode_cre
+ page_cache_release(page);
+ goto fail;
+ }
+- page_cache_release(page);
+ node->page[i] = page;
+ }
+
+@@ -566,13 +565,11 @@ node_error:
+
+ void hfs_bnode_free(struct hfs_bnode *node)
+ {
+-#if 0
+ int i;
+
+ for (i = 0; i < node->tree->pages_per_bnode; i++)
+ if (node->page[i])
+ page_cache_release(node->page[i]);
+-#endif
+ kfree(node);
+ }
+
--- /dev/null
+From a4a9a8cb3248b3b48a6049acaeaf23d4ad3712b9 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 18 Aug 2015 12:12:19 +0300
+Subject: i2c: xgene-slimpro: dma_mapping_error() doesn't return an error code
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit a4a9a8cb3248b3b48a6049acaeaf23d4ad3712b9 upstream.
+
+The dma_mapping_error() function returns true if there is an error, it
+doesn't return an error code. We should return -ENOMEM.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviewed-by: Axel Lin <axel.lin@ingics.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i2c/busses/i2c-xgene-slimpro.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-xgene-slimpro.c
++++ b/drivers/i2c/busses/i2c-xgene-slimpro.c
+@@ -198,10 +198,10 @@ static int slimpro_i2c_blkrd(struct slim
+ int rc;
+
+ paddr = dma_map_single(ctx->dev, ctx->dma_buffer, readlen, DMA_FROM_DEVICE);
+- rc = dma_mapping_error(ctx->dev, paddr);
+- if (rc) {
++ if (dma_mapping_error(ctx->dev, paddr)) {
+ dev_err(&ctx->adapter.dev, "Error in mapping dma buffer %p\n",
+ ctx->dma_buffer);
++ rc = -ENOMEM;
+ goto err;
+ }
+
+@@ -241,10 +241,10 @@ static int slimpro_i2c_blkwr(struct slim
+ memcpy(ctx->dma_buffer, data, writelen);
+ paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen,
+ DMA_TO_DEVICE);
+- rc = dma_mapping_error(ctx->dev, paddr);
+- if (rc) {
++ if (dma_mapping_error(ctx->dev, paddr)) {
+ dev_err(&ctx->adapter.dev, "Error in mapping dma buffer %p\n",
+ ctx->dma_buffer);
++ rc = -ENOMEM;
+ goto err;
+ }
+
--- /dev/null
+From d16739055bd1f562ae4d83e69f7f7f1cefcfbe16 Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Thu, 6 Aug 2015 18:32:48 +0300
+Subject: IB/iser: Fix missing return status check in iser_send_data_out
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit d16739055bd1f562ae4d83e69f7f7f1cefcfbe16 upstream.
+
+Since commit "IB/iser: Fix race between iser connection teardown..."
+iser_initialize_task_headers() might fail, so we need to check that.
+
+Fixes: 7414dde0a6c3a958e (IB/iser: Fix race between iser connection ...)
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/iser/iser_initiator.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -454,7 +454,7 @@ int iser_send_data_out(struct iscsi_conn
+ unsigned long buf_offset;
+ unsigned long data_seg_len;
+ uint32_t itt;
+- int err = 0;
++ int err;
+ struct ib_sge *tx_dsg;
+
+ itt = (__force uint32_t)hdr->itt;
+@@ -475,7 +475,9 @@ int iser_send_data_out(struct iscsi_conn
+ memcpy(&tx_desc->iscsi_header, hdr, sizeof(struct iscsi_hdr));
+
+ /* build the tx desc */
+- iser_initialize_task_headers(task, tx_desc);
++ err = iser_initialize_task_headers(task, tx_desc);
++ if (err)
++ goto send_data_out_error;
+
+ mem_reg = &iser_task->rdma_reg[ISER_DIR_OUT];
+ tx_dsg = &tx_desc->tx_sg[1];
+@@ -502,7 +504,7 @@ int iser_send_data_out(struct iscsi_conn
+
+ send_data_out_error:
+ kmem_cache_free(ig.desc_cache, tx_desc);
+- iser_err("conn %p failed err %d\n",conn, err);
++ iser_err("conn %p failed err %d\n", conn, err);
+ return err;
+ }
+
--- /dev/null
+From 8d5944d80359e645feb2ebd069a6f4caf7825e40 Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Thu, 6 Aug 2015 18:32:50 +0300
+Subject: IB/iser: Fix possible bogus DMA unmapping
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit 8d5944d80359e645feb2ebd069a6f4caf7825e40 upstream.
+
+If iser_initialize_task_headers() routine failed before
+dma mapping, we should not attempt to unmap in cleanup_task().
+
+Fixes: 7414dde0a6c3a958e (IB/iser: Fix race between iser connection ...)
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/iser/iscsi_iser.c | 12 ++++++++----
+ drivers/infiniband/ulp/iser/iscsi_iser.h | 2 ++
+ 2 files changed, 10 insertions(+), 4 deletions(-)
+
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -201,6 +201,7 @@ iser_initialize_task_headers(struct iscs
+ goto out;
+ }
+
++ tx_desc->mapped = true;
+ tx_desc->dma_addr = dma_addr;
+ tx_desc->tx_sg[0].addr = tx_desc->dma_addr;
+ tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
+@@ -360,16 +361,19 @@ iscsi_iser_task_xmit(struct iscsi_task *
+ static void iscsi_iser_cleanup_task(struct iscsi_task *task)
+ {
+ struct iscsi_iser_task *iser_task = task->dd_data;
+- struct iser_tx_desc *tx_desc = &iser_task->desc;
+- struct iser_conn *iser_conn = task->conn->dd_data;
++ struct iser_tx_desc *tx_desc = &iser_task->desc;
++ struct iser_conn *iser_conn = task->conn->dd_data;
+ struct iser_device *device = iser_conn->ib_conn.device;
+
+ /* DEVICE_REMOVAL event might have already released the device */
+ if (!device)
+ return;
+
+- ib_dma_unmap_single(device->ib_device,
+- tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE);
++ if (likely(tx_desc->mapped)) {
++ ib_dma_unmap_single(device->ib_device, tx_desc->dma_addr,
++ ISER_HEADERS_LEN, DMA_TO_DEVICE);
++ tx_desc->mapped = false;
++ }
+
+ /* mgmt tasks do not need special cleanup */
+ if (!task->sc)
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -270,6 +270,7 @@ enum iser_desc_type {
+ * sg[1] optionally points to either of immediate data
+ * unsolicited data-out or control
+ * @num_sge: number sges used on this TX task
++ * @mapped: Is the task header mapped
+ */
+ struct iser_tx_desc {
+ struct iser_hdr iser_header;
+@@ -278,6 +279,7 @@ struct iser_tx_desc {
+ u64 dma_addr;
+ struct ib_sge tx_sg[2];
+ int num_sge;
++ bool mapped;
+ };
+
+ #define ISER_RX_PAD_SIZE (256 - (ISER_RX_PAYLOAD_SIZE + \
--- /dev/null
+From 799cdaf8a98f13d4fba3162e21e1e63f21045010 Mon Sep 17 00:00:00 2001
+From: Ariel Nahum <arieln@mellanox.com>
+Date: Sun, 9 Aug 2015 11:16:27 +0300
+Subject: IB/mlx4: Fix incorrect cq flushing in error state
+
+From: Ariel Nahum <arieln@mellanox.com>
+
+commit 799cdaf8a98f13d4fba3162e21e1e63f21045010 upstream.
+
+When handling a device internal error, the driver is responsible to
+drain the completion queue with flush errors.
+
+In case a completion queue was assigned to multiple send queues, the
+driver iterates over the send queues and generates flush errors of
+inflight wqes. The driver must correctly pass the wc array with an
+offset as a result of the previous send queue iteration. Not doing so
+will overwrite previously set completions and return a wrong number
+of polled completions which includes ones which were not correctly set.
+
+Fixes: 35f05dabf95a (IB/mlx4: Reset flow support for IB kernel ULPs)
+Signed-off-by: Ariel Nahum <arieln@mellanox.com>
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Cc: Yishai Hadas <yishaih@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx4/cq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/infiniband/hw/mlx4/cq.c
++++ b/drivers/infiniband/hw/mlx4/cq.c
+@@ -638,7 +638,7 @@ static void mlx4_ib_poll_sw_comp(struct
+ * simulated FLUSH_ERR completions
+ */
+ list_for_each_entry(qp, &cq->send_qp_list, cq_send_list) {
+- mlx4_ib_qp_sw_comp(qp, num_entries, wc, npolled, 1);
++ mlx4_ib_qp_sw_comp(qp, num_entries, wc + *npolled, npolled, 1);
+ if (*npolled >= num_entries)
+ goto out;
+ }
--- /dev/null
+From 90c1d8b6350cca9d8a234f03c77a317a7613bcee Mon Sep 17 00:00:00 2001
+From: Jack Morgenstein <jackm@dev.mellanox.co.il>
+Date: Thu, 30 Jul 2015 17:34:21 +0300
+Subject: IB/mlx4: Fix potential deadlock when sending mad to wire
+
+From: Jack Morgenstein <jackm@dev.mellanox.co.il>
+
+commit 90c1d8b6350cca9d8a234f03c77a317a7613bcee upstream.
+
+send_mad_to_wire takes the same spinlock that is taken in
+the interrupt context. Therefore, it needs irqsave/restore.
+
+Fixes: b9c5d6a64358 ('IB/mlx4: Add multicast group (MCG) paravirtualization for SR-IOV')
+Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx4/mcg.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/infiniband/hw/mlx4/mcg.c
++++ b/drivers/infiniband/hw/mlx4/mcg.c
+@@ -206,15 +206,16 @@ static int send_mad_to_wire(struct mlx4_
+ {
+ struct mlx4_ib_dev *dev = ctx->dev;
+ struct ib_ah_attr ah_attr;
++ unsigned long flags;
+
+- spin_lock(&dev->sm_lock);
++ spin_lock_irqsave(&dev->sm_lock, flags);
+ if (!dev->sm_ah[ctx->port - 1]) {
+ /* port is not yet Active, sm_ah not ready */
+- spin_unlock(&dev->sm_lock);
++ spin_unlock_irqrestore(&dev->sm_lock, flags);
+ return -EAGAIN;
+ }
+ mlx4_ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr);
+- spin_unlock(&dev->sm_lock);
++ spin_unlock_irqrestore(&dev->sm_lock, flags);
+ return mlx4_ib_send_to_wire(dev, mlx4_master_func_num(dev->dev),
+ ctx->port, IB_QPT_GSI, 0, 1, IB_QP1_QKEY,
+ &ah_attr, NULL, mad);
--- /dev/null
+From 2b135db3e81301d0452e6aa107349abe67b097d6 Mon Sep 17 00:00:00 2001
+From: Jack Morgenstein <jackm@dev.mellanox.co.il>
+Date: Thu, 30 Jul 2015 17:34:23 +0300
+Subject: IB/mlx4: Forbid using sysfs to change RoCE pkeys
+
+From: Jack Morgenstein <jackm@dev.mellanox.co.il>
+
+commit 2b135db3e81301d0452e6aa107349abe67b097d6 upstream.
+
+The pkey mapping for RoCE must remain the default mapping:
+VFs:
+ virtual index 0 = mapped to real index 0 (0xFFFF)
+ All others indices: mapped to a real pkey index containing an
+ invalid pkey.
+PF:
+ virtual index i = real index i.
+
+Don't allow users to change these mappings using files found in
+sysfs.
+
+Fixes: c1e7e466120b ('IB/mlx4: Add iov directory in sysfs under the ib device')
+Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx4/sysfs.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/infiniband/hw/mlx4/sysfs.c
++++ b/drivers/infiniband/hw/mlx4/sysfs.c
+@@ -640,6 +640,8 @@ static int add_port(struct mlx4_ib_dev *
+ struct mlx4_port *p;
+ int i;
+ int ret;
++ int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port_num) ==
++ IB_LINK_LAYER_ETHERNET;
+
+ p = kzalloc(sizeof *p, GFP_KERNEL);
+ if (!p)
+@@ -657,7 +659,8 @@ static int add_port(struct mlx4_ib_dev *
+
+ p->pkey_group.name = "pkey_idx";
+ p->pkey_group.attrs =
+- alloc_group_attrs(show_port_pkey, store_port_pkey,
++ alloc_group_attrs(show_port_pkey,
++ is_eth ? NULL : store_port_pkey,
+ dev->dev->caps.pkey_table_len[port_num]);
+ if (!p->pkey_group.attrs) {
+ ret = -ENOMEM;
--- /dev/null
+From 5e99b139f1b68acd65e36515ca347b03856dfb5a Mon Sep 17 00:00:00 2001
+From: Noa Osherovich <noaos@mellanox.com>
+Date: Thu, 30 Jul 2015 17:34:24 +0300
+Subject: IB/mlx4: Use correct SL on AH query under RoCE
+
+From: Noa Osherovich <noaos@mellanox.com>
+
+commit 5e99b139f1b68acd65e36515ca347b03856dfb5a upstream.
+
+The mlx4 IB driver implementation for ib_query_ah used a wrong offset
+(28 instead of 29) when link type is Ethernet. Fixed to use the correct one.
+
+Fixes: fa417f7b520e ('IB/mlx4: Add support for IBoE')
+Signed-off-by: Shani Michaeli <shanim@mellanox.com>
+Signed-off-by: Noa Osherovich <noaos@mellanox.com>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx4/ah.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/infiniband/hw/mlx4/ah.c
++++ b/drivers/infiniband/hw/mlx4/ah.c
+@@ -148,9 +148,13 @@ int mlx4_ib_query_ah(struct ib_ah *ibah,
+ enum rdma_link_layer ll;
+
+ memset(ah_attr, 0, sizeof *ah_attr);
+- ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
+ ah_attr->port_num = be32_to_cpu(ah->av.ib.port_pd) >> 24;
+ ll = rdma_port_get_link_layer(ibah->device, ah_attr->port_num);
++ if (ll == IB_LINK_LAYER_ETHERNET)
++ ah_attr->sl = be32_to_cpu(ah->av.eth.sl_tclass_flowlabel) >> 29;
++ else
++ ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
++
+ ah_attr->dlid = ll == IB_LINK_LAYER_INFINIBAND ? be16_to_cpu(ah->av.ib.dlid) : 0;
+ if (ah->av.ib.stat_rate)
+ ah_attr->static_rate = ah->av.ib.stat_rate - MLX4_STAT_RATE_OFFSET;
--- /dev/null
+From 11d748045c6dadb279d1acdb6d2ea8f3f2ede85b Mon Sep 17 00:00:00 2001
+From: Haggai Eran <haggaie@mellanox.com>
+Date: Tue, 1 Sep 2015 09:56:56 +0300
+Subject: IB/mlx5: avoid destroying a NULL mr in reg_user_mr error flow
+
+From: Haggai Eran <haggaie@mellanox.com>
+
+commit 11d748045c6dadb279d1acdb6d2ea8f3f2ede85b upstream.
+
+The mlx5_ib_reg_user_mr() function will attempt to call clean_mr() in
+its error flow even though there is never a case where the error flow
+occurs with a valid MR pointer to destroy.
+
+Remove the clean_mr() call and the incorrect comment above it.
+
+Fixes: b4cfe447d47b ("IB/mlx5: Implement on demand paging by adding
+support for MMU notifiers")
+Cc: Eli Cohen <eli@mellanox.com>
+Signed-off-by: Haggai Eran <haggaie@mellanox.com>
+Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx5/mr.c | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+--- a/drivers/infiniband/hw/mlx5/mr.c
++++ b/drivers/infiniband/hw/mlx5/mr.c
+@@ -1118,19 +1118,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct
+ return &mr->ibmr;
+
+ error:
+- /*
+- * Destroy the umem *before* destroying the MR, to ensure we
+- * will not have any in-flight notifiers when destroying the
+- * MR.
+- *
+- * As the MR is completely invalid to begin with, and this
+- * error path is only taken if we can't push the mr entry into
+- * the pagefault tree, this is safe.
+- */
+-
+ ib_umem_release(umem);
+- /* Kill the MR, and return an error code. */
+- clean_mr(mr);
+ return ERR_PTR(err);
+ }
+
--- /dev/null
+From d6f1c17e162b2a11e708f28fa93f2f79c164b442 Mon Sep 17 00:00:00 2001
+From: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Date: Tue, 21 Jul 2015 08:36:07 -0400
+Subject: IB/qib: Change lkey table allocation to support more MRs
+
+From: Mike Marciniszyn <mike.marciniszyn@intel.com>
+
+commit d6f1c17e162b2a11e708f28fa93f2f79c164b442 upstream.
+
+The lkey table is allocated with with a get_user_pages() with an
+order based on a number of index bits from a module parameter.
+
+The underlying kernel code cannot allocate that many contiguous pages.
+
+There is no reason the underlying memory needs to be physically
+contiguous.
+
+This patch:
+- switches the allocation/deallocation to vmalloc/vfree
+- caps the number of bits to 23 to insure at least 1 generation bit
+ o this matches the module parameter description
+
+Reviewed-by: Vinit Agnihotri <vinit.abhay.agnihotri@intel.com>
+Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/qib/qib_keys.c | 4 ++++
+ drivers/infiniband/hw/qib/qib_verbs.c | 14 ++++++++++----
+ drivers/infiniband/hw/qib/qib_verbs.h | 2 ++
+ 3 files changed, 16 insertions(+), 4 deletions(-)
+
+--- a/drivers/infiniband/hw/qib/qib_keys.c
++++ b/drivers/infiniband/hw/qib/qib_keys.c
+@@ -86,6 +86,10 @@ int qib_alloc_lkey(struct qib_mregion *m
+ * unrestricted LKEY.
+ */
+ rkt->gen++;
++ /*
++ * bits are capped in qib_verbs.c to insure enough bits
++ * for generation number
++ */
+ mr->lkey = (r << (32 - ib_qib_lkey_table_size)) |
+ ((((1 << (24 - ib_qib_lkey_table_size)) - 1) & rkt->gen)
+ << 8);
+--- a/drivers/infiniband/hw/qib/qib_verbs.c
++++ b/drivers/infiniband/hw/qib/qib_verbs.c
+@@ -40,6 +40,7 @@
+ #include <linux/rculist.h>
+ #include <linux/mm.h>
+ #include <linux/random.h>
++#include <linux/vmalloc.h>
+
+ #include "qib.h"
+ #include "qib_common.h"
+@@ -2109,10 +2110,16 @@ int qib_register_ib_device(struct qib_de
+ * the LKEY). The remaining bits act as a generation number or tag.
+ */
+ spin_lock_init(&dev->lk_table.lock);
++ /* insure generation is at least 4 bits see keys.c */
++ if (ib_qib_lkey_table_size > MAX_LKEY_TABLE_BITS) {
++ qib_dev_warn(dd, "lkey bits %u too large, reduced to %u\n",
++ ib_qib_lkey_table_size, MAX_LKEY_TABLE_BITS);
++ ib_qib_lkey_table_size = MAX_LKEY_TABLE_BITS;
++ }
+ dev->lk_table.max = 1 << ib_qib_lkey_table_size;
+ lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table);
+ dev->lk_table.table = (struct qib_mregion __rcu **)
+- __get_free_pages(GFP_KERNEL, get_order(lk_tab_size));
++ vmalloc(lk_tab_size);
+ if (dev->lk_table.table == NULL) {
+ ret = -ENOMEM;
+ goto err_lk;
+@@ -2286,7 +2293,7 @@ err_tx:
+ sizeof(struct qib_pio_header),
+ dev->pio_hdrs, dev->pio_hdrs_phys);
+ err_hdrs:
+- free_pages((unsigned long) dev->lk_table.table, get_order(lk_tab_size));
++ vfree(dev->lk_table.table);
+ err_lk:
+ kfree(dev->qp_table);
+ err_qpt:
+@@ -2340,8 +2347,7 @@ void qib_unregister_ib_device(struct qib
+ sizeof(struct qib_pio_header),
+ dev->pio_hdrs, dev->pio_hdrs_phys);
+ lk_tab_size = dev->lk_table.max * sizeof(*dev->lk_table.table);
+- free_pages((unsigned long) dev->lk_table.table,
+- get_order(lk_tab_size));
++ vfree(dev->lk_table.table);
+ kfree(dev->qp_table);
+ }
+
+--- a/drivers/infiniband/hw/qib/qib_verbs.h
++++ b/drivers/infiniband/hw/qib/qib_verbs.h
+@@ -647,6 +647,8 @@ struct qib_qpn_table {
+ struct qpn_map map[QPNMAP_ENTRIES];
+ };
+
++#define MAX_LKEY_TABLE_BITS 23
++
+ struct qib_lkey_table {
+ spinlock_t lock; /* protect changes in this struct */
+ u32 next; /* next unused index (speeds search) */
--- /dev/null
+From c257ea6f9f9aed0b173e0c2932bb8dac5612cdc6 Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@sandisk.com>
+Date: Fri, 31 Jul 2015 14:13:22 -0700
+Subject: IB/srp: Handle partial connection success correctly
+
+From: Bart Van Assche <bart.vanassche@sandisk.com>
+
+commit c257ea6f9f9aed0b173e0c2932bb8dac5612cdc6 upstream.
+
+Avoid that the following kernel warning is reported if the SRP
+target system accepts fewer channels per connection than what
+was requested by the initiator system:
+
+WARNING: at drivers/infiniband/ulp/srp/ib_srp.c:617 srp_destroy_qp+0xb1/0x120 [ib_srp]()
+Call Trace:
+[<ffffffff8105d67f>] warn_slowpath_common+0x7f/0xc0
+[<ffffffff8105d6da>] warn_slowpath_null+0x1a/0x20
+[<ffffffffa05419e1>] srp_destroy_qp+0xb1/0x120 [ib_srp]
+[<ffffffffa05445fb>] srp_create_ch_ib+0x19b/0x420 [ib_srp]
+[<ffffffffa0545257>] srp_create_target+0x7d7/0xa94 [ib_srp]
+[<ffffffff8138dac0>] dev_attr_store+0x20/0x30
+[<ffffffff812079ef>] sysfs_write_file+0xef/0x170
+[<ffffffff81191fc4>] vfs_write+0xb4/0x130
+[<ffffffff8119276f>] sys_write+0x5f/0xa0
+[<ffffffff815a0a59>] system_call_fastpath+0x16/0x1b
+
+Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
+Cc: Sagi Grimberg <sagig@mellanox.com>
+Cc: Sebastian Parschauer <sebastian.riemer@profitbricks.com>
+Cc: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/srp/ib_srp.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/infiniband/ulp/srp/ib_srp.c
++++ b/drivers/infiniband/ulp/srp/ib_srp.c
+@@ -3262,7 +3262,7 @@ static ssize_t srp_create_target(struct
+ srp_free_ch_ib(target, ch);
+ srp_free_req_data(target, ch);
+ target->ch_count = ch - target->ch;
+- break;
++ goto connected;
+ }
+ }
+
+@@ -3272,6 +3272,7 @@ static ssize_t srp_create_target(struct
+ node_idx++;
+ }
+
++connected:
+ target->scsi_host->nr_hw_queues = target->ch_count;
+
+ ret = srp_add_target(host, target);
--- /dev/null
+From bc44bd1d864664f3658352c6aaaa02557d49165d Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@sandisk.com>
+Date: Fri, 14 Aug 2015 11:01:09 -0700
+Subject: IB/srp: Stop the scsi_eh_<n> and scsi_tmf_<n> threads if login fails
+
+From: Bart Van Assche <bart.vanassche@sandisk.com>
+
+commit bc44bd1d864664f3658352c6aaaa02557d49165d upstream.
+
+scsi_host_alloc() not only allocates memory for a SCSI host but also
+creates the scsi_eh_<n> kernel thread and the scsi_tmf_<n> workqueue.
+Stop these threads if login fails by calling scsi_host_put().
+
+Reported-by: Konstantin Krotov <kkv@clodo.ru>
+Fixes: fb49c8bbaae7 ("Remove an extraneous scsi_host_put() from an error path")
+Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
+Cc: Sagi Grimberg <sagig@mellanox.com>
+Cc: Sebastian Parschauer <sebastian.riemer@profitbricks.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/srp/ib_srp.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/infiniband/ulp/srp/ib_srp.c
++++ b/drivers/infiniband/ulp/srp/ib_srp.c
+@@ -2757,6 +2757,13 @@ static int srp_sdev_count(struct Scsi_Ho
+ return c;
+ }
+
++/*
++ * Return values:
++ * < 0 upon failure. Caller is responsible for SRP target port cleanup.
++ * 0 and target->state == SRP_TARGET_REMOVED if asynchronous target port
++ * removal has been scheduled.
++ * 0 and target->state != SRP_TARGET_REMOVED upon success.
++ */
+ static int srp_add_target(struct srp_host *host, struct srp_target_port *target)
+ {
+ struct srp_rport_identifiers ids;
+@@ -3295,6 +3302,8 @@ out:
+ mutex_unlock(&host->add_target_mutex);
+
+ scsi_host_put(target->scsi_host);
++ if (ret < 0)
++ scsi_host_put(target->scsi_host);
+
+ return ret;
+
--- /dev/null
+From 35d4a0b63dc0c6d1177d4f532a9deae958f0662c Mon Sep 17 00:00:00 2001
+From: Yishai Hadas <yishaih@mellanox.com>
+Date: Thu, 13 Aug 2015 18:32:03 +0300
+Subject: IB/uverbs: Fix race between ib_uverbs_open and remove_one
+
+From: Yishai Hadas <yishaih@mellanox.com>
+
+commit 35d4a0b63dc0c6d1177d4f532a9deae958f0662c upstream.
+
+Fixes: 2a72f212263701b927559f6850446421d5906c41 ("IB/uverbs: Remove dev_table")
+
+Before this commit there was a device look-up table that was protected
+by a spin_lock used by ib_uverbs_open and by ib_uverbs_remove_one. When
+it was dropped and container_of was used instead, it enabled the race
+with remove_one as dev might be freed just after:
+dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev) but
+before the kref_get.
+
+In addition, this buggy patch added some dead code as
+container_of(x,y,z) can never be NULL and so dev can never be NULL.
+As a result the comment above ib_uverbs_open saying "the open method
+will either immediately run -ENXIO" is wrong as it can never happen.
+
+The solution follows Jason Gunthorpe suggestion from below URL:
+https://www.mail-archive.com/linux-rdma@vger.kernel.org/msg25692.html
+
+cdev will hold a kref on the parent (the containing structure,
+ib_uverbs_device) and only when that kref is released it is
+guaranteed that open will never be called again.
+
+In addition, fixes the active count scheme to use an atomic
+not a kref to prevent WARN_ON as pointed by above comment
+from Jason.
+
+Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
+Signed-off-by: Shachar Raindel <raindel@mellanox.com>
+Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/uverbs.h | 3 +-
+ drivers/infiniband/core/uverbs_main.c | 43 +++++++++++++++++++++++-----------
+ 2 files changed, 32 insertions(+), 14 deletions(-)
+
+--- a/drivers/infiniband/core/uverbs.h
++++ b/drivers/infiniband/core/uverbs.h
+@@ -85,7 +85,7 @@
+ */
+
+ struct ib_uverbs_device {
+- struct kref ref;
++ atomic_t refcount;
+ int num_comp_vectors;
+ struct completion comp;
+ struct device *dev;
+@@ -94,6 +94,7 @@ struct ib_uverbs_device {
+ struct cdev cdev;
+ struct rb_root xrcd_tree;
+ struct mutex xrcd_tree_mutex;
++ struct kobject kobj;
+ };
+
+ struct ib_uverbs_event_file {
+--- a/drivers/infiniband/core/uverbs_main.c
++++ b/drivers/infiniband/core/uverbs_main.c
+@@ -130,14 +130,18 @@ static int (*uverbs_ex_cmd_table[])(stru
+ static void ib_uverbs_add_one(struct ib_device *device);
+ static void ib_uverbs_remove_one(struct ib_device *device);
+
+-static void ib_uverbs_release_dev(struct kref *ref)
++static void ib_uverbs_release_dev(struct kobject *kobj)
+ {
+ struct ib_uverbs_device *dev =
+- container_of(ref, struct ib_uverbs_device, ref);
++ container_of(kobj, struct ib_uverbs_device, kobj);
+
+- complete(&dev->comp);
++ kfree(dev);
+ }
+
++static struct kobj_type ib_uverbs_dev_ktype = {
++ .release = ib_uverbs_release_dev,
++};
++
+ static void ib_uverbs_release_event_file(struct kref *ref)
+ {
+ struct ib_uverbs_event_file *file =
+@@ -303,13 +307,19 @@ static int ib_uverbs_cleanup_ucontext(st
+ return context->device->dealloc_ucontext(context);
+ }
+
++static void ib_uverbs_comp_dev(struct ib_uverbs_device *dev)
++{
++ complete(&dev->comp);
++}
++
+ static void ib_uverbs_release_file(struct kref *ref)
+ {
+ struct ib_uverbs_file *file =
+ container_of(ref, struct ib_uverbs_file, ref);
+
+ module_put(file->device->ib_dev->owner);
+- kref_put(&file->device->ref, ib_uverbs_release_dev);
++ if (atomic_dec_and_test(&file->device->refcount))
++ ib_uverbs_comp_dev(file->device);
+
+ kfree(file);
+ }
+@@ -743,9 +753,7 @@ static int ib_uverbs_open(struct inode *
+ int ret;
+
+ dev = container_of(inode->i_cdev, struct ib_uverbs_device, cdev);
+- if (dev)
+- kref_get(&dev->ref);
+- else
++ if (!atomic_inc_not_zero(&dev->refcount))
+ return -ENXIO;
+
+ if (!try_module_get(dev->ib_dev->owner)) {
+@@ -766,6 +774,7 @@ static int ib_uverbs_open(struct inode *
+ mutex_init(&file->mutex);
+
+ filp->private_data = file;
++ kobject_get(&dev->kobj);
+
+ return nonseekable_open(inode, filp);
+
+@@ -773,13 +782,16 @@ err_module:
+ module_put(dev->ib_dev->owner);
+
+ err:
+- kref_put(&dev->ref, ib_uverbs_release_dev);
++ if (atomic_dec_and_test(&dev->refcount))
++ ib_uverbs_comp_dev(dev);
++
+ return ret;
+ }
+
+ static int ib_uverbs_close(struct inode *inode, struct file *filp)
+ {
+ struct ib_uverbs_file *file = filp->private_data;
++ struct ib_uverbs_device *dev = file->device;
+
+ ib_uverbs_cleanup_ucontext(file, file->ucontext);
+
+@@ -787,6 +799,7 @@ static int ib_uverbs_close(struct inode
+ kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
+
+ kref_put(&file->ref, ib_uverbs_release_file);
++ kobject_put(&dev->kobj);
+
+ return 0;
+ }
+@@ -882,10 +895,11 @@ static void ib_uverbs_add_one(struct ib_
+ if (!uverbs_dev)
+ return;
+
+- kref_init(&uverbs_dev->ref);
++ atomic_set(&uverbs_dev->refcount, 1);
+ init_completion(&uverbs_dev->comp);
+ uverbs_dev->xrcd_tree = RB_ROOT;
+ mutex_init(&uverbs_dev->xrcd_tree_mutex);
++ kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype);
+
+ spin_lock(&map_lock);
+ devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
+@@ -912,6 +926,7 @@ static void ib_uverbs_add_one(struct ib_
+ cdev_init(&uverbs_dev->cdev, NULL);
+ uverbs_dev->cdev.owner = THIS_MODULE;
+ uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
++ uverbs_dev->cdev.kobj.parent = &uverbs_dev->kobj;
+ kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
+ if (cdev_add(&uverbs_dev->cdev, base, 1))
+ goto err_cdev;
+@@ -942,9 +957,10 @@ err_cdev:
+ clear_bit(devnum, overflow_map);
+
+ err:
+- kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
++ if (atomic_dec_and_test(&uverbs_dev->refcount))
++ ib_uverbs_comp_dev(uverbs_dev);
+ wait_for_completion(&uverbs_dev->comp);
+- kfree(uverbs_dev);
++ kobject_put(&uverbs_dev->kobj);
+ return;
+ }
+
+@@ -964,9 +980,10 @@ static void ib_uverbs_remove_one(struct
+ else
+ clear_bit(uverbs_dev->devnum - IB_UVERBS_MAX_DEVICES, overflow_map);
+
+- kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
++ if (atomic_dec_and_test(&uverbs_dev->refcount))
++ ib_uverbs_comp_dev(uverbs_dev);
+ wait_for_completion(&uverbs_dev->comp);
+- kfree(uverbs_dev);
++ kobject_put(&uverbs_dev->kobj);
+ }
+
+ static char *uverbs_devnode(struct device *dev, umode_t *mode)
--- /dev/null
+From b632ffa7cee439ba5dce3b3bc4a5cbe2b3e20133 Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch@lst.de>
+Date: Wed, 26 Aug 2015 11:00:37 +0200
+Subject: IB/uverbs: reject invalid or unknown opcodes
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit b632ffa7cee439ba5dce3b3bc4a5cbe2b3e20133 upstream.
+
+We have many WR opcodes that are only supported in kernel space
+and/or require optional information to be copied into the WR
+structure. Reject all those not explicitly handled so that we
+can't pass invalid information to drivers.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/uverbs_cmd.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/drivers/infiniband/core/uverbs_cmd.c
++++ b/drivers/infiniband/core/uverbs_cmd.c
+@@ -2346,6 +2346,12 @@ ssize_t ib_uverbs_post_send(struct ib_uv
+ next->send_flags = user_wr->send_flags;
+
+ if (is_ud) {
++ if (next->opcode != IB_WR_SEND &&
++ next->opcode != IB_WR_SEND_WITH_IMM) {
++ ret = -EINVAL;
++ goto out_put;
++ }
++
+ next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
+ file->ucontext);
+ if (!next->wr.ud.ah) {
+@@ -2385,9 +2391,11 @@ ssize_t ib_uverbs_post_send(struct ib_uv
+ user_wr->wr.atomic.compare_add;
+ next->wr.atomic.swap = user_wr->wr.atomic.swap;
+ next->wr.atomic.rkey = user_wr->wr.atomic.rkey;
++ case IB_WR_SEND:
+ break;
+ default:
+- break;
++ ret = -EINVAL;
++ goto out_put;
+ }
+ }
+
--- /dev/null
+From fa92a31b3335478c545cdc8e79e1e9b788184e6b Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 10 Aug 2015 10:45:45 +0200
+Subject: ideapad-laptop: Add Lenovo Yoga 3 14 to no_hw_rfkill dmi list
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit fa92a31b3335478c545cdc8e79e1e9b788184e6b upstream.
+
+Like some of the other Yoga models the Lenovo Yoga 3 14 does not have a
+hw rfkill switch, and trying to read the hw rfkill switch through the
+ideapad module causes it to always reported blocking breaking wifi.
+
+This commit adds the Lenovo Yoga 3 14 to the no_hw_rfkill dmi list, fixing
+the wifi breakage.
+
+BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1239050
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Darren Hart <dvhart@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/platform/x86/ideapad-laptop.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -853,6 +853,13 @@ static const struct dmi_system_id no_hw_
+ },
+ },
+ {
++ .ident = "Lenovo Yoga 3 14",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3 14"),
++ },
++ },
++ {
+ .ident = "Lenovo Yoga 3 Pro 1370",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
--- /dev/null
+From 2d3862d26e67a59340ba1cf1748196c76c5787de Mon Sep 17 00:00:00 2001
+From: Yinghai Lu <yinghai@kernel.org>
+Date: Wed, 9 Sep 2015 15:39:12 -0700
+Subject: lib/decompressors: use real out buf size for gunzip with kernel
+
+From: Yinghai Lu <yinghai@kernel.org>
+
+commit 2d3862d26e67a59340ba1cf1748196c76c5787de upstream.
+
+When loading x86 64bit kernel above 4GiB with patched grub2, got kernel
+gunzip error.
+
+| early console in decompress_kernel
+| decompress_kernel:
+| input: [0x807f2143b4-0x807ff61aee]
+| output: [0x807cc00000-0x807f3ea29b] 0x027ea29c: output_len
+| boot via startup_64
+| KASLR using RDTSC...
+| new output: [0x46fe000000-0x470138cfff] 0x0338d000: output_run_size
+| decompress: [0x46fe000000-0x47007ea29b] <=== [0x807f2143b4-0x807ff61aee]
+|
+| Decompressing Linux... gz...
+|
+| uncompression error
+|
+| -- System halted
+
+the new buffer is at 0x46fe000000ULL, decompressor_gzip is using
+0xffffffb901ffffff as out_len. gunzip in lib/zlib_inflate/inflate.c cap
+that len to 0x01ffffff and decompress fails later.
+
+We could hit this problem with crashkernel booting that uses kexec loading
+kernel above 4GiB.
+
+We have decompress_* support:
+ 1. inbuf[]/outbuf[] for kernel preboot.
+ 2. inbuf[]/flush() for initramfs
+ 3. fill()/flush() for initrd.
+This bug only affect kernel preboot path that use outbuf[].
+
+Add __decompress and take real out_buf_len for gunzip instead of guessing
+wrong buf size.
+
+Fixes: 1431574a1c4 (lib/decompressors: fix "no limit" output buffer length)
+Signed-off-by: Yinghai Lu <yinghai@kernel.org>
+Cc: Alexandre Courbot <acourbot@nvidia.com>
+Cc: Jon Medhurst <tixy@linaro.org>
+Cc: Stephen Warren <swarren@wwwdotorg.org>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Ingo Molnar <mingo@redhat.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm/boot/compressed/decompress.c | 2 +-
+ arch/h8300/boot/compressed/misc.c | 2 +-
+ arch/m32r/boot/compressed/misc.c | 3 ++-
+ arch/mips/boot/compressed/decompress.c | 4 ++--
+ arch/s390/boot/compressed/misc.c | 2 +-
+ arch/sh/boot/compressed/misc.c | 2 +-
+ arch/unicore32/boot/compressed/misc.c | 4 ++--
+ arch/x86/boot/compressed/misc.c | 3 ++-
+ lib/decompress_bunzip2.c | 6 +++---
+ lib/decompress_inflate.c | 31 ++++++++++++++++++++++++++-----
+ lib/decompress_unlz4.c | 6 +++---
+ lib/decompress_unlzma.c | 7 +++----
+ lib/decompress_unlzo.c | 13 ++++++++++++-
+ lib/decompress_unxz.c | 12 +++++++++++-
+ 14 files changed, 70 insertions(+), 27 deletions(-)
+
+--- a/arch/arm/boot/compressed/decompress.c
++++ b/arch/arm/boot/compressed/decompress.c
+@@ -57,5 +57,5 @@ extern char * strstr(const char * s1, co
+
+ int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
+ {
+- return decompress(input, len, NULL, NULL, output, NULL, error);
++ return __decompress(input, len, NULL, NULL, output, 0, NULL, error);
+ }
+--- a/arch/h8300/boot/compressed/misc.c
++++ b/arch/h8300/boot/compressed/misc.c
+@@ -70,5 +70,5 @@ void decompress_kernel(void)
+ free_mem_ptr = (unsigned long)&_end;
+ free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
+
+- decompress(input_data, input_len, NULL, NULL, output, NULL, error);
++ __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
+ }
+--- a/arch/m32r/boot/compressed/misc.c
++++ b/arch/m32r/boot/compressed/misc.c
+@@ -86,6 +86,7 @@ decompress_kernel(int mmu_on, unsigned c
+ free_mem_end_ptr = free_mem_ptr + BOOT_HEAP_SIZE;
+
+ puts("\nDecompressing Linux... ");
+- decompress(input_data, input_len, NULL, NULL, output_data, NULL, error);
++ __decompress(input_data, input_len, NULL, NULL, output_data, 0,
++ NULL, error);
+ puts("done.\nBooting the kernel.\n");
+ }
+--- a/arch/mips/boot/compressed/decompress.c
++++ b/arch/mips/boot/compressed/decompress.c
+@@ -111,8 +111,8 @@ void decompress_kernel(unsigned long boo
+ puts("\n");
+
+ /* Decompress the kernel with according algorithm */
+- decompress((char *)zimage_start, zimage_size, 0, 0,
+- (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, error);
++ __decompress((char *)zimage_start, zimage_size, 0, 0,
++ (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, 0, error);
+
+ /* FIXME: should we flush cache here? */
+ puts("Now, booting the kernel...\n");
+--- a/arch/s390/boot/compressed/misc.c
++++ b/arch/s390/boot/compressed/misc.c
+@@ -167,7 +167,7 @@ unsigned long decompress_kernel(void)
+ #endif
+
+ puts("Uncompressing Linux... ");
+- decompress(input_data, input_len, NULL, NULL, output, NULL, error);
++ __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
+ puts("Ok, booting the kernel.\n");
+ return (unsigned long) output;
+ }
+--- a/arch/sh/boot/compressed/misc.c
++++ b/arch/sh/boot/compressed/misc.c
+@@ -132,7 +132,7 @@ void decompress_kernel(void)
+
+ puts("Uncompressing Linux... ");
+ cache_control(CACHE_ENABLE);
+- decompress(input_data, input_len, NULL, NULL, output, NULL, error);
++ __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
+ cache_control(CACHE_DISABLE);
+ puts("Ok, booting the kernel.\n");
+ }
+--- a/arch/unicore32/boot/compressed/misc.c
++++ b/arch/unicore32/boot/compressed/misc.c
+@@ -119,8 +119,8 @@ unsigned long decompress_kernel(unsigned
+ output_ptr = get_unaligned_le32(tmp);
+
+ arch_decomp_puts("Uncompressing Linux...");
+- decompress(input_data, input_data_end - input_data, NULL, NULL,
+- output_data, NULL, error);
++ __decompress(input_data, input_data_end - input_data, NULL, NULL,
++ output_data, 0, NULL, error);
+ arch_decomp_puts(" done, booting the kernel.\n");
+ return output_ptr;
+ }
+--- a/arch/x86/boot/compressed/misc.c
++++ b/arch/x86/boot/compressed/misc.c
+@@ -424,7 +424,8 @@ asmlinkage __visible void *decompress_ke
+ #endif
+
+ debug_putstr("\nDecompressing Linux... ");
+- decompress(input_data, input_len, NULL, NULL, output, NULL, error);
++ __decompress(input_data, input_len, NULL, NULL, output, output_len,
++ NULL, error);
+ parse_elf(output);
+ /*
+ * 32-bit always performs relocations. 64-bit relocations are only
+--- a/lib/decompress_bunzip2.c
++++ b/lib/decompress_bunzip2.c
+@@ -743,12 +743,12 @@ exit_0:
+ }
+
+ #ifdef PREBOOT
+-STATIC int INIT decompress(unsigned char *buf, long len,
++STATIC int INIT __decompress(unsigned char *buf, long len,
+ long (*fill)(void*, unsigned long),
+ long (*flush)(void*, unsigned long),
+- unsigned char *outbuf,
++ unsigned char *outbuf, long olen,
+ long *pos,
+- void(*error)(char *x))
++ void (*error)(char *x))
+ {
+ return bunzip2(buf, len - 4, fill, flush, outbuf, pos, error);
+ }
+--- a/lib/decompress_inflate.c
++++ b/lib/decompress_inflate.c
+@@ -1,4 +1,5 @@
+ #ifdef STATIC
++#define PREBOOT
+ /* Pre-boot environment: included */
+
+ /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
+@@ -33,23 +34,23 @@ static long INIT nofill(void *buffer, un
+ }
+
+ /* Included from initramfs et al code */
+-STATIC int INIT gunzip(unsigned char *buf, long len,
++STATIC int INIT __gunzip(unsigned char *buf, long len,
+ long (*fill)(void*, unsigned long),
+ long (*flush)(void*, unsigned long),
+- unsigned char *out_buf,
++ unsigned char *out_buf, long out_len,
+ long *pos,
+ void(*error)(char *x)) {
+ u8 *zbuf;
+ struct z_stream_s *strm;
+ int rc;
+- size_t out_len;
+
+ rc = -1;
+ if (flush) {
+ out_len = 0x8000; /* 32 K */
+ out_buf = malloc(out_len);
+ } else {
+- out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
++ if (!out_len)
++ out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
+ }
+ if (!out_buf) {
+ error("Out of memory while allocating output buffer");
+@@ -181,4 +182,24 @@ gunzip_nomem1:
+ return rc; /* returns Z_OK (0) if successful */
+ }
+
+-#define decompress gunzip
++#ifndef PREBOOT
++STATIC int INIT gunzip(unsigned char *buf, long len,
++ long (*fill)(void*, unsigned long),
++ long (*flush)(void*, unsigned long),
++ unsigned char *out_buf,
++ long *pos,
++ void (*error)(char *x))
++{
++ return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error);
++}
++#else
++STATIC int INIT __decompress(unsigned char *buf, long len,
++ long (*fill)(void*, unsigned long),
++ long (*flush)(void*, unsigned long),
++ unsigned char *out_buf, long out_len,
++ long *pos,
++ void (*error)(char *x))
++{
++ return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error);
++}
++#endif
+--- a/lib/decompress_unlz4.c
++++ b/lib/decompress_unlz4.c
+@@ -196,12 +196,12 @@ exit_0:
+ }
+
+ #ifdef PREBOOT
+-STATIC int INIT decompress(unsigned char *buf, long in_len,
++STATIC int INIT __decompress(unsigned char *buf, long in_len,
+ long (*fill)(void*, unsigned long),
+ long (*flush)(void*, unsigned long),
+- unsigned char *output,
++ unsigned char *output, long out_len,
+ long *posp,
+- void(*error)(char *x)
++ void (*error)(char *x)
+ )
+ {
+ return unlz4(buf, in_len - 4, fill, flush, output, posp, error);
+--- a/lib/decompress_unlzma.c
++++ b/lib/decompress_unlzma.c
+@@ -667,13 +667,12 @@ exit_0:
+ }
+
+ #ifdef PREBOOT
+-STATIC int INIT decompress(unsigned char *buf, long in_len,
++STATIC int INIT __decompress(unsigned char *buf, long in_len,
+ long (*fill)(void*, unsigned long),
+ long (*flush)(void*, unsigned long),
+- unsigned char *output,
++ unsigned char *output, long out_len,
+ long *posp,
+- void(*error)(char *x)
+- )
++ void (*error)(char *x))
+ {
+ return unlzma(buf, in_len - 4, fill, flush, output, posp, error);
+ }
+--- a/lib/decompress_unlzo.c
++++ b/lib/decompress_unlzo.c
+@@ -31,6 +31,7 @@
+ */
+
+ #ifdef STATIC
++#define PREBOOT
+ #include "lzo/lzo1x_decompress_safe.c"
+ #else
+ #include <linux/decompress/unlzo.h>
+@@ -287,4 +288,14 @@ exit:
+ return ret;
+ }
+
+-#define decompress unlzo
++#ifdef PREBOOT
++STATIC int INIT __decompress(unsigned char *buf, long len,
++ long (*fill)(void*, unsigned long),
++ long (*flush)(void*, unsigned long),
++ unsigned char *out_buf, long olen,
++ long *pos,
++ void (*error)(char *x))
++{
++ return unlzo(buf, len, fill, flush, out_buf, pos, error);
++}
++#endif
+--- a/lib/decompress_unxz.c
++++ b/lib/decompress_unxz.c
+@@ -394,4 +394,14 @@ error_alloc_state:
+ * This macro is used by architecture-specific files to decompress
+ * the kernel image.
+ */
+-#define decompress unxz
++#ifdef XZ_PREBOOT
++STATIC int INIT __decompress(unsigned char *buf, long len,
++ long (*fill)(void*, unsigned long),
++ long (*flush)(void*, unsigned long),
++ unsigned char *out_buf, long olen,
++ long *pos,
++ void (*error)(char *x))
++{
++ return unxz(buf, len, fill, flush, out_buf, pos, error);
++}
++#endif
iommu-io-pgtable-arm-unmap-and-free-table-when-overwriting-with-block.patch
iommu-tegra-smmu-parameterize-number-of-tlb-lines.patch
iommu-vt-d-really-use-upper-context-table-when-necessary.patch
+ecryptfs-invalidate-dcache-entries-when-lower-i_nlink-is-zero.patch
+hfs-fix-b-tree-corruption-after-insertion-at-position-0.patch
+i2c-xgene-slimpro-dma_mapping_error-doesn-t-return-an-error-code.patch
+ideapad-laptop-add-lenovo-yoga-3-14-to-no_hw_rfkill-dmi-list.patch
+ib-srp-handle-partial-connection-success-correctly.patch
+ib-srp-stop-the-scsi_eh_-n-and-scsi_tmf_-n-threads-if-login-fails.patch
+ib-qib-change-lkey-table-allocation-to-support-more-mrs.patch
+ib-uverbs-reject-invalid-or-unknown-opcodes.patch
+ib-uverbs-fix-race-between-ib_uverbs_open-and-remove_one.patch
+ib-iser-fix-missing-return-status-check-in-iser_send_data_out.patch
+ib-iser-fix-possible-bogus-dma-unmapping.patch
+ib-mlx5-avoid-destroying-a-null-mr-in-reg_user_mr-error-flow.patch
+ib-mlx4-fix-potential-deadlock-when-sending-mad-to-wire.patch
+ib-mlx4-forbid-using-sysfs-to-change-roce-pkeys.patch
+ib-mlx4-use-correct-sl-on-ah-query-under-roce.patch
+ib-mlx4-fix-incorrect-cq-flushing-in-error-state.patch
+stmmac-fix-check-for-phydev-being-open.patch
+hfs-hfsplus-cache-pages-correctly-between-bnode_create-and-bnode_free.patch
+lib-decompressors-use-real-out-buf-size-for-gunzip-with-kernel.patch
--- /dev/null
+From dfc50fcaad574e5c8c85cbc83eca1426b2413fa4 Mon Sep 17 00:00:00 2001
+From: Alexey Brodkin <Alexey.Brodkin@synopsys.com>
+Date: Wed, 9 Sep 2015 18:01:08 +0300
+Subject: stmmac: fix check for phydev being open
+
+From: Alexey Brodkin <Alexey.Brodkin@synopsys.com>
+
+commit dfc50fcaad574e5c8c85cbc83eca1426b2413fa4 upstream.
+
+Current check of phydev with IS_ERR(phydev) may make not much sense
+because of_phy_connect() returns NULL on failure instead of error value.
+
+Still for checking result of phy_connect() IS_ERR() makes perfect sense.
+
+So let's use combined check IS_ERR_OR_NULL() that covers both cases.
+
+Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+Cc: linux-kernel@vger.kernel.org
+Cc: David Miller <davem@davemloft.net>
+Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -837,8 +837,11 @@ static int stmmac_init_phy(struct net_de
+ interface);
+ }
+
+- if (IS_ERR(phydev)) {
++ if (IS_ERR_OR_NULL(phydev)) {
+ pr_err("%s: Could not attach to PHY\n", dev->name);
++ if (!phydev)
++ return -ENODEV;
++
+ return PTR_ERR(phydev);
+ }
+