]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Mar 2015 14:16:29 +0000 (15:16 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Mar 2015 14:16:29 +0000 (15:16 +0100)
added patches:
ib-core-fix-deadlock-on-uverbs-modify_qp-error-flow.patch
ib-core-properly-handle-registration-of-on-demand-paging-mrs-after-dereg.patch
ib-core-when-marshaling-ucma-path-from-user-space-clear-unused-fields.patch
ib-iser-fix-memory-regions-possible-leak.patch
ib-iser-use-correct-dma-direction-when-unmapping-sgs.patch
ib-mlx4-fix-memory-leak-in-__mlx4_ib_modify_qp.patch
ib-mlx4-fix-wrong-usage-of-ipv4-protocol-for-multicast-attach-detach.patch
ib-mlx5-fix-error-code-in-get_port_caps.patch
ib-qib-do-not-write-eeprom.patch
locking-rtmutex-avoid-a-null-pointer-dereference-on-deadlock.patch
sg-fix-read-error-reporting.patch

12 files changed:
queue-3.19/ib-core-fix-deadlock-on-uverbs-modify_qp-error-flow.patch [new file with mode: 0644]
queue-3.19/ib-core-properly-handle-registration-of-on-demand-paging-mrs-after-dereg.patch [new file with mode: 0644]
queue-3.19/ib-core-when-marshaling-ucma-path-from-user-space-clear-unused-fields.patch [new file with mode: 0644]
queue-3.19/ib-iser-fix-memory-regions-possible-leak.patch [new file with mode: 0644]
queue-3.19/ib-iser-use-correct-dma-direction-when-unmapping-sgs.patch [new file with mode: 0644]
queue-3.19/ib-mlx4-fix-memory-leak-in-__mlx4_ib_modify_qp.patch [new file with mode: 0644]
queue-3.19/ib-mlx4-fix-wrong-usage-of-ipv4-protocol-for-multicast-attach-detach.patch [new file with mode: 0644]
queue-3.19/ib-mlx5-fix-error-code-in-get_port_caps.patch [new file with mode: 0644]
queue-3.19/ib-qib-do-not-write-eeprom.patch [new file with mode: 0644]
queue-3.19/locking-rtmutex-avoid-a-null-pointer-dereference-on-deadlock.patch [new file with mode: 0644]
queue-3.19/series
queue-3.19/sg-fix-read-error-reporting.patch [new file with mode: 0644]

diff --git a/queue-3.19/ib-core-fix-deadlock-on-uverbs-modify_qp-error-flow.patch b/queue-3.19/ib-core-fix-deadlock-on-uverbs-modify_qp-error-flow.patch
new file mode 100644 (file)
index 0000000..144ae2b
--- /dev/null
@@ -0,0 +1,51 @@
+From 0fb8bcf022f19a375d7c4bd79ac513da8ae6d78b Mon Sep 17 00:00:00 2001
+From: Moshe Lazer <moshel@mellanox.com>
+Date: Thu, 5 Feb 2015 13:53:52 +0200
+Subject: IB/core: Fix deadlock on uverbs modify_qp error flow
+
+From: Moshe Lazer <moshel@mellanox.com>
+
+commit 0fb8bcf022f19a375d7c4bd79ac513da8ae6d78b upstream.
+
+The deadlock occurs in __uverbs_modify_qp: we take a lock (idr_read_qp)
+and in case of failure in ib_resolve_eth_l2_attrs we don't release
+it (put_qp_read).  Fix that.
+
+Fixes: ed4c54e5b4ba ("IB/core: Resolve Ethernet L2 addresses when modifying QP")
+Signed-off-by: Moshe Lazer <moshel@mellanox.com>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/uverbs_cmd.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/infiniband/core/uverbs_cmd.c
++++ b/drivers/infiniband/core/uverbs_cmd.c
+@@ -2091,20 +2091,21 @@ ssize_t ib_uverbs_modify_qp(struct ib_uv
+       if (qp->real_qp == qp) {
+               ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask);
+               if (ret)
+-                      goto out;
++                      goto release_qp;
+               ret = qp->device->modify_qp(qp, attr,
+                       modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+       } else {
+               ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+       }
+-      put_qp_read(qp);
+-
+       if (ret)
+-              goto out;
++              goto release_qp;
+       ret = in_len;
++release_qp:
++      put_qp_read(qp);
++
+ out:
+       kfree(attr);
diff --git a/queue-3.19/ib-core-properly-handle-registration-of-on-demand-paging-mrs-after-dereg.patch b/queue-3.19/ib-core-properly-handle-registration-of-on-demand-paging-mrs-after-dereg.patch
new file mode 100644 (file)
index 0000000..c02b4f8
--- /dev/null
@@ -0,0 +1,44 @@
+From 4fc701ead77ede96df3e8b3de13fdf2b1326ee5b Mon Sep 17 00:00:00 2001
+From: Haggai Eran <haggaie@mellanox.com>
+Date: Tue, 6 Jan 2015 13:56:02 +0200
+Subject: IB/core: Properly handle registration of on-demand paging MRs after dereg
+
+From: Haggai Eran <haggaie@mellanox.com>
+
+commit 4fc701ead77ede96df3e8b3de13fdf2b1326ee5b upstream.
+
+When the last on-demand paging MR is released the notifier count is
+left non-zero so that concurrent page faults will have to abort. If a
+new MR is then registered, the counter is reset. However, the decision
+is made to put the new MR in the list waiting for the notifier count
+to reach zero, before the counter is reset. An invalidation or another
+MR registration can release the MR to handle page faults, but without
+such an event the MR can wait forever.
+
+The patch fixes this issue by adding a check whether the MR is the
+first on-demand paging MR when deciding whether it is ready to handle
+page faults. If it is the first MR, we know that there are no mmu
+notifiers running in parallel to the registration.
+
+Fixes: 882214e2b128 ("IB/core: Implement support for MMU notifiers regarding on demand paging regions")
+Signed-off-by: Haggai Eran <haggaie@mellanox.com>
+Signed-off-by: Shachar Raindel <raindel@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/umem_odp.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/infiniband/core/umem_odp.c
++++ b/drivers/infiniband/core/umem_odp.c
+@@ -294,7 +294,8 @@ int ib_umem_odp_get(struct ib_ucontext *
+       if (likely(ib_umem_start(umem) != ib_umem_end(umem)))
+               rbt_ib_umem_insert(&umem->odp_data->interval_tree,
+                                  &context->umem_tree);
+-      if (likely(!atomic_read(&context->notifier_count)))
++      if (likely(!atomic_read(&context->notifier_count)) ||
++          context->odp_mrs_count == 1)
+               umem->odp_data->mn_counters_active = true;
+       else
+               list_add(&umem->odp_data->no_private_counters,
diff --git a/queue-3.19/ib-core-when-marshaling-ucma-path-from-user-space-clear-unused-fields.patch b/queue-3.19/ib-core-when-marshaling-ucma-path-from-user-space-clear-unused-fields.patch
new file mode 100644 (file)
index 0000000..c35400a
--- /dev/null
@@ -0,0 +1,37 @@
+From c2be9dc0e0fa59cc43c2c7084fc42b430809a0fe Mon Sep 17 00:00:00 2001
+From: Ilya Nelkenbaum <ilyan@mellanox.com>
+Date: Thu, 5 Feb 2015 13:53:48 +0200
+Subject: IB/core: When marshaling ucma path from user-space, clear unused fields
+
+From: Ilya Nelkenbaum <ilyan@mellanox.com>
+
+commit c2be9dc0e0fa59cc43c2c7084fc42b430809a0fe upstream.
+
+When marshaling a user path to the kernel struct ib_sa_path, we need
+to zero smac and dmac and set the vlan id to the "no vlan" value.
+
+This is to ensure that Ethernet attributes are not used with
+InfiniBand QPs.
+
+Fixes: dd5f03beb4f7 ("IB/core: Ethernet L2 attributes in verbs/cm structures")
+Signed-off-by: Ilya Nelkenbaum <ilyan@mellanox.com>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/ucma.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/infiniband/core/ucma.c
++++ b/drivers/infiniband/core/ucma.c
+@@ -1124,6 +1124,9 @@ static int ucma_set_ib_path(struct ucma_
+       if (!optlen)
+               return -EINVAL;
++      memset(&sa_path, 0, sizeof(sa_path));
++      sa_path.vlan_id = 0xffff;
++
+       ib_sa_unpack_path(path_data->path_rec, &sa_path);
+       ret = rdma_set_ib_paths(ctx->cm_id, &sa_path, 1);
+       if (ret)
diff --git a/queue-3.19/ib-iser-fix-memory-regions-possible-leak.patch b/queue-3.19/ib-iser-fix-memory-regions-possible-leak.patch
new file mode 100644 (file)
index 0000000..42d6c1b
--- /dev/null
@@ -0,0 +1,118 @@
+From 6606e6a2ff2710b473838b291dc533cd8fc1471f Mon Sep 17 00:00:00 2001
+From: Sagi Grimberg <sagig@mellanox.com>
+Date: Sun, 18 Jan 2015 16:51:06 +0200
+Subject: IB/iser: Fix memory regions possible leak
+
+From: Sagi Grimberg <sagig@mellanox.com>
+
+commit 6606e6a2ff2710b473838b291dc533cd8fc1471f upstream.
+
+When teardown process starts during live IO, we need to keep the
+memory regions pool (frmr/fmr) until all in-flight tasks are properly
+released, since each task may return a memory region to the pool. In
+order to do this, we pass a destroy flag to iser_free_ib_conn_res to
+indicate we can destroy the device and the memory regions
+pool. iser_conn_release will pass it as true and also DEVICE_REMOVAL
+event (we need to let the device to properly remove).
+
+Also, Since we conditionally call iser_free_rx_descriptors,
+remove the extra check on iser_conn->rx_descs.
+
+Fixes: 5426b1711fd0 ("IB/iser: Collapse cleanup and disconnect handlers")
+Reported-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/iser/iser_initiator.c |    4 ----
+ drivers/infiniband/ulp/iser/iser_verbs.c     |   25 ++++++++++++++-----------
+ 2 files changed, 14 insertions(+), 15 deletions(-)
+
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -320,9 +320,6 @@ void iser_free_rx_descriptors(struct ise
+       struct ib_conn *ib_conn = &iser_conn->ib_conn;
+       struct iser_device *device = ib_conn->device;
+-      if (!iser_conn->rx_descs)
+-              goto free_login_buf;
+-
+       if (device->iser_free_rdma_reg_res)
+               device->iser_free_rdma_reg_res(ib_conn);
+@@ -334,7 +331,6 @@ void iser_free_rx_descriptors(struct ise
+       /* make sure we never redo any unmapping */
+       iser_conn->rx_descs = NULL;
+-free_login_buf:
+       iser_free_login_buf(iser_conn);
+ }
+--- a/drivers/infiniband/ulp/iser/iser_verbs.c
++++ b/drivers/infiniband/ulp/iser/iser_verbs.c
+@@ -600,16 +600,16 @@ void iser_release_work(struct work_struc
+ /**
+  * iser_free_ib_conn_res - release IB related resources
+  * @iser_conn: iser connection struct
+- * @destroy_device: indicator if we need to try to release
+- *     the iser device (only iscsi shutdown and DEVICE_REMOVAL
+- *     will use this.
++ * @destroy: indicator if we need to try to release the
++ *     iser device and memory regoins pool (only iscsi
++ *     shutdown and DEVICE_REMOVAL will use this).
+  *
+  * This routine is called with the iser state mutex held
+  * so the cm_id removal is out of here. It is Safe to
+  * be invoked multiple times.
+  */
+ static void iser_free_ib_conn_res(struct iser_conn *iser_conn,
+-                                bool destroy_device)
++                                bool destroy)
+ {
+       struct ib_conn *ib_conn = &iser_conn->ib_conn;
+       struct iser_device *device = ib_conn->device;
+@@ -617,17 +617,20 @@ static void iser_free_ib_conn_res(struct
+       iser_info("freeing conn %p cma_id %p qp %p\n",
+                 iser_conn, ib_conn->cma_id, ib_conn->qp);
+-      iser_free_rx_descriptors(iser_conn);
+-
+       if (ib_conn->qp != NULL) {
+               ib_conn->comp->active_qps--;
+               rdma_destroy_qp(ib_conn->cma_id);
+               ib_conn->qp = NULL;
+       }
+-      if (destroy_device && device != NULL) {
+-              iser_device_try_release(device);
+-              ib_conn->device = NULL;
++      if (destroy) {
++              if (iser_conn->rx_descs)
++                      iser_free_rx_descriptors(iser_conn);
++
++              if (device != NULL) {
++                      iser_device_try_release(device);
++                      ib_conn->device = NULL;
++              }
+       }
+ }
+@@ -840,7 +843,7 @@ static void iser_disconnected_handler(st
+ }
+ static void iser_cleanup_handler(struct rdma_cm_id *cma_id,
+-                               bool destroy_device)
++                               bool destroy)
+ {
+       struct iser_conn *iser_conn = (struct iser_conn *)cma_id->context;
+@@ -850,7 +853,7 @@ static void iser_cleanup_handler(struct
+        * and flush errors.
+        */
+       iser_disconnected_handler(cma_id);
+-      iser_free_ib_conn_res(iser_conn, destroy_device);
++      iser_free_ib_conn_res(iser_conn, destroy);
+       complete(&iser_conn->ib_completion);
+ };
diff --git a/queue-3.19/ib-iser-use-correct-dma-direction-when-unmapping-sgs.patch b/queue-3.19/ib-iser-use-correct-dma-direction-when-unmapping-sgs.patch
new file mode 100644 (file)
index 0000000..22e06a3
--- /dev/null
@@ -0,0 +1,96 @@
+From c6c95ef4cec680f7a10aa425a9970744b35b6489 Mon Sep 17 00:00:00 2001
+From: Roi Dayan <roid@mellanox.com>
+Date: Sun, 28 Dec 2014 14:26:11 +0200
+Subject: IB/iser: Use correct dma direction when unmapping SGs
+
+From: Roi Dayan <roid@mellanox.com>
+
+commit c6c95ef4cec680f7a10aa425a9970744b35b6489 upstream.
+
+We always unmap SGs with the same direction instead of unmapping
+with the direction the mapping was done, fix that.
+
+Fixes: 9a8b08fad2ef ("IB/iser: Generalize iser_unmap_task_data and [...]")
+Signed-off-by: Roi Dayan <roid@mellanox.com>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/ulp/iser/iscsi_iser.h     |    4 +++-
+ drivers/infiniband/ulp/iser/iser_initiator.c |   12 ++++++++----
+ drivers/infiniband/ulp/iser/iser_memory.c    |    9 ++++++---
+ 3 files changed, 17 insertions(+), 8 deletions(-)
+
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
+@@ -654,7 +654,9 @@ int iser_dma_map_task_data(struct iscsi_
+                          enum dma_data_direction dma_dir);
+ void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task,
+-                            struct iser_data_buf *data);
++                            struct iser_data_buf *data,
++                            enum dma_data_direction dir);
++
+ int  iser_initialize_task_headers(struct iscsi_task *task,
+                       struct iser_tx_desc *tx_desc);
+ int iser_alloc_rx_descriptors(struct iser_conn *iser_conn,
+--- a/drivers/infiniband/ulp/iser/iser_initiator.c
++++ b/drivers/infiniband/ulp/iser/iser_initiator.c
+@@ -710,19 +710,23 @@ void iser_task_rdma_finalize(struct iscs
+               device->iser_unreg_rdma_mem(iser_task, ISER_DIR_IN);
+               if (is_rdma_data_aligned)
+                       iser_dma_unmap_task_data(iser_task,
+-                                               &iser_task->data[ISER_DIR_IN]);
++                                               &iser_task->data[ISER_DIR_IN],
++                                               DMA_FROM_DEVICE);
+               if (prot_count && is_rdma_prot_aligned)
+                       iser_dma_unmap_task_data(iser_task,
+-                                               &iser_task->prot[ISER_DIR_IN]);
++                                               &iser_task->prot[ISER_DIR_IN],
++                                               DMA_FROM_DEVICE);
+       }
+       if (iser_task->dir[ISER_DIR_OUT]) {
+               device->iser_unreg_rdma_mem(iser_task, ISER_DIR_OUT);
+               if (is_rdma_data_aligned)
+                       iser_dma_unmap_task_data(iser_task,
+-                                               &iser_task->data[ISER_DIR_OUT]);
++                                               &iser_task->data[ISER_DIR_OUT],
++                                               DMA_TO_DEVICE);
+               if (prot_count && is_rdma_prot_aligned)
+                       iser_dma_unmap_task_data(iser_task,
+-                                               &iser_task->prot[ISER_DIR_OUT]);
++                                               &iser_task->prot[ISER_DIR_OUT],
++                                               DMA_TO_DEVICE);
+       }
+ }
+--- a/drivers/infiniband/ulp/iser/iser_memory.c
++++ b/drivers/infiniband/ulp/iser/iser_memory.c
+@@ -332,12 +332,13 @@ int iser_dma_map_task_data(struct iscsi_
+ }
+ void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task,
+-                            struct iser_data_buf *data)
++                            struct iser_data_buf *data,
++                            enum dma_data_direction dir)
+ {
+       struct ib_device *dev;
+       dev = iser_task->iser_conn->ib_conn.device->ib_device;
+-      ib_dma_unmap_sg(dev, data->buf, data->size, DMA_FROM_DEVICE);
++      ib_dma_unmap_sg(dev, data->buf, data->size, dir);
+ }
+ static int fall_to_bounce_buf(struct iscsi_iser_task *iser_task,
+@@ -357,7 +358,9 @@ static int fall_to_bounce_buf(struct isc
+               iser_data_buf_dump(mem, ibdev);
+       /* unmap the command data before accessing it */
+-      iser_dma_unmap_task_data(iser_task, mem);
++      iser_dma_unmap_task_data(iser_task, mem,
++                               (cmd_dir == ISER_DIR_OUT) ?
++                               DMA_TO_DEVICE : DMA_FROM_DEVICE);
+       /* allocate copy buf, if we are writing, copy the */
+       /* unaligned scatterlist, dma map the copy        */
diff --git a/queue-3.19/ib-mlx4-fix-memory-leak-in-__mlx4_ib_modify_qp.patch b/queue-3.19/ib-mlx4-fix-memory-leak-in-__mlx4_ib_modify_qp.patch
new file mode 100644 (file)
index 0000000..e3460ed
--- /dev/null
@@ -0,0 +1,36 @@
+From bede98e781747623ae170667694a71ef19c6ba7f Mon Sep 17 00:00:00 2001
+From: Majd Dibbiny <majd@mellanox.com>
+Date: Thu, 29 Jan 2015 10:41:41 +0200
+Subject: IB/mlx4: Fix memory leak in __mlx4_ib_modify_qp
+
+From: Majd Dibbiny <majd@mellanox.com>
+
+commit bede98e781747623ae170667694a71ef19c6ba7f upstream.
+
+In case handle_eth_ud_smac_index fails, we need to free the allocated resources.
+
+Fixes: 2f5bb473681b ("mlx4: Add ref counting to port MAC table for RoCE")
+Signed-off-by: Majd Dibbiny <majd@mellanox.com>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx4/qp.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/infiniband/hw/mlx4/qp.c
++++ b/drivers/infiniband/hw/mlx4/qp.c
+@@ -1674,8 +1674,10 @@ static int __mlx4_ib_modify_qp(struct ib
+                           qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI ||
+                           qp->mlx4_ib_qp_type == MLX4_IB_QPT_TUN_GSI) {
+                               err = handle_eth_ud_smac_index(dev, qp, (u8 *)attr->smac, context);
+-                              if (err)
+-                                      return -EINVAL;
++                              if (err) {
++                                      err = -EINVAL;
++                                      goto out;
++                              }
+                               if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI)
+                                       dev->qp1_proxy[qp->port - 1] = qp;
+                       }
diff --git a/queue-3.19/ib-mlx4-fix-wrong-usage-of-ipv4-protocol-for-multicast-attach-detach.patch b/queue-3.19/ib-mlx4-fix-wrong-usage-of-ipv4-protocol-for-multicast-attach-detach.patch
new file mode 100644 (file)
index 0000000..0999b36
--- /dev/null
@@ -0,0 +1,56 @@
+From e9a7faf11af94957e5107b40af46c2e329541510 Mon Sep 17 00:00:00 2001
+From: Or Gerlitz <ogerlitz@mellanox.com>
+Date: Wed, 17 Dec 2014 16:17:34 +0200
+Subject: IB/mlx4: Fix wrong usage of IPv4 protocol for multicast attach/detach
+
+From: Or Gerlitz <ogerlitz@mellanox.com>
+
+commit e9a7faf11af94957e5107b40af46c2e329541510 upstream.
+
+The MLX4_PROT_IB_IPV4 protocol should only be used with RoCEv2 and such.
+Removing this wrong usage allows to run multicast applications over RoCE.
+
+Fixes: d487ee77740c ("IB/mlx4: Use IBoE (RoCE) IP based GIDs in the port GID table")
+Reported-by: Carol Soto <clsoto@linux.vnet.ibm.com>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx4/main.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/infiniband/hw/mlx4/main.c
++++ b/drivers/infiniband/hw/mlx4/main.c
+@@ -1222,8 +1222,7 @@ static int mlx4_ib_mcg_attach(struct ib_
+       struct mlx4_ib_qp *mqp = to_mqp(ibqp);
+       u64 reg_id;
+       struct mlx4_ib_steering *ib_steering = NULL;
+-      enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ?
+-              MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6;
++      enum mlx4_protocol prot = MLX4_PROT_IB_IPV6;
+       if (mdev->dev->caps.steering_mode ==
+           MLX4_STEERING_MODE_DEVICE_MANAGED) {
+@@ -1236,8 +1235,10 @@ static int mlx4_ib_mcg_attach(struct ib_
+                                   !!(mqp->flags &
+                                      MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
+                                   prot, &reg_id);
+-      if (err)
++      if (err) {
++              pr_err("multicast attach op failed, err %d\n", err);
+               goto err_malloc;
++      }
+       err = add_gid_entry(ibqp, gid);
+       if (err)
+@@ -1285,8 +1286,7 @@ static int mlx4_ib_mcg_detach(struct ib_
+       struct net_device *ndev;
+       struct mlx4_ib_gid_entry *ge;
+       u64 reg_id = 0;
+-      enum mlx4_protocol prot = (gid->raw[1] == 0x0e) ?
+-              MLX4_PROT_IB_IPV4 : MLX4_PROT_IB_IPV6;
++      enum mlx4_protocol prot =  MLX4_PROT_IB_IPV6;
+       if (mdev->dev->caps.steering_mode ==
+           MLX4_STEERING_MODE_DEVICE_MANAGED) {
diff --git a/queue-3.19/ib-mlx5-fix-error-code-in-get_port_caps.patch b/queue-3.19/ib-mlx5-fix-error-code-in-get_port_caps.patch
new file mode 100644 (file)
index 0000000..555bb25
--- /dev/null
@@ -0,0 +1,32 @@
+From f614fc15ae39ceb531586e3969f2b99fd23182a0 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Mon, 12 Jan 2015 11:56:58 +0300
+Subject: IB/mlx5: Fix error code in get_port_caps()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit f614fc15ae39ceb531586e3969f2b99fd23182a0 upstream.
+
+The current code returns success when kmalloc() fails.  It should
+return an error code, -ENOMEM.
+
+Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/mlx5/main.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/infiniband/hw/mlx5/main.c
++++ b/drivers/infiniband/hw/mlx5/main.c
+@@ -997,7 +997,7 @@ static int get_port_caps(struct mlx5_ib_
+       struct ib_device_attr *dprops = NULL;
+       struct ib_port_attr *pprops = NULL;
+       struct mlx5_general_caps *gen;
+-      int err = 0;
++      int err = -ENOMEM;
+       int port;
+       gen = &dev->mdev->caps.gen;
diff --git a/queue-3.19/ib-qib-do-not-write-eeprom.patch b/queue-3.19/ib-qib-do-not-write-eeprom.patch
new file mode 100644 (file)
index 0000000..96b890e
--- /dev/null
@@ -0,0 +1,340 @@
+From 18c0b82a3e4501511b08d0e8676fb08ac08734a3 Mon Sep 17 00:00:00 2001
+From: Mitko Haralanov <mitko.haralanov@intel.com>
+Date: Fri, 16 Jan 2015 08:55:27 -0500
+Subject: IB/qib: Do not write EEPROM
+
+From: Mitko Haralanov <mitko.haralanov@intel.com>
+
+commit 18c0b82a3e4501511b08d0e8676fb08ac08734a3 upstream.
+
+This changeset removes all the code that allows the driver to write to
+the EEPROM and update the recorded error counters and power on hours.
+
+These two stats are unused and writing them exposes a timing risk
+which could leave the EEPROM in a bad state preventing further normal
+operation of the HCA.
+
+Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com>
+Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/hw/qib/qib.h         |    9 -
+ drivers/infiniband/hw/qib/qib_eeprom.c  |  181 --------------------------------
+ drivers/infiniband/hw/qib/qib_iba6120.c |    2 
+ drivers/infiniband/hw/qib/qib_iba7220.c |    2 
+ drivers/infiniband/hw/qib/qib_iba7322.c |    2 
+ drivers/infiniband/hw/qib/qib_init.c    |    1 
+ drivers/infiniband/hw/qib/qib_sysfs.c   |   24 ----
+ 7 files changed, 1 insertion(+), 220 deletions(-)
+
+--- a/drivers/infiniband/hw/qib/qib.h
++++ b/drivers/infiniband/hw/qib/qib.h
+@@ -1082,12 +1082,6 @@ struct qib_devdata {
+       /* control high-level access to EEPROM */
+       struct mutex eep_lock;
+       uint64_t traffic_wds;
+-      /* active time is kept in seconds, but logged in hours */
+-      atomic_t active_time;
+-      /* Below are nominal shadow of EEPROM, new since last EEPROM update */
+-      uint8_t eep_st_errs[QIB_EEP_LOG_CNT];
+-      uint8_t eep_st_new_errs[QIB_EEP_LOG_CNT];
+-      uint16_t eep_hrs;
+       /*
+        * masks for which bits of errs, hwerrs that cause
+        * each of the counters to increment.
+@@ -1309,8 +1303,7 @@ int qib_twsi_blk_rd(struct qib_devdata *
+ int qib_twsi_blk_wr(struct qib_devdata *dd, int dev, int addr,
+                   const void *buffer, int len);
+ void qib_get_eeprom_info(struct qib_devdata *);
+-int qib_update_eeprom_log(struct qib_devdata *dd);
+-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr);
++#define qib_inc_eeprom_err(dd, eidx, incr)
+ void qib_dump_lookup_output_queue(struct qib_devdata *);
+ void qib_force_pio_avail_update(struct qib_devdata *);
+ void qib_clear_symerror_on_linkup(unsigned long opaque);
+--- a/drivers/infiniband/hw/qib/qib_eeprom.c
++++ b/drivers/infiniband/hw/qib/qib_eeprom.c
+@@ -267,190 +267,9 @@ void qib_get_eeprom_info(struct qib_devd
+                       "Board SN %s did not pass functional test: %s\n",
+                       dd->serial, ifp->if_comment);
+-      memcpy(&dd->eep_st_errs, &ifp->if_errcntp, QIB_EEP_LOG_CNT);
+-      /*
+-       * Power-on (actually "active") hours are kept as little-endian value
+-       * in EEPROM, but as seconds in a (possibly as small as 24-bit)
+-       * atomic_t while running.
+-       */
+-      atomic_set(&dd->active_time, 0);
+-      dd->eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8);
+-
+ done:
+       vfree(buf);
+ bail:;
+ }
+-/**
+- * qib_update_eeprom_log - copy active-time and error counters to eeprom
+- * @dd: the qlogic_ib device
+- *
+- * Although the time is kept as seconds in the qib_devdata struct, it is
+- * rounded to hours for re-write, as we have only 16 bits in EEPROM.
+- * First-cut code reads whole (expected) struct qib_flash, modifies,
+- * re-writes. Future direction: read/write only what we need, assuming
+- * that the EEPROM had to have been "good enough" for driver init, and
+- * if not, we aren't making it worse.
+- *
+- */
+-int qib_update_eeprom_log(struct qib_devdata *dd)
+-{
+-      void *buf;
+-      struct qib_flash *ifp;
+-      int len, hi_water;
+-      uint32_t new_time, new_hrs;
+-      u8 csum;
+-      int ret, idx;
+-      unsigned long flags;
+-
+-      /* first, check if we actually need to do anything. */
+-      ret = 0;
+-      for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
+-              if (dd->eep_st_new_errs[idx]) {
+-                      ret = 1;
+-                      break;
+-              }
+-      }
+-      new_time = atomic_read(&dd->active_time);
+-
+-      if (ret == 0 && new_time < 3600)
+-              goto bail;
+-
+-      /*
+-       * The quick-check above determined that there is something worthy
+-       * of logging, so get current contents and do a more detailed idea.
+-       * read full flash, not just currently used part, since it may have
+-       * been written with a newer definition
+-       */
+-      len = sizeof(struct qib_flash);
+-      buf = vmalloc(len);
+-      ret = 1;
+-      if (!buf) {
+-              qib_dev_err(dd,
+-                      "Couldn't allocate memory to read %u bytes from eeprom for logging\n",
+-                      len);
+-              goto bail;
+-      }
+-
+-      /* Grab semaphore and read current EEPROM. If we get an
+-       * error, let go, but if not, keep it until we finish write.
+-       */
+-      ret = mutex_lock_interruptible(&dd->eep_lock);
+-      if (ret) {
+-              qib_dev_err(dd, "Unable to acquire EEPROM for logging\n");
+-              goto free_bail;
+-      }
+-      ret = qib_twsi_blk_rd(dd, dd->twsi_eeprom_dev, 0, buf, len);
+-      if (ret) {
+-              mutex_unlock(&dd->eep_lock);
+-              qib_dev_err(dd, "Unable read EEPROM for logging\n");
+-              goto free_bail;
+-      }
+-      ifp = (struct qib_flash *)buf;
+-
+-      csum = flash_csum(ifp, 0);
+-      if (csum != ifp->if_csum) {
+-              mutex_unlock(&dd->eep_lock);
+-              qib_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
+-                          csum, ifp->if_csum);
+-              ret = 1;
+-              goto free_bail;
+-      }
+-      hi_water = 0;
+-      spin_lock_irqsave(&dd->eep_st_lock, flags);
+-      for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
+-              int new_val = dd->eep_st_new_errs[idx];
+-              if (new_val) {
+-                      /*
+-                       * If we have seen any errors, add to EEPROM values
+-                       * We need to saturate at 0xFF (255) and we also
+-                       * would need to adjust the checksum if we were
+-                       * trying to minimize EEPROM traffic
+-                       * Note that we add to actual current count in EEPROM,
+-                       * in case it was altered while we were running.
+-                       */
+-                      new_val += ifp->if_errcntp[idx];
+-                      if (new_val > 0xFF)
+-                              new_val = 0xFF;
+-                      if (ifp->if_errcntp[idx] != new_val) {
+-                              ifp->if_errcntp[idx] = new_val;
+-                              hi_water = offsetof(struct qib_flash,
+-                                                  if_errcntp) + idx;
+-                      }
+-                      /*
+-                       * update our shadow (used to minimize EEPROM
+-                       * traffic), to match what we are about to write.
+-                       */
+-                      dd->eep_st_errs[idx] = new_val;
+-                      dd->eep_st_new_errs[idx] = 0;
+-              }
+-      }
+-      /*
+-       * Now update active-time. We would like to round to the nearest hour
+-       * but unless atomic_t are sure to be proper signed ints we cannot,
+-       * because we need to account for what we "transfer" to EEPROM and
+-       * if we log an hour at 31 minutes, then we would need to set
+-       * active_time to -29 to accurately count the _next_ hour.
+-       */
+-      if (new_time >= 3600) {
+-              new_hrs = new_time / 3600;
+-              atomic_sub((new_hrs * 3600), &dd->active_time);
+-              new_hrs += dd->eep_hrs;
+-              if (new_hrs > 0xFFFF)
+-                      new_hrs = 0xFFFF;
+-              dd->eep_hrs = new_hrs;
+-              if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) {
+-                      ifp->if_powerhour[0] = new_hrs & 0xFF;
+-                      hi_water = offsetof(struct qib_flash, if_powerhour);
+-              }
+-              if ((new_hrs >> 8) != ifp->if_powerhour[1]) {
+-                      ifp->if_powerhour[1] = new_hrs >> 8;
+-                      hi_water = offsetof(struct qib_flash, if_powerhour) + 1;
+-              }
+-      }
+-      /*
+-       * There is a tiny possibility that we could somehow fail to write
+-       * the EEPROM after updating our shadows, but problems from holding
+-       * the spinlock too long are a much bigger issue.
+-       */
+-      spin_unlock_irqrestore(&dd->eep_st_lock, flags);
+-      if (hi_water) {
+-              /* we made some change to the data, uopdate cksum and write */
+-              csum = flash_csum(ifp, 1);
+-              ret = eeprom_write_with_enable(dd, 0, buf, hi_water + 1);
+-      }
+-      mutex_unlock(&dd->eep_lock);
+-      if (ret)
+-              qib_dev_err(dd, "Failed updating EEPROM\n");
+-
+-free_bail:
+-      vfree(buf);
+-bail:
+-      return ret;
+-}
+-
+-/**
+- * qib_inc_eeprom_err - increment one of the four error counters
+- * that are logged to EEPROM.
+- * @dd: the qlogic_ib device
+- * @eidx: 0..3, the counter to increment
+- * @incr: how much to add
+- *
+- * Each counter is 8-bits, and saturates at 255 (0xFF). They
+- * are copied to the EEPROM (aka flash) whenever qib_update_eeprom_log()
+- * is called, but it can only be called in a context that allows sleep.
+- * This function can be called even at interrupt level.
+- */
+-void qib_inc_eeprom_err(struct qib_devdata *dd, u32 eidx, u32 incr)
+-{
+-      uint new_val;
+-      unsigned long flags;
+-
+-      spin_lock_irqsave(&dd->eep_st_lock, flags);
+-      new_val = dd->eep_st_new_errs[eidx] + incr;
+-      if (new_val > 255)
+-              new_val = 255;
+-      dd->eep_st_new_errs[eidx] = new_val;
+-      spin_unlock_irqrestore(&dd->eep_st_lock, flags);
+-}
+--- a/drivers/infiniband/hw/qib/qib_iba6120.c
++++ b/drivers/infiniband/hw/qib/qib_iba6120.c
+@@ -2681,8 +2681,6 @@ static void qib_get_6120_faststats(unsig
+       spin_lock_irqsave(&dd->eep_st_lock, flags);
+       traffic_wds -= dd->traffic_wds;
+       dd->traffic_wds += traffic_wds;
+-      if (traffic_wds  >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
+-              atomic_add(5, &dd->active_time); /* S/B #define */
+       spin_unlock_irqrestore(&dd->eep_st_lock, flags);
+       qib_chk_6120_errormask(dd);
+--- a/drivers/infiniband/hw/qib/qib_iba7220.c
++++ b/drivers/infiniband/hw/qib/qib_iba7220.c
+@@ -3297,8 +3297,6 @@ static void qib_get_7220_faststats(unsig
+       spin_lock_irqsave(&dd->eep_st_lock, flags);
+       traffic_wds -= dd->traffic_wds;
+       dd->traffic_wds += traffic_wds;
+-      if (traffic_wds  >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
+-              atomic_add(5, &dd->active_time); /* S/B #define */
+       spin_unlock_irqrestore(&dd->eep_st_lock, flags);
+ done:
+       mod_timer(&dd->stats_timer, jiffies + HZ * ACTIVITY_TIMER);
+--- a/drivers/infiniband/hw/qib/qib_iba7322.c
++++ b/drivers/infiniband/hw/qib/qib_iba7322.c
+@@ -5178,8 +5178,6 @@ static void qib_get_7322_faststats(unsig
+               spin_lock_irqsave(&ppd->dd->eep_st_lock, flags);
+               traffic_wds -= ppd->dd->traffic_wds;
+               ppd->dd->traffic_wds += traffic_wds;
+-              if (traffic_wds >= QIB_TRAFFIC_ACTIVE_THRESHOLD)
+-                      atomic_add(ACTIVITY_TIMER, &ppd->dd->active_time);
+               spin_unlock_irqrestore(&ppd->dd->eep_st_lock, flags);
+               if (ppd->cpspec->qdr_dfe_on && (ppd->link_speed_active &
+                                               QIB_IB_QDR) &&
+--- a/drivers/infiniband/hw/qib/qib_init.c
++++ b/drivers/infiniband/hw/qib/qib_init.c
+@@ -931,7 +931,6 @@ static void qib_shutdown_device(struct q
+               qib_free_pportdata(ppd);
+       }
+-      qib_update_eeprom_log(dd);
+ }
+ /**
+--- a/drivers/infiniband/hw/qib/qib_sysfs.c
++++ b/drivers/infiniband/hw/qib/qib_sysfs.c
+@@ -611,28 +611,6 @@ bail:
+       return ret < 0 ? ret : count;
+ }
+-static ssize_t show_logged_errs(struct device *device,
+-                              struct device_attribute *attr, char *buf)
+-{
+-      struct qib_ibdev *dev =
+-              container_of(device, struct qib_ibdev, ibdev.dev);
+-      struct qib_devdata *dd = dd_from_dev(dev);
+-      int idx, count;
+-
+-      /* force consistency with actual EEPROM */
+-      if (qib_update_eeprom_log(dd) != 0)
+-              return -ENXIO;
+-
+-      count = 0;
+-      for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) {
+-              count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c",
+-                                 dd->eep_st_errs[idx],
+-                                 idx == (QIB_EEP_LOG_CNT - 1) ? '\n' : ' ');
+-      }
+-
+-      return count;
+-}
+-
+ /*
+  * Dump tempsense regs. in decimal, to ease shell-scripts.
+  */
+@@ -679,7 +657,6 @@ static DEVICE_ATTR(nctxts, S_IRUGO, show
+ static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL);
+ static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
+ static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
+-static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
+ static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL);
+ static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL);
+ static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset);
+@@ -693,7 +670,6 @@ static struct device_attribute *qib_attr
+       &dev_attr_nfreectxts,
+       &dev_attr_serial,
+       &dev_attr_boardversion,
+-      &dev_attr_logged_errors,
+       &dev_attr_tempsense,
+       &dev_attr_localbus_info,
+       &dev_attr_chip_reset,
diff --git a/queue-3.19/locking-rtmutex-avoid-a-null-pointer-dereference-on-deadlock.patch b/queue-3.19/locking-rtmutex-avoid-a-null-pointer-dereference-on-deadlock.patch
new file mode 100644 (file)
index 0000000..b2d9ea6
--- /dev/null
@@ -0,0 +1,44 @@
+From 8d1e5a1a1ccf5ae9d8a5a0ee7960202ccb0c5429 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 17 Feb 2015 16:43:43 +0100
+Subject: locking/rtmutex: Avoid a NULL pointer dereference on deadlock
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+commit 8d1e5a1a1ccf5ae9d8a5a0ee7960202ccb0c5429 upstream.
+
+With task_blocks_on_rt_mutex() returning early -EDEADLK we never
+add the waiter to the waitqueue. Later, we try to remove it via
+remove_waiter() and go boom in rt_mutex_top_waiter() because
+rb_entry() gives a NULL pointer.
+
+( Tested on v3.18-RT where rtmutex is used for regular mutex and I
+  tried to get one twice in a row. )
+
+Not sure when this started but I guess 397335f004f4 ("rtmutex: Fix
+deadlock detector for real") or commit 3d5c9340d194 ("rtmutex:
+Handle deadlock detection smarter").
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/1424187823-19600-1-git-send-email-bigeasy@linutronix.de
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/locking/rtmutex.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -1193,7 +1193,8 @@ rt_mutex_slowlock(struct rt_mutex *lock,
+       set_current_state(TASK_RUNNING);
+       if (unlikely(ret)) {
+-              remove_waiter(lock, &waiter);
++              if (rt_mutex_has_waiters(lock))
++                      remove_waiter(lock, &waiter);
+               rt_mutex_handle_deadlock(ret, chwalk, &waiter);
+       }
index be795529eca480c6805cd03b3a4a06f9591f2011..5ae9472ddba42e9c112b4ac8e828b8cc80703734 100644 (file)
@@ -113,3 +113,14 @@ alsa-hda-controller-code-do-not-export-static-functions.patch
 alsa-hda-disable-runtime-pm-for-panther-point-again.patch
 alsa-oxfw-fix-a-condition-and-return-code-in-start_stream.patch
 alsa-hda-one-more-dell-macine-needs-dell1_mic_no_presence-quirk.patch
+locking-rtmutex-avoid-a-null-pointer-dereference-on-deadlock.patch
+sg-fix-read-error-reporting.patch
+ib-qib-do-not-write-eeprom.patch
+ib-iser-fix-memory-regions-possible-leak.patch
+ib-iser-use-correct-dma-direction-when-unmapping-sgs.patch
+ib-mlx5-fix-error-code-in-get_port_caps.patch
+ib-mlx4-fix-memory-leak-in-__mlx4_ib_modify_qp.patch
+ib-mlx4-fix-wrong-usage-of-ipv4-protocol-for-multicast-attach-detach.patch
+ib-core-fix-deadlock-on-uverbs-modify_qp-error-flow.patch
+ib-core-properly-handle-registration-of-on-demand-paging-mrs-after-dereg.patch
+ib-core-when-marshaling-ucma-path-from-user-space-clear-unused-fields.patch
diff --git a/queue-3.19/sg-fix-read-error-reporting.patch b/queue-3.19/sg-fix-read-error-reporting.patch
new file mode 100644 (file)
index 0000000..b49ad6f
--- /dev/null
@@ -0,0 +1,43 @@
+From 3b524a683af8991b4eab4182b947c65f0ce1421b Mon Sep 17 00:00:00 2001
+From: Tony Battersby <tonyb@cybernetics.com>
+Date: Wed, 11 Feb 2015 11:32:06 -0500
+Subject: sg: fix read() error reporting
+
+From: Tony Battersby <tonyb@cybernetics.com>
+
+commit 3b524a683af8991b4eab4182b947c65f0ce1421b upstream.
+
+Fix SCSI generic read() incorrectly returning success after detecting an
+error.
+
+Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
+Acked-by: Douglas Gilbert <dgilbert@interlog.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/sg.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -546,7 +546,7 @@ static ssize_t
+ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
+ {
+       sg_io_hdr_t *hp = &srp->header;
+-      int err = 0;
++      int err = 0, err2;
+       int len;
+       if (count < SZ_SG_IO_HDR) {
+@@ -575,8 +575,8 @@ sg_new_read(Sg_fd * sfp, char __user *bu
+               goto err_out;
+       }
+ err_out:
+-      err = sg_finish_rem_req(srp);
+-      return (0 == err) ? count : err;
++      err2 = sg_finish_rem_req(srp);
++      return err ? : err2 ? : count;
+ }
+ static ssize_t