From 25bbe7b767ef422f9130b34940173dba3378a62f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 10 Mar 2017 09:18:54 +0100 Subject: [PATCH] 4.9-stable patches 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 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 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 md-linear-fix-a-race-between-linear_add-and-linear_congested.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 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 usb-dwc3-gadget-skip-set-clear-halt-when-invalid.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-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 --- ...-when-probing-removing-device-driver.patch | 44 +++ ...t-use-stack-memory-for-usb-transfers.patch | 132 +++++++ ...x-memory-leak-of-priv-cmd_msg_buffer.patch | 52 +++ ...errupt-routine-checks-all-interrupts.patch | 37 ++ ...ackup-fix-a-rescind-processing-issue.patch | 51 +++ ...fcopy-fix-a-rescind-processing-issue.patch | 53 +++ ...l-kvp-fix-a-rescind-processing-issue.patch | 53 +++ ...-hv-vmbus-fix-a-rescind-handling-bug.patch | 136 +++++++ ...-sending-data-on-a-rescinded-channel.patch | 45 +++ ...ocks-check-for-bg-gc-victim-to-fg_gc.patch | 120 ++++++ ...-to-issue-redundant-discard-commands.patch | 49 +++ ...a-problem-of-using-memory-after-free.patch | 39 ++ ...f2fs_add_link-calls-having-same-name.patch | 90 +++++ ...missing-rcu-locking-for-glock-lookup.patch | 54 +++ ...ate-synic-pages-for-all-present-cpus.patch | 41 ++ ...t-reset-hv_context.tsc_page-on-crash.patch | 37 ++ ...v-init-percpu_list-in-hv_synic_alloc.patch | 41 ++ ...ween-linear_add-and-linear_congested.patch | 171 +++++++++ ...on-of-eccstat-registers-for-ifc-v1.0.patch | 63 ++++ .../nfsd-minor-nfsd_setattr-cleanup.patch | 97 +++++ ...fsd-special-case-truncates-some-more.patch | 94 +++++ ...acl-erange-for-some-acl-buffer-sizes.patch | 50 +++ ...v4-fix-getacl-head-length-estimation.patch | 36 ++ ...ate-leak-in-_nfs4_open_and_get_state.patch | 40 ++ ...-fix-reboot-recovery-in-copy-offload.patch | 157 ++++++++ ...d-it-must-be-updated-before-retrying.patch | 58 +++ ...r_kernel_ro-to-possible-feature-mask.patch | 31 ++ ...-host-radix-bits-when-setting-up-cpu.patch | 43 +++ .../powerpc-xmon-fix-data-breakpoint.patch | 44 +++ ...rrect-structure-packing-for-booleans.patch | 63 ++++ ...-iwarp-accepts-w-o-connection-params.patch | 34 ++ ...ader-don-t-overwrite-firmware-object.patch | 51 +++ queue-4.9/rtc-sun6i-add-some-locking.patch | 100 +++++ ...-sun6i-disable-the-build-as-a-module.patch | 45 +++ ...6i-switch-to-the-external-oscillator.patch | 52 +++ queue-4.9/rtlwifi-fix-alignment-issues.patch | 48 +++ ...tlwifi-rtl8192c-common-fix-bug-kasan.patch | 82 ++++ queue-4.9/series | 52 +++ ...get-skip-set-clear-halt-when-invalid.patch | 44 +++ ...b-gadget-f_hid-fix-free-out-requests.patch | 72 ++++ ...ix-prevent-accessing-released-memory.patch | 88 +++++ ...-f_hid-use-spinlock-instead-of-mutex.patch | 214 +++++++++++ ...rescan-pending-list-on-driver-unbind.patch | 124 ++++++ ...dc-fsl-add-missing-complete-function.patch | 58 +++ ...-plat-check-hcc_params-after-add-hcd.patch | 49 +++ ...xx-remove-cppi-3.0-quirk-and-methods.patch | 44 +++ ...ion-causing-incomplete-module-unload.patch | 63 ++++ ...ch-failure-in-w1_attach_slave_device.patch | 34 ++ ...-transfer-buffers-need-to-be-dmaable.patch | 357 ++++++++++++++++++ ...-disable-pad-optimization-by-default.patch | 61 +++ .../xprtrdma-fix-read-chunk-padding.patch | 59 +++ ...rdma-per-connection-pad-optimization.patch | 131 +++++++ ...-reduce-required-number-of-send-sges.patch | 135 +++++++ 53 files changed, 4018 insertions(+) create mode 100644 queue-4.9/bcma-use-get-put-_device-when-probing-removing-device-driver.patch create mode 100644 queue-4.9/can-gs_usb-don-t-use-stack-memory-for-usb-transfers.patch create mode 100644 queue-4.9/can-usb_8dev-fix-memory-leak-of-priv-cmd_msg_buffer.patch create mode 100644 queue-4.9/dmaengine-ipu-make-sure-the-interrupt-routine-checks-all-interrupts.patch create mode 100644 queue-4.9/drivers-hv-util-backup-fix-a-rescind-processing-issue.patch create mode 100644 queue-4.9/drivers-hv-util-fcopy-fix-a-rescind-processing-issue.patch create mode 100644 queue-4.9/drivers-hv-util-kvp-fix-a-rescind-processing-issue.patch create mode 100644 queue-4.9/drivers-hv-vmbus-fix-a-rescind-handling-bug.patch create mode 100644 queue-4.9/drivers-hv-vmbus-prevent-sending-data-on-a-rescinded-channel.patch create mode 100644 queue-4.9/f2fs-add-ovp-valid_blocks-check-for-bg-gc-victim-to-fg_gc.patch create mode 100644 queue-4.9/f2fs-avoid-to-issue-redundant-discard-commands.patch create mode 100644 queue-4.9/f2fs-fix-a-problem-of-using-memory-after-free.patch create mode 100644 queue-4.9/f2fs-fix-multiple-f2fs_add_link-calls-having-same-name.patch create mode 100644 queue-4.9/gfs2-add-missing-rcu-locking-for-glock-lookup.patch create mode 100644 queue-4.9/hv-allocate-synic-pages-for-all-present-cpus.patch create mode 100644 queue-4.9/hv-don-t-reset-hv_context.tsc_page-on-crash.patch create mode 100644 queue-4.9/hv-init-percpu_list-in-hv_synic_alloc.patch create mode 100644 queue-4.9/md-linear-fix-a-race-between-linear_add-and-linear_congested.patch create mode 100644 queue-4.9/mtd-nand-ifc-fix-location-of-eccstat-registers-for-ifc-v1.0.patch create mode 100644 queue-4.9/nfsd-minor-nfsd_setattr-cleanup.patch create mode 100644 queue-4.9/nfsd-special-case-truncates-some-more.patch create mode 100644 queue-4.9/nfsv4-fix-getacl-erange-for-some-acl-buffer-sizes.patch create mode 100644 queue-4.9/nfsv4-fix-getacl-head-length-estimation.patch create mode 100644 queue-4.9/nfsv4-fix-memory-and-state-leak-in-_nfs4_open_and_get_state.patch create mode 100644 queue-4.9/nfsv4-fix-reboot-recovery-in-copy-offload.patch create mode 100644 queue-4.9/pnfs-flexfiles-if-the-layout-is-invalid-it-must-be-updated-before-retrying.patch create mode 100644 queue-4.9/powerpc-mm-add-mmu_ftr_kernel_ro-to-possible-feature-mask.patch create mode 100644 queue-4.9/powerpc-mm-hash-always-clear-uprt-and-host-radix-bits-when-setting-up-cpu.patch create mode 100644 queue-4.9/powerpc-xmon-fix-data-breakpoint.patch create mode 100644 queue-4.9/rdma-core-fix-incorrect-structure-packing-for-booleans.patch create mode 100644 queue-4.9/rdma_cm-fail-iwarp-accepts-w-o-connection-params.patch create mode 100644 queue-4.9/remoteproc-qcom-mdt_loader-don-t-overwrite-firmware-object.patch create mode 100644 queue-4.9/rtc-sun6i-add-some-locking.patch create mode 100644 queue-4.9/rtc-sun6i-disable-the-build-as-a-module.patch create mode 100644 queue-4.9/rtc-sun6i-switch-to-the-external-oscillator.patch create mode 100644 queue-4.9/rtlwifi-fix-alignment-issues.patch create mode 100644 queue-4.9/rtlwifi-rtl8192c-common-fix-bug-kasan.patch create mode 100644 queue-4.9/usb-dwc3-gadget-skip-set-clear-halt-when-invalid.patch create mode 100644 queue-4.9/usb-gadget-f_hid-fix-free-out-requests.patch create mode 100644 queue-4.9/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch create mode 100644 queue-4.9/usb-gadget-f_hid-use-spinlock-instead-of-mutex.patch create mode 100644 queue-4.9/usb-gadget-udc-core-rescan-pending-list-on-driver-unbind.patch create mode 100644 queue-4.9/usb-gadget-udc-fsl-add-missing-complete-function.patch create mode 100644 queue-4.9/usb-host-xhci-plat-check-hcc_params-after-add-hcd.patch create mode 100644 queue-4.9/usb-musb-da8xx-remove-cppi-3.0-quirk-and-methods.patch create mode 100644 queue-4.9/vme-restore-bus_remove-function-causing-incomplete-module-unload.patch create mode 100644 queue-4.9/w1-don-t-leak-refcount-on-slave-attach-failure-in-w1_attach_slave_device.patch create mode 100644 queue-4.9/w1-ds2490-usb-transfer-buffers-need-to-be-dmaable.patch create mode 100644 queue-4.9/xprtrdma-disable-pad-optimization-by-default.patch create mode 100644 queue-4.9/xprtrdma-fix-read-chunk-padding.patch create mode 100644 queue-4.9/xprtrdma-per-connection-pad-optimization.patch create mode 100644 queue-4.9/xprtrdma-reduce-required-number-of-send-sges.patch diff --git a/queue-4.9/bcma-use-get-put-_device-when-probing-removing-device-driver.patch b/queue-4.9/bcma-use-get-put-_device-when-probing-removing-device-driver.patch new file mode 100644 index 00000000000..fb1347a0cc8 --- /dev/null +++ b/queue-4.9/bcma-use-get-put-_device-when-probing-removing-device-driver.patch @@ -0,0 +1,44 @@ +From a971df0b9d04674e325346c17de9a895425ca5e1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +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 + +commit a971df0b9d04674e325346c17de9a895425ca5e1 upstream. + +This allows tracking device state and e.g. makes devm work as expected. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/can-gs_usb-don-t-use-stack-memory-for-usb-transfers.patch b/queue-4.9/can-gs_usb-don-t-use-stack-memory-for-usb-transfers.patch new file mode 100644 index 00000000000..4501a9487af --- /dev/null +++ b/queue-4.9/can-gs_usb-don-t-use-stack-memory-for-usb-transfers.patch @@ -0,0 +1,132 @@ +From c919a3069c775c1c876bec55e00b2305d5125caa Mon Sep 17 00:00:00 2001 +From: Ethan Zonca +Date: Fri, 24 Feb 2017 11:27:36 -0500 +Subject: can: gs_usb: Don't use stack memory for USB transfers + +From: Ethan Zonca + +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 +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/can-usb_8dev-fix-memory-leak-of-priv-cmd_msg_buffer.patch b/queue-4.9/can-usb_8dev-fix-memory-leak-of-priv-cmd_msg_buffer.patch new file mode 100644 index 00000000000..46d6e42282d --- /dev/null +++ b/queue-4.9/can-usb_8dev-fix-memory-leak-of-priv-cmd_msg_buffer.patch @@ -0,0 +1,52 @@ +From 7c42631376306fb3f34d51fda546b50a9b6dd6ec Mon Sep 17 00:00:00 2001 +From: Marc Kleine-Budde +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 + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/dmaengine-ipu-make-sure-the-interrupt-routine-checks-all-interrupts.patch b/queue-4.9/dmaengine-ipu-make-sure-the-interrupt-routine-checks-all-interrupts.patch new file mode 100644 index 00000000000..e7634f00b0c --- /dev/null +++ b/queue-4.9/dmaengine-ipu-make-sure-the-interrupt-routine-checks-all-interrupts.patch @@ -0,0 +1,37 @@ +From adee40b265d7568296e218f079f478197ffa15bf Mon Sep 17 00:00:00 2001 +From: Magnus Lilja +Date: Wed, 21 Dec 2016 22:13:58 +0100 +Subject: dmaengine: ipu: Make sure the interrupt routine checks all interrupts. + +From: Magnus Lilja + +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 +Signed-off-by: Magnus Lilja +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/drivers-hv-util-backup-fix-a-rescind-processing-issue.patch b/queue-4.9/drivers-hv-util-backup-fix-a-rescind-processing-issue.patch new file mode 100644 index 00000000000..92380161a05 --- /dev/null +++ b/queue-4.9/drivers-hv-util-backup-fix-a-rescind-processing-issue.patch @@ -0,0 +1,51 @@ +From d77044d142e960f7b5f814a91ecb8bcf86aa552c Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" +Date: Thu, 22 Dec 2016 16:54:03 -0800 +Subject: Drivers: hv: util: Backup: Fix a rescind processing issue + +From: K. Y. Srinivasan + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/hv_snapshot.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/hv/hv_snapshot.c ++++ b/drivers/hv/hv_snapshot.c +@@ -66,6 +66,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); +@@ -330,11 +331,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"); +@@ -365,4 +368,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.9/drivers-hv-util-fcopy-fix-a-rescind-processing-issue.patch b/queue-4.9/drivers-hv-util-fcopy-fix-a-rescind-processing-issue.patch new file mode 100644 index 00000000000..43e865996a3 --- /dev/null +++ b/queue-4.9/drivers-hv-util-fcopy-fix-a-rescind-processing-issue.patch @@ -0,0 +1,53 @@ +From 20951c7535b5e6af46bc37b7142105f716df739c Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" +Date: Thu, 22 Dec 2016 16:54:02 -0800 +Subject: Drivers: hv: util: Fcopy: Fix a rescind processing issue + +From: K. Y. Srinivasan + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/drivers-hv-util-kvp-fix-a-rescind-processing-issue.patch b/queue-4.9/drivers-hv-util-kvp-fix-a-rescind-processing-issue.patch new file mode 100644 index 00000000000..302c50d7b77 --- /dev/null +++ b/queue-4.9/drivers-hv-util-kvp-fix-a-rescind-processing-issue.patch @@ -0,0 +1,53 @@ +From 5a66fecbf6aa528e375cbebccb1061cc58d80c84 Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" +Date: Thu, 22 Dec 2016 16:54:01 -0800 +Subject: Drivers: hv: util: kvp: Fix a rescind processing issue + +From: K. Y. Srinivasan + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/drivers-hv-vmbus-fix-a-rescind-handling-bug.patch b/queue-4.9/drivers-hv-vmbus-fix-a-rescind-handling-bug.patch new file mode 100644 index 00000000000..6901bd75e28 --- /dev/null +++ b/queue-4.9/drivers-hv-vmbus-fix-a-rescind-handling-bug.patch @@ -0,0 +1,136 @@ +From ccb61f8a99e6c29df4fb96a65dad4fad740d5be9 Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" +Date: Thu, 22 Dec 2016 16:54:00 -0800 +Subject: Drivers: hv: vmbus: Fix a rescind handling bug + +From: K. Y. Srinivasan + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/drivers-hv-vmbus-prevent-sending-data-on-a-rescinded-channel.patch b/queue-4.9/drivers-hv-vmbus-prevent-sending-data-on-a-rescinded-channel.patch new file mode 100644 index 00000000000..b9d65bf816b --- /dev/null +++ b/queue-4.9/drivers-hv-vmbus-prevent-sending-data-on-a-rescinded-channel.patch @@ -0,0 +1,45 @@ +From e7e97dd8b77ee7366f2f8c70a033bf5fa05ec2e0 Mon Sep 17 00:00:00 2001 +From: "K. Y. Srinivasan" +Date: Wed, 7 Dec 2016 01:16:28 -0800 +Subject: Drivers: hv: vmbus: Prevent sending data on a rescinded channel + +From: K. Y. Srinivasan + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/f2fs-add-ovp-valid_blocks-check-for-bg-gc-victim-to-fg_gc.patch b/queue-4.9/f2fs-add-ovp-valid_blocks-check-for-bg-gc-victim-to-fg_gc.patch new file mode 100644 index 00000000000..3c6a90eaa03 --- /dev/null +++ b/queue-4.9/f2fs-add-ovp-valid_blocks-check-for-bg-gc-victim-to-fg_gc.patch @@ -0,0 +1,120 @@ +From e93b9865251a0503d83fd570e7d5a7c8bc351715 Mon Sep 17 00:00:00 2001 +From: Hou Pengyang +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 + +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 +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -834,6 +834,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); + +@@ -972,5 +979,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 +@@ -688,6 +688,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.9/f2fs-avoid-to-issue-redundant-discard-commands.patch b/queue-4.9/f2fs-avoid-to-issue-redundant-discard-commands.patch new file mode 100644 index 00000000000..0166bce05c4 --- /dev/null +++ b/queue-4.9/f2fs-avoid-to-issue-redundant-discard-commands.patch @@ -0,0 +1,49 @@ +From 8b107f5b97772c7c0c218302e9a4d15b4edf50b4 Mon Sep 17 00:00:00 2001 +From: Jaegeuk Kim +Date: Mon, 27 Feb 2017 11:57:11 -0800 +Subject: f2fs: avoid to issue redundant discard commands + +From: Jaegeuk Kim + +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 +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman + +--- + fs/f2fs/segment.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -813,6 +813,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.9/f2fs-fix-a-problem-of-using-memory-after-free.patch b/queue-4.9/f2fs-fix-a-problem-of-using-memory-after-free.patch new file mode 100644 index 00000000000..3c20fa11c5d --- /dev/null +++ b/queue-4.9/f2fs-fix-a-problem-of-using-memory-after-free.patch @@ -0,0 +1,39 @@ +From 7855eba4d6102f811b6dd142d6c749f53b591fa3 Mon Sep 17 00:00:00 2001 +From: Yunlei He +Date: Mon, 19 Dec 2016 20:10:48 +0800 +Subject: f2fs: fix a problem of using memory after free + +From: Yunlei He + +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 +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/f2fs-fix-multiple-f2fs_add_link-calls-having-same-name.patch b/queue-4.9/f2fs-fix-multiple-f2fs_add_link-calls-having-same-name.patch new file mode 100644 index 00000000000..81ccf6a8cca --- /dev/null +++ b/queue-4.9/f2fs-fix-multiple-f2fs_add_link-calls-having-same-name.patch @@ -0,0 +1,90 @@ +From 88c5c13a5027b36d914536fdba23f069d7067204 Mon Sep 17 00:00:00 2001 +From: Jaegeuk Kim +Date: Tue, 14 Feb 2017 09:54:37 -0800 +Subject: f2fs: fix multiple f2fs_add_link() calls having same name + +From: Jaegeuk Kim + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -431,6 +431,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.9/gfs2-add-missing-rcu-locking-for-glock-lookup.patch b/queue-4.9/gfs2-add-missing-rcu-locking-for-glock-lookup.patch new file mode 100644 index 00000000000..29d7eff5bac --- /dev/null +++ b/queue-4.9/gfs2-add-missing-rcu-locking-for-glock-lookup.patch @@ -0,0 +1,54 @@ +From f38e5fb95a1f8feda88531eedc98f69b24748712 Mon Sep 17 00:00:00 2001 +From: Andrew Price +Date: Wed, 22 Feb 2017 12:05:03 -0500 +Subject: gfs2: Add missing rcu locking for glock lookup + +From: Andrew Price + +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 +Signed-off-by: Andreas Gruenbacher +Signed-off-by: Bob Peterson +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/hv-allocate-synic-pages-for-all-present-cpus.patch b/queue-4.9/hv-allocate-synic-pages-for-all-present-cpus.patch new file mode 100644 index 00000000000..c4618b8a683 --- /dev/null +++ b/queue-4.9/hv-allocate-synic-pages-for-all-present-cpus.patch @@ -0,0 +1,41 @@ +From 421b8f20d3c381b215f988b42428f56fc3b82405 Mon Sep 17 00:00:00 2001 +From: Vitaly Kuznetsov +Date: Wed, 7 Dec 2016 01:16:25 -0800 +Subject: hv: allocate synic pages for all present CPUs + +From: Vitaly Kuznetsov + +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 +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/hv-don-t-reset-hv_context.tsc_page-on-crash.patch b/queue-4.9/hv-don-t-reset-hv_context.tsc_page-on-crash.patch new file mode 100644 index 00000000000..b310a2ee613 --- /dev/null +++ b/queue-4.9/hv-don-t-reset-hv_context.tsc_page-on-crash.patch @@ -0,0 +1,37 @@ +From 56ef6718a1d8d77745033c5291e025ce18504159 Mon Sep 17 00:00:00 2001 +From: Vitaly Kuznetsov +Date: Wed, 7 Dec 2016 01:16:27 -0800 +Subject: hv: don't reset hv_context.tsc_page on crash + +From: Vitaly Kuznetsov + +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 +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/hv-init-percpu_list-in-hv_synic_alloc.patch b/queue-4.9/hv-init-percpu_list-in-hv_synic_alloc.patch new file mode 100644 index 00000000000..f1d565f8d96 --- /dev/null +++ b/queue-4.9/hv-init-percpu_list-in-hv_synic_alloc.patch @@ -0,0 +1,41 @@ +From 3c7630d35009e6635e5b58d62de554fd5b6db5df Mon Sep 17 00:00:00 2001 +From: Vitaly Kuznetsov +Date: Wed, 7 Dec 2016 01:16:26 -0800 +Subject: hv: init percpu_list in hv_synic_alloc() + +From: Vitaly Kuznetsov + +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 +Signed-off-by: K. Y. Srinivasan +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/md-linear-fix-a-race-between-linear_add-and-linear_congested.patch b/queue-4.9/md-linear-fix-a-race-between-linear_add-and-linear_congested.patch new file mode 100644 index 00000000000..50950dcc2bf --- /dev/null +++ b/queue-4.9/md-linear-fix-a-race-between-linear_add-and-linear_congested.patch @@ -0,0 +1,171 @@ +From 03a9e24ef2aaa5f1f9837356aed79c860521407a Mon Sep 17 00:00:00 2001 +From: "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 + +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; iraid_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 +Cc: Shaohua Li +Cc: Neil Brown +Signed-off-by: Shaohua Li +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -52,18 +52,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; + } + +@@ -143,6 +151,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: +@@ -195,15 +216,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.9/mtd-nand-ifc-fix-location-of-eccstat-registers-for-ifc-v1.0.patch b/queue-4.9/mtd-nand-ifc-fix-location-of-eccstat-registers-for-ifc-v1.0.patch new file mode 100644 index 00000000000..ab599cb40e0 --- /dev/null +++ b/queue-4.9/mtd-nand-ifc-fix-location-of-eccstat-registers-for-ifc-v1.0.patch @@ -0,0 +1,63 @@ +From 656441478ed55d960df5f3ccdf5a0f8c61dfd0b3 Mon Sep 17 00:00:00 2001 +From: Mark Marshall +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 + +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 +Signed-off-by: Boris Brezillon +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/nfsd-minor-nfsd_setattr-cleanup.patch b/queue-4.9/nfsd-minor-nfsd_setattr-cleanup.patch new file mode 100644 index 00000000000..33afd4939a2 --- /dev/null +++ b/queue-4.9/nfsd-minor-nfsd_setattr-cleanup.patch @@ -0,0 +1,97 @@ +From 758e99fefe1d9230111296956335cd35995c0eaf Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Mon, 20 Feb 2017 17:04:42 -0500 +Subject: nfsd: minor nfsd_setattr cleanup + +From: Christoph Hellwig + +commit 758e99fefe1d9230111296956335cd35995c0eaf upstream. + +Simplify exit paths, size_change use. + +Signed-off-by: Christoph Hellwig +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/nfsd-special-case-truncates-some-more.patch b/queue-4.9/nfsd-special-case-truncates-some-more.patch new file mode 100644 index 00000000000..9accc2c8654 --- /dev/null +++ b/queue-4.9/nfsd-special-case-truncates-some-more.patch @@ -0,0 +1,94 @@ +From 783112f7401ff449d979530209b3f6c2594fdb4e Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Mon, 20 Feb 2017 07:21:33 +0100 +Subject: nfsd: special case truncates some more + +From: Christoph Hellwig + +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 +Tested-by: Chuck Lever +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/nfsv4-fix-getacl-erange-for-some-acl-buffer-sizes.patch b/queue-4.9/nfsv4-fix-getacl-erange-for-some-acl-buffer-sizes.patch new file mode 100644 index 00000000000..3cf1e022199 --- /dev/null +++ b/queue-4.9/nfsv4-fix-getacl-erange-for-some-acl-buffer-sizes.patch @@ -0,0 +1,50 @@ +From ed92d8c137b7794c2c2aa14479298b9885967607 Mon Sep 17 00:00:00 2001 +From: Weston Andros Adamson +Date: Thu, 23 Feb 2017 14:54:21 -0500 +Subject: NFSv4: fix getacl ERANGE for some ACL buffer sizes + +From: Weston Andros Adamson + +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 +Signed-off-by: J. Bruce Fields +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4proc.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -4990,7 +4990,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, +@@ -5004,13 +5004,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.9/nfsv4-fix-getacl-head-length-estimation.patch b/queue-4.9/nfsv4-fix-getacl-head-length-estimation.patch new file mode 100644 index 00000000000..3dd7b4f307c --- /dev/null +++ b/queue-4.9/nfsv4-fix-getacl-head-length-estimation.patch @@ -0,0 +1,36 @@ +From 6682c14bbe505a8b912c57faf544f866777ee48d Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Thu, 23 Feb 2017 14:53:39 -0500 +Subject: NFSv4: fix getacl head length estimation + +From: J. Bruce Fields + +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 +Signed-off-by: J. Bruce Fields +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4xdr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -2492,7 +2492,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.9/nfsv4-fix-memory-and-state-leak-in-_nfs4_open_and_get_state.patch b/queue-4.9/nfsv4-fix-memory-and-state-leak-in-_nfs4_open_and_get_state.patch new file mode 100644 index 00000000000..3384572956a --- /dev/null +++ b/queue-4.9/nfsv4-fix-memory-and-state-leak-in-_nfs4_open_and_get_state.patch @@ -0,0 +1,40 @@ +From a974deee477af89411e0f80456bfb344ac433c98 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +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 + +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 +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4proc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -2708,6 +2708,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) +@@ -2733,7 +2734,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.9/nfsv4-fix-reboot-recovery-in-copy-offload.patch b/queue-4.9/nfsv4-fix-reboot-recovery-in-copy-offload.patch new file mode 100644 index 00000000000..c0b9f707f06 --- /dev/null +++ b/queue-4.9/nfsv4-fix-reboot-recovery-in-copy-offload.patch @@ -0,0 +1,157 @@ +From 9d8cacbf5636657d2cd0dda17438a56d806d3224 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 17 Feb 2017 18:42:32 -0500 +Subject: NFSv4: Fix reboot recovery in copy offload + +From: Trond Myklebust + +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 +Fixes: 2e72448b07dc3 ("NFS: Add COPY nfs operation") +Signed-off-by: Trond Myklebust +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/pnfs-flexfiles-if-the-layout-is-invalid-it-must-be-updated-before-retrying.patch b/queue-4.9/pnfs-flexfiles-if-the-layout-is-invalid-it-must-be-updated-before-retrying.patch new file mode 100644 index 00000000000..6074920144f --- /dev/null +++ b/queue-4.9/pnfs-flexfiles-if-the-layout-is-invalid-it-must-be-updated-before-retrying.patch @@ -0,0 +1,58 @@ +From df3ab232e462bce20710596d697ade6b72497694 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +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 + +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 +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -1073,9 +1073,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: +@@ -1176,9 +1173,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: +@@ -1213,6 +1207,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.9/powerpc-mm-add-mmu_ftr_kernel_ro-to-possible-feature-mask.patch b/queue-4.9/powerpc-mm-add-mmu_ftr_kernel_ro-to-possible-feature-mask.patch new file mode 100644 index 00000000000..7755fcb193c --- /dev/null +++ b/queue-4.9/powerpc-mm-add-mmu_ftr_kernel_ro-to-possible-feature-mask.patch @@ -0,0 +1,31 @@ +From a5ecdad4847897007399d7a14c9109b65ce4c9b7 Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +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 + +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 +Acked-by: Balbir Singh +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/powerpc-mm-hash-always-clear-uprt-and-host-radix-bits-when-setting-up-cpu.patch b/queue-4.9/powerpc-mm-hash-always-clear-uprt-and-host-radix-bits-when-setting-up-cpu.patch new file mode 100644 index 00000000000..966c693c190 --- /dev/null +++ b/queue-4.9/powerpc-mm-hash-always-clear-uprt-and-host-radix-bits-when-setting-up-cpu.patch @@ -0,0 +1,43 @@ +From fda2d27db6eae5c2468f9e4657539b72bbc238bb Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +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 + +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 +Signed-off-by: Aneesh Kumar K.V +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -100,6 +100,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 +@@ -120,6 +122,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.9/powerpc-xmon-fix-data-breakpoint.patch b/queue-4.9/powerpc-xmon-fix-data-breakpoint.patch new file mode 100644 index 00000000000..52df94a57db --- /dev/null +++ b/queue-4.9/powerpc-xmon-fix-data-breakpoint.patch @@ -0,0 +1,44 @@ +From c21a493a2b44650707d06741601894329486f2ad Mon Sep 17 00:00:00 2001 +From: Ravi Bangoria +Date: Tue, 22 Nov 2016 14:55:59 +0530 +Subject: powerpc/xmon: Fix data-breakpoint + +From: Ravi Bangoria + +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 +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/rdma-core-fix-incorrect-structure-packing-for-booleans.patch b/queue-4.9/rdma-core-fix-incorrect-structure-packing-for-booleans.patch new file mode 100644 index 00000000000..4213b012001 --- /dev/null +++ b/queue-4.9/rdma-core-fix-incorrect-structure-packing-for-booleans.patch @@ -0,0 +1,63 @@ +From 55efcfcd7776165b294f8b5cd6e05ca00ec89b7c Mon Sep 17 00:00:00 2001 +From: Jason Gunthorpe +Date: Thu, 22 Dec 2016 18:07:52 -0700 +Subject: RDMA/core: Fix incorrect structure packing for booleans + +From: Jason Gunthorpe + +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 +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/rdma_cm-fail-iwarp-accepts-w-o-connection-params.patch b/queue-4.9/rdma_cm-fail-iwarp-accepts-w-o-connection-params.patch new file mode 100644 index 00000000000..892f91ac24d --- /dev/null +++ b/queue-4.9/rdma_cm-fail-iwarp-accepts-w-o-connection-params.patch @@ -0,0 +1,34 @@ +From f2625f7db4dd0bbd16a9c7d2950e7621f9aa57ad Mon Sep 17 00:00:00 2001 +From: Steve Wise +Date: Tue, 21 Feb 2017 11:21:57 -0800 +Subject: rdma_cm: fail iwarp accepts w/o connection params + +From: Steve Wise + +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 +Acked-by: Sean Hefty +Signed-off-by: Steve Wise +Signed-off-by: Doug Ledford +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/core/cma.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/infiniband/core/cma.c ++++ b/drivers/infiniband/core/cma.c +@@ -3540,6 +3540,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.9/remoteproc-qcom-mdt_loader-don-t-overwrite-firmware-object.patch b/queue-4.9/remoteproc-qcom-mdt_loader-don-t-overwrite-firmware-object.patch new file mode 100644 index 00000000000..ad8e9bd3fe4 --- /dev/null +++ b/queue-4.9/remoteproc-qcom-mdt_loader-don-t-overwrite-firmware-object.patch @@ -0,0 +1,51 @@ +From 3e8b571a9a0881ba3381ca0915995696da145ab8 Mon Sep 17 00:00:00 2001 +From: Bjorn Andersson +Date: Fri, 27 Jan 2017 02:06:36 -0800 +Subject: remoteproc: qcom: mdt_loader: Don't overwrite firmware object + +From: Bjorn Andersson + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -115,6 +115,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; +@@ -153,16 +154,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.9/rtc-sun6i-add-some-locking.patch b/queue-4.9/rtc-sun6i-add-some-locking.patch new file mode 100644 index 00000000000..65882ad0d2e --- /dev/null +++ b/queue-4.9/rtc-sun6i-add-some-locking.patch @@ -0,0 +1,100 @@ +From a9422a19ce270a22fc520f2278fb7e80c58be508 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Mon, 23 Jan 2017 11:41:47 +0100 +Subject: rtc: sun6i: Add some locking + +From: Maxime Ripard + +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 +Signed-off-by: Maxime Ripard +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/rtc-sun6i-disable-the-build-as-a-module.patch b/queue-4.9/rtc-sun6i-disable-the-build-as-a-module.patch new file mode 100644 index 00000000000..5815d59ef9f --- /dev/null +++ b/queue-4.9/rtc-sun6i-disable-the-build-as-a-module.patch @@ -0,0 +1,45 @@ +From 3753941475ae6501dcd1e41832bd0e6c35247d6a Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Mon, 23 Jan 2017 11:41:46 +0100 +Subject: rtc: sun6i: Disable the build as a module + +From: Maxime Ripard + +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 +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -1432,7 +1432,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 "); +-MODULE_LICENSE("GPL"); ++builtin_platform_driver(sun6i_rtc_driver); diff --git a/queue-4.9/rtc-sun6i-switch-to-the-external-oscillator.patch b/queue-4.9/rtc-sun6i-switch-to-the-external-oscillator.patch new file mode 100644 index 00000000000..5bc76ef0683 --- /dev/null +++ b/queue-4.9/rtc-sun6i-switch-to-the-external-oscillator.patch @@ -0,0 +1,52 @@ +From fb61bb82cb46a932ef2fc62e1c731c8e7e6640d5 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Mon, 23 Jan 2017 11:41:48 +0100 +Subject: rtc: sun6i: Switch to the external oscillator + +From: Maxime Ripard + +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 +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/rtlwifi-fix-alignment-issues.patch b/queue-4.9/rtlwifi-fix-alignment-issues.patch new file mode 100644 index 00000000000..bd70b25a1c0 --- /dev/null +++ b/queue-4.9/rtlwifi-fix-alignment-issues.patch @@ -0,0 +1,48 @@ +From 40b368af4b750863b2cb66a3a9513241db2f0793 Mon Sep 17 00:00:00 2001 +From: Ping-Ke Shih +Date: Wed, 28 Dec 2016 15:40:04 -0600 +Subject: rtlwifi: Fix alignment issues + +From: Ping-Ke Shih + +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 +Signed-off-by: Larry Finger +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/rtlwifi-rtl8192c-common-fix-bug-kasan.patch b/queue-4.9/rtlwifi-rtl8192c-common-fix-bug-kasan.patch new file mode 100644 index 00000000000..398daa5e771 --- /dev/null +++ b/queue-4.9/rtlwifi-rtl8192c-common-fix-bug-kasan.patch @@ -0,0 +1,82 @@ +From 6773386f977ce5af339f9678fa2918909a946c6b Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Sun, 5 Feb 2017 10:24:22 -0600 +Subject: rtlwifi: rtl8192c-common: Fix "BUG: KASAN: + +From: Larry Finger + +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: + [] ? dump_stack+0x5c/0x79 + [] ? kasan_report_error+0x4b9/0x4e0 + [] ? _usb_read_sync+0x15c/0x280 [rtl_usb] + [] ? __asan_report_load1_noabort+0x45/0x50 + [] ? rtl92c_dm_bt_coexist+0x858/0x1e40 [rtl8192c_common] + [] ? rtl92c_dm_bt_coexist+0x858/0x1e40 [rtl8192c_common] + [] ? 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 +Signed-off-by: Larry Finger +Cc: Dmitry Osipenko +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -275,10 +275,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 +@@ -150,8 +150,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.9/series b/queue-4.9/series index d2c029e1e2c..1ed83370755 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -93,3 +93,55 @@ arm64-fix-erroneous-__raw_read_system_reg-cases.patch kvm-arm-arm64-vgic-stop-injecting-the-msi-occurrence-twice.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 +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 +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 +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 diff --git a/queue-4.9/usb-dwc3-gadget-skip-set-clear-halt-when-invalid.patch b/queue-4.9/usb-dwc3-gadget-skip-set-clear-halt-when-invalid.patch new file mode 100644 index 00000000000..1351e375d11 --- /dev/null +++ b/queue-4.9/usb-dwc3-gadget-skip-set-clear-halt-when-invalid.patch @@ -0,0 +1,44 @@ +From ffb80fc672c3a7b6afd0cefcb1524fb99917b2f3 Mon Sep 17 00:00:00 2001 +From: Felipe Balbi +Date: Thu, 19 Jan 2017 13:38:42 +0200 +Subject: usb: dwc3: gadget: skip Set/Clear Halt when invalid + +From: Felipe Balbi + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/gadget.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1234,6 +1234,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 +@@ -1258,6 +1261,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.9/usb-gadget-f_hid-fix-free-out-requests.patch b/queue-4.9/usb-gadget-f_hid-fix-free-out-requests.patch new file mode 100644 index 00000000000..33e62f66f8b --- /dev/null +++ b/queue-4.9/usb-gadget-f_hid-fix-free-out-requests.patch @@ -0,0 +1,72 @@ +From 20d2ca955bd09639c7b01db5761d157c297aea0a Mon Sep 17 00:00:00 2001 +From: Krzysztof Opasiak +Date: Thu, 19 Jan 2017 18:55:27 +0100 +Subject: usb: gadget: f_hid: fix: Free out requests + +From: Krzysztof Opasiak + +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 +Signed-off-by: Krzysztof Opasiak +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -371,20 +371,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.9/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch b/queue-4.9/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch new file mode 100644 index 00000000000..9293bcd0116 --- /dev/null +++ b/queue-4.9/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch @@ -0,0 +1,88 @@ +From aa65d11aa008f4de58a9cee7e121666d9d68505e Mon Sep 17 00:00:00 2001 +From: Krzysztof Opasiak +Date: Thu, 19 Jan 2017 18:55:28 +0100 +Subject: usb: gadget: f_hid: fix: Prevent accessing released memory + +From: Krzysztof Opasiak + +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 +Signed-off-by: Krzysztof Opasiak +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -223,6 +223,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); +@@ -238,15 +245,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; +@@ -506,14 +518,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.9/usb-gadget-f_hid-use-spinlock-instead-of-mutex.patch b/queue-4.9/usb-gadget-f_hid-use-spinlock-instead-of-mutex.patch new file mode 100644 index 00000000000..c379b8e9d14 --- /dev/null +++ b/queue-4.9/usb-gadget-f_hid-use-spinlock-instead-of-mutex.patch @@ -0,0 +1,214 @@ +From 33e4c1a9987a1fc3b42c3b534100b5b006d55c61 Mon Sep 17 00:00:00 2001 +From: Krzysztof Opasiak +Date: Thu, 19 Jan 2017 18:55:29 +0100 +Subject: usb: gadget: f_hid: Use spinlock instead of mutex + +From: Krzysztof Opasiak + +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 +Signed-off-by: Krzysztof Opasiak +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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; +@@ -204,20 +204,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 */ +@@ -232,7 +232,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); +@@ -254,9 +254,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); + } +@@ -267,13 +267,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); + } + +@@ -281,18 +284,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; + +@@ -300,17 +304,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; +@@ -318,19 +325,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; + } +@@ -397,9 +408,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; +@@ -523,13 +534,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) +@@ -678,8 +689,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.9/usb-gadget-udc-core-rescan-pending-list-on-driver-unbind.patch b/queue-4.9/usb-gadget-udc-core-rescan-pending-list-on-driver-unbind.patch new file mode 100644 index 00000000000..04c74b27c1e --- /dev/null +++ b/queue-4.9/usb-gadget-udc-core-rescan-pending-list-on-driver-unbind.patch @@ -0,0 +1,124 @@ +From 8236800da115a3e24b9165c573067343f51cf5ea Mon Sep 17 00:00:00 2001 +From: Krzysztof Opasiak +Date: Mon, 16 Jan 2017 08:40:57 +0100 +Subject: usb: gadget: udc-core: Rescan pending list on driver unbind + +From: Krzysztof Opasiak + +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 +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/usb-gadget-udc-fsl-add-missing-complete-function.patch b/queue-4.9/usb-gadget-udc-fsl-add-missing-complete-function.patch new file mode 100644 index 00000000000..7f08e6c240f --- /dev/null +++ b/queue-4.9/usb-gadget-udc-fsl-add-missing-complete-function.patch @@ -0,0 +1,58 @@ +From 5528954a1a0c49c6974ef1b8d6eaceff536204d5 Mon Sep 17 00:00:00 2001 +From: Magnus Lilja +Date: Wed, 25 Jan 2017 22:07:59 +0100 +Subject: usb: gadget: udc: fsl: Add missing complete function. + +From: Magnus Lilja + +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 +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -1249,6 +1249,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) +@@ -1283,7 +1289,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)); +@@ -1366,7 +1372,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.9/usb-host-xhci-plat-check-hcc_params-after-add-hcd.patch b/queue-4.9/usb-host-xhci-plat-check-hcc_params-after-add-hcd.patch new file mode 100644 index 00000000000..fdaa62a041d --- /dev/null +++ b/queue-4.9/usb-host-xhci-plat-check-hcc_params-after-add-hcd.patch @@ -0,0 +1,49 @@ +From 5de4e1ea9a731cad195ce5152705c21daef3bbba Mon Sep 17 00:00:00 2001 +From: William wu +Date: Tue, 17 Jan 2017 15:32:07 +0800 +Subject: usb: host: xhci: plat: check hcc_params after add hcd + +From: William wu + +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 +Acked-by: Roger Quadros +Fixes: 4ac53087d6d4 ("usb: xhci: plat: Create both HCDs before adding them") +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -223,9 +223,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); +@@ -242,6 +239,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.9/usb-musb-da8xx-remove-cppi-3.0-quirk-and-methods.patch b/queue-4.9/usb-musb-da8xx-remove-cppi-3.0-quirk-and-methods.patch new file mode 100644 index 00000000000..1c8382a5b76 --- /dev/null +++ b/queue-4.9/usb-musb-da8xx-remove-cppi-3.0-quirk-and-methods.patch @@ -0,0 +1,44 @@ +From a994ce2d7e66008381a0b184c73be9ae9b72eb5c Mon Sep 17 00:00:00 2001 +From: Alexandre Bailon +Date: Wed, 1 Feb 2017 21:30:12 -0600 +Subject: usb: musb: da8xx: Remove CPPI 3.0 quirk and methods + +From: Alexandre Bailon + +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 +Acked-by: Sergei Shtylyov +Acked-by: Tony Lindgren +Signed-off-by: Bin Liu +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -434,15 +434,11 @@ static int da8xx_musb_exit(struct musb * + } + + 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.9/vme-restore-bus_remove-function-causing-incomplete-module-unload.patch b/queue-4.9/vme-restore-bus_remove-function-causing-incomplete-module-unload.patch new file mode 100644 index 00000000000..47ce239a4de --- /dev/null +++ b/queue-4.9/vme-restore-bus_remove-function-causing-incomplete-module-unload.patch @@ -0,0 +1,63 @@ +From 9797484ba83d68f18fe1cbd964b7cd830f78f0f7 Mon Sep 17 00:00:00 2001 +From: Stefano Babic +Date: Fri, 20 Jan 2017 10:38:20 -0500 +Subject: VME: restore bus_remove function causing incomplete module unload + +From: Stefano Babic + +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 +Acked-by: Martyn Welch +Cc: devel@driverdev.osuosl.org +Signed-off-by: Stefano Babic +Signed-off-by: Paul Gortmaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/w1-don-t-leak-refcount-on-slave-attach-failure-in-w1_attach_slave_device.patch b/queue-4.9/w1-don-t-leak-refcount-on-slave-attach-failure-in-w1_attach_slave_device.patch new file mode 100644 index 00000000000..c76998186e9 --- /dev/null +++ b/queue-4.9/w1-don-t-leak-refcount-on-slave-attach-failure-in-w1_attach_slave_device.patch @@ -0,0 +1,34 @@ +From d2ce4ea1a0b0162e5d2d7e7942ab6f5cc2063d5a Mon Sep 17 00:00:00 2001 +From: "Maciej S. Szmigiero" +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 + +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 +Fixes: 9fcbbac5ded489 ("w1: process w1 netlink commands in w1_process thread") +Cc: Evgeniy Polyakov +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/w1-ds2490-usb-transfer-buffers-need-to-be-dmaable.patch b/queue-4.9/w1-ds2490-usb-transfer-buffers-need-to-be-dmaable.patch new file mode 100644 index 00000000000..3aa58a23ab3 --- /dev/null +++ b/queue-4.9/w1-ds2490-usb-transfer-buffers-need-to-be-dmaable.patch @@ -0,0 +1,357 @@ +From 61cd1b4cd1e8f7f7642ab64529d9bd52e8374641 Mon Sep 17 00:00:00 2001 +From: "Maciej S. Szmigiero" +Date: Wed, 18 Jan 2017 21:31:11 +0100 +Subject: w1: ds2490: USB transfer buffers need to be DMAable + +From: Maciej S. Szmigiero + +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 +Acked-by: Evgeniy Polyakov +Signed-off-by: Greg Kroah-Hartman + +--- + 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; ist_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.9/xprtrdma-disable-pad-optimization-by-default.patch b/queue-4.9/xprtrdma-disable-pad-optimization-by-default.patch new file mode 100644 index 00000000000..24a23317de7 --- /dev/null +++ b/queue-4.9/xprtrdma-disable-pad-optimization-by-default.patch @@ -0,0 +1,61 @@ +From c95a3c6b88658bcb8f77f85f31a0b9d9036e8016 Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Wed, 8 Feb 2017 17:00:02 -0500 +Subject: xprtrdma: Disable pad optimization by default + +From: Chuck Lever + +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 +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/xprtrdma-fix-read-chunk-padding.patch b/queue-4.9/xprtrdma-fix-read-chunk-padding.patch new file mode 100644 index 00000000000..4ca3c36d441 --- /dev/null +++ b/queue-4.9/xprtrdma-fix-read-chunk-padding.patch @@ -0,0 +1,59 @@ +From 24abdf1be15c478e2821d6fc903a4a4440beff02 Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Wed, 8 Feb 2017 16:59:46 -0500 +Subject: xprtrdma: Fix Read chunk padding + +From: Chuck Lever + +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 +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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.9/xprtrdma-per-connection-pad-optimization.patch b/queue-4.9/xprtrdma-per-connection-pad-optimization.patch new file mode 100644 index 00000000000..898d52500e2 --- /dev/null +++ b/queue-4.9/xprtrdma-per-connection-pad-optimization.patch @@ -0,0 +1,131 @@ +From b5f0afbea4f2ea52c613ac2b06cb6de2ea18cb6d Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Wed, 8 Feb 2017 16:59:54 -0500 +Subject: xprtrdma: Per-connection pad optimization + +From: Chuck Lever + +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 +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + struct ib_qp_attr ri_qp_attr; + struct ib_qp_init_attr ri_qp_init_attr; + }; diff --git a/queue-4.9/xprtrdma-reduce-required-number-of-send-sges.patch b/queue-4.9/xprtrdma-reduce-required-number-of-send-sges.patch new file mode 100644 index 00000000000..088ad190c1e --- /dev/null +++ b/queue-4.9/xprtrdma-reduce-required-number-of-send-sges.patch @@ -0,0 +1,135 @@ +From 16f906d66cd76fb9895cbc628f447532a7ac1faa Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Wed, 8 Feb 2017 17:00:10 -0500 +Subject: xprtrdma: Reduce required number of send SGEs + +From: Chuck Lever + +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 +Reported-by: Devesh Sharma +Reported-by: Honggang Li +Reported-by: Ram Amrani +Fixes: 655fec6987be ("xprtrdma: Use gathered Send for large ...") +Tested-by: Honggang Li +Tested-by: Ram Amrani +Tested-by: Steve Wise +Reviewed-by: Parav Pandit +Signed-off-by: Chuck Lever +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -479,18 +479,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", +@@ -515,7 +516,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; + struct ib_qp_attr ri_qp_attr; +@@ -310,6 +311,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, -- 2.47.3