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 | 226 | Felipe W Damasio <felipewd@terra.com.br> |
| 227 | 227 | Felix Kuhling <fxkuehl@gmx.de> |
| 228 | 228 | Felix Moeller <felix@derklecks.de> |
| 229 | +Feng Tang <feng.79.tang@gmail.com> <feng.tang@intel.com> | |
| 229 | 230 | Fenglin Wu <quic_fenglinw@quicinc.com> <fenglinw@codeaurora.org> |
| 230 | 231 | Filipe Lautert <filipe@icewall.org> |
| 231 | 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 | 318 | Jean Tourrilhes <jt@hpl.hp.com> |
| 318 | 319 | Jeevan Shriram <quic_jshriram@quicinc.com> <jshriram@codeaurora.org> |
| 319 | 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 | 323 | Jeff Layton <jlayton@kernel.org> <jlayton@poochiereds.net> |
| 321 | 324 | Jeff Layton <jlayton@kernel.org> <jlayton@primarydata.com> |
| 322 | 325 | Jeff Layton <jlayton@kernel.org> <jlayton@redhat.com> |
| @@ -376,6 +379,7 @@ Juha Yrjola <juha.yrjola@solidboot.com> · 53 unmodified lines | ||
| 376 | 379 | Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com> |
| 377 | 380 | Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com> |
| 378 | 381 | Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org> |
| 382 | +Kalle Valo <kvalo@kernel.org> <quic_kvalo@quicinc.com> | |
| 379 | 383 | Kalyan Thota <quic_kalyant@quicinc.com> <kalyan_t@codeaurora.org> |
| 380 | 384 | Karthikeyan Periyasamy <quic_periyasa@quicinc.com> <periyasa@codeaurora.org> |
| 381 | 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 | 534 | Nicholas Piggin <npiggin@gmail.com> <npiggin@suse.de> |
| 531 | 535 | Nicholas Piggin <npiggin@gmail.com> <nickpiggin@yahoo.com.au> |
| 532 | 536 | Nicholas Piggin <npiggin@gmail.com> <piggin@cyberone.com.au> |
| 537 | +Nick Desaulniers <nick.desaulniers+lkml@gmail.com> <ndesaulniers@google.com> | |
| 533 | 538 | Nicolas Ferre <nicolas.ferre@microchip.com> <nicolas.ferre@atmel.com> |
| 534 | 539 | Nicolas Pitre <nico@fluxnic.net> <nicolas.pitre@linaro.org> |
| 535 | 540 | Nicolas Pitre <nico@fluxnic.net> <nico@linaro.org> |
| @@ -2515,11 +2515,9 @@ D: SLS distribution · 2514 unmodified lines | ||
| 2515 | 2515 | D: Initial implementation of VC's, pty's and select() |
| 2516 | 2516 | |
| 2517 | 2517 | N: Pavel Machek |
| 2518 | −E: pavel@ucw.cz | |
| 2518 | +E: pavel@kernel.org | |
| 2519 | 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, | |
| 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, | |
| 2520 | +D: NBD, Sun4/330 port, USB, work on suspend-to-ram/disk, | |
| 2523 | 2521 | D: Altera SoCFPGA and Nokia N900 support. |
| 2524 | 2522 | S: Czech Republic |
| 2525 | 2523 | |
| @@ -37,7 +37,7 @@ intended to be exhaustive. · 36 unmodified lines | ||
| 37 | 37 | shadow stacks rather than GCS. |
| 38 | 38 | |
| 39 | 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 | 42 | * GCS is enabled per thread. While there is support for disabling GCS |
| 43 | 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 | 9 | maintainers: |
| 10 | 10 | - Taniya Das <quic_tdas@quicinc.com> |
| 11 | + - Imran Shaik <quic_imrashai@quicinc.com> | |
| 11 | 12 | |
| 12 | 13 | description: | |
| 13 | 14 | Qualcomm graphics clock control module provides the clocks, resets and power |
| @@ -23,10 +24,12 @@ description: | · 9 unmodified lines | ||
| 23 | 24 | include/dt-bindings/clock/qcom,gpucc-sm8150.h |
| 24 | 25 | include/dt-bindings/clock/qcom,gpucc-sm8250.h |
| 25 | 26 | include/dt-bindings/clock/qcom,gpucc-sm8350.h |
| 27 | + include/dt-bindings/clock/qcom,qcs8300-gpucc.h | |
| 26 | 28 | |
| 27 | 29 | properties: |
| 28 | 30 | compatible: |
| 29 | 31 | enum: |
| 32 | + - qcom,qcs8300-gpucc | |
| 30 | 33 | - qcom,sdm845-gpucc |
| 31 | 34 | - qcom,sa8775p-gpucc |
| 32 | 35 | - qcom,sc7180-gpucc |
| @@ -8,16 +8,20 @@ title: Qualcomm Camera Clock & Reset Controller on SA8775P · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | maintainers: |
| 10 | 10 | - Taniya Das <quic_tdas@quicinc.com> |
| 11 | + - Imran Shaik <quic_imrashai@quicinc.com> | |
| 11 | 12 | |
| 12 | 13 | description: | |
| 13 | 14 | Qualcomm camera clock control module provides the clocks, resets and power |
| 14 | 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 | 21 | properties: |
| 19 | 22 | compatible: |
| 20 | 23 | enum: |
| 24 | + - qcom,qcs8300-camcc | |
| 21 | 25 | - qcom,sa8775p-camcc |
| 22 | 26 | |
| 23 | 27 | clocks: |
| @@ -18,6 +18,7 @@ description: | · 17 unmodified lines | ||
| 18 | 18 | properties: |
| 19 | 19 | compatible: |
| 20 | 20 | enum: |
| 21 | + - qcom,qcs8300-videocc | |
| 21 | 22 | - qcom,sa8775p-videocc |
| 22 | 23 | |
| 23 | 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 | 23 | compatible: |
| 24 | 24 | enum: |
| 25 | 25 | - ti,am625-dss |
| 26 | − - ti,am62a7,dss | |
| 26 | + - ti,am62a7-dss | |
| 27 | 27 | - ti,am65x-dss |
| 28 | 28 | |
| 29 | 29 | reg: |
| @@ -14,9 +14,8 @@ allOf: · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | description: | |
| 16 | 16 | The Microchip LAN966x outband interrupt controller (OIC) maps the internal |
| 17 | − interrupt sources of the LAN966x device to an external interrupt. | |
| 18 | − When the LAN966x device is used as a PCI device, the external interrupt is | |
| 19 | − routed to the PCI interrupt. | |
| 17 | + interrupt sources of the LAN966x device to a PCI interrupt when the LAN966x | |
| 18 | + device is used as a PCI device. | |
| 20 | 19 | |
| 21 | 20 | properties: |
| 22 | 21 | compatible: |
| @@ -7,7 +7,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | ||
| 7 | 7 | title: Qualcomm Technologies ath10k wireless devices |
| 8 | 8 | |
| 9 | 9 | maintainers: |
| 10 | − - Kalle Valo <kvalo@kernel.org> | |
| 11 | 10 | - Jeff Johnson <jjohnson@kernel.org> |
| 12 | 11 | |
| 13 | 12 | description: |
| @@ -8,7 +8,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 7 unmodified lines | ||
| 8 | 8 | title: Qualcomm Technologies ath11k wireless devices (PCIe) |
| 9 | 9 | |
| 10 | 10 | maintainers: |
| 11 | − - Kalle Valo <kvalo@kernel.org> | |
| 12 | 11 | - Jeff Johnson <jjohnson@kernel.org> |
| 13 | 12 | |
| 14 | 13 | description: | |
| @@ -8,7 +8,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 7 unmodified lines | ||
| 8 | 8 | title: Qualcomm Technologies ath11k wireless devices |
| 9 | 9 | |
| 10 | 10 | maintainers: |
| 11 | − - Kalle Valo <kvalo@kernel.org> | |
| 12 | 11 | - Jeff Johnson <jjohnson@kernel.org> |
| 13 | 12 | |
| 14 | 13 | description: | |
| @@ -9,7 +9,6 @@ title: Qualcomm Technologies ath12k wireless devices (PCIe) with WSI interface · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | maintainers: |
| 11 | 11 | - Jeff Johnson <jjohnson@kernel.org> |
| 12 | − - Kalle Valo <kvalo@kernel.org> | |
| 13 | 12 | |
| 14 | 13 | description: | |
| 15 | 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 | 10 | maintainers: |
| 11 | 11 | - Jeff Johnson <quic_jjohnson@quicinc.com> |
| 12 | − - Kalle Valo <kvalo@kernel.org> | |
| 13 | 12 | |
| 14 | 13 | description: |
| 15 | 14 | Qualcomm Technologies IEEE 802.11be PCIe devices. |
| @@ -36,6 +36,7 @@ properties: · 35 unmodified lines | ||
| 36 | 36 | - qcom,qcs404-qfprom |
| 37 | 37 | - qcom,qcs615-qfprom |
| 38 | 38 | - qcom,qcs8300-qfprom |
| 39 | + - qcom,sar2130p-qfprom | |
| 39 | 40 | - qcom,sc7180-qfprom |
| 40 | 41 | - qcom,sc7280-qfprom |
| 41 | 42 | - qcom,sc8280xp-qfprom |
| @@ -22,7 +22,7 @@ description: · 21 unmodified lines | ||
| 22 | 22 | Each sub-node is identified using the node's name, with valid values listed |
| 23 | 23 | for each of the pmics below. |
| 24 | 24 | |
| 25 | − For mp5496, s1, s2 | |
| 25 | + For mp5496, s1, s2, l2, l5 | |
| 26 | 26 | |
| 27 | 27 | For pm2250, s1, s2, s3, s4, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, |
| 28 | 28 | l12, l13, l14, l15, l16, l17, l18, l19, l20, l21, l22 |
| @@ -41,6 +41,12 @@ Device Drivers Base · 40 unmodified lines | ||
| 41 | 41 | .. kernel-doc:: drivers/base/class.c |
| 42 | 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 | 50 | .. kernel-doc:: drivers/base/node.c |
| 45 | 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 | 9 | :numbered: |
| 10 | 10 | |
| 11 | 11 | CodingStyle |
| 12 | + SubmittingPatches | |
| 12 | 13 | errorcodes |
| @@ -1524,7 +1524,8 @@ attribute-sets: · 1523 unmodified lines | ||
| 1524 | 1524 | nested-attributes: bitset |
| 1525 | 1525 | - |
| 1526 | 1526 | name: hwtstamp-flags |
| 1527 | − type: u32 | |
| 1527 | + type: nest | |
| 1528 | + nested-attributes: bitset | |
| 1528 | 1529 | |
| 1529 | 1530 | operations: |
| 1530 | 1531 | enum-model: directional |
| @@ -369,8 +369,8 @@ to their default. · 368 unmodified lines | ||
| 369 | 369 | |
| 370 | 370 | addr.can_family = AF_CAN; |
| 371 | 371 | addr.can_ifindex = if_nametoindex("can0"); |
| 372 | − addr.tp.tx_id = 0x18DA42F1 | CAN_EFF_FLAG; | |
| 373 | − addr.tp.rx_id = 0x18DAF142 | CAN_EFF_FLAG; | |
| 372 | + addr.can_addr.tp.tx_id = 0x18DA42F1 | CAN_EFF_FLAG; | |
| 373 | + addr.can_addr.tp.rx_id = 0x18DAF142 | CAN_EFF_FLAG; | |
| 374 | 374 | |
| 375 | 375 | ret = bind(s, (struct sockaddr *)&addr, sizeof(addr)); |
| 376 | 376 | if (ret < 0) |
| @@ -112,7 +112,7 @@ Functions · 111 unmodified lines | ||
| 112 | 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 | 182 | the length of the message. skb->len - offset may be greater |
| 183 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1423 | Returns -EINVAL if called on a protected VM. |
| 1424 | 1424 | |
| 1425 | 1425 | 4.36 KVM_SET_TSS_ADDR |
| @@ -2209,7 +2209,6 @@ F: sound/soc/codecs/cs42l84.* · 2208 unmodified lines | ||
| 2209 | 2209 | F: sound/soc/codecs/ssm3515.c |
| 2210 | 2210 | |
| 2211 | 2211 | ARM/APPLE MACHINE SUPPORT |
| 2212 | −M: Hector Martin <marcan@marcan.st> | |
| 2213 | 2212 | M: Sven Peter <sven@svenpeter.dev> |
| 2214 | 2213 | R: Alyssa Rosenzweig <alyssa@rosenzweig.io> |
| 2215 | 2214 | L: asahi@lists.linux.dev |
| @@ -3655,7 +3654,6 @@ F: Documentation/devicetree/bindings/phy/phy-ath79-usb.txt · 1439 unmodified lines | ||
| 3655 | 3654 | F: drivers/phy/qualcomm/phy-ath79-usb.c |
| 3656 | 3655 | |
| 3657 | 3656 | ATHEROS ATH GENERIC UTILITIES |
| 3658 | −M: Kalle Valo <kvalo@kernel.org> | |
| 3659 | 3657 | M: Jeff Johnson <jjohnson@kernel.org> |
| 3660 | 3658 | L: linux-wireless@vger.kernel.org |
| 3661 | 3659 | S: Supported |
| @@ -3860,13 +3858,6 @@ W: https://ez.analog.com/linux-software-drivers · 198 unmodified lines | ||
| 3860 | 3858 | F: Documentation/devicetree/bindings/pwm/adi,axi-pwmgen.yaml |
| 3861 | 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 | 3861 | AZ6007 DVB DRIVER |
| 3871 | 3862 | M: Mauro Carvalho Chehab <mchehab@kernel.org> |
| 3872 | 3863 | L: linux-media@vger.kernel.org |
| @@ -3955,6 +3946,7 @@ M: Kent Overstreet <kent.overstreet@linux.dev> · 82 unmodified lines | ||
| 3955 | 3946 | L: linux-bcachefs@vger.kernel.org |
| 3956 | 3947 | S: Supported |
| 3957 | 3948 | C: irc://irc.oftc.net/bcache |
| 3949 | +P: Documentation/filesystems/bcachefs/SubmittingPatches.rst | |
| 3958 | 3950 | T: git https://evilpiepirate.org/git/bcachefs.git |
| 3959 | 3951 | F: fs/bcachefs/ |
| 3960 | 3952 | F: Documentation/filesystems/bcachefs/ |
| @@ -5663,7 +5655,7 @@ F: .clang-format · 1702 unmodified lines | ||
| 5663 | 5655 | |
| 5664 | 5656 | CLANG/LLVM BUILD SUPPORT |
| 5665 | 5657 | M: Nathan Chancellor <nathan@kernel.org> |
| 5666 | −R: Nick Desaulniers <ndesaulniers@google.com> | |
| 5658 | +R: Nick Desaulniers <nick.desaulniers+lkml@gmail.com> | |
| 5667 | 5659 | R: Bill Wendling <morbo@google.com> |
| 5668 | 5660 | R: Justin Stitt <justinstitt@google.com> |
| 5669 | 5661 | L: llvm@lists.linux.dev |
| @@ -7116,8 +7108,10 @@ F: rust/kernel/device.rs · 1446 unmodified lines | ||
| 7116 | 7108 | F: rust/kernel/device_id.rs |
| 7117 | 7109 | F: rust/kernel/devres.rs |
| 7118 | 7110 | F: rust/kernel/driver.rs |
| 7111 | +F: rust/kernel/faux.rs | |
| 7119 | 7112 | F: rust/kernel/platform.rs |
| 7120 | 7113 | F: samples/rust/rust_driver_platform.rs |
| 7114 | +F: samples/rust/rust_driver_faux.rs | |
| 7121 | 7115 | |
| 7122 | 7116 | DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS) |
| 7123 | 7117 | M: Nishanth Menon <nm@ti.com> |
| @@ -9418,7 +9412,7 @@ F: fs/freevxfs/ · 2294 unmodified lines | ||
| 9418 | 9412 | |
| 9419 | 9413 | FREEZER |
| 9420 | 9414 | M: "Rafael J. Wysocki" <rafael@kernel.org> |
| 9421 | −M: Pavel Machek <pavel@ucw.cz> | |
| 9415 | +M: Pavel Machek <pavel@kernel.org> | |
| 9422 | 9416 | L: linux-pm@vger.kernel.org |
| 9423 | 9417 | S: Supported |
| 9424 | 9418 | F: Documentation/power/freezing-of-tasks.rst |
| @@ -9835,8 +9829,7 @@ F: drivers/input/touchscreen/goodix* · 410 unmodified lines | ||
| 9835 | 9829 | |
| 9836 | 9830 | GOOGLE ETHERNET DRIVERS |
| 9837 | 9831 | M: Jeroen de Borst <jeroendb@google.com> |
| 9838 | −M: Praveen Kaligineedi <pkaligineedi@google.com> | |
| 9839 | −R: Shailend Chand <shailend@google.com> | |
| 9832 | +M: Harshitha Ramamurthy <hramamurthy@google.com> | |
| 9840 | 9833 | L: netdev@vger.kernel.org |
| 9841 | 9834 | S: Maintained |
| 9842 | 9835 | F: Documentation/networking/device_drivers/ethernet/google/gve.rst |
| @@ -9878,7 +9871,7 @@ S: Maintained · 35 unmodified lines | ||
| 9878 | 9871 | F: drivers/staging/gpib/ |
| 9879 | 9872 | |
| 9880 | 9873 | GPIO ACPI SUPPORT |
| 9881 | −M: Mika Westerberg <mika.westerberg@linux.intel.com> | |
| 9874 | +M: Mika Westerberg <westeri@kernel.org> | |
| 9882 | 9875 | M: Andy Shevchenko <andriy.shevchenko@linux.intel.com> |
| 9883 | 9876 | L: linux-gpio@vger.kernel.org |
| 9884 | 9877 | L: linux-acpi@vger.kernel.org |
| @@ -10253,7 +10246,7 @@ F: drivers/video/fbdev/hgafb.c · 368 unmodified lines | ||
| 10253 | 10246 | |
| 10254 | 10247 | HIBERNATION (aka Software Suspend, aka swsusp) |
| 10255 | 10248 | M: "Rafael J. Wysocki" <rafael@kernel.org> |
| 10256 | −M: Pavel Machek <pavel@ucw.cz> | |
| 10249 | +M: Pavel Machek <pavel@kernel.org> | |
| 10257 | 10250 | L: linux-pm@vger.kernel.org |
| 10258 | 10251 | S: Supported |
| 10259 | 10252 | B: https://bugzilla.kernel.org |
| @@ -10822,7 +10815,7 @@ S: Odd Fixes · 562 unmodified lines | ||
| 10822 | 10815 | F: drivers/tty/hvc/ |
| 10823 | 10816 | |
| 10824 | 10817 | I2C ACPI SUPPORT |
| 10825 | −M: Mika Westerberg <mika.westerberg@linux.intel.com> | |
| 10818 | +M: Mika Westerberg <westeri@kernel.org> | |
| 10826 | 10819 | L: linux-i2c@vger.kernel.org |
| 10827 | 10820 | L: linux-acpi@vger.kernel.org |
| 10828 | 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 | 13117 | F: scripts/leaking_addresses.pl |
| 13125 | 13118 | |
| 13126 | 13119 | LED SUBSYSTEM |
| 13127 | −M: Pavel Machek <pavel@ucw.cz> | |
| 13128 | 13120 | M: Lee Jones <lee@kernel.org> |
| 13121 | +M: Pavel Machek <pavel@kernel.org> | |
| 13129 | 13122 | L: linux-leds@vger.kernel.org |
| 13130 | 13123 | S: Maintained |
| 13131 | 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 | 16431 | X: drivers/net/wireless/ |
| 16439 | 16432 | |
| 16440 | 16433 | NETWORKING DRIVERS (WIRELESS) |
| 16441 | −M: Kalle Valo <kvalo@kernel.org> | |
| 16434 | +M: Johannes Berg <johannes@sipsolutions.net> | |
| 16442 | 16435 | L: linux-wireless@vger.kernel.org |
| 16443 | 16436 | S: Maintained |
| 16444 | 16437 | W: https://wireless.wiki.kernel.org/ |
| @@ -16462,6 +16455,28 @@ F: include/net/dsa.h · 17 unmodified lines | ||
| 16462 | 16455 | F: net/dsa/ |
| 16463 | 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 | 16480 | NETWORKING [GENERAL] |
| 16466 | 16481 | M: "David S. Miller" <davem@davemloft.net> |
| 16467 | 16482 | M: Eric Dumazet <edumazet@google.com> |
| @@ -16493,6 +16508,7 @@ F: include/linux/netdev* · 25 unmodified lines | ||
| 16493 | 16508 | F: include/linux/netlink.h |
| 16494 | 16509 | F: include/linux/netpoll.h |
| 16495 | 16510 | F: include/linux/rtnetlink.h |
| 16511 | +F: include/linux/sctp.h | |
| 16496 | 16512 | F: include/linux/seq_file_net.h |
| 16497 | 16513 | F: include/linux/skbuff* |
| 16498 | 16514 | F: include/net/ |
| @@ -16509,6 +16525,7 @@ F: include/uapi/linux/netdev* · 10 unmodified lines | ||
| 16509 | 16525 | F: include/uapi/linux/netlink.h |
| 16510 | 16526 | F: include/uapi/linux/netlink_diag.h |
| 16511 | 16527 | F: include/uapi/linux/rtnetlink.h |
| 16528 | +F: include/uapi/linux/sctp.h | |
| 16512 | 16529 | F: lib/net_utils.c |
| 16513 | 16530 | F: lib/random32.c |
| 16514 | 16531 | F: net/ |
| @@ -16621,6 +16638,7 @@ F: tools/testing/selftests/net/mptcp/ · 106 unmodified lines | ||
| 16621 | 16638 | NETWORKING [TCP] |
| 16622 | 16639 | M: Eric Dumazet <edumazet@google.com> |
| 16623 | 16640 | M: Neal Cardwell <ncardwell@google.com> |
| 16641 | +R: Kuniyuki Iwashima <kuniyu@amazon.com> | |
| 16624 | 16642 | L: netdev@vger.kernel.org |
| 16625 | 16643 | S: Maintained |
| 16626 | 16644 | F: Documentation/networking/net_cachelines/tcp_sock.rst |
| @@ -16648,6 +16666,31 @@ F: include/net/tls.h · 21 unmodified lines | ||
| 16648 | 16666 | F: include/uapi/linux/tls.h |
| 16649 | 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 | 16694 | NETXEN (1/10) GbE SUPPORT |
| 16652 | 16695 | M: Manish Chopra <manishc@marvell.com> |
| 16653 | 16696 | M: Rahul Verma <rahulv@marvell.com> |
| @@ -16781,7 +16824,7 @@ F: include/linux/tick.h · 127 unmodified lines | ||
| 16781 | 16824 | F: kernel/time/tick*.* |
| 16782 | 16825 | |
| 16783 | 16826 | NOKIA N900 CAMERA SUPPORT (ET8EK8 SENSOR, AD5820 FOCUS) |
| 16784 | −M: Pavel Machek <pavel@ucw.cz> | |
| 16827 | +M: Pavel Machek <pavel@kernel.org> | |
| 16785 | 16828 | M: Sakari Ailus <sakari.ailus@iki.fi> |
| 16786 | 16829 | L: linux-media@vger.kernel.org |
| 16787 | 16830 | S: Maintained |
| @@ -17713,6 +17756,7 @@ L: netdev@vger.kernel.org · 925 unmodified lines | ||
| 17713 | 17756 | L: dev@openvswitch.org |
| 17714 | 17757 | S: Maintained |
| 17715 | 17758 | W: http://openvswitch.org |
| 17759 | +F: Documentation/networking/openvswitch.rst | |
| 17716 | 17760 | F: include/uapi/linux/openvswitch.h |
| 17717 | 17761 | F: net/openvswitch/ |
| 17718 | 17762 | F: tools/testing/selftests/net/openvswitch/ |
| @@ -19312,7 +19356,6 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/ · 1593 unmodified lines | ||
| 19312 | 19356 | F: drivers/media/tuners/qt1010* |
| 19313 | 19357 | |
| 19314 | 19358 | QUALCOMM ATH12K WIRELESS DRIVER |
| 19315 | −M: Kalle Valo <kvalo@kernel.org> | |
| 19316 | 19359 | M: Jeff Johnson <jjohnson@kernel.org> |
| 19317 | 19360 | L: ath12k@lists.infradead.org |
| 19318 | 19361 | S: Supported |
| @@ -19322,7 +19365,6 @@ F: drivers/net/wireless/ath/ath12k/ · 3 unmodified lines | ||
| 19322 | 19365 | N: ath12k |
| 19323 | 19366 | |
| 19324 | 19367 | QUALCOMM ATHEROS ATH10K WIRELESS DRIVER |
| 19325 | −M: Kalle Valo <kvalo@kernel.org> | |
| 19326 | 19368 | M: Jeff Johnson <jjohnson@kernel.org> |
| 19327 | 19369 | L: ath10k@lists.infradead.org |
| 19328 | 19370 | S: Supported |
| @@ -19332,7 +19374,6 @@ F: drivers/net/wireless/ath/ath10k/ · 3 unmodified lines | ||
| 19332 | 19374 | N: ath10k |
| 19333 | 19375 | |
| 19334 | 19376 | QUALCOMM ATHEROS ATH11K WIRELESS DRIVER |
| 19335 | −M: Kalle Valo <kvalo@kernel.org> | |
| 19336 | 19377 | M: Jeff Johnson <jjohnson@kernel.org> |
| 19337 | 19378 | L: ath11k@lists.infradead.org |
| 19338 | 19379 | S: Supported |
| @@ -19467,6 +19508,15 @@ L: dmaengine@vger.kernel.org · 128 unmodified lines | ||
| 19467 | 19508 | S: Supported |
| 19468 | 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 | 19520 | QUALCOMM I2C CCI DRIVER |
| 19471 | 19521 | M: Loic Poulain <loic.poulain@linaro.org> |
| 19472 | 19522 | M: Robert Foss <rfoss@kernel.org> |
| @@ -22806,7 +22856,7 @@ F: drivers/sh/ · 3333 unmodified lines | ||
| 22806 | 22856 | SUSPEND TO RAM |
| 22807 | 22857 | M: "Rafael J. Wysocki" <rafael@kernel.org> |
| 22808 | 22858 | M: Len Brown <len.brown@intel.com> |
| 22809 | −M: Pavel Machek <pavel@ucw.cz> | |
| 22859 | +M: Pavel Machek <pavel@kernel.org> | |
| 22810 | 22860 | L: linux-pm@vger.kernel.org |
| 22811 | 22861 | S: Supported |
| 22812 | 22862 | B: https://bugzilla.kernel.org |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 14 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc1 | |
| 5 | +EXTRAVERSION = -rc3 | |
| 6 | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -1120,8 +1120,8 @@ LDFLAGS_vmlinux += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL) · 1111 unmodified lines | ||
| 1120 | 1120 | endif |
| 1121 | 1121 | |
| 1122 | 1122 | # Align the bit size of userspace programs with the kernel |
| 1123 | −KBUILD_USERCFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS)) | |
| 1124 | −KBUILD_USERLDFLAGS += $(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_CPPFLAGS) $(KBUILD_CFLAGS)) | |
| 1125 | 1125 | |
| 1126 | 1126 | # make the checker run with the right architecture |
| 1127 | 1127 | CHECKFLAGS += --arch=$(ARCH) |
| @@ -1421,18 +1421,13 @@ ifneq ($(wildcard $(resolve_btfids_O)),) · 293 unmodified lines | ||
| 1421 | 1421 | $(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean |
| 1422 | 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 | 1424 | tools/: FORCE |
| 1430 | 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 | 1428 | tools/%: FORCE |
| 1434 | 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 | 1433 | # Kernel selftest |
| @@ -74,7 +74,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; · 73 unmodified lines | ||
| 74 | 74 | /* |
| 75 | 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 | 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 | 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 | 140 | extern int alpha_l1i_cacheshape; |
| 145 | 141 | extern int alpha_l1d_cacheshape; |
| 146 | 142 | extern int alpha_l2_cacheshape; |
| @@ -135,7 +135,7 @@ struct crb_struct { · 134 unmodified lines | ||
| 135 | 135 | /* virtual->physical map */ |
| 136 | 136 | unsigned long map_entries; |
| 137 | 137 | unsigned long map_pages; |
| 138 | − struct vf_map_struct map[1]; | |
| 138 | + struct vf_map_struct map[]; | |
| 139 | 139 | }; |
| 140 | 140 | |
| 141 | 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 | 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 | 364 | #define HAVE_ARCH_UNMAPPED_AREA |
| 365 | 365 | |
| 366 | 366 | #endif /* _ALPHA_PGTABLE_H */ |
| @@ -8,23 +8,19 @@ · 7 unmodified lines | ||
| 8 | 8 | #ifndef __ASM_ALPHA_PROCESSOR_H |
| 9 | 9 | #define __ASM_ALPHA_PROCESSOR_H |
| 10 | 10 | |
| 11 | −#include <linux/personality.h> /* for ADDR_LIMIT_32BIT */ | |
| 12 | − | |
| 13 | 11 | /* |
| 14 | 12 | * We have a 42-bit user address space: 4TB user VM... |
| 15 | 13 | */ |
| 16 | 14 | #define TASK_SIZE (0x40000000000UL) |
| 17 | 15 | |
| 18 | −#define STACK_TOP \ | |
| 19 | − (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL) | |
| 16 | +#define STACK_TOP (0x00120000000UL) | |
| 20 | 17 | |
| 21 | 18 | #define STACK_TOP_MAX 0x00120000000UL |
| 22 | 19 | |
| 23 | 20 | /* This decides where the kernel will search for a free chunk of vm |
| 24 | 21 | * space during mmap's. |
| 25 | 22 | */ |
| 26 | −#define TASK_UNMAPPED_BASE \ | |
| 27 | − ((current->personality & ADDR_LIMIT_32BIT) ? 0x40000000 : TASK_SIZE / 2) | |
| 23 | +#define TASK_UNMAPPED_BASE (TASK_SIZE / 2) | |
| 28 | 24 | |
| 29 | 25 | /* This is dead. Everything has been moved to thread_info. */ |
| 30 | 26 | struct thread_struct { }; |
| @@ -42,6 +42,8 @@ struct pt_regs { · 41 unmodified lines | ||
| 42 | 42 | unsigned long trap_a0; |
| 43 | 43 | unsigned long trap_a1; |
| 44 | 44 | unsigned long trap_a2; |
| 45 | +/* This makes the stack 16-byte aligned as GCC expects */ | |
| 46 | + unsigned long __pad0; | |
| 45 | 47 | /* These are saved by PAL-code: */ |
| 46 | 48 | unsigned long ps; |
| 47 | 49 | unsigned long pc; |
| @@ -19,9 +19,13 @@ static void __used foo(void) · 18 unmodified lines | ||
| 19 | 19 | DEFINE(TI_STATUS, offsetof(struct thread_info, status)); |
| 20 | 20 | BLANK(); |
| 21 | 21 | |
| 22 | + DEFINE(SP_OFF, offsetof(struct pt_regs, ps)); | |
| 22 | 23 | DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs)); |
| 23 | 24 | BLANK(); |
| 24 | 25 | |
| 26 | + DEFINE(SWITCH_STACK_SIZE, sizeof(struct switch_stack)); | |
| 27 | + BLANK(); | |
| 28 | + | |
| 25 | 29 | DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache)); |
| 26 | 30 | DEFINE(HAE_REG, offsetof(struct alpha_machine_vector, hae_register)); |
| 27 | 31 | } |
| @@ -15,10 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | .set noat |
| 16 | 16 | .cfi_sections .debug_frame |
| 17 | 17 | |
| 18 | −/* Stack offsets. */ | |
| 19 | −#define SP_OFF 184 | |
| 20 | −#define SWITCH_STACK_SIZE 64 | |
| 21 | − | |
| 22 | 18 | .macro CFI_START_OSF_FRAME func |
| 23 | 19 | .align 4 |
| 24 | 20 | .globl \func |
| @@ -198,8 +194,8 @@ CFI_END_OSF_FRAME entArith · 173 unmodified lines | ||
| 198 | 194 | CFI_START_OSF_FRAME entMM |
| 199 | 195 | SAVE_ALL |
| 200 | 196 | /* save $9 - $15 so the inline exception code can manipulate them. */ |
| 201 | − subq $sp, 56, $sp | |
| 202 | − .cfi_adjust_cfa_offset 56 | |
| 197 | + subq $sp, 64, $sp | |
| 198 | + .cfi_adjust_cfa_offset 64 | |
| 203 | 199 | stq $9, 0($sp) |
| 204 | 200 | stq $10, 8($sp) |
| 205 | 201 | stq $11, 16($sp) |
| @@ -214,7 +210,7 @@ CFI_START_OSF_FRAME entMM · 8 unmodified lines | ||
| 214 | 210 | .cfi_rel_offset $13, 32 |
| 215 | 211 | .cfi_rel_offset $14, 40 |
| 216 | 212 | .cfi_rel_offset $15, 48 |
| 217 | − addq $sp, 56, $19 | |
| 213 | + addq $sp, 64, $19 | |
| 218 | 214 | /* handle the fault */ |
| 219 | 215 | lda $8, 0x3fff |
| 220 | 216 | bic $sp, $8, $8 |
| @@ -227,7 +223,7 @@ CFI_START_OSF_FRAME entMM · 6 unmodified lines | ||
| 227 | 223 | ldq $13, 32($sp) |
| 228 | 224 | ldq $14, 40($sp) |
| 229 | 225 | ldq $15, 48($sp) |
| 230 | − addq $sp, 56, $sp | |
| 226 | + addq $sp, 64, $sp | |
| 231 | 227 | .cfi_restore $9 |
| 232 | 228 | .cfi_restore $10 |
| 233 | 229 | .cfi_restore $11 |
| @@ -235,7 +231,7 @@ CFI_START_OSF_FRAME entMM · 1 unmodified line | ||
| 235 | 231 | .cfi_restore $13 |
| 236 | 232 | .cfi_restore $14 |
| 237 | 233 | .cfi_restore $15 |
| 238 | − .cfi_adjust_cfa_offset -56 | |
| 234 | + .cfi_adjust_cfa_offset -64 | |
| 239 | 235 | /* finish up the syscall as normal. */ |
| 240 | 236 | br ret_from_sys_call |
| 241 | 237 | CFI_END_OSF_FRAME entMM |
| @@ -382,8 +378,8 @@ entUnaUser: · 140 unmodified lines | ||
| 382 | 378 | .cfi_restore $0 |
| 383 | 379 | .cfi_adjust_cfa_offset -256 |
| 384 | 380 | SAVE_ALL /* setup normal kernel stack */ |
| 385 | − lda $sp, -56($sp) | |
| 386 | − .cfi_adjust_cfa_offset 56 | |
| 381 | + lda $sp, -64($sp) | |
| 382 | + .cfi_adjust_cfa_offset 64 | |
| 387 | 383 | stq $9, 0($sp) |
| 388 | 384 | stq $10, 8($sp) |
| 389 | 385 | stq $11, 16($sp) |
| @@ -399,7 +395,7 @@ entUnaUser: · 9 unmodified lines | ||
| 399 | 395 | .cfi_rel_offset $14, 40 |
| 400 | 396 | .cfi_rel_offset $15, 48 |
| 401 | 397 | lda $8, 0x3fff |
| 402 | − addq $sp, 56, $19 | |
| 398 | + addq $sp, 64, $19 | |
| 403 | 399 | bic $sp, $8, $8 |
| 404 | 400 | jsr $26, do_entUnaUser |
| 405 | 401 | ldq $9, 0($sp) |
| @@ -409,7 +405,7 @@ entUnaUser: · 3 unmodified lines | ||
| 409 | 405 | ldq $13, 32($sp) |
| 410 | 406 | ldq $14, 40($sp) |
| 411 | 407 | ldq $15, 48($sp) |
| 412 | − lda $sp, 56($sp) | |
| 408 | + lda $sp, 64($sp) | |
| 413 | 409 | .cfi_restore $9 |
| 414 | 410 | .cfi_restore $10 |
| 415 | 411 | .cfi_restore $11 |
| @@ -417,7 +413,7 @@ entUnaUser: · 1 unmodified line | ||
| 417 | 413 | .cfi_restore $13 |
| 418 | 414 | .cfi_restore $14 |
| 419 | 415 | .cfi_restore $15 |
| 420 | − .cfi_adjust_cfa_offset -56 | |
| 416 | + .cfi_adjust_cfa_offset -64 | |
| 421 | 417 | br ret_from_sys_call |
| 422 | 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 | 1210 | return ret; |
| 1211 | 1211 | } |
| 1212 | 1212 | |
| 1213 | −/* Get an address range which is currently unmapped. Similar to the | |
| 1214 | − generic version except that we know how to honor ADDR_LIMIT_32BIT. */ | |
| 1213 | +/* Get an address range which is currently unmapped. */ | |
| 1215 | 1214 | |
| 1216 | 1215 | static unsigned long |
| 1217 | 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 | 1229 | unsigned long len, unsigned long pgoff, |
| 1231 | 1230 | unsigned long flags, vm_flags_t vm_flags) |
| 1232 | 1231 | { |
| 1233 | − unsigned long limit; | |
| 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; | |
| 1232 | + unsigned long limit = TASK_SIZE; | |
| 1240 | 1233 | |
| 1241 | 1234 | if (len > limit) |
| 1242 | 1235 | return -ENOMEM; |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/log2.h> |
| 14 | 14 | #include <linux/dma-map-ops.h> |
| 15 | 15 | #include <linux/iommu-helper.h> |
| 16 | +#include <linux/string_choices.h> | |
| 16 | 17 | |
| 17 | 18 | #include <asm/io.h> |
| 18 | 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 | 214 | /* If both conditions above are met, we are fine. */ |
| 214 | 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 | 218 | return ok; |
| 218 | 219 | } |
| @@ -649,7 +649,7 @@ s_reg_to_mem (unsigned long s_reg) · 648 unmodified lines | ||
| 649 | 649 | static int unauser_reg_offsets[32] = { |
| 650 | 650 | R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), |
| 651 | 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 | 653 | R(r16), R(r17), R(r18), |
| 654 | 654 | R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26), |
| 655 | 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 | 79 | /* Macro for exception fixup code to access integer registers. */ |
| 80 | 80 | #define dpf_reg(r) \ |
| 81 | − (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \ | |
| 82 | − (r) <= 18 ? (r)+10 : (r)-10]) | |
| 81 | + (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-17 : \ | |
| 82 | + (r) <= 18 ? (r)+11 : (r)-10]) | |
| 83 | 83 | |
| 84 | 84 | asmlinkage void |
| 85 | 85 | do_page_fault(unsigned long address, unsigned long mmcsr, |
| @@ -225,7 +225,6 @@ config ARM64 · 224 unmodified lines | ||
| 225 | 225 | select HAVE_FUNCTION_ERROR_INJECTION |
| 226 | 226 | select HAVE_FUNCTION_GRAPH_FREGS |
| 227 | 227 | select HAVE_FUNCTION_GRAPH_TRACER |
| 228 | − select HAVE_FUNCTION_GRAPH_RETVAL | |
| 229 | 228 | select HAVE_GCC_PLUGINS |
| 230 | 229 | select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && \ |
| 231 | 230 | HW_PERF_EVENTS && HAVE_PERF_EVENTS_NMI |
| @@ -48,7 +48,11 @@ KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU) \ · 47 unmodified lines | ||
| 48 | 48 | KBUILD_CFLAGS += $(call cc-disable-warning, psabi) |
| 49 | 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 | 54 | KBUILD_RUSTFLAGS += --target=aarch64-unknown-none -Ctarget-feature="-neon" |
| 55 | +endif | |
| 52 | 56 | |
| 53 | 57 | KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) |
| 54 | 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 | 605 | __cpacr_to_cptr_set(clr, set));\ |
| 606 | 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 | 609 | * Returns a 'sanitised' view of CPTR_EL2, translating from nVHE to the VHE |
| 652 | 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 | 100 | static inline void *pop_hyp_memcache(struct kvm_hyp_memcache *mc, |
| 101 | 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 | 105 | if (!mc->nr_pages) |
| 106 | 106 | return NULL; |
| @@ -615,8 +615,6 @@ struct cpu_sve_state { · 508 unmodified lines | ||
| 615 | 615 | struct kvm_host_data { |
| 616 | 616 | #define KVM_HOST_DATA_FLAG_HAS_SPE 0 |
| 617 | 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 | 618 | #define KVM_HOST_DATA_FLAG_TRBE_ENABLED 4 |
| 621 | 619 | #define KVM_HOST_DATA_FLAG_EL1_TRACING_CONFIGURED 5 |
| 622 | 620 | unsigned long flags; |
| @@ -624,23 +622,13 @@ struct kvm_host_data { · 1 unmodified line | ||
| 624 | 622 | struct kvm_cpu_context host_ctxt; |
| 625 | 623 | |
| 626 | 624 | /* |
| 627 | − * All pointers in this union are hyp VA. | |
| 625 | + * Hyp VA. | |
| 628 | 626 | * sve_state is only used in pKVM and if system_supports_sve(). |
| 629 | 627 | */ |
| 630 | − union { | |
| 631 | − struct user_fpsimd_state *fpsimd_state; | |
| 632 | − struct cpu_sve_state *sve_state; | |
| 633 | − }; | |
| 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 | − }; | |
| 628 | + struct cpu_sve_state *sve_state; | |
| 629 | + | |
| 630 | + /* Used by pKVM only. */ | |
| 631 | + u64 fpmr; | |
| 644 | 632 | |
| 645 | 633 | /* Ownership of the FP regs */ |
| 646 | 634 | enum { |
| @@ -101,16 +101,18 @@ int populate_cache_leaves(unsigned int cpu) · 100 unmodified lines | ||
| 101 | 101 | unsigned int level, idx; |
| 102 | 102 | enum cache_type type; |
| 103 | 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 | 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 | 108 | type = get_cache_type(level); |
| 109 | 109 | if (type == CACHE_TYPE_SEPARATE) { |
| 110 | − ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level); | |
| 111 | − ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level); | |
| 110 | + if (idx + 1 >= this_cpu_ci->num_leaves) | |
| 111 | + break; | |
| 112 | + ci_leaf_init(&infos[idx++], CACHE_TYPE_DATA, level); | |
| 113 | + ci_leaf_init(&infos[idx++], CACHE_TYPE_INST, level); | |
| 112 | 114 | } else { |
| 113 | − ci_leaf_init(this_leaf++, type, level); | |
| 115 | + ci_leaf_init(&infos[idx++], type, level); | |
| 114 | 116 | } |
| 115 | 117 | } |
| 116 | 118 | return 0; |
| @@ -3091,6 +3091,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { · 3090 unmodified lines | ||
| 3091 | 3091 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM, CAP_HWCAP, KERNEL_HWCAP_FLAGM), |
| 3092 | 3092 | HWCAP_CAP(ID_AA64ISAR0_EL1, TS, FLAGM2, CAP_HWCAP, KERNEL_HWCAP_FLAGM2), |
| 3093 | 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 | 3095 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, IMP, CAP_HWCAP, KERNEL_HWCAP_FP), |
| 3095 | 3096 | HWCAP_CAP(ID_AA64PFR0_EL1, FP, FP16, CAP_HWCAP, KERNEL_HWCAP_FPHP), |
| 3096 | 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 | 3181 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8FMA), |
| 3181 | 3182 | HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP4), |
| 3182 | 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 | 3184 | HWCAP_CAP(ID_AA64SMFR0_EL1, SBitPerm, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SBITPERM), |
| 3186 | 3185 | HWCAP_CAP(ID_AA64SMFR0_EL1, AES, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_AES), |
| 3187 | 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 | 3191 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_F8FMA), |
| 3193 | 3192 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_F8DP4), |
| 3194 | 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 | 3196 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E4M3, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E4M3), |
| 3196 | 3197 | HWCAP_CAP(ID_AA64FPFR0_EL1, F8E5M2, IMP, CAP_HWCAP, KERNEL_HWCAP_F8E5M2), |
| 3197 | 3198 | #ifdef CONFIG_ARM64_POE |
| @@ -1694,31 +1694,6 @@ void fpsimd_signal_preserve_current_state(void) · 1693 unmodified lines | ||
| 1694 | 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 | 1698 | * Associate current's FPSIMD context with this cpu |
| 1724 | 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 | 194 | int cpu; |
| 195 | 195 | |
| 196 | 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 | 199 | return; |
| 199 | 200 | |
| 200 | − for_each_cpu(cpu, cpus) { | |
| 201 | + for_each_cpu(cpu, cpus) | |
| 201 | 202 | if (!freq_counters_valid(cpu)) |
| 202 | 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 | 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 | 245 | static int __init init_amu_fie(void) |
| 239 | 246 | { |
| 240 | − int ret; | |
| 241 | − | |
| 242 | − if (!zalloc_cpumask_var(&amu_fie_cpus, GFP_KERNEL)) | |
| 243 | − return -ENOMEM; | |
| 244 | − | |
| 245 | − ret = cpufreq_register_notifier(&init_amu_fie_notifier, | |
| 247 | + return cpufreq_register_notifier(&init_amu_fie_notifier, | |
| 246 | 248 | CPUFREQ_POLICY_NOTIFIER); |
| 247 | − if (ret) | |
| 248 | − free_cpumask_var(amu_fie_cpus); | |
| 249 | − | |
| 250 | − return ret; | |
| 251 | 249 | } |
| 252 | 250 | core_initcall(init_amu_fie); |
| 253 | 251 | |
| @@ -41,6 +41,7 @@ SECTIONS · 40 unmodified lines | ||
| 41 | 41 | */ |
| 42 | 42 | /DISCARD/ : { |
| 43 | 43 | *(.note.GNU-stack .note.gnu.property) |
| 44 | + *(.ARM.attributes) | |
| 44 | 45 | } |
| 45 | 46 | .note : { *(.note.*) } :text :note |
| 46 | 47 | |
| @@ -162,6 +162,7 @@ SECTIONS · 161 unmodified lines | ||
| 162 | 162 | /DISCARD/ : { |
| 163 | 163 | *(.interp .dynamic) |
| 164 | 164 | *(.dynsym .dynstr .hash .gnu.hash) |
| 165 | + *(.ARM.attributes) | |
| 165 | 166 | } |
| 166 | 167 | |
| 167 | 168 | . = KIMAGE_VADDR; |
| @@ -447,21 +447,19 @@ static void kvm_timer_update_status(struct arch_timer_context *ctx, bool level) · 446 unmodified lines | ||
| 447 | 447 | static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level, |
| 448 | 448 | struct arch_timer_context *timer_ctx) |
| 449 | 449 | { |
| 450 | − int ret; | |
| 451 | − | |
| 452 | 450 | kvm_timer_update_status(timer_ctx, new_level); |
| 453 | 451 | |
| 454 | 452 | timer_ctx->irq.level = new_level; |
| 455 | 453 | trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_irq(timer_ctx), |
| 456 | 454 | timer_ctx->irq.level); |
| 457 | 455 | |
| 458 | − if (!userspace_irqchip(vcpu->kvm)) { | |
| 459 | − ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu, | |
| 460 | − timer_irq(timer_ctx), | |
| 461 | − timer_ctx->irq.level, | |
| 462 | − timer_ctx); | |
| 463 | − WARN_ON(ret); | |
| 464 | − } | |
| 456 | + if (userspace_irqchip(vcpu->kvm)) | |
| 457 | + return; | |
| 458 | + | |
| 459 | + kvm_vgic_inject_irq(vcpu->kvm, vcpu, | |
| 460 | + timer_irq(timer_ctx), | |
| 461 | + timer_ctx->irq.level, | |
| 462 | + timer_ctx); | |
| 465 | 463 | } |
| 466 | 464 | |
| 467 | 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 | 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 | 473 | kvm_timer_update_irq(ctx->vcpu, should_fire, ctx); |
| 476 | − return; | |
| 477 | − } | |
| 478 | 474 | |
| 479 | 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 | 757 | timer_irq(map->direct_ptimer), |
| 762 | 758 | &arch_timer_irq_ops); |
| 763 | 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 | 957 | * which allows trapping of the timer registers even with NV2. |
| 977 | 958 | * Still, this is still worse than FEAT_NV on its own. Meh. |
| 978 | 959 | */ |
| 979 | − if (!vcpu_el2_e2h_is_set(vcpu)) { | |
| 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 { | |
| 960 | + if (!cpus_have_final_cap(ARM64_HAS_ECV)) { | |
| 998 | 961 | /* |
| 999 | 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 | 964 | * state is stored in the VNCR page. The latter could have |
| 1002 | 965 | * been updated behind our back, and we must reset the |
| 1003 | 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 | 976 | struct timer_map map; |
| 1006 | 977 | get_timer_map(vcpu, &map); |
| @@ -2290,6 +2290,19 @@ static int __init init_subsystems(void) · 2289 unmodified lines | ||
| 2290 | 2290 | break; |
| 2291 | 2291 | case -ENODEV: |
| 2292 | 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 | 2306 | vgic_present = false; |
| 2294 | 2307 | err = 0; |
| 2295 | 2308 | break; |
| @@ -2400,6 +2413,13 @@ static void kvm_hyp_init_symbols(void) · 104 unmodified lines | ||
| 2400 | 2413 | kvm_nvhe_sym(id_aa64smfr0_el1_sys_val) = read_sanitised_ftr_reg(SYS_ID_AA64SMFR0_EL1); |
| 2401 | 2414 | kvm_nvhe_sym(__icache_flags) = __icache_flags; |
| 2402 | 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 | 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 | 2481 | per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state = |
| 2462 | 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 | 54 | if (!system_supports_fpsimd()) |
| 55 | 55 | return; |
| 56 | 56 | |
| 57 | − fpsimd_kvm_prepare(); | |
| 58 | − | |
| 59 | 57 | /* |
| 60 | − * We will check TIF_FOREIGN_FPSTATE just before entering the | |
| 61 | − * guest in kvm_arch_vcpu_ctxflush_fp() and override this to | |
| 62 | − * FP_STATE_FREE if the flag set. | |
| 58 | + * Ensure that any host FPSIMD/SVE/SME state is saved and unbound such | |
| 59 | + * that the host kernel is responsible for restoring this state upon | |
| 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 | − *host_data_ptr(fpsimd_state) = kern_hyp_va(¤t->thread.uw.fpsimd_state); | |
| 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 | − } | |
| 65 | + fpsimd_save_and_flush_cpu_state(); | |
| 66 | + *host_data_ptr(fp_owner) = FP_STATE_FREE; | |
| 94 | 67 | |
| 95 | − /* | |
| 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)); | |
| 68 | + WARN_ON_ONCE(system_supports_sme() && 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 | 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 | 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 | 135 | * Flush (save and invalidate) the fpsimd/sve state so that if |
| 213 | 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 | 142 | * when needed. |
| 220 | 143 | */ |
| 221 | 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 | 147 | local_irq_restore(flags); |
| @@ -44,6 +44,11 @@ alternative_if ARM64_HAS_RAS_EXTN · 43 unmodified lines | ||
| 44 | 44 | alternative_else_nop_endif |
| 45 | 45 | mrs x1, isr_el1 |
| 46 | 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 | 52 | mov x0, #ARM_EXCEPTION_IRQ |
| 48 | 53 | ret |
| 49 | 54 | |
| @@ -326,7 +326,7 @@ static inline bool __populate_fault_info(struct kvm_vcpu *vcpu) · 325 unmodified lines | ||
| 326 | 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 | 331 | *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR); |
| 332 | 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 | 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 | 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 | 463 | * If FP/SIMD is not implemented, handle the trap and inject an undefined |
| 384 | 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 | 468 | bool sve_guest; |
| 389 | 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 | 505 | isb(); |
| 426 | 506 | |
| 427 | 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 | 509 | kvm_hyp_save_fpsimd_host(vcpu); |
| 430 | 510 | |
| 431 | 511 | /* Restore the guest state */ |
| @@ -501,9 +581,22 @@ static inline bool handle_tx2_tvm(struct kvm_vcpu *vcpu) · 69 unmodified lines | ||
| 501 | 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 | 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 | 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 | 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 | 685 | if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_TX2_219_TVM) && |
| 593 | 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 | 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 | 705 | if (static_branch_unlikely(&vgic_v3_cpuif_trap) && |
| 613 | 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 | 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 | 715 | if (!__populate_fault_info(vcpu)) |
| 622 | 716 | return true; |
| 623 | 717 | |
| 624 | 718 | return false; |
| 625 | 719 | } |
| 626 | −static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) | |
| 627 | − __alias(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); | |
| 720 | +#define kvm_hyp_handle_iabt_low kvm_hyp_handle_memory_fault | |
| 721 | +#define kvm_hyp_handle_watchpt_low 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 | 725 | if (kvm_hyp_handle_memory_fault(vcpu, exit_code)) |
| 634 | 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 | 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 | 754 | * Allow the hypervisor to handle the exit with an exit handler if it has one. |
| 667 | 755 | * |
| 668 | 756 | * Returns true if the hypervisor handled the exit, and control should go back |
| 669 | 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); | |
| 674 | − exit_handler_fn fn; | |
| 675 | − | |
| 676 | − fn = handlers[kvm_vcpu_trap_get_class(vcpu)]; | |
| 677 | − | |
| 762 | + exit_handler_fn fn = handlers[kvm_vcpu_trap_get_class(vcpu)]; | |
| 678 | 763 | if (fn) |
| 679 | 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 | 789 | * the guest, false when we should restore the host state and return to the |
| 705 | 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 | 795 | if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) |
| 722 | 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 | 821 | goto exit; |
| 748 | 822 | |
| 749 | 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 | 825 | goto guest; |
| 752 | 826 | exit: |
| 753 | 827 | /* Return to the host kernel and handle the exit */ |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | #include <hyp/adjust_pc.h> |
| 8 | +#include <hyp/switch.h> | |
| 8 | 9 | |
| 9 | 10 | #include <asm/pgtable-types.h> |
| 10 | 11 | #include <asm/kvm_asm.h> |
| @@ -83,7 +84,7 @@ static void fpsimd_sve_sync(struct kvm_vcpu *vcpu) · 72 unmodified lines | ||
| 83 | 84 | if (system_supports_sve()) |
| 84 | 85 | __hyp_sve_restore_host(); |
| 85 | 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 | 89 | if (has_fpmr) |
| 89 | 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 | 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 | 117 | static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) |
| 95 | 118 | { |
| 96 | 119 | struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu; |
| 97 | 120 | |
| 98 | 121 | fpsimd_sve_flush(); |
| 122 | + flush_debug_state(hyp_vcpu); | |
| 99 | 123 | |
| 100 | 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 | 147 | unsigned int i; |
| 124 | 148 | |
| 125 | 149 | fpsimd_sve_sync(&hyp_vcpu->vcpu); |
| 150 | + sync_debug_state(hyp_vcpu); | |
| 126 | 151 | |
| 127 | 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 | 226 | sync_hyp_vcpu(hyp_vcpu); |
| 202 | 227 | } else { |
| 228 | + struct kvm_vcpu *vcpu = kern_hyp_va(host_vcpu); | |
| 229 | + | |
| 203 | 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 | 235 | out: |
| 207 | 236 | cpu_reg(host_ctxt, 1) = ret; |
| @@ -651,12 +680,6 @@ void handle_trap(struct kvm_cpu_context *host_ctxt) · 443 unmodified lines | ||
| 651 | 680 | case ESR_ELx_EC_SMC64: |
| 652 | 681 | handle_host_smc(host_ctxt); |
| 653 | 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 | 683 | case ESR_ELx_EC_IABT_LOW: |
| 661 | 684 | case ESR_ELx_EC_DABT_LOW: |
| 662 | 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 | 943 | ret = kvm_pgtable_get_leaf(&vm->pgt, ipa, &pte, &level); |
| 944 | 944 | if (ret) |
| 945 | 945 | return ret; |
| 946 | − if (level != KVM_PGTABLE_LAST_LEVEL) | |
| 947 | − return -E2BIG; | |
| 948 | 946 | if (!kvm_pte_valid(pte)) |
| 949 | 947 | return -ENOENT; |
| 948 | + if (level != KVM_PGTABLE_LAST_LEVEL) | |
| 949 | + return -E2BIG; | |
| 950 | 950 | |
| 951 | 951 | state = guest_get_page_state(pte, ipa); |
| 952 | 952 | if (state != PKVM_PAGE_SHARED_BORROWED) |
| @@ -998,63 +998,73 @@ unlock: · 45 unmodified lines | ||
| 998 | 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 | 1003 | u64 phys; |
| 1006 | 1004 | int ret; |
| 1007 | 1005 | |
| 1008 | − if (prot & ~KVM_PGTABLE_PROT_RWX) | |
| 1009 | − return -EINVAL; | |
| 1006 | + if (!IS_ENABLED(CONFIG_NVHE_EL2_DEBUG)) | |
| 1007 | + return; | |
| 1010 | 1008 | |
| 1011 | 1009 | host_lock_component(); |
| 1012 | 1010 | guest_lock_component(vm); |
| 1013 | 1011 | |
| 1014 | 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 | 1014 | guest_unlock_component(vm); |
| 1019 | 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 | 1023 | u64 ipa = hyp_pfn_to_phys(gfn); |
| 1027 | − u64 phys; | |
| 1028 | 1024 | int ret; |
| 1029 | 1025 | |
| 1030 | − host_lock_component(); | |
| 1031 | − guest_lock_component(vm); | |
| 1026 | + if (pkvm_hyp_vm_is_protected(vm)) | |
| 1027 | + return -EPERM; | |
| 1032 | 1028 | |
| 1033 | − ret = __check_host_shared_guest(vm, &phys, ipa); | |
| 1034 | − if (!ret) | |
| 1035 | − ret = kvm_pgtable_stage2_wrprotect(&vm->pgt, ipa, PAGE_SIZE); | |
| 1029 | + if (prot & ~KVM_PGTABLE_PROT_RWX) | |
| 1030 | + return -EINVAL; | |
| 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 | 1035 | guest_unlock_component(vm); |
| 1038 | − host_unlock_component(); | |
| 1039 | 1036 | |
| 1040 | 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 | 1042 | u64 ipa = hyp_pfn_to_phys(gfn); |
| 1046 | − u64 phys; | |
| 1047 | 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 | 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 | − if (!ret) | |
| 1054 | − ret = kvm_pgtable_stage2_test_clear_young(&vm->pgt, ipa, PAGE_SIZE, mkold); | |
| 1053 | + return ret; | |
| 1054 | +} | |
| 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 | 1067 | guest_unlock_component(vm); |
| 1057 | − host_unlock_component(); | |
| 1058 | 1068 | |
| 1059 | 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 | 1074 | struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu); |
| 1065 | 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); | |
| 1073 | − if (!ret) | |
| 1074 | − kvm_pgtable_stage2_mkyoung(&vm->pgt, ipa, 0); | |
| 1077 | + if (pkvm_hyp_vm_is_protected(vm)) | |
| 1078 | + return -EPERM; | |
| 1075 | 1079 | |
| 1080 | + assert_host_shared_guest(vm, ipa); | |
| 1081 | + guest_lock_component(vm); | |
| 1082 | + kvm_pgtable_stage2_mkyoung(&vm->pgt, ipa, 0); | |
| 1076 | 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 | 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 | 45 | if (has_hvhe()) { |
| 43 | 46 | val |= CPACR_EL1_TTA; |
| 44 | 47 | |
| @@ -47,6 +50,8 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu) · 2 unmodified lines | ||
| 47 | 50 | if (vcpu_has_sve(vcpu)) |
| 48 | 51 | val |= CPACR_EL1_ZEN; |
| 49 | 52 | } |
| 53 | + | |
| 54 | + write_sysreg(val, cpacr_el1); | |
| 50 | 55 | } else { |
| 51 | 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 | 67 | if (!guest_owns_fp_regs()) |
| 63 | 68 | val |= CPTR_EL2_TFP; |
| 69 | + | |
| 70 | + write_sysreg(val, cptr_el2); | |
| 64 | 71 | } |
| 72 | +} | |
| 65 | 73 | |
| 66 | − if (!guest_owns_fp_regs()) | |
| 67 | − __activate_traps_fpsimd32(vcpu); | |
| 74 | +static void __deactivate_cptr_traps(struct kvm_vcpu *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 | 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 | 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 | 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 | 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 | 220 | static const exit_handler_fn hyp_exit_handlers[] = { |
| 224 | 221 | [0 ... ESR_ELx_EC_MAX] = NULL, |
| 225 | 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 | 248 | return hyp_exit_handlers; |
| 252 | 249 | } |
| 253 | 250 | |
| 254 | −/* | |
| 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) | |
| 251 | +static inline bool fixup_guest_exit(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 | 266 | if (unlikely(vcpu_is_protected(vcpu) && vcpu_mode_is_32bit(vcpu))) { |
| 268 | 267 | /* |
| 269 | 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 | 275 | *exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT); |
| 277 | 276 | *exit_code |= ARM_EXCEPTION_IL; |
| 278 | 277 | } |
| 278 | + | |
| 279 | + return __fixup_guest_exit(vcpu, exit_code, handlers); | |
| 279 | 280 | } |
| 280 | 281 | |
| 281 | 282 | /* Switch to the guest for legacy non-VHE systems */ |
| @@ -136,6 +136,16 @@ write: · 135 unmodified lines | ||
| 136 | 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 | 149 | static void __activate_traps(struct kvm_vcpu *vcpu) |
| 140 | 150 | { |
| 141 | 151 | u64 val; |
| @@ -207,7 +217,7 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) · 65 unmodified lines | ||
| 207 | 217 | */ |
| 208 | 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 | 222 | if (!arm64_kernel_unmapped_at_el0()) |
| 213 | 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 | 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 | 426 | static bool kvm_hyp_handle_tlbi_el2(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 425 | 427 | { |
| 426 | 428 | int ret = -EINVAL; |
| @@ -538,13 +540,10 @@ static const exit_handler_fn hyp_exit_handlers[] = { · 111 unmodified lines | ||
| 538 | 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; | |
| 544 | −} | |
| 545 | + synchronize_vcpu_pstate(vcpu, exit_code); | |
| 545 | 546 | |
| 546 | −static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) | |
| 547 | −{ | |
| 548 | 547 | /* |
| 549 | 548 | * If we were in HYP context on entry, adjust the PSTATE view |
| 550 | 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 | 563 | *vcpu_cpsr(vcpu) &= ~(PSR_MODE_MASK | PSR_MODE32_BIT); |
| 565 | 564 | *vcpu_cpsr(vcpu) |= mode; |
| 566 | 565 | } |
| 566 | + | |
| 567 | + return __fixup_guest_exit(vcpu, exit_code, hyp_exit_handlers); | |
| 567 | 568 | } |
| 568 | 569 | |
| 569 | 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 | 580 | sysreg_save_host_state_vhe(host_ctxt); |
| 580 | 581 | |
| 582 | + fpsimd_lazy_switch_to_guest(vcpu); | |
| 583 | + | |
| 581 | 584 | /* |
| 582 | 585 | * Note that ARM erratum 1165522 requires us to configure both stage 1 |
| 583 | 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 | 606 | __deactivate_traps(vcpu); |
| 604 | 607 | |
| 608 | + fpsimd_lazy_switch_to_host(vcpu); | |
| 609 | + | |
| 605 | 610 | sysreg_restore_host_state_vhe(host_ctxt); |
| 606 | 611 | |
| 607 | 612 | if (guest_owns_fp_regs()) |
| @@ -67,26 +67,27 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu) · 66 unmodified lines | ||
| 67 | 67 | if (!tmp) |
| 68 | 68 | return -ENOMEM; |
| 69 | 69 | |
| 70 | + swap(kvm->arch.nested_mmus, tmp); | |
| 71 | + | |
| 70 | 72 | /* |
| 71 | 73 | * If we went through a realocation, adjust the MMU back-pointers in |
| 72 | 74 | * the previously initialised kvm_pgtable structures. |
| 73 | 75 | */ |
| 74 | 76 | if (kvm->arch.nested_mmus != tmp) |
| 75 | 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 | 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 | 83 | if (ret) { |
| 82 | 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 | 87 | return ret; |
| 86 | 88 | } |
| 87 | 89 | |
| 88 | 90 | kvm->arch.nested_mmus_size = num_mmus; |
| 89 | − kvm->arch.nested_mmus = tmp; | |
| 90 | 91 | |
| 91 | 92 | return 0; |
| 92 | 93 | } |
| @@ -1452,6 +1452,16 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu, · 1451 unmodified lines | ||
| 1452 | 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 | 1465 | static s64 kvm_arm64_ftr_safe_value(u32 id, const struct arm64_ftr_bits *ftrp, |
| 1456 | 1466 | s64 new, s64 cur) |
| 1457 | 1467 | { |
| @@ -3103,9 +3113,9 @@ static const struct sys_reg_desc sys_reg_descs[] = { · 1645 unmodified lines | ||
| 3103 | 3113 | EL2_REG(CNTHP_CTL_EL2, access_arch_timer, reset_val, 0), |
| 3104 | 3114 | EL2_REG(CNTHP_CVAL_EL2, access_arch_timer, reset_val, 0), |
| 3105 | 3115 | |
| 3106 | − { SYS_DESC(SYS_CNTHV_TVAL_EL2), access_arch_timer }, | |
| 3107 | − EL2_REG(CNTHV_CTL_EL2, access_arch_timer, reset_val, 0), | |
| 3108 | − EL2_REG(CNTHV_CVAL_EL2, access_arch_timer, reset_val, 0), | |
| 3116 | + { SYS_DESC(SYS_CNTHV_TVAL_EL2), access_hv_timer }, | |
| 3117 | + EL2_REG(CNTHV_CTL_EL2, access_hv_timer, reset_val, 0), | |
| 3118 | + EL2_REG(CNTHV_CVAL_EL2, access_hv_timer, reset_val, 0), | |
| 3109 | 3119 | |
| 3110 | 3120 | { SYS_DESC(SYS_CNTKCTL_EL12), access_cntkctl_el12 }, |
| 3111 | 3121 | |
| @@ -34,9 +34,9 @@ · 33 unmodified lines | ||
| 34 | 34 | * |
| 35 | 35 | * CPU Interface: |
| 36 | 36 | * |
| 37 | − * - kvm_vgic_vcpu_init(): initialization of static data that | |
| 38 | − * doesn't depend on any sizing information or emulation type. No | |
| 39 | − * allocation is allowed there. | |
| 37 | + * - kvm_vgic_vcpu_init(): initialization of static data that doesn't depend | |
| 38 | + * on any sizing information. Private interrupts are allocated if not | |
| 39 | + * already allocated at vgic-creation time. | |
| 40 | 40 | */ |
| 41 | 41 | |
| 42 | 42 | /* EARLY INIT */ |
| @@ -58,6 +58,8 @@ void kvm_vgic_early_init(struct kvm *kvm) · 15 unmodified lines | ||
| 58 | 58 | |
| 59 | 59 | /* CREATION */ |
| 60 | 60 | |
| 61 | +static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type); | |
| 62 | + | |
| 61 | 63 | /** |
| 62 | 64 | * kvm_vgic_create: triggered by the instantiation of the VGIC device by |
| 63 | 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 | 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 | 133 | kvm->arch.vgic.in_kernel = true; |
| 116 | 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 | 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 | 203 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
| 186 | 204 | int i; |
| @@ -218,17 +236,28 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu) · 31 unmodified lines | ||
| 218 | 236 | /* PPIs */ |
| 219 | 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 | 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 | 257 | int ret; |
| 229 | 258 | |
| 230 | 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 | 261 | mutex_unlock(&vcpu->kvm->arch.config_lock); |
| 233 | 262 | |
| 234 | 263 | return ret; |
| @@ -258,7 +287,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) · 23 unmodified lines | ||
| 258 | 287 | if (!irqchip_in_kernel(vcpu->kvm)) |
| 259 | 288 | return 0; |
| 260 | 289 | |
| 261 | − ret = vgic_allocate_private_irqs(vcpu); | |
| 290 | + ret = vgic_allocate_private_irqs(vcpu, dist->vgic_model); | |
| 262 | 291 | if (ret) |
| 263 | 292 | return ret; |
| 264 | 293 | |
| @@ -295,7 +324,7 @@ int vgic_init(struct kvm *kvm) · 30 unmodified lines | ||
| 295 | 324 | { |
| 296 | 325 | struct vgic_dist *dist = &kvm->arch.vgic; |
| 297 | 326 | struct kvm_vcpu *vcpu; |
| 298 | − int ret = 0, i; | |
| 327 | + int ret = 0; | |
| 299 | 328 | unsigned long idx; |
| 300 | 329 | |
| 301 | 330 | lockdep_assert_held(&kvm->arch.config_lock); |
| @@ -315,35 +344,6 @@ int vgic_init(struct kvm *kvm) · 13 unmodified lines | ||
| 315 | 344 | if (ret) |
| 316 | 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 | 348 | * If we have GICv4.1 enabled, unconditionally request enable the |
| 349 | 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 | 162 | unsigned long next; |
| 163 | 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 | 172 | dst_p4dp = p4d_offset(dst_pgdp, start); |
| 166 | 173 | src_p4dp = p4d_offset(src_pgdp, start); |
| 167 | 174 | do { |
| @@ -76,27 +76,6 @@ extern const char *__cpu_full_name[]; · 75 unmodified lines | ||
| 76 | 76 | #define cpu_family_string() __cpu_family[raw_smp_processor_id()] |
| 77 | 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 | 79 | static inline bool cpus_are_siblings(int cpua, int cpub) |
| 101 | 80 | { |
| 102 | 81 | struct cpuinfo_loongarch *infoa = &cpu_data[cpua]; |
| @@ -77,6 +77,8 @@ extern int __cpu_logical_map[NR_CPUS]; · 76 unmodified lines | ||
| 77 | 77 | #define SMP_IRQ_WORK BIT(ACTION_IRQ_WORK) |
| 78 | 78 | #define SMP_CLEAR_VECTOR BIT(ACTION_CLEAR_VECTOR) |
| 79 | 79 | |
| 80 | +struct seq_file; | |
| 81 | + | |
| 80 | 82 | struct secondary_data { |
| 81 | 83 | unsigned long stack; |
| 82 | 84 | unsigned long thread_info; |
| @@ -18,16 +18,19 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | .align 5 |
| 20 | 20 | SYM_FUNC_START(__arch_cpu_idle) |
| 21 | − /* start of rollback region */ | |
| 22 | − LONG_L t0, tp, TI_FLAGS | |
| 23 | − nop | |
| 24 | − andi t0, t0, _TIF_NEED_RESCHED | |
| 25 | − bnez t0, 1f | |
| 26 | − nop | |
| 27 | − nop | |
| 28 | − nop | |
| 21 | + /* start of idle interrupt region */ | |
| 22 | + ori t0, zero, CSR_CRMD_IE | |
| 23 | + /* idle instruction needs irq enabled */ | |
| 24 | + csrxchg t0, t0, LOONGARCH_CSR_CRMD | |
| 25 | + /* | |
| 26 | + * If an interrupt lands here; between enabling interrupts above and | |
| 27 | + * going idle on the next instruction, we must *NOT* go idle since the | |
| 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 | 32 | idle 0 |
| 30 | − /* end of rollback region */ | |
| 33 | + /* end of idle interrupt region */ | |
| 31 | 34 | 1: jr ra |
| 32 | 35 | SYM_FUNC_END(__arch_cpu_idle) |
| 33 | 36 | |
| @@ -35,11 +38,10 @@ SYM_CODE_START(handle_vint) · 1 unmodified line | ||
| 35 | 38 | UNWIND_HINT_UNDEFINED |
| 36 | 39 | BACKUP_T0T1 |
| 37 | 40 | SAVE_ALL |
| 38 | − la_abs t1, __arch_cpu_idle | |
| 41 | + la_abs t1, 1b | |
| 39 | 42 | LONG_L t0, sp, PT_ERA |
| 40 | − /* 32 byte rollback region */ | |
| 41 | − ori t0, t0, 0x1f | |
| 42 | − xori t0, t0, 0x1f | |
| 43 | + /* 3 instructions idle interrupt region */ | |
| 44 | + ori t0, t0, 0b1100 | |
| 43 | 45 | bne t0, t1, 1f |
| 44 | 46 | LONG_S t0, sp, PT_ERA |
| 45 | 47 | 1: move a0, sp |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | void __cpuidle arch_cpu_idle(void) |
| 13 | 13 | { |
| 14 | − raw_local_irq_enable(); | |
| 15 | − __arch_cpu_idle(); /* idle instruction needs irq enabled */ | |
| 14 | + __arch_cpu_idle(); | |
| 16 | 15 | raw_local_irq_disable(); |
| 17 | 16 | } |
| @@ -13,28 +13,12 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <asm/processor.h> |
| 14 | 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 | 16 | static int show_cpuinfo(struct seq_file *m, void *v) |
| 32 | 17 | { |
| 33 | 18 | unsigned long n = (unsigned long) v - 1; |
| 34 | 19 | unsigned int isa = cpu_data[n].isa_level; |
| 35 | 20 | unsigned int version = cpu_data[n].processor_id & 0xff; |
| 36 | 21 | unsigned int fp_version = cpu_data[n].fpu_vers; |
| 37 | − struct proc_cpuinfo_notifier_args proc_cpuinfo_notifier_args; | |
| 38 | 22 | |
| 39 | 23 | #ifdef CONFIG_SMP |
| 40 | 24 | if (!cpu_online(n)) |
| @@ -91,20 +75,13 @@ static int show_cpuinfo(struct seq_file *m, void *v) · 50 unmodified lines | ||
| 91 | 75 | if (cpu_has_lbt_mips) seq_printf(m, " lbt_mips"); |
| 92 | 76 | seq_printf(m, "\n"); |
| 93 | 77 | |
| 94 | − seq_printf(m, "Hardware Watchpoint\t: %s", | |
| 95 | − cpu_has_watch ? "yes, " : "no\n"); | |
| 78 | + seq_printf(m, "Hardware Watchpoint\t: %s", str_yes_no(cpu_has_watch)); | |
| 96 | 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 | 81 | cpu_data[n].watch_ireg_count, cpu_data[n].watch_dreg_count); |
| 99 | 82 | } |
| 100 | 83 | |
| 101 | − proc_cpuinfo_notifier_args.m = m; | |
| 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"); | |
| 84 | + seq_printf(m, "\n\n"); | |
| 108 | 85 | |
| 109 | 86 | return 0; |
| 110 | 87 | } |
| @@ -33,7 +33,7 @@ void machine_halt(void) · 32 unmodified lines | ||
| 33 | 33 | console_flush_on_panic(CONSOLE_FLUSH_PENDING); |
| 34 | 34 | |
| 35 | 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 | 53 | #endif |
| 54 | 54 | |
| 55 | 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 | 74 | acpi_reboot(); |
| 75 | 75 | |
| 76 | 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 | 303 | * TOE=0: Trap on Exception. |
| 304 | 304 | * TIT=0: Trap on Timer. |
| 305 | 305 | */ |
| 306 | − if (env & CSR_GCFG_GCIP_ALL) | |
| 306 | + if (env & CSR_GCFG_GCIP_SECURE) | |
| 307 | 307 | gcfg |= CSR_GCFG_GCI_SECURE; |
| 308 | − if (env & CSR_GCFG_MATC_ROOT) | |
| 308 | + if (env & CSR_GCFG_MATP_ROOT) | |
| 309 | 309 | gcfg |= CSR_GCFG_MATC_ROOT; |
| 310 | 310 | |
| 311 | 311 | write_csr_gcfg(gcfg); |
| @@ -85,7 +85,7 @@ · 84 unmodified lines | ||
| 85 | 85 | * Guest CRMD comes from separate GCSR_CRMD register |
| 86 | 86 | */ |
| 87 | 87 | ori t0, zero, CSR_PRMD_PIE |
| 88 | − csrxchg t0, t0, LOONGARCH_CSR_PRMD | |
| 88 | + csrwr t0, LOONGARCH_CSR_PRMD | |
| 89 | 89 | |
| 90 | 90 | /* Set PVM bit to setup ertn to guest context */ |
| 91 | 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 | 1549 | /* Restore timer state regardless */ |
| 1550 | 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 | 1551 | kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu); |
| 1555 | 1552 | |
| 1556 | 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 | 25 | const u64 *ptr; |
| 26 | 26 | u64 data, sum64 = 0; |
| 27 | 27 | |
| 28 | − if (unlikely(len == 0)) | |
| 28 | + if (unlikely(len <= 0)) | |
| 29 | 29 | return 0; |
| 30 | 30 | |
| 31 | 31 | offset = (unsigned long)buff & 7; |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | * Copyright (C) 2024 Loongson Technology Corporation Limited |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | +#include <linux/memblock.h> | |
| 6 | 7 | #include <linux/pagewalk.h> |
| 7 | 8 | #include <linux/pgtable.h> |
| 8 | 9 | #include <asm/set_memory.h> |
| @@ -167,7 +168,7 @@ bool kernel_page_present(struct page *page) · 158 unmodified lines | ||
| 167 | 168 | unsigned long addr = (unsigned long)page_address(page); |
| 168 | 169 | |
| 169 | 170 | if (addr < vm_map_base) |
| 170 | − return true; | |
| 171 | + return memblock_is_memory(__pa(addr)); | |
| 171 | 172 | |
| 172 | 173 | pgd = pgd_offset_k(addr); |
| 173 | 174 | if (pgd_none(pgdp_get(pgd))) |
| @@ -27,8 +27,8 @@ · 26 unmodified lines | ||
| 27 | 27 | */ |
| 28 | 28 | struct pt_regs { |
| 29 | 29 | #ifdef CONFIG_32BIT |
| 30 | − /* Pad bytes for argument save space on the stack. */ | |
| 31 | − unsigned long pad0[8]; | |
| 30 | + /* Saved syscall stack arguments; entries 0-3 unused. */ | |
| 31 | + unsigned long args[8]; | |
| 32 | 32 | #endif |
| 33 | 33 | |
| 34 | 34 | /* Saved main processor registers. */ |
| @@ -57,37 +57,21 @@ static inline void mips_syscall_update_nr(struct task_struct *task, · 56 unmodified lines | ||
| 57 | 57 | static inline void mips_get_syscall_arg(unsigned long *arg, |
| 58 | 58 | struct task_struct *task, struct pt_regs *regs, unsigned int n) |
| 59 | 59 | { |
| 60 | − unsigned long usp __maybe_unused = regs->regs[29]; | |
| 61 | − | |
| 60 | +#ifdef CONFIG_32BIT | |
| 62 | 61 | switch (n) { |
| 63 | 62 | case 0: case 1: case 2: case 3: |
| 64 | 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 | 64 | return; |
| 72 | −#endif | |
| 73 | − | |
| 74 | −#ifdef CONFIG_64BIT | |
| 75 | 65 | case 4: case 5: case 6: case 7: |
| 76 | −#ifdef CONFIG_MIPS32_O32 | |
| 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 | − | |
| 66 | + *arg = regs->args[n]; | |
| 83 | 67 | return; |
| 84 | −#endif | |
| 85 | − | |
| 86 | − default: | |
| 87 | − BUG(); | |
| 88 | 68 | } |
| 89 | − | |
| 90 | − unreachable(); | |
| 69 | +#else | |
| 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 | 77 | static inline long syscall_get_error(struct task_struct *task, |
| @@ -27,6 +27,12 @@ void output_ptreg_defines(void); · 26 unmodified lines | ||
| 27 | 27 | void output_ptreg_defines(void) |
| 28 | 28 | { |
| 29 | 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 | 36 | OFFSET(PT_R0, pt_regs, regs[0]); |
| 31 | 37 | OFFSET(PT_R1, pt_regs, regs[1]); |
| 32 | 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 | 64 | load_a7: user_lw(t8, 28(t0)) # argument #8 from usp |
| 65 | 65 | loads_done: |
| 66 | 66 | |
| 67 | − sw t5, 16(sp) # argument #5 to ksp | |
| 68 | − sw t6, 20(sp) # argument #6 to ksp | |
| 69 | − sw t7, 24(sp) # argument #7 to ksp | |
| 70 | − sw t8, 28(sp) # argument #8 to ksp | |
| 67 | + sw t5, PT_ARG4(sp) # argument #5 to ksp | |
| 68 | + sw t6, PT_ARG5(sp) # argument #6 to ksp | |
| 69 | + sw t7, PT_ARG6(sp) # argument #7 to ksp | |
| 70 | + sw t8, PT_ARG7(sp) # argument #8 to ksp | |
| 71 | 71 | .set pop |
| 72 | 72 | |
| 73 | 73 | .section __ex_table,"a" |
| @@ -77,9 +77,17 @@ · 76 unmodified lines | ||
| 77 | 77 | /* |
| 78 | 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 | 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 | 92 | #define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ |
| 85 | 93 | do { \ |
| @@ -108,7 +108,7 @@ static int text_area_cpu_up(unsigned int cpu) · 107 unmodified lines | ||
| 108 | 108 | unsigned long addr; |
| 109 | 109 | int err; |
| 110 | 110 | |
| 111 | − area = get_vm_area(PAGE_SIZE, VM_ALLOC); | |
| 111 | + area = get_vm_area(PAGE_SIZE, 0); | |
| 112 | 112 | if (!area) { |
| 113 | 113 | WARN_ONCE(1, "Failed to create text area for cpu %d\n", |
| 114 | 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 | 494 | orig_mm = start_using_temp_mm(patching_mm); |
| 495 | 495 | |
| 496 | + kasan_disable_current(); | |
| 496 | 497 | err = __patch_instructions(patch_addr, code, len, repeat_instr); |
| 498 | + kasan_enable_current(); | |
| 497 | 499 | |
| 498 | 500 | /* context synchronisation performed by __patch_instructions */ |
| 499 | 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 | 75 | srs = (hwirq >> msi_data->srs_shift) & MSI_SRS_MASK; |
| 76 | 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 | 740 | CONFIG_IMA_DEFAULT_HASH_SHA256=y |
| 741 | 741 | CONFIG_IMA_WRITE_POLICY=y |
| 742 | 742 | CONFIG_IMA_APPRAISE=y |
| 743 | −CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" | |
| 744 | 743 | CONFIG_BUG_ON_DATA_CORRUPTION=y |
| 745 | 744 | CONFIG_CRYPTO_USER=m |
| 746 | 745 | # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set |
| @@ -725,7 +725,6 @@ CONFIG_IMA=y · 724 unmodified lines | ||
| 725 | 725 | CONFIG_IMA_DEFAULT_HASH_SHA256=y |
| 726 | 726 | CONFIG_IMA_WRITE_POLICY=y |
| 727 | 727 | CONFIG_IMA_APPRAISE=y |
| 728 | −CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" | |
| 729 | 728 | CONFIG_BUG_ON_DATA_CORRUPTION=y |
| 730 | 729 | CONFIG_CRYPTO_FIPS=y |
| 731 | 730 | CONFIG_CRYPTO_USER=m |
| @@ -62,7 +62,6 @@ CONFIG_ZFCP=y · 61 unmodified lines | ||
| 62 | 62 | # CONFIG_INOTIFY_USER is not set |
| 63 | 63 | # CONFIG_MISC_FILESYSTEMS is not set |
| 64 | 64 | # CONFIG_NETWORK_FILESYSTEMS is not set |
| 65 | −CONFIG_LSM="yama,loadpin,safesetid,integrity" | |
| 66 | 65 | # CONFIG_ZLIB_DFLTCC is not set |
| 67 | 66 | CONFIG_XZ_DEC_MICROLZMA=y |
| 68 | 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 | 53 | unsigned long mask; |
| 54 | 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 | 61 | addr = (const volatile unsigned char *)ptr; |
| 58 | 62 | addr += (nr ^ (BITS_PER_LONG - BITS_PER_BYTE)) / BITS_PER_BYTE; |
| 59 | 63 | mask = 1UL << (nr & (BITS_PER_BYTE - 1)); |
| @@ -23,7 +23,6 @@ · 22 unmodified lines | ||
| 23 | 23 | /** |
| 24 | 24 | * struct gmap_struct - guest address space |
| 25 | 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 | 26 | * @mm: pointer to the parent mm_struct |
| 28 | 27 | * @guest_to_host: radix tree with guest to host address translation |
| 29 | 28 | * @host_to_guest: radix tree with pointer to segment table entries |
| @@ -35,7 +34,6 @@ · 5 unmodified lines | ||
| 35 | 34 | * @guest_handle: protected virtual machine handle for the ultravisor |
| 36 | 35 | * @host_to_rmap: radix tree with gmap_rmap lists |
| 37 | 36 | * @children: list of shadow gmap structures |
| 38 | − * @pt_list: list of all page tables used in the shadow guest address space | |
| 39 | 37 | * @shadow_lock: spinlock to protect the shadow gmap list |
| 40 | 38 | * @parent: pointer to the parent gmap for shadow guest address spaces |
| 41 | 39 | * @orig_asce: ASCE for which the shadow page table has been created |
| @@ -45,7 +43,6 @@ · 3 unmodified lines | ||
| 45 | 43 | */ |
| 46 | 44 | struct gmap { |
| 47 | 45 | struct list_head list; |
| 48 | − struct list_head crst_list; | |
| 49 | 46 | struct mm_struct *mm; |
| 50 | 47 | struct radix_tree_root guest_to_host; |
| 51 | 48 | struct radix_tree_root host_to_guest; |
| @@ -61,7 +58,6 @@ struct gmap { · 9 unmodified lines | ||
| 61 | 58 | /* Additional data for shadow guest address spaces */ |
| 62 | 59 | struct radix_tree_root host_to_rmap; |
| 63 | 60 | struct list_head children; |
| 64 | − struct list_head pt_list; | |
| 65 | 61 | spinlock_t shadow_lock; |
| 66 | 62 | struct gmap *parent; |
| 67 | 63 | unsigned long orig_asce; |
| @@ -106,23 +102,21 @@ struct gmap *gmap_create(struct mm_struct *mm, unsigned long limit); · 38 unmodified lines | ||
| 106 | 102 | void gmap_remove(struct gmap *gmap); |
| 107 | 103 | struct gmap *gmap_get(struct gmap *gmap); |
| 108 | 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 | 108 | int gmap_map_segment(struct gmap *gmap, unsigned long from, |
| 111 | 109 | unsigned long to, unsigned long len); |
| 112 | 110 | int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len); |
| 113 | 111 | unsigned long __gmap_translate(struct gmap *, unsigned long gaddr); |
| 114 | −unsigned long gmap_translate(struct gmap *, unsigned long gaddr); | |
| 115 | 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 | 113 | void gmap_discard(struct gmap *, unsigned long from, unsigned long to); |
| 118 | 114 | void __gmap_zap(struct gmap *, unsigned long gaddr); |
| 119 | 115 | void gmap_unlink(struct mm_struct *, unsigned long *table, unsigned long vmaddr); |
| 120 | 116 | |
| 121 | 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, | |
| 124 | − int edat_level); | |
| 125 | −int gmap_shadow_valid(struct gmap *sg, unsigned long asce, int edat_level); | |
| 119 | +void gmap_unshadow(struct gmap *sg); | |
| 126 | 120 | int gmap_shadow_r2t(struct gmap *sg, unsigned long saddr, unsigned long r2t, |
| 127 | 121 | int fake); |
| 128 | 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 | 125 | int fake); |
| 132 | 126 | int gmap_shadow_pgt(struct gmap *sg, unsigned long saddr, unsigned long pgt, |
| 133 | 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 | 128 | int gmap_shadow_page(struct gmap *sg, unsigned long saddr, pte_t pte); |
| 137 | 129 | |
| 138 | 130 | void gmap_register_pte_notifier(struct gmap_notifier *); |
| 139 | 131 | void gmap_unregister_pte_notifier(struct gmap_notifier *); |
| 140 | 132 | |
| 141 | −int gmap_mprotect_notify(struct gmap *, unsigned long start, | |
| 142 | − unsigned long len, int prot); | |
| 133 | +int gmap_protect_one(struct gmap *gmap, unsigned long gaddr, int prot, unsigned long bits); | |
| 143 | 134 | |
| 144 | 135 | void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4], |
| 145 | 136 | unsigned long gaddr, unsigned long vmaddr); |
| 146 | 137 | int s390_disable_cow_sharing(void); |
| 147 | −void s390_unlist_old_asce(struct gmap *gmap); | |
| 148 | 138 | int s390_replace_asce(struct gmap *gmap); |
| 149 | 139 | void s390_uv_destroy_pfns(unsigned long count, unsigned long *pfns); |
| 150 | 140 | int __s390_uv_destroy_range(struct mm_struct *mm, unsigned long start, |
| 151 | 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 | 146 | * s390_uv_destroy_range - Destroy a range of pages in the given mm. |
| @@ -30,6 +30,8 @@ · 29 unmodified lines | ||
| 30 | 30 | #define KVM_S390_ESCA_CPU_SLOTS 248 |
| 31 | 31 | #define KVM_MAX_VCPUS 255 |
| 32 | 32 | |
| 33 | +#define KVM_INTERNAL_MEM_SLOTS 1 | |
| 34 | + | |
| 33 | 35 | /* |
| 34 | 36 | * These seem to be used for allocating ->chip in the routing table, which we |
| 35 | 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 | 933 | u8 reserved928[0x1000 - 0x928]; /* 0x0928 */ |
| 932 | 934 | }; |
| 933 | 935 | |
| 936 | +struct vsie_page; | |
| 937 | + | |
| 934 | 938 | struct kvm_s390_vsie { |
| 935 | 939 | struct mutex mutex; |
| 936 | 940 | struct radix_tree_root addr_to_page; |
| 937 | 941 | int page_count; |
| 938 | 942 | int next; |
| 939 | − struct page *pages[KVM_MAX_VCPUS]; | |
| 943 | + struct vsie_page *pages[KVM_MAX_VCPUS]; | |
| 940 | 944 | }; |
| 941 | 945 | |
| 942 | 946 | struct kvm_s390_gisa_iam { |
| @@ -420,9 +420,10 @@ void setup_protection_map(void); · 419 unmodified lines | ||
| 420 | 420 | #define PGSTE_HC_BIT 0x0020000000000000UL |
| 421 | 421 | #define PGSTE_GR_BIT 0x0004000000000000UL |
| 422 | 422 | #define PGSTE_GC_BIT 0x0002000000000000UL |
| 423 | −#define PGSTE_UC_BIT 0x0000800000000000UL /* user dirty (migration) */ | |
| 424 | −#define PGSTE_IN_BIT 0x0000400000000000UL /* IPTE notify bit */ | |
| 425 | −#define PGSTE_VSIE_BIT 0x0000200000000000UL /* ref'd in a shadow table */ | |
| 423 | +#define PGSTE_ST2_MASK 0x0000ffff00000000UL | |
| 424 | +#define PGSTE_UC_BIT 0x0000000000008000UL /* user dirty (migration) */ | |
| 425 | +#define PGSTE_IN_BIT 0x0000000000004000UL /* IPTE notify bit */ | |
| 426 | +#define PGSTE_VSIE_BIT 0x0000000000002000UL /* ref'd in a shadow table */ | |
| 426 | 427 | |
| 427 | 428 | /* Guest Page State used for virtualization */ |
| 428 | 429 | #define _PGSTE_GPS_ZERO 0x0000000080000000UL |
| @@ -2007,4 +2008,18 @@ extern void s390_reset_cmma(struct mm_struct *mm); · 1578 unmodified lines | ||
| 2007 | 2008 | #define pmd_pgtable(pmd) \ |
| 2008 | 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 | 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 | 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 | 631 | int uv_destroy_folio(struct folio *folio); |
| 634 | 632 | int uv_destroy_pte(pte_t pte); |
| 635 | 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 | 638 | void setup_uv(void); |
| 639 | 639 | |
| @@ -19,19 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <asm/sections.h> |
| 20 | 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 | 22 | /* the bootdata_preserved fields come from ones in arch/s390/boot/uv.c */ |
| 36 | 23 | int __bootdata_preserved(prot_virt_guest); |
| 37 | 24 | EXPORT_SYMBOL(prot_virt_guest); |
| @@ -159,6 +146,7 @@ int uv_destroy_folio(struct folio *folio) · 121 unmodified lines | ||
| 159 | 146 | folio_put(folio); |
| 160 | 147 | return rc; |
| 161 | 148 | } |
| 149 | +EXPORT_SYMBOL(uv_destroy_folio); | |
| 162 | 150 | |
| 163 | 151 | /* |
| 164 | 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 | 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 | 168 | struct uv_cb_cfs uvcb = { |
| 181 | 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 | 175 | return -EINVAL; |
| 188 | 176 | return 0; |
| 189 | 177 | } |
| 178 | +EXPORT_SYMBOL_GPL(uv_convert_from_secure); | |
| 190 | 179 | |
| 191 | 180 | /* |
| 192 | 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 | 185 | int rc; |
| 197 | 186 | |
| @@ -206,6 +195,7 @@ static int uv_convert_from_secure_folio(struct folio *folio) · 8 unmodified lines | ||
| 206 | 195 | folio_put(folio); |
| 207 | 196 | return rc; |
| 208 | 197 | } |
| 198 | +EXPORT_SYMBOL_GPL(uv_convert_from_secure_folio); | |
| 209 | 199 | |
| 210 | 200 | /* |
| 211 | 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 | 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 | 250 | int expected, cc = 0; |
| 243 | 251 | |
| 252 | + if (folio_test_large(folio)) | |
| 253 | + return -E2BIG; | |
| 244 | 254 | if (folio_test_writeback(folio)) |
| 245 | − return -EAGAIN; | |
| 246 | − expected = expected_folio_refs(folio); | |
| 255 | + return -EBUSY; | |
| 256 | + expected = expected_folio_refs(folio) + 1; | |
| 247 | 257 | if (!folio_ref_freeze(folio, expected)) |
| 248 | 258 | return -EBUSY; |
| 249 | 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 | 277 | return -EAGAIN; |
| 268 | 278 | return uvcb->rc == 0x10a ? -ENXIO : -EINVAL; |
| 269 | 279 | } |
| 270 | − | |
| 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); | |
| 280 | +EXPORT_SYMBOL_GPL(make_folio_secure); | |
| 515 | 281 | |
| 516 | 282 | /* |
| 517 | 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 | 8 | ccflags-y := -Ivirt/kvm -Iarch/s390/kvm |
| 9 | 9 | |
| 10 | 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 | 13 | kvm-$(CONFIG_VFIO_PCI_ZDEV_KVM) += pci.o |
| 14 | 14 | obj-$(CONFIG_KVM) += kvm.o |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <asm/gmap.h> |
| 17 | 17 | #include <asm/dat-bits.h> |
| 18 | 18 | #include "kvm-s390.h" |
| 19 | +#include "gmap.h" | |
| 19 | 20 | #include "gaccess.h" |
| 20 | 21 | |
| 21 | 22 | /* |
| @@ -1392,6 +1393,44 @@ shadow_pgt: · 1370 unmodified lines | ||
| 1392 | 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 | 1435 | * kvm_s390_shadow_fault - handle fault on a shadow page table |
| 1397 | 1436 | * @vcpu: virtual cpu |
| @@ -1415,6 +1454,9 @@ int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg, · 17 unmodified lines | ||
| 1415 | 1454 | int dat_protection, fake; |
| 1416 | 1455 | int rc; |
| 1417 | 1456 | |
| 1457 | + if (KVM_BUG_ON(!gmap_is_shadow(sg), vcpu->kvm)) | |
| 1458 | + return -EFAULT; | |
| 1459 | + | |
| 1418 | 1460 | mmap_read_lock(sg->mm); |
| 1419 | 1461 | /* |
| 1420 | 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 | 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 | 1469 | if (rc) |
| 1428 | 1470 | rc = kvm_s390_shadow_tables(sg, saddr, &pgt, &dat_protection, |
| 1429 | 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 | 21 | #include "gaccess.h" |
| 22 | 22 | #include "trace.h" |
| 23 | 23 | #include "trace-s390.h" |
| 24 | +#include "gmap.h" | |
| 24 | 25 | |
| 25 | 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 | 368 | reg2, &srcaddr, GACC_FETCH, 0); |
| 368 | 369 | if (rc) |
| 369 | 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 | 372 | if (rc != 0) |
| 372 | 373 | return rc; |
| 373 | 374 | |
| @@ -376,7 +377,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu) · 2 unmodified lines | ||
| 376 | 377 | reg1, &dstaddr, GACC_STORE, 0); |
| 377 | 378 | if (rc) |
| 378 | 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 | 381 | if (rc != 0) |
| 381 | 382 | return rc; |
| 382 | 383 | |
| @@ -549,7 +550,7 @@ static int handle_pv_uvc(struct kvm_vcpu *vcpu) · 166 unmodified lines | ||
| 549 | 550 | * If the unpin did not succeed, the guest will exit again for the UVC |
| 550 | 551 | * and we will retry the unpin. |
| 551 | 552 | */ |
| 552 | − if (rc == -EINVAL) | |
| 553 | + if (rc == -EINVAL || rc == -ENXIO) | |
| 553 | 554 | return 0; |
| 554 | 555 | /* |
| 555 | 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 | 2893 | struct kvm_kernel_irq_routing_entry *e, |
| 2894 | 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 | 2899 | switch (ue->type) { |
| 2899 | 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 | 2902 | if (kvm_is_ucontrol(kvm)) |
| 2902 | 2903 | return -EINVAL; |
| 2903 | 2904 | e->set = set_adapter_int; |
| 2904 | − uaddr = gmap_translate(kvm->arch.gmap, ue->u.adapter.summary_addr); | |
| 2905 | − if (uaddr == -EFAULT) | |
| 2906 | − return -EFAULT; | |
| 2907 | − e->adapter.summary_addr = uaddr; | |
| 2908 | − uaddr = gmap_translate(kvm->arch.gmap, ue->u.adapter.ind_addr); | |
| 2909 | − if (uaddr == -EFAULT) | |
| 2905 | + | |
| 2906 | + idx = srcu_read_lock(&kvm->srcu); | |
| 2907 | + uaddr_s = gpa_to_hva(kvm, ue->u.adapter.summary_addr); | |
| 2908 | + uaddr_i = gpa_to_hva(kvm, ue->u.adapter.ind_addr); | |
| 2909 | + srcu_read_unlock(&kvm->srcu, idx); | |
| 2910 | + | |
| 2911 | + if (kvm_is_error_hva(uaddr_s) || kvm_is_error_hva(uaddr_i)) | |
| 2910 | 2912 | return -EFAULT; |
| 2911 | − e->adapter.ind_addr = uaddr; | |
| 2913 | + e->adapter.summary_addr = uaddr_s; | |
| 2914 | + e->adapter.ind_addr = uaddr_i; | |
| 2912 | 2915 | e->adapter.summary_offset = ue->u.adapter.summary_offset; |
| 2913 | 2916 | e->adapter.ind_offset = ue->u.adapter.ind_offset; |
| 2914 | 2917 | e->adapter.adapter_id = ue->u.adapter.adapter_id; |
| @@ -50,6 +50,7 @@ · 49 unmodified lines | ||
| 50 | 50 | #include "kvm-s390.h" |
| 51 | 51 | #include "gaccess.h" |
| 52 | 52 | #include "pci.h" |
| 53 | +#include "gmap.h" | |
| 53 | 54 | |
| 54 | 55 | #define CREATE_TRACE_POINTS |
| 55 | 56 | #include "trace.h" |
| @@ -3428,8 +3429,20 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) · 3372 unmodified lines | ||
| 3428 | 3429 | VM_EVENT(kvm, 3, "vm created with type %lu", type); |
| 3429 | 3430 | |
| 3430 | 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 | 3440 | kvm->arch.gmap = NULL; |
| 3432 | 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 | 3446 | } else { |
| 3434 | 3447 | if (sclp.hamax == U64_MAX) |
| 3435 | 3448 | kvm->arch.mem_limit = TASK_SIZE_MAX; |
| @@ -4498,6 +4511,75 @@ static bool ibs_enabled(struct kvm_vcpu *vcpu) · 1062 unmodified lines | ||
| 4498 | 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 | 4583 | static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu) |
| 4502 | 4584 | { |
| 4503 | 4585 | retry: |
| @@ -4513,9 +4595,8 @@ retry: · 9 unmodified lines | ||
| 4513 | 4595 | */ |
| 4514 | 4596 | if (kvm_check_request(KVM_REQ_REFRESH_GUEST_PREFIX, vcpu)) { |
| 4515 | 4597 | int rc; |
| 4516 | − rc = gmap_mprotect_notify(vcpu->arch.gmap, | |
| 4517 | − kvm_s390_get_prefix(vcpu), | |
| 4518 | − PAGE_SIZE * 2, PROT_WRITE); | |
| 4598 | + | |
| 4599 | + rc = kvm_s390_mprotect_notify_prefix(vcpu); | |
| 4519 | 4600 | if (rc) { |
| 4520 | 4601 | kvm_make_request(KVM_REQ_REFRESH_GUEST_PREFIX, vcpu); |
| 4521 | 4602 | return rc; |
| @@ -4766,11 +4847,111 @@ static int vcpu_post_run_addressing_exception(struct kvm_vcpu *vcpu) · 244 unmodified lines | ||
| 4766 | 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 | 4951 | static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) |
| 4770 | 4952 | { |
| 4771 | 4953 | unsigned int flags = 0; |
| 4772 | 4954 | unsigned long gaddr; |
| 4773 | − int rc = 0; | |
| 4774 | 4955 | |
| 4775 | 4956 | gaddr = current->thread.gmap_teid.addr * PAGE_SIZE; |
| 4776 | 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 | 4962 | vcpu->stat.exit_null++; |
| 4782 | 4963 | break; |
| 4783 | 4964 | case PGM_NON_SECURE_STORAGE_ACCESS: |
| 4784 | − KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, | |
| 4785 | − "Unexpected program interrupt 0x%x, TEID 0x%016lx", | |
| 4786 | − current->thread.gmap_int_code, current->thread.gmap_teid.val); | |
| 4965 | + kvm_s390_assert_primary_as(vcpu); | |
| 4787 | 4966 | /* |
| 4788 | 4967 | * This is normal operation; a page belonging to a protected |
| 4789 | 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 | 4973 | break; |
| 4795 | 4974 | case PGM_SECURE_STORAGE_ACCESS: |
| 4796 | 4975 | case PGM_SECURE_STORAGE_VIOLATION: |
| 4797 | − KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, | |
| 4798 | − "Unexpected program interrupt 0x%x, TEID 0x%016lx", | |
| 4799 | − current->thread.gmap_int_code, current->thread.gmap_teid.val); | |
| 4976 | + kvm_s390_assert_primary_as(vcpu); | |
| 4800 | 4977 | /* |
| 4801 | 4978 | * This can happen after a reboot with asynchronous teardown; |
| 4802 | 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 | 5002 | case PGM_REGION_FIRST_TRANS: |
| 4826 | 5003 | case PGM_REGION_SECOND_TRANS: |
| 4827 | 5004 | case PGM_REGION_THIRD_TRANS: |
| 4828 | − KVM_BUG(current->thread.gmap_teid.as != PSW_BITS_AS_PRIMARY, vcpu->kvm, | |
| 4829 | − "Unexpected program interrupt 0x%x, TEID 0x%016lx", | |
| 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; | |
| 5005 | + kvm_s390_assert_primary_as(vcpu); | |
| 5006 | + return vcpu_dat_fault_handler(vcpu, gaddr, flags); | |
| 4855 | 5007 | default: |
| 4856 | 5008 | KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx", |
| 4857 | 5009 | current->thread.gmap_int_code, current->thread.gmap_teid.val); |
| 4858 | 5010 | send_sig(SIGSEGV, current, 0); |
| 4859 | 5011 | break; |
| 4860 | 5012 | } |
| 4861 | − return rc; | |
| 5013 | + return 0; | |
| 4862 | 5014 | } |
| 4863 | 5015 | |
| 4864 | 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 | 5890 | #endif |
| 5739 | 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 | 5895 | break; |
| 5742 | 5896 | } |
| 5743 | 5897 | case KVM_ENABLE_CAP: |
| @@ -5853,7 +6007,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, · 109 unmodified lines | ||
| 5853 | 6007 | { |
| 5854 | 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 | 6011 | return -EINVAL; |
| 5858 | 6012 | |
| 5859 | 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 | 6060 | int rc = 0; |
| 5907 | 6061 | |
| 6062 | + if (kvm_is_ucontrol(kvm)) | |
| 6063 | + return; | |
| 6064 | + | |
| 5908 | 6065 | switch (change) { |
| 5909 | 6066 | case KVM_MR_DELETE: |
| 5910 | 6067 | rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE, |
| @@ -20,6 +20,8 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <asm/processor.h> |
| 21 | 21 | #include <asm/sclp.h> |
| 22 | 22 | |
| 23 | +#define KVM_S390_UCONTROL_MEMSLOT (KVM_USER_MEM_SLOTS + 0) | |
| 24 | + | |
| 23 | 25 | static inline void kvm_s390_fpu_store(struct kvm_run *run) |
| 24 | 26 | { |
| 25 | 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 | 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 | 293 | /* implemented in pv.c */ |
| 283 | 294 | int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc); |
| 284 | 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 | 419 | void kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm); |
| 409 | 420 | __u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu); |
| 410 | 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 | 431 | /* implemented in diag.c */ |
| 413 | 432 | int kvm_s390_handle_diag(struct kvm_vcpu *vcpu); |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/sched/mm.h> |
| 18 | 18 | #include <linux/mmu_notifier.h> |
| 19 | 19 | #include "kvm-s390.h" |
| 20 | +#include "gmap.h" | |
| 20 | 21 | |
| 21 | 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 | 639 | .tweak[1] = offset, |
| 639 | 640 | }; |
| 640 | 641 | int ret = gmap_make_secure(kvm->arch.gmap, addr, &uvcb); |
| 642 | + unsigned long vmaddr; | |
| 643 | + bool unlocked; | |
| 641 | 644 | |
| 642 | 645 | *rc = uvcb.header.rc; |
| 643 | 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 | 664 | if (ret && ret != -EAGAIN) |
| 646 | 665 | KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x", |
| 647 | 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 | 679 | KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: start addr %lx size %lx", |
| 661 | 680 | addr, size); |
| 662 | 681 | |
| 682 | + guard(srcu)(&kvm->srcu); | |
| 683 | + | |
| 663 | 684 | while (offset < size) { |
| 664 | 685 | ret = unpack_one(kvm, addr, tweak, offset, rc, rrc); |
| 665 | 686 | if (ret == -EAGAIN) { |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/bitmap.h> |
| 14 | 14 | #include <linux/sched/signal.h> |
| 15 | 15 | #include <linux/io.h> |
| 16 | +#include <linux/mman.h> | |
| 16 | 17 | |
| 17 | 18 | #include <asm/gmap.h> |
| 18 | 19 | #include <asm/mmu_context.h> |
| @@ -22,6 +23,11 @@ · 3 unmodified lines | ||
| 22 | 23 | #include <asm/facility.h> |
| 23 | 24 | #include "kvm-s390.h" |
| 24 | 25 | #include "gaccess.h" |
| 26 | +#include "gmap.h" | |
| 27 | + | |
| 28 | +enum vsie_page_flags { | |
| 29 | + VSIE_PAGE_IN_USE = 0, | |
| 30 | +}; | |
| 25 | 31 | |
| 26 | 32 | struct vsie_page { |
| 27 | 33 | struct kvm_s390_sie_block scb_s; /* 0x0000 */ |
| @@ -46,7 +52,18 @@ struct vsie_page { · 18 unmodified lines | ||
| 46 | 52 | gpa_t gvrd_gpa; /* 0x0240 */ |
| 47 | 53 | gpa_t riccbd_gpa; /* 0x0248 */ |
| 48 | 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 | 67 | struct kvm_s390_crypto_cb crycb; /* 0x0700 */ |
| 51 | 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 | 601 | struct kvm *kvm = gmap->private; |
| 585 | 602 | struct vsie_page *cur; |
| 586 | 603 | unsigned long prefix; |
| 587 | − struct page *page; | |
| 588 | 604 | int i; |
| 589 | 605 | |
| 590 | 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 | 610 | * therefore we can safely reference them all the time. |
| 595 | 611 | */ |
| 596 | 612 | for (i = 0; i < kvm->arch.vsie.page_count; i++) { |
| 597 | − page = READ_ONCE(kvm->arch.vsie.pages[i]); | |
| 598 | − if (!page) | |
| 613 | + cur = READ_ONCE(kvm->arch.vsie.pages[i]); | |
| 614 | + if (!cur) | |
| 599 | 615 | continue; |
| 600 | − cur = page_to_virt(page); | |
| 601 | 616 | if (READ_ONCE(cur->gmap) != gmap) |
| 602 | 617 | continue; |
| 603 | 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 | 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 | 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 | 1384 | static struct vsie_page *get_vsie_page(struct kvm *kvm, unsigned long addr) |
| 1356 | 1385 | { |
| 1357 | 1386 | struct vsie_page *vsie_page; |
| 1358 | − struct page *page; | |
| 1359 | 1387 | int nr_vcpus; |
| 1360 | 1388 | |
| 1361 | 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 | 1391 | rcu_read_unlock(); |
| 1364 | − if (page) { | |
| 1365 | − if (page_ref_inc_return(page) == 2) | |
| 1366 | − return page_to_virt(page); | |
| 1367 | − page_ref_dec(page); | |
| 1392 | + if (vsie_page) { | |
| 1393 | + if (try_get_vsie_page(vsie_page)) { | |
| 1394 | + if (vsie_page->scb_gpa == addr) | |
| 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 | 1410 | mutex_lock(&kvm->arch.vsie.mutex); |
| 1377 | 1411 | if (kvm->arch.vsie.page_count < nr_vcpus) { |
| 1378 | − page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO | GFP_DMA); | |
| 1379 | − if (!page) { | |
| 1412 | + vsie_page = (void *)__get_free_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO | GFP_DMA); | |
| 1413 | + if (!vsie_page) { | |
| 1380 | 1414 | mutex_unlock(&kvm->arch.vsie.mutex); |
| 1381 | 1415 | return ERR_PTR(-ENOMEM); |
| 1382 | 1416 | } |
| 1383 | − page_ref_inc(page); | |
| 1384 | − kvm->arch.vsie.pages[kvm->arch.vsie.page_count] = page; | |
| 1417 | + __set_bit(VSIE_PAGE_IN_USE, &vsie_page->flags); | |
| 1418 | + kvm->arch.vsie.pages[kvm->arch.vsie.page_count] = vsie_page; | |
| 1385 | 1419 | kvm->arch.vsie.page_count++; |
| 1386 | 1420 | } else { |
| 1387 | 1421 | /* reuse an existing entry that belongs to nobody */ |
| 1388 | 1422 | while (true) { |
| 1389 | − page = kvm->arch.vsie.pages[kvm->arch.vsie.next]; | |
| 1390 | − if (page_ref_inc_return(page) == 2) | |
| 1423 | + vsie_page = kvm->arch.vsie.pages[kvm->arch.vsie.next]; | |
| 1424 | + if (try_get_vsie_page(vsie_page)) | |
| 1391 | 1425 | break; |
| 1392 | − page_ref_dec(page); | |
| 1393 | 1426 | kvm->arch.vsie.next++; |
| 1394 | 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; | |
| 1399 | − /* double use of the same address */ | |
| 1400 | − if (radix_tree_insert(&kvm->arch.vsie.addr_to_page, addr >> 9, page)) { | |
| 1401 | − page_ref_dec(page); | |
| 1433 | + /* Mark it as invalid until it resides in the tree. */ | |
| 1434 | + vsie_page->scb_gpa = ULONG_MAX; | |
| 1435 | + | |
| 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 | 1440 | mutex_unlock(&kvm->arch.vsie.mutex); |
| 1403 | 1441 | return NULL; |
| 1404 | 1442 | } |
| 1443 | + vsie_page->scb_gpa = addr; | |
| 1405 | 1444 | mutex_unlock(&kvm->arch.vsie.mutex); |
| 1406 | 1445 | |
| 1407 | − vsie_page = page_to_virt(page); | |
| 1408 | 1446 | memset(&vsie_page->scb_s, 0, sizeof(struct kvm_s390_sie_block)); |
| 1409 | 1447 | release_gmap_shadow(vsie_page); |
| 1410 | 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 | 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 | 1453 | int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu) |
| 1424 | 1454 | { |
| 1425 | 1455 | struct vsie_page *vsie_page; |
| @@ -1470,7 +1500,7 @@ out_unshadow: · 44 unmodified lines | ||
| 1470 | 1500 | out_unpin_scb: |
| 1471 | 1501 | unpin_scb(vcpu, vsie_page, scb_addr); |
| 1472 | 1502 | out_put: |
| 1473 | − put_vsie_page(vcpu->kvm, vsie_page); | |
| 1503 | + put_vsie_page(vsie_page); | |
| 1474 | 1504 | |
| 1475 | 1505 | return rc < 0 ? rc : 0; |
| 1476 | 1506 | } |
| @@ -1486,18 +1516,18 @@ void kvm_s390_vsie_init(struct kvm *kvm) · 9 unmodified lines | ||
| 1486 | 1516 | void kvm_s390_vsie_destroy(struct kvm *kvm) |
| 1487 | 1517 | { |
| 1488 | 1518 | struct vsie_page *vsie_page; |
| 1489 | − struct page *page; | |
| 1490 | 1519 | int i; |
| 1491 | 1520 | |
| 1492 | 1521 | mutex_lock(&kvm->arch.vsie.mutex); |
| 1493 | 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 | 1524 | kvm->arch.vsie.pages[i] = NULL; |
| 1496 | − vsie_page = page_to_virt(page); | |
| 1497 | 1525 | release_gmap_shadow(vsie_page); |
| 1498 | 1526 | /* free the radix tree entry */ |
| 1499 | − radix_tree_delete(&kvm->arch.vsie.addr_to_page, page->index >> 9); | |
| 1500 | − __free_page(page); | |
| 1527 | + if (vsie_page->scb_gpa != ULONG_MAX) | |
| 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 | 1532 | kvm->arch.vsie.page_count = 0; |
| 1503 | 1533 | mutex_unlock(&kvm->arch.vsie.mutex); |
| @@ -24,6 +24,16 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <asm/page.h> |
| 25 | 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 | 37 | #define GMAP_SHADOW_FAKE_TABLE 1ULL |
| 28 | 38 | |
| 29 | 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 | 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 | 58 | struct gmap *gmap; |
| 49 | 59 | struct page *page; |
| @@ -70,9 +80,7 @@ static struct gmap *gmap_alloc(unsigned long limit) · 20 unmodified lines | ||
| 70 | 80 | gmap = kzalloc(sizeof(struct gmap), GFP_KERNEL_ACCOUNT); |
| 71 | 81 | if (!gmap) |
| 72 | 82 | goto out; |
| 73 | − INIT_LIST_HEAD(&gmap->crst_list); | |
| 74 | 83 | INIT_LIST_HEAD(&gmap->children); |
| 75 | − INIT_LIST_HEAD(&gmap->pt_list); | |
| 76 | 84 | INIT_RADIX_TREE(&gmap->guest_to_host, GFP_KERNEL_ACCOUNT); |
| 77 | 85 | INIT_RADIX_TREE(&gmap->host_to_guest, GFP_ATOMIC | __GFP_ACCOUNT); |
| 78 | 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 | 90 | page = gmap_alloc_crst(); |
| 83 | 91 | if (!page) |
| 84 | 92 | goto out_free; |
| 85 | − page->index = 0; | |
| 86 | − list_add(&page->lru, &gmap->crst_list); | |
| 87 | 93 | table = page_to_virt(page); |
| 88 | 94 | crst_table_init(table, etype); |
| 89 | 95 | gmap->table = table; |
| @@ -97,6 +103,7 @@ out_free: · 7 unmodified lines | ||
| 97 | 103 | out: |
| 98 | 104 | return NULL; |
| 99 | 105 | } |
| 106 | +EXPORT_SYMBOL_GPL(gmap_alloc); | |
| 100 | 107 | |
| 101 | 108 | /** |
| 102 | 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 | 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 | 217 | * gmap_free - free a guest address space |
| 190 | 218 | * @gmap: pointer to the guest address space structure |
| 191 | 219 | * |
| 192 | 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 | 224 | /* Flush tlb of all gmaps (if not already done for shadows) */ |
| 199 | 225 | if (!(gmap_is_shadow(gmap) && gmap->removed)) |
| 200 | 226 | gmap_flush_tlb(gmap); |
| 201 | 227 | /* Free all segment & region tables. */ |
| 202 | − list_for_each_entry_safe(page, next, &gmap->crst_list, lru) | |
| 203 | − __free_pages(page, CRST_ALLOC_ORDER); | |
| 228 | + gmap_free_crst(gmap->table, gmap_is_shadow(gmap)); | |
| 229 | + | |
| 204 | 230 | gmap_radix_tree_free(&gmap->guest_to_host); |
| 205 | 231 | gmap_radix_tree_free(&gmap->host_to_guest); |
| 206 | 232 | |
| 207 | 233 | /* Free additional data for a shadow gmap */ |
| 208 | 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 | 235 | gmap_rmap_radix_tree_free(&gmap->host_to_rmap); |
| 215 | 236 | /* Release reference to the parent */ |
| 216 | 237 | gmap_put(gmap->parent); |
| @@ -218,6 +239,7 @@ static void gmap_free(struct gmap *gmap) · 1 unmodified line | ||
| 218 | 239 | |
| 219 | 240 | kfree(gmap); |
| 220 | 241 | } |
| 242 | +EXPORT_SYMBOL_GPL(gmap_free); | |
| 221 | 243 | |
| 222 | 244 | /** |
| 223 | 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 | 320 | crst_table_init(new, init); |
| 299 | 321 | spin_lock(&gmap->guest_table_lock); |
| 300 | 322 | if (*table & _REGION_ENTRY_INVALID) { |
| 301 | − list_add(&page->lru, &gmap->crst_list); | |
| 302 | 323 | *table = __pa(new) | _REGION_ENTRY_LENGTH | |
| 303 | 324 | (*table & _REGION_ENTRY_TYPE_MASK); |
| 304 | − page->index = gaddr; | |
| 305 | 325 | page = NULL; |
| 306 | 326 | } |
| 307 | 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 | 330 | return 0; |
| 311 | 331 | } |
| 312 | 332 | |
| 313 | −/** | |
| 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) | |
| 333 | +static unsigned long host_to_guest_lookup(struct gmap *gmap, unsigned long vmaddr) | |
| 320 | 334 | { |
| 321 | − struct page *page; | |
| 322 | − unsigned long offset; | |
| 335 | + return (unsigned long)radix_tree_lookup(&gmap->host_to_guest, vmaddr >> PMD_SHIFT); | |
| 336 | +} | |
| 323 | 337 | |
| 324 | − offset = (unsigned long) entry / sizeof(unsigned long); | |
| 325 | − offset = (offset & (PTRS_PER_PMD - 1)) * PMD_SIZE; | |
| 326 | − page = pmd_pgtable_page((pmd_t *) entry); | |
| 327 | − return page->index + offset; | |
| 338 | +static unsigned long host_to_guest_delete(struct gmap *gmap, unsigned long vmaddr) | |
| 339 | +{ | |
| 340 | + return (unsigned long)radix_tree_delete(&gmap->host_to_guest, vmaddr >> PMD_SHIFT); | |
| 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 | 359 | static int __gmap_unlink_by_vmaddr(struct gmap *gmap, unsigned long vmaddr) |
| 338 | 360 | { |
| 339 | − unsigned long *entry; | |
| 361 | + unsigned long gaddr; | |
| 340 | 362 | int flush = 0; |
| 363 | + pmd_t *pmdp; | |
| 341 | 364 | |
| 342 | 365 | BUG_ON(gmap_is_shadow(gmap)); |
| 343 | 366 | spin_lock(&gmap->guest_table_lock); |
| 344 | − entry = radix_tree_delete(&gmap->host_to_guest, vmaddr >> PMD_SHIFT); | |
| 345 | − if (entry) { | |
| 346 | − flush = (*entry != _SEGMENT_ENTRY_EMPTY); | |
| 347 | − *entry = _SEGMENT_ENTRY_EMPTY; | |
| 367 | + | |
| 368 | + pmdp = host_to_guest_pmd_delete(gmap, vmaddr, &gaddr); | |
| 369 | + if (pmdp) { | |
| 370 | + flush = (pmd_val(*pmdp) != _SEGMENT_ENTRY_EMPTY); | |
| 371 | + *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); | |
| 348 | 372 | } |
| 373 | + | |
| 349 | 374 | spin_unlock(&gmap->guest_table_lock); |
| 350 | 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 | 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 | 492 | * gmap_unlink - disconnect a page table from the gmap shadow tables |
| 488 | 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 | 587 | spin_lock(&gmap->guest_table_lock); |
| 583 | 588 | if (*table == _SEGMENT_ENTRY_EMPTY) { |
| 584 | 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 | 592 | if (!rc) { |
| 587 | 593 | if (pmd_leaf(*pmd)) { |
| 588 | 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 | 611 | radix_tree_preload_end(); |
| 606 | 612 | return rc; |
| 607 | 613 | } |
| 608 | − | |
| 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); | |
| 614 | +EXPORT_SYMBOL(__gmap_link); | |
| 732 | 615 | |
| 733 | 616 | /* |
| 734 | 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 | 737 | * Note: Can also be called for shadow gmaps. |
| 855 | 738 | */ |
| 856 | −static inline unsigned long *gmap_table_walk(struct gmap *gmap, | |
| 857 | − unsigned long gaddr, int level) | |
| 739 | +unsigned long *gmap_table_walk(struct gmap *gmap, unsigned long gaddr, int level) | |
| 858 | 740 | { |
| 859 | 741 | const int asce_type = gmap->asce & _ASCE_TYPE_MASK; |
| 860 | 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 | 788 | return table; |
| 907 | 789 | } |
| 790 | +EXPORT_SYMBOL(gmap_table_walk); | |
| 908 | 791 | |
| 909 | 792 | /** |
| 910 | 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 | 984 | * @prot: indicates access rights: PROT_NONE, PROT_READ or PROT_WRITE |
| 1102 | 985 | * @bits: pgste notification bits to set |
| 1103 | 986 | * |
| 1104 | − * Returns 0 if successfully protected, -ENOMEM if out of memory and | |
| 1105 | − * -EFAULT if gaddr is invalid (or mapping for shadows is missing). | |
| 987 | + * Returns: | |
| 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, | |
| 1110 | − unsigned long len, int prot, unsigned long bits) | |
| 996 | +int gmap_protect_one(struct gmap *gmap, unsigned long gaddr, int prot, unsigned long bits) | |
| 1111 | 997 | { |
| 1112 | − unsigned long vmaddr, dist; | |
| 1113 | 998 | pmd_t *pmdp; |
| 1114 | − int rc; | |
| 999 | + int rc = 0; | |
| 1115 | 1000 | |
| 1116 | 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 */ | |
| 1144 | − vmaddr = __gmap_translate(gmap, gaddr); | |
| 1145 | − if (IS_ERR_VALUE(vmaddr)) | |
| 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 | −} | |
| 1003 | + pmdp = gmap_pmd_op_walk(gmap, gaddr); | |
| 1004 | + if (!pmdp) | |
| 1005 | + return -EAGAIN; | |
| 1154 | 1006 | |
| 1155 | −/** | |
| 1156 | − * gmap_mprotect_notify - change access rights for a range of ptes and | |
| 1157 | − * call the notifier if any pte changes again | |
| 1158 | − * @gmap: pointer to guest mapping meta data structure | |
| 1159 | − * @gaddr: virtual address in the guest address space | |
| 1160 | − * @len: size of area | |
| 1161 | − * @prot: indicates access rights: PROT_NONE, PROT_READ or PROT_WRITE | |
| 1162 | − * | |
| 1163 | − * Returns 0 if for each page in the given range a gmap mapping exists, | |
| 1164 | − * the new access rights could be set and the notifier could be armed. | |
| 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; | |
| 1007 | + if (!pmd_leaf(*pmdp)) { | |
| 1008 | + rc = gmap_protect_pte(gmap, gaddr, pmdp, prot, bits); | |
| 1009 | + if (!rc) | |
| 1010 | + rc = PAGE_SIZE; | |
| 1011 | + } else { | |
| 1012 | + rc = gmap_protect_pmd(gmap, gaddr, pmdp, prot, bits); | |
| 1013 | + if (!rc) | |
| 1014 | + rc = HPAGE_SIZE; | |
| 1015 | + } | |
| 1016 | + gmap_pmd_op_end(gmap, pmdp); | |
| 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 | 1018 | return rc; |
| 1182 | 1019 | } |
| 1183 | −EXPORT_SYMBOL_GPL(gmap_mprotect_notify); | |
| 1020 | +EXPORT_SYMBOL_GPL(gmap_protect_one); | |
| 1184 | 1021 | |
| 1185 | 1022 | /** |
| 1186 | 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 | 1251 | __gmap_unshadow_pgt(sg, raddr, __va(pgt)); |
| 1415 | 1252 | /* Free page table */ |
| 1416 | 1253 | ptdesc = page_ptdesc(phys_to_page(pgt)); |
| 1417 | − list_del(&ptdesc->pt_list); | |
| 1418 | 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 | 1278 | __gmap_unshadow_pgt(sg, raddr, __va(pgt)); |
| 1443 | 1279 | /* Free page table */ |
| 1444 | 1280 | ptdesc = page_ptdesc(phys_to_page(pgt)); |
| 1445 | − list_del(&ptdesc->pt_list); | |
| 1446 | 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 | 1307 | __gmap_unshadow_sgt(sg, raddr, __va(sgt)); |
| 1473 | 1308 | /* Free segment table */ |
| 1474 | 1309 | page = phys_to_page(sgt); |
| 1475 | − list_del(&page->lru); | |
| 1476 | 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 | 1334 | __gmap_unshadow_sgt(sg, raddr, __va(sgt)); |
| 1501 | 1335 | /* Free segment table */ |
| 1502 | 1336 | page = phys_to_page(sgt); |
| 1503 | − list_del(&page->lru); | |
| 1504 | 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 | 1363 | __gmap_unshadow_r3t(sg, raddr, __va(r3t)); |
| 1531 | 1364 | /* Free region 3 table */ |
| 1532 | 1365 | page = phys_to_page(r3t); |
| 1533 | − list_del(&page->lru); | |
| 1534 | 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 | 1390 | __gmap_unshadow_r3t(sg, raddr, __va(r3t)); |
| 1559 | 1391 | /* Free region 3 table */ |
| 1560 | 1392 | page = phys_to_page(r3t); |
| 1561 | − list_del(&page->lru); | |
| 1562 | 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 | 1419 | __gmap_unshadow_r2t(sg, raddr, __va(r2t)); |
| 1589 | 1420 | /* Free region 2 table */ |
| 1590 | 1421 | page = phys_to_page(r2t); |
| 1591 | − list_del(&page->lru); | |
| 1592 | 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 | 1450 | r1t[i] = _REGION1_ENTRY_EMPTY; |
| 1621 | 1451 | /* Free region 2 table */ |
| 1622 | 1452 | page = phys_to_page(r2t); |
| 1623 | − list_del(&page->lru); | |
| 1624 | 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 | 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 | 1465 | unsigned long *table; |
| 1637 | 1466 | |
| @@ -1657,143 +1486,7 @@ static void gmap_unshadow(struct gmap *sg) · 19 unmodified lines | ||
| 1657 | 1486 | break; |
| 1658 | 1487 | } |
| 1659 | 1488 | } |
| 1660 | − | |
| 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); | |
| 1489 | +EXPORT_SYMBOL(gmap_unshadow); | |
| 1797 | 1490 | |
| 1798 | 1491 | /** |
| 1799 | 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 | 1520 | page = gmap_alloc_crst(); |
| 1828 | 1521 | if (!page) |
| 1829 | 1522 | return -ENOMEM; |
| 1830 | − page->index = r2t & _REGION_ENTRY_ORIGIN; | |
| 1831 | − if (fake) | |
| 1832 | − page->index |= GMAP_SHADOW_FAKE_TABLE; | |
| 1833 | 1523 | s_r2t = page_to_phys(page); |
| 1834 | 1524 | /* Install shadow region second table */ |
| 1835 | 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 | 1541 | _REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INVALID; |
| 1852 | 1542 | if (sg->edat_level >= 1) |
| 1853 | 1543 | *table |= (r2t & _REGION_ENTRY_PROTECT); |
| 1854 | − list_add(&page->lru, &sg->crst_list); | |
| 1855 | 1544 | if (fake) { |
| 1856 | 1545 | /* nothing to protect for fake tables */ |
| 1857 | 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 | 1600 | page = gmap_alloc_crst(); |
| 1912 | 1601 | if (!page) |
| 1913 | 1602 | return -ENOMEM; |
| 1914 | − page->index = r3t & _REGION_ENTRY_ORIGIN; | |
| 1915 | − if (fake) | |
| 1916 | − page->index |= GMAP_SHADOW_FAKE_TABLE; | |
| 1917 | 1603 | s_r3t = page_to_phys(page); |
| 1918 | 1604 | /* Install shadow region second table */ |
| 1919 | 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 | 1621 | _REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INVALID; |
| 1936 | 1622 | if (sg->edat_level >= 1) |
| 1937 | 1623 | *table |= (r3t & _REGION_ENTRY_PROTECT); |
| 1938 | − list_add(&page->lru, &sg->crst_list); | |
| 1939 | 1624 | if (fake) { |
| 1940 | 1625 | /* nothing to protect for fake tables */ |
| 1941 | 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 | 1680 | page = gmap_alloc_crst(); |
| 1996 | 1681 | if (!page) |
| 1997 | 1682 | return -ENOMEM; |
| 1998 | − page->index = sgt & _REGION_ENTRY_ORIGIN; | |
| 1999 | − if (fake) | |
| 2000 | − page->index |= GMAP_SHADOW_FAKE_TABLE; | |
| 2001 | 1683 | s_sgt = page_to_phys(page); |
| 2002 | 1684 | /* Install shadow region second table */ |
| 2003 | 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 | 1701 | _REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID; |
| 2020 | 1702 | if (sg->edat_level >= 1) |
| 2021 | 1703 | *table |= sgt & _REGION_ENTRY_PROTECT; |
| 2022 | − list_add(&page->lru, &sg->crst_list); | |
| 2023 | 1704 | if (fake) { |
| 2024 | 1705 | /* nothing to protect for fake tables */ |
| 2025 | 1706 | *table &= ~_REGION_ENTRY_INVALID; |
| @@ -2052,45 +1733,22 @@ out_free: · 26 unmodified lines | ||
| 2052 | 1733 | } |
| 2053 | 1734 | EXPORT_SYMBOL_GPL(gmap_shadow_sgt); |
| 2054 | 1735 | |
| 2055 | −/** | |
| 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) | |
| 1736 | +static void gmap_pgste_set_pgt_addr(struct ptdesc *ptdesc, unsigned long pgt_addr) | |
| 2071 | 1737 | { |
| 2072 | − unsigned long *table; | |
| 2073 | − struct page *page; | |
| 2074 | − int rc; | |
| 1738 | + unsigned long *pgstes = page_to_virt(ptdesc_page(ptdesc)); | |
| 2075 | 1739 | |
| 2076 | − BUG_ON(!gmap_is_shadow(sg)); | |
| 2077 | − spin_lock(&sg->guest_table_lock); | |
| 2078 | − table = gmap_table_walk(sg, saddr, 1); /* get segment pointer */ | |
| 2079 | − if (table && !(*table & _SEGMENT_ENTRY_INVALID)) { | |
| 2080 | − /* Shadow page tables are full pages (pte+pgste) */ | |
| 2081 | − page = pfn_to_page(*table >> PAGE_SHIFT); | |
| 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; | |
| 1740 | + pgstes += _PAGE_ENTRIES; | |
| 1741 | + | |
| 1742 | + pgstes[0] &= ~PGSTE_ST2_MASK; | |
| 1743 | + pgstes[1] &= ~PGSTE_ST2_MASK; | |
| 1744 | + pgstes[2] &= ~PGSTE_ST2_MASK; | |
| 1745 | + pgstes[3] &= ~PGSTE_ST2_MASK; | |
| 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 | 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 | 1777 | ptdesc = page_table_alloc_pgste(sg->mm); |
| 2120 | 1778 | if (!ptdesc) |
| 2121 | 1779 | return -ENOMEM; |
| 2122 | − ptdesc->pt_index = pgt & _SEGMENT_ENTRY_ORIGIN; | |
| 1780 | + origin = pgt & _SEGMENT_ENTRY_ORIGIN; | |
| 2123 | 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 | 1784 | s_pgt = page_to_phys(ptdesc_page(ptdesc)); |
| 2126 | 1785 | /* Install shadow page table */ |
| 2127 | 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 | 1799 | /* mark as invalid as long as the parent table is not protected */ |
| 2141 | 1800 | *table = (unsigned long) s_pgt | _SEGMENT_ENTRY | |
| 2142 | 1801 | (pgt & _SEGMENT_ENTRY_PROTECT) | _SEGMENT_ENTRY_INVALID; |
| 2143 | − list_add(&ptdesc->pt_list, &sg->pt_list); | |
| 2144 | 1802 | if (fake) { |
| 2145 | 1803 | /* nothing to protect for fake tables */ |
| 2146 | 1804 | *table &= ~_SEGMENT_ENTRY_INVALID; |
| @@ -2318,7 +1976,6 @@ void ptep_notify(struct mm_struct *mm, unsigned long vmaddr, · 171 unmodified lines | ||
| 2318 | 1976 | pte_t *pte, unsigned long bits) |
| 2319 | 1977 | { |
| 2320 | 1978 | unsigned long offset, gaddr = 0; |
| 2321 | − unsigned long *table; | |
| 2322 | 1979 | struct gmap *gmap, *sg, *next; |
| 2323 | 1980 | |
| 2324 | 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 | 1983 | rcu_read_lock(); |
| 2327 | 1984 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { |
| 2328 | 1985 | spin_lock(&gmap->guest_table_lock); |
| 2329 | − table = radix_tree_lookup(&gmap->host_to_guest, | |
| 2330 | − vmaddr >> PMD_SHIFT); | |
| 2331 | − if (table) | |
| 2332 | − gaddr = __gmap_segment_gaddr(table) + offset; | |
| 1986 | + gaddr = host_to_guest_lookup(gmap, vmaddr) + offset; | |
| 2333 | 1987 | spin_unlock(&gmap->guest_table_lock); |
| 2334 | − if (!table) | |
| 1988 | + if (!IS_GADDR_VALID(gaddr)) | |
| 2335 | 1989 | continue; |
| 2336 | 1990 | |
| 2337 | 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 | 2045 | rcu_read_lock(); |
| 2392 | 2046 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { |
| 2393 | 2047 | spin_lock(&gmap->guest_table_lock); |
| 2394 | − pmdp = (pmd_t *)radix_tree_delete(&gmap->host_to_guest, | |
| 2395 | − vmaddr >> PMD_SHIFT); | |
| 2048 | + pmdp = host_to_guest_pmd_delete(gmap, vmaddr, &gaddr); | |
| 2396 | 2049 | if (pmdp) { |
| 2397 | − gaddr = __gmap_segment_gaddr((unsigned long *)pmdp); | |
| 2398 | 2050 | pmdp_notify_gmap(gmap, pmdp, gaddr); |
| 2399 | 2051 | WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | |
| 2400 | 2052 | _SEGMENT_ENTRY_GMAP_UC | |
| @@ -2438,28 +2090,25 @@ EXPORT_SYMBOL_GPL(gmap_pmdp_csp); · 37 unmodified lines | ||
| 2438 | 2090 | */ |
| 2439 | 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 | 2094 | struct gmap *gmap; |
| 2443 | 2095 | pmd_t *pmdp; |
| 2444 | 2096 | |
| 2445 | 2097 | rcu_read_lock(); |
| 2446 | 2098 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { |
| 2447 | 2099 | spin_lock(&gmap->guest_table_lock); |
| 2448 | − entry = radix_tree_delete(&gmap->host_to_guest, | |
| 2449 | − vmaddr >> PMD_SHIFT); | |
| 2450 | − if (entry) { | |
| 2451 | − pmdp = (pmd_t *)entry; | |
| 2452 | − gaddr = __gmap_segment_gaddr(entry); | |
| 2100 | + pmdp = host_to_guest_pmd_delete(gmap, vmaddr, &gaddr); | |
| 2101 | + if (pmdp) { | |
| 2453 | 2102 | pmdp_notify_gmap(gmap, pmdp, gaddr); |
| 2454 | − WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | | |
| 2455 | − _SEGMENT_ENTRY_GMAP_UC | | |
| 2456 | − _SEGMENT_ENTRY)); | |
| 2103 | + WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | | |
| 2104 | + _SEGMENT_ENTRY_GMAP_UC | | |
| 2105 | + _SEGMENT_ENTRY)); | |
| 2457 | 2106 | if (MACHINE_HAS_TLB_GUEST) |
| 2458 | 2107 | __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, |
| 2459 | 2108 | gmap->asce, IDTE_LOCAL); |
| 2460 | 2109 | else if (MACHINE_HAS_IDTE) |
| 2461 | 2110 | __pmdp_idte(gaddr, pmdp, 0, 0, IDTE_LOCAL); |
| 2462 | − *entry = _SEGMENT_ENTRY_EMPTY; | |
| 2111 | + *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); | |
| 2463 | 2112 | } |
| 2464 | 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 | 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 | 2127 | struct gmap *gmap; |
| 2479 | 2128 | pmd_t *pmdp; |
| 2480 | 2129 | |
| 2481 | 2130 | rcu_read_lock(); |
| 2482 | 2131 | list_for_each_entry_rcu(gmap, &mm->context.gmap_list, list) { |
| 2483 | 2132 | spin_lock(&gmap->guest_table_lock); |
| 2484 | − entry = radix_tree_delete(&gmap->host_to_guest, | |
| 2485 | − vmaddr >> PMD_SHIFT); | |
| 2486 | − if (entry) { | |
| 2487 | − pmdp = (pmd_t *)entry; | |
| 2488 | − gaddr = __gmap_segment_gaddr(entry); | |
| 2133 | + pmdp = host_to_guest_pmd_delete(gmap, vmaddr, &gaddr); | |
| 2134 | + if (pmdp) { | |
| 2489 | 2135 | pmdp_notify_gmap(gmap, pmdp, gaddr); |
| 2490 | − WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | | |
| 2491 | − _SEGMENT_ENTRY_GMAP_UC | | |
| 2492 | − _SEGMENT_ENTRY)); | |
| 2136 | + WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE | | |
| 2137 | + _SEGMENT_ENTRY_GMAP_UC | | |
| 2138 | + _SEGMENT_ENTRY)); | |
| 2493 | 2139 | if (MACHINE_HAS_TLB_GUEST) |
| 2494 | 2140 | __pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE, |
| 2495 | 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 | 2143 | __pmdp_idte(gaddr, pmdp, 0, 0, IDTE_GLOBAL); |
| 2498 | 2144 | else |
| 2499 | 2145 | __pmdp_csp(pmdp); |
| 2500 | − *entry = _SEGMENT_ENTRY_EMPTY; | |
| 2146 | + *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); | |
| 2501 | 2147 | } |
| 2502 | 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 | 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 | 2592 | * s390_replace_asce - Try to replace the current ASCE of a gmap with a copy |
| 2990 | 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 | 2607 | struct page *page; |
| 3005 | 2608 | void *table; |
| 3006 | 2609 | |
| 3007 | − s390_unlist_old_asce(gmap); | |
| 3008 | − | |
| 3009 | 2610 | /* Replacing segment type ASCEs would cause serious issues */ |
| 3010 | 2611 | if ((gmap->asce & _ASCE_TYPE_MASK) == _ASCE_TYPE_SEGMENT) |
| 3011 | 2612 | return -EINVAL; |
| @@ -3013,19 +2614,9 @@ int s390_replace_asce(struct gmap *gmap) · 1 unmodified line | ||
| 3013 | 2614 | page = gmap_alloc_crst(); |
| 3014 | 2615 | if (!page) |
| 3015 | 2616 | return -ENOMEM; |
| 3016 | − page->index = 0; | |
| 3017 | 2617 | table = page_to_virt(page); |
| 3018 | 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 | 2620 | /* Set new table origin while preserving existing ASCE control bits */ |
| 3030 | 2621 | asce = (gmap->asce & ~_ASCE_ORIGIN) | __pa(table); |
| 3031 | 2622 | WRITE_ONCE(gmap->asce, asce); |
| @@ -3035,3 +2626,31 @@ int s390_replace_asce(struct gmap *gmap) · 3 unmodified lines | ||
| 3035 | 2626 | return 0; |
| 3036 | 2627 | } |
| 3037 | 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 | 177 | table = ptdesc_to_virt(ptdesc); |
| 178 | 178 | __arch_set_page_dat(table, 1); |
| 179 | − /* pt_list is used by gmap only */ | |
| 180 | − INIT_LIST_HEAD(&ptdesc->pt_list); | |
| 181 | 179 | memset64((u64 *)table, _PAGE_INVALID, PTRS_PER_PTE); |
| 182 | 180 | memset64((u64 *)table + PTRS_PER_PTE, 0, PTRS_PER_PTE); |
| 183 | 181 | return table; |
| @@ -331,6 +331,17 @@ error: · 330 unmodified lines | ||
| 331 | 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 | 345 | int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops) |
| 335 | 346 | { |
| 336 | 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 | 357 | topo = topo_is_tid ? zdev->tid : zdev->pchid; |
| 347 | 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 | 368 | if (!zbus) { |
| 349 | 369 | zbus = zpci_bus_alloc(topo, topo_is_tid); |
| 350 | 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 | 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; | |
| 66 | − struct zpci_dev *zdev; | |
| 79 | + int i, vfid, devfn, cand_devfn; | |
| 67 | 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 | 82 | if (!zbus->multifunction) |
| 72 | − return 0; | |
| 73 | − | |
| 74 | − /* If the parent PF for the given VF is also configured in the | |
| 83 | + return NULL; | |
| 84 | + /* Non-VFs and VFs without RID available don't have a parent */ | |
| 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 | 92 | * instance, it must be on the same zbus. |
| 76 | 93 | * We can then identify the parent PF by checking what |
| 77 | 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 | 102 | if (!pdev) |
| 86 | 103 | continue; |
| 87 | 104 | cand_devfn = pci_iov_virtfn_devfn(pdev, vfid); |
| 88 | − if (cand_devfn == virtfn->devfn) { | |
| 89 | − rc = zpci_iov_link_virtfn(pdev, virtfn, vfid); | |
| 90 | − /* balance pci_get_slot() */ | |
| 91 | − pci_dev_put(pdev); | |
| 92 | − break; | |
| 93 | − } | |
| 105 | + if (cand_devfn == devfn) | |
| 106 | + return pdev; | |
| 94 | 107 | /* balance pci_get_slot() */ |
| 95 | 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 | 126 | return rc; |
| 99 | 127 | } |
| @@ -19,6 +19,8 @@ void zpci_iov_map_resources(struct pci_dev *pdev); · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 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 | 24 | #else /* CONFIG_PCI_IOV */ |
| 23 | 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 | 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 | 38 | #endif /* CONFIG_PCI_IOV */ |
| 32 | 39 | #endif /* __S390_PCI_IOV_h */ |
| @@ -25,8 +25,10 @@ · 24 unmodified lines | ||
| 25 | 25 | #define MAX_IRQ_MSG_SIZE (sizeof(struct virtio_pcidev_msg) + sizeof(u32)) |
| 26 | 26 | #define NUM_IRQ_MSGS 10 |
| 27 | 27 | |
| 28 | −#define HANDLE_NO_FREE(ptr) ((void *)((unsigned long)(ptr) | 1)) | |
| 29 | −#define HANDLE_IS_NO_FREE(ptr) ((unsigned long)(ptr) & 1) | |
| 28 | +struct um_pci_message_buffer { | |
| 29 | + struct virtio_pcidev_msg hdr; | |
| 30 | + u8 data[8]; | |
| 31 | +}; | |
| 30 | 32 | |
| 31 | 33 | struct um_pci_device { |
| 32 | 34 | struct virtio_device *vdev; |
| @@ -36,6 +38,11 @@ struct um_pci_device { · 3 unmodified lines | ||
| 36 | 38 | |
| 37 | 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 | 46 | #define UM_PCI_STAT_WAITING 0 |
| 40 | 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 | 68 | static unsigned int um_pci_max_delay_us = 40000; |
| 62 | 69 | module_param_named(max_delay_us, um_pci_max_delay_us, uint, 0644); |
| 63 | 70 | |
| 64 | −struct um_pci_message_buffer { | |
| 65 | − struct virtio_pcidev_msg hdr; | |
| 66 | − u8 data[8]; | |
| 67 | −}; | |
| 71 | +static int um_pci_get_buf(struct um_pci_device *dev, bool *posted) | |
| 72 | +{ | |
| 73 | + int i; | |
| 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 | 106 | static int um_pci_send_cmd(struct um_pci_device *dev, |
| 72 | 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 | 118 | struct um_pci_message_buffer *buf; |
| 84 | 119 | int delay_count = 0; |
| 120 | + bool bounce_out; | |
| 85 | 121 | int ret, len; |
| 122 | + int buf_idx; | |
| 86 | 123 | bool posted; |
| 87 | 124 | |
| 88 | 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 | 138 | break; |
| 102 | 139 | } |
| 103 | 140 | |
| 104 | − buf = get_cpu_var(um_pci_msg_bufs); | |
| 105 | − if (buf) | |
| 106 | − memcpy(buf, cmd, cmd_size); | |
| 141 | + bounce_out = !posted && cmd_size <= sizeof(*cmd) && | |
| 142 | + out && out_size <= sizeof(buf->data); | |
| 107 | 143 | |
| 108 | − if (posted) { | |
| 109 | − u8 *ncmd = kmalloc(cmd_size + extra_size, GFP_ATOMIC); | |
| 110 | − | |
| 111 | − if (ncmd) { | |
| 112 | − memcpy(ncmd, cmd, cmd_size); | |
| 113 | − if (extra) | |
| 114 | − memcpy(ncmd + cmd_size, extra, extra_size); | |
| 115 | − cmd = (void *)ncmd; | |
| 116 | − cmd_size += extra_size; | |
| 117 | − extra = NULL; | |
| 118 | − extra_size = 0; | |
| 119 | − } else { | |
| 120 | − /* try without allocating memory */ | |
| 121 | − posted = false; | |
| 122 | − cmd = (void *)buf; | |
| 144 | + buf_idx = um_pci_get_buf(dev, &posted); | |
| 145 | + buf = &dev->bufs[buf_idx]; | |
| 146 | + memcpy(buf, cmd, cmd_size); | |
| 147 | + | |
| 148 | + if (posted && extra && extra_size > sizeof(buf) - cmd_size) { | |
| 149 | + dev->extra_ptrs[buf_idx] = kmemdup(extra, extra_size, | |
| 150 | + GFP_ATOMIC); | |
| 151 | + | |
| 152 | + if (!dev->extra_ptrs[buf_idx]) { | |
| 153 | + um_pci_free_buf(dev, buf); | |
| 154 | + return -ENOMEM; | |
| 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 | 163 | } else { |
| 125 | 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 | 167 | sg_init_one(&out_sg, cmd, cmd_size); |
| 129 | 168 | if (extra) |
| 130 | 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 | 174 | sg_init_one(&in_sg, out, out_size); |
| 133 | 175 | |
| 134 | 176 | /* add to internal virtio queue */ |
| 135 | 177 | ret = virtqueue_add_sgs(dev->cmd_vq, sgs_list, |
| 136 | 178 | extra ? 2 : 1, |
| 137 | 179 | out ? 1 : 0, |
| 138 | − posted ? cmd : HANDLE_NO_FREE(cmd), | |
| 139 | − GFP_ATOMIC); | |
| 180 | + cmd, GFP_ATOMIC); | |
| 140 | 181 | if (ret) { |
| 141 | − if (posted) | |
| 142 | − kfree(cmd); | |
| 143 | − goto out; | |
| 182 | + um_pci_free_buf(dev, buf); | |
| 183 | + return ret; | |
| 144 | 184 | } |
| 145 | 185 | |
| 146 | 186 | if (posted) { |
| 147 | 187 | virtqueue_kick(dev->cmd_vq); |
| 148 | − ret = 0; | |
| 149 | − goto out; | |
| 188 | + return 0; | |
| 150 | 189 | } |
| 151 | 190 | |
| 152 | 191 | /* kick and poll for getting a response on the queue */ |
| 153 | 192 | set_bit(UM_PCI_STAT_WAITING, &dev->status); |
| 154 | 193 | virtqueue_kick(dev->cmd_vq); |
| 194 | + ret = 0; | |
| 155 | 195 | |
| 156 | 196 | while (1) { |
| 157 | 197 | void *completed = virtqueue_get_buf(dev->cmd_vq, &len); |
| 158 | 198 | |
| 159 | − if (completed == HANDLE_NO_FREE(cmd)) | |
| 199 | + if (completed == buf) | |
| 160 | 200 | break; |
| 161 | 201 | |
| 162 | − if (completed && !HANDLE_IS_NO_FREE(completed)) | |
| 163 | − kfree(completed); | |
| 202 | + if (completed) | |
| 203 | + um_pci_free_buf(dev, completed); | |
| 164 | 204 | |
| 165 | 205 | if (WARN_ONCE(virtqueue_is_broken(dev->cmd_vq) || |
| 166 | 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 | 213 | clear_bit(UM_PCI_STAT_WAITING, &dev->status); |
| 174 | 214 | |
| 175 | −out: | |
| 176 | − put_cpu_var(um_pci_msg_bufs); | |
| 215 | + if (bounce_out) | |
| 216 | + memcpy(out, buf->data, out_size); | |
| 217 | + | |
| 218 | + um_pci_free_buf(dev, buf); | |
| 219 | + | |
| 177 | 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 | 230 | .size = size, |
| 188 | 231 | .addr = offset, |
| 189 | 232 | }; |
| 190 | − /* buf->data is maximum size - we may only use parts of it */ | |
| 191 | − struct um_pci_message_buffer *buf; | |
| 192 | − u8 *data; | |
| 193 | − unsigned long ret = ULONG_MAX; | |
| 194 | − size_t bytes = sizeof(buf->data); | |
| 233 | + /* max 8, we might not use it all */ | |
| 234 | + u8 data[8]; | |
| 195 | 235 | |
| 196 | 236 | if (!dev) |
| 197 | 237 | return ULONG_MAX; |
| 198 | 238 | |
| 199 | − buf = get_cpu_var(um_pci_msg_bufs); | |
| 200 | − data = buf->data; | |
| 201 | − | |
| 202 | − if (buf) | |
| 203 | − memset(data, 0xff, bytes); | |
| 239 | + memset(data, 0xff, sizeof(data)); | |
| 204 | 240 | |
| 205 | 241 | switch (size) { |
| 206 | 242 | case 1: |
| @@ -212,34 +248,26 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset, · 5 unmodified lines | ||
| 212 | 248 | break; |
| 213 | 249 | default: |
| 214 | 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)) | |
| 219 | − goto out; | |
| 254 | + if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, size)) | |
| 255 | + return ULONG_MAX; | |
| 220 | 256 | |
| 221 | 257 | switch (size) { |
| 222 | 258 | case 1: |
| 223 | − ret = data[0]; | |
| 224 | − break; | |
| 259 | + return data[0]; | |
| 225 | 260 | case 2: |
| 226 | − ret = le16_to_cpup((void *)data); | |
| 227 | − break; | |
| 261 | + return le16_to_cpup((void *)data); | |
| 228 | 262 | case 4: |
| 229 | − ret = le32_to_cpup((void *)data); | |
| 230 | − break; | |
| 263 | + return le32_to_cpup((void *)data); | |
| 231 | 264 | #ifdef CONFIG_64BIT |
| 232 | 265 | case 8: |
| 233 | − ret = le64_to_cpup((void *)data); | |
| 234 | − break; | |
| 266 | + return le64_to_cpup((void *)data); | |
| 235 | 267 | #endif |
| 236 | 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 | 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 | 340 | static unsigned long um_pci_bar_read(void *priv, unsigned int offset, |
| 313 | 341 | int size) |
| 314 | 342 | { |
| 315 | − /* buf->data is maximum size - we may only use parts of it */ | |
| 316 | − struct um_pci_message_buffer *buf; | |
| 317 | − u8 *data; | |
| 318 | − unsigned long ret = ULONG_MAX; | |
| 319 | − | |
| 320 | − buf = get_cpu_var(um_pci_msg_bufs); | |
| 321 | − data = buf->data; | |
| 343 | + /* 8 is maximum size - we may only use parts of it */ | |
| 344 | + u8 data[8]; | |
| 322 | 345 | |
| 323 | 346 | switch (size) { |
| 324 | 347 | case 1: |
| @@ -330,33 +353,25 @@ static unsigned long um_pci_bar_read(void *priv, unsigned int offset, · 5 unmodified lines | ||
| 330 | 353 | break; |
| 331 | 354 | default: |
| 332 | 355 | WARN(1, "invalid config space read size %d\n", size); |
| 333 | − goto out; | |
| 356 | + return ULONG_MAX; | |
| 334 | 357 | } |
| 335 | 358 | |
| 336 | 359 | um_pci_bar_copy_from(priv, data, offset, size); |
| 337 | 360 | |
| 338 | 361 | switch (size) { |
| 339 | 362 | case 1: |
| 340 | − ret = data[0]; | |
| 341 | − break; | |
| 363 | + return data[0]; | |
| 342 | 364 | case 2: |
| 343 | − ret = le16_to_cpup((void *)data); | |
| 344 | − break; | |
| 365 | + return le16_to_cpup((void *)data); | |
| 345 | 366 | case 4: |
| 346 | − ret = le32_to_cpup((void *)data); | |
| 347 | − break; | |
| 367 | + return le32_to_cpup((void *)data); | |
| 348 | 368 | #ifdef CONFIG_64BIT |
| 349 | 369 | case 8: |
| 350 | − ret = le64_to_cpup((void *)data); | |
| 351 | − break; | |
| 370 | + return le64_to_cpup((void *)data); | |
| 352 | 371 | #endif |
| 353 | 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 | 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 | 538 | if (test_bit(UM_PCI_STAT_WAITING, &dev->status)) |
| 524 | 539 | return; |
| 525 | 540 | |
| 526 | − while ((cmd = virtqueue_get_buf(vq, &len))) { | |
| 527 | − if (WARN_ON(HANDLE_IS_NO_FREE(cmd))) | |
| 528 | − continue; | |
| 529 | − kfree(cmd); | |
| 530 | − } | |
| 541 | + while ((cmd = virtqueue_get_buf(vq, &len))) | |
| 542 | + um_pci_free_buf(dev, cmd); | |
| 531 | 543 | } |
| 532 | 544 | |
| 533 | 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 | 1018 | "No virtio device ID configured for PCI - no PCI support\n")) |
| 1007 | 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 | 1021 | bridge = pci_alloc_host_bridge(0); |
| 1014 | 1022 | if (!bridge) { |
| 1015 | 1023 | err = -ENOMEM; |
| @@ -1070,7 +1078,6 @@ free: · 54 unmodified lines | ||
| 1070 | 1078 | pci_free_resource_list(&bridge->windows); |
| 1071 | 1079 | pci_free_host_bridge(bridge); |
| 1072 | 1080 | } |
| 1073 | − free_percpu(um_pci_msg_bufs); | |
| 1074 | 1081 | return err; |
| 1075 | 1082 | } |
| 1076 | 1083 | module_init(um_pci_init); |
| @@ -1082,6 +1089,5 @@ static void __exit um_pci_exit(void) · 5 unmodified lines | ||
| 1082 | 1089 | irq_domain_remove(um_pci_inner_domain); |
| 1083 | 1090 | pci_free_resource_list(&bridge->windows); |
| 1084 | 1091 | pci_free_host_bridge(bridge); |
| 1085 | − free_percpu(um_pci_msg_bufs); | |
| 1086 | 1092 | } |
| 1087 | 1093 | module_exit(um_pci_exit); |
| @@ -52,7 +52,7 @@ struct virtio_uml_device { · 51 unmodified lines | ||
| 52 | 52 | struct platform_device *pdev; |
| 53 | 53 | struct virtio_uml_platform_data *pdata; |
| 54 | 54 | |
| 55 | − spinlock_t sock_lock; | |
| 55 | + raw_spinlock_t sock_lock; | |
| 56 | 56 | int sock, req_fd, irq; |
| 57 | 57 | u64 features; |
| 58 | 58 | u64 protocol_features; |
| @@ -246,7 +246,7 @@ static int vhost_user_send(struct virtio_uml_device *vu_dev, · 187 unmodified lines | ||
| 246 | 246 | if (request_ack) |
| 247 | 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 | 250 | rc = full_sendmsg_fds(vu_dev->sock, msg, size, fds, num_fds); |
| 251 | 251 | if (rc < 0) |
| 252 | 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 | 268 | out: |
| 269 | − spin_unlock_irqrestore(&vu_dev->sock_lock, flags); | |
| 269 | + raw_spin_unlock_irqrestore(&vu_dev->sock_lock, flags); | |
| 270 | 270 | return rc; |
| 271 | 271 | } |
| 272 | 272 | |
| @@ -1239,7 +1239,7 @@ static int virtio_uml_probe(struct platform_device *pdev) · 966 unmodified lines | ||
| 1239 | 1239 | goto error_free; |
| 1240 | 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 | 1244 | rc = vhost_user_init(vu_dev); |
| 1245 | 1245 | if (rc) |
| @@ -52,7 +52,7 @@ struct irq_entry { · 51 unmodified lines | ||
| 52 | 52 | bool sigio_workaround; |
| 53 | 53 | }; |
| 54 | 54 | |
| 55 | −static DEFINE_SPINLOCK(irq_lock); | |
| 55 | +static DEFINE_RAW_SPINLOCK(irq_lock); | |
| 56 | 56 | static LIST_HEAD(active_fds); |
| 57 | 57 | static DECLARE_BITMAP(irqs_allocated, UM_LAST_SIGNAL_IRQ); |
| 58 | 58 | static bool irqs_suspended; |
| @@ -257,7 +257,7 @@ static struct irq_entry *get_irq_entry_by_fd(int fd) · 198 unmodified lines | ||
| 257 | 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 | 262 | if (!to_free) |
| 263 | 263 | return; |
| @@ -265,7 +265,6 @@ static void free_irq_entry(struct irq_entry *to_free, bool remove) · 1 unmodified line | ||
| 265 | 265 | if (remove) |
| 266 | 266 | os_del_epoll_fd(to_free->fd); |
| 267 | 267 | list_del(&to_free->list); |
| 268 | − kfree(to_free); | |
| 269 | 268 | } |
| 270 | 269 | |
| 271 | 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 | 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)) | |
| 292 | − free_irq_entry(entry, false); | |
| 290 | + if (update_irq_entry(entry)) | |
| 291 | + return NULL; | |
| 292 | + remove_irq_entry(entry, false); | |
| 293 | + return entry; | |
| 293 | 294 | } |
| 294 | 295 | |
| 295 | 296 | static int activate_fd(int irq, int fd, enum um_irq_type type, void *dev_id, |
| 296 | 297 | void (*timetravel_handler)(int, int, void *, |
| 297 | 298 | struct time_travel_event *)) |
| 298 | 299 | { |
| 299 | − struct irq_entry *irq_entry; | |
| 300 | + struct irq_entry *irq_entry, *to_free = NULL; | |
| 300 | 301 | int err, events = os_event_mask(type); |
| 301 | 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 | 305 | if (err < 0) |
| 305 | 306 | goto out; |
| 306 | 307 | |
| 307 | − spin_lock_irqsave(&irq_lock, flags); | |
| 308 | + raw_spin_lock_irqsave(&irq_lock, flags); | |
| 308 | 309 | irq_entry = get_irq_entry_by_fd(fd); |
| 309 | 310 | if (irq_entry) { |
| 311 | +already: | |
| 310 | 312 | /* cannot register the same FD twice with the same type */ |
| 311 | 313 | if (WARN_ON(irq_entry->reg[type].events)) { |
| 312 | 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 | 318 | /* temporarily disable to avoid IRQ-side locking */ |
| 317 | 319 | os_del_epoll_fd(fd); |
| 318 | 320 | } else { |
| 319 | − irq_entry = kzalloc(sizeof(*irq_entry), GFP_ATOMIC); | |
| 320 | − if (!irq_entry) { | |
| 321 | − err = -ENOMEM; | |
| 322 | − goto out_unlock; | |
| 321 | + struct irq_entry *new; | |
| 322 | + | |
| 323 | + /* don't restore interrupts */ | |
| 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 | 337 | irq_entry->fd = fd; |
| 325 | 338 | list_add_tail(&irq_entry->list, &active_fds); |
| 326 | 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 | 352 | #endif |
| 340 | 353 | |
| 341 | 354 | WARN_ON(!update_irq_entry(irq_entry)); |
| 342 | − spin_unlock_irqrestore(&irq_lock, flags); | |
| 343 | − | |
| 344 | − return 0; | |
| 355 | + err = 0; | |
| 345 | 356 | out_unlock: |
| 346 | − spin_unlock_irqrestore(&irq_lock, flags); | |
| 357 | + raw_spin_unlock_irqrestore(&irq_lock, flags); | |
| 347 | 358 | out: |
| 359 | + kfree(to_free); | |
| 348 | 360 | return err; |
| 349 | 361 | } |
| 350 | 362 | |
| @@ -358,19 +370,20 @@ void free_irq_by_fd(int fd) · 7 unmodified lines | ||
| 358 | 370 | struct irq_entry *to_free; |
| 359 | 371 | unsigned long flags; |
| 360 | 372 | |
| 361 | − spin_lock_irqsave(&irq_lock, flags); | |
| 373 | + raw_spin_lock_irqsave(&irq_lock, flags); | |
| 362 | 374 | to_free = get_irq_entry_by_fd(fd); |
| 363 | − free_irq_entry(to_free, true); | |
| 364 | − spin_unlock_irqrestore(&irq_lock, flags); | |
| 375 | + remove_irq_entry(to_free, true); | |
| 376 | + raw_spin_unlock_irqrestore(&irq_lock, flags); | |
| 377 | + kfree(to_free); | |
| 365 | 378 | } |
| 366 | 379 | EXPORT_SYMBOL(free_irq_by_fd); |
| 367 | 380 | |
| 368 | 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 | 384 | unsigned long flags; |
| 372 | 385 | |
| 373 | − spin_lock_irqsave(&irq_lock, flags); | |
| 386 | + raw_spin_lock_irqsave(&irq_lock, flags); | |
| 374 | 387 | list_for_each_entry(entry, &active_fds, list) { |
| 375 | 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 | 400 | os_del_epoll_fd(entry->fd); |
| 388 | 401 | reg->events = 0; |
| 389 | − update_or_free_irq_entry(entry); | |
| 402 | + to_free = update_or_remove_irq_entry(entry); | |
| 390 | 403 | goto out; |
| 391 | 404 | } |
| 392 | 405 | } |
| 393 | 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 | 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 | 417 | os_del_epoll_fd(fd); |
| 404 | 418 | |
| 405 | − spin_lock_irqsave(&irq_lock, flags); | |
| 419 | + raw_spin_lock_irqsave(&irq_lock, flags); | |
| 406 | 420 | entry = get_irq_entry_by_fd(fd); |
| 407 | 421 | if (!entry) |
| 408 | 422 | goto out; |
| @@ -414,9 +428,10 @@ void deactivate_fd(int fd, int irqnum) · 5 unmodified lines | ||
| 414 | 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 | 432 | out: |
| 419 | − spin_unlock_irqrestore(&irq_lock, flags); | |
| 433 | + raw_spin_unlock_irqrestore(&irq_lock, flags); | |
| 434 | + kfree(entry); | |
| 420 | 435 | |
| 421 | 436 | ignore_sigio_fd(fd); |
| 422 | 437 | } |
| @@ -546,7 +561,7 @@ void um_irqs_suspend(void) · 123 unmodified lines | ||
| 546 | 561 | |
| 547 | 562 | irqs_suspended = true; |
| 548 | 563 | |
| 549 | − spin_lock_irqsave(&irq_lock, flags); | |
| 564 | + raw_spin_lock_irqsave(&irq_lock, flags); | |
| 550 | 565 | list_for_each_entry(entry, &active_fds, list) { |
| 551 | 566 | enum um_irq_type t; |
| 552 | 567 | bool clear = true; |
| @@ -579,7 +594,7 @@ void um_irqs_suspend(void) · 26 unmodified lines | ||
| 579 | 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 | 600 | void um_irqs_resume(void) |
| @@ -588,7 +603,7 @@ void um_irqs_resume(void) · 2 unmodified lines | ||
| 588 | 603 | unsigned long flags; |
| 589 | 604 | |
| 590 | 605 | |
| 591 | − spin_lock_irqsave(&irq_lock, flags); | |
| 606 | + raw_spin_lock_irqsave(&irq_lock, flags); | |
| 592 | 607 | list_for_each_entry(entry, &active_fds, list) { |
| 593 | 608 | if (entry->suspended) { |
| 594 | 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 | 622 | irqs_suspended = false; |
| 608 | 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 | 628 | struct irq_entry *entry; |
| 614 | 629 | unsigned long flags; |
| 615 | 630 | |
| 616 | − spin_lock_irqsave(&irq_lock, flags); | |
| 631 | + raw_spin_lock_irqsave(&irq_lock, flags); | |
| 617 | 632 | list_for_each_entry(entry, &active_fds, list) { |
| 618 | 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 | 645 | unlock: |
| 631 | − spin_unlock_irqrestore(&irq_lock, flags); | |
| 646 | + raw_spin_unlock_irqrestore(&irq_lock, flags); | |
| 632 | 647 | return 0; |
| 633 | 648 | } |
| 634 | 649 | #else |
| @@ -191,7 +191,15 @@ void initial_thread_cb(void (*proc)(void *), void *arg) · 190 unmodified lines | ||
| 191 | 191 | int arch_dup_task_struct(struct task_struct *dst, |
| 192 | 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 | 203 | return 0; |
| 196 | 204 | } |
| 197 | 205 | |
| @@ -181,6 +181,10 @@ extern char __syscall_stub_start[]; · 180 unmodified lines | ||
| 181 | 181 | |
| 182 | 182 | static int stub_exe_fd; |
| 183 | 183 | |
| 184 | +#ifndef CLOSE_RANGE_CLOEXEC | |
| 185 | +#define CLOSE_RANGE_CLOEXEC (1U << 2) | |
| 186 | +#endif | |
| 187 | + | |
| 184 | 188 | static int userspace_tramp(void *stack) |
| 185 | 189 | { |
| 186 | 190 | char *const argv[] = { "uml-userspace", NULL }; |
| @@ -202,8 +206,12 @@ static int userspace_tramp(void *stack) · 15 unmodified lines | ||
| 202 | 206 | init_data.stub_data_fd = phys_mapping(uml_to_phys(stack), &offset); |
| 203 | 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 */ | |
| 206 | − close_range(0, ~0U, CLOSE_RANGE_CLOEXEC); | |
| 209 | + /* | |
| 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 | 216 | fcntl(init_data.stub_data_fd, F_SETFD, 0); |
| 209 | 217 | for (iomem = iomem_regions; iomem; iomem = iomem->next) |
| @@ -224,7 +232,9 @@ static int userspace_tramp(void *stack) · 14 unmodified lines | ||
| 224 | 232 | if (ret != sizeof(init_data)) |
| 225 | 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 | 239 | exit(5); |
| 230 | 240 | } |
| @@ -2599,7 +2599,8 @@ config MITIGATION_IBPB_ENTRY · 2598 unmodified lines | ||
| 2599 | 2599 | depends on CPU_SUP_AMD && X86_64 |
| 2600 | 2600 | default y |
| 2601 | 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 | 2605 | config MITIGATION_IBRS_ENTRY |
| 2605 | 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 | 25 | # avoid errors with '-march=i386', and future flags may depend on the target to |
| 26 | 26 | # be valid. |
| 27 | 27 | KBUILD_CFLAGS := -m$(BITS) -O2 $(CLANG_FLAGS) |
| 28 | +KBUILD_CFLAGS += -std=gnu11 | |
| 28 | 29 | KBUILD_CFLAGS += -fno-strict-aliasing -fPIE |
| 29 | 30 | KBUILD_CFLAGS += -Wundef |
| 30 | 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 | 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 | 4915 | pmu->config_mask |= ARCH_PERFMON_EVENTSEL_UMASK2; |
| 4914 | − if (ebx & ARCH_PERFMON_EXT_EQ) | |
| 4916 | + if (ebx.split.eq) | |
| 4915 | 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 | 4920 | cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF, |
| 4919 | − &eax, &ebx, &ecx, &edx); | |
| 4920 | − pmu->cntr_mask64 = eax; | |
| 4921 | − pmu->fixed_cntr_mask64 = ebx; | |
| 4921 | + &cntr, &fixed_cntr, &ecx, &edx); | |
| 4922 | + pmu->cntr_mask64 = cntr; | |
| 4923 | + pmu->fixed_cntr_mask64 = fixed_cntr; | |
| 4922 | 4924 | } |
| 4923 | 4925 | |
| 4924 | 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 | 4943 | else |
| 4942 | 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 | 4946 | intel_pmu_check_event_constraints(pmu->event_constraints, |
| 4950 | 4947 | pmu->cntr_mask64, |
| 4951 | 4948 | pmu->fixed_cntr_mask64, |
| @@ -5023,9 +5020,6 @@ static bool init_hybrid_pmu(int cpu) · 71 unmodified lines | ||
| 5023 | 5020 | |
| 5024 | 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 | 5023 | pr_cont("\n"); |
| 5030 | 5024 | |
| 5031 | 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 | 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 | 5050 | intel_pmu_lbr_reset(); |
| 5054 | 5051 | |
| 5055 | 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 | 6367 | pmu->intel_cap.capabilities = x86_pmu.intel_cap.capabilities; |
| 6371 | 6368 | if (pmu->pmu_type & hybrid_small_tiny) { |
| 6372 | 6369 | pmu->intel_cap.perf_metrics = 0; |
| 6373 | − pmu->intel_cap.pebs_output_pt_available = 1; | |
| 6374 | 6370 | pmu->mid_ack = true; |
| 6375 | 6371 | } else if (pmu->pmu_type & hybrid_big) { |
| 6376 | 6372 | pmu->intel_cap.perf_metrics = 1; |
| 6377 | − pmu->intel_cap.pebs_output_pt_available = 0; | |
| 6378 | 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 | 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 | 2590 | pr_cont("PEBS-via-PT, "); |
| 2583 | 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 | 370 | unsigned int rapl_pmu_idx; |
| 371 | 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 | 377 | /* unsupported modes and filters */ |
| 374 | 378 | if (event->attr.sample_period) /* no sampling */ |
| 375 | 379 | return -EINVAL; |
| @@ -387,10 +391,6 @@ static int rapl_pmu_event_init(struct perf_event *event) · 11 unmodified lines | ||
| 387 | 391 | rapl_pmus_scope = rapl_pmus->pmu.scope; |
| 388 | 392 | |
| 389 | 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 | 394 | cfg = array_index_nospec((long)cfg, NR_RAPL_PKG_DOMAINS + 1); |
| 395 | 395 | if (!cfg || cfg >= NR_RAPL_PKG_DOMAINS + 1) |
| 396 | 396 | return -EINVAL; |
| @@ -398,10 +398,6 @@ static int rapl_pmu_event_init(struct perf_event *event) · 1 unmodified line | ||
| 398 | 398 | bit = cfg - 1; |
| 399 | 399 | event->hw.event_base = rapl_model->rapl_pkg_msrs[bit].msr; |
| 400 | 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 | 401 | cfg = array_index_nospec((long)cfg, NR_RAPL_CORE_DOMAINS + 1); |
| 406 | 402 | if (!cfg || cfg >= NR_RAPL_PKG_DOMAINS + 1) |
| 407 | 403 | return -EINVAL; |
| @@ -48,6 +48,7 @@ KVM_X86_OP(set_idt) · 47 unmodified lines | ||
| 48 | 48 | KVM_X86_OP(get_gdt) |
| 49 | 49 | KVM_X86_OP(set_gdt) |
| 50 | 50 | KVM_X86_OP(sync_dirty_debug_regs) |
| 51 | +KVM_X86_OP(set_dr6) | |
| 51 | 52 | KVM_X86_OP(set_dr7) |
| 52 | 53 | KVM_X86_OP(cache_reg) |
| 53 | 54 | KVM_X86_OP(get_rflags) |
| @@ -1696,6 +1696,7 @@ struct kvm_x86_ops { · 1695 unmodified lines | ||
| 1696 | 1696 | void (*get_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); |
| 1697 | 1697 | void (*set_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); |
| 1698 | 1698 | void (*sync_dirty_debug_regs)(struct kvm_vcpu *vcpu); |
| 1699 | + void (*set_dr6)(struct kvm_vcpu *vcpu, unsigned long value); | |
| 1699 | 1700 | void (*set_dr7)(struct kvm_vcpu *vcpu, unsigned long value); |
| 1700 | 1701 | void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); |
| 1701 | 1702 | unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); |
| @@ -395,7 +395,8 @@ · 394 unmodified lines | ||
| 395 | 395 | #define MSR_IA32_PASID_VALID BIT_ULL(31) |
| 396 | 396 | |
| 397 | 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 | 400 | #define DEBUGCTLMSR_BTF_SHIFT 1 |
| 400 | 401 | #define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */ |
| 401 | 402 | #define DEBUGCTLMSR_BUS_LOCK_DETECT (1UL << 2) |
| @@ -188,11 +188,33 @@ union cpuid10_edx { · 187 unmodified lines | ||
| 188 | 188 | * detection/enumeration details: |
| 189 | 189 | */ |
| 190 | 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 | 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 | 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 | 532 | #ifdef CONFIG_KVM_AMD_SEV |
| 533 | 533 | bool snp_probe_rmptable_info(void); |
| 534 | +int snp_rmptable_init(void); | |
| 534 | 535 | int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level); |
| 535 | 536 | void snp_dump_hva_rmpentry(unsigned long address); |
| 536 | 537 | int psmash(u64 pfn); |
| @@ -541,6 +542,7 @@ void kdump_sev_callback(void); · 4 unmodified lines | ||
| 541 | 542 | void snp_fixup_e820_tables(void); |
| 542 | 543 | #else |
| 543 | 544 | static inline bool snp_probe_rmptable_info(void) { return false; } |
| 545 | +static inline int snp_rmptable_init(void) { return -ENOSYS; } | |
| 544 | 546 | static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; } |
| 545 | 547 | static inline void snp_dump_hva_rmpentry(unsigned long address) {} |
| 546 | 548 | static inline int psmash(u64 pfn) { return -ENODEV; } |
| @@ -1115,6 +1115,8 @@ do_cmd_auto: · 1114 unmodified lines | ||
| 1115 | 1115 | |
| 1116 | 1116 | case RETBLEED_MITIGATION_IBPB: |
| 1117 | 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 | 1122 | * IBPB on entry already obviates the need for |
| @@ -1124,9 +1126,6 @@ do_cmd_auto: · 3 unmodified lines | ||
| 1124 | 1126 | setup_clear_cpu_cap(X86_FEATURE_UNRET); |
| 1125 | 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 | 1130 | * There is no need for RSB filling: entry_ibpb() ensures |
| 1132 | 1131 | * all predictions, including the RSB, are invalidated, |
| @@ -2646,6 +2645,7 @@ static void __init srso_select_mitigation(void) · 1513 unmodified lines | ||
| 2646 | 2645 | if (IS_ENABLED(CONFIG_MITIGATION_IBPB_ENTRY)) { |
| 2647 | 2646 | if (has_microcode) { |
| 2648 | 2647 | setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); |
| 2648 | + setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); | |
| 2649 | 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 | 2656 | setup_clear_cpu_cap(X86_FEATURE_UNRET); |
| 2657 | 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 | 2666 | } else { |
| 2660 | 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 | 2671 | ibpb_on_vmexit: |
| 2665 | 2672 | case SRSO_CMD_IBPB_ON_VMEXIT: |
| 2666 | − if (IS_ENABLED(CONFIG_MITIGATION_SRSO)) { | |
| 2667 | − if (!boot_cpu_has(X86_FEATURE_ENTRY_IBPB) && has_microcode) { | |
| 2673 | + if (IS_ENABLED(CONFIG_MITIGATION_IBPB_ENTRY)) { | |
| 2674 | + if (has_microcode) { | |
| 2668 | 2675 | setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); |
| 2669 | 2676 | srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT; |
| 2670 | 2677 | |
| @@ -2676,8 +2683,8 @@ ibpb_on_vmexit: · 5 unmodified lines | ||
| 2676 | 2683 | setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT); |
| 2677 | 2684 | } |
| 2678 | 2685 | } else { |
| 2679 | − pr_err("WARNING: kernel not compiled with MITIGATION_SRSO.\n"); | |
| 2680 | − } | |
| 2686 | + pr_err("WARNING: kernel not compiled with MITIGATION_IBPB_ENTRY.\n"); | |
| 2687 | + } | |
| 2681 | 2688 | break; |
| 2682 | 2689 | default: |
| 2683 | 2690 | break; |
| @@ -1180,7 +1180,7 @@ void kvm_set_cpu_caps(void) · 1179 unmodified lines | ||
| 1180 | 1180 | SYNTHESIZED_F(SBPB), |
| 1181 | 1181 | SYNTHESIZED_F(IBPB_BRTYPE), |
| 1182 | 1182 | SYNTHESIZED_F(SRSO_NO), |
| 1183 | − SYNTHESIZED_F(SRSO_USER_KERNEL_NO), | |
| 1183 | + F(SRSO_USER_KERNEL_NO), | |
| 1184 | 1184 | ); |
| 1185 | 1185 | |
| 1186 | 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 | 2226 | u32 vector; |
| 2227 | 2227 | bool all_cpus; |
| 2228 | 2228 | |
| 2229 | + if (!lapic_in_kernel(vcpu)) | |
| 2230 | + return HV_STATUS_INVALID_HYPERCALL_INPUT; | |
| 2231 | + | |
| 2229 | 2232 | if (hc->code == HVCALL_SEND_IPI) { |
| 2230 | 2233 | if (!hc->fast) { |
| 2231 | 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 | 2855 | ent->eax |= HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED; |
| 2853 | 2856 | ent->eax |= HV_X64_APIC_ACCESS_RECOMMENDED; |
| 2854 | 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 | 2860 | ent->eax |= HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED; |
| 2857 | 2861 | if (evmcs_ver) |
| 2858 | 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 | 5540 | union kvm_mmu_page_role root_role; |
| 5541 | 5541 | |
| 5542 | 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 | 5545 | root_role = cpu_role.base; |
| 5546 | 5546 | root_role.level = kvm_mmu_get_tdp_level(vcpu); |
| @@ -7120,6 +7120,19 @@ static void mmu_destroy_caches(void) · 1573 unmodified lines | ||
| 7120 | 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 | 7136 | static int get_nx_huge_pages(char *buffer, const struct kernel_param *kp) |
| 7124 | 7137 | { |
| 7125 | 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 | 7193 | kvm_mmu_zap_all_fast(kvm); |
| 7181 | 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 | 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 | 7328 | mutex_lock(&kvm_lock); |
| 7316 | 7329 | |
| 7317 | 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 | 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 | 7465 | struct kvm_arch *ka = container_of(once, struct kvm_arch, nx_once); |
| 7453 | 7466 | struct kvm *kvm = container_of(ka, struct kvm, arch); |
| 7467 | + struct vhost_task *nx_thread; | |
| 7454 | 7468 | |
| 7455 | 7469 | kvm->arch.nx_huge_page_last = get_jiffies_64(); |
| 7456 | − kvm->arch.nx_huge_page_recovery_thread = vhost_task_create( | |
| 7457 | − kvm_nx_huge_page_recovery_worker, kvm_nx_huge_page_recovery_worker_kill, | |
| 7458 | − kvm, "kvm-nx-lpage-recovery"); | |
| 7470 | + nx_thread = vhost_task_create(kvm_nx_huge_page_recovery_worker, | |
| 7471 | + kvm_nx_huge_page_recovery_worker_kill, | |
| 7472 | + kvm, "kvm-nx-lpage-recovery"); | |
| 7459 | 7473 | |
| 7460 | − if (kvm->arch.nx_huge_page_recovery_thread) | |
| 7461 | − vhost_task_start(kvm->arch.nx_huge_page_recovery_thread); | |
| 7474 | + if (!nx_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 | 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 | 646 | u32 pause_count12; |
| 647 | 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 | 655 | * Filled at exit: exit_code, exit_code_hi, exit_info_1, exit_info_2, |
| 651 | 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 | 771 | * Merge guest and host intercepts - must be called with vcpu in |
| 772 | 772 | * guest-mode to take effect. |
| @@ -2972,6 +2972,16 @@ void __init sev_hardware_setup(void) · 2971 unmodified lines | ||
| 2972 | 2972 | WARN_ON_ONCE(!boot_cpu_has(X86_FEATURE_FLUSHBYASID))) |
| 2973 | 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 | 2985 | /* Retrieve SEV CPUID information */ |
| 2976 | 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 | 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 | 1999 | return; |
| 2000 | 2000 | |
| 2001 | 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 | 4247 | * Run with all-zero DR6 unless needed, so that we can get the exact cause |
| 4248 | 4248 | * of a #DB. |
| 4249 | 4249 | */ |
| 4250 | − if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) | |
| 4251 | − svm_set_dr6(svm, vcpu->arch.dr6); | |
| 4252 | − else | |
| 4253 | − svm_set_dr6(svm, DR6_ACTIVE_LOW); | |
| 4250 | + if (likely(!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))) | |
| 4251 | + svm_set_dr6(vcpu, DR6_ACTIVE_LOW); | |
| 4254 | 4252 | |
| 4255 | 4253 | clgi(); |
| 4256 | 4254 | kvm_load_guest_xsave_state(vcpu); |
| @@ -5043,6 +5041,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { · 786 unmodified lines | ||
| 5043 | 5041 | .set_idt = svm_set_idt, |
| 5044 | 5042 | .get_gdt = svm_get_gdt, |
| 5045 | 5043 | .set_gdt = svm_set_gdt, |
| 5044 | + .set_dr6 = svm_set_dr6, | |
| 5046 | 5045 | .set_dr7 = svm_set_dr7, |
| 5047 | 5046 | .sync_dirty_debug_regs = svm_sync_dirty_debug_regs, |
| 5048 | 5047 | .cache_reg = svm_cache_reg, |
| @@ -61,6 +61,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = { · 60 unmodified lines | ||
| 61 | 61 | .set_idt = vmx_set_idt, |
| 62 | 62 | .get_gdt = vmx_get_gdt, |
| 63 | 63 | .set_gdt = vmx_set_gdt, |
| 64 | + .set_dr6 = vmx_set_dr6, | |
| 64 | 65 | .set_dr7 = vmx_set_dr7, |
| 65 | 66 | .sync_dirty_debug_regs = vmx_sync_dirty_debug_regs, |
| 66 | 67 | .cache_reg = vmx_cache_reg, |
| @@ -5648,6 +5648,12 @@ void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu) · 5647 unmodified lines | ||
| 5648 | 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 | 5657 | void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val) |
| 5652 | 5658 | { |
| 5653 | 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 | 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 | 7426 | /* When single-stepping over STI and MOV SS, we must clear the |
| 7425 | 7427 | * corresponding interruptibility bits in the guest state. Otherwise |
| 7426 | 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 | 73 | void vmx_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt); |
| 74 | 74 | void vmx_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt); |
| 75 | 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 | 77 | void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val); |
| 77 | 78 | void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu); |
| 78 | 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 | 10961 | set_debugreg(vcpu->arch.eff_db[1], 1); |
| 10962 | 10962 | set_debugreg(vcpu->arch.eff_db[2], 2); |
| 10963 | 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 | 10967 | } else if (unlikely(hw_breakpoint_active())) { |
| 10965 | 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 | 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 | 12748 | return 0; |
| 12745 | 12749 | |
| 12746 | 12750 | out_uninit_mmu: |
| @@ -12750,12 +12754,6 @@ out: · 3 unmodified lines | ||
| 12750 | 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 | 12757 | static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu) |
| 12760 | 12758 | { |
| 12761 | 12759 | vcpu_load(vcpu); |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <registers.h> |
| 19 | 19 | #include <sys/mman.h> |
| 20 | 20 | |
| 21 | +static unsigned long ptrace_regset; | |
| 21 | 22 | unsigned long host_fp_size; |
| 22 | 23 | |
| 23 | 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 | 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 | 32 | return -errno; |
| 32 | 33 | return 0; |
| 33 | 34 | } |
| @@ -39,7 +40,7 @@ int put_fp_registers(int pid, unsigned long *regs) · 5 unmodified lines | ||
| 39 | 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 | 44 | return -errno; |
| 44 | 45 | return 0; |
| 45 | 46 | } |
| @@ -58,9 +59,23 @@ int arch_init_registers(int pid) · 12 unmodified lines | ||
| 58 | 59 | return -ENOMEM; |
| 59 | 60 | |
| 60 | 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 | 64 | if (ret) |
| 63 | 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 | 79 | munmap(iov.iov_base, 2 * 1024 * 1024); |
| 65 | 80 | |
| 66 | 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 | 187 | * Put magic/size values for userspace. We do not bother to verify them |
| 188 | 188 | * later on, however, userspace needs them should it try to read the |
| 189 | 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 | 196 | BUILD_BUG_ON(sizeof(int) != FP_XSTATE_MAGIC2_SIZE); |
| 192 | 197 | #ifdef CONFIG_X86_32 |
| 193 | 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 | 372 | int err = 0, sig = ksig->sig; |
| 368 | 373 | unsigned long fp_to; |
| 369 | 374 | |
| 370 | − frame = (struct rt_sigframe __user *) | |
| 371 | − round_down(stack_top - sizeof(struct rt_sigframe), 16); | |
| 375 | + frame = (void __user *)stack_top - sizeof(struct rt_sigframe); | |
| 372 | 376 | |
| 373 | 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 | 383 | /* Subtract 128 for a red zone and 8 for proper alignment */ |
| 377 | 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 | 505 | * described in the SNP_INIT_EX firmware command description in the SNP |
| 506 | 506 | * firmware ABI spec. |
| 507 | 507 | */ |
| 508 | −static int __init snp_rmptable_init(void) | |
| 508 | +int __init snp_rmptable_init(void) | |
| 509 | 509 | { |
| 510 | 510 | unsigned int i; |
| 511 | 511 | u64 val; |
| 512 | 512 | |
| 513 | − if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) | |
| 514 | − return 0; | |
| 513 | + if (WARN_ON_ONCE(!cc_platform_has(CC_ATTR_HOST_SEV_SNP))) | |
| 514 | + return -ENOSYS; | |
| 515 | 515 | |
| 516 | − if (!amd_iommu_snp_en) | |
| 517 | − goto nosnp; | |
| 516 | + if (WARN_ON_ONCE(!amd_iommu_snp_en)) | |
| 517 | + return -ENOSYS; | |
| 518 | 518 | |
| 519 | 519 | if (!setup_rmptable()) |
| 520 | − goto nosnp; | |
| 520 | + return -ENOSYS; | |
| 521 | 521 | |
| 522 | 522 | /* |
| 523 | 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 | 530 | /* Zero out the RMP bookkeeping area */ |
| 531 | 531 | if (!clear_rmptable_bookkeeping()) { |
| 532 | 532 | free_rmp_segment_table(); |
| 533 | − goto nosnp; | |
| 533 | + return -ENOSYS; | |
| 534 | 534 | } |
| 535 | 535 | |
| 536 | 536 | /* Zero out the RMP entries */ |
| @@ -562,17 +562,8 @@ skip_enable: · 25 unmodified lines | ||
| 562 | 562 | crash_kexec_post_notifiers = true; |
| 563 | 563 | |
| 564 | 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 | 567 | static void set_rmp_segment_info(unsigned int segment_shift) |
| 577 | 568 | { |
| 578 | 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 | 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 | 160 | * Note about cr3 (pagetable base) values: |
| 116 | 161 | * |
| @@ -814,6 +859,9 @@ static void __init xen_after_bootmem(void) · 697 unmodified lines | ||
| 814 | 859 | SetPagePinned(virt_to_page(level3_user_vsyscall)); |
| 815 | 860 | #endif |
| 816 | 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 | 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 | 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 | 2254 | #define VOID_PTE (mfn_pte(0, __pgprot(0))) |
| 2211 | 2255 | static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order, |
| 2212 | 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 | 2367 | unsigned int address_bits, |
| 2324 | 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 | 2371 | unsigned long flags; |
| 2328 | 2372 | int success; |
| 2329 | 2373 | unsigned long vstart = (unsigned long)phys_to_virt(pstart); |
| 2330 | 2374 | |
| 2331 | − if (unlikely(order > MAX_CONTIG_ORDER)) | |
| 2332 | − return -ENOMEM; | |
| 2375 | + if (unlikely(order > discontig_frames_order)) { | |
| 2376 | + if (!discontig_frames_dyn) | |
| 2377 | + return -ENOMEM; | |
| 2378 | + | |
| 2379 | + if (alloc_discontig_frames(order)) | |
| 2380 | + return -ENOMEM; | |
| 2381 | + } | |
| 2333 | 2382 | |
| 2334 | 2383 | memset((void *) vstart, 0, PAGE_SIZE << order); |
| 2335 | 2384 | |
| 2336 | 2385 | spin_lock_irqsave(&xen_reservation_lock, flags); |
| 2337 | 2386 | |
| 2387 | + in_frames = discontig_frames; | |
| 2388 | + | |
| 2338 | 2389 | /* 1. Zap current PTEs, remembering MFNs. */ |
| 2339 | 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 | 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 | 2413 | unsigned long flags; |
| 2363 | 2414 | int success; |
| 2364 | 2415 | unsigned long vstart; |
| 2365 | 2416 | |
| 2366 | − if (unlikely(order > MAX_CONTIG_ORDER)) | |
| 2417 | + if (unlikely(order > discontig_frames_order)) | |
| 2367 | 2418 | return; |
| 2368 | 2419 | |
| 2369 | 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 | 2423 | spin_lock_irqsave(&xen_reservation_lock, flags); |
| 2373 | 2424 | |
| 2425 | + out_frames = discontig_frames; | |
| 2426 | + | |
| 2374 | 2427 | /* 1. Find start MFN of contiguous extent. */ |
| 2375 | 2428 | in_frame = virt_to_mfn((void *)vstart); |
| 2376 | 2429 | |
| @@ -100,9 +100,6 @@ SYM_FUNC_START(xen_hypercall_hvm) · 99 unmodified lines | ||
| 100 | 100 | push %r10 |
| 101 | 101 | push %r9 |
| 102 | 102 | push %r8 |
| 103 | −#ifdef CONFIG_FRAME_POINTER | |
| 104 | − pushq $0 /* Dummy push for stack alignment. */ | |
| 105 | −#endif | |
| 106 | 103 | #endif |
| 107 | 104 | /* Set the vendor specific function. */ |
| 108 | 105 | call __xen_hypercall_setfunc |
| @@ -117,11 +114,8 @@ SYM_FUNC_START(xen_hypercall_hvm) · 8 unmodified lines | ||
| 117 | 114 | pop %ebx |
| 118 | 115 | pop %eax |
| 119 | 116 | #else |
| 120 | − lea xen_hypercall_amd(%rip), %rbx | |
| 121 | − cmp %rax, %rbx | |
| 122 | −#ifdef CONFIG_FRAME_POINTER | |
| 123 | − pop %rax /* Dummy pop. */ | |
| 124 | −#endif | |
| 117 | + lea xen_hypercall_amd(%rip), %rcx | |
| 118 | + cmp %rax, %rcx | |
| 125 | 119 | pop %r8 |
| 126 | 120 | pop %r9 |
| 127 | 121 | pop %r10 |
| @@ -132,6 +126,7 @@ SYM_FUNC_START(xen_hypercall_hvm) · 4 unmodified lines | ||
| 132 | 126 | pop %rcx |
| 133 | 127 | pop %rax |
| 134 | 128 | #endif |
| 129 | + FRAME_END | |
| 135 | 130 | /* Use correct hypercall function. */ |
| 136 | 131 | jz xen_hypercall_amd |
| 137 | 132 | jmp xen_hypercall_intel |
| @@ -53,13 +53,25 @@ int mac_partition(struct parsed_partitions *state) · 52 unmodified lines | ||
| 53 | 53 | } |
| 54 | 54 | secsize = be16_to_cpu(md->block_size); |
| 55 | 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 | 66 | datasize = round_down(secsize, 512); |
| 57 | 67 | data = read_part_sector(state, datasize / 512, §); |
| 58 | 68 | if (!data) |
| 59 | 69 | return -1; |
| 60 | 70 | partoffset = secsize % 512; |
| 61 | − if (partoffset + sizeof(*part) > datasize) | |
| 71 | + if (partoffset + sizeof(*part) > datasize) { | |
| 72 | + put_dev_sector(sect); | |
| 62 | 73 | return -1; |
| 74 | + } | |
| 63 | 75 | part = (struct mac_partition *) (data + partoffset); |
| 64 | 76 | if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { |
| 65 | 77 | put_dev_sector(sect); |
| @@ -112,8 +124,8 @@ int mac_partition(struct parsed_partitions *state) · 46 unmodified lines | ||
| 112 | 124 | int i, l; |
| 113 | 125 | |
| 114 | 126 | goodness++; |
| 115 | − l = strlen(part->name); | |
| 116 | − if (strcmp(part->name, "/") == 0) | |
| 127 | + l = strnlen(part->name, sizeof(part->name)); | |
| 128 | + if (strncmp(part->name, "/", sizeof(part->name)) == 0) | |
| 117 | 129 | goodness++; |
| 118 | 130 | for (i = 0; i <= l - 4; ++i) { |
| 119 | 131 | if (strncasecmp(part->name + i, "root", |
| @@ -21,6 +21,11 @@ · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 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 | 30 | * Bind the driver base on (vendor_id, device_id) pair and later use the |
| 26 | 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 | 397 | if (ivpu_fw_is_cold_boot(vdev)) { |
| 398 | 398 | ret = ivpu_pm_dct_init(vdev); |
| 399 | 399 | if (ret) |
| 400 | − goto err_diagnose_failure; | |
| 400 | + goto err_disable_ipc; | |
| 401 | 401 | |
| 402 | 402 | ret = ivpu_hw_sched_init(vdev); |
| 403 | 403 | if (ret) |
| 404 | − goto err_diagnose_failure; | |
| 404 | + goto err_disable_ipc; | |
| 405 | 405 | } |
| 406 | 406 | |
| 407 | 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 | 413 | err_diagnose_failure: |
| 410 | 414 | ivpu_hw_diagnose_failure(vdev); |
| 411 | 415 | ivpu_mmu_evtq_dump(vdev); |
| @@ -115,41 +115,57 @@ err_power_down: · 114 unmodified lines | ||
| 115 | 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); | |
| 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); | |
| 120 | + pm_runtime_disable(vdev->drm.dev); | |
| 133 | 121 | |
| 134 | 122 | atomic_inc(&vdev->pm->reset_counter); |
| 135 | 123 | atomic_set(&vdev->pm->reset_pending, 1); |
| 136 | 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 | 131 | ivpu_pm_prepare_cold_boot(vdev); |
| 140 | 132 | ivpu_jobs_abort_all(vdev); |
| 141 | 133 | ivpu_ms_cleanup_all(vdev); |
| 142 | 134 | |
| 143 | 135 | ret = ivpu_resume(vdev); |
| 144 | − if (ret) | |
| 136 | + if (ret) { | |
| 145 | 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 | 143 | up_write(&vdev->pm->reset_lock); |
| 148 | 144 | atomic_set(&vdev->pm->reset_pending, 0); |
| 149 | 145 | |
| 150 | − kobject_uevent_env(&vdev->drm.dev->kobj, KOBJ_CHANGE, evt); | |
| 151 | 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 | 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 | 325 | int ret; |
| 310 | 326 | |
| 311 | 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 | 333 | return ret; |
| 315 | 334 | } |
| @@ -325,16 +344,13 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev) · 9 unmodified lines | ||
| 325 | 344 | struct ivpu_device *vdev = pci_get_drvdata(pdev); |
| 326 | 345 | |
| 327 | 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); | |
| 332 | − down_write(&vdev->pm->reset_lock); | |
| 333 | − ivpu_prepare_for_reset(vdev); | |
| 334 | − ivpu_hw_reset(vdev); | |
| 335 | − ivpu_pm_prepare_cold_boot(vdev); | |
| 336 | − ivpu_jobs_abort_all(vdev); | |
| 337 | − ivpu_ms_cleanup_all(vdev); | |
| 348 | + ivpu_pm_reset_begin(vdev); | |
| 349 | + | |
| 350 | + if (!pm_runtime_status_suspended(vdev->drm.dev)) { | |
| 351 | + ivpu_prepare_for_reset(vdev); | |
| 352 | + ivpu_hw_reset(vdev); | |
| 353 | + } | |
| 338 | 354 | |
| 339 | 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 | 358 | void ivpu_pm_reset_done_cb(struct pci_dev *pdev) |
| 343 | 359 | { |
| 344 | 360 | struct ivpu_device *vdev = pci_get_drvdata(pdev); |
| 345 | − int ret; | |
| 346 | 361 | |
| 347 | 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); | |
| 356 | − pm_runtime_put_autosuspend(vdev->drm.dev); | |
| 364 | + ivpu_pm_reset_complete(vdev); | |
| 365 | + | |
| 366 | + ivpu_dbg(vdev, PM, "Post-reset done.\n"); | |
| 357 | 367 | } |
| 358 | 368 | |
| 359 | 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 | 164 | void *platform_timer; |
| 165 | 165 | struct acpi_table_gtdt *gtdt; |
| 166 | − int cnt = 0; | |
| 166 | + u32 cnt = 0; | |
| 167 | 167 | |
| 168 | 168 | gtdt = container_of(table, struct acpi_table_gtdt, header); |
| 169 | 169 | acpi_gtdt_desc.gtdt = gtdt; |
| @@ -188,13 +188,17 @@ int __init acpi_gtdt_init(struct acpi_table_header *table, · 18 unmodified lines | ||
| 188 | 188 | cnt++; |
| 189 | 189 | |
| 190 | 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 | 196 | acpi_gtdt_desc.platform_timer = NULL; |
| 192 | − pr_err(FW_BUG "invalid timer data.\n"); | |
| 193 | − return -EINVAL; | |
| 197 | + return 0; | |
| 194 | 198 | } |
| 195 | 199 | |
| 196 | 200 | if (platform_timer_count) |
| 197 | − *platform_timer_count = gtdt->platform_timer_count; | |
| 201 | + *platform_timer_count = cnt; | |
| 198 | 202 | |
| 199 | 203 | return 0; |
| 200 | 204 | } |
| @@ -287,9 +287,7 @@ static acpi_status acpi_platformrt_space_handler(u32 function, · 286 unmodified lines | ||
| 287 | 287 | if (!handler || !module) |
| 288 | 288 | goto invalid_guid; |
| 289 | 289 | |
| 290 | − if (!handler->handler_addr || | |
| 291 | − !handler->static_data_buffer_addr || | |
| 292 | − !handler->acpi_param_buffer_addr) { | |
| 290 | + if (!handler->handler_addr) { | |
| 293 | 291 | buffer->prm_status = PRM_HANDLER_ERROR; |
| 294 | 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 | 1188 | break; |
| 1189 | 1189 | } |
| 1190 | − if (nval == 0) | |
| 1191 | − return -EINVAL; | |
| 1192 | 1190 | |
| 1193 | 1191 | if (obj->type == ACPI_TYPE_BUFFER) { |
| 1194 | 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 | 1210 | ret = acpi_copy_property_array_uint(items, (u64 *)val, nval); |
| 1213 | 1211 | break; |
| 1214 | 1212 | case DEV_PROP_STRING: |
| 1215 | − ret = acpi_copy_property_array_string( | |
| 1216 | − items, (char **)val, | |
| 1217 | − min_t(u32, nval, obj->package.count)); | |
| 1213 | + nval = min_t(u32, nval, obj->package.count); | |
| 1214 | + if (nval == 0) | |
| 1215 | + return -ENODATA; | |
| 1216 | + | |
| 1217 | + ret = acpi_copy_property_array_string(items, (char **)val, nval); | |
| 1218 | 1218 | break; |
| 1219 | 1219 | default: |
| 1220 | 1220 | ret = -EINVAL; |
| @@ -563,6 +563,12 @@ static const struct dmi_system_id irq1_edge_low_force_override[] = { · 562 unmodified lines | ||
| 563 | 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 | 573 | /* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */ |
| 568 | 574 | .matches = { |
| @@ -6,7 +6,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \ · 5 unmodified lines | ||
| 6 | 6 | cpu.o firmware.o init.o map.o devres.o \ |
| 7 | 7 | attribute_container.o transport_class.o \ |
| 8 | 8 | topology.o container.o property.o cacheinfo.o \ |
| 9 | − swnode.o | |
| 9 | + swnode.o faux.o | |
| 10 | 10 | obj-$(CONFIG_AUXILIARY_BUS) += auxiliary.o |
| 11 | 11 | obj-$(CONFIG_DEVTMPFS) += devtmpfs.o |
| 12 | 12 | obj-y += power/ |
| @@ -137,6 +137,7 @@ int hypervisor_init(void); · 136 unmodified lines | ||
| 137 | 137 | static inline int hypervisor_init(void) { return 0; } |
| 138 | 138 | #endif |
| 139 | 139 | int platform_bus_init(void); |
| 140 | +int faux_bus_init(void); | |
| 140 | 141 | void cpu_dev_init(void); |
| 141 | 142 | void container_dev_init(void); |
| 142 | 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 | 32 | /* These are also core pieces, but must come after the |
| 33 | 33 | * core core pieces. |
| 34 | 34 | */ |
| 35 | + faux_bus_init(); | |
| 35 | 36 | of_core_init(); |
| 36 | 37 | platform_bus_init(); |
| 37 | 38 | auxiliary_bus_init(); |
| @@ -1191,24 +1191,18 @@ static pm_message_t resume_event(pm_message_t sleep_state) · 1190 unmodified lines | ||
| 1191 | 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 | 1196 | struct device_link *link; |
| 1197 | 1197 | int idx; |
| 1198 | 1198 | |
| 1199 | − if (dev->parent) { | |
| 1199 | + if (dev->parent) | |
| 1200 | 1200 | dev->parent->power.must_resume = true; |
| 1201 | − if (set_active) | |
| 1202 | − dev->parent->power.set_active = true; | |
| 1203 | − } | |
| 1204 | 1201 | |
| 1205 | 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 | 1205 | link->supplier->power.must_resume = true; |
| 1209 | − if (set_active) | |
| 1210 | − link->supplier->power.set_active = true; | |
| 1211 | − } | |
| 1212 | 1206 | |
| 1213 | 1207 | device_links_read_unlock(idx); |
| 1214 | 1208 | } |
| @@ -1287,9 +1281,12 @@ Skip: · 72 unmodified lines | ||
| 1287 | 1281 | dev->power.must_resume = true; |
| 1288 | 1282 | |
| 1289 | 1283 | if (dev->power.must_resume) { |
| 1290 | − dev->power.set_active = dev->power.set_active || | |
| 1291 | − dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND); | |
| 1292 | − dpm_superior_set_must_resume(dev, dev->power.set_active); | |
| 1284 | + if (dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) { | |
| 1285 | + dev->power.set_active = true; | |
| 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 | 1292 | Complete: |
| @@ -906,6 +906,7 @@ err_alloc: · 905 unmodified lines | ||
| 906 | 906 | kfree(d->wake_buf); |
| 907 | 907 | kfree(d->mask_buf_def); |
| 908 | 908 | kfree(d->mask_buf); |
| 909 | + kfree(d->main_status_buf); | |
| 909 | 910 | kfree(d->status_buf); |
| 910 | 911 | kfree(d->status_reg_buf); |
| 911 | 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 | 982 | kfree(d->wake_buf); |
| 982 | 983 | kfree(d->mask_buf_def); |
| 983 | 984 | kfree(d->mask_buf); |
| 985 | + kfree(d->main_status_buf); | |
| 984 | 986 | kfree(d->status_reg_buf); |
| 985 | 987 | kfree(d->status_buf); |
| 986 | 988 | if (d->config_buf) { |
| @@ -1127,8 +1127,8 @@ static void vdc_queue_drain(struct vdc_port *port) · 1126 unmodified lines | ||
| 1127 | 1127 | |
| 1128 | 1128 | spin_lock_irq(&port->vio.lock); |
| 1129 | 1129 | port->drain = 0; |
| 1130 | − blk_mq_unquiesce_queue(q, memflags); | |
| 1131 | − blk_mq_unfreeze_queue(q); | |
| 1130 | + blk_mq_unquiesce_queue(q); | |
| 1131 | + blk_mq_unfreeze_queue(q, memflags); | |
| 1132 | 1132 | } |
| 1133 | 1133 | |
| 1134 | 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 | 1320 | if (opcode == 0xfc01) |
| 1321 | 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 | 1327 | hdev->stat.cmd_tx++; |
| 1324 | 1328 | break; |
| 1325 | 1329 | case HCI_ACLDATA_PKT: |
| @@ -1357,7 +1361,6 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev, · 31 unmodified lines | ||
| 1357 | 1361 | opcode, btintel_pcie_alivectxt_state2str(old_ctxt), |
| 1358 | 1362 | btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); |
| 1359 | 1363 | if (opcode == HCI_OP_RESET) { |
| 1360 | − data->gp0_received = false; | |
| 1361 | 1364 | ret = wait_event_timeout(data->gp0_wait_q, |
| 1362 | 1365 | data->gp0_received, |
| 1363 | 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 | 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 | 661 | pos->bit); |
| 662 | 662 | } |
| 663 | 663 | |
| @@ -17,7 +17,8 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | config ARM_AIROHA_SOC_CPUFREQ |
| 19 | 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 | 22 | select PM_OPP |
| 22 | 23 | default ARCH_AIROHA |
| 23 | 24 | help |
| @@ -699,7 +699,7 @@ static void amd_pstate_adjust_perf(unsigned int cpu, · 698 unmodified lines | ||
| 699 | 699 | if (min_perf < lowest_nonlinear_perf) |
| 700 | 700 | min_perf = lowest_nonlinear_perf; |
| 701 | 701 | |
| 702 | − max_perf = cap_perf; | |
| 702 | + max_perf = cpudata->max_limit_perf; | |
| 703 | 703 | if (max_perf < min_perf) |
| 704 | 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 | 747 | guard(mutex)(&amd_pstate_driver_lock); |
| 748 | 748 | |
| 749 | 749 | ret = amd_pstate_cpu_boost_update(policy, state); |
| 750 | − policy->boost_enabled = !ret ? state : false; | |
| 751 | 750 | refresh_frequency_limits(policy); |
| 752 | 751 | |
| 753 | 752 | return ret; |
| @@ -822,25 +821,28 @@ static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata) · 68 unmodified lines | ||
| 822 | 821 | |
| 823 | 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 | 825 | struct amd_cpudata *cpudata; |
| 827 | 826 | u32 prev_high = 0, cur_high = 0; |
| 828 | 827 | int ret; |
| 829 | 828 | bool highest_perf_changed = false; |
| 830 | 829 | |
| 830 | + if (!amd_pstate_prefcore) | |
| 831 | + return; | |
| 832 | + | |
| 833 | + policy = cpufreq_cpu_get(cpu); | |
| 831 | 834 | if (!policy) |
| 832 | 835 | return; |
| 833 | 836 | |
| 834 | 837 | cpudata = policy->driver_data; |
| 835 | 838 | |
| 836 | − if (!amd_pstate_prefcore) | |
| 837 | − return; | |
| 838 | − | |
| 839 | 839 | guard(mutex)(&amd_pstate_driver_lock); |
| 840 | 840 | |
| 841 | 841 | ret = amd_get_highest_perf(cpu, &cur_high); |
| 842 | − if (ret) | |
| 843 | − goto free_cpufreq_put; | |
| 842 | + if (ret) { | |
| 843 | + cpufreq_cpu_put(policy); | |
| 844 | + return; | |
| 845 | + } | |
| 844 | 846 | |
| 845 | 847 | prev_high = READ_ONCE(cpudata->prefcore_ranking); |
| 846 | 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 | 852 | if (cur_high < CPPC_MAX_PERF) |
| 851 | 853 | sched_set_itmt_core_prio((int)cur_high, cpu); |
| 852 | 854 | } |
| 853 | − | |
| 854 | −free_cpufreq_put: | |
| 855 | 855 | cpufreq_cpu_put(policy); |
| 856 | 856 | |
| 857 | 857 | if (!highest_perf_changed) |
| @@ -1571,7 +1571,8 @@ static int cpufreq_online(unsigned int cpu) · 1570 unmodified lines | ||
| 1571 | 1571 | policy->cdev = of_cpufreq_cooling_register(policy); |
| 1572 | 1572 | |
| 1573 | 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 | 1576 | policy->boost_enabled = cpufreq_boost_enabled(); |
| 1576 | 1577 | ret = cpufreq_driver->set_boost(policy, policy->boost_enabled); |
| 1577 | 1578 | if (ret) { |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/types.h> |
| 20 | 20 | #include <linux/ccp.h> |
| 21 | 21 | |
| 22 | +#include "sev-dev.h" | |
| 22 | 23 | #include "ccp-dev.h" |
| 23 | 24 | #include "sp-dev.h" |
| 24 | 25 | |
| @@ -253,8 +254,12 @@ unlock: · 228 unmodified lines | ||
| 253 | 254 | static int __init sp_mod_init(void) |
| 254 | 255 | { |
| 255 | 256 | #ifdef CONFIG_X86 |
| 257 | + static bool initialized; | |
| 256 | 258 | int ret; |
| 257 | 259 | |
| 260 | + if (initialized) | |
| 261 | + return 0; | |
| 262 | + | |
| 258 | 263 | ret = sp_pci_init(); |
| 259 | 264 | if (ret) |
| 260 | 265 | return ret; |
| @@ -263,6 +268,8 @@ static int __init sp_mod_init(void) · 2 unmodified lines | ||
| 263 | 268 | psp_pci_init(); |
| 264 | 269 | #endif |
| 265 | 270 | |
| 271 | + initialized = true; | |
| 272 | + | |
| 266 | 273 | return 0; |
| 267 | 274 | #endif |
| 268 | 275 | |
| @@ -279,6 +286,13 @@ static int __init sp_mod_init(void) · 10 unmodified lines | ||
| 279 | 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 | 296 | static void __exit sp_mod_exit(void) |
| 283 | 297 | { |
| 284 | 298 | #ifdef CONFIG_X86 |
| @@ -887,7 +887,7 @@ static int tegra_adma_probe(struct platform_device *pdev) · 886 unmodified lines | ||
| 887 | 887 | const struct tegra_adma_chip_data *cdata; |
| 888 | 888 | struct tegra_adma *tdma; |
| 889 | 889 | struct resource *res_page, *res_base; |
| 890 | − int ret, i, page_no; | |
| 890 | + int ret, i; | |
| 891 | 891 | |
| 892 | 892 | cdata = of_device_get_match_data(&pdev->dev); |
| 893 | 893 | if (!cdata) { |
| @@ -914,9 +914,20 @@ static int tegra_adma_probe(struct platform_device *pdev) · 20 unmodified lines | ||
| 914 | 914 | |
| 915 | 915 | res_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "global"); |
| 916 | 916 | if (res_base) { |
| 917 | − page_no = (res_page->start - res_base->start) / cdata->ch_base_offset; | |
| 918 | − if (page_no <= 0) | |
| 917 | + resource_size_t page_offset, page_no; | |
| 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 | 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 | 931 | tdma->ch_page_no = page_no - 1; |
| 921 | 932 | tdma->base_addr = devm_ioremap_resource(&pdev->dev, res_base); |
| 922 | 933 | if (IS_ERR(tdma->base_addr)) |
| @@ -106,7 +106,7 @@ config ISCSI_IBFT · 105 unmodified lines | ||
| 106 | 106 | select ISCSI_BOOT_SYSFS |
| 107 | 107 | select ISCSI_IBFT_FIND if X86 |
| 108 | 108 | depends on ACPI && SCSI && SCSI_LOWLEVEL |
| 109 | − default n | |
| 109 | + default n | |
| 110 | 110 | help |
| 111 | 111 | This option enables support for detection and exposing of iSCSI |
| 112 | 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 | 934 | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO | |
| 935 | 935 | EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP | |
| 936 | 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 | 939 | snprintf(pos, size, "|attr=0x%016llx]", |
| 939 | 940 | (unsigned long long)attr); |
| 940 | 941 | else |
| 941 | 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 | 944 | attr & EFI_MEMORY_RUNTIME ? "RUN" : "", |
| 945 | + attr & EFI_MEMORY_HOT_PLUGGABLE ? "HP" : "", | |
| 944 | 946 | attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "", |
| 945 | 947 | attr & EFI_MEMORY_CPU_CRYPTO ? "CC" : "", |
| 946 | 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 | 25 | if (md->type != EFI_CONVENTIONAL_MEMORY) |
| 26 | 26 | return 0; |
| 27 | 27 | |
| 28 | + if (md->attribute & EFI_MEMORY_HOT_PLUGGABLE) | |
| 29 | + return 0; | |
| 30 | + | |
| 28 | 31 | if (efi_soft_reserve_enabled() && |
| 29 | 32 | (md->attribute & EFI_MEMORY_SP)) |
| 30 | 33 | return 0; |
| @@ -53,6 +53,9 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, · 52 unmodified lines | ||
| 53 | 53 | if (desc->type != EFI_CONVENTIONAL_MEMORY) |
| 54 | 54 | continue; |
| 55 | 55 | |
| 56 | + if (desc->attribute & EFI_MEMORY_HOT_PLUGGABLE) | |
| 57 | + continue; | |
| 58 | + | |
| 56 | 59 | if (efi_soft_reserve_enabled() && |
| 57 | 60 | (desc->attribute & EFI_MEMORY_SP)) |
| 58 | 61 | continue; |
| @@ -310,7 +310,10 @@ static ssize_t ibft_attr_show_nic(void *data, int type, char *buf) · 309 unmodified lines | ||
| 310 | 310 | str += sprintf_ipaddr(str, nic->ip_addr); |
| 311 | 311 | break; |
| 312 | 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 | 317 | str += sprintf(str, "%pI4", &val); |
| 315 | 318 | break; |
| 316 | 319 | case ISCSI_BOOT_ETH_PREFIX_LEN: |
| @@ -338,6 +338,7 @@ config GPIO_GRANITERAPIDS · 337 unmodified lines | ||
| 338 | 338 | |
| 339 | 339 | config GPIO_GRGPIO |
| 340 | 340 | tristate "Aeroflex Gaisler GRGPIO support" |
| 341 | + depends on OF || COMPILE_TEST | |
| 341 | 342 | select GPIO_GENERIC |
| 342 | 343 | select IRQ_DOMAIN |
| 343 | 344 | help |
| @@ -69,6 +69,22 @@ struct bcm_kona_gpio { · 68 unmodified lines | ||
| 69 | 69 | struct bcm_kona_gpio_bank { |
| 70 | 70 | int id; |
| 71 | 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 | 88 | /* Used in the interrupt handler */ |
| 73 | 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 | 102 | u32 val; |
| 87 | 103 | unsigned long flags; |
| 88 | 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)); | |
| 93 | − val |= BIT(gpio); | |
| 94 | − bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); | |
| 114 | + if (--bank->gpio_unlock_count[bit] == 0) { | |
| 115 | + raw_spin_lock_irqsave(&kona_gpio->lock, flags); | |
| 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 | 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 | 128 | u32 val; |
| 103 | 129 | unsigned long flags; |
| 104 | 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)); | |
| 109 | − val &= ~BIT(gpio); | |
| 110 | − bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val); | |
| 137 | + val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id)); | |
| 138 | + val &= ~BIT(bit); | |
| 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 | 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 | 393 | kona_gpio = irq_data_get_irq_chip_data(d); |
| 362 | 394 | reg_base = kona_gpio->reg_base; |
| 395 | + | |
| 363 | 396 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); |
| 364 | 397 | |
| 365 | 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 | 416 | kona_gpio = irq_data_get_irq_chip_data(d); |
| 384 | 417 | reg_base = kona_gpio->reg_base; |
| 418 | + | |
| 385 | 419 | raw_spin_lock_irqsave(&kona_gpio->lock, flags); |
| 386 | 420 | |
| 387 | 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 | 511 | static int bcm_kona_gpio_irq_reqres(struct irq_data *d) |
| 478 | 512 | { |
| 479 | 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 | 525 | static void bcm_kona_gpio_irq_relres(struct irq_data *d) |
| 485 | 526 | { |
| 486 | 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 | 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 | 659 | bank->irq = platform_get_irq(pdev, i); |
| 615 | 660 | bank->kona_gpio = kona_gpio; |
| 616 | 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 | 663 | ret = -ENOENT; |
| 619 | 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 | 841 | DECLARE_BITMAP(trigger, MAX_LINE); |
| 842 | 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 | 844 | ret = pca953x_read_regs(chip, chip->regs->input, cur_stat); |
| 864 | 845 | if (ret) |
| 865 | 846 | return false; |
| @@ -1028,20 +1028,23 @@ gpio_sim_device_lockup_configfs(struct gpio_sim_device *dev, bool lock) · 1027 unmodified lines | ||
| 1028 | 1028 | struct configfs_subsystem *subsys = dev->group.cg_subsys; |
| 1029 | 1029 | struct gpio_sim_bank *bank; |
| 1030 | 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 | 1035 | * sufficient to lock up all the configfs entries that the |
| 1035 | 1036 | * instantiated, alive device depends on. |
| 1036 | 1037 | */ |
| 1037 | 1038 | list_for_each_entry(bank, &dev->bank_list, siblings) { |
| 1038 | 1039 | list_for_each_entry(line, &bank->line_list, siblings) { |
| 1040 | + item = line->hog ? &line->hog->item | |
| 1041 | + : &line->group.cg_item; | |
| 1042 | + | |
| 1039 | 1043 | if (lock) |
| 1040 | − WARN_ON(configfs_depend_item_unlocked( | |
| 1041 | − subsys, &line->group.cg_item)); | |
| 1044 | + WARN_ON(configfs_depend_item_unlocked(subsys, | |
| 1045 | + item)); | |
| 1042 | 1046 | else |
| 1043 | − configfs_undepend_item_unlocked( | |
| 1044 | − &line->group.cg_item); | |
| 1047 | + configfs_undepend_item_unlocked(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 | 191 | [REG_IE][CSB] = STMPE_IDX_IEGPIOR_CSB, |
| 192 | 192 | [REG_IE][MSB] = STMPE_IDX_IEGPIOR_MSB, |
| 193 | 193 | }; |
| 194 | − int i, j; | |
| 194 | + int ret, i, j; | |
| 195 | 195 | |
| 196 | 196 | /* |
| 197 | 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 | 199 | * GPSR or GPCR registers |
| 200 | 200 | */ |
| 201 | 201 | if (stmpe->partnum == STMPE1600) { |
| 202 | − stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]); | |
| 203 | − stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]); | |
| 202 | + ret = stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]); | |
| 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 | 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 | 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 | 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 | 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 | 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 | 908 | return -EINVAL; |
| 909 | 909 | } |
| 910 | 910 | |
| 911 | 911 | if (gc->ngpio > FASTPATH_NGPIO) |
| 912 | − chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n", | |
| 913 | − gc->ngpio, FASTPATH_NGPIO); | |
| 912 | + dev_warn(dev, "line cnt %u is greater than fast path cnt %u\n", | |
| 913 | + gc->ngpio, FASTPATH_NGPIO); | |
| 914 | 914 | |
| 915 | 915 | return 0; |
| 916 | 916 | } |
| @@ -119,9 +119,11 @@ · 118 unmodified lines | ||
| 119 | 119 | * - 3.57.0 - Compute tunneling on GFX10+ |
| 120 | 120 | * - 3.58.0 - Add GFX12 DCC support |
| 121 | 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 | 125 | #define KMS_DRIVER_MAJOR 3 |
| 124 | −#define KMS_DRIVER_MINOR 59 | |
| 126 | +#define KMS_DRIVER_MINOR 61 | |
| 125 | 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 | 3815 | if (err == -ENODEV) { |
| 3816 | 3816 | dev_warn(adev->dev, "cap microcode does not exist, skip\n"); |
| 3817 | 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 | 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 | 309 | mutex_lock(&adev->mman.gtt_window_lock); |
| 310 | 310 | while (src_mm.remaining) { |
| 311 | 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 | 313 | struct dma_fence *next; |
| 314 | 314 | |
| 315 | 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 | 340 | max_com = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_MAX_COMPRESSED_BLOCK); |
| 341 | 341 | num_type = AMDGPU_TILING_GET(tiling_flags, GFX12_DCC_NUMBER_TYPE); |
| 342 | 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 | 345 | copy_flags |= (AMDGPU_COPY_FLAGS_SET(MAX_COMPRESSED, max_com) | |
| 344 | 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 | 352 | r = amdgpu_copy_buffer(ring, from, to, cur_size, resv, |
| @@ -119,6 +119,8 @@ struct amdgpu_copy_mem { · 118 unmodified lines | ||
| 119 | 119 | #define AMDGPU_COPY_FLAGS_NUMBER_TYPE_MASK 0x07 |
| 120 | 120 | #define AMDGPU_COPY_FLAGS_DATA_FORMAT_SHIFT 8 |
| 121 | 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 | 125 | #define AMDGPU_COPY_FLAGS_SET(field, value) \ |
| 124 | 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 | 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 | 7472 | static const struct amd_ip_funcs gfx_v9_0_ip_funcs = { |
| 7441 | 7473 | .name = "gfx_v9_0", |
| 7442 | 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 | 7645 | .emit_wave_limit = gfx_v9_0_emit_wave_limit, |
| 7614 | 7646 | .reset = gfx_v9_0_reset_kcq, |
| 7615 | 7647 | .emit_cleaner_shader = gfx_v9_0_ring_emit_cleaner_shader, |
| 7616 | − .begin_use = amdgpu_gfx_enforce_isolation_ring_begin_use, | |
| 7617 | − .end_use = amdgpu_gfx_enforce_isolation_ring_end_use, | |
| 7648 | + .begin_use = gfx_v9_0_ring_begin_use_compute, | |
| 7649 | + .end_use = gfx_v9_0_ring_end_use_compute, | |
| 7618 | 7650 | }; |
| 7619 | 7651 | |
| 7620 | 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 | 1741 | uint32_t byte_count, |
| 1742 | 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 | 1746 | max_com = AMDGPU_COPY_FLAGS_GET(copy_flags, MAX_COMPRESSED); |
| 1747 | 1747 | data_format = AMDGPU_COPY_FLAGS_GET(copy_flags, DATA_FORMAT); |
| 1748 | 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 | 1751 | ib->ptr[ib->length_dw++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_COPY) | |
| 1751 | 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 | 1763 | if ((copy_flags & (AMDGPU_COPY_FLAGS_READ_DECOMPRESSED | AMDGPU_COPY_FLAGS_WRITE_COMPRESSED))) |
| 1763 | 1764 | ib->ptr[ib->length_dw++] = SDMA_DCC_DATA_FORMAT(data_format) | SDMA_DCC_NUM_TYPE(num_type) | |
| 1764 | 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 | 1767 | SDMA_DCC_MAX_COM(max_com) | SDMA_DCC_MAX_UCOM(1); |
| 1767 | 1768 | else |
| 1768 | 1769 | ib->ptr[ib->length_dw++] = 0; |
| @@ -4121,7 +4121,8 @@ static const uint32_t cwsr_trap_gfx12_hex[] = { · 4120 unmodified lines | ||
| 4121 | 4121 | 0x0000ffff, 0x8bfe7e7e, |
| 4122 | 4122 | 0x8bea6a6a, 0xb97af804, |
| 4123 | 4123 | 0xbe804ec2, 0xbf94fffe, |
| 4124 | − 0xbe804a6c, 0xbfb10000, | |
| 4124 | + 0xbe804a6c, 0xbe804ec2, | |
| 4125 | + 0xbf94fffe, 0xbfb10000, | |
| 4125 | 4126 | 0xbf9f0000, 0xbf9f0000, |
| 4126 | 4127 | 0xbf9f0000, 0xbf9f0000, |
| 4127 | 4128 | 0xbf9f0000, 0x00000000, |
| @@ -1049,6 +1049,10 @@ L_SKIP_BARRIER_RESTORE: · 1048 unmodified lines | ||
| 1049 | 1049 | s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution |
| 1050 | 1050 | |
| 1051 | 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 | 1056 | s_endpgm_saved |
| 1053 | 1057 | end |
| 1054 | 1058 | |
| @@ -300,7 +300,7 @@ static int init_user_queue(struct process_queue_manager *pqm, · 299 unmodified lines | ||
| 300 | 300 | return 0; |
| 301 | 301 | |
| 302 | 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 | 304 | cleanup: |
| 305 | 305 | uninit_queue(*q); |
| 306 | 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 | 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 | 2137 | context->stream_count == 0) { |
| 2138 | 2138 | /* Must wait for no flips to be pending before doing optimize bw */ |
| 2139 | 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 | 64 | bool should_use_dmub_lock(struct dc_link *link) |
| 65 | 65 | { |
| 66 | − if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 || | |
| 67 | − link->psr_settings.psr_version == DC_PSR_VERSION_1) | |
| 66 | + if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) | |
| 68 | 67 | return true; |
| 69 | 68 | |
| 70 | 69 | if (link->replay_settings.replay_feature_enabled) |
| @@ -29,11 +29,15 @@ dml_ccflags := $(CC_FLAGS_FPU) · 28 unmodified lines | ||
| 29 | 29 | dml_rcflags := $(CC_FLAGS_NO_FPU) |
| 30 | 30 | |
| 31 | 31 | ifneq ($(CONFIG_FRAME_WARN),0) |
| 32 | −ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) | |
| 33 | −frame_warn_flag := -Wframe-larger-than=3072 | |
| 34 | −else | |
| 35 | −frame_warn_flag := -Wframe-larger-than=2048 | |
| 36 | −endif | |
| 32 | + ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) | |
| 33 | + frame_warn_limit := 3072 | |
| 34 | + else | |
| 35 | + frame_warn_limit := 2048 | |
| 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 | 41 | endif |
| 38 | 42 | |
| 39 | 43 | CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) |
| @@ -28,15 +28,19 @@ dml2_ccflags := $(CC_FLAGS_FPU) · 27 unmodified lines | ||
| 28 | 28 | dml2_rcflags := $(CC_FLAGS_NO_FPU) |
| 29 | 29 | |
| 30 | 30 | ifneq ($(CONFIG_FRAME_WARN),0) |
| 31 | −ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) | |
| 32 | −ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy) | |
| 33 | −frame_warn_flag := -Wframe-larger-than=4096 | |
| 34 | −else | |
| 35 | −frame_warn_flag := -Wframe-larger-than=3072 | |
| 36 | −endif | |
| 37 | −else | |
| 38 | −frame_warn_flag := -Wframe-larger-than=2048 | |
| 39 | −endif | |
| 31 | + ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y) | |
| 32 | + ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy) | |
| 33 | + frame_warn_limit := 4096 | |
| 34 | + else | |
| 35 | + frame_warn_limit := 3072 | |
| 36 | + endif | |
| 37 | + else | |
| 38 | + frame_warn_limit := 2048 | |
| 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 | 44 | endif |
| 41 | 45 | |
| 42 | 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 | 1017 | if (disp_cfg_stream_location < 0) |
| 1018 | 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 | 1021 | populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx); |
| 1022 | 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 | 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 | 1042 | if (disp_cfg_plane_location < 0) |
| 1043 | 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 | 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 | 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 | 786 | case SIGNAL_TYPE_DISPLAY_PORT_MST: |
| 787 | 787 | case SIGNAL_TYPE_DISPLAY_PORT: |
| 788 | 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 | 790 | out->OutputEncoder[dml2->v20.scratch.hpo_stream_to_link_encoder_mapping[location]] = dml_dp2p0; |
| 791 | 791 | break; |
| 792 | 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 | 1343 | if (disp_cfg_stream_location < 0) |
| 1344 | 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 | 1348 | populate_dml_timing_cfg_from_stream_state(&dml_dispcfg->timing, disp_cfg_stream_location, context->streams[i]); |
| 1349 | 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 | 1383 | if (disp_cfg_plane_location < 0) |
| 1384 | 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 | 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 | 1389 | populate_dml_plane_cfg_from_plane_state( |
| @@ -129,7 +129,8 @@ bool hubbub3_program_watermarks( · 128 unmodified lines | ||
| 129 | 129 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, |
| 130 | 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 | 135 | return wm_pending; |
| 135 | 136 | } |
| @@ -750,7 +750,8 @@ static bool hubbub31_program_watermarks( · 749 unmodified lines | ||
| 750 | 750 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, |
| 751 | 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 | 755 | return wm_pending; |
| 755 | 756 | } |
| 756 | 757 | |
| @@ -786,7 +786,8 @@ static bool hubbub32_program_watermarks( · 785 unmodified lines | ||
| 786 | 786 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, |
| 787 | 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 | 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 | 326 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/ |
| 327 | 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 | 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 | 500 | //hubp[i].HUBPREQ_DEBUG.HUBPREQ_DEBUG[26] = 1; |
| 501 | 501 | REG_WRITE(HUBPREQ_DEBUG, 1 << 26); |
| 502 | 502 | |
| 503 | + REG_UPDATE(DCHUBP_CNTL, HUBP_TTU_DISABLE, 0); | |
| 504 | + | |
| 503 | 505 | hubp_reset(hubp); |
| 504 | 506 | } |
| 505 | 507 | |
| @@ -168,6 +168,8 @@ void hubp32_init(struct hubp *hubp) · 167 unmodified lines | ||
| 168 | 168 | { |
| 169 | 169 | struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); |
| 170 | 170 | REG_WRITE(HUBPREQ_DEBUG_DB, 1 << 8); |
| 171 | + | |
| 172 | + REG_UPDATE(DCHUBP_CNTL, HUBP_TTU_DISABLE, 0); | |
| 171 | 173 | } |
| 172 | 174 | static struct hubp_funcs dcn32_hubp_funcs = { |
| 173 | 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 | 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 | 241 | dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, |
| 241 | 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 | 78 | int ret = 0; |
| 79 | 79 | const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; |
| 80 | 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 | 83 | if (atomic_read(&adev->pm.pwr_state[block_type]) == pwr_state && |
| 84 | 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 | 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 | 617 | smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL); |
| 617 | 618 | if (!smu_table->hardcode_pptable) |
| 618 | 619 | return -ENOMEM; |
| @@ -160,6 +160,10 @@ static int komeda_wb_connector_add(struct komeda_kms_dev *kms, · 159 unmodified lines | ||
| 160 | 160 | formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl, |
| 161 | 161 | kwb_conn->wb_layer->layer_type, |
| 162 | 162 | &n_formats); |
| 163 | + if (!formats) { | |
| 164 | + kfree(kwb_conn); | |
| 165 | + return -ENOMEM; | |
| 166 | + } | |
| 163 | 167 | |
| 164 | 168 | err = drm_writeback_connector_init(&kms->base, wb_conn, |
| 165 | 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 | 195 | if (enabled) |
| 196 | 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 | 199 | if (i) |
| 200 | 200 | mdelay(1); |
| 201 | 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 | 311 | if (!aux->transfer) |
| 312 | 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 | 314 | cancel_delayed_work_sync(&aux->cec.unregister_work); |
| 325 | 315 | |
| 326 | 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 | 327 | num_las = CEC_MAX_LOG_ADDRS; |
| 338 | 328 | |
| 339 | 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 | 333 | aux->cec.adap->available_log_addrs == num_las) { |
| 342 | 334 | /* Unchanged, so just set the phys addr */ |
| 343 | 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 | 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 | 2548 | case DP_DSC_BITS_PER_PIXEL_1_16: |
| 2549 | 2549 | return 16; |
| 2550 | 2550 | case DP_DSC_BITS_PER_PIXEL_1_8: |
| @@ -4,6 +4,8 @@ config DRM_HISI_HIBMC · 3 unmodified lines | ||
| 4 | 4 | depends on DRM && PCI |
| 5 | 5 | depends on MMU |
| 6 | 6 | select DRM_CLIENT_SELECTION |
| 7 | + select DRM_DISPLAY_HELPER | |
| 8 | + select DRM_DISPLAY_DP_HELPER | |
| 7 | 9 | select DRM_KMS_HELPER |
| 8 | 10 | select DRM_VRAM_HELPER |
| 9 | 11 | select DRM_TTM |
| @@ -41,8 +41,9 @@ static u32 scale(u32 source_val, · 40 unmodified lines | ||
| 41 | 41 | { |
| 42 | 42 | u64 target_val; |
| 43 | 43 | |
| 44 | − WARN_ON(source_min > source_max); | |
| 45 | − WARN_ON(target_min > target_max); | |
| 44 | + if (WARN_ON(source_min >= source_max) || | |
| 45 | + WARN_ON(target_min > target_max)) | |
| 46 | + return target_min; | |
| 46 | 47 | |
| 47 | 48 | /* defensive */ |
| 48 | 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 | 1791 | if (DISPLAY_VER(display) == 11) |
| 1792 | 1792 | return 10; |
| 1793 | 1793 | |
| 1794 | − return 0; | |
| 1794 | + return intel_dp_dsc_min_src_input_bpc(); | |
| 1795 | 1795 | } |
| 1796 | 1796 | |
| 1797 | 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 | 2072 | /* Compressed BPP should be less than the Input DSC bpp */ |
| 2073 | 2073 | dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1); |
| 2074 | 2074 | |
| 2075 | − for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) { | |
| 2076 | − if (valid_dsc_bpp[i] < dsc_min_bpp) | |
| 2075 | + for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) { | |
| 2076 | + if (valid_dsc_bpp[i] < dsc_min_bpp || | |
| 2077 | + valid_dsc_bpp[i] > dsc_max_bpp) | |
| 2077 | 2078 | continue; |
| 2078 | − if (valid_dsc_bpp[i] > dsc_max_bpp) | |
| 2079 | − break; | |
| 2080 | 2079 | |
| 2081 | 2080 | ret = dsc_compute_link_config(intel_dp, |
| 2082 | 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 | 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 | 2831 | as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC; |
| 2834 | 2832 | as_sdp->length = 0x9; |
| 2835 | 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 | 2838 | as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode); |
| 2841 | 2839 | as_sdp->target_rr_divider = true; |
| 2842 | 2840 | } else { |
| 2843 | − as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL; | |
| 2841 | + as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL; | |
| 2844 | 2842 | as_sdp->vtotal = adjusted_mode->vtotal; |
| 2845 | 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 | 342 | break; |
| 343 | 343 | } |
| 344 | + | |
| 345 | + /* Allow using zero step to indicate one try */ | |
| 346 | + if (!step) | |
| 347 | + break; | |
| 344 | 348 | } |
| 345 | 349 | |
| 346 | 350 | if (slots < 0) { |
| @@ -41,7 +41,7 @@ intel_hdcp_adjust_hdcp_line_rekeying(struct intel_encoder *encoder, · 40 unmodified lines | ||
| 41 | 41 | u32 rekey_bit = 0; |
| 42 | 42 | |
| 43 | 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 | 45 | return; |
| 46 | 46 | |
| 47 | 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 | 2189 | drm_dbg_kms(display->drm, |
| 2190 | 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 | 2204 | } else { |
| 2192 | 2205 | drm_dbg_kms(display->drm, |
| 2193 | 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 | 106 | DRM_FORMAT_Y216, |
| 107 | 107 | DRM_FORMAT_XYUV8888, |
| 108 | 108 | DRM_FORMAT_XVYU2101010, |
| 109 | − DRM_FORMAT_XVYU12_16161616, | |
| 110 | − DRM_FORMAT_XVYU16161616, | |
| 111 | 109 | }; |
| 112 | 110 | |
| 113 | 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 | 132 | DRM_FORMAT_Y216, |
| 135 | 133 | DRM_FORMAT_XYUV8888, |
| 136 | 134 | DRM_FORMAT_XVYU2101010, |
| 137 | − DRM_FORMAT_XVYU12_16161616, | |
| 138 | − DRM_FORMAT_XVYU16161616, | |
| 139 | 135 | }; |
| 140 | 136 | |
| 141 | 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 | 209 | struct address_space *mapping = obj->base.filp->f_mapping; |
| 210 | 210 | unsigned int max_segment = i915_sg_segment_size(i915->drm.dev); |
| 211 | 211 | struct sg_table *st; |
| 212 | − struct sgt_iter sgt_iter; | |
| 213 | − struct page *page; | |
| 214 | 212 | int ret; |
| 215 | 213 | |
| 216 | 214 | /* |
| @@ -239,9 +237,7 @@ rebuild_st: · 22 unmodified lines | ||
| 239 | 237 | * for PAGE_SIZE chunks instead may be helpful. |
| 240 | 238 | */ |
| 241 | 239 | if (max_segment > PAGE_SIZE) { |
| 242 | − for_each_sgt_page(page, sgt_iter, st) | |
| 243 | − put_page(page); | |
| 244 | − sg_free_table(st); | |
| 240 | + shmem_sg_free_table(st, mapping, false, false); | |
| 245 | 241 | kfree(st); |
| 246 | 242 | |
| 247 | 243 | max_segment = PAGE_SIZE; |
| @@ -1469,6 +1469,19 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc) · 1468 unmodified lines | ||
| 1469 | 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 | 1485 | static void __update_guc_busyness_stats(struct intel_guc *guc) |
| 1473 | 1486 | { |
| 1474 | 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 | 1632 | if (!guc_submission_initialized(guc)) |
| 1620 | 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 | 1639 | * There is a race with suspend flow where the worker runs after suspend |
| 1624 | 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 | 5536 | drm_printf(p, "GuC lrc descriptor %u:\n", ce->guc_id.id); |
| 5521 | 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", | |
| 5523 | − ce->ring->head, | |
| 5524 | − ce->lrc_reg_state[CTX_RING_HEAD]); | |
| 5525 | − drm_printf(p, "\t\tLRC Tail: Internal %u, Memory %u\n", | |
| 5526 | − ce->ring->tail, | |
| 5527 | − ce->lrc_reg_state[CTX_RING_TAIL]); | |
| 5538 | + if (intel_context_pin_if_active(ce)) { | |
| 5539 | + drm_printf(p, "\t\tLRC Head: Internal %u, Memory %u\n", | |
| 5540 | + ce->ring->head, | |
| 5541 | + ce->lrc_reg_state[CTX_RING_HEAD]); | |
| 5542 | + drm_printf(p, "\t\tLRC Tail: Internal %u, Memory %u\n", | |
| 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 | 5552 | drm_printf(p, "\t\tContext Pin Count: %u\n", |
| 5529 | 5553 | atomic_read(&ce->pin_count)); |
| 5530 | 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 | 168 | return PTR_ERR(ppgtt); |
| 169 | 169 | |
| 170 | 170 | if (!ppgtt->vm.allocate_va_range) |
| 171 | − goto err_ppgtt_cleanup; | |
| 171 | + goto ppgtt_vm_put; | |
| 172 | 172 | |
| 173 | 173 | /* |
| 174 | 174 | * While we only allocate the page tables here and so we could |
| @@ -236,7 +236,7 @@ err_ppgtt_cleanup: · 61 unmodified lines | ||
| 236 | 236 | goto retry; |
| 237 | 237 | } |
| 238 | 238 | i915_gem_ww_ctx_fini(&ww); |
| 239 | − | |
| 239 | +ppgtt_vm_put: | |
| 240 | 240 | i915_vm_put(&ppgtt->vm); |
| 241 | 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 | 803 | int prio; |
| 804 | 804 | |
| 805 | + memset(arg, 0, sizeof(*arg)); | |
| 805 | 806 | for (prio = PANTHOR_GROUP_PRIORITY_REALTIME; prio >= 0; prio--) { |
| 806 | 807 | if (!group_priority_permit(file, prio)) |
| 807 | 808 | arg->allowed_mask |= BIT(prio); |
| @@ -70,10 +70,17 @@ static int light_up_connector(struct kunit *test, · 69 unmodified lines | ||
| 70 | 70 | state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx); |
| 71 | 71 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); |
| 72 | 72 | |
| 73 | +retry: | |
| 73 | 74 | conn_state = drm_atomic_get_connector_state(state, connector); |
| 74 | 75 | KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); |
| 75 | 76 | |
| 76 | 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 | 84 | KUNIT_EXPECT_EQ(test, ret, 0); |
| 78 | 85 | |
| 79 | 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 | 289 | 8); |
| 283 | 290 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 284 | 291 | |
| 285 | − ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 286 | − KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 287 | − | |
| 292 | + drm = &priv->drm; | |
| 293 | + crtc = priv->crtc; | |
| 288 | 294 | conn = &priv->connector; |
| 295 | + | |
| 289 | 296 | preferred = find_preferred_mode(conn); |
| 290 | 297 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 291 | 298 | |
| 292 | − drm = &priv->drm; | |
| 293 | − crtc = priv->crtc; | |
| 299 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 300 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 301 | + | |
| 294 | 302 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 295 | 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 | 353 | 8); |
| 346 | 354 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 347 | 355 | |
| 348 | − ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 349 | − KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 350 | − | |
| 356 | + drm = &priv->drm; | |
| 357 | + crtc = priv->crtc; | |
| 351 | 358 | conn = &priv->connector; |
| 359 | + | |
| 352 | 360 | preferred = find_preferred_mode(conn); |
| 353 | 361 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 354 | 362 | |
| 355 | − drm = &priv->drm; | |
| 356 | − crtc = priv->crtc; | |
| 363 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 364 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 365 | + | |
| 357 | 366 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 358 | 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 | 417 | 8); |
| 409 | 418 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 410 | 419 | |
| 420 | + drm = &priv->drm; | |
| 421 | + crtc = priv->crtc; | |
| 411 | 422 | conn = &priv->connector; |
| 412 | 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 | 425 | preferred = find_preferred_mode(conn); |
| 418 | 426 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 419 | 427 | KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); |
| 420 | 428 | |
| 421 | − drm = &priv->drm; | |
| 422 | − crtc = priv->crtc; | |
| 429 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 430 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 431 | + | |
| 423 | 432 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 424 | 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 | 483 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); |
| 475 | 484 | KUNIT_ASSERT_NOT_NULL(test, mode); |
| 476 | 485 | |
| 477 | − drm = &priv->drm; | |
| 478 | 486 | crtc = priv->crtc; |
| 479 | 487 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); |
| 480 | 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 | 528 | 8); |
| 521 | 529 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 522 | 530 | |
| 531 | + drm = &priv->drm; | |
| 532 | + crtc = priv->crtc; | |
| 523 | 533 | conn = &priv->connector; |
| 524 | 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 | 536 | preferred = find_preferred_mode(conn); |
| 530 | 537 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 531 | 538 | KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); |
| 532 | 539 | |
| 533 | − drm = &priv->drm; | |
| 534 | − crtc = priv->crtc; | |
| 540 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 541 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 542 | + | |
| 535 | 543 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 536 | 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 | 596 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); |
| 589 | 597 | KUNIT_ASSERT_NOT_NULL(test, mode); |
| 590 | 598 | |
| 591 | − drm = &priv->drm; | |
| 592 | 599 | crtc = priv->crtc; |
| 593 | 600 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); |
| 594 | 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 | 643 | 8); |
| 637 | 644 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 638 | 645 | |
| 646 | + drm = &priv->drm; | |
| 647 | + crtc = priv->crtc; | |
| 639 | 648 | conn = &priv->connector; |
| 640 | 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 | 651 | preferred = find_preferred_mode(conn); |
| 646 | 652 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 647 | 653 | KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); |
| 648 | 654 | |
| 649 | − drm = &priv->drm; | |
| 650 | − crtc = priv->crtc; | |
| 655 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 656 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 657 | + | |
| 651 | 658 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 652 | 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 | 711 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); |
| 705 | 712 | KUNIT_ASSERT_NOT_NULL(test, mode); |
| 706 | 713 | |
| 707 | − drm = &priv->drm; | |
| 708 | 714 | crtc = priv->crtc; |
| 709 | 715 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); |
| 710 | 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 | 760 | 10); |
| 755 | 761 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 756 | 762 | |
| 763 | + drm = &priv->drm; | |
| 764 | + crtc = priv->crtc; | |
| 757 | 765 | conn = &priv->connector; |
| 758 | 766 | ret = set_connector_edid(test, conn, |
| 759 | 767 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, |
| 760 | 768 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); |
| 761 | 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 | 771 | preferred = find_preferred_mode(conn); |
| 767 | 772 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 768 | 773 | |
| 769 | − drm = &priv->drm; | |
| 770 | − crtc = priv->crtc; | |
| 774 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 775 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 776 | + | |
| 771 | 777 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 772 | 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 | 834 | 10); |
| 829 | 835 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 830 | 836 | |
| 837 | + drm = &priv->drm; | |
| 838 | + crtc = priv->crtc; | |
| 831 | 839 | conn = &priv->connector; |
| 832 | 840 | ret = set_connector_edid(test, conn, |
| 833 | 841 | test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz, |
| 834 | 842 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz)); |
| 835 | 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 | 845 | preferred = find_preferred_mode(conn); |
| 841 | 846 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 842 | 847 | |
| 843 | − drm = &priv->drm; | |
| 844 | − crtc = priv->crtc; | |
| 848 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 849 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 850 | + | |
| 845 | 851 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 846 | 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 | 905 | 12); |
| 900 | 906 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 901 | 907 | |
| 908 | + drm = &priv->drm; | |
| 909 | + crtc = priv->crtc; | |
| 902 | 910 | conn = &priv->connector; |
| 903 | 911 | ret = set_connector_edid(test, conn, |
| 904 | 912 | test_edid_dvi_1080p, |
| @@ -908,14 +916,12 @@ static void drm_test_check_output_bpc_dvi(struct kunit *test) · 3 unmodified lines | ||
| 908 | 916 | info = &conn->display_info; |
| 909 | 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 | 919 | preferred = find_preferred_mode(conn); |
| 915 | 920 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 916 | 921 | |
| 917 | − drm = &priv->drm; | |
| 918 | − crtc = priv->crtc; | |
| 922 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 923 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 924 | + | |
| 919 | 925 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 920 | 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 | 952 | 8); |
| 947 | 953 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 948 | 954 | |
| 955 | + drm = &priv->drm; | |
| 956 | + crtc = priv->crtc; | |
| 949 | 957 | conn = &priv->connector; |
| 950 | 958 | ret = set_connector_edid(test, conn, |
| 951 | 959 | test_edid_hdmi_1080p_rgb_max_200mhz, |
| 952 | 960 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); |
| 953 | 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 | 963 | preferred = find_preferred_mode(conn); |
| 959 | 964 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 960 | 965 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); |
| 961 | 966 | |
| 962 | − drm = &priv->drm; | |
| 963 | − crtc = priv->crtc; | |
| 967 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 968 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 969 | + | |
| 964 | 970 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 965 | 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 | 999 | 10); |
| 994 | 1000 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 995 | 1001 | |
| 1002 | + drm = &priv->drm; | |
| 1003 | + crtc = priv->crtc; | |
| 996 | 1004 | conn = &priv->connector; |
| 997 | 1005 | ret = set_connector_edid(test, conn, |
| 998 | 1006 | test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, |
| 999 | 1007 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); |
| 1000 | 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 | 1010 | preferred = find_preferred_mode(conn); |
| 1006 | 1011 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1007 | 1012 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); |
| 1008 | 1013 | |
| 1009 | − drm = &priv->drm; | |
| 1010 | − crtc = priv->crtc; | |
| 1014 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1015 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1016 | + | |
| 1011 | 1017 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1012 | 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 | 1046 | 12); |
| 1041 | 1047 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1042 | 1048 | |
| 1049 | + drm = &priv->drm; | |
| 1050 | + crtc = priv->crtc; | |
| 1043 | 1051 | conn = &priv->connector; |
| 1044 | 1052 | ret = set_connector_edid(test, conn, |
| 1045 | 1053 | test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz, |
| 1046 | 1054 | ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz)); |
| 1047 | 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 | 1057 | preferred = find_preferred_mode(conn); |
| 1053 | 1058 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1054 | 1059 | KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); |
| 1055 | 1060 | |
| 1056 | − drm = &priv->drm; | |
| 1057 | − crtc = priv->crtc; | |
| 1061 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1062 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1063 | + | |
| 1058 | 1064 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1059 | 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 | 1097 | 8); |
| 1092 | 1098 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1093 | 1099 | |
| 1094 | − ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1095 | − KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1096 | − | |
| 1100 | + drm = &priv->drm; | |
| 1101 | + crtc = priv->crtc; | |
| 1097 | 1102 | conn = &priv->connector; |
| 1103 | + | |
| 1098 | 1104 | preferred = find_preferred_mode(conn); |
| 1099 | 1105 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1100 | 1106 | |
| 1101 | − drm = &priv->drm; | |
| 1102 | − crtc = priv->crtc; | |
| 1107 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1108 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1109 | + | |
| 1103 | 1110 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1104 | 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 | 1154 | 12); |
| 1148 | 1155 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1149 | 1156 | |
| 1157 | + drm = &priv->drm; | |
| 1158 | + crtc = priv->crtc; | |
| 1150 | 1159 | conn = &priv->connector; |
| 1151 | 1160 | ret = set_connector_edid(test, conn, |
| 1152 | 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 | 1166 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1158 | 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 | 1169 | preferred = find_preferred_mode(conn); |
| 1164 | 1170 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1165 | 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 | 1176 | rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); |
| 1171 | 1177 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1172 | 1178 | |
| 1173 | − drm = &priv->drm; | |
| 1174 | − crtc = priv->crtc; | |
| 1179 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1180 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1181 | + | |
| 1175 | 1182 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1176 | 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 | 1223 | 12); |
| 1217 | 1224 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1218 | 1225 | |
| 1226 | + drm = &priv->drm; | |
| 1227 | + crtc = priv->crtc; | |
| 1219 | 1228 | conn = &priv->connector; |
| 1220 | 1229 | ret = set_connector_edid(test, conn, |
| 1221 | 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 | 1235 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1227 | 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 | 1238 | preferred = find_preferred_mode(conn); |
| 1233 | 1239 | KUNIT_ASSERT_NOT_NULL(test, preferred); |
| 1234 | 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 | 1248 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); |
| 1243 | 1249 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1244 | 1250 | |
| 1245 | − drm = &priv->drm; | |
| 1246 | − crtc = priv->crtc; | |
| 1251 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1252 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1253 | + | |
| 1247 | 1254 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1248 | 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 | 1297 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1291 | 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 | 1300 | mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); |
| 1297 | 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 | 1310 | rate = mode->clock * 1500; |
| 1307 | 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 | 1316 | crtc = priv->crtc; |
| 1311 | 1317 | ret = light_up_connector(test, drm, crtc, conn, mode, ctx); |
| 1312 | 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 | 1346 | 12); |
| 1341 | 1347 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1342 | 1348 | |
| 1349 | + drm = &priv->drm; | |
| 1350 | + crtc = priv->crtc; | |
| 1343 | 1351 | conn = &priv->connector; |
| 1344 | 1352 | ret = set_connector_edid(test, conn, |
| 1345 | 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 | 1358 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1351 | 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 | 1361 | preferred = find_preferred_mode(conn); |
| 1357 | 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 | 1376 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); |
| 1372 | 1377 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1373 | 1378 | |
| 1374 | − drm = &priv->drm; | |
| 1375 | − crtc = priv->crtc; | |
| 1379 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1380 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1381 | + | |
| 1376 | 1382 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1377 | 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 | 1413 | 12); |
| 1408 | 1414 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1409 | 1415 | |
| 1416 | + drm = &priv->drm; | |
| 1417 | + crtc = priv->crtc; | |
| 1410 | 1418 | conn = &priv->connector; |
| 1411 | 1419 | ret = set_connector_edid(test, conn, |
| 1412 | 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 | 1425 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1418 | 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 | 1428 | preferred = find_preferred_mode(conn); |
| 1424 | 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 | 1443 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); |
| 1439 | 1444 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1440 | 1445 | |
| 1441 | − drm = &priv->drm; | |
| 1442 | − crtc = priv->crtc; | |
| 1446 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1447 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1448 | + | |
| 1443 | 1449 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1444 | 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 | 1479 | 8); |
| 1474 | 1480 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1475 | 1481 | |
| 1482 | + drm = &priv->drm; | |
| 1483 | + crtc = priv->crtc; | |
| 1476 | 1484 | conn = &priv->connector; |
| 1477 | 1485 | ret = set_connector_edid(test, conn, |
| 1478 | 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 | 1491 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1484 | 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 | 1494 | preferred = find_preferred_mode(conn); |
| 1490 | 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 | 1501 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); |
| 1497 | 1502 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1498 | 1503 | |
| 1499 | − drm = &priv->drm; | |
| 1500 | − crtc = priv->crtc; | |
| 1504 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1505 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1506 | + | |
| 1501 | 1507 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1502 | 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 | 1539 | 12); |
| 1534 | 1540 | KUNIT_ASSERT_NOT_NULL(test, priv); |
| 1535 | 1541 | |
| 1542 | + drm = &priv->drm; | |
| 1543 | + crtc = priv->crtc; | |
| 1536 | 1544 | conn = &priv->connector; |
| 1537 | 1545 | ret = set_connector_edid(test, conn, |
| 1538 | 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 | 1551 | KUNIT_ASSERT_TRUE(test, info->is_hdmi); |
| 1544 | 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 | 1554 | preferred = find_preferred_mode(conn); |
| 1550 | 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 | 1561 | rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); |
| 1557 | 1562 | KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); |
| 1558 | 1563 | |
| 1559 | − drm = &priv->drm; | |
| 1560 | − crtc = priv->crtc; | |
| 1564 | + ctx = drm_kunit_helper_acquire_ctx_alloc(test); | |
| 1565 | + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); | |
| 1566 | + | |
| 1561 | 1567 | ret = light_up_connector(test, drm, crtc, conn, preferred, ctx); |
| 1562 | 1568 | KUNIT_EXPECT_EQ(test, ret, 0); |
| 1563 | 1569 | |
| @@ -51,6 +51,10 @@ · 50 unmodified lines | ||
| 51 | 51 | /* Common to all OA units */ |
| 52 | 52 | #define OA_OACONTROL_REPORT_BC_MASK REG_GENMASK(9, 9) |
| 53 | 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 | 59 | #define OAG_OA_DEBUG XE_REG(0xdaf8, XE_REG_OPTION_MASKED) |
| 56 | 60 | #define OAG_OA_DEBUG_DISABLE_MMIO_TRG REG_BIT(14) |
| @@ -78,6 +82,8 @@ · 21 unmodified lines | ||
| 78 | 82 | #define OAM_CONTEXT_CONTROL_OFFSET (0x1bc) |
| 79 | 83 | #define OAM_CONTROL_OFFSET (0x194) |
| 80 | 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 | 87 | #define OAM_DEBUG_OFFSET (0x198) |
| 82 | 88 | #define OAM_STATUS_OFFSET (0x19c) |
| 83 | 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 | 119 | drm_puts(&p, "\n**** GuC CT ****\n"); |
| 120 | 120 | xe_guc_ct_snapshot_print(ss->guc.ct, &p); |
| 121 | 121 | |
| 122 | − /* | |
| 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"); */ | |
| 122 | + drm_puts(&p, "\n**** Contexts ****\n"); | |
| 127 | 123 | xe_guc_exec_queue_snapshot_print(ss->ge, &p); |
| 128 | 124 | |
| 129 | 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 | 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 | |
| 399 | − * cannot handle arbitrarily long lines. Note also that printing to dmesg in | |
| 400 | − * piece-meal fashion is not possible, each separate call to drm_puts() has a | |
| 401 | − * line-feed automatically added! Therefore, the entire output line must be | |
| 402 | − * constructed in a local buffer first, then printed in one atomic output call. | |
| 394 | + * The output is split into multiple calls to drm_puts() because some print | |
| 395 | + * targets, e.g. dmesg, cannot handle arbitrarily long lines. These targets may | |
| 396 | + * add newlines, as is the case with dmesg: each drm_puts() call creates a | |
| 397 | + * separate line. | |
| 403 | 398 | * |
| 404 | 399 | * There is also a scheduler yield call to prevent the 'task has been stuck for |
| 405 | 400 | * 120s' kernel hang check feature from firing when printing to a slow target |
| 406 | 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 | 403 | * @p: the printer object to output to |
| 411 | 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 | 408 | * @blob: the Binary Large OBject to dump out |
| 413 | 409 | * @offset: offset in bytes to skip from the front of the BLOB, must be a multiple of sizeof(u32) |
| 414 | 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 | 413 | const void *blob, size_t offset, size_t size) |
| 418 | 414 | { |
| 419 | 415 | const u32 *blob32 = (const u32 *)blob; |
| 420 | 416 | char buff[ASCII85_BUFSZ], *line_buff; |
| 421 | 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 | 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 | 423 | if (size & 3) |
| 436 | 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 | 450 | line_pos += strlen(line_buff + line_pos); |
| 463 | 451 | |
| 464 | 452 | if ((line_pos + MIN_SPACE) >= DMESG_MAX_LINE_LEN) { |
| 465 | − line_buff[line_pos++] = '\n'; | |
| 466 | 453 | line_buff[line_pos++] = 0; |
| 467 | 454 | |
| 468 | 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 | 467 | if (line_pos) { |
| 478 | − line_buff[line_pos++] = '\n'; | |
| 479 | 468 | line_buff[line_pos++] = 0; |
| 480 | − | |
| 481 | 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 | 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 | 33 | const void *blob, size_t offset, size_t size); |
| 34 | 34 | |
| 35 | 35 | #endif |
| @@ -135,8 +135,8 @@ void xe_drm_client_add_bo(struct xe_drm_client *client, · 134 unmodified lines | ||
| 135 | 135 | XE_WARN_ON(bo->client); |
| 136 | 136 | XE_WARN_ON(!list_empty(&bo->client_link)); |
| 137 | 137 | |
| 138 | − spin_lock(&client->bos_lock); | |
| 139 | 138 | bo->client = xe_drm_client_get(client); |
| 139 | + spin_lock(&client->bos_lock); | |
| 140 | 140 | list_add_tail(&bo->client_link, &client->bos_list); |
| 141 | 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 | 532 | if (IS_SRIOV_PF(gt_to_xe(gt)) && !xe_gt_is_media_type(gt)) |
| 533 | 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 | 537 | xe_gt_sriov_pf_init_hw(gt); |
| 538 | + } | |
| 537 | 539 | |
| 538 | 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 | 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 | 84 | static bool pf_needs_enable_ggtt_guest_update(struct xe_device *xe) |
| 72 | 85 | { |
| 73 | 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 | 103 | pf_enable_ggtt_guest_update(gt); |
| 91 | 104 | |
| 92 | 105 | xe_gt_sriov_pf_service_update(gt); |
| 93 | − xe_gt_sriov_pf_migration_init(gt); | |
| 94 | 106 | } |
| 95 | 107 | |
| 96 | 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 | 11 | #ifdef CONFIG_PCI_IOV |
| 12 | 12 | int xe_gt_sriov_pf_init_early(struct xe_gt *gt); |
| 13 | +int xe_gt_sriov_pf_init(struct xe_gt *gt); | |
| 13 | 14 | void xe_gt_sriov_pf_init_hw(struct xe_gt *gt); |
| 14 | 15 | void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid); |
| 15 | 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 | 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 | 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 | 1724 | snapshot->g2h_outstanding); |
| 1725 | 1725 | |
| 1726 | 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 | 1729 | } else { |
| 1729 | 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 | 211 | remain = snapshot->size; |
| 212 | 212 | for (i = 0; i < snapshot->num_chunks; i++) { |
| 213 | 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 | 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 | 237 | u32 tail, hw_tail, partial_report_size, available; |
| 238 | 238 | int report_size = stream->oa_buffer.format->size; |
| 239 | 239 | unsigned long flags; |
| 240 | − bool pollin; | |
| 241 | 240 | |
| 242 | 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 | 281 | stream->oa_buffer.tail = tail; |
| 283 | 282 | |
| 284 | 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 | 286 | spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); |
| 288 | 287 | |
| 289 | − return pollin; | |
| 288 | + return stream->pollin; | |
| 290 | 289 | } |
| 291 | 290 | |
| 292 | 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 | 293 | struct xe_oa_stream *stream = |
| 295 | 294 | container_of(hrtimer, typeof(*stream), poll_check_timer); |
| 296 | 295 | |
| 297 | − if (xe_oa_buffer_check_unlocked(stream)) { | |
| 298 | − stream->pollin = true; | |
| 296 | + if (xe_oa_buffer_check_unlocked(stream)) | |
| 299 | 297 | wake_up(&stream->poll_wq); |
| 300 | − } | |
| 301 | 298 | |
| 302 | 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 | 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 | 458 | static void xe_oa_enable(struct xe_oa_stream *stream) |
| 456 | 459 | { |
| 457 | 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 | 475 | stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG) |
| 473 | 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 | 481 | static void xe_oa_disable(struct xe_oa_stream *stream) |
| 479 | 482 | { |
| 480 | 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 | 486 | if (xe_mmio_wait32(mmio, __oa_regs(stream)->oa_ctrl, |
| 484 | 487 | OAG_OACONTROL_OA_COUNTER_ENABLE, 0, 50000, NULL, false)) |
| 485 | 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 | 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 | 2542 | /* Ensure MMIO trigger remains disabled till there is a stream */ |
| 2538 | 2543 | xe_mmio_write32(>->mmio, u->regs.oa_debug, |
| 2539 | 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 | 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 | 83 | static s64 detect_bar2_dgfx(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) |
| 61 | 84 | { |
| 62 | 85 | struct xe_tile *tile = xe_device_get_root_tile(xe); |
| 63 | 86 | struct xe_mmio *mmio = xe_root_tile_mmio(xe); |
| 64 | 87 | struct pci_dev *pdev = to_pci_dev(xe->drm.dev); |
| 65 | − u64 stolen_size; | |
| 88 | + u64 stolen_size, wopcm_size; | |
| 66 | 89 | u64 tile_offset; |
| 67 | 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 | 97 | if (drm_WARN_ON(&xe->drm, tile_size < mgr->stolen_base)) |
| 75 | 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 | 105 | stolen_size = tile_size - mgr->stolen_base; |
| 106 | + stolen_size -= wopcm_size; | |
| 78 | 107 | |
| 79 | 108 | /* Verify usage fits in the actual resource available */ |
| 80 | 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 | 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 | 121 | static u32 detect_bar2_integrated(struct xe_device *xe, struct xe_ttm_stolen_mgr *mgr) |
| 116 | 122 | { |
| 117 | 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 | 619 | goto free_contexts; |
| 620 | 620 | } |
| 621 | 621 | |
| 622 | + mutex_init(&host->intr_mutex); | |
| 623 | + | |
| 622 | 624 | pm_runtime_enable(&pdev->dev); |
| 623 | 625 | |
| 624 | 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 | 104 | unsigned int id; |
| 105 | 105 | int i, err; |
| 106 | 106 | |
| 107 | − mutex_init(&host->intr_mutex); | |
| 108 | − | |
| 109 | 107 | for (id = 0; id < host1x_syncpt_nb_pts(host); ++id) { |
| 110 | 108 | struct host1x_syncpt *syncpt = &host->syncpt[id]; |
| 111 | 109 | |
| @@ -570,6 +570,8 @@ config HID_LED · 569 unmodified lines | ||
| 570 | 570 | |
| 571 | 571 | config HID_LENOVO |
| 572 | 572 | tristate "Lenovo / Thinkpad devices" |
| 573 | + depends on ACPI | |
| 574 | + select ACPI_PLATFORM_PROFILE | |
| 573 | 575 | select NEW_LEDS |
| 574 | 576 | select LEDS_CLASS |
| 575 | 577 | help |
| @@ -1167,7 +1169,8 @@ config HID_TOPRE · 591 unmodified lines | ||
| 1167 | 1169 | tristate "Topre REALFORCE keyboards" |
| 1168 | 1170 | depends on HID |
| 1169 | 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 | 1175 | config HID_THINGM |
| 1173 | 1176 | tristate "ThingM blink(1) USB RGB LED" |
| @@ -1374,10 +1377,6 @@ endmenu · 200 unmodified lines | ||
| 1374 | 1377 | |
| 1375 | 1378 | source "drivers/hid/bpf/Kconfig" |
| 1376 | 1379 | |
| 1377 | −endif # HID | |
| 1378 | − | |
| 1379 | −source "drivers/hid/usbhid/Kconfig" | |
| 1380 | − | |
| 1381 | 1380 | source "drivers/hid/i2c-hid/Kconfig" |
| 1382 | 1381 | |
| 1383 | 1382 | source "drivers/hid/intel-ish-hid/Kconfig" |
| @@ -1388,4 +1387,10 @@ source "drivers/hid/surface-hid/Kconfig" · 4 unmodified lines | ||
| 1388 | 1387 | |
| 1389 | 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 | 1396 | endif # HID_SUPPORT |
| @@ -5,7 +5,6 @@ menu "AMD SFH HID Support" · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | config AMD_SFH_HID |
| 7 | 7 | tristate "AMD Sensor Fusion Hub" |
| 8 | − depends on HID | |
| 9 | 8 | depends on X86 |
| 10 | 9 | help |
| 11 | 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 | 474 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015) |
| 475 | 475 | table = magic_keyboard_2015_fn_keys; |
| 476 | 476 | else if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 || |
| 477 | + hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024 || | |
| 477 | 478 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 || |
| 478 | 479 | hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021) |
| 479 | 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 | 552 | if (usage->code != code) { |
| 549 | 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 | 1154 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, |
| 1151 | 1155 | { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021), |
| 1152 | 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 | 1161 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), |
| 1154 | 1162 | .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, |
| 1155 | 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 | 553 | static void corsair_void_battery_add_work_handler(struct work_struct *work) |
| 554 | 554 | { |
| 555 | 555 | struct corsair_void_drvdata *drvdata; |
| 556 | − struct power_supply_config psy_cfg; | |
| 556 | + struct power_supply_config psy_cfg = {}; | |
| 557 | 557 | struct power_supply *new_supply; |
| 558 | 558 | |
| 559 | 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 | 726 | if (drvdata->battery) |
| 727 | 727 | power_supply_unregister(drvdata->battery); |
| 728 | 728 | |
| 729 | + cancel_delayed_work_sync(&drvdata->delayed_status_work); | |
| 729 | 730 | cancel_delayed_work_sync(&drvdata->delayed_firmware_work); |
| 730 | 731 | sysfs_remove_group(&hid_dev->dev.kobj, &corsair_void_attr_group); |
| 731 | 732 | } |
| @@ -184,6 +184,7 @@ · 183 unmodified lines | ||
| 184 | 184 | #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 |
| 185 | 185 | #define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 |
| 186 | 186 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c |
| 187 | +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024 0x0320 | |
| 187 | 188 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a |
| 188 | 189 | #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f |
| 189 | 190 | #define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102 |
| @@ -1095,6 +1096,7 @@ · 905 unmodified lines | ||
| 1095 | 1096 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 |
| 1096 | 1097 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003 0x3003 |
| 1097 | 1098 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 |
| 1099 | +#define USB_DEVICE_ID_QUANTA_HP_5MP_CAMERA_5473 0x5473 | |
| 1098 | 1100 | |
| 1099 | 1101 | #define I2C_VENDOR_ID_RAYDIUM 0x2386 |
| 1100 | 1102 | #define I2C_PRODUCT_ID_RAYDIUM_4B33 0x4b33 |
| @@ -1301,6 +1303,7 @@ · 200 unmodified lines | ||
| 1301 | 1303 | #define USB_VENDOR_ID_TOPRE 0x0853 |
| 1302 | 1304 | #define USB_DEVICE_ID_TOPRE_REALFORCE_R2_108 0x0148 |
| 1303 | 1305 | #define USB_DEVICE_ID_TOPRE_REALFORCE_R2_87 0x0146 |
| 1306 | +#define USB_DEVICE_ID_TOPRE_REALFORCE_R3S_87 0x0313 | |
| 1304 | 1307 | |
| 1305 | 1308 | #define USB_VENDOR_ID_TOPSEED 0x0766 |
| 1306 | 1309 | #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 |
| @@ -32,9 +32,7 @@ · 31 unmodified lines | ||
| 32 | 32 | #include <linux/leds.h> |
| 33 | 33 | #include <linux/workqueue.h> |
| 34 | 34 | |
| 35 | −#if IS_ENABLED(CONFIG_ACPI_PLATFORM_PROFILE) | |
| 36 | 35 | #include <linux/platform_profile.h> |
| 37 | −#endif /* CONFIG_ACPI_PLATFORM_PROFILE */ | |
| 38 | 36 | |
| 39 | 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 | 728 | if (hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB) { |
| 731 | 729 | report_key_event(input, KEY_RFKILL); |
| 732 | 730 | return 1; |
| 733 | − } | |
| 734 | −#if IS_ENABLED(CONFIG_ACPI_PLATFORM_PROFILE) | |
| 735 | − else { | |
| 731 | + } else { | |
| 736 | 732 | platform_profile_cycle(); |
| 737 | 733 | return 1; |
| 738 | 734 | } |
| 739 | −#endif /* CONFIG_ACPI_PLATFORM_PROFILE */ | |
| 740 | 735 | return 0; |
| 741 | 736 | case TP_X12_RAW_HOTKEY_FN_F10: |
| 742 | 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 | 1679 | break; |
| 1680 | 1680 | } |
| 1681 | 1681 | |
| 1682 | − if (suffix) | |
| 1682 | + if (suffix) { | |
| 1683 | 1683 | hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL, |
| 1684 | 1684 | "%s %s", hdev->name, suffix); |
| 1685 | + if (!hi->input->name) | |
| 1686 | + return -ENOMEM; | |
| 1687 | + } | |
| 1685 | 1688 | |
| 1686 | 1689 | return 0; |
| 1687 | 1690 | } |
| @@ -891,6 +891,7 @@ static const struct hid_device_id hid_ignore_list[] = { · 890 unmodified lines | ||
| 891 | 891 | { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) }, |
| 892 | 892 | #endif |
| 893 | 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 | 313 | u16 rumble_left; |
| 314 | 314 | u16 rumble_right; |
| 315 | 315 | unsigned int sensor_timestamp_us; |
| 316 | + struct work_struct unregister_work; | |
| 316 | 317 | }; |
| 317 | 318 | |
| 318 | 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 | 1051 | struct steam_device, mode_switch); |
| 1051 | 1052 | unsigned long flags; |
| 1052 | 1053 | bool client_opened; |
| 1053 | − steam->gamepad_mode = !steam->gamepad_mode; | |
| 1054 | 1054 | if (!lizard_mode) |
| 1055 | 1055 | return; |
| 1056 | 1056 | |
| 1057 | + steam->gamepad_mode = !steam->gamepad_mode; | |
| 1057 | 1058 | if (steam->gamepad_mode) |
| 1058 | 1059 | steam_set_lizard_mode(steam, false); |
| 1059 | 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 | 1101 | static bool steam_is_valve_interface(struct hid_device *hdev) |
| 1076 | 1102 | { |
| 1077 | 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 | 1143 | steam->client_opened++; |
| 1118 | 1144 | spin_unlock_irqrestore(&steam->lock, flags); |
| 1119 | 1145 | |
| 1120 | − steam_sensors_unregister(steam); | |
| 1121 | − steam_input_unregister(steam); | |
| 1146 | + schedule_work(&steam->unregister_work); | |
| 1122 | 1147 | |
| 1123 | 1148 | return 0; |
| 1124 | 1149 | } |
| @@ -1135,11 +1160,7 @@ static void steam_client_ll_close(struct hid_device *hdev) · 10 unmodified lines | ||
| 1135 | 1160 | connected = steam->connected && !steam->client_opened; |
| 1136 | 1161 | spin_unlock_irqrestore(&steam->lock, flags); |
| 1137 | 1162 | |
| 1138 | − if (connected) { | |
| 1139 | − steam_set_lizard_mode(steam, lizard_mode); | |
| 1140 | − steam_input_register(steam); | |
| 1141 | − steam_sensors_register(steam); | |
| 1142 | − } | |
| 1163 | + schedule_work(&steam->unregister_work); | |
| 1143 | 1164 | } |
| 1144 | 1165 | |
| 1145 | 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 | 1252 | INIT_LIST_HEAD(&steam->list); |
| 1232 | 1253 | INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); |
| 1233 | 1254 | steam->sensor_timestamp_us = 0; |
| 1255 | + INIT_WORK(&steam->unregister_work, steam_work_unregister_cb); | |
| 1234 | 1256 | |
| 1235 | 1257 | /* |
| 1236 | 1258 | * With the real steam controller interface, do not connect hidraw. |
| @@ -1291,6 +1313,7 @@ err_cancel_work: · 54 unmodified lines | ||
| 1291 | 1313 | cancel_work_sync(&steam->work_connect); |
| 1292 | 1314 | cancel_delayed_work_sync(&steam->mode_switch); |
| 1293 | 1315 | cancel_work_sync(&steam->rumble_work); |
| 1316 | + cancel_work_sync(&steam->unregister_work); | |
| 1294 | 1317 | |
| 1295 | 1318 | return ret; |
| 1296 | 1319 | } |
| @@ -1307,6 +1330,7 @@ static void steam_remove(struct hid_device *hdev) · 10 unmodified lines | ||
| 1307 | 1330 | cancel_delayed_work_sync(&steam->mode_switch); |
| 1308 | 1331 | cancel_work_sync(&steam->work_connect); |
| 1309 | 1332 | cancel_work_sync(&steam->rumble_work); |
| 1333 | + cancel_work_sync(&steam->unregister_work); | |
| 1310 | 1334 | hid_destroy_device(steam->client_hdev); |
| 1311 | 1335 | steam->client_hdev = NULL; |
| 1312 | 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 | 1618 | if (!(b9 & BIT(6)) && steam->did_mode_switch) { |
| 1595 | 1619 | steam->did_mode_switch = false; |
| 1596 | − cancel_delayed_work_sync(&steam->mode_switch); | |
| 1620 | + cancel_delayed_work(&steam->mode_switch); | |
| 1597 | 1621 | } else if (!steam->client_opened && (b9 & BIT(6)) && !steam->did_mode_switch) { |
| 1598 | 1622 | steam->did_mode_switch = true; |
| 1599 | 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 | 1627 | return; |
| 1604 | 1628 | |
| 1605 | 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 | 1694 | steam->sensor_timestamp_us += 4000; |
| 1671 | 1695 | |
| 1672 | − if (!steam->gamepad_mode) | |
| 1696 | + if (!steam->gamepad_mode && lizard_mode) | |
| 1673 | 1697 | return; |
| 1674 | 1698 | |
| 1675 | 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 | 171 | b_ep = ep->desc.bEndpointAddress; |
| 172 | 172 | |
| 173 | 173 | /* Are the expected endpoints present? */ |
| 174 | − u8 ep_addr[1] = {b_ep}; | |
| 174 | + u8 ep_addr[2] = {b_ep, 0}; | |
| 175 | 175 | |
| 176 | 176 | if (!usb_check_int_endpoints(usbif, ep_addr)) { |
| 177 | 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 | 29 | hid_info(hdev, |
| 30 | 30 | "fixing up Topre REALFORCE keyboard report descriptor\n"); |
| 31 | 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 | 38 | return rdesc; |
| 34 | 39 | } |
| @@ -38,6 +43,8 @@ static const struct hid_device_id topre_id_table[] = { · 3 unmodified lines | ||
| 38 | 43 | USB_DEVICE_ID_TOPRE_REALFORCE_R2_108) }, |
| 39 | 44 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE, |
| 40 | 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 | 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 | 106 | "%s::%s", |
| 107 | 107 | dev_name(&input->dev), |
| 108 | 108 | info->led_name); |
| 109 | + if (!led->cdev.name) | |
| 110 | + return -ENOMEM; | |
| 109 | 111 | |
| 110 | 112 | ret = devm_led_classdev_register(&hdev->dev, &led->cdev); |
| 111 | 113 | if (ret) |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | menuconfig I2C_HID |
| 3 | 3 | tristate "I2C HID support" |
| 4 | 4 | default y |
| 5 | − depends on I2C && INPUT && HID | |
| 5 | + depends on I2C | |
| 6 | 6 | |
| 7 | 7 | if I2C_HID |
| 8 | 8 | |
| @@ -6,7 +6,6 @@ config INTEL_ISH_HID · 5 unmodified lines | ||
| 6 | 6 | tristate "Intel Integrated Sensor Hub" |
| 7 | 7 | default n |
| 8 | 8 | depends on X86 |
| 9 | − depends on HID | |
| 10 | 9 | help |
| 11 | 10 | The Integrated Sensor Hub (ISH) enables the ability to offload |
| 12 | 11 | sensor polling and algorithm processing to a dedicated low power |
| @@ -36,6 +36,8 @@ · 35 unmodified lines | ||
| 36 | 36 | #define PCI_DEVICE_ID_INTEL_ISH_ARL_H 0x7745 |
| 37 | 37 | #define PCI_DEVICE_ID_INTEL_ISH_ARL_S 0x7F78 |
| 38 | 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 | 42 | #define REVISION_ID_CHT_A0 0x6 |
| 41 | 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 | 517 | /* ISH FW is dead */ |
| 518 | 518 | if (!ish_is_input_ready(dev)) |
| 519 | 519 | return -EPIPE; |
| 520 | + | |
| 521 | + /* Send clock sync at once after reset */ | |
| 522 | + ishtp_dev->prev_sync = 0; | |
| 523 | + | |
| 520 | 524 | /* |
| 521 | 525 | * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending |
| 522 | 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 | 582 | static void _ish_sync_fw_clock(struct ishtp_device *dev) |
| 579 | 583 | { |
| 580 | − static unsigned long prev_sync; | |
| 581 | − uint64_t usec; | |
| 584 | + struct ipc_time_update_msg time = {}; | |
| 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 | 587 | return; |
| 585 | 588 | |
| 586 | − prev_sync = jiffies; | |
| 587 | − usec = ktime_to_us(ktime_get_boottime()); | |
| 588 | − ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t)); | |
| 589 | + dev->prev_sync = jiffies; | |
| 590 | + /* The fields of time would be updated while sending message */ | |
| 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 | 26 | enum ishtp_driver_data_index { |
| 27 | 27 | ISHTP_DRIVER_DATA_NONE, |
| 28 | 28 | ISHTP_DRIVER_DATA_LNL_M, |
| 29 | + ISHTP_DRIVER_DATA_PTL, | |
| 29 | 30 | }; |
| 30 | 31 | |
| 31 | 32 | #define ISH_FW_GEN_LNL_M "lnlm" |
| 33 | +#define ISH_FW_GEN_PTL "ptl" | |
| 32 | 34 | |
| 33 | 35 | #define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin" |
| 34 | 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 | 39 | [ISHTP_DRIVER_DATA_LNL_M] = { |
| 38 | 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 | 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 | 68 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_H)}, |
| 64 | 69 | {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_S)}, |
| 65 | 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 | 75 | MODULE_DEVICE_TABLE(pci, ish_pci_tbl); |
| @@ -253,6 +253,8 @@ struct ishtp_device { · 252 unmodified lines | ||
| 253 | 253 | unsigned int ipc_tx_cnt; |
| 254 | 254 | unsigned long long ipc_tx_bytes_cnt; |
| 255 | 255 | |
| 256 | + /* Time of the last clock sync */ | |
| 257 | + unsigned long prev_sync; | |
| 256 | 258 | const struct ishtp_hw_ops *ops; |
| 257 | 259 | size_t mtu; |
| 258 | 260 | uint32_t ishtp_msg_hdr; |
| @@ -7,7 +7,6 @@ menu "Intel THC HID Support" · 6 unmodified lines | ||
| 7 | 7 | config INTEL_THC_HID |
| 8 | 8 | tristate "Intel Touch Host Controller" |
| 9 | 9 | depends on ACPI |
| 10 | − select HID | |
| 11 | 10 | help |
| 12 | 11 | THC (Touch Host Controller) is the name of the IP block in PCH that |
| 13 | 12 | interfaces with Touch Devices (ex: touchscreen, touchpad etc.). It |
| @@ -1,7 +1,6 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0+ |
| 2 | 2 | menu "Surface System Aggregator Module HID support" |
| 3 | 3 | depends on SURFACE_AGGREGATOR |
| 4 | − depends on INPUT | |
| 5 | 4 | |
| 6 | 5 | config SURFACE_HID |
| 7 | 6 | tristate "HID transport driver for Surface System Aggregator Module" |
| @@ -39,4 +38,3 @@ endmenu · 31 unmodified lines | ||
| 39 | 38 | |
| 40 | 39 | config SURFACE_HID_CORE |
| 41 | 40 | tristate |
| 42 | − select HID | |
| @@ -5,8 +5,7 @@ menu "USB HID support" · 4 unmodified lines | ||
| 5 | 5 | config USB_HID |
| 6 | 6 | tristate "USB HID transport layer" |
| 7 | 7 | default y |
| 8 | − depends on USB && INPUT | |
| 9 | − select HID | |
| 8 | + depends on HID | |
| 10 | 9 | help |
| 11 | 10 | Say Y here if you want to connect USB keyboards, |
| 12 | 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 | 1300 | info.flags |= I2C_CLIENT_SLAVE; |
| 1301 | 1301 | } |
| 1302 | 1302 | |
| 1303 | − info.flags |= I2C_CLIENT_USER; | |
| 1304 | − | |
| 1305 | 1303 | client = i2c_new_client_device(adap, &info); |
| 1306 | 1304 | if (IS_ERR(client)) |
| 1307 | 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 | 1311 | dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", |
| 1310 | 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 | 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 | 1319 | * And of course let the users delete the devices they instantiated, if |
| 1327 | 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 | 1329 | const char *buf, size_t count) |
| 1337 | 1330 | { |
| 1338 | 1331 | struct i2c_adapter *adap = to_i2c_adapter(dev); |
| 1339 | − struct device *child_dev; | |
| 1332 | + struct i2c_client *client, *next; | |
| 1340 | 1333 | unsigned short addr; |
| 1341 | 1334 | char end; |
| 1342 | 1335 | int res; |
| @@ -1352,19 +1345,28 @@ delete_device_store(struct device *dev, struct device_attribute *attr, · 9 unmodified lines | ||
| 1352 | 1345 | return -EINVAL; |
| 1353 | 1346 | } |
| 1354 | 1347 | |
| 1355 | − mutex_lock(&core_lock); | |
| 1356 | 1348 | /* Make sure the device was added through sysfs */ |
| 1357 | − child_dev = device_find_child(&adap->dev, &addr, __i2c_find_user_addr); | |
| 1358 | − if (child_dev) { | |
| 1359 | − i2c_unregister_device(i2c_verify_client(child_dev)); | |
| 1360 | − put_device(child_dev); | |
| 1361 | − } else { | |
| 1362 | − dev_err(dev, "Can't find userspace-created device at %#x\n", addr); | |
| 1363 | − count = -ENOENT; | |
| 1349 | + res = -ENOENT; | |
| 1350 | + mutex_lock_nested(&adap->userspace_clients_lock, | |
| 1351 | + i2c_adapter_depth(adap)); | |
| 1352 | + list_for_each_entry_safe(client, next, &adap->userspace_clients, | |
| 1353 | + detected) { | |
| 1354 | + if (i2c_encode_flags_to_addr(client) == addr) { | |
| 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 | 1371 | static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, S_IWUSR, NULL, |
| 1370 | 1372 | delete_device_store); |
| @@ -1535,6 +1537,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap) · 164 unmodified lines | ||
| 1535 | 1537 | adap->locked_flags = 0; |
| 1536 | 1538 | rt_mutex_init(&adap->bus_lock); |
| 1537 | 1539 | rt_mutex_init(&adap->mux_lock); |
| 1540 | + mutex_init(&adap->userspace_clients_lock); | |
| 1541 | + INIT_LIST_HEAD(&adap->userspace_clients); | |
| 1538 | 1542 | |
| 1539 | 1543 | /* Set default timeout to 1 second if not already set */ |
| 1540 | 1544 | if (adap->timeout == 0) |
| @@ -1700,6 +1704,23 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap) · 159 unmodified lines | ||
| 1700 | 1704 | } |
| 1701 | 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 | 1724 | static int __unregister_client(struct device *dev, void *dummy) |
| 1704 | 1725 | { |
| 1705 | 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 | 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 | 1746 | * i2c_del_adapter - unregister I2C adapter |
| 1720 | 1747 | * @adap: the adapter being unregistered |
| @@ -1726,6 +1753,7 @@ static int __unregister_dummy(struct device *dev, void *dummy) · 5 unmodified lines | ||
| 1726 | 1753 | void i2c_del_adapter(struct i2c_adapter *adap) |
| 1727 | 1754 | { |
| 1728 | 1755 | struct i2c_adapter *found; |
| 1756 | + struct i2c_client *client, *next; | |
| 1729 | 1757 | |
| 1730 | 1758 | /* First make sure that this adapter was ever added */ |
| 1731 | 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 | 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 | 1786 | /* Detach any active clients. This can't fail, thus we do not |
| 1742 | 1787 | * check the returned value. This is a two-pass process, because |
| 1743 | 1788 | * we can't remove the dummy devices during the first pass: they |
| 1744 | 1789 | * could have been instantiated by real devices wishing to clean |
| 1745 | 1790 | * them up properly, so we give them a chance to do that first. */ |
| 1746 | − mutex_lock(&core_lock); | |
| 1747 | 1791 | device_for_each_child(&adap->dev, NULL, __unregister_client); |
| 1748 | 1792 | device_for_each_child(&adap->dev, NULL, __unregister_dummy); |
| 1749 | − mutex_unlock(&core_lock); | |
| 1750 | 1793 | |
| 1751 | 1794 | /* device name is gone after device_unregister */ |
| 1752 | 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 | 2009 | /* add the driver to the list of i2c drivers in the driver core */ |
| 1967 | 2010 | driver->driver.owner = owner; |
| 1968 | 2011 | driver->driver.bus = &i2c_bus_type; |
| 2012 | + INIT_LIST_HEAD(&driver->clients); | |
| 1969 | 2013 | |
| 1970 | 2014 | /* When registration returns, the driver core |
| 1971 | 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 | 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); | |
| 1989 | − | |
| 1990 | − if (client && client->flags & I2C_CLIENT_AUTO) | |
| 1991 | − i2c_unregister_device(client); | |
| 1992 | − | |
| 2032 | + if (dev->type == &i2c_adapter_type) | |
| 2033 | + i2c_do_del_adapter(data, to_i2c_adapter(dev)); | |
| 1993 | 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 | 2042 | void i2c_del_driver(struct i2c_driver *driver) |
| 2002 | 2043 | { |
| 2003 | − mutex_lock(&core_lock); | |
| 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); | |
| 2044 | + i2c_for_each_dev(driver, __process_removed_driver); | |
| 2009 | 2045 | |
| 2010 | 2046 | driver_unregister(&driver->driver); |
| 2011 | 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 | 2468 | /* Finally call the custom detection function */ |
| 2433 | 2469 | memset(&info, 0, sizeof(struct i2c_board_info)); |
| 2434 | 2470 | info.addr = addr; |
| 2435 | − info.flags = I2C_CLIENT_AUTO; | |
| 2436 | 2471 | err = driver->detect(temp_client, &info); |
| 2437 | 2472 | if (err) { |
| 2438 | 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 | 2494 | dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n", |
| 2460 | 2495 | info.type, info.addr); |
| 2461 | 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 | 2500 | dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n", |
| 2464 | 2501 | info.type, info.addr); |
| 2465 | 2502 | } |
| @@ -175,6 +175,7 @@ · 174 unmodified lines | ||
| 175 | 175 | #define CONTROL_GAM_EN 25 |
| 176 | 176 | #define CONTROL_GALOG_EN 28 |
| 177 | 177 | #define CONTROL_GAINT_EN 29 |
| 178 | +#define CONTROL_EPH_EN 45 | |
| 178 | 179 | #define CONTROL_XT_EN 50 |
| 179 | 180 | #define CONTROL_INTCAPXT_EN 51 |
| 180 | 181 | #define CONTROL_IRTCACHEDIS 59 |
| @@ -2653,6 +2653,10 @@ static void iommu_init_flags(struct amd_iommu *iommu) · 2652 unmodified lines | ||
| 2653 | 2653 | |
| 2654 | 2654 | /* Set IOTLB invalidation timeout to 1s */ |
| 2655 | 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 | 2662 | static void iommu_apply_resume_quirks(struct amd_iommu *iommu) |
| @@ -3194,7 +3198,7 @@ out: · 535 unmodified lines | ||
| 3194 | 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 | 3203 | #ifdef CONFIG_KVM_AMD_SEV |
| 3200 | 3204 | if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) |
| @@ -3219,6 +3223,14 @@ static void iommu_snp_enable(void) · 18 unmodified lines | ||
| 3219 | 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 | 3234 | pr_info("IOMMU SNP support enabled.\n"); |
| 3223 | 3235 | return; |
| 3224 | 3236 | |
| @@ -3318,6 +3330,19 @@ static int __init iommu_go_to_state(enum iommu_init_state state) · 93 unmodified lines | ||
| 3318 | 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 | 3346 | return ret; |
| 3322 | 3347 | } |
| 3323 | 3348 | |
| @@ -3426,18 +3451,23 @@ void __init amd_iommu_detect(void) · 102 unmodified lines | ||
| 3426 | 3451 | int ret; |
| 3427 | 3452 | |
| 3428 | 3453 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) |
| 3429 | − return; | |
| 3454 | + goto disable_snp; | |
| 3430 | 3455 | |
| 3431 | 3456 | if (!amd_iommu_sme_check()) |
| 3432 | − return; | |
| 3457 | + goto disable_snp; | |
| 3433 | 3458 | |
| 3434 | 3459 | ret = iommu_go_to_state(IOMMU_IVRS_DETECTED); |
| 3435 | 3460 | if (ret) |
| 3436 | − return; | |
| 3461 | + goto disable_snp; | |
| 3437 | 3462 | |
| 3438 | 3463 | amd_iommu_detected = true; |
| 3439 | 3464 | iommu_detected = 1; |
| 3440 | 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 | 249 | struct list_head clients; /* list of sysmmu_drvdata.domain_node */ |
| 250 | 250 | sysmmu_pte_t *pgtable; /* lv1 page table, 16KB */ |
| 251 | 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 | 253 | spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ |
| 254 | 254 | struct iommu_domain domain; /* generic domain data structure */ |
| 255 | 255 | }; |
| @@ -292,7 +292,7 @@ struct sysmmu_drvdata { · 36 unmodified lines | ||
| 292 | 292 | struct clk *aclk; /* SYSMMU's aclk clock */ |
| 293 | 293 | struct clk *pclk; /* SYSMMU's pclk clock */ |
| 294 | 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 | 296 | bool active; /* current status */ |
| 297 | 297 | struct exynos_iommu_domain *domain; /* domain we belong to */ |
| 298 | 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 | 746 | ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, 0, |
| 747 | 747 | dev_name(dev), data); |
| 748 | 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 | 750 | return ret; |
| 751 | 751 | } |
| 752 | 752 | |
| @@ -87,7 +87,9 @@ prq_retry: · 86 unmodified lines | ||
| 87 | 87 | struct page_req_dsc *req; |
| 88 | 88 | |
| 89 | 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 | 93 | head = (head + sizeof(*req)) & PRQ_RING_MASK; |
| 92 | 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 | 479 | ops->page_response(dev, iopf, &resp); |
| 480 | 480 | list_del_init(&group->pending_node); |
| 481 | + iopf_free_group(group); | |
| 481 | 482 | } |
| 482 | 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 | 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 | 1760 | * takes precedence. |
| 1761 | 1761 | */ |
| 1762 | 1762 | if (type == IOMMU_DOMAIN_IDENTITY) |
| @@ -169,6 +169,7 @@ config IXP4XX_IRQ · 168 unmodified lines | ||
| 169 | 169 | |
| 170 | 170 | config LAN966X_OIC |
| 171 | 171 | tristate "Microchip LAN966x OIC Support" |
| 172 | + depends on MCHP_LAN966X_PCI || COMPILE_TEST | |
| 172 | 173 | select GENERIC_IRQ_CHIP |
| 173 | 174 | select IRQ_DOMAIN |
| 174 | 175 | help |
| @@ -577,7 +577,8 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) · 576 unmodified lines | ||
| 577 | 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 | 582 | int irq; |
| 582 | 583 | if (cpumask_test_cpu(smp_processor_id(), |
| 583 | 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 | 68 | unsigned long *hwirq, unsigned int *type) |
| 69 | 69 | { |
| 70 | 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 | 73 | struct mvebu_icu *icu = msi_data->icu; |
| 73 | 74 | |
| 74 | 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 | 98 | struct irq_chip *chip = irq_desc_get_chip(part->chained_desc); |
| 99 | 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 | 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 | 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 | 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 | 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 | 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 | 76 | lim.max_write_zeroes_sectors = mddev->chunk_sectors; |
| 77 | 77 | lim.io_min = mddev->chunk_sectors << 9; |
| 78 | 78 | err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY); |
| 79 | − if (err) { | |
| 80 | − queue_limits_cancel_update(mddev->gendisk->queue); | |
| 79 | + if (err) | |
| 81 | 80 | return err; |
| 82 | − } | |
| 83 | 81 | |
| 84 | 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 | 161 | static struct regmap *device_node_get_regmap(struct device_node *np, |
| 162 | + bool create_regmap, | |
| 162 | 163 | bool check_res) |
| 163 | 164 | { |
| 164 | 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 | 175 | if (!syscon) { |
| 175 | − if (of_device_is_compatible(np, "syscon")) | |
| 176 | + if (create_regmap) | |
| 176 | 177 | syscon = of_syscon_register(np, check_res); |
| 177 | 178 | else |
| 178 | 179 | syscon = ERR_PTR(-EINVAL); |
| @@ -233,15 +234,37 @@ err_unlock: · 54 unmodified lines | ||
| 233 | 234 | } |
| 234 | 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 | 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 | 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 | 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 | 269 | EXPORT_SYMBOL_GPL(syscon_node_to_regmap); |
| 247 | 270 | |
| @@ -273,6 +273,7 @@ · 272 unmodified lines | ||
| 273 | 273 | #define MSDC_PAD_TUNE_CMD2_SEL BIT(21) /* RW */ |
| 274 | 274 | |
| 275 | 275 | #define PAD_DS_TUNE_DLY_SEL BIT(0) /* RW */ |
| 276 | +#define PAD_DS_TUNE_DLY2_SEL BIT(1) /* RW */ | |
| 276 | 277 | #define PAD_DS_TUNE_DLY1 GENMASK(6, 2) /* RW */ |
| 277 | 278 | #define PAD_DS_TUNE_DLY2 GENMASK(11, 7) /* RW */ |
| 278 | 279 | #define PAD_DS_TUNE_DLY3 GENMASK(16, 12) /* RW */ |
| @@ -318,6 +319,7 @@ · 39 unmodified lines | ||
| 318 | 319 | |
| 319 | 320 | /* EMMC50_PAD_DS_TUNE mask */ |
| 320 | 321 | #define PAD_DS_DLY_SEL BIT(16) /* RW */ |
| 322 | +#define PAD_DS_DLY2_SEL BIT(15) /* RW */ | |
| 321 | 323 | #define PAD_DS_DLY1 GENMASK(14, 10) /* RW */ |
| 322 | 324 | #define PAD_DS_DLY3 GENMASK(4, 0) /* RW */ |
| 323 | 325 | |
| @@ -2504,13 +2506,23 @@ tune_done: · 2180 unmodified lines | ||
| 2504 | 2506 | static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) |
| 2505 | 2507 | { |
| 2506 | 2508 | struct msdc_host *host = mmc_priv(mmc); |
| 2509 | + | |
| 2507 | 2510 | host->hs400_mode = true; |
| 2508 | 2511 | |
| 2509 | − if (host->top_base) | |
| 2510 | − writel(host->hs400_ds_delay, | |
| 2511 | − host->top_base + EMMC50_PAD_DS_TUNE); | |
| 2512 | − else | |
| 2513 | − writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE); | |
| 2512 | + if (host->top_base) { | |
| 2513 | + if (host->hs400_ds_dly3) | |
| 2514 | + sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, | |
| 2515 | + PAD_DS_DLY3, host->hs400_ds_dly3); | |
| 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 | 2526 | /* hs400 mode must set it to 0 */ |
| 2515 | 2527 | sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS); |
| 2516 | 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 | 2542 | if (host->top_base) { |
| 2531 | 2543 | sdr_set_bits(host->top_base + EMMC50_PAD_DS_TUNE, |
| 2532 | 2544 | PAD_DS_DLY_SEL); |
| 2533 | − if (host->hs400_ds_dly3) | |
| 2534 | − sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, | |
| 2535 | − PAD_DS_DLY3, host->hs400_ds_dly3); | |
| 2545 | + sdr_clr_bits(host->top_base + EMMC50_PAD_DS_TUNE, | |
| 2546 | + PAD_DS_DLY2_SEL); | |
| 2536 | 2547 | } else { |
| 2537 | 2548 | sdr_set_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY_SEL); |
| 2538 | − if (host->hs400_ds_dly3) | |
| 2539 | − sdr_set_field(host->base + PAD_DS_TUNE, | |
| 2540 | − PAD_DS_TUNE_DLY3, host->hs400_ds_dly3); | |
| 2549 | + sdr_clr_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY2_SEL); | |
| 2541 | 2550 | } |
| 2542 | 2551 | |
| 2543 | 2552 | host->hs400_tuning = true; |
| @@ -155,7 +155,6 @@ struct sdhci_am654_data { · 154 unmodified lines | ||
| 155 | 155 | u32 tuning_loop; |
| 156 | 156 | |
| 157 | 157 | #define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) |
| 158 | −#define SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA BIT(1) | |
| 159 | 158 | }; |
| 160 | 159 | |
| 161 | 160 | struct window { |
| @@ -357,29 +356,6 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, · 195 unmodified lines | ||
| 357 | 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 | 359 | static u8 sdhci_am654_write_power_on(struct sdhci_host *host, u8 val, int reg) |
| 384 | 360 | { |
| 385 | 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 | 844 | if (device_property_read_bool(dev, "ti,fails-without-test-cd")) |
| 869 | 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 | 847 | sdhci_get_of_property(pdev); |
| 877 | 848 | |
| 878 | 849 | return 0; |
| @@ -969,7 +940,6 @@ static int sdhci_am654_probe(struct platform_device *pdev) · 90 unmodified lines | ||
| 969 | 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 | 943 | host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning; |
| 974 | 944 | |
| 975 | 945 | pm_runtime_get_noresume(dev); |
| @@ -385,15 +385,16 @@ static int c_can_plat_probe(struct platform_device *pdev) · 384 unmodified lines | ||
| 385 | 385 | if (ret) { |
| 386 | 386 | dev_err(&pdev->dev, "registering %s failed (err=%d)\n", |
| 387 | 387 | KBUILD_MODNAME, ret); |
| 388 | − goto exit_free_device; | |
| 388 | + goto exit_pm_runtime; | |
| 389 | 389 | } |
| 390 | 390 | |
| 391 | 391 | dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n", |
| 392 | 392 | KBUILD_MODNAME, priv->base, dev->irq); |
| 393 | 393 | return 0; |
| 394 | 394 | |
| 395 | −exit_free_device: | |
| 395 | +exit_pm_runtime: | |
| 396 | 396 | pm_runtime_disable(priv->device); |
| 397 | +exit_free_device: | |
| 397 | 398 | free_c_can_dev(dev); |
| 398 | 399 | exit: |
| 399 | 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 | 868 | break; |
| 869 | 869 | case CAN_STATE_ERROR_ACTIVE: |
| 870 | − cf->can_id |= CAN_ERR_CNT; | |
| 871 | − cf->data[1] = CAN_ERR_CRTL_ACTIVE; | |
| 872 | − cf->data[6] = bec.txerr; | |
| 873 | − cf->data[7] = bec.rxerr; | |
| 870 | + if (skb) { | |
| 871 | + cf->can_id |= CAN_ERR_CNT; | |
| 872 | + cf->data[1] = CAN_ERR_CRTL_ACTIVE; | |
| 873 | + cf->data[6] = bec.txerr; | |
| 874 | + cf->data[7] = bec.rxerr; | |
| 875 | + } | |
| 874 | 876 | break; |
| 875 | 877 | default: |
| 876 | 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 | 622 | netdev_dbg(priv->ndev, "RX-FIFO overflow\n"); |
| 623 | 623 | |
| 624 | 624 | skb = rkcanfd_alloc_can_err_skb(priv, &cf, ×tamp); |
| 625 | − if (skb) | |
| 625 | + if (!skb) | |
| 626 | 626 | return 0; |
| 627 | 627 | |
| 628 | 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 | 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 | 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 | 1441 | aq_ptp_ring_free(self); |
| 1442 | 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 | 1447 | mutex_lock(&self->fwreq_mutex); |
| 1446 | 1448 | self->aq_fw_ops->deinit(self->aq_hw); |
| 1447 | 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 | 42 | struct bcmgenet_priv *priv = netdev_priv(dev); |
| 43 | 43 | struct device *kdev = &priv->pdev->dev; |
| 44 | + u32 phy_wolopts = 0; | |
| 44 | 45 | |
| 45 | − if (dev->phydev) | |
| 46 | + if (dev->phydev) { | |
| 46 | 47 | phy_ethtool_get_wol(dev->phydev, wol); |
| 48 | + phy_wolopts = wol->wolopts; | |
| 49 | + } | |
| 47 | 50 | |
| 48 | 51 | /* MAC is not wake-up capable, return what the PHY does */ |
| 49 | 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 | 55 | /* Overlay MAC capabilities with that of the PHY queried before */ |
| 53 | 56 | wol->supported |= WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER; |
| 54 | − wol->wolopts = priv->wolopts; | |
| 55 | − memset(wol->sopass, 0, sizeof(wol->sopass)); | |
| 57 | + wol->wolopts |= priv->wolopts; | |
| 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 | 65 | if (wol->wolopts & WAKE_MAGICSECURE) |
| 58 | 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 | 78 | /* Try Wake-on-LAN from the PHY first */ |
| 71 | 79 | if (dev->phydev) { |
| 72 | 80 | ret = phy_ethtool_set_wol(dev->phydev, wol); |
| 73 | − if (ret != -EOPNOTSUPP) | |
| 81 | + if (ret != -EOPNOTSUPP && wol->wolopts) | |
| 74 | 82 | return ret; |
| 75 | 83 | } |
| 76 | 84 | |
| @@ -55,6 +55,7 @@ · 54 unmodified lines | ||
| 55 | 55 | #include <linux/hwmon.h> |
| 56 | 56 | #include <linux/hwmon-sysfs.h> |
| 57 | 57 | #include <linux/crc32poly.h> |
| 58 | +#include <linux/dmi.h> | |
| 58 | 59 | |
| 59 | 60 | #include <net/checksum.h> |
| 60 | 61 | #include <net/gso.h> |
| @@ -18212,6 +18213,50 @@ unlock: · 18151 unmodified lines | ||
| 18212 | 18213 | |
| 18213 | 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 | 18260 | static void tg3_shutdown(struct pci_dev *pdev) |
| 18216 | 18261 | { |
| 18217 | 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 | 18274 | if (system_state == SYSTEM_POWER_OFF) |
| 18230 | 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 | 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 | 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 | 1129 | /* gqi napi handler defined in gve_main.c */ |
| 1120 | 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 | 1903 | /* Stop tx queues */ |
| 1904 | 1904 | netif_tx_disable(priv->dev); |
| 1905 | 1905 | |
| 1906 | + xdp_features_clear_redirect_target(priv->dev); | |
| 1907 | + | |
| 1906 | 1908 | gve_clear_napi_enabled(priv); |
| 1907 | 1909 | gve_clear_report_stats(priv); |
| 1908 | 1910 | |
| @@ -1972,6 +1974,9 @@ static void gve_turnup(struct gve_priv *priv) · 63 unmodified lines | ||
| 1972 | 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 | 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 | 2251 | if (priv->queue_format == GVE_GQI_QPL_FORMAT) { |
| 2247 | 2252 | xdp_features = NETDEV_XDP_ACT_BASIC; |
| 2248 | 2253 | xdp_features |= NETDEV_XDP_ACT_REDIRECT; |
| 2249 | − xdp_features |= NETDEV_XDP_ACT_NDO_XMIT; | |
| 2250 | 2254 | xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY; |
| 2251 | 2255 | } else { |
| 2252 | 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 | 2408 | dma_addr_t data_dma_addr; |
| 2409 | 2409 | struct netdev_queue *txq; |
| 2410 | 2410 | unsigned long lpar_rc; |
| 2411 | + unsigned int skblen; | |
| 2411 | 2412 | union sub_crq tx_crq; |
| 2412 | 2413 | unsigned int offset; |
| 2413 | 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 | 2523 | tx_buff->skb = skb; |
| 2523 | 2524 | tx_buff->index = bufidx; |
| 2524 | 2525 | tx_buff->pool_index = queue_num; |
| 2526 | + skblen = skb->len; | |
| 2525 | 2527 | |
| 2526 | 2528 | memset(&tx_crq, 0, sizeof(tx_crq)); |
| 2527 | 2529 | tx_crq.v1.first = IBMVNIC_CRQ_CMD; |
| @@ -2614,7 +2616,7 @@ early_exit: · 86 unmodified lines | ||
| 2614 | 2616 | netif_stop_subqueue(netdev, queue_num); |
| 2615 | 2617 | } |
| 2616 | 2618 | |
| 2617 | − tx_bytes += skb->len; | |
| 2619 | + tx_bytes += skblen; | |
| 2618 | 2620 | txq_trans_cond_update(txq); |
| 2619 | 2621 | ret = NETDEV_TX_OK; |
| 2620 | 2622 | goto out; |
| @@ -2903,8 +2903,8 @@ static void iavf_watchdog_task(struct work_struct *work) · 2902 unmodified lines | ||
| 2903 | 2903 | } |
| 2904 | 2904 | |
| 2905 | 2905 | mutex_unlock(&adapter->crit_lock); |
| 2906 | − netdev_unlock(netdev); | |
| 2907 | 2906 | restart_watchdog: |
| 2907 | + netdev_unlock(netdev); | |
| 2908 | 2908 | if (adapter->state >= __IAVF_DOWN) |
| 2909 | 2909 | queue_work(adapter->wq, &adapter->adminq_task); |
| 2910 | 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 | 982 | /* preallocate memory for ice_sched_node */ |
| 983 | 983 | node = devm_kzalloc(ice_hw_to_dev(pi->hw), sizeof(*node), GFP_KERNEL); |
| 984 | + if (!node) | |
| 985 | + return -ENOMEM; | |
| 986 | + | |
| 984 | 987 | *priv = node; |
| 985 | 988 | |
| 986 | 989 | return 0; |
| @@ -527,15 +527,14 @@ err: · 526 unmodified lines | ||
| 527 | 527 | * @xdp: xdp_buff used as input to the XDP program |
| 528 | 528 | * @xdp_prog: XDP program to run |
| 529 | 529 | * @xdp_ring: ring to be used for XDP_TX action |
| 530 | − * @rx_buf: Rx buffer to store the XDP action | |
| 531 | 530 | * @eop_desc: Last descriptor in packet to read metadata from |
| 532 | 531 | * |
| 533 | 532 | * Returns any of ICE_XDP_{PASS, CONSUMED, TX, REDIR} |
| 534 | 533 | */ |
| 535 | −static void | |
| 534 | +static u32 | |
| 536 | 535 | ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, |
| 537 | 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 | 539 | unsigned int ret = ICE_XDP_PASS; |
| 541 | 540 | u32 act; |
| @@ -574,7 +573,7 @@ out_failure: · 32 unmodified lines | ||
| 574 | 573 | ret = ICE_XDP_CONSUMED; |
| 575 | 574 | } |
| 576 | 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 | 859 | xdp_buff_set_frags_flag(xdp); |
| 861 | 860 | } |
| 862 | 861 | |
| 863 | − if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) { | |
| 864 | − ice_set_rx_bufs_act(xdp, rx_ring, ICE_XDP_CONSUMED); | |
| 862 | + if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) | |
| 865 | 863 | return -ENOMEM; |
| 866 | − } | |
| 867 | 864 | |
| 868 | 865 | __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page, |
| 869 | 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 | 921 | struct ice_rx_buf *rx_buf; |
| 925 | 922 | |
| 926 | 923 | rx_buf = &rx_ring->rx_buf[ntc]; |
| 927 | − rx_buf->pgcnt = page_count(rx_buf->page); | |
| 928 | 924 | prefetchw(rx_buf->page); |
| 929 | 925 | |
| 930 | 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 | 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 | 965 | * ice_build_skb - Build skb around an existing buffer |
| 945 | 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 | 1072 | rx_buf->page_offset + headlen, size, |
| 1052 | 1073 | xdp->frame_sz); |
| 1053 | 1074 | } else { |
| 1054 | − /* buffer is unused, change the act that should be taken later | |
| 1055 | − * on; data was copied onto skb's linear part so there's no | |
| 1075 | + /* buffer is unused, restore biased page count in Rx buffer; | |
| 1076 | + * data was copied onto skb's linear part so there's no | |
| 1056 | 1077 | * need for adjusting page offset and we can reuse this buffer |
| 1057 | 1078 | * as-is |
| 1058 | 1079 | */ |
| 1059 | − rx_buf->act = ICE_SKB_CONSUMED; | |
| 1080 | + rx_buf->pagecnt_bias++; | |
| 1060 | 1081 | } |
| 1061 | 1082 | |
| 1062 | 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 | 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 | 1187 | * ice_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf |
| 1108 | 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 | 1200 | unsigned int total_rx_bytes = 0, total_rx_pkts = 0; |
| 1121 | 1201 | unsigned int offset = rx_ring->rx_offset; |
| 1122 | 1202 | struct xdp_buff *xdp = &rx_ring->xdp; |
| 1123 | − u32 cached_ntc = rx_ring->first_desc; | |
| 1124 | 1203 | struct ice_tx_ring *xdp_ring = NULL; |
| 1125 | 1204 | struct bpf_prog *xdp_prog = NULL; |
| 1126 | 1205 | u32 ntc = rx_ring->next_to_clean; |
| 1206 | + u32 cached_ntu, xdp_verdict; | |
| 1127 | 1207 | u32 cnt = rx_ring->count; |
| 1128 | 1208 | u32 xdp_xmit = 0; |
| 1129 | − u32 cached_ntu; | |
| 1130 | 1209 | bool failure; |
| 1131 | − u32 first; | |
| 1132 | 1210 | |
| 1133 | 1211 | xdp_prog = READ_ONCE(rx_ring->xdp_prog); |
| 1134 | 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 | 1268 | xdp_prepare_buff(xdp, hard_start, offset, size, !!offset); |
| 1191 | 1269 | xdp_buff_clear_frags_flag(xdp); |
| 1192 | 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 | 1272 | break; |
| 1194 | 1273 | } |
| 1195 | 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 | 1278 | if (ice_is_non_eop(rx_ring, rx_desc)) |
| 1200 | 1279 | continue; |
| 1201 | 1280 | |
| 1202 | − ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_buf, rx_desc); | |
| 1203 | − if (rx_buf->act == ICE_XDP_PASS) | |
| 1281 | + ice_get_pgcnts(rx_ring); | |
| 1282 | + xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_desc); | |
| 1283 | + if (xdp_verdict == ICE_XDP_PASS) | |
| 1204 | 1284 | goto construct_skb; |
| 1205 | 1285 | total_rx_bytes += xdp_get_buff_len(xdp); |
| 1206 | 1286 | total_rx_pkts++; |
| 1207 | 1287 | |
| 1208 | − xdp->data = NULL; | |
| 1209 | − rx_ring->first_desc = ntc; | |
| 1210 | − rx_ring->nr_frags = 0; | |
| 1288 | + ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); | |
| 1289 | + | |
| 1211 | 1290 | continue; |
| 1212 | 1291 | construct_skb: |
| 1213 | 1292 | if (likely(ice_ring_uses_build_skb(rx_ring))) |
| @@ -1217,18 +1296,12 @@ construct_skb: · 3 unmodified lines | ||
| 1217 | 1296 | /* exit if we failed to retrieve a buffer */ |
| 1218 | 1297 | if (!skb) { |
| 1219 | 1298 | rx_ring->ring_stats->rx_stats.alloc_page_failed++; |
| 1220 | − rx_buf->act = 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; | |
| 1299 | + xdp_verdict = ICE_XDP_CONSUMED; | |
| 1228 | 1300 | } |
| 1229 | − xdp->data = NULL; | |
| 1230 | − rx_ring->first_desc = ntc; | |
| 1231 | − rx_ring->nr_frags = 0; | |
| 1301 | + ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); | |
| 1302 | + | |
| 1303 | + if (!skb) | |
| 1304 | + break; | |
| 1232 | 1305 | |
| 1233 | 1306 | stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S); |
| 1234 | 1307 | if (unlikely(ice_test_staterr(rx_desc->wb.status_error0, |
| @@ -1257,23 +1330,6 @@ construct_skb: · 22 unmodified lines | ||
| 1257 | 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 | 1333 | rx_ring->next_to_clean = ntc; |
| 1278 | 1334 | /* return up to cleaned_count buffers to hardware */ |
| 1279 | 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 | 201 | struct page *page; |
| 202 | 202 | unsigned int page_offset; |
| 203 | 203 | unsigned int pgcnt; |
| 204 | − unsigned int act; | |
| 205 | 204 | unsigned int pagecnt_bias; |
| 206 | 205 | }; |
| 207 | 206 | |
| @@ -5,49 +5,6 @@ · 4 unmodified lines | ||
| 5 | 5 | #define _ICE_TXRX_LIB_H_ |
| 6 | 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 | 9 | * ice_test_staterr - tests bits in Rx descriptor status and error fields |
| 53 | 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 | 2159 | idpf_vport_ctrl_lock(netdev); |
| 2160 | 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 | 2166 | err = idpf_vport_open(vport); |
| 2163 | 2167 | |
| 2168 | +unlock: | |
| 2164 | 2169 | idpf_vport_ctrl_unlock(netdev); |
| 2165 | 2170 | |
| 2166 | 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 | 3008 | return -EINVAL; |
| 3009 | 3009 | |
| 3010 | 3010 | rsc_segments = DIV_ROUND_UP(skb->data_len, rsc_seg_len); |
| 3011 | − if (unlikely(rsc_segments == 1)) | |
| 3012 | − return 0; | |
| 3013 | 3011 | |
| 3014 | 3012 | NAPI_GRO_CB(skb)->count = rsc_segments; |
| 3015 | 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 | 3070 | idpf_rx_hash(rxq, skb, rx_desc, decoded); |
| 3073 | 3071 | |
| 3074 | 3072 | skb->protocol = eth_type_trans(skb, rxq->netdev); |
| 3073 | + skb_record_rx_queue(skb, rxq->idx); | |
| 3075 | 3074 | |
| 3076 | 3075 | if (le16_get_bits(rx_desc->hdrlen_flags, |
| 3077 | 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 | 3079 | csum_bits = idpf_rx_splitq_extract_csum_bits(rx_desc); |
| 3081 | 3080 | idpf_rx_csum(rxq, skb, csum_bits, decoded); |
| 3082 | 3081 | |
| 3083 | − skb_record_rx_queue(skb, rxq->idx); | |
| 3084 | − | |
| 3085 | 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 | 1096 | return -ENOMEM; |
| 1097 | 1097 | } |
| 1098 | 1098 | |
| 1099 | + buffer->type = IGC_TX_BUFFER_TYPE_SKB; | |
| 1099 | 1100 | buffer->skb = skb; |
| 1100 | 1101 | buffer->protocol = 0; |
| 1101 | 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 | 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 | 2708 | unsigned int totalsize = xdp->data_end - xdp->data_meta; |
| 2707 | 2709 | unsigned int metasize = xdp->data - xdp->data_meta; |
| 2708 | 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 | 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 | 2731 | return skb; |
| 2725 | 2732 | } |
| 2726 | 2733 | |
| 2727 | 2734 | static void igc_dispatch_skb_zc(struct igc_q_vector *q_vector, |
| 2728 | 2735 | union igc_adv_rx_desc *desc, |
| 2729 | − struct xdp_buff *xdp, | |
| 2730 | − ktime_t timestamp) | |
| 2736 | + struct igc_xdp_buff *ctx) | |
| 2731 | 2737 | { |
| 2732 | 2738 | struct igc_ring *ring = q_vector->rx.ring; |
| 2733 | 2739 | struct sk_buff *skb; |
| 2734 | 2740 | |
| 2735 | − skb = igc_construct_skb_zc(ring, xdp); | |
| 2741 | + skb = igc_construct_skb_zc(ring, ctx); | |
| 2736 | 2742 | if (!skb) { |
| 2737 | 2743 | ring->rx_stats.alloc_failed++; |
| 2738 | 2744 | set_bit(IGC_RING_FLAG_RX_ALLOC_FAILED, &ring->flags); |
| 2739 | 2745 | return; |
| 2740 | 2746 | } |
| 2741 | 2747 | |
| 2742 | − if (timestamp) | |
| 2743 | − skb_hwtstamps(skb)->hwtstamp = timestamp; | |
| 2744 | − | |
| 2745 | 2748 | if (igc_cleanup_headers(ring, desc, skb)) |
| 2746 | 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 | 2780 | union igc_adv_rx_desc *desc; |
| 2778 | 2781 | struct igc_rx_buffer *bi; |
| 2779 | 2782 | struct igc_xdp_buff *ctx; |
| 2780 | − ktime_t timestamp = 0; | |
| 2781 | 2783 | unsigned int size; |
| 2782 | 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 | 2810 | bi->xdp->data_meta += IGC_TS_HDR_LEN; |
| 2809 | 2811 | size -= IGC_TS_HDR_LEN; |
| 2812 | + } else { | |
| 2813 | + ctx->rx_ts = NULL; | |
| 2810 | 2814 | } |
| 2811 | 2815 | |
| 2812 | 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 | 2819 | res = __igc_xdp_run_prog(adapter, prog, bi->xdp); |
| 2816 | 2820 | switch (res) { |
| 2817 | 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 | 2823 | fallthrough; |
| 2820 | 2824 | case IGC_XDP_CONSUMED: |
| 2821 | 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 | 2105 | /* hand second half of page back to the ring */ |
| 2106 | 2106 | ixgbe_reuse_rx_page(rx_ring, rx_buffer); |
| 2107 | 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 | 2109 | /* the page has been released from the ring */ |
| 2110 | 2110 | IXGBE_CB(skb)->page_released = true; |
| 2111 | 2111 | } else { |
| @@ -768,7 +768,9 @@ static void __mlxsw_sp_port_get_stats(struct net_device *dev, · 767 unmodified lines | ||
| 768 | 768 | err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp); |
| 769 | 769 | if (err) |
| 770 | 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 | 774 | for (i = 0; i < len; i++) { |
| 773 | 775 | data[data_index + i] = hw_stats[i].getter(ppcnt_pl); |
| 774 | 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 | 20 | struct sk_buff *skb; |
| 21 | 21 | |
| 22 | 22 | skb = nfp_app_ctrl_msg_alloc(bpf->app, size, GFP_KERNEL); |
| 23 | + if (!skb) | |
| 24 | + return NULL; | |
| 23 | 25 | skb_put(skb, size); |
| 24 | 26 | |
| 25 | 27 | return skb; |
| @@ -2094,6 +2094,11 @@ static int __alloc_dma_rx_desc_resources(struct stmmac_priv *priv, · 2093 unmodified lines | ||
| 2094 | 2094 | pp_params.offset = stmmac_rx_offset(priv); |
| 2095 | 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 | 2102 | rx_q->page_pool = page_pool_create(&pp_params); |
| 2098 | 2103 | if (IS_ERR(rx_q->page_pool)) { |
| 2099 | 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 | 2429 | u32 chan = 0; |
| 2425 | 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 | 2437 | /* Split up the shared Tx/Rx FIFO memory on DW QoS Eth and DW XGMAC */ |
| 2428 | 2438 | if (priv->plat->has_gmac4 || priv->plat->has_xgmac) { |
| 2429 | 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 | 2902 | int rxfifosz = priv->plat->rx_fifo_size; |
| 2893 | 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 | 2910 | /* Adjust for real per queue fifo size */ |
| 2896 | 2911 | rxfifosz /= rx_channels_count; |
| 2897 | 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 | 5883 | const int mtu = new_mtu; |
| 5869 | 5884 | int ret; |
| 5870 | 5885 | |
| 5886 | + if (txfifosz == 0) | |
| 5887 | + txfifosz = priv->dma_cap.tx_fifo_size; | |
| 5888 | + | |
| 5871 | 5889 | txfifosz /= priv->plat->tx_queues_to_use; |
| 5872 | 5890 | |
| 5873 | 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 | 7237 | priv->plat->tx_queues_to_use = priv->dma_cap.number_tx_queues; |
| 7220 | 7238 | } |
| 7221 | 7239 | |
| 7222 | − if (!priv->plat->rx_fifo_size) { | |
| 7223 | − if (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) { | |
| 7240 | + if (priv->dma_cap.rx_fifo_size && | |
| 7241 | + priv->plat->rx_fifo_size > priv->dma_cap.rx_fifo_size) { | |
| 7231 | 7242 | dev_warn(priv->device, |
| 7232 | 7243 | "Rx FIFO size (%u) exceeds dma capability\n", |
| 7233 | 7244 | priv->plat->rx_fifo_size); |
| 7234 | 7245 | priv->plat->rx_fifo_size = priv->dma_cap.rx_fifo_size; |
| 7235 | 7246 | } |
| 7236 | − if (!priv->plat->tx_fifo_size) { | |
| 7237 | − if (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) { | |
| 7247 | + if (priv->dma_cap.tx_fifo_size && | |
| 7248 | + priv->plat->tx_fifo_size > priv->dma_cap.tx_fifo_size) { | |
| 7245 | 7249 | dev_warn(priv->device, |
| 7246 | 7250 | "Tx FIFO size (%u) exceeds dma capability\n", |
| 7247 | 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 | 828 | static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma) |
| 829 | 829 | { |
| 830 | 830 | struct am65_cpsw_tx_chn *tx_chn = data; |
| 831 | + enum am65_cpsw_tx_buf_type buf_type; | |
| 831 | 832 | struct cppi5_host_desc_t *desc_tx; |
| 833 | + struct xdp_frame *xdpf; | |
| 832 | 834 | struct sk_buff *skb; |
| 833 | 835 | void **swdata; |
| 834 | 836 | |
| 835 | 837 | desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma); |
| 836 | 838 | swdata = cppi5_hdesc_get_swdata(desc_tx); |
| 837 | − skb = *(swdata); | |
| 838 | − am65_cpsw_nuss_xmit_free(tx_chn, desc_tx); | |
| 839 | + buf_type = am65_cpsw_nuss_buf_type(tx_chn, desc_dma); | |
| 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 | 851 | static struct sk_buff *am65_cpsw_build_skb(void *page_addr, |
| 844 | 852 | struct net_device *ndev, |
| 845 | − unsigned int len) | |
| 853 | + unsigned int len, | |
| 854 | + unsigned int headroom) | |
| 846 | 855 | { |
| 847 | 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 | 861 | if (unlikely(!skb)) |
| 853 | 862 | return NULL; |
| 854 | 863 | |
| 855 | − skb_reserve(skb, AM65_CPSW_HEADROOM); | |
| 864 | + skb_reserve(skb, headroom); | |
| 856 | 865 | skb->dev = ndev; |
| 857 | 866 | |
| 858 | 867 | return skb; |
| @@ -1169,9 +1178,11 @@ static int am65_cpsw_run_xdp(struct am65_cpsw_rx_flow *flow, · 310 unmodified lines | ||
| 1169 | 1178 | struct xdp_frame *xdpf; |
| 1170 | 1179 | struct bpf_prog *prog; |
| 1171 | 1180 | struct page *page; |
| 1181 | + int pkt_len; | |
| 1172 | 1182 | u32 act; |
| 1173 | 1183 | int err; |
| 1174 | 1184 | |
| 1185 | + pkt_len = *len; | |
| 1175 | 1186 | prog = READ_ONCE(port->xdp_prog); |
| 1176 | 1187 | if (!prog) |
| 1177 | 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 | 1200 | netif_txq = netdev_get_tx_queue(ndev, tx_chn->id); |
| 1190 | 1201 | |
| 1191 | 1202 | xdpf = xdp_convert_buff_to_frame(xdp); |
| 1192 | − if (unlikely(!xdpf)) | |
| 1203 | + if (unlikely(!xdpf)) { | |
| 1204 | + ndev->stats.tx_dropped++; | |
| 1193 | 1205 | goto drop; |
| 1206 | + } | |
| 1194 | 1207 | |
| 1195 | 1208 | __netif_tx_lock(netif_txq, cpu); |
| 1196 | 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 | 1212 | if (err) |
| 1200 | 1213 | goto drop; |
| 1201 | 1214 | |
| 1202 | − dev_sw_netstats_tx_add(ndev, 1, *len); | |
| 1215 | + dev_sw_netstats_rx_add(ndev, pkt_len); | |
| 1203 | 1216 | ret = AM65_CPSW_XDP_CONSUMED; |
| 1204 | 1217 | goto out; |
| 1205 | 1218 | case XDP_REDIRECT: |
| 1206 | 1219 | if (unlikely(xdp_do_redirect(ndev, xdp, prog))) |
| 1207 | 1220 | goto drop; |
| 1208 | 1221 | |
| 1209 | − dev_sw_netstats_rx_add(ndev, *len); | |
| 1222 | + dev_sw_netstats_rx_add(ndev, pkt_len); | |
| 1210 | 1223 | ret = AM65_CPSW_XDP_REDIRECT; |
| 1211 | 1224 | goto out; |
| 1212 | 1225 | default: |
| @@ -1315,16 +1328,8 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow, · 102 unmodified lines | ||
| 1315 | 1328 | dev_dbg(dev, "%s rx csum_info:%#x\n", __func__, csum_info); |
| 1316 | 1329 | |
| 1317 | 1330 | dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE); |
| 1318 | − | |
| 1319 | 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 | 1333 | if (port->xdp_prog) { |
| 1329 | 1334 | xdp_init_buff(&xdp, PAGE_SIZE, &port->xdp_rxq[flow->id]); |
| 1330 | 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 | 1339 | if (*xdp_state != AM65_CPSW_XDP_PASS) |
| 1335 | 1340 | goto allocate; |
| 1336 | 1341 | |
| 1337 | − /* Compute additional headroom to be reserved */ | |
| 1338 | − headroom = (xdp.data - xdp.data_hard_start) - skb_headroom(skb); | |
| 1339 | − skb_reserve(skb, headroom); | |
| 1342 | + headroom = xdp.data - xdp.data_hard_start; | |
| 1343 | + } else { | |
| 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 | 1354 | ndev_priv = netdev_priv(ndev); |
| @@ -2897,6 +2897,7 @@ static int axienet_probe(struct platform_device *pdev) · 2896 unmodified lines | ||
| 2897 | 2897 | |
| 2898 | 2898 | lp->phylink_config.dev = &ndev->dev; |
| 2899 | 2899 | lp->phylink_config.type = PHYLINK_NETDEV; |
| 2900 | + lp->phylink_config.mac_managed_pm = true; | |
| 2900 | 2901 | lp->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE | |
| 2901 | 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 | 1903 | struct geneve_net *gn = net_generic(net, geneve_net_id); |
| 1904 | 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 */ | |
| 1908 | − for_each_netdev_safe(net, dev, aux) | |
| 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 | − } | |
| 1906 | + list_for_each_entry_safe(geneve, next, &gn->geneve_list, next) | |
| 1907 | + geneve_dellink(geneve->dev, head); | |
| 1920 | 1908 | } |
| 1921 | 1909 | |
| 1922 | 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 | 2481 | list_for_each_entry(net, net_list, exit_list) { |
| 2482 | 2482 | struct gtp_net *gn = net_generic(net, gtp_net_id); |
| 2483 | 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 | 2485 | list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list) |
| 2491 | 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 | 2265 | /* Allow the MAC to stop its clock if the PHY has the capability */ |
| 2266 | 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 | |
| 2269 | − * receive clock. | |
| 2270 | − */ | |
| 2271 | − ret = phy_eee_rx_clock_stop(phy, pl->config->eee_rx_clk_stop_enable); | |
| 2272 | − if (ret == -EOPNOTSUPP) | |
| 2273 | − ret = 0; | |
| 2268 | + if (pl->mac_supports_eee_ops) { | |
| 2269 | + /* Explicitly configure whether the PHY is allowed to stop it's | |
| 2270 | + * receive clock. | |
| 2271 | + */ | |
| 2272 | + ret = phy_eee_rx_clock_stop(phy, | |
| 2273 | + pl->config->eee_rx_clk_stop_enable); | |
| 2274 | + if (ret == -EOPNOTSUPP) | |
| 2275 | + ret = 0; | |
| 2276 | + } | |
| 2274 | 2277 | |
| 2275 | 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 | 1047 | if (ret < 0) |
| 1048 | 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 | 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 | 319 | goto out; |
| 320 | 320 | mW = ret; |
| 321 | 321 | |
| 322 | − ret = pse_pi_get_voltage(rdev); | |
| 322 | + ret = _pse_pi_get_voltage(rdev); | |
| 323 | 323 | if (!ret) { |
| 324 | 324 | dev_err(pcdev->dev, "Voltage null\n"); |
| 325 | 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 | 357 | id = rdev_get_id(rdev); |
| 358 | 358 | mutex_lock(&pcdev->lock); |
| 359 | − ret = pse_pi_get_voltage(rdev); | |
| 359 | + ret = _pse_pi_get_voltage(rdev); | |
| 360 | 360 | if (!ret) { |
| 361 | 361 | dev_err(pcdev->dev, "Voltage null\n"); |
| 362 | 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 | 2639 | ctx.data.u32_val = nla_get_u32(attr_data); |
| 2640 | 2640 | break; |
| 2641 | 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 | 2645 | err = -EINVAL; |
| 2644 | 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 | 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 | 579 | const struct cred *cred = current_cred(); |
| 580 | 580 | struct net *net = dev_net(tun->dev); |
| 581 | 581 | |
| 582 | − if (ns_capable(net->user_ns, CAP_NET_ADMIN)) | |
| 583 | − return 1; | |
| 584 | − if (uid_valid(tun->owner) && uid_eq(cred->euid, tun->owner)) | |
| 585 | − return 1; | |
| 586 | − if (gid_valid(tun->group) && in_egroup_p(tun->group)) | |
| 587 | − return 1; | |
| 588 | − return 0; | |
| 582 | + return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) || | |
| 583 | + (gid_valid(tun->group) && !in_egroup_p(tun->group))) && | |
| 584 | + !ns_capable(net->user_ns, CAP_NET_ADMIN); | |
| 589 | 585 | } |
| 590 | 586 | |
| 591 | 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 | 2778 | !!(tun->flags & IFF_MULTI_QUEUE)) |
| 2783 | 2779 | return -EINVAL; |
| 2784 | 2780 | |
| 2785 | − if (!tun_capable(tun)) | |
| 2781 | + if (tun_not_capable(tun)) | |
| 2786 | 2782 | return -EPERM; |
| 2787 | 2783 | err = security_tun_dev_open(tun->security); |
| 2788 | 2784 | if (err < 0) |
| @@ -28,7 +28,7 @@ vmxnet3_xdp_get_tq(struct vmxnet3_adapter *adapter) · 27 unmodified lines | ||
| 28 | 28 | if (likely(cpu < tq_number)) |
| 29 | 29 | tq = &adapter->tx_queue[cpu]; |
| 30 | 30 | else |
| 31 | − tq = &adapter->tx_queue[reciprocal_scale(cpu, tq_number)]; | |
| 31 | + tq = &adapter->tx_queue[cpu % tq_number]; | |
| 32 | 32 | |
| 33 | 33 | return tq; |
| 34 | 34 | } |
| @@ -124,6 +124,7 @@ vmxnet3_xdp_xmit_frame(struct vmxnet3_adapter *adapter, · 89 unmodified lines | ||
| 124 | 124 | u32 buf_size; |
| 125 | 125 | u32 dw2; |
| 126 | 126 | |
| 127 | + spin_lock_irq(&tq->tx_lock); | |
| 127 | 128 | dw2 = (tq->tx_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT; |
| 128 | 129 | dw2 |= xdpf->len; |
| 129 | 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 | 136 | if (vmxnet3_cmd_ring_desc_avail(&tq->tx_ring) == 0) { |
| 136 | 137 | tq->stats.tx_ring_full++; |
| 138 | + spin_unlock_irq(&tq->tx_lock); | |
| 137 | 139 | return -ENOSPC; |
| 138 | 140 | } |
| 139 | 141 | |
| @@ -142,8 +144,10 @@ vmxnet3_xdp_xmit_frame(struct vmxnet3_adapter *adapter, · 2 unmodified lines | ||
| 142 | 144 | tbi->dma_addr = dma_map_single(&adapter->pdev->dev, |
| 143 | 145 | xdpf->data, buf_size, |
| 144 | 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 | 149 | return -EFAULT; |
| 150 | + } | |
| 147 | 151 | tbi->map_type |= VMXNET3_MAP_SINGLE; |
| 148 | 152 | } else { /* XDP buffer from page pool */ |
| 149 | 153 | page = virt_to_page(xdpf->data); |
| @@ -182,6 +186,7 @@ vmxnet3_xdp_xmit_frame(struct vmxnet3_adapter *adapter, · 32 unmodified lines | ||
| 182 | 186 | dma_wmb(); |
| 183 | 187 | gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^ |
| 184 | 188 | VMXNET3_TXD_GEN); |
| 189 | + spin_unlock_irq(&tq->tx_lock); | |
| 185 | 190 | |
| 186 | 191 | /* No need to handle the case when tx_num_deferred doesn't reach |
| 187 | 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 | 231 | struct vmxnet3_adapter *adapter = netdev_priv(dev); |
| 227 | 232 | struct vmxnet3_tx_queue *tq; |
| 233 | + struct netdev_queue *nq; | |
| 228 | 234 | int i; |
| 229 | 235 | |
| 230 | 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 | 242 | if (tq->stopped) |
| 237 | 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 | 248 | for (i = 0; i < n; i++) { |
| 240 | 249 | if (vmxnet3_xdp_xmit_frame(adapter, frames[i], tq, true)) { |
| 241 | 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 | 254 | tq->stats.xdp_xmit += i; |
| 255 | + __netif_tx_unlock(nq); | |
| 246 | 256 | |
| 247 | 257 | return i; |
| 248 | 258 | } |
| @@ -2898,8 +2898,11 @@ static int vxlan_init(struct net_device *dev) · 2897 unmodified lines | ||
| 2898 | 2898 | struct vxlan_dev *vxlan = netdev_priv(dev); |
| 2899 | 2899 | int err; |
| 2900 | 2900 | |
| 2901 | − if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) | |
| 2902 | − vxlan_vnigroup_init(vxlan); | |
| 2901 | + if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) { | |
| 2902 | + err = vxlan_vnigroup_init(vxlan); | |
| 2903 | + if (err) | |
| 2904 | + return err; | |
| 2905 | + } | |
| 2903 | 2906 | |
| 2904 | 2907 | err = gro_cells_init(&vxlan->gro_cells, dev); |
| 2905 | 2908 | if (err) |
| @@ -4851,6 +4851,22 @@ static struct ath12k_reg_rule · 4850 unmodified lines | ||
| 4851 | 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 | 4870 | static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab, |
| 4855 | 4871 | struct sk_buff *skb, |
| 4856 | 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 | 4877 | u32 num_2g_reg_rules, num_5g_reg_rules; |
| 4862 | 4878 | u32 num_6g_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; |
| 4863 | 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 | 4881 | u32 total_reg_rules = 0; |
| 4865 | 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 | 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 | 4974 | reg_info->dfs_region = le32_to_cpu(ev->dfs_region); |
| 4972 | 4975 | reg_info->phybitmap = le32_to_cpu(ev->phybitmap); |
| 4973 | 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 | 5098 | if (num_5g_reg_rules) { |
| 5074 | − ext_wmi_reg_rule += num_2g_reg_rules; | |
| 5075 | 5099 | reg_info->reg_rules_5g_ptr = |
| 5076 | 5100 | create_ext_reg_rules_from_wmi(num_5g_reg_rules, |
| 5077 | 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 | 5117 | for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) { |
| 5089 | 5118 | reg_info->reg_rules_6g_ap_ptr[i] = |
| @@ -4073,7 +4073,6 @@ struct ath12k_wmi_eht_rate_set_params { · 4072 unmodified lines | ||
| 4073 | 4073 | #define MAX_REG_RULES 10 |
| 4074 | 4074 | #define REG_ALPHA2_LEN 2 |
| 4075 | 4075 | #define MAX_6G_REG_RULES 5 |
| 4076 | −#define REG_US_5G_NUM_REG_RULES 4 | |
| 4077 | 4076 | |
| 4078 | 4077 | enum wmi_start_event_param { |
| 4079 | 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 | 2712 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID, WCC), |
| 2713 | 2713 | BRCMF_PCIE_DEVICE_SUB(0x4355, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4355, WCC), |
| 2714 | 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 | 2716 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID, WCC), |
| 2717 | 2717 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID, WCC), |
| 2718 | 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 | 2723 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID, WCC), |
| 2724 | 2724 | BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID, WCC), |
| 2725 | 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 | 2727 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID, BCA), |
| 2728 | 2728 | BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID, BCA), |
| 2729 | 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 | 220 | if (mbim->rx_seq + 1 != le16_to_cpu(nth16->wSequence) && |
| 221 | 221 | (mbim->rx_seq || le16_to_cpu(nth16->wSequence)) && |
| 222 | 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 | 224 | mbim->rx_seq, le16_to_cpu(nth16->wSequence)); |
| 225 | 225 | } |
| 226 | 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 | 1701 | status = nvme_set_features(ctrl, NVME_FEAT_NUM_QUEUES, q_count, NULL, 0, |
| 1702 | 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 | 1710 | return status; |
| 1705 | 1711 | |
| 1706 | 1712 | /* |
| @@ -781,11 +781,19 @@ restart: · 780 unmodified lines | ||
| 781 | 781 | static void |
| 782 | 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 | 787 | dev_info(ctrl->ctrl.device, |
| 785 | 788 | "NVME-FC{%d}: controller connectivity lost. Awaiting " |
| 786 | 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 | 797 | case NVME_CTRL_NEW: |
| 790 | 798 | case NVME_CTRL_LIVE: |
| 791 | 799 | /* |
| @@ -2079,7 +2087,8 @@ done: · 1287 unmodified lines | ||
| 2079 | 2087 | nvme_fc_complete_rq(rq); |
| 2080 | 2088 | |
| 2081 | 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 | 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 | 2542 | static void |
| 2534 | 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 | 2548 | * if an error (io timeout, etc) while (re)connecting, the remote |
| 2538 | 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 | 2551 | * the controller. Abort any ios on the association and let the |
| 2541 | 2552 | * create_association error path resolve things. |
| 2542 | 2553 | */ |
| 2543 | − if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) { | |
| 2554 | + if (state == NVME_CTRL_CONNECTING) { | |
| 2544 | 2555 | __nvme_fc_abort_outstanding_ios(ctrl, true); |
| 2545 | − set_bit(ASSOC_FAILED, &ctrl->flags); | |
| 2546 | 2556 | dev_warn(ctrl->ctrl.device, |
| 2547 | 2557 | "NVME-FC{%d}: transport error during (re)connect\n", |
| 2548 | 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 | 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 | 2564 | return; |
| 2555 | 2565 | |
| 2556 | 2566 | dev_warn(ctrl->ctrl.device, |
| @@ -3167,12 +3177,18 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) · 610 unmodified lines | ||
| 3167 | 3177 | else |
| 3168 | 3178 | ret = nvme_fc_recreate_io_queues(ctrl); |
| 3169 | 3179 | } |
| 3170 | − if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags)) | |
| 3171 | − ret = -EIO; | |
| 3172 | 3180 | if (ret) |
| 3173 | 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 | 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 | 3594 | list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list); |
| 3579 | 3595 | spin_unlock_irqrestore(&rport->lock, flags); |
| 3580 | 3596 | |
| 3581 | − if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING) || | |
| 3582 | − !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) { | |
| 3597 | + if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) { | |
| 3583 | 3598 | dev_err(ctrl->ctrl.device, |
| 3584 | 3599 | "NVME-FC{%d}: failed to init ctrl state\n", ctrl->cnum); |
| 3585 | 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 | 2153 | return 0; |
| 2154 | 2154 | |
| 2155 | 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 | 2156 | kfree(bufs); |
| 2165 | 2157 | out_free_descs: |
| 2166 | 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 | 3139 | * because of high power consumption (> 2 Watt) in s2idle |
| 3148 | 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 | 3145 | dmi_match(DMI_BOARD_NAME, "PH4PG31") || |
| 3152 | 3146 | dmi_match(DMI_BOARD_NAME, "PH4PRX1_PH6PRX1") || |
| 3153 | 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 | 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 | 796 | .attrs = nvme_tls_attrs, |
| 797 | 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 | 1068 | goto out; |
| 1069 | 1069 | } |
| 1070 | 1070 | status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id)); |
| 1071 | + kfree(id); | |
| 1071 | 1072 | out: |
| 1072 | 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 | 287 | args.subsysnqn = d->subsysnqn; |
| 288 | 288 | args.hostnqn = d->hostnqn; |
| 289 | 289 | args.hostid = &d->hostid; |
| 290 | − args.kato = c->kato; | |
| 290 | + args.kato = le32_to_cpu(c->kato); | |
| 291 | 291 | |
| 292 | 292 | ctrl = nvmet_alloc_ctrl(&args); |
| 293 | 293 | if (!ctrl) |
| @@ -272,7 +272,7 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req) · 271 unmodified lines | ||
| 272 | 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 | 276 | opf |= REQ_FAILFAST_DEV; |
| 277 | 277 | |
| 278 | 278 | if (is_pci_p2pdma_page(sg_page(req->sg))) |
| @@ -589,7 +589,7 @@ struct nvmet_alloc_ctrl_args { · 588 unmodified lines | ||
| 589 | 589 | const struct nvmet_fabrics_ops *ops; |
| 590 | 590 | struct device *p2p_client; |
| 591 | 591 | u32 kato; |
| 592 | − u32 result; | |
| 592 | + __le32 result; | |
| 593 | 593 | u16 error_loc; |
| 594 | 594 | u16 status; |
| 595 | 595 | }; |
| @@ -16,6 +16,8 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/string.h> |
| 17 | 17 | #include <linux/dma-direct.h> /* for bus_dma_region */ |
| 18 | 18 | |
| 19 | +#include <kunit/visibility.h> | |
| 20 | + | |
| 19 | 21 | /* Uncomment me to enable of_dump_addr() debugging output */ |
| 20 | 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 | 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 | 190 | if (overflows_type(start, r->start)) |
| 189 | 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 | 200 | return 0; |
| 199 | 201 | } |
| 202 | +EXPORT_SYMBOL_IF_KUNIT(__of_address_resource_bounds); | |
| 200 | 203 | |
| 201 | 204 | /* |
| 202 | 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 | 208 | static void __maybe_unused of_dump_addr(const char *s, const __be32 *addr, int na) { } |
| 209 | 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 | 215 | #endif /* _LINUX_OF_PRIVATE_H */ |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * KUnit tests for OF APIs |
| 4 | 4 | */ |
| 5 | +#include <linux/ioport.h> | |
| 5 | 6 | #include <linux/module.h> |
| 6 | 7 | #include <linux/of.h> |
| 7 | 8 | |
| @@ -54,8 +55,124 @@ static struct kunit_suite of_dtb_suite = { · 46 unmodified lines | ||
| 54 | 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 | 173 | kunit_test_suites( |
| 58 | − &of_dtb_suite, | |
| 174 | + &of_dtb_suite, &of_address_suite, | |
| 59 | 175 | ); |
| 60 | 176 | MODULE_DESCRIPTION("KUnit tests for OF APIs"); |
| 177 | +MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); | |
| 61 | 178 | MODULE_LICENSE("GPL"); |
| @@ -108,9 +108,6 @@ void pci_save_aspm_l1ss_state(struct pci_dev *pdev) · 107 unmodified lines | ||
| 108 | 108 | pci_read_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL2, cap++); |
| 109 | 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 | 112 | * Save parent's L1 substate configuration so we have it for |
| 116 | 113 | * pci_restore_aspm_l1ss_state(pdev) to restore. |
| @@ -339,13 +339,14 @@ out: · 338 unmodified lines | ||
| 339 | 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 | 345 | u32 rombar, stdbars[PCI_STD_NUM_BARS]; |
| 345 | 346 | unsigned int pos, reg; |
| 346 | 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 | 351 | if (dev->non_compliant_bars) |
| 351 | 352 | return; |
| @@ -5522,7 +5522,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap); · 5521 unmodified lines | ||
| 5522 | 5522 | * AMD Matisse USB 3.0 Host Controller 0x149c |
| 5523 | 5523 | * Intel 82579LM Gigabit Ethernet Controller 0x1502 |
| 5524 | 5524 | * Intel 82579V Gigabit Ethernet Controller 0x1503 |
| 5525 | − * | |
| 5525 | + * Mediatek MT7922 802.11ax PCI Express Wireless Network Adapter | |
| 5526 | 5526 | */ |
| 5527 | 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 | 5534 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x7901, quirk_no_flr); |
| 5535 | 5535 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1502, quirk_no_flr); |
| 5536 | 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 | 5539 | /* FLR may cause the SolidRun SNET DPU (rev 0x1) to hang */ |
| 5539 | 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 | 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 | 365 | pci_dbg(pdev, "set steering tag: %s table, index=%d, tag=%#04x\n", |
| 366 | 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 | 89 | seq_puts(s, items[i].display); |
| 90 | 90 | /* Print unit if available */ |
| 91 | 91 | if (items[i].has_arg) { |
| 92 | − seq_printf(s, " (0x%x", | |
| 93 | − pinconf_to_config_argument(config)); | |
| 92 | + u32 val = pinconf_to_config_argument(config); | |
| 93 | + | |
| 94 | 94 | if (items[i].format) |
| 95 | − seq_printf(s, " %s)", items[i].format); | |
| 95 | + seq_printf(s, " (%u %s)", val, items[i].format); | |
| 96 | 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 | 42 | #define CY8C95X0_PORTSEL 0x18 |
| 43 | 43 | /* Port settings, write PORTSEL first */ |
| 44 | 44 | #define CY8C95X0_INTMASK 0x19 |
| 45 | −#define CY8C95X0_PWMSEL 0x1A | |
| 45 | +#define CY8C95X0_SELPWM 0x1A | |
| 46 | 46 | #define CY8C95X0_INVERT 0x1B |
| 47 | 47 | #define CY8C95X0_DIRECTION 0x1C |
| 48 | 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 | 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 | |
| 332 | − * datasheet). | |
| 331 | + * Only 12 registers are present per port (see Table 6 in the datasheet). | |
| 333 | 332 | */ |
| 334 | − if (reg >= CY8C95X0_VIRTUAL && (reg % MUXED_STRIDE) < 12) | |
| 335 | − return true; | |
| 333 | + if (reg >= CY8C95X0_VIRTUAL && (reg % MUXED_STRIDE) >= 12) | |
| 334 | + return false; | |
| 336 | 335 | |
| 337 | 336 | switch (reg) { |
| 338 | 337 | case 0x24 ... 0x27: |
| 338 | + case 0x31 ... 0x3f: | |
| 339 | 339 | return false; |
| 340 | 340 | default: |
| 341 | 341 | return true; |
| @@ -344,8 +344,11 @@ static bool cy8c95x0_readable_register(struct device *dev, unsigned int reg) · 2 unmodified lines | ||
| 344 | 344 | |
| 345 | 345 | static bool cy8c95x0_writeable_register(struct device *dev, unsigned int reg) |
| 346 | 346 | { |
| 347 | − if (reg >= CY8C95X0_VIRTUAL) | |
| 348 | − return true; | |
| 347 | + /* | |
| 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 | 353 | switch (reg) { |
| 351 | 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 | 356 | case CY8C95X0_DEVID: |
| 354 | 357 | return false; |
| 355 | 358 | case 0x24 ... 0x27: |
| 359 | + case 0x31 ... 0x3f: | |
| 356 | 360 | return false; |
| 357 | 361 | default: |
| 358 | 362 | return true; |
| @@ -365,8 +369,8 @@ static bool cy8c95x0_volatile_register(struct device *dev, unsigned int reg) · 6 unmodified lines | ||
| 365 | 369 | case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7): |
| 366 | 370 | case CY8C95X0_INTSTATUS_(0) ... CY8C95X0_INTSTATUS_(7): |
| 367 | 371 | case CY8C95X0_INTMASK: |
| 372 | + case CY8C95X0_SELPWM: | |
| 368 | 373 | case CY8C95X0_INVERT: |
| 369 | − case CY8C95X0_PWMSEL: | |
| 370 | 374 | case CY8C95X0_DIRECTION: |
| 371 | 375 | case CY8C95X0_DRV_PU: |
| 372 | 376 | case CY8C95X0_DRV_PD: |
| @@ -395,7 +399,7 @@ static bool cy8c95x0_muxed_register(unsigned int reg) · 22 unmodified lines | ||
| 395 | 399 | { |
| 396 | 400 | switch (reg) { |
| 397 | 401 | case CY8C95X0_INTMASK: |
| 398 | − case CY8C95X0_PWMSEL: | |
| 402 | + case CY8C95X0_SELPWM: | |
| 399 | 403 | case CY8C95X0_INVERT: |
| 400 | 404 | case CY8C95X0_DIRECTION: |
| 401 | 405 | case CY8C95X0_DRV_PU: |
| @@ -466,7 +470,11 @@ static const struct regmap_config cy8c9520_i2c_regmap = { · 64 unmodified lines | ||
| 466 | 470 | .max_register = 0, /* Updated at runtime */ |
| 467 | 471 | .num_reg_defaults_raw = 0, /* Updated at runtime */ |
| 468 | 472 | .use_single_read = true, /* Workaround for regcache bug */ |
| 473 | +#if IS_ENABLED(CONFIG_DEBUG_PINCTRL) | |
| 474 | + .disable_locking = false, | |
| 475 | +#else | |
| 469 | 476 | .disable_locking = true, |
| 477 | +#endif | |
| 470 | 478 | }; |
| 471 | 479 | |
| 472 | 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 | 797 | reg = CY8C95X0_DIRECTION; |
| 790 | 798 | break; |
| 791 | 799 | case PIN_CONFIG_MODE_PWM: |
| 792 | − reg = CY8C95X0_PWMSEL; | |
| 800 | + reg = CY8C95X0_SELPWM; | |
| 793 | 801 | break; |
| 794 | 802 | case PIN_CONFIG_OUTPUT: |
| 795 | 803 | reg = CY8C95X0_OUTPUT; |
| @@ -868,7 +876,7 @@ static int cy8c95x0_gpio_set_pincfg(struct cy8c95x0_pinctrl *chip, · 72 unmodified lines | ||
| 868 | 876 | reg = CY8C95X0_DRV_PP_FAST; |
| 869 | 877 | break; |
| 870 | 878 | case PIN_CONFIG_MODE_PWM: |
| 871 | − reg = CY8C95X0_PWMSEL; | |
| 879 | + reg = CY8C95X0_SELPWM; | |
| 872 | 880 | break; |
| 873 | 881 | case PIN_CONFIG_OUTPUT_ENABLE: |
| 874 | 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 | 1161 | bitmap_zero(mask, MAX_LINE); |
| 1154 | 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 | 1165 | seq_puts(s, "not available"); |
| 1158 | 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 | 1206 | u8 port = cypress_get_port(chip, off); |
| 1199 | 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 | 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 | 1356 | ret = devm_request_threaded_irq(chip->dev, irq, |
| 1349 | 1357 | NULL, cy8c95x0_irq_handler, |
| 1350 | − IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_HIGH, | |
| 1358 | + IRQF_ONESHOT | IRQF_SHARED, | |
| 1351 | 1359 | dev_name(chip->dev), chip); |
| 1352 | 1360 | if (ret) { |
| 1353 | 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 | 1446 | switch (chip->tpin) { |
| 1439 | 1447 | case 20: |
| 1440 | 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 | 1450 | break; |
| 1443 | 1451 | case 40: |
| 1444 | 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 | 1454 | break; |
| 1447 | 1455 | case 60: |
| 1448 | 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 | 1458 | break; |
| 1451 | 1459 | default: |
| 1452 | 1460 | return -ENODEV; |
| @@ -1121,7 +1121,7 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv) · 1120 unmodified lines | ||
| 1121 | 1121 | |
| 1122 | 1122 | /* Create platform_profile structure and register */ |
| 1123 | 1123 | priv->dytc->ppdev = devm_platform_profile_register(&priv->platform_device->dev, |
| 1124 | − "ideapad-laptop", &priv->dytc, | |
| 1124 | + "ideapad-laptop", priv->dytc, | |
| 1125 | 1125 | &dytc_profile_ops); |
| 1126 | 1126 | if (IS_ERR(priv->dytc->ppdev)) { |
| 1127 | 1127 | err = PTR_ERR(priv->dytc->ppdev); |
| @@ -23,12 +23,14 @@ · 22 unmodified lines | ||
| 23 | 23 | * IFS Image |
| 24 | 24 | * --------- |
| 25 | 25 | * |
| 26 | − * Intel provides a firmware file containing the scan tests via | |
| 27 | − * github [#f1]_. Similar to microcode there is a separate file for each | |
| 26 | + * Intel provides firmware files containing the scan tests via the webpage [#f1]_. | |
| 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 | 29 | * family-model-stepping. IFS Images are not applicable for some test types. |
| 29 | 30 | * Wherever applicable the sysfs directory would provide a "current_batch" file |
| 30 | 31 | * (see below) for loading the image. |
| 31 | 32 | * |
| 33 | + * .. [#f1] https://intel.com/InFieldScan | |
| 32 | 34 | * |
| 33 | 35 | * IFS Image Loading |
| 34 | 36 | * ----------------- |
| @@ -125,9 +127,6 @@ · 90 unmodified lines | ||
| 125 | 127 | * 2) Hardware allows for some number of cores to be tested in parallel. |
| 126 | 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 | 130 | * Structural Based Functional Test at Field (SBAF): |
| 132 | 131 | * ------------------------------------------------- |
| 133 | 132 | * |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | /* Author: Dan Scally <djrscally@gmail.com> */ |
| 3 | 3 | |
| 4 | 4 | #include <linux/acpi.h> |
| 5 | +#include <linux/array_size.h> | |
| 5 | 6 | #include <linux/bitfield.h> |
| 6 | 7 | #include <linux/device.h> |
| 7 | 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 | 57 | static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry, |
| 57 | 58 | struct acpi_resource_gpio *agpio, |
| 58 | − const char *func, u32 polarity) | |
| 59 | + const char *func, unsigned long gpio_flags) | |
| 59 | 60 | { |
| 60 | 61 | char *path = agpio->resource_source.string_ptr; |
| 61 | 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 | 71 | if (!adev) |
| 71 | 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 | 76 | return 0; |
| 76 | 77 | } |
| 77 | 78 | |
| 78 | 79 | static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472, |
| 79 | 80 | struct acpi_resource_gpio *agpio, |
| 80 | − const char *func, u32 polarity) | |
| 81 | + const char *func, unsigned long gpio_flags) | |
| 81 | 82 | { |
| 82 | 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 | 90 | ret = skl_int3472_fill_gpiod_lookup(&int3472->gpios.table[int3472->n_sensor_gpios], |
| 90 | − agpio, func, polarity); | |
| 91 | + agpio, func, gpio_flags); | |
| 91 | 92 | if (ret) |
| 92 | 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 | 101 | static struct gpio_desc * |
| 101 | 102 | skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, |
| 102 | 103 | struct acpi_resource_gpio *agpio, |
| 103 | − const char *func, u32 polarity) | |
| 104 | + const char *func, unsigned long gpio_flags) | |
| 104 | 105 | { |
| 105 | 106 | struct gpio_desc *desc; |
| 106 | 107 | int ret; |
| @@ -111,7 +112,7 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472, · 4 unmodified lines | ||
| 111 | 112 | return ERR_PTR(-ENOMEM); |
| 112 | 113 | |
| 113 | 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 | 116 | if (ret) |
| 116 | 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 | 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 | 173 | case INT3472_GPIO_TYPE_RESET: |
| 129 | 174 | *func = "reset"; |
| 130 | − *polarity = GPIO_ACTIVE_LOW; | |
| 175 | + *gpio_flags = GPIO_ACTIVE_LOW; | |
| 131 | 176 | break; |
| 132 | 177 | case INT3472_GPIO_TYPE_POWERDOWN: |
| 133 | 178 | *func = "powerdown"; |
| 134 | − *polarity = GPIO_ACTIVE_LOW; | |
| 179 | + *gpio_flags = GPIO_ACTIVE_LOW; | |
| 135 | 180 | break; |
| 136 | 181 | case INT3472_GPIO_TYPE_CLK_ENABLE: |
| 137 | 182 | *func = "clk-enable"; |
| 138 | − *polarity = GPIO_ACTIVE_HIGH; | |
| 183 | + *gpio_flags = GPIO_ACTIVE_HIGH; | |
| 139 | 184 | break; |
| 140 | 185 | case INT3472_GPIO_TYPE_PRIVACY_LED: |
| 141 | 186 | *func = "privacy-led"; |
| 142 | − *polarity = GPIO_ACTIVE_HIGH; | |
| 187 | + *gpio_flags = GPIO_ACTIVE_HIGH; | |
| 143 | 188 | break; |
| 144 | 189 | case INT3472_GPIO_TYPE_POWER_ENABLE: |
| 145 | 190 | *func = "power-enable"; |
| 146 | − *polarity = GPIO_ACTIVE_HIGH; | |
| 191 | + *gpio_flags = GPIO_ACTIVE_HIGH; | |
| 147 | 192 | break; |
| 148 | 193 | default: |
| 149 | 194 | *func = "unknown"; |
| 150 | − *polarity = GPIO_ACTIVE_HIGH; | |
| 195 | + *gpio_flags = GPIO_ACTIVE_HIGH; | |
| 151 | 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 | 239 | struct gpio_desc *gpio; |
| 195 | 240 | const char *err_msg; |
| 196 | 241 | const char *func; |
| 197 | − u32 polarity; | |
| 242 | + unsigned long gpio_flags; | |
| 198 | 243 | int ret; |
| 199 | 244 | |
| 200 | 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 | 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 | 267 | pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value); |
| 223 | 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 | 273 | active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value); |
| 229 | 274 | if (!active_value) |
| 230 | − polarity ^= GPIO_ACTIVE_LOW; | |
| 275 | + gpio_flags ^= GPIO_ACTIVE_LOW; | |
| 231 | 276 | |
| 232 | 277 | dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", func, |
| 233 | 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 | 281 | switch (type) { |
| 237 | 282 | case INT3472_GPIO_TYPE_RESET: |
| 238 | 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 | 285 | if (ret) |
| 241 | 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 | 289 | case INT3472_GPIO_TYPE_CLK_ENABLE: |
| 245 | 290 | case INT3472_GPIO_TYPE_PRIVACY_LED: |
| 246 | 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 | 293 | if (IS_ERR(gpio)) { |
| 249 | 294 | ret = PTR_ERR(gpio); |
| 250 | 295 | err_msg = "Failed to get GPIO\n"; |
| @@ -626,8 +626,8 @@ static u32 convert_ltr_scale(u32 val) · 625 unmodified lines | ||
| 626 | 626 | static int pmc_core_ltr_show(struct seq_file *s, void *unused) |
| 627 | 627 | { |
| 628 | 628 | struct pmc_dev *pmcdev = s->private; |
| 629 | − u64 decoded_snoop_ltr, decoded_non_snoop_ltr; | |
| 630 | − u32 ltr_raw_data, scale, val; | |
| 629 | + u64 decoded_snoop_ltr, decoded_non_snoop_ltr, val; | |
| 630 | + u32 ltr_raw_data, scale; | |
| 631 | 631 | u16 snoop_ltr, nonsnoop_ltr; |
| 632 | 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 | 7886 | #define FAN_NS_CTRL_STATUS BIT(2) /* Bit which determines control is enabled or not */ |
| 7887 | 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 | 7890 | enum { /* Fan control constants */ |
| 7890 | 7891 | fan_status_offset = 0x2f, /* EC register 0x2f */ |
| @@ -7940,6 +7941,7 @@ static int fan_watchdog_maxinterval; · 49 unmodified lines | ||
| 7940 | 7941 | |
| 7941 | 7942 | static bool fan_with_ns_addr; |
| 7942 | 7943 | static bool ecfw_with_fan_dec_rpm; |
| 7944 | +static bool fan_speed_in_tpr; | |
| 7943 | 7945 | |
| 7944 | 7946 | static struct mutex fan_mutex; |
| 7945 | 7947 | |
| @@ -8142,8 +8144,11 @@ static int fan_get_speed(unsigned int *speed) · 196 unmodified lines | ||
| 8142 | 8144 | !acpi_ec_read(fan_rpm_offset + 1, &hi))) |
| 8143 | 8145 | return -EIO; |
| 8144 | 8146 | |
| 8145 | − if (likely(speed)) | |
| 8147 | + if (likely(speed)) { | |
| 8146 | 8148 | *speed = (hi << 8) | lo; |
| 8149 | + if (fan_speed_in_tpr && *speed != 0) | |
| 8150 | + *speed = FAN_CLOCK_TPM / *speed; | |
| 8151 | + } | |
| 8147 | 8152 | break; |
| 8148 | 8153 | case TPACPI_FAN_RD_TPEC_NS: |
| 8149 | 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 | 8181 | if (rc) |
| 8177 | 8182 | return -EIO; |
| 8178 | 8183 | |
| 8179 | − if (likely(speed)) | |
| 8184 | + if (likely(speed)) { | |
| 8180 | 8185 | *speed = (hi << 8) | lo; |
| 8186 | + if (fan_speed_in_tpr && *speed != 0) | |
| 8187 | + *speed = FAN_CLOCK_TPM / *speed; | |
| 8188 | + } | |
| 8181 | 8189 | break; |
| 8182 | 8190 | |
| 8183 | 8191 | case TPACPI_FAN_RD_TPEC_NS: |
| @@ -8788,6 +8796,7 @@ static const struct attribute_group fan_driver_attr_group = { · 604 unmodified lines | ||
| 8788 | 8796 | #define TPACPI_FAN_NOFAN 0x0008 /* no fan available */ |
| 8789 | 8797 | #define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */ |
| 8790 | 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 | 8801 | static const struct tpacpi_quirk fan_quirk_table[] __initconst = { |
| 8793 | 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 | 8826 | TPACPI_Q_LNV3('R', '0', 'V', TPACPI_FAN_NS), /* 11e Gen5 KL-Y */ |
| 8818 | 8827 | TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */ |
| 8819 | 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 | 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 | 8898 | if (quirks & TPACPI_FAN_Q1) |
| 8889 | 8899 | fan_quirk1_setup(); |
| 8900 | + if (quirks & TPACPI_FAN_TPR) | |
| 8901 | + fan_speed_in_tpr = true; | |
| 8890 | 8902 | /* Try and probe the 2nd fan */ |
| 8891 | 8903 | tp_features.second_fan = 1; /* needed for get_speed to work */ |
| 8892 | 8904 | res = fan2_get_speed(&speed); |
| @@ -10319,6 +10331,10 @@ static struct ibm_struct proxsensor_driver_data = { · 1426 unmodified lines | ||
| 10319 | 10331 | #define DYTC_MODE_PSC_BALANCE 5 /* Default mode aka balanced */ |
| 10320 | 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 | 10338 | #define DYTC_ERR_MASK 0xF /* Bits 0-3 in cmd result are the error result */ |
| 10323 | 10339 | #define DYTC_ERR_SUCCESS 1 /* CMD completed successful */ |
| 10324 | 10340 | |
| @@ -10339,6 +10355,10 @@ static int dytc_capabilities; · 14 unmodified lines | ||
| 10339 | 10355 | static bool dytc_mmc_get_available; |
| 10340 | 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 | 10362 | static int convert_dytc_to_profile(int funcmode, int dytcmode, |
| 10343 | 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 | 10381 | return 0; |
| 10362 | 10382 | case DYTC_FUNCTION_PSC: |
| 10363 | − switch (dytcmode) { | |
| 10364 | − case DYTC_MODE_PSC_LOWPOWER: | |
| 10383 | + if (dytcmode == platform_psc_profile_lowpower) | |
| 10365 | 10384 | *profile = PLATFORM_PROFILE_LOW_POWER; |
| 10366 | − break; | |
| 10367 | − case DYTC_MODE_PSC_BALANCE: | |
| 10385 | + else if (dytcmode == platform_psc_profile_balanced) | |
| 10368 | 10386 | *profile = PLATFORM_PROFILE_BALANCED; |
| 10369 | − break; | |
| 10370 | − case DYTC_MODE_PSC_PERFORM: | |
| 10387 | + else if (dytcmode == platform_psc_profile_performance) | |
| 10371 | 10388 | *profile = PLATFORM_PROFILE_PERFORMANCE; |
| 10372 | − break; | |
| 10373 | − default: /* Unknown mode */ | |
| 10389 | + else | |
| 10374 | 10390 | return -EINVAL; |
| 10375 | − } | |
| 10391 | + | |
| 10376 | 10392 | return 0; |
| 10377 | 10393 | case DYTC_FUNCTION_AMT: |
| 10378 | 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 | 10409 | if (dytc_capabilities & BIT(DYTC_FC_MMC)) |
| 10394 | 10410 | *perfmode = DYTC_MODE_MMC_LOWPOWER; |
| 10395 | 10411 | else if (dytc_capabilities & BIT(DYTC_FC_PSC)) |
| 10396 | − *perfmode = DYTC_MODE_PSC_LOWPOWER; | |
| 10412 | + *perfmode = platform_psc_profile_lowpower; | |
| 10397 | 10413 | break; |
| 10398 | 10414 | case PLATFORM_PROFILE_BALANCED: |
| 10399 | 10415 | if (dytc_capabilities & BIT(DYTC_FC_MMC)) |
| 10400 | 10416 | *perfmode = DYTC_MODE_MMC_BALANCE; |
| 10401 | 10417 | else if (dytc_capabilities & BIT(DYTC_FC_PSC)) |
| 10402 | − *perfmode = DYTC_MODE_PSC_BALANCE; | |
| 10418 | + *perfmode = platform_psc_profile_balanced; | |
| 10403 | 10419 | break; |
| 10404 | 10420 | case PLATFORM_PROFILE_PERFORMANCE: |
| 10405 | 10421 | if (dytc_capabilities & BIT(DYTC_FC_MMC)) |
| 10406 | 10422 | *perfmode = DYTC_MODE_MMC_PERFORM; |
| 10407 | 10423 | else if (dytc_capabilities & BIT(DYTC_FC_PSC)) |
| 10408 | − *perfmode = DYTC_MODE_PSC_PERFORM; | |
| 10424 | + *perfmode = platform_psc_profile_performance; | |
| 10409 | 10425 | break; |
| 10410 | 10426 | default: /* Unknown profile */ |
| 10411 | 10427 | return -EOPNOTSUPP; |
| @@ -10599,6 +10615,7 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) · 187 unmodified lines | ||
| 10599 | 10615 | if (output & BIT(DYTC_QUERY_ENABLE_BIT)) |
| 10600 | 10616 | dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF; |
| 10601 | 10617 | |
| 10618 | + dbg_printk(TPACPI_DBG_INIT, "DYTC version %d\n", dytc_version); | |
| 10602 | 10619 | /* Check DYTC is enabled and supports mode setting */ |
| 10603 | 10620 | if (dytc_version < 5) |
| 10604 | 10621 | return -ENODEV; |
| @@ -10637,6 +10654,11 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) · 32 unmodified lines | ||
| 10637 | 10654 | } |
| 10638 | 10655 | } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { /* PSC MODE */ |
| 10639 | 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 | 10662 | } else { |
| 10641 | 10663 | dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n"); |
| 10642 | 10664 | return -ENODEV; |
| @@ -10646,8 +10668,8 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) · 3 unmodified lines | ||
| 10646 | 10668 | "DYTC version %d: thermal mode available\n", dytc_version); |
| 10647 | 10669 | |
| 10648 | 10670 | /* Create platform_profile structure and register */ |
| 10649 | − tpacpi_pprof = devm_platform_profile_register(&tpacpi_pdev->dev, "thinkpad-acpi", | |
| 10650 | − NULL, &dytc_profile_ops); | |
| 10671 | + tpacpi_pprof = platform_profile_register(&tpacpi_pdev->dev, "thinkpad-acpi-profile", | |
| 10672 | + NULL, &dytc_profile_ops); | |
| 10651 | 10673 | /* |
| 10652 | 10674 | * If for some reason platform_profiles aren't enabled |
| 10653 | 10675 | * don't quit terminally. |
| @@ -10665,8 +10687,15 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) · 11 unmodified lines | ||
| 10665 | 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 | 10696 | static struct ibm_struct dytc_profile_driver_data = { |
| 10669 | 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 | 627 | dev_set_name(&control_type->dev, "%s", name); |
| 628 | 628 | result = device_register(&control_type->dev); |
| 629 | 629 | if (result) { |
| 630 | − if (control_type->allocated) | |
| 631 | − kfree(control_type); | |
| 630 | + put_device(&control_type->dev); | |
| 632 | 631 | return ERR_PTR(result); |
| 633 | 632 | } |
| 634 | 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 | 416 | static const struct file_operations vmclock_miscdev_fops = { |
| 417 | + .owner = THIS_MODULE, | |
| 417 | 418 | .mmap = vmclock_miscdev_mmap, |
| 418 | 419 | .read = vmclock_miscdev_read, |
| 419 | 420 | }; |
| 420 | 421 | |
| 421 | 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 = dev_get_drvdata(dev); | |
| 426 | + struct vmclock_state *st = data; | |
| 427 | 427 | |
| 428 | 428 | if (st->ptp_clock) |
| 429 | 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 | 507 | if (ret) { |
| 508 | 508 | dev_info(dev, "Failed to obtain physical address: %d\n", ret); |
| 509 | − goto out; | |
| 509 | + return ret; | |
| 510 | 510 | } |
| 511 | 511 | |
| 512 | 512 | if (resource_size(&st->res) < VMCLOCK_MIN_SIZE) { |
| 513 | 513 | dev_info(dev, "Region too small (0x%llx)\n", |
| 514 | 514 | resource_size(&st->res)); |
| 515 | − ret = -EINVAL; | |
| 516 | − goto out; | |
| 515 | + return -EINVAL; | |
| 517 | 516 | } |
| 518 | 517 | st->clk = devm_memremap(dev, st->res.start, resource_size(&st->res), |
| 519 | 518 | MEMREMAP_WB | MEMREMAP_DEC); |
| @@ -521,31 +520,34 @@ static int vmclock_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 521 | 520 | ret = PTR_ERR(st->clk); |
| 522 | 521 | dev_info(dev, "failed to map shared memory\n"); |
| 523 | 522 | st->clk = NULL; |
| 524 | − goto out; | |
| 523 | + return ret; | |
| 525 | 524 | } |
| 526 | 525 | |
| 527 | 526 | if (le32_to_cpu(st->clk->magic) != VMCLOCK_MAGIC || |
| 528 | 527 | le32_to_cpu(st->clk->size) > resource_size(&st->res) || |
| 529 | 528 | le16_to_cpu(st->clk->version) != 1) { |
| 530 | 529 | dev_info(dev, "vmclock magic fields invalid\n"); |
| 531 | − ret = -EINVAL; | |
| 532 | − goto out; | |
| 530 | + return -EINVAL; | |
| 533 | 531 | } |
| 534 | 532 | |
| 535 | 533 | ret = ida_alloc(&vmclock_ida, GFP_KERNEL); |
| 536 | 534 | if (ret < 0) |
| 537 | − goto out; | |
| 535 | + return ret; | |
| 538 | 536 | |
| 539 | 537 | st->index = ret; |
| 540 | 538 | ret = devm_add_action_or_reset(&pdev->dev, vmclock_put_idx, st); |
| 541 | 539 | if (ret) |
| 542 | − goto out; | |
| 540 | + return ret; | |
| 543 | 541 | |
| 544 | 542 | st->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "vmclock%d", st->index); |
| 545 | − if (!st->name) { | |
| 546 | − ret = -ENOMEM; | |
| 547 | − goto out; | |
| 548 | − } | |
| 543 | + if (!st->name) | |
| 544 | + return -ENOMEM; | |
| 545 | + | |
| 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 | 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 | 556 | * cross that bridge if/when we come to it. |
| 555 | 557 | */ |
| 556 | 558 | if (le32_to_cpu(st->clk->size) >= PAGE_SIZE) { |
| 557 | − st->miscdev.minor = MISC_DYNAMIC_MINOR; | |
| 558 | 559 | st->miscdev.fops = &vmclock_miscdev_fops; |
| 559 | 560 | st->miscdev.name = st->name; |
| 560 | 561 | |
| 561 | 562 | ret = misc_register(&st->miscdev); |
| 562 | 563 | if (ret) |
| 563 | − goto out; | |
| 564 | + return ret; | |
| 564 | 565 | } |
| 565 | 566 | |
| 566 | 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 | 571 | if (IS_ERR(st->ptp_clock)) { |
| 571 | 572 | ret = PTR_ERR(st->ptp_clock); |
| 572 | 573 | st->ptp_clock = NULL; |
| 573 | − vmclock_remove(pdev); | |
| 574 | − goto out; | |
| 574 | + return ret; | |
| 575 | 575 | } |
| 576 | 576 | } |
| 577 | 577 | |
| 578 | 578 | if (!st->miscdev.minor && !st->ptp_clock) { |
| 579 | 579 | /* Neither miscdev nor PTP registered */ |
| 580 | 580 | dev_info(dev, "vmclock: Neither miscdev nor PTP available; not registering\n"); |
| 581 | − ret = -ENODEV; | |
| 582 | − goto out; | |
| 581 | + return -ENODEV; | |
| 583 | 582 | } |
| 584 | 583 | |
| 585 | 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 | 586 | (st->miscdev.minor && st->ptp_clock) ? ", " : "", |
| 588 | 587 | st->ptp_clock ? "PTP" : ""); |
| 589 | 588 | |
| 590 | − dev_set_drvdata(dev, st); | |
| 591 | − | |
| 592 | − out: | |
| 593 | − return ret; | |
| 589 | + return 0; | |
| 594 | 590 | } |
| 595 | 591 | |
| 596 | 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 | 598 | static struct platform_driver vmclock_platform_driver = { |
| 603 | 599 | .probe = vmclock_probe, |
| 604 | − .remove = vmclock_remove, | |
| 605 | 600 | .driver = { |
| 606 | 601 | .name = "vmclock", |
| 607 | 602 | .acpi_match_table = vmclock_acpi_ids, |
| @@ -5774,43 +5774,36 @@ regulator_register(struct device *dev, · 5773 unmodified lines | ||
| 5774 | 5774 | goto clean; |
| 5775 | 5775 | } |
| 5776 | 5776 | |
| 5777 | − if (config->init_data) { | |
| 5778 | − /* | |
| 5779 | − * Providing of_match means the framework is expected to parse | |
| 5780 | − * DT to get the init_data. This would conflict with provided | |
| 5781 | − * init_data, if set. Warn if it happens. | |
| 5782 | − */ | |
| 5783 | − if (regulator_desc->of_match) | |
| 5784 | − dev_warn(dev, "Using provided init data - OF match ignored\n"); | |
| 5777 | + /* | |
| 5778 | + * DT may override the config->init_data provided if the platform | |
| 5779 | + * needs to do so. If so, config->init_data is completely ignored. | |
| 5780 | + */ | |
| 5781 | + init_data = regulator_of_get_init_data(dev, regulator_desc, config, | |
| 5782 | + &rdev->dev.of_node); | |
| 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 | 5805 | init_data = config->init_data; |
| 5787 | 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 | 5809 | ww_mutex_init(&rdev->mutex, ®ulator_ww_class); |
| @@ -695,7 +695,8 @@ static int info_update(void) · 694 unmodified lines | ||
| 695 | 695 | if (time_after(jiffies, chp_info_expires)) { |
| 696 | 696 | /* Data is too old, update. */ |
| 697 | 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 | 701 | mutex_unlock(&info_lock); |
| 701 | 702 | |
| @@ -588,6 +588,15 @@ out: · 587 unmodified lines | ||
| 588 | 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 | 600 | static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 592 | 601 | { |
| 593 | 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 | 610 | dev_set_drvdata(&pdev->dev, ism); |
| 602 | 611 | ism->pdev = pdev; |
| 603 | 612 | ism->dev.parent = &pdev->dev; |
| 613 | + ism->dev.release = ism_dev_release; | |
| 604 | 614 | device_initialize(&ism->dev); |
| 605 | 615 | dev_set_name(&ism->dev, dev_name(&pdev->dev)); |
| 606 | 616 | ret = device_add(&ism->dev); |
| @@ -637,7 +647,7 @@ err: · 30 unmodified lines | ||
| 637 | 647 | device_del(&ism->dev); |
| 638 | 648 | err_dev: |
| 639 | 649 | dev_set_drvdata(&pdev->dev, NULL); |
| 640 | − kfree(ism); | |
| 650 | + put_device(&ism->dev); | |
| 641 | 651 | |
| 642 | 652 | return ret; |
| 643 | 653 | } |
| @@ -682,7 +692,7 @@ static void ism_remove(struct pci_dev *pdev) · 38 unmodified lines | ||
| 682 | 692 | pci_disable_device(pdev); |
| 683 | 693 | device_del(&ism->dev); |
| 684 | 694 | dev_set_drvdata(&pdev->dev, NULL); |
| 685 | − kfree(ism); | |
| 695 | + put_device(&ism->dev); | |
| 686 | 696 | } |
| 687 | 697 | |
| 688 | 698 | static struct pci_driver ism_driver = { |
| @@ -7050,14 +7050,16 @@ int qeth_open(struct net_device *dev) · 7049 unmodified lines | ||
| 7050 | 7050 | card->data.state = CH_STATE_UP; |
| 7051 | 7051 | netif_tx_start_all_queues(dev); |
| 7052 | 7052 | |
| 7053 | − local_bh_disable(); | |
| 7054 | 7053 | qeth_for_each_output_queue(card, queue, i) { |
| 7055 | 7054 | netif_napi_add_tx(dev, &queue->napi, qeth_tx_poll); |
| 7056 | 7055 | napi_enable(&queue->napi); |
| 7057 | − napi_schedule(&queue->napi); | |
| 7058 | 7056 | } |
| 7059 | − | |
| 7060 | 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 | 7063 | napi_schedule(&card->napi); |
| 7062 | 7064 | /* kick-start the NAPI softirq: */ |
| 7063 | 7065 | local_bh_enable(); |
| @@ -2867,7 +2867,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) · 2866 unmodified lines | ||
| 2867 | 2867 | dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", |
| 2868 | 2868 | cpu_to_le32(upper_32_bits(dma_handle)), |
| 2869 | 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 | 2871 | remseg--; |
| 2872 | 2872 | } |
| 2873 | 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 | 872 | case 0x1a: /* start stop unit in progress */ |
| 873 | 873 | case 0x1b: /* sanitize in progress */ |
| 874 | 874 | case 0x1d: /* configuration in progress */ |
| 875 | − case 0x24: /* depopulation in progress */ | |
| 876 | − case 0x25: /* depopulation restore in progress */ | |
| 877 | 875 | action = ACTION_DELAYED_RETRY; |
| 878 | 876 | break; |
| 879 | 877 | case 0x0a: /* ALUA state transition */ |
| 880 | 878 | action = ACTION_DELAYED_REPREP; |
| 881 | 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 | 887 | default: |
| 883 | 888 | action = ACTION_FAIL; |
| 884 | 889 | break; |
| @@ -67,6 +67,13 @@ static void scsi_lib_test_multiple_sense(struct kunit *test) · 66 unmodified lines | ||
| 67 | 67 | }; |
| 68 | 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 | 77 | /* Match end of array */ |
| 71 | 78 | scsi_build_sense(&sc, 0, ILLEGAL_REQUEST, 0x91, 0x36); |
| 72 | 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 | 247 | ret = sbitmap_init_node(&sdev->budget_map, |
| 248 | 248 | scsi_device_max_queue_depth(sdev), |
| 249 | − new_shift, GFP_KERNEL, | |
| 249 | + new_shift, GFP_NOIO, | |
| 250 | 250 | sdev->request_queue->node, false, true); |
| 251 | 251 | if (!ret) |
| 252 | 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 | 1801 | length = scsi_bufflen(scmnd); |
| 1802 | 1802 | payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb; |
| 1803 | + payload->range.len = 0; | |
| 1803 | 1804 | payload_sz = 0; |
| 1804 | 1805 | |
| 1805 | 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 | 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 | 371 | static struct irq_chip smp2p_irq_chip = { |
| @@ -235,8 +235,8 @@ · 234 unmodified lines | ||
| 235 | 235 | /** |
| 236 | 236 | * struct atmel_qspi_pcal - Pad Calibration Clock Division |
| 237 | 237 | * @pclk_rate: peripheral clock rate. |
| 238 | − * @pclkdiv: calibration clock division. The clock applied to the calibration | |
| 239 | − * cell is divided by pclkdiv + 1. | |
| 238 | + * @pclk_div: calibration clock division. The clock applied to the calibration | |
| 239 | + * cell is divided by pclk_div + 1. | |
| 240 | 240 | */ |
| 241 | 241 | struct atmel_qspi_pcal { |
| 242 | 242 | u32 pclk_rate; |
| @@ -399,7 +399,7 @@ static void lpss_ssp_cs_control(struct spi_device *spi, bool enable) · 398 unmodified lines | ||
| 399 | 399 | lpss_ssp_select_cs(spi, config); |
| 400 | 400 | |
| 401 | 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 | 403 | if (config->cs_clk_stays_gated) { |
| 404 | 404 | /* |
| 405 | 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 | 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 | 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 | 117 | char *page) |
| 118 | 118 | { |
| 119 | 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 | 121 | else |
| 122 | − return snprintf(page, PAGE_SIZE, "deactivated"); | |
| 122 | + return snprintf(page, PAGE_SIZE, "deactivated\n"); | |
| 123 | 123 | } |
| 124 | 124 | |
| 125 | 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 | 57 | * @max_level: maximum cooling level. One less than total number of valid |
| 58 | 58 | * cpufreq frequencies. |
| 59 | 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 | 60 | * @policy: cpufreq policy. |
| 63 | 61 | * @cooling_ops: cpufreq callbacks to thermal cooling device ops |
| 64 | 62 | * @idle_time: idle time stats |
| @@ -798,7 +798,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) · 797 unmodified lines | ||
| 798 | 798 | nonseekable_open(inode, filp); |
| 799 | 799 | |
| 800 | 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 | 803 | retval = tty_alloc_file(filp); |
| 804 | 804 | if (retval) |
| @@ -374,6 +374,7 @@ static inline int is_omap1510_8250(struct uart_8250_port *pt) · 373 unmodified lines | ||
| 374 | 374 | |
| 375 | 375 | #ifdef CONFIG_SERIAL_8250_DMA |
| 376 | 376 | extern int serial8250_tx_dma(struct uart_8250_port *); |
| 377 | +extern void serial8250_tx_dma_flush(struct uart_8250_port *); | |
| 377 | 378 | extern int serial8250_rx_dma(struct uart_8250_port *); |
| 378 | 379 | extern void serial8250_rx_dma_flush(struct uart_8250_port *); |
| 379 | 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 | 408 | return -1; |
| 408 | 409 | } |
| 410 | +static inline void serial8250_tx_dma_flush(struct uart_8250_port *p) { } | |
| 409 | 411 | static inline int serial8250_rx_dma(struct uart_8250_port *p) |
| 410 | 412 | { |
| 411 | 413 | return -1; |
| @@ -149,6 +149,22 @@ err: · 148 unmodified lines | ||
| 149 | 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 | 168 | int serial8250_rx_dma(struct uart_8250_port *p) |
| 153 | 169 | { |
| 154 | 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 | 110 | spin_lock_init(&port->lock); |
| 111 | 111 | |
| 112 | 112 | if (resource_type(&resource) == IORESOURCE_IO) { |
| 113 | − port->iotype = UPIO_PORT; | |
| 114 | 113 | port->iobase = resource.start; |
| 115 | 114 | } else { |
| 116 | 115 | port->mapbase = resource.start; |
| @@ -112,7 +112,6 @@ static int serial8250_probe_acpi(struct platform_device *pdev) · 111 unmodified lines | ||
| 112 | 112 | struct device *dev = &pdev->dev; |
| 113 | 113 | struct uart_8250_port uart = { }; |
| 114 | 114 | struct resource *regs; |
| 115 | − unsigned char iotype; | |
| 116 | 115 | int ret, line; |
| 117 | 116 | |
| 118 | 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 | 121 | switch (resource_type(regs)) { |
| 123 | 122 | case IORESOURCE_IO: |
| 124 | 123 | uart.port.iobase = regs->start; |
| 125 | − iotype = UPIO_PORT; | |
| 126 | 124 | break; |
| 127 | 125 | case IORESOURCE_MEM: |
| 128 | 126 | uart.port.mapbase = regs->start; |
| 129 | 127 | uart.port.mapsize = resource_size(regs); |
| 130 | 128 | uart.port.flags = UPF_IOREMAP; |
| 131 | − iotype = UPIO_MEM; | |
| 132 | 129 | break; |
| 133 | 130 | default: |
| 134 | 131 | return -EINVAL; |
| @@ -147,12 +144,6 @@ static int serial8250_probe_acpi(struct platform_device *pdev) · 12 unmodified lines | ||
| 147 | 144 | if (ret) |
| 148 | 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 | 147 | line = serial8250_register_8250_port(&uart); |
| 157 | 148 | if (line < 0) |
| 158 | 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 | 437 | struct uart_8250_port uart, *port; |
| 438 | 438 | int ret, flags = dev_id->driver_data; |
| 439 | − unsigned char iotype; | |
| 440 | 439 | long line; |
| 441 | 440 | |
| 442 | 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 | 447 | memset(&uart, 0, sizeof(uart)); |
| 449 | 448 | if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) { |
| 450 | 449 | uart.port.iobase = pnp_port_start(dev, 2); |
| 451 | − iotype = UPIO_PORT; | |
| 452 | 450 | } else if (pnp_port_valid(dev, 0)) { |
| 453 | 451 | uart.port.iobase = pnp_port_start(dev, 0); |
| 454 | − iotype = UPIO_PORT; | |
| 455 | 452 | } else if (pnp_mem_valid(dev, 0)) { |
| 456 | 453 | uart.port.mapbase = pnp_mem_start(dev, 0); |
| 457 | 454 | uart.port.mapsize = pnp_mem_len(dev, 0); |
| 458 | − iotype = UPIO_MEM; | |
| 459 | 455 | uart.port.flags = UPF_IOREMAP; |
| 460 | 456 | } else |
| 461 | 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 | 467 | if (ret) |
| 472 | 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 | 470 | if (flags & CIR_PORT) { |
| 481 | 471 | uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; |
| 482 | 472 | uart.port.type = PORT_8250_CIR; |
| @@ -2555,6 +2555,14 @@ static void serial8250_shutdown(struct uart_port *port) · 2554 unmodified lines | ||
| 2555 | 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 | 2566 | static unsigned int serial8250_do_get_divisor(struct uart_port *port, |
| 2559 | 2567 | unsigned int baud, |
| 2560 | 2568 | unsigned int *frac) |
| @@ -3244,6 +3252,7 @@ static const struct uart_ops serial8250_pops = { · 683 unmodified lines | ||
| 3244 | 3252 | .break_ctl = serial8250_break_ctl, |
| 3245 | 3253 | .startup = serial8250_startup, |
| 3246 | 3254 | .shutdown = serial8250_shutdown, |
| 3255 | + .flush_buffer = serial8250_flush_buffer, | |
| 3247 | 3256 | .set_termios = serial8250_set_termios, |
| 3248 | 3257 | .set_ldisc = serial8250_set_ldisc, |
| 3249 | 3258 | .pm = serial8250_pm, |
| @@ -1561,7 +1561,7 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype, · 1560 unmodified lines | ||
| 1561 | 1561 | /* Always ask for fixed clock rate from a property. */ |
| 1562 | 1562 | device_property_read_u32(dev, "clock-frequency", &uartclk); |
| 1563 | 1563 | |
| 1564 | − s->polling = !!irq; | |
| 1564 | + s->polling = (irq <= 0); | |
| 1565 | 1565 | if (s->polling) |
| 1566 | 1566 | dev_dbg(dev, |
| 1567 | 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 | 173 | * The caller is responsible to initialize the following fields of the @port |
| 174 | 174 | * ->dev (must be valid) |
| 175 | 175 | * ->flags |
| 176 | + * ->iobase | |
| 176 | 177 | * ->mapbase |
| 177 | 178 | * ->mapsize |
| 178 | 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 | 215 | /* Read the registers I/O access type (default: MMIO 8-bit) */ |
| 215 | 216 | ret = device_property_read_u32(dev, "reg-io-width", &value); |
| 216 | 217 | if (ret) { |
| 217 | − port->iotype = UPIO_MEM; | |
| 218 | + port->iotype = port->iobase ? UPIO_PORT : UPIO_MEM; | |
| 218 | 219 | } else { |
| 219 | 220 | switch (value) { |
| 220 | 221 | case 1: |
| @@ -227,15 +228,16 @@ static int __uart_read_properties(struct uart_port *port, bool use_defaults) · 6 unmodified lines | ||
| 227 | 228 | port->iotype = device_is_big_endian(dev) ? UPIO_MEM32BE : UPIO_MEM32; |
| 228 | 229 | break; |
| 229 | 230 | default: |
| 230 | − if (!use_defaults) { | |
| 231 | − dev_err(dev, "Unsupported reg-io-width (%u)\n", value); | |
| 232 | − return -EINVAL; | |
| 233 | − } | |
| 234 | 231 | port->iotype = UPIO_UNKNOWN; |
| 235 | 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 | 241 | /* Read the address mapping base offset (default: no offset) */ |
| 240 | 242 | ret = device_property_read_u32(dev, "reg-offset", &value); |
| 241 | 243 | if (ret) |
| @@ -2120,8 +2120,6 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba) · 2119 unmodified lines | ||
| 2120 | 2120 | INIT_DELAYED_WORK(&hba->clk_gating.gate_work, ufshcd_gate_work); |
| 2121 | 2121 | INIT_WORK(&hba->clk_gating.ungate_work, ufshcd_ungate_work); |
| 2122 | 2122 | |
| 2123 | − spin_lock_init(&hba->clk_gating.lock); | |
| 2124 | − | |
| 2125 | 2123 | hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue( |
| 2126 | 2124 | "ufs_clk_gating_%d", WQ_MEM_RECLAIM | WQ_HIGHPRI, |
| 2127 | 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 | 3104 | case UPIU_TRANSACTION_QUERY_RSP: { |
| 3107 | 3105 | u8 response = lrbp->ucd_rsp_ptr->header.response; |
| 3108 | 3106 | |
| 3109 | − if (response == 0) | |
| 3107 | + if (response == 0) { | |
| 3110 | 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 | 3114 | break; |
| 3112 | 3115 | } |
| 3113 | 3116 | case UPIU_TRANSACTION_REJECT_UPIU: |
| @@ -5976,24 +5979,6 @@ out: · 2862 unmodified lines | ||
| 5976 | 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 | 5982 | static int __ufshcd_wb_toggle(struct ufs_hba *hba, bool set, enum flag_idn idn) |
| 5998 | 5983 | { |
| 5999 | 5984 | u8 index; |
| @@ -6214,7 +6199,7 @@ static void ufshcd_exception_event_handler(struct work_struct *work) · 214 unmodified lines | ||
| 6214 | 6199 | ufshcd_bkops_exception_event_handler(hba); |
| 6215 | 6200 | |
| 6216 | 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 | 6204 | ufs_debugfs_exception_event(hba, status); |
| 6220 | 6205 | } |
| @@ -9160,7 +9145,7 @@ out: · 2939 unmodified lines | ||
| 9160 | 9145 | if (!IS_ERR_OR_NULL(clki->clk) && clki->enabled) |
| 9161 | 9146 | clk_disable_unprepare(clki->clk); |
| 9162 | 9147 | } |
| 9163 | − } else if (!ret && on) { | |
| 9148 | + } else if (!ret && on && hba->clk_gating.is_initialized) { | |
| 9164 | 9149 | scoped_guard(spinlock_irqsave, &hba->clk_gating.lock) |
| 9165 | 9150 | hba->clk_gating.state = CLKS_ON; |
| 9166 | 9151 | trace_ufshcd_clk_gating(dev_name(hba->dev), |
| @@ -10246,16 +10231,6 @@ int ufshcd_system_thaw(struct device *dev) · 1079 unmodified lines | ||
| 10246 | 10231 | EXPORT_SYMBOL_GPL(ufshcd_system_thaw); |
| 10247 | 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 | 10235 | * ufshcd_set_dma_mask - Set dma mask based on the controller |
| 10261 | 10236 | * addressing capability |
| @@ -10274,12 +10249,26 @@ static int ufshcd_set_dma_mask(struct ufs_hba *hba) · 12 unmodified lines | ||
| 10274 | 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 | 10263 | * ufshcd_alloc_host - allocate Host Bus Adapter (HBA) |
| 10279 | 10264 | * @dev: pointer to device handle |
| 10280 | 10265 | * @hba_handle: driver private handle |
| 10281 | 10266 | * |
| 10282 | 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 | 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 | 10290 | err = -ENOMEM; |
| 10302 | 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 | 10300 | host->nr_maps = HCTX_TYPE_POLL + 1; |
| 10305 | 10301 | hba = shost_priv(host); |
| 10306 | 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 | 10425 | hba->irq = irq; |
| 10430 | 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 | 10434 | err = ufshcd_hba_init(hba); |
| 10433 | 10435 | if (err) |
| 10434 | 10436 | goto out_error; |
| @@ -562,7 +562,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev) · 561 unmodified lines | ||
| 562 | 562 | pm_runtime_forbid(&pdev->dev); |
| 563 | 563 | pm_runtime_get_noresume(&pdev->dev); |
| 564 | 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 | 604 | err = ufshcd_init(hba, mmio_base, pdev->irq); |
| 606 | 605 | if (err) { |
| 607 | 606 | dev_err(&pdev->dev, "Initialization failed\n"); |
| 608 | − ufshcd_dealloc_host(hba); | |
| 609 | 607 | return err; |
| 610 | 608 | } |
| 611 | 609 | |
| @@ -465,21 +465,17 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, · 464 unmodified lines | ||
| 465 | 465 | struct device *dev = &pdev->dev; |
| 466 | 466 | |
| 467 | 467 | mmio_base = devm_platform_ioremap_resource(pdev, 0); |
| 468 | − if (IS_ERR(mmio_base)) { | |
| 469 | − err = PTR_ERR(mmio_base); | |
| 470 | − goto out; | |
| 471 | − } | |
| 468 | + if (IS_ERR(mmio_base)) | |
| 469 | + return PTR_ERR(mmio_base); | |
| 472 | 470 | |
| 473 | 471 | irq = platform_get_irq(pdev, 0); |
| 474 | − if (irq < 0) { | |
| 475 | − err = irq; | |
| 476 | − goto out; | |
| 477 | − } | |
| 472 | + if (irq < 0) | |
| 473 | + return irq; | |
| 478 | 474 | |
| 479 | 475 | err = ufshcd_alloc_host(dev, &hba); |
| 480 | 476 | if (err) { |
| 481 | 477 | dev_err(dev, "Allocation failed\n"); |
| 482 | − goto out; | |
| 478 | + return err; | |
| 483 | 479 | } |
| 484 | 480 | |
| 485 | 481 | hba->vops = vops; |
| @@ -488,13 +484,13 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, · 2 unmodified lines | ||
| 488 | 484 | if (err) { |
| 489 | 485 | dev_err(dev, "%s: clock parse failed %d\n", |
| 490 | 486 | __func__, err); |
| 491 | − goto dealloc_host; | |
| 487 | + return err; | |
| 492 | 488 | } |
| 493 | 489 | err = ufshcd_parse_regulator_info(hba); |
| 494 | 490 | if (err) { |
| 495 | 491 | dev_err(dev, "%s: regulator init failed %d\n", |
| 496 | 492 | __func__, err); |
| 497 | − goto dealloc_host; | |
| 493 | + return err; | |
| 498 | 494 | } |
| 499 | 495 | |
| 500 | 496 | ufshcd_init_lanes_per_dir(hba); |
| @@ -502,25 +498,20 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, · 1 unmodified line | ||
| 502 | 498 | err = ufshcd_parse_operating_points(hba); |
| 503 | 499 | if (err) { |
| 504 | 500 | dev_err(dev, "%s: OPP parse failed %d\n", __func__, err); |
| 505 | − goto dealloc_host; | |
| 501 | + return err; | |
| 506 | 502 | } |
| 507 | 503 | |
| 508 | 504 | err = ufshcd_init(hba, mmio_base, irq); |
| 509 | 505 | if (err) { |
| 510 | 506 | dev_err_probe(dev, err, "Initialization failed with error %d\n", |
| 511 | 507 | err); |
| 512 | − goto dealloc_host; | |
| 508 | + return err; | |
| 513 | 509 | } |
| 514 | 510 | |
| 515 | 511 | pm_runtime_set_active(dev); |
| 516 | 512 | pm_runtime_enable(dev); |
| 517 | 513 | |
| 518 | 514 | return 0; |
| 519 | − | |
| 520 | −dealloc_host: | |
| 521 | − ufshcd_dealloc_host(hba); | |
| 522 | −out: | |
| 523 | − return err; | |
| 524 | 515 | } |
| 525 | 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 | 526 | pm_runtime_get_sync(&pdev->dev); |
| 536 | 527 | ufshcd_remove(hba); |
| 537 | − ufshcd_dealloc_host(hba); | |
| 538 | 528 | pm_runtime_disable(&pdev->dev); |
| 539 | 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 | 371 | static void acm_ctrl_irq(struct urb *urb) |
| 372 | 372 | { |
| 373 | 373 | struct acm *acm = urb->context; |
| 374 | − struct usb_cdc_notification *dr = urb->transfer_buffer; | |
| 374 | + struct usb_cdc_notification *dr; | |
| 375 | 375 | unsigned int current_size = urb->actual_length; |
| 376 | 376 | unsigned int expected_size, copy_size, alloc_size; |
| 377 | 377 | int retval; |
| @@ -398,14 +398,25 @@ static void acm_ctrl_irq(struct urb *urb) · 20 unmodified lines | ||
| 398 | 398 | |
| 399 | 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 | 413 | dr = (struct usb_cdc_notification *)acm->notification_buffer; |
| 403 | − | |
| 414 | + } | |
| 404 | 415 | /* size = notification-header + (optional) data */ |
| 405 | 416 | expected_size = sizeof(struct usb_cdc_notification) + |
| 406 | 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 | 420 | /* notification is transmitted fragmented, reassemble */ |
| 410 | 421 | if (acm->nb_size < expected_size) { |
| 411 | 422 | u8 *new_buffer; |
| @@ -1727,13 +1738,16 @@ static const struct usb_device_id acm_ids[] = { · 1315 unmodified lines | ||
| 1727 | 1738 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ |
| 1728 | 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 | 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 | 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 | 1751 | .driver_info = DISABLE_ECHO, /* Don't echo banner */ |
| 1738 | 1752 | }, |
| 1739 | 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 | 1848 | desc = intf->cur_altsetting; |
| 1849 | 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 | 1863 | * Set default autosuspend delay as 0 to speedup bus suspend, |
| 1853 | 1864 | * based on the below considerations: |
| @@ -4698,7 +4709,6 @@ void usb_ep0_reinit(struct usb_device *udev) · 2844 unmodified lines | ||
| 4698 | 4709 | EXPORT_SYMBOL_GPL(usb_ep0_reinit); |
| 4699 | 4710 | |
| 4700 | 4711 | #define usb_sndaddr0pipe() (PIPE_CONTROL << 30) |
| 4701 | −#define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN) | |
| 4702 | 4712 | |
| 4703 | 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 | 4814 | for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) { |
| 4805 | 4815 | /* Start with invalid values in case the transfer fails */ |
| 4806 | 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 | 4818 | USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, |
| 4809 | 4819 | USB_DT_DEVICE << 8, 0, |
| 4810 | 4820 | buf, size, |
| @@ -435,6 +435,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 434 unmodified lines | ||
| 435 | 435 | { USB_DEVICE(0x0c45, 0x7056), .driver_info = |
| 436 | 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 | 441 | /* Action Semiconductor flash disk */ |
| 439 | 442 | { USB_DEVICE(0x10d6, 0x2200), .driver_info = |
| 440 | 443 | USB_QUIRK_STRING_FETCH_255 }, |
| @@ -525,6 +528,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 84 unmodified lines | ||
| 525 | 528 | /* Blackmagic Design UltraStudio SDI */ |
| 526 | 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 | 534 | /* Hauppauge HVR-950q */ |
| 529 | 535 | { USB_DEVICE(0x2040, 0x7200), .driver_info = |
| 530 | 536 | USB_QUIRK_CONFIG_INTF_STRINGS }, |
| @@ -4615,6 +4615,7 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) · 4614 unmodified lines | ||
| 4615 | 4615 | spin_lock_irqsave(&hsotg->lock, flags); |
| 4616 | 4616 | |
| 4617 | 4617 | hsotg->driver = NULL; |
| 4618 | + hsotg->gadget.dev.of_node = NULL; | |
| 4618 | 4619 | hsotg->gadget.speed = USB_SPEED_UNKNOWN; |
| 4619 | 4620 | hsotg->enabled = 0; |
| 4620 | 4621 | |
| @@ -717,6 +717,7 @@ struct dwc3_event_buffer { · 716 unmodified lines | ||
| 717 | 717 | /** |
| 718 | 718 | * struct dwc3_ep - device side endpoint representation |
| 719 | 719 | * @endpoint: usb endpoint |
| 720 | + * @nostream_work: work for handling bulk NoStream | |
| 720 | 721 | * @cancelled_list: list of cancelled requests for this endpoint |
| 721 | 722 | * @pending_list: list of pending requests for this endpoint |
| 722 | 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 | 2630 | u32 reg; |
| 2631 | 2631 | u32 timeout = 2000; |
| 2632 | + u32 saved_config = 0; | |
| 2632 | 2633 | |
| 2633 | 2634 | if (pm_runtime_suspended(dwc->dev)) |
| 2634 | 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 | 2664 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 2637 | 2665 | if (is_on) { |
| 2638 | 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 | 2688 | reg &= DWC3_DSTS_DEVCTRLHLT; |
| 2661 | 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 | 2697 | if (!timeout) |
| 2664 | 2698 | return -ETIMEDOUT; |
| 2665 | 2699 | |
| @@ -283,7 +283,7 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req) · 282 unmodified lines | ||
| 283 | 283 | /* Our transmit completed. See if there's more to go. |
| 284 | 284 | * f_midi_transmit eats req, don't queue it again. */ |
| 285 | 285 | req->length = 0; |
| 286 | − f_midi_transmit(midi); | |
| 286 | + queue_work(system_highpri_wq, &midi->work); | |
| 287 | 287 | return; |
| 288 | 288 | } |
| 289 | 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 | 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 | 919 | /* allocate instance-specific endpoints */ |
| 911 | 920 | midi->in_ep = usb_ep_autoconfig(cdev->gadget, &bulk_in_desc); |
| 912 | 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 | 1011 | /* configure the endpoint descriptors ... */ |
| 1003 | − ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); | |
| 1004 | − ms_out_desc.bNumEmbMIDIJack = midi->in_ports; | |
| 1012 | + ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); | |
| 1013 | + ms_out_desc.bNumEmbMIDIJack = midi->out_ports; | |
| 1005 | 1014 | |
| 1006 | − ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); | |
| 1007 | − ms_in_desc.bNumEmbMIDIJack = midi->out_ports; | |
| 1015 | + ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); | |
| 1016 | + ms_in_desc.bNumEmbMIDIJack = midi->in_ports; | |
| 1008 | 1017 | |
| 1009 | 1018 | /* ... and add them to the list */ |
| 1010 | 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 | 818 | return -EINVAL; |
| 819 | 819 | |
| 820 | 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 | 822 | if (IS_ERR(video->kworker)) { |
| 823 | 823 | uvcg_err(&video->uvc->func, "failed to create UVCG kworker\n"); |
| 824 | 824 | return PTR_ERR(video->kworker); |
| @@ -1543,8 +1543,8 @@ void usb_del_gadget(struct usb_gadget *gadget) · 1542 unmodified lines | ||
| 1543 | 1543 | |
| 1544 | 1544 | kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); |
| 1545 | 1545 | sysfs_remove_link(&udc->dev.kobj, "gadget"); |
| 1546 | − flush_work(&gadget->work); | |
| 1547 | 1546 | device_del(&gadget->dev); |
| 1547 | + flush_work(&gadget->work); | |
| 1548 | 1548 | ida_free(&gadget_id_numbers, gadget->id_number); |
| 1549 | 1549 | cancel_work_sync(&udc->vbus_work); |
| 1550 | 1550 | device_unregister(&udc->dev); |
| @@ -310,7 +310,7 @@ struct renesas_usb3_request { · 309 unmodified lines | ||
| 310 | 310 | struct list_head queue; |
| 311 | 311 | }; |
| 312 | 312 | |
| 313 | −#define USB3_EP_NAME_SIZE 8 | |
| 313 | +#define USB3_EP_NAME_SIZE 16 | |
| 314 | 314 | struct renesas_usb3_ep { |
| 315 | 315 | struct usb_ep ep; |
| 316 | 316 | struct renesas_usb3 *usb3; |
| @@ -958,6 +958,15 @@ static void quirk_usb_disable_ehci(struct pci_dev *pdev) · 957 unmodified lines | ||
| 958 | 958 | * booting from USB disk or using a usb keyboard |
| 959 | 959 | */ |
| 960 | 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 | 970 | offset = (hcc_params >> 8) & 0xff; |
| 962 | 971 | while (offset && --count) { |
| 963 | 972 | pci_read_config_dword(pdev, offset, &cap); |
| @@ -653,8 +653,8 @@ put_runtime_pm: · 652 unmodified lines | ||
| 653 | 653 | } |
| 654 | 654 | EXPORT_SYMBOL_NS_GPL(xhci_pci_common_probe, "xhci"); |
| 655 | 655 | |
| 656 | −static const struct pci_device_id pci_ids_reject[] = { | |
| 657 | − /* handled by xhci-pci-renesas */ | |
| 656 | +/* handled by xhci-pci-renesas if enabled */ | |
| 657 | +static const struct pci_device_id pci_ids_renesas[] = { | |
| 658 | 658 | { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014) }, |
| 659 | 659 | { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015) }, |
| 660 | 660 | { /* end: all zeroes */ } |
| @@ -662,7 +662,8 @@ static const struct pci_device_id pci_ids_reject[] = { · 1 unmodified line | ||
| 662 | 662 | |
| 663 | 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 | 667 | return -ENODEV; |
| 667 | 668 | |
| 668 | 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 | 212 | if (of_property_read_u32(node, "clock-frequency", &clk_rate)) |
| 213 | 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 | 217 | nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset", |
| 218 | 218 | GPIOD_ASIS); |
| @@ -387,8 +387,11 @@ usb_role_switch_register(struct device *parent, · 386 unmodified lines | ||
| 387 | 387 | dev_set_name(&sw->dev, "%s-role-switch", |
| 388 | 388 | desc->name ? desc->name : dev_name(parent)); |
| 389 | 389 | |
| 390 | + sw->registered = true; | |
| 391 | + | |
| 390 | 392 | ret = device_register(&sw->dev); |
| 391 | 393 | if (ret) { |
| 394 | + sw->registered = false; | |
| 392 | 395 | put_device(&sw->dev); |
| 393 | 396 | return ERR_PTR(ret); |
| 394 | 397 | } |
| @@ -399,8 +402,6 @@ usb_role_switch_register(struct device *parent, · 4 unmodified lines | ||
| 399 | 402 | dev_warn(&sw->dev, "failed to add component\n"); |
| 400 | 403 | } |
| 401 | 404 | |
| 402 | − sw->registered = true; | |
| 403 | − | |
| 404 | 405 | /* TODO: Symlinks for the host port and the device controller. */ |
| 405 | 406 | |
| 406 | 407 | return sw; |
| @@ -619,15 +619,6 @@ static void option_instat_callback(struct urb *urb); · 618 unmodified lines | ||
| 619 | 619 | /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */ |
| 620 | 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 | 622 | /* Device flags */ |
| 632 | 623 | |
| 633 | 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 | 1358 | .driver_info = NCTRL(2) | RSVD(3) }, |
| 1368 | 1359 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */ |
| 1369 | 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 | 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 | 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 | 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 | 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 | 1370 | .driver_info = RSVD(0) }, |
| 1380 | 1371 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */ |
| 1381 | 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 | 1394 | .driver_info = RSVD(0) | NCTRL(3) }, |
| 1404 | 1395 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */ |
| 1405 | 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 | 1413 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), |
| 1407 | 1414 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, |
| 1408 | 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 | 2354 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */ |
| 2348 | 2355 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */ |
| 2349 | 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 | 2365 | { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ |
| 2351 | 2366 | { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ |
| 2352 | 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 | 2418 | { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, |
| 2404 | 2419 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, |
| 2405 | 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 | 2421 | { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */ |
| 2413 | 2422 | .driver_info = NCTRL(1) }, |
| 2414 | 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 | 5591 | tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, |
| 5592 | 5592 | port->pps_data.active, 0); |
| 5593 | 5593 | tcpm_set_charge(port, false); |
| 5594 | − tcpm_set_state(port, hard_reset_state(port), | |
| 5595 | − port->timings.ps_src_off_time); | |
| 5594 | + tcpm_set_state(port, ERROR_RECOVERY, port->timings.ps_src_off_time); | |
| 5596 | 5595 | break; |
| 5597 | 5596 | case PR_SWAP_SNK_SRC_SOURCE_ON: |
| 5598 | 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 | 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 | 85 | static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) |
| 78 | 86 | { |
| 79 | 87 | unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p); |
| 80 | 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 | 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 | 92 | for (i = 1; i < nr_pages; i++) |
| 91 | 93 | if (pfn_to_bfn(++xen_pfn) != ++next_bfn) |
| 92 | 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 | 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 | 118 | int rc; |
| 117 | 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 | 159 | *dma_handle = xen_phys_to_dma(dev, phys); |
| 158 | 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 | 163 | if (xen_create_contiguous_region(phys, order, fls64(dma_mask), |
| 161 | 164 | dma_handle) != 0) |
| 162 | 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 | 185 | size = ALIGN(size, XEN_PAGE_SIZE); |
| 183 | 186 | |
| 184 | 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 | 190 | return; |
| 187 | 191 | |
| 188 | 192 | if (TestClearPageXenRemapped(virt_to_page(vaddr))) |
| @@ -61,6 +61,13 @@ config BCACHEFS_DEBUG · 60 unmodified lines | ||
| 61 | 61 | The resulting code will be significantly slower than normal; you |
| 62 | 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 | 71 | config BCACHEFS_TESTS |
| 65 | 72 | bool "bcachefs unit and performance tests" |
| 66 | 73 | depends on BCACHEFS_FS |
| @@ -1803,7 +1803,6 @@ struct discard_buckets_state { · 1802 unmodified lines | ||
| 1803 | 1803 | u64 open; |
| 1804 | 1804 | u64 need_journal_commit; |
| 1805 | 1805 | u64 discarded; |
| 1806 | − u64 need_journal_commit_this_dev; | |
| 1807 | 1806 | }; |
| 1808 | 1807 | |
| 1809 | 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 | 1826 | goto out; |
| 1828 | 1827 | } |
| 1829 | 1828 | |
| 1830 | − if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal, | |
| 1831 | − c->journal.flushed_seq_ondisk, | |
| 1832 | − pos.inode, pos.offset)) { | |
| 1833 | − s->need_journal_commit++; | |
| 1834 | − s->need_journal_commit_this_dev++; | |
| 1829 | + u64 seq_ready = bch2_bucket_journal_seq_ready(&c->buckets_waiting_for_journal, | |
| 1830 | + pos.inode, pos.offset); | |
| 1831 | + if (seq_ready > c->journal.flushed_seq_ondisk) { | |
| 1832 | + if (seq_ready > c->journal.flushing_seq) | |
| 1833 | + s->need_journal_commit++; | |
| 1835 | 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 | 1864 | discard_locked = true; |
| 1866 | 1865 | } |
| 1867 | 1866 | |
| 1868 | − 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; | |
| 1867 | + if (!bkey_eq(*discard_pos_done, iter.pos)) { | |
| 1880 | 1868 | s->discarded++; |
| 1869 | + *discard_pos_done = iter.pos; | |
| 1881 | 1870 | |
| 1882 | − ret = bch2_trans_relock_notrace(trans); | |
| 1883 | − if (ret) | |
| 1884 | − goto out; | |
| 1871 | + if (ca->mi.discard && !c->opts.nochanges) { | |
| 1872 | + /* | |
| 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 | 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 | 1929 | POS(ca->dev_idx, U64_MAX), 0, k, |
| 1930 | 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 | 1935 | trace_discard_buckets(c, s.seen, s.open, s.need_journal_commit, s.discarded, |
| 1933 | 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 | 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 | 2032 | bch2_trans_put(trans); |
| 2030 | 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 | 205 | return false; |
| 206 | 206 | } |
| 207 | 207 | |
| 208 | − if (bch2_bucket_needs_journal_commit(&c->buckets_waiting_for_journal, | |
| 209 | − c->journal.flushed_seq_ondisk, bucket.inode, bucket.offset)) { | |
| 208 | + u64 journal_seq_ready = | |
| 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 | 214 | s->skipped_need_journal_commit++; |
| 211 | 215 | return false; |
| 212 | 216 | } |
| @@ -570,7 +574,7 @@ alloc: · 357 unmodified lines | ||
| 570 | 574 | ? bch2_bucket_alloc_freelist(trans, ca, watermark, &s, cl) |
| 571 | 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 | 578 | bch2_journal_flush_async(&c->journal, NULL); |
| 575 | 579 | |
| 576 | 580 | if (!ob && s.btree_bitmap != BTREE_BITMAP_ANY) { |
| @@ -18,6 +18,7 @@ struct bucket_alloc_state { · 17 unmodified lines | ||
| 18 | 18 | u64 buckets_seen; |
| 19 | 19 | u64 skipped_open; |
| 20 | 20 | u64 skipped_need_journal_commit; |
| 21 | + u64 need_journal_commit; | |
| 21 | 22 | u64 skipped_nocow; |
| 22 | 23 | u64 skipped_nouse; |
| 23 | 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 | 2357 | bch2_btree_iter_verify_entry_exit(iter); |
| 2358 | 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 | 2366 | if (iter->update_path) { |
| 2361 | 2367 | bch2_path_put_nokeep(trans, iter->update_path, |
| 2362 | 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 | 2628 | bch2_btree_iter_verify_entry_exit(iter); |
| 2623 | 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 | 2637 | while (1) { |
| 2626 | 2638 | k = __bch2_btree_iter_peek_prev(iter, search_key); |
| 2627 | 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 | 2761 | bch2_btree_iter_verify_entry_exit(iter); |
| 2750 | 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 | 2770 | /* extents can't span inode numbers: */ |
| 2753 | 2771 | if ((iter->flags & BTREE_ITER_is_extents) && |
| 2754 | 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 | 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 | 3131 | struct btree_transaction_stats *s = btree_trans_stats(trans); |
| 3110 | 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 | 3186 | if (old_bytes) { |
| 3165 | 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 | 3191 | out_change_top: |
| 3169 | 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 | 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 | 3305 | trans_set_locked(trans, false); |
| 3275 | 3306 | |
| 3276 | 3307 | if (trans->restarted) { |
| @@ -355,6 +355,18 @@ static int btree_trans_restart(struct btree_trans *trans, int err) · 354 unmodified lines | ||
| 355 | 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 | 370 | bool bch2_btree_node_upgrade(struct btree_trans *, |
| 359 | 371 | struct btree_path *, unsigned); |
| 360 | 372 | |
| @@ -739,7 +751,7 @@ transaction_restart: \ · 378 unmodified lines | ||
| 739 | 751 | if (!_ret2) \ |
| 740 | 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 | 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 | 748 | rcu_read_unlock(); |
| 749 | 749 | mutex_lock(&bc->table.mutex); |
| 750 | 750 | mutex_unlock(&bc->table.mutex); |
| 751 | − rcu_read_lock(); | |
| 752 | 751 | continue; |
| 753 | 752 | } |
| 754 | 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 | 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 | 1006 | if (!trans->nr_updates && |
| 1003 | 1007 | !trans->journal_entries_u64s) |
| 1004 | 1008 | goto out_reset; |
| @@ -509,6 +509,9 @@ struct btree_trans { · 508 unmodified lines | ||
| 509 | 509 | bool notrace_relock_fail:1; |
| 510 | 510 | enum bch_errcode restarted:16; |
| 511 | 511 | u32 restart_count; |
| 512 | +#ifdef CONFIG_BCACHEFS_INJECT_TRANSACTION_RESTARTS | |
| 513 | + u32 restart_count_this_trans; | |
| 514 | +#endif | |
| 512 | 515 | |
| 513 | 516 | u64 last_begin_time; |
| 514 | 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 | 682 | b = as->old_nodes[i]; |
| 683 | 683 | |
| 684 | + bch2_trans_begin(trans); | |
| 684 | 685 | btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read); |
| 685 | 686 | seq = b->data ? b->data->keys.seq : 0; |
| 686 | 687 | six_unlock_read(&b->c.lock); |
| 688 | + bch2_trans_unlock_long(trans); | |
| 687 | 689 | |
| 688 | 690 | if (seq == as->old_nodes_seq[i]) |
| 689 | 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 | 279 | struct bset_tree *t = bset_tree_last(b); |
| 280 | 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 | 282 | ssize_t remaining_space = |
| 283 | 283 | __bch2_btree_u64s_remaining(b, bne->keys.start); |
| 284 | 284 | |
| 285 | 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 | 287 | return bne; |
| 288 | 288 | } else { |
| 289 | 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 | 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, | |
| 26 | − u64 flushed_seq, | |
| 27 | − unsigned dev, u64 bucket) | |
| 25 | +u64 bch2_bucket_journal_seq_ready(struct buckets_waiting_for_journal *b, | |
| 26 | + unsigned dev, u64 bucket) | |
| 28 | 27 | { |
| 29 | 28 | struct buckets_waiting_for_journal_table *t; |
| 30 | 29 | u64 dev_bucket = (u64) dev << 56 | bucket; |
| 31 | − bool ret = false; | |
| 32 | − unsigned i; | |
| 30 | + u64 ret = 0; | |
| 33 | 31 | |
| 34 | 32 | mutex_lock(&b->lock); |
| 35 | 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 | 36 | struct bucket_hashed *h = bucket_hash(t, i, dev_bucket); |
| 39 | 37 | |
| 40 | 38 | if (h->dev_bucket == dev_bucket) { |
| 41 | − ret = h->journal_seq > flushed_seq; | |
| 39 | + ret = h->journal_seq; | |
| 42 | 40 | break; |
| 43 | 41 | } |
| 44 | 42 | } |
| @@ -4,8 +4,8 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #include "buckets_waiting_for_journal_types.h" |
| 6 | 6 | |
| 7 | −bool bch2_bucket_needs_journal_commit(struct buckets_waiting_for_journal *, | |
| 8 | − u64, unsigned, u64); | |
| 7 | +u64 bch2_bucket_journal_seq_ready(struct buckets_waiting_for_journal *, | |
| 8 | + unsigned, u64); | |
| 9 | 9 | int bch2_set_bucket_needs_journal_commit(struct buckets_waiting_for_journal *, |
| 10 | 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 | 210 | static inline void bch2_accounting_mem_read(struct bch_fs *c, struct bpos p, |
| 211 | 211 | u64 *v, unsigned nr) |
| 212 | 212 | { |
| 213 | + percpu_down_read(&c->mark_lock); | |
| 213 | 214 | struct bch_accounting_mem *acc = &c->accounting; |
| 214 | 215 | unsigned idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]), |
| 215 | 216 | accounting_pos_cmp, &p); |
| 216 | 217 | |
| 217 | 218 | bch2_accounting_mem_read_counters(acc, idx, v, nr, false); |
| 219 | + percpu_up_read(&c->mark_lock); | |
| 218 | 220 | } |
| 219 | 221 | |
| 220 | 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 | 823 | struct bch_inode_unpacked inode; |
| 824 | 824 | u32 snapshot; |
| 825 | 825 | u64 count; |
| 826 | + u64 i_size; | |
| 826 | 827 | }; |
| 827 | 828 | |
| 828 | 829 | struct inode_walker { |
| @@ -910,8 +911,9 @@ found: · 81 unmodified lines | ||
| 910 | 911 | if (k.k->p.snapshot != i->snapshot && !is_whiteout) { |
| 911 | 912 | struct inode_walker_entry new = *i; |
| 912 | 913 | |
| 913 | − new.snapshot = k.k->p.snapshot; | |
| 914 | − new.count = 0; | |
| 914 | + new.snapshot = k.k->p.snapshot; | |
| 915 | + new.count = 0; | |
| 916 | + new.i_size = 0; | |
| 915 | 917 | |
| 916 | 918 | struct printbuf buf = PRINTBUF; |
| 917 | 919 | bch2_bkey_val_to_text(&buf, c, k); |
| @@ -1116,37 +1118,6 @@ err: · 198 unmodified lines | ||
| 1116 | 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 | 1121 | static int check_inode(struct btree_trans *trans, |
| 1151 | 1122 | struct btree_iter *iter, |
| 1152 | 1123 | struct bkey_s_c k, |
| @@ -1335,16 +1306,6 @@ static int check_inode(struct btree_trans *trans, · 182 unmodified lines | ||
| 1335 | 1306 | u.bi_journal_seq = journal_cur_seq(&c->journal); |
| 1336 | 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 | 1309 | do_update: |
| 1349 | 1310 | if (do_update) { |
| 1350 | 1311 | ret = __bch2_fsck_write_inode(trans, &u); |
| @@ -2017,10 +1978,31 @@ fsck_err: · 666 unmodified lines | ||
| 2017 | 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 | 2003 | u32 restart_count = trans->restart_count; |
| 2023 | 2004 | return check_subdir_count_notnested(trans, w) ?: |
| 2005 | + check_dir_i_size_notnested(trans, w) ?: | |
| 2024 | 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 | 2349 | goto out; |
| 2368 | 2350 | |
| 2369 | 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 | 2353 | if (ret) |
| 2372 | 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 | 2439 | if (ret) |
| 2458 | 2440 | goto err; |
| 2459 | 2441 | |
| 2460 | − if (d.v->d_type == DT_DIR) | |
| 2461 | − for_each_visible_inode(c, s, dir, d.k->p.snapshot, i) | |
| 2442 | + for_each_visible_inode(c, s, dir, d.k->p.snapshot, i) { | |
| 2443 | + if (d.v->d_type == DT_DIR) | |
| 2462 | 2444 | i->count++; |
| 2445 | + i->i_size += bkey_bytes(d.k); | |
| 2446 | + } | |
| 2463 | 2447 | out: |
| 2464 | 2448 | err: |
| 2465 | 2449 | fsck_err: |
| @@ -285,12 +285,14 @@ void bch2_inode_opts_get(struct bch_io_opts *, struct bch_fs *, · 284 unmodified lines | ||
| 285 | 285 | struct bch_inode_unpacked *); |
| 286 | 286 | int bch2_inum_opts_get(struct btree_trans*, subvol_inum, struct bch_io_opts *); |
| 287 | 287 | |
| 288 | +#include "rebalance.h" | |
| 289 | + | |
| 288 | 290 | static inline struct bch_extent_rebalance |
| 289 | 291 | bch2_inode_rebalance_opts_get(struct bch_fs *c, struct bch_inode_unpacked *inode) |
| 290 | 292 | { |
| 291 | 293 | struct bch_io_opts io_opts; |
| 292 | 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 | 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 | 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 | 424 | void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c, |
| 415 | 425 | enum bch_data_type type, |
| 416 | 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 | 1203 | struct bkey_i *insert = bch2_keylist_front(&op->insert_keys); |
| 1194 | 1204 | |
| 1195 | 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 | 1207 | prt_printf(&buf, "btree update error: %s", bch2_err_str(ret)); |
| 1198 | 1208 | bch_err_ratelimited(c, "%s", buf.buf); |
| 1199 | 1209 | printbuf_exit(&buf); |
| @@ -319,6 +319,16 @@ void bch2_journal_halt(struct journal *j) · 318 unmodified lines | ||
| 319 | 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 | 332 | static bool journal_entry_want_write(struct journal *j) |
| 323 | 333 | { |
| 324 | 334 | bool ret = !journal_entry_is_open(j) || |
| @@ -381,9 +391,12 @@ static int journal_entry_open(struct journal *j) · 56 unmodified lines | ||
| 381 | 391 | if (nr_unwritten_journal_entries(j) == ARRAY_SIZE(j->buf)) |
| 382 | 392 | return JOURNAL_ERR_max_in_flight; |
| 383 | 393 | |
| 384 | − if (bch2_fs_fatal_err_on(journal_cur_seq(j) >= JOURNAL_SEQ_MAX, | |
| 385 | − c, "cannot start: journal seq overflow")) | |
| 394 | + if (journal_cur_seq(j) >= JOURNAL_SEQ_MAX) { | |
| 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 | 398 | return JOURNAL_ERR_insufficient_devices; /* -EROFS */ |
| 399 | + } | |
| 387 | 400 | |
| 388 | 401 | BUG_ON(!j->cur_entry_sectors); |
| 389 | 402 | |
| @@ -783,6 +796,7 @@ recheck_need_open: · 393 unmodified lines | ||
| 783 | 796 | } |
| 784 | 797 | |
| 785 | 798 | buf->must_flush = true; |
| 799 | + j->flushing_seq = max(j->flushing_seq, seq); | |
| 786 | 800 | |
| 787 | 801 | if (parent && !closure_wait(&buf->wait, parent)) |
| 788 | 802 | BUG(); |
| @@ -409,6 +409,7 @@ bool bch2_journal_noflush_seq(struct journal *, u64, u64); · 408 unmodified lines | ||
| 409 | 409 | int bch2_journal_meta(struct journal *); |
| 410 | 410 | |
| 411 | 411 | void bch2_journal_halt(struct journal *); |
| 412 | +void bch2_journal_halt_locked(struct journal *); | |
| 412 | 413 | |
| 413 | 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 | 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 | 390 | if (fn == bch2_btree_node_flush0 || |
| 390 | − fn == bch2_btree_node_flush1) | |
| 391 | − return JOURNAL_PIN_TYPE_btree; | |
| 392 | − else if (fn == bch2_btree_key_cache_journal_flush) | |
| 391 | + fn == bch2_btree_node_flush1) { | |
| 392 | + unsigned idx = fn == bch2_btree_node_flush1; | |
| 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 | 397 | return JOURNAL_PIN_TYPE_key_cache; |
| 394 | 398 | else |
| 395 | 399 | return JOURNAL_PIN_TYPE_other; |
| @@ -441,7 +445,7 @@ void bch2_journal_pin_copy(struct journal *j, · 45 unmodified lines | ||
| 441 | 445 | |
| 442 | 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 | 450 | if (reclaim) |
| 447 | 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 | 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 | 474 | if (reclaim) |
| 471 | 475 | bch2_journal_reclaim_fast(j); |
| @@ -587,7 +591,7 @@ static size_t journal_flush_pins(struct journal *j, · 115 unmodified lines | ||
| 587 | 591 | spin_lock(&j->lock); |
| 588 | 592 | /* Pin might have been dropped or rearmed: */ |
| 589 | 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 | 595 | j->flush_in_progress = NULL; |
| 592 | 596 | j->flush_in_progress_dropped = false; |
| 593 | 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 | 874 | mutex_lock(&j->reclaim_lock); |
| 871 | 875 | |
| 872 | − if (journal_flush_pins_or_still_flushing(j, seq_to_flush, | |
| 873 | − BIT(JOURNAL_PIN_TYPE_key_cache)| | |
| 874 | − BIT(JOURNAL_PIN_TYPE_other))) { | |
| 875 | − *did_work = true; | |
| 876 | − goto unlock; | |
| 877 | − } | |
| 878 | − | |
| 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 | − } | |
| 876 | + for (int type = JOURNAL_PIN_TYPE_NR - 1; | |
| 877 | + type >= 0; | |
| 878 | + --type) | |
| 879 | + if (journal_flush_pins_or_still_flushing(j, seq_to_flush, BIT(type))) { | |
| 880 | + *did_work = true; | |
| 881 | + goto unlock; | |
| 882 | + } | |
| 884 | 883 | |
| 885 | 884 | if (seq_to_flush > journal_cur_seq(j)) |
| 886 | 885 | bch2_journal_entry_close(j); |
| @@ -53,7 +53,10 @@ struct journal_buf { · 52 unmodified lines | ||
| 53 | 53 | */ |
| 54 | 54 | |
| 55 | 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 | 60 | JOURNAL_PIN_TYPE_key_cache, |
| 58 | 61 | JOURNAL_PIN_TYPE_other, |
| 59 | 62 | JOURNAL_PIN_TYPE_NR, |
| @@ -237,6 +240,7 @@ struct journal { · 177 unmodified lines | ||
| 237 | 240 | /* seq, last_seq from the most recent journal entry successfully written */ |
| 238 | 241 | u64 seq_ondisk; |
| 239 | 242 | u64 flushed_seq_ondisk; |
| 243 | + u64 flushing_seq; | |
| 240 | 244 | u64 last_seq_ondisk; |
| 241 | 245 | u64 err_seq; |
| 242 | 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 | 659 | struct bch_io_opts bch2_opts_to_inode_opts(struct bch_opts); |
| 660 | 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 | 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 | 123 | incompressible: |
| 124 | − if (opts->background_target && | |
| 125 | − bch2_target_accepts_data(c, BCH_DATA_user, opts->background_target)) { | |
| 124 | + if (opts->background_target) | |
| 126 | 125 | bkey_for_each_ptr_decode(k.k, ptrs, p, entry) |
| 127 | 126 | if (!p.ptr.cached && !bch2_dev_in_target(c, p.ptr.dev, opts->background_target)) |
| 128 | 127 | sectors += p.crc.compressed_size; |
| 129 | − } | |
| 130 | 128 | |
| 131 | 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 | 138 | const struct bch_extent_rebalance *old = bch2_bkey_rebalance_opts(k); |
| 141 | 139 | |
| 142 | 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 | 142 | return old == NULL || memcmp(old, &new, sizeof(new)); |
| 145 | 143 | } else { |
| 146 | 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 | 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 | 165 | } else { |
| 168 | 166 | if (old) |
| 169 | 167 | extent_entry_drop(k, (union bch_extent_entry *) old); |
| @@ -4,8 +4,28 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #include "compress.h" |
| 6 | 6 | #include "disk_groups.h" |
| 7 | +#include "opts.h" | |
| 7 | 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 | 29 | u64 bch2_bkey_sectors_need_rebalance(struct bch_fs *, struct bkey_s_c); |
| 10 | 30 | int bch2_bkey_set_needs_rebalance(struct bch_fs *, struct bch_io_opts *, struct bkey_i *); |
| 11 | 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 | 172 | bool should_commit) |
| 173 | 173 | { |
| 174 | 174 | if (REFLINK_P_ERROR(p.v)) |
| 175 | − return -BCH_ERR_missing_indirect_extent; | |
| 175 | + return 0; | |
| 176 | 176 | |
| 177 | 177 | struct bch_fs *c = trans->c; |
| 178 | 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 | 259 | return k; |
| 260 | 260 | |
| 261 | 261 | if (unlikely(!bkey_extent_is_reflink_data(k.k))) { |
| 262 | − bch2_trans_iter_exit(trans, iter); | |
| 263 | − | |
| 264 | 262 | unsigned size = min((u64) k.k->size, |
| 265 | 263 | REFLINK_P_IDX(p.v) + p.k->size + le32_to_cpu(p.v->back_pad) - |
| 266 | 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 | 267 | int ret = bch2_indirect_extent_missing_error(trans, p, reflink_offset, |
| 270 | 268 | k.k->p.offset, should_commit); |
| 271 | − if (ret) | |
| 269 | + if (ret) { | |
| 270 | + bch2_trans_iter_exit(trans, iter); | |
| 272 | 271 | return bkey_s_c_err(ret); |
| 272 | + } | |
| 273 | 273 | } else if (unlikely(REFLINK_P_ERROR(p.v))) { |
| 274 | − bch2_trans_iter_exit(trans, iter); | |
| 275 | − | |
| 276 | 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 | 277 | return bkey_s_c_err(ret); |
| 278 | + } | |
| 279 | 279 | } |
| 280 | 280 | |
| 281 | 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 | 300 | if (ret) |
| 301 | 301 | return ret; |
| 302 | 302 | |
| 303 | − if (bkey_deleted(k.k)) { | |
| 303 | + if (!bkey_refcount_c(k)) { | |
| 304 | 304 | if (!(flags & BTREE_TRIGGER_overwrite)) |
| 305 | 305 | ret = -BCH_ERR_missing_indirect_extent; |
| 306 | 306 | goto next; |
| @@ -92,7 +92,7 @@ · 91 unmodified lines | ||
| 92 | 92 | BCH_FSCK_ERR_accounting_key_replicas_nr_devs_0, \ |
| 93 | 93 | BCH_FSCK_ERR_accounting_key_junk_at_end) \ |
| 94 | 94 | x(directory_size, \ |
| 95 | − BIT_ULL(BCH_RECOVERY_PASS_check_inodes), \ | |
| 95 | + BIT_ULL(BCH_RECOVERY_PASS_check_dirents), \ | |
| 96 | 96 | BCH_FSCK_ERR_directory_size_mismatch) \ |
| 97 | 97 | |
| 98 | 98 | #define DOWNGRADE_TABLE() \ |
| @@ -180,9 +180,9 @@ enum bch_fsck_flags { · 179 unmodified lines | ||
| 180 | 180 | x(ptr_crc_nonce_mismatch, 162, 0) \ |
| 181 | 181 | x(ptr_stripe_redundant, 163, 0) \ |
| 182 | 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 | 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 | 186 | x(reflink_refcount_underflow, 293, 0) \ |
| 187 | 187 | x(stripe_pos_bad, 167, 0) \ |
| 188 | 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 | 428 | bch2_bkey_get_iter_typed(trans, &snapshot_iter, |
| 429 | 429 | BTREE_ID_snapshots, POS(0, snapid), |
| 430 | 430 | 0, snapshot); |
| 431 | − ret = bkey_err(subvol); | |
| 431 | + ret = bkey_err(snapshot); | |
| 432 | 432 | bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), trans->c, |
| 433 | 433 | "missing snapshot %u", snapid); |
| 434 | 434 | if (ret) |
| @@ -440,6 +440,11 @@ static int __bch2_subvolume_delete(struct btree_trans *trans, u32 subvolid) · 5 unmodified lines | ||
| 440 | 440 | bch2_bkey_get_iter_typed(trans, &snapshot_tree_iter, |
| 441 | 441 | BTREE_ID_snapshot_trees, POS(0, treeid), |
| 442 | 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 | 449 | if (le32_to_cpu(snapshot_tree.v->master_subvol) == subvolid) { |
| 445 | 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 | 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 | 425 | static int bch2_fs_read_write_late(struct bch_fs *c) |
| 415 | 426 | { |
| 416 | 427 | int ret; |
| @@ -29,6 +29,7 @@ int bch2_dev_resize(struct bch_fs *, struct bch_dev *, u64); · 28 unmodified lines | ||
| 29 | 29 | struct bch_dev *bch2_dev_lookup(struct bch_fs *, const char *); |
| 30 | 30 | |
| 31 | 31 | bool bch2_fs_emergency_read_only(struct bch_fs *); |
| 32 | +bool bch2_fs_emergency_read_only_locked(struct bch_fs *); | |
| 32 | 33 | void bch2_fs_read_only(struct bch_fs *); |
| 33 | 34 | |
| 34 | 35 | int bch2_fs_read_write(struct bch_fs *); |
| @@ -727,7 +727,7 @@ DEFINE_EVENT(fs_str, bucket_alloc_fail, · 726 unmodified lines | ||
| 727 | 727 | TP_ARGS(c, str) |
| 728 | 728 | ); |
| 729 | 729 | |
| 730 | −TRACE_EVENT(discard_buckets, | |
| 730 | +DECLARE_EVENT_CLASS(discard_buckets_class, | |
| 731 | 731 | TP_PROTO(struct bch_fs *c, u64 seen, u64 open, |
| 732 | 732 | u64 need_journal_commit, u64 discarded, const char *err), |
| 733 | 733 | TP_ARGS(c, seen, open, need_journal_commit, discarded, err), |
| @@ -759,6 +759,18 @@ TRACE_EVENT(discard_buckets, · 25 unmodified lines | ||
| 759 | 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 | 774 | TRACE_EVENT(bucket_invalidate, |
| 763 | 775 | TP_PROTO(struct bch_fs *c, unsigned dev, u64 bucket, u32 sectors), |
| 764 | 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 | 1497 | if (!p->skip_locking) { |
| 1498 | 1498 | btrfs_unlock_up_safe(p, parent_level + 1); |
| 1499 | + btrfs_maybe_reset_lockdep_class(root, tmp); | |
| 1499 | 1500 | tmp_locked = true; |
| 1500 | 1501 | btrfs_tree_read_lock(tmp); |
| 1501 | 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 | 1541 | if (!p->skip_locking) { |
| 1541 | 1542 | ASSERT(ret == -EAGAIN); |
| 1543 | + btrfs_maybe_reset_lockdep_class(root, tmp); | |
| 1542 | 1544 | tmp_locked = true; |
| 1543 | 1545 | btrfs_tree_read_lock(tmp); |
| 1544 | 1546 | btrfs_release_path(p); |
| @@ -523,8 +523,6 @@ static void end_bbio_data_read(struct btrfs_bio *bbio) · 522 unmodified lines | ||
| 523 | 523 | u64 end; |
| 524 | 524 | u32 len; |
| 525 | 525 | |
| 526 | − /* For now only order 0 folios are supported for data. */ | |
| 527 | − ASSERT(folio_order(folio) == 0); | |
| 528 | 526 | btrfs_debug(fs_info, |
| 529 | 527 | "%s: bi_sector=%llu, err=%d, mirror=%u", |
| 530 | 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 | 551 | if (likely(uptodate)) { |
| 554 | 552 | loff_t i_size = i_size_read(inode); |
| 555 | − pgoff_t end_index = i_size >> folio_shift(folio); | |
| 556 | 553 | |
| 557 | 554 | /* |
| 558 | 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 | 558 | * Here we should only zero the range inside the folio, |
| 562 | 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 | 566 | u32 zero_start = max(offset_in_folio(folio, i_size), |
| 568 | 567 | offset_in_folio(folio, start)); |
| 569 | 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 | 898 | u64 len, struct extent_map **em_cached) |
| 900 | 899 | { |
| 901 | 900 | struct extent_map *em; |
| 902 | − struct extent_state *cached_state = NULL; | |
| 903 | 901 | |
| 904 | 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 | 913 | *em_cached = NULL; |
| 916 | 914 | } |
| 917 | 915 | |
| 918 | − btrfs_lock_and_flush_ordered_range(inode, start, start + len - 1, &cached_state); | |
| 919 | 916 | em = btrfs_get_extent(inode, folio, start, len); |
| 920 | 917 | if (!IS_ERR(em)) { |
| 921 | 918 | BUG_ON(*em_cached); |
| 922 | 919 | refcount_inc(&em->refs); |
| 923 | 920 | *em_cached = em; |
| 924 | 921 | } |
| 925 | − unlock_extent(&inode->io_tree, start, start + len - 1, &cached_state); | |
| 926 | 922 | |
| 927 | 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 | 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 | 956 | size_t zero_offset = offset_in_folio(folio, last_byte); |
| 961 | 957 | |
| 962 | 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 | 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 | 1082 | struct btrfs_bio_ctrl bio_ctrl = { .opf = REQ_OP_READ }; |
| 1083 | 1083 | struct extent_map *em_cached = NULL; |
| 1084 | 1084 | int ret; |
| 1085 | 1085 | |
| 1086 | + btrfs_lock_and_flush_ordered_range(inode, start, end, &cached_state); | |
| 1086 | 1087 | ret = btrfs_do_readpage(folio, &em_cached, &bio_ctrl, NULL); |
| 1088 | + unlock_extent(&inode->io_tree, start, end, &cached_state); | |
| 1089 | + | |
| 1087 | 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 | 2384 | struct btrfs_bio_ctrl bio_ctrl = { .opf = REQ_OP_READ | REQ_RAHEAD }; |
| 2382 | 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 | 2390 | struct extent_map *em_cached = NULL; |
| 2384 | 2391 | u64 prev_em_start = (u64)-1; |
| 2385 | 2392 | |
| 2393 | + btrfs_lock_and_flush_ordered_range(inode, start, end, &cached_state); | |
| 2394 | + | |
| 2386 | 2395 | while ((folio = readahead_folio(rac)) != NULL) |
| 2387 | 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 | 2400 | if (em_cached) |
| 2390 | 2401 | free_extent_map(em_cached); |
| 2391 | 2402 | submit_one_bio(&bio_ctrl); |
| @@ -1039,7 +1039,6 @@ int btrfs_write_check(struct kiocb *iocb, size_t count) · 1038 unmodified lines | ||
| 1039 | 1039 | loff_t pos = iocb->ki_pos; |
| 1040 | 1040 | int ret; |
| 1041 | 1041 | loff_t oldsize; |
| 1042 | − loff_t start_pos; | |
| 1043 | 1042 | |
| 1044 | 1043 | /* |
| 1045 | 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 | 1065 | inode_inc_iversion(inode); |
| 1067 | 1066 | } |
| 1068 | 1067 | |
| 1069 | − start_pos = round_down(pos, fs_info->sectorsize); | |
| 1070 | 1068 | oldsize = i_size_read(inode); |
| 1071 | − if (start_pos > oldsize) { | |
| 1069 | + if (pos > oldsize) { | |
| 1072 | 1070 | /* Expand hole size to cover write data, preventing empty gap */ |
| 1073 | 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 | 1230 | if (WARN_ON_ONCE(len >= ordered->num_bytes)) |
| 1231 | 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 | 1244 | /* We cannot split partially completed ordered extents. */ |
| 1233 | 1245 | if (ordered->bytes_left) { |
| 1234 | 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 | 1880 | * Commit current transaction to make sure all the rfer/excl numbers |
| 1881 | 1881 | * get updated. |
| 1882 | 1882 | */ |
| 1883 | − trans = btrfs_start_transaction(fs_info->quota_root, 0); | |
| 1884 | − if (IS_ERR(trans)) | |
| 1885 | − return PTR_ERR(trans); | |
| 1886 | − | |
| 1887 | − ret = btrfs_commit_transaction(trans); | |
| 1883 | + ret = btrfs_commit_current_transaction(fs_info->quota_root); | |
| 1888 | 1884 | if (ret < 0) |
| 1889 | 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 | 1894 | * It's squota and the subvolume still has numbers needed for future |
| 1899 | 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 | 1901 | ret = 0; |
| 1903 | 1902 | return ret; |
| 1904 | 1903 | } |
| @@ -274,8 +274,10 @@ loop: · 273 unmodified lines | ||
| 274 | 274 | cur_trans = fs_info->running_transaction; |
| 275 | 275 | if (cur_trans) { |
| 276 | 276 | if (TRANS_ABORTED(cur_trans)) { |
| 277 | + const int abort_error = cur_trans->aborted; | |
| 278 | + | |
| 277 | 279 | spin_unlock(&fs_info->trans_lock); |
| 278 | − return cur_trans->aborted; | |
| 280 | + return abort_error; | |
| 279 | 281 | } |
| 280 | 282 | if (btrfs_blocked_trans_types[cur_trans->state] & type) { |
| 281 | 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 | 1700 | smp_store_release(&dentry->d_name.name, dname); /* ^^^ */ |
| 1701 | 1701 | |
| 1702 | 1702 | dentry->d_flags = 0; |
| 1703 | − lockref_init(&dentry->d_lockref, 1); | |
| 1703 | + lockref_init(&dentry->d_lockref); | |
| 1704 | 1704 | seqcount_spinlock_init(&dentry->d_seq, &dentry->d_lock); |
| 1705 | 1705 | dentry->d_inode = NULL; |
| 1706 | 1706 | dentry->d_parent = dentry; |
| @@ -2966,11 +2966,11 @@ static int __d_unalias(struct dentry *dentry, struct dentry *alias) · 1259 unmodified lines | ||
| 2966 | 2966 | goto out_err; |
| 2967 | 2967 | m2 = &alias->d_parent->d_inode->i_rwsem; |
| 2968 | 2968 | out_unalias: |
| 2969 | − if (alias->d_op->d_unalias_trylock && | |
| 2969 | + if (alias->d_op && alias->d_op->d_unalias_trylock && | |
| 2970 | 2970 | !alias->d_op->d_unalias_trylock(alias)) |
| 2971 | 2971 | goto out_err; |
| 2972 | 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 | 2974 | alias->d_op->d_unalias_unlock(alias); |
| 2975 | 2975 | ret = 0; |
| 2976 | 2976 | out_err: |
| @@ -726,7 +726,7 @@ static int z_erofs_register_pcluster(struct z_erofs_frontend *fe) · 725 unmodified lines | ||
| 726 | 726 | if (IS_ERR(pcl)) |
| 727 | 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 | 730 | pcl->algorithmformat = map->m_algorithmformat; |
| 731 | 731 | pcl->length = 0; |
| 732 | 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 | 194 | * refcount bumps we should reinitialize the reused file first. |
| 195 | 195 | */ |
| 196 | 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 | 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 | 380 | if (IS_ERR(file)) { |
| 376 | 381 | ihold(inode); |
| 377 | 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 | 390 | return file; |
| 380 | 391 | } |
| 381 | 392 | EXPORT_SYMBOL(alloc_file_pseudo); |
| @@ -400,6 +411,11 @@ struct file *alloc_file_pseudo_noaccount(struct inode *inode, · 18 unmodified lines | ||
| 400 | 411 | return file; |
| 401 | 412 | } |
| 402 | 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 | 419 | return file; |
| 404 | 420 | } |
| 405 | 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 | 1201 | if (glops->go_instantiate) |
| 1202 | 1202 | gl->gl_flags |= BIT(GLF_INSTANTIATE_NEEDED); |
| 1203 | 1203 | gl->gl_name = name; |
| 1204 | + lockref_init(&gl->gl_lockref); | |
| 1204 | 1205 | lockdep_set_subclass(&gl->gl_lockref.lock, glops->go_subclass); |
| 1205 | − gl->gl_lockref.count = 1; | |
| 1206 | 1206 | gl->gl_state = LM_ST_UNLOCKED; |
| 1207 | 1207 | gl->gl_target = LM_ST_UNLOCKED; |
| 1208 | 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 | 52 | struct gfs2_glock *gl = foo; |
| 53 | 53 | |
| 54 | − spin_lock_init(&gl->gl_lockref.lock); | |
| 55 | 54 | INIT_LIST_HEAD(&gl->gl_holders); |
| 56 | 55 | INIT_LIST_HEAD(&gl->gl_lru); |
| 57 | 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 | 236 | return NULL; |
| 237 | 237 | |
| 238 | 238 | qd->qd_sbd = sdp; |
| 239 | − lockref_init(&qd->qd_lockref, 0); | |
| 239 | + lockref_init(&qd->qd_lockref); | |
| 240 | 240 | qd->qd_id = qid; |
| 241 | 241 | qd->qd_slot = -1; |
| 242 | 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 | 297 | spin_lock_bucket(hash); |
| 298 | 298 | *qdp = qd = gfs2_qd_search_bucket(hash, sdp, qid); |
| 299 | 299 | if (qd == NULL) { |
| 300 | − new_qd->qd_lockref.count++; | |
| 301 | 300 | *qdp = new_qd; |
| 302 | 301 | list_add(&new_qd->qd_list, &sdp->sd_quota_list); |
| 303 | 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 | 1449 | if (qd == NULL) |
| 1451 | 1450 | goto fail_brelse; |
| 1452 | 1451 | |
| 1452 | + qd->qd_lockref.count = 0; | |
| 1453 | 1453 | set_bit(QDF_CHANGE, &qd->qd_flags); |
| 1454 | 1454 | qd->qd_change = qc_change; |
| 1455 | 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 | 5088 | struct vfsmount *mnt = s->mnt; |
| 5089 | 5089 | struct super_block *sb = mnt->mnt_sb; |
| 5090 | + size_t start = seq->count; | |
| 5090 | 5091 | int err; |
| 5091 | 5092 | |
| 5092 | − if (sb->s_op->show_options) { | |
| 5093 | − size_t start = seq->count; | |
| 5094 | − | |
| 5095 | − err = security_sb_show_options(seq, sb); | |
| 5096 | − if (err) | |
| 5097 | − return err; | |
| 5093 | + err = security_sb_show_options(seq, sb); | |
| 5094 | + if (err) | |
| 5095 | + return err; | |
| 5098 | 5096 | |
| 5097 | + if (sb->s_op->show_options) { | |
| 5099 | 5098 | err = sb->s_op->show_options(seq, mnt->mnt_root); |
| 5100 | 5099 | if (err) |
| 5101 | 5100 | return err; |
| 5101 | + } | |
| 5102 | 5102 | |
| 5103 | − if (unlikely(seq_has_overflowed(seq))) | |
| 5104 | − return -EAGAIN; | |
| 5103 | + if (unlikely(seq_has_overflowed(seq))) | |
| 5104 | + return -EAGAIN; | |
| 5105 | 5105 | |
| 5106 | − if (seq->count == start) | |
| 5107 | − return 0; | |
| 5106 | + if (seq->count == start) | |
| 5107 | + return 0; | |
| 5108 | 5108 | |
| 5109 | − /* skip leading comma */ | |
| 5110 | − memmove(seq->buf + start, seq->buf + start + 1, | |
| 5111 | − seq->count - start - 1); | |
| 5112 | − seq->count--; | |
| 5113 | − } | |
| 5109 | + /* skip leading comma */ | |
| 5110 | + memmove(seq->buf + start, seq->buf + start + 1, | |
| 5111 | + seq->count - start - 1); | |
| 5112 | + seq->count--; | |
| 5114 | 5113 | |
| 5115 | 5114 | return 0; |
| 5116 | 5115 | } |
| @@ -5191,39 +5190,45 @@ static int statmount_string(struct kstatmount *s, u64 flag) · 74 unmodified lines | ||
| 5191 | 5190 | size_t kbufsize; |
| 5192 | 5191 | struct seq_file *seq = &s->seq; |
| 5193 | 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 | 5201 | switch (flag) { |
| 5197 | 5202 | case STATMOUNT_FS_TYPE: |
| 5198 | − sm->fs_type = start; | |
| 5203 | + offp = &sm->fs_type; | |
| 5199 | 5204 | ret = statmount_fs_type(s, seq); |
| 5200 | 5205 | break; |
| 5201 | 5206 | case STATMOUNT_MNT_ROOT: |
| 5202 | − sm->mnt_root = start; | |
| 5207 | + offp = &sm->mnt_root; | |
| 5203 | 5208 | ret = statmount_mnt_root(s, seq); |
| 5204 | 5209 | break; |
| 5205 | 5210 | case STATMOUNT_MNT_POINT: |
| 5206 | − sm->mnt_point = start; | |
| 5211 | + offp = &sm->mnt_point; | |
| 5207 | 5212 | ret = statmount_mnt_point(s, seq); |
| 5208 | 5213 | break; |
| 5209 | 5214 | case STATMOUNT_MNT_OPTS: |
| 5210 | − sm->mnt_opts = start; | |
| 5215 | + offp = &sm->mnt_opts; | |
| 5211 | 5216 | ret = statmount_mnt_opts(s, seq); |
| 5212 | 5217 | break; |
| 5213 | 5218 | case STATMOUNT_OPT_ARRAY: |
| 5214 | − sm->opt_array = start; | |
| 5219 | + offp = &sm->opt_array; | |
| 5215 | 5220 | ret = statmount_opt_array(s, seq); |
| 5216 | 5221 | break; |
| 5217 | 5222 | case STATMOUNT_OPT_SEC_ARRAY: |
| 5218 | − sm->opt_sec_array = start; | |
| 5223 | + offp = &sm->opt_sec_array; | |
| 5219 | 5224 | ret = statmount_opt_sec_array(s, seq); |
| 5220 | 5225 | break; |
| 5221 | 5226 | case STATMOUNT_FS_SUBTYPE: |
| 5222 | − sm->fs_subtype = start; | |
| 5227 | + offp = &sm->fs_subtype; | |
| 5223 | 5228 | statmount_fs_subtype(s, seq); |
| 5224 | 5229 | break; |
| 5225 | 5230 | case STATMOUNT_SB_SOURCE: |
| 5226 | − sm->sb_source = start; | |
| 5231 | + offp = &sm->sb_source; | |
| 5227 | 5232 | ret = statmount_sb_source(s, seq); |
| 5228 | 5233 | break; |
| 5229 | 5234 | default: |
| @@ -5251,6 +5256,7 @@ static int statmount_string(struct kstatmount *s, u64 flag) · 21 unmodified lines | ||
| 5251 | 5256 | |
| 5252 | 5257 | seq->buf[seq->count++] = '\0'; |
| 5253 | 5258 | sm->mask |= flag; |
| 5259 | + *offp = start; | |
| 5254 | 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 | 155 | netfs_cache_read_terminated, subreq); |
| 156 | 156 | } |
| 157 | 157 | |
| 158 | −static void netfs_issue_read(struct netfs_io_request *rreq, | |
| 159 | − struct netfs_io_subrequest *subreq) | |
| 158 | +static void netfs_queue_read(struct netfs_io_request *rreq, | |
| 159 | + struct netfs_io_subrequest *subreq, | |
| 160 | + bool last_subreq) | |
| 160 | 161 | { |
| 161 | 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 | 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 | 192 | switch (subreq->source) { |
| 183 | 193 | case NETFS_DOWNLOAD_FROM_SERVER: |
| 184 | 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 | 304 | size -= slice; |
| 295 | 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 | 308 | netfs_issue_read(rreq, subreq); |
| 302 | 309 | cond_resched(); |
| 303 | 310 | } while (size > 0); |
| @@ -135,6 +135,8 @@ extern atomic_t netfs_n_rh_write_begin; · 134 unmodified lines | ||
| 135 | 135 | extern atomic_t netfs_n_rh_write_done; |
| 136 | 136 | extern atomic_t netfs_n_rh_write_failed; |
| 137 | 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 | 140 | extern atomic_t netfs_n_wh_buffered_write; |
| 139 | 141 | extern atomic_t netfs_n_wh_writethrough; |
| 140 | 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 | 149 | extern atomic_t netfs_n_wh_write; |
| 148 | 150 | extern atomic_t netfs_n_wh_write_done; |
| 149 | 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 | 154 | extern atomic_t netfs_n_wb_lock_skip; |
| 151 | 155 | extern atomic_t netfs_n_wb_lock_wait; |
| 152 | 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 | 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 | 475 | if (!work_pending(&rreq->work)) { |
| 475 | 476 | netfs_get_request(rreq, netfs_rreq_trace_get_work); |
| 476 | 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 | 587 | smp_mb__after_atomic(); /* Clear IN_PROGRESS before task state */ |
| 587 | 588 | |
| 588 | 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 | 592 | netfs_wake_read_collector(rreq); |
| 591 | 593 | |
| 592 | 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 | 15 | __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); |
| 16 | 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 | 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 | 48 | __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); |
| 49 | 49 | subreq->retry_count++; |
| 50 | 50 | netfs_reset_iter(subreq); |
| 51 | + netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); | |
| 51 | 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 | 76 | struct iov_iter source; |
| 76 | 77 | unsigned long long start, len; |
| 77 | 78 | size_t part; |
| 78 | − bool boundary = false; | |
| 79 | + bool boundary = false, subreq_superfluous = false; | |
| 79 | 80 | |
| 80 | 81 | /* Go through the subreqs and find the next span of contiguous |
| 81 | 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 | 117 | /* Work through the sublist. */ |
| 117 | 118 | subreq = from; |
| 118 | 119 | list_for_each_entry_from(subreq, &stream->subrequests, rreq_link) { |
| 119 | − if (!len) | |
| 120 | + if (!len) { | |
| 121 | + subreq_superfluous = true; | |
| 120 | 122 | break; |
| 123 | + } | |
| 121 | 124 | subreq->source = NETFS_DOWNLOAD_FROM_SERVER; |
| 122 | 125 | subreq->start = start - subreq->transferred; |
| 123 | 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 | 158 | netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); |
| 156 | 159 | netfs_reissue_read(rreq, subreq); |
| 157 | − if (subreq == to) | |
| 160 | + if (subreq == to) { | |
| 161 | + subreq_superfluous = false; | |
| 158 | 162 | break; |
| 163 | + } | |
| 159 | 164 | } |
| 160 | 165 | |
| 161 | 166 | /* If we managed to use fewer subreqs, we can discard the |
| 162 | 167 | * excess; if we used the same number, then we're done. |
| 163 | 168 | */ |
| 164 | 169 | if (!len) { |
| 165 | − if (subreq == to) | |
| 170 | + if (!subreq_superfluous) | |
| 166 | 171 | continue; |
| 167 | 172 | list_for_each_entry_safe_from(subreq, tmp, |
| 168 | 173 | &stream->subrequests, rreq_link) { |
| 169 | − trace_netfs_sreq(subreq, netfs_sreq_trace_discard); | |
| 174 | + trace_netfs_sreq(subreq, netfs_sreq_trace_superfluous); | |
| 170 | 175 | list_del(&subreq->rreq_link); |
| 171 | 176 | netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_done); |
| 172 | 177 | if (subreq == to) |
| @@ -187,14 +192,12 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq) · 14 unmodified lines | ||
| 187 | 192 | subreq->source = NETFS_DOWNLOAD_FROM_SERVER; |
| 188 | 193 | subreq->start = start; |
| 189 | 194 | subreq->len = len; |
| 190 | − subreq->debug_index = atomic_inc_return(&rreq->subreq_counter); | |
| 191 | 195 | subreq->stream_nr = stream->stream_nr; |
| 192 | 196 | subreq->retry_count = 1; |
| 193 | 197 | |
| 194 | 198 | trace_netfs_sreq_ref(rreq->debug_id, subreq->debug_index, |
| 195 | 199 | refcount_read(&subreq->ref), |
| 196 | 200 | netfs_sreq_trace_new); |
| 197 | − netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); | |
| 198 | 201 | |
| 199 | 202 | list_add(&subreq->rreq_link, &to->rreq_link); |
| 200 | 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 | 260 | struct netfs_io_subrequest *subreq; |
| 258 | 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 | 268 | /* Wait for all outstanding I/O to quiesce before performing retries as |
| 261 | 269 | * we may need to renegotiate the I/O sizes. |
| 262 | 270 | */ |
| 263 | 271 | list_for_each_entry(subreq, &stream->subrequests, rreq_link) { |
| 264 | − wait_on_bit(&subreq->flags, NETFS_SREQ_IN_PROGRESS, | |
| 265 | − TASK_UNINTERRUPTIBLE); | |
| 272 | + if (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags)) | |
| 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 | 291 | trace_netfs_rreq(rreq, netfs_rreq_trace_resubmit); |
| 269 | 292 | netfs_retry_read_subrequests(rreq); |
| @@ -29,6 +29,8 @@ atomic_t netfs_n_rh_write_begin; · 28 unmodified lines | ||
| 29 | 29 | atomic_t netfs_n_rh_write_done; |
| 30 | 30 | atomic_t netfs_n_rh_write_failed; |
| 31 | 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 | 34 | atomic_t netfs_n_wh_buffered_write; |
| 33 | 35 | atomic_t netfs_n_wh_writethrough; |
| 34 | 36 | atomic_t netfs_n_wh_dio_write; |
| @@ -41,6 +43,8 @@ atomic_t netfs_n_wh_upload_failed; · 6 unmodified lines | ||
| 41 | 43 | atomic_t netfs_n_wh_write; |
| 42 | 44 | atomic_t netfs_n_wh_write_done; |
| 43 | 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 | 48 | atomic_t netfs_n_wb_lock_skip; |
| 45 | 49 | atomic_t netfs_n_wb_lock_wait; |
| 46 | 50 | atomic_t netfs_n_folioq; |
| @@ -81,6 +85,11 @@ int netfs_stats_show(struct seq_file *m, void *v) · 34 unmodified lines | ||
| 81 | 85 | atomic_read(&netfs_n_wh_write), |
| 82 | 86 | atomic_read(&netfs_n_wh_write_done), |
| 83 | 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 | 93 | seq_printf(m, "Objs : rr=%u sr=%u foq=%u wsc=%u\n", |
| 85 | 94 | atomic_read(&netfs_n_rh_rreq), |
| 86 | 95 | atomic_read(&netfs_n_rh_sreq), |
| @@ -253,6 +253,7 @@ void netfs_reissue_write(struct netfs_io_stream *stream, · 252 unmodified lines | ||
| 253 | 253 | subreq->retry_count++; |
| 254 | 254 | __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); |
| 255 | 255 | __set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags); |
| 256 | + netfs_stat(&netfs_n_wh_retry_write_subreq); | |
| 256 | 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 | 203 | struct netfs_io_stream *stream; |
| 204 | 204 | int s; |
| 205 | 205 | |
| 206 | + netfs_stat(&netfs_n_wh_retry_write_req); | |
| 207 | + | |
| 206 | 208 | /* Wait for all outstanding I/O to quiesce before performing retries as |
| 207 | 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 | 446 | struct nfsd_file, nf_gc); |
| 447 | 447 | struct nfsd_net *nn = net_generic(nf->nf_net, nfsd_net_id); |
| 448 | 448 | struct nfsd_fcache_disposal *l = nn->fcache_disposal; |
| 449 | + struct svc_serv *serv; | |
| 449 | 450 | |
| 450 | 451 | spin_lock(&l->lock); |
| 451 | 452 | list_move_tail(&nf->nf_gc, &l->freeme); |
| 452 | 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 | 84 | fail: |
| 85 | 85 | posix_acl_release(resp->acl_access); |
| 86 | 86 | posix_acl_release(resp->acl_default); |
| 87 | + resp->acl_access = NULL; | |
| 88 | + resp->acl_default = NULL; | |
| 87 | 89 | goto out; |
| 88 | 90 | } |
| 89 | 91 | |
| @@ -76,6 +76,8 @@ out: · 75 unmodified lines | ||
| 76 | 76 | fail: |
| 77 | 77 | posix_acl_release(resp->acl_access); |
| 78 | 78 | posix_acl_release(resp->acl_default); |
| 79 | + resp->acl_access = NULL; | |
| 80 | + resp->acl_default = NULL; | |
| 79 | 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 | 679 | return status; |
| 680 | 680 | |
| 681 | 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 | 683 | return status; |
| 684 | 684 | if (xdr_stream_decode_uint32_array(xdr, bitmap, 3) < 0) |
| 685 | 685 | return -NFSERR_BAD_XDR; |
| @@ -1583,8 +1583,11 @@ nfsd4_run_cb_work(struct work_struct *work) · 897 unmodified lines | ||
| 1583 | 1583 | nfsd4_process_cb_update(cb); |
| 1584 | 1584 | |
| 1585 | 1585 | clnt = clp->cl_cb_client; |
| 1586 | − if (!clnt) { | |
| 1587 | − /* Callback channel broken, or client killed; give up: */ | |
| 1586 | + if (!clnt || clp->cl_state == NFSD4_COURTESY) { | |
| 1587 | + /* | |
| 1588 | + * Callback channel broken, client killed or | |
| 1589 | + * nfs4_client in courtesy state; give up. | |
| 1590 | + */ | |
| 1588 | 1591 | nfsd41_destroy_cb(cb); |
| 1589 | 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 | 4460 | } while (slot && --cnt > 0); |
| 4461 | 4461 | } |
| 4462 | + | |
| 4463 | +out: | |
| 4462 | 4464 | seq->maxslots = max(session->se_target_maxslots, seq->maxslots); |
| 4463 | 4465 | seq->target_maxslots = session->se_target_maxslots; |
| 4464 | 4466 | |
| 4465 | −out: | |
| 4466 | 4467 | switch (clp->cl_cb_state) { |
| 4467 | 4468 | case NFSD4_CB_DOWN: |
| 4468 | 4469 | seq->status_flags = SEQ4_STATUS_CB_PATH_DOWN; |
| @@ -380,8 +380,9 @@ __fh_verify(struct svc_rqst *rqstp, · 379 unmodified lines | ||
| 380 | 380 | error = check_nfsd_access(exp, rqstp, may_bypass_gss); |
| 381 | 381 | if (error) |
| 382 | 382 | goto out; |
| 383 | − | |
| 384 | − svc_xprt_set_valid(rqstp->rq_xprt); | |
| 383 | + /* During LOCALIO call to fh_verify will be called with a NULL rqstp */ | |
| 384 | + if (rqstp) | |
| 385 | + svc_xprt_set_valid(rqstp->rq_xprt); | |
| 385 | 386 | |
| 386 | 387 | /* Finally, check access permissions. */ |
| 387 | 388 | error = nfsd_permission(cred, exp, dentry, access); |
| @@ -648,7 +648,7 @@ EXPORT_SYMBOL_GPL(fsnotify); · 647 unmodified lines | ||
| 648 | 648 | * Later, fsnotify permission hooks do not check if there are permission event |
| 649 | 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 | 653 | struct dentry *dentry = file->f_path.dentry, *parent; |
| 654 | 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 | 666 | if (likely(!fsnotify_sb_has_priority_watchers(sb, |
| 667 | 667 | FSNOTIFY_PRIO_CONTENT))) { |
| 668 | − file->f_mode |= FMODE_NONOTIFY_PERM; | |
| 668 | + file_set_fsnotify_mode(file, FMODE_NONOTIFY_PERM); | |
| 669 | 669 | return; |
| 670 | 670 | } |
| 671 | 671 | |
| @@ -676,7 +676,7 @@ void file_set_fsnotify_mode(struct file *file) · 4 unmodified lines | ||
| 676 | 676 | if ((!d_is_dir(dentry) && !d_is_reg(dentry)) || |
| 677 | 677 | likely(!fsnotify_sb_has_priority_watchers(sb, |
| 678 | 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 | 680 | return; |
| 681 | 681 | } |
| 682 | 682 | |
| @@ -686,19 +686,25 @@ void file_set_fsnotify_mode(struct file *file) · 3 unmodified lines | ||
| 686 | 686 | */ |
| 687 | 687 | mnt_mask = READ_ONCE(real_mount(file->f_path.mnt)->mnt_fsnotify_mask); |
| 688 | 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 | 692 | return; |
| 693 | + } | |
| 691 | 694 | |
| 692 | 695 | /* Is parent watching for pre-content events on this file? */ |
| 693 | 696 | if (dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED) { |
| 694 | 697 | parent = dget_parent(dentry); |
| 695 | 698 | p_mask = fsnotify_inode_watches_children(d_inode(parent)); |
| 696 | 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 | 703 | return; |
| 704 | + } | |
| 699 | 705 | } |
| 700 | 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 | 709 | #endif |
| 704 | 710 | |
| @@ -905,7 +905,8 @@ static int do_dentry_open(struct file *f, · 904 unmodified lines | ||
| 905 | 905 | f->f_sb_err = file_sample_sb_err(f); |
| 906 | 906 | |
| 907 | 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 | 910 | f->f_op = &empty_fops; |
| 910 | 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 | 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 | − * change anything. | |
| 939 | + * If FMODE_NONOTIFY mode was already set for an fanotify fd or for a | |
| 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 | 943 | error = fsnotify_open_perm(f); |
| 943 | 944 | if (error) |
| 944 | 945 | goto cleanup_all; |
| @@ -1122,7 +1123,7 @@ struct file *dentry_open_nonotify(const struct path *path, int flags, · 177 unmodified lines | ||
| 1122 | 1123 | if (!IS_ERR(f)) { |
| 1123 | 1124 | int error; |
| 1124 | 1125 | |
| 1125 | − f->f_mode |= FMODE_NONOTIFY; | |
| 1126 | + file_set_fsnotify_mode(f, FMODE_NONOTIFY); | |
| 1126 | 1127 | error = vfs_open(path, f); |
| 1127 | 1128 | if (error) { |
| 1128 | 1129 | fput(f); |
| @@ -287,7 +287,6 @@ static bool pidfs_ioctl_valid(unsigned int cmd) · 286 unmodified lines | ||
| 287 | 287 | switch (cmd) { |
| 288 | 288 | case FS_IOC_GETVERSION: |
| 289 | 289 | case PIDFD_GET_CGROUP_NAMESPACE: |
| 290 | − case PIDFD_GET_INFO: | |
| 291 | 290 | case PIDFD_GET_IPC_NAMESPACE: |
| 292 | 291 | case PIDFD_GET_MNT_NAMESPACE: |
| 293 | 292 | case PIDFD_GET_NET_NAMESPACE: |
| @@ -300,6 +299,17 @@ static bool pidfs_ioctl_valid(unsigned int cmd) · 6 unmodified lines | ||
| 300 | 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 | 313 | return false; |
| 304 | 314 | } |
| 305 | 315 | |
| @@ -960,6 +960,12 @@ int create_pipe_files(struct file **res, int flags) · 959 unmodified lines | ||
| 960 | 960 | res[1] = f; |
| 961 | 961 | stream_open(inode, res[0]); |
| 962 | 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 | 969 | return 0; |
| 964 | 970 | } |
| 965 | 971 | |
| @@ -1524,7 +1524,7 @@ int vmcore_add_device_dump(struct vmcoredd_data *data) · 1523 unmodified lines | ||
| 1524 | 1524 | pr_warn_once("Unexpected adding of device dump\n"); |
| 1525 | 1525 | if (vmcore_open) { |
| 1526 | 1526 | ret = -EBUSY; |
| 1527 | − goto out_err; | |
| 1527 | + goto unlock; | |
| 1528 | 1528 | } |
| 1529 | 1529 | |
| 1530 | 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 | 1532 | mutex_unlock(&vmcore_mutex); |
| 1533 | 1533 | return 0; |
| 1534 | 1534 | |
| 1535 | +unlock: | |
| 1536 | + mutex_unlock(&vmcore_mutex); | |
| 1537 | + | |
| 1535 | 1538 | out_err: |
| 1536 | 1539 | vfree(buf); |
| 1537 | 1540 | vfree(dump); |
| @@ -253,6 +253,7 @@ struct cifs_cred { · 252 unmodified lines | ||
| 253 | 253 | struct cifs_open_info_data { |
| 254 | 254 | bool adjust_tz; |
| 255 | 255 | bool reparse_point; |
| 256 | + bool contains_posix_file_info; | |
| 256 | 257 | struct { |
| 257 | 258 | /* ioctl response buffer */ |
| 258 | 259 | struct { |
| @@ -357,7 +358,7 @@ struct smb_version_operations { · 98 unmodified lines | ||
| 357 | 358 | int (*handle_cancelled_mid)(struct mid_q_entry *, struct TCP_Server_Info *); |
| 358 | 359 | void (*downgrade_oplock)(struct TCP_Server_Info *server, |
| 359 | 360 | struct cifsInodeInfo *cinode, __u32 oplock, |
| 360 | − unsigned int epoch, bool *purge_cache); | |
| 361 | + __u16 epoch, bool *purge_cache); | |
| 361 | 362 | /* process transaction2 response */ |
| 362 | 363 | bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *, |
| 363 | 364 | char *, int); |
| @@ -552,12 +553,12 @@ struct smb_version_operations { · 188 unmodified lines | ||
| 552 | 553 | /* if we can do cache read operations */ |
| 553 | 554 | bool (*is_read_op)(__u32); |
| 554 | 555 | /* set oplock level for the inode */ |
| 555 | − void (*set_oplock_level)(struct cifsInodeInfo *, __u32, unsigned int, | |
| 556 | − bool *); | |
| 556 | + void (*set_oplock_level)(struct cifsInodeInfo *cinode, __u32 oplock, __u16 epoch, | |
| 557 | + bool *purge_cache); | |
| 557 | 558 | /* create lease context buffer for CREATE request */ |
| 558 | 559 | char * (*create_lease_buf)(u8 *lease_key, u8 oplock); |
| 559 | 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 | 562 | ssize_t (*copychunk_range)(const unsigned int, |
| 562 | 563 | struct cifsFileInfo *src_file, |
| 563 | 564 | struct cifsFileInfo *target_file, |
| @@ -1447,7 +1448,7 @@ struct cifs_fid { · 883 unmodified lines | ||
| 1447 | 1448 | __u8 create_guid[16]; |
| 1448 | 1449 | __u32 access; |
| 1449 | 1450 | struct cifs_pending_open *pending_open; |
| 1450 | − unsigned int epoch; | |
| 1451 | + __u16 epoch; | |
| 1451 | 1452 | #ifdef CONFIG_CIFS_DEBUG2 |
| 1452 | 1453 | __u64 mid; |
| 1453 | 1454 | #endif /* CIFS_DEBUG2 */ |
| @@ -1480,7 +1481,7 @@ struct cifsFileInfo { · 26 unmodified lines | ||
| 1480 | 1481 | bool oplock_break_cancelled:1; |
| 1481 | 1482 | bool status_file_deleted:1; /* file has been deleted */ |
| 1482 | 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 | 1485 | __u32 oplock_level; /* oplock/lease level from the lease break */ |
| 1485 | 1486 | int count; |
| 1486 | 1487 | spinlock_t file_info_lock; /* protects four flag/count fields above */ |
| @@ -1508,7 +1509,6 @@ struct cifs_io_parms { · 21 unmodified lines | ||
| 1508 | 1509 | struct cifs_io_request { |
| 1509 | 1510 | struct netfs_io_request rreq; |
| 1510 | 1511 | struct cifsFileInfo *cfile; |
| 1511 | − struct TCP_Server_Info *server; | |
| 1512 | 1512 | pid_t pid; |
| 1513 | 1513 | }; |
| 1514 | 1514 | |
| @@ -1577,7 +1577,7 @@ struct cifsInodeInfo { · 62 unmodified lines | ||
| 1577 | 1577 | spinlock_t open_file_lock; /* protects openFileList */ |
| 1578 | 1578 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ |
| 1579 | 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 | 1581 | #define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */ |
| 1582 | 1582 | #define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */ |
| 1583 | 1583 | #define CIFS_INODE_FLAG_UNUSED (2) /* Unused flag */ |
| @@ -2325,8 +2325,8 @@ struct smb2_compound_vars { · 741 unmodified lines | ||
| 2325 | 2325 | struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; |
| 2326 | 2326 | struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; |
| 2327 | 2327 | struct kvec close_iov; |
| 2328 | − struct smb2_file_rename_info rename_info; | |
| 2329 | − struct smb2_file_link_info link_info; | |
| 2328 | + struct smb2_file_rename_info_hdr rename_info; | |
| 2329 | + struct smb2_file_link_info_hdr link_info; | |
| 2330 | 2330 | struct kvec ea_iov; |
| 2331 | 2331 | }; |
| 2332 | 2332 | |
| @@ -150,25 +150,27 @@ again: · 149 unmodified lines | ||
| 150 | 150 | if (rc) |
| 151 | 151 | continue; |
| 152 | 152 | |
| 153 | − if (tgt.flags & DFSREF_STORAGE_SERVER) { | |
| 154 | − rc = cifs_mount_get_tcon(mnt_ctx); | |
| 155 | − if (!rc) | |
| 156 | − rc = cifs_is_path_remote(mnt_ctx); | |
| 153 | + rc = cifs_mount_get_tcon(mnt_ctx); | |
| 154 | + if (rc) { | |
| 155 | + if (tgt.server_type == DFS_TYPE_LINK && | |
| 156 | + DFS_INTERLINK(tgt.flags)) | |
| 157 | + rc = -EREMOTE; | |
| 158 | + } else { | |
| 159 | + rc = cifs_is_path_remote(mnt_ctx); | |
| 157 | 160 | if (!rc) { |
| 158 | 161 | ref_walk_set_tgt_hint(rw); |
| 159 | 162 | break; |
| 160 | 163 | } |
| 161 | − if (rc != -EREMOTE) | |
| 162 | − continue; | |
| 163 | 164 | } |
| 164 | − | |
| 165 | − rc = ref_walk_advance(rw); | |
| 166 | − if (!rc) { | |
| 167 | − rc = setup_dfs_ref(&tgt, rw); | |
| 168 | − if (rc) | |
| 169 | − break; | |
| 170 | − ref_walk_mark_end(rw); | |
| 171 | − goto again; | |
| 165 | + if (rc == -EREMOTE) { | |
| 166 | + rc = ref_walk_advance(rw); | |
| 167 | + if (!rc) { | |
| 168 | + rc = setup_dfs_ref(&tgt, rw); | |
| 169 | + if (rc) | |
| 170 | + break; | |
| 171 | + ref_walk_mark_end(rw); | |
| 172 | + goto again; | |
| 173 | + } | |
| 172 | 174 | } |
| 173 | 175 | } |
| 174 | 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 | 198 | #endif /* _CIFS_DFS_H */ |
| @@ -1136,33 +1136,19 @@ static bool is_ses_good(struct cifs_ses *ses) · 1135 unmodified lines | ||
| 1136 | 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 | 1139 | /* Refresh dfs referral of @ses */ |
| 1153 | 1140 | static void refresh_ses_referral(struct cifs_ses *ses) |
| 1154 | 1141 | { |
| 1155 | 1142 | struct cache_entry *ce; |
| 1156 | 1143 | unsigned int xid; |
| 1157 | − char *path; | |
| 1144 | + const char *path; | |
| 1158 | 1145 | int rc = 0; |
| 1159 | 1146 | |
| 1160 | 1147 | xid = get_xid(); |
| 1161 | 1148 | |
| 1162 | − path = get_ses_refpath(ses); | |
| 1149 | + path = dfs_ses_refpath(ses); | |
| 1163 | 1150 | if (IS_ERR(path)) { |
| 1164 | 1151 | rc = PTR_ERR(path); |
| 1165 | − path = NULL; | |
| 1166 | 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 | 1168 | out: |
| 1183 | 1169 | free_xid(xid); |
| 1184 | − kfree(path); | |
| 1185 | 1170 | } |
| 1186 | 1171 | |
| 1187 | 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 | 1216 | struct dfs_info3_param *refs = NULL; |
| 1232 | 1217 | struct cache_entry *ce; |
| 1233 | 1218 | struct cifs_ses *ses; |
| 1234 | − unsigned int xid; | |
| 1235 | 1219 | bool needs_refresh; |
| 1236 | − char *path; | |
| 1220 | + const char *path; | |
| 1221 | + unsigned int xid; | |
| 1237 | 1222 | int numrefs = 0; |
| 1238 | 1223 | int rc = 0; |
| 1239 | 1224 | |
| 1240 | 1225 | xid = get_xid(); |
| 1241 | 1226 | ses = tcon->ses; |
| 1242 | 1227 | |
| 1243 | − path = get_ses_refpath(ses); | |
| 1228 | + path = dfs_ses_refpath(ses); | |
| 1244 | 1229 | if (IS_ERR(path)) { |
| 1245 | 1230 | rc = PTR_ERR(path); |
| 1246 | − path = NULL; | |
| 1247 | 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 | 1256 | out: |
| 1273 | 1257 | free_xid(xid); |
| 1274 | − kfree(path); | |
| 1275 | 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 | 147 | struct netfs_io_request *rreq = subreq->rreq; |
| 148 | 148 | struct cifs_io_subrequest *rdata = container_of(subreq, struct cifs_io_subrequest, subreq); |
| 149 | 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 | 151 | struct cifs_sb_info *cifs_sb = CIFS_SB(rreq->inode->i_sb); |
| 152 | 152 | size_t size; |
| 153 | 153 | int rc = 0; |
| @@ -156,6 +156,8 @@ static int cifs_prepare_read(struct netfs_io_subrequest *subreq) · 2 unmodified lines | ||
| 156 | 156 | rdata->xid = get_xid(); |
| 157 | 157 | rdata->have_xid = true; |
| 158 | 158 | } |
| 159 | + | |
| 160 | + server = cifs_pick_channel(tlink_tcon(req->cfile->tlink)->ses); | |
| 159 | 161 | rdata->server = server; |
| 160 | 162 | |
| 161 | 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 | 200 | struct netfs_io_request *rreq = subreq->rreq; |
| 199 | 201 | struct cifs_io_subrequest *rdata = container_of(subreq, struct cifs_io_subrequest, subreq); |
| 200 | 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 | 204 | int rc = 0; |
| 203 | 205 | |
| 204 | 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 | 268 | open_file = file->private_data; |
| 267 | 269 | rreq->netfs_priv = file->private_data; |
| 268 | 270 | req->cfile = cifsFileInfo_get(open_file); |
| 269 | − req->server = cifs_pick_channel(tlink_tcon(req->cfile->tlink)->ses); | |
| 270 | 271 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
| 271 | 272 | req->pid = req->cfile->pid; |
| 272 | 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 | 1215 | rc = server->ops->parse_reparse_point(cifs_sb, |
| 1216 | 1216 | full_path, |
| 1217 | 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 | 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 | 1421 | struct cifs_fattr fattr = {}; |
| 1409 | 1422 | int rc; |
| 1410 | 1423 | |
| 1411 | − if (is_inode_cache_good(*inode)) { | |
| 1424 | + if (!data && is_inode_cache_good(*inode)) { | |
| 1412 | 1425 | cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); |
| 1413 | 1426 | return 0; |
| 1414 | 1427 | } |
| @@ -1507,7 +1520,7 @@ int smb311_posix_get_inode_info(struct inode **inode, · 92 unmodified lines | ||
| 1507 | 1520 | struct cifs_fattr fattr = {}; |
| 1508 | 1521 | int rc; |
| 1509 | 1522 | |
| 1510 | − if (is_inode_cache_good(*inode)) { | |
| 1523 | + if (!data && is_inode_cache_good(*inode)) { | |
| 1511 | 1524 | cifs_dbg(FYI, "No need to revalidate cached inode sizes\n"); |
| 1512 | 1525 | return 0; |
| 1513 | 1526 | } |
| @@ -1088,13 +1088,12 @@ int parse_reparse_point(struct reparse_data_buffer *buf, · 1087 unmodified lines | ||
| 1088 | 1088 | le32_to_cpu(buf->ReparseTag)); |
| 1089 | 1089 | return -EIO; |
| 1090 | 1090 | } |
| 1091 | − break; | |
| 1091 | + return 0; | |
| 1092 | 1092 | default: |
| 1093 | 1093 | cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n", |
| 1094 | 1094 | le32_to_cpu(buf->ReparseTag)); |
| 1095 | − break; | |
| 1095 | + return -EOPNOTSUPP; | |
| 1096 | 1096 | } |
| 1097 | − return 0; | |
| 1098 | 1097 | } |
| 1099 | 1098 | |
| 1100 | 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 | 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; | |
| 103 | − u32 attrs = le32_to_cpu(fi->Attributes); | |
| 102 | + u32 attrs; | |
| 104 | 103 | bool ret; |
| 105 | 104 | |
| 106 | − ret = data->reparse_point || (attrs & ATTR_REPARSE); | |
| 107 | − if (ret) | |
| 108 | − attrs |= ATTR_REPARSE; | |
| 109 | − fi->Attributes = cpu_to_le32(attrs); | |
| 105 | + if (data->contains_posix_file_info) { | |
| 106 | + struct smb311_posix_qinfo *fi = &data->posix_fi; | |
| 107 | + | |
| 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 | 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 | 377 | static void |
| 378 | 378 | cifs_downgrade_oplock(struct TCP_Server_Info *server, |
| 379 | 379 | struct cifsInodeInfo *cinode, __u32 oplock, |
| 380 | − unsigned int epoch, bool *purge_cache) | |
| 380 | + __u16 epoch, bool *purge_cache) | |
| 381 | 381 | { |
| 382 | 382 | cifs_set_oplock_level(cinode, oplock); |
| 383 | 383 | } |
| @@ -650,6 +650,7 @@ finished: · 649 unmodified lines | ||
| 650 | 650 | switch (cmds[i]) { |
| 651 | 651 | case SMB2_OP_QUERY_INFO: |
| 652 | 652 | idata = in_iov[i].iov_base; |
| 653 | + idata->contains_posix_file_info = false; | |
| 653 | 654 | if (rc == 0 && cfile && cfile->symlink_target) { |
| 654 | 655 | idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); |
| 655 | 656 | if (!idata->symlink_target) |
| @@ -673,6 +674,7 @@ finished: · 17 unmodified lines | ||
| 673 | 674 | break; |
| 674 | 675 | case SMB2_OP_POSIX_QUERY_INFO: |
| 675 | 676 | idata = in_iov[i].iov_base; |
| 677 | + idata->contains_posix_file_info = true; | |
| 676 | 678 | if (rc == 0 && cfile && cfile->symlink_target) { |
| 677 | 679 | idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); |
| 678 | 680 | if (!idata->symlink_target) |
| @@ -770,6 +772,7 @@ finished: · 91 unmodified lines | ||
| 770 | 772 | idata = in_iov[i].iov_base; |
| 771 | 773 | idata->reparse.io.iov = *iov; |
| 772 | 774 | idata->reparse.io.buftype = resp_buftype[i + 1]; |
| 775 | + idata->contains_posix_file_info = false; /* BB VERIFY */ | |
| 773 | 776 | rbuf = reparse_buf_ptr(iov); |
| 774 | 777 | if (IS_ERR(rbuf)) { |
| 775 | 778 | rc = PTR_ERR(rbuf); |
| @@ -791,6 +794,7 @@ finished: · 15 unmodified lines | ||
| 791 | 794 | case SMB2_OP_QUERY_WSL_EA: |
| 792 | 795 | if (!rc) { |
| 793 | 796 | idata = in_iov[i].iov_base; |
| 797 | + idata->contains_posix_file_info = false; | |
| 794 | 798 | qi_rsp = rsp_iov[i + 1].iov_base; |
| 795 | 799 | data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset); |
| 796 | 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 | 1001 | if (!data->symlink_target) |
| 1002 | 1002 | return -ENOMEM; |
| 1003 | 1003 | } |
| 1004 | + data->contains_posix_file_info = false; | |
| 1004 | 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 | 3905 | static void |
| 3905 | 3906 | smb2_downgrade_oplock(struct TCP_Server_Info *server, |
| 3906 | 3907 | struct cifsInodeInfo *cinode, __u32 oplock, |
| 3907 | − unsigned int epoch, bool *purge_cache) | |
| 3908 | + __u16 epoch, bool *purge_cache) | |
| 3908 | 3909 | { |
| 3909 | 3910 | server->ops->set_oplock_level(cinode, oplock, 0, NULL); |
| 3910 | 3911 | } |
| 3911 | 3912 | |
| 3912 | 3913 | static void |
| 3913 | 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 | 3917 | static void |
| 3917 | 3918 | smb3_downgrade_oplock(struct TCP_Server_Info *server, |
| 3918 | 3919 | struct cifsInodeInfo *cinode, __u32 oplock, |
| 3919 | − unsigned int epoch, bool *purge_cache) | |
| 3920 | + __u16 epoch, bool *purge_cache) | |
| 3920 | 3921 | { |
| 3921 | 3922 | unsigned int old_state = cinode->oplock; |
| 3922 | − unsigned int old_epoch = cinode->epoch; | |
| 3923 | + __u16 old_epoch = cinode->epoch; | |
| 3923 | 3924 | unsigned int new_state; |
| 3924 | 3925 | |
| 3925 | 3926 | if (epoch > old_epoch) { |
| @@ -3939,7 +3940,7 @@ smb3_downgrade_oplock(struct TCP_Server_Info *server, · 13 unmodified lines | ||
| 3939 | 3940 | |
| 3940 | 3941 | static void |
| 3941 | 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 | 3945 | oplock &= 0xFF; |
| 3945 | 3946 | cinode->lease_granted = false; |
| @@ -3963,7 +3964,7 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, · 17 unmodified lines | ||
| 3963 | 3964 | |
| 3964 | 3965 | static void |
| 3965 | 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 | 3969 | char message[5] = {0}; |
| 3969 | 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 | 4002 | static void |
| 4002 | 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 | 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 | 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 | 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 | 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 | 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 | 5147 | FILE_CREATE, CREATE_NOT_DIR | |
| 5147 | 5148 | CREATE_OPTION_SPECIAL, ACL_NO_MODE); |
| 5148 | 5149 | oparms.fid = &fid; |
| 5149 | − | |
| 5150 | + idata.contains_posix_file_info = false; | |
| 5150 | 5151 | rc = server->ops->open(xid, &oparms, &oplock, &idata); |
| 5151 | 5152 | if (rc) |
| 5152 | 5153 | goto out; |
| @@ -2169,7 +2169,7 @@ tcon_exit: · 2168 unmodified lines | ||
| 2169 | 2169 | |
| 2170 | 2170 | tcon_error_exit: |
| 2171 | 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 | 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 | 2330 | int smb2_parse_contexts(struct TCP_Server_Info *server, |
| 2331 | 2331 | struct kvec *rsp_iov, |
| 2332 | − unsigned int *epoch, | |
| 2332 | + __u16 *epoch, | |
| 2333 | 2333 | char *lease_key, __u8 *oplock, |
| 2334 | 2334 | struct smb2_file_all_info *buf, |
| 2335 | 2335 | struct create_posix_rsp *posix) |
| @@ -283,7 +283,7 @@ extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, · 282 unmodified lines | ||
| 283 | 283 | enum securityEnum); |
| 284 | 284 | int smb2_parse_contexts(struct TCP_Server_Info *server, |
| 285 | 285 | struct kvec *rsp_iov, |
| 286 | − unsigned int *epoch, | |
| 286 | + __u16 *epoch, | |
| 287 | 287 | char *lease_key, __u8 *oplock, |
| 288 | 288 | struct smb2_file_all_info *buf, |
| 289 | 289 | struct create_posix_rsp *posix); |
| @@ -1707,23 +1707,33 @@ struct smb2_file_internal_info { · 1706 unmodified lines | ||
| 1707 | 1707 | } __packed; /* level 6 Query */ |
| 1708 | 1708 | |
| 1709 | 1709 | struct smb2_file_rename_info { /* encoding of request for level 10 */ |
| 1710 | − __u8 ReplaceIfExists; /* 1 = replace existing target with new */ | |
| 1711 | − /* 0 = fail if target already exists */ | |
| 1712 | − __u8 Reserved[7]; | |
| 1713 | − __u64 RootDirectory; /* MBZ for network operations (why says spec?) */ | |
| 1714 | − __le32 FileNameLength; | |
| 1710 | + /* New members MUST be added within the struct_group() macro below. */ | |
| 1711 | + __struct_group(smb2_file_rename_info_hdr, __hdr, __packed, | |
| 1712 | + __u8 ReplaceIfExists; /* 1 = replace existing target with new */ | |
| 1713 | + /* 0 = fail if target already exists */ | |
| 1714 | + __u8 Reserved[7]; | |
| 1715 | + __u64 RootDirectory; /* MBZ for network operations (why says spec?) */ | |
| 1716 | + __le32 FileNameLength; | |
| 1717 | + ); | |
| 1715 | 1718 | char FileName[]; /* New name to be assigned */ |
| 1716 | 1719 | /* padding - overall struct size must be >= 24 so filename + pad >= 6 */ |
| 1717 | 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 | 1724 | struct smb2_file_link_info { /* encoding of request for level 11 */ |
| 1720 | − __u8 ReplaceIfExists; /* 1 = replace existing link with new */ | |
| 1721 | − /* 0 = fail if link already exists */ | |
| 1722 | − __u8 Reserved[7]; | |
| 1723 | − __u64 RootDirectory; /* MBZ for network operations (why says spec?) */ | |
| 1724 | − __le32 FileNameLength; | |
| 1725 | + /* New members MUST be added within the struct_group() macro below. */ | |
| 1726 | + __struct_group(smb2_file_link_info_hdr, __hdr, __packed, | |
| 1727 | + __u8 ReplaceIfExists; /* 1 = replace existing link with new */ | |
| 1728 | + /* 0 = fail if link already exists */ | |
| 1729 | + __u8 Reserved[7]; | |
| 1730 | + __u64 RootDirectory; /* MBZ for network operations (why says spec?) */ | |
| 1731 | + __le32 FileNameLength; | |
| 1732 | + ); | |
| 1725 | 1733 | char FileName[]; /* Name to be assigned to new link */ |
| 1726 | 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 | 1739 | * This level 18, although with struct with same name is different from cifs |
| @@ -159,6 +159,9 @@ · 158 unmodified lines | ||
| 159 | 159 | #define IO_REPARSE_TAG_LX_CHR 0x80000025 |
| 160 | 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 | 165 | /* fsctl flags */ |
| 163 | 166 | /* If Flags is set to this value, the request is an FSCTL not ioctl request */ |
| 164 | 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 | 281 | u32 request_mask) |
| 282 | 282 | { |
| 283 | 283 | int error = vfs_getattr(path, stat, request_mask, flags); |
| 284 | + if (error) | |
| 285 | + return error; | |
| 284 | 286 | |
| 285 | 287 | if (request_mask & STATX_MNT_ID_UNIQUE) { |
| 286 | 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 | 304 | if (S_ISBLK(stat->mode)) |
| 303 | 305 | bdev_statx(path, stat, request_mask); |
| 304 | 306 | |
| 305 | − return error; | |
| 307 | + return 0; | |
| 306 | 308 | } |
| 307 | 309 | |
| 308 | 310 | static int vfs_statx_fd(int fd, int flags, struct kstat *stat, |
| @@ -21,7 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 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 | 27 | static int follow_symlinks; |
| 27 | 28 | module_param(follow_symlinks, int, 0444); |
| @@ -3563,12 +3563,12 @@ xfs_bmap_btalloc_at_eof( · 3562 unmodified lines | ||
| 3563 | 3563 | int error; |
| 3564 | 3564 | |
| 3565 | 3565 | /* |
| 3566 | − * If there are already extents in the file, try an exact EOF block | |
| 3567 | − * allocation to extend the file as a contiguous extent. If that fails, | |
| 3568 | − * or it's the first allocation in a file, just try for a stripe aligned | |
| 3569 | − * allocation. | |
| 3566 | + * If there are already extents in the file, and xfs_bmap_adjacent() has | |
| 3567 | + * given a better blkno, try an exact EOF block allocation to extend the | |
| 3568 | + * file as a contiguous extent. If that fails, or it's the first | |
| 3569 | + * allocation in a file, just try for a stripe aligned allocation. | |
| 3570 | 3570 | */ |
| 3571 | − if (ap->offset) { | |
| 3571 | + if (ap->eof) { | |
| 3572 | 3572 | xfs_extlen_t nextminlen = 0; |
| 3573 | 3573 | |
| 3574 | 3574 | /* |
| @@ -3736,7 +3736,8 @@ xfs_bmap_btalloc_best_length( · 161 unmodified lines | ||
| 3736 | 3736 | int error; |
| 3737 | 3737 | |
| 3738 | 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 | 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 | 224 | bool xchk_dir_looks_zapped(struct xfs_inode *dp); |
| 225 | 225 | bool xchk_pptr_looks_zapped(struct xfs_inode *ip); |
| 226 | 226 | |
| 227 | −#ifdef CONFIG_XFS_ONLINE_REPAIR | |
| 228 | 227 | /* Decide if a repair is required. */ |
| 229 | 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 | 243 | return (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) && |
| 245 | 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 | 247 | int xchk_metadata_inode_forks(struct xfs_scrub *sc); |
| 253 | 248 | |
| @@ -1055,9 +1055,17 @@ xrep_dinode_check_dfork( · 1054 unmodified lines | ||
| 1055 | 1055 | return true; |
| 1056 | 1056 | break; |
| 1057 | 1057 | case S_IFREG: |
| 1058 | − if (fmt == XFS_DINODE_FMT_LOCAL) | |
| 1058 | + switch (fmt) { | |
| 1059 | + case XFS_DINODE_FMT_LOCAL: | |
| 1059 | 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 | 1069 | case S_IFLNK: |
| 1062 | 1070 | case S_IFDIR: |
| 1063 | 1071 | switch (fmt) { |
| @@ -191,7 +191,16 @@ int xrep_reset_metafile_resv(struct xfs_scrub *sc); · 190 unmodified lines | ||
| 191 | 191 | #else |
| 192 | 192 | |
| 193 | 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 | 205 | static inline int |
| 197 | 206 | xrep_attempt( |
| @@ -149,6 +149,18 @@ xchk_probe( · 148 unmodified lines | ||
| 149 | 149 | if (xchk_should_terminate(sc, &error)) |
| 150 | 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 | 164 | return 0; |
| 153 | 165 | } |
| 154 | 166 | |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include "xfs_reflink.h" |
| 20 | 20 | #include "xfs_errortag.h" |
| 21 | 21 | #include "xfs_error.h" |
| 22 | +#include "xfs_icache.h" | |
| 22 | 23 | |
| 23 | 24 | struct xfs_writepage_ctx { |
| 24 | 25 | struct iomap_writepage_ctx ctx; |
| @@ -528,12 +529,44 @@ xfs_vm_readahead( · 503 unmodified lines | ||
| 528 | 529 | } |
| 529 | 530 | |
| 530 | 531 | static int |
| 531 | −xfs_iomap_swapfile_activate( | |
| 532 | +xfs_vm_swap_activate( | |
| 532 | 533 | struct swap_info_struct *sis, |
| 533 | 534 | struct file *swap_file, |
| 534 | 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 | 570 | return iomap_swapfile_activate(sis, swap_file, span, |
| 538 | 571 | &xfs_read_iomap_ops); |
| 539 | 572 | } |
| @@ -549,11 +582,11 @@ const struct address_space_operations xfs_address_space_operations = { · 9 unmodified lines | ||
| 549 | 582 | .migrate_folio = filemap_migrate_folio, |
| 550 | 583 | .is_partially_uptodate = iomap_is_partially_uptodate, |
| 551 | 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 | 588 | const struct address_space_operations xfs_dax_aops = { |
| 556 | 589 | .writepages = xfs_dax_writepages, |
| 557 | 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 | 42 | * xfs_buf_rele: |
| 43 | 43 | * b_lock |
| 44 | − * pag_buf_lock | |
| 45 | − * lru_lock | |
| 44 | + * lru_lock | |
| 46 | 45 | * |
| 47 | 46 | * xfs_buftarg_drain_rele |
| 48 | 47 | * lru_lock |
| @@ -220,23 +219,25 @@ _xfs_buf_alloc( · 171 unmodified lines | ||
| 220 | 219 | */ |
| 221 | 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 | 228 | bp->b_hold = 1; |
| 229 | + sema_init(&bp->b_sema, 0); /* held, no waiters */ | |
| 230 | + | |
| 231 | + spin_lock_init(&bp->b_lock); | |
| 225 | 232 | atomic_set(&bp->b_lru_ref, 1); |
| 226 | 233 | init_completion(&bp->b_iowait); |
| 227 | 234 | INIT_LIST_HEAD(&bp->b_lru); |
| 228 | 235 | INIT_LIST_HEAD(&bp->b_list); |
| 229 | 236 | INIT_LIST_HEAD(&bp->b_li_list); |
| 230 | − sema_init(&bp->b_sema, 0); /* held, no waiters */ | |
| 231 | 237 | bp->b_target = target; |
| 232 | 238 | bp->b_mount = target->bt_mount; |
| 233 | 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 | 241 | error = xfs_buf_get_maps(bp, nmaps); |
| 241 | 242 | if (error) { |
| 242 | 243 | kmem_cache_free(xfs_buf_cache, bp); |
| @@ -502,7 +503,6 @@ int · 259 unmodified lines | ||
| 502 | 503 | xfs_buf_cache_init( |
| 503 | 504 | struct xfs_buf_cache *bch) |
| 504 | 505 | { |
| 505 | − spin_lock_init(&bch->bc_lock); | |
| 506 | 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 | 652 | if (error) |
| 653 | 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 | 659 | bp = rhashtable_lookup_get_insert_fast(&bch->bc_hash, |
| 657 | 660 | &new_bp->b_rhash_head, xfs_buf_hash_params); |
| 658 | 661 | if (IS_ERR(bp)) { |
| 662 | + rcu_read_unlock(); | |
| 659 | 663 | error = PTR_ERR(bp); |
| 660 | − spin_unlock(&bch->bc_lock); | |
| 661 | 664 | goto out_free_buf; |
| 662 | 665 | } |
| 663 | 666 | if (bp && xfs_buf_try_hold(bp)) { |
| 664 | 667 | /* found an existing buffer */ |
| 665 | − spin_unlock(&bch->bc_lock); | |
| 668 | + rcu_read_unlock(); | |
| 666 | 669 | error = xfs_buf_find_lock(bp, flags); |
| 667 | 670 | if (error) |
| 668 | 671 | xfs_buf_rele(bp); |
| @@ -670,10 +673,8 @@ xfs_buf_find_insert( · 1 unmodified line | ||
| 670 | 673 | *bpp = bp; |
| 671 | 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 | 678 | *bpp = new_bp; |
| 678 | 679 | return 0; |
| 679 | 680 | |
| @@ -1090,7 +1091,6 @@ xfs_buf_rele_cached( · 410 unmodified lines | ||
| 1090 | 1091 | } |
| 1091 | 1092 | |
| 1092 | 1093 | /* we are asked to drop the last reference */ |
| 1093 | − spin_lock(&bch->bc_lock); | |
| 1094 | 1094 | __xfs_buf_ioacct_dec(bp); |
| 1095 | 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 | 1102 | bp->b_state &= ~XFS_BSTATE_DISPOSE; |
| 1103 | 1103 | else |
| 1104 | 1104 | bp->b_hold--; |
| 1105 | − spin_unlock(&bch->bc_lock); | |
| 1106 | 1105 | } else { |
| 1107 | 1106 | bp->b_hold--; |
| 1108 | 1107 | /* |
| @@ -1120,7 +1119,6 @@ xfs_buf_rele_cached( · 11 unmodified lines | ||
| 1120 | 1119 | ASSERT(!(bp->b_flags & _XBF_DELWRI_Q)); |
| 1121 | 1120 | rhashtable_remove_fast(&bch->bc_hash, &bp->b_rhash_head, |
| 1122 | 1121 | xfs_buf_hash_params); |
| 1123 | − spin_unlock(&bch->bc_lock); | |
| 1124 | 1122 | if (pag) |
| 1125 | 1123 | xfs_perag_put(pag); |
| 1126 | 1124 | freebuf = true; |
| @@ -80,7 +80,6 @@ typedef unsigned int xfs_buf_flags_t; · 79 unmodified lines | ||
| 80 | 80 | #define XFS_BSTATE_IN_FLIGHT (1 << 1) /* I/O in flight */ |
| 81 | 81 | |
| 82 | 82 | struct xfs_buf_cache { |
| 83 | − spinlock_t bc_lock; | |
| 84 | 83 | struct rhashtable bc_hash; |
| 85 | 84 | }; |
| 86 | 85 | |
| @@ -329,22 +329,6 @@ out_trans_cancel: · 328 unmodified lines | ||
| 329 | 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 | 333 | * Performs necessary checks before doing a range exchange, having stabilized |
| 350 | 334 | * mutable inode attributes via i_rwsem. |
| @@ -355,11 +339,13 @@ xfs_exchange_range_checks( · 4 unmodified lines | ||
| 355 | 339 | unsigned int alloc_unit) |
| 356 | 340 | { |
| 357 | 341 | struct inode *inode1 = file_inode(fxr->file1); |
| 342 | + loff_t size1 = i_size_read(inode1); | |
| 358 | 343 | struct inode *inode2 = file_inode(fxr->file2); |
| 344 | + loff_t size2 = i_size_read(inode2); | |
| 359 | 345 | uint64_t allocmask = alloc_unit - 1; |
| 360 | 346 | int64_t test_len; |
| 361 | 347 | uint64_t blen; |
| 362 | − loff_t size1, size2, tmp; | |
| 348 | + loff_t tmp; | |
| 363 | 349 | int error; |
| 364 | 350 | |
| 365 | 351 | /* Don't touch certain kinds of inodes */ |
| @@ -368,24 +354,25 @@ xfs_exchange_range_checks( · 2 unmodified lines | ||
| 368 | 354 | if (IS_SWAPFILE(inode1) || IS_SWAPFILE(inode2)) |
| 369 | 355 | return -ETXTBSY; |
| 370 | 356 | |
| 371 | − size1 = i_size_read(inode1); | |
| 372 | − size2 = i_size_read(inode2); | |
| 373 | − | |
| 374 | 357 | /* Ranges cannot start after EOF. */ |
| 375 | 358 | if (fxr->file1_offset > size1 || fxr->file2_offset > size2) |
| 376 | 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 | 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 | 367 | fxr->length = max_t(int64_t, size1 - fxr->file1_offset, |
| 384 | 368 | size2 - fxr->file2_offset); |
| 385 | − | |
| 386 | − error = xfs_exchange_range_verify_area(fxr); | |
| 387 | − if (error) | |
| 388 | − return error; | |
| 369 | + } else { | |
| 370 | + /* | |
| 371 | + * Otherwise we require both ranges to end within EOF. | |
| 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 | 388 | check_add_overflow(fxr->file2_offset, fxr->length, &tmp)) |
| 402 | 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 | 392 | * Make sure we don't hit any file size limits. If we hit any size |
| 415 | 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 | 726 | struct inode *inode1 = file_inode(fxr->file1); |
| 749 | 727 | struct inode *inode2 = file_inode(fxr->file2); |
| 728 | + loff_t check_len = fxr->length; | |
| 750 | 729 | int ret; |
| 751 | 730 | |
| 752 | 731 | BUILD_BUG_ON(XFS_EXCHANGE_RANGE_ALL_FLAGS & |
| @@ -779,14 +758,18 @@ xfs_exchange_range( · 26 unmodified lines | ||
| 779 | 758 | return -EBADF; |
| 780 | 759 | |
| 781 | 760 | /* |
| 782 | − * If we're not exchanging to EOF, we can check the areas before | |
| 783 | − * stabilizing both files' i_size. | |
| 761 | + * If we're exchanging to EOF we can't calculate the length until taking | |
| 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)) { | |
| 786 | − ret = xfs_exchange_range_verify_area(fxr); | |
| 787 | − if (ret) | |
| 788 | − return ret; | |
| 789 | − } | |
| 765 | + if (fxr->flags & XFS_EXCHANGE_RANGE_TO_EOF) | |
| 766 | + check_len = 0; | |
| 767 | + ret = remap_verify_area(fxr->file1, fxr->file1_offset, check_len, true); | |
| 768 | + if (ret) | |
| 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 | 774 | /* Update cmtime if the fd/inode don't forbid it. */ |
| 792 | 775 | if (!(fxr->file1->f_mode & FMODE_NOCMTIME) && !IS_NOCMTIME(inode1)) |
| @@ -1404,8 +1404,11 @@ xfs_inactive( · 1403 unmodified lines | ||
| 1404 | 1404 | goto out; |
| 1405 | 1405 | |
| 1406 | 1406 | /* Try to clean out the cow blocks if there are any. */ |
| 1407 | − if (xfs_inode_has_cow_data(ip)) | |
| 1408 | − xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true); | |
| 1407 | + if (xfs_inode_has_cow_data(ip)) { | |
| 1408 | + error = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true); | |
| 1409 | + if (error) | |
| 1410 | + goto out; | |
| 1411 | + } | |
| 1409 | 1412 | |
| 1410 | 1413 | if (VFS_I(ip)->i_nlink != 0) { |
| 1411 | 1414 | /* |
| @@ -976,10 +976,8 @@ xfs_dax_write_iomap_end( · 975 unmodified lines | ||
| 976 | 976 | if (!xfs_is_cow_inode(ip)) |
| 977 | 977 | return 0; |
| 978 | 978 | |
| 979 | − if (!written) { | |
| 980 | − xfs_reflink_cancel_cow_range(ip, pos, length, true); | |
| 981 | − return 0; | |
| 982 | − } | |
| 979 | + if (!written) | |
| 980 | + return xfs_reflink_cancel_cow_range(ip, pos, length, true); | |
| 983 | 981 | |
| 984 | 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 | 103 | int |
| 82 | 104 | xfs_qm_newmount( |
| 83 | 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 | |
| 101 | − * the user to change the state of quota on the mount - | |
| 102 | − * this would generate a transaction on the ro device, | |
| 103 | − * which would lead to an I/O error and shutdown | |
| 122 | + * If the device itself is read-only and/or in norecovery | |
| 123 | + * mode, we can't allow the user to change the state of | |
| 124 | + * quota on the mount - this would generate a transaction | |
| 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)) || | |
| 107 | − (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || | |
| 108 | − (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || | |
| 109 | − (!gquotaondisk && XFS_IS_GQUOTA_ON(mp)) || | |
| 110 | − (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) || | |
| 111 | − (!pquotaondisk && XFS_IS_PQUOTA_ON(mp))) && | |
| 112 | − xfs_dev_is_read_only(mp, "changing quota state")) { | |
| 113 | − xfs_warn(mp, "please mount with%s%s%s%s.", | |
| 114 | − (!quotaondisk ? "out quota" : ""), | |
| 115 | − (uquotaondisk ? " usrquota" : ""), | |
| 116 | − (gquotaondisk ? " grpquota" : ""), | |
| 117 | − (pquotaondisk ? " prjquota" : "")); | |
| 129 | + if (xfs_qm_validate_state_change(mp, uquotaondisk, | |
| 130 | + gquotaondisk, pquotaondisk)) { | |
| 131 | + | |
| 132 | + if (xfs_has_metadir(mp)) | |
| 133 | + xfs_warn(mp, | |
| 134 | + "metadir enabled, please mount without any quota mount options"); | |
| 135 | + else | |
| 136 | + xfs_warn(mp, "please mount with%s%s%s%s.", | |
| 137 | + (!quotaondisk ? "out quota" : ""), | |
| 138 | + (uquotaondisk ? " usrquota" : ""), | |
| 139 | + (gquotaondisk ? " grpquota" : ""), | |
| 140 | + (pquotaondisk ? " prjquota" : "")); | |
| 118 | 141 | return -EPERM; |
| 119 | 142 | } |
| 120 | 143 | |
| @@ -1661,8 +1661,12 @@ xfs_fs_fill_super( · 1660 unmodified lines | ||
| 1661 | 1661 | #endif |
| 1662 | 1662 | } |
| 1663 | 1663 | |
| 1664 | − /* Filesystem claims it needs repair, so refuse the mount. */ | |
| 1665 | − if (xfs_has_needsrepair(mp)) { | |
| 1664 | + /* | |
| 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 | 1670 | xfs_warn(mp, "Filesystem needs repair. Please run xfs_repair."); |
| 1667 | 1671 | error = -EFSCORRUPTED; |
| 1668 | 1672 | goto out_free_sb; |
| @@ -1038,6 +1038,7 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG) · 1037 unmodified lines | ||
| 1038 | 1038 | *(.discard) \ |
| 1039 | 1039 | *(.discard.*) \ |
| 1040 | 1040 | *(.export_symbol) \ |
| 1041 | + *(.no_trim_symbol) \ | |
| 1041 | 1042 | *(.modinfo) \ |
| 1042 | 1043 | /* ld.bfd warns about .gnu.version* even when not emitted */ \ |
| 1043 | 1044 | *(.gnu.version*) \ |
| @@ -359,6 +359,7 @@ · 358 unmodified lines | ||
| 359 | 359 | # define DP_DSC_BITS_PER_PIXEL_1_4 0x2 |
| 360 | 360 | # define DP_DSC_BITS_PER_PIXEL_1_2 0x3 |
| 361 | 361 | # define DP_DSC_BITS_PER_PIXEL_1_1 0x4 |
| 362 | +# define DP_DSC_BITS_PER_PIXEL_MASK 0x7 | |
| 362 | 363 | |
| 363 | 364 | #define DP_PSR_SUPPORT 0x070 /* XXX 1.2? */ |
| 364 | 365 | # define DP_PSR_IS_SUPPORTED 1 |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | ||
| 32 | 32 | #include <linux/dynamic_debug.h> |
| 33 | 33 | |
| 34 | 34 | #include <drm/drm.h> |
| 35 | +#include <drm/drm_device.h> | |
| 35 | 36 | |
| 36 | 37 | struct debugfs_regset32; |
| 37 | 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 | 861 | void (*complete)(struct io_comp_batch *)) |
| 862 | 862 | { |
| 863 | 863 | /* |
| 864 | − * blk_mq_end_request_batch() can't end request allocated from | |
| 865 | − * sched tags | |
| 864 | + * Check various conditions that exclude batch processing: | |
| 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 || | |
| 868 | − (req->end_io && !blk_rq_is_passthrough(req))) | |
| 870 | + if (!iob) | |
| 869 | 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 | 881 | if (!iob->complete) |
| 872 | 882 | iob->complete = complete; |
| @@ -71,9 +71,6 @@ enum { · 70 unmodified lines | ||
| 71 | 71 | |
| 72 | 72 | /* Cgroup is frozen. */ |
| 73 | 73 | CGRP_FROZEN, |
| 74 | − | |
| 75 | − /* Control group has to be killed. */ | |
| 76 | − CGRP_KILL, | |
| 77 | 74 | }; |
| 78 | 75 | |
| 79 | 76 | /* cgroup_root->flags */ |
| @@ -461,6 +458,9 @@ struct cgroup { · 381 unmodified lines | ||
| 461 | 458 | |
| 462 | 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 | 464 | struct kernfs_node *kn; /* cgroup kernfs entry */ |
| 465 | 465 | struct cgroup_file procs_file; /* handle for "cgroup.procs" */ |
| 466 | 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 | 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 | 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 | 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 | 254 | * This returns a constant expression while determining if an argument is |
| 249 | 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 | 114 | #define EFI_MAX_MEMORY_TYPE 16 |
| 115 | 115 | |
| 116 | 116 | /* Attribute values: */ |
| 117 | −#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ | |
| 118 | −#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ | |
| 119 | −#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ | |
| 120 | −#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ | |
| 121 | −#define EFI_MEMORY_UCE ((u64)0x0000000000000010ULL) /* uncached, exported */ | |
| 122 | −#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ | |
| 123 | −#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ | |
| 124 | −#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ | |
| 125 | −#define EFI_MEMORY_NV ((u64)0x0000000000008000ULL) /* non-volatile */ | |
| 126 | −#define EFI_MEMORY_MORE_RELIABLE \ | |
| 127 | − ((u64)0x0000000000010000ULL) /* higher reliability */ | |
| 128 | −#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */ | |
| 129 | −#define EFI_MEMORY_SP ((u64)0x0000000000040000ULL) /* soft reserved */ | |
| 130 | −#define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL) /* supports encryption */ | |
| 131 | −#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ | |
| 117 | +#define EFI_MEMORY_UC BIT_ULL(0) /* uncached */ | |
| 118 | +#define EFI_MEMORY_WC BIT_ULL(1) /* write-coalescing */ | |
| 119 | +#define EFI_MEMORY_WT BIT_ULL(2) /* write-through */ | |
| 120 | +#define EFI_MEMORY_WB BIT_ULL(3) /* write-back */ | |
| 121 | +#define EFI_MEMORY_UCE BIT_ULL(4) /* uncached, exported */ | |
| 122 | +#define EFI_MEMORY_WP BIT_ULL(12) /* write-protect */ | |
| 123 | +#define EFI_MEMORY_RP BIT_ULL(13) /* read-protect */ | |
| 124 | +#define EFI_MEMORY_XP BIT_ULL(14) /* execute-protect */ | |
| 125 | +#define EFI_MEMORY_NV BIT_ULL(15) /* non-volatile */ | |
| 126 | +#define EFI_MEMORY_MORE_RELIABLE BIT_ULL(16) /* higher reliability */ | |
| 127 | +#define EFI_MEMORY_RO BIT_ULL(17) /* read-only */ | |
| 128 | +#define EFI_MEMORY_SP BIT_ULL(18) /* soft reserved */ | |
| 129 | +#define EFI_MEMORY_CPU_CRYPTO BIT_ULL(19) /* supports encryption */ | |
| 130 | +#define EFI_MEMORY_HOT_PLUGGABLE BIT_ULL(20) /* supports unplugging at runtime */ | |
| 131 | +#define EFI_MEMORY_RUNTIME BIT_ULL(63) /* range requires runtime mapping */ | |
| 132 | + | |
| 132 | 133 | #define EFI_MEMORY_DESCRIPTOR_VERSION 1 |
| 133 | 134 | |
| 134 | 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 | 222 | #define FMODE_FSNOTIFY_HSM(mode) 0 |
| 223 | 223 | #endif |
| 224 | 224 | |
| 225 | − | |
| 226 | 225 | /* |
| 227 | 226 | * Attribute flags. These should be or-ed together to figure out what |
| 228 | 227 | * has been changed! |
| @@ -791,6 +790,19 @@ struct inode { · 562 unmodified lines | ||
| 791 | 790 | |
| 792 | 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 | 806 | inode->i_link = link; |
| 795 | 807 | inode->i_linklen = linklen; |
| 796 | 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 | 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 | 3161 | static inline bool inode_is_open_for_write(const struct inode *inode) |
| 3144 | 3162 | { |
| 3145 | 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 | 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 | 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 | 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 | 125 | ktime_t softirq_expires_next; |
| 126 | 126 | struct hrtimer *softirq_next_timer; |
| 127 | 127 | struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES]; |
| 128 | + call_single_data_t csd; | |
| 128 | 129 | } ____cacheline_aligned; |
| 129 | 130 | |
| 130 | 131 | |
| @@ -244,6 +244,7 @@ enum i2c_driver_flags { · 243 unmodified lines | ||
| 244 | 244 | * @id_table: List of I2C devices supported by this driver |
| 245 | 245 | * @detect: Callback for device detection |
| 246 | 246 | * @address_list: The I2C addresses to probe (for detect) |
| 247 | + * @clients: List of detected clients we created (for i2c-core use only) | |
| 247 | 248 | * @flags: A bitmask of flags defined in &enum i2c_driver_flags |
| 248 | 249 | * |
| 249 | 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 | 299 | /* Device detection callback for automatic device creation */ |
| 299 | 300 | int (*detect)(struct i2c_client *client, struct i2c_board_info *info); |
| 300 | 301 | const unsigned short *address_list; |
| 302 | + struct list_head clients; | |
| 301 | 303 | |
| 302 | 304 | u32 flags; |
| 303 | 305 | }; |
| @@ -313,6 +315,8 @@ struct i2c_driver { · 9 unmodified lines | ||
| 313 | 315 | * @dev: Driver model device node for the slave. |
| 314 | 316 | * @init_irq: IRQ that was set at initialization |
| 315 | 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 | 320 | * @slave_cb: Callback when I2C slave mode of an adapter is used. The adapter |
| 317 | 321 | * calls it to pass on slave events to the slave driver. |
| 318 | 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 | 336 | #define I2C_CLIENT_SLAVE 0x20 /* we are the slave */ |
| 333 | 337 | #define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */ |
| 334 | 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 | 339 | #define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */ |
| 338 | 340 | /* Must match I2C_M_STOP|IGNORE_NAK */ |
| 339 | 341 | |
| @@ -345,6 +347,7 @@ struct i2c_client { · 5 unmodified lines | ||
| 345 | 347 | struct device dev; /* the device structure */ |
| 346 | 348 | int init_irq; /* irq set at initialization */ |
| 347 | 349 | int irq; /* irq issued by device */ |
| 350 | + struct list_head detected; | |
| 348 | 351 | #if IS_ENABLED(CONFIG_I2C_SLAVE) |
| 349 | 352 | i2c_slave_cb_t slave_cb; /* callback for slave mode */ |
| 350 | 353 | #endif |
| @@ -751,6 +754,9 @@ struct i2c_adapter { · 400 unmodified lines | ||
| 751 | 754 | char name[48]; |
| 752 | 755 | struct completion dev_released; |
| 753 | 756 | |
| 757 | + struct mutex userspace_clients_lock; | |
| 758 | + struct list_head userspace_clients; | |
| 759 | + | |
| 754 | 760 | struct i2c_bus_recovery_info *bus_recovery_info; |
| 755 | 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 | 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 | 542 | extern unsigned long __usecs_to_jiffies(const unsigned int u); |
| 543 | 543 | #if !(USEC_PER_SEC % HZ) |
| @@ -1615,7 +1615,6 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu); · 1614 unmodified lines | ||
| 1615 | 1615 | bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu); |
| 1616 | 1616 | bool kvm_arch_dy_has_pending_interrupt(struct kvm_vcpu *vcpu); |
| 1617 | 1617 | bool kvm_arch_vcpu_preempted_in_kernel(struct kvm_vcpu *vcpu); |
| 1618 | −int kvm_arch_post_init_vm(struct kvm *kvm); | |
| 1619 | 1618 | void kvm_arch_pre_destroy_vm(struct kvm *kvm); |
| 1620 | 1619 | void kvm_arch_create_vm_debugfs(struct kvm *kvm); |
| 1621 | 1620 | |
| @@ -37,12 +37,13 @@ struct lockref { · 36 unmodified lines | ||
| 37 | 37 | /** |
| 38 | 38 | * lockref_init - Initialize a lockref |
| 39 | 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 | 45 | spin_lock_init(&lockref->lock); |
| 45 | − lockref->count = count; | |
| 46 | + lockref->count = 1; | |
| 46 | 47 | } |
| 47 | 48 | |
| 48 | 49 | void lockref_get(struct lockref *lockref); |
| @@ -306,7 +306,10 @@ extern int modules_disabled; /* for sysctl */ · 305 unmodified lines | ||
| 306 | 306 | /* Get/put a kernel symbol (calls must be symmetric) */ |
| 307 | 307 | void *__symbol_get(const char *symbol); |
| 308 | 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 | 314 | /* modules using other modules: kdb wants to see this. */ |
| 312 | 315 | struct module_use { |
| @@ -2663,6 +2663,12 @@ struct net *dev_net(const struct net_device *dev) · 2662 unmodified lines | ||
| 2663 | 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 | 2672 | static inline |
| 2667 | 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 | 2910 | struct pcpu_dstats { |
| 2905 | 2911 | u64_stats_t rx_packets; |
| 2906 | 2912 | u64_stats_t rx_bytes; |
| 2907 | − u64_stats_t rx_drops; | |
| 2908 | 2913 | u64_stats_t tx_packets; |
| 2909 | 2914 | u64_stats_t tx_bytes; |
| 2915 | + u64_stats_t rx_drops; | |
| 2910 | 2916 | u64_stats_t tx_drops; |
| 2911 | 2917 | struct u64_stats_sync syncp; |
| 2912 | 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 | 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 | 3280 | struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type, |
| 3273 | 3281 | const char *hwaddr); |
| 3274 | 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 | 4117 | gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb); |
| 4110 | 4118 | void napi_gro_flush(struct napi_struct *napi, bool flush_old); |
| 4111 | 4119 | struct sk_buff *napi_get_frags(struct napi_struct *napi); |
| 4112 | −void napi_get_frags_check(struct napi_struct *napi); | |
| 4113 | 4120 | gro_result_t napi_gro_frags(struct napi_struct *napi); |
| 4114 | 4121 | |
| 4115 | 4122 | static inline void napi_free_frags(struct napi_struct *napi) |
| @@ -278,7 +278,7 @@ struct netfs_io_request { · 277 unmodified lines | ||
| 278 | 278 | #define NETFS_RREQ_PAUSE 11 /* Pause subrequest generation */ |
| 279 | 279 | #define NETFS_RREQ_USE_IO_ITER 12 /* Use ->io_iter rather than ->i_pages */ |
| 280 | 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 | 282 | #define NETFS_RREQ_USE_PGPRIV2 31 /* [DEPRECATED] Use PG_private_2 to mark |
| 283 | 283 | * write to cache on read */ |
| 284 | 284 | const struct netfs_request_ops *netfs_ops; |
| @@ -3134,6 +3134,7 @@ · 3133 unmodified lines | ||
| 3134 | 3134 | #define PCI_DEVICE_ID_INTEL_HDA_LNL_P 0xa828 |
| 3135 | 3135 | #define PCI_DEVICE_ID_INTEL_S21152BB 0xb152 |
| 3136 | 3136 | #define PCI_DEVICE_ID_INTEL_HDA_BMG 0xe2f7 |
| 3137 | +#define PCI_DEVICE_ID_INTEL_HDA_PTL_H 0xe328 | |
| 3137 | 3138 | #define PCI_DEVICE_ID_INTEL_HDA_PTL 0xe428 |
| 3138 | 3139 | #define PCI_DEVICE_ID_INTEL_HDA_CML_R 0xf0c8 |
| 3139 | 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 | 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 | 827 | * sev_platform_init - perform SEV INIT command |
| 819 | 828 | * |
| @@ -43,6 +43,7 @@ struct kernel_clone_args { · 42 unmodified lines | ||
| 43 | 43 | void *fn_arg; |
| 44 | 44 | struct cgroup *cgrp; |
| 45 | 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 | 91 | struct sk_psock_progs progs; |
| 92 | 92 | #if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) |
| 93 | 93 | struct strparser strp; |
| 94 | + u32 copied_seq; | |
| 95 | + u32 ingress_bytes; | |
| 94 | 96 | #endif |
| 95 | 97 | struct sk_buff_head ingress_skb; |
| 96 | 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 | 414 | * must be discoverable by the compiler. |
| 415 | 415 | */ |
| 416 | 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 | 419 | const size_t _src_len = __builtin_object_size(src, 1); \ |
| 419 | 420 | \ |
| 420 | 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 | 438 | * must be discoverable by the compiler. |
| 438 | 439 | */ |
| 439 | 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 | 443 | const size_t _src_len = __builtin_object_size(src, 1); \ |
| 442 | 444 | \ |
| 443 | 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 | 458 | * Note that sizes of @dest and @src must be known at compile-time. |
| 457 | 459 | */ |
| 458 | 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 | 463 | const size_t _src_len = __builtin_object_size(src, 1); \ |
| 461 | 464 | const size_t _src_chars = strnlen(src, _src_len); \ |
| 462 | 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 | 484 | * Note that sizes of @dest and @src must be known at compile-time. |
| 482 | 485 | */ |
| 483 | 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 | 489 | const size_t _src_len = __builtin_object_size(src, 1); \ |
| 486 | 490 | const size_t _src_chars = strnlen(src, _src_len); \ |
| 487 | 491 | const size_t _copy_len = min(_dest_len - 1, _src_chars); \ |
| @@ -668,7 +668,7 @@ struct l2cap_conn { · 667 unmodified lines | ||
| 668 | 668 | struct l2cap_chan *smp; |
| 669 | 669 | |
| 670 | 670 | struct list_head chan_l; |
| 671 | − struct mutex chan_lock; | |
| 671 | + struct mutex lock; | |
| 672 | 672 | struct kref ref; |
| 673 | 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 | 970 | void l2cap_send_conn_req(struct l2cap_chan *chan); |
| 971 | 971 | |
| 972 | 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 | 974 | void l2cap_conn_put(struct l2cap_conn *conn); |
| 974 | 975 | |
| 975 | 976 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); |
| @@ -11,6 +11,9 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <net/udp.h> |
| 12 | 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 | 17 | struct napi_gro_cb { |
| 15 | 18 | union { |
| 16 | 19 | struct { |
| @@ -471,9 +471,12 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, · 470 unmodified lines | ||
| 471 | 471 | bool forwarding) |
| 472 | 472 | { |
| 473 | 473 | const struct rtable *rt = dst_rtable(dst); |
| 474 | − struct net *net = dev_net(dst->dev); | |
| 475 | − unsigned int mtu; | |
| 474 | + unsigned int mtu, res; | |
| 475 | + struct net *net; | |
| 476 | + | |
| 477 | + rcu_read_lock(); | |
| 476 | 478 | |
| 479 | + net = dev_net_rcu(dst->dev); | |
| 477 | 480 | if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) || |
| 478 | 481 | ip_mtu_locked(dst) || |
| 479 | 482 | !forwarding) { |
| @@ -497,7 +500,11 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, · 17 unmodified lines | ||
| 497 | 500 | out: |
| 498 | 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 | 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 | 198 | if (netif_is_l3_slave(dev)) { |
| 199 | 199 | struct net_device *master; |
| 200 | 200 | |
| 201 | + rcu_read_lock(); | |
| 201 | 202 | master = netdev_master_upper_dev_get_rcu(dev); |
| 202 | 203 | if (master && master->l3mdev_ops->l3mdev_l3_out) |
| 203 | 204 | skb = master->l3mdev_ops->l3mdev_l3_out(master, sk, |
| 204 | 205 | skb, proto); |
| 206 | + rcu_read_unlock(); | |
| 205 | 207 | } |
| 206 | 208 | |
| 207 | 209 | return skb; |
| @@ -297,6 +297,7 @@ static inline int check_net(const struct net *net) · 296 unmodified lines | ||
| 297 | 297 | } |
| 298 | 298 | |
| 299 | 299 | void net_drop_ns(void *); |
| 300 | +void net_passive_dec(struct net *net); | |
| 300 | 301 | |
| 301 | 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 | 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 | 335 | #endif |
| 330 | 336 | |
| 337 | +static inline void net_passive_inc(struct net *net) | |
| 338 | +{ | |
| 339 | + refcount_inc(&net->passive); | |
| 340 | +} | |
| 341 | + | |
| 331 | 342 | /* Returns true if the netns initialization is completed successfully */ |
| 332 | 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 | 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 | 414 | #ifdef CONFIG_NET_NS |
| 404 | 415 | return rcu_dereference(pnet->net); |
| @@ -382,10 +382,15 @@ static inline int inet_iif(const struct sk_buff *skb) · 381 unmodified lines | ||
| 382 | 382 | static inline int ip4_dst_hoplimit(const struct dst_entry *dst) |
| 383 | 383 | { |
| 384 | 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 | 391 | hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl); |
| 392 | + rcu_read_unlock(); | |
| 393 | + } | |
| 389 | 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 | 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 | 856 | u64_stats_update_begin(&bstats->syncp); |
| 857 | 857 | u64_stats_add(&bstats->bytes, bytes); |
| @@ -43,6 +43,8 @@ struct strparser; · 42 unmodified lines | ||
| 43 | 43 | struct strp_callbacks { |
| 44 | 44 | int (*parse_msg)(struct strparser *strp, struct sk_buff *skb); |
| 45 | 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 | 48 | int (*read_sock_done)(struct strparser *strp, int err); |
| 47 | 49 | void (*abort_parser)(struct strparser *strp, int err); |
| 48 | 50 | void (*lock)(struct strparser *strp); |
| @@ -41,6 +41,7 @@ · 40 unmodified lines | ||
| 41 | 41 | #include <net/inet_ecn.h> |
| 42 | 42 | #include <net/dst.h> |
| 43 | 43 | #include <net/mptcp.h> |
| 44 | +#include <net/xfrm.h> | |
| 44 | 45 | |
| 45 | 46 | #include <linux/seq_file.h> |
| 46 | 47 | #include <linux/memcontrol.h> |
| @@ -683,6 +684,19 @@ void tcp_fin(struct sock *sk); · 636 unmodified lines | ||
| 683 | 684 | void tcp_check_space(struct sock *sk); |
| 684 | 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 | 700 | /* tcp_timer.c */ |
| 687 | 701 | void tcp_init_xmit_timers(struct sock *); |
| 688 | 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 | 743 | /* Read 'sendfile()'-style from a TCP socket */ |
| 730 | 744 | int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, |
| 731 | 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 | 749 | int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor); |
| 733 | 750 | struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off); |
| 734 | 751 | void tcp_read_done(struct sock *sk, size_t len); |
| @@ -2599,6 +2616,11 @@ struct sk_psock; · 1864 unmodified lines | ||
| 2599 | 2616 | #ifdef CONFIG_BPF_SYSCALL |
| 2600 | 2617 | int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore); |
| 2601 | 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 | 2624 | #endif /* CONFIG_BPF_SYSCALL */ |
| 2603 | 2625 | |
| 2604 | 2626 | #ifdef CONFIG_INET |
| @@ -99,7 +99,7 @@ · 98 unmodified lines | ||
| 99 | 99 | EM(netfs_sreq_trace_limited, "LIMIT") \ |
| 100 | 100 | EM(netfs_sreq_trace_need_clear, "N-CLR") \ |
| 101 | 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 | 103 | EM(netfs_sreq_trace_prepare, "PREP ") \ |
| 104 | 104 | EM(netfs_sreq_trace_prep_failed, "PRPFL") \ |
| 105 | 105 | EM(netfs_sreq_trace_progress, "PRGRS") \ |
| @@ -108,7 +108,9 @@ · 2 unmodified lines | ||
| 108 | 108 | EM(netfs_sreq_trace_short, "SHORT") \ |
| 109 | 109 | EM(netfs_sreq_trace_split, "SPLIT") \ |
| 110 | 110 | EM(netfs_sreq_trace_submit, "SUBMT") \ |
| 111 | + EM(netfs_sreq_trace_superfluous, "SPRFL") \ | |
| 111 | 112 | EM(netfs_sreq_trace_terminated, "TERM ") \ |
| 113 | + EM(netfs_sreq_trace_wait_for, "_WAIT") \ | |
| 112 | 114 | EM(netfs_sreq_trace_write, "WRITE") \ |
| 113 | 115 | EM(netfs_sreq_trace_write_skip, "SKIP ") \ |
| 114 | 116 | E_(netfs_sreq_trace_write_term, "WTERM") |
| @@ -219,6 +219,7 @@ · 218 unmodified lines | ||
| 219 | 219 | EM(rxrpc_conn_get_conn_input, "GET inp-conn") \ |
| 220 | 220 | EM(rxrpc_conn_get_idle, "GET idle ") \ |
| 221 | 221 | EM(rxrpc_conn_get_poke_abort, "GET pk-abort") \ |
| 222 | + EM(rxrpc_conn_get_poke_secured, "GET secured ") \ | |
| 222 | 223 | EM(rxrpc_conn_get_poke_timer, "GET poke ") \ |
| 223 | 224 | EM(rxrpc_conn_get_service_conn, "GET svc-conn") \ |
| 224 | 225 | EM(rxrpc_conn_new_client, "NEW client ") \ |
| @@ -411,13 +411,20 @@ struct drm_amdgpu_gem_userptr { · 410 unmodified lines | ||
| 411 | 411 | /* GFX12 and later: */ |
| 412 | 412 | #define AMDGPU_TILING_GFX12_SWIZZLE_MODE_SHIFT 0 |
| 413 | 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 | 415 | #define AMDGPU_TILING_GFX12_DCC_MAX_COMPRESSED_BLOCK_SHIFT 3 |
| 416 | 416 | #define AMDGPU_TILING_GFX12_DCC_MAX_COMPRESSED_BLOCK_MASK 0x3 /* 0:64B, 1:128B, 2:256B */ |
| 417 | 417 | #define AMDGPU_TILING_GFX12_DCC_NUMBER_TYPE_SHIFT 5 |
| 418 | 418 | #define AMDGPU_TILING_GFX12_DCC_NUMBER_TYPE_MASK 0x7 /* CB_COLOR0_INFO.NUMBER_TYPE */ |
| 419 | 419 | #define AMDGPU_TILING_GFX12_DCC_DATA_FORMAT_SHIFT 8 |
| 420 | 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 | 429 | /* Set/Get helpers for tiling flags. */ |
| 423 | 430 | #define AMDGPU_TILING_SET(field, value) \ |
| @@ -682,6 +682,7 @@ enum ethtool_link_ext_substate_module { · 681 unmodified lines | ||
| 682 | 682 | * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics |
| 683 | 683 | * @ETH_SS_STATS_RMON: names of RMON statistics |
| 684 | 684 | * @ETH_SS_STATS_PHY: names of PHY(dev) statistics |
| 685 | + * @ETH_SS_TS_FLAGS: hardware timestamping flags | |
| 685 | 686 | * |
| 686 | 687 | * @ETH_SS_COUNT: number of defined string sets |
| 687 | 688 | */ |
| @@ -708,6 +709,7 @@ enum ethtool_stringset { · 20 unmodified lines | ||
| 708 | 709 | ETH_SS_STATS_ETH_CTRL, |
| 709 | 710 | ETH_SS_STATS_RMON, |
| 710 | 711 | ETH_SS_STATS_PHY, |
| 712 | + ETH_SS_TS_FLAGS, | |
| 711 | 713 | |
| 712 | 714 | /* add new constants above here */ |
| 713 | 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 | 38 | #define TS_COMM_LEN 32 /* should be >= TASK_COMM_LEN |
| 39 | 39 | * in linux/sched.h */ |
| 40 | 40 | |
| @@ -30,7 +30,6 @@ enum thermal_genl_attr { · 29 unmodified lines | ||
| 30 | 30 | THERMAL_GENL_ATTR_TZ, |
| 31 | 31 | THERMAL_GENL_ATTR_TZ_ID, |
| 32 | 32 | THERMAL_GENL_ATTR_TZ_TEMP, |
| 33 | − THERMAL_GENL_ATTR_TZ_PREV_TEMP, | |
| 34 | 33 | THERMAL_GENL_ATTR_TZ_TRIP, |
| 35 | 34 | THERMAL_GENL_ATTR_TZ_TRIP_ID, |
| 36 | 35 | THERMAL_GENL_ATTR_TZ_TRIP_TYPE, |
| @@ -54,6 +53,7 @@ enum thermal_genl_attr { · 17 unmodified lines | ||
| 54 | 53 | THERMAL_GENL_ATTR_THRESHOLD, |
| 55 | 54 | THERMAL_GENL_ATTR_THRESHOLD_TEMP, |
| 56 | 55 | THERMAL_GENL_ATTR_THRESHOLD_DIRECTION, |
| 56 | + THERMAL_GENL_ATTR_TZ_PREV_TEMP, | |
| 57 | 57 | __THERMAL_GENL_ATTR_MAX, |
| 58 | 58 | }; |
| 59 | 59 | #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1) |
| @@ -25,7 +25,7 @@ struct virtio_snd_config { · 24 unmodified lines | ||
| 25 | 25 | __le32 streams; |
| 26 | 26 | /* # of available channel maps */ |
| 27 | 27 | __le32 chmaps; |
| 28 | − /* # of available control elements */ | |
| 28 | + /* # of available control elements (if VIRTIO_SND_F_CTLS) */ | |
| 29 | 29 | __le32 controls; |
| 30 | 30 | }; |
| 31 | 31 | |
| @@ -385,8 +385,8 @@ enum { · 384 unmodified lines | ||
| 385 | 385 | |
| 386 | 386 | /* Possible values for dExtendedUFSFeaturesSupport */ |
| 387 | 387 | enum { |
| 388 | − UFS_DEV_LOW_TEMP_NOTIF = BIT(4), | |
| 389 | − UFS_DEV_HIGH_TEMP_NOTIF = BIT(5), | |
| 388 | + UFS_DEV_HIGH_TEMP_NOTIF = BIT(4), | |
| 389 | + UFS_DEV_LOW_TEMP_NOTIF = BIT(5), | |
| 390 | 390 | UFS_DEV_EXT_TEMP_NOTIF = BIT(6), |
| 391 | 391 | UFS_DEV_HPB_SUPPORT = BIT(7), |
| 392 | 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 | 1309 | void ufshcd_enable_irq(struct ufs_hba *hba); |
| 1310 | 1310 | void ufshcd_disable_irq(struct ufs_hba *hba); |
| 1311 | 1311 | int ufshcd_alloc_host(struct device *, struct ufs_hba **); |
| 1312 | −void ufshcd_dealloc_host(struct ufs_hba *); | |
| 1313 | 1312 | int ufshcd_hba_enable(struct ufs_hba *hba); |
| 1314 | 1313 | int ufshcd_init(struct ufs_hba *, void __iomem *, unsigned int); |
| 1315 | 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 | 338 | hlist_add_head(&req->hash_node, &ctx->futex_list); |
| 339 | 339 | io_ring_submit_unlock(ctx, issue_flags); |
| 340 | 340 | |
| 341 | − futex_queue(&ifd->q, hb); | |
| 341 | + futex_queue(&ifd->q, hb, NULL); | |
| 342 | 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 | 425 | int io_remove_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
| 419 | 426 | { |
| 420 | 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 | 643 | /* if mapped buffer ring OR classic exists, don't allow */ |
| 637 | 644 | if (bl->flags & IOBL_BUF_RING || !list_empty(&bl->buf_list)) |
| 638 | 645 | return -EEXIST; |
| 639 | − } else { | |
| 640 | − free_bl = bl = kzalloc(sizeof(*bl), GFP_KERNEL); | |
| 641 | − if (!bl) | |
| 642 | − return -ENOMEM; | |
| 646 | + io_destroy_bl(ctx, bl); | |
| 643 | 647 | } |
| 644 | 648 | |
| 649 | + free_bl = bl = kzalloc(sizeof(*bl), GFP_KERNEL); | |
| 650 | + if (!bl) | |
| 651 | + return -ENOMEM; | |
| 652 | + | |
| 645 | 653 | mmap_offset = (unsigned long)reg.bgid << IORING_OFF_PBUF_SHIFT; |
| 646 | 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 | 54 | continue; |
| 55 | 55 | |
| 56 | 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 | 57 | file->f_op->uring_cmd(cmd, IO_URING_F_CANCEL | |
| 61 | 58 | IO_URING_F_COMPLETE_DEFER); |
| 62 | 59 | ret = true; |
| @@ -179,12 +176,13 @@ static int io_uring_cmd_prep_setup(struct io_kiocb *req, · 116 unmodified lines | ||
| 179 | 176 | return -ENOMEM; |
| 180 | 177 | cache->op_data = NULL; |
| 181 | 178 | |
| 182 | − if (!(req->flags & REQ_F_FORCE_ASYNC)) { | |
| 183 | − /* defer memcpy until we need it */ | |
| 184 | − ioucmd->sqe = sqe; | |
| 185 | − return 0; | |
| 186 | − } | |
| 187 | − | |
| 179 | + /* | |
| 180 | + * Unconditionally cache the SQE for now - this is only needed for | |
| 181 | + * requests that go async, but prep handlers must ensure that any | |
| 182 | + * sqe data is stable beyond prep. Since uring_cmd is special in | |
| 183 | + * that it doesn't read in per-op data, play it safe and ensure that | |
| 184 | + * any SQE data is stable beyond prep. This can later get relaxed. | |
| 185 | + */ | |
| 188 | 186 | memcpy(cache->sqes, sqe, uring_sqe_size(req->ctx)); |
| 189 | 187 | ioucmd->sqe = cache->sqes; |
| 190 | 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 | 249 | ret = file->f_op->uring_cmd(ioucmd, issue_flags); |
| 252 | − if (ret == -EAGAIN) { | |
| 253 | − struct io_uring_cmd_data *cache = req->async_data; | |
| 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 | − | |
| 250 | + if (ret == -EAGAIN || ret == -EIOCBQUEUED) | |
| 251 | + return ret; | |
| 262 | 252 | if (ret < 0) |
| 263 | 253 | req_set_fail(req); |
| 264 | 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 | 118 | static void io_waitid_complete(struct io_kiocb *req, int ret) |
| 119 | 119 | { |
| 120 | 120 | struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid); |
| 121 | − struct io_tw_state ts = {}; | |
| 122 | 121 | |
| 123 | 122 | /* anyone completing better be holding a reference */ |
| 124 | 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 | 130 | if (ret < 0) |
| 132 | 131 | req_set_fail(req); |
| 133 | 132 | io_req_set_res(req, ret, 0); |
| 134 | − io_req_task_complete(req, &ts); | |
| 135 | 133 | } |
| 136 | 134 | |
| 137 | 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 | 151 | list_del_init(&iwa->wo.child_wait.entry); |
| 154 | 152 | spin_unlock_irq(&iw->head->lock); |
| 155 | 153 | io_waitid_complete(req, -ECANCELED); |
| 154 | + io_req_queue_tw_complete(req, -ECANCELED); | |
| 156 | 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 | 259 | io_waitid_complete(req, ret); |
| 260 | + io_req_task_complete(req, ts); | |
| 261 | 261 | } |
| 262 | 262 | |
| 263 | 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 | 285 | int io_waitid_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
| 286 | 286 | { |
| 287 | 287 | struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid); |
| 288 | + struct io_waitid_async *iwa; | |
| 288 | 289 | |
| 289 | 290 | if (sqe->addr || sqe->buf_index || sqe->addr3 || sqe->waitid_flags) |
| 290 | 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 | 298 | iw->which = READ_ONCE(sqe->len); |
| 293 | 299 | iw->upid = READ_ONCE(sqe->fd); |
| 294 | 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 | 305 | int io_waitid(struct io_kiocb *req, unsigned int issue_flags) |
| 300 | 306 | { |
| 301 | 307 | struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid); |
| 308 | + struct io_waitid_async *iwa = req->async_data; | |
| 302 | 309 | struct io_ring_ctx *ctx = req->ctx; |
| 303 | − struct io_waitid_async *iwa; | |
| 304 | 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 | 312 | ret = kernel_waitid_prepare(&iwa->wo, iw->which, iw->upid, &iw->info, |
| 313 | 313 | iw->options, NULL); |
| 314 | 314 | if (ret) |
| @@ -103,48 +103,50 @@ struct bsd_acct_struct { · 102 unmodified lines | ||
| 103 | 103 | atomic_long_t count; |
| 104 | 104 | struct rcu_head rcu; |
| 105 | 105 | struct mutex lock; |
| 106 | − int active; | |
| 106 | + bool active; | |
| 107 | + bool check_space; | |
| 107 | 108 | unsigned long needcheck; |
| 108 | 109 | struct file *file; |
| 109 | 110 | struct pid_namespace *ns; |
| 110 | 111 | struct work_struct work; |
| 111 | 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 | 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 | 124 | struct kstatfs sbuf; |
| 122 | 125 | |
| 123 | − if (time_is_after_jiffies(acct->needcheck)) | |
| 124 | − goto out; | |
| 126 | + if (!acct->check_space) | |
| 127 | + return acct->active; | |
| 125 | 128 | |
| 126 | 129 | /* May block */ |
| 127 | 130 | if (vfs_statfs(&acct->file->f_path, &sbuf)) |
| 128 | − goto out; | |
| 131 | + return acct->active; | |
| 129 | 132 | |
| 130 | 133 | if (acct->active) { |
| 131 | 134 | u64 suspend = sbuf.f_blocks * SUSPEND; |
| 132 | 135 | do_div(suspend, 100); |
| 133 | 136 | if (sbuf.f_bavail <= suspend) { |
| 134 | − acct->active = 0; | |
| 137 | + acct->active = false; | |
| 135 | 138 | pr_info("Process accounting paused\n"); |
| 136 | 139 | } |
| 137 | 140 | } else { |
| 138 | 141 | u64 resume = sbuf.f_blocks * RESUME; |
| 139 | 142 | do_div(resume, 100); |
| 140 | 143 | if (sbuf.f_bavail >= resume) { |
| 141 | − acct->active = 1; | |
| 144 | + acct->active = true; | |
| 142 | 145 | pr_info("Process accounting resumed\n"); |
| 143 | 146 | } |
| 144 | 147 | } |
| 145 | 148 | |
| 146 | 149 | acct->needcheck = jiffies + ACCT_TIMEOUT*HZ; |
| 147 | −out: | |
| 148 | 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 | 192 | struct bsd_acct_struct *acct = to_acct(pin); |
| 191 | 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 | 199 | schedule_work(&acct->work); |
| 194 | 200 | wait_for_completion(&acct->done); |
| 195 | 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 | 209 | struct bsd_acct_struct *acct = container_of(work, struct bsd_acct_struct, work); |
| 204 | 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 | 214 | if (file->f_op->flush) |
| 206 | 215 | file->f_op->flush(file, NULL); |
| 207 | 216 | __fput_sync(file); |
| @@ -234,6 +243,20 @@ static int acct_on(struct filename *pathname) · 26 unmodified lines | ||
| 234 | 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 | 260 | if (!(file->f_mode & FMODE_CAN_WRITE)) { |
| 238 | 261 | kfree(acct); |
| 239 | 262 | filp_close(file, NULL); |
| @@ -430,13 +453,27 @@ static u32 encode_float(u64 value) · 190 unmodified lines | ||
| 430 | 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 | 458 | struct pacct_struct *pacct = ¤t->signal->pacct; |
| 459 | + struct file *file = acct->file; | |
| 460 | + acct_t *ac = &acct->ac; | |
| 436 | 461 | u64 elapsed, run_time; |
| 437 | 462 | time64_t btime; |
| 438 | 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 | 478 | * Fill the accounting struct with the needed info as recorded |
| 442 | 479 | * by the different kernel functions. |
| @@ -484,64 +521,61 @@ static void fill_ac(acct_t *ac) · 41 unmodified lines | ||
| 484 | 521 | ac->ac_majflt = encode_comp_t(pacct->ac_majflt); |
| 485 | 522 | ac->ac_exitcode = pacct->ac_exitcode; |
| 486 | 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 | 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); | |
| 516 | − ac.ac_gid = from_kgid_munged(file->f_cred->user_ns, orig_cred->gid); | |
| 526 | + ac->ac_uid = from_kuid_munged(file->f_cred->user_ns, current_uid()); | |
| 527 | + ac->ac_gid = from_kgid_munged(file->f_cred->user_ns, current_gid()); | |
| 517 | 528 | #if ACCT_VERSION == 1 || ACCT_VERSION == 2 |
| 518 | 529 | /* backward-compatible 16 bit fields */ |
| 519 | − ac.ac_uid16 = ac.ac_uid; | |
| 520 | − ac.ac_gid16 = ac.ac_gid; | |
| 530 | + ac->ac_uid16 = ac->ac_uid; | |
| 531 | + ac->ac_gid16 = ac->ac_gid; | |
| 521 | 532 | #elif ACCT_VERSION == 3 |
| 522 | 533 | { |
| 523 | 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 | 537 | rcu_read_lock(); |
| 527 | − ac.ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), | |
| 528 | − ns); | |
| 538 | + ac->ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), ns); | |
| 529 | 539 | rcu_read_unlock(); |
| 530 | 540 | } |
| 531 | 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 | |
| 534 | − * as we could deadlock the system otherwise. | |
| 554 | + * First check to see if there is enough free_space to continue | |
| 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 | 560 | /* it's been opened O_APPEND, so position is irrelevant */ |
| 538 | 561 | loff_t pos = 0; |
| 539 | − __kernel_write(file, &ac, sizeof(acct_t), &pos); | |
| 562 | + __kernel_write(file, ac, sizeof(acct_t), &pos); | |
| 540 | 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 | 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 | 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 | 43 | #define KERN_VM_SZ (SZ_4G + GUARD_SZ) |
| 44 | 44 | |
| 45 | 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 | 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 | 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 | 6507 | { "rxrpc_resend", 0x10 }, |
| 6508 | 6508 | { "rxrpc_tq", 0x10 }, |
| 6509 | 6509 | { "rxrpc_client", 0x1 }, |
| 6510 | + /* skb */ | |
| 6511 | + {"kfree_skb", 0x1000}, | |
| 6510 | 6512 | /* sunrpc */ |
| 6511 | 6513 | { "xs_stream_read_data", 0x1 }, |
| 6512 | 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 | 268 | /* allow writable mapping for the consumer_pos only */ |
| 269 | 269 | if (vma->vm_pgoff != 0 || vma->vm_end - vma->vm_start != PAGE_SIZE) |
| 270 | 270 | return -EPERM; |
| 271 | − } else { | |
| 272 | − vm_flags_clear(vma, VM_MAYWRITE); | |
| 273 | 271 | } |
| 274 | 272 | /* remap_vmalloc_range() checks size and offset constraints */ |
| 275 | 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 | 287 | * position, and the ring buffer data itself. |
| 290 | 288 | */ |
| 291 | 289 | return -EPERM; |
| 292 | − } else { | |
| 293 | − vm_flags_clear(vma, VM_MAYWRITE); | |
| 294 | 290 | } |
| 295 | 291 | /* remap_vmalloc_range() checks size and offset constraints */ |
| 296 | 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 | 1035 | static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) |
| 1036 | 1036 | { |
| 1037 | 1037 | struct bpf_map *map = filp->private_data; |
| 1038 | − int err; | |
| 1038 | + int err = 0; | |
| 1039 | 1039 | |
| 1040 | 1040 | if (!map->ops->map_mmap || !IS_ERR_OR_NULL(map->record)) |
| 1041 | 1041 | return -ENOTSUPP; |
| @@ -1059,24 +1059,33 @@ static int bpf_map_mmap(struct file *filp, struct vm_area_struct *vma) · 17 unmodified lines | ||
| 1059 | 1059 | err = -EACCES; |
| 1060 | 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 | 1069 | /* set default open/close callbacks */ |
| 1065 | 1070 | vma->vm_ops = &bpf_map_default_vmops; |
| 1066 | 1071 | vma->vm_private_data = map; |
| 1067 | 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 | 1080 | if (!(vma->vm_flags & VM_WRITE)) |
| 1069 | − /* disallow re-mapping with PROT_WRITE */ | |
| 1070 | 1081 | vm_flags_clear(vma, VM_MAYWRITE); |
| 1071 | 1082 | |
| 1072 | 1083 | err = map->ops->map_mmap(map, vma); |
| 1073 | − if (err) | |
| 1074 | − goto out; | |
| 1084 | + if (err) { | |
| 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 | 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 | 1977 | return err; |
| 1969 | 1978 | } |
| 1970 | 1979 | |
| 1971 | −#define MAP_LOOKUP_RETRIES 3 | |
| 1972 | − | |
| 1973 | 1980 | int generic_map_lookup_batch(struct bpf_map *map, |
| 1974 | 1981 | const union bpf_attr *attr, |
| 1975 | 1982 | union bpf_attr __user *uattr) |
| @@ -1979,8 +1986,8 @@ int generic_map_lookup_batch(struct bpf_map *map, · 3 unmodified lines | ||
| 1979 | 1986 | void __user *values = u64_to_user_ptr(attr->batch.values); |
| 1980 | 1987 | void __user *keys = u64_to_user_ptr(attr->batch.keys); |
| 1981 | 1988 | void *buf, *buf_prevkey, *prev_key, *key, *value; |
| 1982 | − int err, retry = MAP_LOOKUP_RETRIES; | |
| 1983 | 1989 | u32 value_size, cp, max_count; |
| 1990 | + int err; | |
| 1984 | 1991 | |
| 1985 | 1992 | if (attr->batch.elem_flags & ~BPF_F_LOCK) |
| 1986 | 1993 | return -EINVAL; |
| @@ -2026,14 +2033,8 @@ int generic_map_lookup_batch(struct bpf_map *map, · 39 unmodified lines | ||
| 2026 | 2033 | err = bpf_map_copy_value(map, key, value, |
| 2027 | 2034 | attr->batch.elem_flags); |
| 2028 | 2035 | |
| 2029 | − if (err == -ENOENT) { | |
| 2030 | − if (retry) { | |
| 2031 | − retry--; | |
| 2032 | − continue; | |
| 2033 | − } | |
| 2034 | − err = -EINTR; | |
| 2035 | − break; | |
| 2036 | − } | |
| 2036 | + if (err == -ENOENT) | |
| 2037 | + goto next_key; | |
| 2037 | 2038 | |
| 2038 | 2039 | if (err) |
| 2039 | 2040 | goto free_buf; |
| @@ -2048,12 +2049,12 @@ int generic_map_lookup_batch(struct bpf_map *map, · 8 unmodified lines | ||
| 2048 | 2049 | goto free_buf; |
| 2049 | 2050 | } |
| 2050 | 2051 | |
| 2052 | + cp++; | |
| 2053 | +next_key: | |
| 2051 | 2054 | if (!prev_key) |
| 2052 | 2055 | prev_key = buf_prevkey; |
| 2053 | 2056 | |
| 2054 | 2057 | swap(prev_key, key); |
| 2055 | − retry = MAP_LOOKUP_RETRIES; | |
| 2056 | − cp++; | |
| 2057 | 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 | 1501 | struct bpf_reference_state *s; |
| 1502 | 1502 | |
| 1503 | 1503 | s = acquire_reference_state(env, insn_idx); |
| 1504 | + if (!s) | |
| 1505 | + return -ENOMEM; | |
| 1504 | 1506 | s->type = type; |
| 1505 | 1507 | s->id = id; |
| 1506 | 1508 | s->ptr = ptr; |
| @@ -9230,10 +9232,11 @@ static int check_reg_const_str(struct bpf_verifier_env *env, · 7723 unmodified lines | ||
| 9230 | 9232 | return 0; |
| 9231 | 9233 | } |
| 9232 | 9234 | |
| 9233 | −/* Returns constant key value if possible, else negative error */ | |
| 9234 | −static s64 get_constant_map_key(struct bpf_verifier_env *env, | |
| 9235 | +/* Returns constant key value in `value` if possible, else negative error */ | |
| 9236 | +static int get_constant_map_key(struct bpf_verifier_env *env, | |
| 9235 | 9237 | struct bpf_reg_state *key, |
| 9236 | − u32 key_size) | |
| 9238 | + u32 key_size, | |
| 9239 | + s64 *value) | |
| 9237 | 9240 | { |
| 9238 | 9241 | struct bpf_func_state *state = func(env, key); |
| 9239 | 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 | 9263 | /* First handle precisely tracked STACK_ZERO */ |
| 9261 | 9264 | for (i = off; i >= 0 && stype[i] == STACK_ZERO; i--) |
| 9262 | 9265 | zero_size++; |
| 9263 | − if (zero_size >= key_size) | |
| 9266 | + if (zero_size >= key_size) { | |
| 9267 | + *value = 0; | |
| 9264 | 9268 | return 0; |
| 9269 | + } | |
| 9265 | 9270 | |
| 9266 | 9271 | /* Check that stack contains a scalar spill of expected size */ |
| 9267 | 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 | 9289 | if (err < 0) |
| 9285 | 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 | 9298 | static int check_func_arg(struct bpf_verifier_env *env, u32 arg, |
| 9291 | 9299 | struct bpf_call_arg_meta *meta, |
| 9292 | 9300 | const struct bpf_func_proto *fn, |
| @@ -9435,9 +9443,16 @@ skip_type_check: · 142 unmodified lines | ||
| 9435 | 9443 | err = check_helper_mem_access(env, regno, key_size, BPF_READ, false, NULL); |
| 9436 | 9444 | if (err) |
| 9437 | 9445 | return err; |
| 9438 | − meta->const_map_key = get_constant_map_key(env, reg, key_size); | |
| 9439 | − if (meta->const_map_key < 0 && meta->const_map_key != -EOPNOTSUPP) | |
| 9440 | − return meta->const_map_key; | |
| 9446 | + if (can_elide_value_nullness(meta->map_ptr->map_type)) { | |
| 9447 | + err = get_constant_map_key(env, reg, key_size, &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 | 9456 | break; |
| 9442 | 9457 | case ARG_PTR_TO_MAP_VALUE: |
| 9443 | 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 | 4013 | lockdep_assert_held(&cgroup_mutex); |
| 4014 | 4014 | |
| 4015 | 4015 | spin_lock_irq(&css_set_lock); |
| 4016 | − set_bit(CGRP_KILL, &cgrp->flags); | |
| 4016 | + cgrp->kill_seq++; | |
| 4017 | 4017 | spin_unlock_irq(&css_set_lock); |
| 4018 | 4018 | |
| 4019 | 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 | 4029 | send_sig(SIGKILL, task, 0); |
| 4030 | 4030 | } |
| 4031 | 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 | 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 | 6484 | spin_lock_irq(&css_set_lock); |
| 6489 | 6485 | cset = task_css_set(current); |
| 6490 | 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 | 6491 | spin_unlock_irq(&css_set_lock); |
| 6492 | 6492 | |
| 6493 | 6493 | if (!(kargs->flags & CLONE_INTO_CGROUP)) { |
| @@ -6668,6 +6668,7 @@ void cgroup_post_fork(struct task_struct *child, · 174 unmodified lines | ||
| 6668 | 6668 | struct kernel_clone_args *kargs) |
| 6669 | 6669 | __releases(&cgroup_threadgroup_rwsem) __releases(&cgroup_mutex) |
| 6670 | 6670 | { |
| 6671 | + unsigned int cgrp_kill_seq = 0; | |
| 6671 | 6672 | unsigned long cgrp_flags = 0; |
| 6672 | 6673 | bool kill = false; |
| 6673 | 6674 | struct cgroup_subsys *ss; |
| @@ -6681,10 +6682,13 @@ void cgroup_post_fork(struct task_struct *child, · 7 unmodified lines | ||
| 6681 | 6682 | |
| 6682 | 6683 | /* init tasks are special, only link regular threads */ |
| 6683 | 6684 | if (likely(child->pid)) { |
| 6684 | − if (kargs->cgrp) | |
| 6685 | + if (kargs->cgrp) { | |
| 6685 | 6686 | cgrp_flags = kargs->cgrp->flags; |
| 6686 | − else | |
| 6687 | + cgrp_kill_seq = kargs->cgrp->kill_seq; | |
| 6688 | + } else { | |
| 6687 | 6689 | cgrp_flags = cset->dfl_cgrp->flags; |
| 6690 | + cgrp_kill_seq = cset->dfl_cgrp->kill_seq; | |
| 6691 | + } | |
| 6688 | 6692 | |
| 6689 | 6693 | WARN_ON_ONCE(!list_empty(&child->cg_list)); |
| 6690 | 6694 | cset->nr_tasks++; |
| @@ -6719,7 +6723,7 @@ void cgroup_post_fork(struct task_struct *child, · 28 unmodified lines | ||
| 6719 | 6723 | * child down right after we finished preparing it for |
| 6720 | 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 | 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 | 591 | cputime->sum_exec_runtime += user; |
| 592 | 592 | cputime->sum_exec_runtime += sys; |
| 593 | − cputime->sum_exec_runtime += cpustat[CPUTIME_STEAL]; | |
| 594 | 593 | |
| 595 | 594 | #ifdef CONFIG_SCHED_CORE |
| 596 | 595 | bstat->forceidle_sum += cpustat[CPUTIME_FORCEIDLE]; |
| @@ -532,7 +532,8 @@ void futex_q_unlock(struct futex_hash_bucket *hb) · 531 unmodified lines | ||
| 532 | 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 | 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 | 550 | plist_node_init(&q->list, prio); |
| 550 | 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 | 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 | 290 | extern int futex_unqueue(struct futex_q *q); |
| 290 | 291 | |
| 291 | 292 | /** |
| 292 | 293 | * futex_queue() - Enqueue the futex_q on the futex_hash_bucket |
| 293 | 294 | * @q: The futex_q to enqueue |
| 294 | 295 | * @hb: The destination hash bucket |
| 296 | + * @task: Task queueing this futex | |
| 295 | 297 | * |
| 296 | 298 | * The hb->lock must be held by the caller, and is released here. A call to |
| 297 | 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 | 301 | * or nothing if the unqueue is done as part of the wake process and the unqueue |
| 300 | 302 | * state is implicit in the state of woken task (see futex_wait_requeue_pi() for |
| 301 | 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 | 309 | __releases(&hb->lock) |
| 305 | 310 | { |
| 306 | − __futex_queue(q, hb); | |
| 311 | + __futex_queue(q, hb, task); | |
| 307 | 312 | spin_unlock(&hb->lock); |
| 308 | 313 | } |
| 309 | 314 | |
| @@ -982,7 +982,7 @@ retry_private: · 981 unmodified lines | ||
| 982 | 982 | /* |
| 983 | 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 | 987 | if (trylock) { |
| 988 | 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 | 349 | * access to the hash list and forcing another memory barrier. |
| 350 | 350 | */ |
| 351 | 351 | set_current_state(TASK_INTERRUPTIBLE|TASK_FREEZABLE); |
| 352 | − futex_queue(q, hb); | |
| 352 | + futex_queue(q, hb, current); | |
| 353 | 353 | |
| 354 | 354 | /* Arm the timer */ |
| 355 | 355 | if (timeout) |
| @@ -460,7 +460,7 @@ retry: · 104 unmodified lines | ||
| 460 | 460 | * next futex. Queue each futex at this moment so hb can |
| 461 | 461 | * be unlocked. |
| 462 | 462 | */ |
| 463 | − futex_queue(q, hb); | |
| 463 | + futex_queue(q, hb, current); | |
| 464 | 464 | continue; |
| 465 | 465 | } |
| 466 | 466 | |
| @@ -31,10 +31,6 @@ config GENERIC_IRQ_EFFECTIVE_AFF_MASK · 30 unmodified lines | ||
| 31 | 31 | config GENERIC_PENDING_IRQ |
| 32 | 32 | bool |
| 33 | 33 | |
| 34 | −# Deduce delayed migration from top-level interrupt chip flags | |
| 35 | −config GENERIC_PENDING_IRQ_CHIPFLAGS | |
| 36 | − bool | |
| 37 | − | |
| 38 | 34 | # Support for generic irq migrating off cpu before the cpu is offline. |
| 39 | 35 | config GENERIC_IRQ_MIGRATION |
| 40 | 36 | bool |
| @@ -859,7 +859,7 @@ int kthread_affine_preferred(struct task_struct *p, const struct cpumask *mask) · 858 unmodified lines | ||
| 859 | 859 | struct kthread *kthread = to_kthread(p); |
| 860 | 860 | cpumask_var_t affinity; |
| 861 | 861 | unsigned long flags; |
| 862 | − int ret; | |
| 862 | + int ret = 0; | |
| 863 | 863 | |
| 864 | 864 | if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE) || kthread->started) { |
| 865 | 865 | WARN_ON(1); |
| @@ -892,7 +892,7 @@ int kthread_affine_preferred(struct task_struct *p, const struct cpumask *mask) · 26 unmodified lines | ||
| 892 | 892 | out: |
| 893 | 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 | 150 | * see this thread after that: we can no longer use signal->autogroup. |
| 151 | 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 | 156 | static void |
| @@ -182,7 +182,7 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag) · 25 unmodified lines | ||
| 182 | 182 | * sched_autogroup_exit_task(). |
| 183 | 183 | */ |
| 184 | 184 | for_each_thread(p, t) |
| 185 | − sched_move_task(t); | |
| 185 | + sched_move_task(t, true); | |
| 186 | 186 | |
| 187 | 187 | unlock_task_sighand(p, &flags); |
| 188 | 188 | autogroup_kref_put(prev); |
| @@ -1063,9 +1063,10 @@ void wake_up_q(struct wake_q_head *head) · 1062 unmodified lines | ||
| 1063 | 1063 | struct task_struct *task; |
| 1064 | 1064 | |
| 1065 | 1065 | task = container_of(node, struct task_struct, wake_q); |
| 1066 | − /* Task can safely be re-inserted now: */ | |
| 1067 | 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 | 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 | 9051 | * now. This function just updates tsk->se.cfs_rq and tsk->se.parent to reflect |
| 9051 | 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 | 9056 | int queued, running, queue_flags = |
| 9056 | 9057 | DEQUEUE_SAVE | DEQUEUE_MOVE | DEQUEUE_NOCLOCK; |
| @@ -9079,7 +9080,8 @@ void sched_move_task(struct task_struct *tsk) · 22 unmodified lines | ||
| 9079 | 9080 | put_prev_task(rq, tsk); |
| 9080 | 9081 | |
| 9081 | 9082 | sched_change_group(tsk, group); |
| 9082 | − scx_move_task(tsk); | |
| 9083 | + if (!for_autogroup) | |
| 9084 | + scx_cgroup_move_task(tsk); | |
| 9083 | 9085 | |
| 9084 | 9086 | if (queued) |
| 9085 | 9087 | enqueue_task(rq, tsk, queue_flags); |
| @@ -9180,7 +9182,7 @@ static void cpu_cgroup_attach(struct cgroup_taskset *tset) · 94 unmodified lines | ||
| 9180 | 9182 | struct cgroup_subsys_state *css; |
| 9181 | 9183 | |
| 9182 | 9184 | cgroup_taskset_for_each(task, css, tset) |
| 9183 | − sched_move_task(task); | |
| 9185 | + sched_move_task(task, false); | |
| 9184 | 9186 | |
| 9185 | 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 | 1262 | if (task_has_dl_policy(p)) { |
| 1263 | 1263 | P(dl.runtime); |
| 1264 | 1264 | P(dl.deadline); |
| 1265 | + } else if (fair_policy(p->policy)) { | |
| 1266 | + P(se.slice); | |
| 1265 | 1267 | } |
| 1266 | 1268 | #ifdef CONFIG_SCHED_CLASS_EXT |
| 1267 | 1269 | __PS("ext.enabled", task_on_scx(p)); |
| @@ -122,6 +122,19 @@ enum scx_ops_flags { · 121 unmodified lines | ||
| 122 | 122 | */ |
| 123 | 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 | 139 | * CPU cgroup support flags |
| 127 | 140 | */ |
| @@ -130,6 +143,7 @@ enum scx_ops_flags { · 2 unmodified lines | ||
| 130 | 143 | SCX_OPS_ALL_FLAGS = SCX_OPS_KEEP_BUILTIN_IDLE | |
| 131 | 144 | SCX_OPS_ENQ_LAST | |
| 132 | 145 | SCX_OPS_ENQ_EXITING | |
| 146 | + SCX_OPS_ENQ_MIGRATION_DISABLED | | |
| 133 | 147 | SCX_OPS_SWITCH_PARTIAL | |
| 134 | 148 | SCX_OPS_HAS_CGROUP_WEIGHT, |
| 135 | 149 | }; |
| @@ -416,7 +430,7 @@ struct sched_ext_ops { · 280 unmodified lines | ||
| 416 | 430 | |
| 417 | 431 | /** |
| 418 | 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 | 434 | * @idle: whether entering or exiting the idle state |
| 421 | 435 | * |
| 422 | 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 | 897 | static DEFINE_STATIC_KEY_FALSE(scx_ops_enq_last); |
| 884 | 898 | static DEFINE_STATIC_KEY_FALSE(scx_ops_enq_exiting); |
| 899 | +static DEFINE_STATIC_KEY_FALSE(scx_ops_enq_migration_disabled); | |
| 885 | 900 | static DEFINE_STATIC_KEY_FALSE(scx_ops_cpu_preempt); |
| 886 | 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 | 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 | 1233 | * @cur: current position, %NULL to start iteration |
| 1219 | 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 | 2029 | unlikely(p->flags & PF_EXITING)) |
| 2015 | 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 | 2037 | if (!SCX_HAS_OP(enqueue)) |
| 2018 | 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 | 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 | 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 | 2334 | * - The BPF scheduler is bypassed while the rq is offline and we can always say |
| 2315 | 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 | 2339 | static bool task_can_run_on_remote_rq(struct task_struct *p, struct rq *rq, |
| 2318 | 2340 | bool trigger_error) |
| 2319 | 2341 | { |
| 2320 | 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 | 2366 | * We don't require the BPF scheduler to avoid dispatching to offline |
| 2324 | 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 | 2371 | if (!task_allowed_on_cpu(p, cpu)) { |
| 2329 | 2372 | if (trigger_error) |
| 2330 | − scx_ops_error("SCX_DSQ_LOCAL[_ON] verdict target cpu %d not allowed for %s[%d]", | |
| 2331 | − cpu_of(rq), p->comm, p->pid); | |
| 2373 | + scx_ops_error("SCX_DSQ_LOCAL[_ON] target CPU %d not allowed for %s[%d]", | |
| 2374 | + cpu, p->comm, p->pid); | |
| 2332 | 2375 | return false; |
| 2333 | 2376 | } |
| 2334 | 2377 | |
| 2335 | − if (unlikely(is_migration_disabled(p))) | |
| 2336 | − return false; | |
| 2337 | − | |
| 2338 | 2378 | if (!scx_rq_online(rq)) |
| 2339 | 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 | 2478 | if (dst_dsq->id == SCX_DSQ_LOCAL) { |
| 2439 | 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 | 2482 | dst_dsq = find_global_dsq(p); |
| 2442 | 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 | 2522 | * A poorly behaving BPF scheduler can live-lock the system by e.g. incessantly |
| 2482 | 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 | 2525 | * bypass mode is switching to guarantee timely completion. |
| 2485 | 2526 | */ |
| 2486 | 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 | 2617 | struct rq *src_rq = task_rq(p); |
| 2577 | 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 | 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 | 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 | 2637 | dispatch_enqueue(find_global_dsq(p), p, |
| 2593 | 2638 | enq_flags | SCX_ENQ_CLEAR_OPSS); |
| 2594 | 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 | 2656 | atomic_long_set_release(&p->scx.ops_state, SCX_OPSS_NONE); |
| 2612 | 2657 | |
| 2613 | 2658 | /* switch to @src_rq lock */ |
| 2614 | − if (rq != src_rq) { | |
| 2615 | − raw_spin_rq_unlock(rq); | |
| 2659 | + if (locked_rq != src_rq) { | |
| 2660 | + raw_spin_rq_unlock(locked_rq); | |
| 2661 | + locked_rq = src_rq; | |
| 2616 | 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 | 2676 | } else { |
| 2631 | 2677 | move_remote_task_to_local_dsq(p, enq_flags, |
| 2632 | 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 | 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 | 2688 | /* switch back to @rq lock */ |
| 2641 | − if (rq != dst_rq) { | |
| 2642 | − raw_spin_rq_unlock(dst_rq); | |
| 2689 | + if (locked_rq != rq) { | |
| 2690 | + raw_spin_rq_unlock(locked_rq); | |
| 2643 | 2691 | raw_spin_rq_lock(rq); |
| 2644 | 2692 | } |
| 2645 | 2693 | #else /* CONFIG_SMP */ |
| @@ -3144,7 +3192,7 @@ static struct task_struct *pick_task_scx(struct rq *rq) · 498 unmodified lines | ||
| 3144 | 3192 | * |
| 3145 | 3193 | * Unless overridden by ops.core_sched_before(), @p->scx.core_sched_at is used |
| 3146 | 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 | 3196 | * behavior. |
| 3149 | 3197 | * |
| 3150 | 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 | 3899 | curr->scx.slice = 0; |
| 3852 | 3900 | touch_core_sched(rq, curr); |
| 3853 | 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 | 3905 | if (!curr->scx.slice) |
| @@ -3998,7 +4046,7 @@ static void scx_ops_disable_task(struct task_struct *p) · 140 unmodified lines | ||
| 3998 | 4046 | WARN_ON_ONCE(scx_get_task_state(p) != SCX_TASK_ENABLED); |
| 3999 | 4047 | |
| 4000 | 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 | 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 | 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 | 4079 | scx_set_task_state(p, SCX_TASK_NONE); |
| 4032 | 4080 | } |
| 4033 | 4081 | |
| @@ -4323,24 +4371,11 @@ err: · 289 unmodified lines | ||
| 4323 | 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 | 4376 | if (!scx_cgroup_enabled) |
| 4329 | 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 | 4380 | * @p must have ops.cgroup_prep_move() called on it and thus |
| 4346 | 4381 | * cgrp_moving_from set. |
| @@ -4590,7 +4625,7 @@ static int scx_cgroup_init(void) · 243 unmodified lines | ||
| 4590 | 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 | 4629 | * cgroups and init, all online cgroups are initialized. |
| 4595 | 4630 | */ |
| 4596 | 4631 | rcu_read_lock(); |
| @@ -5059,6 +5094,7 @@ static void scx_ops_disable_workfn(struct kthread_work *work) · 462 unmodified lines | ||
| 5059 | 5094 | static_branch_disable(&scx_has_op[i]); |
| 5060 | 5095 | static_branch_disable(&scx_ops_enq_last); |
| 5061 | 5096 | static_branch_disable(&scx_ops_enq_exiting); |
| 5097 | + static_branch_disable(&scx_ops_enq_migration_disabled); | |
| 5062 | 5098 | static_branch_disable(&scx_ops_cpu_preempt); |
| 5063 | 5099 | static_branch_disable(&scx_builtin_idle_enabled); |
| 5064 | 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 | 5313 | scx_get_task_state(p), p->scx.flags & ~SCX_TASK_STATE_MASK, |
| 5278 | 5314 | p->scx.dsq_flags, ops_state & SCX_OPSS_STATE_MASK, |
| 5279 | 5315 | ops_state >> SCX_OPSS_QSEQ_SHIFT); |
| 5280 | − dump_line(s, " sticky/holding_cpu=%d/%d dsq_id=%s dsq_vtime=%llu slice=%llu", | |
| 5281 | − p->scx.sticky_cpu, p->scx.holding_cpu, dsq_id_buf, | |
| 5282 | − p->scx.dsq_vtime, p->scx.slice); | |
| 5316 | + dump_line(s, " sticky/holding_cpu=%d/%d dsq_id=%s", | |
| 5317 | + p->scx.sticky_cpu, p->scx.holding_cpu, dsq_id_buf); | |
| 5318 | + dump_line(s, " dsq_vtime=%llu slice=%llu weight=%u", | |
| 5319 | + p->scx.dsq_vtime, p->scx.slice, p->scx.weight); | |
| 5283 | 5320 | dump_line(s, " cpus=%*pb", cpumask_pr_args(p->cpus_ptr)); |
| 5284 | 5321 | |
| 5285 | 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 | 5705 | if (ops->flags & SCX_OPS_ENQ_EXITING) |
| 5669 | 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 | 5709 | if (scx_ops.cpu_acquire || scx_ops.cpu_release) |
| 5671 | 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 | 73 | int scx_tg_online(struct task_group *tg); |
| 74 | 74 | void scx_tg_offline(struct task_group *tg); |
| 75 | 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 | 77 | void scx_cgroup_finish_attach(void); |
| 78 | 78 | void scx_cgroup_cancel_attach(struct cgroup_taskset *tset); |
| 79 | 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 | 82 | static inline int scx_tg_online(struct task_group *tg) { return 0; } |
| 83 | 83 | static inline void scx_tg_offline(struct task_group *tg) {} |
| 84 | 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 | 86 | static inline void scx_cgroup_finish_attach(void) {} |
| 87 | 87 | static inline void scx_cgroup_cancel_attach(struct cgroup_taskset *tset) {} |
| 88 | 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 | 5385 | static void set_delayed(struct sched_entity *se) |
| 5386 | 5386 | { |
| 5387 | 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 | 5397 | for_each_sched_entity(se) { |
| 5389 | 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 | 5406 | static void clear_delayed(struct sched_entity *se) |
| 5398 | 5407 | { |
| 5399 | 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 | 5419 | for_each_sched_entity(se) { |
| 5401 | 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 | 572 | extern void sched_destroy_group(struct task_group *tg); |
| 573 | 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 | 577 | #ifdef CONFIG_FAIR_GROUP_SCHED |
| 578 | 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 | 749 | if (WARN_ON_ONCE(!fprog)) |
| 750 | 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 | 761 | for (pc = 0; pc < fprog->len; pc++) { |
| 753 | 762 | struct sock_filter *insn = &fprog->filter[pc]; |
| 754 | 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 | 1033 | static const int mode1_syscalls[] = { |
| 1025 | 1034 | __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn, |
| 1035 | +#ifdef __NR_uretprobe | |
| 1036 | + __NR_uretprobe, | |
| 1037 | +#endif | |
| 1026 | 1038 | -1, /* negative terminated */ |
| 1027 | 1039 | }; |
| 1028 | 1040 | |
| @@ -373,16 +373,18 @@ void clocksource_verify_percpu(struct clocksource *cs) · 372 unmodified lines | ||
| 373 | 373 | cpumask_clear(&cpus_ahead); |
| 374 | 374 | cpumask_clear(&cpus_behind); |
| 375 | 375 | cpus_read_lock(); |
| 376 | − preempt_disable(); | |
| 376 | + migrate_disable(); | |
| 377 | 377 | clocksource_verify_choose_cpus(); |
| 378 | 378 | if (cpumask_empty(&cpus_chosen)) { |
| 379 | − preempt_enable(); | |
| 379 | + migrate_enable(); | |
| 380 | 380 | cpus_read_unlock(); |
| 381 | 381 | pr_warn("Not enough CPUs to check clocksource '%s'.\n", cs->name); |
| 382 | 382 | return; |
| 383 | 383 | } |
| 384 | 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 | 388 | for_each_cpu(cpu, &cpus_chosen) { |
| 387 | 389 | if (cpu == testcpu) |
| 388 | 390 | continue; |
| @@ -402,6 +404,7 @@ void clocksource_verify_percpu(struct clocksource *cs) · 13 unmodified lines | ||
| 402 | 404 | cs_nsec_min = cs_nsec; |
| 403 | 405 | } |
| 404 | 406 | preempt_enable(); |
| 407 | + migrate_enable(); | |
| 405 | 408 | cpus_read_unlock(); |
| 406 | 409 | if (!cpumask_empty(&cpus_ahead)) |
| 407 | 410 | pr_warn(" CPUs %*pbl ahead of CPU %d for clocksource %s.\n", |
| @@ -58,6 +58,8 @@ · 57 unmodified lines | ||
| 58 | 58 | #define HRTIMER_ACTIVE_SOFT (HRTIMER_ACTIVE_HARD << MASK_SHIFT) |
| 59 | 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 | 64 | * The timer bases: |
| 63 | 65 | * |
| @@ -111,7 +113,8 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = · 47 unmodified lines | ||
| 111 | 113 | .clockid = CLOCK_TAI, |
| 112 | 114 | .get_time = &ktime_get_clocktai, |
| 113 | 115 | }, |
| 114 | − } | |
| 116 | + }, | |
| 117 | + .csd = CSD_INIT(retrigger_next_event, NULL) | |
| 115 | 118 | }; |
| 116 | 119 | |
| 117 | 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 | 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 | 139 | * Functions and macros which are different for UP/SMP systems are kept in a |
| 129 | 140 | * single place |
| @@ -145,11 +156,6 @@ static struct hrtimer_cpu_base migration_cpu_base = { · 15 unmodified lines | ||
| 145 | 156 | |
| 146 | 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 | 160 | * We are using hashed locking: holding per_cpu(hrtimer_bases)[n].lock |
| 155 | 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 | |
| 187 | − * event on the target cpu. When high resolution is enabled, we cannot | |
| 188 | − * reprogram the target cpu hardware and we would cause it to fire | |
| 189 | − * late. To keep it simple, we handle the high resolution enabled and | |
| 190 | − * disabled case similar. | |
| 192 | + * Check if the elected target is suitable considering its next | |
| 193 | + * event and the hotplug state of the current CPU. | |
| 194 | + * | |
| 195 | + * If the elected target is remote and its next event is after the timer | |
| 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 | 203 | * Called with cpu_base->lock of target cpu held. |
| 193 | 204 | */ |
| 194 | −static int | |
| 195 | −hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base) | |
| 205 | +static bool hrtimer_suitable_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 | 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 | 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 | |
| 204 | −struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base, | |
| 205 | − int pinned) | |
| 232 | +static inline struct hrtimer_cpu_base *get_target_base(struct hrtimer_cpu_base *base, 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 | 240 | #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON) |
| 208 | 241 | if (static_branch_likely(&timers_migration_enabled) && !pinned) |
| 209 | 242 | return &per_cpu(hrtimer_bases, get_nohz_timer_target()); |
| @@ -254,8 +287,8 @@ again: · 44 unmodified lines | ||
| 254 | 287 | raw_spin_unlock(&base->cpu_base->lock); |
| 255 | 288 | raw_spin_lock(&new_base->cpu_base->lock); |
| 256 | 289 | |
| 257 | − if (new_cpu_base != this_cpu_base && | |
| 258 | − hrtimer_check_target(timer, new_base)) { | |
| 290 | + if (!hrtimer_suitable_target(timer, new_base, new_cpu_base, | |
| 291 | + this_cpu_base)) { | |
| 259 | 292 | raw_spin_unlock(&new_base->cpu_base->lock); |
| 260 | 293 | raw_spin_lock(&base->cpu_base->lock); |
| 261 | 294 | new_cpu_base = this_cpu_base; |
| @@ -264,8 +297,7 @@ again: · 2 unmodified lines | ||
| 264 | 297 | } |
| 265 | 298 | WRITE_ONCE(timer->base, new_base); |
| 266 | 299 | } else { |
| 267 | − if (new_cpu_base != this_cpu_base && | |
| 268 | − hrtimer_check_target(timer, new_base)) { | |
| 300 | + if (!hrtimer_suitable_target(timer, new_base, new_cpu_base, this_cpu_base)) { | |
| 269 | 301 | new_cpu_base = this_cpu_base; |
| 270 | 302 | goto again; |
| 271 | 303 | } |
| @@ -275,11 +307,6 @@ again: · 3 unmodified lines | ||
| 275 | 307 | |
| 276 | 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 | 310 | static inline struct hrtimer_clock_base * |
| 284 | 311 | lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags) |
| 285 | 312 | __acquires(&timer->base->cpu_base->lock) |
| @@ -716,8 +743,6 @@ static inline int hrtimer_is_hres_enabled(void) · 430 unmodified lines | ||
| 716 | 743 | return hrtimer_hres_enabled; |
| 717 | 744 | } |
| 718 | 745 | |
| 719 | −static void retrigger_next_event(void *arg); | |
| 720 | − | |
| 721 | 746 | /* |
| 722 | 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 | 1230 | u64 delta_ns, const enum hrtimer_mode mode, |
| 1206 | 1231 | struct hrtimer_clock_base *base) |
| 1207 | 1232 | { |
| 1233 | + struct hrtimer_cpu_base *this_cpu_base = this_cpu_ptr(&hrtimer_bases); | |
| 1208 | 1234 | struct hrtimer_clock_base *new_base; |
| 1209 | 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 | 1242 | * and enforce reprogramming after it is queued no matter whether |
| 1217 | 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 | 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 | 1255 | * Remove an active timer from the queue. In case it is not queued |
| 1224 | 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 | 1282 | first = enqueue_hrtimer(timer, new_base, mode); |
| 1251 | − if (!force_local) | |
| 1252 | − return first; | |
| 1283 | + if (!force_local) { | |
| 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 | 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 | 1437 | * This function is called on PREEMPT_RT kernels when the fast path |
| 1375 | 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 | 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 | 1681 | while (i > 0) { |
| 1679 | 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 | 1719 | WARN_ON_ONCE(top == 0); |
| 1717 | 1720 | |
| 1718 | 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 | 1729 | * The target CPU must never do the prepare work, except |
| 1722 | 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 | 1672 | * must be the same. |
| 1673 | 1673 | */ |
| 1674 | 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 | 1678 | int subbuf_size = PAGE_SIZE; |
| 1678 | 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 | 1681 | unsigned long buffers_end; |
| 1681 | 1682 | int i; |
| 1682 | 1683 | |
| 1684 | + if (!subbuf_mask) | |
| 1685 | + return false; | |
| 1686 | + | |
| 1683 | 1687 | /* Check the meta magic and meta struct size */ |
| 1684 | 1688 | if (meta->magic != RING_BUFFER_META_MAGIC || |
| 1685 | 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 | 1717 | subbuf = rb_subbufs_from_meta(meta); |
| 1714 | 1718 | |
| 1719 | + bitmap_clear(subbuf_mask, 0, meta->nr_subbufs); | |
| 1720 | + | |
| 1715 | 1721 | /* Is the meta buffers and the subbufs themselves have correct data? */ |
| 1716 | 1722 | for (i = 0; i < meta->nr_subbufs; i++) { |
| 1717 | 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 | 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 | 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 | 1850 | cpu_buffer->cpu); |
| 1839 | 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 | 1858 | entries += ret; |
| 1842 | 1859 | entry_bytes += local_read(&head_page->page->commit); |
| 1843 | 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 | 1906 | static void rb_range_meta_init(struct trace_buffer *buffer, int nr_pages) |
| 1890 | 1907 | { |
| 1891 | 1908 | struct ring_buffer_meta *meta; |
| 1909 | + unsigned long *subbuf_mask; | |
| 1892 | 1910 | unsigned long delta; |
| 1893 | 1911 | void *subbuf; |
| 1894 | 1912 | int cpu; |
| 1895 | 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 | 1919 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) { |
| 1898 | 1920 | void *next_meta; |
| 1899 | 1921 | |
| 1900 | 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 | 1925 | /* Make the mappings match the current address */ |
| 1904 | 1926 | subbuf = rb_subbufs_from_meta(meta); |
| 1905 | 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 | 1965 | subbuf += meta->subbuf_size; |
| 1944 | 1966 | } |
| 1945 | 1967 | } |
| 1968 | + bitmap_free(subbuf_mask); | |
| 1946 | 1969 | } |
| 1947 | 1970 | |
| 1948 | 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 | 7149 | kfree(cpu_buffer->subbuf_ids); |
| 7127 | 7150 | cpu_buffer->subbuf_ids = NULL; |
| 7128 | 7151 | rb_free_meta_page(cpu_buffer); |
| 7152 | + atomic_dec(&cpu_buffer->resize_disabled); | |
| 7129 | 7153 | } |
| 7130 | 7154 | |
| 7131 | 7155 | unlock: |
| @@ -5977,8 +5977,6 @@ static int __tracing_resize_ring_buffer(struct trace_array *tr, · 5976 unmodified lines | ||
| 5977 | 5977 | ssize_t tracing_resize_ring_buffer(struct trace_array *tr, |
| 5978 | 5978 | unsigned long size, int cpu_id) |
| 5979 | 5979 | { |
| 5980 | − int ret; | |
| 5981 | − | |
| 5982 | 5980 | guard(mutex)(&trace_types_lock); |
| 5983 | 5981 | |
| 5984 | 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 | 5985 | return -EINVAL; |
| 5988 | 5986 | } |
| 5989 | 5987 | |
| 5990 | − ret = __tracing_resize_ring_buffer(tr, size, cpu_id); | |
| 5991 | − if (ret < 0) | |
| 5992 | − ret = -ENOMEM; | |
| 5993 | − | |
| 5994 | − return ret; | |
| 5988 | + return __tracing_resize_ring_buffer(tr, size, cpu_id); | |
| 5995 | 5989 | } |
| 5996 | 5990 | |
| 5997 | 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 | 8279 | struct trace_iterator *iter = &info->iter; |
| 8286 | 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 | 8286 | ret = get_snapshot_map(iter->tr); |
| 8289 | 8287 | if (ret) |
| 8290 | 8288 | return ret; |
| @@ -198,7 +198,7 @@ int trace_graph_entry(struct ftrace_graph_ent *trace, · 197 unmodified lines | ||
| 198 | 198 | * returning from the function. |
| 199 | 199 | */ |
| 200 | 200 | if (ftrace_graph_notrace_addr(trace->func)) { |
| 201 | − *task_var |= TRACE_GRAPH_NOTRACE_BIT; | |
| 201 | + *task_var |= TRACE_GRAPH_NOTRACE; | |
| 202 | 202 | /* |
| 203 | 203 | * Need to return 1 to have the return called |
| 204 | 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 | 3520 | * Leave this pool. Notify regular workers; otherwise, we end up |
| 3527 | 3521 | * with 0 concurrency and stalling the execution. |
| @@ -3532,6 +3526,12 @@ repeat: · 4 unmodified lines | ||
| 3532 | 3526 | |
| 3533 | 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.