From: Greg Kroah-Hartman Date: Mon, 26 Jun 2017 07:00:41 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v3.18.59~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=092f5dd93d1eb816d776864839c29413d91b098e;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: brcmfmac-add-parameter-to-pass-error-code-in-firmware-callback.patch brcmfmac-unbind-all-devices-upon-failure-in-firmware-callback.patch brcmfmac-use-firmware-callback-upon-failure-to-load.patch input-i8042-add-fujitsu-lifebook-ah544-to-notimeout-list.patch powerpc-64s-handle-data-breakpoints-in-radix-mode.patch powerpc-kprobes-pause-function_graph-tracing-during-jprobes-handling.patch time-fix-clock-read-clock-race-around-clocksource-changes.patch time-fix-clock_monotonic_raw-sub-nanosecond-accounting.patch --- diff --git a/queue-4.9/brcmfmac-add-parameter-to-pass-error-code-in-firmware-callback.patch b/queue-4.9/brcmfmac-add-parameter-to-pass-error-code-in-firmware-callback.patch new file mode 100644 index 00000000000..1fd6d5e6d09 --- /dev/null +++ b/queue-4.9/brcmfmac-add-parameter-to-pass-error-code-in-firmware-callback.patch @@ -0,0 +1,180 @@ +From 6d0507a777fbc533f7f1bf5664a81982dd50dece Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Mon, 12 Jun 2017 12:47:32 +0100 +Subject: brcmfmac: add parameter to pass error code in firmware callback + +From: Arend Van Spriel + +commit 6d0507a777fbc533f7f1bf5664a81982dd50dece upstream. + +Extend the parameters in the firmware callback so it can be called +upon success and failure. This allows the caller to properly clear +all resources in the failure path. Right now the error code is +always zero, ie. success. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 10 +++---- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h | 4 +- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 17 ++++++++---- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 17 +++++++----- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 6 ++-- + 5 files changed, 34 insertions(+), 20 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -442,7 +442,7 @@ struct brcmf_fw { + const char *nvram_name; + u16 domain_nr; + u16 bus_nr; +- void (*done)(struct device *dev, const struct firmware *fw, ++ void (*done)(struct device *dev, int err, const struct firmware *fw, + void *nvram_image, u32 nvram_len); + }; + +@@ -477,7 +477,7 @@ static void brcmf_fw_request_nvram_done( + if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) + goto fail; + +- fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length); ++ fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length); + kfree(fwctx); + return; + +@@ -499,7 +499,7 @@ static void brcmf_fw_request_code_done(c + + /* only requested code so done here */ + if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) { +- fwctx->done(fwctx->dev, fw, NULL, 0); ++ fwctx->done(fwctx->dev, 0, fw, NULL, 0); + kfree(fwctx); + return; + } +@@ -522,7 +522,7 @@ fail: + + int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, + const char *code, const char *nvram, +- void (*fw_cb)(struct device *dev, ++ void (*fw_cb)(struct device *dev, int err, + const struct firmware *fw, + void *nvram_image, u32 nvram_len), + u16 domain_nr, u16 bus_nr) +@@ -555,7 +555,7 @@ int brcmf_fw_get_firmwares_pcie(struct d + + int brcmf_fw_get_firmwares(struct device *dev, u16 flags, + const char *code, const char *nvram, +- void (*fw_cb)(struct device *dev, ++ void (*fw_cb)(struct device *dev, int err, + const struct firmware *fw, + void *nvram_image, u32 nvram_len)) + { +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +@@ -73,13 +73,13 @@ void brcmf_fw_nvram_free(void *nvram); + */ + int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, + const char *code, const char *nvram, +- void (*fw_cb)(struct device *dev, ++ void (*fw_cb)(struct device *dev, int err, + const struct firmware *fw, + void *nvram_image, u32 nvram_len), + u16 domain_nr, u16 bus_nr); + int brcmf_fw_get_firmwares(struct device *dev, u16 flags, + const char *code, const char *nvram, +- void (*fw_cb)(struct device *dev, ++ void (*fw_cb)(struct device *dev, int err, + const struct firmware *fw, + void *nvram_image, u32 nvram_len)); + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -1618,16 +1618,23 @@ static const struct brcmf_buscore_ops br + .write32 = brcmf_pcie_buscore_write32, + }; + +-static void brcmf_pcie_setup(struct device *dev, const struct firmware *fw, ++static void brcmf_pcie_setup(struct device *dev, int ret, ++ const struct firmware *fw, + void *nvram, u32 nvram_len) + { +- struct brcmf_bus *bus = dev_get_drvdata(dev); +- struct brcmf_pciedev *pcie_bus_dev = bus->bus_priv.pcie; +- struct brcmf_pciedev_info *devinfo = pcie_bus_dev->devinfo; ++ struct brcmf_bus *bus; ++ struct brcmf_pciedev *pcie_bus_dev; ++ struct brcmf_pciedev_info *devinfo; + struct brcmf_commonring **flowrings; +- int ret; + u32 i; + ++ /* check firmware loading result */ ++ if (ret) ++ goto fail; ++ ++ bus = dev_get_drvdata(dev); ++ pcie_bus_dev = bus->bus_priv.pcie; ++ devinfo = pcie_bus_dev->devinfo; + brcmf_pcie_attach(devinfo); + + /* Some of the firmwares have the size of the memory of the device +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3975,21 +3975,26 @@ static const struct brcmf_bus_ops brcmf_ + .get_memdump = brcmf_sdio_bus_get_memdump, + }; + +-static void brcmf_sdio_firmware_callback(struct device *dev, ++static void brcmf_sdio_firmware_callback(struct device *dev, int err, + const struct firmware *code, + void *nvram, u32 nvram_len) + { +- struct brcmf_bus *bus_if = dev_get_drvdata(dev); +- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; +- struct brcmf_sdio *bus = sdiodev->bus; +- int err = 0; ++ struct brcmf_bus *bus_if; ++ struct brcmf_sdio_dev *sdiodev; ++ struct brcmf_sdio *bus; + u8 saveclk; + +- brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev)); ++ brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); ++ if (err) ++ goto fail; + ++ bus_if = dev_get_drvdata(dev); + if (!bus_if->drvr) + return; + ++ sdiodev = bus_if->bus_priv.sdio; ++ bus = sdiodev->bus; ++ + /* try to download image and nvram to the dongle */ + bus->alp_only = true; + err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +@@ -1158,13 +1158,15 @@ fail: + return ret; + } + +-static void brcmf_usb_probe_phase2(struct device *dev, ++static void brcmf_usb_probe_phase2(struct device *dev, int ret, + const struct firmware *fw, + void *nvram, u32 nvlen) + { + struct brcmf_bus *bus = dev_get_drvdata(dev); + struct brcmf_usbdev_info *devinfo; +- int ret; ++ ++ if (ret) ++ goto error; + + brcmf_dbg(USB, "Start fw downloading\n"); + diff --git a/queue-4.9/brcmfmac-unbind-all-devices-upon-failure-in-firmware-callback.patch b/queue-4.9/brcmfmac-unbind-all-devices-upon-failure-in-firmware-callback.patch new file mode 100644 index 00000000000..fd1357812e9 --- /dev/null +++ b/queue-4.9/brcmfmac-unbind-all-devices-upon-failure-in-firmware-callback.patch @@ -0,0 +1,54 @@ +From 7a51461fc2da82a6c565a3ee65c41c197f28225d Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Mon, 12 Jun 2017 12:47:34 +0100 +Subject: brcmfmac: unbind all devices upon failure in firmware callback + +From: Arend Van Spriel + +commit 7a51461fc2da82a6c565a3ee65c41c197f28225d upstream. + +When request firmware fails, brcmf_ops_sdio_remove is being called and +brcmf_bus freed. In such circumstancies if you do a suspend/resume cycle +the kernel hangs on resume due a NULL pointer dereference in resume +function. So in brcmf_sdio_firmware_callback() we need to unbind the +driver from both sdio_func devices when firmware load failure is indicated. + +Tested-by: Enric Balletbo i Serra +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3985,14 +3985,14 @@ static void brcmf_sdio_firmware_callback + u8 saveclk; + + brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); ++ bus_if = dev_get_drvdata(dev); ++ sdiodev = bus_if->bus_priv.sdio; + if (err) + goto fail; + +- bus_if = dev_get_drvdata(dev); + if (!bus_if->drvr) + return; + +- sdiodev = bus_if->bus_priv.sdio; + bus = sdiodev->bus; + + /* try to download image and nvram to the dongle */ +@@ -4081,6 +4081,7 @@ release: + fail: + brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err); + device_release_driver(dev); ++ device_release_driver(&sdiodev->func[2]->dev); + } + + struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) diff --git a/queue-4.9/brcmfmac-use-firmware-callback-upon-failure-to-load.patch b/queue-4.9/brcmfmac-use-firmware-callback-upon-failure-to-load.patch new file mode 100644 index 00000000000..0fcefb49491 --- /dev/null +++ b/queue-4.9/brcmfmac-use-firmware-callback-upon-failure-to-load.patch @@ -0,0 +1,81 @@ +From 03fb0e8393fae8ebb6710a99387853ed0becbc8e Mon Sep 17 00:00:00 2001 +From: Arend Van Spriel +Date: Mon, 12 Jun 2017 12:47:33 +0100 +Subject: brcmfmac: use firmware callback upon failure to load + +From: Arend Van Spriel + +commit 03fb0e8393fae8ebb6710a99387853ed0becbc8e upstream. + +When firmware loading failed the code used to unbind the device provided +by the calling code. However, for the sdio driver two devices are bound +and both need to be released upon failure. The callback has been extended +with parameter to pass error code so add that in this commit upon firmware +loading failure. + +Reviewed-by: Hante Meuleman +Reviewed-by: Pieter-Paul Giesberts +Reviewed-by: Franky Lin +Signed-off-by: Arend van Spriel +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 27 +++++------- + 1 file changed, 13 insertions(+), 14 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -484,39 +484,38 @@ static void brcmf_fw_request_nvram_done( + fail: + brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); + release_firmware(fwctx->code); +- device_release_driver(fwctx->dev); ++ fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0); + kfree(fwctx); + } + + static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx) + { + struct brcmf_fw *fwctx = ctx; +- int ret; ++ int ret = 0; + + brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev)); +- if (!fw) ++ if (!fw) { ++ ret = -ENOENT; + goto fail; +- +- /* only requested code so done here */ +- if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) { +- fwctx->done(fwctx->dev, 0, fw, NULL, 0); +- kfree(fwctx); +- return; + } ++ /* only requested code so done here */ ++ if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) ++ goto done; ++ + fwctx->code = fw; + ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name, + fwctx->dev, GFP_KERNEL, fwctx, + brcmf_fw_request_nvram_done); + +- if (!ret) +- return; +- +- brcmf_fw_request_nvram_done(NULL, fwctx); ++ /* pass NULL to nvram callback for bcm47xx fallback */ ++ if (ret) ++ brcmf_fw_request_nvram_done(NULL, fwctx); + return; + + fail: + brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); +- device_release_driver(fwctx->dev); ++done: ++ fwctx->done(fwctx->dev, ret, fw, NULL, 0); + kfree(fwctx); + } + diff --git a/queue-4.9/input-i8042-add-fujitsu-lifebook-ah544-to-notimeout-list.patch b/queue-4.9/input-i8042-add-fujitsu-lifebook-ah544-to-notimeout-list.patch new file mode 100644 index 00000000000..ad2cf46a44c --- /dev/null +++ b/queue-4.9/input-i8042-add-fujitsu-lifebook-ah544-to-notimeout-list.patch @@ -0,0 +1,40 @@ +From 817ae460c784f32cd45e60b2b1b21378c3c6a847 Mon Sep 17 00:00:00 2001 +From: Daniel Drake +Date: Mon, 19 Jun 2017 19:48:52 -0700 +Subject: Input: i8042 - add Fujitsu Lifebook AH544 to notimeout list + +From: Daniel Drake + +commit 817ae460c784f32cd45e60b2b1b21378c3c6a847 upstream. + +Without this quirk, the touchpad is not responsive on this product, with +the following message repeated in the logs: + + psmouse serio1: bad data from KBC - timeout + +Add it to the notimeout list alongside other similar Fujitsu laptops. + +Signed-off-by: Daniel Drake +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -788,6 +788,13 @@ static const struct dmi_system_id __init + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"), + }, + }, ++ { ++ /* Fujitsu UH554 laptop */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"), ++ }, ++ }, + { } + }; + diff --git a/queue-4.9/powerpc-64s-handle-data-breakpoints-in-radix-mode.patch b/queue-4.9/powerpc-64s-handle-data-breakpoints-in-radix-mode.patch new file mode 100644 index 00000000000..48ebd6ea083 --- /dev/null +++ b/queue-4.9/powerpc-64s-handle-data-breakpoints-in-radix-mode.patch @@ -0,0 +1,75 @@ +From d89ba5353f301971dd7d2f9fdf25c4432728f38e Mon Sep 17 00:00:00 2001 +From: "Naveen N. Rao" +Date: Wed, 14 Jun 2017 00:12:00 +0530 +Subject: powerpc/64s: Handle data breakpoints in Radix mode + +From: Naveen N. Rao + +commit d89ba5353f301971dd7d2f9fdf25c4432728f38e upstream. + +On Power9, trying to use data breakpoints throws the splat shown +below. This is because the check for a data breakpoint in DSISR is in +do_hash_page(), which is not called when in Radix mode. + + Unable to handle kernel paging request for data at address 0xc000000000e19218 + Faulting instruction address: 0xc0000000001155e8 + cpu 0x0: Vector: 300 (Data Access) at [c0000000ef1e7b20] + pc: c0000000001155e8: find_pid_ns+0x48/0xe0 + lr: c000000000116ac4: find_task_by_vpid+0x44/0x90 + sp: c0000000ef1e7da0 + msr: 9000000000009033 + dar: c000000000e19218 + dsisr: 400000 + +Move the check to handle_page_fault() so as to catch data breakpoints +in both Hash and Radix MMU modes. + +We have to change the check in do_hash_page() against 0xa410 to use +0xa450, so as to include the value of (DSISR_DABRMATCH << 16). + +There are two sites that call handle_page_fault() when in Radix, both +already pass DSISR in r4. + +Fixes: caca285e5ab4 ("powerpc/mm/radix: Use STD_MMU_64 to properly isolate hash related code") +Reported-by: Shriya R. Kulkarni +Signed-off-by: Naveen N. Rao +[mpe: Fix the fall-through case on hash, we need to reload DSISR] +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/exceptions-64s.S | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -1411,10 +1411,8 @@ USE_TEXT_SECTION() + .align 7 + do_hash_page: + #ifdef CONFIG_PPC_STD_MMU_64 +- andis. r0,r4,0xa410 /* weird error? */ ++ andis. r0,r4,0xa450 /* weird error? */ + bne- handle_page_fault /* if not, try to insert a HPTE */ +- andis. r0,r4,DSISR_DABRMATCH@h +- bne- handle_dabr_fault + CURRENT_THREAD_INFO(r11, r1) + lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */ + andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */ +@@ -1438,11 +1436,16 @@ do_hash_page: + + /* Error */ + blt- 13f ++ ++ /* Reload DSISR into r4 for the DABR check below */ ++ ld r4,_DSISR(r1) + #endif /* CONFIG_PPC_STD_MMU_64 */ + + /* Here we have a page fault that hash_page can't handle. */ + handle_page_fault: +-11: ld r4,_DAR(r1) ++11: andis. r0,r4,DSISR_DABRMATCH@h ++ bne- handle_dabr_fault ++ ld r4,_DAR(r1) + ld r5,_DSISR(r1) + addi r3,r1,STACK_FRAME_OVERHEAD + bl do_page_fault diff --git a/queue-4.9/powerpc-kprobes-pause-function_graph-tracing-during-jprobes-handling.patch b/queue-4.9/powerpc-kprobes-pause-function_graph-tracing-during-jprobes-handling.patch new file mode 100644 index 00000000000..8e71bc5c1ad --- /dev/null +++ b/queue-4.9/powerpc-kprobes-pause-function_graph-tracing-during-jprobes-handling.patch @@ -0,0 +1,57 @@ +From a9f8553e935f26cb5447f67e280946b0923cd2dc Mon Sep 17 00:00:00 2001 +From: "Naveen N. Rao" +Date: Thu, 1 Jun 2017 16:18:15 +0530 +Subject: powerpc/kprobes: Pause function_graph tracing during jprobes handling + +From: Naveen N. Rao + +commit a9f8553e935f26cb5447f67e280946b0923cd2dc upstream. + +This fixes a crash when function_graph and jprobes are used together. +This is essentially commit 237d28db036e ("ftrace/jprobes/x86: Fix +conflict between jprobes and function graph tracing"), but for powerpc. + +Jprobes breaks function_graph tracing since the jprobe hook needs to use +jprobe_return(), which never returns back to the hook, but instead to +the original jprobe'd function. The solution is to momentarily pause +function_graph tracing before invoking the jprobe hook and re-enable it +when returning back to the original jprobe'd function. + +Fixes: 6794c78243bf ("powerpc64: port of the function graph tracer") +Signed-off-by: Naveen N. Rao +Acked-by: Masami Hiramatsu +Acked-by: Steven Rostedt (VMware) +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/kprobes.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/powerpc/kernel/kprobes.c ++++ b/arch/powerpc/kernel/kprobes.c +@@ -511,6 +511,15 @@ int __kprobes setjmp_pre_handler(struct + regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc); + #endif + ++ /* ++ * jprobes use jprobe_return() which skips the normal return ++ * path of the function, and this messes up the accounting of the ++ * function graph tracer. ++ * ++ * Pause function graph tracing while performing the jprobe function. ++ */ ++ pause_graph_tracing(); ++ + return 1; + } + +@@ -533,6 +542,8 @@ int __kprobes longjmp_break_handler(stru + * saved regs... + */ + memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); ++ /* It's OK to start function graph tracing again */ ++ unpause_graph_tracing(); + preempt_enable_no_resched(); + return 1; + } diff --git a/queue-4.9/series b/queue-4.9/series index d9239fbfba6..85391e9f725 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -16,3 +16,11 @@ cifs-improve-readdir-verbosity.patch cxgb4-notify-up-to-route-ctrlq-compl-to-rdma-rspq.patch hid-add-quirk-for-dell-pixart-oem-mouse.patch signal-only-reschedule-timers-on-signals-timers-have-sent.patch +powerpc-kprobes-pause-function_graph-tracing-during-jprobes-handling.patch +powerpc-64s-handle-data-breakpoints-in-radix-mode.patch +input-i8042-add-fujitsu-lifebook-ah544-to-notimeout-list.patch +brcmfmac-add-parameter-to-pass-error-code-in-firmware-callback.patch +brcmfmac-use-firmware-callback-upon-failure-to-load.patch +brcmfmac-unbind-all-devices-upon-failure-in-firmware-callback.patch +time-fix-clock-read-clock-race-around-clocksource-changes.patch +time-fix-clock_monotonic_raw-sub-nanosecond-accounting.patch diff --git a/queue-4.9/time-fix-clock-read-clock-race-around-clocksource-changes.patch b/queue-4.9/time-fix-clock-read-clock-race-around-clocksource-changes.patch new file mode 100644 index 00000000000..d7e22e34d5f --- /dev/null +++ b/queue-4.9/time-fix-clock-read-clock-race-around-clocksource-changes.patch @@ -0,0 +1,225 @@ +From ceea5e3771ed2378668455fa21861bead7504df5 Mon Sep 17 00:00:00 2001 +From: John Stultz +Date: Thu, 8 Jun 2017 16:44:20 -0700 +Subject: time: Fix clock->read(clock) race around clocksource changes + +From: John Stultz + +commit ceea5e3771ed2378668455fa21861bead7504df5 upstream. + +In tests, which excercise switching of clocksources, a NULL +pointer dereference can be observed on AMR64 platforms in the +clocksource read() function: + +u64 clocksource_mmio_readl_down(struct clocksource *c) +{ + return ~(u64)readl_relaxed(to_mmio_clksrc(c)->reg) & c->mask; +} + +This is called from the core timekeeping code via: + + cycle_now = tkr->read(tkr->clock); + +tkr->read is the cached tkr->clock->read() function pointer. +When the clocksource is changed then tkr->clock and tkr->read +are updated sequentially. The code above results in a sequential +load operation of tkr->read and tkr->clock as well. + +If the store to tkr->clock hits between the loads of tkr->read +and tkr->clock, then the old read() function is called with the +new clock pointer. As a consequence the read() function +dereferences a different data structure and the resulting 'reg' +pointer can point anywhere including NULL. + +This problem was introduced when the timekeeping code was +switched over to use struct tk_read_base. Before that, it was +theoretically possible as well when the compiler decided to +reload clock in the code sequence: + + now = tk->clock->read(tk->clock); + +Add a helper function which avoids the issue by reading +tk_read_base->clock once into a local variable clk and then issue +the read function via clk->read(clk). This guarantees that the +read() function always gets the proper clocksource pointer handed +in. + +Since there is now no use for the tkr.read pointer, this patch +also removes it, and to address stopping the fast timekeeper +during suspend/resume, it introduces a dummy clocksource to use +rather then just a dummy read function. + +Signed-off-by: John Stultz +Acked-by: Ingo Molnar +Cc: Prarit Bhargava +Cc: Richard Cochran +Cc: Stephen Boyd +Cc: Miroslav Lichvar +Cc: Daniel Mentz +Link: http://lkml.kernel.org/r/1496965462-20003-2-git-send-email-john.stultz@linaro.org +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/timekeeper_internal.h | 1 + kernel/time/timekeeping.c | 52 ++++++++++++++++++++++++------------ + 2 files changed, 36 insertions(+), 17 deletions(-) + +--- a/include/linux/timekeeper_internal.h ++++ b/include/linux/timekeeper_internal.h +@@ -29,7 +29,6 @@ + */ + struct tk_read_base { + struct clocksource *clock; +- cycle_t (*read)(struct clocksource *cs); + cycle_t mask; + cycle_t cycle_last; + u32 mult; +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -116,6 +116,26 @@ static inline void tk_update_sleep_time( + tk->offs_boot = ktime_add(tk->offs_boot, delta); + } + ++/* ++ * tk_clock_read - atomic clocksource read() helper ++ * ++ * This helper is necessary to use in the read paths because, while the ++ * seqlock ensures we don't return a bad value while structures are updated, ++ * it doesn't protect from potential crashes. There is the possibility that ++ * the tkr's clocksource may change between the read reference, and the ++ * clock reference passed to the read function. This can cause crashes if ++ * the wrong clocksource is passed to the wrong read function. ++ * This isn't necessary to use when holding the timekeeper_lock or doing ++ * a read of the fast-timekeeper tkrs (which is protected by its own locking ++ * and update logic). ++ */ ++static inline u64 tk_clock_read(struct tk_read_base *tkr) ++{ ++ struct clocksource *clock = READ_ONCE(tkr->clock); ++ ++ return clock->read(clock); ++} ++ + #ifdef CONFIG_DEBUG_TIMEKEEPING + #define WARNING_FREQ (HZ*300) /* 5 minute rate-limiting */ + +@@ -173,7 +193,7 @@ static inline cycle_t timekeeping_get_de + */ + do { + seq = read_seqcount_begin(&tk_core.seq); +- now = tkr->read(tkr->clock); ++ now = tk_clock_read(tkr); + last = tkr->cycle_last; + mask = tkr->mask; + max = tkr->clock->max_cycles; +@@ -207,7 +227,7 @@ static inline cycle_t timekeeping_get_de + cycle_t cycle_now, delta; + + /* read clocksource */ +- cycle_now = tkr->read(tkr->clock); ++ cycle_now = tk_clock_read(tkr); + + /* calculate the delta since the last update_wall_time */ + delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask); +@@ -236,12 +256,10 @@ static void tk_setup_internals(struct ti + ++tk->cs_was_changed_seq; + old_clock = tk->tkr_mono.clock; + tk->tkr_mono.clock = clock; +- tk->tkr_mono.read = clock->read; + tk->tkr_mono.mask = clock->mask; +- tk->tkr_mono.cycle_last = tk->tkr_mono.read(clock); ++ tk->tkr_mono.cycle_last = tk_clock_read(&tk->tkr_mono); + + tk->tkr_raw.clock = clock; +- tk->tkr_raw.read = clock->read; + tk->tkr_raw.mask = clock->mask; + tk->tkr_raw.cycle_last = tk->tkr_mono.cycle_last; + +@@ -405,7 +423,7 @@ static __always_inline u64 __ktime_get_f + + now += timekeeping_delta_to_ns(tkr, + clocksource_delta( +- tkr->read(tkr->clock), ++ tk_clock_read(tkr), + tkr->cycle_last, + tkr->mask)); + } while (read_seqcount_retry(&tkf->seq, seq)); +@@ -433,6 +451,10 @@ static cycle_t dummy_clock_read(struct c + return cycles_at_suspend; + } + ++static struct clocksource dummy_clock = { ++ .read = dummy_clock_read, ++}; ++ + /** + * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource. + * @tk: Timekeeper to snapshot. +@@ -449,13 +471,13 @@ static void halt_fast_timekeeper(struct + struct tk_read_base *tkr = &tk->tkr_mono; + + memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy)); +- cycles_at_suspend = tkr->read(tkr->clock); +- tkr_dummy.read = dummy_clock_read; ++ cycles_at_suspend = tk_clock_read(tkr); ++ tkr_dummy.clock = &dummy_clock; + update_fast_timekeeper(&tkr_dummy, &tk_fast_mono); + + tkr = &tk->tkr_raw; + memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy)); +- tkr_dummy.read = dummy_clock_read; ++ tkr_dummy.clock = &dummy_clock; + update_fast_timekeeper(&tkr_dummy, &tk_fast_raw); + } + +@@ -621,11 +643,10 @@ static void timekeeping_update(struct ti + */ + static void timekeeping_forward_now(struct timekeeper *tk) + { +- struct clocksource *clock = tk->tkr_mono.clock; + cycle_t cycle_now, delta; + s64 nsec; + +- cycle_now = tk->tkr_mono.read(clock); ++ cycle_now = tk_clock_read(&tk->tkr_mono); + delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask); + tk->tkr_mono.cycle_last = cycle_now; + tk->tkr_raw.cycle_last = cycle_now; +@@ -901,8 +922,7 @@ void ktime_get_snapshot(struct system_ti + + do { + seq = read_seqcount_begin(&tk_core.seq); +- +- now = tk->tkr_mono.read(tk->tkr_mono.clock); ++ now = tk_clock_read(&tk->tkr_mono); + systime_snapshot->cs_was_changed_seq = tk->cs_was_changed_seq; + systime_snapshot->clock_was_set_seq = tk->clock_was_set_seq; + base_real = ktime_add(tk->tkr_mono.base, +@@ -1081,7 +1101,7 @@ int get_device_system_crosststamp(int (* + * Check whether the system counter value provided by the + * device driver is on the current timekeeping interval. + */ +- now = tk->tkr_mono.read(tk->tkr_mono.clock); ++ now = tk_clock_read(&tk->tkr_mono); + interval_start = tk->tkr_mono.cycle_last; + if (!cycle_between(interval_start, cycles, now)) { + clock_was_set_seq = tk->clock_was_set_seq; +@@ -1639,7 +1659,7 @@ void timekeeping_resume(void) + * The less preferred source will only be tried if there is no better + * usable source. The rtc part is handled separately in rtc core code. + */ +- cycle_now = tk->tkr_mono.read(clock); ++ cycle_now = tk_clock_read(&tk->tkr_mono); + if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) && + cycle_now > tk->tkr_mono.cycle_last) { + u64 num, max = ULLONG_MAX; +@@ -2057,7 +2077,7 @@ void update_wall_time(void) + #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET + offset = real_tk->cycle_interval; + #else +- offset = clocksource_delta(tk->tkr_mono.read(tk->tkr_mono.clock), ++ offset = clocksource_delta(tk_clock_read(&tk->tkr_mono), + tk->tkr_mono.cycle_last, tk->tkr_mono.mask); + #endif + diff --git a/queue-4.9/time-fix-clock_monotonic_raw-sub-nanosecond-accounting.patch b/queue-4.9/time-fix-clock_monotonic_raw-sub-nanosecond-accounting.patch new file mode 100644 index 00000000000..e299771cdf3 --- /dev/null +++ b/queue-4.9/time-fix-clock_monotonic_raw-sub-nanosecond-accounting.patch @@ -0,0 +1,107 @@ +From 3d88d56c5873f6eebe23e05c3da701960146b801 Mon Sep 17 00:00:00 2001 +From: John Stultz +Date: Thu, 8 Jun 2017 16:44:21 -0700 +Subject: time: Fix CLOCK_MONOTONIC_RAW sub-nanosecond accounting + +From: John Stultz + +commit 3d88d56c5873f6eebe23e05c3da701960146b801 upstream. + +Due to how the MONOTONIC_RAW accumulation logic was handled, +there is the potential for a 1ns discontinuity when we do +accumulations. This small discontinuity has for the most part +gone un-noticed, but since ARM64 enabled CLOCK_MONOTONIC_RAW +in their vDSO clock_gettime implementation, we've seen failures +with the inconsistency-check test in kselftest. + +This patch addresses the issue by using the same sub-ns +accumulation handling that CLOCK_MONOTONIC uses, which avoids +the issue for in-kernel users. + +Since the ARM64 vDSO implementation has its own clock_gettime +calculation logic, this patch reduces the frequency of errors, +but failures are still seen. The ARM64 vDSO will need to be +updated to include the sub-nanosecond xtime_nsec values in its +calculation for this issue to be completely fixed. + +Signed-off-by: John Stultz +Tested-by: Daniel Mentz +Cc: Prarit Bhargava +Cc: Kevin Brodsky +Cc: Richard Cochran +Cc: Stephen Boyd +Cc: Will Deacon +Cc: Miroslav Lichvar +Link: http://lkml.kernel.org/r/1496965462-20003-3-git-send-email-john.stultz@linaro.org +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/timekeeper_internal.h | 4 ++-- + kernel/time/timekeeping.c | 20 ++++++++++---------- + 2 files changed, 12 insertions(+), 12 deletions(-) + +--- a/include/linux/timekeeper_internal.h ++++ b/include/linux/timekeeper_internal.h +@@ -57,7 +57,7 @@ struct tk_read_base { + * interval. + * @xtime_remainder: Shifted nano seconds left over when rounding + * @cycle_interval +- * @raw_interval: Raw nano seconds accumulated per NTP interval. ++ * @raw_interval: Shifted raw nano seconds accumulated per NTP interval. + * @ntp_error: Difference between accumulated time and NTP time in ntp + * shifted nano seconds. + * @ntp_error_shift: Shift conversion between clock shifted nano seconds and +@@ -99,7 +99,7 @@ struct timekeeper { + cycle_t cycle_interval; + u64 xtime_interval; + s64 xtime_remainder; +- u32 raw_interval; ++ u64 raw_interval; + /* The ntp_tick_length() value currently being used. + * This cached copy ensures we consistently apply the tick + * length for an entire tick, as ntp_tick_length may change +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -278,8 +278,7 @@ static void tk_setup_internals(struct ti + /* Go back from cycles -> shifted ns */ + tk->xtime_interval = (u64) interval * clock->mult; + tk->xtime_remainder = ntpinterval - tk->xtime_interval; +- tk->raw_interval = +- ((u64) interval * clock->mult) >> clock->shift; ++ tk->raw_interval = interval * clock->mult; + + /* if changing clocks, convert xtime_nsec shift units */ + if (old_clock) { +@@ -2023,7 +2022,7 @@ static cycle_t logarithmic_accumulation( + unsigned int *clock_set) + { + cycle_t interval = tk->cycle_interval << shift; +- u64 raw_nsecs; ++ u64 snsec_per_sec; + + /* If the offset is smaller than a shifted interval, do nothing */ + if (offset < interval) +@@ -2038,14 +2037,15 @@ static cycle_t logarithmic_accumulation( + *clock_set |= accumulate_nsecs_to_secs(tk); + + /* Accumulate raw time */ +- raw_nsecs = (u64)tk->raw_interval << shift; +- raw_nsecs += tk->raw_time.tv_nsec; +- if (raw_nsecs >= NSEC_PER_SEC) { +- u64 raw_secs = raw_nsecs; +- raw_nsecs = do_div(raw_secs, NSEC_PER_SEC); +- tk->raw_time.tv_sec += raw_secs; ++ tk->tkr_raw.xtime_nsec += (u64)tk->raw_time.tv_nsec << tk->tkr_raw.shift; ++ tk->tkr_raw.xtime_nsec += tk->raw_interval << shift; ++ snsec_per_sec = (u64)NSEC_PER_SEC << tk->tkr_raw.shift; ++ while (tk->tkr_raw.xtime_nsec >= snsec_per_sec) { ++ tk->tkr_raw.xtime_nsec -= snsec_per_sec; ++ tk->raw_time.tv_sec++; + } +- tk->raw_time.tv_nsec = raw_nsecs; ++ tk->raw_time.tv_nsec = tk->tkr_raw.xtime_nsec >> tk->tkr_raw.shift; ++ tk->tkr_raw.xtime_nsec -= (u64)tk->raw_time.tv_nsec << tk->tkr_raw.shift; + + /* Accumulate error between NTP and clock interval */ + tk->ntp_error += tk->ntp_tick << shift;