Cross-merge bpf fixes after downstream PR (bpf-6.14-rc4). Minor conflict: kernel/bpf/btf.c Adjacent changes: kernel/bpf/arena.c kernel/bpf/btf.c kernel/bpf/syscall.c kernel/bpf/verifier.c mm/memory.c
Unified · Split
| @@ -226,6 +226,7 @@ Fangrui Song <i@maskray.me> <maskray@google.com> · 225 unmodified lines | |||
| 226 | Felipe W Damasio <felipewd@terra.com.br> | 226 | Felipe W Damasio <felipewd@terra.com.br> |
| 227 | Felix Kuhling <fxkuehl@gmx.de> | 227 | Felix Kuhling <fxkuehl@gmx.de> |
| 228 | Felix Moeller <felix@derklecks.de> | 228 | Felix Moeller <felix@derklecks.de> |
| 229 | Feng Tang <feng.79.tang@gmail.com> <feng.tang@intel.com> | ||
| 229 | Fenglin Wu <quic_fenglinw@quicinc.com> <fenglinw@codeaurora.org> | 230 | Fenglin Wu <quic_fenglinw@quicinc.com> <fenglinw@codeaurora.org> |
| 230 | Filipe Lautert <filipe@icewall.org> | 231 | Filipe Lautert <filipe@icewall.org> |
| 231 | Finn Thain <fthain@linux-m68k.org> <fthain@telegraphics.com.au> | 232 | Finn Thain <fthain@linux-m68k.org> <fthain@telegraphics.com.au> |
| @@ -317,6 +318,8 @@ Jayachandran C <c.jayachandran@gmail.com> <jnair@caviumnetworks.com> · 85 unmodified lines | |||
| 317 | Jean Tourrilhes <jt@hpl.hp.com> | 318 | Jean Tourrilhes <jt@hpl.hp.com> |
| 318 | Jeevan Shriram <quic_jshriram@quicinc.com> <jshriram@codeaurora.org> | 319 | Jeevan Shriram <quic_jshriram@quicinc.com> <jshriram@codeaurora.org> |
| 319 | Jeff Garzik <jgarzik@pretzel.yyz.us> | 320 | Jeff Garzik <jgarzik@pretzel.yyz.us> |
| 321 | Jeff Johnson <jeff.johnson@oss.qualcomm.com> <jjohnson@codeaurora.org> | ||
| 322 | Jeff Johnson <jeff.johnson@oss.qualcomm.com> <quic_jjohnson@quicinc.com> | ||
| 320 | Jeff Layton <jlayton@kernel.org> <jlayton@poochiereds.net> | 323 | Jeff Layton <jlayton@kernel.org> <jlayton@poochiereds.net> |
| 321 | Jeff Layton <jlayton@kernel.org> <jlayton@primarydata.com> | 324 | Jeff Layton <jlayton@kernel.org> <jlayton@primarydata.com> |
| 322 | Jeff Layton <jlayton@kernel.org> <jlayton@redhat.com> | 325 | Jeff Layton <jlayton@kernel.org> <jlayton@redhat.com> |
| @@ -376,6 +379,7 @@ Juha Yrjola <juha.yrjola@solidboot.com> · 53 unmodified lines | |||
| 376 | Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com> | 379 | Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com> |
| 377 | Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com> | 380 | Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com> |
| 378 | Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org> | 381 | Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org> |
| 382 | Kalle Valo <kvalo@kernel.org> <quic_kvalo@quicinc.com> | ||
| 379 | Kalyan Thota <quic_kalyant@quicinc.com> <kalyan_t@codeaurora.org> | 383 | Kalyan Thota <quic_kalyant@quicinc.com> <kalyan_t@codeaurora.org> |
| 380 | Karthikeyan Periyasamy <quic_periyasa@quicinc.com> <periyasa@codeaurora.org> | 384 | Karthikeyan Periyasamy <quic_periyasa@quicinc.com> <periyasa@codeaurora.org> |
| 381 | Kathiravan T <quic_kathirav@quicinc.com> <kathirav@codeaurora.org> | 385 | Kathiravan T <quic_kathirav@quicinc.com> <kathirav@codeaurora.org> |
| @@ -530,6 +534,7 @@ Nicholas Piggin <npiggin@gmail.com> <npiggin@kernel.dk> · 148 unmodified lines | |||
| 530 | Nicholas Piggin <npiggin@gmail.com> <npiggin@suse.de> | 534 | Nicholas Piggin <npiggin@gmail.com> <npiggin@suse.de> |
| 531 | Nicholas Piggin <npiggin@gmail.com> <nickpiggin@yahoo.com.au> | 535 | Nicholas Piggin <npiggin@gmail.com> <nickpiggin@yahoo.com.au> |
| 532 | Nicholas Piggin <npiggin@gmail.com> <piggin@cyberone.com.au> | 536 | Nicholas Piggin <npiggin@gmail.com> <piggin@cyberone.com.au> |
| 537 | Nick Desaulniers <nick.desaulniers+lkml@gmail.com> <ndesaulniers@google.com> | ||
| 533 | Nicolas Ferre <nicolas.ferre@microchip.com> <nicolas.ferre@atmel.com> | 538 | Nicolas Ferre <nicolas.ferre@microchip.com> <nicolas.ferre@atmel.com> |
| 534 | Nicolas Pitre <nico@fluxnic.net> <nicolas.pitre@linaro.org> | 539 | Nicolas Pitre <nico@fluxnic.net> <nicolas.pitre@linaro.org> |
| 535 | Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org> | 540 | Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org> |
| @@ -2515,11 +2515,9 @@ D: SLS distribution · 2514 unmodified lines | |||
| 2515 | D: Initial implementation of VC's, pty's and select() | 2515 | D: Initial implementation of VC's, pty's and select() |
| 2516 | 2516 | ||
| 2517 | N: Pavel Machek | 2517 | N: Pavel Machek |
| 2518 | E: pavel@ucw.cz | 2518 | E: pavel@kernel.org |
| 2519 | P: 4096R/92DFCE96 4FA7 9EEF FCD4 C44F C585 B8C7 C060 2241 92DF CE96 | 2519 | P: 4096R/92DFCE96 4FA7 9EEF FCD4 C44F C585 B8C7 C060 2241 92DF CE96 |
| 2520 | D: Softcursor for vga, hypertech cdrom support, vcsa bugfix, nbd, | 2520 | D: NBD, Sun4/330 port, USB, work on suspend-to-ram/disk, |
| 2521 | D: sun4/330 port, capabilities for elf, speedup for rm on ext2, USB, | ||
| 2522 | D: work on suspend-to-ram/disk, killing duplicates from ioctl32, | ||
| 2523 | D: Altera SoCFPGA and Nokia N900 support. | 2521 | D: Altera SoCFPGA and Nokia N900 support. |
| 2524 | S: Czech Republic | 2522 | S: Czech Republic |
| 2525 | 2523 | ||
| @@ -37,7 +37,7 @@ intended to be exhaustive. · 36 unmodified lines | |||
| 37 | shadow stacks rather than GCS. | 37 | shadow stacks rather than GCS. |
| 38 | 38 | ||
| 39 | * Support for GCS is reported to userspace via HWCAP_GCS in the aux vector | 39 | * Support for GCS is reported to userspace via HWCAP_GCS in the aux vector |
| 40 | AT_HWCAP2 entry. | 40 | AT_HWCAP entry. |
| 41 | 41 | ||
| 42 | * GCS is enabled per thread. While there is support for disabling GCS | 42 | * GCS is enabled per thread. While there is support for disabling GCS |
| 43 | at runtime this should be done with great care. | 43 | at runtime this should be done with great care. |
| @@ -8,6 +8,7 @@ title: Qualcomm Graphics Clock & Reset Controller · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Taniya Das <quic_tdas@quicinc.com> | 10 | - Taniya Das <quic_tdas@quicinc.com> |
| 11 | - Imran Shaik <quic_imrashai@quicinc.com> | ||
| 11 | 12 | ||
| 12 | description: | | 13 | description: | |
| 13 | Qualcomm graphics clock control module provides the clocks, resets and power | 14 | Qualcomm graphics clock control module provides the clocks, resets and power |
| @@ -23,10 +24,12 @@ description: | · 9 unmodified lines | |||
| 23 | include/dt-bindings/clock/qcom,gpucc-sm8150.h | 24 | include/dt-bindings/clock/qcom,gpucc-sm8150.h |
| 24 | include/dt-bindings/clock/qcom,gpucc-sm8250.h | 25 | include/dt-bindings/clock/qcom,gpucc-sm8250.h |
| 25 | include/dt-bindings/clock/qcom,gpucc-sm8350.h | 26 | include/dt-bindings/clock/qcom,gpucc-sm8350.h |
| 27 | include/dt-bindings/clock/qcom,qcs8300-gpucc.h | ||
| 26 | 28 | ||
| 27 | properties: | 29 | properties: |
| 28 | compatible: | 30 | compatible: |
| 29 | enum: | 31 | enum: |
| 32 | - qcom,qcs8300-gpucc | ||
| 30 | - qcom,sdm845-gpucc | 33 | - qcom,sdm845-gpucc |
| 31 | - qcom,sa8775p-gpucc | 34 | - qcom,sa8775p-gpucc |
| 32 | - qcom,sc7180-gpucc | 35 | - qcom,sc7180-gpucc |
| @@ -8,16 +8,20 @@ title: Qualcomm Camera Clock & Reset Controller on SA8775P · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Taniya Das <quic_tdas@quicinc.com> | 10 | - Taniya Das <quic_tdas@quicinc.com> |
| 11 | - Imran Shaik <quic_imrashai@quicinc.com> | ||
| 11 | 12 | ||
| 12 | description: | | 13 | description: | |
| 13 | Qualcomm camera clock control module provides the clocks, resets and power | 14 | Qualcomm camera clock control module provides the clocks, resets and power |
| 14 | domains on SA8775p. | 15 | domains on SA8775p. |
| 15 | 16 | ||
| 16 | See also: include/dt-bindings/clock/qcom,sa8775p-camcc.h | 17 | See also: |
| 18 | include/dt-bindings/clock/qcom,qcs8300-camcc.h | ||
| 19 | include/dt-bindings/clock/qcom,sa8775p-camcc.h | ||
| 17 | 20 | ||
| 18 | properties: | 21 | properties: |
| 19 | compatible: | 22 | compatible: |
| 20 | enum: | 23 | enum: |
| 24 | - qcom,qcs8300-camcc | ||
| 21 | - qcom,sa8775p-camcc | 25 | - qcom,sa8775p-camcc |
| 22 | 26 | ||
| 23 | clocks: | 27 | clocks: |
| @@ -18,6 +18,7 @@ description: | · 17 unmodified lines | |||
| 18 | properties: | 18 | properties: |
| 19 | compatible: | 19 | compatible: |
| 20 | enum: | 20 | enum: |
| 21 | - qcom,qcs8300-videocc | ||
| 21 | - qcom,sa8775p-videocc | 22 | - qcom,sa8775p-videocc |
| 22 | 23 | ||
| 23 | clocks: | 24 | clocks: |
| @@ -0,0 +1,29 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/display/panel/powertip,hx8238a.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Powertip Electronic Technology Co. 320 x 240 LCD panel | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Lukasz Majewski <lukma@denx.de> | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: panel-dpi.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | items: | ||
| 18 | - const: powertip,hx8238a | ||
| 19 | - {} # panel-dpi, but not listed here to avoid false select | ||
| 20 | |||
| 21 | height-mm: true | ||
| 22 | panel-timing: true | ||
| 23 | port: true | ||
| 24 | power-supply: true | ||
| 25 | width-mm: true | ||
| 26 | |||
| 27 | additionalProperties: false | ||
| 28 | |||
| 29 | ... | ||
| @@ -0,0 +1,29 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause | ||
| 2 | %YAML 1.2 | ||
| 3 | --- | ||
| 4 | $id: http://devicetree.org/schemas/display/panel/powertip,st7272.yaml# | ||
| 5 | $schema: http://devicetree.org/meta-schemas/core.yaml# | ||
| 6 | |||
| 7 | title: Powertip Electronic Technology Co. 320 x 240 LCD panel | ||
| 8 | |||
| 9 | maintainers: | ||
| 10 | - Lukasz Majewski <lukma@denx.de> | ||
| 11 | |||
| 12 | allOf: | ||
| 13 | - $ref: panel-dpi.yaml# | ||
| 14 | |||
| 15 | properties: | ||
| 16 | compatible: | ||
| 17 | items: | ||
| 18 | - const: powertip,st7272 | ||
| 19 | - {} # panel-dpi, but not listed here to avoid false select | ||
| 20 | |||
| 21 | height-mm: true | ||
| 22 | panel-timing: true | ||
| 23 | port: true | ||
| 24 | power-supply: true | ||
| 25 | width-mm: true | ||
| 26 | |||
| 27 | additionalProperties: false | ||
| 28 | |||
| 29 | ... | ||
| @@ -23,7 +23,7 @@ properties: · 22 unmodified lines | |||
| 23 | compatible: | 23 | compatible: |
| 24 | enum: | 24 | enum: |
| 25 | - ti,am625-dss | 25 | - ti,am625-dss |
| 26 | - ti,am62a7,dss | 26 | - ti,am62a7-dss |
| 27 | - ti,am65x-dss | 27 | - ti,am65x-dss |
| 28 | 28 | ||
| 29 | reg: | 29 | reg: |
| @@ -14,9 +14,8 @@ allOf: · 13 unmodified lines | |||
| 14 | 14 | ||
| 15 | description: | | 15 | description: | |
| 16 | The Microchip LAN966x outband interrupt controller (OIC) maps the internal | 16 | The Microchip LAN966x outband interrupt controller (OIC) maps the internal |
| 17 | interrupt sources of the LAN966x device to an external interrupt. | 17 | interrupt sources of the LAN966x device to a PCI interrupt when the LAN966x |
| 18 | When the LAN966x device is used as a PCI device, the external interrupt is | 18 | device is used as a PCI device. |
| 19 | routed to the PCI interrupt. | ||
| 20 | 19 | ||
| 21 | properties: | 20 | properties: |
| 22 | compatible: | 21 | compatible: |
| @@ -7,7 +7,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | |||
| 7 | title: Qualcomm Technologies ath10k wireless devices | 7 | title: Qualcomm Technologies ath10k wireless devices |
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Kalle Valo <kvalo@kernel.org> | ||
| 11 | - Jeff Johnson <jjohnson@kernel.org> | 10 | - Jeff Johnson <jjohnson@kernel.org> |
| 12 | 11 | ||
| 13 | description: | 12 | description: |
| @@ -8,7 +8,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 7 unmodified lines | |||
| 8 | title: Qualcomm Technologies ath11k wireless devices (PCIe) | 8 | title: Qualcomm Technologies ath11k wireless devices (PCIe) |
| 9 | 9 | ||
| 10 | maintainers: | 10 | maintainers: |
| 11 | - Kalle Valo <kvalo@kernel.org> | ||
| 12 | - Jeff Johnson <jjohnson@kernel.org> | 11 | - Jeff Johnson <jjohnson@kernel.org> |
| 13 | 12 | ||
| 14 | description: | | 13 | description: | |
| @@ -8,7 +8,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 7 unmodified lines | |||
| 8 | title: Qualcomm Technologies ath11k wireless devices | 8 | title: Qualcomm Technologies ath11k wireless devices |
| 9 | 9 | ||
| 10 | maintainers: | 10 | maintainers: |
| 11 | - Kalle Valo <kvalo@kernel.org> | ||
| 12 | - Jeff Johnson <jjohnson@kernel.org> | 11 | - Jeff Johnson <jjohnson@kernel.org> |
| 13 | 12 | ||
| 14 | description: | | 13 | description: | |
| @@ -9,7 +9,6 @@ title: Qualcomm Technologies ath12k wireless devices (PCIe) with WSI interface · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | maintainers: | 10 | maintainers: |
| 11 | - Jeff Johnson <jjohnson@kernel.org> | 11 | - Jeff Johnson <jjohnson@kernel.org> |
| 12 | - Kalle Valo <kvalo@kernel.org> | ||
| 13 | 12 | ||
| 14 | description: | | 13 | description: | |
| 15 | Qualcomm Technologies IEEE 802.11be PCIe devices with WSI interface. | 14 | Qualcomm Technologies IEEE 802.11be PCIe devices with WSI interface. |
| @@ -9,7 +9,6 @@ title: Qualcomm Technologies ath12k wireless devices (PCIe) · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | maintainers: | 10 | maintainers: |
| 11 | - Jeff Johnson <quic_jjohnson@quicinc.com> | 11 | - Jeff Johnson <quic_jjohnson@quicinc.com> |
| 12 | - Kalle Valo <kvalo@kernel.org> | ||
| 13 | 12 | ||
| 14 | description: | 13 | description: |
| 15 | Qualcomm Technologies IEEE 802.11be PCIe devices. | 14 | Qualcomm Technologies IEEE 802.11be PCIe devices. |
| @@ -36,6 +36,7 @@ properties: · 35 unmodified lines | |||
| 36 | - qcom,qcs404-qfprom | 36 | - qcom,qcs404-qfprom |
| 37 | - qcom,qcs615-qfprom | 37 | - qcom,qcs615-qfprom |
| 38 | - qcom,qcs8300-qfprom | 38 | - qcom,qcs8300-qfprom |
| 39 | - qcom,sar2130p-qfprom | ||
| 39 | - qcom,sc7180-qfprom | 40 | - qcom,sc7180-qfprom |
| 40 | - qcom,sc7280-qfprom | 41 | - qcom,sc7280-qfprom |
| 41 | - qcom,sc8280xp-qfprom | 42 | - qcom,sc8280xp-qfprom |
| @@ -22,7 +22,7 @@ description: · 21 unmodified lines | |||
| 22 | Each sub-node is identified using the node's name, with valid values listed | 22 | Each sub-node is identified using the node's name, with valid values listed |
| 23 | for each of the pmics below. | 23 | for each of the pmics below. |
| 24 | 24 | ||
| 25 | For mp5496, s1, s2 | 25 | For mp5496, s1, s2, l2, l5 |
| 26 | 26 | ||
| 27 | For pm2250, s1, s2, s3, s4, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, | 27 | For pm2250, s1, s2, s3, s4, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, |
| 28 | l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22 | 28 | l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22 |
| @@ -41,6 +41,12 @@ Device Drivers Base · 40 unmodified lines | |||
| 41 | .. kernel-doc:: drivers/base/class.c | 41 | .. kernel-doc:: drivers/base/class.c |
| 42 | :export: | 42 | :export: |
| 43 | 43 | ||
| 44 | .. kernel-doc:: include/linux/device/faux.h | ||
| 45 | :internal: | ||
| 46 | |||
| 47 | .. kernel-doc:: drivers/base/faux.c | ||
| 48 | :export: | ||
| 49 | |||
| 44 | .. kernel-doc:: drivers/base/node.c | 50 | .. kernel-doc:: drivers/base/node.c |
| 45 | :internal: | 51 | :internal: |
| 46 | 52 | ||
| @@ -0,0 +1,98 @@ | |||
| 1 | Submitting patches to bcachefs: | ||
| 2 | =============================== | ||
| 3 | |||
| 4 | Patches must be tested before being submitted, either with the xfstests suite | ||
| 5 | [0], or the full bcachefs test suite in ktest [1], depending on what's being | ||
| 6 | touched. Note that ktest wraps xfstests and will be an easier method to running | ||
| 7 | it for most users; it includes single-command wrappers for all the mainstream | ||
| 8 | in-kernel local filesystems. | ||
| 9 | |||
| 10 | Patches will undergo more testing after being merged (including | ||
| 11 | lockdep/kasan/preempt/etc. variants), these are not generally required to be | ||
| 12 | run by the submitter - but do put some thought into what you're changing and | ||
| 13 | which tests might be relevant, e.g. are you dealing with tricky memory layout | ||
| 14 | work? kasan, are you doing locking work? then lockdep; and ktest includes | ||
| 15 | single-command variants for the debug build types you'll most likely need. | ||
| 16 | |||
| 17 | The exception to this rule is incomplete WIP/RFC patches: if you're working on | ||
| 18 | something nontrivial, it's encouraged to send out a WIP patch to let people | ||
| 19 | know what you're doing and make sure you're on the right track. Just make sure | ||
| 20 | it includes a brief note as to what's done and what's incomplete, to avoid | ||
| 21 | confusion. | ||
| 22 | |||
| 23 | Rigorous checkpatch.pl adherence is not required (many of its warnings are | ||
| 24 | considered out of date), but try not to deviate too much without reason. | ||
| 25 | |||
| 26 | Focus on writing code that reads well and is organized well; code should be | ||
| 27 | aesthetically pleasing. | ||
| 28 | |||
| 29 | CI: | ||
| 30 | === | ||
| 31 | |||
| 32 | Instead of running your tests locally, when running the full test suite it's | ||
| 33 | prefereable to let a server farm do it in parallel, and then have the results | ||
| 34 | in a nice test dashboard (which can tell you which failures are new, and | ||
| 35 | presents results in a git log view, avoiding the need for most bisecting). | ||
| 36 | |||
| 37 | That exists [2], and community members may request an account. If you work for | ||
| 38 | a big tech company, you'll need to help out with server costs to get access - | ||
| 39 | but the CI is not restricted to running bcachefs tests: it runs any ktest test | ||
| 40 | (which generally makes it easy to wrap other tests that can run in qemu). | ||
| 41 | |||
| 42 | Other things to think about: | ||
| 43 | ============================ | ||
| 44 | |||
| 45 | - How will we debug this code? Is there sufficient introspection to diagnose | ||
| 46 | when something starts acting wonky on a user machine? | ||
| 47 | |||
| 48 | We don't necessarily need every single field of every data structure visible | ||
| 49 | with introspection, but having the important fields of all the core data | ||
| 50 | types wired up makes debugging drastically easier - a bit of thoughtful | ||
| 51 | foresight greatly reduces the need to have people build custom kernels with | ||
| 52 | debug patches. | ||
| 53 | |||
| 54 | More broadly, think about all the debug tooling that might be needed. | ||
| 55 | |||
| 56 | - Does it make the codebase more or less of a mess? Can we also try to do some | ||
| 57 | organizing, too? | ||
| 58 | |||
| 59 | - Do new tests need to be written? New assertions? How do we know and verify | ||
| 60 | that the code is correct, and what happens if something goes wrong? | ||
| 61 | |||
| 62 | We don't yet have automated code coverage analysis or easy fault injection - | ||
| 63 | but for now, pretend we did and ask what they might tell us. | ||
| 64 | |||
| 65 | Assertions are hugely important, given that we don't yet have a systems | ||
| 66 | language that can do ergonomic embedded correctness proofs. Hitting an assert | ||
| 67 | in testing is much better than wandering off into undefined behaviour la-la | ||
| 68 | land - use them. Use them judiciously, and not as a replacement for proper | ||
| 69 | error handling, but use them. | ||
| 70 | |||
| 71 | - Does it need to be performance tested? Should we add new peformance counters? | ||
| 72 | |||
| 73 | bcachefs has a set of persistent runtime counters which can be viewed with | ||
| 74 | the 'bcachefs fs top' command; this should give users a basic idea of what | ||
| 75 | their filesystem is currently doing. If you're doing a new feature or looking | ||
| 76 | at old code, think if anything should be added. | ||
| 77 | |||
| 78 | - If it's a new on disk format feature - have upgrades and downgrades been | ||
| 79 | tested? (Automated tests exists but aren't in the CI, due to the hassle of | ||
| 80 | disk image management; coordinate to have them run.) | ||
| 81 | |||
| 82 | Mailing list, IRC: | ||
| 83 | ================== | ||
| 84 | |||
| 85 | Patches should hit the list [3], but much discussion and code review happens on | ||
| 86 | IRC as well [4]; many people appreciate the more conversational approach and | ||
| 87 | quicker feedback. | ||
| 88 | |||
| 89 | Additionally, we have a lively user community doing excellent QA work, which | ||
| 90 | exists primarily on IRC. Please make use of that resource; user feedback is | ||
| 91 | important for any nontrivial feature, and documenting it in commit messages | ||
| 92 | would be a good idea. | ||
| 93 | |||
| 94 | [0]: git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git | ||
| 95 | [1]: https://evilpiepirate.org/git/ktest.git/ | ||
| 96 | [2]: https://evilpiepirate.org/~testdashboard/ci/ | ||
| 97 | [3]: linux-bcachefs@vger.kernel.org | ||
| 98 | [4]: irc.oftc.net#bcache, #bcachefs-dev | ||
| @@ -9,4 +9,5 @@ bcachefs Documentation · 8 unmodified lines | |||
| 9 | :numbered: | 9 | :numbered: |
| 10 | 10 | ||
| 11 | CodingStyle | 11 | CodingStyle |
| 12 | SubmittingPatches | ||
| 12 | errorcodes | 13 | errorcodes |
| @@ -1524,7 +1524,8 @@ attribute-sets: · 1523 unmodified lines | |||
| 1524 | nested-attributes: bitset | 1524 | nested-attributes: bitset |
| 1525 | - | 1525 | - |
| 1526 | name: hwtstamp-flags | 1526 | name: hwtstamp-flags |
| 1527 | type: u32 | 1527 | type: nest |
| 1528 | nested-attributes: bitset | ||
| 1528 | 1529 | ||
| 1529 | operations: | 1530 | operations: |
| 1530 | enum-model: directional | 1531 | enum-model: directional |
| @@ -369,8 +369,8 @@ to their default. · 368 unmodified lines | |||
| 369 | 369 | ||
| 370 | addr.can_family = AF_CAN; | 370 | addr.can_family = AF_CAN; |
| 371 | addr.can_ifindex = if_nametoindex("can0"); | 371 | addr.can_ifindex = if_nametoindex("can0"); |
| 372 | addr.tp.tx_id = 0x18DA42F1 | CAN_EFF_FLAG; | 372 | addr.can_addr.tp.tx_id = 0x18DA42F1 | CAN_EFF_FLAG; |
| 373 | addr.tp.rx_id = 0x18DAF142 | CAN_EFF_FLAG; | 373 | addr.can_addr.tp.rx_id = 0x18DAF142 | CAN_EFF_FLAG; |
| 374 | 374 | ||
| 375 | ret = bind(s, (struct sockaddr *)&addr, sizeof(addr)); | 375 | ret = bind(s, (struct sockaddr *)&addr, sizeof(addr)); |
| 376 | if (ret < 0) | 376 | if (ret < 0) |
| @@ -112,7 +112,7 @@ Functions · 111 unmodified lines | |||
| 112 | Callbacks | 112 | Callbacks |
| 113 | ========= | 113 | ========= |
| 114 | 114 | ||
| 115 | There are six callbacks: | 115 | There are seven callbacks: |
| 116 | 116 | ||
| 117 | :: | 117 | :: |
| 118 | 118 | ||
| @@ -182,6 +182,13 @@ There are six callbacks: · 63 unmodified lines | |||
| 182 | the length of the message. skb->len - offset may be greater | 182 | the length of the message. skb->len - offset may be greater |
| 183 | then full_len since strparser does not trim the skb. | 183 | then full_len since strparser does not trim the skb. |
| 184 | 184 | ||
| 185 | :: | ||
| 186 | |||
| 187 | int (*read_sock)(struct strparser *strp, read_descriptor_t *desc, | ||
| 188 | sk_read_actor_t recv_actor); | ||
| 189 | |||
| 190 | The read_sock callback is used by strparser instead of | ||
| 191 | sock->ops->read_sock, if provided. | ||
| 185 | :: | 192 | :: |
| 186 | 193 | ||
| 187 | int (*read_sock_done)(struct strparser *strp, int err); | 194 | int (*read_sock_done)(struct strparser *strp, int err); |
| @@ -308,7 +308,7 @@ an involved disclosed party. The current ambassadors list: · 307 unmodified lines | |||
| 308 | 308 | ||
| 309 | Google Kees Cook <keescook@chromium.org> | 309 | Google Kees Cook <keescook@chromium.org> |
| 310 | 310 | ||
| 311 | LLVM Nick Desaulniers <ndesaulniers@google.com> | 311 | LLVM Nick Desaulniers <nick.desaulniers+lkml@gmail.com> |
| 312 | ============= ======================================================== | 312 | ============= ======================================================== |
| 313 | 313 | ||
| 314 | If you want your organization to be added to the ambassadors list, please | 314 | If you want your organization to be added to the ambassadors list, please |
| @@ -287,7 +287,7 @@ revelada involucrada. La lista de embajadores actuales: · 286 unmodified lines | |||
| 287 | 287 | ||
| 288 | Google Kees Cook <keescook@chromium.org> | 288 | Google Kees Cook <keescook@chromium.org> |
| 289 | 289 | ||
| 290 | LLVM Nick Desaulniers <ndesaulniers@google.com> | 290 | LLVM Nick Desaulniers <nick.desaulniers+lkml@gmail.com> |
| 291 | ============= ======================================================== | 291 | ============= ======================================================== |
| 292 | 292 | ||
| 293 | Si quiere que su organización se añada a la lista de embajadores, por | 293 | Si quiere que su organización se añada a la lista de embajadores, por |
| @@ -1419,7 +1419,7 @@ fetch) is injected in the guest. · 1418 unmodified lines | |||
| 1419 | S390: | 1419 | S390: |
| 1420 | ^^^^^ | 1420 | ^^^^^ |
| 1421 | 1421 | ||
| 1422 | Returns -EINVAL if the VM has the KVM_VM_S390_UCONTROL flag set. | 1422 | Returns -EINVAL or -EEXIST if the VM has the KVM_VM_S390_UCONTROL flag set. |
| 1423 | Returns -EINVAL if called on a protected VM. | 1423 | Returns -EINVAL if called on a protected VM. |
| 1424 | 1424 | ||
| 1425 | 4.36 KVM_SET_TSS_ADDR | 1425 | 4.36 KVM_SET_TSS_ADDR |
| @@ -2209,7 +2209,6 @@ F: sound/soc/codecs/cs42l84.* · 2208 unmodified lines | |||
| 2209 | F: sound/soc/codecs/ssm3515.c | 2209 | F: sound/soc/codecs/ssm3515.c |
| 2210 | 2210 | ||
| 2211 | ARM/APPLE MACHINE SUPPORT | 2211 | ARM/APPLE MACHINE SUPPORT |
| 2212 | M: Hector Martin <marcan@marcan.st> | ||
| 2213 | M: Sven Peter <sven@svenpeter.dev> | 2212 | M: Sven Peter <sven@svenpeter.dev> |
| 2214 | R: Alyssa Rosenzweig <alyssa@rosenzweig.io> | 2213 | R: Alyssa Rosenzweig <alyssa@rosenzweig.io> |
| 2215 | L: asahi@lists.linux.dev | 2214 | L: asahi@lists.linux.dev |
| @@ -3655,7 +3654,6 @@ F: Documentation/devicetree/bindings/phy/phy-ath79-usb.txt · 1439 unmodified lines | |||
| 3655 | F: drivers/phy/qualcomm/phy-ath79-usb.c | 3654 | F: drivers/phy/qualcomm/phy-ath79-usb.c |
| 3656 | 3655 | ||
| 3657 | ATHEROS ATH GENERIC UTILITIES | 3656 | ATHEROS ATH GENERIC UTILITIES |
| 3658 | M: Kalle Valo <kvalo@kernel.org> | ||
| 3659 | M: Jeff Johnson <jjohnson@kernel.org> | 3657 | M: Jeff Johnson <jjohnson@kernel.org> |
| 3660 | L: linux-wireless@vger.kernel.org | 3658 | L: linux-wireless@vger.kernel.org |
| 3661 | S: Supported | 3659 | S: Supported |
| @@ -3860,13 +3858,6 @@ W: https://ez.analog.com/linux-software-drivers · 198 unmodified lines | |||
| 3860 | F: Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml | 3858 | F: Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml |
| 3861 | F: drivers/pwm/pwm-axi-pwmgen.c | 3859 | F: drivers/pwm/pwm-axi-pwmgen.c |
| 3862 | 3860 | ||
| 3863 | AXXIA I2C CONTROLLER | ||
| 3864 | M: Krzysztof Adamski <krzysztof.adamski@nokia.com> | ||
| 3865 | L: linux-i2c@vger.kernel.org | ||
| 3866 | S: Maintained | ||
| 3867 | F: Documentation/devicetree/bindings/i2c/i2c-axxia.txt | ||
| 3868 | F: drivers/i2c/busses/i2c-axxia.c | ||
| 3869 | |||
| 3870 | AZ6007 DVB DRIVER | 3861 | AZ6007 DVB DRIVER |
| 3871 | M: Mauro Carvalho Chehab <mchehab@kernel.org> | 3862 | M: Mauro Carvalho Chehab <mchehab@kernel.org> |
| 3872 | L: linux-media@vger.kernel.org | 3863 | L: linux-media@vger.kernel.org |
| @@ -3955,6 +3946,7 @@ M: Kent Overstreet <kent.overstreet@linux.dev> · 82 unmodified lines | |||
| 3955 | L: linux-bcachefs@vger.kernel.org | 3946 | L: linux-bcachefs@vger.kernel.org |
| 3956 | S: Supported | 3947 | S: Supported |
| 3957 | C: irc://irc.oftc.net/bcache | 3948 | C: irc://irc.oftc.net/bcache |
| 3949 | P: Documentation/filesystems/bcachefs/SubmittingPatches.rst | ||
| 3958 | T: git https://evilpiepirate.org/git/bcachefs.git | 3950 | T: git https://evilpiepirate.org/git/bcachefs.git |
| 3959 | F: fs/bcachefs/ | 3951 | F: fs/bcachefs/ |
| 3960 | F: Documentation/filesystems/bcachefs/ | 3952 | F: Documentation/filesystems/bcachefs/ |
| @@ -5663,7 +5655,7 @@ F: .clang-format · 1702 unmodified lines | |||
| 5663 | 5655 | ||
| 5664 | CLANG/LLVM BUILD SUPPORT | 5656 | CLANG/LLVM BUILD SUPPORT |
| 5665 | M: Nathan Chancellor <nathan@kernel.org> | 5657 | M: Nathan Chancellor <nathan@kernel.org> |
| 5666 | R: Nick Desaulniers <ndesaulniers@google.com> | 5658 | R: Nick Desaulniers <nick.desaulniers+lkml@gmail.com> |
| 5667 | R: Bill Wendling <morbo@google.com> | 5659 | R: Bill Wendling <morbo@google.com> |
| 5668 | R: Justin Stitt <justinstitt@google.com> | 5660 | R: Justin Stitt <justinstitt@google.com> |
| 5669 | L: llvm@lists.linux.dev | 5661 | L: llvm@lists.linux.dev |
| @@ -7116,8 +7108,10 @@ F: rust/kernel/device.rs · 1446 unmodified lines | |||
| 7116 | F: rust/kernel/device_id.rs | 7108 | F: rust/kernel/device_id.rs |
| 7117 | F: rust/kernel/devres.rs | 7109 | F: rust/kernel/devres.rs |
| 7118 | F: rust/kernel/driver.rs | 7110 | F: rust/kernel/driver.rs |
| 7111 | F: rust/kernel/faux.rs | ||
| 7119 | F: rust/kernel/platform.rs | 7112 | F: rust/kernel/platform.rs |
| 7120 | F: samples/rust/rust_driver_platform.rs | 7113 | F: samples/rust/rust_driver_platform.rs |
| 7114 | F: samples/rust/rust_driver_faux.rs | ||
| 7121 | 7115 | ||
| 7122 | DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS) | 7116 | DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS) |
| 7123 | M: Nishanth Menon <nm@ti.com> | 7117 | M: Nishanth Menon <nm@ti.com> |
| @@ -9418,7 +9412,7 @@ F: fs/freevxfs/ · 2294 unmodified lines | |||
| 9418 | 9412 | ||
| 9419 | FREEZER | 9413 | FREEZER |
| 9420 | M: "Rafael J. Wysocki" <rafael@kernel.org> | 9414 | M: "Rafael J. Wysocki" <rafael@kernel.org> |
| 9421 | M: Pavel Machek <pavel@ucw.cz> | 9415 | M: Pavel Machek <pavel@kernel.org> |
| 9422 | L: linux-pm@vger.kernel.org | 9416 | L: linux-pm@vger.kernel.org |
| 9423 | S: Supported | 9417 | S: Supported |
| 9424 | F: Documentation/power/freezing-of-tasks.rst | 9418 | F: Documentation/power/freezing-of-tasks.rst |
| @@ -9835,8 +9829,7 @@ F: drivers/input/touchscreen/goodix* · 410 unmodified lines | |||
| 9835 | 9829 | ||
| 9836 | GOOGLE ETHERNET DRIVERS | 9830 | GOOGLE ETHERNET DRIVERS |
| 9837 | M: Jeroen de Borst <jeroendb@google.com> | 9831 | M: Jeroen de Borst <jeroendb@google.com> |
| 9838 | M: Praveen Kaligineedi <pkaligineedi@google.com> | 9832 | M: Harshitha Ramamurthy <hramamurthy@google.com> |
| 9839 | R: Shailend Chand <shailend@google.com> | ||
| 9840 | L: netdev@vger.kernel.org | 9833 | L: netdev@vger.kernel.org |
| 9841 | S: Maintained | 9834 | S: Maintained |
| 9842 | F: Documentation/networking/device_drivers/ethernet/google/gve.rst | 9835 | F: Documentation/networking/device_drivers/ethernet/google/gve.rst |
| @@ -9878,7 +9871,7 @@ S: Maintained · 35 unmodified lines | |||
| 9878 | F: drivers/staging/gpib/ | 9871 | F: drivers/staging/gpib/ |
| 9879 | 9872 | ||
| 9880 | GPIO ACPI SUPPORT | 9873 | GPIO ACPI SUPPORT |
| 9881 | M: Mika Westerberg <mika.westerberg@linux.intel.com> | 9874 | M: Mika Westerberg <westeri@kernel.org> |
| 9882 | M: Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 9875 | M: Andy Shevchenko <andriy.shevchenko@linux.intel.com> |
| 9883 | L: linux-gpio@vger.kernel.org | 9876 | L: linux-gpio@vger.kernel.org |
| 9884 | L: linux-acpi@vger.kernel.org | 9877 | L: linux-acpi@vger.kernel.org |
| @@ -10253,7 +10246,7 @@ F: drivers/video/fbdev/hgafb.c · 368 unmodified lines | |||
| 10253 | 10246 | ||
| 10254 | HIBERNATION (aka Software Suspend, aka swsusp) | 10247 | HIBERNATION (aka Software Suspend, aka swsusp) |
| 10255 | M: "Rafael J. Wysocki" <rafael@kernel.org> | 10248 | M: "Rafael J. Wysocki" <rafael@kernel.org> |
| 10256 | M: Pavel Machek <pavel@ucw.cz> | 10249 | M: Pavel Machek <pavel@kernel.org> |
| 10257 | L: linux-pm@vger.kernel.org | 10250 | L: linux-pm@vger.kernel.org |
| 10258 | S: Supported | 10251 | S: Supported |
| 10259 | B: https://bugzilla.kernel.org | 10252 | B: https://bugzilla.kernel.org |
| @@ -10822,7 +10815,7 @@ S: Odd Fixes · 562 unmodified lines | |||
| 10822 | F: drivers/tty/hvc/ | 10815 | F: drivers/tty/hvc/ |
| 10823 | 10816 | ||
| 10824 | I2C ACPI SUPPORT | 10817 | I2C ACPI SUPPORT |
| 10825 | M: Mika Westerberg <mika.westerberg@linux.intel.com> | 10818 | M: Mika Westerberg <westeri@kernel.org> |
| 10826 | L: linux-i2c@vger.kernel.org | 10819 | L: linux-i2c@vger.kernel.org |
| 10827 | L: linux-acpi@vger.kernel.org | 10820 | L: linux-acpi@vger.kernel.org |
| 10828 | S: Maintained | 10821 | S: Maintained |
| @@ -13124,8 +13117,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/har · 2295 unmodified lines | |||
| 13124 | F: scripts/leaking_addresses.pl | 13117 | F: scripts/leaking_addresses.pl |
| 13125 | 13118 | ||
| 13126 | LED SUBSYSTEM | 13119 | LED SUBSYSTEM |
| 13127 | M: Pavel Machek <pavel@ucw.cz> | ||
| 13128 | M: Lee Jones <lee@kernel.org> | 13120 | M: Lee Jones <lee@kernel.org> |
| 13121 | M: Pavel Machek <pavel@kernel.org> | ||
| 13129 | L: linux-leds@vger.kernel.org | 13122 | L: linux-leds@vger.kernel.org |
| 13130 | S: Maintained | 13123 | S: Maintained |
| 13131 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds.git | 13124 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds.git |
| @@ -16438,7 +16431,7 @@ X: drivers/net/can/ · 3306 unmodified lines | |||
| 16438 | X: drivers/net/wireless/ | 16431 | X: drivers/net/wireless/ |
| 16439 | 16432 | ||
| 16440 | NETWORKING DRIVERS (WIRELESS) | 16433 | NETWORKING DRIVERS (WIRELESS) |
| 16441 | M: Kalle Valo <kvalo@kernel.org> | 16434 | M: Johannes Berg <johannes@sipsolutions.net> |
| 16442 | L: linux-wireless@vger.kernel.org | 16435 | L: linux-wireless@vger.kernel.org |
| 16443 | S: Maintained | 16436 | S: Maintained |
| 16444 | W: https://wireless.wiki.kernel.org/ | 16437 | W: https://wireless.wiki.kernel.org/ |
| @@ -16462,6 +16455,28 @@ F: include/net/dsa.h · 17 unmodified lines | |||
| 16462 | F: net/dsa/ | 16455 | F: net/dsa/ |
| 16463 | F: tools/testing/selftests/drivers/net/dsa/ | 16456 | F: tools/testing/selftests/drivers/net/dsa/ |
| 16464 | 16457 | ||
| 16458 | NETWORKING [ETHTOOL] | ||
| 16459 | M: Andrew Lunn <andrew@lunn.ch> | ||
| 16460 | M: Jakub Kicinski <kuba@kernel.org> | ||
| 16461 | F: Documentation/netlink/specs/ethtool.yaml | ||
| 16462 | F: Documentation/networking/ethtool-netlink.rst | ||
| 16463 | F: include/linux/ethtool* | ||
| 16464 | F: include/uapi/linux/ethtool* | ||
| 16465 | F: net/ethtool/ | ||
| 16466 | F: tools/testing/selftests/drivers/net/*/ethtool* | ||
| 16467 | |||
| 16468 | NETWORKING [ETHTOOL CABLE TEST] | ||
| 16469 | M: Andrew Lunn <andrew@lunn.ch> | ||
| 16470 | F: net/ethtool/cabletest.c | ||
| 16471 | F: tools/testing/selftests/drivers/net/*/ethtool* | ||
| 16472 | K: cable_test | ||
| 16473 | |||
| 16474 | NETWORKING [ETHTOOL MAC MERGE] | ||
| 16475 | M: Vladimir Oltean <vladimir.oltean@nxp.com> | ||
| 16476 | F: net/ethtool/mm.c | ||
| 16477 | F: tools/testing/selftests/drivers/net/hw/ethtool_mm.sh | ||
| 16478 | K: ethtool_mm | ||
| 16479 | |||
| 16465 | NETWORKING [GENERAL] | 16480 | NETWORKING [GENERAL] |
| 16466 | M: "David S. Miller" <davem@davemloft.net> | 16481 | M: "David S. Miller" <davem@davemloft.net> |
| 16467 | M: Eric Dumazet <edumazet@google.com> | 16482 | M: Eric Dumazet <edumazet@google.com> |
| @@ -16493,6 +16508,7 @@ F: include/linux/netdev* · 25 unmodified lines | |||
| 16493 | F: include/linux/netlink.h | 16508 | F: include/linux/netlink.h |
| 16494 | F: include/linux/netpoll.h | 16509 | F: include/linux/netpoll.h |
| 16495 | F: include/linux/rtnetlink.h | 16510 | F: include/linux/rtnetlink.h |
| 16511 | F: include/linux/sctp.h | ||
| 16496 | F: include/linux/seq_file_net.h | 16512 | F: include/linux/seq_file_net.h |
| 16497 | F: include/linux/skbuff* | 16513 | F: include/linux/skbuff* |
| 16498 | F: include/net/ | 16514 | F: include/net/ |
| @@ -16509,6 +16525,7 @@ F: include/uapi/linux/netdev* · 10 unmodified lines | |||
| 16509 | F: include/uapi/linux/netlink.h | 16525 | F: include/uapi/linux/netlink.h |
| 16510 | F: include/uapi/linux/netlink_diag.h | 16526 | F: include/uapi/linux/netlink_diag.h |
| 16511 | F: include/uapi/linux/rtnetlink.h | 16527 | F: include/uapi/linux/rtnetlink.h |
| 16528 | F: include/uapi/linux/sctp.h | ||
| 16512 | F: lib/net_utils.c | 16529 | F: lib/net_utils.c |
| 16513 | F: lib/random32.c | 16530 | F: lib/random32.c |
| 16514 | F: net/ | 16531 | F: net/ |
| @@ -16621,6 +16638,7 @@ F: tools/testing/selftests/net/mptcp/ · 106 unmodified lines | |||
| 16621 | NETWORKING [TCP] | 16638 | NETWORKING [TCP] |
| 16622 | M: Eric Dumazet <edumazet@google.com> | 16639 | M: Eric Dumazet <edumazet@google.com> |
| 16623 | M: Neal Cardwell <ncardwell@google.com> | 16640 | M: Neal Cardwell <ncardwell@google.com> |
| 16641 | R: Kuniyuki Iwashima <kuniyu@amazon.com> | ||
| 16624 | L: netdev@vger.kernel.org | 16642 | L: netdev@vger.kernel.org |
| 16625 | S: Maintained | 16643 | S: Maintained |
| 16626 | F: Documentation/networking/net_cachelines/tcp_sock.rst | 16644 | F: Documentation/networking/net_cachelines/tcp_sock.rst |
| @@ -16648,6 +16666,31 @@ F: include/net/tls.h · 21 unmodified lines | |||
| 16648 | F: include/uapi/linux/tls.h | 16666 | F: include/uapi/linux/tls.h |
| 16649 | F: net/tls/* | 16667 | F: net/tls/* |
| 16650 | 16668 | ||
| 16669 | NETWORKING [SOCKETS] | ||
| 16670 | M: Eric Dumazet <edumazet@google.com> | ||
| 16671 | M: Kuniyuki Iwashima <kuniyu@amazon.com> | ||
| 16672 | M: Paolo Abeni <pabeni@redhat.com> | ||
| 16673 | M: Willem de Bruijn <willemb@google.com> | ||
| 16674 | S: Maintained | ||
| 16675 | F: include/linux/sock_diag.h | ||
| 16676 | F: include/linux/socket.h | ||
| 16677 | F: include/linux/sockptr.h | ||
| 16678 | F: include/net/sock.h | ||
| 16679 | F: include/net/sock_reuseport.h | ||
| 16680 | F: include/uapi/linux/socket.h | ||
| 16681 | F: net/core/*sock* | ||
| 16682 | F: net/core/scm.c | ||
| 16683 | F: net/socket.c | ||
| 16684 | |||
| 16685 | NETWORKING [UNIX SOCKETS] | ||
| 16686 | M: Kuniyuki Iwashima <kuniyu@amazon.com> | ||
| 16687 | S: Maintained | ||
| 16688 | F: include/net/af_unix.h | ||
| 16689 | F: include/net/netns/unix.h | ||
| 16690 | F: include/uapi/linux/unix_diag.h | ||
| 16691 | F: net/unix/ | ||
| 16692 | F: tools/testing/selftests/net/af_unix/ | ||
| 16693 | |||
| 16651 | NETXEN (1/10) GbE SUPPORT | 16694 | NETXEN (1/10) GbE SUPPORT |
| 16652 | M: Manish Chopra <manishc@marvell.com> | 16695 | M: Manish Chopra <manishc@marvell.com> |
| 16653 | M: Rahul Verma <rahulv@marvell.com> | 16696 | M: Rahul Verma <rahulv@marvell.com> |
| @@ -16781,7 +16824,7 @@ F: include/linux/tick.h · 127 unmodified lines | |||
| 16781 | F: kernel/time/tick*.* | 16824 | F: kernel/time/tick*.* |
| 16782 | 16825 | ||
| 16783 | NOKIA N900 CAMERA SUPPORT (ET8EK8 SENSOR, AD5820 FOCUS) | 16826 | NOKIA N900 CAMERA SUPPORT (ET8EK8 SENSOR, AD5820 FOCUS) |
| 16784 | M: Pavel Machek <pavel@ucw.cz> | 16827 | M: Pavel Machek <pavel@kernel.org> |
| 16785 | M: Sakari Ailus <sakari.ailus@iki.fi> | 16828 | M: Sakari Ailus <sakari.ailus@iki.fi> |
| 16786 | L: linux-media@vger.kernel.org | 16829 | L: linux-media@vger.kernel.org |
| 16787 | S: Maintained | 16830 | S: Maintained |
| @@ -17713,6 +17756,7 @@ L: netdev@vger.kernel.org · 925 unmodified lines | |||
| 17713 | L: dev@openvswitch.org | 17756 | L: dev@openvswitch.org |
| 17714 | S: Maintained | 17757 | S: Maintained |
| 17715 | W: http://openvswitch.org | 17758 | W: http://openvswitch.org |
| 17759 | F: Documentation/networking/openvswitch.rst | ||
| 17716 | F: include/uapi/linux/openvswitch.h | 17760 | F: include/uapi/linux/openvswitch.h |
| 17717 | F: net/openvswitch/ | 17761 | F: net/openvswitch/ |
| 17718 | F: tools/testing/selftests/net/openvswitch/ | 17762 | F: tools/testing/selftests/net/openvswitch/ |
| @@ -19312,7 +19356,6 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/ · 1593 unmodified lines | |||
| 19312 | F: drivers/media/tuners/qt1010* | 19356 | F: drivers/media/tuners/qt1010* |
| 19313 | 19357 | ||
| 19314 | QUALCOMM ATH12K WIRELESS DRIVER | 19358 | QUALCOMM ATH12K WIRELESS DRIVER |
| 19315 | M: Kalle Valo <kvalo@kernel.org> | ||
| 19316 | M: Jeff Johnson <jjohnson@kernel.org> | 19359 | M: Jeff Johnson <jjohnson@kernel.org> |
| 19317 | L: ath12k@lists.infradead.org | 19360 | L: ath12k@lists.infradead.org |
| 19318 | S: Supported | 19361 | S: Supported |
| @@ -19322,7 +19365,6 @@ F: drivers/net/wireless/ath/ath12k/ · 3 unmodified lines | |||
| 19322 | N: ath12k | 19365 | N: ath12k |
| 19323 | 19366 | ||
| 19324 | QUALCOMM ATHEROS ATH10K WIRELESS DRIVER | 19367 | QUALCOMM ATHEROS ATH10K WIRELESS DRIVER |
| 19325 | M: Kalle Valo <kvalo@kernel.org> | ||
| 19326 | M: Jeff Johnson <jjohnson@kernel.org> | 19368 | M: Jeff Johnson <jjohnson@kernel.org> |
| 19327 | L: ath10k@lists.infradead.org | 19369 | L: ath10k@lists.infradead.org |
| 19328 | S: Supported | 19370 | S: Supported |
| @@ -19332,7 +19374,6 @@ F: drivers/net/wireless/ath/ath10k/ · 3 unmodified lines | |||
| 19332 | N: ath10k | 19374 | N: ath10k |
| 19333 | 19375 | ||
| 19334 | QUALCOMM ATHEROS ATH11K WIRELESS DRIVER | 19376 | QUALCOMM ATHEROS ATH11K WIRELESS DRIVER |
| 19335 | M: Kalle Valo <kvalo@kernel.org> | ||
| 19336 | M: Jeff Johnson <jjohnson@kernel.org> | 19377 | M: Jeff Johnson <jjohnson@kernel.org> |
| 19337 | L: ath11k@lists.infradead.org | 19378 | L: ath11k@lists.infradead.org |
| 19338 | S: Supported | 19379 | S: Supported |
| @@ -19467,6 +19508,15 @@ L: dmaengine@vger.kernel.org · 128 unmodified lines | |||
| 19467 | S: Supported | 19508 | S: Supported |
| 19468 | F: drivers/dma/qcom/hidma* | 19509 | F: drivers/dma/qcom/hidma* |
| 19469 | 19510 | ||
| 19511 | QUALCOMM I2C QCOM GENI DRIVER | ||
| 19512 | M: Mukesh Kumar Savaliya <quic_msavaliy@quicinc.com> | ||
| 19513 | M: Viken Dadhaniya <quic_vdadhani@quicinc.com> | ||
| 19514 | L: linux-i2c@vger.kernel.org | ||
| 19515 | L: linux-arm-msm@vger.kernel.org | ||
| 19516 | S: Maintained | ||
| 19517 | F: Documentation/devicetree/bindings/i2c/qcom,i2c-geni-qcom.yaml | ||
| 19518 | F: drivers/i2c/busses/i2c-qcom-geni.c | ||
| 19519 | |||
| 19470 | QUALCOMM I2C CCI DRIVER | 19520 | QUALCOMM I2C CCI DRIVER |
| 19471 | M: Loic Poulain <loic.poulain@linaro.org> | 19521 | M: Loic Poulain <loic.poulain@linaro.org> |
| 19472 | M: Robert Foss <rfoss@kernel.org> | 19522 | M: Robert Foss <rfoss@kernel.org> |
| @@ -22806,7 +22856,7 @@ F: drivers/sh/ · 3333 unmodified lines | |||
| 22806 | SUSPEND TO RAM | 22856 | SUSPEND TO RAM |
| 22807 | M: "Rafael J. Wysocki" <rafael@kernel.org> | 22857 | M: "Rafael J. Wysocki" <rafael@kernel.org> |
| 22808 | M: Len Brown <len.brown@intel.com> | 22858 | M: Len Brown <len.brown@intel.com> |
| 22809 | M: Pavel Machek <pavel@ucw.cz> | 22859 | M: Pavel Machek <pavel@kernel.org> |
| 22810 | L: linux-pm@vger.kernel.org | 22860 | L: linux-pm@vger.kernel.org |
| 22811 | S: Supported | 22861 | S: Supported |
| 22812 | B: https://bugzilla.kernel.org | 22862 | B: https://bugzilla.kernel.org |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 6 | 2 | VERSION = 6 |
| 3 | PATCHLEVEL = 14 | 3 | PATCHLEVEL = 14 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc1 | 5 | EXTRAVERSION = -rc3 |
| 6 | NAME = Baby Opossum Posse | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -1120,8 +1120,8 @@ LDFLAGS_vmlinux += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL) · 1111 unmodified lines | |||
| 1120 | endif | 1120 | endif |
| 1121 | 1121 | ||
| 1122 | # Align the bit size of userspace programs with the kernel | 1122 | # Align the bit size of userspace programs with the kernel |
| 1123 | KBUILD_USERCFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS)) | 1123 | KBUILD_USERCFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)) |
| 1124 | KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS)) | 1124 | KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)) |
| 1125 | 1125 | ||
| 1126 | # make the checker run with the right architecture | 1126 | # make the checker run with the right architecture |
| 1127 | CHECKFLAGS += --arch=$(ARCH) | 1127 | CHECKFLAGS += --arch=$(ARCH) |
| @@ -1421,18 +1421,13 @@ ifneq ($(wildcard $(resolve_btfids_O)),) · 293 unmodified lines | |||
| 1421 | $(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean | 1421 | $(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean |
| 1422 | endif | 1422 | endif |
| 1423 | 1423 | ||
| 1424 | # Clear a bunch of variables before executing the submake | ||
| 1425 | ifeq ($(quiet),silent_) | ||
| 1426 | tools_silent=s | ||
| 1427 | endif | ||
| 1428 | |||
| 1429 | tools/: FORCE | 1424 | tools/: FORCE |
| 1430 | $(Q)mkdir -p $(objtree)/tools | 1425 | $(Q)mkdir -p $(objtree)/tools |
| 1431 | $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(tools_silent) $(filter --j% -j,$(MAKEFLAGS))" O=$(abspath $(objtree)) subdir=tools -C $(srctree)/tools/ | 1426 | $(Q)$(MAKE) LDFLAGS= O=$(abspath $(objtree)) subdir=tools -C $(srctree)/tools/ |
| 1432 | 1427 | ||
| 1433 | tools/%: FORCE | 1428 | tools/%: FORCE |
| 1434 | $(Q)mkdir -p $(objtree)/tools | 1429 | $(Q)mkdir -p $(objtree)/tools |
| 1435 | $(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(tools_silent) $(filter --j% -j,$(MAKEFLAGS))" O=$(abspath $(objtree)) subdir=tools -C $(srctree)/tools/ $* | 1430 | $(Q)$(MAKE) LDFLAGS= O=$(abspath $(objtree)) subdir=tools -C $(srctree)/tools/ $* |
| 1436 | 1431 | ||
| 1437 | # --------------------------------------------------------------------------- | 1432 | # --------------------------------------------------------------------------- |
| 1438 | # Kernel selftest | 1433 | # Kernel selftest |
| @@ -74,7 +74,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; · 73 unmodified lines | |||
| 74 | /* | 74 | /* |
| 75 | * This is used to ensure we don't load something for the wrong architecture. | 75 | * This is used to ensure we don't load something for the wrong architecture. |
| 76 | */ | 76 | */ |
| 77 | #define elf_check_arch(x) ((x)->e_machine == EM_ALPHA) | 77 | #define elf_check_arch(x) (((x)->e_machine == EM_ALPHA) && !((x)->e_flags & EF_ALPHA_32BIT)) |
| 78 | 78 | ||
| 79 | /* | 79 | /* |
| 80 | * These are used to set parameters in the core dumps. | 80 | * These are used to set parameters in the core dumps. |
| @@ -137,10 +137,6 @@ extern int dump_elf_task(elf_greg_t *dest, struct task_struct *task); · 56 unmodified lines | |||
| 137 | : amask (AMASK_CIX) ? "ev6" : "ev67"); \ | 137 | : amask (AMASK_CIX) ? "ev6" : "ev67"); \ |
| 138 | }) | 138 | }) |
| 139 | 139 | ||
| 140 | #define SET_PERSONALITY(EX) \ | ||
| 141 | set_personality(((EX).e_flags & EF_ALPHA_32BIT) \ | ||
| 142 | ? PER_LINUX_32BIT : PER_LINUX) | ||
| 143 | |||
| 144 | extern int alpha_l1i_cacheshape; | 140 | extern int alpha_l1i_cacheshape; |
| 145 | extern int alpha_l1d_cacheshape; | 141 | extern int alpha_l1d_cacheshape; |
| 146 | extern int alpha_l2_cacheshape; | 142 | extern int alpha_l2_cacheshape; |
| @@ -135,7 +135,7 @@ struct crb_struct { · 134 unmodified lines | |||
| 135 | /* virtual->physical map */ | 135 | /* virtual->physical map */ |
| 136 | unsigned long map_entries; | 136 | unsigned long map_entries; |
| 137 | unsigned long map_pages; | 137 | unsigned long map_pages; |
| 138 | struct vf_map_struct map[1]; | 138 | struct vf_map_struct map[]; |
| 139 | }; | 139 | }; |
| 140 | 140 | ||
| 141 | struct memclust_struct { | 141 | struct memclust_struct { |
| @@ -360,7 +360,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte) · 359 unmodified lines | |||
| 360 | 360 | ||
| 361 | extern void paging_init(void); | 361 | extern void paging_init(void); |
| 362 | 362 | ||
| 363 | /* We have our own get_unmapped_area to cope with ADDR_LIMIT_32BIT. */ | 363 | /* We have our own get_unmapped_area */ |
| 364 | #define HAVE_ARCH_UNMAPPED_AREA | 364 | #define HAVE_ARCH_UNMAPPED_AREA |
| 365 | 365 | ||
| 366 | #endif /* _ALPHA_PGTABLE_H */ | 366 | #endif /* _ALPHA_PGTABLE_H */ |
| @@ -8,23 +8,19 @@ · 7 unmodified lines | |||
| 8 | #ifndef __ASM_ALPHA_PROCESSOR_H | 8 | #ifndef __ASM_ALPHA_PROCESSOR_H |
| 9 | #define __ASM_ALPHA_PROCESSOR_H | 9 | #define __ASM_ALPHA_PROCESSOR_H |
| 10 | 10 | ||
| 11 | #include <linux/personality.h> /* for ADDR_LIMIT_32BIT */ | ||
| 12 | |||
| 13 | /* | 11 | /* |
| 14 | * We have a 42-bit user address space: 4TB user VM... | 12 | * We have a 42-bit user address space: 4TB user VM... |
| 15 | */ | 13 | */ |
| 16 | #define TASK_SIZE (0x40000000000UL) | 14 | #define TASK_SIZE (0x40000000000UL) |
| 17 | 15 | ||
| 18 | #define STACK_TOP \ | 16 | #define STACK_TOP (0x00120000000UL) |
| 19 | (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL) | ||
| 20 | 17 | ||
| 21 | #define STACK_TOP_MAX 0x00120000000UL | 18 | #define STACK_TOP_MAX 0x00120000000UL |
| 22 | 19 | ||
| 23 | /* This decides where the kernel will search for a free chunk of vm | 20 | /* This decides where the kernel will search for a free chunk of vm |
| 24 | * space during mmap's. | 21 | * space during mmap's. |
| 25 | */ | 22 | */ |
| 26 | #define TASK_UNMAPPED_BASE \ | 23 | #define TASK_UNMAPPED_BASE (TASK_SIZE / 2) |
| 27 | ((current->personality & ADDR_LIMIT_32BIT) ? 0x40000000 : TASK_SIZE / 2) | ||
| 28 | 24 | ||
| 29 | /* This is dead. Everything has been moved to thread_info. */ | 25 | /* This is dead. Everything has been moved to thread_info. */ |
| 30 | struct thread_struct { }; | 26 | struct thread_struct { }; |
| @@ -42,6 +42,8 @@ struct pt_regs { · 41 unmodified lines | |||
| 42 | unsigned long trap_a0; | 42 | unsigned long trap_a0; |
| 43 | unsigned long trap_a1; | 43 | unsigned long trap_a1; |
| 44 | unsigned long trap_a2; | 44 | unsigned long trap_a2; |
| 45 | /* This makes the stack 16-byte aligned as GCC expects */ | ||
| 46 | unsigned long __pad0; | ||
| 45 | /* These are saved by PAL-code: */ | 47 | /* These are saved by PAL-code: */ |
| 46 | unsigned long ps; | 48 | unsigned long ps; |
| 47 | unsigned long pc; | 49 | unsigned long pc; |
| @@ -19,9 +19,13 @@ static void __used foo(void) · 18 unmodified lines | |||
| 19 | DEFINE(TI_STATUS, offsetof(struct thread_info, status)); | 19 | DEFINE(TI_STATUS, offsetof(struct thread_info, status)); |
| 20 | BLANK(); | 20 | BLANK(); |
| 21 | 21 | ||
| 22 | DEFINE(SP_OFF, offsetof(struct pt_regs, ps)); | ||
| 22 | DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs)); | 23 | DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs)); |
| 23 | BLANK(); | 24 | BLANK(); |
| 24 | 25 | ||
| 26 | DEFINE(SWITCH_STACK_SIZE, sizeof(struct switch_stack)); | ||
| 27 | BLANK(); | ||
| 28 | |||
| 25 | DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache)); | 29 | DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache)); |
| 26 | DEFINE(HAE_REG, offsetof(struct alpha_machine_vector, hae_register)); | 30 | DEFINE(HAE_REG, offsetof(struct alpha_machine_vector, hae_register)); |
| 27 | } | 31 | } |
| @@ -15,10 +15,6 @@ · 14 unmodified lines | |||
| 15 | .set noat | 15 | .set noat |
| 16 | .cfi_sections .debug_frame | 16 | .cfi_sections .debug_frame |
| 17 | 17 | ||
| 18 | /* Stack offsets. */ | ||
| 19 | #define SP_OFF 184 | ||
| 20 | #define SWITCH_STACK_SIZE 64 | ||
| 21 | |||
| 22 | .macro CFI_START_OSF_FRAME func | 18 | .macro CFI_START_OSF_FRAME func |
| 23 | .align 4 | 19 | .align 4 |
| 24 | .globl \func | 20 | .globl \func |
| @@ -198,8 +194,8 @@ CFI_END_OSF_FRAME entArith · 173 unmodified lines | |||
| 198 | CFI_START_OSF_FRAME entMM | 194 | CFI_START_OSF_FRAME entMM |
| 199 | SAVE_ALL | 195 | SAVE_ALL |
| 200 | /* save $9 - $15 so the inline exception code can manipulate them. */ | 196 | /* save $9 - $15 so the inline exception code can manipulate them. */ |
| 201 | subq $sp, 56, $sp | 197 | subq $sp, 64, $sp |
| 202 | .cfi_adjust_cfa_offset 56 | 198 | .cfi_adjust_cfa_offset 64 |
| 203 | stq $9, 0($sp) | 199 | stq $9, 0($sp) |
| 204 | stq $10, 8($sp) | 200 | stq $10, 8($sp) |
| 205 | stq $11, 16($sp) | 201 | stq $11, 16($sp) |
| @@ -214,7 +210,7 @@ CFI_START_OSF_FRAME entMM · 8 unmodified lines | |||
| 214 | .cfi_rel_offset $13, 32 | 210 | .cfi_rel_offset $13, 32 |
| 215 | .cfi_rel_offset $14, 40 | 211 | .cfi_rel_offset $14, 40 |
| 216 | .cfi_rel_offset $15, 48 | 212 | .cfi_rel_offset $15, 48 |
| 217 | addq $sp, 56, $19 | 213 | addq $sp, 64, $19 |
| 218 | /* handle the fault */ | 214 | /* handle the fault */ |
| 219 | lda $8, 0x3fff | 215 | lda $8, 0x3fff |
| 220 | bic $sp, $8, $8 | 216 | bic $sp, $8, $8 |
| @@ -227,7 +223,7 @@ CFI_START_OSF_FRAME entMM · 6 unmodified lines | |||
| 227 | ldq $13, 32($sp) | 223 | ldq $13, 32($sp) |
| 228 | ldq $14, 40($sp) | 224 | ldq $14, 40($sp) |
| 229 | ldq $15, 48($sp) | 225 | ldq $15, 48($sp) |
| 230 | addq $sp, 56, $sp | 226 | addq $sp, 64, $sp |
| 231 | .cfi_restore $9 | 227 | .cfi_restore $9 |
| 232 | .cfi_restore $10 | 228 | .cfi_restore $10 |
| 233 | .cfi_restore $11 | 229 | .cfi_restore $11 |
| @@ -235,7 +231,7 @@ CFI_START_OSF_FRAME entMM · 1 unmodified line | |||
| 235 | .cfi_restore $13 | 231 | .cfi_restore $13 |
| 236 | .cfi_restore $14 | 232 | .cfi_restore $14 |
| 237 | .cfi_restore $15 | 233 | .cfi_restore $15 |
| 238 | .cfi_adjust_cfa_offset -56 | 234 | .cfi_adjust_cfa_offset -64 |
| 239 | /* finish up the syscall as normal. */ | 235 | /* finish up the syscall as normal. */ |
| 240 | br ret_from_sys_call | 236 | br ret_from_sys_call |
| 241 | CFI_END_OSF_FRAME entMM | 237 | CFI_END_OSF_FRAME entMM |
| @@ -382,8 +378,8 @@ entUnaUser: · 140 unmodified lines | |||
| 382 | .cfi_restore $0 | 378 | .cfi_restore $0 |
| 383 | .cfi_adjust_cfa_offset -256 | 379 | .cfi_adjust_cfa_offset -256 |
| 384 | SAVE_ALL /* setup normal kernel stack */ | 380 | SAVE_ALL /* setup normal kernel stack */ |
| 385 | lda $sp, -56($sp) | 381 | lda $sp, -64($sp) |
| 386 | .cfi_adjust_cfa_offset 56 | 382 | .cfi_adjust_cfa_offset 64 |
| 387 | stq $9, 0($sp) | 383 | stq $9, 0($sp) |
| 388 | stq $10, 8($sp) | 384 | stq $10, 8($sp) |
| 389 | stq $11, 16($sp) | 385 | stq $11, 16($sp) |
| @@ -399,7 +395,7 @@ entUnaUser: · 9 unmodified lines | |||
| 399 | .cfi_rel_offset $14, 40 | 395 | .cfi_rel_offset $14, 40 |
| 400 | .cfi_rel_offset $15, 48 | 396 | .cfi_rel_offset $15, 48 |
| 401 | lda $8, 0x3fff | 397 | lda $8, 0x3fff |
| 402 | addq $sp, 56, $19 | 398 | addq $sp, 64, $19 |
| 403 | bic $sp, $8, $8 | 399 | bic $sp, $8, $8 |
| 404 | jsr $26, do_entUnaUser | 400 | jsr $26, do_entUnaUser |
| 405 | ldq $9, 0($sp) | 401 | ldq $9, 0($sp) |
| @@ -409,7 +405,7 @@ entUnaUser: · 3 unmodified lines | |||
| 409 | ldq $13, 32($sp) | 405 | ldq $13, 32($sp) |
| 410 | ldq $14, 40($sp) | 406 | ldq $14, 40($sp) |
| 411 | ldq $15, 48($sp) | 407 | ldq $15, 48($sp) |
| 412 | lda $sp, 56($sp) | 408 | lda $sp, 64($sp) |
| 413 | .cfi_restore $9 | 409 | .cfi_restore $9 |
| 414 | .cfi_restore $10 | 410 | .cfi_restore $10 |
| 415 | .cfi_restore $11 | 411 | .cfi_restore $11 |
| @@ -417,7 +413,7 @@ entUnaUser: · 1 unmodified line | |||
| 417 | .cfi_restore $13 | 413 | .cfi_restore $13 |
| 418 | .cfi_restore $14 | 414 | .cfi_restore $14 |
| 419 | .cfi_restore $15 | 415 | .cfi_restore $15 |
| 420 | .cfi_adjust_cfa_offset -56 | 416 | .cfi_adjust_cfa_offset -64 |
| 421 | br ret_from_sys_call | 417 | br ret_from_sys_call |
| 422 | CFI_END_OSF_FRAME entUna | 418 | CFI_END_OSF_FRAME entUna |
| 423 | 419 | ||
| @@ -1210,8 +1210,7 @@ SYSCALL_DEFINE1(old_adjtimex, struct timex32 __user *, txc_p) · 1209 unmodified lines | |||
| 1210 | return ret; | 1210 | return ret; |
| 1211 | } | 1211 | } |
| 1212 | 1212 | ||
| 1213 | /* Get an address range which is currently unmapped. Similar to the | 1213 | /* Get an address range which is currently unmapped. */ |
| 1214 | generic version except that we know how to honor ADDR_LIMIT_32BIT. */ | ||
| 1215 | 1214 | ||
| 1216 | static unsigned long | 1215 | static unsigned long |
| 1217 | arch_get_unmapped_area_1(unsigned long addr, unsigned long len, | 1216 | arch_get_unmapped_area_1(unsigned long addr, unsigned long len, |
| @@ -1230,13 +1229,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, · 12 unmodified lines | |||
| 1230 | unsigned long len, unsigned long pgoff, | 1229 | unsigned long len, unsigned long pgoff, |
| 1231 | unsigned long flags, vm_flags_t vm_flags) | 1230 | unsigned long flags, vm_flags_t vm_flags) |
| 1232 | { | 1231 | { |
| 1233 | unsigned long limit; | 1232 | unsigned long limit = TASK_SIZE; |
| 1234 | |||
| 1235 | /* "32 bit" actually means 31 bit, since pointers sign extend. */ | ||
| 1236 | if (current->personality & ADDR_LIMIT_32BIT) | ||
| 1237 | limit = 0x80000000; | ||
| 1238 | else | ||
| 1239 | limit = TASK_SIZE; | ||
| 1240 | 1233 | ||
| 1241 | if (len > limit) | 1234 | if (len > limit) |
| 1242 | return -ENOMEM; | 1235 | return -ENOMEM; |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/log2.h> | 13 | #include <linux/log2.h> |
| 14 | #include <linux/dma-map-ops.h> | 14 | #include <linux/dma-map-ops.h> |
| 15 | #include <linux/iommu-helper.h> | 15 | #include <linux/iommu-helper.h> |
| 16 | #include <linux/string_choices.h> | ||
| 16 | 17 | ||
| 17 | #include <asm/io.h> | 18 | #include <asm/io.h> |
| 18 | #include <asm/hwrpb.h> | 19 | #include <asm/hwrpb.h> |
| @@ -212,7 +213,7 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask) · 193 unmodified lines | |||
| 212 | 213 | ||
| 213 | /* If both conditions above are met, we are fine. */ | 214 | /* If both conditions above are met, we are fine. */ |
| 214 | DBGA("pci_dac_dma_supported %s from %ps\n", | 215 | DBGA("pci_dac_dma_supported %s from %ps\n", |
| 215 | ok ? "yes" : "no", __builtin_return_address(0)); | 216 | str_yes_no(ok), __builtin_return_address(0)); |
| 216 | 217 | ||
| 217 | return ok; | 218 | return ok; |
| 218 | } | 219 | } |
| @@ -649,7 +649,7 @@ s_reg_to_mem (unsigned long s_reg) · 648 unmodified lines | |||
| 649 | static int unauser_reg_offsets[32] = { | 649 | static int unauser_reg_offsets[32] = { |
| 650 | R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), | 650 | R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), |
| 651 | /* r9 ... r15 are stored in front of regs. */ | 651 | /* r9 ... r15 are stored in front of regs. */ |
| 652 | -56, -48, -40, -32, -24, -16, -8, | 652 | -64, -56, -48, -40, -32, -24, -16, /* padding at -8 */ |
| 653 | R(r16), R(r17), R(r18), | 653 | R(r16), R(r17), R(r18), |
| 654 | R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26), | 654 | R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26), |
| 655 | R(r27), R(r28), R(gp), | 655 | R(r27), R(r28), R(gp), |
| @@ -78,8 +78,8 @@ __load_new_mm_context(struct mm_struct *next_mm) · 77 unmodified lines | |||
| 78 | 78 | ||
| 79 | /* Macro for exception fixup code to access integer registers. */ | 79 | /* Macro for exception fixup code to access integer registers. */ |
| 80 | #define dpf_reg(r) \ | 80 | #define dpf_reg(r) \ |
| 81 | (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \ | 81 | (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-17 : \ |
| 82 | (r) <= 18 ? (r)+10 : (r)-10]) | 82 | (r) <= 18 ? (r)+11 : (r)-10]) |
| 83 | 83 | ||
| 84 | asmlinkage void | 84 | asmlinkage void |
| 85 | do_page_fault(unsigned long address, unsigned long mmcsr, | 85 | do_page_fault(unsigned long address, unsigned long mmcsr, |
| @@ -225,7 +225,6 @@ config ARM64 · 224 unmodified lines | |||
| 225 | select HAVE_FUNCTION_ERROR_INJECTION | 225 | select HAVE_FUNCTION_ERROR_INJECTION |
| 226 | select HAVE_FUNCTION_GRAPH_FREGS | 226 | select HAVE_FUNCTION_GRAPH_FREGS |
| 227 | select HAVE_FUNCTION_GRAPH_TRACER | 227 | select HAVE_FUNCTION_GRAPH_TRACER |
| 228 | select HAVE_FUNCTION_GRAPH_RETVAL | ||
| 229 | select HAVE_GCC_PLUGINS | 228 | select HAVE_GCC_PLUGINS |
| 230 | select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \ | 229 | select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \ |
| 231 | HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI | 230 | HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI |
| @@ -48,7 +48,11 @@ KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU) \ · 47 unmodified lines | |||
| 48 | KBUILD_CFLAGS += $(call cc-disable-warning, psabi) | 48 | KBUILD_CFLAGS += $(call cc-disable-warning, psabi) |
| 49 | KBUILD_AFLAGS += $(compat_vdso) | 49 | KBUILD_AFLAGS += $(compat_vdso) |
| 50 | 50 | ||
| 51 | ifeq ($(call test-ge, $(CONFIG_RUSTC_VERSION), 108500),y) | ||
| 52 | KBUILD_RUSTFLAGS += --target=aarch64-unknown-none-softfloat | ||
| 53 | else | ||
| 51 | KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon" | 54 | KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon" |
| 55 | endif | ||
| 52 | 56 | ||
| 53 | KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) | 57 | KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) |
| 54 | KBUILD_AFLAGS += $(call cc-option,-mabi=lp64) | 58 | KBUILD_AFLAGS += $(call cc-option,-mabi=lp64) |
| @@ -605,48 +605,6 @@ static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu) · 604 unmodified lines | |||
| 605 | __cpacr_to_cptr_set(clr, set));\ | 605 | __cpacr_to_cptr_set(clr, set));\ |
| 606 | } while (0) | 606 | } while (0) |
| 607 | 607 | ||
| 608 | static __always_inline void kvm_write_cptr_el2(u64 val) | ||
| 609 | { | ||
| 610 | if (has_vhe() || has_hvhe()) | ||
| 611 | write_sysreg(val, cpacr_el1); | ||
| 612 | else | ||
| 613 | write_sysreg(val, cptr_el2); | ||
| 614 | } | ||
| 615 | |||
| 616 | /* Resets the value of cptr_el2 when returning to the host. */ | ||
| 617 | static __always_inline void __kvm_reset_cptr_el2(struct kvm *kvm) | ||
| 618 | { | ||
| 619 | u64 val; | ||
| 620 | |||
| 621 | if (has_vhe()) { | ||
| 622 | val = (CPACR_EL1_FPEN | CPACR_EL1_ZEN_EL1EN); | ||
| 623 | if (cpus_have_final_cap(ARM64_SME)) | ||
| 624 | val |= CPACR_EL1_SMEN_EL1EN; | ||
| 625 | } else if (has_hvhe()) { | ||
| 626 | val = CPACR_EL1_FPEN; | ||
| 627 | |||
| 628 | if (!kvm_has_sve(kvm) || !guest_owns_fp_regs()) | ||
| 629 | val |= CPACR_EL1_ZEN; | ||
| 630 | if (cpus_have_final_cap(ARM64_SME)) | ||
| 631 | val |= CPACR_EL1_SMEN; | ||
| 632 | } else { | ||
| 633 | val = CPTR_NVHE_EL2_RES1; | ||
| 634 | |||
| 635 | if (kvm_has_sve(kvm) && guest_owns_fp_regs()) | ||
| 636 | val |= CPTR_EL2_TZ; | ||
| 637 | if (!cpus_have_final_cap(ARM64_SME)) | ||
| 638 | val |= CPTR_EL2_TSM; | ||
| 639 | } | ||
| 640 | |||
| 641 | kvm_write_cptr_el2(val); | ||
| 642 | } | ||
| 643 | |||
| 644 | #ifdef __KVM_NVHE_HYPERVISOR__ | ||
| 645 | #define kvm_reset_cptr_el2(v) __kvm_reset_cptr_el2(kern_hyp_va((v)->kvm)) | ||
| 646 | #else | ||
| 647 | #define kvm_reset_cptr_el2(v) __kvm_reset_cptr_el2((v)->kvm) | ||
| 648 | #endif | ||
| 649 | |||
| 650 | /* | 608 | /* |
| 651 | * Returns a 'sanitised' view of CPTR_EL2, translating from nVHE to the VHE | 609 | * Returns a 'sanitised' view of CPTR_EL2, translating from nVHE to the VHE |
| 652 | * format if E2H isn't set. | 610 | * format if E2H isn't set. |
| @@ -100,7 +100,7 @@ static inline void push_hyp_memcache(struct kvm_hyp_memcache *mc, · 99 unmodified lines | |||
| 100 | static inline void *pop_hyp_memcache(struct kvm_hyp_memcache *mc, | 100 | static inline void *pop_hyp_memcache(struct kvm_hyp_memcache *mc, |
| 101 | void *(*to_va)(phys_addr_t phys)) | 101 | void *(*to_va)(phys_addr_t phys)) |
| 102 | { | 102 | { |
| 103 | phys_addr_t *p = to_va(mc->head); | 103 | phys_addr_t *p = to_va(mc->head & PAGE_MASK); |
| 104 | 104 | ||
| 105 | if (!mc->nr_pages) | 105 | if (!mc->nr_pages) |
| 106 | return NULL; | 106 | return NULL; |
| @@ -615,8 +615,6 @@ struct cpu_sve_state { · 508 unmodified lines | |||
| 615 | struct kvm_host_data { | 615 | struct kvm_host_data { |
| 616 | #define KVM_HOST_DATA_FLAG_HAS_SPE 0 | 616 | #define KVM_HOST_DATA_FLAG_HAS_SPE 0 |
| 617 | #define KVM_HOST_DATA_FLAG_HAS_TRBE 1 | 617 | #define KVM_HOST_DATA_FLAG_HAS_TRBE 1 |
| 618 | #define KVM_HOST_DATA_FLAG_HOST_SVE_ENABLED 2 | ||
| 619 | #define KVM_HOST_DATA_FLAG_HOST_SME_ENABLED 3 | ||
| 620 | #define KVM_HOST_DATA_FLAG_TRBE_ENABLED 4 | 618 | #define KVM_HOST_DATA_FLAG_TRBE_ENABLED 4 |
| 621 | #define KVM_HOST_DATA_FLAG_EL1_TRACING_CONFIGURED 5 | 619 | #define KVM_HOST_DATA_FLAG_EL1_TRACING_CONFIGURED 5 |
| 622 | unsigned long flags; | 620 | unsigned long flags; |
| @@ -624,23 +622,13 @@ struct kvm_host_data { · 1 unmodified line | |||
| 624 | struct kvm_cpu_context host_ctxt; | 622 | struct kvm_cpu_context host_ctxt; |
| 625 | 623 | ||
| 626 | /* | 624 | /* |
| 627 | * All pointers in this union are hyp VA. | 625 | * Hyp VA. |
| 628 | * sve_state is only used in pKVM and if system_supports_sve(). | 626 | * sve_state is only used in pKVM and if system_supports_sve(). |
| 629 | */ | 627 | */ |
| 630 | union { | 628 | struct cpu_sve_state *sve_state; |
| 631 | struct user_fpsimd_state *fpsimd_state; | 629 | |
| 632 | struct cpu_sve_state *sve_state; | 630 | /* Used by pKVM only. */ |
| 633 | }; | 631 | u64 fpmr; |
| 634 | |||
| 635 | union { | ||
| 636 | /* HYP VA pointer to the host storage for FPMR */ | ||
| 637 | u64 *fpmr_ptr; | ||
| 638 | /* | ||
| 639 | * Used by pKVM only, as it needs to provide storage | ||
| 640 | * for the host | ||
| 641 | */ | ||
| 642 | u64 fpmr; | ||
| 643 | }; | ||
| 644 | 632 | ||
| 645 | /* Ownership of the FP regs */ | 633 | /* Ownership of the FP regs */ |
| 646 | enum { | 634 | enum { |
| @@ -101,16 +101,18 @@ int populate_cache_leaves(unsigned int cpu) · 100 unmodified lines | |||
| 101 | unsigned int level, idx; | 101 | unsigned int level, idx; |
| 102 | enum cache_type type; | 102 | enum cache_type type; |
| 103 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | 103 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); |
| 104 | struct cacheinfo *this_leaf = this_cpu_ci->info_list; | 104 | struct cacheinfo *infos = this_cpu_ci->info_list; |
| 105 | 105 | ||
| 106 | for (idx = 0, level = 1; level <= this_cpu_ci->num_levels && | 106 | for (idx = 0, level = 1; level <= this_cpu_ci->num_levels && |
| 107 | idx < this_cpu_ci->num_leaves; idx++, level++) { | 107 | idx < this_cpu_ci->num_leaves; level++) { |
| 108 | type = get_cache_type(level); | 108 | type = get_cache_type(level); |
| 109 | if (type == CACHE_TYPE_SEPARATE) { | 109 | if (type == CACHE_TYPE_SEPARATE) { |
| 110 | ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level); | 110 | if (idx + 1 >= this_cpu_ci->num_leaves) |
| 111 | ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level); | 111 | break; |
| 112 | ci_leaf_init(&infos[idx++], CACHE_TYPE_DATA, level); | ||
| 113 | ci_leaf_init(&infos[idx++], CACHE_TYPE_INST, level); | ||
| 112 | } else { | 114 | } else { |
| 113 | ci_leaf_init(this_leaf++, type, level); | 115 | ci_leaf_init(&infos[idx++], type, level); |
| 114 | } | 116 | } |
| 115 | } | 117 | } |
| 116 | return 0; | 118 | return 0; |
| @@ -3091,6 +3091,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { · 3090 unmodified lines | |||
| 3091 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM, CAP_HWCAP, KERNEL_HWCAP_FLAGM), | 3091 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM, CAP_HWCAP, KERNEL_HWCAP_FLAGM), |
| 3092 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM2, CAP_HWCAP, KERNEL_HWCAP_FLAGM2), | 3092 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM2, CAP_HWCAP, KERNEL_HWCAP_FLAGM2), |
| 3093 | HWCAP_CAP(ID_AA64ISAR0_EL1, RNDR, IMP, CAP_HWCAP, KERNEL_HWCAP_RNG), | 3093 | HWCAP_CAP(ID_AA64ISAR0_EL1, RNDR, IMP, CAP_HWCAP, KERNEL_HWCAP_RNG), |
| 3094 | HWCAP_CAP(ID_AA64ISAR3_EL1, FPRCVT, IMP, CAP_HWCAP, KERNEL_HWCAP_FPRCVT), | ||
| 3094 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, IMP, CAP_HWCAP, KERNEL_HWCAP_FP), | 3095 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, IMP, CAP_HWCAP, KERNEL_HWCAP_FP), |
| 3095 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, FP16, CAP_HWCAP, KERNEL_HWCAP_FPHP), | 3096 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, FP16, CAP_HWCAP, KERNEL_HWCAP_FPHP), |
| 3096 | HWCAP_CAP(ID_AA64PFR0_EL1, AdvSIMD, IMP, CAP_HWCAP, KERNEL_HWCAP_ASIMD), | 3097 | HWCAP_CAP(ID_AA64PFR0_EL1, AdvSIMD, IMP, CAP_HWCAP, KERNEL_HWCAP_ASIMD), |
| @@ -3180,8 +3181,6 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { · 83 unmodified lines | |||
| 3180 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8FMA), | 3181 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8FMA), |
| 3181 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP4), | 3182 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP4), |
| 3182 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP2), | 3183 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP2), |
| 3183 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8MM8, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8MM8), | ||
| 3184 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8MM4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8MM4), | ||
| 3185 | HWCAP_CAP(ID_AA64SMFR0_EL1, SBitPerm, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SBITPERM), | 3184 | HWCAP_CAP(ID_AA64SMFR0_EL1, SBitPerm, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SBITPERM), |
| 3186 | HWCAP_CAP(ID_AA64SMFR0_EL1, AES, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_AES), | 3185 | HWCAP_CAP(ID_AA64SMFR0_EL1, AES, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_AES), |
| 3187 | HWCAP_CAP(ID_AA64SMFR0_EL1, SFEXPA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SFEXPA), | 3186 | HWCAP_CAP(ID_AA64SMFR0_EL1, SFEXPA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SFEXPA), |
| @@ -3192,6 +3191,8 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { · 4 unmodified lines | |||
| 3192 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_F8FMA), | 3191 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_F8FMA), |
| 3193 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP4), | 3192 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP4), |
| 3194 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP2), | 3193 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP2), |
| 3194 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8MM8, IMP, CAP_HWCAP, KERNEL_HWCAP_F8MM8), | ||
| 3195 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8MM4, IMP, CAP_HWCAP, KERNEL_HWCAP_F8MM4), | ||
| 3195 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E4M3, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E4M3), | 3196 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E4M3, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E4M3), |
| 3196 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E5M2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E5M2), | 3197 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E5M2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E5M2), |
| 3197 | #ifdef CONFIG_ARM64_POE | 3198 | #ifdef CONFIG_ARM64_POE |
| @@ -1694,31 +1694,6 @@ void fpsimd_signal_preserve_current_state(void) · 1693 unmodified lines | |||
| 1694 | sve_to_fpsimd(current); | 1694 | sve_to_fpsimd(current); |
| 1695 | } | 1695 | } |
| 1696 | 1696 | ||
| 1697 | /* | ||
| 1698 | * Called by KVM when entering the guest. | ||
| 1699 | */ | ||
| 1700 | void fpsimd_kvm_prepare(void) | ||
| 1701 | { | ||
| 1702 | if (!system_supports_sve()) | ||
| 1703 | return; | ||
| 1704 | |||
| 1705 | /* | ||
| 1706 | * KVM does not save host SVE state since we can only enter | ||
| 1707 | * the guest from a syscall so the ABI means that only the | ||
| 1708 | * non-saved SVE state needs to be saved. If we have left | ||
| 1709 | * SVE enabled for performance reasons then update the task | ||
| 1710 | * state to be FPSIMD only. | ||
| 1711 | */ | ||
| 1712 | get_cpu_fpsimd_context(); | ||
| 1713 | |||
| 1714 | if (test_and_clear_thread_flag(TIF_SVE)) { | ||
| 1715 | sve_to_fpsimd(current); | ||
| 1716 | current->thread.fp_type = FP_STATE_FPSIMD; | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | put_cpu_fpsimd_context(); | ||
| 1720 | } | ||
| 1721 | |||
| 1722 | /* | 1697 | /* |
| 1723 | * Associate current's FPSIMD context with this cpu | 1698 | * Associate current's FPSIMD context with this cpu |
| 1724 | * The caller must have ownership of the cpu FPSIMD context before calling | 1699 | * The caller must have ownership of the cpu FPSIMD context before calling |
| @@ -194,12 +194,19 @@ static void amu_fie_setup(const struct cpumask *cpus) · 193 unmodified lines | |||
| 194 | int cpu; | 194 | int cpu; |
| 195 | 195 | ||
| 196 | /* We are already set since the last insmod of cpufreq driver */ | 196 | /* We are already set since the last insmod of cpufreq driver */ |
| 197 | if (unlikely(cpumask_subset(cpus, amu_fie_cpus))) | 197 | if (cpumask_available(amu_fie_cpus) && |
| 198 | unlikely(cpumask_subset(cpus, amu_fie_cpus))) | ||
| 198 | return; | 199 | return; |
| 199 | 200 | ||
| 200 | for_each_cpu(cpu, cpus) { | 201 | for_each_cpu(cpu, cpus) |
| 201 | if (!freq_counters_valid(cpu)) | 202 | if (!freq_counters_valid(cpu)) |
| 202 | return; | 203 | return; |
| 204 | |||
| 205 | if (!cpumask_available(amu_fie_cpus) && | ||
| 206 | !zalloc_cpumask_var(&amu_fie_cpus, GFP_KERNEL)) { | ||
| 207 | WARN_ONCE(1, "Failed to allocate FIE cpumask for CPUs[%*pbl]\n", | ||
| 208 | cpumask_pr_args(cpus)); | ||
| 209 | return; | ||
| 203 | } | 210 | } |
| 204 | 211 | ||
| 205 | cpumask_or(amu_fie_cpus, amu_fie_cpus, cpus); | 212 | cpumask_or(amu_fie_cpus, amu_fie_cpus, cpus); |
| @@ -237,17 +244,8 @@ static struct notifier_block init_amu_fie_notifier = { · 31 unmodified lines | |||
| 237 | 244 | ||
| 238 | static int __init init_amu_fie(void) | 245 | static int __init init_amu_fie(void) |
| 239 | { | 246 | { |
| 240 | int ret; | 247 | return cpufreq_register_notifier(&init_amu_fie_notifier, |
| 241 | |||
| 242 | if (!zalloc_cpumask_var(&amu_fie_cpus, GFP_KERNEL)) | ||
| 243 | return -ENOMEM; | ||
| 244 | |||
| 245 | ret = cpufreq_register_notifier(&init_amu_fie_notifier, | ||
| 246 | CPUFREQ_POLICY_NOTIFIER); | 248 | CPUFREQ_POLICY_NOTIFIER); |
| 247 | if (ret) | ||
| 248 | free_cpumask_var(amu_fie_cpus); | ||
| 249 | |||
| 250 | return ret; | ||
| 251 | } | 249 | } |
| 252 | core_initcall(init_amu_fie); | 250 | core_initcall(init_amu_fie); |
| 253 | 251 | ||
| @@ -41,6 +41,7 @@ SECTIONS · 40 unmodified lines | |||
| 41 | */ | 41 | */ |
| 42 | /DISCARD/ : { | 42 | /DISCARD/ : { |
| 43 | *(.note.GNU-stack .note.gnu.property) | 43 | *(.note.GNU-stack .note.gnu.property) |
| 44 | *(.ARM.attributes) | ||
| 44 | } | 45 | } |
| 45 | .note : { *(.note.*) } :text :note | 46 | .note : { *(.note.*) } :text :note |
| 46 | 47 | ||
| @@ -162,6 +162,7 @@ SECTIONS · 161 unmodified lines | |||
| 162 | /DISCARD/ : { | 162 | /DISCARD/ : { |
| 163 | *(.interp .dynamic) | 163 | *(.interp .dynamic) |
| 164 | *(.dynsym .dynstr .hash .gnu.hash) | 164 | *(.dynsym .dynstr .hash .gnu.hash) |
| 165 | *(.ARM.attributes) | ||
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | . = KIMAGE_VADDR; | 168 | . = KIMAGE_VADDR; |
| @@ -447,21 +447,19 @@ static void kvm_timer_update_status(struct arch_timer_context *ctx, bool level) · 446 unmodified lines | |||
| 447 | static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level, | 447 | static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level, |
| 448 | struct arch_timer_context *timer_ctx) | 448 | struct arch_timer_context *timer_ctx) |
| 449 | { | 449 | { |
| 450 | int ret; | ||
| 451 | |||
| 452 | kvm_timer_update_status(timer_ctx, new_level); | 450 | kvm_timer_update_status(timer_ctx, new_level); |
| 453 | 451 | ||
| 454 | timer_ctx->irq.level = new_level; | 452 | timer_ctx->irq.level = new_level; |
| 455 | trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_irq(timer_ctx), | 453 | trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_irq(timer_ctx), |
| 456 | timer_ctx->irq.level); | 454 | timer_ctx->irq.level); |
| 457 | 455 | ||
| 458 | if (!userspace_irqchip(vcpu->kvm)) { | 456 | if (userspace_irqchip(vcpu->kvm)) |
| 459 | ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu, | 457 | return; |
| 460 | timer_irq(timer_ctx), | 458 | |
| 461 | timer_ctx->irq.level, | 459 | kvm_vgic_inject_irq(vcpu->kvm, vcpu, |
| 462 | timer_ctx); | 460 | timer_irq(timer_ctx), |
| 463 | WARN_ON(ret); | 461 | timer_ctx->irq.level, |
| 464 | } | 462 | timer_ctx); |
| 465 | } | 463 | } |
| 466 | 464 | ||
| 467 | /* Only called for a fully emulated timer */ | 465 | /* Only called for a fully emulated timer */ |
| @@ -471,10 +469,8 @@ static void timer_emulate(struct arch_timer_context *ctx) · 3 unmodified lines | |||
| 471 | 469 | ||
| 472 | trace_kvm_timer_emulate(ctx, should_fire); | 470 | trace_kvm_timer_emulate(ctx, should_fire); |
| 473 | 471 | ||
| 474 | if (should_fire != ctx->irq.level) { | 472 | if (should_fire != ctx->irq.level) |
| 475 | kvm_timer_update_irq(ctx->vcpu, should_fire, ctx); | 473 | kvm_timer_update_irq(ctx->vcpu, should_fire, ctx); |
| 476 | return; | ||
| 477 | } | ||
| 478 | 474 | ||
| 479 | kvm_timer_update_status(ctx, should_fire); | 475 | kvm_timer_update_status(ctx, should_fire); |
| 480 | 476 | ||
| @@ -761,21 +757,6 @@ static void kvm_timer_vcpu_load_nested_switch(struct kvm_vcpu *vcpu, · 280 unmodified lines | |||
| 761 | timer_irq(map->direct_ptimer), | 757 | timer_irq(map->direct_ptimer), |
| 762 | &arch_timer_irq_ops); | 758 | &arch_timer_irq_ops); |
| 763 | WARN_ON_ONCE(ret); | 759 | WARN_ON_ONCE(ret); |
| 764 | |||
| 765 | /* | ||
| 766 | * The virtual offset behaviour is "interesting", as it | ||
| 767 | * always applies when HCR_EL2.E2H==0, but only when | ||
| 768 | * accessed from EL1 when HCR_EL2.E2H==1. So make sure we | ||
| 769 | * track E2H when putting the HV timer in "direct" mode. | ||
| 770 | */ | ||
| 771 | if (map->direct_vtimer == vcpu_hvtimer(vcpu)) { | ||
| 772 | struct arch_timer_offset *offs = &map->direct_vtimer->offset; | ||
| 773 | |||
| 774 | if (vcpu_el2_e2h_is_set(vcpu)) | ||
| 775 | offs->vcpu_offset = NULL; | ||
| 776 | else | ||
| 777 | offs->vcpu_offset = &__vcpu_sys_reg(vcpu, CNTVOFF_EL2); | ||
| 778 | } | ||
| 779 | } | 760 | } |
| 780 | } | 761 | } |
| 781 | 762 | ||
| @@ -976,31 +957,21 @@ void kvm_timer_sync_nested(struct kvm_vcpu *vcpu) · 194 unmodified lines | |||
| 976 | * which allows trapping of the timer registers even with NV2. | 957 | * which allows trapping of the timer registers even with NV2. |
| 977 | * Still, this is still worse than FEAT_NV on its own. Meh. | 958 | * Still, this is still worse than FEAT_NV on its own. Meh. |
| 978 | */ | 959 | */ |
| 979 | if (!vcpu_el2_e2h_is_set(vcpu)) { | 960 | if (!cpus_have_final_cap(ARM64_HAS_ECV)) { |
| 980 | if (cpus_have_final_cap(ARM64_HAS_ECV)) | ||
| 981 | return; | ||
| 982 | |||
| 983 | /* | ||
| 984 | * A non-VHE guest hypervisor doesn't have any direct access | ||
| 985 | * to its timers: the EL2 registers trap (and the HW is | ||
| 986 | * fully emulated), while the EL0 registers access memory | ||
| 987 | * despite the access being notionally direct. Boo. | ||
| 988 | * | ||
| 989 | * We update the hardware timer registers with the | ||
| 990 | * latest value written by the guest to the VNCR page | ||
| 991 | * and let the hardware take care of the rest. | ||
| 992 | */ | ||
| 993 | write_sysreg_el0(__vcpu_sys_reg(vcpu, CNTV_CTL_EL0), SYS_CNTV_CTL); | ||
| 994 | write_sysreg_el0(__vcpu_sys_reg(vcpu, CNTV_CVAL_EL0), SYS_CNTV_CVAL); | ||
| 995 | write_sysreg_el0(__vcpu_sys_reg(vcpu, CNTP_CTL_EL0), SYS_CNTP_CTL); | ||
| 996 | write_sysreg_el0(__vcpu_sys_reg(vcpu, CNTP_CVAL_EL0), SYS_CNTP_CVAL); | ||
| 997 | } else { | ||
| 998 | /* | 961 | /* |
| 999 | * For a VHE guest hypervisor, the EL2 state is directly | 962 | * For a VHE guest hypervisor, the EL2 state is directly |
| 1000 | * stored in the host EL1 timers, while the emulated EL0 | 963 | * stored in the host EL1 timers, while the emulated EL1 |
| 1001 | * state is stored in the VNCR page. The latter could have | 964 | * state is stored in the VNCR page. The latter could have |
| 1002 | * been updated behind our back, and we must reset the | 965 | * been updated behind our back, and we must reset the |
| 1003 | * emulation of the timers. | 966 | * emulation of the timers. |
| 967 | * | ||
| 968 | * A non-VHE guest hypervisor doesn't have any direct access | ||
| 969 | * to its timers: the EL2 registers trap despite being | ||
| 970 | * notionally direct (we use the EL1 HW, as for VHE), while | ||
| 971 | * the EL1 registers access memory. | ||
| 972 | * | ||
| 973 | * In both cases, process the emulated timers on each guest | ||
| 974 | * exit. Boo. | ||
| 1004 | */ | 975 | */ |
| 1005 | struct timer_map map; | 976 | struct timer_map map; |
| 1006 | get_timer_map(vcpu, &map); | 977 | get_timer_map(vcpu, &map); |
| @@ -2290,6 +2290,19 @@ static int __init init_subsystems(void) · 2289 unmodified lines | |||
| 2290 | break; | 2290 | break; |
| 2291 | case -ENODEV: | 2291 | case -ENODEV: |
| 2292 | case -ENXIO: | 2292 | case -ENXIO: |
| 2293 | /* | ||
| 2294 | * No VGIC? No pKVM for you. | ||
| 2295 | * | ||
| 2296 | * Protected mode assumes that VGICv3 is present, so no point | ||
| 2297 | * in trying to hobble along if vgic initialization fails. | ||
| 2298 | */ | ||
| 2299 | if (is_protected_kvm_enabled()) | ||
| 2300 | goto out; | ||
| 2301 | |||
| 2302 | /* | ||
| 2303 | * Otherwise, userspace could choose to implement a GIC for its | ||
| 2304 | * guest on non-cooperative hardware. | ||
| 2305 | */ | ||
| 2293 | vgic_present = false; | 2306 | vgic_present = false; |
| 2294 | err = 0; | 2307 | err = 0; |
| 2295 | break; | 2308 | break; |
| @@ -2400,6 +2413,13 @@ static void kvm_hyp_init_symbols(void) · 104 unmodified lines | |||
| 2400 | kvm_nvhe_sym(id_aa64smfr0_el1_sys_val) = read_sanitised_ftr_reg(SYS_ID_AA64SMFR0_EL1); | 2413 | kvm_nvhe_sym(id_aa64smfr0_el1_sys_val) = read_sanitised_ftr_reg(SYS_ID_AA64SMFR0_EL1); |
| 2401 | kvm_nvhe_sym(__icache_flags) = __icache_flags; | 2414 | kvm_nvhe_sym(__icache_flags) = __icache_flags; |
| 2402 | kvm_nvhe_sym(kvm_arm_vmid_bits) = kvm_arm_vmid_bits; | 2415 | kvm_nvhe_sym(kvm_arm_vmid_bits) = kvm_arm_vmid_bits; |
| 2416 | |||
| 2417 | /* | ||
| 2418 | * Flush entire BSS since part of its data containing init symbols is read | ||
| 2419 | * while the MMU is off. | ||
| 2420 | */ | ||
| 2421 | kvm_flush_dcache_to_poc(kvm_ksym_ref(__hyp_bss_start), | ||
| 2422 | kvm_ksym_ref(__hyp_bss_end) - kvm_ksym_ref(__hyp_bss_start)); | ||
| 2403 | } | 2423 | } |
| 2404 | 2424 | ||
| 2405 | static int __init kvm_hyp_init_protection(u32 hyp_va_bits) | 2425 | static int __init kvm_hyp_init_protection(u32 hyp_va_bits) |
| @@ -2461,14 +2481,6 @@ static void finalize_init_hyp_mode(void) · 55 unmodified lines | |||
| 2461 | per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state = | 2481 | per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state = |
| 2462 | kern_hyp_va(sve_state); | 2482 | kern_hyp_va(sve_state); |
| 2463 | } | 2483 | } |
| 2464 | } else { | ||
| 2465 | for_each_possible_cpu(cpu) { | ||
| 2466 | struct user_fpsimd_state *fpsimd_state; | ||
| 2467 | |||
| 2468 | fpsimd_state = &per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->host_ctxt.fp_regs; | ||
| 2469 | per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->fpsimd_state = | ||
| 2470 | kern_hyp_va(fpsimd_state); | ||
| 2471 | } | ||
| 2472 | } | 2484 | } |
| 2473 | } | 2485 | } |
| 2474 | 2486 | ||
| @@ -54,50 +54,18 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) · 53 unmodified lines | |||
| 54 | if (!system_supports_fpsimd()) | 54 | if (!system_supports_fpsimd()) |
| 55 | return; | 55 | return; |
| 56 | 56 | ||
| 57 | fpsimd_kvm_prepare(); | ||
| 58 | |||
| 59 | /* | 57 | /* |
| 60 | * We will check TIF_FOREIGN_FPSTATE just before entering the | 58 | * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such |
| 61 | * guest in kvm_arch_vcpu_ctxflush_fp() and override this to | 59 | * that the host kernel is responsible for restoring this state upon |
| 62 | * FP_STATE_FREE if the flag set. | 60 | * return to userspace, and the hyp code doesn't need to save anything. |
| 61 | * | ||
| 62 | * When the host may use SME, fpsimd_save_and_flush_cpu_state() ensures | ||
| 63 | * that PSTATE.{SM,ZA} == {0,0}. | ||
| 63 | */ | 64 | */ |
| 64 | *host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED; | 65 | fpsimd_save_and_flush_cpu_state(); |
| 65 | *host_data_ptr(fpsimd_state) = kern_hyp_va(¤t->thread.uw.fpsimd_state); | 66 | *host_data_ptr(fp_owner) = FP_STATE_FREE; |
| 66 | *host_data_ptr(fpmr_ptr) = kern_hyp_va(¤t->thread.uw.fpmr); | ||
| 67 | |||
| 68 | host_data_clear_flag(HOST_SVE_ENABLED); | ||
| 69 | if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN) | ||
| 70 | host_data_set_flag(HOST_SVE_ENABLED); | ||
| 71 | |||
| 72 | if (system_supports_sme()) { | ||
| 73 | host_data_clear_flag(HOST_SME_ENABLED); | ||
| 74 | if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN) | ||
| 75 | host_data_set_flag(HOST_SME_ENABLED); | ||
| 76 | |||
| 77 | /* | ||
| 78 | * If PSTATE.SM is enabled then save any pending FP | ||
| 79 | * state and disable PSTATE.SM. If we leave PSTATE.SM | ||
| 80 | * enabled and the guest does not enable SME via | ||
| 81 | * CPACR_EL1.SMEN then operations that should be valid | ||
| 82 | * may generate SME traps from EL1 to EL1 which we | ||
| 83 | * can't intercept and which would confuse the guest. | ||
| 84 | * | ||
| 85 | * Do the same for PSTATE.ZA in the case where there | ||
| 86 | * is state in the registers which has not already | ||
| 87 | * been saved, this is very unlikely to happen. | ||
| 88 | */ | ||
| 89 | if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) { | ||
| 90 | *host_data_ptr(fp_owner) = FP_STATE_FREE; | ||
| 91 | fpsimd_save_and_flush_cpu_state(); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | 67 | ||
| 95 | /* | 68 | WARN_ON_ONCE(system_supports_sme() && read_sysreg_s(SYS_SVCR)); |
| 96 | * If normal guests gain SME support, maintain this behavior for pKVM | ||
| 97 | * guests, which don't support SME. | ||
| 98 | */ | ||
| 99 | WARN_ON(is_protected_kvm_enabled() && system_supports_sme() && | ||
| 100 | read_sysreg_s(SYS_SVCR)); | ||
| 101 | } | 69 | } |
| 102 | 70 | ||
| 103 | /* | 71 | /* |
| @@ -162,52 +130,7 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) · 58 unmodified lines | |||
| 162 | 130 | ||
| 163 | local_irq_save(flags); | 131 | local_irq_save(flags); |
| 164 | 132 | ||
| 165 | /* | ||
| 166 | * If we have VHE then the Hyp code will reset CPACR_EL1 to | ||
| 167 | * the default value and we need to reenable SME. | ||
| 168 | */ | ||
| 169 | if (has_vhe() && system_supports_sme()) { | ||
| 170 | /* Also restore EL0 state seen on entry */ | ||
| 171 | if (host_data_test_flag(HOST_SME_ENABLED)) | ||
| 172 | sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_SMEN); | ||
| 173 | else | ||
| 174 | sysreg_clear_set(CPACR_EL1, | ||
| 175 | CPACR_EL1_SMEN_EL0EN, | ||
| 176 | CPACR_EL1_SMEN_EL1EN); | ||
| 177 | isb(); | ||
| 178 | } | ||
| 179 | |||
| 180 | if (guest_owns_fp_regs()) { | 133 | if (guest_owns_fp_regs()) { |
| 181 | if (vcpu_has_sve(vcpu)) { | ||
| 182 | u64 zcr = read_sysreg_el1(SYS_ZCR); | ||
| 183 | |||
| 184 | /* | ||
| 185 | * If the vCPU is in the hyp context then ZCR_EL1 is | ||
| 186 | * loaded with its vEL2 counterpart. | ||
| 187 | */ | ||
| 188 | __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr; | ||
| 189 | |||
| 190 | /* | ||
| 191 | * Restore the VL that was saved when bound to the CPU, | ||
| 192 | * which is the maximum VL for the guest. Because the | ||
| 193 | * layout of the data when saving the sve state depends | ||
| 194 | * on the VL, we need to use a consistent (i.e., the | ||
| 195 | * maximum) VL. | ||
| 196 | * Note that this means that at guest exit ZCR_EL1 is | ||
| 197 | * not necessarily the same as on guest entry. | ||
| 198 | * | ||
| 199 | * ZCR_EL2 holds the guest hypervisor's VL when running | ||
| 200 | * a nested guest, which could be smaller than the | ||
| 201 | * max for the vCPU. Similar to above, we first need to | ||
| 202 | * switch to a VL consistent with the layout of the | ||
| 203 | * vCPU's SVE state. KVM support for NV implies VHE, so | ||
| 204 | * using the ZCR_EL1 alias is safe. | ||
| 205 | */ | ||
| 206 | if (!has_vhe() || (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu))) | ||
| 207 | sve_cond_update_zcr_vq(vcpu_sve_max_vq(vcpu) - 1, | ||
| 208 | SYS_ZCR_EL1); | ||
| 209 | } | ||
| 210 | |||
| 211 | /* | 134 | /* |
| 212 | * Flush (save and invalidate) the fpsimd/sve state so that if | 135 | * Flush (save and invalidate) the fpsimd/sve state so that if |
| 213 | * the host tries to use fpsimd/sve, it's not using stale data | 136 | * the host tries to use fpsimd/sve, it's not using stale data |
| @@ -219,18 +142,6 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) · 5 unmodified lines | |||
| 219 | * when needed. | 142 | * when needed. |
| 220 | */ | 143 | */ |
| 221 | fpsimd_save_and_flush_cpu_state(); | 144 | fpsimd_save_and_flush_cpu_state(); |
| 222 | } else if (has_vhe() && system_supports_sve()) { | ||
| 223 | /* | ||
| 224 | * The FPSIMD/SVE state in the CPU has not been touched, and we | ||
| 225 | * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been | ||
| 226 | * reset by kvm_reset_cptr_el2() in the Hyp code, disabling SVE | ||
| 227 | * for EL0. To avoid spurious traps, restore the trap state | ||
| 228 | * seen by kvm_arch_vcpu_load_fp(): | ||
| 229 | */ | ||
| 230 | if (host_data_test_flag(HOST_SVE_ENABLED)) | ||
| 231 | sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN); | ||
| 232 | else | ||
| 233 | sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0); | ||
| 234 | } | 145 | } |
| 235 | 146 | ||
| 236 | local_irq_restore(flags); | 147 | local_irq_restore(flags); |
| @@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN · 43 unmodified lines | |||
| 44 | alternative_else_nop_endif | 44 | alternative_else_nop_endif |
| 45 | mrs x1, isr_el1 | 45 | mrs x1, isr_el1 |
| 46 | cbz x1, 1f | 46 | cbz x1, 1f |
| 47 | |||
| 48 | // Ensure that __guest_enter() always provides a context | ||
| 49 | // synchronization event so that callers don't need ISBs for anything | ||
| 50 | // that would usually be synchonized by the ERET. | ||
| 51 | isb | ||
| 47 | mov x0, #ARM_EXCEPTION_IRQ | 52 | mov x0, #ARM_EXCEPTION_IRQ |
| 48 | ret | 53 | ret |
| 49 | 54 | ||
| @@ -326,7 +326,7 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu) · 325 unmodified lines | |||
| 326 | return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault); | 326 | return __get_fault_info(vcpu->arch.fault.esr_el2, &vcpu->arch.fault); |
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | static bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code) | 329 | static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 330 | { | 330 | { |
| 331 | *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR); | 331 | *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR); |
| 332 | arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2); | 332 | arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2); |
| @@ -375,7 +375,87 @@ static inline void __hyp_sve_save_host(void) · 42 unmodified lines | |||
| 375 | true); | 375 | true); |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu); | 378 | static inline void fpsimd_lazy_switch_to_guest(struct kvm_vcpu *vcpu) |
| 379 | { | ||
| 380 | u64 zcr_el1, zcr_el2; | ||
| 381 | |||
| 382 | if (!guest_owns_fp_regs()) | ||
| 383 | return; | ||
| 384 | |||
| 385 | if (vcpu_has_sve(vcpu)) { | ||
| 386 | /* A guest hypervisor may restrict the effective max VL. */ | ||
| 387 | if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) | ||
| 388 | zcr_el2 = __vcpu_sys_reg(vcpu, ZCR_EL2); | ||
| 389 | else | ||
| 390 | zcr_el2 = vcpu_sve_max_vq(vcpu) - 1; | ||
| 391 | |||
| 392 | write_sysreg_el2(zcr_el2, SYS_ZCR); | ||
| 393 | |||
| 394 | zcr_el1 = __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)); | ||
| 395 | write_sysreg_el1(zcr_el1, SYS_ZCR); | ||
| 396 | } | ||
| 397 | } | ||
| 398 | |||
| 399 | static inline void fpsimd_lazy_switch_to_host(struct kvm_vcpu *vcpu) | ||
| 400 | { | ||
| 401 | u64 zcr_el1, zcr_el2; | ||
| 402 | |||
| 403 | if (!guest_owns_fp_regs()) | ||
| 404 | return; | ||
| 405 | |||
| 406 | /* | ||
| 407 | * When the guest owns the FP regs, we know that guest+hyp traps for | ||
| 408 | * any FPSIMD/SVE/SME features exposed to the guest have been disabled | ||
| 409 | * by either fpsimd_lazy_switch_to_guest() or kvm_hyp_handle_fpsimd() | ||
| 410 | * prior to __guest_entry(). As __guest_entry() guarantees a context | ||
| 411 | * synchronization event, we don't need an ISB here to avoid taking | ||
| 412 | * traps for anything that was exposed to the guest. | ||
| 413 | */ | ||
| 414 | if (vcpu_has_sve(vcpu)) { | ||
| 415 | zcr_el1 = read_sysreg_el1(SYS_ZCR); | ||
| 416 | __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1; | ||
| 417 | |||
| 418 | /* | ||
| 419 | * The guest's state is always saved using the guest's max VL. | ||
| 420 | * Ensure that the host has the guest's max VL active such that | ||
| 421 | * the host can save the guest's state lazily, but don't | ||
| 422 | * artificially restrict the host to the guest's max VL. | ||
| 423 | */ | ||
| 424 | if (has_vhe()) { | ||
| 425 | zcr_el2 = vcpu_sve_max_vq(vcpu) - 1; | ||
| 426 | write_sysreg_el2(zcr_el2, SYS_ZCR); | ||
| 427 | } else { | ||
| 428 | zcr_el2 = sve_vq_from_vl(kvm_host_sve_max_vl) - 1; | ||
| 429 | write_sysreg_el2(zcr_el2, SYS_ZCR); | ||
| 430 | |||
| 431 | zcr_el1 = vcpu_sve_max_vq(vcpu) - 1; | ||
| 432 | write_sysreg_el1(zcr_el1, SYS_ZCR); | ||
| 433 | } | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu) | ||
| 438 | { | ||
| 439 | /* | ||
| 440 | * Non-protected kvm relies on the host restoring its sve state. | ||
| 441 | * Protected kvm restores the host's sve state as not to reveal that | ||
| 442 | * fpsimd was used by a guest nor leak upper sve bits. | ||
| 443 | */ | ||
| 444 | if (system_supports_sve()) { | ||
| 445 | __hyp_sve_save_host(); | ||
| 446 | |||
| 447 | /* Re-enable SVE traps if not supported for the guest vcpu. */ | ||
| 448 | if (!vcpu_has_sve(vcpu)) | ||
| 449 | cpacr_clear_set(CPACR_EL1_ZEN, 0); | ||
| 450 | |||
| 451 | } else { | ||
| 452 | __fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs)); | ||
| 453 | } | ||
| 454 | |||
| 455 | if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) | ||
| 456 | *host_data_ptr(fpmr) = read_sysreg_s(SYS_FPMR); | ||
| 457 | } | ||
| 458 | |||
| 379 | 459 | ||
| 380 | /* | 460 | /* |
| 381 | * We trap the first access to the FP/SIMD to save the host context and | 461 | * We trap the first access to the FP/SIMD to save the host context and |
| @@ -383,7 +463,7 @@ static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu); · 1 unmodified line | |||
| 383 | * If FP/SIMD is not implemented, handle the trap and inject an undefined | 463 | * If FP/SIMD is not implemented, handle the trap and inject an undefined |
| 384 | * instruction exception to the guest. Similarly for trapped SVE accesses. | 464 | * instruction exception to the guest. Similarly for trapped SVE accesses. |
| 385 | */ | 465 | */ |
| 386 | static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) | 466 | static inline bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 387 | { | 467 | { |
| 388 | bool sve_guest; | 468 | bool sve_guest; |
| 389 | u8 esr_ec; | 469 | u8 esr_ec; |
| @@ -425,7 +505,7 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) · 35 unmodified lines | |||
| 425 | isb(); | 505 | isb(); |
| 426 | 506 | ||
| 427 | /* Write out the host state if it's in the registers */ | 507 | /* Write out the host state if it's in the registers */ |
| 428 | if (host_owns_fp_regs()) | 508 | if (is_protected_kvm_enabled() && host_owns_fp_regs()) |
| 429 | kvm_hyp_save_fpsimd_host(vcpu); | 509 | kvm_hyp_save_fpsimd_host(vcpu); |
| 430 | 510 | ||
| 431 | /* Restore the guest state */ | 511 | /* Restore the guest state */ |
| @@ -501,9 +581,22 @@ static inline bool handle_tx2_tvm(struct kvm_vcpu *vcpu) · 69 unmodified lines | |||
| 501 | return true; | 581 | return true; |
| 502 | } | 582 | } |
| 503 | 583 | ||
| 584 | /* Open-coded version of timer_get_offset() to allow for kern_hyp_va() */ | ||
| 585 | static inline u64 hyp_timer_get_offset(struct arch_timer_context *ctxt) | ||
| 586 | { | ||
| 587 | u64 offset = 0; | ||
| 588 | |||
| 589 | if (ctxt->offset.vm_offset) | ||
| 590 | offset += *kern_hyp_va(ctxt->offset.vm_offset); | ||
| 591 | if (ctxt->offset.vcpu_offset) | ||
| 592 | offset += *kern_hyp_va(ctxt->offset.vcpu_offset); | ||
| 593 | |||
| 594 | return offset; | ||
| 595 | } | ||
| 596 | |||
| 504 | static inline u64 compute_counter_value(struct arch_timer_context *ctxt) | 597 | static inline u64 compute_counter_value(struct arch_timer_context *ctxt) |
| 505 | { | 598 | { |
| 506 | return arch_timer_read_cntpct_el0() - timer_get_offset(ctxt); | 599 | return arch_timer_read_cntpct_el0() - hyp_timer_get_offset(ctxt); |
| 507 | } | 600 | } |
| 508 | 601 | ||
| 509 | static bool kvm_handle_cntxct(struct kvm_vcpu *vcpu) | 602 | static bool kvm_handle_cntxct(struct kvm_vcpu *vcpu) |
| @@ -587,7 +680,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu) · 77 unmodified lines | |||
| 587 | return true; | 680 | return true; |
| 588 | } | 681 | } |
| 589 | 682 | ||
| 590 | static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code) | 683 | static inline bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 591 | { | 684 | { |
| 592 | if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) && | 685 | if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) && |
| 593 | handle_tx2_tvm(vcpu)) | 686 | handle_tx2_tvm(vcpu)) |
| @@ -607,7 +700,7 @@ static bool kvm_hyp_handle_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code) · 13 unmodified lines | |||
| 607 | return false; | 700 | return false; |
| 608 | } | 701 | } |
| 609 | 702 | ||
| 610 | static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code) | 703 | static inline bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 611 | { | 704 | { |
| 612 | if (static_branch_unlikely(&vgic_v3_cpuif_trap) && | 705 | if (static_branch_unlikely(&vgic_v3_cpuif_trap) && |
| 613 | __vgic_v3_perform_cpuif_access(vcpu) == 1) | 706 | __vgic_v3_perform_cpuif_access(vcpu) == 1) |
| @@ -616,19 +709,18 @@ static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code) · 2 unmodified lines | |||
| 616 | return false; | 709 | return false; |
| 617 | } | 710 | } |
| 618 | 711 | ||
| 619 | static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code) | 712 | static inline bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, |
| 713 | u64 *exit_code) | ||
| 620 | { | 714 | { |
| 621 | if (!__populate_fault_info(vcpu)) | 715 | if (!__populate_fault_info(vcpu)) |
| 622 | return true; | 716 | return true; |
| 623 | 717 | ||
| 624 | return false; | 718 | return false; |
| 625 | } | 719 | } |
| 626 | static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) | 720 | #define kvm_hyp_handle_iabt_low kvm_hyp_handle_memory_fault |
| 627 | __alias(kvm_hyp_handle_memory_fault); | 721 | #define kvm_hyp_handle_watchpt_low kvm_hyp_handle_memory_fault |
| 628 | static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code) | ||
| 629 | __alias(kvm_hyp_handle_memory_fault); | ||
| 630 | 722 | ||
| 631 | static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) | 723 | static inline bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 632 | { | 724 | { |
| 633 | if (kvm_hyp_handle_memory_fault(vcpu, exit_code)) | 725 | if (kvm_hyp_handle_memory_fault(vcpu, exit_code)) |
| 634 | return true; | 726 | return true; |
| @@ -658,23 +750,16 @@ static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) · 23 unmodified lines | |||
| 658 | 750 | ||
| 659 | typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *); | 751 | typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *); |
| 660 | 752 | ||
| 661 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu); | ||
| 662 | |||
| 663 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code); | ||
| 664 | |||
| 665 | /* | 753 | /* |
| 666 | * Allow the hypervisor to handle the exit with an exit handler if it has one. | 754 | * Allow the hypervisor to handle the exit with an exit handler if it has one. |
| 667 | * | 755 | * |
| 668 | * Returns true if the hypervisor handled the exit, and control should go back | 756 | * Returns true if the hypervisor handled the exit, and control should go back |
| 669 | * to the guest, or false if it hasn't. | 757 | * to the guest, or false if it hasn't. |
| 670 | */ | 758 | */ |
| 671 | static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code) | 759 | static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code, |
| 760 | const exit_handler_fn *handlers) | ||
| 672 | { | 761 | { |
| 673 | const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu); | 762 | exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)]; |
| 674 | exit_handler_fn fn; | ||
| 675 | |||
| 676 | fn = handlers[kvm_vcpu_trap_get_class(vcpu)]; | ||
| 677 | |||
| 678 | if (fn) | 763 | if (fn) |
| 679 | return fn(vcpu, exit_code); | 764 | return fn(vcpu, exit_code); |
| 680 | 765 | ||
| @@ -704,20 +789,9 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code · 23 unmodified lines | |||
| 704 | * the guest, false when we should restore the host state and return to the | 789 | * the guest, false when we should restore the host state and return to the |
| 705 | * main run loop. | 790 | * main run loop. |
| 706 | */ | 791 | */ |
| 707 | static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) | 792 | static inline bool __fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code, |
| 793 | const exit_handler_fn *handlers) | ||
| 708 | { | 794 | { |
| 709 | /* | ||
| 710 | * Save PSTATE early so that we can evaluate the vcpu mode | ||
| 711 | * early on. | ||
| 712 | */ | ||
| 713 | synchronize_vcpu_pstate(vcpu, exit_code); | ||
| 714 | |||
| 715 | /* | ||
| 716 | * Check whether we want to repaint the state one way or | ||
| 717 | * another. | ||
| 718 | */ | ||
| 719 | early_exit_filter(vcpu, exit_code); | ||
| 720 | |||
| 721 | if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) | 795 | if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) |
| 722 | vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); | 796 | vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); |
| 723 | 797 | ||
| @@ -747,7 +821,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) · 23 unmodified lines | |||
| 747 | goto exit; | 821 | goto exit; |
| 748 | 822 | ||
| 749 | /* Check if there's an exit handler and allow it to handle the exit. */ | 823 | /* Check if there's an exit handler and allow it to handle the exit. */ |
| 750 | if (kvm_hyp_handle_exit(vcpu, exit_code)) | 824 | if (kvm_hyp_handle_exit(vcpu, exit_code, handlers)) |
| 751 | goto guest; | 825 | goto guest; |
| 752 | exit: | 826 | exit: |
| 753 | /* Return to the host kernel and handle the exit */ | 827 | /* Return to the host kernel and handle the exit */ |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | |||
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <hyp/adjust_pc.h> | 7 | #include <hyp/adjust_pc.h> |
| 8 | #include <hyp/switch.h> | ||
| 8 | 9 | ||
| 9 | #include <asm/pgtable-types.h> | 10 | #include <asm/pgtable-types.h> |
| 10 | #include <asm/kvm_asm.h> | 11 | #include <asm/kvm_asm.h> |
| @@ -83,7 +84,7 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) · 72 unmodified lines | |||
| 83 | if (system_supports_sve()) | 84 | if (system_supports_sve()) |
| 84 | __hyp_sve_restore_host(); | 85 | __hyp_sve_restore_host(); |
| 85 | else | 86 | else |
| 86 | __fpsimd_restore_state(*host_data_ptr(fpsimd_state)); | 87 | __fpsimd_restore_state(host_data_ptr(host_ctxt.fp_regs)); |
| 87 | 88 | ||
| 88 | if (has_fpmr) | 89 | if (has_fpmr) |
| 89 | write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR); | 90 | write_sysreg_s(*host_data_ptr(fpmr), SYS_FPMR); |
| @@ -91,11 +92,34 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) · 1 unmodified line | |||
| 91 | *host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED; | 92 | *host_data_ptr(fp_owner) = FP_STATE_HOST_OWNED; |
| 92 | } | 93 | } |
| 93 | 94 | ||
| 95 | static void flush_debug_state(struct pkvm_hyp_vcpu *hyp_vcpu) | ||
| 96 | { | ||
| 97 | struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu; | ||
| 98 | |||
| 99 | hyp_vcpu->vcpu.arch.debug_owner = host_vcpu->arch.debug_owner; | ||
| 100 | |||
| 101 | if (kvm_guest_owns_debug_regs(&hyp_vcpu->vcpu)) | ||
| 102 | hyp_vcpu->vcpu.arch.vcpu_debug_state = host_vcpu->arch.vcpu_debug_state; | ||
| 103 | else if (kvm_host_owns_debug_regs(&hyp_vcpu->vcpu)) | ||
| 104 | hyp_vcpu->vcpu.arch.external_debug_state = host_vcpu->arch.external_debug_state; | ||
| 105 | } | ||
| 106 | |||
| 107 | static void sync_debug_state(struct pkvm_hyp_vcpu *hyp_vcpu) | ||
| 108 | { | ||
| 109 | struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu; | ||
| 110 | |||
| 111 | if (kvm_guest_owns_debug_regs(&hyp_vcpu->vcpu)) | ||
| 112 | host_vcpu->arch.vcpu_debug_state = hyp_vcpu->vcpu.arch.vcpu_debug_state; | ||
| 113 | else if (kvm_host_owns_debug_regs(&hyp_vcpu->vcpu)) | ||
| 114 | host_vcpu->arch.external_debug_state = hyp_vcpu->vcpu.arch.external_debug_state; | ||
| 115 | } | ||
| 116 | |||
| 94 | static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) | 117 | static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) |
| 95 | { | 118 | { |
| 96 | struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu; | 119 | struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu; |
| 97 | 120 | ||
| 98 | fpsimd_sve_flush(); | 121 | fpsimd_sve_flush(); |
| 122 | flush_debug_state(hyp_vcpu); | ||
| 99 | 123 | ||
| 100 | hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt; | 124 | hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt; |
| 101 | 125 | ||
| @@ -123,6 +147,7 @@ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) · 21 unmodified lines | |||
| 123 | unsigned int i; | 147 | unsigned int i; |
| 124 | 148 | ||
| 125 | fpsimd_sve_sync(&hyp_vcpu->vcpu); | 149 | fpsimd_sve_sync(&hyp_vcpu->vcpu); |
| 150 | sync_debug_state(hyp_vcpu); | ||
| 126 | 151 | ||
| 127 | host_vcpu->arch.ctxt = hyp_vcpu->vcpu.arch.ctxt; | 152 | host_vcpu->arch.ctxt = hyp_vcpu->vcpu.arch.ctxt; |
| 128 | 153 | ||
| @@ -200,8 +225,12 @@ static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt) · 71 unmodified lines | |||
| 200 | 225 | ||
| 201 | sync_hyp_vcpu(hyp_vcpu); | 226 | sync_hyp_vcpu(hyp_vcpu); |
| 202 | } else { | 227 | } else { |
| 228 | struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu); | ||
| 229 | |||
| 203 | /* The host is fully trusted, run its vCPU directly. */ | 230 | /* The host is fully trusted, run its vCPU directly. */ |
| 204 | ret = __kvm_vcpu_run(kern_hyp_va(host_vcpu)); | 231 | fpsimd_lazy_switch_to_guest(vcpu); |
| 232 | ret = __kvm_vcpu_run(vcpu); | ||
| 233 | fpsimd_lazy_switch_to_host(vcpu); | ||
| 205 | } | 234 | } |
| 206 | out: | 235 | out: |
| 207 | cpu_reg(host_ctxt, 1) = ret; | 236 | cpu_reg(host_ctxt, 1) = ret; |
| @@ -651,12 +680,6 @@ void handle_trap(struct kvm_cpu_context *host_ctxt) · 443 unmodified lines | |||
| 651 | case ESR_ELx_EC_SMC64: | 680 | case ESR_ELx_EC_SMC64: |
| 652 | handle_host_smc(host_ctxt); | 681 | handle_host_smc(host_ctxt); |
| 653 | break; | 682 | break; |
| 654 | case ESR_ELx_EC_SVE: | ||
| 655 | cpacr_clear_set(0, CPACR_EL1_ZEN); | ||
| 656 | isb(); | ||
| 657 | sve_cond_update_zcr_vq(sve_vq_from_vl(kvm_host_sve_max_vl) - 1, | ||
| 658 | SYS_ZCR_EL2); | ||
| 659 | break; | ||
| 660 | case ESR_ELx_EC_IABT_LOW: | 683 | case ESR_ELx_EC_IABT_LOW: |
| 661 | case ESR_ELx_EC_DABT_LOW: | 684 | case ESR_ELx_EC_DABT_LOW: |
| 662 | handle_host_mem_abort(host_ctxt); | 685 | handle_host_mem_abort(host_ctxt); |
| @@ -943,10 +943,10 @@ static int __check_host_shared_guest(struct pkvm_hyp_vm *vm, u64 *__phys, u64 ip · 942 unmodified lines | |||
| 943 | ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level); | 943 | ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level); |
| 944 | if (ret) | 944 | if (ret) |
| 945 | return ret; | 945 | return ret; |
| 946 | if (level != KVM_PGTABLE_LAST_LEVEL) | ||
| 947 | return -E2BIG; | ||
| 948 | if (!kvm_pte_valid(pte)) | 946 | if (!kvm_pte_valid(pte)) |
| 949 | return -ENOENT; | 947 | return -ENOENT; |
| 948 | if (level != KVM_PGTABLE_LAST_LEVEL) | ||
| 949 | return -E2BIG; | ||
| 950 | 950 | ||
| 951 | state = guest_get_page_state(pte, ipa); | 951 | state = guest_get_page_state(pte, ipa); |
| 952 | if (state != PKVM_PAGE_SHARED_BORROWED) | 952 | if (state != PKVM_PAGE_SHARED_BORROWED) |
| @@ -998,63 +998,73 @@ unlock: · 45 unmodified lines | |||
| 998 | return ret; | 998 | return ret; |
| 999 | } | 999 | } |
| 1000 | 1000 | ||
| 1001 | int __pkvm_host_relax_perms_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu, enum kvm_pgtable_prot prot) | 1001 | static void assert_host_shared_guest(struct pkvm_hyp_vm *vm, u64 ipa) |
| 1002 | { | 1002 | { |
| 1003 | struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu); | ||
| 1004 | u64 ipa = hyp_pfn_to_phys(gfn); | ||
| 1005 | u64 phys; | 1003 | u64 phys; |
| 1006 | int ret; | 1004 | int ret; |
| 1007 | 1005 | ||
| 1008 | if (prot & ~KVM_PGTABLE_PROT_RWX) | 1006 | if (!IS_ENABLED(CONFIG_NVHE_EL2_DEBUG)) |
| 1009 | return -EINVAL; | 1007 | return; |
| 1010 | 1008 | ||
| 1011 | host_lock_component(); | 1009 | host_lock_component(); |
| 1012 | guest_lock_component(vm); | 1010 | guest_lock_component(vm); |
| 1013 | 1011 | ||
| 1014 | ret = __check_host_shared_guest(vm, &phys, ipa); | 1012 | ret = __check_host_shared_guest(vm, &phys, ipa); |
| 1015 | if (!ret) | ||
| 1016 | ret = kvm_pgtable_stage2_relax_perms(&vm->pgt, ipa, prot, 0); | ||
| 1017 | 1013 | ||
| 1018 | guest_unlock_component(vm); | 1014 | guest_unlock_component(vm); |
| 1019 | host_unlock_component(); | 1015 | host_unlock_component(); |
| 1020 | 1016 | ||
| 1021 | return ret; | 1017 | WARN_ON(ret && ret != -ENOENT); |
| 1022 | } | 1018 | } |
| 1023 | 1019 | ||
| 1024 | int __pkvm_host_wrprotect_guest(u64 gfn, struct pkvm_hyp_vm *vm) | 1020 | int __pkvm_host_relax_perms_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu, enum kvm_pgtable_prot prot) |
| 1025 | { | 1021 | { |
| 1022 | struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu); | ||
| 1026 | u64 ipa = hyp_pfn_to_phys(gfn); | 1023 | u64 ipa = hyp_pfn_to_phys(gfn); |
| 1027 | u64 phys; | ||
| 1028 | int ret; | 1024 | int ret; |
| 1029 | 1025 | ||
| 1030 | host_lock_component(); | 1026 | if (pkvm_hyp_vm_is_protected(vm)) |
| 1031 | guest_lock_component(vm); | 1027 | return -EPERM; |
| 1032 | 1028 | ||
| 1033 | ret = __check_host_shared_guest(vm, &phys, ipa); | 1029 | if (prot & ~KVM_PGTABLE_PROT_RWX) |
| 1034 | if (!ret) | 1030 | return -EINVAL; |
| 1035 | ret = kvm_pgtable_stage2_wrprotect(&vm->pgt, ipa, PAGE_SIZE); | ||
| 1036 | 1031 | ||
| 1032 | assert_host_shared_guest(vm, ipa); | ||
| 1033 | guest_lock_component(vm); | ||
| 1034 | ret = kvm_pgtable_stage2_relax_perms(&vm->pgt, ipa, prot, 0); | ||
| 1037 | guest_unlock_component(vm); | 1035 | guest_unlock_component(vm); |
| 1038 | host_unlock_component(); | ||
| 1039 | 1036 | ||
| 1040 | return ret; | 1037 | return ret; |
| 1041 | } | 1038 | } |
| 1042 | 1039 | ||
| 1043 | int __pkvm_host_test_clear_young_guest(u64 gfn, bool mkold, struct pkvm_hyp_vm *vm) | 1040 | int __pkvm_host_wrprotect_guest(u64 gfn, struct pkvm_hyp_vm *vm) |
| 1044 | { | 1041 | { |
| 1045 | u64 ipa = hyp_pfn_to_phys(gfn); | 1042 | u64 ipa = hyp_pfn_to_phys(gfn); |
| 1046 | u64 phys; | ||
| 1047 | int ret; | 1043 | int ret; |
| 1048 | 1044 | ||
| 1049 | host_lock_component(); | 1045 | if (pkvm_hyp_vm_is_protected(vm)) |
| 1046 | return -EPERM; | ||
| 1047 | |||
| 1048 | assert_host_shared_guest(vm, ipa); | ||
| 1050 | guest_lock_component(vm); | 1049 | guest_lock_component(vm); |
| 1050 | ret = kvm_pgtable_stage2_wrprotect(&vm->pgt, ipa, PAGE_SIZE); | ||
| 1051 | guest_unlock_component(vm); | ||
| 1051 | 1052 | ||
| 1052 | ret = __check_host_shared_guest(vm, &phys, ipa); | 1053 | return ret; |
| 1053 | if (!ret) | 1054 | } |
| 1054 | ret = kvm_pgtable_stage2_test_clear_young(&vm->pgt, ipa, PAGE_SIZE, mkold); | 1055 | |
| 1056 | int __pkvm_host_test_clear_young_guest(u64 gfn, bool mkold, struct pkvm_hyp_vm *vm) | ||
| 1057 | { | ||
| 1058 | u64 ipa = hyp_pfn_to_phys(gfn); | ||
| 1059 | int ret; | ||
| 1060 | |||
| 1061 | if (pkvm_hyp_vm_is_protected(vm)) | ||
| 1062 | return -EPERM; | ||
| 1055 | 1063 | ||
| 1064 | assert_host_shared_guest(vm, ipa); | ||
| 1065 | guest_lock_component(vm); | ||
| 1066 | ret = kvm_pgtable_stage2_test_clear_young(&vm->pgt, ipa, PAGE_SIZE, mkold); | ||
| 1056 | guest_unlock_component(vm); | 1067 | guest_unlock_component(vm); |
| 1057 | host_unlock_component(); | ||
| 1058 | 1068 | ||
| 1059 | return ret; | 1069 | return ret; |
| 1060 | } | 1070 | } |
| @@ -1063,18 +1073,14 @@ int __pkvm_host_mkyoung_guest(u64 gfn, struct pkvm_hyp_vcpu *vcpu) · 2 unmodified lines | |||
| 1063 | { | 1073 | { |
| 1064 | struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu); | 1074 | struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu); |
| 1065 | u64 ipa = hyp_pfn_to_phys(gfn); | 1075 | u64 ipa = hyp_pfn_to_phys(gfn); |
| 1066 | u64 phys; | ||
| 1067 | int ret; | ||
| 1068 | |||
| 1069 | host_lock_component(); | ||
| 1070 | guest_lock_component(vm); | ||
| 1071 | 1076 | ||
| 1072 | ret = __check_host_shared_guest(vm, &phys, ipa); | 1077 | if (pkvm_hyp_vm_is_protected(vm)) |
| 1073 | if (!ret) | 1078 | return -EPERM; |
| 1074 | kvm_pgtable_stage2_mkyoung(&vm->pgt, ipa, 0); | ||
| 1075 | 1079 | ||
| 1080 | assert_host_shared_guest(vm, ipa); | ||
| 1081 | guest_lock_component(vm); | ||
| 1082 | kvm_pgtable_stage2_mkyoung(&vm->pgt, ipa, 0); | ||
| 1076 | guest_unlock_component(vm); | 1083 | guest_unlock_component(vm); |
| 1077 | host_unlock_component(); | ||
| 1078 | 1084 | ||
| 1079 | return ret; | 1085 | return 0; |
| 1080 | } | 1086 | } |
| @@ -39,6 +39,9 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu) · 38 unmodified lines | |||
| 39 | { | 39 | { |
| 40 | u64 val = CPTR_EL2_TAM; /* Same bit irrespective of E2H */ | 40 | u64 val = CPTR_EL2_TAM; /* Same bit irrespective of E2H */ |
| 41 | 41 | ||
| 42 | if (!guest_owns_fp_regs()) | ||
| 43 | __activate_traps_fpsimd32(vcpu); | ||
| 44 | |||
| 42 | if (has_hvhe()) { | 45 | if (has_hvhe()) { |
| 43 | val |= CPACR_EL1_TTA; | 46 | val |= CPACR_EL1_TTA; |
| 44 | 47 | ||
| @@ -47,6 +50,8 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu) · 2 unmodified lines | |||
| 47 | if (vcpu_has_sve(vcpu)) | 50 | if (vcpu_has_sve(vcpu)) |
| 48 | val |= CPACR_EL1_ZEN; | 51 | val |= CPACR_EL1_ZEN; |
| 49 | } | 52 | } |
| 53 | |||
| 54 | write_sysreg(val, cpacr_el1); | ||
| 50 | } else { | 55 | } else { |
| 51 | val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1; | 56 | val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1; |
| 52 | 57 | ||
| @@ -61,12 +66,32 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu) · 8 unmodified lines | |||
| 61 | 66 | ||
| 62 | if (!guest_owns_fp_regs()) | 67 | if (!guest_owns_fp_regs()) |
| 63 | val |= CPTR_EL2_TFP; | 68 | val |= CPTR_EL2_TFP; |
| 69 | |||
| 70 | write_sysreg(val, cptr_el2); | ||
| 64 | } | 71 | } |
| 72 | } | ||
| 65 | 73 | ||
| 66 | if (!guest_owns_fp_regs()) | 74 | static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu) |
| 67 | __activate_traps_fpsimd32(vcpu); | 75 | { |
| 76 | if (has_hvhe()) { | ||
| 77 | u64 val = CPACR_EL1_FPEN; | ||
| 78 | |||
| 79 | if (cpus_have_final_cap(ARM64_SVE)) | ||
| 80 | val |= CPACR_EL1_ZEN; | ||
| 81 | if (cpus_have_final_cap(ARM64_SME)) | ||
| 82 | val |= CPACR_EL1_SMEN; | ||
| 68 | 83 | ||
| 69 | kvm_write_cptr_el2(val); | 84 | write_sysreg(val, cpacr_el1); |
| 85 | } else { | ||
| 86 | u64 val = CPTR_NVHE_EL2_RES1; | ||
| 87 | |||
| 88 | if (!cpus_have_final_cap(ARM64_SVE)) | ||
| 89 | val |= CPTR_EL2_TZ; | ||
| 90 | if (!cpus_have_final_cap(ARM64_SME)) | ||
| 91 | val |= CPTR_EL2_TSM; | ||
| 92 | |||
| 93 | write_sysreg(val, cptr_el2); | ||
| 94 | } | ||
| 70 | } | 95 | } |
| 71 | 96 | ||
| 72 | static void __activate_traps(struct kvm_vcpu *vcpu) | 97 | static void __activate_traps(struct kvm_vcpu *vcpu) |
| @@ -119,7 +144,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) · 46 unmodified lines | |||
| 119 | 144 | ||
| 120 | write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2); | 145 | write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2); |
| 121 | 146 | ||
| 122 | kvm_reset_cptr_el2(vcpu); | 147 | __deactivate_cptr_traps(vcpu); |
| 123 | write_sysreg(__kvm_hyp_host_vector, vbar_el2); | 148 | write_sysreg(__kvm_hyp_host_vector, vbar_el2); |
| 124 | } | 149 | } |
| 125 | 150 | ||
| @@ -192,34 +217,6 @@ static bool kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu, u64 *exit_code) · 66 unmodified lines | |||
| 192 | kvm_handle_pvm_sysreg(vcpu, exit_code)); | 217 | kvm_handle_pvm_sysreg(vcpu, exit_code)); |
| 193 | } | 218 | } |
| 194 | 219 | ||
| 195 | static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu) | ||
| 196 | { | ||
| 197 | /* | ||
| 198 | * Non-protected kvm relies on the host restoring its sve state. | ||
| 199 | * Protected kvm restores the host's sve state as not to reveal that | ||
| 200 | * fpsimd was used by a guest nor leak upper sve bits. | ||
| 201 | */ | ||
| 202 | if (unlikely(is_protected_kvm_enabled() && system_supports_sve())) { | ||
| 203 | __hyp_sve_save_host(); | ||
| 204 | |||
| 205 | /* Re-enable SVE traps if not supported for the guest vcpu. */ | ||
| 206 | if (!vcpu_has_sve(vcpu)) | ||
| 207 | cpacr_clear_set(CPACR_EL1_ZEN, 0); | ||
| 208 | |||
| 209 | } else { | ||
| 210 | __fpsimd_save_state(*host_data_ptr(fpsimd_state)); | ||
| 211 | } | ||
| 212 | |||
| 213 | if (kvm_has_fpmr(kern_hyp_va(vcpu->kvm))) { | ||
| 214 | u64 val = read_sysreg_s(SYS_FPMR); | ||
| 215 | |||
| 216 | if (unlikely(is_protected_kvm_enabled())) | ||
| 217 | *host_data_ptr(fpmr) = val; | ||
| 218 | else | ||
| 219 | **host_data_ptr(fpmr_ptr) = val; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | static const exit_handler_fn hyp_exit_handlers[] = { | 220 | static const exit_handler_fn hyp_exit_handlers[] = { |
| 224 | [0 ... ESR_ELx_EC_MAX] = NULL, | 221 | [0 ... ESR_ELx_EC_MAX] = NULL, |
| 225 | [ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32, | 222 | [ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32, |
| @@ -251,19 +248,21 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu) · 25 unmodified lines | |||
| 251 | return hyp_exit_handlers; | 248 | return hyp_exit_handlers; |
| 252 | } | 249 | } |
| 253 | 250 | ||
| 254 | /* | 251 | static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 255 | * Some guests (e.g., protected VMs) are not be allowed to run in AArch32. | ||
| 256 | * The ARMv8 architecture does not give the hypervisor a mechanism to prevent a | ||
| 257 | * guest from dropping to AArch32 EL0 if implemented by the CPU. If the | ||
| 258 | * hypervisor spots a guest in such a state ensure it is handled, and don't | ||
| 259 | * trust the host to spot or fix it. The check below is based on the one in | ||
| 260 | * kvm_arch_vcpu_ioctl_run(). | ||
| 261 | * | ||
| 262 | * Returns false if the guest ran in AArch32 when it shouldn't have, and | ||
| 263 | * thus should exit to the host, or true if a the guest run loop can continue. | ||
| 264 | */ | ||
| 265 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) | ||
| 266 | { | 252 | { |
| 253 | const exit_handler_fn *handlers = kvm_get_exit_handler_array(vcpu); | ||
| 254 | |||
| 255 | synchronize_vcpu_pstate(vcpu, exit_code); | ||
| 256 | |||
| 257 | /* | ||
| 258 | * Some guests (e.g., protected VMs) are not be allowed to run in | ||
| 259 | * AArch32. The ARMv8 architecture does not give the hypervisor a | ||
| 260 | * mechanism to prevent a guest from dropping to AArch32 EL0 if | ||
| 261 | * implemented by the CPU. If the hypervisor spots a guest in such a | ||
| 262 | * state ensure it is handled, and don't trust the host to spot or fix | ||
| 263 | * it. The check below is based on the one in | ||
| 264 | * kvm_arch_vcpu_ioctl_run(). | ||
| 265 | */ | ||
| 267 | if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) { | 266 | if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) { |
| 268 | /* | 267 | /* |
| 269 | * As we have caught the guest red-handed, decide that it isn't | 268 | * As we have caught the guest red-handed, decide that it isn't |
| @@ -276,6 +275,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) · 6 unmodified lines | |||
| 276 | *exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT); | 275 | *exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT); |
| 277 | *exit_code |= ARM_EXCEPTION_IL; | 276 | *exit_code |= ARM_EXCEPTION_IL; |
| 278 | } | 277 | } |
| 278 | |||
| 279 | return __fixup_guest_exit(vcpu, exit_code, handlers); | ||
| 279 | } | 280 | } |
| 280 | 281 | ||
| 281 | /* Switch to the guest for legacy non-VHE systems */ | 282 | /* Switch to the guest for legacy non-VHE systems */ |
| @@ -136,6 +136,16 @@ write: · 135 unmodified lines | |||
| 136 | write_sysreg(val, cpacr_el1); | 136 | write_sysreg(val, cpacr_el1); |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu) | ||
| 140 | { | ||
| 141 | u64 val = CPACR_EL1_FPEN | CPACR_EL1_ZEN_EL1EN; | ||
| 142 | |||
| 143 | if (cpus_have_final_cap(ARM64_SME)) | ||
| 144 | val |= CPACR_EL1_SMEN_EL1EN; | ||
| 145 | |||
| 146 | write_sysreg(val, cpacr_el1); | ||
| 147 | } | ||
| 148 | |||
| 139 | static void __activate_traps(struct kvm_vcpu *vcpu) | 149 | static void __activate_traps(struct kvm_vcpu *vcpu) |
| 140 | { | 150 | { |
| 141 | u64 val; | 151 | u64 val; |
| @@ -207,7 +217,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) · 65 unmodified lines | |||
| 207 | */ | 217 | */ |
| 208 | asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT)); | 218 | asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT)); |
| 209 | 219 | ||
| 210 | kvm_reset_cptr_el2(vcpu); | 220 | __deactivate_cptr_traps(vcpu); |
| 211 | 221 | ||
| 212 | if (!arm64_kernel_unmapped_at_el0()) | 222 | if (!arm64_kernel_unmapped_at_el0()) |
| 213 | host_vectors = __this_cpu_read(this_cpu_vector); | 223 | host_vectors = __this_cpu_read(this_cpu_vector); |
| @@ -413,14 +423,6 @@ static bool kvm_hyp_handle_eret(struct kvm_vcpu *vcpu, u64 *exit_code) · 199 unmodified lines | |||
| 413 | return true; | 423 | return true; |
| 414 | } | 424 | } |
| 415 | 425 | ||
| 416 | static void kvm_hyp_save_fpsimd_host(struct kvm_vcpu *vcpu) | ||
| 417 | { | ||
| 418 | __fpsimd_save_state(*host_data_ptr(fpsimd_state)); | ||
| 419 | |||
| 420 | if (kvm_has_fpmr(vcpu->kvm)) | ||
| 421 | **host_data_ptr(fpmr_ptr) = read_sysreg_s(SYS_FPMR); | ||
| 422 | } | ||
| 423 | |||
| 424 | static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code) | 426 | static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 425 | { | 427 | { |
| 426 | int ret = -EINVAL; | 428 | int ret = -EINVAL; |
| @@ -538,13 +540,10 @@ static const exit_handler_fn hyp_exit_handlers[] = { · 111 unmodified lines | |||
| 538 | [ESR_ELx_EC_MOPS] = kvm_hyp_handle_mops, | 540 | [ESR_ELx_EC_MOPS] = kvm_hyp_handle_mops, |
| 539 | }; | 541 | }; |
| 540 | 542 | ||
| 541 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu) | 543 | static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 542 | { | 544 | { |
| 543 | return hyp_exit_handlers; | 545 | synchronize_vcpu_pstate(vcpu, exit_code); |
| 544 | } | ||
| 545 | 546 | ||
| 546 | static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) | ||
| 547 | { | ||
| 548 | /* | 547 | /* |
| 549 | * If we were in HYP context on entry, adjust the PSTATE view | 548 | * If we were in HYP context on entry, adjust the PSTATE view |
| 550 | * so that the usual helpers work correctly. | 549 | * so that the usual helpers work correctly. |
| @@ -564,6 +563,8 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) · 13 unmodified lines | |||
| 564 | *vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT); | 563 | *vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT); |
| 565 | *vcpu_cpsr(vcpu) |= mode; | 564 | *vcpu_cpsr(vcpu) |= mode; |
| 566 | } | 565 | } |
| 566 | |||
| 567 | return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers); | ||
| 567 | } | 568 | } |
| 568 | 569 | ||
| 569 | /* Switch to the guest for VHE systems running in EL2 */ | 570 | /* Switch to the guest for VHE systems running in EL2 */ |
| @@ -578,6 +579,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) · 8 unmodified lines | |||
| 578 | 579 | ||
| 579 | sysreg_save_host_state_vhe(host_ctxt); | 580 | sysreg_save_host_state_vhe(host_ctxt); |
| 580 | 581 | ||
| 582 | fpsimd_lazy_switch_to_guest(vcpu); | ||
| 583 | |||
| 581 | /* | 584 | /* |
| 582 | * Note that ARM erratum 1165522 requires us to configure both stage 1 | 585 | * Note that ARM erratum 1165522 requires us to configure both stage 1 |
| 583 | * and stage 2 translation for the guest context before we clear | 586 | * and stage 2 translation for the guest context before we clear |
| @@ -602,6 +605,8 @@ static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) · 18 unmodified lines | |||
| 602 | 605 | ||
| 603 | __deactivate_traps(vcpu); | 606 | __deactivate_traps(vcpu); |
| 604 | 607 | ||
| 608 | fpsimd_lazy_switch_to_host(vcpu); | ||
| 609 | |||
| 605 | sysreg_restore_host_state_vhe(host_ctxt); | 610 | sysreg_restore_host_state_vhe(host_ctxt); |
| 606 | 611 | ||
| 607 | if (guest_owns_fp_regs()) | 612 | if (guest_owns_fp_regs()) |
| @@ -67,26 +67,27 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu) · 66 unmodified lines | |||
| 67 | if (!tmp) | 67 | if (!tmp) |
| 68 | return -ENOMEM; | 68 | return -ENOMEM; |
| 69 | 69 | ||
| 70 | swap(kvm->arch.nested_mmus, tmp); | ||
| 71 | |||
| 70 | /* | 72 | /* |
| 71 | * If we went through a realocation, adjust the MMU back-pointers in | 73 | * If we went through a realocation, adjust the MMU back-pointers in |
| 72 | * the previously initialised kvm_pgtable structures. | 74 | * the previously initialised kvm_pgtable structures. |
| 73 | */ | 75 | */ |
| 74 | if (kvm->arch.nested_mmus != tmp) | 76 | if (kvm->arch.nested_mmus != tmp) |
| 75 | for (int i = 0; i < kvm->arch.nested_mmus_size; i++) | 77 | for (int i = 0; i < kvm->arch.nested_mmus_size; i++) |
| 76 | tmp[i].pgt->mmu = &tmp[i]; | 78 | kvm->arch.nested_mmus[i].pgt->mmu = &kvm->arch.nested_mmus[i]; |
| 77 | 79 | ||
| 78 | for (int i = kvm->arch.nested_mmus_size; !ret && i < num_mmus; i++) | 80 | for (int i = kvm->arch.nested_mmus_size; !ret && i < num_mmus; i++) |
| 79 | ret = init_nested_s2_mmu(kvm, &tmp[i]); | 81 | ret = init_nested_s2_mmu(kvm, &kvm->arch.nested_mmus[i]); |
| 80 | 82 | ||
| 81 | if (ret) { | 83 | if (ret) { |
| 82 | for (int i = kvm->arch.nested_mmus_size; i < num_mmus; i++) | 84 | for (int i = kvm->arch.nested_mmus_size; i < num_mmus; i++) |
| 83 | kvm_free_stage2_pgd(&tmp[i]); | 85 | kvm_free_stage2_pgd(&kvm->arch.nested_mmus[i]); |
| 84 | 86 | ||
| 85 | return ret; | 87 | return ret; |
| 86 | } | 88 | } |
| 87 | 89 | ||
| 88 | kvm->arch.nested_mmus_size = num_mmus; | 90 | kvm->arch.nested_mmus_size = num_mmus; |
| 89 | kvm->arch.nested_mmus = tmp; | ||
| 90 | 91 | ||
| 91 | return 0; | 92 | return 0; |
| 92 | } | 93 | } |
| @@ -1452,6 +1452,16 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu, · 1451 unmodified lines | |||
| 1452 | return true; | 1452 | return true; |
| 1453 | } | 1453 | } |
| 1454 | 1454 | ||
| 1455 | static bool access_hv_timer(struct kvm_vcpu *vcpu, | ||
| 1456 | struct sys_reg_params *p, | ||
| 1457 | const struct sys_reg_desc *r) | ||
| 1458 | { | ||
| 1459 | if (!vcpu_el2_e2h_is_set(vcpu)) | ||
| 1460 | return undef_access(vcpu, p, r); | ||
| 1461 | |||
| 1462 | return access_arch_timer(vcpu, p, r); | ||
| 1463 | } | ||
| 1464 | |||
| 1455 | static s64 kvm_arm64_ftr_safe_value(u32 id, const struct arm64_ftr_bits *ftrp, | 1465 | static s64 kvm_arm64_ftr_safe_value(u32 id, const struct arm64_ftr_bits *ftrp, |
| 1456 | s64 new, s64 cur) | 1466 | s64 new, s64 cur) |
| 1457 | { | 1467 | { |
| @@ -3103,9 +3113,9 @@ static const struct sys_reg_desc sys_reg_descs[] = { · 1645 unmodified lines | |||
| 3103 | EL2_REG(CNTHP_CTL_EL2, access_arch_timer, reset_val, 0), | 3113 | EL2_REG(CNTHP_CTL_EL2, access_arch_timer, reset_val, 0), |
| 3104 | EL2_REG(CNTHP_CVAL_EL2, access_arch_timer, reset_val, 0), | 3114 | EL2_REG(CNTHP_CVAL_EL2, access_arch_timer, reset_val, 0), |
| 3105 | 3115 | ||
| 3106 | { SYS_DESC(SYS_CNTHV_TVAL_EL2), access_arch_timer }, | 3116 | { SYS_DESC(SYS_CNTHV_TVAL_EL2), access_hv_timer }, |
| 3107 | EL2_REG(CNTHV_CTL_EL2, access_arch_timer, reset_val, 0), | 3117 | EL2_REG(CNTHV_CTL_EL2, access_hv_timer, reset_val, 0), |
| 3108 | EL2_REG(CNTHV_CVAL_EL2, access_arch_timer, reset_val, 0), | 3118 | EL2_REG(CNTHV_CVAL_EL2, access_hv_timer, reset_val, 0), |
| 3109 | 3119 | ||
| 3110 | { SYS_DESC(SYS_CNTKCTL_EL12), access_cntkctl_el12 }, | 3120 | { SYS_DESC(SYS_CNTKCTL_EL12), access_cntkctl_el12 }, |
| 3111 | 3121 | ||
| @@ -34,9 +34,9 @@ · 33 unmodified lines | |||
| 34 | * | 34 | * |
| 35 | * CPU Interface: | 35 | * CPU Interface: |
| 36 | * | 36 | * |
| 37 | * - kvm_vgic_vcpu_init(): initialization of static data that | 37 | * - kvm_vgic_vcpu_init(): initialization of static data that doesn't depend |
| 38 | * doesn't depend on any sizing information or emulation type. No | 38 | * on any sizing information. Private interrupts are allocated if not |
| 39 | * allocation is allowed there. | 39 | * already allocated at vgic-creation time. |
| 40 | */ | 40 | */ |
| 41 | 41 | ||
| 42 | /* EARLY INIT */ | 42 | /* EARLY INIT */ |
| @@ -58,6 +58,8 @@ void kvm_vgic_early_init(struct kvm *kvm) · 15 unmodified lines | |||
| 58 | 58 | ||
| 59 | /* CREATION */ | 59 | /* CREATION */ |
| 60 | 60 | ||
| 61 | static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type); | ||
| 62 | |||
| 61 | /** | 63 | /** |
| 62 | * kvm_vgic_create: triggered by the instantiation of the VGIC device by | 64 | * kvm_vgic_create: triggered by the instantiation of the VGIC device by |
| 63 | * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only) | 65 | * user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only) |
| @@ -112,6 +114,22 @@ int kvm_vgic_create(struct kvm *kvm, u32 type) · 48 unmodified lines | |||
| 112 | goto out_unlock; | 114 | goto out_unlock; |
| 113 | } | 115 | } |
| 114 | 116 | ||
| 117 | kvm_for_each_vcpu(i, vcpu, kvm) { | ||
| 118 | ret = vgic_allocate_private_irqs_locked(vcpu, type); | ||
| 119 | if (ret) | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | |||
| 123 | if (ret) { | ||
| 124 | kvm_for_each_vcpu(i, vcpu, kvm) { | ||
| 125 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | ||
| 126 | kfree(vgic_cpu->private_irqs); | ||
| 127 | vgic_cpu->private_irqs = NULL; | ||
| 128 | } | ||
| 129 | |||
| 130 | goto out_unlock; | ||
| 131 | } | ||
| 132 | |||
| 115 | kvm->arch.vgic.in_kernel = true; | 133 | kvm->arch.vgic.in_kernel = true; |
| 116 | kvm->arch.vgic.vgic_model = type; | 134 | kvm->arch.vgic.vgic_model = type; |
| 117 | 135 | ||
| @@ -180,7 +198,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis) · 62 unmodified lines | |||
| 180 | return 0; | 198 | return 0; |
| 181 | } | 199 | } |
| 182 | 200 | ||
| 183 | static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu) | 201 | static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type) |
| 184 | { | 202 | { |
| 185 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | 203 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
| 186 | int i; | 204 | int i; |
| @@ -218,17 +236,28 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu) · 31 unmodified lines | |||
| 218 | /* PPIs */ | 236 | /* PPIs */ |
| 219 | irq->config = VGIC_CONFIG_LEVEL; | 237 | irq->config = VGIC_CONFIG_LEVEL; |
| 220 | } | 238 | } |
| 239 | |||
| 240 | switch (type) { | ||
| 241 | case KVM_DEV_TYPE_ARM_VGIC_V3: | ||
| 242 | irq->group = 1; | ||
| 243 | irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu); | ||
| 244 | break; | ||
| 245 | case KVM_DEV_TYPE_ARM_VGIC_V2: | ||
| 246 | irq->group = 0; | ||
| 247 | irq->targets = BIT(vcpu->vcpu_id); | ||
| 248 | break; | ||
| 249 | } | ||
| 221 | } | 250 | } |
| 222 | 251 | ||
| 223 | return 0; | 252 | return 0; |
| 224 | } | 253 | } |
| 225 | 254 | ||
| 226 | static int vgic_allocate_private_irqs(struct kvm_vcpu *vcpu) | 255 | static int vgic_allocate_private_irqs(struct kvm_vcpu *vcpu, u32 type) |
| 227 | { | 256 | { |
| 228 | int ret; | 257 | int ret; |
| 229 | 258 | ||
| 230 | mutex_lock(&vcpu->kvm->arch.config_lock); | 259 | mutex_lock(&vcpu->kvm->arch.config_lock); |
| 231 | ret = vgic_allocate_private_irqs_locked(vcpu); | 260 | ret = vgic_allocate_private_irqs_locked(vcpu, type); |
| 232 | mutex_unlock(&vcpu->kvm->arch.config_lock); | 261 | mutex_unlock(&vcpu->kvm->arch.config_lock); |
| 233 | 262 | ||
| 234 | return ret; | 263 | return ret; |
| @@ -258,7 +287,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) · 23 unmodified lines | |||
| 258 | if (!irqchip_in_kernel(vcpu->kvm)) | 287 | if (!irqchip_in_kernel(vcpu->kvm)) |
| 259 | return 0; | 288 | return 0; |
| 260 | 289 | ||
| 261 | ret = vgic_allocate_private_irqs(vcpu); | 290 | ret = vgic_allocate_private_irqs(vcpu, dist->vgic_model); |
| 262 | if (ret) | 291 | if (ret) |
| 263 | return ret; | 292 | return ret; |
| 264 | 293 | ||
| @@ -295,7 +324,7 @@ int vgic_init(struct kvm *kvm) · 30 unmodified lines | |||
| 295 | { | 324 | { |
| 296 | struct vgic_dist *dist = &kvm->arch.vgic; | 325 | struct vgic_dist *dist = &kvm->arch.vgic; |
| 297 | struct kvm_vcpu *vcpu; | 326 | struct kvm_vcpu *vcpu; |
| 298 | int ret = 0, i; | 327 | int ret = 0; |
| 299 | unsigned long idx; | 328 | unsigned long idx; |
| 300 | 329 | ||
| 301 | lockdep_assert_held(&kvm->arch.config_lock); | 330 | lockdep_assert_held(&kvm->arch.config_lock); |
| @@ -315,35 +344,6 @@ int vgic_init(struct kvm *kvm) · 13 unmodified lines | |||
| 315 | if (ret) | 344 | if (ret) |
| 316 | goto out; | 345 | goto out; |
| 317 | 346 | ||
| 318 | /* Initialize groups on CPUs created before the VGIC type was known */ | ||
| 319 | kvm_for_each_vcpu(idx, vcpu, kvm) { | ||
| 320 | ret = vgic_allocate_private_irqs_locked(vcpu); | ||
| 321 | if (ret) | ||
| 322 | goto out; | ||
| 323 | |||
| 324 | for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) { | ||
| 325 | struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, i); | ||
| 326 | |||
| 327 | switch (dist->vgic_model) { | ||
| 328 | case KVM_DEV_TYPE_ARM_VGIC_V3: | ||
| 329 | irq->group = 1; | ||
| 330 | irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu); | ||
| 331 | break; | ||
| 332 | case KVM_DEV_TYPE_ARM_VGIC_V2: | ||
| 333 | irq->group = 0; | ||
| 334 | irq->targets = 1U << idx; | ||
| 335 | break; | ||
| 336 | default: | ||
| 337 | ret = -EINVAL; | ||
| 338 | } | ||
| 339 | |||
| 340 | vgic_put_irq(kvm, irq); | ||
| 341 | |||
| 342 | if (ret) | ||
| 343 | goto out; | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | /* | 347 | /* |
| 348 | * If we have GICv4.1 enabled, unconditionally request enable the | 348 | * If we have GICv4.1 enabled, unconditionally request enable the |
| 349 | * v4 support so that we get HW-accelerated vSGIs. Otherwise, only | 349 | * v4 support so that we get HW-accelerated vSGIs. Otherwise, only |
| @@ -162,6 +162,13 @@ static int copy_p4d(struct trans_pgd_info *info, pgd_t *dst_pgdp, · 161 unmodified lines | |||
| 162 | unsigned long next; | 162 | unsigned long next; |
| 163 | unsigned long addr = start; | 163 | unsigned long addr = start; |
| 164 | 164 | ||
| 165 | if (pgd_none(READ_ONCE(*dst_pgdp))) { | ||
| 166 | dst_p4dp = trans_alloc(info); | ||
| 167 | if (!dst_p4dp) | ||
| 168 | return -ENOMEM; | ||
| 169 | pgd_populate(NULL, dst_pgdp, dst_p4dp); | ||
| 170 | } | ||
| 171 | |||
| 165 | dst_p4dp = p4d_offset(dst_pgdp, start); | 172 | dst_p4dp = p4d_offset(dst_pgdp, start); |
| 166 | src_p4dp = p4d_offset(src_pgdp, start); | 173 | src_p4dp = p4d_offset(src_pgdp, start); |
| 167 | do { | 174 | do { |
| @@ -76,27 +76,6 @@ extern const char *__cpu_full_name[]; · 75 unmodified lines | |||
| 76 | #define cpu_family_string() __cpu_family[raw_smp_processor_id()] | 76 | #define cpu_family_string() __cpu_family[raw_smp_processor_id()] |
| 77 | #define cpu_full_name_string() __cpu_full_name[raw_smp_processor_id()] | 77 | #define cpu_full_name_string() __cpu_full_name[raw_smp_processor_id()] |
| 78 | 78 | ||
| 79 | struct seq_file; | ||
| 80 | struct notifier_block; | ||
| 81 | |||
| 82 | extern int register_proc_cpuinfo_notifier(struct notifier_block *nb); | ||
| 83 | extern int proc_cpuinfo_notifier_call_chain(unsigned long val, void *v); | ||
| 84 | |||
| 85 | #define proc_cpuinfo_notifier(fn, pri) \ | ||
| 86 | ({ \ | ||
| 87 | static struct notifier_block fn##_nb = { \ | ||
| 88 | .notifier_call = fn, \ | ||
| 89 | .priority = pri \ | ||
| 90 | }; \ | ||
| 91 | \ | ||
| 92 | register_proc_cpuinfo_notifier(&fn##_nb); \ | ||
| 93 | }) | ||
| 94 | |||
| 95 | struct proc_cpuinfo_notifier_args { | ||
| 96 | struct seq_file *m; | ||
| 97 | unsigned long n; | ||
| 98 | }; | ||
| 99 | |||
| 100 | static inline bool cpus_are_siblings(int cpua, int cpub) | 79 | static inline bool cpus_are_siblings(int cpua, int cpub) |
| 101 | { | 80 | { |
| 102 | struct cpuinfo_loongarch *infoa = &cpu_data[cpua]; | 81 | struct cpuinfo_loongarch *infoa = &cpu_data[cpua]; |
| @@ -77,6 +77,8 @@ extern int __cpu_logical_map[NR_CPUS]; · 76 unmodified lines | |||
| 77 | #define SMP_IRQ_WORK BIT(ACTION_IRQ_WORK) | 77 | #define SMP_IRQ_WORK BIT(ACTION_IRQ_WORK) |
| 78 | #define SMP_CLEAR_VECTOR BIT(ACTION_CLEAR_VECTOR) | 78 | #define SMP_CLEAR_VECTOR BIT(ACTION_CLEAR_VECTOR) |
| 79 | 79 | ||
| 80 | struct seq_file; | ||
| 81 | |||
| 80 | struct secondary_data { | 82 | struct secondary_data { |
| 81 | unsigned long stack; | 83 | unsigned long stack; |
| 82 | unsigned long thread_info; | 84 | unsigned long thread_info; |
| @@ -18,16 +18,19 @@ · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | .align 5 | 19 | .align 5 |
| 20 | SYM_FUNC_START(__arch_cpu_idle) | 20 | SYM_FUNC_START(__arch_cpu_idle) |
| 21 | /* start of rollback region */ | 21 | /* start of idle interrupt region */ |
| 22 | LONG_L t0, tp, TI_FLAGS | 22 | ori t0, zero, CSR_CRMD_IE |
| 23 | nop | 23 | /* idle instruction needs irq enabled */ |
| 24 | andi t0, t0, _TIF_NEED_RESCHED | 24 | csrxchg t0, t0, LOONGARCH_CSR_CRMD |
| 25 | bnez t0, 1f | 25 | /* |
| 26 | nop | 26 | * If an interrupt lands here; between enabling interrupts above and |
| 27 | nop | 27 | * going idle on the next instruction, we must *NOT* go idle since the |
| 28 | nop | 28 | * interrupt could have set TIF_NEED_RESCHED or caused an timer to need |
| 29 | * reprogramming. Fall through -- see handle_vint() below -- and have | ||
| 30 | * the idle loop take care of things. | ||
| 31 | */ | ||
| 29 | idle 0 | 32 | idle 0 |
| 30 | /* end of rollback region */ | 33 | /* end of idle interrupt region */ |
| 31 | 1: jr ra | 34 | 1: jr ra |
| 32 | SYM_FUNC_END(__arch_cpu_idle) | 35 | SYM_FUNC_END(__arch_cpu_idle) |
| 33 | 36 | ||
| @@ -35,11 +38,10 @@ SYM_CODE_START(handle_vint) · 1 unmodified line | |||
| 35 | UNWIND_HINT_UNDEFINED | 38 | UNWIND_HINT_UNDEFINED |
| 36 | BACKUP_T0T1 | 39 | BACKUP_T0T1 |
| 37 | SAVE_ALL | 40 | SAVE_ALL |
| 38 | la_abs t1, __arch_cpu_idle | 41 | la_abs t1, 1b |
| 39 | LONG_L t0, sp, PT_ERA | 42 | LONG_L t0, sp, PT_ERA |
| 40 | /* 32 byte rollback region */ | 43 | /* 3 instructions idle interrupt region */ |
| 41 | ori t0, t0, 0x1f | 44 | ori t0, t0, 0b1100 |
| 42 | xori t0, t0, 0x1f | ||
| 43 | bne t0, t1, 1f | 45 | bne t0, t1, 1f |
| 44 | LONG_S t0, sp, PT_ERA | 46 | LONG_S t0, sp, PT_ERA |
| 45 | 1: move a0, sp | 47 | 1: move a0, sp |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | |||
| 11 | 11 | ||
| 12 | void __cpuidle arch_cpu_idle(void) | 12 | void __cpuidle arch_cpu_idle(void) |
| 13 | { | 13 | { |
| 14 | raw_local_irq_enable(); | 14 | __arch_cpu_idle(); |
| 15 | __arch_cpu_idle(); /* idle instruction needs irq enabled */ | ||
| 16 | raw_local_irq_disable(); | 15 | raw_local_irq_disable(); |
| 17 | } | 16 | } |
| @@ -13,28 +13,12 @@ · 12 unmodified lines | |||
| 13 | #include <asm/processor.h> | 13 | #include <asm/processor.h> |
| 14 | #include <asm/time.h> | 14 | #include <asm/time.h> |
| 15 | 15 | ||
| 16 | /* | ||
| 17 | * No lock; only written during early bootup by CPU 0. | ||
| 18 | */ | ||
| 19 | static RAW_NOTIFIER_HEAD(proc_cpuinfo_chain); | ||
| 20 | |||
| 21 | int __ref register_proc_cpuinfo_notifier(struct notifier_block *nb) | ||
| 22 | { | ||
| 23 | return raw_notifier_chain_register(&proc_cpuinfo_chain, nb); | ||
| 24 | } | ||
| 25 | |||
| 26 | int proc_cpuinfo_notifier_call_chain(unsigned long val, void *v) | ||
| 27 | { | ||
| 28 | return raw_notifier_call_chain(&proc_cpuinfo_chain, val, v); | ||
| 29 | } | ||
| 30 | |||
| 31 | static int show_cpuinfo(struct seq_file *m, void *v) | 16 | static int show_cpuinfo(struct seq_file *m, void *v) |
| 32 | { | 17 | { |
| 33 | unsigned long n = (unsigned long) v - 1; | 18 | unsigned long n = (unsigned long) v - 1; |
| 34 | unsigned int isa = cpu_data[n].isa_level; | 19 | unsigned int isa = cpu_data[n].isa_level; |
| 35 | unsigned int version = cpu_data[n].processor_id & 0xff; | 20 | unsigned int version = cpu_data[n].processor_id & 0xff; |
| 36 | unsigned int fp_version = cpu_data[n].fpu_vers; | 21 | unsigned int fp_version = cpu_data[n].fpu_vers; |
| 37 | struct proc_cpuinfo_notifier_args proc_cpuinfo_notifier_args; | ||
| 38 | 22 | ||
| 39 | #ifdef CONFIG_SMP | 23 | #ifdef CONFIG_SMP |
| 40 | if (!cpu_online(n)) | 24 | if (!cpu_online(n)) |
| @@ -91,20 +75,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) · 50 unmodified lines | |||
| 91 | if (cpu_has_lbt_mips) seq_printf(m, " lbt_mips"); | 75 | if (cpu_has_lbt_mips) seq_printf(m, " lbt_mips"); |
| 92 | seq_printf(m, "\n"); | 76 | seq_printf(m, "\n"); |
| 93 | 77 | ||
| 94 | seq_printf(m, "Hardware Watchpoint\t: %s", | 78 | seq_printf(m, "Hardware Watchpoint\t: %s", str_yes_no(cpu_has_watch)); |
| 95 | cpu_has_watch ? "yes, " : "no\n"); | ||
| 96 | if (cpu_has_watch) { | 79 | if (cpu_has_watch) { |
| 97 | seq_printf(m, "iwatch count: %d, dwatch count: %d\n", | 80 | seq_printf(m, ", iwatch count: %d, dwatch count: %d", |
| 98 | cpu_data[n].watch_ireg_count, cpu_data[n].watch_dreg_count); | 81 | cpu_data[n].watch_ireg_count, cpu_data[n].watch_dreg_count); |
| 99 | } | 82 | } |
| 100 | 83 | ||
| 101 | proc_cpuinfo_notifier_args.m = m; | 84 | seq_printf(m, "\n\n"); |
| 102 | proc_cpuinfo_notifier_args.n = n; | ||
| 103 | |||
| 104 | raw_notifier_call_chain(&proc_cpuinfo_chain, 0, | ||
| 105 | &proc_cpuinfo_notifier_args); | ||
| 106 | |||
| 107 | seq_printf(m, "\n"); | ||
| 108 | 85 | ||
| 109 | return 0; | 86 | return 0; |
| 110 | } | 87 | } |
| @@ -33,7 +33,7 @@ void machine_halt(void) · 32 unmodified lines | |||
| 33 | console_flush_on_panic(CONSOLE_FLUSH_PENDING); | 33 | console_flush_on_panic(CONSOLE_FLUSH_PENDING); |
| 34 | 34 | ||
| 35 | while (true) { | 35 | while (true) { |
| 36 | __arch_cpu_idle(); | 36 | __asm__ __volatile__("idle 0" : : : "memory"); |
| 37 | } | 37 | } |
| 38 | } | 38 | } |
| 39 | 39 | ||
| @@ -53,7 +53,7 @@ void machine_power_off(void) · 13 unmodified lines | |||
| 53 | #endif | 53 | #endif |
| 54 | 54 | ||
| 55 | while (true) { | 55 | while (true) { |
| 56 | __arch_cpu_idle(); | 56 | __asm__ __volatile__("idle 0" : : : "memory"); |
| 57 | } | 57 | } |
| 58 | } | 58 | } |
| 59 | 59 | ||
| @@ -74,6 +74,6 @@ void machine_restart(char *command) · 14 unmodified lines | |||
| 74 | acpi_reboot(); | 74 | acpi_reboot(); |
| 75 | 75 | ||
| 76 | while (true) { | 76 | while (true) { |
| 77 | __arch_cpu_idle(); | 77 | __asm__ __volatile__("idle 0" : : : "memory"); |
| 78 | } | 78 | } |
| 79 | } | 79 | } |
| @@ -303,9 +303,9 @@ int kvm_arch_enable_virtualization_cpu(void) · 302 unmodified lines | |||
| 303 | * TOE=0: Trap on Exception. | 303 | * TOE=0: Trap on Exception. |
| 304 | * TIT=0: Trap on Timer. | 304 | * TIT=0: Trap on Timer. |
| 305 | */ | 305 | */ |
| 306 | if (env & CSR_GCFG_GCIP_ALL) | 306 | if (env & CSR_GCFG_GCIP_SECURE) |
| 307 | gcfg |= CSR_GCFG_GCI_SECURE; | 307 | gcfg |= CSR_GCFG_GCI_SECURE; |
| 308 | if (env & CSR_GCFG_MATC_ROOT) | 308 | if (env & CSR_GCFG_MATP_ROOT) |
| 309 | gcfg |= CSR_GCFG_MATC_ROOT; | 309 | gcfg |= CSR_GCFG_MATC_ROOT; |
| 310 | 310 | ||
| 311 | write_csr_gcfg(gcfg); | 311 | write_csr_gcfg(gcfg); |
| @@ -85,7 +85,7 @@ · 84 unmodified lines | |||
| 85 | * Guest CRMD comes from separate GCSR_CRMD register | 85 | * Guest CRMD comes from separate GCSR_CRMD register |
| 86 | */ | 86 | */ |
| 87 | ori t0, zero, CSR_PRMD_PIE | 87 | ori t0, zero, CSR_PRMD_PIE |
| 88 | csrxchg t0, t0, LOONGARCH_CSR_PRMD | 88 | csrwr t0, LOONGARCH_CSR_PRMD |
| 89 | 89 | ||
| 90 | /* Set PVM bit to setup ertn to guest context */ | 90 | /* Set PVM bit to setup ertn to guest context */ |
| 91 | ori t0, zero, CSR_GSTAT_PVM | 91 | ori t0, zero, CSR_GSTAT_PVM |
| @@ -1548,9 +1548,6 @@ static int _kvm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) · 1547 unmodified lines | |||
| 1548 | 1548 | ||
| 1549 | /* Restore timer state regardless */ | 1549 | /* Restore timer state regardless */ |
| 1550 | kvm_restore_timer(vcpu); | 1550 | kvm_restore_timer(vcpu); |
| 1551 | |||
| 1552 | /* Control guest page CCA attribute */ | ||
| 1553 | change_csr_gcfg(CSR_GCFG_MATC_MASK, CSR_GCFG_MATC_ROOT); | ||
| 1554 | kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); | 1551 | kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); |
| 1555 | 1552 | ||
| 1556 | /* Restore hardware PMU CSRs */ | 1553 | /* Restore hardware PMU CSRs */ |
| @@ -25,7 +25,7 @@ unsigned int __no_sanitize_address do_csum(const unsigned char *buff, int len) · 24 unmodified lines | |||
| 25 | const u64 *ptr; | 25 | const u64 *ptr; |
| 26 | u64 data, sum64 = 0; | 26 | u64 data, sum64 = 0; |
| 27 | 27 | ||
| 28 | if (unlikely(len == 0)) | 28 | if (unlikely(len <= 0)) |
| 29 | return 0; | 29 | return 0; |
| 30 | 30 | ||
| 31 | offset = (unsigned long)buff & 7; | 31 | offset = (unsigned long)buff & 7; |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | * Copyright (C) 2024 Loongson Technology Corporation Limited | 3 | * Copyright (C) 2024 Loongson Technology Corporation Limited |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/memblock.h> | ||
| 6 | #include <linux/pagewalk.h> | 7 | #include <linux/pagewalk.h> |
| 7 | #include <linux/pgtable.h> | 8 | #include <linux/pgtable.h> |
| 8 | #include <asm/set_memory.h> | 9 | #include <asm/set_memory.h> |
| @@ -167,7 +168,7 @@ bool kernel_page_present(struct page *page) · 158 unmodified lines | |||
| 167 | unsigned long addr = (unsigned long)page_address(page); | 168 | unsigned long addr = (unsigned long)page_address(page); |
| 168 | 169 | ||
| 169 | if (addr < vm_map_base) | 170 | if (addr < vm_map_base) |
| 170 | return true; | 171 | return memblock_is_memory(__pa(addr)); |
| 171 | 172 | ||
| 172 | pgd = pgd_offset_k(addr); | 173 | pgd = pgd_offset_k(addr); |
| 173 | if (pgd_none(pgdp_get(pgd))) | 174 | if (pgd_none(pgdp_get(pgd))) |
| @@ -27,8 +27,8 @@ · 26 unmodified lines | |||
| 27 | */ | 27 | */ |
| 28 | struct pt_regs { | 28 | struct pt_regs { |
| 29 | #ifdef CONFIG_32BIT | 29 | #ifdef CONFIG_32BIT |
| 30 | /* Pad bytes for argument save space on the stack. */ | 30 | /* Saved syscall stack arguments; entries 0-3 unused. */ |
| 31 | unsigned long pad0[8]; | 31 | unsigned long args[8]; |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | /* Saved main processor registers. */ | 34 | /* Saved main processor registers. */ |
| @@ -57,37 +57,21 @@ static inline void mips_syscall_update_nr(struct task_struct *task, · 56 unmodified lines | |||
| 57 | static inline void mips_get_syscall_arg(unsigned long *arg, | 57 | static inline void mips_get_syscall_arg(unsigned long *arg, |
| 58 | struct task_struct *task, struct pt_regs *regs, unsigned int n) | 58 | struct task_struct *task, struct pt_regs *regs, unsigned int n) |
| 59 | { | 59 | { |
| 60 | unsigned long usp __maybe_unused = regs->regs[29]; | 60 | #ifdef CONFIG_32BIT |
| 61 | |||
| 62 | switch (n) { | 61 | switch (n) { |
| 63 | case 0: case 1: case 2: case 3: | 62 | case 0: case 1: case 2: case 3: |
| 64 | *arg = regs->regs[4 + n]; | 63 | *arg = regs->regs[4 + n]; |
| 65 | |||
| 66 | return; | ||
| 67 | |||
| 68 | #ifdef CONFIG_32BIT | ||
| 69 | case 4: case 5: case 6: case 7: | ||
| 70 | get_user(*arg, (int *)usp + n); | ||
| 71 | return; | 64 | return; |
| 72 | #endif | ||
| 73 | |||
| 74 | #ifdef CONFIG_64BIT | ||
| 75 | case 4: case 5: case 6: case 7: | 65 | case 4: case 5: case 6: case 7: |
| 76 | #ifdef CONFIG_MIPS32_O32 | 66 | *arg = regs->args[n]; |
| 77 | if (test_tsk_thread_flag(task, TIF_32BIT_REGS)) | ||
| 78 | get_user(*arg, (int *)usp + n); | ||
| 79 | else | ||
| 80 | #endif | ||
| 81 | *arg = regs->regs[4 + n]; | ||
| 82 | |||
| 83 | return; | 67 | return; |
| 84 | #endif | ||
| 85 | |||
| 86 | default: | ||
| 87 | BUG(); | ||
| 88 | } | 68 | } |
| 89 | 69 | #else | |
| 90 | unreachable(); | 70 | *arg = regs->regs[4 + n]; |
| 71 | if ((IS_ENABLED(CONFIG_MIPS32_O32) && | ||
| 72 | test_tsk_thread_flag(task, TIF_32BIT_REGS))) | ||
| 73 | *arg = (unsigned int)*arg; | ||
| 74 | #endif | ||
| 91 | } | 75 | } |
| 92 | 76 | ||
| 93 | static inline long syscall_get_error(struct task_struct *task, | 77 | static inline long syscall_get_error(struct task_struct *task, |
| @@ -27,6 +27,12 @@ void output_ptreg_defines(void); · 26 unmodified lines | |||
| 27 | void output_ptreg_defines(void) | 27 | void output_ptreg_defines(void) |
| 28 | { | 28 | { |
| 29 | COMMENT("MIPS pt_regs offsets."); | 29 | COMMENT("MIPS pt_regs offsets."); |
| 30 | #ifdef CONFIG_32BIT | ||
| 31 | OFFSET(PT_ARG4, pt_regs, args[4]); | ||
| 32 | OFFSET(PT_ARG5, pt_regs, args[5]); | ||
| 33 | OFFSET(PT_ARG6, pt_regs, args[6]); | ||
| 34 | OFFSET(PT_ARG7, pt_regs, args[7]); | ||
| 35 | #endif | ||
| 30 | OFFSET(PT_R0, pt_regs, regs[0]); | 36 | OFFSET(PT_R0, pt_regs, regs[0]); |
| 31 | OFFSET(PT_R1, pt_regs, regs[1]); | 37 | OFFSET(PT_R1, pt_regs, regs[1]); |
| 32 | OFFSET(PT_R2, pt_regs, regs[2]); | 38 | OFFSET(PT_R2, pt_regs, regs[2]); |
| @@ -64,10 +64,10 @@ load_a6: user_lw(t7, 24(t0)) # argument #7 from usp · 63 unmodified lines | |||
| 64 | load_a7: user_lw(t8, 28(t0)) # argument #8 from usp | 64 | load_a7: user_lw(t8, 28(t0)) # argument #8 from usp |
| 65 | loads_done: | 65 | loads_done: |
| 66 | 66 | ||
| 67 | sw t5, 16(sp) # argument #5 to ksp | 67 | sw t5, PT_ARG4(sp) # argument #5 to ksp |
| 68 | sw t6, 20(sp) # argument #6 to ksp | 68 | sw t6, PT_ARG5(sp) # argument #6 to ksp |
| 69 | sw t7, 24(sp) # argument #7 to ksp | 69 | sw t7, PT_ARG6(sp) # argument #7 to ksp |
| 70 | sw t8, 28(sp) # argument #8 to ksp | 70 | sw t8, PT_ARG7(sp) # argument #8 to ksp |
| 71 | .set pop | 71 | .set pop |
| 72 | 72 | ||
| 73 | .section __ex_table,"a" | 73 | .section __ex_table,"a" |
| @@ -77,9 +77,17 @@ · 76 unmodified lines | |||
| 77 | /* | 77 | /* |
| 78 | * With 4K page size the real_pte machinery is all nops. | 78 | * With 4K page size the real_pte machinery is all nops. |
| 79 | */ | 79 | */ |
| 80 | #define __real_pte(e, p, o) ((real_pte_t){(e)}) | 80 | static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep, int offset) |
| 81 | { | ||
| 82 | return (real_pte_t){pte}; | ||
| 83 | } | ||
| 84 | |||
| 81 | #define __rpte_to_pte(r) ((r).pte) | 85 | #define __rpte_to_pte(r) ((r).pte) |
| 82 | #define __rpte_to_hidx(r,index) (pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT) | 86 | |
| 87 | static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index) | ||
| 88 | { | ||
| 89 | return pte_val(__rpte_to_pte(rpte)) >> H_PAGE_F_GIX_SHIFT; | ||
| 90 | } | ||
| 83 | 91 | ||
| 84 | #define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ | 92 | #define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ |
| 85 | do { \ | 93 | do { \ |
| @@ -108,7 +108,7 @@ static int text_area_cpu_up(unsigned int cpu) · 107 unmodified lines | |||
| 108 | unsigned long addr; | 108 | unsigned long addr; |
| 109 | int err; | 109 | int err; |
| 110 | 110 | ||
| 111 | area = get_vm_area(PAGE_SIZE, VM_ALLOC); | 111 | area = get_vm_area(PAGE_SIZE, 0); |
| 112 | if (!area) { | 112 | if (!area) { |
| 113 | WARN_ONCE(1, "Failed to create text area for cpu %d\n", | 113 | WARN_ONCE(1, "Failed to create text area for cpu %d\n", |
| 114 | cpu); | 114 | cpu); |
| @@ -493,7 +493,9 @@ static int __do_patch_instructions_mm(u32 *addr, u32 *code, size_t len, bool rep · 378 unmodified lines | |||
| 493 | 493 | ||
| 494 | orig_mm = start_using_temp_mm(patching_mm); | 494 | orig_mm = start_using_temp_mm(patching_mm); |
| 495 | 495 | ||
| 496 | kasan_disable_current(); | ||
| 496 | err = __patch_instructions(patch_addr, code, len, repeat_instr); | 497 | err = __patch_instructions(patch_addr, code, len, repeat_instr); |
| 498 | kasan_enable_current(); | ||
| 497 | 499 | ||
| 498 | /* context synchronisation performed by __patch_instructions */ | 500 | /* context synchronisation performed by __patch_instructions */ |
| 499 | stop_using_temp_mm(patching_mm, orig_mm); | 501 | stop_using_temp_mm(patching_mm, orig_mm); |
| @@ -75,7 +75,7 @@ static void fsl_msi_print_chip(struct irq_data *irqd, struct seq_file *p) · 74 unmodified lines | |||
| 75 | srs = (hwirq >> msi_data->srs_shift) & MSI_SRS_MASK; | 75 | srs = (hwirq >> msi_data->srs_shift) & MSI_SRS_MASK; |
| 76 | cascade_virq = msi_data->cascade_array[srs]->virq; | 76 | cascade_virq = msi_data->cascade_array[srs]->virq; |
| 77 | 77 | ||
| 78 | seq_printf(p, " fsl-msi-%d", cascade_virq); | 78 | seq_printf(p, "fsl-msi-%d", cascade_virq); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | 81 | ||
| @@ -740,7 +740,6 @@ CONFIG_IMA=y · 739 unmodified lines | |||
| 740 | CONFIG_IMA_DEFAULT_HASH_SHA256=y | 740 | CONFIG_IMA_DEFAULT_HASH_SHA256=y |
| 741 | CONFIG_IMA_WRITE_POLICY=y | 741 | CONFIG_IMA_WRITE_POLICY=y |
| 742 | CONFIG_IMA_APPRAISE=y | 742 | CONFIG_IMA_APPRAISE=y |
| 743 | CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" | ||
| 744 | CONFIG_BUG_ON_DATA_CORRUPTION=y | 743 | CONFIG_BUG_ON_DATA_CORRUPTION=y |
| 745 | CONFIG_CRYPTO_USER=m | 744 | CONFIG_CRYPTO_USER=m |
| 746 | # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set | 745 | # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set |
| @@ -725,7 +725,6 @@ CONFIG_IMA=y · 724 unmodified lines | |||
| 725 | CONFIG_IMA_DEFAULT_HASH_SHA256=y | 725 | CONFIG_IMA_DEFAULT_HASH_SHA256=y |
| 726 | CONFIG_IMA_WRITE_POLICY=y | 726 | CONFIG_IMA_WRITE_POLICY=y |
| 727 | CONFIG_IMA_APPRAISE=y | 727 | CONFIG_IMA_APPRAISE=y |
| 728 | CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" | ||
| 729 | CONFIG_BUG_ON_DATA_CORRUPTION=y | 728 | CONFIG_BUG_ON_DATA_CORRUPTION=y |
| 730 | CONFIG_CRYPTO_FIPS=y | 729 | CONFIG_CRYPTO_FIPS=y |
| 731 | CONFIG_CRYPTO_USER=m | 730 | CONFIG_CRYPTO_USER=m |
| @@ -62,7 +62,6 @@ CONFIG_ZFCP=y · 61 unmodified lines | |||
| 62 | # CONFIG_INOTIFY_USER is not set | 62 | # CONFIG_INOTIFY_USER is not set |
| 63 | # CONFIG_MISC_FILESYSTEMS is not set | 63 | # CONFIG_MISC_FILESYSTEMS is not set |
| 64 | # CONFIG_NETWORK_FILESYSTEMS is not set | 64 | # CONFIG_NETWORK_FILESYSTEMS is not set |
| 65 | CONFIG_LSM="yama,loadpin,safesetid,integrity" | ||
| 66 | # CONFIG_ZLIB_DFLTCC is not set | 65 | # CONFIG_ZLIB_DFLTCC is not set |
| 67 | CONFIG_XZ_DEC_MICROLZMA=y | 66 | CONFIG_XZ_DEC_MICROLZMA=y |
| 68 | CONFIG_PRINTK_TIME=y | 67 | CONFIG_PRINTK_TIME=y |
| @@ -53,7 +53,11 @@ static __always_inline bool arch_test_bit(unsigned long nr, const volatile unsig · 52 unmodified lines | |||
| 53 | unsigned long mask; | 53 | unsigned long mask; |
| 54 | int cc; | 54 | int cc; |
| 55 | 55 | ||
| 56 | if (__builtin_constant_p(nr)) { | 56 | /* |
| 57 | * With CONFIG_PROFILE_ALL_BRANCHES enabled gcc fails to | ||
| 58 | * handle __builtin_constant_p() in some cases. | ||
| 59 | */ | ||
| 60 | if (!IS_ENABLED(CONFIG_PROFILE_ALL_BRANCHES) && __builtin_constant_p(nr)) { | ||
| 57 | addr = (const volatile unsigned char *)ptr; | 61 | addr = (const volatile unsigned char *)ptr; |
| 58 | addr += (nr ^ (BITS_PER_LONG - BITS_PER_BYTE)) / BITS_PER_BYTE; | 62 | addr += (nr ^ (BITS_PER_LONG - BITS_PER_BYTE)) / BITS_PER_BYTE; |
| 59 | mask = 1UL << (nr & (BITS_PER_BYTE - 1)); | 63 | mask = 1UL << (nr & (BITS_PER_BYTE - 1)); |
| @@ -23,7 +23,6 @@ · 22 unmodified lines | |||
| 23 | /** | 23 | /** |
| 24 | * struct gmap_struct - guest address space | 24 | * struct gmap_struct - guest address space |
| 25 | * @list: list head for the mm->context gmap list | 25 | * @list: list head for the mm->context gmap list |
| 26 | * @crst_list: list of all crst tables used in the guest address space | ||
| 27 | * @mm: pointer to the parent mm_struct | 26 | * @mm: pointer to the parent mm_struct |
| 28 | * @guest_to_host: radix tree with guest to host address translation | 27 | * @guest_to_host: radix tree with guest to host address translation |
| 29 | * @host_to_guest: radix tree with pointer to segment table entries | 28 | * @host_to_guest: radix tree with pointer to segment table entries |
| @@ -35,7 +34,6 @@ · 5 unmodified lines | |||
| 35 | * @guest_handle: protected virtual machine handle for the ultravisor | 34 | * @guest_handle: protected virtual machine handle for the ultravisor |
| 36 | * @host_to_rmap: radix tree with gmap_rmap lists | 35 | * @host_to_rmap: radix tree with gmap_rmap lists |
| 37 | * @children: list of shadow gmap structures | 36 | * @children: list of shadow gmap structures |
| 38 | * @pt_list: list of all page tables used in the shadow guest address space | ||
| 39 | * @shadow_lock: spinlock to protect the shadow gmap list | 37 | * @shadow_lock: spinlock to protect the shadow gmap list |
| 40 | * @parent: pointer to the parent gmap for shadow guest address spaces | 38 | * @parent: pointer to the parent gmap for shadow guest address spaces |
| 41 | * @orig_asce: ASCE for which the shadow page table has been created | 39 | * @orig_asce: ASCE for which the shadow page table has been created |
| @@ -45,7 +43,6 @@ · 3 unmodified lines | |||
| 45 | */ | 43 | */ |
| 46 | struct gmap { | 44 | struct gmap { |
| 47 | struct list_head list; | 45 | struct list_head list; |
| 48 | struct list_head crst_list; | ||
| 49 | struct mm_struct *mm; | 46 | struct mm_struct *mm; |
| 50 | struct radix_tree_root guest_to_host; | 47 | struct radix_tree_root guest_to_host; |
| 51 | struct radix_tree_root host_to_guest; | 48 | struct radix_tree_root host_to_guest; |
| @@ -61,7 +58,6 @@ struct gmap { · 9 unmodified lines | |||
| 61 | /* Additional data for shadow guest address spaces */ | 58 | /* Additional data for shadow guest address spaces */ |
| 62 | struct radix_tree_root host_to_rmap; | 59 | struct radix_tree_root host_to_rmap; |
| 63 | struct list_head children; | 60 | struct list_head children; |
| 64 | struct list_head pt_list; | ||
| 65 | spinlock_t shadow_lock; | 61 | spinlock_t shadow_lock; |
| 66 | struct gmap *parent; | 62 | struct gmap *parent; |
| 67 | unsigned long orig_asce; | 63 | unsigned long orig_asce; |
| @@ -106,23 +102,21 @@ struct gmap *gmap_create(struct mm_struct *mm, unsigned long limit); · 38 unmodified lines | |||
| 106 | void gmap_remove(struct gmap *gmap); | 102 | void gmap_remove(struct gmap *gmap); |
| 107 | struct gmap *gmap_get(struct gmap *gmap); | 103 | struct gmap *gmap_get(struct gmap *gmap); |
| 108 | void gmap_put(struct gmap *gmap); | 104 | void gmap_put(struct gmap *gmap); |
| 105 | void gmap_free(struct gmap *gmap); | ||
| 106 | struct gmap *gmap_alloc(unsigned long limit); | ||
| 109 | 107 | ||
| 110 | int gmap_map_segment(struct gmap *gmap, unsigned long from, | 108 | int gmap_map_segment(struct gmap *gmap, unsigned long from, |
| 111 | unsigned long to, unsigned long len); | 109 | unsigned long to, unsigned long len); |
| 112 | int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len); | 110 | int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len); |
| 113 | unsigned long __gmap_translate(struct gmap *, unsigned long gaddr); | 111 | unsigned long __gmap_translate(struct gmap *, unsigned long gaddr); |
| 114 | unsigned long gmap_translate(struct gmap *, unsigned long gaddr); | ||
| 115 | int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr); | 112 | int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr); |
| 116 | int gmap_fault(struct gmap *, unsigned long gaddr, unsigned int fault_flags); | ||
| 117 | void gmap_discard(struct gmap *, unsigned long from, unsigned long to); | 113 | void gmap_discard(struct gmap *, unsigned long from, unsigned long to); |
| 118 | void __gmap_zap(struct gmap *, unsigned long gaddr); | 114 | void __gmap_zap(struct gmap *, unsigned long gaddr); |
| 119 | void gmap_unlink(struct mm_struct *, unsigned long *table, unsigned long vmaddr); | 115 | void gmap_unlink(struct mm_struct *, unsigned long *table, unsigned long vmaddr); |
| 120 | 116 | ||
| 121 | int gmap_read_table(struct gmap *gmap, unsigned long gaddr, unsigned long *val); | 117 | int gmap_read_table(struct gmap *gmap, unsigned long gaddr, unsigned long *val); |
| 122 | 118 | ||
| 123 | struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce, | 119 | void gmap_unshadow(struct gmap *sg); |
| 124 | int edat_level); | ||
| 125 | int gmap_shadow_valid(struct gmap *sg, unsigned long asce, int edat_level); | ||
| 126 | int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t, | 120 | int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t, |
| 127 | int fake); | 121 | int fake); |
| 128 | int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t, | 122 | int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t, |
| @@ -131,24 +125,22 @@ int gmap_shadow_sgt(struct gmap *sg, unsigned long saddr, unsigned long sgt, · 2 unmodified lines | |||
| 131 | int fake); | 125 | int fake); |
| 132 | int gmap_shadow_pgt(struct gmap *sg, unsigned long saddr, unsigned long pgt, | 126 | int gmap_shadow_pgt(struct gmap *sg, unsigned long saddr, unsigned long pgt, |
| 133 | int fake); | 127 | int fake); |
| 134 | int gmap_shadow_pgt_lookup(struct gmap *sg, unsigned long saddr, | ||
| 135 | unsigned long *pgt, int *dat_protection, int *fake); | ||
| 136 | int gmap_shadow_page(struct gmap *sg, unsigned long saddr, pte_t pte); | 128 | int gmap_shadow_page(struct gmap *sg, unsigned long saddr, pte_t pte); |
| 137 | 129 | ||
| 138 | void gmap_register_pte_notifier(struct gmap_notifier *); | 130 | void gmap_register_pte_notifier(struct gmap_notifier *); |
| 139 | void gmap_unregister_pte_notifier(struct gmap_notifier *); | 131 | void gmap_unregister_pte_notifier(struct gmap_notifier *); |
| 140 | 132 | ||
| 141 | int gmap_mprotect_notify(struct gmap *, unsigned long start, | 133 | int gmap_protect_one(struct gmap *gmap, unsigned long gaddr, int prot, unsigned long bits); |
| 142 | unsigned long len, int prot); | ||
| 143 | 134 | ||
| 144 | void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4], | 135 | void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4], |
| 145 | unsigned long gaddr, unsigned long vmaddr); | 136 | unsigned long gaddr, unsigned long vmaddr); |
| 146 | int s390_disable_cow_sharing(void); | 137 | int s390_disable_cow_sharing(void); |
| 147 | void s390_unlist_old_asce(struct gmap *gmap); | ||
| 148 | int s390_replace_asce(struct gmap *gmap); | 138 | int s390_replace_asce(struct gmap *gmap); |
| 149 | void s390_uv_destroy_pfns(unsigned long count, unsigned long *pfns); | 139 | void s390_uv_destroy_pfns(unsigned long count, unsigned long *pfns); |
| 150 | int __s390_uv_destroy_range(struct mm_struct *mm, unsigned long start, | 140 | int __s390_uv_destroy_range(struct mm_struct *mm, unsigned long start, |
| 151 | unsigned long end, bool interruptible); | 141 | unsigned long end, bool interruptible); |
| 142 | int kvm_s390_wiggle_split_folio(struct mm_struct *mm, struct folio *folio, bool split); | ||
| 143 | unsigned long *gmap_table_walk(struct gmap *gmap, unsigned long gaddr, int level); | ||
| 152 | 144 | ||
| 153 | /** | 145 | /** |
| 154 | * s390_uv_destroy_range - Destroy a range of pages in the given mm. | 146 | * s390_uv_destroy_range - Destroy a range of pages in the given mm. |
| @@ -30,6 +30,8 @@ · 29 unmodified lines | |||
| 30 | #define KVM_S390_ESCA_CPU_SLOTS 248 | 30 | #define KVM_S390_ESCA_CPU_SLOTS 248 |
| 31 | #define KVM_MAX_VCPUS 255 | 31 | #define KVM_MAX_VCPUS 255 |
| 32 | 32 | ||
| 33 | #define KVM_INTERNAL_MEM_SLOTS 1 | ||
| 34 | |||
| 33 | /* | 35 | /* |
| 34 | * These seem to be used for allocating ->chip in the routing table, which we | 36 | * These seem to be used for allocating ->chip in the routing table, which we |
| 35 | * don't use. 1 is as small as we can get to reduce the needed memory. If we | 37 | * don't use. 1 is as small as we can get to reduce the needed memory. If we |
| @@ -931,12 +933,14 @@ struct sie_page2 { · 895 unmodified lines | |||
| 931 | u8 reserved928[0x1000 - 0x928]; /* 0x0928 */ | 933 | u8 reserved928[0x1000 - 0x928]; /* 0x0928 */ |
| 932 | }; | 934 | }; |
| 933 | 935 | ||
| 936 | struct vsie_page; | ||
| 937 | |||
| 934 | struct kvm_s390_vsie { | 938 | struct kvm_s390_vsie { |
| 935 | struct mutex mutex; | 939 | struct mutex mutex; |
| 936 | struct radix_tree_root addr_to_page; | 940 | struct radix_tree_root addr_to_page; |
| 937 | int page_count; | 941 | int page_count; |
| 938 | int next; | 942 | int next; |
| 939 | struct page *pages[KVM_MAX_VCPUS]; | 943 | struct vsie_page *pages[KVM_MAX_VCPUS]; |
| 940 | }; | 944 | }; |
| 941 | 945 | ||
| 942 | struct kvm_s390_gisa_iam { | 946 | struct kvm_s390_gisa_iam { |
| @@ -420,9 +420,10 @@ void setup_protection_map(void); · 419 unmodified lines | |||
| 420 | #define PGSTE_HC_BIT 0x0020000000000000UL | 420 | #define PGSTE_HC_BIT 0x0020000000000000UL |
| 421 | #define PGSTE_GR_BIT 0x0004000000000000UL | 421 | #define PGSTE_GR_BIT 0x0004000000000000UL |
| 422 | #define PGSTE_GC_BIT 0x0002000000000000UL | 422 | #define PGSTE_GC_BIT 0x0002000000000000UL |
| 423 | #define PGSTE_UC_BIT 0x0000800000000000UL /* user dirty (migration) */ | 423 | #define PGSTE_ST2_MASK 0x0000ffff00000000UL |
| 424 | #define PGSTE_IN_BIT 0x0000400000000000UL /* IPTE notify bit */ | 424 | #define PGSTE_UC_BIT 0x0000000000008000UL /* user dirty (migration) */ |
| 425 | #define PGSTE_VSIE_BIT 0x0000200000000000UL /* ref'd in a shadow table */ | 425 | #define PGSTE_IN_BIT 0x0000000000004000UL /* IPTE notify bit */ |
| 426 | #define PGSTE_VSIE_BIT 0x0000000000002000UL /* ref'd in a shadow table */ | ||
| 426 | 427 | ||
| 427 | /* Guest Page State used for virtualization */ | 428 | /* Guest Page State used for virtualization */ |
| 428 | #define _PGSTE_GPS_ZERO 0x0000000080000000UL | 429 | #define _PGSTE_GPS_ZERO 0x0000000080000000UL |
| @@ -2007,4 +2008,18 @@ extern void s390_reset_cmma(struct mm_struct *mm); · 1578 unmodified lines | |||
| 2007 | #define pmd_pgtable(pmd) \ | 2008 | #define pmd_pgtable(pmd) \ |
| 2008 | ((pgtable_t)__va(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE)) | 2009 | ((pgtable_t)__va(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE)) |
| 2009 | 2010 | ||
| 2011 | static inline unsigned long gmap_pgste_get_pgt_addr(unsigned long *pgt) | ||
| 2012 | { | ||
| 2013 | unsigned long *pgstes, res; | ||
| 2014 | |||
| 2015 | pgstes = pgt + _PAGE_ENTRIES; | ||
| 2016 | |||
| 2017 | res = (pgstes[0] & PGSTE_ST2_MASK) << 16; | ||
| 2018 | res |= pgstes[1] & PGSTE_ST2_MASK; | ||
| 2019 | res |= (pgstes[2] & PGSTE_ST2_MASK) >> 16; | ||
| 2020 | res |= (pgstes[3] & PGSTE_ST2_MASK) >> 32; | ||
| 2021 | |||
| 2022 | return res; | ||
| 2023 | } | ||
| 2024 | |||
| 2010 | #endif /* _S390_PAGE_H */ | 2025 | #endif /* _S390_PAGE_H */ |
| @@ -628,12 +628,12 @@ static inline int is_prot_virt_host(void) · 627 unmodified lines | |||
| 628 | } | 628 | } |
| 629 | 629 | ||
| 630 | int uv_pin_shared(unsigned long paddr); | 630 | int uv_pin_shared(unsigned long paddr); |
| 631 | int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb); | ||
| 632 | int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr); | ||
| 633 | int uv_destroy_folio(struct folio *folio); | 631 | int uv_destroy_folio(struct folio *folio); |
| 634 | int uv_destroy_pte(pte_t pte); | 632 | int uv_destroy_pte(pte_t pte); |
| 635 | int uv_convert_from_secure_pte(pte_t pte); | 633 | int uv_convert_from_secure_pte(pte_t pte); |
| 636 | int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr); | 634 | int make_folio_secure(struct folio *folio, struct uv_cb_header *uvcb); |
| 635 | int uv_convert_from_secure(unsigned long paddr); | ||
| 636 | int uv_convert_from_secure_folio(struct folio *folio); | ||
| 637 | 637 | ||
| 638 | void setup_uv(void); | 638 | void setup_uv(void); |
| 639 | 639 | ||
| @@ -19,19 +19,6 @@ · 18 unmodified lines | |||
| 19 | #include <asm/sections.h> | 19 | #include <asm/sections.h> |
| 20 | #include <asm/uv.h> | 20 | #include <asm/uv.h> |
| 21 | 21 | ||
| 22 | #if !IS_ENABLED(CONFIG_KVM) | ||
| 23 | unsigned long __gmap_translate(struct gmap *gmap, unsigned long gaddr) | ||
| 24 | { | ||
| 25 | return 0; | ||
| 26 | } | ||
| 27 | |||
| 28 | int gmap_fault(struct gmap *gmap, unsigned long gaddr, | ||
| 29 | unsigned int fault_flags) | ||
| 30 | { | ||
| 31 | return 0; | ||
| 32 | } | ||
| 33 | #endif | ||
| 34 | |||
| 35 | /* the bootdata_preserved fields come from ones in arch/s390/boot/uv.c */ | 22 | /* the bootdata_preserved fields come from ones in arch/s390/boot/uv.c */ |
| 36 | int __bootdata_preserved(prot_virt_guest); | 23 | int __bootdata_preserved(prot_virt_guest); |
| 37 | EXPORT_SYMBOL(prot_virt_guest); | 24 | EXPORT_SYMBOL(prot_virt_guest); |
| @@ -159,6 +146,7 @@ int uv_destroy_folio(struct folio *folio) · 121 unmodified lines | |||
| 159 | folio_put(folio); | 146 | folio_put(folio); |
| 160 | return rc; | 147 | return rc; |
| 161 | } | 148 | } |
| 149 | EXPORT_SYMBOL(uv_destroy_folio); | ||
| 162 | 150 | ||
| 163 | /* | 151 | /* |
| 164 | * The present PTE still indirectly holds a folio reference through the mapping. | 152 | * The present PTE still indirectly holds a folio reference through the mapping. |
| @@ -175,7 +163,7 @@ int uv_destroy_pte(pte_t pte) · 10 unmodified lines | |||
| 175 | * | 163 | * |
| 176 | * @paddr: Absolute host address of page to be exported | 164 | * @paddr: Absolute host address of page to be exported |
| 177 | */ | 165 | */ |
| 178 | static int uv_convert_from_secure(unsigned long paddr) | 166 | int uv_convert_from_secure(unsigned long paddr) |
| 179 | { | 167 | { |
| 180 | struct uv_cb_cfs uvcb = { | 168 | struct uv_cb_cfs uvcb = { |
| 181 | .header.cmd = UVC_CMD_CONV_FROM_SEC_STOR, | 169 | .header.cmd = UVC_CMD_CONV_FROM_SEC_STOR, |
| @@ -187,11 +175,12 @@ static int uv_convert_from_secure(unsigned long paddr) · 5 unmodified lines | |||
| 187 | return -EINVAL; | 175 | return -EINVAL; |
| 188 | return 0; | 176 | return 0; |
| 189 | } | 177 | } |
| 178 | EXPORT_SYMBOL_GPL(uv_convert_from_secure); | ||
| 190 | 179 | ||
| 191 | /* | 180 | /* |
| 192 | * The caller must already hold a reference to the folio. | 181 | * The caller must already hold a reference to the folio. |
| 193 | */ | 182 | */ |
| 194 | static int uv_convert_from_secure_folio(struct folio *folio) | 183 | int uv_convert_from_secure_folio(struct folio *folio) |
| 195 | { | 184 | { |
| 196 | int rc; | 185 | int rc; |
| 197 | 186 | ||
| @@ -206,6 +195,7 @@ static int uv_convert_from_secure_folio(struct folio *folio) · 8 unmodified lines | |||
| 206 | folio_put(folio); | 195 | folio_put(folio); |
| 207 | return rc; | 196 | return rc; |
| 208 | } | 197 | } |
| 198 | EXPORT_SYMBOL_GPL(uv_convert_from_secure_folio); | ||
| 209 | 199 | ||
| 210 | /* | 200 | /* |
| 211 | * The present PTE still indirectly holds a folio reference through the mapping. | 201 | * The present PTE still indirectly holds a folio reference through the mapping. |
| @@ -237,13 +227,33 @@ static int expected_folio_refs(struct folio *folio) · 25 unmodified lines | |||
| 237 | return res; | 227 | return res; |
| 238 | } | 228 | } |
| 239 | 229 | ||
| 240 | static int make_folio_secure(struct folio *folio, struct uv_cb_header *uvcb) | 230 | /** |
| 231 | * make_folio_secure() - make a folio secure | ||
| 232 | * @folio: the folio to make secure | ||
| 233 | * @uvcb: the uvcb that describes the UVC to be used | ||
| 234 | * | ||
| 235 | * The folio @folio will be made secure if possible, @uvcb will be passed | ||
| 236 | * as-is to the UVC. | ||
| 237 | * | ||
| 238 | * Return: 0 on success; | ||
| 239 | * -EBUSY if the folio is in writeback or has too many references; | ||
| 240 | * -E2BIG if the folio is large; | ||
| 241 | * -EAGAIN if the UVC needs to be attempted again; | ||
| 242 | * -ENXIO if the address is not mapped; | ||
| 243 | * -EINVAL if the UVC failed for other reasons. | ||
| 244 | * | ||
| 245 | * Context: The caller must hold exactly one extra reference on the folio | ||
| 246 | * (it's the same logic as split_folio()) | ||
| 247 | */ | ||
| 248 | int make_folio_secure(struct folio *folio, struct uv_cb_header *uvcb) | ||
| 241 | { | 249 | { |
| 242 | int expected, cc = 0; | 250 | int expected, cc = 0; |
| 243 | 251 | ||
| 252 | if (folio_test_large(folio)) | ||
| 253 | return -E2BIG; | ||
| 244 | if (folio_test_writeback(folio)) | 254 | if (folio_test_writeback(folio)) |
| 245 | return -EAGAIN; | 255 | return -EBUSY; |
| 246 | expected = expected_folio_refs(folio); | 256 | expected = expected_folio_refs(folio) + 1; |
| 247 | if (!folio_ref_freeze(folio, expected)) | 257 | if (!folio_ref_freeze(folio, expected)) |
| 248 | return -EBUSY; | 258 | return -EBUSY; |
| 249 | set_bit(PG_arch_1, &folio->flags); | 259 | set_bit(PG_arch_1, &folio->flags); |
| @@ -267,251 +277,7 @@ static int make_folio_secure(struct folio *folio, struct uv_cb_header *uvcb) · 17 unmodified lines | |||
| 267 | return -EAGAIN; | 277 | return -EAGAIN; |
| 268 | return uvcb->rc == 0x10a ? -ENXIO : -EINVAL; | 278 | return uvcb->rc == 0x10a ? -ENXIO : -EINVAL; |
| 269 | } | 279 | } |
| 270 | 280 | EXPORT_SYMBOL_GPL(make_folio_secure); | |
| 271 | /** | ||
| 272 | * should_export_before_import - Determine whether an export is needed | ||
| 273 | * before an import-like operation | ||
| 274 | * @uvcb: the Ultravisor control block of the UVC to be performed | ||
| 275 | * @mm: the mm of the process | ||
| 276 | * | ||
| 277 | * Returns whether an export is needed before every import-like operation. | ||
| 278 | * This is needed for shared pages, which don't trigger a secure storage | ||
| 279 | * exception when accessed from a different guest. | ||
| 280 | * | ||
| 281 | * Although considered as one, the Unpin Page UVC is not an actual import, | ||
| 282 | * so it is not affected. | ||
| 283 | * | ||
| 284 | * No export is needed also when there is only one protected VM, because the | ||
| 285 | * page cannot belong to the wrong VM in that case (there is no "other VM" | ||
| 286 | * it can belong to). | ||
| 287 | * | ||
| 288 | * Return: true if an export is needed before every import, otherwise false. | ||
| 289 | */ | ||
| 290 | static bool should_export_before_import(struct uv_cb_header *uvcb, struct mm_struct *mm) | ||
| 291 | { | ||
| 292 | /* | ||
| 293 | * The misc feature indicates, among other things, that importing a | ||
| 294 | * shared page from a different protected VM will automatically also | ||
| 295 | * transfer its ownership. | ||
| 296 | */ | ||
| 297 | if (uv_has_feature(BIT_UV_FEAT_MISC)) | ||
| 298 | return false; | ||
| 299 | if (uvcb->cmd == UVC_CMD_UNPIN_PAGE_SHARED) | ||
| 300 | return false; | ||
| 301 | return atomic_read(&mm->context.protected_count) > 1; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 305 | * Drain LRU caches: the local one on first invocation and the ones of all | ||
| 306 | * CPUs on successive invocations. Returns "true" on the first invocation. | ||
| 307 | */ | ||
| 308 | static bool drain_lru(bool *drain_lru_called) | ||
| 309 | { | ||
| 310 | /* | ||
| 311 | * If we have tried a local drain and the folio refcount | ||
| 312 | * still does not match our expected safe value, try with a | ||
| 313 | * system wide drain. This is needed if the pagevecs holding | ||
| 314 | * the page are on a different CPU. | ||
| 315 | */ | ||
| 316 | if (*drain_lru_called) { | ||
| 317 | lru_add_drain_all(); | ||
| 318 | /* We give up here, don't retry immediately. */ | ||
| 319 | return false; | ||
| 320 | } | ||
| 321 | /* | ||
| 322 | * We are here if the folio refcount does not match the | ||
| 323 | * expected safe value. The main culprits are usually | ||
| 324 | * pagevecs. With lru_add_drain() we drain the pagevecs | ||
| 325 | * on the local CPU so that hopefully the refcount will | ||
| 326 | * reach the expected safe value. | ||
| 327 | */ | ||
| 328 | lru_add_drain(); | ||
| 329 | *drain_lru_called = true; | ||
| 330 | /* The caller should try again immediately */ | ||
| 331 | return true; | ||
| 332 | } | ||
| 333 | |||
| 334 | /* | ||
| 335 | * Requests the Ultravisor to make a page accessible to a guest. | ||
| 336 | * If it's brought in the first time, it will be cleared. If | ||
| 337 | * it has been exported before, it will be decrypted and integrity | ||
| 338 | * checked. | ||
| 339 | */ | ||
| 340 | int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb) | ||
| 341 | { | ||
| 342 | struct vm_area_struct *vma; | ||
| 343 | bool drain_lru_called = false; | ||
| 344 | spinlock_t *ptelock; | ||
| 345 | unsigned long uaddr; | ||
| 346 | struct folio *folio; | ||
| 347 | pte_t *ptep; | ||
| 348 | int rc; | ||
| 349 | |||
| 350 | again: | ||
| 351 | rc = -EFAULT; | ||
| 352 | mmap_read_lock(gmap->mm); | ||
| 353 | |||
| 354 | uaddr = __gmap_translate(gmap, gaddr); | ||
| 355 | if (IS_ERR_VALUE(uaddr)) | ||
| 356 | goto out; | ||
| 357 | vma = vma_lookup(gmap->mm, uaddr); | ||
| 358 | if (!vma) | ||
| 359 | goto out; | ||
| 360 | /* | ||
| 361 | * Secure pages cannot be huge and userspace should not combine both. | ||
| 362 | * In case userspace does it anyway this will result in an -EFAULT for | ||
| 363 | * the unpack. The guest is thus never reaching secure mode. If | ||
| 364 | * userspace is playing dirty tricky with mapping huge pages later | ||
| 365 | * on this will result in a segmentation fault. | ||
| 366 | */ | ||
| 367 | if (is_vm_hugetlb_page(vma)) | ||
| 368 | goto out; | ||
| 369 | |||
| 370 | rc = -ENXIO; | ||
| 371 | ptep = get_locked_pte(gmap->mm, uaddr, &ptelock); | ||
| 372 | if (!ptep) | ||
| 373 | goto out; | ||
| 374 | if (pte_present(*ptep) && !(pte_val(*ptep) & _PAGE_INVALID) && pte_write(*ptep)) { | ||
| 375 | folio = page_folio(pte_page(*ptep)); | ||
| 376 | rc = -EAGAIN; | ||
| 377 | if (folio_test_large(folio)) { | ||
| 378 | rc = -E2BIG; | ||
| 379 | } else if (folio_trylock(folio)) { | ||
| 380 | if (should_export_before_import(uvcb, gmap->mm)) | ||
| 381 | uv_convert_from_secure(PFN_PHYS(folio_pfn(folio))); | ||
| 382 | rc = make_folio_secure(folio, uvcb); | ||
| 383 | folio_unlock(folio); | ||
| 384 | } | ||
| 385 | |||
| 386 | /* | ||
| 387 | * Once we drop the PTL, the folio may get unmapped and | ||
| 388 | * freed immediately. We need a temporary reference. | ||
| 389 | */ | ||
| 390 | if (rc == -EAGAIN || rc == -E2BIG) | ||
| 391 | folio_get(folio); | ||
| 392 | } | ||
| 393 | pte_unmap_unlock(ptep, ptelock); | ||
| 394 | out: | ||
| 395 | mmap_read_unlock(gmap->mm); | ||
| 396 | |||
| 397 | switch (rc) { | ||
| 398 | case -E2BIG: | ||
| 399 | folio_lock(folio); | ||
| 400 | rc = split_folio(folio); | ||
| 401 | folio_unlock(folio); | ||
| 402 | folio_put(folio); | ||
| 403 | |||
| 404 | switch (rc) { | ||
| 405 | case 0: | ||
| 406 | /* Splitting succeeded, try again immediately. */ | ||
| 407 | goto again; | ||
| 408 | case -EAGAIN: | ||
| 409 | /* Additional folio references. */ | ||
| 410 | if (drain_lru(&drain_lru_called)) | ||
| 411 | goto again; | ||
| 412 | return -EAGAIN; | ||
| 413 | case -EBUSY: | ||
| 414 | /* Unexpected race. */ | ||
| 415 | return -EAGAIN; | ||
| 416 | } | ||
| 417 | WARN_ON_ONCE(1); | ||
| 418 | return -ENXIO; | ||
| 419 | case -EAGAIN: | ||
| 420 | /* | ||
| 421 | * If we are here because the UVC returned busy or partial | ||
| 422 | * completion, this is just a useless check, but it is safe. | ||
| 423 | */ | ||
| 424 | folio_wait_writeback(folio); | ||
| 425 | folio_put(folio); | ||
| 426 | return -EAGAIN; | ||
| 427 | case -EBUSY: | ||
| 428 | /* Additional folio references. */ | ||
| 429 | if (drain_lru(&drain_lru_called)) | ||
| 430 | goto again; | ||
| 431 | return -EAGAIN; | ||
| 432 | case -ENXIO: | ||
| 433 | if (gmap_fault(gmap, gaddr, FAULT_FLAG_WRITE)) | ||
| 434 | return -EFAULT; | ||
| 435 | return -EAGAIN; | ||
| 436 | } | ||
| 437 | return rc; | ||
| 438 | } | ||
| 439 | EXPORT_SYMBOL_GPL(gmap_make_secure); | ||
| 440 | |||
| 441 | int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr) | ||
| 442 | { | ||
| 443 | struct uv_cb_cts uvcb = { | ||
| 444 | .header.cmd = UVC_CMD_CONV_TO_SEC_STOR, | ||
| 445 | .header.len = sizeof(uvcb), | ||
| 446 | .guest_handle = gmap->guest_handle, | ||
| 447 | .gaddr = gaddr, | ||
| 448 | }; | ||
| 449 | |||
| 450 | return gmap_make_secure(gmap, gaddr, &uvcb); | ||
| 451 | } | ||
| 452 | EXPORT_SYMBOL_GPL(gmap_convert_to_secure); | ||
| 453 | |||
| 454 | /** | ||
| 455 | * gmap_destroy_page - Destroy a guest page. | ||
| 456 | * @gmap: the gmap of the guest | ||
| 457 | * @gaddr: the guest address to destroy | ||
| 458 | * | ||
| 459 | * An attempt will be made to destroy the given guest page. If the attempt | ||
| 460 | * fails, an attempt is made to export the page. If both attempts fail, an | ||
| 461 | * appropriate error is returned. | ||
| 462 | */ | ||
| 463 | int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr) | ||
| 464 | { | ||
| 465 | struct vm_area_struct *vma; | ||
| 466 | struct folio_walk fw; | ||
| 467 | unsigned long uaddr; | ||
| 468 | struct folio *folio; | ||
| 469 | int rc; | ||
| 470 | |||
| 471 | rc = -EFAULT; | ||
| 472 | mmap_read_lock(gmap->mm); | ||
| 473 | |||
| 474 | uaddr = __gmap_translate(gmap, gaddr); | ||
| 475 | if (IS_ERR_VALUE(uaddr)) | ||
| 476 | goto out; | ||
| 477 | vma = vma_lookup(gmap->mm, uaddr); | ||
| 478 | if (!vma) | ||
| 479 | goto out; | ||
| 480 | /* | ||
| 481 | * Huge pages should not be able to become secure | ||
| 482 | */ | ||
| 483 | if (is_vm_hugetlb_page(vma)) | ||
| 484 | goto out; | ||
| 485 | |||
| 486 | rc = 0; | ||
| 487 | folio = folio_walk_start(&fw, vma, uaddr, 0); | ||
| 488 | if (!folio) | ||
| 489 | goto out; | ||
| 490 | /* | ||
| 491 | * See gmap_make_secure(): large folios cannot be secure. Small | ||
| 492 | * folio implies FW_LEVEL_PTE. | ||
| 493 | */ | ||
| 494 | if (folio_test_large(folio) || !pte_write(fw.pte)) | ||
| 495 | goto out_walk_end; | ||
| 496 | rc = uv_destroy_folio(folio); | ||
| 497 | /* | ||
| 498 | * Fault handlers can race; it is possible that two CPUs will fault | ||
| 499 | * on the same secure page. One CPU can destroy the page, reboot, | ||
| 500 | * re-enter secure mode and import it, while the second CPU was | ||
| 501 | * stuck at the beginning of the handler. At some point the second | ||
| 502 | * CPU will be able to progress, and it will not be able to destroy | ||
| 503 | * the page. In that case we do not want to terminate the process, | ||
| 504 | * we instead try to export the page. | ||
| 505 | */ | ||
| 506 | if (rc) | ||
| 507 | rc = uv_convert_from_secure_folio(folio); | ||
| 508 | out_walk_end: | ||
| 509 | folio_walk_end(&fw, vma); | ||
| 510 | out: | ||
| 511 | mmap_read_unlock(gmap->mm); | ||
| 512 | return rc; | ||
| 513 | } | ||
| 514 | EXPORT_SYMBOL_GPL(gmap_destroy_page); | ||
| 515 | 281 | ||
| 516 | /* | 282 | /* |
| 517 | * To be called with the folio locked or with an extra reference! This will | 283 | * To be called with the folio locked or with an extra reference! This will |
| @@ -8,7 +8,7 @@ include $(srctree)/virt/kvm/Makefile.kvm · 7 unmodified lines | |||
| 8 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm | 8 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm |
| 9 | 9 | ||
| 10 | kvm-y += kvm-s390.o intercept.o interrupt.o priv.o sigp.o | 10 | kvm-y += kvm-s390.o intercept.o interrupt.o priv.o sigp.o |
| 11 | kvm-y += diag.o gaccess.o guestdbg.o vsie.o pv.o | 11 | kvm-y += diag.o gaccess.o guestdbg.o vsie.o pv.o gmap.o gmap-vsie.o |
| 12 | 12 | ||
| 13 | kvm-$(CONFIG_VFIO_PCI_ZDEV_KVM) += pci.o | 13 | kvm-$(CONFIG_VFIO_PCI_ZDEV_KVM) += pci.o |
| 14 | obj-$(CONFIG_KVM) += kvm.o | 14 | obj-$(CONFIG_KVM) += kvm.o |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include <asm/gmap.h> | 16 | #include <asm/gmap.h> |
| 17 | #include <asm/dat-bits.h> | 17 | #include <asm/dat-bits.h> |
| 18 | #include "kvm-s390.h" | 18 | #include "kvm-s390.h" |
| 19 | #include "gmap.h" | ||
| 19 | #include "gaccess.h" | 20 | #include "gaccess.h" |
| 20 | 21 | ||
| 21 | /* | 22 | /* |
| @@ -1392,6 +1393,44 @@ shadow_pgt: · 1370 unmodified lines | |||
| 1392 | return 0; | 1393 | return 0; |
| 1393 | } | 1394 | } |
| 1394 | 1395 | ||
| 1396 | /** | ||
| 1397 | * shadow_pgt_lookup() - find a shadow page table | ||
| 1398 | * @sg: pointer to the shadow guest address space structure | ||
| 1399 | * @saddr: the address in the shadow aguest address space | ||
| 1400 | * @pgt: parent gmap address of the page table to get shadowed | ||
| 1401 | * @dat_protection: if the pgtable is marked as protected by dat | ||
| 1402 | * @fake: pgt references contiguous guest memory block, not a pgtable | ||
| 1403 | * | ||
| 1404 | * Returns 0 if the shadow page table was found and -EAGAIN if the page | ||
| 1405 | * table was not found. | ||
| 1406 | * | ||
| 1407 | * Called with sg->mm->mmap_lock in read. | ||
| 1408 | */ | ||
| 1409 | static int shadow_pgt_lookup(struct gmap *sg, unsigned long saddr, unsigned long *pgt, | ||
| 1410 | int *dat_protection, int *fake) | ||
| 1411 | { | ||
| 1412 | unsigned long pt_index; | ||
| 1413 | unsigned long *table; | ||
| 1414 | struct page *page; | ||
| 1415 | int rc; | ||
| 1416 | |||
| 1417 | spin_lock(&sg->guest_table_lock); | ||
| 1418 | table = gmap_table_walk(sg, saddr, 1); /* get segment pointer */ | ||
| 1419 | if (table && !(*table & _SEGMENT_ENTRY_INVALID)) { | ||
| 1420 | /* Shadow page tables are full pages (pte+pgste) */ | ||
| 1421 | page = pfn_to_page(*table >> PAGE_SHIFT); | ||
| 1422 | pt_index = gmap_pgste_get_pgt_addr(page_to_virt(page)); | ||
| 1423 | *pgt = pt_index & ~GMAP_SHADOW_FAKE_TABLE; | ||
| 1424 | *dat_protection = !!(*table & _SEGMENT_ENTRY_PROTECT); | ||
| 1425 | *fake = !!(pt_index & GMAP_SHADOW_FAKE_TABLE); | ||
| 1426 | rc = 0; | ||
| 1427 | } else { | ||
| 1428 | rc = -EAGAIN; | ||
| 1429 | } | ||
| 1430 | spin_unlock(&sg->guest_table_lock); | ||
| 1431 | return rc; | ||
| 1432 | } | ||
| 1433 | |||
| 1395 | /** | 1434 | /** |
| 1396 | * kvm_s390_shadow_fault - handle fault on a shadow page table | 1435 | * kvm_s390_shadow_fault - handle fault on a shadow page table |
| 1397 | * @vcpu: virtual cpu | 1436 | * @vcpu: virtual cpu |
| @@ -1415,6 +1454,9 @@ int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, · 17 unmodified lines | |||
| 1415 | int dat_protection, fake; | 1454 | int dat_protection, fake; |
| 1416 | int rc; | 1455 | int rc; |
| 1417 | 1456 | ||
| 1457 | if (KVM_BUG_ON(!gmap_is_shadow(sg), vcpu->kvm)) | ||
| 1458 | return -EFAULT; | ||
| 1459 | |||
| 1418 | mmap_read_lock(sg->mm); | 1460 | mmap_read_lock(sg->mm); |
| 1419 | /* | 1461 | /* |
| 1420 | * We don't want any guest-2 tables to change - so the parent | 1462 | * We don't want any guest-2 tables to change - so the parent |
| @@ -1423,7 +1465,7 @@ int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, · 2 unmodified lines | |||
| 1423 | */ | 1465 | */ |
| 1424 | ipte_lock(vcpu->kvm); | 1466 | ipte_lock(vcpu->kvm); |
| 1425 | 1467 | ||
| 1426 | rc = gmap_shadow_pgt_lookup(sg, saddr, &pgt, &dat_protection, &fake); | 1468 | rc = shadow_pgt_lookup(sg, saddr, &pgt, &dat_protection, &fake); |
| 1427 | if (rc) | 1469 | if (rc) |
| 1428 | rc = kvm_s390_shadow_tables(sg, saddr, &pgt, &dat_protection, | 1470 | rc = kvm_s390_shadow_tables(sg, saddr, &pgt, &dat_protection, |
| 1429 | &fake); | 1471 | &fake); |
| @@ -0,0 +1,142 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Guest memory management for KVM/s390 nested VMs. | ||
| 4 | * | ||
| 5 | * Copyright IBM Corp. 2008, 2020, 2024 | ||
| 6 | * | ||
| 7 | * Author(s): Claudio Imbrenda <imbrenda@linux.ibm.com> | ||
| 8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 9 | * David Hildenbrand <david@redhat.com> | ||
| 10 | * Janosch Frank <frankja@linux.vnet.ibm.com> | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/compiler.h> | ||
| 14 | #include <linux/kvm.h> | ||
| 15 | #include <linux/kvm_host.h> | ||
| 16 | #include <linux/pgtable.h> | ||
| 17 | #include <linux/pagemap.h> | ||
| 18 | #include <linux/mman.h> | ||
| 19 | |||
| 20 | #include <asm/lowcore.h> | ||
| 21 | #include <asm/gmap.h> | ||
| 22 | #include <asm/uv.h> | ||
| 23 | |||
| 24 | #include "kvm-s390.h" | ||
| 25 | #include "gmap.h" | ||
| 26 | |||
| 27 | /** | ||
| 28 | * gmap_find_shadow - find a specific asce in the list of shadow tables | ||
| 29 | * @parent: pointer to the parent gmap | ||
| 30 | * @asce: ASCE for which the shadow table is created | ||
| 31 | * @edat_level: edat level to be used for the shadow translation | ||
| 32 | * | ||
| 33 | * Returns the pointer to a gmap if a shadow table with the given asce is | ||
| 34 | * already available, ERR_PTR(-EAGAIN) if another one is just being created, | ||
| 35 | * otherwise NULL | ||
| 36 | * | ||
| 37 | * Context: Called with parent->shadow_lock held | ||
| 38 | */ | ||
| 39 | static struct gmap *gmap_find_shadow(struct gmap *parent, unsigned long asce, int edat_level) | ||
| 40 | { | ||
| 41 | struct gmap *sg; | ||
| 42 | |||
| 43 | lockdep_assert_held(&parent->shadow_lock); | ||
| 44 | list_for_each_entry(sg, &parent->children, list) { | ||
| 45 | if (!gmap_shadow_valid(sg, asce, edat_level)) | ||
| 46 | continue; | ||
| 47 | if (!sg->initialized) | ||
| 48 | return ERR_PTR(-EAGAIN); | ||
| 49 | refcount_inc(&sg->ref_count); | ||
| 50 | return sg; | ||
| 51 | } | ||
| 52 | return NULL; | ||
| 53 | } | ||
| 54 | |||
| 55 | /** | ||
| 56 | * gmap_shadow - create/find a shadow guest address space | ||
| 57 | * @parent: pointer to the parent gmap | ||
| 58 | * @asce: ASCE for which the shadow table is created | ||
| 59 | * @edat_level: edat level to be used for the shadow translation | ||
| 60 | * | ||
| 61 | * The pages of the top level page table referred by the asce parameter | ||
| 62 | * will be set to read-only and marked in the PGSTEs of the kvm process. | ||
| 63 | * The shadow table will be removed automatically on any change to the | ||
| 64 | * PTE mapping for the source table. | ||
| 65 | * | ||
| 66 | * Returns a guest address space structure, ERR_PTR(-ENOMEM) if out of memory, | ||
| 67 | * ERR_PTR(-EAGAIN) if the caller has to retry and ERR_PTR(-EFAULT) if the | ||
| 68 | * parent gmap table could not be protected. | ||
| 69 | */ | ||
| 70 | struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce, int edat_level) | ||
| 71 | { | ||
| 72 | struct gmap *sg, *new; | ||
| 73 | unsigned long limit; | ||
| 74 | int rc; | ||
| 75 | |||
| 76 | if (KVM_BUG_ON(parent->mm->context.allow_gmap_hpage_1m, (struct kvm *)parent->private) || | ||
| 77 | KVM_BUG_ON(gmap_is_shadow(parent), (struct kvm *)parent->private)) | ||
| 78 | return ERR_PTR(-EFAULT); | ||
| 79 | spin_lock(&parent->shadow_lock); | ||
| 80 | sg = gmap_find_shadow(parent, asce, edat_level); | ||
| 81 | spin_unlock(&parent->shadow_lock); | ||
| 82 | if (sg) | ||
| 83 | return sg; | ||
| 84 | /* Create a new shadow gmap */ | ||
| 85 | limit = -1UL >> (33 - (((asce & _ASCE_TYPE_MASK) >> 2) * 11)); | ||
| 86 | if (asce & _ASCE_REAL_SPACE) | ||
| 87 | limit = -1UL; | ||
| 88 | new = gmap_alloc(limit); | ||
| 89 | if (!new) | ||
| 90 | return ERR_PTR(-ENOMEM); | ||
| 91 | new->mm = parent->mm; | ||
| 92 | new->parent = gmap_get(parent); | ||
| 93 | new->private = parent->private; | ||
| 94 | new->orig_asce = asce; | ||
| 95 | new->edat_level = edat_level; | ||
| 96 | new->initialized = false; | ||
| 97 | spin_lock(&parent->shadow_lock); | ||
| 98 | /* Recheck if another CPU created the same shadow */ | ||
| 99 | sg = gmap_find_shadow(parent, asce, edat_level); | ||
| 100 | if (sg) { | ||
| 101 | spin_unlock(&parent->shadow_lock); | ||
| 102 | gmap_free(new); | ||
| 103 | return sg; | ||
| 104 | } | ||
| 105 | if (asce & _ASCE_REAL_SPACE) { | ||
| 106 | /* only allow one real-space gmap shadow */ | ||
| 107 | list_for_each_entry(sg, &parent->children, list) { | ||
| 108 | if (sg->orig_asce & _ASCE_REAL_SPACE) { | ||
| 109 | spin_lock(&sg->guest_table_lock); | ||
| 110 | gmap_unshadow(sg); | ||
| 111 | spin_unlock(&sg->guest_table_lock); | ||
| 112 | list_del(&sg->list); | ||
| 113 | gmap_put(sg); | ||
| 114 | break; | ||
| 115 | } | ||
| 116 | } | ||
| 117 | } | ||
| 118 | refcount_set(&new->ref_count, 2); | ||
| 119 | list_add(&new->list, &parent->children); | ||
| 120 | if (asce & _ASCE_REAL_SPACE) { | ||
| 121 | /* nothing to protect, return right away */ | ||
| 122 | new->initialized = true; | ||
| 123 | spin_unlock(&parent->shadow_lock); | ||
| 124 | return new; | ||
| 125 | } | ||
| 126 | spin_unlock(&parent->shadow_lock); | ||
| 127 | /* protect after insertion, so it will get properly invalidated */ | ||
| 128 | mmap_read_lock(parent->mm); | ||
| 129 | rc = __kvm_s390_mprotect_many(parent, asce & _ASCE_ORIGIN, | ||
| 130 | ((asce & _ASCE_TABLE_LENGTH) + 1), | ||
| 131 | PROT_READ, GMAP_NOTIFY_SHADOW); | ||
| 132 | mmap_read_unlock(parent->mm); | ||
| 133 | spin_lock(&parent->shadow_lock); | ||
| 134 | new->initialized = true; | ||
| 135 | if (rc) { | ||
| 136 | list_del(&new->list); | ||
| 137 | gmap_free(new); | ||
| 138 | new = ERR_PTR(rc); | ||
| 139 | } | ||
| 140 | spin_unlock(&parent->shadow_lock); | ||
| 141 | return new; | ||
| 142 | } | ||
| @@ -0,0 +1,212 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Guest memory management for KVM/s390 | ||
| 4 | * | ||
| 5 | * Copyright IBM Corp. 2008, 2020, 2024 | ||
| 6 | * | ||
| 7 | * Author(s): Claudio Imbrenda <imbrenda@linux.ibm.com> | ||
| 8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 9 | * David Hildenbrand <david@redhat.com> | ||
| 10 | * Janosch Frank <frankja@linux.vnet.ibm.com> | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/compiler.h> | ||
| 14 | #include <linux/kvm.h> | ||
| 15 | #include <linux/kvm_host.h> | ||
| 16 | #include <linux/pgtable.h> | ||
| 17 | #include <linux/pagemap.h> | ||
| 18 | |||
| 19 | #include <asm/lowcore.h> | ||
| 20 | #include <asm/gmap.h> | ||
| 21 | #include <asm/uv.h> | ||
| 22 | |||
| 23 | #include "gmap.h" | ||
| 24 | |||
| 25 | /** | ||
| 26 | * should_export_before_import - Determine whether an export is needed | ||
| 27 | * before an import-like operation | ||
| 28 | * @uvcb: the Ultravisor control block of the UVC to be performed | ||
| 29 | * @mm: the mm of the process | ||
| 30 | * | ||
| 31 | * Returns whether an export is needed before every import-like operation. | ||
| 32 | * This is needed for shared pages, which don't trigger a secure storage | ||
| 33 | * exception when accessed from a different guest. | ||
| 34 | * | ||
| 35 | * Although considered as one, the Unpin Page UVC is not an actual import, | ||
| 36 | * so it is not affected. | ||
| 37 | * | ||
| 38 | * No export is needed also when there is only one protected VM, because the | ||
| 39 | * page cannot belong to the wrong VM in that case (there is no "other VM" | ||
| 40 | * it can belong to). | ||
| 41 | * | ||
| 42 | * Return: true if an export is needed before every import, otherwise false. | ||
| 43 | */ | ||
| 44 | static bool should_export_before_import(struct uv_cb_header *uvcb, struct mm_struct *mm) | ||
| 45 | { | ||
| 46 | /* | ||
| 47 | * The misc feature indicates, among other things, that importing a | ||
| 48 | * shared page from a different protected VM will automatically also | ||
| 49 | * transfer its ownership. | ||
| 50 | */ | ||
| 51 | if (uv_has_feature(BIT_UV_FEAT_MISC)) | ||
| 52 | return false; | ||
| 53 | if (uvcb->cmd == UVC_CMD_UNPIN_PAGE_SHARED) | ||
| 54 | return false; | ||
| 55 | return atomic_read(&mm->context.protected_count) > 1; | ||
| 56 | } | ||
| 57 | |||
| 58 | static int __gmap_make_secure(struct gmap *gmap, struct page *page, void *uvcb) | ||
| 59 | { | ||
| 60 | struct folio *folio = page_folio(page); | ||
| 61 | int rc; | ||
| 62 | |||
| 63 | /* | ||
| 64 | * Secure pages cannot be huge and userspace should not combine both. | ||
| 65 | * In case userspace does it anyway this will result in an -EFAULT for | ||
| 66 | * the unpack. The guest is thus never reaching secure mode. | ||
| 67 | * If userspace plays dirty tricks and decides to map huge pages at a | ||
| 68 | * later point in time, it will receive a segmentation fault or | ||
| 69 | * KVM_RUN will return -EFAULT. | ||
| 70 | */ | ||
| 71 | if (folio_test_hugetlb(folio)) | ||
| 72 | return -EFAULT; | ||
| 73 | if (folio_test_large(folio)) { | ||
| 74 | mmap_read_unlock(gmap->mm); | ||
| 75 | rc = kvm_s390_wiggle_split_folio(gmap->mm, folio, true); | ||
| 76 | mmap_read_lock(gmap->mm); | ||
| 77 | if (rc) | ||
| 78 | return rc; | ||
| 79 | folio = page_folio(page); | ||
| 80 | } | ||
| 81 | |||
| 82 | if (!folio_trylock(folio)) | ||
| 83 | return -EAGAIN; | ||
| 84 | if (should_export_before_import(uvcb, gmap->mm)) | ||
| 85 | uv_convert_from_secure(folio_to_phys(folio)); | ||
| 86 | rc = make_folio_secure(folio, uvcb); | ||
| 87 | folio_unlock(folio); | ||
| 88 | |||
| 89 | /* | ||
| 90 | * In theory a race is possible and the folio might have become | ||
| 91 | * large again before the folio_trylock() above. In that case, no | ||
| 92 | * action is performed and -EAGAIN is returned; the callers will | ||
| 93 | * have to try again later. | ||
| 94 | * In most cases this implies running the VM again, getting the same | ||
| 95 | * exception again, and make another attempt in this function. | ||
| 96 | * This is expected to happen extremely rarely. | ||
| 97 | */ | ||
| 98 | if (rc == -E2BIG) | ||
| 99 | return -EAGAIN; | ||
| 100 | /* The folio has too many references, try to shake some off */ | ||
| 101 | if (rc == -EBUSY) { | ||
| 102 | mmap_read_unlock(gmap->mm); | ||
| 103 | kvm_s390_wiggle_split_folio(gmap->mm, folio, false); | ||
| 104 | mmap_read_lock(gmap->mm); | ||
| 105 | return -EAGAIN; | ||
| 106 | } | ||
| 107 | |||
| 108 | return rc; | ||
| 109 | } | ||
| 110 | |||
| 111 | /** | ||
| 112 | * gmap_make_secure() - make one guest page secure | ||
| 113 | * @gmap: the guest gmap | ||
| 114 | * @gaddr: the guest address that needs to be made secure | ||
| 115 | * @uvcb: the UVCB specifying which operation needs to be performed | ||
| 116 | * | ||
| 117 | * Context: needs to be called with kvm->srcu held. | ||
| 118 | * Return: 0 on success, < 0 in case of error (see __gmap_make_secure()). | ||
| 119 | */ | ||
| 120 | int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb) | ||
| 121 | { | ||
| 122 | struct kvm *kvm = gmap->private; | ||
| 123 | struct page *page; | ||
| 124 | int rc = 0; | ||
| 125 | |||
| 126 | lockdep_assert_held(&kvm->srcu); | ||
| 127 | |||
| 128 | page = gfn_to_page(kvm, gpa_to_gfn(gaddr)); | ||
| 129 | mmap_read_lock(gmap->mm); | ||
| 130 | if (page) | ||
| 131 | rc = __gmap_make_secure(gmap, page, uvcb); | ||
| 132 | kvm_release_page_clean(page); | ||
| 133 | mmap_read_unlock(gmap->mm); | ||
| 134 | |||
| 135 | return rc; | ||
| 136 | } | ||
| 137 | |||
| 138 | int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr) | ||
| 139 | { | ||
| 140 | struct uv_cb_cts uvcb = { | ||
| 141 | .header.cmd = UVC_CMD_CONV_TO_SEC_STOR, | ||
| 142 | .header.len = sizeof(uvcb), | ||
| 143 | .guest_handle = gmap->guest_handle, | ||
| 144 | .gaddr = gaddr, | ||
| 145 | }; | ||
| 146 | |||
| 147 | return gmap_make_secure(gmap, gaddr, &uvcb); | ||
| 148 | } | ||
| 149 | |||
| 150 | /** | ||
| 151 | * __gmap_destroy_page() - Destroy a guest page. | ||
| 152 | * @gmap: the gmap of the guest | ||
| 153 | * @page: the page to destroy | ||
| 154 | * | ||
| 155 | * An attempt will be made to destroy the given guest page. If the attempt | ||
| 156 | * fails, an attempt is made to export the page. If both attempts fail, an | ||
| 157 | * appropriate error is returned. | ||
| 158 | * | ||
| 159 | * Context: must be called holding the mm lock for gmap->mm | ||
| 160 | */ | ||
| 161 | static int __gmap_destroy_page(struct gmap *gmap, struct page *page) | ||
| 162 | { | ||
| 163 | struct folio *folio = page_folio(page); | ||
| 164 | int rc; | ||
| 165 | |||
| 166 | /* | ||
| 167 | * See gmap_make_secure(): large folios cannot be secure. Small | ||
| 168 | * folio implies FW_LEVEL_PTE. | ||
| 169 | */ | ||
| 170 | if (folio_test_large(folio)) | ||
| 171 | return -EFAULT; | ||
| 172 | |||
| 173 | rc = uv_destroy_folio(folio); | ||
| 174 | /* | ||
| 175 | * Fault handlers can race; it is possible that two CPUs will fault | ||
| 176 | * on the same secure page. One CPU can destroy the page, reboot, | ||
| 177 | * re-enter secure mode and import it, while the second CPU was | ||
| 178 | * stuck at the beginning of the handler. At some point the second | ||
| 179 | * CPU will be able to progress, and it will not be able to destroy | ||
| 180 | * the page. In that case we do not want to terminate the process, | ||
| 181 | * we instead try to export the page. | ||
| 182 | */ | ||
| 183 | if (rc) | ||
| 184 | rc = uv_convert_from_secure_folio(folio); | ||
| 185 | |||
| 186 | return rc; | ||
| 187 | } | ||
| 188 | |||
| 189 | /** | ||
| 190 | * gmap_destroy_page() - Destroy a guest page. | ||
| 191 | * @gmap: the gmap of the guest | ||
| 192 | * @gaddr: the guest address to destroy | ||
| 193 | * | ||
| 194 | * An attempt will be made to destroy the given guest page. If the attempt | ||
| 195 | * fails, an attempt is made to export the page. If both attempts fail, an | ||
| 196 | * appropriate error is returned. | ||
| 197 | * | ||
| 198 | * Context: may sleep. | ||
| 199 | */ | ||
| 200 | int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr) | ||
| 201 | { | ||
| 202 | struct page *page; | ||
| 203 | int rc = 0; | ||
| 204 | |||
| 205 | mmap_read_lock(gmap->mm); | ||
| 206 | page = gfn_to_page(gmap->private, gpa_to_gfn(gaddr)); | ||
| 207 | if (page) | ||
| 208 | rc = __gmap_destroy_page(gmap, page); | ||
| 209 | kvm_release_page_clean(page); | ||
| 210 | mmap_read_unlock(gmap->mm); | ||
| 211 | return rc; | ||
| 212 | } | ||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * KVM guest address space mapping code | ||
| 4 | * | ||
| 5 | * Copyright IBM Corp. 2007, 2016, 2025 | ||
| 6 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 7 | * Claudio Imbrenda <imbrenda@linux.ibm.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef ARCH_KVM_S390_GMAP_H | ||
| 11 | #define ARCH_KVM_S390_GMAP_H | ||
| 12 | |||
| 13 | #define GMAP_SHADOW_FAKE_TABLE 1ULL | ||
| 14 | |||
| 15 | int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb); | ||
| 16 | int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr); | ||
| 17 | int gmap_destroy_page(struct gmap *gmap, unsigned long gaddr); | ||
| 18 | struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce, int edat_level); | ||
| 19 | |||
| 20 | /** | ||
| 21 | * gmap_shadow_valid - check if a shadow guest address space matches the | ||
| 22 | * given properties and is still valid | ||
| 23 | * @sg: pointer to the shadow guest address space structure | ||
| 24 | * @asce: ASCE for which the shadow table is requested | ||
| 25 | * @edat_level: edat level to be used for the shadow translation | ||
| 26 | * | ||
| 27 | * Returns 1 if the gmap shadow is still valid and matches the given | ||
| 28 | * properties, the caller can continue using it. Returns 0 otherwise, the | ||
| 29 | * caller has to request a new shadow gmap in this case. | ||
| 30 | * | ||
| 31 | */ | ||
| 32 | static inline int gmap_shadow_valid(struct gmap *sg, unsigned long asce, int edat_level) | ||
| 33 | { | ||
| 34 | if (sg->removed) | ||
| 35 | return 0; | ||
| 36 | return sg->orig_asce == asce && sg->edat_level == edat_level; | ||
| 37 | } | ||
| 38 | |||
| 39 | #endif | ||
| @@ -21,6 +21,7 @@ · 20 unmodified lines | |||
| 21 | #include "gaccess.h" | 21 | #include "gaccess.h" |
| 22 | #include "trace.h" | 22 | #include "trace.h" |
| 23 | #include "trace-s390.h" | 23 | #include "trace-s390.h" |
| 24 | #include "gmap.h" | ||
| 24 | 25 | ||
| 25 | u8 kvm_s390_get_ilen(struct kvm_vcpu *vcpu) | 26 | u8 kvm_s390_get_ilen(struct kvm_vcpu *vcpu) |
| 26 | { | 27 | { |
| @@ -367,7 +368,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu) · 340 unmodified lines | |||
| 367 | reg2, &srcaddr, GACC_FETCH, 0); | 368 | reg2, &srcaddr, GACC_FETCH, 0); |
| 368 | if (rc) | 369 | if (rc) |
| 369 | return kvm_s390_inject_prog_cond(vcpu, rc); | 370 | return kvm_s390_inject_prog_cond(vcpu, rc); |
| 370 | rc = gmap_fault(vcpu->arch.gmap, srcaddr, 0); | 371 | rc = kvm_s390_handle_dat_fault(vcpu, srcaddr, 0); |
| 371 | if (rc != 0) | 372 | if (rc != 0) |
| 372 | return rc; | 373 | return rc; |
| 373 | 374 | ||
| @@ -376,7 +377,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu) · 2 unmodified lines | |||
| 376 | reg1, &dstaddr, GACC_STORE, 0); | 377 | reg1, &dstaddr, GACC_STORE, 0); |
| 377 | if (rc) | 378 | if (rc) |
| 378 | return kvm_s390_inject_prog_cond(vcpu, rc); | 379 | return kvm_s390_inject_prog_cond(vcpu, rc); |
| 379 | rc = gmap_fault(vcpu->arch.gmap, dstaddr, FAULT_FLAG_WRITE); | 380 | rc = kvm_s390_handle_dat_fault(vcpu, dstaddr, FOLL_WRITE); |
| 380 | if (rc != 0) | 381 | if (rc != 0) |
| 381 | return rc; | 382 | return rc; |
| 382 | 383 | ||
| @@ -549,7 +550,7 @@ static int handle_pv_uvc(struct kvm_vcpu *vcpu) · 166 unmodified lines | |||
| 549 | * If the unpin did not succeed, the guest will exit again for the UVC | 550 | * If the unpin did not succeed, the guest will exit again for the UVC |
| 550 | * and we will retry the unpin. | 551 | * and we will retry the unpin. |
| 551 | */ | 552 | */ |
| 552 | if (rc == -EINVAL) | 553 | if (rc == -EINVAL || rc == -ENXIO) |
| 553 | return 0; | 554 | return 0; |
| 554 | /* | 555 | /* |
| 555 | * If we got -EAGAIN here, we simply return it. It will eventually | 556 | * If we got -EAGAIN here, we simply return it. It will eventually |
| @@ -2893,7 +2893,8 @@ int kvm_set_routing_entry(struct kvm *kvm, · 2892 unmodified lines | |||
| 2893 | struct kvm_kernel_irq_routing_entry *e, | 2893 | struct kvm_kernel_irq_routing_entry *e, |
| 2894 | const struct kvm_irq_routing_entry *ue) | 2894 | const struct kvm_irq_routing_entry *ue) |
| 2895 | { | 2895 | { |
| 2896 | u64 uaddr; | 2896 | u64 uaddr_s, uaddr_i; |
| 2897 | int idx; | ||
| 2897 | 2898 | ||
| 2898 | switch (ue->type) { | 2899 | switch (ue->type) { |
| 2899 | /* we store the userspace addresses instead of the guest addresses */ | 2900 | /* we store the userspace addresses instead of the guest addresses */ |
| @@ -2901,14 +2902,16 @@ int kvm_set_routing_entry(struct kvm *kvm, · 1 unmodified line | |||
| 2901 | if (kvm_is_ucontrol(kvm)) | 2902 | if (kvm_is_ucontrol(kvm)) |
| 2902 | return -EINVAL; | 2903 | return -EINVAL; |
| 2903 | e->set = set_adapter_int; | 2904 | e->set = set_adapter_int; |
| 2904 | uaddr = gmap_translate(kvm->arch.gmap, ue->u.adapter.summary_addr); | 2905 | |
| 2905 | if (uaddr == -EFAULT) | 2906 | idx = srcu_read_lock(&kvm->srcu); |
| 2906 | return -EFAULT; | 2907 | uaddr_s = gpa_to_hva(kvm, ue->u.adapter.summary_addr); |
| 2907 | e->adapter.summary_addr = uaddr; | 2908 | uaddr_i = gpa_to_hva(kvm, ue->u.adapter.ind_addr); |
| 2908 | uaddr = gmap_translate(kvm->arch.gmap, ue->u.adapter.ind_addr); | 2909 | srcu_read_unlock(&kvm->srcu, idx); |
| 2909 | if (uaddr == -EFAULT) | 2910 | |
| 2911 | if (kvm_is_error_hva(uaddr_s) || kvm_is_error_hva(uaddr_i)) | ||
| 2910 | return -EFAULT; | 2912 | return -EFAULT; |
| 2911 | e->adapter.ind_addr = uaddr; | 2913 | e->adapter.summary_addr = uaddr_s; |
| 2914 | e->adapter.ind_addr = uaddr_i; | ||
| 2912 | e->adapter.summary_offset = ue->u.adapter.summary_offset; | 2915 | e->adapter.summary_offset = ue->u.adapter.summary_offset; |
| 2913 | e->adapter.ind_offset = ue->u.adapter.ind_offset; | 2916 | e->adapter.ind_offset = ue->u.adapter.ind_offset; |
| 2914 | e->adapter.adapter_id = ue->u.adapter.adapter_id; | 2917 | e->adapter.adapter_id = ue->u.adapter.adapter_id; |
| @@ -50,6 +50,7 @@ · 49 unmodified lines | |||
| 50 | #include "kvm-s390.h" | 50 | #include "kvm-s390.h" |
| 51 | #include "gaccess.h" | 51 | #include "gaccess.h" |
| 52 | #include "pci.h" | 52 | #include "pci.h" |
| 53 | #include "gmap.h" | ||
| 53 | 54 | ||
| 54 | #define CREATE_TRACE_POINTS | 55 | #define CREATE_TRACE_POINTS |
| 55 | #include "trace.h" | 56 | #include "trace.h" |
| @@ -3428,8 +3429,20 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) · 3372 unmodified lines | |||
| 3428 | VM_EVENT(kvm, 3, "vm created with type %lu", type); | 3429 | VM_EVENT(kvm, 3, "vm created with type %lu", type); |
| 3429 | 3430 | ||
| 3430 | if (type & KVM_VM_S390_UCONTROL) { | 3431 | if (type & KVM_VM_S390_UCONTROL) { |
| 3432 | struct kvm_userspace_memory_region2 fake_memslot = { | ||
| 3433 | .slot = KVM_S390_UCONTROL_MEMSLOT, | ||
| 3434 | .guest_phys_addr = 0, | ||
| 3435 | .userspace_addr = 0, | ||
| 3436 | .memory_size = ALIGN_DOWN(TASK_SIZE, _SEGMENT_SIZE), | ||
| 3437 | .flags = 0, | ||
| 3438 | }; | ||
| 3439 | |||
| 3431 | kvm->arch.gmap = NULL; | 3440 | kvm->arch.gmap = NULL; |
| 3432 | kvm->arch.mem_limit = KVM_S390_NO_MEM_LIMIT; | 3441 | kvm->arch.mem_limit = KVM_S390_NO_MEM_LIMIT; |
| 3442 | /* one flat fake memslot covering the whole address-space */ | ||
| 3443 | mutex_lock(&kvm->slots_lock); | ||
| 3444 | KVM_BUG_ON(kvm_set_internal_memslot(kvm, &fake_memslot), kvm); | ||
| 3445 | mutex_unlock(&kvm->slots_lock); | ||
| 3433 | } else { | 3446 | } else { |
| 3434 | if (sclp.hamax == U64_MAX) | 3447 | if (sclp.hamax == U64_MAX) |
| 3435 | kvm->arch.mem_limit = TASK_SIZE_MAX; | 3448 | kvm->arch.mem_limit = TASK_SIZE_MAX; |
| @@ -4498,6 +4511,75 @@ static bool ibs_enabled(struct kvm_vcpu *vcpu) · 1062 unmodified lines | |||
| 4498 | return kvm_s390_test_cpuflags(vcpu, CPUSTAT_IBS); | 4511 | return kvm_s390_test_cpuflags(vcpu, CPUSTAT_IBS); |
| 4499 | } | 4512 | } |
| 4500 | 4513 | ||
| 4514 | static int __kvm_s390_fixup_fault_sync(struct gmap *gmap, gpa_t gaddr, unsigned int flags) | ||
| 4515 | { | ||
| 4516 | struct kvm *kvm = gmap->private; | ||
| 4517 | gfn_t gfn = gpa_to_gfn(gaddr); | ||
| 4518 | bool unlocked; | ||
| 4519 | hva_t vmaddr; | ||
| 4520 | gpa_t tmp; | ||
| 4521 | int rc; | ||
| 4522 | |||
| 4523 | if (kvm_is_ucontrol(kvm)) { | ||
| 4524 | tmp = __gmap_translate(gmap, gaddr); | ||
| 4525 | gfn = gpa_to_gfn(tmp); | ||
| 4526 | } | ||
| 4527 | |||
| 4528 | vmaddr = gfn_to_hva(kvm, gfn); | ||
| 4529 | rc = fixup_user_fault(gmap->mm, vmaddr, FAULT_FLAG_WRITE, &unlocked); | ||
| 4530 | if (!rc) | ||
| 4531 | rc = __gmap_link(gmap, gaddr, vmaddr); | ||
| 4532 | return rc; | ||
| 4533 | } | ||
| 4534 | |||
| 4535 | /** | ||
| 4536 | * __kvm_s390_mprotect_many() - Apply specified protection to guest pages | ||
| 4537 | * @gmap: the gmap of the guest | ||
| 4538 | * @gpa: the starting guest address | ||
| 4539 | * @npages: how many pages to protect | ||
| 4540 | * @prot: indicates access rights: PROT_NONE, PROT_READ or PROT_WRITE | ||
| 4541 | * @bits: pgste notification bits to set | ||
| 4542 | * | ||
| 4543 | * Returns: 0 in case of success, < 0 in case of error - see gmap_protect_one() | ||
| 4544 | * | ||
| 4545 | * Context: kvm->srcu and gmap->mm need to be held in read mode | ||
| 4546 | */ | ||
| 4547 | int __kvm_s390_mprotect_many(struct gmap *gmap, gpa_t gpa, u8 npages, unsigned int prot, | ||
| 4548 | unsigned long bits) | ||
| 4549 | { | ||
| 4550 | unsigned int fault_flag = (prot & PROT_WRITE) ? FAULT_FLAG_WRITE : 0; | ||
| 4551 | gpa_t end = gpa + npages * PAGE_SIZE; | ||
| 4552 | int rc; | ||
| 4553 | |||
| 4554 | for (; gpa < end; gpa = ALIGN(gpa + 1, rc)) { | ||
| 4555 | rc = gmap_protect_one(gmap, gpa, prot, bits); | ||
| 4556 | if (rc == -EAGAIN) { | ||
| 4557 | __kvm_s390_fixup_fault_sync(gmap, gpa, fault_flag); | ||
| 4558 | rc = gmap_protect_one(gmap, gpa, prot, bits); | ||
| 4559 | } | ||
| 4560 | if (rc < 0) | ||
| 4561 | return rc; | ||
| 4562 | } | ||
| 4563 | |||
| 4564 | return 0; | ||
| 4565 | } | ||
| 4566 | |||
| 4567 | static int kvm_s390_mprotect_notify_prefix(struct kvm_vcpu *vcpu) | ||
| 4568 | { | ||
| 4569 | gpa_t gaddr = kvm_s390_get_prefix(vcpu); | ||
| 4570 | int idx, rc; | ||
| 4571 | |||
| 4572 | idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
| 4573 | mmap_read_lock(vcpu->arch.gmap->mm); | ||
| 4574 | |||
| 4575 | rc = __kvm_s390_mprotect_many(vcpu->arch.gmap, gaddr, 2, PROT_WRITE, GMAP_NOTIFY_MPROT); | ||
| 4576 | |||
| 4577 | mmap_read_unlock(vcpu->arch.gmap->mm); | ||
| 4578 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
| 4579 | |||
| 4580 | return rc; | ||
| 4581 | } | ||
| 4582 | |||
| 4501 | static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu) | 4583 | static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu) |
| 4502 | { | 4584 | { |
| 4503 | retry: | 4585 | retry: |
| @@ -4513,9 +4595,8 @@ retry: · 9 unmodified lines | |||
| 4513 | */ | 4595 | */ |
| 4514 | if (kvm_check_request(KVM_REQ_REFRESH_GUEST_PREFIX, vcpu)) { | 4596 | if (kvm_check_request(KVM_REQ_REFRESH_GUEST_PREFIX, vcpu)) { |
| 4515 | int rc; | 4597 | int rc; |
| 4516 | rc = gmap_mprotect_notify(vcpu->arch.gmap, | 4598 | |
| 4517 | kvm_s390_get_prefix(vcpu), | 4599 | rc = kvm_s390_mprotect_notify_prefix(vcpu); |
| 4518 | PAGE_SIZE * 2, PROT_WRITE); | ||
| 4519 | if (rc) { | 4600 | if (rc) { |
| 4520 | kvm_make_request(KVM_REQ_REFRESH_GUEST_PREFIX, vcpu); | 4601 | kvm_make_request(KVM_REQ_REFRESH_GUEST_PREFIX, vcpu); |
| 4521 | return rc; | 4602 | return rc; |
| @@ -4766,11 +4847,111 @@ static int vcpu_post_run_addressing_exception(struct kvm_vcpu *vcpu) · 244 unmodified lines | |||
| 4766 | return kvm_s390_inject_prog_irq(vcpu, &pgm_info); | 4847 | return kvm_s390_inject_prog_irq(vcpu, &pgm_info); |
| 4767 | } | 4848 | } |
| 4768 | 4849 | ||
| 4850 | static void kvm_s390_assert_primary_as(struct kvm_vcpu *vcpu) | ||
| 4851 | { | ||
| 4852 | KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, | ||
| 4853 | "Unexpected program interrupt 0x%x, TEID 0x%016lx", | ||
| 4854 | current->thread.gmap_int_code, current->thread.gmap_teid.val); | ||
| 4855 | } | ||
| 4856 | |||
| 4857 | /* | ||
| 4858 | * __kvm_s390_handle_dat_fault() - handle a dat fault for the gmap of a vcpu | ||
| 4859 | * @vcpu: the vCPU whose gmap is to be fixed up | ||
| 4860 | * @gfn: the guest frame number used for memslots (including fake memslots) | ||
| 4861 | * @gaddr: the gmap address, does not have to match @gfn for ucontrol gmaps | ||
| 4862 | * @flags: FOLL_* flags | ||
| 4863 | * | ||
| 4864 | * Return: 0 on success, < 0 in case of error. | ||
| 4865 | * Context: The mm lock must not be held before calling. May sleep. | ||
| 4866 | */ | ||
| 4867 | int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, unsigned int flags) | ||
| 4868 | { | ||
| 4869 | struct kvm_memory_slot *slot; | ||
| 4870 | unsigned int fault_flags; | ||
| 4871 | bool writable, unlocked; | ||
| 4872 | unsigned long vmaddr; | ||
| 4873 | struct page *page; | ||
| 4874 | kvm_pfn_t pfn; | ||
| 4875 | int rc; | ||
| 4876 | |||
| 4877 | slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn); | ||
| 4878 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) | ||
| 4879 | return vcpu_post_run_addressing_exception(vcpu); | ||
| 4880 | |||
| 4881 | fault_flags = flags & FOLL_WRITE ? FAULT_FLAG_WRITE : 0; | ||
| 4882 | if (vcpu->arch.gmap->pfault_enabled) | ||
| 4883 | flags |= FOLL_NOWAIT; | ||
| 4884 | vmaddr = __gfn_to_hva_memslot(slot, gfn); | ||
| 4885 | |||
| 4886 | try_again: | ||
| 4887 | pfn = __kvm_faultin_pfn(slot, gfn, flags, &writable, &page); | ||
| 4888 | |||
| 4889 | /* Access outside memory, inject addressing exception */ | ||
| 4890 | if (is_noslot_pfn(pfn)) | ||
| 4891 | return vcpu_post_run_addressing_exception(vcpu); | ||
| 4892 | /* Signal pending: try again */ | ||
| 4893 | if (pfn == KVM_PFN_ERR_SIGPENDING) | ||
| 4894 | return -EAGAIN; | ||
| 4895 | |||
| 4896 | /* Needs I/O, try to setup async pfault (only possible with FOLL_NOWAIT) */ | ||
| 4897 | if (pfn == KVM_PFN_ERR_NEEDS_IO) { | ||
| 4898 | trace_kvm_s390_major_guest_pfault(vcpu); | ||
| 4899 | if (kvm_arch_setup_async_pf(vcpu)) | ||
| 4900 | return 0; | ||
| 4901 | vcpu->stat.pfault_sync++; | ||
| 4902 | /* Could not setup async pfault, try again synchronously */ | ||
| 4903 | flags &= ~FOLL_NOWAIT; | ||
| 4904 | goto try_again; | ||
| 4905 | } | ||
| 4906 | /* Any other error */ | ||
| 4907 | if (is_error_pfn(pfn)) | ||
| 4908 | return -EFAULT; | ||
| 4909 | |||
| 4910 | /* Success */ | ||
| 4911 | mmap_read_lock(vcpu->arch.gmap->mm); | ||
| 4912 | /* Mark the userspace PTEs as young and/or dirty, to avoid page fault loops */ | ||
| 4913 | rc = fixup_user_fault(vcpu->arch.gmap->mm, vmaddr, fault_flags, &unlocked); | ||
| 4914 | if (!rc) | ||
| 4915 | rc = __gmap_link(vcpu->arch.gmap, gaddr, vmaddr); | ||
| 4916 | scoped_guard(spinlock, &vcpu->kvm->mmu_lock) { | ||
| 4917 | kvm_release_faultin_page(vcpu->kvm, page, false, writable); | ||
| 4918 | } | ||
| 4919 | mmap_read_unlock(vcpu->arch.gmap->mm); | ||
| 4920 | return rc; | ||
| 4921 | } | ||
| 4922 | |||
| 4923 | static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, unsigned int flags) | ||
| 4924 | { | ||
| 4925 | unsigned long gaddr_tmp; | ||
| 4926 | gfn_t gfn; | ||
| 4927 | |||
| 4928 | gfn = gpa_to_gfn(gaddr); | ||
| 4929 | if (kvm_is_ucontrol(vcpu->kvm)) { | ||
| 4930 | /* | ||
| 4931 | * This translates the per-vCPU guest address into a | ||
| 4932 | * fake guest address, which can then be used with the | ||
| 4933 | * fake memslots that are identity mapping userspace. | ||
| 4934 | * This allows ucontrol VMs to use the normal fault | ||
| 4935 | * resolution path, like normal VMs. | ||
| 4936 | */ | ||
| 4937 | mmap_read_lock(vcpu->arch.gmap->mm); | ||
| 4938 | gaddr_tmp = __gmap_translate(vcpu->arch.gmap, gaddr); | ||
| 4939 | mmap_read_unlock(vcpu->arch.gmap->mm); | ||
| 4940 | if (gaddr_tmp == -EFAULT) { | ||
| 4941 | vcpu->run->exit_reason = KVM_EXIT_S390_UCONTROL; | ||
| 4942 | vcpu->run->s390_ucontrol.trans_exc_code = gaddr; | ||
| 4943 | vcpu->run->s390_ucontrol.pgm_code = PGM_SEGMENT_TRANSLATION; | ||
| 4944 | return -EREMOTE; | ||
| 4945 | } | ||
| 4946 | gfn = gpa_to_gfn(gaddr_tmp); | ||
| 4947 | } | ||
| 4948 | return __kvm_s390_handle_dat_fault(vcpu, gfn, gaddr, flags); | ||
| 4949 | } | ||
| 4950 | |||
| 4769 | static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) | 4951 | static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) |
| 4770 | { | 4952 | { |
| 4771 | unsigned int flags = 0; | 4953 | unsigned int flags = 0; |
| 4772 | unsigned long gaddr; | 4954 | unsigned long gaddr; |
| 4773 | int rc = 0; | ||
| 4774 | 4955 | ||
| 4775 | gaddr = current->thread.gmap_teid.addr * PAGE_SIZE; | 4956 | gaddr = current->thread.gmap_teid.addr * PAGE_SIZE; |
| 4776 | if (kvm_s390_cur_gmap_fault_is_write()) | 4957 | if (kvm_s390_cur_gmap_fault_is_write()) |
| @@ -4781,9 +4962,7 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) · 4 unmodified lines | |||
| 4781 | vcpu->stat.exit_null++; | 4962 | vcpu->stat.exit_null++; |
| 4782 | break; | 4963 | break; |
| 4783 | case PGM_NON_SECURE_STORAGE_ACCESS: | 4964 | case PGM_NON_SECURE_STORAGE_ACCESS: |
| 4784 | KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, | 4965 | kvm_s390_assert_primary_as(vcpu); |
| 4785 | "Unexpected program interrupt 0x%x, TEID 0x%016lx", | ||
| 4786 | current->thread.gmap_int_code, current->thread.gmap_teid.val); | ||
| 4787 | /* | 4966 | /* |
| 4788 | * This is normal operation; a page belonging to a protected | 4967 | * This is normal operation; a page belonging to a protected |
| 4789 | * guest has not been imported yet. Try to import the page into | 4968 | * guest has not been imported yet. Try to import the page into |
| @@ -4794,9 +4973,7 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) · 4 unmodified lines | |||
| 4794 | break; | 4973 | break; |
| 4795 | case PGM_SECURE_STORAGE_ACCESS: | 4974 | case PGM_SECURE_STORAGE_ACCESS: |
| 4796 | case PGM_SECURE_STORAGE_VIOLATION: | 4975 | case PGM_SECURE_STORAGE_VIOLATION: |
| 4797 | KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, | 4976 | kvm_s390_assert_primary_as(vcpu); |
| 4798 | "Unexpected program interrupt 0x%x, TEID 0x%016lx", | ||
| 4799 | current->thread.gmap_int_code, current->thread.gmap_teid.val); | ||
| 4800 | /* | 4977 | /* |
| 4801 | * This can happen after a reboot with asynchronous teardown; | 4978 | * This can happen after a reboot with asynchronous teardown; |
| 4802 | * the new guest (normal or protected) will run on top of the | 4979 | * the new guest (normal or protected) will run on top of the |
| @@ -4825,40 +5002,15 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) · 22 unmodified lines | |||
| 4825 | case PGM_REGION_FIRST_TRANS: | 5002 | case PGM_REGION_FIRST_TRANS: |
| 4826 | case PGM_REGION_SECOND_TRANS: | 5003 | case PGM_REGION_SECOND_TRANS: |
| 4827 | case PGM_REGION_THIRD_TRANS: | 5004 | case PGM_REGION_THIRD_TRANS: |
| 4828 | KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, | 5005 | kvm_s390_assert_primary_as(vcpu); |
| 4829 | "Unexpected program interrupt 0x%x, TEID 0x%016lx", | 5006 | return vcpu_dat_fault_handler(vcpu, gaddr, flags); |
| 4830 | current->thread.gmap_int_code, current->thread.gmap_teid.val); | ||
| 4831 | if (vcpu->arch.gmap->pfault_enabled) { | ||
| 4832 | rc = gmap_fault(vcpu->arch.gmap, gaddr, flags | FAULT_FLAG_RETRY_NOWAIT); | ||
| 4833 | if (rc == -EFAULT) | ||
| 4834 | return vcpu_post_run_addressing_exception(vcpu); | ||
| 4835 | if (rc == -EAGAIN) { | ||
| 4836 | trace_kvm_s390_major_guest_pfault(vcpu); | ||
| 4837 | if (kvm_arch_setup_async_pf(vcpu)) | ||
| 4838 | return 0; | ||
| 4839 | vcpu->stat.pfault_sync++; | ||
| 4840 | } else { | ||
| 4841 | return rc; | ||
| 4842 | } | ||
| 4843 | } | ||
| 4844 | rc = gmap_fault(vcpu->arch.gmap, gaddr, flags); | ||
| 4845 | if (rc == -EFAULT) { | ||
| 4846 | if (kvm_is_ucontrol(vcpu->kvm)) { | ||
| 4847 | vcpu->run->exit_reason = KVM_EXIT_S390_UCONTROL; | ||
| 4848 | vcpu->run->s390_ucontrol.trans_exc_code = gaddr; | ||
| 4849 | vcpu->run->s390_ucontrol.pgm_code = 0x10; | ||
| 4850 | return -EREMOTE; | ||
| 4851 | } | ||
| 4852 | return vcpu_post_run_addressing_exception(vcpu); | ||
| 4853 | } | ||
| 4854 | break; | ||
| 4855 | default: | 5007 | default: |
| 4856 | KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx", | 5008 | KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx", |
| 4857 | current->thread.gmap_int_code, current->thread.gmap_teid.val); | 5009 | current->thread.gmap_int_code, current->thread.gmap_teid.val); |
| 4858 | send_sig(SIGSEGV, current, 0); | 5010 | send_sig(SIGSEGV, current, 0); |
| 4859 | break; | 5011 | break; |
| 4860 | } | 5012 | } |
| 4861 | return rc; | 5013 | return 0; |
| 4862 | } | 5014 | } |
| 4863 | 5015 | ||
| 4864 | static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) | 5016 | static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) |
| @@ -5737,7 +5889,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 872 unmodified lines | |||
| 5737 | } | 5889 | } |
| 5738 | #endif | 5890 | #endif |
| 5739 | case KVM_S390_VCPU_FAULT: { | 5891 | case KVM_S390_VCPU_FAULT: { |
| 5740 | r = gmap_fault(vcpu->arch.gmap, arg, 0); | 5892 | idx = srcu_read_lock(&vcpu->kvm->srcu); |
| 5893 | r = vcpu_dat_fault_handler(vcpu, arg, 0); | ||
| 5894 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
| 5741 | break; | 5895 | break; |
| 5742 | } | 5896 | } |
| 5743 | case KVM_ENABLE_CAP: | 5897 | case KVM_ENABLE_CAP: |
| @@ -5853,7 +6007,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, · 109 unmodified lines | |||
| 5853 | { | 6007 | { |
| 5854 | gpa_t size; | 6008 | gpa_t size; |
| 5855 | 6009 | ||
| 5856 | if (kvm_is_ucontrol(kvm)) | 6010 | if (kvm_is_ucontrol(kvm) && new->id < KVM_USER_MEM_SLOTS) |
| 5857 | return -EINVAL; | 6011 | return -EINVAL; |
| 5858 | 6012 | ||
| 5859 | /* When we are protected, we should not change the memory slots */ | 6013 | /* When we are protected, we should not change the memory slots */ |
| @@ -5905,6 +6059,9 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, · 45 unmodified lines | |||
| 5905 | { | 6059 | { |
| 5906 | int rc = 0; | 6060 | int rc = 0; |
| 5907 | 6061 | ||
| 6062 | if (kvm_is_ucontrol(kvm)) | ||
| 6063 | return; | ||
| 6064 | |||
| 5908 | switch (change) { | 6065 | switch (change) { |
| 5909 | case KVM_MR_DELETE: | 6066 | case KVM_MR_DELETE: |
| 5910 | rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE, | 6067 | rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE, |
| @@ -20,6 +20,8 @@ · 19 unmodified lines | |||
| 20 | #include <asm/processor.h> | 20 | #include <asm/processor.h> |
| 21 | #include <asm/sclp.h> | 21 | #include <asm/sclp.h> |
| 22 | 22 | ||
| 23 | #define KVM_S390_UCONTROL_MEMSLOT (KVM_USER_MEM_SLOTS + 0) | ||
| 24 | |||
| 23 | static inline void kvm_s390_fpu_store(struct kvm_run *run) | 25 | static inline void kvm_s390_fpu_store(struct kvm_run *run) |
| 24 | { | 26 | { |
| 25 | fpu_stfpc(&run->s.regs.fpc); | 27 | fpu_stfpc(&run->s.regs.fpc); |
| @@ -279,6 +281,15 @@ static inline u32 kvm_s390_get_gisa_desc(struct kvm *kvm) · 253 unmodified lines | |||
| 279 | return gd; | 281 | return gd; |
| 280 | } | 282 | } |
| 281 | 283 | ||
| 284 | static inline hva_t gpa_to_hva(struct kvm *kvm, gpa_t gpa) | ||
| 285 | { | ||
| 286 | hva_t hva = gfn_to_hva(kvm, gpa_to_gfn(gpa)); | ||
| 287 | |||
| 288 | if (!kvm_is_error_hva(hva)) | ||
| 289 | hva |= offset_in_page(gpa); | ||
| 290 | return hva; | ||
| 291 | } | ||
| 292 | |||
| 282 | /* implemented in pv.c */ | 293 | /* implemented in pv.c */ |
| 283 | int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc); | 294 | int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc); |
| 284 | int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc); | 295 | int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc); |
| @@ -408,6 +419,14 @@ void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu); · 123 unmodified lines | |||
| 408 | void kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm); | 419 | void kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm); |
| 409 | __u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu); | 420 | __u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu); |
| 410 | int kvm_s390_cpus_from_pv(struct kvm *kvm, u16 *rc, u16 *rrc); | 421 | int kvm_s390_cpus_from_pv(struct kvm *kvm, u16 *rc, u16 *rrc); |
| 422 | int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, unsigned int flags); | ||
| 423 | int __kvm_s390_mprotect_many(struct gmap *gmap, gpa_t gpa, u8 npages, unsigned int prot, | ||
| 424 | unsigned long bits); | ||
| 425 | |||
| 426 | static inline int kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gpa_t gaddr, unsigned int flags) | ||
| 427 | { | ||
| 428 | return __kvm_s390_handle_dat_fault(vcpu, gpa_to_gfn(gaddr), gaddr, flags); | ||
| 429 | } | ||
| 411 | 430 | ||
| 412 | /* implemented in diag.c */ | 431 | /* implemented in diag.c */ |
| 413 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu); | 432 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu); |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | #include <linux/sched/mm.h> | 17 | #include <linux/sched/mm.h> |
| 18 | #include <linux/mmu_notifier.h> | 18 | #include <linux/mmu_notifier.h> |
| 19 | #include "kvm-s390.h" | 19 | #include "kvm-s390.h" |
| 20 | #include "gmap.h" | ||
| 20 | 21 | ||
| 21 | bool kvm_s390_pv_is_protected(struct kvm *kvm) | 22 | bool kvm_s390_pv_is_protected(struct kvm *kvm) |
| 22 | { | 23 | { |
| @@ -638,10 +639,28 @@ static int unpack_one(struct kvm *kvm, unsigned long addr, u64 tweak, · 615 unmodified lines | |||
| 638 | .tweak[1] = offset, | 639 | .tweak[1] = offset, |
| 639 | }; | 640 | }; |
| 640 | int ret = gmap_make_secure(kvm->arch.gmap, addr, &uvcb); | 641 | int ret = gmap_make_secure(kvm->arch.gmap, addr, &uvcb); |
| 642 | unsigned long vmaddr; | ||
| 643 | bool unlocked; | ||
| 641 | 644 | ||
| 642 | *rc = uvcb.header.rc; | 645 | *rc = uvcb.header.rc; |
| 643 | *rrc = uvcb.header.rrc; | 646 | *rrc = uvcb.header.rrc; |
| 644 | 647 | ||
| 648 | if (ret == -ENXIO) { | ||
| 649 | mmap_read_lock(kvm->mm); | ||
| 650 | vmaddr = gfn_to_hva(kvm, gpa_to_gfn(addr)); | ||
| 651 | if (kvm_is_error_hva(vmaddr)) { | ||
| 652 | ret = -EFAULT; | ||
| 653 | } else { | ||
| 654 | ret = fixup_user_fault(kvm->mm, vmaddr, FAULT_FLAG_WRITE, &unlocked); | ||
| 655 | if (!ret) | ||
| 656 | ret = __gmap_link(kvm->arch.gmap, addr, vmaddr); | ||
| 657 | } | ||
| 658 | mmap_read_unlock(kvm->mm); | ||
| 659 | if (!ret) | ||
| 660 | return -EAGAIN; | ||
| 661 | return ret; | ||
| 662 | } | ||
| 663 | |||
| 645 | if (ret && ret != -EAGAIN) | 664 | if (ret && ret != -EAGAIN) |
| 646 | KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x", | 665 | KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x", |
| 647 | uvcb.gaddr, *rc, *rrc); | 666 | uvcb.gaddr, *rc, *rrc); |
| @@ -660,6 +679,8 @@ int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size, · 12 unmodified lines | |||
| 660 | KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: start addr %lx size %lx", | 679 | KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: start addr %lx size %lx", |
| 661 | addr, size); | 680 | addr, size); |
| 662 | 681 | ||
| 682 | guard(srcu)(&kvm->srcu); | ||
| 683 | |||
| 663 | while (offset < size) { | 684 | while (offset < size) { |
| 664 | ret = unpack_one(kvm, addr, tweak, offset, rc, rrc); | 685 | ret = unpack_one(kvm, addr, tweak, offset, rc, rrc); |
| 665 | if (ret == -EAGAIN) { | 686 | if (ret == -EAGAIN) { |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/bitmap.h> | 13 | #include <linux/bitmap.h> |
| 14 | #include <linux/sched/signal.h> | 14 | #include <linux/sched/signal.h> |
| 15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| 16 | #include <linux/mman.h> | ||
| 16 | 17 | ||
| 17 | #include <asm/gmap.h> | 18 | #include <asm/gmap.h> |
| 18 | #include <asm/mmu_context.h> | 19 | #include <asm/mmu_context.h> |
| @@ -22,6 +23,11 @@ · 3 unmodified lines | |||
| 22 | #include <asm/facility.h> | 23 | #include <asm/facility.h> |
| 23 | #include "kvm-s390.h" | 24 | #include "kvm-s390.h" |
| 24 | #include "gaccess.h" | 25 | #include "gaccess.h" |
| 26 | #include "gmap.h" | ||
| 27 | |||
| 28 | enum vsie_page_flags { | ||
| 29 | VSIE_PAGE_IN_USE = 0, | ||
| 30 | }; | ||
| 25 | 31 | ||
| 26 | struct vsie_page { | 32 | struct vsie_page { |
| 27 | struct kvm_s390_sie_block scb_s; /* 0x0000 */ | 33 | struct kvm_s390_sie_block scb_s; /* 0x0000 */ |
| @@ -46,7 +52,18 @@ struct vsie_page { · 18 unmodified lines | |||
| 46 | gpa_t gvrd_gpa; /* 0x0240 */ | 52 | gpa_t gvrd_gpa; /* 0x0240 */ |
| 47 | gpa_t riccbd_gpa; /* 0x0248 */ | 53 | gpa_t riccbd_gpa; /* 0x0248 */ |
| 48 | gpa_t sdnx_gpa; /* 0x0250 */ | 54 | gpa_t sdnx_gpa; /* 0x0250 */ |
| 49 | __u8 reserved[0x0700 - 0x0258]; /* 0x0258 */ | 55 | /* |
| 56 | * guest address of the original SCB. Remains set for free vsie | ||
| 57 | * pages, so we can properly look them up in our addr_to_page | ||
| 58 | * radix tree. | ||
| 59 | */ | ||
| 60 | gpa_t scb_gpa; /* 0x0258 */ | ||
| 61 | /* | ||
| 62 | * Flags: must be set/cleared atomically after the vsie page can be | ||
| 63 | * looked up by other CPUs. | ||
| 64 | */ | ||
| 65 | unsigned long flags; /* 0x0260 */ | ||
| 66 | __u8 reserved[0x0700 - 0x0268]; /* 0x0268 */ | ||
| 50 | struct kvm_s390_crypto_cb crycb; /* 0x0700 */ | 67 | struct kvm_s390_crypto_cb crycb; /* 0x0700 */ |
| 51 | __u8 fac[S390_ARCH_FAC_LIST_SIZE_BYTE]; /* 0x0800 */ | 68 | __u8 fac[S390_ARCH_FAC_LIST_SIZE_BYTE]; /* 0x0800 */ |
| 52 | }; | 69 | }; |
| @@ -584,7 +601,6 @@ void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start, · 531 unmodified lines | |||
| 584 | struct kvm *kvm = gmap->private; | 601 | struct kvm *kvm = gmap->private; |
| 585 | struct vsie_page *cur; | 602 | struct vsie_page *cur; |
| 586 | unsigned long prefix; | 603 | unsigned long prefix; |
| 587 | struct page *page; | ||
| 588 | int i; | 604 | int i; |
| 589 | 605 | ||
| 590 | if (!gmap_is_shadow(gmap)) | 606 | if (!gmap_is_shadow(gmap)) |
| @@ -594,10 +610,9 @@ void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start, · 3 unmodified lines | |||
| 594 | * therefore we can safely reference them all the time. | 610 | * therefore we can safely reference them all the time. |
| 595 | */ | 611 | */ |
| 596 | for (i = 0; i < kvm->arch.vsie.page_count; i++) { | 612 | for (i = 0; i < kvm->arch.vsie.page_count; i++) { |
| 597 | page = READ_ONCE(kvm->arch.vsie.pages[i]); | 613 | cur = READ_ONCE(kvm->arch.vsie.pages[i]); |
| 598 | if (!page) | 614 | if (!cur) |
| 599 | continue; | 615 | continue; |
| 600 | cur = page_to_virt(page); | ||
| 601 | if (READ_ONCE(cur->gmap) != gmap) | 616 | if (READ_ONCE(cur->gmap) != gmap) |
| 602 | continue; | 617 | continue; |
| 603 | prefix = cur->scb_s.prefix << GUEST_PREFIX_SHIFT; | 618 | prefix = cur->scb_s.prefix << GUEST_PREFIX_SHIFT; |
| @@ -1345,6 +1360,20 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) · 741 unmodified lines | |||
| 1345 | return rc; | 1360 | return rc; |
| 1346 | } | 1361 | } |
| 1347 | 1362 | ||
| 1363 | /* Try getting a given vsie page, returning "true" on success. */ | ||
| 1364 | static inline bool try_get_vsie_page(struct vsie_page *vsie_page) | ||
| 1365 | { | ||
| 1366 | if (test_bit(VSIE_PAGE_IN_USE, &vsie_page->flags)) | ||
| 1367 | return false; | ||
| 1368 | return !test_and_set_bit(VSIE_PAGE_IN_USE, &vsie_page->flags); | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | /* Put a vsie page acquired through get_vsie_page / try_get_vsie_page. */ | ||
| 1372 | static void put_vsie_page(struct vsie_page *vsie_page) | ||
| 1373 | { | ||
| 1374 | clear_bit(VSIE_PAGE_IN_USE, &vsie_page->flags); | ||
| 1375 | } | ||
| 1376 | |||
| 1348 | /* | 1377 | /* |
| 1349 | * Get or create a vsie page for a scb address. | 1378 | * Get or create a vsie page for a scb address. |
| 1350 | * | 1379 | * |
| @@ -1355,16 +1384,21 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) · 4 unmodified lines | |||
| 1355 | static struct vsie_page *get_vsie_page(struct kvm *kvm, unsigned long addr) | 1384 | static struct vsie_page *get_vsie_page(struct kvm *kvm, unsigned long addr) |
| 1356 | { | 1385 | { |
| 1357 | struct vsie_page *vsie_page; | 1386 | struct vsie_page *vsie_page; |
| 1358 | struct page *page; | ||
| 1359 | int nr_vcpus; | 1387 | int nr_vcpus; |
| 1360 | 1388 | ||
| 1361 | rcu_read_lock(); | 1389 | rcu_read_lock(); |
| 1362 | page = radix_tree_lookup(&kvm->arch.vsie.addr_to_page, addr >> 9); | 1390 | vsie_page = radix_tree_lookup(&kvm->arch.vsie.addr_to_page, addr >> 9); |
| 1363 | rcu_read_unlock(); | 1391 | rcu_read_unlock(); |
| 1364 | if (page) { | 1392 | if (vsie_page) { |
| 1365 | if (page_ref_inc_return(page) == 2) | 1393 | if (try_get_vsie_page(vsie_page)) { |
| 1366 | return page_to_virt(page); | 1394 | if (vsie_page->scb_gpa == addr) |
| 1367 | page_ref_dec(page); | 1395 | return vsie_page; |
| 1396 | /* | ||
| 1397 | * We raced with someone reusing + putting this vsie | ||
| 1398 | * page before we grabbed it. | ||
| 1399 | */ | ||
| 1400 | put_vsie_page(vsie_page); | ||
| 1401 | } | ||
| 1368 | } | 1402 | } |
| 1369 | 1403 | ||
| 1370 | /* | 1404 | /* |
| @@ -1375,36 +1409,40 @@ static struct vsie_page *get_vsie_page(struct kvm *kvm, unsigned long addr) · 4 unmodified lines | |||
| 1375 | 1409 | ||
| 1376 | mutex_lock(&kvm->arch.vsie.mutex); | 1410 | mutex_lock(&kvm->arch.vsie.mutex); |
| 1377 | if (kvm->arch.vsie.page_count < nr_vcpus) { | 1411 | if (kvm->arch.vsie.page_count < nr_vcpus) { |
| 1378 | page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO | GFP_DMA); | 1412 | vsie_page = (void *)__get_free_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO | GFP_DMA); |
| 1379 | if (!page) { | 1413 | if (!vsie_page) { |
| 1380 | mutex_unlock(&kvm->arch.vsie.mutex); | 1414 | mutex_unlock(&kvm->arch.vsie.mutex); |
| 1381 | return ERR_PTR(-ENOMEM); | 1415 | return ERR_PTR(-ENOMEM); |
| 1382 | } | 1416 | } |
| 1383 | page_ref_inc(page); | 1417 | __set_bit(VSIE_PAGE_IN_USE, &vsie_page->flags); |
| 1384 | kvm->arch.vsie.pages[kvm->arch.vsie.page_count] = page; | 1418 | kvm->arch.vsie.pages[kvm->arch.vsie.page_count] = vsie_page; |
| 1385 | kvm->arch.vsie.page_count++; | 1419 | kvm->arch.vsie.page_count++; |
| 1386 | } else { | 1420 | } else { |
| 1387 | /* reuse an existing entry that belongs to nobody */ | 1421 | /* reuse an existing entry that belongs to nobody */ |
| 1388 | while (true) { | 1422 | while (true) { |
| 1389 | page = kvm->arch.vsie.pages[kvm->arch.vsie.next]; | 1423 | vsie_page = kvm->arch.vsie.pages[kvm->arch.vsie.next]; |
| 1390 | if (page_ref_inc_return(page) == 2) | 1424 | if (try_get_vsie_page(vsie_page)) |
| 1391 | break; | 1425 | break; |
| 1392 | page_ref_dec(page); | ||
| 1393 | kvm->arch.vsie.next++; | 1426 | kvm->arch.vsie.next++; |
| 1394 | kvm->arch.vsie.next %= nr_vcpus; | 1427 | kvm->arch.vsie.next %= nr_vcpus; |
| 1395 | } | 1428 | } |
| 1396 | radix_tree_delete(&kvm->arch.vsie.addr_to_page, page->index >> 9); | 1429 | if (vsie_page->scb_gpa != ULONG_MAX) |
| 1430 | radix_tree_delete(&kvm->arch.vsie.addr_to_page, | ||
| 1431 | vsie_page->scb_gpa >> 9); | ||
| 1397 | } | 1432 | } |
| 1398 | page->index = addr; | 1433 | /* Mark it as invalid until it resides in the tree. */ |
| 1399 | /* double use of the same address */ | 1434 | vsie_page->scb_gpa = ULONG_MAX; |
| 1400 | if (radix_tree_insert(&kvm->arch.vsie.addr_to_page, addr >> 9, page)) { | 1435 | |
| 1401 | page_ref_dec(page); | 1436 | /* Double use of the same address or allocation failure. */ |
| 1437 | if (radix_tree_insert(&kvm->arch.vsie.addr_to_page, addr >> 9, | ||
| 1438 | vsie_page)) { | ||
| 1439 | put_vsie_page(vsie_page); | ||
| 1402 | mutex_unlock(&kvm->arch.vsie.mutex); | 1440 | mutex_unlock(&kvm->arch.vsie.mutex); |
| 1403 | return NULL; | 1441 | return NULL; |
| 1404 | } | 1442 | } |
| 1443 | vsie_page->scb_gpa = addr; | ||
| 1405 | mutex_unlock(&kvm->arch.vsie.mutex); | 1444 | mutex_unlock(&kvm->arch.vsie.mutex); |
| 1406 | 1445 | ||
| 1407 | vsie_page = page_to_virt(page); | ||
| 1408 | memset(&vsie_page->scb_s, 0, sizeof(struct kvm_s390_sie_block)); | 1446 | memset(&vsie_page->scb_s, 0, sizeof(struct kvm_s390_sie_block)); |
| 1409 | release_gmap_shadow(vsie_page); | 1447 | release_gmap_shadow(vsie_page); |
| 1410 | vsie_page->fault_addr = 0; | 1448 | vsie_page->fault_addr = 0; |
| @@ -1412,14 +1450,6 @@ static struct vsie_page *get_vsie_page(struct kvm *kvm, unsigned long addr) · 1 unmodified line | |||
| 1412 | return vsie_page; | 1450 | return vsie_page; |
| 1413 | } | 1451 | } |
| 1414 | 1452 | ||
| 1415 | /* put a vsie page acquired via get_vsie_page */ | ||
| 1416 | static void put_vsie_page(struct kvm *kvm, struct vsie_page *vsie_page) | ||
| 1417 | { | ||
| 1418 | struct page *page = pfn_to_page(__pa(vsie_page) >> PAGE_SHIFT); | ||
| 1419 | |||
| 1420 | page_ref_dec(page); | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu) | 1453 | int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu) |
| 1424 | { | 1454 | { |
| 1425 | struct vsie_page *vsie_page; | 1455 | struct vsie_page *vsie_page; |
| @@ -1470,7 +1500,7 @@ out_unshadow: · 44 unmodified lines | |||
| 1470 | out_unpin_scb: | 1500 | out_unpin_scb: |
| 1471 | unpin_scb(vcpu, vsie_page, scb_addr); | 1501 | unpin_scb(vcpu, vsie_page, scb_addr); |
| 1472 | out_put: | 1502 | out_put: |
| 1473 | put_vsie_page(vcpu->kvm, vsie_page); | 1503 | put_vsie_page(vsie_page); |
| 1474 | 1504 | ||
| 1475 | return rc < 0 ? rc : 0; | 1505 | return rc < 0 ? rc : 0; |
| 1476 | } | 1506 | } |
| @@ -1486,18 +1516,18 @@ void kvm_s390_vsie_init(struct kvm *kvm) · 9 unmodified lines | |||
| 1486 | void kvm_s390_vsie_destroy(struct kvm *kvm) | 1516 | void kvm_s390_vsie_destroy(struct kvm *kvm) |
| 1487 | { | 1517 | { |
| 1488 | struct vsie_page *vsie_page; | 1518 | struct vsie_page *vsie_page; |
| 1489 | struct page *page; | ||
| 1490 | int i; | 1519 | int i; |
| 1491 | 1520 | ||
| 1492 | mutex_lock(&kvm->arch.vsie.mutex); | 1521 | mutex_lock(&kvm->arch.vsie.mutex); |
| 1493 | for (i = 0; i < kvm->arch.vsie.page_count; i++) { | 1522 | for (i = 0; i < kvm->arch.vsie.page_count; i++) { |
| 1494 | page = kvm->arch.vsie.pages[i]; | 1523 | vsie_page = kvm->arch.vsie.pages[i]; |
| 1495 | kvm->arch.vsie.pages[i] = NULL; | 1524 | kvm->arch.vsie.pages[i] = NULL; |
| 1496 | vsie_page = page_to_virt(page); | ||
| 1497 | release_gmap_shadow(vsie_page); | 1525 | release_gmap_shadow(vsie_page); |
| 1498 | /* free the radix tree entry */ | 1526 | /* free the radix tree entry */ |
| 1499 | radix_tree_delete(&kvm->arch.vsie.addr_to_page, page->index >> 9); | 1527 | if (vsie_page->scb_gpa != ULONG_MAX) |
| 1500 | __free_page(page); | 1528 | radix_tree_delete(&kvm->arch.vsie.addr_to_page, |
| 1529 | vsie_page->scb_gpa >> 9); | ||
| 1530 | free_page((unsigned long)vsie_page); | ||
| 1501 | } | 1531 | } |
| 1502 | kvm->arch.vsie.page_count = 0; | 1532 | kvm->arch.vsie.page_count = 0; |
| 1503 | mutex_unlock(&kvm->arch.vsie.mutex); | 1533 | mutex_unlock(&kvm->arch.vsie.mutex); |
| @@ -24,6 +24,16 @@ · 23 unmodified lines | |||
| 24 | #include <asm/page.h> | 24 | #include <asm/page.h> |
| 25 | #include <asm/tlb.h> | 25 | #include <asm/tlb.h> |
| 26 | 26 | ||
| 27 | /* | ||
| 28 | * The address is saved in a radix tree directly; NULL would be ambiguous, | ||
| 29 | * since 0 is a valid address, and NULL is returned when nothing was found. | ||
| 30 | * The lower bits are ignored by all users of the macro, so it can be used | ||
| 31 | * to distinguish a valid address 0 from a NULL. | ||
| 32 | */ | ||
| 33 | #define VALID_GADDR_FLAG 1 | ||
| 34 | #define IS_GADDR_VALID(gaddr) ((gaddr) & VALID_GADDR_FLAG) | ||
| 35 | #define MAKE_VALID_GADDR(gaddr) (((gaddr) & HPAGE_MASK) | VALID_GADDR_FLAG) | ||
| 36 | |||
| 27 | #define GMAP_SHADOW_FAKE_TABLE 1ULL | 37 | #define GMAP_SHADOW_FAKE_TABLE 1ULL |
| 28 | 38 | ||
| 29 | static struct page *gmap_alloc_crst(void) | 39 | static struct page *gmap_alloc_crst(void) |
| @@ -43,7 +53,7 @@ static struct page *gmap_alloc_crst(void) · 13 unmodified lines | |||
| 43 | * | 53 | * |
| 44 | * Returns a guest address space structure. | 54 | * Returns a guest address space structure. |
| 45 | */ | 55 | */ |
| 46 | static struct gmap *gmap_alloc(unsigned long limit) | 56 | struct gmap *gmap_alloc(unsigned long limit) |
| 47 | { | 57 | { |
| 48 | struct gmap *gmap; | 58 | struct gmap *gmap; |
| 49 | struct page *page; | 59 | struct page *page; |
| @@ -70,9 +80,7 @@ static struct gmap *gmap_alloc(unsigned long limit) · 20 unmodified lines | |||
| 70 | gmap = kzalloc(sizeof(struct gmap), GFP_KERNEL_ACCOUNT); | 80 | gmap = kzalloc(sizeof(struct gmap), GFP_KERNEL_ACCOUNT); |
| 71 | if (!gmap) | 81 | if (!gmap) |
| 72 | goto out; | 82 | goto out; |
| 73 | INIT_LIST_HEAD(&gmap->crst_list); | ||
| 74 | INIT_LIST_HEAD(&gmap->children); | 83 | INIT_LIST_HEAD(&gmap->children); |
| 75 | INIT_LIST_HEAD(&gmap->pt_list); | ||
| 76 | INIT_RADIX_TREE(&gmap->guest_to_host, GFP_KERNEL_ACCOUNT); | 84 | INIT_RADIX_TREE(&gmap->guest_to_host, GFP_KERNEL_ACCOUNT); |
| 77 | INIT_RADIX_TREE(&gmap->host_to_guest, GFP_ATOMIC | __GFP_ACCOUNT); | 85 | INIT_RADIX_TREE(&gmap->host_to_guest, GFP_ATOMIC | __GFP_ACCOUNT); |
| 78 | INIT_RADIX_TREE(&gmap->host_to_rmap, GFP_ATOMIC | __GFP_ACCOUNT); | 86 | INIT_RADIX_TREE(&gmap->host_to_rmap, GFP_ATOMIC | __GFP_ACCOUNT); |
| @@ -82,8 +90,6 @@ static struct gmap *gmap_alloc(unsigned long limit) · 3 unmodified lines | |||
| 82 | page = gmap_alloc_crst(); | 90 | page = gmap_alloc_crst(); |
| 83 | if (!page) | 91 | if (!page) |
| 84 | goto out_free; | 92 | goto out_free; |
| 85 | page->index = 0; | ||
| 86 | list_add(&page->lru, &gmap->crst_list); | ||
| 87 | table = page_to_virt(page); | 93 | table = page_to_virt(page); |
| 88 | crst_table_init(table, etype); | 94 | crst_table_init(table, etype); |
| 89 | gmap->table = table; | 95 | gmap->table = table; |
| @@ -97,6 +103,7 @@ out_free: · 7 unmodified lines | |||
| 97 | out: | 103 | out: |
| 98 | return NULL; | 104 | return NULL; |
| 99 | } | 105 | } |
| 106 | EXPORT_SYMBOL_GPL(gmap_alloc); | ||
| 100 | 107 | ||
| 101 | /** | 108 | /** |
| 102 | * gmap_create - create a guest address space | 109 | * gmap_create - create a guest address space |
| @@ -185,32 +192,46 @@ static void gmap_rmap_radix_tree_free(struct radix_tree_root *root) · 82 unmodified lines | |||
| 185 | } while (nr > 0); | 192 | } while (nr > 0); |
| 186 | } | 193 | } |
| 187 | 194 | ||
| 195 | static void gmap_free_crst(unsigned long *table, bool free_ptes) | ||
| 196 | { | ||
| 197 | bool is_segment = (table[0] & _SEGMENT_ENTRY_TYPE_MASK) == 0; | ||
| 198 | int i; | ||
| 199 | |||
| 200 | if (is_segment) { | ||
| 201 | if (!free_ptes) | ||
| 202 | goto out; | ||
| 203 | for (i = 0; i < _CRST_ENTRIES; i++) | ||
| 204 | if (!(table[i] & _SEGMENT_ENTRY_INVALID)) | ||
| 205 | page_table_free_pgste(page_ptdesc(phys_to_page(table[i]))); | ||
| 206 | } else { | ||
| 207 | for (i = 0; i < _CRST_ENTRIES; i++) | ||
| 208 | if (!(table[i] & _REGION_ENTRY_INVALID)) | ||
| 209 | gmap_free_crst(__va(table[i] & PAGE_MASK), free_ptes); | ||
| 210 | } | ||
| 211 | |||
| 212 | out: | ||
| 213 | free_pages((unsigned long)table, CRST_ALLOC_ORDER); | ||
| 214 | } | ||
| 215 | |||
| 188 | /** | 216 | /** |
| 189 | * gmap_free - free a guest address space | 217 | * gmap_free - free a guest address space |
| 190 | * @gmap: pointer to the guest address space structure | 218 | * @gmap: pointer to the guest address space structure |
| 191 | * | 219 | * |
| 192 | * No locks required. There are no references to this gmap anymore. | 220 | * No locks required. There are no references to this gmap anymore. |
| 193 | */ | 221 | */ |
| 194 | static void gmap_free(struct gmap *gmap) | 222 | void gmap_free(struct gmap *gmap) |
| 195 | { | 223 | { |
| 196 | struct page *page, *next; | ||
| 197 | |||
| 198 | /* Flush tlb of all gmaps (if not already done for shadows) */ | 224 | /* Flush tlb of all gmaps (if not already done for shadows) */ |
| 199 | if (!(gmap_is_shadow(gmap) && gmap->removed)) | 225 | if (!(gmap_is_shadow(gmap) && gmap->removed)) |
| 200 | gmap_flush_tlb(gmap); | 226 | gmap_flush_tlb(gmap); |
| 201 | /* Free all segment & region tables. */ | 227 | /* Free all segment & region tables. */ |
| 202 | list_for_each_entry_safe(page, next, &gmap->crst_list, lru) | 228 | gmap_free_crst(gmap->table, gmap_is_shadow(gmap)); |
| 203 | __free_pages(page, CRST_ALLOC_ORDER); | 229 | |
| 204 | gmap_radix_tree_free(&gmap->guest_to_host); | 230 | gmap_radix_tree_free(&gmap->guest_to_host); |
| 205 | gmap_radix_tree_free(&gmap->host_to_guest); | 231 | gmap_radix_tree_free(&gmap->host_to_guest); |
| 206 | 232 | ||
| 207 | /* Free additional data for a shadow gmap */ | 233 | /* Free additional data for a shadow gmap */ |
| 208 | if (gmap_is_shadow(gmap)) { | 234 | if (gmap_is_shadow(gmap)) { |
| 209 | struct ptdesc *ptdesc, *n; | ||
| 210 | |||
| 211 | /* Free all page tables. */ | ||
| 212 | list_for_each_entry_safe(ptdesc, n, &gmap->pt_list, pt_list) | ||
| 213 | page_table_free_pgste(ptdesc); | ||
| 214 | gmap_rmap_radix_tree_free(&gmap->host_to_rmap); | 235 | gmap_rmap_radix_tree_free(&gmap->host_to_rmap); |
| 215 | /* Release reference to the parent */ | 236 | /* Release reference to the parent */ |
| 216 | gmap_put(gmap->parent); | 237 | gmap_put(gmap->parent); |
| @@ -218,6 +239,7 @@ static void gmap_free(struct gmap *gmap) · 1 unmodified line | |||
| 218 | 239 | ||
| 219 | kfree(gmap); | 240 | kfree(gmap); |
| 220 | } | 241 | } |
| 242 | EXPORT_SYMBOL_GPL(gmap_free); | ||
| 221 | 243 | ||
| 222 | /** | 244 | /** |
| 223 | * gmap_get - increase reference counter for guest address space | 245 | * gmap_get - increase reference counter for guest address space |
| @@ -298,10 +320,8 @@ static int gmap_alloc_table(struct gmap *gmap, unsigned long *table, · 74 unmodified lines | |||
| 298 | crst_table_init(new, init); | 320 | crst_table_init(new, init); |
| 299 | spin_lock(&gmap->guest_table_lock); | 321 | spin_lock(&gmap->guest_table_lock); |
| 300 | if (*table & _REGION_ENTRY_INVALID) { | 322 | if (*table & _REGION_ENTRY_INVALID) { |
| 301 | list_add(&page->lru, &gmap->crst_list); | ||
| 302 | *table = __pa(new) | _REGION_ENTRY_LENGTH | | 323 | *table = __pa(new) | _REGION_ENTRY_LENGTH | |
| 303 | (*table & _REGION_ENTRY_TYPE_MASK); | 324 | (*table & _REGION_ENTRY_TYPE_MASK); |
| 304 | page->index = gaddr; | ||
| 305 | page = NULL; | 325 | page = NULL; |
| 306 | } | 326 | } |
| 307 | spin_unlock(&gmap->guest_table_lock); | 327 | spin_unlock(&gmap->guest_table_lock); |
| @@ -310,21 +330,23 @@ static int gmap_alloc_table(struct gmap *gmap, unsigned long *table, · 2 unmodified lines | |||
| 310 | return 0; | 330 | return 0; |
| 311 | } | 331 | } |
| 312 | 332 | ||
| 313 | /** | 333 | static unsigned long host_to_guest_lookup(struct gmap *gmap, unsigned long vmaddr) |
| 314 | * __gmap_segment_gaddr - find virtual address from segment pointer | ||
| 315 | * @entry: pointer to a segment table entry in the guest address space | ||
| 316 | * | ||
| 317 | * Returns the virtual address in the guest address space for the segment | ||
| 318 | */ | ||
| 319 | static unsigned long __gmap_segment_gaddr(unsigned long *entry) | ||
| 320 | { | 334 | { |
| 321 | struct page *page; | 335 | return (unsigned long)radix_tree_lookup(&gmap->host_to_guest, vmaddr >> PMD_SHIFT); |
| 322 | unsigned long offset; | 336 | } |
| 323 | 337 | ||
| 324 | offset = (unsigned long) entry / sizeof(unsigned long); | 338 | static unsigned long host_to_guest_delete(struct gmap *gmap, unsigned long vmaddr) |
| 325 | offset = (offset & (PTRS_PER_PMD - 1)) * PMD_SIZE; | 339 | { |
| 326 | page = pmd_pgtable_page((pmd_t *) entry); | 340 | return (unsigned long)radix_tree_delete(&gmap->host_to_guest, vmaddr >> PMD_SHIFT); |
| 327 | return page->index + offset; | 341 | } |
| 342 | |||
| 343 | static pmd_t *host_to_guest_pmd_delete(struct gmap *gmap, unsigned long vmaddr, | ||
| 344 | unsigned long *gaddr) | ||
| 345 | { | ||
| 346 | *gaddr = host_to_guest_delete(gmap, vmaddr); | ||
| 347 | if (IS_GADDR_VALID(*gaddr)) | ||
| 348 | return (pmd_t *)gmap_table_walk(gmap, *gaddr, 1); | ||
| 349 | return NULL; | ||
| 328 | } | 350 | } |
| 329 | 351 | ||
| 330 | /** | 352 | /** |
| @@ -336,16 +358,19 @@ static unsigned long __gmap_segment_gaddr(unsigned long *entry) · 5 unmodified lines | |||
| 336 | */ | 358 | */ |
| 337 | static int __gmap_unlink_by_vmaddr(struct gmap *gmap, unsigned long vmaddr) | 359 | static int __gmap_unlink_by_vmaddr(struct gmap *gmap, unsigned long vmaddr) |
| 338 | { | 360 | { |
| 339 | unsigned long *entry; | 361 | unsigned long gaddr; |
| 340 | int flush = 0; | 362 | int flush = 0; |
| 363 | pmd_t *pmdp; | ||
| 341 | 364 | ||
| 342 | BUG_ON(gmap_is_shadow(gmap)); | 365 | BUG_ON(gmap_is_shadow(gmap)); |
| 343 | spin_lock(&gmap->guest_table_lock); | 366 | spin_lock(&gmap->guest_table_lock); |
| 344 | entry = radix_tree_delete(&gmap->host_to_guest, vmaddr >> PMD_SHIFT); | 367 | |
| 345 | if (entry) { | 368 | pmdp = host_to_guest_pmd_delete(gmap, vmaddr, &gaddr); |
| 346 | flush = (*entry != _SEGMENT_ENTRY_EMPTY); | 369 | if (pmdp) { |
| 347 | *entry = _SEGMENT_ENTRY_EMPTY; | 370 | flush = (pmd_val(*pmdp) != _SEGMENT_ENTRY_EMPTY); |
| 371 | *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); | ||
| 348 | } | 372 | } |
| 373 | |||
| 349 | spin_unlock(&gmap->guest_table_lock); | 374 | spin_unlock(&gmap->guest_table_lock); |
| 350 | return flush; | 375 | return flush; |
| 351 | } | 376 | } |
| @@ -463,26 +488,6 @@ unsigned long __gmap_translate(struct gmap *gmap, unsigned long gaddr) · 111 unmodified lines | |||
| 463 | } | 488 | } |
| 464 | EXPORT_SYMBOL_GPL(__gmap_translate); | 489 | EXPORT_SYMBOL_GPL(__gmap_translate); |
| 465 | 490 | ||
| 466 | /** | ||
| 467 | * gmap_translate - translate a guest address to a user space address | ||
| 468 | * @gmap: pointer to guest mapping meta data structure | ||
| 469 | * @gaddr: guest address | ||
| 470 | * | ||
| 471 | * Returns user space address which corresponds to the guest address or | ||
| 472 | * -EFAULT if no such mapping exists. | ||
| 473 | * This function does not establish potentially missing page table entries. | ||
| 474 | */ | ||
| 475 | unsigned long gmap_translate(struct gmap *gmap, unsigned long gaddr) | ||
| 476 | { | ||
| 477 | unsigned long rc; | ||
| 478 | |||
| 479 | mmap_read_lock(gmap->mm); | ||
| 480 | rc = __gmap_translate(gmap, gaddr); | ||
| 481 | mmap_read_unlock(gmap->mm); | ||
| 482 | return rc; | ||
| 483 | } | ||
| 484 | EXPORT_SYMBOL_GPL(gmap_translate); | ||
| 485 | |||
| 486 | /** | 491 | /** |
| 487 | * gmap_unlink - disconnect a page table from the gmap shadow tables | 492 | * gmap_unlink - disconnect a page table from the gmap shadow tables |
| 488 | * @mm: pointer to the parent mm_struct | 493 | * @mm: pointer to the parent mm_struct |
| @@ -582,7 +587,8 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr) · 93 unmodified lines | |||
| 582 | spin_lock(&gmap->guest_table_lock); | 587 | spin_lock(&gmap->guest_table_lock); |
| 583 | if (*table == _SEGMENT_ENTRY_EMPTY) { | 588 | if (*table == _SEGMENT_ENTRY_EMPTY) { |
| 584 | rc = radix_tree_insert(&gmap->host_to_guest, | 589 | rc = radix_tree_insert(&gmap->host_to_guest, |
| 585 | vmaddr >> PMD_SHIFT, table); | 590 | vmaddr >> PMD_SHIFT, |
| 591 | (void *)MAKE_VALID_GADDR(gaddr)); | ||
| 586 | if (!rc) { | 592 | if (!rc) { |
| 587 | if (pmd_leaf(*pmd)) { | 593 | if (pmd_leaf(*pmd)) { |
| 588 | *table = (pmd_val(*pmd) & | 594 | *table = (pmd_val(*pmd) & |
| @@ -605,130 +611,7 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr) · 16 unmodified lines | |||
| 605 | radix_tree_preload_end(); | 611 | radix_tree_preload_end(); |
| 606 | return rc; | 612 | return rc; |
| 607 | } | 613 | } |
| 608 | 614 | EXPORT_SYMBOL(__gmap_link); | |
| 609 | /** | ||
| 610 | * fixup_user_fault_nowait - manually resolve a user page fault without waiting | ||
| 611 | * @mm: mm_struct of target mm | ||
| 612 | * @address: user address | ||
| 613 | * @fault_flags:flags to pass down to handle_mm_fault() | ||
| 614 | * @unlocked: did we unlock the mmap_lock while retrying | ||
| 615 | * | ||
| 616 | * This function behaves similarly to fixup_user_fault(), but it guarantees | ||
| 617 | * that the fault will be resolved without waiting. The function might drop | ||
| 618 | * and re-acquire the mm lock, in which case @unlocked will be set to true. | ||
| 619 | * | ||
| 620 | * The guarantee is that the fault is handled without waiting, but the | ||
| 621 | * function itself might sleep, due to the lock. | ||
| 622 | * | ||
| 623 | * Context: Needs to be called with mm->mmap_lock held in read mode, and will | ||
| 624 | * return with the lock held in read mode; @unlocked will indicate whether | ||
| 625 | * the lock has been dropped and re-acquired. This is the same behaviour as | ||
| 626 | * fixup_user_fault(). | ||
| 627 | * | ||
| 628 | * Return: 0 on success, -EAGAIN if the fault cannot be resolved without | ||
| 629 | * waiting, -EFAULT if the fault cannot be resolved, -ENOMEM if out of | ||
| 630 | * memory. | ||
| 631 | */ | ||
| 632 | static int fixup_user_fault_nowait(struct mm_struct *mm, unsigned long address, | ||
| 633 | unsigned int fault_flags, bool *unlocked) | ||
| 634 | { | ||
| 635 | struct vm_area_struct *vma; | ||
| 636 | unsigned int test_flags; | ||
| 637 | vm_fault_t fault; | ||
| 638 | int rc; | ||
| 639 | |||
| 640 | fault_flags |= FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT; | ||
| 641 | test_flags = fault_flags & FAULT_FLAG_WRITE ? VM_WRITE : VM_READ; | ||
| 642 | |||
| 643 | vma = find_vma(mm, address); | ||
| 644 | if (unlikely(!vma || address < vma->vm_start)) | ||
| 645 | return -EFAULT; | ||
| 646 | if (unlikely(!(vma->vm_flags & test_flags))) | ||
| 647 | return -EFAULT; | ||
| 648 | |||
| 649 | fault = handle_mm_fault(vma, address, fault_flags, NULL); | ||
| 650 | /* the mm lock has been dropped, take it again */ | ||
| 651 | if (fault & VM_FAULT_COMPLETED) { | ||
| 652 | *unlocked = true; | ||
| 653 | mmap_read_lock(mm); | ||
| 654 | return 0; | ||
| 655 | } | ||
| 656 | /* the mm lock has not been dropped */ | ||
| 657 | if (fault & VM_FAULT_ERROR) { | ||
| 658 | rc = vm_fault_to_errno(fault, 0); | ||
| 659 | BUG_ON(!rc); | ||
| 660 | return rc; | ||
| 661 | } | ||
| 662 | /* the mm lock has not been dropped because of FAULT_FLAG_RETRY_NOWAIT */ | ||
| 663 | if (fault & VM_FAULT_RETRY) | ||
| 664 | return -EAGAIN; | ||
| 665 | /* nothing needed to be done and the mm lock has not been dropped */ | ||
| 666 | return 0; | ||
| 667 | } | ||
| 668 | |||
| 669 | /** | ||
| 670 | * __gmap_fault - resolve a fault on a guest address | ||
| 671 | * @gmap: pointer to guest mapping meta data structure | ||
| 672 | * @gaddr: guest address | ||
| 673 | * @fault_flags: flags to pass down to handle_mm_fault() | ||
| 674 | * | ||
| 675 | * Context: Needs to be called with mm->mmap_lock held in read mode. Might | ||
| 676 | * drop and re-acquire the lock. Will always return with the lock held. | ||
| 677 | */ | ||
| 678 | static int __gmap_fault(struct gmap *gmap, unsigned long gaddr, unsigned int fault_flags) | ||
| 679 | { | ||
| 680 | unsigned long vmaddr; | ||
| 681 | bool unlocked; | ||
| 682 | int rc = 0; | ||
| 683 | |||
| 684 | retry: | ||
| 685 | unlocked = false; | ||
| 686 | |||
| 687 | vmaddr = __gmap_translate(gmap, gaddr); | ||
| 688 | if (IS_ERR_VALUE(vmaddr)) | ||
| 689 | return vmaddr; | ||
| 690 | |||
| 691 | if (fault_flags & FAULT_FLAG_RETRY_NOWAIT) | ||
| 692 | rc = fixup_user_fault_nowait(gmap->mm, vmaddr, fault_flags, &unlocked); | ||
| 693 | else | ||
| 694 | rc = fixup_user_fault(gmap->mm, vmaddr, fault_flags, &unlocked); | ||
| 695 | if (rc) | ||
| 696 | return rc; | ||
| 697 | /* | ||
| 698 | * In the case that fixup_user_fault unlocked the mmap_lock during | ||
| 699 | * fault-in, redo __gmap_translate() to avoid racing with a | ||
| 700 | * map/unmap_segment. | ||
| 701 | * In particular, __gmap_translate(), fixup_user_fault{,_nowait}(), | ||
| 702 | * and __gmap_link() must all be called atomically in one go; if the | ||
| 703 | * lock had been dropped in between, a retry is needed. | ||
| 704 | */ | ||
| 705 | if (unlocked) | ||
| 706 | goto retry; | ||
| 707 | |||
| 708 | return __gmap_link(gmap, gaddr, vmaddr); | ||
| 709 | } | ||
| 710 | |||
| 711 | /** | ||
| 712 | * gmap_fault - resolve a fault on a guest address | ||
| 713 | * @gmap: pointer to guest mapping meta data structure | ||
| 714 | * @gaddr: guest address | ||
| 715 | * @fault_flags: flags to pass down to handle_mm_fault() | ||
| 716 | * | ||
| 717 | * Returns 0 on success, -ENOMEM for out of memory conditions, -EFAULT if the | ||
| 718 | * vm address is already mapped to a different guest segment, and -EAGAIN if | ||
| 719 | * FAULT_FLAG_RETRY_NOWAIT was specified and the fault could not be processed | ||
| 720 | * immediately. | ||
| 721 | */ | ||
| 722 | int gmap_fault(struct gmap *gmap, unsigned long gaddr, unsigned int fault_flags) | ||
| 723 | { | ||
| 724 | int rc; | ||
| 725 | |||
| 726 | mmap_read_lock(gmap->mm); | ||
| 727 | rc = __gmap_fault(gmap, gaddr, fault_flags); | ||
| 728 | mmap_read_unlock(gmap->mm); | ||
| 729 | return rc; | ||
| 730 | } | ||
| 731 | EXPORT_SYMBOL_GPL(gmap_fault); | ||
| 732 | 615 | ||
| 733 | /* | 616 | /* |
| 734 | * this function is assumed to be called with mmap_lock held | 617 | * this function is assumed to be called with mmap_lock held |
| @@ -853,8 +736,7 @@ static void gmap_call_notifier(struct gmap *gmap, unsigned long start, · 118 unmodified lines | |||
| 853 | * | 736 | * |
| 854 | * Note: Can also be called for shadow gmaps. | 737 | * Note: Can also be called for shadow gmaps. |
| 855 | */ | 738 | */ |
| 856 | static inline unsigned long *gmap_table_walk(struct gmap *gmap, | 739 | unsigned long *gmap_table_walk(struct gmap *gmap, unsigned long gaddr, int level) |
| 857 | unsigned long gaddr, int level) | ||
| 858 | { | 740 | { |
| 859 | const int asce_type = gmap->asce & _ASCE_TYPE_MASK; | 741 | const int asce_type = gmap->asce & _ASCE_TYPE_MASK; |
| 860 | unsigned long *table = gmap->table; | 742 | unsigned long *table = gmap->table; |
| @@ -905,6 +787,7 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap, · 44 unmodified lines | |||
| 905 | } | 787 | } |
| 906 | return table; | 788 | return table; |
| 907 | } | 789 | } |
| 790 | EXPORT_SYMBOL(gmap_table_walk); | ||
| 908 | 791 | ||
| 909 | /** | 792 | /** |
| 910 | * gmap_pte_op_walk - walk the gmap page table, get the page table lock | 793 | * gmap_pte_op_walk - walk the gmap page table, get the page table lock |
| @@ -1101,86 +984,40 @@ static int gmap_protect_pte(struct gmap *gmap, unsigned long gaddr, · 190 unmodified lines | |||
| 1101 | * @prot: indicates access rights: PROT_NONE, PROT_READ or PROT_WRITE | 984 | * @prot: indicates access rights: PROT_NONE, PROT_READ or PROT_WRITE |
| 1102 | * @bits: pgste notification bits to set | 985 | * @bits: pgste notification bits to set |
| 1103 | * | 986 | * |
| 1104 | * Returns 0 if successfully protected, -ENOMEM if out of memory and | 987 | * Returns: |
| 1105 | * -EFAULT if gaddr is invalid (or mapping for shadows is missing). | 988 | * PAGE_SIZE if a small page was successfully protected; |
| 989 | * HPAGE_SIZE if a large page was successfully protected; | ||
| 990 | * -ENOMEM if out of memory; | ||
| 991 | * -EFAULT if gaddr is invalid (or mapping for shadows is missing); | ||
| 992 | * -EAGAIN if the guest mapping is missing and should be fixed by the caller. | ||
| 1106 | * | 993 | * |
| 1107 | * Called with sg->mm->mmap_lock in read. | 994 | * Context: Called with sg->mm->mmap_lock in read. |
| 1108 | */ | 995 | */ |
| 1109 | static int gmap_protect_range(struct gmap *gmap, unsigned long gaddr, | 996 | int gmap_protect_one(struct gmap *gmap, unsigned long gaddr, int prot, unsigned long bits) |
| 1110 | unsigned long len, int prot, unsigned long bits) | ||
| 1111 | { | 997 | { |
| 1112 | unsigned long vmaddr, dist; | ||
| 1113 | pmd_t *pmdp; | 998 | pmd_t *pmdp; |
| 1114 | int rc; | 999 | int rc = 0; |
| 1115 | 1000 | ||
| 1116 | BUG_ON(gmap_is_shadow(gmap)); | 1001 | BUG_ON(gmap_is_shadow(gmap)); |
| 1117 | while (len) { | ||
| 1118 | rc = -EAGAIN; | ||
| 1119 | pmdp = gmap_pmd_op_walk(gmap, gaddr); | ||
| 1120 | if (pmdp) { | ||
| 1121 | if (!pmd_leaf(*pmdp)) { | ||
| 1122 | rc = gmap_protect_pte(gmap, gaddr, pmdp, prot, | ||
| 1123 | bits); | ||
| 1124 | if (!rc) { | ||
| 1125 | len -= PAGE_SIZE; | ||
| 1126 | gaddr += PAGE_SIZE; | ||
| 1127 | } | ||
| 1128 | } else { | ||
| 1129 | rc = gmap_protect_pmd(gmap, gaddr, pmdp, prot, | ||
| 1130 | bits); | ||
| 1131 | if (!rc) { | ||
| 1132 | dist = HPAGE_SIZE - (gaddr & ~HPAGE_MASK); | ||
| 1133 | len = len < dist ? 0 : len - dist; | ||
| 1134 | gaddr = (gaddr & HPAGE_MASK) + HPAGE_SIZE; | ||
| 1135 | } | ||
| 1136 | } | ||
| 1137 | gmap_pmd_op_end(gmap, pmdp); | ||
| 1138 | } | ||
| 1139 | if (rc) { | ||
| 1140 | if (rc == -EINVAL) | ||
| 1141 | return rc; | ||
| 1142 | 1002 | ||
| 1143 | /* -EAGAIN, fixup of userspace mm and gmap */ | 1003 | pmdp = gmap_pmd_op_walk(gmap, gaddr); |
| 1144 | vmaddr = __gmap_translate(gmap, gaddr); | 1004 | if (!pmdp) |
| 1145 | if (IS_ERR_VALUE(vmaddr)) | 1005 | return -EAGAIN; |
| 1146 | return vmaddr; | ||
| 1147 | rc = gmap_pte_op_fixup(gmap, gaddr, vmaddr, prot); | ||
| 1148 | if (rc) | ||
| 1149 | return rc; | ||
| 1150 | } | ||
| 1151 | } | ||
| 1152 | return 0; | ||
| 1153 | } | ||
| 1154 | 1006 | ||
| 1155 | /** | 1007 | if (!pmd_leaf(*pmdp)) { |
| 1156 | * gmap_mprotect_notify - change access rights for a range of ptes and | 1008 | rc = gmap_protect_pte(gmap, gaddr, pmdp, prot, bits); |
| 1157 | * call the notifier if any pte changes again | 1009 | if (!rc) |
| 1158 | * @gmap: pointer to guest mapping meta data structure | 1010 | rc = PAGE_SIZE; |
| 1159 | * @gaddr: virtual address in the guest address space | 1011 | } else { |
| 1160 | * @len: size of area | 1012 | rc = gmap_protect_pmd(gmap, gaddr, pmdp, prot, bits); |
| 1161 | * @prot: indicates access rights: PROT_NONE, PROT_READ or PROT_WRITE | 1013 | if (!rc) |
| 1162 | * | 1014 | rc = HPAGE_SIZE; |
| 1163 | * Returns 0 if for each page in the given range a gmap mapping exists, | 1015 | } |
| 1164 | * the new access rights could be set and the notifier could be armed. | 1016 | gmap_pmd_op_end(gmap, pmdp); |
| 1165 | * If the gmap mapping is missing for one or more pages -EFAULT is | ||
| 1166 | * returned. If no memory could be allocated -ENOMEM is returned. | ||
| 1167 | * This function establishes missing page table entries. | ||
| 1168 | */ | ||
| 1169 | int gmap_mprotect_notify(struct gmap *gmap, unsigned long gaddr, | ||
| 1170 | unsigned long len, int prot) | ||
| 1171 | { | ||
| 1172 | int rc; | ||
| 1173 | 1017 | ||
| 1174 | if ((gaddr & ~PAGE_MASK) || (len & ~PAGE_MASK) || gmap_is_shadow(gmap)) | ||
| 1175 | return -EINVAL; | ||
| 1176 | if (!MACHINE_HAS_ESOP && prot == PROT_READ) | ||
| 1177 | return -EINVAL; | ||
| 1178 | mmap_read_lock(gmap->mm); | ||
| 1179 | rc = gmap_protect_range(gmap, gaddr, len, prot, GMAP_NOTIFY_MPROT); | ||
| 1180 | mmap_read_unlock(gmap->mm); | ||
| 1181 | return rc; | 1018 | return rc; |
| 1182 | } | 1019 | } |
| 1183 | EXPORT_SYMBOL_GPL(gmap_mprotect_notify); | 1020 | EXPORT_SYMBOL_GPL(gmap_protect_one); |
| 1184 | 1021 | ||
| 1185 | /** | 1022 | /** |
| 1186 | * gmap_read_table - get an unsigned long value from a guest page table using | 1023 | * gmap_read_table - get an unsigned long value from a guest page table using |
| @@ -1414,7 +1251,6 @@ static void gmap_unshadow_pgt(struct gmap *sg, unsigned long raddr) · 227 unmodified lines | |||
| 1414 | __gmap_unshadow_pgt(sg, raddr, __va(pgt)); | 1251 | __gmap_unshadow_pgt(sg, raddr, __va(pgt)); |
| 1415 | /* Free page table */ | 1252 | /* Free page table */ |
| 1416 | ptdesc = page_ptdesc(phys_to_page(pgt)); | 1253 | ptdesc = page_ptdesc(phys_to_page(pgt)); |
| 1417 | list_del(&ptdesc->pt_list); | ||
| 1418 | page_table_free_pgste(ptdesc); | 1254 | page_table_free_pgste(ptdesc); |
| 1419 | } | 1255 | } |
| 1420 | 1256 | ||
| @@ -1442,7 +1278,6 @@ static void __gmap_unshadow_sgt(struct gmap *sg, unsigned long raddr, · 21 unmodified lines | |||
| 1442 | __gmap_unshadow_pgt(sg, raddr, __va(pgt)); | 1278 | __gmap_unshadow_pgt(sg, raddr, __va(pgt)); |
| 1443 | /* Free page table */ | 1279 | /* Free page table */ |
| 1444 | ptdesc = page_ptdesc(phys_to_page(pgt)); | 1280 | ptdesc = page_ptdesc(phys_to_page(pgt)); |
| 1445 | list_del(&ptdesc->pt_list); | ||
| 1446 | page_table_free_pgste(ptdesc); | 1281 | page_table_free_pgste(ptdesc); |
| 1447 | } | 1282 | } |
| 1448 | } | 1283 | } |
| @@ -1472,7 +1307,6 @@ static void gmap_unshadow_sgt(struct gmap *sg, unsigned long raddr) · 23 unmodified lines | |||
| 1472 | __gmap_unshadow_sgt(sg, raddr, __va(sgt)); | 1307 | __gmap_unshadow_sgt(sg, raddr, __va(sgt)); |
| 1473 | /* Free segment table */ | 1308 | /* Free segment table */ |
| 1474 | page = phys_to_page(sgt); | 1309 | page = phys_to_page(sgt); |
| 1475 | list_del(&page->lru); | ||
| 1476 | __free_pages(page, CRST_ALLOC_ORDER); | 1310 | __free_pages(page, CRST_ALLOC_ORDER); |
| 1477 | } | 1311 | } |
| 1478 | 1312 | ||
| @@ -1500,7 +1334,6 @@ static void __gmap_unshadow_r3t(struct gmap *sg, unsigned long raddr, · 21 unmodified lines | |||
| 1500 | __gmap_unshadow_sgt(sg, raddr, __va(sgt)); | 1334 | __gmap_unshadow_sgt(sg, raddr, __va(sgt)); |
| 1501 | /* Free segment table */ | 1335 | /* Free segment table */ |
| 1502 | page = phys_to_page(sgt); | 1336 | page = phys_to_page(sgt); |
| 1503 | list_del(&page->lru); | ||
| 1504 | __free_pages(page, CRST_ALLOC_ORDER); | 1337 | __free_pages(page, CRST_ALLOC_ORDER); |
| 1505 | } | 1338 | } |
| 1506 | } | 1339 | } |
| @@ -1530,7 +1363,6 @@ static void gmap_unshadow_r3t(struct gmap *sg, unsigned long raddr) · 23 unmodified lines | |||
| 1530 | __gmap_unshadow_r3t(sg, raddr, __va(r3t)); | 1363 | __gmap_unshadow_r3t(sg, raddr, __va(r3t)); |
| 1531 | /* Free region 3 table */ | 1364 | /* Free region 3 table */ |
| 1532 | page = phys_to_page(r3t); | 1365 | page = phys_to_page(r3t); |
| 1533 | list_del(&page->lru); | ||
| 1534 | __free_pages(page, CRST_ALLOC_ORDER); | 1366 | __free_pages(page, CRST_ALLOC_ORDER); |
| 1535 | } | 1367 | } |
| 1536 | 1368 | ||
| @@ -1558,7 +1390,6 @@ static void __gmap_unshadow_r2t(struct gmap *sg, unsigned long raddr, · 21 unmodified lines | |||
| 1558 | __gmap_unshadow_r3t(sg, raddr, __va(r3t)); | 1390 | __gmap_unshadow_r3t(sg, raddr, __va(r3t)); |
| 1559 | /* Free region 3 table */ | 1391 | /* Free region 3 table */ |
| 1560 | page = phys_to_page(r3t); | 1392 | page = phys_to_page(r3t); |
| 1561 | list_del(&page->lru); | ||
| 1562 | __free_pages(page, CRST_ALLOC_ORDER); | 1393 | __free_pages(page, CRST_ALLOC_ORDER); |
| 1563 | } | 1394 | } |
| 1564 | } | 1395 | } |
| @@ -1588,7 +1419,6 @@ static void gmap_unshadow_r2t(struct gmap *sg, unsigned long raddr) · 23 unmodified lines | |||
| 1588 | __gmap_unshadow_r2t(sg, raddr, __va(r2t)); | 1419 | __gmap_unshadow_r2t(sg, raddr, __va(r2t)); |
| 1589 | /* Free region 2 table */ | 1420 | /* Free region 2 table */ |
| 1590 | page = phys_to_page(r2t); | 1421 | page = phys_to_page(r2t); |
| 1591 | list_del(&page->lru); | ||
| 1592 | __free_pages(page, CRST_ALLOC_ORDER); | 1422 | __free_pages(page, CRST_ALLOC_ORDER); |
| 1593 | } | 1423 | } |
| 1594 | 1424 | ||
| @@ -1620,7 +1450,6 @@ static void __gmap_unshadow_r1t(struct gmap *sg, unsigned long raddr, · 25 unmodified lines | |||
| 1620 | r1t[i] = _REGION1_ENTRY_EMPTY; | 1450 | r1t[i] = _REGION1_ENTRY_EMPTY; |
| 1621 | /* Free region 2 table */ | 1451 | /* Free region 2 table */ |
| 1622 | page = phys_to_page(r2t); | 1452 | page = phys_to_page(r2t); |
| 1623 | list_del(&page->lru); | ||
| 1624 | __free_pages(page, CRST_ALLOC_ORDER); | 1453 | __free_pages(page, CRST_ALLOC_ORDER); |
| 1625 | } | 1454 | } |
| 1626 | } | 1455 | } |
| @@ -1631,7 +1460,7 @@ static void __gmap_unshadow_r1t(struct gmap *sg, unsigned long raddr, · 4 unmodified lines | |||
| 1631 | * | 1460 | * |
| 1632 | * Called with sg->guest_table_lock | 1461 | * Called with sg->guest_table_lock |
| 1633 | */ | 1462 | */ |
| 1634 | static void gmap_unshadow(struct gmap *sg) | 1463 | void gmap_unshadow(struct gmap *sg) |
| 1635 | { | 1464 | { |
| 1636 | unsigned long *table; | 1465 | unsigned long *table; |
| 1637 | 1466 | ||
| @@ -1657,143 +1486,7 @@ static void gmap_unshadow(struct gmap *sg) · 19 unmodified lines | |||
| 1657 | break; | 1486 | break; |
| 1658 | } | 1487 | } |
| 1659 | } | 1488 | } |
| 1660 | 1489 | EXPORT_SYMBOL(gmap_unshadow); | |
| 1661 | /** | ||
| 1662 | * gmap_find_shadow - find a specific asce in the list of shadow tables | ||
| 1663 | * @parent: pointer to the parent gmap | ||
| 1664 | * @asce: ASCE for which the shadow table is created | ||
| 1665 | * @edat_level: edat level to be used for the shadow translation | ||
| 1666 | * | ||
| 1667 | * Returns the pointer to a gmap if a shadow table with the given asce is | ||
| 1668 | * already available, ERR_PTR(-EAGAIN) if another one is just being created, | ||
| 1669 | * otherwise NULL | ||
| 1670 | */ | ||
| 1671 | static struct gmap *gmap_find_shadow(struct gmap *parent, unsigned long asce, | ||
| 1672 | int edat_level) | ||
| 1673 | { | ||
| 1674 | struct gmap *sg; | ||
| 1675 | |||
| 1676 | list_for_each_entry(sg, &parent->children, list) { | ||
| 1677 | if (sg->orig_asce != asce || sg->edat_level != edat_level || | ||
| 1678 | sg->removed) | ||
| 1679 | continue; | ||
| 1680 | if (!sg->initialized) | ||
| 1681 | return ERR_PTR(-EAGAIN); | ||
| 1682 | refcount_inc(&sg->ref_count); | ||
| 1683 | return sg; | ||
| 1684 | } | ||
| 1685 | return NULL; | ||
| 1686 | } | ||
| 1687 | |||
| 1688 | /** | ||
| 1689 | * gmap_shadow_valid - check if a shadow guest address space matches the | ||
| 1690 | * given properties and is still valid | ||
| 1691 | * @sg: pointer to the shadow guest address space structure | ||
| 1692 | * @asce: ASCE for which the shadow table is requested | ||
| 1693 | * @edat_level: edat level to be used for the shadow translation | ||
| 1694 | * | ||
| 1695 | * Returns 1 if the gmap shadow is still valid and matches the given | ||
| 1696 | * properties, the caller can continue using it. Returns 0 otherwise, the | ||
| 1697 | * caller has to request a new shadow gmap in this case. | ||
| 1698 | * | ||
| 1699 | */ | ||
| 1700 | int gmap_shadow_valid(struct gmap *sg, unsigned long asce, int edat_level) | ||
| 1701 | { | ||
| 1702 | if (sg->removed) | ||
| 1703 | return 0; | ||
| 1704 | return sg->orig_asce == asce && sg->edat_level == edat_level; | ||
| 1705 | } | ||
| 1706 | EXPORT_SYMBOL_GPL(gmap_shadow_valid); | ||
| 1707 | |||
| 1708 | /** | ||
| 1709 | * gmap_shadow - create/find a shadow guest address space | ||
| 1710 | * @parent: pointer to the parent gmap | ||
| 1711 | * @asce: ASCE for which the shadow table is created | ||
| 1712 | * @edat_level: edat level to be used for the shadow translation | ||
| 1713 | * | ||
| 1714 | * The pages of the top level page table referred by the asce parameter | ||
| 1715 | * will be set to read-only and marked in the PGSTEs of the kvm process. | ||
| 1716 | * The shadow table will be removed automatically on any change to the | ||
| 1717 | * PTE mapping for the source table. | ||
| 1718 | * | ||
| 1719 | * Returns a guest address space structure, ERR_PTR(-ENOMEM) if out of memory, | ||
| 1720 | * ERR_PTR(-EAGAIN) if the caller has to retry and ERR_PTR(-EFAULT) if the | ||
| 1721 | * parent gmap table could not be protected. | ||
| 1722 | */ | ||
| 1723 | struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce, | ||
| 1724 | int edat_level) | ||
| 1725 | { | ||
| 1726 | struct gmap *sg, *new; | ||
| 1727 | unsigned long limit; | ||
| 1728 | int rc; | ||
| 1729 | |||
| 1730 | BUG_ON(parent->mm->context.allow_gmap_hpage_1m); | ||
| 1731 | BUG_ON(gmap_is_shadow(parent)); | ||
| 1732 | spin_lock(&parent->shadow_lock); | ||
| 1733 | sg = gmap_find_shadow(parent, asce, edat_level); | ||
| 1734 | spin_unlock(&parent->shadow_lock); | ||
| 1735 | if (sg) | ||
| 1736 | return sg; | ||
| 1737 | /* Create a new shadow gmap */ | ||
| 1738 | limit = -1UL >> (33 - (((asce & _ASCE_TYPE_MASK) >> 2) * 11)); | ||
| 1739 | if (asce & _ASCE_REAL_SPACE) | ||
| 1740 | limit = -1UL; | ||
| 1741 | new = gmap_alloc(limit); | ||
| 1742 | if (!new) | ||
| 1743 | return ERR_PTR(-ENOMEM); | ||
| 1744 | new->mm = parent->mm; | ||
| 1745 | new->parent = gmap_get(parent); | ||
| 1746 | new->private = parent->private; | ||
| 1747 | new->orig_asce = asce; | ||
| 1748 | new->edat_level = edat_level; | ||
| 1749 | new->initialized = false; | ||
| 1750 | spin_lock(&parent->shadow_lock); | ||
| 1751 | /* Recheck if another CPU created the same shadow */ | ||
| 1752 | sg = gmap_find_shadow(parent, asce, edat_level); | ||
| 1753 | if (sg) { | ||
| 1754 | spin_unlock(&parent->shadow_lock); | ||
| 1755 | gmap_free(new); | ||
| 1756 | return sg; | ||
| 1757 | } | ||
| 1758 | if (asce & _ASCE_REAL_SPACE) { | ||
| 1759 | /* only allow one real-space gmap shadow */ | ||
| 1760 | list_for_each_entry(sg, &parent->children, list) { | ||
| 1761 | if (sg->orig_asce & _ASCE_REAL_SPACE) { | ||
| 1762 | spin_lock(&sg->guest_table_lock); | ||
| 1763 | gmap_unshadow(sg); | ||
| 1764 | spin_unlock(&sg->guest_table_lock); | ||
| 1765 | list_del(&sg->list); | ||
| 1766 | gmap_put(sg); | ||
| 1767 | break; | ||
| 1768 | } | ||
| 1769 | } | ||
| 1770 | } | ||
| 1771 | refcount_set(&new->ref_count, 2); | ||
| 1772 | list_add(&new->list, &parent->children); | ||
| 1773 | if (asce & _ASCE_REAL_SPACE) { | ||
| 1774 | /* nothing to protect, return right away */ | ||
| 1775 | new->initialized = true; | ||
| 1776 | spin_unlock(&parent->shadow_lock); | ||
| 1777 | return new; | ||
| 1778 | } | ||
| 1779 | spin_unlock(&parent->shadow_lock); | ||
| 1780 | /* protect after insertion, so it will get properly invalidated */ | ||
| 1781 | mmap_read_lock(parent->mm); | ||
| 1782 | rc = gmap_protect_range(parent, asce & _ASCE_ORIGIN, | ||
| 1783 | ((asce & _ASCE_TABLE_LENGTH) + 1) * PAGE_SIZE, | ||
| 1784 | PROT_READ, GMAP_NOTIFY_SHADOW); | ||
| 1785 | mmap_read_unlock(parent->mm); | ||
| 1786 | spin_lock(&parent->shadow_lock); | ||
| 1787 | new->initialized = true; | ||
| 1788 | if (rc) { | ||
| 1789 | list_del(&new->list); | ||
| 1790 | gmap_free(new); | ||
| 1791 | new = ERR_PTR(rc); | ||
| 1792 | } | ||
| 1793 | spin_unlock(&parent->shadow_lock); | ||
| 1794 | return new; | ||
| 1795 | } | ||
| 1796 | EXPORT_SYMBOL_GPL(gmap_shadow); | ||
| 1797 | 1490 | ||
| 1798 | /** | 1491 | /** |
| 1799 | * gmap_shadow_r2t - create an empty shadow region 2 table | 1492 | * gmap_shadow_r2t - create an empty shadow region 2 table |
| @@ -1827,9 +1520,6 @@ int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t, · 27 unmodified lines | |||
| 1827 | page = gmap_alloc_crst(); | 1520 | page = gmap_alloc_crst(); |
| 1828 | if (!page) | 1521 | if (!page) |
| 1829 | return -ENOMEM; | 1522 | return -ENOMEM; |
| 1830 | page->index = r2t & _REGION_ENTRY_ORIGIN; | ||
| 1831 | if (fake) | ||
| 1832 | page->index |= GMAP_SHADOW_FAKE_TABLE; | ||
| 1833 | s_r2t = page_to_phys(page); | 1523 | s_r2t = page_to_phys(page); |
| 1834 | /* Install shadow region second table */ | 1524 | /* Install shadow region second table */ |
| 1835 | spin_lock(&sg->guest_table_lock); | 1525 | spin_lock(&sg->guest_table_lock); |
| @@ -1851,7 +1541,6 @@ int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t, · 15 unmodified lines | |||
| 1851 | _REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INVALID; | 1541 | _REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INVALID; |
| 1852 | if (sg->edat_level >= 1) | 1542 | if (sg->edat_level >= 1) |
| 1853 | *table |= (r2t & _REGION_ENTRY_PROTECT); | 1543 | *table |= (r2t & _REGION_ENTRY_PROTECT); |
| 1854 | list_add(&page->lru, &sg->crst_list); | ||
| 1855 | if (fake) { | 1544 | if (fake) { |
| 1856 | /* nothing to protect for fake tables */ | 1545 | /* nothing to protect for fake tables */ |
| 1857 | *table &= ~_REGION_ENTRY_INVALID; | 1546 | *table &= ~_REGION_ENTRY_INVALID; |
| @@ -1911,9 +1600,6 @@ int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t, · 53 unmodified lines | |||
| 1911 | page = gmap_alloc_crst(); | 1600 | page = gmap_alloc_crst(); |
| 1912 | if (!page) | 1601 | if (!page) |
| 1913 | return -ENOMEM; | 1602 | return -ENOMEM; |
| 1914 | page->index = r3t & _REGION_ENTRY_ORIGIN; | ||
| 1915 | if (fake) | ||
| 1916 | page->index |= GMAP_SHADOW_FAKE_TABLE; | ||
| 1917 | s_r3t = page_to_phys(page); | 1603 | s_r3t = page_to_phys(page); |
| 1918 | /* Install shadow region second table */ | 1604 | /* Install shadow region second table */ |
| 1919 | spin_lock(&sg->guest_table_lock); | 1605 | spin_lock(&sg->guest_table_lock); |
| @@ -1935,7 +1621,6 @@ int gmap_shadow_r3t(struct gmap *sg, unsigned long saddr, unsigned long r3t, · 15 unmodified lines | |||
| 1935 | _REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INVALID; | 1621 | _REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INVALID; |
| 1936 | if (sg->edat_level >= 1) | 1622 | if (sg->edat_level >= 1) |
| 1937 | *table |= (r3t & _REGION_ENTRY_PROTECT); | 1623 | *table |= (r3t & _REGION_ENTRY_PROTECT); |
| 1938 | list_add(&page->lru, &sg->crst_list); | ||
| 1939 | if (fake) { | 1624 | if (fake) { |
| 1940 | /* nothing to protect for fake tables */ | 1625 | /* nothing to protect for fake tables */ |
| 1941 | *table &= ~_REGION_ENTRY_INVALID; | 1626 | *table &= ~_REGION_ENTRY_INVALID; |
| @@ -1995,9 +1680,6 @@ int gmap_shadow_sgt(struct gmap *sg, unsigned long saddr, unsigned long sgt, · 53 unmodified lines | |||
| 1995 | page = gmap_alloc_crst(); | 1680 | page = gmap_alloc_crst(); |
| 1996 | if (!page) | 1681 | if (!page) |
| 1997 | return -ENOMEM; | 1682 | return -ENOMEM; |
| 1998 | page->index = sgt & _REGION_ENTRY_ORIGIN; | ||
| 1999 | if (fake) | ||
| 2000 | page->index |= GMAP_SHADOW_FAKE_TABLE; | ||
| 2001 | s_sgt = page_to_phys(page); | 1683 | s_sgt = page_to_phys(page); |
| 2002 | /* Install shadow region second table */ | 1684 | /* Install shadow region second table */ |
| 2003 | spin_lock(&sg->guest_table_lock); | 1685 | spin_lock(&sg->guest_table_lock); |
| @@ -2019,7 +1701,6 @@ int gmap_shadow_sgt(struct gmap *sg, unsigned long saddr, unsigned long sgt, · 15 unmodified lines | |||
| 2019 | _REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID; | 1701 | _REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID; |
| 2020 | if (sg->edat_level >= 1) | 1702 | if (sg->edat_level >= 1) |
| 2021 | *table |= sgt & _REGION_ENTRY_PROTECT; | 1703 | *table |= sgt & _REGION_ENTRY_PROTECT; |
| 2022 | list_add(&page->lru, &sg->crst_list); | ||
| 2023 | if (fake) { | 1704 | if (fake) { |
| 2024 | /* nothing to protect for fake tables */ | 1705 | /* nothing to protect for fake tables */ |
| 2025 | *table &= ~_REGION_ENTRY_INVALID; | 1706 | *table &= ~_REGION_ENTRY_INVALID; |
| @@ -2052,45 +1733,22 @@ out_free: · 26 unmodified lines | |||
| 2052 | } | 1733 | } |
| 2053 | EXPORT_SYMBOL_GPL(gmap_shadow_sgt); | 1734 | EXPORT_SYMBOL_GPL(gmap_shadow_sgt); |
| 2054 | 1735 | ||
| 2055 | /** | 1736 | static void gmap_pgste_set_pgt_addr(struct ptdesc *ptdesc, unsigned long pgt_addr) |
| 2056 | * gmap_shadow_pgt_lookup - find a shadow page table | ||
| 2057 | * @sg: pointer to the shadow guest address space structure | ||
| 2058 | * @saddr: the address in the shadow aguest address space | ||
| 2059 | * @pgt: parent gmap address of the page table to get shadowed | ||
| 2060 | * @dat_protection: if the pgtable is marked as protected by dat | ||
| 2061 | * @fake: pgt references contiguous guest memory block, not a pgtable | ||
| 2062 | * | ||
| 2063 | * Returns 0 if the shadow page table was found and -EAGAIN if the page | ||
| 2064 | * table was not found. | ||
| 2065 | * | ||
| 2066 | * Called with sg->mm->mmap_lock in read. | ||
| 2067 | */ | ||
| 2068 | int gmap_shadow_pgt_lookup(struct gmap *sg, unsigned long saddr, | ||
| 2069 | unsigned long *pgt, int *dat_protection, | ||
| 2070 | int *fake) | ||
| 2071 | { | 1737 | { |
| 2072 | unsigned long *table; | 1738 | unsigned long *pgstes = page_to_virt(ptdesc_page(ptdesc)); |
| 2073 | struct page *page; | ||
| 2074 | int rc; | ||
| 2075 | 1739 | ||
| 2076 | BUG_ON(!gmap_is_shadow(sg)); | 1740 | pgstes += _PAGE_ENTRIES; |
| 2077 | spin_lock(&sg->guest_table_lock); | 1741 | |
| 2078 | table = gmap_table_walk(sg, saddr, 1); /* get segment pointer */ | 1742 | pgstes[0] &= ~PGSTE_ST2_MASK; |
| 2079 | if (table && !(*table & _SEGMENT_ENTRY_INVALID)) { | 1743 | pgstes[1] &= ~PGSTE_ST2_MASK; |
| 2080 | /* Shadow page tables are full pages (pte+pgste) */ | 1744 | pgstes[2] &= ~PGSTE_ST2_MASK; |
| 2081 | page = pfn_to_page(*table >> PAGE_SHIFT); | 1745 | pgstes[3] &= ~PGSTE_ST2_MASK; |
| 2082 | *pgt = page->index & ~GMAP_SHADOW_FAKE_TABLE; | ||
| 2083 | *dat_protection = !!(*table & _SEGMENT_ENTRY_PROTECT); | ||
| 2084 | *fake = !!(page->index & GMAP_SHADOW_FAKE_TABLE); | ||
| 2085 | rc = 0; | ||
| 2086 | } else { | ||
| 2087 | rc = -EAGAIN; | ||
| 2088 | } | ||
| 2089 | spin_unlock(&sg->guest_table_lock); | ||
| 2090 | return rc; | ||
| 2091 | 1746 | ||
| 1747 | pgstes[0] |= (pgt_addr >> 16) & PGSTE_ST2_MASK; | ||
| 1748 | pgstes[1] |= pgt_addr & PGSTE_ST2_MASK; | ||
| 1749 | pgstes[2] |= (pgt_addr << 16) & PGSTE_ST2_MASK; | ||
| 1750 | pgstes[3] |= (pgt_addr << 32) & PGSTE_ST2_MASK; | ||
| 2092 | } | 1751 | } |
| 2093 | EXPORT_SYMBOL_GPL(gmap_shadow_pgt_lookup); | ||
| 2094 | 1752 | ||
| 2095 | /** | 1753 | /** |
| 2096 | * gmap_shadow_pgt - instantiate a shadow page table | 1754 | * gmap_shadow_pgt - instantiate a shadow page table |
| @@ -2119,9 +1777,10 @@ int gmap_shadow_pgt(struct gmap *sg, unsigned long saddr, unsigned long pgt, · 22 unmodified lines | |||
| 2119 | ptdesc = page_table_alloc_pgste(sg->mm); | 1777 | ptdesc = page_table_alloc_pgste(sg->mm); |
| 2120 | if (!ptdesc) | 1778 | if (!ptdesc) |
| 2121 | return -ENOMEM; | 1779 | return -ENOMEM; |
| 2122 | ptdesc->pt_index = pgt & _SEGMENT_ENTRY_ORIGIN; | 1780 | origin = pgt & _SEGMENT_ENTRY_ORIGIN; |
| 2123 | if (fake) | 1781 | if (fake) |
| 2124 | ptdesc->pt_index |= GMAP_SHADOW_FAKE_TABLE; | 1782 | origin |= GMAP_SHADOW_FAKE_TABLE; |
| 1783 | gmap_pgste_set_pgt_addr(ptdesc, origin); | ||
| 2125 | s_pgt = page_to_phys(ptdesc_page(ptdesc)); | 1784 | s_pgt = page_to_phys(ptdesc_page(ptdesc)); |
| 2126 | /* Install shadow page table */ | 1785 | /* Install shadow page table */ |
| 2127 | spin_lock(&sg->guest_table_lock); | 1786 | spin_lock(&sg->guest_table_lock); |
| @@ -2140,7 +1799,6 @@ int gmap_shadow_pgt(struct gmap *sg, unsigned long saddr, unsigned long pgt, · 12 unmodified lines | |||
| 2140 | /* mark as invalid as long as the parent table is not protected */ | 1799 | /* mark as invalid as long as the parent table is not protected */ |
| 2141 | *table = (unsigned long) s_pgt | _SEGMENT_ENTRY | | 1800 | *table = (unsigned long) s_pgt | _SEGMENT_ENTRY | |
| 2142 | (pgt & _SEGMENT_ENTRY_PROTECT) | _SEGMENT_ENTRY_INVALID; | 1801 | (pgt & _SEGMENT_ENTRY_PROTECT) | _SEGMENT_ENTRY_INVALID; |
| 2143 | list_add(&ptdesc->pt_list, &sg->pt_list); | ||
| 2144 | if (fake) { | 1802 | if (fake) { |
| 2145 | /* nothing to protect for fake tables */ | 1803 | /* nothing to protect for fake tables */ |
| 2146 | *table &= ~_SEGMENT_ENTRY_INVALID; | 1804 | *table &= ~_SEGMENT_ENTRY_INVALID; |
| @@ -2318,7 +1976,6 @@ void ptep_notify(struct mm_struct *mm, unsigned long vmaddr, · 171 unmodified lines | |||
| 2318 | pte_t *pte, unsigned long bits) | 1976 | pte_t *pte, unsigned long bits) |
| 2319 | { | 1977 | { |
| 2320 | unsigned long offset, gaddr = 0; | 1978 | unsigned long offset, gaddr = 0; |
| 2321 | unsigned long *table; | ||
| 2322 | struct gmap *gmap, *sg, *next; | 1979 | struct gmap *gmap, *sg, *next; |
| 2323 | 1980 | ||
| 2324 | offset = ((unsigned long) pte) & (255 * sizeof(pte_t)); | 1981 | offset = ((unsigned long) pte) & (255 * sizeof(pte_t)); |
| @@ -2326,12 +1983,9 @@ void ptep_notify(struct mm_struct *mm, unsigned long vmaddr, · 1 unmodified line | |||
| 2326 | rcu_read_lock(); | 1983 | rcu_read_lock(); |
| 2327 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { | 1984 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { |
| 2328 | spin_lock(&gmap->guest_table_lock); | 1985 | spin_lock(&gmap->guest_table_lock); |
| 2329 | table = radix_tree_lookup(&gmap->host_to_guest, | 1986 | gaddr = host_to_guest_lookup(gmap, vmaddr) + offset; |
| 2330 | vmaddr >> PMD_SHIFT); | ||
| 2331 | if (table) | ||
| 2332 | gaddr = __gmap_segment_gaddr(table) + offset; | ||
| 2333 | spin_unlock(&gmap->guest_table_lock); | 1987 | spin_unlock(&gmap->guest_table_lock); |
| 2334 | if (!table) | 1988 | if (!IS_GADDR_VALID(gaddr)) |
| 2335 | continue; | 1989 | continue; |
| 2336 | 1990 | ||
| 2337 | if (!list_empty(&gmap->children) && (bits & PGSTE_VSIE_BIT)) { | 1991 | if (!list_empty(&gmap->children) && (bits & PGSTE_VSIE_BIT)) { |
| @@ -2391,10 +2045,8 @@ static void gmap_pmdp_clear(struct mm_struct *mm, unsigned long vmaddr, · 53 unmodified lines | |||
| 2391 | rcu_read_lock(); | 2045 | rcu_read_lock(); |
| 2392 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { | 2046 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { |
| 2393 | spin_lock(&gmap->guest_table_lock); | 2047 | spin_lock(&gmap->guest_table_lock); |
| 2394 | pmdp = (pmd_t *)radix_tree_delete(&gmap->host_to_guest, | 2048 | pmdp = host_to_guest_pmd_delete(gmap, vmaddr, &gaddr); |
| 2395 | vmaddr >> PMD_SHIFT); | ||
| 2396 | if (pmdp) { | 2049 | if (pmdp) { |
| 2397 | gaddr = __gmap_segment_gaddr((unsigned long *)pmdp); | ||
| 2398 | pmdp_notify_gmap(gmap, pmdp, gaddr); | 2050 | pmdp_notify_gmap(gmap, pmdp, gaddr); |
| 2399 | WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | | 2051 | WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | |
| 2400 | _SEGMENT_ENTRY_GMAP_UC | | 2052 | _SEGMENT_ENTRY_GMAP_UC | |
| @@ -2438,28 +2090,25 @@ EXPORT_SYMBOL_GPL(gmap_pmdp_csp); · 37 unmodified lines | |||
| 2438 | */ | 2090 | */ |
| 2439 | void gmap_pmdp_idte_local(struct mm_struct *mm, unsigned long vmaddr) | 2091 | void gmap_pmdp_idte_local(struct mm_struct *mm, unsigned long vmaddr) |
| 2440 | { | 2092 | { |
| 2441 | unsigned long *entry, gaddr; | 2093 | unsigned long gaddr; |
| 2442 | struct gmap *gmap; | 2094 | struct gmap *gmap; |
| 2443 | pmd_t *pmdp; | 2095 | pmd_t *pmdp; |
| 2444 | 2096 | ||
| 2445 | rcu_read_lock(); | 2097 | rcu_read_lock(); |
| 2446 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { | 2098 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { |
| 2447 | spin_lock(&gmap->guest_table_lock); | 2099 | spin_lock(&gmap->guest_table_lock); |
| 2448 | entry = radix_tree_delete(&gmap->host_to_guest, | 2100 | pmdp = host_to_guest_pmd_delete(gmap, vmaddr, &gaddr); |
| 2449 | vmaddr >> PMD_SHIFT); | 2101 | if (pmdp) { |
| 2450 | if (entry) { | ||
| 2451 | pmdp = (pmd_t *)entry; | ||
| 2452 | gaddr = __gmap_segment_gaddr(entry); | ||
| 2453 | pmdp_notify_gmap(gmap, pmdp, gaddr); | 2102 | pmdp_notify_gmap(gmap, pmdp, gaddr); |
| 2454 | WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | | 2103 | WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | |
| 2455 | _SEGMENT_ENTRY_GMAP_UC | | 2104 | _SEGMENT_ENTRY_GMAP_UC | |
| 2456 | _SEGMENT_ENTRY)); | 2105 | _SEGMENT_ENTRY)); |
| 2457 | if (MACHINE_HAS_TLB_GUEST) | 2106 | if (MACHINE_HAS_TLB_GUEST) |
| 2458 | __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, | 2107 | __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, |
| 2459 | gmap->asce, IDTE_LOCAL); | 2108 | gmap->asce, IDTE_LOCAL); |
| 2460 | else if (MACHINE_HAS_IDTE) | 2109 | else if (MACHINE_HAS_IDTE) |
| 2461 | __pmdp_idte(gaddr, pmdp, 0, 0, IDTE_LOCAL); | 2110 | __pmdp_idte(gaddr, pmdp, 0, 0, IDTE_LOCAL); |
| 2462 | *entry = _SEGMENT_ENTRY_EMPTY; | 2111 | *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); |
| 2463 | } | 2112 | } |
| 2464 | spin_unlock(&gmap->guest_table_lock); | 2113 | spin_unlock(&gmap->guest_table_lock); |
| 2465 | } | 2114 | } |
| @@ -2474,22 +2123,19 @@ EXPORT_SYMBOL_GPL(gmap_pmdp_idte_local); · 8 unmodified lines | |||
| 2474 | */ | 2123 | */ |
| 2475 | void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr) | 2124 | void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr) |
| 2476 | { | 2125 | { |
| 2477 | unsigned long *entry, gaddr; | 2126 | unsigned long gaddr; |
| 2478 | struct gmap *gmap; | 2127 | struct gmap *gmap; |
| 2479 | pmd_t *pmdp; | 2128 | pmd_t *pmdp; |
| 2480 | 2129 | ||
| 2481 | rcu_read_lock(); | 2130 | rcu_read_lock(); |
| 2482 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { | 2131 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { |
| 2483 | spin_lock(&gmap->guest_table_lock); | 2132 | spin_lock(&gmap->guest_table_lock); |
| 2484 | entry = radix_tree_delete(&gmap->host_to_guest, | 2133 | pmdp = host_to_guest_pmd_delete(gmap, vmaddr, &gaddr); |
| 2485 | vmaddr >> PMD_SHIFT); | 2134 | if (pmdp) { |
| 2486 | if (entry) { | ||
| 2487 | pmdp = (pmd_t *)entry; | ||
| 2488 | gaddr = __gmap_segment_gaddr(entry); | ||
| 2489 | pmdp_notify_gmap(gmap, pmdp, gaddr); | 2135 | pmdp_notify_gmap(gmap, pmdp, gaddr); |
| 2490 | WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | | 2136 | WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | |
| 2491 | _SEGMENT_ENTRY_GMAP_UC | | 2137 | _SEGMENT_ENTRY_GMAP_UC | |
| 2492 | _SEGMENT_ENTRY)); | 2138 | _SEGMENT_ENTRY)); |
| 2493 | if (MACHINE_HAS_TLB_GUEST) | 2139 | if (MACHINE_HAS_TLB_GUEST) |
| 2494 | __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, | 2140 | __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, |
| 2495 | gmap->asce, IDTE_GLOBAL); | 2141 | gmap->asce, IDTE_GLOBAL); |
| @@ -2497,7 +2143,7 @@ void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr) · 1 unmodified line | |||
| 2497 | __pmdp_idte(gaddr, pmdp, 0, 0, IDTE_GLOBAL); | 2143 | __pmdp_idte(gaddr, pmdp, 0, 0, IDTE_GLOBAL); |
| 2498 | else | 2144 | else |
| 2499 | __pmdp_csp(pmdp); | 2145 | __pmdp_csp(pmdp); |
| 2500 | *entry = _SEGMENT_ENTRY_EMPTY; | 2146 | *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); |
| 2501 | } | 2147 | } |
| 2502 | spin_unlock(&gmap->guest_table_lock); | 2148 | spin_unlock(&gmap->guest_table_lock); |
| 2503 | } | 2149 | } |
| @@ -2942,49 +2588,6 @@ int __s390_uv_destroy_range(struct mm_struct *mm, unsigned long start, · 438 unmodified lines | |||
| 2942 | } | 2588 | } |
| 2943 | EXPORT_SYMBOL_GPL(__s390_uv_destroy_range); | 2589 | EXPORT_SYMBOL_GPL(__s390_uv_destroy_range); |
| 2944 | 2590 | ||
| 2945 | /** | ||
| 2946 | * s390_unlist_old_asce - Remove the topmost level of page tables from the | ||
| 2947 | * list of page tables of the gmap. | ||
| 2948 | * @gmap: the gmap whose table is to be removed | ||
| 2949 | * | ||
| 2950 | * On s390x, KVM keeps a list of all pages containing the page tables of the | ||
| 2951 | * gmap (the CRST list). This list is used at tear down time to free all | ||
| 2952 | * pages that are now not needed anymore. | ||
| 2953 | * | ||
| 2954 | * This function removes the topmost page of the tree (the one pointed to by | ||
| 2955 | * the ASCE) from the CRST list. | ||
| 2956 | * | ||
| 2957 | * This means that it will not be freed when the VM is torn down, and needs | ||
| 2958 | * to be handled separately by the caller, unless a leak is actually | ||
| 2959 | * intended. Notice that this function will only remove the page from the | ||
| 2960 | * list, the page will still be used as a top level page table (and ASCE). | ||
| 2961 | */ | ||
| 2962 | void s390_unlist_old_asce(struct gmap *gmap) | ||
| 2963 | { | ||
| 2964 | struct page *old; | ||
| 2965 | |||
| 2966 | old = virt_to_page(gmap->table); | ||
| 2967 | spin_lock(&gmap->guest_table_lock); | ||
| 2968 | list_del(&old->lru); | ||
| 2969 | /* | ||
| 2970 | * Sometimes the topmost page might need to be "removed" multiple | ||
| 2971 | * times, for example if the VM is rebooted into secure mode several | ||
| 2972 | * times concurrently, or if s390_replace_asce fails after calling | ||
| 2973 | * s390_remove_old_asce and is attempted again later. In that case | ||
| 2974 | * the old asce has been removed from the list, and therefore it | ||
| 2975 | * will not be freed when the VM terminates, but the ASCE is still | ||
| 2976 | * in use and still pointed to. | ||
| 2977 | * A subsequent call to replace_asce will follow the pointer and try | ||
| 2978 | * to remove the same page from the list again. | ||
| 2979 | * Therefore it's necessary that the page of the ASCE has valid | ||
| 2980 | * pointers, so list_del can work (and do nothing) without | ||
| 2981 | * dereferencing stale or invalid pointers. | ||
| 2982 | */ | ||
| 2983 | INIT_LIST_HEAD(&old->lru); | ||
| 2984 | spin_unlock(&gmap->guest_table_lock); | ||
| 2985 | } | ||
| 2986 | EXPORT_SYMBOL_GPL(s390_unlist_old_asce); | ||
| 2987 | |||
| 2988 | /** | 2591 | /** |
| 2989 | * s390_replace_asce - Try to replace the current ASCE of a gmap with a copy | 2592 | * s390_replace_asce - Try to replace the current ASCE of a gmap with a copy |
| 2990 | * @gmap: the gmap whose ASCE needs to be replaced | 2593 | * @gmap: the gmap whose ASCE needs to be replaced |
| @@ -3004,8 +2607,6 @@ int s390_replace_asce(struct gmap *gmap) · 13 unmodified lines | |||
| 3004 | struct page *page; | 2607 | struct page *page; |
| 3005 | void *table; | 2608 | void *table; |
| 3006 | 2609 | ||
| 3007 | s390_unlist_old_asce(gmap); | ||
| 3008 | |||
| 3009 | /* Replacing segment type ASCEs would cause serious issues */ | 2610 | /* Replacing segment type ASCEs would cause serious issues */ |
| 3010 | if ((gmap->asce & _ASCE_TYPE_MASK) == _ASCE_TYPE_SEGMENT) | 2611 | if ((gmap->asce & _ASCE_TYPE_MASK) == _ASCE_TYPE_SEGMENT) |
| 3011 | return -EINVAL; | 2612 | return -EINVAL; |
| @@ -3013,19 +2614,9 @@ int s390_replace_asce(struct gmap *gmap) · 1 unmodified line | |||
| 3013 | page = gmap_alloc_crst(); | 2614 | page = gmap_alloc_crst(); |
| 3014 | if (!page) | 2615 | if (!page) |
| 3015 | return -ENOMEM; | 2616 | return -ENOMEM; |
| 3016 | page->index = 0; | ||
| 3017 | table = page_to_virt(page); | 2617 | table = page_to_virt(page); |
| 3018 | memcpy(table, gmap->table, 1UL << (CRST_ALLOC_ORDER + PAGE_SHIFT)); | 2618 | memcpy(table, gmap->table, 1UL << (CRST_ALLOC_ORDER + PAGE_SHIFT)); |
| 3019 | 2619 | ||
| 3020 | /* | ||
| 3021 | * The caller has to deal with the old ASCE, but here we make sure | ||
| 3022 | * the new one is properly added to the CRST list, so that | ||
| 3023 | * it will be freed when the VM is torn down. | ||
| 3024 | */ | ||
| 3025 | spin_lock(&gmap->guest_table_lock); | ||
| 3026 | list_add(&page->lru, &gmap->crst_list); | ||
| 3027 | spin_unlock(&gmap->guest_table_lock); | ||
| 3028 | |||
| 3029 | /* Set new table origin while preserving existing ASCE control bits */ | 2620 | /* Set new table origin while preserving existing ASCE control bits */ |
| 3030 | asce = (gmap->asce & ~_ASCE_ORIGIN) | __pa(table); | 2621 | asce = (gmap->asce & ~_ASCE_ORIGIN) | __pa(table); |
| 3031 | WRITE_ONCE(gmap->asce, asce); | 2622 | WRITE_ONCE(gmap->asce, asce); |
| @@ -3035,3 +2626,31 @@ int s390_replace_asce(struct gmap *gmap) · 3 unmodified lines | |||
| 3035 | return 0; | 2626 | return 0; |
| 3036 | } | 2627 | } |
| 3037 | EXPORT_SYMBOL_GPL(s390_replace_asce); | 2628 | EXPORT_SYMBOL_GPL(s390_replace_asce); |
| 2629 | |||
| 2630 | /** | ||
| 2631 | * kvm_s390_wiggle_split_folio() - try to drain extra references to a folio and optionally split | ||
| 2632 | * @mm: the mm containing the folio to work on | ||
| 2633 | * @folio: the folio | ||
| 2634 | * @split: whether to split a large folio | ||
| 2635 | * | ||
| 2636 | * Context: Must be called while holding an extra reference to the folio; | ||
| 2637 | * the mm lock should not be held. | ||
| 2638 | */ | ||
| 2639 | int kvm_s390_wiggle_split_folio(struct mm_struct *mm, struct folio *folio, bool split) | ||
| 2640 | { | ||
| 2641 | int rc; | ||
| 2642 | |||
| 2643 | lockdep_assert_not_held(&mm->mmap_lock); | ||
| 2644 | folio_wait_writeback(folio); | ||
| 2645 | lru_add_drain_all(); | ||
| 2646 | if (split) { | ||
| 2647 | folio_lock(folio); | ||
| 2648 | rc = split_folio(folio); | ||
| 2649 | folio_unlock(folio); | ||
| 2650 | |||
| 2651 | if (rc != -EBUSY) | ||
| 2652 | return rc; | ||
| 2653 | } | ||
| 2654 | return -EAGAIN; | ||
| 2655 | } | ||
| 2656 | EXPORT_SYMBOL_GPL(kvm_s390_wiggle_split_folio); | ||
| @@ -176,8 +176,6 @@ unsigned long *page_table_alloc(struct mm_struct *mm) · 175 unmodified lines | |||
| 176 | } | 176 | } |
| 177 | table = ptdesc_to_virt(ptdesc); | 177 | table = ptdesc_to_virt(ptdesc); |
| 178 | __arch_set_page_dat(table, 1); | 178 | __arch_set_page_dat(table, 1); |
| 179 | /* pt_list is used by gmap only */ | ||
| 180 | INIT_LIST_HEAD(&ptdesc->pt_list); | ||
| 181 | memset64((u64 *)table, _PAGE_INVALID, PTRS_PER_PTE); | 179 | memset64((u64 *)table, _PAGE_INVALID, PTRS_PER_PTE); |
| 182 | memset64((u64 *)table + PTRS_PER_PTE, 0, PTRS_PER_PTE); | 180 | memset64((u64 *)table + PTRS_PER_PTE, 0, PTRS_PER_PTE); |
| 183 | return table; | 181 | return table; |
| @@ -331,6 +331,17 @@ error: · 330 unmodified lines | |||
| 331 | return rc; | 331 | return rc; |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | static bool zpci_bus_is_isolated_vf(struct zpci_bus *zbus, struct zpci_dev *zdev) | ||
| 335 | { | ||
| 336 | struct pci_dev *pdev; | ||
| 337 | |||
| 338 | pdev = zpci_iov_find_parent_pf(zbus, zdev); | ||
| 339 | if (!pdev) | ||
| 340 | return true; | ||
| 341 | pci_dev_put(pdev); | ||
| 342 | return false; | ||
| 343 | } | ||
| 344 | |||
| 334 | int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) | 345 | int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) |
| 335 | { | 346 | { |
| 336 | bool topo_is_tid = zdev->tid_avail; | 347 | bool topo_is_tid = zdev->tid_avail; |
| @@ -345,6 +356,15 @@ int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) · 8 unmodified lines | |||
| 345 | 356 | ||
| 346 | topo = topo_is_tid ? zdev->tid : zdev->pchid; | 357 | topo = topo_is_tid ? zdev->tid : zdev->pchid; |
| 347 | zbus = zpci_bus_get(topo, topo_is_tid); | 358 | zbus = zpci_bus_get(topo, topo_is_tid); |
| 359 | /* | ||
| 360 | * An isolated VF gets its own domain/bus even if there exists | ||
| 361 | * a matching domain/bus already | ||
| 362 | */ | ||
| 363 | if (zbus && zpci_bus_is_isolated_vf(zbus, zdev)) { | ||
| 364 | zpci_bus_put(zbus); | ||
| 365 | zbus = NULL; | ||
| 366 | } | ||
| 367 | |||
| 348 | if (!zbus) { | 368 | if (!zbus) { |
| 349 | zbus = zpci_bus_alloc(topo, topo_is_tid); | 369 | zbus = zpci_bus_alloc(topo, topo_is_tid); |
| 350 | if (!zbus) | 370 | if (!zbus) |
| @@ -60,18 +60,35 @@ static int zpci_iov_link_virtfn(struct pci_dev *pdev, struct pci_dev *virtfn, in · 59 unmodified lines | |||
| 60 | return 0; | 60 | return 0; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn) | 63 | /** |
| 64 | * zpci_iov_find_parent_pf - Find the parent PF, if any, of the given function | ||
| 65 | * @zbus: The bus that the PCI function is on, or would be added on | ||
| 66 | * @zdev: The PCI function | ||
| 67 | * | ||
| 68 | * Finds the parent PF, if it exists and is configured, of the given PCI function | ||
| 69 | * and increments its refcount. Th PF is searched for on the provided bus so the | ||
| 70 | * caller has to ensure that this is the correct bus to search. This function may | ||
| 71 | * be used before adding the PCI function to a zbus. | ||
| 72 | * | ||
| 73 | * Return: Pointer to the struct pci_dev of the parent PF or NULL if it not | ||
| 74 | * found. If the function is not a VF or has no RequesterID information, | ||
| 75 | * NULL is returned as well. | ||
| 76 | */ | ||
| 77 | struct pci_dev *zpci_iov_find_parent_pf(struct zpci_bus *zbus, struct zpci_dev *zdev) | ||
| 64 | { | 78 | { |
| 65 | int i, cand_devfn; | 79 | int i, vfid, devfn, cand_devfn; |
| 66 | struct zpci_dev *zdev; | ||
| 67 | struct pci_dev *pdev; | 80 | struct pci_dev *pdev; |
| 68 | int vfid = vfn - 1; /* Linux' vfid's start at 0 vfn at 1*/ | ||
| 69 | int rc = 0; | ||
| 70 | 81 | ||
| 71 | if (!zbus->multifunction) | 82 | if (!zbus->multifunction) |
| 72 | return 0; | 83 | return NULL; |
| 73 | 84 | /* Non-VFs and VFs without RID available don't have a parent */ | |
| 74 | /* If the parent PF for the given VF is also configured in the | 85 | if (!zdev->vfn || !zdev->rid_available) |
| 86 | return NULL; | ||
| 87 | /* Linux vfid starts at 0 vfn at 1 */ | ||
| 88 | vfid = zdev->vfn - 1; | ||
| 89 | devfn = zdev->rid & ZPCI_RID_MASK_DEVFN; | ||
| 90 | /* | ||
| 91 | * If the parent PF for the given VF is also configured in the | ||
| 75 | * instance, it must be on the same zbus. | 92 | * instance, it must be on the same zbus. |
| 76 | * We can then identify the parent PF by checking what | 93 | * We can then identify the parent PF by checking what |
| 77 | * devfn the VF would have if it belonged to that PF using the PF's | 94 | * devfn the VF would have if it belonged to that PF using the PF's |
| @@ -85,15 +102,26 @@ int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn · 7 unmodified lines | |||
| 85 | if (!pdev) | 102 | if (!pdev) |
| 86 | continue; | 103 | continue; |
| 87 | cand_devfn = pci_iov_virtfn_devfn(pdev, vfid); | 104 | cand_devfn = pci_iov_virtfn_devfn(pdev, vfid); |
| 88 | if (cand_devfn == virtfn->devfn) { | 105 | if (cand_devfn == devfn) |
| 89 | rc = zpci_iov_link_virtfn(pdev, virtfn, vfid); | 106 | return pdev; |
| 90 | /* balance pci_get_slot() */ | ||
| 91 | pci_dev_put(pdev); | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | /* balance pci_get_slot() */ | 107 | /* balance pci_get_slot() */ |
| 95 | pci_dev_put(pdev); | 108 | pci_dev_put(pdev); |
| 96 | } | 109 | } |
| 97 | } | 110 | } |
| 111 | return NULL; | ||
| 112 | } | ||
| 113 | |||
| 114 | int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn) | ||
| 115 | { | ||
| 116 | struct zpci_dev *zdev = to_zpci(virtfn); | ||
| 117 | struct pci_dev *pdev_pf; | ||
| 118 | int rc = 0; | ||
| 119 | |||
| 120 | pdev_pf = zpci_iov_find_parent_pf(zbus, zdev); | ||
| 121 | if (pdev_pf) { | ||
| 122 | /* Linux' vfids start at 0 while zdev->vfn starts at 1 */ | ||
| 123 | rc = zpci_iov_link_virtfn(pdev_pf, virtfn, zdev->vfn - 1); | ||
| 124 | pci_dev_put(pdev_pf); | ||
| 125 | } | ||
| 98 | return rc; | 126 | return rc; |
| 99 | } | 127 | } |
| @@ -19,6 +19,8 @@ void zpci_iov_map_resources(struct pci_dev *pdev); · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn); | 20 | int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *virtfn, int vfn); |
| 21 | 21 | ||
| 22 | struct pci_dev *zpci_iov_find_parent_pf(struct zpci_bus *zbus, struct zpci_dev *zdev); | ||
| 23 | |||
| 22 | #else /* CONFIG_PCI_IOV */ | 24 | #else /* CONFIG_PCI_IOV */ |
| 23 | static inline void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn) {} | 25 | static inline void zpci_iov_remove_virtfn(struct pci_dev *pdev, int vfn) {} |
| 24 | 26 | ||
| @@ -28,5 +30,10 @@ static inline int zpci_iov_setup_virtfn(struct zpci_bus *zbus, struct pci_dev *v · 3 unmodified lines | |||
| 28 | { | 30 | { |
| 29 | return 0; | 31 | return 0; |
| 30 | } | 32 | } |
| 33 | |||
| 34 | static inline struct pci_dev *zpci_iov_find_parent_pf(struct zpci_bus *zbus, struct zpci_dev *zdev) | ||
| 35 | { | ||
| 36 | return NULL; | ||
| 37 | } | ||
| 31 | #endif /* CONFIG_PCI_IOV */ | 38 | #endif /* CONFIG_PCI_IOV */ |
| 32 | #endif /* __S390_PCI_IOV_h */ | 39 | #endif /* __S390_PCI_IOV_h */ |
| @@ -25,8 +25,10 @@ · 24 unmodified lines | |||
| 25 | #define MAX_IRQ_MSG_SIZE (sizeof(struct virtio_pcidev_msg) + sizeof(u32)) | 25 | #define MAX_IRQ_MSG_SIZE (sizeof(struct virtio_pcidev_msg) + sizeof(u32)) |
| 26 | #define NUM_IRQ_MSGS 10 | 26 | #define NUM_IRQ_MSGS 10 |
| 27 | 27 | ||
| 28 | #define HANDLE_NO_FREE(ptr) ((void *)((unsigned long)(ptr) | 1)) | 28 | struct um_pci_message_buffer { |
| 29 | #define HANDLE_IS_NO_FREE(ptr) ((unsigned long)(ptr) & 1) | 29 | struct virtio_pcidev_msg hdr; |
| 30 | u8 data[8]; | ||
| 31 | }; | ||
| 30 | 32 | ||
| 31 | struct um_pci_device { | 33 | struct um_pci_device { |
| 32 | struct virtio_device *vdev; | 34 | struct virtio_device *vdev; |
| @@ -36,6 +38,11 @@ struct um_pci_device { · 3 unmodified lines | |||
| 36 | 38 | ||
| 37 | struct virtqueue *cmd_vq, *irq_vq; | 39 | struct virtqueue *cmd_vq, *irq_vq; |
| 38 | 40 | ||
| 41 | #define UM_PCI_WRITE_BUFS 20 | ||
| 42 | struct um_pci_message_buffer bufs[UM_PCI_WRITE_BUFS + 1]; | ||
| 43 | void *extra_ptrs[UM_PCI_WRITE_BUFS + 1]; | ||
| 44 | DECLARE_BITMAP(used_bufs, UM_PCI_WRITE_BUFS); | ||
| 45 | |||
| 39 | #define UM_PCI_STAT_WAITING 0 | 46 | #define UM_PCI_STAT_WAITING 0 |
| 40 | unsigned long status; | 47 | unsigned long status; |
| 41 | 48 | ||
| @@ -61,12 +68,40 @@ static unsigned long um_pci_msi_used[BITS_TO_LONGS(MAX_MSI_VECTORS)]; · 19 unmodified lines | |||
| 61 | static unsigned int um_pci_max_delay_us = 40000; | 68 | static unsigned int um_pci_max_delay_us = 40000; |
| 62 | module_param_named(max_delay_us, um_pci_max_delay_us, uint, 0644); | 69 | module_param_named(max_delay_us, um_pci_max_delay_us, uint, 0644); |
| 63 | 70 | ||
| 64 | struct um_pci_message_buffer { | 71 | static int um_pci_get_buf(struct um_pci_device *dev, bool *posted) |
| 65 | struct virtio_pcidev_msg hdr; | 72 | { |
| 66 | u8 data[8]; | 73 | int i; |
| 67 | }; | 74 | |
| 75 | for (i = 0; i < UM_PCI_WRITE_BUFS; i++) { | ||
| 76 | if (!test_and_set_bit(i, dev->used_bufs)) | ||
| 77 | return i; | ||
| 78 | } | ||
| 68 | 79 | ||
| 69 | static struct um_pci_message_buffer __percpu *um_pci_msg_bufs; | 80 | *posted = false; |
| 81 | return UM_PCI_WRITE_BUFS; | ||
| 82 | } | ||
| 83 | |||
| 84 | static void um_pci_free_buf(struct um_pci_device *dev, void *buf) | ||
| 85 | { | ||
| 86 | int i; | ||
| 87 | |||
| 88 | if (buf == &dev->bufs[UM_PCI_WRITE_BUFS]) { | ||
| 89 | kfree(dev->extra_ptrs[UM_PCI_WRITE_BUFS]); | ||
| 90 | dev->extra_ptrs[UM_PCI_WRITE_BUFS] = NULL; | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | for (i = 0; i < UM_PCI_WRITE_BUFS; i++) { | ||
| 95 | if (buf == &dev->bufs[i]) { | ||
| 96 | kfree(dev->extra_ptrs[i]); | ||
| 97 | dev->extra_ptrs[i] = NULL; | ||
| 98 | WARN_ON(!test_and_clear_bit(i, dev->used_bufs)); | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | WARN_ON(1); | ||
| 104 | } | ||
| 70 | 105 | ||
| 71 | static int um_pci_send_cmd(struct um_pci_device *dev, | 106 | static int um_pci_send_cmd(struct um_pci_device *dev, |
| 72 | struct virtio_pcidev_msg *cmd, | 107 | struct virtio_pcidev_msg *cmd, |
| @@ -82,7 +117,9 @@ static int um_pci_send_cmd(struct um_pci_device *dev, · 9 unmodified lines | |||
| 82 | }; | 117 | }; |
| 83 | struct um_pci_message_buffer *buf; | 118 | struct um_pci_message_buffer *buf; |
| 84 | int delay_count = 0; | 119 | int delay_count = 0; |
| 120 | bool bounce_out; | ||
| 85 | int ret, len; | 121 | int ret, len; |
| 122 | int buf_idx; | ||
| 86 | bool posted; | 123 | bool posted; |
| 87 | 124 | ||
| 88 | if (WARN_ON(cmd_size < sizeof(*cmd) || cmd_size > sizeof(*buf))) | 125 | if (WARN_ON(cmd_size < sizeof(*cmd) || cmd_size > sizeof(*buf))) |
| @@ -101,26 +138,28 @@ static int um_pci_send_cmd(struct um_pci_device *dev, · 12 unmodified lines | |||
| 101 | break; | 138 | break; |
| 102 | } | 139 | } |
| 103 | 140 | ||
| 104 | buf = get_cpu_var(um_pci_msg_bufs); | 141 | bounce_out = !posted && cmd_size <= sizeof(*cmd) && |
| 105 | if (buf) | 142 | out && out_size <= sizeof(buf->data); |
| 106 | memcpy(buf, cmd, cmd_size); | ||
| 107 | 143 | ||
| 108 | if (posted) { | 144 | buf_idx = um_pci_get_buf(dev, &posted); |
| 109 | u8 *ncmd = kmalloc(cmd_size + extra_size, GFP_ATOMIC); | 145 | buf = &dev->bufs[buf_idx]; |
| 110 | 146 | memcpy(buf, cmd, cmd_size); | |
| 111 | if (ncmd) { | 147 | |
| 112 | memcpy(ncmd, cmd, cmd_size); | 148 | if (posted && extra && extra_size > sizeof(buf) - cmd_size) { |
| 113 | if (extra) | 149 | dev->extra_ptrs[buf_idx] = kmemdup(extra, extra_size, |
| 114 | memcpy(ncmd + cmd_size, extra, extra_size); | 150 | GFP_ATOMIC); |
| 115 | cmd = (void *)ncmd; | 151 | |
| 116 | cmd_size += extra_size; | 152 | if (!dev->extra_ptrs[buf_idx]) { |
| 117 | extra = NULL; | 153 | um_pci_free_buf(dev, buf); |
| 118 | extra_size = 0; | 154 | return -ENOMEM; |
| 119 | } else { | ||
| 120 | /* try without allocating memory */ | ||
| 121 | posted = false; | ||
| 122 | cmd = (void *)buf; | ||
| 123 | } | 155 | } |
| 156 | extra = dev->extra_ptrs[buf_idx]; | ||
| 157 | } else if (extra && extra_size <= sizeof(buf) - cmd_size) { | ||
| 158 | memcpy((u8 *)buf + cmd_size, extra, extra_size); | ||
| 159 | cmd_size += extra_size; | ||
| 160 | extra_size = 0; | ||
| 161 | extra = NULL; | ||
| 162 | cmd = (void *)buf; | ||
| 124 | } else { | 163 | } else { |
| 125 | cmd = (void *)buf; | 164 | cmd = (void *)buf; |
| 126 | } | 165 | } |
| @@ -128,39 +167,40 @@ static int um_pci_send_cmd(struct um_pci_device *dev, · 1 unmodified line | |||
| 128 | sg_init_one(&out_sg, cmd, cmd_size); | 167 | sg_init_one(&out_sg, cmd, cmd_size); |
| 129 | if (extra) | 168 | if (extra) |
| 130 | sg_init_one(&extra_sg, extra, extra_size); | 169 | sg_init_one(&extra_sg, extra, extra_size); |
| 131 | if (out) | 170 | /* allow stack for small buffers */ |
| 171 | if (bounce_out) | ||
| 172 | sg_init_one(&in_sg, buf->data, out_size); | ||
| 173 | else if (out) | ||
| 132 | sg_init_one(&in_sg, out, out_size); | 174 | sg_init_one(&in_sg, out, out_size); |
| 133 | 175 | ||
| 134 | /* add to internal virtio queue */ | 176 | /* add to internal virtio queue */ |
| 135 | ret = virtqueue_add_sgs(dev->cmd_vq, sgs_list, | 177 | ret = virtqueue_add_sgs(dev->cmd_vq, sgs_list, |
| 136 | extra ? 2 : 1, | 178 | extra ? 2 : 1, |
| 137 | out ? 1 : 0, | 179 | out ? 1 : 0, |
| 138 | posted ? cmd : HANDLE_NO_FREE(cmd), | 180 | cmd, GFP_ATOMIC); |
| 139 | GFP_ATOMIC); | ||
| 140 | if (ret) { | 181 | if (ret) { |
| 141 | if (posted) | 182 | um_pci_free_buf(dev, buf); |
| 142 | kfree(cmd); | 183 | return ret; |
| 143 | goto out; | ||
| 144 | } | 184 | } |
| 145 | 185 | ||
| 146 | if (posted) { | 186 | if (posted) { |
| 147 | virtqueue_kick(dev->cmd_vq); | 187 | virtqueue_kick(dev->cmd_vq); |
| 148 | ret = 0; | 188 | return 0; |
| 149 | goto out; | ||
| 150 | } | 189 | } |
| 151 | 190 | ||
| 152 | /* kick and poll for getting a response on the queue */ | 191 | /* kick and poll for getting a response on the queue */ |
| 153 | set_bit(UM_PCI_STAT_WAITING, &dev->status); | 192 | set_bit(UM_PCI_STAT_WAITING, &dev->status); |
| 154 | virtqueue_kick(dev->cmd_vq); | 193 | virtqueue_kick(dev->cmd_vq); |
| 194 | ret = 0; | ||
| 155 | 195 | ||
| 156 | while (1) { | 196 | while (1) { |
| 157 | void *completed = virtqueue_get_buf(dev->cmd_vq, &len); | 197 | void *completed = virtqueue_get_buf(dev->cmd_vq, &len); |
| 158 | 198 | ||
| 159 | if (completed == HANDLE_NO_FREE(cmd)) | 199 | if (completed == buf) |
| 160 | break; | 200 | break; |
| 161 | 201 | ||
| 162 | if (completed && !HANDLE_IS_NO_FREE(completed)) | 202 | if (completed) |
| 163 | kfree(completed); | 203 | um_pci_free_buf(dev, completed); |
| 164 | 204 | ||
| 165 | if (WARN_ONCE(virtqueue_is_broken(dev->cmd_vq) || | 205 | if (WARN_ONCE(virtqueue_is_broken(dev->cmd_vq) || |
| 166 | ++delay_count > um_pci_max_delay_us, | 206 | ++delay_count > um_pci_max_delay_us, |
| @@ -172,8 +212,11 @@ static int um_pci_send_cmd(struct um_pci_device *dev, · 5 unmodified lines | |||
| 172 | } | 212 | } |
| 173 | clear_bit(UM_PCI_STAT_WAITING, &dev->status); | 213 | clear_bit(UM_PCI_STAT_WAITING, &dev->status); |
| 174 | 214 | ||
| 175 | out: | 215 | if (bounce_out) |
| 176 | put_cpu_var(um_pci_msg_bufs); | 216 | memcpy(out, buf->data, out_size); |
| 217 | |||
| 218 | um_pci_free_buf(dev, buf); | ||
| 219 | |||
| 177 | return ret; | 220 | return ret; |
| 178 | } | 221 | } |
| 179 | 222 | ||
| @@ -187,20 +230,13 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset, · 7 unmodified lines | |||
| 187 | .size = size, | 230 | .size = size, |
| 188 | .addr = offset, | 231 | .addr = offset, |
| 189 | }; | 232 | }; |
| 190 | /* buf->data is maximum size - we may only use parts of it */ | 233 | /* max 8, we might not use it all */ |
| 191 | struct um_pci_message_buffer *buf; | 234 | u8 data[8]; |
| 192 | u8 *data; | ||
| 193 | unsigned long ret = ULONG_MAX; | ||
| 194 | size_t bytes = sizeof(buf->data); | ||
| 195 | 235 | ||
| 196 | if (!dev) | 236 | if (!dev) |
| 197 | return ULONG_MAX; | 237 | return ULONG_MAX; |
| 198 | 238 | ||
| 199 | buf = get_cpu_var(um_pci_msg_bufs); | 239 | memset(data, 0xff, sizeof(data)); |
| 200 | data = buf->data; | ||
| 201 | |||
| 202 | if (buf) | ||
| 203 | memset(data, 0xff, bytes); | ||
| 204 | 240 | ||
| 205 | switch (size) { | 241 | switch (size) { |
| 206 | case 1: | 242 | case 1: |
| @@ -212,34 +248,26 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset, · 5 unmodified lines | |||
| 212 | break; | 248 | break; |
| 213 | default: | 249 | default: |
| 214 | WARN(1, "invalid config space read size %d\n", size); | 250 | WARN(1, "invalid config space read size %d\n", size); |
| 215 | goto out; | 251 | return ULONG_MAX; |
| 216 | } | 252 | } |
| 217 | 253 | ||
| 218 | if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, bytes)) | 254 | if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, size)) |
| 219 | goto out; | 255 | return ULONG_MAX; |
| 220 | 256 | ||
| 221 | switch (size) { | 257 | switch (size) { |
| 222 | case 1: | 258 | case 1: |
| 223 | ret = data[0]; | 259 | return data[0]; |
| 224 | break; | ||
| 225 | case 2: | 260 | case 2: |
| 226 | ret = le16_to_cpup((void *)data); | 261 | return le16_to_cpup((void *)data); |
| 227 | break; | ||
| 228 | case 4: | 262 | case 4: |
| 229 | ret = le32_to_cpup((void *)data); | 263 | return le32_to_cpup((void *)data); |
| 230 | break; | ||
| 231 | #ifdef CONFIG_64BIT | 264 | #ifdef CONFIG_64BIT |
| 232 | case 8: | 265 | case 8: |
| 233 | ret = le64_to_cpup((void *)data); | 266 | return le64_to_cpup((void *)data); |
| 234 | break; | ||
| 235 | #endif | 267 | #endif |
| 236 | default: | 268 | default: |
| 237 | break; | 269 | return ULONG_MAX; |
| 238 | } | 270 | } |
| 239 | |||
| 240 | out: | ||
| 241 | put_cpu_var(um_pci_msg_bufs); | ||
| 242 | return ret; | ||
| 243 | } | 271 | } |
| 244 | 272 | ||
| 245 | static void um_pci_cfgspace_write(void *priv, unsigned int offset, int size, | 273 | static void um_pci_cfgspace_write(void *priv, unsigned int offset, int size, |
| @@ -312,13 +340,8 @@ static void um_pci_bar_copy_from(void *priv, void *buffer, · 66 unmodified lines | |||
| 312 | static unsigned long um_pci_bar_read(void *priv, unsigned int offset, | 340 | static unsigned long um_pci_bar_read(void *priv, unsigned int offset, |
| 313 | int size) | 341 | int size) |
| 314 | { | 342 | { |
| 315 | /* buf->data is maximum size - we may only use parts of it */ | 343 | /* 8 is maximum size - we may only use parts of it */ |
| 316 | struct um_pci_message_buffer *buf; | 344 | u8 data[8]; |
| 317 | u8 *data; | ||
| 318 | unsigned long ret = ULONG_MAX; | ||
| 319 | |||
| 320 | buf = get_cpu_var(um_pci_msg_bufs); | ||
| 321 | data = buf->data; | ||
| 322 | 345 | ||
| 323 | switch (size) { | 346 | switch (size) { |
| 324 | case 1: | 347 | case 1: |
| @@ -330,33 +353,25 @@ static unsigned long um_pci_bar_read(void *priv, unsigned int offset, · 5 unmodified lines | |||
| 330 | break; | 353 | break; |
| 331 | default: | 354 | default: |
| 332 | WARN(1, "invalid config space read size %d\n", size); | 355 | WARN(1, "invalid config space read size %d\n", size); |
| 333 | goto out; | 356 | return ULONG_MAX; |
| 334 | } | 357 | } |
| 335 | 358 | ||
| 336 | um_pci_bar_copy_from(priv, data, offset, size); | 359 | um_pci_bar_copy_from(priv, data, offset, size); |
| 337 | 360 | ||
| 338 | switch (size) { | 361 | switch (size) { |
| 339 | case 1: | 362 | case 1: |
| 340 | ret = data[0]; | 363 | return data[0]; |
| 341 | break; | ||
| 342 | case 2: | 364 | case 2: |
| 343 | ret = le16_to_cpup((void *)data); | 365 | return le16_to_cpup((void *)data); |
| 344 | break; | ||
| 345 | case 4: | 366 | case 4: |
| 346 | ret = le32_to_cpup((void *)data); | 367 | return le32_to_cpup((void *)data); |
| 347 | break; | ||
| 348 | #ifdef CONFIG_64BIT | 368 | #ifdef CONFIG_64BIT |
| 349 | case 8: | 369 | case 8: |
| 350 | ret = le64_to_cpup((void *)data); | 370 | return le64_to_cpup((void *)data); |
| 351 | break; | ||
| 352 | #endif | 371 | #endif |
| 353 | default: | 372 | default: |
| 354 | break; | 373 | return ULONG_MAX; |
| 355 | } | 374 | } |
| 356 | |||
| 357 | out: | ||
| 358 | put_cpu_var(um_pci_msg_bufs); | ||
| 359 | return ret; | ||
| 360 | } | 375 | } |
| 361 | 376 | ||
| 362 | static void um_pci_bar_copy_to(void *priv, unsigned int offset, | 377 | static void um_pci_bar_copy_to(void *priv, unsigned int offset, |
| @@ -523,11 +538,8 @@ static void um_pci_cmd_vq_cb(struct virtqueue *vq) · 160 unmodified lines | |||
| 523 | if (test_bit(UM_PCI_STAT_WAITING, &dev->status)) | 538 | if (test_bit(UM_PCI_STAT_WAITING, &dev->status)) |
| 524 | return; | 539 | return; |
| 525 | 540 | ||
| 526 | while ((cmd = virtqueue_get_buf(vq, &len))) { | 541 | while ((cmd = virtqueue_get_buf(vq, &len))) |
| 527 | if (WARN_ON(HANDLE_IS_NO_FREE(cmd))) | 542 | um_pci_free_buf(dev, cmd); |
| 528 | continue; | ||
| 529 | kfree(cmd); | ||
| 530 | } | ||
| 531 | } | 543 | } |
| 532 | 544 | ||
| 533 | static void um_pci_irq_vq_cb(struct virtqueue *vq) | 545 | static void um_pci_irq_vq_cb(struct virtqueue *vq) |
| @@ -1006,10 +1018,6 @@ static int __init um_pci_init(void) · 472 unmodified lines | |||
| 1006 | "No virtio device ID configured for PCI - no PCI support\n")) | 1018 | "No virtio device ID configured for PCI - no PCI support\n")) |
| 1007 | return 0; | 1019 | return 0; |
| 1008 | 1020 | ||
| 1009 | um_pci_msg_bufs = alloc_percpu(struct um_pci_message_buffer); | ||
| 1010 | if (!um_pci_msg_bufs) | ||
| 1011 | return -ENOMEM; | ||
| 1012 | |||
| 1013 | bridge = pci_alloc_host_bridge(0); | 1021 | bridge = pci_alloc_host_bridge(0); |
| 1014 | if (!bridge) { | 1022 | if (!bridge) { |
| 1015 | err = -ENOMEM; | 1023 | err = -ENOMEM; |
| @@ -1070,7 +1078,6 @@ free: · 54 unmodified lines | |||
| 1070 | pci_free_resource_list(&bridge->windows); | 1078 | pci_free_resource_list(&bridge->windows); |
| 1071 | pci_free_host_bridge(bridge); | 1079 | pci_free_host_bridge(bridge); |
| 1072 | } | 1080 | } |
| 1073 | free_percpu(um_pci_msg_bufs); | ||
| 1074 | return err; | 1081 | return err; |
| 1075 | } | 1082 | } |
| 1076 | module_init(um_pci_init); | 1083 | module_init(um_pci_init); |
| @@ -1082,6 +1089,5 @@ static void __exit um_pci_exit(void) · 5 unmodified lines | |||
| 1082 | irq_domain_remove(um_pci_inner_domain); | 1089 | irq_domain_remove(um_pci_inner_domain); |
| 1083 | pci_free_resource_list(&bridge->windows); | 1090 | pci_free_resource_list(&bridge->windows); |
| 1084 | pci_free_host_bridge(bridge); | 1091 | pci_free_host_bridge(bridge); |
| 1085 | free_percpu(um_pci_msg_bufs); | ||
| 1086 | } | 1092 | } |
| 1087 | module_exit(um_pci_exit); | 1093 | module_exit(um_pci_exit); |
| @@ -52,7 +52,7 @@ struct virtio_uml_device { · 51 unmodified lines | |||
| 52 | struct platform_device *pdev; | 52 | struct platform_device *pdev; |
| 53 | struct virtio_uml_platform_data *pdata; | 53 | struct virtio_uml_platform_data *pdata; |
| 54 | 54 | ||
| 55 | spinlock_t sock_lock; | 55 | raw_spinlock_t sock_lock; |
| 56 | int sock, req_fd, irq; | 56 | int sock, req_fd, irq; |
| 57 | u64 features; | 57 | u64 features; |
| 58 | u64 protocol_features; | 58 | u64 protocol_features; |
| @@ -246,7 +246,7 @@ static int vhost_user_send(struct virtio_uml_device *vu_dev, · 187 unmodified lines | |||
| 246 | if (request_ack) | 246 | if (request_ack) |
| 247 | msg->header.flags |= VHOST_USER_FLAG_NEED_REPLY; | 247 | msg->header.flags |= VHOST_USER_FLAG_NEED_REPLY; |
| 248 | 248 | ||
| 249 | spin_lock_irqsave(&vu_dev->sock_lock, flags); | 249 | raw_spin_lock_irqsave(&vu_dev->sock_lock, flags); |
| 250 | rc = full_sendmsg_fds(vu_dev->sock, msg, size, fds, num_fds); | 250 | rc = full_sendmsg_fds(vu_dev->sock, msg, size, fds, num_fds); |
| 251 | if (rc < 0) | 251 | if (rc < 0) |
| 252 | goto out; | 252 | goto out; |
| @@ -266,7 +266,7 @@ static int vhost_user_send(struct virtio_uml_device *vu_dev, · 13 unmodified lines | |||
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | out: | 268 | out: |
| 269 | spin_unlock_irqrestore(&vu_dev->sock_lock, flags); | 269 | raw_spin_unlock_irqrestore(&vu_dev->sock_lock, flags); |
| 270 | return rc; | 270 | return rc; |
| 271 | } | 271 | } |
| 272 | 272 | ||
| @@ -1239,7 +1239,7 @@ static int virtio_uml_probe(struct platform_device *pdev) · 966 unmodified lines | |||
| 1239 | goto error_free; | 1239 | goto error_free; |
| 1240 | vu_dev->sock = rc; | 1240 | vu_dev->sock = rc; |
| 1241 | 1241 | ||
| 1242 | spin_lock_init(&vu_dev->sock_lock); | 1242 | raw_spin_lock_init(&vu_dev->sock_lock); |
| 1243 | 1243 | ||
| 1244 | rc = vhost_user_init(vu_dev); | 1244 | rc = vhost_user_init(vu_dev); |
| 1245 | if (rc) | 1245 | if (rc) |
| @@ -52,7 +52,7 @@ struct irq_entry { · 51 unmodified lines | |||
| 52 | bool sigio_workaround; | 52 | bool sigio_workaround; |
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | static DEFINE_SPINLOCK(irq_lock); | 55 | static DEFINE_RAW_SPINLOCK(irq_lock); |
| 56 | static LIST_HEAD(active_fds); | 56 | static LIST_HEAD(active_fds); |
| 57 | static DECLARE_BITMAP(irqs_allocated, UM_LAST_SIGNAL_IRQ); | 57 | static DECLARE_BITMAP(irqs_allocated, UM_LAST_SIGNAL_IRQ); |
| 58 | static bool irqs_suspended; | 58 | static bool irqs_suspended; |
| @@ -257,7 +257,7 @@ static struct irq_entry *get_irq_entry_by_fd(int fd) · 198 unmodified lines | |||
| 257 | return NULL; | 257 | return NULL; |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static void free_irq_entry(struct irq_entry *to_free, bool remove) | 260 | static void remove_irq_entry(struct irq_entry *to_free, bool remove) |
| 261 | { | 261 | { |
| 262 | if (!to_free) | 262 | if (!to_free) |
| 263 | return; | 263 | return; |
| @@ -265,7 +265,6 @@ static void free_irq_entry(struct irq_entry *to_free, bool remove) · 1 unmodified line | |||
| 265 | if (remove) | 265 | if (remove) |
| 266 | os_del_epoll_fd(to_free->fd); | 266 | os_del_epoll_fd(to_free->fd); |
| 267 | list_del(&to_free->list); | 267 | list_del(&to_free->list); |
| 268 | kfree(to_free); | ||
| 269 | } | 268 | } |
| 270 | 269 | ||
| 271 | static bool update_irq_entry(struct irq_entry *entry) | 270 | static bool update_irq_entry(struct irq_entry *entry) |
| @@ -286,17 +285,19 @@ static bool update_irq_entry(struct irq_entry *entry) · 14 unmodified lines | |||
| 286 | return false; | 285 | return false; |
| 287 | } | 286 | } |
| 288 | 287 | ||
| 289 | static void update_or_free_irq_entry(struct irq_entry *entry) | 288 | static struct irq_entry *update_or_remove_irq_entry(struct irq_entry *entry) |
| 290 | { | 289 | { |
| 291 | if (!update_irq_entry(entry)) | 290 | if (update_irq_entry(entry)) |
| 292 | free_irq_entry(entry, false); | 291 | return NULL; |
| 292 | remove_irq_entry(entry, false); | ||
| 293 | return entry; | ||
| 293 | } | 294 | } |
| 294 | 295 | ||
| 295 | static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id, | 296 | static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id, |
| 296 | void (*timetravel_handler)(int, int, void *, | 297 | void (*timetravel_handler)(int, int, void *, |
| 297 | struct time_travel_event *)) | 298 | struct time_travel_event *)) |
| 298 | { | 299 | { |
| 299 | struct irq_entry *irq_entry; | 300 | struct irq_entry *irq_entry, *to_free = NULL; |
| 300 | int err, events = os_event_mask(type); | 301 | int err, events = os_event_mask(type); |
| 301 | unsigned long flags; | 302 | unsigned long flags; |
| 302 | 303 | ||
| @@ -304,9 +305,10 @@ static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id, · 1 unmodified line | |||
| 304 | if (err < 0) | 305 | if (err < 0) |
| 305 | goto out; | 306 | goto out; |
| 306 | 307 | ||
| 307 | spin_lock_irqsave(&irq_lock, flags); | 308 | raw_spin_lock_irqsave(&irq_lock, flags); |
| 308 | irq_entry = get_irq_entry_by_fd(fd); | 309 | irq_entry = get_irq_entry_by_fd(fd); |
| 309 | if (irq_entry) { | 310 | if (irq_entry) { |
| 311 | already: | ||
| 310 | /* cannot register the same FD twice with the same type */ | 312 | /* cannot register the same FD twice with the same type */ |
| 311 | if (WARN_ON(irq_entry->reg[type].events)) { | 313 | if (WARN_ON(irq_entry->reg[type].events)) { |
| 312 | err = -EALREADY; | 314 | err = -EALREADY; |
| @@ -316,11 +318,22 @@ static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id, · 3 unmodified lines | |||
| 316 | /* temporarily disable to avoid IRQ-side locking */ | 318 | /* temporarily disable to avoid IRQ-side locking */ |
| 317 | os_del_epoll_fd(fd); | 319 | os_del_epoll_fd(fd); |
| 318 | } else { | 320 | } else { |
| 319 | irq_entry = kzalloc(sizeof(*irq_entry), GFP_ATOMIC); | 321 | struct irq_entry *new; |
| 320 | if (!irq_entry) { | 322 | |
| 321 | err = -ENOMEM; | 323 | /* don't restore interrupts */ |
| 322 | goto out_unlock; | 324 | raw_spin_unlock(&irq_lock); |
| 325 | new = kzalloc(sizeof(*irq_entry), GFP_ATOMIC); | ||
| 326 | if (!new) { | ||
| 327 | local_irq_restore(flags); | ||
| 328 | return -ENOMEM; | ||
| 323 | } | 329 | } |
| 330 | raw_spin_lock(&irq_lock); | ||
| 331 | irq_entry = get_irq_entry_by_fd(fd); | ||
| 332 | if (irq_entry) { | ||
| 333 | to_free = new; | ||
| 334 | goto already; | ||
| 335 | } | ||
| 336 | irq_entry = new; | ||
| 324 | irq_entry->fd = fd; | 337 | irq_entry->fd = fd; |
| 325 | list_add_tail(&irq_entry->list, &active_fds); | 338 | list_add_tail(&irq_entry->list, &active_fds); |
| 326 | maybe_sigio_broken(fd); | 339 | maybe_sigio_broken(fd); |
| @@ -339,12 +352,11 @@ static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id, · 12 unmodified lines | |||
| 339 | #endif | 352 | #endif |
| 340 | 353 | ||
| 341 | WARN_ON(!update_irq_entry(irq_entry)); | 354 | WARN_ON(!update_irq_entry(irq_entry)); |
| 342 | spin_unlock_irqrestore(&irq_lock, flags); | 355 | err = 0; |
| 343 | |||
| 344 | return 0; | ||
| 345 | out_unlock: | 356 | out_unlock: |
| 346 | spin_unlock_irqrestore(&irq_lock, flags); | 357 | raw_spin_unlock_irqrestore(&irq_lock, flags); |
| 347 | out: | 358 | out: |
| 359 | kfree(to_free); | ||
| 348 | return err; | 360 | return err; |
| 349 | } | 361 | } |
| 350 | 362 | ||
| @@ -358,19 +370,20 @@ void free_irq_by_fd(int fd) · 7 unmodified lines | |||
| 358 | struct irq_entry *to_free; | 370 | struct irq_entry *to_free; |
| 359 | unsigned long flags; | 371 | unsigned long flags; |
| 360 | 372 | ||
| 361 | spin_lock_irqsave(&irq_lock, flags); | 373 | raw_spin_lock_irqsave(&irq_lock, flags); |
| 362 | to_free = get_irq_entry_by_fd(fd); | 374 | to_free = get_irq_entry_by_fd(fd); |
| 363 | free_irq_entry(to_free, true); | 375 | remove_irq_entry(to_free, true); |
| 364 | spin_unlock_irqrestore(&irq_lock, flags); | 376 | raw_spin_unlock_irqrestore(&irq_lock, flags); |
| 377 | kfree(to_free); | ||
| 365 | } | 378 | } |
| 366 | EXPORT_SYMBOL(free_irq_by_fd); | 379 | EXPORT_SYMBOL(free_irq_by_fd); |
| 367 | 380 | ||
| 368 | static void free_irq_by_irq_and_dev(unsigned int irq, void *dev) | 381 | static void free_irq_by_irq_and_dev(unsigned int irq, void *dev) |
| 369 | { | 382 | { |
| 370 | struct irq_entry *entry; | 383 | struct irq_entry *entry, *to_free = NULL; |
| 371 | unsigned long flags; | 384 | unsigned long flags; |
| 372 | 385 | ||
| 373 | spin_lock_irqsave(&irq_lock, flags); | 386 | raw_spin_lock_irqsave(&irq_lock, flags); |
| 374 | list_for_each_entry(entry, &active_fds, list) { | 387 | list_for_each_entry(entry, &active_fds, list) { |
| 375 | enum um_irq_type i; | 388 | enum um_irq_type i; |
| 376 | 389 | ||
| @@ -386,12 +399,13 @@ static void free_irq_by_irq_and_dev(unsigned int irq, void *dev) · 9 unmodified lines | |||
| 386 | 399 | ||
| 387 | os_del_epoll_fd(entry->fd); | 400 | os_del_epoll_fd(entry->fd); |
| 388 | reg->events = 0; | 401 | reg->events = 0; |
| 389 | update_or_free_irq_entry(entry); | 402 | to_free = update_or_remove_irq_entry(entry); |
| 390 | goto out; | 403 | goto out; |
| 391 | } | 404 | } |
| 392 | } | 405 | } |
| 393 | out: | 406 | out: |
| 394 | spin_unlock_irqrestore(&irq_lock, flags); | 407 | raw_spin_unlock_irqrestore(&irq_lock, flags); |
| 408 | kfree(to_free); | ||
| 395 | } | 409 | } |
| 396 | 410 | ||
| 397 | void deactivate_fd(int fd, int irqnum) | 411 | void deactivate_fd(int fd, int irqnum) |
| @@ -402,7 +416,7 @@ void deactivate_fd(int fd, int irqnum) · 4 unmodified lines | |||
| 402 | 416 | ||
| 403 | os_del_epoll_fd(fd); | 417 | os_del_epoll_fd(fd); |
| 404 | 418 | ||
| 405 | spin_lock_irqsave(&irq_lock, flags); | 419 | raw_spin_lock_irqsave(&irq_lock, flags); |
| 406 | entry = get_irq_entry_by_fd(fd); | 420 | entry = get_irq_entry_by_fd(fd); |
| 407 | if (!entry) | 421 | if (!entry) |
| 408 | goto out; | 422 | goto out; |
| @@ -414,9 +428,10 @@ void deactivate_fd(int fd, int irqnum) · 5 unmodified lines | |||
| 414 | entry->reg[i].events = 0; | 428 | entry->reg[i].events = 0; |
| 415 | } | 429 | } |
| 416 | 430 | ||
| 417 | update_or_free_irq_entry(entry); | 431 | entry = update_or_remove_irq_entry(entry); |
| 418 | out: | 432 | out: |
| 419 | spin_unlock_irqrestore(&irq_lock, flags); | 433 | raw_spin_unlock_irqrestore(&irq_lock, flags); |
| 434 | kfree(entry); | ||
| 420 | 435 | ||
| 421 | ignore_sigio_fd(fd); | 436 | ignore_sigio_fd(fd); |
| 422 | } | 437 | } |
| @@ -546,7 +561,7 @@ void um_irqs_suspend(void) · 123 unmodified lines | |||
| 546 | 561 | ||
| 547 | irqs_suspended = true; | 562 | irqs_suspended = true; |
| 548 | 563 | ||
| 549 | spin_lock_irqsave(&irq_lock, flags); | 564 | raw_spin_lock_irqsave(&irq_lock, flags); |
| 550 | list_for_each_entry(entry, &active_fds, list) { | 565 | list_for_each_entry(entry, &active_fds, list) { |
| 551 | enum um_irq_type t; | 566 | enum um_irq_type t; |
| 552 | bool clear = true; | 567 | bool clear = true; |
| @@ -579,7 +594,7 @@ void um_irqs_suspend(void) · 26 unmodified lines | |||
| 579 | !__ignore_sigio_fd(entry->fd); | 594 | !__ignore_sigio_fd(entry->fd); |
| 580 | } | 595 | } |
| 581 | } | 596 | } |
| 582 | spin_unlock_irqrestore(&irq_lock, flags); | 597 | raw_spin_unlock_irqrestore(&irq_lock, flags); |
| 583 | } | 598 | } |
| 584 | 599 | ||
| 585 | void um_irqs_resume(void) | 600 | void um_irqs_resume(void) |
| @@ -588,7 +603,7 @@ void um_irqs_resume(void) · 2 unmodified lines | |||
| 588 | unsigned long flags; | 603 | unsigned long flags; |
| 589 | 604 | ||
| 590 | 605 | ||
| 591 | spin_lock_irqsave(&irq_lock, flags); | 606 | raw_spin_lock_irqsave(&irq_lock, flags); |
| 592 | list_for_each_entry(entry, &active_fds, list) { | 607 | list_for_each_entry(entry, &active_fds, list) { |
| 593 | if (entry->suspended) { | 608 | if (entry->suspended) { |
| 594 | int err = os_set_fd_async(entry->fd); | 609 | int err = os_set_fd_async(entry->fd); |
| @@ -602,7 +617,7 @@ void um_irqs_resume(void) · 7 unmodified lines | |||
| 602 | } | 617 | } |
| 603 | } | 618 | } |
| 604 | } | 619 | } |
| 605 | spin_unlock_irqrestore(&irq_lock, flags); | 620 | raw_spin_unlock_irqrestore(&irq_lock, flags); |
| 606 | 621 | ||
| 607 | irqs_suspended = false; | 622 | irqs_suspended = false; |
| 608 | send_sigio_to_self(); | 623 | send_sigio_to_self(); |
| @@ -613,7 +628,7 @@ static int normal_irq_set_wake(struct irq_data *d, unsigned int on) · 4 unmodified lines | |||
| 613 | struct irq_entry *entry; | 628 | struct irq_entry *entry; |
| 614 | unsigned long flags; | 629 | unsigned long flags; |
| 615 | 630 | ||
| 616 | spin_lock_irqsave(&irq_lock, flags); | 631 | raw_spin_lock_irqsave(&irq_lock, flags); |
| 617 | list_for_each_entry(entry, &active_fds, list) { | 632 | list_for_each_entry(entry, &active_fds, list) { |
| 618 | enum um_irq_type t; | 633 | enum um_irq_type t; |
| 619 | 634 | ||
| @@ -628,7 +643,7 @@ static int normal_irq_set_wake(struct irq_data *d, unsigned int on) · 8 unmodified lines | |||
| 628 | } | 643 | } |
| 629 | } | 644 | } |
| 630 | unlock: | 645 | unlock: |
| 631 | spin_unlock_irqrestore(&irq_lock, flags); | 646 | raw_spin_unlock_irqrestore(&irq_lock, flags); |
| 632 | return 0; | 647 | return 0; |
| 633 | } | 648 | } |
| 634 | #else | 649 | #else |
| @@ -191,7 +191,15 @@ void initial_thread_cb(void (*proc)(void *), void *arg) · 190 unmodified lines | |||
| 191 | int arch_dup_task_struct(struct task_struct *dst, | 191 | int arch_dup_task_struct(struct task_struct *dst, |
| 192 | struct task_struct *src) | 192 | struct task_struct *src) |
| 193 | { | 193 | { |
| 194 | memcpy(dst, src, arch_task_struct_size); | 194 | /* init_task is not dynamically sized (missing FPU state) */ |
| 195 | if (unlikely(src == &init_task)) { | ||
| 196 | memcpy(dst, src, sizeof(init_task)); | ||
| 197 | memset((void *)dst + sizeof(init_task), 0, | ||
| 198 | arch_task_struct_size - sizeof(init_task)); | ||
| 199 | } else { | ||
| 200 | memcpy(dst, src, arch_task_struct_size); | ||
| 201 | } | ||
| 202 | |||
| 195 | return 0; | 203 | return 0; |
| 196 | } | 204 | } |
| 197 | 205 | ||
| @@ -181,6 +181,10 @@ extern char __syscall_stub_start[]; · 180 unmodified lines | |||
| 181 | 181 | ||
| 182 | static int stub_exe_fd; | 182 | static int stub_exe_fd; |
| 183 | 183 | ||
| 184 | #ifndef CLOSE_RANGE_CLOEXEC | ||
| 185 | #define CLOSE_RANGE_CLOEXEC (1U << 2) | ||
| 186 | #endif | ||
| 187 | |||
| 184 | static int userspace_tramp(void *stack) | 188 | static int userspace_tramp(void *stack) |
| 185 | { | 189 | { |
| 186 | char *const argv[] = { "uml-userspace", NULL }; | 190 | char *const argv[] = { "uml-userspace", NULL }; |
| @@ -202,8 +206,12 @@ static int userspace_tramp(void *stack) · 15 unmodified lines | |||
| 202 | init_data.stub_data_fd = phys_mapping(uml_to_phys(stack), &offset); | 206 | init_data.stub_data_fd = phys_mapping(uml_to_phys(stack), &offset); |
| 203 | init_data.stub_data_offset = MMAP_OFFSET(offset); | 207 | init_data.stub_data_offset = MMAP_OFFSET(offset); |
| 204 | 208 | ||
| 205 | /* Set CLOEXEC on all FDs and then unset on all memory related FDs */ | 209 | /* |
| 206 | close_range(0, ~0U, CLOSE_RANGE_CLOEXEC); | 210 | * Avoid leaking unneeded FDs to the stub by setting CLOEXEC on all FDs |
| 211 | * and then unsetting it on all memory related FDs. | ||
| 212 | * This is not strictly necessary from a safety perspective. | ||
| 213 | */ | ||
| 214 | syscall(__NR_close_range, 0, ~0U, CLOSE_RANGE_CLOEXEC); | ||
| 207 | 215 | ||
| 208 | fcntl(init_data.stub_data_fd, F_SETFD, 0); | 216 | fcntl(init_data.stub_data_fd, F_SETFD, 0); |
| 209 | for (iomem = iomem_regions; iomem; iomem = iomem->next) | 217 | for (iomem = iomem_regions; iomem; iomem = iomem->next) |
| @@ -224,7 +232,9 @@ static int userspace_tramp(void *stack) · 14 unmodified lines | |||
| 224 | if (ret != sizeof(init_data)) | 232 | if (ret != sizeof(init_data)) |
| 225 | exit(4); | 233 | exit(4); |
| 226 | 234 | ||
| 227 | execveat(stub_exe_fd, "", argv, NULL, AT_EMPTY_PATH); | 235 | /* Raw execveat for compatibility with older libc versions */ |
| 236 | syscall(__NR_execveat, stub_exe_fd, (unsigned long)"", | ||
| 237 | (unsigned long)argv, NULL, AT_EMPTY_PATH); | ||
| 228 | 238 | ||
| 229 | exit(5); | 239 | exit(5); |
| 230 | } | 240 | } |
| @@ -2599,7 +2599,8 @@ config MITIGATION_IBPB_ENTRY · 2598 unmodified lines | |||
| 2599 | depends on CPU_SUP_AMD && X86_64 | 2599 | depends on CPU_SUP_AMD && X86_64 |
| 2600 | default y | 2600 | default y |
| 2601 | help | 2601 | help |
| 2602 | Compile the kernel with support for the retbleed=ibpb mitigation. | 2602 | Compile the kernel with support for the retbleed=ibpb and |
| 2603 | spec_rstack_overflow={ibpb,ibpb-vmexit} mitigations. | ||
| 2603 | 2604 | ||
| 2604 | config MITIGATION_IBRS_ENTRY | 2605 | config MITIGATION_IBRS_ENTRY |
| 2605 | bool "Enable IBRS on kernel entry" | 2606 | bool "Enable IBRS on kernel entry" |
| @@ -25,6 +25,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \ · 24 unmodified lines | |||
| 25 | # avoid errors with '-march=i386', and future flags may depend on the target to | 25 | # avoid errors with '-march=i386', and future flags may depend on the target to |
| 26 | # be valid. | 26 | # be valid. |
| 27 | KBUILD_CFLAGS := -m$(BITS) -O2 $(CLANG_FLAGS) | 27 | KBUILD_CFLAGS := -m$(BITS) -O2 $(CLANG_FLAGS) |
| 28 | KBUILD_CFLAGS += -std=gnu11 | ||
| 28 | KBUILD_CFLAGS += -fno-strict-aliasing -fPIE | 29 | KBUILD_CFLAGS += -fno-strict-aliasing -fPIE |
| 29 | KBUILD_CFLAGS += -Wundef | 30 | KBUILD_CFLAGS += -Wundef |
| 30 | KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING | 31 | KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING |
| @@ -4905,20 +4905,22 @@ static inline bool intel_pmu_broken_perf_cap(void) · 4904 unmodified lines | |||
| 4905 | 4905 | ||
| 4906 | static void update_pmu_cap(struct x86_hybrid_pmu *pmu) | 4906 | static void update_pmu_cap(struct x86_hybrid_pmu *pmu) |
| 4907 | { | 4907 | { |
| 4908 | unsigned int sub_bitmaps, eax, ebx, ecx, edx; | 4908 | unsigned int cntr, fixed_cntr, ecx, edx; |
| 4909 | union cpuid35_eax eax; | ||
| 4910 | union cpuid35_ebx ebx; | ||
| 4909 | 4911 | ||
| 4910 | cpuid(ARCH_PERFMON_EXT_LEAF, &sub_bitmaps, &ebx, &ecx, &edx); | 4912 | cpuid(ARCH_PERFMON_EXT_LEAF, &eax.full, &ebx.full, &ecx, &edx); |
| 4911 | 4913 | ||
| 4912 | if (ebx & ARCH_PERFMON_EXT_UMASK2) | 4914 | if (ebx.split.umask2) |
| 4913 | pmu->config_mask |= ARCH_PERFMON_EVENTSEL_UMASK2; | 4915 | pmu->config_mask |= ARCH_PERFMON_EVENTSEL_UMASK2; |
| 4914 | if (ebx & ARCH_PERFMON_EXT_EQ) | 4916 | if (ebx.split.eq) |
| 4915 | pmu->config_mask |= ARCH_PERFMON_EVENTSEL_EQ; | 4917 | pmu->config_mask |= ARCH_PERFMON_EVENTSEL_EQ; |
| 4916 | 4918 | ||
| 4917 | if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT) { | 4919 | if (eax.split.cntr_subleaf) { |
| 4918 | cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF, | 4920 | cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF, |
| 4919 | &eax, &ebx, &ecx, &edx); | 4921 | &cntr, &fixed_cntr, &ecx, &edx); |
| 4920 | pmu->cntr_mask64 = eax; | 4922 | pmu->cntr_mask64 = cntr; |
| 4921 | pmu->fixed_cntr_mask64 = ebx; | 4923 | pmu->fixed_cntr_mask64 = fixed_cntr; |
| 4922 | } | 4924 | } |
| 4923 | 4925 | ||
| 4924 | if (!intel_pmu_broken_perf_cap()) { | 4926 | if (!intel_pmu_broken_perf_cap()) { |
| @@ -4941,11 +4943,6 @@ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu) · 16 unmodified lines | |||
| 4941 | else | 4943 | else |
| 4942 | pmu->intel_ctrl &= ~(1ULL << GLOBAL_CTRL_EN_PERF_METRICS); | 4944 | pmu->intel_ctrl &= ~(1ULL << GLOBAL_CTRL_EN_PERF_METRICS); |
| 4943 | 4945 | ||
| 4944 | if (pmu->intel_cap.pebs_output_pt_available) | ||
| 4945 | pmu->pmu.capabilities |= PERF_PMU_CAP_AUX_OUTPUT; | ||
| 4946 | else | ||
| 4947 | pmu->pmu.capabilities &= ~PERF_PMU_CAP_AUX_OUTPUT; | ||
| 4948 | |||
| 4949 | intel_pmu_check_event_constraints(pmu->event_constraints, | 4946 | intel_pmu_check_event_constraints(pmu->event_constraints, |
| 4950 | pmu->cntr_mask64, | 4947 | pmu->cntr_mask64, |
| 4951 | pmu->fixed_cntr_mask64, | 4948 | pmu->fixed_cntr_mask64, |
| @@ -5023,9 +5020,6 @@ static bool init_hybrid_pmu(int cpu) · 71 unmodified lines | |||
| 5023 | 5020 | ||
| 5024 | pr_info("%s PMU driver: ", pmu->name); | 5021 | pr_info("%s PMU driver: ", pmu->name); |
| 5025 | 5022 | ||
| 5026 | if (pmu->intel_cap.pebs_output_pt_available) | ||
| 5027 | pr_cont("PEBS-via-PT "); | ||
| 5028 | |||
| 5029 | pr_cont("\n"); | 5023 | pr_cont("\n"); |
| 5030 | 5024 | ||
| 5031 | x86_pmu_show_pmu_cap(&pmu->pmu); | 5025 | x86_pmu_show_pmu_cap(&pmu->pmu); |
| @@ -5048,8 +5042,11 @@ static void intel_pmu_cpu_starting(int cpu) · 16 unmodified lines | |||
| 5048 | 5042 | ||
| 5049 | init_debug_store_on_cpu(cpu); | 5043 | init_debug_store_on_cpu(cpu); |
| 5050 | /* | 5044 | /* |
| 5051 | * Deal with CPUs that don't clear their LBRs on power-up. | 5045 | * Deal with CPUs that don't clear their LBRs on power-up, and that may |
| 5046 | * even boot with LBRs enabled. | ||
| 5052 | */ | 5047 | */ |
| 5048 | if (!static_cpu_has(X86_FEATURE_ARCH_LBR) && x86_pmu.lbr_nr) | ||
| 5049 | msr_clear_bit(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_LBR_BIT); | ||
| 5053 | intel_pmu_lbr_reset(); | 5050 | intel_pmu_lbr_reset(); |
| 5054 | 5051 | ||
| 5055 | cpuc->lbr_sel = NULL; | 5052 | cpuc->lbr_sel = NULL; |
| @@ -6370,11 +6367,9 @@ static __always_inline int intel_pmu_init_hybrid(enum hybrid_pmu_type pmus) · 1314 unmodified lines | |||
| 6370 | pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities; | 6367 | pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities; |
| 6371 | if (pmu->pmu_type & hybrid_small_tiny) { | 6368 | if (pmu->pmu_type & hybrid_small_tiny) { |
| 6372 | pmu->intel_cap.perf_metrics = 0; | 6369 | pmu->intel_cap.perf_metrics = 0; |
| 6373 | pmu->intel_cap.pebs_output_pt_available = 1; | ||
| 6374 | pmu->mid_ack = true; | 6370 | pmu->mid_ack = true; |
| 6375 | } else if (pmu->pmu_type & hybrid_big) { | 6371 | } else if (pmu->pmu_type & hybrid_big) { |
| 6376 | pmu->intel_cap.perf_metrics = 1; | 6372 | pmu->intel_cap.perf_metrics = 1; |
| 6377 | pmu->intel_cap.pebs_output_pt_available = 0; | ||
| 6378 | pmu->late_ack = true; | 6373 | pmu->late_ack = true; |
| 6379 | } | 6374 | } |
| 6380 | } | 6375 | } |
| @@ -2578,7 +2578,15 @@ void __init intel_ds_init(void) · 2577 unmodified lines | |||
| 2578 | } | 2578 | } |
| 2579 | pr_cont("PEBS fmt4%c%s, ", pebs_type, pebs_qual); | 2579 | pr_cont("PEBS fmt4%c%s, ", pebs_type, pebs_qual); |
| 2580 | 2580 | ||
| 2581 | if (!is_hybrid() && x86_pmu.intel_cap.pebs_output_pt_available) { | 2581 | /* |
| 2582 | * The PEBS-via-PT is not supported on hybrid platforms, | ||
| 2583 | * because not all CPUs of a hybrid machine support it. | ||
| 2584 | * The global x86_pmu.intel_cap, which only contains the | ||
| 2585 | * common capabilities, is used to check the availability | ||
| 2586 | * of the feature. The per-PMU pebs_output_pt_available | ||
| 2587 | * in a hybrid machine should be ignored. | ||
| 2588 | */ | ||
| 2589 | if (x86_pmu.intel_cap.pebs_output_pt_available) { | ||
| 2582 | pr_cont("PEBS-via-PT, "); | 2590 | pr_cont("PEBS-via-PT, "); |
| 2583 | x86_get_pmu(smp_processor_id())->capabilities |= PERF_PMU_CAP_AUX_OUTPUT; | 2591 | x86_get_pmu(smp_processor_id())->capabilities |= PERF_PMU_CAP_AUX_OUTPUT; |
| 2584 | } | 2592 | } |
| @@ -370,6 +370,10 @@ static int rapl_pmu_event_init(struct perf_event *event) · 369 unmodified lines | |||
| 370 | unsigned int rapl_pmu_idx; | 370 | unsigned int rapl_pmu_idx; |
| 371 | struct rapl_pmus *rapl_pmus; | 371 | struct rapl_pmus *rapl_pmus; |
| 372 | 372 | ||
| 373 | /* only look at RAPL events */ | ||
| 374 | if (event->attr.type != event->pmu->type) | ||
| 375 | return -ENOENT; | ||
| 376 | |||
| 373 | /* unsupported modes and filters */ | 377 | /* unsupported modes and filters */ |
| 374 | if (event->attr.sample_period) /* no sampling */ | 378 | if (event->attr.sample_period) /* no sampling */ |
| 375 | return -EINVAL; | 379 | return -EINVAL; |
| @@ -387,10 +391,6 @@ static int rapl_pmu_event_init(struct perf_event *event) · 11 unmodified lines | |||
| 387 | rapl_pmus_scope = rapl_pmus->pmu.scope; | 391 | rapl_pmus_scope = rapl_pmus->pmu.scope; |
| 388 | 392 | ||
| 389 | if (rapl_pmus_scope == PERF_PMU_SCOPE_PKG || rapl_pmus_scope == PERF_PMU_SCOPE_DIE) { | 393 | if (rapl_pmus_scope == PERF_PMU_SCOPE_PKG || rapl_pmus_scope == PERF_PMU_SCOPE_DIE) { |
| 390 | /* only look at RAPL package events */ | ||
| 391 | if (event->attr.type != rapl_pmus_pkg->pmu.type) | ||
| 392 | return -ENOENT; | ||
| 393 | |||
| 394 | cfg = array_index_nospec((long)cfg, NR_RAPL_PKG_DOMAINS + 1); | 394 | cfg = array_index_nospec((long)cfg, NR_RAPL_PKG_DOMAINS + 1); |
| 395 | if (!cfg || cfg >= NR_RAPL_PKG_DOMAINS + 1) | 395 | if (!cfg || cfg >= NR_RAPL_PKG_DOMAINS + 1) |
| 396 | return -EINVAL; | 396 | return -EINVAL; |
| @@ -398,10 +398,6 @@ static int rapl_pmu_event_init(struct perf_event *event) · 1 unmodified line | |||
| 398 | bit = cfg - 1; | 398 | bit = cfg - 1; |
| 399 | event->hw.event_base = rapl_model->rapl_pkg_msrs[bit].msr; | 399 | event->hw.event_base = rapl_model->rapl_pkg_msrs[bit].msr; |
| 400 | } else if (rapl_pmus_scope == PERF_PMU_SCOPE_CORE) { | 400 | } else if (rapl_pmus_scope == PERF_PMU_SCOPE_CORE) { |
| 401 | /* only look at RAPL core events */ | ||
| 402 | if (event->attr.type != rapl_pmus_core->pmu.type) | ||
| 403 | return -ENOENT; | ||
| 404 | |||
| 405 | cfg = array_index_nospec((long)cfg, NR_RAPL_CORE_DOMAINS + 1); | 401 | cfg = array_index_nospec((long)cfg, NR_RAPL_CORE_DOMAINS + 1); |
| 406 | if (!cfg || cfg >= NR_RAPL_PKG_DOMAINS + 1) | 402 | if (!cfg || cfg >= NR_RAPL_PKG_DOMAINS + 1) |
| 407 | return -EINVAL; | 403 | return -EINVAL; |
| @@ -48,6 +48,7 @@ KVM_X86_OP(set_idt) · 47 unmodified lines | |||
| 48 | KVM_X86_OP(get_gdt) | 48 | KVM_X86_OP(get_gdt) |
| 49 | KVM_X86_OP(set_gdt) | 49 | KVM_X86_OP(set_gdt) |
| 50 | KVM_X86_OP(sync_dirty_debug_regs) | 50 | KVM_X86_OP(sync_dirty_debug_regs) |
| 51 | KVM_X86_OP(set_dr6) | ||
| 51 | KVM_X86_OP(set_dr7) | 52 | KVM_X86_OP(set_dr7) |
| 52 | KVM_X86_OP(cache_reg) | 53 | KVM_X86_OP(cache_reg) |
| 53 | KVM_X86_OP(get_rflags) | 54 | KVM_X86_OP(get_rflags) |
| @@ -1696,6 +1696,7 @@ struct kvm_x86_ops { · 1695 unmodified lines | |||
| 1696 | void (*get_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); | 1696 | void (*get_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); |
| 1697 | void (*set_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); | 1697 | void (*set_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); |
| 1698 | void (*sync_dirty_debug_regs)(struct kvm_vcpu *vcpu); | 1698 | void (*sync_dirty_debug_regs)(struct kvm_vcpu *vcpu); |
| 1699 | void (*set_dr6)(struct kvm_vcpu *vcpu, unsigned long value); | ||
| 1699 | void (*set_dr7)(struct kvm_vcpu *vcpu, unsigned long value); | 1700 | void (*set_dr7)(struct kvm_vcpu *vcpu, unsigned long value); |
| 1700 | void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); | 1701 | void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); |
| 1701 | unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); | 1702 | unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); |
| @@ -395,7 +395,8 @@ · 394 unmodified lines | |||
| 395 | #define MSR_IA32_PASID_VALID BIT_ULL(31) | 395 | #define MSR_IA32_PASID_VALID BIT_ULL(31) |
| 396 | 396 | ||
| 397 | /* DEBUGCTLMSR bits (others vary by model): */ | 397 | /* DEBUGCTLMSR bits (others vary by model): */ |
| 398 | #define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */ | 398 | #define DEBUGCTLMSR_LBR_BIT 0 /* last branch recording */ |
| 399 | #define DEBUGCTLMSR_LBR (1UL << DEBUGCTLMSR_LBR_BIT) | ||
| 399 | #define DEBUGCTLMSR_BTF_SHIFT 1 | 400 | #define DEBUGCTLMSR_BTF_SHIFT 1 |
| 400 | #define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */ | 401 | #define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */ |
| 401 | #define DEBUGCTLMSR_BUS_LOCK_DETECT (1UL << 2) | 402 | #define DEBUGCTLMSR_BUS_LOCK_DETECT (1UL << 2) |
| @@ -188,11 +188,33 @@ union cpuid10_edx { · 187 unmodified lines | |||
| 188 | * detection/enumeration details: | 188 | * detection/enumeration details: |
| 189 | */ | 189 | */ |
| 190 | #define ARCH_PERFMON_EXT_LEAF 0x00000023 | 190 | #define ARCH_PERFMON_EXT_LEAF 0x00000023 |
| 191 | #define ARCH_PERFMON_EXT_UMASK2 0x1 | ||
| 192 | #define ARCH_PERFMON_EXT_EQ 0x2 | ||
| 193 | #define ARCH_PERFMON_NUM_COUNTER_LEAF_BIT 0x1 | ||
| 194 | #define ARCH_PERFMON_NUM_COUNTER_LEAF 0x1 | 191 | #define ARCH_PERFMON_NUM_COUNTER_LEAF 0x1 |
| 195 | 192 | ||
| 193 | union cpuid35_eax { | ||
| 194 | struct { | ||
| 195 | unsigned int leaf0:1; | ||
| 196 | /* Counters Sub-Leaf */ | ||
| 197 | unsigned int cntr_subleaf:1; | ||
| 198 | /* Auto Counter Reload Sub-Leaf */ | ||
| 199 | unsigned int acr_subleaf:1; | ||
| 200 | /* Events Sub-Leaf */ | ||
| 201 | unsigned int events_subleaf:1; | ||
| 202 | unsigned int reserved:28; | ||
| 203 | } split; | ||
| 204 | unsigned int full; | ||
| 205 | }; | ||
| 206 | |||
| 207 | union cpuid35_ebx { | ||
| 208 | struct { | ||
| 209 | /* UnitMask2 Supported */ | ||
| 210 | unsigned int umask2:1; | ||
| 211 | /* EQ-bit Supported */ | ||
| 212 | unsigned int eq:1; | ||
| 213 | unsigned int reserved:30; | ||
| 214 | } split; | ||
| 215 | unsigned int full; | ||
| 216 | }; | ||
| 217 | |||
| 196 | /* | 218 | /* |
| 197 | * Intel Architectural LBR CPUID detection/enumeration details: | 219 | * Intel Architectural LBR CPUID detection/enumeration details: |
| 198 | */ | 220 | */ |
| @@ -531,6 +531,7 @@ static inline void __init snp_secure_tsc_init(void) { } · 530 unmodified lines | |||
| 531 | 531 | ||
| 532 | #ifdef CONFIG_KVM_AMD_SEV | 532 | #ifdef CONFIG_KVM_AMD_SEV |
| 533 | bool snp_probe_rmptable_info(void); | 533 | bool snp_probe_rmptable_info(void); |
| 534 | int snp_rmptable_init(void); | ||
| 534 | int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level); | 535 | int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level); |
| 535 | void snp_dump_hva_rmpentry(unsigned long address); | 536 | void snp_dump_hva_rmpentry(unsigned long address); |
| 536 | int psmash(u64 pfn); | 537 | int psmash(u64 pfn); |
| @@ -541,6 +542,7 @@ void kdump_sev_callback(void); · 4 unmodified lines | |||
| 541 | void snp_fixup_e820_tables(void); | 542 | void snp_fixup_e820_tables(void); |
| 542 | #else | 543 | #else |
| 543 | static inline bool snp_probe_rmptable_info(void) { return false; } | 544 | static inline bool snp_probe_rmptable_info(void) { return false; } |
| 545 | static inline int snp_rmptable_init(void) { return -ENOSYS; } | ||
| 544 | static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; } | 546 | static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; } |
| 545 | static inline void snp_dump_hva_rmpentry(unsigned long address) {} | 547 | static inline void snp_dump_hva_rmpentry(unsigned long address) {} |
| 546 | static inline int psmash(u64 pfn) { return -ENODEV; } | 548 | static inline int psmash(u64 pfn) { return -ENODEV; } |
| @@ -1115,6 +1115,8 @@ do_cmd_auto: · 1114 unmodified lines | |||
| 1115 | 1115 | ||
| 1116 | case RETBLEED_MITIGATION_IBPB: | 1116 | case RETBLEED_MITIGATION_IBPB: |
| 1117 | setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); | 1117 | setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); |
| 1118 | setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); | ||
| 1119 | mitigate_smt = true; | ||
| 1118 | 1120 | ||
| 1119 | /* | 1121 | /* |
| 1120 | * IBPB on entry already obviates the need for | 1122 | * IBPB on entry already obviates the need for |
| @@ -1124,9 +1126,6 @@ do_cmd_auto: · 3 unmodified lines | |||
| 1124 | setup_clear_cpu_cap(X86_FEATURE_UNRET); | 1126 | setup_clear_cpu_cap(X86_FEATURE_UNRET); |
| 1125 | setup_clear_cpu_cap(X86_FEATURE_RETHUNK); | 1127 | setup_clear_cpu_cap(X86_FEATURE_RETHUNK); |
| 1126 | 1128 | ||
| 1127 | setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); | ||
| 1128 | mitigate_smt = true; | ||
| 1129 | |||
| 1130 | /* | 1129 | /* |
| 1131 | * There is no need for RSB filling: entry_ibpb() ensures | 1130 | * There is no need for RSB filling: entry_ibpb() ensures |
| 1132 | * all predictions, including the RSB, are invalidated, | 1131 | * all predictions, including the RSB, are invalidated, |
| @@ -2646,6 +2645,7 @@ static void __init srso_select_mitigation(void) · 1513 unmodified lines | |||
| 2646 | if (IS_ENABLED(CONFIG_MITIGATION_IBPB_ENTRY)) { | 2645 | if (IS_ENABLED(CONFIG_MITIGATION_IBPB_ENTRY)) { |
| 2647 | if (has_microcode) { | 2646 | if (has_microcode) { |
| 2648 | setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); | 2647 | setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); |
| 2648 | setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); | ||
| 2649 | srso_mitigation = SRSO_MITIGATION_IBPB; | 2649 | srso_mitigation = SRSO_MITIGATION_IBPB; |
| 2650 | 2650 | ||
| 2651 | /* | 2651 | /* |
| @@ -2655,6 +2655,13 @@ static void __init srso_select_mitigation(void) · 3 unmodified lines | |||
| 2655 | */ | 2655 | */ |
| 2656 | setup_clear_cpu_cap(X86_FEATURE_UNRET); | 2656 | setup_clear_cpu_cap(X86_FEATURE_UNRET); |
| 2657 | setup_clear_cpu_cap(X86_FEATURE_RETHUNK); | 2657 | setup_clear_cpu_cap(X86_FEATURE_RETHUNK); |
| 2658 | |||
| 2659 | /* | ||
| 2660 | * There is no need for RSB filling: entry_ibpb() ensures | ||
| 2661 | * all predictions, including the RSB, are invalidated, | ||
| 2662 | * regardless of IBPB implementation. | ||
| 2663 | */ | ||
| 2664 | setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT); | ||
| 2658 | } | 2665 | } |
| 2659 | } else { | 2666 | } else { |
| 2660 | pr_err("WARNING: kernel not compiled with MITIGATION_IBPB_ENTRY.\n"); | 2667 | pr_err("WARNING: kernel not compiled with MITIGATION_IBPB_ENTRY.\n"); |
| @@ -2663,8 +2670,8 @@ static void __init srso_select_mitigation(void) · 2 unmodified lines | |||
| 2663 | 2670 | ||
| 2664 | ibpb_on_vmexit: | 2671 | ibpb_on_vmexit: |
| 2665 | case SRSO_CMD_IBPB_ON_VMEXIT: | 2672 | case SRSO_CMD_IBPB_ON_VMEXIT: |
| 2666 | if (IS_ENABLED(CONFIG_MITIGATION_SRSO)) { | 2673 | if (IS_ENABLED(CONFIG_MITIGATION_IBPB_ENTRY)) { |
| 2667 | if (!boot_cpu_has(X86_FEATURE_ENTRY_IBPB) && has_microcode) { | 2674 | if (has_microcode) { |
| 2668 | setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); | 2675 | setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); |
| 2669 | srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT; | 2676 | srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT; |
| 2670 | 2677 | ||
| @@ -2676,8 +2683,8 @@ ibpb_on_vmexit: · 5 unmodified lines | |||
| 2676 | setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT); | 2683 | setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT); |
| 2677 | } | 2684 | } |
| 2678 | } else { | 2685 | } else { |
| 2679 | pr_err("WARNING: kernel not compiled with MITIGATION_SRSO.\n"); | 2686 | pr_err("WARNING: kernel not compiled with MITIGATION_IBPB_ENTRY.\n"); |
| 2680 | } | 2687 | } |
| 2681 | break; | 2688 | break; |
| 2682 | default: | 2689 | default: |
| 2683 | break; | 2690 | break; |
| @@ -1180,7 +1180,7 @@ void kvm_set_cpu_caps(void) · 1179 unmodified lines | |||
| 1180 | SYNTHESIZED_F(SBPB), | 1180 | SYNTHESIZED_F(SBPB), |
| 1181 | SYNTHESIZED_F(IBPB_BRTYPE), | 1181 | SYNTHESIZED_F(IBPB_BRTYPE), |
| 1182 | SYNTHESIZED_F(SRSO_NO), | 1182 | SYNTHESIZED_F(SRSO_NO), |
| 1183 | SYNTHESIZED_F(SRSO_USER_KERNEL_NO), | 1183 | F(SRSO_USER_KERNEL_NO), |
| 1184 | ); | 1184 | ); |
| 1185 | 1185 | ||
| 1186 | kvm_cpu_cap_init(CPUID_8000_0022_EAX, | 1186 | kvm_cpu_cap_init(CPUID_8000_0022_EAX, |
| @@ -2226,6 +2226,9 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc) · 2225 unmodified lines | |||
| 2226 | u32 vector; | 2226 | u32 vector; |
| 2227 | bool all_cpus; | 2227 | bool all_cpus; |
| 2228 | 2228 | ||
| 2229 | if (!lapic_in_kernel(vcpu)) | ||
| 2230 | return HV_STATUS_INVALID_HYPERCALL_INPUT; | ||
| 2231 | |||
| 2229 | if (hc->code == HVCALL_SEND_IPI) { | 2232 | if (hc->code == HVCALL_SEND_IPI) { |
| 2230 | if (!hc->fast) { | 2233 | if (!hc->fast) { |
| 2231 | if (unlikely(kvm_read_guest(kvm, hc->ingpa, &send_ipi, | 2234 | if (unlikely(kvm_read_guest(kvm, hc->ingpa, &send_ipi, |
| @@ -2852,7 +2855,8 @@ int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid, · 620 unmodified lines | |||
| 2852 | ent->eax |= HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED; | 2855 | ent->eax |= HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED; |
| 2853 | ent->eax |= HV_X64_APIC_ACCESS_RECOMMENDED; | 2856 | ent->eax |= HV_X64_APIC_ACCESS_RECOMMENDED; |
| 2854 | ent->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED; | 2857 | ent->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED; |
| 2855 | ent->eax |= HV_X64_CLUSTER_IPI_RECOMMENDED; | 2858 | if (!vcpu || lapic_in_kernel(vcpu)) |
| 2859 | ent->eax |= HV_X64_CLUSTER_IPI_RECOMMENDED; | ||
| 2856 | ent->eax |= HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED; | 2860 | ent->eax |= HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED; |
| 2857 | if (evmcs_ver) | 2861 | if (evmcs_ver) |
| 2858 | ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED; | 2862 | ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED; |
| @@ -5540,7 +5540,7 @@ void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0, · 5539 unmodified lines | |||
| 5540 | union kvm_mmu_page_role root_role; | 5540 | union kvm_mmu_page_role root_role; |
| 5541 | 5541 | ||
| 5542 | /* NPT requires CR0.PG=1. */ | 5542 | /* NPT requires CR0.PG=1. */ |
| 5543 | WARN_ON_ONCE(cpu_role.base.direct); | 5543 | WARN_ON_ONCE(cpu_role.base.direct || !cpu_role.base.guest_mode); |
| 5544 | 5544 | ||
| 5545 | root_role = cpu_role.base; | 5545 | root_role = cpu_role.base; |
| 5546 | root_role.level = kvm_mmu_get_tdp_level(vcpu); | 5546 | root_role.level = kvm_mmu_get_tdp_level(vcpu); |
| @@ -7120,6 +7120,19 @@ static void mmu_destroy_caches(void) · 1573 unmodified lines | |||
| 7120 | kmem_cache_destroy(mmu_page_header_cache); | 7120 | kmem_cache_destroy(mmu_page_header_cache); |
| 7121 | } | 7121 | } |
| 7122 | 7122 | ||
| 7123 | static void kvm_wake_nx_recovery_thread(struct kvm *kvm) | ||
| 7124 | { | ||
| 7125 | /* | ||
| 7126 | * The NX recovery thread is spawned on-demand at the first KVM_RUN and | ||
| 7127 | * may not be valid even though the VM is globally visible. Do nothing, | ||
| 7128 | * as such a VM can't have any possible NX huge pages. | ||
| 7129 | */ | ||
| 7130 | struct vhost_task *nx_thread = READ_ONCE(kvm->arch.nx_huge_page_recovery_thread); | ||
| 7131 | |||
| 7132 | if (nx_thread) | ||
| 7133 | vhost_task_wake(nx_thread); | ||
| 7134 | } | ||
| 7135 | |||
| 7123 | static int get_nx_huge_pages(char *buffer, const struct kernel_param *kp) | 7136 | static int get_nx_huge_pages(char *buffer, const struct kernel_param *kp) |
| 7124 | { | 7137 | { |
| 7125 | if (nx_hugepage_mitigation_hard_disabled) | 7138 | if (nx_hugepage_mitigation_hard_disabled) |
| @@ -7180,7 +7193,7 @@ static int set_nx_huge_pages(const char *val, const struct kernel_param *kp) · 54 unmodified lines | |||
| 7180 | kvm_mmu_zap_all_fast(kvm); | 7193 | kvm_mmu_zap_all_fast(kvm); |
| 7181 | mutex_unlock(&kvm->slots_lock); | 7194 | mutex_unlock(&kvm->slots_lock); |
| 7182 | 7195 | ||
| 7183 | vhost_task_wake(kvm->arch.nx_huge_page_recovery_thread); | 7196 | kvm_wake_nx_recovery_thread(kvm); |
| 7184 | } | 7197 | } |
| 7185 | mutex_unlock(&kvm_lock); | 7198 | mutex_unlock(&kvm_lock); |
| 7186 | } | 7199 | } |
| @@ -7315,7 +7328,7 @@ static int set_nx_huge_pages_recovery_param(const char *val, const struct kernel · 128 unmodified lines | |||
| 7315 | mutex_lock(&kvm_lock); | 7328 | mutex_lock(&kvm_lock); |
| 7316 | 7329 | ||
| 7317 | list_for_each_entry(kvm, &vm_list, vm_list) | 7330 | list_for_each_entry(kvm, &vm_list, vm_list) |
| 7318 | vhost_task_wake(kvm->arch.nx_huge_page_recovery_thread); | 7331 | kvm_wake_nx_recovery_thread(kvm); |
| 7319 | 7332 | ||
| 7320 | mutex_unlock(&kvm_lock); | 7333 | mutex_unlock(&kvm_lock); |
| 7321 | } | 7334 | } |
| @@ -7451,14 +7464,20 @@ static void kvm_mmu_start_lpage_recovery(struct once *once) · 129 unmodified lines | |||
| 7451 | { | 7464 | { |
| 7452 | struct kvm_arch *ka = container_of(once, struct kvm_arch, nx_once); | 7465 | struct kvm_arch *ka = container_of(once, struct kvm_arch, nx_once); |
| 7453 | struct kvm *kvm = container_of(ka, struct kvm, arch); | 7466 | struct kvm *kvm = container_of(ka, struct kvm, arch); |
| 7467 | struct vhost_task *nx_thread; | ||
| 7454 | 7468 | ||
| 7455 | kvm->arch.nx_huge_page_last = get_jiffies_64(); | 7469 | kvm->arch.nx_huge_page_last = get_jiffies_64(); |
| 7456 | kvm->arch.nx_huge_page_recovery_thread = vhost_task_create( | 7470 | nx_thread = vhost_task_create(kvm_nx_huge_page_recovery_worker, |
| 7457 | kvm_nx_huge_page_recovery_worker, kvm_nx_huge_page_recovery_worker_kill, | 7471 | kvm_nx_huge_page_recovery_worker_kill, |
| 7458 | kvm, "kvm-nx-lpage-recovery"); | 7472 | kvm, "kvm-nx-lpage-recovery"); |
| 7459 | 7473 | ||
| 7460 | if (kvm->arch.nx_huge_page_recovery_thread) | 7474 | if (!nx_thread) |
| 7461 | vhost_task_start(kvm->arch.nx_huge_page_recovery_thread); | 7475 | return; |
| 7476 | |||
| 7477 | vhost_task_start(nx_thread); | ||
| 7478 | |||
| 7479 | /* Make the task visible only once it is fully started. */ | ||
| 7480 | WRITE_ONCE(kvm->arch.nx_huge_page_recovery_thread, nx_thread); | ||
| 7462 | } | 7481 | } |
| 7463 | 7482 | ||
| 7464 | int kvm_mmu_post_init_vm(struct kvm *kvm) | 7483 | int kvm_mmu_post_init_vm(struct kvm *kvm) |
| @@ -646,6 +646,11 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm, · 645 unmodified lines | |||
| 646 | u32 pause_count12; | 646 | u32 pause_count12; |
| 647 | u32 pause_thresh12; | 647 | u32 pause_thresh12; |
| 648 | 648 | ||
| 649 | nested_svm_transition_tlb_flush(vcpu); | ||
| 650 | |||
| 651 | /* Enter Guest-Mode */ | ||
| 652 | enter_guest_mode(vcpu); | ||
| 653 | |||
| 649 | /* | 654 | /* |
| 650 | * Filled at exit: exit_code, exit_code_hi, exit_info_1, exit_info_2, | 655 | * Filled at exit: exit_code, exit_code_hi, exit_info_1, exit_info_2, |
| 651 | * exit_int_info, exit_int_info_err, next_rip, insn_len, insn_bytes. | 656 | * exit_int_info, exit_int_info_err, next_rip, insn_len, insn_bytes. |
| @@ -762,11 +767,6 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm, · 110 unmodified lines | |||
| 762 | } | 767 | } |
| 763 | } | 768 | } |
| 764 | 769 | ||
| 765 | nested_svm_transition_tlb_flush(vcpu); | ||
| 766 | |||
| 767 | /* Enter Guest-Mode */ | ||
| 768 | enter_guest_mode(vcpu); | ||
| 769 | |||
| 770 | /* | 770 | /* |
| 771 | * Merge guest and host intercepts - must be called with vcpu in | 771 | * Merge guest and host intercepts - must be called with vcpu in |
| 772 | * guest-mode to take effect. | 772 | * guest-mode to take effect. |
| @@ -2972,6 +2972,16 @@ void __init sev_hardware_setup(void) · 2971 unmodified lines | |||
| 2972 | WARN_ON_ONCE(!boot_cpu_has(X86_FEATURE_FLUSHBYASID))) | 2972 | WARN_ON_ONCE(!boot_cpu_has(X86_FEATURE_FLUSHBYASID))) |
| 2973 | goto out; | 2973 | goto out; |
| 2974 | 2974 | ||
| 2975 | /* | ||
| 2976 | * The kernel's initcall infrastructure lacks the ability to express | ||
| 2977 | * dependencies between initcalls, whereas the modules infrastructure | ||
| 2978 | * automatically handles dependencies via symbol loading. Ensure the | ||
| 2979 | * PSP SEV driver is initialized before proceeding if KVM is built-in, | ||
| 2980 | * as the dependency isn't handled by the initcall infrastructure. | ||
| 2981 | */ | ||
| 2982 | if (IS_BUILTIN(CONFIG_KVM_AMD) && sev_module_init()) | ||
| 2983 | goto out; | ||
| 2984 | |||
| 2975 | /* Retrieve SEV CPUID information */ | 2985 | /* Retrieve SEV CPUID information */ |
| 2976 | cpuid(0x8000001f, &eax, &ebx, &ecx, &edx); | 2986 | cpuid(0x8000001f, &eax, &ebx, &ecx, &edx); |
| 2977 | 2987 | ||
| @@ -1991,11 +1991,11 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) · 1990 unmodified lines | |||
| 1991 | svm->asid = sd->next_asid++; | 1991 | svm->asid = sd->next_asid++; |
| 1992 | } | 1992 | } |
| 1993 | 1993 | ||
| 1994 | static void svm_set_dr6(struct vcpu_svm *svm, unsigned long value) | 1994 | static void svm_set_dr6(struct kvm_vcpu *vcpu, unsigned long value) |
| 1995 | { | 1995 | { |
| 1996 | struct vmcb *vmcb = svm->vmcb; | 1996 | struct vmcb *vmcb = to_svm(vcpu)->vmcb; |
| 1997 | 1997 | ||
| 1998 | if (svm->vcpu.arch.guest_state_protected) | 1998 | if (vcpu->arch.guest_state_protected) |
| 1999 | return; | 1999 | return; |
| 2000 | 2000 | ||
| 2001 | if (unlikely(value != vmcb->save.dr6)) { | 2001 | if (unlikely(value != vmcb->save.dr6)) { |
| @@ -4247,10 +4247,8 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, · 2245 unmodified lines | |||
| 4247 | * Run with all-zero DR6 unless needed, so that we can get the exact cause | 4247 | * Run with all-zero DR6 unless needed, so that we can get the exact cause |
| 4248 | * of a #DB. | 4248 | * of a #DB. |
| 4249 | */ | 4249 | */ |
| 4250 | if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) | 4250 | if (likely(!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))) |
| 4251 | svm_set_dr6(svm, vcpu->arch.dr6); | 4251 | svm_set_dr6(vcpu, DR6_ACTIVE_LOW); |
| 4252 | else | ||
| 4253 | svm_set_dr6(svm, DR6_ACTIVE_LOW); | ||
| 4254 | 4252 | ||
| 4255 | clgi(); | 4253 | clgi(); |
| 4256 | kvm_load_guest_xsave_state(vcpu); | 4254 | kvm_load_guest_xsave_state(vcpu); |
| @@ -5043,6 +5041,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { · 786 unmodified lines | |||
| 5043 | .set_idt = svm_set_idt, | 5041 | .set_idt = svm_set_idt, |
| 5044 | .get_gdt = svm_get_gdt, | 5042 | .get_gdt = svm_get_gdt, |
| 5045 | .set_gdt = svm_set_gdt, | 5043 | .set_gdt = svm_set_gdt, |
| 5044 | .set_dr6 = svm_set_dr6, | ||
| 5046 | .set_dr7 = svm_set_dr7, | 5045 | .set_dr7 = svm_set_dr7, |
| 5047 | .sync_dirty_debug_regs = svm_sync_dirty_debug_regs, | 5046 | .sync_dirty_debug_regs = svm_sync_dirty_debug_regs, |
| 5048 | .cache_reg = svm_cache_reg, | 5047 | .cache_reg = svm_cache_reg, |
| @@ -61,6 +61,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = { · 60 unmodified lines | |||
| 61 | .set_idt = vmx_set_idt, | 61 | .set_idt = vmx_set_idt, |
| 62 | .get_gdt = vmx_get_gdt, | 62 | .get_gdt = vmx_get_gdt, |
| 63 | .set_gdt = vmx_set_gdt, | 63 | .set_gdt = vmx_set_gdt, |
| 64 | .set_dr6 = vmx_set_dr6, | ||
| 64 | .set_dr7 = vmx_set_dr7, | 65 | .set_dr7 = vmx_set_dr7, |
| 65 | .sync_dirty_debug_regs = vmx_sync_dirty_debug_regs, | 66 | .sync_dirty_debug_regs = vmx_sync_dirty_debug_regs, |
| 66 | .cache_reg = vmx_cache_reg, | 67 | .cache_reg = vmx_cache_reg, |
| @@ -5648,6 +5648,12 @@ void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu) · 5647 unmodified lines | |||
| 5648 | set_debugreg(DR6_RESERVED, 6); | 5648 | set_debugreg(DR6_RESERVED, 6); |
| 5649 | } | 5649 | } |
| 5650 | 5650 | ||
| 5651 | void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val) | ||
| 5652 | { | ||
| 5653 | lockdep_assert_irqs_disabled(); | ||
| 5654 | set_debugreg(vcpu->arch.dr6, 6); | ||
| 5655 | } | ||
| 5656 | |||
| 5651 | void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val) | 5657 | void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val) |
| 5652 | { | 5658 | { |
| 5653 | vmcs_writel(GUEST_DR7, val); | 5659 | vmcs_writel(GUEST_DR7, val); |
| @@ -7417,10 +7423,6 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit) · 1763 unmodified lines | |||
| 7417 | vmx->loaded_vmcs->host_state.cr4 = cr4; | 7423 | vmx->loaded_vmcs->host_state.cr4 = cr4; |
| 7418 | } | 7424 | } |
| 7419 | 7425 | ||
| 7420 | /* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */ | ||
| 7421 | if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) | ||
| 7422 | set_debugreg(vcpu->arch.dr6, 6); | ||
| 7423 | |||
| 7424 | /* When single-stepping over STI and MOV SS, we must clear the | 7426 | /* When single-stepping over STI and MOV SS, we must clear the |
| 7425 | * corresponding interruptibility bits in the guest state. Otherwise | 7427 | * corresponding interruptibility bits in the guest state. Otherwise |
| 7426 | * vmentry fails as it then expects bit 14 (BS) in pending debug | 7428 | * vmentry fails as it then expects bit 14 (BS) in pending debug |
| @@ -73,6 +73,7 @@ void vmx_get_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt); · 72 unmodified lines | |||
| 73 | void vmx_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt); | 73 | void vmx_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt); |
| 74 | void vmx_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt); | 74 | void vmx_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt); |
| 75 | void vmx_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt); | 75 | void vmx_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt); |
| 76 | void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val); | ||
| 76 | void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val); | 77 | void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val); |
| 77 | void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu); | 78 | void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu); |
| 78 | void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg); | 79 | void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg); |
| @@ -10961,6 +10961,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 10960 unmodified lines | |||
| 10961 | set_debugreg(vcpu->arch.eff_db[1], 1); | 10961 | set_debugreg(vcpu->arch.eff_db[1], 1); |
| 10962 | set_debugreg(vcpu->arch.eff_db[2], 2); | 10962 | set_debugreg(vcpu->arch.eff_db[2], 2); |
| 10963 | set_debugreg(vcpu->arch.eff_db[3], 3); | 10963 | set_debugreg(vcpu->arch.eff_db[3], 3); |
| 10964 | /* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */ | ||
| 10965 | if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) | ||
| 10966 | kvm_x86_call(set_dr6)(vcpu, vcpu->arch.dr6); | ||
| 10964 | } else if (unlikely(hw_breakpoint_active())) { | 10967 | } else if (unlikely(hw_breakpoint_active())) { |
| 10965 | set_debugreg(0, 7); | 10968 | set_debugreg(0, 7); |
| 10966 | } | 10969 | } |
| @@ -12741,6 +12744,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) · 1774 unmodified lines | |||
| 12741 | "does not run without ignore_msrs=1, please report it to kvm@vger.kernel.org.\n"); | 12744 | "does not run without ignore_msrs=1, please report it to kvm@vger.kernel.org.\n"); |
| 12742 | } | 12745 | } |
| 12743 | 12746 | ||
| 12747 | once_init(&kvm->arch.nx_once); | ||
| 12744 | return 0; | 12748 | return 0; |
| 12745 | 12749 | ||
| 12746 | out_uninit_mmu: | 12750 | out_uninit_mmu: |
| @@ -12750,12 +12754,6 @@ out: · 3 unmodified lines | |||
| 12750 | return ret; | 12754 | return ret; |
| 12751 | } | 12755 | } |
| 12752 | 12756 | ||
| 12753 | int kvm_arch_post_init_vm(struct kvm *kvm) | ||
| 12754 | { | ||
| 12755 | once_init(&kvm->arch.nx_once); | ||
| 12756 | return 0; | ||
| 12757 | } | ||
| 12758 | |||
| 12759 | static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu) | 12757 | static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu) |
| 12760 | { | 12758 | { |
| 12761 | vcpu_load(vcpu); | 12759 | vcpu_load(vcpu); |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <registers.h> | 18 | #include <registers.h> |
| 19 | #include <sys/mman.h> | 19 | #include <sys/mman.h> |
| 20 | 20 | ||
| 21 | static unsigned long ptrace_regset; | ||
| 21 | unsigned long host_fp_size; | 22 | unsigned long host_fp_size; |
| 22 | 23 | ||
| 23 | int get_fp_registers(int pid, unsigned long *regs) | 24 | int get_fp_registers(int pid, unsigned long *regs) |
| @@ -27,7 +28,7 @@ int get_fp_registers(int pid, unsigned long *regs) · 3 unmodified lines | |||
| 27 | .iov_len = host_fp_size, | 28 | .iov_len = host_fp_size, |
| 28 | }; | 29 | }; |
| 29 | 30 | ||
| 30 | if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) | 31 | if (ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov) < 0) |
| 31 | return -errno; | 32 | return -errno; |
| 32 | return 0; | 33 | return 0; |
| 33 | } | 34 | } |
| @@ -39,7 +40,7 @@ int put_fp_registers(int pid, unsigned long *regs) · 5 unmodified lines | |||
| 39 | .iov_len = host_fp_size, | 40 | .iov_len = host_fp_size, |
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) | 43 | if (ptrace(PTRACE_SETREGSET, pid, ptrace_regset, &iov) < 0) |
| 43 | return -errno; | 44 | return -errno; |
| 44 | return 0; | 45 | return 0; |
| 45 | } | 46 | } |
| @@ -58,9 +59,23 @@ int arch_init_registers(int pid) · 12 unmodified lines | |||
| 58 | return -ENOMEM; | 59 | return -ENOMEM; |
| 59 | 60 | ||
| 60 | /* GDB has x86_xsave_length, which uses x86_cpuid_count */ | 61 | /* GDB has x86_xsave_length, which uses x86_cpuid_count */ |
| 61 | ret = ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov); | 62 | ptrace_regset = NT_X86_XSTATE; |
| 63 | ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); | ||
| 62 | if (ret) | 64 | if (ret) |
| 63 | ret = -errno; | 65 | ret = -errno; |
| 66 | |||
| 67 | if (ret == -ENODEV) { | ||
| 68 | #ifdef CONFIG_X86_32 | ||
| 69 | ptrace_regset = NT_PRXFPREG; | ||
| 70 | #else | ||
| 71 | ptrace_regset = NT_PRFPREG; | ||
| 72 | #endif | ||
| 73 | iov.iov_len = 2 * 1024 * 1024; | ||
| 74 | ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); | ||
| 75 | if (ret) | ||
| 76 | ret = -errno; | ||
| 77 | } | ||
| 78 | |||
| 64 | munmap(iov.iov_base, 2 * 1024 * 1024); | 79 | munmap(iov.iov_base, 2 * 1024 * 1024); |
| 65 | 80 | ||
| 66 | host_fp_size = iov.iov_len; | 81 | host_fp_size = iov.iov_len; |
| @@ -187,7 +187,12 @@ static int copy_sc_to_user(struct sigcontext __user *to, · 186 unmodified lines | |||
| 187 | * Put magic/size values for userspace. We do not bother to verify them | 187 | * Put magic/size values for userspace. We do not bother to verify them |
| 188 | * later on, however, userspace needs them should it try to read the | 188 | * later on, however, userspace needs them should it try to read the |
| 189 | * XSTATE data. And ptrace does not fill in these parts. | 189 | * XSTATE data. And ptrace does not fill in these parts. |
| 190 | * | ||
| 191 | * Skip this if we do not have an XSTATE frame. | ||
| 190 | */ | 192 | */ |
| 193 | if (host_fp_size <= sizeof(to_fp64->fpstate)) | ||
| 194 | return 0; | ||
| 195 | |||
| 191 | BUILD_BUG_ON(sizeof(int) != FP_XSTATE_MAGIC2_SIZE); | 196 | BUILD_BUG_ON(sizeof(int) != FP_XSTATE_MAGIC2_SIZE); |
| 192 | #ifdef CONFIG_X86_32 | 197 | #ifdef CONFIG_X86_32 |
| 193 | __put_user(offsetof(struct _fpstate_32, _fxsr_env) + | 198 | __put_user(offsetof(struct _fpstate_32, _fxsr_env) + |
| @@ -367,11 +372,13 @@ int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig, · 173 unmodified lines | |||
| 367 | int err = 0, sig = ksig->sig; | 372 | int err = 0, sig = ksig->sig; |
| 368 | unsigned long fp_to; | 373 | unsigned long fp_to; |
| 369 | 374 | ||
| 370 | frame = (struct rt_sigframe __user *) | 375 | frame = (void __user *)stack_top - sizeof(struct rt_sigframe); |
| 371 | round_down(stack_top - sizeof(struct rt_sigframe), 16); | ||
| 372 | 376 | ||
| 373 | /* Add required space for math frame */ | 377 | /* Add required space for math frame */ |
| 374 | frame = (struct rt_sigframe __user *)((unsigned long)frame - math_size); | 378 | frame = (void __user *)((unsigned long)frame - math_size); |
| 379 | |||
| 380 | /* ABI requires 16 byte boundary alignment */ | ||
| 381 | frame = (void __user *)round_down((unsigned long)frame, 16); | ||
| 375 | 382 | ||
| 376 | /* Subtract 128 for a red zone and 8 for proper alignment */ | 383 | /* Subtract 128 for a red zone and 8 for proper alignment */ |
| 377 | frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); | 384 | frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); |
| @@ -505,19 +505,19 @@ static bool __init setup_rmptable(void) · 504 unmodified lines | |||
| 505 | * described in the SNP_INIT_EX firmware command description in the SNP | 505 | * described in the SNP_INIT_EX firmware command description in the SNP |
| 506 | * firmware ABI spec. | 506 | * firmware ABI spec. |
| 507 | */ | 507 | */ |
| 508 | static int __init snp_rmptable_init(void) | 508 | int __init snp_rmptable_init(void) |
| 509 | { | 509 | { |
| 510 | unsigned int i; | 510 | unsigned int i; |
| 511 | u64 val; | 511 | u64 val; |
| 512 | 512 | ||
| 513 | if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) | 513 | if (WARN_ON_ONCE(!cc_platform_has(CC_ATTR_HOST_SEV_SNP))) |
| 514 | return 0; | 514 | return -ENOSYS; |
| 515 | 515 | ||
| 516 | if (!amd_iommu_snp_en) | 516 | if (WARN_ON_ONCE(!amd_iommu_snp_en)) |
| 517 | goto nosnp; | 517 | return -ENOSYS; |
| 518 | 518 | ||
| 519 | if (!setup_rmptable()) | 519 | if (!setup_rmptable()) |
| 520 | goto nosnp; | 520 | return -ENOSYS; |
| 521 | 521 | ||
| 522 | /* | 522 | /* |
| 523 | * Check if SEV-SNP is already enabled, this can happen in case of | 523 | * Check if SEV-SNP is already enabled, this can happen in case of |
| @@ -530,7 +530,7 @@ static int __init snp_rmptable_init(void) · 6 unmodified lines | |||
| 530 | /* Zero out the RMP bookkeeping area */ | 530 | /* Zero out the RMP bookkeeping area */ |
| 531 | if (!clear_rmptable_bookkeeping()) { | 531 | if (!clear_rmptable_bookkeeping()) { |
| 532 | free_rmp_segment_table(); | 532 | free_rmp_segment_table(); |
| 533 | goto nosnp; | 533 | return -ENOSYS; |
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | /* Zero out the RMP entries */ | 536 | /* Zero out the RMP entries */ |
| @@ -562,17 +562,8 @@ skip_enable: · 25 unmodified lines | |||
| 562 | crash_kexec_post_notifiers = true; | 562 | crash_kexec_post_notifiers = true; |
| 563 | 563 | ||
| 564 | return 0; | 564 | return 0; |
| 565 | |||
| 566 | nosnp: | ||
| 567 | cc_platform_clear(CC_ATTR_HOST_SEV_SNP); | ||
| 568 | return -ENOSYS; | ||
| 569 | } | 565 | } |
| 570 | 566 | ||
| 571 | /* | ||
| 572 | * This must be called after the IOMMU has been initialized. | ||
| 573 | */ | ||
| 574 | device_initcall(snp_rmptable_init); | ||
| 575 | |||
| 576 | static void set_rmp_segment_info(unsigned int segment_shift) | 567 | static void set_rmp_segment_info(unsigned int segment_shift) |
| 577 | { | 568 | { |
| 578 | rmp_segment_shift = segment_shift; | 569 | rmp_segment_shift = segment_shift; |
| @@ -111,6 +111,51 @@ static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; · 110 unmodified lines | |||
| 111 | */ | 111 | */ |
| 112 | static DEFINE_SPINLOCK(xen_reservation_lock); | 112 | static DEFINE_SPINLOCK(xen_reservation_lock); |
| 113 | 113 | ||
| 114 | /* Protected by xen_reservation_lock. */ | ||
| 115 | #define MIN_CONTIG_ORDER 9 /* 2MB */ | ||
| 116 | static unsigned int discontig_frames_order = MIN_CONTIG_ORDER; | ||
| 117 | static unsigned long discontig_frames_early[1UL << MIN_CONTIG_ORDER] __initdata; | ||
| 118 | static unsigned long *discontig_frames __refdata = discontig_frames_early; | ||
| 119 | static bool discontig_frames_dyn; | ||
| 120 | |||
| 121 | static int alloc_discontig_frames(unsigned int order) | ||
| 122 | { | ||
| 123 | unsigned long *new_array, *old_array; | ||
| 124 | unsigned int old_order; | ||
| 125 | unsigned long flags; | ||
| 126 | |||
| 127 | BUG_ON(order < MIN_CONTIG_ORDER); | ||
| 128 | BUILD_BUG_ON(sizeof(discontig_frames_early) != PAGE_SIZE); | ||
| 129 | |||
| 130 | new_array = (unsigned long *)__get_free_pages(GFP_KERNEL, | ||
| 131 | order - MIN_CONTIG_ORDER); | ||
| 132 | if (!new_array) | ||
| 133 | return -ENOMEM; | ||
| 134 | |||
| 135 | spin_lock_irqsave(&xen_reservation_lock, flags); | ||
| 136 | |||
| 137 | old_order = discontig_frames_order; | ||
| 138 | |||
| 139 | if (order > discontig_frames_order || !discontig_frames_dyn) { | ||
| 140 | if (!discontig_frames_dyn) | ||
| 141 | old_array = NULL; | ||
| 142 | else | ||
| 143 | old_array = discontig_frames; | ||
| 144 | |||
| 145 | discontig_frames = new_array; | ||
| 146 | discontig_frames_order = order; | ||
| 147 | discontig_frames_dyn = true; | ||
| 148 | } else { | ||
| 149 | old_array = new_array; | ||
| 150 | } | ||
| 151 | |||
| 152 | spin_unlock_irqrestore(&xen_reservation_lock, flags); | ||
| 153 | |||
| 154 | free_pages((unsigned long)old_array, old_order - MIN_CONTIG_ORDER); | ||
| 155 | |||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 114 | /* | 159 | /* |
| 115 | * Note about cr3 (pagetable base) values: | 160 | * Note about cr3 (pagetable base) values: |
| 116 | * | 161 | * |
| @@ -814,6 +859,9 @@ static void __init xen_after_bootmem(void) · 697 unmodified lines | |||
| 814 | SetPagePinned(virt_to_page(level3_user_vsyscall)); | 859 | SetPagePinned(virt_to_page(level3_user_vsyscall)); |
| 815 | #endif | 860 | #endif |
| 816 | xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP); | 861 | xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP); |
| 862 | |||
| 863 | if (alloc_discontig_frames(MIN_CONTIG_ORDER)) | ||
| 864 | BUG(); | ||
| 817 | } | 865 | } |
| 818 | 866 | ||
| 819 | static void xen_unpin_page(struct mm_struct *mm, struct page *page, | 867 | static void xen_unpin_page(struct mm_struct *mm, struct page *page, |
| @@ -2203,10 +2251,6 @@ void __init xen_init_mmu_ops(void) · 1383 unmodified lines | |||
| 2203 | memset(dummy_mapping, 0xff, PAGE_SIZE); | 2251 | memset(dummy_mapping, 0xff, PAGE_SIZE); |
| 2204 | } | 2252 | } |
| 2205 | 2253 | ||
| 2206 | /* Protected by xen_reservation_lock. */ | ||
| 2207 | #define MAX_CONTIG_ORDER 9 /* 2MB */ | ||
| 2208 | static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER]; | ||
| 2209 | |||
| 2210 | #define VOID_PTE (mfn_pte(0, __pgprot(0))) | 2254 | #define VOID_PTE (mfn_pte(0, __pgprot(0))) |
| 2211 | static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order, | 2255 | static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order, |
| 2212 | unsigned long *in_frames, | 2256 | unsigned long *in_frames, |
| @@ -2323,18 +2367,25 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, · 110 unmodified lines | |||
| 2323 | unsigned int address_bits, | 2367 | unsigned int address_bits, |
| 2324 | dma_addr_t *dma_handle) | 2368 | dma_addr_t *dma_handle) |
| 2325 | { | 2369 | { |
| 2326 | unsigned long *in_frames = discontig_frames, out_frame; | 2370 | unsigned long *in_frames, out_frame; |
| 2327 | unsigned long flags; | 2371 | unsigned long flags; |
| 2328 | int success; | 2372 | int success; |
| 2329 | unsigned long vstart = (unsigned long)phys_to_virt(pstart); | 2373 | unsigned long vstart = (unsigned long)phys_to_virt(pstart); |
| 2330 | 2374 | ||
| 2331 | if (unlikely(order > MAX_CONTIG_ORDER)) | 2375 | if (unlikely(order > discontig_frames_order)) { |
| 2332 | return -ENOMEM; | 2376 | if (!discontig_frames_dyn) |
| 2377 | return -ENOMEM; | ||
| 2378 | |||
| 2379 | if (alloc_discontig_frames(order)) | ||
| 2380 | return -ENOMEM; | ||
| 2381 | } | ||
| 2333 | 2382 | ||
| 2334 | memset((void *) vstart, 0, PAGE_SIZE << order); | 2383 | memset((void *) vstart, 0, PAGE_SIZE << order); |
| 2335 | 2384 | ||
| 2336 | spin_lock_irqsave(&xen_reservation_lock, flags); | 2385 | spin_lock_irqsave(&xen_reservation_lock, flags); |
| 2337 | 2386 | ||
| 2387 | in_frames = discontig_frames; | ||
| 2388 | |||
| 2338 | /* 1. Zap current PTEs, remembering MFNs. */ | 2389 | /* 1. Zap current PTEs, remembering MFNs. */ |
| 2339 | xen_zap_pfn_range(vstart, order, in_frames, NULL); | 2390 | xen_zap_pfn_range(vstart, order, in_frames, NULL); |
| 2340 | 2391 | ||
| @@ -2358,12 +2409,12 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order, · 17 unmodified lines | |||
| 2358 | 2409 | ||
| 2359 | void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order) | 2410 | void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order) |
| 2360 | { | 2411 | { |
| 2361 | unsigned long *out_frames = discontig_frames, in_frame; | 2412 | unsigned long *out_frames, in_frame; |
| 2362 | unsigned long flags; | 2413 | unsigned long flags; |
| 2363 | int success; | 2414 | int success; |
| 2364 | unsigned long vstart; | 2415 | unsigned long vstart; |
| 2365 | 2416 | ||
| 2366 | if (unlikely(order > MAX_CONTIG_ORDER)) | 2417 | if (unlikely(order > discontig_frames_order)) |
| 2367 | return; | 2418 | return; |
| 2368 | 2419 | ||
| 2369 | vstart = (unsigned long)phys_to_virt(pstart); | 2420 | vstart = (unsigned long)phys_to_virt(pstart); |
| @@ -2371,6 +2422,8 @@ void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order) · 1 unmodified line | |||
| 2371 | 2422 | ||
| 2372 | spin_lock_irqsave(&xen_reservation_lock, flags); | 2423 | spin_lock_irqsave(&xen_reservation_lock, flags); |
| 2373 | 2424 | ||
| 2425 | out_frames = discontig_frames; | ||
| 2426 | |||
| 2374 | /* 1. Find start MFN of contiguous extent. */ | 2427 | /* 1. Find start MFN of contiguous extent. */ |
| 2375 | in_frame = virt_to_mfn((void *)vstart); | 2428 | in_frame = virt_to_mfn((void *)vstart); |
| 2376 | 2429 | ||
| @@ -100,9 +100,6 @@ SYM_FUNC_START(xen_hypercall_hvm) · 99 unmodified lines | |||
| 100 | push %r10 | 100 | push %r10 |
| 101 | push %r9 | 101 | push %r9 |
| 102 | push %r8 | 102 | push %r8 |
| 103 | #ifdef CONFIG_FRAME_POINTER | ||
| 104 | pushq $0 /* Dummy push for stack alignment. */ | ||
| 105 | #endif | ||
| 106 | #endif | 103 | #endif |
| 107 | /* Set the vendor specific function. */ | 104 | /* Set the vendor specific function. */ |
| 108 | call __xen_hypercall_setfunc | 105 | call __xen_hypercall_setfunc |
| @@ -117,11 +114,8 @@ SYM_FUNC_START(xen_hypercall_hvm) · 8 unmodified lines | |||
| 117 | pop %ebx | 114 | pop %ebx |
| 118 | pop %eax | 115 | pop %eax |
| 119 | #else | 116 | #else |
| 120 | lea xen_hypercall_amd(%rip), %rbx | 117 | lea xen_hypercall_amd(%rip), %rcx |
| 121 | cmp %rax, %rbx | 118 | cmp %rax, %rcx |
| 122 | #ifdef CONFIG_FRAME_POINTER | ||
| 123 | pop %rax /* Dummy pop. */ | ||
| 124 | #endif | ||
| 125 | pop %r8 | 119 | pop %r8 |
| 126 | pop %r9 | 120 | pop %r9 |
| 127 | pop %r10 | 121 | pop %r10 |
| @@ -132,6 +126,7 @@ SYM_FUNC_START(xen_hypercall_hvm) · 4 unmodified lines | |||
| 132 | pop %rcx | 126 | pop %rcx |
| 133 | pop %rax | 127 | pop %rax |
| 134 | #endif | 128 | #endif |
| 129 | FRAME_END | ||
| 135 | /* Use correct hypercall function. */ | 130 | /* Use correct hypercall function. */ |
| 136 | jz xen_hypercall_amd | 131 | jz xen_hypercall_amd |
| 137 | jmp xen_hypercall_intel | 132 | jmp xen_hypercall_intel |
| @@ -53,13 +53,25 @@ int mac_partition(struct parsed_partitions *state) · 52 unmodified lines | |||
| 53 | } | 53 | } |
| 54 | secsize = be16_to_cpu(md->block_size); | 54 | secsize = be16_to_cpu(md->block_size); |
| 55 | put_dev_sector(sect); | 55 | put_dev_sector(sect); |
| 56 | |||
| 57 | /* | ||
| 58 | * If the "block size" is not a power of 2, things get weird - we might | ||
| 59 | * end up with a partition straddling a sector boundary, so we wouldn't | ||
| 60 | * be able to read a partition entry with read_part_sector(). | ||
| 61 | * Real block sizes are probably (?) powers of two, so just require | ||
| 62 | * that. | ||
| 63 | */ | ||
| 64 | if (!is_power_of_2(secsize)) | ||
| 65 | return -1; | ||
| 56 | datasize = round_down(secsize, 512); | 66 | datasize = round_down(secsize, 512); |
| 57 | data = read_part_sector(state, datasize / 512, §); | 67 | data = read_part_sector(state, datasize / 512, §); |
| 58 | if (!data) | 68 | if (!data) |
| 59 | return -1; | 69 | return -1; |
| 60 | partoffset = secsize % 512; | 70 | partoffset = secsize % 512; |
| 61 | if (partoffset + sizeof(*part) > datasize) | 71 | if (partoffset + sizeof(*part) > datasize) { |
| 72 | put_dev_sector(sect); | ||
| 62 | return -1; | 73 | return -1; |
| 74 | } | ||
| 63 | part = (struct mac_partition *) (data + partoffset); | 75 | part = (struct mac_partition *) (data + partoffset); |
| 64 | if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { | 76 | if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { |
| 65 | put_dev_sector(sect); | 77 | put_dev_sector(sect); |
| @@ -112,8 +124,8 @@ int mac_partition(struct parsed_partitions *state) · 46 unmodified lines | |||
| 112 | int i, l; | 124 | int i, l; |
| 113 | 125 | ||
| 114 | goodness++; | 126 | goodness++; |
| 115 | l = strlen(part->name); | 127 | l = strnlen(part->name, sizeof(part->name)); |
| 116 | if (strcmp(part->name, "/") == 0) | 128 | if (strncmp(part->name, "/", sizeof(part->name)) == 0) |
| 117 | goodness++; | 129 | goodness++; |
| 118 | for (i = 0; i <= l - 4; ++i) { | 130 | for (i = 0; i <= l - 4; ++i) { |
| 119 | if (strncasecmp(part->name + i, "root", | 131 | if (strncasecmp(part->name + i, "root", |
| @@ -21,6 +21,11 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | #define AMDXDNA_AUTOSUSPEND_DELAY 5000 /* milliseconds */ | 22 | #define AMDXDNA_AUTOSUSPEND_DELAY 5000 /* milliseconds */ |
| 23 | 23 | ||
| 24 | MODULE_FIRMWARE("amdnpu/1502_00/npu.sbin"); | ||
| 25 | MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin"); | ||
| 26 | MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin"); | ||
| 27 | MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin"); | ||
| 28 | |||
| 24 | /* | 29 | /* |
| 25 | * Bind the driver base on (vendor_id, device_id) pair and later use the | 30 | * Bind the driver base on (vendor_id, device_id) pair and later use the |
| 26 | * (device_id, rev_id) pair as a key to select the devices. The devices with | 31 | * (device_id, rev_id) pair as a key to select the devices. The devices with |
| @@ -397,15 +397,19 @@ int ivpu_boot(struct ivpu_device *vdev) · 396 unmodified lines | |||
| 397 | if (ivpu_fw_is_cold_boot(vdev)) { | 397 | if (ivpu_fw_is_cold_boot(vdev)) { |
| 398 | ret = ivpu_pm_dct_init(vdev); | 398 | ret = ivpu_pm_dct_init(vdev); |
| 399 | if (ret) | 399 | if (ret) |
| 400 | goto err_diagnose_failure; | 400 | goto err_disable_ipc; |
| 401 | 401 | ||
| 402 | ret = ivpu_hw_sched_init(vdev); | 402 | ret = ivpu_hw_sched_init(vdev); |
| 403 | if (ret) | 403 | if (ret) |
| 404 | goto err_diagnose_failure; | 404 | goto err_disable_ipc; |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | return 0; | 407 | return 0; |
| 408 | 408 | ||
| 409 | err_disable_ipc: | ||
| 410 | ivpu_ipc_disable(vdev); | ||
| 411 | ivpu_hw_irq_disable(vdev); | ||
| 412 | disable_irq(vdev->irq); | ||
| 409 | err_diagnose_failure: | 413 | err_diagnose_failure: |
| 410 | ivpu_hw_diagnose_failure(vdev); | 414 | ivpu_hw_diagnose_failure(vdev); |
| 411 | ivpu_mmu_evtq_dump(vdev); | 415 | ivpu_mmu_evtq_dump(vdev); |
| @@ -115,41 +115,57 @@ err_power_down: · 114 unmodified lines | |||
| 115 | return ret; | 115 | return ret; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static void ivpu_pm_recovery_work(struct work_struct *work) | 118 | static void ivpu_pm_reset_begin(struct ivpu_device *vdev) |
| 119 | { | 119 | { |
| 120 | struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, recovery_work); | 120 | pm_runtime_disable(vdev->drm.dev); |
| 121 | struct ivpu_device *vdev = pm->vdev; | ||
| 122 | char *evt[2] = {"IVPU_PM_EVENT=IVPU_RECOVER", NULL}; | ||
| 123 | int ret; | ||
| 124 | |||
| 125 | ivpu_err(vdev, "Recovering the NPU (reset #%d)\n", atomic_read(&vdev->pm->reset_counter)); | ||
| 126 | |||
| 127 | ret = pm_runtime_resume_and_get(vdev->drm.dev); | ||
| 128 | if (ret) | ||
| 129 | ivpu_err(vdev, "Failed to resume NPU: %d\n", ret); | ||
| 130 | |||
| 131 | ivpu_jsm_state_dump(vdev); | ||
| 132 | ivpu_dev_coredump(vdev); | ||
| 133 | 121 | ||
| 134 | atomic_inc(&vdev->pm->reset_counter); | 122 | atomic_inc(&vdev->pm->reset_counter); |
| 135 | atomic_set(&vdev->pm->reset_pending, 1); | 123 | atomic_set(&vdev->pm->reset_pending, 1); |
| 136 | down_write(&vdev->pm->reset_lock); | 124 | down_write(&vdev->pm->reset_lock); |
| 125 | } | ||
| 126 | |||
| 127 | static void ivpu_pm_reset_complete(struct ivpu_device *vdev) | ||
| 128 | { | ||
| 129 | int ret; | ||
| 137 | 130 | ||
| 138 | ivpu_suspend(vdev); | ||
| 139 | ivpu_pm_prepare_cold_boot(vdev); | 131 | ivpu_pm_prepare_cold_boot(vdev); |
| 140 | ivpu_jobs_abort_all(vdev); | 132 | ivpu_jobs_abort_all(vdev); |
| 141 | ivpu_ms_cleanup_all(vdev); | 133 | ivpu_ms_cleanup_all(vdev); |
| 142 | 134 | ||
| 143 | ret = ivpu_resume(vdev); | 135 | ret = ivpu_resume(vdev); |
| 144 | if (ret) | 136 | if (ret) { |
| 145 | ivpu_err(vdev, "Failed to resume NPU: %d\n", ret); | 137 | ivpu_err(vdev, "Failed to resume NPU: %d\n", ret); |
| 138 | pm_runtime_set_suspended(vdev->drm.dev); | ||
| 139 | } else { | ||
| 140 | pm_runtime_set_active(vdev->drm.dev); | ||
| 141 | } | ||
| 146 | 142 | ||
| 147 | up_write(&vdev->pm->reset_lock); | 143 | up_write(&vdev->pm->reset_lock); |
| 148 | atomic_set(&vdev->pm->reset_pending, 0); | 144 | atomic_set(&vdev->pm->reset_pending, 0); |
| 149 | 145 | ||
| 150 | kobject_uevent_env(&vdev->drm.dev->kobj, KOBJ_CHANGE, evt); | ||
| 151 | pm_runtime_mark_last_busy(vdev->drm.dev); | 146 | pm_runtime_mark_last_busy(vdev->drm.dev); |
| 152 | pm_runtime_put_autosuspend(vdev->drm.dev); | 147 | pm_runtime_enable(vdev->drm.dev); |
| 148 | } | ||
| 149 | |||
| 150 | static void ivpu_pm_recovery_work(struct work_struct *work) | ||
| 151 | { | ||
| 152 | struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, recovery_work); | ||
| 153 | struct ivpu_device *vdev = pm->vdev; | ||
| 154 | char *evt[2] = {"IVPU_PM_EVENT=IVPU_RECOVER", NULL}; | ||
| 155 | |||
| 156 | ivpu_err(vdev, "Recovering the NPU (reset #%d)\n", atomic_read(&vdev->pm->reset_counter)); | ||
| 157 | |||
| 158 | ivpu_pm_reset_begin(vdev); | ||
| 159 | |||
| 160 | if (!pm_runtime_status_suspended(vdev->drm.dev)) { | ||
| 161 | ivpu_jsm_state_dump(vdev); | ||
| 162 | ivpu_dev_coredump(vdev); | ||
| 163 | ivpu_suspend(vdev); | ||
| 164 | } | ||
| 165 | |||
| 166 | ivpu_pm_reset_complete(vdev); | ||
| 167 | |||
| 168 | kobject_uevent_env(&vdev->drm.dev->kobj, KOBJ_CHANGE, evt); | ||
| 153 | } | 169 | } |
| 154 | 170 | ||
| 155 | void ivpu_pm_trigger_recovery(struct ivpu_device *vdev, const char *reason) | 171 | void ivpu_pm_trigger_recovery(struct ivpu_device *vdev, const char *reason) |
| @@ -309,7 +325,10 @@ int ivpu_rpm_get(struct ivpu_device *vdev) · 153 unmodified lines | |||
| 309 | int ret; | 325 | int ret; |
| 310 | 326 | ||
| 311 | ret = pm_runtime_resume_and_get(vdev->drm.dev); | 327 | ret = pm_runtime_resume_and_get(vdev->drm.dev); |
| 312 | drm_WARN_ON(&vdev->drm, ret < 0); | 328 | if (ret < 0) { |
| 329 | ivpu_err(vdev, "Failed to resume NPU: %d\n", ret); | ||
| 330 | pm_runtime_set_suspended(vdev->drm.dev); | ||
| 331 | } | ||
| 313 | 332 | ||
| 314 | return ret; | 333 | return ret; |
| 315 | } | 334 | } |
| @@ -325,16 +344,13 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev) · 9 unmodified lines | |||
| 325 | struct ivpu_device *vdev = pci_get_drvdata(pdev); | 344 | struct ivpu_device *vdev = pci_get_drvdata(pdev); |
| 326 | 345 | ||
| 327 | ivpu_dbg(vdev, PM, "Pre-reset..\n"); | 346 | ivpu_dbg(vdev, PM, "Pre-reset..\n"); |
| 328 | atomic_inc(&vdev->pm->reset_counter); | ||
| 329 | atomic_set(&vdev->pm->reset_pending, 1); | ||
| 330 | 347 | ||
| 331 | pm_runtime_get_sync(vdev->drm.dev); | 348 | ivpu_pm_reset_begin(vdev); |
| 332 | down_write(&vdev->pm->reset_lock); | 349 | |
| 333 | ivpu_prepare_for_reset(vdev); | 350 | if (!pm_runtime_status_suspended(vdev->drm.dev)) { |
| 334 | ivpu_hw_reset(vdev); | 351 | ivpu_prepare_for_reset(vdev); |
| 335 | ivpu_pm_prepare_cold_boot(vdev); | 352 | ivpu_hw_reset(vdev); |
| 336 | ivpu_jobs_abort_all(vdev); | 353 | } |
| 337 | ivpu_ms_cleanup_all(vdev); | ||
| 338 | 354 | ||
| 339 | ivpu_dbg(vdev, PM, "Pre-reset done.\n"); | 355 | ivpu_dbg(vdev, PM, "Pre-reset done.\n"); |
| 340 | } | 356 | } |
| @@ -342,18 +358,12 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev) · 1 unmodified line | |||
| 342 | void ivpu_pm_reset_done_cb(struct pci_dev *pdev) | 358 | void ivpu_pm_reset_done_cb(struct pci_dev *pdev) |
| 343 | { | 359 | { |
| 344 | struct ivpu_device *vdev = pci_get_drvdata(pdev); | 360 | struct ivpu_device *vdev = pci_get_drvdata(pdev); |
| 345 | int ret; | ||
| 346 | 361 | ||
| 347 | ivpu_dbg(vdev, PM, "Post-reset..\n"); | 362 | ivpu_dbg(vdev, PM, "Post-reset..\n"); |
| 348 | ret = ivpu_resume(vdev); | ||
| 349 | if (ret) | ||
| 350 | ivpu_err(vdev, "Failed to set RESUME state: %d\n", ret); | ||
| 351 | up_write(&vdev->pm->reset_lock); | ||
| 352 | atomic_set(&vdev->pm->reset_pending, 0); | ||
| 353 | ivpu_dbg(vdev, PM, "Post-reset done.\n"); | ||
| 354 | 363 | ||
| 355 | pm_runtime_mark_last_busy(vdev->drm.dev); | 364 | ivpu_pm_reset_complete(vdev); |
| 356 | pm_runtime_put_autosuspend(vdev->drm.dev); | 365 | |
| 366 | ivpu_dbg(vdev, PM, "Post-reset done.\n"); | ||
| 357 | } | 367 | } |
| 358 | 368 | ||
| 359 | void ivpu_pm_init(struct ivpu_device *vdev) | 369 | void ivpu_pm_init(struct ivpu_device *vdev) |
| @@ -163,7 +163,7 @@ int __init acpi_gtdt_init(struct acpi_table_header *table, · 162 unmodified lines | |||
| 163 | { | 163 | { |
| 164 | void *platform_timer; | 164 | void *platform_timer; |
| 165 | struct acpi_table_gtdt *gtdt; | 165 | struct acpi_table_gtdt *gtdt; |
| 166 | int cnt = 0; | 166 | u32 cnt = 0; |
| 167 | 167 | ||
| 168 | gtdt = container_of(table, struct acpi_table_gtdt, header); | 168 | gtdt = container_of(table, struct acpi_table_gtdt, header); |
| 169 | acpi_gtdt_desc.gtdt = gtdt; | 169 | acpi_gtdt_desc.gtdt = gtdt; |
| @@ -188,13 +188,17 @@ int __init acpi_gtdt_init(struct acpi_table_header *table, · 18 unmodified lines | |||
| 188 | cnt++; | 188 | cnt++; |
| 189 | 189 | ||
| 190 | if (cnt != gtdt->platform_timer_count) { | 190 | if (cnt != gtdt->platform_timer_count) { |
| 191 | cnt = min(cnt, gtdt->platform_timer_count); | ||
| 192 | pr_err(FW_BUG "limiting Platform Timer count to %d\n", cnt); | ||
| 193 | } | ||
| 194 | |||
| 195 | if (!cnt) { | ||
| 191 | acpi_gtdt_desc.platform_timer = NULL; | 196 | acpi_gtdt_desc.platform_timer = NULL; |
| 192 | pr_err(FW_BUG "invalid timer data.\n"); | 197 | return 0; |
| 193 | return -EINVAL; | ||
| 194 | } | 198 | } |
| 195 | 199 | ||
| 196 | if (platform_timer_count) | 200 | if (platform_timer_count) |
| 197 | *platform_timer_count = gtdt->platform_timer_count; | 201 | *platform_timer_count = cnt; |
| 198 | 202 | ||
| 199 | return 0; | 203 | return 0; |
| 200 | } | 204 | } |
| @@ -287,9 +287,7 @@ static acpi_status acpi_platformrt_space_handler(u32 function, · 286 unmodified lines | |||
| 287 | if (!handler || !module) | 287 | if (!handler || !module) |
| 288 | goto invalid_guid; | 288 | goto invalid_guid; |
| 289 | 289 | ||
| 290 | if (!handler->handler_addr || | 290 | if (!handler->handler_addr) { |
| 291 | !handler->static_data_buffer_addr || | ||
| 292 | !handler->acpi_param_buffer_addr) { | ||
| 293 | buffer->prm_status = PRM_HANDLER_ERROR; | 291 | buffer->prm_status = PRM_HANDLER_ERROR; |
| 294 | return AE_OK; | 292 | return AE_OK; |
| 295 | } | 293 | } |
| @@ -1187,8 +1187,6 @@ static int acpi_data_prop_read(const struct acpi_device_data *data, · 1186 unmodified lines | |||
| 1187 | } | 1187 | } |
| 1188 | break; | 1188 | break; |
| 1189 | } | 1189 | } |
| 1190 | if (nval == 0) | ||
| 1191 | return -EINVAL; | ||
| 1192 | 1190 | ||
| 1193 | if (obj->type == ACPI_TYPE_BUFFER) { | 1191 | if (obj->type == ACPI_TYPE_BUFFER) { |
| 1194 | if (proptype != DEV_PROP_U8) | 1192 | if (proptype != DEV_PROP_U8) |
| @@ -1212,9 +1210,11 @@ static int acpi_data_prop_read(const struct acpi_device_data *data, · 17 unmodified lines | |||
| 1212 | ret = acpi_copy_property_array_uint(items, (u64 *)val, nval); | 1210 | ret = acpi_copy_property_array_uint(items, (u64 *)val, nval); |
| 1213 | break; | 1211 | break; |
| 1214 | case DEV_PROP_STRING: | 1212 | case DEV_PROP_STRING: |
| 1215 | ret = acpi_copy_property_array_string( | 1213 | nval = min_t(u32, nval, obj->package.count); |
| 1216 | items, (char **)val, | 1214 | if (nval == 0) |
| 1217 | min_t(u32, nval, obj->package.count)); | 1215 | return -ENODATA; |
| 1216 | |||
| 1217 | ret = acpi_copy_property_array_string(items, (char **)val, nval); | ||
| 1218 | break; | 1218 | break; |
| 1219 | default: | 1219 | default: |
| 1220 | ret = -EINVAL; | 1220 | ret = -EINVAL; |
| @@ -563,6 +563,12 @@ static const struct dmi_system_id irq1_edge_low_force_override[] = { · 562 unmodified lines | |||
| 563 | DMI_MATCH(DMI_BOARD_NAME, "RP-15"), | 563 | DMI_MATCH(DMI_BOARD_NAME, "RP-15"), |
| 564 | }, | 564 | }, |
| 565 | }, | 565 | }, |
| 566 | { | ||
| 567 | .matches = { | ||
| 568 | DMI_MATCH(DMI_SYS_VENDOR, "Eluktronics Inc."), | ||
| 569 | DMI_MATCH(DMI_BOARD_NAME, "MECH-17"), | ||
| 570 | }, | ||
| 571 | }, | ||
| 566 | { | 572 | { |
| 567 | /* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */ | 573 | /* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */ |
| 568 | .matches = { | 574 | .matches = { |
| @@ -6,7 +6,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \ · 5 unmodified lines | |||
| 6 | cpu.o firmware.o init.o map.o devres.o \ | 6 | cpu.o firmware.o init.o map.o devres.o \ |
| 7 | attribute_container.o transport_class.o \ | 7 | attribute_container.o transport_class.o \ |
| 8 | topology.o container.o property.o cacheinfo.o \ | 8 | topology.o container.o property.o cacheinfo.o \ |
| 9 | swnode.o | 9 | swnode.o faux.o |
| 10 | obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o | 10 | obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o |
| 11 | obj-$(CONFIG_DEVTMPFS) += devtmpfs.o | 11 | obj-$(CONFIG_DEVTMPFS) += devtmpfs.o |
| 12 | obj-y += power/ | 12 | obj-y += power/ |
| @@ -137,6 +137,7 @@ int hypervisor_init(void); · 136 unmodified lines | |||
| 137 | static inline int hypervisor_init(void) { return 0; } | 137 | static inline int hypervisor_init(void) { return 0; } |
| 138 | #endif | 138 | #endif |
| 139 | int platform_bus_init(void); | 139 | int platform_bus_init(void); |
| 140 | int faux_bus_init(void); | ||
| 140 | void cpu_dev_init(void); | 141 | void cpu_dev_init(void); |
| 141 | void container_dev_init(void); | 142 | void container_dev_init(void); |
| 142 | #ifdef CONFIG_AUXILIARY_BUS | 143 | #ifdef CONFIG_AUXILIARY_BUS |
| @@ -0,0 +1,232 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2025 Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
| 4 | * Copyright (c) 2025 The Linux Foundation | ||
| 5 | * | ||
| 6 | * A "simple" faux bus that allows devices to be created and added | ||
| 7 | * automatically to it. This is to be used whenever you need to create a | ||
| 8 | * device that is not associated with any "real" system resources, and do | ||
| 9 | * not want to have to deal with a bus/driver binding logic. It is | ||
| 10 | * intended to be very simple, with only a create and a destroy function | ||
| 11 | * available. | ||
| 12 | */ | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/slab.h> | ||
| 16 | #include <linux/string.h> | ||
| 17 | #include <linux/container_of.h> | ||
| 18 | #include <linux/device/faux.h> | ||
| 19 | #include "base.h" | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Internal wrapper structure so we can hold a pointer to the | ||
| 23 | * faux_device_ops for this device. | ||
| 24 | */ | ||
| 25 | struct faux_object { | ||
| 26 | struct faux_device faux_dev; | ||
| 27 | const struct faux_device_ops *faux_ops; | ||
| 28 | }; | ||
| 29 | #define to_faux_object(dev) container_of_const(dev, struct faux_object, faux_dev.dev) | ||
| 30 | |||
| 31 | static struct device faux_bus_root = { | ||
| 32 | .init_name = "faux", | ||
| 33 | }; | ||
| 34 | |||
| 35 | static int faux_match(struct device *dev, const struct device_driver *drv) | ||
| 36 | { | ||
| 37 | /* Match always succeeds, we only have one driver */ | ||
| 38 | return 1; | ||
| 39 | } | ||
| 40 | |||
| 41 | static int faux_probe(struct device *dev) | ||
| 42 | { | ||
| 43 | struct faux_object *faux_obj = to_faux_object(dev); | ||
| 44 | struct faux_device *faux_dev = &faux_obj->faux_dev; | ||
| 45 | const struct faux_device_ops *faux_ops = faux_obj->faux_ops; | ||
| 46 | int ret = 0; | ||
| 47 | |||
| 48 | if (faux_ops && faux_ops->probe) | ||
| 49 | ret = faux_ops->probe(faux_dev); | ||
| 50 | |||
| 51 | return ret; | ||
| 52 | } | ||
| 53 | |||
| 54 | static void faux_remove(struct device *dev) | ||
| 55 | { | ||
| 56 | struct faux_object *faux_obj = to_faux_object(dev); | ||
| 57 | struct faux_device *faux_dev = &faux_obj->faux_dev; | ||
| 58 | const struct faux_device_ops *faux_ops = faux_obj->faux_ops; | ||
| 59 | |||
| 60 | if (faux_ops && faux_ops->remove) | ||
| 61 | faux_ops->remove(faux_dev); | ||
| 62 | } | ||
| 63 | |||
| 64 | static const struct bus_type faux_bus_type = { | ||
| 65 | .name = "faux", | ||
| 66 | .match = faux_match, | ||
| 67 | .probe = faux_probe, | ||
| 68 | .remove = faux_remove, | ||
| 69 | }; | ||
| 70 | |||
| 71 | static struct device_driver faux_driver = { | ||
| 72 | .name = "faux_driver", | ||
| 73 | .bus = &faux_bus_type, | ||
| 74 | .probe_type = PROBE_FORCE_SYNCHRONOUS, | ||
| 75 | }; | ||
| 76 | |||
| 77 | static void faux_device_release(struct device *dev) | ||
| 78 | { | ||
| 79 | struct faux_object *faux_obj = to_faux_object(dev); | ||
| 80 | |||
| 81 | kfree(faux_obj); | ||
| 82 | } | ||
| 83 | |||
| 84 | /** | ||
| 85 | * faux_device_create_with_groups - Create and register with the driver | ||
| 86 | * core a faux device and populate the device with an initial | ||
| 87 | * set of sysfs attributes. | ||
| 88 | * @name: The name of the device we are adding, must be unique for | ||
| 89 | * all faux devices. | ||
| 90 | * @parent: Pointer to a potential parent struct device. If set to | ||
| 91 | * NULL, the device will be created in the "root" of the faux | ||
| 92 | * device tree in sysfs. | ||
| 93 | * @faux_ops: struct faux_device_ops that the new device will call back | ||
| 94 | * into, can be NULL. | ||
| 95 | * @groups: The set of sysfs attributes that will be created for this | ||
| 96 | * device when it is registered with the driver core. | ||
| 97 | * | ||
| 98 | * Create a new faux device and register it in the driver core properly. | ||
| 99 | * If present, callbacks in @faux_ops will be called with the device that | ||
| 100 | * for the caller to do something with at the proper time given the | ||
| 101 | * device's lifecycle. | ||
| 102 | * | ||
| 103 | * Note, when this function is called, the functions specified in struct | ||
| 104 | * faux_ops can be called before the function returns, so be prepared for | ||
| 105 | * everything to be properly initialized before that point in time. | ||
| 106 | * | ||
| 107 | * Return: | ||
| 108 | * * NULL if an error happened with creating the device | ||
| 109 | * * pointer to a valid struct faux_device that is registered with sysfs | ||
| 110 | */ | ||
| 111 | struct faux_device *faux_device_create_with_groups(const char *name, | ||
| 112 | struct device *parent, | ||
| 113 | const struct faux_device_ops *faux_ops, | ||
| 114 | const struct attribute_group **groups) | ||
| 115 | { | ||
| 116 | struct faux_object *faux_obj; | ||
| 117 | struct faux_device *faux_dev; | ||
| 118 | struct device *dev; | ||
| 119 | int ret; | ||
| 120 | |||
| 121 | faux_obj = kzalloc(sizeof(*faux_obj), GFP_KERNEL); | ||
| 122 | if (!faux_obj) | ||
| 123 | return NULL; | ||
| 124 | |||
| 125 | /* Save off the callbacks so we can use them in the future */ | ||
| 126 | faux_obj->faux_ops = faux_ops; | ||
| 127 | |||
| 128 | /* Initialize the device portion and register it with the driver core */ | ||
| 129 | faux_dev = &faux_obj->faux_dev; | ||
| 130 | dev = &faux_dev->dev; | ||
| 131 | |||
| 132 | device_initialize(dev); | ||
| 133 | dev->release = faux_device_release; | ||
| 134 | if (parent) | ||
| 135 | dev->parent = parent; | ||
| 136 | else | ||
| 137 | dev->parent = &faux_bus_root; | ||
| 138 | dev->bus = &faux_bus_type; | ||
| 139 | dev->groups = groups; | ||
| 140 | dev_set_name(dev, "%s", name); | ||
| 141 | |||
| 142 | ret = device_add(dev); | ||
| 143 | if (ret) { | ||
| 144 | pr_err("%s: device_add for faux device '%s' failed with %d\n", | ||
| 145 | __func__, name, ret); | ||
| 146 | put_device(dev); | ||
| 147 | return NULL; | ||
| 148 | } | ||
| 149 | |||
| 150 | return faux_dev; | ||
| 151 | } | ||
| 152 | EXPORT_SYMBOL_GPL(faux_device_create_with_groups); | ||
| 153 | |||
| 154 | /** | ||
| 155 | * faux_device_create - create and register with the driver core a faux device | ||
| 156 | * @name: The name of the device we are adding, must be unique for all | ||
| 157 | * faux devices. | ||
| 158 | * @parent: Pointer to a potential parent struct device. If set to | ||
| 159 | * NULL, the device will be created in the "root" of the faux | ||
| 160 | * device tree in sysfs. | ||
| 161 | * @faux_ops: struct faux_device_ops that the new device will call back | ||
| 162 | * into, can be NULL. | ||
| 163 | * | ||
| 164 | * Create a new faux device and register it in the driver core properly. | ||
| 165 | * If present, callbacks in @faux_ops will be called with the device that | ||
| 166 | * for the caller to do something with at the proper time given the | ||
| 167 | * device's lifecycle. | ||
| 168 | * | ||
| 169 | * Note, when this function is called, the functions specified in struct | ||
| 170 | * faux_ops can be called before the function returns, so be prepared for | ||
| 171 | * everything to be properly initialized before that point in time. | ||
| 172 | * | ||
| 173 | * Return: | ||
| 174 | * * NULL if an error happened with creating the device | ||
| 175 | * * pointer to a valid struct faux_device that is registered with sysfs | ||
| 176 | */ | ||
| 177 | struct faux_device *faux_device_create(const char *name, | ||
| 178 | struct device *parent, | ||
| 179 | const struct faux_device_ops *faux_ops) | ||
| 180 | { | ||
| 181 | return faux_device_create_with_groups(name, parent, faux_ops, NULL); | ||
| 182 | } | ||
| 183 | EXPORT_SYMBOL_GPL(faux_device_create); | ||
| 184 | |||
| 185 | /** | ||
| 186 | * faux_device_destroy - destroy a faux device | ||
| 187 | * @faux_dev: faux device to destroy | ||
| 188 | * | ||
| 189 | * Unregisters and cleans up a device that was created with a call to | ||
| 190 | * faux_device_create() | ||
| 191 | */ | ||
| 192 | void faux_device_destroy(struct faux_device *faux_dev) | ||
| 193 | { | ||
| 194 | struct device *dev = &faux_dev->dev; | ||
| 195 | |||
| 196 | if (!faux_dev) | ||
| 197 | return; | ||
| 198 | |||
| 199 | device_del(dev); | ||
| 200 | |||
| 201 | /* The final put_device() will clean up the memory we allocated for this device. */ | ||
| 202 | put_device(dev); | ||
| 203 | } | ||
| 204 | EXPORT_SYMBOL_GPL(faux_device_destroy); | ||
| 205 | |||
| 206 | int __init faux_bus_init(void) | ||
| 207 | { | ||
| 208 | int ret; | ||
| 209 | |||
| 210 | ret = device_register(&faux_bus_root); | ||
| 211 | if (ret) { | ||
| 212 | put_device(&faux_bus_root); | ||
| 213 | return ret; | ||
| 214 | } | ||
| 215 | |||
| 216 | ret = bus_register(&faux_bus_type); | ||
| 217 | if (ret) | ||
| 218 | goto error_bus; | ||
| 219 | |||
| 220 | ret = driver_register(&faux_driver); | ||
| 221 | if (ret) | ||
| 222 | goto error_driver; | ||
| 223 | |||
| 224 | return ret; | ||
| 225 | |||
| 226 | error_driver: | ||
| 227 | bus_unregister(&faux_bus_type); | ||
| 228 | |||
| 229 | error_bus: | ||
| 230 | device_unregister(&faux_bus_root); | ||
| 231 | return ret; | ||
| 232 | } | ||
| @@ -32,6 +32,7 @@ void __init driver_init(void) · 31 unmodified lines | |||
| 32 | /* These are also core pieces, but must come after the | 32 | /* These are also core pieces, but must come after the |
| 33 | * core core pieces. | 33 | * core core pieces. |
| 34 | */ | 34 | */ |
| 35 | faux_bus_init(); | ||
| 35 | of_core_init(); | 36 | of_core_init(); |
| 36 | platform_bus_init(); | 37 | platform_bus_init(); |
| 37 | auxiliary_bus_init(); | 38 | auxiliary_bus_init(); |
| @@ -1191,24 +1191,18 @@ static pm_message_t resume_event(pm_message_t sleep_state) · 1190 unmodified lines | |||
| 1191 | return PMSG_ON; | 1191 | return PMSG_ON; |
| 1192 | } | 1192 | } |
| 1193 | 1193 | ||
| 1194 | static void dpm_superior_set_must_resume(struct device *dev, bool set_active) | 1194 | static void dpm_superior_set_must_resume(struct device *dev) |
| 1195 | { | 1195 | { |
| 1196 | struct device_link *link; | 1196 | struct device_link *link; |
| 1197 | int idx; | 1197 | int idx; |
| 1198 | 1198 | ||
| 1199 | if (dev->parent) { | 1199 | if (dev->parent) |
| 1200 | dev->parent->power.must_resume = true; | 1200 | dev->parent->power.must_resume = true; |
| 1201 | if (set_active) | ||
| 1202 | dev->parent->power.set_active = true; | ||
| 1203 | } | ||
| 1204 | 1201 | ||
| 1205 | idx = device_links_read_lock(); | 1202 | idx = device_links_read_lock(); |
| 1206 | 1203 | ||
| 1207 | list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) { | 1204 | list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) |
| 1208 | link->supplier->power.must_resume = true; | 1205 | link->supplier->power.must_resume = true; |
| 1209 | if (set_active) | ||
| 1210 | link->supplier->power.set_active = true; | ||
| 1211 | } | ||
| 1212 | 1206 | ||
| 1213 | device_links_read_unlock(idx); | 1207 | device_links_read_unlock(idx); |
| 1214 | } | 1208 | } |
| @@ -1287,9 +1281,12 @@ Skip: · 72 unmodified lines | |||
| 1287 | dev->power.must_resume = true; | 1281 | dev->power.must_resume = true; |
| 1288 | 1282 | ||
| 1289 | if (dev->power.must_resume) { | 1283 | if (dev->power.must_resume) { |
| 1290 | dev->power.set_active = dev->power.set_active || | 1284 | if (dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) { |
| 1291 | dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND); | 1285 | dev->power.set_active = true; |
| 1292 | dpm_superior_set_must_resume(dev, dev->power.set_active); | 1286 | if (dev->parent && !dev->parent->power.ignore_children) |
| 1287 | dev->parent->power.set_active = true; | ||
| 1288 | } | ||
| 1289 | dpm_superior_set_must_resume(dev); | ||
| 1293 | } | 1290 | } |
| 1294 | 1291 | ||
| 1295 | Complete: | 1292 | Complete: |
| @@ -906,6 +906,7 @@ err_alloc: · 905 unmodified lines | |||
| 906 | kfree(d->wake_buf); | 906 | kfree(d->wake_buf); |
| 907 | kfree(d->mask_buf_def); | 907 | kfree(d->mask_buf_def); |
| 908 | kfree(d->mask_buf); | 908 | kfree(d->mask_buf); |
| 909 | kfree(d->main_status_buf); | ||
| 909 | kfree(d->status_buf); | 910 | kfree(d->status_buf); |
| 910 | kfree(d->status_reg_buf); | 911 | kfree(d->status_reg_buf); |
| 911 | if (d->config_buf) { | 912 | if (d->config_buf) { |
| @@ -981,6 +982,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d) · 69 unmodified lines | |||
| 981 | kfree(d->wake_buf); | 982 | kfree(d->wake_buf); |
| 982 | kfree(d->mask_buf_def); | 983 | kfree(d->mask_buf_def); |
| 983 | kfree(d->mask_buf); | 984 | kfree(d->mask_buf); |
| 985 | kfree(d->main_status_buf); | ||
| 984 | kfree(d->status_reg_buf); | 986 | kfree(d->status_reg_buf); |
| 985 | kfree(d->status_buf); | 987 | kfree(d->status_buf); |
| 986 | if (d->config_buf) { | 988 | if (d->config_buf) { |
| @@ -1127,8 +1127,8 @@ static void vdc_queue_drain(struct vdc_port *port) · 1126 unmodified lines | |||
| 1127 | 1127 | ||
| 1128 | spin_lock_irq(&port->vio.lock); | 1128 | spin_lock_irq(&port->vio.lock); |
| 1129 | port->drain = 0; | 1129 | port->drain = 0; |
| 1130 | blk_mq_unquiesce_queue(q, memflags); | 1130 | blk_mq_unquiesce_queue(q); |
| 1131 | blk_mq_unfreeze_queue(q); | 1131 | blk_mq_unfreeze_queue(q, memflags); |
| 1132 | } | 1132 | } |
| 1133 | 1133 | ||
| 1134 | static void vdc_ldc_reset_timer_work(struct work_struct *work) | 1134 | static void vdc_ldc_reset_timer_work(struct work_struct *work) |
| @@ -1320,6 +1320,10 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, · 1319 unmodified lines | |||
| 1320 | if (opcode == 0xfc01) | 1320 | if (opcode == 0xfc01) |
| 1321 | btintel_pcie_inject_cmd_complete(hdev, opcode); | 1321 | btintel_pcie_inject_cmd_complete(hdev, opcode); |
| 1322 | } | 1322 | } |
| 1323 | /* Firmware raises alive interrupt on HCI_OP_RESET */ | ||
| 1324 | if (opcode == HCI_OP_RESET) | ||
| 1325 | data->gp0_received = false; | ||
| 1326 | |||
| 1323 | hdev->stat.cmd_tx++; | 1327 | hdev->stat.cmd_tx++; |
| 1324 | break; | 1328 | break; |
| 1325 | case HCI_ACLDATA_PKT: | 1329 | case HCI_ACLDATA_PKT: |
| @@ -1357,7 +1361,6 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, · 31 unmodified lines | |||
| 1357 | opcode, btintel_pcie_alivectxt_state2str(old_ctxt), | 1361 | opcode, btintel_pcie_alivectxt_state2str(old_ctxt), |
| 1358 | btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); | 1362 | btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); |
| 1359 | if (opcode == HCI_OP_RESET) { | 1363 | if (opcode == HCI_OP_RESET) { |
| 1360 | data->gp0_received = false; | ||
| 1361 | ret = wait_event_timeout(data->gp0_wait_q, | 1364 | ret = wait_event_timeout(data->gp0_wait_q, |
| 1362 | data->gp0_received, | 1365 | data->gp0_received, |
| 1363 | msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); | 1366 | msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); |
| @@ -657,7 +657,7 @@ static void moxtet_irq_print_chip(struct irq_data *d, struct seq_file *p) · 656 unmodified lines | |||
| 657 | 657 | ||
| 658 | id = moxtet->modules[pos->idx]; | 658 | id = moxtet->modules[pos->idx]; |
| 659 | 659 | ||
| 660 | seq_printf(p, " moxtet-%s.%i#%i", mox_module_name(id), pos->idx, | 660 | seq_printf(p, "moxtet-%s.%i#%i", mox_module_name(id), pos->idx, |
| 661 | pos->bit); | 661 | pos->bit); |
| 662 | } | 662 | } |
| 663 | 663 | ||
| @@ -17,7 +17,8 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | config ARM_AIROHA_SOC_CPUFREQ | 18 | config ARM_AIROHA_SOC_CPUFREQ |
| 19 | tristate "Airoha EN7581 SoC CPUFreq support" | 19 | tristate "Airoha EN7581 SoC CPUFreq support" |
| 20 | depends on (ARCH_AIROHA && OF) || COMPILE_TEST | 20 | depends on ARCH_AIROHA || COMPILE_TEST |
| 21 | depends on OF | ||
| 21 | select PM_OPP | 22 | select PM_OPP |
| 22 | default ARCH_AIROHA | 23 | default ARCH_AIROHA |
| 23 | help | 24 | help |
| @@ -699,7 +699,7 @@ static void amd_pstate_adjust_perf(unsigned int cpu, · 698 unmodified lines | |||
| 699 | if (min_perf < lowest_nonlinear_perf) | 699 | if (min_perf < lowest_nonlinear_perf) |
| 700 | min_perf = lowest_nonlinear_perf; | 700 | min_perf = lowest_nonlinear_perf; |
| 701 | 701 | ||
| 702 | max_perf = cap_perf; | 702 | max_perf = cpudata->max_limit_perf; |
| 703 | if (max_perf < min_perf) | 703 | if (max_perf < min_perf) |
| 704 | max_perf = min_perf; | 704 | max_perf = min_perf; |
| 705 | 705 | ||
| @@ -747,7 +747,6 @@ static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state) · 41 unmodified lines | |||
| 747 | guard(mutex)(&amd_pstate_driver_lock); | 747 | guard(mutex)(&amd_pstate_driver_lock); |
| 748 | 748 | ||
| 749 | ret = amd_pstate_cpu_boost_update(policy, state); | 749 | ret = amd_pstate_cpu_boost_update(policy, state); |
| 750 | policy->boost_enabled = !ret ? state : false; | ||
| 751 | refresh_frequency_limits(policy); | 750 | refresh_frequency_limits(policy); |
| 752 | 751 | ||
| 753 | return ret; | 752 | return ret; |
| @@ -822,25 +821,28 @@ static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata) · 68 unmodified lines | |||
| 822 | 821 | ||
| 823 | static void amd_pstate_update_limits(unsigned int cpu) | 822 | static void amd_pstate_update_limits(unsigned int cpu) |
| 824 | { | 823 | { |
| 825 | struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); | 824 | struct cpufreq_policy *policy = NULL; |
| 826 | struct amd_cpudata *cpudata; | 825 | struct amd_cpudata *cpudata; |
| 827 | u32 prev_high = 0, cur_high = 0; | 826 | u32 prev_high = 0, cur_high = 0; |
| 828 | int ret; | 827 | int ret; |
| 829 | bool highest_perf_changed = false; | 828 | bool highest_perf_changed = false; |
| 830 | 829 | ||
| 830 | if (!amd_pstate_prefcore) | ||
| 831 | return; | ||
| 832 | |||
| 833 | policy = cpufreq_cpu_get(cpu); | ||
| 831 | if (!policy) | 834 | if (!policy) |
| 832 | return; | 835 | return; |
| 833 | 836 | ||
| 834 | cpudata = policy->driver_data; | 837 | cpudata = policy->driver_data; |
| 835 | 838 | ||
| 836 | if (!amd_pstate_prefcore) | ||
| 837 | return; | ||
| 838 | |||
| 839 | guard(mutex)(&amd_pstate_driver_lock); | 839 | guard(mutex)(&amd_pstate_driver_lock); |
| 840 | 840 | ||
| 841 | ret = amd_get_highest_perf(cpu, &cur_high); | 841 | ret = amd_get_highest_perf(cpu, &cur_high); |
| 842 | if (ret) | 842 | if (ret) { |
| 843 | goto free_cpufreq_put; | 843 | cpufreq_cpu_put(policy); |
| 844 | return; | ||
| 845 | } | ||
| 844 | 846 | ||
| 845 | prev_high = READ_ONCE(cpudata->prefcore_ranking); | 847 | prev_high = READ_ONCE(cpudata->prefcore_ranking); |
| 846 | highest_perf_changed = (prev_high != cur_high); | 848 | highest_perf_changed = (prev_high != cur_high); |
| @@ -850,8 +852,6 @@ static void amd_pstate_update_limits(unsigned int cpu) · 3 unmodified lines | |||
| 850 | if (cur_high < CPPC_MAX_PERF) | 852 | if (cur_high < CPPC_MAX_PERF) |
| 851 | sched_set_itmt_core_prio((int)cur_high, cpu); | 853 | sched_set_itmt_core_prio((int)cur_high, cpu); |
| 852 | } | 854 | } |
| 853 | |||
| 854 | free_cpufreq_put: | ||
| 855 | cpufreq_cpu_put(policy); | 855 | cpufreq_cpu_put(policy); |
| 856 | 856 | ||
| 857 | if (!highest_perf_changed) | 857 | if (!highest_perf_changed) |
| @@ -1571,7 +1571,8 @@ static int cpufreq_online(unsigned int cpu) · 1570 unmodified lines | |||
| 1571 | policy->cdev = of_cpufreq_cooling_register(policy); | 1571 | policy->cdev = of_cpufreq_cooling_register(policy); |
| 1572 | 1572 | ||
| 1573 | /* Let the per-policy boost flag mirror the cpufreq_driver boost during init */ | 1573 | /* Let the per-policy boost flag mirror the cpufreq_driver boost during init */ |
| 1574 | if (policy->boost_enabled != cpufreq_boost_enabled()) { | 1574 | if (cpufreq_driver->set_boost && |
| 1575 | policy->boost_enabled != cpufreq_boost_enabled()) { | ||
| 1575 | policy->boost_enabled = cpufreq_boost_enabled(); | 1576 | policy->boost_enabled = cpufreq_boost_enabled(); |
| 1576 | ret = cpufreq_driver->set_boost(policy, policy->boost_enabled); | 1577 | ret = cpufreq_driver->set_boost(policy, policy->boost_enabled); |
| 1577 | if (ret) { | 1578 | if (ret) { |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
| 20 | #include <linux/ccp.h> | 20 | #include <linux/ccp.h> |
| 21 | 21 | ||
| 22 | #include "sev-dev.h" | ||
| 22 | #include "ccp-dev.h" | 23 | #include "ccp-dev.h" |
| 23 | #include "sp-dev.h" | 24 | #include "sp-dev.h" |
| 24 | 25 | ||
| @@ -253,8 +254,12 @@ unlock: · 228 unmodified lines | |||
| 253 | static int __init sp_mod_init(void) | 254 | static int __init sp_mod_init(void) |
| 254 | { | 255 | { |
| 255 | #ifdef CONFIG_X86 | 256 | #ifdef CONFIG_X86 |
| 257 | static bool initialized; | ||
| 256 | int ret; | 258 | int ret; |
| 257 | 259 | ||
| 260 | if (initialized) | ||
| 261 | return 0; | ||
| 262 | |||
| 258 | ret = sp_pci_init(); | 263 | ret = sp_pci_init(); |
| 259 | if (ret) | 264 | if (ret) |
| 260 | return ret; | 265 | return ret; |
| @@ -263,6 +268,8 @@ static int __init sp_mod_init(void) · 2 unmodified lines | |||
| 263 | psp_pci_init(); | 268 | psp_pci_init(); |
| 264 | #endif | 269 | #endif |
| 265 | 270 | ||
| 271 | initialized = true; | ||
| 272 | |||
| 266 | return 0; | 273 | return 0; |
| 267 | #endif | 274 | #endif |
| 268 | 275 | ||
| @@ -279,6 +286,13 @@ static int __init sp_mod_init(void) · 10 unmodified lines | |||
| 279 | return -ENODEV; | 286 | return -ENODEV; |
| 280 | } | 287 | } |
| 281 | 288 | ||
| 289 | #if IS_BUILTIN(CONFIG_KVM_AMD) && IS_ENABLED(CONFIG_KVM_AMD_SEV) | ||
| 290 | int __init sev_module_init(void) | ||
| 291 | { | ||
| 292 | return sp_mod_init(); | ||
| 293 | } | ||
| 294 | #endif | ||
| 295 | |||
| 282 | static void __exit sp_mod_exit(void) | 296 | static void __exit sp_mod_exit(void) |
| 283 | { | 297 | { |
| 284 | #ifdef CONFIG_X86 | 298 | #ifdef CONFIG_X86 |
| @@ -887,7 +887,7 @@ static int tegra_adma_probe(struct platform_device *pdev) · 886 unmodified lines | |||
| 887 | const struct tegra_adma_chip_data *cdata; | 887 | const struct tegra_adma_chip_data *cdata; |
| 888 | struct tegra_adma *tdma; | 888 | struct tegra_adma *tdma; |
| 889 | struct resource *res_page, *res_base; | 889 | struct resource *res_page, *res_base; |
| 890 | int ret, i, page_no; | 890 | int ret, i; |
| 891 | 891 | ||
| 892 | cdata = of_device_get_match_data(&pdev->dev); | 892 | cdata = of_device_get_match_data(&pdev->dev); |
| 893 | if (!cdata) { | 893 | if (!cdata) { |
| @@ -914,9 +914,20 @@ static int tegra_adma_probe(struct platform_device *pdev) · 20 unmodified lines | |||
| 914 | 914 | ||
| 915 | res_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "global"); | 915 | res_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "global"); |
| 916 | if (res_base) { | 916 | if (res_base) { |
| 917 | page_no = (res_page->start - res_base->start) / cdata->ch_base_offset; | 917 | resource_size_t page_offset, page_no; |
| 918 | if (page_no <= 0) | 918 | unsigned int ch_base_offset; |
| 919 | |||
| 920 | if (res_page->start < res_base->start) | ||
| 921 | return -EINVAL; | ||
| 922 | page_offset = res_page->start - res_base->start; | ||
| 923 | ch_base_offset = cdata->ch_base_offset; | ||
| 924 | if (!ch_base_offset) | ||
| 919 | return -EINVAL; | 925 | return -EINVAL; |
| 926 | |||
| 927 | page_no = div_u64(page_offset, ch_base_offset); | ||
| 928 | if (!page_no || page_no > INT_MAX) | ||
| 929 | return -EINVAL; | ||
| 930 | |||
| 920 | tdma->ch_page_no = page_no - 1; | 931 | tdma->ch_page_no = page_no - 1; |
| 921 | tdma->base_addr = devm_ioremap_resource(&pdev->dev, res_base); | 932 | tdma->base_addr = devm_ioremap_resource(&pdev->dev, res_base); |
| 922 | if (IS_ERR(tdma->base_addr)) | 933 | if (IS_ERR(tdma->base_addr)) |
| @@ -106,7 +106,7 @@ config ISCSI_IBFT · 105 unmodified lines | |||
| 106 | select ISCSI_BOOT_SYSFS | 106 | select ISCSI_BOOT_SYSFS |
| 107 | select ISCSI_IBFT_FIND if X86 | 107 | select ISCSI_IBFT_FIND if X86 |
| 108 | depends on ACPI && SCSI && SCSI_LOWLEVEL | 108 | depends on ACPI && SCSI && SCSI_LOWLEVEL |
| 109 | default n | 109 | default n |
| 110 | help | 110 | help |
| 111 | This option enables support for detection and exposing of iSCSI | 111 | This option enables support for detection and exposing of iSCSI |
| 112 | Boot Firmware Table (iBFT) via sysfs to userspace. If you wish to | 112 | Boot Firmware Table (iBFT) via sysfs to userspace. If you wish to |
| @@ -934,13 +934,15 @@ char * __init efi_md_typeattr_format(char *buf, size_t size, · 933 unmodified lines | |||
| 934 | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO | | 934 | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO | |
| 935 | EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP | | 935 | EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP | |
| 936 | EFI_MEMORY_NV | EFI_MEMORY_SP | EFI_MEMORY_CPU_CRYPTO | | 936 | EFI_MEMORY_NV | EFI_MEMORY_SP | EFI_MEMORY_CPU_CRYPTO | |
| 937 | EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE)) | 937 | EFI_MEMORY_MORE_RELIABLE | EFI_MEMORY_HOT_PLUGGABLE | |
| 938 | EFI_MEMORY_RUNTIME)) | ||
| 938 | snprintf(pos, size, "|attr=0x%016llx]", | 939 | snprintf(pos, size, "|attr=0x%016llx]", |
| 939 | (unsigned long long)attr); | 940 | (unsigned long long)attr); |
| 940 | else | 941 | else |
| 941 | snprintf(pos, size, | 942 | snprintf(pos, size, |
| 942 | "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]", | 943 | "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]", |
| 943 | attr & EFI_MEMORY_RUNTIME ? "RUN" : "", | 944 | attr & EFI_MEMORY_RUNTIME ? "RUN" : "", |
| 945 | attr & EFI_MEMORY_HOT_PLUGGABLE ? "HP" : "", | ||
| 944 | attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "", | 946 | attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "", |
| 945 | attr & EFI_MEMORY_CPU_CRYPTO ? "CC" : "", | 947 | attr & EFI_MEMORY_CPU_CRYPTO ? "CC" : "", |
| 946 | attr & EFI_MEMORY_SP ? "SP" : "", | 948 | attr & EFI_MEMORY_SP ? "SP" : "", |
| @@ -25,6 +25,9 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md, · 24 unmodified lines | |||
| 25 | if (md->type != EFI_CONVENTIONAL_MEMORY) | 25 | if (md->type != EFI_CONVENTIONAL_MEMORY) |
| 26 | return 0; | 26 | return 0; |
| 27 | 27 | ||
| 28 | if (md->attribute & EFI_MEMORY_HOT_PLUGGABLE) | ||
| 29 | return 0; | ||
| 30 | |||
| 28 | if (efi_soft_reserve_enabled() && | 31 | if (efi_soft_reserve_enabled() && |
| 29 | (md->attribute & EFI_MEMORY_SP)) | 32 | (md->attribute & EFI_MEMORY_SP)) |
| 30 | return 0; | 33 | return 0; |
| @@ -53,6 +53,9 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, · 52 unmodified lines | |||
| 53 | if (desc->type != EFI_CONVENTIONAL_MEMORY) | 53 | if (desc->type != EFI_CONVENTIONAL_MEMORY) |
| 54 | continue; | 54 | continue; |
| 55 | 55 | ||
| 56 | if (desc->attribute & EFI_MEMORY_HOT_PLUGGABLE) | ||
| 57 | continue; | ||
| 58 | |||
| 56 | if (efi_soft_reserve_enabled() && | 59 | if (efi_soft_reserve_enabled() && |
| 57 | (desc->attribute & EFI_MEMORY_SP)) | 60 | (desc->attribute & EFI_MEMORY_SP)) |
| 58 | continue; | 61 | continue; |
| @@ -310,7 +310,10 @@ static ssize_t ibft_attr_show_nic(void *data, int type, char *buf) · 309 unmodified lines | |||
| 310 | str += sprintf_ipaddr(str, nic->ip_addr); | 310 | str += sprintf_ipaddr(str, nic->ip_addr); |
| 311 | break; | 311 | break; |
| 312 | case ISCSI_BOOT_ETH_SUBNET_MASK: | 312 | case ISCSI_BOOT_ETH_SUBNET_MASK: |
| 313 | val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1)); | 313 | if (nic->subnet_mask_prefix > 32) |
| 314 | val = cpu_to_be32(~0); | ||
| 315 | else | ||
| 316 | val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1)); | ||
| 314 | str += sprintf(str, "%pI4", &val); | 317 | str += sprintf(str, "%pI4", &val); |
| 315 | break; | 318 | break; |
| 316 | case ISCSI_BOOT_ETH_PREFIX_LEN: | 319 | case ISCSI_BOOT_ETH_PREFIX_LEN: |
| @@ -338,6 +338,7 @@ config GPIO_GRANITERAPIDS · 337 unmodified lines | |||
| 338 | 338 | ||
| 339 | config GPIO_GRGPIO | 339 | config GPIO_GRGPIO |
| 340 | tristate "Aeroflex Gaisler GRGPIO support" | 340 | tristate "Aeroflex Gaisler GRGPIO support" |
| 341 | depends on OF || COMPILE_TEST | ||
| 341 | select GPIO_GENERIC | 342 | select GPIO_GENERIC |
| 342 | select IRQ_DOMAIN | 343 | select IRQ_DOMAIN |
| 343 | help | 344 | help |
| @@ -69,6 +69,22 @@ struct bcm_kona_gpio { · 68 unmodified lines | |||
| 69 | struct bcm_kona_gpio_bank { | 69 | struct bcm_kona_gpio_bank { |
| 70 | int id; | 70 | int id; |
| 71 | int irq; | 71 | int irq; |
| 72 | /* | ||
| 73 | * Used to keep track of lock/unlock operations for each GPIO in the | ||
| 74 | * bank. | ||
| 75 | * | ||
| 76 | * All GPIOs are locked by default (see bcm_kona_gpio_reset), and the | ||
| 77 | * unlock count for all GPIOs is 0 by default. Each unlock increments | ||
| 78 | * the counter, and each lock decrements the counter. | ||
| 79 | * | ||
| 80 | * The lock function only locks the GPIO once its unlock counter is | ||
| 81 | * down to 0. This is necessary because the GPIO is unlocked in two | ||
| 82 | * places in this driver: once for requested GPIOs, and once for | ||
| 83 | * requested IRQs. Since it is possible for a GPIO to be requested | ||
| 84 | * as both a GPIO and an IRQ, we need to ensure that we don't lock it | ||
| 85 | * too early. | ||
| 86 | */ | ||
| 87 | u8 gpio_unlock_count[GPIO_PER_BANK]; | ||
| 72 | /* Used in the interrupt handler */ | 88 | /* Used in the interrupt handler */ |
| 73 | struct bcm_kona_gpio *kona_gpio; | 89 | struct bcm_kona_gpio *kona_gpio; |
| 74 | }; | 90 | }; |
| @@ -86,14 +102,24 @@ static void bcm_kona_gpio_lock_gpio(struct bcm_kona_gpio *kona_gpio, · 11 unmodified lines | |||
| 86 | u32 val; | 102 | u32 val; |
| 87 | unsigned long flags; | 103 | unsigned long flags; |
| 88 | int bank_id = GPIO_BANK(gpio); | 104 | int bank_id = GPIO_BANK(gpio); |
| 105 | int bit = GPIO_BIT(gpio); | ||
| 106 | struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id]; | ||
| 89 | 107 | ||
| 90 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); | 108 | if (bank->gpio_unlock_count[bit] == 0) { |
| 109 | dev_err(kona_gpio->gpio_chip.parent, | ||
| 110 | "Unbalanced locks for GPIO %u\n", gpio); | ||
| 111 | return; | ||
| 112 | } | ||
| 91 | 113 | ||
| 92 | val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); | 114 | if (--bank->gpio_unlock_count[bit] == 0) { |
| 93 | val |= BIT(gpio); | 115 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); |
| 94 | bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); | ||
| 95 | 116 | ||
| 96 | raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); | 117 | val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); |
| 118 | val |= BIT(bit); | ||
| 119 | bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); | ||
| 120 | |||
| 121 | raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); | ||
| 122 | } | ||
| 97 | } | 123 | } |
| 98 | 124 | ||
| 99 | static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio, | 125 | static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio, |
| @@ -102,14 +128,20 @@ static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio, · 2 unmodified lines | |||
| 102 | u32 val; | 128 | u32 val; |
| 103 | unsigned long flags; | 129 | unsigned long flags; |
| 104 | int bank_id = GPIO_BANK(gpio); | 130 | int bank_id = GPIO_BANK(gpio); |
| 131 | int bit = GPIO_BIT(gpio); | ||
| 132 | struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id]; | ||
| 105 | 133 | ||
| 106 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); | 134 | if (bank->gpio_unlock_count[bit] == 0) { |
| 135 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); | ||
| 107 | 136 | ||
| 108 | val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); | 137 | val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); |
| 109 | val &= ~BIT(gpio); | 138 | val &= ~BIT(bit); |
| 110 | bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); | 139 | bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); |
| 111 | 140 | ||
| 112 | raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); | 141 | raw_spin_unlock_irqrestore(&kona_gpio->lock, flags); |
| 142 | } | ||
| 143 | |||
| 144 | ++bank->gpio_unlock_count[bit]; | ||
| 113 | } | 145 | } |
| 114 | 146 | ||
| 115 | static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio) | 147 | static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio) |
| @@ -360,6 +392,7 @@ static void bcm_kona_gpio_irq_mask(struct irq_data *d) · 244 unmodified lines | |||
| 360 | 392 | ||
| 361 | kona_gpio = irq_data_get_irq_chip_data(d); | 393 | kona_gpio = irq_data_get_irq_chip_data(d); |
| 362 | reg_base = kona_gpio->reg_base; | 394 | reg_base = kona_gpio->reg_base; |
| 395 | |||
| 363 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); | 396 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); |
| 364 | 397 | ||
| 365 | val = readl(reg_base + GPIO_INT_MASK(bank_id)); | 398 | val = readl(reg_base + GPIO_INT_MASK(bank_id)); |
| @@ -382,6 +415,7 @@ static void bcm_kona_gpio_irq_unmask(struct irq_data *d) · 16 unmodified lines | |||
| 382 | 415 | ||
| 383 | kona_gpio = irq_data_get_irq_chip_data(d); | 416 | kona_gpio = irq_data_get_irq_chip_data(d); |
| 384 | reg_base = kona_gpio->reg_base; | 417 | reg_base = kona_gpio->reg_base; |
| 418 | |||
| 385 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); | 419 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); |
| 386 | 420 | ||
| 387 | val = readl(reg_base + GPIO_INT_MSKCLR(bank_id)); | 421 | val = readl(reg_base + GPIO_INT_MSKCLR(bank_id)); |
| @@ -477,15 +511,26 @@ static void bcm_kona_gpio_irq_handler(struct irq_desc *desc) · 89 unmodified lines | |||
| 477 | static int bcm_kona_gpio_irq_reqres(struct irq_data *d) | 511 | static int bcm_kona_gpio_irq_reqres(struct irq_data *d) |
| 478 | { | 512 | { |
| 479 | struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); | 513 | struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); |
| 514 | unsigned int gpio = d->hwirq; | ||
| 480 | 515 | ||
| 481 | return gpiochip_reqres_irq(&kona_gpio->gpio_chip, d->hwirq); | 516 | /* |
| 517 | * We need to unlock the GPIO before any other operations are performed | ||
| 518 | * on the relevant GPIO configuration registers | ||
| 519 | */ | ||
| 520 | bcm_kona_gpio_unlock_gpio(kona_gpio, gpio); | ||
| 521 | |||
| 522 | return gpiochip_reqres_irq(&kona_gpio->gpio_chip, gpio); | ||
| 482 | } | 523 | } |
| 483 | 524 | ||
| 484 | static void bcm_kona_gpio_irq_relres(struct irq_data *d) | 525 | static void bcm_kona_gpio_irq_relres(struct irq_data *d) |
| 485 | { | 526 | { |
| 486 | struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); | 527 | struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d); |
| 528 | unsigned int gpio = d->hwirq; | ||
| 529 | |||
| 530 | /* Once we no longer use it, lock the GPIO again */ | ||
| 531 | bcm_kona_gpio_lock_gpio(kona_gpio, gpio); | ||
| 487 | 532 | ||
| 488 | gpiochip_relres_irq(&kona_gpio->gpio_chip, d->hwirq); | 533 | gpiochip_relres_irq(&kona_gpio->gpio_chip, gpio); |
| 489 | } | 534 | } |
| 490 | 535 | ||
| 491 | static struct irq_chip bcm_gpio_irq_chip = { | 536 | static struct irq_chip bcm_gpio_irq_chip = { |
| @@ -614,7 +659,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) · 122 unmodified lines | |||
| 614 | bank->irq = platform_get_irq(pdev, i); | 659 | bank->irq = platform_get_irq(pdev, i); |
| 615 | bank->kona_gpio = kona_gpio; | 660 | bank->kona_gpio = kona_gpio; |
| 616 | if (bank->irq < 0) { | 661 | if (bank->irq < 0) { |
| 617 | dev_err(dev, "Couldn't get IRQ for bank %d", i); | 662 | dev_err(dev, "Couldn't get IRQ for bank %d\n", i); |
| 618 | ret = -ENOENT; | 663 | ret = -ENOENT; |
| 619 | goto err_irq_domain; | 664 | goto err_irq_domain; |
| 620 | } | 665 | } |
| @@ -841,25 +841,6 @@ static bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pendin · 840 unmodified lines | |||
| 841 | DECLARE_BITMAP(trigger, MAX_LINE); | 841 | DECLARE_BITMAP(trigger, MAX_LINE); |
| 842 | int ret; | 842 | int ret; |
| 843 | 843 | ||
| 844 | if (chip->driver_data & PCA_PCAL) { | ||
| 845 | /* Read the current interrupt status from the device */ | ||
| 846 | ret = pca953x_read_regs(chip, PCAL953X_INT_STAT, trigger); | ||
| 847 | if (ret) | ||
| 848 | return false; | ||
| 849 | |||
| 850 | /* Check latched inputs and clear interrupt status */ | ||
| 851 | ret = pca953x_read_regs(chip, chip->regs->input, cur_stat); | ||
| 852 | if (ret) | ||
| 853 | return false; | ||
| 854 | |||
| 855 | /* Apply filter for rising/falling edge selection */ | ||
| 856 | bitmap_replace(new_stat, chip->irq_trig_fall, chip->irq_trig_raise, cur_stat, gc->ngpio); | ||
| 857 | |||
| 858 | bitmap_and(pending, new_stat, trigger, gc->ngpio); | ||
| 859 | |||
| 860 | return !bitmap_empty(pending, gc->ngpio); | ||
| 861 | } | ||
| 862 | |||
| 863 | ret = pca953x_read_regs(chip, chip->regs->input, cur_stat); | 844 | ret = pca953x_read_regs(chip, chip->regs->input, cur_stat); |
| 864 | if (ret) | 845 | if (ret) |
| 865 | return false; | 846 | return false; |
| @@ -1028,20 +1028,23 @@ gpio_sim_device_lockup_configfs(struct gpio_sim_device *dev, bool lock) · 1027 unmodified lines | |||
| 1028 | struct configfs_subsystem *subsys = dev->group.cg_subsys; | 1028 | struct configfs_subsystem *subsys = dev->group.cg_subsys; |
| 1029 | struct gpio_sim_bank *bank; | 1029 | struct gpio_sim_bank *bank; |
| 1030 | struct gpio_sim_line *line; | 1030 | struct gpio_sim_line *line; |
| 1031 | struct config_item *item; | ||
| 1031 | 1032 | ||
| 1032 | /* | 1033 | /* |
| 1033 | * The device only needs to depend on leaf line entries. This is | 1034 | * The device only needs to depend on leaf entries. This is |
| 1034 | * sufficient to lock up all the configfs entries that the | 1035 | * sufficient to lock up all the configfs entries that the |
| 1035 | * instantiated, alive device depends on. | 1036 | * instantiated, alive device depends on. |
| 1036 | */ | 1037 | */ |
| 1037 | list_for_each_entry(bank, &dev->bank_list, siblings) { | 1038 | list_for_each_entry(bank, &dev->bank_list, siblings) { |
| 1038 | list_for_each_entry(line, &bank->line_list, siblings) { | 1039 | list_for_each_entry(line, &bank->line_list, siblings) { |
| 1040 | item = line->hog ? &line->hog->item | ||
| 1041 | : &line->group.cg_item; | ||
| 1042 | |||
| 1039 | if (lock) | 1043 | if (lock) |
| 1040 | WARN_ON(configfs_depend_item_unlocked( | 1044 | WARN_ON(configfs_depend_item_unlocked(subsys, |
| 1041 | subsys, &line->group.cg_item)); | 1045 | item)); |
| 1042 | else | 1046 | else |
| 1043 | configfs_undepend_item_unlocked( | 1047 | configfs_undepend_item_unlocked(item); |
| 1044 | &line->group.cg_item); | ||
| 1045 | } | 1048 | } |
| 1046 | } | 1049 | } |
| 1047 | } | 1050 | } |
| @@ -191,7 +191,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d) · 190 unmodified lines | |||
| 191 | [REG_IE][CSB] = STMPE_IDX_IEGPIOR_CSB, | 191 | [REG_IE][CSB] = STMPE_IDX_IEGPIOR_CSB, |
| 192 | [REG_IE][MSB] = STMPE_IDX_IEGPIOR_MSB, | 192 | [REG_IE][MSB] = STMPE_IDX_IEGPIOR_MSB, |
| 193 | }; | 193 | }; |
| 194 | int i, j; | 194 | int ret, i, j; |
| 195 | 195 | ||
| 196 | /* | 196 | /* |
| 197 | * STMPE1600: to be able to get IRQ from pins, | 197 | * STMPE1600: to be able to get IRQ from pins, |
| @@ -199,8 +199,16 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d) · 1 unmodified line | |||
| 199 | * GPSR or GPCR registers | 199 | * GPSR or GPCR registers |
| 200 | */ | 200 | */ |
| 201 | if (stmpe->partnum == STMPE1600) { | 201 | if (stmpe->partnum == STMPE1600) { |
| 202 | stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]); | 202 | ret = stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]); |
| 203 | stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]); | 203 | if (ret < 0) { |
| 204 | dev_err(stmpe->dev, "Failed to read GPMR_LSB: %d\n", ret); | ||
| 205 | goto err; | ||
| 206 | } | ||
| 207 | ret = stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]); | ||
| 208 | if (ret < 0) { | ||
| 209 | dev_err(stmpe->dev, "Failed to read GPMR_CSB: %d\n", ret); | ||
| 210 | goto err; | ||
| 211 | } | ||
| 204 | } | 212 | } |
| 205 | 213 | ||
| 206 | for (i = 0; i < CACHE_NR_REGS; i++) { | 214 | for (i = 0; i < CACHE_NR_REGS; i++) { |
| @@ -222,6 +230,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d) · 15 unmodified lines | |||
| 222 | } | 230 | } |
| 223 | } | 231 | } |
| 224 | 232 | ||
| 233 | err: | ||
| 225 | mutex_unlock(&stmpe_gpio->irq_lock); | 234 | mutex_unlock(&stmpe_gpio->irq_lock); |
| 226 | } | 235 | } |
| 227 | 236 | ||
| @@ -1689,6 +1689,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { · 1688 unmodified lines | |||
| 1689 | .ignore_wake = "PNP0C50:00@8", | 1689 | .ignore_wake = "PNP0C50:00@8", |
| 1690 | }, | 1690 | }, |
| 1691 | }, | 1691 | }, |
| 1692 | { | ||
| 1693 | /* | ||
| 1694 | * Spurious wakeups from GPIO 11 | ||
| 1695 | * Found in BIOS 1.04 | ||
| 1696 | * https://gitlab.freedesktop.org/drm/amd/-/issues/3954 | ||
| 1697 | */ | ||
| 1698 | .matches = { | ||
| 1699 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
| 1700 | DMI_MATCH(DMI_PRODUCT_FAMILY, "Acer Nitro V 14"), | ||
| 1701 | }, | ||
| 1702 | .driver_data = &(struct acpi_gpiolib_dmi_quirk) { | ||
| 1703 | .ignore_interrupt = "AMDI0030:00@11", | ||
| 1704 | }, | ||
| 1705 | }, | ||
| 1692 | {} /* Terminating entry */ | 1706 | {} /* Terminating entry */ |
| 1693 | }; | 1707 | }; |
| 1694 | 1708 | ||
| @@ -904,13 +904,13 @@ int gpiochip_get_ngpios(struct gpio_chip *gc, struct device *dev) · 903 unmodified lines | |||
| 904 | } | 904 | } |
| 905 | 905 | ||
| 906 | if (gc->ngpio == 0) { | 906 | if (gc->ngpio == 0) { |
| 907 | chip_err(gc, "tried to insert a GPIO chip with zero lines\n"); | 907 | dev_err(dev, "tried to insert a GPIO chip with zero lines\n"); |
| 908 | return -EINVAL; | 908 | return -EINVAL; |
| 909 | } | 909 | } |
| 910 | 910 | ||
| 911 | if (gc->ngpio > FASTPATH_NGPIO) | 911 | if (gc->ngpio > FASTPATH_NGPIO) |
| 912 | chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n", | 912 | dev_warn(dev, "line cnt %u is greater than fast path cnt %u\n", |
| 913 | gc->ngpio, FASTPATH_NGPIO); | 913 | gc->ngpio, FASTPATH_NGPIO); |
| 914 | 914 | ||
| 915 | return 0; | 915 | return 0; |
| 916 | } | 916 | } |
| @@ -119,9 +119,11 @@ · 118 unmodified lines | |||
| 119 | * - 3.57.0 - Compute tunneling on GFX10+ | 119 | * - 3.57.0 - Compute tunneling on GFX10+ |
| 120 | * - 3.58.0 - Add GFX12 DCC support | 120 | * - 3.58.0 - Add GFX12 DCC support |
| 121 | * - 3.59.0 - Cleared VRAM | 121 | * - 3.59.0 - Cleared VRAM |
| 122 | * - 3.60.0 - Add AMDGPU_TILING_GFX12_DCC_WRITE_COMPRESS_DISABLE (Vulkan requirement) | ||
| 123 | * - 3.61.0 - Contains fix for RV/PCO compute queues | ||
| 122 | */ | 124 | */ |
| 123 | #define KMS_DRIVER_MAJOR 3 | 125 | #define KMS_DRIVER_MAJOR 3 |
| 124 | #define KMS_DRIVER_MINOR 59 | 126 | #define KMS_DRIVER_MINOR 61 |
| 125 | #define KMS_DRIVER_PATCHLEVEL 0 | 127 | #define KMS_DRIVER_PATCHLEVEL 0 |
| 126 | 128 | ||
| 127 | /* | 129 | /* |
| @@ -3815,9 +3815,10 @@ int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name) · 3814 unmodified lines | |||
| 3815 | if (err == -ENODEV) { | 3815 | if (err == -ENODEV) { |
| 3816 | dev_warn(adev->dev, "cap microcode does not exist, skip\n"); | 3816 | dev_warn(adev->dev, "cap microcode does not exist, skip\n"); |
| 3817 | err = 0; | 3817 | err = 0; |
| 3818 | goto out; | 3818 | } else { |
| 3819 | dev_err(adev->dev, "fail to initialize cap microcode\n"); | ||
| 3819 | } | 3820 | } |
| 3820 | dev_err(adev->dev, "fail to initialize cap microcode\n"); | 3821 | goto out; |
| 3821 | } | 3822 | } |
| 3822 | 3823 | ||
| 3823 | info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP]; | 3824 | info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP]; |
| @@ -309,7 +309,7 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, · 308 unmodified lines | |||
| 309 | mutex_lock(&adev->mman.gtt_window_lock); | 309 | mutex_lock(&adev->mman.gtt_window_lock); |
| 310 | while (src_mm.remaining) { | 310 | while (src_mm.remaining) { |
| 311 | uint64_t from, to, cur_size, tiling_flags; | 311 | uint64_t from, to, cur_size, tiling_flags; |
| 312 | uint32_t num_type, data_format, max_com; | 312 | uint32_t num_type, data_format, max_com, write_compress_disable; |
| 313 | struct dma_fence *next; | 313 | struct dma_fence *next; |
| 314 | 314 | ||
| 315 | /* Never copy more than 256MiB at once to avoid a timeout */ | 315 | /* Never copy more than 256MiB at once to avoid a timeout */ |
| @@ -340,9 +340,13 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, · 24 unmodified lines | |||
| 340 | max_com = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_MAX_COMPRESSED_BLOCK); | 340 | max_com = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_MAX_COMPRESSED_BLOCK); |
| 341 | num_type = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_NUMBER_TYPE); | 341 | num_type = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_NUMBER_TYPE); |
| 342 | data_format = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_DATA_FORMAT); | 342 | data_format = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_DATA_FORMAT); |
| 343 | write_compress_disable = | ||
| 344 | AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_WRITE_COMPRESS_DISABLE); | ||
| 343 | copy_flags |= (AMDGPU_COPY_FLAGS_SET(MAX_COMPRESSED, max_com) | | 345 | copy_flags |= (AMDGPU_COPY_FLAGS_SET(MAX_COMPRESSED, max_com) | |
| 344 | AMDGPU_COPY_FLAGS_SET(NUMBER_TYPE, num_type) | | 346 | AMDGPU_COPY_FLAGS_SET(NUMBER_TYPE, num_type) | |
| 345 | AMDGPU_COPY_FLAGS_SET(DATA_FORMAT, data_format)); | 347 | AMDGPU_COPY_FLAGS_SET(DATA_FORMAT, data_format) | |
| 348 | AMDGPU_COPY_FLAGS_SET(WRITE_COMPRESS_DISABLE, | ||
| 349 | write_compress_disable)); | ||
| 346 | } | 350 | } |
| 347 | 351 | ||
| 348 | r = amdgpu_copy_buffer(ring, from, to, cur_size, resv, | 352 | r = amdgpu_copy_buffer(ring, from, to, cur_size, resv, |
| @@ -119,6 +119,8 @@ struct amdgpu_copy_mem { · 118 unmodified lines | |||
| 119 | #define AMDGPU_COPY_FLAGS_NUMBER_TYPE_MASK 0x07 | 119 | #define AMDGPU_COPY_FLAGS_NUMBER_TYPE_MASK 0x07 |
| 120 | #define AMDGPU_COPY_FLAGS_DATA_FORMAT_SHIFT 8 | 120 | #define AMDGPU_COPY_FLAGS_DATA_FORMAT_SHIFT 8 |
| 121 | #define AMDGPU_COPY_FLAGS_DATA_FORMAT_MASK 0x3f | 121 | #define AMDGPU_COPY_FLAGS_DATA_FORMAT_MASK 0x3f |
| 122 | #define AMDGPU_COPY_FLAGS_WRITE_COMPRESS_DISABLE_SHIFT 14 | ||
| 123 | #define AMDGPU_COPY_FLAGS_WRITE_COMPRESS_DISABLE_MASK 0x1 | ||
| 122 | 124 | ||
| 123 | #define AMDGPU_COPY_FLAGS_SET(field, value) \ | 125 | #define AMDGPU_COPY_FLAGS_SET(field, value) \ |
| 124 | (((__u32)(value) & AMDGPU_COPY_FLAGS_##field##_MASK) << AMDGPU_COPY_FLAGS_##field##_SHIFT) | 126 | (((__u32)(value) & AMDGPU_COPY_FLAGS_##field##_MASK) << AMDGPU_COPY_FLAGS_##field##_SHIFT) |
| @@ -7437,6 +7437,38 @@ static void gfx_v9_0_ring_emit_cleaner_shader(struct amdgpu_ring *ring) · 7436 unmodified lines | |||
| 7437 | amdgpu_ring_write(ring, 0); /* RESERVED field, programmed to zero */ | 7437 | amdgpu_ring_write(ring, 0); /* RESERVED field, programmed to zero */ |
| 7438 | } | 7438 | } |
| 7439 | 7439 | ||
| 7440 | static void gfx_v9_0_ring_begin_use_compute(struct amdgpu_ring *ring) | ||
| 7441 | { | ||
| 7442 | struct amdgpu_device *adev = ring->adev; | ||
| 7443 | struct amdgpu_ip_block *gfx_block = | ||
| 7444 | amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GFX); | ||
| 7445 | |||
| 7446 | amdgpu_gfx_enforce_isolation_ring_begin_use(ring); | ||
| 7447 | |||
| 7448 | /* Raven and PCO APUs seem to have stability issues | ||
| 7449 | * with compute and gfxoff and gfx pg. Disable gfx pg during | ||
| 7450 | * submission and allow again afterwards. | ||
| 7451 | */ | ||
| 7452 | if (gfx_block && amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 1, 0)) | ||
| 7453 | gfx_v9_0_set_powergating_state(gfx_block, AMD_PG_STATE_UNGATE); | ||
| 7454 | } | ||
| 7455 | |||
| 7456 | static void gfx_v9_0_ring_end_use_compute(struct amdgpu_ring *ring) | ||
| 7457 | { | ||
| 7458 | struct amdgpu_device *adev = ring->adev; | ||
| 7459 | struct amdgpu_ip_block *gfx_block = | ||
| 7460 | amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GFX); | ||
| 7461 | |||
| 7462 | /* Raven and PCO APUs seem to have stability issues | ||
| 7463 | * with compute and gfxoff and gfx pg. Disable gfx pg during | ||
| 7464 | * submission and allow again afterwards. | ||
| 7465 | */ | ||
| 7466 | if (gfx_block && amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 1, 0)) | ||
| 7467 | gfx_v9_0_set_powergating_state(gfx_block, AMD_PG_STATE_GATE); | ||
| 7468 | |||
| 7469 | amdgpu_gfx_enforce_isolation_ring_end_use(ring); | ||
| 7470 | } | ||
| 7471 | |||
| 7440 | static const struct amd_ip_funcs gfx_v9_0_ip_funcs = { | 7472 | static const struct amd_ip_funcs gfx_v9_0_ip_funcs = { |
| 7441 | .name = "gfx_v9_0", | 7473 | .name = "gfx_v9_0", |
| 7442 | .early_init = gfx_v9_0_early_init, | 7474 | .early_init = gfx_v9_0_early_init, |
| @@ -7613,8 +7645,8 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = { · 170 unmodified lines | |||
| 7613 | .emit_wave_limit = gfx_v9_0_emit_wave_limit, | 7645 | .emit_wave_limit = gfx_v9_0_emit_wave_limit, |
| 7614 | .reset = gfx_v9_0_reset_kcq, | 7646 | .reset = gfx_v9_0_reset_kcq, |
| 7615 | .emit_cleaner_shader = gfx_v9_0_ring_emit_cleaner_shader, | 7647 | .emit_cleaner_shader = gfx_v9_0_ring_emit_cleaner_shader, |
| 7616 | .begin_use = amdgpu_gfx_enforce_isolation_ring_begin_use, | 7648 | .begin_use = gfx_v9_0_ring_begin_use_compute, |
| 7617 | .end_use = amdgpu_gfx_enforce_isolation_ring_end_use, | 7649 | .end_use = gfx_v9_0_ring_end_use_compute, |
| 7618 | }; | 7650 | }; |
| 7619 | 7651 | ||
| 7620 | static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = { | 7652 | static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = { |
| @@ -1741,11 +1741,12 @@ static void sdma_v7_0_emit_copy_buffer(struct amdgpu_ib *ib, · 1740 unmodified lines | |||
| 1741 | uint32_t byte_count, | 1741 | uint32_t byte_count, |
| 1742 | uint32_t copy_flags) | 1742 | uint32_t copy_flags) |
| 1743 | { | 1743 | { |
| 1744 | uint32_t num_type, data_format, max_com; | 1744 | uint32_t num_type, data_format, max_com, write_cm; |
| 1745 | 1745 | ||
| 1746 | max_com = AMDGPU_COPY_FLAGS_GET(copy_flags, MAX_COMPRESSED); | 1746 | max_com = AMDGPU_COPY_FLAGS_GET(copy_flags, MAX_COMPRESSED); |
| 1747 | data_format = AMDGPU_COPY_FLAGS_GET(copy_flags, DATA_FORMAT); | 1747 | data_format = AMDGPU_COPY_FLAGS_GET(copy_flags, DATA_FORMAT); |
| 1748 | num_type = AMDGPU_COPY_FLAGS_GET(copy_flags, NUMBER_TYPE); | 1748 | num_type = AMDGPU_COPY_FLAGS_GET(copy_flags, NUMBER_TYPE); |
| 1749 | write_cm = AMDGPU_COPY_FLAGS_GET(copy_flags, WRITE_COMPRESS_DISABLE) ? 2 : 1; | ||
| 1749 | 1750 | ||
| 1750 | ib->ptr[ib->length_dw++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_COPY) | | 1751 | ib->ptr[ib->length_dw++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_COPY) | |
| 1751 | SDMA_PKT_COPY_LINEAR_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) | | 1752 | SDMA_PKT_COPY_LINEAR_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) | |
| @@ -1762,7 +1763,7 @@ static void sdma_v7_0_emit_copy_buffer(struct amdgpu_ib *ib, · 10 unmodified lines | |||
| 1762 | if ((copy_flags & (AMDGPU_COPY_FLAGS_READ_DECOMPRESSED | AMDGPU_COPY_FLAGS_WRITE_COMPRESSED))) | 1763 | if ((copy_flags & (AMDGPU_COPY_FLAGS_READ_DECOMPRESSED | AMDGPU_COPY_FLAGS_WRITE_COMPRESSED))) |
| 1763 | ib->ptr[ib->length_dw++] = SDMA_DCC_DATA_FORMAT(data_format) | SDMA_DCC_NUM_TYPE(num_type) | | 1764 | ib->ptr[ib->length_dw++] = SDMA_DCC_DATA_FORMAT(data_format) | SDMA_DCC_NUM_TYPE(num_type) | |
| 1764 | ((copy_flags & AMDGPU_COPY_FLAGS_READ_DECOMPRESSED) ? SDMA_DCC_READ_CM(2) : 0) | | 1765 | ((copy_flags & AMDGPU_COPY_FLAGS_READ_DECOMPRESSED) ? SDMA_DCC_READ_CM(2) : 0) | |
| 1765 | ((copy_flags & AMDGPU_COPY_FLAGS_WRITE_COMPRESSED) ? SDMA_DCC_WRITE_CM(1) : 0) | | 1766 | ((copy_flags & AMDGPU_COPY_FLAGS_WRITE_COMPRESSED) ? SDMA_DCC_WRITE_CM(write_cm) : 0) | |
| 1766 | SDMA_DCC_MAX_COM(max_com) | SDMA_DCC_MAX_UCOM(1); | 1767 | SDMA_DCC_MAX_COM(max_com) | SDMA_DCC_MAX_UCOM(1); |
| 1767 | else | 1768 | else |
| 1768 | ib->ptr[ib->length_dw++] = 0; | 1769 | ib->ptr[ib->length_dw++] = 0; |
| @@ -4121,7 +4121,8 @@ static const uint32_t cwsr_trap_gfx12_hex[] = { · 4120 unmodified lines | |||
| 4121 | 0x0000ffff, 0x8bfe7e7e, | 4121 | 0x0000ffff, 0x8bfe7e7e, |
| 4122 | 0x8bea6a6a, 0xb97af804, | 4122 | 0x8bea6a6a, 0xb97af804, |
| 4123 | 0xbe804ec2, 0xbf94fffe, | 4123 | 0xbe804ec2, 0xbf94fffe, |
| 4124 | 0xbe804a6c, 0xbfb10000, | 4124 | 0xbe804a6c, 0xbe804ec2, |
| 4125 | 0xbf94fffe, 0xbfb10000, | ||
| 4125 | 0xbf9f0000, 0xbf9f0000, | 4126 | 0xbf9f0000, 0xbf9f0000, |
| 4126 | 0xbf9f0000, 0xbf9f0000, | 4127 | 0xbf9f0000, 0xbf9f0000, |
| 4127 | 0xbf9f0000, 0x00000000, | 4128 | 0xbf9f0000, 0x00000000, |
| @@ -1049,6 +1049,10 @@ L_SKIP_BARRIER_RESTORE: · 1048 unmodified lines | |||
| 1049 | s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution | 1049 | s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution |
| 1050 | 1050 | ||
| 1051 | L_END_PGM: | 1051 | L_END_PGM: |
| 1052 | // Make sure that no wave of the workgroup can exit the trap handler | ||
| 1053 | // before the workgroup barrier state is saved. | ||
| 1054 | s_barrier_signal -2 | ||
| 1055 | s_barrier_wait -2 | ||
| 1052 | s_endpgm_saved | 1056 | s_endpgm_saved |
| 1053 | end | 1057 | end |
| 1054 | 1058 | ||
| @@ -300,7 +300,7 @@ static int init_user_queue(struct process_queue_manager *pqm, · 299 unmodified lines | |||
| 300 | return 0; | 300 | return 0; |
| 301 | 301 | ||
| 302 | free_gang_ctx_bo: | 302 | free_gang_ctx_bo: |
| 303 | amdgpu_amdkfd_free_gtt_mem(dev->adev, (*q)->gang_ctx_bo); | 303 | amdgpu_amdkfd_free_gtt_mem(dev->adev, &(*q)->gang_ctx_bo); |
| 304 | cleanup: | 304 | cleanup: |
| 305 | uninit_queue(*q); | 305 | uninit_queue(*q); |
| 306 | *q = NULL; | 306 | *q = NULL; |
| @@ -2133,7 +2133,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c · 2132 unmodified lines | |||
| 2133 | 2133 | ||
| 2134 | dc_enable_stereo(dc, context, dc_streams, context->stream_count); | 2134 | dc_enable_stereo(dc, context, dc_streams, context->stream_count); |
| 2135 | 2135 | ||
| 2136 | if (context->stream_count > get_seamless_boot_stream_count(context) || | 2136 | if (get_seamless_boot_stream_count(context) == 0 || |
| 2137 | context->stream_count == 0) { | 2137 | context->stream_count == 0) { |
| 2138 | /* Must wait for no flips to be pending before doing optimize bw */ | 2138 | /* Must wait for no flips to be pending before doing optimize bw */ |
| 2139 | hwss_wait_for_no_pipes_pending(dc, context); | 2139 | hwss_wait_for_no_pipes_pending(dc, context); |
| @@ -63,8 +63,7 @@ void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv, · 62 unmodified lines | |||
| 63 | 63 | ||
| 64 | bool should_use_dmub_lock(struct dc_link *link) | 64 | bool should_use_dmub_lock(struct dc_link *link) |
| 65 | { | 65 | { |
| 66 | if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 || | 66 | if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) |
| 67 | link->psr_settings.psr_version == DC_PSR_VERSION_1) | ||
| 68 | return true; | 67 | return true; |
| 69 | 68 | ||
| 70 | if (link->replay_settings.replay_feature_enabled) | 69 | if (link->replay_settings.replay_feature_enabled) |
| @@ -29,11 +29,15 @@ dml_ccflags := $(CC_FLAGS_FPU) · 28 unmodified lines | |||
| 29 | dml_rcflags := $(CC_FLAGS_NO_FPU) | 29 | dml_rcflags := $(CC_FLAGS_NO_FPU) |
| 30 | 30 | ||
| 31 | ifneq ($(CONFIG_FRAME_WARN),0) | 31 | ifneq ($(CONFIG_FRAME_WARN),0) |
| 32 | ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) | 32 | ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) |
| 33 | frame_warn_flag := -Wframe-larger-than=3072 | 33 | frame_warn_limit := 3072 |
| 34 | else | 34 | else |
| 35 | frame_warn_flag := -Wframe-larger-than=2048 | 35 | frame_warn_limit := 2048 |
| 36 | endif | 36 | endif |
| 37 | |||
| 38 | ifeq ($(call test-lt, $(CONFIG_FRAME_WARN), $(frame_warn_limit)),y) | ||
| 39 | frame_warn_flag := -Wframe-larger-than=$(frame_warn_limit) | ||
| 40 | endif | ||
| 37 | endif | 41 | endif |
| 38 | 42 | ||
| 39 | CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) | 43 | CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) |
| @@ -28,15 +28,19 @@ dml2_ccflags := $(CC_FLAGS_FPU) · 27 unmodified lines | |||
| 28 | dml2_rcflags := $(CC_FLAGS_NO_FPU) | 28 | dml2_rcflags := $(CC_FLAGS_NO_FPU) |
| 29 | 29 | ||
| 30 | ifneq ($(CONFIG_FRAME_WARN),0) | 30 | ifneq ($(CONFIG_FRAME_WARN),0) |
| 31 | ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) | 31 | ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) |
| 32 | ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy) | 32 | ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy) |
| 33 | frame_warn_flag := -Wframe-larger-than=4096 | 33 | frame_warn_limit := 4096 |
| 34 | else | 34 | else |
| 35 | frame_warn_flag := -Wframe-larger-than=3072 | 35 | frame_warn_limit := 3072 |
| 36 | endif | 36 | endif |
| 37 | else | 37 | else |
| 38 | frame_warn_flag := -Wframe-larger-than=2048 | 38 | frame_warn_limit := 2048 |
| 39 | endif | 39 | endif |
| 40 | |||
| 41 | ifeq ($(call test-lt, $(CONFIG_FRAME_WARN), $(frame_warn_limit)),y) | ||
| 42 | frame_warn_flag := -Wframe-larger-than=$(frame_warn_limit) | ||
| 43 | endif | ||
| 40 | endif | 44 | endif |
| 41 | 45 | ||
| 42 | subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2 | 46 | subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2 |
| @@ -1017,7 +1017,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s · 1016 unmodified lines | |||
| 1017 | if (disp_cfg_stream_location < 0) | 1017 | if (disp_cfg_stream_location < 0) |
| 1018 | disp_cfg_stream_location = dml_dispcfg->num_streams++; | 1018 | disp_cfg_stream_location = dml_dispcfg->num_streams++; |
| 1019 | 1019 | ||
| 1020 | ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__); | 1020 | ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__); |
| 1021 | populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx); | 1021 | populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx); |
| 1022 | adjust_dml21_hblank_timing_config_from_pipe_ctx(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, &context->res_ctx.pipe_ctx[stream_index]); | 1022 | adjust_dml21_hblank_timing_config_from_pipe_ctx(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, &context->res_ctx.pipe_ctx[stream_index]); |
| 1023 | populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]); | 1023 | populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]); |
| @@ -1042,7 +1042,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s · 18 unmodified lines | |||
| 1042 | if (disp_cfg_plane_location < 0) | 1042 | if (disp_cfg_plane_location < 0) |
| 1043 | disp_cfg_plane_location = dml_dispcfg->num_planes++; | 1043 | disp_cfg_plane_location = dml_dispcfg->num_planes++; |
| 1044 | 1044 | ||
| 1045 | ASSERT(disp_cfg_plane_location >= 0 && disp_cfg_plane_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__); | 1045 | ASSERT(disp_cfg_plane_location >= 0 && disp_cfg_plane_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__); |
| 1046 | 1046 | ||
| 1047 | populate_dml21_surface_config_from_plane_state(in_dc, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location].surface, context->stream_status[stream_index].plane_states[plane_index]); | 1047 | populate_dml21_surface_config_from_plane_state(in_dc, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location].surface, context->stream_status[stream_index].plane_states[plane_index]); |
| 1048 | populate_dml21_plane_config_from_plane_state(dml_ctx, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->stream_status[stream_index].plane_states[plane_index], context, stream_index); | 1048 | populate_dml21_plane_config_from_plane_state(dml_ctx, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->stream_status[stream_index].plane_states[plane_index], context, stream_index); |
| @@ -786,7 +786,7 @@ static void populate_dml_output_cfg_from_stream_state(struct dml_output_cfg_st * · 785 unmodified lines | |||
| 786 | case SIGNAL_TYPE_DISPLAY_PORT_MST: | 786 | case SIGNAL_TYPE_DISPLAY_PORT_MST: |
| 787 | case SIGNAL_TYPE_DISPLAY_PORT: | 787 | case SIGNAL_TYPE_DISPLAY_PORT: |
| 788 | out->OutputEncoder[location] = dml_dp; | 788 | out->OutputEncoder[location] = dml_dp; |
| 789 | if (dml2->v20.scratch.hpo_stream_to_link_encoder_mapping[location] != -1) | 789 | if (location < MAX_HPO_DP2_ENCODERS && dml2->v20.scratch.hpo_stream_to_link_encoder_mapping[location] != -1) |
| 790 | out->OutputEncoder[dml2->v20.scratch.hpo_stream_to_link_encoder_mapping[location]] = dml_dp2p0; | 790 | out->OutputEncoder[dml2->v20.scratch.hpo_stream_to_link_encoder_mapping[location]] = dml_dp2p0; |
| 791 | break; | 791 | break; |
| 792 | case SIGNAL_TYPE_EDP: | 792 | case SIGNAL_TYPE_EDP: |
| @@ -1343,7 +1343,7 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat · 550 unmodified lines | |||
| 1343 | if (disp_cfg_stream_location < 0) | 1343 | if (disp_cfg_stream_location < 0) |
| 1344 | disp_cfg_stream_location = dml_dispcfg->num_timings++; | 1344 | disp_cfg_stream_location = dml_dispcfg->num_timings++; |
| 1345 | 1345 | ||
| 1346 | ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__); | 1346 | ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__); |
| 1347 | 1347 | ||
| 1348 | populate_dml_timing_cfg_from_stream_state(&dml_dispcfg->timing, disp_cfg_stream_location, context->streams[i]); | 1348 | populate_dml_timing_cfg_from_stream_state(&dml_dispcfg->timing, disp_cfg_stream_location, context->streams[i]); |
| 1349 | populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_stream_location, context->streams[i], current_pipe_context, dml2); | 1349 | populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_stream_location, context->streams[i], current_pipe_context, dml2); |
| @@ -1383,7 +1383,7 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat · 33 unmodified lines | |||
| 1383 | if (disp_cfg_plane_location < 0) | 1383 | if (disp_cfg_plane_location < 0) |
| 1384 | disp_cfg_plane_location = dml_dispcfg->num_surfaces++; | 1384 | disp_cfg_plane_location = dml_dispcfg->num_surfaces++; |
| 1385 | 1385 | ||
| 1386 | ASSERT(disp_cfg_plane_location >= 0 && disp_cfg_plane_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__); | 1386 | ASSERT(disp_cfg_plane_location >= 0 && disp_cfg_plane_location < __DML2_WRAPPER_MAX_STREAMS_PLANES__); |
| 1387 | 1387 | ||
| 1388 | populate_dml_surface_cfg_from_plane_state(dml2->v20.dml_core_ctx.project, &dml_dispcfg->surface, disp_cfg_plane_location, context->stream_status[i].plane_states[j]); | 1388 | populate_dml_surface_cfg_from_plane_state(dml2->v20.dml_core_ctx.project, &dml_dispcfg->surface, disp_cfg_plane_location, context->stream_status[i].plane_states[j]); |
| 1389 | populate_dml_plane_cfg_from_plane_state( | 1389 | populate_dml_plane_cfg_from_plane_state( |
| @@ -129,7 +129,8 @@ bool hubbub3_program_watermarks( · 128 unmodified lines | |||
| 129 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, | 129 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, |
| 130 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF); | 130 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF); |
| 131 | 131 | ||
| 132 | hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); | 132 | if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter) |
| 133 | hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); | ||
| 133 | 134 | ||
| 134 | return wm_pending; | 135 | return wm_pending; |
| 135 | } | 136 | } |
| @@ -750,7 +750,8 @@ static bool hubbub31_program_watermarks( · 749 unmodified lines | |||
| 750 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, | 750 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, |
| 751 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);*/ | 751 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);*/ |
| 752 | 752 | ||
| 753 | hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); | 753 | if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter) |
| 754 | hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); | ||
| 754 | return wm_pending; | 755 | return wm_pending; |
| 755 | } | 756 | } |
| 756 | 757 | ||
| @@ -786,7 +786,8 @@ static bool hubbub32_program_watermarks( · 785 unmodified lines | |||
| 786 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, | 786 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, |
| 787 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);*/ | 787 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);*/ |
| 788 | 788 | ||
| 789 | hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); | 789 | if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter) |
| 790 | hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); | ||
| 790 | 791 | ||
| 791 | hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); | 792 | hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); |
| 792 | 793 | ||
| @@ -326,7 +326,8 @@ static bool hubbub35_program_watermarks( · 325 unmodified lines | |||
| 326 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/ | 326 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/ |
| 327 | REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF); | 327 | REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF); |
| 328 | 328 | ||
| 329 | hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); | 329 | if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter) |
| 330 | hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); | ||
| 330 | 331 | ||
| 331 | hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); | 332 | hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow); |
| 332 | 333 | ||
| @@ -500,6 +500,8 @@ void hubp3_init(struct hubp *hubp) · 499 unmodified lines | |||
| 500 | //hubp[i].HUBPREQ_DEBUG.HUBPREQ_DEBUG[26] = 1; | 500 | //hubp[i].HUBPREQ_DEBUG.HUBPREQ_DEBUG[26] = 1; |
| 501 | REG_WRITE(HUBPREQ_DEBUG, 1 << 26); | 501 | REG_WRITE(HUBPREQ_DEBUG, 1 << 26); |
| 502 | 502 | ||
| 503 | REG_UPDATE(DCHUBP_CNTL, HUBP_TTU_DISABLE, 0); | ||
| 504 | |||
| 503 | hubp_reset(hubp); | 505 | hubp_reset(hubp); |
| 504 | } | 506 | } |
| 505 | 507 | ||
| @@ -168,6 +168,8 @@ void hubp32_init(struct hubp *hubp) · 167 unmodified lines | |||
| 168 | { | 168 | { |
| 169 | struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); | 169 | struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); |
| 170 | REG_WRITE(HUBPREQ_DEBUG_DB, 1 << 8); | 170 | REG_WRITE(HUBPREQ_DEBUG_DB, 1 << 8); |
| 171 | |||
| 172 | REG_UPDATE(DCHUBP_CNTL, HUBP_TTU_DISABLE, 0); | ||
| 171 | } | 173 | } |
| 172 | static struct hubp_funcs dcn32_hubp_funcs = { | 174 | static struct hubp_funcs dcn32_hubp_funcs = { |
| 173 | .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer, | 175 | .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer, |
| @@ -236,7 +236,8 @@ void dcn35_init_hw(struct dc *dc) · 235 unmodified lines | |||
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | hws->funcs.init_pipes(dc, dc->current_state); | 238 | hws->funcs.init_pipes(dc, dc->current_state); |
| 239 | if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) | 239 | if (dc->res_pool->hubbub->funcs->allow_self_refresh_control && |
| 240 | !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter) | ||
| 240 | dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, | 241 | dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, |
| 241 | !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter); | 242 | !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter); |
| 242 | } | 243 | } |
| @@ -78,7 +78,7 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, · 77 unmodified lines | |||
| 78 | int ret = 0; | 78 | int ret = 0; |
| 79 | const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; | 79 | const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; |
| 80 | enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON; | 80 | enum ip_power_state pwr_state = gate ? POWER_STATE_OFF : POWER_STATE_ON; |
| 81 | bool is_vcn = (block_type == AMD_IP_BLOCK_TYPE_UVD || block_type == AMD_IP_BLOCK_TYPE_VCN); | 81 | bool is_vcn = block_type == AMD_IP_BLOCK_TYPE_VCN; |
| 82 | 82 | ||
| 83 | if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state && | 83 | if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state && |
| 84 | (!is_vcn || adev->vcn.num_vcn_inst == 1)) { | 84 | (!is_vcn || adev->vcn.num_vcn_inst == 1)) { |
| @@ -612,7 +612,8 @@ static int smu_sys_set_pp_table(void *handle, · 611 unmodified lines | |||
| 612 | return -EIO; | 612 | return -EIO; |
| 613 | } | 613 | } |
| 614 | 614 | ||
| 615 | if (!smu_table->hardcode_pptable) { | 615 | if (!smu_table->hardcode_pptable || smu_table->power_play_table_size < size) { |
| 616 | kfree(smu_table->hardcode_pptable); | ||
| 616 | smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL); | 617 | smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL); |
| 617 | if (!smu_table->hardcode_pptable) | 618 | if (!smu_table->hardcode_pptable) |
| 618 | return -ENOMEM; | 619 | return -ENOMEM; |
| @@ -160,6 +160,10 @@ static int komeda_wb_connector_add(struct komeda_kms_dev *kms, · 159 unmodified lines | |||
| 160 | formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl, | 160 | formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl, |
| 161 | kwb_conn->wb_layer->layer_type, | 161 | kwb_conn->wb_layer->layer_type, |
| 162 | &n_formats); | 162 | &n_formats); |
| 163 | if (!formats) { | ||
| 164 | kfree(kwb_conn); | ||
| 165 | return -ENOMEM; | ||
| 166 | } | ||
| 163 | 167 | ||
| 164 | err = drm_writeback_connector_init(&kms->base, wb_conn, | 168 | err = drm_writeback_connector_init(&kms->base, wb_conn, |
| 165 | &komeda_wb_connector_funcs, | 169 | &komeda_wb_connector_funcs, |
| @@ -195,7 +195,7 @@ static bool __ast_dp_wait_enable(struct ast_device *ast, bool enabled) · 194 unmodified lines | |||
| 195 | if (enabled) | 195 | if (enabled) |
| 196 | vgacrdf_test |= AST_IO_VGACRDF_DP_VIDEO_ENABLE; | 196 | vgacrdf_test |= AST_IO_VGACRDF_DP_VIDEO_ENABLE; |
| 197 | 197 | ||
| 198 | for (i = 0; i < 200; ++i) { | 198 | for (i = 0; i < 1000; ++i) { |
| 199 | if (i) | 199 | if (i) |
| 200 | mdelay(1); | 200 | mdelay(1); |
| 201 | vgacrdf = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xdf, | 201 | vgacrdf = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xdf, |
| @@ -311,16 +311,6 @@ void drm_dp_cec_attach(struct drm_dp_aux *aux, u16 source_physical_address) · 310 unmodified lines | |||
| 311 | if (!aux->transfer) | 311 | if (!aux->transfer) |
| 312 | return; | 312 | return; |
| 313 | 313 | ||
| 314 | #ifndef CONFIG_MEDIA_CEC_RC | ||
| 315 | /* | ||
| 316 | * CEC_CAP_RC is part of CEC_CAP_DEFAULTS, but it is stripped by | ||
| 317 | * cec_allocate_adapter() if CONFIG_MEDIA_CEC_RC is undefined. | ||
| 318 | * | ||
| 319 | * Do this here as well to ensure the tests against cec_caps are | ||
| 320 | * correct. | ||
| 321 | */ | ||
| 322 | cec_caps &= ~CEC_CAP_RC; | ||
| 323 | #endif | ||
| 324 | cancel_delayed_work_sync(&aux->cec.unregister_work); | 314 | cancel_delayed_work_sync(&aux->cec.unregister_work); |
| 325 | 315 | ||
| 326 | mutex_lock(&aux->cec.lock); | 316 | mutex_lock(&aux->cec.lock); |
| @@ -337,7 +327,9 @@ void drm_dp_cec_attach(struct drm_dp_aux *aux, u16 source_physical_address) · 10 unmodified lines | |||
| 337 | num_las = CEC_MAX_LOG_ADDRS; | 327 | num_las = CEC_MAX_LOG_ADDRS; |
| 338 | 328 | ||
| 339 | if (aux->cec.adap) { | 329 | if (aux->cec.adap) { |
| 340 | if (aux->cec.adap->capabilities == cec_caps && | 330 | /* Check if the adapter properties have changed */ |
| 331 | if ((aux->cec.adap->capabilities & CEC_CAP_MONITOR_ALL) == | ||
| 332 | (cec_caps & CEC_CAP_MONITOR_ALL) && | ||
| 341 | aux->cec.adap->available_log_addrs == num_las) { | 333 | aux->cec.adap->available_log_addrs == num_las) { |
| 342 | /* Unchanged, so just set the phys addr */ | 334 | /* Unchanged, so just set the phys addr */ |
| 343 | cec_s_phys_addr(aux->cec.adap, source_physical_address, false); | 335 | cec_s_phys_addr(aux->cec.adap, source_physical_address, false); |
| @@ -2544,7 +2544,7 @@ u8 drm_dp_dsc_sink_bpp_incr(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]) · 2543 unmodified lines | |||
| 2544 | { | 2544 | { |
| 2545 | u8 bpp_increment_dpcd = dsc_dpcd[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT]; | 2545 | u8 bpp_increment_dpcd = dsc_dpcd[DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT]; |
| 2546 | 2546 | ||
| 2547 | switch (bpp_increment_dpcd) { | 2547 | switch (bpp_increment_dpcd & DP_DSC_BITS_PER_PIXEL_MASK) { |
| 2548 | case DP_DSC_BITS_PER_PIXEL_1_16: | 2548 | case DP_DSC_BITS_PER_PIXEL_1_16: |
| 2549 | return 16; | 2549 | return 16; |
| 2550 | case DP_DSC_BITS_PER_PIXEL_1_8: | 2550 | case DP_DSC_BITS_PER_PIXEL_1_8: |
| @@ -4,6 +4,8 @@ config DRM_HISI_HIBMC · 3 unmodified lines | |||
| 4 | depends on DRM && PCI | 4 | depends on DRM && PCI |
| 5 | depends on MMU | 5 | depends on MMU |
| 6 | select DRM_CLIENT_SELECTION | 6 | select DRM_CLIENT_SELECTION |
| 7 | select DRM_DISPLAY_HELPER | ||
| 8 | select DRM_DISPLAY_DP_HELPER | ||
| 7 | select DRM_KMS_HELPER | 9 | select DRM_KMS_HELPER |
| 8 | select DRM_VRAM_HELPER | 10 | select DRM_VRAM_HELPER |
| 9 | select DRM_TTM | 11 | select DRM_TTM |
| @@ -41,8 +41,9 @@ static u32 scale(u32 source_val, · 40 unmodified lines | |||
| 41 | { | 41 | { |
| 42 | u64 target_val; | 42 | u64 target_val; |
| 43 | 43 | ||
| 44 | WARN_ON(source_min > source_max); | 44 | if (WARN_ON(source_min >= source_max) || |
| 45 | WARN_ON(target_min > target_max); | 45 | WARN_ON(target_min > target_max)) |
| 46 | return target_min; | ||
| 46 | 47 | ||
| 47 | /* defensive */ | 48 | /* defensive */ |
| 48 | source_val = clamp(source_val, source_min, source_max); | 49 | source_val = clamp(source_val, source_min, source_max); |
| @@ -1791,7 +1791,7 @@ int intel_dp_dsc_max_src_input_bpc(struct intel_display *display) · 1790 unmodified lines | |||
| 1791 | if (DISPLAY_VER(display) == 11) | 1791 | if (DISPLAY_VER(display) == 11) |
| 1792 | return 10; | 1792 | return 10; |
| 1793 | 1793 | ||
| 1794 | return 0; | 1794 | return intel_dp_dsc_min_src_input_bpc(); |
| 1795 | } | 1795 | } |
| 1796 | 1796 | ||
| 1797 | int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector, | 1797 | int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector, |
| @@ -2072,11 +2072,10 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp, · 274 unmodified lines | |||
| 2072 | /* Compressed BPP should be less than the Input DSC bpp */ | 2072 | /* Compressed BPP should be less than the Input DSC bpp */ |
| 2073 | dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1); | 2073 | dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1); |
| 2074 | 2074 | ||
| 2075 | for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) { | 2075 | for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) { |
| 2076 | if (valid_dsc_bpp[i] < dsc_min_bpp) | 2076 | if (valid_dsc_bpp[i] < dsc_min_bpp || |
| 2077 | valid_dsc_bpp[i] > dsc_max_bpp) | ||
| 2077 | continue; | 2078 | continue; |
| 2078 | if (valid_dsc_bpp[i] > dsc_max_bpp) | ||
| 2079 | break; | ||
| 2080 | 2079 | ||
| 2081 | ret = dsc_compute_link_config(intel_dp, | 2080 | ret = dsc_compute_link_config(intel_dp, |
| 2082 | pipe_config, | 2081 | pipe_config, |
| @@ -2829,7 +2828,6 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, · 746 unmodified lines | |||
| 2829 | 2828 | ||
| 2830 | crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); | 2829 | crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); |
| 2831 | 2830 | ||
| 2832 | /* Currently only DP_AS_SDP_AVT_FIXED_VTOTAL mode supported */ | ||
| 2833 | as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC; | 2831 | as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC; |
| 2834 | as_sdp->length = 0x9; | 2832 | as_sdp->length = 0x9; |
| 2835 | as_sdp->duration_incr_ms = 0; | 2833 | as_sdp->duration_incr_ms = 0; |
| @@ -2840,7 +2838,7 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, · 4 unmodified lines | |||
| 2840 | as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode); | 2838 | as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode); |
| 2841 | as_sdp->target_rr_divider = true; | 2839 | as_sdp->target_rr_divider = true; |
| 2842 | } else { | 2840 | } else { |
| 2843 | as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL; | 2841 | as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL; |
| 2844 | as_sdp->vtotal = adjusted_mode->vtotal; | 2842 | as_sdp->vtotal = adjusted_mode->vtotal; |
| 2845 | as_sdp->target_rr = 0; | 2843 | as_sdp->target_rr = 0; |
| 2846 | } | 2844 | } |
| @@ -341,6 +341,10 @@ int intel_dp_mtp_tu_compute_config(struct intel_dp *intel_dp, · 340 unmodified lines | |||
| 341 | 341 | ||
| 342 | break; | 342 | break; |
| 343 | } | 343 | } |
| 344 | |||
| 345 | /* Allow using zero step to indicate one try */ | ||
| 346 | if (!step) | ||
| 347 | break; | ||
| 344 | } | 348 | } |
| 345 | 349 | ||
| 346 | if (slots < 0) { | 350 | if (slots < 0) { |
| @@ -41,7 +41,7 @@ intel_hdcp_adjust_hdcp_line_rekeying(struct intel_encoder *encoder, · 40 unmodified lines | |||
| 41 | u32 rekey_bit = 0; | 41 | u32 rekey_bit = 0; |
| 42 | 42 | ||
| 43 | /* Here we assume HDMI is in TMDS mode of operation */ | 43 | /* Here we assume HDMI is in TMDS mode of operation */ |
| 44 | if (encoder->type != INTEL_OUTPUT_HDMI) | 44 | if (!intel_encoder_is_hdmi(encoder)) |
| 45 | return; | 45 | return; |
| 46 | 46 | ||
| 47 | if (DISPLAY_VER(display) >= 30) { | 47 | if (DISPLAY_VER(display) >= 30) { |
| @@ -2188,6 +2188,19 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) · 2140 unmodified lines | |||
| 2188 | 2188 | ||
| 2189 | drm_dbg_kms(display->drm, | 2189 | drm_dbg_kms(display->drm, |
| 2190 | "HDCP2.2 Downstream topology change\n"); | 2190 | "HDCP2.2 Downstream topology change\n"); |
| 2191 | |||
| 2192 | ret = hdcp2_authenticate_repeater_topology(connector); | ||
| 2193 | if (!ret) { | ||
| 2194 | intel_hdcp_update_value(connector, | ||
| 2195 | DRM_MODE_CONTENT_PROTECTION_ENABLED, | ||
| 2196 | true); | ||
| 2197 | goto out; | ||
| 2198 | } | ||
| 2199 | |||
| 2200 | drm_dbg_kms(display->drm, | ||
| 2201 | "[CONNECTOR:%d:%s] Repeater topology auth failed.(%d)\n", | ||
| 2202 | connector->base.base.id, connector->base.name, | ||
| 2203 | ret); | ||
| 2191 | } else { | 2204 | } else { |
| 2192 | drm_dbg_kms(display->drm, | 2205 | drm_dbg_kms(display->drm, |
| 2193 | "[CONNECTOR:%d:%s] HDCP2.2 link failed, retrying auth\n", | 2206 | "[CONNECTOR:%d:%s] HDCP2.2 link failed, retrying auth\n", |
| @@ -106,8 +106,6 @@ static const u32 icl_sdr_y_plane_formats[] = { · 105 unmodified lines | |||
| 106 | DRM_FORMAT_Y216, | 106 | DRM_FORMAT_Y216, |
| 107 | DRM_FORMAT_XYUV8888, | 107 | DRM_FORMAT_XYUV8888, |
| 108 | DRM_FORMAT_XVYU2101010, | 108 | DRM_FORMAT_XVYU2101010, |
| 109 | DRM_FORMAT_XVYU12_16161616, | ||
| 110 | DRM_FORMAT_XVYU16161616, | ||
| 111 | }; | 109 | }; |
| 112 | 110 | ||
| 113 | static const u32 icl_sdr_uv_plane_formats[] = { | 111 | static const u32 icl_sdr_uv_plane_formats[] = { |
| @@ -134,8 +132,6 @@ static const u32 icl_sdr_uv_plane_formats[] = { · 20 unmodified lines | |||
| 134 | DRM_FORMAT_Y216, | 132 | DRM_FORMAT_Y216, |
| 135 | DRM_FORMAT_XYUV8888, | 133 | DRM_FORMAT_XYUV8888, |
| 136 | DRM_FORMAT_XVYU2101010, | 134 | DRM_FORMAT_XVYU2101010, |
| 137 | DRM_FORMAT_XVYU12_16161616, | ||
| 138 | DRM_FORMAT_XVYU16161616, | ||
| 139 | }; | 135 | }; |
| 140 | 136 | ||
| 141 | static const u32 icl_hdr_plane_formats[] = { | 137 | static const u32 icl_hdr_plane_formats[] = { |
| @@ -209,8 +209,6 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj) · 208 unmodified lines | |||
| 209 | struct address_space *mapping = obj->base.filp->f_mapping; | 209 | struct address_space *mapping = obj->base.filp->f_mapping; |
| 210 | unsigned int max_segment = i915_sg_segment_size(i915->drm.dev); | 210 | unsigned int max_segment = i915_sg_segment_size(i915->drm.dev); |
| 211 | struct sg_table *st; | 211 | struct sg_table *st; |
| 212 | struct sgt_iter sgt_iter; | ||
| 213 | struct page *page; | ||
| 214 | int ret; | 212 | int ret; |
| 215 | 213 | ||
| 216 | /* | 214 | /* |
| @@ -239,9 +237,7 @@ rebuild_st: · 22 unmodified lines | |||
| 239 | * for PAGE_SIZE chunks instead may be helpful. | 237 | * for PAGE_SIZE chunks instead may be helpful. |
| 240 | */ | 238 | */ |
| 241 | if (max_segment > PAGE_SIZE) { | 239 | if (max_segment > PAGE_SIZE) { |
| 242 | for_each_sgt_page(page, sgt_iter, st) | 240 | shmem_sg_free_table(st, mapping, false, false); |
| 243 | put_page(page); | ||
| 244 | sg_free_table(st); | ||
| 245 | kfree(st); | 241 | kfree(st); |
| 246 | 242 | ||
| 247 | max_segment = PAGE_SIZE; | 243 | max_segment = PAGE_SIZE; |
| @@ -1469,6 +1469,19 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc) · 1468 unmodified lines | |||
| 1469 | spin_unlock_irqrestore(&guc->timestamp.lock, flags); | 1469 | spin_unlock_irqrestore(&guc->timestamp.lock, flags); |
| 1470 | } | 1470 | } |
| 1471 | 1471 | ||
| 1472 | static void __update_guc_busyness_running_state(struct intel_guc *guc) | ||
| 1473 | { | ||
| 1474 | struct intel_gt *gt = guc_to_gt(guc); | ||
| 1475 | struct intel_engine_cs *engine; | ||
| 1476 | enum intel_engine_id id; | ||
| 1477 | unsigned long flags; | ||
| 1478 | |||
| 1479 | spin_lock_irqsave(&guc->timestamp.lock, flags); | ||
| 1480 | for_each_engine(engine, gt, id) | ||
| 1481 | engine->stats.guc.running = false; | ||
| 1482 | spin_unlock_irqrestore(&guc->timestamp.lock, flags); | ||
| 1483 | } | ||
| 1484 | |||
| 1472 | static void __update_guc_busyness_stats(struct intel_guc *guc) | 1485 | static void __update_guc_busyness_stats(struct intel_guc *guc) |
| 1473 | { | 1486 | { |
| 1474 | struct intel_gt *gt = guc_to_gt(guc); | 1487 | struct intel_gt *gt = guc_to_gt(guc); |
| @@ -1619,6 +1632,9 @@ void intel_guc_busyness_park(struct intel_gt *gt) · 144 unmodified lines | |||
| 1619 | if (!guc_submission_initialized(guc)) | 1632 | if (!guc_submission_initialized(guc)) |
| 1620 | return; | 1633 | return; |
| 1621 | 1634 | ||
| 1635 | /* Assume no engines are running and set running state to false */ | ||
| 1636 | __update_guc_busyness_running_state(guc); | ||
| 1637 | |||
| 1622 | /* | 1638 | /* |
| 1623 | * There is a race with suspend flow where the worker runs after suspend | 1639 | * There is a race with suspend flow where the worker runs after suspend |
| 1624 | * and causes an unclaimed register access warning. Cancel the worker | 1640 | * and causes an unclaimed register access warning. Cancel the worker |
| @@ -5519,12 +5535,20 @@ static inline void guc_log_context(struct drm_printer *p, · 3894 unmodified lines | |||
| 5519 | { | 5535 | { |
| 5520 | drm_printf(p, "GuC lrc descriptor %u:\n", ce->guc_id.id); | 5536 | drm_printf(p, "GuC lrc descriptor %u:\n", ce->guc_id.id); |
| 5521 | drm_printf(p, "\tHW Context Desc: 0x%08x\n", ce->lrc.lrca); | 5537 | drm_printf(p, "\tHW Context Desc: 0x%08x\n", ce->lrc.lrca); |
| 5522 | drm_printf(p, "\t\tLRC Head: Internal %u, Memory %u\n", | 5538 | if (intel_context_pin_if_active(ce)) { |
| 5523 | ce->ring->head, | 5539 | drm_printf(p, "\t\tLRC Head: Internal %u, Memory %u\n", |
| 5524 | ce->lrc_reg_state[CTX_RING_HEAD]); | 5540 | ce->ring->head, |
| 5525 | drm_printf(p, "\t\tLRC Tail: Internal %u, Memory %u\n", | 5541 | ce->lrc_reg_state[CTX_RING_HEAD]); |
| 5526 | ce->ring->tail, | 5542 | drm_printf(p, "\t\tLRC Tail: Internal %u, Memory %u\n", |
| 5527 | ce->lrc_reg_state[CTX_RING_TAIL]); | 5543 | ce->ring->tail, |
| 5544 | ce->lrc_reg_state[CTX_RING_TAIL]); | ||
| 5545 | intel_context_unpin(ce); | ||
| 5546 | } else { | ||
| 5547 | drm_printf(p, "\t\tLRC Head: Internal %u, Memory not pinned\n", | ||
| 5548 | ce->ring->head); | ||
| 5549 | drm_printf(p, "\t\tLRC Tail: Internal %u, Memory not pinned\n", | ||
| 5550 | ce->ring->tail); | ||
| 5551 | } | ||
| 5528 | drm_printf(p, "\t\tContext Pin Count: %u\n", | 5552 | drm_printf(p, "\t\tContext Pin Count: %u\n", |
| 5529 | atomic_read(&ce->pin_count)); | 5553 | atomic_read(&ce->pin_count)); |
| 5530 | drm_printf(p, "\t\tGuC ID Ref Count: %u\n", | 5554 | drm_printf(p, "\t\tGuC ID Ref Count: %u\n", |
| @@ -168,7 +168,7 @@ static int igt_ppgtt_alloc(void *arg) · 167 unmodified lines | |||
| 168 | return PTR_ERR(ppgtt); | 168 | return PTR_ERR(ppgtt); |
| 169 | 169 | ||
| 170 | if (!ppgtt->vm.allocate_va_range) | 170 | if (!ppgtt->vm.allocate_va_range) |
| 171 | goto err_ppgtt_cleanup; | 171 | goto ppgtt_vm_put; |
| 172 | 172 | ||
| 173 | /* | 173 | /* |
| 174 | * While we only allocate the page tables here and so we could | 174 | * While we only allocate the page tables here and so we could |
| @@ -236,7 +236,7 @@ err_ppgtt_cleanup: · 61 unmodified lines | |||
| 236 | goto retry; | 236 | goto retry; |
| 237 | } | 237 | } |
| 238 | i915_gem_ww_ctx_fini(&ww); | 238 | i915_gem_ww_ctx_fini(&ww); |
| 239 | 239 | ppgtt_vm_put: | |
| 240 | i915_vm_put(&ppgtt->vm); | 240 | i915_vm_put(&ppgtt->vm); |
| 241 | return err; | 241 | return err; |
| 242 | } | 242 | } |
| @@ -802,6 +802,7 @@ static void panthor_query_group_priorities_info(struct drm_file *file, · 801 unmodified lines | |||
| 802 | { | 802 | { |
| 803 | int prio; | 803 | int prio; |
| 804 | 804 | ||
| 805 | memset(arg, 0, sizeof(*arg)); | ||
| 805 | for (prio = PANTHOR_GROUP_PRIORITY_REALTIME; prio >= 0; prio--) { | 806 | for (prio = PANTHOR_GROUP_PRIORITY_REALTIME; prio >= 0; prio--) { |
| 806 | if (!group_priority_permit(file, prio)) | 807 | if (!group_priority_permit(file, prio)) |
| 807 | arg->allowed_mask |= BIT(prio); | 808 | arg->allowed_mask |= BIT(prio); |
| @@ -70,10 +70,17 @@ static int light_up_connector(struct kunit *test, · 69 unmodified lines | |||
| 70 | state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); | 70 | state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); |
| 71 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); | 71 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); |
| 72 | 72 | ||
| 73 | retry: | ||
| 73 | conn_state = drm_atomic_get_connector_state(state, connector); | 74 | conn_state = drm_atomic_get_connector_state(state, connector); |
| 74 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); | 75 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); |
| 75 | 76 | ||
| 76 | ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); | 77 | ret = drm_atomic_set_crtc_for_connector(conn_state, crtc); |
| 78 | if (ret == -EDEADLK) { | ||
| 79 | drm_atomic_state_clear(state); | ||
| 80 | ret = drm_modeset_backoff(ctx); | ||
| 81 | if (!ret) | ||
| 82 | goto retry; | ||
| 83 | } | ||
| 77 | KUNIT_EXPECT_EQ(test, ret, 0); | 84 | KUNIT_EXPECT_EQ(test, ret, 0); |
| 78 | 85 | ||
| 79 | crtc_state = drm_atomic_get_crtc_state(state, crtc); | 86 | crtc_state = drm_atomic_get_crtc_state(state, crtc); |
| @@ -282,15 +289,16 @@ static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test) · 202 unmodified lines | |||
| 282 | 8); | 289 | 8); |
| 283 | KUNIT_ASSERT_NOT_NULL(test, priv); | 290 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 284 | 291 | ||
| 285 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | 292 | drm = &priv->drm; |
| 286 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | 293 | crtc = priv->crtc; |
| 287 | |||
| 288 | conn = &priv->connector; | 294 | conn = &priv->connector; |
| 295 | |||
| 289 | preferred = find_preferred_mode(conn); | 296 | preferred = find_preferred_mode(conn); |
| 290 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 297 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 291 | 298 | ||
| 292 | drm = &priv->drm; | 299 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 293 | crtc = priv->crtc; | 300 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 301 | |||
| 294 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 302 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 295 | KUNIT_ASSERT_EQ(test, ret, 0); | 303 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 296 | 304 | ||
| @@ -345,15 +353,16 @@ static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *tes · 48 unmodified lines | |||
| 345 | 8); | 353 | 8); |
| 346 | KUNIT_ASSERT_NOT_NULL(test, priv); | 354 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 347 | 355 | ||
| 348 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | 356 | drm = &priv->drm; |
| 349 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | 357 | crtc = priv->crtc; |
| 350 | |||
| 351 | conn = &priv->connector; | 358 | conn = &priv->connector; |
| 359 | |||
| 352 | preferred = find_preferred_mode(conn); | 360 | preferred = find_preferred_mode(conn); |
| 353 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 361 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 354 | 362 | ||
| 355 | drm = &priv->drm; | 363 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 356 | crtc = priv->crtc; | 364 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 365 | |||
| 357 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 366 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 358 | KUNIT_ASSERT_EQ(test, ret, 0); | 367 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 359 | 368 | ||
| @@ -408,18 +417,18 @@ static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test) · 48 unmodified lines | |||
| 408 | 8); | 417 | 8); |
| 409 | KUNIT_ASSERT_NOT_NULL(test, priv); | 418 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 410 | 419 | ||
| 420 | drm = &priv->drm; | ||
| 421 | crtc = priv->crtc; | ||
| 411 | conn = &priv->connector; | 422 | conn = &priv->connector; |
| 412 | KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); | 423 | KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); |
| 413 | 424 | ||
| 414 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 415 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 416 | |||
| 417 | preferred = find_preferred_mode(conn); | 425 | preferred = find_preferred_mode(conn); |
| 418 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 426 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 419 | KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); | 427 | KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); |
| 420 | 428 | ||
| 421 | drm = &priv->drm; | 429 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 422 | crtc = priv->crtc; | 430 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 431 | |||
| 423 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 432 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 424 | KUNIT_ASSERT_EQ(test, ret, 0); | 433 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 425 | 434 | ||
| @@ -474,7 +483,6 @@ static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test) · 48 unmodified lines | |||
| 474 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); | 483 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); |
| 475 | KUNIT_ASSERT_NOT_NULL(test, mode); | 484 | KUNIT_ASSERT_NOT_NULL(test, mode); |
| 476 | 485 | ||
| 477 | drm = &priv->drm; | ||
| 478 | crtc = priv->crtc; | 486 | crtc = priv->crtc; |
| 479 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); | 487 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); |
| 480 | KUNIT_ASSERT_EQ(test, ret, 0); | 488 | KUNIT_ASSERT_EQ(test, ret, 0); |
| @@ -520,18 +528,18 @@ static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test) · 39 unmodified lines | |||
| 520 | 8); | 528 | 8); |
| 521 | KUNIT_ASSERT_NOT_NULL(test, priv); | 529 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 522 | 530 | ||
| 531 | drm = &priv->drm; | ||
| 532 | crtc = priv->crtc; | ||
| 523 | conn = &priv->connector; | 533 | conn = &priv->connector; |
| 524 | KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); | 534 | KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); |
| 525 | 535 | ||
| 526 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 527 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 528 | |||
| 529 | preferred = find_preferred_mode(conn); | 536 | preferred = find_preferred_mode(conn); |
| 530 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 537 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 531 | KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); | 538 | KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); |
| 532 | 539 | ||
| 533 | drm = &priv->drm; | 540 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 534 | crtc = priv->crtc; | 541 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 542 | |||
| 535 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 543 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 536 | KUNIT_ASSERT_EQ(test, ret, 0); | 544 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 537 | 545 | ||
| @@ -588,7 +596,6 @@ static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test) · 50 unmodified lines | |||
| 588 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); | 596 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); |
| 589 | KUNIT_ASSERT_NOT_NULL(test, mode); | 597 | KUNIT_ASSERT_NOT_NULL(test, mode); |
| 590 | 598 | ||
| 591 | drm = &priv->drm; | ||
| 592 | crtc = priv->crtc; | 599 | crtc = priv->crtc; |
| 593 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); | 600 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); |
| 594 | KUNIT_ASSERT_EQ(test, ret, 0); | 601 | KUNIT_ASSERT_EQ(test, ret, 0); |
| @@ -636,18 +643,18 @@ static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test) · 41 unmodified lines | |||
| 636 | 8); | 643 | 8); |
| 637 | KUNIT_ASSERT_NOT_NULL(test, priv); | 644 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 638 | 645 | ||
| 646 | drm = &priv->drm; | ||
| 647 | crtc = priv->crtc; | ||
| 639 | conn = &priv->connector; | 648 | conn = &priv->connector; |
| 640 | KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); | 649 | KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); |
| 641 | 650 | ||
| 642 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 643 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 644 | |||
| 645 | preferred = find_preferred_mode(conn); | 651 | preferred = find_preferred_mode(conn); |
| 646 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 652 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 647 | KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); | 653 | KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); |
| 648 | 654 | ||
| 649 | drm = &priv->drm; | 655 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 650 | crtc = priv->crtc; | 656 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 657 | |||
| 651 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 658 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 652 | KUNIT_ASSERT_EQ(test, ret, 0); | 659 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 653 | 660 | ||
| @@ -704,7 +711,6 @@ static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *te · 50 unmodified lines | |||
| 704 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); | 711 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); |
| 705 | KUNIT_ASSERT_NOT_NULL(test, mode); | 712 | KUNIT_ASSERT_NOT_NULL(test, mode); |
| 706 | 713 | ||
| 707 | drm = &priv->drm; | ||
| 708 | crtc = priv->crtc; | 714 | crtc = priv->crtc; |
| 709 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); | 715 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); |
| 710 | KUNIT_ASSERT_EQ(test, ret, 0); | 716 | KUNIT_ASSERT_EQ(test, ret, 0); |
| @@ -754,20 +760,20 @@ static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test) · 43 unmodified lines | |||
| 754 | 10); | 760 | 10); |
| 755 | KUNIT_ASSERT_NOT_NULL(test, priv); | 761 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 756 | 762 | ||
| 763 | drm = &priv->drm; | ||
| 764 | crtc = priv->crtc; | ||
| 757 | conn = &priv->connector; | 765 | conn = &priv->connector; |
| 758 | ret = set_connector_edid(test, conn, | 766 | ret = set_connector_edid(test, conn, |
| 759 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, | 767 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, |
| 760 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); | 768 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); |
| 761 | KUNIT_ASSERT_GT(test, ret, 0); | 769 | KUNIT_ASSERT_GT(test, ret, 0); |
| 762 | 770 | ||
| 763 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 764 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 765 | |||
| 766 | preferred = find_preferred_mode(conn); | 771 | preferred = find_preferred_mode(conn); |
| 767 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 772 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 768 | 773 | ||
| 769 | drm = &priv->drm; | 774 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 770 | crtc = priv->crtc; | 775 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 776 | |||
| 771 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 777 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 772 | KUNIT_ASSERT_EQ(test, ret, 0); | 778 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 773 | 779 | ||
| @@ -828,20 +834,20 @@ static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test) · 54 unmodified lines | |||
| 828 | 10); | 834 | 10); |
| 829 | KUNIT_ASSERT_NOT_NULL(test, priv); | 835 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 830 | 836 | ||
| 837 | drm = &priv->drm; | ||
| 838 | crtc = priv->crtc; | ||
| 831 | conn = &priv->connector; | 839 | conn = &priv->connector; |
| 832 | ret = set_connector_edid(test, conn, | 840 | ret = set_connector_edid(test, conn, |
| 833 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, | 841 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, |
| 834 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); | 842 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); |
| 835 | KUNIT_ASSERT_GT(test, ret, 0); | 843 | KUNIT_ASSERT_GT(test, ret, 0); |
| 836 | 844 | ||
| 837 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 838 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 839 | |||
| 840 | preferred = find_preferred_mode(conn); | 845 | preferred = find_preferred_mode(conn); |
| 841 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 846 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 842 | 847 | ||
| 843 | drm = &priv->drm; | 848 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 844 | crtc = priv->crtc; | 849 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 850 | |||
| 845 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 851 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 846 | KUNIT_ASSERT_EQ(test, ret, 0); | 852 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 847 | 853 | ||
| @@ -899,6 +905,8 @@ static void drm_test_check_output_bpc_dvi(struct kunit *test) · 51 unmodified lines | |||
| 899 | 12); | 905 | 12); |
| 900 | KUNIT_ASSERT_NOT_NULL(test, priv); | 906 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 901 | 907 | ||
| 908 | drm = &priv->drm; | ||
| 909 | crtc = priv->crtc; | ||
| 902 | conn = &priv->connector; | 910 | conn = &priv->connector; |
| 903 | ret = set_connector_edid(test, conn, | 911 | ret = set_connector_edid(test, conn, |
| 904 | test_edid_dvi_1080p, | 912 | test_edid_dvi_1080p, |
| @@ -908,14 +916,12 @@ static void drm_test_check_output_bpc_dvi(struct kunit *test) · 3 unmodified lines | |||
| 908 | info = &conn->display_info; | 916 | info = &conn->display_info; |
| 909 | KUNIT_ASSERT_FALSE(test, info->is_hdmi); | 917 | KUNIT_ASSERT_FALSE(test, info->is_hdmi); |
| 910 | 918 | ||
| 911 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 912 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 913 | |||
| 914 | preferred = find_preferred_mode(conn); | 919 | preferred = find_preferred_mode(conn); |
| 915 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 920 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 916 | 921 | ||
| 917 | drm = &priv->drm; | 922 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 918 | crtc = priv->crtc; | 923 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 924 | |||
| 919 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 925 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 920 | KUNIT_ASSERT_EQ(test, ret, 0); | 926 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 921 | 927 | ||
| @@ -946,21 +952,21 @@ static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test) · 24 unmodified lines | |||
| 946 | 8); | 952 | 8); |
| 947 | KUNIT_ASSERT_NOT_NULL(test, priv); | 953 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 948 | 954 | ||
| 955 | drm = &priv->drm; | ||
| 956 | crtc = priv->crtc; | ||
| 949 | conn = &priv->connector; | 957 | conn = &priv->connector; |
| 950 | ret = set_connector_edid(test, conn, | 958 | ret = set_connector_edid(test, conn, |
| 951 | test_edid_hdmi_1080p_rgb_max_200mhz, | 959 | test_edid_hdmi_1080p_rgb_max_200mhz, |
| 952 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); | 960 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); |
| 953 | KUNIT_ASSERT_GT(test, ret, 0); | 961 | KUNIT_ASSERT_GT(test, ret, 0); |
| 954 | 962 | ||
| 955 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 956 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 957 | |||
| 958 | preferred = find_preferred_mode(conn); | 963 | preferred = find_preferred_mode(conn); |
| 959 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 964 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 960 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); | 965 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); |
| 961 | 966 | ||
| 962 | drm = &priv->drm; | 967 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 963 | crtc = priv->crtc; | 968 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 969 | |||
| 964 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 970 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 965 | KUNIT_ASSERT_EQ(test, ret, 0); | 971 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 966 | 972 | ||
| @@ -993,21 +999,21 @@ static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test) · 26 unmodified lines | |||
| 993 | 10); | 999 | 10); |
| 994 | KUNIT_ASSERT_NOT_NULL(test, priv); | 1000 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 995 | 1001 | ||
| 1002 | drm = &priv->drm; | ||
| 1003 | crtc = priv->crtc; | ||
| 996 | conn = &priv->connector; | 1004 | conn = &priv->connector; |
| 997 | ret = set_connector_edid(test, conn, | 1005 | ret = set_connector_edid(test, conn, |
| 998 | test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, | 1006 | test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, |
| 999 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); | 1007 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); |
| 1000 | KUNIT_ASSERT_GT(test, ret, 0); | 1008 | KUNIT_ASSERT_GT(test, ret, 0); |
| 1001 | 1009 | ||
| 1002 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 1003 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1004 | |||
| 1005 | preferred = find_preferred_mode(conn); | 1010 | preferred = find_preferred_mode(conn); |
| 1006 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 1011 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1007 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); | 1012 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); |
| 1008 | 1013 | ||
| 1009 | drm = &priv->drm; | 1014 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1010 | crtc = priv->crtc; | 1015 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 1016 | |||
| 1011 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 1017 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1012 | KUNIT_ASSERT_EQ(test, ret, 0); | 1018 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 1013 | 1019 | ||
| @@ -1040,21 +1046,21 @@ static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test) · 26 unmodified lines | |||
| 1040 | 12); | 1046 | 12); |
| 1041 | KUNIT_ASSERT_NOT_NULL(test, priv); | 1047 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1042 | 1048 | ||
| 1049 | drm = &priv->drm; | ||
| 1050 | crtc = priv->crtc; | ||
| 1043 | conn = &priv->connector; | 1051 | conn = &priv->connector; |
| 1044 | ret = set_connector_edid(test, conn, | 1052 | ret = set_connector_edid(test, conn, |
| 1045 | test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, | 1053 | test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, |
| 1046 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); | 1054 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); |
| 1047 | KUNIT_ASSERT_GT(test, ret, 0); | 1055 | KUNIT_ASSERT_GT(test, ret, 0); |
| 1048 | 1056 | ||
| 1049 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 1050 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1051 | |||
| 1052 | preferred = find_preferred_mode(conn); | 1057 | preferred = find_preferred_mode(conn); |
| 1053 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 1058 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1054 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); | 1059 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); |
| 1055 | 1060 | ||
| 1056 | drm = &priv->drm; | 1061 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1057 | crtc = priv->crtc; | 1062 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 1063 | |||
| 1058 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 1064 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1059 | KUNIT_ASSERT_EQ(test, ret, 0); | 1065 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 1060 | 1066 | ||
| @@ -1091,15 +1097,16 @@ static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test) · 30 unmodified lines | |||
| 1091 | 8); | 1097 | 8); |
| 1092 | KUNIT_ASSERT_NOT_NULL(test, priv); | 1098 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1093 | 1099 | ||
| 1094 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | 1100 | drm = &priv->drm; |
| 1095 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | 1101 | crtc = priv->crtc; |
| 1096 | |||
| 1097 | conn = &priv->connector; | 1102 | conn = &priv->connector; |
| 1103 | |||
| 1098 | preferred = find_preferred_mode(conn); | 1104 | preferred = find_preferred_mode(conn); |
| 1099 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 1105 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1100 | 1106 | ||
| 1101 | drm = &priv->drm; | 1107 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1102 | crtc = priv->crtc; | 1108 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 1109 | |||
| 1103 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 1110 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1104 | KUNIT_ASSERT_EQ(test, ret, 0); | 1111 | KUNIT_ASSERT_EQ(test, ret, 0); |
| 1105 | 1112 | ||
| @@ -1147,6 +1154,8 @@ static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test) · 41 unmodified lines | |||
| 1147 | 12); | 1154 | 12); |
| 1148 | KUNIT_ASSERT_NOT_NULL(test, priv); | 1155 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1149 | 1156 | ||
| 1157 | drm = &priv->drm; | ||
| 1158 | crtc = priv->crtc; | ||
| 1150 | conn = &priv->connector; | 1159 | conn = &priv->connector; |
| 1151 | ret = set_connector_edid(test, conn, | 1160 | ret = set_connector_edid(test, conn, |
| 1152 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, | 1161 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, |
| @@ -1157,9 +1166,6 @@ static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test) · 4 unmodified lines | |||
| 1157 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); | 1166 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1158 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); | 1167 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); |
| 1159 | 1168 | ||
| 1160 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 1161 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1162 | |||
| 1163 | preferred = find_preferred_mode(conn); | 1169 | preferred = find_preferred_mode(conn); |
| 1164 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 1170 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1165 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); | 1171 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); |
| @@ -1170,8 +1176,9 @@ static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test) · 4 unmodified lines | |||
| 1170 | rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); | 1176 | rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); |
| 1171 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); | 1177 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1172 | 1178 | ||
| 1173 | drm = &priv->drm; | 1179 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1174 | crtc = priv->crtc; | 1180 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 1181 | |||
| 1175 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 1182 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1176 | KUNIT_EXPECT_EQ(test, ret, 0); | 1183 | KUNIT_EXPECT_EQ(test, ret, 0); |
| 1177 | 1184 | ||
| @@ -1216,6 +1223,8 @@ static void drm_test_check_max_tmds_rate_format_fallback(struct kunit *test) · 38 unmodified lines | |||
| 1216 | 12); | 1223 | 12); |
| 1217 | KUNIT_ASSERT_NOT_NULL(test, priv); | 1224 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1218 | 1225 | ||
| 1226 | drm = &priv->drm; | ||
| 1227 | crtc = priv->crtc; | ||
| 1219 | conn = &priv->connector; | 1228 | conn = &priv->connector; |
| 1220 | ret = set_connector_edid(test, conn, | 1229 | ret = set_connector_edid(test, conn, |
| 1221 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, | 1230 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, |
| @@ -1226,9 +1235,6 @@ static void drm_test_check_max_tmds_rate_format_fallback(struct kunit *test) · 4 unmodified lines | |||
| 1226 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); | 1235 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1227 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); | 1236 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); |
| 1228 | 1237 | ||
| 1229 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 1230 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1231 | |||
| 1232 | preferred = find_preferred_mode(conn); | 1238 | preferred = find_preferred_mode(conn); |
| 1233 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 1239 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1234 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); | 1240 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); |
| @@ -1242,8 +1248,9 @@ static void drm_test_check_max_tmds_rate_format_fallback(struct kunit *test) · 7 unmodified lines | |||
| 1242 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); | 1248 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); |
| 1243 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); | 1249 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1244 | 1250 | ||
| 1245 | drm = &priv->drm; | 1251 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1246 | crtc = priv->crtc; | 1252 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 1253 | |||
| 1247 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 1254 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1248 | KUNIT_EXPECT_EQ(test, ret, 0); | 1255 | KUNIT_EXPECT_EQ(test, ret, 0); |
| 1249 | 1256 | ||
| @@ -1290,9 +1297,6 @@ static void drm_test_check_output_bpc_format_vic_1(struct kunit *test) · 40 unmodified lines | |||
| 1290 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); | 1297 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1291 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); | 1298 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); |
| 1292 | 1299 | ||
| 1293 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 1294 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1295 | |||
| 1296 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); | 1300 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); |
| 1297 | KUNIT_ASSERT_NOT_NULL(test, mode); | 1301 | KUNIT_ASSERT_NOT_NULL(test, mode); |
| 1298 | 1302 | ||
| @@ -1306,7 +1310,9 @@ static void drm_test_check_output_bpc_format_vic_1(struct kunit *test) · 7 unmodified lines | |||
| 1306 | rate = mode->clock * 1500; | 1310 | rate = mode->clock * 1500; |
| 1307 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); | 1311 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1308 | 1312 | ||
| 1309 | drm = &priv->drm; | 1313 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1314 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1315 | |||
| 1310 | crtc = priv->crtc; | 1316 | crtc = priv->crtc; |
| 1311 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); | 1317 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); |
| 1312 | KUNIT_EXPECT_EQ(test, ret, 0); | 1318 | KUNIT_EXPECT_EQ(test, ret, 0); |
| @@ -1340,6 +1346,8 @@ static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test) · 27 unmodified lines | |||
| 1340 | 12); | 1346 | 12); |
| 1341 | KUNIT_ASSERT_NOT_NULL(test, priv); | 1347 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1342 | 1348 | ||
| 1349 | drm = &priv->drm; | ||
| 1350 | crtc = priv->crtc; | ||
| 1343 | conn = &priv->connector; | 1351 | conn = &priv->connector; |
| 1344 | ret = set_connector_edid(test, conn, | 1352 | ret = set_connector_edid(test, conn, |
| 1345 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, | 1353 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, |
| @@ -1350,9 +1358,6 @@ static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test) · 4 unmodified lines | |||
| 1350 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); | 1358 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1351 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); | 1359 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); |
| 1352 | 1360 | ||
| 1353 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 1354 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1355 | |||
| 1356 | preferred = find_preferred_mode(conn); | 1361 | preferred = find_preferred_mode(conn); |
| 1357 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 1362 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1358 | 1363 | ||
| @@ -1371,8 +1376,9 @@ static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test) · 12 unmodified lines | |||
| 1371 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); | 1376 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); |
| 1372 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); | 1377 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1373 | 1378 | ||
| 1374 | drm = &priv->drm; | 1379 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1375 | crtc = priv->crtc; | 1380 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 1381 | |||
| 1376 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 1382 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1377 | KUNIT_EXPECT_EQ(test, ret, 0); | 1383 | KUNIT_EXPECT_EQ(test, ret, 0); |
| 1378 | 1384 | ||
| @@ -1407,6 +1413,8 @@ static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test · 28 unmodified lines | |||
| 1407 | 12); | 1413 | 12); |
| 1408 | KUNIT_ASSERT_NOT_NULL(test, priv); | 1414 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1409 | 1415 | ||
| 1416 | drm = &priv->drm; | ||
| 1417 | crtc = priv->crtc; | ||
| 1410 | conn = &priv->connector; | 1418 | conn = &priv->connector; |
| 1411 | ret = set_connector_edid(test, conn, | 1419 | ret = set_connector_edid(test, conn, |
| 1412 | test_edid_hdmi_1080p_rgb_max_200mhz, | 1420 | test_edid_hdmi_1080p_rgb_max_200mhz, |
| @@ -1417,9 +1425,6 @@ static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test · 4 unmodified lines | |||
| 1417 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); | 1425 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1418 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); | 1426 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); |
| 1419 | 1427 | ||
| 1420 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 1421 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1422 | |||
| 1423 | preferred = find_preferred_mode(conn); | 1428 | preferred = find_preferred_mode(conn); |
| 1424 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 1429 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1425 | 1430 | ||
| @@ -1438,8 +1443,9 @@ static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test · 12 unmodified lines | |||
| 1438 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); | 1443 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); |
| 1439 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); | 1444 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1440 | 1445 | ||
| 1441 | drm = &priv->drm; | 1446 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1442 | crtc = priv->crtc; | 1447 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 1448 | |||
| 1443 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 1449 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1444 | KUNIT_EXPECT_EQ(test, ret, 0); | 1450 | KUNIT_EXPECT_EQ(test, ret, 0); |
| 1445 | 1451 | ||
| @@ -1473,6 +1479,8 @@ static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test · 27 unmodified lines | |||
| 1473 | 8); | 1479 | 8); |
| 1474 | KUNIT_ASSERT_NOT_NULL(test, priv); | 1480 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1475 | 1481 | ||
| 1482 | drm = &priv->drm; | ||
| 1483 | crtc = priv->crtc; | ||
| 1476 | conn = &priv->connector; | 1484 | conn = &priv->connector; |
| 1477 | ret = set_connector_edid(test, conn, | 1485 | ret = set_connector_edid(test, conn, |
| 1478 | test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, | 1486 | test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, |
| @@ -1483,9 +1491,6 @@ static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test · 4 unmodified lines | |||
| 1483 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); | 1491 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1484 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); | 1492 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); |
| 1485 | 1493 | ||
| 1486 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 1487 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1488 | |||
| 1489 | preferred = find_preferred_mode(conn); | 1494 | preferred = find_preferred_mode(conn); |
| 1490 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 1495 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1491 | 1496 | ||
| @@ -1496,8 +1501,9 @@ static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test · 4 unmodified lines | |||
| 1496 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); | 1501 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); |
| 1497 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); | 1502 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1498 | 1503 | ||
| 1499 | drm = &priv->drm; | 1504 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1500 | crtc = priv->crtc; | 1505 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 1506 | |||
| 1501 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 1507 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1502 | KUNIT_EXPECT_EQ(test, ret, 0); | 1508 | KUNIT_EXPECT_EQ(test, ret, 0); |
| 1503 | 1509 | ||
| @@ -1533,6 +1539,8 @@ static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *tes · 29 unmodified lines | |||
| 1533 | 12); | 1539 | 12); |
| 1534 | KUNIT_ASSERT_NOT_NULL(test, priv); | 1540 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1535 | 1541 | ||
| 1542 | drm = &priv->drm; | ||
| 1543 | crtc = priv->crtc; | ||
| 1536 | conn = &priv->connector; | 1544 | conn = &priv->connector; |
| 1537 | ret = set_connector_edid(test, conn, | 1545 | ret = set_connector_edid(test, conn, |
| 1538 | test_edid_hdmi_1080p_rgb_max_340mhz, | 1546 | test_edid_hdmi_1080p_rgb_max_340mhz, |
| @@ -1543,9 +1551,6 @@ static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *tes · 4 unmodified lines | |||
| 1543 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); | 1551 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1544 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); | 1552 | KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); |
| 1545 | 1553 | ||
| 1546 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); | ||
| 1547 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | ||
| 1548 | |||
| 1549 | preferred = find_preferred_mode(conn); | 1554 | preferred = find_preferred_mode(conn); |
| 1550 | KUNIT_ASSERT_NOT_NULL(test, preferred); | 1555 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1551 | 1556 | ||
| @@ -1556,8 +1561,9 @@ static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *tes · 4 unmodified lines | |||
| 1556 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); | 1561 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); |
| 1557 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); | 1562 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1558 | 1563 | ||
| 1559 | drm = &priv->drm; | 1564 | ctx = drm_kunit_helper_acquire_ctx_alloc(test); |
| 1560 | crtc = priv->crtc; | 1565 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); |
| 1566 | |||
| 1561 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); | 1567 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1562 | KUNIT_EXPECT_EQ(test, ret, 0); | 1568 | KUNIT_EXPECT_EQ(test, ret, 0); |
| 1563 | 1569 | ||
| @@ -51,6 +51,10 @@ · 50 unmodified lines | |||
| 51 | /* Common to all OA units */ | 51 | /* Common to all OA units */ |
| 52 | #define OA_OACONTROL_REPORT_BC_MASK REG_GENMASK(9, 9) | 52 | #define OA_OACONTROL_REPORT_BC_MASK REG_GENMASK(9, 9) |
| 53 | #define OA_OACONTROL_COUNTER_SIZE_MASK REG_GENMASK(8, 8) | 53 | #define OA_OACONTROL_COUNTER_SIZE_MASK REG_GENMASK(8, 8) |
| 54 | #define OAG_OACONTROL_USED_BITS \ | ||
| 55 | (OAG_OACONTROL_OA_PES_DISAG_EN | OAG_OACONTROL_OA_CCS_SELECT_MASK | \ | ||
| 56 | OAG_OACONTROL_OA_COUNTER_SEL_MASK | OAG_OACONTROL_OA_COUNTER_ENABLE | \ | ||
| 57 | OA_OACONTROL_REPORT_BC_MASK | OA_OACONTROL_COUNTER_SIZE_MASK) | ||
| 54 | 58 | ||
| 55 | #define OAG_OA_DEBUG XE_REG(0xdaf8, XE_REG_OPTION_MASKED) | 59 | #define OAG_OA_DEBUG XE_REG(0xdaf8, XE_REG_OPTION_MASKED) |
| 56 | #define OAG_OA_DEBUG_DISABLE_MMIO_TRG REG_BIT(14) | 60 | #define OAG_OA_DEBUG_DISABLE_MMIO_TRG REG_BIT(14) |
| @@ -78,6 +82,8 @@ · 21 unmodified lines | |||
| 78 | #define OAM_CONTEXT_CONTROL_OFFSET (0x1bc) | 82 | #define OAM_CONTEXT_CONTROL_OFFSET (0x1bc) |
| 79 | #define OAM_CONTROL_OFFSET (0x194) | 83 | #define OAM_CONTROL_OFFSET (0x194) |
| 80 | #define OAM_CONTROL_COUNTER_SEL_MASK REG_GENMASK(3, 1) | 84 | #define OAM_CONTROL_COUNTER_SEL_MASK REG_GENMASK(3, 1) |
| 85 | #define OAM_OACONTROL_USED_BITS \ | ||
| 86 | (OAM_CONTROL_COUNTER_SEL_MASK | OAG_OACONTROL_OA_COUNTER_ENABLE) | ||
| 81 | #define OAM_DEBUG_OFFSET (0x198) | 87 | #define OAM_DEBUG_OFFSET (0x198) |
| 82 | #define OAM_STATUS_OFFSET (0x19c) | 88 | #define OAM_STATUS_OFFSET (0x19c) |
| 83 | #define OAM_MMIO_TRG_OFFSET (0x1d0) | 89 | #define OAM_MMIO_TRG_OFFSET (0x1d0) |
| @@ -119,11 +119,7 @@ static ssize_t __xe_devcoredump_read(char *buffer, size_t count, · 118 unmodified lines | |||
| 119 | drm_puts(&p, "\n**** GuC CT ****\n"); | 119 | drm_puts(&p, "\n**** GuC CT ****\n"); |
| 120 | xe_guc_ct_snapshot_print(ss->guc.ct, &p); | 120 | xe_guc_ct_snapshot_print(ss->guc.ct, &p); |
| 121 | 121 | ||
| 122 | /* | 122 | drm_puts(&p, "\n**** Contexts ****\n"); |
| 123 | * Don't add a new section header here because the mesa debug decoder | ||
| 124 | * tool expects the context information to be in the 'GuC CT' section. | ||
| 125 | */ | ||
| 126 | /* drm_puts(&p, "\n**** Contexts ****\n"); */ | ||
| 127 | xe_guc_exec_queue_snapshot_print(ss->ge, &p); | 123 | xe_guc_exec_queue_snapshot_print(ss->ge, &p); |
| 128 | 124 | ||
| 129 | drm_puts(&p, "\n**** Job ****\n"); | 125 | drm_puts(&p, "\n**** Job ****\n"); |
| @@ -395,42 +391,34 @@ int xe_devcoredump_init(struct xe_device *xe) · 265 unmodified lines | |||
| 395 | /** | 391 | /** |
| 396 | * xe_print_blob_ascii85 - print a BLOB to some useful location in ASCII85 | 392 | * xe_print_blob_ascii85 - print a BLOB to some useful location in ASCII85 |
| 397 | * | 393 | * |
| 398 | * The output is split to multiple lines because some print targets, e.g. dmesg | 394 | * The output is split into multiple calls to drm_puts() because some print |
| 399 | * cannot handle arbitrarily long lines. Note also that printing to dmesg in | 395 | * targets, e.g. dmesg, cannot handle arbitrarily long lines. These targets may |
| 400 | * piece-meal fashion is not possible, each separate call to drm_puts() has a | 396 | * add newlines, as is the case with dmesg: each drm_puts() call creates a |
| 401 | * line-feed automatically added! Therefore, the entire output line must be | 397 | * separate line. |
| 402 | * constructed in a local buffer first, then printed in one atomic output call. | ||
| 403 | * | 398 | * |
| 404 | * There is also a scheduler yield call to prevent the 'task has been stuck for | 399 | * There is also a scheduler yield call to prevent the 'task has been stuck for |
| 405 | * 120s' kernel hang check feature from firing when printing to a slow target | 400 | * 120s' kernel hang check feature from firing when printing to a slow target |
| 406 | * such as dmesg over a serial port. | 401 | * such as dmesg over a serial port. |
| 407 | * | 402 | * |
| 408 | * TODO: Add compression prior to the ASCII85 encoding to shrink huge buffers down. | ||
| 409 | * | ||
| 410 | * @p: the printer object to output to | 403 | * @p: the printer object to output to |
| 411 | * @prefix: optional prefix to add to output string | 404 | * @prefix: optional prefix to add to output string |
| 405 | * @suffix: optional suffix to add at the end. 0 disables it and is | ||
| 406 | * not added to the output, which is useful when using multiple calls | ||
| 407 | * to dump data to @p | ||
| 412 | * @blob: the Binary Large OBject to dump out | 408 | * @blob: the Binary Large OBject to dump out |
| 413 | * @offset: offset in bytes to skip from the front of the BLOB, must be a multiple of sizeof(u32) | 409 | * @offset: offset in bytes to skip from the front of the BLOB, must be a multiple of sizeof(u32) |
| 414 | * @size: the size in bytes of the BLOB, must be a multiple of sizeof(u32) | 410 | * @size: the size in bytes of the BLOB, must be a multiple of sizeof(u32) |
| 415 | */ | 411 | */ |
| 416 | void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, | 412 | void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, char suffix, |
| 417 | const void *blob, size_t offset, size_t size) | 413 | const void *blob, size_t offset, size_t size) |
| 418 | { | 414 | { |
| 419 | const u32 *blob32 = (const u32 *)blob; | 415 | const u32 *blob32 = (const u32 *)blob; |
| 420 | char buff[ASCII85_BUFSZ], *line_buff; | 416 | char buff[ASCII85_BUFSZ], *line_buff; |
| 421 | size_t line_pos = 0; | 417 | size_t line_pos = 0; |
| 422 | 418 | ||
| 423 | /* | ||
| 424 | * Splitting blobs across multiple lines is not compatible with the mesa | ||
| 425 | * debug decoder tool. Note that even dropping the explicit '\n' below | ||
| 426 | * doesn't help because the GuC log is so big some underlying implementation | ||
| 427 | * still splits the lines at 512K characters. So just bail completely for | ||
| 428 | * the moment. | ||
| 429 | */ | ||
| 430 | return; | ||
| 431 | |||
| 432 | #define DMESG_MAX_LINE_LEN 800 | 419 | #define DMESG_MAX_LINE_LEN 800 |
| 433 | #define MIN_SPACE (ASCII85_BUFSZ + 2) /* 85 + "\n\0" */ | 420 | /* Always leave space for the suffix char and the \0 */ |
| 421 | #define MIN_SPACE (ASCII85_BUFSZ + 2) /* 85 + "<suffix>\0" */ | ||
| 434 | 422 | ||
| 435 | if (size & 3) | 423 | if (size & 3) |
| 436 | drm_printf(p, "Size not word aligned: %zu", size); | 424 | drm_printf(p, "Size not word aligned: %zu", size); |
| @@ -462,7 +450,6 @@ void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, · 25 unmodified lines | |||
| 462 | line_pos += strlen(line_buff + line_pos); | 450 | line_pos += strlen(line_buff + line_pos); |
| 463 | 451 | ||
| 464 | if ((line_pos + MIN_SPACE) >= DMESG_MAX_LINE_LEN) { | 452 | if ((line_pos + MIN_SPACE) >= DMESG_MAX_LINE_LEN) { |
| 465 | line_buff[line_pos++] = '\n'; | ||
| 466 | line_buff[line_pos++] = 0; | 453 | line_buff[line_pos++] = 0; |
| 467 | 454 | ||
| 468 | drm_puts(p, line_buff); | 455 | drm_puts(p, line_buff); |
| @@ -474,10 +461,11 @@ void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, · 5 unmodified lines | |||
| 474 | } | 461 | } |
| 475 | } | 462 | } |
| 476 | 463 | ||
| 464 | if (suffix) | ||
| 465 | line_buff[line_pos++] = suffix; | ||
| 466 | |||
| 477 | if (line_pos) { | 467 | if (line_pos) { |
| 478 | line_buff[line_pos++] = '\n'; | ||
| 479 | line_buff[line_pos++] = 0; | 468 | line_buff[line_pos++] = 0; |
| 480 | |||
| 481 | drm_puts(p, line_buff); | 469 | drm_puts(p, line_buff); |
| 482 | } | 470 | } |
| 483 | 471 | ||
| @@ -29,7 +29,7 @@ static inline int xe_devcoredump_init(struct xe_device *xe) · 28 unmodified lines | |||
| 29 | } | 29 | } |
| 30 | #endif | 30 | #endif |
| 31 | 31 | ||
| 32 | void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, | 32 | void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix, char suffix, |
| 33 | const void *blob, size_t offset, size_t size); | 33 | const void *blob, size_t offset, size_t size); |
| 34 | 34 | ||
| 35 | #endif | 35 | #endif |
| @@ -135,8 +135,8 @@ void xe_drm_client_add_bo(struct xe_drm_client *client, · 134 unmodified lines | |||
| 135 | XE_WARN_ON(bo->client); | 135 | XE_WARN_ON(bo->client); |
| 136 | XE_WARN_ON(!list_empty(&bo->client_link)); | 136 | XE_WARN_ON(!list_empty(&bo->client_link)); |
| 137 | 137 | ||
| 138 | spin_lock(&client->bos_lock); | ||
| 139 | bo->client = xe_drm_client_get(client); | 138 | bo->client = xe_drm_client_get(client); |
| 139 | spin_lock(&client->bos_lock); | ||
| 140 | list_add_tail(&bo->client_link, &client->bos_list); | 140 | list_add_tail(&bo->client_link, &client->bos_list); |
| 141 | spin_unlock(&client->bos_lock); | 141 | spin_unlock(&client->bos_lock); |
| 142 | } | 142 | } |
| @@ -532,8 +532,10 @@ static int all_fw_domain_init(struct xe_gt *gt) · 531 unmodified lines | |||
| 532 | if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt)) | 532 | if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt)) |
| 533 | xe_lmtt_init_hw(>_to_tile(gt)->sriov.pf.lmtt); | 533 | xe_lmtt_init_hw(>_to_tile(gt)->sriov.pf.lmtt); |
| 534 | 534 | ||
| 535 | if (IS_SRIOV_PF(gt_to_xe(gt))) | 535 | if (IS_SRIOV_PF(gt_to_xe(gt))) { |
| 536 | xe_gt_sriov_pf_init(gt); | ||
| 536 | xe_gt_sriov_pf_init_hw(gt); | 537 | xe_gt_sriov_pf_init_hw(gt); |
| 538 | } | ||
| 537 | 539 | ||
| 538 | xe_force_wake_put(gt_to_fw(gt), fw_ref); | 540 | xe_force_wake_put(gt_to_fw(gt), fw_ref); |
| 539 | 541 | ||
| @@ -68,6 +68,19 @@ int xe_gt_sriov_pf_init_early(struct xe_gt *gt) · 67 unmodified lines | |||
| 68 | return 0; | 68 | return 0; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | /** | ||
| 72 | * xe_gt_sriov_pf_init - Prepare SR-IOV PF data structures on PF. | ||
| 73 | * @gt: the &xe_gt to initialize | ||
| 74 | * | ||
| 75 | * Late one-time initialization of the PF data. | ||
| 76 | * | ||
| 77 | * Return: 0 on success or a negative error code on failure. | ||
| 78 | */ | ||
| 79 | int xe_gt_sriov_pf_init(struct xe_gt *gt) | ||
| 80 | { | ||
| 81 | return xe_gt_sriov_pf_migration_init(gt); | ||
| 82 | } | ||
| 83 | |||
| 71 | static bool pf_needs_enable_ggtt_guest_update(struct xe_device *xe) | 84 | static bool pf_needs_enable_ggtt_guest_update(struct xe_device *xe) |
| 72 | { | 85 | { |
| 73 | return GRAPHICS_VERx100(xe) == 1200; | 86 | return GRAPHICS_VERx100(xe) == 1200; |
| @@ -90,7 +103,6 @@ void xe_gt_sriov_pf_init_hw(struct xe_gt *gt) · 16 unmodified lines | |||
| 90 | pf_enable_ggtt_guest_update(gt); | 103 | pf_enable_ggtt_guest_update(gt); |
| 91 | 104 | ||
| 92 | xe_gt_sriov_pf_service_update(gt); | 105 | xe_gt_sriov_pf_service_update(gt); |
| 93 | xe_gt_sriov_pf_migration_init(gt); | ||
| 94 | } | 106 | } |
| 95 | 107 | ||
| 96 | static u32 pf_get_vf_regs_stride(struct xe_device *xe) | 108 | static u32 pf_get_vf_regs_stride(struct xe_device *xe) |
| @@ -10,6 +10,7 @@ struct xe_gt; · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | #ifdef CONFIG_PCI_IOV | 11 | #ifdef CONFIG_PCI_IOV |
| 12 | int xe_gt_sriov_pf_init_early(struct xe_gt *gt); | 12 | int xe_gt_sriov_pf_init_early(struct xe_gt *gt); |
| 13 | int xe_gt_sriov_pf_init(struct xe_gt *gt); | ||
| 13 | void xe_gt_sriov_pf_init_hw(struct xe_gt *gt); | 14 | void xe_gt_sriov_pf_init_hw(struct xe_gt *gt); |
| 14 | void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid); | 15 | void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid); |
| 15 | void xe_gt_sriov_pf_restart(struct xe_gt *gt); | 16 | void xe_gt_sriov_pf_restart(struct xe_gt *gt); |
| @@ -19,6 +20,11 @@ static inline int xe_gt_sriov_pf_init_early(struct xe_gt *gt) · 3 unmodified lines | |||
| 19 | return 0; | 20 | return 0; |
| 20 | } | 21 | } |
| 21 | 22 | ||
| 23 | static inline int xe_gt_sriov_pf_init(struct xe_gt *gt) | ||
| 24 | { | ||
| 25 | return 0; | ||
| 26 | } | ||
| 27 | |||
| 22 | static inline void xe_gt_sriov_pf_init_hw(struct xe_gt *gt) | 28 | static inline void xe_gt_sriov_pf_init_hw(struct xe_gt *gt) |
| 23 | { | 29 | { |
| 24 | } | 30 | } |
| @@ -1724,7 +1724,8 @@ void xe_guc_ct_snapshot_print(struct xe_guc_ct_snapshot *snapshot, · 1723 unmodified lines | |||
| 1724 | snapshot->g2h_outstanding); | 1724 | snapshot->g2h_outstanding); |
| 1725 | 1725 | ||
| 1726 | if (snapshot->ctb) | 1726 | if (snapshot->ctb) |
| 1727 | xe_print_blob_ascii85(p, "CTB data", snapshot->ctb, 0, snapshot->ctb_size); | 1727 | xe_print_blob_ascii85(p, "CTB data", '\n', |
| 1728 | snapshot->ctb, 0, snapshot->ctb_size); | ||
| 1728 | } else { | 1729 | } else { |
| 1729 | drm_puts(p, "CT disabled\n"); | 1730 | drm_puts(p, "CT disabled\n"); |
| 1730 | } | 1731 | } |
| @@ -211,8 +211,10 @@ void xe_guc_log_snapshot_print(struct xe_guc_log_snapshot *snapshot, struct drm_ · 210 unmodified lines | |||
| 211 | remain = snapshot->size; | 211 | remain = snapshot->size; |
| 212 | for (i = 0; i < snapshot->num_chunks; i++) { | 212 | for (i = 0; i < snapshot->num_chunks; i++) { |
| 213 | size_t size = min(GUC_LOG_CHUNK_SIZE, remain); | 213 | size_t size = min(GUC_LOG_CHUNK_SIZE, remain); |
| 214 | const char *prefix = i ? NULL : "Log data"; | ||
| 215 | char suffix = i == snapshot->num_chunks - 1 ? '\n' : 0; | ||
| 214 | 216 | ||
| 215 | xe_print_blob_ascii85(p, i ? NULL : "Log data", snapshot->copy[i], 0, size); | 217 | xe_print_blob_ascii85(p, prefix, suffix, snapshot->copy[i], 0, size); |
| 216 | remain -= size; | 218 | remain -= size; |
| 217 | } | 219 | } |
| 218 | } | 220 | } |
| @@ -237,7 +237,6 @@ static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream) · 236 unmodified lines | |||
| 237 | u32 tail, hw_tail, partial_report_size, available; | 237 | u32 tail, hw_tail, partial_report_size, available; |
| 238 | int report_size = stream->oa_buffer.format->size; | 238 | int report_size = stream->oa_buffer.format->size; |
| 239 | unsigned long flags; | 239 | unsigned long flags; |
| 240 | bool pollin; | ||
| 241 | 240 | ||
| 242 | spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); | 241 | spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); |
| 243 | 242 | ||
| @@ -282,11 +281,11 @@ static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream) · 38 unmodified lines | |||
| 282 | stream->oa_buffer.tail = tail; | 281 | stream->oa_buffer.tail = tail; |
| 283 | 282 | ||
| 284 | available = xe_oa_circ_diff(stream, stream->oa_buffer.tail, stream->oa_buffer.head); | 283 | available = xe_oa_circ_diff(stream, stream->oa_buffer.tail, stream->oa_buffer.head); |
| 285 | pollin = available >= stream->wait_num_reports * report_size; | 284 | stream->pollin = available >= stream->wait_num_reports * report_size; |
| 286 | 285 | ||
| 287 | spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); | 286 | spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); |
| 288 | 287 | ||
| 289 | return pollin; | 288 | return stream->pollin; |
| 290 | } | 289 | } |
| 291 | 290 | ||
| 292 | static enum hrtimer_restart xe_oa_poll_check_timer_cb(struct hrtimer *hrtimer) | 291 | static enum hrtimer_restart xe_oa_poll_check_timer_cb(struct hrtimer *hrtimer) |
| @@ -294,10 +293,8 @@ static enum hrtimer_restart xe_oa_poll_check_timer_cb(struct hrtimer *hrtimer) · 1 unmodified line | |||
| 294 | struct xe_oa_stream *stream = | 293 | struct xe_oa_stream *stream = |
| 295 | container_of(hrtimer, typeof(*stream), poll_check_timer); | 294 | container_of(hrtimer, typeof(*stream), poll_check_timer); |
| 296 | 295 | ||
| 297 | if (xe_oa_buffer_check_unlocked(stream)) { | 296 | if (xe_oa_buffer_check_unlocked(stream)) |
| 298 | stream->pollin = true; | ||
| 299 | wake_up(&stream->poll_wq); | 297 | wake_up(&stream->poll_wq); |
| 300 | } | ||
| 301 | 298 | ||
| 302 | hrtimer_forward_now(hrtimer, ns_to_ktime(stream->poll_period_ns)); | 299 | hrtimer_forward_now(hrtimer, ns_to_ktime(stream->poll_period_ns)); |
| 303 | 300 | ||
| @@ -452,6 +449,12 @@ static u32 __oa_ccs_select(struct xe_oa_stream *stream) · 148 unmodified lines | |||
| 452 | return val; | 449 | return val; |
| 453 | } | 450 | } |
| 454 | 451 | ||
| 452 | static u32 __oactrl_used_bits(struct xe_oa_stream *stream) | ||
| 453 | { | ||
| 454 | return stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG ? | ||
| 455 | OAG_OACONTROL_USED_BITS : OAM_OACONTROL_USED_BITS; | ||
| 456 | } | ||
| 457 | |||
| 455 | static void xe_oa_enable(struct xe_oa_stream *stream) | 458 | static void xe_oa_enable(struct xe_oa_stream *stream) |
| 456 | { | 459 | { |
| 457 | const struct xe_oa_format *format = stream->oa_buffer.format; | 460 | const struct xe_oa_format *format = stream->oa_buffer.format; |
| @@ -472,14 +475,14 @@ static void xe_oa_enable(struct xe_oa_stream *stream) · 14 unmodified lines | |||
| 472 | stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG) | 475 | stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG) |
| 473 | val |= OAG_OACONTROL_OA_PES_DISAG_EN; | 476 | val |= OAG_OACONTROL_OA_PES_DISAG_EN; |
| 474 | 477 | ||
| 475 | xe_mmio_write32(&stream->gt->mmio, regs->oa_ctrl, val); | 478 | xe_mmio_rmw32(&stream->gt->mmio, regs->oa_ctrl, __oactrl_used_bits(stream), val); |
| 476 | } | 479 | } |
| 477 | 480 | ||
| 478 | static void xe_oa_disable(struct xe_oa_stream *stream) | 481 | static void xe_oa_disable(struct xe_oa_stream *stream) |
| 479 | { | 482 | { |
| 480 | struct xe_mmio *mmio = &stream->gt->mmio; | 483 | struct xe_mmio *mmio = &stream->gt->mmio; |
| 481 | 484 | ||
| 482 | xe_mmio_write32(mmio, __oa_regs(stream)->oa_ctrl, 0); | 485 | xe_mmio_rmw32(mmio, __oa_regs(stream)->oa_ctrl, __oactrl_used_bits(stream), 0); |
| 483 | if (xe_mmio_wait32(mmio, __oa_regs(stream)->oa_ctrl, | 486 | if (xe_mmio_wait32(mmio, __oa_regs(stream)->oa_ctrl, |
| 484 | OAG_OACONTROL_OA_COUNTER_ENABLE, 0, 50000, NULL, false)) | 487 | OAG_OACONTROL_OA_COUNTER_ENABLE, 0, 50000, NULL, false)) |
| 485 | drm_err(&stream->oa->xe->drm, | 488 | drm_err(&stream->oa->xe->drm, |
| @@ -2534,6 +2537,8 @@ static void __xe_oa_init_oa_units(struct xe_gt *gt) · 2048 unmodified lines | |||
| 2534 | u->type = DRM_XE_OA_UNIT_TYPE_OAM; | 2537 | u->type = DRM_XE_OA_UNIT_TYPE_OAM; |
| 2535 | } | 2538 | } |
| 2536 | 2539 | ||
| 2540 | xe_mmio_write32(>->mmio, u->regs.oa_ctrl, 0); | ||
| 2541 | |||
| 2537 | /* Ensure MMIO trigger remains disabled till there is a stream */ | 2542 | /* Ensure MMIO trigger remains disabled till there is a stream */ |
| 2538 | xe_mmio_write32(>->mmio, u->regs.oa_debug, | 2543 | xe_mmio_write32(>->mmio, u->regs.oa_debug, |
| 2539 | oag_configure_mmio_trigger(NULL, false)); | 2544 | oag_configure_mmio_trigger(NULL, false)); |
| @@ -57,12 +57,35 @@ bool xe_ttm_stolen_cpu_access_needs_ggtt(struct xe_device *xe) · 56 unmodified lines | |||
| 57 | return GRAPHICS_VERx100(xe) < 1270 && !IS_DGFX(xe); | 57 | return GRAPHICS_VERx100(xe) < 1270 && !IS_DGFX(xe); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static u32 get_wopcm_size(struct xe_device *xe) | ||
| 61 | { | ||
| 62 | u32 wopcm_size; | ||
| 63 | u64 val; | ||
| 64 | |||
| 65 | val = xe_mmio_read64_2x32(xe_root_tile_mmio(xe), STOLEN_RESERVED); | ||
| 66 | val = REG_FIELD_GET64(WOPCM_SIZE_MASK, val); | ||
| 67 | |||
| 68 | switch (val) { | ||
| 69 | case 0x5 ... 0x6: | ||
| 70 | val--; | ||
| 71 | fallthrough; | ||
| 72 | case 0x0 ... 0x3: | ||
| 73 | wopcm_size = (1U << val) * SZ_1M; | ||
| 74 | break; | ||
| 75 | default: | ||
| 76 | WARN(1, "Missing case wopcm_size=%llx\n", val); | ||
| 77 | wopcm_size = 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | return wopcm_size; | ||
| 81 | } | ||
| 82 | |||
| 60 | static s64 detect_bar2_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) | 83 | static s64 detect_bar2_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) |
| 61 | { | 84 | { |
| 62 | struct xe_tile *tile = xe_device_get_root_tile(xe); | 85 | struct xe_tile *tile = xe_device_get_root_tile(xe); |
| 63 | struct xe_mmio *mmio = xe_root_tile_mmio(xe); | 86 | struct xe_mmio *mmio = xe_root_tile_mmio(xe); |
| 64 | struct pci_dev *pdev = to_pci_dev(xe->drm.dev); | 87 | struct pci_dev *pdev = to_pci_dev(xe->drm.dev); |
| 65 | u64 stolen_size; | 88 | u64 stolen_size, wopcm_size; |
| 66 | u64 tile_offset; | 89 | u64 tile_offset; |
| 67 | u64 tile_size; | 90 | u64 tile_size; |
| 68 | 91 | ||
| @@ -74,7 +97,13 @@ static s64 detect_bar2_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) · 5 unmodified lines | |||
| 74 | if (drm_WARN_ON(&xe->drm, tile_size < mgr->stolen_base)) | 97 | if (drm_WARN_ON(&xe->drm, tile_size < mgr->stolen_base)) |
| 75 | return 0; | 98 | return 0; |
| 76 | 99 | ||
| 100 | /* Carve out the top of DSM as it contains the reserved WOPCM region */ | ||
| 101 | wopcm_size = get_wopcm_size(xe); | ||
| 102 | if (drm_WARN_ON(&xe->drm, !wopcm_size)) | ||
| 103 | return 0; | ||
| 104 | |||
| 77 | stolen_size = tile_size - mgr->stolen_base; | 105 | stolen_size = tile_size - mgr->stolen_base; |
| 106 | stolen_size -= wopcm_size; | ||
| 78 | 107 | ||
| 79 | /* Verify usage fits in the actual resource available */ | 108 | /* Verify usage fits in the actual resource available */ |
| 80 | if (mgr->stolen_base + stolen_size <= pci_resource_len(pdev, LMEM_BAR)) | 109 | if (mgr->stolen_base + stolen_size <= pci_resource_len(pdev, LMEM_BAR)) |
| @@ -89,29 +118,6 @@ static s64 detect_bar2_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) · 8 unmodified lines | |||
| 89 | return ALIGN_DOWN(stolen_size, SZ_1M); | 118 | return ALIGN_DOWN(stolen_size, SZ_1M); |
| 90 | } | 119 | } |
| 91 | 120 | ||
| 92 | static u32 get_wopcm_size(struct xe_device *xe) | ||
| 93 | { | ||
| 94 | u32 wopcm_size; | ||
| 95 | u64 val; | ||
| 96 | |||
| 97 | val = xe_mmio_read64_2x32(xe_root_tile_mmio(xe), STOLEN_RESERVED); | ||
| 98 | val = REG_FIELD_GET64(WOPCM_SIZE_MASK, val); | ||
| 99 | |||
| 100 | switch (val) { | ||
| 101 | case 0x5 ... 0x6: | ||
| 102 | val--; | ||
| 103 | fallthrough; | ||
| 104 | case 0x0 ... 0x3: | ||
| 105 | wopcm_size = (1U << val) * SZ_1M; | ||
| 106 | break; | ||
| 107 | default: | ||
| 108 | WARN(1, "Missing case wopcm_size=%llx\n", val); | ||
| 109 | wopcm_size = 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | return wopcm_size; | ||
| 113 | } | ||
| 114 | |||
| 115 | static u32 detect_bar2_integrated(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) | 121 | static u32 detect_bar2_integrated(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) |
| 116 | { | 122 | { |
| 117 | struct pci_dev *pdev = to_pci_dev(xe->drm.dev); | 123 | struct pci_dev *pdev = to_pci_dev(xe->drm.dev); |
| @@ -619,6 +619,8 @@ static int host1x_probe(struct platform_device *pdev) · 618 unmodified lines | |||
| 619 | goto free_contexts; | 619 | goto free_contexts; |
| 620 | } | 620 | } |
| 621 | 621 | ||
| 622 | mutex_init(&host->intr_mutex); | ||
| 623 | |||
| 622 | pm_runtime_enable(&pdev->dev); | 624 | pm_runtime_enable(&pdev->dev); |
| 623 | 625 | ||
| 624 | err = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); | 626 | err = devm_tegra_core_dev_init_opp_table_common(&pdev->dev); |
| @@ -104,8 +104,6 @@ int host1x_intr_init(struct host1x *host) · 103 unmodified lines | |||
| 104 | unsigned int id; | 104 | unsigned int id; |
| 105 | int i, err; | 105 | int i, err; |
| 106 | 106 | ||
| 107 | mutex_init(&host->intr_mutex); | ||
| 108 | |||
| 109 | for (id = 0; id < host1x_syncpt_nb_pts(host); ++id) { | 107 | for (id = 0; id < host1x_syncpt_nb_pts(host); ++id) { |
| 110 | struct host1x_syncpt *syncpt = &host->syncpt[id]; | 108 | struct host1x_syncpt *syncpt = &host->syncpt[id]; |
| 111 | 109 | ||
| @@ -570,6 +570,8 @@ config HID_LED · 569 unmodified lines | |||
| 570 | 570 | ||
| 571 | config HID_LENOVO | 571 | config HID_LENOVO |
| 572 | tristate "Lenovo / Thinkpad devices" | 572 | tristate "Lenovo / Thinkpad devices" |
| 573 | depends on ACPI | ||
| 574 | select ACPI_PLATFORM_PROFILE | ||
| 573 | select NEW_LEDS | 575 | select NEW_LEDS |
| 574 | select LEDS_CLASS | 576 | select LEDS_CLASS |
| 575 | help | 577 | help |
| @@ -1167,7 +1169,8 @@ config HID_TOPRE · 591 unmodified lines | |||
| 1167 | tristate "Topre REALFORCE keyboards" | 1169 | tristate "Topre REALFORCE keyboards" |
| 1168 | depends on HID | 1170 | depends on HID |
| 1169 | help | 1171 | help |
| 1170 | Say Y for N-key rollover support on Topre REALFORCE R2 108/87 key keyboards. | 1172 | Say Y for N-key rollover support on Topre REALFORCE R2 108/87 key and |
| 1173 | Topre REALFORCE R3S 87 key keyboards. | ||
| 1171 | 1174 | ||
| 1172 | config HID_THINGM | 1175 | config HID_THINGM |
| 1173 | tristate "ThingM blink(1) USB RGB LED" | 1176 | tristate "ThingM blink(1) USB RGB LED" |
| @@ -1374,10 +1377,6 @@ endmenu · 200 unmodified lines | |||
| 1374 | 1377 | ||
| 1375 | source "drivers/hid/bpf/Kconfig" | 1378 | source "drivers/hid/bpf/Kconfig" |
| 1376 | 1379 | ||
| 1377 | endif # HID | ||
| 1378 | |||
| 1379 | source "drivers/hid/usbhid/Kconfig" | ||
| 1380 | |||
| 1381 | source "drivers/hid/i2c-hid/Kconfig" | 1380 | source "drivers/hid/i2c-hid/Kconfig" |
| 1382 | 1381 | ||
| 1383 | source "drivers/hid/intel-ish-hid/Kconfig" | 1382 | source "drivers/hid/intel-ish-hid/Kconfig" |
| @@ -1388,4 +1387,10 @@ source "drivers/hid/surface-hid/Kconfig" · 4 unmodified lines | |||
| 1388 | 1387 | ||
| 1389 | source "drivers/hid/intel-thc-hid/Kconfig" | 1388 | source "drivers/hid/intel-thc-hid/Kconfig" |
| 1390 | 1389 | ||
| 1390 | endif # HID | ||
| 1391 | |||
| 1392 | # USB support may be used with HID disabled | ||
| 1393 | |||
| 1394 | source "drivers/hid/usbhid/Kconfig" | ||
| 1395 | |||
| 1391 | endif # HID_SUPPORT | 1396 | endif # HID_SUPPORT |
| @@ -5,7 +5,6 @@ menu "AMD SFH HID Support" · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | config AMD_SFH_HID | 6 | config AMD_SFH_HID |
| 7 | tristate "AMD Sensor Fusion Hub" | 7 | tristate "AMD Sensor Fusion Hub" |
| 8 | depends on HID | ||
| 9 | depends on X86 | 8 | depends on X86 |
| 10 | help | 9 | help |
| 11 | If you say yes to this option, support will be included for the | 10 | If you say yes to this option, support will be included for the |
| @@ -474,6 +474,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, · 473 unmodified lines | |||
| 474 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015) | 474 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015) |
| 475 | table = magic_keyboard_2015_fn_keys; | 475 | table = magic_keyboard_2015_fn_keys; |
| 476 | else if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 || | 476 | else if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 || |
| 477 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024 || | ||
| 477 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 || | 478 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 || |
| 478 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021) | 479 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021) |
| 479 | table = apple2021_fn_keys; | 480 | table = apple2021_fn_keys; |
| @@ -545,6 +546,9 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, · 65 unmodified lines | |||
| 545 | } | 546 | } |
| 546 | } | 547 | } |
| 547 | 548 | ||
| 549 | if (usage->hid == 0xc0301) /* Omoton KB066 quirk */ | ||
| 550 | code = KEY_F6; | ||
| 551 | |||
| 548 | if (usage->code != code) { | 552 | if (usage->code != code) { |
| 549 | input_event_with_scancode(input, usage->type, code, usage->hid, value); | 553 | input_event_with_scancode(input, usage->type, code, usage->hid, value); |
| 550 | 554 | ||
| @@ -1150,6 +1154,10 @@ static const struct hid_device_id apple_devices[] = { · 599 unmodified lines | |||
| 1150 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, | 1154 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, |
| 1151 | { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021), | 1155 | { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021), |
| 1152 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, | 1156 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, |
| 1157 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024), | ||
| 1158 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, | ||
| 1159 | { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024), | ||
| 1160 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, | ||
| 1153 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), | 1161 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), |
| 1154 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, | 1162 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, |
| 1155 | { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), | 1163 | { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), |
| @@ -553,7 +553,7 @@ static void corsair_void_battery_remove_work_handler(struct work_struct *work) · 552 unmodified lines | |||
| 553 | static void corsair_void_battery_add_work_handler(struct work_struct *work) | 553 | static void corsair_void_battery_add_work_handler(struct work_struct *work) |
| 554 | { | 554 | { |
| 555 | struct corsair_void_drvdata *drvdata; | 555 | struct corsair_void_drvdata *drvdata; |
| 556 | struct power_supply_config psy_cfg; | 556 | struct power_supply_config psy_cfg = {}; |
| 557 | struct power_supply *new_supply; | 557 | struct power_supply *new_supply; |
| 558 | 558 | ||
| 559 | drvdata = container_of(work, struct corsair_void_drvdata, | 559 | drvdata = container_of(work, struct corsair_void_drvdata, |
| @@ -726,6 +726,7 @@ static void corsair_void_remove(struct hid_device *hid_dev) · 166 unmodified lines | |||
| 726 | if (drvdata->battery) | 726 | if (drvdata->battery) |
| 727 | power_supply_unregister(drvdata->battery); | 727 | power_supply_unregister(drvdata->battery); |
| 728 | 728 | ||
| 729 | cancel_delayed_work_sync(&drvdata->delayed_status_work); | ||
| 729 | cancel_delayed_work_sync(&drvdata->delayed_firmware_work); | 730 | cancel_delayed_work_sync(&drvdata->delayed_firmware_work); |
| 730 | sysfs_remove_group(&hid_dev->dev.kobj, &corsair_void_attr_group); | 731 | sysfs_remove_group(&hid_dev->dev.kobj, &corsair_void_attr_group); |
| 731 | } | 732 | } |
| @@ -184,6 +184,7 @@ · 183 unmodified lines | |||
| 184 | #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 | 184 | #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 |
| 185 | #define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 | 185 | #define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 |
| 186 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c | 186 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c |
| 187 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024 0x0320 | ||
| 187 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a | 188 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a |
| 188 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f | 189 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f |
| 189 | #define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102 | 190 | #define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102 |
| @@ -1095,6 +1096,7 @@ · 905 unmodified lines | |||
| 1095 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 | 1096 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 |
| 1096 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003 0x3003 | 1097 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003 0x3003 |
| 1097 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 | 1098 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 |
| 1099 | #define USB_DEVICE_ID_QUANTA_HP_5MP_CAMERA_5473 0x5473 | ||
| 1098 | 1100 | ||
| 1099 | #define I2C_VENDOR_ID_RAYDIUM 0x2386 | 1101 | #define I2C_VENDOR_ID_RAYDIUM 0x2386 |
| 1100 | #define I2C_PRODUCT_ID_RAYDIUM_4B33 0x4b33 | 1102 | #define I2C_PRODUCT_ID_RAYDIUM_4B33 0x4b33 |
| @@ -1301,6 +1303,7 @@ · 200 unmodified lines | |||
| 1301 | #define USB_VENDOR_ID_TOPRE 0x0853 | 1303 | #define USB_VENDOR_ID_TOPRE 0x0853 |
| 1302 | #define USB_DEVICE_ID_TOPRE_REALFORCE_R2_108 0x0148 | 1304 | #define USB_DEVICE_ID_TOPRE_REALFORCE_R2_108 0x0148 |
| 1303 | #define USB_DEVICE_ID_TOPRE_REALFORCE_R2_87 0x0146 | 1305 | #define USB_DEVICE_ID_TOPRE_REALFORCE_R2_87 0x0146 |
| 1306 | #define USB_DEVICE_ID_TOPRE_REALFORCE_R3S_87 0x0313 | ||
| 1304 | 1307 | ||
| 1305 | #define USB_VENDOR_ID_TOPSEED 0x0766 | 1308 | #define USB_VENDOR_ID_TOPSEED 0x0766 |
| 1306 | #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 | 1309 | #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 |
| @@ -32,9 +32,7 @@ · 31 unmodified lines | |||
| 32 | #include <linux/leds.h> | 32 | #include <linux/leds.h> |
| 33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
| 34 | 34 | ||
| 35 | #if IS_ENABLED(CONFIG_ACPI_PLATFORM_PROFILE) | ||
| 36 | #include <linux/platform_profile.h> | 35 | #include <linux/platform_profile.h> |
| 37 | #endif /* CONFIG_ACPI_PLATFORM_PROFILE */ | ||
| 38 | 36 | ||
| 39 | #include "hid-ids.h" | 37 | #include "hid-ids.h" |
| 40 | 38 | ||
| @@ -730,13 +728,10 @@ static int lenovo_raw_event_TP_X12_tab(struct hid_device *hdev, u32 raw_data) · 689 unmodified lines | |||
| 730 | if (hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB) { | 728 | if (hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB) { |
| 731 | report_key_event(input, KEY_RFKILL); | 729 | report_key_event(input, KEY_RFKILL); |
| 732 | return 1; | 730 | return 1; |
| 733 | } | 731 | } else { |
| 734 | #if IS_ENABLED(CONFIG_ACPI_PLATFORM_PROFILE) | ||
| 735 | else { | ||
| 736 | platform_profile_cycle(); | 732 | platform_profile_cycle(); |
| 737 | return 1; | 733 | return 1; |
| 738 | } | 734 | } |
| 739 | #endif /* CONFIG_ACPI_PLATFORM_PROFILE */ | ||
| 740 | return 0; | 735 | return 0; |
| 741 | case TP_X12_RAW_HOTKEY_FN_F10: | 736 | case TP_X12_RAW_HOTKEY_FN_F10: |
| 742 | /* TAB1 has PICKUP Phone and TAB2 use Snipping tool*/ | 737 | /* TAB1 has PICKUP Phone and TAB2 use Snipping tool*/ |
| @@ -1679,9 +1679,12 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) · 1678 unmodified lines | |||
| 1679 | break; | 1679 | break; |
| 1680 | } | 1680 | } |
| 1681 | 1681 | ||
| 1682 | if (suffix) | 1682 | if (suffix) { |
| 1683 | hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, | 1683 | hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, |
| 1684 | "%s %s", hdev->name, suffix); | 1684 | "%s %s", hdev->name, suffix); |
| 1685 | if (!hi->input->name) | ||
| 1686 | return -ENOMEM; | ||
| 1687 | } | ||
| 1685 | 1688 | ||
| 1686 | return 0; | 1689 | return 0; |
| 1687 | } | 1690 | } |
| @@ -891,6 +891,7 @@ static const struct hid_device_id hid_ignore_list[] = { · 890 unmodified lines | |||
| 891 | { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) }, | 891 | { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) }, |
| 892 | #endif | 892 | #endif |
| 893 | { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) }, | 893 | { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) }, |
| 894 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_HP_5MP_CAMERA_5473) }, | ||
| 894 | { } | 895 | { } |
| 895 | }; | 896 | }; |
| 896 | 897 | ||
| @@ -313,6 +313,7 @@ struct steam_device { · 312 unmodified lines | |||
| 313 | u16 rumble_left; | 313 | u16 rumble_left; |
| 314 | u16 rumble_right; | 314 | u16 rumble_right; |
| 315 | unsigned int sensor_timestamp_us; | 315 | unsigned int sensor_timestamp_us; |
| 316 | struct work_struct unregister_work; | ||
| 316 | }; | 317 | }; |
| 317 | 318 | ||
| 318 | static int steam_recv_report(struct steam_device *steam, | 319 | static int steam_recv_report(struct steam_device *steam, |
| @@ -1050,10 +1051,10 @@ static void steam_mode_switch_cb(struct work_struct *work) · 731 unmodified lines | |||
| 1050 | struct steam_device, mode_switch); | 1051 | struct steam_device, mode_switch); |
| 1051 | unsigned long flags; | 1052 | unsigned long flags; |
| 1052 | bool client_opened; | 1053 | bool client_opened; |
| 1053 | steam->gamepad_mode = !steam->gamepad_mode; | ||
| 1054 | if (!lizard_mode) | 1054 | if (!lizard_mode) |
| 1055 | return; | 1055 | return; |
| 1056 | 1056 | ||
| 1057 | steam->gamepad_mode = !steam->gamepad_mode; | ||
| 1057 | if (steam->gamepad_mode) | 1058 | if (steam->gamepad_mode) |
| 1058 | steam_set_lizard_mode(steam, false); | 1059 | steam_set_lizard_mode(steam, false); |
| 1059 | else { | 1060 | else { |
| @@ -1072,6 +1073,31 @@ static void steam_mode_switch_cb(struct work_struct *work) · 12 unmodified lines | |||
| 1072 | } | 1073 | } |
| 1073 | } | 1074 | } |
| 1074 | 1075 | ||
| 1076 | static void steam_work_unregister_cb(struct work_struct *work) | ||
| 1077 | { | ||
| 1078 | struct steam_device *steam = container_of(work, struct steam_device, | ||
| 1079 | unregister_work); | ||
| 1080 | unsigned long flags; | ||
| 1081 | bool connected; | ||
| 1082 | bool opened; | ||
| 1083 | |||
| 1084 | spin_lock_irqsave(&steam->lock, flags); | ||
| 1085 | opened = steam->client_opened; | ||
| 1086 | connected = steam->connected; | ||
| 1087 | spin_unlock_irqrestore(&steam->lock, flags); | ||
| 1088 | |||
| 1089 | if (connected) { | ||
| 1090 | if (opened) { | ||
| 1091 | steam_sensors_unregister(steam); | ||
| 1092 | steam_input_unregister(steam); | ||
| 1093 | } else { | ||
| 1094 | steam_set_lizard_mode(steam, lizard_mode); | ||
| 1095 | steam_input_register(steam); | ||
| 1096 | steam_sensors_register(steam); | ||
| 1097 | } | ||
| 1098 | } | ||
| 1099 | } | ||
| 1100 | |||
| 1075 | static bool steam_is_valve_interface(struct hid_device *hdev) | 1101 | static bool steam_is_valve_interface(struct hid_device *hdev) |
| 1076 | { | 1102 | { |
| 1077 | struct hid_report_enum *rep_enum; | 1103 | struct hid_report_enum *rep_enum; |
| @@ -1117,8 +1143,7 @@ static int steam_client_ll_open(struct hid_device *hdev) · 39 unmodified lines | |||
| 1117 | steam->client_opened++; | 1143 | steam->client_opened++; |
| 1118 | spin_unlock_irqrestore(&steam->lock, flags); | 1144 | spin_unlock_irqrestore(&steam->lock, flags); |
| 1119 | 1145 | ||
| 1120 | steam_sensors_unregister(steam); | 1146 | schedule_work(&steam->unregister_work); |
| 1121 | steam_input_unregister(steam); | ||
| 1122 | 1147 | ||
| 1123 | return 0; | 1148 | return 0; |
| 1124 | } | 1149 | } |
| @@ -1135,11 +1160,7 @@ static void steam_client_ll_close(struct hid_device *hdev) · 10 unmodified lines | |||
| 1135 | connected = steam->connected && !steam->client_opened; | 1160 | connected = steam->connected && !steam->client_opened; |
| 1136 | spin_unlock_irqrestore(&steam->lock, flags); | 1161 | spin_unlock_irqrestore(&steam->lock, flags); |
| 1137 | 1162 | ||
| 1138 | if (connected) { | 1163 | schedule_work(&steam->unregister_work); |
| 1139 | steam_set_lizard_mode(steam, lizard_mode); | ||
| 1140 | steam_input_register(steam); | ||
| 1141 | steam_sensors_register(steam); | ||
| 1142 | } | ||
| 1143 | } | 1164 | } |
| 1144 | 1165 | ||
| 1145 | static int steam_client_ll_raw_request(struct hid_device *hdev, | 1166 | static int steam_client_ll_raw_request(struct hid_device *hdev, |
| @@ -1231,6 +1252,7 @@ static int steam_probe(struct hid_device *hdev, · 85 unmodified lines | |||
| 1231 | INIT_LIST_HEAD(&steam->list); | 1252 | INIT_LIST_HEAD(&steam->list); |
| 1232 | INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); | 1253 | INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); |
| 1233 | steam->sensor_timestamp_us = 0; | 1254 | steam->sensor_timestamp_us = 0; |
| 1255 | INIT_WORK(&steam->unregister_work, steam_work_unregister_cb); | ||
| 1234 | 1256 | ||
| 1235 | /* | 1257 | /* |
| 1236 | * With the real steam controller interface, do not connect hidraw. | 1258 | * With the real steam controller interface, do not connect hidraw. |
| @@ -1291,6 +1313,7 @@ err_cancel_work: · 54 unmodified lines | |||
| 1291 | cancel_work_sync(&steam->work_connect); | 1313 | cancel_work_sync(&steam->work_connect); |
| 1292 | cancel_delayed_work_sync(&steam->mode_switch); | 1314 | cancel_delayed_work_sync(&steam->mode_switch); |
| 1293 | cancel_work_sync(&steam->rumble_work); | 1315 | cancel_work_sync(&steam->rumble_work); |
| 1316 | cancel_work_sync(&steam->unregister_work); | ||
| 1294 | 1317 | ||
| 1295 | return ret; | 1318 | return ret; |
| 1296 | } | 1319 | } |
| @@ -1307,6 +1330,7 @@ static void steam_remove(struct hid_device *hdev) · 10 unmodified lines | |||
| 1307 | cancel_delayed_work_sync(&steam->mode_switch); | 1330 | cancel_delayed_work_sync(&steam->mode_switch); |
| 1308 | cancel_work_sync(&steam->work_connect); | 1331 | cancel_work_sync(&steam->work_connect); |
| 1309 | cancel_work_sync(&steam->rumble_work); | 1332 | cancel_work_sync(&steam->rumble_work); |
| 1333 | cancel_work_sync(&steam->unregister_work); | ||
| 1310 | hid_destroy_device(steam->client_hdev); | 1334 | hid_destroy_device(steam->client_hdev); |
| 1311 | steam->client_hdev = NULL; | 1335 | steam->client_hdev = NULL; |
| 1312 | steam->client_opened = 0; | 1336 | steam->client_opened = 0; |
| @@ -1593,13 +1617,13 @@ static void steam_do_deck_input_event(struct steam_device *steam, · 280 unmodified lines | |||
| 1593 | 1617 | ||
| 1594 | if (!(b9 & BIT(6)) && steam->did_mode_switch) { | 1618 | if (!(b9 & BIT(6)) && steam->did_mode_switch) { |
| 1595 | steam->did_mode_switch = false; | 1619 | steam->did_mode_switch = false; |
| 1596 | cancel_delayed_work_sync(&steam->mode_switch); | 1620 | cancel_delayed_work(&steam->mode_switch); |
| 1597 | } else if (!steam->client_opened && (b9 & BIT(6)) && !steam->did_mode_switch) { | 1621 | } else if (!steam->client_opened && (b9 & BIT(6)) && !steam->did_mode_switch) { |
| 1598 | steam->did_mode_switch = true; | 1622 | steam->did_mode_switch = true; |
| 1599 | schedule_delayed_work(&steam->mode_switch, 45 * HZ / 100); | 1623 | schedule_delayed_work(&steam->mode_switch, 45 * HZ / 100); |
| 1600 | } | 1624 | } |
| 1601 | 1625 | ||
| 1602 | if (!steam->gamepad_mode) | 1626 | if (!steam->gamepad_mode && lizard_mode) |
| 1603 | return; | 1627 | return; |
| 1604 | 1628 | ||
| 1605 | lpad_touched = b10 & BIT(3); | 1629 | lpad_touched = b10 & BIT(3); |
| @@ -1669,7 +1693,7 @@ static void steam_do_deck_sensors_event(struct steam_device *steam, · 63 unmodified lines | |||
| 1669 | */ | 1693 | */ |
| 1670 | steam->sensor_timestamp_us += 4000; | 1694 | steam->sensor_timestamp_us += 4000; |
| 1671 | 1695 | ||
| 1672 | if (!steam->gamepad_mode) | 1696 | if (!steam->gamepad_mode && lizard_mode) |
| 1673 | return; | 1697 | return; |
| 1674 | 1698 | ||
| 1675 | input_event(sensors, EV_MSC, MSC_TIMESTAMP, steam->sensor_timestamp_us); | 1699 | input_event(sensors, EV_MSC, MSC_TIMESTAMP, steam->sensor_timestamp_us); |
| @@ -171,7 +171,7 @@ static void thrustmaster_interrupts(struct hid_device *hdev) · 170 unmodified lines | |||
| 171 | b_ep = ep->desc.bEndpointAddress; | 171 | b_ep = ep->desc.bEndpointAddress; |
| 172 | 172 | ||
| 173 | /* Are the expected endpoints present? */ | 173 | /* Are the expected endpoints present? */ |
| 174 | u8 ep_addr[1] = {b_ep}; | 174 | u8 ep_addr[2] = {b_ep, 0}; |
| 175 | 175 | ||
| 176 | if (!usb_check_int_endpoints(usbif, ep_addr)) { | 176 | if (!usb_check_int_endpoints(usbif, ep_addr)) { |
| 177 | hid_err(hdev, "Unexpected non-int endpoint\n"); | 177 | hid_err(hdev, "Unexpected non-int endpoint\n"); |
| @@ -29,6 +29,11 @@ static const __u8 *topre_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 28 unmodified lines | |||
| 29 | hid_info(hdev, | 29 | hid_info(hdev, |
| 30 | "fixing up Topre REALFORCE keyboard report descriptor\n"); | 30 | "fixing up Topre REALFORCE keyboard report descriptor\n"); |
| 31 | rdesc[72] = 0x02; | 31 | rdesc[72] = 0x02; |
| 32 | } else if (*rsize >= 106 && rdesc[28] == 0x29 && rdesc[29] == 0xe7 && | ||
| 33 | rdesc[30] == 0x81 && rdesc[31] == 0x00) { | ||
| 34 | hid_info(hdev, | ||
| 35 | "fixing up Topre REALFORCE keyboard report descriptor\n"); | ||
| 36 | rdesc[31] = 0x02; | ||
| 32 | } | 37 | } |
| 33 | return rdesc; | 38 | return rdesc; |
| 34 | } | 39 | } |
| @@ -38,6 +43,8 @@ static const struct hid_device_id topre_id_table[] = { · 3 unmodified lines | |||
| 38 | USB_DEVICE_ID_TOPRE_REALFORCE_R2_108) }, | 43 | USB_DEVICE_ID_TOPRE_REALFORCE_R2_108) }, |
| 39 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE, | 44 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE, |
| 40 | USB_DEVICE_ID_TOPRE_REALFORCE_R2_87) }, | 45 | USB_DEVICE_ID_TOPRE_REALFORCE_R2_87) }, |
| 46 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE, | ||
| 47 | USB_DEVICE_ID_TOPRE_REALFORCE_R3S_87) }, | ||
| 41 | { } | 48 | { } |
| 42 | }; | 49 | }; |
| 43 | MODULE_DEVICE_TABLE(hid, topre_id_table); | 50 | MODULE_DEVICE_TABLE(hid, topre_id_table); |
| @@ -106,6 +106,8 @@ static int winwing_init_led(struct hid_device *hdev, · 105 unmodified lines | |||
| 106 | "%s::%s", | 106 | "%s::%s", |
| 107 | dev_name(&input->dev), | 107 | dev_name(&input->dev), |
| 108 | info->led_name); | 108 | info->led_name); |
| 109 | if (!led->cdev.name) | ||
| 110 | return -ENOMEM; | ||
| 109 | 111 | ||
| 110 | ret = devm_led_classdev_register(&hdev->dev, &led->cdev); | 112 | ret = devm_led_classdev_register(&hdev->dev, &led->cdev); |
| 111 | if (ret) | 113 | if (ret) |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | menuconfig I2C_HID | 2 | menuconfig I2C_HID |
| 3 | tristate "I2C HID support" | 3 | tristate "I2C HID support" |
| 4 | default y | 4 | default y |
| 5 | depends on I2C && INPUT && HID | 5 | depends on I2C |
| 6 | 6 | ||
| 7 | if I2C_HID | 7 | if I2C_HID |
| 8 | 8 | ||
| @@ -6,7 +6,6 @@ config INTEL_ISH_HID · 5 unmodified lines | |||
| 6 | tristate "Intel Integrated Sensor Hub" | 6 | tristate "Intel Integrated Sensor Hub" |
| 7 | default n | 7 | default n |
| 8 | depends on X86 | 8 | depends on X86 |
| 9 | depends on HID | ||
| 10 | help | 9 | help |
| 11 | The Integrated Sensor Hub (ISH) enables the ability to offload | 10 | The Integrated Sensor Hub (ISH) enables the ability to offload |
| 12 | sensor polling and algorithm processing to a dedicated low power | 11 | sensor polling and algorithm processing to a dedicated low power |
| @@ -36,6 +36,8 @@ · 35 unmodified lines | |||
| 36 | #define PCI_DEVICE_ID_INTEL_ISH_ARL_H 0x7745 | 36 | #define PCI_DEVICE_ID_INTEL_ISH_ARL_H 0x7745 |
| 37 | #define PCI_DEVICE_ID_INTEL_ISH_ARL_S 0x7F78 | 37 | #define PCI_DEVICE_ID_INTEL_ISH_ARL_S 0x7F78 |
| 38 | #define PCI_DEVICE_ID_INTEL_ISH_LNL_M 0xA845 | 38 | #define PCI_DEVICE_ID_INTEL_ISH_LNL_M 0xA845 |
| 39 | #define PCI_DEVICE_ID_INTEL_ISH_PTL_H 0xE345 | ||
| 40 | #define PCI_DEVICE_ID_INTEL_ISH_PTL_P 0xE445 | ||
| 39 | 41 | ||
| 40 | #define REVISION_ID_CHT_A0 0x6 | 42 | #define REVISION_ID_CHT_A0 0x6 |
| 41 | #define REVISION_ID_CHT_Ax_SI 0x0 | 43 | #define REVISION_ID_CHT_Ax_SI 0x0 |
| @@ -517,6 +517,10 @@ static int ish_fw_reset_handler(struct ishtp_device *dev) · 516 unmodified lines | |||
| 517 | /* ISH FW is dead */ | 517 | /* ISH FW is dead */ |
| 518 | if (!ish_is_input_ready(dev)) | 518 | if (!ish_is_input_ready(dev)) |
| 519 | return -EPIPE; | 519 | return -EPIPE; |
| 520 | |||
| 521 | /* Send clock sync at once after reset */ | ||
| 522 | ishtp_dev->prev_sync = 0; | ||
| 523 | |||
| 520 | /* | 524 | /* |
| 521 | * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending | 525 | * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending |
| 522 | * RESET_NOTIFY_ACK - FW will be checking for it | 526 | * RESET_NOTIFY_ACK - FW will be checking for it |
| @@ -577,15 +581,14 @@ static void fw_reset_work_fn(struct work_struct *work) · 54 unmodified lines | |||
| 577 | */ | 581 | */ |
| 578 | static void _ish_sync_fw_clock(struct ishtp_device *dev) | 582 | static void _ish_sync_fw_clock(struct ishtp_device *dev) |
| 579 | { | 583 | { |
| 580 | static unsigned long prev_sync; | 584 | struct ipc_time_update_msg time = {}; |
| 581 | uint64_t usec; | ||
| 582 | 585 | ||
| 583 | if (prev_sync && time_before(jiffies, prev_sync + 20 * HZ)) | 586 | if (dev->prev_sync && time_before(jiffies, dev->prev_sync + 20 * HZ)) |
| 584 | return; | 587 | return; |
| 585 | 588 | ||
| 586 | prev_sync = jiffies; | 589 | dev->prev_sync = jiffies; |
| 587 | usec = ktime_to_us(ktime_get_boottime()); | 590 | /* The fields of time would be updated while sending message */ |
| 588 | ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t)); | 591 | ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &time, sizeof(time)); |
| 589 | } | 592 | } |
| 590 | 593 | ||
| 591 | /** | 594 | /** |
| @@ -26,9 +26,11 @@ · 25 unmodified lines | |||
| 26 | enum ishtp_driver_data_index { | 26 | enum ishtp_driver_data_index { |
| 27 | ISHTP_DRIVER_DATA_NONE, | 27 | ISHTP_DRIVER_DATA_NONE, |
| 28 | ISHTP_DRIVER_DATA_LNL_M, | 28 | ISHTP_DRIVER_DATA_LNL_M, |
| 29 | ISHTP_DRIVER_DATA_PTL, | ||
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 31 | #define ISH_FW_GEN_LNL_M "lnlm" | 32 | #define ISH_FW_GEN_LNL_M "lnlm" |
| 33 | #define ISH_FW_GEN_PTL "ptl" | ||
| 32 | 34 | ||
| 33 | #define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin" | 35 | #define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin" |
| 34 | #define ISH_FIRMWARE_PATH_ALL "intel/ish/ish_*.bin" | 36 | #define ISH_FIRMWARE_PATH_ALL "intel/ish/ish_*.bin" |
| @@ -37,6 +39,9 @@ static struct ishtp_driver_data ishtp_driver_data[] = { · 2 unmodified lines | |||
| 37 | [ISHTP_DRIVER_DATA_LNL_M] = { | 39 | [ISHTP_DRIVER_DATA_LNL_M] = { |
| 38 | .fw_generation = ISH_FW_GEN_LNL_M, | 40 | .fw_generation = ISH_FW_GEN_LNL_M, |
| 39 | }, | 41 | }, |
| 42 | [ISHTP_DRIVER_DATA_PTL] = { | ||
| 43 | .fw_generation = ISH_FW_GEN_PTL, | ||
| 44 | }, | ||
| 40 | }; | 45 | }; |
| 41 | 46 | ||
| 42 | static const struct pci_device_id ish_pci_tbl[] = { | 47 | static const struct pci_device_id ish_pci_tbl[] = { |
| @@ -63,6 +68,8 @@ static const struct pci_device_id ish_pci_tbl[] = { · 20 unmodified lines | |||
| 63 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_H)}, | 68 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_H)}, |
| 64 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_S)}, | 69 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_S)}, |
| 65 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_LNL_M), .driver_data = ISHTP_DRIVER_DATA_LNL_M}, | 70 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_LNL_M), .driver_data = ISHTP_DRIVER_DATA_LNL_M}, |
| 71 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_PTL_H), .driver_data = ISHTP_DRIVER_DATA_PTL}, | ||
| 72 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_PTL_P), .driver_data = ISHTP_DRIVER_DATA_PTL}, | ||
| 66 | {} | 73 | {} |
| 67 | }; | 74 | }; |
| 68 | MODULE_DEVICE_TABLE(pci, ish_pci_tbl); | 75 | MODULE_DEVICE_TABLE(pci, ish_pci_tbl); |
| @@ -253,6 +253,8 @@ struct ishtp_device { · 252 unmodified lines | |||
| 253 | unsigned int ipc_tx_cnt; | 253 | unsigned int ipc_tx_cnt; |
| 254 | unsigned long long ipc_tx_bytes_cnt; | 254 | unsigned long long ipc_tx_bytes_cnt; |
| 255 | 255 | ||
| 256 | /* Time of the last clock sync */ | ||
| 257 | unsigned long prev_sync; | ||
| 256 | const struct ishtp_hw_ops *ops; | 258 | const struct ishtp_hw_ops *ops; |
| 257 | size_t mtu; | 259 | size_t mtu; |
| 258 | uint32_t ishtp_msg_hdr; | 260 | uint32_t ishtp_msg_hdr; |
| @@ -7,7 +7,6 @@ menu "Intel THC HID Support" · 6 unmodified lines | |||
| 7 | config INTEL_THC_HID | 7 | config INTEL_THC_HID |
| 8 | tristate "Intel Touch Host Controller" | 8 | tristate "Intel Touch Host Controller" |
| 9 | depends on ACPI | 9 | depends on ACPI |
| 10 | select HID | ||
| 11 | help | 10 | help |
| 12 | THC (Touch Host Controller) is the name of the IP block in PCH that | 11 | THC (Touch Host Controller) is the name of the IP block in PCH that |
| 13 | interfaces with Touch Devices (ex: touchscreen, touchpad etc.). It | 12 | interfaces with Touch Devices (ex: touchscreen, touchpad etc.). It |
| @@ -1,7 +1,6 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0+ | 1 | # SPDX-License-Identifier: GPL-2.0+ |
| 2 | menu "Surface System Aggregator Module HID support" | 2 | menu "Surface System Aggregator Module HID support" |
| 3 | depends on SURFACE_AGGREGATOR | 3 | depends on SURFACE_AGGREGATOR |
| 4 | depends on INPUT | ||
| 5 | 4 | ||
| 6 | config SURFACE_HID | 5 | config SURFACE_HID |
| 7 | tristate "HID transport driver for Surface System Aggregator Module" | 6 | tristate "HID transport driver for Surface System Aggregator Module" |
| @@ -39,4 +38,3 @@ endmenu · 31 unmodified lines | |||
| 39 | 38 | ||
| 40 | config SURFACE_HID_CORE | 39 | config SURFACE_HID_CORE |
| 41 | tristate | 40 | tristate |
| 42 | select HID | ||
| @@ -5,8 +5,7 @@ menu "USB HID support" · 4 unmodified lines | |||
| 5 | config USB_HID | 5 | config USB_HID |
| 6 | tristate "USB HID transport layer" | 6 | tristate "USB HID transport layer" |
| 7 | default y | 7 | default y |
| 8 | depends on USB && INPUT | 8 | depends on HID |
| 9 | select HID | ||
| 10 | help | 9 | help |
| 11 | Say Y here if you want to connect USB keyboards, | 10 | Say Y here if you want to connect USB keyboards, |
| 12 | mice, joysticks, graphic tablets, or any other HID based devices | 11 | mice, joysticks, graphic tablets, or any other HID based devices |
| @@ -1300,12 +1300,14 @@ new_device_store(struct device *dev, struct device_attribute *attr, · 1299 unmodified lines | |||
| 1300 | info.flags |= I2C_CLIENT_SLAVE; | 1300 | info.flags |= I2C_CLIENT_SLAVE; |
| 1301 | } | 1301 | } |
| 1302 | 1302 | ||
| 1303 | info.flags |= I2C_CLIENT_USER; | ||
| 1304 | |||
| 1305 | client = i2c_new_client_device(adap, &info); | 1303 | client = i2c_new_client_device(adap, &info); |
| 1306 | if (IS_ERR(client)) | 1304 | if (IS_ERR(client)) |
| 1307 | return PTR_ERR(client); | 1305 | return PTR_ERR(client); |
| 1308 | 1306 | ||
| 1307 | /* Keep track of the added device */ | ||
| 1308 | mutex_lock(&adap->userspace_clients_lock); | ||
| 1309 | list_add_tail(&client->detected, &adap->userspace_clients); | ||
| 1310 | mutex_unlock(&adap->userspace_clients_lock); | ||
| 1309 | dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", | 1311 | dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", |
| 1310 | info.type, info.addr); | 1312 | info.type, info.addr); |
| 1311 | 1313 | ||
| @@ -1313,15 +1315,6 @@ new_device_store(struct device *dev, struct device_attribute *attr, · 1 unmodified line | |||
| 1313 | } | 1315 | } |
| 1314 | static DEVICE_ATTR_WO(new_device); | 1316 | static DEVICE_ATTR_WO(new_device); |
| 1315 | 1317 | ||
| 1316 | static int __i2c_find_user_addr(struct device *dev, const void *addrp) | ||
| 1317 | { | ||
| 1318 | struct i2c_client *client = i2c_verify_client(dev); | ||
| 1319 | unsigned short addr = *(unsigned short *)addrp; | ||
| 1320 | |||
| 1321 | return client && client->flags & I2C_CLIENT_USER && | ||
| 1322 | i2c_encode_flags_to_addr(client) == addr; | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | /* | 1318 | /* |
| 1326 | * And of course let the users delete the devices they instantiated, if | 1319 | * And of course let the users delete the devices they instantiated, if |
| 1327 | * they got it wrong. This interface can only be used to delete devices | 1320 | * they got it wrong. This interface can only be used to delete devices |
| @@ -1336,7 +1329,7 @@ delete_device_store(struct device *dev, struct device_attribute *attr, · 8 unmodified lines | |||
| 1336 | const char *buf, size_t count) | 1329 | const char *buf, size_t count) |
| 1337 | { | 1330 | { |
| 1338 | struct i2c_adapter *adap = to_i2c_adapter(dev); | 1331 | struct i2c_adapter *adap = to_i2c_adapter(dev); |
| 1339 | struct device *child_dev; | 1332 | struct i2c_client *client, *next; |
| 1340 | unsigned short addr; | 1333 | unsigned short addr; |
| 1341 | char end; | 1334 | char end; |
| 1342 | int res; | 1335 | int res; |
| @@ -1352,19 +1345,28 @@ delete_device_store(struct device *dev, struct device_attribute *attr, · 9 unmodified lines | |||
| 1352 | return -EINVAL; | 1345 | return -EINVAL; |
| 1353 | } | 1346 | } |
| 1354 | 1347 | ||
| 1355 | mutex_lock(&core_lock); | ||
| 1356 | /* Make sure the device was added through sysfs */ | 1348 | /* Make sure the device was added through sysfs */ |
| 1357 | child_dev = device_find_child(&adap->dev, &addr, __i2c_find_user_addr); | 1349 | res = -ENOENT; |
| 1358 | if (child_dev) { | 1350 | mutex_lock_nested(&adap->userspace_clients_lock, |
| 1359 | i2c_unregister_device(i2c_verify_client(child_dev)); | 1351 | i2c_adapter_depth(adap)); |
| 1360 | put_device(child_dev); | 1352 | list_for_each_entry_safe(client, next, &adap->userspace_clients, |
| 1361 | } else { | 1353 | detected) { |
| 1362 | dev_err(dev, "Can't find userspace-created device at %#x\n", addr); | 1354 | if (i2c_encode_flags_to_addr(client) == addr) { |
| 1363 | count = -ENOENT; | 1355 | dev_info(dev, "%s: Deleting device %s at 0x%02hx\n", |
| 1356 | "delete_device", client->name, client->addr); | ||
| 1357 | |||
| 1358 | list_del(&client->detected); | ||
| 1359 | i2c_unregister_device(client); | ||
| 1360 | res = count; | ||
| 1361 | break; | ||
| 1362 | } | ||
| 1364 | } | 1363 | } |
| 1365 | mutex_unlock(&core_lock); | 1364 | mutex_unlock(&adap->userspace_clients_lock); |
| 1366 | 1365 | ||
| 1367 | return count; | 1366 | if (res < 0) |
| 1367 | dev_err(dev, "%s: Can't find device in list\n", | ||
| 1368 | "delete_device"); | ||
| 1369 | return res; | ||
| 1368 | } | 1370 | } |
| 1369 | static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL, | 1371 | static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL, |
| 1370 | delete_device_store); | 1372 | delete_device_store); |
| @@ -1535,6 +1537,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) · 164 unmodified lines | |||
| 1535 | adap->locked_flags = 0; | 1537 | adap->locked_flags = 0; |
| 1536 | rt_mutex_init(&adap->bus_lock); | 1538 | rt_mutex_init(&adap->bus_lock); |
| 1537 | rt_mutex_init(&adap->mux_lock); | 1539 | rt_mutex_init(&adap->mux_lock); |
| 1540 | mutex_init(&adap->userspace_clients_lock); | ||
| 1541 | INIT_LIST_HEAD(&adap->userspace_clients); | ||
| 1538 | 1542 | ||
| 1539 | /* Set default timeout to 1 second if not already set */ | 1543 | /* Set default timeout to 1 second if not already set */ |
| 1540 | if (adap->timeout == 0) | 1544 | if (adap->timeout == 0) |
| @@ -1700,6 +1704,23 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap) · 159 unmodified lines | |||
| 1700 | } | 1704 | } |
| 1701 | EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter); | 1705 | EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter); |
| 1702 | 1706 | ||
| 1707 | static void i2c_do_del_adapter(struct i2c_driver *driver, | ||
| 1708 | struct i2c_adapter *adapter) | ||
| 1709 | { | ||
| 1710 | struct i2c_client *client, *_n; | ||
| 1711 | |||
| 1712 | /* Remove the devices we created ourselves as the result of hardware | ||
| 1713 | * probing (using a driver's detect method) */ | ||
| 1714 | list_for_each_entry_safe(client, _n, &driver->clients, detected) { | ||
| 1715 | if (client->adapter == adapter) { | ||
| 1716 | dev_dbg(&adapter->dev, "Removing %s at 0x%x\n", | ||
| 1717 | client->name, client->addr); | ||
| 1718 | list_del(&client->detected); | ||
| 1719 | i2c_unregister_device(client); | ||
| 1720 | } | ||
| 1721 | } | ||
| 1722 | } | ||
| 1723 | |||
| 1703 | static int __unregister_client(struct device *dev, void *dummy) | 1724 | static int __unregister_client(struct device *dev, void *dummy) |
| 1704 | { | 1725 | { |
| 1705 | struct i2c_client *client = i2c_verify_client(dev); | 1726 | struct i2c_client *client = i2c_verify_client(dev); |
| @@ -1715,6 +1736,12 @@ static int __unregister_dummy(struct device *dev, void *dummy) · 9 unmodified lines | |||
| 1715 | return 0; | 1736 | return 0; |
| 1716 | } | 1737 | } |
| 1717 | 1738 | ||
| 1739 | static int __process_removed_adapter(struct device_driver *d, void *data) | ||
| 1740 | { | ||
| 1741 | i2c_do_del_adapter(to_i2c_driver(d), data); | ||
| 1742 | return 0; | ||
| 1743 | } | ||
| 1744 | |||
| 1718 | /** | 1745 | /** |
| 1719 | * i2c_del_adapter - unregister I2C adapter | 1746 | * i2c_del_adapter - unregister I2C adapter |
| 1720 | * @adap: the adapter being unregistered | 1747 | * @adap: the adapter being unregistered |
| @@ -1726,6 +1753,7 @@ static int __unregister_dummy(struct device *dev, void *dummy) · 5 unmodified lines | |||
| 1726 | void i2c_del_adapter(struct i2c_adapter *adap) | 1753 | void i2c_del_adapter(struct i2c_adapter *adap) |
| 1727 | { | 1754 | { |
| 1728 | struct i2c_adapter *found; | 1755 | struct i2c_adapter *found; |
| 1756 | struct i2c_client *client, *next; | ||
| 1729 | 1757 | ||
| 1730 | /* First make sure that this adapter was ever added */ | 1758 | /* First make sure that this adapter was ever added */ |
| 1731 | mutex_lock(&core_lock); | 1759 | mutex_lock(&core_lock); |
| @@ -1737,16 +1765,31 @@ void i2c_del_adapter(struct i2c_adapter *adap) · 5 unmodified lines | |||
| 1737 | } | 1765 | } |
| 1738 | 1766 | ||
| 1739 | i2c_acpi_remove_space_handler(adap); | 1767 | i2c_acpi_remove_space_handler(adap); |
| 1768 | /* Tell drivers about this removal */ | ||
| 1769 | mutex_lock(&core_lock); | ||
| 1770 | bus_for_each_drv(&i2c_bus_type, NULL, adap, | ||
| 1771 | __process_removed_adapter); | ||
| 1772 | mutex_unlock(&core_lock); | ||
| 1773 | |||
| 1774 | /* Remove devices instantiated from sysfs */ | ||
| 1775 | mutex_lock_nested(&adap->userspace_clients_lock, | ||
| 1776 | i2c_adapter_depth(adap)); | ||
| 1777 | list_for_each_entry_safe(client, next, &adap->userspace_clients, | ||
| 1778 | detected) { | ||
| 1779 | dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, | ||
| 1780 | client->addr); | ||
| 1781 | list_del(&client->detected); | ||
| 1782 | i2c_unregister_device(client); | ||
| 1783 | } | ||
| 1784 | mutex_unlock(&adap->userspace_clients_lock); | ||
| 1740 | 1785 | ||
| 1741 | /* Detach any active clients. This can't fail, thus we do not | 1786 | /* Detach any active clients. This can't fail, thus we do not |
| 1742 | * check the returned value. This is a two-pass process, because | 1787 | * check the returned value. This is a two-pass process, because |
| 1743 | * we can't remove the dummy devices during the first pass: they | 1788 | * we can't remove the dummy devices during the first pass: they |
| 1744 | * could have been instantiated by real devices wishing to clean | 1789 | * could have been instantiated by real devices wishing to clean |
| 1745 | * them up properly, so we give them a chance to do that first. */ | 1790 | * them up properly, so we give them a chance to do that first. */ |
| 1746 | mutex_lock(&core_lock); | ||
| 1747 | device_for_each_child(&adap->dev, NULL, __unregister_client); | 1791 | device_for_each_child(&adap->dev, NULL, __unregister_client); |
| 1748 | device_for_each_child(&adap->dev, NULL, __unregister_dummy); | 1792 | device_for_each_child(&adap->dev, NULL, __unregister_dummy); |
| 1749 | mutex_unlock(&core_lock); | ||
| 1750 | 1793 | ||
| 1751 | /* device name is gone after device_unregister */ | 1794 | /* device name is gone after device_unregister */ |
| 1752 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); | 1795 | dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); |
| @@ -1966,6 +2009,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) · 213 unmodified lines | |||
| 1966 | /* add the driver to the list of i2c drivers in the driver core */ | 2009 | /* add the driver to the list of i2c drivers in the driver core */ |
| 1967 | driver->driver.owner = owner; | 2010 | driver->driver.owner = owner; |
| 1968 | driver->driver.bus = &i2c_bus_type; | 2011 | driver->driver.bus = &i2c_bus_type; |
| 2012 | INIT_LIST_HEAD(&driver->clients); | ||
| 1969 | 2013 | ||
| 1970 | /* When registration returns, the driver core | 2014 | /* When registration returns, the driver core |
| 1971 | * will have called probe() for all matching-but-unbound devices. | 2015 | * will have called probe() for all matching-but-unbound devices. |
| @@ -1983,13 +2027,10 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) · 11 unmodified lines | |||
| 1983 | } | 2027 | } |
| 1984 | EXPORT_SYMBOL(i2c_register_driver); | 2028 | EXPORT_SYMBOL(i2c_register_driver); |
| 1985 | 2029 | ||
| 1986 | static int __i2c_unregister_detected_client(struct device *dev, void *argp) | 2030 | static int __process_removed_driver(struct device *dev, void *data) |
| 1987 | { | 2031 | { |
| 1988 | struct i2c_client *client = i2c_verify_client(dev); | 2032 | if (dev->type == &i2c_adapter_type) |
| 1989 | 2033 | i2c_do_del_adapter(data, to_i2c_adapter(dev)); | |
| 1990 | if (client && client->flags & I2C_CLIENT_AUTO) | ||
| 1991 | i2c_unregister_device(client); | ||
| 1992 | |||
| 1993 | return 0; | 2034 | return 0; |
| 1994 | } | 2035 | } |
| 1995 | 2036 | ||
| @@ -2000,12 +2041,7 @@ static int __i2c_unregister_detected_client(struct device *dev, void *argp) · 4 unmodified lines | |||
| 2000 | */ | 2041 | */ |
| 2001 | void i2c_del_driver(struct i2c_driver *driver) | 2042 | void i2c_del_driver(struct i2c_driver *driver) |
| 2002 | { | 2043 | { |
| 2003 | mutex_lock(&core_lock); | 2044 | i2c_for_each_dev(driver, __process_removed_driver); |
| 2004 | /* Satisfy __must_check, function can't fail */ | ||
| 2005 | if (driver_for_each_device(&driver->driver, NULL, NULL, | ||
| 2006 | __i2c_unregister_detected_client)) { | ||
| 2007 | } | ||
| 2008 | mutex_unlock(&core_lock); | ||
| 2009 | 2045 | ||
| 2010 | driver_unregister(&driver->driver); | 2046 | driver_unregister(&driver->driver); |
| 2011 | pr_debug("driver [%s] unregistered\n", driver->driver.name); | 2047 | pr_debug("driver [%s] unregistered\n", driver->driver.name); |
| @@ -2432,7 +2468,6 @@ static int i2c_detect_address(struct i2c_client *temp_client, · 420 unmodified lines | |||
| 2432 | /* Finally call the custom detection function */ | 2468 | /* Finally call the custom detection function */ |
| 2433 | memset(&info, 0, sizeof(struct i2c_board_info)); | 2469 | memset(&info, 0, sizeof(struct i2c_board_info)); |
| 2434 | info.addr = addr; | 2470 | info.addr = addr; |
| 2435 | info.flags = I2C_CLIENT_AUTO; | ||
| 2436 | err = driver->detect(temp_client, &info); | 2471 | err = driver->detect(temp_client, &info); |
| 2437 | if (err) { | 2472 | if (err) { |
| 2438 | /* -ENODEV is returned if the detection fails. We catch it | 2473 | /* -ENODEV is returned if the detection fails. We catch it |
| @@ -2459,7 +2494,9 @@ static int i2c_detect_address(struct i2c_client *temp_client, · 20 unmodified lines | |||
| 2459 | dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n", | 2494 | dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n", |
| 2460 | info.type, info.addr); | 2495 | info.type, info.addr); |
| 2461 | client = i2c_new_client_device(adapter, &info); | 2496 | client = i2c_new_client_device(adapter, &info); |
| 2462 | if (IS_ERR(client)) | 2497 | if (!IS_ERR(client)) |
| 2498 | list_add_tail(&client->detected, &driver->clients); | ||
| 2499 | else | ||
| 2463 | dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n", | 2500 | dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n", |
| 2464 | info.type, info.addr); | 2501 | info.type, info.addr); |
| 2465 | } | 2502 | } |
| @@ -175,6 +175,7 @@ · 174 unmodified lines | |||
| 175 | #define CONTROL_GAM_EN 25 | 175 | #define CONTROL_GAM_EN 25 |
| 176 | #define CONTROL_GALOG_EN 28 | 176 | #define CONTROL_GALOG_EN 28 |
| 177 | #define CONTROL_GAINT_EN 29 | 177 | #define CONTROL_GAINT_EN 29 |
| 178 | #define CONTROL_EPH_EN 45 | ||
| 178 | #define CONTROL_XT_EN 50 | 179 | #define CONTROL_XT_EN 50 |
| 179 | #define CONTROL_INTCAPXT_EN 51 | 180 | #define CONTROL_INTCAPXT_EN 51 |
| 180 | #define CONTROL_IRTCACHEDIS 59 | 181 | #define CONTROL_IRTCACHEDIS 59 |
| @@ -2653,6 +2653,10 @@ static void iommu_init_flags(struct amd_iommu *iommu) · 2652 unmodified lines | |||
| 2653 | 2653 | ||
| 2654 | /* Set IOTLB invalidation timeout to 1s */ | 2654 | /* Set IOTLB invalidation timeout to 1s */ |
| 2655 | iommu_set_inv_tlb_timeout(iommu, CTRL_INV_TO_1S); | 2655 | iommu_set_inv_tlb_timeout(iommu, CTRL_INV_TO_1S); |
| 2656 | |||
| 2657 | /* Enable Enhanced Peripheral Page Request Handling */ | ||
| 2658 | if (check_feature(FEATURE_EPHSUP)) | ||
| 2659 | iommu_feature_enable(iommu, CONTROL_EPH_EN); | ||
| 2656 | } | 2660 | } |
| 2657 | 2661 | ||
| 2658 | static void iommu_apply_resume_quirks(struct amd_iommu *iommu) | 2662 | static void iommu_apply_resume_quirks(struct amd_iommu *iommu) |
| @@ -3194,7 +3198,7 @@ out: · 535 unmodified lines | |||
| 3194 | return true; | 3198 | return true; |
| 3195 | } | 3199 | } |
| 3196 | 3200 | ||
| 3197 | static void iommu_snp_enable(void) | 3201 | static __init void iommu_snp_enable(void) |
| 3198 | { | 3202 | { |
| 3199 | #ifdef CONFIG_KVM_AMD_SEV | 3203 | #ifdef CONFIG_KVM_AMD_SEV |
| 3200 | if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) | 3204 | if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) |
| @@ -3219,6 +3223,14 @@ static void iommu_snp_enable(void) · 18 unmodified lines | |||
| 3219 | goto disable_snp; | 3223 | goto disable_snp; |
| 3220 | } | 3224 | } |
| 3221 | 3225 | ||
| 3226 | /* | ||
| 3227 | * Enable host SNP support once SNP support is checked on IOMMU. | ||
| 3228 | */ | ||
| 3229 | if (snp_rmptable_init()) { | ||
| 3230 | pr_warn("SNP: RMP initialization failed, SNP cannot be supported.\n"); | ||
| 3231 | goto disable_snp; | ||
| 3232 | } | ||
| 3233 | |||
| 3222 | pr_info("IOMMU SNP support enabled.\n"); | 3234 | pr_info("IOMMU SNP support enabled.\n"); |
| 3223 | return; | 3235 | return; |
| 3224 | 3236 | ||
| @@ -3318,6 +3330,19 @@ static int __init iommu_go_to_state(enum iommu_init_state state) · 93 unmodified lines | |||
| 3318 | ret = state_next(); | 3330 | ret = state_next(); |
| 3319 | } | 3331 | } |
| 3320 | 3332 | ||
| 3333 | /* | ||
| 3334 | * SNP platform initilazation requires IOMMUs to be fully configured. | ||
| 3335 | * If the SNP support on IOMMUs has NOT been checked, simply mark SNP | ||
| 3336 | * as unsupported. If the SNP support on IOMMUs has been checked and | ||
| 3337 | * host SNP support enabled but RMP enforcement has not been enabled | ||
| 3338 | * in IOMMUs, then the system is in a half-baked state, but can limp | ||
| 3339 | * along as all memory should be Hypervisor-Owned in the RMP. WARN, | ||
| 3340 | * but leave SNP as "supported" to avoid confusing the kernel. | ||
| 3341 | */ | ||
| 3342 | if (ret && cc_platform_has(CC_ATTR_HOST_SEV_SNP) && | ||
| 3343 | !WARN_ON_ONCE(amd_iommu_snp_en)) | ||
| 3344 | cc_platform_clear(CC_ATTR_HOST_SEV_SNP); | ||
| 3345 | |||
| 3321 | return ret; | 3346 | return ret; |
| 3322 | } | 3347 | } |
| 3323 | 3348 | ||
| @@ -3426,18 +3451,23 @@ void __init amd_iommu_detect(void) · 102 unmodified lines | |||
| 3426 | int ret; | 3451 | int ret; |
| 3427 | 3452 | ||
| 3428 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) | 3453 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) |
| 3429 | return; | 3454 | goto disable_snp; |
| 3430 | 3455 | ||
| 3431 | if (!amd_iommu_sme_check()) | 3456 | if (!amd_iommu_sme_check()) |
| 3432 | return; | 3457 | goto disable_snp; |
| 3433 | 3458 | ||
| 3434 | ret = iommu_go_to_state(IOMMU_IVRS_DETECTED); | 3459 | ret = iommu_go_to_state(IOMMU_IVRS_DETECTED); |
| 3435 | if (ret) | 3460 | if (ret) |
| 3436 | return; | 3461 | goto disable_snp; |
| 3437 | 3462 | ||
| 3438 | amd_iommu_detected = true; | 3463 | amd_iommu_detected = true; |
| 3439 | iommu_detected = 1; | 3464 | iommu_detected = 1; |
| 3440 | x86_init.iommu.iommu_init = amd_iommu_init; | 3465 | x86_init.iommu.iommu_init = amd_iommu_init; |
| 3466 | return; | ||
| 3467 | |||
| 3468 | disable_snp: | ||
| 3469 | if (cc_platform_has(CC_ATTR_HOST_SEV_SNP)) | ||
| 3470 | cc_platform_clear(CC_ATTR_HOST_SEV_SNP); | ||
| 3441 | } | 3471 | } |
| 3442 | 3472 | ||
| 3443 | /**************************************************************************** | 3473 | /**************************************************************************** |
| @@ -249,7 +249,7 @@ struct exynos_iommu_domain { · 248 unmodified lines | |||
| 249 | struct list_head clients; /* list of sysmmu_drvdata.domain_node */ | 249 | struct list_head clients; /* list of sysmmu_drvdata.domain_node */ |
| 250 | sysmmu_pte_t *pgtable; /* lv1 page table, 16KB */ | 250 | sysmmu_pte_t *pgtable; /* lv1 page table, 16KB */ |
| 251 | short *lv2entcnt; /* free lv2 entry counter for each section */ | 251 | short *lv2entcnt; /* free lv2 entry counter for each section */ |
| 252 | spinlock_t lock; /* lock for modyfying list of clients */ | 252 | spinlock_t lock; /* lock for modifying list of clients */ |
| 253 | spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ | 253 | spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ |
| 254 | struct iommu_domain domain; /* generic domain data structure */ | 254 | struct iommu_domain domain; /* generic domain data structure */ |
| 255 | }; | 255 | }; |
| @@ -292,7 +292,7 @@ struct sysmmu_drvdata { · 36 unmodified lines | |||
| 292 | struct clk *aclk; /* SYSMMU's aclk clock */ | 292 | struct clk *aclk; /* SYSMMU's aclk clock */ |
| 293 | struct clk *pclk; /* SYSMMU's pclk clock */ | 293 | struct clk *pclk; /* SYSMMU's pclk clock */ |
| 294 | struct clk *clk_master; /* master's device clock */ | 294 | struct clk *clk_master; /* master's device clock */ |
| 295 | spinlock_t lock; /* lock for modyfying state */ | 295 | spinlock_t lock; /* lock for modifying state */ |
| 296 | bool active; /* current status */ | 296 | bool active; /* current status */ |
| 297 | struct exynos_iommu_domain *domain; /* domain we belong to */ | 297 | struct exynos_iommu_domain *domain; /* domain we belong to */ |
| 298 | struct list_head domain_node; /* node for domain clients list */ | 298 | struct list_head domain_node; /* node for domain clients list */ |
| @@ -746,7 +746,7 @@ static int exynos_sysmmu_probe(struct platform_device *pdev) · 447 unmodified lines | |||
| 746 | ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, 0, | 746 | ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, 0, |
| 747 | dev_name(dev), data); | 747 | dev_name(dev), data); |
| 748 | if (ret) { | 748 | if (ret) { |
| 749 | dev_err(dev, "Unabled to register handler of irq %d\n", irq); | 749 | dev_err(dev, "Unable to register handler of irq %d\n", irq); |
| 750 | return ret; | 750 | return ret; |
| 751 | } | 751 | } |
| 752 | 752 | ||
| @@ -87,7 +87,9 @@ prq_retry: · 86 unmodified lines | |||
| 87 | struct page_req_dsc *req; | 87 | struct page_req_dsc *req; |
| 88 | 88 | ||
| 89 | req = &iommu->prq[head / sizeof(*req)]; | 89 | req = &iommu->prq[head / sizeof(*req)]; |
| 90 | if (!req->pasid_present || req->pasid != pasid) { | 90 | if (req->rid != sid || |
| 91 | (req->pasid_present && pasid != req->pasid) || | ||
| 92 | (!req->pasid_present && pasid != IOMMU_NO_PASID)) { | ||
| 91 | head = (head + sizeof(*req)) & PRQ_RING_MASK; | 93 | head = (head + sizeof(*req)) & PRQ_RING_MASK; |
| 92 | continue; | 94 | continue; |
| 93 | } | 95 | } |
| @@ -478,6 +478,7 @@ void iopf_queue_remove_device(struct iopf_queue *queue, struct device *dev) · 477 unmodified lines | |||
| 478 | 478 | ||
| 479 | ops->page_response(dev, iopf, &resp); | 479 | ops->page_response(dev, iopf, &resp); |
| 480 | list_del_init(&group->pending_node); | 480 | list_del_init(&group->pending_node); |
| 481 | iopf_free_group(group); | ||
| 481 | } | 482 | } |
| 482 | mutex_unlock(&fault_param->lock); | 483 | mutex_unlock(&fault_param->lock); |
| 483 | 484 | ||
| @@ -1756,7 +1756,7 @@ static int iommu_get_def_domain_type(struct iommu_group *group, · 1755 unmodified lines | |||
| 1756 | group->id); | 1756 | group->id); |
| 1757 | 1757 | ||
| 1758 | /* | 1758 | /* |
| 1759 | * Try to recover, drivers are allowed to force IDENITY or DMA, IDENTITY | 1759 | * Try to recover, drivers are allowed to force IDENTITY or DMA, IDENTITY |
| 1760 | * takes precedence. | 1760 | * takes precedence. |
| 1761 | */ | 1761 | */ |
| 1762 | if (type == IOMMU_DOMAIN_IDENTITY) | 1762 | if (type == IOMMU_DOMAIN_IDENTITY) |
| @@ -169,6 +169,7 @@ config IXP4XX_IRQ · 168 unmodified lines | |||
| 169 | 169 | ||
| 170 | config LAN966X_OIC | 170 | config LAN966X_OIC |
| 171 | tristate "Microchip LAN966x OIC Support" | 171 | tristate "Microchip LAN966x OIC Support" |
| 172 | depends on MCHP_LAN966X_PCI || COMPILE_TEST | ||
| 172 | select GENERIC_IRQ_CHIP | 173 | select GENERIC_IRQ_CHIP |
| 173 | select IRQ_DOMAIN | 174 | select IRQ_DOMAIN |
| 174 | help | 175 | help |
| @@ -577,7 +577,8 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) · 576 unmodified lines | |||
| 577 | AIC_FIQ_HWIRQ(AIC_TMR_EL02_VIRT)); | 577 | AIC_FIQ_HWIRQ(AIC_TMR_EL02_VIRT)); |
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | if (read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & PMCR0_IACT) { | 580 | if ((read_sysreg_s(SYS_IMP_APL_PMCR0_EL1) & (PMCR0_IMODE | PMCR0_IACT)) == |
| 581 | (FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_FIQ) | PMCR0_IACT)) { | ||
| 581 | int irq; | 582 | int irq; |
| 582 | if (cpumask_test_cpu(smp_processor_id(), | 583 | if (cpumask_test_cpu(smp_processor_id(), |
| 583 | &aic_irqc->fiq_aff[AIC_CPU_PMU_P]->aff)) | 584 | &aic_irqc->fiq_aff[AIC_CPU_PMU_P]->aff)) |
| @@ -68,7 +68,8 @@ static int mvebu_icu_translate(struct irq_domain *d, struct irq_fwspec *fwspec, · 67 unmodified lines | |||
| 68 | unsigned long *hwirq, unsigned int *type) | 68 | unsigned long *hwirq, unsigned int *type) |
| 69 | { | 69 | { |
| 70 | unsigned int param_count = static_branch_unlikely(&legacy_bindings) ? 3 : 2; | 70 | unsigned int param_count = static_branch_unlikely(&legacy_bindings) ? 3 : 2; |
| 71 | struct mvebu_icu_msi_data *msi_data = d->host_data; | 71 | struct msi_domain_info *info = d->host_data; |
| 72 | struct mvebu_icu_msi_data *msi_data = info->chip_data; | ||
| 72 | struct mvebu_icu *icu = msi_data->icu; | 73 | struct mvebu_icu *icu = msi_data->icu; |
| 73 | 74 | ||
| 74 | /* Check the count of the parameters in dt */ | 75 | /* Check the count of the parameters in dt */ |
| @@ -98,7 +98,7 @@ static void partition_irq_print_chip(struct irq_data *d, struct seq_file *p) · 97 unmodified lines | |||
| 98 | struct irq_chip *chip = irq_desc_get_chip(part->chained_desc); | 98 | struct irq_chip *chip = irq_desc_get_chip(part->chained_desc); |
| 99 | struct irq_data *data = irq_desc_get_irq_data(part->chained_desc); | 99 | struct irq_data *data = irq_desc_get_irq_data(part->chained_desc); |
| 100 | 100 | ||
| 101 | seq_printf(p, " %5s-%lu", chip->name, data->hwirq); | 101 | seq_printf(p, "%5s-%lu", chip->name, data->hwirq); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | static struct irq_chip partition_irq_chip = { | 104 | static struct irq_chip partition_irq_chip = { |
| @@ -27,7 +27,7 @@ static void imsic_ipi_send(unsigned int cpu) · 26 unmodified lines | |||
| 27 | { | 27 | { |
| 28 | struct imsic_local_config *local = per_cpu_ptr(imsic->global.local, cpu); | 28 | struct imsic_local_config *local = per_cpu_ptr(imsic->global.local, cpu); |
| 29 | 29 | ||
| 30 | writel_relaxed(IMSIC_IPI_ID, local->msi_va); | 30 | writel(IMSIC_IPI_ID, local->msi_va); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | static void imsic_ipi_starting_cpu(void) | 33 | static void imsic_ipi_starting_cpu(void) |
| @@ -31,7 +31,7 @@ static DEFINE_PER_CPU(void __iomem *, sswi_cpu_regs); · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | static void thead_aclint_sswi_ipi_send(unsigned int cpu) | 32 | static void thead_aclint_sswi_ipi_send(unsigned int cpu) |
| 33 | { | 33 | { |
| 34 | writel_relaxed(0x1, per_cpu(sswi_cpu_regs, cpu)); | 34 | writel(0x1, per_cpu(sswi_cpu_regs, cpu)); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | static void thead_aclint_sswi_ipi_clear(void) | 37 | static void thead_aclint_sswi_ipi_clear(void) |
| @@ -76,10 +76,8 @@ static int linear_set_limits(struct mddev *mddev) · 75 unmodified lines | |||
| 76 | lim.max_write_zeroes_sectors = mddev->chunk_sectors; | 76 | lim.max_write_zeroes_sectors = mddev->chunk_sectors; |
| 77 | lim.io_min = mddev->chunk_sectors << 9; | 77 | lim.io_min = mddev->chunk_sectors << 9; |
| 78 | err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY); | 78 | err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY); |
| 79 | if (err) { | 79 | if (err) |
| 80 | queue_limits_cancel_update(mddev->gendisk->queue); | ||
| 81 | return err; | 80 | return err; |
| 82 | } | ||
| 83 | 81 | ||
| 84 | return queue_limits_set(mddev->gendisk->queue, &lim); | 82 | return queue_limits_set(mddev->gendisk->queue, &lim); |
| 85 | } | 83 | } |
| @@ -159,6 +159,7 @@ err_regmap: · 158 unmodified lines | |||
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | static struct regmap *device_node_get_regmap(struct device_node *np, | 161 | static struct regmap *device_node_get_regmap(struct device_node *np, |
| 162 | bool create_regmap, | ||
| 162 | bool check_res) | 163 | bool check_res) |
| 163 | { | 164 | { |
| 164 | struct syscon *entry, *syscon = NULL; | 165 | struct syscon *entry, *syscon = NULL; |
| @@ -172,7 +173,7 @@ static struct regmap *device_node_get_regmap(struct device_node *np, · 7 unmodified lines | |||
| 172 | } | 173 | } |
| 173 | 174 | ||
| 174 | if (!syscon) { | 175 | if (!syscon) { |
| 175 | if (of_device_is_compatible(np, "syscon")) | 176 | if (create_regmap) |
| 176 | syscon = of_syscon_register(np, check_res); | 177 | syscon = of_syscon_register(np, check_res); |
| 177 | else | 178 | else |
| 178 | syscon = ERR_PTR(-EINVAL); | 179 | syscon = ERR_PTR(-EINVAL); |
| @@ -233,15 +234,37 @@ err_unlock: · 54 unmodified lines | |||
| 233 | } | 234 | } |
| 234 | EXPORT_SYMBOL_GPL(of_syscon_register_regmap); | 235 | EXPORT_SYMBOL_GPL(of_syscon_register_regmap); |
| 235 | 236 | ||
| 237 | /** | ||
| 238 | * device_node_to_regmap() - Get or create a regmap for specified device node | ||
| 239 | * @np: Device tree node | ||
| 240 | * | ||
| 241 | * Get a regmap for the specified device node. If there's not an existing | ||
| 242 | * regmap, then one is instantiated. This function should not be used if the | ||
| 243 | * device node has a custom regmap driver or has resources (clocks, resets) to | ||
| 244 | * be managed. Use syscon_node_to_regmap() instead for those cases. | ||
| 245 | * | ||
| 246 | * Return: regmap ptr on success, negative error code on failure. | ||
| 247 | */ | ||
| 236 | struct regmap *device_node_to_regmap(struct device_node *np) | 248 | struct regmap *device_node_to_regmap(struct device_node *np) |
| 237 | { | 249 | { |
| 238 | return device_node_get_regmap(np, false); | 250 | return device_node_get_regmap(np, true, false); |
| 239 | } | 251 | } |
| 240 | EXPORT_SYMBOL_GPL(device_node_to_regmap); | 252 | EXPORT_SYMBOL_GPL(device_node_to_regmap); |
| 241 | 253 | ||
| 254 | /** | ||
| 255 | * syscon_node_to_regmap() - Get or create a regmap for specified syscon device node | ||
| 256 | * @np: Device tree node | ||
| 257 | * | ||
| 258 | * Get a regmap for the specified device node. If there's not an existing | ||
| 259 | * regmap, then one is instantiated if the node is a generic "syscon". This | ||
| 260 | * function is safe to use for a syscon registered with | ||
| 261 | * of_syscon_register_regmap(). | ||
| 262 | * | ||
| 263 | * Return: regmap ptr on success, negative error code on failure. | ||
| 264 | */ | ||
| 242 | struct regmap *syscon_node_to_regmap(struct device_node *np) | 265 | struct regmap *syscon_node_to_regmap(struct device_node *np) |
| 243 | { | 266 | { |
| 244 | return device_node_get_regmap(np, true); | 267 | return device_node_get_regmap(np, of_device_is_compatible(np, "syscon"), true); |
| 245 | } | 268 | } |
| 246 | EXPORT_SYMBOL_GPL(syscon_node_to_regmap); | 269 | EXPORT_SYMBOL_GPL(syscon_node_to_regmap); |
| 247 | 270 | ||
| @@ -273,6 +273,7 @@ · 272 unmodified lines | |||
| 273 | #define MSDC_PAD_TUNE_CMD2_SEL BIT(21) /* RW */ | 273 | #define MSDC_PAD_TUNE_CMD2_SEL BIT(21) /* RW */ |
| 274 | 274 | ||
| 275 | #define PAD_DS_TUNE_DLY_SEL BIT(0) /* RW */ | 275 | #define PAD_DS_TUNE_DLY_SEL BIT(0) /* RW */ |
| 276 | #define PAD_DS_TUNE_DLY2_SEL BIT(1) /* RW */ | ||
| 276 | #define PAD_DS_TUNE_DLY1 GENMASK(6, 2) /* RW */ | 277 | #define PAD_DS_TUNE_DLY1 GENMASK(6, 2) /* RW */ |
| 277 | #define PAD_DS_TUNE_DLY2 GENMASK(11, 7) /* RW */ | 278 | #define PAD_DS_TUNE_DLY2 GENMASK(11, 7) /* RW */ |
| 278 | #define PAD_DS_TUNE_DLY3 GENMASK(16, 12) /* RW */ | 279 | #define PAD_DS_TUNE_DLY3 GENMASK(16, 12) /* RW */ |
| @@ -318,6 +319,7 @@ · 39 unmodified lines | |||
| 318 | 319 | ||
| 319 | /* EMMC50_PAD_DS_TUNE mask */ | 320 | /* EMMC50_PAD_DS_TUNE mask */ |
| 320 | #define PAD_DS_DLY_SEL BIT(16) /* RW */ | 321 | #define PAD_DS_DLY_SEL BIT(16) /* RW */ |
| 322 | #define PAD_DS_DLY2_SEL BIT(15) /* RW */ | ||
| 321 | #define PAD_DS_DLY1 GENMASK(14, 10) /* RW */ | 323 | #define PAD_DS_DLY1 GENMASK(14, 10) /* RW */ |
| 322 | #define PAD_DS_DLY3 GENMASK(4, 0) /* RW */ | 324 | #define PAD_DS_DLY3 GENMASK(4, 0) /* RW */ |
| 323 | 325 | ||
| @@ -2504,13 +2506,23 @@ tune_done: · 2180 unmodified lines | |||
| 2504 | static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) | 2506 | static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) |
| 2505 | { | 2507 | { |
| 2506 | struct msdc_host *host = mmc_priv(mmc); | 2508 | struct msdc_host *host = mmc_priv(mmc); |
| 2509 | |||
| 2507 | host->hs400_mode = true; | 2510 | host->hs400_mode = true; |
| 2508 | 2511 | ||
| 2509 | if (host->top_base) | 2512 | if (host->top_base) { |
| 2510 | writel(host->hs400_ds_delay, | 2513 | if (host->hs400_ds_dly3) |
| 2511 | host->top_base + EMMC50_PAD_DS_TUNE); | 2514 | sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, |
| 2512 | else | 2515 | PAD_DS_DLY3, host->hs400_ds_dly3); |
| 2513 | writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE); | 2516 | if (host->hs400_ds_delay) |
| 2517 | writel(host->hs400_ds_delay, | ||
| 2518 | host->top_base + EMMC50_PAD_DS_TUNE); | ||
| 2519 | } else { | ||
| 2520 | if (host->hs400_ds_dly3) | ||
| 2521 | sdr_set_field(host->base + PAD_DS_TUNE, | ||
| 2522 | PAD_DS_TUNE_DLY3, host->hs400_ds_dly3); | ||
| 2523 | if (host->hs400_ds_delay) | ||
| 2524 | writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE); | ||
| 2525 | } | ||
| 2514 | /* hs400 mode must set it to 0 */ | 2526 | /* hs400 mode must set it to 0 */ |
| 2515 | sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS); | 2527 | sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS); |
| 2516 | /* to improve read performance, set outstanding to 2 */ | 2528 | /* to improve read performance, set outstanding to 2 */ |
| @@ -2530,14 +2542,11 @@ static int msdc_execute_hs400_tuning(struct mmc_host *mmc, struct mmc_card *card · 13 unmodified lines | |||
| 2530 | if (host->top_base) { | 2542 | if (host->top_base) { |
| 2531 | sdr_set_bits(host->top_base + EMMC50_PAD_DS_TUNE, | 2543 | sdr_set_bits(host->top_base + EMMC50_PAD_DS_TUNE, |
| 2532 | PAD_DS_DLY_SEL); | 2544 | PAD_DS_DLY_SEL); |
| 2533 | if (host->hs400_ds_dly3) | 2545 | sdr_clr_bits(host->top_base + EMMC50_PAD_DS_TUNE, |
| 2534 | sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, | 2546 | PAD_DS_DLY2_SEL); |
| 2535 | PAD_DS_DLY3, host->hs400_ds_dly3); | ||
| 2536 | } else { | 2547 | } else { |
| 2537 | sdr_set_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY_SEL); | 2548 | sdr_set_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY_SEL); |
| 2538 | if (host->hs400_ds_dly3) | 2549 | sdr_clr_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY2_SEL); |
| 2539 | sdr_set_field(host->base + PAD_DS_TUNE, | ||
| 2540 | PAD_DS_TUNE_DLY3, host->hs400_ds_dly3); | ||
| 2541 | } | 2550 | } |
| 2542 | 2551 | ||
| 2543 | host->hs400_tuning = true; | 2552 | host->hs400_tuning = true; |
| @@ -155,7 +155,6 @@ struct sdhci_am654_data { · 154 unmodified lines | |||
| 155 | u32 tuning_loop; | 155 | u32 tuning_loop; |
| 156 | 156 | ||
| 157 | #define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) | 157 | #define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) |
| 158 | #define SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA BIT(1) | ||
| 159 | }; | 158 | }; |
| 160 | 159 | ||
| 161 | struct window { | 160 | struct window { |
| @@ -357,29 +356,6 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, · 195 unmodified lines | |||
| 357 | sdhci_set_clock(host, clock); | 356 | sdhci_set_clock(host, clock); |
| 358 | } | 357 | } |
| 359 | 358 | ||
| 360 | static int sdhci_am654_start_signal_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) | ||
| 361 | { | ||
| 362 | struct sdhci_host *host = mmc_priv(mmc); | ||
| 363 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 364 | struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); | ||
| 365 | int ret; | ||
| 366 | |||
| 367 | if ((sdhci_am654->quirks & SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA) && | ||
| 368 | ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { | ||
| 369 | if (!IS_ERR(mmc->supply.vqmmc)) { | ||
| 370 | ret = mmc_regulator_set_vqmmc(mmc, ios); | ||
| 371 | if (ret < 0) { | ||
| 372 | pr_err("%s: Switching to 1.8V signalling voltage failed,\n", | ||
| 373 | mmc_hostname(mmc)); | ||
| 374 | return -EIO; | ||
| 375 | } | ||
| 376 | } | ||
| 377 | return 0; | ||
| 378 | } | ||
| 379 | |||
| 380 | return sdhci_start_signal_voltage_switch(mmc, ios); | ||
| 381 | } | ||
| 382 | |||
| 383 | static u8 sdhci_am654_write_power_on(struct sdhci_host *host, u8 val, int reg) | 359 | static u8 sdhci_am654_write_power_on(struct sdhci_host *host, u8 val, int reg) |
| 384 | { | 360 | { |
| 385 | writeb(val, host->ioaddr + reg); | 361 | writeb(val, host->ioaddr + reg); |
| @@ -868,11 +844,6 @@ static int sdhci_am654_get_of_property(struct platform_device *pdev, · 482 unmodified lines | |||
| 868 | if (device_property_read_bool(dev, "ti,fails-without-test-cd")) | 844 | if (device_property_read_bool(dev, "ti,fails-without-test-cd")) |
| 869 | sdhci_am654->quirks |= SDHCI_AM654_QUIRK_FORCE_CDTEST; | 845 | sdhci_am654->quirks |= SDHCI_AM654_QUIRK_FORCE_CDTEST; |
| 870 | 846 | ||
| 871 | /* Suppress v1p8 ena for eMMC and SD with vqmmc supply */ | ||
| 872 | if (!!of_parse_phandle(dev->of_node, "vmmc-supply", 0) == | ||
| 873 | !!of_parse_phandle(dev->of_node, "vqmmc-supply", 0)) | ||
| 874 | sdhci_am654->quirks |= SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA; | ||
| 875 | |||
| 876 | sdhci_get_of_property(pdev); | 847 | sdhci_get_of_property(pdev); |
| 877 | 848 | ||
| 878 | return 0; | 849 | return 0; |
| @@ -969,7 +940,6 @@ static int sdhci_am654_probe(struct platform_device *pdev) · 90 unmodified lines | |||
| 969 | goto err_pltfm_free; | 940 | goto err_pltfm_free; |
| 970 | } | 941 | } |
| 971 | 942 | ||
| 972 | host->mmc_host_ops.start_signal_voltage_switch = sdhci_am654_start_signal_voltage_switch; | ||
| 973 | host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning; | 943 | host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning; |
| 974 | 944 | ||
| 975 | pm_runtime_get_noresume(dev); | 945 | pm_runtime_get_noresume(dev); |
| @@ -385,15 +385,16 @@ static int c_can_plat_probe(struct platform_device *pdev) · 384 unmodified lines | |||
| 385 | if (ret) { | 385 | if (ret) { |
| 386 | dev_err(&pdev->dev, "registering %s failed (err=%d)\n", | 386 | dev_err(&pdev->dev, "registering %s failed (err=%d)\n", |
| 387 | KBUILD_MODNAME, ret); | 387 | KBUILD_MODNAME, ret); |
| 388 | goto exit_free_device; | 388 | goto exit_pm_runtime; |
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n", | 391 | dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n", |
| 392 | KBUILD_MODNAME, priv->base, dev->irq); | 392 | KBUILD_MODNAME, priv->base, dev->irq); |
| 393 | return 0; | 393 | return 0; |
| 394 | 394 | ||
| 395 | exit_free_device: | 395 | exit_pm_runtime: |
| 396 | pm_runtime_disable(priv->device); | 396 | pm_runtime_disable(priv->device); |
| 397 | exit_free_device: | ||
| 397 | free_c_can_dev(dev); | 398 | free_c_can_dev(dev); |
| 398 | exit: | 399 | exit: |
| 399 | dev_err(&pdev->dev, "probe failed\n"); | 400 | dev_err(&pdev->dev, "probe failed\n"); |
| @@ -867,10 +867,12 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr) · 866 unmodified lines | |||
| 867 | } | 867 | } |
| 868 | break; | 868 | break; |
| 869 | case CAN_STATE_ERROR_ACTIVE: | 869 | case CAN_STATE_ERROR_ACTIVE: |
| 870 | cf->can_id |= CAN_ERR_CNT; | 870 | if (skb) { |
| 871 | cf->data[1] = CAN_ERR_CRTL_ACTIVE; | 871 | cf->can_id |= CAN_ERR_CNT; |
| 872 | cf->data[6] = bec.txerr; | 872 | cf->data[1] = CAN_ERR_CRTL_ACTIVE; |
| 873 | cf->data[7] = bec.rxerr; | 873 | cf->data[6] = bec.txerr; |
| 874 | cf->data[7] = bec.rxerr; | ||
| 875 | } | ||
| 874 | break; | 876 | break; |
| 875 | default: | 877 | default: |
| 876 | netdev_warn(ndev, "unhandled error state (%d:%s)!\n", | 878 | netdev_warn(ndev, "unhandled error state (%d:%s)!\n", |
| @@ -622,7 +622,7 @@ rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv) · 621 unmodified lines | |||
| 622 | netdev_dbg(priv->ndev, "RX-FIFO overflow\n"); | 622 | netdev_dbg(priv->ndev, "RX-FIFO overflow\n"); |
| 623 | 623 | ||
| 624 | skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); | 624 | skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); |
| 625 | if (skb) | 625 | if (!skb) |
| 626 | return 0; | 626 | return 0; |
| 627 | 627 | ||
| 628 | rkcanfd_get_berr_counter_corrected(priv, &bec); | 628 | rkcanfd_get_berr_counter_corrected(priv, &bec); |
| @@ -248,7 +248,11 @@ static int es58x_devlink_info_get(struct devlink *devlink, · 247 unmodified lines | |||
| 248 | return ret; | 248 | return ret; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | return devlink_info_serial_number_put(req, es58x_dev->udev->serial); | 251 | if (es58x_dev->udev->serial) |
| 252 | ret = devlink_info_serial_number_put(req, | ||
| 253 | es58x_dev->udev->serial); | ||
| 254 | |||
| 255 | return ret; | ||
| 252 | } | 256 | } |
| 253 | 257 | ||
| 254 | const struct devlink_ops es58x_dl_ops = { | 258 | const struct devlink_ops es58x_dl_ops = { |
| @@ -1441,7 +1441,9 @@ void aq_nic_deinit(struct aq_nic_s *self, bool link_down) · 1440 unmodified lines | |||
| 1441 | aq_ptp_ring_free(self); | 1441 | aq_ptp_ring_free(self); |
| 1442 | aq_ptp_free(self); | 1442 | aq_ptp_free(self); |
| 1443 | 1443 | ||
| 1444 | if (likely(self->aq_fw_ops->deinit) && link_down) { | 1444 | /* May be invoked during hot unplug. */ |
| 1445 | if (pci_device_is_present(self->pdev) && | ||
| 1446 | likely(self->aq_fw_ops->deinit) && link_down) { | ||
| 1445 | mutex_lock(&self->fwreq_mutex); | 1447 | mutex_lock(&self->fwreq_mutex); |
| 1446 | self->aq_fw_ops->deinit(self->aq_hw); | 1448 | self->aq_fw_ops->deinit(self->aq_hw); |
| 1447 | mutex_unlock(&self->fwreq_mutex); | 1449 | mutex_unlock(&self->fwreq_mutex); |
| @@ -41,9 +41,12 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) · 40 unmodified lines | |||
| 41 | { | 41 | { |
| 42 | struct bcmgenet_priv *priv = netdev_priv(dev); | 42 | struct bcmgenet_priv *priv = netdev_priv(dev); |
| 43 | struct device *kdev = &priv->pdev->dev; | 43 | struct device *kdev = &priv->pdev->dev; |
| 44 | u32 phy_wolopts = 0; | ||
| 44 | 45 | ||
| 45 | if (dev->phydev) | 46 | if (dev->phydev) { |
| 46 | phy_ethtool_get_wol(dev->phydev, wol); | 47 | phy_ethtool_get_wol(dev->phydev, wol); |
| 48 | phy_wolopts = wol->wolopts; | ||
| 49 | } | ||
| 47 | 50 | ||
| 48 | /* MAC is not wake-up capable, return what the PHY does */ | 51 | /* MAC is not wake-up capable, return what the PHY does */ |
| 49 | if (!device_can_wakeup(kdev)) | 52 | if (!device_can_wakeup(kdev)) |
| @@ -51,9 +54,14 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) · 1 unmodified line | |||
| 51 | 54 | ||
| 52 | /* Overlay MAC capabilities with that of the PHY queried before */ | 55 | /* Overlay MAC capabilities with that of the PHY queried before */ |
| 53 | wol->supported |= WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER; | 56 | wol->supported |= WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER; |
| 54 | wol->wolopts = priv->wolopts; | 57 | wol->wolopts |= priv->wolopts; |
| 55 | memset(wol->sopass, 0, sizeof(wol->sopass)); | ||
| 56 | 58 | ||
| 59 | /* Return the PHY configured magic password */ | ||
| 60 | if (phy_wolopts & WAKE_MAGICSECURE) | ||
| 61 | return; | ||
| 62 | |||
| 63 | /* Otherwise the MAC one */ | ||
| 64 | memset(wol->sopass, 0, sizeof(wol->sopass)); | ||
| 57 | if (wol->wolopts & WAKE_MAGICSECURE) | 65 | if (wol->wolopts & WAKE_MAGICSECURE) |
| 58 | memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass)); | 66 | memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass)); |
| 59 | } | 67 | } |
| @@ -70,7 +78,7 @@ int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) · 10 unmodified lines | |||
| 70 | /* Try Wake-on-LAN from the PHY first */ | 78 | /* Try Wake-on-LAN from the PHY first */ |
| 71 | if (dev->phydev) { | 79 | if (dev->phydev) { |
| 72 | ret = phy_ethtool_set_wol(dev->phydev, wol); | 80 | ret = phy_ethtool_set_wol(dev->phydev, wol); |
| 73 | if (ret != -EOPNOTSUPP) | 81 | if (ret != -EOPNOTSUPP && wol->wolopts) |
| 74 | return ret; | 82 | return ret; |
| 75 | } | 83 | } |
| 76 | 84 | ||
| @@ -55,6 +55,7 @@ · 54 unmodified lines | |||
| 55 | #include <linux/hwmon.h> | 55 | #include <linux/hwmon.h> |
| 56 | #include <linux/hwmon-sysfs.h> | 56 | #include <linux/hwmon-sysfs.h> |
| 57 | #include <linux/crc32poly.h> | 57 | #include <linux/crc32poly.h> |
| 58 | #include <linux/dmi.h> | ||
| 58 | 59 | ||
| 59 | #include <net/checksum.h> | 60 | #include <net/checksum.h> |
| 60 | #include <net/gso.h> | 61 | #include <net/gso.h> |
| @@ -18212,6 +18213,50 @@ unlock: · 18151 unmodified lines | |||
| 18212 | 18213 | ||
| 18213 | static SIMPLE_DEV_PM_OPS(tg3_pm_ops, tg3_suspend, tg3_resume); | 18214 | static SIMPLE_DEV_PM_OPS(tg3_pm_ops, tg3_suspend, tg3_resume); |
| 18214 | 18215 | ||
| 18216 | /* Systems where ACPI _PTS (Prepare To Sleep) S5 will result in a fatal | ||
| 18217 | * PCIe AER event on the tg3 device if the tg3 device is not, or cannot | ||
| 18218 | * be, powered down. | ||
| 18219 | */ | ||
| 18220 | static const struct dmi_system_id tg3_restart_aer_quirk_table[] = { | ||
| 18221 | { | ||
| 18222 | .matches = { | ||
| 18223 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 18224 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R440"), | ||
| 18225 | }, | ||
| 18226 | }, | ||
| 18227 | { | ||
| 18228 | .matches = { | ||
| 18229 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 18230 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R540"), | ||
| 18231 | }, | ||
| 18232 | }, | ||
| 18233 | { | ||
| 18234 | .matches = { | ||
| 18235 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 18236 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R640"), | ||
| 18237 | }, | ||
| 18238 | }, | ||
| 18239 | { | ||
| 18240 | .matches = { | ||
| 18241 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 18242 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R650"), | ||
| 18243 | }, | ||
| 18244 | }, | ||
| 18245 | { | ||
| 18246 | .matches = { | ||
| 18247 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 18248 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R740"), | ||
| 18249 | }, | ||
| 18250 | }, | ||
| 18251 | { | ||
| 18252 | .matches = { | ||
| 18253 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 18254 | DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R750"), | ||
| 18255 | }, | ||
| 18256 | }, | ||
| 18257 | {} | ||
| 18258 | }; | ||
| 18259 | |||
| 18215 | static void tg3_shutdown(struct pci_dev *pdev) | 18260 | static void tg3_shutdown(struct pci_dev *pdev) |
| 18216 | { | 18261 | { |
| 18217 | struct net_device *dev = pci_get_drvdata(pdev); | 18262 | struct net_device *dev = pci_get_drvdata(pdev); |
| @@ -18228,6 +18273,19 @@ static void tg3_shutdown(struct pci_dev *pdev) · 10 unmodified lines | |||
| 18228 | 18273 | ||
| 18229 | if (system_state == SYSTEM_POWER_OFF) | 18274 | if (system_state == SYSTEM_POWER_OFF) |
| 18230 | tg3_power_down(tp); | 18275 | tg3_power_down(tp); |
| 18276 | else if (system_state == SYSTEM_RESTART && | ||
| 18277 | dmi_first_match(tg3_restart_aer_quirk_table) && | ||
| 18278 | pdev->current_state != PCI_D3cold && | ||
| 18279 | pdev->current_state != PCI_UNKNOWN) { | ||
| 18280 | /* Disable PCIe AER on the tg3 to avoid a fatal | ||
| 18281 | * error during this system restart. | ||
| 18282 | */ | ||
| 18283 | pcie_capability_clear_word(pdev, PCI_EXP_DEVCTL, | ||
| 18284 | PCI_EXP_DEVCTL_CERE | | ||
| 18285 | PCI_EXP_DEVCTL_NFERE | | ||
| 18286 | PCI_EXP_DEVCTL_FERE | | ||
| 18287 | PCI_EXP_DEVCTL_URRE); | ||
| 18288 | } | ||
| 18231 | 18289 | ||
| 18232 | rtnl_unlock(); | 18290 | rtnl_unlock(); |
| 18233 | 18291 | ||
| @@ -1116,6 +1116,16 @@ static inline u32 gve_xdp_tx_start_queue_id(struct gve_priv *priv) · 1115 unmodified lines | |||
| 1116 | return gve_xdp_tx_queue_id(priv, 0); | 1116 | return gve_xdp_tx_queue_id(priv, 0); |
| 1117 | } | 1117 | } |
| 1118 | 1118 | ||
| 1119 | static inline bool gve_supports_xdp_xmit(struct gve_priv *priv) | ||
| 1120 | { | ||
| 1121 | switch (priv->queue_format) { | ||
| 1122 | case GVE_GQI_QPL_FORMAT: | ||
| 1123 | return true; | ||
| 1124 | default: | ||
| 1125 | return false; | ||
| 1126 | } | ||
| 1127 | } | ||
| 1128 | |||
| 1119 | /* gqi napi handler defined in gve_main.c */ | 1129 | /* gqi napi handler defined in gve_main.c */ |
| 1120 | int gve_napi_poll(struct napi_struct *napi, int budget); | 1130 | int gve_napi_poll(struct napi_struct *napi, int budget); |
| 1121 | 1131 | ||
| @@ -1903,6 +1903,8 @@ static void gve_turndown(struct gve_priv *priv) · 1902 unmodified lines | |||
| 1903 | /* Stop tx queues */ | 1903 | /* Stop tx queues */ |
| 1904 | netif_tx_disable(priv->dev); | 1904 | netif_tx_disable(priv->dev); |
| 1905 | 1905 | ||
| 1906 | xdp_features_clear_redirect_target(priv->dev); | ||
| 1907 | |||
| 1906 | gve_clear_napi_enabled(priv); | 1908 | gve_clear_napi_enabled(priv); |
| 1907 | gve_clear_report_stats(priv); | 1909 | gve_clear_report_stats(priv); |
| 1908 | 1910 | ||
| @@ -1972,6 +1974,9 @@ static void gve_turnup(struct gve_priv *priv) · 63 unmodified lines | |||
| 1972 | napi_schedule(&block->napi); | 1974 | napi_schedule(&block->napi); |
| 1973 | } | 1975 | } |
| 1974 | 1976 | ||
| 1977 | if (priv->num_xdp_queues && gve_supports_xdp_xmit(priv)) | ||
| 1978 | xdp_features_set_redirect_target(priv->dev, false); | ||
| 1979 | |||
| 1975 | gve_set_napi_enabled(priv); | 1980 | gve_set_napi_enabled(priv); |
| 1976 | } | 1981 | } |
| 1977 | 1982 | ||
| @@ -2246,7 +2251,6 @@ static void gve_set_netdev_xdp_features(struct gve_priv *priv) · 268 unmodified lines | |||
| 2246 | if (priv->queue_format == GVE_GQI_QPL_FORMAT) { | 2251 | if (priv->queue_format == GVE_GQI_QPL_FORMAT) { |
| 2247 | xdp_features = NETDEV_XDP_ACT_BASIC; | 2252 | xdp_features = NETDEV_XDP_ACT_BASIC; |
| 2248 | xdp_features |= NETDEV_XDP_ACT_REDIRECT; | 2253 | xdp_features |= NETDEV_XDP_ACT_REDIRECT; |
| 2249 | xdp_features |= NETDEV_XDP_ACT_NDO_XMIT; | ||
| 2250 | xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY; | 2254 | xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY; |
| 2251 | } else { | 2255 | } else { |
| 2252 | xdp_features = 0; | 2256 | xdp_features = 0; |
| @@ -2408,6 +2408,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) · 2407 unmodified lines | |||
| 2408 | dma_addr_t data_dma_addr; | 2408 | dma_addr_t data_dma_addr; |
| 2409 | struct netdev_queue *txq; | 2409 | struct netdev_queue *txq; |
| 2410 | unsigned long lpar_rc; | 2410 | unsigned long lpar_rc; |
| 2411 | unsigned int skblen; | ||
| 2411 | union sub_crq tx_crq; | 2412 | union sub_crq tx_crq; |
| 2412 | unsigned int offset; | 2413 | unsigned int offset; |
| 2413 | bool use_scrq_send_direct = false; | 2414 | bool use_scrq_send_direct = false; |
| @@ -2522,6 +2523,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) · 108 unmodified lines | |||
| 2522 | tx_buff->skb = skb; | 2523 | tx_buff->skb = skb; |
| 2523 | tx_buff->index = bufidx; | 2524 | tx_buff->index = bufidx; |
| 2524 | tx_buff->pool_index = queue_num; | 2525 | tx_buff->pool_index = queue_num; |
| 2526 | skblen = skb->len; | ||
| 2525 | 2527 | ||
| 2526 | memset(&tx_crq, 0, sizeof(tx_crq)); | 2528 | memset(&tx_crq, 0, sizeof(tx_crq)); |
| 2527 | tx_crq.v1.first = IBMVNIC_CRQ_CMD; | 2529 | tx_crq.v1.first = IBMVNIC_CRQ_CMD; |
| @@ -2614,7 +2616,7 @@ early_exit: · 86 unmodified lines | |||
| 2614 | netif_stop_subqueue(netdev, queue_num); | 2616 | netif_stop_subqueue(netdev, queue_num); |
| 2615 | } | 2617 | } |
| 2616 | 2618 | ||
| 2617 | tx_bytes += skb->len; | 2619 | tx_bytes += skblen; |
| 2618 | txq_trans_cond_update(txq); | 2620 | txq_trans_cond_update(txq); |
| 2619 | ret = NETDEV_TX_OK; | 2621 | ret = NETDEV_TX_OK; |
| 2620 | goto out; | 2622 | goto out; |
| @@ -2903,8 +2903,8 @@ static void iavf_watchdog_task(struct work_struct *work) · 2902 unmodified lines | |||
| 2903 | } | 2903 | } |
| 2904 | 2904 | ||
| 2905 | mutex_unlock(&adapter->crit_lock); | 2905 | mutex_unlock(&adapter->crit_lock); |
| 2906 | netdev_unlock(netdev); | ||
| 2907 | restart_watchdog: | 2906 | restart_watchdog: |
| 2907 | netdev_unlock(netdev); | ||
| 2908 | if (adapter->state >= __IAVF_DOWN) | 2908 | if (adapter->state >= __IAVF_DOWN) |
| 2909 | queue_work(adapter->wq, &adapter->adminq_task); | 2909 | queue_work(adapter->wq, &adapter->adminq_task); |
| 2910 | if (adapter->aq_required) | 2910 | if (adapter->aq_required) |
| @@ -981,6 +981,9 @@ static int ice_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv · 980 unmodified lines | |||
| 981 | 981 | ||
| 982 | /* preallocate memory for ice_sched_node */ | 982 | /* preallocate memory for ice_sched_node */ |
| 983 | node = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*node), GFP_KERNEL); | 983 | node = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*node), GFP_KERNEL); |
| 984 | if (!node) | ||
| 985 | return -ENOMEM; | ||
| 986 | |||
| 984 | *priv = node; | 987 | *priv = node; |
| 985 | 988 | ||
| 986 | return 0; | 989 | return 0; |
| @@ -527,15 +527,14 @@ err: · 526 unmodified lines | |||
| 527 | * @xdp: xdp_buff used as input to the XDP program | 527 | * @xdp: xdp_buff used as input to the XDP program |
| 528 | * @xdp_prog: XDP program to run | 528 | * @xdp_prog: XDP program to run |
| 529 | * @xdp_ring: ring to be used for XDP_TX action | 529 | * @xdp_ring: ring to be used for XDP_TX action |
| 530 | * @rx_buf: Rx buffer to store the XDP action | ||
| 531 | * @eop_desc: Last descriptor in packet to read metadata from | 530 | * @eop_desc: Last descriptor in packet to read metadata from |
| 532 | * | 531 | * |
| 533 | * Returns any of ICE_XDP_{PASS, CONSUMED, TX, REDIR} | 532 | * Returns any of ICE_XDP_{PASS, CONSUMED, TX, REDIR} |
| 534 | */ | 533 | */ |
| 535 | static void | 534 | static u32 |
| 536 | ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, | 535 | ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, |
| 537 | struct bpf_prog *xdp_prog, struct ice_tx_ring *xdp_ring, | 536 | struct bpf_prog *xdp_prog, struct ice_tx_ring *xdp_ring, |
| 538 | struct ice_rx_buf *rx_buf, union ice_32b_rx_flex_desc *eop_desc) | 537 | union ice_32b_rx_flex_desc *eop_desc) |
| 539 | { | 538 | { |
| 540 | unsigned int ret = ICE_XDP_PASS; | 539 | unsigned int ret = ICE_XDP_PASS; |
| 541 | u32 act; | 540 | u32 act; |
| @@ -574,7 +573,7 @@ out_failure: · 32 unmodified lines | |||
| 574 | ret = ICE_XDP_CONSUMED; | 573 | ret = ICE_XDP_CONSUMED; |
| 575 | } | 574 | } |
| 576 | exit: | 575 | exit: |
| 577 | ice_set_rx_bufs_act(xdp, rx_ring, ret); | 576 | return ret; |
| 578 | } | 577 | } |
| 579 | 578 | ||
| 580 | /** | 579 | /** |
| @@ -860,10 +859,8 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, · 279 unmodified lines | |||
| 860 | xdp_buff_set_frags_flag(xdp); | 859 | xdp_buff_set_frags_flag(xdp); |
| 861 | } | 860 | } |
| 862 | 861 | ||
| 863 | if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) { | 862 | if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) |
| 864 | ice_set_rx_bufs_act(xdp, rx_ring, ICE_XDP_CONSUMED); | ||
| 865 | return -ENOMEM; | 863 | return -ENOMEM; |
| 866 | } | ||
| 867 | 864 | ||
| 868 | __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page, | 865 | __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page, |
| 869 | rx_buf->page_offset, size); | 866 | rx_buf->page_offset, size); |
| @@ -924,7 +921,6 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size, · 54 unmodified lines | |||
| 924 | struct ice_rx_buf *rx_buf; | 921 | struct ice_rx_buf *rx_buf; |
| 925 | 922 | ||
| 926 | rx_buf = &rx_ring->rx_buf[ntc]; | 923 | rx_buf = &rx_ring->rx_buf[ntc]; |
| 927 | rx_buf->pgcnt = page_count(rx_buf->page); | ||
| 928 | prefetchw(rx_buf->page); | 924 | prefetchw(rx_buf->page); |
| 929 | 925 | ||
| 930 | if (!size) | 926 | if (!size) |
| @@ -940,6 +936,31 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size, · 9 unmodified lines | |||
| 940 | return rx_buf; | 936 | return rx_buf; |
| 941 | } | 937 | } |
| 942 | 938 | ||
| 939 | /** | ||
| 940 | * ice_get_pgcnts - grab page_count() for gathered fragments | ||
| 941 | * @rx_ring: Rx descriptor ring to store the page counts on | ||
| 942 | * | ||
| 943 | * This function is intended to be called right before running XDP | ||
| 944 | * program so that the page recycling mechanism will be able to take | ||
| 945 | * a correct decision regarding underlying pages; this is done in such | ||
| 946 | * way as XDP program can change the refcount of page | ||
| 947 | */ | ||
| 948 | static void ice_get_pgcnts(struct ice_rx_ring *rx_ring) | ||
| 949 | { | ||
| 950 | u32 nr_frags = rx_ring->nr_frags + 1; | ||
| 951 | u32 idx = rx_ring->first_desc; | ||
| 952 | struct ice_rx_buf *rx_buf; | ||
| 953 | u32 cnt = rx_ring->count; | ||
| 954 | |||
| 955 | for (int i = 0; i < nr_frags; i++) { | ||
| 956 | rx_buf = &rx_ring->rx_buf[idx]; | ||
| 957 | rx_buf->pgcnt = page_count(rx_buf->page); | ||
| 958 | |||
| 959 | if (++idx == cnt) | ||
| 960 | idx = 0; | ||
| 961 | } | ||
| 962 | } | ||
| 963 | |||
| 943 | /** | 964 | /** |
| 944 | * ice_build_skb - Build skb around an existing buffer | 965 | * ice_build_skb - Build skb around an existing buffer |
| 945 | * @rx_ring: Rx descriptor ring to transact packets on | 966 | * @rx_ring: Rx descriptor ring to transact packets on |
| @@ -1051,12 +1072,12 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp) · 105 unmodified lines | |||
| 1051 | rx_buf->page_offset + headlen, size, | 1072 | rx_buf->page_offset + headlen, size, |
| 1052 | xdp->frame_sz); | 1073 | xdp->frame_sz); |
| 1053 | } else { | 1074 | } else { |
| 1054 | /* buffer is unused, change the act that should be taken later | 1075 | /* buffer is unused, restore biased page count in Rx buffer; |
| 1055 | * on; data was copied onto skb's linear part so there's no | 1076 | * data was copied onto skb's linear part so there's no |
| 1056 | * need for adjusting page offset and we can reuse this buffer | 1077 | * need for adjusting page offset and we can reuse this buffer |
| 1057 | * as-is | 1078 | * as-is |
| 1058 | */ | 1079 | */ |
| 1059 | rx_buf->act = ICE_SKB_CONSUMED; | 1080 | rx_buf->pagecnt_bias++; |
| 1060 | } | 1081 | } |
| 1061 | 1082 | ||
| 1062 | if (unlikely(xdp_buff_has_frags(xdp))) { | 1083 | if (unlikely(xdp_buff_has_frags(xdp))) { |
| @@ -1103,6 +1124,65 @@ ice_put_rx_buf(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf) · 40 unmodified lines | |||
| 1103 | rx_buf->page = NULL; | 1124 | rx_buf->page = NULL; |
| 1104 | } | 1125 | } |
| 1105 | 1126 | ||
| 1127 | /** | ||
| 1128 | * ice_put_rx_mbuf - ice_put_rx_buf() caller, for all frame frags | ||
| 1129 | * @rx_ring: Rx ring with all the auxiliary data | ||
| 1130 | * @xdp: XDP buffer carrying linear + frags part | ||
| 1131 | * @xdp_xmit: XDP_TX/XDP_REDIRECT verdict storage | ||
| 1132 | * @ntc: a current next_to_clean value to be stored at rx_ring | ||
| 1133 | * @verdict: return code from XDP program execution | ||
| 1134 | * | ||
| 1135 | * Walk through gathered fragments and satisfy internal page | ||
| 1136 | * recycle mechanism; we take here an action related to verdict | ||
| 1137 | * returned by XDP program; | ||
| 1138 | */ | ||
| 1139 | static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, | ||
| 1140 | u32 *xdp_xmit, u32 ntc, u32 verdict) | ||
| 1141 | { | ||
| 1142 | u32 nr_frags = rx_ring->nr_frags + 1; | ||
| 1143 | u32 idx = rx_ring->first_desc; | ||
| 1144 | u32 cnt = rx_ring->count; | ||
| 1145 | u32 post_xdp_frags = 1; | ||
| 1146 | struct ice_rx_buf *buf; | ||
| 1147 | int i; | ||
| 1148 | |||
| 1149 | if (unlikely(xdp_buff_has_frags(xdp))) | ||
| 1150 | post_xdp_frags += xdp_get_shared_info_from_buff(xdp)->nr_frags; | ||
| 1151 | |||
| 1152 | for (i = 0; i < post_xdp_frags; i++) { | ||
| 1153 | buf = &rx_ring->rx_buf[idx]; | ||
| 1154 | |||
| 1155 | if (verdict & (ICE_XDP_TX | ICE_XDP_REDIR)) { | ||
| 1156 | ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); | ||
| 1157 | *xdp_xmit |= verdict; | ||
| 1158 | } else if (verdict & ICE_XDP_CONSUMED) { | ||
| 1159 | buf->pagecnt_bias++; | ||
| 1160 | } else if (verdict == ICE_XDP_PASS) { | ||
| 1161 | ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | ice_put_rx_buf(rx_ring, buf); | ||
| 1165 | |||
| 1166 | if (++idx == cnt) | ||
| 1167 | idx = 0; | ||
| 1168 | } | ||
| 1169 | /* handle buffers that represented frags released by XDP prog; | ||
| 1170 | * for these we keep pagecnt_bias as-is; refcount from struct page | ||
| 1171 | * has been decremented within XDP prog and we do not have to increase | ||
| 1172 | * the biased refcnt | ||
| 1173 | */ | ||
| 1174 | for (; i < nr_frags; i++) { | ||
| 1175 | buf = &rx_ring->rx_buf[idx]; | ||
| 1176 | ice_put_rx_buf(rx_ring, buf); | ||
| 1177 | if (++idx == cnt) | ||
| 1178 | idx = 0; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | xdp->data = NULL; | ||
| 1182 | rx_ring->first_desc = ntc; | ||
| 1183 | rx_ring->nr_frags = 0; | ||
| 1184 | } | ||
| 1185 | |||
| 1106 | /** | 1186 | /** |
| 1107 | * ice_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf | 1187 | * ice_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf |
| 1108 | * @rx_ring: Rx descriptor ring to transact packets on | 1188 | * @rx_ring: Rx descriptor ring to transact packets on |
| @@ -1120,15 +1200,13 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) · 11 unmodified lines | |||
| 1120 | unsigned int total_rx_bytes = 0, total_rx_pkts = 0; | 1200 | unsigned int total_rx_bytes = 0, total_rx_pkts = 0; |
| 1121 | unsigned int offset = rx_ring->rx_offset; | 1201 | unsigned int offset = rx_ring->rx_offset; |
| 1122 | struct xdp_buff *xdp = &rx_ring->xdp; | 1202 | struct xdp_buff *xdp = &rx_ring->xdp; |
| 1123 | u32 cached_ntc = rx_ring->first_desc; | ||
| 1124 | struct ice_tx_ring *xdp_ring = NULL; | 1203 | struct ice_tx_ring *xdp_ring = NULL; |
| 1125 | struct bpf_prog *xdp_prog = NULL; | 1204 | struct bpf_prog *xdp_prog = NULL; |
| 1126 | u32 ntc = rx_ring->next_to_clean; | 1205 | u32 ntc = rx_ring->next_to_clean; |
| 1206 | u32 cached_ntu, xdp_verdict; | ||
| 1127 | u32 cnt = rx_ring->count; | 1207 | u32 cnt = rx_ring->count; |
| 1128 | u32 xdp_xmit = 0; | 1208 | u32 xdp_xmit = 0; |
| 1129 | u32 cached_ntu; | ||
| 1130 | bool failure; | 1209 | bool failure; |
| 1131 | u32 first; | ||
| 1132 | 1210 | ||
| 1133 | xdp_prog = READ_ONCE(rx_ring->xdp_prog); | 1211 | xdp_prog = READ_ONCE(rx_ring->xdp_prog); |
| 1134 | if (xdp_prog) { | 1212 | if (xdp_prog) { |
| @@ -1190,6 +1268,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) · 55 unmodified lines | |||
| 1190 | xdp_prepare_buff(xdp, hard_start, offset, size, !!offset); | 1268 | xdp_prepare_buff(xdp, hard_start, offset, size, !!offset); |
| 1191 | xdp_buff_clear_frags_flag(xdp); | 1269 | xdp_buff_clear_frags_flag(xdp); |
| 1192 | } else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) { | 1270 | } else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) { |
| 1271 | ice_put_rx_mbuf(rx_ring, xdp, NULL, ntc, ICE_XDP_CONSUMED); | ||
| 1193 | break; | 1272 | break; |
| 1194 | } | 1273 | } |
| 1195 | if (++ntc == cnt) | 1274 | if (++ntc == cnt) |
| @@ -1199,15 +1278,15 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) · 3 unmodified lines | |||
| 1199 | if (ice_is_non_eop(rx_ring, rx_desc)) | 1278 | if (ice_is_non_eop(rx_ring, rx_desc)) |
| 1200 | continue; | 1279 | continue; |
| 1201 | 1280 | ||
| 1202 | ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_buf, rx_desc); | 1281 | ice_get_pgcnts(rx_ring); |
| 1203 | if (rx_buf->act == ICE_XDP_PASS) | 1282 | xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_desc); |
| 1283 | if (xdp_verdict == ICE_XDP_PASS) | ||
| 1204 | goto construct_skb; | 1284 | goto construct_skb; |
| 1205 | total_rx_bytes += xdp_get_buff_len(xdp); | 1285 | total_rx_bytes += xdp_get_buff_len(xdp); |
| 1206 | total_rx_pkts++; | 1286 | total_rx_pkts++; |
| 1207 | 1287 | ||
| 1208 | xdp->data = NULL; | 1288 | ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); |
| 1209 | rx_ring->first_desc = ntc; | 1289 | |
| 1210 | rx_ring->nr_frags = 0; | ||
| 1211 | continue; | 1290 | continue; |
| 1212 | construct_skb: | 1291 | construct_skb: |
| 1213 | if (likely(ice_ring_uses_build_skb(rx_ring))) | 1292 | if (likely(ice_ring_uses_build_skb(rx_ring))) |
| @@ -1217,18 +1296,12 @@ construct_skb: · 3 unmodified lines | |||
| 1217 | /* exit if we failed to retrieve a buffer */ | 1296 | /* exit if we failed to retrieve a buffer */ |
| 1218 | if (!skb) { | 1297 | if (!skb) { |
| 1219 | rx_ring->ring_stats->rx_stats.alloc_page_failed++; | 1298 | rx_ring->ring_stats->rx_stats.alloc_page_failed++; |
| 1220 | rx_buf->act = ICE_XDP_CONSUMED; | 1299 | xdp_verdict = ICE_XDP_CONSUMED; |
| 1221 | if (unlikely(xdp_buff_has_frags(xdp))) | ||
| 1222 | ice_set_rx_bufs_act(xdp, rx_ring, | ||
| 1223 | ICE_XDP_CONSUMED); | ||
| 1224 | xdp->data = NULL; | ||
| 1225 | rx_ring->first_desc = ntc; | ||
| 1226 | rx_ring->nr_frags = 0; | ||
| 1227 | break; | ||
| 1228 | } | 1300 | } |
| 1229 | xdp->data = NULL; | 1301 | ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); |
| 1230 | rx_ring->first_desc = ntc; | 1302 | |
| 1231 | rx_ring->nr_frags = 0; | 1303 | if (!skb) |
| 1304 | break; | ||
| 1232 | 1305 | ||
| 1233 | stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S); | 1306 | stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S); |
| 1234 | if (unlikely(ice_test_staterr(rx_desc->wb.status_error0, | 1307 | if (unlikely(ice_test_staterr(rx_desc->wb.status_error0, |
| @@ -1257,23 +1330,6 @@ construct_skb: · 22 unmodified lines | |||
| 1257 | total_rx_pkts++; | 1330 | total_rx_pkts++; |
| 1258 | } | 1331 | } |
| 1259 | 1332 | ||
| 1260 | first = rx_ring->first_desc; | ||
| 1261 | while (cached_ntc != first) { | ||
| 1262 | struct ice_rx_buf *buf = &rx_ring->rx_buf[cached_ntc]; | ||
| 1263 | |||
| 1264 | if (buf->act & (ICE_XDP_TX | ICE_XDP_REDIR)) { | ||
| 1265 | ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); | ||
| 1266 | xdp_xmit |= buf->act; | ||
| 1267 | } else if (buf->act & ICE_XDP_CONSUMED) { | ||
| 1268 | buf->pagecnt_bias++; | ||
| 1269 | } else if (buf->act == ICE_XDP_PASS) { | ||
| 1270 | ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | ice_put_rx_buf(rx_ring, buf); | ||
| 1274 | if (++cached_ntc >= cnt) | ||
| 1275 | cached_ntc = 0; | ||
| 1276 | } | ||
| 1277 | rx_ring->next_to_clean = ntc; | 1333 | rx_ring->next_to_clean = ntc; |
| 1278 | /* return up to cleaned_count buffers to hardware */ | 1334 | /* return up to cleaned_count buffers to hardware */ |
| 1279 | failure = ice_alloc_rx_bufs(rx_ring, ICE_RX_DESC_UNUSED(rx_ring)); | 1335 | failure = ice_alloc_rx_bufs(rx_ring, ICE_RX_DESC_UNUSED(rx_ring)); |
| @@ -201,7 +201,6 @@ struct ice_rx_buf { · 200 unmodified lines | |||
| 201 | struct page *page; | 201 | struct page *page; |
| 202 | unsigned int page_offset; | 202 | unsigned int page_offset; |
| 203 | unsigned int pgcnt; | 203 | unsigned int pgcnt; |
| 204 | unsigned int act; | ||
| 205 | unsigned int pagecnt_bias; | 204 | unsigned int pagecnt_bias; |
| 206 | }; | 205 | }; |
| 207 | 206 | ||
| @@ -5,49 +5,6 @@ · 4 unmodified lines | |||
| 5 | #define _ICE_TXRX_LIB_H_ | 5 | #define _ICE_TXRX_LIB_H_ |
| 6 | #include "ice.h" | 6 | #include "ice.h" |
| 7 | 7 | ||
| 8 | /** | ||
| 9 | * ice_set_rx_bufs_act - propagate Rx buffer action to frags | ||
| 10 | * @xdp: XDP buffer representing frame (linear and frags part) | ||
| 11 | * @rx_ring: Rx ring struct | ||
| 12 | * act: action to store onto Rx buffers related to XDP buffer parts | ||
| 13 | * | ||
| 14 | * Set action that should be taken before putting Rx buffer from first frag | ||
| 15 | * to the last. | ||
| 16 | */ | ||
| 17 | static inline void | ||
| 18 | ice_set_rx_bufs_act(struct xdp_buff *xdp, const struct ice_rx_ring *rx_ring, | ||
| 19 | const unsigned int act) | ||
| 20 | { | ||
| 21 | u32 sinfo_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags; | ||
| 22 | u32 nr_frags = rx_ring->nr_frags + 1; | ||
| 23 | u32 idx = rx_ring->first_desc; | ||
| 24 | u32 cnt = rx_ring->count; | ||
| 25 | struct ice_rx_buf *buf; | ||
| 26 | |||
| 27 | for (int i = 0; i < nr_frags; i++) { | ||
| 28 | buf = &rx_ring->rx_buf[idx]; | ||
| 29 | buf->act = act; | ||
| 30 | |||
| 31 | if (++idx == cnt) | ||
| 32 | idx = 0; | ||
| 33 | } | ||
| 34 | |||
| 35 | /* adjust pagecnt_bias on frags freed by XDP prog */ | ||
| 36 | if (sinfo_frags < rx_ring->nr_frags && act == ICE_XDP_CONSUMED) { | ||
| 37 | u32 delta = rx_ring->nr_frags - sinfo_frags; | ||
| 38 | |||
| 39 | while (delta) { | ||
| 40 | if (idx == 0) | ||
| 41 | idx = cnt - 1; | ||
| 42 | else | ||
| 43 | idx--; | ||
| 44 | buf = &rx_ring->rx_buf[idx]; | ||
| 45 | buf->pagecnt_bias--; | ||
| 46 | delta--; | ||
| 47 | } | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | /** | 8 | /** |
| 52 | * ice_test_staterr - tests bits in Rx descriptor status and error fields | 9 | * ice_test_staterr - tests bits in Rx descriptor status and error fields |
| 53 | * @status_err_n: Rx descriptor status_error0 or status_error1 bits | 10 | * @status_err_n: Rx descriptor status_error0 or status_error1 bits |
| @@ -2159,8 +2159,13 @@ static int idpf_open(struct net_device *netdev) · 2158 unmodified lines | |||
| 2159 | idpf_vport_ctrl_lock(netdev); | 2159 | idpf_vport_ctrl_lock(netdev); |
| 2160 | vport = idpf_netdev_to_vport(netdev); | 2160 | vport = idpf_netdev_to_vport(netdev); |
| 2161 | 2161 | ||
| 2162 | err = idpf_set_real_num_queues(vport); | ||
| 2163 | if (err) | ||
| 2164 | goto unlock; | ||
| 2165 | |||
| 2162 | err = idpf_vport_open(vport); | 2166 | err = idpf_vport_open(vport); |
| 2163 | 2167 | ||
| 2168 | unlock: | ||
| 2164 | idpf_vport_ctrl_unlock(netdev); | 2169 | idpf_vport_ctrl_unlock(netdev); |
| 2165 | 2170 | ||
| 2166 | return err; | 2171 | return err; |
| @@ -3008,8 +3008,6 @@ static int idpf_rx_rsc(struct idpf_rx_queue *rxq, struct sk_buff *skb, · 3007 unmodified lines | |||
| 3008 | return -EINVAL; | 3008 | return -EINVAL; |
| 3009 | 3009 | ||
| 3010 | rsc_segments = DIV_ROUND_UP(skb->data_len, rsc_seg_len); | 3010 | rsc_segments = DIV_ROUND_UP(skb->data_len, rsc_seg_len); |
| 3011 | if (unlikely(rsc_segments == 1)) | ||
| 3012 | return 0; | ||
| 3013 | 3011 | ||
| 3014 | NAPI_GRO_CB(skb)->count = rsc_segments; | 3012 | NAPI_GRO_CB(skb)->count = rsc_segments; |
| 3015 | skb_shinfo(skb)->gso_size = rsc_seg_len; | 3013 | skb_shinfo(skb)->gso_size = rsc_seg_len; |
| @@ -3072,6 +3070,7 @@ idpf_rx_process_skb_fields(struct idpf_rx_queue *rxq, struct sk_buff *skb, · 56 unmodified lines | |||
| 3072 | idpf_rx_hash(rxq, skb, rx_desc, decoded); | 3070 | idpf_rx_hash(rxq, skb, rx_desc, decoded); |
| 3073 | 3071 | ||
| 3074 | skb->protocol = eth_type_trans(skb, rxq->netdev); | 3072 | skb->protocol = eth_type_trans(skb, rxq->netdev); |
| 3073 | skb_record_rx_queue(skb, rxq->idx); | ||
| 3075 | 3074 | ||
| 3076 | if (le16_get_bits(rx_desc->hdrlen_flags, | 3075 | if (le16_get_bits(rx_desc->hdrlen_flags, |
| 3077 | VIRTCHNL2_RX_FLEX_DESC_ADV_RSC_M)) | 3076 | VIRTCHNL2_RX_FLEX_DESC_ADV_RSC_M)) |
| @@ -3080,8 +3079,6 @@ idpf_rx_process_skb_fields(struct idpf_rx_queue *rxq, struct sk_buff *skb, · 2 unmodified lines | |||
| 3080 | csum_bits = idpf_rx_splitq_extract_csum_bits(rx_desc); | 3079 | csum_bits = idpf_rx_splitq_extract_csum_bits(rx_desc); |
| 3081 | idpf_rx_csum(rxq, skb, csum_bits, decoded); | 3080 | idpf_rx_csum(rxq, skb, csum_bits, decoded); |
| 3082 | 3081 | ||
| 3083 | skb_record_rx_queue(skb, rxq->idx); | ||
| 3084 | |||
| 3085 | return 0; | 3082 | return 0; |
| 3086 | } | 3083 | } |
| 3087 | 3084 | ||
| @@ -1096,6 +1096,7 @@ static int igc_init_empty_frame(struct igc_ring *ring, · 1095 unmodified lines | |||
| 1096 | return -ENOMEM; | 1096 | return -ENOMEM; |
| 1097 | } | 1097 | } |
| 1098 | 1098 | ||
| 1099 | buffer->type = IGC_TX_BUFFER_TYPE_SKB; | ||
| 1099 | buffer->skb = skb; | 1100 | buffer->skb = skb; |
| 1100 | buffer->protocol = 0; | 1101 | buffer->protocol = 0; |
| 1101 | buffer->bytecount = skb->len; | 1102 | buffer->bytecount = skb->len; |
| @@ -2701,8 +2702,9 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget) · 1599 unmodified lines | |||
| 2701 | } | 2702 | } |
| 2702 | 2703 | ||
| 2703 | static struct sk_buff *igc_construct_skb_zc(struct igc_ring *ring, | 2704 | static struct sk_buff *igc_construct_skb_zc(struct igc_ring *ring, |
| 2704 | struct xdp_buff *xdp) | 2705 | struct igc_xdp_buff *ctx) |
| 2705 | { | 2706 | { |
| 2707 | struct xdp_buff *xdp = &ctx->xdp; | ||
| 2706 | unsigned int totalsize = xdp->data_end - xdp->data_meta; | 2708 | unsigned int totalsize = xdp->data_end - xdp->data_meta; |
| 2707 | unsigned int metasize = xdp->data - xdp->data_meta; | 2709 | unsigned int metasize = xdp->data - xdp->data_meta; |
| 2708 | struct sk_buff *skb; | 2710 | struct sk_buff *skb; |
| @@ -2721,27 +2723,28 @@ static struct sk_buff *igc_construct_skb_zc(struct igc_ring *ring, · 12 unmodified lines | |||
| 2721 | __skb_pull(skb, metasize); | 2723 | __skb_pull(skb, metasize); |
| 2722 | } | 2724 | } |
| 2723 | 2725 | ||
| 2726 | if (ctx->rx_ts) { | ||
| 2727 | skb_shinfo(skb)->tx_flags |= SKBTX_HW_TSTAMP_NETDEV; | ||
| 2728 | skb_hwtstamps(skb)->netdev_data = ctx->rx_ts; | ||
| 2729 | } | ||
| 2730 | |||
| 2724 | return skb; | 2731 | return skb; |
| 2725 | } | 2732 | } |
| 2726 | 2733 | ||
| 2727 | static void igc_dispatch_skb_zc(struct igc_q_vector *q_vector, | 2734 | static void igc_dispatch_skb_zc(struct igc_q_vector *q_vector, |
| 2728 | union igc_adv_rx_desc *desc, | 2735 | union igc_adv_rx_desc *desc, |
| 2729 | struct xdp_buff *xdp, | 2736 | struct igc_xdp_buff *ctx) |
| 2730 | ktime_t timestamp) | ||
| 2731 | { | 2737 | { |
| 2732 | struct igc_ring *ring = q_vector->rx.ring; | 2738 | struct igc_ring *ring = q_vector->rx.ring; |
| 2733 | struct sk_buff *skb; | 2739 | struct sk_buff *skb; |
| 2734 | 2740 | ||
| 2735 | skb = igc_construct_skb_zc(ring, xdp); | 2741 | skb = igc_construct_skb_zc(ring, ctx); |
| 2736 | if (!skb) { | 2742 | if (!skb) { |
| 2737 | ring->rx_stats.alloc_failed++; | 2743 | ring->rx_stats.alloc_failed++; |
| 2738 | set_bit(IGC_RING_FLAG_RX_ALLOC_FAILED, &ring->flags); | 2744 | set_bit(IGC_RING_FLAG_RX_ALLOC_FAILED, &ring->flags); |
| 2739 | return; | 2745 | return; |
| 2740 | } | 2746 | } |
| 2741 | 2747 | ||
| 2742 | if (timestamp) | ||
| 2743 | skb_hwtstamps(skb)->hwtstamp = timestamp; | ||
| 2744 | |||
| 2745 | if (igc_cleanup_headers(ring, desc, skb)) | 2748 | if (igc_cleanup_headers(ring, desc, skb)) |
| 2746 | return; | 2749 | return; |
| 2747 | 2750 | ||
| @@ -2777,7 +2780,6 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget) · 29 unmodified lines | |||
| 2777 | union igc_adv_rx_desc *desc; | 2780 | union igc_adv_rx_desc *desc; |
| 2778 | struct igc_rx_buffer *bi; | 2781 | struct igc_rx_buffer *bi; |
| 2779 | struct igc_xdp_buff *ctx; | 2782 | struct igc_xdp_buff *ctx; |
| 2780 | ktime_t timestamp = 0; | ||
| 2781 | unsigned int size; | 2783 | unsigned int size; |
| 2782 | int res; | 2784 | int res; |
| 2783 | 2785 | ||
| @@ -2807,6 +2809,8 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget) · 23 unmodified lines | |||
| 2807 | */ | 2809 | */ |
| 2808 | bi->xdp->data_meta += IGC_TS_HDR_LEN; | 2810 | bi->xdp->data_meta += IGC_TS_HDR_LEN; |
| 2809 | size -= IGC_TS_HDR_LEN; | 2811 | size -= IGC_TS_HDR_LEN; |
| 2812 | } else { | ||
| 2813 | ctx->rx_ts = NULL; | ||
| 2810 | } | 2814 | } |
| 2811 | 2815 | ||
| 2812 | bi->xdp->data_end = bi->xdp->data + size; | 2816 | bi->xdp->data_end = bi->xdp->data + size; |
| @@ -2815,7 +2819,7 @@ static int igc_clean_rx_irq_zc(struct igc_q_vector *q_vector, const int budget) · 2 unmodified lines | |||
| 2815 | res = __igc_xdp_run_prog(adapter, prog, bi->xdp); | 2819 | res = __igc_xdp_run_prog(adapter, prog, bi->xdp); |
| 2816 | switch (res) { | 2820 | switch (res) { |
| 2817 | case IGC_XDP_PASS: | 2821 | case IGC_XDP_PASS: |
| 2818 | igc_dispatch_skb_zc(q_vector, desc, bi->xdp, timestamp); | 2822 | igc_dispatch_skb_zc(q_vector, desc, ctx); |
| 2819 | fallthrough; | 2823 | fallthrough; |
| 2820 | case IGC_XDP_CONSUMED: | 2824 | case IGC_XDP_CONSUMED: |
| 2821 | xsk_buff_free(bi->xdp); | 2825 | xsk_buff_free(bi->xdp); |
| @@ -2105,7 +2105,7 @@ static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring, · 2104 unmodified lines | |||
| 2105 | /* hand second half of page back to the ring */ | 2105 | /* hand second half of page back to the ring */ |
| 2106 | ixgbe_reuse_rx_page(rx_ring, rx_buffer); | 2106 | ixgbe_reuse_rx_page(rx_ring, rx_buffer); |
| 2107 | } else { | 2107 | } else { |
| 2108 | if (!IS_ERR(skb) && IXGBE_CB(skb)->dma == rx_buffer->dma) { | 2108 | if (skb && IXGBE_CB(skb)->dma == rx_buffer->dma) { |
| 2109 | /* the page has been released from the ring */ | 2109 | /* the page has been released from the ring */ |
| 2110 | IXGBE_CB(skb)->page_released = true; | 2110 | IXGBE_CB(skb)->page_released = true; |
| 2111 | } else { | 2111 | } else { |
| @@ -768,7 +768,9 @@ static void __mlxsw_sp_port_get_stats(struct net_device *dev, · 767 unmodified lines | |||
| 768 | err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp); | 768 | err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp); |
| 769 | if (err) | 769 | if (err) |
| 770 | return; | 770 | return; |
| 771 | mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl); | 771 | err = mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl); |
| 772 | if (err) | ||
| 773 | return; | ||
| 772 | for (i = 0; i < len; i++) { | 774 | for (i = 0; i < len; i++) { |
| 773 | data[data_index + i] = hw_stats[i].getter(ppcnt_pl); | 775 | data[data_index + i] = hw_stats[i].getter(ppcnt_pl); |
| 774 | if (!hw_stats[i].cells_bytes) | 776 | if (!hw_stats[i].cells_bytes) |
| @@ -20,6 +20,8 @@ nfp_bpf_cmsg_alloc(struct nfp_app_bpf *bpf, unsigned int size) · 19 unmodified lines | |||
| 20 | struct sk_buff *skb; | 20 | struct sk_buff *skb; |
| 21 | 21 | ||
| 22 | skb = nfp_app_ctrl_msg_alloc(bpf->app, size, GFP_KERNEL); | 22 | skb = nfp_app_ctrl_msg_alloc(bpf->app, size, GFP_KERNEL); |
| 23 | if (!skb) | ||
| 24 | return NULL; | ||
| 23 | skb_put(skb, size); | 25 | skb_put(skb, size); |
| 24 | 26 | ||
| 25 | return skb; | 27 | return skb; |
| @@ -2094,6 +2094,11 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, · 2093 unmodified lines | |||
| 2094 | pp_params.offset = stmmac_rx_offset(priv); | 2094 | pp_params.offset = stmmac_rx_offset(priv); |
| 2095 | pp_params.max_len = dma_conf->dma_buf_sz; | 2095 | pp_params.max_len = dma_conf->dma_buf_sz; |
| 2096 | 2096 | ||
| 2097 | if (priv->sph) { | ||
| 2098 | pp_params.offset = 0; | ||
| 2099 | pp_params.max_len += stmmac_rx_offset(priv); | ||
| 2100 | } | ||
| 2101 | |||
| 2097 | rx_q->page_pool = page_pool_create(&pp_params); | 2102 | rx_q->page_pool = page_pool_create(&pp_params); |
| 2098 | if (IS_ERR(rx_q->page_pool)) { | 2103 | if (IS_ERR(rx_q->page_pool)) { |
| 2099 | ret = PTR_ERR(rx_q->page_pool); | 2104 | ret = PTR_ERR(rx_q->page_pool); |
| @@ -2424,6 +2429,11 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv) · 324 unmodified lines | |||
| 2424 | u32 chan = 0; | 2429 | u32 chan = 0; |
| 2425 | u8 qmode = 0; | 2430 | u8 qmode = 0; |
| 2426 | 2431 | ||
| 2432 | if (rxfifosz == 0) | ||
| 2433 | rxfifosz = priv->dma_cap.rx_fifo_size; | ||
| 2434 | if (txfifosz == 0) | ||
| 2435 | txfifosz = priv->dma_cap.tx_fifo_size; | ||
| 2436 | |||
| 2427 | /* Split up the shared Tx/Rx FIFO memory on DW QoS Eth and DW XGMAC */ | 2437 | /* Split up the shared Tx/Rx FIFO memory on DW QoS Eth and DW XGMAC */ |
| 2428 | if (priv->plat->has_gmac4 || priv->plat->has_xgmac) { | 2438 | if (priv->plat->has_gmac4 || priv->plat->has_xgmac) { |
| 2429 | rxfifosz /= rx_channels_count; | 2439 | rxfifosz /= rx_channels_count; |
| @@ -2892,6 +2902,11 @@ static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode, · 462 unmodified lines | |||
| 2892 | int rxfifosz = priv->plat->rx_fifo_size; | 2902 | int rxfifosz = priv->plat->rx_fifo_size; |
| 2893 | int txfifosz = priv->plat->tx_fifo_size; | 2903 | int txfifosz = priv->plat->tx_fifo_size; |
| 2894 | 2904 | ||
| 2905 | if (rxfifosz == 0) | ||
| 2906 | rxfifosz = priv->dma_cap.rx_fifo_size; | ||
| 2907 | if (txfifosz == 0) | ||
| 2908 | txfifosz = priv->dma_cap.tx_fifo_size; | ||
| 2909 | |||
| 2895 | /* Adjust for real per queue fifo size */ | 2910 | /* Adjust for real per queue fifo size */ |
| 2896 | rxfifosz /= rx_channels_count; | 2911 | rxfifosz /= rx_channels_count; |
| 2897 | txfifosz /= tx_channels_count; | 2912 | txfifosz /= tx_channels_count; |
| @@ -5868,6 +5883,9 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) · 2970 unmodified lines | |||
| 5868 | const int mtu = new_mtu; | 5883 | const int mtu = new_mtu; |
| 5869 | int ret; | 5884 | int ret; |
| 5870 | 5885 | ||
| 5886 | if (txfifosz == 0) | ||
| 5887 | txfifosz = priv->dma_cap.tx_fifo_size; | ||
| 5888 | |||
| 5871 | txfifosz /= priv->plat->tx_queues_to_use; | 5889 | txfifosz /= priv->plat->tx_queues_to_use; |
| 5872 | 5890 | ||
| 5873 | if (stmmac_xdp_is_enabled(priv) && new_mtu > ETH_DATA_LEN) { | 5891 | if (stmmac_xdp_is_enabled(priv) && new_mtu > ETH_DATA_LEN) { |
| @@ -7219,29 +7237,15 @@ static int stmmac_hw_init(struct stmmac_priv *priv) · 1345 unmodified lines | |||
| 7219 | priv->plat->tx_queues_to_use = priv->dma_cap.number_tx_queues; | 7237 | priv->plat->tx_queues_to_use = priv->dma_cap.number_tx_queues; |
| 7220 | } | 7238 | } |
| 7221 | 7239 | ||
| 7222 | if (!priv->plat->rx_fifo_size) { | 7240 | if (priv->dma_cap.rx_fifo_size && |
| 7223 | if (priv->dma_cap.rx_fifo_size) { | 7241 | priv->plat->rx_fifo_size > priv->dma_cap.rx_fifo_size) { |
| 7224 | priv->plat->rx_fifo_size = priv->dma_cap.rx_fifo_size; | ||
| 7225 | } else { | ||
| 7226 | dev_err(priv->device, "Can't specify Rx FIFO size\n"); | ||
| 7227 | return -ENODEV; | ||
| 7228 | } | ||
| 7229 | } else if (priv->dma_cap.rx_fifo_size && | ||
| 7230 | priv->plat->rx_fifo_size > priv->dma_cap.rx_fifo_size) { | ||
| 7231 | dev_warn(priv->device, | 7242 | dev_warn(priv->device, |
| 7232 | "Rx FIFO size (%u) exceeds dma capability\n", | 7243 | "Rx FIFO size (%u) exceeds dma capability\n", |
| 7233 | priv->plat->rx_fifo_size); | 7244 | priv->plat->rx_fifo_size); |
| 7234 | priv->plat->rx_fifo_size = priv->dma_cap.rx_fifo_size; | 7245 | priv->plat->rx_fifo_size = priv->dma_cap.rx_fifo_size; |
| 7235 | } | 7246 | } |
| 7236 | if (!priv->plat->tx_fifo_size) { | 7247 | if (priv->dma_cap.tx_fifo_size && |
| 7237 | if (priv->dma_cap.tx_fifo_size) { | 7248 | priv->plat->tx_fifo_size > priv->dma_cap.tx_fifo_size) { |
| 7238 | priv->plat->tx_fifo_size = priv->dma_cap.tx_fifo_size; | ||
| 7239 | } else { | ||
| 7240 | dev_err(priv->device, "Can't specify Tx FIFO size\n"); | ||
| 7241 | return -ENODEV; | ||
| 7242 | } | ||
| 7243 | } else if (priv->dma_cap.tx_fifo_size && | ||
| 7244 | priv->plat->tx_fifo_size > priv->dma_cap.tx_fifo_size) { | ||
| 7245 | dev_warn(priv->device, | 7249 | dev_warn(priv->device, |
| 7246 | "Tx FIFO size (%u) exceeds dma capability\n", | 7250 | "Tx FIFO size (%u) exceeds dma capability\n", |
| 7247 | priv->plat->tx_fifo_size); | 7251 | priv->plat->tx_fifo_size); |
| @@ -828,21 +828,30 @@ static void am65_cpsw_nuss_xmit_free(struct am65_cpsw_tx_chn *tx_chn, · 827 unmodified lines | |||
| 828 | static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma) | 828 | static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma) |
| 829 | { | 829 | { |
| 830 | struct am65_cpsw_tx_chn *tx_chn = data; | 830 | struct am65_cpsw_tx_chn *tx_chn = data; |
| 831 | enum am65_cpsw_tx_buf_type buf_type; | ||
| 831 | struct cppi5_host_desc_t *desc_tx; | 832 | struct cppi5_host_desc_t *desc_tx; |
| 833 | struct xdp_frame *xdpf; | ||
| 832 | struct sk_buff *skb; | 834 | struct sk_buff *skb; |
| 833 | void **swdata; | 835 | void **swdata; |
| 834 | 836 | ||
| 835 | desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma); | 837 | desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma); |
| 836 | swdata = cppi5_hdesc_get_swdata(desc_tx); | 838 | swdata = cppi5_hdesc_get_swdata(desc_tx); |
| 837 | skb = *(swdata); | 839 | buf_type = am65_cpsw_nuss_buf_type(tx_chn, desc_dma); |
| 838 | am65_cpsw_nuss_xmit_free(tx_chn, desc_tx); | 840 | if (buf_type == AM65_CPSW_TX_BUF_TYPE_SKB) { |
| 841 | skb = *(swdata); | ||
| 842 | dev_kfree_skb_any(skb); | ||
| 843 | } else { | ||
| 844 | xdpf = *(swdata); | ||
| 845 | xdp_return_frame(xdpf); | ||
| 846 | } | ||
| 839 | 847 | ||
| 840 | dev_kfree_skb_any(skb); | 848 | am65_cpsw_nuss_xmit_free(tx_chn, desc_tx); |
| 841 | } | 849 | } |
| 842 | 850 | ||
| 843 | static struct sk_buff *am65_cpsw_build_skb(void *page_addr, | 851 | static struct sk_buff *am65_cpsw_build_skb(void *page_addr, |
| 844 | struct net_device *ndev, | 852 | struct net_device *ndev, |
| 845 | unsigned int len) | 853 | unsigned int len, |
| 854 | unsigned int headroom) | ||
| 846 | { | 855 | { |
| 847 | struct sk_buff *skb; | 856 | struct sk_buff *skb; |
| 848 | 857 | ||
| @@ -852,7 +861,7 @@ static struct sk_buff *am65_cpsw_build_skb(void *page_addr, · 3 unmodified lines | |||
| 852 | if (unlikely(!skb)) | 861 | if (unlikely(!skb)) |
| 853 | return NULL; | 862 | return NULL; |
| 854 | 863 | ||
| 855 | skb_reserve(skb, AM65_CPSW_HEADROOM); | 864 | skb_reserve(skb, headroom); |
| 856 | skb->dev = ndev; | 865 | skb->dev = ndev; |
| 857 | 866 | ||
| 858 | return skb; | 867 | return skb; |
| @@ -1169,9 +1178,11 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow, · 310 unmodified lines | |||
| 1169 | struct xdp_frame *xdpf; | 1178 | struct xdp_frame *xdpf; |
| 1170 | struct bpf_prog *prog; | 1179 | struct bpf_prog *prog; |
| 1171 | struct page *page; | 1180 | struct page *page; |
| 1181 | int pkt_len; | ||
| 1172 | u32 act; | 1182 | u32 act; |
| 1173 | int err; | 1183 | int err; |
| 1174 | 1184 | ||
| 1185 | pkt_len = *len; | ||
| 1175 | prog = READ_ONCE(port->xdp_prog); | 1186 | prog = READ_ONCE(port->xdp_prog); |
| 1176 | if (!prog) | 1187 | if (!prog) |
| 1177 | return AM65_CPSW_XDP_PASS; | 1188 | return AM65_CPSW_XDP_PASS; |
| @@ -1189,8 +1200,10 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow, · 11 unmodified lines | |||
| 1189 | netif_txq = netdev_get_tx_queue(ndev, tx_chn->id); | 1200 | netif_txq = netdev_get_tx_queue(ndev, tx_chn->id); |
| 1190 | 1201 | ||
| 1191 | xdpf = xdp_convert_buff_to_frame(xdp); | 1202 | xdpf = xdp_convert_buff_to_frame(xdp); |
| 1192 | if (unlikely(!xdpf)) | 1203 | if (unlikely(!xdpf)) { |
| 1204 | ndev->stats.tx_dropped++; | ||
| 1193 | goto drop; | 1205 | goto drop; |
| 1206 | } | ||
| 1194 | 1207 | ||
| 1195 | __netif_tx_lock(netif_txq, cpu); | 1208 | __netif_tx_lock(netif_txq, cpu); |
| 1196 | err = am65_cpsw_xdp_tx_frame(ndev, tx_chn, xdpf, | 1209 | err = am65_cpsw_xdp_tx_frame(ndev, tx_chn, xdpf, |
| @@ -1199,14 +1212,14 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow, · 2 unmodified lines | |||
| 1199 | if (err) | 1212 | if (err) |
| 1200 | goto drop; | 1213 | goto drop; |
| 1201 | 1214 | ||
| 1202 | dev_sw_netstats_tx_add(ndev, 1, *len); | 1215 | dev_sw_netstats_rx_add(ndev, pkt_len); |
| 1203 | ret = AM65_CPSW_XDP_CONSUMED; | 1216 | ret = AM65_CPSW_XDP_CONSUMED; |
| 1204 | goto out; | 1217 | goto out; |
| 1205 | case XDP_REDIRECT: | 1218 | case XDP_REDIRECT: |
| 1206 | if (unlikely(xdp_do_redirect(ndev, xdp, prog))) | 1219 | if (unlikely(xdp_do_redirect(ndev, xdp, prog))) |
| 1207 | goto drop; | 1220 | goto drop; |
| 1208 | 1221 | ||
| 1209 | dev_sw_netstats_rx_add(ndev, *len); | 1222 | dev_sw_netstats_rx_add(ndev, pkt_len); |
| 1210 | ret = AM65_CPSW_XDP_REDIRECT; | 1223 | ret = AM65_CPSW_XDP_REDIRECT; |
| 1211 | goto out; | 1224 | goto out; |
| 1212 | default: | 1225 | default: |
| @@ -1315,16 +1328,8 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow, · 102 unmodified lines | |||
| 1315 | dev_dbg(dev, "%s rx csum_info:%#x\n", __func__, csum_info); | 1328 | dev_dbg(dev, "%s rx csum_info:%#x\n", __func__, csum_info); |
| 1316 | 1329 | ||
| 1317 | dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE); | 1330 | dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE); |
| 1318 | |||
| 1319 | k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); | 1331 | k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); |
| 1320 | 1332 | ||
| 1321 | skb = am65_cpsw_build_skb(page_addr, ndev, | ||
| 1322 | AM65_CPSW_MAX_PACKET_SIZE); | ||
| 1323 | if (unlikely(!skb)) { | ||
| 1324 | new_page = page; | ||
| 1325 | goto requeue; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | if (port->xdp_prog) { | 1333 | if (port->xdp_prog) { |
| 1329 | xdp_init_buff(&xdp, PAGE_SIZE, &port->xdp_rxq[flow->id]); | 1334 | xdp_init_buff(&xdp, PAGE_SIZE, &port->xdp_rxq[flow->id]); |
| 1330 | xdp_prepare_buff(&xdp, page_addr, AM65_CPSW_HEADROOM, | 1335 | xdp_prepare_buff(&xdp, page_addr, AM65_CPSW_HEADROOM, |
| @@ -1334,9 +1339,16 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow, · 3 unmodified lines | |||
| 1334 | if (*xdp_state != AM65_CPSW_XDP_PASS) | 1339 | if (*xdp_state != AM65_CPSW_XDP_PASS) |
| 1335 | goto allocate; | 1340 | goto allocate; |
| 1336 | 1341 | ||
| 1337 | /* Compute additional headroom to be reserved */ | 1342 | headroom = xdp.data - xdp.data_hard_start; |
| 1338 | headroom = (xdp.data - xdp.data_hard_start) - skb_headroom(skb); | 1343 | } else { |
| 1339 | skb_reserve(skb, headroom); | 1344 | headroom = AM65_CPSW_HEADROOM; |
| 1345 | } | ||
| 1346 | |||
| 1347 | skb = am65_cpsw_build_skb(page_addr, ndev, | ||
| 1348 | AM65_CPSW_MAX_PACKET_SIZE, headroom); | ||
| 1349 | if (unlikely(!skb)) { | ||
| 1350 | new_page = page; | ||
| 1351 | goto requeue; | ||
| 1340 | } | 1352 | } |
| 1341 | 1353 | ||
| 1342 | ndev_priv = netdev_priv(ndev); | 1354 | ndev_priv = netdev_priv(ndev); |
| @@ -2897,6 +2897,7 @@ static int axienet_probe(struct platform_device *pdev) · 2896 unmodified lines | |||
| 2897 | 2897 | ||
| 2898 | lp->phylink_config.dev = &ndev->dev; | 2898 | lp->phylink_config.dev = &ndev->dev; |
| 2899 | lp->phylink_config.type = PHYLINK_NETDEV; | 2899 | lp->phylink_config.type = PHYLINK_NETDEV; |
| 2900 | lp->phylink_config.mac_managed_pm = true; | ||
| 2900 | lp->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | | 2901 | lp->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | |
| 2901 | MAC_10FD | MAC_100FD | MAC_1000FD; | 2902 | MAC_10FD | MAC_100FD | MAC_1000FD; |
| 2902 | 2903 | ||
| @@ -1902,21 +1902,9 @@ static void geneve_destroy_tunnels(struct net *net, struct list_head *head) · 1901 unmodified lines | |||
| 1902 | { | 1902 | { |
| 1903 | struct geneve_net *gn = net_generic(net, geneve_net_id); | 1903 | struct geneve_net *gn = net_generic(net, geneve_net_id); |
| 1904 | struct geneve_dev *geneve, *next; | 1904 | struct geneve_dev *geneve, *next; |
| 1905 | struct net_device *dev, *aux; | ||
| 1906 | 1905 | ||
| 1907 | /* gather any geneve devices that were moved into this ns */ | 1906 | list_for_each_entry_safe(geneve, next, &gn->geneve_list, next) |
| 1908 | for_each_netdev_safe(net, dev, aux) | 1907 | geneve_dellink(geneve->dev, head); |
| 1909 | if (dev->rtnl_link_ops == &geneve_link_ops) | ||
| 1910 | unregister_netdevice_queue(dev, head); | ||
| 1911 | |||
| 1912 | /* now gather any other geneve devices that were created in this ns */ | ||
| 1913 | list_for_each_entry_safe(geneve, next, &gn->geneve_list, next) { | ||
| 1914 | /* If geneve->dev is in the same netns, it was already added | ||
| 1915 | * to the list by the previous loop. | ||
| 1916 | */ | ||
| 1917 | if (!net_eq(dev_net(geneve->dev), net)) | ||
| 1918 | unregister_netdevice_queue(geneve->dev, head); | ||
| 1919 | } | ||
| 1920 | } | 1908 | } |
| 1921 | 1909 | ||
| 1922 | static void __net_exit geneve_exit_batch_rtnl(struct list_head *net_list, | 1910 | static void __net_exit geneve_exit_batch_rtnl(struct list_head *net_list, |
| @@ -2481,11 +2481,6 @@ static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list, · 2480 unmodified lines | |||
| 2481 | list_for_each_entry(net, net_list, exit_list) { | 2481 | list_for_each_entry(net, net_list, exit_list) { |
| 2482 | struct gtp_net *gn = net_generic(net, gtp_net_id); | 2482 | struct gtp_net *gn = net_generic(net, gtp_net_id); |
| 2483 | struct gtp_dev *gtp, *gtp_next; | 2483 | struct gtp_dev *gtp, *gtp_next; |
| 2484 | struct net_device *dev; | ||
| 2485 | |||
| 2486 | for_each_netdev(net, dev) | ||
| 2487 | if (dev->rtnl_link_ops == >p_link_ops) | ||
| 2488 | gtp_dellink(dev, dev_to_kill); | ||
| 2489 | 2484 | ||
| 2490 | list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list) | 2485 | list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list) |
| 2491 | gtp_dellink(gtp->dev, dev_to_kill); | 2486 | gtp_dellink(gtp->dev, dev_to_kill); |
| @@ -2265,12 +2265,15 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy, · 2264 unmodified lines | |||
| 2265 | /* Allow the MAC to stop its clock if the PHY has the capability */ | 2265 | /* Allow the MAC to stop its clock if the PHY has the capability */ |
| 2266 | pl->mac_tx_clk_stop = phy_eee_tx_clock_stop_capable(phy) > 0; | 2266 | pl->mac_tx_clk_stop = phy_eee_tx_clock_stop_capable(phy) > 0; |
| 2267 | 2267 | ||
| 2268 | /* Explicitly configure whether the PHY is allowed to stop it's | 2268 | if (pl->mac_supports_eee_ops) { |
| 2269 | * receive clock. | 2269 | /* Explicitly configure whether the PHY is allowed to stop it's |
| 2270 | */ | 2270 | * receive clock. |
| 2271 | ret = phy_eee_rx_clock_stop(phy, pl->config->eee_rx_clk_stop_enable); | 2271 | */ |
| 2272 | if (ret == -EOPNOTSUPP) | 2272 | ret = phy_eee_rx_clock_stop(phy, |
| 2273 | ret = 0; | 2273 | pl->config->eee_rx_clk_stop_enable); |
| 2274 | if (ret == -EOPNOTSUPP) | ||
| 2275 | ret = 0; | ||
| 2276 | } | ||
| 2274 | 2277 | ||
| 2275 | return ret; | 2278 | return ret; |
| 2276 | } | 2279 | } |
| @@ -1047,7 +1047,7 @@ static int pd692x0_pi_get_pw_limit(struct pse_controller_dev *pcdev, · 1046 unmodified lines | |||
| 1047 | if (ret < 0) | 1047 | if (ret < 0) |
| 1048 | return ret; | 1048 | return ret; |
| 1049 | 1049 | ||
| 1050 | return pd692x0_pi_get_pw_from_table(buf.data[2], buf.data[3]); | 1050 | return pd692x0_pi_get_pw_from_table(buf.data[0], buf.data[1]); |
| 1051 | } | 1051 | } |
| 1052 | 1052 | ||
| 1053 | static int pd692x0_pi_set_pw_limit(struct pse_controller_dev *pcdev, | 1053 | static int pd692x0_pi_set_pw_limit(struct pse_controller_dev *pcdev, |
| @@ -319,7 +319,7 @@ static int pse_pi_get_current_limit(struct regulator_dev *rdev) · 318 unmodified lines | |||
| 319 | goto out; | 319 | goto out; |
| 320 | mW = ret; | 320 | mW = ret; |
| 321 | 321 | ||
| 322 | ret = pse_pi_get_voltage(rdev); | 322 | ret = _pse_pi_get_voltage(rdev); |
| 323 | if (!ret) { | 323 | if (!ret) { |
| 324 | dev_err(pcdev->dev, "Voltage null\n"); | 324 | dev_err(pcdev->dev, "Voltage null\n"); |
| 325 | ret = -ERANGE; | 325 | ret = -ERANGE; |
| @@ -356,7 +356,7 @@ static int pse_pi_set_current_limit(struct regulator_dev *rdev, int min_uA, · 30 unmodified lines | |||
| 356 | 356 | ||
| 357 | id = rdev_get_id(rdev); | 357 | id = rdev_get_id(rdev); |
| 358 | mutex_lock(&pcdev->lock); | 358 | mutex_lock(&pcdev->lock); |
| 359 | ret = pse_pi_get_voltage(rdev); | 359 | ret = _pse_pi_get_voltage(rdev); |
| 360 | if (!ret) { | 360 | if (!ret) { |
| 361 | dev_err(pcdev->dev, "Voltage null\n"); | 361 | dev_err(pcdev->dev, "Voltage null\n"); |
| 362 | ret = -ERANGE; | 362 | ret = -ERANGE; |
| @@ -2639,7 +2639,9 @@ int team_nl_options_set_doit(struct sk_buff *skb, struct genl_info *info) · 2638 unmodified lines | |||
| 2639 | ctx.data.u32_val = nla_get_u32(attr_data); | 2639 | ctx.data.u32_val = nla_get_u32(attr_data); |
| 2640 | break; | 2640 | break; |
| 2641 | case TEAM_OPTION_TYPE_STRING: | 2641 | case TEAM_OPTION_TYPE_STRING: |
| 2642 | if (nla_len(attr_data) > TEAM_STRING_MAX_LEN) { | 2642 | if (nla_len(attr_data) > TEAM_STRING_MAX_LEN || |
| 2643 | !memchr(nla_data(attr_data), '\0', | ||
| 2644 | nla_len(attr_data))) { | ||
| 2643 | err = -EINVAL; | 2645 | err = -EINVAL; |
| 2644 | goto team_put; | 2646 | goto team_put; |
| 2645 | } | 2647 | } |
| @@ -574,18 +574,14 @@ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb, · 573 unmodified lines | |||
| 574 | return ret; | 574 | return ret; |
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | static inline bool tun_capable(struct tun_struct *tun) | 577 | static inline bool tun_not_capable(struct tun_struct *tun) |
| 578 | { | 578 | { |
| 579 | const struct cred *cred = current_cred(); | 579 | const struct cred *cred = current_cred(); |
| 580 | struct net *net = dev_net(tun->dev); | 580 | struct net *net = dev_net(tun->dev); |
| 581 | 581 | ||
| 582 | if (ns_capable(net->user_ns, CAP_NET_ADMIN)) | 582 | return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) || |
| 583 | return 1; | 583 | (gid_valid(tun->group) && !in_egroup_p(tun->group))) && |
| 584 | if (uid_valid(tun->owner) && uid_eq(cred->euid, tun->owner)) | 584 | !ns_capable(net->user_ns, CAP_NET_ADMIN); |
| 585 | return 1; | ||
| 586 | if (gid_valid(tun->group) && in_egroup_p(tun->group)) | ||
| 587 | return 1; | ||
| 588 | return 0; | ||
| 589 | } | 585 | } |
| 590 | 586 | ||
| 591 | static void tun_set_real_num_queues(struct tun_struct *tun) | 587 | static void tun_set_real_num_queues(struct tun_struct *tun) |
| @@ -2782,7 +2778,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) · 2190 unmodified lines | |||
| 2782 | !!(tun->flags & IFF_MULTI_QUEUE)) | 2778 | !!(tun->flags & IFF_MULTI_QUEUE)) |
| 2783 | return -EINVAL; | 2779 | return -EINVAL; |
| 2784 | 2780 | ||
| 2785 | if (!tun_capable(tun)) | 2781 | if (tun_not_capable(tun)) |
| 2786 | return -EPERM; | 2782 | return -EPERM; |
| 2787 | err = security_tun_dev_open(tun->security); | 2783 | err = security_tun_dev_open(tun->security); |
| 2788 | if (err < 0) | 2784 | if (err < 0) |
| @@ -28,7 +28,7 @@ vmxnet3_xdp_get_tq(struct vmxnet3_adapter *adapter) · 27 unmodified lines | |||
| 28 | if (likely(cpu < tq_number)) | 28 | if (likely(cpu < tq_number)) |
| 29 | tq = &adapter->tx_queue[cpu]; | 29 | tq = &adapter->tx_queue[cpu]; |
| 30 | else | 30 | else |
| 31 | tq = &adapter->tx_queue[reciprocal_scale(cpu, tq_number)]; | 31 | tq = &adapter->tx_queue[cpu % tq_number]; |
| 32 | 32 | ||
| 33 | return tq; | 33 | return tq; |
| 34 | } | 34 | } |
| @@ -124,6 +124,7 @@ vmxnet3_xdp_xmit_frame(struct vmxnet3_adapter *adapter, · 89 unmodified lines | |||
| 124 | u32 buf_size; | 124 | u32 buf_size; |
| 125 | u32 dw2; | 125 | u32 dw2; |
| 126 | 126 | ||
| 127 | spin_lock_irq(&tq->tx_lock); | ||
| 127 | dw2 = (tq->tx_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT; | 128 | dw2 = (tq->tx_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT; |
| 128 | dw2 |= xdpf->len; | 129 | dw2 |= xdpf->len; |
| 129 | ctx.sop_txd = tq->tx_ring.base + tq->tx_ring.next2fill; | 130 | ctx.sop_txd = tq->tx_ring.base + tq->tx_ring.next2fill; |
| @@ -134,6 +135,7 @@ vmxnet3_xdp_xmit_frame(struct vmxnet3_adapter *adapter, · 4 unmodified lines | |||
| 134 | 135 | ||
| 135 | if (vmxnet3_cmd_ring_desc_avail(&tq->tx_ring) == 0) { | 136 | if (vmxnet3_cmd_ring_desc_avail(&tq->tx_ring) == 0) { |
| 136 | tq->stats.tx_ring_full++; | 137 | tq->stats.tx_ring_full++; |
| 138 | spin_unlock_irq(&tq->tx_lock); | ||
| 137 | return -ENOSPC; | 139 | return -ENOSPC; |
| 138 | } | 140 | } |
| 139 | 141 | ||
| @@ -142,8 +144,10 @@ vmxnet3_xdp_xmit_frame(struct vmxnet3_adapter *adapter, · 2 unmodified lines | |||
| 142 | tbi->dma_addr = dma_map_single(&adapter->pdev->dev, | 144 | tbi->dma_addr = dma_map_single(&adapter->pdev->dev, |
| 143 | xdpf->data, buf_size, | 145 | xdpf->data, buf_size, |
| 144 | DMA_TO_DEVICE); | 146 | DMA_TO_DEVICE); |
| 145 | if (dma_mapping_error(&adapter->pdev->dev, tbi->dma_addr)) | 147 | if (dma_mapping_error(&adapter->pdev->dev, tbi->dma_addr)) { |
| 148 | spin_unlock_irq(&tq->tx_lock); | ||
| 146 | return -EFAULT; | 149 | return -EFAULT; |
| 150 | } | ||
| 147 | tbi->map_type |= VMXNET3_MAP_SINGLE; | 151 | tbi->map_type |= VMXNET3_MAP_SINGLE; |
| 148 | } else { /* XDP buffer from page pool */ | 152 | } else { /* XDP buffer from page pool */ |
| 149 | page = virt_to_page(xdpf->data); | 153 | page = virt_to_page(xdpf->data); |
| @@ -182,6 +186,7 @@ vmxnet3_xdp_xmit_frame(struct vmxnet3_adapter *adapter, · 32 unmodified lines | |||
| 182 | dma_wmb(); | 186 | dma_wmb(); |
| 183 | gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^ | 187 | gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^ |
| 184 | VMXNET3_TXD_GEN); | 188 | VMXNET3_TXD_GEN); |
| 189 | spin_unlock_irq(&tq->tx_lock); | ||
| 185 | 190 | ||
| 186 | /* No need to handle the case when tx_num_deferred doesn't reach | 191 | /* No need to handle the case when tx_num_deferred doesn't reach |
| 187 | * threshold. Backend driver at hypervisor side will poll and reset | 192 | * threshold. Backend driver at hypervisor side will poll and reset |
| @@ -225,6 +230,7 @@ vmxnet3_xdp_xmit(struct net_device *dev, · 37 unmodified lines | |||
| 225 | { | 230 | { |
| 226 | struct vmxnet3_adapter *adapter = netdev_priv(dev); | 231 | struct vmxnet3_adapter *adapter = netdev_priv(dev); |
| 227 | struct vmxnet3_tx_queue *tq; | 232 | struct vmxnet3_tx_queue *tq; |
| 233 | struct netdev_queue *nq; | ||
| 228 | int i; | 234 | int i; |
| 229 | 235 | ||
| 230 | if (unlikely(test_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state))) | 236 | if (unlikely(test_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state))) |
| @@ -236,6 +242,9 @@ vmxnet3_xdp_xmit(struct net_device *dev, · 5 unmodified lines | |||
| 236 | if (tq->stopped) | 242 | if (tq->stopped) |
| 237 | return -ENETDOWN; | 243 | return -ENETDOWN; |
| 238 | 244 | ||
| 245 | nq = netdev_get_tx_queue(adapter->netdev, tq->qid); | ||
| 246 | |||
| 247 | __netif_tx_lock(nq, smp_processor_id()); | ||
| 239 | for (i = 0; i < n; i++) { | 248 | for (i = 0; i < n; i++) { |
| 240 | if (vmxnet3_xdp_xmit_frame(adapter, frames[i], tq, true)) { | 249 | if (vmxnet3_xdp_xmit_frame(adapter, frames[i], tq, true)) { |
| 241 | tq->stats.xdp_xmit_err++; | 250 | tq->stats.xdp_xmit_err++; |
| @@ -243,6 +252,7 @@ vmxnet3_xdp_xmit(struct net_device *dev, · 1 unmodified line | |||
| 243 | } | 252 | } |
| 244 | } | 253 | } |
| 245 | tq->stats.xdp_xmit += i; | 254 | tq->stats.xdp_xmit += i; |
| 255 | __netif_tx_unlock(nq); | ||
| 246 | 256 | ||
| 247 | return i; | 257 | return i; |
| 248 | } | 258 | } |
| @@ -2898,8 +2898,11 @@ static int vxlan_init(struct net_device *dev) · 2897 unmodified lines | |||
| 2898 | struct vxlan_dev *vxlan = netdev_priv(dev); | 2898 | struct vxlan_dev *vxlan = netdev_priv(dev); |
| 2899 | int err; | 2899 | int err; |
| 2900 | 2900 | ||
| 2901 | if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) | 2901 | if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) { |
| 2902 | vxlan_vnigroup_init(vxlan); | 2902 | err = vxlan_vnigroup_init(vxlan); |
| 2903 | if (err) | ||
| 2904 | return err; | ||
| 2905 | } | ||
| 2903 | 2906 | ||
| 2904 | err = gro_cells_init(&vxlan->gro_cells, dev); | 2907 | err = gro_cells_init(&vxlan->gro_cells, dev); |
| 2905 | if (err) | 2908 | if (err) |
| @@ -4851,6 +4851,22 @@ static struct ath12k_reg_rule · 4850 unmodified lines | |||
| 4851 | return reg_rule_ptr; | 4851 | return reg_rule_ptr; |
| 4852 | } | 4852 | } |
| 4853 | 4853 | ||
| 4854 | static u8 ath12k_wmi_ignore_num_extra_rules(struct ath12k_wmi_reg_rule_ext_params *rule, | ||
| 4855 | u32 num_reg_rules) | ||
| 4856 | { | ||
| 4857 | u8 num_invalid_5ghz_rules = 0; | ||
| 4858 | u32 count, start_freq; | ||
| 4859 | |||
| 4860 | for (count = 0; count < num_reg_rules; count++) { | ||
| 4861 | start_freq = le32_get_bits(rule[count].freq_info, REG_RULE_START_FREQ); | ||
| 4862 | |||
| 4863 | if (start_freq >= ATH12K_MIN_6G_FREQ) | ||
| 4864 | num_invalid_5ghz_rules++; | ||
| 4865 | } | ||
| 4866 | |||
| 4867 | return num_invalid_5ghz_rules; | ||
| 4868 | } | ||
| 4869 | |||
| 4854 | static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, | 4870 | static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, |
| 4855 | struct sk_buff *skb, | 4871 | struct sk_buff *skb, |
| 4856 | struct ath12k_reg_info *reg_info) | 4872 | struct ath12k_reg_info *reg_info) |
| @@ -4861,6 +4877,7 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, · 4 unmodified lines | |||
| 4861 | u32 num_2g_reg_rules, num_5g_reg_rules; | 4877 | u32 num_2g_reg_rules, num_5g_reg_rules; |
| 4862 | u32 num_6g_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; | 4878 | u32 num_6g_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; |
| 4863 | u32 num_6g_reg_rules_cl[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; | 4879 | u32 num_6g_reg_rules_cl[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; |
| 4880 | u8 num_invalid_5ghz_ext_rules; | ||
| 4864 | u32 total_reg_rules = 0; | 4881 | u32 total_reg_rules = 0; |
| 4865 | int ret, i, j; | 4882 | int ret, i, j; |
| 4866 | 4883 | ||
| @@ -4954,20 +4971,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, · 87 unmodified lines | |||
| 4954 | 4971 | ||
| 4955 | memcpy(reg_info->alpha2, &ev->alpha2, REG_ALPHA2_LEN); | 4972 | memcpy(reg_info->alpha2, &ev->alpha2, REG_ALPHA2_LEN); |
| 4956 | 4973 | ||
| 4957 | /* FIXME: Currently FW includes 6G reg rule also in 5G rule | ||
| 4958 | * list for country US. | ||
| 4959 | * Having same 6G reg rule in 5G and 6G rules list causes | ||
| 4960 | * intersect check to be true, and same rules will be shown | ||
| 4961 | * multiple times in iw cmd. So added hack below to avoid | ||
| 4962 | * parsing 6G rule from 5G reg rule list, and this can be | ||
| 4963 | * removed later, after FW updates to remove 6G reg rule | ||
| 4964 | * from 5G rules list. | ||
| 4965 | */ | ||
| 4966 | if (memcmp(reg_info->alpha2, "US", 2) == 0) { | ||
| 4967 | reg_info->num_5g_reg_rules = REG_US_5G_NUM_REG_RULES; | ||
| 4968 | num_5g_reg_rules = reg_info->num_5g_reg_rules; | ||
| 4969 | } | ||
| 4970 | |||
| 4971 | reg_info->dfs_region = le32_to_cpu(ev->dfs_region); | 4974 | reg_info->dfs_region = le32_to_cpu(ev->dfs_region); |
| 4972 | reg_info->phybitmap = le32_to_cpu(ev->phybitmap); | 4975 | reg_info->phybitmap = le32_to_cpu(ev->phybitmap); |
| 4973 | reg_info->num_phy = le32_to_cpu(ev->num_phy); | 4976 | reg_info->num_phy = le32_to_cpu(ev->num_phy); |
| @@ -5070,8 +5073,29 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, · 96 unmodified lines | |||
| 5070 | } | 5073 | } |
| 5071 | } | 5074 | } |
| 5072 | 5075 | ||
| 5076 | ext_wmi_reg_rule += num_2g_reg_rules; | ||
| 5077 | |||
| 5078 | /* Firmware might include 6 GHz reg rule in 5 GHz rule list | ||
| 5079 | * for few countries along with separate 6 GHz rule. | ||
| 5080 | * Having same 6 GHz reg rule in 5 GHz and 6 GHz rules list | ||
| 5081 | * causes intersect check to be true, and same rules will be | ||
| 5082 | * shown multiple times in iw cmd. | ||
| 5083 | * Hence, avoid parsing 6 GHz rule from 5 GHz reg rule list | ||
| 5084 | */ | ||
| 5085 | num_invalid_5ghz_ext_rules = ath12k_wmi_ignore_num_extra_rules(ext_wmi_reg_rule, | ||
| 5086 | num_5g_reg_rules); | ||
| 5087 | |||
| 5088 | if (num_invalid_5ghz_ext_rules) { | ||
| 5089 | ath12k_dbg(ab, ATH12K_DBG_WMI, | ||
| 5090 | "CC: %s 5 GHz reg rules number %d from fw, %d number of invalid 5 GHz rules", | ||
| 5091 | reg_info->alpha2, reg_info->num_5g_reg_rules, | ||
| 5092 | num_invalid_5ghz_ext_rules); | ||
| 5093 | |||
| 5094 | num_5g_reg_rules = num_5g_reg_rules - num_invalid_5ghz_ext_rules; | ||
| 5095 | reg_info->num_5g_reg_rules = num_5g_reg_rules; | ||
| 5096 | } | ||
| 5097 | |||
| 5073 | if (num_5g_reg_rules) { | 5098 | if (num_5g_reg_rules) { |
| 5074 | ext_wmi_reg_rule += num_2g_reg_rules; | ||
| 5075 | reg_info->reg_rules_5g_ptr = | 5099 | reg_info->reg_rules_5g_ptr = |
| 5076 | create_ext_reg_rules_from_wmi(num_5g_reg_rules, | 5100 | create_ext_reg_rules_from_wmi(num_5g_reg_rules, |
| 5077 | ext_wmi_reg_rule); | 5101 | ext_wmi_reg_rule); |
| @@ -5083,7 +5107,12 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, · 5 unmodified lines | |||
| 5083 | } | 5107 | } |
| 5084 | } | 5108 | } |
| 5085 | 5109 | ||
| 5086 | ext_wmi_reg_rule += num_5g_reg_rules; | 5110 | /* We have adjusted the number of 5 GHz reg rules above. But still those |
| 5111 | * many rules needs to be adjusted in ext_wmi_reg_rule. | ||
| 5112 | * | ||
| 5113 | * NOTE: num_invalid_5ghz_ext_rules will be 0 for rest other cases. | ||
| 5114 | */ | ||
| 5115 | ext_wmi_reg_rule += (num_5g_reg_rules + num_invalid_5ghz_ext_rules); | ||
| 5087 | 5116 | ||
| 5088 | for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) { | 5117 | for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) { |
| 5089 | reg_info->reg_rules_6g_ap_ptr[i] = | 5118 | reg_info->reg_rules_6g_ap_ptr[i] = |
| @@ -4073,7 +4073,6 @@ struct ath12k_wmi_eht_rate_set_params { · 4072 unmodified lines | |||
| 4073 | #define MAX_REG_RULES 10 | 4073 | #define MAX_REG_RULES 10 |
| 4074 | #define REG_ALPHA2_LEN 2 | 4074 | #define REG_ALPHA2_LEN 2 |
| 4075 | #define MAX_6G_REG_RULES 5 | 4075 | #define MAX_6G_REG_RULES 5 |
| 4076 | #define REG_US_5G_NUM_REG_RULES 4 | ||
| 4077 | 4076 | ||
| 4078 | enum wmi_start_event_param { | 4077 | enum wmi_start_event_param { |
| 4079 | WMI_VDEV_START_RESP_EVENT = 0, | 4078 | WMI_VDEV_START_RESP_EVENT = 0, |
| @@ -2712,7 +2712,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { · 2711 unmodified lines | |||
| 2712 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID, WCC), | 2712 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID, WCC), |
| 2713 | BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355, WCC), | 2713 | BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355, WCC), |
| 2714 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_RAW_DEVICE_ID, WCC), | 2714 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_RAW_DEVICE_ID, WCC), |
| 2715 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4355_DEVICE_ID, WCC), | 2715 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4355_DEVICE_ID, WCC_SEED), |
| 2716 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID, WCC), | 2716 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID, WCC), |
| 2717 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID, WCC), | 2717 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID, WCC), |
| 2718 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID, WCC), | 2718 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID, WCC), |
| @@ -2723,7 +2723,7 @@ static const struct pci_device_id brcmf_pcie_devid_table[] = { · 4 unmodified lines | |||
| 2723 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID, WCC), | 2723 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID, WCC), |
| 2724 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID, WCC), | 2724 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID, WCC), |
| 2725 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID, WCC), | 2725 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID, WCC), |
| 2726 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID, WCC), | 2726 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4364_DEVICE_ID, WCC_SEED), |
| 2727 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID, BCA), | 2727 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID, BCA), |
| 2728 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID, BCA), | 2728 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID, BCA), |
| 2729 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID, BCA), | 2729 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID, BCA), |
| @@ -220,7 +220,7 @@ static int mbim_rx_verify_nth16(struct mhi_mbim_context *mbim, struct sk_buff *s · 219 unmodified lines | |||
| 220 | if (mbim->rx_seq + 1 != le16_to_cpu(nth16->wSequence) && | 220 | if (mbim->rx_seq + 1 != le16_to_cpu(nth16->wSequence) && |
| 221 | (mbim->rx_seq || le16_to_cpu(nth16->wSequence)) && | 221 | (mbim->rx_seq || le16_to_cpu(nth16->wSequence)) && |
| 222 | !(mbim->rx_seq == 0xffff && !le16_to_cpu(nth16->wSequence))) { | 222 | !(mbim->rx_seq == 0xffff && !le16_to_cpu(nth16->wSequence))) { |
| 223 | net_err_ratelimited("sequence number glitch prev=%d curr=%d\n", | 223 | net_dbg_ratelimited("sequence number glitch prev=%d curr=%d\n", |
| 224 | mbim->rx_seq, le16_to_cpu(nth16->wSequence)); | 224 | mbim->rx_seq, le16_to_cpu(nth16->wSequence)); |
| 225 | } | 225 | } |
| 226 | mbim->rx_seq = le16_to_cpu(nth16->wSequence); | 226 | mbim->rx_seq = le16_to_cpu(nth16->wSequence); |
| @@ -1700,7 +1700,13 @@ int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count) · 1699 unmodified lines | |||
| 1700 | 1700 | ||
| 1701 | status = nvme_set_features(ctrl, NVME_FEAT_NUM_QUEUES, q_count, NULL, 0, | 1701 | status = nvme_set_features(ctrl, NVME_FEAT_NUM_QUEUES, q_count, NULL, 0, |
| 1702 | &result); | 1702 | &result); |
| 1703 | if (status < 0) | 1703 | |
| 1704 | /* | ||
| 1705 | * It's either a kernel error or the host observed a connection | ||
| 1706 | * lost. In either case it's not possible communicate with the | ||
| 1707 | * controller and thus enter the error code path. | ||
| 1708 | */ | ||
| 1709 | if (status < 0 || status == NVME_SC_HOST_PATH_ERROR) | ||
| 1704 | return status; | 1710 | return status; |
| 1705 | 1711 | ||
| 1706 | /* | 1712 | /* |
| @@ -781,11 +781,19 @@ restart: · 780 unmodified lines | |||
| 781 | static void | 781 | static void |
| 782 | nvme_fc_ctrl_connectivity_loss(struct nvme_fc_ctrl *ctrl) | 782 | nvme_fc_ctrl_connectivity_loss(struct nvme_fc_ctrl *ctrl) |
| 783 | { | 783 | { |
| 784 | enum nvme_ctrl_state state; | ||
| 785 | unsigned long flags; | ||
| 786 | |||
| 784 | dev_info(ctrl->ctrl.device, | 787 | dev_info(ctrl->ctrl.device, |
| 785 | "NVME-FC{%d}: controller connectivity lost. Awaiting " | 788 | "NVME-FC{%d}: controller connectivity lost. Awaiting " |
| 786 | "Reconnect", ctrl->cnum); | 789 | "Reconnect", ctrl->cnum); |
| 787 | 790 | ||
| 788 | switch (nvme_ctrl_state(&ctrl->ctrl)) { | 791 | spin_lock_irqsave(&ctrl->lock, flags); |
| 792 | set_bit(ASSOC_FAILED, &ctrl->flags); | ||
| 793 | state = nvme_ctrl_state(&ctrl->ctrl); | ||
| 794 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
| 795 | |||
| 796 | switch (state) { | ||
| 789 | case NVME_CTRL_NEW: | 797 | case NVME_CTRL_NEW: |
| 790 | case NVME_CTRL_LIVE: | 798 | case NVME_CTRL_LIVE: |
| 791 | /* | 799 | /* |
| @@ -2079,7 +2087,8 @@ done: · 1287 unmodified lines | |||
| 2079 | nvme_fc_complete_rq(rq); | 2087 | nvme_fc_complete_rq(rq); |
| 2080 | 2088 | ||
| 2081 | check_error: | 2089 | check_error: |
| 2082 | if (terminate_assoc && ctrl->ctrl.state != NVME_CTRL_RESETTING) | 2090 | if (terminate_assoc && |
| 2091 | nvme_ctrl_state(&ctrl->ctrl) != NVME_CTRL_RESETTING) | ||
| 2083 | queue_work(nvme_reset_wq, &ctrl->ioerr_work); | 2092 | queue_work(nvme_reset_wq, &ctrl->ioerr_work); |
| 2084 | } | 2093 | } |
| 2085 | 2094 | ||
| @@ -2533,6 +2542,8 @@ __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues) · 447 unmodified lines | |||
| 2533 | static void | 2542 | static void |
| 2534 | nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg) | 2543 | nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg) |
| 2535 | { | 2544 | { |
| 2545 | enum nvme_ctrl_state state = nvme_ctrl_state(&ctrl->ctrl); | ||
| 2546 | |||
| 2536 | /* | 2547 | /* |
| 2537 | * if an error (io timeout, etc) while (re)connecting, the remote | 2548 | * if an error (io timeout, etc) while (re)connecting, the remote |
| 2538 | * port requested terminating of the association (disconnect_ls) | 2549 | * port requested terminating of the association (disconnect_ls) |
| @@ -2540,9 +2551,8 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg) · 1 unmodified line | |||
| 2540 | * the controller. Abort any ios on the association and let the | 2551 | * the controller. Abort any ios on the association and let the |
| 2541 | * create_association error path resolve things. | 2552 | * create_association error path resolve things. |
| 2542 | */ | 2553 | */ |
| 2543 | if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) { | 2554 | if (state == NVME_CTRL_CONNECTING) { |
| 2544 | __nvme_fc_abort_outstanding_ios(ctrl, true); | 2555 | __nvme_fc_abort_outstanding_ios(ctrl, true); |
| 2545 | set_bit(ASSOC_FAILED, &ctrl->flags); | ||
| 2546 | dev_warn(ctrl->ctrl.device, | 2556 | dev_warn(ctrl->ctrl.device, |
| 2547 | "NVME-FC{%d}: transport error during (re)connect\n", | 2557 | "NVME-FC{%d}: transport error during (re)connect\n", |
| 2548 | ctrl->cnum); | 2558 | ctrl->cnum); |
| @@ -2550,7 +2560,7 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg) · 1 unmodified line | |||
| 2550 | } | 2560 | } |
| 2551 | 2561 | ||
| 2552 | /* Otherwise, only proceed if in LIVE state - e.g. on first error */ | 2562 | /* Otherwise, only proceed if in LIVE state - e.g. on first error */ |
| 2553 | if (ctrl->ctrl.state != NVME_CTRL_LIVE) | 2563 | if (state != NVME_CTRL_LIVE) |
| 2554 | return; | 2564 | return; |
| 2555 | 2565 | ||
| 2556 | dev_warn(ctrl->ctrl.device, | 2566 | dev_warn(ctrl->ctrl.device, |
| @@ -3167,12 +3177,18 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) · 610 unmodified lines | |||
| 3167 | else | 3177 | else |
| 3168 | ret = nvme_fc_recreate_io_queues(ctrl); | 3178 | ret = nvme_fc_recreate_io_queues(ctrl); |
| 3169 | } | 3179 | } |
| 3170 | if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags)) | ||
| 3171 | ret = -EIO; | ||
| 3172 | if (ret) | 3180 | if (ret) |
| 3173 | goto out_term_aen_ops; | 3181 | goto out_term_aen_ops; |
| 3174 | 3182 | ||
| 3175 | changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); | 3183 | spin_lock_irqsave(&ctrl->lock, flags); |
| 3184 | if (!test_bit(ASSOC_FAILED, &ctrl->flags)) | ||
| 3185 | changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); | ||
| 3186 | else | ||
| 3187 | ret = -EIO; | ||
| 3188 | spin_unlock_irqrestore(&ctrl->lock, flags); | ||
| 3189 | |||
| 3190 | if (ret) | ||
| 3191 | goto out_term_aen_ops; | ||
| 3176 | 3192 | ||
| 3177 | ctrl->ctrl.nr_reconnects = 0; | 3193 | ctrl->ctrl.nr_reconnects = 0; |
| 3178 | 3194 | ||
| @@ -3578,8 +3594,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, · 399 unmodified lines | |||
| 3578 | list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list); | 3594 | list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list); |
| 3579 | spin_unlock_irqrestore(&rport->lock, flags); | 3595 | spin_unlock_irqrestore(&rport->lock, flags); |
| 3580 | 3596 | ||
| 3581 | if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING) || | 3597 | if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) { |
| 3582 | !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) { | ||
| 3583 | dev_err(ctrl->ctrl.device, | 3598 | dev_err(ctrl->ctrl.device, |
| 3584 | "NVME-FC{%d}: failed to init ctrl state\n", ctrl->cnum); | 3599 | "NVME-FC{%d}: failed to init ctrl state\n", ctrl->cnum); |
| 3585 | goto fail_ctrl; | 3600 | goto fail_ctrl; |
| @@ -2153,14 +2153,6 @@ static int nvme_alloc_host_mem_multi(struct nvme_dev *dev, u64 preferred, · 2152 unmodified lines | |||
| 2153 | return 0; | 2153 | return 0; |
| 2154 | 2154 | ||
| 2155 | out_free_bufs: | 2155 | out_free_bufs: |
| 2156 | while (--i >= 0) { | ||
| 2157 | size_t size = le32_to_cpu(descs[i].size) * NVME_CTRL_PAGE_SIZE; | ||
| 2158 | |||
| 2159 | dma_free_attrs(dev->dev, size, bufs[i], | ||
| 2160 | le64_to_cpu(descs[i].addr), | ||
| 2161 | DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN); | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | kfree(bufs); | 2156 | kfree(bufs); |
| 2165 | out_free_descs: | 2157 | out_free_descs: |
| 2166 | dma_free_coherent(dev->dev, descs_size, descs, descs_dma); | 2158 | dma_free_coherent(dev->dev, descs_size, descs, descs_dma); |
| @@ -3147,7 +3139,9 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev) · 980 unmodified lines | |||
| 3147 | * because of high power consumption (> 2 Watt) in s2idle | 3139 | * because of high power consumption (> 2 Watt) in s2idle |
| 3148 | * sleep. Only some boards with Intel CPU are affected. | 3140 | * sleep. Only some boards with Intel CPU are affected. |
| 3149 | */ | 3141 | */ |
| 3150 | if (dmi_match(DMI_BOARD_NAME, "GMxPXxx") || | 3142 | if (dmi_match(DMI_BOARD_NAME, "DN50Z-140HC-YD") || |
| 3143 | dmi_match(DMI_BOARD_NAME, "GMxPXxx") || | ||
| 3144 | dmi_match(DMI_BOARD_NAME, "GXxMRXx") || | ||
| 3151 | dmi_match(DMI_BOARD_NAME, "PH4PG31") || | 3145 | dmi_match(DMI_BOARD_NAME, "PH4PG31") || |
| 3152 | dmi_match(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1") || | 3146 | dmi_match(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1") || |
| 3153 | dmi_match(DMI_BOARD_NAME, "PH6PG01_PH6PG71")) | 3147 | dmi_match(DMI_BOARD_NAME, "PH6PG01_PH6PG71")) |
| @@ -792,7 +792,7 @@ static umode_t nvme_tls_attrs_are_visible(struct kobject *kobj, · 791 unmodified lines | |||
| 792 | return a->mode; | 792 | return a->mode; |
| 793 | } | 793 | } |
| 794 | 794 | ||
| 795 | const struct attribute_group nvme_tls_attrs_group = { | 795 | static const struct attribute_group nvme_tls_attrs_group = { |
| 796 | .attrs = nvme_tls_attrs, | 796 | .attrs = nvme_tls_attrs, |
| 797 | .is_visible = nvme_tls_attrs_are_visible, | 797 | .is_visible = nvme_tls_attrs_are_visible, |
| 798 | }; | 798 | }; |
| @@ -1068,6 +1068,7 @@ static void nvme_execute_identify_ns_nvm(struct nvmet_req *req) · 1067 unmodified lines | |||
| 1068 | goto out; | 1068 | goto out; |
| 1069 | } | 1069 | } |
| 1070 | status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id)); | 1070 | status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id)); |
| 1071 | kfree(id); | ||
| 1071 | out: | 1072 | out: |
| 1072 | nvmet_req_complete(req, status); | 1073 | nvmet_req_complete(req, status); |
| 1073 | } | 1074 | } |
| @@ -287,7 +287,7 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req) · 286 unmodified lines | |||
| 287 | args.subsysnqn = d->subsysnqn; | 287 | args.subsysnqn = d->subsysnqn; |
| 288 | args.hostnqn = d->hostnqn; | 288 | args.hostnqn = d->hostnqn; |
| 289 | args.hostid = &d->hostid; | 289 | args.hostid = &d->hostid; |
| 290 | args.kato = c->kato; | 290 | args.kato = le32_to_cpu(c->kato); |
| 291 | 291 | ||
| 292 | ctrl = nvmet_alloc_ctrl(&args); | 292 | ctrl = nvmet_alloc_ctrl(&args); |
| 293 | if (!ctrl) | 293 | if (!ctrl) |
| @@ -272,7 +272,7 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req) · 271 unmodified lines | |||
| 272 | iter_flags = SG_MITER_FROM_SG; | 272 | iter_flags = SG_MITER_FROM_SG; |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | if (req->cmd->rw.control & NVME_RW_LR) | 275 | if (req->cmd->rw.control & cpu_to_le16(NVME_RW_LR)) |
| 276 | opf |= REQ_FAILFAST_DEV; | 276 | opf |= REQ_FAILFAST_DEV; |
| 277 | 277 | ||
| 278 | if (is_pci_p2pdma_page(sg_page(req->sg))) | 278 | if (is_pci_p2pdma_page(sg_page(req->sg))) |
| @@ -589,7 +589,7 @@ struct nvmet_alloc_ctrl_args { · 588 unmodified lines | |||
| 589 | const struct nvmet_fabrics_ops *ops; | 589 | const struct nvmet_fabrics_ops *ops; |
| 590 | struct device *p2p_client; | 590 | struct device *p2p_client; |
| 591 | u32 kato; | 591 | u32 kato; |
| 592 | u32 result; | 592 | __le32 result; |
| 593 | u16 error_loc; | 593 | u16 error_loc; |
| 594 | u16 status; | 594 | u16 status; |
| 595 | }; | 595 | }; |
| @@ -16,6 +16,8 @@ · 15 unmodified lines | |||
| 16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
| 17 | #include <linux/dma-direct.h> /* for bus_dma_region */ | 17 | #include <linux/dma-direct.h> /* for bus_dma_region */ |
| 18 | 18 | ||
| 19 | #include <kunit/visibility.h> | ||
| 20 | |||
| 19 | /* Uncomment me to enable of_dump_addr() debugging output */ | 21 | /* Uncomment me to enable of_dump_addr() debugging output */ |
| 20 | // #define DEBUG | 22 | // #define DEBUG |
| 21 | 23 | ||
| @@ -183,7 +185,7 @@ static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, · 161 unmodified lines | |||
| 183 | 185 | ||
| 184 | #endif /* CONFIG_PCI */ | 186 | #endif /* CONFIG_PCI */ |
| 185 | 187 | ||
| 186 | static int __of_address_resource_bounds(struct resource *r, u64 start, u64 size) | 188 | VISIBLE_IF_KUNIT int __of_address_resource_bounds(struct resource *r, u64 start, u64 size) |
| 187 | { | 189 | { |
| 188 | if (overflows_type(start, r->start)) | 190 | if (overflows_type(start, r->start)) |
| 189 | return -EOVERFLOW; | 191 | return -EOVERFLOW; |
| @@ -197,6 +199,7 @@ static int __of_address_resource_bounds(struct resource *r, u64 start, u64 size) · 7 unmodified lines | |||
| 197 | 199 | ||
| 198 | return 0; | 200 | return 0; |
| 199 | } | 201 | } |
| 202 | EXPORT_SYMBOL_IF_KUNIT(__of_address_resource_bounds); | ||
| 200 | 203 | ||
| 201 | /* | 204 | /* |
| 202 | * of_pci_range_to_resource - Create a resource from an of_pci_range | 205 | * of_pci_range_to_resource - Create a resource from an of_pci_range |
| @@ -208,4 +208,8 @@ static void __maybe_unused of_dump_addr(const char *s, const __be32 *addr, int n · 207 unmodified lines | |||
| 208 | static void __maybe_unused of_dump_addr(const char *s, const __be32 *addr, int na) { } | 208 | static void __maybe_unused of_dump_addr(const char *s, const __be32 *addr, int na) { } |
| 209 | #endif | 209 | #endif |
| 210 | 210 | ||
| 211 | #if IS_ENABLED(CONFIG_KUNIT) | ||
| 212 | int __of_address_resource_bounds(struct resource *r, u64 start, u64 size); | ||
| 213 | #endif | ||
| 214 | |||
| 211 | #endif /* _LINUX_OF_PRIVATE_H */ | 215 | #endif /* _LINUX_OF_PRIVATE_H */ |
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | /* | 2 | /* |
| 3 | * KUnit tests for OF APIs | 3 | * KUnit tests for OF APIs |
| 4 | */ | 4 | */ |
| 5 | #include <linux/ioport.h> | ||
| 5 | #include <linux/module.h> | 6 | #include <linux/module.h> |
| 6 | #include <linux/of.h> | 7 | #include <linux/of.h> |
| 7 | 8 | ||
| @@ -54,8 +55,124 @@ static struct kunit_suite of_dtb_suite = { · 46 unmodified lines | |||
| 54 | .init = of_dtb_test_init, | 55 | .init = of_dtb_test_init, |
| 55 | }; | 56 | }; |
| 56 | 57 | ||
| 58 | struct of_address_resource_bounds_case { | ||
| 59 | u64 start; | ||
| 60 | u64 size; | ||
| 61 | int ret; | ||
| 62 | |||
| 63 | u64 res_start; | ||
| 64 | u64 res_end; | ||
| 65 | }; | ||
| 66 | |||
| 67 | static void of_address_resource_bounds_case_desc(const struct of_address_resource_bounds_case *p, | ||
| 68 | char *name) | ||
| 69 | { | ||
| 70 | snprintf(name, KUNIT_PARAM_DESC_SIZE, "start=0x%016llx,size=0x%016llx", p->start, p->size); | ||
| 71 | } | ||
| 72 | |||
| 73 | static const struct of_address_resource_bounds_case of_address_resource_bounds_cases[] = { | ||
| 74 | { | ||
| 75 | .start = 0, | ||
| 76 | .size = 0, | ||
| 77 | .ret = 0, | ||
| 78 | .res_start = 0, | ||
| 79 | .res_end = -1, | ||
| 80 | }, | ||
| 81 | { | ||
| 82 | .start = 0, | ||
| 83 | .size = 0x1000, | ||
| 84 | .ret = 0, | ||
| 85 | .res_start = 0, | ||
| 86 | .res_end = 0xfff, | ||
| 87 | }, | ||
| 88 | { | ||
| 89 | .start = 0x1000, | ||
| 90 | .size = 0, | ||
| 91 | .ret = 0, | ||
| 92 | .res_start = 0x1000, | ||
| 93 | .res_end = 0xfff, | ||
| 94 | }, | ||
| 95 | { | ||
| 96 | .start = 0x1000, | ||
| 97 | .size = 0x1000, | ||
| 98 | .ret = 0, | ||
| 99 | .res_start = 0x1000, | ||
| 100 | .res_end = 0x1fff, | ||
| 101 | }, | ||
| 102 | { | ||
| 103 | .start = 1, | ||
| 104 | .size = RESOURCE_SIZE_MAX, | ||
| 105 | .ret = 0, | ||
| 106 | .res_start = 1, | ||
| 107 | .res_end = RESOURCE_SIZE_MAX, | ||
| 108 | }, | ||
| 109 | { | ||
| 110 | .start = RESOURCE_SIZE_MAX, | ||
| 111 | .size = 1, | ||
| 112 | .ret = 0, | ||
| 113 | .res_start = RESOURCE_SIZE_MAX, | ||
| 114 | .res_end = RESOURCE_SIZE_MAX, | ||
| 115 | }, | ||
| 116 | { | ||
| 117 | .start = 2, | ||
| 118 | .size = RESOURCE_SIZE_MAX, | ||
| 119 | .ret = -EOVERFLOW, | ||
| 120 | }, | ||
| 121 | { | ||
| 122 | .start = RESOURCE_SIZE_MAX, | ||
| 123 | .size = 2, | ||
| 124 | .ret = -EOVERFLOW, | ||
| 125 | }, | ||
| 126 | { | ||
| 127 | .start = ULL(0x100000000), | ||
| 128 | .size = 1, | ||
| 129 | .ret = sizeof(resource_size_t) > sizeof(u32) ? 0 : -EOVERFLOW, | ||
| 130 | .res_start = ULL(0x100000000), | ||
| 131 | .res_end = ULL(0x100000000), | ||
| 132 | }, | ||
| 133 | { | ||
| 134 | .start = 0x1000, | ||
| 135 | .size = 0xffffffff, | ||
| 136 | .ret = sizeof(resource_size_t) > sizeof(u32) ? 0 : -EOVERFLOW, | ||
| 137 | .res_start = 0x1000, | ||
| 138 | .res_end = ULL(0x100000ffe), | ||
| 139 | }, | ||
| 140 | }; | ||
| 141 | |||
| 142 | KUNIT_ARRAY_PARAM(of_address_resource_bounds, | ||
| 143 | of_address_resource_bounds_cases, of_address_resource_bounds_case_desc); | ||
| 144 | |||
| 145 | static void of_address_resource_bounds(struct kunit *test) | ||
| 146 | { | ||
| 147 | const struct of_address_resource_bounds_case *param = test->param_value; | ||
| 148 | struct resource r; /* Intentionally uninitialized */ | ||
| 149 | int ret; | ||
| 150 | |||
| 151 | if (!IS_ENABLED(CONFIG_OF_ADDRESS)) | ||
| 152 | kunit_skip(test, "CONFIG_OF_ADDRESS not enabled\n"); | ||
| 153 | |||
| 154 | ret = __of_address_resource_bounds(&r, param->start, param->size); | ||
| 155 | KUNIT_EXPECT_EQ(test, param->ret, ret); | ||
| 156 | if (ret == 0) { | ||
| 157 | KUNIT_EXPECT_EQ(test, (resource_size_t)param->res_start, r.start); | ||
| 158 | KUNIT_EXPECT_EQ(test, (resource_size_t)param->res_end, r.end); | ||
| 159 | KUNIT_EXPECT_EQ(test, param->size, resource_size(&r)); | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | static struct kunit_case of_address_test_cases[] = { | ||
| 164 | KUNIT_CASE_PARAM(of_address_resource_bounds, of_address_resource_bounds_gen_params), | ||
| 165 | {} | ||
| 166 | }; | ||
| 167 | |||
| 168 | static struct kunit_suite of_address_suite = { | ||
| 169 | .name = "of_address", | ||
| 170 | .test_cases = of_address_test_cases, | ||
| 171 | }; | ||
| 172 | |||
| 57 | kunit_test_suites( | 173 | kunit_test_suites( |
| 58 | &of_dtb_suite, | 174 | &of_dtb_suite, &of_address_suite, |
| 59 | ); | 175 | ); |
| 60 | MODULE_DESCRIPTION("KUnit tests for OF APIs"); | 176 | MODULE_DESCRIPTION("KUnit tests for OF APIs"); |
| 177 | MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); | ||
| 61 | MODULE_LICENSE("GPL"); | 178 | MODULE_LICENSE("GPL"); |
| @@ -108,9 +108,6 @@ void pci_save_aspm_l1ss_state(struct pci_dev *pdev) · 107 unmodified lines | |||
| 108 | pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL2, cap++); | 108 | pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL2, cap++); |
| 109 | pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL1, cap++); | 109 | pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL1, cap++); |
| 110 | 110 | ||
| 111 | if (parent->state_saved) | ||
| 112 | return; | ||
| 113 | |||
| 114 | /* | 111 | /* |
| 115 | * Save parent's L1 substate configuration so we have it for | 112 | * Save parent's L1 substate configuration so we have it for |
| 116 | * pci_restore_aspm_l1ss_state(pdev) to restore. | 113 | * pci_restore_aspm_l1ss_state(pdev) to restore. |
| @@ -339,13 +339,14 @@ out: · 338 unmodified lines | |||
| 339 | return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; | 339 | return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | 342 | static __always_inline void pci_read_bases(struct pci_dev *dev, |
| 343 | unsigned int howmany, int rom) | ||
| 343 | { | 344 | { |
| 344 | u32 rombar, stdbars[PCI_STD_NUM_BARS]; | 345 | u32 rombar, stdbars[PCI_STD_NUM_BARS]; |
| 345 | unsigned int pos, reg; | 346 | unsigned int pos, reg; |
| 346 | u16 orig_cmd; | 347 | u16 orig_cmd; |
| 347 | 348 | ||
| 348 | BUILD_BUG_ON(howmany > PCI_STD_NUM_BARS); | 349 | BUILD_BUG_ON(statically_true(howmany > PCI_STD_NUM_BARS)); |
| 349 | 350 | ||
| 350 | if (dev->non_compliant_bars) | 351 | if (dev->non_compliant_bars) |
| 351 | return; | 352 | return; |
| @@ -5522,7 +5522,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap); · 5521 unmodified lines | |||
| 5522 | * AMD Matisse USB 3.0 Host Controller 0x149c | 5522 | * AMD Matisse USB 3.0 Host Controller 0x149c |
| 5523 | * Intel 82579LM Gigabit Ethernet Controller 0x1502 | 5523 | * Intel 82579LM Gigabit Ethernet Controller 0x1502 |
| 5524 | * Intel 82579V Gigabit Ethernet Controller 0x1503 | 5524 | * Intel 82579V Gigabit Ethernet Controller 0x1503 |
| 5525 | * | 5525 | * Mediatek MT7922 802.11ax PCI Express Wireless Network Adapter |
| 5526 | */ | 5526 | */ |
| 5527 | static void quirk_no_flr(struct pci_dev *dev) | 5527 | static void quirk_no_flr(struct pci_dev *dev) |
| 5528 | { | 5528 | { |
| @@ -5534,6 +5534,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x149c, quirk_no_flr); · 5 unmodified lines | |||
| 5534 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x7901, quirk_no_flr); | 5534 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x7901, quirk_no_flr); |
| 5535 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1502, quirk_no_flr); | 5535 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1502, quirk_no_flr); |
| 5536 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1503, quirk_no_flr); | 5536 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1503, quirk_no_flr); |
| 5537 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MEDIATEK, 0x0616, quirk_no_flr); | ||
| 5537 | 5538 | ||
| 5538 | /* FLR may cause the SolidRun SNET DPU (rev 0x1) to hang */ | 5539 | /* FLR may cause the SolidRun SNET DPU (rev 0x1) to hang */ |
| 5539 | static void quirk_no_flr_snet(struct pci_dev *dev) | 5540 | static void quirk_no_flr_snet(struct pci_dev *dev) |
| @@ -360,7 +360,7 @@ int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index, u16 tag) · 359 unmodified lines | |||
| 360 | return err; | 360 | return err; |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | set_ctrl_reg_req_en(pdev, pdev->tph_mode); | 363 | set_ctrl_reg_req_en(pdev, pdev->tph_req_type); |
| 364 | 364 | ||
| 365 | pci_dbg(pdev, "set steering tag: %s table, index=%d, tag=%#04x\n", | 365 | pci_dbg(pdev, "set steering tag: %s table, index=%d, tag=%#04x\n", |
| 366 | (loc == PCI_TPH_LOC_MSIX) ? "MSI-X" : "ST", index, tag); | 366 | (loc == PCI_TPH_LOC_MSIX) ? "MSI-X" : "ST", index, tag); |
| @@ -89,12 +89,12 @@ static void pinconf_generic_dump_one(struct pinctrl_dev *pctldev, · 88 unmodified lines | |||
| 89 | seq_puts(s, items[i].display); | 89 | seq_puts(s, items[i].display); |
| 90 | /* Print unit if available */ | 90 | /* Print unit if available */ |
| 91 | if (items[i].has_arg) { | 91 | if (items[i].has_arg) { |
| 92 | seq_printf(s, " (0x%x", | 92 | u32 val = pinconf_to_config_argument(config); |
| 93 | pinconf_to_config_argument(config)); | 93 | |
| 94 | if (items[i].format) | 94 | if (items[i].format) |
| 95 | seq_printf(s, " %s)", items[i].format); | 95 | seq_printf(s, " (%u %s)", val, items[i].format); |
| 96 | else | 96 | else |
| 97 | seq_puts(s, ")"); | 97 | seq_printf(s, " (0x%x)", val); |
| 98 | } | 98 | } |
| 99 | } | 99 | } |
| 100 | } | 100 | } |
| @@ -42,7 +42,7 @@ · 41 unmodified lines | |||
| 42 | #define CY8C95X0_PORTSEL 0x18 | 42 | #define CY8C95X0_PORTSEL 0x18 |
| 43 | /* Port settings, write PORTSEL first */ | 43 | /* Port settings, write PORTSEL first */ |
| 44 | #define CY8C95X0_INTMASK 0x19 | 44 | #define CY8C95X0_INTMASK 0x19 |
| 45 | #define CY8C95X0_PWMSEL 0x1A | 45 | #define CY8C95X0_SELPWM 0x1A |
| 46 | #define CY8C95X0_INVERT 0x1B | 46 | #define CY8C95X0_INVERT 0x1B |
| 47 | #define CY8C95X0_DIRECTION 0x1C | 47 | #define CY8C95X0_DIRECTION 0x1C |
| 48 | /* Drive mode register change state on writing '1' */ | 48 | /* Drive mode register change state on writing '1' */ |
| @@ -328,14 +328,14 @@ static int cypress_get_pin_mask(struct cy8c95x0_pinctrl *chip, unsigned int pin) · 279 unmodified lines | |||
| 328 | static bool cy8c95x0_readable_register(struct device *dev, unsigned int reg) | 328 | static bool cy8c95x0_readable_register(struct device *dev, unsigned int reg) |
| 329 | { | 329 | { |
| 330 | /* | 330 | /* |
| 331 | * Only 12 registers are present per port (see Table 6 in the | 331 | * Only 12 registers are present per port (see Table 6 in the datasheet). |
| 332 | * datasheet). | ||
| 333 | */ | 332 | */ |
| 334 | if (reg >= CY8C95X0_VIRTUAL && (reg % MUXED_STRIDE) < 12) | 333 | if (reg >= CY8C95X0_VIRTUAL && (reg % MUXED_STRIDE) >= 12) |
| 335 | return true; | 334 | return false; |
| 336 | 335 | ||
| 337 | switch (reg) { | 336 | switch (reg) { |
| 338 | case 0x24 ... 0x27: | 337 | case 0x24 ... 0x27: |
| 338 | case 0x31 ... 0x3f: | ||
| 339 | return false; | 339 | return false; |
| 340 | default: | 340 | default: |
| 341 | return true; | 341 | return true; |
| @@ -344,8 +344,11 @@ static bool cy8c95x0_readable_register(struct device *dev, unsigned int reg) · 2 unmodified lines | |||
| 344 | 344 | ||
| 345 | static bool cy8c95x0_writeable_register(struct device *dev, unsigned int reg) | 345 | static bool cy8c95x0_writeable_register(struct device *dev, unsigned int reg) |
| 346 | { | 346 | { |
| 347 | if (reg >= CY8C95X0_VIRTUAL) | 347 | /* |
| 348 | return true; | 348 | * Only 12 registers are present per port (see Table 6 in the datasheet). |
| 349 | */ | ||
| 350 | if (reg >= CY8C95X0_VIRTUAL && (reg % MUXED_STRIDE) >= 12) | ||
| 351 | return false; | ||
| 349 | 352 | ||
| 350 | switch (reg) { | 353 | switch (reg) { |
| 351 | case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7): | 354 | case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7): |
| @@ -353,6 +356,7 @@ static bool cy8c95x0_writeable_register(struct device *dev, unsigned int reg) · 1 unmodified line | |||
| 353 | case CY8C95X0_DEVID: | 356 | case CY8C95X0_DEVID: |
| 354 | return false; | 357 | return false; |
| 355 | case 0x24 ... 0x27: | 358 | case 0x24 ... 0x27: |
| 359 | case 0x31 ... 0x3f: | ||
| 356 | return false; | 360 | return false; |
| 357 | default: | 361 | default: |
| 358 | return true; | 362 | return true; |
| @@ -365,8 +369,8 @@ static bool cy8c95x0_volatile_register(struct device *dev, unsigned int reg) · 6 unmodified lines | |||
| 365 | case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7): | 369 | case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7): |
| 366 | case CY8C95X0_INTSTATUS_(0) ... CY8C95X0_INTSTATUS_(7): | 370 | case CY8C95X0_INTSTATUS_(0) ... CY8C95X0_INTSTATUS_(7): |
| 367 | case CY8C95X0_INTMASK: | 371 | case CY8C95X0_INTMASK: |
| 372 | case CY8C95X0_SELPWM: | ||
| 368 | case CY8C95X0_INVERT: | 373 | case CY8C95X0_INVERT: |
| 369 | case CY8C95X0_PWMSEL: | ||
| 370 | case CY8C95X0_DIRECTION: | 374 | case CY8C95X0_DIRECTION: |
| 371 | case CY8C95X0_DRV_PU: | 375 | case CY8C95X0_DRV_PU: |
| 372 | case CY8C95X0_DRV_PD: | 376 | case CY8C95X0_DRV_PD: |
| @@ -395,7 +399,7 @@ static bool cy8c95x0_muxed_register(unsigned int reg) · 22 unmodified lines | |||
| 395 | { | 399 | { |
| 396 | switch (reg) { | 400 | switch (reg) { |
| 397 | case CY8C95X0_INTMASK: | 401 | case CY8C95X0_INTMASK: |
| 398 | case CY8C95X0_PWMSEL: | 402 | case CY8C95X0_SELPWM: |
| 399 | case CY8C95X0_INVERT: | 403 | case CY8C95X0_INVERT: |
| 400 | case CY8C95X0_DIRECTION: | 404 | case CY8C95X0_DIRECTION: |
| 401 | case CY8C95X0_DRV_PU: | 405 | case CY8C95X0_DRV_PU: |
| @@ -466,7 +470,11 @@ static const struct regmap_config cy8c9520_i2c_regmap = { · 64 unmodified lines | |||
| 466 | .max_register = 0, /* Updated at runtime */ | 470 | .max_register = 0, /* Updated at runtime */ |
| 467 | .num_reg_defaults_raw = 0, /* Updated at runtime */ | 471 | .num_reg_defaults_raw = 0, /* Updated at runtime */ |
| 468 | .use_single_read = true, /* Workaround for regcache bug */ | 472 | .use_single_read = true, /* Workaround for regcache bug */ |
| 473 | #if IS_ENABLED(CONFIG_DEBUG_PINCTRL) | ||
| 474 | .disable_locking = false, | ||
| 475 | #else | ||
| 469 | .disable_locking = true, | 476 | .disable_locking = true, |
| 477 | #endif | ||
| 470 | }; | 478 | }; |
| 471 | 479 | ||
| 472 | static inline int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip, | 480 | static inline int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip, |
| @@ -789,7 +797,7 @@ static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip, · 316 unmodified lines | |||
| 789 | reg = CY8C95X0_DIRECTION; | 797 | reg = CY8C95X0_DIRECTION; |
| 790 | break; | 798 | break; |
| 791 | case PIN_CONFIG_MODE_PWM: | 799 | case PIN_CONFIG_MODE_PWM: |
| 792 | reg = CY8C95X0_PWMSEL; | 800 | reg = CY8C95X0_SELPWM; |
| 793 | break; | 801 | break; |
| 794 | case PIN_CONFIG_OUTPUT: | 802 | case PIN_CONFIG_OUTPUT: |
| 795 | reg = CY8C95X0_OUTPUT; | 803 | reg = CY8C95X0_OUTPUT; |
| @@ -868,7 +876,7 @@ static int cy8c95x0_gpio_set_pincfg(struct cy8c95x0_pinctrl *chip, · 72 unmodified lines | |||
| 868 | reg = CY8C95X0_DRV_PP_FAST; | 876 | reg = CY8C95X0_DRV_PP_FAST; |
| 869 | break; | 877 | break; |
| 870 | case PIN_CONFIG_MODE_PWM: | 878 | case PIN_CONFIG_MODE_PWM: |
| 871 | reg = CY8C95X0_PWMSEL; | 879 | reg = CY8C95X0_SELPWM; |
| 872 | break; | 880 | break; |
| 873 | case PIN_CONFIG_OUTPUT_ENABLE: | 881 | case PIN_CONFIG_OUTPUT_ENABLE: |
| 874 | return cy8c95x0_pinmux_direction(chip, off, !arg); | 882 | return cy8c95x0_pinmux_direction(chip, off, !arg); |
| @@ -1153,7 +1161,7 @@ static void cy8c95x0_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file * · 278 unmodified lines | |||
| 1153 | bitmap_zero(mask, MAX_LINE); | 1161 | bitmap_zero(mask, MAX_LINE); |
| 1154 | __set_bit(pin, mask); | 1162 | __set_bit(pin, mask); |
| 1155 | 1163 | ||
| 1156 | if (cy8c95x0_read_regs_mask(chip, CY8C95X0_PWMSEL, pwm, mask)) { | 1164 | if (cy8c95x0_read_regs_mask(chip, CY8C95X0_SELPWM, pwm, mask)) { |
| 1157 | seq_puts(s, "not available"); | 1165 | seq_puts(s, "not available"); |
| 1158 | return; | 1166 | return; |
| 1159 | } | 1167 | } |
| @@ -1198,7 +1206,7 @@ static int cy8c95x0_set_mode(struct cy8c95x0_pinctrl *chip, unsigned int off, bo · 38 unmodified lines | |||
| 1198 | u8 port = cypress_get_port(chip, off); | 1206 | u8 port = cypress_get_port(chip, off); |
| 1199 | u8 bit = cypress_get_pin_mask(chip, off); | 1207 | u8 bit = cypress_get_pin_mask(chip, off); |
| 1200 | 1208 | ||
| 1201 | return cy8c95x0_regmap_write_bits(chip, CY8C95X0_PWMSEL, port, bit, mode ? bit : 0); | 1209 | return cy8c95x0_regmap_write_bits(chip, CY8C95X0_SELPWM, port, bit, mode ? bit : 0); |
| 1202 | } | 1210 | } |
| 1203 | 1211 | ||
| 1204 | static int cy8c95x0_pinmux_mode(struct cy8c95x0_pinctrl *chip, | 1212 | static int cy8c95x0_pinmux_mode(struct cy8c95x0_pinctrl *chip, |
| @@ -1347,7 +1355,7 @@ static int cy8c95x0_irq_setup(struct cy8c95x0_pinctrl *chip, int irq) · 142 unmodified lines | |||
| 1347 | 1355 | ||
| 1348 | ret = devm_request_threaded_irq(chip->dev, irq, | 1356 | ret = devm_request_threaded_irq(chip->dev, irq, |
| 1349 | NULL, cy8c95x0_irq_handler, | 1357 | NULL, cy8c95x0_irq_handler, |
| 1350 | IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_HIGH, | 1358 | IRQF_ONESHOT | IRQF_SHARED, |
| 1351 | dev_name(chip->dev), chip); | 1359 | dev_name(chip->dev), chip); |
| 1352 | if (ret) { | 1360 | if (ret) { |
| 1353 | dev_err(chip->dev, "failed to request irq %d\n", irq); | 1361 | dev_err(chip->dev, "failed to request irq %d\n", irq); |
| @@ -1438,15 +1446,15 @@ static int cy8c95x0_probe(struct i2c_client *client) · 84 unmodified lines | |||
| 1438 | switch (chip->tpin) { | 1446 | switch (chip->tpin) { |
| 1439 | case 20: | 1447 | case 20: |
| 1440 | strscpy(chip->name, cy8c95x0_id[0].name); | 1448 | strscpy(chip->name, cy8c95x0_id[0].name); |
| 1441 | regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 3 * MUXED_STRIDE; | 1449 | regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 3 * MUXED_STRIDE - 1; |
| 1442 | break; | 1450 | break; |
| 1443 | case 40: | 1451 | case 40: |
| 1444 | strscpy(chip->name, cy8c95x0_id[1].name); | 1452 | strscpy(chip->name, cy8c95x0_id[1].name); |
| 1445 | regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 6 * MUXED_STRIDE; | 1453 | regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 6 * MUXED_STRIDE - 1; |
| 1446 | break; | 1454 | break; |
| 1447 | case 60: | 1455 | case 60: |
| 1448 | strscpy(chip->name, cy8c95x0_id[2].name); | 1456 | strscpy(chip->name, cy8c95x0_id[2].name); |
| 1449 | regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 8 * MUXED_STRIDE; | 1457 | regmap_range_conf.range_max = CY8C95X0_VIRTUAL + 8 * MUXED_STRIDE - 1; |
| 1450 | break; | 1458 | break; |
| 1451 | default: | 1459 | default: |
| 1452 | return -ENODEV; | 1460 | return -ENODEV; |
| @@ -1121,7 +1121,7 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv) · 1120 unmodified lines | |||
| 1121 | 1121 | ||
| 1122 | /* Create platform_profile structure and register */ | 1122 | /* Create platform_profile structure and register */ |
| 1123 | priv->dytc->ppdev = devm_platform_profile_register(&priv->platform_device->dev, | 1123 | priv->dytc->ppdev = devm_platform_profile_register(&priv->platform_device->dev, |
| 1124 | "ideapad-laptop", &priv->dytc, | 1124 | "ideapad-laptop", priv->dytc, |
| 1125 | &dytc_profile_ops); | 1125 | &dytc_profile_ops); |
| 1126 | if (IS_ERR(priv->dytc->ppdev)) { | 1126 | if (IS_ERR(priv->dytc->ppdev)) { |
| 1127 | err = PTR_ERR(priv->dytc->ppdev); | 1127 | err = PTR_ERR(priv->dytc->ppdev); |
| @@ -23,12 +23,14 @@ · 22 unmodified lines | |||
| 23 | * IFS Image | 23 | * IFS Image |
| 24 | * --------- | 24 | * --------- |
| 25 | * | 25 | * |
| 26 | * Intel provides a firmware file containing the scan tests via | 26 | * Intel provides firmware files containing the scan tests via the webpage [#f1]_. |
| 27 | * github [#f1]_. Similar to microcode there is a separate file for each | 27 | * Look under "In-Field Scan Test Images Download" section towards the |
| 28 | * end of the page. Similar to microcode, there are separate files for each | ||
| 28 | * family-model-stepping. IFS Images are not applicable for some test types. | 29 | * family-model-stepping. IFS Images are not applicable for some test types. |
| 29 | * Wherever applicable the sysfs directory would provide a "current_batch" file | 30 | * Wherever applicable the sysfs directory would provide a "current_batch" file |
| 30 | * (see below) for loading the image. | 31 | * (see below) for loading the image. |
| 31 | * | 32 | * |
| 33 | * .. [#f1] https://intel.com/InFieldScan | ||
| 32 | * | 34 | * |
| 33 | * IFS Image Loading | 35 | * IFS Image Loading |
| 34 | * ----------------- | 36 | * ----------------- |
| @@ -125,9 +127,6 @@ · 90 unmodified lines | |||
| 125 | * 2) Hardware allows for some number of cores to be tested in parallel. | 127 | * 2) Hardware allows for some number of cores to be tested in parallel. |
| 126 | * The driver does not make use of this, it only tests one core at a time. | 128 | * The driver does not make use of this, it only tests one core at a time. |
| 127 | * | 129 | * |
| 128 | * .. [#f1] https://github.com/intel/TBD | ||
| 129 | * | ||
| 130 | * | ||
| 131 | * Structural Based Functional Test at Field (SBAF): | 130 | * Structural Based Functional Test at Field (SBAF): |
| 132 | * ------------------------------------------------- | 131 | * ------------------------------------------------- |
| 133 | * | 132 | * |
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | /* Author: Dan Scally <djrscally@gmail.com> */ | 2 | /* Author: Dan Scally <djrscally@gmail.com> */ |
| 3 | 3 | ||
| 4 | #include <linux/acpi.h> | 4 | #include <linux/acpi.h> |
| 5 | #include <linux/array_size.h> | ||
| 5 | #include <linux/bitfield.h> | 6 | #include <linux/bitfield.h> |
| 6 | #include <linux/device.h> | 7 | #include <linux/device.h> |
| 7 | #include <linux/gpio/consumer.h> | 8 | #include <linux/gpio/consumer.h> |
| @@ -55,7 +56,7 @@ static void skl_int3472_log_sensor_module_name(struct int3472_discrete_device *i · 47 unmodified lines | |||
| 55 | 56 | ||
| 56 | static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry, | 57 | static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry, |
| 57 | struct acpi_resource_gpio *agpio, | 58 | struct acpi_resource_gpio *agpio, |
| 58 | const char *func, u32 polarity) | 59 | const char *func, unsigned long gpio_flags) |
| 59 | { | 60 | { |
| 60 | char *path = agpio->resource_source.string_ptr; | 61 | char *path = agpio->resource_source.string_ptr; |
| 61 | struct acpi_device *adev; | 62 | struct acpi_device *adev; |
| @@ -70,14 +71,14 @@ static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry, · 8 unmodified lines | |||
| 70 | if (!adev) | 71 | if (!adev) |
| 71 | return -ENODEV; | 72 | return -ENODEV; |
| 72 | 73 | ||
| 73 | *table_entry = GPIO_LOOKUP(acpi_dev_name(adev), agpio->pin_table[0], func, polarity); | 74 | *table_entry = GPIO_LOOKUP(acpi_dev_name(adev), agpio->pin_table[0], func, gpio_flags); |
| 74 | 75 | ||
| 75 | return 0; | 76 | return 0; |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472, | 79 | static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472, |
| 79 | struct acpi_resource_gpio *agpio, | 80 | struct acpi_resource_gpio *agpio, |
| 80 | const char *func, u32 polarity) | 81 | const char *func, unsigned long gpio_flags) |
| 81 | { | 82 | { |
| 82 | int ret; | 83 | int ret; |
| 83 | 84 | ||
| @@ -87,7 +88,7 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347 · 3 unmodified lines | |||
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | ret = skl_int3472_fill_gpiod_lookup(&int3472->gpios.table[int3472->n_sensor_gpios], | 90 | ret = skl_int3472_fill_gpiod_lookup(&int3472->gpios.table[int3472->n_sensor_gpios], |
| 90 | agpio, func, polarity); | 91 | agpio, func, gpio_flags); |
| 91 | if (ret) | 92 | if (ret) |
| 92 | return ret; | 93 | return ret; |
| 93 | 94 | ||
| @@ -100,7 +101,7 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347 · 6 unmodified lines | |||
| 100 | static struct gpio_desc * | 101 | static struct gpio_desc * |
| 101 | skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, | 102 | skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, |
| 102 | struct acpi_resource_gpio *agpio, | 103 | struct acpi_resource_gpio *agpio, |
| 103 | const char *func, u32 polarity) | 104 | const char *func, unsigned long gpio_flags) |
| 104 | { | 105 | { |
| 105 | struct gpio_desc *desc; | 106 | struct gpio_desc *desc; |
| 106 | int ret; | 107 | int ret; |
| @@ -111,7 +112,7 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, · 4 unmodified lines | |||
| 111 | return ERR_PTR(-ENOMEM); | 112 | return ERR_PTR(-ENOMEM); |
| 112 | 113 | ||
| 113 | lookup->dev_id = dev_name(int3472->dev); | 114 | lookup->dev_id = dev_name(int3472->dev); |
| 114 | ret = skl_int3472_fill_gpiod_lookup(&lookup->table[0], agpio, func, polarity); | 115 | ret = skl_int3472_fill_gpiod_lookup(&lookup->table[0], agpio, func, gpio_flags); |
| 115 | if (ret) | 116 | if (ret) |
| 116 | return ERR_PTR(ret); | 117 | return ERR_PTR(ret); |
| 117 | 118 | ||
| @@ -122,32 +123,76 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, · 4 unmodified lines | |||
| 122 | return desc; | 123 | return desc; |
| 123 | } | 124 | } |
| 124 | 125 | ||
| 125 | static void int3472_get_func_and_polarity(u8 type, const char **func, u32 *polarity) | 126 | /** |
| 127 | * struct int3472_gpio_map - Map GPIOs to whatever is expected by the | ||
| 128 | * sensor driver (as in DT bindings) | ||
| 129 | * @hid: The ACPI HID of the device without the instance number e.g. INT347E | ||
| 130 | * @type_from: The GPIO type from ACPI ?SDT | ||
| 131 | * @type_to: The assigned GPIO type, typically same as @type_from | ||
| 132 | * @func: The function, e.g. "enable" | ||
| 133 | * @polarity_low: GPIO_ACTIVE_LOW true if the @polarity_low is true, | ||
| 134 | * GPIO_ACTIVE_HIGH otherwise | ||
| 135 | */ | ||
| 136 | struct int3472_gpio_map { | ||
| 137 | const char *hid; | ||
| 138 | u8 type_from; | ||
| 139 | u8 type_to; | ||
| 140 | bool polarity_low; | ||
| 141 | const char *func; | ||
| 142 | }; | ||
| 143 | |||
| 144 | static const struct int3472_gpio_map int3472_gpio_map[] = { | ||
| 145 | { "INT347E", INT3472_GPIO_TYPE_RESET, INT3472_GPIO_TYPE_RESET, false, "enable" }, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static void int3472_get_func_and_polarity(struct acpi_device *adev, u8 *type, | ||
| 149 | const char **func, unsigned long *gpio_flags) | ||
| 126 | { | 150 | { |
| 127 | switch (type) { | 151 | unsigned int i; |
| 152 | |||
| 153 | for (i = 0; i < ARRAY_SIZE(int3472_gpio_map); i++) { | ||
| 154 | /* | ||
| 155 | * Map the firmware-provided GPIO to whatever a driver expects | ||
| 156 | * (as in DT bindings). First check if the type matches with the | ||
| 157 | * GPIO map, then further check that the device _HID matches. | ||
| 158 | */ | ||
| 159 | if (*type != int3472_gpio_map[i].type_from) | ||
| 160 | continue; | ||
| 161 | |||
| 162 | if (!acpi_dev_hid_uid_match(adev, int3472_gpio_map[i].hid, NULL)) | ||
| 163 | continue; | ||
| 164 | |||
| 165 | *type = int3472_gpio_map[i].type_to; | ||
| 166 | *gpio_flags = int3472_gpio_map[i].polarity_low ? | ||
| 167 | GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH; | ||
| 168 | *func = int3472_gpio_map[i].func; | ||
| 169 | return; | ||
| 170 | } | ||
| 171 | |||
| 172 | switch (*type) { | ||
| 128 | case INT3472_GPIO_TYPE_RESET: | 173 | case INT3472_GPIO_TYPE_RESET: |
| 129 | *func = "reset"; | 174 | *func = "reset"; |
| 130 | *polarity = GPIO_ACTIVE_LOW; | 175 | *gpio_flags = GPIO_ACTIVE_LOW; |
| 131 | break; | 176 | break; |
| 132 | case INT3472_GPIO_TYPE_POWERDOWN: | 177 | case INT3472_GPIO_TYPE_POWERDOWN: |
| 133 | *func = "powerdown"; | 178 | *func = "powerdown"; |
| 134 | *polarity = GPIO_ACTIVE_LOW; | 179 | *gpio_flags = GPIO_ACTIVE_LOW; |
| 135 | break; | 180 | break; |
| 136 | case INT3472_GPIO_TYPE_CLK_ENABLE: | 181 | case INT3472_GPIO_TYPE_CLK_ENABLE: |
| 137 | *func = "clk-enable"; | 182 | *func = "clk-enable"; |
| 138 | *polarity = GPIO_ACTIVE_HIGH; | 183 | *gpio_flags = GPIO_ACTIVE_HIGH; |
| 139 | break; | 184 | break; |
| 140 | case INT3472_GPIO_TYPE_PRIVACY_LED: | 185 | case INT3472_GPIO_TYPE_PRIVACY_LED: |
| 141 | *func = "privacy-led"; | 186 | *func = "privacy-led"; |
| 142 | *polarity = GPIO_ACTIVE_HIGH; | 187 | *gpio_flags = GPIO_ACTIVE_HIGH; |
| 143 | break; | 188 | break; |
| 144 | case INT3472_GPIO_TYPE_POWER_ENABLE: | 189 | case INT3472_GPIO_TYPE_POWER_ENABLE: |
| 145 | *func = "power-enable"; | 190 | *func = "power-enable"; |
| 146 | *polarity = GPIO_ACTIVE_HIGH; | 191 | *gpio_flags = GPIO_ACTIVE_HIGH; |
| 147 | break; | 192 | break; |
| 148 | default: | 193 | default: |
| 149 | *func = "unknown"; | 194 | *func = "unknown"; |
| 150 | *polarity = GPIO_ACTIVE_HIGH; | 195 | *gpio_flags = GPIO_ACTIVE_HIGH; |
| 151 | break; | 196 | break; |
| 152 | } | 197 | } |
| 153 | } | 198 | } |
| @@ -194,7 +239,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, · 40 unmodified lines | |||
| 194 | struct gpio_desc *gpio; | 239 | struct gpio_desc *gpio; |
| 195 | const char *err_msg; | 240 | const char *err_msg; |
| 196 | const char *func; | 241 | const char *func; |
| 197 | u32 polarity; | 242 | unsigned long gpio_flags; |
| 198 | int ret; | 243 | int ret; |
| 199 | 244 | ||
| 200 | if (!acpi_gpio_get_io_resource(ares, &agpio)) | 245 | if (!acpi_gpio_get_io_resource(ares, &agpio)) |
| @@ -217,7 +262,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, · 16 unmodified lines | |||
| 217 | 262 | ||
| 218 | type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value); | 263 | type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value); |
| 219 | 264 | ||
| 220 | int3472_get_func_and_polarity(type, &func, &polarity); | 265 | int3472_get_func_and_polarity(int3472->sensor, &type, &func, &gpio_flags); |
| 221 | 266 | ||
| 222 | pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value); | 267 | pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value); |
| 223 | /* Pin field is not really used under Windows and wraps around at 8 bits */ | 268 | /* Pin field is not really used under Windows and wraps around at 8 bits */ |
| @@ -227,16 +272,16 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, · 3 unmodified lines | |||
| 227 | 272 | ||
| 228 | active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value); | 273 | active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value); |
| 229 | if (!active_value) | 274 | if (!active_value) |
| 230 | polarity ^= GPIO_ACTIVE_LOW; | 275 | gpio_flags ^= GPIO_ACTIVE_LOW; |
| 231 | 276 | ||
| 232 | dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", func, | 277 | dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", func, |
| 233 | agpio->resource_source.string_ptr, agpio->pin_table[0], | 278 | agpio->resource_source.string_ptr, agpio->pin_table[0], |
| 234 | str_high_low(polarity == GPIO_ACTIVE_HIGH)); | 279 | str_high_low(gpio_flags == GPIO_ACTIVE_HIGH)); |
| 235 | 280 | ||
| 236 | switch (type) { | 281 | switch (type) { |
| 237 | case INT3472_GPIO_TYPE_RESET: | 282 | case INT3472_GPIO_TYPE_RESET: |
| 238 | case INT3472_GPIO_TYPE_POWERDOWN: | 283 | case INT3472_GPIO_TYPE_POWERDOWN: |
| 239 | ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, func, polarity); | 284 | ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, func, gpio_flags); |
| 240 | if (ret) | 285 | if (ret) |
| 241 | err_msg = "Failed to map GPIO pin to sensor\n"; | 286 | err_msg = "Failed to map GPIO pin to sensor\n"; |
| 242 | 287 | ||
| @@ -244,7 +289,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares, · 1 unmodified line | |||
| 244 | case INT3472_GPIO_TYPE_CLK_ENABLE: | 289 | case INT3472_GPIO_TYPE_CLK_ENABLE: |
| 245 | case INT3472_GPIO_TYPE_PRIVACY_LED: | 290 | case INT3472_GPIO_TYPE_PRIVACY_LED: |
| 246 | case INT3472_GPIO_TYPE_POWER_ENABLE: | 291 | case INT3472_GPIO_TYPE_POWER_ENABLE: |
| 247 | gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, func, polarity); | 292 | gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, func, gpio_flags); |
| 248 | if (IS_ERR(gpio)) { | 293 | if (IS_ERR(gpio)) { |
| 249 | ret = PTR_ERR(gpio); | 294 | ret = PTR_ERR(gpio); |
| 250 | err_msg = "Failed to get GPIO\n"; | 295 | err_msg = "Failed to get GPIO\n"; |
| @@ -626,8 +626,8 @@ static u32 convert_ltr_scale(u32 val) · 625 unmodified lines | |||
| 626 | static int pmc_core_ltr_show(struct seq_file *s, void *unused) | 626 | static int pmc_core_ltr_show(struct seq_file *s, void *unused) |
| 627 | { | 627 | { |
| 628 | struct pmc_dev *pmcdev = s->private; | 628 | struct pmc_dev *pmcdev = s->private; |
| 629 | u64 decoded_snoop_ltr, decoded_non_snoop_ltr; | 629 | u64 decoded_snoop_ltr, decoded_non_snoop_ltr, val; |
| 630 | u32 ltr_raw_data, scale, val; | 630 | u32 ltr_raw_data, scale; |
| 631 | u16 snoop_ltr, nonsnoop_ltr; | 631 | u16 snoop_ltr, nonsnoop_ltr; |
| 632 | unsigned int i, index, ltr_index = 0; | 632 | unsigned int i, index, ltr_index = 0; |
| 633 | 633 | ||
| @@ -7885,6 +7885,7 @@ static struct ibm_struct volume_driver_data = { · 7884 unmodified lines | |||
| 7885 | 7885 | ||
| 7886 | #define FAN_NS_CTRL_STATUS BIT(2) /* Bit which determines control is enabled or not */ | 7886 | #define FAN_NS_CTRL_STATUS BIT(2) /* Bit which determines control is enabled or not */ |
| 7887 | #define FAN_NS_CTRL BIT(4) /* Bit which determines control is by host or EC */ | 7887 | #define FAN_NS_CTRL BIT(4) /* Bit which determines control is by host or EC */ |
| 7888 | #define FAN_CLOCK_TPM (22500*60) /* Ticks per minute for a 22.5 kHz clock */ | ||
| 7888 | 7889 | ||
| 7889 | enum { /* Fan control constants */ | 7890 | enum { /* Fan control constants */ |
| 7890 | fan_status_offset = 0x2f, /* EC register 0x2f */ | 7891 | fan_status_offset = 0x2f, /* EC register 0x2f */ |
| @@ -7940,6 +7941,7 @@ static int fan_watchdog_maxinterval; · 49 unmodified lines | |||
| 7940 | 7941 | ||
| 7941 | static bool fan_with_ns_addr; | 7942 | static bool fan_with_ns_addr; |
| 7942 | static bool ecfw_with_fan_dec_rpm; | 7943 | static bool ecfw_with_fan_dec_rpm; |
| 7944 | static bool fan_speed_in_tpr; | ||
| 7943 | 7945 | ||
| 7944 | static struct mutex fan_mutex; | 7946 | static struct mutex fan_mutex; |
| 7945 | 7947 | ||
| @@ -8142,8 +8144,11 @@ static int fan_get_speed(unsigned int *speed) · 196 unmodified lines | |||
| 8142 | !acpi_ec_read(fan_rpm_offset + 1, &hi))) | 8144 | !acpi_ec_read(fan_rpm_offset + 1, &hi))) |
| 8143 | return -EIO; | 8145 | return -EIO; |
| 8144 | 8146 | ||
| 8145 | if (likely(speed)) | 8147 | if (likely(speed)) { |
| 8146 | *speed = (hi << 8) | lo; | 8148 | *speed = (hi << 8) | lo; |
| 8149 | if (fan_speed_in_tpr && *speed != 0) | ||
| 8150 | *speed = FAN_CLOCK_TPM / *speed; | ||
| 8151 | } | ||
| 8147 | break; | 8152 | break; |
| 8148 | case TPACPI_FAN_RD_TPEC_NS: | 8153 | case TPACPI_FAN_RD_TPEC_NS: |
| 8149 | if (!acpi_ec_read(fan_rpm_status_ns, &lo)) | 8154 | if (!acpi_ec_read(fan_rpm_status_ns, &lo)) |
| @@ -8176,8 +8181,11 @@ static int fan2_get_speed(unsigned int *speed) · 26 unmodified lines | |||
| 8176 | if (rc) | 8181 | if (rc) |
| 8177 | return -EIO; | 8182 | return -EIO; |
| 8178 | 8183 | ||
| 8179 | if (likely(speed)) | 8184 | if (likely(speed)) { |
| 8180 | *speed = (hi << 8) | lo; | 8185 | *speed = (hi << 8) | lo; |
| 8186 | if (fan_speed_in_tpr && *speed != 0) | ||
| 8187 | *speed = FAN_CLOCK_TPM / *speed; | ||
| 8188 | } | ||
| 8181 | break; | 8189 | break; |
| 8182 | 8190 | ||
| 8183 | case TPACPI_FAN_RD_TPEC_NS: | 8191 | case TPACPI_FAN_RD_TPEC_NS: |
| @@ -8788,6 +8796,7 @@ static const struct attribute_group fan_driver_attr_group = { · 604 unmodified lines | |||
| 8788 | #define TPACPI_FAN_NOFAN 0x0008 /* no fan available */ | 8796 | #define TPACPI_FAN_NOFAN 0x0008 /* no fan available */ |
| 8789 | #define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */ | 8797 | #define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */ |
| 8790 | #define TPACPI_FAN_DECRPM 0x0020 /* For ECFW's with RPM in register as decimal */ | 8798 | #define TPACPI_FAN_DECRPM 0x0020 /* For ECFW's with RPM in register as decimal */ |
| 8799 | #define TPACPI_FAN_TPR 0x0040 /* Fan speed is in Ticks Per Revolution */ | ||
| 8791 | 8800 | ||
| 8792 | static const struct tpacpi_quirk fan_quirk_table[] __initconst = { | 8801 | static const struct tpacpi_quirk fan_quirk_table[] __initconst = { |
| 8793 | TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1), | 8802 | TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1), |
| @@ -8817,6 +8826,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = { · 23 unmodified lines | |||
| 8817 | TPACPI_Q_LNV3('R', '0', 'V', TPACPI_FAN_NS), /* 11e Gen5 KL-Y */ | 8826 | TPACPI_Q_LNV3('R', '0', 'V', TPACPI_FAN_NS), /* 11e Gen5 KL-Y */ |
| 8818 | TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */ | 8827 | TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */ |
| 8819 | TPACPI_Q_LNV3('R', '0', 'Q', TPACPI_FAN_DECRPM),/* L480 */ | 8828 | TPACPI_Q_LNV3('R', '0', 'Q', TPACPI_FAN_DECRPM),/* L480 */ |
| 8829 | TPACPI_Q_LNV('8', 'F', TPACPI_FAN_TPR), /* ThinkPad x120e */ | ||
| 8820 | }; | 8830 | }; |
| 8821 | 8831 | ||
| 8822 | static int __init fan_init(struct ibm_init_struct *iibm) | 8832 | static int __init fan_init(struct ibm_init_struct *iibm) |
| @@ -8887,6 +8897,8 @@ static int __init fan_init(struct ibm_init_struct *iibm) · 64 unmodified lines | |||
| 8887 | 8897 | ||
| 8888 | if (quirks & TPACPI_FAN_Q1) | 8898 | if (quirks & TPACPI_FAN_Q1) |
| 8889 | fan_quirk1_setup(); | 8899 | fan_quirk1_setup(); |
| 8900 | if (quirks & TPACPI_FAN_TPR) | ||
| 8901 | fan_speed_in_tpr = true; | ||
| 8890 | /* Try and probe the 2nd fan */ | 8902 | /* Try and probe the 2nd fan */ |
| 8891 | tp_features.second_fan = 1; /* needed for get_speed to work */ | 8903 | tp_features.second_fan = 1; /* needed for get_speed to work */ |
| 8892 | res = fan2_get_speed(&speed); | 8904 | res = fan2_get_speed(&speed); |
| @@ -10319,6 +10331,10 @@ static struct ibm_struct proxsensor_driver_data = { · 1426 unmodified lines | |||
| 10319 | #define DYTC_MODE_PSC_BALANCE 5 /* Default mode aka balanced */ | 10331 | #define DYTC_MODE_PSC_BALANCE 5 /* Default mode aka balanced */ |
| 10320 | #define DYTC_MODE_PSC_PERFORM 7 /* High power mode aka performance */ | 10332 | #define DYTC_MODE_PSC_PERFORM 7 /* High power mode aka performance */ |
| 10321 | 10333 | ||
| 10334 | #define DYTC_MODE_PSCV9_LOWPOWER 1 /* Low power mode */ | ||
| 10335 | #define DYTC_MODE_PSCV9_BALANCE 3 /* Default mode aka balanced */ | ||
| 10336 | #define DYTC_MODE_PSCV9_PERFORM 4 /* High power mode aka performance */ | ||
| 10337 | |||
| 10322 | #define DYTC_ERR_MASK 0xF /* Bits 0-3 in cmd result are the error result */ | 10338 | #define DYTC_ERR_MASK 0xF /* Bits 0-3 in cmd result are the error result */ |
| 10323 | #define DYTC_ERR_SUCCESS 1 /* CMD completed successful */ | 10339 | #define DYTC_ERR_SUCCESS 1 /* CMD completed successful */ |
| 10324 | 10340 | ||
| @@ -10339,6 +10355,10 @@ static int dytc_capabilities; · 14 unmodified lines | |||
| 10339 | static bool dytc_mmc_get_available; | 10355 | static bool dytc_mmc_get_available; |
| 10340 | static int profile_force; | 10356 | static int profile_force; |
| 10341 | 10357 | ||
| 10358 | static int platform_psc_profile_lowpower = DYTC_MODE_PSC_LOWPOWER; | ||
| 10359 | static int platform_psc_profile_balanced = DYTC_MODE_PSC_BALANCE; | ||
| 10360 | static int platform_psc_profile_performance = DYTC_MODE_PSC_PERFORM; | ||
| 10361 | |||
| 10342 | static int convert_dytc_to_profile(int funcmode, int dytcmode, | 10362 | static int convert_dytc_to_profile(int funcmode, int dytcmode, |
| 10343 | enum platform_profile_option *profile) | 10363 | enum platform_profile_option *profile) |
| 10344 | { | 10364 | { |
| @@ -10360,19 +10380,15 @@ static int convert_dytc_to_profile(int funcmode, int dytcmode, · 15 unmodified lines | |||
| 10360 | } | 10380 | } |
| 10361 | return 0; | 10381 | return 0; |
| 10362 | case DYTC_FUNCTION_PSC: | 10382 | case DYTC_FUNCTION_PSC: |
| 10363 | switch (dytcmode) { | 10383 | if (dytcmode == platform_psc_profile_lowpower) |
| 10364 | case DYTC_MODE_PSC_LOWPOWER: | ||
| 10365 | *profile = PLATFORM_PROFILE_LOW_POWER; | 10384 | *profile = PLATFORM_PROFILE_LOW_POWER; |
| 10366 | break; | 10385 | else if (dytcmode == platform_psc_profile_balanced) |
| 10367 | case DYTC_MODE_PSC_BALANCE: | ||
| 10368 | *profile = PLATFORM_PROFILE_BALANCED; | 10386 | *profile = PLATFORM_PROFILE_BALANCED; |
| 10369 | break; | 10387 | else if (dytcmode == platform_psc_profile_performance) |
| 10370 | case DYTC_MODE_PSC_PERFORM: | ||
| 10371 | *profile = PLATFORM_PROFILE_PERFORMANCE; | 10388 | *profile = PLATFORM_PROFILE_PERFORMANCE; |
| 10372 | break; | 10389 | else |
| 10373 | default: /* Unknown mode */ | ||
| 10374 | return -EINVAL; | 10390 | return -EINVAL; |
| 10375 | } | 10391 | |
| 10376 | return 0; | 10392 | return 0; |
| 10377 | case DYTC_FUNCTION_AMT: | 10393 | case DYTC_FUNCTION_AMT: |
| 10378 | /* For now return balanced. It's the closest we have to 'auto' */ | 10394 | /* For now return balanced. It's the closest we have to 'auto' */ |
| @@ -10393,19 +10409,19 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe · 14 unmodified lines | |||
| 10393 | if (dytc_capabilities & BIT(DYTC_FC_MMC)) | 10409 | if (dytc_capabilities & BIT(DYTC_FC_MMC)) |
| 10394 | *perfmode = DYTC_MODE_MMC_LOWPOWER; | 10410 | *perfmode = DYTC_MODE_MMC_LOWPOWER; |
| 10395 | else if (dytc_capabilities & BIT(DYTC_FC_PSC)) | 10411 | else if (dytc_capabilities & BIT(DYTC_FC_PSC)) |
| 10396 | *perfmode = DYTC_MODE_PSC_LOWPOWER; | 10412 | *perfmode = platform_psc_profile_lowpower; |
| 10397 | break; | 10413 | break; |
| 10398 | case PLATFORM_PROFILE_BALANCED: | 10414 | case PLATFORM_PROFILE_BALANCED: |
| 10399 | if (dytc_capabilities & BIT(DYTC_FC_MMC)) | 10415 | if (dytc_capabilities & BIT(DYTC_FC_MMC)) |
| 10400 | *perfmode = DYTC_MODE_MMC_BALANCE; | 10416 | *perfmode = DYTC_MODE_MMC_BALANCE; |
| 10401 | else if (dytc_capabilities & BIT(DYTC_FC_PSC)) | 10417 | else if (dytc_capabilities & BIT(DYTC_FC_PSC)) |
| 10402 | *perfmode = DYTC_MODE_PSC_BALANCE; | 10418 | *perfmode = platform_psc_profile_balanced; |
| 10403 | break; | 10419 | break; |
| 10404 | case PLATFORM_PROFILE_PERFORMANCE: | 10420 | case PLATFORM_PROFILE_PERFORMANCE: |
| 10405 | if (dytc_capabilities & BIT(DYTC_FC_MMC)) | 10421 | if (dytc_capabilities & BIT(DYTC_FC_MMC)) |
| 10406 | *perfmode = DYTC_MODE_MMC_PERFORM; | 10422 | *perfmode = DYTC_MODE_MMC_PERFORM; |
| 10407 | else if (dytc_capabilities & BIT(DYTC_FC_PSC)) | 10423 | else if (dytc_capabilities & BIT(DYTC_FC_PSC)) |
| 10408 | *perfmode = DYTC_MODE_PSC_PERFORM; | 10424 | *perfmode = platform_psc_profile_performance; |
| 10409 | break; | 10425 | break; |
| 10410 | default: /* Unknown profile */ | 10426 | default: /* Unknown profile */ |
| 10411 | return -EOPNOTSUPP; | 10427 | return -EOPNOTSUPP; |
| @@ -10599,6 +10615,7 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) · 187 unmodified lines | |||
| 10599 | if (output & BIT(DYTC_QUERY_ENABLE_BIT)) | 10615 | if (output & BIT(DYTC_QUERY_ENABLE_BIT)) |
| 10600 | dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF; | 10616 | dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF; |
| 10601 | 10617 | ||
| 10618 | dbg_printk(TPACPI_DBG_INIT, "DYTC version %d\n", dytc_version); | ||
| 10602 | /* Check DYTC is enabled and supports mode setting */ | 10619 | /* Check DYTC is enabled and supports mode setting */ |
| 10603 | if (dytc_version < 5) | 10620 | if (dytc_version < 5) |
| 10604 | return -ENODEV; | 10621 | return -ENODEV; |
| @@ -10637,6 +10654,11 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) · 32 unmodified lines | |||
| 10637 | } | 10654 | } |
| 10638 | } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { /* PSC MODE */ | 10655 | } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { /* PSC MODE */ |
| 10639 | pr_debug("PSC is supported\n"); | 10656 | pr_debug("PSC is supported\n"); |
| 10657 | if (dytc_version >= 9) { /* update profiles for DYTC 9 and up */ | ||
| 10658 | platform_psc_profile_lowpower = DYTC_MODE_PSCV9_LOWPOWER; | ||
| 10659 | platform_psc_profile_balanced = DYTC_MODE_PSCV9_BALANCE; | ||
| 10660 | platform_psc_profile_performance = DYTC_MODE_PSCV9_PERFORM; | ||
| 10661 | } | ||
| 10640 | } else { | 10662 | } else { |
| 10641 | dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n"); | 10663 | dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n"); |
| 10642 | return -ENODEV; | 10664 | return -ENODEV; |
| @@ -10646,8 +10668,8 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) · 3 unmodified lines | |||
| 10646 | "DYTC version %d: thermal mode available\n", dytc_version); | 10668 | "DYTC version %d: thermal mode available\n", dytc_version); |
| 10647 | 10669 | ||
| 10648 | /* Create platform_profile structure and register */ | 10670 | /* Create platform_profile structure and register */ |
| 10649 | tpacpi_pprof = devm_platform_profile_register(&tpacpi_pdev->dev, "thinkpad-acpi", | 10671 | tpacpi_pprof = platform_profile_register(&tpacpi_pdev->dev, "thinkpad-acpi-profile", |
| 10650 | NULL, &dytc_profile_ops); | 10672 | NULL, &dytc_profile_ops); |
| 10651 | /* | 10673 | /* |
| 10652 | * If for some reason platform_profiles aren't enabled | 10674 | * If for some reason platform_profiles aren't enabled |
| 10653 | * don't quit terminally. | 10675 | * don't quit terminally. |
| @@ -10665,8 +10687,15 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) · 11 unmodified lines | |||
| 10665 | return 0; | 10687 | return 0; |
| 10666 | } | 10688 | } |
| 10667 | 10689 | ||
| 10690 | static void dytc_profile_exit(void) | ||
| 10691 | { | ||
| 10692 | if (!IS_ERR_OR_NULL(tpacpi_pprof)) | ||
| 10693 | platform_profile_remove(tpacpi_pprof); | ||
| 10694 | } | ||
| 10695 | |||
| 10668 | static struct ibm_struct dytc_profile_driver_data = { | 10696 | static struct ibm_struct dytc_profile_driver_data = { |
| 10669 | .name = "dytc-profile", | 10697 | .name = "dytc-profile", |
| 10698 | .exit = dytc_profile_exit, | ||
| 10670 | }; | 10699 | }; |
| 10671 | 10700 | ||
| 10672 | /************************************************************************* | 10701 | /************************************************************************* |
| @@ -627,8 +627,7 @@ struct powercap_control_type *powercap_register_control_type( · 626 unmodified lines | |||
| 627 | dev_set_name(&control_type->dev, "%s", name); | 627 | dev_set_name(&control_type->dev, "%s", name); |
| 628 | result = device_register(&control_type->dev); | 628 | result = device_register(&control_type->dev); |
| 629 | if (result) { | 629 | if (result) { |
| 630 | if (control_type->allocated) | 630 | put_device(&control_type->dev); |
| 631 | kfree(control_type); | ||
| 632 | return ERR_PTR(result); | 631 | return ERR_PTR(result); |
| 633 | } | 632 | } |
| 634 | idr_init(&control_type->idr); | 633 | idr_init(&control_type->idr); |
| @@ -414,16 +414,16 @@ static ssize_t vmclock_miscdev_read(struct file *fp, char __user *buf, · 413 unmodified lines | |||
| 414 | } | 414 | } |
| 415 | 415 | ||
| 416 | static const struct file_operations vmclock_miscdev_fops = { | 416 | static const struct file_operations vmclock_miscdev_fops = { |
| 417 | .owner = THIS_MODULE, | ||
| 417 | .mmap = vmclock_miscdev_mmap, | 418 | .mmap = vmclock_miscdev_mmap, |
| 418 | .read = vmclock_miscdev_read, | 419 | .read = vmclock_miscdev_read, |
| 419 | }; | 420 | }; |
| 420 | 421 | ||
| 421 | /* module operations */ | 422 | /* module operations */ |
| 422 | 423 | ||
| 423 | static void vmclock_remove(struct platform_device *pdev) | 424 | static void vmclock_remove(void *data) |
| 424 | { | 425 | { |
| 425 | struct device *dev = &pdev->dev; | 426 | struct vmclock_state *st = data; |
| 426 | struct vmclock_state *st = dev_get_drvdata(dev); | ||
| 427 | 427 | ||
| 428 | if (st->ptp_clock) | 428 | if (st->ptp_clock) |
| 429 | ptp_clock_unregister(st->ptp_clock); | 429 | ptp_clock_unregister(st->ptp_clock); |
| @@ -506,14 +506,13 @@ static int vmclock_probe(struct platform_device *pdev) · 76 unmodified lines | |||
| 506 | 506 | ||
| 507 | if (ret) { | 507 | if (ret) { |
| 508 | dev_info(dev, "Failed to obtain physical address: %d\n", ret); | 508 | dev_info(dev, "Failed to obtain physical address: %d\n", ret); |
| 509 | goto out; | 509 | return ret; |
| 510 | } | 510 | } |
| 511 | 511 | ||
| 512 | if (resource_size(&st->res) < VMCLOCK_MIN_SIZE) { | 512 | if (resource_size(&st->res) < VMCLOCK_MIN_SIZE) { |
| 513 | dev_info(dev, "Region too small (0x%llx)\n", | 513 | dev_info(dev, "Region too small (0x%llx)\n", |
| 514 | resource_size(&st->res)); | 514 | resource_size(&st->res)); |
| 515 | ret = -EINVAL; | 515 | return -EINVAL; |
| 516 | goto out; | ||
| 517 | } | 516 | } |
| 518 | st->clk = devm_memremap(dev, st->res.start, resource_size(&st->res), | 517 | st->clk = devm_memremap(dev, st->res.start, resource_size(&st->res), |
| 519 | MEMREMAP_WB | MEMREMAP_DEC); | 518 | MEMREMAP_WB | MEMREMAP_DEC); |
| @@ -521,31 +520,34 @@ static int vmclock_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 521 | ret = PTR_ERR(st->clk); | 520 | ret = PTR_ERR(st->clk); |
| 522 | dev_info(dev, "failed to map shared memory\n"); | 521 | dev_info(dev, "failed to map shared memory\n"); |
| 523 | st->clk = NULL; | 522 | st->clk = NULL; |
| 524 | goto out; | 523 | return ret; |
| 525 | } | 524 | } |
| 526 | 525 | ||
| 527 | if (le32_to_cpu(st->clk->magic) != VMCLOCK_MAGIC || | 526 | if (le32_to_cpu(st->clk->magic) != VMCLOCK_MAGIC || |
| 528 | le32_to_cpu(st->clk->size) > resource_size(&st->res) || | 527 | le32_to_cpu(st->clk->size) > resource_size(&st->res) || |
| 529 | le16_to_cpu(st->clk->version) != 1) { | 528 | le16_to_cpu(st->clk->version) != 1) { |
| 530 | dev_info(dev, "vmclock magic fields invalid\n"); | 529 | dev_info(dev, "vmclock magic fields invalid\n"); |
| 531 | ret = -EINVAL; | 530 | return -EINVAL; |
| 532 | goto out; | ||
| 533 | } | 531 | } |
| 534 | 532 | ||
| 535 | ret = ida_alloc(&vmclock_ida, GFP_KERNEL); | 533 | ret = ida_alloc(&vmclock_ida, GFP_KERNEL); |
| 536 | if (ret < 0) | 534 | if (ret < 0) |
| 537 | goto out; | 535 | return ret; |
| 538 | 536 | ||
| 539 | st->index = ret; | 537 | st->index = ret; |
| 540 | ret = devm_add_action_or_reset(&pdev->dev, vmclock_put_idx, st); | 538 | ret = devm_add_action_or_reset(&pdev->dev, vmclock_put_idx, st); |
| 541 | if (ret) | 539 | if (ret) |
| 542 | goto out; | 540 | return ret; |
| 543 | 541 | ||
| 544 | st->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "vmclock%d", st->index); | 542 | st->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "vmclock%d", st->index); |
| 545 | if (!st->name) { | 543 | if (!st->name) |
| 546 | ret = -ENOMEM; | 544 | return -ENOMEM; |
| 547 | goto out; | 545 | |
| 548 | } | 546 | st->miscdev.minor = MISC_DYNAMIC_MINOR; |
| 547 | |||
| 548 | ret = devm_add_action_or_reset(&pdev->dev, vmclock_remove, st); | ||
| 549 | if (ret) | ||
| 550 | return ret; | ||
| 549 | 551 | ||
| 550 | /* | 552 | /* |
| 551 | * If the structure is big enough, it can be mapped to userspace. | 553 | * If the structure is big enough, it can be mapped to userspace. |
| @@ -554,13 +556,12 @@ static int vmclock_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 554 | * cross that bridge if/when we come to it. | 556 | * cross that bridge if/when we come to it. |
| 555 | */ | 557 | */ |
| 556 | if (le32_to_cpu(st->clk->size) >= PAGE_SIZE) { | 558 | if (le32_to_cpu(st->clk->size) >= PAGE_SIZE) { |
| 557 | st->miscdev.minor = MISC_DYNAMIC_MINOR; | ||
| 558 | st->miscdev.fops = &vmclock_miscdev_fops; | 559 | st->miscdev.fops = &vmclock_miscdev_fops; |
| 559 | st->miscdev.name = st->name; | 560 | st->miscdev.name = st->name; |
| 560 | 561 | ||
| 561 | ret = misc_register(&st->miscdev); | 562 | ret = misc_register(&st->miscdev); |
| 562 | if (ret) | 563 | if (ret) |
| 563 | goto out; | 564 | return ret; |
| 564 | } | 565 | } |
| 565 | 566 | ||
| 566 | /* If there is valid clock information, register a PTP clock */ | 567 | /* If there is valid clock information, register a PTP clock */ |
| @@ -570,16 +571,14 @@ static int vmclock_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 570 | if (IS_ERR(st->ptp_clock)) { | 571 | if (IS_ERR(st->ptp_clock)) { |
| 571 | ret = PTR_ERR(st->ptp_clock); | 572 | ret = PTR_ERR(st->ptp_clock); |
| 572 | st->ptp_clock = NULL; | 573 | st->ptp_clock = NULL; |
| 573 | vmclock_remove(pdev); | 574 | return ret; |
| 574 | goto out; | ||
| 575 | } | 575 | } |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | if (!st->miscdev.minor && !st->ptp_clock) { | 578 | if (!st->miscdev.minor && !st->ptp_clock) { |
| 579 | /* Neither miscdev nor PTP registered */ | 579 | /* Neither miscdev nor PTP registered */ |
| 580 | dev_info(dev, "vmclock: Neither miscdev nor PTP available; not registering\n"); | 580 | dev_info(dev, "vmclock: Neither miscdev nor PTP available; not registering\n"); |
| 581 | ret = -ENODEV; | 581 | return -ENODEV; |
| 582 | goto out; | ||
| 583 | } | 582 | } |
| 584 | 583 | ||
| 585 | dev_info(dev, "%s: registered %s%s%s\n", st->name, | 584 | dev_info(dev, "%s: registered %s%s%s\n", st->name, |
| @@ -587,10 +586,7 @@ static int vmclock_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 587 | (st->miscdev.minor && st->ptp_clock) ? ", " : "", | 586 | (st->miscdev.minor && st->ptp_clock) ? ", " : "", |
| 588 | st->ptp_clock ? "PTP" : ""); | 587 | st->ptp_clock ? "PTP" : ""); |
| 589 | 588 | ||
| 590 | dev_set_drvdata(dev, st); | 589 | return 0; |
| 591 | |||
| 592 | out: | ||
| 593 | return ret; | ||
| 594 | } | 590 | } |
| 595 | 591 | ||
| 596 | static const struct acpi_device_id vmclock_acpi_ids[] = { | 592 | static const struct acpi_device_id vmclock_acpi_ids[] = { |
| @@ -601,7 +597,6 @@ MODULE_DEVICE_TABLE(acpi, vmclock_acpi_ids); · 4 unmodified lines | |||
| 601 | 597 | ||
| 602 | static struct platform_driver vmclock_platform_driver = { | 598 | static struct platform_driver vmclock_platform_driver = { |
| 603 | .probe = vmclock_probe, | 599 | .probe = vmclock_probe, |
| 604 | .remove = vmclock_remove, | ||
| 605 | .driver = { | 600 | .driver = { |
| 606 | .name = "vmclock", | 601 | .name = "vmclock", |
| 607 | .acpi_match_table = vmclock_acpi_ids, | 602 | .acpi_match_table = vmclock_acpi_ids, |
| @@ -5774,43 +5774,36 @@ regulator_register(struct device *dev, · 5773 unmodified lines | |||
| 5774 | goto clean; | 5774 | goto clean; |
| 5775 | } | 5775 | } |
| 5776 | 5776 | ||
| 5777 | if (config->init_data) { | 5777 | /* |
| 5778 | /* | 5778 | * DT may override the config->init_data provided if the platform |
| 5779 | * Providing of_match means the framework is expected to parse | 5779 | * needs to do so. If so, config->init_data is completely ignored. |
| 5780 | * DT to get the init_data. This would conflict with provided | 5780 | */ |
| 5781 | * init_data, if set. Warn if it happens. | 5781 | init_data = regulator_of_get_init_data(dev, regulator_desc, config, |
| 5782 | */ | 5782 | &rdev->dev.of_node); |
| 5783 | if (regulator_desc->of_match) | ||
| 5784 | dev_warn(dev, "Using provided init data - OF match ignored\n"); | ||
| 5785 | 5783 | ||
| 5784 | /* | ||
| 5785 | * Sometimes not all resources are probed already so we need to take | ||
| 5786 | * that into account. This happens most the time if the ena_gpiod comes | ||
| 5787 | * from a gpio extender or something else. | ||
| 5788 | */ | ||
| 5789 | if (PTR_ERR(init_data) == -EPROBE_DEFER) { | ||
| 5790 | ret = -EPROBE_DEFER; | ||
| 5791 | goto clean; | ||
| 5792 | } | ||
| 5793 | |||
| 5794 | /* | ||
| 5795 | * We need to keep track of any GPIO descriptor coming from the | ||
| 5796 | * device tree until we have handled it over to the core. If the | ||
| 5797 | * config that was passed in to this function DOES NOT contain | ||
| 5798 | * a descriptor, and the config after this call DOES contain | ||
| 5799 | * a descriptor, we definitely got one from parsing the device | ||
| 5800 | * tree. | ||
| 5801 | */ | ||
| 5802 | if (!cfg->ena_gpiod && config->ena_gpiod) | ||
| 5803 | dangling_of_gpiod = true; | ||
| 5804 | if (!init_data) { | ||
| 5786 | init_data = config->init_data; | 5805 | init_data = config->init_data; |
| 5787 | rdev->dev.of_node = of_node_get(config->of_node); | 5806 | rdev->dev.of_node = of_node_get(config->of_node); |
| 5788 | |||
| 5789 | } else { | ||
| 5790 | init_data = regulator_of_get_init_data(dev, regulator_desc, | ||
| 5791 | config, | ||
| 5792 | &rdev->dev.of_node); | ||
| 5793 | |||
| 5794 | /* | ||
| 5795 | * Sometimes not all resources are probed already so we need to | ||
| 5796 | * take that into account. This happens most the time if the | ||
| 5797 | * ena_gpiod comes from a gpio extender or something else. | ||
| 5798 | */ | ||
| 5799 | if (PTR_ERR(init_data) == -EPROBE_DEFER) { | ||
| 5800 | ret = -EPROBE_DEFER; | ||
| 5801 | goto clean; | ||
| 5802 | } | ||
| 5803 | |||
| 5804 | /* | ||
| 5805 | * We need to keep track of any GPIO descriptor coming from the | ||
| 5806 | * device tree until we have handled it over to the core. If the | ||
| 5807 | * config that was passed in to this function DOES NOT contain a | ||
| 5808 | * descriptor, and the config after this call DOES contain a | ||
| 5809 | * descriptor, we definitely got one from parsing the device | ||
| 5810 | * tree. | ||
| 5811 | */ | ||
| 5812 | if (!cfg->ena_gpiod && config->ena_gpiod) | ||
| 5813 | dangling_of_gpiod = true; | ||
| 5814 | } | 5807 | } |
| 5815 | 5808 | ||
| 5816 | ww_mutex_init(&rdev->mutex, ®ulator_ww_class); | 5809 | ww_mutex_init(&rdev->mutex, ®ulator_ww_class); |
| @@ -695,7 +695,8 @@ static int info_update(void) · 694 unmodified lines | |||
| 695 | if (time_after(jiffies, chp_info_expires)) { | 695 | if (time_after(jiffies, chp_info_expires)) { |
| 696 | /* Data is too old, update. */ | 696 | /* Data is too old, update. */ |
| 697 | rc = sclp_chp_read_info(&chp_info); | 697 | rc = sclp_chp_read_info(&chp_info); |
| 698 | chp_info_expires = jiffies + CHP_INFO_UPDATE_INTERVAL ; | 698 | if (!rc) |
| 699 | chp_info_expires = jiffies + CHP_INFO_UPDATE_INTERVAL; | ||
| 699 | } | 700 | } |
| 700 | mutex_unlock(&info_lock); | 701 | mutex_unlock(&info_lock); |
| 701 | 702 | ||
| @@ -588,6 +588,15 @@ out: · 587 unmodified lines | |||
| 588 | return ret; | 588 | return ret; |
| 589 | } | 589 | } |
| 590 | 590 | ||
| 591 | static void ism_dev_release(struct device *dev) | ||
| 592 | { | ||
| 593 | struct ism_dev *ism; | ||
| 594 | |||
| 595 | ism = container_of(dev, struct ism_dev, dev); | ||
| 596 | |||
| 597 | kfree(ism); | ||
| 598 | } | ||
| 599 | |||
| 591 | static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 600 | static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 592 | { | 601 | { |
| 593 | struct ism_dev *ism; | 602 | struct ism_dev *ism; |
| @@ -601,6 +610,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 7 unmodified lines | |||
| 601 | dev_set_drvdata(&pdev->dev, ism); | 610 | dev_set_drvdata(&pdev->dev, ism); |
| 602 | ism->pdev = pdev; | 611 | ism->pdev = pdev; |
| 603 | ism->dev.parent = &pdev->dev; | 612 | ism->dev.parent = &pdev->dev; |
| 613 | ism->dev.release = ism_dev_release; | ||
| 604 | device_initialize(&ism->dev); | 614 | device_initialize(&ism->dev); |
| 605 | dev_set_name(&ism->dev, dev_name(&pdev->dev)); | 615 | dev_set_name(&ism->dev, dev_name(&pdev->dev)); |
| 606 | ret = device_add(&ism->dev); | 616 | ret = device_add(&ism->dev); |
| @@ -637,7 +647,7 @@ err: · 30 unmodified lines | |||
| 637 | device_del(&ism->dev); | 647 | device_del(&ism->dev); |
| 638 | err_dev: | 648 | err_dev: |
| 639 | dev_set_drvdata(&pdev->dev, NULL); | 649 | dev_set_drvdata(&pdev->dev, NULL); |
| 640 | kfree(ism); | 650 | put_device(&ism->dev); |
| 641 | 651 | ||
| 642 | return ret; | 652 | return ret; |
| 643 | } | 653 | } |
| @@ -682,7 +692,7 @@ static void ism_remove(struct pci_dev *pdev) · 38 unmodified lines | |||
| 682 | pci_disable_device(pdev); | 692 | pci_disable_device(pdev); |
| 683 | device_del(&ism->dev); | 693 | device_del(&ism->dev); |
| 684 | dev_set_drvdata(&pdev->dev, NULL); | 694 | dev_set_drvdata(&pdev->dev, NULL); |
| 685 | kfree(ism); | 695 | put_device(&ism->dev); |
| 686 | } | 696 | } |
| 687 | 697 | ||
| 688 | static struct pci_driver ism_driver = { | 698 | static struct pci_driver ism_driver = { |
| @@ -7050,14 +7050,16 @@ int qeth_open(struct net_device *dev) · 7049 unmodified lines | |||
| 7050 | card->data.state = CH_STATE_UP; | 7050 | card->data.state = CH_STATE_UP; |
| 7051 | netif_tx_start_all_queues(dev); | 7051 | netif_tx_start_all_queues(dev); |
| 7052 | 7052 | ||
| 7053 | local_bh_disable(); | ||
| 7054 | qeth_for_each_output_queue(card, queue, i) { | 7053 | qeth_for_each_output_queue(card, queue, i) { |
| 7055 | netif_napi_add_tx(dev, &queue->napi, qeth_tx_poll); | 7054 | netif_napi_add_tx(dev, &queue->napi, qeth_tx_poll); |
| 7056 | napi_enable(&queue->napi); | 7055 | napi_enable(&queue->napi); |
| 7057 | napi_schedule(&queue->napi); | ||
| 7058 | } | 7056 | } |
| 7059 | |||
| 7060 | napi_enable(&card->napi); | 7057 | napi_enable(&card->napi); |
| 7058 | |||
| 7059 | local_bh_disable(); | ||
| 7060 | qeth_for_each_output_queue(card, queue, i) { | ||
| 7061 | napi_schedule(&queue->napi); | ||
| 7062 | } | ||
| 7061 | napi_schedule(&card->napi); | 7063 | napi_schedule(&card->napi); |
| 7062 | /* kick-start the NAPI softirq: */ | 7064 | /* kick-start the NAPI softirq: */ |
| 7063 | local_bh_enable(); | 7065 | local_bh_enable(); |
| @@ -2867,7 +2867,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) · 2866 unmodified lines | |||
| 2867 | dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", | 2867 | dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", |
| 2868 | cpu_to_le32(upper_32_bits(dma_handle)), | 2868 | cpu_to_le32(upper_32_bits(dma_handle)), |
| 2869 | cpu_to_le32(lower_32_bits(dma_handle)), | 2869 | cpu_to_le32(lower_32_bits(dma_handle)), |
| 2870 | cpu_to_le32(sg_dma_len(sg_next(s)))); | 2870 | cpu_to_le32(sg_dma_len(s))); |
| 2871 | remseg--; | 2871 | remseg--; |
| 2872 | } | 2872 | } |
| 2873 | dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather " | 2873 | dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather " |
| @@ -872,13 +872,18 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result) · 871 unmodified lines | |||
| 872 | case 0x1a: /* start stop unit in progress */ | 872 | case 0x1a: /* start stop unit in progress */ |
| 873 | case 0x1b: /* sanitize in progress */ | 873 | case 0x1b: /* sanitize in progress */ |
| 874 | case 0x1d: /* configuration in progress */ | 874 | case 0x1d: /* configuration in progress */ |
| 875 | case 0x24: /* depopulation in progress */ | ||
| 876 | case 0x25: /* depopulation restore in progress */ | ||
| 877 | action = ACTION_DELAYED_RETRY; | 875 | action = ACTION_DELAYED_RETRY; |
| 878 | break; | 876 | break; |
| 879 | case 0x0a: /* ALUA state transition */ | 877 | case 0x0a: /* ALUA state transition */ |
| 880 | action = ACTION_DELAYED_REPREP; | 878 | action = ACTION_DELAYED_REPREP; |
| 881 | break; | 879 | break; |
| 880 | /* | ||
| 881 | * Depopulation might take many hours, | ||
| 882 | * thus it is not worthwhile to retry. | ||
| 883 | */ | ||
| 884 | case 0x24: /* depopulation in progress */ | ||
| 885 | case 0x25: /* depopulation restore in progress */ | ||
| 886 | fallthrough; | ||
| 882 | default: | 887 | default: |
| 883 | action = ACTION_FAIL; | 888 | action = ACTION_FAIL; |
| 884 | break; | 889 | break; |
| @@ -67,6 +67,13 @@ static void scsi_lib_test_multiple_sense(struct kunit *test) · 66 unmodified lines | |||
| 67 | }; | 67 | }; |
| 68 | int i; | 68 | int i; |
| 69 | 69 | ||
| 70 | /* Success */ | ||
| 71 | sc.result = 0; | ||
| 72 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures)); | ||
| 73 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, NULL)); | ||
| 74 | /* Command failed but caller did not pass in a failures array */ | ||
| 75 | scsi_build_sense(&sc, 0, ILLEGAL_REQUEST, 0x91, 0x36); | ||
| 76 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, NULL)); | ||
| 70 | /* Match end of array */ | 77 | /* Match end of array */ |
| 71 | scsi_build_sense(&sc, 0, ILLEGAL_REQUEST, 0x91, 0x36); | 78 | scsi_build_sense(&sc, 0, ILLEGAL_REQUEST, 0x91, 0x36); |
| 72 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures)); | 79 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures)); |
| @@ -246,7 +246,7 @@ static int scsi_realloc_sdev_budget_map(struct scsi_device *sdev, · 245 unmodified lines | |||
| 246 | } | 246 | } |
| 247 | ret = sbitmap_init_node(&sdev->budget_map, | 247 | ret = sbitmap_init_node(&sdev->budget_map, |
| 248 | scsi_device_max_queue_depth(sdev), | 248 | scsi_device_max_queue_depth(sdev), |
| 249 | new_shift, GFP_KERNEL, | 249 | new_shift, GFP_NOIO, |
| 250 | sdev->request_queue->node, false, true); | 250 | sdev->request_queue->node, false, true); |
| 251 | if (!ret) | 251 | if (!ret) |
| 252 | sbitmap_resize(&sdev->budget_map, depth); | 252 | sbitmap_resize(&sdev->budget_map, depth); |
| @@ -1800,6 +1800,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) · 1799 unmodified lines | |||
| 1800 | 1800 | ||
| 1801 | length = scsi_bufflen(scmnd); | 1801 | length = scsi_bufflen(scmnd); |
| 1802 | payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb; | 1802 | payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb; |
| 1803 | payload->range.len = 0; | ||
| 1803 | payload_sz = 0; | 1804 | payload_sz = 0; |
| 1804 | 1805 | ||
| 1805 | if (scsi_sg_count(scmnd)) { | 1806 | if (scsi_sg_count(scmnd)) { |
| @@ -365,7 +365,7 @@ static void smp2p_irq_print_chip(struct irq_data *irqd, struct seq_file *p) · 364 unmodified lines | |||
| 365 | { | 365 | { |
| 366 | struct smp2p_entry *entry = irq_data_get_irq_chip_data(irqd); | 366 | struct smp2p_entry *entry = irq_data_get_irq_chip_data(irqd); |
| 367 | 367 | ||
| 368 | seq_printf(p, " %8s", dev_name(entry->smp2p->dev)); | 368 | seq_printf(p, "%8s", dev_name(entry->smp2p->dev)); |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | static struct irq_chip smp2p_irq_chip = { | 371 | static struct irq_chip smp2p_irq_chip = { |
| @@ -235,8 +235,8 @@ · 234 unmodified lines | |||
| 235 | /** | 235 | /** |
| 236 | * struct atmel_qspi_pcal - Pad Calibration Clock Division | 236 | * struct atmel_qspi_pcal - Pad Calibration Clock Division |
| 237 | * @pclk_rate: peripheral clock rate. | 237 | * @pclk_rate: peripheral clock rate. |
| 238 | * @pclkdiv: calibration clock division. The clock applied to the calibration | 238 | * @pclk_div: calibration clock division. The clock applied to the calibration |
| 239 | * cell is divided by pclkdiv + 1. | 239 | * cell is divided by pclk_div + 1. |
| 240 | */ | 240 | */ |
| 241 | struct atmel_qspi_pcal { | 241 | struct atmel_qspi_pcal { |
| 242 | u32 pclk_rate; | 242 | u32 pclk_rate; |
| @@ -399,7 +399,7 @@ static void lpss_ssp_cs_control(struct spi_device *spi, bool enable) · 398 unmodified lines | |||
| 399 | lpss_ssp_select_cs(spi, config); | 399 | lpss_ssp_select_cs(spi, config); |
| 400 | 400 | ||
| 401 | mask = LPSS_CS_CONTROL_CS_HIGH; | 401 | mask = LPSS_CS_CONTROL_CS_HIGH; |
| 402 | __lpss_ssp_update_priv(drv_data, config->reg_cs_ctrl, mask, enable ? mask : 0); | 402 | __lpss_ssp_update_priv(drv_data, config->reg_cs_ctrl, mask, enable ? 0 : mask); |
| 403 | if (config->cs_clk_stays_gated) { | 403 | if (config->cs_clk_stays_gated) { |
| 404 | /* | 404 | /* |
| 405 | * Changing CS alone when dynamic clock gating is on won't | 405 | * Changing CS alone when dynamic clock gating is on won't |
| @@ -116,6 +116,9 @@ struct f_ospi { · 115 unmodified lines | |||
| 116 | 116 | ||
| 117 | static u32 f_ospi_get_dummy_cycle(const struct spi_mem_op *op) | 117 | static u32 f_ospi_get_dummy_cycle(const struct spi_mem_op *op) |
| 118 | { | 118 | { |
| 119 | if (!op->dummy.nbytes) | ||
| 120 | return 0; | ||
| 121 | |||
| 119 | return (op->dummy.nbytes * 8) / op->dummy.buswidth; | 122 | return (op->dummy.nbytes * 8) / op->dummy.buswidth; |
| 120 | } | 123 | } |
| 121 | 124 | ||
| @@ -117,9 +117,9 @@ static ssize_t target_stat_tgt_status_show(struct config_item *item, · 116 unmodified lines | |||
| 117 | char *page) | 117 | char *page) |
| 118 | { | 118 | { |
| 119 | if (to_stat_tgt_dev(item)->export_count) | 119 | if (to_stat_tgt_dev(item)->export_count) |
| 120 | return snprintf(page, PAGE_SIZE, "activated"); | 120 | return snprintf(page, PAGE_SIZE, "activated\n"); |
| 121 | else | 121 | else |
| 122 | return snprintf(page, PAGE_SIZE, "deactivated"); | 122 | return snprintf(page, PAGE_SIZE, "deactivated\n"); |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static ssize_t target_stat_tgt_non_access_lus_show(struct config_item *item, | 125 | static ssize_t target_stat_tgt_non_access_lus_show(struct config_item *item, |
| @@ -57,8 +57,6 @@ struct time_in_idle { · 56 unmodified lines | |||
| 57 | * @max_level: maximum cooling level. One less than total number of valid | 57 | * @max_level: maximum cooling level. One less than total number of valid |
| 58 | * cpufreq frequencies. | 58 | * cpufreq frequencies. |
| 59 | * @em: Reference on the Energy Model of the device | 59 | * @em: Reference on the Energy Model of the device |
| 60 | * @cdev: thermal_cooling_device pointer to keep track of the | ||
| 61 | * registered cooling device. | ||
| 62 | * @policy: cpufreq policy. | 60 | * @policy: cpufreq policy. |
| 63 | * @cooling_ops: cpufreq callbacks to thermal cooling device ops | 61 | * @cooling_ops: cpufreq callbacks to thermal cooling device ops |
| 64 | * @idle_time: idle time stats | 62 | * @idle_time: idle time stats |
| @@ -798,7 +798,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) · 797 unmodified lines | |||
| 798 | nonseekable_open(inode, filp); | 798 | nonseekable_open(inode, filp); |
| 799 | 799 | ||
| 800 | /* We refuse fsnotify events on ptmx, since it's a shared resource */ | 800 | /* We refuse fsnotify events on ptmx, since it's a shared resource */ |
| 801 | filp->f_mode |= FMODE_NONOTIFY; | 801 | file_set_fsnotify_mode(filp, FMODE_NONOTIFY); |
| 802 | 802 | ||
| 803 | retval = tty_alloc_file(filp); | 803 | retval = tty_alloc_file(filp); |
| 804 | if (retval) | 804 | if (retval) |
| @@ -374,6 +374,7 @@ static inline int is_omap1510_8250(struct uart_8250_port *pt) · 373 unmodified lines | |||
| 374 | 374 | ||
| 375 | #ifdef CONFIG_SERIAL_8250_DMA | 375 | #ifdef CONFIG_SERIAL_8250_DMA |
| 376 | extern int serial8250_tx_dma(struct uart_8250_port *); | 376 | extern int serial8250_tx_dma(struct uart_8250_port *); |
| 377 | extern void serial8250_tx_dma_flush(struct uart_8250_port *); | ||
| 377 | extern int serial8250_rx_dma(struct uart_8250_port *); | 378 | extern int serial8250_rx_dma(struct uart_8250_port *); |
| 378 | extern void serial8250_rx_dma_flush(struct uart_8250_port *); | 379 | extern void serial8250_rx_dma_flush(struct uart_8250_port *); |
| 379 | extern int serial8250_request_dma(struct uart_8250_port *); | 380 | extern int serial8250_request_dma(struct uart_8250_port *); |
| @@ -406,6 +407,7 @@ static inline int serial8250_tx_dma(struct uart_8250_port *p) · 26 unmodified lines | |||
| 406 | { | 407 | { |
| 407 | return -1; | 408 | return -1; |
| 408 | } | 409 | } |
| 410 | static inline void serial8250_tx_dma_flush(struct uart_8250_port *p) { } | ||
| 409 | static inline int serial8250_rx_dma(struct uart_8250_port *p) | 411 | static inline int serial8250_rx_dma(struct uart_8250_port *p) |
| 410 | { | 412 | { |
| 411 | return -1; | 413 | return -1; |
| @@ -149,6 +149,22 @@ err: · 148 unmodified lines | |||
| 149 | return ret; | 149 | return ret; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | void serial8250_tx_dma_flush(struct uart_8250_port *p) | ||
| 153 | { | ||
| 154 | struct uart_8250_dma *dma = p->dma; | ||
| 155 | |||
| 156 | if (!dma->tx_running) | ||
| 157 | return; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * kfifo_reset() has been called by the serial core, avoid | ||
| 161 | * advancing and underflowing in __dma_tx_complete(). | ||
| 162 | */ | ||
| 163 | dma->tx_size = 0; | ||
| 164 | |||
| 165 | dmaengine_terminate_async(dma->rxchan); | ||
| 166 | } | ||
| 167 | |||
| 152 | int serial8250_rx_dma(struct uart_8250_port *p) | 168 | int serial8250_rx_dma(struct uart_8250_port *p) |
| 153 | { | 169 | { |
| 154 | struct uart_8250_dma *dma = p->dma; | 170 | struct uart_8250_dma *dma = p->dma; |
| @@ -110,7 +110,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev, · 109 unmodified lines | |||
| 110 | spin_lock_init(&port->lock); | 110 | spin_lock_init(&port->lock); |
| 111 | 111 | ||
| 112 | if (resource_type(&resource) == IORESOURCE_IO) { | 112 | if (resource_type(&resource) == IORESOURCE_IO) { |
| 113 | port->iotype = UPIO_PORT; | ||
| 114 | port->iobase = resource.start; | 113 | port->iobase = resource.start; |
| 115 | } else { | 114 | } else { |
| 116 | port->mapbase = resource.start; | 115 | port->mapbase = resource.start; |
| @@ -112,7 +112,6 @@ static int serial8250_probe_acpi(struct platform_device *pdev) · 111 unmodified lines | |||
| 112 | struct device *dev = &pdev->dev; | 112 | struct device *dev = &pdev->dev; |
| 113 | struct uart_8250_port uart = { }; | 113 | struct uart_8250_port uart = { }; |
| 114 | struct resource *regs; | 114 | struct resource *regs; |
| 115 | unsigned char iotype; | ||
| 116 | int ret, line; | 115 | int ret, line; |
| 117 | 116 | ||
| 118 | regs = platform_get_mem_or_io(pdev, 0); | 117 | regs = platform_get_mem_or_io(pdev, 0); |
| @@ -122,13 +121,11 @@ static int serial8250_probe_acpi(struct platform_device *pdev) · 3 unmodified lines | |||
| 122 | switch (resource_type(regs)) { | 121 | switch (resource_type(regs)) { |
| 123 | case IORESOURCE_IO: | 122 | case IORESOURCE_IO: |
| 124 | uart.port.iobase = regs->start; | 123 | uart.port.iobase = regs->start; |
| 125 | iotype = UPIO_PORT; | ||
| 126 | break; | 124 | break; |
| 127 | case IORESOURCE_MEM: | 125 | case IORESOURCE_MEM: |
| 128 | uart.port.mapbase = regs->start; | 126 | uart.port.mapbase = regs->start; |
| 129 | uart.port.mapsize = resource_size(regs); | 127 | uart.port.mapsize = resource_size(regs); |
| 130 | uart.port.flags = UPF_IOREMAP; | 128 | uart.port.flags = UPF_IOREMAP; |
| 131 | iotype = UPIO_MEM; | ||
| 132 | break; | 129 | break; |
| 133 | default: | 130 | default: |
| 134 | return -EINVAL; | 131 | return -EINVAL; |
| @@ -147,12 +144,6 @@ static int serial8250_probe_acpi(struct platform_device *pdev) · 12 unmodified lines | |||
| 147 | if (ret) | 144 | if (ret) |
| 148 | return ret; | 145 | return ret; |
| 149 | 146 | ||
| 150 | /* | ||
| 151 | * The previous call may not set iotype correctly when reg-io-width | ||
| 152 | * property is absent and it doesn't support IO port resource. | ||
| 153 | */ | ||
| 154 | uart.port.iotype = iotype; | ||
| 155 | |||
| 156 | line = serial8250_register_8250_port(&uart); | 147 | line = serial8250_register_8250_port(&uart); |
| 157 | if (line < 0) | 148 | if (line < 0) |
| 158 | return line; | 149 | return line; |
| @@ -436,7 +436,6 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) · 435 unmodified lines | |||
| 436 | { | 436 | { |
| 437 | struct uart_8250_port uart, *port; | 437 | struct uart_8250_port uart, *port; |
| 438 | int ret, flags = dev_id->driver_data; | 438 | int ret, flags = dev_id->driver_data; |
| 439 | unsigned char iotype; | ||
| 440 | long line; | 439 | long line; |
| 441 | 440 | ||
| 442 | if (flags & UNKNOWN_DEV) { | 441 | if (flags & UNKNOWN_DEV) { |
| @@ -448,14 +447,11 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) · 5 unmodified lines | |||
| 448 | memset(&uart, 0, sizeof(uart)); | 447 | memset(&uart, 0, sizeof(uart)); |
| 449 | if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) { | 448 | if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) { |
| 450 | uart.port.iobase = pnp_port_start(dev, 2); | 449 | uart.port.iobase = pnp_port_start(dev, 2); |
| 451 | iotype = UPIO_PORT; | ||
| 452 | } else if (pnp_port_valid(dev, 0)) { | 450 | } else if (pnp_port_valid(dev, 0)) { |
| 453 | uart.port.iobase = pnp_port_start(dev, 0); | 451 | uart.port.iobase = pnp_port_start(dev, 0); |
| 454 | iotype = UPIO_PORT; | ||
| 455 | } else if (pnp_mem_valid(dev, 0)) { | 452 | } else if (pnp_mem_valid(dev, 0)) { |
| 456 | uart.port.mapbase = pnp_mem_start(dev, 0); | 453 | uart.port.mapbase = pnp_mem_start(dev, 0); |
| 457 | uart.port.mapsize = pnp_mem_len(dev, 0); | 454 | uart.port.mapsize = pnp_mem_len(dev, 0); |
| 458 | iotype = UPIO_MEM; | ||
| 459 | uart.port.flags = UPF_IOREMAP; | 455 | uart.port.flags = UPF_IOREMAP; |
| 460 | } else | 456 | } else |
| 461 | return -ENODEV; | 457 | return -ENODEV; |
| @@ -471,12 +467,6 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) · 9 unmodified lines | |||
| 471 | if (ret) | 467 | if (ret) |
| 472 | return ret; | 468 | return ret; |
| 473 | 469 | ||
| 474 | /* | ||
| 475 | * The previous call may not set iotype correctly when reg-io-width | ||
| 476 | * property is absent and it doesn't support IO port resource. | ||
| 477 | */ | ||
| 478 | uart.port.iotype = iotype; | ||
| 479 | |||
| 480 | if (flags & CIR_PORT) { | 470 | if (flags & CIR_PORT) { |
| 481 | uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; | 471 | uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; |
| 482 | uart.port.type = PORT_8250_CIR; | 472 | uart.port.type = PORT_8250_CIR; |
| @@ -2555,6 +2555,14 @@ static void serial8250_shutdown(struct uart_port *port) · 2554 unmodified lines | |||
| 2555 | serial8250_do_shutdown(port); | 2555 | serial8250_do_shutdown(port); |
| 2556 | } | 2556 | } |
| 2557 | 2557 | ||
| 2558 | static void serial8250_flush_buffer(struct uart_port *port) | ||
| 2559 | { | ||
| 2560 | struct uart_8250_port *up = up_to_u8250p(port); | ||
| 2561 | |||
| 2562 | if (up->dma) | ||
| 2563 | serial8250_tx_dma_flush(up); | ||
| 2564 | } | ||
| 2565 | |||
| 2558 | static unsigned int serial8250_do_get_divisor(struct uart_port *port, | 2566 | static unsigned int serial8250_do_get_divisor(struct uart_port *port, |
| 2559 | unsigned int baud, | 2567 | unsigned int baud, |
| 2560 | unsigned int *frac) | 2568 | unsigned int *frac) |
| @@ -3244,6 +3252,7 @@ static const struct uart_ops serial8250_pops = { · 683 unmodified lines | |||
| 3244 | .break_ctl = serial8250_break_ctl, | 3252 | .break_ctl = serial8250_break_ctl, |
| 3245 | .startup = serial8250_startup, | 3253 | .startup = serial8250_startup, |
| 3246 | .shutdown = serial8250_shutdown, | 3254 | .shutdown = serial8250_shutdown, |
| 3255 | .flush_buffer = serial8250_flush_buffer, | ||
| 3247 | .set_termios = serial8250_set_termios, | 3256 | .set_termios = serial8250_set_termios, |
| 3248 | .set_ldisc = serial8250_set_ldisc, | 3257 | .set_ldisc = serial8250_set_ldisc, |
| 3249 | .pm = serial8250_pm, | 3258 | .pm = serial8250_pm, |
| @@ -1561,7 +1561,7 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype, · 1560 unmodified lines | |||
| 1561 | /* Always ask for fixed clock rate from a property. */ | 1561 | /* Always ask for fixed clock rate from a property. */ |
| 1562 | device_property_read_u32(dev, "clock-frequency", &uartclk); | 1562 | device_property_read_u32(dev, "clock-frequency", &uartclk); |
| 1563 | 1563 | ||
| 1564 | s->polling = !!irq; | 1564 | s->polling = (irq <= 0); |
| 1565 | if (s->polling) | 1565 | if (s->polling) |
| 1566 | dev_dbg(dev, | 1566 | dev_dbg(dev, |
| 1567 | "No interrupt pin definition, falling back to polling mode\n"); | 1567 | "No interrupt pin definition, falling back to polling mode\n"); |
| @@ -173,6 +173,7 @@ EXPORT_SYMBOL(uart_remove_one_port); · 172 unmodified lines | |||
| 173 | * The caller is responsible to initialize the following fields of the @port | 173 | * The caller is responsible to initialize the following fields of the @port |
| 174 | * ->dev (must be valid) | 174 | * ->dev (must be valid) |
| 175 | * ->flags | 175 | * ->flags |
| 176 | * ->iobase | ||
| 176 | * ->mapbase | 177 | * ->mapbase |
| 177 | * ->mapsize | 178 | * ->mapsize |
| 178 | * ->regshift (if @use_defaults is false) | 179 | * ->regshift (if @use_defaults is false) |
| @@ -214,7 +215,7 @@ static int __uart_read_properties(struct uart_port *port, bool use_defaults) · 35 unmodified lines | |||
| 214 | /* Read the registers I/O access type (default: MMIO 8-bit) */ | 215 | /* Read the registers I/O access type (default: MMIO 8-bit) */ |
| 215 | ret = device_property_read_u32(dev, "reg-io-width", &value); | 216 | ret = device_property_read_u32(dev, "reg-io-width", &value); |
| 216 | if (ret) { | 217 | if (ret) { |
| 217 | port->iotype = UPIO_MEM; | 218 | port->iotype = port->iobase ? UPIO_PORT : UPIO_MEM; |
| 218 | } else { | 219 | } else { |
| 219 | switch (value) { | 220 | switch (value) { |
| 220 | case 1: | 221 | case 1: |
| @@ -227,15 +228,16 @@ static int __uart_read_properties(struct uart_port *port, bool use_defaults) · 6 unmodified lines | |||
| 227 | port->iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32; | 228 | port->iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32; |
| 228 | break; | 229 | break; |
| 229 | default: | 230 | default: |
| 230 | if (!use_defaults) { | ||
| 231 | dev_err(dev, "Unsupported reg-io-width (%u)\n", value); | ||
| 232 | return -EINVAL; | ||
| 233 | } | ||
| 234 | port->iotype = UPIO_UNKNOWN; | 231 | port->iotype = UPIO_UNKNOWN; |
| 235 | break; | 232 | break; |
| 236 | } | 233 | } |
| 237 | } | 234 | } |
| 238 | 235 | ||
| 236 | if (!use_defaults && port->iotype == UPIO_UNKNOWN) { | ||
| 237 | dev_err(dev, "Unsupported reg-io-width (%u)\n", value); | ||
| 238 | return -EINVAL; | ||
| 239 | } | ||
| 240 | |||
| 239 | /* Read the address mapping base offset (default: no offset) */ | 241 | /* Read the address mapping base offset (default: no offset) */ |
| 240 | ret = device_property_read_u32(dev, "reg-offset", &value); | 242 | ret = device_property_read_u32(dev, "reg-offset", &value); |
| 241 | if (ret) | 243 | if (ret) |
| @@ -2120,8 +2120,6 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba) · 2119 unmodified lines | |||
| 2120 | INIT_DELAYED_WORK(&hba->clk_gating.gate_work, ufshcd_gate_work); | 2120 | INIT_DELAYED_WORK(&hba->clk_gating.gate_work, ufshcd_gate_work); |
| 2121 | INIT_WORK(&hba->clk_gating.ungate_work, ufshcd_ungate_work); | 2121 | INIT_WORK(&hba->clk_gating.ungate_work, ufshcd_ungate_work); |
| 2122 | 2122 | ||
| 2123 | spin_lock_init(&hba->clk_gating.lock); | ||
| 2124 | |||
| 2125 | hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue( | 2123 | hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue( |
| 2126 | "ufs_clk_gating_%d", WQ_MEM_RECLAIM | WQ_HIGHPRI, | 2124 | "ufs_clk_gating_%d", WQ_MEM_RECLAIM | WQ_HIGHPRI, |
| 2127 | hba->host->host_no); | 2125 | hba->host->host_no); |
| @@ -3106,8 +3104,13 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) · 978 unmodified lines | |||
| 3106 | case UPIU_TRANSACTION_QUERY_RSP: { | 3104 | case UPIU_TRANSACTION_QUERY_RSP: { |
| 3107 | u8 response = lrbp->ucd_rsp_ptr->header.response; | 3105 | u8 response = lrbp->ucd_rsp_ptr->header.response; |
| 3108 | 3106 | ||
| 3109 | if (response == 0) | 3107 | if (response == 0) { |
| 3110 | err = ufshcd_copy_query_response(hba, lrbp); | 3108 | err = ufshcd_copy_query_response(hba, lrbp); |
| 3109 | } else { | ||
| 3110 | err = -EINVAL; | ||
| 3111 | dev_err(hba->dev, "%s: unexpected response in Query RSP: %x\n", | ||
| 3112 | __func__, response); | ||
| 3113 | } | ||
| 3111 | break; | 3114 | break; |
| 3112 | } | 3115 | } |
| 3113 | case UPIU_TRANSACTION_REJECT_UPIU: | 3116 | case UPIU_TRANSACTION_REJECT_UPIU: |
| @@ -5976,24 +5979,6 @@ out: · 2862 unmodified lines | |||
| 5976 | __func__, err); | 5979 | __func__, err); |
| 5977 | } | 5980 | } |
| 5978 | 5981 | ||
| 5979 | static void ufshcd_temp_exception_event_handler(struct ufs_hba *hba, u16 status) | ||
| 5980 | { | ||
| 5981 | u32 value; | ||
| 5982 | |||
| 5983 | if (ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, | ||
| 5984 | QUERY_ATTR_IDN_CASE_ROUGH_TEMP, 0, 0, &value)) | ||
| 5985 | return; | ||
| 5986 | |||
| 5987 | dev_info(hba->dev, "exception Tcase %d\n", value - 80); | ||
| 5988 | |||
| 5989 | ufs_hwmon_notify_event(hba, status & MASK_EE_URGENT_TEMP); | ||
| 5990 | |||
| 5991 | /* | ||
| 5992 | * A placeholder for the platform vendors to add whatever additional | ||
| 5993 | * steps required | ||
| 5994 | */ | ||
| 5995 | } | ||
| 5996 | |||
| 5997 | static int __ufshcd_wb_toggle(struct ufs_hba *hba, bool set, enum flag_idn idn) | 5982 | static int __ufshcd_wb_toggle(struct ufs_hba *hba, bool set, enum flag_idn idn) |
| 5998 | { | 5983 | { |
| 5999 | u8 index; | 5984 | u8 index; |
| @@ -6214,7 +6199,7 @@ static void ufshcd_exception_event_handler(struct work_struct *work) · 214 unmodified lines | |||
| 6214 | ufshcd_bkops_exception_event_handler(hba); | 6199 | ufshcd_bkops_exception_event_handler(hba); |
| 6215 | 6200 | ||
| 6216 | if (status & hba->ee_drv_mask & MASK_EE_URGENT_TEMP) | 6201 | if (status & hba->ee_drv_mask & MASK_EE_URGENT_TEMP) |
| 6217 | ufshcd_temp_exception_event_handler(hba, status); | 6202 | ufs_hwmon_notify_event(hba, status & MASK_EE_URGENT_TEMP); |
| 6218 | 6203 | ||
| 6219 | ufs_debugfs_exception_event(hba, status); | 6204 | ufs_debugfs_exception_event(hba, status); |
| 6220 | } | 6205 | } |
| @@ -9160,7 +9145,7 @@ out: · 2939 unmodified lines | |||
| 9160 | if (!IS_ERR_OR_NULL(clki->clk) && clki->enabled) | 9145 | if (!IS_ERR_OR_NULL(clki->clk) && clki->enabled) |
| 9161 | clk_disable_unprepare(clki->clk); | 9146 | clk_disable_unprepare(clki->clk); |
| 9162 | } | 9147 | } |
| 9163 | } else if (!ret && on) { | 9148 | } else if (!ret && on && hba->clk_gating.is_initialized) { |
| 9164 | scoped_guard(spinlock_irqsave, &hba->clk_gating.lock) | 9149 | scoped_guard(spinlock_irqsave, &hba->clk_gating.lock) |
| 9165 | hba->clk_gating.state = CLKS_ON; | 9150 | hba->clk_gating.state = CLKS_ON; |
| 9166 | trace_ufshcd_clk_gating(dev_name(hba->dev), | 9151 | trace_ufshcd_clk_gating(dev_name(hba->dev), |
| @@ -10246,16 +10231,6 @@ int ufshcd_system_thaw(struct device *dev) · 1079 unmodified lines | |||
| 10246 | EXPORT_SYMBOL_GPL(ufshcd_system_thaw); | 10231 | EXPORT_SYMBOL_GPL(ufshcd_system_thaw); |
| 10247 | #endif /* CONFIG_PM_SLEEP */ | 10232 | #endif /* CONFIG_PM_SLEEP */ |
| 10248 | 10233 | ||
| 10249 | /** | ||
| 10250 | * ufshcd_dealloc_host - deallocate Host Bus Adapter (HBA) | ||
| 10251 | * @hba: pointer to Host Bus Adapter (HBA) | ||
| 10252 | */ | ||
| 10253 | void ufshcd_dealloc_host(struct ufs_hba *hba) | ||
| 10254 | { | ||
| 10255 | scsi_host_put(hba->host); | ||
| 10256 | } | ||
| 10257 | EXPORT_SYMBOL_GPL(ufshcd_dealloc_host); | ||
| 10258 | |||
| 10259 | /** | 10234 | /** |
| 10260 | * ufshcd_set_dma_mask - Set dma mask based on the controller | 10235 | * ufshcd_set_dma_mask - Set dma mask based on the controller |
| 10261 | * addressing capability | 10236 | * addressing capability |
| @@ -10274,12 +10249,26 @@ static int ufshcd_set_dma_mask(struct ufs_hba *hba) · 12 unmodified lines | |||
| 10274 | return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32)); | 10249 | return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32)); |
| 10275 | } | 10250 | } |
| 10276 | 10251 | ||
| 10252 | /** | ||
| 10253 | * ufshcd_devres_release - devres cleanup handler, invoked during release of | ||
| 10254 | * hba->dev | ||
| 10255 | * @host: pointer to SCSI host | ||
| 10256 | */ | ||
| 10257 | static void ufshcd_devres_release(void *host) | ||
| 10258 | { | ||
| 10259 | scsi_host_put(host); | ||
| 10260 | } | ||
| 10261 | |||
| 10277 | /** | 10262 | /** |
| 10278 | * ufshcd_alloc_host - allocate Host Bus Adapter (HBA) | 10263 | * ufshcd_alloc_host - allocate Host Bus Adapter (HBA) |
| 10279 | * @dev: pointer to device handle | 10264 | * @dev: pointer to device handle |
| 10280 | * @hba_handle: driver private handle | 10265 | * @hba_handle: driver private handle |
| 10281 | * | 10266 | * |
| 10282 | * Return: 0 on success, non-zero value on failure. | 10267 | * Return: 0 on success, non-zero value on failure. |
| 10268 | * | ||
| 10269 | * NOTE: There is no corresponding ufshcd_dealloc_host() because this function | ||
| 10270 | * keeps track of its allocations using devres and deallocates everything on | ||
| 10271 | * device removal automatically. | ||
| 10283 | */ | 10272 | */ |
| 10284 | int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle) | 10273 | int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle) |
| 10285 | { | 10274 | { |
| @@ -10301,6 +10290,13 @@ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle) · 15 unmodified lines | |||
| 10301 | err = -ENOMEM; | 10290 | err = -ENOMEM; |
| 10302 | goto out_error; | 10291 | goto out_error; |
| 10303 | } | 10292 | } |
| 10293 | |||
| 10294 | err = devm_add_action_or_reset(dev, ufshcd_devres_release, | ||
| 10295 | host); | ||
| 10296 | if (err) | ||
| 10297 | return dev_err_probe(dev, err, | ||
| 10298 | "failed to add ufshcd dealloc action\n"); | ||
| 10299 | |||
| 10304 | host->nr_maps = HCTX_TYPE_POLL + 1; | 10300 | host->nr_maps = HCTX_TYPE_POLL + 1; |
| 10305 | hba = shost_priv(host); | 10301 | hba = shost_priv(host); |
| 10306 | hba->host = host; | 10302 | hba->host = host; |
| @@ -10429,6 +10425,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) · 122 unmodified lines | |||
| 10429 | hba->irq = irq; | 10425 | hba->irq = irq; |
| 10430 | hba->vps = &ufs_hba_vps; | 10426 | hba->vps = &ufs_hba_vps; |
| 10431 | 10427 | ||
| 10428 | /* | ||
| 10429 | * Initialize clk_gating.lock early since it is being used in | ||
| 10430 | * ufshcd_setup_clocks() | ||
| 10431 | */ | ||
| 10432 | spin_lock_init(&hba->clk_gating.lock); | ||
| 10433 | |||
| 10432 | err = ufshcd_hba_init(hba); | 10434 | err = ufshcd_hba_init(hba); |
| 10433 | if (err) | 10435 | if (err) |
| 10434 | goto out_error; | 10436 | goto out_error; |
| @@ -562,7 +562,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev) · 561 unmodified lines | |||
| 562 | pm_runtime_forbid(&pdev->dev); | 562 | pm_runtime_forbid(&pdev->dev); |
| 563 | pm_runtime_get_noresume(&pdev->dev); | 563 | pm_runtime_get_noresume(&pdev->dev); |
| 564 | ufshcd_remove(hba); | 564 | ufshcd_remove(hba); |
| 565 | ufshcd_dealloc_host(hba); | ||
| 566 | } | 565 | } |
| 567 | 566 | ||
| 568 | /** | 567 | /** |
| @@ -605,7 +604,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 36 unmodified lines | |||
| 605 | err = ufshcd_init(hba, mmio_base, pdev->irq); | 604 | err = ufshcd_init(hba, mmio_base, pdev->irq); |
| 606 | if (err) { | 605 | if (err) { |
| 607 | dev_err(&pdev->dev, "Initialization failed\n"); | 606 | dev_err(&pdev->dev, "Initialization failed\n"); |
| 608 | ufshcd_dealloc_host(hba); | ||
| 609 | return err; | 607 | return err; |
| 610 | } | 608 | } |
| 611 | 609 | ||
| @@ -465,21 +465,17 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, · 464 unmodified lines | |||
| 465 | struct device *dev = &pdev->dev; | 465 | struct device *dev = &pdev->dev; |
| 466 | 466 | ||
| 467 | mmio_base = devm_platform_ioremap_resource(pdev, 0); | 467 | mmio_base = devm_platform_ioremap_resource(pdev, 0); |
| 468 | if (IS_ERR(mmio_base)) { | 468 | if (IS_ERR(mmio_base)) |
| 469 | err = PTR_ERR(mmio_base); | 469 | return PTR_ERR(mmio_base); |
| 470 | goto out; | ||
| 471 | } | ||
| 472 | 470 | ||
| 473 | irq = platform_get_irq(pdev, 0); | 471 | irq = platform_get_irq(pdev, 0); |
| 474 | if (irq < 0) { | 472 | if (irq < 0) |
| 475 | err = irq; | 473 | return irq; |
| 476 | goto out; | ||
| 477 | } | ||
| 478 | 474 | ||
| 479 | err = ufshcd_alloc_host(dev, &hba); | 475 | err = ufshcd_alloc_host(dev, &hba); |
| 480 | if (err) { | 476 | if (err) { |
| 481 | dev_err(dev, "Allocation failed\n"); | 477 | dev_err(dev, "Allocation failed\n"); |
| 482 | goto out; | 478 | return err; |
| 483 | } | 479 | } |
| 484 | 480 | ||
| 485 | hba->vops = vops; | 481 | hba->vops = vops; |
| @@ -488,13 +484,13 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, · 2 unmodified lines | |||
| 488 | if (err) { | 484 | if (err) { |
| 489 | dev_err(dev, "%s: clock parse failed %d\n", | 485 | dev_err(dev, "%s: clock parse failed %d\n", |
| 490 | __func__, err); | 486 | __func__, err); |
| 491 | goto dealloc_host; | 487 | return err; |
| 492 | } | 488 | } |
| 493 | err = ufshcd_parse_regulator_info(hba); | 489 | err = ufshcd_parse_regulator_info(hba); |
| 494 | if (err) { | 490 | if (err) { |
| 495 | dev_err(dev, "%s: regulator init failed %d\n", | 491 | dev_err(dev, "%s: regulator init failed %d\n", |
| 496 | __func__, err); | 492 | __func__, err); |
| 497 | goto dealloc_host; | 493 | return err; |
| 498 | } | 494 | } |
| 499 | 495 | ||
| 500 | ufshcd_init_lanes_per_dir(hba); | 496 | ufshcd_init_lanes_per_dir(hba); |
| @@ -502,25 +498,20 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, · 1 unmodified line | |||
| 502 | err = ufshcd_parse_operating_points(hba); | 498 | err = ufshcd_parse_operating_points(hba); |
| 503 | if (err) { | 499 | if (err) { |
| 504 | dev_err(dev, "%s: OPP parse failed %d\n", __func__, err); | 500 | dev_err(dev, "%s: OPP parse failed %d\n", __func__, err); |
| 505 | goto dealloc_host; | 501 | return err; |
| 506 | } | 502 | } |
| 507 | 503 | ||
| 508 | err = ufshcd_init(hba, mmio_base, irq); | 504 | err = ufshcd_init(hba, mmio_base, irq); |
| 509 | if (err) { | 505 | if (err) { |
| 510 | dev_err_probe(dev, err, "Initialization failed with error %d\n", | 506 | dev_err_probe(dev, err, "Initialization failed with error %d\n", |
| 511 | err); | 507 | err); |
| 512 | goto dealloc_host; | 508 | return err; |
| 513 | } | 509 | } |
| 514 | 510 | ||
| 515 | pm_runtime_set_active(dev); | 511 | pm_runtime_set_active(dev); |
| 516 | pm_runtime_enable(dev); | 512 | pm_runtime_enable(dev); |
| 517 | 513 | ||
| 518 | return 0; | 514 | return 0; |
| 519 | |||
| 520 | dealloc_host: | ||
| 521 | ufshcd_dealloc_host(hba); | ||
| 522 | out: | ||
| 523 | return err; | ||
| 524 | } | 515 | } |
| 525 | EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init); | 516 | EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init); |
| 526 | 517 | ||
| @@ -534,7 +525,6 @@ void ufshcd_pltfrm_remove(struct platform_device *pdev) · 7 unmodified lines | |||
| 534 | 525 | ||
| 535 | pm_runtime_get_sync(&pdev->dev); | 526 | pm_runtime_get_sync(&pdev->dev); |
| 536 | ufshcd_remove(hba); | 527 | ufshcd_remove(hba); |
| 537 | ufshcd_dealloc_host(hba); | ||
| 538 | pm_runtime_disable(&pdev->dev); | 528 | pm_runtime_disable(&pdev->dev); |
| 539 | pm_runtime_put_noidle(&pdev->dev); | 529 | pm_runtime_put_noidle(&pdev->dev); |
| 540 | } | 530 | } |
| @@ -371,7 +371,7 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf) · 370 unmodified lines | |||
| 371 | static void acm_ctrl_irq(struct urb *urb) | 371 | static void acm_ctrl_irq(struct urb *urb) |
| 372 | { | 372 | { |
| 373 | struct acm *acm = urb->context; | 373 | struct acm *acm = urb->context; |
| 374 | struct usb_cdc_notification *dr = urb->transfer_buffer; | 374 | struct usb_cdc_notification *dr; |
| 375 | unsigned int current_size = urb->actual_length; | 375 | unsigned int current_size = urb->actual_length; |
| 376 | unsigned int expected_size, copy_size, alloc_size; | 376 | unsigned int expected_size, copy_size, alloc_size; |
| 377 | int retval; | 377 | int retval; |
| @@ -398,14 +398,25 @@ static void acm_ctrl_irq(struct urb *urb) · 20 unmodified lines | |||
| 398 | 398 | ||
| 399 | usb_mark_last_busy(acm->dev); | 399 | usb_mark_last_busy(acm->dev); |
| 400 | 400 | ||
| 401 | if (acm->nb_index) | 401 | if (acm->nb_index == 0) { |
| 402 | /* | ||
| 403 | * The first chunk of a message must contain at least the | ||
| 404 | * notification header with the length field, otherwise we | ||
| 405 | * can't get an expected_size. | ||
| 406 | */ | ||
| 407 | if (current_size < sizeof(struct usb_cdc_notification)) { | ||
| 408 | dev_dbg(&acm->control->dev, "urb too short\n"); | ||
| 409 | goto exit; | ||
| 410 | } | ||
| 411 | dr = urb->transfer_buffer; | ||
| 412 | } else { | ||
| 402 | dr = (struct usb_cdc_notification *)acm->notification_buffer; | 413 | dr = (struct usb_cdc_notification *)acm->notification_buffer; |
| 403 | 414 | } | |
| 404 | /* size = notification-header + (optional) data */ | 415 | /* size = notification-header + (optional) data */ |
| 405 | expected_size = sizeof(struct usb_cdc_notification) + | 416 | expected_size = sizeof(struct usb_cdc_notification) + |
| 406 | le16_to_cpu(dr->wLength); | 417 | le16_to_cpu(dr->wLength); |
| 407 | 418 | ||
| 408 | if (current_size < expected_size) { | 419 | if (acm->nb_index != 0 || current_size < expected_size) { |
| 409 | /* notification is transmitted fragmented, reassemble */ | 420 | /* notification is transmitted fragmented, reassemble */ |
| 410 | if (acm->nb_size < expected_size) { | 421 | if (acm->nb_size < expected_size) { |
| 411 | u8 *new_buffer; | 422 | u8 *new_buffer; |
| @@ -1727,13 +1738,16 @@ static const struct usb_device_id acm_ids[] = { · 1315 unmodified lines | |||
| 1727 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ | 1738 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ |
| 1728 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1739 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
| 1729 | }, | 1740 | }, |
| 1730 | { USB_DEVICE(0x045b, 0x023c), /* Renesas USB Download mode */ | 1741 | { USB_DEVICE(0x045b, 0x023c), /* Renesas R-Car H3 USB Download mode */ |
| 1742 | .driver_info = DISABLE_ECHO, /* Don't echo banner */ | ||
| 1743 | }, | ||
| 1744 | { USB_DEVICE(0x045b, 0x0247), /* Renesas R-Car D3 USB Download mode */ | ||
| 1731 | .driver_info = DISABLE_ECHO, /* Don't echo banner */ | 1745 | .driver_info = DISABLE_ECHO, /* Don't echo banner */ |
| 1732 | }, | 1746 | }, |
| 1733 | { USB_DEVICE(0x045b, 0x0248), /* Renesas USB Download mode */ | 1747 | { USB_DEVICE(0x045b, 0x0248), /* Renesas R-Car M3-N USB Download mode */ |
| 1734 | .driver_info = DISABLE_ECHO, /* Don't echo banner */ | 1748 | .driver_info = DISABLE_ECHO, /* Don't echo banner */ |
| 1735 | }, | 1749 | }, |
| 1736 | { USB_DEVICE(0x045b, 0x024D), /* Renesas USB Download mode */ | 1750 | { USB_DEVICE(0x045b, 0x024D), /* Renesas R-Car E3 USB Download mode */ |
| 1737 | .driver_info = DISABLE_ECHO, /* Don't echo banner */ | 1751 | .driver_info = DISABLE_ECHO, /* Don't echo banner */ |
| 1738 | }, | 1752 | }, |
| 1739 | { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ | 1753 | { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ |
| @@ -1848,6 +1848,17 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) · 1847 unmodified lines | |||
| 1848 | desc = intf->cur_altsetting; | 1848 | desc = intf->cur_altsetting; |
| 1849 | hdev = interface_to_usbdev(intf); | 1849 | hdev = interface_to_usbdev(intf); |
| 1850 | 1850 | ||
| 1851 | /* | ||
| 1852 | * The USB 2.0 spec prohibits hubs from having more than one | ||
| 1853 | * configuration or interface, and we rely on this prohibition. | ||
| 1854 | * Refuse to accept a device that violates it. | ||
| 1855 | */ | ||
| 1856 | if (hdev->descriptor.bNumConfigurations > 1 || | ||
| 1857 | hdev->actconfig->desc.bNumInterfaces > 1) { | ||
| 1858 | dev_err(&intf->dev, "Invalid hub with more than one config or interface\n"); | ||
| 1859 | return -EINVAL; | ||
| 1860 | } | ||
| 1861 | |||
| 1851 | /* | 1862 | /* |
| 1852 | * Set default autosuspend delay as 0 to speedup bus suspend, | 1863 | * Set default autosuspend delay as 0 to speedup bus suspend, |
| 1853 | * based on the below considerations: | 1864 | * based on the below considerations: |
| @@ -4698,7 +4709,6 @@ void usb_ep0_reinit(struct usb_device *udev) · 2844 unmodified lines | |||
| 4698 | EXPORT_SYMBOL_GPL(usb_ep0_reinit); | 4709 | EXPORT_SYMBOL_GPL(usb_ep0_reinit); |
| 4699 | 4710 | ||
| 4700 | #define usb_sndaddr0pipe() (PIPE_CONTROL << 30) | 4711 | #define usb_sndaddr0pipe() (PIPE_CONTROL << 30) |
| 4701 | #define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN) | ||
| 4702 | 4712 | ||
| 4703 | static int hub_set_address(struct usb_device *udev, int devnum) | 4713 | static int hub_set_address(struct usb_device *udev, int devnum) |
| 4704 | { | 4714 | { |
| @@ -4804,7 +4814,7 @@ static int get_bMaxPacketSize0(struct usb_device *udev, · 99 unmodified lines | |||
| 4804 | for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) { | 4814 | for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) { |
| 4805 | /* Start with invalid values in case the transfer fails */ | 4815 | /* Start with invalid values in case the transfer fails */ |
| 4806 | buf->bDescriptorType = buf->bMaxPacketSize0 = 0; | 4816 | buf->bDescriptorType = buf->bMaxPacketSize0 = 0; |
| 4807 | rc = usb_control_msg(udev, usb_rcvaddr0pipe(), | 4817 | rc = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 4808 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, | 4818 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, |
| 4809 | USB_DT_DEVICE << 8, 0, | 4819 | USB_DT_DEVICE << 8, 0, |
| 4810 | buf, size, | 4820 | buf, size, |
| @@ -435,6 +435,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 434 unmodified lines | |||
| 435 | { USB_DEVICE(0x0c45, 0x7056), .driver_info = | 435 | { USB_DEVICE(0x0c45, 0x7056), .driver_info = |
| 436 | USB_QUIRK_IGNORE_REMOTE_WAKEUP }, | 436 | USB_QUIRK_IGNORE_REMOTE_WAKEUP }, |
| 437 | 437 | ||
| 438 | /* Sony Xperia XZ1 Compact (lilac) smartphone in fastboot mode */ | ||
| 439 | { USB_DEVICE(0x0fce, 0x0dde), .driver_info = USB_QUIRK_NO_LPM }, | ||
| 440 | |||
| 438 | /* Action Semiconductor flash disk */ | 441 | /* Action Semiconductor flash disk */ |
| 439 | { USB_DEVICE(0x10d6, 0x2200), .driver_info = | 442 | { USB_DEVICE(0x10d6, 0x2200), .driver_info = |
| 440 | USB_QUIRK_STRING_FETCH_255 }, | 443 | USB_QUIRK_STRING_FETCH_255 }, |
| @@ -525,6 +528,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 84 unmodified lines | |||
| 525 | /* Blackmagic Design UltraStudio SDI */ | 528 | /* Blackmagic Design UltraStudio SDI */ |
| 526 | { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM }, | 529 | { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM }, |
| 527 | 530 | ||
| 531 | /* Teclast disk */ | ||
| 532 | { USB_DEVICE(0x1f75, 0x0917), .driver_info = USB_QUIRK_NO_LPM }, | ||
| 533 | |||
| 528 | /* Hauppauge HVR-950q */ | 534 | /* Hauppauge HVR-950q */ |
| 529 | { USB_DEVICE(0x2040, 0x7200), .driver_info = | 535 | { USB_DEVICE(0x2040, 0x7200), .driver_info = |
| 530 | USB_QUIRK_CONFIG_INTF_STRINGS }, | 536 | USB_QUIRK_CONFIG_INTF_STRINGS }, |
| @@ -4615,6 +4615,7 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) · 4614 unmodified lines | |||
| 4615 | spin_lock_irqsave(&hsotg->lock, flags); | 4615 | spin_lock_irqsave(&hsotg->lock, flags); |
| 4616 | 4616 | ||
| 4617 | hsotg->driver = NULL; | 4617 | hsotg->driver = NULL; |
| 4618 | hsotg->gadget.dev.of_node = NULL; | ||
| 4618 | hsotg->gadget.speed = USB_SPEED_UNKNOWN; | 4619 | hsotg->gadget.speed = USB_SPEED_UNKNOWN; |
| 4619 | hsotg->enabled = 0; | 4620 | hsotg->enabled = 0; |
| 4620 | 4621 | ||
| @@ -717,6 +717,7 @@ struct dwc3_event_buffer { · 716 unmodified lines | |||
| 717 | /** | 717 | /** |
| 718 | * struct dwc3_ep - device side endpoint representation | 718 | * struct dwc3_ep - device side endpoint representation |
| 719 | * @endpoint: usb endpoint | 719 | * @endpoint: usb endpoint |
| 720 | * @nostream_work: work for handling bulk NoStream | ||
| 720 | * @cancelled_list: list of cancelled requests for this endpoint | 721 | * @cancelled_list: list of cancelled requests for this endpoint |
| 721 | * @pending_list: list of pending requests for this endpoint | 722 | * @pending_list: list of pending requests for this endpoint |
| 722 | * @started_list: list of started requests on this endpoint | 723 | * @started_list: list of started requests on this endpoint |
| @@ -2629,10 +2629,38 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) · 2628 unmodified lines | |||
| 2629 | { | 2629 | { |
| 2630 | u32 reg; | 2630 | u32 reg; |
| 2631 | u32 timeout = 2000; | 2631 | u32 timeout = 2000; |
| 2632 | u32 saved_config = 0; | ||
| 2632 | 2633 | ||
| 2633 | if (pm_runtime_suspended(dwc->dev)) | 2634 | if (pm_runtime_suspended(dwc->dev)) |
| 2634 | return 0; | 2635 | return 0; |
| 2635 | 2636 | ||
| 2637 | /* | ||
| 2638 | * When operating in USB 2.0 speeds (HS/FS), ensure that | ||
| 2639 | * GUSB2PHYCFG.ENBLSLPM and GUSB2PHYCFG.SUSPHY are cleared before starting | ||
| 2640 | * or stopping the controller. This resolves timeout issues that occur | ||
| 2641 | * during frequent role switches between host and device modes. | ||
| 2642 | * | ||
| 2643 | * Save and clear these settings, then restore them after completing the | ||
| 2644 | * controller start or stop sequence. | ||
| 2645 | * | ||
| 2646 | * This solution was discovered through experimentation as it is not | ||
| 2647 | * mentioned in the dwc3 programming guide. It has been tested on an | ||
| 2648 | * Exynos platforms. | ||
| 2649 | */ | ||
| 2650 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | ||
| 2651 | if (reg & DWC3_GUSB2PHYCFG_SUSPHY) { | ||
| 2652 | saved_config |= DWC3_GUSB2PHYCFG_SUSPHY; | ||
| 2653 | reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; | ||
| 2654 | } | ||
| 2655 | |||
| 2656 | if (reg & DWC3_GUSB2PHYCFG_ENBLSLPM) { | ||
| 2657 | saved_config |= DWC3_GUSB2PHYCFG_ENBLSLPM; | ||
| 2658 | reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; | ||
| 2659 | } | ||
| 2660 | |||
| 2661 | if (saved_config) | ||
| 2662 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | ||
| 2663 | |||
| 2636 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | 2664 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 2637 | if (is_on) { | 2665 | if (is_on) { |
| 2638 | if (DWC3_VER_IS_WITHIN(DWC3, ANY, 187A)) { | 2666 | if (DWC3_VER_IS_WITHIN(DWC3, ANY, 187A)) { |
| @@ -2660,6 +2688,12 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) · 21 unmodified lines | |||
| 2660 | reg &= DWC3_DSTS_DEVCTRLHLT; | 2688 | reg &= DWC3_DSTS_DEVCTRLHLT; |
| 2661 | } while (--timeout && !(!is_on ^ !reg)); | 2689 | } while (--timeout && !(!is_on ^ !reg)); |
| 2662 | 2690 | ||
| 2691 | if (saved_config) { | ||
| 2692 | reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | ||
| 2693 | reg |= saved_config; | ||
| 2694 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); | ||
| 2695 | } | ||
| 2696 | |||
| 2663 | if (!timeout) | 2697 | if (!timeout) |
| 2664 | return -ETIMEDOUT; | 2698 | return -ETIMEDOUT; |
| 2665 | 2699 | ||
| @@ -283,7 +283,7 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req) · 282 unmodified lines | |||
| 283 | /* Our transmit completed. See if there's more to go. | 283 | /* Our transmit completed. See if there's more to go. |
| 284 | * f_midi_transmit eats req, don't queue it again. */ | 284 | * f_midi_transmit eats req, don't queue it again. */ |
| 285 | req->length = 0; | 285 | req->length = 0; |
| 286 | f_midi_transmit(midi); | 286 | queue_work(system_highpri_wq, &midi->work); |
| 287 | return; | 287 | return; |
| 288 | } | 288 | } |
| 289 | break; | 289 | break; |
| @@ -907,6 +907,15 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) · 617 unmodified lines | |||
| 907 | 907 | ||
| 908 | status = -ENODEV; | 908 | status = -ENODEV; |
| 909 | 909 | ||
| 910 | /* | ||
| 911 | * Reset wMaxPacketSize with maximum packet size of FS bulk transfer before | ||
| 912 | * endpoint claim. This ensures that the wMaxPacketSize does not exceed the | ||
| 913 | * limit during bind retries where configured dwc3 TX/RX FIFO's maxpacket | ||
| 914 | * size of 512 bytes for IN/OUT endpoints in support HS speed only. | ||
| 915 | */ | ||
| 916 | bulk_in_desc.wMaxPacketSize = cpu_to_le16(64); | ||
| 917 | bulk_out_desc.wMaxPacketSize = cpu_to_le16(64); | ||
| 918 | |||
| 910 | /* allocate instance-specific endpoints */ | 919 | /* allocate instance-specific endpoints */ |
| 911 | midi->in_ep = usb_ep_autoconfig(cdev->gadget, &bulk_in_desc); | 920 | midi->in_ep = usb_ep_autoconfig(cdev->gadget, &bulk_in_desc); |
| 912 | if (!midi->in_ep) | 921 | if (!midi->in_ep) |
| @@ -1000,11 +1009,11 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) · 87 unmodified lines | |||
| 1000 | } | 1009 | } |
| 1001 | 1010 | ||
| 1002 | /* configure the endpoint descriptors ... */ | 1011 | /* configure the endpoint descriptors ... */ |
| 1003 | ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); | 1012 | ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); |
| 1004 | ms_out_desc.bNumEmbMIDIJack = midi->in_ports; | 1013 | ms_out_desc.bNumEmbMIDIJack = midi->out_ports; |
| 1005 | 1014 | ||
| 1006 | ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); | 1015 | ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); |
| 1007 | ms_in_desc.bNumEmbMIDIJack = midi->out_ports; | 1016 | ms_in_desc.bNumEmbMIDIJack = midi->in_ports; |
| 1008 | 1017 | ||
| 1009 | /* ... and add them to the list */ | 1018 | /* ... and add them to the list */ |
| 1010 | endpoint_descriptor_index = i; | 1019 | endpoint_descriptor_index = i; |
| @@ -818,7 +818,7 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc) · 817 unmodified lines | |||
| 818 | return -EINVAL; | 818 | return -EINVAL; |
| 819 | 819 | ||
| 820 | /* Allocate a kthread for asynchronous hw submit handler. */ | 820 | /* Allocate a kthread for asynchronous hw submit handler. */ |
| 821 | video->kworker = kthread_create_worker(0, "UVCG"); | 821 | video->kworker = kthread_run_worker(0, "UVCG"); |
| 822 | if (IS_ERR(video->kworker)) { | 822 | if (IS_ERR(video->kworker)) { |
| 823 | uvcg_err(&video->uvc->func, "failed to create UVCG kworker\n"); | 823 | uvcg_err(&video->uvc->func, "failed to create UVCG kworker\n"); |
| 824 | return PTR_ERR(video->kworker); | 824 | return PTR_ERR(video->kworker); |
| @@ -1543,8 +1543,8 @@ void usb_del_gadget(struct usb_gadget *gadget) · 1542 unmodified lines | |||
| 1543 | 1543 | ||
| 1544 | kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); | 1544 | kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); |
| 1545 | sysfs_remove_link(&udc->dev.kobj, "gadget"); | 1545 | sysfs_remove_link(&udc->dev.kobj, "gadget"); |
| 1546 | flush_work(&gadget->work); | ||
| 1547 | device_del(&gadget->dev); | 1546 | device_del(&gadget->dev); |
| 1547 | flush_work(&gadget->work); | ||
| 1548 | ida_free(&gadget_id_numbers, gadget->id_number); | 1548 | ida_free(&gadget_id_numbers, gadget->id_number); |
| 1549 | cancel_work_sync(&udc->vbus_work); | 1549 | cancel_work_sync(&udc->vbus_work); |
| 1550 | device_unregister(&udc->dev); | 1550 | device_unregister(&udc->dev); |
| @@ -310,7 +310,7 @@ struct renesas_usb3_request { · 309 unmodified lines | |||
| 310 | struct list_head queue; | 310 | struct list_head queue; |
| 311 | }; | 311 | }; |
| 312 | 312 | ||
| 313 | #define USB3_EP_NAME_SIZE 8 | 313 | #define USB3_EP_NAME_SIZE 16 |
| 314 | struct renesas_usb3_ep { | 314 | struct renesas_usb3_ep { |
| 315 | struct usb_ep ep; | 315 | struct usb_ep ep; |
| 316 | struct renesas_usb3 *usb3; | 316 | struct renesas_usb3 *usb3; |
| @@ -958,6 +958,15 @@ static void quirk_usb_disable_ehci(struct pci_dev *pdev) · 957 unmodified lines | |||
| 958 | * booting from USB disk or using a usb keyboard | 958 | * booting from USB disk or using a usb keyboard |
| 959 | */ | 959 | */ |
| 960 | hcc_params = readl(base + EHCI_HCC_PARAMS); | 960 | hcc_params = readl(base + EHCI_HCC_PARAMS); |
| 961 | |||
| 962 | /* LS7A EHCI controller doesn't have extended capabilities, the | ||
| 963 | * EECP (EHCI Extended Capabilities Pointer) field of HCCPARAMS | ||
| 964 | * register should be 0x0 but it reads as 0xa0. So clear it to | ||
| 965 | * avoid error messages on boot. | ||
| 966 | */ | ||
| 967 | if (pdev->vendor == PCI_VENDOR_ID_LOONGSON && pdev->device == 0x7a14) | ||
| 968 | hcc_params &= ~(0xffL << 8); | ||
| 969 | |||
| 961 | offset = (hcc_params >> 8) & 0xff; | 970 | offset = (hcc_params >> 8) & 0xff; |
| 962 | while (offset && --count) { | 971 | while (offset && --count) { |
| 963 | pci_read_config_dword(pdev, offset, &cap); | 972 | pci_read_config_dword(pdev, offset, &cap); |
| @@ -653,8 +653,8 @@ put_runtime_pm: · 652 unmodified lines | |||
| 653 | } | 653 | } |
| 654 | EXPORT_SYMBOL_NS_GPL(xhci_pci_common_probe, "xhci"); | 654 | EXPORT_SYMBOL_NS_GPL(xhci_pci_common_probe, "xhci"); |
| 655 | 655 | ||
| 656 | static const struct pci_device_id pci_ids_reject[] = { | 656 | /* handled by xhci-pci-renesas if enabled */ |
| 657 | /* handled by xhci-pci-renesas */ | 657 | static const struct pci_device_id pci_ids_renesas[] = { |
| 658 | { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014) }, | 658 | { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014) }, |
| 659 | { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015) }, | 659 | { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015) }, |
| 660 | { /* end: all zeroes */ } | 660 | { /* end: all zeroes */ } |
| @@ -662,7 +662,8 @@ static const struct pci_device_id pci_ids_reject[] = { · 1 unmodified line | |||
| 662 | 662 | ||
| 663 | static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | 663 | static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) |
| 664 | { | 664 | { |
| 665 | if (pci_match_id(pci_ids_reject, dev)) | 665 | if (IS_ENABLED(CONFIG_USB_XHCI_PCI_RENESAS) && |
| 666 | pci_match_id(pci_ids_renesas, dev)) | ||
| 666 | return -ENODEV; | 667 | return -ENODEV; |
| 667 | 668 | ||
| 668 | return xhci_pci_common_probe(dev, id); | 669 | return xhci_pci_common_probe(dev, id); |
| @@ -212,7 +212,7 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop) · 211 unmodified lines | |||
| 212 | if (of_property_read_u32(node, "clock-frequency", &clk_rate)) | 212 | if (of_property_read_u32(node, "clock-frequency", &clk_rate)) |
| 213 | clk_rate = 0; | 213 | clk_rate = 0; |
| 214 | 214 | ||
| 215 | needs_clk = of_property_read_bool(node, "clocks"); | 215 | needs_clk = of_property_present(node, "clocks"); |
| 216 | } | 216 | } |
| 217 | nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset", | 217 | nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset", |
| 218 | GPIOD_ASIS); | 218 | GPIOD_ASIS); |
| @@ -387,8 +387,11 @@ usb_role_switch_register(struct device *parent, · 386 unmodified lines | |||
| 387 | dev_set_name(&sw->dev, "%s-role-switch", | 387 | dev_set_name(&sw->dev, "%s-role-switch", |
| 388 | desc->name ? desc->name : dev_name(parent)); | 388 | desc->name ? desc->name : dev_name(parent)); |
| 389 | 389 | ||
| 390 | sw->registered = true; | ||
| 391 | |||
| 390 | ret = device_register(&sw->dev); | 392 | ret = device_register(&sw->dev); |
| 391 | if (ret) { | 393 | if (ret) { |
| 394 | sw->registered = false; | ||
| 392 | put_device(&sw->dev); | 395 | put_device(&sw->dev); |
| 393 | return ERR_PTR(ret); | 396 | return ERR_PTR(ret); |
| 394 | } | 397 | } |
| @@ -399,8 +402,6 @@ usb_role_switch_register(struct device *parent, · 4 unmodified lines | |||
| 399 | dev_warn(&sw->dev, "failed to add component\n"); | 402 | dev_warn(&sw->dev, "failed to add component\n"); |
| 400 | } | 403 | } |
| 401 | 404 | ||
| 402 | sw->registered = true; | ||
| 403 | |||
| 404 | /* TODO: Symlinks for the host port and the device controller. */ | 405 | /* TODO: Symlinks for the host port and the device controller. */ |
| 405 | 406 | ||
| 406 | return sw; | 407 | return sw; |
| @@ -619,15 +619,6 @@ static void option_instat_callback(struct urb *urb); · 618 unmodified lines | |||
| 619 | /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */ | 619 | /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */ |
| 620 | #define LUAT_PRODUCT_AIR720U 0x4e00 | 620 | #define LUAT_PRODUCT_AIR720U 0x4e00 |
| 621 | 621 | ||
| 622 | /* MeiG Smart Technology products */ | ||
| 623 | #define MEIGSMART_VENDOR_ID 0x2dee | ||
| 624 | /* MeiG Smart SRM815/SRM825L based on Qualcomm 315 */ | ||
| 625 | #define MEIGSMART_PRODUCT_SRM825L 0x4d22 | ||
| 626 | /* MeiG Smart SLM320 based on UNISOC UIS8910 */ | ||
| 627 | #define MEIGSMART_PRODUCT_SLM320 0x4d41 | ||
| 628 | /* MeiG Smart SLM770A based on ASR1803 */ | ||
| 629 | #define MEIGSMART_PRODUCT_SLM770A 0x4d57 | ||
| 630 | |||
| 631 | /* Device flags */ | 622 | /* Device flags */ |
| 632 | 623 | ||
| 633 | /* Highest interface number which can be used with NCTRL() and RSVD() */ | 624 | /* Highest interface number which can be used with NCTRL() and RSVD() */ |
| @@ -1367,15 +1358,15 @@ static const struct usb_device_id option_ids[] = { · 733 unmodified lines | |||
| 1367 | .driver_info = NCTRL(2) | RSVD(3) }, | 1358 | .driver_info = NCTRL(2) | RSVD(3) }, |
| 1368 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */ | 1359 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */ |
| 1369 | .driver_info = NCTRL(0) | RSVD(1) }, | 1360 | .driver_info = NCTRL(0) | RSVD(1) }, |
| 1370 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990 (rmnet) */ | 1361 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990A (rmnet) */ |
| 1371 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, | 1362 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, |
| 1372 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990 (MBIM) */ | 1363 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990A (MBIM) */ |
| 1373 | .driver_info = NCTRL(0) | RSVD(1) }, | 1364 | .driver_info = NCTRL(0) | RSVD(1) }, |
| 1374 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990 (RNDIS) */ | 1365 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990A (RNDIS) */ |
| 1375 | .driver_info = NCTRL(2) | RSVD(3) }, | 1366 | .driver_info = NCTRL(2) | RSVD(3) }, |
| 1376 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */ | 1367 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990A (ECM) */ |
| 1377 | .driver_info = NCTRL(0) | RSVD(1) }, | 1368 | .driver_info = NCTRL(0) | RSVD(1) }, |
| 1378 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */ | 1369 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990A (PCIe) */ |
| 1379 | .driver_info = RSVD(0) }, | 1370 | .driver_info = RSVD(0) }, |
| 1380 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */ | 1371 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */ |
| 1381 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, | 1372 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, |
| @@ -1403,6 +1394,22 @@ static const struct usb_device_id option_ids[] = { · 21 unmodified lines | |||
| 1403 | .driver_info = RSVD(0) | NCTRL(3) }, | 1394 | .driver_info = RSVD(0) | NCTRL(3) }, |
| 1404 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */ | 1395 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */ |
| 1405 | .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, | 1396 | .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, |
| 1397 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d0, 0x60) }, /* Telit FN990B (rmnet) */ | ||
| 1398 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d0, 0x40) }, | ||
| 1399 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d0, 0x30), | ||
| 1400 | .driver_info = NCTRL(5) }, | ||
| 1401 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d1, 0x60) }, /* Telit FN990B (MBIM) */ | ||
| 1402 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d1, 0x40) }, | ||
| 1403 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d1, 0x30), | ||
| 1404 | .driver_info = NCTRL(6) }, | ||
| 1405 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d2, 0x60) }, /* Telit FN990B (RNDIS) */ | ||
| 1406 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d2, 0x40) }, | ||
| 1407 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d2, 0x30), | ||
| 1408 | .driver_info = NCTRL(6) }, | ||
| 1409 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d3, 0x60) }, /* Telit FN990B (ECM) */ | ||
| 1410 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d3, 0x40) }, | ||
| 1411 | { USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d3, 0x30), | ||
| 1412 | .driver_info = NCTRL(6) }, | ||
| 1406 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), | 1413 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), |
| 1407 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, | 1414 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, |
| 1408 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), | 1415 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), |
| @@ -2347,6 +2354,14 @@ static const struct usb_device_id option_ids[] = { · 938 unmodified lines | |||
| 2347 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */ | 2354 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */ |
| 2348 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */ | 2355 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */ |
| 2349 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */ | 2356 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */ |
| 2357 | { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d41, 0xff, 0, 0) }, /* MeiG Smart SLM320 */ | ||
| 2358 | { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d57, 0xff, 0, 0) }, /* MeiG Smart SLM770A */ | ||
| 2359 | { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0, 0) }, /* MeiG Smart SRM815 */ | ||
| 2360 | { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0x10, 0x02) }, /* MeiG Smart SLM828 */ | ||
| 2361 | { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0x10, 0x03) }, /* MeiG Smart SLM828 */ | ||
| 2362 | { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x30) }, /* MeiG Smart SRM815 and SRM825L */ | ||
| 2363 | { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x40) }, /* MeiG Smart SRM825L */ | ||
| 2364 | { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x60) }, /* MeiG Smart SRM825L */ | ||
| 2350 | { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ | 2365 | { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ |
| 2351 | { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ | 2366 | { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ |
| 2352 | { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ | 2367 | { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ |
| @@ -2403,12 +2418,6 @@ static const struct usb_device_id option_ids[] = { · 50 unmodified lines | |||
| 2403 | { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, | 2418 | { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, |
| 2404 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, | 2419 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, |
| 2405 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, | 2420 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, |
| 2406 | { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) }, | ||
| 2407 | { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM770A, 0xff, 0, 0) }, | ||
| 2408 | { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0, 0) }, | ||
| 2409 | { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) }, | ||
| 2410 | { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) }, | ||
| 2411 | { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) }, | ||
| 2412 | { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */ | 2421 | { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */ |
| 2413 | .driver_info = NCTRL(1) }, | 2422 | .driver_info = NCTRL(1) }, |
| 2414 | { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0640, 0xff), /* TCL IK512 ECM */ | 2423 | { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0640, 0xff), /* TCL IK512 ECM */ |
| @@ -5591,8 +5591,7 @@ static void run_state_machine(struct tcpm_port *port) · 5590 unmodified lines | |||
| 5591 | tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, | 5591 | tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, |
| 5592 | port->pps_data.active, 0); | 5592 | port->pps_data.active, 0); |
| 5593 | tcpm_set_charge(port, false); | 5593 | tcpm_set_charge(port, false); |
| 5594 | tcpm_set_state(port, hard_reset_state(port), | 5594 | tcpm_set_state(port, ERROR_RECOVERY, port->timings.ps_src_off_time); |
| 5595 | port->timings.ps_src_off_time); | ||
| 5596 | break; | 5595 | break; |
| 5597 | case PR_SWAP_SNK_SRC_SOURCE_ON: | 5596 | case PR_SWAP_SNK_SRC_SOURCE_ON: |
| 5598 | tcpm_enable_auto_vbus_discharge(port, true); | 5597 | tcpm_enable_auto_vbus_discharge(port, true); |
| @@ -74,19 +74,21 @@ static inline phys_addr_t xen_dma_to_phys(struct device *dev, · 73 unmodified lines | |||
| 74 | return xen_bus_to_phys(dev, dma_to_phys(dev, dma_addr)); | 74 | return xen_bus_to_phys(dev, dma_to_phys(dev, dma_addr)); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | static inline bool range_requires_alignment(phys_addr_t p, size_t size) | ||
| 78 | { | ||
| 79 | phys_addr_t algn = 1ULL << (get_order(size) + PAGE_SHIFT); | ||
| 80 | phys_addr_t bus_addr = pfn_to_bfn(XEN_PFN_DOWN(p)) << XEN_PAGE_SHIFT; | ||
| 81 | |||
| 82 | return IS_ALIGNED(p, algn) && !IS_ALIGNED(bus_addr, algn); | ||
| 83 | } | ||
| 84 | |||
| 77 | static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) | 85 | static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) |
| 78 | { | 86 | { |
| 79 | unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p); | 87 | unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p); |
| 80 | unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size); | 88 | unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size); |
| 81 | phys_addr_t algn = 1ULL << (get_order(size) + PAGE_SHIFT); | ||
| 82 | 89 | ||
| 83 | next_bfn = pfn_to_bfn(xen_pfn); | 90 | next_bfn = pfn_to_bfn(xen_pfn); |
| 84 | 91 | ||
| 85 | /* If buffer is physically aligned, ensure DMA alignment. */ | ||
| 86 | if (IS_ALIGNED(p, algn) && | ||
| 87 | !IS_ALIGNED((phys_addr_t)next_bfn << XEN_PAGE_SHIFT, algn)) | ||
| 88 | return 1; | ||
| 89 | |||
| 90 | for (i = 1; i < nr_pages; i++) | 92 | for (i = 1; i < nr_pages; i++) |
| 91 | if (pfn_to_bfn(++xen_pfn) != ++next_bfn) | 93 | if (pfn_to_bfn(++xen_pfn) != ++next_bfn) |
| 92 | return 1; | 94 | return 1; |
| @@ -111,7 +113,7 @@ static struct io_tlb_pool *xen_swiotlb_find_pool(struct device *dev, · 18 unmodified lines | |||
| 111 | } | 113 | } |
| 112 | 114 | ||
| 113 | #ifdef CONFIG_X86 | 115 | #ifdef CONFIG_X86 |
| 114 | int xen_swiotlb_fixup(void *buf, unsigned long nslabs) | 116 | int __init xen_swiotlb_fixup(void *buf, unsigned long nslabs) |
| 115 | { | 117 | { |
| 116 | int rc; | 118 | int rc; |
| 117 | unsigned int order = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT); | 119 | unsigned int order = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT); |
| @@ -156,7 +158,8 @@ xen_swiotlb_alloc_coherent(struct device *dev, size_t size, · 38 unmodified lines | |||
| 156 | 158 | ||
| 157 | *dma_handle = xen_phys_to_dma(dev, phys); | 159 | *dma_handle = xen_phys_to_dma(dev, phys); |
| 158 | if (*dma_handle + size - 1 > dma_mask || | 160 | if (*dma_handle + size - 1 > dma_mask || |
| 159 | range_straddles_page_boundary(phys, size)) { | 161 | range_straddles_page_boundary(phys, size) || |
| 162 | range_requires_alignment(phys, size)) { | ||
| 160 | if (xen_create_contiguous_region(phys, order, fls64(dma_mask), | 163 | if (xen_create_contiguous_region(phys, order, fls64(dma_mask), |
| 161 | dma_handle) != 0) | 164 | dma_handle) != 0) |
| 162 | goto out_free_pages; | 165 | goto out_free_pages; |
| @@ -182,7 +185,8 @@ xen_swiotlb_free_coherent(struct device *dev, size_t size, void *vaddr, · 19 unmodified lines | |||
| 182 | size = ALIGN(size, XEN_PAGE_SIZE); | 185 | size = ALIGN(size, XEN_PAGE_SIZE); |
| 183 | 186 | ||
| 184 | if (WARN_ON_ONCE(dma_handle + size - 1 > dev->coherent_dma_mask) || | 187 | if (WARN_ON_ONCE(dma_handle + size - 1 > dev->coherent_dma_mask) || |
| 185 | WARN_ON_ONCE(range_straddles_page_boundary(phys, size))) | 188 | WARN_ON_ONCE(range_straddles_page_boundary(phys, size) || |
| 189 | range_requires_alignment(phys, size))) | ||
| 186 | return; | 190 | return; |
| 187 | 191 | ||
| 188 | if (TestClearPageXenRemapped(virt_to_page(vaddr))) | 192 | if (TestClearPageXenRemapped(virt_to_page(vaddr))) |
| @@ -61,6 +61,13 @@ config BCACHEFS_DEBUG · 60 unmodified lines | |||
| 61 | The resulting code will be significantly slower than normal; you | 61 | The resulting code will be significantly slower than normal; you |
| 62 | probably shouldn't select this option unless you're a developer. | 62 | probably shouldn't select this option unless you're a developer. |
| 63 | 63 | ||
| 64 | config BCACHEFS_INJECT_TRANSACTION_RESTARTS | ||
| 65 | bool "Randomly inject transaction restarts" | ||
| 66 | depends on BCACHEFS_DEBUG | ||
| 67 | help | ||
| 68 | Randomly inject transaction restarts in a few core paths - may have a | ||
| 69 | significant performance penalty | ||
| 70 | |||
| 64 | config BCACHEFS_TESTS | 71 | config BCACHEFS_TESTS |
| 65 | bool "bcachefs unit and performance tests" | 72 | bool "bcachefs unit and performance tests" |
| 66 | depends on BCACHEFS_FS | 73 | depends on BCACHEFS_FS |
| @@ -1803,7 +1803,6 @@ struct discard_buckets_state { · 1802 unmodified lines | |||
| 1803 | u64 open; | 1803 | u64 open; |
| 1804 | u64 need_journal_commit; | 1804 | u64 need_journal_commit; |
| 1805 | u64 discarded; | 1805 | u64 discarded; |
| 1806 | u64 need_journal_commit_this_dev; | ||
| 1807 | }; | 1806 | }; |
| 1808 | 1807 | ||
| 1809 | static int bch2_discard_one_bucket(struct btree_trans *trans, | 1808 | static int bch2_discard_one_bucket(struct btree_trans *trans, |
| @@ -1827,11 +1826,11 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, · 17 unmodified lines | |||
| 1827 | goto out; | 1826 | goto out; |
| 1828 | } | 1827 | } |
| 1829 | 1828 | ||
| 1830 | if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal, | 1829 | u64 seq_ready = bch2_bucket_journal_seq_ready(&c->buckets_waiting_for_journal, |
| 1831 | c->journal.flushed_seq_ondisk, | 1830 | pos.inode, pos.offset); |
| 1832 | pos.inode, pos.offset)) { | 1831 | if (seq_ready > c->journal.flushed_seq_ondisk) { |
| 1833 | s->need_journal_commit++; | 1832 | if (seq_ready > c->journal.flushing_seq) |
| 1834 | s->need_journal_commit_this_dev++; | 1833 | s->need_journal_commit++; |
| 1835 | goto out; | 1834 | goto out; |
| 1836 | } | 1835 | } |
| 1837 | 1836 | ||
| @@ -1865,23 +1864,24 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, · 27 unmodified lines | |||
| 1865 | discard_locked = true; | 1864 | discard_locked = true; |
| 1866 | } | 1865 | } |
| 1867 | 1866 | ||
| 1868 | if (!bkey_eq(*discard_pos_done, iter.pos) && | 1867 | if (!bkey_eq(*discard_pos_done, iter.pos)) { |
| 1869 | ca->mi.discard && !c->opts.nochanges) { | ||
| 1870 | /* | ||
| 1871 | * This works without any other locks because this is the only | ||
| 1872 | * thread that removes items from the need_discard tree | ||
| 1873 | */ | ||
| 1874 | bch2_trans_unlock_long(trans); | ||
| 1875 | blkdev_issue_discard(ca->disk_sb.bdev, | ||
| 1876 | k.k->p.offset * ca->mi.bucket_size, | ||
| 1877 | ca->mi.bucket_size, | ||
| 1878 | GFP_KERNEL); | ||
| 1879 | *discard_pos_done = iter.pos; | ||
| 1880 | s->discarded++; | 1868 | s->discarded++; |
| 1869 | *discard_pos_done = iter.pos; | ||
| 1881 | 1870 | ||
| 1882 | ret = bch2_trans_relock_notrace(trans); | 1871 | if (ca->mi.discard && !c->opts.nochanges) { |
| 1883 | if (ret) | 1872 | /* |
| 1884 | goto out; | 1873 | * This works without any other locks because this is the only |
| 1874 | * thread that removes items from the need_discard tree | ||
| 1875 | */ | ||
| 1876 | bch2_trans_unlock_long(trans); | ||
| 1877 | blkdev_issue_discard(ca->disk_sb.bdev, | ||
| 1878 | k.k->p.offset * ca->mi.bucket_size, | ||
| 1879 | ca->mi.bucket_size, | ||
| 1880 | GFP_KERNEL); | ||
| 1881 | ret = bch2_trans_relock_notrace(trans); | ||
| 1882 | if (ret) | ||
| 1883 | goto out; | ||
| 1884 | } | ||
| 1885 | } | 1885 | } |
| 1886 | 1886 | ||
| 1887 | SET_BCH_ALLOC_V4_NEED_DISCARD(&a->v, false); | 1887 | SET_BCH_ALLOC_V4_NEED_DISCARD(&a->v, false); |
| @@ -1929,6 +1929,9 @@ static void bch2_do_discards_work(struct work_struct *work) · 41 unmodified lines | |||
| 1929 | POS(ca->dev_idx, U64_MAX), 0, k, | 1929 | POS(ca->dev_idx, U64_MAX), 0, k, |
| 1930 | bch2_discard_one_bucket(trans, ca, &iter, &discard_pos_done, &s, false))); | 1930 | bch2_discard_one_bucket(trans, ca, &iter, &discard_pos_done, &s, false))); |
| 1931 | 1931 | ||
| 1932 | if (s.need_journal_commit > dev_buckets_available(ca, BCH_WATERMARK_normal)) | ||
| 1933 | bch2_journal_flush_async(&c->journal, NULL); | ||
| 1934 | |||
| 1932 | trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded, | 1935 | trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded, |
| 1933 | bch2_err_str(ret)); | 1936 | bch2_err_str(ret)); |
| 1934 | 1937 | ||
| @@ -2024,7 +2027,7 @@ static void bch2_do_discards_fast_work(struct work_struct *work) · 89 unmodified lines | |||
| 2024 | break; | 2027 | break; |
| 2025 | } | 2028 | } |
| 2026 | 2029 | ||
| 2027 | trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret)); | 2030 | trace_discard_buckets_fast(c, s.seen, s.open, s.need_journal_commit, s.discarded, bch2_err_str(ret)); |
| 2028 | 2031 | ||
| 2029 | bch2_trans_put(trans); | 2032 | bch2_trans_put(trans); |
| 2030 | percpu_ref_put(&ca->io_ref); | 2033 | percpu_ref_put(&ca->io_ref); |
| @@ -205,8 +205,12 @@ static inline bool may_alloc_bucket(struct bch_fs *c, · 204 unmodified lines | |||
| 205 | return false; | 205 | return false; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal, | 208 | u64 journal_seq_ready = |
| 209 | c->journal.flushed_seq_ondisk, bucket.inode, bucket.offset)) { | 209 | bch2_bucket_journal_seq_ready(&c->buckets_waiting_for_journal, |
| 210 | bucket.inode, bucket.offset); | ||
| 211 | if (journal_seq_ready > c->journal.flushed_seq_ondisk) { | ||
| 212 | if (journal_seq_ready > c->journal.flushing_seq) | ||
| 213 | s->need_journal_commit++; | ||
| 210 | s->skipped_need_journal_commit++; | 214 | s->skipped_need_journal_commit++; |
| 211 | return false; | 215 | return false; |
| 212 | } | 216 | } |
| @@ -570,7 +574,7 @@ alloc: · 357 unmodified lines | |||
| 570 | ? bch2_bucket_alloc_freelist(trans, ca, watermark, &s, cl) | 574 | ? bch2_bucket_alloc_freelist(trans, ca, watermark, &s, cl) |
| 571 | : bch2_bucket_alloc_early(trans, ca, watermark, &s, cl); | 575 | : bch2_bucket_alloc_early(trans, ca, watermark, &s, cl); |
| 572 | 576 | ||
| 573 | if (s.skipped_need_journal_commit * 2 > avail) | 577 | if (s.need_journal_commit * 2 > avail) |
| 574 | bch2_journal_flush_async(&c->journal, NULL); | 578 | bch2_journal_flush_async(&c->journal, NULL); |
| 575 | 579 | ||
| 576 | if (!ob && s.btree_bitmap != BTREE_BITMAP_ANY) { | 580 | if (!ob && s.btree_bitmap != BTREE_BITMAP_ANY) { |
| @@ -18,6 +18,7 @@ struct bucket_alloc_state { · 17 unmodified lines | |||
| 18 | u64 buckets_seen; | 18 | u64 buckets_seen; |
| 19 | u64 skipped_open; | 19 | u64 skipped_open; |
| 20 | u64 skipped_need_journal_commit; | 20 | u64 skipped_need_journal_commit; |
| 21 | u64 need_journal_commit; | ||
| 21 | u64 skipped_nocow; | 22 | u64 skipped_nocow; |
| 22 | u64 skipped_nouse; | 23 | u64 skipped_nouse; |
| 23 | u64 skipped_mi_btree_bitmap; | 24 | u64 skipped_mi_btree_bitmap; |
| @@ -2357,6 +2357,12 @@ struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos en · 2356 unmodified lines | |||
| 2357 | bch2_btree_iter_verify_entry_exit(iter); | 2357 | bch2_btree_iter_verify_entry_exit(iter); |
| 2358 | EBUG_ON((iter->flags & BTREE_ITER_filter_snapshots) && bkey_eq(end, POS_MAX)); | 2358 | EBUG_ON((iter->flags & BTREE_ITER_filter_snapshots) && bkey_eq(end, POS_MAX)); |
| 2359 | 2359 | ||
| 2360 | ret = trans_maybe_inject_restart(trans, _RET_IP_); | ||
| 2361 | if (unlikely(ret)) { | ||
| 2362 | k = bkey_s_c_err(ret); | ||
| 2363 | goto out_no_locked; | ||
| 2364 | } | ||
| 2365 | |||
| 2360 | if (iter->update_path) { | 2366 | if (iter->update_path) { |
| 2361 | bch2_path_put_nokeep(trans, iter->update_path, | 2367 | bch2_path_put_nokeep(trans, iter->update_path, |
| 2362 | iter->flags & BTREE_ITER_intent); | 2368 | iter->flags & BTREE_ITER_intent); |
| @@ -2622,6 +2628,12 @@ struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bp · 259 unmodified lines | |||
| 2622 | bch2_btree_iter_verify_entry_exit(iter); | 2628 | bch2_btree_iter_verify_entry_exit(iter); |
| 2623 | EBUG_ON((iter->flags & BTREE_ITER_filter_snapshots) && bpos_eq(end, POS_MIN)); | 2629 | EBUG_ON((iter->flags & BTREE_ITER_filter_snapshots) && bpos_eq(end, POS_MIN)); |
| 2624 | 2630 | ||
| 2631 | int ret = trans_maybe_inject_restart(trans, _RET_IP_); | ||
| 2632 | if (unlikely(ret)) { | ||
| 2633 | k = bkey_s_c_err(ret); | ||
| 2634 | goto out_no_locked; | ||
| 2635 | } | ||
| 2636 | |||
| 2625 | while (1) { | 2637 | while (1) { |
| 2626 | k = __bch2_btree_iter_peek_prev(iter, search_key); | 2638 | k = __bch2_btree_iter_peek_prev(iter, search_key); |
| 2627 | if (unlikely(!k.k)) | 2639 | if (unlikely(!k.k)) |
| @@ -2749,6 +2761,12 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter) · 121 unmodified lines | |||
| 2749 | bch2_btree_iter_verify_entry_exit(iter); | 2761 | bch2_btree_iter_verify_entry_exit(iter); |
| 2750 | EBUG_ON(btree_iter_path(trans, iter)->level && (iter->flags & BTREE_ITER_with_key_cache)); | 2762 | EBUG_ON(btree_iter_path(trans, iter)->level && (iter->flags & BTREE_ITER_with_key_cache)); |
| 2751 | 2763 | ||
| 2764 | ret = trans_maybe_inject_restart(trans, _RET_IP_); | ||
| 2765 | if (unlikely(ret)) { | ||
| 2766 | k = bkey_s_c_err(ret); | ||
| 2767 | goto out_no_locked; | ||
| 2768 | } | ||
| 2769 | |||
| 2752 | /* extents can't span inode numbers: */ | 2770 | /* extents can't span inode numbers: */ |
| 2753 | if ((iter->flags & BTREE_ITER_is_extents) && | 2771 | if ((iter->flags & BTREE_ITER_is_extents) && |
| 2754 | unlikely(iter->pos.offset == KEY_OFFSET_MAX)) { | 2772 | unlikely(iter->pos.offset == KEY_OFFSET_MAX)) { |
| @@ -3106,6 +3124,10 @@ void *__bch2_trans_kmalloc(struct btree_trans *trans, size_t size) · 351 unmodified lines | |||
| 3106 | 3124 | ||
| 3107 | WARN_ON_ONCE(new_bytes > BTREE_TRANS_MEM_MAX); | 3125 | WARN_ON_ONCE(new_bytes > BTREE_TRANS_MEM_MAX); |
| 3108 | 3126 | ||
| 3127 | ret = trans_maybe_inject_restart(trans, _RET_IP_); | ||
| 3128 | if (ret) | ||
| 3129 | return ERR_PTR(ret); | ||
| 3130 | |||
| 3109 | struct btree_transaction_stats *s = btree_trans_stats(trans); | 3131 | struct btree_transaction_stats *s = btree_trans_stats(trans); |
| 3110 | s->max_mem = max(s->max_mem, new_bytes); | 3132 | s->max_mem = max(s->max_mem, new_bytes); |
| 3111 | 3133 | ||
| @@ -3163,7 +3185,8 @@ out_new_mem: · 51 unmodified lines | |||
| 3163 | 3185 | ||
| 3164 | if (old_bytes) { | 3186 | if (old_bytes) { |
| 3165 | trace_and_count(c, trans_restart_mem_realloced, trans, _RET_IP_, new_bytes); | 3187 | trace_and_count(c, trans_restart_mem_realloced, trans, _RET_IP_, new_bytes); |
| 3166 | return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_mem_realloced)); | 3188 | return ERR_PTR(btree_trans_restart_ip(trans, |
| 3189 | BCH_ERR_transaction_restart_mem_realloced, _RET_IP_)); | ||
| 3167 | } | 3190 | } |
| 3168 | out_change_top: | 3191 | out_change_top: |
| 3169 | p = trans->mem + trans->mem_top; | 3192 | p = trans->mem + trans->mem_top; |
| @@ -3271,6 +3294,14 @@ u32 bch2_trans_begin(struct btree_trans *trans) · 101 unmodified lines | |||
| 3271 | 3294 | ||
| 3272 | trans->last_begin_ip = _RET_IP_; | 3295 | trans->last_begin_ip = _RET_IP_; |
| 3273 | 3296 | ||
| 3297 | #ifdef CONFIG_BCACHEFS_INJECT_TRANSACTION_RESTARTS | ||
| 3298 | if (trans->restarted) { | ||
| 3299 | trans->restart_count_this_trans++; | ||
| 3300 | } else { | ||
| 3301 | trans->restart_count_this_trans = 0; | ||
| 3302 | } | ||
| 3303 | #endif | ||
| 3304 | |||
| 3274 | trans_set_locked(trans, false); | 3305 | trans_set_locked(trans, false); |
| 3275 | 3306 | ||
| 3276 | if (trans->restarted) { | 3307 | if (trans->restarted) { |
| @@ -355,6 +355,18 @@ static int btree_trans_restart(struct btree_trans *trans, int err) · 354 unmodified lines | |||
| 355 | return btree_trans_restart_ip(trans, err, _THIS_IP_); | 355 | return btree_trans_restart_ip(trans, err, _THIS_IP_); |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | static inline int trans_maybe_inject_restart(struct btree_trans *trans, unsigned long ip) | ||
| 359 | { | ||
| 360 | #ifdef CONFIG_BCACHEFS_INJECT_TRANSACTION_RESTARTS | ||
| 361 | if (!(ktime_get_ns() & ~(~0ULL << min(63, (10 + trans->restart_count_this_trans))))) { | ||
| 362 | trace_and_count(trans->c, trans_restart_injected, trans, ip); | ||
| 363 | return btree_trans_restart_ip(trans, | ||
| 364 | BCH_ERR_transaction_restart_fault_inject, ip); | ||
| 365 | } | ||
| 366 | #endif | ||
| 367 | return 0; | ||
| 368 | } | ||
| 369 | |||
| 358 | bool bch2_btree_node_upgrade(struct btree_trans *, | 370 | bool bch2_btree_node_upgrade(struct btree_trans *, |
| 359 | struct btree_path *, unsigned); | 371 | struct btree_path *, unsigned); |
| 360 | 372 | ||
| @@ -739,7 +751,7 @@ transaction_restart: \ · 378 unmodified lines | |||
| 739 | if (!_ret2) \ | 751 | if (!_ret2) \ |
| 740 | bch2_trans_verify_not_restarted(_trans, _restart_count);\ | 752 | bch2_trans_verify_not_restarted(_trans, _restart_count);\ |
| 741 | \ | 753 | \ |
| 742 | _ret2 ?: trans_was_restarted(_trans, _restart_count); \ | 754 | _ret2 ?: trans_was_restarted(_trans, _orig_restart_count); \ |
| 743 | }) | 755 | }) |
| 744 | 756 | ||
| 745 | #define for_each_btree_key_max_continue(_trans, _iter, \ | 757 | #define for_each_btree_key_max_continue(_trans, _iter, \ |
| @@ -748,7 +748,6 @@ void bch2_fs_btree_key_cache_exit(struct btree_key_cache *bc) · 747 unmodified lines | |||
| 748 | rcu_read_unlock(); | 748 | rcu_read_unlock(); |
| 749 | mutex_lock(&bc->table.mutex); | 749 | mutex_lock(&bc->table.mutex); |
| 750 | mutex_unlock(&bc->table.mutex); | 750 | mutex_unlock(&bc->table.mutex); |
| 751 | rcu_read_lock(); | ||
| 752 | continue; | 751 | continue; |
| 753 | } | 752 | } |
| 754 | for (i = 0; i < tbl->size; i++) | 753 | for (i = 0; i < tbl->size; i++) |
| @@ -999,6 +999,10 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags) · 998 unmodified lines | |||
| 999 | 999 | ||
| 1000 | bch2_trans_verify_not_unlocked_or_in_restart(trans); | 1000 | bch2_trans_verify_not_unlocked_or_in_restart(trans); |
| 1001 | 1001 | ||
| 1002 | ret = trans_maybe_inject_restart(trans, _RET_IP_); | ||
| 1003 | if (unlikely(ret)) | ||
| 1004 | goto out_reset; | ||
| 1005 | |||
| 1002 | if (!trans->nr_updates && | 1006 | if (!trans->nr_updates && |
| 1003 | !trans->journal_entries_u64s) | 1007 | !trans->journal_entries_u64s) |
| 1004 | goto out_reset; | 1008 | goto out_reset; |
| @@ -509,6 +509,9 @@ struct btree_trans { · 508 unmodified lines | |||
| 509 | bool notrace_relock_fail:1; | 509 | bool notrace_relock_fail:1; |
| 510 | enum bch_errcode restarted:16; | 510 | enum bch_errcode restarted:16; |
| 511 | u32 restart_count; | 511 | u32 restart_count; |
| 512 | #ifdef CONFIG_BCACHEFS_INJECT_TRANSACTION_RESTARTS | ||
| 513 | u32 restart_count_this_trans; | ||
| 514 | #endif | ||
| 512 | 515 | ||
| 513 | u64 last_begin_time; | 516 | u64 last_begin_time; |
| 514 | unsigned long last_begin_ip; | 517 | unsigned long last_begin_ip; |
| @@ -681,9 +681,11 @@ static void btree_update_nodes_written(struct btree_update *as) · 680 unmodified lines | |||
| 681 | 681 | ||
| 682 | b = as->old_nodes[i]; | 682 | b = as->old_nodes[i]; |
| 683 | 683 | ||
| 684 | bch2_trans_begin(trans); | ||
| 684 | btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read); | 685 | btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read); |
| 685 | seq = b->data ? b->data->keys.seq : 0; | 686 | seq = b->data ? b->data->keys.seq : 0; |
| 686 | six_unlock_read(&b->c.lock); | 687 | six_unlock_read(&b->c.lock); |
| 688 | bch2_trans_unlock_long(trans); | ||
| 687 | 689 | ||
| 688 | if (seq == as->old_nodes_seq[i]) | 690 | if (seq == as->old_nodes_seq[i]) |
| 689 | wait_on_bit_io(&b->flags, BTREE_NODE_write_in_flight_inner, | 691 | wait_on_bit_io(&b->flags, BTREE_NODE_write_in_flight_inner, |
| @@ -278,12 +278,12 @@ static inline struct btree_node_entry *want_new_bset(struct bch_fs *c, struct bt · 277 unmodified lines | |||
| 278 | { | 278 | { |
| 279 | struct bset_tree *t = bset_tree_last(b); | 279 | struct bset_tree *t = bset_tree_last(b); |
| 280 | struct btree_node_entry *bne = max(write_block(b), | 280 | struct btree_node_entry *bne = max(write_block(b), |
| 281 | (void *) btree_bkey_last(b, bset_tree_last(b))); | 281 | (void *) btree_bkey_last(b, t)); |
| 282 | ssize_t remaining_space = | 282 | ssize_t remaining_space = |
| 283 | __bch2_btree_u64s_remaining(b, bne->keys.start); | 283 | __bch2_btree_u64s_remaining(b, bne->keys.start); |
| 284 | 284 | ||
| 285 | if (unlikely(bset_written(b, bset(b, t)))) { | 285 | if (unlikely(bset_written(b, bset(b, t)))) { |
| 286 | if (remaining_space > (ssize_t) (block_bytes(c) >> 3)) | 286 | if (b->written + block_sectors(c) <= btree_sectors(c)) |
| 287 | return bne; | 287 | return bne; |
| 288 | } else { | 288 | } else { |
| 289 | if (unlikely(bset_u64s(t) * sizeof(u64) > btree_write_set_buffer(b)) && | 289 | if (unlikely(bset_u64s(t) * sizeof(u64) > btree_write_set_buffer(b)) && |
| @@ -22,23 +22,21 @@ static void bucket_table_init(struct buckets_waiting_for_journal_table *t, size_ · 21 unmodified lines | |||
| 22 | memset(t->d, 0, sizeof(t->d[0]) << t->bits); | 22 | memset(t->d, 0, sizeof(t->d[0]) << t->bits); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | bool bch2_bucket_needs_journal_commit(struct buckets_waiting_for_journal *b, | 25 | u64 bch2_bucket_journal_seq_ready(struct buckets_waiting_for_journal *b, |
| 26 | u64 flushed_seq, | 26 | unsigned dev, u64 bucket) |
| 27 | unsigned dev, u64 bucket) | ||
| 28 | { | 27 | { |
| 29 | struct buckets_waiting_for_journal_table *t; | 28 | struct buckets_waiting_for_journal_table *t; |
| 30 | u64 dev_bucket = (u64) dev << 56 | bucket; | 29 | u64 dev_bucket = (u64) dev << 56 | bucket; |
| 31 | bool ret = false; | 30 | u64 ret = 0; |
| 32 | unsigned i; | ||
| 33 | 31 | ||
| 34 | mutex_lock(&b->lock); | 32 | mutex_lock(&b->lock); |
| 35 | t = b->t; | 33 | t = b->t; |
| 36 | 34 | ||
| 37 | for (i = 0; i < ARRAY_SIZE(t->hash_seeds); i++) { | 35 | for (unsigned i = 0; i < ARRAY_SIZE(t->hash_seeds); i++) { |
| 38 | struct bucket_hashed *h = bucket_hash(t, i, dev_bucket); | 36 | struct bucket_hashed *h = bucket_hash(t, i, dev_bucket); |
| 39 | 37 | ||
| 40 | if (h->dev_bucket == dev_bucket) { | 38 | if (h->dev_bucket == dev_bucket) { |
| 41 | ret = h->journal_seq > flushed_seq; | 39 | ret = h->journal_seq; |
| 42 | break; | 40 | break; |
| 43 | } | 41 | } |
| 44 | } | 42 | } |
| @@ -4,8 +4,8 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include "buckets_waiting_for_journal_types.h" | 5 | #include "buckets_waiting_for_journal_types.h" |
| 6 | 6 | ||
| 7 | bool bch2_bucket_needs_journal_commit(struct buckets_waiting_for_journal *, | 7 | u64 bch2_bucket_journal_seq_ready(struct buckets_waiting_for_journal *, |
| 8 | u64, unsigned, u64); | 8 | unsigned, u64); |
| 9 | int bch2_set_bucket_needs_journal_commit(struct buckets_waiting_for_journal *, | 9 | int bch2_set_bucket_needs_journal_commit(struct buckets_waiting_for_journal *, |
| 10 | u64, unsigned, u64, u64); | 10 | u64, unsigned, u64, u64); |
| 11 | 11 | ||
| @@ -210,11 +210,13 @@ static inline void bch2_accounting_mem_read_counters(struct bch_accounting_mem * · 209 unmodified lines | |||
| 210 | static inline void bch2_accounting_mem_read(struct bch_fs *c, struct bpos p, | 210 | static inline void bch2_accounting_mem_read(struct bch_fs *c, struct bpos p, |
| 211 | u64 *v, unsigned nr) | 211 | u64 *v, unsigned nr) |
| 212 | { | 212 | { |
| 213 | percpu_down_read(&c->mark_lock); | ||
| 213 | struct bch_accounting_mem *acc = &c->accounting; | 214 | struct bch_accounting_mem *acc = &c->accounting; |
| 214 | unsigned idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]), | 215 | unsigned idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]), |
| 215 | accounting_pos_cmp, &p); | 216 | accounting_pos_cmp, &p); |
| 216 | 217 | ||
| 217 | bch2_accounting_mem_read_counters(acc, idx, v, nr, false); | 218 | bch2_accounting_mem_read_counters(acc, idx, v, nr, false); |
| 219 | percpu_up_read(&c->mark_lock); | ||
| 218 | } | 220 | } |
| 219 | 221 | ||
| 220 | static inline struct bversion journal_pos_to_bversion(struct journal_res *res, unsigned offset) | 222 | static inline struct bversion journal_pos_to_bversion(struct journal_res *res, unsigned offset) |
| @@ -823,6 +823,7 @@ struct inode_walker_entry { · 822 unmodified lines | |||
| 823 | struct bch_inode_unpacked inode; | 823 | struct bch_inode_unpacked inode; |
| 824 | u32 snapshot; | 824 | u32 snapshot; |
| 825 | u64 count; | 825 | u64 count; |
| 826 | u64 i_size; | ||
| 826 | }; | 827 | }; |
| 827 | 828 | ||
| 828 | struct inode_walker { | 829 | struct inode_walker { |
| @@ -910,8 +911,9 @@ found: · 81 unmodified lines | |||
| 910 | if (k.k->p.snapshot != i->snapshot && !is_whiteout) { | 911 | if (k.k->p.snapshot != i->snapshot && !is_whiteout) { |
| 911 | struct inode_walker_entry new = *i; | 912 | struct inode_walker_entry new = *i; |
| 912 | 913 | ||
| 913 | new.snapshot = k.k->p.snapshot; | 914 | new.snapshot = k.k->p.snapshot; |
| 914 | new.count = 0; | 915 | new.count = 0; |
| 916 | new.i_size = 0; | ||
| 915 | 917 | ||
| 916 | struct printbuf buf = PRINTBUF; | 918 | struct printbuf buf = PRINTBUF; |
| 917 | bch2_bkey_val_to_text(&buf, c, k); | 919 | bch2_bkey_val_to_text(&buf, c, k); |
| @@ -1116,37 +1118,6 @@ err: · 198 unmodified lines | |||
| 1116 | return ret; | 1118 | return ret; |
| 1117 | } | 1119 | } |
| 1118 | 1120 | ||
| 1119 | static int check_directory_size(struct btree_trans *trans, | ||
| 1120 | struct bch_inode_unpacked *inode_u, | ||
| 1121 | struct bkey_s_c inode_k, bool *write_inode) | ||
| 1122 | { | ||
| 1123 | struct btree_iter iter; | ||
| 1124 | struct bkey_s_c k; | ||
| 1125 | u64 new_size = 0; | ||
| 1126 | int ret; | ||
| 1127 | |||
| 1128 | for_each_btree_key_max_norestart(trans, iter, BTREE_ID_dirents, | ||
| 1129 | SPOS(inode_k.k->p.offset, 0, inode_k.k->p.snapshot), | ||
| 1130 | POS(inode_k.k->p.offset, U64_MAX), | ||
| 1131 | 0, k, ret) { | ||
| 1132 | if (k.k->type != KEY_TYPE_dirent) | ||
| 1133 | continue; | ||
| 1134 | |||
| 1135 | struct bkey_s_c_dirent dirent = bkey_s_c_to_dirent(k); | ||
| 1136 | struct qstr name = bch2_dirent_get_name(dirent); | ||
| 1137 | |||
| 1138 | new_size += dirent_occupied_size(&name); | ||
| 1139 | } | ||
| 1140 | bch2_trans_iter_exit(trans, &iter); | ||
| 1141 | |||
| 1142 | if (!ret && inode_u->bi_size != new_size) { | ||
| 1143 | inode_u->bi_size = new_size; | ||
| 1144 | *write_inode = true; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | return ret; | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | static int check_inode(struct btree_trans *trans, | 1121 | static int check_inode(struct btree_trans *trans, |
| 1151 | struct btree_iter *iter, | 1122 | struct btree_iter *iter, |
| 1152 | struct bkey_s_c k, | 1123 | struct bkey_s_c k, |
| @@ -1335,16 +1306,6 @@ static int check_inode(struct btree_trans *trans, · 182 unmodified lines | |||
| 1335 | u.bi_journal_seq = journal_cur_seq(&c->journal); | 1306 | u.bi_journal_seq = journal_cur_seq(&c->journal); |
| 1336 | do_update = true; | 1307 | do_update = true; |
| 1337 | } | 1308 | } |
| 1338 | |||
| 1339 | if (S_ISDIR(u.bi_mode)) { | ||
| 1340 | ret = check_directory_size(trans, &u, k, &do_update); | ||
| 1341 | |||
| 1342 | fsck_err_on(ret, | ||
| 1343 | trans, directory_size_mismatch, | ||
| 1344 | "directory inode %llu:%u with the mismatch directory size", | ||
| 1345 | u.bi_inum, k.k->p.snapshot); | ||
| 1346 | ret = 0; | ||
| 1347 | } | ||
| 1348 | do_update: | 1309 | do_update: |
| 1349 | if (do_update) { | 1310 | if (do_update) { |
| 1350 | ret = __bch2_fsck_write_inode(trans, &u); | 1311 | ret = __bch2_fsck_write_inode(trans, &u); |
| @@ -2017,10 +1978,31 @@ fsck_err: · 666 unmodified lines | |||
| 2017 | return ret; | 1978 | return ret; |
| 2018 | } | 1979 | } |
| 2019 | 1980 | ||
| 2020 | static int check_subdir_count(struct btree_trans *trans, struct inode_walker *w) | 1981 | static int check_dir_i_size_notnested(struct btree_trans *trans, struct inode_walker *w) |
| 1982 | { | ||
| 1983 | struct bch_fs *c = trans->c; | ||
| 1984 | int ret = 0; | ||
| 1985 | |||
| 1986 | darray_for_each(w->inodes, i) | ||
| 1987 | if (fsck_err_on(i->inode.bi_size != i->i_size, | ||
| 1988 | trans, inode_dir_wrong_nlink, | ||
| 1989 | "directory %llu:%u with wrong i_size: got %llu, should be %llu", | ||
| 1990 | w->last_pos.inode, i->snapshot, i->inode.bi_size, i->i_size)) { | ||
| 1991 | i->inode.bi_size = i->i_size; | ||
| 1992 | ret = bch2_fsck_write_inode(trans, &i->inode); | ||
| 1993 | if (ret) | ||
| 1994 | break; | ||
| 1995 | } | ||
| 1996 | fsck_err: | ||
| 1997 | bch_err_fn(c, ret); | ||
| 1998 | return ret; | ||
| 1999 | } | ||
| 2000 | |||
| 2001 | static int check_subdir_dirents_count(struct btree_trans *trans, struct inode_walker *w) | ||
| 2021 | { | 2002 | { |
| 2022 | u32 restart_count = trans->restart_count; | 2003 | u32 restart_count = trans->restart_count; |
| 2023 | return check_subdir_count_notnested(trans, w) ?: | 2004 | return check_subdir_count_notnested(trans, w) ?: |
| 2005 | check_dir_i_size_notnested(trans, w) ?: | ||
| 2024 | trans_was_restarted(trans, restart_count); | 2006 | trans_was_restarted(trans, restart_count); |
| 2025 | } | 2007 | } |
| 2026 | 2008 | ||
| @@ -2367,7 +2349,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, · 340 unmodified lines | |||
| 2367 | goto out; | 2349 | goto out; |
| 2368 | 2350 | ||
| 2369 | if (dir->last_pos.inode != k.k->p.inode && dir->have_inodes) { | 2351 | if (dir->last_pos.inode != k.k->p.inode && dir->have_inodes) { |
| 2370 | ret = check_subdir_count(trans, dir); | 2352 | ret = check_subdir_dirents_count(trans, dir); |
| 2371 | if (ret) | 2353 | if (ret) |
| 2372 | goto err; | 2354 | goto err; |
| 2373 | } | 2355 | } |
| @@ -2457,9 +2439,11 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, · 83 unmodified lines | |||
| 2457 | if (ret) | 2439 | if (ret) |
| 2458 | goto err; | 2440 | goto err; |
| 2459 | 2441 | ||
| 2460 | if (d.v->d_type == DT_DIR) | 2442 | for_each_visible_inode(c, s, dir, d.k->p.snapshot, i) { |
| 2461 | for_each_visible_inode(c, s, dir, d.k->p.snapshot, i) | 2443 | if (d.v->d_type == DT_DIR) |
| 2462 | i->count++; | 2444 | i->count++; |
| 2445 | i->i_size += bkey_bytes(d.k); | ||
| 2446 | } | ||
| 2463 | out: | 2447 | out: |
| 2464 | err: | 2448 | err: |
| 2465 | fsck_err: | 2449 | fsck_err: |
| @@ -285,12 +285,14 @@ void bch2_inode_opts_get(struct bch_io_opts *, struct bch_fs *, · 284 unmodified lines | |||
| 285 | struct bch_inode_unpacked *); | 285 | struct bch_inode_unpacked *); |
| 286 | int bch2_inum_opts_get(struct btree_trans*, subvol_inum, struct bch_io_opts *); | 286 | int bch2_inum_opts_get(struct btree_trans*, subvol_inum, struct bch_io_opts *); |
| 287 | 287 | ||
| 288 | #include "rebalance.h" | ||
| 289 | |||
| 288 | static inline struct bch_extent_rebalance | 290 | static inline struct bch_extent_rebalance |
| 289 | bch2_inode_rebalance_opts_get(struct bch_fs *c, struct bch_inode_unpacked *inode) | 291 | bch2_inode_rebalance_opts_get(struct bch_fs *c, struct bch_inode_unpacked *inode) |
| 290 | { | 292 | { |
| 291 | struct bch_io_opts io_opts; | 293 | struct bch_io_opts io_opts; |
| 292 | bch2_inode_opts_get(&io_opts, c, inode); | 294 | bch2_inode_opts_get(&io_opts, c, inode); |
| 293 | return io_opts_to_rebalance_opts(&io_opts); | 295 | return io_opts_to_rebalance_opts(c, &io_opts); |
| 294 | } | 296 | } |
| 295 | 297 | ||
| 296 | int bch2_inode_rm_snapshot(struct btree_trans *, u64, u32); | 298 | int bch2_inode_rm_snapshot(struct btree_trans *, u64, u32); |
| @@ -411,6 +411,16 @@ void bch2_write_op_error(struct printbuf *out, struct bch_write_op *op) · 410 unmodified lines | |||
| 411 | __bch2_write_op_error(out, op, op->pos.offset); | 411 | __bch2_write_op_error(out, op, op->pos.offset); |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | static void bch2_write_op_error_trans(struct btree_trans *trans, struct printbuf *out, | ||
| 415 | struct bch_write_op *op, u64 offset) | ||
| 416 | { | ||
| 417 | bch2_inum_offset_err_msg_trans(trans, out, | ||
| 418 | (subvol_inum) { op->subvol, op->pos.inode, }, | ||
| 419 | offset << 9); | ||
| 420 | prt_printf(out, "write error%s: ", | ||
| 421 | op->flags & BCH_WRITE_MOVE ? "(internal move)" : ""); | ||
| 422 | } | ||
| 423 | |||
| 414 | void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c, | 424 | void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c, |
| 415 | enum bch_data_type type, | 425 | enum bch_data_type type, |
| 416 | const struct bkey_i *k, | 426 | const struct bkey_i *k, |
| @@ -1193,7 +1203,7 @@ static void bch2_nocow_write_convert_unwritten(struct bch_write_op *op) · 776 unmodified lines | |||
| 1193 | struct bkey_i *insert = bch2_keylist_front(&op->insert_keys); | 1203 | struct bkey_i *insert = bch2_keylist_front(&op->insert_keys); |
| 1194 | 1204 | ||
| 1195 | struct printbuf buf = PRINTBUF; | 1205 | struct printbuf buf = PRINTBUF; |
| 1196 | __bch2_write_op_error(&buf, op, bkey_start_offset(&insert->k)); | 1206 | bch2_write_op_error_trans(trans, &buf, op, bkey_start_offset(&insert->k)); |
| 1197 | prt_printf(&buf, "btree update error: %s", bch2_err_str(ret)); | 1207 | prt_printf(&buf, "btree update error: %s", bch2_err_str(ret)); |
| 1198 | bch_err_ratelimited(c, "%s", buf.buf); | 1208 | bch_err_ratelimited(c, "%s", buf.buf); |
| 1199 | printbuf_exit(&buf); | 1209 | printbuf_exit(&buf); |
| @@ -319,6 +319,16 @@ void bch2_journal_halt(struct journal *j) · 318 unmodified lines | |||
| 319 | spin_unlock(&j->lock); | 319 | spin_unlock(&j->lock); |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | void bch2_journal_halt_locked(struct journal *j) | ||
| 323 | { | ||
| 324 | lockdep_assert_held(&j->lock); | ||
| 325 | |||
| 326 | __journal_entry_close(j, JOURNAL_ENTRY_ERROR_VAL, true); | ||
| 327 | if (!j->err_seq) | ||
| 328 | j->err_seq = journal_cur_seq(j); | ||
| 329 | journal_wake(j); | ||
| 330 | } | ||
| 331 | |||
| 322 | static bool journal_entry_want_write(struct journal *j) | 332 | static bool journal_entry_want_write(struct journal *j) |
| 323 | { | 333 | { |
| 324 | bool ret = !journal_entry_is_open(j) || | 334 | bool ret = !journal_entry_is_open(j) || |
| @@ -381,9 +391,12 @@ static int journal_entry_open(struct journal *j) · 56 unmodified lines | |||
| 381 | if (nr_unwritten_journal_entries(j) == ARRAY_SIZE(j->buf)) | 391 | if (nr_unwritten_journal_entries(j) == ARRAY_SIZE(j->buf)) |
| 382 | return JOURNAL_ERR_max_in_flight; | 392 | return JOURNAL_ERR_max_in_flight; |
| 383 | 393 | ||
| 384 | if (bch2_fs_fatal_err_on(journal_cur_seq(j) >= JOURNAL_SEQ_MAX, | 394 | if (journal_cur_seq(j) >= JOURNAL_SEQ_MAX) { |
| 385 | c, "cannot start: journal seq overflow")) | 395 | bch_err(c, "cannot start: journal seq overflow"); |
| 396 | if (bch2_fs_emergency_read_only_locked(c)) | ||
| 397 | bch_err(c, "fatal error - emergency read only"); | ||
| 386 | return JOURNAL_ERR_insufficient_devices; /* -EROFS */ | 398 | return JOURNAL_ERR_insufficient_devices; /* -EROFS */ |
| 399 | } | ||
| 387 | 400 | ||
| 388 | BUG_ON(!j->cur_entry_sectors); | 401 | BUG_ON(!j->cur_entry_sectors); |
| 389 | 402 | ||
| @@ -783,6 +796,7 @@ recheck_need_open: · 393 unmodified lines | |||
| 783 | } | 796 | } |
| 784 | 797 | ||
| 785 | buf->must_flush = true; | 798 | buf->must_flush = true; |
| 799 | j->flushing_seq = max(j->flushing_seq, seq); | ||
| 786 | 800 | ||
| 787 | if (parent && !closure_wait(&buf->wait, parent)) | 801 | if (parent && !closure_wait(&buf->wait, parent)) |
| 788 | BUG(); | 802 | BUG(); |
| @@ -409,6 +409,7 @@ bool bch2_journal_noflush_seq(struct journal *, u64, u64); · 408 unmodified lines | |||
| 409 | int bch2_journal_meta(struct journal *); | 409 | int bch2_journal_meta(struct journal *); |
| 410 | 410 | ||
| 411 | void bch2_journal_halt(struct journal *); | 411 | void bch2_journal_halt(struct journal *); |
| 412 | void bch2_journal_halt_locked(struct journal *); | ||
| 412 | 413 | ||
| 413 | static inline int bch2_journal_error(struct journal *j) | 414 | static inline int bch2_journal_error(struct journal *j) |
| 414 | { | 415 | { |
| @@ -384,12 +384,16 @@ void bch2_journal_pin_drop(struct journal *j, · 383 unmodified lines | |||
| 384 | spin_unlock(&j->lock); | 384 | spin_unlock(&j->lock); |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | static enum journal_pin_type journal_pin_type(journal_pin_flush_fn fn) | 387 | static enum journal_pin_type journal_pin_type(struct journal_entry_pin *pin, |
| 388 | journal_pin_flush_fn fn) | ||
| 388 | { | 389 | { |
| 389 | if (fn == bch2_btree_node_flush0 || | 390 | if (fn == bch2_btree_node_flush0 || |
| 390 | fn == bch2_btree_node_flush1) | 391 | fn == bch2_btree_node_flush1) { |
| 391 | return JOURNAL_PIN_TYPE_btree; | 392 | unsigned idx = fn == bch2_btree_node_flush1; |
| 392 | else if (fn == bch2_btree_key_cache_journal_flush) | 393 | struct btree *b = container_of(pin, struct btree, writes[idx].journal); |
| 394 | |||
| 395 | return JOURNAL_PIN_TYPE_btree0 - b->c.level; | ||
| 396 | } else if (fn == bch2_btree_key_cache_journal_flush) | ||
| 393 | return JOURNAL_PIN_TYPE_key_cache; | 397 | return JOURNAL_PIN_TYPE_key_cache; |
| 394 | else | 398 | else |
| 395 | return JOURNAL_PIN_TYPE_other; | 399 | return JOURNAL_PIN_TYPE_other; |
| @@ -441,7 +445,7 @@ void bch2_journal_pin_copy(struct journal *j, · 45 unmodified lines | |||
| 441 | 445 | ||
| 442 | bool reclaim = __journal_pin_drop(j, dst); | 446 | bool reclaim = __journal_pin_drop(j, dst); |
| 443 | 447 | ||
| 444 | bch2_journal_pin_set_locked(j, seq, dst, flush_fn, journal_pin_type(flush_fn)); | 448 | bch2_journal_pin_set_locked(j, seq, dst, flush_fn, journal_pin_type(dst, flush_fn)); |
| 445 | 449 | ||
| 446 | if (reclaim) | 450 | if (reclaim) |
| 447 | bch2_journal_reclaim_fast(j); | 451 | bch2_journal_reclaim_fast(j); |
| @@ -465,7 +469,7 @@ void bch2_journal_pin_set(struct journal *j, u64 seq, · 17 unmodified lines | |||
| 465 | 469 | ||
| 466 | bool reclaim = __journal_pin_drop(j, pin); | 470 | bool reclaim = __journal_pin_drop(j, pin); |
| 467 | 471 | ||
| 468 | bch2_journal_pin_set_locked(j, seq, pin, flush_fn, journal_pin_type(flush_fn)); | 472 | bch2_journal_pin_set_locked(j, seq, pin, flush_fn, journal_pin_type(pin, flush_fn)); |
| 469 | 473 | ||
| 470 | if (reclaim) | 474 | if (reclaim) |
| 471 | bch2_journal_reclaim_fast(j); | 475 | bch2_journal_reclaim_fast(j); |
| @@ -587,7 +591,7 @@ static size_t journal_flush_pins(struct journal *j, · 115 unmodified lines | |||
| 587 | spin_lock(&j->lock); | 591 | spin_lock(&j->lock); |
| 588 | /* Pin might have been dropped or rearmed: */ | 592 | /* Pin might have been dropped or rearmed: */ |
| 589 | if (likely(!err && !j->flush_in_progress_dropped)) | 593 | if (likely(!err && !j->flush_in_progress_dropped)) |
| 590 | list_move(&pin->list, &journal_seq_pin(j, seq)->flushed[journal_pin_type(flush_fn)]); | 594 | list_move(&pin->list, &journal_seq_pin(j, seq)->flushed[journal_pin_type(pin, flush_fn)]); |
| 591 | j->flush_in_progress = NULL; | 595 | j->flush_in_progress = NULL; |
| 592 | j->flush_in_progress_dropped = false; | 596 | j->flush_in_progress_dropped = false; |
| 593 | spin_unlock(&j->lock); | 597 | spin_unlock(&j->lock); |
| @@ -869,18 +873,13 @@ static int journal_flush_done(struct journal *j, u64 seq_to_flush, · 275 unmodified lines | |||
| 869 | 873 | ||
| 870 | mutex_lock(&j->reclaim_lock); | 874 | mutex_lock(&j->reclaim_lock); |
| 871 | 875 | ||
| 872 | if (journal_flush_pins_or_still_flushing(j, seq_to_flush, | 876 | for (int type = JOURNAL_PIN_TYPE_NR - 1; |
| 873 | BIT(JOURNAL_PIN_TYPE_key_cache)| | 877 | type >= 0; |
| 874 | BIT(JOURNAL_PIN_TYPE_other))) { | 878 | --type) |
| 875 | *did_work = true; | 879 | if (journal_flush_pins_or_still_flushing(j, seq_to_flush, BIT(type))) { |
| 876 | goto unlock; | 880 | *did_work = true; |
| 877 | } | 881 | goto unlock; |
| 878 | 882 | } | |
| 879 | if (journal_flush_pins_or_still_flushing(j, seq_to_flush, | ||
| 880 | BIT(JOURNAL_PIN_TYPE_btree))) { | ||
| 881 | *did_work = true; | ||
| 882 | goto unlock; | ||
| 883 | } | ||
| 884 | 883 | ||
| 885 | if (seq_to_flush > journal_cur_seq(j)) | 884 | if (seq_to_flush > journal_cur_seq(j)) |
| 886 | bch2_journal_entry_close(j); | 885 | bch2_journal_entry_close(j); |
| @@ -53,7 +53,10 @@ struct journal_buf { · 52 unmodified lines | |||
| 53 | */ | 53 | */ |
| 54 | 54 | ||
| 55 | enum journal_pin_type { | 55 | enum journal_pin_type { |
| 56 | JOURNAL_PIN_TYPE_btree, | 56 | JOURNAL_PIN_TYPE_btree3, |
| 57 | JOURNAL_PIN_TYPE_btree2, | ||
| 58 | JOURNAL_PIN_TYPE_btree1, | ||
| 59 | JOURNAL_PIN_TYPE_btree0, | ||
| 57 | JOURNAL_PIN_TYPE_key_cache, | 60 | JOURNAL_PIN_TYPE_key_cache, |
| 58 | JOURNAL_PIN_TYPE_other, | 61 | JOURNAL_PIN_TYPE_other, |
| 59 | JOURNAL_PIN_TYPE_NR, | 62 | JOURNAL_PIN_TYPE_NR, |
| @@ -237,6 +240,7 @@ struct journal { · 177 unmodified lines | |||
| 237 | /* seq, last_seq from the most recent journal entry successfully written */ | 240 | /* seq, last_seq from the most recent journal entry successfully written */ |
| 238 | u64 seq_ondisk; | 241 | u64 seq_ondisk; |
| 239 | u64 flushed_seq_ondisk; | 242 | u64 flushed_seq_ondisk; |
| 243 | u64 flushing_seq; | ||
| 240 | u64 last_seq_ondisk; | 244 | u64 last_seq_ondisk; |
| 241 | u64 err_seq; | 245 | u64 err_seq; |
| 242 | u64 last_empty_seq; | 246 | u64 last_empty_seq; |
| @@ -659,18 +659,4 @@ static inline void bch2_io_opts_fixups(struct bch_io_opts *opts) · 658 unmodified lines | |||
| 659 | struct bch_io_opts bch2_opts_to_inode_opts(struct bch_opts); | 659 | struct bch_io_opts bch2_opts_to_inode_opts(struct bch_opts); |
| 660 | bool bch2_opt_is_inode_opt(enum bch_opt_id); | 660 | bool bch2_opt_is_inode_opt(enum bch_opt_id); |
| 661 | 661 | ||
| 662 | /* rebalance opts: */ | ||
| 663 | |||
| 664 | static inline struct bch_extent_rebalance io_opts_to_rebalance_opts(struct bch_io_opts *opts) | ||
| 665 | { | ||
| 666 | return (struct bch_extent_rebalance) { | ||
| 667 | .type = BIT(BCH_EXTENT_ENTRY_rebalance), | ||
| 668 | #define x(_name) \ | ||
| 669 | ._name = opts->_name, \ | ||
| 670 | ._name##_from_inode = opts->_name##_from_inode, | ||
| 671 | BCH_REBALANCE_OPTS() | ||
| 672 | #undef x | ||
| 673 | }; | ||
| 674 | }; | ||
| 675 | |||
| 676 | #endif /* _BCACHEFS_OPTS_H */ | 662 | #endif /* _BCACHEFS_OPTS_H */ |
| @@ -121,12 +121,10 @@ u64 bch2_bkey_sectors_need_rebalance(struct bch_fs *c, struct bkey_s_c k) · 120 unmodified lines | |||
| 121 | } | 121 | } |
| 122 | } | 122 | } |
| 123 | incompressible: | 123 | incompressible: |
| 124 | if (opts->background_target && | 124 | if (opts->background_target) |
| 125 | bch2_target_accepts_data(c, BCH_DATA_user, opts->background_target)) { | ||
| 126 | bkey_for_each_ptr_decode(k.k, ptrs, p, entry) | 125 | bkey_for_each_ptr_decode(k.k, ptrs, p, entry) |
| 127 | if (!p.ptr.cached && !bch2_dev_in_target(c, p.ptr.dev, opts->background_target)) | 126 | if (!p.ptr.cached && !bch2_dev_in_target(c, p.ptr.dev, opts->background_target)) |
| 128 | sectors += p.crc.compressed_size; | 127 | sectors += p.crc.compressed_size; |
| 129 | } | ||
| 130 | 128 | ||
| 131 | return sectors; | 129 | return sectors; |
| 132 | } | 130 | } |
| @@ -140,7 +138,7 @@ static bool bch2_bkey_rebalance_needs_update(struct bch_fs *c, struct bch_io_opt · 7 unmodified lines | |||
| 140 | const struct bch_extent_rebalance *old = bch2_bkey_rebalance_opts(k); | 138 | const struct bch_extent_rebalance *old = bch2_bkey_rebalance_opts(k); |
| 141 | 139 | ||
| 142 | if (k.k->type == KEY_TYPE_reflink_v || bch2_bkey_ptrs_need_rebalance(c, opts, k)) { | 140 | if (k.k->type == KEY_TYPE_reflink_v || bch2_bkey_ptrs_need_rebalance(c, opts, k)) { |
| 143 | struct bch_extent_rebalance new = io_opts_to_rebalance_opts(opts); | 141 | struct bch_extent_rebalance new = io_opts_to_rebalance_opts(c, opts); |
| 144 | return old == NULL || memcmp(old, &new, sizeof(new)); | 142 | return old == NULL || memcmp(old, &new, sizeof(new)); |
| 145 | } else { | 143 | } else { |
| 146 | return old != NULL; | 144 | return old != NULL; |
| @@ -163,7 +161,7 @@ int bch2_bkey_set_needs_rebalance(struct bch_fs *c, struct bch_io_opts *opts, · 16 unmodified lines | |||
| 163 | k.k->u64s += sizeof(*old) / sizeof(u64); | 161 | k.k->u64s += sizeof(*old) / sizeof(u64); |
| 164 | } | 162 | } |
| 165 | 163 | ||
| 166 | *old = io_opts_to_rebalance_opts(opts); | 164 | *old = io_opts_to_rebalance_opts(c, opts); |
| 167 | } else { | 165 | } else { |
| 168 | if (old) | 166 | if (old) |
| 169 | extent_entry_drop(k, (union bch_extent_entry *) old); | 167 | extent_entry_drop(k, (union bch_extent_entry *) old); |
| @@ -4,8 +4,28 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include "compress.h" | 5 | #include "compress.h" |
| 6 | #include "disk_groups.h" | 6 | #include "disk_groups.h" |
| 7 | #include "opts.h" | ||
| 7 | #include "rebalance_types.h" | 8 | #include "rebalance_types.h" |
| 8 | 9 | ||
| 10 | static inline struct bch_extent_rebalance io_opts_to_rebalance_opts(struct bch_fs *c, | ||
| 11 | struct bch_io_opts *opts) | ||
| 12 | { | ||
| 13 | struct bch_extent_rebalance r = { | ||
| 14 | .type = BIT(BCH_EXTENT_ENTRY_rebalance), | ||
| 15 | #define x(_name) \ | ||
| 16 | ._name = opts->_name, \ | ||
| 17 | ._name##_from_inode = opts->_name##_from_inode, | ||
| 18 | BCH_REBALANCE_OPTS() | ||
| 19 | #undef x | ||
| 20 | }; | ||
| 21 | |||
| 22 | if (r.background_target && | ||
| 23 | !bch2_target_accepts_data(c, BCH_DATA_user, r.background_target)) | ||
| 24 | r.background_target = 0; | ||
| 25 | |||
| 26 | return r; | ||
| 27 | }; | ||
| 28 | |||
| 9 | u64 bch2_bkey_sectors_need_rebalance(struct bch_fs *, struct bkey_s_c); | 29 | u64 bch2_bkey_sectors_need_rebalance(struct bch_fs *, struct bkey_s_c); |
| 10 | int bch2_bkey_set_needs_rebalance(struct bch_fs *, struct bch_io_opts *, struct bkey_i *); | 30 | int bch2_bkey_set_needs_rebalance(struct bch_fs *, struct bch_io_opts *, struct bkey_i *); |
| 11 | int bch2_get_update_rebalance_opts(struct btree_trans *, | 31 | int bch2_get_update_rebalance_opts(struct btree_trans *, |
| @@ -172,7 +172,7 @@ static int bch2_indirect_extent_missing_error(struct btree_trans *trans, · 171 unmodified lines | |||
| 172 | bool should_commit) | 172 | bool should_commit) |
| 173 | { | 173 | { |
| 174 | if (REFLINK_P_ERROR(p.v)) | 174 | if (REFLINK_P_ERROR(p.v)) |
| 175 | return -BCH_ERR_missing_indirect_extent; | 175 | return 0; |
| 176 | 176 | ||
| 177 | struct bch_fs *c = trans->c; | 177 | struct bch_fs *c = trans->c; |
| 178 | u64 live_start = REFLINK_P_IDX(p.v); | 178 | u64 live_start = REFLINK_P_IDX(p.v); |
| @@ -259,8 +259,6 @@ struct bkey_s_c bch2_lookup_indirect_extent(struct btree_trans *trans, · 80 unmodified lines | |||
| 259 | return k; | 259 | return k; |
| 260 | 260 | ||
| 261 | if (unlikely(!bkey_extent_is_reflink_data(k.k))) { | 261 | if (unlikely(!bkey_extent_is_reflink_data(k.k))) { |
| 262 | bch2_trans_iter_exit(trans, iter); | ||
| 263 | |||
| 264 | unsigned size = min((u64) k.k->size, | 262 | unsigned size = min((u64) k.k->size, |
| 265 | REFLINK_P_IDX(p.v) + p.k->size + le32_to_cpu(p.v->back_pad) - | 263 | REFLINK_P_IDX(p.v) + p.k->size + le32_to_cpu(p.v->back_pad) - |
| 266 | reflink_offset); | 264 | reflink_offset); |
| @@ -268,14 +266,16 @@ struct bkey_s_c bch2_lookup_indirect_extent(struct btree_trans *trans, · 1 unmodified line | |||
| 268 | 266 | ||
| 269 | int ret = bch2_indirect_extent_missing_error(trans, p, reflink_offset, | 267 | int ret = bch2_indirect_extent_missing_error(trans, p, reflink_offset, |
| 270 | k.k->p.offset, should_commit); | 268 | k.k->p.offset, should_commit); |
| 271 | if (ret) | 269 | if (ret) { |
| 270 | bch2_trans_iter_exit(trans, iter); | ||
| 272 | return bkey_s_c_err(ret); | 271 | return bkey_s_c_err(ret); |
| 272 | } | ||
| 273 | } else if (unlikely(REFLINK_P_ERROR(p.v))) { | 273 | } else if (unlikely(REFLINK_P_ERROR(p.v))) { |
| 274 | bch2_trans_iter_exit(trans, iter); | ||
| 275 | |||
| 276 | int ret = bch2_indirect_extent_not_missing(trans, p, should_commit); | 274 | int ret = bch2_indirect_extent_not_missing(trans, p, should_commit); |
| 277 | if (ret) | 275 | if (ret) { |
| 276 | bch2_trans_iter_exit(trans, iter); | ||
| 278 | return bkey_s_c_err(ret); | 277 | return bkey_s_c_err(ret); |
| 278 | } | ||
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | *offset_into_extent = reflink_offset - bkey_start_offset(k.k); | 281 | *offset_into_extent = reflink_offset - bkey_start_offset(k.k); |
| @@ -300,7 +300,7 @@ static int trans_trigger_reflink_p_segment(struct btree_trans *trans, · 18 unmodified lines | |||
| 300 | if (ret) | 300 | if (ret) |
| 301 | return ret; | 301 | return ret; |
| 302 | 302 | ||
| 303 | if (bkey_deleted(k.k)) { | 303 | if (!bkey_refcount_c(k)) { |
| 304 | if (!(flags & BTREE_TRIGGER_overwrite)) | 304 | if (!(flags & BTREE_TRIGGER_overwrite)) |
| 305 | ret = -BCH_ERR_missing_indirect_extent; | 305 | ret = -BCH_ERR_missing_indirect_extent; |
| 306 | goto next; | 306 | goto next; |
| @@ -92,7 +92,7 @@ · 91 unmodified lines | |||
| 92 | BCH_FSCK_ERR_accounting_key_replicas_nr_devs_0, \ | 92 | BCH_FSCK_ERR_accounting_key_replicas_nr_devs_0, \ |
| 93 | BCH_FSCK_ERR_accounting_key_junk_at_end) \ | 93 | BCH_FSCK_ERR_accounting_key_junk_at_end) \ |
| 94 | x(directory_size, \ | 94 | x(directory_size, \ |
| 95 | BIT_ULL(BCH_RECOVERY_PASS_check_inodes), \ | 95 | BIT_ULL(BCH_RECOVERY_PASS_check_dirents), \ |
| 96 | BCH_FSCK_ERR_directory_size_mismatch) \ | 96 | BCH_FSCK_ERR_directory_size_mismatch) \ |
| 97 | 97 | ||
| 98 | #define DOWNGRADE_TABLE() \ | 98 | #define DOWNGRADE_TABLE() \ |
| @@ -180,9 +180,9 @@ enum bch_fsck_flags { · 179 unmodified lines | |||
| 180 | x(ptr_crc_nonce_mismatch, 162, 0) \ | 180 | x(ptr_crc_nonce_mismatch, 162, 0) \ |
| 181 | x(ptr_stripe_redundant, 163, 0) \ | 181 | x(ptr_stripe_redundant, 163, 0) \ |
| 182 | x(reservation_key_nr_replicas_invalid, 164, 0) \ | 182 | x(reservation_key_nr_replicas_invalid, 164, 0) \ |
| 183 | x(reflink_v_refcount_wrong, 165, 0) \ | 183 | x(reflink_v_refcount_wrong, 165, FSCK_AUTOFIX) \ |
| 184 | x(reflink_v_pos_bad, 292, 0) \ | 184 | x(reflink_v_pos_bad, 292, 0) \ |
| 185 | x(reflink_p_to_missing_reflink_v, 166, 0) \ | 185 | x(reflink_p_to_missing_reflink_v, 166, FSCK_AUTOFIX) \ |
| 186 | x(reflink_refcount_underflow, 293, 0) \ | 186 | x(reflink_refcount_underflow, 293, 0) \ |
| 187 | x(stripe_pos_bad, 167, 0) \ | 187 | x(stripe_pos_bad, 167, 0) \ |
| 188 | x(stripe_val_size_bad, 168, 0) \ | 188 | x(stripe_val_size_bad, 168, 0) \ |
| @@ -428,7 +428,7 @@ static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid) · 427 unmodified lines | |||
| 428 | bch2_bkey_get_iter_typed(trans, &snapshot_iter, | 428 | bch2_bkey_get_iter_typed(trans, &snapshot_iter, |
| 429 | BTREE_ID_snapshots, POS(0, snapid), | 429 | BTREE_ID_snapshots, POS(0, snapid), |
| 430 | 0, snapshot); | 430 | 0, snapshot); |
| 431 | ret = bkey_err(subvol); | 431 | ret = bkey_err(snapshot); |
| 432 | bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c, | 432 | bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c, |
| 433 | "missing snapshot %u", snapid); | 433 | "missing snapshot %u", snapid); |
| 434 | if (ret) | 434 | if (ret) |
| @@ -440,6 +440,11 @@ static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid) · 5 unmodified lines | |||
| 440 | bch2_bkey_get_iter_typed(trans, &snapshot_tree_iter, | 440 | bch2_bkey_get_iter_typed(trans, &snapshot_tree_iter, |
| 441 | BTREE_ID_snapshot_trees, POS(0, treeid), | 441 | BTREE_ID_snapshot_trees, POS(0, treeid), |
| 442 | 0, snapshot_tree); | 442 | 0, snapshot_tree); |
| 443 | ret = bkey_err(snapshot_tree); | ||
| 444 | bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c, | ||
| 445 | "missing snapshot tree %u", treeid); | ||
| 446 | if (ret) | ||
| 447 | goto err; | ||
| 443 | 448 | ||
| 444 | if (le32_to_cpu(snapshot_tree.v->master_subvol) == subvolid) { | 449 | if (le32_to_cpu(snapshot_tree.v->master_subvol) == subvolid) { |
| 445 | struct bkey_i_snapshot_tree *snapshot_tree_mut = | 450 | struct bkey_i_snapshot_tree *snapshot_tree_mut = |
| @@ -411,6 +411,17 @@ bool bch2_fs_emergency_read_only(struct bch_fs *c) · 410 unmodified lines | |||
| 411 | return ret; | 411 | return ret; |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | bool bch2_fs_emergency_read_only_locked(struct bch_fs *c) | ||
| 415 | { | ||
| 416 | bool ret = !test_and_set_bit(BCH_FS_emergency_ro, &c->flags); | ||
| 417 | |||
| 418 | bch2_journal_halt_locked(&c->journal); | ||
| 419 | bch2_fs_read_only_async(c); | ||
| 420 | |||
| 421 | wake_up(&bch2_read_only_wait); | ||
| 422 | return ret; | ||
| 423 | } | ||
| 424 | |||
| 414 | static int bch2_fs_read_write_late(struct bch_fs *c) | 425 | static int bch2_fs_read_write_late(struct bch_fs *c) |
| 415 | { | 426 | { |
| 416 | int ret; | 427 | int ret; |
| @@ -29,6 +29,7 @@ int bch2_dev_resize(struct bch_fs *, struct bch_dev *, u64); · 28 unmodified lines | |||
| 29 | struct bch_dev *bch2_dev_lookup(struct bch_fs *, const char *); | 29 | struct bch_dev *bch2_dev_lookup(struct bch_fs *, const char *); |
| 30 | 30 | ||
| 31 | bool bch2_fs_emergency_read_only(struct bch_fs *); | 31 | bool bch2_fs_emergency_read_only(struct bch_fs *); |
| 32 | bool bch2_fs_emergency_read_only_locked(struct bch_fs *); | ||
| 32 | void bch2_fs_read_only(struct bch_fs *); | 33 | void bch2_fs_read_only(struct bch_fs *); |
| 33 | 34 | ||
| 34 | int bch2_fs_read_write(struct bch_fs *); | 35 | int bch2_fs_read_write(struct bch_fs *); |
| @@ -727,7 +727,7 @@ DEFINE_EVENT(fs_str, bucket_alloc_fail, · 726 unmodified lines | |||
| 727 | TP_ARGS(c, str) | 727 | TP_ARGS(c, str) |
| 728 | ); | 728 | ); |
| 729 | 729 | ||
| 730 | TRACE_EVENT(discard_buckets, | 730 | DECLARE_EVENT_CLASS(discard_buckets_class, |
| 731 | TP_PROTO(struct bch_fs *c, u64 seen, u64 open, | 731 | TP_PROTO(struct bch_fs *c, u64 seen, u64 open, |
| 732 | u64 need_journal_commit, u64 discarded, const char *err), | 732 | u64 need_journal_commit, u64 discarded, const char *err), |
| 733 | TP_ARGS(c, seen, open, need_journal_commit, discarded, err), | 733 | TP_ARGS(c, seen, open, need_journal_commit, discarded, err), |
| @@ -759,6 +759,18 @@ TRACE_EVENT(discard_buckets, · 25 unmodified lines | |||
| 759 | __entry->err) | 759 | __entry->err) |
| 760 | ); | 760 | ); |
| 761 | 761 | ||
| 762 | DEFINE_EVENT(discard_buckets_class, discard_buckets, | ||
| 763 | TP_PROTO(struct bch_fs *c, u64 seen, u64 open, | ||
| 764 | u64 need_journal_commit, u64 discarded, const char *err), | ||
| 765 | TP_ARGS(c, seen, open, need_journal_commit, discarded, err) | ||
| 766 | ); | ||
| 767 | |||
| 768 | DEFINE_EVENT(discard_buckets_class, discard_buckets_fast, | ||
| 769 | TP_PROTO(struct bch_fs *c, u64 seen, u64 open, | ||
| 770 | u64 need_journal_commit, u64 discarded, const char *err), | ||
| 771 | TP_ARGS(c, seen, open, need_journal_commit, discarded, err) | ||
| 772 | ); | ||
| 773 | |||
| 762 | TRACE_EVENT(bucket_invalidate, | 774 | TRACE_EVENT(bucket_invalidate, |
| 763 | TP_PROTO(struct bch_fs *c, unsigned dev, u64 bucket, u32 sectors), | 775 | TP_PROTO(struct bch_fs *c, unsigned dev, u64 bucket, u32 sectors), |
| 764 | TP_ARGS(c, dev, bucket, sectors), | 776 | TP_ARGS(c, dev, bucket, sectors), |
| @@ -1496,6 +1496,7 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p, · 1495 unmodified lines | |||
| 1496 | 1496 | ||
| 1497 | if (!p->skip_locking) { | 1497 | if (!p->skip_locking) { |
| 1498 | btrfs_unlock_up_safe(p, parent_level + 1); | 1498 | btrfs_unlock_up_safe(p, parent_level + 1); |
| 1499 | btrfs_maybe_reset_lockdep_class(root, tmp); | ||
| 1499 | tmp_locked = true; | 1500 | tmp_locked = true; |
| 1500 | btrfs_tree_read_lock(tmp); | 1501 | btrfs_tree_read_lock(tmp); |
| 1501 | btrfs_release_path(p); | 1502 | btrfs_release_path(p); |
| @@ -1539,6 +1540,7 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p, · 37 unmodified lines | |||
| 1539 | 1540 | ||
| 1540 | if (!p->skip_locking) { | 1541 | if (!p->skip_locking) { |
| 1541 | ASSERT(ret == -EAGAIN); | 1542 | ASSERT(ret == -EAGAIN); |
| 1543 | btrfs_maybe_reset_lockdep_class(root, tmp); | ||
| 1542 | tmp_locked = true; | 1544 | tmp_locked = true; |
| 1543 | btrfs_tree_read_lock(tmp); | 1545 | btrfs_tree_read_lock(tmp); |
| 1544 | btrfs_release_path(p); | 1546 | btrfs_release_path(p); |
| @@ -523,8 +523,6 @@ static void end_bbio_data_read(struct btrfs_bio *bbio) · 522 unmodified lines | |||
| 523 | u64 end; | 523 | u64 end; |
| 524 | u32 len; | 524 | u32 len; |
| 525 | 525 | ||
| 526 | /* For now only order 0 folios are supported for data. */ | ||
| 527 | ASSERT(folio_order(folio) == 0); | ||
| 528 | btrfs_debug(fs_info, | 526 | btrfs_debug(fs_info, |
| 529 | "%s: bi_sector=%llu, err=%d, mirror=%u", | 527 | "%s: bi_sector=%llu, err=%d, mirror=%u", |
| 530 | __func__, bio->bi_iter.bi_sector, bio->bi_status, | 528 | __func__, bio->bi_iter.bi_sector, bio->bi_status, |
| @@ -552,7 +550,6 @@ static void end_bbio_data_read(struct btrfs_bio *bbio) · 21 unmodified lines | |||
| 552 | 550 | ||
| 553 | if (likely(uptodate)) { | 551 | if (likely(uptodate)) { |
| 554 | loff_t i_size = i_size_read(inode); | 552 | loff_t i_size = i_size_read(inode); |
| 555 | pgoff_t end_index = i_size >> folio_shift(folio); | ||
| 556 | 553 | ||
| 557 | /* | 554 | /* |
| 558 | * Zero out the remaining part if this range straddles | 555 | * Zero out the remaining part if this range straddles |
| @@ -561,9 +558,11 @@ static void end_bbio_data_read(struct btrfs_bio *bbio) · 2 unmodified lines | |||
| 561 | * Here we should only zero the range inside the folio, | 558 | * Here we should only zero the range inside the folio, |
| 562 | * not touch anything else. | 559 | * not touch anything else. |
| 563 | * | 560 | * |
| 564 | * NOTE: i_size is exclusive while end is inclusive. | 561 | * NOTE: i_size is exclusive while end is inclusive and |
| 562 | * folio_contains() takes PAGE_SIZE units. | ||
| 565 | */ | 563 | */ |
| 566 | if (folio_index(folio) == end_index && i_size <= end) { | 564 | if (folio_contains(folio, i_size >> PAGE_SHIFT) && |
| 565 | i_size <= end) { | ||
| 567 | u32 zero_start = max(offset_in_folio(folio, i_size), | 566 | u32 zero_start = max(offset_in_folio(folio, i_size), |
| 568 | offset_in_folio(folio, start)); | 567 | offset_in_folio(folio, start)); |
| 569 | u32 zero_len = offset_in_folio(folio, end) + 1 - | 568 | u32 zero_len = offset_in_folio(folio, end) + 1 - |
| @@ -899,7 +898,6 @@ static struct extent_map *get_extent_map(struct btrfs_inode *inode, · 329 unmodified lines | |||
| 899 | u64 len, struct extent_map **em_cached) | 898 | u64 len, struct extent_map **em_cached) |
| 900 | { | 899 | { |
| 901 | struct extent_map *em; | 900 | struct extent_map *em; |
| 902 | struct extent_state *cached_state = NULL; | ||
| 903 | 901 | ||
| 904 | ASSERT(em_cached); | 902 | ASSERT(em_cached); |
| 905 | 903 | ||
| @@ -915,14 +913,12 @@ static struct extent_map *get_extent_map(struct btrfs_inode *inode, · 9 unmodified lines | |||
| 915 | *em_cached = NULL; | 913 | *em_cached = NULL; |
| 916 | } | 914 | } |
| 917 | 915 | ||
| 918 | btrfs_lock_and_flush_ordered_range(inode, start, start + len - 1, &cached_state); | ||
| 919 | em = btrfs_get_extent(inode, folio, start, len); | 916 | em = btrfs_get_extent(inode, folio, start, len); |
| 920 | if (!IS_ERR(em)) { | 917 | if (!IS_ERR(em)) { |
| 921 | BUG_ON(*em_cached); | 918 | BUG_ON(*em_cached); |
| 922 | refcount_inc(&em->refs); | 919 | refcount_inc(&em->refs); |
| 923 | *em_cached = em; | 920 | *em_cached = em; |
| 924 | } | 921 | } |
| 925 | unlock_extent(&inode->io_tree, start, start + len - 1, &cached_state); | ||
| 926 | 922 | ||
| 927 | return em; | 923 | return em; |
| 928 | } | 924 | } |
| @@ -956,7 +952,7 @@ static int btrfs_do_readpage(struct folio *folio, struct extent_map **em_cached, · 27 unmodified lines | |||
| 956 | return ret; | 952 | return ret; |
| 957 | } | 953 | } |
| 958 | 954 | ||
| 959 | if (folio->index == last_byte >> folio_shift(folio)) { | 955 | if (folio_contains(folio, last_byte >> PAGE_SHIFT)) { |
| 960 | size_t zero_offset = offset_in_folio(folio, last_byte); | 956 | size_t zero_offset = offset_in_folio(folio, last_byte); |
| 961 | 957 | ||
| 962 | if (zero_offset) { | 958 | if (zero_offset) { |
| @@ -1079,11 +1075,18 @@ static int btrfs_do_readpage(struct folio *folio, struct extent_map **em_cached, · 116 unmodified lines | |||
| 1079 | 1075 | ||
| 1080 | int btrfs_read_folio(struct file *file, struct folio *folio) | 1076 | int btrfs_read_folio(struct file *file, struct folio *folio) |
| 1081 | { | 1077 | { |
| 1078 | struct btrfs_inode *inode = folio_to_inode(folio); | ||
| 1079 | const u64 start = folio_pos(folio); | ||
| 1080 | const u64 end = start + folio_size(folio) - 1; | ||
| 1081 | struct extent_state *cached_state = NULL; | ||
| 1082 | struct btrfs_bio_ctrl bio_ctrl = { .opf = REQ_OP_READ }; | 1082 | struct btrfs_bio_ctrl bio_ctrl = { .opf = REQ_OP_READ }; |
| 1083 | struct extent_map *em_cached = NULL; | 1083 | struct extent_map *em_cached = NULL; |
| 1084 | int ret; | 1084 | int ret; |
| 1085 | 1085 | ||
| 1086 | btrfs_lock_and_flush_ordered_range(inode, start, end, &cached_state); | ||
| 1086 | ret = btrfs_do_readpage(folio, &em_cached, &bio_ctrl, NULL); | 1087 | ret = btrfs_do_readpage(folio, &em_cached, &bio_ctrl, NULL); |
| 1088 | unlock_extent(&inode->io_tree, start, end, &cached_state); | ||
| 1089 | |||
| 1087 | free_extent_map(em_cached); | 1090 | free_extent_map(em_cached); |
| 1088 | 1091 | ||
| 1089 | /* | 1092 | /* |
| @@ -2380,12 +2383,20 @@ void btrfs_readahead(struct readahead_control *rac) · 1290 unmodified lines | |||
| 2380 | { | 2383 | { |
| 2381 | struct btrfs_bio_ctrl bio_ctrl = { .opf = REQ_OP_READ | REQ_RAHEAD }; | 2384 | struct btrfs_bio_ctrl bio_ctrl = { .opf = REQ_OP_READ | REQ_RAHEAD }; |
| 2382 | struct folio *folio; | 2385 | struct folio *folio; |
| 2386 | struct btrfs_inode *inode = BTRFS_I(rac->mapping->host); | ||
| 2387 | const u64 start = readahead_pos(rac); | ||
| 2388 | const u64 end = start + readahead_length(rac) - 1; | ||
| 2389 | struct extent_state *cached_state = NULL; | ||
| 2383 | struct extent_map *em_cached = NULL; | 2390 | struct extent_map *em_cached = NULL; |
| 2384 | u64 prev_em_start = (u64)-1; | 2391 | u64 prev_em_start = (u64)-1; |
| 2385 | 2392 | ||
| 2393 | btrfs_lock_and_flush_ordered_range(inode, start, end, &cached_state); | ||
| 2394 | |||
| 2386 | while ((folio = readahead_folio(rac)) != NULL) | 2395 | while ((folio = readahead_folio(rac)) != NULL) |
| 2387 | btrfs_do_readpage(folio, &em_cached, &bio_ctrl, &prev_em_start); | 2396 | btrfs_do_readpage(folio, &em_cached, &bio_ctrl, &prev_em_start); |
| 2388 | 2397 | ||
| 2398 | unlock_extent(&inode->io_tree, start, end, &cached_state); | ||
| 2399 | |||
| 2389 | if (em_cached) | 2400 | if (em_cached) |
| 2390 | free_extent_map(em_cached); | 2401 | free_extent_map(em_cached); |
| 2391 | submit_one_bio(&bio_ctrl); | 2402 | submit_one_bio(&bio_ctrl); |
| @@ -1039,7 +1039,6 @@ int btrfs_write_check(struct kiocb *iocb, size_t count) · 1038 unmodified lines | |||
| 1039 | loff_t pos = iocb->ki_pos; | 1039 | loff_t pos = iocb->ki_pos; |
| 1040 | int ret; | 1040 | int ret; |
| 1041 | loff_t oldsize; | 1041 | loff_t oldsize; |
| 1042 | loff_t start_pos; | ||
| 1043 | 1042 | ||
| 1044 | /* | 1043 | /* |
| 1045 | * Quickly bail out on NOWAIT writes if we don't have the nodatacow or | 1044 | * Quickly bail out on NOWAIT writes if we don't have the nodatacow or |
| @@ -1066,9 +1065,8 @@ int btrfs_write_check(struct kiocb *iocb, size_t count) · 20 unmodified lines | |||
| 1066 | inode_inc_iversion(inode); | 1065 | inode_inc_iversion(inode); |
| 1067 | } | 1066 | } |
| 1068 | 1067 | ||
| 1069 | start_pos = round_down(pos, fs_info->sectorsize); | ||
| 1070 | oldsize = i_size_read(inode); | 1068 | oldsize = i_size_read(inode); |
| 1071 | if (start_pos > oldsize) { | 1069 | if (pos > oldsize) { |
| 1072 | /* Expand hole size to cover write data, preventing empty gap */ | 1070 | /* Expand hole size to cover write data, preventing empty gap */ |
| 1073 | loff_t end_pos = round_up(pos + count, fs_info->sectorsize); | 1071 | loff_t end_pos = round_up(pos + count, fs_info->sectorsize); |
| 1074 | 1072 | ||
| @@ -1229,6 +1229,18 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( · 1228 unmodified lines | |||
| 1229 | */ | 1229 | */ |
| 1230 | if (WARN_ON_ONCE(len >= ordered->num_bytes)) | 1230 | if (WARN_ON_ONCE(len >= ordered->num_bytes)) |
| 1231 | return ERR_PTR(-EINVAL); | 1231 | return ERR_PTR(-EINVAL); |
| 1232 | /* | ||
| 1233 | * If our ordered extent had an error there's no point in continuing. | ||
| 1234 | * The error may have come from a transaction abort done either by this | ||
| 1235 | * task or some other concurrent task, and the transaction abort path | ||
| 1236 | * iterates over all existing ordered extents and sets the flag | ||
| 1237 | * BTRFS_ORDERED_IOERR on them. | ||
| 1238 | */ | ||
| 1239 | if (unlikely(flags & (1U << BTRFS_ORDERED_IOERR))) { | ||
| 1240 | const int fs_error = BTRFS_FS_ERROR(fs_info); | ||
| 1241 | |||
| 1242 | return fs_error ? ERR_PTR(fs_error) : ERR_PTR(-EIO); | ||
| 1243 | } | ||
| 1232 | /* We cannot split partially completed ordered extents. */ | 1244 | /* We cannot split partially completed ordered extents. */ |
| 1233 | if (ordered->bytes_left) { | 1245 | if (ordered->bytes_left) { |
| 1234 | ASSERT(!(flags & ~BTRFS_ORDERED_TYPE_FLAGS)); | 1246 | ASSERT(!(flags & ~BTRFS_ORDERED_TYPE_FLAGS)); |
| @@ -1880,11 +1880,7 @@ int btrfs_qgroup_cleanup_dropped_subvolume(struct btrfs_fs_info *fs_info, u64 su · 1879 unmodified lines | |||
| 1880 | * Commit current transaction to make sure all the rfer/excl numbers | 1880 | * Commit current transaction to make sure all the rfer/excl numbers |
| 1881 | * get updated. | 1881 | * get updated. |
| 1882 | */ | 1882 | */ |
| 1883 | trans = btrfs_start_transaction(fs_info->quota_root, 0); | 1883 | ret = btrfs_commit_current_transaction(fs_info->quota_root); |
| 1884 | if (IS_ERR(trans)) | ||
| 1885 | return PTR_ERR(trans); | ||
| 1886 | |||
| 1887 | ret = btrfs_commit_transaction(trans); | ||
| 1888 | if (ret < 0) | 1884 | if (ret < 0) |
| 1889 | return ret; | 1885 | return ret; |
| 1890 | 1886 | ||
| @@ -1897,8 +1893,11 @@ int btrfs_qgroup_cleanup_dropped_subvolume(struct btrfs_fs_info *fs_info, u64 su · 6 unmodified lines | |||
| 1897 | /* | 1893 | /* |
| 1898 | * It's squota and the subvolume still has numbers needed for future | 1894 | * It's squota and the subvolume still has numbers needed for future |
| 1899 | * accounting, in this case we can not delete it. Just skip it. | 1895 | * accounting, in this case we can not delete it. Just skip it. |
| 1896 | * | ||
| 1897 | * Or the qgroup is already removed by a qgroup rescan. For both cases we're | ||
| 1898 | * safe to ignore them. | ||
| 1900 | */ | 1899 | */ |
| 1901 | if (ret == -EBUSY) | 1900 | if (ret == -EBUSY || ret == -ENOENT) |
| 1902 | ret = 0; | 1901 | ret = 0; |
| 1903 | return ret; | 1902 | return ret; |
| 1904 | } | 1903 | } |
| @@ -274,8 +274,10 @@ loop: · 273 unmodified lines | |||
| 274 | cur_trans = fs_info->running_transaction; | 274 | cur_trans = fs_info->running_transaction; |
| 275 | if (cur_trans) { | 275 | if (cur_trans) { |
| 276 | if (TRANS_ABORTED(cur_trans)) { | 276 | if (TRANS_ABORTED(cur_trans)) { |
| 277 | const int abort_error = cur_trans->aborted; | ||
| 278 | |||
| 277 | spin_unlock(&fs_info->trans_lock); | 279 | spin_unlock(&fs_info->trans_lock); |
| 278 | return cur_trans->aborted; | 280 | return abort_error; |
| 279 | } | 281 | } |
| 280 | if (btrfs_blocked_trans_types[cur_trans->state] & type) { | 282 | if (btrfs_blocked_trans_types[cur_trans->state] & type) { |
| 281 | spin_unlock(&fs_info->trans_lock); | 283 | spin_unlock(&fs_info->trans_lock); |
| @@ -1700,7 +1700,7 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) · 1699 unmodified lines | |||
| 1700 | smp_store_release(&dentry->d_name.name, dname); /* ^^^ */ | 1700 | smp_store_release(&dentry->d_name.name, dname); /* ^^^ */ |
| 1701 | 1701 | ||
| 1702 | dentry->d_flags = 0; | 1702 | dentry->d_flags = 0; |
| 1703 | lockref_init(&dentry->d_lockref, 1); | 1703 | lockref_init(&dentry->d_lockref); |
| 1704 | seqcount_spinlock_init(&dentry->d_seq, &dentry->d_lock); | 1704 | seqcount_spinlock_init(&dentry->d_seq, &dentry->d_lock); |
| 1705 | dentry->d_inode = NULL; | 1705 | dentry->d_inode = NULL; |
| 1706 | dentry->d_parent = dentry; | 1706 | dentry->d_parent = dentry; |
| @@ -2966,11 +2966,11 @@ static int __d_unalias(struct dentry *dentry, struct dentry *alias) · 1259 unmodified lines | |||
| 2966 | goto out_err; | 2966 | goto out_err; |
| 2967 | m2 = &alias->d_parent->d_inode->i_rwsem; | 2967 | m2 = &alias->d_parent->d_inode->i_rwsem; |
| 2968 | out_unalias: | 2968 | out_unalias: |
| 2969 | if (alias->d_op->d_unalias_trylock && | 2969 | if (alias->d_op && alias->d_op->d_unalias_trylock && |
| 2970 | !alias->d_op->d_unalias_trylock(alias)) | 2970 | !alias->d_op->d_unalias_trylock(alias)) |
| 2971 | goto out_err; | 2971 | goto out_err; |
| 2972 | __d_move(alias, dentry, false); | 2972 | __d_move(alias, dentry, false); |
| 2973 | if (alias->d_op->d_unalias_unlock) | 2973 | if (alias->d_op && alias->d_op->d_unalias_unlock) |
| 2974 | alias->d_op->d_unalias_unlock(alias); | 2974 | alias->d_op->d_unalias_unlock(alias); |
| 2975 | ret = 0; | 2975 | ret = 0; |
| 2976 | out_err: | 2976 | out_err: |
| @@ -726,7 +726,7 @@ static int z_erofs_register_pcluster(struct z_erofs_frontend *fe) · 725 unmodified lines | |||
| 726 | if (IS_ERR(pcl)) | 726 | if (IS_ERR(pcl)) |
| 727 | return PTR_ERR(pcl); | 727 | return PTR_ERR(pcl); |
| 728 | 728 | ||
| 729 | lockref_init(&pcl->lockref, 1); /* one ref for this request */ | 729 | lockref_init(&pcl->lockref); /* one ref for this request */ |
| 730 | pcl->algorithmformat = map->m_algorithmformat; | 730 | pcl->algorithmformat = map->m_algorithmformat; |
| 731 | pcl->length = 0; | 731 | pcl->length = 0; |
| 732 | pcl->partial = true; | 732 | pcl->partial = true; |
| @@ -194,6 +194,11 @@ static int init_file(struct file *f, int flags, const struct cred *cred) · 193 unmodified lines | |||
| 194 | * refcount bumps we should reinitialize the reused file first. | 194 | * refcount bumps we should reinitialize the reused file first. |
| 195 | */ | 195 | */ |
| 196 | file_ref_init(&f->f_ref, 1); | 196 | file_ref_init(&f->f_ref, 1); |
| 197 | /* | ||
| 198 | * Disable permission and pre-content events for all files by default. | ||
| 199 | * They may be enabled later by file_set_fsnotify_mode_from_watchers(). | ||
| 200 | */ | ||
| 201 | file_set_fsnotify_mode(f, FMODE_NONOTIFY_PERM); | ||
| 197 | return 0; | 202 | return 0; |
| 198 | } | 203 | } |
| 199 | 204 | ||
| @@ -375,7 +380,13 @@ struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt, · 175 unmodified lines | |||
| 375 | if (IS_ERR(file)) { | 380 | if (IS_ERR(file)) { |
| 376 | ihold(inode); | 381 | ihold(inode); |
| 377 | path_put(&path); | 382 | path_put(&path); |
| 383 | return file; | ||
| 378 | } | 384 | } |
| 385 | /* | ||
| 386 | * Disable all fsnotify events for pseudo files by default. | ||
| 387 | * They may be enabled by caller with file_set_fsnotify_mode(). | ||
| 388 | */ | ||
| 389 | file_set_fsnotify_mode(file, FMODE_NONOTIFY); | ||
| 379 | return file; | 390 | return file; |
| 380 | } | 391 | } |
| 381 | EXPORT_SYMBOL(alloc_file_pseudo); | 392 | EXPORT_SYMBOL(alloc_file_pseudo); |
| @@ -400,6 +411,11 @@ struct file *alloc_file_pseudo_noaccount(struct inode *inode, · 18 unmodified lines | |||
| 400 | return file; | 411 | return file; |
| 401 | } | 412 | } |
| 402 | file_init_path(file, &path, fops); | 413 | file_init_path(file, &path, fops); |
| 414 | /* | ||
| 415 | * Disable all fsnotify events for pseudo files by default. | ||
| 416 | * They may be enabled by caller with file_set_fsnotify_mode(). | ||
| 417 | */ | ||
| 418 | file_set_fsnotify_mode(file, FMODE_NONOTIFY); | ||
| 403 | return file; | 419 | return file; |
| 404 | } | 420 | } |
| 405 | EXPORT_SYMBOL_GPL(alloc_file_pseudo_noaccount); | 421 | EXPORT_SYMBOL_GPL(alloc_file_pseudo_noaccount); |
| @@ -1201,8 +1201,8 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, · 1200 unmodified lines | |||
| 1201 | if (glops->go_instantiate) | 1201 | if (glops->go_instantiate) |
| 1202 | gl->gl_flags |= BIT(GLF_INSTANTIATE_NEEDED); | 1202 | gl->gl_flags |= BIT(GLF_INSTANTIATE_NEEDED); |
| 1203 | gl->gl_name = name; | 1203 | gl->gl_name = name; |
| 1204 | lockref_init(&gl->gl_lockref); | ||
| 1204 | lockdep_set_subclass(&gl->gl_lockref.lock, glops->go_subclass); | 1205 | lockdep_set_subclass(&gl->gl_lockref.lock, glops->go_subclass); |
| 1205 | gl->gl_lockref.count = 1; | ||
| 1206 | gl->gl_state = LM_ST_UNLOCKED; | 1206 | gl->gl_state = LM_ST_UNLOCKED; |
| 1207 | gl->gl_target = LM_ST_UNLOCKED; | 1207 | gl->gl_target = LM_ST_UNLOCKED; |
| 1208 | gl->gl_demote_state = LM_ST_EXCLUSIVE; | 1208 | gl->gl_demote_state = LM_ST_EXCLUSIVE; |
| @@ -51,7 +51,6 @@ static void gfs2_init_glock_once(void *foo) · 50 unmodified lines | |||
| 51 | { | 51 | { |
| 52 | struct gfs2_glock *gl = foo; | 52 | struct gfs2_glock *gl = foo; |
| 53 | 53 | ||
| 54 | spin_lock_init(&gl->gl_lockref.lock); | ||
| 55 | INIT_LIST_HEAD(&gl->gl_holders); | 54 | INIT_LIST_HEAD(&gl->gl_holders); |
| 56 | INIT_LIST_HEAD(&gl->gl_lru); | 55 | INIT_LIST_HEAD(&gl->gl_lru); |
| 57 | INIT_LIST_HEAD(&gl->gl_ail_list); | 56 | INIT_LIST_HEAD(&gl->gl_ail_list); |
| @@ -236,7 +236,7 @@ static struct gfs2_quota_data *qd_alloc(unsigned hash, struct gfs2_sbd *sdp, str · 235 unmodified lines | |||
| 236 | return NULL; | 236 | return NULL; |
| 237 | 237 | ||
| 238 | qd->qd_sbd = sdp; | 238 | qd->qd_sbd = sdp; |
| 239 | lockref_init(&qd->qd_lockref, 0); | 239 | lockref_init(&qd->qd_lockref); |
| 240 | qd->qd_id = qid; | 240 | qd->qd_id = qid; |
| 241 | qd->qd_slot = -1; | 241 | qd->qd_slot = -1; |
| 242 | INIT_LIST_HEAD(&qd->qd_lru); | 242 | INIT_LIST_HEAD(&qd->qd_lru); |
| @@ -297,7 +297,6 @@ static int qd_get(struct gfs2_sbd *sdp, struct kqid qid, · 54 unmodified lines | |||
| 297 | spin_lock_bucket(hash); | 297 | spin_lock_bucket(hash); |
| 298 | *qdp = qd = gfs2_qd_search_bucket(hash, sdp, qid); | 298 | *qdp = qd = gfs2_qd_search_bucket(hash, sdp, qid); |
| 299 | if (qd == NULL) { | 299 | if (qd == NULL) { |
| 300 | new_qd->qd_lockref.count++; | ||
| 301 | *qdp = new_qd; | 300 | *qdp = new_qd; |
| 302 | list_add(&new_qd->qd_list, &sdp->sd_quota_list); | 301 | list_add(&new_qd->qd_list, &sdp->sd_quota_list); |
| 303 | hlist_bl_add_head_rcu(&new_qd->qd_hlist, &qd_hash_table[hash]); | 302 | hlist_bl_add_head_rcu(&new_qd->qd_hlist, &qd_hash_table[hash]); |
| @@ -1450,6 +1449,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) · 1146 unmodified lines | |||
| 1450 | if (qd == NULL) | 1449 | if (qd == NULL) |
| 1451 | goto fail_brelse; | 1450 | goto fail_brelse; |
| 1452 | 1451 | ||
| 1452 | qd->qd_lockref.count = 0; | ||
| 1453 | set_bit(QDF_CHANGE, &qd->qd_flags); | 1453 | set_bit(QDF_CHANGE, &qd->qd_flags); |
| 1454 | qd->qd_change = qc_change; | 1454 | qd->qd_change = qc_change; |
| 1455 | qd->qd_slot = slot; | 1455 | qd->qd_slot = slot; |
| @@ -5087,30 +5087,29 @@ static int statmount_mnt_opts(struct kstatmount *s, struct seq_file *seq) · 5086 unmodified lines | |||
| 5087 | { | 5087 | { |
| 5088 | struct vfsmount *mnt = s->mnt; | 5088 | struct vfsmount *mnt = s->mnt; |
| 5089 | struct super_block *sb = mnt->mnt_sb; | 5089 | struct super_block *sb = mnt->mnt_sb; |
| 5090 | size_t start = seq->count; | ||
| 5090 | int err; | 5091 | int err; |
| 5091 | 5092 | ||
| 5092 | if (sb->s_op->show_options) { | 5093 | err = security_sb_show_options(seq, sb); |
| 5093 | size_t start = seq->count; | 5094 | if (err) |
| 5094 | 5095 | return err; | |
| 5095 | err = security_sb_show_options(seq, sb); | ||
| 5096 | if (err) | ||
| 5097 | return err; | ||
| 5098 | 5096 | ||
| 5097 | if (sb->s_op->show_options) { | ||
| 5099 | err = sb->s_op->show_options(seq, mnt->mnt_root); | 5098 | err = sb->s_op->show_options(seq, mnt->mnt_root); |
| 5100 | if (err) | 5099 | if (err) |
| 5101 | return err; | 5100 | return err; |
| 5101 | } | ||
| 5102 | 5102 | ||
| 5103 | if (unlikely(seq_has_overflowed(seq))) | 5103 | if (unlikely(seq_has_overflowed(seq))) |
| 5104 | return -EAGAIN; | 5104 | return -EAGAIN; |
| 5105 | 5105 | ||
| 5106 | if (seq->count == start) | 5106 | if (seq->count == start) |
| 5107 | return 0; | 5107 | return 0; |
| 5108 | 5108 | ||
| 5109 | /* skip leading comma */ | 5109 | /* skip leading comma */ |
| 5110 | memmove(seq->buf + start, seq->buf + start + 1, | 5110 | memmove(seq->buf + start, seq->buf + start + 1, |
| 5111 | seq->count - start - 1); | 5111 | seq->count - start - 1); |
| 5112 | seq->count--; | 5112 | seq->count--; |
| 5113 | } | ||
| 5114 | 5113 | ||
| 5115 | return 0; | 5114 | return 0; |
| 5116 | } | 5115 | } |
| @@ -5191,39 +5190,45 @@ static int statmount_string(struct kstatmount *s, u64 flag) · 74 unmodified lines | |||
| 5191 | size_t kbufsize; | 5190 | size_t kbufsize; |
| 5192 | struct seq_file *seq = &s->seq; | 5191 | struct seq_file *seq = &s->seq; |
| 5193 | struct statmount *sm = &s->sm; | 5192 | struct statmount *sm = &s->sm; |
| 5194 | u32 start = seq->count; | 5193 | u32 start, *offp; |
| 5194 | |||
| 5195 | /* Reserve an empty string at the beginning for any unset offsets */ | ||
| 5196 | if (!seq->count) | ||
| 5197 | seq_putc(seq, 0); | ||
| 5198 | |||
| 5199 | start = seq->count; | ||
| 5195 | 5200 | ||
| 5196 | switch (flag) { | 5201 | switch (flag) { |
| 5197 | case STATMOUNT_FS_TYPE: | 5202 | case STATMOUNT_FS_TYPE: |
| 5198 | sm->fs_type = start; | 5203 | offp = &sm->fs_type; |
| 5199 | ret = statmount_fs_type(s, seq); | 5204 | ret = statmount_fs_type(s, seq); |
| 5200 | break; | 5205 | break; |
| 5201 | case STATMOUNT_MNT_ROOT: | 5206 | case STATMOUNT_MNT_ROOT: |
| 5202 | sm->mnt_root = start; | 5207 | offp = &sm->mnt_root; |
| 5203 | ret = statmount_mnt_root(s, seq); | 5208 | ret = statmount_mnt_root(s, seq); |
| 5204 | break; | 5209 | break; |
| 5205 | case STATMOUNT_MNT_POINT: | 5210 | case STATMOUNT_MNT_POINT: |
| 5206 | sm->mnt_point = start; | 5211 | offp = &sm->mnt_point; |
| 5207 | ret = statmount_mnt_point(s, seq); | 5212 | ret = statmount_mnt_point(s, seq); |
| 5208 | break; | 5213 | break; |
| 5209 | case STATMOUNT_MNT_OPTS: | 5214 | case STATMOUNT_MNT_OPTS: |
| 5210 | sm->mnt_opts = start; | 5215 | offp = &sm->mnt_opts; |
| 5211 | ret = statmount_mnt_opts(s, seq); | 5216 | ret = statmount_mnt_opts(s, seq); |
| 5212 | break; | 5217 | break; |
| 5213 | case STATMOUNT_OPT_ARRAY: | 5218 | case STATMOUNT_OPT_ARRAY: |
| 5214 | sm->opt_array = start; | 5219 | offp = &sm->opt_array; |
| 5215 | ret = statmount_opt_array(s, seq); | 5220 | ret = statmount_opt_array(s, seq); |
| 5216 | break; | 5221 | break; |
| 5217 | case STATMOUNT_OPT_SEC_ARRAY: | 5222 | case STATMOUNT_OPT_SEC_ARRAY: |
| 5218 | sm->opt_sec_array = start; | 5223 | offp = &sm->opt_sec_array; |
| 5219 | ret = statmount_opt_sec_array(s, seq); | 5224 | ret = statmount_opt_sec_array(s, seq); |
| 5220 | break; | 5225 | break; |
| 5221 | case STATMOUNT_FS_SUBTYPE: | 5226 | case STATMOUNT_FS_SUBTYPE: |
| 5222 | sm->fs_subtype = start; | 5227 | offp = &sm->fs_subtype; |
| 5223 | statmount_fs_subtype(s, seq); | 5228 | statmount_fs_subtype(s, seq); |
| 5224 | break; | 5229 | break; |
| 5225 | case STATMOUNT_SB_SOURCE: | 5230 | case STATMOUNT_SB_SOURCE: |
| 5226 | sm->sb_source = start; | 5231 | offp = &sm->sb_source; |
| 5227 | ret = statmount_sb_source(s, seq); | 5232 | ret = statmount_sb_source(s, seq); |
| 5228 | break; | 5233 | break; |
| 5229 | default: | 5234 | default: |
| @@ -5251,6 +5256,7 @@ static int statmount_string(struct kstatmount *s, u64 flag) · 21 unmodified lines | |||
| 5251 | 5256 | ||
| 5252 | seq->buf[seq->count++] = '\0'; | 5257 | seq->buf[seq->count++] = '\0'; |
| 5253 | sm->mask |= flag; | 5258 | sm->mask |= flag; |
| 5259 | *offp = start; | ||
| 5254 | return 0; | 5260 | return 0; |
| 5255 | } | 5261 | } |
| 5256 | 5262 | ||
| @@ -155,8 +155,9 @@ static void netfs_read_cache_to_pagecache(struct netfs_io_request *rreq, · 154 unmodified lines | |||
| 155 | netfs_cache_read_terminated, subreq); | 155 | netfs_cache_read_terminated, subreq); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | static void netfs_issue_read(struct netfs_io_request *rreq, | 158 | static void netfs_queue_read(struct netfs_io_request *rreq, |
| 159 | struct netfs_io_subrequest *subreq) | 159 | struct netfs_io_subrequest *subreq, |
| 160 | bool last_subreq) | ||
| 160 | { | 161 | { |
| 161 | struct netfs_io_stream *stream = &rreq->io_streams[0]; | 162 | struct netfs_io_stream *stream = &rreq->io_streams[0]; |
| 162 | 163 | ||
| @@ -177,8 +178,17 @@ static void netfs_issue_read(struct netfs_io_request *rreq, · 14 unmodified lines | |||
| 177 | } | 178 | } |
| 178 | } | 179 | } |
| 179 | 180 | ||
| 181 | if (last_subreq) { | ||
| 182 | smp_wmb(); /* Write lists before ALL_QUEUED. */ | ||
| 183 | set_bit(NETFS_RREQ_ALL_QUEUED, &rreq->flags); | ||
| 184 | } | ||
| 185 | |||
| 180 | spin_unlock(&rreq->lock); | 186 | spin_unlock(&rreq->lock); |
| 187 | } | ||
| 181 | 188 | ||
| 189 | static void netfs_issue_read(struct netfs_io_request *rreq, | ||
| 190 | struct netfs_io_subrequest *subreq) | ||
| 191 | { | ||
| 182 | switch (subreq->source) { | 192 | switch (subreq->source) { |
| 183 | case NETFS_DOWNLOAD_FROM_SERVER: | 193 | case NETFS_DOWNLOAD_FROM_SERVER: |
| 184 | rreq->netfs_ops->issue_read(subreq); | 194 | rreq->netfs_ops->issue_read(subreq); |
| @@ -293,11 +303,8 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq) · 108 unmodified lines | |||
| 293 | } | 303 | } |
| 294 | size -= slice; | 304 | size -= slice; |
| 295 | start += slice; | 305 | start += slice; |
| 296 | if (size <= 0) { | ||
| 297 | smp_wmb(); /* Write lists before ALL_QUEUED. */ | ||
| 298 | set_bit(NETFS_RREQ_ALL_QUEUED, &rreq->flags); | ||
| 299 | } | ||
| 300 | 306 | ||
| 307 | netfs_queue_read(rreq, subreq, size <= 0); | ||
| 301 | netfs_issue_read(rreq, subreq); | 308 | netfs_issue_read(rreq, subreq); |
| 302 | cond_resched(); | 309 | cond_resched(); |
| 303 | } while (size > 0); | 310 | } while (size > 0); |
| @@ -135,6 +135,8 @@ extern atomic_t netfs_n_rh_write_begin; · 134 unmodified lines | |||
| 135 | extern atomic_t netfs_n_rh_write_done; | 135 | extern atomic_t netfs_n_rh_write_done; |
| 136 | extern atomic_t netfs_n_rh_write_failed; | 136 | extern atomic_t netfs_n_rh_write_failed; |
| 137 | extern atomic_t netfs_n_rh_write_zskip; | 137 | extern atomic_t netfs_n_rh_write_zskip; |
| 138 | extern atomic_t netfs_n_rh_retry_read_req; | ||
| 139 | extern atomic_t netfs_n_rh_retry_read_subreq; | ||
| 138 | extern atomic_t netfs_n_wh_buffered_write; | 140 | extern atomic_t netfs_n_wh_buffered_write; |
| 139 | extern atomic_t netfs_n_wh_writethrough; | 141 | extern atomic_t netfs_n_wh_writethrough; |
| 140 | extern atomic_t netfs_n_wh_dio_write; | 142 | extern atomic_t netfs_n_wh_dio_write; |
| @@ -147,6 +149,8 @@ extern atomic_t netfs_n_wh_upload_failed; · 6 unmodified lines | |||
| 147 | extern atomic_t netfs_n_wh_write; | 149 | extern atomic_t netfs_n_wh_write; |
| 148 | extern atomic_t netfs_n_wh_write_done; | 150 | extern atomic_t netfs_n_wh_write_done; |
| 149 | extern atomic_t netfs_n_wh_write_failed; | 151 | extern atomic_t netfs_n_wh_write_failed; |
| 152 | extern atomic_t netfs_n_wh_retry_write_req; | ||
| 153 | extern atomic_t netfs_n_wh_retry_write_subreq; | ||
| 150 | extern atomic_t netfs_n_wb_lock_skip; | 154 | extern atomic_t netfs_n_wb_lock_skip; |
| 151 | extern atomic_t netfs_n_wb_lock_wait; | 155 | extern atomic_t netfs_n_wb_lock_wait; |
| 152 | extern atomic_t netfs_n_folioq; | 156 | extern atomic_t netfs_n_folioq; |
| @@ -470,7 +470,8 @@ void netfs_read_collection_worker(struct work_struct *work) · 469 unmodified lines | |||
| 470 | */ | 470 | */ |
| 471 | void netfs_wake_read_collector(struct netfs_io_request *rreq) | 471 | void netfs_wake_read_collector(struct netfs_io_request *rreq) |
| 472 | { | 472 | { |
| 473 | if (test_bit(NETFS_RREQ_OFFLOAD_COLLECTION, &rreq->flags)) { | 473 | if (test_bit(NETFS_RREQ_OFFLOAD_COLLECTION, &rreq->flags) && |
| 474 | !test_bit(NETFS_RREQ_RETRYING, &rreq->flags)) { | ||
| 474 | if (!work_pending(&rreq->work)) { | 475 | if (!work_pending(&rreq->work)) { |
| 475 | netfs_get_request(rreq, netfs_rreq_trace_get_work); | 476 | netfs_get_request(rreq, netfs_rreq_trace_get_work); |
| 476 | if (!queue_work(system_unbound_wq, &rreq->work)) | 477 | if (!queue_work(system_unbound_wq, &rreq->work)) |
| @@ -586,7 +587,8 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq) · 109 unmodified lines | |||
| 586 | smp_mb__after_atomic(); /* Clear IN_PROGRESS before task state */ | 587 | smp_mb__after_atomic(); /* Clear IN_PROGRESS before task state */ |
| 587 | 588 | ||
| 588 | /* If we are at the head of the queue, wake up the collector. */ | 589 | /* If we are at the head of the queue, wake up the collector. */ |
| 589 | if (list_is_first(&subreq->rreq_link, &stream->subrequests)) | 590 | if (list_is_first(&subreq->rreq_link, &stream->subrequests) || |
| 591 | test_bit(NETFS_RREQ_RETRYING, &rreq->flags)) | ||
| 590 | netfs_wake_read_collector(rreq); | 592 | netfs_wake_read_collector(rreq); |
| 591 | 593 | ||
| 592 | netfs_put_subrequest(subreq, true, netfs_sreq_trace_put_terminated); | 594 | netfs_put_subrequest(subreq, true, netfs_sreq_trace_put_terminated); |
| @@ -14,7 +14,7 @@ static void netfs_reissue_read(struct netfs_io_request *rreq, · 13 unmodified lines | |||
| 14 | { | 14 | { |
| 15 | __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); | 15 | __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); |
| 16 | __set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags); | 16 | __set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags); |
| 17 | netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); | 17 | netfs_stat(&netfs_n_rh_retry_read_subreq); |
| 18 | subreq->rreq->netfs_ops->issue_read(subreq); | 18 | subreq->rreq->netfs_ops->issue_read(subreq); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| @@ -48,6 +48,7 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq) · 27 unmodified lines | |||
| 48 | __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); | 48 | __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); |
| 49 | subreq->retry_count++; | 49 | subreq->retry_count++; |
| 50 | netfs_reset_iter(subreq); | 50 | netfs_reset_iter(subreq); |
| 51 | netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); | ||
| 51 | netfs_reissue_read(rreq, subreq); | 52 | netfs_reissue_read(rreq, subreq); |
| 52 | } | 53 | } |
| 53 | } | 54 | } |
| @@ -75,7 +76,7 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq) · 21 unmodified lines | |||
| 75 | struct iov_iter source; | 76 | struct iov_iter source; |
| 76 | unsigned long long start, len; | 77 | unsigned long long start, len; |
| 77 | size_t part; | 78 | size_t part; |
| 78 | bool boundary = false; | 79 | bool boundary = false, subreq_superfluous = false; |
| 79 | 80 | ||
| 80 | /* Go through the subreqs and find the next span of contiguous | 81 | /* Go through the subreqs and find the next span of contiguous |
| 81 | * buffer that we then rejig (cifs, for example, needs the | 82 | * buffer that we then rejig (cifs, for example, needs the |
| @@ -116,8 +117,10 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq) · 34 unmodified lines | |||
| 116 | /* Work through the sublist. */ | 117 | /* Work through the sublist. */ |
| 117 | subreq = from; | 118 | subreq = from; |
| 118 | list_for_each_entry_from(subreq, &stream->subrequests, rreq_link) { | 119 | list_for_each_entry_from(subreq, &stream->subrequests, rreq_link) { |
| 119 | if (!len) | 120 | if (!len) { |
| 121 | subreq_superfluous = true; | ||
| 120 | break; | 122 | break; |
| 123 | } | ||
| 121 | subreq->source = NETFS_DOWNLOAD_FROM_SERVER; | 124 | subreq->source = NETFS_DOWNLOAD_FROM_SERVER; |
| 122 | subreq->start = start - subreq->transferred; | 125 | subreq->start = start - subreq->transferred; |
| 123 | subreq->len = len + subreq->transferred; | 126 | subreq->len = len + subreq->transferred; |
| @@ -154,19 +157,21 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq) · 30 unmodified lines | |||
| 154 | 157 | ||
| 155 | netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); | 158 | netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); |
| 156 | netfs_reissue_read(rreq, subreq); | 159 | netfs_reissue_read(rreq, subreq); |
| 157 | if (subreq == to) | 160 | if (subreq == to) { |
| 161 | subreq_superfluous = false; | ||
| 158 | break; | 162 | break; |
| 163 | } | ||
| 159 | } | 164 | } |
| 160 | 165 | ||
| 161 | /* If we managed to use fewer subreqs, we can discard the | 166 | /* If we managed to use fewer subreqs, we can discard the |
| 162 | * excess; if we used the same number, then we're done. | 167 | * excess; if we used the same number, then we're done. |
| 163 | */ | 168 | */ |
| 164 | if (!len) { | 169 | if (!len) { |
| 165 | if (subreq == to) | 170 | if (!subreq_superfluous) |
| 166 | continue; | 171 | continue; |
| 167 | list_for_each_entry_safe_from(subreq, tmp, | 172 | list_for_each_entry_safe_from(subreq, tmp, |
| 168 | &stream->subrequests, rreq_link) { | 173 | &stream->subrequests, rreq_link) { |
| 169 | trace_netfs_sreq(subreq, netfs_sreq_trace_discard); | 174 | trace_netfs_sreq(subreq, netfs_sreq_trace_superfluous); |
| 170 | list_del(&subreq->rreq_link); | 175 | list_del(&subreq->rreq_link); |
| 171 | netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_done); | 176 | netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_done); |
| 172 | if (subreq == to) | 177 | if (subreq == to) |
| @@ -187,14 +192,12 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq) · 14 unmodified lines | |||
| 187 | subreq->source = NETFS_DOWNLOAD_FROM_SERVER; | 192 | subreq->source = NETFS_DOWNLOAD_FROM_SERVER; |
| 188 | subreq->start = start; | 193 | subreq->start = start; |
| 189 | subreq->len = len; | 194 | subreq->len = len; |
| 190 | subreq->debug_index = atomic_inc_return(&rreq->subreq_counter); | ||
| 191 | subreq->stream_nr = stream->stream_nr; | 195 | subreq->stream_nr = stream->stream_nr; |
| 192 | subreq->retry_count = 1; | 196 | subreq->retry_count = 1; |
| 193 | 197 | ||
| 194 | trace_netfs_sreq_ref(rreq->debug_id, subreq->debug_index, | 198 | trace_netfs_sreq_ref(rreq->debug_id, subreq->debug_index, |
| 195 | refcount_read(&subreq->ref), | 199 | refcount_read(&subreq->ref), |
| 196 | netfs_sreq_trace_new); | 200 | netfs_sreq_trace_new); |
| 197 | netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); | ||
| 198 | 201 | ||
| 199 | list_add(&subreq->rreq_link, &to->rreq_link); | 202 | list_add(&subreq->rreq_link, &to->rreq_link); |
| 200 | to = list_next_entry(to, rreq_link); | 203 | to = list_next_entry(to, rreq_link); |
| @@ -256,14 +259,34 @@ void netfs_retry_reads(struct netfs_io_request *rreq) · 55 unmodified lines | |||
| 256 | { | 259 | { |
| 257 | struct netfs_io_subrequest *subreq; | 260 | struct netfs_io_subrequest *subreq; |
| 258 | struct netfs_io_stream *stream = &rreq->io_streams[0]; | 261 | struct netfs_io_stream *stream = &rreq->io_streams[0]; |
| 262 | DEFINE_WAIT(myself); | ||
| 263 | |||
| 264 | netfs_stat(&netfs_n_rh_retry_read_req); | ||
| 265 | |||
| 266 | set_bit(NETFS_RREQ_RETRYING, &rreq->flags); | ||
| 259 | 267 | ||
| 260 | /* Wait for all outstanding I/O to quiesce before performing retries as | 268 | /* Wait for all outstanding I/O to quiesce before performing retries as |
| 261 | * we may need to renegotiate the I/O sizes. | 269 | * we may need to renegotiate the I/O sizes. |
| 262 | */ | 270 | */ |
| 263 | list_for_each_entry(subreq, &stream->subrequests, rreq_link) { | 271 | list_for_each_entry(subreq, &stream->subrequests, rreq_link) { |
| 264 | wait_on_bit(&subreq->flags, NETFS_SREQ_IN_PROGRESS, | 272 | if (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags)) |
| 265 | TASK_UNINTERRUPTIBLE); | 273 | continue; |
| 274 | |||
| 275 | trace_netfs_rreq(rreq, netfs_rreq_trace_wait_queue); | ||
| 276 | for (;;) { | ||
| 277 | prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE); | ||
| 278 | |||
| 279 | if (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags)) | ||
| 280 | break; | ||
| 281 | |||
| 282 | trace_netfs_sreq(subreq, netfs_sreq_trace_wait_for); | ||
| 283 | schedule(); | ||
| 284 | trace_netfs_rreq(rreq, netfs_rreq_trace_woke_queue); | ||
| 285 | } | ||
| 286 | |||
| 287 | finish_wait(&rreq->waitq, &myself); | ||
| 266 | } | 288 | } |
| 289 | clear_bit(NETFS_RREQ_RETRYING, &rreq->flags); | ||
| 267 | 290 | ||
| 268 | trace_netfs_rreq(rreq, netfs_rreq_trace_resubmit); | 291 | trace_netfs_rreq(rreq, netfs_rreq_trace_resubmit); |
| 269 | netfs_retry_read_subrequests(rreq); | 292 | netfs_retry_read_subrequests(rreq); |
| @@ -29,6 +29,8 @@ atomic_t netfs_n_rh_write_begin; · 28 unmodified lines | |||
| 29 | atomic_t netfs_n_rh_write_done; | 29 | atomic_t netfs_n_rh_write_done; |
| 30 | atomic_t netfs_n_rh_write_failed; | 30 | atomic_t netfs_n_rh_write_failed; |
| 31 | atomic_t netfs_n_rh_write_zskip; | 31 | atomic_t netfs_n_rh_write_zskip; |
| 32 | atomic_t netfs_n_rh_retry_read_req; | ||
| 33 | atomic_t netfs_n_rh_retry_read_subreq; | ||
| 32 | atomic_t netfs_n_wh_buffered_write; | 34 | atomic_t netfs_n_wh_buffered_write; |
| 33 | atomic_t netfs_n_wh_writethrough; | 35 | atomic_t netfs_n_wh_writethrough; |
| 34 | atomic_t netfs_n_wh_dio_write; | 36 | atomic_t netfs_n_wh_dio_write; |
| @@ -41,6 +43,8 @@ atomic_t netfs_n_wh_upload_failed; · 6 unmodified lines | |||
| 41 | atomic_t netfs_n_wh_write; | 43 | atomic_t netfs_n_wh_write; |
| 42 | atomic_t netfs_n_wh_write_done; | 44 | atomic_t netfs_n_wh_write_done; |
| 43 | atomic_t netfs_n_wh_write_failed; | 45 | atomic_t netfs_n_wh_write_failed; |
| 46 | atomic_t netfs_n_wh_retry_write_req; | ||
| 47 | atomic_t netfs_n_wh_retry_write_subreq; | ||
| 44 | atomic_t netfs_n_wb_lock_skip; | 48 | atomic_t netfs_n_wb_lock_skip; |
| 45 | atomic_t netfs_n_wb_lock_wait; | 49 | atomic_t netfs_n_wb_lock_wait; |
| 46 | atomic_t netfs_n_folioq; | 50 | atomic_t netfs_n_folioq; |
| @@ -81,6 +85,11 @@ int netfs_stats_show(struct seq_file *m, void *v) · 34 unmodified lines | |||
| 81 | atomic_read(&netfs_n_wh_write), | 85 | atomic_read(&netfs_n_wh_write), |
| 82 | atomic_read(&netfs_n_wh_write_done), | 86 | atomic_read(&netfs_n_wh_write_done), |
| 83 | atomic_read(&netfs_n_wh_write_failed)); | 87 | atomic_read(&netfs_n_wh_write_failed)); |
| 88 | seq_printf(m, "Retries: rq=%u rs=%u wq=%u ws=%u\n", | ||
| 89 | atomic_read(&netfs_n_rh_retry_read_req), | ||
| 90 | atomic_read(&netfs_n_rh_retry_read_subreq), | ||
| 91 | atomic_read(&netfs_n_wh_retry_write_req), | ||
| 92 | atomic_read(&netfs_n_wh_retry_write_subreq)); | ||
| 84 | seq_printf(m, "Objs : rr=%u sr=%u foq=%u wsc=%u\n", | 93 | seq_printf(m, "Objs : rr=%u sr=%u foq=%u wsc=%u\n", |
| 85 | atomic_read(&netfs_n_rh_rreq), | 94 | atomic_read(&netfs_n_rh_rreq), |
| 86 | atomic_read(&netfs_n_rh_sreq), | 95 | atomic_read(&netfs_n_rh_sreq), |
| @@ -253,6 +253,7 @@ void netfs_reissue_write(struct netfs_io_stream *stream, · 252 unmodified lines | |||
| 253 | subreq->retry_count++; | 253 | subreq->retry_count++; |
| 254 | __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); | 254 | __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); |
| 255 | __set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags); | 255 | __set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags); |
| 256 | netfs_stat(&netfs_n_wh_retry_write_subreq); | ||
| 256 | netfs_do_issue_write(stream, subreq); | 257 | netfs_do_issue_write(stream, subreq); |
| 257 | } | 258 | } |
| 258 | 259 | ||
| @@ -203,6 +203,8 @@ void netfs_retry_writes(struct netfs_io_request *wreq) · 202 unmodified lines | |||
| 203 | struct netfs_io_stream *stream; | 203 | struct netfs_io_stream *stream; |
| 204 | int s; | 204 | int s; |
| 205 | 205 | ||
| 206 | netfs_stat(&netfs_n_wh_retry_write_req); | ||
| 207 | |||
| 206 | /* Wait for all outstanding I/O to quiesce before performing retries as | 208 | /* Wait for all outstanding I/O to quiesce before performing retries as |
| 207 | * we may need to renegotiate the I/O sizes. | 209 | * we may need to renegotiate the I/O sizes. |
| 208 | */ | 210 | */ |
| @@ -446,11 +446,20 @@ nfsd_file_dispose_list_delayed(struct list_head *dispose) · 445 unmodified lines | |||
| 446 | struct nfsd_file, nf_gc); | 446 | struct nfsd_file, nf_gc); |
| 447 | struct nfsd_net *nn = net_generic(nf->nf_net, nfsd_net_id); | 447 | struct nfsd_net *nn = net_generic(nf->nf_net, nfsd_net_id); |
| 448 | struct nfsd_fcache_disposal *l = nn->fcache_disposal; | 448 | struct nfsd_fcache_disposal *l = nn->fcache_disposal; |
| 449 | struct svc_serv *serv; | ||
| 449 | 450 | ||
| 450 | spin_lock(&l->lock); | 451 | spin_lock(&l->lock); |
| 451 | list_move_tail(&nf->nf_gc, &l->freeme); | 452 | list_move_tail(&nf->nf_gc, &l->freeme); |
| 452 | spin_unlock(&l->lock); | 453 | spin_unlock(&l->lock); |
| 453 | svc_wake_up(nn->nfsd_serv); | 454 | |
| 455 | /* | ||
| 456 | * The filecache laundrette is shut down after the | ||
| 457 | * nn->nfsd_serv pointer is cleared, but before the | ||
| 458 | * svc_serv is freed. | ||
| 459 | */ | ||
| 460 | serv = nn->nfsd_serv; | ||
| 461 | if (serv) | ||
| 462 | svc_wake_up(serv); | ||
| 454 | } | 463 | } |
| 455 | } | 464 | } |
| 456 | 465 | ||
| @@ -84,6 +84,8 @@ out: · 83 unmodified lines | |||
| 84 | fail: | 84 | fail: |
| 85 | posix_acl_release(resp->acl_access); | 85 | posix_acl_release(resp->acl_access); |
| 86 | posix_acl_release(resp->acl_default); | 86 | posix_acl_release(resp->acl_default); |
| 87 | resp->acl_access = NULL; | ||
| 88 | resp->acl_default = NULL; | ||
| 87 | goto out; | 89 | goto out; |
| 88 | } | 90 | } |
| 89 | 91 | ||
| @@ -76,6 +76,8 @@ out: · 75 unmodified lines | |||
| 76 | fail: | 76 | fail: |
| 77 | posix_acl_release(resp->acl_access); | 77 | posix_acl_release(resp->acl_access); |
| 78 | posix_acl_release(resp->acl_default); | 78 | posix_acl_release(resp->acl_default); |
| 79 | resp->acl_access = NULL; | ||
| 80 | resp->acl_default = NULL; | ||
| 79 | goto out; | 81 | goto out; |
| 80 | } | 82 | } |
| 81 | 83 | ||
| @@ -679,7 +679,7 @@ static int nfs4_xdr_dec_cb_getattr(struct rpc_rqst *rqstp, · 678 unmodified lines | |||
| 679 | return status; | 679 | return status; |
| 680 | 680 | ||
| 681 | status = decode_cb_op_status(xdr, OP_CB_GETATTR, &cb->cb_status); | 681 | status = decode_cb_op_status(xdr, OP_CB_GETATTR, &cb->cb_status); |
| 682 | if (unlikely(status || cb->cb_seq_status)) | 682 | if (unlikely(status || cb->cb_status)) |
| 683 | return status; | 683 | return status; |
| 684 | if (xdr_stream_decode_uint32_array(xdr, bitmap, 3) < 0) | 684 | if (xdr_stream_decode_uint32_array(xdr, bitmap, 3) < 0) |
| 685 | return -NFSERR_BAD_XDR; | 685 | return -NFSERR_BAD_XDR; |
| @@ -1583,8 +1583,11 @@ nfsd4_run_cb_work(struct work_struct *work) · 897 unmodified lines | |||
| 1583 | nfsd4_process_cb_update(cb); | 1583 | nfsd4_process_cb_update(cb); |
| 1584 | 1584 | ||
| 1585 | clnt = clp->cl_cb_client; | 1585 | clnt = clp->cl_cb_client; |
| 1586 | if (!clnt) { | 1586 | if (!clnt || clp->cl_state == NFSD4_COURTESY) { |
| 1587 | /* Callback channel broken, or client killed; give up: */ | 1587 | /* |
| 1588 | * Callback channel broken, client killed or | ||
| 1589 | * nfs4_client in courtesy state; give up. | ||
| 1590 | */ | ||
| 1588 | nfsd41_destroy_cb(cb); | 1591 | nfsd41_destroy_cb(cb); |
| 1589 | return; | 1592 | return; |
| 1590 | } | 1593 | } |
| @@ -4459,10 +4459,11 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, · 4458 unmodified lines | |||
| 4459 | } | 4459 | } |
| 4460 | } while (slot && --cnt > 0); | 4460 | } while (slot && --cnt > 0); |
| 4461 | } | 4461 | } |
| 4462 | |||
| 4463 | out: | ||
| 4462 | seq->maxslots = max(session->se_target_maxslots, seq->maxslots); | 4464 | seq->maxslots = max(session->se_target_maxslots, seq->maxslots); |
| 4463 | seq->target_maxslots = session->se_target_maxslots; | 4465 | seq->target_maxslots = session->se_target_maxslots; |
| 4464 | 4466 | ||
| 4465 | out: | ||
| 4466 | switch (clp->cl_cb_state) { | 4467 | switch (clp->cl_cb_state) { |
| 4467 | case NFSD4_CB_DOWN: | 4468 | case NFSD4_CB_DOWN: |
| 4468 | seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN; | 4469 | seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN; |
| @@ -380,8 +380,9 @@ __fh_verify(struct svc_rqst *rqstp, · 379 unmodified lines | |||
| 380 | error = check_nfsd_access(exp, rqstp, may_bypass_gss); | 380 | error = check_nfsd_access(exp, rqstp, may_bypass_gss); |
| 381 | if (error) | 381 | if (error) |
| 382 | goto out; | 382 | goto out; |
| 383 | 383 | /* During LOCALIO call to fh_verify will be called with a NULL rqstp */ | |
| 384 | svc_xprt_set_valid(rqstp->rq_xprt); | 384 | if (rqstp) |
| 385 | svc_xprt_set_valid(rqstp->rq_xprt); | ||
| 385 | 386 | ||
| 386 | /* Finally, check access permissions. */ | 387 | /* Finally, check access permissions. */ |
| 387 | error = nfsd_permission(cred, exp, dentry, access); | 388 | error = nfsd_permission(cred, exp, dentry, access); |
| @@ -648,7 +648,7 @@ EXPORT_SYMBOL_GPL(fsnotify); · 647 unmodified lines | |||
| 648 | * Later, fsnotify permission hooks do not check if there are permission event | 648 | * Later, fsnotify permission hooks do not check if there are permission event |
| 649 | * watches, but that there were permission event watches at open time. | 649 | * watches, but that there were permission event watches at open time. |
| 650 | */ | 650 | */ |
| 651 | void file_set_fsnotify_mode(struct file *file) | 651 | void file_set_fsnotify_mode_from_watchers(struct file *file) |
| 652 | { | 652 | { |
| 653 | struct dentry *dentry = file->f_path.dentry, *parent; | 653 | struct dentry *dentry = file->f_path.dentry, *parent; |
| 654 | struct super_block *sb = dentry->d_sb; | 654 | struct super_block *sb = dentry->d_sb; |
| @@ -665,7 +665,7 @@ void file_set_fsnotify_mode(struct file *file) · 10 unmodified lines | |||
| 665 | */ | 665 | */ |
| 666 | if (likely(!fsnotify_sb_has_priority_watchers(sb, | 666 | if (likely(!fsnotify_sb_has_priority_watchers(sb, |
| 667 | FSNOTIFY_PRIO_CONTENT))) { | 667 | FSNOTIFY_PRIO_CONTENT))) { |
| 668 | file->f_mode |= FMODE_NONOTIFY_PERM; | 668 | file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM); |
| 669 | return; | 669 | return; |
| 670 | } | 670 | } |
| 671 | 671 | ||
| @@ -676,7 +676,7 @@ void file_set_fsnotify_mode(struct file *file) · 4 unmodified lines | |||
| 676 | if ((!d_is_dir(dentry) && !d_is_reg(dentry)) || | 676 | if ((!d_is_dir(dentry) && !d_is_reg(dentry)) || |
| 677 | likely(!fsnotify_sb_has_priority_watchers(sb, | 677 | likely(!fsnotify_sb_has_priority_watchers(sb, |
| 678 | FSNOTIFY_PRIO_PRE_CONTENT))) { | 678 | FSNOTIFY_PRIO_PRE_CONTENT))) { |
| 679 | file->f_mode |= FMODE_NONOTIFY | FMODE_NONOTIFY_PERM; | 679 | file_set_fsnotify_mode(file, FMODE_NONOTIFY | FMODE_NONOTIFY_PERM); |
| 680 | return; | 680 | return; |
| 681 | } | 681 | } |
| 682 | 682 | ||
| @@ -686,19 +686,25 @@ void file_set_fsnotify_mode(struct file *file) · 3 unmodified lines | |||
| 686 | */ | 686 | */ |
| 687 | mnt_mask = READ_ONCE(real_mount(file->f_path.mnt)->mnt_fsnotify_mask); | 687 | mnt_mask = READ_ONCE(real_mount(file->f_path.mnt)->mnt_fsnotify_mask); |
| 688 | if (unlikely(fsnotify_object_watched(d_inode(dentry), mnt_mask, | 688 | if (unlikely(fsnotify_object_watched(d_inode(dentry), mnt_mask, |
| 689 | FSNOTIFY_PRE_CONTENT_EVENTS))) | 689 | FSNOTIFY_PRE_CONTENT_EVENTS))) { |
| 690 | /* Enable pre-content events */ | ||
| 691 | file_set_fsnotify_mode(file, 0); | ||
| 690 | return; | 692 | return; |
| 693 | } | ||
| 691 | 694 | ||
| 692 | /* Is parent watching for pre-content events on this file? */ | 695 | /* Is parent watching for pre-content events on this file? */ |
| 693 | if (dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED) { | 696 | if (dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED) { |
| 694 | parent = dget_parent(dentry); | 697 | parent = dget_parent(dentry); |
| 695 | p_mask = fsnotify_inode_watches_children(d_inode(parent)); | 698 | p_mask = fsnotify_inode_watches_children(d_inode(parent)); |
| 696 | dput(parent); | 699 | dput(parent); |
| 697 | if (p_mask & FSNOTIFY_PRE_CONTENT_EVENTS) | 700 | if (p_mask & FSNOTIFY_PRE_CONTENT_EVENTS) { |
| 701 | /* Enable pre-content events */ | ||
| 702 | file_set_fsnotify_mode(file, 0); | ||
| 698 | return; | 703 | return; |
| 704 | } | ||
| 699 | } | 705 | } |
| 700 | /* Nobody watching for pre-content events from this file */ | 706 | /* Nobody watching for pre-content events from this file */ |
| 701 | file->f_mode |= FMODE_NONOTIFY | FMODE_NONOTIFY_PERM; | 707 | file_set_fsnotify_mode(file, FMODE_NONOTIFY | FMODE_NONOTIFY_PERM); |
| 702 | } | 708 | } |
| 703 | #endif | 709 | #endif |
| 704 | 710 | ||
| @@ -905,7 +905,8 @@ static int do_dentry_open(struct file *f, · 904 unmodified lines | |||
| 905 | f->f_sb_err = file_sample_sb_err(f); | 905 | f->f_sb_err = file_sample_sb_err(f); |
| 906 | 906 | ||
| 907 | if (unlikely(f->f_flags & O_PATH)) { | 907 | if (unlikely(f->f_flags & O_PATH)) { |
| 908 | f->f_mode = FMODE_PATH | FMODE_OPENED | FMODE_NONOTIFY; | 908 | f->f_mode = FMODE_PATH | FMODE_OPENED; |
| 909 | file_set_fsnotify_mode(f, FMODE_NONOTIFY); | ||
| 909 | f->f_op = &empty_fops; | 910 | f->f_op = &empty_fops; |
| 910 | return 0; | 911 | return 0; |
| 911 | } | 912 | } |
| @@ -935,10 +936,10 @@ static int do_dentry_open(struct file *f, · 23 unmodified lines | |||
| 935 | 936 | ||
| 936 | /* | 937 | /* |
| 937 | * Set FMODE_NONOTIFY_* bits according to existing permission watches. | 938 | * Set FMODE_NONOTIFY_* bits according to existing permission watches. |
| 938 | * If FMODE_NONOTIFY was already set for an fanotify fd, this doesn't | 939 | * If FMODE_NONOTIFY mode was already set for an fanotify fd or for a |
| 939 | * change anything. | 940 | * pseudo file, this call will not change the mode. |
| 940 | */ | 941 | */ |
| 941 | file_set_fsnotify_mode(f); | 942 | file_set_fsnotify_mode_from_watchers(f); |
| 942 | error = fsnotify_open_perm(f); | 943 | error = fsnotify_open_perm(f); |
| 943 | if (error) | 944 | if (error) |
| 944 | goto cleanup_all; | 945 | goto cleanup_all; |
| @@ -1122,7 +1123,7 @@ struct file *dentry_open_nonotify(const struct path *path, int flags, · 177 unmodified lines | |||
| 1122 | if (!IS_ERR(f)) { | 1123 | if (!IS_ERR(f)) { |
| 1123 | int error; | 1124 | int error; |
| 1124 | 1125 | ||
| 1125 | f->f_mode |= FMODE_NONOTIFY; | 1126 | file_set_fsnotify_mode(f, FMODE_NONOTIFY); |
| 1126 | error = vfs_open(path, f); | 1127 | error = vfs_open(path, f); |
| 1127 | if (error) { | 1128 | if (error) { |
| 1128 | fput(f); | 1129 | fput(f); |
| @@ -287,7 +287,6 @@ static bool pidfs_ioctl_valid(unsigned int cmd) · 286 unmodified lines | |||
| 287 | switch (cmd) { | 287 | switch (cmd) { |
| 288 | case FS_IOC_GETVERSION: | 288 | case FS_IOC_GETVERSION: |
| 289 | case PIDFD_GET_CGROUP_NAMESPACE: | 289 | case PIDFD_GET_CGROUP_NAMESPACE: |
| 290 | case PIDFD_GET_INFO: | ||
| 291 | case PIDFD_GET_IPC_NAMESPACE: | 290 | case PIDFD_GET_IPC_NAMESPACE: |
| 292 | case PIDFD_GET_MNT_NAMESPACE: | 291 | case PIDFD_GET_MNT_NAMESPACE: |
| 293 | case PIDFD_GET_NET_NAMESPACE: | 292 | case PIDFD_GET_NET_NAMESPACE: |
| @@ -300,6 +299,17 @@ static bool pidfs_ioctl_valid(unsigned int cmd) · 6 unmodified lines | |||
| 300 | return true; | 299 | return true; |
| 301 | } | 300 | } |
| 302 | 301 | ||
| 302 | /* Extensible ioctls require some more careful checks. */ | ||
| 303 | switch (_IOC_NR(cmd)) { | ||
| 304 | case _IOC_NR(PIDFD_GET_INFO): | ||
| 305 | /* | ||
| 306 | * Try to prevent performing a pidfd ioctl when someone | ||
| 307 | * erronously mistook the file descriptor for a pidfd. | ||
| 308 | * This is not perfect but will catch most cases. | ||
| 309 | */ | ||
| 310 | return (_IOC_TYPE(cmd) == _IOC_TYPE(PIDFD_GET_INFO)); | ||
| 311 | } | ||
| 312 | |||
| 303 | return false; | 313 | return false; |
| 304 | } | 314 | } |
| 305 | 315 | ||
| @@ -960,6 +960,12 @@ int create_pipe_files(struct file **res, int flags) · 959 unmodified lines | |||
| 960 | res[1] = f; | 960 | res[1] = f; |
| 961 | stream_open(inode, res[0]); | 961 | stream_open(inode, res[0]); |
| 962 | stream_open(inode, res[1]); | 962 | stream_open(inode, res[1]); |
| 963 | /* | ||
| 964 | * Disable permission and pre-content events, but enable legacy | ||
| 965 | * inotify events for legacy users. | ||
| 966 | */ | ||
| 967 | file_set_fsnotify_mode(res[0], FMODE_NONOTIFY_PERM); | ||
| 968 | file_set_fsnotify_mode(res[1], FMODE_NONOTIFY_PERM); | ||
| 963 | return 0; | 969 | return 0; |
| 964 | } | 970 | } |
| 965 | 971 | ||
| @@ -1524,7 +1524,7 @@ int vmcore_add_device_dump(struct vmcoredd_data *data) · 1523 unmodified lines | |||
| 1524 | pr_warn_once("Unexpected adding of device dump\n"); | 1524 | pr_warn_once("Unexpected adding of device dump\n"); |
| 1525 | if (vmcore_open) { | 1525 | if (vmcore_open) { |
| 1526 | ret = -EBUSY; | 1526 | ret = -EBUSY; |
| 1527 | goto out_err; | 1527 | goto unlock; |
| 1528 | } | 1528 | } |
| 1529 | 1529 | ||
| 1530 | list_add_tail(&dump->list, &vmcoredd_list); | 1530 | list_add_tail(&dump->list, &vmcoredd_list); |
| @@ -1532,6 +1532,9 @@ int vmcore_add_device_dump(struct vmcoredd_data *data) · 1 unmodified line | |||
| 1532 | mutex_unlock(&vmcore_mutex); | 1532 | mutex_unlock(&vmcore_mutex); |
| 1533 | return 0; | 1533 | return 0; |
| 1534 | 1534 | ||
| 1535 | unlock: | ||
| 1536 | mutex_unlock(&vmcore_mutex); | ||
| 1537 | |||
| 1535 | out_err: | 1538 | out_err: |
| 1536 | vfree(buf); | 1539 | vfree(buf); |
| 1537 | vfree(dump); | 1540 | vfree(dump); |
| @@ -253,6 +253,7 @@ struct cifs_cred { · 252 unmodified lines | |||
| 253 | struct cifs_open_info_data { | 253 | struct cifs_open_info_data { |
| 254 | bool adjust_tz; | 254 | bool adjust_tz; |
| 255 | bool reparse_point; | 255 | bool reparse_point; |
| 256 | bool contains_posix_file_info; | ||
| 256 | struct { | 257 | struct { |
| 257 | /* ioctl response buffer */ | 258 | /* ioctl response buffer */ |
| 258 | struct { | 259 | struct { |
| @@ -357,7 +358,7 @@ struct smb_version_operations { · 98 unmodified lines | |||
| 357 | int (*handle_cancelled_mid)(struct mid_q_entry *, struct TCP_Server_Info *); | 358 | int (*handle_cancelled_mid)(struct mid_q_entry *, struct TCP_Server_Info *); |
| 358 | void (*downgrade_oplock)(struct TCP_Server_Info *server, | 359 | void (*downgrade_oplock)(struct TCP_Server_Info *server, |
| 359 | struct cifsInodeInfo *cinode, __u32 oplock, | 360 | struct cifsInodeInfo *cinode, __u32 oplock, |
| 360 | unsigned int epoch, bool *purge_cache); | 361 | __u16 epoch, bool *purge_cache); |
| 361 | /* process transaction2 response */ | 362 | /* process transaction2 response */ |
| 362 | bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *, | 363 | bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *, |
| 363 | char *, int); | 364 | char *, int); |
| @@ -552,12 +553,12 @@ struct smb_version_operations { · 188 unmodified lines | |||
| 552 | /* if we can do cache read operations */ | 553 | /* if we can do cache read operations */ |
| 553 | bool (*is_read_op)(__u32); | 554 | bool (*is_read_op)(__u32); |
| 554 | /* set oplock level for the inode */ | 555 | /* set oplock level for the inode */ |
| 555 | void (*set_oplock_level)(struct cifsInodeInfo *, __u32, unsigned int, | 556 | void (*set_oplock_level)(struct cifsInodeInfo *cinode, __u32 oplock, __u16 epoch, |
| 556 | bool *); | 557 | bool *purge_cache); |
| 557 | /* create lease context buffer for CREATE request */ | 558 | /* create lease context buffer for CREATE request */ |
| 558 | char * (*create_lease_buf)(u8 *lease_key, u8 oplock); | 559 | char * (*create_lease_buf)(u8 *lease_key, u8 oplock); |
| 559 | /* parse lease context buffer and return oplock/epoch info */ | 560 | /* parse lease context buffer and return oplock/epoch info */ |
| 560 | __u8 (*parse_lease_buf)(void *buf, unsigned int *epoch, char *lkey); | 561 | __u8 (*parse_lease_buf)(void *buf, __u16 *epoch, char *lkey); |
| 561 | ssize_t (*copychunk_range)(const unsigned int, | 562 | ssize_t (*copychunk_range)(const unsigned int, |
| 562 | struct cifsFileInfo *src_file, | 563 | struct cifsFileInfo *src_file, |
| 563 | struct cifsFileInfo *target_file, | 564 | struct cifsFileInfo *target_file, |
| @@ -1447,7 +1448,7 @@ struct cifs_fid { · 883 unmodified lines | |||
| 1447 | __u8 create_guid[16]; | 1448 | __u8 create_guid[16]; |
| 1448 | __u32 access; | 1449 | __u32 access; |
| 1449 | struct cifs_pending_open *pending_open; | 1450 | struct cifs_pending_open *pending_open; |
| 1450 | unsigned int epoch; | 1451 | __u16 epoch; |
| 1451 | #ifdef CONFIG_CIFS_DEBUG2 | 1452 | #ifdef CONFIG_CIFS_DEBUG2 |
| 1452 | __u64 mid; | 1453 | __u64 mid; |
| 1453 | #endif /* CIFS_DEBUG2 */ | 1454 | #endif /* CIFS_DEBUG2 */ |
| @@ -1480,7 +1481,7 @@ struct cifsFileInfo { · 26 unmodified lines | |||
| 1480 | bool oplock_break_cancelled:1; | 1481 | bool oplock_break_cancelled:1; |
| 1481 | bool status_file_deleted:1; /* file has been deleted */ | 1482 | bool status_file_deleted:1; /* file has been deleted */ |
| 1482 | bool offload:1; /* offload final part of _put to a wq */ | 1483 | bool offload:1; /* offload final part of _put to a wq */ |
| 1483 | unsigned int oplock_epoch; /* epoch from the lease break */ | 1484 | __u16 oplock_epoch; /* epoch from the lease break */ |
| 1484 | __u32 oplock_level; /* oplock/lease level from the lease break */ | 1485 | __u32 oplock_level; /* oplock/lease level from the lease break */ |
| 1485 | int count; | 1486 | int count; |
| 1486 | spinlock_t file_info_lock; /* protects four flag/count fields above */ | 1487 | spinlock_t file_info_lock; /* protects four flag/count fields above */ |
| @@ -1508,7 +1509,6 @@ struct cifs_io_parms { · 21 unmodified lines | |||
| 1508 | struct cifs_io_request { | 1509 | struct cifs_io_request { |
| 1509 | struct netfs_io_request rreq; | 1510 | struct netfs_io_request rreq; |
| 1510 | struct cifsFileInfo *cfile; | 1511 | struct cifsFileInfo *cfile; |
| 1511 | struct TCP_Server_Info *server; | ||
| 1512 | pid_t pid; | 1512 | pid_t pid; |
| 1513 | }; | 1513 | }; |
| 1514 | 1514 | ||
| @@ -1577,7 +1577,7 @@ struct cifsInodeInfo { · 62 unmodified lines | |||
| 1577 | spinlock_t open_file_lock; /* protects openFileList */ | 1577 | spinlock_t open_file_lock; /* protects openFileList */ |
| 1578 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ | 1578 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ |
| 1579 | unsigned int oplock; /* oplock/lease level we have */ | 1579 | unsigned int oplock; /* oplock/lease level we have */ |
| 1580 | unsigned int epoch; /* used to track lease state changes */ | 1580 | __u16 epoch; /* used to track lease state changes */ |
| 1581 | #define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */ | 1581 | #define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */ |
| 1582 | #define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */ | 1582 | #define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */ |
| 1583 | #define CIFS_INODE_FLAG_UNUSED (2) /* Unused flag */ | 1583 | #define CIFS_INODE_FLAG_UNUSED (2) /* Unused flag */ |
| @@ -2325,8 +2325,8 @@ struct smb2_compound_vars { · 741 unmodified lines | |||
| 2325 | struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; | 2325 | struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; |
| 2326 | struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; | 2326 | struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; |
| 2327 | struct kvec close_iov; | 2327 | struct kvec close_iov; |
| 2328 | struct smb2_file_rename_info rename_info; | 2328 | struct smb2_file_rename_info_hdr rename_info; |
| 2329 | struct smb2_file_link_info link_info; | 2329 | struct smb2_file_link_info_hdr link_info; |
| 2330 | struct kvec ea_iov; | 2330 | struct kvec ea_iov; |
| 2331 | }; | 2331 | }; |
| 2332 | 2332 | ||
| @@ -150,25 +150,27 @@ again: · 149 unmodified lines | |||
| 150 | if (rc) | 150 | if (rc) |
| 151 | continue; | 151 | continue; |
| 152 | 152 | ||
| 153 | if (tgt.flags & DFSREF_STORAGE_SERVER) { | 153 | rc = cifs_mount_get_tcon(mnt_ctx); |
| 154 | rc = cifs_mount_get_tcon(mnt_ctx); | 154 | if (rc) { |
| 155 | if (!rc) | 155 | if (tgt.server_type == DFS_TYPE_LINK && |
| 156 | rc = cifs_is_path_remote(mnt_ctx); | 156 | DFS_INTERLINK(tgt.flags)) |
| 157 | rc = -EREMOTE; | ||
| 158 | } else { | ||
| 159 | rc = cifs_is_path_remote(mnt_ctx); | ||
| 157 | if (!rc) { | 160 | if (!rc) { |
| 158 | ref_walk_set_tgt_hint(rw); | 161 | ref_walk_set_tgt_hint(rw); |
| 159 | break; | 162 | break; |
| 160 | } | 163 | } |
| 161 | if (rc != -EREMOTE) | ||
| 162 | continue; | ||
| 163 | } | 164 | } |
| 164 | 165 | if (rc == -EREMOTE) { | |
| 165 | rc = ref_walk_advance(rw); | 166 | rc = ref_walk_advance(rw); |
| 166 | if (!rc) { | 167 | if (!rc) { |
| 167 | rc = setup_dfs_ref(&tgt, rw); | 168 | rc = setup_dfs_ref(&tgt, rw); |
| 168 | if (rc) | 169 | if (rc) |
| 169 | break; | 170 | break; |
| 170 | ref_walk_mark_end(rw); | 171 | ref_walk_mark_end(rw); |
| 171 | goto again; | 172 | goto again; |
| 173 | } | ||
| 172 | } | 174 | } |
| 173 | } | 175 | } |
| 174 | } while (rc && ref_walk_descend(rw)); | 176 | } while (rc && ref_walk_descend(rw)); |
| @@ -188,4 +188,11 @@ static inline void dfs_put_root_smb_sessions(struct list_head *head) · 187 unmodified lines | |||
| 188 | } | 188 | } |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | static inline const char *dfs_ses_refpath(struct cifs_ses *ses) | ||
| 192 | { | ||
| 193 | const char *path = ses->server->leaf_fullpath; | ||
| 194 | |||
| 195 | return path ? path + 1 : ERR_PTR(-ENOENT); | ||
| 196 | } | ||
| 197 | |||
| 191 | #endif /* _CIFS_DFS_H */ | 198 | #endif /* _CIFS_DFS_H */ |
| @@ -1136,33 +1136,19 @@ static bool is_ses_good(struct cifs_ses *ses) · 1135 unmodified lines | |||
| 1136 | return ret; | 1136 | return ret; |
| 1137 | } | 1137 | } |
| 1138 | 1138 | ||
| 1139 | static char *get_ses_refpath(struct cifs_ses *ses) | ||
| 1140 | { | ||
| 1141 | struct TCP_Server_Info *server = ses->server; | ||
| 1142 | char *path = ERR_PTR(-ENOENT); | ||
| 1143 | |||
| 1144 | if (server->leaf_fullpath) { | ||
| 1145 | path = kstrdup(server->leaf_fullpath + 1, GFP_KERNEL); | ||
| 1146 | if (!path) | ||
| 1147 | path = ERR_PTR(-ENOMEM); | ||
| 1148 | } | ||
| 1149 | return path; | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | /* Refresh dfs referral of @ses */ | 1139 | /* Refresh dfs referral of @ses */ |
| 1153 | static void refresh_ses_referral(struct cifs_ses *ses) | 1140 | static void refresh_ses_referral(struct cifs_ses *ses) |
| 1154 | { | 1141 | { |
| 1155 | struct cache_entry *ce; | 1142 | struct cache_entry *ce; |
| 1156 | unsigned int xid; | 1143 | unsigned int xid; |
| 1157 | char *path; | 1144 | const char *path; |
| 1158 | int rc = 0; | 1145 | int rc = 0; |
| 1159 | 1146 | ||
| 1160 | xid = get_xid(); | 1147 | xid = get_xid(); |
| 1161 | 1148 | ||
| 1162 | path = get_ses_refpath(ses); | 1149 | path = dfs_ses_refpath(ses); |
| 1163 | if (IS_ERR(path)) { | 1150 | if (IS_ERR(path)) { |
| 1164 | rc = PTR_ERR(path); | 1151 | rc = PTR_ERR(path); |
| 1165 | path = NULL; | ||
| 1166 | goto out; | 1152 | goto out; |
| 1167 | } | 1153 | } |
| 1168 | 1154 | ||
| @@ -1181,7 +1167,6 @@ static void refresh_ses_referral(struct cifs_ses *ses) · 12 unmodified lines | |||
| 1181 | 1167 | ||
| 1182 | out: | 1168 | out: |
| 1183 | free_xid(xid); | 1169 | free_xid(xid); |
| 1184 | kfree(path); | ||
| 1185 | } | 1170 | } |
| 1186 | 1171 | ||
| 1187 | static int __refresh_tcon_referral(struct cifs_tcon *tcon, | 1172 | static int __refresh_tcon_referral(struct cifs_tcon *tcon, |
| @@ -1231,19 +1216,18 @@ static void refresh_tcon_referral(struct cifs_tcon *tcon, bool force_refresh) · 43 unmodified lines | |||
| 1231 | struct dfs_info3_param *refs = NULL; | 1216 | struct dfs_info3_param *refs = NULL; |
| 1232 | struct cache_entry *ce; | 1217 | struct cache_entry *ce; |
| 1233 | struct cifs_ses *ses; | 1218 | struct cifs_ses *ses; |
| 1234 | unsigned int xid; | ||
| 1235 | bool needs_refresh; | 1219 | bool needs_refresh; |
| 1236 | char *path; | 1220 | const char *path; |
| 1221 | unsigned int xid; | ||
| 1237 | int numrefs = 0; | 1222 | int numrefs = 0; |
| 1238 | int rc = 0; | 1223 | int rc = 0; |
| 1239 | 1224 | ||
| 1240 | xid = get_xid(); | 1225 | xid = get_xid(); |
| 1241 | ses = tcon->ses; | 1226 | ses = tcon->ses; |
| 1242 | 1227 | ||
| 1243 | path = get_ses_refpath(ses); | 1228 | path = dfs_ses_refpath(ses); |
| 1244 | if (IS_ERR(path)) { | 1229 | if (IS_ERR(path)) { |
| 1245 | rc = PTR_ERR(path); | 1230 | rc = PTR_ERR(path); |
| 1246 | path = NULL; | ||
| 1247 | goto out; | 1231 | goto out; |
| 1248 | } | 1232 | } |
| 1249 | 1233 | ||
| @@ -1271,7 +1255,6 @@ static void refresh_tcon_referral(struct cifs_tcon *tcon, bool force_refresh) · 21 unmodified lines | |||
| 1271 | 1255 | ||
| 1272 | out: | 1256 | out: |
| 1273 | free_xid(xid); | 1257 | free_xid(xid); |
| 1274 | kfree(path); | ||
| 1275 | free_dfs_info_array(refs, numrefs); | 1258 | free_dfs_info_array(refs, numrefs); |
| 1276 | } | 1259 | } |
| 1277 | 1260 | ||
| @@ -147,7 +147,7 @@ static int cifs_prepare_read(struct netfs_io_subrequest *subreq) · 146 unmodified lines | |||
| 147 | struct netfs_io_request *rreq = subreq->rreq; | 147 | struct netfs_io_request *rreq = subreq->rreq; |
| 148 | struct cifs_io_subrequest *rdata = container_of(subreq, struct cifs_io_subrequest, subreq); | 148 | struct cifs_io_subrequest *rdata = container_of(subreq, struct cifs_io_subrequest, subreq); |
| 149 | struct cifs_io_request *req = container_of(subreq->rreq, struct cifs_io_request, rreq); | 149 | struct cifs_io_request *req = container_of(subreq->rreq, struct cifs_io_request, rreq); |
| 150 | struct TCP_Server_Info *server = req->server; | 150 | struct TCP_Server_Info *server; |
| 151 | struct cifs_sb_info *cifs_sb = CIFS_SB(rreq->inode->i_sb); | 151 | struct cifs_sb_info *cifs_sb = CIFS_SB(rreq->inode->i_sb); |
| 152 | size_t size; | 152 | size_t size; |
| 153 | int rc = 0; | 153 | int rc = 0; |
| @@ -156,6 +156,8 @@ static int cifs_prepare_read(struct netfs_io_subrequest *subreq) · 2 unmodified lines | |||
| 156 | rdata->xid = get_xid(); | 156 | rdata->xid = get_xid(); |
| 157 | rdata->have_xid = true; | 157 | rdata->have_xid = true; |
| 158 | } | 158 | } |
| 159 | |||
| 160 | server = cifs_pick_channel(tlink_tcon(req->cfile->tlink)->ses); | ||
| 159 | rdata->server = server; | 161 | rdata->server = server; |
| 160 | 162 | ||
| 161 | if (cifs_sb->ctx->rsize == 0) | 163 | if (cifs_sb->ctx->rsize == 0) |
| @@ -198,7 +200,7 @@ static void cifs_issue_read(struct netfs_io_subrequest *subreq) · 36 unmodified lines | |||
| 198 | struct netfs_io_request *rreq = subreq->rreq; | 200 | struct netfs_io_request *rreq = subreq->rreq; |
| 199 | struct cifs_io_subrequest *rdata = container_of(subreq, struct cifs_io_subrequest, subreq); | 201 | struct cifs_io_subrequest *rdata = container_of(subreq, struct cifs_io_subrequest, subreq); |
| 200 | struct cifs_io_request *req = container_of(subreq->rreq, struct cifs_io_request, rreq); | 202 | struct cifs_io_request *req = container_of(subreq->rreq, struct cifs_io_request, rreq); |
| 201 | struct TCP_Server_Info *server = req->server; | 203 | struct TCP_Server_Info *server = rdata->server; |
| 202 | int rc = 0; | 204 | int rc = 0; |
| 203 | 205 | ||
| 204 | cifs_dbg(FYI, "%s: op=%08x[%x] mapping=%p len=%zu/%zu\n", | 206 | cifs_dbg(FYI, "%s: op=%08x[%x] mapping=%p len=%zu/%zu\n", |
| @@ -266,7 +268,6 @@ static int cifs_init_request(struct netfs_io_request *rreq, struct file *file) · 61 unmodified lines | |||
| 266 | open_file = file->private_data; | 268 | open_file = file->private_data; |
| 267 | rreq->netfs_priv = file->private_data; | 269 | rreq->netfs_priv = file->private_data; |
| 268 | req->cfile = cifsFileInfo_get(open_file); | 270 | req->cfile = cifsFileInfo_get(open_file); |
| 269 | req->server = cifs_pick_channel(tlink_tcon(req->cfile->tlink)->ses); | ||
| 270 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 271 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
| 271 | req->pid = req->cfile->pid; | 272 | req->pid = req->cfile->pid; |
| 272 | } else if (rreq->origin != NETFS_WRITEBACK) { | 273 | } else if (rreq->origin != NETFS_WRITEBACK) { |
| @@ -1215,6 +1215,19 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, · 1214 unmodified lines | |||
| 1215 | rc = server->ops->parse_reparse_point(cifs_sb, | 1215 | rc = server->ops->parse_reparse_point(cifs_sb, |
| 1216 | full_path, | 1216 | full_path, |
| 1217 | iov, data); | 1217 | iov, data); |
| 1218 | /* | ||
| 1219 | * If the reparse point was not handled but it is the | ||
| 1220 | * name surrogate which points to directory, then treat | ||
| 1221 | * is as a new mount point. Name surrogate reparse point | ||
| 1222 | * represents another named entity in the system. | ||
| 1223 | */ | ||
| 1224 | if (rc == -EOPNOTSUPP && | ||
| 1225 | IS_REPARSE_TAG_NAME_SURROGATE(data->reparse.tag) && | ||
| 1226 | (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY)) { | ||
| 1227 | rc = 0; | ||
| 1228 | cifs_create_junction_fattr(fattr, sb); | ||
| 1229 | goto out; | ||
| 1230 | } | ||
| 1218 | } | 1231 | } |
| 1219 | 1232 | ||
| 1220 | if (data->reparse.tag == IO_REPARSE_TAG_SYMLINK && !rc) { | 1233 | if (data->reparse.tag == IO_REPARSE_TAG_SYMLINK && !rc) { |
| @@ -1408,7 +1421,7 @@ int cifs_get_inode_info(struct inode **inode, · 187 unmodified lines | |||
| 1408 | struct cifs_fattr fattr = {}; | 1421 | struct cifs_fattr fattr = {}; |
| 1409 | int rc; | 1422 | int rc; |
| 1410 | 1423 | ||
| 1411 | if (is_inode_cache_good(*inode)) { | 1424 | if (!data && is_inode_cache_good(*inode)) { |
| 1412 | cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); | 1425 | cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); |
| 1413 | return 0; | 1426 | return 0; |
| 1414 | } | 1427 | } |
| @@ -1507,7 +1520,7 @@ int smb311_posix_get_inode_info(struct inode **inode, · 92 unmodified lines | |||
| 1507 | struct cifs_fattr fattr = {}; | 1520 | struct cifs_fattr fattr = {}; |
| 1508 | int rc; | 1521 | int rc; |
| 1509 | 1522 | ||
| 1510 | if (is_inode_cache_good(*inode)) { | 1523 | if (!data && is_inode_cache_good(*inode)) { |
| 1511 | cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); | 1524 | cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); |
| 1512 | return 0; | 1525 | return 0; |
| 1513 | } | 1526 | } |
| @@ -1088,13 +1088,12 @@ int parse_reparse_point(struct reparse_data_buffer *buf, · 1087 unmodified lines | |||
| 1088 | le32_to_cpu(buf->ReparseTag)); | 1088 | le32_to_cpu(buf->ReparseTag)); |
| 1089 | return -EIO; | 1089 | return -EIO; |
| 1090 | } | 1090 | } |
| 1091 | break; | 1091 | return 0; |
| 1092 | default: | 1092 | default: |
| 1093 | cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n", | 1093 | cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n", |
| 1094 | le32_to_cpu(buf->ReparseTag)); | 1094 | le32_to_cpu(buf->ReparseTag)); |
| 1095 | break; | 1095 | return -EOPNOTSUPP; |
| 1096 | } | 1096 | } |
| 1097 | return 0; | ||
| 1098 | } | 1097 | } |
| 1099 | 1098 | ||
| 1100 | int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, | 1099 | int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, |
| @@ -99,14 +99,30 @@ static inline bool reparse_inode_match(struct inode *inode, · 98 unmodified lines | |||
| 99 | 99 | ||
| 100 | static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data) | 100 | static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data) |
| 101 | { | 101 | { |
| 102 | struct smb2_file_all_info *fi = &data->fi; | 102 | u32 attrs; |
| 103 | u32 attrs = le32_to_cpu(fi->Attributes); | ||
| 104 | bool ret; | 103 | bool ret; |
| 105 | 104 | ||
| 106 | ret = data->reparse_point || (attrs & ATTR_REPARSE); | 105 | if (data->contains_posix_file_info) { |
| 107 | if (ret) | 106 | struct smb311_posix_qinfo *fi = &data->posix_fi; |
| 108 | attrs |= ATTR_REPARSE; | 107 | |
| 109 | fi->Attributes = cpu_to_le32(attrs); | 108 | attrs = le32_to_cpu(fi->DosAttributes); |
| 109 | if (data->reparse_point) { | ||
| 110 | attrs |= ATTR_REPARSE; | ||
| 111 | fi->DosAttributes = cpu_to_le32(attrs); | ||
| 112 | } | ||
| 113 | |||
| 114 | } else { | ||
| 115 | struct smb2_file_all_info *fi = &data->fi; | ||
| 116 | |||
| 117 | attrs = le32_to_cpu(fi->Attributes); | ||
| 118 | if (data->reparse_point) { | ||
| 119 | attrs |= ATTR_REPARSE; | ||
| 120 | fi->Attributes = cpu_to_le32(attrs); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | ret = attrs & ATTR_REPARSE; | ||
| 125 | |||
| 110 | return ret; | 126 | return ret; |
| 111 | } | 127 | } |
| 112 | 128 | ||
| @@ -377,7 +377,7 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr) · 376 unmodified lines | |||
| 377 | static void | 377 | static void |
| 378 | cifs_downgrade_oplock(struct TCP_Server_Info *server, | 378 | cifs_downgrade_oplock(struct TCP_Server_Info *server, |
| 379 | struct cifsInodeInfo *cinode, __u32 oplock, | 379 | struct cifsInodeInfo *cinode, __u32 oplock, |
| 380 | unsigned int epoch, bool *purge_cache) | 380 | __u16 epoch, bool *purge_cache) |
| 381 | { | 381 | { |
| 382 | cifs_set_oplock_level(cinode, oplock); | 382 | cifs_set_oplock_level(cinode, oplock); |
| 383 | } | 383 | } |
| @@ -650,6 +650,7 @@ finished: · 649 unmodified lines | |||
| 650 | switch (cmds[i]) { | 650 | switch (cmds[i]) { |
| 651 | case SMB2_OP_QUERY_INFO: | 651 | case SMB2_OP_QUERY_INFO: |
| 652 | idata = in_iov[i].iov_base; | 652 | idata = in_iov[i].iov_base; |
| 653 | idata->contains_posix_file_info = false; | ||
| 653 | if (rc == 0 && cfile && cfile->symlink_target) { | 654 | if (rc == 0 && cfile && cfile->symlink_target) { |
| 654 | idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); | 655 | idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); |
| 655 | if (!idata->symlink_target) | 656 | if (!idata->symlink_target) |
| @@ -673,6 +674,7 @@ finished: · 17 unmodified lines | |||
| 673 | break; | 674 | break; |
| 674 | case SMB2_OP_POSIX_QUERY_INFO: | 675 | case SMB2_OP_POSIX_QUERY_INFO: |
| 675 | idata = in_iov[i].iov_base; | 676 | idata = in_iov[i].iov_base; |
| 677 | idata->contains_posix_file_info = true; | ||
| 676 | if (rc == 0 && cfile && cfile->symlink_target) { | 678 | if (rc == 0 && cfile && cfile->symlink_target) { |
| 677 | idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); | 679 | idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); |
| 678 | if (!idata->symlink_target) | 680 | if (!idata->symlink_target) |
| @@ -770,6 +772,7 @@ finished: · 91 unmodified lines | |||
| 770 | idata = in_iov[i].iov_base; | 772 | idata = in_iov[i].iov_base; |
| 771 | idata->reparse.io.iov = *iov; | 773 | idata->reparse.io.iov = *iov; |
| 772 | idata->reparse.io.buftype = resp_buftype[i + 1]; | 774 | idata->reparse.io.buftype = resp_buftype[i + 1]; |
| 775 | idata->contains_posix_file_info = false; /* BB VERIFY */ | ||
| 773 | rbuf = reparse_buf_ptr(iov); | 776 | rbuf = reparse_buf_ptr(iov); |
| 774 | if (IS_ERR(rbuf)) { | 777 | if (IS_ERR(rbuf)) { |
| 775 | rc = PTR_ERR(rbuf); | 778 | rc = PTR_ERR(rbuf); |
| @@ -791,6 +794,7 @@ finished: · 15 unmodified lines | |||
| 791 | case SMB2_OP_QUERY_WSL_EA: | 794 | case SMB2_OP_QUERY_WSL_EA: |
| 792 | if (!rc) { | 795 | if (!rc) { |
| 793 | idata = in_iov[i].iov_base; | 796 | idata = in_iov[i].iov_base; |
| 797 | idata->contains_posix_file_info = false; | ||
| 794 | qi_rsp = rsp_iov[i + 1].iov_base; | 798 | qi_rsp = rsp_iov[i + 1].iov_base; |
| 795 | data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset); | 799 | data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset); |
| 796 | size[0] = le32_to_cpu(qi_rsp->OutputBufferLength); | 800 | size[0] = le32_to_cpu(qi_rsp->OutputBufferLength); |
| @@ -1001,6 +1001,7 @@ static int smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, · 1000 unmodified lines | |||
| 1001 | if (!data->symlink_target) | 1001 | if (!data->symlink_target) |
| 1002 | return -ENOMEM; | 1002 | return -ENOMEM; |
| 1003 | } | 1003 | } |
| 1004 | data->contains_posix_file_info = false; | ||
| 1004 | return SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid, &data->fi); | 1005 | return SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid, &data->fi); |
| 1005 | } | 1006 | } |
| 1006 | 1007 | ||
| @@ -3904,22 +3905,22 @@ static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode, · 2897 unmodified lines | |||
| 3904 | static void | 3905 | static void |
| 3905 | smb2_downgrade_oplock(struct TCP_Server_Info *server, | 3906 | smb2_downgrade_oplock(struct TCP_Server_Info *server, |
| 3906 | struct cifsInodeInfo *cinode, __u32 oplock, | 3907 | struct cifsInodeInfo *cinode, __u32 oplock, |
| 3907 | unsigned int epoch, bool *purge_cache) | 3908 | __u16 epoch, bool *purge_cache) |
| 3908 | { | 3909 | { |
| 3909 | server->ops->set_oplock_level(cinode, oplock, 0, NULL); | 3910 | server->ops->set_oplock_level(cinode, oplock, 0, NULL); |
| 3910 | } | 3911 | } |
| 3911 | 3912 | ||
| 3912 | static void | 3913 | static void |
| 3913 | smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, | 3914 | smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, |
| 3914 | unsigned int epoch, bool *purge_cache); | 3915 | __u16 epoch, bool *purge_cache); |
| 3915 | 3916 | ||
| 3916 | static void | 3917 | static void |
| 3917 | smb3_downgrade_oplock(struct TCP_Server_Info *server, | 3918 | smb3_downgrade_oplock(struct TCP_Server_Info *server, |
| 3918 | struct cifsInodeInfo *cinode, __u32 oplock, | 3919 | struct cifsInodeInfo *cinode, __u32 oplock, |
| 3919 | unsigned int epoch, bool *purge_cache) | 3920 | __u16 epoch, bool *purge_cache) |
| 3920 | { | 3921 | { |
| 3921 | unsigned int old_state = cinode->oplock; | 3922 | unsigned int old_state = cinode->oplock; |
| 3922 | unsigned int old_epoch = cinode->epoch; | 3923 | __u16 old_epoch = cinode->epoch; |
| 3923 | unsigned int new_state; | 3924 | unsigned int new_state; |
| 3924 | 3925 | ||
| 3925 | if (epoch > old_epoch) { | 3926 | if (epoch > old_epoch) { |
| @@ -3939,7 +3940,7 @@ smb3_downgrade_oplock(struct TCP_Server_Info *server, · 13 unmodified lines | |||
| 3939 | 3940 | ||
| 3940 | static void | 3941 | static void |
| 3941 | smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, | 3942 | smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, |
| 3942 | unsigned int epoch, bool *purge_cache) | 3943 | __u16 epoch, bool *purge_cache) |
| 3943 | { | 3944 | { |
| 3944 | oplock &= 0xFF; | 3945 | oplock &= 0xFF; |
| 3945 | cinode->lease_granted = false; | 3946 | cinode->lease_granted = false; |
| @@ -3963,7 +3964,7 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, · 17 unmodified lines | |||
| 3963 | 3964 | ||
| 3964 | static void | 3965 | static void |
| 3965 | smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, | 3966 | smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, |
| 3966 | unsigned int epoch, bool *purge_cache) | 3967 | __u16 epoch, bool *purge_cache) |
| 3967 | { | 3968 | { |
| 3968 | char message[5] = {0}; | 3969 | char message[5] = {0}; |
| 3969 | unsigned int new_oplock = 0; | 3970 | unsigned int new_oplock = 0; |
| @@ -4000,7 +4001,7 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, · 30 unmodified lines | |||
| 4000 | 4001 | ||
| 4001 | static void | 4002 | static void |
| 4002 | smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, | 4003 | smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, |
| 4003 | unsigned int epoch, bool *purge_cache) | 4004 | __u16 epoch, bool *purge_cache) |
| 4004 | { | 4005 | { |
| 4005 | unsigned int old_oplock = cinode->oplock; | 4006 | unsigned int old_oplock = cinode->oplock; |
| 4006 | 4007 | ||
| @@ -4114,7 +4115,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock) · 107 unmodified lines | |||
| 4114 | } | 4115 | } |
| 4115 | 4116 | ||
| 4116 | static __u8 | 4117 | static __u8 |
| 4117 | smb2_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key) | 4118 | smb2_parse_lease_buf(void *buf, __u16 *epoch, char *lease_key) |
| 4118 | { | 4119 | { |
| 4119 | struct create_lease *lc = (struct create_lease *)buf; | 4120 | struct create_lease *lc = (struct create_lease *)buf; |
| 4120 | 4121 | ||
| @@ -4125,7 +4126,7 @@ smb2_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key) · 4 unmodified lines | |||
| 4125 | } | 4126 | } |
| 4126 | 4127 | ||
| 4127 | static __u8 | 4128 | static __u8 |
| 4128 | smb3_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key) | 4129 | smb3_parse_lease_buf(void *buf, __u16 *epoch, char *lease_key) |
| 4129 | { | 4130 | { |
| 4130 | struct create_lease_v2 *lc = (struct create_lease_v2 *)buf; | 4131 | struct create_lease_v2 *lc = (struct create_lease_v2 *)buf; |
| 4131 | 4132 | ||
| @@ -5146,7 +5147,7 @@ int __cifs_sfu_make_node(unsigned int xid, struct inode *inode, · 1014 unmodified lines | |||
| 5146 | FILE_CREATE, CREATE_NOT_DIR | | 5147 | FILE_CREATE, CREATE_NOT_DIR | |
| 5147 | CREATE_OPTION_SPECIAL, ACL_NO_MODE); | 5148 | CREATE_OPTION_SPECIAL, ACL_NO_MODE); |
| 5148 | oparms.fid = &fid; | 5149 | oparms.fid = &fid; |
| 5149 | 5150 | idata.contains_posix_file_info = false; | |
| 5150 | rc = server->ops->open(xid, &oparms, &oplock, &idata); | 5151 | rc = server->ops->open(xid, &oparms, &oplock, &idata); |
| 5151 | if (rc) | 5152 | if (rc) |
| 5152 | goto out; | 5153 | goto out; |
| @@ -2169,7 +2169,7 @@ tcon_exit: · 2168 unmodified lines | |||
| 2169 | 2169 | ||
| 2170 | tcon_error_exit: | 2170 | tcon_error_exit: |
| 2171 | if (rsp && rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) | 2171 | if (rsp && rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) |
| 2172 | cifs_tcon_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); | 2172 | cifs_dbg(VFS | ONCE, "BAD_NETWORK_NAME: %s\n", tree); |
| 2173 | goto tcon_exit; | 2173 | goto tcon_exit; |
| 2174 | } | 2174 | } |
| 2175 | 2175 | ||
| @@ -2329,7 +2329,7 @@ parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info, · 153 unmodified lines | |||
| 2329 | 2329 | ||
| 2330 | int smb2_parse_contexts(struct TCP_Server_Info *server, | 2330 | int smb2_parse_contexts(struct TCP_Server_Info *server, |
| 2331 | struct kvec *rsp_iov, | 2331 | struct kvec *rsp_iov, |
| 2332 | unsigned int *epoch, | 2332 | __u16 *epoch, |
| 2333 | char *lease_key, __u8 *oplock, | 2333 | char *lease_key, __u8 *oplock, |
| 2334 | struct smb2_file_all_info *buf, | 2334 | struct smb2_file_all_info *buf, |
| 2335 | struct create_posix_rsp *posix) | 2335 | struct create_posix_rsp *posix) |
| @@ -283,7 +283,7 @@ extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, · 282 unmodified lines | |||
| 283 | enum securityEnum); | 283 | enum securityEnum); |
| 284 | int smb2_parse_contexts(struct TCP_Server_Info *server, | 284 | int smb2_parse_contexts(struct TCP_Server_Info *server, |
| 285 | struct kvec *rsp_iov, | 285 | struct kvec *rsp_iov, |
| 286 | unsigned int *epoch, | 286 | __u16 *epoch, |
| 287 | char *lease_key, __u8 *oplock, | 287 | char *lease_key, __u8 *oplock, |
| 288 | struct smb2_file_all_info *buf, | 288 | struct smb2_file_all_info *buf, |
| 289 | struct create_posix_rsp *posix); | 289 | struct create_posix_rsp *posix); |
| @@ -1707,23 +1707,33 @@ struct smb2_file_internal_info { · 1706 unmodified lines | |||
| 1707 | } __packed; /* level 6 Query */ | 1707 | } __packed; /* level 6 Query */ |
| 1708 | 1708 | ||
| 1709 | struct smb2_file_rename_info { /* encoding of request for level 10 */ | 1709 | struct smb2_file_rename_info { /* encoding of request for level 10 */ |
| 1710 | __u8 ReplaceIfExists; /* 1 = replace existing target with new */ | 1710 | /* New members MUST be added within the struct_group() macro below. */ |
| 1711 | /* 0 = fail if target already exists */ | 1711 | __struct_group(smb2_file_rename_info_hdr, __hdr, __packed, |
| 1712 | __u8 Reserved[7]; | 1712 | __u8 ReplaceIfExists; /* 1 = replace existing target with new */ |
| 1713 | __u64 RootDirectory; /* MBZ for network operations (why says spec?) */ | 1713 | /* 0 = fail if target already exists */ |
| 1714 | __le32 FileNameLength; | 1714 | __u8 Reserved[7]; |
| 1715 | __u64 RootDirectory; /* MBZ for network operations (why says spec?) */ | ||
| 1716 | __le32 FileNameLength; | ||
| 1717 | ); | ||
| 1715 | char FileName[]; /* New name to be assigned */ | 1718 | char FileName[]; /* New name to be assigned */ |
| 1716 | /* padding - overall struct size must be >= 24 so filename + pad >= 6 */ | 1719 | /* padding - overall struct size must be >= 24 so filename + pad >= 6 */ |
| 1717 | } __packed; /* level 10 Set */ | 1720 | } __packed; /* level 10 Set */ |
| 1721 | static_assert(offsetof(struct smb2_file_rename_info, FileName) == sizeof(struct smb2_file_rename_info_hdr), | ||
| 1722 | "struct member likely outside of __struct_group()"); | ||
| 1718 | 1723 | ||
| 1719 | struct smb2_file_link_info { /* encoding of request for level 11 */ | 1724 | struct smb2_file_link_info { /* encoding of request for level 11 */ |
| 1720 | __u8 ReplaceIfExists; /* 1 = replace existing link with new */ | 1725 | /* New members MUST be added within the struct_group() macro below. */ |
| 1721 | /* 0 = fail if link already exists */ | 1726 | __struct_group(smb2_file_link_info_hdr, __hdr, __packed, |
| 1722 | __u8 Reserved[7]; | 1727 | __u8 ReplaceIfExists; /* 1 = replace existing link with new */ |
| 1723 | __u64 RootDirectory; /* MBZ for network operations (why says spec?) */ | 1728 | /* 0 = fail if link already exists */ |
| 1724 | __le32 FileNameLength; | 1729 | __u8 Reserved[7]; |
| 1730 | __u64 RootDirectory; /* MBZ for network operations (why says spec?) */ | ||
| 1731 | __le32 FileNameLength; | ||
| 1732 | ); | ||
| 1725 | char FileName[]; /* Name to be assigned to new link */ | 1733 | char FileName[]; /* Name to be assigned to new link */ |
| 1726 | } __packed; /* level 11 Set */ | 1734 | } __packed; /* level 11 Set */ |
| 1735 | static_assert(offsetof(struct smb2_file_link_info, FileName) == sizeof(struct smb2_file_link_info_hdr), | ||
| 1736 | "struct member likely outside of __struct_group()"); | ||
| 1727 | 1737 | ||
| 1728 | /* | 1738 | /* |
| 1729 | * This level 18, although with struct with same name is different from cifs | 1739 | * This level 18, although with struct with same name is different from cifs |
| @@ -159,6 +159,9 @@ · 158 unmodified lines | |||
| 159 | #define IO_REPARSE_TAG_LX_CHR 0x80000025 | 159 | #define IO_REPARSE_TAG_LX_CHR 0x80000025 |
| 160 | #define IO_REPARSE_TAG_LX_BLK 0x80000026 | 160 | #define IO_REPARSE_TAG_LX_BLK 0x80000026 |
| 161 | 161 | ||
| 162 | /* If Name Surrogate Bit is set, the file or directory represents another named entity in the system. */ | ||
| 163 | #define IS_REPARSE_TAG_NAME_SURROGATE(tag) (!!((tag) & 0x20000000)) | ||
| 164 | |||
| 162 | /* fsctl flags */ | 165 | /* fsctl flags */ |
| 163 | /* If Flags is set to this value, the request is an FSCTL not ioctl request */ | 166 | /* If Flags is set to this value, the request is an FSCTL not ioctl request */ |
| 164 | #define SMB2_0_IOCTL_IS_FSCTL 0x00000001 | 167 | #define SMB2_0_IOCTL_IS_FSCTL 0x00000001 |
| @@ -281,6 +281,8 @@ static int vfs_statx_path(struct path *path, int flags, struct kstat *stat, · 280 unmodified lines | |||
| 281 | u32 request_mask) | 281 | u32 request_mask) |
| 282 | { | 282 | { |
| 283 | int error = vfs_getattr(path, stat, request_mask, flags); | 283 | int error = vfs_getattr(path, stat, request_mask, flags); |
| 284 | if (error) | ||
| 285 | return error; | ||
| 284 | 286 | ||
| 285 | if (request_mask & STATX_MNT_ID_UNIQUE) { | 287 | if (request_mask & STATX_MNT_ID_UNIQUE) { |
| 286 | stat->mnt_id = real_mount(path->mnt)->mnt_id_unique; | 288 | stat->mnt_id = real_mount(path->mnt)->mnt_id_unique; |
| @@ -302,7 +304,7 @@ static int vfs_statx_path(struct path *path, int flags, struct kstat *stat, · 15 unmodified lines | |||
| 302 | if (S_ISBLK(stat->mode)) | 304 | if (S_ISBLK(stat->mode)) |
| 303 | bdev_statx(path, stat, request_mask); | 305 | bdev_statx(path, stat, request_mask); |
| 304 | 306 | ||
| 305 | return error; | 307 | return 0; |
| 306 | } | 308 | } |
| 307 | 309 | ||
| 308 | static int vfs_statx_fd(int fd, int flags, struct kstat *stat, | 310 | static int vfs_statx_fd(int fd, int flags, struct kstat *stat, |
| @@ -21,7 +21,8 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ | 22 | #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ |
| 23 | 23 | ||
| 24 | static const unsigned char VBSF_MOUNT_SIGNATURE[4] = "\000\377\376\375"; | 24 | static const unsigned char VBSF_MOUNT_SIGNATURE[4] = { '\000', '\377', '\376', |
| 25 | '\375' }; | ||
| 25 | 26 | ||
| 26 | static int follow_symlinks; | 27 | static int follow_symlinks; |
| 27 | module_param(follow_symlinks, int, 0444); | 28 | module_param(follow_symlinks, int, 0444); |
| @@ -3563,12 +3563,12 @@ xfs_bmap_btalloc_at_eof( · 3562 unmodified lines | |||
| 3563 | int error; | 3563 | int error; |
| 3564 | 3564 | ||
| 3565 | /* | 3565 | /* |
| 3566 | * If there are already extents in the file, try an exact EOF block | 3566 | * If there are already extents in the file, and xfs_bmap_adjacent() has |
| 3567 | * allocation to extend the file as a contiguous extent. If that fails, | 3567 | * given a better blkno, try an exact EOF block allocation to extend the |
| 3568 | * or it's the first allocation in a file, just try for a stripe aligned | 3568 | * file as a contiguous extent. If that fails, or it's the first |
| 3569 | * allocation. | 3569 | * allocation in a file, just try for a stripe aligned allocation. |
| 3570 | */ | 3570 | */ |
| 3571 | if (ap->offset) { | 3571 | if (ap->eof) { |
| 3572 | xfs_extlen_t nextminlen = 0; | 3572 | xfs_extlen_t nextminlen = 0; |
| 3573 | 3573 | ||
| 3574 | /* | 3574 | /* |
| @@ -3736,7 +3736,8 @@ xfs_bmap_btalloc_best_length( · 161 unmodified lines | |||
| 3736 | int error; | 3736 | int error; |
| 3737 | 3737 | ||
| 3738 | ap->blkno = XFS_INO_TO_FSB(args->mp, ap->ip->i_ino); | 3738 | ap->blkno = XFS_INO_TO_FSB(args->mp, ap->ip->i_ino); |
| 3739 | xfs_bmap_adjacent(ap); | 3739 | if (!xfs_bmap_adjacent(ap)) |
| 3740 | ap->eof = false; | ||
| 3740 | 3741 | ||
| 3741 | /* | 3742 | /* |
| 3742 | * Search for an allocation group with a single extent large enough for | 3743 | * Search for an allocation group with a single extent large enough for |
| @@ -224,7 +224,6 @@ static inline bool xchk_skip_xref(struct xfs_scrub_metadata *sm) · 223 unmodified lines | |||
| 224 | bool xchk_dir_looks_zapped(struct xfs_inode *dp); | 224 | bool xchk_dir_looks_zapped(struct xfs_inode *dp); |
| 225 | bool xchk_pptr_looks_zapped(struct xfs_inode *ip); | 225 | bool xchk_pptr_looks_zapped(struct xfs_inode *ip); |
| 226 | 226 | ||
| 227 | #ifdef CONFIG_XFS_ONLINE_REPAIR | ||
| 228 | /* Decide if a repair is required. */ | 227 | /* Decide if a repair is required. */ |
| 229 | static inline bool xchk_needs_repair(const struct xfs_scrub_metadata *sm) | 228 | static inline bool xchk_needs_repair(const struct xfs_scrub_metadata *sm) |
| 230 | { | 229 | { |
| @@ -244,10 +243,6 @@ static inline bool xchk_could_repair(const struct xfs_scrub *sc) · 13 unmodified lines | |||
| 244 | return (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) && | 243 | return (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) && |
| 245 | !(sc->flags & XREP_ALREADY_FIXED); | 244 | !(sc->flags & XREP_ALREADY_FIXED); |
| 246 | } | 245 | } |
| 247 | #else | ||
| 248 | # define xchk_needs_repair(sc) (false) | ||
| 249 | # define xchk_could_repair(sc) (false) | ||
| 250 | #endif /* CONFIG_XFS_ONLINE_REPAIR */ | ||
| 251 | 246 | ||
| 252 | int xchk_metadata_inode_forks(struct xfs_scrub *sc); | 247 | int xchk_metadata_inode_forks(struct xfs_scrub *sc); |
| 253 | 248 | ||
| @@ -1055,9 +1055,17 @@ xrep_dinode_check_dfork( · 1054 unmodified lines | |||
| 1055 | return true; | 1055 | return true; |
| 1056 | break; | 1056 | break; |
| 1057 | case S_IFREG: | 1057 | case S_IFREG: |
| 1058 | if (fmt == XFS_DINODE_FMT_LOCAL) | 1058 | switch (fmt) { |
| 1059 | case XFS_DINODE_FMT_LOCAL: | ||
| 1059 | return true; | 1060 | return true; |
| 1060 | fallthrough; | 1061 | case XFS_DINODE_FMT_EXTENTS: |
| 1062 | case XFS_DINODE_FMT_BTREE: | ||
| 1063 | case XFS_DINODE_FMT_META_BTREE: | ||
| 1064 | break; | ||
| 1065 | default: | ||
| 1066 | return true; | ||
| 1067 | } | ||
| 1068 | break; | ||
| 1061 | case S_IFLNK: | 1069 | case S_IFLNK: |
| 1062 | case S_IFDIR: | 1070 | case S_IFDIR: |
| 1063 | switch (fmt) { | 1071 | switch (fmt) { |
| @@ -191,7 +191,16 @@ int xrep_reset_metafile_resv(struct xfs_scrub *sc); · 190 unmodified lines | |||
| 191 | #else | 191 | #else |
| 192 | 192 | ||
| 193 | #define xrep_ino_dqattach(sc) (0) | 193 | #define xrep_ino_dqattach(sc) (0) |
| 194 | #define xrep_will_attempt(sc) (false) | 194 | |
| 195 | /* | ||
| 196 | * When online repair is not built into the kernel, we still want to attempt | ||
| 197 | * the repair so that the stub xrep_attempt below will return EOPNOTSUPP. | ||
| 198 | */ | ||
| 199 | static inline bool xrep_will_attempt(const struct xfs_scrub *sc) | ||
| 200 | { | ||
| 201 | return (sc->sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD) || | ||
| 202 | xchk_needs_repair(sc->sm); | ||
| 203 | } | ||
| 195 | 204 | ||
| 196 | static inline int | 205 | static inline int |
| 197 | xrep_attempt( | 206 | xrep_attempt( |
| @@ -149,6 +149,18 @@ xchk_probe( · 148 unmodified lines | |||
| 149 | if (xchk_should_terminate(sc, &error)) | 149 | if (xchk_should_terminate(sc, &error)) |
| 150 | return error; | 150 | return error; |
| 151 | 151 | ||
| 152 | /* | ||
| 153 | * If the caller is probing to see if repair works but repair isn't | ||
| 154 | * built into the kernel, return EOPNOTSUPP because that's the signal | ||
| 155 | * that userspace expects. If online repair is built in, set the | ||
| 156 | * CORRUPT flag (without any of the usual tracing/logging) to force us | ||
| 157 | * into xrep_probe. | ||
| 158 | */ | ||
| 159 | if (xchk_could_repair(sc)) { | ||
| 160 | if (!IS_ENABLED(CONFIG_XFS_ONLINE_REPAIR)) | ||
| 161 | return -EOPNOTSUPP; | ||
| 162 | sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT; | ||
| 163 | } | ||
| 152 | return 0; | 164 | return 0; |
| 153 | } | 165 | } |
| 154 | 166 | ||
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | #include "xfs_reflink.h" | 19 | #include "xfs_reflink.h" |
| 20 | #include "xfs_errortag.h" | 20 | #include "xfs_errortag.h" |
| 21 | #include "xfs_error.h" | 21 | #include "xfs_error.h" |
| 22 | #include "xfs_icache.h" | ||
| 22 | 23 | ||
| 23 | struct xfs_writepage_ctx { | 24 | struct xfs_writepage_ctx { |
| 24 | struct iomap_writepage_ctx ctx; | 25 | struct iomap_writepage_ctx ctx; |
| @@ -528,12 +529,44 @@ xfs_vm_readahead( · 503 unmodified lines | |||
| 528 | } | 529 | } |
| 529 | 530 | ||
| 530 | static int | 531 | static int |
| 531 | xfs_iomap_swapfile_activate( | 532 | xfs_vm_swap_activate( |
| 532 | struct swap_info_struct *sis, | 533 | struct swap_info_struct *sis, |
| 533 | struct file *swap_file, | 534 | struct file *swap_file, |
| 534 | sector_t *span) | 535 | sector_t *span) |
| 535 | { | 536 | { |
| 536 | sis->bdev = xfs_inode_buftarg(XFS_I(file_inode(swap_file)))->bt_bdev; | 537 | struct xfs_inode *ip = XFS_I(file_inode(swap_file)); |
| 538 | |||
| 539 | /* | ||
| 540 | * Swap file activation can race against concurrent shared extent | ||
| 541 | * removal in files that have been cloned. If this happens, | ||
| 542 | * iomap_swapfile_iter() can fail because it encountered a shared | ||
| 543 | * extent even though an operation is in progress to remove those | ||
| 544 | * shared extents. | ||
| 545 | * | ||
| 546 | * This race becomes problematic when we defer extent removal | ||
| 547 | * operations beyond the end of a syscall (i.e. use async background | ||
| 548 | * processing algorithms). Users think the extents are no longer | ||
| 549 | * shared, but iomap_swapfile_iter() still sees them as shared | ||
| 550 | * because the refcountbt entries for the extents being removed have | ||
| 551 | * not yet been updated. Hence the swapon call fails unexpectedly. | ||
| 552 | * | ||
| 553 | * The race condition is currently most obvious from the unlink() | ||
| 554 | * operation as extent removal is deferred until after the last | ||
| 555 | * reference to the inode goes away. We then process the extent | ||
| 556 | * removal asynchronously, hence triggers the "syscall completed but | ||
| 557 | * work not done" condition mentioned above. To close this race | ||
| 558 | * window, we need to flush any pending inodegc operations to ensure | ||
| 559 | * they have updated the refcountbt records before we try to map the | ||
| 560 | * swapfile. | ||
| 561 | */ | ||
| 562 | xfs_inodegc_flush(ip->i_mount); | ||
| 563 | |||
| 564 | /* | ||
| 565 | * Direct the swap code to the correct block device when this file | ||
| 566 | * sits on the RT device. | ||
| 567 | */ | ||
| 568 | sis->bdev = xfs_inode_buftarg(ip)->bt_bdev; | ||
| 569 | |||
| 537 | return iomap_swapfile_activate(sis, swap_file, span, | 570 | return iomap_swapfile_activate(sis, swap_file, span, |
| 538 | &xfs_read_iomap_ops); | 571 | &xfs_read_iomap_ops); |
| 539 | } | 572 | } |
| @@ -549,11 +582,11 @@ const struct address_space_operations xfs_address_space_operations = { · 9 unmodified lines | |||
| 549 | .migrate_folio = filemap_migrate_folio, | 582 | .migrate_folio = filemap_migrate_folio, |
| 550 | .is_partially_uptodate = iomap_is_partially_uptodate, | 583 | .is_partially_uptodate = iomap_is_partially_uptodate, |
| 551 | .error_remove_folio = generic_error_remove_folio, | 584 | .error_remove_folio = generic_error_remove_folio, |
| 552 | .swap_activate = xfs_iomap_swapfile_activate, | 585 | .swap_activate = xfs_vm_swap_activate, |
| 553 | }; | 586 | }; |
| 554 | 587 | ||
| 555 | const struct address_space_operations xfs_dax_aops = { | 588 | const struct address_space_operations xfs_dax_aops = { |
| 556 | .writepages = xfs_dax_writepages, | 589 | .writepages = xfs_dax_writepages, |
| 557 | .dirty_folio = noop_dirty_folio, | 590 | .dirty_folio = noop_dirty_folio, |
| 558 | .swap_activate = xfs_iomap_swapfile_activate, | 591 | .swap_activate = xfs_vm_swap_activate, |
| 559 | }; | 592 | }; |
| @@ -41,8 +41,7 @@ struct kmem_cache *xfs_buf_cache; · 40 unmodified lines | |||
| 41 | * | 41 | * |
| 42 | * xfs_buf_rele: | 42 | * xfs_buf_rele: |
| 43 | * b_lock | 43 | * b_lock |
| 44 | * pag_buf_lock | 44 | * lru_lock |
| 45 | * lru_lock | ||
| 46 | * | 45 | * |
| 47 | * xfs_buftarg_drain_rele | 46 | * xfs_buftarg_drain_rele |
| 48 | * lru_lock | 47 | * lru_lock |
| @@ -220,23 +219,25 @@ _xfs_buf_alloc( · 171 unmodified lines | |||
| 220 | */ | 219 | */ |
| 221 | flags &= ~(XBF_UNMAPPED | XBF_TRYLOCK | XBF_ASYNC | XBF_READ_AHEAD); | 220 | flags &= ~(XBF_UNMAPPED | XBF_TRYLOCK | XBF_ASYNC | XBF_READ_AHEAD); |
| 222 | 221 | ||
| 223 | spin_lock_init(&bp->b_lock); | 222 | /* |
| 223 | * A new buffer is held and locked by the owner. This ensures that the | ||
| 224 | * buffer is owned by the caller and racing RCU lookups right after | ||
| 225 | * inserting into the hash table are safe (and will have to wait for | ||
| 226 | * the unlock to do anything non-trivial). | ||
| 227 | */ | ||
| 224 | bp->b_hold = 1; | 228 | bp->b_hold = 1; |
| 229 | sema_init(&bp->b_sema, 0); /* held, no waiters */ | ||
| 230 | |||
| 231 | spin_lock_init(&bp->b_lock); | ||
| 225 | atomic_set(&bp->b_lru_ref, 1); | 232 | atomic_set(&bp->b_lru_ref, 1); |
| 226 | init_completion(&bp->b_iowait); | 233 | init_completion(&bp->b_iowait); |
| 227 | INIT_LIST_HEAD(&bp->b_lru); | 234 | INIT_LIST_HEAD(&bp->b_lru); |
| 228 | INIT_LIST_HEAD(&bp->b_list); | 235 | INIT_LIST_HEAD(&bp->b_list); |
| 229 | INIT_LIST_HEAD(&bp->b_li_list); | 236 | INIT_LIST_HEAD(&bp->b_li_list); |
| 230 | sema_init(&bp->b_sema, 0); /* held, no waiters */ | ||
| 231 | bp->b_target = target; | 237 | bp->b_target = target; |
| 232 | bp->b_mount = target->bt_mount; | 238 | bp->b_mount = target->bt_mount; |
| 233 | bp->b_flags = flags; | 239 | bp->b_flags = flags; |
| 234 | 240 | ||
| 235 | /* | ||
| 236 | * Set length and io_length to the same value initially. | ||
| 237 | * I/O routines should use io_length, which will be the same in | ||
| 238 | * most cases but may be reset (e.g. XFS recovery). | ||
| 239 | */ | ||
| 240 | error = xfs_buf_get_maps(bp, nmaps); | 241 | error = xfs_buf_get_maps(bp, nmaps); |
| 241 | if (error) { | 242 | if (error) { |
| 242 | kmem_cache_free(xfs_buf_cache, bp); | 243 | kmem_cache_free(xfs_buf_cache, bp); |
| @@ -502,7 +503,6 @@ int · 259 unmodified lines | |||
| 502 | xfs_buf_cache_init( | 503 | xfs_buf_cache_init( |
| 503 | struct xfs_buf_cache *bch) | 504 | struct xfs_buf_cache *bch) |
| 504 | { | 505 | { |
| 505 | spin_lock_init(&bch->bc_lock); | ||
| 506 | return rhashtable_init(&bch->bc_hash, &xfs_buf_hash_params); | 506 | return rhashtable_init(&bch->bc_hash, &xfs_buf_hash_params); |
| 507 | } | 507 | } |
| 508 | 508 | ||
| @@ -652,17 +652,20 @@ xfs_buf_find_insert( · 143 unmodified lines | |||
| 652 | if (error) | 652 | if (error) |
| 653 | goto out_free_buf; | 653 | goto out_free_buf; |
| 654 | 654 | ||
| 655 | spin_lock(&bch->bc_lock); | 655 | /* The new buffer keeps the perag reference until it is freed. */ |
| 656 | new_bp->b_pag = pag; | ||
| 657 | |||
| 658 | rcu_read_lock(); | ||
| 656 | bp = rhashtable_lookup_get_insert_fast(&bch->bc_hash, | 659 | bp = rhashtable_lookup_get_insert_fast(&bch->bc_hash, |
| 657 | &new_bp->b_rhash_head, xfs_buf_hash_params); | 660 | &new_bp->b_rhash_head, xfs_buf_hash_params); |
| 658 | if (IS_ERR(bp)) { | 661 | if (IS_ERR(bp)) { |
| 662 | rcu_read_unlock(); | ||
| 659 | error = PTR_ERR(bp); | 663 | error = PTR_ERR(bp); |
| 660 | spin_unlock(&bch->bc_lock); | ||
| 661 | goto out_free_buf; | 664 | goto out_free_buf; |
| 662 | } | 665 | } |
| 663 | if (bp && xfs_buf_try_hold(bp)) { | 666 | if (bp && xfs_buf_try_hold(bp)) { |
| 664 | /* found an existing buffer */ | 667 | /* found an existing buffer */ |
| 665 | spin_unlock(&bch->bc_lock); | 668 | rcu_read_unlock(); |
| 666 | error = xfs_buf_find_lock(bp, flags); | 669 | error = xfs_buf_find_lock(bp, flags); |
| 667 | if (error) | 670 | if (error) |
| 668 | xfs_buf_rele(bp); | 671 | xfs_buf_rele(bp); |
| @@ -670,10 +673,8 @@ xfs_buf_find_insert( · 1 unmodified line | |||
| 670 | *bpp = bp; | 673 | *bpp = bp; |
| 671 | goto out_free_buf; | 674 | goto out_free_buf; |
| 672 | } | 675 | } |
| 676 | rcu_read_unlock(); | ||
| 673 | 677 | ||
| 674 | /* The new buffer keeps the perag reference until it is freed. */ | ||
| 675 | new_bp->b_pag = pag; | ||
| 676 | spin_unlock(&bch->bc_lock); | ||
| 677 | *bpp = new_bp; | 678 | *bpp = new_bp; |
| 678 | return 0; | 679 | return 0; |
| 679 | 680 | ||
| @@ -1090,7 +1091,6 @@ xfs_buf_rele_cached( · 410 unmodified lines | |||
| 1090 | } | 1091 | } |
| 1091 | 1092 | ||
| 1092 | /* we are asked to drop the last reference */ | 1093 | /* we are asked to drop the last reference */ |
| 1093 | spin_lock(&bch->bc_lock); | ||
| 1094 | __xfs_buf_ioacct_dec(bp); | 1094 | __xfs_buf_ioacct_dec(bp); |
| 1095 | if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) { | 1095 | if (!(bp->b_flags & XBF_STALE) && atomic_read(&bp->b_lru_ref)) { |
| 1096 | /* | 1096 | /* |
| @@ -1102,7 +1102,6 @@ xfs_buf_rele_cached( · 5 unmodified lines | |||
| 1102 | bp->b_state &= ~XFS_BSTATE_DISPOSE; | 1102 | bp->b_state &= ~XFS_BSTATE_DISPOSE; |
| 1103 | else | 1103 | else |
| 1104 | bp->b_hold--; | 1104 | bp->b_hold--; |
| 1105 | spin_unlock(&bch->bc_lock); | ||
| 1106 | } else { | 1105 | } else { |
| 1107 | bp->b_hold--; | 1106 | bp->b_hold--; |
| 1108 | /* | 1107 | /* |
| @@ -1120,7 +1119,6 @@ xfs_buf_rele_cached( · 11 unmodified lines | |||
| 1120 | ASSERT(!(bp->b_flags & _XBF_DELWRI_Q)); | 1119 | ASSERT(!(bp->b_flags & _XBF_DELWRI_Q)); |
| 1121 | rhashtable_remove_fast(&bch->bc_hash, &bp->b_rhash_head, | 1120 | rhashtable_remove_fast(&bch->bc_hash, &bp->b_rhash_head, |
| 1122 | xfs_buf_hash_params); | 1121 | xfs_buf_hash_params); |
| 1123 | spin_unlock(&bch->bc_lock); | ||
| 1124 | if (pag) | 1122 | if (pag) |
| 1125 | xfs_perag_put(pag); | 1123 | xfs_perag_put(pag); |
| 1126 | freebuf = true; | 1124 | freebuf = true; |
| @@ -80,7 +80,6 @@ typedef unsigned int xfs_buf_flags_t; · 79 unmodified lines | |||
| 80 | #define XFS_BSTATE_IN_FLIGHT (1 << 1) /* I/O in flight */ | 80 | #define XFS_BSTATE_IN_FLIGHT (1 << 1) /* I/O in flight */ |
| 81 | 81 | ||
| 82 | struct xfs_buf_cache { | 82 | struct xfs_buf_cache { |
| 83 | spinlock_t bc_lock; | ||
| 84 | struct rhashtable bc_hash; | 83 | struct rhashtable bc_hash; |
| 85 | }; | 84 | }; |
| 86 | 85 | ||
| @@ -329,22 +329,6 @@ out_trans_cancel: · 328 unmodified lines | |||
| 329 | * successfully but before locks are dropped. | 329 | * successfully but before locks are dropped. |
| 330 | */ | 330 | */ |
| 331 | 331 | ||
| 332 | /* Verify that we have security clearance to perform this operation. */ | ||
| 333 | static int | ||
| 334 | xfs_exchange_range_verify_area( | ||
| 335 | struct xfs_exchrange *fxr) | ||
| 336 | { | ||
| 337 | int ret; | ||
| 338 | |||
| 339 | ret = remap_verify_area(fxr->file1, fxr->file1_offset, fxr->length, | ||
| 340 | true); | ||
| 341 | if (ret) | ||
| 342 | return ret; | ||
| 343 | |||
| 344 | return remap_verify_area(fxr->file2, fxr->file2_offset, fxr->length, | ||
| 345 | true); | ||
| 346 | } | ||
| 347 | |||
| 348 | /* | 332 | /* |
| 349 | * Performs necessary checks before doing a range exchange, having stabilized | 333 | * Performs necessary checks before doing a range exchange, having stabilized |
| 350 | * mutable inode attributes via i_rwsem. | 334 | * mutable inode attributes via i_rwsem. |
| @@ -355,11 +339,13 @@ xfs_exchange_range_checks( · 4 unmodified lines | |||
| 355 | unsigned int alloc_unit) | 339 | unsigned int alloc_unit) |
| 356 | { | 340 | { |
| 357 | struct inode *inode1 = file_inode(fxr->file1); | 341 | struct inode *inode1 = file_inode(fxr->file1); |
| 342 | loff_t size1 = i_size_read(inode1); | ||
| 358 | struct inode *inode2 = file_inode(fxr->file2); | 343 | struct inode *inode2 = file_inode(fxr->file2); |
| 344 | loff_t size2 = i_size_read(inode2); | ||
| 359 | uint64_t allocmask = alloc_unit - 1; | 345 | uint64_t allocmask = alloc_unit - 1; |
| 360 | int64_t test_len; | 346 | int64_t test_len; |
| 361 | uint64_t blen; | 347 | uint64_t blen; |
| 362 | loff_t size1, size2, tmp; | 348 | loff_t tmp; |
| 363 | int error; | 349 | int error; |
| 364 | 350 | ||
| 365 | /* Don't touch certain kinds of inodes */ | 351 | /* Don't touch certain kinds of inodes */ |
| @@ -368,24 +354,25 @@ xfs_exchange_range_checks( · 2 unmodified lines | |||
| 368 | if (IS_SWAPFILE(inode1) || IS_SWAPFILE(inode2)) | 354 | if (IS_SWAPFILE(inode1) || IS_SWAPFILE(inode2)) |
| 369 | return -ETXTBSY; | 355 | return -ETXTBSY; |
| 370 | 356 | ||
| 371 | size1 = i_size_read(inode1); | ||
| 372 | size2 = i_size_read(inode2); | ||
| 373 | |||
| 374 | /* Ranges cannot start after EOF. */ | 357 | /* Ranges cannot start after EOF. */ |
| 375 | if (fxr->file1_offset > size1 || fxr->file2_offset > size2) | 358 | if (fxr->file1_offset > size1 || fxr->file2_offset > size2) |
| 376 | return -EINVAL; | 359 | return -EINVAL; |
| 377 | 360 | ||
| 378 | /* | ||
| 379 | * If the caller said to exchange to EOF, we set the length of the | ||
| 380 | * request large enough to cover everything to the end of both files. | ||
| 381 | */ | ||
| 382 | if (fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF) { | 361 | if (fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF) { |
| 362 | /* | ||
| 363 | * If the caller said to exchange to EOF, we set the length of | ||
| 364 | * the request large enough to cover everything to the end of | ||
| 365 | * both files. | ||
| 366 | */ | ||
| 383 | fxr->length = max_t(int64_t, size1 - fxr->file1_offset, | 367 | fxr->length = max_t(int64_t, size1 - fxr->file1_offset, |
| 384 | size2 - fxr->file2_offset); | 368 | size2 - fxr->file2_offset); |
| 385 | 369 | } else { | |
| 386 | error = xfs_exchange_range_verify_area(fxr); | 370 | /* |
| 387 | if (error) | 371 | * Otherwise we require both ranges to end within EOF. |
| 388 | return error; | 372 | */ |
| 373 | if (fxr->file1_offset + fxr->length > size1 || | ||
| 374 | fxr->file2_offset + fxr->length > size2) | ||
| 375 | return -EINVAL; | ||
| 389 | } | 376 | } |
| 390 | 377 | ||
| 391 | /* | 378 | /* |
| @@ -401,15 +388,6 @@ xfs_exchange_range_checks( · 9 unmodified lines | |||
| 401 | check_add_overflow(fxr->file2_offset, fxr->length, &tmp)) | 388 | check_add_overflow(fxr->file2_offset, fxr->length, &tmp)) |
| 402 | return -EINVAL; | 389 | return -EINVAL; |
| 403 | 390 | ||
| 404 | /* | ||
| 405 | * We require both ranges to end within EOF, unless we're exchanging | ||
| 406 | * to EOF. | ||
| 407 | */ | ||
| 408 | if (!(fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF) && | ||
| 409 | (fxr->file1_offset + fxr->length > size1 || | ||
| 410 | fxr->file2_offset + fxr->length > size2)) | ||
| 411 | return -EINVAL; | ||
| 412 | |||
| 413 | /* | 391 | /* |
| 414 | * Make sure we don't hit any file size limits. If we hit any size | 392 | * Make sure we don't hit any file size limits. If we hit any size |
| 415 | * limits such that test_length was adjusted, we abort the whole | 393 | * limits such that test_length was adjusted, we abort the whole |
| @@ -747,6 +725,7 @@ xfs_exchange_range( · 331 unmodified lines | |||
| 747 | { | 725 | { |
| 748 | struct inode *inode1 = file_inode(fxr->file1); | 726 | struct inode *inode1 = file_inode(fxr->file1); |
| 749 | struct inode *inode2 = file_inode(fxr->file2); | 727 | struct inode *inode2 = file_inode(fxr->file2); |
| 728 | loff_t check_len = fxr->length; | ||
| 750 | int ret; | 729 | int ret; |
| 751 | 730 | ||
| 752 | BUILD_BUG_ON(XFS_EXCHANGE_RANGE_ALL_FLAGS & | 731 | BUILD_BUG_ON(XFS_EXCHANGE_RANGE_ALL_FLAGS & |
| @@ -779,14 +758,18 @@ xfs_exchange_range( · 26 unmodified lines | |||
| 779 | return -EBADF; | 758 | return -EBADF; |
| 780 | 759 | ||
| 781 | /* | 760 | /* |
| 782 | * If we're not exchanging to EOF, we can check the areas before | 761 | * If we're exchanging to EOF we can't calculate the length until taking |
| 783 | * stabilizing both files' i_size. | 762 | * the iolock. Pass a 0 length to remap_verify_area similar to the |
| 763 | * FICLONE and FICLONERANGE ioctls that support cloning to EOF as well. | ||
| 784 | */ | 764 | */ |
| 785 | if (!(fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF)) { | 765 | if (fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF) |
| 786 | ret = xfs_exchange_range_verify_area(fxr); | 766 | check_len = 0; |
| 787 | if (ret) | 767 | ret = remap_verify_area(fxr->file1, fxr->file1_offset, check_len, true); |
| 788 | return ret; | 768 | if (ret) |
| 789 | } | 769 | return ret; |
| 770 | ret = remap_verify_area(fxr->file2, fxr->file2_offset, check_len, true); | ||
| 771 | if (ret) | ||
| 772 | return ret; | ||
| 790 | 773 | ||
| 791 | /* Update cmtime if the fd/inode don't forbid it. */ | 774 | /* Update cmtime if the fd/inode don't forbid it. */ |
| 792 | if (!(fxr->file1->f_mode & FMODE_NOCMTIME) && !IS_NOCMTIME(inode1)) | 775 | if (!(fxr->file1->f_mode & FMODE_NOCMTIME) && !IS_NOCMTIME(inode1)) |
| @@ -1404,8 +1404,11 @@ xfs_inactive( · 1403 unmodified lines | |||
| 1404 | goto out; | 1404 | goto out; |
| 1405 | 1405 | ||
| 1406 | /* Try to clean out the cow blocks if there are any. */ | 1406 | /* Try to clean out the cow blocks if there are any. */ |
| 1407 | if (xfs_inode_has_cow_data(ip)) | 1407 | if (xfs_inode_has_cow_data(ip)) { |
| 1408 | xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true); | 1408 | error = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true); |
| 1409 | if (error) | ||
| 1410 | goto out; | ||
| 1411 | } | ||
| 1409 | 1412 | ||
| 1410 | if (VFS_I(ip)->i_nlink != 0) { | 1413 | if (VFS_I(ip)->i_nlink != 0) { |
| 1411 | /* | 1414 | /* |
| @@ -976,10 +976,8 @@ xfs_dax_write_iomap_end( · 975 unmodified lines | |||
| 976 | if (!xfs_is_cow_inode(ip)) | 976 | if (!xfs_is_cow_inode(ip)) |
| 977 | return 0; | 977 | return 0; |
| 978 | 978 | ||
| 979 | if (!written) { | 979 | if (!written) |
| 980 | xfs_reflink_cancel_cow_range(ip, pos, length, true); | 980 | return xfs_reflink_cancel_cow_range(ip, pos, length, true); |
| 981 | return 0; | ||
| 982 | } | ||
| 983 | 981 | ||
| 984 | return xfs_reflink_end_cow(ip, pos, written); | 982 | return xfs_reflink_end_cow(ip, pos, written); |
| 985 | } | 983 | } |
| @@ -78,6 +78,28 @@ xfs_qm_statvfs( · 77 unmodified lines | |||
| 78 | } | 78 | } |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | STATIC int | ||
| 82 | xfs_qm_validate_state_change( | ||
| 83 | struct xfs_mount *mp, | ||
| 84 | uint uqd, | ||
| 85 | uint gqd, | ||
| 86 | uint pqd) | ||
| 87 | { | ||
| 88 | int state; | ||
| 89 | |||
| 90 | /* Is quota state changing? */ | ||
| 91 | state = ((uqd && !XFS_IS_UQUOTA_ON(mp)) || | ||
| 92 | (!uqd && XFS_IS_UQUOTA_ON(mp)) || | ||
| 93 | (gqd && !XFS_IS_GQUOTA_ON(mp)) || | ||
| 94 | (!gqd && XFS_IS_GQUOTA_ON(mp)) || | ||
| 95 | (pqd && !XFS_IS_PQUOTA_ON(mp)) || | ||
| 96 | (!pqd && XFS_IS_PQUOTA_ON(mp))); | ||
| 97 | |||
| 98 | return state && | ||
| 99 | (xfs_dev_is_read_only(mp, "changing quota state") || | ||
| 100 | xfs_has_norecovery(mp)); | ||
| 101 | } | ||
| 102 | |||
| 81 | int | 103 | int |
| 82 | xfs_qm_newmount( | 104 | xfs_qm_newmount( |
| 83 | xfs_mount_t *mp, | 105 | xfs_mount_t *mp, |
| @@ -97,24 +119,25 @@ xfs_qm_newmount( · 13 unmodified lines | |||
| 97 | } | 119 | } |
| 98 | 120 | ||
| 99 | /* | 121 | /* |
| 100 | * If the device itself is read-only, we can't allow | 122 | * If the device itself is read-only and/or in norecovery |
| 101 | * the user to change the state of quota on the mount - | 123 | * mode, we can't allow the user to change the state of |
| 102 | * this would generate a transaction on the ro device, | 124 | * quota on the mount - this would generate a transaction |
| 103 | * which would lead to an I/O error and shutdown | 125 | * on the ro device, which would lead to an I/O error and |
| 126 | * shutdown. | ||
| 104 | */ | 127 | */ |
| 105 | 128 | ||
| 106 | if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || | 129 | if (xfs_qm_validate_state_change(mp, uquotaondisk, |
| 107 | (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || | 130 | gquotaondisk, pquotaondisk)) { |
| 108 | (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || | 131 | |
| 109 | (!gquotaondisk && XFS_IS_GQUOTA_ON(mp)) || | 132 | if (xfs_has_metadir(mp)) |
| 110 | (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) || | 133 | xfs_warn(mp, |
| 111 | (!pquotaondisk && XFS_IS_PQUOTA_ON(mp))) && | 134 | "metadir enabled, please mount without any quota mount options"); |
| 112 | xfs_dev_is_read_only(mp, "changing quota state")) { | 135 | else |
| 113 | xfs_warn(mp, "please mount with%s%s%s%s.", | 136 | xfs_warn(mp, "please mount with%s%s%s%s.", |
| 114 | (!quotaondisk ? "out quota" : ""), | 137 | (!quotaondisk ? "out quota" : ""), |
| 115 | (uquotaondisk ? " usrquota" : ""), | 138 | (uquotaondisk ? " usrquota" : ""), |
| 116 | (gquotaondisk ? " grpquota" : ""), | 139 | (gquotaondisk ? " grpquota" : ""), |
| 117 | (pquotaondisk ? " prjquota" : "")); | 140 | (pquotaondisk ? " prjquota" : "")); |
| 118 | return -EPERM; | 141 | return -EPERM; |
| 119 | } | 142 | } |
| 120 | 143 | ||
| @@ -1661,8 +1661,12 @@ xfs_fs_fill_super( · 1660 unmodified lines | |||
| 1661 | #endif | 1661 | #endif |
| 1662 | } | 1662 | } |
| 1663 | 1663 | ||
| 1664 | /* Filesystem claims it needs repair, so refuse the mount. */ | 1664 | /* |
| 1665 | if (xfs_has_needsrepair(mp)) { | 1665 | * Filesystem claims it needs repair, so refuse the mount unless |
| 1666 | * norecovery is also specified, in which case the filesystem can | ||
| 1667 | * be mounted with no risk of further damage. | ||
| 1668 | */ | ||
| 1669 | if (xfs_has_needsrepair(mp) && !xfs_has_norecovery(mp)) { | ||
| 1666 | xfs_warn(mp, "Filesystem needs repair. Please run xfs_repair."); | 1670 | xfs_warn(mp, "Filesystem needs repair. Please run xfs_repair."); |
| 1667 | error = -EFSCORRUPTED; | 1671 | error = -EFSCORRUPTED; |
| 1668 | goto out_free_sb; | 1672 | goto out_free_sb; |
| @@ -1038,6 +1038,7 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG) · 1037 unmodified lines | |||
| 1038 | *(.discard) \ | 1038 | *(.discard) \ |
| 1039 | *(.discard.*) \ | 1039 | *(.discard.*) \ |
| 1040 | *(.export_symbol) \ | 1040 | *(.export_symbol) \ |
| 1041 | *(.no_trim_symbol) \ | ||
| 1041 | *(.modinfo) \ | 1042 | *(.modinfo) \ |
| 1042 | /* ld.bfd warns about .gnu.version* even when not emitted */ \ | 1043 | /* ld.bfd warns about .gnu.version* even when not emitted */ \ |
| 1043 | *(.gnu.version*) \ | 1044 | *(.gnu.version*) \ |
| @@ -359,6 +359,7 @@ · 358 unmodified lines | |||
| 359 | # define DP_DSC_BITS_PER_PIXEL_1_4 0x2 | 359 | # define DP_DSC_BITS_PER_PIXEL_1_4 0x2 |
| 360 | # define DP_DSC_BITS_PER_PIXEL_1_2 0x3 | 360 | # define DP_DSC_BITS_PER_PIXEL_1_2 0x3 |
| 361 | # define DP_DSC_BITS_PER_PIXEL_1_1 0x4 | 361 | # define DP_DSC_BITS_PER_PIXEL_1_1 0x4 |
| 362 | # define DP_DSC_BITS_PER_PIXEL_MASK 0x7 | ||
| 362 | 363 | ||
| 363 | #define DP_PSR_SUPPORT 0x070 /* XXX 1.2? */ | 364 | #define DP_PSR_SUPPORT 0x070 /* XXX 1.2? */ |
| 364 | # define DP_PSR_IS_SUPPORTED 1 | 365 | # define DP_PSR_IS_SUPPORTED 1 |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | |||
| 32 | #include <linux/dynamic_debug.h> | 32 | #include <linux/dynamic_debug.h> |
| 33 | 33 | ||
| 34 | #include <drm/drm.h> | 34 | #include <drm/drm.h> |
| 35 | #include <drm/drm_device.h> | ||
| 35 | 36 | ||
| 36 | struct debugfs_regset32; | 37 | struct debugfs_regset32; |
| 37 | struct drm_device; | 38 | struct drm_device; |
| @@ -0,0 +1,16 @@ | |||
| 1 | /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef _DT_BINDINGS_CLK_QCOM_QCS8300_CAM_CC_H | ||
| 7 | #define _DT_BINDINGS_CLK_QCOM_QCS8300_CAM_CC_H | ||
| 8 | |||
| 9 | #include "qcom,sa8775p-camcc.h" | ||
| 10 | |||
| 11 | /* QCS8300 introduces below new clocks compared to SA8775P */ | ||
| 12 | |||
| 13 | /* CAM_CC clocks */ | ||
| 14 | #define CAM_CC_TITAN_TOP_ACCU_SHIFT_CLK 86 | ||
| 15 | |||
| 16 | #endif | ||
| @@ -0,0 +1,17 @@ | |||
| 1 | /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef _DT_BINDINGS_CLK_QCOM_GPUCC_QCS8300_H | ||
| 7 | #define _DT_BINDINGS_CLK_QCOM_GPUCC_QCS8300_H | ||
| 8 | |||
| 9 | #include "qcom,sa8775p-gpucc.h" | ||
| 10 | |||
| 11 | /* QCS8300 introduces below new clocks compared to SA8775P */ | ||
| 12 | |||
| 13 | /* GPU_CC clocks */ | ||
| 14 | #define GPU_CC_CX_ACCU_SHIFT_CLK 23 | ||
| 15 | #define GPU_CC_GX_ACCU_SHIFT_CLK 24 | ||
| 16 | |||
| 17 | #endif | ||
| @@ -861,12 +861,22 @@ static inline bool blk_mq_add_to_batch(struct request *req, · 860 unmodified lines | |||
| 861 | void (*complete)(struct io_comp_batch *)) | 861 | void (*complete)(struct io_comp_batch *)) |
| 862 | { | 862 | { |
| 863 | /* | 863 | /* |
| 864 | * blk_mq_end_request_batch() can't end request allocated from | 864 | * Check various conditions that exclude batch processing: |
| 865 | * sched tags | 865 | * 1) No batch container |
| 866 | * 2) Has scheduler data attached | ||
| 867 | * 3) Not a passthrough request and end_io set | ||
| 868 | * 4) Not a passthrough request and an ioerror | ||
| 866 | */ | 869 | */ |
| 867 | if (!iob || (req->rq_flags & RQF_SCHED_TAGS) || ioerror || | 870 | if (!iob) |
| 868 | (req->end_io && !blk_rq_is_passthrough(req))) | ||
| 869 | return false; | 871 | return false; |
| 872 | if (req->rq_flags & RQF_SCHED_TAGS) | ||
| 873 | return false; | ||
| 874 | if (!blk_rq_is_passthrough(req)) { | ||
| 875 | if (req->end_io) | ||
| 876 | return false; | ||
| 877 | if (ioerror < 0) | ||
| 878 | return false; | ||
| 879 | } | ||
| 870 | 880 | ||
| 871 | if (!iob->complete) | 881 | if (!iob->complete) |
| 872 | iob->complete = complete; | 882 | iob->complete = complete; |
| @@ -71,9 +71,6 @@ enum { · 70 unmodified lines | |||
| 71 | 71 | ||
| 72 | /* Cgroup is frozen. */ | 72 | /* Cgroup is frozen. */ |
| 73 | CGRP_FROZEN, | 73 | CGRP_FROZEN, |
| 74 | |||
| 75 | /* Control group has to be killed. */ | ||
| 76 | CGRP_KILL, | ||
| 77 | }; | 74 | }; |
| 78 | 75 | ||
| 79 | /* cgroup_root->flags */ | 76 | /* cgroup_root->flags */ |
| @@ -461,6 +458,9 @@ struct cgroup { · 381 unmodified lines | |||
| 461 | 458 | ||
| 462 | int nr_threaded_children; /* # of live threaded child cgroups */ | 459 | int nr_threaded_children; /* # of live threaded child cgroups */ |
| 463 | 460 | ||
| 461 | /* sequence number for cgroup.kill, serialized by css_set_lock. */ | ||
| 462 | unsigned int kill_seq; | ||
| 463 | |||
| 464 | struct kernfs_node *kn; /* cgroup kernfs entry */ | 464 | struct kernfs_node *kn; /* cgroup kernfs entry */ |
| 465 | struct cgroup_file procs_file; /* handle for "cgroup.procs" */ | 465 | struct cgroup_file procs_file; /* handle for "cgroup.procs" */ |
| 466 | struct cgroup_file events_file; /* handle for "cgroup.events" */ | 466 | struct cgroup_file events_file; /* handle for "cgroup.events" */ |
| @@ -191,6 +191,25 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, · 190 unmodified lines | |||
| 191 | __v; \ | 191 | __v; \ |
| 192 | }) | 192 | }) |
| 193 | 193 | ||
| 194 | #ifdef __CHECKER__ | ||
| 195 | #define __BUILD_BUG_ON_ZERO_MSG(e, msg) (0) | ||
| 196 | #else /* __CHECKER__ */ | ||
| 197 | #define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);})) | ||
| 198 | #endif /* __CHECKER__ */ | ||
| 199 | |||
| 200 | /* &a[0] degrades to a pointer: a different type from an array */ | ||
| 201 | #define __is_array(a) (!__same_type((a), &(a)[0])) | ||
| 202 | #define __must_be_array(a) __BUILD_BUG_ON_ZERO_MSG(!__is_array(a), \ | ||
| 203 | "must be array") | ||
| 204 | |||
| 205 | #define __is_byte_array(a) (__is_array(a) && sizeof((a)[0]) == 1) | ||
| 206 | #define __must_be_byte_array(a) __BUILD_BUG_ON_ZERO_MSG(!__is_byte_array(a), \ | ||
| 207 | "must be byte array") | ||
| 208 | |||
| 209 | /* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */ | ||
| 210 | #define __must_be_cstr(p) \ | ||
| 211 | __BUILD_BUG_ON_ZERO_MSG(__annotated(p, nonstring), "must be cstr (NUL-terminated)") | ||
| 212 | |||
| 194 | #endif /* __KERNEL__ */ | 213 | #endif /* __KERNEL__ */ |
| 195 | 214 | ||
| 196 | /** | 215 | /** |
| @@ -231,19 +250,6 @@ static inline void *offset_to_ptr(const int *off) · 34 unmodified lines | |||
| 231 | 250 | ||
| 232 | #define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym)) | 251 | #define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym)) |
| 233 | 252 | ||
| 234 | #ifdef __CHECKER__ | ||
| 235 | #define __BUILD_BUG_ON_ZERO_MSG(e, msg) (0) | ||
| 236 | #else /* __CHECKER__ */ | ||
| 237 | #define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);})) | ||
| 238 | #endif /* __CHECKER__ */ | ||
| 239 | |||
| 240 | /* &a[0] degrades to a pointer: a different type from an array */ | ||
| 241 | #define __must_be_array(a) __BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array") | ||
| 242 | |||
| 243 | /* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */ | ||
| 244 | #define __must_be_cstr(p) \ | ||
| 245 | __BUILD_BUG_ON_ZERO_MSG(__annotated(p, nonstring), "must be cstr (NUL-terminated)") | ||
| 246 | |||
| 247 | /* | 253 | /* |
| 248 | * This returns a constant expression while determining if an argument is | 254 | * This returns a constant expression while determining if an argument is |
| 249 | * a constant expression, most importantly without evaluating the argument. | 255 | * a constant expression, most importantly without evaluating the argument. |
| @@ -0,0 +1,69 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2025 Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
| 4 | * Copyright (c) 2025 The Linux Foundation | ||
| 5 | * | ||
| 6 | * A "simple" faux bus that allows devices to be created and added | ||
| 7 | * automatically to it. This is to be used whenever you need to create a | ||
| 8 | * device that is not associated with any "real" system resources, and do | ||
| 9 | * not want to have to deal with a bus/driver binding logic. It is | ||
| 10 | * intended to be very simple, with only a create and a destroy function | ||
| 11 | * available. | ||
| 12 | */ | ||
| 13 | #ifndef _FAUX_DEVICE_H_ | ||
| 14 | #define _FAUX_DEVICE_H_ | ||
| 15 | |||
| 16 | #include <linux/container_of.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | |||
| 19 | /** | ||
| 20 | * struct faux_device - a "faux" device | ||
| 21 | * @dev: internal struct device of the object | ||
| 22 | * | ||
| 23 | * A simple faux device that can be created/destroyed. To be used when a | ||
| 24 | * driver only needs to have a device to "hang" something off. This can be | ||
| 25 | * used for downloading firmware or other basic tasks. Use this instead of | ||
| 26 | * a struct platform_device if the device has no resources assigned to | ||
| 27 | * it at all. | ||
| 28 | */ | ||
| 29 | struct faux_device { | ||
| 30 | struct device dev; | ||
| 31 | }; | ||
| 32 | #define to_faux_device(x) container_of_const((x), struct faux_device, dev) | ||
| 33 | |||
| 34 | /** | ||
| 35 | * struct faux_device_ops - a set of callbacks for a struct faux_device | ||
| 36 | * @probe: called when a faux device is probed by the driver core | ||
| 37 | * before the device is fully bound to the internal faux bus | ||
| 38 | * code. If probe succeeds, return 0, otherwise return a | ||
| 39 | * negative error number to stop the probe sequence from | ||
| 40 | * succeeding. | ||
| 41 | * @remove: called when a faux device is removed from the system | ||
| 42 | * | ||
| 43 | * Both @probe and @remove are optional, if not needed, set to NULL. | ||
| 44 | */ | ||
| 45 | struct faux_device_ops { | ||
| 46 | int (*probe)(struct faux_device *faux_dev); | ||
| 47 | void (*remove)(struct faux_device *faux_dev); | ||
| 48 | }; | ||
| 49 | |||
| 50 | struct faux_device *faux_device_create(const char *name, | ||
| 51 | struct device *parent, | ||
| 52 | const struct faux_device_ops *faux_ops); | ||
| 53 | struct faux_device *faux_device_create_with_groups(const char *name, | ||
| 54 | struct device *parent, | ||
| 55 | const struct faux_device_ops *faux_ops, | ||
| 56 | const struct attribute_group **groups); | ||
| 57 | void faux_device_destroy(struct faux_device *faux_dev); | ||
| 58 | |||
| 59 | static inline void *faux_device_get_drvdata(const struct faux_device *faux_dev) | ||
| 60 | { | ||
| 61 | return dev_get_drvdata(&faux_dev->dev); | ||
| 62 | } | ||
| 63 | |||
| 64 | static inline void faux_device_set_drvdata(struct faux_device *faux_dev, void *data) | ||
| 65 | { | ||
| 66 | dev_set_drvdata(&faux_dev->dev, data); | ||
| 67 | } | ||
| 68 | |||
| 69 | #endif /* _FAUX_DEVICE_H_ */ | ||
| @@ -114,21 +114,22 @@ typedef struct { · 113 unmodified lines | |||
| 114 | #define EFI_MAX_MEMORY_TYPE 16 | 114 | #define EFI_MAX_MEMORY_TYPE 16 |
| 115 | 115 | ||
| 116 | /* Attribute values: */ | 116 | /* Attribute values: */ |
| 117 | #define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ | 117 | #define EFI_MEMORY_UC BIT_ULL(0) /* uncached */ |
| 118 | #define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ | 118 | #define EFI_MEMORY_WC BIT_ULL(1) /* write-coalescing */ |
| 119 | #define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ | 119 | #define EFI_MEMORY_WT BIT_ULL(2) /* write-through */ |
| 120 | #define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ | 120 | #define EFI_MEMORY_WB BIT_ULL(3) /* write-back */ |
| 121 | #define EFI_MEMORY_UCE ((u64)0x0000000000000010ULL) /* uncached, exported */ | 121 | #define EFI_MEMORY_UCE BIT_ULL(4) /* uncached, exported */ |
| 122 | #define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ | 122 | #define EFI_MEMORY_WP BIT_ULL(12) /* write-protect */ |
| 123 | #define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ | 123 | #define EFI_MEMORY_RP BIT_ULL(13) /* read-protect */ |
| 124 | #define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ | 124 | #define EFI_MEMORY_XP BIT_ULL(14) /* execute-protect */ |
| 125 | #define EFI_MEMORY_NV ((u64)0x0000000000008000ULL) /* non-volatile */ | 125 | #define EFI_MEMORY_NV BIT_ULL(15) /* non-volatile */ |
| 126 | #define EFI_MEMORY_MORE_RELIABLE \ | 126 | #define EFI_MEMORY_MORE_RELIABLE BIT_ULL(16) /* higher reliability */ |
| 127 | ((u64)0x0000000000010000ULL) /* higher reliability */ | 127 | #define EFI_MEMORY_RO BIT_ULL(17) /* read-only */ |
| 128 | #define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */ | 128 | #define EFI_MEMORY_SP BIT_ULL(18) /* soft reserved */ |
| 129 | #define EFI_MEMORY_SP ((u64)0x0000000000040000ULL) /* soft reserved */ | 129 | #define EFI_MEMORY_CPU_CRYPTO BIT_ULL(19) /* supports encryption */ |
| 130 | #define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL) /* supports encryption */ | 130 | #define EFI_MEMORY_HOT_PLUGGABLE BIT_ULL(20) /* supports unplugging at runtime */ |
| 131 | #define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ | 131 | #define EFI_MEMORY_RUNTIME BIT_ULL(63) /* range requires runtime mapping */ |
| 132 | |||
| 132 | #define EFI_MEMORY_DESCRIPTOR_VERSION 1 | 133 | #define EFI_MEMORY_DESCRIPTOR_VERSION 1 |
| 133 | 134 | ||
| 134 | #define EFI_PAGE_SHIFT 12 | 135 | #define EFI_PAGE_SHIFT 12 |
| @@ -222,7 +222,6 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, · 221 unmodified lines | |||
| 222 | #define FMODE_FSNOTIFY_HSM(mode) 0 | 222 | #define FMODE_FSNOTIFY_HSM(mode) 0 |
| 223 | #endif | 223 | #endif |
| 224 | 224 | ||
| 225 | |||
| 226 | /* | 225 | /* |
| 227 | * Attribute flags. These should be or-ed together to figure out what | 226 | * Attribute flags. These should be or-ed together to figure out what |
| 228 | * has been changed! | 227 | * has been changed! |
| @@ -791,6 +790,19 @@ struct inode { · 562 unmodified lines | |||
| 791 | 790 | ||
| 792 | static inline void inode_set_cached_link(struct inode *inode, char *link, int linklen) | 791 | static inline void inode_set_cached_link(struct inode *inode, char *link, int linklen) |
| 793 | { | 792 | { |
| 793 | int testlen; | ||
| 794 | |||
| 795 | /* | ||
| 796 | * TODO: patch it into a debug-only check if relevant macros show up. | ||
| 797 | * In the meantime, since we are suffering strlen even on production kernels | ||
| 798 | * to find the right length, do a fixup if the wrong value got passed. | ||
| 799 | */ | ||
| 800 | testlen = strlen(link); | ||
| 801 | if (testlen != linklen) { | ||
| 802 | WARN_ONCE(1, "bad length passed for symlink [%s] (got %d, expected %d)", | ||
| 803 | link, linklen, testlen); | ||
| 804 | linklen = testlen; | ||
| 805 | } | ||
| 794 | inode->i_link = link; | 806 | inode->i_link = link; |
| 795 | inode->i_linklen = linklen; | 807 | inode->i_linklen = linklen; |
| 796 | inode->i_opflags |= IOP_CACHED_LINK; | 808 | inode->i_opflags |= IOP_CACHED_LINK; |
| @@ -3140,6 +3152,12 @@ static inline void exe_file_allow_write_access(struct file *exe_file) · 2343 unmodified lines | |||
| 3140 | allow_write_access(exe_file); | 3152 | allow_write_access(exe_file); |
| 3141 | } | 3153 | } |
| 3142 | 3154 | ||
| 3155 | static inline void file_set_fsnotify_mode(struct file *file, fmode_t mode) | ||
| 3156 | { | ||
| 3157 | file->f_mode &= ~FMODE_FSNOTIFY_MASK; | ||
| 3158 | file->f_mode |= mode; | ||
| 3159 | } | ||
| 3160 | |||
| 3143 | static inline bool inode_is_open_for_write(const struct inode *inode) | 3161 | static inline bool inode_is_open_for_write(const struct inode *inode) |
| 3144 | { | 3162 | { |
| 3145 | return atomic_read(&inode->i_writecount) > 0; | 3163 | return atomic_read(&inode->i_writecount) > 0; |
| @@ -129,7 +129,7 @@ static inline int fsnotify_file(struct file *file, __u32 mask) · 128 unmodified lines | |||
| 129 | 129 | ||
| 130 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 130 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |
| 131 | 131 | ||
| 132 | void file_set_fsnotify_mode(struct file *file); | 132 | void file_set_fsnotify_mode_from_watchers(struct file *file); |
| 133 | 133 | ||
| 134 | /* | 134 | /* |
| 135 | * fsnotify_file_area_perm - permission hook before access to file range | 135 | * fsnotify_file_area_perm - permission hook before access to file range |
| @@ -213,7 +213,7 @@ static inline int fsnotify_open_perm(struct file *file) · 77 unmodified lines | |||
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | #else | 215 | #else |
| 216 | static inline void file_set_fsnotify_mode(struct file *file) | 216 | static inline void file_set_fsnotify_mode_from_watchers(struct file *file) |
| 217 | { | 217 | { |
| 218 | } | 218 | } |
| 219 | 219 | ||
| @@ -125,6 +125,7 @@ struct hrtimer_cpu_base { · 124 unmodified lines | |||
| 125 | ktime_t softirq_expires_next; | 125 | ktime_t softirq_expires_next; |
| 126 | struct hrtimer *softirq_next_timer; | 126 | struct hrtimer *softirq_next_timer; |
| 127 | struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; | 127 | struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; |
| 128 | call_single_data_t csd; | ||
| 128 | } ____cacheline_aligned; | 129 | } ____cacheline_aligned; |
| 129 | 130 | ||
| 130 | 131 | ||
| @@ -244,6 +244,7 @@ enum i2c_driver_flags { · 243 unmodified lines | |||
| 244 | * @id_table: List of I2C devices supported by this driver | 244 | * @id_table: List of I2C devices supported by this driver |
| 245 | * @detect: Callback for device detection | 245 | * @detect: Callback for device detection |
| 246 | * @address_list: The I2C addresses to probe (for detect) | 246 | * @address_list: The I2C addresses to probe (for detect) |
| 247 | * @clients: List of detected clients we created (for i2c-core use only) | ||
| 247 | * @flags: A bitmask of flags defined in &enum i2c_driver_flags | 248 | * @flags: A bitmask of flags defined in &enum i2c_driver_flags |
| 248 | * | 249 | * |
| 249 | * The driver.owner field should be set to the module owner of this driver. | 250 | * The driver.owner field should be set to the module owner of this driver. |
| @@ -298,6 +299,7 @@ struct i2c_driver { · 48 unmodified lines | |||
| 298 | /* Device detection callback for automatic device creation */ | 299 | /* Device detection callback for automatic device creation */ |
| 299 | int (*detect)(struct i2c_client *client, struct i2c_board_info *info); | 300 | int (*detect)(struct i2c_client *client, struct i2c_board_info *info); |
| 300 | const unsigned short *address_list; | 301 | const unsigned short *address_list; |
| 302 | struct list_head clients; | ||
| 301 | 303 | ||
| 302 | u32 flags; | 304 | u32 flags; |
| 303 | }; | 305 | }; |
| @@ -313,6 +315,8 @@ struct i2c_driver { · 9 unmodified lines | |||
| 313 | * @dev: Driver model device node for the slave. | 315 | * @dev: Driver model device node for the slave. |
| 314 | * @init_irq: IRQ that was set at initialization | 316 | * @init_irq: IRQ that was set at initialization |
| 315 | * @irq: indicates the IRQ generated by this device (if any) | 317 | * @irq: indicates the IRQ generated by this device (if any) |
| 318 | * @detected: member of an i2c_driver.clients list or i2c-core's | ||
| 319 | * userspace_devices list | ||
| 316 | * @slave_cb: Callback when I2C slave mode of an adapter is used. The adapter | 320 | * @slave_cb: Callback when I2C slave mode of an adapter is used. The adapter |
| 317 | * calls it to pass on slave events to the slave driver. | 321 | * calls it to pass on slave events to the slave driver. |
| 318 | * @devres_group_id: id of the devres group that will be created for resources | 322 | * @devres_group_id: id of the devres group that will be created for resources |
| @@ -332,8 +336,6 @@ struct i2c_client { · 13 unmodified lines | |||
| 332 | #define I2C_CLIENT_SLAVE 0x20 /* we are the slave */ | 336 | #define I2C_CLIENT_SLAVE 0x20 /* we are the slave */ |
| 333 | #define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */ | 337 | #define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */ |
| 334 | #define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */ | 338 | #define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */ |
| 335 | #define I2C_CLIENT_AUTO 0x100 /* client was auto-detected */ | ||
| 336 | #define I2C_CLIENT_USER 0x200 /* client was userspace-created */ | ||
| 337 | #define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */ | 339 | #define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */ |
| 338 | /* Must match I2C_M_STOP|IGNORE_NAK */ | 340 | /* Must match I2C_M_STOP|IGNORE_NAK */ |
| 339 | 341 | ||
| @@ -345,6 +347,7 @@ struct i2c_client { · 5 unmodified lines | |||
| 345 | struct device dev; /* the device structure */ | 347 | struct device dev; /* the device structure */ |
| 346 | int init_irq; /* irq set at initialization */ | 348 | int init_irq; /* irq set at initialization */ |
| 347 | int irq; /* irq issued by device */ | 349 | int irq; /* irq issued by device */ |
| 350 | struct list_head detected; | ||
| 348 | #if IS_ENABLED(CONFIG_I2C_SLAVE) | 351 | #if IS_ENABLED(CONFIG_I2C_SLAVE) |
| 349 | i2c_slave_cb_t slave_cb; /* callback for slave mode */ | 352 | i2c_slave_cb_t slave_cb; /* callback for slave mode */ |
| 350 | #endif | 353 | #endif |
| @@ -751,6 +754,9 @@ struct i2c_adapter { · 400 unmodified lines | |||
| 751 | char name[48]; | 754 | char name[48]; |
| 752 | struct completion dev_released; | 755 | struct completion dev_released; |
| 753 | 756 | ||
| 757 | struct mutex userspace_clients_lock; | ||
| 758 | struct list_head userspace_clients; | ||
| 759 | |||
| 754 | struct i2c_bus_recovery_info *bus_recovery_info; | 760 | struct i2c_bus_recovery_info *bus_recovery_info; |
| 755 | const struct i2c_adapter_quirks *quirks; | 761 | const struct i2c_adapter_quirks *quirks; |
| 756 | 762 | ||
| @@ -537,7 +537,7 @@ static __always_inline unsigned long msecs_to_jiffies(const unsigned int m) · 536 unmodified lines | |||
| 537 | * | 537 | * |
| 538 | * Return: jiffies value | 538 | * Return: jiffies value |
| 539 | */ | 539 | */ |
| 540 | #define secs_to_jiffies(_secs) ((_secs) * HZ) | 540 | #define secs_to_jiffies(_secs) (unsigned long)((_secs) * HZ) |
| 541 | 541 | ||
| 542 | extern unsigned long __usecs_to_jiffies(const unsigned int u); | 542 | extern unsigned long __usecs_to_jiffies(const unsigned int u); |
| 543 | #if !(USEC_PER_SEC % HZ) | 543 | #if !(USEC_PER_SEC % HZ) |
| @@ -1615,7 +1615,6 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu); · 1614 unmodified lines | |||
| 1615 | bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu); | 1615 | bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu); |
| 1616 | bool kvm_arch_dy_has_pending_interrupt(struct kvm_vcpu *vcpu); | 1616 | bool kvm_arch_dy_has_pending_interrupt(struct kvm_vcpu *vcpu); |
| 1617 | bool kvm_arch_vcpu_preempted_in_kernel(struct kvm_vcpu *vcpu); | 1617 | bool kvm_arch_vcpu_preempted_in_kernel(struct kvm_vcpu *vcpu); |
| 1618 | int kvm_arch_post_init_vm(struct kvm *kvm); | ||
| 1619 | void kvm_arch_pre_destroy_vm(struct kvm *kvm); | 1618 | void kvm_arch_pre_destroy_vm(struct kvm *kvm); |
| 1620 | void kvm_arch_create_vm_debugfs(struct kvm *kvm); | 1619 | void kvm_arch_create_vm_debugfs(struct kvm *kvm); |
| 1621 | 1620 | ||
| @@ -37,12 +37,13 @@ struct lockref { · 36 unmodified lines | |||
| 37 | /** | 37 | /** |
| 38 | * lockref_init - Initialize a lockref | 38 | * lockref_init - Initialize a lockref |
| 39 | * @lockref: pointer to lockref structure | 39 | * @lockref: pointer to lockref structure |
| 40 | * @count: initial count | 40 | * |
| 41 | * Initializes @lockref->count to 1. | ||
| 41 | */ | 42 | */ |
| 42 | static inline void lockref_init(struct lockref *lockref, unsigned int count) | 43 | static inline void lockref_init(struct lockref *lockref) |
| 43 | { | 44 | { |
| 44 | spin_lock_init(&lockref->lock); | 45 | spin_lock_init(&lockref->lock); |
| 45 | lockref->count = count; | 46 | lockref->count = 1; |
| 46 | } | 47 | } |
| 47 | 48 | ||
| 48 | void lockref_get(struct lockref *lockref); | 49 | void lockref_get(struct lockref *lockref); |
| @@ -306,7 +306,10 @@ extern int modules_disabled; /* for sysctl */ · 305 unmodified lines | |||
| 306 | /* Get/put a kernel symbol (calls must be symmetric) */ | 306 | /* Get/put a kernel symbol (calls must be symmetric) */ |
| 307 | void *__symbol_get(const char *symbol); | 307 | void *__symbol_get(const char *symbol); |
| 308 | void *__symbol_get_gpl(const char *symbol); | 308 | void *__symbol_get_gpl(const char *symbol); |
| 309 | #define symbol_get(x) ((typeof(&x))(__symbol_get(__stringify(x)))) | 309 | #define symbol_get(x) ({ \ |
| 310 | static const char __notrim[] \ | ||
| 311 | __used __section(".no_trim_symbol") = __stringify(x); \ | ||
| 312 | (typeof(&x))(__symbol_get(__stringify(x))); }) | ||
| 310 | 313 | ||
| 311 | /* modules using other modules: kdb wants to see this. */ | 314 | /* modules using other modules: kdb wants to see this. */ |
| 312 | struct module_use { | 315 | struct module_use { |
| @@ -2663,6 +2663,12 @@ struct net *dev_net(const struct net_device *dev) · 2662 unmodified lines | |||
| 2663 | return read_pnet(&dev->nd_net); | 2663 | return read_pnet(&dev->nd_net); |
| 2664 | } | 2664 | } |
| 2665 | 2665 | ||
| 2666 | static inline | ||
| 2667 | struct net *dev_net_rcu(const struct net_device *dev) | ||
| 2668 | { | ||
| 2669 | return read_pnet_rcu(&dev->nd_net); | ||
| 2670 | } | ||
| 2671 | |||
| 2666 | static inline | 2672 | static inline |
| 2667 | void dev_net_set(struct net_device *dev, struct net *net) | 2673 | void dev_net_set(struct net_device *dev, struct net *net) |
| 2668 | { | 2674 | { |
| @@ -2904,9 +2910,9 @@ struct pcpu_sw_netstats { · 235 unmodified lines | |||
| 2904 | struct pcpu_dstats { | 2910 | struct pcpu_dstats { |
| 2905 | u64_stats_t rx_packets; | 2911 | u64_stats_t rx_packets; |
| 2906 | u64_stats_t rx_bytes; | 2912 | u64_stats_t rx_bytes; |
| 2907 | u64_stats_t rx_drops; | ||
| 2908 | u64_stats_t tx_packets; | 2913 | u64_stats_t tx_packets; |
| 2909 | u64_stats_t tx_bytes; | 2914 | u64_stats_t tx_bytes; |
| 2915 | u64_stats_t rx_drops; | ||
| 2910 | u64_stats_t tx_drops; | 2916 | u64_stats_t tx_drops; |
| 2911 | struct u64_stats_sync syncp; | 2917 | struct u64_stats_sync syncp; |
| 2912 | } __aligned(8 * sizeof(u64)); | 2918 | } __aligned(8 * sizeof(u64)); |
| @@ -3269,6 +3275,8 @@ static inline struct net_device *first_net_device_rcu(struct net *net) · 356 unmodified lines | |||
| 3269 | } | 3275 | } |
| 3270 | 3276 | ||
| 3271 | int netdev_boot_setup_check(struct net_device *dev); | 3277 | int netdev_boot_setup_check(struct net_device *dev); |
| 3278 | struct net_device *dev_getbyhwaddr(struct net *net, unsigned short type, | ||
| 3279 | const char *hwaddr); | ||
| 3272 | struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type, | 3280 | struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type, |
| 3273 | const char *hwaddr); | 3281 | const char *hwaddr); |
| 3274 | struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type); | 3282 | struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type); |
| @@ -4109,7 +4117,6 @@ void netif_receive_skb_list(struct list_head *head); · 834 unmodified lines | |||
| 4109 | gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); | 4117 | gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); |
| 4110 | void napi_gro_flush(struct napi_struct *napi, bool flush_old); | 4118 | void napi_gro_flush(struct napi_struct *napi, bool flush_old); |
| 4111 | struct sk_buff *napi_get_frags(struct napi_struct *napi); | 4119 | struct sk_buff *napi_get_frags(struct napi_struct *napi); |
| 4112 | void napi_get_frags_check(struct napi_struct *napi); | ||
| 4113 | gro_result_t napi_gro_frags(struct napi_struct *napi); | 4120 | gro_result_t napi_gro_frags(struct napi_struct *napi); |
| 4114 | 4121 | ||
| 4115 | static inline void napi_free_frags(struct napi_struct *napi) | 4122 | static inline void napi_free_frags(struct napi_struct *napi) |
| @@ -278,7 +278,7 @@ struct netfs_io_request { · 277 unmodified lines | |||
| 278 | #define NETFS_RREQ_PAUSE 11 /* Pause subrequest generation */ | 278 | #define NETFS_RREQ_PAUSE 11 /* Pause subrequest generation */ |
| 279 | #define NETFS_RREQ_USE_IO_ITER 12 /* Use ->io_iter rather than ->i_pages */ | 279 | #define NETFS_RREQ_USE_IO_ITER 12 /* Use ->io_iter rather than ->i_pages */ |
| 280 | #define NETFS_RREQ_ALL_QUEUED 13 /* All subreqs are now queued */ | 280 | #define NETFS_RREQ_ALL_QUEUED 13 /* All subreqs are now queued */ |
| 281 | #define NETFS_RREQ_NEED_RETRY 14 /* Need to try retrying */ | 281 | #define NETFS_RREQ_RETRYING 14 /* Set if we're in the retry path */ |
| 282 | #define NETFS_RREQ_USE_PGPRIV2 31 /* [DEPRECATED] Use PG_private_2 to mark | 282 | #define NETFS_RREQ_USE_PGPRIV2 31 /* [DEPRECATED] Use PG_private_2 to mark |
| 283 | * write to cache on read */ | 283 | * write to cache on read */ |
| 284 | const struct netfs_request_ops *netfs_ops; | 284 | const struct netfs_request_ops *netfs_ops; |
| @@ -3134,6 +3134,7 @@ · 3133 unmodified lines | |||
| 3134 | #define PCI_DEVICE_ID_INTEL_HDA_LNL_P 0xa828 | 3134 | #define PCI_DEVICE_ID_INTEL_HDA_LNL_P 0xa828 |
| 3135 | #define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 | 3135 | #define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 |
| 3136 | #define PCI_DEVICE_ID_INTEL_HDA_BMG 0xe2f7 | 3136 | #define PCI_DEVICE_ID_INTEL_HDA_BMG 0xe2f7 |
| 3137 | #define PCI_DEVICE_ID_INTEL_HDA_PTL_H 0xe328 | ||
| 3137 | #define PCI_DEVICE_ID_INTEL_HDA_PTL 0xe428 | 3138 | #define PCI_DEVICE_ID_INTEL_HDA_PTL 0xe428 |
| 3138 | #define PCI_DEVICE_ID_INTEL_HDA_CML_R 0xf0c8 | 3139 | #define PCI_DEVICE_ID_INTEL_HDA_CML_R 0xf0c8 |
| 3139 | #define PCI_DEVICE_ID_INTEL_HDA_RKL_S 0xf1c8 | 3140 | #define PCI_DEVICE_ID_INTEL_HDA_RKL_S 0xf1c8 |
| @@ -814,6 +814,15 @@ struct sev_data_snp_commit { · 813 unmodified lines | |||
| 814 | 814 | ||
| 815 | #ifdef CONFIG_CRYPTO_DEV_SP_PSP | 815 | #ifdef CONFIG_CRYPTO_DEV_SP_PSP |
| 816 | 816 | ||
| 817 | /** | ||
| 818 | * sev_module_init - perform PSP SEV module initialization | ||
| 819 | * | ||
| 820 | * Returns: | ||
| 821 | * 0 if the PSP module is successfully initialized | ||
| 822 | * negative value if the PSP module initialization fails | ||
| 823 | */ | ||
| 824 | int sev_module_init(void); | ||
| 825 | |||
| 817 | /** | 826 | /** |
| 818 | * sev_platform_init - perform SEV INIT command | 827 | * sev_platform_init - perform SEV INIT command |
| 819 | * | 828 | * |
| @@ -43,6 +43,7 @@ struct kernel_clone_args { · 42 unmodified lines | |||
| 43 | void *fn_arg; | 43 | void *fn_arg; |
| 44 | struct cgroup *cgrp; | 44 | struct cgroup *cgrp; |
| 45 | struct css_set *cset; | 45 | struct css_set *cset; |
| 46 | unsigned int kill_seq; | ||
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 48 | /* | 49 | /* |
| @@ -91,6 +91,8 @@ struct sk_psock { · 90 unmodified lines | |||
| 91 | struct sk_psock_progs progs; | 91 | struct sk_psock_progs progs; |
| 92 | #if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) | 92 | #if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) |
| 93 | struct strparser strp; | 93 | struct strparser strp; |
| 94 | u32 copied_seq; | ||
| 95 | u32 ingress_bytes; | ||
| 94 | #endif | 96 | #endif |
| 95 | struct sk_buff_head ingress_skb; | 97 | struct sk_buff_head ingress_skb; |
| 96 | struct list_head ingress_msg; | 98 | struct list_head ingress_msg; |
| @@ -414,7 +414,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, · 413 unmodified lines | |||
| 414 | * must be discoverable by the compiler. | 414 | * must be discoverable by the compiler. |
| 415 | */ | 415 | */ |
| 416 | #define strtomem_pad(dest, src, pad) do { \ | 416 | #define strtomem_pad(dest, src, pad) do { \ |
| 417 | const size_t _dest_len = __builtin_object_size(dest, 1); \ | 417 | const size_t _dest_len = __must_be_byte_array(dest) + \ |
| 418 | ARRAY_SIZE(dest); \ | ||
| 418 | const size_t _src_len = __builtin_object_size(src, 1); \ | 419 | const size_t _src_len = __builtin_object_size(src, 1); \ |
| 419 | \ | 420 | \ |
| 420 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ | 421 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ |
| @@ -437,7 +438,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, · 16 unmodified lines | |||
| 437 | * must be discoverable by the compiler. | 438 | * must be discoverable by the compiler. |
| 438 | */ | 439 | */ |
| 439 | #define strtomem(dest, src) do { \ | 440 | #define strtomem(dest, src) do { \ |
| 440 | const size_t _dest_len = __builtin_object_size(dest, 1); \ | 441 | const size_t _dest_len = __must_be_byte_array(dest) + \ |
| 442 | ARRAY_SIZE(dest); \ | ||
| 441 | const size_t _src_len = __builtin_object_size(src, 1); \ | 443 | const size_t _src_len = __builtin_object_size(src, 1); \ |
| 442 | \ | 444 | \ |
| 443 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ | 445 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ |
| @@ -456,7 +458,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, · 12 unmodified lines | |||
| 456 | * Note that sizes of @dest and @src must be known at compile-time. | 458 | * Note that sizes of @dest and @src must be known at compile-time. |
| 457 | */ | 459 | */ |
| 458 | #define memtostr(dest, src) do { \ | 460 | #define memtostr(dest, src) do { \ |
| 459 | const size_t _dest_len = __builtin_object_size(dest, 1); \ | 461 | const size_t _dest_len = __must_be_byte_array(dest) + \ |
| 462 | ARRAY_SIZE(dest); \ | ||
| 460 | const size_t _src_len = __builtin_object_size(src, 1); \ | 463 | const size_t _src_len = __builtin_object_size(src, 1); \ |
| 461 | const size_t _src_chars = strnlen(src, _src_len); \ | 464 | const size_t _src_chars = strnlen(src, _src_len); \ |
| 462 | const size_t _copy_len = min(_dest_len - 1, _src_chars); \ | 465 | const size_t _copy_len = min(_dest_len - 1, _src_chars); \ |
| @@ -481,7 +484,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, · 18 unmodified lines | |||
| 481 | * Note that sizes of @dest and @src must be known at compile-time. | 484 | * Note that sizes of @dest and @src must be known at compile-time. |
| 482 | */ | 485 | */ |
| 483 | #define memtostr_pad(dest, src) do { \ | 486 | #define memtostr_pad(dest, src) do { \ |
| 484 | const size_t _dest_len = __builtin_object_size(dest, 1); \ | 487 | const size_t _dest_len = __must_be_byte_array(dest) + \ |
| 488 | ARRAY_SIZE(dest); \ | ||
| 485 | const size_t _src_len = __builtin_object_size(src, 1); \ | 489 | const size_t _src_len = __builtin_object_size(src, 1); \ |
| 486 | const size_t _src_chars = strnlen(src, _src_len); \ | 490 | const size_t _src_chars = strnlen(src, _src_len); \ |
| 487 | const size_t _copy_len = min(_dest_len - 1, _src_chars); \ | 491 | const size_t _copy_len = min(_dest_len - 1, _src_chars); \ |
| @@ -668,7 +668,7 @@ struct l2cap_conn { · 667 unmodified lines | |||
| 668 | struct l2cap_chan *smp; | 668 | struct l2cap_chan *smp; |
| 669 | 669 | ||
| 670 | struct list_head chan_l; | 670 | struct list_head chan_l; |
| 671 | struct mutex chan_lock; | 671 | struct mutex lock; |
| 672 | struct kref ref; | 672 | struct kref ref; |
| 673 | struct list_head users; | 673 | struct list_head users; |
| 674 | }; | 674 | }; |
| @@ -970,6 +970,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err); · 295 unmodified lines | |||
| 970 | void l2cap_send_conn_req(struct l2cap_chan *chan); | 970 | void l2cap_send_conn_req(struct l2cap_chan *chan); |
| 971 | 971 | ||
| 972 | struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn); | 972 | struct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn); |
| 973 | struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *conn); | ||
| 973 | void l2cap_conn_put(struct l2cap_conn *conn); | 974 | void l2cap_conn_put(struct l2cap_conn *conn); |
| 974 | 975 | ||
| 975 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); | 976 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); |
| @@ -11,6 +11,9 @@ · 10 unmodified lines | |||
| 11 | #include <net/udp.h> | 11 | #include <net/udp.h> |
| 12 | #include <net/hotdata.h> | 12 | #include <net/hotdata.h> |
| 13 | 13 | ||
| 14 | /* This should be increased if a protocol with a bigger head is added. */ | ||
| 15 | #define GRO_MAX_HEAD (MAX_HEADER + 128) | ||
| 16 | |||
| 14 | struct napi_gro_cb { | 17 | struct napi_gro_cb { |
| 15 | union { | 18 | union { |
| 16 | struct { | 19 | struct { |
| @@ -471,9 +471,12 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, · 470 unmodified lines | |||
| 471 | bool forwarding) | 471 | bool forwarding) |
| 472 | { | 472 | { |
| 473 | const struct rtable *rt = dst_rtable(dst); | 473 | const struct rtable *rt = dst_rtable(dst); |
| 474 | struct net *net = dev_net(dst->dev); | 474 | unsigned int mtu, res; |
| 475 | unsigned int mtu; | 475 | struct net *net; |
| 476 | |||
| 477 | rcu_read_lock(); | ||
| 476 | 478 | ||
| 479 | net = dev_net_rcu(dst->dev); | ||
| 477 | if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) || | 480 | if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) || |
| 478 | ip_mtu_locked(dst) || | 481 | ip_mtu_locked(dst) || |
| 479 | !forwarding) { | 482 | !forwarding) { |
| @@ -497,7 +500,11 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, · 17 unmodified lines | |||
| 497 | out: | 500 | out: |
| 498 | mtu = min_t(unsigned int, mtu, IP_MAX_MTU); | 501 | mtu = min_t(unsigned int, mtu, IP_MAX_MTU); |
| 499 | 502 | ||
| 500 | return mtu - lwtunnel_headroom(dst->lwtstate, mtu); | 503 | res = mtu - lwtunnel_headroom(dst->lwtstate, mtu); |
| 504 | |||
| 505 | rcu_read_unlock(); | ||
| 506 | |||
| 507 | return res; | ||
| 501 | } | 508 | } |
| 502 | 509 | ||
| 503 | static inline unsigned int ip_skb_dst_mtu(struct sock *sk, | 510 | static inline unsigned int ip_skb_dst_mtu(struct sock *sk, |
| @@ -198,10 +198,12 @@ struct sk_buff *l3mdev_l3_out(struct sock *sk, struct sk_buff *skb, u16 proto) · 197 unmodified lines | |||
| 198 | if (netif_is_l3_slave(dev)) { | 198 | if (netif_is_l3_slave(dev)) { |
| 199 | struct net_device *master; | 199 | struct net_device *master; |
| 200 | 200 | ||
| 201 | rcu_read_lock(); | ||
| 201 | master = netdev_master_upper_dev_get_rcu(dev); | 202 | master = netdev_master_upper_dev_get_rcu(dev); |
| 202 | if (master && master->l3mdev_ops->l3mdev_l3_out) | 203 | if (master && master->l3mdev_ops->l3mdev_l3_out) |
| 203 | skb = master->l3mdev_ops->l3mdev_l3_out(master, sk, | 204 | skb = master->l3mdev_ops->l3mdev_l3_out(master, sk, |
| 204 | skb, proto); | 205 | skb, proto); |
| 206 | rcu_read_unlock(); | ||
| 205 | } | 207 | } |
| 206 | 208 | ||
| 207 | return skb; | 209 | return skb; |
| @@ -297,6 +297,7 @@ static inline int check_net(const struct net *net) · 296 unmodified lines | |||
| 297 | } | 297 | } |
| 298 | 298 | ||
| 299 | void net_drop_ns(void *); | 299 | void net_drop_ns(void *); |
| 300 | void net_passive_dec(struct net *net); | ||
| 300 | 301 | ||
| 301 | #else | 302 | #else |
| 302 | 303 | ||
| @@ -326,8 +327,18 @@ static inline int check_net(const struct net *net) · 23 unmodified lines | |||
| 326 | } | 327 | } |
| 327 | 328 | ||
| 328 | #define net_drop_ns NULL | 329 | #define net_drop_ns NULL |
| 330 | |||
| 331 | static inline void net_passive_dec(struct net *net) | ||
| 332 | { | ||
| 333 | refcount_dec(&net->passive); | ||
| 334 | } | ||
| 329 | #endif | 335 | #endif |
| 330 | 336 | ||
| 337 | static inline void net_passive_inc(struct net *net) | ||
| 338 | { | ||
| 339 | refcount_inc(&net->passive); | ||
| 340 | } | ||
| 341 | |||
| 331 | /* Returns true if the netns initialization is completed successfully */ | 342 | /* Returns true if the netns initialization is completed successfully */ |
| 332 | static inline bool net_initialized(const struct net *net) | 343 | static inline bool net_initialized(const struct net *net) |
| 333 | { | 344 | { |
| @@ -398,7 +409,7 @@ static inline struct net *read_pnet(const possible_net_t *pnet) · 64 unmodified lines | |||
| 398 | #endif | 409 | #endif |
| 399 | } | 410 | } |
| 400 | 411 | ||
| 401 | static inline struct net *read_pnet_rcu(possible_net_t *pnet) | 412 | static inline struct net *read_pnet_rcu(const possible_net_t *pnet) |
| 402 | { | 413 | { |
| 403 | #ifdef CONFIG_NET_NS | 414 | #ifdef CONFIG_NET_NS |
| 404 | return rcu_dereference(pnet->net); | 415 | return rcu_dereference(pnet->net); |
| @@ -382,10 +382,15 @@ static inline int inet_iif(const struct sk_buff *skb) · 381 unmodified lines | |||
| 382 | static inline int ip4_dst_hoplimit(const struct dst_entry *dst) | 382 | static inline int ip4_dst_hoplimit(const struct dst_entry *dst) |
| 383 | { | 383 | { |
| 384 | int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT); | 384 | int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT); |
| 385 | struct net *net = dev_net(dst->dev); | ||
| 386 | 385 | ||
| 387 | if (hoplimit == 0) | 386 | if (hoplimit == 0) { |
| 387 | const struct net *net; | ||
| 388 | |||
| 389 | rcu_read_lock(); | ||
| 390 | net = dev_net_rcu(dst->dev); | ||
| 388 | hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl); | 391 | hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl); |
| 392 | rcu_read_unlock(); | ||
| 393 | } | ||
| 389 | return hoplimit; | 394 | return hoplimit; |
| 390 | } | 395 | } |
| 391 | 396 | ||
| @@ -851,7 +851,7 @@ static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, · 850 unmodified lines | |||
| 851 | } | 851 | } |
| 852 | 852 | ||
| 853 | static inline void _bstats_update(struct gnet_stats_basic_sync *bstats, | 853 | static inline void _bstats_update(struct gnet_stats_basic_sync *bstats, |
| 854 | __u64 bytes, __u32 packets) | 854 | __u64 bytes, __u64 packets) |
| 855 | { | 855 | { |
| 856 | u64_stats_update_begin(&bstats->syncp); | 856 | u64_stats_update_begin(&bstats->syncp); |
| 857 | u64_stats_add(&bstats->bytes, bytes); | 857 | u64_stats_add(&bstats->bytes, bytes); |
| @@ -43,6 +43,8 @@ struct strparser; · 42 unmodified lines | |||
| 43 | struct strp_callbacks { | 43 | struct strp_callbacks { |
| 44 | int (*parse_msg)(struct strparser *strp, struct sk_buff *skb); | 44 | int (*parse_msg)(struct strparser *strp, struct sk_buff *skb); |
| 45 | void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb); | 45 | void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb); |
| 46 | int (*read_sock)(struct strparser *strp, read_descriptor_t *desc, | ||
| 47 | sk_read_actor_t recv_actor); | ||
| 46 | int (*read_sock_done)(struct strparser *strp, int err); | 48 | int (*read_sock_done)(struct strparser *strp, int err); |
| 47 | void (*abort_parser)(struct strparser *strp, int err); | 49 | void (*abort_parser)(struct strparser *strp, int err); |
| 48 | void (*lock)(struct strparser *strp); | 50 | void (*lock)(struct strparser *strp); |
| @@ -41,6 +41,7 @@ · 40 unmodified lines | |||
| 41 | #include <net/inet_ecn.h> | 41 | #include <net/inet_ecn.h> |
| 42 | #include <net/dst.h> | 42 | #include <net/dst.h> |
| 43 | #include <net/mptcp.h> | 43 | #include <net/mptcp.h> |
| 44 | #include <net/xfrm.h> | ||
| 44 | 45 | ||
| 45 | #include <linux/seq_file.h> | 46 | #include <linux/seq_file.h> |
| 46 | #include <linux/memcontrol.h> | 47 | #include <linux/memcontrol.h> |
| @@ -683,6 +684,19 @@ void tcp_fin(struct sock *sk); · 636 unmodified lines | |||
| 683 | void tcp_check_space(struct sock *sk); | 684 | void tcp_check_space(struct sock *sk); |
| 684 | void tcp_sack_compress_send_ack(struct sock *sk); | 685 | void tcp_sack_compress_send_ack(struct sock *sk); |
| 685 | 686 | ||
| 687 | static inline void tcp_cleanup_skb(struct sk_buff *skb) | ||
| 688 | { | ||
| 689 | skb_dst_drop(skb); | ||
| 690 | secpath_reset(skb); | ||
| 691 | } | ||
| 692 | |||
| 693 | static inline void tcp_add_receive_queue(struct sock *sk, struct sk_buff *skb) | ||
| 694 | { | ||
| 695 | DEBUG_NET_WARN_ON_ONCE(skb_dst(skb)); | ||
| 696 | DEBUG_NET_WARN_ON_ONCE(secpath_exists(skb)); | ||
| 697 | __skb_queue_tail(&sk->sk_receive_queue, skb); | ||
| 698 | } | ||
| 699 | |||
| 686 | /* tcp_timer.c */ | 700 | /* tcp_timer.c */ |
| 687 | void tcp_init_xmit_timers(struct sock *); | 701 | void tcp_init_xmit_timers(struct sock *); |
| 688 | static inline void tcp_clear_xmit_timers(struct sock *sk) | 702 | static inline void tcp_clear_xmit_timers(struct sock *sk) |
| @@ -729,6 +743,9 @@ void tcp_get_info(struct sock *, struct tcp_info *); · 40 unmodified lines | |||
| 729 | /* Read 'sendfile()'-style from a TCP socket */ | 743 | /* Read 'sendfile()'-style from a TCP socket */ |
| 730 | int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | 744 | int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, |
| 731 | sk_read_actor_t recv_actor); | 745 | sk_read_actor_t recv_actor); |
| 746 | int tcp_read_sock_noack(struct sock *sk, read_descriptor_t *desc, | ||
| 747 | sk_read_actor_t recv_actor, bool noack, | ||
| 748 | u32 *copied_seq); | ||
| 732 | int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor); | 749 | int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor); |
| 733 | struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off); | 750 | struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off); |
| 734 | void tcp_read_done(struct sock *sk, size_t len); | 751 | void tcp_read_done(struct sock *sk, size_t len); |
| @@ -2599,6 +2616,11 @@ struct sk_psock; · 1864 unmodified lines | |||
| 2599 | #ifdef CONFIG_BPF_SYSCALL | 2616 | #ifdef CONFIG_BPF_SYSCALL |
| 2600 | int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore); | 2617 | int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore); |
| 2601 | void tcp_bpf_clone(const struct sock *sk, struct sock *newsk); | 2618 | void tcp_bpf_clone(const struct sock *sk, struct sock *newsk); |
| 2619 | #ifdef CONFIG_BPF_STREAM_PARSER | ||
| 2620 | struct strparser; | ||
| 2621 | int tcp_bpf_strp_read_sock(struct strparser *strp, read_descriptor_t *desc, | ||
| 2622 | sk_read_actor_t recv_actor); | ||
| 2623 | #endif /* CONFIG_BPF_STREAM_PARSER */ | ||
| 2602 | #endif /* CONFIG_BPF_SYSCALL */ | 2624 | #endif /* CONFIG_BPF_SYSCALL */ |
| 2603 | 2625 | ||
| 2604 | #ifdef CONFIG_INET | 2626 | #ifdef CONFIG_INET |
| @@ -99,7 +99,7 @@ · 98 unmodified lines | |||
| 99 | EM(netfs_sreq_trace_limited, "LIMIT") \ | 99 | EM(netfs_sreq_trace_limited, "LIMIT") \ |
| 100 | EM(netfs_sreq_trace_need_clear, "N-CLR") \ | 100 | EM(netfs_sreq_trace_need_clear, "N-CLR") \ |
| 101 | EM(netfs_sreq_trace_partial_read, "PARTR") \ | 101 | EM(netfs_sreq_trace_partial_read, "PARTR") \ |
| 102 | EM(netfs_sreq_trace_need_retry, "NRTRY") \ | 102 | EM(netfs_sreq_trace_need_retry, "ND-RT") \ |
| 103 | EM(netfs_sreq_trace_prepare, "PREP ") \ | 103 | EM(netfs_sreq_trace_prepare, "PREP ") \ |
| 104 | EM(netfs_sreq_trace_prep_failed, "PRPFL") \ | 104 | EM(netfs_sreq_trace_prep_failed, "PRPFL") \ |
| 105 | EM(netfs_sreq_trace_progress, "PRGRS") \ | 105 | EM(netfs_sreq_trace_progress, "PRGRS") \ |
| @@ -108,7 +108,9 @@ · 2 unmodified lines | |||
| 108 | EM(netfs_sreq_trace_short, "SHORT") \ | 108 | EM(netfs_sreq_trace_short, "SHORT") \ |
| 109 | EM(netfs_sreq_trace_split, "SPLIT") \ | 109 | EM(netfs_sreq_trace_split, "SPLIT") \ |
| 110 | EM(netfs_sreq_trace_submit, "SUBMT") \ | 110 | EM(netfs_sreq_trace_submit, "SUBMT") \ |
| 111 | EM(netfs_sreq_trace_superfluous, "SPRFL") \ | ||
| 111 | EM(netfs_sreq_trace_terminated, "TERM ") \ | 112 | EM(netfs_sreq_trace_terminated, "TERM ") \ |
| 113 | EM(netfs_sreq_trace_wait_for, "_WAIT") \ | ||
| 112 | EM(netfs_sreq_trace_write, "WRITE") \ | 114 | EM(netfs_sreq_trace_write, "WRITE") \ |
| 113 | EM(netfs_sreq_trace_write_skip, "SKIP ") \ | 115 | EM(netfs_sreq_trace_write_skip, "SKIP ") \ |
| 114 | E_(netfs_sreq_trace_write_term, "WTERM") | 116 | E_(netfs_sreq_trace_write_term, "WTERM") |
| @@ -219,6 +219,7 @@ · 218 unmodified lines | |||
| 219 | EM(rxrpc_conn_get_conn_input, "GET inp-conn") \ | 219 | EM(rxrpc_conn_get_conn_input, "GET inp-conn") \ |
| 220 | EM(rxrpc_conn_get_idle, "GET idle ") \ | 220 | EM(rxrpc_conn_get_idle, "GET idle ") \ |
| 221 | EM(rxrpc_conn_get_poke_abort, "GET pk-abort") \ | 221 | EM(rxrpc_conn_get_poke_abort, "GET pk-abort") \ |
| 222 | EM(rxrpc_conn_get_poke_secured, "GET secured ") \ | ||
| 222 | EM(rxrpc_conn_get_poke_timer, "GET poke ") \ | 223 | EM(rxrpc_conn_get_poke_timer, "GET poke ") \ |
| 223 | EM(rxrpc_conn_get_service_conn, "GET svc-conn") \ | 224 | EM(rxrpc_conn_get_service_conn, "GET svc-conn") \ |
| 224 | EM(rxrpc_conn_new_client, "NEW client ") \ | 225 | EM(rxrpc_conn_new_client, "NEW client ") \ |
| @@ -411,13 +411,20 @@ struct drm_amdgpu_gem_userptr { · 410 unmodified lines | |||
| 411 | /* GFX12 and later: */ | 411 | /* GFX12 and later: */ |
| 412 | #define AMDGPU_TILING_GFX12_SWIZZLE_MODE_SHIFT 0 | 412 | #define AMDGPU_TILING_GFX12_SWIZZLE_MODE_SHIFT 0 |
| 413 | #define AMDGPU_TILING_GFX12_SWIZZLE_MODE_MASK 0x7 | 413 | #define AMDGPU_TILING_GFX12_SWIZZLE_MODE_MASK 0x7 |
| 414 | /* These are DCC recompression setting for memory management: */ | 414 | /* These are DCC recompression settings for memory management: */ |
| 415 | #define AMDGPU_TILING_GFX12_DCC_MAX_COMPRESSED_BLOCK_SHIFT 3 | 415 | #define AMDGPU_TILING_GFX12_DCC_MAX_COMPRESSED_BLOCK_SHIFT 3 |
| 416 | #define AMDGPU_TILING_GFX12_DCC_MAX_COMPRESSED_BLOCK_MASK 0x3 /* 0:64B, 1:128B, 2:256B */ | 416 | #define AMDGPU_TILING_GFX12_DCC_MAX_COMPRESSED_BLOCK_MASK 0x3 /* 0:64B, 1:128B, 2:256B */ |
| 417 | #define AMDGPU_TILING_GFX12_DCC_NUMBER_TYPE_SHIFT 5 | 417 | #define AMDGPU_TILING_GFX12_DCC_NUMBER_TYPE_SHIFT 5 |
| 418 | #define AMDGPU_TILING_GFX12_DCC_NUMBER_TYPE_MASK 0x7 /* CB_COLOR0_INFO.NUMBER_TYPE */ | 418 | #define AMDGPU_TILING_GFX12_DCC_NUMBER_TYPE_MASK 0x7 /* CB_COLOR0_INFO.NUMBER_TYPE */ |
| 419 | #define AMDGPU_TILING_GFX12_DCC_DATA_FORMAT_SHIFT 8 | 419 | #define AMDGPU_TILING_GFX12_DCC_DATA_FORMAT_SHIFT 8 |
| 420 | #define AMDGPU_TILING_GFX12_DCC_DATA_FORMAT_MASK 0x3f /* [0:4]:CB_COLOR0_INFO.FORMAT, [5]:MM */ | 420 | #define AMDGPU_TILING_GFX12_DCC_DATA_FORMAT_MASK 0x3f /* [0:4]:CB_COLOR0_INFO.FORMAT, [5]:MM */ |
| 421 | /* When clearing the buffer or moving it from VRAM to GTT, don't compress and set DCC metadata | ||
| 422 | * to uncompressed. Set when parts of an allocation bypass DCC and read raw data. */ | ||
| 423 | #define AMDGPU_TILING_GFX12_DCC_WRITE_COMPRESS_DISABLE_SHIFT 14 | ||
| 424 | #define AMDGPU_TILING_GFX12_DCC_WRITE_COMPRESS_DISABLE_MASK 0x1 | ||
| 425 | /* bit gap */ | ||
| 426 | #define AMDGPU_TILING_GFX12_SCANOUT_SHIFT 63 | ||
| 427 | #define AMDGPU_TILING_GFX12_SCANOUT_MASK 0x1 | ||
| 421 | 428 | ||
| 422 | /* Set/Get helpers for tiling flags. */ | 429 | /* Set/Get helpers for tiling flags. */ |
| 423 | #define AMDGPU_TILING_SET(field, value) \ | 430 | #define AMDGPU_TILING_SET(field, value) \ |
| @@ -682,6 +682,7 @@ enum ethtool_link_ext_substate_module { · 681 unmodified lines | |||
| 682 | * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics | 682 | * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics |
| 683 | * @ETH_SS_STATS_RMON: names of RMON statistics | 683 | * @ETH_SS_STATS_RMON: names of RMON statistics |
| 684 | * @ETH_SS_STATS_PHY: names of PHY(dev) statistics | 684 | * @ETH_SS_STATS_PHY: names of PHY(dev) statistics |
| 685 | * @ETH_SS_TS_FLAGS: hardware timestamping flags | ||
| 685 | * | 686 | * |
| 686 | * @ETH_SS_COUNT: number of defined string sets | 687 | * @ETH_SS_COUNT: number of defined string sets |
| 687 | */ | 688 | */ |
| @@ -708,6 +709,7 @@ enum ethtool_stringset { · 20 unmodified lines | |||
| 708 | ETH_SS_STATS_ETH_CTRL, | 709 | ETH_SS_STATS_ETH_CTRL, |
| 709 | ETH_SS_STATS_RMON, | 710 | ETH_SS_STATS_RMON, |
| 710 | ETH_SS_STATS_PHY, | 711 | ETH_SS_STATS_PHY, |
| 712 | ETH_SS_TS_FLAGS, | ||
| 711 | 713 | ||
| 712 | /* add new constants above here */ | 714 | /* add new constants above here */ |
| 713 | ETH_SS_COUNT | 715 | ETH_SS_COUNT |
| @@ -34,7 +34,7 @@ · 33 unmodified lines | |||
| 34 | */ | 34 | */ |
| 35 | 35 | ||
| 36 | 36 | ||
| 37 | #define TASKSTATS_VERSION 14 | 37 | #define TASKSTATS_VERSION 15 |
| 38 | #define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN | 38 | #define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN |
| 39 | * in linux/sched.h */ | 39 | * in linux/sched.h */ |
| 40 | 40 | ||
| @@ -30,7 +30,6 @@ enum thermal_genl_attr { · 29 unmodified lines | |||
| 30 | THERMAL_GENL_ATTR_TZ, | 30 | THERMAL_GENL_ATTR_TZ, |
| 31 | THERMAL_GENL_ATTR_TZ_ID, | 31 | THERMAL_GENL_ATTR_TZ_ID, |
| 32 | THERMAL_GENL_ATTR_TZ_TEMP, | 32 | THERMAL_GENL_ATTR_TZ_TEMP, |
| 33 | THERMAL_GENL_ATTR_TZ_PREV_TEMP, | ||
| 34 | THERMAL_GENL_ATTR_TZ_TRIP, | 33 | THERMAL_GENL_ATTR_TZ_TRIP, |
| 35 | THERMAL_GENL_ATTR_TZ_TRIP_ID, | 34 | THERMAL_GENL_ATTR_TZ_TRIP_ID, |
| 36 | THERMAL_GENL_ATTR_TZ_TRIP_TYPE, | 35 | THERMAL_GENL_ATTR_TZ_TRIP_TYPE, |
| @@ -54,6 +53,7 @@ enum thermal_genl_attr { · 17 unmodified lines | |||
| 54 | THERMAL_GENL_ATTR_THRESHOLD, | 53 | THERMAL_GENL_ATTR_THRESHOLD, |
| 55 | THERMAL_GENL_ATTR_THRESHOLD_TEMP, | 54 | THERMAL_GENL_ATTR_THRESHOLD_TEMP, |
| 56 | THERMAL_GENL_ATTR_THRESHOLD_DIRECTION, | 55 | THERMAL_GENL_ATTR_THRESHOLD_DIRECTION, |
| 56 | THERMAL_GENL_ATTR_TZ_PREV_TEMP, | ||
| 57 | __THERMAL_GENL_ATTR_MAX, | 57 | __THERMAL_GENL_ATTR_MAX, |
| 58 | }; | 58 | }; |
| 59 | #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1) | 59 | #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1) |
| @@ -25,7 +25,7 @@ struct virtio_snd_config { · 24 unmodified lines | |||
| 25 | __le32 streams; | 25 | __le32 streams; |
| 26 | /* # of available channel maps */ | 26 | /* # of available channel maps */ |
| 27 | __le32 chmaps; | 27 | __le32 chmaps; |
| 28 | /* # of available control elements */ | 28 | /* # of available control elements (if VIRTIO_SND_F_CTLS) */ |
| 29 | __le32 controls; | 29 | __le32 controls; |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| @@ -385,8 +385,8 @@ enum { · 384 unmodified lines | |||
| 385 | 385 | ||
| 386 | /* Possible values for dExtendedUFSFeaturesSupport */ | 386 | /* Possible values for dExtendedUFSFeaturesSupport */ |
| 387 | enum { | 387 | enum { |
| 388 | UFS_DEV_LOW_TEMP_NOTIF = BIT(4), | 388 | UFS_DEV_HIGH_TEMP_NOTIF = BIT(4), |
| 389 | UFS_DEV_HIGH_TEMP_NOTIF = BIT(5), | 389 | UFS_DEV_LOW_TEMP_NOTIF = BIT(5), |
| 390 | UFS_DEV_EXT_TEMP_NOTIF = BIT(6), | 390 | UFS_DEV_EXT_TEMP_NOTIF = BIT(6), |
| 391 | UFS_DEV_HPB_SUPPORT = BIT(7), | 391 | UFS_DEV_HPB_SUPPORT = BIT(7), |
| 392 | UFS_DEV_WRITE_BOOSTER_SUP = BIT(8), | 392 | UFS_DEV_WRITE_BOOSTER_SUP = BIT(8), |
| @@ -1309,7 +1309,6 @@ static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg) · 1308 unmodified lines | |||
| 1309 | void ufshcd_enable_irq(struct ufs_hba *hba); | 1309 | void ufshcd_enable_irq(struct ufs_hba *hba); |
| 1310 | void ufshcd_disable_irq(struct ufs_hba *hba); | 1310 | void ufshcd_disable_irq(struct ufs_hba *hba); |
| 1311 | int ufshcd_alloc_host(struct device *, struct ufs_hba **); | 1311 | int ufshcd_alloc_host(struct device *, struct ufs_hba **); |
| 1312 | void ufshcd_dealloc_host(struct ufs_hba *); | ||
| 1313 | int ufshcd_hba_enable(struct ufs_hba *hba); | 1312 | int ufshcd_hba_enable(struct ufs_hba *hba); |
| 1314 | int ufshcd_init(struct ufs_hba *, void __iomem *, unsigned int); | 1313 | int ufshcd_init(struct ufs_hba *, void __iomem *, unsigned int); |
| 1315 | int ufshcd_link_recovery(struct ufs_hba *hba); | 1314 | int ufshcd_link_recovery(struct ufs_hba *hba); |
| @@ -338,7 +338,7 @@ int io_futex_wait(struct io_kiocb *req, unsigned int issue_flags) · 337 unmodified lines | |||
| 338 | hlist_add_head(&req->hash_node, &ctx->futex_list); | 338 | hlist_add_head(&req->hash_node, &ctx->futex_list); |
| 339 | io_ring_submit_unlock(ctx, issue_flags); | 339 | io_ring_submit_unlock(ctx, issue_flags); |
| 340 | 340 | ||
| 341 | futex_queue(&ifd->q, hb); | 341 | futex_queue(&ifd->q, hb, NULL); |
| 342 | return IOU_ISSUE_SKIP_COMPLETE; | 342 | return IOU_ISSUE_SKIP_COMPLETE; |
| 343 | } | 343 | } |
| 344 | 344 | ||
| @@ -415,6 +415,13 @@ void io_destroy_buffers(struct io_ring_ctx *ctx) · 414 unmodified lines | |||
| 415 | } | 415 | } |
| 416 | } | 416 | } |
| 417 | 417 | ||
| 418 | static void io_destroy_bl(struct io_ring_ctx *ctx, struct io_buffer_list *bl) | ||
| 419 | { | ||
| 420 | scoped_guard(mutex, &ctx->mmap_lock) | ||
| 421 | WARN_ON_ONCE(xa_erase(&ctx->io_bl_xa, bl->bgid) != bl); | ||
| 422 | io_put_bl(ctx, bl); | ||
| 423 | } | ||
| 424 | |||
| 418 | int io_remove_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | 425 | int io_remove_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
| 419 | { | 426 | { |
| 420 | struct io_provide_buf *p = io_kiocb_to_cmd(req, struct io_provide_buf); | 427 | struct io_provide_buf *p = io_kiocb_to_cmd(req, struct io_provide_buf); |
| @@ -636,12 +643,13 @@ int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg) · 215 unmodified lines | |||
| 636 | /* if mapped buffer ring OR classic exists, don't allow */ | 643 | /* if mapped buffer ring OR classic exists, don't allow */ |
| 637 | if (bl->flags & IOBL_BUF_RING || !list_empty(&bl->buf_list)) | 644 | if (bl->flags & IOBL_BUF_RING || !list_empty(&bl->buf_list)) |
| 638 | return -EEXIST; | 645 | return -EEXIST; |
| 639 | } else { | 646 | io_destroy_bl(ctx, bl); |
| 640 | free_bl = bl = kzalloc(sizeof(*bl), GFP_KERNEL); | ||
| 641 | if (!bl) | ||
| 642 | return -ENOMEM; | ||
| 643 | } | 647 | } |
| 644 | 648 | ||
| 649 | free_bl = bl = kzalloc(sizeof(*bl), GFP_KERNEL); | ||
| 650 | if (!bl) | ||
| 651 | return -ENOMEM; | ||
| 652 | |||
| 645 | mmap_offset = (unsigned long)reg.bgid << IORING_OFF_PBUF_SHIFT; | 653 | mmap_offset = (unsigned long)reg.bgid << IORING_OFF_PBUF_SHIFT; |
| 646 | ring_size = flex_array_size(br, bufs, reg.ring_entries); | 654 | ring_size = flex_array_size(br, bufs, reg.ring_entries); |
| 647 | 655 | ||
| @@ -54,9 +54,6 @@ bool io_uring_try_cancel_uring_cmd(struct io_ring_ctx *ctx, · 53 unmodified lines | |||
| 54 | continue; | 54 | continue; |
| 55 | 55 | ||
| 56 | if (cmd->flags & IORING_URING_CMD_CANCELABLE) { | 56 | if (cmd->flags & IORING_URING_CMD_CANCELABLE) { |
| 57 | /* ->sqe isn't available if no async data */ | ||
| 58 | if (!req_has_async_data(req)) | ||
| 59 | cmd->sqe = NULL; | ||
| 60 | file->f_op->uring_cmd(cmd, IO_URING_F_CANCEL | | 57 | file->f_op->uring_cmd(cmd, IO_URING_F_CANCEL | |
| 61 | IO_URING_F_COMPLETE_DEFER); | 58 | IO_URING_F_COMPLETE_DEFER); |
| 62 | ret = true; | 59 | ret = true; |
| @@ -179,12 +176,13 @@ static int io_uring_cmd_prep_setup(struct io_kiocb *req, · 116 unmodified lines | |||
| 179 | return -ENOMEM; | 176 | return -ENOMEM; |
| 180 | cache->op_data = NULL; | 177 | cache->op_data = NULL; |
| 181 | 178 | ||
| 182 | if (!(req->flags & REQ_F_FORCE_ASYNC)) { | 179 | /* |
| 183 | /* defer memcpy until we need it */ | 180 | * Unconditionally cache the SQE for now - this is only needed for |
| 184 | ioucmd->sqe = sqe; | 181 | * requests that go async, but prep handlers must ensure that any |
| 185 | return 0; | 182 | * sqe data is stable beyond prep. Since uring_cmd is special in |
| 186 | } | 183 | * that it doesn't read in per-op data, play it safe and ensure that |
| 187 | 184 | * any SQE data is stable beyond prep. This can later get relaxed. | |
| 185 | */ | ||
| 188 | memcpy(cache->sqes, sqe, uring_sqe_size(req->ctx)); | 186 | memcpy(cache->sqes, sqe, uring_sqe_size(req->ctx)); |
| 189 | ioucmd->sqe = cache->sqes; | 187 | ioucmd->sqe = cache->sqes; |
| 190 | return 0; | 188 | return 0; |
| @@ -249,16 +247,8 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags) · 58 unmodified lines | |||
| 249 | } | 247 | } |
| 250 | 248 | ||
| 251 | ret = file->f_op->uring_cmd(ioucmd, issue_flags); | 249 | ret = file->f_op->uring_cmd(ioucmd, issue_flags); |
| 252 | if (ret == -EAGAIN) { | 250 | if (ret == -EAGAIN || ret == -EIOCBQUEUED) |
| 253 | struct io_uring_cmd_data *cache = req->async_data; | 251 | return ret; |
| 254 | |||
| 255 | if (ioucmd->sqe != (void *) cache) | ||
| 256 | memcpy(cache->sqes, ioucmd->sqe, uring_sqe_size(req->ctx)); | ||
| 257 | return -EAGAIN; | ||
| 258 | } else if (ret == -EIOCBQUEUED) { | ||
| 259 | return -EIOCBQUEUED; | ||
| 260 | } | ||
| 261 | |||
| 262 | if (ret < 0) | 252 | if (ret < 0) |
| 263 | req_set_fail(req); | 253 | req_set_fail(req); |
| 264 | io_req_uring_cleanup(req, issue_flags); | 254 | io_req_uring_cleanup(req, issue_flags); |
| @@ -118,7 +118,6 @@ static int io_waitid_finish(struct io_kiocb *req, int ret) · 117 unmodified lines | |||
| 118 | static void io_waitid_complete(struct io_kiocb *req, int ret) | 118 | static void io_waitid_complete(struct io_kiocb *req, int ret) |
| 119 | { | 119 | { |
| 120 | struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid); | 120 | struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid); |
| 121 | struct io_tw_state ts = {}; | ||
| 122 | 121 | ||
| 123 | /* anyone completing better be holding a reference */ | 122 | /* anyone completing better be holding a reference */ |
| 124 | WARN_ON_ONCE(!(atomic_read(&iw->refs) & IO_WAITID_REF_MASK)); | 123 | WARN_ON_ONCE(!(atomic_read(&iw->refs) & IO_WAITID_REF_MASK)); |
| @@ -131,7 +130,6 @@ static void io_waitid_complete(struct io_kiocb *req, int ret) · 6 unmodified lines | |||
| 131 | if (ret < 0) | 130 | if (ret < 0) |
| 132 | req_set_fail(req); | 131 | req_set_fail(req); |
| 133 | io_req_set_res(req, ret, 0); | 132 | io_req_set_res(req, ret, 0); |
| 134 | io_req_task_complete(req, &ts); | ||
| 135 | } | 133 | } |
| 136 | 134 | ||
| 137 | static bool __io_waitid_cancel(struct io_ring_ctx *ctx, struct io_kiocb *req) | 135 | static bool __io_waitid_cancel(struct io_ring_ctx *ctx, struct io_kiocb *req) |
| @@ -153,6 +151,7 @@ static bool __io_waitid_cancel(struct io_ring_ctx *ctx, struct io_kiocb *req) · 15 unmodified lines | |||
| 153 | list_del_init(&iwa->wo.child_wait.entry); | 151 | list_del_init(&iwa->wo.child_wait.entry); |
| 154 | spin_unlock_irq(&iw->head->lock); | 152 | spin_unlock_irq(&iw->head->lock); |
| 155 | io_waitid_complete(req, -ECANCELED); | 153 | io_waitid_complete(req, -ECANCELED); |
| 154 | io_req_queue_tw_complete(req, -ECANCELED); | ||
| 156 | return true; | 155 | return true; |
| 157 | } | 156 | } |
| 158 | 157 | ||
| @@ -258,6 +257,7 @@ static void io_waitid_cb(struct io_kiocb *req, struct io_tw_state *ts) · 99 unmodified lines | |||
| 258 | } | 257 | } |
| 259 | 258 | ||
| 260 | io_waitid_complete(req, ret); | 259 | io_waitid_complete(req, ret); |
| 260 | io_req_task_complete(req, ts); | ||
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | static int io_waitid_wait(struct wait_queue_entry *wait, unsigned mode, | 263 | static int io_waitid_wait(struct wait_queue_entry *wait, unsigned mode, |
| @@ -285,10 +285,16 @@ static int io_waitid_wait(struct wait_queue_entry *wait, unsigned mode, · 21 unmodified lines | |||
| 285 | int io_waitid_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | 285 | int io_waitid_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
| 286 | { | 286 | { |
| 287 | struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid); | 287 | struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid); |
| 288 | struct io_waitid_async *iwa; | ||
| 288 | 289 | ||
| 289 | if (sqe->addr || sqe->buf_index || sqe->addr3 || sqe->waitid_flags) | 290 | if (sqe->addr || sqe->buf_index || sqe->addr3 || sqe->waitid_flags) |
| 290 | return -EINVAL; | 291 | return -EINVAL; |
| 291 | 292 | ||
| 293 | iwa = io_uring_alloc_async_data(NULL, req); | ||
| 294 | if (!unlikely(iwa)) | ||
| 295 | return -ENOMEM; | ||
| 296 | iwa->req = req; | ||
| 297 | |||
| 292 | iw->which = READ_ONCE(sqe->len); | 298 | iw->which = READ_ONCE(sqe->len); |
| 293 | iw->upid = READ_ONCE(sqe->fd); | 299 | iw->upid = READ_ONCE(sqe->fd); |
| 294 | iw->options = READ_ONCE(sqe->file_index); | 300 | iw->options = READ_ONCE(sqe->file_index); |
| @@ -299,16 +305,10 @@ int io_waitid_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 4 unmodified lines | |||
| 299 | int io_waitid(struct io_kiocb *req, unsigned int issue_flags) | 305 | int io_waitid(struct io_kiocb *req, unsigned int issue_flags) |
| 300 | { | 306 | { |
| 301 | struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid); | 307 | struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid); |
| 308 | struct io_waitid_async *iwa = req->async_data; | ||
| 302 | struct io_ring_ctx *ctx = req->ctx; | 309 | struct io_ring_ctx *ctx = req->ctx; |
| 303 | struct io_waitid_async *iwa; | ||
| 304 | int ret; | 310 | int ret; |
| 305 | 311 | ||
| 306 | iwa = io_uring_alloc_async_data(NULL, req); | ||
| 307 | if (!iwa) | ||
| 308 | return -ENOMEM; | ||
| 309 | |||
| 310 | iwa->req = req; | ||
| 311 | |||
| 312 | ret = kernel_waitid_prepare(&iwa->wo, iw->which, iw->upid, &iw->info, | 312 | ret = kernel_waitid_prepare(&iwa->wo, iw->which, iw->upid, &iw->info, |
| 313 | iw->options, NULL); | 313 | iw->options, NULL); |
| 314 | if (ret) | 314 | if (ret) |
| @@ -103,48 +103,50 @@ struct bsd_acct_struct { · 102 unmodified lines | |||
| 103 | atomic_long_t count; | 103 | atomic_long_t count; |
| 104 | struct rcu_head rcu; | 104 | struct rcu_head rcu; |
| 105 | struct mutex lock; | 105 | struct mutex lock; |
| 106 | int active; | 106 | bool active; |
| 107 | bool check_space; | ||
| 107 | unsigned long needcheck; | 108 | unsigned long needcheck; |
| 108 | struct file *file; | 109 | struct file *file; |
| 109 | struct pid_namespace *ns; | 110 | struct pid_namespace *ns; |
| 110 | struct work_struct work; | 111 | struct work_struct work; |
| 111 | struct completion done; | 112 | struct completion done; |
| 113 | acct_t ac; | ||
| 112 | }; | 114 | }; |
| 113 | 115 | ||
| 114 | static void do_acct_process(struct bsd_acct_struct *acct); | 116 | static void fill_ac(struct bsd_acct_struct *acct); |
| 117 | static void acct_write_process(struct bsd_acct_struct *acct); | ||
| 115 | 118 | ||
| 116 | /* | 119 | /* |
| 117 | * Check the amount of free space and suspend/resume accordingly. | 120 | * Check the amount of free space and suspend/resume accordingly. |
| 118 | */ | 121 | */ |
| 119 | static int check_free_space(struct bsd_acct_struct *acct) | 122 | static bool check_free_space(struct bsd_acct_struct *acct) |
| 120 | { | 123 | { |
| 121 | struct kstatfs sbuf; | 124 | struct kstatfs sbuf; |
| 122 | 125 | ||
| 123 | if (time_is_after_jiffies(acct->needcheck)) | 126 | if (!acct->check_space) |
| 124 | goto out; | 127 | return acct->active; |
| 125 | 128 | ||
| 126 | /* May block */ | 129 | /* May block */ |
| 127 | if (vfs_statfs(&acct->file->f_path, &sbuf)) | 130 | if (vfs_statfs(&acct->file->f_path, &sbuf)) |
| 128 | goto out; | 131 | return acct->active; |
| 129 | 132 | ||
| 130 | if (acct->active) { | 133 | if (acct->active) { |
| 131 | u64 suspend = sbuf.f_blocks * SUSPEND; | 134 | u64 suspend = sbuf.f_blocks * SUSPEND; |
| 132 | do_div(suspend, 100); | 135 | do_div(suspend, 100); |
| 133 | if (sbuf.f_bavail <= suspend) { | 136 | if (sbuf.f_bavail <= suspend) { |
| 134 | acct->active = 0; | 137 | acct->active = false; |
| 135 | pr_info("Process accounting paused\n"); | 138 | pr_info("Process accounting paused\n"); |
| 136 | } | 139 | } |
| 137 | } else { | 140 | } else { |
| 138 | u64 resume = sbuf.f_blocks * RESUME; | 141 | u64 resume = sbuf.f_blocks * RESUME; |
| 139 | do_div(resume, 100); | 142 | do_div(resume, 100); |
| 140 | if (sbuf.f_bavail >= resume) { | 143 | if (sbuf.f_bavail >= resume) { |
| 141 | acct->active = 1; | 144 | acct->active = true; |
| 142 | pr_info("Process accounting resumed\n"); | 145 | pr_info("Process accounting resumed\n"); |
| 143 | } | 146 | } |
| 144 | } | 147 | } |
| 145 | 148 | ||
| 146 | acct->needcheck = jiffies + ACCT_TIMEOUT*HZ; | 149 | acct->needcheck = jiffies + ACCT_TIMEOUT*HZ; |
| 147 | out: | ||
| 148 | return acct->active; | 150 | return acct->active; |
| 149 | } | 151 | } |
| 150 | 152 | ||
| @@ -189,7 +191,11 @@ static void acct_pin_kill(struct fs_pin *pin) · 38 unmodified lines | |||
| 189 | { | 191 | { |
| 190 | struct bsd_acct_struct *acct = to_acct(pin); | 192 | struct bsd_acct_struct *acct = to_acct(pin); |
| 191 | mutex_lock(&acct->lock); | 193 | mutex_lock(&acct->lock); |
| 192 | do_acct_process(acct); | 194 | /* |
| 195 | * Fill the accounting struct with the exiting task's info | ||
| 196 | * before punting to the workqueue. | ||
| 197 | */ | ||
| 198 | fill_ac(acct); | ||
| 193 | schedule_work(&acct->work); | 199 | schedule_work(&acct->work); |
| 194 | wait_for_completion(&acct->done); | 200 | wait_for_completion(&acct->done); |
| 195 | cmpxchg(&acct->ns->bacct, pin, NULL); | 201 | cmpxchg(&acct->ns->bacct, pin, NULL); |
| @@ -202,6 +208,9 @@ static void close_work(struct work_struct *work) · 6 unmodified lines | |||
| 202 | { | 208 | { |
| 203 | struct bsd_acct_struct *acct = container_of(work, struct bsd_acct_struct, work); | 209 | struct bsd_acct_struct *acct = container_of(work, struct bsd_acct_struct, work); |
| 204 | struct file *file = acct->file; | 210 | struct file *file = acct->file; |
| 211 | |||
| 212 | /* We were fired by acct_pin_kill() which holds acct->lock. */ | ||
| 213 | acct_write_process(acct); | ||
| 205 | if (file->f_op->flush) | 214 | if (file->f_op->flush) |
| 206 | file->f_op->flush(file, NULL); | 215 | file->f_op->flush(file, NULL); |
| 207 | __fput_sync(file); | 216 | __fput_sync(file); |
| @@ -234,6 +243,20 @@ static int acct_on(struct filename *pathname) · 26 unmodified lines | |||
| 234 | return -EACCES; | 243 | return -EACCES; |
| 235 | } | 244 | } |
| 236 | 245 | ||
| 246 | /* Exclude kernel kernel internal filesystems. */ | ||
| 247 | if (file_inode(file)->i_sb->s_flags & (SB_NOUSER | SB_KERNMOUNT)) { | ||
| 248 | kfree(acct); | ||
| 249 | filp_close(file, NULL); | ||
| 250 | return -EINVAL; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* Exclude procfs and sysfs. */ | ||
| 254 | if (file_inode(file)->i_sb->s_iflags & SB_I_USERNS_VISIBLE) { | ||
| 255 | kfree(acct); | ||
| 256 | filp_close(file, NULL); | ||
| 257 | return -EINVAL; | ||
| 258 | } | ||
| 259 | |||
| 237 | if (!(file->f_mode & FMODE_CAN_WRITE)) { | 260 | if (!(file->f_mode & FMODE_CAN_WRITE)) { |
| 238 | kfree(acct); | 261 | kfree(acct); |
| 239 | filp_close(file, NULL); | 262 | filp_close(file, NULL); |
| @@ -430,13 +453,27 @@ static u32 encode_float(u64 value) · 190 unmodified lines | |||
| 430 | * do_exit() or when switching to a different output file. | 453 | * do_exit() or when switching to a different output file. |
| 431 | */ | 454 | */ |
| 432 | 455 | ||
| 433 | static void fill_ac(acct_t *ac) | 456 | static void fill_ac(struct bsd_acct_struct *acct) |
| 434 | { | 457 | { |
| 435 | struct pacct_struct *pacct = ¤t->signal->pacct; | 458 | struct pacct_struct *pacct = ¤t->signal->pacct; |
| 459 | struct file *file = acct->file; | ||
| 460 | acct_t *ac = &acct->ac; | ||
| 436 | u64 elapsed, run_time; | 461 | u64 elapsed, run_time; |
| 437 | time64_t btime; | 462 | time64_t btime; |
| 438 | struct tty_struct *tty; | 463 | struct tty_struct *tty; |
| 439 | 464 | ||
| 465 | lockdep_assert_held(&acct->lock); | ||
| 466 | |||
| 467 | if (time_is_after_jiffies(acct->needcheck)) { | ||
| 468 | acct->check_space = false; | ||
| 469 | |||
| 470 | /* Don't fill in @ac if nothing will be written. */ | ||
| 471 | if (!acct->active) | ||
| 472 | return; | ||
| 473 | } else { | ||
| 474 | acct->check_space = true; | ||
| 475 | } | ||
| 476 | |||
| 440 | /* | 477 | /* |
| 441 | * Fill the accounting struct with the needed info as recorded | 478 | * Fill the accounting struct with the needed info as recorded |
| 442 | * by the different kernel functions. | 479 | * by the different kernel functions. |
| @@ -484,64 +521,61 @@ static void fill_ac(acct_t *ac) · 41 unmodified lines | |||
| 484 | ac->ac_majflt = encode_comp_t(pacct->ac_majflt); | 521 | ac->ac_majflt = encode_comp_t(pacct->ac_majflt); |
| 485 | ac->ac_exitcode = pacct->ac_exitcode; | 522 | ac->ac_exitcode = pacct->ac_exitcode; |
| 486 | spin_unlock_irq(¤t->sighand->siglock); | 523 | spin_unlock_irq(¤t->sighand->siglock); |
| 487 | } | ||
| 488 | /* | ||
| 489 | * do_acct_process does all actual work. Caller holds the reference to file. | ||
| 490 | */ | ||
| 491 | static void do_acct_process(struct bsd_acct_struct *acct) | ||
| 492 | { | ||
| 493 | acct_t ac; | ||
| 494 | unsigned long flim; | ||
| 495 | const struct cred *orig_cred; | ||
| 496 | struct file *file = acct->file; | ||
| 497 | 524 | ||
| 498 | /* | ||
| 499 | * Accounting records are not subject to resource limits. | ||
| 500 | */ | ||
| 501 | flim = rlimit(RLIMIT_FSIZE); | ||
| 502 | current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; | ||
| 503 | /* Perform file operations on behalf of whoever enabled accounting */ | ||
| 504 | orig_cred = override_creds(file->f_cred); | ||
| 505 | |||
| 506 | /* | ||
| 507 | * First check to see if there is enough free_space to continue | ||
| 508 | * the process accounting system. | ||
| 509 | */ | ||
| 510 | if (!check_free_space(acct)) | ||
| 511 | goto out; | ||
| 512 | |||
| 513 | fill_ac(&ac); | ||
| 514 | /* we really need to bite the bullet and change layout */ | 525 | /* we really need to bite the bullet and change layout */ |
| 515 | ac.ac_uid = from_kuid_munged(file->f_cred->user_ns, orig_cred->uid); | 526 | ac->ac_uid = from_kuid_munged(file->f_cred->user_ns, current_uid()); |
| 516 | ac.ac_gid = from_kgid_munged(file->f_cred->user_ns, orig_cred->gid); | 527 | ac->ac_gid = from_kgid_munged(file->f_cred->user_ns, current_gid()); |
| 517 | #if ACCT_VERSION == 1 || ACCT_VERSION == 2 | 528 | #if ACCT_VERSION == 1 || ACCT_VERSION == 2 |
| 518 | /* backward-compatible 16 bit fields */ | 529 | /* backward-compatible 16 bit fields */ |
| 519 | ac.ac_uid16 = ac.ac_uid; | 530 | ac->ac_uid16 = ac->ac_uid; |
| 520 | ac.ac_gid16 = ac.ac_gid; | 531 | ac->ac_gid16 = ac->ac_gid; |
| 521 | #elif ACCT_VERSION == 3 | 532 | #elif ACCT_VERSION == 3 |
| 522 | { | 533 | { |
| 523 | struct pid_namespace *ns = acct->ns; | 534 | struct pid_namespace *ns = acct->ns; |
| 524 | 535 | ||
| 525 | ac.ac_pid = task_tgid_nr_ns(current, ns); | 536 | ac->ac_pid = task_tgid_nr_ns(current, ns); |
| 526 | rcu_read_lock(); | 537 | rcu_read_lock(); |
| 527 | ac.ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), | 538 | ac->ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), ns); |
| 528 | ns); | ||
| 529 | rcu_read_unlock(); | 539 | rcu_read_unlock(); |
| 530 | } | 540 | } |
| 531 | #endif | 541 | #endif |
| 542 | } | ||
| 543 | |||
| 544 | static void acct_write_process(struct bsd_acct_struct *acct) | ||
| 545 | { | ||
| 546 | struct file *file = acct->file; | ||
| 547 | const struct cred *cred; | ||
| 548 | acct_t *ac = &acct->ac; | ||
| 549 | |||
| 550 | /* Perform file operations on behalf of whoever enabled accounting */ | ||
| 551 | cred = override_creds(file->f_cred); | ||
| 552 | |||
| 532 | /* | 553 | /* |
| 533 | * Get freeze protection. If the fs is frozen, just skip the write | 554 | * First check to see if there is enough free_space to continue |
| 534 | * as we could deadlock the system otherwise. | 555 | * the process accounting system. Then get freeze protection. If |
| 556 | * the fs is frozen, just skip the write as we could deadlock | ||
| 557 | * the system otherwise. | ||
| 535 | */ | 558 | */ |
| 536 | if (file_start_write_trylock(file)) { | 559 | if (check_free_space(acct) && file_start_write_trylock(file)) { |
| 537 | /* it's been opened O_APPEND, so position is irrelevant */ | 560 | /* it's been opened O_APPEND, so position is irrelevant */ |
| 538 | loff_t pos = 0; | 561 | loff_t pos = 0; |
| 539 | __kernel_write(file, &ac, sizeof(acct_t), &pos); | 562 | __kernel_write(file, ac, sizeof(acct_t), &pos); |
| 540 | file_end_write(file); | 563 | file_end_write(file); |
| 541 | } | 564 | } |
| 542 | out: | 565 | |
| 566 | revert_creds(cred); | ||
| 567 | } | ||
| 568 | |||
| 569 | static void do_acct_process(struct bsd_acct_struct *acct) | ||
| 570 | { | ||
| 571 | unsigned long flim; | ||
| 572 | |||
| 573 | /* Accounting records are not subject to resource limits. */ | ||
| 574 | flim = rlimit(RLIMIT_FSIZE); | ||
| 575 | current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; | ||
| 576 | fill_ac(acct); | ||
| 577 | acct_write_process(acct); | ||
| 543 | current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim; | 578 | current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim; |
| 544 | revert_creds(orig_cred); | ||
| 545 | } | 579 | } |
| 546 | 580 | ||
| 547 | /** | 581 | /** |
| @@ -39,7 +39,7 @@ · 38 unmodified lines | |||
| 39 | */ | 39 | */ |
| 40 | 40 | ||
| 41 | /* number of bytes addressable by LDX/STX insn with 16-bit 'off' field */ | 41 | /* number of bytes addressable by LDX/STX insn with 16-bit 'off' field */ |
| 42 | #define GUARD_SZ (1ull << sizeof_field(struct bpf_insn, off) * 8) | 42 | #define GUARD_SZ round_up(1ull << sizeof_field(struct bpf_insn, off) * 8, PAGE_SIZE << 1) |
| 43 | #define KERN_VM_SZ (SZ_4G + GUARD_SZ) | 43 | #define KERN_VM_SZ (SZ_4G + GUARD_SZ) |
| 44 | 44 | ||
| 45 | struct bpf_arena { | 45 | struct bpf_arena { |
| @@ -153,7 +153,7 @@ static struct bpf_map *cgroup_storage_map_alloc(union bpf_attr *attr) · 152 unmodified lines | |||
| 153 | 153 | ||
| 154 | static void cgroup_storage_map_free(struct bpf_map *map) | 154 | static void cgroup_storage_map_free(struct bpf_map *map) |
| 155 | { | 155 | { |
| 156 | bpf_local_storage_map_free(map, &cgroup_cache, NULL); | 156 | bpf_local_storage_map_free(map, &cgroup_cache, &bpf_cgrp_storage_busy); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | /* *gfp_flags* is a hidden argument provided by the verifier */ | 159 | /* *gfp_flags* is a hidden argument provided by the verifier */ |
| @@ -6507,6 +6507,8 @@ static const struct bpf_raw_tp_null_args raw_tp_null_args[] = { · 6506 unmodified lines | |||
| 6507 | { "rxrpc_resend", 0x10 }, | 6507 | { "rxrpc_resend", 0x10 }, |
| 6508 | { "rxrpc_tq", 0x10 }, | 6508 | { "rxrpc_tq", 0x10 }, |
| 6509 | { "rxrpc_client", 0x1 }, | 6509 | { "rxrpc_client", 0x1 }, |
| 6510 | /* skb */ | ||
| 6511 | {"kfree_skb", 0x1000}, | ||
| 6510 | /* sunrpc */ | 6512 | /* sunrpc */ |
| 6511 | { "xs_stream_read_data", 0x1 }, | 6513 | { "xs_stream_read_data", 0x1 }, |
| 6512 | /* ... from xprt_cong_event event class */ | 6514 | /* ... from xprt_cong_event event class */ |
| @@ -268,8 +268,6 @@ static int ringbuf_map_mmap_kern(struct bpf_map *map, struct vm_area_struct *vma · 267 unmodified lines | |||
| 268 | /* allow writable mapping for the consumer_pos only */ | 268 | /* allow writable mapping for the consumer_pos only */ |
| 269 | if (vma->vm_pgoff != 0 || vma->vm_end - vma->vm_start != PAGE_SIZE) | 269 | if (vma->vm_pgoff != 0 || vma->vm_end - vma->vm_start != PAGE_SIZE) |
| 270 | return -EPERM; | 270 | return -EPERM; |
| 271 | } else { | ||
| 272 | vm_flags_clear(vma, VM_MAYWRITE); | ||
| 273 | } | 271 | } |
| 274 | /* remap_vmalloc_range() checks size and offset constraints */ | 272 | /* remap_vmalloc_range() checks size and offset constraints */ |
| 275 | return remap_vmalloc_range(vma, rb_map->rb, | 273 | return remap_vmalloc_range(vma, rb_map->rb, |
| @@ -289,8 +287,6 @@ static int ringbuf_map_mmap_user(struct bpf_map *map, struct vm_area_struct *vma · 13 unmodified lines | |||
| 289 | * position, and the ring buffer data itself. | 287 | * position, and the ring buffer data itself. |
| 290 | */ | 288 | */ |
| 291 | return -EPERM; | 289 | return -EPERM; |
| 292 | } else { | ||
| 293 | vm_flags_clear(vma, VM_MAYWRITE); | ||
| 294 | } | 290 | } |
| 295 | /* remap_vmalloc_range() checks size and offset constraints */ | 291 | /* remap_vmalloc_range() checks size and offset constraints */ |
| 296 | return remap_vmalloc_range(vma, rb_map->rb, vma->vm_pgoff + RINGBUF_PGOFF); | 292 | return remap_vmalloc_range(vma, rb_map->rb, vma->vm_pgoff + RINGBUF_PGOFF); |
| @@ -1035,7 +1035,7 @@ static const struct vm_operations_struct bpf_map_default_vmops = { · 1034 unmodified lines | |||
| 1035 | static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) | 1035 | static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) |
| 1036 | { | 1036 | { |
| 1037 | struct bpf_map *map = filp->private_data; | 1037 | struct bpf_map *map = filp->private_data; |
| 1038 | int err; | 1038 | int err = 0; |
| 1039 | 1039 | ||
| 1040 | if (!map->ops->map_mmap || !IS_ERR_OR_NULL(map->record)) | 1040 | if (!map->ops->map_mmap || !IS_ERR_OR_NULL(map->record)) |
| 1041 | return -ENOTSUPP; | 1041 | return -ENOTSUPP; |
| @@ -1059,24 +1059,33 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) · 17 unmodified lines | |||
| 1059 | err = -EACCES; | 1059 | err = -EACCES; |
| 1060 | goto out; | 1060 | goto out; |
| 1061 | } | 1061 | } |
| 1062 | bpf_map_write_active_inc(map); | ||
| 1062 | } | 1063 | } |
| 1064 | out: | ||
| 1065 | mutex_unlock(&map->freeze_mutex); | ||
| 1066 | if (err) | ||
| 1067 | return err; | ||
| 1063 | 1068 | ||
| 1064 | /* set default open/close callbacks */ | 1069 | /* set default open/close callbacks */ |
| 1065 | vma->vm_ops = &bpf_map_default_vmops; | 1070 | vma->vm_ops = &bpf_map_default_vmops; |
| 1066 | vma->vm_private_data = map; | 1071 | vma->vm_private_data = map; |
| 1067 | vm_flags_clear(vma, VM_MAYEXEC); | 1072 | vm_flags_clear(vma, VM_MAYEXEC); |
| 1073 | /* If mapping is read-only, then disallow potentially re-mapping with | ||
| 1074 | * PROT_WRITE by dropping VM_MAYWRITE flag. This VM_MAYWRITE clearing | ||
| 1075 | * means that as far as BPF map's memory-mapped VMAs are concerned, | ||
| 1076 | * VM_WRITE and VM_MAYWRITE and equivalent, if one of them is set, | ||
| 1077 | * both should be set, so we can forget about VM_MAYWRITE and always | ||
| 1078 | * check just VM_WRITE | ||
| 1079 | */ | ||
| 1068 | if (!(vma->vm_flags & VM_WRITE)) | 1080 | if (!(vma->vm_flags & VM_WRITE)) |
| 1069 | /* disallow re-mapping with PROT_WRITE */ | ||
| 1070 | vm_flags_clear(vma, VM_MAYWRITE); | 1081 | vm_flags_clear(vma, VM_MAYWRITE); |
| 1071 | 1082 | ||
| 1072 | err = map->ops->map_mmap(map, vma); | 1083 | err = map->ops->map_mmap(map, vma); |
| 1073 | if (err) | 1084 | if (err) { |
| 1074 | goto out; | 1085 | if (vma->vm_flags & VM_WRITE) |
| 1086 | bpf_map_write_active_dec(map); | ||
| 1087 | } | ||
| 1075 | 1088 | ||
| 1076 | if (vma->vm_flags & VM_MAYWRITE) | ||
| 1077 | bpf_map_write_active_inc(map); | ||
| 1078 | out: | ||
| 1079 | mutex_unlock(&map->freeze_mutex); | ||
| 1080 | return err; | 1089 | return err; |
| 1081 | } | 1090 | } |
| 1082 | 1091 | ||
| @@ -1968,8 +1977,6 @@ int generic_map_update_batch(struct bpf_map *map, struct file *map_file, · 885 unmodified lines | |||
| 1968 | return err; | 1977 | return err; |
| 1969 | } | 1978 | } |
| 1970 | 1979 | ||
| 1971 | #define MAP_LOOKUP_RETRIES 3 | ||
| 1972 | |||
| 1973 | int generic_map_lookup_batch(struct bpf_map *map, | 1980 | int generic_map_lookup_batch(struct bpf_map *map, |
| 1974 | const union bpf_attr *attr, | 1981 | const union bpf_attr *attr, |
| 1975 | union bpf_attr __user *uattr) | 1982 | union bpf_attr __user *uattr) |
| @@ -1979,8 +1986,8 @@ int generic_map_lookup_batch(struct bpf_map *map, · 3 unmodified lines | |||
| 1979 | void __user *values = u64_to_user_ptr(attr->batch.values); | 1986 | void __user *values = u64_to_user_ptr(attr->batch.values); |
| 1980 | void __user *keys = u64_to_user_ptr(attr->batch.keys); | 1987 | void __user *keys = u64_to_user_ptr(attr->batch.keys); |
| 1981 | void *buf, *buf_prevkey, *prev_key, *key, *value; | 1988 | void *buf, *buf_prevkey, *prev_key, *key, *value; |
| 1982 | int err, retry = MAP_LOOKUP_RETRIES; | ||
| 1983 | u32 value_size, cp, max_count; | 1989 | u32 value_size, cp, max_count; |
| 1990 | int err; | ||
| 1984 | 1991 | ||
| 1985 | if (attr->batch.elem_flags & ~BPF_F_LOCK) | 1992 | if (attr->batch.elem_flags & ~BPF_F_LOCK) |
| 1986 | return -EINVAL; | 1993 | return -EINVAL; |
| @@ -2026,14 +2033,8 @@ int generic_map_lookup_batch(struct bpf_map *map, · 39 unmodified lines | |||
| 2026 | err = bpf_map_copy_value(map, key, value, | 2033 | err = bpf_map_copy_value(map, key, value, |
| 2027 | attr->batch.elem_flags); | 2034 | attr->batch.elem_flags); |
| 2028 | 2035 | ||
| 2029 | if (err == -ENOENT) { | 2036 | if (err == -ENOENT) |
| 2030 | if (retry) { | 2037 | goto next_key; |
| 2031 | retry--; | ||
| 2032 | continue; | ||
| 2033 | } | ||
| 2034 | err = -EINTR; | ||
| 2035 | break; | ||
| 2036 | } | ||
| 2037 | 2038 | ||
| 2038 | if (err) | 2039 | if (err) |
| 2039 | goto free_buf; | 2040 | goto free_buf; |
| @@ -2048,12 +2049,12 @@ int generic_map_lookup_batch(struct bpf_map *map, · 8 unmodified lines | |||
| 2048 | goto free_buf; | 2049 | goto free_buf; |
| 2049 | } | 2050 | } |
| 2050 | 2051 | ||
| 2052 | cp++; | ||
| 2053 | next_key: | ||
| 2051 | if (!prev_key) | 2054 | if (!prev_key) |
| 2052 | prev_key = buf_prevkey; | 2055 | prev_key = buf_prevkey; |
| 2053 | 2056 | ||
| 2054 | swap(prev_key, key); | 2057 | swap(prev_key, key); |
| 2055 | retry = MAP_LOOKUP_RETRIES; | ||
| 2056 | cp++; | ||
| 2057 | cond_resched(); | 2058 | cond_resched(); |
| 2058 | } | 2059 | } |
| 2059 | 2060 | ||
| @@ -1501,6 +1501,8 @@ static int acquire_lock_state(struct bpf_verifier_env *env, int insn_idx, enum r · 1500 unmodified lines | |||
| 1501 | struct bpf_reference_state *s; | 1501 | struct bpf_reference_state *s; |
| 1502 | 1502 | ||
| 1503 | s = acquire_reference_state(env, insn_idx); | 1503 | s = acquire_reference_state(env, insn_idx); |
| 1504 | if (!s) | ||
| 1505 | return -ENOMEM; | ||
| 1504 | s->type = type; | 1506 | s->type = type; |
| 1505 | s->id = id; | 1507 | s->id = id; |
| 1506 | s->ptr = ptr; | 1508 | s->ptr = ptr; |
| @@ -9230,10 +9232,11 @@ static int check_reg_const_str(struct bpf_verifier_env *env, · 7723 unmodified lines | |||
| 9230 | return 0; | 9232 | return 0; |
| 9231 | } | 9233 | } |
| 9232 | 9234 | ||
| 9233 | /* Returns constant key value if possible, else negative error */ | 9235 | /* Returns constant key value in `value` if possible, else negative error */ |
| 9234 | static s64 get_constant_map_key(struct bpf_verifier_env *env, | 9236 | static int get_constant_map_key(struct bpf_verifier_env *env, |
| 9235 | struct bpf_reg_state *key, | 9237 | struct bpf_reg_state *key, |
| 9236 | u32 key_size) | 9238 | u32 key_size, |
| 9239 | s64 *value) | ||
| 9237 | { | 9240 | { |
| 9238 | struct bpf_func_state *state = func(env, key); | 9241 | struct bpf_func_state *state = func(env, key); |
| 9239 | struct bpf_reg_state *reg; | 9242 | struct bpf_reg_state *reg; |
| @@ -9260,8 +9263,10 @@ static s64 get_constant_map_key(struct bpf_verifier_env *env, · 20 unmodified lines | |||
| 9260 | /* First handle precisely tracked STACK_ZERO */ | 9263 | /* First handle precisely tracked STACK_ZERO */ |
| 9261 | for (i = off; i >= 0 && stype[i] == STACK_ZERO; i--) | 9264 | for (i = off; i >= 0 && stype[i] == STACK_ZERO; i--) |
| 9262 | zero_size++; | 9265 | zero_size++; |
| 9263 | if (zero_size >= key_size) | 9266 | if (zero_size >= key_size) { |
| 9267 | *value = 0; | ||
| 9264 | return 0; | 9268 | return 0; |
| 9269 | } | ||
| 9265 | 9270 | ||
| 9266 | /* Check that stack contains a scalar spill of expected size */ | 9271 | /* Check that stack contains a scalar spill of expected size */ |
| 9267 | if (!is_spilled_scalar_reg(&state->stack[spi])) | 9272 | if (!is_spilled_scalar_reg(&state->stack[spi])) |
| @@ -9284,9 +9289,12 @@ static s64 get_constant_map_key(struct bpf_verifier_env *env, · 16 unmodified lines | |||
| 9284 | if (err < 0) | 9289 | if (err < 0) |
| 9285 | return err; | 9290 | return err; |
| 9286 | 9291 | ||
| 9287 | return reg->var_off.value; | 9292 | *value = reg->var_off.value; |
| 9293 | return 0; | ||
| 9288 | } | 9294 | } |
| 9289 | 9295 | ||
| 9296 | static bool can_elide_value_nullness(enum bpf_map_type type); | ||
| 9297 | |||
| 9290 | static int check_func_arg(struct bpf_verifier_env *env, u32 arg, | 9298 | static int check_func_arg(struct bpf_verifier_env *env, u32 arg, |
| 9291 | struct bpf_call_arg_meta *meta, | 9299 | struct bpf_call_arg_meta *meta, |
| 9292 | const struct bpf_func_proto *fn, | 9300 | const struct bpf_func_proto *fn, |
| @@ -9435,9 +9443,16 @@ skip_type_check: · 142 unmodified lines | |||
| 9435 | err = check_helper_mem_access(env, regno, key_size, BPF_READ, false, NULL); | 9443 | err = check_helper_mem_access(env, regno, key_size, BPF_READ, false, NULL); |
| 9436 | if (err) | 9444 | if (err) |
| 9437 | return err; | 9445 | return err; |
| 9438 | meta->const_map_key = get_constant_map_key(env, reg, key_size); | 9446 | if (can_elide_value_nullness(meta->map_ptr->map_type)) { |
| 9439 | if (meta->const_map_key < 0 && meta->const_map_key != -EOPNOTSUPP) | 9447 | err = get_constant_map_key(env, reg, key_size, &meta->const_map_key); |
| 9440 | return meta->const_map_key; | 9448 | if (err < 0) { |
| 9449 | meta->const_map_key = -1; | ||
| 9450 | if (err == -EOPNOTSUPP) | ||
| 9451 | err = 0; | ||
| 9452 | else | ||
| 9453 | return err; | ||
| 9454 | } | ||
| 9455 | } | ||
| 9441 | break; | 9456 | break; |
| 9442 | case ARG_PTR_TO_MAP_VALUE: | 9457 | case ARG_PTR_TO_MAP_VALUE: |
| 9443 | if (type_may_be_null(arg_type) && register_is_null(reg)) | 9458 | if (type_may_be_null(arg_type) && register_is_null(reg)) |
| @@ -4013,7 +4013,7 @@ static void __cgroup_kill(struct cgroup *cgrp) · 4012 unmodified lines | |||
| 4013 | lockdep_assert_held(&cgroup_mutex); | 4013 | lockdep_assert_held(&cgroup_mutex); |
| 4014 | 4014 | ||
| 4015 | spin_lock_irq(&css_set_lock); | 4015 | spin_lock_irq(&css_set_lock); |
| 4016 | set_bit(CGRP_KILL, &cgrp->flags); | 4016 | cgrp->kill_seq++; |
| 4017 | spin_unlock_irq(&css_set_lock); | 4017 | spin_unlock_irq(&css_set_lock); |
| 4018 | 4018 | ||
| 4019 | css_task_iter_start(&cgrp->self, CSS_TASK_ITER_PROCS | CSS_TASK_ITER_THREADED, &it); | 4019 | css_task_iter_start(&cgrp->self, CSS_TASK_ITER_PROCS | CSS_TASK_ITER_THREADED, &it); |
| @@ -4029,10 +4029,6 @@ static void __cgroup_kill(struct cgroup *cgrp) · 9 unmodified lines | |||
| 4029 | send_sig(SIGKILL, task, 0); | 4029 | send_sig(SIGKILL, task, 0); |
| 4030 | } | 4030 | } |
| 4031 | css_task_iter_end(&it); | 4031 | css_task_iter_end(&it); |
| 4032 | |||
| 4033 | spin_lock_irq(&css_set_lock); | ||
| 4034 | clear_bit(CGRP_KILL, &cgrp->flags); | ||
| 4035 | spin_unlock_irq(&css_set_lock); | ||
| 4036 | } | 4032 | } |
| 4037 | 4033 | ||
| 4038 | static void cgroup_kill(struct cgroup *cgrp) | 4034 | static void cgroup_kill(struct cgroup *cgrp) |
| @@ -6488,6 +6484,10 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs) · 2449 unmodified lines | |||
| 6488 | spin_lock_irq(&css_set_lock); | 6484 | spin_lock_irq(&css_set_lock); |
| 6489 | cset = task_css_set(current); | 6485 | cset = task_css_set(current); |
| 6490 | get_css_set(cset); | 6486 | get_css_set(cset); |
| 6487 | if (kargs->cgrp) | ||
| 6488 | kargs->kill_seq = kargs->cgrp->kill_seq; | ||
| 6489 | else | ||
| 6490 | kargs->kill_seq = cset->dfl_cgrp->kill_seq; | ||
| 6491 | spin_unlock_irq(&css_set_lock); | 6491 | spin_unlock_irq(&css_set_lock); |
| 6492 | 6492 | ||
| 6493 | if (!(kargs->flags & CLONE_INTO_CGROUP)) { | 6493 | if (!(kargs->flags & CLONE_INTO_CGROUP)) { |
| @@ -6668,6 +6668,7 @@ void cgroup_post_fork(struct task_struct *child, · 174 unmodified lines | |||
| 6668 | struct kernel_clone_args *kargs) | 6668 | struct kernel_clone_args *kargs) |
| 6669 | __releases(&cgroup_threadgroup_rwsem) __releases(&cgroup_mutex) | 6669 | __releases(&cgroup_threadgroup_rwsem) __releases(&cgroup_mutex) |
| 6670 | { | 6670 | { |
| 6671 | unsigned int cgrp_kill_seq = 0; | ||
| 6671 | unsigned long cgrp_flags = 0; | 6672 | unsigned long cgrp_flags = 0; |
| 6672 | bool kill = false; | 6673 | bool kill = false; |
| 6673 | struct cgroup_subsys *ss; | 6674 | struct cgroup_subsys *ss; |
| @@ -6681,10 +6682,13 @@ void cgroup_post_fork(struct task_struct *child, · 7 unmodified lines | |||
| 6681 | 6682 | ||
| 6682 | /* init tasks are special, only link regular threads */ | 6683 | /* init tasks are special, only link regular threads */ |
| 6683 | if (likely(child->pid)) { | 6684 | if (likely(child->pid)) { |
| 6684 | if (kargs->cgrp) | 6685 | if (kargs->cgrp) { |
| 6685 | cgrp_flags = kargs->cgrp->flags; | 6686 | cgrp_flags = kargs->cgrp->flags; |
| 6686 | else | 6687 | cgrp_kill_seq = kargs->cgrp->kill_seq; |
| 6688 | } else { | ||
| 6687 | cgrp_flags = cset->dfl_cgrp->flags; | 6689 | cgrp_flags = cset->dfl_cgrp->flags; |
| 6690 | cgrp_kill_seq = cset->dfl_cgrp->kill_seq; | ||
| 6691 | } | ||
| 6688 | 6692 | ||
| 6689 | WARN_ON_ONCE(!list_empty(&child->cg_list)); | 6693 | WARN_ON_ONCE(!list_empty(&child->cg_list)); |
| 6690 | cset->nr_tasks++; | 6694 | cset->nr_tasks++; |
| @@ -6719,7 +6723,7 @@ void cgroup_post_fork(struct task_struct *child, · 28 unmodified lines | |||
| 6719 | * child down right after we finished preparing it for | 6723 | * child down right after we finished preparing it for |
| 6720 | * userspace. | 6724 | * userspace. |
| 6721 | */ | 6725 | */ |
| 6722 | kill = test_bit(CGRP_KILL, &cgrp_flags); | 6726 | kill = kargs->kill_seq != cgrp_kill_seq; |
| 6723 | } | 6727 | } |
| 6724 | 6728 | ||
| 6725 | spin_unlock_irq(&css_set_lock); | 6729 | spin_unlock_irq(&css_set_lock); |
| @@ -590,7 +590,6 @@ static void root_cgroup_cputime(struct cgroup_base_stat *bstat) · 589 unmodified lines | |||
| 590 | 590 | ||
| 591 | cputime->sum_exec_runtime += user; | 591 | cputime->sum_exec_runtime += user; |
| 592 | cputime->sum_exec_runtime += sys; | 592 | cputime->sum_exec_runtime += sys; |
| 593 | cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL]; | ||
| 594 | 593 | ||
| 595 | #ifdef CONFIG_SCHED_CORE | 594 | #ifdef CONFIG_SCHED_CORE |
| 596 | bstat->forceidle_sum += cpustat[CPUTIME_FORCEIDLE]; | 595 | bstat->forceidle_sum += cpustat[CPUTIME_FORCEIDLE]; |
| @@ -532,7 +532,8 @@ void futex_q_unlock(struct futex_hash_bucket *hb) · 531 unmodified lines | |||
| 532 | futex_hb_waiters_dec(hb); | 532 | futex_hb_waiters_dec(hb); |
| 533 | } | 533 | } |
| 534 | 534 | ||
| 535 | void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb) | 535 | void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb, |
| 536 | struct task_struct *task) | ||
| 536 | { | 537 | { |
| 537 | int prio; | 538 | int prio; |
| 538 | 539 | ||
| @@ -548,7 +549,7 @@ void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb) · 9 unmodified lines | |||
| 548 | 549 | ||
| 549 | plist_node_init(&q->list, prio); | 550 | plist_node_init(&q->list, prio); |
| 550 | plist_add(&q->list, &hb->chain); | 551 | plist_add(&q->list, &hb->chain); |
| 551 | q->task = current; | 552 | q->task = task; |
| 552 | } | 553 | } |
| 553 | 554 | ||
| 554 | /** | 555 | /** |
| @@ -285,13 +285,15 @@ static inline int futex_get_value_locked(u32 *dest, u32 __user *from) · 284 unmodified lines | |||
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | extern void __futex_unqueue(struct futex_q *q); | 287 | extern void __futex_unqueue(struct futex_q *q); |
| 288 | extern void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb); | 288 | extern void __futex_queue(struct futex_q *q, struct futex_hash_bucket *hb, |
| 289 | struct task_struct *task); | ||
| 289 | extern int futex_unqueue(struct futex_q *q); | 290 | extern int futex_unqueue(struct futex_q *q); |
| 290 | 291 | ||
| 291 | /** | 292 | /** |
| 292 | * futex_queue() - Enqueue the futex_q on the futex_hash_bucket | 293 | * futex_queue() - Enqueue the futex_q on the futex_hash_bucket |
| 293 | * @q: The futex_q to enqueue | 294 | * @q: The futex_q to enqueue |
| 294 | * @hb: The destination hash bucket | 295 | * @hb: The destination hash bucket |
| 296 | * @task: Task queueing this futex | ||
| 295 | * | 297 | * |
| 296 | * The hb->lock must be held by the caller, and is released here. A call to | 298 | * The hb->lock must be held by the caller, and is released here. A call to |
| 297 | * futex_queue() is typically paired with exactly one call to futex_unqueue(). The | 299 | * futex_queue() is typically paired with exactly one call to futex_unqueue(). The |
| @@ -299,11 +301,14 @@ extern int futex_unqueue(struct futex_q *q); · 1 unmodified line | |||
| 299 | * or nothing if the unqueue is done as part of the wake process and the unqueue | 301 | * or nothing if the unqueue is done as part of the wake process and the unqueue |
| 300 | * state is implicit in the state of woken task (see futex_wait_requeue_pi() for | 302 | * state is implicit in the state of woken task (see futex_wait_requeue_pi() for |
| 301 | * an example). | 303 | * an example). |
| 304 | * | ||
| 305 | * Note that @task may be NULL, for async usage of futexes. | ||
| 302 | */ | 306 | */ |
| 303 | static inline void futex_queue(struct futex_q *q, struct futex_hash_bucket *hb) | 307 | static inline void futex_queue(struct futex_q *q, struct futex_hash_bucket *hb, |
| 308 | struct task_struct *task) | ||
| 304 | __releases(&hb->lock) | 309 | __releases(&hb->lock) |
| 305 | { | 310 | { |
| 306 | __futex_queue(q, hb); | 311 | __futex_queue(q, hb, task); |
| 307 | spin_unlock(&hb->lock); | 312 | spin_unlock(&hb->lock); |
| 308 | } | 313 | } |
| 309 | 314 | ||
| @@ -982,7 +982,7 @@ retry_private: · 981 unmodified lines | |||
| 982 | /* | 982 | /* |
| 983 | * Only actually queue now that the atomic ops are done: | 983 | * Only actually queue now that the atomic ops are done: |
| 984 | */ | 984 | */ |
| 985 | __futex_queue(&q, hb); | 985 | __futex_queue(&q, hb, current); |
| 986 | 986 | ||
| 987 | if (trylock) { | 987 | if (trylock) { |
| 988 | ret = rt_mutex_futex_trylock(&q.pi_state->pi_mutex); | 988 | ret = rt_mutex_futex_trylock(&q.pi_state->pi_mutex); |
| @@ -349,7 +349,7 @@ void futex_wait_queue(struct futex_hash_bucket *hb, struct futex_q *q, · 348 unmodified lines | |||
| 349 | * access to the hash list and forcing another memory barrier. | 349 | * access to the hash list and forcing another memory barrier. |
| 350 | */ | 350 | */ |
| 351 | set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE); | 351 | set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE); |
| 352 | futex_queue(q, hb); | 352 | futex_queue(q, hb, current); |
| 353 | 353 | ||
| 354 | /* Arm the timer */ | 354 | /* Arm the timer */ |
| 355 | if (timeout) | 355 | if (timeout) |
| @@ -460,7 +460,7 @@ retry: · 104 unmodified lines | |||
| 460 | * next futex. Queue each futex at this moment so hb can | 460 | * next futex. Queue each futex at this moment so hb can |
| 461 | * be unlocked. | 461 | * be unlocked. |
| 462 | */ | 462 | */ |
| 463 | futex_queue(q, hb); | 463 | futex_queue(q, hb, current); |
| 464 | continue; | 464 | continue; |
| 465 | } | 465 | } |
| 466 | 466 | ||
| @@ -31,10 +31,6 @@ config GENERIC_IRQ_EFFECTIVE_AFF_MASK · 30 unmodified lines | |||
| 31 | config GENERIC_PENDING_IRQ | 31 | config GENERIC_PENDING_IRQ |
| 32 | bool | 32 | bool |
| 33 | 33 | ||
| 34 | # Deduce delayed migration from top-level interrupt chip flags | ||
| 35 | config GENERIC_PENDING_IRQ_CHIPFLAGS | ||
| 36 | bool | ||
| 37 | |||
| 38 | # Support for generic irq migrating off cpu before the cpu is offline. | 34 | # Support for generic irq migrating off cpu before the cpu is offline. |
| 39 | config GENERIC_IRQ_MIGRATION | 35 | config GENERIC_IRQ_MIGRATION |
| 40 | bool | 36 | bool |
| @@ -859,7 +859,7 @@ int kthread_affine_preferred(struct task_struct *p, const struct cpumask *mask) · 858 unmodified lines | |||
| 859 | struct kthread *kthread = to_kthread(p); | 859 | struct kthread *kthread = to_kthread(p); |
| 860 | cpumask_var_t affinity; | 860 | cpumask_var_t affinity; |
| 861 | unsigned long flags; | 861 | unsigned long flags; |
| 862 | int ret; | 862 | int ret = 0; |
| 863 | 863 | ||
| 864 | if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE) || kthread->started) { | 864 | if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE) || kthread->started) { |
| 865 | WARN_ON(1); | 865 | WARN_ON(1); |
| @@ -892,7 +892,7 @@ int kthread_affine_preferred(struct task_struct *p, const struct cpumask *mask) · 26 unmodified lines | |||
| 892 | out: | 892 | out: |
| 893 | free_cpumask_var(affinity); | 893 | free_cpumask_var(affinity); |
| 894 | 894 | ||
| 895 | return 0; | 895 | return ret; |
| 896 | } | 896 | } |
| 897 | 897 | ||
| 898 | /* | 898 | /* |
| @@ -150,7 +150,7 @@ void sched_autogroup_exit_task(struct task_struct *p) · 149 unmodified lines | |||
| 150 | * see this thread after that: we can no longer use signal->autogroup. | 150 | * see this thread after that: we can no longer use signal->autogroup. |
| 151 | * See the PF_EXITING check in task_wants_autogroup(). | 151 | * See the PF_EXITING check in task_wants_autogroup(). |
| 152 | */ | 152 | */ |
| 153 | sched_move_task(p); | 153 | sched_move_task(p, true); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | static void | 156 | static void |
| @@ -182,7 +182,7 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag) · 25 unmodified lines | |||
| 182 | * sched_autogroup_exit_task(). | 182 | * sched_autogroup_exit_task(). |
| 183 | */ | 183 | */ |
| 184 | for_each_thread(p, t) | 184 | for_each_thread(p, t) |
| 185 | sched_move_task(t); | 185 | sched_move_task(t, true); |
| 186 | 186 | ||
| 187 | unlock_task_sighand(p, &flags); | 187 | unlock_task_sighand(p, &flags); |
| 188 | autogroup_kref_put(prev); | 188 | autogroup_kref_put(prev); |
| @@ -1063,9 +1063,10 @@ void wake_up_q(struct wake_q_head *head) · 1062 unmodified lines | |||
| 1063 | struct task_struct *task; | 1063 | struct task_struct *task; |
| 1064 | 1064 | ||
| 1065 | task = container_of(node, struct task_struct, wake_q); | 1065 | task = container_of(node, struct task_struct, wake_q); |
| 1066 | /* Task can safely be re-inserted now: */ | ||
| 1067 | node = node->next; | 1066 | node = node->next; |
| 1068 | task->wake_q.next = NULL; | 1067 | /* pairs with cmpxchg_relaxed() in __wake_q_add() */ |
| 1068 | WRITE_ONCE(task->wake_q.next, NULL); | ||
| 1069 | /* Task can safely be re-inserted now. */ | ||
| 1069 | 1070 | ||
| 1070 | /* | 1071 | /* |
| 1071 | * wake_up_process() executes a full barrier, which pairs with | 1072 | * wake_up_process() executes a full barrier, which pairs with |
| @@ -9050,7 +9051,7 @@ static void sched_change_group(struct task_struct *tsk, struct task_group *group · 7978 unmodified lines | |||
| 9050 | * now. This function just updates tsk->se.cfs_rq and tsk->se.parent to reflect | 9051 | * now. This function just updates tsk->se.cfs_rq and tsk->se.parent to reflect |
| 9051 | * its new group. | 9052 | * its new group. |
| 9052 | */ | 9053 | */ |
| 9053 | void sched_move_task(struct task_struct *tsk) | 9054 | void sched_move_task(struct task_struct *tsk, bool for_autogroup) |
| 9054 | { | 9055 | { |
| 9055 | int queued, running, queue_flags = | 9056 | int queued, running, queue_flags = |
| 9056 | DEQUEUE_SAVE | DEQUEUE_MOVE | DEQUEUE_NOCLOCK; | 9057 | DEQUEUE_SAVE | DEQUEUE_MOVE | DEQUEUE_NOCLOCK; |
| @@ -9079,7 +9080,8 @@ void sched_move_task(struct task_struct *tsk) · 22 unmodified lines | |||
| 9079 | put_prev_task(rq, tsk); | 9080 | put_prev_task(rq, tsk); |
| 9080 | 9081 | ||
| 9081 | sched_change_group(tsk, group); | 9082 | sched_change_group(tsk, group); |
| 9082 | scx_move_task(tsk); | 9083 | if (!for_autogroup) |
| 9084 | scx_cgroup_move_task(tsk); | ||
| 9083 | 9085 | ||
| 9084 | if (queued) | 9086 | if (queued) |
| 9085 | enqueue_task(rq, tsk, queue_flags); | 9087 | enqueue_task(rq, tsk, queue_flags); |
| @@ -9180,7 +9182,7 @@ static void cpu_cgroup_attach(struct cgroup_taskset *tset) · 94 unmodified lines | |||
| 9180 | struct cgroup_subsys_state *css; | 9182 | struct cgroup_subsys_state *css; |
| 9181 | 9183 | ||
| 9182 | cgroup_taskset_for_each(task, css, tset) | 9184 | cgroup_taskset_for_each(task, css, tset) |
| 9183 | sched_move_task(task); | 9185 | sched_move_task(task, false); |
| 9184 | 9186 | ||
| 9185 | scx_cgroup_finish_attach(); | 9187 | scx_cgroup_finish_attach(); |
| 9186 | } | 9188 | } |
| @@ -1262,6 +1262,8 @@ void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns, · 1261 unmodified lines | |||
| 1262 | if (task_has_dl_policy(p)) { | 1262 | if (task_has_dl_policy(p)) { |
| 1263 | P(dl.runtime); | 1263 | P(dl.runtime); |
| 1264 | P(dl.deadline); | 1264 | P(dl.deadline); |
| 1265 | } else if (fair_policy(p->policy)) { | ||
| 1266 | P(se.slice); | ||
| 1265 | } | 1267 | } |
| 1266 | #ifdef CONFIG_SCHED_CLASS_EXT | 1268 | #ifdef CONFIG_SCHED_CLASS_EXT |
| 1267 | __PS("ext.enabled", task_on_scx(p)); | 1269 | __PS("ext.enabled", task_on_scx(p)); |
| @@ -122,6 +122,19 @@ enum scx_ops_flags { · 121 unmodified lines | |||
| 122 | */ | 122 | */ |
| 123 | SCX_OPS_SWITCH_PARTIAL = 1LLU << 3, | 123 | SCX_OPS_SWITCH_PARTIAL = 1LLU << 3, |
| 124 | 124 | ||
| 125 | /* | ||
| 126 | * A migration disabled task can only execute on its current CPU. By | ||
| 127 | * default, such tasks are automatically put on the CPU's local DSQ with | ||
| 128 | * the default slice on enqueue. If this ops flag is set, they also go | ||
| 129 | * through ops.enqueue(). | ||
| 130 | * | ||
| 131 | * A migration disabled task never invokes ops.select_cpu() as it can | ||
| 132 | * only select the current CPU. Also, p->cpus_ptr will only contain its | ||
| 133 | * current CPU while p->nr_cpus_allowed keeps tracking p->user_cpus_ptr | ||
| 134 | * and thus may disagree with cpumask_weight(p->cpus_ptr). | ||
| 135 | */ | ||
| 136 | SCX_OPS_ENQ_MIGRATION_DISABLED = 1LLU << 4, | ||
| 137 | |||
| 125 | /* | 138 | /* |
| 126 | * CPU cgroup support flags | 139 | * CPU cgroup support flags |
| 127 | */ | 140 | */ |
| @@ -130,6 +143,7 @@ enum scx_ops_flags { · 2 unmodified lines | |||
| 130 | SCX_OPS_ALL_FLAGS = SCX_OPS_KEEP_BUILTIN_IDLE | | 143 | SCX_OPS_ALL_FLAGS = SCX_OPS_KEEP_BUILTIN_IDLE | |
| 131 | SCX_OPS_ENQ_LAST | | 144 | SCX_OPS_ENQ_LAST | |
| 132 | SCX_OPS_ENQ_EXITING | | 145 | SCX_OPS_ENQ_EXITING | |
| 146 | SCX_OPS_ENQ_MIGRATION_DISABLED | | ||
| 133 | SCX_OPS_SWITCH_PARTIAL | | 147 | SCX_OPS_SWITCH_PARTIAL | |
| 134 | SCX_OPS_HAS_CGROUP_WEIGHT, | 148 | SCX_OPS_HAS_CGROUP_WEIGHT, |
| 135 | }; | 149 | }; |
| @@ -416,7 +430,7 @@ struct sched_ext_ops { · 280 unmodified lines | |||
| 416 | 430 | ||
| 417 | /** | 431 | /** |
| 418 | * @update_idle: Update the idle state of a CPU | 432 | * @update_idle: Update the idle state of a CPU |
| 419 | * @cpu: CPU to udpate the idle state for | 433 | * @cpu: CPU to update the idle state for |
| 420 | * @idle: whether entering or exiting the idle state | 434 | * @idle: whether entering or exiting the idle state |
| 421 | * | 435 | * |
| 422 | * This operation is called when @rq's CPU goes or leaves the idle | 436 | * This operation is called when @rq's CPU goes or leaves the idle |
| @@ -882,6 +896,7 @@ static bool scx_warned_zero_slice; · 459 unmodified lines | |||
| 882 | 896 | ||
| 883 | static DEFINE_STATIC_KEY_FALSE(scx_ops_enq_last); | 897 | static DEFINE_STATIC_KEY_FALSE(scx_ops_enq_last); |
| 884 | static DEFINE_STATIC_KEY_FALSE(scx_ops_enq_exiting); | 898 | static DEFINE_STATIC_KEY_FALSE(scx_ops_enq_exiting); |
| 899 | static DEFINE_STATIC_KEY_FALSE(scx_ops_enq_migration_disabled); | ||
| 885 | static DEFINE_STATIC_KEY_FALSE(scx_ops_cpu_preempt); | 900 | static DEFINE_STATIC_KEY_FALSE(scx_ops_cpu_preempt); |
| 886 | static DEFINE_STATIC_KEY_FALSE(scx_builtin_idle_enabled); | 901 | static DEFINE_STATIC_KEY_FALSE(scx_builtin_idle_enabled); |
| 887 | 902 | ||
| @@ -1214,7 +1229,7 @@ static bool scx_kf_allowed_if_unlocked(void) · 326 unmodified lines | |||
| 1214 | 1229 | ||
| 1215 | /** | 1230 | /** |
| 1216 | * nldsq_next_task - Iterate to the next task in a non-local DSQ | 1231 | * nldsq_next_task - Iterate to the next task in a non-local DSQ |
| 1217 | * @dsq: user dsq being interated | 1232 | * @dsq: user dsq being iterated |
| 1218 | * @cur: current position, %NULL to start iteration | 1233 | * @cur: current position, %NULL to start iteration |
| 1219 | * @rev: walk backwards | 1234 | * @rev: walk backwards |
| 1220 | * | 1235 | * |
| @@ -2014,6 +2029,11 @@ static void do_enqueue_task(struct rq *rq, struct task_struct *p, u64 enq_flags, · 793 unmodified lines | |||
| 2014 | unlikely(p->flags & PF_EXITING)) | 2029 | unlikely(p->flags & PF_EXITING)) |
| 2015 | goto local; | 2030 | goto local; |
| 2016 | 2031 | ||
| 2032 | /* see %SCX_OPS_ENQ_MIGRATION_DISABLED */ | ||
| 2033 | if (!static_branch_unlikely(&scx_ops_enq_migration_disabled) && | ||
| 2034 | is_migration_disabled(p)) | ||
| 2035 | goto local; | ||
| 2036 | |||
| 2017 | if (!SCX_HAS_OP(enqueue)) | 2037 | if (!SCX_HAS_OP(enqueue)) |
| 2018 | goto global; | 2038 | goto global; |
| 2019 | 2039 | ||
| @@ -2078,7 +2098,7 @@ static void set_task_runnable(struct rq *rq, struct task_struct *p) · 58 unmodified lines | |||
| 2078 | 2098 | ||
| 2079 | /* | 2099 | /* |
| 2080 | * list_add_tail() must be used. scx_ops_bypass() depends on tasks being | 2100 | * list_add_tail() must be used. scx_ops_bypass() depends on tasks being |
| 2081 | * appened to the runnable_list. | 2101 | * appended to the runnable_list. |
| 2082 | */ | 2102 | */ |
| 2083 | list_add_tail(&p->scx.runnable_node, &rq->scx.runnable_list); | 2103 | list_add_tail(&p->scx.runnable_node, &rq->scx.runnable_list); |
| 2084 | } | 2104 | } |
| @@ -2313,12 +2333,35 @@ static void move_remote_task_to_local_dsq(struct task_struct *p, u64 enq_flags, · 228 unmodified lines | |||
| 2313 | * | 2333 | * |
| 2314 | * - The BPF scheduler is bypassed while the rq is offline and we can always say | 2334 | * - The BPF scheduler is bypassed while the rq is offline and we can always say |
| 2315 | * no to the BPF scheduler initiated migrations while offline. | 2335 | * no to the BPF scheduler initiated migrations while offline. |
| 2336 | * | ||
| 2337 | * The caller must ensure that @p and @rq are on different CPUs. | ||
| 2316 | */ | 2338 | */ |
| 2317 | static bool task_can_run_on_remote_rq(struct task_struct *p, struct rq *rq, | 2339 | static bool task_can_run_on_remote_rq(struct task_struct *p, struct rq *rq, |
| 2318 | bool trigger_error) | 2340 | bool trigger_error) |
| 2319 | { | 2341 | { |
| 2320 | int cpu = cpu_of(rq); | 2342 | int cpu = cpu_of(rq); |
| 2321 | 2343 | ||
| 2344 | SCHED_WARN_ON(task_cpu(p) == cpu); | ||
| 2345 | |||
| 2346 | /* | ||
| 2347 | * If @p has migration disabled, @p->cpus_ptr is updated to contain only | ||
| 2348 | * the pinned CPU in migrate_disable_switch() while @p is being switched | ||
| 2349 | * out. However, put_prev_task_scx() is called before @p->cpus_ptr is | ||
| 2350 | * updated and thus another CPU may see @p on a DSQ inbetween leading to | ||
| 2351 | * @p passing the below task_allowed_on_cpu() check while migration is | ||
| 2352 | * disabled. | ||
| 2353 | * | ||
| 2354 | * Test the migration disabled state first as the race window is narrow | ||
| 2355 | * and the BPF scheduler failing to check migration disabled state can | ||
| 2356 | * easily be masked if task_allowed_on_cpu() is done first. | ||
| 2357 | */ | ||
| 2358 | if (unlikely(is_migration_disabled(p))) { | ||
| 2359 | if (trigger_error) | ||
| 2360 | scx_ops_error("SCX_DSQ_LOCAL[_ON] cannot move migration disabled %s[%d] from CPU %d to %d", | ||
| 2361 | p->comm, p->pid, task_cpu(p), cpu); | ||
| 2362 | return false; | ||
| 2363 | } | ||
| 2364 | |||
| 2322 | /* | 2365 | /* |
| 2323 | * We don't require the BPF scheduler to avoid dispatching to offline | 2366 | * We don't require the BPF scheduler to avoid dispatching to offline |
| 2324 | * CPUs mostly for convenience but also because CPUs can go offline | 2367 | * CPUs mostly for convenience but also because CPUs can go offline |
| @@ -2327,14 +2370,11 @@ static bool task_can_run_on_remote_rq(struct task_struct *p, struct rq *rq, · 2 unmodified lines | |||
| 2327 | */ | 2370 | */ |
| 2328 | if (!task_allowed_on_cpu(p, cpu)) { | 2371 | if (!task_allowed_on_cpu(p, cpu)) { |
| 2329 | if (trigger_error) | 2372 | if (trigger_error) |
| 2330 | scx_ops_error("SCX_DSQ_LOCAL[_ON] verdict target cpu %d not allowed for %s[%d]", | 2373 | scx_ops_error("SCX_DSQ_LOCAL[_ON] target CPU %d not allowed for %s[%d]", |
| 2331 | cpu_of(rq), p->comm, p->pid); | 2374 | cpu, p->comm, p->pid); |
| 2332 | return false; | 2375 | return false; |
| 2333 | } | 2376 | } |
| 2334 | 2377 | ||
| 2335 | if (unlikely(is_migration_disabled(p))) | ||
| 2336 | return false; | ||
| 2337 | |||
| 2338 | if (!scx_rq_online(rq)) | 2378 | if (!scx_rq_online(rq)) |
| 2339 | return false; | 2379 | return false; |
| 2340 | 2380 | ||
| @@ -2437,7 +2477,8 @@ static struct rq *move_task_between_dsqs(struct task_struct *p, u64 enq_flags, · 96 unmodified lines | |||
| 2437 | 2477 | ||
| 2438 | if (dst_dsq->id == SCX_DSQ_LOCAL) { | 2478 | if (dst_dsq->id == SCX_DSQ_LOCAL) { |
| 2439 | dst_rq = container_of(dst_dsq, struct rq, scx.local_dsq); | 2479 | dst_rq = container_of(dst_dsq, struct rq, scx.local_dsq); |
| 2440 | if (!task_can_run_on_remote_rq(p, dst_rq, true)) { | 2480 | if (src_rq != dst_rq && |
| 2481 | unlikely(!task_can_run_on_remote_rq(p, dst_rq, true))) { | ||
| 2441 | dst_dsq = find_global_dsq(p); | 2482 | dst_dsq = find_global_dsq(p); |
| 2442 | dst_rq = src_rq; | 2483 | dst_rq = src_rq; |
| 2443 | } | 2484 | } |
| @@ -2480,7 +2521,7 @@ static struct rq *move_task_between_dsqs(struct task_struct *p, u64 enq_flags, · 36 unmodified lines | |||
| 2480 | /* | 2521 | /* |
| 2481 | * A poorly behaving BPF scheduler can live-lock the system by e.g. incessantly | 2522 | * A poorly behaving BPF scheduler can live-lock the system by e.g. incessantly |
| 2482 | * banging on the same DSQ on a large NUMA system to the point where switching | 2523 | * banging on the same DSQ on a large NUMA system to the point where switching |
| 2483 | * to the bypass mode can take a long time. Inject artifical delays while the | 2524 | * to the bypass mode can take a long time. Inject artificial delays while the |
| 2484 | * bypass mode is switching to guarantee timely completion. | 2525 | * bypass mode is switching to guarantee timely completion. |
| 2485 | */ | 2526 | */ |
| 2486 | static void scx_ops_breather(struct rq *rq) | 2527 | static void scx_ops_breather(struct rq *rq) |
| @@ -2575,6 +2616,9 @@ static void dispatch_to_local_dsq(struct rq *rq, struct scx_dispatch_q *dst_dsq, · 88 unmodified lines | |||
| 2575 | { | 2616 | { |
| 2576 | struct rq *src_rq = task_rq(p); | 2617 | struct rq *src_rq = task_rq(p); |
| 2577 | struct rq *dst_rq = container_of(dst_dsq, struct rq, scx.local_dsq); | 2618 | struct rq *dst_rq = container_of(dst_dsq, struct rq, scx.local_dsq); |
| 2619 | #ifdef CONFIG_SMP | ||
| 2620 | struct rq *locked_rq = rq; | ||
| 2621 | #endif | ||
| 2578 | 2622 | ||
| 2579 | /* | 2623 | /* |
| 2580 | * We're synchronized against dequeue through DISPATCHING. As @p can't | 2624 | * We're synchronized against dequeue through DISPATCHING. As @p can't |
| @@ -2588,7 +2632,8 @@ static void dispatch_to_local_dsq(struct rq *rq, struct scx_dispatch_q *dst_dsq, · 7 unmodified lines | |||
| 2588 | } | 2632 | } |
| 2589 | 2633 | ||
| 2590 | #ifdef CONFIG_SMP | 2634 | #ifdef CONFIG_SMP |
| 2591 | if (unlikely(!task_can_run_on_remote_rq(p, dst_rq, true))) { | 2635 | if (src_rq != dst_rq && |
| 2636 | unlikely(!task_can_run_on_remote_rq(p, dst_rq, true))) { | ||
| 2592 | dispatch_enqueue(find_global_dsq(p), p, | 2637 | dispatch_enqueue(find_global_dsq(p), p, |
| 2593 | enq_flags | SCX_ENQ_CLEAR_OPSS); | 2638 | enq_flags | SCX_ENQ_CLEAR_OPSS); |
| 2594 | return; | 2639 | return; |
| @@ -2611,8 +2656,9 @@ static void dispatch_to_local_dsq(struct rq *rq, struct scx_dispatch_q *dst_dsq, · 16 unmodified lines | |||
| 2611 | atomic_long_set_release(&p->scx.ops_state, SCX_OPSS_NONE); | 2656 | atomic_long_set_release(&p->scx.ops_state, SCX_OPSS_NONE); |
| 2612 | 2657 | ||
| 2613 | /* switch to @src_rq lock */ | 2658 | /* switch to @src_rq lock */ |
| 2614 | if (rq != src_rq) { | 2659 | if (locked_rq != src_rq) { |
| 2615 | raw_spin_rq_unlock(rq); | 2660 | raw_spin_rq_unlock(locked_rq); |
| 2661 | locked_rq = src_rq; | ||
| 2616 | raw_spin_rq_lock(src_rq); | 2662 | raw_spin_rq_lock(src_rq); |
| 2617 | } | 2663 | } |
| 2618 | 2664 | ||
| @@ -2630,6 +2676,8 @@ static void dispatch_to_local_dsq(struct rq *rq, struct scx_dispatch_q *dst_dsq, · 11 unmodified lines | |||
| 2630 | } else { | 2676 | } else { |
| 2631 | move_remote_task_to_local_dsq(p, enq_flags, | 2677 | move_remote_task_to_local_dsq(p, enq_flags, |
| 2632 | src_rq, dst_rq); | 2678 | src_rq, dst_rq); |
| 2679 | /* task has been moved to dst_rq, which is now locked */ | ||
| 2680 | locked_rq = dst_rq; | ||
| 2633 | } | 2681 | } |
| 2634 | 2682 | ||
| 2635 | /* if the destination CPU is idle, wake it up */ | 2683 | /* if the destination CPU is idle, wake it up */ |
| @@ -2638,8 +2686,8 @@ static void dispatch_to_local_dsq(struct rq *rq, struct scx_dispatch_q *dst_dsq, · 2 unmodified lines | |||
| 2638 | } | 2686 | } |
| 2639 | 2687 | ||
| 2640 | /* switch back to @rq lock */ | 2688 | /* switch back to @rq lock */ |
| 2641 | if (rq != dst_rq) { | 2689 | if (locked_rq != rq) { |
| 2642 | raw_spin_rq_unlock(dst_rq); | 2690 | raw_spin_rq_unlock(locked_rq); |
| 2643 | raw_spin_rq_lock(rq); | 2691 | raw_spin_rq_lock(rq); |
| 2644 | } | 2692 | } |
| 2645 | #else /* CONFIG_SMP */ | 2693 | #else /* CONFIG_SMP */ |
| @@ -3144,7 +3192,7 @@ static struct task_struct *pick_task_scx(struct rq *rq) · 498 unmodified lines | |||
| 3144 | * | 3192 | * |
| 3145 | * Unless overridden by ops.core_sched_before(), @p->scx.core_sched_at is used | 3193 | * Unless overridden by ops.core_sched_before(), @p->scx.core_sched_at is used |
| 3146 | * to implement the default task ordering. The older the timestamp, the higher | 3194 | * to implement the default task ordering. The older the timestamp, the higher |
| 3147 | * prority the task - the global FIFO ordering matching the default scheduling | 3195 | * priority the task - the global FIFO ordering matching the default scheduling |
| 3148 | * behavior. | 3196 | * behavior. |
| 3149 | * | 3197 | * |
| 3150 | * When ops.core_sched_before() is enabled, @p->scx.core_sched_at is used to | 3198 | * When ops.core_sched_before() is enabled, @p->scx.core_sched_at is used to |
| @@ -3851,7 +3899,7 @@ static void task_tick_scx(struct rq *rq, struct task_struct *curr, int queued) · 700 unmodified lines | |||
| 3851 | curr->scx.slice = 0; | 3899 | curr->scx.slice = 0; |
| 3852 | touch_core_sched(rq, curr); | 3900 | touch_core_sched(rq, curr); |
| 3853 | } else if (SCX_HAS_OP(tick)) { | 3901 | } else if (SCX_HAS_OP(tick)) { |
| 3854 | SCX_CALL_OP(SCX_KF_REST, tick, curr); | 3902 | SCX_CALL_OP_TASK(SCX_KF_REST, tick, curr); |
| 3855 | } | 3903 | } |
| 3856 | 3904 | ||
| 3857 | if (!curr->scx.slice) | 3905 | if (!curr->scx.slice) |
| @@ -3998,7 +4046,7 @@ static void scx_ops_disable_task(struct task_struct *p) · 140 unmodified lines | |||
| 3998 | WARN_ON_ONCE(scx_get_task_state(p) != SCX_TASK_ENABLED); | 4046 | WARN_ON_ONCE(scx_get_task_state(p) != SCX_TASK_ENABLED); |
| 3999 | 4047 | ||
| 4000 | if (SCX_HAS_OP(disable)) | 4048 | if (SCX_HAS_OP(disable)) |
| 4001 | SCX_CALL_OP(SCX_KF_REST, disable, p); | 4049 | SCX_CALL_OP_TASK(SCX_KF_REST, disable, p); |
| 4002 | scx_set_task_state(p, SCX_TASK_READY); | 4050 | scx_set_task_state(p, SCX_TASK_READY); |
| 4003 | } | 4051 | } |
| 4004 | 4052 | ||
| @@ -4027,7 +4075,7 @@ static void scx_ops_exit_task(struct task_struct *p) · 22 unmodified lines | |||
| 4027 | } | 4075 | } |
| 4028 | 4076 | ||
| 4029 | if (SCX_HAS_OP(exit_task)) | 4077 | if (SCX_HAS_OP(exit_task)) |
| 4030 | SCX_CALL_OP(SCX_KF_REST, exit_task, p, &args); | 4078 | SCX_CALL_OP_TASK(SCX_KF_REST, exit_task, p, &args); |
| 4031 | scx_set_task_state(p, SCX_TASK_NONE); | 4079 | scx_set_task_state(p, SCX_TASK_NONE); |
| 4032 | } | 4080 | } |
| 4033 | 4081 | ||
| @@ -4323,24 +4371,11 @@ err: · 289 unmodified lines | |||
| 4323 | return ops_sanitize_err("cgroup_prep_move", ret); | 4371 | return ops_sanitize_err("cgroup_prep_move", ret); |
| 4324 | } | 4372 | } |
| 4325 | 4373 | ||
| 4326 | void scx_move_task(struct task_struct *p) | 4374 | void scx_cgroup_move_task(struct task_struct *p) |
| 4327 | { | 4375 | { |
| 4328 | if (!scx_cgroup_enabled) | 4376 | if (!scx_cgroup_enabled) |
| 4329 | return; | 4377 | return; |
| 4330 | 4378 | ||
| 4331 | /* | ||
| 4332 | * We're called from sched_move_task() which handles both cgroup and | ||
| 4333 | * autogroup moves. Ignore the latter. | ||
| 4334 | * | ||
| 4335 | * Also ignore exiting tasks, because in the exit path tasks transition | ||
| 4336 | * from the autogroup to the root group, so task_group_is_autogroup() | ||
| 4337 | * alone isn't able to catch exiting autogroup tasks. This is safe for | ||
| 4338 | * cgroup_move(), because cgroup migrations never happen for PF_EXITING | ||
| 4339 | * tasks. | ||
| 4340 | */ | ||
| 4341 | if (task_group_is_autogroup(task_group(p)) || (p->flags & PF_EXITING)) | ||
| 4342 | return; | ||
| 4343 | |||
| 4344 | /* | 4379 | /* |
| 4345 | * @p must have ops.cgroup_prep_move() called on it and thus | 4380 | * @p must have ops.cgroup_prep_move() called on it and thus |
| 4346 | * cgrp_moving_from set. | 4381 | * cgrp_moving_from set. |
| @@ -4590,7 +4625,7 @@ static int scx_cgroup_init(void) · 243 unmodified lines | |||
| 4590 | cgroup_warned_missing_idle = false; | 4625 | cgroup_warned_missing_idle = false; |
| 4591 | 4626 | ||
| 4592 | /* | 4627 | /* |
| 4593 | * scx_tg_on/offline() are excluded thorugh scx_cgroup_rwsem. If we walk | 4628 | * scx_tg_on/offline() are excluded through scx_cgroup_rwsem. If we walk |
| 4594 | * cgroups and init, all online cgroups are initialized. | 4629 | * cgroups and init, all online cgroups are initialized. |
| 4595 | */ | 4630 | */ |
| 4596 | rcu_read_lock(); | 4631 | rcu_read_lock(); |
| @@ -5059,6 +5094,7 @@ static void scx_ops_disable_workfn(struct kthread_work *work) · 462 unmodified lines | |||
| 5059 | static_branch_disable(&scx_has_op[i]); | 5094 | static_branch_disable(&scx_has_op[i]); |
| 5060 | static_branch_disable(&scx_ops_enq_last); | 5095 | static_branch_disable(&scx_ops_enq_last); |
| 5061 | static_branch_disable(&scx_ops_enq_exiting); | 5096 | static_branch_disable(&scx_ops_enq_exiting); |
| 5097 | static_branch_disable(&scx_ops_enq_migration_disabled); | ||
| 5062 | static_branch_disable(&scx_ops_cpu_preempt); | 5098 | static_branch_disable(&scx_ops_cpu_preempt); |
| 5063 | static_branch_disable(&scx_builtin_idle_enabled); | 5099 | static_branch_disable(&scx_builtin_idle_enabled); |
| 5064 | synchronize_rcu(); | 5100 | synchronize_rcu(); |
| @@ -5277,9 +5313,10 @@ static void scx_dump_task(struct seq_buf *s, struct scx_dump_ctx *dctx, · 212 unmodified lines | |||
| 5277 | scx_get_task_state(p), p->scx.flags & ~SCX_TASK_STATE_MASK, | 5313 | scx_get_task_state(p), p->scx.flags & ~SCX_TASK_STATE_MASK, |
| 5278 | p->scx.dsq_flags, ops_state & SCX_OPSS_STATE_MASK, | 5314 | p->scx.dsq_flags, ops_state & SCX_OPSS_STATE_MASK, |
| 5279 | ops_state >> SCX_OPSS_QSEQ_SHIFT); | 5315 | ops_state >> SCX_OPSS_QSEQ_SHIFT); |
| 5280 | dump_line(s, " sticky/holding_cpu=%d/%d dsq_id=%s dsq_vtime=%llu slice=%llu", | 5316 | dump_line(s, " sticky/holding_cpu=%d/%d dsq_id=%s", |
| 5281 | p->scx.sticky_cpu, p->scx.holding_cpu, dsq_id_buf, | 5317 | p->scx.sticky_cpu, p->scx.holding_cpu, dsq_id_buf); |
| 5282 | p->scx.dsq_vtime, p->scx.slice); | 5318 | dump_line(s, " dsq_vtime=%llu slice=%llu weight=%u", |
| 5319 | p->scx.dsq_vtime, p->scx.slice, p->scx.weight); | ||
| 5283 | dump_line(s, " cpus=%*pb", cpumask_pr_args(p->cpus_ptr)); | 5320 | dump_line(s, " cpus=%*pb", cpumask_pr_args(p->cpus_ptr)); |
| 5284 | 5321 | ||
| 5285 | if (SCX_HAS_OP(dump_task)) { | 5322 | if (SCX_HAS_OP(dump_task)) { |
| @@ -5667,6 +5704,8 @@ static int scx_ops_enable(struct sched_ext_ops *ops, struct bpf_link *link) · 381 unmodified lines | |||
| 5667 | 5704 | ||
| 5668 | if (ops->flags & SCX_OPS_ENQ_EXITING) | 5705 | if (ops->flags & SCX_OPS_ENQ_EXITING) |
| 5669 | static_branch_enable(&scx_ops_enq_exiting); | 5706 | static_branch_enable(&scx_ops_enq_exiting); |
| 5707 | if (ops->flags & SCX_OPS_ENQ_MIGRATION_DISABLED) | ||
| 5708 | static_branch_enable(&scx_ops_enq_migration_disabled); | ||
| 5670 | if (scx_ops.cpu_acquire || scx_ops.cpu_release) | 5709 | if (scx_ops.cpu_acquire || scx_ops.cpu_release) |
| 5671 | static_branch_enable(&scx_ops_cpu_preempt); | 5710 | static_branch_enable(&scx_ops_cpu_preempt); |
| 5672 | 5711 | ||
| @@ -73,7 +73,7 @@ static inline void scx_update_idle(struct rq *rq, bool idle, bool do_notify) {} · 72 unmodified lines | |||
| 73 | int scx_tg_online(struct task_group *tg); | 73 | int scx_tg_online(struct task_group *tg); |
| 74 | void scx_tg_offline(struct task_group *tg); | 74 | void scx_tg_offline(struct task_group *tg); |
| 75 | int scx_cgroup_can_attach(struct cgroup_taskset *tset); | 75 | int scx_cgroup_can_attach(struct cgroup_taskset *tset); |
| 76 | void scx_move_task(struct task_struct *p); | 76 | void scx_cgroup_move_task(struct task_struct *p); |
| 77 | void scx_cgroup_finish_attach(void); | 77 | void scx_cgroup_finish_attach(void); |
| 78 | void scx_cgroup_cancel_attach(struct cgroup_taskset *tset); | 78 | void scx_cgroup_cancel_attach(struct cgroup_taskset *tset); |
| 79 | void scx_group_set_weight(struct task_group *tg, unsigned long cgrp_weight); | 79 | void scx_group_set_weight(struct task_group *tg, unsigned long cgrp_weight); |
| @@ -82,7 +82,7 @@ void scx_group_set_idle(struct task_group *tg, bool idle); · 2 unmodified lines | |||
| 82 | static inline int scx_tg_online(struct task_group *tg) { return 0; } | 82 | static inline int scx_tg_online(struct task_group *tg) { return 0; } |
| 83 | static inline void scx_tg_offline(struct task_group *tg) {} | 83 | static inline void scx_tg_offline(struct task_group *tg) {} |
| 84 | static inline int scx_cgroup_can_attach(struct cgroup_taskset *tset) { return 0; } | 84 | static inline int scx_cgroup_can_attach(struct cgroup_taskset *tset) { return 0; } |
| 85 | static inline void scx_move_task(struct task_struct *p) {} | 85 | static inline void scx_cgroup_move_task(struct task_struct *p) {} |
| 86 | static inline void scx_cgroup_finish_attach(void) {} | 86 | static inline void scx_cgroup_finish_attach(void) {} |
| 87 | static inline void scx_cgroup_cancel_attach(struct cgroup_taskset *tset) {} | 87 | static inline void scx_cgroup_cancel_attach(struct cgroup_taskset *tset) {} |
| 88 | static inline void scx_group_set_weight(struct task_group *tg, unsigned long cgrp_weight) {} | 88 | static inline void scx_group_set_weight(struct task_group *tg, unsigned long cgrp_weight) {} |
| @@ -5385,6 +5385,15 @@ static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq); · 5384 unmodified lines | |||
| 5385 | static void set_delayed(struct sched_entity *se) | 5385 | static void set_delayed(struct sched_entity *se) |
| 5386 | { | 5386 | { |
| 5387 | se->sched_delayed = 1; | 5387 | se->sched_delayed = 1; |
| 5388 | |||
| 5389 | /* | ||
| 5390 | * Delayed se of cfs_rq have no tasks queued on them. | ||
| 5391 | * Do not adjust h_nr_runnable since dequeue_entities() | ||
| 5392 | * will account it for blocked tasks. | ||
| 5393 | */ | ||
| 5394 | if (!entity_is_task(se)) | ||
| 5395 | return; | ||
| 5396 | |||
| 5388 | for_each_sched_entity(se) { | 5397 | for_each_sched_entity(se) { |
| 5389 | struct cfs_rq *cfs_rq = cfs_rq_of(se); | 5398 | struct cfs_rq *cfs_rq = cfs_rq_of(se); |
| 5390 | 5399 | ||
| @@ -5397,6 +5406,16 @@ static void set_delayed(struct sched_entity *se) · 6 unmodified lines | |||
| 5397 | static void clear_delayed(struct sched_entity *se) | 5406 | static void clear_delayed(struct sched_entity *se) |
| 5398 | { | 5407 | { |
| 5399 | se->sched_delayed = 0; | 5408 | se->sched_delayed = 0; |
| 5409 | |||
| 5410 | /* | ||
| 5411 | * Delayed se of cfs_rq have no tasks queued on them. | ||
| 5412 | * Do not adjust h_nr_runnable since a dequeue has | ||
| 5413 | * already accounted for it or an enqueue of a task | ||
| 5414 | * below it will account for it in enqueue_task_fair(). | ||
| 5415 | */ | ||
| 5416 | if (!entity_is_task(se)) | ||
| 5417 | return; | ||
| 5418 | |||
| 5400 | for_each_sched_entity(se) { | 5419 | for_each_sched_entity(se) { |
| 5401 | struct cfs_rq *cfs_rq = cfs_rq_of(se); | 5420 | struct cfs_rq *cfs_rq = cfs_rq_of(se); |
| 5402 | 5421 | ||
| @@ -572,7 +572,7 @@ extern void sched_online_group(struct task_group *tg, · 571 unmodified lines | |||
| 572 | extern void sched_destroy_group(struct task_group *tg); | 572 | extern void sched_destroy_group(struct task_group *tg); |
| 573 | extern void sched_release_group(struct task_group *tg); | 573 | extern void sched_release_group(struct task_group *tg); |
| 574 | 574 | ||
| 575 | extern void sched_move_task(struct task_struct *tsk); | 575 | extern void sched_move_task(struct task_struct *tsk, bool for_autogroup); |
| 576 | 576 | ||
| 577 | #ifdef CONFIG_FAIR_GROUP_SCHED | 577 | #ifdef CONFIG_FAIR_GROUP_SCHED |
| 578 | extern int sched_group_set_shares(struct task_group *tg, unsigned long shares); | 578 | extern int sched_group_set_shares(struct task_group *tg, unsigned long shares); |
| @@ -749,6 +749,15 @@ static bool seccomp_is_const_allow(struct sock_fprog_kern *fprog, · 748 unmodified lines | |||
| 749 | if (WARN_ON_ONCE(!fprog)) | 749 | if (WARN_ON_ONCE(!fprog)) |
| 750 | return false; | 750 | return false; |
| 751 | 751 | ||
| 752 | /* Our single exception to filtering. */ | ||
| 753 | #ifdef __NR_uretprobe | ||
| 754 | #ifdef SECCOMP_ARCH_COMPAT | ||
| 755 | if (sd->arch == SECCOMP_ARCH_NATIVE) | ||
| 756 | #endif | ||
| 757 | if (sd->nr == __NR_uretprobe) | ||
| 758 | return true; | ||
| 759 | #endif | ||
| 760 | |||
| 752 | for (pc = 0; pc < fprog->len; pc++) { | 761 | for (pc = 0; pc < fprog->len; pc++) { |
| 753 | struct sock_filter *insn = &fprog->filter[pc]; | 762 | struct sock_filter *insn = &fprog->filter[pc]; |
| 754 | u16 code = insn->code; | 763 | u16 code = insn->code; |
| @@ -1023,6 +1032,9 @@ static inline void seccomp_log(unsigned long syscall, long signr, u32 action, · 268 unmodified lines | |||
| 1023 | */ | 1032 | */ |
| 1024 | static const int mode1_syscalls[] = { | 1033 | static const int mode1_syscalls[] = { |
| 1025 | __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn, | 1034 | __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn, |
| 1035 | #ifdef __NR_uretprobe | ||
| 1036 | __NR_uretprobe, | ||
| 1037 | #endif | ||
| 1026 | -1, /* negative terminated */ | 1038 | -1, /* negative terminated */ |
| 1027 | }; | 1039 | }; |
| 1028 | 1040 | ||
| @@ -373,16 +373,18 @@ void clocksource_verify_percpu(struct clocksource *cs) · 372 unmodified lines | |||
| 373 | cpumask_clear(&cpus_ahead); | 373 | cpumask_clear(&cpus_ahead); |
| 374 | cpumask_clear(&cpus_behind); | 374 | cpumask_clear(&cpus_behind); |
| 375 | cpus_read_lock(); | 375 | cpus_read_lock(); |
| 376 | preempt_disable(); | 376 | migrate_disable(); |
| 377 | clocksource_verify_choose_cpus(); | 377 | clocksource_verify_choose_cpus(); |
| 378 | if (cpumask_empty(&cpus_chosen)) { | 378 | if (cpumask_empty(&cpus_chosen)) { |
| 379 | preempt_enable(); | 379 | migrate_enable(); |
| 380 | cpus_read_unlock(); | 380 | cpus_read_unlock(); |
| 381 | pr_warn("Not enough CPUs to check clocksource '%s'.\n", cs->name); | 381 | pr_warn("Not enough CPUs to check clocksource '%s'.\n", cs->name); |
| 382 | return; | 382 | return; |
| 383 | } | 383 | } |
| 384 | testcpu = smp_processor_id(); | 384 | testcpu = smp_processor_id(); |
| 385 | pr_warn("Checking clocksource %s synchronization from CPU %d to CPUs %*pbl.\n", cs->name, testcpu, cpumask_pr_args(&cpus_chosen)); | 385 | pr_info("Checking clocksource %s synchronization from CPU %d to CPUs %*pbl.\n", |
| 386 | cs->name, testcpu, cpumask_pr_args(&cpus_chosen)); | ||
| 387 | preempt_disable(); | ||
| 386 | for_each_cpu(cpu, &cpus_chosen) { | 388 | for_each_cpu(cpu, &cpus_chosen) { |
| 387 | if (cpu == testcpu) | 389 | if (cpu == testcpu) |
| 388 | continue; | 390 | continue; |
| @@ -402,6 +404,7 @@ void clocksource_verify_percpu(struct clocksource *cs) · 13 unmodified lines | |||
| 402 | cs_nsec_min = cs_nsec; | 404 | cs_nsec_min = cs_nsec; |
| 403 | } | 405 | } |
| 404 | preempt_enable(); | 406 | preempt_enable(); |
| 407 | migrate_enable(); | ||
| 405 | cpus_read_unlock(); | 408 | cpus_read_unlock(); |
| 406 | if (!cpumask_empty(&cpus_ahead)) | 409 | if (!cpumask_empty(&cpus_ahead)) |
| 407 | pr_warn(" CPUs %*pbl ahead of CPU %d for clocksource %s.\n", | 410 | pr_warn(" CPUs %*pbl ahead of CPU %d for clocksource %s.\n", |
| @@ -58,6 +58,8 @@ · 57 unmodified lines | |||
| 58 | #define HRTIMER_ACTIVE_SOFT (HRTIMER_ACTIVE_HARD << MASK_SHIFT) | 58 | #define HRTIMER_ACTIVE_SOFT (HRTIMER_ACTIVE_HARD << MASK_SHIFT) |
| 59 | #define HRTIMER_ACTIVE_ALL (HRTIMER_ACTIVE_SOFT | HRTIMER_ACTIVE_HARD) | 59 | #define HRTIMER_ACTIVE_ALL (HRTIMER_ACTIVE_SOFT | HRTIMER_ACTIVE_HARD) |
| 60 | 60 | ||
| 61 | static void retrigger_next_event(void *arg); | ||
| 62 | |||
| 61 | /* | 63 | /* |
| 62 | * The timer bases: | 64 | * The timer bases: |
| 63 | * | 65 | * |
| @@ -111,7 +113,8 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = · 47 unmodified lines | |||
| 111 | .clockid = CLOCK_TAI, | 113 | .clockid = CLOCK_TAI, |
| 112 | .get_time = &ktime_get_clocktai, | 114 | .get_time = &ktime_get_clocktai, |
| 113 | }, | 115 | }, |
| 114 | } | 116 | }, |
| 117 | .csd = CSD_INIT(retrigger_next_event, NULL) | ||
| 115 | }; | 118 | }; |
| 116 | 119 | ||
| 117 | static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { | 120 | static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { |
| @@ -124,6 +127,14 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { · 6 unmodified lines | |||
| 124 | [CLOCK_TAI] = HRTIMER_BASE_TAI, | 127 | [CLOCK_TAI] = HRTIMER_BASE_TAI, |
| 125 | }; | 128 | }; |
| 126 | 129 | ||
| 130 | static inline bool hrtimer_base_is_online(struct hrtimer_cpu_base *base) | ||
| 131 | { | ||
| 132 | if (!IS_ENABLED(CONFIG_HOTPLUG_CPU)) | ||
| 133 | return true; | ||
| 134 | else | ||
| 135 | return likely(base->online); | ||
| 136 | } | ||
| 137 | |||
| 127 | /* | 138 | /* |
| 128 | * Functions and macros which are different for UP/SMP systems are kept in a | 139 | * Functions and macros which are different for UP/SMP systems are kept in a |
| 129 | * single place | 140 | * single place |
| @@ -145,11 +156,6 @@ static struct hrtimer_cpu_base migration_cpu_base = { · 15 unmodified lines | |||
| 145 | 156 | ||
| 146 | #define migration_base migration_cpu_base.clock_base[0] | 157 | #define migration_base migration_cpu_base.clock_base[0] |
| 147 | 158 | ||
| 148 | static inline bool is_migration_base(struct hrtimer_clock_base *base) | ||
| 149 | { | ||
| 150 | return base == &migration_base; | ||
| 151 | } | ||
| 152 | |||
| 153 | /* | 159 | /* |
| 154 | * We are using hashed locking: holding per_cpu(hrtimer_bases)[n].lock | 160 | * We are using hashed locking: holding per_cpu(hrtimer_bases)[n].lock |
| 155 | * means that all timers which are tied to this base via timer->base are | 161 | * means that all timers which are tied to this base via timer->base are |
| @@ -183,27 +189,54 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer, · 27 unmodified lines | |||
| 183 | } | 189 | } |
| 184 | 190 | ||
| 185 | /* | 191 | /* |
| 186 | * We do not migrate the timer when it is expiring before the next | 192 | * Check if the elected target is suitable considering its next |
| 187 | * event on the target cpu. When high resolution is enabled, we cannot | 193 | * event and the hotplug state of the current CPU. |
| 188 | * reprogram the target cpu hardware and we would cause it to fire | 194 | * |
| 189 | * late. To keep it simple, we handle the high resolution enabled and | 195 | * If the elected target is remote and its next event is after the timer |
| 190 | * disabled case similar. | 196 | * to queue, then a remote reprogram is necessary. However there is no |
| 197 | * guarantee the IPI handling the operation would arrive in time to meet | ||
| 198 | * the high resolution deadline. In this case the local CPU becomes a | ||
| 199 | * preferred target, unless it is offline. | ||
| 200 | * | ||
| 201 | * High and low resolution modes are handled the same way for simplicity. | ||
| 191 | * | 202 | * |
| 192 | * Called with cpu_base->lock of target cpu held. | 203 | * Called with cpu_base->lock of target cpu held. |
| 193 | */ | 204 | */ |
| 194 | static int | 205 | static bool hrtimer_suitable_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base, |
| 195 | hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base) | 206 | struct hrtimer_cpu_base *new_cpu_base, |
| 207 | struct hrtimer_cpu_base *this_cpu_base) | ||
| 196 | { | 208 | { |
| 197 | ktime_t expires; | 209 | ktime_t expires; |
| 198 | 210 | ||
| 211 | /* | ||
| 212 | * The local CPU clockevent can be reprogrammed. Also get_target_base() | ||
| 213 | * guarantees it is online. | ||
| 214 | */ | ||
| 215 | if (new_cpu_base == this_cpu_base) | ||
| 216 | return true; | ||
| 217 | |||
| 218 | /* | ||
| 219 | * The offline local CPU can't be the default target if the | ||
| 220 | * next remote target event is after this timer. Keep the | ||
| 221 | * elected new base. An IPI will we issued to reprogram | ||
| 222 | * it as a last resort. | ||
| 223 | */ | ||
| 224 | if (!hrtimer_base_is_online(this_cpu_base)) | ||
| 225 | return true; | ||
| 226 | |||
| 199 | expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset); | 227 | expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset); |
| 200 | return expires < new_base->cpu_base->expires_next; | 228 | |
| 229 | return expires >= new_base->cpu_base->expires_next; | ||
| 201 | } | 230 | } |
| 202 | 231 | ||
| 203 | static inline | 232 | static inline struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base, int pinned) |
| 204 | struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base, | ||
| 205 | int pinned) | ||
| 206 | { | 233 | { |
| 234 | if (!hrtimer_base_is_online(base)) { | ||
| 235 | int cpu = cpumask_any_and(cpu_online_mask, housekeeping_cpumask(HK_TYPE_TIMER)); | ||
| 236 | |||
| 237 | return &per_cpu(hrtimer_bases, cpu); | ||
| 238 | } | ||
| 239 | |||
| 207 | #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON) | 240 | #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON) |
| 208 | if (static_branch_likely(&timers_migration_enabled) && !pinned) | 241 | if (static_branch_likely(&timers_migration_enabled) && !pinned) |
| 209 | return &per_cpu(hrtimer_bases, get_nohz_timer_target()); | 242 | return &per_cpu(hrtimer_bases, get_nohz_timer_target()); |
| @@ -254,8 +287,8 @@ again: · 44 unmodified lines | |||
| 254 | raw_spin_unlock(&base->cpu_base->lock); | 287 | raw_spin_unlock(&base->cpu_base->lock); |
| 255 | raw_spin_lock(&new_base->cpu_base->lock); | 288 | raw_spin_lock(&new_base->cpu_base->lock); |
| 256 | 289 | ||
| 257 | if (new_cpu_base != this_cpu_base && | 290 | if (!hrtimer_suitable_target(timer, new_base, new_cpu_base, |
| 258 | hrtimer_check_target(timer, new_base)) { | 291 | this_cpu_base)) { |
| 259 | raw_spin_unlock(&new_base->cpu_base->lock); | 292 | raw_spin_unlock(&new_base->cpu_base->lock); |
| 260 | raw_spin_lock(&base->cpu_base->lock); | 293 | raw_spin_lock(&base->cpu_base->lock); |
| 261 | new_cpu_base = this_cpu_base; | 294 | new_cpu_base = this_cpu_base; |
| @@ -264,8 +297,7 @@ again: · 2 unmodified lines | |||
| 264 | } | 297 | } |
| 265 | WRITE_ONCE(timer->base, new_base); | 298 | WRITE_ONCE(timer->base, new_base); |
| 266 | } else { | 299 | } else { |
| 267 | if (new_cpu_base != this_cpu_base && | 300 | if (!hrtimer_suitable_target(timer, new_base, new_cpu_base, this_cpu_base)) { |
| 268 | hrtimer_check_target(timer, new_base)) { | ||
| 269 | new_cpu_base = this_cpu_base; | 301 | new_cpu_base = this_cpu_base; |
| 270 | goto again; | 302 | goto again; |
| 271 | } | 303 | } |
| @@ -275,11 +307,6 @@ again: · 3 unmodified lines | |||
| 275 | 307 | ||
| 276 | #else /* CONFIG_SMP */ | 308 | #else /* CONFIG_SMP */ |
| 277 | 309 | ||
| 278 | static inline bool is_migration_base(struct hrtimer_clock_base *base) | ||
| 279 | { | ||
| 280 | return false; | ||
| 281 | } | ||
| 282 | |||
| 283 | static inline struct hrtimer_clock_base * | 310 | static inline struct hrtimer_clock_base * |
| 284 | lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags) | 311 | lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags) |
| 285 | __acquires(&timer->base->cpu_base->lock) | 312 | __acquires(&timer->base->cpu_base->lock) |
| @@ -716,8 +743,6 @@ static inline int hrtimer_is_hres_enabled(void) · 430 unmodified lines | |||
| 716 | return hrtimer_hres_enabled; | 743 | return hrtimer_hres_enabled; |
| 717 | } | 744 | } |
| 718 | 745 | ||
| 719 | static void retrigger_next_event(void *arg); | ||
| 720 | |||
| 721 | /* | 746 | /* |
| 722 | * Switch to high resolution mode | 747 | * Switch to high resolution mode |
| 723 | */ | 748 | */ |
| @@ -1205,6 +1230,7 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, · 481 unmodified lines | |||
| 1205 | u64 delta_ns, const enum hrtimer_mode mode, | 1230 | u64 delta_ns, const enum hrtimer_mode mode, |
| 1206 | struct hrtimer_clock_base *base) | 1231 | struct hrtimer_clock_base *base) |
| 1207 | { | 1232 | { |
| 1233 | struct hrtimer_cpu_base *this_cpu_base = this_cpu_ptr(&hrtimer_bases); | ||
| 1208 | struct hrtimer_clock_base *new_base; | 1234 | struct hrtimer_clock_base *new_base; |
| 1209 | bool force_local, first; | 1235 | bool force_local, first; |
| 1210 | 1236 | ||
| @@ -1216,9 +1242,15 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, · 5 unmodified lines | |||
| 1216 | * and enforce reprogramming after it is queued no matter whether | 1242 | * and enforce reprogramming after it is queued no matter whether |
| 1217 | * it is the new first expiring timer again or not. | 1243 | * it is the new first expiring timer again or not. |
| 1218 | */ | 1244 | */ |
| 1219 | force_local = base->cpu_base == this_cpu_ptr(&hrtimer_bases); | 1245 | force_local = base->cpu_base == this_cpu_base; |
| 1220 | force_local &= base->cpu_base->next_timer == timer; | 1246 | force_local &= base->cpu_base->next_timer == timer; |
| 1221 | 1247 | ||
| 1248 | /* | ||
| 1249 | * Don't force local queuing if this enqueue happens on a unplugged | ||
| 1250 | * CPU after hrtimer_cpu_dying() has been invoked. | ||
| 1251 | */ | ||
| 1252 | force_local &= this_cpu_base->online; | ||
| 1253 | |||
| 1222 | /* | 1254 | /* |
| 1223 | * Remove an active timer from the queue. In case it is not queued | 1255 | * Remove an active timer from the queue. In case it is not queued |
| 1224 | * on the current CPU, make sure that remove_hrtimer() updates the | 1256 | * on the current CPU, make sure that remove_hrtimer() updates the |
| @@ -1248,8 +1280,27 @@ static int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, · 23 unmodified lines | |||
| 1248 | } | 1280 | } |
| 1249 | 1281 | ||
| 1250 | first = enqueue_hrtimer(timer, new_base, mode); | 1282 | first = enqueue_hrtimer(timer, new_base, mode); |
| 1251 | if (!force_local) | 1283 | if (!force_local) { |
| 1252 | return first; | 1284 | /* |
| 1285 | * If the current CPU base is online, then the timer is | ||
| 1286 | * never queued on a remote CPU if it would be the first | ||
| 1287 | * expiring timer there. | ||
| 1288 | */ | ||
| 1289 | if (hrtimer_base_is_online(this_cpu_base)) | ||
| 1290 | return first; | ||
| 1291 | |||
| 1292 | /* | ||
| 1293 | * Timer was enqueued remote because the current base is | ||
| 1294 | * already offline. If the timer is the first to expire, | ||
| 1295 | * kick the remote CPU to reprogram the clock event. | ||
| 1296 | */ | ||
| 1297 | if (first) { | ||
| 1298 | struct hrtimer_cpu_base *new_cpu_base = new_base->cpu_base; | ||
| 1299 | |||
| 1300 | smp_call_function_single_async(new_cpu_base->cpu, &new_cpu_base->csd); | ||
| 1301 | } | ||
| 1302 | return 0; | ||
| 1303 | } | ||
| 1253 | 1304 | ||
| 1254 | /* | 1305 | /* |
| 1255 | * Timer was forced to stay on the current CPU to avoid | 1306 | * Timer was forced to stay on the current CPU to avoid |
| @@ -1370,6 +1421,18 @@ static void hrtimer_sync_wait_running(struct hrtimer_cpu_base *cpu_base, · 114 unmodified lines | |||
| 1370 | } | 1421 | } |
| 1371 | } | 1422 | } |
| 1372 | 1423 | ||
| 1424 | #ifdef CONFIG_SMP | ||
| 1425 | static __always_inline bool is_migration_base(struct hrtimer_clock_base *base) | ||
| 1426 | { | ||
| 1427 | return base == &migration_base; | ||
| 1428 | } | ||
| 1429 | #else | ||
| 1430 | static __always_inline bool is_migration_base(struct hrtimer_clock_base *base) | ||
| 1431 | { | ||
| 1432 | return false; | ||
| 1433 | } | ||
| 1434 | #endif | ||
| 1435 | |||
| 1373 | /* | 1436 | /* |
| 1374 | * This function is called on PREEMPT_RT kernels when the fast path | 1437 | * This function is called on PREEMPT_RT kernels when the fast path |
| 1375 | * deletion of a timer failed because the timer callback function was | 1438 | * deletion of a timer failed because the timer callback function was |
| @@ -1675,6 +1675,9 @@ static int tmigr_setup_groups(unsigned int cpu, unsigned int node) · 1674 unmodified lines | |||
| 1675 | 1675 | ||
| 1676 | } while (i < tmigr_hierarchy_levels); | 1676 | } while (i < tmigr_hierarchy_levels); |
| 1677 | 1677 | ||
| 1678 | /* Assert single root */ | ||
| 1679 | WARN_ON_ONCE(!err && !group->parent && !list_is_singular(&tmigr_level_list[top])); | ||
| 1680 | |||
| 1678 | while (i > 0) { | 1681 | while (i > 0) { |
| 1679 | group = stack[--i]; | 1682 | group = stack[--i]; |
| 1680 | 1683 | ||
| @@ -1716,7 +1719,12 @@ static int tmigr_setup_groups(unsigned int cpu, unsigned int node) · 35 unmodified lines | |||
| 1716 | WARN_ON_ONCE(top == 0); | 1719 | WARN_ON_ONCE(top == 0); |
| 1717 | 1720 | ||
| 1718 | lvllist = &tmigr_level_list[top]; | 1721 | lvllist = &tmigr_level_list[top]; |
| 1719 | if (group->num_children == 1 && list_is_singular(lvllist)) { | 1722 | |
| 1723 | /* | ||
| 1724 | * Newly created root level should have accounted the upcoming | ||
| 1725 | * CPU's child group and pre-accounted the old root. | ||
| 1726 | */ | ||
| 1727 | if (group->num_children == 2 && list_is_singular(lvllist)) { | ||
| 1720 | /* | 1728 | /* |
| 1721 | * The target CPU must never do the prepare work, except | 1729 | * The target CPU must never do the prepare work, except |
| 1722 | * on early boot when the boot CPU is the target. Otherwise | 1730 | * on early boot when the boot CPU is the target. Otherwise |
| @@ -1672,7 +1672,8 @@ static void *rb_range_buffer(struct ring_buffer_per_cpu *cpu_buffer, int idx) · 1671 unmodified lines | |||
| 1672 | * must be the same. | 1672 | * must be the same. |
| 1673 | */ | 1673 | */ |
| 1674 | static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, | 1674 | static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, |
| 1675 | struct trace_buffer *buffer, int nr_pages) | 1675 | struct trace_buffer *buffer, int nr_pages, |
| 1676 | unsigned long *subbuf_mask) | ||
| 1676 | { | 1677 | { |
| 1677 | int subbuf_size = PAGE_SIZE; | 1678 | int subbuf_size = PAGE_SIZE; |
| 1678 | struct buffer_data_page *subbuf; | 1679 | struct buffer_data_page *subbuf; |
| @@ -1680,6 +1681,9 @@ static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, · 1 unmodified line | |||
| 1680 | unsigned long buffers_end; | 1681 | unsigned long buffers_end; |
| 1681 | int i; | 1682 | int i; |
| 1682 | 1683 | ||
| 1684 | if (!subbuf_mask) | ||
| 1685 | return false; | ||
| 1686 | |||
| 1683 | /* Check the meta magic and meta struct size */ | 1687 | /* Check the meta magic and meta struct size */ |
| 1684 | if (meta->magic != RING_BUFFER_META_MAGIC || | 1688 | if (meta->magic != RING_BUFFER_META_MAGIC || |
| 1685 | meta->struct_size != sizeof(*meta)) { | 1689 | meta->struct_size != sizeof(*meta)) { |
| @@ -1712,6 +1716,8 @@ static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, · 26 unmodified lines | |||
| 1712 | 1716 | ||
| 1713 | subbuf = rb_subbufs_from_meta(meta); | 1717 | subbuf = rb_subbufs_from_meta(meta); |
| 1714 | 1718 | ||
| 1719 | bitmap_clear(subbuf_mask, 0, meta->nr_subbufs); | ||
| 1720 | |||
| 1715 | /* Is the meta buffers and the subbufs themselves have correct data? */ | 1721 | /* Is the meta buffers and the subbufs themselves have correct data? */ |
| 1716 | for (i = 0; i < meta->nr_subbufs; i++) { | 1722 | for (i = 0; i < meta->nr_subbufs; i++) { |
| 1717 | if (meta->buffers[i] < 0 || | 1723 | if (meta->buffers[i] < 0 || |
| @@ -1725,6 +1731,12 @@ static bool rb_meta_valid(struct ring_buffer_meta *meta, int cpu, · 7 unmodified lines | |||
| 1725 | return false; | 1731 | return false; |
| 1726 | } | 1732 | } |
| 1727 | 1733 | ||
| 1734 | if (test_bit(meta->buffers[i], subbuf_mask)) { | ||
| 1735 | pr_info("Ring buffer boot meta [%d] array has duplicates\n", cpu); | ||
| 1736 | return false; | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | set_bit(meta->buffers[i], subbuf_mask); | ||
| 1728 | subbuf = (void *)subbuf + subbuf_size; | 1740 | subbuf = (void *)subbuf + subbuf_size; |
| 1729 | } | 1741 | } |
| 1730 | 1742 | ||
| @@ -1838,6 +1850,11 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) · 107 unmodified lines | |||
| 1838 | cpu_buffer->cpu); | 1850 | cpu_buffer->cpu); |
| 1839 | goto invalid; | 1851 | goto invalid; |
| 1840 | } | 1852 | } |
| 1853 | |||
| 1854 | /* If the buffer has content, update pages_touched */ | ||
| 1855 | if (ret) | ||
| 1856 | local_inc(&cpu_buffer->pages_touched); | ||
| 1857 | |||
| 1841 | entries += ret; | 1858 | entries += ret; |
| 1842 | entry_bytes += local_read(&head_page->page->commit); | 1859 | entry_bytes += local_read(&head_page->page->commit); |
| 1843 | local_set(&cpu_buffer->head_page->entries, ret); | 1860 | local_set(&cpu_buffer->head_page->entries, ret); |
| @@ -1889,17 +1906,22 @@ static void rb_meta_init_text_addr(struct ring_buffer_meta *meta) · 45 unmodified lines | |||
| 1889 | static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) | 1906 | static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) |
| 1890 | { | 1907 | { |
| 1891 | struct ring_buffer_meta *meta; | 1908 | struct ring_buffer_meta *meta; |
| 1909 | unsigned long *subbuf_mask; | ||
| 1892 | unsigned long delta; | 1910 | unsigned long delta; |
| 1893 | void *subbuf; | 1911 | void *subbuf; |
| 1894 | int cpu; | 1912 | int cpu; |
| 1895 | int i; | 1913 | int i; |
| 1896 | 1914 | ||
| 1915 | /* Create a mask to test the subbuf array */ | ||
| 1916 | subbuf_mask = bitmap_alloc(nr_pages + 1, GFP_KERNEL); | ||
| 1917 | /* If subbuf_mask fails to allocate, then rb_meta_valid() will return false */ | ||
| 1918 | |||
| 1897 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) { | 1919 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) { |
| 1898 | void *next_meta; | 1920 | void *next_meta; |
| 1899 | 1921 | ||
| 1900 | meta = rb_range_meta(buffer, nr_pages, cpu); | 1922 | meta = rb_range_meta(buffer, nr_pages, cpu); |
| 1901 | 1923 | ||
| 1902 | if (rb_meta_valid(meta, cpu, buffer, nr_pages)) { | 1924 | if (rb_meta_valid(meta, cpu, buffer, nr_pages, subbuf_mask)) { |
| 1903 | /* Make the mappings match the current address */ | 1925 | /* Make the mappings match the current address */ |
| 1904 | subbuf = rb_subbufs_from_meta(meta); | 1926 | subbuf = rb_subbufs_from_meta(meta); |
| 1905 | delta = (unsigned long)subbuf - meta->first_buffer; | 1927 | delta = (unsigned long)subbuf - meta->first_buffer; |
| @@ -1943,6 +1965,7 @@ static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) · 37 unmodified lines | |||
| 1943 | subbuf += meta->subbuf_size; | 1965 | subbuf += meta->subbuf_size; |
| 1944 | } | 1966 | } |
| 1945 | } | 1967 | } |
| 1968 | bitmap_free(subbuf_mask); | ||
| 1946 | } | 1969 | } |
| 1947 | 1970 | ||
| 1948 | static void *rbm_start(struct seq_file *m, loff_t *pos) | 1971 | static void *rbm_start(struct seq_file *m, loff_t *pos) |
| @@ -7126,6 +7149,7 @@ int ring_buffer_map(struct trace_buffer *buffer, int cpu, · 5177 unmodified lines | |||
| 7126 | kfree(cpu_buffer->subbuf_ids); | 7149 | kfree(cpu_buffer->subbuf_ids); |
| 7127 | cpu_buffer->subbuf_ids = NULL; | 7150 | cpu_buffer->subbuf_ids = NULL; |
| 7128 | rb_free_meta_page(cpu_buffer); | 7151 | rb_free_meta_page(cpu_buffer); |
| 7152 | atomic_dec(&cpu_buffer->resize_disabled); | ||
| 7129 | } | 7153 | } |
| 7130 | 7154 | ||
| 7131 | unlock: | 7155 | unlock: |
| @@ -5977,8 +5977,6 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr, · 5976 unmodified lines | |||
| 5977 | ssize_t tracing_resize_ring_buffer(struct trace_array *tr, | 5977 | ssize_t tracing_resize_ring_buffer(struct trace_array *tr, |
| 5978 | unsigned long size, int cpu_id) | 5978 | unsigned long size, int cpu_id) |
| 5979 | { | 5979 | { |
| 5980 | int ret; | ||
| 5981 | |||
| 5982 | guard(mutex)(&trace_types_lock); | 5980 | guard(mutex)(&trace_types_lock); |
| 5983 | 5981 | ||
| 5984 | if (cpu_id != RING_BUFFER_ALL_CPUS) { | 5982 | if (cpu_id != RING_BUFFER_ALL_CPUS) { |
| @@ -5987,11 +5985,7 @@ ssize_t tracing_resize_ring_buffer(struct trace_array *tr, · 2 unmodified lines | |||
| 5987 | return -EINVAL; | 5985 | return -EINVAL; |
| 5988 | } | 5986 | } |
| 5989 | 5987 | ||
| 5990 | ret = __tracing_resize_ring_buffer(tr, size, cpu_id); | 5988 | return __tracing_resize_ring_buffer(tr, size, cpu_id); |
| 5991 | if (ret < 0) | ||
| 5992 | ret = -ENOMEM; | ||
| 5993 | |||
| 5994 | return ret; | ||
| 5995 | } | 5989 | } |
| 5996 | 5990 | ||
| 5997 | static void update_last_data(struct trace_array *tr) | 5991 | static void update_last_data(struct trace_array *tr) |
| @@ -8285,6 +8279,10 @@ static int tracing_buffers_mmap(struct file *filp, struct vm_area_struct *vma) · 2287 unmodified lines | |||
| 8285 | struct trace_iterator *iter = &info->iter; | 8279 | struct trace_iterator *iter = &info->iter; |
| 8286 | int ret = 0; | 8280 | int ret = 0; |
| 8287 | 8281 | ||
| 8282 | /* Currently the boot mapped buffer is not supported for mmap */ | ||
| 8283 | if (iter->tr->flags & TRACE_ARRAY_FL_BOOT) | ||
| 8284 | return -ENODEV; | ||
| 8285 | |||
| 8288 | ret = get_snapshot_map(iter->tr); | 8286 | ret = get_snapshot_map(iter->tr); |
| 8289 | if (ret) | 8287 | if (ret) |
| 8290 | return ret; | 8288 | return ret; |
| @@ -198,7 +198,7 @@ int trace_graph_entry(struct ftrace_graph_ent *trace, · 197 unmodified lines | |||
| 198 | * returning from the function. | 198 | * returning from the function. |
| 199 | */ | 199 | */ |
| 200 | if (ftrace_graph_notrace_addr(trace->func)) { | 200 | if (ftrace_graph_notrace_addr(trace->func)) { |
| 201 | *task_var |= TRACE_GRAPH_NOTRACE_BIT; | 201 | *task_var |= TRACE_GRAPH_NOTRACE; |
| 202 | /* | 202 | /* |
| 203 | * Need to return 1 to have the return called | 203 | * Need to return 1 to have the return called |
| 204 | * that will clear the NOTRACE bit. | 204 | * that will clear the NOTRACE bit. |
| @@ -3516,12 +3516,6 @@ repeat: · 3515 unmodified lines | |||
| 3516 | } | 3516 | } |
| 3517 | } | 3517 | } |
| 3518 | 3518 | ||
| 3519 | /* | ||
| 3520 | * Put the reference grabbed by send_mayday(). @pool won't | ||
| 3521 | * go away while we're still attached to it. | ||
| 3522 | */ | ||
| 3523 | put_pwq(pwq); | ||
| 3524 | |||
| 3525 | /* | 3519 | /* |
| 3526 | * Leave this pool. Notify regular workers; otherwise, we end up | 3520 | * Leave this pool. Notify regular workers; otherwise, we end up |
| 3527 | * with 0 concurrency and stalling the execution. | 3521 | * with 0 concurrency and stalling the execution. |
| @@ -3532,6 +3526,12 @@ repeat: · 4 unmodified lines | |||
| 3532 | 3526 | ||
| 3533 | worker_detach_from_pool(rescuer); | 3527 | worker_detach_from_pool(rescuer); |
10 more lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 246 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 538 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 195 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 129 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 169 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 117 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 160 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 138 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 168 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 183 lines aren’t shown here.
This diff is large: its 455 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 220 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.