]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Mar 2017 08:38:30 +0000 (09:38 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Mar 2017 08:38:30 +0000 (09:38 +0100)
added patches:
bcma-use-get-put-_device-when-probing-removing-device-driver.patch
can-gs_usb-don-t-use-stack-memory-for-usb-transfers.patch
can-usb_8dev-fix-memory-leak-of-priv-cmd_msg_buffer.patch
ceph-update-readpages-osd-request-according-to-size-of-pages.patch
dmaengine-ipu-make-sure-the-interrupt-routine-checks-all-interrupts.patch
drivers-hv-util-backup-fix-a-rescind-processing-issue.patch
drivers-hv-util-fcopy-fix-a-rescind-processing-issue.patch
drivers-hv-util-kvp-fix-a-rescind-processing-issue.patch
drivers-hv-vmbus-fix-a-rescind-handling-bug.patch
drivers-hv-vmbus-prevent-sending-data-on-a-rescinded-channel.patch
f2fs-add-ovp-valid_blocks-check-for-bg-gc-victim-to-fg_gc.patch
f2fs-avoid-to-issue-redundant-discard-commands.patch
f2fs-fix-a-problem-of-using-memory-after-free.patch
f2fs-fix-multiple-f2fs_add_link-calls-having-same-name.patch
f2fs-fix-zoned-block-device-support.patch
gfs2-add-missing-rcu-locking-for-glock-lookup.patch
hv-allocate-synic-pages-for-all-present-cpus.patch
hv-don-t-reset-hv_context.tsc_page-on-crash.patch
hv-init-percpu_list-in-hv_synic_alloc.patch
iio-pressure-mpl115-do-not-rely-on-structure-field-ordering.patch
iio-pressure-mpl3115-do-not-rely-on-structure-field-ordering.patch
md-linear-fix-a-race-between-linear_add-and-linear_congested.patch
mips-ip22-fix-build-error-due-to-binutils-2.25-uselessnes.patch
mips-ip22-reformat-inline-assembler-code-to-modern-standards.patch
module-fix-memory-leak-on-early-load_module-failures.patch
mtd-nand-ifc-fix-location-of-eccstat-registers-for-ifc-v1.0.patch
nfsd-minor-nfsd_setattr-cleanup.patch
nfsd-special-case-truncates-some-more.patch
nfsv4-fix-getacl-erange-for-some-acl-buffer-sizes.patch
nfsv4-fix-getacl-head-length-estimation.patch
nfsv4-fix-memory-and-state-leak-in-_nfs4_open_and_get_state.patch
nfsv4-fix-reboot-recovery-in-copy-offload.patch
pnfs-flexfiles-if-the-layout-is-invalid-it-must-be-updated-before-retrying.patch
powerpc-mm-add-mmu_ftr_kernel_ro-to-possible-feature-mask.patch
powerpc-mm-hash-always-clear-uprt-and-host-radix-bits-when-setting-up-cpu.patch
powerpc-xmon-fix-data-breakpoint.patch
rdma-core-fix-incorrect-structure-packing-for-booleans.patch
rdma_cm-fail-iwarp-accepts-w-o-connection-params.patch
remoteproc-qcom-mdt_loader-don-t-overwrite-firmware-object.patch
revert-nfsv4.1-handle-nfs4err_badsession-nfs4err_deadsession-replies-to-op_sequence.patch
rtc-sun6i-add-some-locking.patch
rtc-sun6i-disable-the-build-as-a-module.patch
rtc-sun6i-switch-to-the-external-oscillator.patch
rtlwifi-fix-alignment-issues.patch
rtlwifi-rtl8192c-common-fix-bug-kasan.patch
scsi-lpfc-correct-wq-creation-for-pagesize.patch
usb-dwc3-gadget-skip-set-clear-halt-when-invalid.patch
usb-gadget-f_hid-fix-free-out-requests.patch
usb-gadget-f_hid-fix-move-in-request-allocation-to-set_alt.patch
usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch
usb-gadget-f_hid-use-spinlock-instead-of-mutex.patch
usb-gadget-udc-core-rescan-pending-list-on-driver-unbind.patch
usb-gadget-udc-fsl-add-missing-complete-function.patch
usb-host-xhci-plat-check-hcc_params-after-add-hcd.patch
usb-musb-da8xx-remove-cppi-3.0-quirk-and-methods.patch
vme-restore-bus_remove-function-causing-incomplete-module-unload.patch
w1-don-t-leak-refcount-on-slave-attach-failure-in-w1_attach_slave_device.patch
w1-ds2490-usb-transfer-buffers-need-to-be-dmaable.patch
xprtrdma-disable-pad-optimization-by-default.patch
xprtrdma-fix-read-chunk-padding.patch
xprtrdma-per-connection-pad-optimization.patch
xprtrdma-reduce-required-number-of-send-sges.patch

63 files changed:
queue-4.10/bcma-use-get-put-_device-when-probing-removing-device-driver.patch [new file with mode: 0644]
queue-4.10/can-gs_usb-don-t-use-stack-memory-for-usb-transfers.patch [new file with mode: 0644]
queue-4.10/can-usb_8dev-fix-memory-leak-of-priv-cmd_msg_buffer.patch [new file with mode: 0644]
queue-4.10/ceph-update-readpages-osd-request-according-to-size-of-pages.patch [new file with mode: 0644]
queue-4.10/dmaengine-ipu-make-sure-the-interrupt-routine-checks-all-interrupts.patch [new file with mode: 0644]
queue-4.10/drivers-hv-util-backup-fix-a-rescind-processing-issue.patch [new file with mode: 0644]
queue-4.10/drivers-hv-util-fcopy-fix-a-rescind-processing-issue.patch [new file with mode: 0644]
queue-4.10/drivers-hv-util-kvp-fix-a-rescind-processing-issue.patch [new file with mode: 0644]
queue-4.10/drivers-hv-vmbus-fix-a-rescind-handling-bug.patch [new file with mode: 0644]
queue-4.10/drivers-hv-vmbus-prevent-sending-data-on-a-rescinded-channel.patch [new file with mode: 0644]
queue-4.10/f2fs-add-ovp-valid_blocks-check-for-bg-gc-victim-to-fg_gc.patch [new file with mode: 0644]
queue-4.10/f2fs-avoid-to-issue-redundant-discard-commands.patch [new file with mode: 0644]
queue-4.10/f2fs-fix-a-problem-of-using-memory-after-free.patch [new file with mode: 0644]
queue-4.10/f2fs-fix-multiple-f2fs_add_link-calls-having-same-name.patch [new file with mode: 0644]
queue-4.10/f2fs-fix-zoned-block-device-support.patch [new file with mode: 0644]
queue-4.10/gfs2-add-missing-rcu-locking-for-glock-lookup.patch [new file with mode: 0644]
queue-4.10/hv-allocate-synic-pages-for-all-present-cpus.patch [new file with mode: 0644]
queue-4.10/hv-don-t-reset-hv_context.tsc_page-on-crash.patch [new file with mode: 0644]
queue-4.10/hv-init-percpu_list-in-hv_synic_alloc.patch [new file with mode: 0644]
queue-4.10/iio-pressure-mpl115-do-not-rely-on-structure-field-ordering.patch [new file with mode: 0644]
queue-4.10/iio-pressure-mpl3115-do-not-rely-on-structure-field-ordering.patch [new file with mode: 0644]
queue-4.10/md-linear-fix-a-race-between-linear_add-and-linear_congested.patch [new file with mode: 0644]
queue-4.10/mips-ip22-fix-build-error-due-to-binutils-2.25-uselessnes.patch [new file with mode: 0644]
queue-4.10/mips-ip22-reformat-inline-assembler-code-to-modern-standards.patch [new file with mode: 0644]
queue-4.10/module-fix-memory-leak-on-early-load_module-failures.patch [new file with mode: 0644]
queue-4.10/mtd-nand-ifc-fix-location-of-eccstat-registers-for-ifc-v1.0.patch [new file with mode: 0644]
queue-4.10/nfsd-minor-nfsd_setattr-cleanup.patch [new file with mode: 0644]
queue-4.10/nfsd-special-case-truncates-some-more.patch [new file with mode: 0644]
queue-4.10/nfsv4-fix-getacl-erange-for-some-acl-buffer-sizes.patch [new file with mode: 0644]
queue-4.10/nfsv4-fix-getacl-head-length-estimation.patch [new file with mode: 0644]
queue-4.10/nfsv4-fix-memory-and-state-leak-in-_nfs4_open_and_get_state.patch [new file with mode: 0644]
queue-4.10/nfsv4-fix-reboot-recovery-in-copy-offload.patch [new file with mode: 0644]
queue-4.10/pnfs-flexfiles-if-the-layout-is-invalid-it-must-be-updated-before-retrying.patch [new file with mode: 0644]
queue-4.10/powerpc-mm-add-mmu_ftr_kernel_ro-to-possible-feature-mask.patch [new file with mode: 0644]
queue-4.10/powerpc-mm-hash-always-clear-uprt-and-host-radix-bits-when-setting-up-cpu.patch [new file with mode: 0644]
queue-4.10/powerpc-xmon-fix-data-breakpoint.patch [new file with mode: 0644]
queue-4.10/rdma-core-fix-incorrect-structure-packing-for-booleans.patch [new file with mode: 0644]
queue-4.10/rdma_cm-fail-iwarp-accepts-w-o-connection-params.patch [new file with mode: 0644]
queue-4.10/remoteproc-qcom-mdt_loader-don-t-overwrite-firmware-object.patch [new file with mode: 0644]
queue-4.10/revert-nfsv4.1-handle-nfs4err_badsession-nfs4err_deadsession-replies-to-op_sequence.patch [new file with mode: 0644]
queue-4.10/rtc-sun6i-add-some-locking.patch [new file with mode: 0644]
queue-4.10/rtc-sun6i-disable-the-build-as-a-module.patch [new file with mode: 0644]
queue-4.10/rtc-sun6i-switch-to-the-external-oscillator.patch [new file with mode: 0644]
queue-4.10/rtlwifi-fix-alignment-issues.patch [new file with mode: 0644]
queue-4.10/rtlwifi-rtl8192c-common-fix-bug-kasan.patch [new file with mode: 0644]
queue-4.10/scsi-lpfc-correct-wq-creation-for-pagesize.patch [new file with mode: 0644]
queue-4.10/series
queue-4.10/usb-dwc3-gadget-skip-set-clear-halt-when-invalid.patch [new file with mode: 0644]
queue-4.10/usb-gadget-f_hid-fix-free-out-requests.patch [new file with mode: 0644]
queue-4.10/usb-gadget-f_hid-fix-move-in-request-allocation-to-set_alt.patch [new file with mode: 0644]
queue-4.10/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch [new file with mode: 0644]
queue-4.10/usb-gadget-f_hid-use-spinlock-instead-of-mutex.patch [new file with mode: 0644]
queue-4.10/usb-gadget-udc-core-rescan-pending-list-on-driver-unbind.patch [new file with mode: 0644]
queue-4.10/usb-gadget-udc-fsl-add-missing-complete-function.patch [new file with mode: 0644]
queue-4.10/usb-host-xhci-plat-check-hcc_params-after-add-hcd.patch [new file with mode: 0644]
queue-4.10/usb-musb-da8xx-remove-cppi-3.0-quirk-and-methods.patch [new file with mode: 0644]
queue-4.10/vme-restore-bus_remove-function-causing-incomplete-module-unload.patch [new file with mode: 0644]
queue-4.10/w1-don-t-leak-refcount-on-slave-attach-failure-in-w1_attach_slave_device.patch [new file with mode: 0644]
queue-4.10/w1-ds2490-usb-transfer-buffers-need-to-be-dmaable.patch [new file with mode: 0644]
queue-4.10/xprtrdma-disable-pad-optimization-by-default.patch [new file with mode: 0644]
queue-4.10/xprtrdma-fix-read-chunk-padding.patch [new file with mode: 0644]
queue-4.10/xprtrdma-per-connection-pad-optimization.patch [new file with mode: 0644]
queue-4.10/xprtrdma-reduce-required-number-of-send-sges.patch [new file with mode: 0644]

diff --git a/queue-4.10/bcma-use-get-put-_device-when-probing-removing-device-driver.patch b/queue-4.10/bcma-use-get-put-_device-when-probing-removing-device-driver.patch
new file mode 100644 (file)
index 0000000..fb1347a
--- /dev/null
@@ -0,0 +1,44 @@
+From a971df0b9d04674e325346c17de9a895425ca5e1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Sat, 28 Jan 2017 14:31:22 +0100
+Subject: bcma: use (get|put)_device when probing/removing device driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rafał Miłecki <rafal@milecki.pl>
+
+commit a971df0b9d04674e325346c17de9a895425ca5e1 upstream.
+
+This allows tracking device state and e.g. makes devm work as expected.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/bcma/main.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/bcma/main.c
++++ b/drivers/bcma/main.c
+@@ -633,8 +633,11 @@ static int bcma_device_probe(struct devi
+                                              drv);
+       int err = 0;
++      get_device(dev);
+       if (adrv->probe)
+               err = adrv->probe(core);
++      if (err)
++              put_device(dev);
+       return err;
+ }
+@@ -647,6 +650,7 @@ static int bcma_device_remove(struct dev
+       if (adrv->remove)
+               adrv->remove(core);
++      put_device(dev);
+       return 0;
+ }
diff --git a/queue-4.10/can-gs_usb-don-t-use-stack-memory-for-usb-transfers.patch b/queue-4.10/can-gs_usb-don-t-use-stack-memory-for-usb-transfers.patch
new file mode 100644 (file)
index 0000000..4501a94
--- /dev/null
@@ -0,0 +1,132 @@
+From c919a3069c775c1c876bec55e00b2305d5125caa Mon Sep 17 00:00:00 2001
+From: Ethan Zonca <e@ethanzonca.com>
+Date: Fri, 24 Feb 2017 11:27:36 -0500
+Subject: can: gs_usb: Don't use stack memory for USB transfers
+
+From: Ethan Zonca <e@ethanzonca.com>
+
+commit c919a3069c775c1c876bec55e00b2305d5125caa upstream.
+
+Fixes: 05ca5270005c can: gs_usb: add ethtool set_phys_id callback to locate physical device
+
+The gs_usb driver is performing USB transfers using buffers allocated on
+the stack. This causes the driver to not function with vmapped stacks.
+Instead, allocate memory for the transfer buffers.
+
+Signed-off-by: Ethan Zonca <e@ethanzonca.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/usb/gs_usb.c |   40 +++++++++++++++++++++++++++++-----------
+ 1 file changed, 29 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/can/usb/gs_usb.c
++++ b/drivers/net/can/usb/gs_usb.c
+@@ -908,10 +908,14 @@ static int gs_usb_probe(struct usb_inter
+       struct gs_usb *dev;
+       int rc = -ENOMEM;
+       unsigned int icount, i;
+-      struct gs_host_config hconf = {
+-              .byte_order = 0x0000beef,
+-      };
+-      struct gs_device_config dconf;
++      struct gs_host_config *hconf;
++      struct gs_device_config *dconf;
++
++      hconf = kmalloc(sizeof(*hconf), GFP_KERNEL);
++      if (!hconf)
++              return -ENOMEM;
++
++      hconf->byte_order = 0x0000beef;
+       /* send host config */
+       rc = usb_control_msg(interface_to_usbdev(intf),
+@@ -920,16 +924,22 @@ static int gs_usb_probe(struct usb_inter
+                            USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+                            1,
+                            intf->altsetting[0].desc.bInterfaceNumber,
+-                           &hconf,
+-                           sizeof(hconf),
++                           hconf,
++                           sizeof(*hconf),
+                            1000);
++      kfree(hconf);
++
+       if (rc < 0) {
+               dev_err(&intf->dev, "Couldn't send data format (err=%d)\n",
+                       rc);
+               return rc;
+       }
++      dconf = kmalloc(sizeof(*dconf), GFP_KERNEL);
++      if (!dconf)
++              return -ENOMEM;
++
+       /* read device config */
+       rc = usb_control_msg(interface_to_usbdev(intf),
+                            usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
+@@ -937,28 +947,33 @@ static int gs_usb_probe(struct usb_inter
+                            USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+                            1,
+                            intf->altsetting[0].desc.bInterfaceNumber,
+-                           &dconf,
+-                           sizeof(dconf),
++                           dconf,
++                           sizeof(*dconf),
+                            1000);
+       if (rc < 0) {
+               dev_err(&intf->dev, "Couldn't get device config: (err=%d)\n",
+                       rc);
++              kfree(dconf);
+               return rc;
+       }
+-      icount = dconf.icount + 1;
++      icount = dconf->icount + 1;
+       dev_info(&intf->dev, "Configuring for %d interfaces\n", icount);
+       if (icount > GS_MAX_INTF) {
+               dev_err(&intf->dev,
+                       "Driver cannot handle more that %d CAN interfaces\n",
+                       GS_MAX_INTF);
++              kfree(dconf);
+               return -EINVAL;
+       }
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+-      if (!dev)
++      if (!dev) {
++              kfree(dconf);
+               return -ENOMEM;
++      }
++
+       init_usb_anchor(&dev->rx_submitted);
+       atomic_set(&dev->active_channels, 0);
+@@ -967,7 +982,7 @@ static int gs_usb_probe(struct usb_inter
+       dev->udev = interface_to_usbdev(intf);
+       for (i = 0; i < icount; i++) {
+-              dev->canch[i] = gs_make_candev(i, intf, &dconf);
++              dev->canch[i] = gs_make_candev(i, intf, dconf);
+               if (IS_ERR_OR_NULL(dev->canch[i])) {
+                       /* save error code to return later */
+                       rc = PTR_ERR(dev->canch[i]);
+@@ -978,12 +993,15 @@ static int gs_usb_probe(struct usb_inter
+                               gs_destroy_candev(dev->canch[i]);
+                       usb_kill_anchored_urbs(&dev->rx_submitted);
++                      kfree(dconf);
+                       kfree(dev);
+                       return rc;
+               }
+               dev->canch[i]->parent = dev;
+       }
++      kfree(dconf);
++
+       return 0;
+ }
diff --git a/queue-4.10/can-usb_8dev-fix-memory-leak-of-priv-cmd_msg_buffer.patch b/queue-4.10/can-usb_8dev-fix-memory-leak-of-priv-cmd_msg_buffer.patch
new file mode 100644 (file)
index 0000000..46d6e42
--- /dev/null
@@ -0,0 +1,52 @@
+From 7c42631376306fb3f34d51fda546b50a9b6dd6ec Mon Sep 17 00:00:00 2001
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+Date: Thu, 2 Mar 2017 12:03:40 +0100
+Subject: can: usb_8dev: Fix memory leak of priv->cmd_msg_buffer
+
+From: Marc Kleine-Budde <mkl@pengutronix.de>
+
+commit 7c42631376306fb3f34d51fda546b50a9b6dd6ec upstream.
+
+The priv->cmd_msg_buffer is allocated in the probe function, but never
+kfree()ed. This patch converts the kzalloc() to resource-managed
+kzalloc.
+
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/can/usb/usb_8dev.c |    9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/can/usb/usb_8dev.c
++++ b/drivers/net/can/usb/usb_8dev.c
+@@ -951,8 +951,8 @@ static int usb_8dev_probe(struct usb_int
+       for (i = 0; i < MAX_TX_URBS; i++)
+               priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+-      priv->cmd_msg_buffer = kzalloc(sizeof(struct usb_8dev_cmd_msg),
+-                                    GFP_KERNEL);
++      priv->cmd_msg_buffer = devm_kzalloc(&intf->dev, sizeof(struct usb_8dev_cmd_msg),
++                                          GFP_KERNEL);
+       if (!priv->cmd_msg_buffer)
+               goto cleanup_candev;
+@@ -966,7 +966,7 @@ static int usb_8dev_probe(struct usb_int
+       if (err) {
+               netdev_err(netdev,
+                       "couldn't register CAN device: %d\n", err);
+-              goto cleanup_cmd_msg_buffer;
++              goto cleanup_candev;
+       }
+       err = usb_8dev_cmd_version(priv, &version);
+@@ -987,9 +987,6 @@ static int usb_8dev_probe(struct usb_int
+ cleanup_unregister_candev:
+       unregister_netdev(priv->netdev);
+-cleanup_cmd_msg_buffer:
+-      kfree(priv->cmd_msg_buffer);
+-
+ cleanup_candev:
+       free_candev(netdev);
diff --git a/queue-4.10/ceph-update-readpages-osd-request-according-to-size-of-pages.patch b/queue-4.10/ceph-update-readpages-osd-request-according-to-size-of-pages.patch
new file mode 100644 (file)
index 0000000..9acd3e7
--- /dev/null
@@ -0,0 +1,44 @@
+From d641df819db8b80198fd85d9de91137e8a823b07 Mon Sep 17 00:00:00 2001
+From: "Yan, Zheng" <zyan@redhat.com>
+Date: Thu, 19 Jan 2017 11:21:29 +0800
+Subject: ceph: update readpages osd request according to size of pages
+
+From: Yan, Zheng <zyan@redhat.com>
+
+commit d641df819db8b80198fd85d9de91137e8a823b07 upstream.
+
+add_to_page_cache_lru() can fails, so the actual pages to read
+can be smaller than the initial size of osd request. We need to
+update osd request size in that case.
+
+Signed-off-by: Yan, Zheng <zyan@redhat.com>
+Reviewed-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ceph/addr.c        |    1 +
+ net/ceph/osd_client.c |    3 ++-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/ceph/addr.c
++++ b/fs/ceph/addr.c
+@@ -391,6 +391,7 @@ static int start_read(struct inode *inod
+                       nr_pages = i;
+                       if (nr_pages > 0) {
+                               len = nr_pages << PAGE_SHIFT;
++                              osd_req_op_extent_update(req, 0, len);
+                               break;
+                       }
+                       goto out_pages;
+--- a/net/ceph/osd_client.c
++++ b/net/ceph/osd_client.c
+@@ -672,7 +672,8 @@ void osd_req_op_extent_update(struct cep
+       BUG_ON(length > previous);
+       op->extent.length = length;
+-      op->indata_len -= previous - length;
++      if (op->op == CEPH_OSD_OP_WRITE || op->op == CEPH_OSD_OP_WRITEFULL)
++              op->indata_len -= previous - length;
+ }
+ EXPORT_SYMBOL(osd_req_op_extent_update);
diff --git a/queue-4.10/dmaengine-ipu-make-sure-the-interrupt-routine-checks-all-interrupts.patch b/queue-4.10/dmaengine-ipu-make-sure-the-interrupt-routine-checks-all-interrupts.patch
new file mode 100644 (file)
index 0000000..e7634f0
--- /dev/null
@@ -0,0 +1,37 @@
+From adee40b265d7568296e218f079f478197ffa15bf Mon Sep 17 00:00:00 2001
+From: Magnus Lilja <lilja.magnus@gmail.com>
+Date: Wed, 21 Dec 2016 22:13:58 +0100
+Subject: dmaengine: ipu: Make sure the interrupt routine checks all interrupts.
+
+From: Magnus Lilja <lilja.magnus@gmail.com>
+
+commit adee40b265d7568296e218f079f478197ffa15bf upstream.
+
+Commit 3d8cc00073d6 ("dmaengine: ipu: Consolidate duplicated irq handlers")
+consolidated the two interrupts routines into one, but the remaining
+interrupt routine only checks the status of the error interrupts, not the
+normal interrupts.
+
+This patch fixes that problem (tested on i.MX31 PDK board).
+
+Fixes: 3d8cc00073d6 ("dmaengine: ipu: Consolidate duplicated irq handlers")
+Cc: Vinod Koul <vinod.koul@intel.com>
+Signed-off-by: Magnus Lilja <lilja.magnus@gmail.com>
+Signed-off-by: Vinod Koul <vinod.koul@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma/ipu/ipu_irq.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/dma/ipu/ipu_irq.c
++++ b/drivers/dma/ipu/ipu_irq.c
+@@ -272,7 +272,7 @@ static void ipu_irq_handler(struct irq_d
+       u32 status;
+       int i, line;
+-      for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) {
++      for (i = 0; i < IPU_IRQ_NR_BANKS; i++) {
+               struct ipu_irq_bank *bank = irq_bank + i;
+               raw_spin_lock(&bank_lock);
diff --git a/queue-4.10/drivers-hv-util-backup-fix-a-rescind-processing-issue.patch b/queue-4.10/drivers-hv-util-backup-fix-a-rescind-processing-issue.patch
new file mode 100644 (file)
index 0000000..02c67bc
--- /dev/null
@@ -0,0 +1,51 @@
+From d77044d142e960f7b5f814a91ecb8bcf86aa552c Mon Sep 17 00:00:00 2001
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+Date: Thu, 22 Dec 2016 16:54:03 -0800
+Subject: Drivers: hv: util: Backup: Fix a rescind processing issue
+
+From: K. Y. Srinivasan <kys@microsoft.com>
+
+commit d77044d142e960f7b5f814a91ecb8bcf86aa552c upstream.
+
+VSS may use a char device to support the communication between
+the user level daemon and the driver. When the VSS channel is rescinded
+we need to make sure that the char device is fully cleaned up before
+we can process a new VSS offer from the host. Implement this logic.
+
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/hv_snapshot.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/hv/hv_snapshot.c
++++ b/drivers/hv/hv_snapshot.c
+@@ -69,6 +69,7 @@ static int dm_reg_value;
+ static const char vss_devname[] = "vmbus/hv_vss";
+ static __u8 *recv_buffer;
+ static struct hvutil_transport *hvt;
++static struct completion release_event;
+ static void vss_timeout_func(struct work_struct *dummy);
+ static void vss_handle_request(struct work_struct *dummy);
+@@ -345,11 +346,13 @@ static void vss_on_reset(void)
+       if (cancel_delayed_work_sync(&vss_timeout_work))
+               vss_respond_to_host(HV_E_FAIL);
+       vss_transaction.state = HVUTIL_DEVICE_INIT;
++      complete(&release_event);
+ }
+ int
+ hv_vss_init(struct hv_util_service *srv)
+ {
++      init_completion(&release_event);
+       if (vmbus_proto_version < VERSION_WIN8_1) {
+               pr_warn("Integration service 'Backup (volume snapshot)'"
+                       " not supported on this host version.\n");
+@@ -382,4 +385,5 @@ void hv_vss_deinit(void)
+       cancel_delayed_work_sync(&vss_timeout_work);
+       cancel_work_sync(&vss_handle_request_work);
+       hvutil_transport_destroy(hvt);
++      wait_for_completion(&release_event);
+ }
diff --git a/queue-4.10/drivers-hv-util-fcopy-fix-a-rescind-processing-issue.patch b/queue-4.10/drivers-hv-util-fcopy-fix-a-rescind-processing-issue.patch
new file mode 100644 (file)
index 0000000..43e8659
--- /dev/null
@@ -0,0 +1,53 @@
+From 20951c7535b5e6af46bc37b7142105f716df739c Mon Sep 17 00:00:00 2001
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+Date: Thu, 22 Dec 2016 16:54:02 -0800
+Subject: Drivers: hv: util: Fcopy: Fix a rescind processing issue
+
+From: K. Y. Srinivasan <kys@microsoft.com>
+
+commit 20951c7535b5e6af46bc37b7142105f716df739c upstream.
+
+Fcopy may use a char device to support the communication between
+the user level daemon and the driver. When the Fcopy channel is rescinded
+we need to make sure that the char device is fully cleaned up before
+we can process a new Fcopy offer from the host. Implement this logic.
+
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/hv_fcopy.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/hv/hv_fcopy.c
++++ b/drivers/hv/hv_fcopy.c
+@@ -61,6 +61,7 @@ static DECLARE_WORK(fcopy_send_work, fco
+ static const char fcopy_devname[] = "vmbus/hv_fcopy";
+ static u8 *recv_buffer;
+ static struct hvutil_transport *hvt;
++static struct completion release_event;
+ /*
+  * This state maintains the version number registered by the daemon.
+  */
+@@ -317,6 +318,7 @@ static void fcopy_on_reset(void)
+       if (cancel_delayed_work_sync(&fcopy_timeout_work))
+               fcopy_respond_to_host(HV_E_FAIL);
++      complete(&release_event);
+ }
+ int hv_fcopy_init(struct hv_util_service *srv)
+@@ -324,6 +326,7 @@ int hv_fcopy_init(struct hv_util_service
+       recv_buffer = srv->recv_buffer;
+       fcopy_transaction.recv_channel = srv->channel;
++      init_completion(&release_event);
+       /*
+        * When this driver loads, the user level daemon that
+        * processes the host requests may not yet be running.
+@@ -345,4 +348,5 @@ void hv_fcopy_deinit(void)
+       fcopy_transaction.state = HVUTIL_DEVICE_DYING;
+       cancel_delayed_work_sync(&fcopy_timeout_work);
+       hvutil_transport_destroy(hvt);
++      wait_for_completion(&release_event);
+ }
diff --git a/queue-4.10/drivers-hv-util-kvp-fix-a-rescind-processing-issue.patch b/queue-4.10/drivers-hv-util-kvp-fix-a-rescind-processing-issue.patch
new file mode 100644 (file)
index 0000000..302c50d
--- /dev/null
@@ -0,0 +1,53 @@
+From 5a66fecbf6aa528e375cbebccb1061cc58d80c84 Mon Sep 17 00:00:00 2001
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+Date: Thu, 22 Dec 2016 16:54:01 -0800
+Subject: Drivers: hv: util: kvp: Fix a rescind processing issue
+
+From: K. Y. Srinivasan <kys@microsoft.com>
+
+commit 5a66fecbf6aa528e375cbebccb1061cc58d80c84 upstream.
+
+KVP may use a char device to support the communication between
+the user level daemon and the driver. When the KVP channel is rescinded
+we need to make sure that the char device is fully cleaned up before
+we can process a new KVP offer from the host. Implement this logic.
+
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/hv_kvp.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/hv/hv_kvp.c
++++ b/drivers/hv/hv_kvp.c
+@@ -88,6 +88,7 @@ static DECLARE_WORK(kvp_sendkey_work, kv
+ static const char kvp_devname[] = "vmbus/hv_kvp";
+ static u8 *recv_buffer;
+ static struct hvutil_transport *hvt;
++static struct completion release_event;
+ /*
+  * Register the kernel component with the user-level daemon.
+  * As part of this registration, pass the LIC version number.
+@@ -716,6 +717,7 @@ static void kvp_on_reset(void)
+       if (cancel_delayed_work_sync(&kvp_timeout_work))
+               kvp_respond_to_host(NULL, HV_E_FAIL);
+       kvp_transaction.state = HVUTIL_DEVICE_INIT;
++      complete(&release_event);
+ }
+ int
+@@ -724,6 +726,7 @@ hv_kvp_init(struct hv_util_service *srv)
+       recv_buffer = srv->recv_buffer;
+       kvp_transaction.recv_channel = srv->channel;
++      init_completion(&release_event);
+       /*
+        * When this driver loads, the user level daemon that
+        * processes the host requests may not yet be running.
+@@ -747,4 +750,5 @@ void hv_kvp_deinit(void)
+       cancel_delayed_work_sync(&kvp_timeout_work);
+       cancel_work_sync(&kvp_sendkey_work);
+       hvutil_transport_destroy(hvt);
++      wait_for_completion(&release_event);
+ }
diff --git a/queue-4.10/drivers-hv-vmbus-fix-a-rescind-handling-bug.patch b/queue-4.10/drivers-hv-vmbus-fix-a-rescind-handling-bug.patch
new file mode 100644 (file)
index 0000000..6901bd7
--- /dev/null
@@ -0,0 +1,136 @@
+From ccb61f8a99e6c29df4fb96a65dad4fad740d5be9 Mon Sep 17 00:00:00 2001
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+Date: Thu, 22 Dec 2016 16:54:00 -0800
+Subject: Drivers: hv: vmbus: Fix a rescind handling bug
+
+From: K. Y. Srinivasan <kys@microsoft.com>
+
+commit ccb61f8a99e6c29df4fb96a65dad4fad740d5be9 upstream.
+
+The host can rescind a channel that has been offered to the
+guest and once the channel is rescinded, the host does not
+respond to any requests on that channel. Deal with the case where
+the guest may be blocked waiting for a response from the host.
+
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/channel.c      |   18 ++++++++++++++++++
+ drivers/hv/channel_mgmt.c |   25 +++++++++++++++++++++++++
+ include/linux/hyperv.h    |    1 +
+ 3 files changed, 44 insertions(+)
+
+--- a/drivers/hv/channel.c
++++ b/drivers/hv/channel.c
+@@ -157,6 +157,7 @@ int vmbus_open(struct vmbus_channel *new
+       }
+       init_completion(&open_info->waitevent);
++      open_info->waiting_channel = newchannel;
+       open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
+       open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
+@@ -194,6 +195,11 @@ int vmbus_open(struct vmbus_channel *new
+       list_del(&open_info->msglistentry);
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
++      if (newchannel->rescind) {
++              err = -ENODEV;
++              goto error_free_gpadl;
++      }
++
+       if (open_info->response.open_result.status) {
+               err = -EAGAIN;
+               goto error_free_gpadl;
+@@ -405,6 +411,7 @@ int vmbus_establish_gpadl(struct vmbus_c
+               return ret;
+       init_completion(&msginfo->waitevent);
++      msginfo->waiting_channel = channel;
+       gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
+       gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
+@@ -441,6 +448,11 @@ int vmbus_establish_gpadl(struct vmbus_c
+       }
+       wait_for_completion(&msginfo->waitevent);
++      if (channel->rescind) {
++              ret = -ENODEV;
++              goto cleanup;
++      }
++
+       /* At this point, we received the gpadl created msg */
+       *gpadl_handle = gpadlmsg->gpadl;
+@@ -474,6 +486,7 @@ int vmbus_teardown_gpadl(struct vmbus_ch
+               return -ENOMEM;
+       init_completion(&info->waitevent);
++      info->waiting_channel = channel;
+       msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
+@@ -493,6 +506,11 @@ int vmbus_teardown_gpadl(struct vmbus_ch
+       wait_for_completion(&info->waitevent);
++      if (channel->rescind) {
++              ret = -ENODEV;
++              goto post_msg_err;
++      }
++
+ post_msg_err:
+       spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+       list_del(&info->msglistentry);
+--- a/drivers/hv/channel_mgmt.c
++++ b/drivers/hv/channel_mgmt.c
+@@ -147,6 +147,29 @@ static const struct {
+       { HV_RDV_GUID   },
+ };
++/*
++ * The rescinded channel may be blocked waiting for a response from the host;
++ * take care of that.
++ */
++static void vmbus_rescind_cleanup(struct vmbus_channel *channel)
++{
++      struct vmbus_channel_msginfo *msginfo;
++      unsigned long flags;
++
++
++      spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
++
++      list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
++                              msglistentry) {
++
++              if (msginfo->waiting_channel == channel) {
++                      complete(&msginfo->waitevent);
++                      break;
++              }
++      }
++      spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
++}
++
+ static bool is_unsupported_vmbus_devs(const uuid_le *guid)
+ {
+       int i;
+@@ -825,6 +848,8 @@ static void vmbus_onoffer_rescind(struct
+       channel->rescind = true;
+       spin_unlock_irqrestore(&channel->lock, flags);
++      vmbus_rescind_cleanup(channel);
++
+       if (channel->device_obj) {
+               if (channel->chn_rescind_callback) {
+                       channel->chn_rescind_callback(channel);
+--- a/include/linux/hyperv.h
++++ b/include/linux/hyperv.h
+@@ -641,6 +641,7 @@ struct vmbus_channel_msginfo {
+       /* Synchronize the request/response if needed */
+       struct completion  waitevent;
++      struct vmbus_channel *waiting_channel;
+       union {
+               struct vmbus_channel_version_supported version_supported;
+               struct vmbus_channel_open_result open_result;
diff --git a/queue-4.10/drivers-hv-vmbus-prevent-sending-data-on-a-rescinded-channel.patch b/queue-4.10/drivers-hv-vmbus-prevent-sending-data-on-a-rescinded-channel.patch
new file mode 100644 (file)
index 0000000..b9d65bf
--- /dev/null
@@ -0,0 +1,45 @@
+From e7e97dd8b77ee7366f2f8c70a033bf5fa05ec2e0 Mon Sep 17 00:00:00 2001
+From: "K. Y. Srinivasan" <kys@microsoft.com>
+Date: Wed, 7 Dec 2016 01:16:28 -0800
+Subject: Drivers: hv: vmbus: Prevent sending data on a rescinded channel
+
+From: K. Y. Srinivasan <kys@microsoft.com>
+
+commit e7e97dd8b77ee7366f2f8c70a033bf5fa05ec2e0 upstream.
+
+After the channel is rescinded, the host does not read from the rescinded channel.
+Fail writes to a channel that has already been rescinded. If we permit writes on a
+rescinded channel, since the host will not respond we will have situations where
+we will be unable to unload vmbus drivers that cannot have any outstanding requests
+to the host at the point they are unoaded.
+
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/ring_buffer.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/hv/ring_buffer.c
++++ b/drivers/hv/ring_buffer.c
+@@ -298,6 +298,9 @@ int hv_ringbuffer_write(struct vmbus_cha
+       unsigned long flags = 0;
+       struct hv_ring_buffer_info *outring_info = &channel->outbound;
++      if (channel->rescind)
++              return -ENODEV;
++
+       for (i = 0; i < kv_count; i++)
+               totalbytes_towrite += kv_list[i].iov_len;
+@@ -350,6 +353,10 @@ int hv_ringbuffer_write(struct vmbus_cha
+               spin_unlock_irqrestore(&outring_info->ring_lock, flags);
+       hv_signal_on_write(old_write, channel, kick_q);
++
++      if (channel->rescind)
++              return -ENODEV;
++
+       return 0;
+ }
diff --git a/queue-4.10/f2fs-add-ovp-valid_blocks-check-for-bg-gc-victim-to-fg_gc.patch b/queue-4.10/f2fs-add-ovp-valid_blocks-check-for-bg-gc-victim-to-fg_gc.patch
new file mode 100644 (file)
index 0000000..d86f0a8
--- /dev/null
@@ -0,0 +1,120 @@
+From e93b9865251a0503d83fd570e7d5a7c8bc351715 Mon Sep 17 00:00:00 2001
+From: Hou Pengyang <houpengyang@huawei.com>
+Date: Thu, 16 Feb 2017 12:34:31 +0000
+Subject: f2fs: add ovp valid_blocks check for bg gc victim to fg_gc
+
+From: Hou Pengyang <houpengyang@huawei.com>
+
+commit e93b9865251a0503d83fd570e7d5a7c8bc351715 upstream.
+
+For foreground gc, greedy algorithm should be adapted, which makes
+this formula work well:
+
+       (2 * (100 / config.overprovision + 1) + 6)
+
+But currently, we fg_gc have a prior to select bg_gc victim segments to gc
+first, these victims are selected by cost-benefit algorithm, we can't guarantee
+such segments have the small valid blocks, which may destroy the f2fs rule, on
+the worstest case, would consume all the free segments.
+
+This patch fix this by add a filter in check_bg_victims, if segment's has # of
+valid blocks over overprovision ratio, skip such segments.
+
+Signed-off-by: Hou Pengyang <houpengyang@huawei.com>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/f2fs.h    |    3 +++
+ fs/f2fs/gc.c      |   22 ++++++++++++++++++++--
+ fs/f2fs/segment.h |    9 +++++++++
+ 3 files changed, 32 insertions(+), 2 deletions(-)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -864,6 +864,9 @@ struct f2fs_sb_info {
+       struct f2fs_gc_kthread  *gc_thread;     /* GC thread */
+       unsigned int cur_victim_sec;            /* current victim section num */
++      /* threshold for converting bg victims for fg */
++      u64 fggc_threshold;
++
+       /* maximum # of trials to find a victim segment for SSR and GC */
+       unsigned int max_victim_search;
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -166,7 +166,8 @@ static void select_policy(struct f2fs_sb
+               p->ofs_unit = sbi->segs_per_sec;
+       }
+-      if (p->max_search > sbi->max_victim_search)
++      /* we need to check every dirty segments in the FG_GC case */
++      if (gc_type != FG_GC && p->max_search > sbi->max_victim_search)
+               p->max_search = sbi->max_victim_search;
+       p->offset = sbi->last_victim[p->gc_mode];
+@@ -199,6 +200,10 @@ static unsigned int check_bg_victims(str
+       for_each_set_bit(secno, dirty_i->victim_secmap, MAIN_SECS(sbi)) {
+               if (sec_usage_check(sbi, secno))
+                       continue;
++
++              if (no_fggc_candidate(sbi, secno))
++                      continue;
++
+               clear_bit(secno, dirty_i->victim_secmap);
+               return secno * sbi->segs_per_sec;
+       }
+@@ -322,13 +327,15 @@ static int get_victim_by_default(struct
+                       nsearched++;
+               }
+-
+               secno = GET_SECNO(sbi, segno);
+               if (sec_usage_check(sbi, secno))
+                       goto next;
+               if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
+                       goto next;
++              if (gc_type == FG_GC && p.alloc_mode == LFS &&
++                                      no_fggc_candidate(sbi, secno))
++                      goto next;
+               cost = get_gc_cost(sbi, segno, &p);
+@@ -983,5 +990,16 @@ stop:
+ void build_gc_manager(struct f2fs_sb_info *sbi)
+ {
++      u64 main_count, resv_count, ovp_count, blocks_per_sec;
++
+       DIRTY_I(sbi)->v_ops = &default_v_ops;
++
++      /* threshold of # of valid blocks in a section for victims of FG_GC */
++      main_count = SM_I(sbi)->main_segments << sbi->log_blocks_per_seg;
++      resv_count = SM_I(sbi)->reserved_segments << sbi->log_blocks_per_seg;
++      ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg;
++      blocks_per_sec = sbi->blocks_per_seg * sbi->segs_per_sec;
++
++      sbi->fggc_threshold = div_u64((main_count - ovp_count) * blocks_per_sec,
++                                      (main_count - resv_count));
+ }
+--- a/fs/f2fs/segment.h
++++ b/fs/f2fs/segment.h
+@@ -689,6 +689,15 @@ static inline block_t sum_blk_addr(struc
+                               - (base + 1) + type;
+ }
++static inline bool no_fggc_candidate(struct f2fs_sb_info *sbi,
++                                              unsigned int secno)
++{
++      if (get_valid_blocks(sbi, secno, sbi->segs_per_sec) >=
++                                              sbi->fggc_threshold)
++              return true;
++      return false;
++}
++
+ static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno)
+ {
+       if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno))
diff --git a/queue-4.10/f2fs-avoid-to-issue-redundant-discard-commands.patch b/queue-4.10/f2fs-avoid-to-issue-redundant-discard-commands.patch
new file mode 100644 (file)
index 0000000..4449b9a
--- /dev/null
@@ -0,0 +1,49 @@
+From 8b107f5b97772c7c0c218302e9a4d15b4edf50b4 Mon Sep 17 00:00:00 2001
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+Date: Mon, 27 Feb 2017 11:57:11 -0800
+Subject: f2fs: avoid to issue redundant discard commands
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+commit 8b107f5b97772c7c0c218302e9a4d15b4edf50b4 upstream.
+
+If segs_per_sec is over 1 like under SMR, previously f2fs issues discard
+commands redundantly on the same section, since we didn't move end position
+for the previous discard command.
+
+E.g.,
+
+                       start  end
+                         |    |
+      prefree_bitmap = [01111100111100]
+
+And, after issue discard for this section,
+                             end      start
+                              |        |
+      prefree_bitmap = [01111100111100]
+
+Select this section again by searching from (end + 1),
+                             start  end
+                                |   |
+      prefree_bitmap = [01111100111100]
+
+Fixes: 36abef4e796d38 ("f2fs: introduce mode=lfs mount option")
+Cc: Damien Le Moal <damien.lemoal@wdc.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/segment.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -935,6 +935,8 @@ next:
+               start = start_segno + sbi->segs_per_sec;
+               if (start < end)
+                       goto next;
++              else
++                      end = start - 1;
+       }
+       mutex_unlock(&dirty_i->seglist_lock);
diff --git a/queue-4.10/f2fs-fix-a-problem-of-using-memory-after-free.patch b/queue-4.10/f2fs-fix-a-problem-of-using-memory-after-free.patch
new file mode 100644 (file)
index 0000000..3c20fa1
--- /dev/null
@@ -0,0 +1,39 @@
+From 7855eba4d6102f811b6dd142d6c749f53b591fa3 Mon Sep 17 00:00:00 2001
+From: Yunlei He <heyunlei@huawei.com>
+Date: Mon, 19 Dec 2016 20:10:48 +0800
+Subject: f2fs: fix a problem of using memory after free
+
+From: Yunlei He <heyunlei@huawei.com>
+
+commit 7855eba4d6102f811b6dd142d6c749f53b591fa3 upstream.
+
+This patch fix a problem of using memory after free
+in function __try_merge_extent_node.
+
+Fixes: 0f825ee6e873 ("f2fs: add new interfaces for extent tree")
+Signed-off-by: Yunlei He <heyunlei@huawei.com>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/extent_cache.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/f2fs/extent_cache.c
++++ b/fs/f2fs/extent_cache.c
+@@ -352,11 +352,12 @@ static struct extent_node *__try_merge_e
+       }
+       if (next_ex && __is_front_mergeable(ei, &next_ex->ei)) {
+-              if (en)
+-                      __release_extent_node(sbi, et, prev_ex);
+               next_ex->ei.fofs = ei->fofs;
+               next_ex->ei.blk = ei->blk;
+               next_ex->ei.len += ei->len;
++              if (en)
++                      __release_extent_node(sbi, et, prev_ex);
++
+               en = next_ex;
+       }
diff --git a/queue-4.10/f2fs-fix-multiple-f2fs_add_link-calls-having-same-name.patch b/queue-4.10/f2fs-fix-multiple-f2fs_add_link-calls-having-same-name.patch
new file mode 100644 (file)
index 0000000..c05b63b
--- /dev/null
@@ -0,0 +1,90 @@
+From 88c5c13a5027b36d914536fdba23f069d7067204 Mon Sep 17 00:00:00 2001
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+Date: Tue, 14 Feb 2017 09:54:37 -0800
+Subject: f2fs: fix multiple f2fs_add_link() calls having same name
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+commit 88c5c13a5027b36d914536fdba23f069d7067204 upstream.
+
+It turns out a stakable filesystem like sdcardfs in AOSP can trigger multiple
+vfs_create() to lower filesystem. In that case, f2fs will add multiple dentries
+having same name which breaks filesystem consistency.
+
+Until upper layer fixes, let's work around by f2fs, which shows actually not
+much performance regression.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/dir.c  |   34 +++++++++++++++++++++++++++++-----
+ fs/f2fs/f2fs.h |    1 +
+ 2 files changed, 30 insertions(+), 5 deletions(-)
+
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -207,9 +207,13 @@ static struct f2fs_dir_entry *find_in_le
+               f2fs_put_page(dentry_page, 0);
+       }
+-      if (!de && room && F2FS_I(dir)->chash != namehash) {
+-              F2FS_I(dir)->chash = namehash;
+-              F2FS_I(dir)->clevel = level;
++      /* This is to increase the speed of f2fs_create */
++      if (!de && room) {
++              F2FS_I(dir)->task = current;
++              if (F2FS_I(dir)->chash != namehash) {
++                      F2FS_I(dir)->chash = namehash;
++                      F2FS_I(dir)->clevel = level;
++              }
+       }
+       return de;
+@@ -643,14 +647,34 @@ int __f2fs_add_link(struct inode *dir, c
+                               struct inode *inode, nid_t ino, umode_t mode)
+ {
+       struct fscrypt_name fname;
++      struct page *page = NULL;
++      struct f2fs_dir_entry *de = NULL;
+       int err;
+       err = fscrypt_setup_filename(dir, name, 0, &fname);
+       if (err)
+               return err;
+-      err = __f2fs_do_add_link(dir, &fname, inode, ino, mode);
+-
++      /*
++       * An immature stakable filesystem shows a race condition between lookup
++       * and create. If we have same task when doing lookup and create, it's
++       * definitely fine as expected by VFS normally. Otherwise, let's just
++       * verify on-disk dentry one more time, which guarantees filesystem
++       * consistency more.
++       */
++      if (current != F2FS_I(dir)->task) {
++              de = __f2fs_find_entry(dir, &fname, &page);
++              F2FS_I(dir)->task = NULL;
++      }
++      if (de) {
++              f2fs_dentry_kunmap(dir, page);
++              f2fs_put_page(page, 0);
++              err = -EEXIST;
++      } else if (IS_ERR(page)) {
++              err = PTR_ERR(page);
++      } else {
++              err = __f2fs_do_add_link(dir, &fname, inode, ino, mode);
++      }
+       fscrypt_free_filename(&fname);
+       return err;
+ }
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -434,6 +434,7 @@ struct f2fs_inode_info {
+       atomic_t dirty_pages;           /* # of dirty pages */
+       f2fs_hash_t chash;              /* hash value of given file name */
+       unsigned int clevel;            /* maximum level of given file name */
++      struct task_struct *task;       /* lookup and create consistency */
+       nid_t i_xattr_nid;              /* node id that contains xattrs */
+       unsigned long long xattr_ver;   /* cp version of xattr modification */
+       loff_t  last_disk_size;         /* lastly written file size */
diff --git a/queue-4.10/f2fs-fix-zoned-block-device-support.patch b/queue-4.10/f2fs-fix-zoned-block-device-support.patch
new file mode 100644 (file)
index 0000000..a7c4494
--- /dev/null
@@ -0,0 +1,125 @@
+From 7bb3a371d199156cb6a863feab377146b80942c5 Mon Sep 17 00:00:00 2001
+From: Masato Suzuki <masato.suzuki@wdc.com>
+Date: Mon, 27 Feb 2017 20:52:49 +0900
+Subject: f2fs: Fix zoned block device support
+
+From: Masato Suzuki <masato.suzuki@wdc.com>
+
+commit 7bb3a371d199156cb6a863feab377146b80942c5 upstream.
+
+The introduction of the multi-device feature partially broke the support
+for zoned block devices. In the function f2fs_scan_devices, sbi->devs
+allocation and initialization is skipped in the case of a single device
+mount. This result in no device information structure being allocated
+for the device. This is fine if the device is a regular device, but in
+the case of a zoned block device, the device zone type array is not
+initialized, which causes the function __f2fs_issue_discard_zone to fail
+as get_blkz_type is unable to determine the zone type of a section.
+
+Fix this by always allocating and initializing the sbi->devs device
+information array even in the case of a single device if that device is
+zoned. For this particular case, make sure to obtain a reference on the
+single device so that the call to blkdev_put() in destroy_device_list
+operates as expected.
+
+Fixes: 3c62be17d4f562f4 ("f2fs: support multiple devices")
+Signed-off-by: Masato Suzuki <masato.suzuki@wdc.com>
+Acked-by: Damien Le Moal <damien.lemoal@wdc.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/super.c |   69 ++++++++++++++++++++++++++++++++++++--------------------
+ 1 file changed, 45 insertions(+), 24 deletions(-)
+
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -1698,36 +1698,55 @@ int f2fs_commit_super(struct f2fs_sb_inf
+ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
+ {
+       struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++      unsigned int max_devices = MAX_DEVICES;
+       int i;
+-      for (i = 0; i < MAX_DEVICES; i++) {
+-              if (!RDEV(i).path[0])
++      /* Initialize single device information */
++      if (!RDEV(0).path[0]) {
++              if (!bdev_is_zoned(sbi->sb->s_bdev))
+                       return 0;
++              max_devices = 1;
++      }
+-              if (i == 0) {
+-                      sbi->devs = kzalloc(sizeof(struct f2fs_dev_info) *
+-                                              MAX_DEVICES, GFP_KERNEL);
+-                      if (!sbi->devs)
+-                              return -ENOMEM;
+-              }
+-
+-              memcpy(FDEV(i).path, RDEV(i).path, MAX_PATH_LEN);
+-              FDEV(i).total_segments = le32_to_cpu(RDEV(i).total_segments);
+-              if (i == 0) {
+-                      FDEV(i).start_blk = 0;
+-                      FDEV(i).end_blk = FDEV(i).start_blk +
+-                              (FDEV(i).total_segments <<
+-                              sbi->log_blocks_per_seg) - 1 +
+-                              le32_to_cpu(raw_super->segment0_blkaddr);
++      /*
++       * Initialize multiple devices information, or single
++       * zoned block device information.
++       */
++      sbi->devs = kcalloc(max_devices, sizeof(struct f2fs_dev_info),
++                              GFP_KERNEL);
++      if (!sbi->devs)
++              return -ENOMEM;
++
++      for (i = 0; i < max_devices; i++) {
++
++              if (i > 0 && !RDEV(i).path[0])
++                      break;
++
++              if (max_devices == 1) {
++                      /* Single zoned block device mount */
++                      FDEV(0).bdev =
++                              blkdev_get_by_dev(sbi->sb->s_bdev->bd_dev,
++                                      sbi->sb->s_mode, sbi->sb->s_type);
+               } else {
+-                      FDEV(i).start_blk = FDEV(i - 1).end_blk + 1;
+-                      FDEV(i).end_blk = FDEV(i).start_blk +
+-                              (FDEV(i).total_segments <<
+-                              sbi->log_blocks_per_seg) - 1;
+-              }
+-
+-              FDEV(i).bdev = blkdev_get_by_path(FDEV(i).path,
++                      /* Multi-device mount */
++                      memcpy(FDEV(i).path, RDEV(i).path, MAX_PATH_LEN);
++                      FDEV(i).total_segments =
++                              le32_to_cpu(RDEV(i).total_segments);
++                      if (i == 0) {
++                              FDEV(i).start_blk = 0;
++                              FDEV(i).end_blk = FDEV(i).start_blk +
++                                  (FDEV(i).total_segments <<
++                                  sbi->log_blocks_per_seg) - 1 +
++                                  le32_to_cpu(raw_super->segment0_blkaddr);
++                      } else {
++                              FDEV(i).start_blk = FDEV(i - 1).end_blk + 1;
++                              FDEV(i).end_blk = FDEV(i).start_blk +
++                                      (FDEV(i).total_segments <<
++                                      sbi->log_blocks_per_seg) - 1;
++                      }
++                      FDEV(i).bdev = blkdev_get_by_path(FDEV(i).path,
+                                       sbi->sb->s_mode, sbi->sb->s_type);
++              }
+               if (IS_ERR(FDEV(i).bdev))
+                       return PTR_ERR(FDEV(i).bdev);
+@@ -1747,6 +1766,8 @@ static int f2fs_scan_devices(struct f2fs
+                                       "Failed to initialize F2FS blkzone information");
+                               return -EINVAL;
+                       }
++                      if (max_devices == 1)
++                              break;
+                       f2fs_msg(sbi->sb, KERN_INFO,
+                               "Mount Device [%2d]: %20s, %8u, %8x - %8x (zone: %s)",
+                               i, FDEV(i).path,
diff --git a/queue-4.10/gfs2-add-missing-rcu-locking-for-glock-lookup.patch b/queue-4.10/gfs2-add-missing-rcu-locking-for-glock-lookup.patch
new file mode 100644 (file)
index 0000000..29d7eff
--- /dev/null
@@ -0,0 +1,54 @@
+From f38e5fb95a1f8feda88531eedc98f69b24748712 Mon Sep 17 00:00:00 2001
+From: Andrew Price <anprice@redhat.com>
+Date: Wed, 22 Feb 2017 12:05:03 -0500
+Subject: gfs2: Add missing rcu locking for glock       lookup
+
+From: Andrew Price <anprice@redhat.com>
+
+commit f38e5fb95a1f8feda88531eedc98f69b24748712 upstream.
+
+We must hold the rcu read lock across looking up glocks and trying to
+bump their refcount to prevent the glocks from being freed in between.
+
+Signed-off-by: Andrew Price <anprice@redhat.com>
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+Signed-off-by: Bob Peterson <rpeterso@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/gfs2/glock.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/fs/gfs2/glock.c
++++ b/fs/gfs2/glock.c
+@@ -658,9 +658,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp,
+       struct kmem_cache *cachep;
+       int ret, tries = 0;
++      rcu_read_lock();
+       gl = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
+       if (gl && !lockref_get_not_dead(&gl->gl_lockref))
+               gl = NULL;
++      rcu_read_unlock();
+       *glp = gl;
+       if (gl)
+@@ -728,15 +730,18 @@ again:
+       if (ret == -EEXIST) {
+               ret = 0;
++              rcu_read_lock();
+               tmp = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
+               if (tmp == NULL || !lockref_get_not_dead(&tmp->gl_lockref)) {
+                       if (++tries < 100) {
++                              rcu_read_unlock();
+                               cond_resched();
+                               goto again;
+                       }
+                       tmp = NULL;
+                       ret = -ENOMEM;
+               }
++              rcu_read_unlock();
+       } else {
+               WARN_ON_ONCE(ret);
+       }
diff --git a/queue-4.10/hv-allocate-synic-pages-for-all-present-cpus.patch b/queue-4.10/hv-allocate-synic-pages-for-all-present-cpus.patch
new file mode 100644 (file)
index 0000000..c4618b8
--- /dev/null
@@ -0,0 +1,41 @@
+From 421b8f20d3c381b215f988b42428f56fc3b82405 Mon Sep 17 00:00:00 2001
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+Date: Wed, 7 Dec 2016 01:16:25 -0800
+Subject: hv: allocate synic pages for all present CPUs
+
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+commit 421b8f20d3c381b215f988b42428f56fc3b82405 upstream.
+
+It may happen that not all CPUs are online when we do hv_synic_alloc() and
+in case more CPUs come online later we may try accessing these allocated
+structures.
+
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/hv.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/hv/hv.c
++++ b/drivers/hv/hv.c
+@@ -411,7 +411,7 @@ int hv_synic_alloc(void)
+               goto err;
+       }
+-      for_each_online_cpu(cpu) {
++      for_each_present_cpu(cpu) {
+               hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
+               if (hv_context.event_dpc[cpu] == NULL) {
+                       pr_err("Unable to allocate event dpc\n");
+@@ -482,7 +482,7 @@ void hv_synic_free(void)
+       int cpu;
+       kfree(hv_context.hv_numa_map);
+-      for_each_online_cpu(cpu)
++      for_each_present_cpu(cpu)
+               hv_synic_free_cpu(cpu);
+ }
diff --git a/queue-4.10/hv-don-t-reset-hv_context.tsc_page-on-crash.patch b/queue-4.10/hv-don-t-reset-hv_context.tsc_page-on-crash.patch
new file mode 100644 (file)
index 0000000..b310a2e
--- /dev/null
@@ -0,0 +1,37 @@
+From 56ef6718a1d8d77745033c5291e025ce18504159 Mon Sep 17 00:00:00 2001
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+Date: Wed, 7 Dec 2016 01:16:27 -0800
+Subject: hv: don't reset hv_context.tsc_page on crash
+
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+commit 56ef6718a1d8d77745033c5291e025ce18504159 upstream.
+
+It may happen that secondary CPUs are still alive and resetting
+hv_context.tsc_page will cause a consequent crash in read_hv_clock_tsc()
+as we don't check for it being not NULL there. It is safe as we're not
+freeing this page anyways.
+
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/hv.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/hv/hv.c
++++ b/drivers/hv/hv.c
+@@ -309,9 +309,10 @@ void hv_cleanup(bool crash)
+               hypercall_msr.as_uint64 = 0;
+               wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
+-              if (!crash)
++              if (!crash) {
+                       vfree(hv_context.tsc_page);
+-              hv_context.tsc_page = NULL;
++                      hv_context.tsc_page = NULL;
++              }
+       }
+ #endif
+ }
diff --git a/queue-4.10/hv-init-percpu_list-in-hv_synic_alloc.patch b/queue-4.10/hv-init-percpu_list-in-hv_synic_alloc.patch
new file mode 100644 (file)
index 0000000..f1d565f
--- /dev/null
@@ -0,0 +1,41 @@
+From 3c7630d35009e6635e5b58d62de554fd5b6db5df Mon Sep 17 00:00:00 2001
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+Date: Wed, 7 Dec 2016 01:16:26 -0800
+Subject: hv: init percpu_list in hv_synic_alloc()
+
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+commit 3c7630d35009e6635e5b58d62de554fd5b6db5df upstream.
+
+Initializing hv_context.percpu_list in hv_synic_alloc() helps to prevent a
+crash in percpu_channel_enq() when not all CPUs were online during
+initialization and it naturally belongs there.
+
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hv/hv.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/hv/hv.c
++++ b/drivers/hv/hv.c
+@@ -457,6 +457,8 @@ int hv_synic_alloc(void)
+                       pr_err("Unable to allocate post msg page\n");
+                       goto err;
+               }
++
++              INIT_LIST_HEAD(&hv_context.percpu_list[cpu]);
+       }
+       return 0;
+@@ -552,8 +554,6 @@ void hv_synic_init(void *arg)
+       rdmsrl(HV_X64_MSR_VP_INDEX, vp_index);
+       hv_context.vp_index[cpu] = (u32)vp_index;
+-      INIT_LIST_HEAD(&hv_context.percpu_list[cpu]);
+-
+       /*
+        * Register the per-cpu clockevent source.
+        */
diff --git a/queue-4.10/iio-pressure-mpl115-do-not-rely-on-structure-field-ordering.patch b/queue-4.10/iio-pressure-mpl115-do-not-rely-on-structure-field-ordering.patch
new file mode 100644 (file)
index 0000000..62bc00d
--- /dev/null
@@ -0,0 +1,51 @@
+From 6a6e1d56a0769795a36c0461c64bf5e5b9bbb4c0 Mon Sep 17 00:00:00 2001
+From: Peter Rosin <peda@axentia.se>
+Date: Wed, 1 Feb 2017 21:40:57 +0100
+Subject: iio: pressure: mpl115: do not rely on structure field ordering
+
+From: Peter Rosin <peda@axentia.se>
+
+commit 6a6e1d56a0769795a36c0461c64bf5e5b9bbb4c0 upstream.
+
+Fixes a regression triggered by a change in the layout of
+struct iio_chan_spec, but the real bug is in the driver which assumed
+a specific structure layout in the first place. Hint: the three bits were
+not OR:ed together as implied by the indentation prior to this patch,
+there was a comma between the first two, which accidentally moved the
+..._SCALE and ..._OFFSET bits to the next structure field. That field
+was .info_mask_shared_by_type before the _available attributes was added
+by commit 51239600074b ("iio:core: add a callback to allow drivers to
+provide _available attributes") and .info_mask_separate_available
+afterwards, and the regression happened.
+
+info_mask_shared_by_type is actually a better choice than the originally
+intended info_mask_separate for the ..._SCALE and ..._OFFSET bits since
+a constant is returned from mpl115_read_raw for the scale/offset. Using
+info_mask_shared_by_type also preserves the behavior from before the
+regression and is therefore less likely to cause other interesting side
+effects.
+
+The above mentioned regression causes unintended sysfs attibutes to
+show up that are not backed by code, in turn causing a NULL pointer
+defererence to happen on access.
+
+Fixes: 3017d90e8931 ("iio: Add Freescale MPL115A2 pressure / temperature sensor driver")
+Fixes: 51239600074b ("iio:core: add a callback to allow drivers to provide _available attributes")
+Signed-off-by: Peter Rosin <peda@axentia.se>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/pressure/mpl115.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/iio/pressure/mpl115.c
++++ b/drivers/iio/pressure/mpl115.c
+@@ -137,6 +137,7 @@ static const struct iio_chan_spec mpl115
+       {
+               .type = IIO_TEMP,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
++              .info_mask_shared_by_type =
+                       BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
+       },
+ };
diff --git a/queue-4.10/iio-pressure-mpl3115-do-not-rely-on-structure-field-ordering.patch b/queue-4.10/iio-pressure-mpl3115-do-not-rely-on-structure-field-ordering.patch
new file mode 100644 (file)
index 0000000..8bc756d
--- /dev/null
@@ -0,0 +1,128 @@
+From 9cf6cdba586ced75c69b8314b88b2d2f5ce9b3ed Mon Sep 17 00:00:00 2001
+From: Peter Rosin <peda@axentia.se>
+Date: Wed, 1 Feb 2017 21:40:56 +0100
+Subject: iio: pressure: mpl3115: do not rely on structure field ordering
+
+From: Peter Rosin <peda@axentia.se>
+
+commit 9cf6cdba586ced75c69b8314b88b2d2f5ce9b3ed upstream.
+
+Fixes a regression triggered by a change in the layout of
+struct iio_chan_spec, but the real bug is in the driver which assumed
+a specific structure layout in the first place. Hint: the two bits were
+not OR:ed together as implied by the indentation prior to this patch,
+there was a comma between them, which accidentally moved the ..._SCALE
+bit to the next structure field. That field was .info_mask_shared_by_type
+before the _available attributes was added by commit 51239600074b
+("iio:core: add a callback to allow drivers to provide _available
+attributes") and .info_mask_separate_available afterwards, and the
+regression happened.
+
+info_mask_shared_by_type is actually a better choice than the originally
+intended info_mask_separate for the ..._SCALE bit since a constant is
+returned from mpl3115_read_raw for the scale. Using
+info_mask_shared_by_type also preserves the behavior from before the
+regression and is therefore less likely to cause other interesting side
+effects.
+
+The above mentioned regression causes an unintended sysfs attibute to
+show up that is not backed by code, in turn causing the following NULL
+pointer defererence to happen on access.
+
+Segmentation fault
+
+Unable to handle kernel NULL pointer dereference at virtual address 00000000
+pgd = ecc3c000
+[00000000] *pgd=87f91831
+Internal error: Oops: 80000007 [#1] SMP ARM
+Modules linked in:
+CPU: 1 PID: 1051 Comm: cat Not tainted 4.10.0-rc5-00009-gffd8858-dirty #3
+Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
+task: ed54ec00 task.stack: ee2bc000
+PC is at 0x0
+LR is at iio_read_channel_info_avail+0x40/0x280
+pc : [<00000000>]    lr : [<c06fbc1c>]    psr: a0070013
+sp : ee2bdda8  ip : 00000000  fp : ee2bddf4
+r10: c0a53c74  r9 : ed79f000  r8 : ee8d1018
+r7 : 00001000  r6 : 00000fff  r5 : ee8b9a00  r4 : ed79f000
+r3 : ee2bddc4  r2 : ee2bddbc  r1 : c0a86dcc  r0 : ee8d1000
+Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
+Control: 10c5387d  Table: 3cc3c04a  DAC: 00000051
+Process cat (pid: 1051, stack limit = 0xee2bc210)
+Stack: (0xee2bdda8 to 0xee2be000)
+dda0:                   ee2bddc0 00000002 c016d720 c016d394 ed54ec00 00000000
+ddc0: 60070013 ed413780 00000001 edffd480 ee8b9a00 00000fff 00001000 ee8d1018
+dde0: ed79f000 c0a53c74 ee2bde0c ee2bddf8 c0513c58 c06fbbe8 edffd480 edffd540
+de00: ee2bde3c ee2bde10 c0293474 c0513c40 c02933e4 ee2bde60 00000001 ed413780
+de20: 00000001 ed413780 00000000 edffd480 ee2bde4c ee2bde40 c0291d00 c02933f0
+de40: ee2bde9c ee2bde50 c024679c c0291ce0 edffd4b0 b6e37000 00020000 ee2bdf78
+de60: 00000000 00000000 ed54ec00 ed013200 00000817 c0a111fc edffd540 ed413780
+de80: b6e37000 00020000 00020000 ee2bdf78 ee2bded4 ee2bdea0 c0292890 c0246604
+dea0: c0117940 c016ba50 00000025 c0a111fc b6e37000 ed413780 ee2bdf78 00020000
+dec0: ee2bc000 b6e37000 ee2bdf44 ee2bded8 c021d158 c0292770 c0117764 b6e36004
+dee0: c0f0d7c4 ee2bdfb0 b6f89228 00021008 ee2bdfac ee2bdf00 c0101374 c0117770
+df00: 00000000 00000000 ee2bc000 00000000 ee2bdf34 ee2bdf20 c016ba04 c0171080
+df20: 00000000 00020000 ed413780 b6e37000 00000000 ee2bdf78 ee2bdf74 ee2bdf48
+df40: c021e7a0 c021d130 c023e300 c023e280 ee2bdf74 00000000 00000000 ed413780
+df60: ed413780 00020000 ee2bdfa4 ee2bdf78 c021e870 c021e71c 00000000 00000000
+df80: 00020000 00020000 b6e37000 00000003 c0108084 00000000 00000000 ee2bdfa8
+dfa0: c0107ee0 c021e838 00020000 00020000 00000003 b6e37000 00020000 0001a2b4
+dfc0: 00020000 00020000 b6e37000 00000003 7fffe000 00000000 00000000 00020000
+dfe0: 00000000 be98eb4c 0000c740 b6f1985c 60070010 00000003 00000000 00000000
+Backtrace:
+[<c06fbbdc>] (iio_read_channel_info_avail) from [<c0513c58>] (dev_attr_show+0x24/0x50)
+ r10:c0a53c74 r9:ed79f000 r8:ee8d1018 r7:00001000 r6:00000fff r5:ee8b9a00
+ r4:edffd480
+[<c0513c34>] (dev_attr_show) from [<c0293474>] (sysfs_kf_seq_show+0x90/0x110)
+ r5:edffd540 r4:edffd480
+[<c02933e4>] (sysfs_kf_seq_show) from [<c0291d00>] (kernfs_seq_show+0x2c/0x30)
+ r10:edffd480 r9:00000000 r8:ed413780 r7:00000001 r6:ed413780 r5:00000001
+ r4:ee2bde60 r3:c02933e4
+[<c0291cd4>] (kernfs_seq_show) from [<c024679c>] (seq_read+0x1a4/0x4e0)
+[<c02465f8>] (seq_read) from [<c0292890>] (kernfs_fop_read+0x12c/0x1cc)
+ r10:ee2bdf78 r9:00020000 r8:00020000 r7:b6e37000 r6:ed413780 r5:edffd540
+ r4:c0a111fc
+[<c0292764>] (kernfs_fop_read) from [<c021d158>] (__vfs_read+0x34/0x118)
+ r10:b6e37000 r9:ee2bc000 r8:00020000 r7:ee2bdf78 r6:ed413780 r5:b6e37000
+ r4:c0a111fc
+[<c021d124>] (__vfs_read) from [<c021e7a0>] (vfs_read+0x90/0x11c)
+ r8:ee2bdf78 r7:00000000 r6:b6e37000 r5:ed413780 r4:00020000
+[<c021e710>] (vfs_read) from [<c021e870>] (SyS_read+0x44/0x90)
+ r8:00020000 r7:ed413780 r6:ed413780 r5:00000000 r4:00000000
+[<c021e82c>] (SyS_read) from [<c0107ee0>] (ret_fast_syscall+0x0/0x1c)
+ r10:00000000 r8:c0108084 r7:00000003 r6:b6e37000 r5:00020000 r4:00020000
+Code: bad PC value
+---[ end trace 9c4938ccd0389004 ]---
+
+Fixes: cc26ad455f57 ("iio: Add Freescale MPL3115A2 pressure / temperature sensor driver")
+Fixes: 51239600074b ("iio:core: add a callback to allow drivers to provide _available attributes")
+Reported-by: Ken Lin <ken.lin@advantech.com>
+Tested-by: Ken Lin <ken.lin@advantech.com>
+Signed-off-by: Peter Rosin <peda@axentia.se>
+Signed-off-by: Jonathan Cameron <jic23@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iio/pressure/mpl3115.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/iio/pressure/mpl3115.c
++++ b/drivers/iio/pressure/mpl3115.c
+@@ -190,7 +190,7 @@ static const struct iio_chan_spec mpl311
+       {
+               .type = IIO_PRESSURE,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+-                      BIT(IIO_CHAN_INFO_SCALE),
++              .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .scan_index = 0,
+               .scan_type = {
+                       .sign = 'u',
+@@ -203,7 +203,7 @@ static const struct iio_chan_spec mpl311
+       {
+               .type = IIO_TEMP,
+               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+-                      BIT(IIO_CHAN_INFO_SCALE),
++              .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+               .scan_index = 1,
+               .scan_type = {
+                       .sign = 's',
diff --git a/queue-4.10/md-linear-fix-a-race-between-linear_add-and-linear_congested.patch b/queue-4.10/md-linear-fix-a-race-between-linear_add-and-linear_congested.patch
new file mode 100644 (file)
index 0000000..902c563
--- /dev/null
@@ -0,0 +1,171 @@
+From 03a9e24ef2aaa5f1f9837356aed79c860521407a Mon Sep 17 00:00:00 2001
+From: "colyli@suse.de" <colyli@suse.de>
+Date: Sat, 28 Jan 2017 21:11:49 +0800
+Subject: md linear: fix a race between linear_add() and linear_congested()
+
+From: colyli@suse.de <colyli@suse.de>
+
+commit 03a9e24ef2aaa5f1f9837356aed79c860521407a upstream.
+
+Recently I receive a bug report that on Linux v3.0 based kerenl, hot add
+disk to a md linear device causes kernel crash at linear_congested(). From
+the crash image analysis, I find in linear_congested(), mddev->raid_disks
+contains value N, but conf->disks[] only has N-1 pointers available. Then
+a NULL pointer deference crashes the kernel.
+
+There is a race between linear_add() and linear_congested(), RCU stuffs
+used in these two functions cannot avoid the race. Since Linuv v4.0
+RCU code is replaced by introducing mddev_suspend().  After checking the
+upstream code, it seems linear_congested() is not called in
+generic_make_request() code patch, so mddev_suspend() cannot provent it
+from being called. The possible race still exists.
+
+Here I explain how the race still exists in current code.  For a machine
+has many CPUs, on one CPU, linear_add() is called to add a hard disk to a
+md linear device; at the same time on other CPU, linear_congested() is
+called to detect whether this md linear device is congested before issuing
+an I/O request onto it.
+
+Now I use a possible code execution time sequence to demo how the possible
+race happens,
+
+seq    linear_add()                linear_congested()
+ 0                                 conf=mddev->private
+ 1   oldconf=mddev->private
+ 2   mddev->raid_disks++
+ 3                              for (i=0; i<mddev->raid_disks;i++)
+ 4                                bdev_get_queue(conf->disks[i].rdev->bdev)
+ 5   mddev->private=newconf
+
+In linear_add() mddev->raid_disks is increased in time seq 2, and on
+another CPU in linear_congested() the for-loop iterates conf->disks[i] by
+the increased mddev->raid_disks in time seq 3,4. But conf with one more
+element (which is a pointer to struct dev_info type) to conf->disks[] is
+not updated yet, accessing its structure member in time seq 4 will cause a
+NULL pointer deference fault.
+
+To fix this race, there are 2 parts of modification in the patch,
+ 1) Add 'int raid_disks' in struct linear_conf, as a copy of
+    mddev->raid_disks. It is initialized in linear_conf(), always being
+    consistent with pointers number of 'struct dev_info disks[]'. When
+    iterating conf->disks[] in linear_congested(), use conf->raid_disks to
+    replace mddev->raid_disks in the for-loop, then NULL pointer deference
+    will not happen again.
+ 2) RCU stuffs are back again, and use kfree_rcu() in linear_add() to
+    free oldconf memory. Because oldconf may be referenced as mddev->private
+    in linear_congested(), kfree_rcu() makes sure that its memory will not
+    be released until no one uses it any more.
+Also some code comments are added in this patch, to make this modification
+to be easier understandable.
+
+This patch can be applied for kernels since v4.0 after commit:
+3be260cc18f8 ("md/linear: remove rcu protections in favour of
+suspend/resume"). But this bug is reported on Linux v3.0 based kernel, for
+people who maintain kernels before Linux v4.0, they need to do some back
+back port to this patch.
+
+Changelog:
+ - V3: add 'int raid_disks' in struct linear_conf, and use kfree_rcu() to
+       replace rcu_call() in linear_add().
+ - v2: add RCU stuffs by suggestion from Shaohua and Neil.
+ - v1: initial effort.
+
+Signed-off-by: Coly Li <colyli@suse.de>
+Cc: Shaohua Li <shli@fb.com>
+Cc: Neil Brown <neilb@suse.com>
+Signed-off-by: Shaohua Li <shli@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/linear.c |   39 ++++++++++++++++++++++++++++++++++-----
+ drivers/md/linear.h |    1 +
+ 2 files changed, 35 insertions(+), 5 deletions(-)
+
+--- a/drivers/md/linear.c
++++ b/drivers/md/linear.c
+@@ -53,18 +53,26 @@ static inline struct dev_info *which_dev
+       return conf->disks + lo;
+ }
++/*
++ * In linear_congested() conf->raid_disks is used as a copy of
++ * mddev->raid_disks to iterate conf->disks[], because conf->raid_disks
++ * and conf->disks[] are created in linear_conf(), they are always
++ * consitent with each other, but mddev->raid_disks does not.
++ */
+ static int linear_congested(struct mddev *mddev, int bits)
+ {
+       struct linear_conf *conf;
+       int i, ret = 0;
+-      conf = mddev->private;
++      rcu_read_lock();
++      conf = rcu_dereference(mddev->private);
+-      for (i = 0; i < mddev->raid_disks && !ret ; i++) {
++      for (i = 0; i < conf->raid_disks && !ret ; i++) {
+               struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
+               ret |= bdi_congested(&q->backing_dev_info, bits);
+       }
++      rcu_read_unlock();
+       return ret;
+ }
+@@ -144,6 +152,19 @@ static struct linear_conf *linear_conf(s
+                       conf->disks[i-1].end_sector +
+                       conf->disks[i].rdev->sectors;
++      /*
++       * conf->raid_disks is copy of mddev->raid_disks. The reason to
++       * keep a copy of mddev->raid_disks in struct linear_conf is,
++       * mddev->raid_disks may not be consistent with pointers number of
++       * conf->disks[] when it is updated in linear_add() and used to
++       * iterate old conf->disks[] earray in linear_congested().
++       * Here conf->raid_disks is always consitent with number of
++       * pointers in conf->disks[] array, and mddev->private is updated
++       * with rcu_assign_pointer() in linear_addr(), such race can be
++       * avoided.
++       */
++      conf->raid_disks = raid_disks;
++
+       return conf;
+ out:
+@@ -196,15 +217,23 @@ static int linear_add(struct mddev *mdde
+       if (!newconf)
+               return -ENOMEM;
++      /* newconf->raid_disks already keeps a copy of * the increased
++       * value of mddev->raid_disks, WARN_ONCE() is just used to make
++       * sure of this. It is possible that oldconf is still referenced
++       * in linear_congested(), therefore kfree_rcu() is used to free
++       * oldconf until no one uses it anymore.
++       */
+       mddev_suspend(mddev);
+-      oldconf = mddev->private;
++      oldconf = rcu_dereference(mddev->private);
+       mddev->raid_disks++;
+-      mddev->private = newconf;
++      WARN_ONCE(mddev->raid_disks != newconf->raid_disks,
++              "copied raid_disks doesn't match mddev->raid_disks");
++      rcu_assign_pointer(mddev->private, newconf);
+       md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
+       set_capacity(mddev->gendisk, mddev->array_sectors);
+       mddev_resume(mddev);
+       revalidate_disk(mddev->gendisk);
+-      kfree(oldconf);
++      kfree_rcu(oldconf, rcu);
+       return 0;
+ }
+--- a/drivers/md/linear.h
++++ b/drivers/md/linear.h
+@@ -10,6 +10,7 @@ struct linear_conf
+ {
+       struct rcu_head         rcu;
+       sector_t                array_sectors;
++      int                     raid_disks; /* a copy of mddev->raid_disks */
+       struct dev_info         disks[0];
+ };
+ #endif
diff --git a/queue-4.10/mips-ip22-fix-build-error-due-to-binutils-2.25-uselessnes.patch b/queue-4.10/mips-ip22-fix-build-error-due-to-binutils-2.25-uselessnes.patch
new file mode 100644 (file)
index 0000000..028a8c3
--- /dev/null
@@ -0,0 +1,66 @@
+From ae2f5e5ed04a17c1aa1f0a3714c725e12c21d2a9 Mon Sep 17 00:00:00 2001
+From: Ralf Baechle <ralf@linux-mips.org>
+Date: Thu, 15 Dec 2016 12:39:22 +0100
+Subject: MIPS: IP22: Fix build error due to binutils 2.25 uselessnes.
+
+From: Ralf Baechle <ralf@linux-mips.org>
+
+commit ae2f5e5ed04a17c1aa1f0a3714c725e12c21d2a9 upstream.
+
+Fix the following build error with binutils 2.25.
+
+  CC      arch/mips/mm/sc-ip22.o
+{standard input}: Assembler messages:
+{standard input}:132: Error: number (0x9000000080000000) larger than 32 bits
+{standard input}:159: Error: number (0x9000000080000000) larger than 32 bits
+{standard input}:200: Error: number (0x9000000080000000) larger than 32 bits
+scripts/Makefile.build:293: recipe for target 'arch/mips/mm/sc-ip22.o' failed
+make[1]: *** [arch/mips/mm/sc-ip22.o] Error 1
+
+MIPS has used .set mips3 to temporarily switch the assembler to 64 bit
+mode in 64 bit kernels virtually forever.  Binutils 2.25 broke this
+behavious partially by happily accepting 64 bit instructions in .set mips3
+mode but puking on 64 bit constants when generating 32 bit ELF.  Binutils
+2.26 restored the old behaviour again.
+
+Fix build with binutils 2.25 by open coding the offending
+
+       dli $1, 0x9000000080000000
+
+as
+
+       li      $1, 0x9000
+       dsll    $1, $1, 48
+
+which is ugly be the only thing that will build on all binutils vintages.
+
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/mips/mm/sc-ip22.c |   13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/arch/mips/mm/sc-ip22.c
++++ b/arch/mips/mm/sc-ip22.c
+@@ -39,7 +39,18 @@ static inline void indy_sc_wipe(unsigned
+       "       li      $1, 0x80                # Go 64 bit             \n"
+       "       mtc0    $1, $12                                         \n"
+       "                                                               \n"
+-      "       dli     $1, 0x9000000080000000                          \n"
++      "       #                                                       \n"
++      "       # Open code a dli $1, 0x9000000080000000                \n"
++      "       #                                                       \n"
++      "       # Required because binutils 2.25 will happily accept    \n"
++      "       # 64 bit instructions in .set mips3 mode but puke on    \n"
++      "       # 64 bit constants when generating 32 bit ELF           \n"
++      "       #                                                       \n"
++      "       lui     $1,0x9000                                       \n"
++      "       dsll    $1,$1,0x10                                      \n"
++      "       ori     $1,$1,0x8000                                    \n"
++      "       dsll    $1,$1,0x10                                      \n"
++      "                                                               \n"
+       "       or      %0, $1                  # first line to flush   \n"
+       "       or      %1, $1                  # last line to flush    \n"
+       "       .set    at                                              \n"
diff --git a/queue-4.10/mips-ip22-reformat-inline-assembler-code-to-modern-standards.patch b/queue-4.10/mips-ip22-reformat-inline-assembler-code-to-modern-standards.patch
new file mode 100644 (file)
index 0000000..7d811b8
--- /dev/null
@@ -0,0 +1,68 @@
+From f9f1c8db1c37253805eaa32265e1e1af3ae7d0a4 Mon Sep 17 00:00:00 2001
+From: Ralf Baechle <ralf@linux-mips.org>
+Date: Thu, 15 Dec 2016 12:27:21 +0100
+Subject: MIPS: IP22: Reformat inline assembler code to modern standards.
+
+From: Ralf Baechle <ralf@linux-mips.org>
+
+commit f9f1c8db1c37253805eaa32265e1e1af3ae7d0a4 upstream.
+
+Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/mips/mm/sc-ip22.c |   43 +++++++++++++++++++++++--------------------
+ 1 file changed, 23 insertions(+), 20 deletions(-)
+
+--- a/arch/mips/mm/sc-ip22.c
++++ b/arch/mips/mm/sc-ip22.c
+@@ -31,26 +31,29 @@ static inline void indy_sc_wipe(unsigned
+       unsigned long tmp;
+       __asm__ __volatile__(
+-      ".set\tpush\t\t\t# indy_sc_wipe\n\t"
+-      ".set\tnoreorder\n\t"
+-      ".set\tmips3\n\t"
+-      ".set\tnoat\n\t"
+-      "mfc0\t%2, $12\n\t"
+-      "li\t$1, 0x80\t\t\t# Go 64 bit\n\t"
+-      "mtc0\t$1, $12\n\t"
+-
+-      "dli\t$1, 0x9000000080000000\n\t"
+-      "or\t%0, $1\t\t\t# first line to flush\n\t"
+-      "or\t%1, $1\t\t\t# last line to flush\n\t"
+-      ".set\tat\n\t"
+-
+-      "1:\tsw\t$0, 0(%0)\n\t"
+-      "bne\t%0, %1, 1b\n\t"
+-      " daddu\t%0, 32\n\t"
+-
+-      "mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t"
+-      "nop; nop; nop; nop;\n\t"
+-      ".set\tpop"
++      "       .set    push                    # indy_sc_wipe          \n"
++      "       .set    noreorder                                       \n"
++      "       .set    mips3                                           \n"
++      "       .set    noat                                            \n"
++      "       mfc0    %2, $12                                         \n"
++      "       li      $1, 0x80                # Go 64 bit             \n"
++      "       mtc0    $1, $12                                         \n"
++      "                                                               \n"
++      "       dli     $1, 0x9000000080000000                          \n"
++      "       or      %0, $1                  # first line to flush   \n"
++      "       or      %1, $1                  # last line to flush    \n"
++      "       .set    at                                              \n"
++      "                                                               \n"
++      "1:     sw      $0, 0(%0)                                       \n"
++      "       bne     %0, %1, 1b                                      \n"
++      "        daddu  %0, 32                                          \n"
++      "                                                               \n"
++      "       mtc0    %2, $12                 # Back to 32 bit        \n"
++      "       nop                             # pipeline hazard       \n"
++      "       nop                                                     \n"
++      "       nop                                                     \n"
++      "       nop                                                     \n"
++      "       .set    pop                                             \n"
+       : "=r" (first), "=r" (last), "=&r" (tmp)
+       : "0" (first), "1" (last));
+ }
diff --git a/queue-4.10/module-fix-memory-leak-on-early-load_module-failures.patch b/queue-4.10/module-fix-memory-leak-on-early-load_module-failures.patch
new file mode 100644 (file)
index 0000000..7c69934
--- /dev/null
@@ -0,0 +1,65 @@
+From a5544880aff90baf1bd4443ac7ff65182213ffcd Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Fri, 10 Feb 2017 14:06:22 -0800
+Subject: module: fix memory leak on early load_module() failures
+
+From: Luis R. Rodriguez <mcgrof@kernel.org>
+
+commit a5544880aff90baf1bd4443ac7ff65182213ffcd upstream.
+
+While looking for early possible module loading failures I was
+able to reproduce a memory leak possible with kmemleak. There
+are a few rare ways to trigger a failure:
+
+  o we've run into a failure while processing kernel parameters
+    (parse_args() returns an error)
+  o mod_sysfs_setup() fails
+  o we're a live patch module and copy_module_elf() fails
+
+Chances of running into this issue is really low.
+
+kmemleak splat:
+
+unreferenced object 0xffff9f2c4ada1b00 (size 32):
+  comm "kworker/u16:4", pid 82, jiffies 4294897636 (age 681.816s)
+  hex dump (first 32 bytes):
+    6d 65 6d 73 74 69 63 6b 30 00 00 00 00 00 00 00  memstick0.......
+    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
+  backtrace:
+    [<ffffffff8c6cfeba>] kmemleak_alloc+0x4a/0xa0
+    [<ffffffff8c200046>] __kmalloc_track_caller+0x126/0x230
+    [<ffffffff8c1bc581>] kstrdup+0x31/0x60
+    [<ffffffff8c1bc5d4>] kstrdup_const+0x24/0x30
+    [<ffffffff8c3c23aa>] kvasprintf_const+0x7a/0x90
+    [<ffffffff8c3b5481>] kobject_set_name_vargs+0x21/0x90
+    [<ffffffff8c4fbdd7>] dev_set_name+0x47/0x50
+    [<ffffffffc07819e5>] memstick_check+0x95/0x33c [memstick]
+    [<ffffffff8c09c893>] process_one_work+0x1f3/0x4b0
+    [<ffffffff8c09cb98>] worker_thread+0x48/0x4e0
+    [<ffffffff8c0a2b79>] kthread+0xc9/0xe0
+    [<ffffffff8c6dab5f>] ret_from_fork+0x1f/0x40
+    [<ffffffffffffffff>] 0xffffffffffffffff
+
+Fixes: e180a6b7759a ("param: fix charp parameters set via sysfs")
+Reviewed-by: Miroslav Benes <mbenes@suse.cz>
+Reviewed-by: Aaron Tomlin <atomlin@redhat.com>
+Reviewed-by: Rusty Russell <rusty@rustcorp.com.au>
+Acked-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Signed-off-by: Jessica Yu <jeyu@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/module.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -3719,6 +3719,7 @@ static int load_module(struct load_info
+       mod_sysfs_teardown(mod);
+  coming_cleanup:
+       mod->state = MODULE_STATE_GOING;
++      destroy_params(mod->kp, mod->num_kp);
+       blocking_notifier_call_chain(&module_notify_list,
+                                    MODULE_STATE_GOING, mod);
+       klp_module_going(mod);
diff --git a/queue-4.10/mtd-nand-ifc-fix-location-of-eccstat-registers-for-ifc-v1.0.patch b/queue-4.10/mtd-nand-ifc-fix-location-of-eccstat-registers-for-ifc-v1.0.patch
new file mode 100644 (file)
index 0000000..ab599cb
--- /dev/null
@@ -0,0 +1,63 @@
+From 656441478ed55d960df5f3ccdf5a0f8c61dfd0b3 Mon Sep 17 00:00:00 2001
+From: Mark Marshall <mark.marshall@omicronenergy.com>
+Date: Thu, 26 Jan 2017 16:18:27 +0100
+Subject: mtd: nand: ifc: Fix location of eccstat registers for IFC V1.0
+
+From: Mark Marshall <mark.marshall@omicronenergy.com>
+
+commit 656441478ed55d960df5f3ccdf5a0f8c61dfd0b3 upstream.
+
+The commit 7a654172161c ("mtd/ifc: Add support for IFC controller
+version 2.0") added support for version 2.0 of the IFC controller.
+The version 2.0 controller has the ECC status registers at a different
+location to the previous versions.
+
+Correct the fsl_ifc_nand structure so that the ECC status can be read
+from the correct location for both version 1.0 and 2.0 of the controller.
+
+Fixes: 7a654172161c ("mtd/ifc: Add support for IFC controller version 2.0")
+Signed-off-by: Mark Marshall <mark.marshall@omicronenergy.com>
+Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mtd/nand/fsl_ifc_nand.c |    8 +++++++-
+ include/linux/fsl_ifc.h         |    8 ++++++--
+ 2 files changed, 13 insertions(+), 3 deletions(-)
+
+--- a/drivers/mtd/nand/fsl_ifc_nand.c
++++ b/drivers/mtd/nand/fsl_ifc_nand.c
+@@ -258,9 +258,15 @@ static void fsl_ifc_run_command(struct m
+               int bufnum = nctrl->page & priv->bufnum_mask;
+               int sector = bufnum * chip->ecc.steps;
+               int sector_end = sector + chip->ecc.steps - 1;
++              __be32 *eccstat_regs;
++
++              if (ctrl->version >= FSL_IFC_VERSION_2_0_0)
++                      eccstat_regs = ifc->ifc_nand.v2_nand_eccstat;
++              else
++                      eccstat_regs = ifc->ifc_nand.v1_nand_eccstat;
+               for (i = sector / 4; i <= sector_end / 4; i++)
+-                      eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]);
++                      eccstat[i] = ifc_in32(&eccstat_regs[i]);
+               for (i = sector; i <= sector_end; i++) {
+                       errors = check_read_ecc(mtd, ctrl, eccstat, i);
+--- a/include/linux/fsl_ifc.h
++++ b/include/linux/fsl_ifc.h
+@@ -733,8 +733,12 @@ struct fsl_ifc_nand {
+       __be32 nand_erattr1;
+       u32 res19[0x10];
+       __be32 nand_fsr;
+-      u32 res20[0x3];
+-      __be32 nand_eccstat[6];
++      u32 res20;
++      /* The V1 nand_eccstat is actually 4 words that overlaps the
++       * V2 nand_eccstat.
++       */
++      __be32 v1_nand_eccstat[2];
++      __be32 v2_nand_eccstat[6];
+       u32 res21[0x1c];
+       __be32 nanndcr;
+       u32 res22[0x2];
diff --git a/queue-4.10/nfsd-minor-nfsd_setattr-cleanup.patch b/queue-4.10/nfsd-minor-nfsd_setattr-cleanup.patch
new file mode 100644 (file)
index 0000000..33afd49
--- /dev/null
@@ -0,0 +1,97 @@
+From 758e99fefe1d9230111296956335cd35995c0eaf Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch@lst.de>
+Date: Mon, 20 Feb 2017 17:04:42 -0500
+Subject: nfsd: minor nfsd_setattr cleanup
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 758e99fefe1d9230111296956335cd35995c0eaf upstream.
+
+Simplify exit paths, size_change use.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfsd/vfs.c |   29 ++++++++++++-----------------
+ 1 file changed, 12 insertions(+), 17 deletions(-)
+
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -377,7 +377,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str
+       __be32          err;
+       int             host_err;
+       bool            get_write_count;
+-      int             size_change = 0;
++      bool            size_change = (iap->ia_valid & ATTR_SIZE);
+       if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
+               accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE;
+@@ -390,11 +390,11 @@ nfsd_setattr(struct svc_rqst *rqstp, str
+       /* Get inode */
+       err = fh_verify(rqstp, fhp, ftype, accmode);
+       if (err)
+-              goto out;
++              return err;
+       if (get_write_count) {
+               host_err = fh_want_write(fhp);
+               if (host_err)
+-                      return nfserrno(host_err);
++                      goto out;
+       }
+       dentry = fhp->fh_dentry;
+@@ -405,19 +405,21 @@ nfsd_setattr(struct svc_rqst *rqstp, str
+               iap->ia_valid &= ~ATTR_MODE;
+       if (!iap->ia_valid)
+-              goto out;
++              return 0;
+       nfsd_sanitize_attrs(inode, iap);
++      if (check_guard && guardtime != inode->i_ctime.tv_sec)
++              return nfserr_notsync;
++
+       /*
+        * The size case is special, it changes the file in addition to the
+        * attributes.
+        */
+-      if (iap->ia_valid & ATTR_SIZE) {
++      if (size_change) {
+               err = nfsd_get_write_access(rqstp, fhp, iap);
+               if (err)
+-                      goto out;
+-              size_change = 1;
++                      return err;
+               /*
+                * RFC5661, Section 18.30.4:
+@@ -432,23 +434,16 @@ nfsd_setattr(struct svc_rqst *rqstp, str
+       iap->ia_valid |= ATTR_CTIME;
+-      if (check_guard && guardtime != inode->i_ctime.tv_sec) {
+-              err = nfserr_notsync;
+-              goto out_put_write_access;
+-      }
+-
+       fh_lock(fhp);
+       host_err = notify_change(dentry, iap, NULL);
+       fh_unlock(fhp);
+-      err = nfserrno(host_err);
+-out_put_write_access:
+       if (size_change)
+               put_write_access(inode);
+-      if (!err)
+-              err = nfserrno(commit_metadata(fhp));
+ out:
+-      return err;
++      if (!host_err)
++              host_err = commit_metadata(fhp);
++      return nfserrno(host_err);
+ }
+ #if defined(CONFIG_NFSD_V4)
diff --git a/queue-4.10/nfsd-special-case-truncates-some-more.patch b/queue-4.10/nfsd-special-case-truncates-some-more.patch
new file mode 100644 (file)
index 0000000..9accc2c
--- /dev/null
@@ -0,0 +1,94 @@
+From 783112f7401ff449d979530209b3f6c2594fdb4e Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch@lst.de>
+Date: Mon, 20 Feb 2017 07:21:33 +0100
+Subject: nfsd: special case truncates some more
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 783112f7401ff449d979530209b3f6c2594fdb4e upstream.
+
+Both the NFS protocols and the Linux VFS use a setattr operation with a
+bitmap of attributes to set to set various file attributes including the
+file size and the uid/gid.
+
+The Linux syscalls never mix size updates with unrelated updates like
+the uid/gid, and some file systems like XFS and GFS2 rely on the fact
+that truncates don't update random other attributes, and many other file
+systems handle the case but do not update the other attributes in the
+same transaction.  NFSD on the other hand passes the attributes it gets
+on the wire more or less directly through to the VFS, leading to updates
+the file systems don't expect.  XFS at least has an assert on the
+allowed attributes, which caught an unusual NFS client setting the size
+and group at the same time.
+
+To handle this issue properly this splits the notify_change call in
+nfsd_setattr into two separate ones.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Tested-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfsd/vfs.c |   32 ++++++++++++++++++++++++++------
+ 1 file changed, 26 insertions(+), 6 deletions(-)
+
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -414,13 +414,19 @@ nfsd_setattr(struct svc_rqst *rqstp, str
+       /*
+        * The size case is special, it changes the file in addition to the
+-       * attributes.
++       * attributes, and file systems don't expect it to be mixed with
++       * "random" attribute changes.  We thus split out the size change
++       * into a separate call to ->setattr, and do the rest as a separate
++       * setattr call.
+        */
+       if (size_change) {
+               err = nfsd_get_write_access(rqstp, fhp, iap);
+               if (err)
+                       return err;
++      }
++      fh_lock(fhp);
++      if (size_change) {
+               /*
+                * RFC5661, Section 18.30.4:
+                *   Changing the size of a file with SETATTR indirectly
+@@ -428,16 +434,30 @@ nfsd_setattr(struct svc_rqst *rqstp, str
+                *
+                * (and similar for the older RFCs)
+                */
+-              if (iap->ia_size != i_size_read(inode))
+-                      iap->ia_valid |= ATTR_MTIME;
++              struct iattr size_attr = {
++                      .ia_valid       = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME,
++                      .ia_size        = iap->ia_size,
++              };
++
++              host_err = notify_change(dentry, &size_attr, NULL);
++              if (host_err)
++                      goto out_unlock;
++              iap->ia_valid &= ~ATTR_SIZE;
++
++              /*
++               * Avoid the additional setattr call below if the only other
++               * attribute that the client sends is the mtime, as we update
++               * it as part of the size change above.
++               */
++              if ((iap->ia_valid & ~ATTR_MTIME) == 0)
++                      goto out_unlock;
+       }
+       iap->ia_valid |= ATTR_CTIME;
+-
+-      fh_lock(fhp);
+       host_err = notify_change(dentry, iap, NULL);
+-      fh_unlock(fhp);
++out_unlock:
++      fh_unlock(fhp);
+       if (size_change)
+               put_write_access(inode);
+ out:
diff --git a/queue-4.10/nfsv4-fix-getacl-erange-for-some-acl-buffer-sizes.patch b/queue-4.10/nfsv4-fix-getacl-erange-for-some-acl-buffer-sizes.patch
new file mode 100644 (file)
index 0000000..c2e2cc5
--- /dev/null
@@ -0,0 +1,50 @@
+From ed92d8c137b7794c2c2aa14479298b9885967607 Mon Sep 17 00:00:00 2001
+From: Weston Andros Adamson <dros@primarydata.com>
+Date: Thu, 23 Feb 2017 14:54:21 -0500
+Subject: NFSv4: fix getacl ERANGE for some ACL buffer sizes
+
+From: Weston Andros Adamson <dros@primarydata.com>
+
+commit ed92d8c137b7794c2c2aa14479298b9885967607 upstream.
+
+We're not taking into account that the space needed for the (variable
+length) attr bitmap, with the result that we'd sometimes get a spurious
+ERANGE when the ACL data got close to the end of a page.
+
+Just add in an extra page to make sure.
+
+Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |    8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -5065,7 +5065,7 @@ out:
+  */
+ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
+ {
+-      struct page *pages[NFS4ACL_MAXPAGES] = {NULL, };
++      struct page *pages[NFS4ACL_MAXPAGES + 1] = {NULL, };
+       struct nfs_getaclargs args = {
+               .fh = NFS_FH(inode),
+               .acl_pages = pages,
+@@ -5079,13 +5079,9 @@ static ssize_t __nfs4_get_acl_uncached(s
+               .rpc_argp = &args,
+               .rpc_resp = &res,
+       };
+-      unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
++      unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE) + 1;
+       int ret = -ENOMEM, i;
+-      /* As long as we're doing a round trip to the server anyway,
+-       * let's be prepared for a page of acl data. */
+-      if (npages == 0)
+-              npages = 1;
+       if (npages > ARRAY_SIZE(pages))
+               return -ERANGE;
diff --git a/queue-4.10/nfsv4-fix-getacl-head-length-estimation.patch b/queue-4.10/nfsv4-fix-getacl-head-length-estimation.patch
new file mode 100644 (file)
index 0000000..f1e9417
--- /dev/null
@@ -0,0 +1,36 @@
+From 6682c14bbe505a8b912c57faf544f866777ee48d Mon Sep 17 00:00:00 2001
+From: "J. Bruce Fields" <bfields@redhat.com>
+Date: Thu, 23 Feb 2017 14:53:39 -0500
+Subject: NFSv4: fix getacl head length estimation
+
+From: J. Bruce Fields <bfields@redhat.com>
+
+commit 6682c14bbe505a8b912c57faf544f866777ee48d upstream.
+
+Bitmap and attrlen follow immediately after the op reply header.  This
+was an oversight from commit bf118a342f.
+
+Consequences of this are just minor efficiency (extra calls to
+xdr_shrink_bufhead).
+
+Fixes: bf118a342f10 "NFSv4: include bitmap in nfsv4 get acl data"
+Reviewed-by: Kinglong Mee <kinglongmee@gmail.com>
+Signed-off-by: J. Bruce Fields <bfields@redhat.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4xdr.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -2524,7 +2524,7 @@ static void nfs4_xdr_enc_getacl(struct r
+       encode_compound_hdr(xdr, req, &hdr);
+       encode_sequence(xdr, &args->seq_args, &hdr);
+       encode_putfh(xdr, args->fh, &hdr);
+-      replen = hdr.replen + op_decode_hdr_maxsz + 1;
++      replen = hdr.replen + op_decode_hdr_maxsz;
+       encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr);
+       xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
diff --git a/queue-4.10/nfsv4-fix-memory-and-state-leak-in-_nfs4_open_and_get_state.patch b/queue-4.10/nfsv4-fix-memory-and-state-leak-in-_nfs4_open_and_get_state.patch
new file mode 100644 (file)
index 0000000..d4edce4
--- /dev/null
@@ -0,0 +1,40 @@
+From a974deee477af89411e0f80456bfb344ac433c98 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Wed, 8 Feb 2017 11:29:46 -0500
+Subject: NFSv4: Fix memory and state leak in _nfs4_open_and_get_state
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit a974deee477af89411e0f80456bfb344ac433c98 upstream.
+
+If we exit because the file access check failed, we currently
+leak the struct nfs4_state. We need to attach it to the
+open context before returning.
+
+Fixes: 3efb9722475e ("NFSv4: Refactor _nfs4_open_and_get_state..")
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -2730,6 +2730,7 @@ static int _nfs4_open_and_get_state(stru
+       ret = PTR_ERR(state);
+       if (IS_ERR(state))
+               goto out;
++      ctx->state = state;
+       if (server->caps & NFS_CAP_POSIX_LOCK)
+               set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
+       if (opendata->o_res.rflags & NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK)
+@@ -2755,7 +2756,6 @@ static int _nfs4_open_and_get_state(stru
+       if (ret != 0)
+               goto out;
+-      ctx->state = state;
+       if (d_inode(dentry) == state->inode) {
+               nfs_inode_attach_open_context(ctx);
+               if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
diff --git a/queue-4.10/nfsv4-fix-reboot-recovery-in-copy-offload.patch b/queue-4.10/nfsv4-fix-reboot-recovery-in-copy-offload.patch
new file mode 100644 (file)
index 0000000..c0b9f70
--- /dev/null
@@ -0,0 +1,157 @@
+From 9d8cacbf5636657d2cd0dda17438a56d806d3224 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Fri, 17 Feb 2017 18:42:32 -0500
+Subject: NFSv4: Fix reboot recovery in copy offload
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit 9d8cacbf5636657d2cd0dda17438a56d806d3224 upstream.
+
+Copy offload code needs to be hooked into the code for handling
+NFS4ERR_BAD_STATEID by ensuring that we set the "stateid" field
+in struct nfs4_exception.
+
+Reported-by: Olga Kornievskaia <aglo@umich.edu>
+Fixes: 2e72448b07dc3 ("NFS: Add COPY nfs operation")
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs42proc.c |   63 +++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 37 insertions(+), 26 deletions(-)
+
+--- a/fs/nfs/nfs42proc.c
++++ b/fs/nfs/nfs42proc.c
+@@ -128,30 +128,26 @@ out_unlock:
+       return err;
+ }
+-static ssize_t _nfs42_proc_copy(struct file *src, loff_t pos_src,
++static ssize_t _nfs42_proc_copy(struct file *src,
+                               struct nfs_lock_context *src_lock,
+-                              struct file *dst, loff_t pos_dst,
++                              struct file *dst,
+                               struct nfs_lock_context *dst_lock,
+-                              size_t count)
++                              struct nfs42_copy_args *args,
++                              struct nfs42_copy_res *res)
+ {
+-      struct nfs42_copy_args args = {
+-              .src_fh         = NFS_FH(file_inode(src)),
+-              .src_pos        = pos_src,
+-              .dst_fh         = NFS_FH(file_inode(dst)),
+-              .dst_pos        = pos_dst,
+-              .count          = count,
+-      };
+-      struct nfs42_copy_res res;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COPY],
+-              .rpc_argp = &args,
+-              .rpc_resp = &res,
++              .rpc_argp = args,
++              .rpc_resp = res,
+       };
+       struct inode *dst_inode = file_inode(dst);
+       struct nfs_server *server = NFS_SERVER(dst_inode);
++      loff_t pos_src = args->src_pos;
++      loff_t pos_dst = args->dst_pos;
++      size_t count = args->count;
+       int status;
+-      status = nfs4_set_rw_stateid(&args.src_stateid, src_lock->open_context,
++      status = nfs4_set_rw_stateid(&args->src_stateid, src_lock->open_context,
+                                    src_lock, FMODE_READ);
+       if (status)
+               return status;
+@@ -161,7 +157,7 @@ static ssize_t _nfs42_proc_copy(struct f
+       if (status)
+               return status;
+-      status = nfs4_set_rw_stateid(&args.dst_stateid, dst_lock->open_context,
++      status = nfs4_set_rw_stateid(&args->dst_stateid, dst_lock->open_context,
+                                    dst_lock, FMODE_WRITE);
+       if (status)
+               return status;
+@@ -171,22 +167,22 @@ static ssize_t _nfs42_proc_copy(struct f
+               return status;
+       status = nfs4_call_sync(server->client, server, &msg,
+-                              &args.seq_args, &res.seq_res, 0);
++                              &args->seq_args, &res->seq_res, 0);
+       if (status == -ENOTSUPP)
+               server->caps &= ~NFS_CAP_COPY;
+       if (status)
+               return status;
+-      if (res.write_res.verifier.committed != NFS_FILE_SYNC) {
+-              status = nfs_commit_file(dst, &res.write_res.verifier.verifier);
++      if (res->write_res.verifier.committed != NFS_FILE_SYNC) {
++              status = nfs_commit_file(dst, &res->write_res.verifier.verifier);
+               if (status)
+                       return status;
+       }
+       truncate_pagecache_range(dst_inode, pos_dst,
+-                               pos_dst + res.write_res.count);
++                               pos_dst + res->write_res.count);
+-      return res.write_res.count;
++      return res->write_res.count;
+ }
+ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
+@@ -196,8 +192,22 @@ ssize_t nfs42_proc_copy(struct file *src
+       struct nfs_server *server = NFS_SERVER(file_inode(dst));
+       struct nfs_lock_context *src_lock;
+       struct nfs_lock_context *dst_lock;
+-      struct nfs4_exception src_exception = { };
+-      struct nfs4_exception dst_exception = { };
++      struct nfs42_copy_args args = {
++              .src_fh         = NFS_FH(file_inode(src)),
++              .src_pos        = pos_src,
++              .dst_fh         = NFS_FH(file_inode(dst)),
++              .dst_pos        = pos_dst,
++              .count          = count,
++      };
++      struct nfs42_copy_res res;
++      struct nfs4_exception src_exception = {
++              .inode          = file_inode(src),
++              .stateid        = &args.src_stateid,
++      };
++      struct nfs4_exception dst_exception = {
++              .inode          = file_inode(dst),
++              .stateid        = &args.dst_stateid,
++      };
+       ssize_t err, err2;
+       if (!nfs_server_capable(file_inode(dst), NFS_CAP_COPY))
+@@ -207,7 +217,6 @@ ssize_t nfs42_proc_copy(struct file *src
+       if (IS_ERR(src_lock))
+               return PTR_ERR(src_lock);
+-      src_exception.inode = file_inode(src);
+       src_exception.state = src_lock->open_context->state;
+       dst_lock = nfs_get_lock_context(nfs_file_open_context(dst));
+@@ -216,15 +225,17 @@ ssize_t nfs42_proc_copy(struct file *src
+               goto out_put_src_lock;
+       }
+-      dst_exception.inode = file_inode(dst);
+       dst_exception.state = dst_lock->open_context->state;
+       do {
+               inode_lock(file_inode(dst));
+-              err = _nfs42_proc_copy(src, pos_src, src_lock,
+-                                     dst, pos_dst, dst_lock, count);
++              err = _nfs42_proc_copy(src, src_lock,
++                              dst, dst_lock,
++                              &args, &res);
+               inode_unlock(file_inode(dst));
++              if (err >= 0)
++                      break;
+               if (err == -ENOTSUPP) {
+                       err = -EOPNOTSUPP;
+                       break;
diff --git a/queue-4.10/pnfs-flexfiles-if-the-layout-is-invalid-it-must-be-updated-before-retrying.patch b/queue-4.10/pnfs-flexfiles-if-the-layout-is-invalid-it-must-be-updated-before-retrying.patch
new file mode 100644 (file)
index 0000000..3c2d8a9
--- /dev/null
@@ -0,0 +1,58 @@
+From df3ab232e462bce20710596d697ade6b72497694 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Fri, 17 Feb 2017 19:49:09 -0500
+Subject: pNFS/flexfiles: If the layout is invalid, it must be updated before retrying
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit df3ab232e462bce20710596d697ade6b72497694 upstream.
+
+If we see that our pNFS READ/WRITE/COMMIT operation failed, but we
+also see that our layout segment is no longer valid, then we need to
+get a new layout segment before retrying.
+
+Fixes: 90816d1ddacf ("NFSv4.1/flexfiles: Don't mark the entire deviceid...")
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/flexfilelayout/flexfilelayout.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/fs/nfs/flexfilelayout/flexfilelayout.c
++++ b/fs/nfs/flexfilelayout/flexfilelayout.c
+@@ -1053,9 +1053,6 @@ static int ff_layout_async_handle_error_
+       struct nfs_client *mds_client = mds_server->nfs_client;
+       struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table;
+-      if (task->tk_status >= 0)
+-              return 0;
+-
+       switch (task->tk_status) {
+       /* MDS state errors */
+       case -NFS4ERR_DELEG_REVOKED:
+@@ -1157,9 +1154,6 @@ static int ff_layout_async_handle_error_
+ {
+       struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx);
+-      if (task->tk_status >= 0)
+-              return 0;
+-
+       switch (task->tk_status) {
+       /* File access problems. Don't mark the device as unavailable */
+       case -EACCES:
+@@ -1195,6 +1189,13 @@ static int ff_layout_async_handle_error(
+ {
+       int vers = clp->cl_nfs_mod->rpc_vers->number;
++      if (task->tk_status >= 0)
++              return 0;
++
++      /* Handle the case of an invalid layout segment */
++      if (!pnfs_is_valid_lseg(lseg))
++              return -NFS4ERR_RESET_TO_PNFS;
++
+       switch (vers) {
+       case 3:
+               return ff_layout_async_handle_error_v3(task, lseg, idx);
diff --git a/queue-4.10/powerpc-mm-add-mmu_ftr_kernel_ro-to-possible-feature-mask.patch b/queue-4.10/powerpc-mm-add-mmu_ftr_kernel_ro-to-possible-feature-mask.patch
new file mode 100644 (file)
index 0000000..7755fcb
--- /dev/null
@@ -0,0 +1,31 @@
+From a5ecdad4847897007399d7a14c9109b65ce4c9b7 Mon Sep 17 00:00:00 2001
+From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
+Date: Tue, 7 Feb 2017 00:09:27 +0530
+Subject: powerpc/mm: Add MMU_FTR_KERNEL_RO to possible feature mask
+
+From: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+
+commit a5ecdad4847897007399d7a14c9109b65ce4c9b7 upstream.
+
+Without this we will always find the feature disabled.
+
+Fixes: 984d7a1ec6 ("powerpc/mm: Fixup kernel read only mapping")
+Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+Acked-by: Balbir Singh <bsingharora@gmail.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/include/asm/mmu.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/powerpc/include/asm/mmu.h
++++ b/arch/powerpc/include/asm/mmu.h
+@@ -136,6 +136,7 @@ enum {
+               MMU_FTR_NO_SLBIE_B | MMU_FTR_16M_PAGE | MMU_FTR_TLBIEL |
+               MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_CI_LARGE_PAGE |
+               MMU_FTR_1T_SEGMENT | MMU_FTR_TLBIE_CROP_VA |
++              MMU_FTR_KERNEL_RO |
+ #ifdef CONFIG_PPC_RADIX_MMU
+               MMU_FTR_TYPE_RADIX |
+ #endif
diff --git a/queue-4.10/powerpc-mm-hash-always-clear-uprt-and-host-radix-bits-when-setting-up-cpu.patch b/queue-4.10/powerpc-mm-hash-always-clear-uprt-and-host-radix-bits-when-setting-up-cpu.patch
new file mode 100644 (file)
index 0000000..6bee015
--- /dev/null
@@ -0,0 +1,43 @@
+From fda2d27db6eae5c2468f9e4657539b72bbc238bb Mon Sep 17 00:00:00 2001
+From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
+Date: Wed, 22 Feb 2017 10:42:02 +0530
+Subject: powerpc/mm/hash: Always clear UPRT and Host Radix bits when setting up CPU
+
+From: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+
+commit fda2d27db6eae5c2468f9e4657539b72bbc238bb upstream.
+
+We will set LPCR with correct value for radix during int. This make sure we
+start with a sanitized value of LPCR. In case of kexec, cpus can have LPCR
+value based on the previous translation mode we were running.
+
+Fixes: fe036a0605d60 ("powerpc/64/kexec: Fix MMU cleanup on radix")
+Acked-by: Michael Neuling <mikey@neuling.org>
+Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kernel/cpu_setup_power.S |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/powerpc/kernel/cpu_setup_power.S
++++ b/arch/powerpc/kernel/cpu_setup_power.S
+@@ -101,6 +101,8 @@ _GLOBAL(__setup_cpu_power9)
+       mfspr   r3,SPRN_LPCR
+       LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
+       or      r3, r3, r4
++      LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR)
++      andc    r3, r3, r4
+       bl      __init_LPCR
+       bl      __init_HFSCR
+       bl      __init_tlb_power9
+@@ -122,6 +124,8 @@ _GLOBAL(__restore_cpu_power9)
+       mfspr   r3,SPRN_LPCR
+       LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
+       or      r3, r3, r4
++      LOAD_REG_IMMEDIATE(r4, LPCR_UPRT | LPCR_HR)
++      andc    r3, r3, r4
+       bl      __init_LPCR
+       bl      __init_HFSCR
+       bl      __init_tlb_power9
diff --git a/queue-4.10/powerpc-xmon-fix-data-breakpoint.patch b/queue-4.10/powerpc-xmon-fix-data-breakpoint.patch
new file mode 100644 (file)
index 0000000..52df94a
--- /dev/null
@@ -0,0 +1,44 @@
+From c21a493a2b44650707d06741601894329486f2ad Mon Sep 17 00:00:00 2001
+From: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
+Date: Tue, 22 Nov 2016 14:55:59 +0530
+Subject: powerpc/xmon: Fix data-breakpoint
+
+From: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
+
+commit c21a493a2b44650707d06741601894329486f2ad upstream.
+
+Currently xmon data-breakpoint feature is broken.
+
+Whenever there is a watchpoint match occurs, hw_breakpoint_handler will
+be called by do_break via notifier chains mechanism. If watchpoint is
+registered by xmon, hw_breakpoint_handler won't find any associated
+perf_event and returns immediately with NOTIFY_STOP. Similarly, do_break
+also returns without notifying to xmon.
+
+Solve this by returning NOTIFY_DONE when hw_breakpoint_handler does not
+find any perf_event associated with matched watchpoint, rather than
+NOTIFY_STOP, which tells the core code to continue calling the other
+breakpoint handlers including the xmon one.
+
+Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kernel/hw_breakpoint.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/arch/powerpc/kernel/hw_breakpoint.c
++++ b/arch/powerpc/kernel/hw_breakpoint.c
+@@ -228,8 +228,10 @@ int hw_breakpoint_handler(struct die_arg
+       rcu_read_lock();
+       bp = __this_cpu_read(bp_per_reg);
+-      if (!bp)
++      if (!bp) {
++              rc = NOTIFY_DONE;
+               goto out;
++      }
+       info = counter_arch_bp(bp);
+       /*
diff --git a/queue-4.10/rdma-core-fix-incorrect-structure-packing-for-booleans.patch b/queue-4.10/rdma-core-fix-incorrect-structure-packing-for-booleans.patch
new file mode 100644 (file)
index 0000000..4213b01
--- /dev/null
@@ -0,0 +1,63 @@
+From 55efcfcd7776165b294f8b5cd6e05ca00ec89b7c Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Thu, 22 Dec 2016 18:07:52 -0700
+Subject: RDMA/core: Fix incorrect structure packing for booleans
+
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+
+commit 55efcfcd7776165b294f8b5cd6e05ca00ec89b7c upstream.
+
+The RDMA core uses ib_pack() to convert from unpacked CPU structs
+to on-the-wire bitpacked structs.
+
+This process requires that 1 bit fields are declared as u8 in the
+unpacked struct, otherwise the packing process does not read the
+value properly and the packed result is wired to 0. Several
+places wrongly used int.
+
+Crucially this means the kernel has never, set reversible
+correctly in the path record request. It has always asked for
+irreversible paths even if the ULP requests otherwise.
+
+When the kernel is used with a SM that supports this feature, it
+completely breaks communication management if reversible paths are
+not properly requested.
+
+The only reason this ever worked is because opensm ignores the
+reversible bit.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/rdma/ib_sa.h |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/include/rdma/ib_sa.h
++++ b/include/rdma/ib_sa.h
+@@ -153,12 +153,12 @@ struct ib_sa_path_rec {
+       union ib_gid sgid;
+       __be16       dlid;
+       __be16       slid;
+-      int          raw_traffic;
++      u8           raw_traffic;
+       /* reserved */
+       __be32       flow_label;
+       u8           hop_limit;
+       u8           traffic_class;
+-      int          reversible;
++      u8           reversible;
+       u8           numb_path;
+       __be16       pkey;
+       __be16       qos_class;
+@@ -220,7 +220,7 @@ struct ib_sa_mcmember_rec {
+       u8           hop_limit;
+       u8           scope;
+       u8           join_state;
+-      int          proxy_join;
++      u8           proxy_join;
+ };
+ /* Service Record Component Mask Sec 15.2.5.14 Ver 1.1        */
diff --git a/queue-4.10/rdma_cm-fail-iwarp-accepts-w-o-connection-params.patch b/queue-4.10/rdma_cm-fail-iwarp-accepts-w-o-connection-params.patch
new file mode 100644 (file)
index 0000000..5cf97b8
--- /dev/null
@@ -0,0 +1,34 @@
+From f2625f7db4dd0bbd16a9c7d2950e7621f9aa57ad Mon Sep 17 00:00:00 2001
+From: Steve Wise <swise@opengridcomputing.com>
+Date: Tue, 21 Feb 2017 11:21:57 -0800
+Subject: rdma_cm: fail iwarp accepts w/o connection params
+
+From: Steve Wise <swise@opengridcomputing.com>
+
+commit f2625f7db4dd0bbd16a9c7d2950e7621f9aa57ad upstream.
+
+cma_accept_iw() needs to return an error if conn_params is NULL.
+Since this is coming from user space, we can crash.
+
+Reported-by: Shaobo He <shaobo@cs.utah.edu>
+Acked-by: Sean Hefty <sean.hefty@intel.com>
+Signed-off-by: Steve Wise <swise@opengridcomputing.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/infiniband/core/cma.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/infiniband/core/cma.c
++++ b/drivers/infiniband/core/cma.c
+@@ -3583,6 +3583,9 @@ static int cma_accept_iw(struct rdma_id_
+       struct iw_cm_conn_param iw_param;
+       int ret;
++      if (!conn_param)
++              return -EINVAL;
++
+       ret = cma_modify_qp_rtr(id_priv, conn_param);
+       if (ret)
+               return ret;
diff --git a/queue-4.10/remoteproc-qcom-mdt_loader-don-t-overwrite-firmware-object.patch b/queue-4.10/remoteproc-qcom-mdt_loader-don-t-overwrite-firmware-object.patch
new file mode 100644 (file)
index 0000000..3901381
--- /dev/null
@@ -0,0 +1,51 @@
+From 3e8b571a9a0881ba3381ca0915995696da145ab8 Mon Sep 17 00:00:00 2001
+From: Bjorn Andersson <bjorn.andersson@linaro.org>
+Date: Fri, 27 Jan 2017 02:06:36 -0800
+Subject: remoteproc: qcom: mdt_loader: Don't overwrite firmware object
+
+From: Bjorn Andersson <bjorn.andersson@linaro.org>
+
+commit 3e8b571a9a0881ba3381ca0915995696da145ab8 upstream.
+
+The "fw" firmware object is passed from the remoteproc core and should
+not be overwritten, as that results in leaked buffers and a double free
+of the the last firmware object.
+
+Fixes: 051fb70fd4ea ("remoteproc: qcom: Driver for the self-authenticating Hexagon v5")
+Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/remoteproc/qcom_mdt_loader.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/remoteproc/qcom_mdt_loader.c
++++ b/drivers/remoteproc/qcom_mdt_loader.c
+@@ -116,6 +116,7 @@ int qcom_mdt_load(struct rproc *rproc,
+       const struct elf32_phdr *phdrs;
+       const struct elf32_phdr *phdr;
+       const struct elf32_hdr *ehdr;
++      const struct firmware *seg_fw;
+       size_t fw_name_len;
+       char *fw_name;
+       void *ptr;
+@@ -154,16 +155,16 @@ int qcom_mdt_load(struct rproc *rproc,
+               if (phdr->p_filesz) {
+                       sprintf(fw_name + fw_name_len - 3, "b%02d", i);
+-                      ret = request_firmware(&fw, fw_name, &rproc->dev);
++                      ret = request_firmware(&seg_fw, fw_name, &rproc->dev);
+                       if (ret) {
+                               dev_err(&rproc->dev, "failed to load %s\n",
+                                       fw_name);
+                               break;
+                       }
+-                      memcpy(ptr, fw->data, fw->size);
++                      memcpy(ptr, seg_fw->data, seg_fw->size);
+-                      release_firmware(fw);
++                      release_firmware(seg_fw);
+               }
+               if (phdr->p_memsz > phdr->p_filesz)
diff --git a/queue-4.10/revert-nfsv4.1-handle-nfs4err_badsession-nfs4err_deadsession-replies-to-op_sequence.patch b/queue-4.10/revert-nfsv4.1-handle-nfs4err_badsession-nfs4err_deadsession-replies-to-op_sequence.patch
new file mode 100644 (file)
index 0000000..5d6f5a2
--- /dev/null
@@ -0,0 +1,35 @@
+From a5e14c9376871ee74fe93fdcb380c5d54eaa2d43 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Fri, 17 Feb 2017 19:50:18 -0500
+Subject: Revert "NFSv4.1: Handle NFS4ERR_BADSESSION/NFS4ERR_DEADSESSION replies to OP_SEQUENCE"
+
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+
+commit a5e14c9376871ee74fe93fdcb380c5d54eaa2d43 upstream.
+
+This reverts commit 2cf10cdd486c362f983abdce00dc1127e8ab8c59.
+
+The patch has been seen to cause excessive looping.
+
+Reported-by: Olga Kornievskaia <aglo@umich.edu>
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |    4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -815,10 +815,6 @@ static int nfs41_sequence_process(struct
+       case -NFS4ERR_SEQ_FALSE_RETRY:
+               ++slot->seq_nr;
+               goto retry_nowait;
+-      case -NFS4ERR_DEADSESSION:
+-      case -NFS4ERR_BADSESSION:
+-              nfs4_schedule_session_recovery(session, res->sr_status);
+-              goto retry_nowait;
+       default:
+               /* Just update the slot sequence no. */
+               slot->seq_done = 1;
diff --git a/queue-4.10/rtc-sun6i-add-some-locking.patch b/queue-4.10/rtc-sun6i-add-some-locking.patch
new file mode 100644 (file)
index 0000000..65882ad
--- /dev/null
@@ -0,0 +1,100 @@
+From a9422a19ce270a22fc520f2278fb7e80c58be508 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Mon, 23 Jan 2017 11:41:47 +0100
+Subject: rtc: sun6i: Add some locking
+
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+
+commit a9422a19ce270a22fc520f2278fb7e80c58be508 upstream.
+
+Some registers have a read-modify-write access pattern that are not atomic.
+
+Add some locking to prevent from concurrent accesses.
+
+Acked-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/rtc/rtc-sun6i.c |   17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+--- a/drivers/rtc/rtc-sun6i.c
++++ b/drivers/rtc/rtc-sun6i.c
+@@ -114,13 +114,17 @@ struct sun6i_rtc_dev {
+       void __iomem *base;
+       int irq;
+       unsigned long alarm;
++
++      spinlock_t lock;
+ };
+ static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id)
+ {
+       struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id;
++      irqreturn_t ret = IRQ_NONE;
+       u32 val;
++      spin_lock(&chip->lock);
+       val = readl(chip->base + SUN6I_ALRM_IRQ_STA);
+       if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) {
+@@ -129,10 +133,11 @@ static irqreturn_t sun6i_rtc_alarmirq(in
+               rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF);
+-              return IRQ_HANDLED;
++              ret = IRQ_HANDLED;
+       }
++      spin_unlock(&chip->lock);
+-      return IRQ_NONE;
++      return ret;
+ }
+ static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip)
+@@ -140,6 +145,7 @@ static void sun6i_rtc_setaie(int to, str
+       u32 alrm_val = 0;
+       u32 alrm_irq_val = 0;
+       u32 alrm_wake_val = 0;
++      unsigned long flags;
+       if (to) {
+               alrm_val = SUN6I_ALRM_EN_CNT_EN;
+@@ -150,9 +156,11 @@ static void sun6i_rtc_setaie(int to, str
+                      chip->base + SUN6I_ALRM_IRQ_STA);
+       }
++      spin_lock_irqsave(&chip->lock, flags);
+       writel(alrm_val, chip->base + SUN6I_ALRM_EN);
+       writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN);
+       writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG);
++      spin_unlock_irqrestore(&chip->lock, flags);
+ }
+ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+@@ -191,11 +199,15 @@ static int sun6i_rtc_gettime(struct devi
+ static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+ {
+       struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
++      unsigned long flags;
+       u32 alrm_st;
+       u32 alrm_en;
++      spin_lock_irqsave(&chip->lock, flags);
+       alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN);
+       alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA);
++      spin_unlock_irqrestore(&chip->lock, flags);
++
+       wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN);
+       wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN);
+       rtc_time_to_tm(chip->alarm, &wkalrm->time);
+@@ -356,6 +368,7 @@ static int sun6i_rtc_probe(struct platfo
+       chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
++      spin_lock_init(&chip->lock);
+       platform_set_drvdata(pdev, chip);
+       chip->dev = &pdev->dev;
diff --git a/queue-4.10/rtc-sun6i-disable-the-build-as-a-module.patch b/queue-4.10/rtc-sun6i-disable-the-build-as-a-module.patch
new file mode 100644 (file)
index 0000000..2edba4a
--- /dev/null
@@ -0,0 +1,45 @@
+From 3753941475ae6501dcd1e41832bd0e6c35247d6a Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Mon, 23 Jan 2017 11:41:46 +0100
+Subject: rtc: sun6i: Disable the build as a module
+
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+
+commit 3753941475ae6501dcd1e41832bd0e6c35247d6a upstream.
+
+Since we have to provide the clock very early on, the RTC driver cannot be
+built as a module. Make sure that won't happen.
+
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/rtc/Kconfig     |    2 +-
+ drivers/rtc/rtc-sun6i.c |    7 +------
+ 2 files changed, 2 insertions(+), 7 deletions(-)
+
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -1434,7 +1434,7 @@ config RTC_DRV_SUN4V
+         based RTC on SUN4V systems.
+ config RTC_DRV_SUN6I
+-      tristate "Allwinner A31 RTC"
++      bool "Allwinner A31 RTC"
+       default MACH_SUN6I || MACH_SUN8I || COMPILE_TEST
+       depends on ARCH_SUNXI
+       help
+--- a/drivers/rtc/rtc-sun6i.c
++++ b/drivers/rtc/rtc-sun6i.c
+@@ -439,9 +439,4 @@ static struct platform_driver sun6i_rtc_
+               .of_match_table = sun6i_rtc_dt_ids,
+       },
+ };
+-
+-module_platform_driver(sun6i_rtc_driver);
+-
+-MODULE_DESCRIPTION("sun6i RTC driver");
+-MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
+-MODULE_LICENSE("GPL");
++builtin_platform_driver(sun6i_rtc_driver);
diff --git a/queue-4.10/rtc-sun6i-switch-to-the-external-oscillator.patch b/queue-4.10/rtc-sun6i-switch-to-the-external-oscillator.patch
new file mode 100644 (file)
index 0000000..5bc76ef
--- /dev/null
@@ -0,0 +1,52 @@
+From fb61bb82cb46a932ef2fc62e1c731c8e7e6640d5 Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+Date: Mon, 23 Jan 2017 11:41:48 +0100
+Subject: rtc: sun6i: Switch to the external oscillator
+
+From: Maxime Ripard <maxime.ripard@free-electrons.com>
+
+commit fb61bb82cb46a932ef2fc62e1c731c8e7e6640d5 upstream.
+
+The RTC is clocked from either an internal, imprecise, oscillator or an
+external one, which is usually much more accurate.
+
+The difference perceived between the time elapsed and the time reported by
+the RTC is in a 10% scale, which prevents the RTC from being useful at all.
+
+Fortunately, the external oscillator is reported to be mandatory in the
+Allwinner datasheet, so we can just switch to it.
+
+Fixes: 9765d2d94309 ("rtc: sun6i: Add sun6i RTC driver")
+Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
+Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/rtc/rtc-sun6i.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/rtc/rtc-sun6i.c
++++ b/drivers/rtc/rtc-sun6i.c
+@@ -37,9 +37,11 @@
+ /* Control register */
+ #define SUN6I_LOSC_CTRL                               0x0000
++#define SUN6I_LOSC_CTRL_KEY                   (0x16aa << 16)
+ #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC          BIT(9)
+ #define SUN6I_LOSC_CTRL_RTC_HMS_ACC           BIT(8)
+ #define SUN6I_LOSC_CTRL_RTC_YMD_ACC           BIT(7)
++#define SUN6I_LOSC_CTRL_EXT_OSC                       BIT(0)
+ #define SUN6I_LOSC_CTRL_ACC_MASK              GENMASK(9, 7)
+ /* RTC */
+@@ -417,6 +419,10 @@ static int sun6i_rtc_probe(struct platfo
+       /* disable alarm wakeup */
+       writel(0, chip->base + SUN6I_ALARM_CONFIG);
++      /* switch to the external, more precise, oscillator */
++      writel(SUN6I_LOSC_CTRL_KEY | SUN6I_LOSC_CTRL_EXT_OSC,
++             chip->base + SUN6I_LOSC_CTRL);
++
+       chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev,
+                                       &sun6i_rtc_ops, THIS_MODULE);
+       if (IS_ERR(chip->rtc)) {
diff --git a/queue-4.10/rtlwifi-fix-alignment-issues.patch b/queue-4.10/rtlwifi-fix-alignment-issues.patch
new file mode 100644 (file)
index 0000000..bd70b25
--- /dev/null
@@ -0,0 +1,48 @@
+From 40b368af4b750863b2cb66a3a9513241db2f0793 Mon Sep 17 00:00:00 2001
+From: Ping-Ke Shih <pkshih@realtek.com>
+Date: Wed, 28 Dec 2016 15:40:04 -0600
+Subject: rtlwifi: Fix alignment issues
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+commit 40b368af4b750863b2cb66a3a9513241db2f0793 upstream.
+
+The addresses of Wlan NIC registers are natural alignment, but some
+drivers have bugs. These are evident on platforms that need natural
+alignment to access registers.  This change contains the following:
+ 1. Function _rtl8821ae_dbi_read() is used to read one byte from DBI,
+    thus it should use rtl_read_byte().
+ 2. Register 0x4C7 of 8192ee is single byte.
+
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c |    2 +-
+ drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c
+@@ -1006,7 +1006,7 @@ static void _rtl92ee_hw_configure(struct
+       rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x100a);
+       /* Note Data sheet don't define */
+-      rtl_write_word(rtlpriv, 0x4C7, 0x80);
++      rtl_write_byte(rtlpriv, 0x4C7, 0x80);
+       rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20);
+--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+@@ -1128,7 +1128,7 @@ static u8 _rtl8821ae_dbi_read(struct rtl
+       }
+       if (0 == tmp) {
+               read_addr = REG_DBI_RDATA + addr % 4;
+-              ret = rtl_read_word(rtlpriv, read_addr);
++              ret = rtl_read_byte(rtlpriv, read_addr);
+       }
+       return ret;
+ }
diff --git a/queue-4.10/rtlwifi-rtl8192c-common-fix-bug-kasan.patch b/queue-4.10/rtlwifi-rtl8192c-common-fix-bug-kasan.patch
new file mode 100644 (file)
index 0000000..eef2e3a
--- /dev/null
@@ -0,0 +1,82 @@
+From 6773386f977ce5af339f9678fa2918909a946c6b Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Sun, 5 Feb 2017 10:24:22 -0600
+Subject: rtlwifi: rtl8192c-common: Fix "BUG: KASAN:
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit 6773386f977ce5af339f9678fa2918909a946c6b upstream.
+
+Kernels built with CONFIG_KASAN=y report the following BUG for rtl8192cu
+and rtl8192c-common:
+
+==================================================================
+BUG: KASAN: slab-out-of-bounds in rtl92c_dm_bt_coexist+0x858/0x1e40
+     [rtl8192c_common] at addr ffff8801c90edb08
+Read of size 1 by task kworker/0:1/38
+page:ffffea0007243800 count:1 mapcount:0 mapping:          (null)
+     index:0x0 compound_mapcount: 0
+flags: 0x8000000000004000(head)
+page dumped because: kasan: bad access detected
+CPU: 0 PID: 38 Comm: kworker/0:1 Not tainted 4.9.7-gentoo #3
+Hardware name: Gigabyte Technology Co., Ltd. To be filled by
+     O.E.M./Z77-DS3H, BIOS F11a 11/13/2013
+Workqueue: rtl92c_usb rtl_watchdog_wq_callback [rtlwifi]
+  0000000000000000 ffffffff829eea33 ffff8801d7f0fa30 ffff8801c90edb08
+  ffffffff824c0f09 ffff8801d4abee80 0000000000000004 0000000000000297
+  ffffffffc070b57c ffff8801c7aa7c48 ffff880100000004 ffffffff000003e8
+Call Trace:
+  [<ffffffff829eea33>] ? dump_stack+0x5c/0x79
+  [<ffffffff824c0f09>] ? kasan_report_error+0x4b9/0x4e0
+  [<ffffffffc070b57c>] ? _usb_read_sync+0x15c/0x280 [rtl_usb]
+  [<ffffffff824c0f75>] ? __asan_report_load1_noabort+0x45/0x50
+  [<ffffffffc06d7a88>] ? rtl92c_dm_bt_coexist+0x858/0x1e40 [rtl8192c_common]
+  [<ffffffffc06d7a88>] ? rtl92c_dm_bt_coexist+0x858/0x1e40 [rtl8192c_common]
+  [<ffffffffc06d0cbe>] ? rtl92c_dm_rf_saving+0x96e/0x1330 [rtl8192c_common]
+...
+
+The problem is due to rtl8192ce and rtl8192cu sharing routines, and having
+different layouts of struct rtl_pci_priv, which is used by rtl8192ce, and
+struct rtl_usb_priv, which is used by rtl8192cu. The problem was resolved
+by placing the struct bt_coexist_info at the head of each of those private
+areas.
+
+Reported-and-tested-by: Dmitry Osipenko <digetx@gmail.com>
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Cc: Dmitry Osipenko <digetx@gmail.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/realtek/rtlwifi/pci.h |    4 ++--
+ drivers/net/wireless/realtek/rtlwifi/usb.h |    3 ++-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtlwifi/pci.h
++++ b/drivers/net/wireless/realtek/rtlwifi/pci.h
+@@ -271,10 +271,10 @@ struct mp_adapter {
+ };
+ struct rtl_pci_priv {
++      struct bt_coexist_info bt_coexist;
++      struct rtl_led_ctl ledctl;
+       struct rtl_pci dev;
+       struct mp_adapter ndis_adapter;
+-      struct rtl_led_ctl ledctl;
+-      struct bt_coexist_info bt_coexist;
+ };
+ #define rtl_pcipriv(hw)               (((struct rtl_pci_priv *)(rtl_priv(hw))->priv))
+--- a/drivers/net/wireless/realtek/rtlwifi/usb.h
++++ b/drivers/net/wireless/realtek/rtlwifi/usb.h
+@@ -146,8 +146,9 @@ struct rtl_usb {
+ };
+ struct rtl_usb_priv {
+-      struct rtl_usb dev;
++      struct bt_coexist_info bt_coexist;
+       struct rtl_led_ctl ledctl;
++      struct rtl_usb dev;
+ };
+ #define rtl_usbpriv(hw)        (((struct rtl_usb_priv *)(rtl_priv(hw))->priv))
diff --git a/queue-4.10/scsi-lpfc-correct-wq-creation-for-pagesize.patch b/queue-4.10/scsi-lpfc-correct-wq-creation-for-pagesize.patch
new file mode 100644 (file)
index 0000000..2be646a
--- /dev/null
@@ -0,0 +1,79 @@
+From 8ea73db486cda442f0671f4bc9c03a76be398a28 Mon Sep 17 00:00:00 2001
+From: James Smart <jsmart2021@gmail.com>
+Date: Sun, 12 Feb 2017 13:52:25 -0800
+Subject: scsi: lpfc: Correct WQ creation for pagesize
+
+From: James Smart <jsmart2021@gmail.com>
+
+commit 8ea73db486cda442f0671f4bc9c03a76be398a28 upstream.
+
+Correct WQ creation for pagesize
+
+The driver was calculating the adapter command pagesize indicator from
+the system pagesize. However, the buffers the driver allocates are only
+one size (SLI4_PAGE_SIZE), so no calculation was necessary.
+
+Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
+Signed-off-by: James Smart <james.smart@broadcom.com>
+Reviewed-by: Hannes Reinecke <hare@suse.com>
+Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Cc: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/lpfc/lpfc_hw4.h |    2 ++
+ drivers/scsi/lpfc/lpfc_sli.c |    9 +++++----
+ 2 files changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/scsi/lpfc/lpfc_hw4.h
++++ b/drivers/scsi/lpfc/lpfc_hw4.h
+@@ -1186,6 +1186,7 @@ struct lpfc_mbx_wq_create {
+ #define lpfc_mbx_wq_create_page_size_SHIFT    0
+ #define lpfc_mbx_wq_create_page_size_MASK     0x000000FF
+ #define lpfc_mbx_wq_create_page_size_WORD     word1
++#define LPFC_WQ_PAGE_SIZE_4096        0x1
+ #define lpfc_mbx_wq_create_wqe_size_SHIFT     8
+ #define lpfc_mbx_wq_create_wqe_size_MASK      0x0000000F
+ #define lpfc_mbx_wq_create_wqe_size_WORD      word1
+@@ -1257,6 +1258,7 @@ struct rq_context {
+ #define lpfc_rq_context_page_size_SHIFT       0               /* Version 1 Only */
+ #define lpfc_rq_context_page_size_MASK        0x000000FF
+ #define lpfc_rq_context_page_size_WORD        word0
++#define       LPFC_RQ_PAGE_SIZE_4096  0x1
+       uint32_t reserved1;
+       uint32_t word2;
+ #define lpfc_rq_context_cq_id_SHIFT   16
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -13718,7 +13718,7 @@ lpfc_wq_create(struct lpfc_hba *phba, st
+                              LPFC_WQ_WQE_SIZE_128);
+                       bf_set(lpfc_mbx_wq_create_page_size,
+                              &wq_create->u.request_1,
+-                             (PAGE_SIZE/SLI4_PAGE_SIZE));
++                             LPFC_WQ_PAGE_SIZE_4096);
+                       page = wq_create->u.request_1.page;
+                       break;
+               }
+@@ -13744,8 +13744,9 @@ lpfc_wq_create(struct lpfc_hba *phba, st
+                              LPFC_WQ_WQE_SIZE_128);
+                       break;
+               }
+-              bf_set(lpfc_mbx_wq_create_page_size, &wq_create->u.request_1,
+-                     (PAGE_SIZE/SLI4_PAGE_SIZE));
++              bf_set(lpfc_mbx_wq_create_page_size,
++                     &wq_create->u.request_1,
++                     LPFC_WQ_PAGE_SIZE_4096);
+               page = wq_create->u.request_1.page;
+               break;
+       default:
+@@ -13931,7 +13932,7 @@ lpfc_rq_create(struct lpfc_hba *phba, st
+                      LPFC_RQE_SIZE_8);
+               bf_set(lpfc_rq_context_page_size,
+                      &rq_create->u.request.context,
+-                     (PAGE_SIZE/SLI4_PAGE_SIZE));
++                     LPFC_RQ_PAGE_SIZE_4096);
+       } else {
+               switch (hrq->entry_count) {
+               default:
index 8b77ba445850e79e93c6b2d32d3ed5e17c9c3017..620ccce8231cb9b1e45cf751ef23a8cb0cd7fffb 100644 (file)
@@ -103,3 +103,65 @@ arm64-dma-mapping-fix-dma_mapping_error-when-bypassing-swiotlb.patch
 arm64-fix-erroneous-__raw_read_system_reg-cases.patch
 kvm-arm-arm64-vgic-stop-injecting-the-msi-occurrence-twice.patch
 revert-arm64-mm-set-the-contiguous-bit-for-kernel-mappings-where-appropriate.patch
+iio-pressure-mpl115-do-not-rely-on-structure-field-ordering.patch
+iio-pressure-mpl3115-do-not-rely-on-structure-field-ordering.patch
+can-gs_usb-don-t-use-stack-memory-for-usb-transfers.patch
+can-usb_8dev-fix-memory-leak-of-priv-cmd_msg_buffer.patch
+w1-don-t-leak-refcount-on-slave-attach-failure-in-w1_attach_slave_device.patch
+w1-ds2490-usb-transfer-buffers-need-to-be-dmaable.patch
+usb-musb-da8xx-remove-cppi-3.0-quirk-and-methods.patch
+usb-dwc3-gadget-skip-set-clear-halt-when-invalid.patch
+usb-host-xhci-plat-check-hcc_params-after-add-hcd.patch
+usb-gadget-udc-core-rescan-pending-list-on-driver-unbind.patch
+usb-gadget-udc-fsl-add-missing-complete-function.patch
+usb-gadget-f_hid-fix-free-out-requests.patch
+usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch
+usb-gadget-f_hid-use-spinlock-instead-of-mutex.patch
+usb-gadget-f_hid-fix-move-in-request-allocation-to-set_alt.patch
+hv-allocate-synic-pages-for-all-present-cpus.patch
+hv-init-percpu_list-in-hv_synic_alloc.patch
+hv-don-t-reset-hv_context.tsc_page-on-crash.patch
+drivers-hv-vmbus-prevent-sending-data-on-a-rescinded-channel.patch
+drivers-hv-vmbus-fix-a-rescind-handling-bug.patch
+drivers-hv-util-kvp-fix-a-rescind-processing-issue.patch
+drivers-hv-util-fcopy-fix-a-rescind-processing-issue.patch
+drivers-hv-util-backup-fix-a-rescind-processing-issue.patch
+rdma-core-fix-incorrect-structure-packing-for-booleans.patch
+rdma_cm-fail-iwarp-accepts-w-o-connection-params.patch
+gfs2-add-missing-rcu-locking-for-glock-lookup.patch
+remoteproc-qcom-mdt_loader-don-t-overwrite-firmware-object.patch
+rtlwifi-fix-alignment-issues.patch
+rtlwifi-rtl8192c-common-fix-bug-kasan.patch
+vme-restore-bus_remove-function-causing-incomplete-module-unload.patch
+nfsd-minor-nfsd_setattr-cleanup.patch
+nfsd-special-case-truncates-some-more.patch
+nfsv4-fix-memory-and-state-leak-in-_nfs4_open_and_get_state.patch
+nfsv4-fix-reboot-recovery-in-copy-offload.patch
+pnfs-flexfiles-if-the-layout-is-invalid-it-must-be-updated-before-retrying.patch
+revert-nfsv4.1-handle-nfs4err_badsession-nfs4err_deadsession-replies-to-op_sequence.patch
+nfsv4-fix-getacl-head-length-estimation.patch
+nfsv4-fix-getacl-erange-for-some-acl-buffer-sizes.patch
+f2fs-fix-a-problem-of-using-memory-after-free.patch
+f2fs-fix-multiple-f2fs_add_link-calls-having-same-name.patch
+f2fs-add-ovp-valid_blocks-check-for-bg-gc-victim-to-fg_gc.patch
+f2fs-avoid-to-issue-redundant-discard-commands.patch
+f2fs-fix-zoned-block-device-support.patch
+rtc-sun6i-disable-the-build-as-a-module.patch
+rtc-sun6i-add-some-locking.patch
+rtc-sun6i-switch-to-the-external-oscillator.patch
+md-linear-fix-a-race-between-linear_add-and-linear_congested.patch
+bcma-use-get-put-_device-when-probing-removing-device-driver.patch
+mtd-nand-ifc-fix-location-of-eccstat-registers-for-ifc-v1.0.patch
+dmaengine-ipu-make-sure-the-interrupt-routine-checks-all-interrupts.patch
+xprtrdma-fix-read-chunk-padding.patch
+xprtrdma-per-connection-pad-optimization.patch
+xprtrdma-disable-pad-optimization-by-default.patch
+xprtrdma-reduce-required-number-of-send-sges.patch
+powerpc-xmon-fix-data-breakpoint.patch
+powerpc-mm-add-mmu_ftr_kernel_ro-to-possible-feature-mask.patch
+powerpc-mm-hash-always-clear-uprt-and-host-radix-bits-when-setting-up-cpu.patch
+module-fix-memory-leak-on-early-load_module-failures.patch
+mips-ip22-reformat-inline-assembler-code-to-modern-standards.patch
+mips-ip22-fix-build-error-due-to-binutils-2.25-uselessnes.patch
+scsi-lpfc-correct-wq-creation-for-pagesize.patch
+ceph-update-readpages-osd-request-according-to-size-of-pages.patch
diff --git a/queue-4.10/usb-dwc3-gadget-skip-set-clear-halt-when-invalid.patch b/queue-4.10/usb-dwc3-gadget-skip-set-clear-halt-when-invalid.patch
new file mode 100644 (file)
index 0000000..8dc3620
--- /dev/null
@@ -0,0 +1,44 @@
+From ffb80fc672c3a7b6afd0cefcb1524fb99917b2f3 Mon Sep 17 00:00:00 2001
+From: Felipe Balbi <felipe.balbi@linux.intel.com>
+Date: Thu, 19 Jan 2017 13:38:42 +0200
+Subject: usb: dwc3: gadget: skip Set/Clear Halt when invalid
+
+From: Felipe Balbi <felipe.balbi@linux.intel.com>
+
+commit ffb80fc672c3a7b6afd0cefcb1524fb99917b2f3 upstream.
+
+At least macOS seems to be sending
+ClearFeature(ENDPOINT_HALT) to endpoints which
+aren't Halted. This makes DWC3's CLEARSTALL command
+time out which causes several issues for the driver.
+
+Instead, let's just return 0 and bail out early.
+
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/gadget.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1335,6 +1335,9 @@ int __dwc3_gadget_ep_set_halt(struct dwc
+               unsigned transfer_in_flight;
+               unsigned started;
++              if (dep->flags & DWC3_EP_STALL)
++                      return 0;
++
+               if (dep->number > 1)
+                       trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue);
+               else
+@@ -1356,6 +1359,8 @@ int __dwc3_gadget_ep_set_halt(struct dwc
+               else
+                       dep->flags |= DWC3_EP_STALL;
+       } else {
++              if (!(dep->flags & DWC3_EP_STALL))
++                      return 0;
+               ret = dwc3_send_clear_stall_ep_cmd(dep);
+               if (ret)
diff --git a/queue-4.10/usb-gadget-f_hid-fix-free-out-requests.patch b/queue-4.10/usb-gadget-f_hid-fix-free-out-requests.patch
new file mode 100644 (file)
index 0000000..59107d9
--- /dev/null
@@ -0,0 +1,72 @@
+From 20d2ca955bd09639c7b01db5761d157c297aea0a Mon Sep 17 00:00:00 2001
+From: Krzysztof Opasiak <kopasiak90@gmail.com>
+Date: Thu, 19 Jan 2017 18:55:27 +0100
+Subject: usb: gadget: f_hid: fix: Free out requests
+
+From: Krzysztof Opasiak <kopasiak90@gmail.com>
+
+commit 20d2ca955bd09639c7b01db5761d157c297aea0a upstream.
+
+Requests for out endpoint are allocated in bind() function
+but never released.
+
+This commit ensures that all pending requests are released
+when we disable out endpoint.
+
+Fixes: 99c515005857 ("usb: gadget: hidg: register OUT INT endpoint for SET_REPORT")
+Tested-by: David Lechner <david@lechnology.com>
+Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_hid.c |   32 ++++++++++++++++++++++++--------
+ 1 file changed, 24 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -425,20 +425,36 @@ static inline struct usb_request *hidg_a
+ static void hidg_set_report_complete(struct usb_ep *ep, struct usb_request *req)
+ {
+       struct f_hidg *hidg = (struct f_hidg *) req->context;
++      struct usb_composite_dev *cdev = hidg->func.config->cdev;
+       struct f_hidg_req_list *req_list;
+       unsigned long flags;
+-      req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
+-      if (!req_list)
+-              return;
++      switch (req->status) {
++      case 0:
++              req_list = kzalloc(sizeof(*req_list), GFP_ATOMIC);
++              if (!req_list) {
++                      ERROR(cdev, "Unable to allocate mem for req_list\n");
++                      goto free_req;
++              }
+-      req_list->req = req;
++              req_list->req = req;
+-      spin_lock_irqsave(&hidg->spinlock, flags);
+-      list_add_tail(&req_list->list, &hidg->completed_out_req);
+-      spin_unlock_irqrestore(&hidg->spinlock, flags);
++              spin_lock_irqsave(&hidg->spinlock, flags);
++              list_add_tail(&req_list->list, &hidg->completed_out_req);
++              spin_unlock_irqrestore(&hidg->spinlock, flags);
+-      wake_up(&hidg->read_queue);
++              wake_up(&hidg->read_queue);
++              break;
++      default:
++              ERROR(cdev, "Set report failed %d\n", req->status);
++              /* FALLTHROUGH */
++      case -ECONNABORTED:             /* hardware forced ep reset */
++      case -ECONNRESET:               /* request dequeued */
++      case -ESHUTDOWN:                /* disconnect from host */
++free_req:
++              free_ep_req(ep, req);
++              return;
++      }
+ }
+ static int hidg_setup(struct usb_function *f,
diff --git a/queue-4.10/usb-gadget-f_hid-fix-move-in-request-allocation-to-set_alt.patch b/queue-4.10/usb-gadget-f_hid-fix-move-in-request-allocation-to-set_alt.patch
new file mode 100644 (file)
index 0000000..ec5fdac
--- /dev/null
@@ -0,0 +1,228 @@
+From 749494b6bdbbaf0899aa1c62a1ad74cd747bce47 Mon Sep 17 00:00:00 2001
+From: Krzysztof Opasiak <kopasiak90@gmail.com>
+Date: Tue, 24 Jan 2017 03:27:24 +0100
+Subject: usb: gadget: f_hid: fix: Move IN request allocation to set_alt()
+
+From: Krzysztof Opasiak <kopasiak90@gmail.com>
+
+commit 749494b6bdbbaf0899aa1c62a1ad74cd747bce47 upstream.
+
+Since commit: ba1582f22231 ("usb: gadget: f_hid: use alloc_ep_req()")
+we cannot allocate any requests in bind() as we check if we should
+align request buffer based on endpoint descriptor which is assigned
+in set_alt().
+
+Allocating request in bind() function causes a NULL pointer
+dereference.
+
+This commit moves allocation of IN request from bind() to set_alt()
+to prevent this issue.
+
+Fixes: ba1582f22231 ("usb: gadget: f_hid: use alloc_ep_req()")
+Tested-by: David Lechner <david@lechnology.com>
+Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_hid.c |   89 +++++++++++++++++++++++++++---------
+ 1 file changed, 67 insertions(+), 22 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -338,6 +338,7 @@ static ssize_t f_hidg_write(struct file
+                           size_t count, loff_t *offp)
+ {
+       struct f_hidg *hidg  = file->private_data;
++      struct usb_request *req;
+       unsigned long flags;
+       ssize_t status = -ENOMEM;
+@@ -347,7 +348,7 @@ static ssize_t f_hidg_write(struct file
+       spin_lock_irqsave(&hidg->write_spinlock, flags);
+ #define WRITE_COND (!hidg->write_pending)
+-
++try_again:
+       /* write queue */
+       while (!WRITE_COND) {
+               spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+@@ -362,6 +363,7 @@ static ssize_t f_hidg_write(struct file
+       }
+       hidg->write_pending = 1;
++      req = hidg->req;
+       count  = min_t(unsigned, count, hidg->report_length);
+       spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+@@ -374,24 +376,38 @@ static ssize_t f_hidg_write(struct file
+               goto release_write_pending;
+       }
+-      hidg->req->status   = 0;
+-      hidg->req->zero     = 0;
+-      hidg->req->length   = count;
+-      hidg->req->complete = f_hidg_req_complete;
+-      hidg->req->context  = hidg;
++      spin_lock_irqsave(&hidg->write_spinlock, flags);
++
++      /* we our function has been disabled by host */
++      if (!hidg->req) {
++              free_ep_req(hidg->in_ep, hidg->req);
++              /*
++               * TODO
++               * Should we fail with error here?
++               */
++              goto try_again;
++      }
++
++      req->status   = 0;
++      req->zero     = 0;
++      req->length   = count;
++      req->complete = f_hidg_req_complete;
++      req->context  = hidg;
+       status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
+       if (status < 0) {
+               ERROR(hidg->func.config->cdev,
+                       "usb_ep_queue error on int endpoint %zd\n", status);
+-              goto release_write_pending;
++              goto release_write_pending_unlocked;
+       } else {
+               status = count;
+       }
++      spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+       return status;
+ release_write_pending:
+       spin_lock_irqsave(&hidg->write_spinlock, flags);
++release_write_pending_unlocked:
+       hidg->write_pending = 0;
+       spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+@@ -595,12 +611,23 @@ static void hidg_disable(struct usb_func
+               kfree(list);
+       }
+       spin_unlock_irqrestore(&hidg->read_spinlock, flags);
++
++      spin_lock_irqsave(&hidg->write_spinlock, flags);
++      if (!hidg->write_pending) {
++              free_ep_req(hidg->in_ep, hidg->req);
++              hidg->write_pending = 1;
++      }
++
++      hidg->req = NULL;
++      spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+ }
+ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+ {
+       struct usb_composite_dev                *cdev = f->config->cdev;
+       struct f_hidg                           *hidg = func_to_hidg(f);
++      struct usb_request                      *req_in = NULL;
++      unsigned long                           flags;
+       int i, status = 0;
+       VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
+@@ -621,6 +648,12 @@ static int hidg_set_alt(struct usb_funct
+                       goto fail;
+               }
+               hidg->in_ep->driver_data = hidg;
++
++              req_in = hidg_alloc_ep_req(hidg->in_ep, hidg->report_length);
++              if (!req_in) {
++                      status = -ENOMEM;
++                      goto disable_ep_in;
++              }
+       }
+@@ -632,12 +665,12 @@ static int hidg_set_alt(struct usb_funct
+                                           hidg->out_ep);
+               if (status) {
+                       ERROR(cdev, "config_ep_by_speed FAILED!\n");
+-                      goto fail;
++                      goto free_req_in;
+               }
+               status = usb_ep_enable(hidg->out_ep);
+               if (status < 0) {
+                       ERROR(cdev, "Enable OUT endpoint FAILED!\n");
+-                      goto fail;
++                      goto free_req_in;
+               }
+               hidg->out_ep->driver_data = hidg;
+@@ -653,17 +686,37 @@ static int hidg_set_alt(struct usb_funct
+                               req->context  = hidg;
+                               status = usb_ep_queue(hidg->out_ep, req,
+                                                     GFP_ATOMIC);
+-                              if (status)
++                              if (status) {
+                                       ERROR(cdev, "%s queue req --> %d\n",
+                                               hidg->out_ep->name, status);
++                                      free_ep_req(hidg->out_ep, req);
++                              }
+                       } else {
+-                              usb_ep_disable(hidg->out_ep);
+                               status = -ENOMEM;
+-                              goto fail;
++                              goto disable_out_ep;
+                       }
+               }
+       }
++      if (hidg->in_ep != NULL) {
++              spin_lock_irqsave(&hidg->write_spinlock, flags);
++              hidg->req = req_in;
++              hidg->write_pending = 0;
++              spin_unlock_irqrestore(&hidg->write_spinlock, flags);
++
++              wake_up(&hidg->write_queue);
++      }
++      return 0;
++disable_out_ep:
++      usb_ep_disable(hidg->out_ep);
++free_req_in:
++      if (req_in)
++              free_ep_req(hidg->in_ep, req_in);
++
++disable_ep_in:
++      if (hidg->in_ep)
++              usb_ep_disable(hidg->in_ep);
++
+ fail:
+       return status;
+ }
+@@ -712,12 +765,6 @@ static int hidg_bind(struct usb_configur
+               goto fail;
+       hidg->out_ep = ep;
+-      /* preallocate request and buffer */
+-      status = -ENOMEM;
+-      hidg->req = alloc_ep_req(hidg->in_ep, hidg->report_length);
+-      if (!hidg->req)
+-              goto fail;
+-
+       /* set descriptor dynamic values */
+       hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
+       hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
+@@ -755,6 +802,8 @@ static int hidg_bind(struct usb_configur
+               goto fail;
+       spin_lock_init(&hidg->write_spinlock);
++      hidg->write_pending = 1;
++      hidg->req = NULL;
+       spin_lock_init(&hidg->read_spinlock);
+       init_waitqueue_head(&hidg->write_queue);
+       init_waitqueue_head(&hidg->read_queue);
+@@ -1019,10 +1068,6 @@ static void hidg_unbind(struct usb_confi
+       device_destroy(hidg_class, MKDEV(major, hidg->minor));
+       cdev_del(&hidg->cdev);
+-      /* disable/free request and end point */
+-      usb_ep_disable(hidg->in_ep);
+-      free_ep_req(hidg->in_ep, hidg->req);
+-
+       usb_free_all_descriptors(f);
+ }
diff --git a/queue-4.10/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch b/queue-4.10/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch
new file mode 100644 (file)
index 0000000..ee2c8de
--- /dev/null
@@ -0,0 +1,88 @@
+From aa65d11aa008f4de58a9cee7e121666d9d68505e Mon Sep 17 00:00:00 2001
+From: Krzysztof Opasiak <kopasiak90@gmail.com>
+Date: Thu, 19 Jan 2017 18:55:28 +0100
+Subject: usb: gadget: f_hid: fix: Prevent accessing released memory
+
+From: Krzysztof Opasiak <kopasiak90@gmail.com>
+
+commit aa65d11aa008f4de58a9cee7e121666d9d68505e upstream.
+
+When we unlock our spinlock to copy data to user we may get
+disabled by USB host and free the whole list of completed out
+requests including the one from which we are copying the data
+to user memory.
+
+To prevent from this let's remove our working element from
+the list and place it back only if there is sth left when we
+finish with it.
+
+Fixes: 99c515005857 ("usb: gadget: hidg: register OUT INT endpoint for SET_REPORT")
+Tested-by: David Lechner <david@lechnology.com>
+Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_hid.c |   24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -277,6 +277,13 @@ static ssize_t f_hidg_read(struct file *
+       /* pick the first one */
+       list = list_first_entry(&hidg->completed_out_req,
+                               struct f_hidg_req_list, list);
++
++      /*
++       * Remove this from list to protect it from beign free()
++       * while host disables our function
++       */
++      list_del(&list->list);
++
+       req = list->req;
+       count = min_t(unsigned int, count, req->actual - list->pos);
+       spin_unlock_irqrestore(&hidg->spinlock, flags);
+@@ -292,15 +299,20 @@ static ssize_t f_hidg_read(struct file *
+        * call, taking into account its current read position.
+        */
+       if (list->pos == req->actual) {
+-              spin_lock_irqsave(&hidg->spinlock, flags);
+-              list_del(&list->list);
+               kfree(list);
+-              spin_unlock_irqrestore(&hidg->spinlock, flags);
+               req->length = hidg->report_length;
+               ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL);
+-              if (ret < 0)
++              if (ret < 0) {
++                      free_ep_req(hidg->out_ep, req);
+                       return ret;
++              }
++      } else {
++              spin_lock_irqsave(&hidg->spinlock, flags);
++              list_add(&list->list, &hidg->completed_out_req);
++              spin_unlock_irqrestore(&hidg->spinlock, flags);
++
++              wake_up(&hidg->read_queue);
+       }
+       return count;
+@@ -560,14 +572,18 @@ static void hidg_disable(struct usb_func
+ {
+       struct f_hidg *hidg = func_to_hidg(f);
+       struct f_hidg_req_list *list, *next;
++      unsigned long flags;
+       usb_ep_disable(hidg->in_ep);
+       usb_ep_disable(hidg->out_ep);
++      spin_lock_irqsave(&hidg->spinlock, flags);
+       list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
++              free_ep_req(hidg->out_ep, list->req);
+               list_del(&list->list);
+               kfree(list);
+       }
++      spin_unlock_irqrestore(&hidg->spinlock, flags);
+ }
+ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
diff --git a/queue-4.10/usb-gadget-f_hid-use-spinlock-instead-of-mutex.patch b/queue-4.10/usb-gadget-f_hid-use-spinlock-instead-of-mutex.patch
new file mode 100644 (file)
index 0000000..aa8ab93
--- /dev/null
@@ -0,0 +1,214 @@
+From 33e4c1a9987a1fc3b42c3b534100b5b006d55c61 Mon Sep 17 00:00:00 2001
+From: Krzysztof Opasiak <kopasiak90@gmail.com>
+Date: Thu, 19 Jan 2017 18:55:29 +0100
+Subject: usb: gadget: f_hid: Use spinlock instead of mutex
+
+From: Krzysztof Opasiak <kopasiak90@gmail.com>
+
+commit 33e4c1a9987a1fc3b42c3b534100b5b006d55c61 upstream.
+
+As IN request has to be allocated in set_alt() and released in
+disable() we cannot use mutex to protect it as we cannot sleep
+in those funcitons. Let's replace this mutex with a spinlock.
+
+Tested-by: David Lechner <david@lechnology.com>
+Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_hid.c |   57 +++++++++++++++++++++---------------
+ 1 file changed, 34 insertions(+), 23 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -50,12 +50,12 @@ struct f_hidg {
+       /* recv report */
+       struct list_head                completed_out_req;
+-      spinlock_t                      spinlock;
++      spinlock_t                      read_spinlock;
+       wait_queue_head_t               read_queue;
+       unsigned int                    qlen;
+       /* send report */
+-      struct mutex                    lock;
++      spinlock_t                      write_spinlock;
+       bool                            write_pending;
+       wait_queue_head_t               write_queue;
+       struct usb_request              *req;
+@@ -258,20 +258,20 @@ static ssize_t f_hidg_read(struct file *
+       if (!access_ok(VERIFY_WRITE, buffer, count))
+               return -EFAULT;
+-      spin_lock_irqsave(&hidg->spinlock, flags);
++      spin_lock_irqsave(&hidg->read_spinlock, flags);
+ #define READ_COND (!list_empty(&hidg->completed_out_req))
+       /* wait for at least one buffer to complete */
+       while (!READ_COND) {
+-              spin_unlock_irqrestore(&hidg->spinlock, flags);
++              spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+               if (file->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               if (wait_event_interruptible(hidg->read_queue, READ_COND))
+                       return -ERESTARTSYS;
+-              spin_lock_irqsave(&hidg->spinlock, flags);
++              spin_lock_irqsave(&hidg->read_spinlock, flags);
+       }
+       /* pick the first one */
+@@ -286,7 +286,7 @@ static ssize_t f_hidg_read(struct file *
+       req = list->req;
+       count = min_t(unsigned int, count, req->actual - list->pos);
+-      spin_unlock_irqrestore(&hidg->spinlock, flags);
++      spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+       /* copy to user outside spinlock */
+       count -= copy_to_user(buffer, req->buf + list->pos, count);
+@@ -308,9 +308,9 @@ static ssize_t f_hidg_read(struct file *
+                       return ret;
+               }
+       } else {
+-              spin_lock_irqsave(&hidg->spinlock, flags);
++              spin_lock_irqsave(&hidg->read_spinlock, flags);
+               list_add(&list->list, &hidg->completed_out_req);
+-              spin_unlock_irqrestore(&hidg->spinlock, flags);
++              spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+               wake_up(&hidg->read_queue);
+       }
+@@ -321,13 +321,16 @@ static ssize_t f_hidg_read(struct file *
+ static void f_hidg_req_complete(struct usb_ep *ep, struct usb_request *req)
+ {
+       struct f_hidg *hidg = (struct f_hidg *)ep->driver_data;
++      unsigned long flags;
+       if (req->status != 0) {
+               ERROR(hidg->func.config->cdev,
+                       "End Point Request ERROR: %d\n", req->status);
+       }
++      spin_lock_irqsave(&hidg->write_spinlock, flags);
+       hidg->write_pending = 0;
++      spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+       wake_up(&hidg->write_queue);
+ }
+@@ -335,18 +338,19 @@ static ssize_t f_hidg_write(struct file
+                           size_t count, loff_t *offp)
+ {
+       struct f_hidg *hidg  = file->private_data;
++      unsigned long flags;
+       ssize_t status = -ENOMEM;
+       if (!access_ok(VERIFY_READ, buffer, count))
+               return -EFAULT;
+-      mutex_lock(&hidg->lock);
++      spin_lock_irqsave(&hidg->write_spinlock, flags);
+ #define WRITE_COND (!hidg->write_pending)
+       /* write queue */
+       while (!WRITE_COND) {
+-              mutex_unlock(&hidg->lock);
++              spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+               if (file->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+@@ -354,17 +358,20 @@ static ssize_t f_hidg_write(struct file
+                               hidg->write_queue, WRITE_COND))
+                       return -ERESTARTSYS;
+-              mutex_lock(&hidg->lock);
++              spin_lock_irqsave(&hidg->write_spinlock, flags);
+       }
++      hidg->write_pending = 1;
+       count  = min_t(unsigned, count, hidg->report_length);
++
++      spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+       status = copy_from_user(hidg->req->buf, buffer, count);
+       if (status != 0) {
+               ERROR(hidg->func.config->cdev,
+                       "copy_from_user error\n");
+-              mutex_unlock(&hidg->lock);
+-              return -EINVAL;
++              status = -EINVAL;
++              goto release_write_pending;
+       }
+       hidg->req->status   = 0;
+@@ -372,19 +379,23 @@ static ssize_t f_hidg_write(struct file
+       hidg->req->length   = count;
+       hidg->req->complete = f_hidg_req_complete;
+       hidg->req->context  = hidg;
+-      hidg->write_pending = 1;
+       status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
+       if (status < 0) {
+               ERROR(hidg->func.config->cdev,
+                       "usb_ep_queue error on int endpoint %zd\n", status);
+-              hidg->write_pending = 0;
+-              wake_up(&hidg->write_queue);
++              goto release_write_pending;
+       } else {
+               status = count;
+       }
+-      mutex_unlock(&hidg->lock);
++      return status;
++release_write_pending:
++      spin_lock_irqsave(&hidg->write_spinlock, flags);
++      hidg->write_pending = 0;
++      spin_unlock_irqrestore(&hidg->write_spinlock, flags);
++
++      wake_up(&hidg->write_queue);
+       return status;
+ }
+@@ -451,9 +462,9 @@ static void hidg_set_report_complete(str
+               req_list->req = req;
+-              spin_lock_irqsave(&hidg->spinlock, flags);
++              spin_lock_irqsave(&hidg->read_spinlock, flags);
+               list_add_tail(&req_list->list, &hidg->completed_out_req);
+-              spin_unlock_irqrestore(&hidg->spinlock, flags);
++              spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+               wake_up(&hidg->read_queue);
+               break;
+@@ -577,13 +588,13 @@ static void hidg_disable(struct usb_func
+       usb_ep_disable(hidg->in_ep);
+       usb_ep_disable(hidg->out_ep);
+-      spin_lock_irqsave(&hidg->spinlock, flags);
++      spin_lock_irqsave(&hidg->read_spinlock, flags);
+       list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
+               free_ep_req(hidg->out_ep, list->req);
+               list_del(&list->list);
+               kfree(list);
+       }
+-      spin_unlock_irqrestore(&hidg->spinlock, flags);
++      spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+ }
+ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+@@ -743,8 +754,8 @@ static int hidg_bind(struct usb_configur
+       if (status)
+               goto fail;
+-      mutex_init(&hidg->lock);
+-      spin_lock_init(&hidg->spinlock);
++      spin_lock_init(&hidg->write_spinlock);
++      spin_lock_init(&hidg->read_spinlock);
+       init_waitqueue_head(&hidg->write_queue);
+       init_waitqueue_head(&hidg->read_queue);
+       INIT_LIST_HEAD(&hidg->completed_out_req);
diff --git a/queue-4.10/usb-gadget-udc-core-rescan-pending-list-on-driver-unbind.patch b/queue-4.10/usb-gadget-udc-core-rescan-pending-list-on-driver-unbind.patch
new file mode 100644 (file)
index 0000000..04c74b2
--- /dev/null
@@ -0,0 +1,124 @@
+From 8236800da115a3e24b9165c573067343f51cf5ea Mon Sep 17 00:00:00 2001
+From: Krzysztof Opasiak <k.opasiak@samsung.com>
+Date: Mon, 16 Jan 2017 08:40:57 +0100
+Subject: usb: gadget: udc-core: Rescan pending list on driver unbind
+
+From: Krzysztof Opasiak <k.opasiak@samsung.com>
+
+commit 8236800da115a3e24b9165c573067343f51cf5ea upstream.
+
+Since:
+
+commit 855ed04a3758 ("usb: gadget: udc-core: independent registration
+of gadgets and gadget drivers")
+
+if we load gadget module but there is no free udc available
+then it will be stored on a pending gadgets list.
+
+$ modprobe g_zero.ko
+$ modprobe g_ether.ko
+[] udc-core: couldn't find an available UDC - added [g_ether] to list
+of pending drivers
+
+We scan this list each time when new UDC appears in system.
+But we can get a free UDC each time after gadget unbind.
+This commit add scanning of that list directly after unbinding
+gadget from udc.
+
+Thanks to this, when we unload first gadget:
+
+$ rmmod g_zero.ko
+
+gadget which is pending is automatically
+attached to that UDC (if name matches).
+
+Fixes: 855ed04a3758  ("usb: gadget: udc-core: independent registration of gadgets and gadget drivers")
+Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/udc/core.c |   45 ++++++++++++++++++++++++++++--------------
+ 1 file changed, 31 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1080,6 +1080,24 @@ static void usb_udc_nop_release(struct d
+       dev_vdbg(dev, "%s\n", __func__);
+ }
++/* should be called with udc_lock held */
++static int check_pending_gadget_drivers(struct usb_udc *udc)
++{
++      struct usb_gadget_driver *driver;
++      int ret = 0;
++
++      list_for_each_entry(driver, &gadget_driver_pending_list, pending)
++              if (!driver->udc_name || strcmp(driver->udc_name,
++                                              dev_name(&udc->dev)) == 0) {
++                      ret = udc_bind_to_driver(udc, driver);
++                      if (ret != -EPROBE_DEFER)
++                              list_del(&driver->pending);
++                      break;
++              }
++
++      return ret;
++}
++
+ /**
+  * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
+  * @parent: the parent device to this udc. Usually the controller driver's
+@@ -1093,7 +1111,6 @@ int usb_add_gadget_udc_release(struct de
+               void (*release)(struct device *dev))
+ {
+       struct usb_udc          *udc;
+-      struct usb_gadget_driver *driver;
+       int                     ret = -ENOMEM;
+       udc = kzalloc(sizeof(*udc), GFP_KERNEL);
+@@ -1136,17 +1153,9 @@ int usb_add_gadget_udc_release(struct de
+       udc->vbus = true;
+       /* pick up one of pending gadget drivers */
+-      list_for_each_entry(driver, &gadget_driver_pending_list, pending) {
+-              if (!driver->udc_name || strcmp(driver->udc_name,
+-                                              dev_name(&udc->dev)) == 0) {
+-                      ret = udc_bind_to_driver(udc, driver);
+-                      if (ret != -EPROBE_DEFER)
+-                              list_del(&driver->pending);
+-                      if (ret)
+-                              goto err5;
+-                      break;
+-              }
+-      }
++      ret = check_pending_gadget_drivers(udc);
++      if (ret)
++              goto err5;
+       mutex_unlock(&udc_lock);
+@@ -1356,14 +1365,22 @@ int usb_gadget_unregister_driver(struct
+               return -EINVAL;
+       mutex_lock(&udc_lock);
+-      list_for_each_entry(udc, &udc_list, list)
++      list_for_each_entry(udc, &udc_list, list) {
+               if (udc->driver == driver) {
+                       usb_gadget_remove_driver(udc);
+                       usb_gadget_set_state(udc->gadget,
+-                                      USB_STATE_NOTATTACHED);
++                                           USB_STATE_NOTATTACHED);
++
++                      /* Maybe there is someone waiting for this UDC? */
++                      check_pending_gadget_drivers(udc);
++                      /*
++                       * For now we ignore bind errors as probably it's
++                       * not a valid reason to fail other's gadget unbind
++                       */
+                       ret = 0;
+                       break;
+               }
++      }
+       if (ret) {
+               list_del(&driver->pending);
diff --git a/queue-4.10/usb-gadget-udc-fsl-add-missing-complete-function.patch b/queue-4.10/usb-gadget-udc-fsl-add-missing-complete-function.patch
new file mode 100644 (file)
index 0000000..4555148
--- /dev/null
@@ -0,0 +1,58 @@
+From 5528954a1a0c49c6974ef1b8d6eaceff536204d5 Mon Sep 17 00:00:00 2001
+From: Magnus Lilja <lilja.magnus@gmail.com>
+Date: Wed, 25 Jan 2017 22:07:59 +0100
+Subject: usb: gadget: udc: fsl: Add missing complete function.
+
+From: Magnus Lilja <lilja.magnus@gmail.com>
+
+commit 5528954a1a0c49c6974ef1b8d6eaceff536204d5 upstream.
+
+Commit 304f7e5e1d08 ("usb: gadget: Refactor request completion")
+removed check if req->req.complete is non-NULL, resulting in a NULL
+pointer derefence and a kernel panic.
+This patch adds an empty complete function instead of re-introducing
+the req->req.complete check.
+
+Fixes: 304f7e5e1d08 ("usb: gadget: Refactor request completion")
+
+Signed-off-by: Magnus Lilja <lilja.magnus@gmail.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/udc/fsl_udc_core.c |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/udc/fsl_udc_core.c
++++ b/drivers/usb/gadget/udc/fsl_udc_core.c
+@@ -1248,6 +1248,12 @@ static const struct usb_gadget_ops fsl_g
+       .udc_stop = fsl_udc_stop,
+ };
++/*
++ * Empty complete function used by this driver to fill in the req->complete
++ * field when creating a request since the complete field is mandatory.
++ */
++static void fsl_noop_complete(struct usb_ep *ep, struct usb_request *req) { }
++
+ /* Set protocol stall on ep0, protocol stall will automatically be cleared
+    on new transaction */
+ static void ep0stall(struct fsl_udc *udc)
+@@ -1282,7 +1288,7 @@ static int ep0_prime_status(struct fsl_u
+       req->req.length = 0;
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+-      req->req.complete = NULL;
++      req->req.complete = fsl_noop_complete;
+       req->dtd_count = 0;
+       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+@@ -1365,7 +1371,7 @@ static void ch9getstatus(struct fsl_udc
+       req->req.length = 2;
+       req->req.status = -EINPROGRESS;
+       req->req.actual = 0;
+-      req->req.complete = NULL;
++      req->req.complete = fsl_noop_complete;
+       req->dtd_count = 0;
+       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
diff --git a/queue-4.10/usb-host-xhci-plat-check-hcc_params-after-add-hcd.patch b/queue-4.10/usb-host-xhci-plat-check-hcc_params-after-add-hcd.patch
new file mode 100644 (file)
index 0000000..5260449
--- /dev/null
@@ -0,0 +1,49 @@
+From 5de4e1ea9a731cad195ce5152705c21daef3bbba Mon Sep 17 00:00:00 2001
+From: William wu <william.wu@rock-chips.com>
+Date: Tue, 17 Jan 2017 15:32:07 +0800
+Subject: usb: host: xhci: plat: check hcc_params after add hcd
+
+From: William wu <william.wu@rock-chips.com>
+
+commit 5de4e1ea9a731cad195ce5152705c21daef3bbba upstream.
+
+The commit 4ac53087d6d4 ("usb: xhci: plat: Create both
+HCDs before adding them") move add hcd to the end of
+probe, this cause hcc_params uninitiated, because xHCI
+driver sets hcc_params in xhci_gen_setup() called from
+usb_add_hcd().
+
+This patch checks the Maximum Primary Stream Array Size
+in the hcc_params register after add primary hcd.
+
+Signed-off-by: William wu <william.wu@rock-chips.com>
+Acked-by: Roger Quadros <rogerq@ti.com>
+Fixes: 4ac53087d6d4 ("usb: xhci: plat: Create both HCDs before adding them")
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-plat.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -232,9 +232,6 @@ static int xhci_plat_probe(struct platfo
+       if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
+               xhci->quirks |= XHCI_LPM_SUPPORT;
+-      if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+-              xhci->shared_hcd->can_do_streams = 1;
+-
+       hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
+       if (IS_ERR(hcd->usb_phy)) {
+               ret = PTR_ERR(hcd->usb_phy);
+@@ -251,6 +248,9 @@ static int xhci_plat_probe(struct platfo
+       if (ret)
+               goto disable_usb_phy;
++      if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
++              xhci->shared_hcd->can_do_streams = 1;
++
+       ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+       if (ret)
+               goto dealloc_usb2_hcd;
diff --git a/queue-4.10/usb-musb-da8xx-remove-cppi-3.0-quirk-and-methods.patch b/queue-4.10/usb-musb-da8xx-remove-cppi-3.0-quirk-and-methods.patch
new file mode 100644 (file)
index 0000000..7c82db2
--- /dev/null
@@ -0,0 +1,44 @@
+From a994ce2d7e66008381a0b184c73be9ae9b72eb5c Mon Sep 17 00:00:00 2001
+From: Alexandre Bailon <abailon@baylibre.com>
+Date: Wed, 1 Feb 2017 21:30:12 -0600
+Subject: usb: musb: da8xx: Remove CPPI 3.0 quirk and methods
+
+From: Alexandre Bailon <abailon@baylibre.com>
+
+commit a994ce2d7e66008381a0b184c73be9ae9b72eb5c upstream.
+
+DA8xx driver is registering and using the CPPI 3.0 DMA controller but
+actually, the DA8xx has a CPPI 4.1 DMA controller.
+Remove the CPPI 3.0 quirk and methods.
+
+Fixes: f8e9f34f80a2 ("usb: musb: Fix up DMA related macros")
+Fixes: 7f6283ed6fe8 ("usb: musb: Set up function pointers for DMA")
+Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
+Acked-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Bin Liu <b-liu@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/musb/da8xx.c |    6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+--- a/drivers/usb/musb/da8xx.c
++++ b/drivers/usb/musb/da8xx.c
+@@ -458,15 +458,11 @@ static inline u8 get_vbus_power(struct d
+ }
+ static const struct musb_platform_ops da8xx_ops = {
+-      .quirks         = MUSB_DMA_CPPI | MUSB_INDEXED_EP,
++      .quirks         = MUSB_INDEXED_EP,
+       .init           = da8xx_musb_init,
+       .exit           = da8xx_musb_exit,
+       .fifo_mode      = 2,
+-#ifdef CONFIG_USB_TI_CPPI_DMA
+-      .dma_init       = cppi_dma_controller_create,
+-      .dma_exit       = cppi_dma_controller_destroy,
+-#endif
+       .enable         = da8xx_musb_enable,
+       .disable        = da8xx_musb_disable,
diff --git a/queue-4.10/vme-restore-bus_remove-function-causing-incomplete-module-unload.patch b/queue-4.10/vme-restore-bus_remove-function-causing-incomplete-module-unload.patch
new file mode 100644 (file)
index 0000000..47ce239
--- /dev/null
@@ -0,0 +1,63 @@
+From 9797484ba83d68f18fe1cbd964b7cd830f78f0f7 Mon Sep 17 00:00:00 2001
+From: Stefano Babic <sbabic@denx.de>
+Date: Fri, 20 Jan 2017 10:38:20 -0500
+Subject: VME: restore bus_remove function causing incomplete module unload
+
+From: Stefano Babic <sbabic@denx.de>
+
+commit 9797484ba83d68f18fe1cbd964b7cd830f78f0f7 upstream.
+
+Commit 050c3d52cc7810d9d17b8cd231708609af6876ae ("vme: make core
+vme support explicitly non-modular") dropped the remove function
+because it appeared as if it was for removal of the bus, which is
+not supported.
+
+However, vme_bus_remove() is called when a VME device is removed
+from the bus and not when the bus is removed; as it calls the VME
+device driver's cleanup function.  Without this function, the
+remove() in the VME device driver is never called and VME device
+drivers cannot be reloaded again.
+
+Here we restore the remove function that was deleted in that
+commit, and the reference to the function in the bus structure.
+
+Fixes: 050c3d52cc78 ("vme: make core vme support explicitly non-modular")
+Cc: Manohar Vanga <manohar.vanga@gmail.com>
+Acked-by: Martyn Welch <martyn@welchs.me.uk>
+Cc: devel@driverdev.osuosl.org
+Signed-off-by: Stefano Babic <sbabic@denx.de>
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/vme/vme.c |   15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/drivers/vme/vme.c
++++ b/drivers/vme/vme.c
+@@ -1625,10 +1625,25 @@ static int vme_bus_probe(struct device *
+       return retval;
+ }
++static int vme_bus_remove(struct device *dev)
++{
++      int retval = -ENODEV;
++      struct vme_driver *driver;
++      struct vme_dev *vdev = dev_to_vme_dev(dev);
++
++      driver = dev->platform_data;
++
++      if (driver->remove != NULL)
++              retval = driver->remove(vdev);
++
++      return retval;
++}
++
+ struct bus_type vme_bus_type = {
+       .name = "vme",
+       .match = vme_bus_match,
+       .probe = vme_bus_probe,
++      .remove = vme_bus_remove,
+ };
+ EXPORT_SYMBOL(vme_bus_type);
diff --git a/queue-4.10/w1-don-t-leak-refcount-on-slave-attach-failure-in-w1_attach_slave_device.patch b/queue-4.10/w1-don-t-leak-refcount-on-slave-attach-failure-in-w1_attach_slave_device.patch
new file mode 100644 (file)
index 0000000..c769981
--- /dev/null
@@ -0,0 +1,34 @@
+From d2ce4ea1a0b0162e5d2d7e7942ab6f5cc2063d5a Mon Sep 17 00:00:00 2001
+From: "Maciej S. Szmigiero" <mail@maciej.szmigiero.name>
+Date: Sat, 21 Jan 2017 23:50:18 +0100
+Subject: w1: don't leak refcount on slave attach failure in w1_attach_slave_device()
+
+From: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
+
+commit d2ce4ea1a0b0162e5d2d7e7942ab6f5cc2063d5a upstream.
+
+Near the beginning of w1_attach_slave_device() we increment a w1 master
+reference count.
+Later, when we are going to exit this function without actually attaching
+a slave device (due to failure of __w1_attach_slave_device()) we need to
+decrement this reference count back.
+
+Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
+Fixes: 9fcbbac5ded489 ("w1: process w1 netlink commands in w1_process thread")
+Cc: Evgeniy Polyakov <zbr@ioremap.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/w1/w1.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/w1/w1.c
++++ b/drivers/w1/w1.c
+@@ -763,6 +763,7 @@ int w1_attach_slave_device(struct w1_mas
+               dev_err(&dev->dev, "%s: Attaching %s failed.\n", __func__,
+                        sl->name);
+               w1_family_put(sl->family);
++              atomic_dec(&sl->master->refcnt);
+               kfree(sl);
+               return err;
+       }
diff --git a/queue-4.10/w1-ds2490-usb-transfer-buffers-need-to-be-dmaable.patch b/queue-4.10/w1-ds2490-usb-transfer-buffers-need-to-be-dmaable.patch
new file mode 100644 (file)
index 0000000..3aa58a2
--- /dev/null
@@ -0,0 +1,357 @@
+From 61cd1b4cd1e8f7f7642ab64529d9bd52e8374641 Mon Sep 17 00:00:00 2001
+From: "Maciej S. Szmigiero" <mail@maciej.szmigiero.name>
+Date: Wed, 18 Jan 2017 21:31:11 +0100
+Subject: w1: ds2490: USB transfer buffers need to be DMAable
+
+From: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
+
+commit 61cd1b4cd1e8f7f7642ab64529d9bd52e8374641 upstream.
+
+ds2490 driver was doing USB transfers from / to buffers on a stack.
+This is not permitted and made the driver non-working with vmapped stacks.
+
+Since all these transfers are done under the same bus_mutex lock we can
+simply use shared buffers in a device private structure for two most common
+of them.
+
+While we are at it, let's also fix a comparison between int and size_t in
+ds9490r_search() which made the driver spin in this function if state
+register get requests were failing.
+
+Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
+Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/w1/masters/ds2490.c |  142 ++++++++++++++++++++++++++------------------
+ 1 file changed, 84 insertions(+), 58 deletions(-)
+
+--- a/drivers/w1/masters/ds2490.c
++++ b/drivers/w1/masters/ds2490.c
+@@ -153,6 +153,9 @@ struct ds_device
+        */
+       u16                     spu_bit;
++      u8                      st_buf[ST_SIZE];
++      u8                      byte_buf;
++
+       struct w1_bus_master    master;
+ };
+@@ -174,7 +177,6 @@ struct ds_status
+       u8                      data_in_buffer_status;
+       u8                      reserved1;
+       u8                      reserved2;
+-
+ };
+ static struct usb_device_id ds_id_table [] = {
+@@ -244,28 +246,6 @@ static int ds_send_control(struct ds_dev
+       return err;
+ }
+-static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
+-                               unsigned char *buf, int size)
+-{
+-      int count, err;
+-
+-      memset(st, 0, sizeof(*st));
+-
+-      count = 0;
+-      err = usb_interrupt_msg(dev->udev, usb_rcvintpipe(dev->udev,
+-              dev->ep[EP_STATUS]), buf, size, &count, 1000);
+-      if (err < 0) {
+-              pr_err("Failed to read 1-wire data from 0x%x: err=%d.\n",
+-                     dev->ep[EP_STATUS], err);
+-              return err;
+-      }
+-
+-      if (count >= sizeof(*st))
+-              memcpy(st, buf, sizeof(*st));
+-
+-      return count;
+-}
+-
+ static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off)
+ {
+       pr_info("%45s: %8x\n", str, buf[off]);
+@@ -324,6 +304,35 @@ static void ds_dump_status(struct ds_dev
+       }
+ }
++static int ds_recv_status(struct ds_device *dev, struct ds_status *st,
++                        bool dump)
++{
++      int count, err;
++
++      if (st)
++              memset(st, 0, sizeof(*st));
++
++      count = 0;
++      err = usb_interrupt_msg(dev->udev,
++                              usb_rcvintpipe(dev->udev,
++                                             dev->ep[EP_STATUS]),
++                              dev->st_buf, sizeof(dev->st_buf),
++                              &count, 1000);
++      if (err < 0) {
++              pr_err("Failed to read 1-wire data from 0x%x: err=%d.\n",
++                     dev->ep[EP_STATUS], err);
++              return err;
++      }
++
++      if (dump)
++              ds_dump_status(dev, dev->st_buf, count);
++
++      if (st && count >= sizeof(*st))
++              memcpy(st, dev->st_buf, sizeof(*st));
++
++      return count;
++}
++
+ static void ds_reset_device(struct ds_device *dev)
+ {
+       ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+@@ -344,7 +353,6 @@ static void ds_reset_device(struct ds_de
+ static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
+ {
+       int count, err;
+-      struct ds_status st;
+       /* Careful on size.  If size is less than what is available in
+        * the input buffer, the device fails the bulk transfer and
+@@ -359,14 +367,9 @@ static int ds_recv_data(struct ds_device
+       err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
+                               buf, size, &count, 1000);
+       if (err < 0) {
+-              u8 buf[ST_SIZE];
+-              int count;
+-
+               pr_info("Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
+               usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
+-
+-              count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+-              ds_dump_status(dev, buf, count);
++              ds_recv_status(dev, NULL, true);
+               return err;
+       }
+@@ -404,7 +407,6 @@ int ds_stop_pulse(struct ds_device *dev,
+ {
+       struct ds_status st;
+       int count = 0, err = 0;
+-      u8 buf[ST_SIZE];
+       do {
+               err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
+@@ -413,7 +415,7 @@ int ds_stop_pulse(struct ds_device *dev,
+               err = ds_send_control(dev, CTL_RESUME_EXE, 0);
+               if (err)
+                       break;
+-              err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
++              err = ds_recv_status(dev, &st, false);
+               if (err)
+                       break;
+@@ -456,18 +458,17 @@ int ds_detect(struct ds_device *dev, str
+ static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+ {
+-      u8 buf[ST_SIZE];
+       int err, count = 0;
+       do {
+               st->status = 0;
+-              err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
++              err = ds_recv_status(dev, st, false);
+ #if 0
+               if (err >= 0) {
+                       int i;
+                       printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
+                       for (i=0; i<err; ++i)
+-                              printk("%02x ", buf[i]);
++                              printk("%02x ", dev->st_buf[i]);
+                       printk("\n");
+               }
+ #endif
+@@ -485,7 +486,7 @@ static int ds_wait_status(struct ds_devi
+        * can do something with it).
+        */
+       if (err > 16 || count >= 100 || err < 0)
+-              ds_dump_status(dev, buf, err);
++              ds_dump_status(dev, dev->st_buf, err);
+       /* Extended data isn't an error.  Well, a short is, but the dump
+        * would have already told the user that and we can't do anything
+@@ -608,7 +609,6 @@ static int ds_write_byte(struct ds_devic
+ {
+       int err;
+       struct ds_status st;
+-      u8 rbyte;
+       err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte);
+       if (err)
+@@ -621,11 +621,11 @@ static int ds_write_byte(struct ds_devic
+       if (err)
+               return err;
+-      err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
++      err = ds_recv_data(dev, &dev->byte_buf, 1);
+       if (err < 0)
+               return err;
+-      return !(byte == rbyte);
++      return !(byte == dev->byte_buf);
+ }
+ static int ds_read_byte(struct ds_device *dev, u8 *byte)
+@@ -712,7 +712,6 @@ static void ds9490r_search(void *data, s
+       int err;
+       u16 value, index;
+       struct ds_status st;
+-      u8 st_buf[ST_SIZE];
+       int search_limit;
+       int found = 0;
+       int i;
+@@ -724,7 +723,12 @@ static void ds9490r_search(void *data, s
+       /* FIFO 128 bytes, bulk packet size 64, read a multiple of the
+        * packet size.
+        */
+-      u64 buf[2*64/8];
++      const size_t bufsize = 2 * 64;
++      u64 *buf;
++
++      buf = kmalloc(bufsize, GFP_KERNEL);
++      if (!buf)
++              return;
+       mutex_lock(&master->bus_mutex);
+@@ -745,10 +749,9 @@ static void ds9490r_search(void *data, s
+       do {
+               schedule_timeout(jtime);
+-              if (ds_recv_status_nodump(dev, &st, st_buf, sizeof(st_buf)) <
+-                      sizeof(st)) {
++              err = ds_recv_status(dev, &st, false);
++              if (err < 0 || err < sizeof(st))
+                       break;
+-              }
+               if (st.data_in_buffer_status) {
+                       /* Bulk in can receive partial ids, but when it does
+@@ -758,7 +761,7 @@ static void ds9490r_search(void *data, s
+                        * bulk without first checking if status says there
+                        * is data to read.
+                        */
+-                      err = ds_recv_data(dev, (u8 *)buf, sizeof(buf));
++                      err = ds_recv_data(dev, (u8 *)buf, bufsize);
+                       if (err < 0)
+                               break;
+                       for (i = 0; i < err/8; ++i) {
+@@ -794,9 +797,14 @@ static void ds9490r_search(void *data, s
+       }
+ search_out:
+       mutex_unlock(&master->bus_mutex);
++      kfree(buf);
+ }
+ #if 0
++/*
++ * FIXME: if this disabled code is ever used in the future all ds_send_data()
++ * calls must be changed to use a DMAable buffer.
++ */
+ static int ds_match_access(struct ds_device *dev, u64 init)
+ {
+       int err;
+@@ -845,13 +853,12 @@ static int ds_set_path(struct ds_device
+ static u8 ds9490r_touch_bit(void *data, u8 bit)
+ {
+-      u8 ret;
+       struct ds_device *dev = data;
+-      if (ds_touch_bit(dev, bit, &ret))
++      if (ds_touch_bit(dev, bit, &dev->byte_buf))
+               return 0;
+-      return ret;
++      return dev->byte_buf;
+ }
+ #if 0
+@@ -866,13 +873,12 @@ static u8 ds9490r_read_bit(void *data)
+ {
+       struct ds_device *dev = data;
+       int err;
+-      u8 bit = 0;
+-      err = ds_touch_bit(dev, 1, &bit);
++      err = ds_touch_bit(dev, 1, &dev->byte_buf);
+       if (err)
+               return 0;
+-      return bit & 1;
++      return dev->byte_buf & 1;
+ }
+ #endif
+@@ -887,32 +893,52 @@ static u8 ds9490r_read_byte(void *data)
+ {
+       struct ds_device *dev = data;
+       int err;
+-      u8 byte = 0;
+-      err = ds_read_byte(dev, &byte);
++      err = ds_read_byte(dev, &dev->byte_buf);
+       if (err)
+               return 0;
+-      return byte;
++      return dev->byte_buf;
+ }
+ static void ds9490r_write_block(void *data, const u8 *buf, int len)
+ {
+       struct ds_device *dev = data;
++      u8 *tbuf;
++
++      if (len <= 0)
++              return;
++
++      tbuf = kmalloc(len, GFP_KERNEL);
++      if (!tbuf)
++              return;
++
++      memcpy(tbuf, buf, len);
++      ds_write_block(dev, tbuf, len);
+-      ds_write_block(dev, (u8 *)buf, len);
++      kfree(tbuf);
+ }
+ static u8 ds9490r_read_block(void *data, u8 *buf, int len)
+ {
+       struct ds_device *dev = data;
+       int err;
++      u8 *tbuf;
+-      err = ds_read_block(dev, buf, len);
+-      if (err < 0)
++      if (len <= 0)
++              return 0;
++
++      tbuf = kmalloc(len, GFP_KERNEL);
++      if (!tbuf)
+               return 0;
+-      return len;
++      err = ds_read_block(dev, tbuf, len);
++      if (err >= 0)
++              memcpy(buf, tbuf, len);
++
++      kfree(tbuf);
++
++      return err >= 0 ? len : 0;
+ }
+ static u8 ds9490r_reset(void *data)
diff --git a/queue-4.10/xprtrdma-disable-pad-optimization-by-default.patch b/queue-4.10/xprtrdma-disable-pad-optimization-by-default.patch
new file mode 100644 (file)
index 0000000..24a2331
--- /dev/null
@@ -0,0 +1,61 @@
+From c95a3c6b88658bcb8f77f85f31a0b9d9036e8016 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Wed, 8 Feb 2017 17:00:02 -0500
+Subject: xprtrdma: Disable pad optimization by default
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit c95a3c6b88658bcb8f77f85f31a0b9d9036e8016 upstream.
+
+Commit d5440e27d3e5 ("xprtrdma: Enable pad optimization") made the
+Linux client omit XDR round-up padding in normal Read and Write
+chunks so that the client doesn't have to register and invalidate
+3-byte memory regions that contain no real data.
+
+Unfortunately, my cheery 2014 assessment that this optimization "is
+supported now by both Linux and Solaris servers" was premature.
+We've found bugs in Solaris in this area since commit d5440e27d3e5
+("xprtrdma: Enable pad optimization") was merged (SYMLINK is the
+main offender).
+
+So for maximum interoperability, I'm disabling this optimization
+again. If a CM private message is exchanged when connecting, the
+client recognizes that the server is Linux, and enables the
+optimization for that connection.
+
+Until now the Solaris server bugs did not impact common operations,
+and were thus largely benign. Soon, less capable devices on Linux
+NFS/RDMA clients will make use of Read chunks more often, and these
+Solaris bugs will prevent interoperation in more cases.
+
+Fixes: 677eb17e94ed ("xprtrdma: Fix XDR tail buffer marshalling")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/xprtrdma/transport.c |    2 +-
+ net/sunrpc/xprtrdma/verbs.c     |    1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/sunrpc/xprtrdma/transport.c
++++ b/net/sunrpc/xprtrdma/transport.c
+@@ -67,7 +67,7 @@ unsigned int xprt_rdma_max_inline_read =
+ static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE;
+ static unsigned int xprt_rdma_inline_write_padding;
+ static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_FRMR;
+-              int xprt_rdma_pad_optimize = 1;
++              int xprt_rdma_pad_optimize = 0;
+ #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
+--- a/net/sunrpc/xprtrdma/verbs.c
++++ b/net/sunrpc/xprtrdma/verbs.c
+@@ -216,6 +216,7 @@ rpcrdma_update_connect_private(struct rp
+           pmsg->cp_magic == rpcrdma_cmp_magic &&
+           pmsg->cp_version == RPCRDMA_CMP_VERSION) {
+               r_xprt->rx_ia.ri_reminv_expected = true;
++              r_xprt->rx_ia.ri_implicit_roundup = true;
+               rsize = rpcrdma_decode_buffer_size(pmsg->cp_send_size);
+               wsize = rpcrdma_decode_buffer_size(pmsg->cp_recv_size);
+       }
diff --git a/queue-4.10/xprtrdma-fix-read-chunk-padding.patch b/queue-4.10/xprtrdma-fix-read-chunk-padding.patch
new file mode 100644 (file)
index 0000000..4ca3c36
--- /dev/null
@@ -0,0 +1,59 @@
+From 24abdf1be15c478e2821d6fc903a4a4440beff02 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Wed, 8 Feb 2017 16:59:46 -0500
+Subject: xprtrdma: Fix Read chunk padding
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit 24abdf1be15c478e2821d6fc903a4a4440beff02 upstream.
+
+When pad optimization is disabled, rpcrdma_convert_iovs still
+does not add explicit XDR round-up padding to a Read chunk.
+
+Commit 677eb17e94ed ("xprtrdma: Fix XDR tail buffer marshalling")
+incorrectly short-circuited the test for whether round-up padding
+is needed that appears later in rpcrdma_convert_iovs.
+
+However, if this is indeed a regular Read chunk (and not a
+Position-Zero Read chunk), the tail iovec _always_ contains the
+chunk's padding, and never anything else.
+
+So, it's easy to just skip the tail when padding optimization is
+enabled, and add the tail in a subsequent Read chunk segment, if
+disabled.
+
+Fixes: 677eb17e94ed ("xprtrdma: Fix XDR tail buffer marshalling")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/xprtrdma/rpc_rdma.c |   10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/net/sunrpc/xprtrdma/rpc_rdma.c
++++ b/net/sunrpc/xprtrdma/rpc_rdma.c
+@@ -226,8 +226,10 @@ rpcrdma_convert_iovs(struct xdr_buf *xdr
+       if (len && n == RPCRDMA_MAX_SEGS)
+               goto out_overflow;
+-      /* When encoding the read list, the tail is always sent inline */
+-      if (type == rpcrdma_readch)
++      /* When encoding a Read chunk, the tail iovec contains an
++       * XDR pad and may be omitted.
++       */
++      if (type == rpcrdma_readch && xprt_rdma_pad_optimize)
+               return n;
+       /* When encoding the Write list, some servers need to see an extra
+@@ -238,10 +240,6 @@ rpcrdma_convert_iovs(struct xdr_buf *xdr
+               return n;
+       if (xdrbuf->tail[0].iov_len) {
+-              /* the rpcrdma protocol allows us to omit any trailing
+-               * xdr pad bytes, saving the server an RDMA operation. */
+-              if (xdrbuf->tail[0].iov_len < 4 && xprt_rdma_pad_optimize)
+-                      return n;
+               n = rpcrdma_convert_kvec(&xdrbuf->tail[0], seg, n);
+               if (n == RPCRDMA_MAX_SEGS)
+                       goto out_overflow;
diff --git a/queue-4.10/xprtrdma-per-connection-pad-optimization.patch b/queue-4.10/xprtrdma-per-connection-pad-optimization.patch
new file mode 100644 (file)
index 0000000..a8cac35
--- /dev/null
@@ -0,0 +1,131 @@
+From b5f0afbea4f2ea52c613ac2b06cb6de2ea18cb6d Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Wed, 8 Feb 2017 16:59:54 -0500
+Subject: xprtrdma: Per-connection pad optimization
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit b5f0afbea4f2ea52c613ac2b06cb6de2ea18cb6d upstream.
+
+Pad optimization is changed by echoing into
+/proc/sys/sunrpc/rdma_pad_optimize. This is a global setting,
+affecting all RPC-over-RDMA connections to all servers.
+
+The marshaling code picks up that value and uses it for decisions
+about how to construct each RPC-over-RDMA frame. Having it change
+suddenly in mid-operation can result in unexpected failures. And
+some servers a client mounts might need chunk round-up, while
+others don't.
+
+So instead, copy the pad_optimize setting into each connection's
+rpcrdma_ia when the transport is created, and use the copy, which
+can't change during the life of the connection, instead.
+
+This also removes a hack: rpcrdma_convert_iovs was using
+the remote-invalidation-expected flag to predict when it could leave
+out Write chunk padding. This is because the Linux server handles
+implicit XDR padding on Write chunks correctly, and only Linux
+servers can set the connection's remote-invalidation-expected flag.
+
+It's more sensible to use the pad optimization setting instead.
+
+Fixes: 677eb17e94ed ("xprtrdma: Fix XDR tail buffer marshalling")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/xprtrdma/rpc_rdma.c  |   28 ++++++++++++++--------------
+ net/sunrpc/xprtrdma/verbs.c     |    1 +
+ net/sunrpc/xprtrdma/xprt_rdma.h |    1 +
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+
+--- a/net/sunrpc/xprtrdma/rpc_rdma.c
++++ b/net/sunrpc/xprtrdma/rpc_rdma.c
+@@ -186,9 +186,9 @@ rpcrdma_convert_kvec(struct kvec *vec, s
+  */
+ static int
+-rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos,
+-      enum rpcrdma_chunktype type, struct rpcrdma_mr_seg *seg,
+-      bool reminv_expected)
++rpcrdma_convert_iovs(struct rpcrdma_xprt *r_xprt, struct xdr_buf *xdrbuf,
++                   unsigned int pos, enum rpcrdma_chunktype type,
++                   struct rpcrdma_mr_seg *seg)
+ {
+       int len, n, p, page_base;
+       struct page **ppages;
+@@ -229,14 +229,15 @@ rpcrdma_convert_iovs(struct xdr_buf *xdr
+       /* When encoding a Read chunk, the tail iovec contains an
+        * XDR pad and may be omitted.
+        */
+-      if (type == rpcrdma_readch && xprt_rdma_pad_optimize)
++      if (type == rpcrdma_readch && r_xprt->rx_ia.ri_implicit_roundup)
+               return n;
+-      /* When encoding the Write list, some servers need to see an extra
+-       * segment for odd-length Write chunks. The upper layer provides
+-       * space in the tail iovec for this purpose.
++      /* When encoding a Write chunk, some servers need to see an
++       * extra segment for non-XDR-aligned Write chunks. The upper
++       * layer provides space in the tail iovec that may be used
++       * for this purpose.
+        */
+-      if (type == rpcrdma_writech && reminv_expected)
++      if (type == rpcrdma_writech && r_xprt->rx_ia.ri_implicit_roundup)
+               return n;
+       if (xdrbuf->tail[0].iov_len) {
+@@ -291,7 +292,8 @@ rpcrdma_encode_read_list(struct rpcrdma_
+       if (rtype == rpcrdma_areadch)
+               pos = 0;
+       seg = req->rl_segments;
+-      nsegs = rpcrdma_convert_iovs(&rqst->rq_snd_buf, pos, rtype, seg, false);
++      nsegs = rpcrdma_convert_iovs(r_xprt, &rqst->rq_snd_buf, pos,
++                                   rtype, seg);
+       if (nsegs < 0)
+               return ERR_PTR(nsegs);
+@@ -353,10 +355,9 @@ rpcrdma_encode_write_list(struct rpcrdma
+       }
+       seg = req->rl_segments;
+-      nsegs = rpcrdma_convert_iovs(&rqst->rq_rcv_buf,
++      nsegs = rpcrdma_convert_iovs(r_xprt, &rqst->rq_rcv_buf,
+                                    rqst->rq_rcv_buf.head[0].iov_len,
+-                                   wtype, seg,
+-                                   r_xprt->rx_ia.ri_reminv_expected);
++                                   wtype, seg);
+       if (nsegs < 0)
+               return ERR_PTR(nsegs);
+@@ -421,8 +422,7 @@ rpcrdma_encode_reply_chunk(struct rpcrdm
+       }
+       seg = req->rl_segments;
+-      nsegs = rpcrdma_convert_iovs(&rqst->rq_rcv_buf, 0, wtype, seg,
+-                                   r_xprt->rx_ia.ri_reminv_expected);
++      nsegs = rpcrdma_convert_iovs(r_xprt, &rqst->rq_rcv_buf, 0, wtype, seg);
+       if (nsegs < 0)
+               return ERR_PTR(nsegs);
+--- a/net/sunrpc/xprtrdma/verbs.c
++++ b/net/sunrpc/xprtrdma/verbs.c
+@@ -208,6 +208,7 @@ rpcrdma_update_connect_private(struct rp
+       /* Default settings for RPC-over-RDMA Version One */
+       r_xprt->rx_ia.ri_reminv_expected = false;
++      r_xprt->rx_ia.ri_implicit_roundup = xprt_rdma_pad_optimize;
+       rsize = RPCRDMA_V1_DEF_INLINE_SIZE;
+       wsize = RPCRDMA_V1_DEF_INLINE_SIZE;
+--- a/net/sunrpc/xprtrdma/xprt_rdma.h
++++ b/net/sunrpc/xprtrdma/xprt_rdma.h
+@@ -75,6 +75,7 @@ struct rpcrdma_ia {
+       unsigned int            ri_max_inline_write;
+       unsigned int            ri_max_inline_read;
+       bool                    ri_reminv_expected;
++      bool                    ri_implicit_roundup;
+       enum ib_mr_type         ri_mrtype;
+       struct ib_qp_attr       ri_qp_attr;
+       struct ib_qp_init_attr  ri_qp_init_attr;
diff --git a/queue-4.10/xprtrdma-reduce-required-number-of-send-sges.patch b/queue-4.10/xprtrdma-reduce-required-number-of-send-sges.patch
new file mode 100644 (file)
index 0000000..bc985d5
--- /dev/null
@@ -0,0 +1,135 @@
+From 16f906d66cd76fb9895cbc628f447532a7ac1faa Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Wed, 8 Feb 2017 17:00:10 -0500
+Subject: xprtrdma: Reduce required number of send SGEs
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit 16f906d66cd76fb9895cbc628f447532a7ac1faa upstream.
+
+The MAX_SEND_SGES check introduced in commit 655fec6987be
+("xprtrdma: Use gathered Send for large inline messages") fails
+for devices that have a small max_sge.
+
+Instead of checking for a large fixed maximum number of SGEs,
+check for a minimum small number. RPC-over-RDMA will switch to
+using a Read chunk if an xdr_buf has more pages than can fit in
+the device's max_sge limit. This is considerably better than
+failing all together to mount the server.
+
+This fix supports devices that have as few as three send SGEs
+available.
+
+Reported-by: Selvin Xavier <selvin.xavier@broadcom.com>
+Reported-by: Devesh Sharma <devesh.sharma@broadcom.com>
+Reported-by: Honggang Li <honli@redhat.com>
+Reported-by: Ram Amrani <Ram.Amrani@cavium.com>
+Fixes: 655fec6987be ("xprtrdma: Use gathered Send for large ...")
+Tested-by: Honggang Li <honli@redhat.com>
+Tested-by: Ram Amrani <Ram.Amrani@cavium.com>
+Tested-by: Steve Wise <swise@opengridcomputing.com>
+Reviewed-by: Parav Pandit <parav@mellanox.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sunrpc/xprtrdma/rpc_rdma.c  |   26 +++++++++++++++++++++++---
+ net/sunrpc/xprtrdma/verbs.c     |   13 +++++++------
+ net/sunrpc/xprtrdma/xprt_rdma.h |    2 ++
+ 3 files changed, 32 insertions(+), 9 deletions(-)
+
+--- a/net/sunrpc/xprtrdma/rpc_rdma.c
++++ b/net/sunrpc/xprtrdma/rpc_rdma.c
+@@ -125,14 +125,34 @@ void rpcrdma_set_max_header_sizes(struct
+ /* The client can send a request inline as long as the RPCRDMA header
+  * plus the RPC call fit under the transport's inline limit. If the
+  * combined call message size exceeds that limit, the client must use
+- * the read chunk list for this operation.
++ * a Read chunk for this operation.
++ *
++ * A Read chunk is also required if sending the RPC call inline would
++ * exceed this device's max_sge limit.
+  */
+ static bool rpcrdma_args_inline(struct rpcrdma_xprt *r_xprt,
+                               struct rpc_rqst *rqst)
+ {
+-      struct rpcrdma_ia *ia = &r_xprt->rx_ia;
++      struct xdr_buf *xdr = &rqst->rq_snd_buf;
++      unsigned int count, remaining, offset;
+-      return rqst->rq_snd_buf.len <= ia->ri_max_inline_write;
++      if (xdr->len > r_xprt->rx_ia.ri_max_inline_write)
++              return false;
++
++      if (xdr->page_len) {
++              remaining = xdr->page_len;
++              offset = xdr->page_base & ~PAGE_MASK;
++              count = 0;
++              while (remaining) {
++                      remaining -= min_t(unsigned int,
++                                         PAGE_SIZE - offset, remaining);
++                      offset = 0;
++                      if (++count > r_xprt->rx_ia.ri_max_send_sges)
++                              return false;
++              }
++      }
++
++      return true;
+ }
+ /* The client can't know how large the actual reply will be. Thus it
+--- a/net/sunrpc/xprtrdma/verbs.c
++++ b/net/sunrpc/xprtrdma/verbs.c
+@@ -488,18 +488,19 @@ rpcrdma_ia_close(struct rpcrdma_ia *ia)
+  */
+ int
+ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
+-                              struct rpcrdma_create_data_internal *cdata)
++                struct rpcrdma_create_data_internal *cdata)
+ {
+       struct rpcrdma_connect_private *pmsg = &ep->rep_cm_private;
++      unsigned int max_qp_wr, max_sge;
+       struct ib_cq *sendcq, *recvcq;
+-      unsigned int max_qp_wr;
+       int rc;
+-      if (ia->ri_device->attrs.max_sge < RPCRDMA_MAX_SEND_SGES) {
+-              dprintk("RPC:       %s: insufficient sge's available\n",
+-                      __func__);
++      max_sge = min(ia->ri_device->attrs.max_sge, RPCRDMA_MAX_SEND_SGES);
++      if (max_sge < RPCRDMA_MIN_SEND_SGES) {
++              pr_warn("rpcrdma: HCA provides only %d send SGEs\n", max_sge);
+               return -ENOMEM;
+       }
++      ia->ri_max_send_sges = max_sge - RPCRDMA_MIN_SEND_SGES;
+       if (ia->ri_device->attrs.max_qp_wr <= RPCRDMA_BACKWARD_WRS) {
+               dprintk("RPC:       %s: insufficient wqe's available\n",
+@@ -524,7 +525,7 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep,
+       ep->rep_attr.cap.max_recv_wr = cdata->max_requests;
+       ep->rep_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS;
+       ep->rep_attr.cap.max_recv_wr += 1;      /* drain cqe */
+-      ep->rep_attr.cap.max_send_sge = RPCRDMA_MAX_SEND_SGES;
++      ep->rep_attr.cap.max_send_sge = max_sge;
+       ep->rep_attr.cap.max_recv_sge = 1;
+       ep->rep_attr.cap.max_inline_data = 0;
+       ep->rep_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
+--- a/net/sunrpc/xprtrdma/xprt_rdma.h
++++ b/net/sunrpc/xprtrdma/xprt_rdma.h
+@@ -74,6 +74,7 @@ struct rpcrdma_ia {
+       unsigned int            ri_max_frmr_depth;
+       unsigned int            ri_max_inline_write;
+       unsigned int            ri_max_inline_read;
++      unsigned int            ri_max_send_sges;
+       bool                    ri_reminv_expected;
+       bool                    ri_implicit_roundup;
+       enum ib_mr_type         ri_mrtype;
+@@ -311,6 +312,7 @@ struct rpcrdma_mr_seg {            /* chunk descri
+  * - xdr_buf tail iovec
+  */
+ enum {
++      RPCRDMA_MIN_SEND_SGES = 3,
+       RPCRDMA_MAX_SEND_PAGES = PAGE_SIZE + RPCRDMA_MAX_INLINE - 1,
+       RPCRDMA_MAX_PAGE_SGES = (RPCRDMA_MAX_SEND_PAGES >> PAGE_SHIFT) + 1,
+       RPCRDMA_MAX_SEND_SGES = 1 + 1 + RPCRDMA_MAX_PAGE_SGES + 1,