We need the char-misc fixes in here as well.
Unified · Split
| @@ -31,11 +31,11 @@ properties: · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | clocks: | 32 | clocks: |
| 33 | minItems: 1 | 33 | minItems: 1 |
| 34 | maxItems: 3 | 34 | maxItems: 7 |
| 35 | 35 | ||
| 36 | clock-names: | 36 | clock-names: |
| 37 | minItems: 1 | 37 | minItems: 1 |
| 38 | maxItems: 3 | 38 | maxItems: 7 |
| 39 | 39 | ||
| 40 | required: | 40 | required: |
| 41 | - compatible | 41 | - compatible |
| @@ -72,6 +72,32 @@ allOf: · 30 unmodified lines | |||
| 72 | contains: | 72 | contains: |
| 73 | enum: | 73 | enum: |
| 74 | - qcom,sdm660-a2noc | 74 | - qcom,sdm660-a2noc |
| 75 | then: | ||
| 76 | properties: | ||
| 77 | clocks: | ||
| 78 | items: | ||
| 79 | - description: Bus Clock. | ||
| 80 | - description: Bus A Clock. | ||
| 81 | - description: IPA Clock. | ||
| 82 | - description: UFS AXI Clock. | ||
| 83 | - description: Aggregate2 UFS AXI Clock. | ||
| 84 | - description: Aggregate2 USB3 AXI Clock. | ||
| 85 | - description: Config NoC USB2 AXI Clock. | ||
| 86 | clock-names: | ||
| 87 | items: | ||
| 88 | - const: bus | ||
| 89 | - const: bus_a | ||
| 90 | - const: ipa | ||
| 91 | - const: ufs_axi | ||
| 92 | - const: aggre2_ufs_axi | ||
| 93 | - const: aggre2_usb3_axi | ||
| 94 | - const: cfg_noc_usb2_axi | ||
| 95 | |||
| 96 | - if: | ||
| 97 | properties: | ||
| 98 | compatible: | ||
| 99 | contains: | ||
| 100 | enum: | ||
| 75 | - qcom,sdm660-bimc | 101 | - qcom,sdm660-bimc |
| 76 | - qcom,sdm660-cnoc | 102 | - qcom,sdm660-cnoc |
| 77 | - qcom,sdm660-gnoc | 103 | - qcom,sdm660-gnoc |
| @@ -91,6 +117,7 @@ examples: · 13 unmodified lines | |||
| 91 | - | | 117 | - | |
| 92 | #include <dt-bindings/clock/qcom,rpmcc.h> | 118 | #include <dt-bindings/clock/qcom,rpmcc.h> |
| 93 | #include <dt-bindings/clock/qcom,mmcc-sdm660.h> | 119 | #include <dt-bindings/clock/qcom,mmcc-sdm660.h> |
| 120 | #include <dt-bindings/clock/qcom,gcc-sdm660.h> | ||
| 94 | 121 | ||
| 95 | bimc: interconnect@1008000 { | 122 | bimc: interconnect@1008000 { |
| 96 | compatible = "qcom,sdm660-bimc"; | 123 | compatible = "qcom,sdm660-bimc"; |
| @@ -123,9 +150,20 @@ examples: · 26 unmodified lines | |||
| 123 | compatible = "qcom,sdm660-a2noc"; | 150 | compatible = "qcom,sdm660-a2noc"; |
| 124 | reg = <0x01704000 0xc100>; | 151 | reg = <0x01704000 0xc100>; |
| 125 | #interconnect-cells = <1>; | 152 | #interconnect-cells = <1>; |
| 126 | clock-names = "bus", "bus_a"; | 153 | clock-names = "bus", |
| 154 | "bus_a", | ||
| 155 | "ipa", | ||
| 156 | "ufs_axi", | ||
| 157 | "aggre2_ufs_axi", | ||
| 158 | "aggre2_usb3_axi", | ||
| 159 | "cfg_noc_usb2_axi"; | ||
| 127 | clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>, | 160 | clocks = <&rpmcc RPM_SMD_AGGR2_NOC_CLK>, |
| 128 | <&rpmcc RPM_SMD_AGGR2_NOC_A_CLK>; | 161 | <&rpmcc RPM_SMD_AGGR2_NOC_A_CLK>, |
| 162 | <&rpmcc RPM_SMD_IPA_CLK>, | ||
| 163 | <&gcc GCC_UFS_AXI_CLK>, | ||
| 164 | <&gcc GCC_AGGRE2_UFS_AXI_CLK>, | ||
| 165 | <&gcc GCC_AGGRE2_USB3_AXI_CLK>, | ||
| 166 | <&gcc GCC_CFG_NOC_USB2_AXI_CLK>; | ||
| 129 | }; | 167 | }; |
| 130 | 168 | ||
| 131 | mnoc: interconnect@1745000 { | 169 | mnoc: interconnect@1745000 { |
| @@ -132,20 +132,3 @@ On Family 17h and Family 18h CPUs, additional temperature sensors may report · 131 unmodified lines | |||
| 132 | Core Complex Die (CCD) temperatures. Up to 8 such temperatures are reported | 132 | Core Complex Die (CCD) temperatures. Up to 8 such temperatures are reported |
| 133 | as temp{3..10}_input, labeled Tccd{1..8}. Actual support depends on the CPU | 133 | as temp{3..10}_input, labeled Tccd{1..8}. Actual support depends on the CPU |
| 134 | variant. | 134 | variant. |
| 135 | |||
| 136 | Various Family 17h and 18h CPUs report voltage and current telemetry | ||
| 137 | information. The following attributes may be reported. | ||
| 138 | |||
| 139 | Attribute Label Description | ||
| 140 | =============== ======= ================ | ||
| 141 | in0_input Vcore Core voltage | ||
| 142 | in1_input Vsoc SoC voltage | ||
| 143 | curr1_input Icore Core current | ||
| 144 | curr2_input Isoc SoC current | ||
| 145 | =============== ======= ================ | ||
| 146 | |||
| 147 | Current values are raw (unscaled) as reported by the CPU. Core current is | ||
| 148 | reported as multiples of 1A / LSB. SoC is reported as multiples of 0.25A | ||
| 149 | / LSB. The real current is board specific. Reported currents should be seen | ||
| 150 | as rough guidance, and should be scaled using sensors3.conf as appropriate | ||
| 151 | for a given board. | ||
| @@ -414,7 +414,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm · 413 unmodified lines | |||
| 414 | F: drivers/acpi/pmic/ | 414 | F: drivers/acpi/pmic/ |
| 415 | 415 | ||
| 416 | ACPI THERMAL DRIVER | 416 | ACPI THERMAL DRIVER |
| 417 | M: Zhang Rui <rui.zhang@intel.com> | 417 | M: Rafael J. Wysocki <rafael@kernel.org> |
| 418 | R: Zhang Rui <rui.zhang@intel.com> | ||
| 418 | L: linux-acpi@vger.kernel.org | 419 | L: linux-acpi@vger.kernel.org |
| 419 | S: Supported | 420 | S: Supported |
| 420 | W: https://01.org/linux-acpi | 421 | W: https://01.org/linux-acpi |
| @@ -810,7 +811,7 @@ F: Documentation/devicetree/bindings/dma/altr,msgdma.yaml · 389 unmodified lines | |||
| 810 | F: drivers/dma/altera-msgdma.c | 811 | F: drivers/dma/altera-msgdma.c |
| 811 | 812 | ||
| 812 | ALTERA PIO DRIVER | 813 | ALTERA PIO DRIVER |
| 813 | M: Joyce Ooi <joyce.ooi@intel.com> | 814 | M: Mun Yew Tham <mun.yew.tham@intel.com> |
| 814 | L: linux-gpio@vger.kernel.org | 815 | L: linux-gpio@vger.kernel.org |
| 815 | S: Maintained | 816 | S: Maintained |
| 816 | F: drivers/gpio/gpio-altera.c | 817 | F: drivers/gpio/gpio-altera.c |
| @@ -2961,7 +2962,7 @@ F: crypto/async_tx/ · 2144 unmodified lines | |||
| 2961 | F: include/linux/async_tx.h | 2962 | F: include/linux/async_tx.h |
| 2962 | 2963 | ||
| 2963 | AT24 EEPROM DRIVER | 2964 | AT24 EEPROM DRIVER |
| 2964 | M: Bartosz Golaszewski <bgolaszewski@baylibre.com> | 2965 | M: Bartosz Golaszewski <brgl@bgdev.pl> |
| 2965 | L: linux-i2c@vger.kernel.org | 2966 | L: linux-i2c@vger.kernel.org |
| 2966 | S: Maintained | 2967 | S: Maintained |
| 2967 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git | 2968 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git |
| @@ -3384,9 +3385,11 @@ F: Documentation/networking/filter.rst · 416 unmodified lines | |||
| 3384 | F: Documentation/userspace-api/ebpf/ | 3385 | F: Documentation/userspace-api/ebpf/ |
| 3385 | F: arch/*/net/* | 3386 | F: arch/*/net/* |
| 3386 | F: include/linux/bpf* | 3387 | F: include/linux/bpf* |
| 3388 | F: include/linux/btf* | ||
| 3387 | F: include/linux/filter.h | 3389 | F: include/linux/filter.h |
| 3388 | F: include/trace/events/xdp.h | 3390 | F: include/trace/events/xdp.h |
| 3389 | F: include/uapi/linux/bpf* | 3391 | F: include/uapi/linux/bpf* |
| 3392 | F: include/uapi/linux/btf* | ||
| 3390 | F: include/uapi/linux/filter.h | 3393 | F: include/uapi/linux/filter.h |
| 3391 | F: kernel/bpf/ | 3394 | F: kernel/bpf/ |
| 3392 | F: kernel/trace/bpf_trace.c | 3395 | F: kernel/trace/bpf_trace.c |
| @@ -3820,7 +3823,6 @@ F: drivers/scsi/mpi3mr/ · 427 unmodified lines | |||
| 3820 | 3823 | ||
| 3821 | BROADCOM NETXTREME-E ROCE DRIVER | 3824 | BROADCOM NETXTREME-E ROCE DRIVER |
| 3822 | M: Selvin Xavier <selvin.xavier@broadcom.com> | 3825 | M: Selvin Xavier <selvin.xavier@broadcom.com> |
| 3823 | M: Naresh Kumar PBS <nareshkumar.pbs@broadcom.com> | ||
| 3824 | L: linux-rdma@vger.kernel.org | 3826 | L: linux-rdma@vger.kernel.org |
| 3825 | S: Supported | 3827 | S: Supported |
| 3826 | W: http://www.broadcom.com | 3828 | W: http://www.broadcom.com |
| @@ -4655,7 +4657,7 @@ W: http://linux-cifs.samba.org/ · 828 unmodified lines | |||
| 4655 | T: git git://git.samba.org/sfrench/cifs-2.6.git | 4657 | T: git git://git.samba.org/sfrench/cifs-2.6.git |
| 4656 | F: Documentation/admin-guide/cifs/ | 4658 | F: Documentation/admin-guide/cifs/ |
| 4657 | F: fs/cifs/ | 4659 | F: fs/cifs/ |
| 4658 | F: fs/cifs_common/ | 4660 | F: fs/smbfs_common/ |
| 4659 | 4661 | ||
| 4660 | COMPACTPCI HOTPLUG CORE | 4662 | COMPACTPCI HOTPLUG CORE |
| 4661 | M: Scott Murray <scott@spiteful.org> | 4663 | M: Scott Murray <scott@spiteful.org> |
| @@ -7985,7 +7987,7 @@ F: include/linux/gpio/regmap.h · 3323 unmodified lines | |||
| 7985 | 7987 | ||
| 7986 | GPIO SUBSYSTEM | 7988 | GPIO SUBSYSTEM |
| 7987 | M: Linus Walleij <linus.walleij@linaro.org> | 7989 | M: Linus Walleij <linus.walleij@linaro.org> |
| 7988 | M: Bartosz Golaszewski <bgolaszewski@baylibre.com> | 7990 | M: Bartosz Golaszewski <brgl@bgdev.pl> |
| 7989 | L: linux-gpio@vger.kernel.org | 7991 | L: linux-gpio@vger.kernel.org |
| 7990 | S: Maintained | 7992 | S: Maintained |
| 7991 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git | 7993 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git |
| @@ -10193,8 +10195,8 @@ M: Hyunchul Lee <hyc.lee@gmail.com> · 2201 unmodified lines | |||
| 10193 | L: linux-cifs@vger.kernel.org | 10195 | L: linux-cifs@vger.kernel.org |
| 10194 | S: Maintained | 10196 | S: Maintained |
| 10195 | T: git git://git.samba.org/ksmbd.git | 10197 | T: git git://git.samba.org/ksmbd.git |
| 10196 | F: fs/cifs_common/ | ||
| 10197 | F: fs/ksmbd/ | 10198 | F: fs/ksmbd/ |
| 10199 | F: fs/smbfs_common/ | ||
| 10198 | 10200 | ||
| 10199 | KERNEL UNIT TESTING FRAMEWORK (KUnit) | 10201 | KERNEL UNIT TESTING FRAMEWORK (KUnit) |
| 10200 | M: Brendan Higgins <brendanhiggins@google.com> | 10202 | M: Brendan Higgins <brendanhiggins@google.com> |
| @@ -11366,7 +11368,7 @@ F: Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.yaml · 1165 unmodified lines | |||
| 11366 | F: drivers/iio/proximity/mb1232.c | 11368 | F: drivers/iio/proximity/mb1232.c |
| 11367 | 11369 | ||
| 11368 | MAXIM MAX77650 PMIC MFD DRIVER | 11370 | MAXIM MAX77650 PMIC MFD DRIVER |
| 11369 | M: Bartosz Golaszewski <bgolaszewski@baylibre.com> | 11371 | M: Bartosz Golaszewski <brgl@bgdev.pl> |
| 11370 | L: linux-kernel@vger.kernel.org | 11372 | L: linux-kernel@vger.kernel.org |
| 11371 | S: Maintained | 11373 | S: Maintained |
| 11372 | F: Documentation/devicetree/bindings/*/*max77650.yaml | 11374 | F: Documentation/devicetree/bindings/*/*max77650.yaml |
| @@ -17883,7 +17885,8 @@ M: Olivier Moysan <olivier.moysan@foss.st.com> · 6510 unmodified lines | |||
| 17883 | M: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com> | 17885 | M: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com> |
| 17884 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 17886 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
| 17885 | S: Maintained | 17887 | S: Maintained |
| 17886 | F: Documentation/devicetree/bindings/iio/adc/st,stm32-*.yaml | 17888 | F: Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml |
| 17889 | F: Documentation/devicetree/bindings/sound/st,stm32-*.yaml | ||
| 17887 | F: sound/soc/stm/ | 17890 | F: sound/soc/stm/ |
| 17888 | 17891 | ||
| 17889 | STM32 TIMER/LPTIMER DRIVERS | 17892 | STM32 TIMER/LPTIMER DRIVERS |
| @@ -18547,13 +18550,14 @@ T: git git://linuxtv.org/media_tree.git · 657 unmodified lines | |||
| 18547 | F: drivers/media/radio/radio-raremono.c | 18550 | F: drivers/media/radio/radio-raremono.c |
| 18548 | 18551 | ||
| 18549 | THERMAL | 18552 | THERMAL |
| 18550 | M: Zhang Rui <rui.zhang@intel.com> | 18553 | M: Rafael J. Wysocki <rafael@kernel.org> |
| 18551 | M: Daniel Lezcano <daniel.lezcano@linaro.org> | 18554 | M: Daniel Lezcano <daniel.lezcano@linaro.org> |
| 18552 | R: Amit Kucheria <amitk@kernel.org> | 18555 | R: Amit Kucheria <amitk@kernel.org> |
| 18556 | R: Zhang Rui <rui.zhang@intel.com> | ||
| 18553 | L: linux-pm@vger.kernel.org | 18557 | L: linux-pm@vger.kernel.org |
| 18554 | S: Supported | 18558 | S: Supported |
| 18555 | Q: https://patchwork.kernel.org/project/linux-pm/list/ | 18559 | Q: https://patchwork.kernel.org/project/linux-pm/list/ |
| 18556 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git | 18560 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git thermal |
| 18557 | F: Documentation/devicetree/bindings/thermal/ | 18561 | F: Documentation/devicetree/bindings/thermal/ |
| 18558 | F: drivers/thermal/ | 18562 | F: drivers/thermal/ |
| 18559 | F: include/linux/cpu_cooling.h | 18563 | F: include/linux/cpu_cooling.h |
| @@ -18682,7 +18686,7 @@ F: include/linux/clk/ti.h · 122 unmodified lines | |||
| 18682 | 18686 | ||
| 18683 | TI DAVINCI MACHINE SUPPORT | 18687 | TI DAVINCI MACHINE SUPPORT |
| 18684 | M: Sekhar Nori <nsekhar@ti.com> | 18688 | M: Sekhar Nori <nsekhar@ti.com> |
| 18685 | R: Bartosz Golaszewski <bgolaszewski@baylibre.com> | 18689 | R: Bartosz Golaszewski <brgl@bgdev.pl> |
| 18686 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 18690 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 18687 | S: Supported | 18691 | S: Supported |
| 18688 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git | 18692 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 5 | 2 | VERSION = 5 |
| 3 | PATCHLEVEL = 15 | 3 | PATCHLEVEL = 15 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc3 | 5 | EXTRAVERSION = -rc4 |
| 6 | NAME = Opossums on Parade | 6 | NAME = Opossums on Parade |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -54,7 +54,7 @@ $(obj)/kvm_nvhe.tmp.o: $(obj)/hyp.lds $(addprefix $(obj)/,$(hyp-obj)) FORCE · 53 unmodified lines | |||
| 54 | # runtime. Because the hypervisor is part of the kernel binary, relocations | 54 | # runtime. Because the hypervisor is part of the kernel binary, relocations |
| 55 | # produce a kernel VA. We enumerate relocations targeting hyp at build time | 55 | # produce a kernel VA. We enumerate relocations targeting hyp at build time |
| 56 | # and convert the kernel VAs at those positions to hyp VAs. | 56 | # and convert the kernel VAs at those positions to hyp VAs. |
| 57 | $(obj)/hyp-reloc.S: $(obj)/kvm_nvhe.tmp.o $(obj)/gen-hyprel | 57 | $(obj)/hyp-reloc.S: $(obj)/kvm_nvhe.tmp.o $(obj)/gen-hyprel FORCE |
| 58 | $(call if_changed,hyprel) | 58 | $(call if_changed,hyprel) |
| 59 | 59 | ||
| 60 | # 5) Compile hyp-reloc.S and link it into the existing partially linked object. | 60 | # 5) Compile hyp-reloc.S and link it into the existing partially linked object. |
| @@ -50,9 +50,6 @@ static struct perf_guest_info_callbacks kvm_guest_cbs = { · 49 unmodified lines | |||
| 50 | 50 | ||
| 51 | int kvm_perf_init(void) | 51 | int kvm_perf_init(void) |
| 52 | { | 52 | { |
| 53 | if (kvm_pmu_probe_pmuver() != ID_AA64DFR0_PMUVER_IMP_DEF && !is_protected_kvm_enabled()) | ||
| 54 | static_branch_enable(&kvm_arm_pmu_available); | ||
| 55 | |||
| 56 | return perf_register_guest_info_callbacks(&kvm_guest_cbs); | 53 | return perf_register_guest_info_callbacks(&kvm_guest_cbs); |
| 57 | } | 54 | } |
| 58 | 55 | ||
| @@ -740,7 +740,14 @@ void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data, · 739 unmodified lines | |||
| 740 | kvm_pmu_create_perf_event(vcpu, select_idx); | 740 | kvm_pmu_create_perf_event(vcpu, select_idx); |
| 741 | } | 741 | } |
| 742 | 742 | ||
| 743 | int kvm_pmu_probe_pmuver(void) | 743 | void kvm_host_pmu_init(struct arm_pmu *pmu) |
| 744 | { | ||
| 745 | if (pmu->pmuver != 0 && pmu->pmuver != ID_AA64DFR0_PMUVER_IMP_DEF && | ||
| 746 | !kvm_arm_support_pmu_v3() && !is_protected_kvm_enabled()) | ||
| 747 | static_branch_enable(&kvm_arm_pmu_available); | ||
| 748 | } | ||
| 749 | |||
| 750 | static int kvm_pmu_probe_pmuver(void) | ||
| 744 | { | 751 | { |
| 745 | struct perf_event_attr attr = { }; | 752 | struct perf_event_attr attr = { }; |
| 746 | struct perf_event *event; | 753 | struct perf_event *event; |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | |||
| 15 | #include <asm/unistd.h> | 15 | #include <asm/unistd.h> |
| 16 | #include <asm/errno.h> | 16 | #include <asm/errno.h> |
| 17 | #include <asm/setup.h> | 17 | #include <asm/setup.h> |
| 18 | #include <asm/segment.h> | ||
| 19 | #include <asm/traps.h> | 18 | #include <asm/traps.h> |
| 20 | #include <asm/asm-offsets.h> | 19 | #include <asm/asm-offsets.h> |
| 21 | #include <asm/entry.h> | 20 | #include <asm/entry.h> |
| @@ -25,7 +24,6 @@ · 3 unmodified lines | |||
| 25 | .globl system_call | 24 | .globl system_call |
| 26 | .globl resume | 25 | .globl resume |
| 27 | .globl ret_from_exception | 26 | .globl ret_from_exception |
| 28 | .globl ret_from_signal | ||
| 29 | .globl sys_call_table | 27 | .globl sys_call_table |
| 30 | .globl bad_interrupt | 28 | .globl bad_interrupt |
| 31 | .globl inthandler1 | 29 | .globl inthandler1 |
| @@ -59,8 +57,6 @@ do_trace: · 27 unmodified lines | |||
| 59 | subql #4,%sp /* dummy return address */ | 57 | subql #4,%sp /* dummy return address */ |
| 60 | SAVE_SWITCH_STACK | 58 | SAVE_SWITCH_STACK |
| 61 | jbsr syscall_trace_leave | 59 | jbsr syscall_trace_leave |
| 62 | |||
| 63 | ret_from_signal: | ||
| 64 | RESTORE_SWITCH_STACK | 60 | RESTORE_SWITCH_STACK |
| 65 | addql #4,%sp | 61 | addql #4,%sp |
| 66 | jra ret_from_exception | 62 | jra ret_from_exception |
| @@ -29,7 +29,6 @@ config M68K · 28 unmodified lines | |||
| 29 | select NO_DMA if !MMU && !COLDFIRE | 29 | select NO_DMA if !MMU && !COLDFIRE |
| 30 | select OLD_SIGACTION | 30 | select OLD_SIGACTION |
| 31 | select OLD_SIGSUSPEND3 | 31 | select OLD_SIGSUSPEND3 |
| 32 | select SET_FS | ||
| 33 | select UACCESS_MEMCPY if !MMU | 32 | select UACCESS_MEMCPY if !MMU |
| 34 | select VIRT_TO_BUS | 33 | select VIRT_TO_BUS |
| 35 | select ZONE_DMA | 34 | select ZONE_DMA |
| @@ -31,7 +31,6 @@ · 30 unmodified lines | |||
| 31 | #include <asm/thread_info.h> | 31 | #include <asm/thread_info.h> |
| 32 | #include <asm/errno.h> | 32 | #include <asm/errno.h> |
| 33 | #include <asm/setup.h> | 33 | #include <asm/setup.h> |
| 34 | #include <asm/segment.h> | ||
| 35 | #include <asm/asm-offsets.h> | 34 | #include <asm/asm-offsets.h> |
| 36 | #include <asm/entry.h> | 35 | #include <asm/entry.h> |
| 37 | 36 | ||
| @@ -51,7 +50,6 @@ sw_usp: · 13 unmodified lines | |||
| 51 | .globl system_call | 50 | .globl system_call |
| 52 | .globl resume | 51 | .globl resume |
| 53 | .globl ret_from_exception | 52 | .globl ret_from_exception |
| 54 | .globl ret_from_signal | ||
| 55 | .globl sys_call_table | 53 | .globl sys_call_table |
| 56 | .globl inthandler | 54 | .globl inthandler |
| 57 | 55 | ||
| @@ -98,8 +96,6 @@ ENTRY(system_call) · 40 unmodified lines | |||
| 98 | subql #4,%sp /* dummy return address */ | 96 | subql #4,%sp /* dummy return address */ |
| 99 | SAVE_SWITCH_STACK | 97 | SAVE_SWITCH_STACK |
| 100 | jbsr syscall_trace_leave | 98 | jbsr syscall_trace_leave |
| 101 | |||
| 102 | ret_from_signal: | ||
| 103 | RESTORE_SWITCH_STACK | 99 | RESTORE_SWITCH_STACK |
| 104 | addql #4,%sp | 100 | addql #4,%sp |
| 105 | 101 | ||
| @@ -9,7 +9,6 @@ · 8 unmodified lines | |||
| 9 | #define __ASM_M68K_PROCESSOR_H | 9 | #define __ASM_M68K_PROCESSOR_H |
| 10 | 10 | ||
| 11 | #include <linux/thread_info.h> | 11 | #include <linux/thread_info.h> |
| 12 | #include <asm/segment.h> | ||
| 13 | #include <asm/fpu.h> | 12 | #include <asm/fpu.h> |
| 14 | #include <asm/ptrace.h> | 13 | #include <asm/ptrace.h> |
| 15 | 14 | ||
| @@ -75,11 +74,37 @@ static inline void wrusp(unsigned long usp) · 59 unmodified lines | |||
| 75 | #define TASK_UNMAPPED_BASE 0 | 74 | #define TASK_UNMAPPED_BASE 0 |
| 76 | #endif | 75 | #endif |
| 77 | 76 | ||
| 77 | /* Address spaces (or Function Codes in Motorola lingo) */ | ||
| 78 | #define USER_DATA 1 | ||
| 79 | #define USER_PROGRAM 2 | ||
| 80 | #define SUPER_DATA 5 | ||
| 81 | #define SUPER_PROGRAM 6 | ||
| 82 | #define CPU_SPACE 7 | ||
| 83 | |||
| 84 | #ifdef CONFIG_CPU_HAS_ADDRESS_SPACES | ||
| 85 | /* | ||
| 86 | * Set the SFC/DFC registers for special MM operations. For most normal | ||
| 87 | * operation these remain set to USER_DATA for the uaccess routines. | ||
| 88 | */ | ||
| 89 | static inline void set_fc(unsigned long val) | ||
| 90 | { | ||
| 91 | WARN_ON_ONCE(in_interrupt()); | ||
| 92 | |||
| 93 | __asm__ __volatile__ ("movec %0,%/sfc\n\t" | ||
| 94 | "movec %0,%/dfc\n\t" | ||
| 95 | : /* no outputs */ : "r" (val) : "memory"); | ||
| 96 | } | ||
| 97 | #else | ||
| 98 | static inline void set_fc(unsigned long val) | ||
| 99 | { | ||
| 100 | } | ||
| 101 | #endif /* CONFIG_CPU_HAS_ADDRESS_SPACES */ | ||
| 102 | |||
| 78 | struct thread_struct { | 103 | struct thread_struct { |
| 79 | unsigned long ksp; /* kernel stack pointer */ | 104 | unsigned long ksp; /* kernel stack pointer */ |
| 80 | unsigned long usp; /* user stack pointer */ | 105 | unsigned long usp; /* user stack pointer */ |
| 81 | unsigned short sr; /* saved status register */ | 106 | unsigned short sr; /* saved status register */ |
| 82 | unsigned short fs; /* saved fs (sfc, dfc) */ | 107 | unsigned short fc; /* saved fc (sfc, dfc) */ |
| 83 | unsigned long crp[2]; /* cpu root pointer */ | 108 | unsigned long crp[2]; /* cpu root pointer */ |
| 84 | unsigned long esp0; /* points to SR of stack frame */ | 109 | unsigned long esp0; /* points to SR of stack frame */ |
| 85 | unsigned long faddr; /* info about last fault */ | 110 | unsigned long faddr; /* info about last fault */ |
| @@ -92,7 +117,7 @@ struct thread_struct { · 6 unmodified lines | |||
| 92 | #define INIT_THREAD { \ | 117 | #define INIT_THREAD { \ |
| 93 | .ksp = sizeof(init_stack) + (unsigned long) init_stack, \ | 118 | .ksp = sizeof(init_stack) + (unsigned long) init_stack, \ |
| 94 | .sr = PS_S, \ | 119 | .sr = PS_S, \ |
| 95 | .fs = __KERNEL_DS, \ | 120 | .fc = USER_DATA, \ |
| 96 | } | 121 | } |
| 97 | 122 | ||
| 98 | /* | 123 | /* |
| @@ -1,59 +0,0 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | #ifndef _M68K_SEGMENT_H | ||
| 3 | #define _M68K_SEGMENT_H | ||
| 4 | |||
| 5 | /* define constants */ | ||
| 6 | /* Address spaces (FC0-FC2) */ | ||
| 7 | #define USER_DATA (1) | ||
| 8 | #ifndef __USER_DS | ||
| 9 | #define __USER_DS (USER_DATA) | ||
| 10 | #endif | ||
| 11 | #define USER_PROGRAM (2) | ||
| 12 | #define SUPER_DATA (5) | ||
| 13 | #ifndef __KERNEL_DS | ||
| 14 | #define __KERNEL_DS (SUPER_DATA) | ||
| 15 | #endif | ||
| 16 | #define SUPER_PROGRAM (6) | ||
| 17 | #define CPU_SPACE (7) | ||
| 18 | |||
| 19 | #ifndef __ASSEMBLY__ | ||
| 20 | |||
| 21 | typedef struct { | ||
| 22 | unsigned long seg; | ||
| 23 | } mm_segment_t; | ||
| 24 | |||
| 25 | #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) | ||
| 26 | |||
| 27 | #ifdef CONFIG_CPU_HAS_ADDRESS_SPACES | ||
| 28 | /* | ||
| 29 | * Get/set the SFC/DFC registers for MOVES instructions | ||
| 30 | */ | ||
| 31 | #define USER_DS MAKE_MM_SEG(__USER_DS) | ||
| 32 | #define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS) | ||
| 33 | |||
| 34 | static inline mm_segment_t get_fs(void) | ||
| 35 | { | ||
| 36 | mm_segment_t _v; | ||
| 37 | __asm__ ("movec %/dfc,%0":"=r" (_v.seg):); | ||
| 38 | return _v; | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline void set_fs(mm_segment_t val) | ||
| 42 | { | ||
| 43 | __asm__ __volatile__ ("movec %0,%/sfc\n\t" | ||
| 44 | "movec %0,%/dfc\n\t" | ||
| 45 | : /* no outputs */ : "r" (val.seg) : "memory"); | ||
| 46 | } | ||
| 47 | |||
| 48 | #else | ||
| 49 | #define USER_DS MAKE_MM_SEG(TASK_SIZE) | ||
| 50 | #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) | ||
| 51 | #define get_fs() (current_thread_info()->addr_limit) | ||
| 52 | #define set_fs(x) (current_thread_info()->addr_limit = (x)) | ||
| 53 | #endif | ||
| 54 | |||
| 55 | #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) | ||
| 56 | |||
| 57 | #endif /* __ASSEMBLY__ */ | ||
| 58 | |||
| 59 | #endif /* _M68K_SEGMENT_H */ | ||
| @@ -4,7 +4,6 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <asm/types.h> | 5 | #include <asm/types.h> |
| 6 | #include <asm/page.h> | 6 | #include <asm/page.h> |
| 7 | #include <asm/segment.h> | ||
| 8 | 7 | ||
| 9 | /* | 8 | /* |
| 10 | * On machines with 4k pages we default to an 8k thread size, though we | 9 | * On machines with 4k pages we default to an 8k thread size, though we |
| @@ -27,7 +26,6 @@ · 16 unmodified lines | |||
| 27 | struct thread_info { | 26 | struct thread_info { |
| 28 | struct task_struct *task; /* main task structure */ | 27 | struct task_struct *task; /* main task structure */ |
| 29 | unsigned long flags; | 28 | unsigned long flags; |
| 30 | mm_segment_t addr_limit; /* thread address space */ | ||
| 31 | int preempt_count; /* 0 => preemptable, <0 => BUG */ | 29 | int preempt_count; /* 0 => preemptable, <0 => BUG */ |
| 32 | __u32 cpu; /* should always be 0 on m68k */ | 30 | __u32 cpu; /* should always be 0 on m68k */ |
| 33 | unsigned long tp_value; /* thread pointer */ | 31 | unsigned long tp_value; /* thread pointer */ |
| @@ -37,7 +35,6 @@ struct thread_info { · 3 unmodified lines | |||
| 37 | #define INIT_THREAD_INFO(tsk) \ | 35 | #define INIT_THREAD_INFO(tsk) \ |
| 38 | { \ | 36 | { \ |
| 39 | .task = &tsk, \ | 37 | .task = &tsk, \ |
| 40 | .addr_limit = KERNEL_DS, \ | ||
| 41 | .preempt_count = INIT_PREEMPT_COUNT, \ | 38 | .preempt_count = INIT_PREEMPT_COUNT, \ |
| 42 | } | 39 | } |
| 43 | 40 | ||
| @@ -13,13 +13,12 @@ static inline void flush_tlb_kernel_page(void *addr) · 12 unmodified lines | |||
| 13 | if (CPU_IS_COLDFIRE) { | 13 | if (CPU_IS_COLDFIRE) { |
| 14 | mmu_write(MMUOR, MMUOR_CNL); | 14 | mmu_write(MMUOR, MMUOR_CNL); |
| 15 | } else if (CPU_IS_040_OR_060) { | 15 | } else if (CPU_IS_040_OR_060) { |
| 16 | mm_segment_t old_fs = get_fs(); | 16 | set_fc(SUPER_DATA); |
| 17 | set_fs(KERNEL_DS); | ||
| 18 | __asm__ __volatile__(".chip 68040\n\t" | 17 | __asm__ __volatile__(".chip 68040\n\t" |
| 19 | "pflush (%0)\n\t" | 18 | "pflush (%0)\n\t" |
| 20 | ".chip 68k" | 19 | ".chip 68k" |
| 21 | : : "a" (addr)); | 20 | : : "a" (addr)); |
| 22 | set_fs(old_fs); | 21 | set_fc(USER_DATA); |
| 23 | } else if (CPU_IS_020_OR_030) | 22 | } else if (CPU_IS_020_OR_030) |
| 24 | __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr)); | 23 | __asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr)); |
| 25 | } | 24 | } |
| @@ -84,12 +83,8 @@ static inline void flush_tlb_mm(struct mm_struct *mm) · 58 unmodified lines | |||
| 84 | 83 | ||
| 85 | static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) | 84 | static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) |
| 86 | { | 85 | { |
| 87 | if (vma->vm_mm == current->active_mm) { | 86 | if (vma->vm_mm == current->active_mm) |
| 88 | mm_segment_t old_fs = force_uaccess_begin(); | ||
| 89 | |||
| 90 | __flush_tlb_one(addr); | 87 | __flush_tlb_one(addr); |
| 91 | force_uaccess_end(old_fs); | ||
| 92 | } | ||
| 93 | } | 88 | } |
| 94 | 89 | ||
| 95 | static inline void flush_tlb_range(struct vm_area_struct *vma, | 90 | static inline void flush_tlb_range(struct vm_area_struct *vma, |
| @@ -267,6 +267,10 @@ struct frame { · 266 unmodified lines | |||
| 267 | } un; | 267 | } un; |
| 268 | }; | 268 | }; |
| 269 | 269 | ||
| 270 | #ifdef CONFIG_M68040 | ||
| 271 | asmlinkage void berr_040cleanup(struct frame *fp); | ||
| 272 | #endif | ||
| 273 | |||
| 270 | #endif /* __ASSEMBLY__ */ | 274 | #endif /* __ASSEMBLY__ */ |
| 271 | 275 | ||
| 272 | #endif /* _M68K_TRAPS_H */ | 276 | #endif /* _M68K_TRAPS_H */ |
| @@ -9,13 +9,16 @@ · 8 unmodified lines | |||
| 9 | */ | 9 | */ |
| 10 | #include <linux/compiler.h> | 10 | #include <linux/compiler.h> |
| 11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
| 12 | #include <asm/segment.h> | ||
| 13 | #include <asm/extable.h> | 12 | #include <asm/extable.h> |
| 14 | 13 | ||
| 15 | /* We let the MMU do all checking */ | 14 | /* We let the MMU do all checking */ |
| 16 | static inline int access_ok(const void __user *addr, | 15 | static inline int access_ok(const void __user *addr, |
| 17 | unsigned long size) | 16 | unsigned long size) |
| 18 | { | 17 | { |
| 18 | /* | ||
| 19 | * XXX: for !CONFIG_CPU_HAS_ADDRESS_SPACES this really needs to check | ||
| 20 | * for TASK_SIZE! | ||
| 21 | */ | ||
| 19 | return 1; | 22 | return 1; |
| 20 | } | 23 | } |
| 21 | 24 | ||
| @@ -35,12 +38,9 @@ static inline int access_ok(const void __user *addr, · 13 unmodified lines | |||
| 35 | #define MOVES "move" | 38 | #define MOVES "move" |
| 36 | #endif | 39 | #endif |
| 37 | 40 | ||
| 38 | extern int __put_user_bad(void); | 41 | #define __put_user_asm(inst, res, x, ptr, bwl, reg, err) \ |
| 39 | extern int __get_user_bad(void); | ||
| 40 | |||
| 41 | #define __put_user_asm(res, x, ptr, bwl, reg, err) \ | ||
| 42 | asm volatile ("\n" \ | 42 | asm volatile ("\n" \ |
| 43 | "1: "MOVES"."#bwl" %2,%1\n" \ | 43 | "1: "inst"."#bwl" %2,%1\n" \ |
| 44 | "2:\n" \ | 44 | "2:\n" \ |
| 45 | " .section .fixup,\"ax\"\n" \ | 45 | " .section .fixup,\"ax\"\n" \ |
| 46 | " .even\n" \ | 46 | " .even\n" \ |
| @@ -56,6 +56,31 @@ asm volatile ("\n" \ · 9 unmodified lines | |||
| 56 | : "+d" (res), "=m" (*(ptr)) \ | 56 | : "+d" (res), "=m" (*(ptr)) \ |
| 57 | : #reg (x), "i" (err)) | 57 | : #reg (x), "i" (err)) |
| 58 | 58 | ||
| 59 | #define __put_user_asm8(inst, res, x, ptr) \ | ||
| 60 | do { \ | ||
| 61 | const void *__pu_ptr = (const void __force *)(ptr); \ | ||
| 62 | \ | ||
| 63 | asm volatile ("\n" \ | ||
| 64 | "1: "inst".l %2,(%1)+\n" \ | ||
| 65 | "2: "inst".l %R2,(%1)\n" \ | ||
| 66 | "3:\n" \ | ||
| 67 | " .section .fixup,\"ax\"\n" \ | ||
| 68 | " .even\n" \ | ||
| 69 | "10: movel %3,%0\n" \ | ||
| 70 | " jra 3b\n" \ | ||
| 71 | " .previous\n" \ | ||
| 72 | "\n" \ | ||
| 73 | " .section __ex_table,\"a\"\n" \ | ||
| 74 | " .align 4\n" \ | ||
| 75 | " .long 1b,10b\n" \ | ||
| 76 | " .long 2b,10b\n" \ | ||
| 77 | " .long 3b,10b\n" \ | ||
| 78 | " .previous" \ | ||
| 79 | : "+d" (res), "+a" (__pu_ptr) \ | ||
| 80 | : "r" (x), "i" (-EFAULT) \ | ||
| 81 | : "memory"); \ | ||
| 82 | } while (0) | ||
| 83 | |||
| 59 | /* | 84 | /* |
| 60 | * These are the main single-value transfer routines. They automatically | 85 | * These are the main single-value transfer routines. They automatically |
| 61 | * use the right size if we just have the right pointer type. | 86 | * use the right size if we just have the right pointer type. |
| @@ -68,51 +93,29 @@ asm volatile ("\n" \ · 6 unmodified lines | |||
| 68 | __chk_user_ptr(ptr); \ | 93 | __chk_user_ptr(ptr); \ |
| 69 | switch (sizeof (*(ptr))) { \ | 94 | switch (sizeof (*(ptr))) { \ |
| 70 | case 1: \ | 95 | case 1: \ |
| 71 | __put_user_asm(__pu_err, __pu_val, ptr, b, d, -EFAULT); \ | 96 | __put_user_asm(MOVES, __pu_err, __pu_val, ptr, b, d, -EFAULT); \ |
| 72 | break; \ | 97 | break; \ |
| 73 | case 2: \ | 98 | case 2: \ |
| 74 | __put_user_asm(__pu_err, __pu_val, ptr, w, r, -EFAULT); \ | 99 | __put_user_asm(MOVES, __pu_err, __pu_val, ptr, w, r, -EFAULT); \ |
| 75 | break; \ | 100 | break; \ |
| 76 | case 4: \ | 101 | case 4: \ |
| 77 | __put_user_asm(__pu_err, __pu_val, ptr, l, r, -EFAULT); \ | 102 | __put_user_asm(MOVES, __pu_err, __pu_val, ptr, l, r, -EFAULT); \ |
| 78 | break; \ | 103 | break; \ |
| 79 | case 8: \ | 104 | case 8: \ |
| 80 | { \ | 105 | __put_user_asm8(MOVES, __pu_err, __pu_val, ptr); \ |
| 81 | const void __user *__pu_ptr = (ptr); \ | ||
| 82 | asm volatile ("\n" \ | ||
| 83 | "1: "MOVES".l %2,(%1)+\n" \ | ||
| 84 | "2: "MOVES".l %R2,(%1)\n" \ | ||
| 85 | "3:\n" \ | ||
| 86 | " .section .fixup,\"ax\"\n" \ | ||
| 87 | " .even\n" \ | ||
| 88 | "10: movel %3,%0\n" \ | ||
| 89 | " jra 3b\n" \ | ||
| 90 | " .previous\n" \ | ||
| 91 | "\n" \ | ||
| 92 | " .section __ex_table,\"a\"\n" \ | ||
| 93 | " .align 4\n" \ | ||
| 94 | " .long 1b,10b\n" \ | ||
| 95 | " .long 2b,10b\n" \ | ||
| 96 | " .long 3b,10b\n" \ | ||
| 97 | " .previous" \ | ||
| 98 | : "+d" (__pu_err), "+a" (__pu_ptr) \ | ||
| 99 | : "r" (__pu_val), "i" (-EFAULT) \ | ||
| 100 | : "memory"); \ | ||
| 101 | break; \ | 106 | break; \ |
| 102 | } \ | ||
| 103 | default: \ | 107 | default: \ |
| 104 | __pu_err = __put_user_bad(); \ | 108 | BUILD_BUG(); \ |
| 105 | break; \ | ||
| 106 | } \ | 109 | } \ |
| 107 | __pu_err; \ | 110 | __pu_err; \ |
| 108 | }) | 111 | }) |
| 109 | #define put_user(x, ptr) __put_user(x, ptr) | 112 | #define put_user(x, ptr) __put_user(x, ptr) |
| 110 | 113 | ||
| 111 | 114 | ||
| 112 | #define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({ \ | 115 | #define __get_user_asm(inst, res, x, ptr, type, bwl, reg, err) ({ \ |
| 113 | type __gu_val; \ | 116 | type __gu_val; \ |
| 114 | asm volatile ("\n" \ | 117 | asm volatile ("\n" \ |
| 115 | "1: "MOVES"."#bwl" %2,%1\n" \ | 118 | "1: "inst"."#bwl" %2,%1\n" \ |
| 116 | "2:\n" \ | 119 | "2:\n" \ |
| 117 | " .section .fixup,\"ax\"\n" \ | 120 | " .section .fixup,\"ax\"\n" \ |
| 118 | " .even\n" \ | 121 | " .even\n" \ |
| @@ -130,53 +133,57 @@ asm volatile ("\n" \ · 11 unmodified lines | |||
| 130 | (x) = (__force typeof(*(ptr)))(__force unsigned long)__gu_val; \ | 133 | (x) = (__force typeof(*(ptr)))(__force unsigned long)__gu_val; \ |
| 131 | }) | 134 | }) |
| 132 | 135 | ||
| 136 | #define __get_user_asm8(inst, res, x, ptr) \ | ||
| 137 | do { \ | ||
| 138 | const void *__gu_ptr = (const void __force *)(ptr); \ | ||
| 139 | union { \ | ||
| 140 | u64 l; \ | ||
| 141 | __typeof__(*(ptr)) t; \ | ||
| 142 | } __gu_val; \ | ||
| 143 | \ | ||
| 144 | asm volatile ("\n" \ | ||
| 145 | "1: "inst".l (%2)+,%1\n" \ | ||
| 146 | "2: "inst".l (%2),%R1\n" \ | ||
| 147 | "3:\n" \ | ||
| 148 | " .section .fixup,\"ax\"\n" \ | ||
| 149 | " .even\n" \ | ||
| 150 | "10: move.l %3,%0\n" \ | ||
| 151 | " sub.l %1,%1\n" \ | ||
| 152 | " sub.l %R1,%R1\n" \ | ||
| 153 | " jra 3b\n" \ | ||
| 154 | " .previous\n" \ | ||
| 155 | "\n" \ | ||
| 156 | " .section __ex_table,\"a\"\n" \ | ||
| 157 | " .align 4\n" \ | ||
| 158 | " .long 1b,10b\n" \ | ||
| 159 | " .long 2b,10b\n" \ | ||
| 160 | " .previous" \ | ||
| 161 | : "+d" (res), "=&r" (__gu_val.l), \ | ||
| 162 | "+a" (__gu_ptr) \ | ||
| 163 | : "i" (-EFAULT) \ | ||
| 164 | : "memory"); \ | ||
| 165 | (x) = __gu_val.t; \ | ||
| 166 | } while (0) | ||
| 167 | |||
| 133 | #define __get_user(x, ptr) \ | 168 | #define __get_user(x, ptr) \ |
| 134 | ({ \ | 169 | ({ \ |
| 135 | int __gu_err = 0; \ | 170 | int __gu_err = 0; \ |
| 136 | __chk_user_ptr(ptr); \ | 171 | __chk_user_ptr(ptr); \ |
| 137 | switch (sizeof(*(ptr))) { \ | 172 | switch (sizeof(*(ptr))) { \ |
| 138 | case 1: \ | 173 | case 1: \ |
| 139 | __get_user_asm(__gu_err, x, ptr, u8, b, d, -EFAULT); \ | 174 | __get_user_asm(MOVES, __gu_err, x, ptr, u8, b, d, -EFAULT); \ |
| 140 | break; \ | 175 | break; \ |
| 141 | case 2: \ | 176 | case 2: \ |
| 142 | __get_user_asm(__gu_err, x, ptr, u16, w, r, -EFAULT); \ | 177 | __get_user_asm(MOVES, __gu_err, x, ptr, u16, w, r, -EFAULT); \ |
| 143 | break; \ | 178 | break; \ |
| 144 | case 4: \ | 179 | case 4: \ |
| 145 | __get_user_asm(__gu_err, x, ptr, u32, l, r, -EFAULT); \ | 180 | __get_user_asm(MOVES, __gu_err, x, ptr, u32, l, r, -EFAULT); \ |
| 146 | break; \ | 181 | break; \ |
| 147 | case 8: { \ | 182 | case 8: \ |
| 148 | const void __user *__gu_ptr = (ptr); \ | 183 | __get_user_asm8(MOVES, __gu_err, x, ptr); \ |
| 149 | union { \ | ||
| 150 | u64 l; \ | ||
| 151 | __typeof__(*(ptr)) t; \ | ||
| 152 | } __gu_val; \ | ||
| 153 | asm volatile ("\n" \ | ||
| 154 | "1: "MOVES".l (%2)+,%1\n" \ | ||
| 155 | "2: "MOVES".l (%2),%R1\n" \ | ||
| 156 | "3:\n" \ | ||
| 157 | " .section .fixup,\"ax\"\n" \ | ||
| 158 | " .even\n" \ | ||
| 159 | "10: move.l %3,%0\n" \ | ||
| 160 | " sub.l %1,%1\n" \ | ||
| 161 | " sub.l %R1,%R1\n" \ | ||
| 162 | " jra 3b\n" \ | ||
| 163 | " .previous\n" \ | ||
| 164 | "\n" \ | ||
| 165 | " .section __ex_table,\"a\"\n" \ | ||
| 166 | " .align 4\n" \ | ||
| 167 | " .long 1b,10b\n" \ | ||
| 168 | " .long 2b,10b\n" \ | ||
| 169 | " .previous" \ | ||
| 170 | : "+d" (__gu_err), "=&r" (__gu_val.l), \ | ||
| 171 | "+a" (__gu_ptr) \ | ||
| 172 | : "i" (-EFAULT) \ | ||
| 173 | : "memory"); \ | ||
| 174 | (x) = __gu_val.t; \ | ||
| 175 | break; \ | 184 | break; \ |
| 176 | } \ | ||
| 177 | default: \ | 185 | default: \ |
| 178 | __gu_err = __get_user_bad(); \ | 186 | BUILD_BUG(); \ |
| 179 | break; \ | ||
| 180 | } \ | 187 | } \ |
| 181 | __gu_err; \ | 188 | __gu_err; \ |
| 182 | }) | 189 | }) |
| @@ -322,16 +329,19 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n) · 139 unmodified lines | |||
| 322 | 329 | ||
| 323 | switch (n) { | 330 | switch (n) { |
| 324 | case 1: | 331 | case 1: |
| 325 | __put_user_asm(res, *(u8 *)from, (u8 __user *)to, b, d, 1); | 332 | __put_user_asm(MOVES, res, *(u8 *)from, (u8 __user *)to, |
| 333 | b, d, 1); | ||
| 326 | break; | 334 | break; |
| 327 | case 2: | 335 | case 2: |
| 328 | __put_user_asm(res, *(u16 *)from, (u16 __user *)to, w, r, 2); | 336 | __put_user_asm(MOVES, res, *(u16 *)from, (u16 __user *)to, |
| 337 | w, r, 2); | ||
| 329 | break; | 338 | break; |
| 330 | case 3: | 339 | case 3: |
| 331 | __constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,); | 340 | __constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,); |
| 332 | break; | 341 | break; |
| 333 | case 4: | 342 | case 4: |
| 334 | __put_user_asm(res, *(u32 *)from, (u32 __user *)to, l, r, 4); | 343 | __put_user_asm(MOVES, res, *(u32 *)from, (u32 __user *)to, |
| 344 | l, r, 4); | ||
| 335 | break; | 345 | break; |
| 336 | case 5: | 346 | case 5: |
| 337 | __constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,); | 347 | __constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,); |
| @@ -380,8 +390,65 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n) · 42 unmodified lines | |||
| 380 | #define INLINE_COPY_FROM_USER | 390 | #define INLINE_COPY_FROM_USER |
| 381 | #define INLINE_COPY_TO_USER | 391 | #define INLINE_COPY_TO_USER |
| 382 | 392 | ||
| 383 | #define user_addr_max() \ | 393 | #define HAVE_GET_KERNEL_NOFAULT |
| 384 | (uaccess_kernel() ? ~0UL : TASK_SIZE) | 394 | |
| 395 | #define __get_kernel_nofault(dst, src, type, err_label) \ | ||
| 396 | do { \ | ||
| 397 | type *__gk_dst = (type *)(dst); \ | ||
| 398 | type *__gk_src = (type *)(src); \ | ||
| 399 | int __gk_err = 0; \ | ||
| 400 | \ | ||
| 401 | switch (sizeof(type)) { \ | ||
| 402 | case 1: \ | ||
| 403 | __get_user_asm("move", __gk_err, *__gk_dst, __gk_src, \ | ||
| 404 | u8, b, d, -EFAULT); \ | ||
| 405 | break; \ | ||
| 406 | case 2: \ | ||
| 407 | __get_user_asm("move", __gk_err, *__gk_dst, __gk_src, \ | ||
| 408 | u16, w, r, -EFAULT); \ | ||
| 409 | break; \ | ||
| 410 | case 4: \ | ||
| 411 | __get_user_asm("move", __gk_err, *__gk_dst, __gk_src, \ | ||
| 412 | u32, l, r, -EFAULT); \ | ||
| 413 | break; \ | ||
| 414 | case 8: \ | ||
| 415 | __get_user_asm8("move", __gk_err, *__gk_dst, __gk_src); \ | ||
| 416 | break; \ | ||
| 417 | default: \ | ||
| 418 | BUILD_BUG(); \ | ||
| 419 | } \ | ||
| 420 | if (unlikely(__gk_err)) \ | ||
| 421 | goto err_label; \ | ||
| 422 | } while (0) | ||
| 423 | |||
| 424 | #define __put_kernel_nofault(dst, src, type, err_label) \ | ||
| 425 | do { \ | ||
| 426 | type __pk_src = *(type *)(src); \ | ||
| 427 | type *__pk_dst = (type *)(dst); \ | ||
| 428 | int __pk_err = 0; \ | ||
| 429 | \ | ||
| 430 | switch (sizeof(type)) { \ | ||
| 431 | case 1: \ | ||
| 432 | __put_user_asm("move", __pk_err, __pk_src, __pk_dst, \ | ||
| 433 | b, d, -EFAULT); \ | ||
| 434 | break; \ | ||
| 435 | case 2: \ | ||
| 436 | __put_user_asm("move", __pk_err, __pk_src, __pk_dst, \ | ||
| 437 | w, r, -EFAULT); \ | ||
| 438 | break; \ | ||
| 439 | case 4: \ | ||
| 440 | __put_user_asm("move", __pk_err, __pk_src, __pk_dst, \ | ||
| 441 | l, r, -EFAULT); \ | ||
| 442 | break; \ | ||
| 443 | case 8: \ | ||
| 444 | __put_user_asm8("move", __pk_err, __pk_src, __pk_dst); \ | ||
| 445 | break; \ | ||
| 446 | default: \ | ||
| 447 | BUILD_BUG(); \ | ||
| 448 | } \ | ||
| 449 | if (unlikely(__pk_err)) \ | ||
| 450 | goto err_label; \ | ||
| 451 | } while (0) | ||
| 385 | 452 | ||
| 386 | extern long strncpy_from_user(char *dst, const char __user *src, long count); | 453 | extern long strncpy_from_user(char *dst, const char __user *src, long count); |
| 387 | extern __must_check long strnlen_user(const char __user *str, long n); | 454 | extern __must_check long strnlen_user(const char __user *str, long n); |
| @@ -31,7 +31,7 @@ int main(void) · 30 unmodified lines | |||
| 31 | DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); | 31 | DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); |
| 32 | DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); | 32 | DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); |
| 33 | DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); | 33 | DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); |
| 34 | DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); | 34 | DEFINE(THREAD_FC, offsetof(struct thread_struct, fc)); |
| 35 | DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); | 35 | DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); |
| 36 | DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); | 36 | DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); |
| 37 | DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); | 37 | DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); |
| @@ -36,7 +36,6 @@ · 35 unmodified lines | |||
| 36 | #include <linux/linkage.h> | 36 | #include <linux/linkage.h> |
| 37 | #include <asm/errno.h> | 37 | #include <asm/errno.h> |
| 38 | #include <asm/setup.h> | 38 | #include <asm/setup.h> |
| 39 | #include <asm/segment.h> | ||
| 40 | #include <asm/traps.h> | 39 | #include <asm/traps.h> |
| 41 | #include <asm/unistd.h> | 40 | #include <asm/unistd.h> |
| 42 | #include <asm/asm-offsets.h> | 41 | #include <asm/asm-offsets.h> |
| @@ -78,20 +77,38 @@ ENTRY(__sys_clone3) · 35 unmodified lines | |||
| 78 | 77 | ||
| 79 | ENTRY(sys_sigreturn) | 78 | ENTRY(sys_sigreturn) |
| 80 | SAVE_SWITCH_STACK | 79 | SAVE_SWITCH_STACK |
| 81 | movel %sp,%sp@- | switch_stack pointer | 80 | movel %sp,%a1 | switch_stack pointer |
| 82 | pea %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer | 81 | lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer |
| 82 | lea %sp@(-84),%sp | leave a gap | ||
| 83 | movel %a1,%sp@- | ||
| 84 | movel %a0,%sp@- | ||
| 83 | jbsr do_sigreturn | 85 | jbsr do_sigreturn |
| 84 | addql #8,%sp | 86 | jra 1f | shared with rt_sigreturn() |
| 85 | RESTORE_SWITCH_STACK | ||
| 86 | rts | ||
| 87 | 87 | ||
| 88 | ENTRY(sys_rt_sigreturn) | 88 | ENTRY(sys_rt_sigreturn) |
| 89 | SAVE_SWITCH_STACK | 89 | SAVE_SWITCH_STACK |
| 90 | movel %sp,%sp@- | switch_stack pointer | 90 | movel %sp,%a1 | switch_stack pointer |
| 91 | pea %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer | 91 | lea %sp@(SWITCH_STACK_SIZE),%a0 | pt_regs pointer |
| 92 | lea %sp@(-84),%sp | leave a gap | ||
| 93 | movel %a1,%sp@- | ||
| 94 | movel %a0,%sp@- | ||
| 95 | | stack contents: | ||
| 96 | | [original pt_regs address] [original switch_stack address] | ||
| 97 | | [gap] [switch_stack] [pt_regs] [exception frame] | ||
| 92 | jbsr do_rt_sigreturn | 98 | jbsr do_rt_sigreturn |
| 93 | addql #8,%sp | 99 | |
| 100 | 1: | ||
| 101 | | stack contents now: | ||
| 102 | | [original pt_regs address] [original switch_stack address] | ||
| 103 | | [unused part of the gap] [moved switch_stack] [moved pt_regs] | ||
| 104 | | [replacement exception frame] | ||
| 105 | | return value of do_{rt_,}sigreturn() points to moved switch_stack. | ||
| 106 | |||
| 107 | movel %d0,%sp | discard the leftover junk | ||
| 94 | RESTORE_SWITCH_STACK | 108 | RESTORE_SWITCH_STACK |
| 109 | | stack contents now is just [syscall return address] [pt_regs] [frame] | ||
| 110 | | return pt_regs.d0 | ||
| 111 | movel %sp@(PT_OFF_D0+4),%d0 | ||
| 95 | rts | 112 | rts |
| 96 | 113 | ||
| 97 | ENTRY(buserr) | 114 | ENTRY(buserr) |
| @@ -182,25 +199,6 @@ do_trace_exit: · 84 unmodified lines | |||
| 182 | addql #4,%sp | 199 | addql #4,%sp |
| 183 | jra .Lret_from_exception | 200 | jra .Lret_from_exception |
| 184 | 201 | ||
| 185 | ENTRY(ret_from_signal) | ||
| 186 | movel %curptr@(TASK_STACK),%a1 | ||
| 187 | tstb %a1@(TINFO_FLAGS+2) | ||
| 188 | jge 1f | ||
| 189 | jbsr syscall_trace | ||
| 190 | 1: RESTORE_SWITCH_STACK | ||
| 191 | addql #4,%sp | ||
| 192 | /* on 68040 complete pending writebacks if any */ | ||
| 193 | #ifdef CONFIG_M68040 | ||
| 194 | bfextu %sp@(PT_OFF_FORMATVEC){#0,#4},%d0 | ||
| 195 | subql #7,%d0 | bus error frame ? | ||
| 196 | jbne 1f | ||
| 197 | movel %sp,%sp@- | ||
| 198 | jbsr berr_040cleanup | ||
| 199 | addql #4,%sp | ||
| 200 | 1: | ||
| 201 | #endif | ||
| 202 | jra .Lret_from_exception | ||
| 203 | |||
| 204 | ENTRY(system_call) | 202 | ENTRY(system_call) |
| 205 | SAVE_ALL_SYS | 203 | SAVE_ALL_SYS |
| 206 | 204 | ||
| @@ -338,7 +336,7 @@ resume: · 131 unmodified lines | |||
| 338 | 336 | ||
| 339 | /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ | 337 | /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ |
| 340 | movec %sfc,%d0 | 338 | movec %sfc,%d0 |
| 341 | movew %d0,%a0@(TASK_THREAD+THREAD_FS) | 339 | movew %d0,%a0@(TASK_THREAD+THREAD_FC) |
| 342 | 340 | ||
| 343 | /* save usp */ | 341 | /* save usp */ |
| 344 | /* it is better to use a movel here instead of a movew 8*) */ | 342 | /* it is better to use a movel here instead of a movew 8*) */ |
| @@ -424,7 +422,7 @@ resume: · 79 unmodified lines | |||
| 424 | movel %a0,%usp | 422 | movel %a0,%usp |
| 425 | 423 | ||
| 426 | /* restore fs (sfc,%dfc) */ | 424 | /* restore fs (sfc,%dfc) */ |
| 427 | movew %a1@(TASK_THREAD+THREAD_FS),%a0 | 425 | movew %a1@(TASK_THREAD+THREAD_FC),%a0 |
| 428 | movec %a0,%sfc | 426 | movec %a0,%sfc |
| 429 | movec %a0,%dfc | 427 | movec %a0,%dfc |
| 430 | 428 | ||
| @@ -92,7 +92,7 @@ void show_regs(struct pt_regs * regs) · 91 unmodified lines | |||
| 92 | 92 | ||
| 93 | void flush_thread(void) | 93 | void flush_thread(void) |
| 94 | { | 94 | { |
| 95 | current->thread.fs = __USER_DS; | 95 | current->thread.fc = USER_DATA; |
| 96 | #ifdef CONFIG_FPU | 96 | #ifdef CONFIG_FPU |
| 97 | if (!FPU_IS_EMU) { | 97 | if (!FPU_IS_EMU) { |
| 98 | unsigned long zero = 0; | 98 | unsigned long zero = 0; |
| @@ -155,7 +155,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, · 56 unmodified lines | |||
| 155 | * Must save the current SFC/DFC value, NOT the value when | 155 | * Must save the current SFC/DFC value, NOT the value when |
| 156 | * the parent was last descheduled - RGH 10-08-96 | 156 | * the parent was last descheduled - RGH 10-08-96 |
| 157 | */ | 157 | */ |
| 158 | p->thread.fs = get_fs().seg; | 158 | p->thread.fc = USER_DATA; |
| 159 | 159 | ||
| 160 | if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { | 160 | if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { |
| 161 | /* kernel thread */ | 161 | /* kernel thread */ |
| @@ -447,7 +447,7 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) · 446 unmodified lines | |||
| 447 | 447 | ||
| 448 | if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { | 448 | if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { |
| 449 | fpu_version = sc->sc_fpstate[0]; | 449 | fpu_version = sc->sc_fpstate[0]; |
| 450 | if (CPU_IS_020_OR_030 && | 450 | if (CPU_IS_020_OR_030 && !regs->stkadj && |
| 451 | regs->vector >= (VEC_FPBRUC * 4) && | 451 | regs->vector >= (VEC_FPBRUC * 4) && |
| 452 | regs->vector <= (VEC_FPNAN * 4)) { | 452 | regs->vector <= (VEC_FPNAN * 4)) { |
| 453 | /* Clear pending exception in 68882 idle frame */ | 453 | /* Clear pending exception in 68882 idle frame */ |
| @@ -510,7 +510,7 @@ static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs * · 56 unmodified lines | |||
| 510 | if (!(CPU_IS_060 || CPU_IS_COLDFIRE)) | 510 | if (!(CPU_IS_060 || CPU_IS_COLDFIRE)) |
| 511 | context_size = fpstate[1]; | 511 | context_size = fpstate[1]; |
| 512 | fpu_version = fpstate[0]; | 512 | fpu_version = fpstate[0]; |
| 513 | if (CPU_IS_020_OR_030 && | 513 | if (CPU_IS_020_OR_030 && !regs->stkadj && |
| 514 | regs->vector >= (VEC_FPBRUC * 4) && | 514 | regs->vector >= (VEC_FPBRUC * 4) && |
| 515 | regs->vector <= (VEC_FPNAN * 4)) { | 515 | regs->vector <= (VEC_FPNAN * 4)) { |
| 516 | /* Clear pending exception in 68882 idle frame */ | 516 | /* Clear pending exception in 68882 idle frame */ |
| @@ -641,56 +641,35 @@ static inline void siginfo_build_tests(void) · 124 unmodified lines | |||
| 641 | static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, | 641 | static int mangle_kernel_stack(struct pt_regs *regs, int formatvec, |
| 642 | void __user *fp) | 642 | void __user *fp) |
| 643 | { | 643 | { |
| 644 | int fsize = frame_extra_sizes(formatvec >> 12); | 644 | int extra = frame_extra_sizes(formatvec >> 12); |
| 645 | if (fsize < 0) { | 645 | char buf[sizeof_field(struct frame, un)]; |
| 646 | |||
| 647 | if (extra < 0) { | ||
| 646 | /* | 648 | /* |
| 647 | * user process trying to return with weird frame format | 649 | * user process trying to return with weird frame format |
| 648 | */ | 650 | */ |
| 649 | pr_debug("user process returning with weird frame format\n"); | 651 | pr_debug("user process returning with weird frame format\n"); |
| 650 | return 1; | 652 | return -1; |
| 651 | } | 653 | } |
| 652 | if (!fsize) { | 654 | if (extra && copy_from_user(buf, fp, extra)) |
| 653 | regs->format = formatvec >> 12; | 655 | return -1; |
| 654 | regs->vector = formatvec & 0xfff; | 656 | regs->format = formatvec >> 12; |
| 655 | } else { | 657 | regs->vector = formatvec & 0xfff; |
| 656 | struct switch_stack *sw = (struct switch_stack *)regs - 1; | 658 | if (extra) { |
| 657 | /* yes, twice as much as max(sizeof(frame.un.fmt<x>)) */ | 659 | void *p = (struct switch_stack *)regs - 1; |
| 658 | unsigned long buf[sizeof_field(struct frame, un) / 2]; | 660 | struct frame *new = (void *)regs - extra; |
| 659 | 661 | int size = sizeof(struct pt_regs)+sizeof(struct switch_stack); | |
| 660 | /* that'll make sure that expansion won't crap over data */ | 662 | |
| 661 | if (copy_from_user(buf + fsize / 4, fp, fsize)) | 663 | memmove(p - extra, p, size); |
| 662 | return 1; | 664 | memcpy(p - extra + size, buf, extra); |
| 663 | 665 | current->thread.esp0 = (unsigned long)&new->ptregs; | |
| 664 | /* point of no return */ | 666 | #ifdef CONFIG_M68040 |
| 665 | regs->format = formatvec >> 12; | 667 | /* on 68040 complete pending writebacks if any */ |
| 666 | regs->vector = formatvec & 0xfff; | 668 | if (new->ptregs.format == 7) // bus error frame |
| 667 | #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) | 669 | berr_040cleanup(new); |
| 668 | __asm__ __volatile__ ( | ||
| 669 | #ifdef CONFIG_COLDFIRE | ||
| 670 | " movel %0,%/sp\n\t" | ||
| 671 | " bra ret_from_signal\n" | ||
| 672 | #else | ||
| 673 | " movel %0,%/a0\n\t" | ||
| 674 | " subl %1,%/a0\n\t" /* make room on stack */ | ||
| 675 | " movel %/a0,%/sp\n\t" /* set stack pointer */ | ||
| 676 | /* move switch_stack and pt_regs */ | ||
| 677 | "1: movel %0@+,%/a0@+\n\t" | ||
| 678 | " dbra %2,1b\n\t" | ||
| 679 | " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ | ||
| 680 | " lsrl #2,%1\n\t" | ||
| 681 | " subql #1,%1\n\t" | ||
| 682 | /* copy to the gap we'd made */ | ||
| 683 | "2: movel %4@+,%/a0@+\n\t" | ||
| 684 | " dbra %1,2b\n\t" | ||
| 685 | " bral ret_from_signal\n" | ||
| 686 | #endif | 670 | #endif |
| 687 | : /* no outputs, it doesn't ever return */ | ||
| 688 | : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), | ||
| 689 | "n" (frame_offset), "a" (buf + fsize/4) | ||
| 690 | : "a0"); | ||
| 691 | #undef frame_offset | ||
| 692 | } | 671 | } |
| 693 | return 0; | 672 | return extra; |
| 694 | } | 673 | } |
| 695 | 674 | ||
| 696 | static inline int | 675 | static inline int |
| @@ -698,7 +677,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u · 1 unmodified line | |||
| 698 | { | 677 | { |
| 699 | int formatvec; | 678 | int formatvec; |
| 700 | struct sigcontext context; | 679 | struct sigcontext context; |
| 701 | int err = 0; | ||
| 702 | 680 | ||
| 703 | siginfo_build_tests(); | 681 | siginfo_build_tests(); |
| 704 | 682 | ||
| @@ -707,7 +685,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u · 2 unmodified lines | |||
| 707 | 685 | ||
| 708 | /* get previous context */ | 686 | /* get previous context */ |
| 709 | if (copy_from_user(&context, usc, sizeof(context))) | 687 | if (copy_from_user(&context, usc, sizeof(context))) |
| 710 | goto badframe; | 688 | return -1; |
| 711 | 689 | ||
| 712 | /* restore passed registers */ | 690 | /* restore passed registers */ |
| 713 | regs->d0 = context.sc_d0; | 691 | regs->d0 = context.sc_d0; |
| @@ -720,15 +698,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u · 6 unmodified lines | |||
| 720 | wrusp(context.sc_usp); | 698 | wrusp(context.sc_usp); |
| 721 | formatvec = context.sc_formatvec; | 699 | formatvec = context.sc_formatvec; |
| 722 | 700 | ||
| 723 | err = restore_fpu_state(&context); | 701 | if (restore_fpu_state(&context)) |
| 702 | return -1; | ||
| 724 | 703 | ||
| 725 | if (err || mangle_kernel_stack(regs, formatvec, fp)) | 704 | return mangle_kernel_stack(regs, formatvec, fp); |
| 726 | goto badframe; | ||
| 727 | |||
| 728 | return 0; | ||
| 729 | |||
| 730 | badframe: | ||
| 731 | return 1; | ||
| 732 | } | 705 | } |
| 733 | 706 | ||
| 734 | static inline int | 707 | static inline int |
| @@ -745,7 +718,7 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, · 10 unmodified lines | |||
| 745 | 718 | ||
| 746 | err = __get_user(temp, &uc->uc_mcontext.version); | 719 | err = __get_user(temp, &uc->uc_mcontext.version); |
| 747 | if (temp != MCONTEXT_VERSION) | 720 | if (temp != MCONTEXT_VERSION) |
| 748 | goto badframe; | 721 | return -1; |
| 749 | /* restore passed registers */ | 722 | /* restore passed registers */ |
| 750 | err |= __get_user(regs->d0, &gregs[0]); | 723 | err |= __get_user(regs->d0, &gregs[0]); |
| 751 | err |= __get_user(regs->d1, &gregs[1]); | 724 | err |= __get_user(regs->d1, &gregs[1]); |
| @@ -774,22 +747,17 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, · 22 unmodified lines | |||
| 774 | err |= restore_altstack(&uc->uc_stack); | 747 | err |= restore_altstack(&uc->uc_stack); |
| 775 | 748 | ||
| 776 | if (err) | 749 | if (err) |
| 777 | goto badframe; | 750 | return -1; |
| 778 | 751 | ||
| 779 | if (mangle_kernel_stack(regs, temp, &uc->uc_extra)) | 752 | return mangle_kernel_stack(regs, temp, &uc->uc_extra); |
| 780 | goto badframe; | ||
| 781 | |||
| 782 | return 0; | ||
| 783 | |||
| 784 | badframe: | ||
| 785 | return 1; | ||
| 786 | } | 753 | } |
| 787 | 754 | ||
| 788 | asmlinkage int do_sigreturn(struct pt_regs *regs, struct switch_stack *sw) | 755 | asmlinkage void *do_sigreturn(struct pt_regs *regs, struct switch_stack *sw) |
| 789 | { | 756 | { |
| 790 | unsigned long usp = rdusp(); | 757 | unsigned long usp = rdusp(); |
| 791 | struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); | 758 | struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); |
| 792 | sigset_t set; | 759 | sigset_t set; |
| 760 | int size; | ||
| 793 | 761 | ||
| 794 | if (!access_ok(frame, sizeof(*frame))) | 762 | if (!access_ok(frame, sizeof(*frame))) |
| 795 | goto badframe; | 763 | goto badframe; |
| @@ -801,20 +769,22 @@ asmlinkage int do_sigreturn(struct pt_regs *regs, struct switch_stack *sw) · 5 unmodified lines | |||
| 801 | 769 | ||
| 802 | set_current_blocked(&set); | 770 | set_current_blocked(&set); |
| 803 | 771 | ||
| 804 | if (restore_sigcontext(regs, &frame->sc, frame + 1)) | 772 | size = restore_sigcontext(regs, &frame->sc, frame + 1); |
| 773 | if (size < 0) | ||
| 805 | goto badframe; | 774 | goto badframe; |
| 806 | return regs->d0; | 775 | return (void *)sw - size; |
| 807 | 776 | ||
| 808 | badframe: | 777 | badframe: |
| 809 | force_sig(SIGSEGV); | 778 | force_sig(SIGSEGV); |
| 810 | return 0; | 779 | return sw; |
| 811 | } | 780 | } |
| 812 | 781 | ||
| 813 | asmlinkage int do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw) | 782 | asmlinkage void *do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw) |
| 814 | { | 783 | { |
| 815 | unsigned long usp = rdusp(); | 784 | unsigned long usp = rdusp(); |
| 816 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); | 785 | struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); |
| 817 | sigset_t set; | 786 | sigset_t set; |
| 787 | int size; | ||
| 818 | 788 | ||
| 819 | if (!access_ok(frame, sizeof(*frame))) | 789 | if (!access_ok(frame, sizeof(*frame))) |
| 820 | goto badframe; | 790 | goto badframe; |
| @@ -823,27 +793,34 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw) · 2 unmodified lines | |||
| 823 | 793 | ||
| 824 | set_current_blocked(&set); | 794 | set_current_blocked(&set); |
| 825 | 795 | ||
| 826 | if (rt_restore_ucontext(regs, sw, &frame->uc)) | 796 | size = rt_restore_ucontext(regs, sw, &frame->uc); |
| 797 | if (size < 0) | ||
| 827 | goto badframe; | 798 | goto badframe; |
| 828 | return regs->d0; | 799 | return (void *)sw - size; |
| 829 | 800 | ||
| 830 | badframe: | 801 | badframe: |
| 831 | force_sig(SIGSEGV); | 802 | force_sig(SIGSEGV); |
| 832 | return 0; | 803 | return sw; |
| 804 | } | ||
| 805 | |||
| 806 | static inline struct pt_regs *rte_regs(struct pt_regs *regs) | ||
| 807 | { | ||
| 808 | return (void *)regs + regs->stkadj; | ||
| 833 | } | 809 | } |
| 834 | 810 | ||
| 835 | static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, | 811 | static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, |
| 836 | unsigned long mask) | 812 | unsigned long mask) |
| 837 | { | 813 | { |
| 814 | struct pt_regs *tregs = rte_regs(regs); | ||
| 838 | sc->sc_mask = mask; | 815 | sc->sc_mask = mask; |
| 839 | sc->sc_usp = rdusp(); | 816 | sc->sc_usp = rdusp(); |
| 840 | sc->sc_d0 = regs->d0; | 817 | sc->sc_d0 = regs->d0; |
| 841 | sc->sc_d1 = regs->d1; | 818 | sc->sc_d1 = regs->d1; |
| 842 | sc->sc_a0 = regs->a0; | 819 | sc->sc_a0 = regs->a0; |
| 843 | sc->sc_a1 = regs->a1; | 820 | sc->sc_a1 = regs->a1; |
| 844 | sc->sc_sr = regs->sr; | 821 | sc->sc_sr = tregs->sr; |
| 845 | sc->sc_pc = regs->pc; | 822 | sc->sc_pc = tregs->pc; |
| 846 | sc->sc_formatvec = regs->format << 12 | regs->vector; | 823 | sc->sc_formatvec = tregs->format << 12 | tregs->vector; |
| 847 | save_a5_state(sc, regs); | 824 | save_a5_state(sc, regs); |
| 848 | save_fpu_state(sc, regs); | 825 | save_fpu_state(sc, regs); |
| 849 | } | 826 | } |
| @@ -851,6 +828,7 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, · 1 unmodified line | |||
| 851 | static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs) | 828 | static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs) |
| 852 | { | 829 | { |
| 853 | struct switch_stack *sw = (struct switch_stack *)regs - 1; | 830 | struct switch_stack *sw = (struct switch_stack *)regs - 1; |
| 831 | struct pt_regs *tregs = rte_regs(regs); | ||
| 854 | greg_t __user *gregs = uc->uc_mcontext.gregs; | 832 | greg_t __user *gregs = uc->uc_mcontext.gregs; |
| 855 | int err = 0; | 833 | int err = 0; |
| 856 | 834 | ||
| @@ -871,9 +849,9 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs * · 14 unmodified lines | |||
| 871 | err |= __put_user(sw->a5, &gregs[13]); | 849 | err |= __put_user(sw->a5, &gregs[13]); |
| 872 | err |= __put_user(sw->a6, &gregs[14]); | 850 | err |= __put_user(sw->a6, &gregs[14]); |
| 873 | err |= __put_user(rdusp(), &gregs[15]); | 851 | err |= __put_user(rdusp(), &gregs[15]); |
| 874 | err |= __put_user(regs->pc, &gregs[16]); | 852 | err |= __put_user(tregs->pc, &gregs[16]); |
| 875 | err |= __put_user(regs->sr, &gregs[17]); | 853 | err |= __put_user(tregs->sr, &gregs[17]); |
| 876 | err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec); | 854 | err |= __put_user((tregs->format << 12) | tregs->vector, &uc->uc_formatvec); |
| 877 | err |= rt_save_fpu_state(uc, regs); | 855 | err |= rt_save_fpu_state(uc, regs); |
| 878 | return err; | 856 | return err; |
| 879 | } | 857 | } |
| @@ -890,13 +868,14 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, · 10 unmodified lines | |||
| 890 | struct pt_regs *regs) | 868 | struct pt_regs *regs) |
| 891 | { | 869 | { |
| 892 | struct sigframe __user *frame; | 870 | struct sigframe __user *frame; |
| 893 | int fsize = frame_extra_sizes(regs->format); | 871 | struct pt_regs *tregs = rte_regs(regs); |
| 872 | int fsize = frame_extra_sizes(tregs->format); | ||
| 894 | struct sigcontext context; | 873 | struct sigcontext context; |
| 895 | int err = 0, sig = ksig->sig; | 874 | int err = 0, sig = ksig->sig; |
| 896 | 875 | ||
| 897 | if (fsize < 0) { | 876 | if (fsize < 0) { |
| 898 | pr_debug("setup_frame: Unknown frame format %#x\n", | 877 | pr_debug("setup_frame: Unknown frame format %#x\n", |
| 899 | regs->format); | 878 | tregs->format); |
| 900 | return -EFAULT; | 879 | return -EFAULT; |
| 901 | } | 880 | } |
| 902 | 881 | ||
| @@ -907,7 +886,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, · 4 unmodified lines | |||
| 907 | 886 | ||
| 908 | err |= __put_user(sig, &frame->sig); | 887 | err |= __put_user(sig, &frame->sig); |
| 909 | 888 | ||
| 910 | err |= __put_user(regs->vector, &frame->code); | 889 | err |= __put_user(tregs->vector, &frame->code); |
| 911 | err |= __put_user(&frame->sc, &frame->psc); | 890 | err |= __put_user(&frame->sc, &frame->psc); |
| 912 | 891 | ||
| 913 | if (_NSIG_WORDS > 1) | 892 | if (_NSIG_WORDS > 1) |
| @@ -933,34 +912,28 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, · 19 unmodified lines | |||
| 933 | 912 | ||
| 934 | push_cache ((unsigned long) &frame->retcode); | 913 | push_cache ((unsigned long) &frame->retcode); |
| 935 | 914 | ||
| 936 | /* | ||
| 937 | * Set up registers for signal handler. All the state we are about | ||
| 938 | * to destroy is successfully copied to sigframe. | ||
| 939 | */ | ||
| 940 | wrusp ((unsigned long) frame); | ||
| 941 | regs->pc = (unsigned long) ksig->ka.sa.sa_handler; | ||
| 942 | adjustformat(regs); | ||
| 943 | |||
| 944 | /* | 915 | /* |
| 945 | * This is subtle; if we build more than one sigframe, all but the | 916 | * This is subtle; if we build more than one sigframe, all but the |
| 946 | * first one will see frame format 0 and have fsize == 0, so we won't | 917 | * first one will see frame format 0 and have fsize == 0, so we won't |
| 947 | * screw stkadj. | 918 | * screw stkadj. |
| 948 | */ | 919 | */ |
| 949 | if (fsize) | 920 | if (fsize) { |
| 950 | regs->stkadj = fsize; | 921 | regs->stkadj = fsize; |
| 951 | 922 | tregs = rte_regs(regs); | |
| 952 | /* Prepare to skip over the extra stuff in the exception frame. */ | ||
| 953 | if (regs->stkadj) { | ||
| 954 | struct pt_regs *tregs = | ||
| 955 | (struct pt_regs *)((ulong)regs + regs->stkadj); | ||
| 956 | pr_debug("Performing stackadjust=%04lx\n", regs->stkadj); | 923 | pr_debug("Performing stackadjust=%04lx\n", regs->stkadj); |
| 957 | /* This must be copied with decreasing addresses to | ||
| 958 | handle overlaps. */ | ||
| 959 | tregs->vector = 0; | 924 | tregs->vector = 0; |
| 960 | tregs->format = 0; | 925 | tregs->format = 0; |
| 961 | tregs->pc = regs->pc; | ||
| 962 | tregs->sr = regs->sr; | 926 | tregs->sr = regs->sr; |
| 963 | } | 927 | } |
| 928 | |||
| 929 | /* | ||
| 930 | * Set up registers for signal handler. All the state we are about | ||
| 931 | * to destroy is successfully copied to sigframe. | ||
| 932 | */ | ||
| 933 | wrusp ((unsigned long) frame); | ||
| 934 | tregs->pc = (unsigned long) ksig->ka.sa.sa_handler; | ||
| 935 | adjustformat(regs); | ||
| 936 | |||
| 964 | return 0; | 937 | return 0; |
| 965 | } | 938 | } |
| 966 | 939 | ||
| @@ -968,7 +941,8 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, · 1 unmodified line | |||
| 968 | struct pt_regs *regs) | 941 | struct pt_regs *regs) |
| 969 | { | 942 | { |
| 970 | struct rt_sigframe __user *frame; | 943 | struct rt_sigframe __user *frame; |
| 971 | int fsize = frame_extra_sizes(regs->format); | 944 | struct pt_regs *tregs = rte_regs(regs); |
| 945 | int fsize = frame_extra_sizes(tregs->format); | ||
| 972 | int err = 0, sig = ksig->sig; | 946 | int err = 0, sig = ksig->sig; |
| 973 | 947 | ||
| 974 | if (fsize < 0) { | 948 | if (fsize < 0) { |
| @@ -1018,34 +992,27 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, · 43 unmodified lines | |||
| 1018 | 992 | ||
| 1019 | push_cache ((unsigned long) &frame->retcode); | 993 | push_cache ((unsigned long) &frame->retcode); |
| 1020 | 994 | ||
| 1021 | /* | ||
| 1022 | * Set up registers for signal handler. All the state we are about | ||
| 1023 | * to destroy is successfully copied to sigframe. | ||
| 1024 | */ | ||
| 1025 | wrusp ((unsigned long) frame); | ||
| 1026 | regs->pc = (unsigned long) ksig->ka.sa.sa_handler; | ||
| 1027 | adjustformat(regs); | ||
| 1028 | |||
| 1029 | /* | 995 | /* |
| 1030 | * This is subtle; if we build more than one sigframe, all but the | 996 | * This is subtle; if we build more than one sigframe, all but the |
| 1031 | * first one will see frame format 0 and have fsize == 0, so we won't | 997 | * first one will see frame format 0 and have fsize == 0, so we won't |
| 1032 | * screw stkadj. | 998 | * screw stkadj. |
| 1033 | */ | 999 | */ |
| 1034 | if (fsize) | 1000 | if (fsize) { |
| 1035 | regs->stkadj = fsize; | 1001 | regs->stkadj = fsize; |
| 1036 | 1002 | tregs = rte_regs(regs); | |
| 1037 | /* Prepare to skip over the extra stuff in the exception frame. */ | ||
| 1038 | if (regs->stkadj) { | ||
| 1039 | struct pt_regs *tregs = | ||
| 1040 | (struct pt_regs *)((ulong)regs + regs->stkadj); | ||
| 1041 | pr_debug("Performing stackadjust=%04lx\n", regs->stkadj); | 1003 | pr_debug("Performing stackadjust=%04lx\n", regs->stkadj); |
| 1042 | /* This must be copied with decreasing addresses to | ||
| 1043 | handle overlaps. */ | ||
| 1044 | tregs->vector = 0; | 1004 | tregs->vector = 0; |
| 1045 | tregs->format = 0; | 1005 | tregs->format = 0; |
| 1046 | tregs->pc = regs->pc; | ||
| 1047 | tregs->sr = regs->sr; | 1006 | tregs->sr = regs->sr; |
| 1048 | } | 1007 | } |
| 1008 | |||
| 1009 | /* | ||
| 1010 | * Set up registers for signal handler. All the state we are about | ||
| 1011 | * to destroy is successfully copied to sigframe. | ||
| 1012 | */ | ||
| 1013 | wrusp ((unsigned long) frame); | ||
| 1014 | tregs->pc = (unsigned long) ksig->ka.sa.sa_handler; | ||
| 1015 | adjustformat(regs); | ||
| 1049 | return 0; | 1016 | return 0; |
| 1050 | } | 1017 | } |
| 1051 | 1018 | ||
| @@ -181,9 +181,8 @@ static inline void access_error060 (struct frame *fp) · 180 unmodified lines | |||
| 181 | static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) | 181 | static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) |
| 182 | { | 182 | { |
| 183 | unsigned long mmusr; | 183 | unsigned long mmusr; |
| 184 | mm_segment_t old_fs = get_fs(); | ||
| 185 | 184 | ||
| 186 | set_fs(MAKE_MM_SEG(wbs)); | 185 | set_fc(wbs); |
| 187 | 186 | ||
| 188 | if (iswrite) | 187 | if (iswrite) |
| 189 | asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); | 188 | asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); |
| @@ -192,7 +191,7 @@ static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) · 2 unmodified lines | |||
| 192 | 191 | ||
| 193 | asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); | 192 | asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); |
| 194 | 193 | ||
| 195 | set_fs(old_fs); | 194 | set_fc(USER_DATA); |
| 196 | 195 | ||
| 197 | return mmusr; | 196 | return mmusr; |
| 198 | } | 197 | } |
| @@ -201,10 +200,8 @@ static inline int do_040writeback1(unsigned short wbs, unsigned long wba, · 2 unmodified lines | |||
| 201 | unsigned long wbd) | 200 | unsigned long wbd) |
| 202 | { | 201 | { |
| 203 | int res = 0; | 202 | int res = 0; |
| 204 | mm_segment_t old_fs = get_fs(); | ||
| 205 | 203 | ||
| 206 | /* set_fs can not be moved, otherwise put_user() may oops */ | 204 | set_fc(wbs); |
| 207 | set_fs(MAKE_MM_SEG(wbs)); | ||
| 208 | 205 | ||
| 209 | switch (wbs & WBSIZ_040) { | 206 | switch (wbs & WBSIZ_040) { |
| 210 | case BA_SIZE_BYTE: | 207 | case BA_SIZE_BYTE: |
| @@ -218,9 +215,7 @@ static inline int do_040writeback1(unsigned short wbs, unsigned long wba, · 7 unmodified lines | |||
| 218 | break; | 215 | break; |
| 219 | } | 216 | } |
| 220 | 217 | ||
| 221 | /* set_fs can not be moved, otherwise put_user() may oops */ | 218 | set_fc(USER_DATA); |
| 222 | set_fs(old_fs); | ||
| 223 | |||
| 224 | 219 | ||
| 225 | pr_debug("do_040writeback1, res=%d\n", res); | 220 | pr_debug("do_040writeback1, res=%d\n", res); |
| 226 | 221 | ||
| @@ -18,7 +18,6 @@ · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | #include <linux/uaccess.h> | 19 | #include <linux/uaccess.h> |
| 20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
| 21 | #include <asm/segment.h> | ||
| 22 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
| 23 | #include <asm/macintosh.h> | 22 | #include <asm/macintosh.h> |
| 24 | #include <asm/mac_via.h> | 23 | #include <asm/mac_via.h> |
| @@ -49,24 +49,7 @@ static unsigned long virt_to_phys_slow(unsigned long vaddr) · 48 unmodified lines | |||
| 49 | if (mmusr & MMU_R_040) | 49 | if (mmusr & MMU_R_040) |
| 50 | return (mmusr & PAGE_MASK) | (vaddr & ~PAGE_MASK); | 50 | return (mmusr & PAGE_MASK) | (vaddr & ~PAGE_MASK); |
| 51 | } else { | 51 | } else { |
| 52 | unsigned short mmusr; | 52 | WARN_ON_ONCE(!CPU_IS_040_OR_060); |
| 53 | unsigned long *descaddr; | ||
| 54 | |||
| 55 | asm volatile ("ptestr %3,%2@,#7,%0\n\t" | ||
| 56 | "pmove %%psr,%1" | ||
| 57 | : "=a&" (descaddr), "=m" (mmusr) | ||
| 58 | : "a" (vaddr), "d" (get_fs().seg)); | ||
| 59 | if (mmusr & (MMU_I|MMU_B|MMU_L)) | ||
| 60 | return 0; | ||
| 61 | descaddr = phys_to_virt((unsigned long)descaddr); | ||
| 62 | switch (mmusr & MMU_NUM) { | ||
| 63 | case 1: | ||
| 64 | return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff); | ||
| 65 | case 2: | ||
| 66 | return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff); | ||
| 67 | case 3: | ||
| 68 | return (*descaddr & PAGE_MASK) | (vaddr & ~PAGE_MASK); | ||
| 69 | } | ||
| 70 | } | 53 | } |
| 71 | return 0; | 54 | return 0; |
| 72 | } | 55 | } |
| @@ -107,11 +90,9 @@ void flush_icache_user_range(unsigned long address, unsigned long endaddr) · 34 unmodified lines | |||
| 107 | 90 | ||
| 108 | void flush_icache_range(unsigned long address, unsigned long endaddr) | 91 | void flush_icache_range(unsigned long address, unsigned long endaddr) |
| 109 | { | 92 | { |
| 110 | mm_segment_t old_fs = get_fs(); | 93 | set_fc(SUPER_DATA); |
| 111 | |||
| 112 | set_fs(KERNEL_DS); | ||
| 113 | flush_icache_user_range(address, endaddr); | 94 | flush_icache_user_range(address, endaddr); |
| 114 | set_fs(old_fs); | 95 | set_fc(USER_DATA); |
| 115 | } | 96 | } |
| 116 | EXPORT_SYMBOL(flush_icache_range); | 97 | EXPORT_SYMBOL(flush_icache_range); |
| 117 | 98 | ||
| @@ -72,12 +72,6 @@ void __init paging_init(void) · 71 unmodified lines | |||
| 72 | if (!empty_zero_page) | 72 | if (!empty_zero_page) |
| 73 | panic("%s: Failed to allocate %lu bytes align=0x%lx\n", | 73 | panic("%s: Failed to allocate %lu bytes align=0x%lx\n", |
| 74 | __func__, PAGE_SIZE, PAGE_SIZE); | 74 | __func__, PAGE_SIZE, PAGE_SIZE); |
| 75 | |||
| 76 | /* | ||
| 77 | * Set up SFC/DFC registers (user data space). | ||
| 78 | */ | ||
| 79 | set_fs (USER_DS); | ||
| 80 | |||
| 81 | max_zone_pfn[ZONE_DMA] = end_mem >> PAGE_SHIFT; | 75 | max_zone_pfn[ZONE_DMA] = end_mem >> PAGE_SHIFT; |
| 82 | free_area_init(max_zone_pfn); | 76 | free_area_init(max_zone_pfn); |
| 83 | } | 77 | } |
| @@ -17,7 +17,6 @@ · 16 unmodified lines | |||
| 17 | #include <linux/vmalloc.h> | 17 | #include <linux/vmalloc.h> |
| 18 | 18 | ||
| 19 | #include <asm/setup.h> | 19 | #include <asm/setup.h> |
| 20 | #include <asm/segment.h> | ||
| 21 | #include <asm/page.h> | 20 | #include <asm/page.h> |
| 22 | #include <asm/io.h> | 21 | #include <asm/io.h> |
| 23 | #include <asm/tlbflush.h> | 22 | #include <asm/tlbflush.h> |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | |||
| 15 | #include <linux/gfp.h> | 15 | #include <linux/gfp.h> |
| 16 | 16 | ||
| 17 | #include <asm/setup.h> | 17 | #include <asm/setup.h> |
| 18 | #include <asm/segment.h> | ||
| 19 | #include <asm/page.h> | 18 | #include <asm/page.h> |
| 20 | #include <asm/traps.h> | 19 | #include <asm/traps.h> |
| 21 | #include <asm/machdep.h> | 20 | #include <asm/machdep.h> |
| @@ -467,7 +467,7 @@ void __init paging_init(void) · 466 unmodified lines | |||
| 467 | /* | 467 | /* |
| 468 | * Set up SFC/DFC registers | 468 | * Set up SFC/DFC registers |
| 469 | */ | 469 | */ |
| 470 | set_fs(KERNEL_DS); | 470 | set_fc(USER_DATA); |
| 471 | 471 | ||
| 472 | #ifdef DEBUG | 472 | #ifdef DEBUG |
| 473 | printk ("before free_area_init\n"); | 473 | printk ("before free_area_init\n"); |
| @@ -31,7 +31,6 @@ · 30 unmodified lines | |||
| 31 | #include <asm/intersil.h> | 31 | #include <asm/intersil.h> |
| 32 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
| 33 | #include <asm/sections.h> | 33 | #include <asm/sections.h> |
| 34 | #include <asm/segment.h> | ||
| 35 | #include <asm/sun3ints.h> | 34 | #include <asm/sun3ints.h> |
| 36 | 35 | ||
| 37 | char sun3_reserved_pmeg[SUN3_PMEGS_NUM]; | 36 | char sun3_reserved_pmeg[SUN3_PMEGS_NUM]; |
| @@ -89,7 +88,7 @@ void __init sun3_init(void) · 51 unmodified lines | |||
| 89 | sun3_reserved_pmeg[249] = 1; | 88 | sun3_reserved_pmeg[249] = 1; |
| 90 | sun3_reserved_pmeg[252] = 1; | 89 | sun3_reserved_pmeg[252] = 1; |
| 91 | sun3_reserved_pmeg[253] = 1; | 90 | sun3_reserved_pmeg[253] = 1; |
| 92 | set_fs(KERNEL_DS); | 91 | set_fc(USER_DATA); |
| 93 | } | 92 | } |
| 94 | 93 | ||
| 95 | /* Without this, Bad Things happen when something calls arch_reset. */ | 94 | /* Without this, Bad Things happen when something calls arch_reset. */ |
| @@ -23,7 +23,6 @@ · 22 unmodified lines | |||
| 23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
| 24 | #include <asm/page.h> | 24 | #include <asm/page.h> |
| 25 | #include <asm/sun3mmu.h> | 25 | #include <asm/sun3mmu.h> |
| 26 | #include <asm/segment.h> | ||
| 27 | #include <asm/oplib.h> | 26 | #include <asm/oplib.h> |
| 28 | #include <asm/mmu_context.h> | 27 | #include <asm/mmu_context.h> |
| 29 | #include <asm/dvma.h> | 28 | #include <asm/dvma.h> |
| @@ -191,14 +190,13 @@ void __init mmu_emu_init(unsigned long bootmem_end) · 161 unmodified lines | |||
| 191 | for(seg = 0; seg < PAGE_OFFSET; seg += SUN3_PMEG_SIZE) | 190 | for(seg = 0; seg < PAGE_OFFSET; seg += SUN3_PMEG_SIZE) |
| 192 | sun3_put_segmap(seg, SUN3_INVALID_PMEG); | 191 | sun3_put_segmap(seg, SUN3_INVALID_PMEG); |
| 193 | 192 | ||
| 194 | set_fs(MAKE_MM_SEG(3)); | 193 | set_fc(3); |
| 195 | for(seg = 0; seg < 0x10000000; seg += SUN3_PMEG_SIZE) { | 194 | for(seg = 0; seg < 0x10000000; seg += SUN3_PMEG_SIZE) { |
| 196 | i = sun3_get_segmap(seg); | 195 | i = sun3_get_segmap(seg); |
| 197 | for(j = 1; j < CONTEXTS_NUM; j++) | 196 | for(j = 1; j < CONTEXTS_NUM; j++) |
| 198 | (*(romvec->pv_setctxt))(j, (void *)seg, i); | 197 | (*(romvec->pv_setctxt))(j, (void *)seg, i); |
| 199 | } | 198 | } |
| 200 | set_fs(KERNEL_DS); | 199 | set_fc(USER_DATA); |
| 201 | |||
| 202 | } | 200 | } |
| 203 | 201 | ||
| 204 | /* erase the mappings for a dead context. Uses the pg_dir for hints | 202 | /* erase the mappings for a dead context. Uses the pg_dir for hints |
| @@ -11,7 +11,6 @@ · 10 unmodified lines | |||
| 11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
| 12 | #include <linux/kernel_stat.h> | 12 | #include <linux/kernel_stat.h> |
| 13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
| 14 | #include <asm/segment.h> | ||
| 15 | #include <asm/intersil.h> | 14 | #include <asm/intersil.h> |
| 16 | #include <asm/oplib.h> | 15 | #include <asm/oplib.h> |
| 17 | #include <asm/sun3ints.h> | 16 | #include <asm/sun3ints.h> |
| @@ -14,7 +14,6 @@ · 13 unmodified lines | |||
| 14 | #include <asm/traps.h> | 14 | #include <asm/traps.h> |
| 15 | #include <asm/sun3xprom.h> | 15 | #include <asm/sun3xprom.h> |
| 16 | #include <asm/idprom.h> | 16 | #include <asm/idprom.h> |
| 17 | #include <asm/segment.h> | ||
| 18 | #include <asm/sun3ints.h> | 17 | #include <asm/sun3ints.h> |
| 19 | #include <asm/openprom.h> | 18 | #include <asm/openprom.h> |
| 20 | #include <asm/machines.h> | 19 | #include <asm/machines.h> |
| @@ -662,6 +662,11 @@ static void build_epilogue(struct jit_ctx *ctx) · 661 unmodified lines | |||
| 662 | ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative : func) : \ | 662 | ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative : func) : \ |
| 663 | func##_positive) | 663 | func##_positive) |
| 664 | 664 | ||
| 665 | static bool is_bad_offset(int b_off) | ||
| 666 | { | ||
| 667 | return b_off > 0x1ffff || b_off < -0x20000; | ||
| 668 | } | ||
| 669 | |||
| 665 | static int build_body(struct jit_ctx *ctx) | 670 | static int build_body(struct jit_ctx *ctx) |
| 666 | { | 671 | { |
| 667 | const struct bpf_prog *prog = ctx->skf; | 672 | const struct bpf_prog *prog = ctx->skf; |
| @@ -728,7 +733,10 @@ load_common: · 60 unmodified lines | |||
| 728 | /* Load return register on DS for failures */ | 733 | /* Load return register on DS for failures */ |
| 729 | emit_reg_move(r_ret, r_zero, ctx); | 734 | emit_reg_move(r_ret, r_zero, ctx); |
| 730 | /* Return with error */ | 735 | /* Return with error */ |
| 731 | emit_b(b_imm(prog->len, ctx), ctx); | 736 | b_off = b_imm(prog->len, ctx); |
| 737 | if (is_bad_offset(b_off)) | ||
| 738 | return -E2BIG; | ||
| 739 | emit_b(b_off, ctx); | ||
| 732 | emit_nop(ctx); | 740 | emit_nop(ctx); |
| 733 | break; | 741 | break; |
| 734 | case BPF_LD | BPF_W | BPF_IND: | 742 | case BPF_LD | BPF_W | BPF_IND: |
| @@ -775,8 +783,10 @@ load_ind: · 40 unmodified lines | |||
| 775 | emit_jalr(MIPS_R_RA, r_s0, ctx); | 783 | emit_jalr(MIPS_R_RA, r_s0, ctx); |
| 776 | emit_reg_move(MIPS_R_A0, r_skb, ctx); /* delay slot */ | 784 | emit_reg_move(MIPS_R_A0, r_skb, ctx); /* delay slot */ |
| 777 | /* Check the error value */ | 785 | /* Check the error value */ |
| 778 | emit_bcond(MIPS_COND_NE, r_ret, 0, | 786 | b_off = b_imm(prog->len, ctx); |
| 779 | b_imm(prog->len, ctx), ctx); | 787 | if (is_bad_offset(b_off)) |
| 788 | return -E2BIG; | ||
| 789 | emit_bcond(MIPS_COND_NE, r_ret, 0, b_off, ctx); | ||
| 780 | emit_reg_move(r_ret, r_zero, ctx); | 790 | emit_reg_move(r_ret, r_zero, ctx); |
| 781 | /* We are good */ | 791 | /* We are good */ |
| 782 | /* X <- P[1:K] & 0xf */ | 792 | /* X <- P[1:K] & 0xf */ |
| @@ -855,8 +865,10 @@ load_ind: · 72 unmodified lines | |||
| 855 | /* A /= X */ | 865 | /* A /= X */ |
| 856 | ctx->flags |= SEEN_X | SEEN_A; | 866 | ctx->flags |= SEEN_X | SEEN_A; |
| 857 | /* Check if r_X is zero */ | 867 | /* Check if r_X is zero */ |
| 858 | emit_bcond(MIPS_COND_EQ, r_X, r_zero, | 868 | b_off = b_imm(prog->len, ctx); |
| 859 | b_imm(prog->len, ctx), ctx); | 869 | if (is_bad_offset(b_off)) |
| 870 | return -E2BIG; | ||
| 871 | emit_bcond(MIPS_COND_EQ, r_X, r_zero, b_off, ctx); | ||
| 860 | emit_load_imm(r_ret, 0, ctx); /* delay slot */ | 872 | emit_load_imm(r_ret, 0, ctx); /* delay slot */ |
| 861 | emit_div(r_A, r_X, ctx); | 873 | emit_div(r_A, r_X, ctx); |
| 862 | break; | 874 | break; |
| @@ -864,8 +876,10 @@ load_ind: · 1 unmodified line | |||
| 864 | /* A %= X */ | 876 | /* A %= X */ |
| 865 | ctx->flags |= SEEN_X | SEEN_A; | 877 | ctx->flags |= SEEN_X | SEEN_A; |
| 866 | /* Check if r_X is zero */ | 878 | /* Check if r_X is zero */ |
| 867 | emit_bcond(MIPS_COND_EQ, r_X, r_zero, | 879 | b_off = b_imm(prog->len, ctx); |
| 868 | b_imm(prog->len, ctx), ctx); | 880 | if (is_bad_offset(b_off)) |
| 881 | return -E2BIG; | ||
| 882 | emit_bcond(MIPS_COND_EQ, r_X, r_zero, b_off, ctx); | ||
| 869 | emit_load_imm(r_ret, 0, ctx); /* delay slot */ | 883 | emit_load_imm(r_ret, 0, ctx); /* delay slot */ |
| 870 | emit_mod(r_A, r_X, ctx); | 884 | emit_mod(r_A, r_X, ctx); |
| 871 | break; | 885 | break; |
| @@ -926,7 +940,10 @@ load_ind: · 54 unmodified lines | |||
| 926 | break; | 940 | break; |
| 927 | case BPF_JMP | BPF_JA: | 941 | case BPF_JMP | BPF_JA: |
| 928 | /* pc += K */ | 942 | /* pc += K */ |
| 929 | emit_b(b_imm(i + k + 1, ctx), ctx); | 943 | b_off = b_imm(i + k + 1, ctx); |
| 944 | if (is_bad_offset(b_off)) | ||
| 945 | return -E2BIG; | ||
| 946 | emit_b(b_off, ctx); | ||
| 930 | emit_nop(ctx); | 947 | emit_nop(ctx); |
| 931 | break; | 948 | break; |
| 932 | case BPF_JMP | BPF_JEQ | BPF_K: | 949 | case BPF_JMP | BPF_JEQ | BPF_K: |
| @@ -1056,12 +1073,16 @@ jmp_cmp: · 123 unmodified lines | |||
| 1056 | break; | 1073 | break; |
| 1057 | case BPF_RET | BPF_A: | 1074 | case BPF_RET | BPF_A: |
| 1058 | ctx->flags |= SEEN_A; | 1075 | ctx->flags |= SEEN_A; |
| 1059 | if (i != prog->len - 1) | 1076 | if (i != prog->len - 1) { |
| 1060 | /* | 1077 | /* |
| 1061 | * If this is not the last instruction | 1078 | * If this is not the last instruction |
| 1062 | * then jump to the epilogue | 1079 | * then jump to the epilogue |
| 1063 | */ | 1080 | */ |
| 1064 | emit_b(b_imm(prog->len, ctx), ctx); | 1081 | b_off = b_imm(prog->len, ctx); |
| 1082 | if (is_bad_offset(b_off)) | ||
| 1083 | return -E2BIG; | ||
| 1084 | emit_b(b_off, ctx); | ||
| 1085 | } | ||
| 1065 | emit_reg_move(r_ret, r_A, ctx); /* delay slot */ | 1086 | emit_reg_move(r_ret, r_A, ctx); /* delay slot */ |
| 1066 | break; | 1087 | break; |
| 1067 | case BPF_RET | BPF_K: | 1088 | case BPF_RET | BPF_K: |
| @@ -1075,7 +1096,10 @@ jmp_cmp: · 7 unmodified lines | |||
| 1075 | * If this is not the last instruction | 1096 | * If this is not the last instruction |
| 1076 | * then jump to the epilogue | 1097 | * then jump to the epilogue |
| 1077 | */ | 1098 | */ |
| 1078 | emit_b(b_imm(prog->len, ctx), ctx); | 1099 | b_off = b_imm(prog->len, ctx); |
| 1100 | if (is_bad_offset(b_off)) | ||
| 1101 | return -E2BIG; | ||
| 1102 | emit_b(b_off, ctx); | ||
| 1079 | emit_nop(ctx); | 1103 | emit_nop(ctx); |
| 1080 | } | 1104 | } |
| 1081 | break; | 1105 | break; |
| @@ -1133,8 +1157,10 @@ jmp_cmp: · 51 unmodified lines | |||
| 1133 | /* Load *dev pointer */ | 1157 | /* Load *dev pointer */ |
| 1134 | emit_load_ptr(r_s0, r_skb, off, ctx); | 1158 | emit_load_ptr(r_s0, r_skb, off, ctx); |
| 1135 | /* error (0) in the delay slot */ | 1159 | /* error (0) in the delay slot */ |
| 1136 | emit_bcond(MIPS_COND_EQ, r_s0, r_zero, | 1160 | b_off = b_imm(prog->len, ctx); |
| 1137 | b_imm(prog->len, ctx), ctx); | 1161 | if (is_bad_offset(b_off)) |
| 1162 | return -E2BIG; | ||
| 1163 | emit_bcond(MIPS_COND_EQ, r_s0, r_zero, b_off, ctx); | ||
| 1138 | emit_reg_move(r_ret, r_zero, ctx); | 1164 | emit_reg_move(r_ret, r_zero, ctx); |
| 1139 | if (code == (BPF_ANC | SKF_AD_IFINDEX)) { | 1165 | if (code == (BPF_ANC | SKF_AD_IFINDEX)) { |
| 1140 | BUILD_BUG_ON(sizeof_field(struct net_device, ifindex) != 4); | 1166 | BUILD_BUG_ON(sizeof_field(struct net_device, ifindex) != 4); |
| @@ -1244,7 +1270,10 @@ void bpf_jit_compile(struct bpf_prog *fp) · 103 unmodified lines | |||
| 1244 | 1270 | ||
| 1245 | /* Generate the actual JIT code */ | 1271 | /* Generate the actual JIT code */ |
| 1246 | build_prologue(&ctx); | 1272 | build_prologue(&ctx); |
| 1247 | build_body(&ctx); | 1273 | if (build_body(&ctx)) { |
| 1274 | module_memfree(ctx.target); | ||
| 1275 | goto out; | ||
| 1276 | } | ||
| 1248 | build_epilogue(&ctx); | 1277 | build_epilogue(&ctx); |
| 1249 | 1278 | ||
| 1250 | /* Update the icache */ | 1279 | /* Update the icache */ |
| @@ -3,9 +3,10 @@ · 2 unmodified lines | |||
| 3 | config EARLY_PRINTK | 3 | config EARLY_PRINTK |
| 4 | bool "Activate early kernel debugging" | 4 | bool "Activate early kernel debugging" |
| 5 | default y | 5 | default y |
| 6 | depends on TTY | ||
| 6 | select SERIAL_CORE_CONSOLE | 7 | select SERIAL_CORE_CONSOLE |
| 7 | help | 8 | help |
| 8 | Enable early printk on console | 9 | Enable early printk on console. |
| 9 | This is useful for kernel debugging when your machine crashes very | 10 | This is useful for kernel debugging when your machine crashes very |
| 10 | early before the console code is initialized. | 11 | early before the console code is initialized. |
| 11 | You should normally say N here, unless you want to debug such a crash. | 12 | You should normally say N here, unless you want to debug such a crash. |
| @@ -149,8 +149,6 @@ static void __init find_limits(unsigned long *min, unsigned long *max_low, · 148 unmodified lines | |||
| 149 | 149 | ||
| 150 | void __init setup_arch(char **cmdline_p) | 150 | void __init setup_arch(char **cmdline_p) |
| 151 | { | 151 | { |
| 152 | int dram_start; | ||
| 153 | |||
| 154 | console_verbose(); | 152 | console_verbose(); |
| 155 | 153 | ||
| 156 | memory_start = memblock_start_of_DRAM(); | 154 | memory_start = memblock_start_of_DRAM(); |
| @@ -419,13 +419,13 @@ static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu) · 418 unmodified lines | |||
| 419 | static void __set_cpu_idle(struct kvm_vcpu *vcpu) | 419 | static void __set_cpu_idle(struct kvm_vcpu *vcpu) |
| 420 | { | 420 | { |
| 421 | kvm_s390_set_cpuflags(vcpu, CPUSTAT_WAIT); | 421 | kvm_s390_set_cpuflags(vcpu, CPUSTAT_WAIT); |
| 422 | set_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask); | 422 | set_bit(vcpu->vcpu_idx, vcpu->kvm->arch.idle_mask); |
| 423 | } | 423 | } |
| 424 | 424 | ||
| 425 | static void __unset_cpu_idle(struct kvm_vcpu *vcpu) | 425 | static void __unset_cpu_idle(struct kvm_vcpu *vcpu) |
| 426 | { | 426 | { |
| 427 | kvm_s390_clear_cpuflags(vcpu, CPUSTAT_WAIT); | 427 | kvm_s390_clear_cpuflags(vcpu, CPUSTAT_WAIT); |
| 428 | clear_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask); | 428 | clear_bit(vcpu->vcpu_idx, vcpu->kvm->arch.idle_mask); |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | static void __reset_intercept_indicators(struct kvm_vcpu *vcpu) | 431 | static void __reset_intercept_indicators(struct kvm_vcpu *vcpu) |
| @@ -4066,7 +4066,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu) · 4065 unmodified lines | |||
| 4066 | kvm_s390_patch_guest_per_regs(vcpu); | 4066 | kvm_s390_patch_guest_per_regs(vcpu); |
| 4067 | } | 4067 | } |
| 4068 | 4068 | ||
| 4069 | clear_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.gisa_int.kicked_mask); | 4069 | clear_bit(vcpu->vcpu_idx, vcpu->kvm->arch.gisa_int.kicked_mask); |
| 4070 | 4070 | ||
| 4071 | vcpu->arch.sie_block->icptcode = 0; | 4071 | vcpu->arch.sie_block->icptcode = 0; |
| 4072 | cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags); | 4072 | cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags); |
| @@ -79,7 +79,7 @@ static inline int is_vcpu_stopped(struct kvm_vcpu *vcpu) · 78 unmodified lines | |||
| 79 | 79 | ||
| 80 | static inline int is_vcpu_idle(struct kvm_vcpu *vcpu) | 80 | static inline int is_vcpu_idle(struct kvm_vcpu *vcpu) |
| 81 | { | 81 | { |
| 82 | return test_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask); | 82 | return test_bit(vcpu->vcpu_idx, vcpu->kvm->arch.idle_mask); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | static inline int kvm_is_ucontrol(struct kvm *kvm) | 85 | static inline int kvm_is_ucontrol(struct kvm *kvm) |
| @@ -367,10 +367,11 @@ SYM_FUNC_START(sm4_aesni_avx_crypt8) · 366 unmodified lines | |||
| 367 | * %rdx: src (1..8 blocks) | 367 | * %rdx: src (1..8 blocks) |
| 368 | * %rcx: num blocks (1..8) | 368 | * %rcx: num blocks (1..8) |
| 369 | */ | 369 | */ |
| 370 | FRAME_BEGIN | ||
| 371 | |||
| 372 | cmpq $5, %rcx; | 370 | cmpq $5, %rcx; |
| 373 | jb sm4_aesni_avx_crypt4; | 371 | jb sm4_aesni_avx_crypt4; |
| 372 | |||
| 373 | FRAME_BEGIN | ||
| 374 | |||
| 374 | vmovdqu (0 * 16)(%rdx), RA0; | 375 | vmovdqu (0 * 16)(%rdx), RA0; |
| 375 | vmovdqu (1 * 16)(%rdx), RA1; | 376 | vmovdqu (1 * 16)(%rdx), RA1; |
| 376 | vmovdqu (2 * 16)(%rdx), RA2; | 377 | vmovdqu (2 * 16)(%rdx), RA2; |
| @@ -2465,6 +2465,7 @@ static int x86_pmu_event_init(struct perf_event *event) · 2464 unmodified lines | |||
| 2465 | if (err) { | 2465 | if (err) { |
| 2466 | if (event->destroy) | 2466 | if (event->destroy) |
| 2467 | event->destroy(event); | 2467 | event->destroy(event); |
| 2468 | event->destroy = NULL; | ||
| 2468 | } | 2469 | } |
| 2469 | 2470 | ||
| 2470 | if (READ_ONCE(x86_pmu.attr_rdpmc) && | 2471 | if (READ_ONCE(x86_pmu.attr_rdpmc) && |
| @@ -263,6 +263,7 @@ static struct event_constraint intel_icl_event_constraints[] = { · 262 unmodified lines | |||
| 263 | INTEL_EVENT_CONSTRAINT_RANGE(0xa8, 0xb0, 0xf), | 263 | INTEL_EVENT_CONSTRAINT_RANGE(0xa8, 0xb0, 0xf), |
| 264 | INTEL_EVENT_CONSTRAINT_RANGE(0xb7, 0xbd, 0xf), | 264 | INTEL_EVENT_CONSTRAINT_RANGE(0xb7, 0xbd, 0xf), |
| 265 | INTEL_EVENT_CONSTRAINT_RANGE(0xd0, 0xe6, 0xf), | 265 | INTEL_EVENT_CONSTRAINT_RANGE(0xd0, 0xe6, 0xf), |
| 266 | INTEL_EVENT_CONSTRAINT(0xef, 0xf), | ||
| 266 | INTEL_EVENT_CONSTRAINT_RANGE(0xf0, 0xf4, 0xf), | 267 | INTEL_EVENT_CONSTRAINT_RANGE(0xf0, 0xf4, 0xf), |
| 267 | EVENT_CONSTRAINT_END | 268 | EVENT_CONSTRAINT_END |
| 268 | }; | 269 | }; |
| @@ -46,7 +46,7 @@ struct kvm_page_track_notifier_node { · 45 unmodified lines | |||
| 46 | struct kvm_page_track_notifier_node *node); | 46 | struct kvm_page_track_notifier_node *node); |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | void kvm_page_track_init(struct kvm *kvm); | 49 | int kvm_page_track_init(struct kvm *kvm); |
| 50 | void kvm_page_track_cleanup(struct kvm *kvm); | 50 | void kvm_page_track_cleanup(struct kvm *kvm); |
| 51 | 51 | ||
| 52 | void kvm_page_track_free_memslot(struct kvm_memory_slot *slot); | 52 | void kvm_page_track_free_memslot(struct kvm_memory_slot *slot); |
| @@ -2,6 +2,20 @@ · 1 unmodified line | |||
| 2 | #ifndef _ASM_X86_KVM_CLOCK_H | 2 | #ifndef _ASM_X86_KVM_CLOCK_H |
| 3 | #define _ASM_X86_KVM_CLOCK_H | 3 | #define _ASM_X86_KVM_CLOCK_H |
| 4 | 4 | ||
| 5 | #include <linux/percpu.h> | ||
| 6 | |||
| 5 | extern struct clocksource kvm_clock; | 7 | extern struct clocksource kvm_clock; |
| 6 | 8 | ||
| 9 | DECLARE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu); | ||
| 10 | |||
| 11 | static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void) | ||
| 12 | { | ||
| 13 | return &this_cpu_read(hv_clock_per_cpu)->pvti; | ||
| 14 | } | ||
| 15 | |||
| 16 | static inline struct pvclock_vsyscall_time_info *this_cpu_hvclock(void) | ||
| 17 | { | ||
| 18 | return this_cpu_read(hv_clock_per_cpu); | ||
| 19 | } | ||
| 20 | |||
| 7 | #endif /* _ASM_X86_KVM_CLOCK_H */ | 21 | #endif /* _ASM_X86_KVM_CLOCK_H */ |
| @@ -49,18 +49,9 @@ early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall); · 48 unmodified lines | |||
| 49 | static struct pvclock_vsyscall_time_info | 49 | static struct pvclock_vsyscall_time_info |
| 50 | hv_clock_boot[HVC_BOOT_ARRAY_SIZE] __bss_decrypted __aligned(PAGE_SIZE); | 50 | hv_clock_boot[HVC_BOOT_ARRAY_SIZE] __bss_decrypted __aligned(PAGE_SIZE); |
| 51 | static struct pvclock_wall_clock wall_clock __bss_decrypted; | 51 | static struct pvclock_wall_clock wall_clock __bss_decrypted; |
| 52 | static DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu); | ||
| 53 | static struct pvclock_vsyscall_time_info *hvclock_mem; | 52 | static struct pvclock_vsyscall_time_info *hvclock_mem; |
| 54 | 53 | DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu); | |
| 55 | static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void) | 54 | EXPORT_PER_CPU_SYMBOL_GPL(hv_clock_per_cpu); |
| 56 | { | ||
| 57 | return &this_cpu_read(hv_clock_per_cpu)->pvti; | ||
| 58 | } | ||
| 59 | |||
| 60 | static inline struct pvclock_vsyscall_time_info *this_cpu_hvclock(void) | ||
| 61 | { | ||
| 62 | return this_cpu_read(hv_clock_per_cpu); | ||
| 63 | } | ||
| 64 | 55 | ||
| 65 | /* | 56 | /* |
| 66 | * The wallclock is the time of day when we booted. Since then, some time may | 57 | * The wallclock is the time of day when we booted. Since then, some time may |
| @@ -65,8 +65,8 @@ static inline struct kvm_cpuid_entry2 *cpuid_entry2_find( · 64 unmodified lines | |||
| 65 | for (i = 0; i < nent; i++) { | 65 | for (i = 0; i < nent; i++) { |
| 66 | e = &entries[i]; | 66 | e = &entries[i]; |
| 67 | 67 | ||
| 68 | if (e->function == function && (e->index == index || | 68 | if (e->function == function && |
| 69 | !(e->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX))) | 69 | (!(e->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) || e->index == index)) |
| 70 | return e; | 70 | return e; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| @@ -435,7 +435,6 @@ static int fastop(struct x86_emulate_ctxt *ctxt, fastop_t fop); · 434 unmodified lines | |||
| 435 | __FOP_RET(#op) | 435 | __FOP_RET(#op) |
| 436 | 436 | ||
| 437 | asm(".pushsection .fixup, \"ax\"\n" | 437 | asm(".pushsection .fixup, \"ax\"\n" |
| 438 | ".global kvm_fastop_exception \n" | ||
| 439 | "kvm_fastop_exception: xor %esi, %esi; ret\n" | 438 | "kvm_fastop_exception: xor %esi, %esi; ret\n" |
| 440 | ".popsection"); | 439 | ".popsection"); |
| 441 | 440 | ||
| @@ -4206,7 +4205,7 @@ static int check_rdtsc(struct x86_emulate_ctxt *ctxt) · 3764 unmodified lines | |||
| 4206 | u64 cr4 = ctxt->ops->get_cr(ctxt, 4); | 4205 | u64 cr4 = ctxt->ops->get_cr(ctxt, 4); |
| 4207 | 4206 | ||
| 4208 | if (cr4 & X86_CR4_TSD && ctxt->ops->cpl(ctxt)) | 4207 | if (cr4 & X86_CR4_TSD && ctxt->ops->cpl(ctxt)) |
| 4209 | return emulate_ud(ctxt); | 4208 | return emulate_gp(ctxt, 0); |
| 4210 | 4209 | ||
| 4211 | return X86EMUL_CONTINUE; | 4210 | return X86EMUL_CONTINUE; |
| 4212 | } | 4211 | } |
| @@ -939,7 +939,7 @@ static int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) · 938 unmodified lines | |||
| 939 | for (i = 0; i < ARRAY_SIZE(hv_vcpu->stimer); i++) | 939 | for (i = 0; i < ARRAY_SIZE(hv_vcpu->stimer); i++) |
| 940 | stimer_init(&hv_vcpu->stimer[i], i); | 940 | stimer_init(&hv_vcpu->stimer[i], i); |
| 941 | 941 | ||
| 942 | hv_vcpu->vp_index = kvm_vcpu_get_idx(vcpu); | 942 | hv_vcpu->vp_index = vcpu->vcpu_idx; |
| 943 | 943 | ||
| 944 | return 0; | 944 | return 0; |
| 945 | } | 945 | } |
| @@ -1444,7 +1444,6 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) · 498 unmodified lines | |||
| 1444 | switch (msr) { | 1444 | switch (msr) { |
| 1445 | case HV_X64_MSR_VP_INDEX: { | 1445 | case HV_X64_MSR_VP_INDEX: { |
| 1446 | struct kvm_hv *hv = to_kvm_hv(vcpu->kvm); | 1446 | struct kvm_hv *hv = to_kvm_hv(vcpu->kvm); |
| 1447 | int vcpu_idx = kvm_vcpu_get_idx(vcpu); | ||
| 1448 | u32 new_vp_index = (u32)data; | 1447 | u32 new_vp_index = (u32)data; |
| 1449 | 1448 | ||
| 1450 | if (!host || new_vp_index >= KVM_MAX_VCPUS) | 1449 | if (!host || new_vp_index >= KVM_MAX_VCPUS) |
| @@ -1459,9 +1458,9 @@ static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) · 8 unmodified lines | |||
| 1459 | * VP index is changing, adjust num_mismatched_vp_indexes if | 1458 | * VP index is changing, adjust num_mismatched_vp_indexes if |
| 1460 | * it now matches or no longer matches vcpu_idx. | 1459 | * it now matches or no longer matches vcpu_idx. |
| 1461 | */ | 1460 | */ |
| 1462 | if (hv_vcpu->vp_index == vcpu_idx) | 1461 | if (hv_vcpu->vp_index == vcpu->vcpu_idx) |
| 1463 | atomic_inc(&hv->num_mismatched_vp_indexes); | 1462 | atomic_inc(&hv->num_mismatched_vp_indexes); |
| 1464 | else if (new_vp_index == vcpu_idx) | 1463 | else if (new_vp_index == vcpu->vcpu_idx) |
| 1465 | atomic_dec(&hv->num_mismatched_vp_indexes); | 1464 | atomic_dec(&hv->num_mismatched_vp_indexes); |
| 1466 | 1465 | ||
| 1467 | hv_vcpu->vp_index = new_vp_index; | 1466 | hv_vcpu->vp_index = new_vp_index; |
| @@ -83,7 +83,7 @@ static inline u32 kvm_hv_get_vpindex(struct kvm_vcpu *vcpu) · 82 unmodified lines | |||
| 83 | { | 83 | { |
| 84 | struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); | 84 | struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); |
| 85 | 85 | ||
| 86 | return hv_vcpu ? hv_vcpu->vp_index : kvm_vcpu_get_idx(vcpu); | 86 | return hv_vcpu ? hv_vcpu->vp_index : vcpu->vcpu_idx; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host); | 89 | int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host); |
| @@ -319,8 +319,8 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) · 318 unmodified lines | |||
| 319 | unsigned index; | 319 | unsigned index; |
| 320 | bool mask_before, mask_after; | 320 | bool mask_before, mask_after; |
| 321 | union kvm_ioapic_redirect_entry *e; | 321 | union kvm_ioapic_redirect_entry *e; |
| 322 | unsigned long vcpu_bitmap; | ||
| 323 | int old_remote_irr, old_delivery_status, old_dest_id, old_dest_mode; | 322 | int old_remote_irr, old_delivery_status, old_dest_id, old_dest_mode; |
| 323 | DECLARE_BITMAP(vcpu_bitmap, KVM_MAX_VCPUS); | ||
| 324 | 324 | ||
| 325 | switch (ioapic->ioregsel) { | 325 | switch (ioapic->ioregsel) { |
| 326 | case IOAPIC_REG_VERSION: | 326 | case IOAPIC_REG_VERSION: |
| @@ -384,9 +384,9 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) · 57 unmodified lines | |||
| 384 | irq.shorthand = APIC_DEST_NOSHORT; | 384 | irq.shorthand = APIC_DEST_NOSHORT; |
| 385 | irq.dest_id = e->fields.dest_id; | 385 | irq.dest_id = e->fields.dest_id; |
| 386 | irq.msi_redir_hint = false; | 386 | irq.msi_redir_hint = false; |
| 387 | bitmap_zero(&vcpu_bitmap, 16); | 387 | bitmap_zero(vcpu_bitmap, KVM_MAX_VCPUS); |
| 388 | kvm_bitmap_or_dest_vcpus(ioapic->kvm, &irq, | 388 | kvm_bitmap_or_dest_vcpus(ioapic->kvm, &irq, |
| 389 | &vcpu_bitmap); | 389 | vcpu_bitmap); |
| 390 | if (old_dest_mode != e->fields.dest_mode || | 390 | if (old_dest_mode != e->fields.dest_mode || |
| 391 | old_dest_id != e->fields.dest_id) { | 391 | old_dest_id != e->fields.dest_id) { |
| 392 | /* | 392 | /* |
| @@ -399,10 +399,10 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) · 6 unmodified lines | |||
| 399 | kvm_lapic_irq_dest_mode( | 399 | kvm_lapic_irq_dest_mode( |
| 400 | !!e->fields.dest_mode); | 400 | !!e->fields.dest_mode); |
| 401 | kvm_bitmap_or_dest_vcpus(ioapic->kvm, &irq, | 401 | kvm_bitmap_or_dest_vcpus(ioapic->kvm, &irq, |
| 402 | &vcpu_bitmap); | 402 | vcpu_bitmap); |
| 403 | } | 403 | } |
| 404 | kvm_make_scan_ioapic_request_mask(ioapic->kvm, | 404 | kvm_make_scan_ioapic_request_mask(ioapic->kvm, |
| 405 | &vcpu_bitmap); | 405 | vcpu_bitmap); |
| 406 | } else { | 406 | } else { |
| 407 | kvm_make_scan_ioapic_request(ioapic->kvm); | 407 | kvm_make_scan_ioapic_request(ioapic->kvm); |
| 408 | } | 408 | } |
| @@ -2027,8 +2027,8 @@ static void mmu_pages_clear_parents(struct mmu_page_path *parents) · 2026 unmodified lines | |||
| 2027 | } while (!sp->unsync_children); | 2027 | } while (!sp->unsync_children); |
| 2028 | } | 2028 | } |
| 2029 | 2029 | ||
| 2030 | static void mmu_sync_children(struct kvm_vcpu *vcpu, | 2030 | static int mmu_sync_children(struct kvm_vcpu *vcpu, |
| 2031 | struct kvm_mmu_page *parent) | 2031 | struct kvm_mmu_page *parent, bool can_yield) |
| 2032 | { | 2032 | { |
| 2033 | int i; | 2033 | int i; |
| 2034 | struct kvm_mmu_page *sp; | 2034 | struct kvm_mmu_page *sp; |
| @@ -2055,12 +2055,18 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu, · 20 unmodified lines | |||
| 2055 | } | 2055 | } |
| 2056 | if (need_resched() || rwlock_needbreak(&vcpu->kvm->mmu_lock)) { | 2056 | if (need_resched() || rwlock_needbreak(&vcpu->kvm->mmu_lock)) { |
| 2057 | kvm_mmu_flush_or_zap(vcpu, &invalid_list, false, flush); | 2057 | kvm_mmu_flush_or_zap(vcpu, &invalid_list, false, flush); |
| 2058 | if (!can_yield) { | ||
| 2059 | kvm_make_request(KVM_REQ_MMU_SYNC, vcpu); | ||
| 2060 | return -EINTR; | ||
| 2061 | } | ||
| 2062 | |||
| 2058 | cond_resched_rwlock_write(&vcpu->kvm->mmu_lock); | 2063 | cond_resched_rwlock_write(&vcpu->kvm->mmu_lock); |
| 2059 | flush = false; | 2064 | flush = false; |
| 2060 | } | 2065 | } |
| 2061 | } | 2066 | } |
| 2062 | 2067 | ||
| 2063 | kvm_mmu_flush_or_zap(vcpu, &invalid_list, false, flush); | 2068 | kvm_mmu_flush_or_zap(vcpu, &invalid_list, false, flush); |
| 2069 | return 0; | ||
| 2064 | } | 2070 | } |
| 2065 | 2071 | ||
| 2066 | static void __clear_sp_write_flooding_count(struct kvm_mmu_page *sp) | 2072 | static void __clear_sp_write_flooding_count(struct kvm_mmu_page *sp) |
| @@ -2146,9 +2152,6 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, · 79 unmodified lines | |||
| 2146 | kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); | 2152 | kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); |
| 2147 | } | 2153 | } |
| 2148 | 2154 | ||
| 2149 | if (sp->unsync_children) | ||
| 2150 | kvm_make_request(KVM_REQ_MMU_SYNC, vcpu); | ||
| 2151 | |||
| 2152 | __clear_sp_write_flooding_count(sp); | 2155 | __clear_sp_write_flooding_count(sp); |
| 2153 | 2156 | ||
| 2154 | trace_get_page: | 2157 | trace_get_page: |
| @@ -3684,7 +3687,7 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) · 1529 unmodified lines | |||
| 3684 | write_lock(&vcpu->kvm->mmu_lock); | 3687 | write_lock(&vcpu->kvm->mmu_lock); |
| 3685 | kvm_mmu_audit(vcpu, AUDIT_PRE_SYNC); | 3688 | kvm_mmu_audit(vcpu, AUDIT_PRE_SYNC); |
| 3686 | 3689 | ||
| 3687 | mmu_sync_children(vcpu, sp); | 3690 | mmu_sync_children(vcpu, sp, true); |
| 3688 | 3691 | ||
| 3689 | kvm_mmu_audit(vcpu, AUDIT_POST_SYNC); | 3692 | kvm_mmu_audit(vcpu, AUDIT_POST_SYNC); |
| 3690 | write_unlock(&vcpu->kvm->mmu_lock); | 3693 | write_unlock(&vcpu->kvm->mmu_lock); |
| @@ -3700,7 +3703,7 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu) · 9 unmodified lines | |||
| 3700 | if (IS_VALID_PAE_ROOT(root)) { | 3703 | if (IS_VALID_PAE_ROOT(root)) { |
| 3701 | root &= PT64_BASE_ADDR_MASK; | 3704 | root &= PT64_BASE_ADDR_MASK; |
| 3702 | sp = to_shadow_page(root); | 3705 | sp = to_shadow_page(root); |
| 3703 | mmu_sync_children(vcpu, sp); | 3706 | mmu_sync_children(vcpu, sp, true); |
| 3704 | } | 3707 | } |
| 3705 | } | 3708 | } |
| 3706 | 3709 | ||
| @@ -164,13 +164,13 @@ void kvm_page_track_cleanup(struct kvm *kvm) · 163 unmodified lines | |||
| 164 | cleanup_srcu_struct(&head->track_srcu); | 164 | cleanup_srcu_struct(&head->track_srcu); |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | void kvm_page_track_init(struct kvm *kvm) | 167 | int kvm_page_track_init(struct kvm *kvm) |
| 168 | { | 168 | { |
| 169 | struct kvm_page_track_notifier_head *head; | 169 | struct kvm_page_track_notifier_head *head; |
| 170 | 170 | ||
| 171 | head = &kvm->arch.track_notifier_head; | 171 | head = &kvm->arch.track_notifier_head; |
| 172 | init_srcu_struct(&head->track_srcu); | ||
| 173 | INIT_HLIST_HEAD(&head->track_notifier_list); | 172 | INIT_HLIST_HEAD(&head->track_notifier_list); |
| 173 | return init_srcu_struct(&head->track_srcu); | ||
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | /* | 176 | /* |
| @@ -707,8 +707,27 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, · 706 unmodified lines | |||
| 707 | if (!is_shadow_present_pte(*it.sptep)) { | 707 | if (!is_shadow_present_pte(*it.sptep)) { |
| 708 | table_gfn = gw->table_gfn[it.level - 2]; | 708 | table_gfn = gw->table_gfn[it.level - 2]; |
| 709 | access = gw->pt_access[it.level - 2]; | 709 | access = gw->pt_access[it.level - 2]; |
| 710 | sp = kvm_mmu_get_page(vcpu, table_gfn, addr, it.level-1, | 710 | sp = kvm_mmu_get_page(vcpu, table_gfn, addr, |
| 711 | false, access); | 711 | it.level-1, false, access); |
| 712 | /* | ||
| 713 | * We must synchronize the pagetable before linking it | ||
| 714 | * because the guest doesn't need to flush tlb when | ||
| 715 | * the gpte is changed from non-present to present. | ||
| 716 | * Otherwise, the guest may use the wrong mapping. | ||
| 717 | * | ||
| 718 | * For PG_LEVEL_4K, kvm_mmu_get_page() has already | ||
| 719 | * synchronized it transiently via kvm_sync_page(). | ||
| 720 | * | ||
| 721 | * For higher level pagetable, we synchronize it via | ||
| 722 | * the slower mmu_sync_children(). If it needs to | ||
| 723 | * break, some progress has been made; return | ||
| 724 | * RET_PF_RETRY and retry on the next #PF. | ||
| 725 | * KVM_REQ_MMU_SYNC is not necessary but it | ||
| 726 | * expedites the process. | ||
| 727 | */ | ||
| 728 | if (sp->unsync_children && | ||
| 729 | mmu_sync_children(vcpu, sp, false)) | ||
| 730 | return RET_PF_RETRY; | ||
| 712 | } | 731 | } |
| 713 | 732 | ||
| 714 | /* | 733 | /* |
| @@ -1047,14 +1066,6 @@ static gpa_t FNAME(gva_to_gpa_nested)(struct kvm_vcpu *vcpu, gpa_t vaddr, · 332 unmodified lines | |||
| 1047 | * Using the cached information from sp->gfns is safe because: | 1066 | * Using the cached information from sp->gfns is safe because: |
| 1048 | * - The spte has a reference to the struct page, so the pfn for a given gfn | 1067 | * - The spte has a reference to the struct page, so the pfn for a given gfn |
| 1049 | * can't change unless all sptes pointing to it are nuked first. | 1068 | * can't change unless all sptes pointing to it are nuked first. |
| 1050 | * | ||
| 1051 | * Note: | ||
| 1052 | * We should flush all tlbs if spte is dropped even though guest is | ||
| 1053 | * responsible for it. Since if we don't, kvm_mmu_notifier_invalidate_page | ||
| 1054 | * and kvm_mmu_notifier_invalidate_range_start detect the mapping page isn't | ||
| 1055 | * used by guest then tlbs are not flushed, so guest is allowed to access the | ||
| 1056 | * freed pages. | ||
| 1057 | * And we increase kvm->tlbs_dirty to delay tlbs flush in this case. | ||
| 1058 | */ | 1069 | */ |
| 1059 | static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) | 1070 | static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) |
| 1060 | { | 1071 | { |
| @@ -1107,13 +1118,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) · 46 unmodified lines | |||
| 1107 | return 0; | 1118 | return 0; |
| 1108 | 1119 | ||
| 1109 | if (FNAME(prefetch_invalid_gpte)(vcpu, sp, &sp->spt[i], gpte)) { | 1120 | if (FNAME(prefetch_invalid_gpte)(vcpu, sp, &sp->spt[i], gpte)) { |
| 1110 | /* | 1121 | set_spte_ret |= SET_SPTE_NEED_REMOTE_TLB_FLUSH; |
| 1111 | * Update spte before increasing tlbs_dirty to make | ||
| 1112 | * sure no tlb flush is lost after spte is zapped; see | ||
| 1113 | * the comments in kvm_flush_remote_tlbs(). | ||
| 1114 | */ | ||
| 1115 | smp_wmb(); | ||
| 1116 | vcpu->kvm->tlbs_dirty++; | ||
| 1117 | continue; | 1122 | continue; |
| 1118 | } | 1123 | } |
| 1119 | 1124 | ||
| @@ -1128,12 +1133,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) · 8 unmodified lines | |||
| 1128 | 1133 | ||
| 1129 | if (gfn != sp->gfns[i]) { | 1134 | if (gfn != sp->gfns[i]) { |
| 1130 | drop_spte(vcpu->kvm, &sp->spt[i]); | 1135 | drop_spte(vcpu->kvm, &sp->spt[i]); |
| 1131 | /* | 1136 | set_spte_ret |= SET_SPTE_NEED_REMOTE_TLB_FLUSH; |
| 1132 | * The same as above where we are doing | ||
| 1133 | * prefetch_invalid_gpte(). | ||
| 1134 | */ | ||
| 1135 | smp_wmb(); | ||
| 1136 | vcpu->kvm->tlbs_dirty++; | ||
| 1137 | continue; | 1137 | continue; |
| 1138 | } | 1138 | } |
| 1139 | 1139 | ||
| @@ -545,7 +545,6 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm) · 544 unmodified lines | |||
| 545 | (svm->nested.ctl.int_ctl & int_ctl_vmcb12_bits) | | 545 | (svm->nested.ctl.int_ctl & int_ctl_vmcb12_bits) | |
| 546 | (svm->vmcb01.ptr->control.int_ctl & int_ctl_vmcb01_bits); | 546 | (svm->vmcb01.ptr->control.int_ctl & int_ctl_vmcb01_bits); |
| 547 | 547 | ||
| 548 | svm->vmcb->control.virt_ext = svm->nested.ctl.virt_ext; | ||
| 549 | svm->vmcb->control.int_vector = svm->nested.ctl.int_vector; | 548 | svm->vmcb->control.int_vector = svm->nested.ctl.int_vector; |
| 550 | svm->vmcb->control.int_state = svm->nested.ctl.int_state; | 549 | svm->vmcb->control.int_state = svm->nested.ctl.int_state; |
| 551 | svm->vmcb->control.event_inj = svm->nested.ctl.event_inj; | 550 | svm->vmcb->control.event_inj = svm->nested.ctl.event_inj; |
| @@ -579,7 +578,7 @@ static void nested_svm_copy_common_state(struct vmcb *from_vmcb, struct vmcb *to · 27 unmodified lines | |||
| 579 | } | 578 | } |
| 580 | 579 | ||
| 581 | int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa, | 580 | int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa, |
| 582 | struct vmcb *vmcb12) | 581 | struct vmcb *vmcb12, bool from_vmrun) |
| 583 | { | 582 | { |
| 584 | struct vcpu_svm *svm = to_svm(vcpu); | 583 | struct vcpu_svm *svm = to_svm(vcpu); |
| 585 | int ret; | 584 | int ret; |
| @@ -609,13 +608,16 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa, · 23 unmodified lines | |||
| 609 | nested_vmcb02_prepare_save(svm, vmcb12); | 608 | nested_vmcb02_prepare_save(svm, vmcb12); |
| 610 | 609 | ||
| 611 | ret = nested_svm_load_cr3(&svm->vcpu, vmcb12->save.cr3, | 610 | ret = nested_svm_load_cr3(&svm->vcpu, vmcb12->save.cr3, |
| 612 | nested_npt_enabled(svm), true); | 611 | nested_npt_enabled(svm), from_vmrun); |
| 613 | if (ret) | 612 | if (ret) |
| 614 | return ret; | 613 | return ret; |
| 615 | 614 | ||
| 616 | if (!npt_enabled) | 615 | if (!npt_enabled) |
| 617 | vcpu->arch.mmu->inject_page_fault = svm_inject_page_fault_nested; | 616 | vcpu->arch.mmu->inject_page_fault = svm_inject_page_fault_nested; |
| 618 | 617 | ||
| 618 | if (!from_vmrun) | ||
| 619 | kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); | ||
| 620 | |||
| 619 | svm_set_gif(svm, true); | 621 | svm_set_gif(svm, true); |
| 620 | 622 | ||
| 621 | return 0; | 623 | return 0; |
| @@ -681,7 +683,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) · 59 unmodified lines | |||
| 681 | 683 | ||
| 682 | svm->nested.nested_run_pending = 1; | 684 | svm->nested.nested_run_pending = 1; |
| 683 | 685 | ||
| 684 | if (enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12)) | 686 | if (enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, true)) |
| 685 | goto out_exit_err; | 687 | goto out_exit_err; |
| 686 | 688 | ||
| 687 | if (nested_svm_vmrun_msrpm(svm)) | 689 | if (nested_svm_vmrun_msrpm(svm)) |
| @@ -595,43 +595,50 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm) · 594 unmodified lines | |||
| 595 | return 0; | 595 | return 0; |
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | static int sev_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp) | 598 | static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu, |
| 599 | int *error) | ||
| 599 | { | 600 | { |
| 600 | struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; | ||
| 601 | struct sev_data_launch_update_vmsa vmsa; | 601 | struct sev_data_launch_update_vmsa vmsa; |
| 602 | struct vcpu_svm *svm = to_svm(vcpu); | ||
| 603 | int ret; | ||
| 604 | |||
| 605 | /* Perform some pre-encryption checks against the VMSA */ | ||
| 606 | ret = sev_es_sync_vmsa(svm); | ||
| 607 | if (ret) | ||
| 608 | return ret; | ||
| 609 | |||
| 610 | /* | ||
| 611 | * The LAUNCH_UPDATE_VMSA command will perform in-place encryption of | ||
| 612 | * the VMSA memory content (i.e it will write the same memory region | ||
| 613 | * with the guest's key), so invalidate it first. | ||
| 614 | */ | ||
| 615 | clflush_cache_range(svm->vmsa, PAGE_SIZE); | ||
| 616 | |||
| 617 | vmsa.reserved = 0; | ||
| 618 | vmsa.handle = to_kvm_svm(kvm)->sev_info.handle; | ||
| 619 | vmsa.address = __sme_pa(svm->vmsa); | ||
| 620 | vmsa.len = PAGE_SIZE; | ||
| 621 | return sev_issue_cmd(kvm, SEV_CMD_LAUNCH_UPDATE_VMSA, &vmsa, error); | ||
| 622 | } | ||
| 623 | |||
| 624 | static int sev_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp) | ||
| 625 | { | ||
| 602 | struct kvm_vcpu *vcpu; | 626 | struct kvm_vcpu *vcpu; |
| 603 | int i, ret; | 627 | int i, ret; |
| 604 | 628 | ||
| 605 | if (!sev_es_guest(kvm)) | 629 | if (!sev_es_guest(kvm)) |
| 606 | return -ENOTTY; | 630 | return -ENOTTY; |
| 607 | 631 | ||
| 608 | vmsa.reserved = 0; | ||
| 609 | |||
| 610 | kvm_for_each_vcpu(i, vcpu, kvm) { | 632 | kvm_for_each_vcpu(i, vcpu, kvm) { |
| 611 | struct vcpu_svm *svm = to_svm(vcpu); | 633 | ret = mutex_lock_killable(&vcpu->mutex); |
| 612 | |||
| 613 | /* Perform some pre-encryption checks against the VMSA */ | ||
| 614 | ret = sev_es_sync_vmsa(svm); | ||
| 615 | if (ret) | 634 | if (ret) |
| 616 | return ret; | 635 | return ret; |
| 617 | 636 | ||
| 618 | /* | 637 | ret = __sev_launch_update_vmsa(kvm, vcpu, &argp->error); |
| 619 | * The LAUNCH_UPDATE_VMSA command will perform in-place | ||
| 620 | * encryption of the VMSA memory content (i.e it will write | ||
| 621 | * the same memory region with the guest's key), so invalidate | ||
| 622 | * it first. | ||
| 623 | */ | ||
| 624 | clflush_cache_range(svm->vmsa, PAGE_SIZE); | ||
| 625 | 638 | ||
| 626 | vmsa.handle = sev->handle; | 639 | mutex_unlock(&vcpu->mutex); |
| 627 | vmsa.address = __sme_pa(svm->vmsa); | ||
| 628 | vmsa.len = PAGE_SIZE; | ||
| 629 | ret = sev_issue_cmd(kvm, SEV_CMD_LAUNCH_UPDATE_VMSA, &vmsa, | ||
| 630 | &argp->error); | ||
| 631 | if (ret) | 640 | if (ret) |
| 632 | return ret; | 641 | return ret; |
| 633 | |||
| 634 | svm->vcpu.arch.guest_state_protected = true; | ||
| 635 | } | 642 | } |
| 636 | 643 | ||
| 637 | return 0; | 644 | return 0; |
| @@ -1397,8 +1404,10 @@ static int sev_receive_start(struct kvm *kvm, struct kvm_sev_cmd *argp) · 759 unmodified lines | |||
| 1397 | 1404 | ||
| 1398 | /* Bind ASID to this guest */ | 1405 | /* Bind ASID to this guest */ |
| 1399 | ret = sev_bind_asid(kvm, start.handle, error); | 1406 | ret = sev_bind_asid(kvm, start.handle, error); |
| 1400 | if (ret) | 1407 | if (ret) { |
| 1408 | sev_decommission(start.handle); | ||
| 1401 | goto e_free_session; | 1409 | goto e_free_session; |
| 1410 | } | ||
| 1402 | 1411 | ||
| 1403 | params.handle = start.handle; | 1412 | params.handle = start.handle; |
| 1404 | if (copy_to_user((void __user *)(uintptr_t)argp->data, | 1413 | if (copy_to_user((void __user *)(uintptr_t)argp->data, |
| @@ -1464,7 +1473,7 @@ static int sev_receive_update_data(struct kvm *kvm, struct kvm_sev_cmd *argp) · 59 unmodified lines | |||
| 1464 | 1473 | ||
| 1465 | /* Pin guest memory */ | 1474 | /* Pin guest memory */ |
| 1466 | guest_page = sev_pin_memory(kvm, params.guest_uaddr & PAGE_MASK, | 1475 | guest_page = sev_pin_memory(kvm, params.guest_uaddr & PAGE_MASK, |
| 1467 | PAGE_SIZE, &n, 0); | 1476 | PAGE_SIZE, &n, 1); |
| 1468 | if (IS_ERR(guest_page)) { | 1477 | if (IS_ERR(guest_page)) { |
| 1469 | ret = PTR_ERR(guest_page); | 1478 | ret = PTR_ERR(guest_page); |
| 1470 | goto e_free_trans; | 1479 | goto e_free_trans; |
| @@ -1501,6 +1510,20 @@ static int sev_receive_finish(struct kvm *kvm, struct kvm_sev_cmd *argp) · 30 unmodified lines | |||
| 1501 | return sev_issue_cmd(kvm, SEV_CMD_RECEIVE_FINISH, &data, &argp->error); | 1510 | return sev_issue_cmd(kvm, SEV_CMD_RECEIVE_FINISH, &data, &argp->error); |
| 1502 | } | 1511 | } |
| 1503 | 1512 | ||
| 1513 | static bool cmd_allowed_from_miror(u32 cmd_id) | ||
| 1514 | { | ||
| 1515 | /* | ||
| 1516 | * Allow mirrors VM to call KVM_SEV_LAUNCH_UPDATE_VMSA to enable SEV-ES | ||
| 1517 | * active mirror VMs. Also allow the debugging and status commands. | ||
| 1518 | */ | ||
| 1519 | if (cmd_id == KVM_SEV_LAUNCH_UPDATE_VMSA || | ||
| 1520 | cmd_id == KVM_SEV_GUEST_STATUS || cmd_id == KVM_SEV_DBG_DECRYPT || | ||
| 1521 | cmd_id == KVM_SEV_DBG_ENCRYPT) | ||
| 1522 | return true; | ||
| 1523 | |||
| 1524 | return false; | ||
| 1525 | } | ||
| 1526 | |||
| 1504 | int svm_mem_enc_op(struct kvm *kvm, void __user *argp) | 1527 | int svm_mem_enc_op(struct kvm *kvm, void __user *argp) |
| 1505 | { | 1528 | { |
| 1506 | struct kvm_sev_cmd sev_cmd; | 1529 | struct kvm_sev_cmd sev_cmd; |
| @@ -1517,8 +1540,9 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp) · 10 unmodified lines | |||
| 1517 | 1540 | ||
| 1518 | mutex_lock(&kvm->lock); | 1541 | mutex_lock(&kvm->lock); |
| 1519 | 1542 | ||
| 1520 | /* enc_context_owner handles all memory enc operations */ | 1543 | /* Only the enc_context_owner handles some memory enc operations. */ |
| 1521 | if (is_mirroring_enc_context(kvm)) { | 1544 | if (is_mirroring_enc_context(kvm) && |
| 1545 | !cmd_allowed_from_miror(sev_cmd.id)) { | ||
| 1522 | r = -EINVAL; | 1546 | r = -EINVAL; |
| 1523 | goto out; | 1547 | goto out; |
| 1524 | } | 1548 | } |
| @@ -1715,8 +1739,7 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd) · 190 unmodified lines | |||
| 1715 | { | 1739 | { |
| 1716 | struct file *source_kvm_file; | 1740 | struct file *source_kvm_file; |
| 1717 | struct kvm *source_kvm; | 1741 | struct kvm *source_kvm; |
| 1718 | struct kvm_sev_info *mirror_sev; | 1742 | struct kvm_sev_info source_sev, *mirror_sev; |
| 1719 | unsigned int asid; | ||
| 1720 | int ret; | 1743 | int ret; |
| 1721 | 1744 | ||
| 1722 | source_kvm_file = fget(source_fd); | 1745 | source_kvm_file = fget(source_fd); |
| @@ -1739,7 +1762,8 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd) · 16 unmodified lines | |||
| 1739 | goto e_source_unlock; | 1762 | goto e_source_unlock; |
| 1740 | } | 1763 | } |
| 1741 | 1764 | ||
| 1742 | asid = to_kvm_svm(source_kvm)->sev_info.asid; | 1765 | memcpy(&source_sev, &to_kvm_svm(source_kvm)->sev_info, |
| 1766 | sizeof(source_sev)); | ||
| 1743 | 1767 | ||
| 1744 | /* | 1768 | /* |
| 1745 | * The mirror kvm holds an enc_context_owner ref so its asid can't | 1769 | * The mirror kvm holds an enc_context_owner ref so its asid can't |
| @@ -1759,8 +1783,16 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd) · 13 unmodified lines | |||
| 1759 | /* Set enc_context_owner and copy its encryption context over */ | 1783 | /* Set enc_context_owner and copy its encryption context over */ |
| 1760 | mirror_sev = &to_kvm_svm(kvm)->sev_info; | 1784 | mirror_sev = &to_kvm_svm(kvm)->sev_info; |
| 1761 | mirror_sev->enc_context_owner = source_kvm; | 1785 | mirror_sev->enc_context_owner = source_kvm; |
| 1762 | mirror_sev->asid = asid; | ||
| 1763 | mirror_sev->active = true; | 1786 | mirror_sev->active = true; |
| 1787 | mirror_sev->asid = source_sev.asid; | ||
| 1788 | mirror_sev->fd = source_sev.fd; | ||
| 1789 | mirror_sev->es_active = source_sev.es_active; | ||
| 1790 | mirror_sev->handle = source_sev.handle; | ||
| 1791 | /* | ||
| 1792 | * Do not copy ap_jump_table. Since the mirror does not share the same | ||
| 1793 | * KVM contexts as the original, and they may have different | ||
| 1794 | * memory-views. | ||
| 1795 | */ | ||
| 1764 | 1796 | ||
| 1765 | mutex_unlock(&kvm->lock); | 1797 | mutex_unlock(&kvm->lock); |
| 1766 | return 0; | 1798 | return 0; |
| @@ -1566,6 +1566,8 @@ static void svm_clear_vintr(struct vcpu_svm *svm) · 1565 unmodified lines | |||
| 1566 | 1566 | ||
| 1567 | svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & | 1567 | svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & |
| 1568 | V_IRQ_INJECTION_BITS_MASK; | 1568 | V_IRQ_INJECTION_BITS_MASK; |
| 1569 | |||
| 1570 | svm->vmcb->control.int_vector = svm->nested.ctl.int_vector; | ||
| 1569 | } | 1571 | } |
| 1570 | 1572 | ||
| 1571 | vmcb_mark_dirty(svm->vmcb, VMCB_INTR); | 1573 | vmcb_mark_dirty(svm->vmcb, VMCB_INTR); |
| @@ -2222,6 +2224,10 @@ static int gp_interception(struct kvm_vcpu *vcpu) · 650 unmodified lines | |||
| 2222 | if (error_code) | 2224 | if (error_code) |
| 2223 | goto reinject; | 2225 | goto reinject; |
| 2224 | 2226 | ||
| 2227 | /* All SVM instructions expect page aligned RAX */ | ||
| 2228 | if (svm->vmcb->save.rax & ~PAGE_MASK) | ||
| 2229 | goto reinject; | ||
| 2230 | |||
| 2225 | /* Decode the instruction for usage later */ | 2231 | /* Decode the instruction for usage later */ |
| 2226 | if (x86_decode_emulated_instruction(vcpu, 0, NULL, 0) != EMULATION_OK) | 2232 | if (x86_decode_emulated_instruction(vcpu, 0, NULL, 0) != EMULATION_OK) |
| 2227 | goto reinject; | 2233 | goto reinject; |
| @@ -4285,43 +4291,44 @@ static int svm_enter_smm(struct kvm_vcpu *vcpu, char *smstate) · 2057 unmodified lines | |||
| 4285 | struct kvm_host_map map_save; | 4291 | struct kvm_host_map map_save; |
| 4286 | int ret; | 4292 | int ret; |
| 4287 | 4293 | ||
| 4288 | if (is_guest_mode(vcpu)) { | 4294 | if (!is_guest_mode(vcpu)) |
| 4289 | /* FED8h - SVM Guest */ | 4295 | return 0; |
| 4290 | put_smstate(u64, smstate, 0x7ed8, 1); | ||
| 4291 | /* FEE0h - SVM Guest VMCB Physical Address */ | ||
| 4292 | put_smstate(u64, smstate, 0x7ee0, svm->nested.vmcb12_gpa); | ||
| 4293 | 4296 | ||
| 4294 | svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX]; | 4297 | /* FED8h - SVM Guest */ |
| 4295 | svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP]; | 4298 | put_smstate(u64, smstate, 0x7ed8, 1); |
| 4296 | svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP]; | 4299 | /* FEE0h - SVM Guest VMCB Physical Address */ |
| 4300 | put_smstate(u64, smstate, 0x7ee0, svm->nested.vmcb12_gpa); | ||
| 4297 | 4301 | ||
| 4298 | ret = nested_svm_vmexit(svm); | 4302 | svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX]; |
| 4299 | if (ret) | 4303 | svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP]; |
| 4300 | return ret; | 4304 | svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP]; |
| 4301 | 4305 | ||
| 4302 | /* | 4306 | ret = nested_svm_vmexit(svm); |
| 4303 | * KVM uses VMCB01 to store L1 host state while L2 runs but | 4307 | if (ret) |
| 4304 | * VMCB01 is going to be used during SMM and thus the state will | 4308 | return ret; |
| 4305 | * be lost. Temporary save non-VMLOAD/VMSAVE state to the host save | ||
| 4306 | * area pointed to by MSR_VM_HSAVE_PA. APM guarantees that the | ||
| 4307 | * format of the area is identical to guest save area offsetted | ||
| 4308 | * by 0x400 (matches the offset of 'struct vmcb_save_area' | ||
| 4309 | * within 'struct vmcb'). Note: HSAVE area may also be used by | ||
| 4310 | * L1 hypervisor to save additional host context (e.g. KVM does | ||
| 4311 | * that, see svm_prepare_guest_switch()) which must be | ||
| 4312 | * preserved. | ||
| 4313 | */ | ||
| 4314 | if (kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.hsave_msr), | ||
| 4315 | &map_save) == -EINVAL) | ||
| 4316 | return 1; | ||
| 4317 | 4309 | ||
| 4318 | BUILD_BUG_ON(offsetof(struct vmcb, save) != 0x400); | 4310 | /* |
| 4311 | * KVM uses VMCB01 to store L1 host state while L2 runs but | ||
| 4312 | * VMCB01 is going to be used during SMM and thus the state will | ||
| 4313 | * be lost. Temporary save non-VMLOAD/VMSAVE state to the host save | ||
| 4314 | * area pointed to by MSR_VM_HSAVE_PA. APM guarantees that the | ||
| 4315 | * format of the area is identical to guest save area offsetted | ||
| 4316 | * by 0x400 (matches the offset of 'struct vmcb_save_area' | ||
| 4317 | * within 'struct vmcb'). Note: HSAVE area may also be used by | ||
| 4318 | * L1 hypervisor to save additional host context (e.g. KVM does | ||
| 4319 | * that, see svm_prepare_guest_switch()) which must be | ||
| 4320 | * preserved. | ||
| 4321 | */ | ||
| 4322 | if (kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.hsave_msr), | ||
| 4323 | &map_save) == -EINVAL) | ||
| 4324 | return 1; | ||
| 4319 | 4325 | ||
| 4320 | svm_copy_vmrun_state(map_save.hva + 0x400, | 4326 | BUILD_BUG_ON(offsetof(struct vmcb, save) != 0x400); |
| 4321 | &svm->vmcb01.ptr->save); | ||
| 4322 | 4327 | ||
| 4323 | kvm_vcpu_unmap(vcpu, &map_save, true); | 4328 | svm_copy_vmrun_state(map_save.hva + 0x400, |
| 4324 | } | 4329 | &svm->vmcb01.ptr->save); |
| 4330 | |||
| 4331 | kvm_vcpu_unmap(vcpu, &map_save, true); | ||
| 4325 | return 0; | 4332 | return 0; |
| 4326 | } | 4333 | } |
| 4327 | 4334 | ||
| @@ -4329,50 +4336,54 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const char *smstate) · 1 unmodified line | |||
| 4329 | { | 4336 | { |
| 4330 | struct vcpu_svm *svm = to_svm(vcpu); | 4337 | struct vcpu_svm *svm = to_svm(vcpu); |
| 4331 | struct kvm_host_map map, map_save; | 4338 | struct kvm_host_map map, map_save; |
| 4332 | int ret = 0; | 4339 | u64 saved_efer, vmcb12_gpa; |
| 4340 | struct vmcb *vmcb12; | ||
| 4341 | int ret; | ||
| 4333 | 4342 | ||
| 4334 | if (guest_cpuid_has(vcpu, X86_FEATURE_LM)) { | 4343 | if (!guest_cpuid_has(vcpu, X86_FEATURE_LM)) |
| 4335 | u64 saved_efer = GET_SMSTATE(u64, smstate, 0x7ed0); | 4344 | return 0; |
| 4336 | u64 guest = GET_SMSTATE(u64, smstate, 0x7ed8); | ||
| 4337 | u64 vmcb12_gpa = GET_SMSTATE(u64, smstate, 0x7ee0); | ||
| 4338 | struct vmcb *vmcb12; | ||
| 4339 | 4345 | ||
| 4340 | if (guest) { | 4346 | /* Non-zero if SMI arrived while vCPU was in guest mode. */ |
| 4341 | if (!guest_cpuid_has(vcpu, X86_FEATURE_SVM)) | 4347 | if (!GET_SMSTATE(u64, smstate, 0x7ed8)) |
| 4342 | return 1; | 4348 | return 0; |
| 4343 | 4349 | ||
| 4344 | if (!(saved_efer & EFER_SVME)) | 4350 | if (!guest_cpuid_has(vcpu, X86_FEATURE_SVM)) |
| 4345 | return 1; | 4351 | return 1; |
| 4346 | 4352 | ||
| 4347 | if (kvm_vcpu_map(vcpu, | 4353 | saved_efer = GET_SMSTATE(u64, smstate, 0x7ed0); |
| 4348 | gpa_to_gfn(vmcb12_gpa), &map) == -EINVAL) | 4354 | if (!(saved_efer & EFER_SVME)) |
| 4349 | return 1; | 4355 | return 1; |
| 4350 | 4356 | ||
| 4351 | if (svm_allocate_nested(svm)) | 4357 | vmcb12_gpa = GET_SMSTATE(u64, smstate, 0x7ee0); |
| 4352 | return 1; | 4358 | if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map) == -EINVAL) |
| 4359 | return 1; | ||
| 4353 | 4360 | ||
| 4354 | vmcb12 = map.hva; | 4361 | ret = 1; |
| 4362 | if (kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.hsave_msr), &map_save) == -EINVAL) | ||
| 4363 | goto unmap_map; | ||
| 4355 | 4364 | ||
| 4356 | nested_load_control_from_vmcb12(svm, &vmcb12->control); | 4365 | if (svm_allocate_nested(svm)) |
| 4366 | goto unmap_save; | ||
| 4357 | 4367 | ||
| 4358 | ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12); | 4368 | /* |
| 4359 | kvm_vcpu_unmap(vcpu, &map, true); | 4369 | * Restore L1 host state from L1 HSAVE area as VMCB01 was |
| 4370 | * used during SMM (see svm_enter_smm()) | ||
| 4371 | */ | ||
| 4360 | 4372 | ||
| 4361 | /* | 4373 | svm_copy_vmrun_state(&svm->vmcb01.ptr->save, map_save.hva + 0x400); |
| 4362 | * Restore L1 host state from L1 HSAVE area as VMCB01 was | ||
| 4363 | * used during SMM (see svm_enter_smm()) | ||
| 4364 | */ | ||
| 4365 | if (kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.hsave_msr), | ||
| 4366 | &map_save) == -EINVAL) | ||
| 4367 | return 1; | ||
| 4368 | 4374 | ||
| 4369 | svm_copy_vmrun_state(&svm->vmcb01.ptr->save, | 4375 | /* |
| 4370 | map_save.hva + 0x400); | 4376 | * Enter the nested guest now |
| 4377 | */ | ||
| 4371 | 4378 | ||
| 4372 | kvm_vcpu_unmap(vcpu, &map_save, true); | 4379 | vmcb12 = map.hva; |
| 4373 | } | 4380 | nested_load_control_from_vmcb12(svm, &vmcb12->control); |
| 4374 | } | 4381 | ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, false); |
| 4375 | 4382 | ||
| 4383 | unmap_save: | ||
| 4384 | kvm_vcpu_unmap(vcpu, &map_save, true); | ||
| 4385 | unmap_map: | ||
| 4386 | kvm_vcpu_unmap(vcpu, &map, true); | ||
| 4376 | return ret; | 4387 | return ret; |
| 4377 | } | 4388 | } |
| 4378 | 4389 | ||
| @@ -459,7 +459,8 @@ static inline bool nested_exit_on_nmi(struct vcpu_svm *svm) · 458 unmodified lines | |||
| 459 | return vmcb_is_intercept(&svm->nested.ctl, INTERCEPT_NMI); | 459 | return vmcb_is_intercept(&svm->nested.ctl, INTERCEPT_NMI); |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb_gpa, struct vmcb *vmcb12); | 462 | int enter_svm_guest_mode(struct kvm_vcpu *vcpu, |
| 463 | u64 vmcb_gpa, struct vmcb *vmcb12, bool from_vmrun); | ||
| 463 | void svm_leave_nested(struct vcpu_svm *svm); | 464 | void svm_leave_nested(struct vcpu_svm *svm); |
| 464 | void svm_free_nested(struct vcpu_svm *svm); | 465 | void svm_free_nested(struct vcpu_svm *svm); |
| 465 | int svm_allocate_nested(struct vcpu_svm *svm); | 466 | int svm_allocate_nested(struct vcpu_svm *svm); |
| @@ -353,14 +353,20 @@ void nested_evmcs_filter_control_msr(u32 msr_index, u64 *pdata) · 352 unmodified lines | |||
| 353 | switch (msr_index) { | 353 | switch (msr_index) { |
| 354 | case MSR_IA32_VMX_EXIT_CTLS: | 354 | case MSR_IA32_VMX_EXIT_CTLS: |
| 355 | case MSR_IA32_VMX_TRUE_EXIT_CTLS: | 355 | case MSR_IA32_VMX_TRUE_EXIT_CTLS: |
| 356 | ctl_high &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL; | 356 | ctl_high &= ~EVMCS1_UNSUPPORTED_VMEXIT_CTRL; |
| 357 | break; | 357 | break; |
| 358 | case MSR_IA32_VMX_ENTRY_CTLS: | 358 | case MSR_IA32_VMX_ENTRY_CTLS: |
| 359 | case MSR_IA32_VMX_TRUE_ENTRY_CTLS: | 359 | case MSR_IA32_VMX_TRUE_ENTRY_CTLS: |
| 360 | ctl_high &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL; | 360 | ctl_high &= ~EVMCS1_UNSUPPORTED_VMENTRY_CTRL; |
| 361 | break; | 361 | break; |
| 362 | case MSR_IA32_VMX_PROCBASED_CTLS2: | 362 | case MSR_IA32_VMX_PROCBASED_CTLS2: |
| 363 | ctl_high &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES; | 363 | ctl_high &= ~EVMCS1_UNSUPPORTED_2NDEXEC; |
| 364 | break; | ||
| 365 | case MSR_IA32_VMX_PINBASED_CTLS: | ||
| 366 | ctl_high &= ~EVMCS1_UNSUPPORTED_PINCTRL; | ||
| 367 | break; | ||
| 368 | case MSR_IA32_VMX_VMFUNC: | ||
| 369 | ctl_low &= ~EVMCS1_UNSUPPORTED_VMFUNC; | ||
| 364 | break; | 370 | break; |
| 365 | } | 371 | } |
| 366 | 372 | ||
| @@ -2583,8 +2583,13 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, · 2582 unmodified lines | |||
| 2583 | * Guest state is invalid and unrestricted guest is disabled, | 2583 | * Guest state is invalid and unrestricted guest is disabled, |
| 2584 | * which means L1 attempted VMEntry to L2 with invalid state. | 2584 | * which means L1 attempted VMEntry to L2 with invalid state. |
| 2585 | * Fail the VMEntry. | 2585 | * Fail the VMEntry. |
| 2586 | * | ||
| 2587 | * However when force loading the guest state (SMM exit or | ||
| 2588 | * loading nested state after migration, it is possible to | ||
| 2589 | * have invalid guest state now, which will be later fixed by | ||
| 2590 | * restoring L2 register state | ||
| 2586 | */ | 2591 | */ |
| 2587 | if (CC(!vmx_guest_state_valid(vcpu))) { | 2592 | if (CC(from_vmentry && !vmx_guest_state_valid(vcpu))) { |
| 2588 | *entry_failure_code = ENTRY_FAIL_DEFAULT; | 2593 | *entry_failure_code = ENTRY_FAIL_DEFAULT; |
| 2589 | return -EINVAL; | 2594 | return -EINVAL; |
| 2590 | } | 2595 | } |
| @@ -4351,6 +4356,8 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, · 1760 unmodified lines | |||
| 4351 | if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr, | 4356 | if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr, |
| 4352 | vmcs12->vm_exit_msr_load_count)) | 4357 | vmcs12->vm_exit_msr_load_count)) |
| 4353 | nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL); | 4358 | nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL); |
| 4359 | |||
| 4360 | to_vmx(vcpu)->emulation_required = vmx_emulation_required(vcpu); | ||
| 4354 | } | 4361 | } |
| 4355 | 4362 | ||
| 4356 | static inline u64 nested_vmx_get_vmcs01_guest_efer(struct vcpu_vmx *vmx) | 4363 | static inline u64 nested_vmx_get_vmcs01_guest_efer(struct vcpu_vmx *vmx) |
| @@ -4899,14 +4906,7 @@ out_vmcs02: · 542 unmodified lines | |||
| 4899 | return -ENOMEM; | 4906 | return -ENOMEM; |
| 4900 | } | 4907 | } |
| 4901 | 4908 | ||
| 4902 | /* | 4909 | /* Emulate the VMXON instruction. */ |
| 4903 | * Emulate the VMXON instruction. | ||
| 4904 | * Currently, we just remember that VMX is active, and do not save or even | ||
| 4905 | * inspect the argument to VMXON (the so-called "VMXON pointer") because we | ||
| 4906 | * do not currently need to store anything in that guest-allocated memory | ||
| 4907 | * region. Consequently, VMCLEAR and VMPTRLD also do not verify that the their | ||
| 4908 | * argument is different from the VMXON pointer (which the spec says they do). | ||
| 4909 | */ | ||
| 4910 | static int handle_vmon(struct kvm_vcpu *vcpu) | 4910 | static int handle_vmon(struct kvm_vcpu *vcpu) |
| 4911 | { | 4911 | { |
| 4912 | int ret; | 4912 | int ret; |
| @@ -5903,6 +5903,12 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu, · 990 unmodified lines | |||
| 5903 | case EXIT_REASON_VMFUNC: | 5903 | case EXIT_REASON_VMFUNC: |
| 5904 | /* VM functions are emulated through L2->L0 vmexits. */ | 5904 | /* VM functions are emulated through L2->L0 vmexits. */ |
| 5905 | return true; | 5905 | return true; |
| 5906 | case EXIT_REASON_BUS_LOCK: | ||
| 5907 | /* | ||
| 5908 | * At present, bus lock VM exit is never exposed to L1. | ||
| 5909 | * Handle L2's bus locks in L0 directly. | ||
| 5910 | */ | ||
| 5911 | return true; | ||
| 5906 | default: | 5912 | default: |
| 5907 | break; | 5913 | break; |
| 5908 | } | 5914 | } |
| @@ -1323,7 +1323,7 @@ static void vmx_vcpu_put(struct kvm_vcpu *vcpu) · 1322 unmodified lines | |||
| 1323 | vmx_prepare_switch_to_host(to_vmx(vcpu)); | 1323 | vmx_prepare_switch_to_host(to_vmx(vcpu)); |
| 1324 | } | 1324 | } |
| 1325 | 1325 | ||
| 1326 | static bool emulation_required(struct kvm_vcpu *vcpu) | 1326 | bool vmx_emulation_required(struct kvm_vcpu *vcpu) |
| 1327 | { | 1327 | { |
| 1328 | return emulate_invalid_guest_state && !vmx_guest_state_valid(vcpu); | 1328 | return emulate_invalid_guest_state && !vmx_guest_state_valid(vcpu); |
| 1329 | } | 1329 | } |
| @@ -1367,7 +1367,7 @@ void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) · 37 unmodified lines | |||
| 1367 | vmcs_writel(GUEST_RFLAGS, rflags); | 1367 | vmcs_writel(GUEST_RFLAGS, rflags); |
| 1368 | 1368 | ||
| 1369 | if ((old_rflags ^ vmx->rflags) & X86_EFLAGS_VM) | 1369 | if ((old_rflags ^ vmx->rflags) & X86_EFLAGS_VM) |
| 1370 | vmx->emulation_required = emulation_required(vcpu); | 1370 | vmx->emulation_required = vmx_emulation_required(vcpu); |
| 1371 | } | 1371 | } |
| 1372 | 1372 | ||
| 1373 | u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu) | 1373 | u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu) |
| @@ -1837,10 +1837,11 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) · 463 unmodified lines | |||
| 1837 | &msr_info->data)) | 1837 | &msr_info->data)) |
| 1838 | return 1; | 1838 | return 1; |
| 1839 | /* | 1839 | /* |
| 1840 | * Enlightened VMCS v1 doesn't have certain fields, but buggy | 1840 | * Enlightened VMCS v1 doesn't have certain VMCS fields but |
| 1841 | * Hyper-V versions are still trying to use corresponding | 1841 | * instead of just ignoring the features, different Hyper-V |
| 1842 | * features when they are exposed. Filter out the essential | 1842 | * versions are either trying to use them and fail or do some |
| 1843 | * minimum. | 1843 | * sanity checking and refuse to boot. Filter all unsupported |
| 1844 | * features out. | ||
| 1844 | */ | 1845 | */ |
| 1845 | if (!msr_info->host_initiated && | 1846 | if (!msr_info->host_initiated && |
| 1846 | vmx->nested.enlightened_vmcs_enabled) | 1847 | vmx->nested.enlightened_vmcs_enabled) |
| @@ -3077,7 +3078,7 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) · 1230 unmodified lines | |||
| 3077 | } | 3078 | } |
| 3078 | 3079 | ||
| 3079 | /* depends on vcpu->arch.cr0 to be set to a new value */ | 3080 | /* depends on vcpu->arch.cr0 to be set to a new value */ |
| 3080 | vmx->emulation_required = emulation_required(vcpu); | 3081 | vmx->emulation_required = vmx_emulation_required(vcpu); |
| 3081 | } | 3082 | } |
| 3082 | 3083 | ||
| 3083 | static int vmx_get_max_tdp_level(void) | 3084 | static int vmx_get_max_tdp_level(void) |
| @@ -3330,7 +3331,7 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int · 246 unmodified lines | |||
| 3330 | { | 3331 | { |
| 3331 | __vmx_set_segment(vcpu, var, seg); | 3332 | __vmx_set_segment(vcpu, var, seg); |
| 3332 | 3333 | ||
| 3333 | to_vmx(vcpu)->emulation_required = emulation_required(vcpu); | 3334 | to_vmx(vcpu)->emulation_required = vmx_emulation_required(vcpu); |
| 3334 | } | 3335 | } |
| 3335 | 3336 | ||
| 3336 | static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) | 3337 | static void vmx_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l) |
| @@ -6621,10 +6622,24 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu) · 3284 unmodified lines | |||
| 6621 | vmx->loaded_vmcs->soft_vnmi_blocked)) | 6622 | vmx->loaded_vmcs->soft_vnmi_blocked)) |
| 6622 | vmx->loaded_vmcs->entry_time = ktime_get(); | 6623 | vmx->loaded_vmcs->entry_time = ktime_get(); |
| 6623 | 6624 | ||
| 6624 | /* Don't enter VMX if guest state is invalid, let the exit handler | 6625 | /* |
| 6625 | start emulation until we arrive back to a valid state */ | 6626 | * Don't enter VMX if guest state is invalid, let the exit handler |
| 6626 | if (vmx->emulation_required) | 6627 | * start emulation until we arrive back to a valid state. Synthesize a |
| 6628 | * consistency check VM-Exit due to invalid guest state and bail. | ||
| 6629 | */ | ||
| 6630 | if (unlikely(vmx->emulation_required)) { | ||
| 6631 | |||
| 6632 | /* We don't emulate invalid state of a nested guest */ | ||
| 6633 | vmx->fail = is_guest_mode(vcpu); | ||
| 6634 | |||
| 6635 | vmx->exit_reason.full = EXIT_REASON_INVALID_STATE; | ||
| 6636 | vmx->exit_reason.failed_vmentry = 1; | ||
| 6637 | kvm_register_mark_available(vcpu, VCPU_EXREG_EXIT_INFO_1); | ||
| 6638 | vmx->exit_qualification = ENTRY_FAIL_DEFAULT; | ||
| 6639 | kvm_register_mark_available(vcpu, VCPU_EXREG_EXIT_INFO_2); | ||
| 6640 | vmx->exit_intr_info = 0; | ||
| 6627 | return EXIT_FASTPATH_NONE; | 6641 | return EXIT_FASTPATH_NONE; |
| 6642 | } | ||
| 6628 | 6643 | ||
| 6629 | trace_kvm_entry(vcpu); | 6644 | trace_kvm_entry(vcpu); |
| 6630 | 6645 | ||
| @@ -6833,7 +6848,7 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu) · 202 unmodified lines | |||
| 6833 | */ | 6848 | */ |
| 6834 | tsx_ctrl = vmx_find_uret_msr(vmx, MSR_IA32_TSX_CTRL); | 6849 | tsx_ctrl = vmx_find_uret_msr(vmx, MSR_IA32_TSX_CTRL); |
| 6835 | if (tsx_ctrl) | 6850 | if (tsx_ctrl) |
| 6836 | vmx->guest_uret_msrs[i].mask = ~(u64)TSX_CTRL_CPUID_CLEAR; | 6851 | tsx_ctrl->mask = ~(u64)TSX_CTRL_CPUID_CLEAR; |
| 6837 | } | 6852 | } |
| 6838 | 6853 | ||
| 6839 | err = alloc_loaded_vmcs(&vmx->vmcs01); | 6854 | err = alloc_loaded_vmcs(&vmx->vmcs01); |
| @@ -248,12 +248,8 @@ struct vcpu_vmx { · 247 unmodified lines | |||
| 248 | * only loaded into hardware when necessary, e.g. SYSCALL #UDs outside | 248 | * only loaded into hardware when necessary, e.g. SYSCALL #UDs outside |
| 249 | * of 64-bit mode or if EFER.SCE=1, thus the SYSCALL MSRs don't need to | 249 | * of 64-bit mode or if EFER.SCE=1, thus the SYSCALL MSRs don't need to |
| 250 | * be loaded into hardware if those conditions aren't met. | 250 | * be loaded into hardware if those conditions aren't met. |
| 251 | * nr_active_uret_msrs tracks the number of MSRs that need to be loaded | ||
| 252 | * into hardware when running the guest. guest_uret_msrs[] is resorted | ||
| 253 | * whenever the number of "active" uret MSRs is modified. | ||
| 254 | */ | 251 | */ |
| 255 | struct vmx_uret_msr guest_uret_msrs[MAX_NR_USER_RETURN_MSRS]; | 252 | struct vmx_uret_msr guest_uret_msrs[MAX_NR_USER_RETURN_MSRS]; |
| 256 | int nr_active_uret_msrs; | ||
| 257 | bool guest_uret_msrs_loaded; | 253 | bool guest_uret_msrs_loaded; |
| 258 | #ifdef CONFIG_X86_64 | 254 | #ifdef CONFIG_X86_64 |
| 259 | u64 msr_host_kernel_gs_base; | 255 | u64 msr_host_kernel_gs_base; |
| @@ -359,6 +355,7 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu); · 99 unmodified lines | |||
| 359 | void vmx_set_host_fs_gs(struct vmcs_host_state *host, u16 fs_sel, u16 gs_sel, | 355 | void vmx_set_host_fs_gs(struct vmcs_host_state *host, u16 fs_sel, u16 gs_sel, |
| 360 | unsigned long fs_base, unsigned long gs_base); | 356 | unsigned long fs_base, unsigned long gs_base); |
| 361 | int vmx_get_cpl(struct kvm_vcpu *vcpu); | 357 | int vmx_get_cpl(struct kvm_vcpu *vcpu); |
| 358 | bool vmx_emulation_required(struct kvm_vcpu *vcpu); | ||
| 362 | unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu); | 359 | unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu); |
| 363 | void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags); | 360 | void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags); |
| 364 | u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu); | 361 | u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu); |
| @@ -1332,6 +1332,13 @@ static const u32 msrs_to_save_all[] = { · 1331 unmodified lines | |||
| 1332 | MSR_ARCH_PERFMON_EVENTSEL0 + 12, MSR_ARCH_PERFMON_EVENTSEL0 + 13, | 1332 | MSR_ARCH_PERFMON_EVENTSEL0 + 12, MSR_ARCH_PERFMON_EVENTSEL0 + 13, |
| 1333 | MSR_ARCH_PERFMON_EVENTSEL0 + 14, MSR_ARCH_PERFMON_EVENTSEL0 + 15, | 1333 | MSR_ARCH_PERFMON_EVENTSEL0 + 14, MSR_ARCH_PERFMON_EVENTSEL0 + 15, |
| 1334 | MSR_ARCH_PERFMON_EVENTSEL0 + 16, MSR_ARCH_PERFMON_EVENTSEL0 + 17, | 1334 | MSR_ARCH_PERFMON_EVENTSEL0 + 16, MSR_ARCH_PERFMON_EVENTSEL0 + 17, |
| 1335 | |||
| 1336 | MSR_K7_EVNTSEL0, MSR_K7_EVNTSEL1, MSR_K7_EVNTSEL2, MSR_K7_EVNTSEL3, | ||
| 1337 | MSR_K7_PERFCTR0, MSR_K7_PERFCTR1, MSR_K7_PERFCTR2, MSR_K7_PERFCTR3, | ||
| 1338 | MSR_F15H_PERF_CTL0, MSR_F15H_PERF_CTL1, MSR_F15H_PERF_CTL2, | ||
| 1339 | MSR_F15H_PERF_CTL3, MSR_F15H_PERF_CTL4, MSR_F15H_PERF_CTL5, | ||
| 1340 | MSR_F15H_PERF_CTR0, MSR_F15H_PERF_CTR1, MSR_F15H_PERF_CTR2, | ||
| 1341 | MSR_F15H_PERF_CTR3, MSR_F15H_PERF_CTR4, MSR_F15H_PERF_CTR5, | ||
| 1335 | }; | 1342 | }; |
| 1336 | 1343 | ||
| 1337 | static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_all)]; | 1344 | static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_all)]; |
| @@ -2969,7 +2976,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) · 1631 unmodified lines | |||
| 2969 | offsetof(struct compat_vcpu_info, time)); | 2976 | offsetof(struct compat_vcpu_info, time)); |
| 2970 | if (vcpu->xen.vcpu_time_info_set) | 2977 | if (vcpu->xen.vcpu_time_info_set) |
| 2971 | kvm_setup_pvclock_page(v, &vcpu->xen.vcpu_time_info_cache, 0); | 2978 | kvm_setup_pvclock_page(v, &vcpu->xen.vcpu_time_info_cache, 0); |
| 2972 | if (v == kvm_get_vcpu(v->kvm, 0)) | 2979 | if (!v->vcpu_idx) |
| 2973 | kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock); | 2980 | kvm_hv_setup_tsc_page(v->kvm, &vcpu->hv_clock); |
| 2974 | return 0; | 2981 | return 0; |
| 2975 | } | 2982 | } |
| @@ -7658,6 +7665,13 @@ static void kvm_smm_changed(struct kvm_vcpu *vcpu, bool entering_smm) · 4682 unmodified lines | |||
| 7658 | 7665 | ||
| 7659 | /* Process a latched INIT or SMI, if any. */ | 7666 | /* Process a latched INIT or SMI, if any. */ |
| 7660 | kvm_make_request(KVM_REQ_EVENT, vcpu); | 7667 | kvm_make_request(KVM_REQ_EVENT, vcpu); |
| 7668 | |||
| 7669 | /* | ||
| 7670 | * Even if KVM_SET_SREGS2 loaded PDPTRs out of band, | ||
| 7671 | * on SMM exit we still need to reload them from | ||
| 7672 | * guest memory | ||
| 7673 | */ | ||
| 7674 | vcpu->arch.pdptrs_from_userspace = false; | ||
| 7661 | } | 7675 | } |
| 7662 | 7676 | ||
| 7663 | kvm_mmu_reset_context(vcpu); | 7677 | kvm_mmu_reset_context(vcpu); |
| @@ -10652,6 +10666,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) · 2988 unmodified lines | |||
| 10652 | int r; | 10666 | int r; |
| 10653 | 10667 | ||
| 10654 | vcpu->arch.last_vmentry_cpu = -1; | 10668 | vcpu->arch.last_vmentry_cpu = -1; |
| 10669 | vcpu->arch.regs_avail = ~0; | ||
| 10670 | vcpu->arch.regs_dirty = ~0; | ||
| 10655 | 10671 | ||
| 10656 | if (!irqchip_in_kernel(vcpu->kvm) || kvm_vcpu_is_reset_bsp(vcpu)) | 10672 | if (!irqchip_in_kernel(vcpu->kvm) || kvm_vcpu_is_reset_bsp(vcpu)) |
| 10657 | vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; | 10673 | vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; |
| @@ -10893,6 +10909,9 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) · 235 unmodified lines | |||
| 10893 | kvm_set_rflags(vcpu, X86_EFLAGS_FIXED); | 10909 | kvm_set_rflags(vcpu, X86_EFLAGS_FIXED); |
| 10894 | kvm_rip_write(vcpu, 0xfff0); | 10910 | kvm_rip_write(vcpu, 0xfff0); |
| 10895 | 10911 | ||
| 10912 | vcpu->arch.cr3 = 0; | ||
| 10913 | kvm_register_mark_dirty(vcpu, VCPU_EXREG_CR3); | ||
| 10914 | |||
| 10896 | /* | 10915 | /* |
| 10897 | * CR0.CD/NW are set on RESET, preserved on INIT. Note, some versions | 10916 | * CR0.CD/NW are set on RESET, preserved on INIT. Note, some versions |
| 10898 | * of Intel's SDM list CD/NW as being set on INIT, but they contradict | 10917 | * of Intel's SDM list CD/NW as being set on INIT, but they contradict |
| @@ -11139,9 +11158,15 @@ void kvm_arch_free_vm(struct kvm *kvm) · 240 unmodified lines | |||
| 11139 | 11158 | ||
| 11140 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | 11159 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) |
| 11141 | { | 11160 | { |
| 11161 | int ret; | ||
| 11162 | |||
| 11142 | if (type) | 11163 | if (type) |
| 11143 | return -EINVAL; | 11164 | return -EINVAL; |
| 11144 | 11165 | ||
| 11166 | ret = kvm_page_track_init(kvm); | ||
| 11167 | if (ret) | ||
| 11168 | return ret; | ||
| 11169 | |||
| 11145 | INIT_HLIST_HEAD(&kvm->arch.mask_notifier_list); | 11170 | INIT_HLIST_HEAD(&kvm->arch.mask_notifier_list); |
| 11146 | INIT_LIST_HEAD(&kvm->arch.active_mmu_pages); | 11171 | INIT_LIST_HEAD(&kvm->arch.active_mmu_pages); |
| 11147 | INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages); | 11172 | INIT_LIST_HEAD(&kvm->arch.zapped_obsolete_pages); |
| @@ -11174,7 +11199,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) · 26 unmodified lines | |||
| 11174 | 11199 | ||
| 11175 | kvm_apicv_init(kvm); | 11200 | kvm_apicv_init(kvm); |
| 11176 | kvm_hv_init_vm(kvm); | 11201 | kvm_hv_init_vm(kvm); |
| 11177 | kvm_page_track_init(kvm); | ||
| 11178 | kvm_mmu_init_vm(kvm); | 11202 | kvm_mmu_init_vm(kvm); |
| 11179 | kvm_xen_init_vm(kvm); | 11203 | kvm_xen_init_vm(kvm); |
| 11180 | 11204 | ||
| @@ -1341,9 +1341,10 @@ st: if (is_imm8(insn->off)) · 1340 unmodified lines | |||
| 1341 | if (insn->imm == (BPF_AND | BPF_FETCH) || | 1341 | if (insn->imm == (BPF_AND | BPF_FETCH) || |
| 1342 | insn->imm == (BPF_OR | BPF_FETCH) || | 1342 | insn->imm == (BPF_OR | BPF_FETCH) || |
| 1343 | insn->imm == (BPF_XOR | BPF_FETCH)) { | 1343 | insn->imm == (BPF_XOR | BPF_FETCH)) { |
| 1344 | u8 *branch_target; | ||
| 1345 | bool is64 = BPF_SIZE(insn->code) == BPF_DW; | 1344 | bool is64 = BPF_SIZE(insn->code) == BPF_DW; |
| 1346 | u32 real_src_reg = src_reg; | 1345 | u32 real_src_reg = src_reg; |
| 1346 | u32 real_dst_reg = dst_reg; | ||
| 1347 | u8 *branch_target; | ||
| 1347 | 1348 | ||
| 1348 | /* | 1349 | /* |
| 1349 | * Can't be implemented with a single x86 insn. | 1350 | * Can't be implemented with a single x86 insn. |
| @@ -1354,11 +1355,13 @@ st: if (is_imm8(insn->off)) · 4 unmodified lines | |||
| 1354 | emit_mov_reg(&prog, true, BPF_REG_AX, BPF_REG_0); | 1355 | emit_mov_reg(&prog, true, BPF_REG_AX, BPF_REG_0); |
| 1355 | if (src_reg == BPF_REG_0) | 1356 | if (src_reg == BPF_REG_0) |
| 1356 | real_src_reg = BPF_REG_AX; | 1357 | real_src_reg = BPF_REG_AX; |
| 1358 | if (dst_reg == BPF_REG_0) | ||
| 1359 | real_dst_reg = BPF_REG_AX; | ||
| 1357 | 1360 | ||
| 1358 | branch_target = prog; | 1361 | branch_target = prog; |
| 1359 | /* Load old value */ | 1362 | /* Load old value */ |
| 1360 | emit_ldx(&prog, BPF_SIZE(insn->code), | 1363 | emit_ldx(&prog, BPF_SIZE(insn->code), |
| 1361 | BPF_REG_0, dst_reg, insn->off); | 1364 | BPF_REG_0, real_dst_reg, insn->off); |
| 1362 | /* | 1365 | /* |
| 1363 | * Perform the (commutative) operation locally, | 1366 | * Perform the (commutative) operation locally, |
| 1364 | * put the result in the AUX_REG. | 1367 | * put the result in the AUX_REG. |
| @@ -1369,7 +1372,8 @@ st: if (is_imm8(insn->off)) · 4 unmodified lines | |||
| 1369 | add_2reg(0xC0, AUX_REG, real_src_reg)); | 1372 | add_2reg(0xC0, AUX_REG, real_src_reg)); |
| 1370 | /* Attempt to swap in new value */ | 1373 | /* Attempt to swap in new value */ |
| 1371 | err = emit_atomic(&prog, BPF_CMPXCHG, | 1374 | err = emit_atomic(&prog, BPF_CMPXCHG, |
| 1372 | dst_reg, AUX_REG, insn->off, | 1375 | real_dst_reg, AUX_REG, |
| 1376 | insn->off, | ||
| 1373 | BPF_SIZE(insn->code)); | 1377 | BPF_SIZE(insn->code)); |
| 1374 | if (WARN_ON(err)) | 1378 | if (WARN_ON(err)) |
| 1375 | return err; | 1379 | return err; |
| @@ -1383,11 +1387,10 @@ st: if (is_imm8(insn->off)) · 7 unmodified lines | |||
| 1383 | /* Restore R0 after clobbering RAX */ | 1387 | /* Restore R0 after clobbering RAX */ |
| 1384 | emit_mov_reg(&prog, true, BPF_REG_0, BPF_REG_AX); | 1388 | emit_mov_reg(&prog, true, BPF_REG_0, BPF_REG_AX); |
| 1385 | break; | 1389 | break; |
| 1386 | |||
| 1387 | } | 1390 | } |
| 1388 | 1391 | ||
| 1389 | err = emit_atomic(&prog, insn->imm, dst_reg, src_reg, | 1392 | err = emit_atomic(&prog, insn->imm, dst_reg, src_reg, |
| 1390 | insn->off, BPF_SIZE(insn->code)); | 1393 | insn->off, BPF_SIZE(insn->code)); |
| 1391 | if (err) | 1394 | if (err) |
| 1392 | return err; | 1395 | return err; |
| 1393 | break; | 1396 | break; |
| @@ -1744,7 +1747,7 @@ static void restore_regs(const struct btf_func_model *m, u8 **prog, int nr_args, · 350 unmodified lines | |||
| 1744 | } | 1747 | } |
| 1745 | 1748 | ||
| 1746 | static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog, | 1749 | static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog, |
| 1747 | struct bpf_prog *p, int stack_size, bool mod_ret) | 1750 | struct bpf_prog *p, int stack_size, bool save_ret) |
| 1748 | { | 1751 | { |
| 1749 | u8 *prog = *pprog; | 1752 | u8 *prog = *pprog; |
| 1750 | u8 *jmp_insn; | 1753 | u8 *jmp_insn; |
| @@ -1777,11 +1780,15 @@ static int invoke_bpf_prog(const struct btf_func_model *m, u8 **pprog, · 26 unmodified lines | |||
| 1777 | if (emit_call(&prog, p->bpf_func, prog)) | 1780 | if (emit_call(&prog, p->bpf_func, prog)) |
| 1778 | return -EINVAL; | 1781 | return -EINVAL; |
| 1779 | 1782 | ||
| 1780 | /* BPF_TRAMP_MODIFY_RETURN trampolines can modify the return | 1783 | /* |
| 1784 | * BPF_TRAMP_MODIFY_RETURN trampolines can modify the return | ||
| 1781 | * of the previous call which is then passed on the stack to | 1785 | * of the previous call which is then passed on the stack to |
| 1782 | * the next BPF program. | 1786 | * the next BPF program. |
| 1787 | * | ||
| 1788 | * BPF_TRAMP_FENTRY trampoline may need to return the return | ||
| 1789 | * value of BPF_PROG_TYPE_STRUCT_OPS prog. | ||
| 1783 | */ | 1790 | */ |
| 1784 | if (mod_ret) | 1791 | if (save_ret) |
| 1785 | emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8); | 1792 | emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -8); |
| 1786 | 1793 | ||
| 1787 | /* replace 2 nops with JE insn, since jmp target is known */ | 1794 | /* replace 2 nops with JE insn, since jmp target is known */ |
| @@ -1828,13 +1835,15 @@ static int emit_cond_near_jump(u8 **pprog, void *func, void *ip, u8 jmp_cond) · 40 unmodified lines | |||
| 1828 | } | 1835 | } |
| 1829 | 1836 | ||
| 1830 | static int invoke_bpf(const struct btf_func_model *m, u8 **pprog, | 1837 | static int invoke_bpf(const struct btf_func_model *m, u8 **pprog, |
| 1831 | struct bpf_tramp_progs *tp, int stack_size) | 1838 | struct bpf_tramp_progs *tp, int stack_size, |
| 1839 | bool save_ret) | ||
| 1832 | { | 1840 | { |
| 1833 | int i; | 1841 | int i; |
| 1834 | u8 *prog = *pprog; | 1842 | u8 *prog = *pprog; |
| 1835 | 1843 | ||
| 1836 | for (i = 0; i < tp->nr_progs; i++) { | 1844 | for (i = 0; i < tp->nr_progs; i++) { |
| 1837 | if (invoke_bpf_prog(m, &prog, tp->progs[i], stack_size, false)) | 1845 | if (invoke_bpf_prog(m, &prog, tp->progs[i], stack_size, |
| 1846 | save_ret)) | ||
| 1838 | return -EINVAL; | 1847 | return -EINVAL; |
| 1839 | } | 1848 | } |
| 1840 | *pprog = prog; | 1849 | *pprog = prog; |
| @@ -1877,6 +1886,23 @@ static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog, · 36 unmodified lines | |||
| 1877 | return 0; | 1886 | return 0; |
| 1878 | } | 1887 | } |
| 1879 | 1888 | ||
| 1889 | static bool is_valid_bpf_tramp_flags(unsigned int flags) | ||
| 1890 | { | ||
| 1891 | if ((flags & BPF_TRAMP_F_RESTORE_REGS) && | ||
| 1892 | (flags & BPF_TRAMP_F_SKIP_FRAME)) | ||
| 1893 | return false; | ||
| 1894 | |||
| 1895 | /* | ||
| 1896 | * BPF_TRAMP_F_RET_FENTRY_RET is only used by bpf_struct_ops, | ||
| 1897 | * and it must be used alone. | ||
| 1898 | */ | ||
| 1899 | if ((flags & BPF_TRAMP_F_RET_FENTRY_RET) && | ||
| 1900 | (flags & ~BPF_TRAMP_F_RET_FENTRY_RET)) | ||
| 1901 | return false; | ||
| 1902 | |||
| 1903 | return true; | ||
| 1904 | } | ||
| 1905 | |||
| 1880 | /* Example: | 1906 | /* Example: |
| 1881 | * __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev); | 1907 | * __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev); |
| 1882 | * its 'struct btf_func_model' will be nr_args=2 | 1908 | * its 'struct btf_func_model' will be nr_args=2 |
| @@ -1949,17 +1975,19 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i · 66 unmodified lines | |||
| 1949 | struct bpf_tramp_progs *fmod_ret = &tprogs[BPF_TRAMP_MODIFY_RETURN]; | 1975 | struct bpf_tramp_progs *fmod_ret = &tprogs[BPF_TRAMP_MODIFY_RETURN]; |
| 1950 | u8 **branches = NULL; | 1976 | u8 **branches = NULL; |
| 1951 | u8 *prog; | 1977 | u8 *prog; |
| 1978 | bool save_ret; | ||
| 1952 | 1979 | ||
| 1953 | /* x86-64 supports up to 6 arguments. 7+ can be added in the future */ | 1980 | /* x86-64 supports up to 6 arguments. 7+ can be added in the future */ |
| 1954 | if (nr_args > 6) | 1981 | if (nr_args > 6) |
| 1955 | return -ENOTSUPP; | 1982 | return -ENOTSUPP; |
| 1956 | 1983 | ||
| 1957 | if ((flags & BPF_TRAMP_F_RESTORE_REGS) && | 1984 | if (!is_valid_bpf_tramp_flags(flags)) |
| 1958 | (flags & BPF_TRAMP_F_SKIP_FRAME)) | ||
| 1959 | return -EINVAL; | 1985 | return -EINVAL; |
| 1960 | 1986 | ||
| 1961 | if (flags & BPF_TRAMP_F_CALL_ORIG) | 1987 | /* room for return value of orig_call or fentry prog */ |
| 1962 | stack_size += 8; /* room for return value of orig_call */ | 1988 | save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET); |
| 1989 | if (save_ret) | ||
| 1990 | stack_size += 8; | ||
| 1963 | 1991 | ||
| 1964 | if (flags & BPF_TRAMP_F_IP_ARG) | 1992 | if (flags & BPF_TRAMP_F_IP_ARG) |
| 1965 | stack_size += 8; /* room for IP address argument */ | 1993 | stack_size += 8; /* room for IP address argument */ |
| @@ -2005,7 +2033,8 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i · 39 unmodified lines | |||
| 2005 | } | 2033 | } |
| 2006 | 2034 | ||
| 2007 | if (fentry->nr_progs) | 2035 | if (fentry->nr_progs) |
| 2008 | if (invoke_bpf(m, &prog, fentry, stack_size)) | 2036 | if (invoke_bpf(m, &prog, fentry, stack_size, |
| 2037 | flags & BPF_TRAMP_F_RET_FENTRY_RET)) | ||
| 2009 | return -EINVAL; | 2038 | return -EINVAL; |
| 2010 | 2039 | ||
| 2011 | if (fmod_ret->nr_progs) { | 2040 | if (fmod_ret->nr_progs) { |
| @@ -2052,7 +2081,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i · 40 unmodified lines | |||
| 2052 | } | 2081 | } |
| 2053 | 2082 | ||
| 2054 | if (fexit->nr_progs) | 2083 | if (fexit->nr_progs) |
| 2055 | if (invoke_bpf(m, &prog, fexit, stack_size)) { | 2084 | if (invoke_bpf(m, &prog, fexit, stack_size, false)) { |
| 2056 | ret = -EINVAL; | 2085 | ret = -EINVAL; |
| 2057 | goto cleanup; | 2086 | goto cleanup; |
| 2058 | } | 2087 | } |
| @@ -2072,9 +2101,10 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i · 13 unmodified lines | |||
| 2072 | ret = -EINVAL; | 2101 | ret = -EINVAL; |
| 2073 | goto cleanup; | 2102 | goto cleanup; |
| 2074 | } | 2103 | } |
| 2075 | /* restore original return value back into RAX */ | ||
| 2076 | emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, -8); | ||
| 2077 | } | 2104 | } |
| 2105 | /* restore return value of orig_call or fentry prog back into RAX */ | ||
| 2106 | if (save_ret) | ||
| 2107 | emit_ldx(&prog, BPF_DW, BPF_REG_0, BPF_REG_FP, -8); | ||
| 2078 | 2108 | ||
| 2079 | EMIT1(0x5B); /* pop rbx */ | 2109 | EMIT1(0x5B); /* pop rbx */ |
| 2080 | EMIT1(0xC9); /* leave */ | 2110 | EMIT1(0xC9); /* leave */ |
| @@ -2662,15 +2662,6 @@ bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) · 2661 unmodified lines | |||
| 2662 | * are likely to increase the throughput. | 2662 | * are likely to increase the throughput. |
| 2663 | */ | 2663 | */ |
| 2664 | bfqq->new_bfqq = new_bfqq; | 2664 | bfqq->new_bfqq = new_bfqq; |
| 2665 | /* | ||
| 2666 | * The above assignment schedules the following redirections: | ||
| 2667 | * each time some I/O for bfqq arrives, the process that | ||
| 2668 | * generated that I/O is disassociated from bfqq and | ||
| 2669 | * associated with new_bfqq. Here we increases new_bfqq->ref | ||
| 2670 | * in advance, adding the number of processes that are | ||
| 2671 | * expected to be associated with new_bfqq as they happen to | ||
| 2672 | * issue I/O. | ||
| 2673 | */ | ||
| 2674 | new_bfqq->ref += process_refs; | 2665 | new_bfqq->ref += process_refs; |
| 2675 | return new_bfqq; | 2666 | return new_bfqq; |
| 2676 | } | 2667 | } |
| @@ -2733,10 +2724,6 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, · 56 unmodified lines | |||
| 2733 | { | 2724 | { |
| 2734 | struct bfq_queue *in_service_bfqq, *new_bfqq; | 2725 | struct bfq_queue *in_service_bfqq, *new_bfqq; |
| 2735 | 2726 | ||
| 2736 | /* if a merge has already been setup, then proceed with that first */ | ||
| 2737 | if (bfqq->new_bfqq) | ||
| 2738 | return bfqq->new_bfqq; | ||
| 2739 | |||
| 2740 | /* | 2727 | /* |
| 2741 | * Check delayed stable merge for rotational or non-queueing | 2728 | * Check delayed stable merge for rotational or non-queueing |
| 2742 | * devs. For this branch to be executed, bfqq must not be | 2729 | * devs. For this branch to be executed, bfqq must not be |
| @@ -2838,6 +2825,9 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, · 95 unmodified lines | |||
| 2838 | if (bfq_too_late_for_merging(bfqq)) | 2825 | if (bfq_too_late_for_merging(bfqq)) |
| 2839 | return NULL; | 2826 | return NULL; |
| 2840 | 2827 | ||
| 2828 | if (bfqq->new_bfqq) | ||
| 2829 | return bfqq->new_bfqq; | ||
| 2830 | |||
| 2841 | if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq)) | 2831 | if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq)) |
| 2842 | return NULL; | 2832 | return NULL; |
| 2843 | 2833 | ||
| @@ -3007,6 +3007,18 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc, · 3006 unmodified lines | |||
| 3007 | ndr_desc->target_node = NUMA_NO_NODE; | 3007 | ndr_desc->target_node = NUMA_NO_NODE; |
| 3008 | } | 3008 | } |
| 3009 | 3009 | ||
| 3010 | /* Fallback to address based numa information if node lookup failed */ | ||
| 3011 | if (ndr_desc->numa_node == NUMA_NO_NODE) { | ||
| 3012 | ndr_desc->numa_node = memory_add_physaddr_to_nid(spa->address); | ||
| 3013 | dev_info(acpi_desc->dev, "changing numa node from %d to %d for nfit region [%pa-%pa]", | ||
| 3014 | NUMA_NO_NODE, ndr_desc->numa_node, &res.start, &res.end); | ||
| 3015 | } | ||
| 3016 | if (ndr_desc->target_node == NUMA_NO_NODE) { | ||
| 3017 | ndr_desc->target_node = phys_to_target_node(spa->address); | ||
| 3018 | dev_info(acpi_desc->dev, "changing target node from %d to %d for nfit region [%pa-%pa]", | ||
| 3019 | NUMA_NO_NODE, ndr_desc->numa_node, &res.start, &res.end); | ||
| 3020 | } | ||
| 3021 | |||
| 3010 | /* | 3022 | /* |
| 3011 | * Persistence domain bits are hierarchical, if | 3023 | * Persistence domain bits are hierarchical, if |
| 3012 | * ACPI_NFIT_CAPABILITY_CACHE_FLUSH is set then | 3024 | * ACPI_NFIT_CAPABILITY_CACHE_FLUSH is set then |
| @@ -95,12 +95,29 @@ int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup) · 94 unmodified lines | |||
| 95 | 95 | ||
| 96 | list_add(&link->s_hook, &sup->consumers); | 96 | list_add(&link->s_hook, &sup->consumers); |
| 97 | list_add(&link->c_hook, &con->suppliers); | 97 | list_add(&link->c_hook, &con->suppliers); |
| 98 | pr_debug("%pfwP Linked as a fwnode consumer to %pfwP\n", | ||
| 99 | con, sup); | ||
| 98 | out: | 100 | out: |
| 99 | mutex_unlock(&fwnode_link_lock); | 101 | mutex_unlock(&fwnode_link_lock); |
| 100 | 102 | ||
| 101 | return ret; | 103 | return ret; |
| 102 | } | 104 | } |
| 103 | 105 | ||
| 106 | /** | ||
| 107 | * __fwnode_link_del - Delete a link between two fwnode_handles. | ||
| 108 | * @link: the fwnode_link to be deleted | ||
| 109 | * | ||
| 110 | * The fwnode_link_lock needs to be held when this function is called. | ||
| 111 | */ | ||
| 112 | static void __fwnode_link_del(struct fwnode_link *link) | ||
| 113 | { | ||
| 114 | pr_debug("%pfwP Dropping the fwnode link to %pfwP\n", | ||
| 115 | link->consumer, link->supplier); | ||
| 116 | list_del(&link->s_hook); | ||
| 117 | list_del(&link->c_hook); | ||
| 118 | kfree(link); | ||
| 119 | } | ||
| 120 | |||
| 104 | /** | 121 | /** |
| 105 | * fwnode_links_purge_suppliers - Delete all supplier links of fwnode_handle. | 122 | * fwnode_links_purge_suppliers - Delete all supplier links of fwnode_handle. |
| 106 | * @fwnode: fwnode whose supplier links need to be deleted | 123 | * @fwnode: fwnode whose supplier links need to be deleted |
| @@ -112,11 +129,8 @@ static void fwnode_links_purge_suppliers(struct fwnode_handle *fwnode) · 5 unmodified lines | |||
| 112 | struct fwnode_link *link, *tmp; | 129 | struct fwnode_link *link, *tmp; |
| 113 | 130 | ||
| 114 | mutex_lock(&fwnode_link_lock); | 131 | mutex_lock(&fwnode_link_lock); |
| 115 | list_for_each_entry_safe(link, tmp, &fwnode->suppliers, c_hook) { | 132 | list_for_each_entry_safe(link, tmp, &fwnode->suppliers, c_hook) |
| 116 | list_del(&link->s_hook); | 133 | __fwnode_link_del(link); |
| 117 | list_del(&link->c_hook); | ||
| 118 | kfree(link); | ||
| 119 | } | ||
| 120 | mutex_unlock(&fwnode_link_lock); | 134 | mutex_unlock(&fwnode_link_lock); |
| 121 | } | 135 | } |
| 122 | 136 | ||
| @@ -131,11 +145,8 @@ static void fwnode_links_purge_consumers(struct fwnode_handle *fwnode) · 8 unmodified lines | |||
| 131 | struct fwnode_link *link, *tmp; | 145 | struct fwnode_link *link, *tmp; |
| 132 | 146 | ||
| 133 | mutex_lock(&fwnode_link_lock); | 147 | mutex_lock(&fwnode_link_lock); |
| 134 | list_for_each_entry_safe(link, tmp, &fwnode->consumers, s_hook) { | 148 | list_for_each_entry_safe(link, tmp, &fwnode->consumers, s_hook) |
| 135 | list_del(&link->s_hook); | 149 | __fwnode_link_del(link); |
| 136 | list_del(&link->c_hook); | ||
| 137 | kfree(link); | ||
| 138 | } | ||
| 139 | mutex_unlock(&fwnode_link_lock); | 150 | mutex_unlock(&fwnode_link_lock); |
| 140 | } | 151 | } |
| 141 | 152 | ||
| @@ -975,6 +986,7 @@ int device_links_check_suppliers(struct device *dev) · 833 unmodified lines | |||
| 975 | { | 986 | { |
| 976 | struct device_link *link; | 987 | struct device_link *link; |
| 977 | int ret = 0; | 988 | int ret = 0; |
| 989 | struct fwnode_handle *sup_fw; | ||
| 978 | 990 | ||
| 979 | /* | 991 | /* |
| 980 | * Device waiting for supplier to become available is not allowed to | 992 | * Device waiting for supplier to become available is not allowed to |
| @@ -983,10 +995,11 @@ int device_links_check_suppliers(struct device *dev) · 2 unmodified lines | |||
| 983 | mutex_lock(&fwnode_link_lock); | 995 | mutex_lock(&fwnode_link_lock); |
| 984 | if (dev->fwnode && !list_empty(&dev->fwnode->suppliers) && | 996 | if (dev->fwnode && !list_empty(&dev->fwnode->suppliers) && |
| 985 | !fw_devlink_is_permissive()) { | 997 | !fw_devlink_is_permissive()) { |
| 986 | dev_dbg(dev, "probe deferral - wait for supplier %pfwP\n", | 998 | sup_fw = list_first_entry(&dev->fwnode->suppliers, |
| 987 | list_first_entry(&dev->fwnode->suppliers, | 999 | struct fwnode_link, |
| 988 | struct fwnode_link, | 1000 | c_hook)->supplier; |
| 989 | c_hook)->supplier); | 1001 | dev_err_probe(dev, -EPROBE_DEFER, "wait for supplier %pfwP\n", |
| 1002 | sup_fw); | ||
| 990 | mutex_unlock(&fwnode_link_lock); | 1003 | mutex_unlock(&fwnode_link_lock); |
| 991 | return -EPROBE_DEFER; | 1004 | return -EPROBE_DEFER; |
| 992 | } | 1005 | } |
| @@ -1001,8 +1014,9 @@ int device_links_check_suppliers(struct device *dev) · 8 unmodified lines | |||
| 1001 | if (link->status != DL_STATE_AVAILABLE && | 1014 | if (link->status != DL_STATE_AVAILABLE && |
| 1002 | !(link->flags & DL_FLAG_SYNC_STATE_ONLY)) { | 1015 | !(link->flags & DL_FLAG_SYNC_STATE_ONLY)) { |
| 1003 | device_links_missing_supplier(dev); | 1016 | device_links_missing_supplier(dev); |
| 1004 | dev_dbg(dev, "probe deferral - supplier %s not ready\n", | 1017 | dev_err_probe(dev, -EPROBE_DEFER, |
| 1005 | dev_name(link->supplier)); | 1018 | "supplier %s not ready\n", |
| 1019 | dev_name(link->supplier)); | ||
| 1006 | ret = -EPROBE_DEFER; | 1020 | ret = -EPROBE_DEFER; |
| 1007 | break; | 1021 | break; |
| 1008 | } | 1022 | } |
| @@ -1722,6 +1736,25 @@ static int fw_devlink_create_devlink(struct device *con, · 713 unmodified lines | |||
| 1722 | struct device *sup_dev; | 1736 | struct device *sup_dev; |
| 1723 | int ret = 0; | 1737 | int ret = 0; |
| 1724 | 1738 | ||
| 1739 | /* | ||
| 1740 | * In some cases, a device P might also be a supplier to its child node | ||
| 1741 | * C. However, this would defer the probe of C until the probe of P | ||
| 1742 | * completes successfully. This is perfectly fine in the device driver | ||
| 1743 | * model. device_add() doesn't guarantee probe completion of the device | ||
| 1744 | * by the time it returns. | ||
| 1745 | * | ||
| 1746 | * However, there are a few drivers that assume C will finish probing | ||
| 1747 | * as soon as it's added and before P finishes probing. So, we provide | ||
| 1748 | * a flag to let fw_devlink know not to delay the probe of C until the | ||
| 1749 | * probe of P completes successfully. | ||
| 1750 | * | ||
| 1751 | * When such a flag is set, we can't create device links where P is the | ||
| 1752 | * supplier of C as that would delay the probe of C. | ||
| 1753 | */ | ||
| 1754 | if (sup_handle->flags & FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD && | ||
| 1755 | fwnode_is_ancestor_of(sup_handle, con->fwnode)) | ||
| 1756 | return -EINVAL; | ||
| 1757 | |||
| 1725 | sup_dev = get_dev_from_fwnode(sup_handle); | 1758 | sup_dev = get_dev_from_fwnode(sup_handle); |
| 1726 | if (sup_dev) { | 1759 | if (sup_dev) { |
| 1727 | /* | 1760 | /* |
| @@ -1772,14 +1805,21 @@ static int fw_devlink_create_devlink(struct device *con, · 44 unmodified lines | |||
| 1772 | * be broken by applying logic. Check for these types of cycles and | 1805 | * be broken by applying logic. Check for these types of cycles and |
| 1773 | * break them so that devices in the cycle probe properly. | 1806 | * break them so that devices in the cycle probe properly. |
| 1774 | * | 1807 | * |
| 1775 | * If the supplier's parent is dependent on the consumer, then | 1808 | * If the supplier's parent is dependent on the consumer, then the |
| 1776 | * the consumer-supplier dependency is a false dependency. So, | 1809 | * consumer and supplier have a cyclic dependency. Since fw_devlink |
| 1777 | * treat it as an invalid link. | 1810 | * can't tell which of the inferred dependencies are incorrect, don't |
| 1811 | * enforce probe ordering between any of the devices in this cyclic | ||
| 1812 | * dependency. Do this by relaxing all the fw_devlink device links in | ||
| 1813 | * this cycle and by treating the fwnode link between the consumer and | ||
| 1814 | * the supplier as an invalid dependency. | ||
| 1778 | */ | 1815 | */ |
| 1779 | sup_dev = fwnode_get_next_parent_dev(sup_handle); | 1816 | sup_dev = fwnode_get_next_parent_dev(sup_handle); |
| 1780 | if (sup_dev && device_is_dependent(con, sup_dev)) { | 1817 | if (sup_dev && device_is_dependent(con, sup_dev)) { |
| 1781 | dev_dbg(con, "Not linking to %pfwP - False link\n", | 1818 | dev_info(con, "Fixing up cyclic dependency with %pfwP (%s)\n", |
| 1782 | sup_handle); | 1819 | sup_handle, dev_name(sup_dev)); |
| 1820 | device_links_write_lock(); | ||
| 1821 | fw_devlink_relax_cycle(con, sup_dev); | ||
| 1822 | device_links_write_unlock(); | ||
| 1783 | ret = -EINVAL; | 1823 | ret = -EINVAL; |
| 1784 | } else { | 1824 | } else { |
| 1785 | /* | 1825 | /* |
| @@ -1858,9 +1898,7 @@ static void __fw_devlink_link_to_consumers(struct device *dev) · 72 unmodified lines | |||
| 1858 | if (!own_link || ret == -EAGAIN) | 1898 | if (!own_link || ret == -EAGAIN) |
| 1859 | continue; | 1899 | continue; |
| 1860 | 1900 | ||
| 1861 | list_del(&link->s_hook); | 1901 | __fwnode_link_del(link); |
| 1862 | list_del(&link->c_hook); | ||
| 1863 | kfree(link); | ||
| 1864 | } | 1902 | } |
| 1865 | } | 1903 | } |
| 1866 | 1904 | ||
| @@ -1912,9 +1950,7 @@ static void __fw_devlink_link_to_suppliers(struct device *dev, · 45 unmodified lines | |||
| 1912 | if (!own_link || ret == -EAGAIN) | 1950 | if (!own_link || ret == -EAGAIN) |
| 1913 | continue; | 1951 | continue; |
| 1914 | 1952 | ||
| 1915 | list_del(&link->s_hook); | 1953 | __fwnode_link_del(link); |
| 1916 | list_del(&link->c_hook); | ||
| 1917 | kfree(link); | ||
| 1918 | 1954 | ||
| 1919 | /* If no device link was created, nothing more to do. */ | 1955 | /* If no device link was created, nothing more to do. */ |
| 1920 | if (ret) | 1956 | if (ret) |
| @@ -97,13 +97,18 @@ struct nbd_config { · 96 unmodified lines | |||
| 97 | 97 | ||
| 98 | atomic_t recv_threads; | 98 | atomic_t recv_threads; |
| 99 | wait_queue_head_t recv_wq; | 99 | wait_queue_head_t recv_wq; |
| 100 | loff_t blksize; | 100 | unsigned int blksize_bits; |
| 101 | loff_t bytesize; | 101 | loff_t bytesize; |
| 102 | #if IS_ENABLED(CONFIG_DEBUG_FS) | 102 | #if IS_ENABLED(CONFIG_DEBUG_FS) |
| 103 | struct dentry *dbg_dir; | 103 | struct dentry *dbg_dir; |
| 104 | #endif | 104 | #endif |
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| 107 | static inline unsigned int nbd_blksize(struct nbd_config *config) | ||
| 108 | { | ||
| 109 | return 1u << config->blksize_bits; | ||
| 110 | } | ||
| 111 | |||
| 107 | struct nbd_device { | 112 | struct nbd_device { |
| 108 | struct blk_mq_tag_set tag_set; | 113 | struct blk_mq_tag_set tag_set; |
| 109 | 114 | ||
| @@ -146,7 +151,7 @@ static struct dentry *nbd_dbg_dir; · 36 unmodified lines | |||
| 146 | 151 | ||
| 147 | #define NBD_MAGIC 0x68797548 | 152 | #define NBD_MAGIC 0x68797548 |
| 148 | 153 | ||
| 149 | #define NBD_DEF_BLKSIZE 1024 | 154 | #define NBD_DEF_BLKSIZE_BITS 10 |
| 150 | 155 | ||
| 151 | static unsigned int nbds_max = 16; | 156 | static unsigned int nbds_max = 16; |
| 152 | static int max_part = 16; | 157 | static int max_part = 16; |
| @@ -317,12 +322,12 @@ static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, · 164 unmodified lines | |||
| 317 | loff_t blksize) | 322 | loff_t blksize) |
| 318 | { | 323 | { |
| 319 | if (!blksize) | 324 | if (!blksize) |
| 320 | blksize = NBD_DEF_BLKSIZE; | 325 | blksize = 1u << NBD_DEF_BLKSIZE_BITS; |
| 321 | if (blksize < 512 || blksize > PAGE_SIZE || !is_power_of_2(blksize)) | 326 | if (blksize < 512 || blksize > PAGE_SIZE || !is_power_of_2(blksize)) |
| 322 | return -EINVAL; | 327 | return -EINVAL; |
| 323 | 328 | ||
| 324 | nbd->config->bytesize = bytesize; | 329 | nbd->config->bytesize = bytesize; |
| 325 | nbd->config->blksize = blksize; | 330 | nbd->config->blksize_bits = __ffs(blksize); |
| 326 | 331 | ||
| 327 | if (!nbd->task_recv) | 332 | if (!nbd->task_recv) |
| 328 | return 0; | 333 | return 0; |
| @@ -1337,7 +1342,7 @@ static int nbd_start_device(struct nbd_device *nbd) · 1008 unmodified lines | |||
| 1337 | args->index = i; | 1342 | args->index = i; |
| 1338 | queue_work(nbd->recv_workq, &args->work); | 1343 | queue_work(nbd->recv_workq, &args->work); |
| 1339 | } | 1344 | } |
| 1340 | return nbd_set_size(nbd, config->bytesize, config->blksize); | 1345 | return nbd_set_size(nbd, config->bytesize, nbd_blksize(config)); |
| 1341 | } | 1346 | } |
| 1342 | 1347 | ||
| 1343 | static int nbd_start_device_ioctl(struct nbd_device *nbd, struct block_device *bdev) | 1348 | static int nbd_start_device_ioctl(struct nbd_device *nbd, struct block_device *bdev) |
| @@ -1406,11 +1411,11 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, · 62 unmodified lines | |||
| 1406 | case NBD_SET_BLKSIZE: | 1411 | case NBD_SET_BLKSIZE: |
| 1407 | return nbd_set_size(nbd, config->bytesize, arg); | 1412 | return nbd_set_size(nbd, config->bytesize, arg); |
| 1408 | case NBD_SET_SIZE: | 1413 | case NBD_SET_SIZE: |
| 1409 | return nbd_set_size(nbd, arg, config->blksize); | 1414 | return nbd_set_size(nbd, arg, nbd_blksize(config)); |
| 1410 | case NBD_SET_SIZE_BLOCKS: | 1415 | case NBD_SET_SIZE_BLOCKS: |
| 1411 | if (check_mul_overflow((loff_t)arg, config->blksize, &bytesize)) | 1416 | if (check_shl_overflow(arg, config->blksize_bits, &bytesize)) |
| 1412 | return -EINVAL; | 1417 | return -EINVAL; |
| 1413 | return nbd_set_size(nbd, bytesize, config->blksize); | 1418 | return nbd_set_size(nbd, bytesize, nbd_blksize(config)); |
| 1414 | case NBD_SET_TIMEOUT: | 1419 | case NBD_SET_TIMEOUT: |
| 1415 | nbd_set_cmd_timeout(nbd, arg); | 1420 | nbd_set_cmd_timeout(nbd, arg); |
| 1416 | return 0; | 1421 | return 0; |
| @@ -1476,7 +1481,7 @@ static struct nbd_config *nbd_alloc_config(void) · 59 unmodified lines | |||
| 1476 | atomic_set(&config->recv_threads, 0); | 1481 | atomic_set(&config->recv_threads, 0); |
| 1477 | init_waitqueue_head(&config->recv_wq); | 1482 | init_waitqueue_head(&config->recv_wq); |
| 1478 | init_waitqueue_head(&config->conn_wait); | 1483 | init_waitqueue_head(&config->conn_wait); |
| 1479 | config->blksize = NBD_DEF_BLKSIZE; | 1484 | config->blksize_bits = NBD_DEF_BLKSIZE_BITS; |
| 1480 | atomic_set(&config->live_connections, 0); | 1485 | atomic_set(&config->live_connections, 0); |
| 1481 | try_module_get(THIS_MODULE); | 1486 | try_module_get(THIS_MODULE); |
| 1482 | return config; | 1487 | return config; |
| @@ -1604,7 +1609,7 @@ static int nbd_dev_dbg_init(struct nbd_device *nbd) · 121 unmodified lines | |||
| 1604 | debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_fops); | 1609 | debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_fops); |
| 1605 | debugfs_create_u64("size_bytes", 0444, dir, &config->bytesize); | 1610 | debugfs_create_u64("size_bytes", 0444, dir, &config->bytesize); |
| 1606 | debugfs_create_u32("timeout", 0444, dir, &nbd->tag_set.timeout); | 1611 | debugfs_create_u32("timeout", 0444, dir, &nbd->tag_set.timeout); |
| 1607 | debugfs_create_u64("blocksize", 0444, dir, &config->blksize); | 1612 | debugfs_create_u32("blocksize_bits", 0444, dir, &config->blksize_bits); |
| 1608 | debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_fops); | 1613 | debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_fops); |
| 1609 | 1614 | ||
| 1610 | return 0; | 1615 | return 0; |
| @@ -1826,7 +1831,7 @@ nbd_device_policy[NBD_DEVICE_ATTR_MAX + 1] = { · 215 unmodified lines | |||
| 1826 | static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd) | 1831 | static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd) |
| 1827 | { | 1832 | { |
| 1828 | struct nbd_config *config = nbd->config; | 1833 | struct nbd_config *config = nbd->config; |
| 1829 | u64 bsize = config->blksize; | 1834 | u64 bsize = nbd_blksize(config); |
| 1830 | u64 bytes = config->bytesize; | 1835 | u64 bytes = config->bytesize; |
| 1831 | 1836 | ||
| 1832 | if (info->attrs[NBD_ATTR_SIZE_BYTES]) | 1837 | if (info->attrs[NBD_ATTR_SIZE_BYTES]) |
| @@ -1835,7 +1840,7 @@ static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd) · 2 unmodified lines | |||
| 1835 | if (info->attrs[NBD_ATTR_BLOCK_SIZE_BYTES]) | 1840 | if (info->attrs[NBD_ATTR_BLOCK_SIZE_BYTES]) |
| 1836 | bsize = nla_get_u64(info->attrs[NBD_ATTR_BLOCK_SIZE_BYTES]); | 1841 | bsize = nla_get_u64(info->attrs[NBD_ATTR_BLOCK_SIZE_BYTES]); |
| 1837 | 1842 | ||
| 1838 | if (bytes != config->bytesize || bsize != config->blksize) | 1843 | if (bytes != config->bytesize || bsize != nbd_blksize(config)) |
| 1839 | return nbd_set_size(nbd, bytes, bsize); | 1844 | return nbd_set_size(nbd, bytes, bsize); |
| 1840 | return 0; | 1845 | return 0; |
| 1841 | } | 1846 | } |
| @@ -778,7 +778,7 @@ ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) · 777 unmodified lines | |||
| 778 | in_place ? DMA_BIDIRECTIONAL | 778 | in_place ? DMA_BIDIRECTIONAL |
| 779 | : DMA_TO_DEVICE); | 779 | : DMA_TO_DEVICE); |
| 780 | if (ret) | 780 | if (ret) |
| 781 | goto e_ctx; | 781 | goto e_aad; |
| 782 | 782 | ||
| 783 | if (in_place) { | 783 | if (in_place) { |
| 784 | dst = src; | 784 | dst = src; |
| @@ -863,7 +863,7 @@ ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) · 78 unmodified lines | |||
| 863 | op.u.aes.size = 0; | 863 | op.u.aes.size = 0; |
| 864 | ret = cmd_q->ccp->vdata->perform->aes(&op); | 864 | ret = cmd_q->ccp->vdata->perform->aes(&op); |
| 865 | if (ret) | 865 | if (ret) |
| 866 | goto e_dst; | 866 | goto e_final_wa; |
| 867 | 867 | ||
| 868 | if (aes->action == CCP_AES_ACTION_ENCRYPT) { | 868 | if (aes->action == CCP_AES_ACTION_ENCRYPT) { |
| 869 | /* Put the ciphered tag after the ciphertext. */ | 869 | /* Put the ciphered tag after the ciphertext. */ |
| @@ -873,17 +873,19 @@ ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) · 3 unmodified lines | |||
| 873 | ret = ccp_init_dm_workarea(&tag, cmd_q, authsize, | 873 | ret = ccp_init_dm_workarea(&tag, cmd_q, authsize, |
| 874 | DMA_BIDIRECTIONAL); | 874 | DMA_BIDIRECTIONAL); |
| 875 | if (ret) | 875 | if (ret) |
| 876 | goto e_tag; | 876 | goto e_final_wa; |
| 877 | ret = ccp_set_dm_area(&tag, 0, p_tag, 0, authsize); | 877 | ret = ccp_set_dm_area(&tag, 0, p_tag, 0, authsize); |
| 878 | if (ret) | 878 | if (ret) { |
| 879 | goto e_tag; | 879 | ccp_dm_free(&tag); |
| 880 | goto e_final_wa; | ||
| 881 | } | ||
| 880 | 882 | ||
| 881 | ret = crypto_memneq(tag.address, final_wa.address, | 883 | ret = crypto_memneq(tag.address, final_wa.address, |
| 882 | authsize) ? -EBADMSG : 0; | 884 | authsize) ? -EBADMSG : 0; |
| 883 | ccp_dm_free(&tag); | 885 | ccp_dm_free(&tag); |
| 884 | } | 886 | } |
| 885 | 887 | ||
| 886 | e_tag: | 888 | e_final_wa: |
| 887 | ccp_dm_free(&final_wa); | 889 | ccp_dm_free(&final_wa); |
| 888 | 890 | ||
| 889 | e_dst: | 891 | e_dst: |
| @@ -468,15 +468,8 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) · 467 unmodified lines | |||
| 468 | mutex_lock(&chip->i2c_lock); | 468 | mutex_lock(&chip->i2c_lock); |
| 469 | ret = regmap_read(chip->regmap, inreg, ®_val); | 469 | ret = regmap_read(chip->regmap, inreg, ®_val); |
| 470 | mutex_unlock(&chip->i2c_lock); | 470 | mutex_unlock(&chip->i2c_lock); |
| 471 | if (ret < 0) { | 471 | if (ret < 0) |
| 472 | /* | 472 | return ret; |
| 473 | * NOTE: | ||
| 474 | * diagnostic already emitted; that's all we should | ||
| 475 | * do unless gpio_*_value_cansleep() calls become different | ||
| 476 | * from their nonsleeping siblings (and report faults). | ||
| 477 | */ | ||
| 478 | return 0; | ||
| 479 | } | ||
| 480 | 473 | ||
| 481 | return !!(reg_val & bit); | 474 | return !!(reg_val & bit); |
| 482 | } | 475 | } |
| @@ -689,6 +689,7 @@ static int rockchip_gpio_probe(struct platform_device *pdev) · 688 unmodified lines | |||
| 689 | struct device_node *pctlnp = of_get_parent(np); | 689 | struct device_node *pctlnp = of_get_parent(np); |
| 690 | struct pinctrl_dev *pctldev = NULL; | 690 | struct pinctrl_dev *pctldev = NULL; |
| 691 | struct rockchip_pin_bank *bank = NULL; | 691 | struct rockchip_pin_bank *bank = NULL; |
| 692 | struct rockchip_pin_output_deferred *cfg; | ||
| 692 | static int gpio; | 693 | static int gpio; |
| 693 | int id, ret; | 694 | int id, ret; |
| 694 | 695 | ||
| @@ -716,12 +717,33 @@ static int rockchip_gpio_probe(struct platform_device *pdev) · 21 unmodified lines | |||
| 716 | if (ret) | 717 | if (ret) |
| 717 | return ret; | 718 | return ret; |
| 718 | 719 | ||
| 720 | /* | ||
| 721 | * Prevent clashes with a deferred output setting | ||
| 722 | * being added right at this moment. | ||
| 723 | */ | ||
| 724 | mutex_lock(&bank->deferred_lock); | ||
| 725 | |||
| 719 | ret = rockchip_gpiolib_register(bank); | 726 | ret = rockchip_gpiolib_register(bank); |
| 720 | if (ret) { | 727 | if (ret) { |
| 721 | clk_disable_unprepare(bank->clk); | 728 | clk_disable_unprepare(bank->clk); |
| 729 | mutex_unlock(&bank->deferred_lock); | ||
| 722 | return ret; | 730 | return ret; |
| 723 | } | 731 | } |
| 724 | 732 | ||
| 733 | while (!list_empty(&bank->deferred_output)) { | ||
| 734 | cfg = list_first_entry(&bank->deferred_output, | ||
| 735 | struct rockchip_pin_output_deferred, head); | ||
| 736 | list_del(&cfg->head); | ||
| 737 | |||
| 738 | ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg); | ||
| 739 | if (ret) | ||
| 740 | dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin, cfg->arg); | ||
| 741 | |||
| 742 | kfree(cfg); | ||
| 743 | } | ||
| 744 | |||
| 745 | mutex_unlock(&bank->deferred_lock); | ||
| 746 | |||
| 725 | platform_set_drvdata(pdev, bank); | 747 | platform_set_drvdata(pdev, bank); |
| 726 | dev_info(dev, "probed %pOF\n", np); | 748 | dev_info(dev, "probed %pOF\n", np); |
| 727 | 749 | ||
| @@ -837,6 +837,28 @@ static int convert_tiling_flags_to_modifier(struct amdgpu_framebuffer *afb) · 836 unmodified lines | |||
| 837 | return 0; | 837 | return 0; |
| 838 | } | 838 | } |
| 839 | 839 | ||
| 840 | /* Mirrors the is_displayable check in radeonsi's gfx6_compute_surface */ | ||
| 841 | static int check_tiling_flags_gfx6(struct amdgpu_framebuffer *afb) | ||
| 842 | { | ||
| 843 | u64 micro_tile_mode; | ||
| 844 | |||
| 845 | /* Zero swizzle mode means linear */ | ||
| 846 | if (AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0) | ||
| 847 | return 0; | ||
| 848 | |||
| 849 | micro_tile_mode = AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE); | ||
| 850 | switch (micro_tile_mode) { | ||
| 851 | case 0: /* DISPLAY */ | ||
| 852 | case 3: /* RENDER */ | ||
| 853 | return 0; | ||
| 854 | default: | ||
| 855 | drm_dbg_kms(afb->base.dev, | ||
| 856 | "Micro tile mode %llu not supported for scanout\n", | ||
| 857 | micro_tile_mode); | ||
| 858 | return -EINVAL; | ||
| 859 | } | ||
| 860 | } | ||
| 861 | |||
| 840 | static void get_block_dimensions(unsigned int block_log2, unsigned int cpp, | 862 | static void get_block_dimensions(unsigned int block_log2, unsigned int cpp, |
| 841 | unsigned int *width, unsigned int *height) | 863 | unsigned int *width, unsigned int *height) |
| 842 | { | 864 | { |
| @@ -1103,6 +1125,7 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev, · 260 unmodified lines | |||
| 1103 | const struct drm_mode_fb_cmd2 *mode_cmd, | 1125 | const struct drm_mode_fb_cmd2 *mode_cmd, |
| 1104 | struct drm_gem_object *obj) | 1126 | struct drm_gem_object *obj) |
| 1105 | { | 1127 | { |
| 1128 | struct amdgpu_device *adev = drm_to_adev(dev); | ||
| 1106 | int ret, i; | 1129 | int ret, i; |
| 1107 | 1130 | ||
| 1108 | /* | 1131 | /* |
| @@ -1122,6 +1145,14 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev, · 13 unmodified lines | |||
| 1122 | if (ret) | 1145 | if (ret) |
| 1123 | return ret; | 1146 | return ret; |
| 1124 | 1147 | ||
| 1148 | if (!dev->mode_config.allow_fb_modifiers) { | ||
| 1149 | drm_WARN_ONCE(dev, adev->family >= AMDGPU_FAMILY_AI, | ||
| 1150 | "GFX9+ requires FB check based on format modifier\n"); | ||
| 1151 | ret = check_tiling_flags_gfx6(rfb); | ||
| 1152 | if (ret) | ||
| 1153 | return ret; | ||
| 1154 | } | ||
| 1155 | |||
| 1125 | if (dev->mode_config.allow_fb_modifiers && | 1156 | if (dev->mode_config.allow_fb_modifiers && |
| 1126 | !(rfb->base.flags & DRM_MODE_FB_MODIFIERS)) { | 1157 | !(rfb->base.flags & DRM_MODE_FB_MODIFIERS)) { |
| 1127 | ret = convert_tiling_flags_to_modifier(rfb); | 1158 | ret = convert_tiling_flags_to_modifier(rfb); |
| @@ -3599,7 +3599,7 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring) · 3598 unmodified lines | |||
| 3599 | 3599 | ||
| 3600 | /* set static priority for a queue/ring */ | 3600 | /* set static priority for a queue/ring */ |
| 3601 | gfx_v9_0_mqd_set_priority(ring, mqd); | 3601 | gfx_v9_0_mqd_set_priority(ring, mqd); |
| 3602 | mqd->cp_hqd_quantum = RREG32(mmCP_HQD_QUANTUM); | 3602 | mqd->cp_hqd_quantum = RREG32_SOC15(GC, 0, mmCP_HQD_QUANTUM); |
| 3603 | 3603 | ||
| 3604 | /* map_queues packet doesn't need activate the queue, | 3604 | /* map_queues packet doesn't need activate the queue, |
| 3605 | * so only kiq need set this field. | 3605 | * so only kiq need set this field. |
| @@ -1098,6 +1098,8 @@ static int gmc_v10_0_hw_fini(void *handle) · 1097 unmodified lines | |||
| 1098 | { | 1098 | { |
| 1099 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1099 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1100 | 1100 | ||
| 1101 | gmc_v10_0_gart_disable(adev); | ||
| 1102 | |||
| 1101 | if (amdgpu_sriov_vf(adev)) { | 1103 | if (amdgpu_sriov_vf(adev)) { |
| 1102 | /* full access mode, so don't touch any GMC register */ | 1104 | /* full access mode, so don't touch any GMC register */ |
| 1103 | DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); | 1105 | DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); |
| @@ -1106,7 +1108,6 @@ static int gmc_v10_0_hw_fini(void *handle) · 2 unmodified lines | |||
| 1106 | 1108 | ||
| 1107 | amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0); | 1109 | amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0); |
| 1108 | amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0); | 1110 | amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0); |
| 1109 | gmc_v10_0_gart_disable(adev); | ||
| 1110 | 1111 | ||
| 1111 | return 0; | 1112 | return 0; |
| 1112 | } | 1113 | } |
| @@ -1794,6 +1794,8 @@ static int gmc_v9_0_hw_fini(void *handle) · 1793 unmodified lines | |||
| 1794 | { | 1794 | { |
| 1795 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1795 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1796 | 1796 | ||
| 1797 | gmc_v9_0_gart_disable(adev); | ||
| 1798 | |||
| 1797 | if (amdgpu_sriov_vf(adev)) { | 1799 | if (amdgpu_sriov_vf(adev)) { |
| 1798 | /* full access mode, so don't touch any GMC register */ | 1800 | /* full access mode, so don't touch any GMC register */ |
| 1799 | DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); | 1801 | DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); |
| @@ -1802,7 +1804,6 @@ static int gmc_v9_0_hw_fini(void *handle) · 2 unmodified lines | |||
| 1802 | 1804 | ||
| 1803 | amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0); | 1805 | amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0); |
| 1804 | amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0); | 1806 | amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0); |
| 1805 | gmc_v9_0_gart_disable(adev); | ||
| 1806 | 1807 | ||
| 1807 | return 0; | 1808 | return 0; |
| 1808 | } | 1809 | } |
| @@ -868,6 +868,12 @@ static int sdma_v5_2_start(struct amdgpu_device *adev) · 867 unmodified lines | |||
| 868 | msleep(1000); | 868 | msleep(1000); |
| 869 | } | 869 | } |
| 870 | 870 | ||
| 871 | /* TODO: check whether can submit a doorbell request to raise | ||
| 872 | * a doorbell fence to exit gfxoff. | ||
| 873 | */ | ||
| 874 | if (adev->in_s0ix) | ||
| 875 | amdgpu_gfx_off_ctrl(adev, false); | ||
| 876 | |||
| 871 | sdma_v5_2_soft_reset(adev); | 877 | sdma_v5_2_soft_reset(adev); |
| 872 | /* unhalt the MEs */ | 878 | /* unhalt the MEs */ |
| 873 | sdma_v5_2_enable(adev, true); | 879 | sdma_v5_2_enable(adev, true); |
| @@ -876,6 +882,8 @@ static int sdma_v5_2_start(struct amdgpu_device *adev) · 2 unmodified lines | |||
| 876 | 882 | ||
| 877 | /* start the gfx rings and rlc compute queues */ | 883 | /* start the gfx rings and rlc compute queues */ |
| 878 | r = sdma_v5_2_gfx_resume(adev); | 884 | r = sdma_v5_2_gfx_resume(adev); |
| 885 | if (adev->in_s0ix) | ||
| 886 | amdgpu_gfx_off_ctrl(adev, true); | ||
| 879 | if (r) | 887 | if (r) |
| 880 | return r; | 888 | return r; |
| 881 | r = sdma_v5_2_rlc_resume(adev); | 889 | r = sdma_v5_2_rlc_resume(adev); |
| @@ -1115,6 +1115,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) · 1114 unmodified lines | |||
| 1115 | 1115 | ||
| 1116 | init_data.asic_id.pci_revision_id = adev->pdev->revision; | 1116 | init_data.asic_id.pci_revision_id = adev->pdev->revision; |
| 1117 | init_data.asic_id.hw_internal_rev = adev->external_rev_id; | 1117 | init_data.asic_id.hw_internal_rev = adev->external_rev_id; |
| 1118 | init_data.asic_id.chip_id = adev->pdev->device; | ||
| 1118 | 1119 | ||
| 1119 | init_data.asic_id.vram_width = adev->gmc.vram_width; | 1120 | init_data.asic_id.vram_width = adev->gmc.vram_width; |
| 1120 | /* TODO: initialize init_data.asic_id.vram_type here!!!! */ | 1121 | /* TODO: initialize init_data.asic_id.vram_type here!!!! */ |
| @@ -1719,6 +1720,7 @@ static int dm_late_init(void *handle) · 598 unmodified lines | |||
| 1719 | linear_lut[i] = 0xFFFF * i / 15; | 1720 | linear_lut[i] = 0xFFFF * i / 15; |
| 1720 | 1721 | ||
| 1721 | params.set = 0; | 1722 | params.set = 0; |
| 1723 | params.backlight_ramping_override = false; | ||
| 1722 | params.backlight_ramping_start = 0xCCCC; | 1724 | params.backlight_ramping_start = 0xCCCC; |
| 1723 | params.backlight_ramping_reduction = 0xCCCCCCCC; | 1725 | params.backlight_ramping_reduction = 0xCCCCCCCC; |
| 1724 | params.backlight_lut_array_size = 16; | 1726 | params.backlight_lut_array_size = 16; |
| @@ -1826,14 +1826,13 @@ bool perform_link_training_with_retries( · 1825 unmodified lines | |||
| 1826 | if (panel_mode == DP_PANEL_MODE_EDP) { | 1826 | if (panel_mode == DP_PANEL_MODE_EDP) { |
| 1827 | struct cp_psp *cp_psp = &stream->ctx->cp_psp; | 1827 | struct cp_psp *cp_psp = &stream->ctx->cp_psp; |
| 1828 | 1828 | ||
| 1829 | if (cp_psp && cp_psp->funcs.enable_assr) { | 1829 | if (cp_psp && cp_psp->funcs.enable_assr) |
| 1830 | if (!cp_psp->funcs.enable_assr(cp_psp->handle, link)) { | 1830 | /* ASSR is bound to fail with unsigned PSP |
| 1831 | /* since eDP implies ASSR on, change panel | 1831 | * verstage used during devlopment phase. |
| 1832 | * mode to disable ASSR | 1832 | * Report and continue with eDP panel mode to |
| 1833 | */ | 1833 | * perform eDP link training with right settings |
| 1834 | panel_mode = DP_PANEL_MODE_DEFAULT; | 1834 | */ |
| 1835 | } | 1835 | cp_psp->funcs.enable_assr(cp_psp->handle, link); |
| 1836 | } | ||
| 1837 | } | 1836 | } |
| 1838 | #endif | 1837 | #endif |
| 1839 | 1838 | ||
| @@ -793,7 +793,6 @@ static int exynos5433_decon_probe(struct platform_device *pdev) · 792 unmodified lines | |||
| 793 | { | 793 | { |
| 794 | struct device *dev = &pdev->dev; | 794 | struct device *dev = &pdev->dev; |
| 795 | struct decon_context *ctx; | 795 | struct decon_context *ctx; |
| 796 | struct resource *res; | ||
| 797 | int ret; | 796 | int ret; |
| 798 | int i; | 797 | int i; |
| 799 | 798 | ||
| @@ -818,8 +817,7 @@ static int exynos5433_decon_probe(struct platform_device *pdev) · 18 unmodified lines | |||
| 818 | ctx->clks[i] = clk; | 817 | ctx->clks[i] = clk; |
| 819 | } | 818 | } |
| 820 | 819 | ||
| 821 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 820 | ctx->addr = devm_platform_ioremap_resource(pdev, 0); |
| 822 | ctx->addr = devm_ioremap_resource(dev, res); | ||
| 823 | if (IS_ERR(ctx->addr)) | 821 | if (IS_ERR(ctx->addr)) |
| 824 | return PTR_ERR(ctx->addr); | 822 | return PTR_ERR(ctx->addr); |
| 825 | 823 | ||
| @@ -1738,7 +1738,6 @@ static const struct component_ops exynos_dsi_component_ops = { · 1737 unmodified lines | |||
| 1738 | static int exynos_dsi_probe(struct platform_device *pdev) | 1738 | static int exynos_dsi_probe(struct platform_device *pdev) |
| 1739 | { | 1739 | { |
| 1740 | struct device *dev = &pdev->dev; | 1740 | struct device *dev = &pdev->dev; |
| 1741 | struct resource *res; | ||
| 1742 | struct exynos_dsi *dsi; | 1741 | struct exynos_dsi *dsi; |
| 1743 | int ret, i; | 1742 | int ret, i; |
| 1744 | 1743 | ||
| @@ -1789,8 +1788,7 @@ static int exynos_dsi_probe(struct platform_device *pdev) · 44 unmodified lines | |||
| 1789 | } | 1788 | } |
| 1790 | } | 1789 | } |
| 1791 | 1790 | ||
| 1792 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1791 | dsi->reg_base = devm_platform_ioremap_resource(pdev, 0); |
| 1793 | dsi->reg_base = devm_ioremap_resource(dev, res); | ||
| 1794 | if (IS_ERR(dsi->reg_base)) | 1792 | if (IS_ERR(dsi->reg_base)) |
| 1795 | return PTR_ERR(dsi->reg_base); | 1793 | return PTR_ERR(dsi->reg_base); |
| 1796 | 1794 | ||
| @@ -85,7 +85,6 @@ struct fimc_scaler { · 84 unmodified lines | |||
| 85 | /* | 85 | /* |
| 86 | * A structure of fimc context. | 86 | * A structure of fimc context. |
| 87 | * | 87 | * |
| 88 | * @regs_res: register resources. | ||
| 89 | * @regs: memory mapped io registers. | 88 | * @regs: memory mapped io registers. |
| 90 | * @lock: locking of operations. | 89 | * @lock: locking of operations. |
| 91 | * @clocks: fimc clocks. | 90 | * @clocks: fimc clocks. |
| @@ -103,7 +102,6 @@ struct fimc_context { · 11 unmodified lines | |||
| 103 | struct exynos_drm_ipp_formats *formats; | 102 | struct exynos_drm_ipp_formats *formats; |
| 104 | unsigned int num_formats; | 103 | unsigned int num_formats; |
| 105 | 104 | ||
| 106 | struct resource *regs_res; | ||
| 107 | void __iomem *regs; | 105 | void __iomem *regs; |
| 108 | spinlock_t lock; | 106 | spinlock_t lock; |
| 109 | struct clk *clocks[FIMC_CLKS_MAX]; | 107 | struct clk *clocks[FIMC_CLKS_MAX]; |
| @@ -1327,8 +1325,7 @@ static int fimc_probe(struct platform_device *pdev) · 1217 unmodified lines | |||
| 1327 | ctx->num_formats = num_formats; | 1325 | ctx->num_formats = num_formats; |
| 1328 | 1326 | ||
| 1329 | /* resource memory */ | 1327 | /* resource memory */ |
| 1330 | ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1328 | ctx->regs = devm_platform_ioremap_resource(pdev, 0); |
| 1331 | ctx->regs = devm_ioremap_resource(dev, ctx->regs_res); | ||
| 1332 | if (IS_ERR(ctx->regs)) | 1329 | if (IS_ERR(ctx->regs)) |
| 1333 | return PTR_ERR(ctx->regs); | 1330 | return PTR_ERR(ctx->regs); |
| 1334 | 1331 | ||
| @@ -1202,9 +1202,7 @@ static int fimd_probe(struct platform_device *pdev) · 1201 unmodified lines | |||
| 1202 | return PTR_ERR(ctx->lcd_clk); | 1202 | return PTR_ERR(ctx->lcd_clk); |
| 1203 | } | 1203 | } |
| 1204 | 1204 | ||
| 1205 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1205 | ctx->regs = devm_platform_ioremap_resource(pdev, 0); |
| 1206 | |||
| 1207 | ctx->regs = devm_ioremap_resource(dev, res); | ||
| 1208 | if (IS_ERR(ctx->regs)) | 1206 | if (IS_ERR(ctx->regs)) |
| 1209 | return PTR_ERR(ctx->regs); | 1207 | return PTR_ERR(ctx->regs); |
| 1210 | 1208 | ||
| @@ -1449,7 +1449,6 @@ static const struct component_ops g2d_component_ops = { · 1448 unmodified lines | |||
| 1449 | static int g2d_probe(struct platform_device *pdev) | 1449 | static int g2d_probe(struct platform_device *pdev) |
| 1450 | { | 1450 | { |
| 1451 | struct device *dev = &pdev->dev; | 1451 | struct device *dev = &pdev->dev; |
| 1452 | struct resource *res; | ||
| 1453 | struct g2d_data *g2d; | 1452 | struct g2d_data *g2d; |
| 1454 | int ret; | 1453 | int ret; |
| 1455 | 1454 | ||
| @@ -1491,9 +1490,7 @@ static int g2d_probe(struct platform_device *pdev) · 35 unmodified lines | |||
| 1491 | clear_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); | 1490 | clear_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); |
| 1492 | clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); | 1491 | clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); |
| 1493 | 1492 | ||
| 1494 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1493 | g2d->regs = devm_platform_ioremap_resource(pdev, 0); |
| 1495 | |||
| 1496 | g2d->regs = devm_ioremap_resource(dev, res); | ||
| 1497 | if (IS_ERR(g2d->regs)) { | 1494 | if (IS_ERR(g2d->regs)) { |
| 1498 | ret = PTR_ERR(g2d->regs); | 1495 | ret = PTR_ERR(g2d->regs); |
| 1499 | goto err_put_clk; | 1496 | goto err_put_clk; |
| @@ -86,7 +86,6 @@ struct gsc_scaler { · 85 unmodified lines | |||
| 86 | /* | 86 | /* |
| 87 | * A structure of gsc context. | 87 | * A structure of gsc context. |
| 88 | * | 88 | * |
| 89 | * @regs_res: register resources. | ||
| 90 | * @regs: memory mapped io registers. | 89 | * @regs: memory mapped io registers. |
| 91 | * @gsc_clk: gsc gate clock. | 90 | * @gsc_clk: gsc gate clock. |
| 92 | * @sc: scaler infomations. | 91 | * @sc: scaler infomations. |
| @@ -103,7 +102,6 @@ struct gsc_context { · 10 unmodified lines | |||
| 103 | struct exynos_drm_ipp_formats *formats; | 102 | struct exynos_drm_ipp_formats *formats; |
| 104 | unsigned int num_formats; | 103 | unsigned int num_formats; |
| 105 | 104 | ||
| 106 | struct resource *regs_res; | ||
| 107 | void __iomem *regs; | 105 | void __iomem *regs; |
| 108 | const char **clk_names; | 106 | const char **clk_names; |
| 109 | struct clk *clocks[GSC_MAX_CLOCKS]; | 107 | struct clk *clocks[GSC_MAX_CLOCKS]; |
| @@ -1272,9 +1270,7 @@ static int gsc_probe(struct platform_device *pdev) · 1162 unmodified lines | |||
| 1272 | } | 1270 | } |
| 1273 | } | 1271 | } |
| 1274 | 1272 | ||
| 1275 | /* resource memory */ | 1273 | ctx->regs = devm_platform_ioremap_resource(pdev, 0); |
| 1276 | ctx->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1277 | ctx->regs = devm_ioremap_resource(dev, ctx->regs_res); | ||
| 1278 | if (IS_ERR(ctx->regs)) | 1274 | if (IS_ERR(ctx->regs)) |
| 1279 | return PTR_ERR(ctx->regs); | 1275 | return PTR_ERR(ctx->regs); |
| 1280 | 1276 | ||
| @@ -278,7 +278,6 @@ static const struct component_ops rotator_component_ops = { · 277 unmodified lines | |||
| 278 | static int rotator_probe(struct platform_device *pdev) | 278 | static int rotator_probe(struct platform_device *pdev) |
| 279 | { | 279 | { |
| 280 | struct device *dev = &pdev->dev; | 280 | struct device *dev = &pdev->dev; |
| 281 | struct resource *regs_res; | ||
| 282 | struct rot_context *rot; | 281 | struct rot_context *rot; |
| 283 | const struct rot_variant *variant; | 282 | const struct rot_variant *variant; |
| 284 | int irq; | 283 | int irq; |
| @@ -292,8 +291,7 @@ static int rotator_probe(struct platform_device *pdev) · 7 unmodified lines | |||
| 292 | rot->formats = variant->formats; | 291 | rot->formats = variant->formats; |
| 293 | rot->num_formats = variant->num_formats; | 292 | rot->num_formats = variant->num_formats; |
| 294 | rot->dev = dev; | 293 | rot->dev = dev; |
| 295 | regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 294 | rot->regs = devm_platform_ioremap_resource(pdev, 0); |
| 296 | rot->regs = devm_ioremap_resource(dev, regs_res); | ||
| 297 | if (IS_ERR(rot->regs)) | 295 | if (IS_ERR(rot->regs)) |
| 298 | return PTR_ERR(rot->regs); | 296 | return PTR_ERR(rot->regs); |
| 299 | 297 | ||
| @@ -485,7 +485,6 @@ static const struct component_ops scaler_component_ops = { · 484 unmodified lines | |||
| 485 | static int scaler_probe(struct platform_device *pdev) | 485 | static int scaler_probe(struct platform_device *pdev) |
| 486 | { | 486 | { |
| 487 | struct device *dev = &pdev->dev; | 487 | struct device *dev = &pdev->dev; |
| 488 | struct resource *regs_res; | ||
| 489 | struct scaler_context *scaler; | 488 | struct scaler_context *scaler; |
| 490 | int irq; | 489 | int irq; |
| 491 | int ret, i; | 490 | int ret, i; |
| @@ -498,8 +497,7 @@ static int scaler_probe(struct platform_device *pdev) · 6 unmodified lines | |||
| 498 | (struct scaler_data *)of_device_get_match_data(dev); | 497 | (struct scaler_data *)of_device_get_match_data(dev); |
| 499 | 498 | ||
| 500 | scaler->dev = dev; | 499 | scaler->dev = dev; |
| 501 | regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 500 | scaler->regs = devm_platform_ioremap_resource(pdev, 0); |
| 502 | scaler->regs = devm_ioremap_resource(dev, regs_res); | ||
| 503 | if (IS_ERR(scaler->regs)) | 501 | if (IS_ERR(scaler->regs)) |
| 504 | return PTR_ERR(scaler->regs); | 502 | return PTR_ERR(scaler->regs); |
| 505 | 503 | ||
| @@ -1957,7 +1957,6 @@ static int hdmi_probe(struct platform_device *pdev) · 1956 unmodified lines | |||
| 1957 | struct hdmi_audio_infoframe *audio_infoframe; | 1957 | struct hdmi_audio_infoframe *audio_infoframe; |
| 1958 | struct device *dev = &pdev->dev; | 1958 | struct device *dev = &pdev->dev; |
| 1959 | struct hdmi_context *hdata; | 1959 | struct hdmi_context *hdata; |
| 1960 | struct resource *res; | ||
| 1961 | int ret; | 1960 | int ret; |
| 1962 | 1961 | ||
| 1963 | hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL); | 1962 | hdata = devm_kzalloc(dev, sizeof(struct hdmi_context), GFP_KERNEL); |
| @@ -1979,8 +1978,7 @@ static int hdmi_probe(struct platform_device *pdev) · 15 unmodified lines | |||
| 1979 | return ret; | 1978 | return ret; |
| 1980 | } | 1979 | } |
| 1981 | 1980 | ||
| 1982 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1981 | hdata->regs = devm_platform_ioremap_resource(pdev, 0); |
| 1983 | hdata->regs = devm_ioremap_resource(dev, res); | ||
| 1984 | if (IS_ERR(hdata->regs)) { | 1982 | if (IS_ERR(hdata->regs)) { |
| 1985 | ret = PTR_ERR(hdata->regs); | 1983 | ret = PTR_ERR(hdata->regs); |
| 1986 | return ret; | 1984 | return ret; |
| @@ -362,8 +362,9 @@ static int __intel_context_active(struct i915_active *active) · 361 unmodified lines | |||
| 362 | return 0; | 362 | return 0; |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | static int sw_fence_dummy_notify(struct i915_sw_fence *sf, | 365 | static int __i915_sw_fence_call |
| 366 | enum i915_sw_fence_notify state) | 366 | sw_fence_dummy_notify(struct i915_sw_fence *sf, |
| 367 | enum i915_sw_fence_notify state) | ||
| 367 | { | 368 | { |
| 368 | return NOTIFY_DONE; | 369 | return NOTIFY_DONE; |
| 369 | } | 370 | } |
| @@ -882,8 +882,6 @@ void intel_rps_park(struct intel_rps *rps) · 881 unmodified lines | |||
| 882 | if (!intel_rps_is_enabled(rps)) | 882 | if (!intel_rps_is_enabled(rps)) |
| 883 | return; | 883 | return; |
| 884 | 884 | ||
| 885 | GEM_BUG_ON(atomic_read(&rps->num_waiters)); | ||
| 886 | |||
| 887 | if (!intel_rps_clear_active(rps)) | 885 | if (!intel_rps_clear_active(rps)) |
| 888 | return; | 886 | return; |
| 889 | 887 | ||
| @@ -102,11 +102,11 @@ static_assert(sizeof(struct guc_ct_buffer_desc) == 64); · 101 unmodified lines | |||
| 102 | * | +-------+--------------------------------------------------------------+ | 102 | * | +-------+--------------------------------------------------------------+ |
| 103 | * | | 7:0 | NUM_DWORDS = length (in dwords) of the embedded HXG message | | 103 | * | | 7:0 | NUM_DWORDS = length (in dwords) of the embedded HXG message | |
| 104 | * +---+-------+--------------------------------------------------------------+ | 104 | * +---+-------+--------------------------------------------------------------+ |
| 105 | * | 1 | 31:0 | +--------------------------------------------------------+ | | 105 | * | 1 | 31:0 | | |
| 106 | * +---+-------+ | | | | 106 | * +---+-------+ | |
| 107 | * |...| | | Embedded `HXG Message`_ | | | 107 | * |...| | [Embedded `HXG Message`_] | |
| 108 | * +---+-------+ | | | | 108 | * +---+-------+ | |
| 109 | * | n | 31:0 | +--------------------------------------------------------+ | | 109 | * | n | 31:0 | | |
| 110 | * +---+-------+--------------------------------------------------------------+ | 110 | * +---+-------+--------------------------------------------------------------+ |
| 111 | */ | 111 | */ |
| 112 | 112 | ||
| @@ -38,11 +38,11 @@ · 37 unmodified lines | |||
| 38 | * +---+-------+--------------------------------------------------------------+ | 38 | * +---+-------+--------------------------------------------------------------+ |
| 39 | * | | Bits | Description | | 39 | * | | Bits | Description | |
| 40 | * +===+=======+==============================================================+ | 40 | * +===+=======+==============================================================+ |
| 41 | * | 0 | 31:0 | +--------------------------------------------------------+ | | 41 | * | 0 | 31:0 | | |
| 42 | * +---+-------+ | | | | 42 | * +---+-------+ | |
| 43 | * |...| | | Embedded `HXG Message`_ | | | 43 | * |...| | [Embedded `HXG Message`_] | |
| 44 | * +---+-------+ | | | | 44 | * +---+-------+ | |
| 45 | * | n | 31:0 | +--------------------------------------------------------+ | | 45 | * | n | 31:0 | | |
| 46 | * +---+-------+--------------------------------------------------------------+ | 46 | * +---+-------+--------------------------------------------------------------+ |
| 47 | */ | 47 | */ |
| 48 | 48 | ||
| @@ -576,7 +576,7 @@ retry: · 575 unmodified lines | |||
| 576 | 576 | ||
| 577 | /* No one is going to touch shadow bb from now on. */ | 577 | /* No one is going to touch shadow bb from now on. */ |
| 578 | i915_gem_object_flush_map(bb->obj); | 578 | i915_gem_object_flush_map(bb->obj); |
| 579 | i915_gem_object_unlock(bb->obj); | 579 | i915_gem_ww_ctx_fini(&ww); |
| 580 | } | 580 | } |
| 581 | } | 581 | } |
| 582 | return 0; | 582 | return 0; |
| @@ -630,7 +630,7 @@ retry: · 47 unmodified lines | |||
| 630 | return ret; | 630 | return ret; |
| 631 | } | 631 | } |
| 632 | 632 | ||
| 633 | i915_gem_object_unlock(wa_ctx->indirect_ctx.obj); | 633 | i915_gem_ww_ctx_fini(&ww); |
| 634 | 634 | ||
| 635 | /* FIXME: we are not tracking our pinned VMA leaving it | 635 | /* FIXME: we are not tracking our pinned VMA leaving it |
| 636 | * up to the core to fix up the stray pin_count upon | 636 | * up to the core to fix up the stray pin_count upon |
| @@ -829,8 +829,6 @@ static void __i915_request_ctor(void *arg) · 828 unmodified lines | |||
| 829 | i915_sw_fence_init(&rq->submit, submit_notify); | 829 | i915_sw_fence_init(&rq->submit, submit_notify); |
| 830 | i915_sw_fence_init(&rq->semaphore, semaphore_notify); | 830 | i915_sw_fence_init(&rq->semaphore, semaphore_notify); |
| 831 | 831 | ||
| 832 | dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock, 0, 0); | ||
| 833 | |||
| 834 | rq->capture_list = NULL; | 832 | rq->capture_list = NULL; |
| 835 | 833 | ||
| 836 | init_llist_head(&rq->execute_cb); | 834 | init_llist_head(&rq->execute_cb); |
| @@ -905,17 +903,12 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp) · 68 unmodified lines | |||
| 905 | rq->ring = ce->ring; | 903 | rq->ring = ce->ring; |
| 906 | rq->execution_mask = ce->engine->mask; | 904 | rq->execution_mask = ce->engine->mask; |
| 907 | 905 | ||
| 908 | kref_init(&rq->fence.refcount); | ||
| 909 | rq->fence.flags = 0; | ||
| 910 | rq->fence.error = 0; | ||
| 911 | INIT_LIST_HEAD(&rq->fence.cb_list); | ||
| 912 | |||
| 913 | ret = intel_timeline_get_seqno(tl, rq, &seqno); | 906 | ret = intel_timeline_get_seqno(tl, rq, &seqno); |
| 914 | if (ret) | 907 | if (ret) |
| 915 | goto err_free; | 908 | goto err_free; |
| 916 | 909 | ||
| 917 | rq->fence.context = tl->fence_context; | 910 | dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock, |
| 918 | rq->fence.seqno = seqno; | 911 | tl->fence_context, seqno); |
| 919 | 912 | ||
| 920 | RCU_INIT_POINTER(rq->timeline, tl); | 913 | RCU_INIT_POINTER(rq->timeline, tl); |
| 921 | rq->hwsp_seqno = tl->hwsp_seqno; | 914 | rq->hwsp_seqno = tl->hwsp_seqno; |
| @@ -1845,7 +1845,6 @@ tegra_crtc_update_memory_bandwidth(struct drm_crtc *crtc, · 1844 unmodified lines | |||
| 1845 | bool prepare_bandwidth_transition) | 1845 | bool prepare_bandwidth_transition) |
| 1846 | { | 1846 | { |
| 1847 | const struct tegra_plane_state *old_tegra_state, *new_tegra_state; | 1847 | const struct tegra_plane_state *old_tegra_state, *new_tegra_state; |
| 1848 | const struct tegra_dc_state *old_dc_state, *new_dc_state; | ||
| 1849 | u32 i, new_avg_bw, old_avg_bw, new_peak_bw, old_peak_bw; | 1848 | u32 i, new_avg_bw, old_avg_bw, new_peak_bw, old_peak_bw; |
| 1850 | const struct drm_plane_state *old_plane_state; | 1849 | const struct drm_plane_state *old_plane_state; |
| 1851 | const struct drm_crtc_state *old_crtc_state; | 1850 | const struct drm_crtc_state *old_crtc_state; |
| @@ -1858,8 +1857,6 @@ tegra_crtc_update_memory_bandwidth(struct drm_crtc *crtc, · 6 unmodified lines | |||
| 1858 | return; | 1857 | return; |
| 1859 | 1858 | ||
| 1860 | old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); | 1859 | old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); |
| 1861 | old_dc_state = to_const_dc_state(old_crtc_state); | ||
| 1862 | new_dc_state = to_const_dc_state(crtc->state); | ||
| 1863 | 1860 | ||
| 1864 | if (!crtc->state->active) { | 1861 | if (!crtc->state->active) { |
| 1865 | if (!old_crtc_state->active) | 1862 | if (!old_crtc_state->active) |
| @@ -35,12 +35,6 @@ static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state) · 34 unmodified lines | |||
| 35 | return NULL; | 35 | return NULL; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | static inline const struct tegra_dc_state * | ||
| 39 | to_const_dc_state(const struct drm_crtc_state *state) | ||
| 40 | { | ||
| 41 | return to_dc_state((struct drm_crtc_state *)state); | ||
| 42 | } | ||
| 43 | |||
| 44 | struct tegra_dc_stats { | 38 | struct tegra_dc_stats { |
| 45 | unsigned long frames; | 39 | unsigned long frames; |
| 46 | unsigned long vblank; | 40 | unsigned long vblank; |
| @@ -222,7 +222,7 @@ int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data, struct drm_f · 221 unmodified lines | |||
| 222 | mapping->iova = sg_dma_address(mapping->sgt->sgl); | 222 | mapping->iova = sg_dma_address(mapping->sgt->sgl); |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | mapping->iova_end = mapping->iova + host1x_to_tegra_bo(mapping->bo)->size; | 225 | mapping->iova_end = mapping->iova + host1x_to_tegra_bo(mapping->bo)->gem.size; |
| 226 | 226 | ||
| 227 | err = xa_alloc(&context->mappings, &args->mapping, mapping, XA_LIMIT(1, U32_MAX), | 227 | err = xa_alloc(&context->mappings, &args->mapping, mapping, XA_LIMIT(1, U32_MAX), |
| 228 | GFP_KERNEL); | 228 | GFP_KERNEL); |
| @@ -15,7 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include "intr.h" | 15 | #include "intr.h" |
| 16 | #include "syncpt.h" | 16 | #include "syncpt.h" |
| 17 | 17 | ||
| 18 | DEFINE_SPINLOCK(lock); | 18 | static DEFINE_SPINLOCK(lock); |
| 19 | 19 | ||
| 20 | struct host1x_syncpt_fence { | 20 | struct host1x_syncpt_fence { |
| 21 | struct dma_fence base; | 21 | struct dma_fence base; |
| @@ -152,8 +152,10 @@ struct dma_fence *host1x_fence_create(struct host1x_syncpt *sp, u32 threshold) · 130 unmodified lines | |||
| 152 | return ERR_PTR(-ENOMEM); | 152 | return ERR_PTR(-ENOMEM); |
| 153 | 153 | ||
| 154 | fence->waiter = kzalloc(sizeof(*fence->waiter), GFP_KERNEL); | 154 | fence->waiter = kzalloc(sizeof(*fence->waiter), GFP_KERNEL); |
| 155 | if (!fence->waiter) | 155 | if (!fence->waiter) { |
| 156 | kfree(fence); | ||
| 156 | return ERR_PTR(-ENOMEM); | 157 | return ERR_PTR(-ENOMEM); |
| 158 | } | ||
| 157 | 159 | ||
| 158 | fence->sp = sp; | 160 | fence->sp = sp; |
| 159 | fence->threshold = threshold; | 161 | fence->threshold = threshold; |
| @@ -255,13 +255,13 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i · 254 unmodified lines | |||
| 255 | if (!privdata->cl_data) | 255 | if (!privdata->cl_data) |
| 256 | return -ENOMEM; | 256 | return -ENOMEM; |
| 257 | 257 | ||
| 258 | rc = devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata); | 258 | mp2_select_ops(privdata); |
| 259 | |||
| 260 | rc = amd_sfh_hid_client_init(privdata); | ||
| 259 | if (rc) | 261 | if (rc) |
| 260 | return rc; | 262 | return rc; |
| 261 | 263 | ||
| 262 | mp2_select_ops(privdata); | 264 | return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata); |
| 263 | |||
| 264 | return amd_sfh_hid_client_init(privdata); | ||
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | static int __maybe_unused amd_mp2_pci_resume(struct device *dev) | 267 | static int __maybe_unused amd_mp2_pci_resume(struct device *dev) |
| @@ -336,12 +336,19 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field, · 335 unmodified lines | |||
| 336 | 336 | ||
| 337 | /* | 337 | /* |
| 338 | * MacBook JIS keyboard has wrong logical maximum | 338 | * MacBook JIS keyboard has wrong logical maximum |
| 339 | * Magic Keyboard JIS has wrong logical maximum | ||
| 339 | */ | 340 | */ |
| 340 | static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 341 | static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 341 | unsigned int *rsize) | 342 | unsigned int *rsize) |
| 342 | { | 343 | { |
| 343 | struct apple_sc *asc = hid_get_drvdata(hdev); | 344 | struct apple_sc *asc = hid_get_drvdata(hdev); |
| 344 | 345 | ||
| 346 | if(*rsize >=71 && rdesc[70] == 0x65 && rdesc[64] == 0x65) { | ||
| 347 | hid_info(hdev, | ||
| 348 | "fixing up Magic Keyboard JIS report descriptor\n"); | ||
| 349 | rdesc[64] = rdesc[70] = 0xe7; | ||
| 350 | } | ||
| 351 | |||
| 345 | if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 && | 352 | if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 && |
| 346 | rdesc[53] == 0x65 && rdesc[59] == 0x65) { | 353 | rdesc[53] == 0x65 && rdesc[59] == 0x65) { |
| 347 | hid_info(hdev, | 354 | hid_info(hdev, |
| @@ -56,15 +56,22 @@ static int betopff_init(struct hid_device *hid) · 55 unmodified lines | |||
| 56 | { | 56 | { |
| 57 | struct betopff_device *betopff; | 57 | struct betopff_device *betopff; |
| 58 | struct hid_report *report; | 58 | struct hid_report *report; |
| 59 | struct hid_input *hidinput = | 59 | struct hid_input *hidinput; |
| 60 | list_first_entry(&hid->inputs, struct hid_input, list); | ||
| 61 | struct list_head *report_list = | 60 | struct list_head *report_list = |
| 62 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | 61 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; |
| 63 | struct input_dev *dev = hidinput->input; | 62 | struct input_dev *dev; |
| 64 | int field_count = 0; | 63 | int field_count = 0; |
| 65 | int error; | 64 | int error; |
| 66 | int i, j; | 65 | int i, j; |
| 67 | 66 | ||
| 67 | if (list_empty(&hid->inputs)) { | ||
| 68 | hid_err(hid, "no inputs found\n"); | ||
| 69 | return -ENODEV; | ||
| 70 | } | ||
| 71 | |||
| 72 | hidinput = list_first_entry(&hid->inputs, struct hid_input, list); | ||
| 73 | dev = hidinput->input; | ||
| 74 | |||
| 68 | if (list_empty(report_list)) { | 75 | if (list_empty(report_list)) { |
| 69 | hid_err(hid, "no output reports found\n"); | 76 | hid_err(hid, "no output reports found\n"); |
| 70 | return -ENODEV; | 77 | return -ENODEV; |
| @@ -198,7 +198,9 @@ static int u2fzero_rng_read(struct hwrng *rng, void *data, · 197 unmodified lines | |||
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | ret = u2fzero_recv(dev, &req, &resp); | 200 | ret = u2fzero_recv(dev, &req, &resp); |
| 201 | if (ret < 0) | 201 | |
| 202 | /* ignore errors or packets without data */ | ||
| 203 | if (ret < offsetof(struct u2f_hid_msg, init.data)) | ||
| 202 | return 0; | 204 | return 0; |
| 203 | 205 | ||
| 204 | /* only take the minimum amount of data it is safe to take */ | 206 | /* only take the minimum amount of data it is safe to take */ |
| @@ -4746,6 +4746,12 @@ static const struct wacom_features wacom_features_0x393 = · 4745 unmodified lines | |||
| 4746 | { "Wacom Intuos Pro S", 31920, 19950, 8191, 63, | 4746 | { "Wacom Intuos Pro S", 31920, 19950, 8191, 63, |
| 4747 | INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, | 4747 | INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, |
| 4748 | .touch_max = 10 }; | 4748 | .touch_max = 10 }; |
| 4749 | static const struct wacom_features wacom_features_0x3c6 = | ||
| 4750 | { "Wacom Intuos BT S", 15200, 9500, 4095, 63, | ||
| 4751 | INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 }; | ||
| 4752 | static const struct wacom_features wacom_features_0x3c8 = | ||
| 4753 | { "Wacom Intuos BT M", 21600, 13500, 4095, 63, | ||
| 4754 | INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 }; | ||
| 4749 | 4755 | ||
| 4750 | static const struct wacom_features wacom_features_HID_ANY_ID = | 4756 | static const struct wacom_features wacom_features_HID_ANY_ID = |
| 4751 | { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; | 4757 | { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; |
| @@ -4919,6 +4925,8 @@ const struct hid_device_id wacom_ids[] = { · 167 unmodified lines | |||
| 4919 | { USB_DEVICE_WACOM(0x37A) }, | 4925 | { USB_DEVICE_WACOM(0x37A) }, |
| 4920 | { USB_DEVICE_WACOM(0x37B) }, | 4926 | { USB_DEVICE_WACOM(0x37B) }, |
| 4921 | { BT_DEVICE_WACOM(0x393) }, | 4927 | { BT_DEVICE_WACOM(0x393) }, |
| 4928 | { BT_DEVICE_WACOM(0x3c6) }, | ||
| 4929 | { BT_DEVICE_WACOM(0x3c8) }, | ||
| 4922 | { USB_DEVICE_WACOM(0x4001) }, | 4930 | { USB_DEVICE_WACOM(0x4001) }, |
| 4923 | { USB_DEVICE_WACOM(0x4004) }, | 4931 | { USB_DEVICE_WACOM(0x4004) }, |
| 4924 | { USB_DEVICE_WACOM(0x5000) }, | 4932 | { USB_DEVICE_WACOM(0x5000) }, |
| @@ -362,12 +362,6 @@ static const struct hwmon_channel_info *k10temp_info[] = { · 361 unmodified lines | |||
| 362 | HWMON_T_INPUT | HWMON_T_LABEL, | 362 | HWMON_T_INPUT | HWMON_T_LABEL, |
| 363 | HWMON_T_INPUT | HWMON_T_LABEL, | 363 | HWMON_T_INPUT | HWMON_T_LABEL, |
| 364 | HWMON_T_INPUT | HWMON_T_LABEL), | 364 | HWMON_T_INPUT | HWMON_T_LABEL), |
| 365 | HWMON_CHANNEL_INFO(in, | ||
| 366 | HWMON_I_INPUT | HWMON_I_LABEL, | ||
| 367 | HWMON_I_INPUT | HWMON_I_LABEL), | ||
| 368 | HWMON_CHANNEL_INFO(curr, | ||
| 369 | HWMON_C_INPUT | HWMON_C_LABEL, | ||
| 370 | HWMON_C_INPUT | HWMON_C_LABEL), | ||
| 371 | NULL | 365 | NULL |
| 372 | }; | 366 | }; |
| 373 | 367 | ||
| @@ -989,8 +989,12 @@ static int ltc2947_setup(struct ltc2947_data *st) · 988 unmodified lines | |||
| 989 | return ret; | 989 | return ret; |
| 990 | 990 | ||
| 991 | /* check external clock presence */ | 991 | /* check external clock presence */ |
| 992 | extclk = devm_clk_get(st->dev, NULL); | 992 | extclk = devm_clk_get_optional(st->dev, NULL); |
| 993 | if (!IS_ERR(extclk)) { | 993 | if (IS_ERR(extclk)) |
| 994 | return dev_err_probe(st->dev, PTR_ERR(extclk), | ||
| 995 | "Failed to get external clock\n"); | ||
| 996 | |||
| 997 | if (extclk) { | ||
| 994 | unsigned long rate_hz; | 998 | unsigned long rate_hz; |
| 995 | u8 pre = 0, div, tbctl; | 999 | u8 pre = 0, div, tbctl; |
| 996 | u64 aux; | 1000 | u64 aux; |
| @@ -315,8 +315,8 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, · 314 unmodified lines | |||
| 315 | { | 315 | { |
| 316 | struct mlxreg_fan *fan = cdev->devdata; | 316 | struct mlxreg_fan *fan = cdev->devdata; |
| 317 | unsigned long cur_state; | 317 | unsigned long cur_state; |
| 318 | int i, config = 0; | ||
| 318 | u32 regval; | 319 | u32 regval; |
| 319 | int i; | ||
| 320 | int err; | 320 | int err; |
| 321 | 321 | ||
| 322 | /* | 322 | /* |
| @@ -329,6 +329,12 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, · 6 unmodified lines | |||
| 329 | * overwritten. | 329 | * overwritten. |
| 330 | */ | 330 | */ |
| 331 | if (state >= MLXREG_FAN_SPEED_MIN && state <= MLXREG_FAN_SPEED_MAX) { | 331 | if (state >= MLXREG_FAN_SPEED_MIN && state <= MLXREG_FAN_SPEED_MAX) { |
| 332 | /* | ||
| 333 | * This is configuration change, which is only supported through sysfs. | ||
| 334 | * For configuration non-zero value is to be returned to avoid thermal | ||
| 335 | * statistics update. | ||
| 336 | */ | ||
| 337 | config = 1; | ||
| 332 | state -= MLXREG_FAN_MAX_STATE; | 338 | state -= MLXREG_FAN_MAX_STATE; |
| 333 | for (i = 0; i < state; i++) | 339 | for (i = 0; i < state; i++) |
| 334 | fan->cooling_levels[i] = state; | 340 | fan->cooling_levels[i] = state; |
| @@ -343,7 +349,7 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, · 8 unmodified lines | |||
| 343 | 349 | ||
| 344 | cur_state = MLXREG_FAN_PWM_DUTY2STATE(regval); | 350 | cur_state = MLXREG_FAN_PWM_DUTY2STATE(regval); |
| 345 | if (state < cur_state) | 351 | if (state < cur_state) |
| 346 | return 0; | 352 | return config; |
| 347 | 353 | ||
| 348 | state = cur_state; | 354 | state = cur_state; |
| 349 | } | 355 | } |
| @@ -359,7 +365,7 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, · 9 unmodified lines | |||
| 359 | dev_err(fan->dev, "Failed to write PWM duty\n"); | 365 | dev_err(fan->dev, "Failed to write PWM duty\n"); |
| 360 | return err; | 366 | return err; |
| 361 | } | 367 | } |
| 362 | return 0; | 368 | return config; |
| 363 | } | 369 | } |
| 364 | 370 | ||
| 365 | static const struct thermal_cooling_device_ops mlxreg_fan_cooling_ops = { | 371 | static const struct thermal_cooling_device_ops mlxreg_fan_cooling_ops = { |
| @@ -340,18 +340,11 @@ static ssize_t occ_show_temp_10(struct device *dev, · 339 unmodified lines | |||
| 340 | if (val == OCC_TEMP_SENSOR_FAULT) | 340 | if (val == OCC_TEMP_SENSOR_FAULT) |
| 341 | return -EREMOTEIO; | 341 | return -EREMOTEIO; |
| 342 | 342 | ||
| 343 | /* | 343 | /* sensor not ready */ |
| 344 | * VRM doesn't return temperature, only alarm bit. This | 344 | if (val == 0) |
| 345 | * attribute maps to tempX_alarm instead of tempX_input for | 345 | return -EAGAIN; |
| 346 | * VRM | ||
| 347 | */ | ||
| 348 | if (temp->fru_type != OCC_FRU_TYPE_VRM) { | ||
| 349 | /* sensor not ready */ | ||
| 350 | if (val == 0) | ||
| 351 | return -EAGAIN; | ||
| 352 | 346 | ||
| 353 | val *= 1000; | 347 | val *= 1000; |
| 354 | } | ||
| 355 | break; | 348 | break; |
| 356 | case 2: | 349 | case 2: |
| 357 | val = temp->fru_type; | 350 | val = temp->fru_type; |
| @@ -886,7 +879,7 @@ static int occ_setup_sensor_attrs(struct occ *occ) · 528 unmodified lines | |||
| 886 | 0, i); | 879 | 0, i); |
| 887 | attr++; | 880 | attr++; |
| 888 | 881 | ||
| 889 | if (sensors->temp.version > 1 && | 882 | if (sensors->temp.version == 2 && |
| 890 | temp->fru_type == OCC_FRU_TYPE_VRM) { | 883 | temp->fru_type == OCC_FRU_TYPE_VRM) { |
| 891 | snprintf(attr->name, sizeof(attr->name), | 884 | snprintf(attr->name, sizeof(attr->name), |
| 892 | "temp%d_alarm", s); | 885 | "temp%d_alarm", s); |
| @@ -171,8 +171,14 @@ static ssize_t ibm_cffps_debugfs_read(struct file *file, char __user *buf, · 170 unmodified lines | |||
| 171 | cmd = CFFPS_SN_CMD; | 171 | cmd = CFFPS_SN_CMD; |
| 172 | break; | 172 | break; |
| 173 | case CFFPS_DEBUGFS_MAX_POWER_OUT: | 173 | case CFFPS_DEBUGFS_MAX_POWER_OUT: |
| 174 | rc = i2c_smbus_read_word_swapped(psu->client, | 174 | if (psu->version == cffps1) { |
| 175 | CFFPS_MAX_POWER_OUT_CMD); | 175 | rc = i2c_smbus_read_word_swapped(psu->client, |
| 176 | CFFPS_MAX_POWER_OUT_CMD); | ||
| 177 | } else { | ||
| 178 | rc = i2c_smbus_read_word_data(psu->client, | ||
| 179 | CFFPS_MAX_POWER_OUT_CMD); | ||
| 180 | } | ||
| 181 | |||
| 176 | if (rc < 0) | 182 | if (rc < 0) |
| 177 | return rc; | 183 | return rc; |
| 178 | 184 | ||
| @@ -54,7 +54,7 @@ · 53 unmodified lines | |||
| 54 | 54 | ||
| 55 | #define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \ | 55 | #define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \ |
| 56 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \ | 56 | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \ |
| 57 | PMBUS_PHASE_VIRTUAL) | 57 | PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL) |
| 58 | 58 | ||
| 59 | struct mp2975_data { | 59 | struct mp2975_data { |
| 60 | struct pmbus_driver_info info; | 60 | struct pmbus_driver_info info; |
| @@ -100,71 +100,81 @@ struct tmp421_data { · 99 unmodified lines | |||
| 100 | s16 temp[4]; | 100 | s16 temp[4]; |
| 101 | }; | 101 | }; |
| 102 | 102 | ||
| 103 | static int temp_from_s16(s16 reg) | 103 | static int temp_from_raw(u16 reg, bool extended) |
| 104 | { | 104 | { |
| 105 | /* Mask out status bits */ | 105 | /* Mask out status bits */ |
| 106 | int temp = reg & ~0xf; | 106 | int temp = reg & ~0xf; |
| 107 | 107 | ||
| 108 | return (temp * 1000 + 128) / 256; | 108 | if (extended) |
| 109 | } | 109 | temp = temp - 64 * 256; |
| 110 | 110 | else | |
| 111 | static int temp_from_u16(u16 reg) | 111 | temp = (s16)temp; |
| 112 | { | ||
| 113 | /* Mask out status bits */ | ||
| 114 | int temp = reg & ~0xf; | ||
| 115 | |||
| 116 | /* Add offset for extended temperature range. */ | ||
| 117 | temp -= 64 * 256; | ||
| 118 | 112 | ||
| 119 | return (temp * 1000 + 128) / 256; | 113 | return DIV_ROUND_CLOSEST(temp * 1000, 256); |
| 120 | } | 114 | } |
| 121 | 115 | ||
| 122 | static struct tmp421_data *tmp421_update_device(struct device *dev) | 116 | static int tmp421_update_device(struct tmp421_data *data) |
| 123 | { | 117 | { |
| 124 | struct tmp421_data *data = dev_get_drvdata(dev); | ||
| 125 | struct i2c_client *client = data->client; | 118 | struct i2c_client *client = data->client; |
| 119 | int ret = 0; | ||
| 126 | int i; | 120 | int i; |
| 127 | 121 | ||
| 128 | mutex_lock(&data->update_lock); | 122 | mutex_lock(&data->update_lock); |
| 129 | 123 | ||
| 130 | if (time_after(jiffies, data->last_updated + (HZ / 2)) || | 124 | if (time_after(jiffies, data->last_updated + (HZ / 2)) || |
| 131 | !data->valid) { | 125 | !data->valid) { |
| 132 | data->config = i2c_smbus_read_byte_data(client, | 126 | ret = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1); |
| 133 | TMP421_CONFIG_REG_1); | 127 | if (ret < 0) |
| 128 | goto exit; | ||
| 129 | data->config = ret; | ||
| 134 | 130 | ||
| 135 | for (i = 0; i < data->channels; i++) { | 131 | for (i = 0; i < data->channels; i++) { |
| 136 | data->temp[i] = i2c_smbus_read_byte_data(client, | 132 | ret = i2c_smbus_read_byte_data(client, TMP421_TEMP_MSB[i]); |
| 137 | TMP421_TEMP_MSB[i]) << 8; | 133 | if (ret < 0) |
| 138 | data->temp[i] |= i2c_smbus_read_byte_data(client, | 134 | goto exit; |
| 139 | TMP421_TEMP_LSB[i]); | 135 | data->temp[i] = ret << 8; |
| 136 | |||
| 137 | ret = i2c_smbus_read_byte_data(client, TMP421_TEMP_LSB[i]); | ||
| 138 | if (ret < 0) | ||
| 139 | goto exit; | ||
| 140 | data->temp[i] |= ret; | ||
| 140 | } | 141 | } |
| 141 | data->last_updated = jiffies; | 142 | data->last_updated = jiffies; |
| 142 | data->valid = 1; | 143 | data->valid = 1; |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 146 | exit: | ||
| 145 | mutex_unlock(&data->update_lock); | 147 | mutex_unlock(&data->update_lock); |
| 146 | 148 | ||
| 147 | return data; | 149 | if (ret < 0) { |
| 150 | data->valid = 0; | ||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | return 0; | ||
| 148 | } | 155 | } |
| 149 | 156 | ||
| 150 | static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, | 157 | static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, |
| 151 | u32 attr, int channel, long *val) | 158 | u32 attr, int channel, long *val) |
| 152 | { | 159 | { |
| 153 | struct tmp421_data *tmp421 = tmp421_update_device(dev); | 160 | struct tmp421_data *tmp421 = dev_get_drvdata(dev); |
| 161 | int ret = 0; | ||
| 162 | |||
| 163 | ret = tmp421_update_device(tmp421); | ||
| 164 | if (ret) | ||
| 165 | return ret; | ||
| 154 | 166 | ||
| 155 | switch (attr) { | 167 | switch (attr) { |
| 156 | case hwmon_temp_input: | 168 | case hwmon_temp_input: |
| 157 | if (tmp421->config & TMP421_CONFIG_RANGE) | 169 | *val = temp_from_raw(tmp421->temp[channel], |
| 158 | *val = temp_from_u16(tmp421->temp[channel]); | 170 | tmp421->config & TMP421_CONFIG_RANGE); |
| 159 | else | ||
| 160 | *val = temp_from_s16(tmp421->temp[channel]); | ||
| 161 | return 0; | 171 | return 0; |
| 162 | case hwmon_temp_fault: | 172 | case hwmon_temp_fault: |
| 163 | /* | 173 | /* |
| 164 | * The OPEN bit signals a fault. This is bit 0 of the temperature | 174 | * Any of OPEN or /PVLD bits indicate a hardware mulfunction |
| 165 | * register (low byte). | 175 | * and the conversion result may be incorrect |
| 166 | */ | 176 | */ |
| 167 | *val = tmp421->temp[channel] & 0x01; | 177 | *val = !!(tmp421->temp[channel] & 0x03); |
| 168 | return 0; | 178 | return 0; |
| 169 | default: | 179 | default: |
| 170 | return -EOPNOTSUPP; | 180 | return -EOPNOTSUPP; |
| @@ -177,9 +187,6 @@ static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type, · 6 unmodified lines | |||
| 177 | { | 187 | { |
| 178 | switch (attr) { | 188 | switch (attr) { |
| 179 | case hwmon_temp_fault: | 189 | case hwmon_temp_fault: |
| 180 | if (channel == 0) | ||
| 181 | return 0; | ||
| 182 | return 0444; | ||
| 183 | case hwmon_temp_input: | 190 | case hwmon_temp_input: |
| 184 | return 0444; | 191 | return 0444; |
| 185 | default: | 192 | default: |
| @@ -273,9 +273,6 @@ struct w83791d_data { · 272 unmodified lines | |||
| 273 | char valid; /* !=0 if following fields are valid */ | 273 | char valid; /* !=0 if following fields are valid */ |
| 274 | unsigned long last_updated; /* In jiffies */ | 274 | unsigned long last_updated; /* In jiffies */ |
| 275 | 275 | ||
| 276 | /* array of 2 pointers to subclients */ | ||
| 277 | struct i2c_client *lm75[2]; | ||
| 278 | |||
| 279 | /* volts */ | 276 | /* volts */ |
| 280 | u8 in[NUMBER_OF_VIN]; /* Register value */ | 277 | u8 in[NUMBER_OF_VIN]; /* Register value */ |
| 281 | u8 in_max[NUMBER_OF_VIN]; /* Register value */ | 278 | u8 in_max[NUMBER_OF_VIN]; /* Register value */ |
| @@ -1257,7 +1254,6 @@ static const struct attribute_group w83791d_group_fanpwm45 = { · 975 unmodified lines | |||
| 1257 | static int w83791d_detect_subclients(struct i2c_client *client) | 1254 | static int w83791d_detect_subclients(struct i2c_client *client) |
| 1258 | { | 1255 | { |
| 1259 | struct i2c_adapter *adapter = client->adapter; | 1256 | struct i2c_adapter *adapter = client->adapter; |
| 1260 | struct w83791d_data *data = i2c_get_clientdata(client); | ||
| 1261 | int address = client->addr; | 1257 | int address = client->addr; |
| 1262 | int i, id; | 1258 | int i, id; |
| 1263 | u8 val; | 1259 | u8 val; |
| @@ -1280,22 +1276,19 @@ static int w83791d_detect_subclients(struct i2c_client *client) · 16 unmodified lines | |||
| 1280 | } | 1276 | } |
| 1281 | 1277 | ||
| 1282 | val = w83791d_read(client, W83791D_REG_I2C_SUBADDR); | 1278 | val = w83791d_read(client, W83791D_REG_I2C_SUBADDR); |
| 1283 | if (!(val & 0x08)) | 1279 | |
| 1284 | data->lm75[0] = devm_i2c_new_dummy_device(&client->dev, adapter, | 1280 | if (!(val & 0x88) && (val & 0x7) == ((val >> 4) & 0x7)) { |
| 1285 | 0x48 + (val & 0x7)); | 1281 | dev_err(&client->dev, |
| 1286 | if (!(val & 0x80)) { | 1282 | "duplicate addresses 0x%x, use force_subclient\n", 0x48 + (val & 0x7)); |
| 1287 | if (!IS_ERR(data->lm75[0]) && | 1283 | return -ENODEV; |
| 1288 | ((val & 0x7) == ((val >> 4) & 0x7))) { | ||
| 1289 | dev_err(&client->dev, | ||
| 1290 | "duplicate addresses 0x%x, " | ||
| 1291 | "use force_subclient\n", | ||
| 1292 | data->lm75[0]->addr); | ||
| 1293 | return -ENODEV; | ||
| 1294 | } | ||
| 1295 | data->lm75[1] = devm_i2c_new_dummy_device(&client->dev, adapter, | ||
| 1296 | 0x48 + ((val >> 4) & 0x7)); | ||
| 1297 | } | 1284 | } |
| 1298 | 1285 | ||
| 1286 | if (!(val & 0x08)) | ||
| 1287 | devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + (val & 0x7)); | ||
| 1288 | |||
| 1289 | if (!(val & 0x80)) | ||
| 1290 | devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + ((val >> 4) & 0x7)); | ||
| 1291 | |||
| 1299 | return 0; | 1292 | return 0; |
| 1300 | } | 1293 | } |
| 1301 | 1294 | ||
| @@ -264,9 +264,6 @@ struct w83792d_data { · 263 unmodified lines | |||
| 264 | char valid; /* !=0 if following fields are valid */ | 264 | char valid; /* !=0 if following fields are valid */ |
| 265 | unsigned long last_updated; /* In jiffies */ | 265 | unsigned long last_updated; /* In jiffies */ |
| 266 | 266 | ||
| 267 | /* array of 2 pointers to subclients */ | ||
| 268 | struct i2c_client *lm75[2]; | ||
| 269 | |||
| 270 | u8 in[9]; /* Register value */ | 267 | u8 in[9]; /* Register value */ |
| 271 | u8 in_max[9]; /* Register value */ | 268 | u8 in_max[9]; /* Register value */ |
| 272 | u8 in_min[9]; /* Register value */ | 269 | u8 in_min[9]; /* Register value */ |
| @@ -927,7 +924,6 @@ w83792d_detect_subclients(struct i2c_client *new_client) · 654 unmodified lines | |||
| 927 | int address = new_client->addr; | 924 | int address = new_client->addr; |
| 928 | u8 val; | 925 | u8 val; |
| 929 | struct i2c_adapter *adapter = new_client->adapter; | 926 | struct i2c_adapter *adapter = new_client->adapter; |
| 930 | struct w83792d_data *data = i2c_get_clientdata(new_client); | ||
| 931 | 927 | ||
| 932 | id = i2c_adapter_id(adapter); | 928 | id = i2c_adapter_id(adapter); |
| 933 | if (force_subclients[0] == id && force_subclients[1] == address) { | 929 | if (force_subclients[0] == id && force_subclients[1] == address) { |
| @@ -946,21 +942,19 @@ w83792d_detect_subclients(struct i2c_client *new_client) · 12 unmodified lines | |||
| 946 | } | 942 | } |
| 947 | 943 | ||
| 948 | val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); | 944 | val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); |
| 949 | if (!(val & 0x08)) | 945 | |
| 950 | data->lm75[0] = devm_i2c_new_dummy_device(&new_client->dev, adapter, | 946 | if (!(val & 0x88) && (val & 0x7) == ((val >> 4) & 0x7)) { |
| 951 | 0x48 + (val & 0x7)); | 947 | dev_err(&new_client->dev, |
| 952 | if (!(val & 0x80)) { | 948 | "duplicate addresses 0x%x, use force_subclient\n", 0x48 + (val & 0x7)); |
| 953 | if (!IS_ERR(data->lm75[0]) && | 949 | return -ENODEV; |
| 954 | ((val & 0x7) == ((val >> 4) & 0x7))) { | ||
| 955 | dev_err(&new_client->dev, | ||
| 956 | "duplicate addresses 0x%x, use force_subclient\n", | ||
| 957 | data->lm75[0]->addr); | ||
| 958 | return -ENODEV; | ||
| 959 | } | ||
| 960 | data->lm75[1] = devm_i2c_new_dummy_device(&new_client->dev, adapter, | ||
| 961 | 0x48 + ((val >> 4) & 0x7)); | ||
| 962 | } | 950 | } |
| 963 | 951 | ||
| 952 | if (!(val & 0x08)) | ||
| 953 | devm_i2c_new_dummy_device(&new_client->dev, adapter, 0x48 + (val & 0x7)); | ||
| 954 | |||
| 955 | if (!(val & 0x80)) | ||
| 956 | devm_i2c_new_dummy_device(&new_client->dev, adapter, 0x48 + ((val >> 4) & 0x7)); | ||
| 957 | |||
| 964 | return 0; | 958 | return 0; |
| 965 | } | 959 | } |
| 966 | 960 | ||
| @@ -202,7 +202,6 @@ static inline s8 TEMP_TO_REG(long val, s8 min, s8 max) · 201 unmodified lines | |||
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | struct w83793_data { | 204 | struct w83793_data { |
| 205 | struct i2c_client *lm75[2]; | ||
| 206 | struct device *hwmon_dev; | 205 | struct device *hwmon_dev; |
| 207 | struct mutex update_lock; | 206 | struct mutex update_lock; |
| 208 | char valid; /* !=0 if following fields are valid */ | 207 | char valid; /* !=0 if following fields are valid */ |
| @@ -1566,7 +1565,6 @@ w83793_detect_subclients(struct i2c_client *client) · 1357 unmodified lines | |||
| 1566 | int address = client->addr; | 1565 | int address = client->addr; |
| 1567 | u8 tmp; | 1566 | u8 tmp; |
| 1568 | struct i2c_adapter *adapter = client->adapter; | 1567 | struct i2c_adapter *adapter = client->adapter; |
| 1569 | struct w83793_data *data = i2c_get_clientdata(client); | ||
| 1570 | 1568 | ||
| 1571 | id = i2c_adapter_id(adapter); | 1569 | id = i2c_adapter_id(adapter); |
| 1572 | if (force_subclients[0] == id && force_subclients[1] == address) { | 1570 | if (force_subclients[0] == id && force_subclients[1] == address) { |
| @@ -1586,21 +1584,19 @@ w83793_detect_subclients(struct i2c_client *client) · 13 unmodified lines | |||
| 1586 | } | 1584 | } |
| 1587 | 1585 | ||
| 1588 | tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR); | 1586 | tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR); |
| 1589 | if (!(tmp & 0x08)) | 1587 | |
| 1590 | data->lm75[0] = devm_i2c_new_dummy_device(&client->dev, adapter, | 1588 | if (!(tmp & 0x88) && (tmp & 0x7) == ((tmp >> 4) & 0x7)) { |
| 1591 | 0x48 + (tmp & 0x7)); | 1589 | dev_err(&client->dev, |
| 1592 | if (!(tmp & 0x80)) { | 1590 | "duplicate addresses 0x%x, use force_subclient\n", 0x48 + (tmp & 0x7)); |
| 1593 | if (!IS_ERR(data->lm75[0]) | 1591 | return -ENODEV; |
| 1594 | && ((tmp & 0x7) == ((tmp >> 4) & 0x7))) { | ||
| 1595 | dev_err(&client->dev, | ||
| 1596 | "duplicate addresses 0x%x, " | ||
| 1597 | "use force_subclients\n", data->lm75[0]->addr); | ||
| 1598 | return -ENODEV; | ||
| 1599 | } | ||
| 1600 | data->lm75[1] = devm_i2c_new_dummy_device(&client->dev, adapter, | ||
| 1601 | 0x48 + ((tmp >> 4) & 0x7)); | ||
| 1602 | } | 1592 | } |
| 1603 | 1593 | ||
| 1594 | if (!(tmp & 0x08)) | ||
| 1595 | devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + (tmp & 0x7)); | ||
| 1596 | |||
| 1597 | if (!(tmp & 0x80)) | ||
| 1598 | devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + ((tmp >> 4) & 0x7)); | ||
| 1599 | |||
| 1604 | return 0; | 1600 | return 0; |
| 1605 | } | 1601 | } |
| 1606 | 1602 | ||
| @@ -1746,15 +1746,16 @@ static void cma_cancel_route(struct rdma_id_private *id_priv) · 1745 unmodified lines | |||
| 1746 | } | 1746 | } |
| 1747 | } | 1747 | } |
| 1748 | 1748 | ||
| 1749 | static void cma_cancel_listens(struct rdma_id_private *id_priv) | 1749 | static void _cma_cancel_listens(struct rdma_id_private *id_priv) |
| 1750 | { | 1750 | { |
| 1751 | struct rdma_id_private *dev_id_priv; | 1751 | struct rdma_id_private *dev_id_priv; |
| 1752 | 1752 | ||
| 1753 | lockdep_assert_held(&lock); | ||
| 1754 | |||
| 1753 | /* | 1755 | /* |
| 1754 | * Remove from listen_any_list to prevent added devices from spawning | 1756 | * Remove from listen_any_list to prevent added devices from spawning |
| 1755 | * additional listen requests. | 1757 | * additional listen requests. |
| 1756 | */ | 1758 | */ |
| 1757 | mutex_lock(&lock); | ||
| 1758 | list_del(&id_priv->list); | 1759 | list_del(&id_priv->list); |
| 1759 | 1760 | ||
| 1760 | while (!list_empty(&id_priv->listen_list)) { | 1761 | while (!list_empty(&id_priv->listen_list)) { |
| @@ -1768,6 +1769,12 @@ static void cma_cancel_listens(struct rdma_id_private *id_priv) · 7 unmodified lines | |||
| 1768 | rdma_destroy_id(&dev_id_priv->id); | 1769 | rdma_destroy_id(&dev_id_priv->id); |
| 1769 | mutex_lock(&lock); | 1770 | mutex_lock(&lock); |
| 1770 | } | 1771 | } |
| 1772 | } | ||
| 1773 | |||
| 1774 | static void cma_cancel_listens(struct rdma_id_private *id_priv) | ||
| 1775 | { | ||
| 1776 | mutex_lock(&lock); | ||
| 1777 | _cma_cancel_listens(id_priv); | ||
| 1771 | mutex_unlock(&lock); | 1778 | mutex_unlock(&lock); |
| 1772 | } | 1779 | } |
| 1773 | 1780 | ||
| @@ -1776,6 +1783,14 @@ static void cma_cancel_operation(struct rdma_id_private *id_priv, · 2 unmodified lines | |||
| 1776 | { | 1783 | { |
| 1777 | switch (state) { | 1784 | switch (state) { |
| 1778 | case RDMA_CM_ADDR_QUERY: | 1785 | case RDMA_CM_ADDR_QUERY: |
| 1786 | /* | ||
| 1787 | * We can avoid doing the rdma_addr_cancel() based on state, | ||
| 1788 | * only RDMA_CM_ADDR_QUERY has a work that could still execute. | ||
| 1789 | * Notice that the addr_handler work could still be exiting | ||
| 1790 | * outside this state, however due to the interaction with the | ||
| 1791 | * handler_mutex the work is guaranteed not to touch id_priv | ||
| 1792 | * during exit. | ||
| 1793 | */ | ||
| 1779 | rdma_addr_cancel(&id_priv->id.route.addr.dev_addr); | 1794 | rdma_addr_cancel(&id_priv->id.route.addr.dev_addr); |
| 1780 | break; | 1795 | break; |
| 1781 | case RDMA_CM_ROUTE_QUERY: | 1796 | case RDMA_CM_ROUTE_QUERY: |
| @@ -1810,6 +1825,8 @@ static void cma_release_port(struct rdma_id_private *id_priv) · 28 unmodified lines | |||
| 1810 | static void destroy_mc(struct rdma_id_private *id_priv, | 1825 | static void destroy_mc(struct rdma_id_private *id_priv, |
| 1811 | struct cma_multicast *mc) | 1826 | struct cma_multicast *mc) |
| 1812 | { | 1827 | { |
| 1828 | bool send_only = mc->join_state == BIT(SENDONLY_FULLMEMBER_JOIN); | ||
| 1829 | |||
| 1813 | if (rdma_cap_ib_mcast(id_priv->id.device, id_priv->id.port_num)) | 1830 | if (rdma_cap_ib_mcast(id_priv->id.device, id_priv->id.port_num)) |
| 1814 | ib_sa_free_multicast(mc->sa_mc); | 1831 | ib_sa_free_multicast(mc->sa_mc); |
| 1815 | 1832 | ||
| @@ -1826,7 +1843,10 @@ static void destroy_mc(struct rdma_id_private *id_priv, · 10 unmodified lines | |||
| 1826 | 1843 | ||
| 1827 | cma_set_mgid(id_priv, (struct sockaddr *)&mc->addr, | 1844 | cma_set_mgid(id_priv, (struct sockaddr *)&mc->addr, |
| 1828 | &mgid); | 1845 | &mgid); |
| 1829 | cma_igmp_send(ndev, &mgid, false); | 1846 | |
| 1847 | if (!send_only) | ||
| 1848 | cma_igmp_send(ndev, &mgid, false); | ||
| 1849 | |||
| 1830 | dev_put(ndev); | 1850 | dev_put(ndev); |
| 1831 | } | 1851 | } |
| 1832 | 1852 | ||
| @@ -2574,7 +2594,7 @@ static int cma_listen_on_all(struct rdma_id_private *id_priv) · 741 unmodified lines | |||
| 2574 | return 0; | 2594 | return 0; |
| 2575 | 2595 | ||
| 2576 | err_listen: | 2596 | err_listen: |
| 2577 | list_del(&id_priv->list); | 2597 | _cma_cancel_listens(id_priv); |
| 2578 | mutex_unlock(&lock); | 2598 | mutex_unlock(&lock); |
| 2579 | if (to_destroy) | 2599 | if (to_destroy) |
| 2580 | rdma_destroy_id(&to_destroy->id); | 2600 | rdma_destroy_id(&to_destroy->id); |
| @@ -3413,6 +3433,21 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, · 832 unmodified lines | |||
| 3413 | if (dst_addr->sa_family == AF_IB) { | 3433 | if (dst_addr->sa_family == AF_IB) { |
| 3414 | ret = cma_resolve_ib_addr(id_priv); | 3434 | ret = cma_resolve_ib_addr(id_priv); |
| 3415 | } else { | 3435 | } else { |
| 3436 | /* | ||
| 3437 | * The FSM can return back to RDMA_CM_ADDR_BOUND after | ||
| 3438 | * rdma_resolve_ip() is called, eg through the error | ||
| 3439 | * path in addr_handler(). If this happens the existing | ||
| 3440 | * request must be canceled before issuing a new one. | ||
| 3441 | * Since canceling a request is a bit slow and this | ||
| 3442 | * oddball path is rare, keep track once a request has | ||
| 3443 | * been issued. The track turns out to be a permanent | ||
| 3444 | * state since this is the only cancel as it is | ||
| 3445 | * immediately before rdma_resolve_ip(). | ||
| 3446 | */ | ||
| 3447 | if (id_priv->used_resolve_ip) | ||
| 3448 | rdma_addr_cancel(&id->route.addr.dev_addr); | ||
| 3449 | else | ||
| 3450 | id_priv->used_resolve_ip = 1; | ||
| 3416 | ret = rdma_resolve_ip(cma_src_addr(id_priv), dst_addr, | 3451 | ret = rdma_resolve_ip(cma_src_addr(id_priv), dst_addr, |
| 3417 | &id->route.addr.dev_addr, | 3452 | &id->route.addr.dev_addr, |
| 3418 | timeout_ms, addr_handler, | 3453 | timeout_ms, addr_handler, |
| @@ -3771,9 +3806,13 @@ int rdma_listen(struct rdma_cm_id *id, int backlog) · 352 unmodified lines | |||
| 3771 | int ret; | 3806 | int ret; |
| 3772 | 3807 | ||
| 3773 | if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_LISTEN)) { | 3808 | if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_LISTEN)) { |
| 3809 | struct sockaddr_in any_in = { | ||
| 3810 | .sin_family = AF_INET, | ||
| 3811 | .sin_addr.s_addr = htonl(INADDR_ANY), | ||
| 3812 | }; | ||
| 3813 | |||
| 3774 | /* For a well behaved ULP state will be RDMA_CM_IDLE */ | 3814 | /* For a well behaved ULP state will be RDMA_CM_IDLE */ |
| 3775 | id->route.addr.src_addr.ss_family = AF_INET; | 3815 | ret = rdma_bind_addr(id, (struct sockaddr *)&any_in); |
| 3776 | ret = rdma_bind_addr(id, cma_src_addr(id_priv)); | ||
| 3777 | if (ret) | 3816 | if (ret) |
| 3778 | return ret; | 3817 | return ret; |
| 3779 | if (WARN_ON(!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, | 3818 | if (WARN_ON(!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, |
| @@ -91,6 +91,7 @@ struct rdma_id_private { · 90 unmodified lines | |||
| 91 | u8 afonly; | 91 | u8 afonly; |
| 92 | u8 timeout; | 92 | u8 timeout; |
| 93 | u8 min_rnr_timer; | 93 | u8 min_rnr_timer; |
| 94 | u8 used_resolve_ip; | ||
| 94 | enum ib_gid_type gid_type; | 95 | enum ib_gid_type gid_type; |
| 95 | 96 | ||
| 96 | /* | 97 | /* |
| @@ -876,14 +876,14 @@ void hfi1_ipoib_tx_timeout(struct net_device *dev, unsigned int q) · 875 unmodified lines | |||
| 876 | struct hfi1_ipoib_txq *txq = &priv->txqs[q]; | 876 | struct hfi1_ipoib_txq *txq = &priv->txqs[q]; |
| 877 | u64 completed = atomic64_read(&txq->complete_txreqs); | 877 | u64 completed = atomic64_read(&txq->complete_txreqs); |
| 878 | 878 | ||
| 879 | dd_dev_info(priv->dd, "timeout txq %llx q %u stopped %u stops %d no_desc %d ring_full %d\n", | 879 | dd_dev_info(priv->dd, "timeout txq %p q %u stopped %u stops %d no_desc %d ring_full %d\n", |
| 880 | (unsigned long long)txq, q, | 880 | txq, q, |
| 881 | __netif_subqueue_stopped(dev, txq->q_idx), | 881 | __netif_subqueue_stopped(dev, txq->q_idx), |
| 882 | atomic_read(&txq->stops), | 882 | atomic_read(&txq->stops), |
| 883 | atomic_read(&txq->no_desc), | 883 | atomic_read(&txq->no_desc), |
| 884 | atomic_read(&txq->ring_full)); | 884 | atomic_read(&txq->ring_full)); |
| 885 | dd_dev_info(priv->dd, "sde %llx engine %u\n", | 885 | dd_dev_info(priv->dd, "sde %p engine %u\n", |
| 886 | (unsigned long long)txq->sde, | 886 | txq->sde, |
| 887 | txq->sde ? txq->sde->this_idx : 0); | 887 | txq->sde ? txq->sde->this_idx : 0); |
| 888 | dd_dev_info(priv->dd, "flow %x\n", txq->flow.as_int); | 888 | dd_dev_info(priv->dd, "flow %x\n", txq->flow.as_int); |
| 889 | dd_dev_info(priv->dd, "sent %llu completed %llu used %llu\n", | 889 | dd_dev_info(priv->dd, "sent %llu completed %llu used %llu\n", |
| @@ -326,19 +326,30 @@ static void set_cq_param(struct hns_roce_cq *hr_cq, u32 cq_entries, int vector, · 325 unmodified lines | |||
| 326 | INIT_LIST_HEAD(&hr_cq->rq_list); | 326 | INIT_LIST_HEAD(&hr_cq->rq_list); |
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | static void set_cqe_size(struct hns_roce_cq *hr_cq, struct ib_udata *udata, | 329 | static int set_cqe_size(struct hns_roce_cq *hr_cq, struct ib_udata *udata, |
| 330 | struct hns_roce_ib_create_cq *ucmd) | 330 | struct hns_roce_ib_create_cq *ucmd) |
| 331 | { | 331 | { |
| 332 | struct hns_roce_dev *hr_dev = to_hr_dev(hr_cq->ib_cq.device); | 332 | struct hns_roce_dev *hr_dev = to_hr_dev(hr_cq->ib_cq.device); |
| 333 | 333 | ||
| 334 | if (udata) { | 334 | if (!udata) { |
| 335 | if (udata->inlen >= offsetofend(typeof(*ucmd), cqe_size)) | ||
| 336 | hr_cq->cqe_size = ucmd->cqe_size; | ||
| 337 | else | ||
| 338 | hr_cq->cqe_size = HNS_ROCE_V2_CQE_SIZE; | ||
| 339 | } else { | ||
| 340 | hr_cq->cqe_size = hr_dev->caps.cqe_sz; | 335 | hr_cq->cqe_size = hr_dev->caps.cqe_sz; |
| 336 | return 0; | ||
| 337 | } | ||
| 338 | |||
| 339 | if (udata->inlen >= offsetofend(typeof(*ucmd), cqe_size)) { | ||
| 340 | if (ucmd->cqe_size != HNS_ROCE_V2_CQE_SIZE && | ||
| 341 | ucmd->cqe_size != HNS_ROCE_V3_CQE_SIZE) { | ||
| 342 | ibdev_err(&hr_dev->ib_dev, | ||
| 343 | "invalid cqe size %u.\n", ucmd->cqe_size); | ||
| 344 | return -EINVAL; | ||
| 345 | } | ||
| 346 | |||
| 347 | hr_cq->cqe_size = ucmd->cqe_size; | ||
| 348 | } else { | ||
| 349 | hr_cq->cqe_size = HNS_ROCE_V2_CQE_SIZE; | ||
| 341 | } | 350 | } |
| 351 | |||
| 352 | return 0; | ||
| 342 | } | 353 | } |
| 343 | 354 | ||
| 344 | int hns_roce_create_cq(struct ib_cq *ib_cq, const struct ib_cq_init_attr *attr, | 355 | int hns_roce_create_cq(struct ib_cq *ib_cq, const struct ib_cq_init_attr *attr, |
| @@ -366,7 +377,9 @@ int hns_roce_create_cq(struct ib_cq *ib_cq, const struct ib_cq_init_attr *attr, · 21 unmodified lines | |||
| 366 | 377 | ||
| 367 | set_cq_param(hr_cq, attr->cqe, attr->comp_vector, &ucmd); | 378 | set_cq_param(hr_cq, attr->cqe, attr->comp_vector, &ucmd); |
| 368 | 379 | ||
| 369 | set_cqe_size(hr_cq, udata, &ucmd); | 380 | ret = set_cqe_size(hr_cq, udata, &ucmd); |
| 381 | if (ret) | ||
| 382 | return ret; | ||
| 370 | 383 | ||
| 371 | ret = alloc_cq_buf(hr_dev, hr_cq, udata, ucmd.buf_addr); | 384 | ret = alloc_cq_buf(hr_dev, hr_cq, udata, ucmd.buf_addr); |
| 372 | if (ret) { | 385 | if (ret) { |
| @@ -3299,7 +3299,7 @@ static void __hns_roce_v2_cq_clean(struct hns_roce_cq *hr_cq, u32 qpn, · 3298 unmodified lines | |||
| 3299 | dest = get_cqe_v2(hr_cq, (prod_index + nfreed) & | 3299 | dest = get_cqe_v2(hr_cq, (prod_index + nfreed) & |
| 3300 | hr_cq->ib_cq.cqe); | 3300 | hr_cq->ib_cq.cqe); |
| 3301 | owner_bit = hr_reg_read(dest, CQE_OWNER); | 3301 | owner_bit = hr_reg_read(dest, CQE_OWNER); |
| 3302 | memcpy(dest, cqe, sizeof(*cqe)); | 3302 | memcpy(dest, cqe, hr_cq->cqe_size); |
| 3303 | hr_reg_write(dest, CQE_OWNER, owner_bit); | 3303 | hr_reg_write(dest, CQE_OWNER, owner_bit); |
| 3304 | } | 3304 | } |
| 3305 | } | 3305 | } |
| @@ -4397,7 +4397,12 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, · 1091 unmodified lines | |||
| 4397 | hr_qp->path_mtu = ib_mtu; | 4397 | hr_qp->path_mtu = ib_mtu; |
| 4398 | 4398 | ||
| 4399 | mtu = ib_mtu_enum_to_int(ib_mtu); | 4399 | mtu = ib_mtu_enum_to_int(ib_mtu); |
| 4400 | if (WARN_ON(mtu < 0)) | 4400 | if (WARN_ON(mtu <= 0)) |
| 4401 | return -EINVAL; | ||
| 4402 | #define MAX_LP_MSG_LEN 65536 | ||
| 4403 | /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 64KB */ | ||
| 4404 | lp_pktn_ini = ilog2(MAX_LP_MSG_LEN / mtu); | ||
| 4405 | if (WARN_ON(lp_pktn_ini >= 0xF)) | ||
| 4401 | return -EINVAL; | 4406 | return -EINVAL; |
| 4402 | 4407 | ||
| 4403 | if (attr_mask & IB_QP_PATH_MTU) { | 4408 | if (attr_mask & IB_QP_PATH_MTU) { |
| @@ -4405,10 +4410,6 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, · 1 unmodified line | |||
| 4405 | hr_reg_clear(qpc_mask, QPC_MTU); | 4410 | hr_reg_clear(qpc_mask, QPC_MTU); |
| 4406 | } | 4411 | } |
| 4407 | 4412 | ||
| 4408 | #define MAX_LP_MSG_LEN 65536 | ||
| 4409 | /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 64KB */ | ||
| 4410 | lp_pktn_ini = ilog2(MAX_LP_MSG_LEN / mtu); | ||
| 4411 | |||
| 4412 | hr_reg_write(context, QPC_LP_PKTN_INI, lp_pktn_ini); | 4413 | hr_reg_write(context, QPC_LP_PKTN_INI, lp_pktn_ini); |
| 4413 | hr_reg_clear(qpc_mask, QPC_LP_PKTN_INI); | 4414 | hr_reg_clear(qpc_mask, QPC_LP_PKTN_INI); |
| 4414 | 4415 | ||
| @@ -3496,7 +3496,7 @@ static void irdma_cm_disconn_true(struct irdma_qp *iwqp) · 3495 unmodified lines | |||
| 3496 | original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT || | 3496 | original_hw_tcp_state == IRDMA_TCP_STATE_TIME_WAIT || |
| 3497 | last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE || | 3497 | last_ae == IRDMA_AE_RDMAP_ROE_BAD_LLP_CLOSE || |
| 3498 | last_ae == IRDMA_AE_BAD_CLOSE || | 3498 | last_ae == IRDMA_AE_BAD_CLOSE || |
| 3499 | last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->reset)) { | 3499 | last_ae == IRDMA_AE_LLP_CONNECTION_RESET || iwdev->rf->reset)) { |
| 3500 | issue_close = 1; | 3500 | issue_close = 1; |
| 3501 | iwqp->cm_id = NULL; | 3501 | iwqp->cm_id = NULL; |
| 3502 | qp->term_flags = 0; | 3502 | qp->term_flags = 0; |
| @@ -4250,7 +4250,7 @@ void irdma_cm_teardown_connections(struct irdma_device *iwdev, u32 *ipaddr, · 747 unmodified lines | |||
| 4250 | teardown_entry); | 4250 | teardown_entry); |
| 4251 | attr.qp_state = IB_QPS_ERR; | 4251 | attr.qp_state = IB_QPS_ERR; |
| 4252 | irdma_modify_qp(&cm_node->iwqp->ibqp, &attr, IB_QP_STATE, NULL); | 4252 | irdma_modify_qp(&cm_node->iwqp->ibqp, &attr, IB_QP_STATE, NULL); |
| 4253 | if (iwdev->reset) | 4253 | if (iwdev->rf->reset) |
| 4254 | irdma_cm_disconn(cm_node->iwqp); | 4254 | irdma_cm_disconn(cm_node->iwqp); |
| 4255 | irdma_rem_ref_cm_node(cm_node); | 4255 | irdma_rem_ref_cm_node(cm_node); |
| 4256 | } | 4256 | } |
| @@ -176,6 +176,14 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, · 175 unmodified lines | |||
| 176 | case IRDMA_AE_LLP_RECEIVED_MPA_CRC_ERROR: | 176 | case IRDMA_AE_LLP_RECEIVED_MPA_CRC_ERROR: |
| 177 | qp->flush_code = FLUSH_GENERAL_ERR; | 177 | qp->flush_code = FLUSH_GENERAL_ERR; |
| 178 | break; | 178 | break; |
| 179 | case IRDMA_AE_LLP_TOO_MANY_RETRIES: | ||
| 180 | qp->flush_code = FLUSH_RETRY_EXC_ERR; | ||
| 181 | break; | ||
| 182 | case IRDMA_AE_AMP_MWBIND_INVALID_RIGHTS: | ||
| 183 | case IRDMA_AE_AMP_MWBIND_BIND_DISABLED: | ||
| 184 | case IRDMA_AE_AMP_MWBIND_INVALID_BOUNDS: | ||
| 185 | qp->flush_code = FLUSH_MW_BIND_ERR; | ||
| 186 | break; | ||
| 179 | default: | 187 | default: |
| 180 | qp->flush_code = FLUSH_FATAL_ERR; | 188 | qp->flush_code = FLUSH_FATAL_ERR; |
| 181 | break; | 189 | break; |
| @@ -1489,7 +1497,7 @@ void irdma_reinitialize_ieq(struct irdma_sc_vsi *vsi) · 1307 unmodified lines | |||
| 1489 | 1497 | ||
| 1490 | irdma_puda_dele_rsrc(vsi, IRDMA_PUDA_RSRC_TYPE_IEQ, false); | 1498 | irdma_puda_dele_rsrc(vsi, IRDMA_PUDA_RSRC_TYPE_IEQ, false); |
| 1491 | if (irdma_initialize_ieq(iwdev)) { | 1499 | if (irdma_initialize_ieq(iwdev)) { |
| 1492 | iwdev->reset = true; | 1500 | iwdev->rf->reset = true; |
| 1493 | rf->gen_ops.request_reset(rf); | 1501 | rf->gen_ops.request_reset(rf); |
| 1494 | } | 1502 | } |
| 1495 | } | 1503 | } |
| @@ -1632,13 +1640,13 @@ void irdma_rt_deinit_hw(struct irdma_device *iwdev) · 136 unmodified lines | |||
| 1632 | case IEQ_CREATED: | 1640 | case IEQ_CREATED: |
| 1633 | if (!iwdev->roce_mode) | 1641 | if (!iwdev->roce_mode) |
| 1634 | irdma_puda_dele_rsrc(&iwdev->vsi, IRDMA_PUDA_RSRC_TYPE_IEQ, | 1642 | irdma_puda_dele_rsrc(&iwdev->vsi, IRDMA_PUDA_RSRC_TYPE_IEQ, |
| 1635 | iwdev->reset); | 1643 | iwdev->rf->reset); |
| 1636 | fallthrough; | 1644 | fallthrough; |
| 1637 | case ILQ_CREATED: | 1645 | case ILQ_CREATED: |
| 1638 | if (!iwdev->roce_mode) | 1646 | if (!iwdev->roce_mode) |
| 1639 | irdma_puda_dele_rsrc(&iwdev->vsi, | 1647 | irdma_puda_dele_rsrc(&iwdev->vsi, |
| 1640 | IRDMA_PUDA_RSRC_TYPE_ILQ, | 1648 | IRDMA_PUDA_RSRC_TYPE_ILQ, |
| 1641 | iwdev->reset); | 1649 | iwdev->rf->reset); |
| 1642 | break; | 1650 | break; |
| 1643 | default: | 1651 | default: |
| 1644 | ibdev_warn(&iwdev->ibdev, "bad init_state = %d\n", iwdev->init_state); | 1652 | ibdev_warn(&iwdev->ibdev, "bad init_state = %d\n", iwdev->init_state); |
| @@ -55,7 +55,7 @@ static void i40iw_close(struct i40e_info *cdev_info, struct i40e_client *client, · 54 unmodified lines | |||
| 55 | 55 | ||
| 56 | iwdev = to_iwdev(ibdev); | 56 | iwdev = to_iwdev(ibdev); |
| 57 | if (reset) | 57 | if (reset) |
| 58 | iwdev->reset = true; | 58 | iwdev->rf->reset = true; |
| 59 | 59 | ||
| 60 | iwdev->iw_status = 0; | 60 | iwdev->iw_status = 0; |
| 61 | irdma_port_ibevent(iwdev); | 61 | irdma_port_ibevent(iwdev); |
| @@ -346,7 +346,6 @@ struct irdma_device { · 345 unmodified lines | |||
| 346 | bool roce_mode:1; | 346 | bool roce_mode:1; |
| 347 | bool roce_dcqcn_en:1; | 347 | bool roce_dcqcn_en:1; |
| 348 | bool dcb:1; | 348 | bool dcb:1; |
| 349 | bool reset:1; | ||
| 350 | bool iw_ooo:1; | 349 | bool iw_ooo:1; |
| 351 | enum init_completion_state init_state; | 350 | enum init_completion_state init_state; |
| 352 | 351 | ||
| @@ -102,6 +102,8 @@ enum irdma_flush_opcode { · 101 unmodified lines | |||
| 102 | FLUSH_REM_OP_ERR, | 102 | FLUSH_REM_OP_ERR, |
| 103 | FLUSH_LOC_LEN_ERR, | 103 | FLUSH_LOC_LEN_ERR, |
| 104 | FLUSH_FATAL_ERR, | 104 | FLUSH_FATAL_ERR, |
| 105 | FLUSH_RETRY_EXC_ERR, | ||
| 106 | FLUSH_MW_BIND_ERR, | ||
| 105 | }; | 107 | }; |
| 106 | 108 | ||
| 107 | enum irdma_cmpl_status { | 109 | enum irdma_cmpl_status { |
| @@ -2507,7 +2507,7 @@ void irdma_modify_qp_to_err(struct irdma_sc_qp *sc_qp) · 2506 unmodified lines | |||
| 2507 | struct irdma_qp *qp = sc_qp->qp_uk.back_qp; | 2507 | struct irdma_qp *qp = sc_qp->qp_uk.back_qp; |
| 2508 | struct ib_qp_attr attr; | 2508 | struct ib_qp_attr attr; |
| 2509 | 2509 | ||
| 2510 | if (qp->iwdev->reset) | 2510 | if (qp->iwdev->rf->reset) |
| 2511 | return; | 2511 | return; |
| 2512 | attr.qp_state = IB_QPS_ERR; | 2512 | attr.qp_state = IB_QPS_ERR; |
| 2513 | 2513 | ||
| @@ -535,8 +535,7 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) · 534 unmodified lines | |||
| 535 | irdma_qp_rem_ref(&iwqp->ibqp); | 535 | irdma_qp_rem_ref(&iwqp->ibqp); |
| 536 | wait_for_completion(&iwqp->free_qp); | 536 | wait_for_completion(&iwqp->free_qp); |
| 537 | irdma_free_lsmm_rsrc(iwqp); | 537 | irdma_free_lsmm_rsrc(iwqp); |
| 538 | if (!iwdev->reset) | 538 | irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp); |
| 539 | irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp); | ||
| 540 | 539 | ||
| 541 | if (!iwqp->user_mode) { | 540 | if (!iwqp->user_mode) { |
| 542 | if (iwqp->iwscq) { | 541 | if (iwqp->iwscq) { |
| @@ -2035,7 +2034,7 @@ static int irdma_create_cq(struct ib_cq *ibcq, · 1492 unmodified lines | |||
| 2035 | /* Kmode allocations */ | 2034 | /* Kmode allocations */ |
| 2036 | int rsize; | 2035 | int rsize; |
| 2037 | 2036 | ||
| 2038 | if (entries > rf->max_cqe) { | 2037 | if (entries < 1 || entries > rf->max_cqe) { |
| 2039 | err_code = -EINVAL; | 2038 | err_code = -EINVAL; |
| 2040 | goto cq_free_rsrc; | 2039 | goto cq_free_rsrc; |
| 2041 | } | 2040 | } |
| @@ -3353,6 +3352,10 @@ static enum ib_wc_status irdma_flush_err_to_ib_wc_status(enum irdma_flush_opcode · 1311 unmodified lines | |||
| 3353 | return IB_WC_LOC_LEN_ERR; | 3352 | return IB_WC_LOC_LEN_ERR; |
| 3354 | case FLUSH_GENERAL_ERR: | 3353 | case FLUSH_GENERAL_ERR: |
| 3355 | return IB_WC_WR_FLUSH_ERR; | 3354 | return IB_WC_WR_FLUSH_ERR; |
| 3355 | case FLUSH_RETRY_EXC_ERR: | ||
| 3356 | return IB_WC_RETRY_EXC_ERR; | ||
| 3357 | case FLUSH_MW_BIND_ERR: | ||
| 3358 | return IB_WC_MW_BIND_ERR; | ||
| 3356 | case FLUSH_FATAL_ERR: | 3359 | case FLUSH_FATAL_ERR: |
| 3357 | default: | 3360 | default: |
| 3358 | return IB_WC_FATAL_ERR; | 3361 | return IB_WC_FATAL_ERR; |
| @@ -403,7 +403,7 @@ static ssize_t diagc_attr_store(struct ib_device *ibdev, u32 port_num, · 402 unmodified lines | |||
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | #define QIB_DIAGC_ATTR(N) \ | 405 | #define QIB_DIAGC_ATTR(N) \ |
| 406 | static_assert(&((struct qib_ibport *)0)->rvp.n_##N != (u64 *)NULL); \ | 406 | static_assert(__same_type(((struct qib_ibport *)0)->rvp.n_##N, u64)); \ |
| 407 | static struct qib_diagc_attr qib_diagc_attr_##N = { \ | 407 | static struct qib_diagc_attr qib_diagc_attr_##N = { \ |
| 408 | .attr = __ATTR(N, 0664, diagc_attr_show, diagc_attr_store), \ | 408 | .attr = __ATTR(N, 0664, diagc_attr_show, diagc_attr_store), \ |
| 409 | .counter = \ | 409 | .counter = \ |
| @@ -90,7 +90,7 @@ struct usnic_ib_dev { · 89 unmodified lines | |||
| 90 | 90 | ||
| 91 | struct usnic_ib_vf { | 91 | struct usnic_ib_vf { |
| 92 | struct usnic_ib_dev *pf; | 92 | struct usnic_ib_dev *pf; |
| 93 | spinlock_t lock; | 93 | struct mutex lock; |
| 94 | struct usnic_vnic *vnic; | 94 | struct usnic_vnic *vnic; |
| 95 | unsigned int qp_grp_ref_cnt; | 95 | unsigned int qp_grp_ref_cnt; |
| 96 | struct usnic_ib_pd *pd; | 96 | struct usnic_ib_pd *pd; |
| @@ -572,7 +572,7 @@ static int usnic_ib_pci_probe(struct pci_dev *pdev, · 571 unmodified lines | |||
| 572 | } | 572 | } |
| 573 | 573 | ||
| 574 | vf->pf = pf; | 574 | vf->pf = pf; |
| 575 | spin_lock_init(&vf->lock); | 575 | mutex_init(&vf->lock); |
| 576 | mutex_lock(&pf->usdev_lock); | 576 | mutex_lock(&pf->usdev_lock); |
| 577 | list_add_tail(&vf->link, &pf->vf_dev_list); | 577 | list_add_tail(&vf->link, &pf->vf_dev_list); |
| 578 | /* | 578 | /* |
| @@ -196,7 +196,7 @@ find_free_vf_and_create_qp_grp(struct ib_qp *qp, · 195 unmodified lines | |||
| 196 | for (i = 0; dev_list[i]; i++) { | 196 | for (i = 0; dev_list[i]; i++) { |
| 197 | dev = dev_list[i]; | 197 | dev = dev_list[i]; |
| 198 | vf = dev_get_drvdata(dev); | 198 | vf = dev_get_drvdata(dev); |
| 199 | spin_lock(&vf->lock); | 199 | mutex_lock(&vf->lock); |
| 200 | vnic = vf->vnic; | 200 | vnic = vf->vnic; |
| 201 | if (!usnic_vnic_check_room(vnic, res_spec)) { | 201 | if (!usnic_vnic_check_room(vnic, res_spec)) { |
| 202 | usnic_dbg("Found used vnic %s from %s\n", | 202 | usnic_dbg("Found used vnic %s from %s\n", |
| @@ -208,10 +208,10 @@ find_free_vf_and_create_qp_grp(struct ib_qp *qp, · 5 unmodified lines | |||
| 208 | vf, pd, res_spec, | 208 | vf, pd, res_spec, |
| 209 | trans_spec); | 209 | trans_spec); |
| 210 | 210 | ||
| 211 | spin_unlock(&vf->lock); | 211 | mutex_unlock(&vf->lock); |
| 212 | goto qp_grp_check; | 212 | goto qp_grp_check; |
| 213 | } | 213 | } |
| 214 | spin_unlock(&vf->lock); | 214 | mutex_unlock(&vf->lock); |
| 215 | 215 | ||
| 216 | } | 216 | } |
| 217 | usnic_uiom_free_dev_list(dev_list); | 217 | usnic_uiom_free_dev_list(dev_list); |
| @@ -220,7 +220,7 @@ find_free_vf_and_create_qp_grp(struct ib_qp *qp, · 2 unmodified lines | |||
| 220 | 220 | ||
| 221 | /* Try to find resources on an unused vf */ | 221 | /* Try to find resources on an unused vf */ |
| 222 | list_for_each_entry(vf, &us_ibdev->vf_dev_list, link) { | 222 | list_for_each_entry(vf, &us_ibdev->vf_dev_list, link) { |
| 223 | spin_lock(&vf->lock); | 223 | mutex_lock(&vf->lock); |
| 224 | vnic = vf->vnic; | 224 | vnic = vf->vnic; |
| 225 | if (vf->qp_grp_ref_cnt == 0 && | 225 | if (vf->qp_grp_ref_cnt == 0 && |
| 226 | usnic_vnic_check_room(vnic, res_spec) == 0) { | 226 | usnic_vnic_check_room(vnic, res_spec) == 0) { |
| @@ -228,10 +228,10 @@ find_free_vf_and_create_qp_grp(struct ib_qp *qp, · 1 unmodified line | |||
| 228 | vf, pd, res_spec, | 228 | vf, pd, res_spec, |
| 229 | trans_spec); | 229 | trans_spec); |
| 230 | 230 | ||
| 231 | spin_unlock(&vf->lock); | 231 | mutex_unlock(&vf->lock); |
| 232 | goto qp_grp_check; | 232 | goto qp_grp_check; |
| 233 | } | 233 | } |
| 234 | spin_unlock(&vf->lock); | 234 | mutex_unlock(&vf->lock); |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | usnic_info("No free qp grp found on %s\n", | 237 | usnic_info("No free qp grp found on %s\n", |
| @@ -253,9 +253,9 @@ static void qp_grp_destroy(struct usnic_ib_qp_grp *qp_grp) · 15 unmodified lines | |||
| 253 | 253 | ||
| 254 | WARN_ON(qp_grp->state != IB_QPS_RESET); | 254 | WARN_ON(qp_grp->state != IB_QPS_RESET); |
| 255 | 255 | ||
| 256 | spin_lock(&vf->lock); | 256 | mutex_lock(&vf->lock); |
| 257 | usnic_ib_qp_grp_destroy(qp_grp); | 257 | usnic_ib_qp_grp_destroy(qp_grp); |
| 258 | spin_unlock(&vf->lock); | 258 | mutex_unlock(&vf->lock); |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | static int create_qp_validate_user_data(struct usnic_ib_create_qp_cmd cmd) | 261 | static int create_qp_validate_user_data(struct usnic_ib_create_qp_cmd cmd) |
| @@ -44,9 +44,9 @@ · 43 unmodified lines | |||
| 44 | #define NOC_PERM_MODE_BYPASS (1 << NOC_QOS_MODE_BYPASS) | 44 | #define NOC_PERM_MODE_BYPASS (1 << NOC_QOS_MODE_BYPASS) |
| 45 | 45 | ||
| 46 | #define NOC_QOS_PRIORITYn_ADDR(n) (0x8 + (n * 0x1000)) | 46 | #define NOC_QOS_PRIORITYn_ADDR(n) (0x8 + (n * 0x1000)) |
| 47 | #define NOC_QOS_PRIORITY_MASK 0xf | 47 | #define NOC_QOS_PRIORITY_P1_MASK 0xc |
| 48 | #define NOC_QOS_PRIORITY_P0_MASK 0x3 | ||
| 48 | #define NOC_QOS_PRIORITY_P1_SHIFT 0x2 | 49 | #define NOC_QOS_PRIORITY_P1_SHIFT 0x2 |
| 49 | #define NOC_QOS_PRIORITY_P0_SHIFT 0x3 | ||
| 50 | 50 | ||
| 51 | #define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000)) | 51 | #define NOC_QOS_MODEn_ADDR(n) (0xc + (n * 0x1000)) |
| 52 | #define NOC_QOS_MODEn_MASK 0x3 | 52 | #define NOC_QOS_MODEn_MASK 0x3 |
| @@ -173,6 +173,16 @@ static const struct clk_bulk_data bus_mm_clocks[] = { · 120 unmodified lines | |||
| 173 | { .id = "iface" }, | 173 | { .id = "iface" }, |
| 174 | }; | 174 | }; |
| 175 | 175 | ||
| 176 | static const struct clk_bulk_data bus_a2noc_clocks[] = { | ||
| 177 | { .id = "bus" }, | ||
| 178 | { .id = "bus_a" }, | ||
| 179 | { .id = "ipa" }, | ||
| 180 | { .id = "ufs_axi" }, | ||
| 181 | { .id = "aggre2_ufs_axi" }, | ||
| 182 | { .id = "aggre2_usb3_axi" }, | ||
| 183 | { .id = "cfg_noc_usb2_axi" }, | ||
| 184 | }; | ||
| 185 | |||
| 176 | /** | 186 | /** |
| 177 | * struct qcom_icc_provider - Qualcomm specific interconnect provider | 187 | * struct qcom_icc_provider - Qualcomm specific interconnect provider |
| 178 | * @provider: generic interconnect provider | 188 | * @provider: generic interconnect provider |
| @@ -307,7 +317,7 @@ DEFINE_QNODE(slv_bimc_cfg, SDM660_SLAVE_BIMC_CFG, 4, -1, 56, true, -1, 0, -1, 0) · 128 unmodified lines | |||
| 307 | DEFINE_QNODE(slv_prng, SDM660_SLAVE_PRNG, 4, -1, 44, true, -1, 0, -1, 0); | 317 | DEFINE_QNODE(slv_prng, SDM660_SLAVE_PRNG, 4, -1, 44, true, -1, 0, -1, 0); |
| 308 | DEFINE_QNODE(slv_spdm, SDM660_SLAVE_SPDM, 4, -1, 60, true, -1, 0, -1, 0); | 318 | DEFINE_QNODE(slv_spdm, SDM660_SLAVE_SPDM, 4, -1, 60, true, -1, 0, -1, 0); |
| 309 | DEFINE_QNODE(slv_qdss_cfg, SDM660_SLAVE_QDSS_CFG, 4, -1, 63, true, -1, 0, -1, 0); | 319 | DEFINE_QNODE(slv_qdss_cfg, SDM660_SLAVE_QDSS_CFG, 4, -1, 63, true, -1, 0, -1, 0); |
| 310 | DEFINE_QNODE(slv_cnoc_mnoc_cfg, SDM660_SLAVE_BLSP_1, 4, -1, 66, true, -1, 0, -1, SDM660_MASTER_CNOC_MNOC_CFG); | 320 | DEFINE_QNODE(slv_cnoc_mnoc_cfg, SDM660_SLAVE_CNOC_MNOC_CFG, 4, -1, 66, true, -1, 0, -1, SDM660_MASTER_CNOC_MNOC_CFG); |
| 311 | DEFINE_QNODE(slv_snoc_cfg, SDM660_SLAVE_SNOC_CFG, 4, -1, 70, true, -1, 0, -1, 0); | 321 | DEFINE_QNODE(slv_snoc_cfg, SDM660_SLAVE_SNOC_CFG, 4, -1, 70, true, -1, 0, -1, 0); |
| 312 | DEFINE_QNODE(slv_qm_cfg, SDM660_SLAVE_QM_CFG, 4, -1, 212, true, -1, 0, -1, 0); | 322 | DEFINE_QNODE(slv_qm_cfg, SDM660_SLAVE_QM_CFG, 4, -1, 212, true, -1, 0, -1, 0); |
| 313 | DEFINE_QNODE(slv_clk_ctl, SDM660_SLAVE_CLK_CTL, 4, -1, 47, true, -1, 0, -1, 0); | 323 | DEFINE_QNODE(slv_clk_ctl, SDM660_SLAVE_CLK_CTL, 4, -1, 47, true, -1, 0, -1, 0); |
| @@ -624,13 +634,12 @@ static int qcom_icc_noc_set_qos_priority(struct regmap *rmap, · 310 unmodified lines | |||
| 624 | /* Must be updated one at a time, P1 first, P0 last */ | 634 | /* Must be updated one at a time, P1 first, P0 last */ |
| 625 | val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT; | 635 | val = qos->areq_prio << NOC_QOS_PRIORITY_P1_SHIFT; |
| 626 | rc = regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port), | 636 | rc = regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port), |
| 627 | NOC_QOS_PRIORITY_MASK, val); | 637 | NOC_QOS_PRIORITY_P1_MASK, val); |
| 628 | if (rc) | 638 | if (rc) |
| 629 | return rc; | 639 | return rc; |
| 630 | 640 | ||
| 631 | val = qos->prio_level << NOC_QOS_PRIORITY_P0_SHIFT; | ||
| 632 | return regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port), | 641 | return regmap_update_bits(rmap, NOC_QOS_PRIORITYn_ADDR(qos->qos_port), |
| 633 | NOC_QOS_PRIORITY_MASK, val); | 642 | NOC_QOS_PRIORITY_P0_MASK, qos->prio_level); |
| 634 | } | 643 | } |
| 635 | 644 | ||
| 636 | static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw) | 645 | static int qcom_icc_set_noc_qos(struct icc_node *src, u64 max_bw) |
| @@ -810,6 +819,10 @@ static int qnoc_probe(struct platform_device *pdev) · 173 unmodified lines | |||
| 810 | qp->bus_clks = devm_kmemdup(dev, bus_mm_clocks, | 819 | qp->bus_clks = devm_kmemdup(dev, bus_mm_clocks, |
| 811 | sizeof(bus_mm_clocks), GFP_KERNEL); | 820 | sizeof(bus_mm_clocks), GFP_KERNEL); |
| 812 | qp->num_clks = ARRAY_SIZE(bus_mm_clocks); | 821 | qp->num_clks = ARRAY_SIZE(bus_mm_clocks); |
| 822 | } else if (of_device_is_compatible(dev->of_node, "qcom,sdm660-a2noc")) { | ||
| 823 | qp->bus_clks = devm_kmemdup(dev, bus_a2noc_clocks, | ||
| 824 | sizeof(bus_a2noc_clocks), GFP_KERNEL); | ||
| 825 | qp->num_clks = ARRAY_SIZE(bus_a2noc_clocks); | ||
| 813 | } else { | 826 | } else { |
| 814 | if (of_device_is_compatible(dev->of_node, "qcom,sdm660-bimc")) | 827 | if (of_device_is_compatible(dev->of_node, "qcom,sdm660-bimc")) |
| 815 | qp->is_bimc_node = true; | 828 | qp->is_bimc_node = true; |
| @@ -183,7 +183,6 @@ struct apple_dart_master_cfg { · 182 unmodified lines | |||
| 183 | 183 | ||
| 184 | static struct platform_driver apple_dart_driver; | 184 | static struct platform_driver apple_dart_driver; |
| 185 | static const struct iommu_ops apple_dart_iommu_ops; | 185 | static const struct iommu_ops apple_dart_iommu_ops; |
| 186 | static const struct iommu_flush_ops apple_dart_tlb_ops; | ||
| 187 | 186 | ||
| 188 | static struct apple_dart_domain *to_dart_domain(struct iommu_domain *dom) | 187 | static struct apple_dart_domain *to_dart_domain(struct iommu_domain *dom) |
| 189 | { | 188 | { |
| @@ -338,22 +337,6 @@ static void apple_dart_iotlb_sync_map(struct iommu_domain *domain, · 148 unmodified lines | |||
| 338 | apple_dart_domain_flush_tlb(to_dart_domain(domain)); | 337 | apple_dart_domain_flush_tlb(to_dart_domain(domain)); |
| 339 | } | 338 | } |
| 340 | 339 | ||
| 341 | static void apple_dart_tlb_flush_all(void *cookie) | ||
| 342 | { | ||
| 343 | apple_dart_domain_flush_tlb(cookie); | ||
| 344 | } | ||
| 345 | |||
| 346 | static void apple_dart_tlb_flush_walk(unsigned long iova, size_t size, | ||
| 347 | size_t granule, void *cookie) | ||
| 348 | { | ||
| 349 | apple_dart_domain_flush_tlb(cookie); | ||
| 350 | } | ||
| 351 | |||
| 352 | static const struct iommu_flush_ops apple_dart_tlb_ops = { | ||
| 353 | .tlb_flush_all = apple_dart_tlb_flush_all, | ||
| 354 | .tlb_flush_walk = apple_dart_tlb_flush_walk, | ||
| 355 | }; | ||
| 356 | |||
| 357 | static phys_addr_t apple_dart_iova_to_phys(struct iommu_domain *domain, | 340 | static phys_addr_t apple_dart_iova_to_phys(struct iommu_domain *domain, |
| 358 | dma_addr_t iova) | 341 | dma_addr_t iova) |
| 359 | { | 342 | { |
| @@ -435,7 +418,6 @@ static int apple_dart_finalize_domain(struct iommu_domain *domain, · 75 unmodified lines | |||
| 435 | .ias = 32, | 418 | .ias = 32, |
| 436 | .oas = 36, | 419 | .oas = 36, |
| 437 | .coherent_walk = 1, | 420 | .coherent_walk = 1, |
| 438 | .tlb = &apple_dart_tlb_ops, | ||
| 439 | .iommu_dev = dart->dev, | 421 | .iommu_dev = dart->dev, |
| 440 | }; | 422 | }; |
| 441 | 423 | ||
| @@ -661,16 +643,34 @@ static int apple_dart_of_xlate(struct device *dev, struct of_phandle_args *args) · 219 unmodified lines | |||
| 661 | return -EINVAL; | 643 | return -EINVAL; |
| 662 | } | 644 | } |
| 663 | 645 | ||
| 646 | static DEFINE_MUTEX(apple_dart_groups_lock); | ||
| 647 | |||
| 648 | static void apple_dart_release_group(void *iommu_data) | ||
| 649 | { | ||
| 650 | int i, sid; | ||
| 651 | struct apple_dart_stream_map *stream_map; | ||
| 652 | struct apple_dart_master_cfg *group_master_cfg = iommu_data; | ||
| 653 | |||
| 654 | mutex_lock(&apple_dart_groups_lock); | ||
| 655 | |||
| 656 | for_each_stream_map(i, group_master_cfg, stream_map) | ||
| 657 | for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS) | ||
| 658 | stream_map->dart->sid2group[sid] = NULL; | ||
| 659 | |||
| 660 | kfree(iommu_data); | ||
| 661 | mutex_unlock(&apple_dart_groups_lock); | ||
| 662 | } | ||
| 663 | |||
| 664 | static struct iommu_group *apple_dart_device_group(struct device *dev) | 664 | static struct iommu_group *apple_dart_device_group(struct device *dev) |
| 665 | { | 665 | { |
| 666 | static DEFINE_MUTEX(lock); | ||
| 667 | int i, sid; | 666 | int i, sid; |
| 668 | struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev); | 667 | struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev); |
| 669 | struct apple_dart_stream_map *stream_map; | 668 | struct apple_dart_stream_map *stream_map; |
| 669 | struct apple_dart_master_cfg *group_master_cfg; | ||
| 670 | struct iommu_group *group = NULL; | 670 | struct iommu_group *group = NULL; |
| 671 | struct iommu_group *res = ERR_PTR(-EINVAL); | 671 | struct iommu_group *res = ERR_PTR(-EINVAL); |
| 672 | 672 | ||
| 673 | mutex_lock(&lock); | 673 | mutex_lock(&apple_dart_groups_lock); |
| 674 | 674 | ||
| 675 | for_each_stream_map(i, cfg, stream_map) { | 675 | for_each_stream_map(i, cfg, stream_map) { |
| 676 | for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS) { | 676 | for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS) { |
| @@ -698,6 +698,20 @@ static struct iommu_group *apple_dart_device_group(struct device *dev) · 21 unmodified lines | |||
| 698 | #endif | 698 | #endif |
| 699 | group = generic_device_group(dev); | 699 | group = generic_device_group(dev); |
| 700 | 700 | ||
| 701 | res = ERR_PTR(-ENOMEM); | ||
| 702 | if (!group) | ||
| 703 | goto out; | ||
| 704 | |||
| 705 | group_master_cfg = kzalloc(sizeof(*group_master_cfg), GFP_KERNEL); | ||
| 706 | if (!group_master_cfg) { | ||
| 707 | iommu_group_put(group); | ||
| 708 | goto out; | ||
| 709 | } | ||
| 710 | |||
| 711 | memcpy(group_master_cfg, cfg, sizeof(*group_master_cfg)); | ||
| 712 | iommu_group_set_iommudata(group, group_master_cfg, | ||
| 713 | apple_dart_release_group); | ||
| 714 | |||
| 701 | for_each_stream_map(i, cfg, stream_map) | 715 | for_each_stream_map(i, cfg, stream_map) |
| 702 | for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS) | 716 | for_each_set_bit(sid, &stream_map->sidmap, DART_MAX_STREAMS) |
| 703 | stream_map->dart->sid2group[sid] = group; | 717 | stream_map->dart->sid2group[sid] = group; |
| @@ -705,7 +719,7 @@ static struct iommu_group *apple_dart_device_group(struct device *dev) · 1 unmodified line | |||
| 705 | res = group; | 719 | res = group; |
| 706 | 720 | ||
| 707 | out: | 721 | out: |
| 708 | mutex_unlock(&lock); | 722 | mutex_unlock(&apple_dart_groups_lock); |
| 709 | return res; | 723 | return res; |
| 710 | } | 724 | } |
| 711 | 725 | ||
| @@ -1942,18 +1942,18 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type, · 1941 unmodified lines | |||
| 1942 | reason = dmar_get_fault_reason(fault_reason, &fault_type); | 1942 | reason = dmar_get_fault_reason(fault_reason, &fault_type); |
| 1943 | 1943 | ||
| 1944 | if (fault_type == INTR_REMAP) | 1944 | if (fault_type == INTR_REMAP) |
| 1945 | pr_err("[INTR-REMAP] Request device [0x%02x:0x%02x.%d] fault index 0x%llx [fault reason 0x%02x] %s\n", | 1945 | pr_err("[INTR-REMAP] Request device [%02x:%02x.%d] fault index 0x%llx [fault reason 0x%02x] %s\n", |
| 1946 | source_id >> 8, PCI_SLOT(source_id & 0xFF), | 1946 | source_id >> 8, PCI_SLOT(source_id & 0xFF), |
| 1947 | PCI_FUNC(source_id & 0xFF), addr >> 48, | 1947 | PCI_FUNC(source_id & 0xFF), addr >> 48, |
| 1948 | fault_reason, reason); | 1948 | fault_reason, reason); |
| 1949 | else if (pasid == INVALID_IOASID) | 1949 | else if (pasid == INVALID_IOASID) |
| 1950 | pr_err("[%s NO_PASID] Request device [0x%02x:0x%02x.%d] fault addr 0x%llx [fault reason 0x%02x] %s\n", | 1950 | pr_err("[%s NO_PASID] Request device [%02x:%02x.%d] fault addr 0x%llx [fault reason 0x%02x] %s\n", |
| 1951 | type ? "DMA Read" : "DMA Write", | 1951 | type ? "DMA Read" : "DMA Write", |
| 1952 | source_id >> 8, PCI_SLOT(source_id & 0xFF), | 1952 | source_id >> 8, PCI_SLOT(source_id & 0xFF), |
| 1953 | PCI_FUNC(source_id & 0xFF), addr, | 1953 | PCI_FUNC(source_id & 0xFF), addr, |
| 1954 | fault_reason, reason); | 1954 | fault_reason, reason); |
| 1955 | else | 1955 | else |
| 1956 | pr_err("[%s PASID 0x%x] Request device [0x%02x:0x%02x.%d] fault addr 0x%llx [fault reason 0x%02x] %s\n", | 1956 | pr_err("[%s PASID 0x%x] Request device [%02x:%02x.%d] fault addr 0x%llx [fault reason 0x%02x] %s\n", |
| 1957 | type ? "DMA Read" : "DMA Write", pasid, | 1957 | type ? "DMA Read" : "DMA Write", pasid, |
| 1958 | source_id >> 8, PCI_SLOT(source_id & 0xFF), | 1958 | source_id >> 8, PCI_SLOT(source_id & 0xFF), |
| 1959 | PCI_FUNC(source_id & 0xFF), addr, | 1959 | PCI_FUNC(source_id & 0xFF), addr, |
| @@ -33,6 +33,7 @@ struct ipoctal_channel { · 32 unmodified lines | |||
| 33 | unsigned int pointer_read; | 33 | unsigned int pointer_read; |
| 34 | unsigned int pointer_write; | 34 | unsigned int pointer_write; |
| 35 | struct tty_port tty_port; | 35 | struct tty_port tty_port; |
| 36 | bool tty_registered; | ||
| 36 | union scc2698_channel __iomem *regs; | 37 | union scc2698_channel __iomem *regs; |
| 37 | union scc2698_block __iomem *block_regs; | 38 | union scc2698_block __iomem *block_regs; |
| 38 | unsigned int board_id; | 39 | unsigned int board_id; |
| @@ -81,22 +82,34 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) · 42 unmodified lines | |||
| 81 | return 0; | 82 | return 0; |
| 82 | } | 83 | } |
| 83 | 84 | ||
| 84 | static int ipoctal_open(struct tty_struct *tty, struct file *file) | 85 | static int ipoctal_install(struct tty_driver *driver, struct tty_struct *tty) |
| 85 | { | 86 | { |
| 86 | struct ipoctal_channel *channel = dev_get_drvdata(tty->dev); | 87 | struct ipoctal_channel *channel = dev_get_drvdata(tty->dev); |
| 87 | struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index); | 88 | struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index); |
| 88 | int err; | 89 | int res; |
| 89 | |||
| 90 | tty->driver_data = channel; | ||
| 91 | 90 | ||
| 92 | if (!ipack_get_carrier(ipoctal->dev)) | 91 | if (!ipack_get_carrier(ipoctal->dev)) |
| 93 | return -EBUSY; | 92 | return -EBUSY; |
| 94 | 93 | ||
| 95 | err = tty_port_open(&channel->tty_port, tty, file); | 94 | res = tty_standard_install(driver, tty); |
| 96 | if (err) | 95 | if (res) |
| 97 | ipack_put_carrier(ipoctal->dev); | 96 | goto err_put_carrier; |
| 97 | |||
| 98 | tty->driver_data = channel; | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | |||
| 102 | err_put_carrier: | ||
| 103 | ipack_put_carrier(ipoctal->dev); | ||
| 104 | |||
| 105 | return res; | ||
| 106 | } | ||
| 107 | |||
| 108 | static int ipoctal_open(struct tty_struct *tty, struct file *file) | ||
| 109 | { | ||
| 110 | struct ipoctal_channel *channel = tty->driver_data; | ||
| 98 | 111 | ||
| 99 | return err; | 112 | return tty_port_open(&channel->tty_port, tty, file); |
| 100 | } | 113 | } |
| 101 | 114 | ||
| 102 | static void ipoctal_reset_stats(struct ipoctal_stats *stats) | 115 | static void ipoctal_reset_stats(struct ipoctal_stats *stats) |
| @@ -264,7 +277,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, · 161 unmodified lines | |||
| 264 | int res; | 277 | int res; |
| 265 | int i; | 278 | int i; |
| 266 | struct tty_driver *tty; | 279 | struct tty_driver *tty; |
| 267 | char name[20]; | ||
| 268 | struct ipoctal_channel *channel; | 280 | struct ipoctal_channel *channel; |
| 269 | struct ipack_region *region; | 281 | struct ipack_region *region; |
| 270 | void __iomem *addr; | 282 | void __iomem *addr; |
| @@ -355,8 +367,11 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, · 84 unmodified lines | |||
| 355 | /* Fill struct tty_driver with ipoctal data */ | 367 | /* Fill struct tty_driver with ipoctal data */ |
| 356 | tty->owner = THIS_MODULE; | 368 | tty->owner = THIS_MODULE; |
| 357 | tty->driver_name = KBUILD_MODNAME; | 369 | tty->driver_name = KBUILD_MODNAME; |
| 358 | sprintf(name, KBUILD_MODNAME ".%d.%d.", bus_nr, slot); | 370 | tty->name = kasprintf(GFP_KERNEL, KBUILD_MODNAME ".%d.%d.", bus_nr, slot); |
| 359 | tty->name = name; | 371 | if (!tty->name) { |
| 372 | res = -ENOMEM; | ||
| 373 | goto err_put_driver; | ||
| 374 | } | ||
| 360 | tty->major = 0; | 375 | tty->major = 0; |
| 361 | 376 | ||
| 362 | tty->minor_start = 0; | 377 | tty->minor_start = 0; |
| @@ -371,8 +386,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, · 8 unmodified lines | |||
| 371 | res = tty_register_driver(tty); | 386 | res = tty_register_driver(tty); |
| 372 | if (res) { | 387 | if (res) { |
| 373 | dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n"); | 388 | dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n"); |
| 374 | tty_driver_kref_put(tty); | 389 | goto err_free_name; |
| 375 | return res; | ||
| 376 | } | 390 | } |
| 377 | 391 | ||
| 378 | /* Save struct tty_driver for use it when uninstalling the device */ | 392 | /* Save struct tty_driver for use it when uninstalling the device */ |
| @@ -383,7 +397,9 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, · 4 unmodified lines | |||
| 383 | 397 | ||
| 384 | channel = &ipoctal->channel[i]; | 398 | channel = &ipoctal->channel[i]; |
| 385 | tty_port_init(&channel->tty_port); | 399 | tty_port_init(&channel->tty_port); |
| 386 | tty_port_alloc_xmit_buf(&channel->tty_port); | 400 | res = tty_port_alloc_xmit_buf(&channel->tty_port); |
| 401 | if (res) | ||
| 402 | continue; | ||
| 387 | channel->tty_port.ops = &ipoctal_tty_port_ops; | 403 | channel->tty_port.ops = &ipoctal_tty_port_ops; |
| 388 | 404 | ||
| 389 | ipoctal_reset_stats(&channel->stats); | 405 | ipoctal_reset_stats(&channel->stats); |
| @@ -391,13 +407,15 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, · 1 unmodified line | |||
| 391 | spin_lock_init(&channel->lock); | 407 | spin_lock_init(&channel->lock); |
| 392 | channel->pointer_read = 0; | 408 | channel->pointer_read = 0; |
| 393 | channel->pointer_write = 0; | 409 | channel->pointer_write = 0; |
| 394 | tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL); | 410 | tty_dev = tty_port_register_device_attr(&channel->tty_port, tty, |
| 411 | i, NULL, channel, NULL); | ||
| 395 | if (IS_ERR(tty_dev)) { | 412 | if (IS_ERR(tty_dev)) { |
| 396 | dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n"); | 413 | dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n"); |
| 414 | tty_port_free_xmit_buf(&channel->tty_port); | ||
| 397 | tty_port_destroy(&channel->tty_port); | 415 | tty_port_destroy(&channel->tty_port); |
| 398 | continue; | 416 | continue; |
| 399 | } | 417 | } |
| 400 | dev_set_drvdata(tty_dev, channel); | 418 | channel->tty_registered = true; |
| 401 | } | 419 | } |
| 402 | 420 | ||
| 403 | /* | 421 | /* |
| @@ -409,6 +427,13 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, · 5 unmodified lines | |||
| 409 | ipoctal_irq_handler, ipoctal); | 427 | ipoctal_irq_handler, ipoctal); |
| 410 | 428 | ||
| 411 | return 0; | 429 | return 0; |
| 430 | |||
| 431 | err_free_name: | ||
| 432 | kfree(tty->name); | ||
| 433 | err_put_driver: | ||
| 434 | tty_driver_kref_put(tty); | ||
| 435 | |||
| 436 | return res; | ||
| 412 | } | 437 | } |
| 413 | 438 | ||
| 414 | static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel, | 439 | static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel, |
| @@ -648,6 +673,7 @@ static void ipoctal_cleanup(struct tty_struct *tty) · 233 unmodified lines | |||
| 648 | 673 | ||
| 649 | static const struct tty_operations ipoctal_fops = { | 674 | static const struct tty_operations ipoctal_fops = { |
| 650 | .ioctl = NULL, | 675 | .ioctl = NULL, |
| 676 | .install = ipoctal_install, | ||
| 651 | .open = ipoctal_open, | 677 | .open = ipoctal_open, |
| 652 | .close = ipoctal_close, | 678 | .close = ipoctal_close, |
| 653 | .write = ipoctal_write_tty, | 679 | .write = ipoctal_write_tty, |
| @@ -690,12 +716,17 @@ static void __ipoctal_remove(struct ipoctal *ipoctal) · 36 unmodified lines | |||
| 690 | 716 | ||
| 691 | for (i = 0; i < NR_CHANNELS; i++) { | 717 | for (i = 0; i < NR_CHANNELS; i++) { |
| 692 | struct ipoctal_channel *channel = &ipoctal->channel[i]; | 718 | struct ipoctal_channel *channel = &ipoctal->channel[i]; |
| 719 | |||
| 720 | if (!channel->tty_registered) | ||
| 721 | continue; | ||
| 722 | |||
| 693 | tty_unregister_device(ipoctal->tty_drv, i); | 723 | tty_unregister_device(ipoctal->tty_drv, i); |
| 694 | tty_port_free_xmit_buf(&channel->tty_port); | 724 | tty_port_free_xmit_buf(&channel->tty_port); |
| 695 | tty_port_destroy(&channel->tty_port); | 725 | tty_port_destroy(&channel->tty_port); |
| 696 | } | 726 | } |
| 697 | 727 | ||
| 698 | tty_unregister_driver(ipoctal->tty_drv); | 728 | tty_unregister_driver(ipoctal->tty_drv); |
| 729 | kfree(ipoctal->tty_drv->name); | ||
| 699 | tty_driver_kref_put(ipoctal->tty_drv); | 730 | tty_driver_kref_put(ipoctal->tty_drv); |
| 700 | kfree(ipoctal); | 731 | kfree(ipoctal); |
| 701 | } | 732 | } |
| @@ -1140,8 +1140,8 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, · 1139 unmodified lines | |||
| 1140 | continue; | 1140 | continue; |
| 1141 | length = 0; | 1141 | length = 0; |
| 1142 | switch (c) { | 1142 | switch (c) { |
| 1143 | /* SOF0: baseline JPEG */ | 1143 | /* JPEG_MARKER_SOF0: baseline JPEG */ |
| 1144 | case SOF0: | 1144 | case JPEG_MARKER_SOF0: |
| 1145 | if (get_word_be(&jpeg_buffer, &word)) | 1145 | if (get_word_be(&jpeg_buffer, &word)) |
| 1146 | break; | 1146 | break; |
| 1147 | length = (long)word - 2; | 1147 | length = (long)word - 2; |
| @@ -1172,7 +1172,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, · 24 unmodified lines | |||
| 1172 | notfound = 0; | 1172 | notfound = 0; |
| 1173 | break; | 1173 | break; |
| 1174 | 1174 | ||
| 1175 | case DQT: | 1175 | case JPEG_MARKER_DQT: |
| 1176 | if (get_word_be(&jpeg_buffer, &word)) | 1176 | if (get_word_be(&jpeg_buffer, &word)) |
| 1177 | break; | 1177 | break; |
| 1178 | length = (long)word - 2; | 1178 | length = (long)word - 2; |
| @@ -1185,7 +1185,7 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, · 6 unmodified lines | |||
| 1185 | skip(&jpeg_buffer, length); | 1185 | skip(&jpeg_buffer, length); |
| 1186 | break; | 1186 | break; |
| 1187 | 1187 | ||
| 1188 | case DHT: | 1188 | case JPEG_MARKER_DHT: |
| 1189 | if (get_word_be(&jpeg_buffer, &word)) | 1189 | if (get_word_be(&jpeg_buffer, &word)) |
| 1190 | break; | 1190 | break; |
| 1191 | length = (long)word - 2; | 1191 | length = (long)word - 2; |
| @@ -1198,15 +1198,15 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, · 6 unmodified lines | |||
| 1198 | skip(&jpeg_buffer, length); | 1198 | skip(&jpeg_buffer, length); |
| 1199 | break; | 1199 | break; |
| 1200 | 1200 | ||
| 1201 | case SOS: | 1201 | case JPEG_MARKER_SOS: |
| 1202 | sos = jpeg_buffer.curr - 2; /* 0xffda */ | 1202 | sos = jpeg_buffer.curr - 2; /* 0xffda */ |
| 1203 | break; | 1203 | break; |
| 1204 | 1204 | ||
| 1205 | /* skip payload-less markers */ | 1205 | /* skip payload-less markers */ |
| 1206 | case RST ... RST + 7: | 1206 | case JPEG_MARKER_RST ... JPEG_MARKER_RST + 7: |
| 1207 | case SOI: | 1207 | case JPEG_MARKER_SOI: |
| 1208 | case EOI: | 1208 | case JPEG_MARKER_EOI: |
| 1209 | case TEM: | 1209 | case JPEG_MARKER_TEM: |
| 1210 | break; | 1210 | break; |
| 1211 | 1211 | ||
| 1212 | /* skip uninteresting payload markers */ | 1212 | /* skip uninteresting payload markers */ |
| @@ -37,15 +37,15 @@ · 36 unmodified lines | |||
| 37 | #define EXYNOS3250_IRQ_TIMEOUT 0x10000000 | 37 | #define EXYNOS3250_IRQ_TIMEOUT 0x10000000 |
| 38 | 38 | ||
| 39 | /* a selection of JPEG markers */ | 39 | /* a selection of JPEG markers */ |
| 40 | #define TEM 0x01 | 40 | #define JPEG_MARKER_TEM 0x01 |
| 41 | #define SOF0 0xc0 | 41 | #define JPEG_MARKER_SOF0 0xc0 |
| 42 | #define DHT 0xc4 | 42 | #define JPEG_MARKER_DHT 0xc4 |
| 43 | #define RST 0xd0 | 43 | #define JPEG_MARKER_RST 0xd0 |
| 44 | #define SOI 0xd8 | 44 | #define JPEG_MARKER_SOI 0xd8 |
| 45 | #define EOI 0xd9 | 45 | #define JPEG_MARKER_EOI 0xd9 |
| 46 | #define SOS 0xda | 46 | #define JPEG_MARKER_SOS 0xda |
| 47 | #define DQT 0xdb | 47 | #define JPEG_MARKER_DQT 0xdb |
| 48 | #define DHP 0xde | 48 | #define JPEG_MARKER_DHP 0xde |
| 49 | 49 | ||
| 50 | /* Flags that indicate a format can be used for capture/output */ | 50 | /* Flags that indicate a format can be used for capture/output */ |
| 51 | #define SJPEG_FMT_FLAG_ENC_CAPTURE (1 << 0) | 51 | #define SJPEG_FMT_FLAG_ENC_CAPTURE (1 << 0) |
| @@ -187,11 +187,11 @@ struct s5p_jpeg_marker { · 135 unmodified lines | |||
| 187 | * @fmt: driver-specific format of this queue | 187 | * @fmt: driver-specific format of this queue |
| 188 | * @w: image width | 188 | * @w: image width |
| 189 | * @h: image height | 189 | * @h: image height |
| 190 | * @sos: SOS marker's position relative to the buffer beginning | 190 | * @sos: JPEG_MARKER_SOS's position relative to the buffer beginning |
| 191 | * @dht: DHT markers' positions relative to the buffer beginning | 191 | * @dht: JPEG_MARKER_DHT' positions relative to the buffer beginning |
| 192 | * @dqt: DQT markers' positions relative to the buffer beginning | 192 | * @dqt: JPEG_MARKER_DQT' positions relative to the buffer beginning |
| 193 | * @sof: SOF0 marker's position relative to the buffer beginning | 193 | * @sof: JPEG_MARKER_SOF0's position relative to the buffer beginning |
| 194 | * @sof_len: SOF0 marker's payload length (without length field itself) | 194 | * @sof_len: JPEG_MARKER_SOF0's payload length (without length field itself) |
| 195 | * @size: image buffer size in bytes | 195 | * @size: image buffer size in bytes |
| 196 | */ | 196 | */ |
| 197 | struct s5p_jpeg_q_data { | 197 | struct s5p_jpeg_q_data { |
| @@ -24,6 +24,7 @@ static const u8 COMMAND_VERSION[] = { 'v' }; · 23 unmodified lines | |||
| 24 | // End transmit and repeat reset command so we exit sump mode | 24 | // End transmit and repeat reset command so we exit sump mode |
| 25 | static const u8 COMMAND_RESET[] = { 0xff, 0xff, 0, 0, 0, 0, 0 }; | 25 | static const u8 COMMAND_RESET[] = { 0xff, 0xff, 0, 0, 0, 0, 0 }; |
| 26 | static const u8 COMMAND_SMODE_ENTER[] = { 's' }; | 26 | static const u8 COMMAND_SMODE_ENTER[] = { 's' }; |
| 27 | static const u8 COMMAND_SMODE_EXIT[] = { 0 }; | ||
| 27 | static const u8 COMMAND_TXSTART[] = { 0x26, 0x24, 0x25, 0x03 }; | 28 | static const u8 COMMAND_TXSTART[] = { 0x26, 0x24, 0x25, 0x03 }; |
| 28 | 29 | ||
| 29 | #define REPLY_XMITCOUNT 't' | 30 | #define REPLY_XMITCOUNT 't' |
| @@ -309,12 +310,30 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count) · 279 unmodified lines | |||
| 309 | buf[i] = cpu_to_be16(v); | 310 | buf[i] = cpu_to_be16(v); |
| 310 | } | 311 | } |
| 311 | 312 | ||
| 312 | buf[count] = cpu_to_be16(0xffff); | 313 | buf[count] = 0xffff; |
| 313 | 314 | ||
| 314 | irtoy->tx_buf = buf; | 315 | irtoy->tx_buf = buf; |
| 315 | irtoy->tx_len = size; | 316 | irtoy->tx_len = size; |
| 316 | irtoy->emitted = 0; | 317 | irtoy->emitted = 0; |
| 317 | 318 | ||
| 319 | // There is an issue where if the unit is receiving IR while the | ||
| 320 | // first TXSTART command is sent, the device might end up hanging | ||
| 321 | // with its led on. It does not respond to any command when this | ||
| 322 | // happens. To work around this, re-enter sample mode. | ||
| 323 | err = irtoy_command(irtoy, COMMAND_SMODE_EXIT, | ||
| 324 | sizeof(COMMAND_SMODE_EXIT), STATE_RESET); | ||
| 325 | if (err) { | ||
| 326 | dev_err(irtoy->dev, "exit sample mode: %d\n", err); | ||
| 327 | return err; | ||
| 328 | } | ||
| 329 | |||
| 330 | err = irtoy_command(irtoy, COMMAND_SMODE_ENTER, | ||
| 331 | sizeof(COMMAND_SMODE_ENTER), STATE_COMMAND); | ||
| 332 | if (err) { | ||
| 333 | dev_err(irtoy->dev, "enter sample mode: %d\n", err); | ||
| 334 | return err; | ||
| 335 | } | ||
| 336 | |||
| 318 | err = irtoy_command(irtoy, COMMAND_TXSTART, sizeof(COMMAND_TXSTART), | 337 | err = irtoy_command(irtoy, COMMAND_TXSTART, sizeof(COMMAND_TXSTART), |
| 319 | STATE_TX); | 338 | STATE_TX); |
| 320 | kfree(buf); | 339 | kfree(buf); |
| @@ -1802,10 +1802,15 @@ static enum hrtimer_restart dw_mci_fault_timer(struct hrtimer *t) · 1801 unmodified lines | |||
| 1802 | 1802 | ||
| 1803 | spin_lock_irqsave(&host->irq_lock, flags); | 1803 | spin_lock_irqsave(&host->irq_lock, flags); |
| 1804 | 1804 | ||
| 1805 | if (!host->data_status) | 1805 | /* |
| 1806 | * Only inject an error if we haven't already got an error or data over | ||
| 1807 | * interrupt. | ||
| 1808 | */ | ||
| 1809 | if (!host->data_status) { | ||
| 1806 | host->data_status = SDMMC_INT_DCRC; | 1810 | host->data_status = SDMMC_INT_DCRC; |
| 1807 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | 1811 | set_bit(EVENT_DATA_ERROR, &host->pending_events); |
| 1808 | tasklet_schedule(&host->tasklet); | 1812 | tasklet_schedule(&host->tasklet); |
| 1813 | } | ||
| 1809 | 1814 | ||
| 1810 | spin_unlock_irqrestore(&host->irq_lock, flags); | 1815 | spin_unlock_irqrestore(&host->irq_lock, flags); |
| 1811 | 1816 | ||
| @@ -2721,12 +2726,16 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) · 909 unmodified lines | |||
| 2721 | } | 2726 | } |
| 2722 | 2727 | ||
| 2723 | if (pending & DW_MCI_DATA_ERROR_FLAGS) { | 2728 | if (pending & DW_MCI_DATA_ERROR_FLAGS) { |
| 2729 | spin_lock(&host->irq_lock); | ||
| 2730 | |||
| 2724 | /* if there is an error report DATA_ERROR */ | 2731 | /* if there is an error report DATA_ERROR */ |
| 2725 | mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); | 2732 | mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); |
| 2726 | host->data_status = pending; | 2733 | host->data_status = pending; |
| 2727 | smp_wmb(); /* drain writebuffer */ | 2734 | smp_wmb(); /* drain writebuffer */ |
| 2728 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | 2735 | set_bit(EVENT_DATA_ERROR, &host->pending_events); |
| 2729 | tasklet_schedule(&host->tasklet); | 2736 | tasklet_schedule(&host->tasklet); |
| 2737 | |||
| 2738 | spin_unlock(&host->irq_lock); | ||
| 2730 | } | 2739 | } |
| 2731 | 2740 | ||
| 2732 | if (pending & SDMMC_INT_DATA_OVER) { | 2741 | if (pending & SDMMC_INT_DATA_OVER) { |
| @@ -561,6 +561,8 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) · 560 unmodified lines | |||
| 561 | /* Unknown why but without polling reset status, it will hang */ | 561 | /* Unknown why but without polling reset status, it will hang */ |
| 562 | read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100, | 562 | read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100, |
| 563 | false, priv->rstc); | 563 | false, priv->rstc); |
| 564 | /* At least SDHI_VER_GEN2_SDR50 needs manual release of reset */ | ||
| 565 | sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); | ||
| 564 | priv->needs_adjust_hs400 = false; | 566 | priv->needs_adjust_hs400 = false; |
| 565 | renesas_sdhi_set_clock(host, host->clk_cache); | 567 | renesas_sdhi_set_clock(host, host->clk_cache); |
| 566 | } else if (priv->scc_ctl) { | 568 | } else if (priv->scc_ctl) { |
| @@ -2834,8 +2834,8 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) · 2833 unmodified lines | |||
| 2834 | if (err) | 2834 | if (err) |
| 2835 | return err; | 2835 | return err; |
| 2836 | 2836 | ||
| 2837 | /* Port Control 2: don't force a good FCS, set the maximum frame size to | 2837 | /* Port Control 2: don't force a good FCS, set the MTU size to |
| 2838 | * 10240 bytes, disable 802.1q tags checking, don't discard tagged or | 2838 | * 10222 bytes, disable 802.1q tags checking, don't discard tagged or |
| 2839 | * untagged frames on this port, do a destination address lookup on all | 2839 | * untagged frames on this port, do a destination address lookup on all |
| 2840 | * received packets as usual, disable ARP mirroring and don't send a | 2840 | * received packets as usual, disable ARP mirroring and don't send a |
| 2841 | * copy of all transmitted/received frames on this port to the CPU. | 2841 | * copy of all transmitted/received frames on this port to the CPU. |
| @@ -2854,7 +2854,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) · 12 unmodified lines | |||
| 2854 | return err; | 2854 | return err; |
| 2855 | 2855 | ||
| 2856 | if (chip->info->ops->port_set_jumbo_size) { | 2856 | if (chip->info->ops->port_set_jumbo_size) { |
| 2857 | err = chip->info->ops->port_set_jumbo_size(chip, port, 10240); | 2857 | err = chip->info->ops->port_set_jumbo_size(chip, port, 10218); |
| 2858 | if (err) | 2858 | if (err) |
| 2859 | return err; | 2859 | return err; |
| 2860 | } | 2860 | } |
| @@ -2944,10 +2944,10 @@ static int mv88e6xxx_get_max_mtu(struct dsa_switch *ds, int port) · 83 unmodified lines | |||
| 2944 | struct mv88e6xxx_chip *chip = ds->priv; | 2944 | struct mv88e6xxx_chip *chip = ds->priv; |
| 2945 | 2945 | ||
| 2946 | if (chip->info->ops->port_set_jumbo_size) | 2946 | if (chip->info->ops->port_set_jumbo_size) |
| 2947 | return 10240; | 2947 | return 10240 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; |
| 2948 | else if (chip->info->ops->set_max_frame_size) | 2948 | else if (chip->info->ops->set_max_frame_size) |
| 2949 | return 1632; | 2949 | return 1632 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; |
| 2950 | return 1522; | 2950 | return 1522 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; |
| 2951 | } | 2951 | } |
| 2952 | 2952 | ||
| 2953 | static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) | 2953 | static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) |
| @@ -2955,6 +2955,9 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) · 1 unmodified line | |||
| 2955 | struct mv88e6xxx_chip *chip = ds->priv; | 2955 | struct mv88e6xxx_chip *chip = ds->priv; |
| 2956 | int ret = 0; | 2956 | int ret = 0; |
| 2957 | 2957 | ||
| 2958 | if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) | ||
| 2959 | new_mtu += EDSA_HLEN; | ||
| 2960 | |||
| 2958 | mv88e6xxx_reg_lock(chip); | 2961 | mv88e6xxx_reg_lock(chip); |
| 2959 | if (chip->info->ops->port_set_jumbo_size) | 2962 | if (chip->info->ops->port_set_jumbo_size) |
| 2960 | ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu); | 2963 | ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu); |
| @@ -3725,7 +3728,6 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { · 764 unmodified lines | |||
| 3725 | .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, | 3728 | .port_set_ucast_flood = mv88e6352_port_set_ucast_flood, |
| 3726 | .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, | 3729 | .port_set_mcast_flood = mv88e6352_port_set_mcast_flood, |
| 3727 | .port_set_ether_type = mv88e6351_port_set_ether_type, | 3730 | .port_set_ether_type = mv88e6351_port_set_ether_type, |
| 3728 | .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, | ||
| 3729 | .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, | 3731 | .port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting, |
| 3730 | .port_pause_limit = mv88e6097_port_pause_limit, | 3732 | .port_pause_limit = mv88e6097_port_pause_limit, |
| 3731 | .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, | 3733 | .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, |
| @@ -3750,6 +3752,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { · 18 unmodified lines | |||
| 3750 | .avb_ops = &mv88e6165_avb_ops, | 3752 | .avb_ops = &mv88e6165_avb_ops, |
| 3751 | .ptp_ops = &mv88e6165_ptp_ops, | 3753 | .ptp_ops = &mv88e6165_ptp_ops, |
| 3752 | .phylink_validate = mv88e6185_phylink_validate, | 3754 | .phylink_validate = mv88e6185_phylink_validate, |
| 3755 | .set_max_frame_size = mv88e6185_g1_set_max_frame_size, | ||
| 3753 | }; | 3756 | }; |
| 3754 | 3757 | ||
| 3755 | static const struct mv88e6xxx_ops mv88e6165_ops = { | 3758 | static const struct mv88e6xxx_ops mv88e6165_ops = { |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <linux/timecounter.h> | 18 | #include <linux/timecounter.h> |
| 19 | #include <net/dsa.h> | 19 | #include <net/dsa.h> |
| 20 | 20 | ||
| 21 | #define EDSA_HLEN 8 | ||
| 21 | #define MV88E6XXX_N_FID 4096 | 22 | #define MV88E6XXX_N_FID 4096 |
| 22 | 23 | ||
| 23 | /* PVT limits for 4-bit port and 5-bit switch */ | 24 | /* PVT limits for 4-bit port and 5-bit switch */ |
| @@ -232,6 +232,8 @@ int mv88e6185_g1_set_max_frame_size(struct mv88e6xxx_chip *chip, int mtu) · 231 unmodified lines | |||
| 232 | u16 val; | 232 | u16 val; |
| 233 | int err; | 233 | int err; |
| 234 | 234 | ||
| 235 | mtu += ETH_HLEN + ETH_FCS_LEN; | ||
| 236 | |||
| 235 | err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val); | 237 | err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val); |
| 236 | if (err) | 238 | if (err) |
| 237 | return err; | 239 | return err; |
| @@ -1277,6 +1277,8 @@ int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port, · 1276 unmodified lines | |||
| 1277 | u16 reg; | 1277 | u16 reg; |
| 1278 | int err; | 1278 | int err; |
| 1279 | 1279 | ||
| 1280 | size += VLAN_ETH_HLEN + ETH_FCS_LEN; | ||
| 1281 | |||
| 1280 | err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®); | 1282 | err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, ®); |
| 1281 | if (err) | 1283 | if (err) |
| 1282 | return err; | 1284 | return err; |
| @@ -192,6 +192,9 @@ static int bgmac_probe(struct platform_device *pdev) · 191 unmodified lines | |||
| 192 | bgmac->dma_dev = &pdev->dev; | 192 | bgmac->dma_dev = &pdev->dev; |
| 193 | 193 | ||
| 194 | ret = of_get_mac_address(np, bgmac->net_dev->dev_addr); | 194 | ret = of_get_mac_address(np, bgmac->net_dev->dev_addr); |
| 195 | if (ret == -EPROBE_DEFER) | ||
| 196 | return ret; | ||
| 197 | |||
| 195 | if (ret) | 198 | if (ret) |
| 196 | dev_warn(&pdev->dev, | 199 | dev_warn(&pdev->dev, |
| 197 | "MAC address not present in device tree\n"); | 200 | "MAC address not present in device tree\n"); |
| @@ -541,8 +541,7 @@ static void enetc_mac_config(struct enetc_hw *hw, phy_interface_t phy_mode) · 540 unmodified lines | |||
| 541 | 541 | ||
| 542 | if (phy_interface_mode_is_rgmii(phy_mode)) { | 542 | if (phy_interface_mode_is_rgmii(phy_mode)) { |
| 543 | val = enetc_port_rd(hw, ENETC_PM0_IF_MODE); | 543 | val = enetc_port_rd(hw, ENETC_PM0_IF_MODE); |
| 544 | val &= ~ENETC_PM0_IFM_EN_AUTO; | 544 | val &= ~(ENETC_PM0_IFM_EN_AUTO | ENETC_PM0_IFM_IFMODE_MASK); |
| 545 | val &= ENETC_PM0_IFM_IFMODE_MASK; | ||
| 546 | val |= ENETC_PM0_IFM_IFMODE_GMII | ENETC_PM0_IFM_RG; | 545 | val |= ENETC_PM0_IFM_IFMODE_GMII | ENETC_PM0_IFM_RG; |
| 547 | enetc_port_wr(hw, ENETC_PM0_IF_MODE, val); | 546 | enetc_port_wr(hw, ENETC_PM0_IF_MODE, val); |
| 548 | } | 547 | } |
| @@ -752,7 +752,6 @@ struct hnae3_tc_info { · 751 unmodified lines | |||
| 752 | u8 prio_tc[HNAE3_MAX_USER_PRIO]; /* TC indexed by prio */ | 752 | u8 prio_tc[HNAE3_MAX_USER_PRIO]; /* TC indexed by prio */ |
| 753 | u16 tqp_count[HNAE3_MAX_TC]; | 753 | u16 tqp_count[HNAE3_MAX_TC]; |
| 754 | u16 tqp_offset[HNAE3_MAX_TC]; | 754 | u16 tqp_offset[HNAE3_MAX_TC]; |
| 755 | unsigned long tc_en; /* bitmap of TC enabled */ | ||
| 756 | u8 num_tc; /* Total number of enabled TCs */ | 755 | u8 num_tc; /* Total number of enabled TCs */ |
| 757 | bool mqprio_active; | 756 | bool mqprio_active; |
| 758 | }; | 757 | }; |
| @@ -623,13 +623,9 @@ static int hns3_nic_set_real_num_queue(struct net_device *netdev) · 622 unmodified lines | |||
| 623 | return ret; | 623 | return ret; |
| 624 | } | 624 | } |
| 625 | 625 | ||
| 626 | for (i = 0; i < HNAE3_MAX_TC; i++) { | 626 | for (i = 0; i < tc_info->num_tc; i++) |
| 627 | if (!test_bit(i, &tc_info->tc_en)) | ||
| 628 | continue; | ||
| 629 | |||
| 630 | netdev_set_tc_queue(netdev, i, tc_info->tqp_count[i], | 627 | netdev_set_tc_queue(netdev, i, tc_info->tqp_count[i], |
| 631 | tc_info->tqp_offset[i]); | 628 | tc_info->tqp_offset[i]); |
| 632 | } | ||
| 633 | } | 629 | } |
| 634 | 630 | ||
| 635 | ret = netif_set_real_num_tx_queues(netdev, queue_size); | 631 | ret = netif_set_real_num_tx_queues(netdev, queue_size); |
| @@ -779,6 +775,11 @@ static int hns3_nic_net_open(struct net_device *netdev) · 143 unmodified lines | |||
| 779 | if (hns3_nic_resetting(netdev)) | 775 | if (hns3_nic_resetting(netdev)) |
| 780 | return -EBUSY; | 776 | return -EBUSY; |
| 781 | 777 | ||
| 778 | if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) { | ||
| 779 | netdev_warn(netdev, "net open repeatedly!\n"); | ||
| 780 | return 0; | ||
| 781 | } | ||
| 782 | |||
| 782 | netif_carrier_off(netdev); | 783 | netif_carrier_off(netdev); |
| 783 | 784 | ||
| 784 | ret = hns3_nic_set_real_num_queue(netdev); | 785 | ret = hns3_nic_set_real_num_queue(netdev); |
| @@ -4865,12 +4866,9 @@ static void hns3_init_tx_ring_tc(struct hns3_nic_priv *priv) · 4080 unmodified lines | |||
| 4865 | struct hnae3_tc_info *tc_info = &kinfo->tc_info; | 4866 | struct hnae3_tc_info *tc_info = &kinfo->tc_info; |
| 4866 | int i; | 4867 | int i; |
| 4867 | 4868 | ||
| 4868 | for (i = 0; i < HNAE3_MAX_TC; i++) { | 4869 | for (i = 0; i < tc_info->num_tc; i++) { |
| 4869 | int j; | 4870 | int j; |
| 4870 | 4871 | ||
| 4871 | if (!test_bit(i, &tc_info->tc_en)) | ||
| 4872 | continue; | ||
| 4873 | |||
| 4874 | for (j = 0; j < tc_info->tqp_count[i]; j++) { | 4872 | for (j = 0; j < tc_info->tqp_count[i]; j++) { |
| 4875 | struct hnae3_queue *q; | 4873 | struct hnae3_queue *q; |
| 4876 | 4874 | ||
| @@ -334,7 +334,8 @@ static void hns3_selftest_prepare(struct net_device *ndev, · 333 unmodified lines | |||
| 334 | 334 | ||
| 335 | #if IS_ENABLED(CONFIG_VLAN_8021Q) | 335 | #if IS_ENABLED(CONFIG_VLAN_8021Q) |
| 336 | /* Disable the vlan filter for selftest does not support it */ | 336 | /* Disable the vlan filter for selftest does not support it */ |
| 337 | if (h->ae_algo->ops->enable_vlan_filter) | 337 | if (h->ae_algo->ops->enable_vlan_filter && |
| 338 | ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) | ||
| 338 | h->ae_algo->ops->enable_vlan_filter(h, false); | 339 | h->ae_algo->ops->enable_vlan_filter(h, false); |
| 339 | #endif | 340 | #endif |
| 340 | 341 | ||
| @@ -359,7 +360,8 @@ static void hns3_selftest_restore(struct net_device *ndev, bool if_running) · 18 unmodified lines | |||
| 359 | h->ae_algo->ops->halt_autoneg(h, false); | 360 | h->ae_algo->ops->halt_autoneg(h, false); |
| 360 | 361 | ||
| 361 | #if IS_ENABLED(CONFIG_VLAN_8021Q) | 362 | #if IS_ENABLED(CONFIG_VLAN_8021Q) |
| 362 | if (h->ae_algo->ops->enable_vlan_filter) | 363 | if (h->ae_algo->ops->enable_vlan_filter && |
| 364 | ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) | ||
| 363 | h->ae_algo->ops->enable_vlan_filter(h, true); | 365 | h->ae_algo->ops->enable_vlan_filter(h, true); |
| 364 | #endif | 366 | #endif |
| 365 | 367 | ||
| @@ -467,7 +467,7 @@ err_csq: · 466 unmodified lines | |||
| 467 | return ret; | 467 | return ret; |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | static int hclge_firmware_compat_config(struct hclge_dev *hdev) | 470 | static int hclge_firmware_compat_config(struct hclge_dev *hdev, bool en) |
| 471 | { | 471 | { |
| 472 | struct hclge_firmware_compat_cmd *req; | 472 | struct hclge_firmware_compat_cmd *req; |
| 473 | struct hclge_desc desc; | 473 | struct hclge_desc desc; |
| @@ -475,13 +475,16 @@ static int hclge_firmware_compat_config(struct hclge_dev *hdev) · 1 unmodified line | |||
| 475 | 475 | ||
| 476 | hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_IMP_COMPAT_CFG, false); | 476 | hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_IMP_COMPAT_CFG, false); |
| 477 | 477 | ||
| 478 | req = (struct hclge_firmware_compat_cmd *)desc.data; | 478 | if (en) { |
| 479 | req = (struct hclge_firmware_compat_cmd *)desc.data; | ||
| 479 | 480 | ||
| 480 | hnae3_set_bit(compat, HCLGE_LINK_EVENT_REPORT_EN_B, 1); | 481 | hnae3_set_bit(compat, HCLGE_LINK_EVENT_REPORT_EN_B, 1); |
| 481 | hnae3_set_bit(compat, HCLGE_NCSI_ERROR_REPORT_EN_B, 1); | 482 | hnae3_set_bit(compat, HCLGE_NCSI_ERROR_REPORT_EN_B, 1); |
| 482 | if (hnae3_dev_phy_imp_supported(hdev)) | 483 | if (hnae3_dev_phy_imp_supported(hdev)) |
| 483 | hnae3_set_bit(compat, HCLGE_PHY_IMP_EN_B, 1); | 484 | hnae3_set_bit(compat, HCLGE_PHY_IMP_EN_B, 1); |
| 484 | req->compat = cpu_to_le32(compat); | 485 | |
| 486 | req->compat = cpu_to_le32(compat); | ||
| 487 | } | ||
| 485 | 488 | ||
| 486 | return hclge_cmd_send(&hdev->hw, &desc, 1); | 489 | return hclge_cmd_send(&hdev->hw, &desc, 1); |
| 487 | } | 490 | } |
| @@ -538,7 +541,7 @@ int hclge_cmd_init(struct hclge_dev *hdev) · 50 unmodified lines | |||
| 538 | /* ask the firmware to enable some features, driver can work without | 541 | /* ask the firmware to enable some features, driver can work without |
| 539 | * it. | 542 | * it. |
| 540 | */ | 543 | */ |
| 541 | ret = hclge_firmware_compat_config(hdev); | 544 | ret = hclge_firmware_compat_config(hdev, true); |
| 542 | if (ret) | 545 | if (ret) |
| 543 | dev_warn(&hdev->pdev->dev, | 546 | dev_warn(&hdev->pdev->dev, |
| 544 | "Firmware compatible features not enabled(%d).\n", | 547 | "Firmware compatible features not enabled(%d).\n", |
| @@ -568,6 +571,8 @@ static void hclge_cmd_uninit_regs(struct hclge_hw *hw) · 23 unmodified lines | |||
| 568 | 571 | ||
| 569 | void hclge_cmd_uninit(struct hclge_dev *hdev) | 572 | void hclge_cmd_uninit(struct hclge_dev *hdev) |
| 570 | { | 573 | { |
| 574 | hclge_firmware_compat_config(hdev, false); | ||
| 575 | |||
| 571 | set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state); | 576 | set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state); |
| 572 | /* wait to ensure that the firmware completes the possible left | 577 | /* wait to ensure that the firmware completes the possible left |
| 573 | * over commands. | 578 | * over commands. |
| @@ -247,6 +247,10 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets) · 246 unmodified lines | |||
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | hclge_tm_schd_info_update(hdev, num_tc); | 249 | hclge_tm_schd_info_update(hdev, num_tc); |
| 250 | if (num_tc > 1) | ||
| 251 | hdev->flag |= HCLGE_FLAG_DCB_ENABLE; | ||
| 252 | else | ||
| 253 | hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; | ||
| 250 | 254 | ||
| 251 | ret = hclge_ieee_ets_to_tm_info(hdev, ets); | 255 | ret = hclge_ieee_ets_to_tm_info(hdev, ets); |
| 252 | if (ret) | 256 | if (ret) |
| @@ -306,8 +310,7 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc) · 53 unmodified lines | |||
| 306 | u8 i, j, pfc_map, *prio_tc; | 310 | u8 i, j, pfc_map, *prio_tc; |
| 307 | int ret; | 311 | int ret; |
| 308 | 312 | ||
| 309 | if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || | 313 | if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) |
| 310 | hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE) | ||
| 311 | return -EINVAL; | 314 | return -EINVAL; |
| 312 | 315 | ||
| 313 | if (pfc->pfc_en == hdev->tm_info.pfc_en) | 316 | if (pfc->pfc_en == hdev->tm_info.pfc_en) |
| @@ -441,8 +444,6 @@ static int hclge_mqprio_qopt_check(struct hclge_dev *hdev, · 127 unmodified lines | |||
| 441 | static void hclge_sync_mqprio_qopt(struct hnae3_tc_info *tc_info, | 444 | static void hclge_sync_mqprio_qopt(struct hnae3_tc_info *tc_info, |
| 442 | struct tc_mqprio_qopt_offload *mqprio_qopt) | 445 | struct tc_mqprio_qopt_offload *mqprio_qopt) |
| 443 | { | 446 | { |
| 444 | int i; | ||
| 445 | |||
| 446 | memset(tc_info, 0, sizeof(*tc_info)); | 447 | memset(tc_info, 0, sizeof(*tc_info)); |
| 447 | tc_info->num_tc = mqprio_qopt->qopt.num_tc; | 448 | tc_info->num_tc = mqprio_qopt->qopt.num_tc; |
| 448 | memcpy(tc_info->prio_tc, mqprio_qopt->qopt.prio_tc_map, | 449 | memcpy(tc_info->prio_tc, mqprio_qopt->qopt.prio_tc_map, |
| @@ -451,9 +452,6 @@ static void hclge_sync_mqprio_qopt(struct hnae3_tc_info *tc_info, · 2 unmodified lines | |||
| 451 | sizeof_field(struct hnae3_tc_info, tqp_count)); | 452 | sizeof_field(struct hnae3_tc_info, tqp_count)); |
| 452 | memcpy(tc_info->tqp_offset, mqprio_qopt->qopt.offset, | 453 | memcpy(tc_info->tqp_offset, mqprio_qopt->qopt.offset, |
| 453 | sizeof_field(struct hnae3_tc_info, tqp_offset)); | 454 | sizeof_field(struct hnae3_tc_info, tqp_offset)); |
| 454 | |||
| 455 | for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) | ||
| 456 | set_bit(tc_info->prio_tc[i], &tc_info->tc_en); | ||
| 457 | } | 455 | } |
| 458 | 456 | ||
| 459 | static int hclge_config_tc(struct hclge_dev *hdev, | 457 | static int hclge_config_tc(struct hclge_dev *hdev, |
| @@ -519,12 +517,17 @@ static int hclge_setup_tc(struct hnae3_handle *h, · 59 unmodified lines | |||
| 519 | return hclge_notify_init_up(hdev); | 517 | return hclge_notify_init_up(hdev); |
| 520 | 518 | ||
| 521 | err_out: | 519 | err_out: |
| 522 | /* roll-back */ | 520 | if (!tc) { |
| 523 | memcpy(&kinfo->tc_info, &old_tc_info, sizeof(old_tc_info)); | 521 | dev_warn(&hdev->pdev->dev, |
| 524 | if (hclge_config_tc(hdev, &kinfo->tc_info)) | 522 | "failed to destroy mqprio, will active after reset, ret = %d\n", |
| 525 | dev_err(&hdev->pdev->dev, | 523 | ret); |
| 526 | "failed to roll back tc configuration\n"); | 524 | } else { |
| 527 | 525 | /* roll-back */ | |
| 526 | memcpy(&kinfo->tc_info, &old_tc_info, sizeof(old_tc_info)); | ||
| 527 | if (hclge_config_tc(hdev, &kinfo->tc_info)) | ||
| 528 | dev_err(&hdev->pdev->dev, | ||
| 529 | "failed to roll back tc configuration\n"); | ||
| 530 | } | ||
| 528 | hclge_notify_init_up(hdev); | 531 | hclge_notify_init_up(hdev); |
| 529 | 532 | ||
| 530 | return ret; | 533 | return ret; |
| @@ -719,9 +719,9 @@ static void hclge_dbg_fill_shaper_content(struct hclge_tm_shaper_para *para, · 718 unmodified lines | |||
| 719 | sprintf(result[(*index)++], "%6u", para->rate); | 719 | sprintf(result[(*index)++], "%6u", para->rate); |
| 720 | } | 720 | } |
| 721 | 721 | ||
| 722 | static int hclge_dbg_dump_tm_pg(struct hclge_dev *hdev, char *buf, int len) | 722 | static int __hclge_dbg_dump_tm_pg(struct hclge_dev *hdev, char *data_str, |
| 723 | char *buf, int len) | ||
| 723 | { | 724 | { |
| 724 | char data_str[ARRAY_SIZE(tm_pg_items)][HCLGE_DBG_DATA_STR_LEN]; | ||
| 725 | struct hclge_tm_shaper_para c_shaper_para, p_shaper_para; | 725 | struct hclge_tm_shaper_para c_shaper_para, p_shaper_para; |
| 726 | char *result[ARRAY_SIZE(tm_pg_items)], *sch_mode_str; | 726 | char *result[ARRAY_SIZE(tm_pg_items)], *sch_mode_str; |
| 727 | u8 pg_id, sch_mode, weight, pri_bit_map, i, j; | 727 | u8 pg_id, sch_mode, weight, pri_bit_map, i, j; |
| @@ -729,8 +729,10 @@ static int hclge_dbg_dump_tm_pg(struct hclge_dev *hdev, char *buf, int len) · 1 unmodified line | |||
| 729 | int pos = 0; | 729 | int pos = 0; |
| 730 | int ret; | 730 | int ret; |
| 731 | 731 | ||
| 732 | for (i = 0; i < ARRAY_SIZE(tm_pg_items); i++) | 732 | for (i = 0; i < ARRAY_SIZE(tm_pg_items); i++) { |
| 733 | result[i] = &data_str[i][0]; | 733 | result[i] = data_str; |
| 734 | data_str += HCLGE_DBG_DATA_STR_LEN; | ||
| 735 | } | ||
| 734 | 736 | ||
| 735 | hclge_dbg_fill_content(content, sizeof(content), tm_pg_items, | 737 | hclge_dbg_fill_content(content, sizeof(content), tm_pg_items, |
| 736 | NULL, ARRAY_SIZE(tm_pg_items)); | 738 | NULL, ARRAY_SIZE(tm_pg_items)); |
| @@ -781,6 +783,24 @@ static int hclge_dbg_dump_tm_pg(struct hclge_dev *hdev, char *buf, int len) · 44 unmodified lines | |||
| 781 | return 0; | 783 | return 0; |
| 782 | } | 784 | } |
| 783 | 785 | ||
| 786 | static int hclge_dbg_dump_tm_pg(struct hclge_dev *hdev, char *buf, int len) | ||
| 787 | { | ||
| 788 | char *data_str; | ||
| 789 | int ret; | ||
| 790 | |||
| 791 | data_str = kcalloc(ARRAY_SIZE(tm_pg_items), | ||
| 792 | HCLGE_DBG_DATA_STR_LEN, GFP_KERNEL); | ||
| 793 | |||
| 794 | if (!data_str) | ||
| 795 | return -ENOMEM; | ||
| 796 | |||
| 797 | ret = __hclge_dbg_dump_tm_pg(hdev, data_str, buf, len); | ||
| 798 | |||
| 799 | kfree(data_str); | ||
| 800 | |||
| 801 | return ret; | ||
| 802 | } | ||
| 803 | |||
| 784 | static int hclge_dbg_dump_tm_port(struct hclge_dev *hdev, char *buf, int len) | 804 | static int hclge_dbg_dump_tm_port(struct hclge_dev *hdev, char *buf, int len) |
| 785 | { | 805 | { |
| 786 | struct hclge_tm_shaper_para shaper_para; | 806 | struct hclge_tm_shaper_para shaper_para; |
| @@ -8708,15 +8708,8 @@ int hclge_add_uc_addr_common(struct hclge_vport *vport, · 8707 unmodified lines | |||
| 8708 | } | 8708 | } |
| 8709 | 8709 | ||
| 8710 | /* check if we just hit the duplicate */ | 8710 | /* check if we just hit the duplicate */ |
| 8711 | if (!ret) { | 8711 | if (!ret) |
| 8712 | dev_warn(&hdev->pdev->dev, "VF %u mac(%pM) exists\n", | 8712 | return -EEXIST; |
| 8713 | vport->vport_id, addr); | ||
| 8714 | return 0; | ||
| 8715 | } | ||
| 8716 | |||
| 8717 | dev_err(&hdev->pdev->dev, | ||
| 8718 | "PF failed to add unicast entry(%pM) in the MAC table\n", | ||
| 8719 | addr); | ||
| 8720 | 8713 | ||
| 8721 | return ret; | 8714 | return ret; |
| 8722 | } | 8715 | } |
| @@ -8868,7 +8861,13 @@ static void hclge_sync_vport_mac_list(struct hclge_vport *vport, · 145 unmodified lines | |||
| 8868 | } else { | 8861 | } else { |
| 8869 | set_bit(HCLGE_VPORT_STATE_MAC_TBL_CHANGE, | 8862 | set_bit(HCLGE_VPORT_STATE_MAC_TBL_CHANGE, |
| 8870 | &vport->state); | 8863 | &vport->state); |
| 8871 | break; | 8864 | |
| 8865 | /* If one unicast mac address is existing in hardware, | ||
| 8866 | * we need to try whether other unicast mac addresses | ||
| 8867 | * are new addresses that can be added. | ||
| 8868 | */ | ||
| 8869 | if (ret != -EEXIST) | ||
| 8870 | break; | ||
| 8872 | } | 8871 | } |
| 8873 | } | 8872 | } |
| 8874 | } | 8873 | } |
| @@ -12797,8 +12796,12 @@ static void hclge_sync_promisc_mode(struct hclge_dev *hdev) · 3922 unmodified lines | |||
| 12797 | continue; | 12796 | continue; |
| 12798 | 12797 | ||
| 12799 | if (vport->vf_info.trusted) { | 12798 | if (vport->vf_info.trusted) { |
| 12800 | uc_en = vport->vf_info.request_uc_en > 0; | 12799 | uc_en = vport->vf_info.request_uc_en > 0 || |
| 12801 | mc_en = vport->vf_info.request_mc_en > 0; | 12800 | vport->overflow_promisc_flags & |
| 12801 | HNAE3_OVERFLOW_UPE; | ||
| 12802 | mc_en = vport->vf_info.request_mc_en > 0 || | ||
| 12803 | vport->overflow_promisc_flags & | ||
| 12804 | HNAE3_OVERFLOW_MPE; | ||
| 12802 | } | 12805 | } |
| 12803 | bc_en = vport->vf_info.request_bc_en > 0; | 12806 | bc_en = vport->vf_info.request_bc_en > 0; |
| 12804 | 12807 | ||
| @@ -687,12 +687,10 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) · 686 unmodified lines | |||
| 687 | 687 | ||
| 688 | for (i = 0; i < HNAE3_MAX_TC; i++) { | 688 | for (i = 0; i < HNAE3_MAX_TC; i++) { |
| 689 | if (hdev->hw_tc_map & BIT(i) && i < kinfo->tc_info.num_tc) { | 689 | if (hdev->hw_tc_map & BIT(i) && i < kinfo->tc_info.num_tc) { |
| 690 | set_bit(i, &kinfo->tc_info.tc_en); | ||
| 691 | kinfo->tc_info.tqp_offset[i] = i * kinfo->rss_size; | 690 | kinfo->tc_info.tqp_offset[i] = i * kinfo->rss_size; |
| 692 | kinfo->tc_info.tqp_count[i] = kinfo->rss_size; | 691 | kinfo->tc_info.tqp_count[i] = kinfo->rss_size; |
| 693 | } else { | 692 | } else { |
| 694 | /* Set to default queue if TC is disable */ | 693 | /* Set to default queue if TC is disable */ |
| 695 | clear_bit(i, &kinfo->tc_info.tc_en); | ||
| 696 | kinfo->tc_info.tqp_offset[i] = 0; | 694 | kinfo->tc_info.tqp_offset[i] = 0; |
| 697 | kinfo->tc_info.tqp_count[i] = 1; | 695 | kinfo->tc_info.tqp_count[i] = 1; |
| 698 | } | 696 | } |
| @@ -729,14 +727,6 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev) · 30 unmodified lines | |||
| 729 | for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) | 727 | for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) |
| 730 | hdev->tm_info.prio_tc[i] = | 728 | hdev->tm_info.prio_tc[i] = |
| 731 | (i >= hdev->tm_info.num_tc) ? 0 : i; | 729 | (i >= hdev->tm_info.num_tc) ? 0 : i; |
| 732 | |||
| 733 | /* DCB is enabled if we have more than 1 TC or pfc_en is | ||
| 734 | * non-zero. | ||
| 735 | */ | ||
| 736 | if (hdev->tm_info.num_tc > 1 || hdev->tm_info.pfc_en) | ||
| 737 | hdev->flag |= HCLGE_FLAG_DCB_ENABLE; | ||
| 738 | else | ||
| 739 | hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; | ||
| 740 | } | 730 | } |
| 741 | 731 | ||
| 742 | static void hclge_tm_pg_info_init(struct hclge_dev *hdev) | 732 | static void hclge_tm_pg_info_init(struct hclge_dev *hdev) |
| @@ -767,10 +757,10 @@ static void hclge_tm_pg_info_init(struct hclge_dev *hdev) · 24 unmodified lines | |||
| 767 | 757 | ||
| 768 | static void hclge_update_fc_mode_by_dcb_flag(struct hclge_dev *hdev) | 758 | static void hclge_update_fc_mode_by_dcb_flag(struct hclge_dev *hdev) |
| 769 | { | 759 | { |
| 770 | if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) { | 760 | if (hdev->tm_info.num_tc == 1 && !hdev->tm_info.pfc_en) { |
| 771 | if (hdev->fc_mode_last_time == HCLGE_FC_PFC) | 761 | if (hdev->fc_mode_last_time == HCLGE_FC_PFC) |
| 772 | dev_warn(&hdev->pdev->dev, | 762 | dev_warn(&hdev->pdev->dev, |
| 773 | "DCB is disable, but last mode is FC_PFC\n"); | 763 | "Only 1 tc used, but last mode is FC_PFC\n"); |
| 774 | 764 | ||
| 775 | hdev->tm_info.fc_mode = hdev->fc_mode_last_time; | 765 | hdev->tm_info.fc_mode = hdev->fc_mode_last_time; |
| 776 | } else if (hdev->tm_info.fc_mode != HCLGE_FC_PFC) { | 766 | } else if (hdev->tm_info.fc_mode != HCLGE_FC_PFC) { |
| @@ -796,7 +786,7 @@ static void hclge_update_fc_mode(struct hclge_dev *hdev) · 19 unmodified lines | |||
| 796 | } | 786 | } |
| 797 | } | 787 | } |
| 798 | 788 | ||
| 799 | static void hclge_pfc_info_init(struct hclge_dev *hdev) | 789 | void hclge_tm_pfc_info_update(struct hclge_dev *hdev) |
| 800 | { | 790 | { |
| 801 | if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3) | 791 | if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3) |
| 802 | hclge_update_fc_mode(hdev); | 792 | hclge_update_fc_mode(hdev); |
| @@ -812,7 +802,7 @@ static void hclge_tm_schd_info_init(struct hclge_dev *hdev) · 9 unmodified lines | |||
| 812 | 802 | ||
| 813 | hclge_tm_vport_info_update(hdev); | 803 | hclge_tm_vport_info_update(hdev); |
| 814 | 804 | ||
| 815 | hclge_pfc_info_init(hdev); | 805 | hclge_tm_pfc_info_update(hdev); |
| 816 | } | 806 | } |
| 817 | 807 | ||
| 818 | static int hclge_tm_pg_to_pri_map(struct hclge_dev *hdev) | 808 | static int hclge_tm_pg_to_pri_map(struct hclge_dev *hdev) |
| @@ -1558,19 +1548,6 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc) · 739 unmodified lines | |||
| 1558 | hclge_tm_schd_info_init(hdev); | 1548 | hclge_tm_schd_info_init(hdev); |
| 1559 | } | 1549 | } |
| 1560 | 1550 | ||
| 1561 | void hclge_tm_pfc_info_update(struct hclge_dev *hdev) | ||
| 1562 | { | ||
| 1563 | /* DCB is enabled if we have more than 1 TC or pfc_en is | ||
| 1564 | * non-zero. | ||
| 1565 | */ | ||
| 1566 | if (hdev->tm_info.num_tc > 1 || hdev->tm_info.pfc_en) | ||
| 1567 | hdev->flag |= HCLGE_FLAG_DCB_ENABLE; | ||
| 1568 | else | ||
| 1569 | hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; | ||
| 1570 | |||
| 1571 | hclge_pfc_info_init(hdev); | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) | 1551 | int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) |
| 1575 | { | 1552 | { |
| 1576 | int ret; | 1553 | int ret; |
| @@ -1616,7 +1593,7 @@ int hclge_tm_vport_map_update(struct hclge_dev *hdev) · 39 unmodified lines | |||
| 1616 | if (ret) | 1593 | if (ret) |
| 1617 | return ret; | 1594 | return ret; |
| 1618 | 1595 | ||
| 1619 | if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) | 1596 | if (hdev->tm_info.num_tc == 1 && !hdev->tm_info.pfc_en) |
| 1620 | return 0; | 1597 | return 0; |
| 1621 | 1598 | ||
| 1622 | return hclge_tm_bp_setup(hdev); | 1599 | return hclge_tm_bp_setup(hdev); |
| @@ -354,7 +354,7 @@ static int hns_mdio_reset(struct mii_bus *bus) · 353 unmodified lines | |||
| 354 | 354 | ||
| 355 | if (dev_of_node(bus->parent)) { | 355 | if (dev_of_node(bus->parent)) { |
| 356 | if (!mdio_dev->subctrl_vbase) { | 356 | if (!mdio_dev->subctrl_vbase) { |
| 357 | dev_err(&bus->dev, "mdio sys ctl reg has not maped\n"); | 357 | dev_err(&bus->dev, "mdio sys ctl reg has not mapped\n"); |
| 358 | return -ENODEV; | 358 | return -ENODEV; |
| 359 | } | 359 | } |
| 360 | 360 | ||
| @@ -4708,14 +4708,6 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, · 4707 unmodified lines | |||
| 4708 | return 0; | 4708 | return 0; |
| 4709 | } | 4709 | } |
| 4710 | 4710 | ||
| 4711 | if (adapter->failover_pending) { | ||
| 4712 | adapter->init_done_rc = -EAGAIN; | ||
| 4713 | netdev_dbg(netdev, "Failover pending, ignoring login response\n"); | ||
| 4714 | complete(&adapter->init_done); | ||
| 4715 | /* login response buffer will be released on reset */ | ||
| 4716 | return 0; | ||
| 4717 | } | ||
| 4718 | |||
| 4719 | netdev->mtu = adapter->req_mtu - ETH_HLEN; | 4711 | netdev->mtu = adapter->req_mtu - ETH_HLEN; |
| 4720 | 4712 | ||
| 4721 | netdev_dbg(adapter->netdev, "Login Response Buffer:\n"); | 4713 | netdev_dbg(adapter->netdev, "Login Response Buffer:\n"); |
| @@ -2437,11 +2437,15 @@ static void e100_get_drvinfo(struct net_device *netdev, · 2436 unmodified lines | |||
| 2437 | sizeof(info->bus_info)); | 2437 | sizeof(info->bus_info)); |
| 2438 | } | 2438 | } |
| 2439 | 2439 | ||
| 2440 | #define E100_PHY_REGS 0x1C | 2440 | #define E100_PHY_REGS 0x1D |
| 2441 | static int e100_get_regs_len(struct net_device *netdev) | 2441 | static int e100_get_regs_len(struct net_device *netdev) |
| 2442 | { | 2442 | { |
| 2443 | struct nic *nic = netdev_priv(netdev); | 2443 | struct nic *nic = netdev_priv(netdev); |
| 2444 | return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf); | 2444 | |
| 2445 | /* We know the number of registers, and the size of the dump buffer. | ||
| 2446 | * Calculate the total size in bytes. | ||
| 2447 | */ | ||
| 2448 | return (1 + E100_PHY_REGS) * sizeof(u32) + sizeof(nic->mem->dump_buf); | ||
| 2445 | } | 2449 | } |
| 2446 | 2450 | ||
| 2447 | static void e100_get_regs(struct net_device *netdev, | 2451 | static void e100_get_regs(struct net_device *netdev, |
| @@ -2455,14 +2459,18 @@ static void e100_get_regs(struct net_device *netdev, · 7 unmodified lines | |||
| 2455 | buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | | 2459 | buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | |
| 2456 | ioread8(&nic->csr->scb.cmd_lo) << 16 | | 2460 | ioread8(&nic->csr->scb.cmd_lo) << 16 | |
| 2457 | ioread16(&nic->csr->scb.status); | 2461 | ioread16(&nic->csr->scb.status); |
| 2458 | for (i = E100_PHY_REGS; i >= 0; i--) | 2462 | for (i = 0; i < E100_PHY_REGS; i++) |
| 2459 | buff[1 + E100_PHY_REGS - i] = | 2463 | /* Note that we read the registers in reverse order. This |
| 2460 | mdio_read(netdev, nic->mii.phy_id, i); | 2464 | * ordering is the ABI apparently used by ethtool and other |
| 2465 | * applications. | ||
| 2466 | */ | ||
| 2467 | buff[1 + i] = mdio_read(netdev, nic->mii.phy_id, | ||
| 2468 | E100_PHY_REGS - 1 - i); | ||
| 2461 | memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); | 2469 | memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); |
| 2462 | e100_exec_cb(nic, NULL, e100_dump); | 2470 | e100_exec_cb(nic, NULL, e100_dump); |
| 2463 | msleep(10); | 2471 | msleep(10); |
| 2464 | memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, | 2472 | memcpy(&buff[1 + E100_PHY_REGS], nic->mem->dump_buf, |
| 2465 | sizeof(nic->mem->dump_buf)); | 2473 | sizeof(nic->mem->dump_buf)); |
| 2466 | } | 2474 | } |
| 2467 | 2475 | ||
| 2468 | static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | 2476 | static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) |
| @@ -3208,7 +3208,7 @@ static unsigned int ixgbe_max_channels(struct ixgbe_adapter *adapter) · 3207 unmodified lines | |||
| 3208 | max_combined = ixgbe_max_rss_indices(adapter); | 3208 | max_combined = ixgbe_max_rss_indices(adapter); |
| 3209 | } | 3209 | } |
| 3210 | 3210 | ||
| 3211 | return max_combined; | 3211 | return min_t(int, max_combined, num_online_cpus()); |
| 3212 | } | 3212 | } |
| 3213 | 3213 | ||
| 3214 | static void ixgbe_get_channels(struct net_device *dev, | 3214 | static void ixgbe_get_channels(struct net_device *dev, |
| @@ -10112,6 +10112,7 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog) · 10111 unmodified lines | |||
| 10112 | struct ixgbe_adapter *adapter = netdev_priv(dev); | 10112 | struct ixgbe_adapter *adapter = netdev_priv(dev); |
| 10113 | struct bpf_prog *old_prog; | 10113 | struct bpf_prog *old_prog; |
| 10114 | bool need_reset; | 10114 | bool need_reset; |
| 10115 | int num_queues; | ||
| 10115 | 10116 | ||
| 10116 | if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) | 10117 | if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) |
| 10117 | return -EINVAL; | 10118 | return -EINVAL; |
| @@ -10161,11 +10162,14 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog) · 43 unmodified lines | |||
| 10161 | /* Kick start the NAPI context if there is an AF_XDP socket open | 10162 | /* Kick start the NAPI context if there is an AF_XDP socket open |
| 10162 | * on that queue id. This so that receiving will start. | 10163 | * on that queue id. This so that receiving will start. |
| 10163 | */ | 10164 | */ |
| 10164 | if (need_reset && prog) | 10165 | if (need_reset && prog) { |
| 10165 | for (i = 0; i < adapter->num_rx_queues; i++) | 10166 | num_queues = min_t(int, adapter->num_rx_queues, |
| 10167 | adapter->num_xdp_queues); | ||
| 10168 | for (i = 0; i < num_queues; i++) | ||
| 10166 | if (adapter->xdp_ring[i]->xsk_pool) | 10169 | if (adapter->xdp_ring[i]->xsk_pool) |
| 10167 | (void)ixgbe_xsk_wakeup(adapter->netdev, i, | 10170 | (void)ixgbe_xsk_wakeup(adapter->netdev, i, |
| 10168 | XDP_WAKEUP_RX); | 10171 | XDP_WAKEUP_RX); |
| 10172 | } | ||
| 10169 | 10173 | ||
| 10170 | return 0; | 10174 | return 0; |
| 10171 | } | 10175 | } |
| @@ -4,8 +4,6 @@ · 3 unmodified lines | |||
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_KS8842) += ks8842.o | 6 | obj-$(CONFIG_KS8842) += ks8842.o |
| 7 | obj-$(CONFIG_KS8851) += ks8851.o | 7 | obj-$(CONFIG_KS8851) += ks8851_common.o ks8851_spi.o |
| 8 | ks8851-objs = ks8851_common.o ks8851_spi.o | 8 | obj-$(CONFIG_KS8851_MLL) += ks8851_common.o ks8851_par.o |
| 9 | obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o | ||
| 10 | ks8851_mll-objs = ks8851_common.o ks8851_par.o | ||
| 11 | obj-$(CONFIG_KSZ884X_PCI) += ksz884x.o | 9 | obj-$(CONFIG_KSZ884X_PCI) += ksz884x.o |
| @@ -1057,6 +1057,7 @@ int ks8851_suspend(struct device *dev) · 1056 unmodified lines | |||
| 1057 | 1057 | ||
| 1058 | return 0; | 1058 | return 0; |
| 1059 | } | 1059 | } |
| 1060 | EXPORT_SYMBOL_GPL(ks8851_suspend); | ||
| 1060 | 1061 | ||
| 1061 | int ks8851_resume(struct device *dev) | 1062 | int ks8851_resume(struct device *dev) |
| 1062 | { | 1063 | { |
| @@ -1070,6 +1071,7 @@ int ks8851_resume(struct device *dev) · 7 unmodified lines | |||
| 1070 | 1071 | ||
| 1071 | return 0; | 1072 | return 0; |
| 1072 | } | 1073 | } |
| 1074 | EXPORT_SYMBOL_GPL(ks8851_resume); | ||
| 1073 | #endif | 1075 | #endif |
| 1074 | 1076 | ||
| 1075 | static int ks8851_register_mdiobus(struct ks8851_net *ks, struct device *dev) | 1077 | static int ks8851_register_mdiobus(struct ks8851_net *ks, struct device *dev) |
| @@ -1243,6 +1245,7 @@ err_reg: · 167 unmodified lines | |||
| 1243 | err_reg_io: | 1245 | err_reg_io: |
| 1244 | return ret; | 1246 | return ret; |
| 1245 | } | 1247 | } |
| 1248 | EXPORT_SYMBOL_GPL(ks8851_probe_common); | ||
| 1246 | 1249 | ||
| 1247 | int ks8851_remove_common(struct device *dev) | 1250 | int ks8851_remove_common(struct device *dev) |
| 1248 | { | 1251 | { |
| @@ -1261,3 +1264,8 @@ int ks8851_remove_common(struct device *dev) · 12 unmodified lines | |||
| 1261 | 1264 | ||
| 1262 | return 0; | 1265 | return 0; |
| 1263 | } | 1266 | } |
| 1267 | EXPORT_SYMBOL_GPL(ks8851_remove_common); | ||
| 1268 | |||
| 1269 | MODULE_DESCRIPTION("KS8851 Network driver"); | ||
| 1270 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
| 1271 | MODULE_LICENSE("GPL"); | ||
| @@ -380,15 +380,6 @@ static void ionic_sw_stats_get_txq_values(struct ionic_lif *lif, u64 **buf, · 379 unmodified lines | |||
| 380 | &ionic_dbg_intr_stats_desc[i]); | 380 | &ionic_dbg_intr_stats_desc[i]); |
| 381 | (*buf)++; | 381 | (*buf)++; |
| 382 | } | 382 | } |
| 383 | for (i = 0; i < IONIC_NUM_DBG_NAPI_STATS; i++) { | ||
| 384 | **buf = IONIC_READ_STAT64(&txqcq->napi_stats, | ||
| 385 | &ionic_dbg_napi_stats_desc[i]); | ||
| 386 | (*buf)++; | ||
| 387 | } | ||
| 388 | for (i = 0; i < IONIC_MAX_NUM_NAPI_CNTR; i++) { | ||
| 389 | **buf = txqcq->napi_stats.work_done_cntr[i]; | ||
| 390 | (*buf)++; | ||
| 391 | } | ||
| 392 | for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) { | 383 | for (i = 0; i < IONIC_MAX_NUM_SG_CNTR; i++) { |
| 393 | **buf = txstats->sg_cntr[i]; | 384 | **buf = txstats->sg_cntr[i]; |
| 394 | (*buf)++; | 385 | (*buf)++; |
| @@ -486,6 +486,10 @@ bool stmmac_eee_init(struct stmmac_priv *priv) · 485 unmodified lines | |||
| 486 | timer_setup(&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer, 0); | 486 | timer_setup(&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer, 0); |
| 487 | stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS, | 487 | stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS, |
| 488 | eee_tw_timer); | 488 | eee_tw_timer); |
| 489 | if (priv->hw->xpcs) | ||
| 490 | xpcs_config_eee(priv->hw->xpcs, | ||
| 491 | priv->plat->mult_fact_100ns, | ||
| 492 | true); | ||
| 489 | } | 493 | } |
| 490 | 494 | ||
| 491 | if (priv->plat->has_gmac4 && priv->tx_lpi_timer <= STMMAC_ET_MAX) { | 495 | if (priv->plat->has_gmac4 && priv->tx_lpi_timer <= STMMAC_ET_MAX) { |
| @@ -73,6 +73,7 @@ config CASSINI · 72 unmodified lines | |||
| 73 | config SUNVNET_COMMON | 73 | config SUNVNET_COMMON |
| 74 | tristate "Common routines to support Sun Virtual Networking" | 74 | tristate "Common routines to support Sun Virtual Networking" |
| 75 | depends on SUN_LDOMS | 75 | depends on SUN_LDOMS |
| 76 | depends on INET | ||
| 76 | default m | 77 | default m |
| 77 | 78 | ||
| 78 | config SUNVNET | 79 | config SUNVNET |
| @@ -48,6 +48,7 @@ config BPQETHER · 47 unmodified lines | |||
| 48 | config DMASCC | 48 | config DMASCC |
| 49 | tristate "High-speed (DMA) SCC driver for AX.25" | 49 | tristate "High-speed (DMA) SCC driver for AX.25" |
| 50 | depends on ISA && AX25 && BROKEN_ON_SMP && ISA_DMA_API | 50 | depends on ISA && AX25 && BROKEN_ON_SMP && ISA_DMA_API |
| 51 | depends on VIRT_TO_BUS | ||
| 51 | help | 52 | help |
| 52 | This is a driver for high-speed SCC boards, i.e. those supporting | 53 | This is a driver for high-speed SCC boards, i.e. those supporting |
| 53 | DMA on one port. You usually use those boards to connect your | 54 | DMA on one port. You usually use those boards to connect your |
| @@ -207,6 +207,7 @@ static int ipq4019_mdio_probe(struct platform_device *pdev) · 206 unmodified lines | |||
| 207 | { | 207 | { |
| 208 | struct ipq4019_mdio_data *priv; | 208 | struct ipq4019_mdio_data *priv; |
| 209 | struct mii_bus *bus; | 209 | struct mii_bus *bus; |
| 210 | struct resource *res; | ||
| 210 | int ret; | 211 | int ret; |
| 211 | 212 | ||
| 212 | bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); | 213 | bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); |
| @@ -224,7 +225,10 @@ static int ipq4019_mdio_probe(struct platform_device *pdev) · 11 unmodified lines | |||
| 224 | return PTR_ERR(priv->mdio_clk); | 225 | return PTR_ERR(priv->mdio_clk); |
| 225 | 226 | ||
| 226 | /* The platform resource is provided on the chipset IPQ5018 */ | 227 | /* The platform resource is provided on the chipset IPQ5018 */ |
| 227 | priv->eth_ldo_rdy = devm_platform_ioremap_resource(pdev, 1); | 228 | /* This resource is optional */ |
| 229 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 230 | if (res) | ||
| 231 | priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res); | ||
| 228 | 232 | ||
| 229 | bus->name = "ipq4019_mdio"; | 233 | bus->name = "ipq4019_mdio"; |
| 230 | bus->read = ipq4019_mdio_read; | 234 | bus->read = ipq4019_mdio_read; |
| @@ -134,8 +134,9 @@ static int mscc_miim_reset(struct mii_bus *bus) · 133 unmodified lines | |||
| 134 | 134 | ||
| 135 | static int mscc_miim_probe(struct platform_device *pdev) | 135 | static int mscc_miim_probe(struct platform_device *pdev) |
| 136 | { | 136 | { |
| 137 | struct mii_bus *bus; | ||
| 138 | struct mscc_miim_dev *dev; | 137 | struct mscc_miim_dev *dev; |
| 138 | struct resource *res; | ||
| 139 | struct mii_bus *bus; | ||
| 139 | int ret; | 140 | int ret; |
| 140 | 141 | ||
| 141 | bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*dev)); | 142 | bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*dev)); |
| @@ -156,10 +157,14 @@ static int mscc_miim_probe(struct platform_device *pdev) · 14 unmodified lines | |||
| 156 | return PTR_ERR(dev->regs); | 157 | return PTR_ERR(dev->regs); |
| 157 | } | 158 | } |
| 158 | 159 | ||
| 159 | dev->phy_regs = devm_platform_ioremap_resource(pdev, 1); | 160 | /* This resource is optional */ |
| 160 | if (IS_ERR(dev->phy_regs)) { | 161 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
| 161 | dev_err(&pdev->dev, "Unable to map internal phy registers\n"); | 162 | if (res) { |
| 162 | return PTR_ERR(dev->phy_regs); | 163 | dev->phy_regs = devm_ioremap_resource(&pdev->dev, res); |
| 164 | if (IS_ERR(dev->phy_regs)) { | ||
| 165 | dev_err(&pdev->dev, "Unable to map internal phy registers\n"); | ||
| 166 | return PTR_ERR(dev->phy_regs); | ||
| 167 | } | ||
| 163 | } | 168 | } |
| 164 | 169 | ||
| 165 | ret = of_mdiobus_register(bus, pdev->dev.of_node); | 170 | ret = of_mdiobus_register(bus, pdev->dev.of_node); |
| @@ -321,7 +321,7 @@ static int mhi_net_newlink(struct mhi_device *mhi_dev, struct net_device *ndev) · 320 unmodified lines | |||
| 321 | /* Start MHI channels */ | 321 | /* Start MHI channels */ |
| 322 | err = mhi_prepare_for_transfer(mhi_dev); | 322 | err = mhi_prepare_for_transfer(mhi_dev); |
| 323 | if (err) | 323 | if (err) |
| 324 | goto out_err; | 324 | return err; |
| 325 | 325 | ||
| 326 | /* Number of transfer descriptors determines size of the queue */ | 326 | /* Number of transfer descriptors determines size of the queue */ |
| 327 | mhi_netdev->rx_queue_sz = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE); | 327 | mhi_netdev->rx_queue_sz = mhi_get_free_desc_count(mhi_dev, DMA_FROM_DEVICE); |
| @@ -331,10 +331,6 @@ static int mhi_net_newlink(struct mhi_device *mhi_dev, struct net_device *ndev) · 3 unmodified lines | |||
| 331 | return err; | 331 | return err; |
| 332 | 332 | ||
| 333 | return 0; | 333 | return 0; |
| 334 | |||
| 335 | out_err: | ||
| 336 | free_netdev(ndev); | ||
| 337 | return err; | ||
| 338 | } | 334 | } |
| 339 | 335 | ||
| 340 | static void mhi_net_dellink(struct mhi_device *mhi_dev, struct net_device *ndev) | 336 | static void mhi_net_dellink(struct mhi_device *mhi_dev, struct net_device *ndev) |
| @@ -27,7 +27,12 @@ · 26 unmodified lines | |||
| 27 | #define MII_BCM7XXX_SHD_2_ADDR_CTRL 0xe | 27 | #define MII_BCM7XXX_SHD_2_ADDR_CTRL 0xe |
| 28 | #define MII_BCM7XXX_SHD_2_CTRL_STAT 0xf | 28 | #define MII_BCM7XXX_SHD_2_CTRL_STAT 0xf |
| 29 | #define MII_BCM7XXX_SHD_2_BIAS_TRIM 0x1a | 29 | #define MII_BCM7XXX_SHD_2_BIAS_TRIM 0x1a |
| 30 | #define MII_BCM7XXX_SHD_3_PCS_CTRL 0x0 | ||
| 31 | #define MII_BCM7XXX_SHD_3_PCS_STATUS 0x1 | ||
| 32 | #define MII_BCM7XXX_SHD_3_EEE_CAP 0x2 | ||
| 30 | #define MII_BCM7XXX_SHD_3_AN_EEE_ADV 0x3 | 33 | #define MII_BCM7XXX_SHD_3_AN_EEE_ADV 0x3 |
| 34 | #define MII_BCM7XXX_SHD_3_EEE_LP 0x4 | ||
| 35 | #define MII_BCM7XXX_SHD_3_EEE_WK_ERR 0x5 | ||
| 31 | #define MII_BCM7XXX_SHD_3_PCS_CTRL_2 0x6 | 36 | #define MII_BCM7XXX_SHD_3_PCS_CTRL_2 0x6 |
| 32 | #define MII_BCM7XXX_PCS_CTRL_2_DEF 0x4400 | 37 | #define MII_BCM7XXX_PCS_CTRL_2_DEF 0x4400 |
| 33 | #define MII_BCM7XXX_SHD_3_AN_STAT 0xb | 38 | #define MII_BCM7XXX_SHD_3_AN_STAT 0xb |
| @@ -216,25 +221,37 @@ static int bcm7xxx_28nm_resume(struct phy_device *phydev) · 182 unmodified lines | |||
| 216 | return genphy_config_aneg(phydev); | 221 | return genphy_config_aneg(phydev); |
| 217 | } | 222 | } |
| 218 | 223 | ||
| 219 | static int phy_set_clr_bits(struct phy_device *dev, int location, | 224 | static int __phy_set_clr_bits(struct phy_device *dev, int location, |
| 220 | int set_mask, int clr_mask) | 225 | int set_mask, int clr_mask) |
| 221 | { | 226 | { |
| 222 | int v, ret; | 227 | int v, ret; |
| 223 | 228 | ||
| 224 | v = phy_read(dev, location); | 229 | v = __phy_read(dev, location); |
| 225 | if (v < 0) | 230 | if (v < 0) |
| 226 | return v; | 231 | return v; |
| 227 | 232 | ||
| 228 | v &= ~clr_mask; | 233 | v &= ~clr_mask; |
| 229 | v |= set_mask; | 234 | v |= set_mask; |
| 230 | 235 | ||
| 231 | ret = phy_write(dev, location, v); | 236 | ret = __phy_write(dev, location, v); |
| 232 | if (ret < 0) | 237 | if (ret < 0) |
| 233 | return ret; | 238 | return ret; |
| 234 | 239 | ||
| 235 | return v; | 240 | return v; |
| 236 | } | 241 | } |
| 237 | 242 | ||
| 243 | static int phy_set_clr_bits(struct phy_device *dev, int location, | ||
| 244 | int set_mask, int clr_mask) | ||
| 245 | { | ||
| 246 | int ret; | ||
| 247 | |||
| 248 | mutex_lock(&dev->mdio.bus->mdio_lock); | ||
| 249 | ret = __phy_set_clr_bits(dev, location, set_mask, clr_mask); | ||
| 250 | mutex_unlock(&dev->mdio.bus->mdio_lock); | ||
| 251 | |||
| 252 | return ret; | ||
| 253 | } | ||
| 254 | |||
| 238 | static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev) | 255 | static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev) |
| 239 | { | 256 | { |
| 240 | int ret; | 257 | int ret; |
| @@ -398,6 +415,93 @@ static int bcm7xxx_28nm_ephy_config_init(struct phy_device *phydev) · 157 unmodified lines | |||
| 398 | return bcm7xxx_28nm_ephy_apd_enable(phydev); | 415 | return bcm7xxx_28nm_ephy_apd_enable(phydev); |
| 399 | } | 416 | } |
| 400 | 417 | ||
| 418 | #define MII_BCM7XXX_REG_INVALID 0xff | ||
| 419 | |||
| 420 | static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum) | ||
| 421 | { | ||
| 422 | switch (regnum) { | ||
| 423 | case MDIO_CTRL1: | ||
| 424 | return MII_BCM7XXX_SHD_3_PCS_CTRL; | ||
| 425 | case MDIO_STAT1: | ||
| 426 | return MII_BCM7XXX_SHD_3_PCS_STATUS; | ||
| 427 | case MDIO_PCS_EEE_ABLE: | ||
| 428 | return MII_BCM7XXX_SHD_3_EEE_CAP; | ||
| 429 | case MDIO_AN_EEE_ADV: | ||
| 430 | return MII_BCM7XXX_SHD_3_AN_EEE_ADV; | ||
| 431 | case MDIO_AN_EEE_LPABLE: | ||
| 432 | return MII_BCM7XXX_SHD_3_EEE_LP; | ||
| 433 | case MDIO_PCS_EEE_WK_ERR: | ||
| 434 | return MII_BCM7XXX_SHD_3_EEE_WK_ERR; | ||
| 435 | default: | ||
| 436 | return MII_BCM7XXX_REG_INVALID; | ||
| 437 | } | ||
| 438 | } | ||
| 439 | |||
| 440 | static bool bcm7xxx_28nm_ephy_dev_valid(int devnum) | ||
| 441 | { | ||
| 442 | return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS; | ||
| 443 | } | ||
| 444 | |||
| 445 | static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev, | ||
| 446 | int devnum, u16 regnum) | ||
| 447 | { | ||
| 448 | u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum); | ||
| 449 | int ret; | ||
| 450 | |||
| 451 | if (!bcm7xxx_28nm_ephy_dev_valid(devnum) || | ||
| 452 | shd == MII_BCM7XXX_REG_INVALID) | ||
| 453 | return -EOPNOTSUPP; | ||
| 454 | |||
| 455 | /* set shadow mode 2 */ | ||
| 456 | ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, | ||
| 457 | MII_BCM7XXX_SHD_MODE_2, 0); | ||
| 458 | if (ret < 0) | ||
| 459 | return ret; | ||
| 460 | |||
| 461 | /* Access the desired shadow register address */ | ||
| 462 | ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd); | ||
| 463 | if (ret < 0) | ||
| 464 | goto reset_shadow_mode; | ||
| 465 | |||
| 466 | ret = __phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT); | ||
| 467 | |||
| 468 | reset_shadow_mode: | ||
| 469 | /* reset shadow mode 2 */ | ||
| 470 | __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, | ||
| 471 | MII_BCM7XXX_SHD_MODE_2); | ||
| 472 | return ret; | ||
| 473 | } | ||
| 474 | |||
| 475 | static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev, | ||
| 476 | int devnum, u16 regnum, u16 val) | ||
| 477 | { | ||
| 478 | u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum); | ||
| 479 | int ret; | ||
| 480 | |||
| 481 | if (!bcm7xxx_28nm_ephy_dev_valid(devnum) || | ||
| 482 | shd == MII_BCM7XXX_REG_INVALID) | ||
| 483 | return -EOPNOTSUPP; | ||
| 484 | |||
| 485 | /* set shadow mode 2 */ | ||
| 486 | ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, | ||
| 487 | MII_BCM7XXX_SHD_MODE_2, 0); | ||
| 488 | if (ret < 0) | ||
| 489 | return ret; | ||
| 490 | |||
| 491 | /* Access the desired shadow register address */ | ||
| 492 | ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd); | ||
| 493 | if (ret < 0) | ||
| 494 | goto reset_shadow_mode; | ||
| 495 | |||
| 496 | /* Write the desired value in the shadow register */ | ||
| 497 | __phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val); | ||
| 498 | |||
| 499 | reset_shadow_mode: | ||
| 500 | /* reset shadow mode 2 */ | ||
| 501 | return __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0, | ||
| 502 | MII_BCM7XXX_SHD_MODE_2); | ||
| 503 | } | ||
| 504 | |||
| 401 | static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev) | 505 | static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev) |
| 402 | { | 506 | { |
| 403 | int ret; | 507 | int ret; |
| @@ -595,6 +699,8 @@ static void bcm7xxx_28nm_remove(struct phy_device *phydev) · 191 unmodified lines | |||
| 595 | .get_stats = bcm7xxx_28nm_get_phy_stats, \ | 699 | .get_stats = bcm7xxx_28nm_get_phy_stats, \ |
| 596 | .probe = bcm7xxx_28nm_probe, \ | 700 | .probe = bcm7xxx_28nm_probe, \ |
| 597 | .remove = bcm7xxx_28nm_remove, \ | 701 | .remove = bcm7xxx_28nm_remove, \ |
| 702 | .read_mmd = bcm7xxx_28nm_ephy_read_mmd, \ | ||
| 703 | .write_mmd = bcm7xxx_28nm_ephy_write_mmd, \ | ||
| 598 | } | 704 | } |
| 599 | 705 | ||
| 600 | #define BCM7XXX_40NM_EPHY(_oui, _name) \ | 706 | #define BCM7XXX_40NM_EPHY(_oui, _name) \ |
| @@ -525,6 +525,10 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) · 524 unmodified lines | |||
| 525 | NULL == bus->read || NULL == bus->write) | 525 | NULL == bus->read || NULL == bus->write) |
| 526 | return -EINVAL; | 526 | return -EINVAL; |
| 527 | 527 | ||
| 528 | if (bus->parent && bus->parent->of_node) | ||
| 529 | bus->parent->of_node->fwnode.flags |= | ||
| 530 | FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD; | ||
| 531 | |||
| 528 | BUG_ON(bus->state != MDIOBUS_ALLOCATED && | 532 | BUG_ON(bus->state != MDIOBUS_ALLOCATED && |
| 529 | bus->state != MDIOBUS_UNREGISTERED); | 533 | bus->state != MDIOBUS_UNREGISTERED); |
| 530 | 534 | ||
| @@ -537,6 +541,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) · 6 unmodified lines | |||
| 537 | err = device_register(&bus->dev); | 541 | err = device_register(&bus->dev); |
| 538 | if (err) { | 542 | if (err) { |
| 539 | pr_err("mii_bus %s failed to register\n", bus->id); | 543 | pr_err("mii_bus %s failed to register\n", bus->id); |
| 544 | put_device(&bus->dev); | ||
| 540 | return -EINVAL; | 545 | return -EINVAL; |
| 541 | } | 546 | } |
| 542 | 547 | ||
| @@ -493,6 +493,25 @@ static int gpy_loopback(struct phy_device *phydev, bool enable) · 492 unmodified lines | |||
| 493 | return ret; | 493 | return ret; |
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | static int gpy115_loopback(struct phy_device *phydev, bool enable) | ||
| 497 | { | ||
| 498 | int ret; | ||
| 499 | int fw_minor; | ||
| 500 | |||
| 501 | if (enable) | ||
| 502 | return gpy_loopback(phydev, enable); | ||
| 503 | |||
| 504 | ret = phy_read(phydev, PHY_FWV); | ||
| 505 | if (ret < 0) | ||
| 506 | return ret; | ||
| 507 | |||
| 508 | fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, ret); | ||
| 509 | if (fw_minor > 0x0076) | ||
| 510 | return gpy_loopback(phydev, 0); | ||
| 511 | |||
| 512 | return genphy_soft_reset(phydev); | ||
| 513 | } | ||
| 514 | |||
| 496 | static struct phy_driver gpy_drivers[] = { | 515 | static struct phy_driver gpy_drivers[] = { |
| 497 | { | 516 | { |
| 498 | PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx), | 517 | PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx), |
| @@ -527,7 +546,7 @@ static struct phy_driver gpy_drivers[] = { · 28 unmodified lines | |||
| 527 | .handle_interrupt = gpy_handle_interrupt, | 546 | .handle_interrupt = gpy_handle_interrupt, |
| 528 | .set_wol = gpy_set_wol, | 547 | .set_wol = gpy_set_wol, |
| 529 | .get_wol = gpy_get_wol, | 548 | .get_wol = gpy_get_wol, |
| 530 | .set_loopback = gpy_loopback, | 549 | .set_loopback = gpy115_loopback, |
| 531 | }, | 550 | }, |
| 532 | { | 551 | { |
| 533 | PHY_ID_MATCH_MODEL(PHY_ID_GPY115C), | 552 | PHY_ID_MATCH_MODEL(PHY_ID_GPY115C), |
| @@ -544,7 +563,7 @@ static struct phy_driver gpy_drivers[] = { · 10 unmodified lines | |||
| 544 | .handle_interrupt = gpy_handle_interrupt, | 563 | .handle_interrupt = gpy_handle_interrupt, |
| 545 | .set_wol = gpy_set_wol, | 564 | .set_wol = gpy_set_wol, |
| 546 | .get_wol = gpy_get_wol, | 565 | .get_wol = gpy_get_wol, |
| 547 | .set_loopback = gpy_loopback, | 566 | .set_loopback = gpy115_loopback, |
| 548 | }, | 567 | }, |
| 549 | { | 568 | { |
| 550 | .phy_id = PHY_ID_GPY211B, | 569 | .phy_id = PHY_ID_GPY211B, |
| @@ -1178,7 +1178,10 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) · 1177 unmodified lines | |||
| 1178 | 1178 | ||
| 1179 | static void smsc95xx_handle_link_change(struct net_device *net) | 1179 | static void smsc95xx_handle_link_change(struct net_device *net) |
| 1180 | { | 1180 | { |
| 1181 | struct usbnet *dev = netdev_priv(net); | ||
| 1182 | |||
| 1181 | phy_print_status(net->phydev); | 1183 | phy_print_status(net->phydev); |
| 1184 | usbnet_defer_kevent(dev, EVENT_LINK_CHANGE); | ||
| 1182 | } | 1185 | } |
| 1183 | 1186 | ||
| 1184 | static int smsc95xx_start_phy(struct usbnet *dev) | 1187 | static int smsc95xx_start_phy(struct usbnet *dev) |
| @@ -1867,8 +1867,8 @@ mac80211_hwsim_beacon(struct hrtimer *timer) · 1866 unmodified lines | |||
| 1867 | bcn_int -= data->bcn_delta; | 1867 | bcn_int -= data->bcn_delta; |
| 1868 | data->bcn_delta = 0; | 1868 | data->bcn_delta = 0; |
| 1869 | } | 1869 | } |
| 1870 | hrtimer_forward(&data->beacon_timer, hrtimer_get_expires(timer), | 1870 | hrtimer_forward_now(&data->beacon_timer, |
| 1871 | ns_to_ktime(bcn_int * NSEC_PER_USEC)); | 1871 | ns_to_ktime(bcn_int * NSEC_PER_USEC)); |
| 1872 | return HRTIMER_RESTART; | 1872 | return HRTIMER_RESTART; |
| 1873 | } | 1873 | } |
| 1874 | 1874 | ||
| @@ -380,7 +380,6 @@ static int pmem_attach_disk(struct device *dev, · 379 unmodified lines | |||
| 380 | struct nd_pfn_sb *pfn_sb; | 380 | struct nd_pfn_sb *pfn_sb; |
| 381 | struct pmem_device *pmem; | 381 | struct pmem_device *pmem; |
| 382 | struct request_queue *q; | 382 | struct request_queue *q; |
| 383 | struct device *gendev; | ||
| 384 | struct gendisk *disk; | 383 | struct gendisk *disk; |
| 385 | void *addr; | 384 | void *addr; |
| 386 | int rc; | 385 | int rc; |
| @@ -489,10 +488,8 @@ static int pmem_attach_disk(struct device *dev, · 102 unmodified lines | |||
| 489 | } | 488 | } |
| 490 | dax_write_cache(dax_dev, nvdimm_has_cache(nd_region)); | 489 | dax_write_cache(dax_dev, nvdimm_has_cache(nd_region)); |
| 491 | pmem->dax_dev = dax_dev; | 490 | pmem->dax_dev = dax_dev; |
| 492 | gendev = disk_to_dev(disk); | ||
| 493 | gendev->groups = pmem_attribute_groups; | ||
| 494 | 491 | ||
| 495 | device_add_disk(dev, disk, NULL); | 492 | device_add_disk(dev, disk, pmem_attribute_groups); |
| 496 | if (devm_add_action_or_reset(dev, pmem_release_disk, pmem)) | 493 | if (devm_add_action_or_reset(dev, pmem_release_disk, pmem)) |
| 497 | return -ENOMEM; | 494 | return -ENOMEM; |
| 498 | 495 | ||
| @@ -978,6 +978,7 @@ EXPORT_SYMBOL_GPL(nvme_cleanup_cmd); · 977 unmodified lines | |||
| 978 | blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req) | 978 | blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req) |
| 979 | { | 979 | { |
| 980 | struct nvme_command *cmd = nvme_req(req)->cmd; | 980 | struct nvme_command *cmd = nvme_req(req)->cmd; |
| 981 | struct nvme_ctrl *ctrl = nvme_req(req)->ctrl; | ||
| 981 | blk_status_t ret = BLK_STS_OK; | 982 | blk_status_t ret = BLK_STS_OK; |
| 982 | 983 | ||
| 983 | if (!(req->rq_flags & RQF_DONTPREP)) { | 984 | if (!(req->rq_flags & RQF_DONTPREP)) { |
| @@ -1026,7 +1027,8 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req) · 42 unmodified lines | |||
| 1026 | return BLK_STS_IOERR; | 1027 | return BLK_STS_IOERR; |
| 1027 | } | 1028 | } |
| 1028 | 1029 | ||
| 1029 | nvme_req(req)->genctr++; | 1030 | if (!(ctrl->quirks & NVME_QUIRK_SKIP_CID_GEN)) |
| 1031 | nvme_req(req)->genctr++; | ||
| 1030 | cmd->common.command_id = nvme_cid(req); | 1032 | cmd->common.command_id = nvme_cid(req); |
| 1031 | trace_nvme_setup_cmd(req, cmd); | 1033 | trace_nvme_setup_cmd(req, cmd); |
| 1032 | return ret; | 1034 | return ret; |
| @@ -138,6 +138,12 @@ enum nvme_quirks { · 137 unmodified lines | |||
| 138 | * 48 bits. | 138 | * 48 bits. |
| 139 | */ | 139 | */ |
| 140 | NVME_QUIRK_DMA_ADDRESS_BITS_48 = (1 << 16), | 140 | NVME_QUIRK_DMA_ADDRESS_BITS_48 = (1 << 16), |
| 141 | |||
| 142 | /* | ||
| 143 | * The controller requires the command_id value be be limited, so skip | ||
| 144 | * encoding the generation sequence number. | ||
| 145 | */ | ||
| 146 | NVME_QUIRK_SKIP_CID_GEN = (1 << 17), | ||
| 141 | }; | 147 | }; |
| 142 | 148 | ||
| 143 | /* | 149 | /* |
| @@ -3369,7 +3369,8 @@ static const struct pci_device_id nvme_id_table[] = { · 3368 unmodified lines | |||
| 3369 | { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005), | 3369 | { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005), |
| 3370 | .driver_data = NVME_QUIRK_SINGLE_VECTOR | | 3370 | .driver_data = NVME_QUIRK_SINGLE_VECTOR | |
| 3371 | NVME_QUIRK_128_BYTES_SQES | | 3371 | NVME_QUIRK_128_BYTES_SQES | |
| 3372 | NVME_QUIRK_SHARED_TAGS }, | 3372 | NVME_QUIRK_SHARED_TAGS | |
| 3373 | NVME_QUIRK_SKIP_CID_GEN }, | ||
| 3373 | 3374 | ||
| 3374 | { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, | 3375 | { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, |
| 3375 | { 0, } | 3376 | { 0, } |
| @@ -952,6 +952,8 @@ int armpmu_register(struct arm_pmu *pmu) · 951 unmodified lines | |||
| 952 | pmu->name, pmu->num_events, | 952 | pmu->name, pmu->num_events, |
| 953 | has_nmi ? ", using NMIs" : ""); | 953 | has_nmi ? ", using NMIs" : ""); |
| 954 | 954 | ||
| 955 | kvm_host_pmu_init(pmu); | ||
| 956 | |||
| 955 | return 0; | 957 | return 0; |
| 956 | 958 | ||
| 957 | out_destroy: | 959 | out_destroy: |
| @@ -2306,7 +2306,7 @@ EXPORT_SYMBOL_GPL(devm_pinctrl_register_and_init); · 2305 unmodified lines | |||
| 2306 | 2306 | ||
| 2307 | /** | 2307 | /** |
| 2308 | * devm_pinctrl_unregister() - Resource managed version of pinctrl_unregister(). | 2308 | * devm_pinctrl_unregister() - Resource managed version of pinctrl_unregister(). |
| 2309 | * @dev: device for which which resource was allocated | 2309 | * @dev: device for which resource was allocated |
| 2310 | * @pctldev: the pinctrl device to unregister. | 2310 | * @pctldev: the pinctrl device to unregister. |
| 2311 | */ | 2311 | */ |
| 2312 | void devm_pinctrl_unregister(struct device *dev, struct pinctrl_dev *pctldev) | 2312 | void devm_pinctrl_unregister(struct device *dev, struct pinctrl_dev *pctldev) |
| @@ -445,6 +445,7 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on) · 444 unmodified lines | |||
| 445 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | 445 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
| 446 | struct amd_gpio *gpio_dev = gpiochip_get_data(gc); | 446 | struct amd_gpio *gpio_dev = gpiochip_get_data(gc); |
| 447 | u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3); | 447 | u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3); |
| 448 | int err; | ||
| 448 | 449 | ||
| 449 | raw_spin_lock_irqsave(&gpio_dev->lock, flags); | 450 | raw_spin_lock_irqsave(&gpio_dev->lock, flags); |
| 450 | pin_reg = readl(gpio_dev->base + (d->hwirq)*4); | 451 | pin_reg = readl(gpio_dev->base + (d->hwirq)*4); |
| @@ -457,6 +458,15 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on) · 6 unmodified lines | |||
| 457 | writel(pin_reg, gpio_dev->base + (d->hwirq)*4); | 458 | writel(pin_reg, gpio_dev->base + (d->hwirq)*4); |
| 458 | raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); | 459 | raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); |
| 459 | 460 | ||
| 461 | if (on) | ||
| 462 | err = enable_irq_wake(gpio_dev->irq); | ||
| 463 | else | ||
| 464 | err = disable_irq_wake(gpio_dev->irq); | ||
| 465 | |||
| 466 | if (err) | ||
| 467 | dev_err(&gpio_dev->pdev->dev, "failed to %s wake-up interrupt\n", | ||
| 468 | on ? "enable" : "disable"); | ||
| 469 | |||
| 460 | return 0; | 470 | return 0; |
| 461 | } | 471 | } |
| 462 | 472 | ||
| @@ -902,7 +912,6 @@ static struct pinctrl_desc amd_pinctrl_desc = { · 439 unmodified lines | |||
| 902 | static int amd_gpio_probe(struct platform_device *pdev) | 912 | static int amd_gpio_probe(struct platform_device *pdev) |
| 903 | { | 913 | { |
| 904 | int ret = 0; | 914 | int ret = 0; |
| 905 | int irq_base; | ||
| 906 | struct resource *res; | 915 | struct resource *res; |
| 907 | struct amd_gpio *gpio_dev; | 916 | struct amd_gpio *gpio_dev; |
| 908 | struct gpio_irq_chip *girq; | 917 | struct gpio_irq_chip *girq; |
| @@ -925,9 +934,9 @@ static int amd_gpio_probe(struct platform_device *pdev) · 16 unmodified lines | |||
| 925 | if (!gpio_dev->base) | 934 | if (!gpio_dev->base) |
| 926 | return -ENOMEM; | 935 | return -ENOMEM; |
| 927 | 936 | ||
| 928 | irq_base = platform_get_irq(pdev, 0); | 937 | gpio_dev->irq = platform_get_irq(pdev, 0); |
| 929 | if (irq_base < 0) | 938 | if (gpio_dev->irq < 0) |
| 930 | return irq_base; | 939 | return gpio_dev->irq; |
| 931 | 940 | ||
| 932 | #ifdef CONFIG_PM_SLEEP | 941 | #ifdef CONFIG_PM_SLEEP |
| 933 | gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins, | 942 | gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins, |
| @@ -987,7 +996,7 @@ static int amd_gpio_probe(struct platform_device *pdev) · 53 unmodified lines | |||
| 987 | goto out2; | 996 | goto out2; |
| 988 | } | 997 | } |
| 989 | 998 | ||
| 990 | ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler, | 999 | ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler, |
| 991 | IRQF_SHARED, KBUILD_MODNAME, gpio_dev); | 1000 | IRQF_SHARED, KBUILD_MODNAME, gpio_dev); |
| 992 | if (ret) | 1001 | if (ret) |
| 993 | goto out2; | 1002 | goto out2; |
| @@ -98,6 +98,7 @@ struct amd_gpio { · 97 unmodified lines | |||
| 98 | struct resource *res; | 98 | struct resource *res; |
| 99 | struct platform_device *pdev; | 99 | struct platform_device *pdev; |
| 100 | u32 *saved_regs; | 100 | u32 *saved_regs; |
| 101 | int irq; | ||
| 101 | }; | 102 | }; |
| 102 | 103 | ||
| 103 | /* KERNCZ configuration*/ | 104 | /* KERNCZ configuration*/ |
| @@ -2092,6 +2092,23 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, · 2091 unmodified lines | |||
| 2092 | return false; | 2092 | return false; |
| 2093 | } | 2093 | } |
| 2094 | 2094 | ||
| 2095 | static int rockchip_pinconf_defer_output(struct rockchip_pin_bank *bank, | ||
| 2096 | unsigned int pin, u32 arg) | ||
| 2097 | { | ||
| 2098 | struct rockchip_pin_output_deferred *cfg; | ||
| 2099 | |||
| 2100 | cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); | ||
| 2101 | if (!cfg) | ||
| 2102 | return -ENOMEM; | ||
| 2103 | |||
| 2104 | cfg->pin = pin; | ||
| 2105 | cfg->arg = arg; | ||
| 2106 | |||
| 2107 | list_add_tail(&cfg->head, &bank->deferred_output); | ||
| 2108 | |||
| 2109 | return 0; | ||
| 2110 | } | ||
| 2111 | |||
| 2095 | /* set the pin config settings for a specified pin */ | 2112 | /* set the pin config settings for a specified pin */ |
| 2096 | static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, | 2113 | static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, |
| 2097 | unsigned long *configs, unsigned num_configs) | 2114 | unsigned long *configs, unsigned num_configs) |
| @@ -2136,6 +2153,22 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, · 38 unmodified lines | |||
| 2136 | if (rc != RK_FUNC_GPIO) | 2153 | if (rc != RK_FUNC_GPIO) |
| 2137 | return -EINVAL; | 2154 | return -EINVAL; |
| 2138 | 2155 | ||
| 2156 | /* | ||
| 2157 | * Check for gpio driver not being probed yet. | ||
| 2158 | * The lock makes sure that either gpio-probe has completed | ||
| 2159 | * or the gpio driver hasn't probed yet. | ||
| 2160 | */ | ||
| 2161 | mutex_lock(&bank->deferred_lock); | ||
| 2162 | if (!gpio || !gpio->direction_output) { | ||
| 2163 | rc = rockchip_pinconf_defer_output(bank, pin - bank->pin_base, arg); | ||
| 2164 | mutex_unlock(&bank->deferred_lock); | ||
| 2165 | if (rc) | ||
| 2166 | return rc; | ||
| 2167 | |||
| 2168 | break; | ||
| 2169 | } | ||
| 2170 | mutex_unlock(&bank->deferred_lock); | ||
| 2171 | |||
| 2139 | rc = gpio->direction_output(gpio, pin - bank->pin_base, | 2172 | rc = gpio->direction_output(gpio, pin - bank->pin_base, |
| 2140 | arg); | 2173 | arg); |
| 2141 | if (rc) | 2174 | if (rc) |
| @@ -2204,6 +2237,11 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, · 62 unmodified lines | |||
| 2204 | if (rc != RK_FUNC_GPIO) | 2237 | if (rc != RK_FUNC_GPIO) |
| 2205 | return -EINVAL; | 2238 | return -EINVAL; |
| 2206 | 2239 | ||
| 2240 | if (!gpio || !gpio->get) { | ||
| 2241 | arg = 0; | ||
| 2242 | break; | ||
| 2243 | } | ||
| 2244 | |||
| 2207 | rc = gpio->get(gpio, pin - bank->pin_base); | 2245 | rc = gpio->get(gpio, pin - bank->pin_base); |
| 2208 | if (rc < 0) | 2246 | if (rc < 0) |
| 2209 | return rc; | 2247 | return rc; |
| @@ -2450,6 +2488,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, · 240 unmodified lines | |||
| 2450 | pin_bank->name, pin); | 2488 | pin_bank->name, pin); |
| 2451 | pdesc++; | 2489 | pdesc++; |
| 2452 | } | 2490 | } |
| 2491 | |||
| 2492 | INIT_LIST_HEAD(&pin_bank->deferred_output); | ||
| 2493 | mutex_init(&pin_bank->deferred_lock); | ||
| 2453 | } | 2494 | } |
| 2454 | 2495 | ||
| 2455 | ret = rockchip_pinctrl_parse_dt(pdev, info); | 2496 | ret = rockchip_pinctrl_parse_dt(pdev, info); |
| @@ -2716,6 +2757,31 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) · 260 unmodified lines | |||
| 2716 | return 0; | 2757 | return 0; |
| 2717 | } | 2758 | } |
| 2718 | 2759 | ||
| 2760 | static int rockchip_pinctrl_remove(struct platform_device *pdev) | ||
| 2761 | { | ||
| 2762 | struct rockchip_pinctrl *info = platform_get_drvdata(pdev); | ||
| 2763 | struct rockchip_pin_bank *bank; | ||
| 2764 | struct rockchip_pin_output_deferred *cfg; | ||
| 2765 | int i; | ||
| 2766 | |||
| 2767 | of_platform_depopulate(&pdev->dev); | ||
| 2768 | |||
| 2769 | for (i = 0; i < info->ctrl->nr_banks; i++) { | ||
| 2770 | bank = &info->ctrl->pin_banks[i]; | ||
| 2771 | |||
| 2772 | mutex_lock(&bank->deferred_lock); | ||
| 2773 | while (!list_empty(&bank->deferred_output)) { | ||
| 2774 | cfg = list_first_entry(&bank->deferred_output, | ||
| 2775 | struct rockchip_pin_output_deferred, head); | ||
| 2776 | list_del(&cfg->head); | ||
| 2777 | kfree(cfg); | ||
| 2778 | } | ||
| 2779 | mutex_unlock(&bank->deferred_lock); | ||
| 2780 | } | ||
| 2781 | |||
| 2782 | return 0; | ||
| 2783 | } | ||
| 2784 | |||
| 2719 | static struct rockchip_pin_bank px30_pin_banks[] = { | 2785 | static struct rockchip_pin_bank px30_pin_banks[] = { |
| 2720 | PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU, | 2786 | PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU, |
| 2721 | IOMUX_SOURCE_PMU, | 2787 | IOMUX_SOURCE_PMU, |
| @@ -3175,6 +3241,7 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = { · 453 unmodified lines | |||
| 3175 | 3241 | ||
| 3176 | static struct platform_driver rockchip_pinctrl_driver = { | 3242 | static struct platform_driver rockchip_pinctrl_driver = { |
| 3177 | .probe = rockchip_pinctrl_probe, | 3243 | .probe = rockchip_pinctrl_probe, |
| 3244 | .remove = rockchip_pinctrl_remove, | ||
| 3178 | .driver = { | 3245 | .driver = { |
| 3179 | .name = "rockchip-pinctrl", | 3246 | .name = "rockchip-pinctrl", |
| 3180 | .pm = &rockchip_pinctrl_dev_pm_ops, | 3247 | .pm = &rockchip_pinctrl_dev_pm_ops, |
| @@ -141,6 +141,8 @@ struct rockchip_drv { · 140 unmodified lines | |||
| 141 | * @toggle_edge_mode: bit mask to toggle (falling/rising) edge mode | 141 | * @toggle_edge_mode: bit mask to toggle (falling/rising) edge mode |
| 142 | * @recalced_mask: bit mask to indicate a need to recalulate the mask | 142 | * @recalced_mask: bit mask to indicate a need to recalulate the mask |
| 143 | * @route_mask: bits describing the routing pins of per bank | 143 | * @route_mask: bits describing the routing pins of per bank |
| 144 | * @deferred_output: gpio output settings to be done after gpio bank probed | ||
| 145 | * @deferred_lock: mutex for the deferred_output shared btw gpio and pinctrl | ||
| 144 | */ | 146 | */ |
| 145 | struct rockchip_pin_bank { | 147 | struct rockchip_pin_bank { |
| 146 | struct device *dev; | 148 | struct device *dev; |
| @@ -169,6 +171,8 @@ struct rockchip_pin_bank { · 22 unmodified lines | |||
| 169 | u32 toggle_edge_mode; | 171 | u32 toggle_edge_mode; |
| 170 | u32 recalced_mask; | 172 | u32 recalced_mask; |
| 171 | u32 route_mask; | 173 | u32 route_mask; |
| 174 | struct list_head deferred_output; | ||
| 175 | struct mutex deferred_lock; | ||
| 172 | }; | 176 | }; |
| 173 | 177 | ||
| 174 | /** | 178 | /** |
| @@ -243,6 +247,12 @@ struct rockchip_pin_config { · 68 unmodified lines | |||
| 243 | unsigned int nconfigs; | 247 | unsigned int nconfigs; |
| 244 | }; | 248 | }; |
| 245 | 249 | ||
| 250 | struct rockchip_pin_output_deferred { | ||
| 251 | struct list_head head; | ||
| 252 | unsigned int pin; | ||
| 253 | u32 arg; | ||
| 254 | }; | ||
| 255 | |||
| 246 | /** | 256 | /** |
| 247 | * struct rockchip_pin_group: represent group of pins of a pinmux function. | 257 | * struct rockchip_pin_group: represent group of pins of a pinmux function. |
| 248 | * @name: name of the pin group, used to lookup the group. | 258 | * @name: name of the pin group, used to lookup the group. |
| @@ -1496,6 +1496,7 @@ static const struct of_device_id sc7280_pinctrl_of_match[] = { · 1495 unmodified lines | |||
| 1496 | static struct platform_driver sc7280_pinctrl_driver = { | 1496 | static struct platform_driver sc7280_pinctrl_driver = { |
| 1497 | .driver = { | 1497 | .driver = { |
| 1498 | .name = "sc7280-pinctrl", | 1498 | .name = "sc7280-pinctrl", |
| 1499 | .pm = &msm_pinctrl_dev_pm_ops, | ||
| 1499 | .of_match_table = sc7280_pinctrl_of_match, | 1500 | .of_match_table = sc7280_pinctrl_of_match, |
| 1500 | }, | 1501 | }, |
| 1501 | .probe = sc7280_pinctrl_probe, | 1502 | .probe = sc7280_pinctrl_probe, |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. | 3 | * Copyright (c) 2012-2014, 2016-2021 The Linux Foundation. All rights reserved. |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/gpio/driver.h> | 6 | #include <linux/gpio/driver.h> |
| @@ -14,6 +14,7 @@ · 7 unmodified lines | |||
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/regmap.h> | 15 | #include <linux/regmap.h> |
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | #include <linux/spmi.h> | ||
| 17 | #include <linux/types.h> | 18 | #include <linux/types.h> |
| 18 | 19 | ||
| 19 | #include <dt-bindings/pinctrl/qcom,pmic-gpio.h> | 20 | #include <dt-bindings/pinctrl/qcom,pmic-gpio.h> |
| @@ -171,6 +172,8 @@ struct pmic_gpio_state { · 151 unmodified lines | |||
| 171 | struct pinctrl_dev *ctrl; | 172 | struct pinctrl_dev *ctrl; |
| 172 | struct gpio_chip chip; | 173 | struct gpio_chip chip; |
| 173 | struct irq_chip irq; | 174 | struct irq_chip irq; |
| 175 | u8 usid; | ||
| 176 | u8 pid_base; | ||
| 174 | }; | 177 | }; |
| 175 | 178 | ||
| 176 | static const struct pinconf_generic_params pmic_gpio_bindings[] = { | 179 | static const struct pinconf_generic_params pmic_gpio_bindings[] = { |
| @@ -949,12 +952,36 @@ static int pmic_gpio_child_to_parent_hwirq(struct gpio_chip *chip, · 772 unmodified lines | |||
| 949 | unsigned int *parent_hwirq, | 952 | unsigned int *parent_hwirq, |
| 950 | unsigned int *parent_type) | 953 | unsigned int *parent_type) |
| 951 | { | 954 | { |
| 952 | *parent_hwirq = child_hwirq + 0xc0; | 955 | struct pmic_gpio_state *state = gpiochip_get_data(chip); |
| 956 | |||
| 957 | *parent_hwirq = child_hwirq + state->pid_base; | ||
| 953 | *parent_type = child_type; | 958 | *parent_type = child_type; |
| 954 | 959 | ||
| 955 | return 0; | 960 | return 0; |
| 956 | } | 961 | } |
| 957 | 962 | ||
| 963 | static void *pmic_gpio_populate_parent_fwspec(struct gpio_chip *chip, | ||
| 964 | unsigned int parent_hwirq, | ||
| 965 | unsigned int parent_type) | ||
| 966 | { | ||
| 967 | struct pmic_gpio_state *state = gpiochip_get_data(chip); | ||
| 968 | struct irq_fwspec *fwspec; | ||
| 969 | |||
| 970 | fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL); | ||
| 971 | if (!fwspec) | ||
| 972 | return NULL; | ||
| 973 | |||
| 974 | fwspec->fwnode = chip->irq.parent_domain->fwnode; | ||
| 975 | |||
| 976 | fwspec->param_count = 4; | ||
| 977 | fwspec->param[0] = state->usid; | ||
| 978 | fwspec->param[1] = parent_hwirq; | ||
| 979 | /* param[2] must be left as 0 */ | ||
| 980 | fwspec->param[3] = parent_type; | ||
| 981 | |||
| 982 | return fwspec; | ||
| 983 | } | ||
| 984 | |||
| 958 | static int pmic_gpio_probe(struct platform_device *pdev) | 985 | static int pmic_gpio_probe(struct platform_device *pdev) |
| 959 | { | 986 | { |
| 960 | struct irq_domain *parent_domain; | 987 | struct irq_domain *parent_domain; |
| @@ -965,6 +992,7 @@ static int pmic_gpio_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 965 | struct pmic_gpio_pad *pad, *pads; | 992 | struct pmic_gpio_pad *pad, *pads; |
| 966 | struct pmic_gpio_state *state; | 993 | struct pmic_gpio_state *state; |
| 967 | struct gpio_irq_chip *girq; | 994 | struct gpio_irq_chip *girq; |
| 995 | const struct spmi_device *parent_spmi_dev; | ||
| 968 | int ret, npins, i; | 996 | int ret, npins, i; |
| 969 | u32 reg; | 997 | u32 reg; |
| 970 | 998 | ||
| @@ -984,6 +1012,9 @@ static int pmic_gpio_probe(struct platform_device *pdev) · 13 unmodified lines | |||
| 984 | 1012 | ||
| 985 | state->dev = &pdev->dev; | 1013 | state->dev = &pdev->dev; |
| 986 | state->map = dev_get_regmap(dev->parent, NULL); | 1014 | state->map = dev_get_regmap(dev->parent, NULL); |
| 1015 | parent_spmi_dev = to_spmi_device(dev->parent); | ||
| 1016 | state->usid = parent_spmi_dev->usid; | ||
| 1017 | state->pid_base = reg >> 8; | ||
| 987 | 1018 | ||
| 988 | pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL); | 1019 | pindesc = devm_kcalloc(dev, npins, sizeof(*pindesc), GFP_KERNEL); |
| 989 | if (!pindesc) | 1020 | if (!pindesc) |
| @@ -1059,7 +1090,7 @@ static int pmic_gpio_probe(struct platform_device *pdev) · 69 unmodified lines | |||
| 1059 | girq->fwnode = of_node_to_fwnode(state->dev->of_node); | 1090 | girq->fwnode = of_node_to_fwnode(state->dev->of_node); |
| 1060 | girq->parent_domain = parent_domain; | 1091 | girq->parent_domain = parent_domain; |
| 1061 | girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq; | 1092 | girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq; |
| 1062 | girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell; | 1093 | girq->populate_parent_alloc_arg = pmic_gpio_populate_parent_fwspec; |
| 1063 | girq->child_offset_to_irq = pmic_gpio_child_offset_to_irq; | 1094 | girq->child_offset_to_irq = pmic_gpio_child_offset_to_irq; |
| 1064 | girq->child_irq_domain_ops.translate = pmic_gpio_domain_translate; | 1095 | girq->child_irq_domain_ops.translate = pmic_gpio_domain_translate; |
| 1065 | 1096 | ||
| @@ -15,8 +15,6 @@ · 14 unmodified lines | |||
| 15 | #include <linux/ptp_clock_kernel.h> | 15 | #include <linux/ptp_clock_kernel.h> |
| 16 | #include <linux/ptp_kvm.h> | 16 | #include <linux/ptp_kvm.h> |
| 17 | 17 | ||
| 18 | struct pvclock_vsyscall_time_info *hv_clock; | ||
| 19 | |||
| 20 | static phys_addr_t clock_pair_gpa; | 18 | static phys_addr_t clock_pair_gpa; |
| 21 | static struct kvm_clock_pairing clock_pair; | 19 | static struct kvm_clock_pairing clock_pair; |
| 22 | 20 | ||
| @@ -28,8 +26,7 @@ int kvm_arch_ptp_init(void) · 5 unmodified lines | |||
| 28 | return -ENODEV; | 26 | return -ENODEV; |
| 29 | 27 | ||
| 30 | clock_pair_gpa = slow_virt_to_phys(&clock_pair); | 28 | clock_pair_gpa = slow_virt_to_phys(&clock_pair); |
| 31 | hv_clock = pvclock_get_pvti_cpu0_va(); | 29 | if (!pvclock_get_pvti_cpu0_va()) |
| 32 | if (!hv_clock) | ||
| 33 | return -ENODEV; | 30 | return -ENODEV; |
| 34 | 31 | ||
| 35 | ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa, | 32 | ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa, |
| @@ -64,10 +61,8 @@ int kvm_arch_ptp_get_crosststamp(u64 *cycle, struct timespec64 *tspec, · 28 unmodified lines | |||
| 64 | struct pvclock_vcpu_time_info *src; | 61 | struct pvclock_vcpu_time_info *src; |
| 65 | unsigned int version; | 62 | unsigned int version; |
| 66 | long ret; | 63 | long ret; |
| 67 | int cpu; | ||
| 68 | 64 | ||
| 69 | cpu = smp_processor_id(); | 65 | src = this_cpu_pvti(); |
| 70 | src = &hv_clock[cpu].pvti; | ||
| 71 | 66 | ||
| 72 | do { | 67 | do { |
| 73 | /* | 68 | /* |
| @@ -262,10 +262,12 @@ static int blacklist_parse_proc_parameters(char *buf) · 261 unmodified lines | |||
| 262 | 262 | ||
| 263 | if (strcmp("free", parm) == 0) { | 263 | if (strcmp("free", parm) == 0) { |
| 264 | rc = blacklist_parse_parameters(buf, free, 0); | 264 | rc = blacklist_parse_parameters(buf, free, 0); |
| 265 | /* There could be subchannels without proper devices connected. | 265 | /* |
| 266 | * evaluate all the entries | 266 | * Evaluate the subchannels without an online device. This way, |
| 267 | * no path-verification will be triggered on those subchannels | ||
| 268 | * and it avoids unnecessary delays. | ||
| 267 | */ | 269 | */ |
| 268 | css_schedule_eval_all(); | 270 | css_schedule_eval_cond(CSS_EVAL_NOT_ONLINE, 0); |
| 269 | } else if (strcmp("add", parm) == 0) | 271 | } else if (strcmp("add", parm) == 0) |
| 270 | rc = blacklist_parse_parameters(buf, add, 0); | 272 | rc = blacklist_parse_parameters(buf, add, 0); |
| 271 | else if (strcmp("purge", parm) == 0) | 273 | else if (strcmp("purge", parm) == 0) |
| @@ -788,27 +788,49 @@ static int __unset_registered(struct device *dev, void *data) · 787 unmodified lines | |||
| 788 | return 0; | 788 | return 0; |
| 789 | } | 789 | } |
| 790 | 790 | ||
| 791 | void css_schedule_eval_all_unreg(unsigned long delay) | 791 | static int __unset_online(struct device *dev, void *data) |
| 792 | { | ||
| 793 | struct idset *set = data; | ||
| 794 | struct subchannel *sch = to_subchannel(dev); | ||
| 795 | struct ccw_device *cdev = sch_get_cdev(sch); | ||
| 796 | |||
| 797 | if (cdev && cdev->online) | ||
| 798 | idset_sch_del(set, sch->schid); | ||
| 799 | |||
| 800 | return 0; | ||
| 801 | } | ||
| 802 | |||
| 803 | void css_schedule_eval_cond(enum css_eval_cond cond, unsigned long delay) | ||
| 792 | { | 804 | { |
| 793 | unsigned long flags; | 805 | unsigned long flags; |
| 794 | struct idset *unreg_set; | 806 | struct idset *set; |
| 795 | 807 | ||
| 796 | /* Find unregistered subchannels. */ | 808 | /* Find unregistered subchannels. */ |
| 797 | unreg_set = idset_sch_new(); | 809 | set = idset_sch_new(); |
| 798 | if (!unreg_set) { | 810 | if (!set) { |
| 799 | /* Fallback. */ | 811 | /* Fallback. */ |
| 800 | css_schedule_eval_all(); | 812 | css_schedule_eval_all(); |
| 801 | return; | 813 | return; |
| 802 | } | 814 | } |
| 803 | idset_fill(unreg_set); | 815 | idset_fill(set); |
| 804 | bus_for_each_dev(&css_bus_type, NULL, unreg_set, __unset_registered); | 816 | switch (cond) { |
| 817 | case CSS_EVAL_UNREG: | ||
| 818 | bus_for_each_dev(&css_bus_type, NULL, set, __unset_registered); | ||
| 819 | break; | ||
| 820 | case CSS_EVAL_NOT_ONLINE: | ||
| 821 | bus_for_each_dev(&css_bus_type, NULL, set, __unset_online); | ||
| 822 | break; | ||
| 823 | default: | ||
| 824 | break; | ||
| 825 | } | ||
| 826 | |||
| 805 | /* Apply to slow_subchannel_set. */ | 827 | /* Apply to slow_subchannel_set. */ |
| 806 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 828 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
| 807 | idset_add_set(slow_subchannel_set, unreg_set); | 829 | idset_add_set(slow_subchannel_set, set); |
| 808 | atomic_set(&css_eval_scheduled, 1); | 830 | atomic_set(&css_eval_scheduled, 1); |
| 809 | queue_delayed_work(cio_work_q, &slow_path_work, delay); | 831 | queue_delayed_work(cio_work_q, &slow_path_work, delay); |
| 810 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 832 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
| 811 | idset_free(unreg_set); | 833 | idset_free(set); |
| 812 | } | 834 | } |
| 813 | 835 | ||
| 814 | void css_wait_for_slow_path(void) | 836 | void css_wait_for_slow_path(void) |
| @@ -820,7 +842,7 @@ void css_wait_for_slow_path(void) · 5 unmodified lines | |||
| 820 | void css_schedule_reprobe(void) | 842 | void css_schedule_reprobe(void) |
| 821 | { | 843 | { |
| 822 | /* Schedule with a delay to allow merging of subsequent calls. */ | 844 | /* Schedule with a delay to allow merging of subsequent calls. */ |
| 823 | css_schedule_eval_all_unreg(1 * HZ); | 845 | css_schedule_eval_cond(CSS_EVAL_UNREG, 1 * HZ); |
| 824 | } | 846 | } |
| 825 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); | 847 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); |
| 826 | 848 | ||
| @@ -34,6 +34,14 @@ · 33 unmodified lines | |||
| 34 | #define SNID_STATE3_MULTI_PATH 1 | 34 | #define SNID_STATE3_MULTI_PATH 1 |
| 35 | #define SNID_STATE3_SINGLE_PATH 0 | 35 | #define SNID_STATE3_SINGLE_PATH 0 |
| 36 | 36 | ||
| 37 | /* | ||
| 38 | * Conditions used to specify which subchannels need evaluation | ||
| 39 | */ | ||
| 40 | enum css_eval_cond { | ||
| 41 | CSS_EVAL_UNREG, /* unregistered subchannels */ | ||
| 42 | CSS_EVAL_NOT_ONLINE /* sch without an online-device */ | ||
| 43 | }; | ||
| 44 | |||
| 37 | struct path_state { | 45 | struct path_state { |
| 38 | __u8 state1 : 2; /* path state value 1 */ | 46 | __u8 state1 : 2; /* path state value 1 */ |
| 39 | __u8 state2 : 2; /* path state value 2 */ | 47 | __u8 state2 : 2; /* path state value 2 */ |
| @@ -136,7 +144,7 @@ static inline struct channel_subsystem *css_by_id(u8 cssid) · 96 unmodified lines | |||
| 136 | /* Helper functions to build lists for the slow path. */ | 144 | /* Helper functions to build lists for the slow path. */ |
| 137 | void css_schedule_eval(struct subchannel_id schid); | 145 | void css_schedule_eval(struct subchannel_id schid); |
| 138 | void css_schedule_eval_all(void); | 146 | void css_schedule_eval_all(void); |
| 139 | void css_schedule_eval_all_unreg(unsigned long delay); | 147 | void css_schedule_eval_cond(enum css_eval_cond, unsigned long delay); |
| 140 | int css_complete_work(void); | 148 | int css_complete_work(void); |
| 141 | 149 | ||
| 142 | int sch_is_pseudo_sch(struct subchannel *); | 150 | int sch_is_pseudo_sch(struct subchannel *); |
| @@ -361,6 +361,7 @@ err_list: · 360 unmodified lines | |||
| 361 | mutex_lock(&matrix_dev->lock); | 361 | mutex_lock(&matrix_dev->lock); |
| 362 | list_del(&matrix_mdev->node); | 362 | list_del(&matrix_mdev->node); |
| 363 | mutex_unlock(&matrix_dev->lock); | 363 | mutex_unlock(&matrix_dev->lock); |
| 364 | vfio_uninit_group_dev(&matrix_mdev->vdev); | ||
| 364 | kfree(matrix_mdev); | 365 | kfree(matrix_mdev); |
| 365 | err_dec_available: | 366 | err_dec_available: |
| 366 | atomic_inc(&matrix_dev->available_instances); | 367 | atomic_inc(&matrix_dev->available_instances); |
| @@ -376,9 +377,10 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev) · 9 unmodified lines | |||
| 376 | mutex_lock(&matrix_dev->lock); | 377 | mutex_lock(&matrix_dev->lock); |
| 377 | vfio_ap_mdev_reset_queues(matrix_mdev); | 378 | vfio_ap_mdev_reset_queues(matrix_mdev); |
| 378 | list_del(&matrix_mdev->node); | 379 | list_del(&matrix_mdev->node); |
| 380 | mutex_unlock(&matrix_dev->lock); | ||
| 381 | vfio_uninit_group_dev(&matrix_mdev->vdev); | ||
| 379 | kfree(matrix_mdev); | 382 | kfree(matrix_mdev); |
| 380 | atomic_inc(&matrix_dev->available_instances); | 383 | atomic_inc(&matrix_dev->available_instances); |
| 381 | mutex_unlock(&matrix_dev->lock); | ||
| 382 | } | 384 | } |
| 383 | 385 | ||
| 384 | static ssize_t name_show(struct mdev_type *mtype, | 386 | static ssize_t name_show(struct mdev_type *mtype, |
| @@ -1254,3 +1254,4 @@ MODULE_DEVICE_TABLE(pci, csio_pci_tbl); · 1253 unmodified lines | |||
| 1254 | MODULE_VERSION(CSIO_DRV_VERSION); | 1254 | MODULE_VERSION(CSIO_DRV_VERSION); |
| 1255 | MODULE_FIRMWARE(FW_FNAME_T5); | 1255 | MODULE_FIRMWARE(FW_FNAME_T5); |
| 1256 | MODULE_FIRMWARE(FW_FNAME_T6); | 1256 | MODULE_FIRMWARE(FW_FNAME_T6); |
| 1257 | MODULE_SOFTDEP("pre: cxgb4"); | ||
| @@ -2634,7 +2634,7 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, · 2633 unmodified lines | |||
| 2634 | } | 2634 | } |
| 2635 | 2635 | ||
| 2636 | if (unlikely(logit)) | 2636 | if (unlikely(logit)) |
| 2637 | ql_log(ql_log_warn, fcport->vha, 0x5060, | 2637 | ql_log(ql_dbg_io, fcport->vha, 0x5060, |
| 2638 | "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n", | 2638 | "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n", |
| 2639 | sp->name, sp->handle, comp_status, | 2639 | sp->name, sp->handle, comp_status, |
| 2640 | fd->transferred_length, le32_to_cpu(sts->residual_len), | 2640 | fd->transferred_length, le32_to_cpu(sts->residual_len), |
| @@ -3491,7 +3491,7 @@ check_scsi_status: · 850 unmodified lines | |||
| 3491 | 3491 | ||
| 3492 | out: | 3492 | out: |
| 3493 | if (logit) | 3493 | if (logit) |
| 3494 | ql_log(ql_log_warn, fcport->vha, 0x3022, | 3494 | ql_log(ql_dbg_io, fcport->vha, 0x3022, |
| 3495 | "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n", | 3495 | "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n", |
| 3496 | comp_status, scsi_status, res, vha->host_no, | 3496 | comp_status, scsi_status, res, vha->host_no, |
| 3497 | cp->device->id, cp->device->lun, fcport->d_id.b.domain, | 3497 | cp->device->id, cp->device->lun, fcport->d_id.b.domain, |
| @@ -118,7 +118,7 @@ static int ses_recv_diag(struct scsi_device *sdev, int page_code, · 117 unmodified lines | |||
| 118 | static int ses_send_diag(struct scsi_device *sdev, int page_code, | 118 | static int ses_send_diag(struct scsi_device *sdev, int page_code, |
| 119 | void *buf, int bufflen) | 119 | void *buf, int bufflen) |
| 120 | { | 120 | { |
| 121 | u32 result; | 121 | int result; |
| 122 | 122 | ||
| 123 | unsigned char cmd[] = { | 123 | unsigned char cmd[] = { |
| 124 | SEND_DIAGNOSTIC, | 124 | SEND_DIAGNOSTIC, |
| @@ -318,8 +318,7 @@ static void ufshcd_add_query_upiu_trace(struct ufs_hba *hba, · 317 unmodified lines | |||
| 318 | static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag, | 318 | static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag, |
| 319 | enum ufs_trace_str_t str_t) | 319 | enum ufs_trace_str_t str_t) |
| 320 | { | 320 | { |
| 321 | int off = (int)tag - hba->nutrs; | 321 | struct utp_task_req_desc *descp = &hba->utmrdl_base_addr[tag]; |
| 322 | struct utp_task_req_desc *descp = &hba->utmrdl_base_addr[off]; | ||
| 323 | 322 | ||
| 324 | if (!trace_ufshcd_upiu_enabled()) | 323 | if (!trace_ufshcd_upiu_enabled()) |
| 325 | return; | 324 | return; |
| @@ -300,7 +300,7 @@ static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, · 299 unmodified lines | |||
| 300 | } | 300 | } |
| 301 | break; | 301 | break; |
| 302 | default: | 302 | default: |
| 303 | pr_info("Unsupport virtio scsi event reason %x\n", event->reason); | 303 | pr_info("Unsupported virtio scsi event reason %x\n", event->reason); |
| 304 | } | 304 | } |
| 305 | } | 305 | } |
| 306 | 306 | ||
| @@ -392,7 +392,7 @@ static void virtscsi_handle_event(struct work_struct *work) · 85 unmodified lines | |||
| 392 | virtscsi_handle_param_change(vscsi, event); | 392 | virtscsi_handle_param_change(vscsi, event); |
| 393 | break; | 393 | break; |
| 394 | default: | 394 | default: |
| 395 | pr_err("Unsupport virtio scsi event %x\n", event->event); | 395 | pr_err("Unsupported virtio scsi event %x\n", event->event); |
| 396 | } | 396 | } |
| 397 | virtscsi_kick_event(vscsi, event_node); | 397 | virtscsi_kick_event(vscsi, event_node); |
| 398 | } | 398 | } |
| @@ -919,7 +919,7 @@ static int hantro_probe(struct platform_device *pdev) · 918 unmodified lines | |||
| 919 | if (!vpu->variant->irqs[i].handler) | 919 | if (!vpu->variant->irqs[i].handler) |
| 920 | continue; | 920 | continue; |
| 921 | 921 | ||
| 922 | if (vpu->variant->num_clocks > 1) { | 922 | if (vpu->variant->num_irqs > 1) { |
| 923 | irq_name = vpu->variant->irqs[i].name; | 923 | irq_name = vpu->variant->irqs[i].name; |
| 924 | irq = platform_get_irq_byname(vpu->pdev, irq_name); | 924 | irq = platform_get_irq_byname(vpu->pdev, irq_name); |
| 925 | } else { | 925 | } else { |
| @@ -135,7 +135,7 @@ void cedrus_prepare_format(struct v4l2_pix_format *pix_fmt) · 134 unmodified lines | |||
| 135 | sizeimage = bytesperline * height; | 135 | sizeimage = bytesperline * height; |
| 136 | 136 | ||
| 137 | /* Chroma plane size. */ | 137 | /* Chroma plane size. */ |
| 138 | sizeimage += bytesperline * height / 2; | 138 | sizeimage += bytesperline * ALIGN(height, 64) / 2; |
| 139 | 139 | ||
| 140 | break; | 140 | break; |
| 141 | 141 | ||
| @@ -1714,6 +1714,9 @@ static void mlx5_vdpa_set_vq_ready(struct vdpa_device *vdev, u16 idx, bool ready · 1713 unmodified lines | |||
| 1714 | struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); | 1714 | struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev); |
| 1715 | struct mlx5_vdpa_virtqueue *mvq; | 1715 | struct mlx5_vdpa_virtqueue *mvq; |
| 1716 | 1716 | ||
| 1717 | if (!mvdev->actual_features) | ||
| 1718 | return; | ||
| 1719 | |||
| 1717 | if (!is_index_valid(mvdev, idx)) | 1720 | if (!is_index_valid(mvdev, idx)) |
| 1718 | return; | 1721 | return; |
| 1719 | 1722 | ||
| @@ -2145,6 +2148,8 @@ static void clear_vqs_ready(struct mlx5_vdpa_net *ndev) · 425 unmodified lines | |||
| 2145 | 2148 | ||
| 2146 | for (i = 0; i < ndev->mvdev.max_vqs; i++) | 2149 | for (i = 0; i < ndev->mvdev.max_vqs; i++) |
| 2147 | ndev->vqs[i].ready = false; | 2150 | ndev->vqs[i].ready = false; |
| 2151 | |||
| 2152 | ndev->mvdev.cvq.ready = false; | ||
| 2148 | } | 2153 | } |
| 2149 | 2154 | ||
| 2150 | static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status) | 2155 | static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status) |
| @@ -665,13 +665,11 @@ static void vduse_vdpa_set_config(struct vdpa_device *vdpa, unsigned int offset, · 664 unmodified lines | |||
| 665 | static int vduse_vdpa_reset(struct vdpa_device *vdpa) | 665 | static int vduse_vdpa_reset(struct vdpa_device *vdpa) |
| 666 | { | 666 | { |
| 667 | struct vduse_dev *dev = vdpa_to_vduse(vdpa); | 667 | struct vduse_dev *dev = vdpa_to_vduse(vdpa); |
| 668 | 668 | int ret = vduse_dev_set_status(dev, 0); | |
| 669 | if (vduse_dev_set_status(dev, 0)) | ||
| 670 | return -EIO; | ||
| 671 | 669 | ||
| 672 | vduse_dev_reset(dev); | 670 | vduse_dev_reset(dev); |
| 673 | 671 | ||
| 674 | return 0; | 672 | return ret; |
| 675 | } | 673 | } |
| 676 | 674 | ||
| 677 | static u32 vduse_vdpa_get_generation(struct vdpa_device *vdpa) | 675 | static u32 vduse_vdpa_get_generation(struct vdpa_device *vdpa) |
| @@ -1593,8 +1591,10 @@ static int vduse_init(void) · 915 unmodified lines | |||
| 1593 | 1591 | ||
| 1594 | vduse_irq_wq = alloc_workqueue("vduse-irq", | 1592 | vduse_irq_wq = alloc_workqueue("vduse-irq", |
| 1595 | WQ_HIGHPRI | WQ_SYSFS | WQ_UNBOUND, 0); | 1593 | WQ_HIGHPRI | WQ_SYSFS | WQ_UNBOUND, 0); |
| 1596 | if (!vduse_irq_wq) | 1594 | if (!vduse_irq_wq) { |
| 1595 | ret = -ENOMEM; | ||
| 1597 | goto err_wq; | 1596 | goto err_wq; |
| 1597 | } | ||
| 1598 | 1598 | ||
| 1599 | ret = vduse_domain_init(); | 1599 | ret = vduse_domain_init(); |
| 1600 | if (ret) | 1600 | if (ret) |
| @@ -565,7 +565,7 @@ static bool vfio_pci_dev_below_slot(struct pci_dev *pdev, struct pci_slot *slot) · 564 unmodified lines | |||
| 565 | } | 565 | } |
| 566 | 566 | ||
| 567 | struct vfio_pci_walk_info { | 567 | struct vfio_pci_walk_info { |
| 568 | int (*fn)(struct pci_dev *, void *data); | 568 | int (*fn)(struct pci_dev *pdev, void *data); |
| 569 | void *data; | 569 | void *data; |
| 570 | struct pci_dev *pdev; | 570 | struct pci_dev *pdev; |
| 571 | bool slot; | 571 | bool slot; |
| @@ -640,7 +640,7 @@ static int vhost_vdpa_va_map(struct vhost_vdpa *v, · 639 unmodified lines | |||
| 640 | u64 offset, map_size, map_iova = iova; | 640 | u64 offset, map_size, map_iova = iova; |
| 641 | struct vdpa_map_file *map_file; | 641 | struct vdpa_map_file *map_file; |
| 642 | struct vm_area_struct *vma; | 642 | struct vm_area_struct *vma; |
| 643 | int ret; | 643 | int ret = 0; |
| 644 | 644 | ||
| 645 | mmap_read_lock(dev->mm); | 645 | mmap_read_lock(dev->mm); |
| 646 | 646 | ||
| @@ -345,8 +345,13 @@ static int virtio_device_of_init(struct virtio_device *dev) · 344 unmodified lines | |||
| 345 | ret = snprintf(compat, sizeof(compat), "virtio,device%x", dev->id.device); | 345 | ret = snprintf(compat, sizeof(compat), "virtio,device%x", dev->id.device); |
| 346 | BUG_ON(ret >= sizeof(compat)); | 346 | BUG_ON(ret >= sizeof(compat)); |
| 347 | 347 | ||
| 348 | /* | ||
| 349 | * On powerpc/pseries virtio devices are PCI devices so PCI | ||
| 350 | * vendor/device ids play the role of the "compatible" property. | ||
| 351 | * Simply don't init of_node in this case. | ||
| 352 | */ | ||
| 348 | if (!of_device_is_compatible(np, compat)) { | 353 | if (!of_device_is_compatible(np, compat)) { |
| 349 | ret = -EINVAL; | 354 | ret = 0; |
| 350 | goto out; | 355 | goto out; |
| 351 | } | 356 | } |
| 352 | 357 | ||
| @@ -1666,7 +1666,7 @@ config WDT_MTX1 · 1665 unmodified lines | |||
| 1666 | 1666 | ||
| 1667 | config SIBYTE_WDOG | 1667 | config SIBYTE_WDOG |
| 1668 | tristate "Sibyte SoC hardware watchdog" | 1668 | tristate "Sibyte SoC hardware watchdog" |
| 1669 | depends on CPU_SB1 || (MIPS && COMPILE_TEST) | 1669 | depends on CPU_SB1 |
| 1670 | help | 1670 | help |
| 1671 | Watchdog driver for the built in watchdog hardware in Sibyte | 1671 | Watchdog driver for the built in watchdog hardware in Sibyte |
| 1672 | SoC processors. There are apparently two watchdog timers | 1672 | SoC processors. There are apparently two watchdog timers |
| @@ -630,7 +630,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, · 629 unmodified lines | |||
| 630 | 630 | ||
| 631 | vaddr = eppnt->p_vaddr; | 631 | vaddr = eppnt->p_vaddr; |
| 632 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) | 632 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) |
| 633 | elf_type |= MAP_FIXED_NOREPLACE; | 633 | elf_type |= MAP_FIXED; |
| 634 | else if (no_base && interp_elf_ex->e_type == ET_DYN) | 634 | else if (no_base && interp_elf_ex->e_type == ET_DYN) |
| 635 | load_addr = -vaddr; | 635 | load_addr = -vaddr; |
| 636 | 636 | ||
| @@ -528,7 +528,7 @@ void debugfs_create_file_size(const char *name, umode_t mode, · 527 unmodified lines | |||
| 528 | { | 528 | { |
| 529 | struct dentry *de = debugfs_create_file(name, mode, parent, data, fops); | 529 | struct dentry *de = debugfs_create_file(name, mode, parent, data, fops); |
| 530 | 530 | ||
| 531 | if (de) | 531 | if (!IS_ERR(de)) |
| 532 | d_inode(de)->i_size = file_size; | 532 | d_inode(de)->i_size = file_size; |
| 533 | } | 533 | } |
| 534 | EXPORT_SYMBOL_GPL(debugfs_create_file_size); | 534 | EXPORT_SYMBOL_GPL(debugfs_create_file_size); |
| @@ -551,7 +551,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx) · 550 unmodified lines | |||
| 551 | struct dir_private_info *info = file->private_data; | 551 | struct dir_private_info *info = file->private_data; |
| 552 | struct inode *inode = file_inode(file); | 552 | struct inode *inode = file_inode(file); |
| 553 | struct fname *fname; | 553 | struct fname *fname; |
| 554 | int ret; | 554 | int ret = 0; |
| 555 | 555 | ||
| 556 | if (!info) { | 556 | if (!info) { |
| 557 | info = ext4_htree_create_dir_info(file, ctx->pos); | 557 | info = ext4_htree_create_dir_info(file, ctx->pos); |
| @@ -599,7 +599,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx) · 41 unmodified lines | |||
| 599 | info->curr_minor_hash, | 599 | info->curr_minor_hash, |
| 600 | &info->next_hash); | 600 | &info->next_hash); |
| 601 | if (ret < 0) | 601 | if (ret < 0) |
| 602 | return ret; | 602 | goto finished; |
| 603 | if (ret == 0) { | 603 | if (ret == 0) { |
| 604 | ctx->pos = ext4_get_htree_eof(file); | 604 | ctx->pos = ext4_get_htree_eof(file); |
| 605 | break; | 605 | break; |
| @@ -630,7 +630,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx) · 24 unmodified lines | |||
| 630 | } | 630 | } |
| 631 | finished: | 631 | finished: |
| 632 | info->last_pos = ctx->pos; | 632 | info->last_pos = ctx->pos; |
| 633 | return 0; | 633 | return ret < 0 ? ret : 0; |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | static int ext4_release_dir(struct inode *inode, struct file *filp) | 636 | static int ext4_release_dir(struct inode *inode, struct file *filp) |
| @@ -3593,9 +3593,6 @@ extern int ext4_da_write_inline_data_begin(struct address_space *mapping, · 3592 unmodified lines | |||
| 3593 | unsigned flags, | 3593 | unsigned flags, |
| 3594 | struct page **pagep, | 3594 | struct page **pagep, |
| 3595 | void **fsdata); | 3595 | void **fsdata); |
| 3596 | extern int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, | ||
| 3597 | unsigned len, unsigned copied, | ||
| 3598 | struct page *page); | ||
| 3599 | extern int ext4_try_add_inline_entry(handle_t *handle, | 3596 | extern int ext4_try_add_inline_entry(handle_t *handle, |
| 3600 | struct ext4_filename *fname, | 3597 | struct ext4_filename *fname, |
| 3601 | struct inode *dir, struct inode *inode); | 3598 | struct inode *dir, struct inode *inode); |
| @@ -5916,7 +5916,7 @@ void ext4_ext_replay_shrink_inode(struct inode *inode, ext4_lblk_t end) · 5915 unmodified lines | |||
| 5916 | } | 5916 | } |
| 5917 | 5917 | ||
| 5918 | /* Check if *cur is a hole and if it is, skip it */ | 5918 | /* Check if *cur is a hole and if it is, skip it */ |
| 5919 | static void skip_hole(struct inode *inode, ext4_lblk_t *cur) | 5919 | static int skip_hole(struct inode *inode, ext4_lblk_t *cur) |
| 5920 | { | 5920 | { |
| 5921 | int ret; | 5921 | int ret; |
| 5922 | struct ext4_map_blocks map; | 5922 | struct ext4_map_blocks map; |
| @@ -5925,9 +5925,12 @@ static void skip_hole(struct inode *inode, ext4_lblk_t *cur) · 2 unmodified lines | |||
| 5925 | map.m_len = ((inode->i_size) >> inode->i_sb->s_blocksize_bits) - *cur; | 5925 | map.m_len = ((inode->i_size) >> inode->i_sb->s_blocksize_bits) - *cur; |
| 5926 | 5926 | ||
| 5927 | ret = ext4_map_blocks(NULL, inode, &map, 0); | 5927 | ret = ext4_map_blocks(NULL, inode, &map, 0); |
| 5928 | if (ret < 0) | ||
| 5929 | return ret; | ||
| 5928 | if (ret != 0) | 5930 | if (ret != 0) |
| 5929 | return; | 5931 | return 0; |
| 5930 | *cur = *cur + map.m_len; | 5932 | *cur = *cur + map.m_len; |
| 5933 | return 0; | ||
| 5931 | } | 5934 | } |
| 5932 | 5935 | ||
| 5933 | /* Count number of blocks used by this inode and update i_blocks */ | 5936 | /* Count number of blocks used by this inode and update i_blocks */ |
| @@ -5976,7 +5979,9 @@ int ext4_ext_replay_set_iblocks(struct inode *inode) · 42 unmodified lines | |||
| 5976 | * iblocks by total number of differences found. | 5979 | * iblocks by total number of differences found. |
| 5977 | */ | 5980 | */ |
| 5978 | cur = 0; | 5981 | cur = 0; |
| 5979 | skip_hole(inode, &cur); | 5982 | ret = skip_hole(inode, &cur); |
| 5983 | if (ret < 0) | ||
| 5984 | goto out; | ||
| 5980 | path = ext4_find_extent(inode, cur, NULL, 0); | 5985 | path = ext4_find_extent(inode, cur, NULL, 0); |
| 5981 | if (IS_ERR(path)) | 5986 | if (IS_ERR(path)) |
| 5982 | goto out; | 5987 | goto out; |
| @@ -5995,8 +6000,12 @@ int ext4_ext_replay_set_iblocks(struct inode *inode) · 12 unmodified lines | |||
| 5995 | } | 6000 | } |
| 5996 | cur = max(cur + 1, le32_to_cpu(ex->ee_block) + | 6001 | cur = max(cur + 1, le32_to_cpu(ex->ee_block) + |
| 5997 | ext4_ext_get_actual_len(ex)); | 6002 | ext4_ext_get_actual_len(ex)); |
| 5998 | skip_hole(inode, &cur); | 6003 | ret = skip_hole(inode, &cur); |
| 5999 | 6004 | if (ret < 0) { | |
| 6005 | ext4_ext_drop_refs(path); | ||
| 6006 | kfree(path); | ||
| 6007 | break; | ||
| 6008 | } | ||
| 6000 | path2 = ext4_find_extent(inode, cur, NULL, 0); | 6009 | path2 = ext4_find_extent(inode, cur, NULL, 0); |
| 6001 | if (IS_ERR(path2)) { | 6010 | if (IS_ERR(path2)) { |
| 6002 | ext4_ext_drop_refs(path); | 6011 | ext4_ext_drop_refs(path); |
| @@ -892,6 +892,12 @@ static int ext4_fc_write_inode_data(struct inode *inode, u32 *crc) · 891 unmodified lines | |||
| 892 | sizeof(lrange), (u8 *)&lrange, crc)) | 892 | sizeof(lrange), (u8 *)&lrange, crc)) |
| 893 | return -ENOSPC; | 893 | return -ENOSPC; |
| 894 | } else { | 894 | } else { |
| 895 | unsigned int max = (map.m_flags & EXT4_MAP_UNWRITTEN) ? | ||
| 896 | EXT_UNWRITTEN_MAX_LEN : EXT_INIT_MAX_LEN; | ||
| 897 | |||
| 898 | /* Limit the number of blocks in one extent */ | ||
| 899 | map.m_len = min(max, map.m_len); | ||
| 900 | |||
| 895 | fc_ext.fc_ino = cpu_to_le32(inode->i_ino); | 901 | fc_ext.fc_ino = cpu_to_le32(inode->i_ino); |
| 896 | ex = (struct ext4_extent *)&fc_ext.fc_ex; | 902 | ex = (struct ext4_extent *)&fc_ext.fc_ex; |
| 897 | ex->ee_block = cpu_to_le32(map.m_lblk); | 903 | ex->ee_block = cpu_to_le32(map.m_lblk); |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/iomap.h> | 7 | #include <linux/iomap.h> |
| 8 | #include <linux/fiemap.h> | 8 | #include <linux/fiemap.h> |
| 9 | #include <linux/iversion.h> | 9 | #include <linux/iversion.h> |
| 10 | #include <linux/backing-dev.h> | ||
| 10 | 11 | ||
| 11 | #include "ext4_jbd2.h" | 12 | #include "ext4_jbd2.h" |
| 12 | #include "ext4.h" | 13 | #include "ext4.h" |
| @@ -733,45 +734,83 @@ convert: · 720 unmodified lines | |||
| 733 | int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, | 734 | int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, |
| 734 | unsigned copied, struct page *page) | 735 | unsigned copied, struct page *page) |
| 735 | { | 736 | { |
| 736 | int ret, no_expand; | 737 | handle_t *handle = ext4_journal_current_handle(); |
| 738 | int no_expand; | ||
| 737 | void *kaddr; | 739 | void *kaddr; |
| 738 | struct ext4_iloc iloc; | 740 | struct ext4_iloc iloc; |
| 741 | int ret = 0, ret2; | ||
| 742 | |||
| 743 | if (unlikely(copied < len) && !PageUptodate(page)) | ||
| 744 | copied = 0; | ||
| 739 | 745 | ||
| 740 | if (unlikely(copied < len)) { | 746 | if (likely(copied)) { |
| 741 | if (!PageUptodate(page)) { | 747 | ret = ext4_get_inode_loc(inode, &iloc); |
| 742 | copied = 0; | 748 | if (ret) { |
| 749 | unlock_page(page); | ||
| 750 | put_page(page); | ||
| 751 | ext4_std_error(inode->i_sb, ret); | ||
| 743 | goto out; | 752 | goto out; |
| 744 | } | 753 | } |
| 745 | } | 754 | ext4_write_lock_xattr(inode, &no_expand); |
| 755 | BUG_ON(!ext4_has_inline_data(inode)); | ||
| 746 | 756 | ||
| 747 | ret = ext4_get_inode_loc(inode, &iloc); | 757 | /* |
| 748 | if (ret) { | 758 | * ei->i_inline_off may have changed since |
| 749 | ext4_std_error(inode->i_sb, ret); | 759 | * ext4_write_begin() called |
| 750 | copied = 0; | 760 | * ext4_try_to_write_inline_data() |
| 751 | goto out; | 761 | */ |
| 752 | } | 762 | (void) ext4_find_inline_data_nolock(inode); |
| 753 | 763 | ||
| 754 | ext4_write_lock_xattr(inode, &no_expand); | 764 | kaddr = kmap_atomic(page); |
| 755 | BUG_ON(!ext4_has_inline_data(inode)); | 765 | ext4_write_inline_data(inode, &iloc, kaddr, pos, copied); |
| 766 | kunmap_atomic(kaddr); | ||
| 767 | SetPageUptodate(page); | ||
| 768 | /* clear page dirty so that writepages wouldn't work for us. */ | ||
| 769 | ClearPageDirty(page); | ||
| 756 | 770 | ||
| 757 | /* | 771 | ext4_write_unlock_xattr(inode, &no_expand); |
| 758 | * ei->i_inline_off may have changed since ext4_write_begin() | 772 | brelse(iloc.bh); |
| 759 | * called ext4_try_to_write_inline_data() | ||
| 760 | */ | ||
| 761 | (void) ext4_find_inline_data_nolock(inode); | ||
| 762 | 773 | ||
| 763 | kaddr = kmap_atomic(page); | 774 | /* |
| 764 | ext4_write_inline_data(inode, &iloc, kaddr, pos, len); | 775 | * It's important to update i_size while still holding page |
| 765 | kunmap_atomic(kaddr); | 776 | * lock: page writeout could otherwise come in and zero |
| 766 | SetPageUptodate(page); | 777 | * beyond i_size. |
| 767 | /* clear page dirty so that writepages wouldn't work for us. */ | 778 | */ |
| 768 | ClearPageDirty(page); | 779 | ext4_update_inode_size(inode, pos + copied); |
| 780 | } | ||
| 781 | unlock_page(page); | ||
| 782 | put_page(page); | ||
| 769 | 783 | ||
| 770 | ext4_write_unlock_xattr(inode, &no_expand); | 784 | /* |
| 771 | brelse(iloc.bh); | 785 | * Don't mark the inode dirty under page lock. First, it unnecessarily |
| 772 | mark_inode_dirty(inode); | 786 | * makes the holding time of page lock longer. Second, it forces lock |
| 787 | * ordering of page lock and transaction start for journaling | ||
| 788 | * filesystems. | ||
| 789 | */ | ||
| 790 | if (likely(copied)) | ||
| 791 | mark_inode_dirty(inode); | ||
| 773 | out: | 792 | out: |
| 774 | return copied; | 793 | /* |
| 794 | * If we didn't copy as much data as expected, we need to trim back | ||
| 795 | * size of xattr containing inline data. | ||
| 796 | */ | ||
| 797 | if (pos + len > inode->i_size && ext4_can_truncate(inode)) | ||
| 798 | ext4_orphan_add(handle, inode); | ||
| 799 | |||
| 800 | ret2 = ext4_journal_stop(handle); | ||
| 801 | if (!ret) | ||
| 802 | ret = ret2; | ||
| 803 | if (pos + len > inode->i_size) { | ||
| 804 | ext4_truncate_failed_write(inode); | ||
| 805 | /* | ||
| 806 | * If truncate failed early the inode might still be | ||
| 807 | * on the orphan list; we need to make sure the inode | ||
| 808 | * is removed from the orphan list in that case. | ||
| 809 | */ | ||
| 810 | if (inode->i_nlink) | ||
| 811 | ext4_orphan_del(NULL, inode); | ||
| 812 | } | ||
| 813 | return ret ? ret : copied; | ||
| 775 | } | 814 | } |
| 776 | 815 | ||
| 777 | struct buffer_head * | 816 | struct buffer_head * |
| @@ -953,43 +992,6 @@ out: · 175 unmodified lines | |||
| 953 | return ret; | 992 | return ret; |
| 954 | } | 993 | } |
| 955 | 994 | ||
| 956 | int ext4_da_write_inline_data_end(struct inode *inode, loff_t pos, | ||
| 957 | unsigned len, unsigned copied, | ||
| 958 | struct page *page) | ||
| 959 | { | ||
| 960 | int ret; | ||
| 961 | |||
| 962 | ret = ext4_write_inline_data_end(inode, pos, len, copied, page); | ||
| 963 | if (ret < 0) { | ||
| 964 | unlock_page(page); | ||
| 965 | put_page(page); | ||
| 966 | return ret; | ||
| 967 | } | ||
| 968 | copied = ret; | ||
| 969 | |||
| 970 | /* | ||
| 971 | * No need to use i_size_read() here, the i_size | ||
| 972 | * cannot change under us because we hold i_mutex. | ||
| 973 | * | ||
| 974 | * But it's important to update i_size while still holding page lock: | ||
| 975 | * page writeout could otherwise come in and zero beyond i_size. | ||
| 976 | */ | ||
| 977 | if (pos+copied > inode->i_size) | ||
| 978 | i_size_write(inode, pos+copied); | ||
| 979 | unlock_page(page); | ||
| 980 | put_page(page); | ||
| 981 | |||
| 982 | /* | ||
| 983 | * Don't mark the inode dirty under page lock. First, it unnecessarily | ||
| 984 | * makes the holding time of page lock longer. Second, it forces lock | ||
| 985 | * ordering of page lock and transaction start for journaling | ||
| 986 | * filesystems. | ||
| 987 | */ | ||
| 988 | mark_inode_dirty(inode); | ||
| 989 | |||
| 990 | return copied; | ||
| 991 | } | ||
| 992 | |||
| 993 | #ifdef INLINE_DIR_DEBUG | 995 | #ifdef INLINE_DIR_DEBUG |
| 994 | void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh, | 996 | void ext4_show_inline_dir(struct inode *dir, struct buffer_head *bh, |
| 995 | void *inline_start, int inline_size) | 997 | void *inline_start, int inline_size) |
| @@ -1917,6 +1919,24 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline) · 921 unmodified lines | |||
| 1917 | EXT4_I(inode)->i_disksize = i_size; | 1919 | EXT4_I(inode)->i_disksize = i_size; |
| 1918 | 1920 | ||
| 1919 | if (i_size < inline_size) { | 1921 | if (i_size < inline_size) { |
| 1922 | /* | ||
| 1923 | * if there's inline data to truncate and this file was | ||
| 1924 | * converted to extents after that inline data was written, | ||
| 1925 | * the extent status cache must be cleared to avoid leaving | ||
| 1926 | * behind stale delayed allocated extent entries | ||
| 1927 | */ | ||
| 1928 | if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { | ||
| 1929 | retry: | ||
| 1930 | err = ext4_es_remove_extent(inode, 0, EXT_MAX_BLOCKS); | ||
| 1931 | if (err == -ENOMEM) { | ||
| 1932 | cond_resched(); | ||
| 1933 | congestion_wait(BLK_RW_ASYNC, HZ/50); | ||
| 1934 | goto retry; | ||
| 1935 | } | ||
| 1936 | if (err) | ||
| 1937 | goto out_error; | ||
| 1938 | } | ||
| 1939 | |||
| 1920 | /* Clear the content in the xattr space. */ | 1940 | /* Clear the content in the xattr space. */ |
| 1921 | if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { | 1941 | if (inline_size > EXT4_MIN_INLINE_DATA_SIZE) { |
| 1922 | if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0) | 1942 | if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0) |
| @@ -1284,22 +1284,14 @@ static int ext4_write_end(struct file *file, · 1283 unmodified lines | |||
| 1284 | loff_t old_size = inode->i_size; | 1284 | loff_t old_size = inode->i_size; |
| 1285 | int ret = 0, ret2; | 1285 | int ret = 0, ret2; |
| 1286 | int i_size_changed = 0; | 1286 | int i_size_changed = 0; |
| 1287 | int inline_data = ext4_has_inline_data(inode); | ||
| 1288 | bool verity = ext4_verity_in_progress(inode); | 1287 | bool verity = ext4_verity_in_progress(inode); |
| 1289 | 1288 | ||
| 1290 | trace_ext4_write_end(inode, pos, len, copied); | 1289 | trace_ext4_write_end(inode, pos, len, copied); |
| 1291 | if (inline_data) { | 1290 | |
| 1292 | ret = ext4_write_inline_data_end(inode, pos, len, | 1291 | if (ext4_has_inline_data(inode)) |
| 1293 | copied, page); | 1292 | return ext4_write_inline_data_end(inode, pos, len, copied, page); |
| 1294 | if (ret < 0) { | 1293 | |
| 1295 | unlock_page(page); | 1294 | copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); |
| 1296 | put_page(page); | ||
| 1297 | goto errout; | ||
| 1298 | } | ||
| 1299 | copied = ret; | ||
| 1300 | } else | ||
| 1301 | copied = block_write_end(file, mapping, pos, | ||
| 1302 | len, copied, page, fsdata); | ||
| 1303 | /* | 1295 | /* |
| 1304 | * it's important to update i_size while still holding page lock: | 1296 | * it's important to update i_size while still holding page lock: |
| 1305 | * page writeout could otherwise come in and zero beyond i_size. | 1297 | * page writeout could otherwise come in and zero beyond i_size. |
| @@ -1320,7 +1312,7 @@ static int ext4_write_end(struct file *file, · 14 unmodified lines | |||
| 1320 | * ordering of page lock and transaction start for journaling | 1312 | * ordering of page lock and transaction start for journaling |
| 1321 | * filesystems. | 1313 | * filesystems. |
| 1322 | */ | 1314 | */ |
| 1323 | if (i_size_changed || inline_data) | 1315 | if (i_size_changed) |
| 1324 | ret = ext4_mark_inode_dirty(handle, inode); | 1316 | ret = ext4_mark_inode_dirty(handle, inode); |
| 1325 | 1317 | ||
| 1326 | if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode)) | 1318 | if (pos + len > inode->i_size && !verity && ext4_can_truncate(inode)) |
| @@ -1329,7 +1321,7 @@ static int ext4_write_end(struct file *file, · 2 unmodified lines | |||
| 1329 | * inode->i_size. So truncate them | 1321 | * inode->i_size. So truncate them |
| 1330 | */ | 1322 | */ |
| 1331 | ext4_orphan_add(handle, inode); | 1323 | ext4_orphan_add(handle, inode); |
| 1332 | errout: | 1324 | |
| 1333 | ret2 = ext4_journal_stop(handle); | 1325 | ret2 = ext4_journal_stop(handle); |
| 1334 | if (!ret) | 1326 | if (!ret) |
| 1335 | ret = ret2; | 1327 | ret = ret2; |
| @@ -1395,7 +1387,6 @@ static int ext4_journalled_write_end(struct file *file, · 59 unmodified lines | |||
| 1395 | int partial = 0; | 1387 | int partial = 0; |
| 1396 | unsigned from, to; | 1388 | unsigned from, to; |
| 1397 | int size_changed = 0; | 1389 | int size_changed = 0; |
| 1398 | int inline_data = ext4_has_inline_data(inode); | ||
| 1399 | bool verity = ext4_verity_in_progress(inode); | 1390 | bool verity = ext4_verity_in_progress(inode); |
| 1400 | 1391 | ||
| 1401 | trace_ext4_journalled_write_end(inode, pos, len, copied); | 1392 | trace_ext4_journalled_write_end(inode, pos, len, copied); |
| @@ -1404,16 +1395,10 @@ static int ext4_journalled_write_end(struct file *file, · 2 unmodified lines | |||
| 1404 | 1395 | ||
| 1405 | BUG_ON(!ext4_handle_valid(handle)); | 1396 | BUG_ON(!ext4_handle_valid(handle)); |
| 1406 | 1397 | ||
| 1407 | if (inline_data) { | 1398 | if (ext4_has_inline_data(inode)) |
| 1408 | ret = ext4_write_inline_data_end(inode, pos, len, | 1399 | return ext4_write_inline_data_end(inode, pos, len, copied, page); |
| 1409 | copied, page); | 1400 | |
| 1410 | if (ret < 0) { | 1401 | if (unlikely(copied < len) && !PageUptodate(page)) { |
| 1411 | unlock_page(page); | ||
| 1412 | put_page(page); | ||
| 1413 | goto errout; | ||
| 1414 | } | ||
| 1415 | copied = ret; | ||
| 1416 | } else if (unlikely(copied < len) && !PageUptodate(page)) { | ||
| 1417 | copied = 0; | 1402 | copied = 0; |
| 1418 | ext4_journalled_zero_new_buffers(handle, inode, page, from, to); | 1403 | ext4_journalled_zero_new_buffers(handle, inode, page, from, to); |
| 1419 | } else { | 1404 | } else { |
| @@ -1436,7 +1421,7 @@ static int ext4_journalled_write_end(struct file *file, · 16 unmodified lines | |||
| 1436 | if (old_size < pos && !verity) | 1421 | if (old_size < pos && !verity) |
| 1437 | pagecache_isize_extended(inode, old_size, pos); | 1422 | pagecache_isize_extended(inode, old_size, pos); |
| 1438 | 1423 | ||
| 1439 | if (size_changed || inline_data) { | 1424 | if (size_changed) { |
| 1440 | ret2 = ext4_mark_inode_dirty(handle, inode); | 1425 | ret2 = ext4_mark_inode_dirty(handle, inode); |
| 1441 | if (!ret) | 1426 | if (!ret) |
| 1442 | ret = ret2; | 1427 | ret = ret2; |
| @@ -1449,7 +1434,6 @@ static int ext4_journalled_write_end(struct file *file, · 6 unmodified lines | |||
| 1449 | */ | 1434 | */ |
| 1450 | ext4_orphan_add(handle, inode); | 1435 | ext4_orphan_add(handle, inode); |
| 1451 | 1436 | ||
| 1452 | errout: | ||
| 1453 | ret2 = ext4_journal_stop(handle); | 1437 | ret2 = ext4_journal_stop(handle); |
| 1454 | if (!ret) | 1438 | if (!ret) |
| 1455 | ret = ret2; | 1439 | ret = ret2; |
| @@ -1644,6 +1628,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) · 188 unmodified lines | |||
| 1644 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 1628 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
| 1645 | int ret; | 1629 | int ret; |
| 1646 | bool allocated = false; | 1630 | bool allocated = false; |
| 1631 | bool reserved = false; | ||
| 1647 | 1632 | ||
| 1648 | /* | 1633 | /* |
| 1649 | * If the cluster containing lblk is shared with a delayed, | 1634 | * If the cluster containing lblk is shared with a delayed, |
| @@ -1660,6 +1645,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) · 10 unmodified lines | |||
| 1660 | ret = ext4_da_reserve_space(inode); | 1645 | ret = ext4_da_reserve_space(inode); |
| 1661 | if (ret != 0) /* ENOSPC */ | 1646 | if (ret != 0) /* ENOSPC */ |
| 1662 | goto errout; | 1647 | goto errout; |
| 1648 | reserved = true; | ||
| 1663 | } else { /* bigalloc */ | 1649 | } else { /* bigalloc */ |
| 1664 | if (!ext4_es_scan_clu(inode, &ext4_es_is_delonly, lblk)) { | 1650 | if (!ext4_es_scan_clu(inode, &ext4_es_is_delonly, lblk)) { |
| 1665 | if (!ext4_es_scan_clu(inode, | 1651 | if (!ext4_es_scan_clu(inode, |
| @@ -1672,6 +1658,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) · 6 unmodified lines | |||
| 1672 | ret = ext4_da_reserve_space(inode); | 1658 | ret = ext4_da_reserve_space(inode); |
| 1673 | if (ret != 0) /* ENOSPC */ | 1659 | if (ret != 0) /* ENOSPC */ |
| 1674 | goto errout; | 1660 | goto errout; |
| 1661 | reserved = true; | ||
| 1675 | } else { | 1662 | } else { |
| 1676 | allocated = true; | 1663 | allocated = true; |
| 1677 | } | 1664 | } |
| @@ -1682,6 +1669,8 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) · 4 unmodified lines | |||
| 1682 | } | 1669 | } |
| 1683 | 1670 | ||
| 1684 | ret = ext4_es_insert_delayed_block(inode, lblk, allocated); | 1671 | ret = ext4_es_insert_delayed_block(inode, lblk, allocated); |
| 1672 | if (ret && reserved) | ||
| 1673 | ext4_da_release_space(inode, 1); | ||
| 1685 | 1674 | ||
| 1686 | errout: | 1675 | errout: |
| 1687 | return ret; | 1676 | return ret; |
| @@ -1722,13 +1711,16 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, · 34 unmodified lines | |||
| 1722 | } | 1711 | } |
| 1723 | 1712 | ||
| 1724 | /* | 1713 | /* |
| 1725 | * Delayed extent could be allocated by fallocate. | 1714 | * the buffer head associated with a delayed and not unwritten |
| 1726 | * So we need to check it. | 1715 | * block found in the extent status cache must contain an |
| 1716 | * invalid block number and have its BH_New and BH_Delay bits | ||
| 1717 | * set, reflecting the state assigned when the block was | ||
| 1718 | * initially delayed allocated | ||
| 1727 | */ | 1719 | */ |
| 1728 | if (ext4_es_is_delayed(&es) && !ext4_es_is_unwritten(&es)) { | 1720 | if (ext4_es_is_delonly(&es)) { |
| 1729 | map_bh(bh, inode->i_sb, invalid_block); | 1721 | BUG_ON(bh->b_blocknr != invalid_block); |
| 1730 | set_buffer_new(bh); | 1722 | BUG_ON(!buffer_new(bh)); |
| 1731 | set_buffer_delay(bh); | 1723 | BUG_ON(!buffer_delay(bh)); |
| 1732 | return 0; | 1724 | return 0; |
| 1733 | } | 1725 | } |
| 1734 | 1726 | ||
| @@ -2932,19 +2924,6 @@ static int ext4_nonda_switch(struct super_block *sb) · 1197 unmodified lines | |||
| 2932 | return 0; | 2924 | return 0; |
| 2933 | } | 2925 | } |
| 2934 | 2926 | ||
| 2935 | /* We always reserve for an inode update; the superblock could be there too */ | ||
| 2936 | static int ext4_da_write_credits(struct inode *inode, loff_t pos, unsigned len) | ||
| 2937 | { | ||
| 2938 | if (likely(ext4_has_feature_large_file(inode->i_sb))) | ||
| 2939 | return 1; | ||
| 2940 | |||
| 2941 | if (pos + len <= 0x7fffffffULL) | ||
| 2942 | return 1; | ||
| 2943 | |||
| 2944 | /* We might need to update the superblock to set LARGE_FILE */ | ||
| 2945 | return 2; | ||
| 2946 | } | ||
| 2947 | |||
| 2948 | static int ext4_da_write_begin(struct file *file, struct address_space *mapping, | 2927 | static int ext4_da_write_begin(struct file *file, struct address_space *mapping, |
| 2949 | loff_t pos, unsigned len, unsigned flags, | 2928 | loff_t pos, unsigned len, unsigned flags, |
| 2950 | struct page **pagep, void **fsdata) | 2929 | struct page **pagep, void **fsdata) |
| @@ -2953,7 +2932,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, · 2 unmodified lines | |||
| 2953 | struct page *page; | 2932 | struct page *page; |
| 2954 | pgoff_t index; | 2933 | pgoff_t index; |
| 2955 | struct inode *inode = mapping->host; | 2934 | struct inode *inode = mapping->host; |
| 2956 | handle_t *handle; | ||
| 2957 | 2935 | ||
| 2958 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) | 2936 | if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) |
| 2959 | return -EIO; | 2937 | return -EIO; |
| @@ -2979,41 +2957,11 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, · 19 unmodified lines | |||
| 2979 | return 0; | 2957 | return 0; |
| 2980 | } | 2958 | } |
| 2981 | 2959 | ||
| 2982 | /* | 2960 | retry: |
| 2983 | * grab_cache_page_write_begin() can take a long time if the | ||
| 2984 | * system is thrashing due to memory pressure, or if the page | ||
| 2985 | * is being written back. So grab it first before we start | ||
| 2986 | * the transaction handle. This also allows us to allocate | ||
| 2987 | * the page (if needed) without using GFP_NOFS. | ||
| 2988 | */ | ||
| 2989 | retry_grab: | ||
| 2990 | page = grab_cache_page_write_begin(mapping, index, flags); | 2961 | page = grab_cache_page_write_begin(mapping, index, flags); |
| 2991 | if (!page) | 2962 | if (!page) |
| 2992 | return -ENOMEM; | 2963 | return -ENOMEM; |
| 2993 | unlock_page(page); | ||
| 2994 | 2964 | ||
| 2995 | /* | ||
| 2996 | * With delayed allocation, we don't log the i_disksize update | ||
| 2997 | * if there is delayed block allocation. But we still need | ||
| 2998 | * to journalling the i_disksize update if writes to the end | ||
| 2999 | * of file which has an already mapped buffer. | ||
| 3000 | */ | ||
| 3001 | retry_journal: | ||
| 3002 | handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, | ||
| 3003 | ext4_da_write_credits(inode, pos, len)); | ||
| 3004 | if (IS_ERR(handle)) { | ||
| 3005 | put_page(page); | ||
| 3006 | return PTR_ERR(handle); | ||
| 3007 | } | ||
| 3008 | |||
| 3009 | lock_page(page); | ||
| 3010 | if (page->mapping != mapping) { | ||
| 3011 | /* The page got truncated from under us */ | ||
| 3012 | unlock_page(page); | ||
| 3013 | put_page(page); | ||
| 3014 | ext4_journal_stop(handle); | ||
| 3015 | goto retry_grab; | ||
| 3016 | } | ||
| 3017 | /* In case writeback began while the page was unlocked */ | 2965 | /* In case writeback began while the page was unlocked */ |
| 3018 | wait_for_stable_page(page); | 2966 | wait_for_stable_page(page); |
| 3019 | 2967 | ||
| @@ -3025,20 +2973,18 @@ retry_journal: · 5 unmodified lines | |||
| 3025 | #endif | 2973 | #endif |
| 3026 | if (ret < 0) { | 2974 | if (ret < 0) { |
| 3027 | unlock_page(page); | 2975 | unlock_page(page); |
| 3028 | ext4_journal_stop(handle); | 2976 | put_page(page); |
| 3029 | /* | 2977 | /* |
| 3030 | * block_write_begin may have instantiated a few blocks | 2978 | * block_write_begin may have instantiated a few blocks |
| 3031 | * outside i_size. Trim these off again. Don't need | 2979 | * outside i_size. Trim these off again. Don't need |
| 3032 | * i_size_read because we hold i_mutex. | 2980 | * i_size_read because we hold inode lock. |
| 3033 | */ | 2981 | */ |
| 3034 | if (pos + len > inode->i_size) | 2982 | if (pos + len > inode->i_size) |
| 3035 | ext4_truncate_failed_write(inode); | 2983 | ext4_truncate_failed_write(inode); |
| 3036 | 2984 | ||
| 3037 | if (ret == -ENOSPC && | 2985 | if (ret == -ENOSPC && |
| 3038 | ext4_should_retry_alloc(inode->i_sb, &retries)) | 2986 | ext4_should_retry_alloc(inode->i_sb, &retries)) |
| 3039 | goto retry_journal; | 2987 | goto retry; |
| 3040 | |||
| 3041 | put_page(page); | ||
| 3042 | return ret; | 2988 | return ret; |
| 3043 | } | 2989 | } |
| 3044 | 2990 | ||
| @@ -3075,8 +3021,6 @@ static int ext4_da_write_end(struct file *file, · 30 unmodified lines | |||
| 3075 | struct page *page, void *fsdata) | 3021 | struct page *page, void *fsdata) |
| 3076 | { | 3022 | { |
| 3077 | struct inode *inode = mapping->host; | 3023 | struct inode *inode = mapping->host; |
| 3078 | int ret = 0, ret2; | ||
| 3079 | handle_t *handle = ext4_journal_current_handle(); | ||
| 3080 | loff_t new_i_size; | 3024 | loff_t new_i_size; |
| 3081 | unsigned long start, end; | 3025 | unsigned long start, end; |
| 3082 | int write_mode = (int)(unsigned long)fsdata; | 3026 | int write_mode = (int)(unsigned long)fsdata; |
| @@ -3086,44 +3030,36 @@ static int ext4_da_write_end(struct file *file, · 3 unmodified lines | |||
| 3086 | len, copied, page, fsdata); | 3030 | len, copied, page, fsdata); |
| 3087 | 3031 | ||
| 3088 | trace_ext4_da_write_end(inode, pos, len, copied); | 3032 | trace_ext4_da_write_end(inode, pos, len, copied); |
| 3033 | |||
| 3034 | if (write_mode != CONVERT_INLINE_DATA && | ||
| 3035 | ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA) && | ||
| 3036 | ext4_has_inline_data(inode)) | ||
| 3037 | return ext4_write_inline_data_end(inode, pos, len, copied, page); | ||
| 3038 | |||
| 3089 | start = pos & (PAGE_SIZE - 1); | 3039 | start = pos & (PAGE_SIZE - 1); |
| 3090 | end = start + copied - 1; | 3040 | end = start + copied - 1; |
| 3091 | 3041 | ||
| 3092 | /* | 3042 | /* |
| 3093 | * generic_write_end() will run mark_inode_dirty() if i_size | 3043 | * Since we are holding inode lock, we are sure i_disksize <= |
| 3094 | * changes. So let's piggyback the i_disksize mark_inode_dirty | 3044 | * i_size. We also know that if i_disksize < i_size, there are |
| 3095 | * into that. | 3045 | * delalloc writes pending in the range upto i_size. If the end of |
| 3046 | * the current write is <= i_size, there's no need to touch | ||
| 3047 | * i_disksize since writeback will push i_disksize upto i_size | ||
| 3048 | * eventually. If the end of the current write is > i_size and | ||
| 3049 | * inside an allocated block (ext4_da_should_update_i_disksize() | ||
| 3050 | * check), we need to update i_disksize here as neither | ||
| 3051 | * ext4_writepage() nor certain ext4_writepages() paths not | ||
| 3052 | * allocating blocks update i_disksize. | ||
| 3053 | * | ||
| 3054 | * Note that we defer inode dirtying to generic_write_end() / | ||
| 3055 | * ext4_da_write_inline_data_end(). | ||
| 3096 | */ | 3056 | */ |
| 3097 | new_i_size = pos + copied; | 3057 | new_i_size = pos + copied; |
| 3098 | if (copied && new_i_size > EXT4_I(inode)->i_disksize) { | 3058 | if (copied && new_i_size > inode->i_size && |
| 3099 | if (ext4_has_inline_data(inode) || | 3059 | ext4_da_should_update_i_disksize(page, end)) |
| 3100 | ext4_da_should_update_i_disksize(page, end)) { | 3060 | ext4_update_i_disksize(inode, new_i_size); |
| 3101 | ext4_update_i_disksize(inode, new_i_size); | ||
| 3102 | /* We need to mark inode dirty even if | ||
| 3103 | * new_i_size is less that inode->i_size | ||
| 3104 | * bu greater than i_disksize.(hint delalloc) | ||
| 3105 | */ | ||
| 3106 | ret = ext4_mark_inode_dirty(handle, inode); | ||
| 3107 | } | ||
| 3108 | } | ||
| 3109 | 3061 | ||
| 3110 | if (write_mode != CONVERT_INLINE_DATA && | 3062 | return generic_write_end(file, mapping, pos, len, copied, page, fsdata); |
| 3111 | ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA) && | ||
| 3112 | ext4_has_inline_data(inode)) | ||
| 3113 | ret2 = ext4_da_write_inline_data_end(inode, pos, len, copied, | ||
| 3114 | page); | ||
| 3115 | else | ||
| 3116 | ret2 = generic_write_end(file, mapping, pos, len, copied, | ||
| 3117 | page, fsdata); | ||
| 3118 | |||
| 3119 | copied = ret2; | ||
| 3120 | if (ret2 < 0) | ||
| 3121 | ret = ret2; | ||
| 3122 | ret2 = ext4_journal_stop(handle); | ||
| 3123 | if (unlikely(ret2 && !ret)) | ||
| 3124 | ret = ret2; | ||
| 3125 | |||
| 3126 | return ret ? ret : copied; | ||
| 3127 | } | 3063 | } |
| 3128 | 3064 | ||
| 3129 | /* | 3065 | /* |
| @@ -4340,6 +4276,12 @@ static int __ext4_get_inode_loc(struct super_block *sb, unsigned long ino, · 1210 unmodified lines | |||
| 4340 | goto has_buffer; | 4276 | goto has_buffer; |
| 4341 | 4277 | ||
| 4342 | lock_buffer(bh); | 4278 | lock_buffer(bh); |
| 4279 | if (ext4_buffer_uptodate(bh)) { | ||
| 4280 | /* Someone brought it uptodate while we waited */ | ||
| 4281 | unlock_buffer(bh); | ||
| 4282 | goto has_buffer; | ||
| 4283 | } | ||
| 4284 | |||
| 4343 | /* | 4285 | /* |
| 4344 | * If we have all information of the inode in memory and this | 4286 | * If we have all information of the inode in memory and this |
| 4345 | * is the only valid inode in the block, we need not read the | 4287 | * is the only valid inode in the block, we need not read the |
| @@ -658,7 +658,7 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error, · 657 unmodified lines | |||
| 658 | * constraints, it may not be safe to do it right here so we | 658 | * constraints, it may not be safe to do it right here so we |
| 659 | * defer superblock flushing to a workqueue. | 659 | * defer superblock flushing to a workqueue. |
| 660 | */ | 660 | */ |
| 661 | if (continue_fs) | 661 | if (continue_fs && journal) |
| 662 | schedule_work(&EXT4_SB(sb)->s_error_work); | 662 | schedule_work(&EXT4_SB(sb)->s_error_work); |
| 663 | else | 663 | else |
| 664 | ext4_commit_super(sb); | 664 | ext4_commit_super(sb); |
| @@ -1350,6 +1350,12 @@ static void ext4_destroy_inode(struct inode *inode) · 685 unmodified lines | |||
| 1350 | true); | 1350 | true); |
| 1351 | dump_stack(); | 1351 | dump_stack(); |
| 1352 | } | 1352 | } |
| 1353 | |||
| 1354 | if (EXT4_I(inode)->i_reserved_data_blocks) | ||
| 1355 | ext4_msg(inode->i_sb, KERN_ERR, | ||
| 1356 | "Inode %lu (%p): i_reserved_data_blocks (%u) not cleared!", | ||
| 1357 | inode->i_ino, EXT4_I(inode), | ||
| 1358 | EXT4_I(inode)->i_reserved_data_blocks); | ||
| 1353 | } | 1359 | } |
| 1354 | 1360 | ||
| 1355 | static void init_once(void *foo) | 1361 | static void init_once(void *foo) |
| @@ -3021,17 +3027,17 @@ static loff_t ext4_max_size(int blkbits, int has_huge_files) · 1665 unmodified lines | |||
| 3021 | */ | 3027 | */ |
| 3022 | static loff_t ext4_max_bitmap_size(int bits, int has_huge_files) | 3028 | static loff_t ext4_max_bitmap_size(int bits, int has_huge_files) |
| 3023 | { | 3029 | { |
| 3024 | loff_t res = EXT4_NDIR_BLOCKS; | 3030 | unsigned long long upper_limit, res = EXT4_NDIR_BLOCKS; |
| 3025 | int meta_blocks; | 3031 | int meta_blocks; |
| 3026 | loff_t upper_limit; | 3032 | |
| 3027 | /* This is calculated to be the largest file size for a dense, block | 3033 | /* |
| 3034 | * This is calculated to be the largest file size for a dense, block | ||
| 3028 | * mapped file such that the file's total number of 512-byte sectors, | 3035 | * mapped file such that the file's total number of 512-byte sectors, |
| 3029 | * including data and all indirect blocks, does not exceed (2^48 - 1). | 3036 | * including data and all indirect blocks, does not exceed (2^48 - 1). |
| 3030 | * | 3037 | * |
| 3031 | * __u32 i_blocks_lo and _u16 i_blocks_high represent the total | 3038 | * __u32 i_blocks_lo and _u16 i_blocks_high represent the total |
| 3032 | * number of 512-byte sectors of the file. | 3039 | * number of 512-byte sectors of the file. |
| 3033 | */ | 3040 | */ |
| 3034 | |||
| 3035 | if (!has_huge_files) { | 3041 | if (!has_huge_files) { |
| 3036 | /* | 3042 | /* |
| 3037 | * !has_huge_files or implies that the inode i_block field | 3043 | * !has_huge_files or implies that the inode i_block field |
| @@ -3074,7 +3080,7 @@ static loff_t ext4_max_bitmap_size(int bits, int has_huge_files) · 36 unmodified lines | |||
| 3074 | if (res > MAX_LFS_FILESIZE) | 3080 | if (res > MAX_LFS_FILESIZE) |
| 3075 | res = MAX_LFS_FILESIZE; | 3081 | res = MAX_LFS_FILESIZE; |
| 3076 | 3082 | ||
| 3077 | return res; | 3083 | return (loff_t)res; |
| 3078 | } | 3084 | } |
| 3079 | 3085 | ||
| 3080 | static ext4_fsblk_t descriptor_loc(struct super_block *sb, | 3086 | static ext4_fsblk_t descriptor_loc(struct super_block *sb, |
| @@ -5042,12 +5048,15 @@ failed_mount_wq: · 1961 unmodified lines | |||
| 5042 | sbi->s_ea_block_cache = NULL; | 5048 | sbi->s_ea_block_cache = NULL; |
| 5043 | 5049 | ||
| 5044 | if (sbi->s_journal) { | 5050 | if (sbi->s_journal) { |
| 5051 | /* flush s_error_work before journal destroy. */ | ||
| 5052 | flush_work(&sbi->s_error_work); | ||
| 5045 | jbd2_journal_destroy(sbi->s_journal); | 5053 | jbd2_journal_destroy(sbi->s_journal); |
| 5046 | sbi->s_journal = NULL; | 5054 | sbi->s_journal = NULL; |
| 5047 | } | 5055 | } |
| 5048 | failed_mount3a: | 5056 | failed_mount3a: |
| 5049 | ext4_es_unregister_shrinker(sbi); | 5057 | ext4_es_unregister_shrinker(sbi); |
| 5050 | failed_mount3: | 5058 | failed_mount3: |
| 5059 | /* flush s_error_work before sbi destroy */ | ||
| 5051 | flush_work(&sbi->s_error_work); | 5060 | flush_work(&sbi->s_error_work); |
| 5052 | del_timer_sync(&sbi->s_err_report); | 5061 | del_timer_sync(&sbi->s_err_report); |
| 5053 | ext4_stop_mmpd(sbi); | 5062 | ext4_stop_mmpd(sbi); |
| @@ -584,10 +584,7 @@ loop: · 583 unmodified lines | |||
| 584 | 584 | ||
| 585 | if (!get_signal(&ksig)) | 585 | if (!get_signal(&ksig)) |
| 586 | continue; | 586 | continue; |
| 587 | if (fatal_signal_pending(current) || | 587 | break; |
| 588 | signal_group_exit(current->signal)) | ||
| 589 | break; | ||
| 590 | continue; | ||
| 591 | } | 588 | } |
| 592 | last_timeout = !ret; | 589 | last_timeout = !ret; |
| 593 | } | 590 | } |
| @@ -403,7 +403,6 @@ struct io_ring_ctx { · 402 unmodified lines | |||
| 403 | struct wait_queue_head cq_wait; | 403 | struct wait_queue_head cq_wait; |
| 404 | unsigned cq_extra; | 404 | unsigned cq_extra; |
| 405 | atomic_t cq_timeouts; | 405 | atomic_t cq_timeouts; |
| 406 | struct fasync_struct *cq_fasync; | ||
| 407 | unsigned cq_last_tm_flush; | 406 | unsigned cq_last_tm_flush; |
| 408 | } ____cacheline_aligned_in_smp; | 407 | } ____cacheline_aligned_in_smp; |
| 409 | 408 | ||
| @@ -1614,10 +1613,8 @@ static void io_cqring_ev_posted(struct io_ring_ctx *ctx) · 1204 unmodified lines | |||
| 1614 | wake_up(&ctx->sq_data->wait); | 1613 | wake_up(&ctx->sq_data->wait); |
| 1615 | if (io_should_trigger_evfd(ctx)) | 1614 | if (io_should_trigger_evfd(ctx)) |
| 1616 | eventfd_signal(ctx->cq_ev_fd, 1); | 1615 | eventfd_signal(ctx->cq_ev_fd, 1); |
| 1617 | if (waitqueue_active(&ctx->poll_wait)) { | 1616 | if (waitqueue_active(&ctx->poll_wait)) |
| 1618 | wake_up_interruptible(&ctx->poll_wait); | 1617 | wake_up_interruptible(&ctx->poll_wait); |
| 1619 | kill_fasync(&ctx->cq_fasync, SIGIO, POLL_IN); | ||
| 1620 | } | ||
| 1621 | } | 1618 | } |
| 1622 | 1619 | ||
| 1623 | static void io_cqring_ev_posted_iopoll(struct io_ring_ctx *ctx) | 1620 | static void io_cqring_ev_posted_iopoll(struct io_ring_ctx *ctx) |
| @@ -1631,10 +1628,8 @@ static void io_cqring_ev_posted_iopoll(struct io_ring_ctx *ctx) · 7 unmodified lines | |||
| 1631 | } | 1628 | } |
| 1632 | if (io_should_trigger_evfd(ctx)) | 1629 | if (io_should_trigger_evfd(ctx)) |
| 1633 | eventfd_signal(ctx->cq_ev_fd, 1); | 1630 | eventfd_signal(ctx->cq_ev_fd, 1); |
| 1634 | if (waitqueue_active(&ctx->poll_wait)) { | 1631 | if (waitqueue_active(&ctx->poll_wait)) |
| 1635 | wake_up_interruptible(&ctx->poll_wait); | 1632 | wake_up_interruptible(&ctx->poll_wait); |
| 1636 | kill_fasync(&ctx->cq_fasync, SIGIO, POLL_IN); | ||
| 1637 | } | ||
| 1638 | } | 1633 | } |
| 1639 | 1634 | ||
| 1640 | /* Returns true if there are no backlogged entries after the flush */ | 1635 | /* Returns true if there are no backlogged entries after the flush */ |
| @@ -9345,13 +9340,6 @@ static __poll_t io_uring_poll(struct file *file, poll_table *wait) · 7704 unmodified lines | |||
| 9345 | return mask; | 9340 | return mask; |
| 9346 | } | 9341 | } |
| 9347 | 9342 | ||
| 9348 | static int io_uring_fasync(int fd, struct file *file, int on) | ||
| 9349 | { | ||
| 9350 | struct io_ring_ctx *ctx = file->private_data; | ||
| 9351 | |||
| 9352 | return fasync_helper(fd, file, on, &ctx->cq_fasync); | ||
| 9353 | } | ||
| 9354 | |||
| 9355 | static int io_unregister_personality(struct io_ring_ctx *ctx, unsigned id) | 9343 | static int io_unregister_personality(struct io_ring_ctx *ctx, unsigned id) |
| 9356 | { | 9344 | { |
| 9357 | const struct cred *creds; | 9345 | const struct cred *creds; |
| @@ -10145,7 +10133,6 @@ static const struct file_operations io_uring_fops = { · 787 unmodified lines | |||
| 10145 | .mmap_capabilities = io_uring_nommu_mmap_capabilities, | 10133 | .mmap_capabilities = io_uring_nommu_mmap_capabilities, |
| 10146 | #endif | 10134 | #endif |
| 10147 | .poll = io_uring_poll, | 10135 | .poll = io_uring_poll, |
| 10148 | .fasync = io_uring_fasync, | ||
| 10149 | #ifdef CONFIG_PROC_FS | 10136 | #ifdef CONFIG_PROC_FS |
| 10150 | .show_fdinfo = io_uring_show_fdinfo, | 10137 | .show_fdinfo = io_uring_show_fdinfo, |
| 10151 | #endif | 10138 | #endif |
| @@ -1116,8 +1116,13 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir, · 1115 unmodified lines | |||
| 1116 | if (!inode) | 1116 | if (!inode) |
| 1117 | inode = ERR_PTR(-ENOMEM); | 1117 | inode = ERR_PTR(-ENOMEM); |
| 1118 | } | 1118 | } |
| 1119 | /* Needed only for negative dentry validation */ | 1119 | /* |
| 1120 | if (!inode) | 1120 | * Needed for negative dentry validation. |
| 1121 | * The negative dentry can be created in kernfs_iop_lookup() | ||
| 1122 | * or transforms from positive dentry in dentry_unlink_inode() | ||
| 1123 | * called from vfs_rmdir(). | ||
| 1124 | */ | ||
| 1125 | if (!IS_ERR(inode)) | ||
| 1121 | kernfs_set_rev(parent, dentry); | 1126 | kernfs_set_rev(parent, dentry); |
| 1122 | up_read(&kernfs_rwsem); | 1127 | up_read(&kernfs_rwsem); |
| 1123 | 1128 | ||
| @@ -68,125 +68,6 @@ void ksmbd_copy_gss_neg_header(void *buf) · 67 unmodified lines | |||
| 68 | memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH); | 68 | memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static void | ||
| 72 | str_to_key(unsigned char *str, unsigned char *key) | ||
| 73 | { | ||
| 74 | int i; | ||
| 75 | |||
| 76 | key[0] = str[0] >> 1; | ||
| 77 | key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2); | ||
| 78 | key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3); | ||
| 79 | key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4); | ||
| 80 | key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5); | ||
| 81 | key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6); | ||
| 82 | key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7); | ||
| 83 | key[7] = str[6] & 0x7F; | ||
| 84 | for (i = 0; i < 8; i++) | ||
| 85 | key[i] = (key[i] << 1); | ||
| 86 | } | ||
| 87 | |||
| 88 | static int | ||
| 89 | smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) | ||
| 90 | { | ||
| 91 | unsigned char key2[8]; | ||
| 92 | struct des_ctx ctx; | ||
| 93 | |||
| 94 | if (fips_enabled) { | ||
| 95 | ksmbd_debug(AUTH, "FIPS compliance enabled: DES not permitted\n"); | ||
| 96 | return -ENOENT; | ||
| 97 | } | ||
| 98 | |||
| 99 | str_to_key(key, key2); | ||
| 100 | des_expand_key(&ctx, key2, DES_KEY_SIZE); | ||
| 101 | des_encrypt(&ctx, out, in); | ||
| 102 | memzero_explicit(&ctx, sizeof(ctx)); | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | static int ksmbd_enc_p24(unsigned char *p21, const unsigned char *c8, unsigned char *p24) | ||
| 107 | { | ||
| 108 | int rc; | ||
| 109 | |||
| 110 | rc = smbhash(p24, c8, p21); | ||
| 111 | if (rc) | ||
| 112 | return rc; | ||
| 113 | rc = smbhash(p24 + 8, c8, p21 + 7); | ||
| 114 | if (rc) | ||
| 115 | return rc; | ||
| 116 | return smbhash(p24 + 16, c8, p21 + 14); | ||
| 117 | } | ||
| 118 | |||
| 119 | /* produce a md4 message digest from data of length n bytes */ | ||
| 120 | static int ksmbd_enc_md4(unsigned char *md4_hash, unsigned char *link_str, | ||
| 121 | int link_len) | ||
| 122 | { | ||
| 123 | int rc; | ||
| 124 | struct ksmbd_crypto_ctx *ctx; | ||
| 125 | |||
| 126 | ctx = ksmbd_crypto_ctx_find_md4(); | ||
| 127 | if (!ctx) { | ||
| 128 | ksmbd_debug(AUTH, "Crypto md4 allocation error\n"); | ||
| 129 | return -ENOMEM; | ||
| 130 | } | ||
| 131 | |||
| 132 | rc = crypto_shash_init(CRYPTO_MD4(ctx)); | ||
| 133 | if (rc) { | ||
| 134 | ksmbd_debug(AUTH, "Could not init md4 shash\n"); | ||
| 135 | goto out; | ||
| 136 | } | ||
| 137 | |||
| 138 | rc = crypto_shash_update(CRYPTO_MD4(ctx), link_str, link_len); | ||
| 139 | if (rc) { | ||
| 140 | ksmbd_debug(AUTH, "Could not update with link_str\n"); | ||
| 141 | goto out; | ||
| 142 | } | ||
| 143 | |||
| 144 | rc = crypto_shash_final(CRYPTO_MD4(ctx), md4_hash); | ||
| 145 | if (rc) | ||
| 146 | ksmbd_debug(AUTH, "Could not generate md4 hash\n"); | ||
| 147 | out: | ||
| 148 | ksmbd_release_crypto_ctx(ctx); | ||
| 149 | return rc; | ||
| 150 | } | ||
| 151 | |||
| 152 | static int ksmbd_enc_update_sess_key(unsigned char *md5_hash, char *nonce, | ||
| 153 | char *server_challenge, int len) | ||
| 154 | { | ||
| 155 | int rc; | ||
| 156 | struct ksmbd_crypto_ctx *ctx; | ||
| 157 | |||
| 158 | ctx = ksmbd_crypto_ctx_find_md5(); | ||
| 159 | if (!ctx) { | ||
| 160 | ksmbd_debug(AUTH, "Crypto md5 allocation error\n"); | ||
| 161 | return -ENOMEM; | ||
| 162 | } | ||
| 163 | |||
| 164 | rc = crypto_shash_init(CRYPTO_MD5(ctx)); | ||
| 165 | if (rc) { | ||
| 166 | ksmbd_debug(AUTH, "Could not init md5 shash\n"); | ||
| 167 | goto out; | ||
| 168 | } | ||
| 169 | |||
| 170 | rc = crypto_shash_update(CRYPTO_MD5(ctx), server_challenge, len); | ||
| 171 | if (rc) { | ||
| 172 | ksmbd_debug(AUTH, "Could not update with challenge\n"); | ||
| 173 | goto out; | ||
| 174 | } | ||
| 175 | |||
| 176 | rc = crypto_shash_update(CRYPTO_MD5(ctx), nonce, len); | ||
| 177 | if (rc) { | ||
| 178 | ksmbd_debug(AUTH, "Could not update with nonce\n"); | ||
| 179 | goto out; | ||
| 180 | } | ||
| 181 | |||
| 182 | rc = crypto_shash_final(CRYPTO_MD5(ctx), md5_hash); | ||
| 183 | if (rc) | ||
| 184 | ksmbd_debug(AUTH, "Could not generate md5 hash\n"); | ||
| 185 | out: | ||
| 186 | ksmbd_release_crypto_ctx(ctx); | ||
| 187 | return rc; | ||
| 188 | } | ||
| 189 | |||
| 190 | /** | 71 | /** |
| 191 | * ksmbd_gen_sess_key() - function to generate session key | 72 | * ksmbd_gen_sess_key() - function to generate session key |
| 192 | * @sess: session of connection | 73 | * @sess: session of connection |
| @@ -324,43 +205,6 @@ out: · 131 unmodified lines | |||
| 324 | return ret; | 205 | return ret; |
| 325 | } | 206 | } |
| 326 | 207 | ||
| 327 | /** | ||
| 328 | * ksmbd_auth_ntlm() - NTLM authentication handler | ||
| 329 | * @sess: session of connection | ||
| 330 | * @pw_buf: NTLM challenge response | ||
| 331 | * @passkey: user password | ||
| 332 | * | ||
| 333 | * Return: 0 on success, error number on error | ||
| 334 | */ | ||
| 335 | int ksmbd_auth_ntlm(struct ksmbd_session *sess, char *pw_buf) | ||
| 336 | { | ||
| 337 | int rc; | ||
| 338 | unsigned char p21[21]; | ||
| 339 | char key[CIFS_AUTH_RESP_SIZE]; | ||
| 340 | |||
| 341 | memset(p21, '\0', 21); | ||
| 342 | memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE); | ||
| 343 | rc = ksmbd_enc_p24(p21, sess->ntlmssp.cryptkey, key); | ||
| 344 | if (rc) { | ||
| 345 | pr_err("password processing failed\n"); | ||
| 346 | return rc; | ||
| 347 | } | ||
| 348 | |||
| 349 | ksmbd_enc_md4(sess->sess_key, user_passkey(sess->user), | ||
| 350 | CIFS_SMB1_SESSKEY_SIZE); | ||
| 351 | memcpy(sess->sess_key + CIFS_SMB1_SESSKEY_SIZE, key, | ||
| 352 | CIFS_AUTH_RESP_SIZE); | ||
| 353 | sess->sequence_number = 1; | ||
| 354 | |||
| 355 | if (strncmp(pw_buf, key, CIFS_AUTH_RESP_SIZE) != 0) { | ||
| 356 | ksmbd_debug(AUTH, "ntlmv1 authentication failed\n"); | ||
| 357 | return -EINVAL; | ||
| 358 | } | ||
| 359 | |||
| 360 | ksmbd_debug(AUTH, "ntlmv1 authentication pass\n"); | ||
| 361 | return 0; | ||
| 362 | } | ||
| 363 | |||
| 364 | /** | 208 | /** |
| 365 | * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler | 209 | * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler |
| 366 | * @sess: session of connection | 210 | * @sess: session of connection |
| @@ -441,44 +285,6 @@ out: · 74 unmodified lines | |||
| 441 | return rc; | 285 | return rc; |
| 442 | } | 286 | } |
| 443 | 287 | ||
| 444 | /** | ||
| 445 | * __ksmbd_auth_ntlmv2() - NTLM2(extended security) authentication handler | ||
| 446 | * @sess: session of connection | ||
| 447 | * @client_nonce: client nonce from LM response. | ||
| 448 | * @ntlm_resp: ntlm response data from client. | ||
| 449 | * | ||
| 450 | * Return: 0 on success, error number on error | ||
| 451 | */ | ||
| 452 | static int __ksmbd_auth_ntlmv2(struct ksmbd_session *sess, char *client_nonce, | ||
| 453 | char *ntlm_resp) | ||
| 454 | { | ||
| 455 | char sess_key[CIFS_SMB1_SESSKEY_SIZE] = {0}; | ||
| 456 | int rc; | ||
| 457 | unsigned char p21[21]; | ||
| 458 | char key[CIFS_AUTH_RESP_SIZE]; | ||
| 459 | |||
| 460 | rc = ksmbd_enc_update_sess_key(sess_key, | ||
| 461 | client_nonce, | ||
| 462 | (char *)sess->ntlmssp.cryptkey, 8); | ||
| 463 | if (rc) { | ||
| 464 | pr_err("password processing failed\n"); | ||
| 465 | goto out; | ||
| 466 | } | ||
| 467 | |||
| 468 | memset(p21, '\0', 21); | ||
| 469 | memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE); | ||
| 470 | rc = ksmbd_enc_p24(p21, sess_key, key); | ||
| 471 | if (rc) { | ||
| 472 | pr_err("password processing failed\n"); | ||
| 473 | goto out; | ||
| 474 | } | ||
| 475 | |||
| 476 | if (memcmp(ntlm_resp, key, CIFS_AUTH_RESP_SIZE) != 0) | ||
| 477 | rc = -EINVAL; | ||
| 478 | out: | ||
| 479 | return rc; | ||
| 480 | } | ||
| 481 | |||
| 482 | /** | 288 | /** |
| 483 | * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct | 289 | * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct |
| 484 | * authenticate blob | 290 | * authenticate blob |
| @@ -512,17 +318,6 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, · 27 unmodified lines | |||
| 512 | nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset); | 318 | nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset); |
| 513 | nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length); | 319 | nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length); |
| 514 | 320 | ||
| 515 | /* process NTLM authentication */ | ||
| 516 | if (nt_len == CIFS_AUTH_RESP_SIZE) { | ||
| 517 | if (le32_to_cpu(authblob->NegotiateFlags) & | ||
| 518 | NTLMSSP_NEGOTIATE_EXTENDED_SEC) | ||
| 519 | return __ksmbd_auth_ntlmv2(sess, (char *)authblob + | ||
| 520 | lm_off, (char *)authblob + nt_off); | ||
| 521 | else | ||
| 522 | return ksmbd_auth_ntlm(sess, (char *)authblob + | ||
| 523 | nt_off); | ||
| 524 | } | ||
| 525 | |||
| 526 | /* TODO : use domain name that imported from configuration file */ | 321 | /* TODO : use domain name that imported from configuration file */ |
| 527 | domain_name = smb_strndup_from_utf16((const char *)authblob + | 322 | domain_name = smb_strndup_from_utf16((const char *)authblob + |
| 528 | le32_to_cpu(authblob->DomainName.BufferOffset), | 323 | le32_to_cpu(authblob->DomainName.BufferOffset), |
| @@ -81,12 +81,6 @@ static struct shash_desc *alloc_shash_desc(int id) · 80 unmodified lines | |||
| 81 | case CRYPTO_SHASH_SHA512: | 81 | case CRYPTO_SHASH_SHA512: |
| 82 | tfm = crypto_alloc_shash("sha512", 0, 0); | 82 | tfm = crypto_alloc_shash("sha512", 0, 0); |
| 83 | break; | 83 | break; |
| 84 | case CRYPTO_SHASH_MD4: | ||
| 85 | tfm = crypto_alloc_shash("md4", 0, 0); | ||
| 86 | break; | ||
| 87 | case CRYPTO_SHASH_MD5: | ||
| 88 | tfm = crypto_alloc_shash("md5", 0, 0); | ||
| 89 | break; | ||
| 90 | default: | 84 | default: |
| 91 | return NULL; | 85 | return NULL; |
| 92 | } | 86 | } |
| @@ -214,16 +208,6 @@ struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void) · 121 unmodified lines | |||
| 214 | return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512); | 208 | return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512); |
| 215 | } | 209 | } |
| 216 | 210 | ||
| 217 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void) | ||
| 218 | { | ||
| 219 | return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD4); | ||
| 220 | } | ||
| 221 | |||
| 222 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void) | ||
| 223 | { | ||
| 224 | return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD5); | ||
| 225 | } | ||
| 226 | |||
| 227 | static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id) | 211 | static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id) |
| 228 | { | 212 | { |
| 229 | struct ksmbd_crypto_ctx *ctx; | 213 | struct ksmbd_crypto_ctx *ctx; |
| @@ -15,8 +15,6 @@ enum { · 14 unmodified lines | |||
| 15 | CRYPTO_SHASH_CMACAES, | 15 | CRYPTO_SHASH_CMACAES, |
| 16 | CRYPTO_SHASH_SHA256, | 16 | CRYPTO_SHASH_SHA256, |
| 17 | CRYPTO_SHASH_SHA512, | 17 | CRYPTO_SHASH_SHA512, |
| 18 | CRYPTO_SHASH_MD4, | ||
| 19 | CRYPTO_SHASH_MD5, | ||
| 20 | CRYPTO_SHASH_MAX, | 18 | CRYPTO_SHASH_MAX, |
| 21 | }; | 19 | }; |
| 22 | 20 | ||
| @@ -43,8 +41,6 @@ struct ksmbd_crypto_ctx { · 20 unmodified lines | |||
| 43 | #define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES]) | 41 | #define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES]) |
| 44 | #define CRYPTO_SHA256(c) ((c)->desc[CRYPTO_SHASH_SHA256]) | 42 | #define CRYPTO_SHA256(c) ((c)->desc[CRYPTO_SHASH_SHA256]) |
| 45 | #define CRYPTO_SHA512(c) ((c)->desc[CRYPTO_SHASH_SHA512]) | 43 | #define CRYPTO_SHA512(c) ((c)->desc[CRYPTO_SHASH_SHA512]) |
| 46 | #define CRYPTO_MD4(c) ((c)->desc[CRYPTO_SHASH_MD4]) | ||
| 47 | #define CRYPTO_MD5(c) ((c)->desc[CRYPTO_SHASH_MD5]) | ||
| 48 | 44 | ||
| 49 | #define CRYPTO_HMACMD5_TFM(c) ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm) | 45 | #define CRYPTO_HMACMD5_TFM(c) ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm) |
| 50 | #define CRYPTO_HMACSHA256_TFM(c)\ | 46 | #define CRYPTO_HMACSHA256_TFM(c)\ |
| @@ -52,8 +48,6 @@ struct ksmbd_crypto_ctx { · 1 unmodified line | |||
| 52 | #define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm) | 48 | #define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm) |
| 53 | #define CRYPTO_SHA256_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA256]->tfm) | 49 | #define CRYPTO_SHA256_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA256]->tfm) |
| 54 | #define CRYPTO_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm) | 50 | #define CRYPTO_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm) |
| 55 | #define CRYPTO_MD4_TFM(c) ((c)->desc[CRYPTO_SHASH_MD4]->tfm) | ||
| 56 | #define CRYPTO_MD5_TFM(c) ((c)->desc[CRYPTO_SHASH_MD5]->tfm) | ||
| 57 | 51 | ||
| 58 | #define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM]) | 52 | #define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM]) |
| 59 | #define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM]) | 53 | #define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM]) |
| @@ -64,8 +58,6 @@ struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void); · 4 unmodified lines | |||
| 64 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void); | 58 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void); |
| 65 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void); | 59 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void); |
| 66 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void); | 60 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void); |
| 67 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void); | ||
| 68 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void); | ||
| 69 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void); | 61 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void); |
| 70 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void); | 62 | struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void); |
| 71 | void ksmbd_crypto_destroy(void); | 63 | void ksmbd_crypto_destroy(void); |
| @@ -162,17 +162,14 @@ char *convert_to_nt_pathname(char *filename) · 161 unmodified lines | |||
| 162 | { | 162 | { |
| 163 | char *ab_pathname; | 163 | char *ab_pathname; |
| 164 | 164 | ||
| 165 | if (strlen(filename) == 0) { | 165 | if (strlen(filename) == 0) |
| 166 | ab_pathname = kmalloc(2, GFP_KERNEL); | 166 | filename = "\\"; |
| 167 | ab_pathname[0] = '\\'; | ||
| 168 | ab_pathname[1] = '\0'; | ||
| 169 | } else { | ||
| 170 | ab_pathname = kstrdup(filename, GFP_KERNEL); | ||
| 171 | if (!ab_pathname) | ||
| 172 | return NULL; | ||
| 173 | 167 | ||
| 174 | ksmbd_conv_path_to_windows(ab_pathname); | 168 | ab_pathname = kstrdup(filename, GFP_KERNEL); |
| 175 | } | 169 | if (!ab_pathname) |
| 170 | return NULL; | ||
| 171 | |||
| 172 | ksmbd_conv_path_to_windows(ab_pathname); | ||
| 176 | return ab_pathname; | 173 | return ab_pathname; |
| 177 | } | 174 | } |
| 178 | 175 | ||
| @@ -1451,26 +1451,47 @@ struct lease_ctx_info *parse_lease_state(void *open_req) · 1450 unmodified lines | |||
| 1451 | */ | 1451 | */ |
| 1452 | struct create_context *smb2_find_context_vals(void *open_req, const char *tag) | 1452 | struct create_context *smb2_find_context_vals(void *open_req, const char *tag) |
| 1453 | { | 1453 | { |
| 1454 | char *data_offset; | ||
| 1455 | struct create_context *cc; | 1454 | struct create_context *cc; |
| 1456 | unsigned int next = 0; | 1455 | unsigned int next = 0; |
| 1457 | char *name; | 1456 | char *name; |
| 1458 | struct smb2_create_req *req = (struct smb2_create_req *)open_req; | 1457 | struct smb2_create_req *req = (struct smb2_create_req *)open_req; |
| 1458 | unsigned int remain_len, name_off, name_len, value_off, value_len, | ||
| 1459 | cc_len; | ||
| 1459 | 1460 | ||
| 1460 | data_offset = (char *)req + 4 + le32_to_cpu(req->CreateContextsOffset); | 1461 | /* |
| 1461 | cc = (struct create_context *)data_offset; | 1462 | * CreateContextsOffset and CreateContextsLength are guaranteed to |
| 1463 | * be valid because of ksmbd_smb2_check_message(). | ||
| 1464 | */ | ||
| 1465 | cc = (struct create_context *)((char *)req + 4 + | ||
| 1466 | le32_to_cpu(req->CreateContextsOffset)); | ||
| 1467 | remain_len = le32_to_cpu(req->CreateContextsLength); | ||
| 1462 | do { | 1468 | do { |
| 1463 | int val; | ||
| 1464 | |||
| 1465 | cc = (struct create_context *)((char *)cc + next); | 1469 | cc = (struct create_context *)((char *)cc + next); |
| 1466 | name = le16_to_cpu(cc->NameOffset) + (char *)cc; | 1470 | if (remain_len < offsetof(struct create_context, Buffer)) |
| 1467 | val = le16_to_cpu(cc->NameLength); | ||
| 1468 | if (val < 4) | ||
| 1469 | return ERR_PTR(-EINVAL); | 1471 | return ERR_PTR(-EINVAL); |
| 1470 | 1472 | ||
| 1471 | if (memcmp(name, tag, val) == 0) | ||
| 1472 | return cc; | ||
| 1473 | next = le32_to_cpu(cc->Next); | 1473 | next = le32_to_cpu(cc->Next); |
| 1474 | name_off = le16_to_cpu(cc->NameOffset); | ||
| 1475 | name_len = le16_to_cpu(cc->NameLength); | ||
| 1476 | value_off = le16_to_cpu(cc->DataOffset); | ||
| 1477 | value_len = le32_to_cpu(cc->DataLength); | ||
| 1478 | cc_len = next ? next : remain_len; | ||
| 1479 | |||
| 1480 | if ((next & 0x7) != 0 || | ||
| 1481 | next > remain_len || | ||
| 1482 | name_off != offsetof(struct create_context, Buffer) || | ||
| 1483 | name_len < 4 || | ||
| 1484 | name_off + name_len > cc_len || | ||
| 1485 | (value_off & 0x7) != 0 || | ||
| 1486 | (value_off && (value_off < name_off + name_len)) || | ||
| 1487 | ((u64)value_off + value_len > cc_len)) | ||
| 1488 | return ERR_PTR(-EINVAL); | ||
| 1489 | |||
| 1490 | name = (char *)cc + name_off; | ||
| 1491 | if (memcmp(name, tag, name_len) == 0) | ||
| 1492 | return cc; | ||
| 1493 | |||
| 1494 | remain_len -= next; | ||
| 1474 | } while (next != 0); | 1495 | } while (next != 0); |
| 1475 | 1496 | ||
| 1476 | return NULL; | 1497 | return NULL; |
| @@ -459,13 +459,22 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work) · 458 unmodified lines | |||
| 459 | bool is_chained_smb2_message(struct ksmbd_work *work) | 459 | bool is_chained_smb2_message(struct ksmbd_work *work) |
| 460 | { | 460 | { |
| 461 | struct smb2_hdr *hdr = work->request_buf; | 461 | struct smb2_hdr *hdr = work->request_buf; |
| 462 | unsigned int len; | 462 | unsigned int len, next_cmd; |
| 463 | 463 | ||
| 464 | if (hdr->ProtocolId != SMB2_PROTO_NUMBER) | 464 | if (hdr->ProtocolId != SMB2_PROTO_NUMBER) |
| 465 | return false; | 465 | return false; |
| 466 | 466 | ||
| 467 | hdr = ksmbd_req_buf_next(work); | 467 | hdr = ksmbd_req_buf_next(work); |
| 468 | if (le32_to_cpu(hdr->NextCommand) > 0) { | 468 | next_cmd = le32_to_cpu(hdr->NextCommand); |
| 469 | if (next_cmd > 0) { | ||
| 470 | if ((u64)work->next_smb2_rcv_hdr_off + next_cmd + | ||
| 471 | __SMB2_HEADER_STRUCTURE_SIZE > | ||
| 472 | get_rfc1002_len(work->request_buf)) { | ||
| 473 | pr_err("next command(%u) offset exceeds smb msg size\n", | ||
| 474 | next_cmd); | ||
| 475 | return false; | ||
| 476 | } | ||
| 477 | |||
| 469 | ksmbd_debug(SMB, "got SMB2 chained command\n"); | 478 | ksmbd_debug(SMB, "got SMB2 chained command\n"); |
| 470 | init_chained_smb2_rsp(work); | 479 | init_chained_smb2_rsp(work); |
| 471 | return true; | 480 | return true; |
| @@ -1058,6 +1067,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work) · 586 unmodified lines | |||
| 1058 | struct smb2_negotiate_req *req = work->request_buf; | 1067 | struct smb2_negotiate_req *req = work->request_buf; |
| 1059 | struct smb2_negotiate_rsp *rsp = work->response_buf; | 1068 | struct smb2_negotiate_rsp *rsp = work->response_buf; |
| 1060 | int rc = 0; | 1069 | int rc = 0; |
| 1070 | unsigned int smb2_buf_len, smb2_neg_size; | ||
| 1061 | __le32 status; | 1071 | __le32 status; |
| 1062 | 1072 | ||
| 1063 | ksmbd_debug(SMB, "Received negotiate request\n"); | 1073 | ksmbd_debug(SMB, "Received negotiate request\n"); |
| @@ -1075,6 +1085,44 @@ int smb2_handle_negotiate(struct ksmbd_work *work) · 11 unmodified lines | |||
| 1075 | goto err_out; | 1085 | goto err_out; |
| 1076 | } | 1086 | } |
| 1077 | 1087 | ||
| 1088 | smb2_buf_len = get_rfc1002_len(work->request_buf); | ||
| 1089 | smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects) - 4; | ||
| 1090 | if (smb2_neg_size > smb2_buf_len) { | ||
| 1091 | rsp->hdr.Status = STATUS_INVALID_PARAMETER; | ||
| 1092 | rc = -EINVAL; | ||
| 1093 | goto err_out; | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | if (conn->dialect == SMB311_PROT_ID) { | ||
| 1097 | unsigned int nego_ctxt_off = le32_to_cpu(req->NegotiateContextOffset); | ||
| 1098 | |||
| 1099 | if (smb2_buf_len < nego_ctxt_off) { | ||
| 1100 | rsp->hdr.Status = STATUS_INVALID_PARAMETER; | ||
| 1101 | rc = -EINVAL; | ||
| 1102 | goto err_out; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | if (smb2_neg_size > nego_ctxt_off) { | ||
| 1106 | rsp->hdr.Status = STATUS_INVALID_PARAMETER; | ||
| 1107 | rc = -EINVAL; | ||
| 1108 | goto err_out; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > | ||
| 1112 | nego_ctxt_off) { | ||
| 1113 | rsp->hdr.Status = STATUS_INVALID_PARAMETER; | ||
| 1114 | rc = -EINVAL; | ||
| 1115 | goto err_out; | ||
| 1116 | } | ||
| 1117 | } else { | ||
| 1118 | if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > | ||
| 1119 | smb2_buf_len) { | ||
| 1120 | rsp->hdr.Status = STATUS_INVALID_PARAMETER; | ||
| 1121 | rc = -EINVAL; | ||
| 1122 | goto err_out; | ||
| 1123 | } | ||
| 1124 | } | ||
| 1125 | |||
| 1078 | conn->cli_cap = le32_to_cpu(req->Capabilities); | 1126 | conn->cli_cap = le32_to_cpu(req->Capabilities); |
| 1079 | switch (conn->dialect) { | 1127 | switch (conn->dialect) { |
| 1080 | case SMB311_PROT_ID: | 1128 | case SMB311_PROT_ID: |
| @@ -2093,16 +2141,22 @@ out: · 1012 unmodified lines | |||
| 2093 | * smb2_set_ea() - handler for setting extended attributes using set | 2141 | * smb2_set_ea() - handler for setting extended attributes using set |
| 2094 | * info command | 2142 | * info command |
| 2095 | * @eabuf: set info command buffer | 2143 | * @eabuf: set info command buffer |
| 2144 | * @buf_len: set info command buffer length | ||
| 2096 | * @path: dentry path for get ea | 2145 | * @path: dentry path for get ea |
| 2097 | * | 2146 | * |
| 2098 | * Return: 0 on success, otherwise error | 2147 | * Return: 0 on success, otherwise error |
| 2099 | */ | 2148 | */ |
| 2100 | static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path) | 2149 | static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len, |
| 2150 | struct path *path) | ||
| 2101 | { | 2151 | { |
| 2102 | struct user_namespace *user_ns = mnt_user_ns(path->mnt); | 2152 | struct user_namespace *user_ns = mnt_user_ns(path->mnt); |
| 2103 | char *attr_name = NULL, *value; | 2153 | char *attr_name = NULL, *value; |
| 2104 | int rc = 0; | 2154 | int rc = 0; |
| 2105 | int next = 0; | 2155 | unsigned int next = 0; |
| 2156 | |||
| 2157 | if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + | ||
| 2158 | le16_to_cpu(eabuf->EaValueLength)) | ||
| 2159 | return -EINVAL; | ||
| 2106 | 2160 | ||
| 2107 | attr_name = kmalloc(XATTR_NAME_MAX + 1, GFP_KERNEL); | 2161 | attr_name = kmalloc(XATTR_NAME_MAX + 1, GFP_KERNEL); |
| 2108 | if (!attr_name) | 2162 | if (!attr_name) |
| @@ -2167,7 +2221,13 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path) · 58 unmodified lines | |||
| 2167 | 2221 | ||
| 2168 | next: | 2222 | next: |
| 2169 | next = le32_to_cpu(eabuf->NextEntryOffset); | 2223 | next = le32_to_cpu(eabuf->NextEntryOffset); |
| 2224 | if (next == 0 || buf_len < next) | ||
| 2225 | break; | ||
| 2226 | buf_len -= next; | ||
| 2170 | eabuf = (struct smb2_ea_info *)((char *)eabuf + next); | 2227 | eabuf = (struct smb2_ea_info *)((char *)eabuf + next); |
| 2228 | if (next < (u32)eabuf->EaNameLength + le16_to_cpu(eabuf->EaValueLength)) | ||
| 2229 | break; | ||
| 2230 | |||
| 2171 | } while (next != 0); | 2231 | } while (next != 0); |
| 2172 | 2232 | ||
| 2173 | kfree(attr_name); | 2233 | kfree(attr_name); |
| @@ -2367,6 +2427,10 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work, · 193 unmodified lines | |||
| 2367 | ksmbd_debug(SMB, | 2427 | ksmbd_debug(SMB, |
| 2368 | "Set ACLs using SMB2_CREATE_SD_BUFFER context\n"); | 2428 | "Set ACLs using SMB2_CREATE_SD_BUFFER context\n"); |
| 2369 | sd_buf = (struct create_sd_buf_req *)context; | 2429 | sd_buf = (struct create_sd_buf_req *)context; |
| 2430 | if (le16_to_cpu(context->DataOffset) + | ||
| 2431 | le32_to_cpu(context->DataLength) < | ||
| 2432 | sizeof(struct create_sd_buf_req)) | ||
| 2433 | return -EINVAL; | ||
| 2370 | return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd, | 2434 | return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd, |
| 2371 | le32_to_cpu(sd_buf->ccontext.DataLength), true); | 2435 | le32_to_cpu(sd_buf->ccontext.DataLength), true); |
| 2372 | } | 2436 | } |
| @@ -2561,6 +2625,12 @@ int smb2_open(struct ksmbd_work *work) · 188 unmodified lines | |||
| 2561 | goto err_out1; | 2625 | goto err_out1; |
| 2562 | } else if (context) { | 2626 | } else if (context) { |
| 2563 | ea_buf = (struct create_ea_buf_req *)context; | 2627 | ea_buf = (struct create_ea_buf_req *)context; |
| 2628 | if (le16_to_cpu(context->DataOffset) + | ||
| 2629 | le32_to_cpu(context->DataLength) < | ||
| 2630 | sizeof(struct create_ea_buf_req)) { | ||
| 2631 | rc = -EINVAL; | ||
| 2632 | goto err_out1; | ||
| 2633 | } | ||
| 2564 | if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) { | 2634 | if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) { |
| 2565 | rsp->hdr.Status = STATUS_ACCESS_DENIED; | 2635 | rsp->hdr.Status = STATUS_ACCESS_DENIED; |
| 2566 | rc = -EACCES; | 2636 | rc = -EACCES; |
| @@ -2599,6 +2669,12 @@ int smb2_open(struct ksmbd_work *work) · 32 unmodified lines | |||
| 2599 | } else if (context) { | 2669 | } else if (context) { |
| 2600 | struct create_posix *posix = | 2670 | struct create_posix *posix = |
| 2601 | (struct create_posix *)context; | 2671 | (struct create_posix *)context; |
| 2672 | if (le16_to_cpu(context->DataOffset) + | ||
| 2673 | le32_to_cpu(context->DataLength) < | ||
| 2674 | sizeof(struct create_posix)) { | ||
| 2675 | rc = -EINVAL; | ||
| 2676 | goto err_out1; | ||
| 2677 | } | ||
| 2602 | ksmbd_debug(SMB, "get posix context\n"); | 2678 | ksmbd_debug(SMB, "get posix context\n"); |
| 2603 | 2679 | ||
| 2604 | posix_mode = le32_to_cpu(posix->Mode); | 2680 | posix_mode = le32_to_cpu(posix->Mode); |
| @@ -2748,7 +2824,15 @@ int smb2_open(struct ksmbd_work *work) · 143 unmodified lines | |||
| 2748 | created = true; | 2824 | created = true; |
| 2749 | user_ns = mnt_user_ns(path.mnt); | 2825 | user_ns = mnt_user_ns(path.mnt); |
| 2750 | if (ea_buf) { | 2826 | if (ea_buf) { |
| 2751 | rc = smb2_set_ea(&ea_buf->ea, &path); | 2827 | if (le32_to_cpu(ea_buf->ccontext.DataLength) < |
| 2828 | sizeof(struct smb2_ea_info)) { | ||
| 2829 | rc = -EINVAL; | ||
| 2830 | goto err_out; | ||
| 2831 | } | ||
| 2832 | |||
| 2833 | rc = smb2_set_ea(&ea_buf->ea, | ||
| 2834 | le32_to_cpu(ea_buf->ccontext.DataLength), | ||
| 2835 | &path); | ||
| 2752 | if (rc == -EOPNOTSUPP) | 2836 | if (rc == -EOPNOTSUPP) |
| 2753 | rc = 0; | 2837 | rc = 0; |
| 2754 | else if (rc) | 2838 | else if (rc) |
| @@ -2981,9 +3065,16 @@ int smb2_open(struct ksmbd_work *work) · 226 unmodified lines | |||
| 2981 | rc = PTR_ERR(az_req); | 3065 | rc = PTR_ERR(az_req); |
| 2982 | goto err_out; | 3066 | goto err_out; |
| 2983 | } else if (az_req) { | 3067 | } else if (az_req) { |
| 2984 | loff_t alloc_size = le64_to_cpu(az_req->AllocationSize); | 3068 | loff_t alloc_size; |
| 2985 | int err; | 3069 | int err; |
| 2986 | 3070 | ||
| 3071 | if (le16_to_cpu(az_req->ccontext.DataOffset) + | ||
| 3072 | le32_to_cpu(az_req->ccontext.DataLength) < | ||
| 3073 | sizeof(struct create_alloc_size_req)) { | ||
| 3074 | rc = -EINVAL; | ||
| 3075 | goto err_out; | ||
| 3076 | } | ||
| 3077 | alloc_size = le64_to_cpu(az_req->AllocationSize); | ||
| 2987 | ksmbd_debug(SMB, | 3078 | ksmbd_debug(SMB, |
| 2988 | "request smb2 create allocate size : %llu\n", | 3079 | "request smb2 create allocate size : %llu\n", |
| 2989 | alloc_size); | 3080 | alloc_size); |
| @@ -4152,7 +4243,7 @@ static void get_file_access_info(struct smb2_query_info_rsp *rsp, · 1162 unmodified lines | |||
| 4152 | static int get_file_basic_info(struct smb2_query_info_rsp *rsp, | 4243 | static int get_file_basic_info(struct smb2_query_info_rsp *rsp, |
| 4153 | struct ksmbd_file *fp, void *rsp_org) | 4244 | struct ksmbd_file *fp, void *rsp_org) |
| 4154 | { | 4245 | { |
| 4155 | struct smb2_file_all_info *basic_info; | 4246 | struct smb2_file_basic_info *basic_info; |
| 4156 | struct kstat stat; | 4247 | struct kstat stat; |
| 4157 | u64 time; | 4248 | u64 time; |
| 4158 | 4249 | ||
| @@ -4162,7 +4253,7 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp, · 3 unmodified lines | |||
| 4162 | return -EACCES; | 4253 | return -EACCES; |
| 4163 | } | 4254 | } |
| 4164 | 4255 | ||
| 4165 | basic_info = (struct smb2_file_all_info *)rsp->Buffer; | 4256 | basic_info = (struct smb2_file_basic_info *)rsp->Buffer; |
| 4166 | generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp), | 4257 | generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp), |
| 4167 | &stat); | 4258 | &stat); |
| 4168 | basic_info->CreationTime = cpu_to_le64(fp->create_time); | 4259 | basic_info->CreationTime = cpu_to_le64(fp->create_time); |
| @@ -4175,9 +4266,8 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp, · 6 unmodified lines | |||
| 4175 | basic_info->Attributes = fp->f_ci->m_fattr; | 4266 | basic_info->Attributes = fp->f_ci->m_fattr; |
| 4176 | basic_info->Pad1 = 0; | 4267 | basic_info->Pad1 = 0; |
| 4177 | rsp->OutputBufferLength = | 4268 | rsp->OutputBufferLength = |
| 4178 | cpu_to_le32(offsetof(struct smb2_file_all_info, AllocationSize)); | 4269 | cpu_to_le32(sizeof(struct smb2_file_basic_info)); |
| 4179 | inc_rfc1001_len(rsp_org, offsetof(struct smb2_file_all_info, | 4270 | inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_basic_info)); |
| 4180 | AllocationSize)); | ||
| 4181 | return 0; | 4271 | return 0; |
| 4182 | } | 4272 | } |
| 4183 | 4273 | ||
| @@ -5333,7 +5423,7 @@ out: · 1149 unmodified lines | |||
| 5333 | static int smb2_create_link(struct ksmbd_work *work, | 5423 | static int smb2_create_link(struct ksmbd_work *work, |
| 5334 | struct ksmbd_share_config *share, | 5424 | struct ksmbd_share_config *share, |
| 5335 | struct smb2_file_link_info *file_info, | 5425 | struct smb2_file_link_info *file_info, |
| 5336 | struct file *filp, | 5426 | unsigned int buf_len, struct file *filp, |
| 5337 | struct nls_table *local_nls) | 5427 | struct nls_table *local_nls) |
| 5338 | { | 5428 | { |
| 5339 | char *link_name = NULL, *target_name = NULL, *pathname = NULL; | 5429 | char *link_name = NULL, *target_name = NULL, *pathname = NULL; |
| @@ -5341,6 +5431,10 @@ static int smb2_create_link(struct ksmbd_work *work, · 1 unmodified line | |||
| 5341 | bool file_present = true; | 5431 | bool file_present = true; |
| 5342 | int rc; | 5432 | int rc; |
| 5343 | 5433 | ||
| 5434 | if (buf_len < (u64)sizeof(struct smb2_file_link_info) + | ||
| 5435 | le32_to_cpu(file_info->FileNameLength)) | ||
| 5436 | return -EINVAL; | ||
| 5437 | |||
| 5344 | ksmbd_debug(SMB, "setting FILE_LINK_INFORMATION\n"); | 5438 | ksmbd_debug(SMB, "setting FILE_LINK_INFORMATION\n"); |
| 5345 | pathname = kmalloc(PATH_MAX, GFP_KERNEL); | 5439 | pathname = kmalloc(PATH_MAX, GFP_KERNEL); |
| 5346 | if (!pathname) | 5440 | if (!pathname) |
| @@ -5400,10 +5494,10 @@ out: · 53 unmodified lines | |||
| 5400 | return rc; | 5494 | return rc; |
| 5401 | } | 5495 | } |
| 5402 | 5496 | ||
| 5403 | static int set_file_basic_info(struct ksmbd_file *fp, char *buf, | 5497 | static int set_file_basic_info(struct ksmbd_file *fp, |
| 5498 | struct smb2_file_basic_info *file_info, | ||
| 5404 | struct ksmbd_share_config *share) | 5499 | struct ksmbd_share_config *share) |
| 5405 | { | 5500 | { |
| 5406 | struct smb2_file_all_info *file_info; | ||
| 5407 | struct iattr attrs; | 5501 | struct iattr attrs; |
| 5408 | struct timespec64 ctime; | 5502 | struct timespec64 ctime; |
| 5409 | struct file *filp; | 5503 | struct file *filp; |
| @@ -5414,7 +5508,6 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf, · 4 unmodified lines | |||
| 5414 | if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE)) | 5508 | if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE)) |
| 5415 | return -EACCES; | 5509 | return -EACCES; |
| 5416 | 5510 | ||
| 5417 | file_info = (struct smb2_file_all_info *)buf; | ||
| 5418 | attrs.ia_valid = 0; | 5511 | attrs.ia_valid = 0; |
| 5419 | filp = fp->filp; | 5512 | filp = fp->filp; |
| 5420 | inode = file_inode(filp); | 5513 | inode = file_inode(filp); |
| @@ -5491,7 +5584,8 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf, · 70 unmodified lines | |||
| 5491 | } | 5584 | } |
| 5492 | 5585 | ||
| 5493 | static int set_file_allocation_info(struct ksmbd_work *work, | 5586 | static int set_file_allocation_info(struct ksmbd_work *work, |
| 5494 | struct ksmbd_file *fp, char *buf) | 5587 | struct ksmbd_file *fp, |
| 5588 | struct smb2_file_alloc_info *file_alloc_info) | ||
| 5495 | { | 5589 | { |
| 5496 | /* | 5590 | /* |
| 5497 | * TODO : It's working fine only when store dos attributes | 5591 | * TODO : It's working fine only when store dos attributes |
| @@ -5499,7 +5593,6 @@ static int set_file_allocation_info(struct ksmbd_work *work, · 1 unmodified line | |||
| 5499 | * properly with any smb.conf option | 5593 | * properly with any smb.conf option |
| 5500 | */ | 5594 | */ |
| 5501 | 5595 | ||
| 5502 | struct smb2_file_alloc_info *file_alloc_info; | ||
| 5503 | loff_t alloc_blks; | 5596 | loff_t alloc_blks; |
| 5504 | struct inode *inode; | 5597 | struct inode *inode; |
| 5505 | int rc; | 5598 | int rc; |
| @@ -5507,7 +5600,6 @@ static int set_file_allocation_info(struct ksmbd_work *work, · 1 unmodified line | |||
| 5507 | if (!(fp->daccess & FILE_WRITE_DATA_LE)) | 5600 | if (!(fp->daccess & FILE_WRITE_DATA_LE)) |
| 5508 | return -EACCES; | 5601 | return -EACCES; |
| 5509 | 5602 | ||
| 5510 | file_alloc_info = (struct smb2_file_alloc_info *)buf; | ||
| 5511 | alloc_blks = (le64_to_cpu(file_alloc_info->AllocationSize) + 511) >> 9; | 5603 | alloc_blks = (le64_to_cpu(file_alloc_info->AllocationSize) + 511) >> 9; |
| 5512 | inode = file_inode(fp->filp); | 5604 | inode = file_inode(fp->filp); |
| 5513 | 5605 | ||
| @@ -5543,9 +5635,8 @@ static int set_file_allocation_info(struct ksmbd_work *work, · 29 unmodified lines | |||
| 5543 | } | 5635 | } |
| 5544 | 5636 | ||
| 5545 | static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp, | 5637 | static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp, |
| 5546 | char *buf) | 5638 | struct smb2_file_eof_info *file_eof_info) |
| 5547 | { | 5639 | { |
| 5548 | struct smb2_file_eof_info *file_eof_info; | ||
| 5549 | loff_t newsize; | 5640 | loff_t newsize; |
| 5550 | struct inode *inode; | 5641 | struct inode *inode; |
| 5551 | int rc; | 5642 | int rc; |
| @@ -5553,7 +5644,6 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp, · 1 unmodified line | |||
| 5553 | if (!(fp->daccess & FILE_WRITE_DATA_LE)) | 5644 | if (!(fp->daccess & FILE_WRITE_DATA_LE)) |
| 5554 | return -EACCES; | 5645 | return -EACCES; |
| 5555 | 5646 | ||
| 5556 | file_eof_info = (struct smb2_file_eof_info *)buf; | ||
| 5557 | newsize = le64_to_cpu(file_eof_info->EndOfFile); | 5647 | newsize = le64_to_cpu(file_eof_info->EndOfFile); |
| 5558 | inode = file_inode(fp->filp); | 5648 | inode = file_inode(fp->filp); |
| 5559 | 5649 | ||
| @@ -5580,7 +5670,8 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp, · 20 unmodified lines | |||
| 5580 | } | 5670 | } |
| 5581 | 5671 | ||
| 5582 | static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, | 5672 | static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, |
| 5583 | char *buf) | 5673 | struct smb2_file_rename_info *rename_info, |
| 5674 | unsigned int buf_len) | ||
| 5584 | { | 5675 | { |
| 5585 | struct user_namespace *user_ns; | 5676 | struct user_namespace *user_ns; |
| 5586 | struct ksmbd_file *parent_fp; | 5677 | struct ksmbd_file *parent_fp; |
| @@ -5593,6 +5684,10 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, · 6 unmodified lines | |||
| 5593 | return -EACCES; | 5684 | return -EACCES; |
| 5594 | } | 5685 | } |
| 5595 | 5686 | ||
| 5687 | if (buf_len < (u64)sizeof(struct smb2_file_rename_info) + | ||
| 5688 | le32_to_cpu(rename_info->FileNameLength)) | ||
| 5689 | return -EINVAL; | ||
| 5690 | |||
| 5596 | user_ns = file_mnt_user_ns(fp->filp); | 5691 | user_ns = file_mnt_user_ns(fp->filp); |
| 5597 | if (ksmbd_stream_fd(fp)) | 5692 | if (ksmbd_stream_fd(fp)) |
| 5598 | goto next; | 5693 | goto next; |
| @@ -5615,14 +5710,13 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, · 16 unmodified lines | |||
| 5615 | } | 5710 | } |
| 5616 | } | 5711 | } |
| 5617 | next: | 5712 | next: |
| 5618 | return smb2_rename(work, fp, user_ns, | 5713 | return smb2_rename(work, fp, user_ns, rename_info, |
| 5619 | (struct smb2_file_rename_info *)buf, | ||
| 5620 | work->sess->conn->local_nls); | 5714 | work->sess->conn->local_nls); |
| 5621 | } | 5715 | } |
| 5622 | 5716 | ||
| 5623 | static int set_file_disposition_info(struct ksmbd_file *fp, char *buf) | 5717 | static int set_file_disposition_info(struct ksmbd_file *fp, |
| 5718 | struct smb2_file_disposition_info *file_info) | ||
| 5624 | { | 5719 | { |
| 5625 | struct smb2_file_disposition_info *file_info; | ||
| 5626 | struct inode *inode; | 5720 | struct inode *inode; |
| 5627 | 5721 | ||
| 5628 | if (!(fp->daccess & FILE_DELETE_LE)) { | 5722 | if (!(fp->daccess & FILE_DELETE_LE)) { |
| @@ -5631,7 +5725,6 @@ static int set_file_disposition_info(struct ksmbd_file *fp, char *buf) · 2 unmodified lines | |||
| 5631 | } | 5725 | } |
| 5632 | 5726 | ||
| 5633 | inode = file_inode(fp->filp); | 5727 | inode = file_inode(fp->filp); |
| 5634 | file_info = (struct smb2_file_disposition_info *)buf; | ||
| 5635 | if (file_info->DeletePending) { | 5728 | if (file_info->DeletePending) { |
| 5636 | if (S_ISDIR(inode->i_mode) && | 5729 | if (S_ISDIR(inode->i_mode) && |
| 5637 | ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY) | 5730 | ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY) |
| @@ -5643,15 +5736,14 @@ static int set_file_disposition_info(struct ksmbd_file *fp, char *buf) · 5 unmodified lines | |||
| 5643 | return 0; | 5736 | return 0; |
| 5644 | } | 5737 | } |
| 5645 | 5738 | ||
| 5646 | static int set_file_position_info(struct ksmbd_file *fp, char *buf) | 5739 | static int set_file_position_info(struct ksmbd_file *fp, |
| 5740 | struct smb2_file_pos_info *file_info) | ||
| 5647 | { | 5741 | { |
| 5648 | struct smb2_file_pos_info *file_info; | ||
| 5649 | loff_t current_byte_offset; | 5742 | loff_t current_byte_offset; |
| 5650 | unsigned long sector_size; | 5743 | unsigned long sector_size; |
| 5651 | struct inode *inode; | 5744 | struct inode *inode; |
| 5652 | 5745 | ||
| 5653 | inode = file_inode(fp->filp); | 5746 | inode = file_inode(fp->filp); |
| 5654 | file_info = (struct smb2_file_pos_info *)buf; | ||
| 5655 | current_byte_offset = le64_to_cpu(file_info->CurrentByteOffset); | 5747 | current_byte_offset = le64_to_cpu(file_info->CurrentByteOffset); |
| 5656 | sector_size = inode->i_sb->s_blocksize; | 5748 | sector_size = inode->i_sb->s_blocksize; |
| 5657 | 5749 | ||
| @@ -5667,12 +5759,11 @@ static int set_file_position_info(struct ksmbd_file *fp, char *buf) · 9 unmodified lines | |||
| 5667 | return 0; | 5759 | return 0; |
| 5668 | } | 5760 | } |
| 5669 | 5761 | ||
| 5670 | static int set_file_mode_info(struct ksmbd_file *fp, char *buf) | 5762 | static int set_file_mode_info(struct ksmbd_file *fp, |
| 5763 | struct smb2_file_mode_info *file_info) | ||
| 5671 | { | 5764 | { |
| 5672 | struct smb2_file_mode_info *file_info; | ||
| 5673 | __le32 mode; | 5765 | __le32 mode; |
| 5674 | 5766 | ||
| 5675 | file_info = (struct smb2_file_mode_info *)buf; | ||
| 5676 | mode = file_info->Mode; | 5767 | mode = file_info->Mode; |
| 5677 | 5768 | ||
| 5678 | if ((mode & ~FILE_MODE_INFO_MASK) || | 5769 | if ((mode & ~FILE_MODE_INFO_MASK) || |
| @@ -5702,40 +5793,74 @@ static int set_file_mode_info(struct ksmbd_file *fp, char *buf) · 23 unmodified lines | |||
| 5702 | * TODO: need to implement an error handling for STATUS_INFO_LENGTH_MISMATCH | 5793 | * TODO: need to implement an error handling for STATUS_INFO_LENGTH_MISMATCH |
| 5703 | */ | 5794 | */ |
| 5704 | static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, | 5795 | static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, |
| 5705 | int info_class, char *buf, | 5796 | struct smb2_set_info_req *req, |
| 5706 | struct ksmbd_share_config *share) | 5797 | struct ksmbd_share_config *share) |
| 5707 | { | 5798 | { |
| 5708 | switch (info_class) { | 5799 | unsigned int buf_len = le32_to_cpu(req->BufferLength); |
| 5800 | |||
| 5801 | switch (req->FileInfoClass) { | ||
| 5709 | case FILE_BASIC_INFORMATION: | 5802 | case FILE_BASIC_INFORMATION: |
| 5710 | return set_file_basic_info(fp, buf, share); | 5803 | { |
| 5804 | if (buf_len < sizeof(struct smb2_file_basic_info)) | ||
| 5805 | return -EINVAL; | ||
| 5711 | 5806 | ||
| 5807 | return set_file_basic_info(fp, (struct smb2_file_basic_info *)req->Buffer, share); | ||
| 5808 | } | ||
| 5712 | case FILE_ALLOCATION_INFORMATION: | 5809 | case FILE_ALLOCATION_INFORMATION: |
| 5713 | return set_file_allocation_info(work, fp, buf); | 5810 | { |
| 5811 | if (buf_len < sizeof(struct smb2_file_alloc_info)) | ||
| 5812 | return -EINVAL; | ||
| 5714 | 5813 | ||
| 5814 | return set_file_allocation_info(work, fp, | ||
| 5815 | (struct smb2_file_alloc_info *)req->Buffer); | ||
| 5816 | } | ||
| 5715 | case FILE_END_OF_FILE_INFORMATION: | 5817 | case FILE_END_OF_FILE_INFORMATION: |
| 5716 | return set_end_of_file_info(work, fp, buf); | 5818 | { |
| 5819 | if (buf_len < sizeof(struct smb2_file_eof_info)) | ||
| 5820 | return -EINVAL; | ||
| 5717 | 5821 | ||
| 5822 | return set_end_of_file_info(work, fp, | ||
| 5823 | (struct smb2_file_eof_info *)req->Buffer); | ||
| 5824 | } | ||
| 5718 | case FILE_RENAME_INFORMATION: | 5825 | case FILE_RENAME_INFORMATION: |
| 5826 | { | ||
| 5719 | if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { | 5827 | if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { |
| 5720 | ksmbd_debug(SMB, | 5828 | ksmbd_debug(SMB, |
| 5721 | "User does not have write permission\n"); | 5829 | "User does not have write permission\n"); |
| 5722 | return -EACCES; | 5830 | return -EACCES; |
| 5723 | } | 5831 | } |
| 5724 | return set_rename_info(work, fp, buf); | ||
| 5725 | 5832 | ||
| 5833 | if (buf_len < sizeof(struct smb2_file_rename_info)) | ||
| 5834 | return -EINVAL; | ||
| 5835 | |||
| 5836 | return set_rename_info(work, fp, | ||
| 5837 | (struct smb2_file_rename_info *)req->Buffer, | ||
| 5838 | buf_len); | ||
| 5839 | } | ||
| 5726 | case FILE_LINK_INFORMATION: | 5840 | case FILE_LINK_INFORMATION: |
| 5841 | { | ||
| 5842 | if (buf_len < sizeof(struct smb2_file_link_info)) | ||
| 5843 | return -EINVAL; | ||
| 5844 | |||
| 5727 | return smb2_create_link(work, work->tcon->share_conf, | 5845 | return smb2_create_link(work, work->tcon->share_conf, |
| 5728 | (struct smb2_file_link_info *)buf, fp->filp, | 5846 | (struct smb2_file_link_info *)req->Buffer, |
| 5847 | buf_len, fp->filp, | ||
| 5729 | work->sess->conn->local_nls); | 5848 | work->sess->conn->local_nls); |
| 5730 | 5849 | } | |
| 5731 | case FILE_DISPOSITION_INFORMATION: | 5850 | case FILE_DISPOSITION_INFORMATION: |
| 5851 | { | ||
| 5732 | if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { | 5852 | if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { |
| 5733 | ksmbd_debug(SMB, | 5853 | ksmbd_debug(SMB, |
| 5734 | "User does not have write permission\n"); | 5854 | "User does not have write permission\n"); |
| 5735 | return -EACCES; | 5855 | return -EACCES; |
| 5736 | } | 5856 | } |
| 5737 | return set_file_disposition_info(fp, buf); | ||
| 5738 | 5857 | ||
| 5858 | if (buf_len < sizeof(struct smb2_file_disposition_info)) | ||
| 5859 | return -EINVAL; | ||
| 5860 | |||
| 5861 | return set_file_disposition_info(fp, | ||
| 5862 | (struct smb2_file_disposition_info *)req->Buffer); | ||
| 5863 | } | ||
| 5739 | case FILE_FULL_EA_INFORMATION: | 5864 | case FILE_FULL_EA_INFORMATION: |
| 5740 | { | 5865 | { |
| 5741 | if (!(fp->daccess & FILE_WRITE_EA_LE)) { | 5866 | if (!(fp->daccess & FILE_WRITE_EA_LE)) { |
| @@ -5744,18 +5869,29 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, · 2 unmodified lines | |||
| 5744 | return -EACCES; | 5869 | return -EACCES; |
| 5745 | } | 5870 | } |
| 5746 | 5871 | ||
| 5747 | return smb2_set_ea((struct smb2_ea_info *)buf, | 5872 | if (buf_len < sizeof(struct smb2_ea_info)) |
| 5748 | &fp->filp->f_path); | 5873 | return -EINVAL; |
| 5749 | } | ||
| 5750 | 5874 | ||
| 5875 | return smb2_set_ea((struct smb2_ea_info *)req->Buffer, | ||
| 5876 | buf_len, &fp->filp->f_path); | ||
| 5877 | } | ||
| 5751 | case FILE_POSITION_INFORMATION: | 5878 | case FILE_POSITION_INFORMATION: |
| 5752 | return set_file_position_info(fp, buf); | 5879 | { |
| 5880 | if (buf_len < sizeof(struct smb2_file_pos_info)) | ||
| 5881 | return -EINVAL; | ||
| 5753 | 5882 | ||
| 5883 | return set_file_position_info(fp, (struct smb2_file_pos_info *)req->Buffer); | ||
| 5884 | } | ||
| 5754 | case FILE_MODE_INFORMATION: | 5885 | case FILE_MODE_INFORMATION: |
| 5755 | return set_file_mode_info(fp, buf); | 5886 | { |
| 5887 | if (buf_len < sizeof(struct smb2_file_mode_info)) | ||
| 5888 | return -EINVAL; | ||
| 5889 | |||
| 5890 | return set_file_mode_info(fp, (struct smb2_file_mode_info *)req->Buffer); | ||
| 5891 | } | ||
| 5756 | } | 5892 | } |
| 5757 | 5893 | ||
| 5758 | pr_err("Unimplemented Fileinfoclass :%d\n", info_class); | 5894 | pr_err("Unimplemented Fileinfoclass :%d\n", req->FileInfoClass); |
| 5759 | return -EOPNOTSUPP; | 5895 | return -EOPNOTSUPP; |
| 5760 | } | 5896 | } |
| 5761 | 5897 | ||
| @@ -5816,8 +5952,7 @@ int smb2_set_info(struct ksmbd_work *work) · 54 unmodified lines | |||
| 5816 | switch (req->InfoType) { | 5952 | switch (req->InfoType) { |
| 5817 | case SMB2_O_INFO_FILE: | 5953 | case SMB2_O_INFO_FILE: |
| 5818 | ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n"); | 5954 | ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n"); |
| 5819 | rc = smb2_set_info_file(work, fp, req->FileInfoClass, | 5955 | rc = smb2_set_info_file(work, fp, req, work->tcon->share_conf); |
| 5820 | req->Buffer, work->tcon->share_conf); | ||
| 5821 | break; | 5956 | break; |
| 5822 | case SMB2_O_INFO_SECURITY: | 5957 | case SMB2_O_INFO_SECURITY: |
| 5823 | ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n"); | 5958 | ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n"); |
| @@ -8171,7 +8306,8 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work) · 2347 unmodified lines | |||
| 8171 | 8306 | ||
| 8172 | WORK_BUFFERS(work, req, rsp); | 8307 | WORK_BUFFERS(work, req, rsp); |
| 8173 | 8308 | ||
| 8174 | if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE) | 8309 | if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE && |
| 8310 | conn->preauth_info) | ||
| 8175 | ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp, | 8311 | ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp, |
| 8176 | conn->preauth_info->Preauth_HashValue); | 8312 | conn->preauth_info->Preauth_HashValue); |
| 8177 | 8313 | ||
| @@ -8278,16 +8414,8 @@ int smb3_decrypt_req(struct ksmbd_work *work) · 100 unmodified lines | |||
| 8278 | unsigned int buf_data_size = pdu_length + 4 - | 8414 | unsigned int buf_data_size = pdu_length + 4 - |
| 8279 | sizeof(struct smb2_transform_hdr); | 8415 | sizeof(struct smb2_transform_hdr); |
| 8280 | struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; | 8416 | struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; |
| 8281 | unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize); | ||
| 8282 | int rc = 0; | 8417 | int rc = 0; |
| 8283 | 8418 | ||
| 8284 | sess = ksmbd_session_lookup_all(conn, le64_to_cpu(tr_hdr->SessionId)); | ||
| 8285 | if (!sess) { | ||
| 8286 | pr_err("invalid session id(%llx) in transform header\n", | ||
| 8287 | le64_to_cpu(tr_hdr->SessionId)); | ||
| 8288 | return -ECONNABORTED; | ||
| 8289 | } | ||
| 8290 | |||
| 8291 | if (pdu_length + 4 < | 8419 | if (pdu_length + 4 < |
| 8292 | sizeof(struct smb2_transform_hdr) + sizeof(struct smb2_hdr)) { | 8420 | sizeof(struct smb2_transform_hdr) + sizeof(struct smb2_hdr)) { |
| 8293 | pr_err("Transform message is too small (%u)\n", | 8421 | pr_err("Transform message is too small (%u)\n", |
| @@ -8295,11 +8423,19 @@ int smb3_decrypt_req(struct ksmbd_work *work) · 1 unmodified line | |||
| 8295 | return -ECONNABORTED; | 8423 | return -ECONNABORTED; |
| 8296 | } | 8424 | } |
| 8297 | 8425 | ||
| 8298 | if (pdu_length + 4 < orig_len + sizeof(struct smb2_transform_hdr)) { | 8426 | if (pdu_length + 4 < |
| 8427 | le32_to_cpu(tr_hdr->OriginalMessageSize) + sizeof(struct smb2_transform_hdr)) { | ||
| 8299 | pr_err("Transform message is broken\n"); | 8428 | pr_err("Transform message is broken\n"); |
| 8300 | return -ECONNABORTED; | 8429 | return -ECONNABORTED; |
| 8301 | } | 8430 | } |
| 8302 | 8431 | ||
| 8432 | sess = ksmbd_session_lookup_all(conn, le64_to_cpu(tr_hdr->SessionId)); | ||
| 8433 | if (!sess) { | ||
| 8434 | pr_err("invalid session id(%llx) in transform header\n", | ||
| 8435 | le64_to_cpu(tr_hdr->SessionId)); | ||
| 8436 | return -ECONNABORTED; | ||
| 8437 | } | ||
| 8438 | |||
| 8303 | iov[0].iov_base = buf; | 8439 | iov[0].iov_base = buf; |
| 8304 | iov[0].iov_len = sizeof(struct smb2_transform_hdr); | 8440 | iov[0].iov_len = sizeof(struct smb2_transform_hdr); |
| 8305 | iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr); | 8441 | iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr); |
| @@ -1464,6 +1464,15 @@ struct smb2_file_all_info { /* data block encoding of response to level 18 */ · 1463 unmodified lines | |||
| 1464 | char FileName[1]; | 1464 | char FileName[1]; |
| 1465 | } __packed; /* level 18 Query */ | 1465 | } __packed; /* level 18 Query */ |
| 1466 | 1466 | ||
| 1467 | struct smb2_file_basic_info { /* data block encoding of response to level 18 */ | ||
| 1468 | __le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */ | ||
| 1469 | __le64 LastAccessTime; | ||
| 1470 | __le64 LastWriteTime; | ||
| 1471 | __le64 ChangeTime; | ||
| 1472 | __le32 Attributes; | ||
| 1473 | __u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */ | ||
| 1474 | } __packed; | ||
| 1475 | |||
| 1467 | struct smb2_file_alt_name_info { | 1476 | struct smb2_file_alt_name_info { |
| 1468 | __le32 FileNameLength; | 1477 | __le32 FileNameLength; |
| 1469 | char FileName[0]; | 1478 | char FileName[0]; |
| @@ -155,20 +155,7 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work) · 154 unmodified lines | |||
| 155 | */ | 155 | */ |
| 156 | bool ksmbd_smb_request(struct ksmbd_conn *conn) | 156 | bool ksmbd_smb_request(struct ksmbd_conn *conn) |
| 157 | { | 157 | { |
| 158 | int type = *(char *)conn->request_buf; | 158 | return conn->request_buf[0] == 0; |
| 159 | |||
| 160 | switch (type) { | ||
| 161 | case RFC1002_SESSION_MESSAGE: | ||
| 162 | /* Regular SMB request */ | ||
| 163 | return true; | ||
| 164 | case RFC1002_SESSION_KEEP_ALIVE: | ||
| 165 | ksmbd_debug(SMB, "RFC 1002 session keep alive\n"); | ||
| 166 | break; | ||
| 167 | default: | ||
| 168 | ksmbd_debug(SMB, "RFC 1002 unknown request type 0x%x\n", type); | ||
| 169 | } | ||
| 170 | |||
| 171 | return false; | ||
| 172 | } | 159 | } |
| 173 | 160 | ||
| 174 | static bool supported_protocol(int idx) | 161 | static bool supported_protocol(int idx) |
| @@ -182,10 +169,12 @@ static bool supported_protocol(int idx) · 7 unmodified lines | |||
| 182 | idx <= server_conf.max_protocol); | 169 | idx <= server_conf.max_protocol); |
| 183 | } | 170 | } |
| 184 | 171 | ||
| 185 | static char *next_dialect(char *dialect, int *next_off) | 172 | static char *next_dialect(char *dialect, int *next_off, int bcount) |
| 186 | { | 173 | { |
| 187 | dialect = dialect + *next_off; | 174 | dialect = dialect + *next_off; |
| 188 | *next_off = strlen(dialect); | 175 | *next_off = strnlen(dialect, bcount); |
| 176 | if (dialect[*next_off] != '\0') | ||
| 177 | return NULL; | ||
| 189 | return dialect; | 178 | return dialect; |
| 190 | } | 179 | } |
| 191 | 180 | ||
| @@ -200,7 +189,9 @@ static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count) · 8 unmodified lines | |||
| 200 | dialect = cli_dialects; | 189 | dialect = cli_dialects; |
| 201 | bcount = le16_to_cpu(byte_count); | 190 | bcount = le16_to_cpu(byte_count); |
| 202 | do { | 191 | do { |
| 203 | dialect = next_dialect(dialect, &next); | 192 | dialect = next_dialect(dialect, &next, bcount); |
| 193 | if (!dialect) | ||
| 194 | break; | ||
| 204 | ksmbd_debug(SMB, "client requested dialect %s\n", | 195 | ksmbd_debug(SMB, "client requested dialect %s\n", |
| 205 | dialect); | 196 | dialect); |
| 206 | if (!strcmp(dialect, smb1_protos[i].name)) { | 197 | if (!strcmp(dialect, smb1_protos[i].name)) { |
| @@ -248,13 +239,22 @@ int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count) · 41 unmodified lines | |||
| 248 | 239 | ||
| 249 | static int ksmbd_negotiate_smb_dialect(void *buf) | 240 | static int ksmbd_negotiate_smb_dialect(void *buf) |
| 250 | { | 241 | { |
| 251 | __le32 proto; | 242 | int smb_buf_length = get_rfc1002_len(buf); |
| 243 | __le32 proto = ((struct smb2_hdr *)buf)->ProtocolId; | ||
| 252 | 244 | ||
| 253 | proto = ((struct smb2_hdr *)buf)->ProtocolId; | ||
| 254 | if (proto == SMB2_PROTO_NUMBER) { | 245 | if (proto == SMB2_PROTO_NUMBER) { |
| 255 | struct smb2_negotiate_req *req; | 246 | struct smb2_negotiate_req *req; |
| 247 | int smb2_neg_size = | ||
| 248 | offsetof(struct smb2_negotiate_req, Dialects) - 4; | ||
| 256 | 249 | ||
| 257 | req = (struct smb2_negotiate_req *)buf; | 250 | req = (struct smb2_negotiate_req *)buf; |
| 251 | if (smb2_neg_size > smb_buf_length) | ||
| 252 | goto err_out; | ||
| 253 | |||
| 254 | if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > | ||
| 255 | smb_buf_length) | ||
| 256 | goto err_out; | ||
| 257 | |||
| 258 | return ksmbd_lookup_dialect_by_id(req->Dialects, | 258 | return ksmbd_lookup_dialect_by_id(req->Dialects, |
| 259 | req->DialectCount); | 259 | req->DialectCount); |
| 260 | } | 260 | } |
| @@ -264,10 +264,19 @@ static int ksmbd_negotiate_smb_dialect(void *buf) · 3 unmodified lines | |||
| 264 | struct smb_negotiate_req *req; | 264 | struct smb_negotiate_req *req; |
| 265 | 265 | ||
| 266 | req = (struct smb_negotiate_req *)buf; | 266 | req = (struct smb_negotiate_req *)buf; |
| 267 | if (le16_to_cpu(req->ByteCount) < 2) | ||
| 268 | goto err_out; | ||
| 269 | |||
| 270 | if (offsetof(struct smb_negotiate_req, DialectsArray) - 4 + | ||
| 271 | le16_to_cpu(req->ByteCount) > smb_buf_length) { | ||
| 272 | goto err_out; | ||
| 273 | } | ||
| 274 | |||
| 267 | return ksmbd_lookup_dialect_by_name(req->DialectsArray, | 275 | return ksmbd_lookup_dialect_by_name(req->DialectsArray, |
| 268 | req->ByteCount); | 276 | req->ByteCount); |
| 269 | } | 277 | } |
| 270 | 278 | ||
| 279 | err_out: | ||
| 271 | return BAD_PROT_ID; | 280 | return BAD_PROT_ID; |
| 272 | } | 281 | } |
| 273 | 282 | ||
| @@ -48,14 +48,6 @@ · 47 unmodified lines | |||
| 48 | #define CIFS_DEFAULT_IOSIZE (64 * 1024) | 48 | #define CIFS_DEFAULT_IOSIZE (64 * 1024) |
| 49 | #define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */ | 49 | #define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */ |
| 50 | 50 | ||
| 51 | /* RFC 1002 session packet types */ | ||
| 52 | #define RFC1002_SESSION_MESSAGE 0x00 | ||
| 53 | #define RFC1002_SESSION_REQUEST 0x81 | ||
| 54 | #define RFC1002_POSITIVE_SESSION_RESPONSE 0x82 | ||
| 55 | #define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83 | ||
| 56 | #define RFC1002_RETARGET_SESSION_RESPONSE 0x84 | ||
| 57 | #define RFC1002_SESSION_KEEP_ALIVE 0x85 | ||
| 58 | |||
| 59 | /* Responses when opening a file. */ | 51 | /* Responses when opening a file. */ |
| 60 | #define F_SUPERSEDED 0 | 52 | #define F_SUPERSEDED 0 |
| 61 | #define F_OPENED 1 | 53 | #define F_OPENED 1 |
| @@ -380,7 +380,7 @@ static void parse_dacl(struct user_namespace *user_ns, · 379 unmodified lines | |||
| 380 | { | 380 | { |
| 381 | int i, ret; | 381 | int i, ret; |
| 382 | int num_aces = 0; | 382 | int num_aces = 0; |
| 383 | int acl_size; | 383 | unsigned int acl_size; |
| 384 | char *acl_base; | 384 | char *acl_base; |
| 385 | struct smb_ace **ppace; | 385 | struct smb_ace **ppace; |
| 386 | struct posix_acl_entry *cf_pace, *cf_pdace; | 386 | struct posix_acl_entry *cf_pace, *cf_pdace; |
| @@ -392,7 +392,7 @@ static void parse_dacl(struct user_namespace *user_ns, · 5 unmodified lines | |||
| 392 | return; | 392 | return; |
| 393 | 393 | ||
| 394 | /* validate that we do not go past end of acl */ | 394 | /* validate that we do not go past end of acl */ |
| 395 | if (end_of_acl <= (char *)pdacl || | 395 | if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) || |
| 396 | end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { | 396 | end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { |
| 397 | pr_err("ACL too small to parse DACL\n"); | 397 | pr_err("ACL too small to parse DACL\n"); |
| 398 | return; | 398 | return; |
| @@ -431,8 +431,22 @@ static void parse_dacl(struct user_namespace *user_ns, · 32 unmodified lines | |||
| 431 | * user/group/other have no permissions | 431 | * user/group/other have no permissions |
| 432 | */ | 432 | */ |
| 433 | for (i = 0; i < num_aces; ++i) { | 433 | for (i = 0; i < num_aces; ++i) { |
| 434 | if (end_of_acl - acl_base < acl_size) | ||
| 435 | break; | ||
| 436 | |||
| 434 | ppace[i] = (struct smb_ace *)(acl_base + acl_size); | 437 | ppace[i] = (struct smb_ace *)(acl_base + acl_size); |
| 435 | acl_base = (char *)ppace[i]; | 438 | acl_base = (char *)ppace[i]; |
| 439 | acl_size = offsetof(struct smb_ace, sid) + | ||
| 440 | offsetof(struct smb_sid, sub_auth); | ||
| 441 | |||
| 442 | if (end_of_acl - acl_base < acl_size || | ||
| 443 | ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES || | ||
| 444 | (end_of_acl - acl_base < | ||
| 445 | acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) || | ||
| 446 | (le16_to_cpu(ppace[i]->size) < | ||
| 447 | acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth)) | ||
| 448 | break; | ||
| 449 | |||
| 436 | acl_size = le16_to_cpu(ppace[i]->size); | 450 | acl_size = le16_to_cpu(ppace[i]->size); |
| 437 | ppace[i]->access_req = | 451 | ppace[i]->access_req = |
| 438 | smb_map_generic_desired_access(ppace[i]->access_req); | 452 | smb_map_generic_desired_access(ppace[i]->access_req); |
| @@ -807,6 +821,9 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, · 368 unmodified lines | |||
| 807 | if (!pntsd) | 821 | if (!pntsd) |
| 808 | return -EIO; | 822 | return -EIO; |
| 809 | 823 | ||
| 824 | if (acl_len < sizeof(struct smb_ntsd)) | ||
| 825 | return -EINVAL; | ||
| 826 | |||
| 810 | owner_sid_ptr = (struct smb_sid *)((char *)pntsd + | 827 | owner_sid_ptr = (struct smb_sid *)((char *)pntsd + |
| 811 | le32_to_cpu(pntsd->osidoffset)); | 828 | le32_to_cpu(pntsd->osidoffset)); |
| 812 | group_sid_ptr = (struct smb_sid *)((char *)pntsd + | 829 | group_sid_ptr = (struct smb_sid *)((char *)pntsd + |
| @@ -215,7 +215,7 @@ out_error: · 214 unmodified lines | |||
| 215 | * ksmbd_kthread_fn() - listen to new SMB connections and callback server | 215 | * ksmbd_kthread_fn() - listen to new SMB connections and callback server |
| 216 | * @p: arguments to forker thread | 216 | * @p: arguments to forker thread |
| 217 | * | 217 | * |
| 218 | * Return: Returns a task_struct or ERR_PTR | 218 | * Return: 0 on success, error number otherwise |
| 219 | */ | 219 | */ |
| 220 | static int ksmbd_kthread_fn(void *p) | 220 | static int ksmbd_kthread_fn(void *p) |
| 221 | { | 221 | { |
| @@ -387,7 +387,7 @@ static void tcp_destroy_socket(struct socket *ksmbd_socket) · 165 unmodified lines | |||
| 387 | /** | 387 | /** |
| 388 | * create_socket - create socket for ksmbd/0 | 388 | * create_socket - create socket for ksmbd/0 |
| 389 | * | 389 | * |
| 390 | * Return: Returns a task_struct or ERR_PTR | 390 | * Return: 0 on success, error number otherwise |
| 391 | */ | 391 | */ |
| 392 | static int create_socket(struct interface *iface) | 392 | static int create_socket(struct interface *iface) |
| 393 | { | 393 | { |
| @@ -21,10 +21,7 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ | 22 | #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ |
| 23 | 23 | ||
| 24 | #define VBSF_MOUNT_SIGNATURE_BYTE_0 ('\000') | 24 | static const unsigned char VBSF_MOUNT_SIGNATURE[4] = "\000\377\376\375"; |
| 25 | #define VBSF_MOUNT_SIGNATURE_BYTE_1 ('\377') | ||
| 26 | #define VBSF_MOUNT_SIGNATURE_BYTE_2 ('\376') | ||
| 27 | #define VBSF_MOUNT_SIGNATURE_BYTE_3 ('\375') | ||
| 28 | 25 | ||
| 29 | static int follow_symlinks; | 26 | static int follow_symlinks; |
| 30 | module_param(follow_symlinks, int, 0444); | 27 | module_param(follow_symlinks, int, 0444); |
| @@ -386,12 +383,7 @@ fail_nomem: · 355 unmodified lines | |||
| 386 | 383 | ||
| 387 | static int vboxsf_parse_monolithic(struct fs_context *fc, void *data) | 384 | static int vboxsf_parse_monolithic(struct fs_context *fc, void *data) |
| 388 | { | 385 | { |
| 389 | unsigned char *options = data; | 386 | if (data && !memcmp(data, VBSF_MOUNT_SIGNATURE, 4)) { |
| 390 | |||
| 391 | if (options && options[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 && | ||
| 392 | options[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 && | ||
| 393 | options[2] == VBSF_MOUNT_SIGNATURE_BYTE_2 && | ||
| 394 | options[3] == VBSF_MOUNT_SIGNATURE_BYTE_3) { | ||
| 395 | vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n"); | 387 | vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n"); |
| 396 | return -EINVAL; | 388 | return -EINVAL; |
| 397 | } | 389 | } |
| @@ -177,7 +177,7 @@ static int build_merkle_tree(struct file *filp, · 176 unmodified lines | |||
| 177 | * (level 0) and ascending to the root node (level 'num_levels - 1'). | 177 | * (level 0) and ascending to the root node (level 'num_levels - 1'). |
| 178 | * Then at the end (level 'num_levels'), calculate the root hash. | 178 | * Then at the end (level 'num_levels'), calculate the root hash. |
| 179 | */ | 179 | */ |
| 180 | blocks = (inode->i_size + params->block_size - 1) >> | 180 | blocks = ((u64)inode->i_size + params->block_size - 1) >> |
| 181 | params->log_blocksize; | 181 | params->log_blocksize; |
| 182 | for (level = 0; level <= params->num_levels; level++) { | 182 | for (level = 0; level <= params->num_levels; level++) { |
| 183 | err = build_merkle_tree_level(filp, level, blocks, params, | 183 | err = build_merkle_tree_level(filp, level, blocks, params, |
| @@ -89,7 +89,7 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params, · 88 unmodified lines | |||
| 89 | */ | 89 | */ |
| 90 | 90 | ||
| 91 | /* Compute number of levels and the number of blocks in each level */ | 91 | /* Compute number of levels and the number of blocks in each level */ |
| 92 | blocks = (inode->i_size + params->block_size - 1) >> log_blocksize; | 92 | blocks = ((u64)inode->i_size + params->block_size - 1) >> log_blocksize; |
| 93 | pr_debug("Data is %lld bytes (%llu blocks)\n", inode->i_size, blocks); | 93 | pr_debug("Data is %lld bytes (%llu blocks)\n", inode->i_size, blocks); |
| 94 | while (blocks > 1) { | 94 | while (blocks > 1) { |
| 95 | if (params->num_levels >= FS_VERITY_MAX_LEVELS) { | 95 | if (params->num_levels >= FS_VERITY_MAX_LEVELS) { |
| @@ -61,7 +61,6 @@ int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu, · 60 unmodified lines | |||
| 61 | int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, | 61 | int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, |
| 62 | struct kvm_device_attr *attr); | 62 | struct kvm_device_attr *attr); |
| 63 | int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu); | 63 | int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu); |
| 64 | int kvm_pmu_probe_pmuver(void); | ||
| 65 | #else | 64 | #else |
| 66 | struct kvm_pmu { | 65 | struct kvm_pmu { |
| 67 | }; | 66 | }; |
| @@ -118,8 +117,6 @@ static inline u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1) · 50 unmodified lines | |||
| 118 | return 0; | 117 | return 0; |
| 119 | } | 118 | } |
| 120 | 119 | ||
| 121 | static inline int kvm_pmu_probe_pmuver(void) { return 0xf; } | ||
| 122 | |||
| 123 | #endif | 120 | #endif |
| 124 | 121 | ||
| 125 | #endif | 122 | #endif |
| @@ -578,11 +578,12 @@ struct btf_func_model { · 577 unmodified lines | |||
| 578 | * programs only. Should not be used with normal calls and indirect calls. | 578 | * programs only. Should not be used with normal calls and indirect calls. |
| 579 | */ | 579 | */ |
| 580 | #define BPF_TRAMP_F_SKIP_FRAME BIT(2) | 580 | #define BPF_TRAMP_F_SKIP_FRAME BIT(2) |
| 581 | |||
| 582 | /* Store IP address of the caller on the trampoline stack, | 581 | /* Store IP address of the caller on the trampoline stack, |
| 583 | * so it's available for trampoline's programs. | 582 | * so it's available for trampoline's programs. |
| 584 | */ | 583 | */ |
| 585 | #define BPF_TRAMP_F_IP_ARG BIT(3) | 584 | #define BPF_TRAMP_F_IP_ARG BIT(3) |
| 585 | /* Return the return value of fentry prog. Only used by bpf_struct_ops. */ | ||
| 586 | #define BPF_TRAMP_F_RET_FENTRY_RET BIT(4) | ||
| 586 | 587 | ||
| 587 | /* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50 | 588 | /* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50 |
| 588 | * bytes on x86. Pick a number to fit into BPF_IMAGE_SIZE / 2 | 589 | * bytes on x86. Pick a number to fit into BPF_IMAGE_SIZE / 2 |
| @@ -996,14 +996,15 @@ cpumap_print_to_pagebuf(bool list, char *buf, const struct cpumask *mask) · 995 unmodified lines | |||
| 996 | * cpumask; Typically used by bin_attribute to export cpumask bitmask | 996 | * cpumask; Typically used by bin_attribute to export cpumask bitmask |
| 997 | * ABI. | 997 | * ABI. |
| 998 | * | 998 | * |
| 999 | * Returns the length of how many bytes have been copied. | 999 | * Returns the length of how many bytes have been copied, excluding |
| 1000 | * terminating '\0'. | ||
| 1000 | */ | 1001 | */ |
| 1001 | static inline ssize_t | 1002 | static inline ssize_t |
| 1002 | cpumap_print_bitmask_to_buf(char *buf, const struct cpumask *mask, | 1003 | cpumap_print_bitmask_to_buf(char *buf, const struct cpumask *mask, |
| 1003 | loff_t off, size_t count) | 1004 | loff_t off, size_t count) |
| 1004 | { | 1005 | { |
| 1005 | return bitmap_print_bitmask_to_buf(buf, cpumask_bits(mask), | 1006 | return bitmap_print_bitmask_to_buf(buf, cpumask_bits(mask), |
| 1006 | nr_cpu_ids, off, count); | 1007 | nr_cpu_ids, off, count) - 1; |
| 1007 | } | 1008 | } |
| 1008 | 1009 | ||
| 1009 | /** | 1010 | /** |
| @@ -1018,7 +1019,7 @@ cpumap_print_list_to_buf(char *buf, const struct cpumask *mask, · 8 unmodified lines | |||
| 1018 | loff_t off, size_t count) | 1019 | loff_t off, size_t count) |
| 1019 | { | 1020 | { |
| 1020 | return bitmap_print_list_to_buf(buf, cpumask_bits(mask), | 1021 | return bitmap_print_list_to_buf(buf, cpumask_bits(mask), |
| 1021 | nr_cpu_ids, off, count); | 1022 | nr_cpu_ids, off, count) - 1; |
| 1022 | } | 1023 | } |
| 1023 | 1024 | ||
| 1024 | #if NR_CPUS <= BITS_PER_LONG | 1025 | #if NR_CPUS <= BITS_PER_LONG |
| @@ -22,10 +22,15 @@ struct device; · 21 unmodified lines | |||
| 22 | * LINKS_ADDED: The fwnode has already be parsed to add fwnode links. | 22 | * LINKS_ADDED: The fwnode has already be parsed to add fwnode links. |
| 23 | * NOT_DEVICE: The fwnode will never be populated as a struct device. | 23 | * NOT_DEVICE: The fwnode will never be populated as a struct device. |
| 24 | * INITIALIZED: The hardware corresponding to fwnode has been initialized. | 24 | * INITIALIZED: The hardware corresponding to fwnode has been initialized. |
| 25 | * NEEDS_CHILD_BOUND_ON_ADD: For this fwnode/device to probe successfully, its | ||
| 26 | * driver needs its child devices to be bound with | ||
| 27 | * their respective drivers as soon as they are | ||
| 28 | * added. | ||
| 25 | */ | 29 | */ |
| 26 | #define FWNODE_FLAG_LINKS_ADDED BIT(0) | 30 | #define FWNODE_FLAG_LINKS_ADDED BIT(0) |
| 27 | #define FWNODE_FLAG_NOT_DEVICE BIT(1) | 31 | #define FWNODE_FLAG_NOT_DEVICE BIT(1) |
| 28 | #define FWNODE_FLAG_INITIALIZED BIT(2) | 32 | #define FWNODE_FLAG_INITIALIZED BIT(2) |
| 33 | #define FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD BIT(3) | ||
| 29 | 34 | ||
| 30 | struct fwnode_handle { | 35 | struct fwnode_handle { |
| 31 | struct fwnode_handle *secondary; | 36 | struct fwnode_handle *secondary; |
| @@ -608,7 +608,6 @@ struct kvm { · 607 unmodified lines | |||
| 608 | unsigned long mmu_notifier_range_start; | 608 | unsigned long mmu_notifier_range_start; |
| 609 | unsigned long mmu_notifier_range_end; | 609 | unsigned long mmu_notifier_range_end; |
| 610 | #endif | 610 | #endif |
| 611 | long tlbs_dirty; | ||
| 612 | struct list_head devices; | 611 | struct list_head devices; |
| 613 | u64 manual_dirty_log_protect; | 612 | u64 manual_dirty_log_protect; |
| 614 | struct dentry *debugfs_dentry; | 613 | struct dentry *debugfs_dentry; |
| @@ -721,11 +720,6 @@ static inline struct kvm_vcpu *kvm_get_vcpu_by_id(struct kvm *kvm, int id) · 106 unmodified lines | |||
| 721 | return NULL; | 720 | return NULL; |
| 722 | } | 721 | } |
| 723 | 722 | ||
| 724 | static inline int kvm_vcpu_get_idx(struct kvm_vcpu *vcpu) | ||
| 725 | { | ||
| 726 | return vcpu->vcpu_idx; | ||
| 727 | } | ||
| 728 | |||
| 729 | #define kvm_for_each_memslot(memslot, slots) \ | 723 | #define kvm_for_each_memslot(memslot, slots) \ |
| 730 | for (memslot = &slots->memslots[0]; \ | 724 | for (memslot = &slots->memslots[0]; \ |
| 731 | memslot < slots->memslots + slots->used_slots; memslot++) \ | 725 | memslot < slots->memslots + slots->used_slots; memslot++) \ |
| @@ -163,6 +163,12 @@ int arm_pmu_acpi_probe(armpmu_init_fn init_fn); · 162 unmodified lines | |||
| 163 | static inline int arm_pmu_acpi_probe(armpmu_init_fn init_fn) { return 0; } | 163 | static inline int arm_pmu_acpi_probe(armpmu_init_fn init_fn) { return 0; } |
| 164 | #endif | 164 | #endif |
| 165 | 165 | ||
| 166 | #ifdef CONFIG_KVM | ||
| 167 | void kvm_host_pmu_init(struct arm_pmu *pmu); | ||
| 168 | #else | ||
| 169 | #define kvm_host_pmu_init(x) do { } while(0) | ||
| 170 | #endif | ||
| 171 | |||
| 166 | /* Internal functions only for core arm_pmu code */ | 172 | /* Internal functions only for core arm_pmu code */ |
| 167 | struct arm_pmu *armpmu_alloc(void); | 173 | struct arm_pmu *armpmu_alloc(void); |
| 168 | struct arm_pmu *armpmu_alloc_atomic(void); | 174 | struct arm_pmu *armpmu_alloc_atomic(void); |
| @@ -683,7 +683,9 @@ struct perf_event { · 682 unmodified lines | |||
| 683 | /* | 683 | /* |
| 684 | * timestamp shadows the actual context timing but it can | 684 | * timestamp shadows the actual context timing but it can |
| 685 | * be safely used in NMI interrupt context. It reflects the | 685 | * be safely used in NMI interrupt context. It reflects the |
| 686 | * context time as it was when the event was last scheduled in. | 686 | * context time as it was when the event was last scheduled in, |
| 687 | * or when ctx_sched_in failed to schedule the event because we | ||
| 688 | * run out of PMC. | ||
| 687 | * | 689 | * |
| 688 | * ctx_time already accounts for ctx->timestamp. Therefore to | 690 | * ctx_time already accounts for ctx->timestamp. Therefore to |
| 689 | * compute ctx_time for a sample, simply add perf_clock(). | 691 | * compute ctx_time for a sample, simply add perf_clock(). |
| @@ -1720,7 +1720,7 @@ extern struct pid *cad_pid; · 1719 unmodified lines | |||
| 1720 | #define tsk_used_math(p) ((p)->flags & PF_USED_MATH) | 1720 | #define tsk_used_math(p) ((p)->flags & PF_USED_MATH) |
| 1721 | #define used_math() tsk_used_math(current) | 1721 | #define used_math() tsk_used_math(current) |
| 1722 | 1722 | ||
| 1723 | static inline bool is_percpu_thread(void) | 1723 | static __always_inline bool is_percpu_thread(void) |
| 1724 | { | 1724 | { |
| 1725 | #ifdef CONFIG_SMP | 1725 | #ifdef CONFIG_SMP |
| 1726 | return (current->flags & PF_NO_SETAFFINITY) && | 1726 | return (current->flags & PF_NO_SETAFFINITY) && |
| @@ -597,5 +597,5 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, · 596 unmodified lines | |||
| 597 | int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh, | 597 | int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh, |
| 598 | u8 rt_family, unsigned char *flags, bool skip_oif); | 598 | u8 rt_family, unsigned char *flags, bool skip_oif); |
| 599 | int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh, | 599 | int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh, |
| 600 | int nh_weight, u8 rt_family); | 600 | int nh_weight, u8 rt_family, u32 nh_tclassid); |
| 601 | #endif /* _NET_FIB_H */ | 601 | #endif /* _NET_FIB_H */ |
| @@ -2818,13 +2818,13 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); · 2817 unmodified lines | |||
| 2818 | * Mac80211 drivers should set the @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 flag | 2818 | * Mac80211 drivers should set the @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 flag |
| 2819 | * when they are able to replace in-use PTK keys according to the following | 2819 | * when they are able to replace in-use PTK keys according to the following |
| 2820 | * requirements: | 2820 | * requirements: |
| 2821 | * 1) They do not hand over frames decrypted with the old key to | 2821 | * 1) They do not hand over frames decrypted with the old key to mac80211 |
| 2822 | mac80211 once the call to set_key() with command %DISABLE_KEY has been | 2822 | once the call to set_key() with command %DISABLE_KEY has been completed, |
| 2823 | completed when also setting @IEEE80211_KEY_FLAG_GENERATE_IV for any key, | ||
| 2824 | 2) either drop or continue to use the old key for any outgoing frames queued | 2823 | 2) either drop or continue to use the old key for any outgoing frames queued |
| 2825 | at the time of the key deletion (including re-transmits), | 2824 | at the time of the key deletion (including re-transmits), |
| 2826 | 3) never send out a frame queued prior to the set_key() %SET_KEY command | 2825 | 3) never send out a frame queued prior to the set_key() %SET_KEY command |
| 2827 | encrypted with the new key and | 2826 | encrypted with the new key when also needing |
| 2827 | @IEEE80211_KEY_FLAG_GENERATE_IV and | ||
| 2828 | 4) never send out a frame unencrypted when it should be encrypted. | 2828 | 4) never send out a frame unencrypted when it should be encrypted. |
| 2829 | Mac80211 will not queue any new frames for a deleted key to the driver. | 2829 | Mac80211 will not queue any new frames for a deleted key to the driver. |
| 2830 | */ | 2830 | */ |
| @@ -325,7 +325,7 @@ int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh, · 324 unmodified lines | |||
| 325 | struct fib_nh_common *nhc = &nhi->fib_nhc; | 325 | struct fib_nh_common *nhc = &nhi->fib_nhc; |
| 326 | int weight = nhg->nh_entries[i].weight; | 326 | int weight = nhg->nh_entries[i].weight; |
| 327 | 327 | ||
| 328 | if (fib_add_nexthop(skb, nhc, weight, rt_family) < 0) | 328 | if (fib_add_nexthop(skb, nhc, weight, rt_family, 0) < 0) |
| 329 | return -EMSGSIZE; | 329 | return -EMSGSIZE; |
| 330 | } | 330 | } |
| 331 | 331 | ||
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <uapi/linux/pkt_sched.h> | 11 | #include <uapi/linux/pkt_sched.h> |
| 12 | 12 | ||
| 13 | #define DEFAULT_TX_QUEUE_LEN 1000 | 13 | #define DEFAULT_TX_QUEUE_LEN 1000 |
| 14 | #define STAB_SIZE_LOG_MAX 30 | ||
| 14 | 15 | ||
| 15 | struct qdisc_walker { | 16 | struct qdisc_walker { |
| 16 | int stop; | 17 | int stop; |
| @@ -488,8 +488,10 @@ struct sock { · 487 unmodified lines | |||
| 488 | u8 sk_prefer_busy_poll; | 488 | u8 sk_prefer_busy_poll; |
| 489 | u16 sk_busy_poll_budget; | 489 | u16 sk_busy_poll_budget; |
| 490 | #endif | 490 | #endif |
| 491 | spinlock_t sk_peer_lock; | ||
| 491 | struct pid *sk_peer_pid; | 492 | struct pid *sk_peer_pid; |
| 492 | const struct cred *sk_peer_cred; | 493 | const struct cred *sk_peer_cred; |
| 494 | |||
| 493 | long sk_rcvtimeo; | 495 | long sk_rcvtimeo; |
| 494 | ktime_t sk_stamp; | 496 | ktime_t sk_stamp; |
| 495 | #if BITS_PER_LONG==32 | 497 | #if BITS_PER_LONG==32 |
| @@ -1623,7 +1625,36 @@ void release_sock(struct sock *sk); · 1127 unmodified lines | |||
| 1623 | SINGLE_DEPTH_NESTING) | 1625 | SINGLE_DEPTH_NESTING) |
| 1624 | #define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock)) | 1626 | #define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock)) |
| 1625 | 1627 | ||
| 1626 | bool lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock); | 1628 | bool __lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock); |
| 1629 | |||
| 1630 | /** | ||
| 1631 | * lock_sock_fast - fast version of lock_sock | ||
| 1632 | * @sk: socket | ||
| 1633 | * | ||
| 1634 | * This version should be used for very small section, where process wont block | ||
| 1635 | * return false if fast path is taken: | ||
| 1636 | * | ||
| 1637 | * sk_lock.slock locked, owned = 0, BH disabled | ||
| 1638 | * | ||
| 1639 | * return true if slow path is taken: | ||
| 1640 | * | ||
| 1641 | * sk_lock.slock unlocked, owned = 1, BH enabled | ||
| 1642 | */ | ||
| 1643 | static inline bool lock_sock_fast(struct sock *sk) | ||
| 1644 | { | ||
| 1645 | /* The sk_lock has mutex_lock() semantics here. */ | ||
| 1646 | mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_); | ||
| 1647 | |||
| 1648 | return __lock_sock_fast(sk); | ||
| 1649 | } | ||
| 1650 | |||
| 1651 | /* fast socket lock variant for caller already holding a [different] socket lock */ | ||
| 1652 | static inline bool lock_sock_fast_nested(struct sock *sk) | ||
| 1653 | { | ||
| 1654 | mutex_acquire(&sk->sk_lock.dep_map, SINGLE_DEPTH_NESTING, 0, _RET_IP_); | ||
| 1655 | |||
| 1656 | return __lock_sock_fast(sk); | ||
| 1657 | } | ||
| 1627 | 1658 | ||
| 1628 | /** | 1659 | /** |
| 1629 | * unlock_sock_fast - complement of lock_sock_fast | 1660 | * unlock_sock_fast - complement of lock_sock_fast |
| @@ -98,6 +98,7 @@ struct snd_rawmidi_file { · 97 unmodified lines | |||
| 98 | struct snd_rawmidi *rmidi; | 98 | struct snd_rawmidi *rmidi; |
| 99 | struct snd_rawmidi_substream *input; | 99 | struct snd_rawmidi_substream *input; |
| 100 | struct snd_rawmidi_substream *output; | 100 | struct snd_rawmidi_substream *output; |
| 101 | unsigned int user_pversion; /* supported protocol version */ | ||
| 101 | }; | 102 | }; |
| 102 | 103 | ||
| 103 | struct snd_rawmidi_str { | 104 | struct snd_rawmidi_str { |
| @@ -305,7 +305,7 @@ TRACE_EVENT(cachefiles_mark_buried, · 304 unmodified lines | |||
| 305 | ), | 305 | ), |
| 306 | 306 | ||
| 307 | TP_fast_assign( | 307 | TP_fast_assign( |
| 308 | __entry->obj = obj->fscache.debug_id; | 308 | __entry->obj = obj ? obj->fscache.debug_id : UINT_MAX; |
| 309 | __entry->de = de; | 309 | __entry->de = de; |
| 310 | __entry->why = why; | 310 | __entry->why = why; |
| 311 | ), | 311 | ), |
| @@ -784,6 +784,7 @@ struct snd_rawmidi_status { · 783 unmodified lines | |||
| 784 | 784 | ||
| 785 | #define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) | 785 | #define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) |
| 786 | #define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info) | 786 | #define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info) |
| 787 | #define SNDRV_RAWMIDI_IOCTL_USER_PVERSION _IOW('W', 0x02, int) | ||
| 787 | #define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params) | 788 | #define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params) |
| 788 | #define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status) | 789 | #define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status) |
| 789 | #define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int) | 790 | #define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int) |
| @@ -368,6 +368,7 @@ static int bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, · 367 unmodified lines | |||
| 368 | const struct btf_type *mtype, *ptype; | 368 | const struct btf_type *mtype, *ptype; |
| 369 | struct bpf_prog *prog; | 369 | struct bpf_prog *prog; |
| 370 | u32 moff; | 370 | u32 moff; |
| 371 | u32 flags; | ||
| 371 | 372 | ||
| 372 | moff = btf_member_bit_offset(t, member) / 8; | 373 | moff = btf_member_bit_offset(t, member) / 8; |
| 373 | ptype = btf_type_resolve_ptr(btf_vmlinux, member->type, NULL); | 374 | ptype = btf_type_resolve_ptr(btf_vmlinux, member->type, NULL); |
| @@ -431,10 +432,12 @@ static int bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, · 57 unmodified lines | |||
| 431 | 432 | ||
| 432 | tprogs[BPF_TRAMP_FENTRY].progs[0] = prog; | 433 | tprogs[BPF_TRAMP_FENTRY].progs[0] = prog; |
| 433 | tprogs[BPF_TRAMP_FENTRY].nr_progs = 1; | 434 | tprogs[BPF_TRAMP_FENTRY].nr_progs = 1; |
| 435 | flags = st_ops->func_models[i].ret_size > 0 ? | ||
| 436 | BPF_TRAMP_F_RET_FENTRY_RET : 0; | ||
| 434 | err = arch_prepare_bpf_trampoline(NULL, image, | 437 | err = arch_prepare_bpf_trampoline(NULL, image, |
| 435 | st_map->image + PAGE_SIZE, | 438 | st_map->image + PAGE_SIZE, |
| 436 | &st_ops->func_models[i], 0, | 439 | &st_ops->func_models[i], |
| 437 | tprogs, NULL); | 440 | flags, tprogs, NULL); |
| 438 | if (err < 0) | 441 | if (err < 0) |
| 439 | goto reset_unlock; | 442 | goto reset_unlock; |
| 440 | 443 | ||
| @@ -827,7 +827,7 @@ int bpf_jit_charge_modmem(u32 pages) · 826 unmodified lines | |||
| 827 | { | 827 | { |
| 828 | if (atomic_long_add_return(pages, &bpf_jit_current) > | 828 | if (atomic_long_add_return(pages, &bpf_jit_current) > |
| 829 | (bpf_jit_limit >> PAGE_SHIFT)) { | 829 | (bpf_jit_limit >> PAGE_SHIFT)) { |
| 830 | if (!capable(CAP_SYS_ADMIN)) { | 830 | if (!bpf_capable()) { |
| 831 | atomic_long_sub(pages, &bpf_jit_current); | 831 | atomic_long_sub(pages, &bpf_jit_current); |
| 832 | return -EPERM; | 832 | return -EPERM; |
| 833 | } | 833 | } |
| @@ -6574,22 +6574,29 @@ int cgroup_parse_float(const char *input, unsigned dec_shift, s64 *v) · 6573 unmodified lines | |||
| 6574 | 6574 | ||
| 6575 | void cgroup_sk_alloc(struct sock_cgroup_data *skcd) | 6575 | void cgroup_sk_alloc(struct sock_cgroup_data *skcd) |
| 6576 | { | 6576 | { |
| 6577 | /* Don't associate the sock with unrelated interrupted task's cgroup. */ | 6577 | struct cgroup *cgroup; |
| 6578 | if (in_interrupt()) | ||
| 6579 | return; | ||
| 6580 | 6578 | ||
| 6581 | rcu_read_lock(); | 6579 | rcu_read_lock(); |
| 6580 | /* Don't associate the sock with unrelated interrupted task's cgroup. */ | ||
| 6581 | if (in_interrupt()) { | ||
| 6582 | cgroup = &cgrp_dfl_root.cgrp; | ||
| 6583 | cgroup_get(cgroup); | ||
| 6584 | goto out; | ||
| 6585 | } | ||
| 6586 | |||
| 6582 | while (true) { | 6587 | while (true) { |
| 6583 | struct css_set *cset; | 6588 | struct css_set *cset; |
| 6584 | 6589 | ||
| 6585 | cset = task_css_set(current); | 6590 | cset = task_css_set(current); |
| 6586 | if (likely(cgroup_tryget(cset->dfl_cgrp))) { | 6591 | if (likely(cgroup_tryget(cset->dfl_cgrp))) { |
| 6587 | skcd->cgroup = cset->dfl_cgrp; | 6592 | cgroup = cset->dfl_cgrp; |
| 6588 | cgroup_bpf_get(cset->dfl_cgrp); | ||
| 6589 | break; | 6593 | break; |
| 6590 | } | 6594 | } |
| 6591 | cpu_relax(); | 6595 | cpu_relax(); |
| 6592 | } | 6596 | } |
| 6597 | out: | ||
| 6598 | skcd->cgroup = cgroup; | ||
| 6599 | cgroup_bpf_get(cgroup); | ||
| 6593 | rcu_read_unlock(); | 6600 | rcu_read_unlock(); |
| 6594 | } | 6601 | } |
| 6595 | 6602 | ||
| @@ -3707,6 +3707,29 @@ static noinline int visit_groups_merge(struct perf_cpu_context *cpuctx, · 3706 unmodified lines | |||
| 3707 | return 0; | 3707 | return 0; |
| 3708 | } | 3708 | } |
| 3709 | 3709 | ||
| 3710 | static inline bool event_update_userpage(struct perf_event *event) | ||
| 3711 | { | ||
| 3712 | if (likely(!atomic_read(&event->mmap_count))) | ||
| 3713 | return false; | ||
| 3714 | |||
| 3715 | perf_event_update_time(event); | ||
| 3716 | perf_set_shadow_time(event, event->ctx); | ||
| 3717 | perf_event_update_userpage(event); | ||
| 3718 | |||
| 3719 | return true; | ||
| 3720 | } | ||
| 3721 | |||
| 3722 | static inline void group_update_userpage(struct perf_event *group_event) | ||
| 3723 | { | ||
| 3724 | struct perf_event *event; | ||
| 3725 | |||
| 3726 | if (!event_update_userpage(group_event)) | ||
| 3727 | return; | ||
| 3728 | |||
| 3729 | for_each_sibling_event(event, group_event) | ||
| 3730 | event_update_userpage(event); | ||
| 3731 | } | ||
| 3732 | |||
| 3710 | static int merge_sched_in(struct perf_event *event, void *data) | 3733 | static int merge_sched_in(struct perf_event *event, void *data) |
| 3711 | { | 3734 | { |
| 3712 | struct perf_event_context *ctx = event->ctx; | 3735 | struct perf_event_context *ctx = event->ctx; |
| @@ -3725,14 +3748,15 @@ static int merge_sched_in(struct perf_event *event, void *data) · 12 unmodified lines | |||
| 3725 | } | 3748 | } |
| 3726 | 3749 | ||
| 3727 | if (event->state == PERF_EVENT_STATE_INACTIVE) { | 3750 | if (event->state == PERF_EVENT_STATE_INACTIVE) { |
| 3751 | *can_add_hw = 0; | ||
| 3728 | if (event->attr.pinned) { | 3752 | if (event->attr.pinned) { |
| 3729 | perf_cgroup_event_disable(event, ctx); | 3753 | perf_cgroup_event_disable(event, ctx); |
| 3730 | perf_event_set_state(event, PERF_EVENT_STATE_ERROR); | 3754 | perf_event_set_state(event, PERF_EVENT_STATE_ERROR); |
| 3755 | } else { | ||
| 3756 | ctx->rotate_necessary = 1; | ||
| 3757 | perf_mux_hrtimer_restart(cpuctx); | ||
| 3758 | group_update_userpage(event); | ||
| 3731 | } | 3759 | } |
| 3732 | |||
| 3733 | *can_add_hw = 0; | ||
| 3734 | ctx->rotate_necessary = 1; | ||
| 3735 | perf_mux_hrtimer_restart(cpuctx); | ||
| 3736 | } | 3760 | } |
| 3737 | 3761 | ||
| 3738 | return 0; | 3762 | return 0; |
| @@ -6324,6 +6348,8 @@ accounting: · 2585 unmodified lines | |||
| 6324 | 6348 | ||
| 6325 | ring_buffer_attach(event, rb); | 6349 | ring_buffer_attach(event, rb); |
| 6326 | 6350 | ||
| 6351 | perf_event_update_time(event); | ||
| 6352 | perf_set_shadow_time(event, event->ctx); | ||
| 6327 | perf_event_init_userpage(event); | 6353 | perf_event_init_userpage(event); |
| 6328 | perf_event_update_userpage(event); | 6354 | perf_event_update_userpage(event); |
| 6329 | } else { | 6355 | } else { |
| @@ -173,16 +173,22 @@ static ssize_t sched_scaling_write(struct file *filp, const char __user *ubuf, · 172 unmodified lines | |||
| 173 | size_t cnt, loff_t *ppos) | 173 | size_t cnt, loff_t *ppos) |
| 174 | { | 174 | { |
| 175 | char buf[16]; | 175 | char buf[16]; |
| 176 | unsigned int scaling; | ||
| 176 | 177 | ||
| 177 | if (cnt > 15) | 178 | if (cnt > 15) |
| 178 | cnt = 15; | 179 | cnt = 15; |
| 179 | 180 | ||
| 180 | if (copy_from_user(&buf, ubuf, cnt)) | 181 | if (copy_from_user(&buf, ubuf, cnt)) |
| 181 | return -EFAULT; | 182 | return -EFAULT; |
| 183 | buf[cnt] = '\0'; | ||
| 182 | 184 | ||
| 183 | if (kstrtouint(buf, 10, &sysctl_sched_tunable_scaling)) | 185 | if (kstrtouint(buf, 10, &scaling)) |
| 184 | return -EINVAL; | 186 | return -EINVAL; |
| 185 | 187 | ||
| 188 | if (scaling >= SCHED_TUNABLESCALING_END) | ||
| 189 | return -EINVAL; | ||
| 190 | |||
| 191 | sysctl_sched_tunable_scaling = scaling; | ||
| 186 | if (sched_update_scaling()) | 192 | if (sched_update_scaling()) |
| 187 | return -EINVAL; | 193 | return -EINVAL; |
| 188 | 194 | ||
| @@ -4936,8 +4936,12 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq) · 4935 unmodified lines | |||
| 4936 | /* update hierarchical throttle state */ | 4936 | /* update hierarchical throttle state */ |
| 4937 | walk_tg_tree_from(cfs_rq->tg, tg_nop, tg_unthrottle_up, (void *)rq); | 4937 | walk_tg_tree_from(cfs_rq->tg, tg_nop, tg_unthrottle_up, (void *)rq); |
| 4938 | 4938 | ||
| 4939 | if (!cfs_rq->load.weight) | 4939 | /* Nothing to run but something to decay (on_list)? Complete the branch */ |
| 4940 | if (!cfs_rq->load.weight) { | ||
| 4941 | if (cfs_rq->on_list) | ||
| 4942 | goto unthrottle_throttle; | ||
| 4940 | return; | 4943 | return; |
| 4944 | } | ||
| 4941 | 4945 | ||
| 4942 | task_delta = cfs_rq->h_nr_running; | 4946 | task_delta = cfs_rq->h_nr_running; |
| 4943 | idle_task_delta = cfs_rq->idle_h_nr_running; | 4947 | idle_task_delta = cfs_rq->idle_h_nr_running; |
| @@ -552,6 +552,12 @@ static void convert_skb_to___skb(struct sk_buff *skb, struct __sk_buff *__skb) · 551 unmodified lines | |||
| 552 | __skb->gso_segs = skb_shinfo(skb)->gso_segs; | 552 | __skb->gso_segs = skb_shinfo(skb)->gso_segs; |
| 553 | } | 553 | } |
| 554 | 554 | ||
| 555 | static struct proto bpf_dummy_proto = { | ||
| 556 | .name = "bpf_dummy", | ||
| 557 | .owner = THIS_MODULE, | ||
| 558 | .obj_size = sizeof(struct sock), | ||
| 559 | }; | ||
| 560 | |||
| 555 | int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, | 561 | int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, |
| 556 | union bpf_attr __user *uattr) | 562 | union bpf_attr __user *uattr) |
| 557 | { | 563 | { |
| @@ -596,20 +602,19 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, · 38 unmodified lines | |||
| 596 | break; | 602 | break; |
| 597 | } | 603 | } |
| 598 | 604 | ||
| 599 | sk = kzalloc(sizeof(struct sock), GFP_USER); | 605 | sk = sk_alloc(net, AF_UNSPEC, GFP_USER, &bpf_dummy_proto, 1); |
| 600 | if (!sk) { | 606 | if (!sk) { |
| 601 | kfree(data); | 607 | kfree(data); |
| 602 | kfree(ctx); | 608 | kfree(ctx); |
| 603 | return -ENOMEM; | 609 | return -ENOMEM; |
| 604 | } | 610 | } |
| 605 | sock_net_set(sk, net); | ||
| 606 | sock_init_data(NULL, sk); | 611 | sock_init_data(NULL, sk); |
| 607 | 612 | ||
| 608 | skb = build_skb(data, 0); | 613 | skb = build_skb(data, 0); |
| 609 | if (!skb) { | 614 | if (!skb) { |
| 610 | kfree(data); | 615 | kfree(data); |
| 611 | kfree(ctx); | 616 | kfree(ctx); |
| 612 | kfree(sk); | 617 | sk_free(sk); |
| 613 | return -ENOMEM; | 618 | return -ENOMEM; |
| 614 | } | 619 | } |
| 615 | skb->sk = sk; | 620 | skb->sk = sk; |
| @@ -682,8 +687,7 @@ out: · 66 unmodified lines | |||
| 682 | if (dev && dev != net->loopback_dev) | 687 | if (dev && dev != net->loopback_dev) |
| 683 | dev_put(dev); | 688 | dev_put(dev); |
| 684 | kfree_skb(skb); | 689 | kfree_skb(skb); |
| 685 | bpf_sk_storage_free(sk); | 690 | sk_free(sk); |
| 686 | kfree(sk); | ||
| 687 | kfree(ctx); | 691 | kfree(ctx); |
| 688 | return ret; | 692 | return ret; |
| 689 | } | 693 | } |
| @@ -1677,8 +1677,6 @@ static void br_multicast_update_querier(struct net_bridge_mcast *brmctx, · 1676 unmodified lines | |||
| 1677 | int ifindex, | 1677 | int ifindex, |
| 1678 | struct br_ip *saddr) | 1678 | struct br_ip *saddr) |
| 1679 | { | 1679 | { |
| 1680 | lockdep_assert_held_once(&brmctx->br->multicast_lock); | ||
| 1681 | |||
| 1682 | write_seqcount_begin(&querier->seq); | 1680 | write_seqcount_begin(&querier->seq); |
| 1683 | querier->port_ifidx = ifindex; | 1681 | querier->port_ifidx = ifindex; |
| 1684 | memcpy(&querier->addr, saddr, sizeof(*saddr)); | 1682 | memcpy(&querier->addr, saddr, sizeof(*saddr)); |
| @@ -3867,13 +3865,13 @@ void br_multicast_ctx_init(struct net_bridge *br, · 2182 unmodified lines | |||
| 3867 | 3865 | ||
| 3868 | brmctx->ip4_other_query.delay_time = 0; | 3866 | brmctx->ip4_other_query.delay_time = 0; |
| 3869 | brmctx->ip4_querier.port_ifidx = 0; | 3867 | brmctx->ip4_querier.port_ifidx = 0; |
| 3870 | seqcount_init(&brmctx->ip4_querier.seq); | 3868 | seqcount_spinlock_init(&brmctx->ip4_querier.seq, &br->multicast_lock); |
| 3871 | brmctx->multicast_igmp_version = 2; | 3869 | brmctx->multicast_igmp_version = 2; |
| 3872 | #if IS_ENABLED(CONFIG_IPV6) | 3870 | #if IS_ENABLED(CONFIG_IPV6) |
| 3873 | brmctx->multicast_mld_version = 1; | 3871 | brmctx->multicast_mld_version = 1; |
| 3874 | brmctx->ip6_other_query.delay_time = 0; | 3872 | brmctx->ip6_other_query.delay_time = 0; |
| 3875 | brmctx->ip6_querier.port_ifidx = 0; | 3873 | brmctx->ip6_querier.port_ifidx = 0; |
| 3876 | seqcount_init(&brmctx->ip6_querier.seq); | 3874 | seqcount_spinlock_init(&brmctx->ip6_querier.seq, &br->multicast_lock); |
| 3877 | #endif | 3875 | #endif |
| 3878 | 3876 | ||
| 3879 | timer_setup(&brmctx->ip4_mc_router_timer, | 3877 | timer_setup(&brmctx->ip4_mc_router_timer, |
| @@ -82,7 +82,7 @@ struct bridge_mcast_other_query { · 81 unmodified lines | |||
| 82 | struct bridge_mcast_querier { | 82 | struct bridge_mcast_querier { |
| 83 | struct br_ip addr; | 83 | struct br_ip addr; |
| 84 | int port_ifidx; | 84 | int port_ifidx; |
| 85 | seqcount_t seq; | 85 | seqcount_spinlock_t seq; |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | /* IGMP/MLD statistics */ | 88 | /* IGMP/MLD statistics */ |
| @@ -50,6 +50,11 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, · 49 unmodified lines | |||
| 50 | if (addr_len > MAX_ADDR_LEN) | 50 | if (addr_len > MAX_ADDR_LEN) |
| 51 | return -EINVAL; | 51 | return -EINVAL; |
| 52 | 52 | ||
| 53 | ha = list_first_entry(&list->list, struct netdev_hw_addr, list); | ||
| 54 | if (ha && !memcmp(addr, ha->addr, addr_len) && | ||
| 55 | (!addr_type || addr_type == ha->type)) | ||
| 56 | goto found_it; | ||
| 57 | |||
| 53 | while (*ins_point) { | 58 | while (*ins_point) { |
| 54 | int diff; | 59 | int diff; |
| 55 | 60 | ||
| @@ -64,6 +69,7 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, · 8 unmodified lines | |||
| 64 | } else if (diff > 0) { | 69 | } else if (diff > 0) { |
| 65 | ins_point = &parent->rb_right; | 70 | ins_point = &parent->rb_right; |
| 66 | } else { | 71 | } else { |
| 72 | found_it: | ||
| 67 | if (exclusive) | 73 | if (exclusive) |
| 68 | return -EEXIST; | 74 | return -EEXIST; |
| 69 | if (global) { | 75 | if (global) { |
| @@ -1376,6 +1376,16 @@ set_sndbuf: · 1375 unmodified lines | |||
| 1376 | } | 1376 | } |
| 1377 | EXPORT_SYMBOL(sock_setsockopt); | 1377 | EXPORT_SYMBOL(sock_setsockopt); |
| 1378 | 1378 | ||
| 1379 | static const struct cred *sk_get_peer_cred(struct sock *sk) | ||
| 1380 | { | ||
| 1381 | const struct cred *cred; | ||
| 1382 | |||
| 1383 | spin_lock(&sk->sk_peer_lock); | ||
| 1384 | cred = get_cred(sk->sk_peer_cred); | ||
| 1385 | spin_unlock(&sk->sk_peer_lock); | ||
| 1386 | |||
| 1387 | return cred; | ||
| 1388 | } | ||
| 1379 | 1389 | ||
| 1380 | static void cred_to_ucred(struct pid *pid, const struct cred *cred, | 1390 | static void cred_to_ucred(struct pid *pid, const struct cred *cred, |
| 1381 | struct ucred *ucred) | 1391 | struct ucred *ucred) |
| @@ -1552,7 +1562,11 @@ int sock_getsockopt(struct socket *sock, int level, int optname, · 170 unmodified lines | |||
| 1552 | struct ucred peercred; | 1562 | struct ucred peercred; |
| 1553 | if (len > sizeof(peercred)) | 1563 | if (len > sizeof(peercred)) |
| 1554 | len = sizeof(peercred); | 1564 | len = sizeof(peercred); |
| 1565 | |||
| 1566 | spin_lock(&sk->sk_peer_lock); | ||
| 1555 | cred_to_ucred(sk->sk_peer_pid, sk->sk_peer_cred, &peercred); | 1567 | cred_to_ucred(sk->sk_peer_pid, sk->sk_peer_cred, &peercred); |
| 1568 | spin_unlock(&sk->sk_peer_lock); | ||
| 1569 | |||
| 1556 | if (copy_to_user(optval, &peercred, len)) | 1570 | if (copy_to_user(optval, &peercred, len)) |
| 1557 | return -EFAULT; | 1571 | return -EFAULT; |
| 1558 | goto lenout; | 1572 | goto lenout; |
| @@ -1560,20 +1574,23 @@ int sock_getsockopt(struct socket *sock, int level, int optname, · 1 unmodified line | |||
| 1560 | 1574 | ||
| 1561 | case SO_PEERGROUPS: | 1575 | case SO_PEERGROUPS: |
| 1562 | { | 1576 | { |
| 1577 | const struct cred *cred; | ||
| 1563 | int ret, n; | 1578 | int ret, n; |
| 1564 | 1579 | ||
| 1565 | if (!sk->sk_peer_cred) | 1580 | cred = sk_get_peer_cred(sk); |
| 1581 | if (!cred) | ||
| 1566 | return -ENODATA; | 1582 | return -ENODATA; |
| 1567 | 1583 | ||
| 1568 | n = sk->sk_peer_cred->group_info->ngroups; | 1584 | n = cred->group_info->ngroups; |
| 1569 | if (len < n * sizeof(gid_t)) { | 1585 | if (len < n * sizeof(gid_t)) { |
| 1570 | len = n * sizeof(gid_t); | 1586 | len = n * sizeof(gid_t); |
| 1587 | put_cred(cred); | ||
| 1571 | return put_user(len, optlen) ? -EFAULT : -ERANGE; | 1588 | return put_user(len, optlen) ? -EFAULT : -ERANGE; |
| 1572 | } | 1589 | } |
| 1573 | len = n * sizeof(gid_t); | 1590 | len = n * sizeof(gid_t); |
| 1574 | 1591 | ||
| 1575 | ret = groups_to_user((gid_t __user *)optval, | 1592 | ret = groups_to_user((gid_t __user *)optval, cred->group_info); |
| 1576 | sk->sk_peer_cred->group_info); | 1593 | put_cred(cred); |
| 1577 | if (ret) | 1594 | if (ret) |
| 1578 | return ret; | 1595 | return ret; |
| 1579 | goto lenout; | 1596 | goto lenout; |
| @@ -1935,9 +1952,10 @@ static void __sk_destruct(struct rcu_head *head) · 355 unmodified lines | |||
| 1935 | sk->sk_frag.page = NULL; | 1952 | sk->sk_frag.page = NULL; |
| 1936 | } | 1953 | } |
| 1937 | 1954 | ||
| 1938 | if (sk->sk_peer_cred) | 1955 | /* We do not need to acquire sk->sk_peer_lock, we are the last user. */ |
| 1939 | put_cred(sk->sk_peer_cred); | 1956 | put_cred(sk->sk_peer_cred); |
| 1940 | put_pid(sk->sk_peer_pid); | 1957 | put_pid(sk->sk_peer_pid); |
| 1958 | |||
| 1941 | if (likely(sk->sk_net_refcnt)) | 1959 | if (likely(sk->sk_net_refcnt)) |
| 1942 | put_net(sock_net(sk)); | 1960 | put_net(sock_net(sk)); |
| 1943 | sk_prot_free(sk->sk_prot_creator, sk); | 1961 | sk_prot_free(sk->sk_prot_creator, sk); |
| @@ -3145,6 +3163,8 @@ void sock_init_data(struct socket *sock, struct sock *sk) · 1201 unmodified lines | |||
| 3145 | 3163 | ||
| 3146 | sk->sk_peer_pid = NULL; | 3164 | sk->sk_peer_pid = NULL; |
| 3147 | sk->sk_peer_cred = NULL; | 3165 | sk->sk_peer_cred = NULL; |
| 3166 | spin_lock_init(&sk->sk_peer_lock); | ||
| 3167 | |||
| 3148 | sk->sk_write_pending = 0; | 3168 | sk->sk_write_pending = 0; |
| 3149 | sk->sk_rcvlowat = 1; | 3169 | sk->sk_rcvlowat = 1; |
| 3150 | sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; | 3170 | sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; |
| @@ -3210,24 +3230,8 @@ void release_sock(struct sock *sk) · 59 unmodified lines | |||
| 3210 | } | 3230 | } |
| 3211 | EXPORT_SYMBOL(release_sock); | 3231 | EXPORT_SYMBOL(release_sock); |
| 3212 | 3232 | ||
| 3213 | /** | 3233 | bool __lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock) |
| 3214 | * lock_sock_fast - fast version of lock_sock | ||
| 3215 | * @sk: socket | ||
| 3216 | * | ||
| 3217 | * This version should be used for very small section, where process wont block | ||
| 3218 | * return false if fast path is taken: | ||
| 3219 | * | ||
| 3220 | * sk_lock.slock locked, owned = 0, BH disabled | ||
| 3221 | * | ||
| 3222 | * return true if slow path is taken: | ||
| 3223 | * | ||
| 3224 | * sk_lock.slock unlocked, owned = 1, BH enabled | ||
| 3225 | */ | ||
| 3226 | bool lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock) | ||
| 3227 | { | 3234 | { |
| 3228 | /* The sk_lock has mutex_lock() semantics here. */ | ||
| 3229 | mutex_acquire(&sk->sk_lock.dep_map, 0, 0, _RET_IP_); | ||
| 3230 | |||
| 3231 | might_sleep(); | 3235 | might_sleep(); |
| 3232 | spin_lock_bh(&sk->sk_lock.slock); | 3236 | spin_lock_bh(&sk->sk_lock.slock); |
| 3233 | 3237 | ||
| @@ -3256,7 +3260,7 @@ bool lock_sock_fast(struct sock *sk) __acquires(&sk->sk_lock.slock) · 22 unmodified lines | |||
| 3256 | spin_unlock_bh(&sk->sk_lock.slock); | 3260 | spin_unlock_bh(&sk->sk_lock.slock); |
| 3257 | return true; | 3261 | return true; |
| 3258 | } | 3262 | } |
| 3259 | EXPORT_SYMBOL(lock_sock_fast); | 3263 | EXPORT_SYMBOL(__lock_sock_fast); |
| 3260 | 3264 | ||
| 3261 | int sock_gettstamp(struct socket *sock, void __user *userstamp, | 3265 | int sock_gettstamp(struct socket *sock, void __user *userstamp, |
| 3262 | bool timeval, bool time32) | 3266 | bool timeval, bool time32) |
| @@ -1661,7 +1661,7 @@ EXPORT_SYMBOL_GPL(fib_nexthop_info); · 1660 unmodified lines | |||
| 1661 | 1661 | ||
| 1662 | #if IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) || IS_ENABLED(CONFIG_IPV6) | 1662 | #if IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) || IS_ENABLED(CONFIG_IPV6) |
| 1663 | int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc, | 1663 | int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc, |
| 1664 | int nh_weight, u8 rt_family) | 1664 | int nh_weight, u8 rt_family, u32 nh_tclassid) |
| 1665 | { | 1665 | { |
| 1666 | const struct net_device *dev = nhc->nhc_dev; | 1666 | const struct net_device *dev = nhc->nhc_dev; |
| 1667 | struct rtnexthop *rtnh; | 1667 | struct rtnexthop *rtnh; |
| @@ -1679,6 +1679,9 @@ int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc, · 11 unmodified lines | |||
| 1679 | 1679 | ||
| 1680 | rtnh->rtnh_flags = flags; | 1680 | rtnh->rtnh_flags = flags; |
| 1681 | 1681 | ||
| 1682 | if (nh_tclassid && nla_put_u32(skb, RTA_FLOW, nh_tclassid)) | ||
| 1683 | goto nla_put_failure; | ||
| 1684 | |||
| 1682 | /* length of rtnetlink header + attributes */ | 1685 | /* length of rtnetlink header + attributes */ |
| 1683 | rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh; | 1686 | rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh; |
| 1684 | 1687 | ||
| @@ -1706,14 +1709,13 @@ static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi) · 21 unmodified lines | |||
| 1706 | } | 1709 | } |
| 1707 | 1710 | ||
| 1708 | for_nexthops(fi) { | 1711 | for_nexthops(fi) { |
| 1709 | if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight, | 1712 | u32 nh_tclassid = 0; |
| 1710 | AF_INET) < 0) | ||
| 1711 | goto nla_put_failure; | ||
| 1712 | #ifdef CONFIG_IP_ROUTE_CLASSID | 1713 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 1713 | if (nh->nh_tclassid && | 1714 | nh_tclassid = nh->nh_tclassid; |
| 1714 | nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid)) | ||
| 1715 | goto nla_put_failure; | ||
| 1716 | #endif | 1715 | #endif |
| 1716 | if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight, | ||
| 1717 | AF_INET, nh_tclassid) < 0) | ||
| 1718 | goto nla_put_failure; | ||
| 1717 | } endfor_nexthops(fi); | 1719 | } endfor_nexthops(fi); |
| 1718 | 1720 | ||
| 1719 | mp_end: | 1721 | mp_end: |
| @@ -42,7 +42,7 @@ iptable_raw_hook(void *priv, struct sk_buff *skb, · 41 unmodified lines | |||
| 42 | 42 | ||
| 43 | static struct nf_hook_ops *rawtable_ops __read_mostly; | 43 | static struct nf_hook_ops *rawtable_ops __read_mostly; |
| 44 | 44 | ||
| 45 | static int __net_init iptable_raw_table_init(struct net *net) | 45 | static int iptable_raw_table_init(struct net *net) |
| 46 | { | 46 | { |
| 47 | struct ipt_replace *repl; | 47 | struct ipt_replace *repl; |
| 48 | const struct xt_table *table = &packet_raw; | 48 | const struct xt_table *table = &packet_raw; |
| @@ -1053,7 +1053,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 1052 unmodified lines | |||
| 1053 | __be16 dport; | 1053 | __be16 dport; |
| 1054 | u8 tos; | 1054 | u8 tos; |
| 1055 | int err, is_udplite = IS_UDPLITE(sk); | 1055 | int err, is_udplite = IS_UDPLITE(sk); |
| 1056 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 1056 | int corkreq = READ_ONCE(up->corkflag) || msg->msg_flags&MSG_MORE; |
| 1057 | int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); | 1057 | int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); |
| 1058 | struct sk_buff *skb; | 1058 | struct sk_buff *skb; |
| 1059 | struct ip_options_data opt_copy; | 1059 | struct ip_options_data opt_copy; |
| @@ -1361,7 +1361,7 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset, · 301 unmodified lines | |||
| 1361 | } | 1361 | } |
| 1362 | 1362 | ||
| 1363 | up->len += size; | 1363 | up->len += size; |
| 1364 | if (!(up->corkflag || (flags&MSG_MORE))) | 1364 | if (!(READ_ONCE(up->corkflag) || (flags&MSG_MORE))) |
| 1365 | ret = udp_push_pending_frames(sk); | 1365 | ret = udp_push_pending_frames(sk); |
| 1366 | if (!ret) | 1366 | if (!ret) |
| 1367 | ret = size; | 1367 | ret = size; |
| @@ -2662,9 +2662,9 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, · 1294 unmodified lines | |||
| 2662 | switch (optname) { | 2662 | switch (optname) { |
| 2663 | case UDP_CORK: | 2663 | case UDP_CORK: |
| 2664 | if (val != 0) { | 2664 | if (val != 0) { |
| 2665 | up->corkflag = 1; | 2665 | WRITE_ONCE(up->corkflag, 1); |
| 2666 | } else { | 2666 | } else { |
| 2667 | up->corkflag = 0; | 2667 | WRITE_ONCE(up->corkflag, 0); |
| 2668 | lock_sock(sk); | 2668 | lock_sock(sk); |
| 2669 | push_pending_frames(sk); | 2669 | push_pending_frames(sk); |
| 2670 | release_sock(sk); | 2670 | release_sock(sk); |
| @@ -2787,7 +2787,7 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname, · 116 unmodified lines | |||
| 2787 | 2787 | ||
| 2788 | switch (optname) { | 2788 | switch (optname) { |
| 2789 | case UDP_CORK: | 2789 | case UDP_CORK: |
| 2790 | val = up->corkflag; | 2790 | val = READ_ONCE(up->corkflag); |
| 2791 | break; | 2791 | break; |
| 2792 | 2792 | ||
| 2793 | case UDP_ENCAP: | 2793 | case UDP_ENCAP: |
| @@ -273,6 +273,7 @@ ip6t_do_table(struct sk_buff *skb, · 272 unmodified lines | |||
| 273 | * things we don't know, ie. tcp syn flag or ports). If the | 273 | * things we don't know, ie. tcp syn flag or ports). If the |
| 274 | * rule is also a fragment-specific rule, non-fragments won't | 274 | * rule is also a fragment-specific rule, non-fragments won't |
| 275 | * match it. */ | 275 | * match it. */ |
| 276 | acpar.fragoff = 0; | ||
| 276 | acpar.hotdrop = false; | 277 | acpar.hotdrop = false; |
| 277 | acpar.state = state; | 278 | acpar.state = state; |
| 278 | 279 | ||
| @@ -5681,14 +5681,15 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, · 5680 unmodified lines | |||
| 5681 | goto nla_put_failure; | 5681 | goto nla_put_failure; |
| 5682 | 5682 | ||
| 5683 | if (fib_add_nexthop(skb, &rt->fib6_nh->nh_common, | 5683 | if (fib_add_nexthop(skb, &rt->fib6_nh->nh_common, |
| 5684 | rt->fib6_nh->fib_nh_weight, AF_INET6) < 0) | 5684 | rt->fib6_nh->fib_nh_weight, AF_INET6, |
| 5685 | 0) < 0) | ||
| 5685 | goto nla_put_failure; | 5686 | goto nla_put_failure; |
| 5686 | 5687 | ||
| 5687 | list_for_each_entry_safe(sibling, next_sibling, | 5688 | list_for_each_entry_safe(sibling, next_sibling, |
| 5688 | &rt->fib6_siblings, fib6_siblings) { | 5689 | &rt->fib6_siblings, fib6_siblings) { |
| 5689 | if (fib_add_nexthop(skb, &sibling->fib6_nh->nh_common, | 5690 | if (fib_add_nexthop(skb, &sibling->fib6_nh->nh_common, |
| 5690 | sibling->fib6_nh->fib_nh_weight, | 5691 | sibling->fib6_nh->fib_nh_weight, |
| 5691 | AF_INET6) < 0) | 5692 | AF_INET6, 0) < 0) |
| 5692 | goto nla_put_failure; | 5693 | goto nla_put_failure; |
| 5693 | } | 5694 | } |
| 5694 | 5695 | ||
| @@ -1303,7 +1303,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 1302 unmodified lines | |||
| 1303 | int addr_len = msg->msg_namelen; | 1303 | int addr_len = msg->msg_namelen; |
| 1304 | bool connected = false; | 1304 | bool connected = false; |
| 1305 | int ulen = len; | 1305 | int ulen = len; |
| 1306 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 1306 | int corkreq = READ_ONCE(up->corkflag) || msg->msg_flags&MSG_MORE; |
| 1307 | int err; | 1307 | int err; |
| 1308 | int is_udplite = IS_UDPLITE(sk); | 1308 | int is_udplite = IS_UDPLITE(sk); |
| 1309 | int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); | 1309 | int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); |
| @@ -60,7 +60,10 @@ static struct mesh_table *mesh_table_alloc(void) · 59 unmodified lines | |||
| 60 | atomic_set(&newtbl->entries, 0); | 60 | atomic_set(&newtbl->entries, 0); |
| 61 | spin_lock_init(&newtbl->gates_lock); | 61 | spin_lock_init(&newtbl->gates_lock); |
| 62 | spin_lock_init(&newtbl->walk_lock); | 62 | spin_lock_init(&newtbl->walk_lock); |
| 63 | rhashtable_init(&newtbl->rhead, &mesh_rht_params); | 63 | if (rhashtable_init(&newtbl->rhead, &mesh_rht_params)) { |
| 64 | kfree(newtbl); | ||
| 65 | return NULL; | ||
| 66 | } | ||
| 64 | 67 | ||
| 65 | return newtbl; | 68 | return newtbl; |
| 66 | } | 69 | } |
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | /* | 2 | /* |
| 3 | * Copyright 2012-2013, Marco Porsch <marco.porsch@s2005.tu-chemnitz.de> | 3 | * Copyright 2012-2013, Marco Porsch <marco.porsch@s2005.tu-chemnitz.de> |
| 4 | * Copyright 2012-2013, cozybit Inc. | 4 | * Copyright 2012-2013, cozybit Inc. |
| 5 | * Copyright (C) 2021 Intel Corporation | ||
| 5 | */ | 6 | */ |
| 6 | 7 | ||
| 7 | #include "mesh.h" | 8 | #include "mesh.h" |
| @@ -588,7 +589,7 @@ void ieee80211_mps_frame_release(struct sta_info *sta, · 580 unmodified lines | |||
| 588 | 589 | ||
| 589 | /* only transmit to PS STA with announced, non-zero awake window */ | 590 | /* only transmit to PS STA with announced, non-zero awake window */ |
| 590 | if (test_sta_flag(sta, WLAN_STA_PS_STA) && | 591 | if (test_sta_flag(sta, WLAN_STA_PS_STA) && |
| 591 | (!elems->awake_window || !le16_to_cpu(*elems->awake_window))) | 592 | (!elems->awake_window || !get_unaligned_le16(elems->awake_window))) |
| 592 | return; | 593 | return; |
| 593 | 594 | ||
| 594 | if (!test_sta_flag(sta, WLAN_STA_MPSP_OWNER)) | 595 | if (!test_sta_flag(sta, WLAN_STA_MPSP_OWNER)) |
| @@ -392,10 +392,6 @@ static bool rate_control_send_low(struct ieee80211_sta *pubsta, · 391 unmodified lines | |||
| 392 | int mcast_rate; | 392 | int mcast_rate; |
| 393 | bool use_basicrate = false; | 393 | bool use_basicrate = false; |
| 394 | 394 | ||
| 395 | if (ieee80211_is_tx_data(txrc->skb) && | ||
| 396 | info->flags & IEEE80211_TX_CTL_NO_ACK) | ||
| 397 | return false; | ||
| 398 | |||
| 399 | if (!pubsta || rc_no_data_or_no_ack_use_min(txrc)) { | 395 | if (!pubsta || rc_no_data_or_no_ack_use_min(txrc)) { |
| 400 | __rate_control_send_low(txrc->hw, sband, pubsta, info, | 396 | __rate_control_send_low(txrc->hw, sband, pubsta, info, |
| 401 | txrc->rate_idx_mask); | 397 | txrc->rate_idx_mask); |
| @@ -4131,7 +4131,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) · 4130 unmodified lines | |||
| 4131 | if (!bssid) | 4131 | if (!bssid) |
| 4132 | return false; | 4132 | return false; |
| 4133 | if (ether_addr_equal(sdata->vif.addr, hdr->addr2) || | 4133 | if (ether_addr_equal(sdata->vif.addr, hdr->addr2) || |
| 4134 | ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2)) | 4134 | ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2) || |
| 4135 | !is_valid_ether_addr(hdr->addr2)) | ||
| 4135 | return false; | 4136 | return false; |
| 4136 | if (ieee80211_is_beacon(hdr->frame_control)) | 4137 | if (ieee80211_is_beacon(hdr->frame_control)) |
| 4137 | return true; | 4138 | return true; |
| @@ -2209,7 +2209,11 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb, · 2208 unmodified lines | |||
| 2209 | } | 2209 | } |
| 2210 | 2210 | ||
| 2211 | vht_mcs = iterator.this_arg[4] >> 4; | 2211 | vht_mcs = iterator.this_arg[4] >> 4; |
| 2212 | if (vht_mcs > 11) | ||
| 2213 | vht_mcs = 0; | ||
| 2212 | vht_nss = iterator.this_arg[4] & 0xF; | 2214 | vht_nss = iterator.this_arg[4] & 0xF; |
| 2215 | if (!vht_nss || vht_nss > 8) | ||
| 2216 | vht_nss = 1; | ||
| 2213 | break; | 2217 | break; |
| 2214 | 2218 | ||
| 2215 | /* | 2219 | /* |
| @@ -3380,6 +3384,14 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata, · 1164 unmodified lines | |||
| 3380 | if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head)) | 3384 | if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head)) |
| 3381 | goto out; | 3385 | goto out; |
| 3382 | 3386 | ||
| 3387 | /* If n == 2, the "while (*frag_tail)" loop above didn't execute | ||
| 3388 | * and frag_tail should be &skb_shinfo(head)->frag_list. | ||
| 3389 | * However, ieee80211_amsdu_prepare_head() can reallocate it. | ||
| 3390 | * Reload frag_tail to have it pointing to the correct place. | ||
| 3391 | */ | ||
| 3392 | if (n == 2) | ||
| 3393 | frag_tail = &skb_shinfo(head)->frag_list; | ||
| 3394 | |||
| 3383 | /* | 3395 | /* |
| 3384 | * Pad out the previous subframe to a multiple of 4 by adding the | 3396 | * Pad out the previous subframe to a multiple of 4 by adding the |
| 3385 | * padding to the next one, that's being added. Note that head->len | 3397 | * padding to the next one, that's being added. Note that head->len |
| @@ -520,6 +520,9 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, · 519 unmodified lines | |||
| 520 | return RX_DROP_UNUSABLE; | 520 | return RX_DROP_UNUSABLE; |
| 521 | } | 521 | } |
| 522 | 522 | ||
| 523 | /* reload hdr - skb might have been reallocated */ | ||
| 524 | hdr = (void *)rx->skb->data; | ||
| 525 | |||
| 523 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len; | 526 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len; |
| 524 | if (!rx->sta || data_len < 0) | 527 | if (!rx->sta || data_len < 0) |
| 525 | return RX_DROP_UNUSABLE; | 528 | return RX_DROP_UNUSABLE; |
| @@ -749,6 +752,9 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) · 223 unmodified lines | |||
| 749 | return RX_DROP_UNUSABLE; | 752 | return RX_DROP_UNUSABLE; |
| 750 | } | 753 | } |
| 751 | 754 | ||
| 755 | /* reload hdr - skb might have been reallocated */ | ||
| 756 | hdr = (void *)rx->skb->data; | ||
| 757 | |||
| 752 | data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - mic_len; | 758 | data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - mic_len; |
| 753 | if (!rx->sta || data_len < 0) | 759 | if (!rx->sta || data_len < 0) |
| 754 | return RX_DROP_UNUSABLE; | 760 | return RX_DROP_UNUSABLE; |
| @@ -36,7 +36,7 @@ static int mptcp_diag_dump_one(struct netlink_callback *cb, · 35 unmodified lines | |||
| 36 | struct sock *sk; | 36 | struct sock *sk; |
| 37 | 37 | ||
| 38 | net = sock_net(in_skb->sk); | 38 | net = sock_net(in_skb->sk); |
| 39 | msk = mptcp_token_get_sock(req->id.idiag_cookie[0]); | 39 | msk = mptcp_token_get_sock(net, req->id.idiag_cookie[0]); |
| 40 | if (!msk) | 40 | if (!msk) |
| 41 | goto out_nosk; | 41 | goto out_nosk; |
| 42 | 42 | ||
| @@ -1718,9 +1718,7 @@ static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info) · 1717 unmodified lines | |||
| 1718 | 1718 | ||
| 1719 | list_for_each_entry(entry, &pernet->local_addr_list, list) { | 1719 | list_for_each_entry(entry, &pernet->local_addr_list, list) { |
| 1720 | if (addresses_equal(&entry->addr, &addr.addr, true)) { | 1720 | if (addresses_equal(&entry->addr, &addr.addr, true)) { |
| 1721 | ret = mptcp_nl_addr_backup(net, &entry->addr, bkup); | 1721 | mptcp_nl_addr_backup(net, &entry->addr, bkup); |
| 1722 | if (ret) | ||
| 1723 | return ret; | ||
| 1724 | 1722 | ||
| 1725 | if (bkup) | 1723 | if (bkup) |
| 1726 | entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP; | 1724 | entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP; |
| @@ -2735,7 +2735,7 @@ cleanup: · 2734 unmodified lines | |||
| 2735 | inet_csk(sk)->icsk_mtup.probe_timestamp = tcp_jiffies32; | 2735 | inet_csk(sk)->icsk_mtup.probe_timestamp = tcp_jiffies32; |
| 2736 | mptcp_for_each_subflow(mptcp_sk(sk), subflow) { | 2736 | mptcp_for_each_subflow(mptcp_sk(sk), subflow) { |
| 2737 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | 2737 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 2738 | bool slow = lock_sock_fast(ssk); | 2738 | bool slow = lock_sock_fast_nested(ssk); |
| 2739 | 2739 | ||
| 2740 | sock_orphan(ssk); | 2740 | sock_orphan(ssk); |
| 2741 | unlock_sock_fast(ssk, slow); | 2741 | unlock_sock_fast(ssk, slow); |
| @@ -709,7 +709,7 @@ int mptcp_token_new_connect(struct sock *sk); · 708 unmodified lines | |||
| 709 | void mptcp_token_accept(struct mptcp_subflow_request_sock *r, | 709 | void mptcp_token_accept(struct mptcp_subflow_request_sock *r, |
| 710 | struct mptcp_sock *msk); | 710 | struct mptcp_sock *msk); |
| 711 | bool mptcp_token_exists(u32 token); | 711 | bool mptcp_token_exists(u32 token); |
| 712 | struct mptcp_sock *mptcp_token_get_sock(u32 token); | 712 | struct mptcp_sock *mptcp_token_get_sock(struct net *net, u32 token); |
| 713 | struct mptcp_sock *mptcp_token_iter_next(const struct net *net, long *s_slot, | 713 | struct mptcp_sock *mptcp_token_iter_next(const struct net *net, long *s_slot, |
| 714 | long *s_num); | 714 | long *s_num); |
| 715 | void mptcp_token_destroy(struct mptcp_sock *msk); | 715 | void mptcp_token_destroy(struct mptcp_sock *msk); |
| @@ -86,7 +86,7 @@ static struct mptcp_sock *subflow_token_join_request(struct request_sock *req) · 85 unmodified lines | |||
| 86 | struct mptcp_sock *msk; | 86 | struct mptcp_sock *msk; |
| 87 | int local_id; | 87 | int local_id; |
| 88 | 88 | ||
| 89 | msk = mptcp_token_get_sock(subflow_req->token); | 89 | msk = mptcp_token_get_sock(sock_net(req_to_sk(req)), subflow_req->token); |
| 90 | if (!msk) { | 90 | if (!msk) { |
| 91 | SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINNOTOKEN); | 91 | SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINNOTOKEN); |
| 92 | return NULL; | 92 | return NULL; |
| @@ -108,18 +108,12 @@ bool mptcp_token_join_cookie_init_state(struct mptcp_subflow_request_sock *subfl · 107 unmodified lines | |||
| 108 | 108 | ||
| 109 | e->valid = 0; | 109 | e->valid = 0; |
| 110 | 110 | ||
| 111 | msk = mptcp_token_get_sock(e->token); | 111 | msk = mptcp_token_get_sock(net, e->token); |
| 112 | if (!msk) { | 112 | if (!msk) { |
| 113 | spin_unlock_bh(&join_entry_locks[i]); | 113 | spin_unlock_bh(&join_entry_locks[i]); |
| 114 | return false; | 114 | return false; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | /* If this fails, the token got re-used in the mean time by another | ||
| 118 | * mptcp socket in a different netns, i.e. entry is outdated. | ||
| 119 | */ | ||
| 120 | if (!net_eq(sock_net((struct sock *)msk), net)) | ||
| 121 | goto err_put; | ||
| 122 | |||
| 123 | subflow_req->remote_nonce = e->remote_nonce; | 117 | subflow_req->remote_nonce = e->remote_nonce; |
| 124 | subflow_req->local_nonce = e->local_nonce; | 118 | subflow_req->local_nonce = e->local_nonce; |
| 125 | subflow_req->backup = e->backup; | 119 | subflow_req->backup = e->backup; |
| @@ -128,11 +122,6 @@ bool mptcp_token_join_cookie_init_state(struct mptcp_subflow_request_sock *subfl · 2 unmodified lines | |||
| 128 | subflow_req->msk = msk; | 122 | subflow_req->msk = msk; |
| 129 | spin_unlock_bh(&join_entry_locks[i]); | 123 | spin_unlock_bh(&join_entry_locks[i]); |
| 130 | return true; | 124 | return true; |
| 131 | |||
| 132 | err_put: | ||
| 133 | spin_unlock_bh(&join_entry_locks[i]); | ||
| 134 | sock_put((struct sock *)msk); | ||
| 135 | return false; | ||
| 136 | } | 125 | } |
| 137 | 126 | ||
| 138 | void __init mptcp_join_cookie_init(void) | 127 | void __init mptcp_join_cookie_init(void) |
| @@ -231,6 +231,7 @@ found: · 230 unmodified lines | |||
| 231 | 231 | ||
| 232 | /** | 232 | /** |
| 233 | * mptcp_token_get_sock - retrieve mptcp connection sock using its token | 233 | * mptcp_token_get_sock - retrieve mptcp connection sock using its token |
| 234 | * @net: restrict to this namespace | ||
| 234 | * @token: token of the mptcp connection to retrieve | 235 | * @token: token of the mptcp connection to retrieve |
| 235 | * | 236 | * |
| 236 | * This function returns the mptcp connection structure with the given token. | 237 | * This function returns the mptcp connection structure with the given token. |
| @@ -238,7 +239,7 @@ found: · 1 unmodified line | |||
| 238 | * | 239 | * |
| 239 | * returns NULL if no connection with the given token value exists. | 240 | * returns NULL if no connection with the given token value exists. |
| 240 | */ | 241 | */ |
| 241 | struct mptcp_sock *mptcp_token_get_sock(u32 token) | 242 | struct mptcp_sock *mptcp_token_get_sock(struct net *net, u32 token) |
| 242 | { | 243 | { |
| 243 | struct hlist_nulls_node *pos; | 244 | struct hlist_nulls_node *pos; |
| 244 | struct token_bucket *bucket; | 245 | struct token_bucket *bucket; |
| @@ -251,11 +252,15 @@ struct mptcp_sock *mptcp_token_get_sock(u32 token) · 6 unmodified lines | |||
| 251 | again: | 252 | again: |
| 252 | sk_nulls_for_each_rcu(sk, pos, &bucket->msk_chain) { | 253 | sk_nulls_for_each_rcu(sk, pos, &bucket->msk_chain) { |
| 253 | msk = mptcp_sk(sk); | 254 | msk = mptcp_sk(sk); |
| 254 | if (READ_ONCE(msk->token) != token) | 255 | if (READ_ONCE(msk->token) != token || |
| 256 | !net_eq(sock_net(sk), net)) | ||
| 255 | continue; | 257 | continue; |
| 258 | |||
| 256 | if (!refcount_inc_not_zero(&sk->sk_refcnt)) | 259 | if (!refcount_inc_not_zero(&sk->sk_refcnt)) |
| 257 | goto not_found; | 260 | goto not_found; |
| 258 | if (READ_ONCE(msk->token) != token) { | 261 | |
| 262 | if (READ_ONCE(msk->token) != token || | ||
| 263 | !net_eq(sock_net(sk), net)) { | ||
| 259 | sock_put(sk); | 264 | sock_put(sk); |
| 260 | goto again; | 265 | goto again; |
| 261 | } | 266 | } |
| @@ -11,6 +11,7 @@ static struct mptcp_subflow_request_sock *build_req_sock(struct kunit *test) · 10 unmodified lines | |||
| 11 | GFP_USER); | 11 | GFP_USER); |
| 12 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, req); | 12 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, req); |
| 13 | mptcp_token_init_request((struct request_sock *)req); | 13 | mptcp_token_init_request((struct request_sock *)req); |
| 14 | sock_net_set((struct sock *)req, &init_net); | ||
| 14 | return req; | 15 | return req; |
| 15 | } | 16 | } |
| 16 | 17 | ||
| @@ -22,7 +23,7 @@ static void mptcp_token_test_req_basic(struct kunit *test) · 5 unmodified lines | |||
| 22 | KUNIT_ASSERT_EQ(test, 0, | 23 | KUNIT_ASSERT_EQ(test, 0, |
| 23 | mptcp_token_new_request((struct request_sock *)req)); | 24 | mptcp_token_new_request((struct request_sock *)req)); |
| 24 | KUNIT_EXPECT_NE(test, 0, (int)req->token); | 25 | KUNIT_EXPECT_NE(test, 0, (int)req->token); |
| 25 | KUNIT_EXPECT_PTR_EQ(test, null_msk, mptcp_token_get_sock(req->token)); | 26 | KUNIT_EXPECT_PTR_EQ(test, null_msk, mptcp_token_get_sock(&init_net, req->token)); |
| 26 | 27 | ||
| 27 | /* cleanup */ | 28 | /* cleanup */ |
| 28 | mptcp_token_destroy_request((struct request_sock *)req); | 29 | mptcp_token_destroy_request((struct request_sock *)req); |
| @@ -55,6 +56,7 @@ static struct mptcp_sock *build_msk(struct kunit *test) · 26 unmodified lines | |||
| 55 | msk = kunit_kzalloc(test, sizeof(struct mptcp_sock), GFP_USER); | 56 | msk = kunit_kzalloc(test, sizeof(struct mptcp_sock), GFP_USER); |
| 56 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, msk); | 57 | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, msk); |
| 57 | refcount_set(&((struct sock *)msk)->sk_refcnt, 1); | 58 | refcount_set(&((struct sock *)msk)->sk_refcnt, 1); |
| 59 | sock_net_set((struct sock *)msk, &init_net); | ||
| 58 | return msk; | 60 | return msk; |
| 59 | } | 61 | } |
| 60 | 62 | ||
| @@ -74,11 +76,11 @@ static void mptcp_token_test_msk_basic(struct kunit *test) · 13 unmodified lines | |||
| 74 | mptcp_token_new_connect((struct sock *)icsk)); | 76 | mptcp_token_new_connect((struct sock *)icsk)); |
| 75 | KUNIT_EXPECT_NE(test, 0, (int)ctx->token); | 77 | KUNIT_EXPECT_NE(test, 0, (int)ctx->token); |
| 76 | KUNIT_EXPECT_EQ(test, ctx->token, msk->token); | 78 | KUNIT_EXPECT_EQ(test, ctx->token, msk->token); |
| 77 | KUNIT_EXPECT_PTR_EQ(test, msk, mptcp_token_get_sock(ctx->token)); | 79 | KUNIT_EXPECT_PTR_EQ(test, msk, mptcp_token_get_sock(&init_net, ctx->token)); |
| 78 | KUNIT_EXPECT_EQ(test, 2, (int)refcount_read(&sk->sk_refcnt)); | 80 | KUNIT_EXPECT_EQ(test, 2, (int)refcount_read(&sk->sk_refcnt)); |
| 79 | 81 | ||
| 80 | mptcp_token_destroy(msk); | 82 | mptcp_token_destroy(msk); |
| 81 | KUNIT_EXPECT_PTR_EQ(test, null_msk, mptcp_token_get_sock(ctx->token)); | 83 | KUNIT_EXPECT_PTR_EQ(test, null_msk, mptcp_token_get_sock(&init_net, ctx->token)); |
| 82 | } | 84 | } |
| 83 | 85 | ||
| 84 | static void mptcp_token_test_accept(struct kunit *test) | 86 | static void mptcp_token_test_accept(struct kunit *test) |
| @@ -90,11 +92,11 @@ static void mptcp_token_test_accept(struct kunit *test) · 5 unmodified lines | |||
| 90 | mptcp_token_new_request((struct request_sock *)req)); | 92 | mptcp_token_new_request((struct request_sock *)req)); |
| 91 | msk->token = req->token; | 93 | msk->token = req->token; |
| 92 | mptcp_token_accept(req, msk); | 94 | mptcp_token_accept(req, msk); |
| 93 | KUNIT_EXPECT_PTR_EQ(test, msk, mptcp_token_get_sock(msk->token)); | 95 | KUNIT_EXPECT_PTR_EQ(test, msk, mptcp_token_get_sock(&init_net, msk->token)); |
| 94 | 96 | ||
| 95 | /* this is now a no-op */ | 97 | /* this is now a no-op */ |
| 96 | mptcp_token_destroy_request((struct request_sock *)req); | 98 | mptcp_token_destroy_request((struct request_sock *)req); |
| 97 | KUNIT_EXPECT_PTR_EQ(test, msk, mptcp_token_get_sock(msk->token)); | 99 | KUNIT_EXPECT_PTR_EQ(test, msk, mptcp_token_get_sock(&init_net, msk->token)); |
| 98 | 100 | ||
| 99 | /* cleanup */ | 101 | /* cleanup */ |
| 100 | mptcp_token_destroy(msk); | 102 | mptcp_token_destroy(msk); |
| @@ -116,7 +118,7 @@ static void mptcp_token_test_destroyed(struct kunit *test) · 15 unmodified lines | |||
| 116 | 118 | ||
| 117 | /* simulate race on removal */ | 119 | /* simulate race on removal */ |
| 118 | refcount_set(&sk->sk_refcnt, 0); | 120 | refcount_set(&sk->sk_refcnt, 0); |
| 119 | KUNIT_EXPECT_PTR_EQ(test, null_msk, mptcp_token_get_sock(msk->token)); | 121 | KUNIT_EXPECT_PTR_EQ(test, null_msk, mptcp_token_get_sock(&init_net, msk->token)); |
| 120 | 122 | ||
| 121 | /* cleanup */ | 123 | /* cleanup */ |
| 122 | mptcp_token_destroy(msk); | 124 | mptcp_token_destroy(msk); |
| @@ -130,11 +130,11 @@ htable_size(u8 hbits) · 129 unmodified lines | |||
| 130 | { | 130 | { |
| 131 | size_t hsize; | 131 | size_t hsize; |
| 132 | 132 | ||
| 133 | /* We must fit both into u32 in jhash and size_t */ | 133 | /* We must fit both into u32 in jhash and INT_MAX in kvmalloc_node() */ |
| 134 | if (hbits > 31) | 134 | if (hbits > 31) |
| 135 | return 0; | 135 | return 0; |
| 136 | hsize = jhash_size(hbits); | 136 | hsize = jhash_size(hbits); |
| 137 | if ((((size_t)-1) - sizeof(struct htable)) / sizeof(struct hbucket *) | 137 | if ((INT_MAX - sizeof(struct htable)) / sizeof(struct hbucket *) |
| 138 | < hsize) | 138 | < hsize) |
| 139 | return 0; | 139 | return 0; |
| 140 | 140 | ||
| @@ -1468,6 +1468,10 @@ int __init ip_vs_conn_init(void) · 1467 unmodified lines | |||
| 1468 | int idx; | 1468 | int idx; |
| 1469 | 1469 | ||
| 1470 | /* Compute size and mask */ | 1470 | /* Compute size and mask */ |
| 1471 | if (ip_vs_conn_tab_bits < 8 || ip_vs_conn_tab_bits > 20) { | ||
| 1472 | pr_info("conn_tab_bits not in [8, 20]. Using default value\n"); | ||
| 1473 | ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS; | ||
| 1474 | } | ||
| 1471 | ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; | 1475 | ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; |
| 1472 | ip_vs_conn_tab_mask = ip_vs_conn_tab_size - 1; | 1476 | ip_vs_conn_tab_mask = ip_vs_conn_tab_size - 1; |
| 1473 | 1477 | ||
| @@ -74,10 +74,14 @@ static __read_mostly struct kmem_cache *nf_conntrack_cachep; · 73 unmodified lines | |||
| 74 | static DEFINE_SPINLOCK(nf_conntrack_locks_all_lock); | 74 | static DEFINE_SPINLOCK(nf_conntrack_locks_all_lock); |
| 75 | static __read_mostly bool nf_conntrack_locks_all; | 75 | static __read_mostly bool nf_conntrack_locks_all; |
| 76 | 76 | ||
| 77 | /* serialize hash resizes and nf_ct_iterate_cleanup */ | ||
| 78 | static DEFINE_MUTEX(nf_conntrack_mutex); | ||
| 79 | |||
| 77 | #define GC_SCAN_INTERVAL (120u * HZ) | 80 | #define GC_SCAN_INTERVAL (120u * HZ) |
| 78 | #define GC_SCAN_MAX_DURATION msecs_to_jiffies(10) | 81 | #define GC_SCAN_MAX_DURATION msecs_to_jiffies(10) |
| 79 | 82 | ||
| 80 | #define MAX_CHAINLEN 64u | 83 | #define MIN_CHAINLEN 8u |
| 84 | #define MAX_CHAINLEN (32u - MIN_CHAINLEN) | ||
| 81 | 85 | ||
| 82 | static struct conntrack_gc_work conntrack_gc_work; | 86 | static struct conntrack_gc_work conntrack_gc_work; |
| 83 | 87 | ||
| @@ -188,11 +192,13 @@ seqcount_spinlock_t nf_conntrack_generation __read_mostly; · 104 unmodified lines | |||
| 188 | static siphash_key_t nf_conntrack_hash_rnd __read_mostly; | 192 | static siphash_key_t nf_conntrack_hash_rnd __read_mostly; |
| 189 | 193 | ||
| 190 | static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, | 194 | static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, |
| 195 | unsigned int zoneid, | ||
| 191 | const struct net *net) | 196 | const struct net *net) |
| 192 | { | 197 | { |
| 193 | struct { | 198 | struct { |
| 194 | struct nf_conntrack_man src; | 199 | struct nf_conntrack_man src; |
| 195 | union nf_inet_addr dst_addr; | 200 | union nf_inet_addr dst_addr; |
| 201 | unsigned int zone; | ||
| 196 | u32 net_mix; | 202 | u32 net_mix; |
| 197 | u16 dport; | 203 | u16 dport; |
| 198 | u16 proto; | 204 | u16 proto; |
| @@ -205,6 +211,7 @@ static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, · 6 unmodified lines | |||
| 205 | /* The direction must be ignored, so handle usable members manually. */ | 211 | /* The direction must be ignored, so handle usable members manually. */ |
| 206 | combined.src = tuple->src; | 212 | combined.src = tuple->src; |
| 207 | combined.dst_addr = tuple->dst.u3; | 213 | combined.dst_addr = tuple->dst.u3; |
| 214 | combined.zone = zoneid; | ||
| 208 | combined.net_mix = net_hash_mix(net); | 215 | combined.net_mix = net_hash_mix(net); |
| 209 | combined.dport = (__force __u16)tuple->dst.u.all; | 216 | combined.dport = (__force __u16)tuple->dst.u.all; |
| 210 | combined.proto = tuple->dst.protonum; | 217 | combined.proto = tuple->dst.protonum; |
| @@ -219,15 +226,17 @@ static u32 scale_hash(u32 hash) · 8 unmodified lines | |||
| 219 | 226 | ||
| 220 | static u32 __hash_conntrack(const struct net *net, | 227 | static u32 __hash_conntrack(const struct net *net, |
| 221 | const struct nf_conntrack_tuple *tuple, | 228 | const struct nf_conntrack_tuple *tuple, |
| 229 | unsigned int zoneid, | ||
| 222 | unsigned int size) | 230 | unsigned int size) |
| 223 | { | 231 | { |
| 224 | return reciprocal_scale(hash_conntrack_raw(tuple, net), size); | 232 | return reciprocal_scale(hash_conntrack_raw(tuple, zoneid, net), size); |
| 225 | } | 233 | } |
| 226 | 234 | ||
| 227 | static u32 hash_conntrack(const struct net *net, | 235 | static u32 hash_conntrack(const struct net *net, |
| 228 | const struct nf_conntrack_tuple *tuple) | 236 | const struct nf_conntrack_tuple *tuple, |
| 237 | unsigned int zoneid) | ||
| 229 | { | 238 | { |
| 230 | return scale_hash(hash_conntrack_raw(tuple, net)); | 239 | return scale_hash(hash_conntrack_raw(tuple, zoneid, net)); |
| 231 | } | 240 | } |
| 232 | 241 | ||
| 233 | static bool nf_ct_get_tuple_ports(const struct sk_buff *skb, | 242 | static bool nf_ct_get_tuple_ports(const struct sk_buff *skb, |
| @@ -650,9 +659,11 @@ static void nf_ct_delete_from_lists(struct nf_conn *ct) · 416 unmodified lines | |||
| 650 | do { | 659 | do { |
| 651 | sequence = read_seqcount_begin(&nf_conntrack_generation); | 660 | sequence = read_seqcount_begin(&nf_conntrack_generation); |
| 652 | hash = hash_conntrack(net, | 661 | hash = hash_conntrack(net, |
| 653 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 662 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |
| 663 | nf_ct_zone_id(nf_ct_zone(ct), IP_CT_DIR_ORIGINAL)); | ||
| 654 | reply_hash = hash_conntrack(net, | 664 | reply_hash = hash_conntrack(net, |
| 655 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 665 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
| 666 | nf_ct_zone_id(nf_ct_zone(ct), IP_CT_DIR_REPLY)); | ||
| 656 | } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); | 667 | } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); |
| 657 | 668 | ||
| 658 | clean_from_lists(ct); | 669 | clean_from_lists(ct); |
| @@ -819,8 +830,20 @@ struct nf_conntrack_tuple_hash * · 160 unmodified lines | |||
| 819 | nf_conntrack_find_get(struct net *net, const struct nf_conntrack_zone *zone, | 830 | nf_conntrack_find_get(struct net *net, const struct nf_conntrack_zone *zone, |
| 820 | const struct nf_conntrack_tuple *tuple) | 831 | const struct nf_conntrack_tuple *tuple) |
| 821 | { | 832 | { |
| 822 | return __nf_conntrack_find_get(net, zone, tuple, | 833 | unsigned int rid, zone_id = nf_ct_zone_id(zone, IP_CT_DIR_ORIGINAL); |
| 823 | hash_conntrack_raw(tuple, net)); | 834 | struct nf_conntrack_tuple_hash *thash; |
| 835 | |||
| 836 | thash = __nf_conntrack_find_get(net, zone, tuple, | ||
| 837 | hash_conntrack_raw(tuple, zone_id, net)); | ||
| 838 | |||
| 839 | if (thash) | ||
| 840 | return thash; | ||
| 841 | |||
| 842 | rid = nf_ct_zone_id(zone, IP_CT_DIR_REPLY); | ||
| 843 | if (rid != zone_id) | ||
| 844 | return __nf_conntrack_find_get(net, zone, tuple, | ||
| 845 | hash_conntrack_raw(tuple, rid, net)); | ||
| 846 | return thash; | ||
| 824 | } | 847 | } |
| 825 | EXPORT_SYMBOL_GPL(nf_conntrack_find_get); | 848 | EXPORT_SYMBOL_GPL(nf_conntrack_find_get); |
| 826 | 849 | ||
| @@ -842,6 +865,7 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) · 15 unmodified lines | |||
| 842 | unsigned int hash, reply_hash; | 865 | unsigned int hash, reply_hash; |
| 843 | struct nf_conntrack_tuple_hash *h; | 866 | struct nf_conntrack_tuple_hash *h; |
| 844 | struct hlist_nulls_node *n; | 867 | struct hlist_nulls_node *n; |
| 868 | unsigned int max_chainlen; | ||
| 845 | unsigned int chainlen = 0; | 869 | unsigned int chainlen = 0; |
| 846 | unsigned int sequence; | 870 | unsigned int sequence; |
| 847 | int err = -EEXIST; | 871 | int err = -EEXIST; |
| @@ -852,18 +876,22 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) · 4 unmodified lines | |||
| 852 | do { | 876 | do { |
| 853 | sequence = read_seqcount_begin(&nf_conntrack_generation); | 877 | sequence = read_seqcount_begin(&nf_conntrack_generation); |
| 854 | hash = hash_conntrack(net, | 878 | hash = hash_conntrack(net, |
| 855 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 879 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |
| 880 | nf_ct_zone_id(nf_ct_zone(ct), IP_CT_DIR_ORIGINAL)); | ||
| 856 | reply_hash = hash_conntrack(net, | 881 | reply_hash = hash_conntrack(net, |
| 857 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 882 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
| 883 | nf_ct_zone_id(nf_ct_zone(ct), IP_CT_DIR_REPLY)); | ||
| 858 | } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); | 884 | } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); |
| 859 | 885 | ||
| 886 | max_chainlen = MIN_CHAINLEN + prandom_u32_max(MAX_CHAINLEN); | ||
| 887 | |||
| 860 | /* See if there's one in the list already, including reverse */ | 888 | /* See if there's one in the list already, including reverse */ |
| 861 | hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[hash], hnnode) { | 889 | hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[hash], hnnode) { |
| 862 | if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | 890 | if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |
| 863 | zone, net)) | 891 | zone, net)) |
| 864 | goto out; | 892 | goto out; |
| 865 | 893 | ||
| 866 | if (chainlen++ > MAX_CHAINLEN) | 894 | if (chainlen++ > max_chainlen) |
| 867 | goto chaintoolong; | 895 | goto chaintoolong; |
| 868 | } | 896 | } |
| 869 | 897 | ||
| @@ -873,7 +901,7 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) · 3 unmodified lines | |||
| 873 | if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, | 901 | if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
| 874 | zone, net)) | 902 | zone, net)) |
| 875 | goto out; | 903 | goto out; |
| 876 | if (chainlen++ > MAX_CHAINLEN) | 904 | if (chainlen++ > max_chainlen) |
| 877 | goto chaintoolong; | 905 | goto chaintoolong; |
| 878 | } | 906 | } |
| 879 | 907 | ||
| @@ -1103,8 +1131,8 @@ drop: · 223 unmodified lines | |||
| 1103 | int | 1131 | int |
| 1104 | __nf_conntrack_confirm(struct sk_buff *skb) | 1132 | __nf_conntrack_confirm(struct sk_buff *skb) |
| 1105 | { | 1133 | { |
| 1134 | unsigned int chainlen = 0, sequence, max_chainlen; | ||
| 1106 | const struct nf_conntrack_zone *zone; | 1135 | const struct nf_conntrack_zone *zone; |
| 1107 | unsigned int chainlen = 0, sequence; | ||
| 1108 | unsigned int hash, reply_hash; | 1136 | unsigned int hash, reply_hash; |
| 1109 | struct nf_conntrack_tuple_hash *h; | 1137 | struct nf_conntrack_tuple_hash *h; |
| 1110 | struct nf_conn *ct; | 1138 | struct nf_conn *ct; |
| @@ -1133,8 +1161,8 @@ __nf_conntrack_confirm(struct sk_buff *skb) · 22 unmodified lines | |||
| 1133 | hash = *(unsigned long *)&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev; | 1161 | hash = *(unsigned long *)&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev; |
| 1134 | hash = scale_hash(hash); | 1162 | hash = scale_hash(hash); |
| 1135 | reply_hash = hash_conntrack(net, | 1163 | reply_hash = hash_conntrack(net, |
| 1136 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 1164 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
| 1137 | 1165 | nf_ct_zone_id(nf_ct_zone(ct), IP_CT_DIR_REPLY)); | |
| 1138 | } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); | 1166 | } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); |
| 1139 | 1167 | ||
| 1140 | /* We're not in hash table, and we refuse to set up related | 1168 | /* We're not in hash table, and we refuse to set up related |
| @@ -1168,6 +1196,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) · 27 unmodified lines | |||
| 1168 | goto dying; | 1196 | goto dying; |
| 1169 | } | 1197 | } |
| 1170 | 1198 | ||
| 1199 | max_chainlen = MIN_CHAINLEN + prandom_u32_max(MAX_CHAINLEN); | ||
| 1171 | /* See if there's one in the list already, including reverse: | 1200 | /* See if there's one in the list already, including reverse: |
| 1172 | NAT could have grabbed it without realizing, since we're | 1201 | NAT could have grabbed it without realizing, since we're |
| 1173 | not in the hash. If there is, we lost race. */ | 1202 | not in the hash. If there is, we lost race. */ |
| @@ -1175,7 +1204,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) · 1 unmodified line | |||
| 1175 | if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | 1204 | if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |
| 1176 | zone, net)) | 1205 | zone, net)) |
| 1177 | goto out; | 1206 | goto out; |
| 1178 | if (chainlen++ > MAX_CHAINLEN) | 1207 | if (chainlen++ > max_chainlen) |
| 1179 | goto chaintoolong; | 1208 | goto chaintoolong; |
| 1180 | } | 1209 | } |
| 1181 | 1210 | ||
| @@ -1184,7 +1213,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) · 2 unmodified lines | |||
| 1184 | if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, | 1213 | if (nf_ct_key_equal(h, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
| 1185 | zone, net)) | 1214 | zone, net)) |
| 1186 | goto out; | 1215 | goto out; |
| 1187 | if (chainlen++ > MAX_CHAINLEN) { | 1216 | if (chainlen++ > max_chainlen) { |
| 1188 | chaintoolong: | 1217 | chaintoolong: |
| 1189 | nf_ct_add_to_dying_list(ct); | 1218 | nf_ct_add_to_dying_list(ct); |
| 1190 | NF_CT_STAT_INC(net, chaintoolong); | 1219 | NF_CT_STAT_INC(net, chaintoolong); |
| @@ -1246,7 +1275,7 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, · 55 unmodified lines | |||
| 1246 | rcu_read_lock(); | 1275 | rcu_read_lock(); |
| 1247 | begin: | 1276 | begin: |
| 1248 | nf_conntrack_get_ht(&ct_hash, &hsize); | 1277 | nf_conntrack_get_ht(&ct_hash, &hsize); |
| 1249 | hash = __hash_conntrack(net, tuple, hsize); | 1278 | hash = __hash_conntrack(net, tuple, nf_ct_zone_id(zone, IP_CT_DIR_REPLY), hsize); |
| 1250 | 1279 | ||
| 1251 | hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[hash], hnnode) { | 1280 | hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[hash], hnnode) { |
| 1252 | ct = nf_ct_tuplehash_to_ctrack(h); | 1281 | ct = nf_ct_tuplehash_to_ctrack(h); |
| @@ -1687,8 +1716,8 @@ resolve_normal_ct(struct nf_conn *tmpl, · 434 unmodified lines | |||
| 1687 | struct nf_conntrack_tuple_hash *h; | 1716 | struct nf_conntrack_tuple_hash *h; |
| 1688 | enum ip_conntrack_info ctinfo; | 1717 | enum ip_conntrack_info ctinfo; |
| 1689 | struct nf_conntrack_zone tmp; | 1718 | struct nf_conntrack_zone tmp; |
| 1719 | u32 hash, zone_id, rid; | ||
| 1690 | struct nf_conn *ct; | 1720 | struct nf_conn *ct; |
| 1691 | u32 hash; | ||
| 1692 | 1721 | ||
| 1693 | if (!nf_ct_get_tuple(skb, skb_network_offset(skb), | 1722 | if (!nf_ct_get_tuple(skb, skb_network_offset(skb), |
| 1694 | dataoff, state->pf, protonum, state->net, | 1723 | dataoff, state->pf, protonum, state->net, |
| @@ -1699,8 +1728,20 @@ resolve_normal_ct(struct nf_conn *tmpl, · 4 unmodified lines | |||
| 1699 | 1728 | ||
| 1700 | /* look for tuple match */ | 1729 | /* look for tuple match */ |
| 1701 | zone = nf_ct_zone_tmpl(tmpl, skb, &tmp); | 1730 | zone = nf_ct_zone_tmpl(tmpl, skb, &tmp); |
| 1702 | hash = hash_conntrack_raw(&tuple, state->net); | 1731 | |
| 1732 | zone_id = nf_ct_zone_id(zone, IP_CT_DIR_ORIGINAL); | ||
| 1733 | hash = hash_conntrack_raw(&tuple, zone_id, state->net); | ||
| 1703 | h = __nf_conntrack_find_get(state->net, zone, &tuple, hash); | 1734 | h = __nf_conntrack_find_get(state->net, zone, &tuple, hash); |
| 1735 | |||
| 1736 | if (!h) { | ||
| 1737 | rid = nf_ct_zone_id(zone, IP_CT_DIR_REPLY); | ||
| 1738 | if (zone_id != rid) { | ||
| 1739 | u32 tmp = hash_conntrack_raw(&tuple, rid, state->net); | ||
| 1740 | |||
| 1741 | h = __nf_conntrack_find_get(state->net, zone, &tuple, tmp); | ||
| 1742 | } | ||
| 1743 | } | ||
| 1744 | |||
| 1704 | if (!h) { | 1745 | if (!h) { |
| 1705 | h = init_conntrack(state->net, tmpl, &tuple, | 1746 | h = init_conntrack(state->net, tmpl, &tuple, |
| 1706 | skb, dataoff, hash); | 1747 | skb, dataoff, hash); |
| @@ -2225,28 +2266,31 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data), · 518 unmodified lines | |||
| 2225 | spinlock_t *lockp; | 2266 | spinlock_t *lockp; |
| 2226 | 2267 | ||
| 2227 | for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { | 2268 | for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { |
| 2269 | struct hlist_nulls_head *hslot = &nf_conntrack_hash[*bucket]; | ||
| 2270 | |||
| 2271 | if (hlist_nulls_empty(hslot)) | ||
| 2272 | continue; | ||
| 2273 | |||
| 2228 | lockp = &nf_conntrack_locks[*bucket % CONNTRACK_LOCKS]; | 2274 | lockp = &nf_conntrack_locks[*bucket % CONNTRACK_LOCKS]; |
| 2229 | local_bh_disable(); | 2275 | local_bh_disable(); |
| 2230 | nf_conntrack_lock(lockp); | 2276 | nf_conntrack_lock(lockp); |
| 2231 | if (*bucket < nf_conntrack_htable_size) { | 2277 | hlist_nulls_for_each_entry(h, n, hslot, hnnode) { |
| 2232 | hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnnode) { | 2278 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_REPLY) |
| 2233 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_REPLY) | 2279 | continue; |
| 2234 | continue; | 2280 | /* All nf_conn objects are added to hash table twice, one |
| 2235 | /* All nf_conn objects are added to hash table twice, one | 2281 | * for original direction tuple, once for the reply tuple. |
| 2236 | * for original direction tuple, once for the reply tuple. | 2282 | * |
| 2237 | * | 2283 | * Exception: In the IPS_NAT_CLASH case, only the reply |
| 2238 | * Exception: In the IPS_NAT_CLASH case, only the reply | 2284 | * tuple is added (the original tuple already existed for |
| 2239 | * tuple is added (the original tuple already existed for | 2285 | * a different object). |
| 2240 | * a different object). | 2286 | * |
| 2241 | * | 2287 | * We only need to call the iterator once for each |
| 2242 | * We only need to call the iterator once for each | 2288 | * conntrack, so we just use the 'reply' direction |
| 2243 | * conntrack, so we just use the 'reply' direction | 2289 | * tuple while iterating. |
| 2244 | * tuple while iterating. | 2290 | */ |
| 2245 | */ | 2291 | ct = nf_ct_tuplehash_to_ctrack(h); |
| 2246 | ct = nf_ct_tuplehash_to_ctrack(h); | 2292 | if (iter(ct, data)) |
| 2247 | if (iter(ct, data)) | 2293 | goto found; |
| 2248 | goto found; | ||
| 2249 | } | ||
| 2250 | } | 2294 | } |
| 2251 | spin_unlock(lockp); | 2295 | spin_unlock(lockp); |
| 2252 | local_bh_enable(); | 2296 | local_bh_enable(); |
| @@ -2264,26 +2308,20 @@ found: · 11 unmodified lines | |||
| 2264 | static void nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), | 2308 | static void nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), |
| 2265 | void *data, u32 portid, int report) | 2309 | void *data, u32 portid, int report) |
| 2266 | { | 2310 | { |
| 2267 | unsigned int bucket = 0, sequence; | 2311 | unsigned int bucket = 0; |
| 2268 | struct nf_conn *ct; | 2312 | struct nf_conn *ct; |
| 2269 | 2313 | ||
| 2270 | might_sleep(); | 2314 | might_sleep(); |
| 2271 | 2315 | ||
| 2272 | for (;;) { | 2316 | mutex_lock(&nf_conntrack_mutex); |
| 2273 | sequence = read_seqcount_begin(&nf_conntrack_generation); | 2317 | while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) { |
| 2274 | 2318 | /* Time to push up daises... */ | |
| 2275 | while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) { | ||
| 2276 | /* Time to push up daises... */ | ||
| 2277 | 2319 | ||
| 2278 | nf_ct_delete(ct, portid, report); | 2320 | nf_ct_delete(ct, portid, report); |
| 2279 | nf_ct_put(ct); | 2321 | nf_ct_put(ct); |
| 2280 | cond_resched(); | 2322 | cond_resched(); |
| 2281 | } | ||
| 2282 | |||
| 2283 | if (!read_seqcount_retry(&nf_conntrack_generation, sequence)) | ||
| 2284 | break; | ||
| 2285 | bucket = 0; | ||
| 2286 | } | 2323 | } |
| 2324 | mutex_unlock(&nf_conntrack_mutex); | ||
| 2287 | } | 2325 | } |
| 2288 | 2326 | ||
| 2289 | struct iter_data { | 2327 | struct iter_data { |
| @@ -2519,8 +2557,10 @@ int nf_conntrack_hash_resize(unsigned int hashsize) · 229 unmodified lines | |||
| 2519 | if (!hash) | 2557 | if (!hash) |
| 2520 | return -ENOMEM; | 2558 | return -ENOMEM; |
| 2521 | 2559 | ||
| 2560 | mutex_lock(&nf_conntrack_mutex); | ||
| 2522 | old_size = nf_conntrack_htable_size; | 2561 | old_size = nf_conntrack_htable_size; |
| 2523 | if (old_size == hashsize) { | 2562 | if (old_size == hashsize) { |
| 2563 | mutex_unlock(&nf_conntrack_mutex); | ||
| 2524 | kvfree(hash); | 2564 | kvfree(hash); |
| 2525 | return 0; | 2565 | return 0; |
| 2526 | } | 2566 | } |
| @@ -2537,12 +2577,16 @@ int nf_conntrack_hash_resize(unsigned int hashsize) · 10 unmodified lines | |||
| 2537 | 2577 | ||
| 2538 | for (i = 0; i < nf_conntrack_htable_size; i++) { | 2578 | for (i = 0; i < nf_conntrack_htable_size; i++) { |
| 2539 | while (!hlist_nulls_empty(&nf_conntrack_hash[i])) { | 2579 | while (!hlist_nulls_empty(&nf_conntrack_hash[i])) { |
| 2580 | unsigned int zone_id; | ||
| 2581 | |||
| 2540 | h = hlist_nulls_entry(nf_conntrack_hash[i].first, | 2582 | h = hlist_nulls_entry(nf_conntrack_hash[i].first, |
| 2541 | struct nf_conntrack_tuple_hash, hnnode); | 2583 | struct nf_conntrack_tuple_hash, hnnode); |
| 2542 | ct = nf_ct_tuplehash_to_ctrack(h); | 2584 | ct = nf_ct_tuplehash_to_ctrack(h); |
| 2543 | hlist_nulls_del_rcu(&h->hnnode); | 2585 | hlist_nulls_del_rcu(&h->hnnode); |
| 2586 | |||
| 2587 | zone_id = nf_ct_zone_id(nf_ct_zone(ct), NF_CT_DIRECTION(h)); | ||
| 2544 | bucket = __hash_conntrack(nf_ct_net(ct), | 2588 | bucket = __hash_conntrack(nf_ct_net(ct), |
| 2545 | &h->tuple, hashsize); | 2589 | &h->tuple, zone_id, hashsize); |
| 2546 | hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); | 2590 | hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); |
| 2547 | } | 2591 | } |
| 2548 | } | 2592 | } |
| @@ -2556,6 +2600,8 @@ int nf_conntrack_hash_resize(unsigned int hashsize) · 7 unmodified lines | |||
| 2556 | nf_conntrack_all_unlock(); | 2600 | nf_conntrack_all_unlock(); |
| 2557 | local_bh_enable(); | 2601 | local_bh_enable(); |
| 2558 | 2602 | ||
| 2603 | mutex_unlock(&nf_conntrack_mutex); | ||
| 2604 | |||
| 2559 | synchronize_net(); | 2605 | synchronize_net(); |
| 2560 | kvfree(old_hash); | 2606 | kvfree(old_hash); |
| 2561 | return 0; | 2607 | return 0; |
| @@ -150,13 +150,16 @@ static void __nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl) · 149 unmodified lines | |||
| 150 | 150 | ||
| 151 | /* We keep an extra hash for each conntrack, for fast searching. */ | 151 | /* We keep an extra hash for each conntrack, for fast searching. */ |
| 152 | static unsigned int | 152 | static unsigned int |
| 153 | hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple) | 153 | hash_by_src(const struct net *net, |
| 154 | const struct nf_conntrack_zone *zone, | ||
| 155 | const struct nf_conntrack_tuple *tuple) | ||
| 154 | { | 156 | { |
| 155 | unsigned int hash; | 157 | unsigned int hash; |
| 156 | struct { | 158 | struct { |
| 157 | struct nf_conntrack_man src; | 159 | struct nf_conntrack_man src; |
| 158 | u32 net_mix; | 160 | u32 net_mix; |
| 159 | u32 protonum; | 161 | u32 protonum; |
| 162 | u32 zone; | ||
| 160 | } __aligned(SIPHASH_ALIGNMENT) combined; | 163 | } __aligned(SIPHASH_ALIGNMENT) combined; |
| 161 | 164 | ||
| 162 | get_random_once(&nf_nat_hash_rnd, sizeof(nf_nat_hash_rnd)); | 165 | get_random_once(&nf_nat_hash_rnd, sizeof(nf_nat_hash_rnd)); |
| @@ -165,9 +168,13 @@ hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple) · 2 unmodified lines | |||
| 165 | 168 | ||
| 166 | /* Original src, to ensure we map it consistently if poss. */ | 169 | /* Original src, to ensure we map it consistently if poss. */ |
| 167 | combined.src = tuple->src; | 170 | combined.src = tuple->src; |
| 168 | combined.net_mix = net_hash_mix(n); | 171 | combined.net_mix = net_hash_mix(net); |
| 169 | combined.protonum = tuple->dst.protonum; | 172 | combined.protonum = tuple->dst.protonum; |
| 170 | 173 | ||
| 174 | /* Zone ID can be used provided its valid for both directions */ | ||
| 175 | if (zone->dir == NF_CT_DEFAULT_ZONE_DIR) | ||
| 176 | combined.zone = zone->id; | ||
| 177 | |||
| 171 | hash = siphash(&combined, sizeof(combined), &nf_nat_hash_rnd); | 178 | hash = siphash(&combined, sizeof(combined), &nf_nat_hash_rnd); |
| 172 | 179 | ||
| 173 | return reciprocal_scale(hash, nf_nat_htable_size); | 180 | return reciprocal_scale(hash, nf_nat_htable_size); |
| @@ -272,7 +279,7 @@ find_appropriate_src(struct net *net, · 98 unmodified lines | |||
| 272 | struct nf_conntrack_tuple *result, | 279 | struct nf_conntrack_tuple *result, |
| 273 | const struct nf_nat_range2 *range) | 280 | const struct nf_nat_range2 *range) |
| 274 | { | 281 | { |
| 275 | unsigned int h = hash_by_src(net, tuple); | 282 | unsigned int h = hash_by_src(net, zone, tuple); |
| 276 | const struct nf_conn *ct; | 283 | const struct nf_conn *ct; |
| 277 | 284 | ||
| 278 | hlist_for_each_entry_rcu(ct, &nf_nat_bysource[h], nat_bysource) { | 285 | hlist_for_each_entry_rcu(ct, &nf_nat_bysource[h], nat_bysource) { |
| @@ -619,7 +626,7 @@ nf_nat_setup_info(struct nf_conn *ct, · 340 unmodified lines | |||
| 619 | unsigned int srchash; | 626 | unsigned int srchash; |
| 620 | spinlock_t *lock; | 627 | spinlock_t *lock; |
| 621 | 628 | ||
| 622 | srchash = hash_by_src(net, | 629 | srchash = hash_by_src(net, nf_ct_zone(ct), |
| 623 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 630 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
| 624 | lock = &nf_nat_locks[srchash % CONNTRACK_LOCKS]; | 631 | lock = &nf_nat_locks[srchash % CONNTRACK_LOCKS]; |
| 625 | spin_lock_bh(lock); | 632 | spin_lock_bh(lock); |
| @@ -788,7 +795,7 @@ static void __nf_nat_cleanup_conntrack(struct nf_conn *ct) · 162 unmodified lines | |||
| 788 | { | 795 | { |
| 789 | unsigned int h; | 796 | unsigned int h; |
| 790 | 797 | ||
| 791 | h = hash_by_src(nf_ct_net(ct), &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 798 | h = hash_by_src(nf_ct_net(ct), nf_ct_zone(ct), &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
| 792 | spin_lock_bh(&nf_nat_locks[h % CONNTRACK_LOCKS]); | 799 | spin_lock_bh(&nf_nat_locks[h % CONNTRACK_LOCKS]); |
| 793 | hlist_del_rcu(&ct->nat_bysource); | 800 | hlist_del_rcu(&ct->nat_bysource); |
| 794 | spin_unlock_bh(&nf_nat_locks[h % CONNTRACK_LOCKS]); | 801 | spin_unlock_bh(&nf_nat_locks[h % CONNTRACK_LOCKS]); |
| @@ -9,8 +9,19 @@ · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | #include <net/netfilter/nf_nat_masquerade.h> | 10 | #include <net/netfilter/nf_nat_masquerade.h> |
| 11 | 11 | ||
| 12 | struct masq_dev_work { | ||
| 13 | struct work_struct work; | ||
| 14 | struct net *net; | ||
| 15 | union nf_inet_addr addr; | ||
| 16 | int ifindex; | ||
| 17 | int (*iter)(struct nf_conn *i, void *data); | ||
| 18 | }; | ||
| 19 | |||
| 20 | #define MAX_MASQ_WORKER_COUNT 16 | ||
| 21 | |||
| 12 | static DEFINE_MUTEX(masq_mutex); | 22 | static DEFINE_MUTEX(masq_mutex); |
| 13 | static unsigned int masq_refcnt __read_mostly; | 23 | static unsigned int masq_refcnt __read_mostly; |
| 24 | static atomic_t masq_worker_count __read_mostly; | ||
| 14 | 25 | ||
| 15 | unsigned int | 26 | unsigned int |
| 16 | nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum, | 27 | nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum, |
| @@ -63,13 +74,71 @@ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum, · 46 unmodified lines | |||
| 63 | } | 74 | } |
| 64 | EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4); | 75 | EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4); |
| 65 | 76 | ||
| 66 | static int device_cmp(struct nf_conn *i, void *ifindex) | 77 | static void iterate_cleanup_work(struct work_struct *work) |
| 78 | { | ||
| 79 | struct masq_dev_work *w; | ||
| 80 | |||
| 81 | w = container_of(work, struct masq_dev_work, work); | ||
| 82 | |||
| 83 | nf_ct_iterate_cleanup_net(w->net, w->iter, (void *)w, 0, 0); | ||
| 84 | |||
| 85 | put_net(w->net); | ||
| 86 | kfree(w); | ||
| 87 | atomic_dec(&masq_worker_count); | ||
| 88 | module_put(THIS_MODULE); | ||
| 89 | } | ||
| 90 | |||
| 91 | /* Iterate conntrack table in the background and remove conntrack entries | ||
| 92 | * that use the device/address being removed. | ||
| 93 | * | ||
| 94 | * In case too many work items have been queued already or memory allocation | ||
| 95 | * fails iteration is skipped, conntrack entries will time out eventually. | ||
| 96 | */ | ||
| 97 | static void nf_nat_masq_schedule(struct net *net, union nf_inet_addr *addr, | ||
| 98 | int ifindex, | ||
| 99 | int (*iter)(struct nf_conn *i, void *data), | ||
| 100 | gfp_t gfp_flags) | ||
| 101 | { | ||
| 102 | struct masq_dev_work *w; | ||
| 103 | |||
| 104 | if (atomic_read(&masq_worker_count) > MAX_MASQ_WORKER_COUNT) | ||
| 105 | return; | ||
| 106 | |||
| 107 | net = maybe_get_net(net); | ||
| 108 | if (!net) | ||
| 109 | return; | ||
| 110 | |||
| 111 | if (!try_module_get(THIS_MODULE)) | ||
| 112 | goto err_module; | ||
| 113 | |||
| 114 | w = kzalloc(sizeof(*w), gfp_flags); | ||
| 115 | if (w) { | ||
| 116 | /* We can overshoot MAX_MASQ_WORKER_COUNT, no big deal */ | ||
| 117 | atomic_inc(&masq_worker_count); | ||
| 118 | |||
| 119 | INIT_WORK(&w->work, iterate_cleanup_work); | ||
| 120 | w->ifindex = ifindex; | ||
| 121 | w->net = net; | ||
| 122 | w->iter = iter; | ||
| 123 | if (addr) | ||
| 124 | w->addr = *addr; | ||
| 125 | schedule_work(&w->work); | ||
| 126 | return; | ||
| 127 | } | ||
| 128 | |||
| 129 | module_put(THIS_MODULE); | ||
| 130 | err_module: | ||
| 131 | put_net(net); | ||
| 132 | } | ||
| 133 | |||
| 134 | static int device_cmp(struct nf_conn *i, void *arg) | ||
| 67 | { | 135 | { |
| 68 | const struct nf_conn_nat *nat = nfct_nat(i); | 136 | const struct nf_conn_nat *nat = nfct_nat(i); |
| 137 | const struct masq_dev_work *w = arg; | ||
| 69 | 138 | ||
| 70 | if (!nat) | 139 | if (!nat) |
| 71 | return 0; | 140 | return 0; |
| 72 | return nat->masq_index == (int)(long)ifindex; | 141 | return nat->masq_index == w->ifindex; |
| 73 | } | 142 | } |
| 74 | 143 | ||
| 75 | static int masq_device_event(struct notifier_block *this, | 144 | static int masq_device_event(struct notifier_block *this, |
| @@ -85,8 +154,8 @@ static int masq_device_event(struct notifier_block *this, · 9 unmodified lines | |||
| 85 | * and forget them. | 154 | * and forget them. |
| 86 | */ | 155 | */ |
| 87 | 156 | ||
| 88 | nf_ct_iterate_cleanup_net(net, device_cmp, | 157 | nf_nat_masq_schedule(net, NULL, dev->ifindex, |
| 89 | (void *)(long)dev->ifindex, 0, 0); | 158 | device_cmp, GFP_KERNEL); |
| 90 | } | 159 | } |
| 91 | 160 | ||
| 92 | return NOTIFY_DONE; | 161 | return NOTIFY_DONE; |
| @@ -94,35 +163,45 @@ static int masq_device_event(struct notifier_block *this, · 1 unmodified line | |||
| 94 | 163 | ||
| 95 | static int inet_cmp(struct nf_conn *ct, void *ptr) | 164 | static int inet_cmp(struct nf_conn *ct, void *ptr) |
| 96 | { | 165 | { |
| 97 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; | ||
| 98 | struct net_device *dev = ifa->ifa_dev->dev; | ||
| 99 | struct nf_conntrack_tuple *tuple; | 166 | struct nf_conntrack_tuple *tuple; |
| 167 | struct masq_dev_work *w = ptr; | ||
| 100 | 168 | ||
| 101 | if (!device_cmp(ct, (void *)(long)dev->ifindex)) | 169 | if (!device_cmp(ct, ptr)) |
| 102 | return 0; | 170 | return 0; |
| 103 | 171 | ||
| 104 | tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; | 172 | tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; |
| 105 | 173 | ||
| 106 | return ifa->ifa_address == tuple->dst.u3.ip; | 174 | return nf_inet_addr_cmp(&w->addr, &tuple->dst.u3); |
| 107 | } | 175 | } |
| 108 | 176 | ||
| 109 | static int masq_inet_event(struct notifier_block *this, | 177 | static int masq_inet_event(struct notifier_block *this, |
| 110 | unsigned long event, | 178 | unsigned long event, |
| 111 | void *ptr) | 179 | void *ptr) |
| 112 | { | 180 | { |
| 113 | struct in_device *idev = ((struct in_ifaddr *)ptr)->ifa_dev; | 181 | const struct in_ifaddr *ifa = ptr; |
| 114 | struct net *net = dev_net(idev->dev); | 182 | const struct in_device *idev; |
| 183 | const struct net_device *dev; | ||
| 184 | union nf_inet_addr addr; | ||
| 185 | |||
| 186 | if (event != NETDEV_DOWN) | ||
| 187 | return NOTIFY_DONE; | ||
| 115 | 188 | ||
| 116 | /* The masq_dev_notifier will catch the case of the device going | 189 | /* The masq_dev_notifier will catch the case of the device going |
| 117 | * down. So if the inetdev is dead and being destroyed we have | 190 | * down. So if the inetdev is dead and being destroyed we have |
| 118 | * no work to do. Otherwise this is an individual address removal | 191 | * no work to do. Otherwise this is an individual address removal |
| 119 | * and we have to perform the flush. | 192 | * and we have to perform the flush. |
| 120 | */ | 193 | */ |
| 194 | idev = ifa->ifa_dev; | ||
| 121 | if (idev->dead) | 195 | if (idev->dead) |
| 122 | return NOTIFY_DONE; | 196 | return NOTIFY_DONE; |
| 123 | 197 | ||
| 124 | if (event == NETDEV_DOWN) | 198 | memset(&addr, 0, sizeof(addr)); |
| 125 | nf_ct_iterate_cleanup_net(net, inet_cmp, ptr, 0, 0); | 199 | |
| 200 | addr.ip = ifa->ifa_address; | ||
| 201 | |||
| 202 | dev = idev->dev; | ||
| 203 | nf_nat_masq_schedule(dev_net(idev->dev), &addr, dev->ifindex, | ||
| 204 | inet_cmp, GFP_KERNEL); | ||
| 126 | 205 | ||
| 127 | return NOTIFY_DONE; | 206 | return NOTIFY_DONE; |
| 128 | } | 207 | } |
| @@ -136,8 +215,6 @@ static struct notifier_block masq_inet_notifier = { · 7 unmodified lines | |||
| 136 | }; | 215 | }; |
| 137 | 216 | ||
| 138 | #if IS_ENABLED(CONFIG_IPV6) | 217 | #if IS_ENABLED(CONFIG_IPV6) |
| 139 | static atomic_t v6_worker_count __read_mostly; | ||
| 140 | |||
| 141 | static int | 218 | static int |
| 142 | nat_ipv6_dev_get_saddr(struct net *net, const struct net_device *dev, | 219 | nat_ipv6_dev_get_saddr(struct net *net, const struct net_device *dev, |
| 143 | const struct in6_addr *daddr, unsigned int srcprefs, | 220 | const struct in6_addr *daddr, unsigned int srcprefs, |
| @@ -187,40 +264,6 @@ nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range, · 43 unmodified lines | |||
| 187 | } | 264 | } |
| 188 | EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6); | 265 | EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6); |
| 189 | 266 | ||
| 190 | struct masq_dev_work { | ||
| 191 | struct work_struct work; | ||
| 192 | struct net *net; | ||
| 193 | struct in6_addr addr; | ||
| 194 | int ifindex; | ||
| 195 | }; | ||
| 196 | |||
| 197 | static int inet6_cmp(struct nf_conn *ct, void *work) | ||
| 198 | { | ||
| 199 | struct masq_dev_work *w = (struct masq_dev_work *)work; | ||
| 200 | struct nf_conntrack_tuple *tuple; | ||
| 201 | |||
| 202 | if (!device_cmp(ct, (void *)(long)w->ifindex)) | ||
| 203 | return 0; | ||
| 204 | |||
| 205 | tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; | ||
| 206 | |||
| 207 | return ipv6_addr_equal(&w->addr, &tuple->dst.u3.in6); | ||
| 208 | } | ||
| 209 | |||
| 210 | static void iterate_cleanup_work(struct work_struct *work) | ||
| 211 | { | ||
| 212 | struct masq_dev_work *w; | ||
| 213 | |||
| 214 | w = container_of(work, struct masq_dev_work, work); | ||
| 215 | |||
| 216 | nf_ct_iterate_cleanup_net(w->net, inet6_cmp, (void *)w, 0, 0); | ||
| 217 | |||
| 218 | put_net(w->net); | ||
| 219 | kfree(w); | ||
| 220 | atomic_dec(&v6_worker_count); | ||
| 221 | module_put(THIS_MODULE); | ||
| 222 | } | ||
| 223 | |||
| 224 | /* atomic notifier; can't call nf_ct_iterate_cleanup_net (it can sleep). | 267 | /* atomic notifier; can't call nf_ct_iterate_cleanup_net (it can sleep). |
| 225 | * | 268 | * |
| 226 | * Defer it to the system workqueue. | 269 | * Defer it to the system workqueue. |
| @@ -233,36 +276,19 @@ static int masq_inet6_event(struct notifier_block *this, · 6 unmodified lines | |||
| 233 | { | 276 | { |
| 234 | struct inet6_ifaddr *ifa = ptr; | 277 | struct inet6_ifaddr *ifa = ptr; |
| 235 | const struct net_device *dev; | 278 | const struct net_device *dev; |
| 236 | struct masq_dev_work *w; | 279 | union nf_inet_addr addr; |
| 237 | struct net *net; | ||
| 238 | 280 | ||
| 239 | if (event != NETDEV_DOWN || atomic_read(&v6_worker_count) >= 16) | 281 | if (event != NETDEV_DOWN) |
| 240 | return NOTIFY_DONE; | 282 | return NOTIFY_DONE; |
| 241 | 283 | ||
| 242 | dev = ifa->idev->dev; | 284 | dev = ifa->idev->dev; |
| 243 | net = maybe_get_net(dev_net(dev)); | ||
| 244 | if (!net) | ||
| 245 | return NOTIFY_DONE; | ||
| 246 | 285 | ||
| 247 | if (!try_module_get(THIS_MODULE)) | 286 | memset(&addr, 0, sizeof(addr)); |
| 248 | goto err_module; | ||
| 249 | 287 | ||
| 250 | w = kmalloc(sizeof(*w), GFP_ATOMIC); | 288 | addr.in6 = ifa->addr; |
| 251 | if (w) { | ||
| 252 | atomic_inc(&v6_worker_count); | ||
| 253 | |||
| 254 | INIT_WORK(&w->work, iterate_cleanup_work); | ||
| 255 | w->ifindex = dev->ifindex; | ||
| 256 | w->net = net; | ||
| 257 | w->addr = ifa->addr; | ||
| 258 | schedule_work(&w->work); | ||
| 259 | 289 | ||
| 260 | return NOTIFY_DONE; | 290 | nf_nat_masq_schedule(dev_net(dev), &addr, dev->ifindex, inet_cmp, |
| 261 | } | 291 | GFP_ATOMIC); |
| 262 | |||
| 263 | module_put(THIS_MODULE); | ||
| 264 | err_module: | ||
| 265 | put_net(net); | ||
| 266 | return NOTIFY_DONE; | 292 | return NOTIFY_DONE; |
| 267 | } | 293 | } |
| 268 | 294 | ||
| @@ -4336,7 +4336,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, · 4335 unmodified lines | |||
| 4336 | if (ops->privsize != NULL) | 4336 | if (ops->privsize != NULL) |
| 4337 | size = ops->privsize(nla, &desc); | 4337 | size = ops->privsize(nla, &desc); |
| 4338 | alloc_size = sizeof(*set) + size + udlen; | 4338 | alloc_size = sizeof(*set) + size + udlen; |
| 4339 | if (alloc_size < size) | 4339 | if (alloc_size < size || alloc_size > INT_MAX) |
| 4340 | return -ENOMEM; | 4340 | return -ENOMEM; |
| 4341 | set = kvzalloc(alloc_size, GFP_KERNEL); | 4341 | set = kvzalloc(alloc_size, GFP_KERNEL); |
| 4342 | if (!set) | 4342 | if (!set) |
| @@ -9599,7 +9599,6 @@ static void __nft_release_table(struct net *net, struct nft_table *table) · 5256 unmodified lines | |||
| 9599 | table->use--; | 9599 | table->use--; |
| 9600 | nf_tables_chain_destroy(&ctx); | 9600 | nf_tables_chain_destroy(&ctx); |
| 9601 | } | 9601 | } |
| 9602 | list_del(&table->list); | ||
| 9603 | nf_tables_table_destroy(&ctx); | 9602 | nf_tables_table_destroy(&ctx); |
| 9604 | } | 9603 | } |
| 9605 | 9604 | ||
| @@ -9612,6 +9611,8 @@ static void __nft_release_tables(struct net *net) · 6 unmodified lines | |||
| 9612 | if (nft_table_has_owner(table)) | 9611 | if (nft_table_has_owner(table)) |
| 9613 | continue; | 9612 | continue; |
| 9614 | 9613 | ||
| 9614 | list_del(&table->list); | ||
| 9615 | |||
| 9615 | __nft_release_table(net, table); | 9616 | __nft_release_table(net, table); |
| 9616 | } | 9617 | } |
| 9617 | } | 9618 | } |
| @@ -9619,31 +9620,38 @@ static void __nft_release_tables(struct net *net) · 1 unmodified line | |||
| 9619 | static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event, | 9620 | static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event, |
| 9620 | void *ptr) | 9621 | void *ptr) |
| 9621 | { | 9622 | { |
| 9623 | struct nft_table *table, *to_delete[8]; | ||
| 9622 | struct nftables_pernet *nft_net; | 9624 | struct nftables_pernet *nft_net; |
| 9623 | struct netlink_notify *n = ptr; | 9625 | struct netlink_notify *n = ptr; |
| 9624 | struct nft_table *table, *nt; | ||
| 9625 | struct net *net = n->net; | 9626 | struct net *net = n->net; |
| 9626 | bool release = false; | 9627 | unsigned int deleted; |
| 9628 | bool restart = false; | ||
| 9627 | 9629 | ||
| 9628 | if (event != NETLINK_URELEASE || n->protocol != NETLINK_NETFILTER) | 9630 | if (event != NETLINK_URELEASE || n->protocol != NETLINK_NETFILTER) |
| 9629 | return NOTIFY_DONE; | 9631 | return NOTIFY_DONE; |
| 9630 | 9632 | ||
| 9631 | nft_net = nft_pernet(net); | 9633 | nft_net = nft_pernet(net); |
| 9634 | deleted = 0; | ||
| 9632 | mutex_lock(&nft_net->commit_mutex); | 9635 | mutex_lock(&nft_net->commit_mutex); |
| 9636 | again: | ||
| 9633 | list_for_each_entry(table, &nft_net->tables, list) { | 9637 | list_for_each_entry(table, &nft_net->tables, list) { |
| 9634 | if (nft_table_has_owner(table) && | 9638 | if (nft_table_has_owner(table) && |
| 9635 | n->portid == table->nlpid) { | 9639 | n->portid == table->nlpid) { |
| 9636 | __nft_release_hook(net, table); | 9640 | __nft_release_hook(net, table); |
| 9637 | release = true; | 9641 | list_del_rcu(&table->list); |
| 9642 | to_delete[deleted++] = table; | ||
| 9643 | if (deleted >= ARRAY_SIZE(to_delete)) | ||
| 9644 | break; | ||
| 9638 | } | 9645 | } |
| 9639 | } | 9646 | } |
| 9640 | if (release) { | 9647 | if (deleted) { |
| 9648 | restart = deleted >= ARRAY_SIZE(to_delete); | ||
| 9641 | synchronize_rcu(); | 9649 | synchronize_rcu(); |
| 9642 | list_for_each_entry_safe(table, nt, &nft_net->tables, list) { | 9650 | while (deleted) |
| 9643 | if (nft_table_has_owner(table) && | 9651 | __nft_release_table(net, to_delete[--deleted]); |
| 9644 | n->portid == table->nlpid) | 9652 | |
| 9645 | __nft_release_table(net, table); | 9653 | if (restart) |
| 9646 | } | 9654 | goto again; |
| 9647 | } | 9655 | } |
| 9648 | mutex_unlock(&nft_net->commit_mutex); | 9656 | mutex_unlock(&nft_net->commit_mutex); |
| 9649 | 9657 | ||
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | #include <linux/netfilter_bridge/ebtables.h> | 19 | #include <linux/netfilter_bridge/ebtables.h> |
| 20 | #include <linux/netfilter_arp/arp_tables.h> | 20 | #include <linux/netfilter_arp/arp_tables.h> |
| 21 | #include <net/netfilter/nf_tables.h> | 21 | #include <net/netfilter/nf_tables.h> |
| 22 | #include <net/netfilter/nf_log.h> | ||
| 22 | 23 | ||
| 23 | /* Used for matches where *info is larger than X byte */ | 24 | /* Used for matches where *info is larger than X byte */ |
| 24 | #define NFT_MATCH_LARGE_THRESH 192 | 25 | #define NFT_MATCH_LARGE_THRESH 192 |
| @@ -257,8 +258,22 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr, · 232 unmodified lines | |||
| 257 | nft_compat_wait_for_destructors(); | 258 | nft_compat_wait_for_destructors(); |
| 258 | 259 | ||
| 259 | ret = xt_check_target(&par, size, proto, inv); | 260 | ret = xt_check_target(&par, size, proto, inv); |
| 260 | if (ret < 0) | 261 | if (ret < 0) { |
| 262 | if (ret == -ENOENT) { | ||
| 263 | const char *modname = NULL; | ||
| 264 | |||
| 265 | if (strcmp(target->name, "LOG") == 0) | ||
| 266 | modname = "nf_log_syslog"; | ||
| 267 | else if (strcmp(target->name, "NFLOG") == 0) | ||
| 268 | modname = "nfnetlink_log"; | ||
| 269 | |||
| 270 | if (modname && | ||
| 271 | nft_request_module(ctx->net, "%s", modname) == -EAGAIN) | ||
| 272 | return -EAGAIN; | ||
| 273 | } | ||
| 274 | |||
| 261 | return ret; | 275 | return ret; |
| 276 | } | ||
| 262 | 277 | ||
| 263 | /* The standard target cannot be used */ | 278 | /* The standard target cannot be used */ |
| 264 | if (!target->target) | 279 | if (!target->target) |
| @@ -44,6 +44,7 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par) · 43 unmodified lines | |||
| 44 | static int log_tg_check(const struct xt_tgchk_param *par) | 44 | static int log_tg_check(const struct xt_tgchk_param *par) |
| 45 | { | 45 | { |
| 46 | const struct xt_log_info *loginfo = par->targinfo; | 46 | const struct xt_log_info *loginfo = par->targinfo; |
| 47 | int ret; | ||
| 47 | 48 | ||
| 48 | if (par->family != NFPROTO_IPV4 && par->family != NFPROTO_IPV6) | 49 | if (par->family != NFPROTO_IPV4 && par->family != NFPROTO_IPV6) |
| 49 | return -EINVAL; | 50 | return -EINVAL; |
| @@ -58,7 +59,14 @@ static int log_tg_check(const struct xt_tgchk_param *par) · 8 unmodified lines | |||
| 58 | return -EINVAL; | 59 | return -EINVAL; |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | return nf_logger_find_get(par->family, NF_LOG_TYPE_LOG); | 62 | ret = nf_logger_find_get(par->family, NF_LOG_TYPE_LOG); |
| 63 | if (ret != 0 && !par->nft_compat) { | ||
| 64 | request_module("%s", "nf_log_syslog"); | ||
| 65 | |||
| 66 | ret = nf_logger_find_get(par->family, NF_LOG_TYPE_LOG); | ||
| 67 | } | ||
| 68 | |||
| 69 | return ret; | ||
| 62 | } | 70 | } |
| 63 | 71 | ||
| 64 | static void log_tg_destroy(const struct xt_tgdtor_param *par) | 72 | static void log_tg_destroy(const struct xt_tgdtor_param *par) |
| @@ -42,13 +42,21 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par) · 41 unmodified lines | |||
| 42 | static int nflog_tg_check(const struct xt_tgchk_param *par) | 42 | static int nflog_tg_check(const struct xt_tgchk_param *par) |
| 43 | { | 43 | { |
| 44 | const struct xt_nflog_info *info = par->targinfo; | 44 | const struct xt_nflog_info *info = par->targinfo; |
| 45 | int ret; | ||
| 45 | 46 | ||
| 46 | if (info->flags & ~XT_NFLOG_MASK) | 47 | if (info->flags & ~XT_NFLOG_MASK) |
| 47 | return -EINVAL; | 48 | return -EINVAL; |
| 48 | if (info->prefix[sizeof(info->prefix) - 1] != '\0') | 49 | if (info->prefix[sizeof(info->prefix) - 1] != '\0') |
| 49 | return -EINVAL; | 50 | return -EINVAL; |
| 50 | 51 | ||
| 51 | return nf_logger_find_get(par->family, NF_LOG_TYPE_ULOG); | 52 | ret = nf_logger_find_get(par->family, NF_LOG_TYPE_ULOG); |
| 53 | if (ret != 0 && !par->nft_compat) { | ||
| 54 | request_module("%s", "nfnetlink_log"); | ||
| 55 | |||
| 56 | ret = nf_logger_find_get(par->family, NF_LOG_TYPE_ULOG); | ||
| 57 | } | ||
| 58 | |||
| 59 | return ret; | ||
| 52 | } | 60 | } |
| 53 | 61 | ||
| 54 | static void nflog_tg_destroy(const struct xt_tgdtor_param *par) | 62 | static void nflog_tg_destroy(const struct xt_tgdtor_param *par) |
| @@ -2188,18 +2188,24 @@ static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg, · 2187 unmodified lines | |||
| 2188 | 2188 | ||
| 2189 | arg->count = arg->skip; | 2189 | arg->count = arg->skip; |
| 2190 | 2190 | ||
| 2191 | rcu_read_lock(); | ||
| 2191 | idr_for_each_entry_continue_ul(&head->handle_idr, f, tmp, id) { | 2192 | idr_for_each_entry_continue_ul(&head->handle_idr, f, tmp, id) { |
| 2192 | /* don't return filters that are being deleted */ | 2193 | /* don't return filters that are being deleted */ |
| 2193 | if (!refcount_inc_not_zero(&f->refcnt)) | 2194 | if (!refcount_inc_not_zero(&f->refcnt)) |
| 2194 | continue; | 2195 | continue; |
| 2196 | rcu_read_unlock(); | ||
| 2197 | |||
| 2195 | if (arg->fn(tp, f, arg) < 0) { | 2198 | if (arg->fn(tp, f, arg) < 0) { |
| 2196 | __fl_put(f); | 2199 | __fl_put(f); |
| 2197 | arg->stop = 1; | 2200 | arg->stop = 1; |
| 2201 | rcu_read_lock(); | ||
| 2198 | break; | 2202 | break; |
| 2199 | } | 2203 | } |
| 2200 | __fl_put(f); | 2204 | __fl_put(f); |
| 2201 | arg->count++; | 2205 | arg->count++; |
| 2206 | rcu_read_lock(); | ||
| 2202 | } | 2207 | } |
| 2208 | rcu_read_unlock(); | ||
| 2203 | arg->cookie = id; | 2209 | arg->cookie = id; |
| 2204 | } | 2210 | } |
| 2205 | 2211 | ||
| @@ -513,6 +513,12 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt, · 512 unmodified lines | |||
| 513 | return stab; | 513 | return stab; |
| 514 | } | 514 | } |
| 515 | 515 | ||
| 516 | if (s->size_log > STAB_SIZE_LOG_MAX || | ||
| 517 | s->cell_log > STAB_SIZE_LOG_MAX) { | ||
| 518 | NL_SET_ERR_MSG(extack, "Invalid logarithmic size of size table"); | ||
| 519 | return ERR_PTR(-EINVAL); | ||
| 520 | } | ||
| 521 | |||
| 516 | stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL); | 522 | stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL); |
| 517 | if (!stab) | 523 | if (!stab) |
| 518 | return ERR_PTR(-ENOMEM); | 524 | return ERR_PTR(-ENOMEM); |
| @@ -702,7 +702,7 @@ static int sctp_rcv_ootb(struct sk_buff *skb) · 701 unmodified lines | |||
| 702 | ch = skb_header_pointer(skb, offset, sizeof(*ch), &_ch); | 702 | ch = skb_header_pointer(skb, offset, sizeof(*ch), &_ch); |
| 703 | 703 | ||
| 704 | /* Break out if chunk length is less then minimal. */ | 704 | /* Break out if chunk length is less then minimal. */ |
| 705 | if (ntohs(ch->length) < sizeof(_ch)) | 705 | if (!ch || ntohs(ch->length) < sizeof(_ch)) |
| 706 | break; | 706 | break; |
| 707 | 707 | ||
| 708 | ch_end = offset + SCTP_PAD4(ntohs(ch->length)); | 708 | ch_end = offset + SCTP_PAD4(ntohs(ch->length)); |
| @@ -608,20 +608,42 @@ static void unix_release_sock(struct sock *sk, int embrion) · 607 unmodified lines | |||
| 608 | 608 | ||
| 609 | static void init_peercred(struct sock *sk) | 609 | static void init_peercred(struct sock *sk) |
| 610 | { | 610 | { |
| 611 | put_pid(sk->sk_peer_pid); | 611 | const struct cred *old_cred; |
| 612 | if (sk->sk_peer_cred) | 612 | struct pid *old_pid; |
| 613 | put_cred(sk->sk_peer_cred); | 613 | |
| 614 | spin_lock(&sk->sk_peer_lock); | ||
| 615 | old_pid = sk->sk_peer_pid; | ||
| 616 | old_cred = sk->sk_peer_cred; | ||
| 614 | sk->sk_peer_pid = get_pid(task_tgid(current)); | 617 | sk->sk_peer_pid = get_pid(task_tgid(current)); |
| 615 | sk->sk_peer_cred = get_current_cred(); | 618 | sk->sk_peer_cred = get_current_cred(); |
| 619 | spin_unlock(&sk->sk_peer_lock); | ||
| 620 | |||
| 621 | put_pid(old_pid); | ||
| 622 | put_cred(old_cred); | ||
| 616 | } | 623 | } |
| 617 | 624 | ||
| 618 | static void copy_peercred(struct sock *sk, struct sock *peersk) | 625 | static void copy_peercred(struct sock *sk, struct sock *peersk) |
| 619 | { | 626 | { |
| 620 | put_pid(sk->sk_peer_pid); | 627 | const struct cred *old_cred; |
| 621 | if (sk->sk_peer_cred) | 628 | struct pid *old_pid; |
| 622 | put_cred(sk->sk_peer_cred); | 629 | |
| 630 | if (sk < peersk) { | ||
| 631 | spin_lock(&sk->sk_peer_lock); | ||
| 632 | spin_lock_nested(&peersk->sk_peer_lock, SINGLE_DEPTH_NESTING); | ||
| 633 | } else { | ||
| 634 | spin_lock(&peersk->sk_peer_lock); | ||
| 635 | spin_lock_nested(&sk->sk_peer_lock, SINGLE_DEPTH_NESTING); | ||
| 636 | } | ||
| 637 | old_pid = sk->sk_peer_pid; | ||
| 638 | old_cred = sk->sk_peer_cred; | ||
| 623 | sk->sk_peer_pid = get_pid(peersk->sk_peer_pid); | 639 | sk->sk_peer_pid = get_pid(peersk->sk_peer_pid); |
| 624 | sk->sk_peer_cred = get_cred(peersk->sk_peer_cred); | 640 | sk->sk_peer_cred = get_cred(peersk->sk_peer_cred); |
| 641 | |||
| 642 | spin_unlock(&sk->sk_peer_lock); | ||
| 643 | spin_unlock(&peersk->sk_peer_lock); | ||
| 644 | |||
| 645 | put_pid(old_pid); | ||
| 646 | put_cred(old_cred); | ||
| 625 | } | 647 | } |
| 626 | 648 | ||
| 627 | static int unix_listen(struct socket *sock, int backlog) | 649 | static int unix_listen(struct socket *sock, int backlog) |
| @@ -828,20 +850,25 @@ struct proto unix_stream_proto = { · 200 unmodified lines | |||
| 828 | 850 | ||
| 829 | static struct sock *unix_create1(struct net *net, struct socket *sock, int kern, int type) | 851 | static struct sock *unix_create1(struct net *net, struct socket *sock, int kern, int type) |
| 830 | { | 852 | { |
| 831 | struct sock *sk = NULL; | ||
| 832 | struct unix_sock *u; | 853 | struct unix_sock *u; |
| 854 | struct sock *sk; | ||
| 855 | int err; | ||
| 833 | 856 | ||
| 834 | atomic_long_inc(&unix_nr_socks); | 857 | atomic_long_inc(&unix_nr_socks); |
| 835 | if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files()) | 858 | if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files()) { |
| 836 | goto out; | 859 | err = -ENFILE; |
| 860 | goto err; | ||
| 861 | } | ||
| 837 | 862 | ||
| 838 | if (type == SOCK_STREAM) | 863 | if (type == SOCK_STREAM) |
| 839 | sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_stream_proto, kern); | 864 | sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_stream_proto, kern); |
| 840 | else /*dgram and seqpacket */ | 865 | else /*dgram and seqpacket */ |
| 841 | sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_dgram_proto, kern); | 866 | sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_dgram_proto, kern); |
| 842 | 867 | ||
| 843 | if (!sk) | 868 | if (!sk) { |
| 844 | goto out; | 869 | err = -ENOMEM; |
| 870 | goto err; | ||
| 871 | } | ||
| 845 | 872 | ||
| 846 | sock_init_data(sock, sk); | 873 | sock_init_data(sock, sk); |
| 847 | 874 | ||
| @@ -861,20 +888,23 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern, · 13 unmodified lines | |||
| 861 | init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay); | 888 | init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay); |
| 862 | memset(&u->scm_stat, 0, sizeof(struct scm_stat)); | 889 | memset(&u->scm_stat, 0, sizeof(struct scm_stat)); |
| 863 | unix_insert_socket(unix_sockets_unbound(sk), sk); | 890 | unix_insert_socket(unix_sockets_unbound(sk), sk); |
| 864 | out: | 891 | |
| 865 | if (sk == NULL) | 892 | local_bh_disable(); |
| 866 | atomic_long_dec(&unix_nr_socks); | 893 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
| 867 | else { | 894 | local_bh_enable(); |
| 868 | local_bh_disable(); | 895 | |
| 869 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | ||
| 870 | local_bh_enable(); | ||
| 871 | } | ||
| 872 | return sk; | 896 | return sk; |
| 897 | |||
| 898 | err: | ||
| 899 | atomic_long_dec(&unix_nr_socks); | ||
| 900 | return ERR_PTR(err); | ||
| 873 | } | 901 | } |
| 874 | 902 | ||
| 875 | static int unix_create(struct net *net, struct socket *sock, int protocol, | 903 | static int unix_create(struct net *net, struct socket *sock, int protocol, |
| 876 | int kern) | 904 | int kern) |
| 877 | { | 905 | { |
| 906 | struct sock *sk; | ||
| 907 | |||
| 878 | if (protocol && protocol != PF_UNIX) | 908 | if (protocol && protocol != PF_UNIX) |
| 879 | return -EPROTONOSUPPORT; | 909 | return -EPROTONOSUPPORT; |
| 880 | 910 | ||
| @@ -901,7 +931,11 @@ static int unix_create(struct net *net, struct socket *sock, int protocol, · 20 unmodified lines | |||
| 901 | return -ESOCKTNOSUPPORT; | 931 | return -ESOCKTNOSUPPORT; |
| 902 | } | 932 | } |
| 903 | 933 | ||
| 904 | return unix_create1(net, sock, kern, sock->type) ? 0 : -ENOMEM; | 934 | sk = unix_create1(net, sock, kern, sock->type); |
| 935 | if (IS_ERR(sk)) | ||
| 936 | return PTR_ERR(sk); | ||
| 937 | |||
| 938 | return 0; | ||
| 905 | } | 939 | } |
| 906 | 940 | ||
| 907 | static int unix_release(struct socket *sock) | 941 | static int unix_release(struct socket *sock) |
| @@ -1314,12 +1348,15 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, · 406 unmodified lines | |||
| 1314 | we will have to recheck all again in any case. | 1348 | we will have to recheck all again in any case. |
| 1315 | */ | 1349 | */ |
| 1316 | 1350 | ||
| 1317 | err = -ENOMEM; | ||
| 1318 | |||
| 1319 | /* create new sock for complete connection */ | 1351 | /* create new sock for complete connection */ |
| 1320 | newsk = unix_create1(sock_net(sk), NULL, 0, sock->type); | 1352 | newsk = unix_create1(sock_net(sk), NULL, 0, sock->type); |
| 1321 | if (newsk == NULL) | 1353 | if (IS_ERR(newsk)) { |
| 1354 | err = PTR_ERR(newsk); | ||
| 1355 | newsk = NULL; | ||
| 1322 | goto out; | 1356 | goto out; |
| 1357 | } | ||
| 1358 | |||
| 1359 | err = -ENOMEM; | ||
| 1323 | 1360 | ||
| 1324 | /* Allocate skb for sending to listening sock */ | 1361 | /* Allocate skb for sending to listening sock */ |
| 1325 | skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL); | 1362 | skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL); |
| @@ -873,12 +873,21 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long · 872 unmodified lines | |||
| 873 | return -EINVAL; | 873 | return -EINVAL; |
| 874 | } | 874 | } |
| 875 | } | 875 | } |
| 876 | case SNDRV_RAWMIDI_IOCTL_USER_PVERSION: | ||
| 877 | if (get_user(rfile->user_pversion, (unsigned int __user *)arg)) | ||
| 878 | return -EFAULT; | ||
| 879 | return 0; | ||
| 880 | |||
| 876 | case SNDRV_RAWMIDI_IOCTL_PARAMS: | 881 | case SNDRV_RAWMIDI_IOCTL_PARAMS: |
| 877 | { | 882 | { |
| 878 | struct snd_rawmidi_params params; | 883 | struct snd_rawmidi_params params; |
| 879 | 884 | ||
| 880 | if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params))) | 885 | if (copy_from_user(¶ms, argp, sizeof(struct snd_rawmidi_params))) |
| 881 | return -EFAULT; | 886 | return -EFAULT; |
| 887 | if (rfile->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 2)) { | ||
| 888 | params.mode = 0; | ||
| 889 | memset(params.reserved, 0, sizeof(params.reserved)); | ||
| 890 | } | ||
| 882 | switch (params.stream) { | 891 | switch (params.stream) { |
| 883 | case SNDRV_RAWMIDI_STREAM_OUTPUT: | 892 | case SNDRV_RAWMIDI_STREAM_OUTPUT: |
| 884 | if (rfile->output == NULL) | 893 | if (rfile->output == NULL) |
| @@ -143,7 +143,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) · 142 unmodified lines | |||
| 143 | if (pointer_update) | 143 | if (pointer_update) |
| 144 | pcsp_pointer_update(chip); | 144 | pcsp_pointer_update(chip); |
| 145 | 145 | ||
| 146 | hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns)); | 146 | hrtimer_forward_now(handle, ns_to_ktime(ns)); |
| 147 | 147 | ||
| 148 | return HRTIMER_RESTART; | 148 | return HRTIMER_RESTART; |
| 149 | } | 149 | } |
| @@ -276,10 +276,11 @@ static void __maybe_unused copy_message(u64 *frames, __be32 *buffer, · 275 unmodified lines | |||
| 276 | 276 | ||
| 277 | /* This is just for v2/v3 protocol. */ | 277 | /* This is just for v2/v3 protocol. */ |
| 278 | for (i = 0; i < data_blocks; ++i) { | 278 | for (i = 0; i < data_blocks; ++i) { |
| 279 | *frames = (be32_to_cpu(buffer[1]) << 16) | | 279 | *frames = be32_to_cpu(buffer[1]); |
| 280 | (be32_to_cpu(buffer[2]) >> 16); | 280 | *frames <<= 16; |
| 281 | *frames |= be32_to_cpu(buffer[2]) >> 16; | ||
| 282 | ++frames; | ||
| 281 | buffer += data_block_quadlets; | 283 | buffer += data_block_quadlets; |
| 282 | frames++; | ||
| 283 | } | 284 | } |
| 284 | } | 285 | } |
| 285 | 286 | ||
| @@ -184,13 +184,16 @@ static int detect_quirks(struct snd_oxfw *oxfw, const struct ieee1394_device_id · 183 unmodified lines | |||
| 184 | model = val; | 184 | model = val; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | /* | 187 | if (vendor == VENDOR_LOUD) { |
| 188 | * Mackie Onyx Satellite with base station has a quirk to report a wrong | 188 | // Mackie Onyx Satellite with base station has a quirk to report a wrong |
| 189 | * value in 'dbs' field of CIP header against its format information. | 189 | // value in 'dbs' field of CIP header against its format information. |
| 190 | */ | ||
| 191 | if (vendor == VENDOR_LOUD && model == MODEL_SATELLITE) | ||
| 192 | oxfw->quirks |= SND_OXFW_QUIRK_WRONG_DBS; | 190 | oxfw->quirks |= SND_OXFW_QUIRK_WRONG_DBS; |
| 193 | 191 | ||
| 192 | // OXFW971-based models may transfer events by blocking method. | ||
| 193 | if (!(oxfw->quirks & SND_OXFW_QUIRK_JUMBO_PAYLOAD)) | ||
| 194 | oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION; | ||
| 195 | } | ||
| 196 | |||
| 194 | return 0; | 197 | return 0; |
| 195 | } | 198 | } |
| 196 | 199 | ||
| @@ -883,10 +883,11 @@ static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev) · 882 unmodified lines | |||
| 883 | return azx_get_pos_posbuf(chip, azx_dev); | 883 | return azx_get_pos_posbuf(chip, azx_dev); |
| 884 | } | 884 | } |
| 885 | 885 | ||
| 886 | static void azx_shutdown_chip(struct azx *chip) | 886 | static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset) |
| 887 | { | 887 | { |
| 888 | azx_stop_chip(chip); | 888 | azx_stop_chip(chip); |
| 889 | azx_enter_link_reset(chip); | 889 | if (!skip_link_reset) |
| 890 | azx_enter_link_reset(chip); | ||
| 890 | azx_clear_irq_pending(chip); | 891 | azx_clear_irq_pending(chip); |
| 891 | display_power(chip, false); | 892 | display_power(chip, false); |
| 892 | } | 893 | } |
| @@ -895,6 +896,11 @@ static void azx_shutdown_chip(struct azx *chip) · 2 unmodified lines | |||
| 895 | static DEFINE_MUTEX(card_list_lock); | 896 | static DEFINE_MUTEX(card_list_lock); |
| 896 | static LIST_HEAD(card_list); | 897 | static LIST_HEAD(card_list); |
| 897 | 898 | ||
| 899 | static void azx_shutdown_chip(struct azx *chip) | ||
| 900 | { | ||
| 901 | __azx_shutdown_chip(chip, false); | ||
| 902 | } | ||
| 903 | |||
| 898 | static void azx_add_card_list(struct azx *chip) | 904 | static void azx_add_card_list(struct azx *chip) |
| 899 | { | 905 | { |
| 900 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); | 906 | struct hda_intel *hda = container_of(chip, struct hda_intel, chip); |
| @@ -2357,7 +2363,7 @@ static void azx_shutdown(struct pci_dev *pci) · 1456 unmodified lines | |||
| 2357 | return; | 2363 | return; |
| 2358 | chip = card->private_data; | 2364 | chip = card->private_data; |
| 2359 | if (chip && chip->running) | 2365 | if (chip && chip->running) |
| 2360 | azx_shutdown_chip(chip); | 2366 | __azx_shutdown_chip(chip, true); |
| 2361 | } | 2367 | } |
| 2362 | 2368 | ||
| 2363 | /* PCI IDs */ | 2369 | /* PCI IDs */ |
| @@ -1207,6 +1207,9 @@ void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int ac · 1206 unmodified lines | |||
| 1207 | snd_hda_jack_add_kctl(codec, DOLPHIN_LO_PIN_NID, "Line Out", true, | 1207 | snd_hda_jack_add_kctl(codec, DOLPHIN_LO_PIN_NID, "Line Out", true, |
| 1208 | SND_JACK_HEADPHONE, NULL); | 1208 | SND_JACK_HEADPHONE, NULL); |
| 1209 | 1209 | ||
| 1210 | snd_hda_jack_add_kctl(codec, DOLPHIN_AMIC_PIN_NID, "Microphone", true, | ||
| 1211 | SND_JACK_MICROPHONE, NULL); | ||
| 1212 | |||
| 1210 | cs8409_fix_caps(codec, DOLPHIN_HP_PIN_NID); | 1213 | cs8409_fix_caps(codec, DOLPHIN_HP_PIN_NID); |
| 1211 | cs8409_fix_caps(codec, DOLPHIN_LO_PIN_NID); | 1214 | cs8409_fix_caps(codec, DOLPHIN_LO_PIN_NID); |
| 1212 | cs8409_fix_caps(codec, DOLPHIN_AMIC_PIN_NID); | 1215 | cs8409_fix_caps(codec, DOLPHIN_AMIC_PIN_NID); |
| @@ -6429,6 +6429,20 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec, · 6428 unmodified lines | |||
| 6429 | hda_fixup_thinkpad_acpi(codec, fix, action); | 6429 | hda_fixup_thinkpad_acpi(codec, fix, action); |
| 6430 | } | 6430 | } |
| 6431 | 6431 | ||
| 6432 | /* Fixup for Lenovo Legion 15IMHg05 speaker output on headset removal. */ | ||
| 6433 | static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec, | ||
| 6434 | const struct hda_fixup *fix, | ||
| 6435 | int action) | ||
| 6436 | { | ||
| 6437 | struct alc_spec *spec = codec->spec; | ||
| 6438 | |||
| 6439 | switch (action) { | ||
| 6440 | case HDA_FIXUP_ACT_PRE_PROBE: | ||
| 6441 | spec->gen.suppress_auto_mute = 1; | ||
| 6442 | break; | ||
| 6443 | } | ||
| 6444 | } | ||
| 6445 | |||
| 6432 | /* for alc295_fixup_hp_top_speakers */ | 6446 | /* for alc295_fixup_hp_top_speakers */ |
| 6433 | #include "hp_x360_helper.c" | 6447 | #include "hp_x360_helper.c" |
| 6434 | 6448 | ||
| @@ -6646,6 +6660,10 @@ enum { · 211 unmodified lines | |||
| 6646 | ALC623_FIXUP_LENOVO_THINKSTATION_P340, | 6660 | ALC623_FIXUP_LENOVO_THINKSTATION_P340, |
| 6647 | ALC255_FIXUP_ACER_HEADPHONE_AND_MIC, | 6661 | ALC255_FIXUP_ACER_HEADPHONE_AND_MIC, |
| 6648 | ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST, | 6662 | ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST, |
| 6663 | ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS, | ||
| 6664 | ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE, | ||
| 6665 | ALC287_FIXUP_YOGA7_14ITL_SPEAKERS, | ||
| 6666 | ALC287_FIXUP_13S_GEN2_SPEAKERS | ||
| 6649 | }; | 6667 | }; |
| 6650 | 6668 | ||
| 6651 | static const struct hda_fixup alc269_fixups[] = { | 6669 | static const struct hda_fixup alc269_fixups[] = { |
| @@ -8236,6 +8254,113 @@ static const struct hda_fixup alc269_fixups[] = { · 1584 unmodified lines | |||
| 8236 | .chained = true, | 8254 | .chained = true, |
| 8237 | .chain_id = ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF, | 8255 | .chain_id = ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF, |
| 8238 | }, | 8256 | }, |
| 8257 | [ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS] = { | ||
| 8258 | .type = HDA_FIXUP_VERBS, | ||
| 8259 | //.v.verbs = legion_15imhg05_coefs, | ||
| 8260 | .v.verbs = (const struct hda_verb[]) { | ||
| 8261 | // set left speaker Legion 7i. | ||
| 8262 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, | ||
| 8263 | { 0x20, AC_VERB_SET_PROC_COEF, 0x41 }, | ||
| 8264 | |||
| 8265 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, | ||
| 8266 | { 0x20, AC_VERB_SET_PROC_COEF, 0xc }, | ||
| 8267 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8268 | { 0x20, AC_VERB_SET_PROC_COEF, 0x1a }, | ||
| 8269 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8270 | |||
| 8271 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, | ||
| 8272 | { 0x20, AC_VERB_SET_PROC_COEF, 0x2 }, | ||
| 8273 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8274 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8275 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8276 | |||
| 8277 | // set right speaker Legion 7i. | ||
| 8278 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, | ||
| 8279 | { 0x20, AC_VERB_SET_PROC_COEF, 0x42 }, | ||
| 8280 | |||
| 8281 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, | ||
| 8282 | { 0x20, AC_VERB_SET_PROC_COEF, 0xc }, | ||
| 8283 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8284 | { 0x20, AC_VERB_SET_PROC_COEF, 0x2a }, | ||
| 8285 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8286 | |||
| 8287 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, | ||
| 8288 | { 0x20, AC_VERB_SET_PROC_COEF, 0x2 }, | ||
| 8289 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8290 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8291 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8292 | {} | ||
| 8293 | }, | ||
| 8294 | .chained = true, | ||
| 8295 | .chain_id = ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE, | ||
| 8296 | }, | ||
| 8297 | [ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE] = { | ||
| 8298 | .type = HDA_FIXUP_FUNC, | ||
| 8299 | .v.func = alc287_fixup_legion_15imhg05_speakers, | ||
| 8300 | .chained = true, | ||
| 8301 | .chain_id = ALC269_FIXUP_HEADSET_MODE, | ||
| 8302 | }, | ||
| 8303 | [ALC287_FIXUP_YOGA7_14ITL_SPEAKERS] = { | ||
| 8304 | .type = HDA_FIXUP_VERBS, | ||
| 8305 | .v.verbs = (const struct hda_verb[]) { | ||
| 8306 | // set left speaker Yoga 7i. | ||
| 8307 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, | ||
| 8308 | { 0x20, AC_VERB_SET_PROC_COEF, 0x41 }, | ||
| 8309 | |||
| 8310 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, | ||
| 8311 | { 0x20, AC_VERB_SET_PROC_COEF, 0xc }, | ||
| 8312 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8313 | { 0x20, AC_VERB_SET_PROC_COEF, 0x1a }, | ||
| 8314 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8315 | |||
| 8316 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, | ||
| 8317 | { 0x20, AC_VERB_SET_PROC_COEF, 0x2 }, | ||
| 8318 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8319 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8320 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8321 | |||
| 8322 | // set right speaker Yoga 7i. | ||
| 8323 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, | ||
| 8324 | { 0x20, AC_VERB_SET_PROC_COEF, 0x46 }, | ||
| 8325 | |||
| 8326 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, | ||
| 8327 | { 0x20, AC_VERB_SET_PROC_COEF, 0xc }, | ||
| 8328 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8329 | { 0x20, AC_VERB_SET_PROC_COEF, 0x2a }, | ||
| 8330 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8331 | |||
| 8332 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, | ||
| 8333 | { 0x20, AC_VERB_SET_PROC_COEF, 0x2 }, | ||
| 8334 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8335 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8336 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8337 | {} | ||
| 8338 | }, | ||
| 8339 | .chained = true, | ||
| 8340 | .chain_id = ALC269_FIXUP_HEADSET_MODE, | ||
| 8341 | }, | ||
| 8342 | [ALC287_FIXUP_13S_GEN2_SPEAKERS] = { | ||
| 8343 | .type = HDA_FIXUP_VERBS, | ||
| 8344 | .v.verbs = (const struct hda_verb[]) { | ||
| 8345 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, | ||
| 8346 | { 0x20, AC_VERB_SET_PROC_COEF, 0x41 }, | ||
| 8347 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8348 | { 0x20, AC_VERB_SET_PROC_COEF, 0x2 }, | ||
| 8349 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8350 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8351 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8352 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x24 }, | ||
| 8353 | { 0x20, AC_VERB_SET_PROC_COEF, 0x42 }, | ||
| 8354 | { 0x20, AC_VERB_SET_COEF_INDEX, 0x26 }, | ||
| 8355 | { 0x20, AC_VERB_SET_PROC_COEF, 0x2 }, | ||
| 8356 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8357 | { 0x20, AC_VERB_SET_PROC_COEF, 0x0 }, | ||
| 8358 | { 0x20, AC_VERB_SET_PROC_COEF, 0xb020 }, | ||
| 8359 | {} | ||
| 8360 | }, | ||
| 8361 | .chained = true, | ||
| 8362 | .chain_id = ALC269_FIXUP_HEADSET_MODE, | ||
| 8363 | }, | ||
| 8239 | }; | 8364 | }; |
| 8240 | 8365 | ||
| 8241 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 8366 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
| @@ -8630,6 +8755,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 388 unmodified lines | |||
| 8630 | SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME), | 8755 | SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME), |
| 8631 | SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF), | 8756 | SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF), |
| 8632 | SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP), | 8757 | SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP), |
| 8758 | SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS), | ||
| 8759 | SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), | ||
| 8760 | SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), | ||
| 8761 | SND_PCI_QUIRK(0x17aa, 0x3819, "Lenovo 13s Gen2 ITL", ALC287_FIXUP_13S_GEN2_SPEAKERS), | ||
| 8633 | SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), | 8762 | SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), |
| 8634 | SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), | 8763 | SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), |
| 8635 | SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), | 8764 | SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), |
| @@ -52,7 +52,7 @@ · 51 unmodified lines | |||
| 52 | #define PCXHR_DSP 2 | 52 | #define PCXHR_DSP 2 |
| 53 | 53 | ||
| 54 | #if (PCXHR_DSP_OFFSET_MAX > PCXHR_PLX_OFFSET_MIN) | 54 | #if (PCXHR_DSP_OFFSET_MAX > PCXHR_PLX_OFFSET_MIN) |
| 55 | #undef PCXHR_REG_TO_PORT(x) | 55 | #error PCXHR_REG_TO_PORT(x) |
| 56 | #else | 56 | #else |
| 57 | #define PCXHR_REG_TO_PORT(x) ((x)>PCXHR_DSP_OFFSET_MAX ? PCXHR_PLX : PCXHR_DSP) | 57 | #define PCXHR_REG_TO_PORT(x) ((x)>PCXHR_DSP_OFFSET_MAX ? PCXHR_PLX : PCXHR_DSP) |
| 58 | #endif | 58 | #endif |
| @@ -1073,6 +1073,16 @@ static int fsl_esai_probe(struct platform_device *pdev) · 1072 unmodified lines | |||
| 1073 | if (ret < 0) | 1073 | if (ret < 0) |
| 1074 | goto err_pm_get_sync; | 1074 | goto err_pm_get_sync; |
| 1075 | 1075 | ||
| 1076 | /* | ||
| 1077 | * Register platform component before registering cpu dai for there | ||
| 1078 | * is not defer probe for platform component in snd_soc_add_pcm_runtime(). | ||
| 1079 | */ | ||
| 1080 | ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE); | ||
| 1081 | if (ret) { | ||
| 1082 | dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); | ||
| 1083 | goto err_pm_get_sync; | ||
| 1084 | } | ||
| 1085 | |||
| 1076 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component, | 1086 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component, |
| 1077 | &fsl_esai_dai, 1); | 1087 | &fsl_esai_dai, 1); |
| 1078 | if (ret) { | 1088 | if (ret) { |
| @@ -1082,12 +1092,6 @@ static int fsl_esai_probe(struct platform_device *pdev) · 3 unmodified lines | |||
| 1082 | 1092 | ||
| 1083 | INIT_WORK(&esai_priv->work, fsl_esai_hw_reset); | 1093 | INIT_WORK(&esai_priv->work, fsl_esai_hw_reset); |
| 1084 | 1094 | ||
| 1085 | ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE); | ||
| 1086 | if (ret) { | ||
| 1087 | dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); | ||
| 1088 | goto err_pm_get_sync; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | return ret; | 1095 | return ret; |
| 1092 | 1096 | ||
| 1093 | err_pm_get_sync: | 1097 | err_pm_get_sync: |
| @@ -737,18 +737,23 @@ static int fsl_micfil_probe(struct platform_device *pdev) · 736 unmodified lines | |||
| 737 | pm_runtime_enable(&pdev->dev); | 737 | pm_runtime_enable(&pdev->dev); |
| 738 | regcache_cache_only(micfil->regmap, true); | 738 | regcache_cache_only(micfil->regmap, true); |
| 739 | 739 | ||
| 740 | /* | ||
| 741 | * Register platform component before registering cpu dai for there | ||
| 742 | * is not defer probe for platform component in snd_soc_add_pcm_runtime(). | ||
| 743 | */ | ||
| 744 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
| 745 | if (ret) { | ||
| 746 | dev_err(&pdev->dev, "failed to pcm register\n"); | ||
| 747 | return ret; | ||
| 748 | } | ||
| 749 | |||
| 740 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_micfil_component, | 750 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_micfil_component, |
| 741 | &fsl_micfil_dai, 1); | 751 | &fsl_micfil_dai, 1); |
| 742 | if (ret) { | 752 | if (ret) { |
| 743 | dev_err(&pdev->dev, "failed to register component %s\n", | 753 | dev_err(&pdev->dev, "failed to register component %s\n", |
| 744 | fsl_micfil_component.name); | 754 | fsl_micfil_component.name); |
| 745 | return ret; | ||
| 746 | } | 755 | } |
| 747 | 756 | ||
| 748 | ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); | ||
| 749 | if (ret) | ||
| 750 | dev_err(&pdev->dev, "failed to pcm register\n"); | ||
| 751 | |||
| 752 | return ret; | 757 | return ret; |
| 753 | } | 758 | } |
| 754 | 759 | ||
| @@ -1152,11 +1152,10 @@ static int fsl_sai_probe(struct platform_device *pdev) · 1151 unmodified lines | |||
| 1152 | if (ret < 0) | 1152 | if (ret < 0) |
| 1153 | goto err_pm_get_sync; | 1153 | goto err_pm_get_sync; |
| 1154 | 1154 | ||
| 1155 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, | 1155 | /* |
| 1156 | &sai->cpu_dai_drv, 1); | 1156 | * Register platform component before registering cpu dai for there |
| 1157 | if (ret) | 1157 | * is not defer probe for platform component in snd_soc_add_pcm_runtime(). |
| 1158 | goto err_pm_get_sync; | 1158 | */ |
| 1159 | |||
| 1160 | if (sai->soc_data->use_imx_pcm) { | 1159 | if (sai->soc_data->use_imx_pcm) { |
| 1161 | ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE); | 1160 | ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE); |
| 1162 | if (ret) | 1161 | if (ret) |
| @@ -1167,6 +1166,11 @@ static int fsl_sai_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 1167 | goto err_pm_get_sync; | 1166 | goto err_pm_get_sync; |
| 1168 | } | 1167 | } |
| 1169 | 1168 | ||
| 1169 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, | ||
| 1170 | &sai->cpu_dai_drv, 1); | ||
| 1171 | if (ret) | ||
| 1172 | goto err_pm_get_sync; | ||
| 1173 | |||
| 1170 | return ret; | 1174 | return ret; |
| 1171 | 1175 | ||
| 1172 | err_pm_get_sync: | 1176 | err_pm_get_sync: |
| @@ -1434,16 +1434,20 @@ static int fsl_spdif_probe(struct platform_device *pdev) · 1433 unmodified lines | |||
| 1434 | pm_runtime_enable(&pdev->dev); | 1434 | pm_runtime_enable(&pdev->dev); |
| 1435 | regcache_cache_only(spdif_priv->regmap, true); | 1435 | regcache_cache_only(spdif_priv->regmap, true); |
| 1436 | 1436 | ||
| 1437 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_spdif_component, | 1437 | /* |
| 1438 | &spdif_priv->cpu_dai_drv, 1); | 1438 | * Register platform component before registering cpu dai for there |
| 1439 | * is not defer probe for platform component in snd_soc_add_pcm_runtime(). | ||
| 1440 | */ | ||
| 1441 | ret = imx_pcm_dma_init(pdev, IMX_SPDIF_DMABUF_SIZE); | ||
| 1439 | if (ret) { | 1442 | if (ret) { |
| 1440 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); | 1443 | dev_err_probe(&pdev->dev, ret, "imx_pcm_dma_init failed\n"); |
| 1441 | goto err_pm_disable; | 1444 | goto err_pm_disable; |
| 1442 | } | 1445 | } |
| 1443 | 1446 | ||
| 1444 | ret = imx_pcm_dma_init(pdev, IMX_SPDIF_DMABUF_SIZE); | 1447 | ret = devm_snd_soc_register_component(&pdev->dev, &fsl_spdif_component, |
| 1448 | &spdif_priv->cpu_dai_drv, 1); | ||
| 1445 | if (ret) { | 1449 | if (ret) { |
| 1446 | dev_err_probe(&pdev->dev, ret, "imx_pcm_dma_init failed\n"); | 1450 | dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); |
| 1447 | goto err_pm_disable; | 1451 | goto err_pm_disable; |
| 1448 | } | 1452 | } |
| 1449 | 1453 | ||
| @@ -1215,18 +1215,23 @@ static int fsl_xcvr_probe(struct platform_device *pdev) · 1214 unmodified lines | |||
| 1215 | pm_runtime_enable(dev); | 1215 | pm_runtime_enable(dev); |
| 1216 | regcache_cache_only(xcvr->regmap, true); | 1216 | regcache_cache_only(xcvr->regmap, true); |
| 1217 | 1217 | ||
| 1218 | /* | ||
| 1219 | * Register platform component before registering cpu dai for there | ||
| 1220 | * is not defer probe for platform component in snd_soc_add_pcm_runtime(). | ||
| 1221 | */ | ||
| 1222 | ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0); | ||
| 1223 | if (ret) { | ||
| 1224 | dev_err(dev, "failed to pcm register\n"); | ||
| 1225 | return ret; | ||
| 1226 | } | ||
| 1227 | |||
| 1218 | ret = devm_snd_soc_register_component(dev, &fsl_xcvr_comp, | 1228 | ret = devm_snd_soc_register_component(dev, &fsl_xcvr_comp, |
| 1219 | &fsl_xcvr_dai, 1); | 1229 | &fsl_xcvr_dai, 1); |
| 1220 | if (ret) { | 1230 | if (ret) { |
| 1221 | dev_err(dev, "failed to register component %s\n", | 1231 | dev_err(dev, "failed to register component %s\n", |
| 1222 | fsl_xcvr_comp.name); | 1232 | fsl_xcvr_comp.name); |
| 1223 | return ret; | ||
| 1224 | } | 1233 | } |
| 1225 | 1234 | ||
| 1226 | ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0); | ||
| 1227 | if (ret) | ||
| 1228 | dev_err(dev, "failed to pcm register\n"); | ||
| 1229 | |||
| 1230 | return ret; | 1235 | return ret; |
| 1231 | } | 1236 | } |
| 1232 | 1237 | ||
| @@ -929,6 +929,11 @@ static int create_sdw_dailink(struct snd_soc_card *card, · 928 unmodified lines | |||
| 929 | cpus + *cpu_id, cpu_dai_num, | 929 | cpus + *cpu_id, cpu_dai_num, |
| 930 | codecs, codec_num, | 930 | codecs, codec_num, |
| 931 | NULL, &sdw_ops); | 931 | NULL, &sdw_ops); |
| 932 | /* | ||
| 933 | * SoundWire DAILINKs use 'stream' functions and Bank Switch operations | ||
| 934 | * based on wait_for_completion(), tag them as 'nonatomic'. | ||
| 935 | */ | ||
| 936 | dai_links[*be_index].nonatomic = true; | ||
| 932 | 937 | ||
| 933 | ret = set_codec_init_func(card, link, dai_links + (*be_index)++, | 938 | ret = set_codec_init_func(card, link, dai_links + (*be_index)++, |
| 934 | playback, group_id); | 939 | playback, group_id); |
| @@ -1,6 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | config SND_SOC_MEDIATEK | 2 | config SND_SOC_MEDIATEK |
| 3 | tristate | 3 | tristate |
| 4 | select REGMAP_MMIO | ||
| 4 | 5 | ||
| 5 | config SND_SOC_MT2701 | 6 | config SND_SOC_MT2701 |
| 6 | tristate "ASoC support for Mediatek MT2701 chip" | 7 | tristate "ASoC support for Mediatek MT2701 chip" |
| @@ -188,7 +189,9 @@ config SND_SOC_MT8192_MT6359_RT1015_RT5682 · 181 unmodified lines | |||
| 188 | config SND_SOC_MT8195 | 189 | config SND_SOC_MT8195 |
| 189 | tristate "ASoC support for Mediatek MT8195 chip" | 190 | tristate "ASoC support for Mediatek MT8195 chip" |
| 190 | depends on ARCH_MEDIATEK || COMPILE_TEST | 191 | depends on ARCH_MEDIATEK || COMPILE_TEST |
| 192 | depends on COMMON_CLK | ||
| 191 | select SND_SOC_MEDIATEK | 193 | select SND_SOC_MEDIATEK |
| 194 | select MFD_SYSCON if SND_SOC_MT6359 | ||
| 192 | help | 195 | help |
| 193 | This adds ASoC platform driver support for Mediatek MT8195 chip | 196 | This adds ASoC platform driver support for Mediatek MT8195 chip |
| 194 | that can be used with other codecs. | 197 | that can be used with other codecs. |
| @@ -334,9 +334,11 @@ int mtk_afe_suspend(struct snd_soc_component *component) · 333 unmodified lines | |||
| 334 | devm_kcalloc(dev, afe->reg_back_up_list_num, | 334 | devm_kcalloc(dev, afe->reg_back_up_list_num, |
| 335 | sizeof(unsigned int), GFP_KERNEL); | 335 | sizeof(unsigned int), GFP_KERNEL); |
| 336 | 336 | ||
| 337 | for (i = 0; i < afe->reg_back_up_list_num; i++) | 337 | if (afe->reg_back_up) { |
| 338 | regmap_read(regmap, afe->reg_back_up_list[i], | 338 | for (i = 0; i < afe->reg_back_up_list_num; i++) |
| 339 | &afe->reg_back_up[i]); | 339 | regmap_read(regmap, afe->reg_back_up_list[i], |
| 340 | &afe->reg_back_up[i]); | ||
| 341 | } | ||
| 340 | 342 | ||
| 341 | afe->suspended = true; | 343 | afe->suspended = true; |
| 342 | afe->runtime_suspend(dev); | 344 | afe->runtime_suspend(dev); |
| @@ -356,12 +358,13 @@ int mtk_afe_resume(struct snd_soc_component *component) · 13 unmodified lines | |||
| 356 | 358 | ||
| 357 | afe->runtime_resume(dev); | 359 | afe->runtime_resume(dev); |
| 358 | 360 | ||
| 359 | if (!afe->reg_back_up) | 361 | if (!afe->reg_back_up) { |
| 360 | dev_dbg(dev, "%s no reg_backup\n", __func__); | 362 | dev_dbg(dev, "%s no reg_backup\n", __func__); |
| 361 | 363 | } else { | |
| 362 | for (i = 0; i < afe->reg_back_up_list_num; i++) | 364 | for (i = 0; i < afe->reg_back_up_list_num; i++) |
| 363 | mtk_regmap_write(regmap, afe->reg_back_up_list[i], | 365 | mtk_regmap_write(regmap, afe->reg_back_up_list[i], |
| 364 | afe->reg_back_up[i]); | 366 | afe->reg_back_up[i]); |
| 367 | } | ||
| 365 | 368 | ||
| 366 | afe->suspended = false; | 369 | afe->suspended = false; |
| 367 | return 0; | 370 | return 0; |
| @@ -424,8 +424,8 @@ static int mt8195_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) · 423 unmodified lines | |||
| 424 | return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); | 424 | return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | static int mt8195_hdmitx_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, | 427 | static int mt8195_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, |
| 428 | struct snd_pcm_hw_params *params) | 428 | struct snd_pcm_hw_params *params) |
| 429 | 429 | ||
| 430 | { | 430 | { |
| 431 | /* fix BE i2s format to 32bit, clean param mask first */ | 431 | /* fix BE i2s format to 32bit, clean param mask first */ |
| @@ -902,7 +902,7 @@ static struct snd_soc_dai_link mt8195_mt6359_rt1019_rt5682_dai_links[] = { · 470 unmodified lines | |||
| 902 | .no_pcm = 1, | 902 | .no_pcm = 1, |
| 903 | .dpcm_playback = 1, | 903 | .dpcm_playback = 1, |
| 904 | .ops = &mt8195_dptx_ops, | 904 | .ops = &mt8195_dptx_ops, |
| 905 | .be_hw_params_fixup = mt8195_hdmitx_dptx_hw_params_fixup, | 905 | .be_hw_params_fixup = mt8195_dptx_hw_params_fixup, |
| 906 | SND_SOC_DAILINK_REG(DPTX_BE), | 906 | SND_SOC_DAILINK_REG(DPTX_BE), |
| 907 | }, | 907 | }, |
| 908 | [DAI_LINK_ETDM1_IN_BE] = { | 908 | [DAI_LINK_ETDM1_IN_BE] = { |
| @@ -953,7 +953,6 @@ static struct snd_soc_dai_link mt8195_mt6359_rt1019_rt5682_dai_links[] = { · 44 unmodified lines | |||
| 953 | SND_SOC_DAIFMT_NB_NF | | 953 | SND_SOC_DAIFMT_NB_NF | |
| 954 | SND_SOC_DAIFMT_CBS_CFS, | 954 | SND_SOC_DAIFMT_CBS_CFS, |
| 955 | .dpcm_playback = 1, | 955 | .dpcm_playback = 1, |
| 956 | .be_hw_params_fixup = mt8195_hdmitx_dptx_hw_params_fixup, | ||
| 957 | SND_SOC_DAILINK_REG(ETDM3_OUT_BE), | 956 | SND_SOC_DAILINK_REG(ETDM3_OUT_BE), |
| 958 | }, | 957 | }, |
| 959 | [DAI_LINK_PCM1_BE] = { | 958 | [DAI_LINK_PCM1_BE] = { |
| @@ -371,7 +371,6 @@ int snd_sof_device_remove(struct device *dev) · 370 unmodified lines | |||
| 371 | dev_warn(dev, "error: %d failed to prepare DSP for device removal", | 371 | dev_warn(dev, "error: %d failed to prepare DSP for device removal", |
| 372 | ret); | 372 | ret); |
| 373 | 373 | ||
| 374 | snd_sof_fw_unload(sdev); | ||
| 375 | snd_sof_ipc_free(sdev); | 374 | snd_sof_ipc_free(sdev); |
| 376 | snd_sof_free_debug(sdev); | 375 | snd_sof_free_debug(sdev); |
| 377 | snd_sof_free_trace(sdev); | 376 | snd_sof_free_trace(sdev); |
| @@ -394,8 +393,7 @@ int snd_sof_device_remove(struct device *dev) · 16 unmodified lines | |||
| 394 | snd_sof_remove(sdev); | 393 | snd_sof_remove(sdev); |
| 395 | 394 | ||
| 396 | /* release firmware */ | 395 | /* release firmware */ |
| 397 | release_firmware(pdata->fw); | 396 | snd_sof_fw_unload(sdev); |
| 398 | pdata->fw = NULL; | ||
| 399 | 397 | ||
| 400 | return 0; | 398 | return 0; |
| 401 | } | 399 | } |
| @@ -365,7 +365,14 @@ static int imx8_remove(struct snd_sof_dev *sdev) · 364 unmodified lines | |||
| 365 | /* on i.MX8 there is 1 to 1 match between type and BAR idx */ | 365 | /* on i.MX8 there is 1 to 1 match between type and BAR idx */ |
| 366 | static int imx8_get_bar_index(struct snd_sof_dev *sdev, u32 type) | 366 | static int imx8_get_bar_index(struct snd_sof_dev *sdev, u32 type) |
| 367 | { | 367 | { |
| 368 | return type; | 368 | /* Only IRAM and SRAM bars are valid */ |
| 369 | switch (type) { | ||
| 370 | case SOF_FW_BLK_TYPE_IRAM: | ||
| 371 | case SOF_FW_BLK_TYPE_SRAM: | ||
| 372 | return type; | ||
| 373 | default: | ||
| 374 | return -EINVAL; | ||
| 375 | } | ||
| 369 | } | 376 | } |
| 370 | 377 | ||
| 371 | static void imx8_ipc_msg_data(struct snd_sof_dev *sdev, | 378 | static void imx8_ipc_msg_data(struct snd_sof_dev *sdev, |
| @@ -228,7 +228,14 @@ static int imx8m_remove(struct snd_sof_dev *sdev) · 227 unmodified lines | |||
| 228 | /* on i.MX8 there is 1 to 1 match between type and BAR idx */ | 228 | /* on i.MX8 there is 1 to 1 match between type and BAR idx */ |
| 229 | static int imx8m_get_bar_index(struct snd_sof_dev *sdev, u32 type) | 229 | static int imx8m_get_bar_index(struct snd_sof_dev *sdev, u32 type) |
| 230 | { | 230 | { |
| 231 | return type; | 231 | /* Only IRAM and SRAM bars are valid */ |
| 232 | switch (type) { | ||
| 233 | case SOF_FW_BLK_TYPE_IRAM: | ||
| 234 | case SOF_FW_BLK_TYPE_SRAM: | ||
| 235 | return type; | ||
| 236 | default: | ||
| 237 | return -EINVAL; | ||
| 238 | } | ||
| 232 | } | 239 | } |
| 233 | 240 | ||
| 234 | static void imx8m_ipc_msg_data(struct snd_sof_dev *sdev, | 241 | static void imx8m_ipc_msg_data(struct snd_sof_dev *sdev, |
| @@ -729,10 +729,10 @@ int snd_sof_load_firmware_raw(struct snd_sof_dev *sdev) · 728 unmodified lines | |||
| 729 | ret = request_firmware(&plat_data->fw, fw_filename, sdev->dev); | 729 | ret = request_firmware(&plat_data->fw, fw_filename, sdev->dev); |
| 730 | 730 | ||
| 731 | if (ret < 0) { | 731 | if (ret < 0) { |
| 732 | dev_err(sdev->dev, "error: request firmware %s failed err: %d\n", | ||
| 733 | fw_filename, ret); | ||
| 734 | dev_err(sdev->dev, | 732 | dev_err(sdev->dev, |
| 735 | "you may need to download the firmware from https://github.com/thesofproject/sof-bin/\n"); | 733 | "error: sof firmware file is missing, you might need to\n"); |
| 734 | dev_err(sdev->dev, | ||
| 735 | " download it from https://github.com/thesofproject/sof-bin/\n"); | ||
| 736 | goto err; | 736 | goto err; |
| 737 | } else { | 737 | } else { |
| 738 | dev_dbg(sdev->dev, "request_firmware %s successful\n", | 738 | dev_dbg(sdev->dev, "request_firmware %s successful\n", |
| @@ -880,5 +880,7 @@ EXPORT_SYMBOL(snd_sof_run_firmware); · 141 unmodified lines | |||
| 880 | void snd_sof_fw_unload(struct snd_sof_dev *sdev) | 880 | void snd_sof_fw_unload(struct snd_sof_dev *sdev) |
| 881 | { | 881 | { |
| 882 | /* TODO: support module unloading at runtime */ | 882 | /* TODO: support module unloading at runtime */ |
| 883 | release_firmware(sdev->pdata->fw); | ||
| 884 | sdev->pdata->fw = NULL; | ||
| 883 | } | 885 | } |
| 884 | EXPORT_SYMBOL(snd_sof_fw_unload); | 886 | EXPORT_SYMBOL(snd_sof_fw_unload); |
| @@ -530,7 +530,6 @@ void snd_sof_trace_notify_for_error(struct snd_sof_dev *sdev) · 529 unmodified lines | |||
| 530 | return; | 530 | return; |
| 531 | 531 | ||
| 532 | if (sdev->dtrace_is_enabled) { | 532 | if (sdev->dtrace_is_enabled) { |
| 533 | dev_err(sdev->dev, "error: waking up any trace sleepers\n"); | ||
| 534 | sdev->dtrace_error = true; | 533 | sdev->dtrace_error = true; |
| 535 | wake_up(&sdev->trace_sleep); | 534 | wake_up(&sdev->trace_sleep); |
| 536 | } | 535 | } |
| @@ -122,9 +122,9 @@ static void xtensa_stack(struct snd_sof_dev *sdev, void *oops, u32 *stack, · 121 unmodified lines | |||
| 122 | * 0x0049fbb0: 8000f2d0 0049fc00 6f6c6c61 00632e63 | 122 | * 0x0049fbb0: 8000f2d0 0049fc00 6f6c6c61 00632e63 |
| 123 | */ | 123 | */ |
| 124 | for (i = 0; i < stack_words; i += 4) { | 124 | for (i = 0; i < stack_words; i += 4) { |
| 125 | hex_dump_to_buffer(stack + i * 4, 16, 16, 4, | 125 | hex_dump_to_buffer(stack + i, 16, 16, 4, |
| 126 | buf, sizeof(buf), false); | 126 | buf, sizeof(buf), false); |
| 127 | dev_err(sdev->dev, "0x%08x: %s\n", stack_ptr + i, buf); | 127 | dev_err(sdev->dev, "0x%08x: %s\n", stack_ptr + i * 4, buf); |
| 128 | } | 128 | } |
| 129 | } | 129 | } |
| 130 | 130 | ||
| @@ -1054,7 +1054,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) · 1053 unmodified lines | |||
| 1054 | return 0; | 1054 | return 0; |
| 1055 | } | 1055 | } |
| 1056 | 1056 | ||
| 1057 | static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) | 1057 | static int usb_audio_resume(struct usb_interface *intf) |
| 1058 | { | 1058 | { |
| 1059 | struct snd_usb_audio *chip = usb_get_intfdata(intf); | 1059 | struct snd_usb_audio *chip = usb_get_intfdata(intf); |
| 1060 | struct snd_usb_stream *as; | 1060 | struct snd_usb_stream *as; |
| @@ -1080,7 +1080,7 @@ static int __usb_audio_resume(struct usb_interface *intf, bool reset_resume) · 19 unmodified lines | |||
| 1080 | * we just notify and restart the mixers | 1080 | * we just notify and restart the mixers |
| 1081 | */ | 1081 | */ |
| 1082 | list_for_each_entry(mixer, &chip->mixer_list, list) { | 1082 | list_for_each_entry(mixer, &chip->mixer_list, list) { |
| 1083 | err = snd_usb_mixer_resume(mixer, reset_resume); | 1083 | err = snd_usb_mixer_resume(mixer); |
| 1084 | if (err < 0) | 1084 | if (err < 0) |
| 1085 | goto err_out; | 1085 | goto err_out; |
| 1086 | } | 1086 | } |
| @@ -1100,20 +1100,10 @@ err_out: · 13 unmodified lines | |||
| 1100 | atomic_dec(&chip->active); /* allow autopm after this point */ | 1100 | atomic_dec(&chip->active); /* allow autopm after this point */ |
| 1101 | return err; | 1101 | return err; |
| 1102 | } | 1102 | } |
| 1103 | |||
| 1104 | static int usb_audio_resume(struct usb_interface *intf) | ||
| 1105 | { | ||
| 1106 | return __usb_audio_resume(intf, false); | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | static int usb_audio_reset_resume(struct usb_interface *intf) | ||
| 1110 | { | ||
| 1111 | return __usb_audio_resume(intf, true); | ||
| 1112 | } | ||
| 1113 | #else | 1103 | #else |
| 1114 | #define usb_audio_suspend NULL | 1104 | #define usb_audio_suspend NULL |
| 1115 | #define usb_audio_resume NULL | 1105 | #define usb_audio_resume NULL |
| 1116 | #define usb_audio_reset_resume NULL | 1106 | #define usb_audio_resume NULL |
| 1117 | #endif /* CONFIG_PM */ | 1107 | #endif /* CONFIG_PM */ |
| 1118 | 1108 | ||
| 1119 | static const struct usb_device_id usb_audio_ids [] = { | 1109 | static const struct usb_device_id usb_audio_ids [] = { |
| @@ -1135,7 +1125,7 @@ static struct usb_driver usb_audio_driver = { · 15 unmodified lines | |||
| 1135 | .disconnect = usb_audio_disconnect, | 1125 | .disconnect = usb_audio_disconnect, |
| 1136 | .suspend = usb_audio_suspend, | 1126 | .suspend = usb_audio_suspend, |
| 1137 | .resume = usb_audio_resume, | 1127 | .resume = usb_audio_resume, |
| 1138 | .reset_resume = usb_audio_reset_resume, | 1128 | .reset_resume = usb_audio_resume, |
| 1139 | .id_table = usb_audio_ids, | 1129 | .id_table = usb_audio_ids, |
| 1140 | .supports_autosuspend = 1, | 1130 | .supports_autosuspend = 1, |
| 1141 | }; | 1131 | }; |
| @@ -3653,33 +3653,16 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list) · 3652 unmodified lines | |||
| 3653 | return 0; | 3653 | return 0; |
| 3654 | } | 3654 | } |
| 3655 | 3655 | ||
| 3656 | static int default_mixer_reset_resume(struct usb_mixer_elem_list *list) | 3656 | int snd_usb_mixer_resume(struct usb_mixer_interface *mixer) |
| 3657 | { | ||
| 3658 | int err; | ||
| 3659 | |||
| 3660 | if (list->resume) { | ||
| 3661 | err = list->resume(list); | ||
| 3662 | if (err < 0) | ||
| 3663 | return err; | ||
| 3664 | } | ||
| 3665 | return restore_mixer_value(list); | ||
| 3666 | } | ||
| 3667 | |||
| 3668 | int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume) | ||
| 3669 | { | 3657 | { |
| 3670 | struct usb_mixer_elem_list *list; | 3658 | struct usb_mixer_elem_list *list; |
| 3671 | usb_mixer_elem_resume_func_t f; | ||
| 3672 | int id, err; | 3659 | int id, err; |
| 3673 | 3660 | ||
| 3674 | /* restore cached mixer values */ | 3661 | /* restore cached mixer values */ |
| 3675 | for (id = 0; id < MAX_ID_ELEMS; id++) { | 3662 | for (id = 0; id < MAX_ID_ELEMS; id++) { |
| 3676 | for_each_mixer_elem(list, mixer, id) { | 3663 | for_each_mixer_elem(list, mixer, id) { |
| 3677 | if (reset_resume) | 3664 | if (list->resume) { |
| 3678 | f = list->reset_resume; | 3665 | err = list->resume(list); |
| 3679 | else | ||
| 3680 | f = list->resume; | ||
| 3681 | if (f) { | ||
| 3682 | err = f(list); | ||
| 3683 | if (err < 0) | 3666 | if (err < 0) |
| 3684 | return err; | 3667 | return err; |
| 3685 | } | 3668 | } |
| @@ -3700,7 +3683,6 @@ void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list, · 14 unmodified lines | |||
| 3700 | list->id = unitid; | 3683 | list->id = unitid; |
| 3701 | list->dump = snd_usb_mixer_dump_cval; | 3684 | list->dump = snd_usb_mixer_dump_cval; |
| 3702 | #ifdef CONFIG_PM | 3685 | #ifdef CONFIG_PM |
| 3703 | list->resume = NULL; | 3686 | list->resume = restore_mixer_value; |
| 3704 | list->reset_resume = default_mixer_reset_resume; | ||
| 3705 | #endif | 3687 | #endif |
| 3706 | } | 3688 | } |
| @@ -70,7 +70,6 @@ struct usb_mixer_elem_list { · 69 unmodified lines | |||
| 70 | bool is_std_info; | 70 | bool is_std_info; |
| 71 | usb_mixer_elem_dump_func_t dump; | 71 | usb_mixer_elem_dump_func_t dump; |
| 72 | usb_mixer_elem_resume_func_t resume; | 72 | usb_mixer_elem_resume_func_t resume; |
| 73 | usb_mixer_elem_resume_func_t reset_resume; | ||
| 74 | }; | 73 | }; |
| 75 | 74 | ||
| 76 | /* iterate over mixer element list of the given unit id */ | 75 | /* iterate over mixer element list of the given unit id */ |
| @@ -121,7 +120,7 @@ int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, · 44 unmodified lines | |||
| 121 | 120 | ||
| 122 | #ifdef CONFIG_PM | 121 | #ifdef CONFIG_PM |
| 123 | int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer); | 122 | int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer); |
| 124 | int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume); | 123 | int snd_usb_mixer_resume(struct usb_mixer_interface *mixer); |
| 125 | #endif | 124 | #endif |
| 126 | 125 | ||
| 127 | int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, | 126 | int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, |
| @@ -151,7 +151,7 @@ static int add_single_ctl_with_resume(struct usb_mixer_interface *mixer, · 150 unmodified lines | |||
| 151 | *listp = list; | 151 | *listp = list; |
| 152 | list->mixer = mixer; | 152 | list->mixer = mixer; |
| 153 | list->id = id; | 153 | list->id = id; |
| 154 | list->reset_resume = resume; | 154 | list->resume = resume; |
| 155 | kctl = snd_ctl_new1(knew, list); | 155 | kctl = snd_ctl_new1(knew, list); |
| 156 | if (!kctl) { | 156 | if (!kctl) { |
| 157 | kfree(list); | 157 | kfree(list); |
| @@ -1649,11 +1649,17 @@ static bool btf_is_non_static(const struct btf_type *t) · 1648 unmodified lines | |||
| 1649 | static int find_glob_sym_btf(struct src_obj *obj, Elf64_Sym *sym, const char *sym_name, | 1649 | static int find_glob_sym_btf(struct src_obj *obj, Elf64_Sym *sym, const char *sym_name, |
| 1650 | int *out_btf_sec_id, int *out_btf_id) | 1650 | int *out_btf_sec_id, int *out_btf_id) |
| 1651 | { | 1651 | { |
| 1652 | int i, j, n = btf__get_nr_types(obj->btf), m, btf_id = 0; | 1652 | int i, j, n, m, btf_id = 0; |
| 1653 | const struct btf_type *t; | 1653 | const struct btf_type *t; |
| 1654 | const struct btf_var_secinfo *vi; | 1654 | const struct btf_var_secinfo *vi; |
| 1655 | const char *name; | 1655 | const char *name; |
| 1656 | 1656 | ||
| 1657 | if (!obj->btf) { | ||
| 1658 | pr_warn("failed to find BTF info for object '%s'\n", obj->filename); | ||
| 1659 | return -EINVAL; | ||
| 1660 | } | ||
| 1661 | |||
| 1662 | n = btf__get_nr_types(obj->btf); | ||
| 1657 | for (i = 1; i <= n; i++) { | 1663 | for (i = 1; i <= n; i++) { |
| 1658 | t = btf__type_by_id(obj->btf, i); | 1664 | t = btf__type_by_id(obj->btf, i); |
| 1659 | 1665 | ||
| @@ -58,6 +58,24 @@ void __weak arch_handle_alternative(unsigned short feature, struct special_alt * · 57 unmodified lines | |||
| 58 | { | 58 | { |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | static bool reloc2sec_off(struct reloc *reloc, struct section **sec, unsigned long *off) | ||
| 62 | { | ||
| 63 | switch (reloc->sym->type) { | ||
| 64 | case STT_FUNC: | ||
| 65 | *sec = reloc->sym->sec; | ||
| 66 | *off = reloc->sym->offset + reloc->addend; | ||
| 67 | return true; | ||
| 68 | |||
| 69 | case STT_SECTION: | ||
| 70 | *sec = reloc->sym->sec; | ||
| 71 | *off = reloc->addend; | ||
| 72 | return true; | ||
| 73 | |||
| 74 | default: | ||
| 75 | return false; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 61 | static int get_alt_entry(struct elf *elf, struct special_entry *entry, | 79 | static int get_alt_entry(struct elf *elf, struct special_entry *entry, |
| 62 | struct section *sec, int idx, | 80 | struct section *sec, int idx, |
| 63 | struct special_alt *alt) | 81 | struct special_alt *alt) |
| @@ -91,15 +109,14 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry, · 27 unmodified lines | |||
| 91 | WARN_FUNC("can't find orig reloc", sec, offset + entry->orig); | 109 | WARN_FUNC("can't find orig reloc", sec, offset + entry->orig); |
| 92 | return -1; | 110 | return -1; |
| 93 | } | 111 | } |
| 94 | if (orig_reloc->sym->type != STT_SECTION) { | 112 | if (!reloc2sec_off(orig_reloc, &alt->orig_sec, &alt->orig_off)) { |
| 95 | WARN_FUNC("don't know how to handle non-section reloc symbol %s", | 113 | WARN_FUNC("don't know how to handle reloc symbol type %d: %s", |
| 96 | sec, offset + entry->orig, orig_reloc->sym->name); | 114 | sec, offset + entry->orig, |
| 115 | orig_reloc->sym->type, | ||
| 116 | orig_reloc->sym->name); | ||
| 97 | return -1; | 117 | return -1; |
| 98 | } | 118 | } |
| 99 | 119 | ||
| 100 | alt->orig_sec = orig_reloc->sym->sec; | ||
| 101 | alt->orig_off = orig_reloc->addend; | ||
| 102 | |||
| 103 | if (!entry->group || alt->new_len) { | 120 | if (!entry->group || alt->new_len) { |
| 104 | new_reloc = find_reloc_by_dest(elf, sec, offset + entry->new); | 121 | new_reloc = find_reloc_by_dest(elf, sec, offset + entry->new); |
| 105 | if (!new_reloc) { | 122 | if (!new_reloc) { |
| @@ -116,8 +133,13 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry, · 10 unmodified lines | |||
| 116 | if (arch_is_retpoline(new_reloc->sym)) | 133 | if (arch_is_retpoline(new_reloc->sym)) |
| 117 | return 1; | 134 | return 1; |
| 118 | 135 | ||
| 119 | alt->new_sec = new_reloc->sym->sec; | 136 | if (!reloc2sec_off(new_reloc, &alt->new_sec, &alt->new_off)) { |
| 120 | alt->new_off = (unsigned int)new_reloc->addend; | 137 | WARN_FUNC("don't know how to handle reloc symbol type %d: %s", |
| 138 | sec, offset + entry->new, | ||
| 139 | new_reloc->sym->type, | ||
| 140 | new_reloc->sym->name); | ||
| 141 | return -1; | ||
| 142 | } | ||
| 121 | 143 | ||
| 122 | /* _ASM_EXTABLE_EX hack */ | 144 | /* _ASM_EXTABLE_EX hack */ |
| 123 | if (alt->new_off >= 0x7ffffff0) | 145 | if (alt->new_off >= 0x7ffffff0) |
| @@ -164,7 +164,7 @@ const char unwinding_data[n]: an array of unwinding data, consisting of the EH F · 163 unmodified lines | |||
| 164 | The EH Frame header follows the Linux Standard Base (LSB) specification as described in the document at https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html | 164 | The EH Frame header follows the Linux Standard Base (LSB) specification as described in the document at https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html |
| 165 | 165 | ||
| 166 | 166 | ||
| 167 | The EH Frame follows the LSB specicfication as described in the document at https://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html | 167 | The EH Frame follows the LSB specification as described in the document at https://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html |
| 168 | 168 | ||
| 169 | 169 | ||
| 170 | NOTE: The mapped_size is generally either the same as unwind_data_size (if the unwinding data was mapped in memory by the running process) or zero (if the unwinding data is not mapped by the process). If the unwinding data was not mapped, then only the EH Frame Header will be read, which can be used to specify FP based unwinding for a function which does not have unwinding information. | 170 | NOTE: The mapped_size is generally either the same as unwind_data_size (if the unwinding data was mapped in memory by the running process) or zero (if the unwinding data is not mapped by the process). If the unwinding data was not mapped, then only the EH Frame Header will be read, which can be used to specify FP based unwinding for a function which does not have unwinding information. |
| @@ -261,7 +261,7 @@ COALESCE · 260 unmodified lines | |||
| 261 | User can specify how to sort offsets for cacheline. | 261 | User can specify how to sort offsets for cacheline. |
| 262 | 262 | ||
| 263 | Following fields are available and governs the final | 263 | Following fields are available and governs the final |
| 264 | output fields set for caheline offsets output: | 264 | output fields set for cacheline offsets output: |
| 265 | 265 | ||
| 266 | tid - coalesced by process TIDs | 266 | tid - coalesced by process TIDs |
| 267 | pid - coalesced by process PIDs | 267 | pid - coalesced by process PIDs |
| @@ -883,7 +883,7 @@ and "r" can be combined to get calls and returns. · 882 unmodified lines | |||
| 883 | 883 | ||
| 884 | "Transactions" events correspond to the start or end of transactions. The | 884 | "Transactions" events correspond to the start or end of transactions. The |
| 885 | 'flags' field can be used in perf script to determine whether the event is a | 885 | 'flags' field can be used in perf script to determine whether the event is a |
| 886 | tranasaction start, commit or abort. | 886 | transaction start, commit or abort. |
| 887 | 887 | ||
| 888 | Note that "instructions", "branches" and "transactions" events depend on code | 888 | Note that "instructions", "branches" and "transactions" events depend on code |
| 889 | flow packets which can be disabled by using the config term "branch=0". Refer | 889 | flow packets which can be disabled by using the config term "branch=0". Refer |
| @@ -44,7 +44,7 @@ COMMON OPTIONS · 43 unmodified lines | |||
| 44 | 44 | ||
| 45 | -f:: | 45 | -f:: |
| 46 | --force:: | 46 | --force:: |
| 47 | Don't complan, do it. | 47 | Don't complain, do it. |
| 48 | 48 | ||
| 49 | REPORT OPTIONS | 49 | REPORT OPTIONS |
| 50 | -------------- | 50 | -------------- |
| @@ -54,7 +54,7 @@ all sched_wakeup events in the system: · 53 unmodified lines | |||
| 54 | Traces meant to be processed using a script should be recorded with | 54 | Traces meant to be processed using a script should be recorded with |
| 55 | the above option: -a to enable system-wide collection. | 55 | the above option: -a to enable system-wide collection. |
| 56 | 56 | ||
| 57 | The format file for the sched_wakep event defines the following fields | 57 | The format file for the sched_wakeup event defines the following fields |
| 58 | (see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format): | 58 | (see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format): |
| 59 | 59 | ||
| 60 | ---- | 60 | ---- |
| @@ -448,7 +448,7 @@ all sched_wakeup events in the system: · 447 unmodified lines | |||
| 448 | Traces meant to be processed using a script should be recorded with | 448 | Traces meant to be processed using a script should be recorded with |
| 449 | the above option: -a to enable system-wide collection. | 449 | the above option: -a to enable system-wide collection. |
| 450 | 450 | ||
| 451 | The format file for the sched_wakep event defines the following fields | 451 | The format file for the sched_wakeup event defines the following fields |
| 452 | (see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format): | 452 | (see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format): |
| 453 | 453 | ||
| 454 | ---- | 454 | ---- |
| @@ -385,7 +385,7 @@ Aggregate counts per physical processor for system-wide mode measurements. · 384 unmodified lines | |||
| 385 | Print metrics or metricgroups specified in a comma separated list. | 385 | Print metrics or metricgroups specified in a comma separated list. |
| 386 | For a group all metrics from the group are added. | 386 | For a group all metrics from the group are added. |
| 387 | The events from the metrics are automatically measured. | 387 | The events from the metrics are automatically measured. |
| 388 | See perf list output for the possble metrics and metricgroups. | 388 | See perf list output for the possible metrics and metricgroups. |
| 389 | 389 | ||
| 390 | -A:: | 390 | -A:: |
| 391 | --no-aggr:: | 391 | --no-aggr:: |
| @@ -2,7 +2,7 @@ Using TopDown metrics in user space · 1 unmodified line | |||
| 2 | ----------------------------------- | 2 | ----------------------------------- |
| 3 | 3 | ||
| 4 | Intel CPUs (since Sandy Bridge and Silvermont) support a TopDown | 4 | Intel CPUs (since Sandy Bridge and Silvermont) support a TopDown |
| 5 | methology to break down CPU pipeline execution into 4 bottlenecks: | 5 | methodology to break down CPU pipeline execution into 4 bottlenecks: |
| 6 | frontend bound, backend bound, bad speculation, retiring. | 6 | frontend bound, backend bound, bad speculation, retiring. |
| 7 | 7 | ||
| 8 | For more details on Topdown see [1][5] | 8 | For more details on Topdown see [1][5] |
| @@ -8,10 +8,10 @@ · 7 unmodified lines | |||
| 8 | #include <linux/coresight-pmu.h> | 8 | #include <linux/coresight-pmu.h> |
| 9 | #include <linux/zalloc.h> | 9 | #include <linux/zalloc.h> |
| 10 | 10 | ||
| 11 | #include "../../util/auxtrace.h" | 11 | #include "../../../util/auxtrace.h" |
| 12 | #include "../../util/debug.h" | 12 | #include "../../../util/debug.h" |
| 13 | #include "../../util/evlist.h" | 13 | #include "../../../util/evlist.h" |
| 14 | #include "../../util/pmu.h" | 14 | #include "../../../util/pmu.h" |
| 15 | #include "cs-etm.h" | 15 | #include "cs-etm.h" |
| 16 | #include "arm-spe.h" | 16 | #include "arm-spe.h" |
| 17 | 17 | ||
| @@ -16,19 +16,19 @@ · 15 unmodified lines | |||
| 16 | #include <linux/zalloc.h> | 16 | #include <linux/zalloc.h> |
| 17 | 17 | ||
| 18 | #include "cs-etm.h" | 18 | #include "cs-etm.h" |
| 19 | #include "../../util/debug.h" | 19 | #include "../../../util/debug.h" |
| 20 | #include "../../util/record.h" | 20 | #include "../../../util/record.h" |
| 21 | #include "../../util/auxtrace.h" | 21 | #include "../../../util/auxtrace.h" |
| 22 | #include "../../util/cpumap.h" | 22 | #include "../../../util/cpumap.h" |
| 23 | #include "../../util/event.h" | 23 | #include "../../../util/event.h" |
| 24 | #include "../../util/evlist.h" | 24 | #include "../../../util/evlist.h" |
| 25 | #include "../../util/evsel.h" | 25 | #include "../../../util/evsel.h" |
| 26 | #include "../../util/perf_api_probe.h" | 26 | #include "../../../util/perf_api_probe.h" |
| 27 | #include "../../util/evsel_config.h" | 27 | #include "../../../util/evsel_config.h" |
| 28 | #include "../../util/pmu.h" | 28 | #include "../../../util/pmu.h" |
| 29 | #include "../../util/cs-etm.h" | 29 | #include "../../../util/cs-etm.h" |
| 30 | #include <internal/lib.h> // page_size | 30 | #include <internal/lib.h> // page_size |
| 31 | #include "../../util/session.h" | 31 | #include "../../../util/session.h" |
| 32 | 32 | ||
| 33 | #include <errno.h> | 33 | #include <errno.h> |
| 34 | #include <stdlib.h> | 34 | #include <stdlib.h> |
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | #include "../../util/perf_regs.h" | 2 | #include "../../../util/perf_regs.h" |
| 3 | 3 | ||
| 4 | const struct sample_reg sample_reg_masks[] = { | 4 | const struct sample_reg sample_reg_masks[] = { |
| 5 | SMPL_REG_END | 5 | SMPL_REG_END |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
| 11 | 11 | ||
| 12 | #include "arm-spe.h" | 12 | #include "arm-spe.h" |
| 13 | #include "../../util/pmu.h" | 13 | #include "../../../util/pmu.h" |
| 14 | 14 | ||
| 15 | struct perf_event_attr | 15 | struct perf_event_attr |
| 16 | *perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) | 16 | *perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) |
| @@ -1,8 +1,8 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | #include <elfutils/libdwfl.h> | 2 | #include <elfutils/libdwfl.h> |
| 3 | #include "../../util/unwind-libdw.h" | 3 | #include "../../../util/unwind-libdw.h" |
| 4 | #include "../../util/perf_regs.h" | 4 | #include "../../../util/perf_regs.h" |
| 5 | #include "../../util/event.h" | 5 | #include "../../../util/event.h" |
| 6 | 6 | ||
| 7 | bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg) | 7 | bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg) |
| 8 | { | 8 | { |
| @@ -3,8 +3,8 @@ · 2 unmodified lines | |||
| 3 | #include <errno.h> | 3 | #include <errno.h> |
| 4 | #include <libunwind.h> | 4 | #include <libunwind.h> |
| 5 | #include "perf_regs.h" | 5 | #include "perf_regs.h" |
| 6 | #include "../../util/unwind.h" | 6 | #include "../../../util/unwind.h" |
| 7 | #include "../../util/debug.h" | 7 | #include "../../../util/debug.h" |
| 8 | 8 | ||
| 9 | int libunwind__arch_reg_id(int regnum) | 9 | int libunwind__arch_reg_id(int regnum) |
| 10 | { | 10 | { |
| @@ -432,7 +432,7 @@ void iostat_print_metric(struct perf_stat_config *config, struct evsel *evsel, · 431 unmodified lines | |||
| 432 | u8 die = ((struct iio_root_port *)evsel->priv)->die; | 432 | u8 die = ((struct iio_root_port *)evsel->priv)->die; |
| 433 | struct perf_counts_values *count = perf_counts(evsel->counts, die, 0); | 433 | struct perf_counts_values *count = perf_counts(evsel->counts, die, 0); |
| 434 | 434 | ||
| 435 | if (count->run && count->ena) { | 435 | if (count && count->run && count->ena) { |
| 436 | if (evsel->prev_raw_counts && !out->force_header) { | 436 | if (evsel->prev_raw_counts && !out->force_header) { |
| 437 | struct perf_counts_values *prev_count = | 437 | struct perf_counts_values *prev_count = |
| 438 | perf_counts(evsel->prev_raw_counts, die, 0); | 438 | perf_counts(evsel->prev_raw_counts, die, 0); |
| @@ -2408,6 +2408,8 @@ int cmd_stat(int argc, const char **argv) · 2407 unmodified lines | |||
| 2408 | goto out; | 2408 | goto out; |
| 2409 | } else if (verbose) | 2409 | } else if (verbose) |
| 2410 | iostat_list(evsel_list, &stat_config); | 2410 | iostat_list(evsel_list, &stat_config); |
| 2411 | if (iostat_mode == IOSTAT_RUN && !target__has_cpu(&target)) | ||
| 2412 | target.system_wide = true; | ||
| 2411 | } | 2413 | } |
| 2412 | 2414 | ||
| 2413 | if (add_default_attributes()) | 2415 | if (add_default_attributes()) |
| @@ -1046,7 +1046,7 @@ · 1045 unmodified lines | |||
| 1046 | { | 1046 | { |
| 1047 | "EventCode": "0x4e010", | 1047 | "EventCode": "0x4e010", |
| 1048 | "EventName": "PM_GCT_NOSLOT_IC_L3MISS", | 1048 | "EventName": "PM_GCT_NOSLOT_IC_L3MISS", |
| 1049 | "BriefDescription": "Gct empty for this thread due to icach l3 miss", | 1049 | "BriefDescription": "Gct empty for this thread due to icache l3 miss", |
| 1050 | "PublicDescription": "" | 1050 | "PublicDescription": "" |
| 1051 | }, | 1051 | }, |
| 1052 | { | 1052 | { |
| @@ -229,8 +229,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, · 228 unmodified lines | |||
| 229 | struct thread *thread, struct state *state) | 229 | struct thread *thread, struct state *state) |
| 230 | { | 230 | { |
| 231 | struct addr_location al; | 231 | struct addr_location al; |
| 232 | unsigned char buf1[BUFSZ]; | 232 | unsigned char buf1[BUFSZ] = {0}; |
| 233 | unsigned char buf2[BUFSZ]; | 233 | unsigned char buf2[BUFSZ] = {0}; |
| 234 | size_t ret_len; | 234 | size_t ret_len; |
| 235 | u64 objdump_addr; | 235 | u64 objdump_addr; |
| 236 | const char *objdump_name; | 236 | const char *objdump_name; |
| @@ -20,6 +20,23 @@ · 19 unmodified lines | |||
| 20 | /* For bsearch. We try to unwind functions in shared object. */ | 20 | /* For bsearch. We try to unwind functions in shared object. */ |
| 21 | #include <stdlib.h> | 21 | #include <stdlib.h> |
| 22 | 22 | ||
| 23 | /* | ||
| 24 | * The test will assert frames are on the stack but tail call optimizations lose | ||
| 25 | * the frame of the caller. Clang can disable this optimization on a called | ||
| 26 | * function but GCC currently (11/2020) lacks this attribute. The barrier is | ||
| 27 | * used to inhibit tail calls in these cases. | ||
| 28 | */ | ||
| 29 | #ifdef __has_attribute | ||
| 30 | #if __has_attribute(disable_tail_calls) | ||
| 31 | #define NO_TAIL_CALL_ATTRIBUTE __attribute__((disable_tail_calls)) | ||
| 32 | #define NO_TAIL_CALL_BARRIER | ||
| 33 | #endif | ||
| 34 | #endif | ||
| 35 | #ifndef NO_TAIL_CALL_ATTRIBUTE | ||
| 36 | #define NO_TAIL_CALL_ATTRIBUTE | ||
| 37 | #define NO_TAIL_CALL_BARRIER __asm__ __volatile__("" : : : "memory"); | ||
| 38 | #endif | ||
| 39 | |||
| 23 | static int mmap_handler(struct perf_tool *tool __maybe_unused, | 40 | static int mmap_handler(struct perf_tool *tool __maybe_unused, |
| 24 | union perf_event *event, | 41 | union perf_event *event, |
| 25 | struct perf_sample *sample, | 42 | struct perf_sample *sample, |
| @@ -91,7 +108,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) · 65 unmodified lines | |||
| 91 | return strcmp((const char *) symbol, funcs[idx]); | 108 | return strcmp((const char *) symbol, funcs[idx]); |
| 92 | } | 109 | } |
| 93 | 110 | ||
| 94 | noinline int test_dwarf_unwind__thread(struct thread *thread) | 111 | NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__thread(struct thread *thread) |
| 95 | { | 112 | { |
| 96 | struct perf_sample sample; | 113 | struct perf_sample sample; |
| 97 | unsigned long cnt = 0; | 114 | unsigned long cnt = 0; |
| @@ -122,7 +139,7 @@ noinline int test_dwarf_unwind__thread(struct thread *thread) · 24 unmodified lines | |||
| 122 | 139 | ||
| 123 | static int global_unwind_retval = -INT_MAX; | 140 | static int global_unwind_retval = -INT_MAX; |
| 124 | 141 | ||
| 125 | noinline int test_dwarf_unwind__compare(void *p1, void *p2) | 142 | NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__compare(void *p1, void *p2) |
| 126 | { | 143 | { |
| 127 | /* Any possible value should be 'thread' */ | 144 | /* Any possible value should be 'thread' */ |
| 128 | struct thread *thread = *(struct thread **)p1; | 145 | struct thread *thread = *(struct thread **)p1; |
| @@ -141,7 +158,7 @@ noinline int test_dwarf_unwind__compare(void *p1, void *p2) · 12 unmodified lines | |||
| 141 | return p1 - p2; | 158 | return p1 - p2; |
| 142 | } | 159 | } |
| 143 | 160 | ||
| 144 | noinline int test_dwarf_unwind__krava_3(struct thread *thread) | 161 | NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_3(struct thread *thread) |
| 145 | { | 162 | { |
| 146 | struct thread *array[2] = {thread, thread}; | 163 | struct thread *array[2] = {thread, thread}; |
| 147 | void *fp = &bsearch; | 164 | void *fp = &bsearch; |
| @@ -160,14 +177,22 @@ noinline int test_dwarf_unwind__krava_3(struct thread *thread) · 12 unmodified lines | |||
| 160 | return global_unwind_retval; | 177 | return global_unwind_retval; |
| 161 | } | 178 | } |
| 162 | 179 | ||
| 163 | noinline int test_dwarf_unwind__krava_2(struct thread *thread) | 180 | NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_2(struct thread *thread) |
| 164 | { | 181 | { |
| 165 | return test_dwarf_unwind__krava_3(thread); | 182 | int ret; |
| 183 | |||
| 184 | ret = test_dwarf_unwind__krava_3(thread); | ||
| 185 | NO_TAIL_CALL_BARRIER; | ||
| 186 | return ret; | ||
| 166 | } | 187 | } |
| 167 | 188 | ||
| 168 | noinline int test_dwarf_unwind__krava_1(struct thread *thread) | 189 | NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_1(struct thread *thread) |
| 169 | { | 190 | { |
| 170 | return test_dwarf_unwind__krava_2(thread); | 191 | int ret; |
| 192 | |||
| 193 | ret = test_dwarf_unwind__krava_2(thread); | ||
| 194 | NO_TAIL_CALL_BARRIER; | ||
| 195 | return ret; | ||
| 171 | } | 196 | } |
| 172 | 197 | ||
| 173 | int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused) | 198 | int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused) |
| @@ -801,7 +801,7 @@ int perf_config_set(struct perf_config_set *set, · 800 unmodified lines | |||
| 801 | section->name, item->name); | 801 | section->name, item->name); |
| 802 | ret = fn(key, value, data); | 802 | ret = fn(key, value, data); |
| 803 | if (ret < 0) { | 803 | if (ret < 0) { |
| 804 | pr_err("Error: wrong config key-value pair %s=%s\n", | 804 | pr_err("Error in the given config file: wrong config key-value pair %s=%s\n", |
| 805 | key, value); | 805 | key, value); |
| 806 | /* | 806 | /* |
| 807 | * Can't be just a 'break', as perf_config_set__for_each_entry() | 807 | * Can't be just a 'break', as perf_config_set__for_each_entry() |
| @@ -375,7 +375,8 @@ $(TRUNNER_BPF_OBJS): $(TRUNNER_OUTPUT)/%.o: \ · 374 unmodified lines | |||
| 375 | $(TRUNNER_BPF_PROGS_DIR)/%.c \ | 375 | $(TRUNNER_BPF_PROGS_DIR)/%.c \ |
| 376 | $(TRUNNER_BPF_PROGS_DIR)/*.h \ | 376 | $(TRUNNER_BPF_PROGS_DIR)/*.h \ |
| 377 | $$(INCLUDE_DIR)/vmlinux.h \ | 377 | $$(INCLUDE_DIR)/vmlinux.h \ |
| 378 | $(wildcard $(BPFDIR)/bpf_*.h) | $(TRUNNER_OUTPUT) | 378 | $(wildcard $(BPFDIR)/bpf_*.h) \ |
| 379 | | $(TRUNNER_OUTPUT) $$(BPFOBJ) | ||
| 379 | $$(call $(TRUNNER_BPF_BUILD_RULE),$$<,$$@, \ | 380 | $$(call $(TRUNNER_BPF_BUILD_RULE),$$<,$$@, \ |
| 380 | $(TRUNNER_BPF_CFLAGS)) | 381 | $(TRUNNER_BPF_CFLAGS)) |
| 381 | 382 | ||
| @@ -112,6 +112,14 @@ setup() · 111 unmodified lines | |||
| 112 | ip netns add "${NS2}" | 112 | ip netns add "${NS2}" |
| 113 | ip netns add "${NS3}" | 113 | ip netns add "${NS3}" |
| 114 | 114 | ||
| 115 | # rp_filter gets confused by what these tests are doing, so disable it | ||
| 116 | ip netns exec ${NS1} sysctl -wq net.ipv4.conf.all.rp_filter=0 | ||
| 117 | ip netns exec ${NS2} sysctl -wq net.ipv4.conf.all.rp_filter=0 | ||
| 118 | ip netns exec ${NS3} sysctl -wq net.ipv4.conf.all.rp_filter=0 | ||
| 119 | ip netns exec ${NS1} sysctl -wq net.ipv4.conf.default.rp_filter=0 | ||
| 120 | ip netns exec ${NS2} sysctl -wq net.ipv4.conf.default.rp_filter=0 | ||
| 121 | ip netns exec ${NS3} sysctl -wq net.ipv4.conf.default.rp_filter=0 | ||
| 122 | |||
| 115 | ip link add veth1 type veth peer name veth2 | 123 | ip link add veth1 type veth peer name veth2 |
| 116 | ip link add veth3 type veth peer name veth4 | 124 | ip link add veth3 type veth peer name veth4 |
| 117 | ip link add veth5 type veth peer name veth6 | 125 | ip link add veth5 type veth peer name veth6 |
| @@ -236,11 +244,6 @@ setup() · 118 unmodified lines | |||
| 236 | ip -netns ${NS1} -6 route add ${IPv6_GRE}/128 dev veth5 via ${IPv6_6} ${VRF} | 244 | ip -netns ${NS1} -6 route add ${IPv6_GRE}/128 dev veth5 via ${IPv6_6} ${VRF} |
| 237 | ip -netns ${NS2} -6 route add ${IPv6_GRE}/128 dev veth7 via ${IPv6_8} ${VRF} | 245 | ip -netns ${NS2} -6 route add ${IPv6_GRE}/128 dev veth7 via ${IPv6_8} ${VRF} |
| 238 | 246 | ||
| 239 | # rp_filter gets confused by what these tests are doing, so disable it | ||
| 240 | ip netns exec ${NS1} sysctl -wq net.ipv4.conf.all.rp_filter=0 | ||
| 241 | ip netns exec ${NS2} sysctl -wq net.ipv4.conf.all.rp_filter=0 | ||
| 242 | ip netns exec ${NS3} sysctl -wq net.ipv4.conf.all.rp_filter=0 | ||
| 243 | |||
| 244 | TMPFILE=$(mktemp /tmp/test_lwt_ip_encap.XXXXXX) | 247 | TMPFILE=$(mktemp /tmp/test_lwt_ip_encap.XXXXXX) |
| 245 | 248 | ||
| 246 | sleep 1 # reduce flakiness | 249 | sleep 1 # reduce flakiness |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | |||
| 24 | /x86_64/smm_test | 24 | /x86_64/smm_test |
| 25 | /x86_64/state_test | 25 | /x86_64/state_test |
| 26 | /x86_64/svm_vmcall_test | 26 | /x86_64/svm_vmcall_test |
| 27 | /x86_64/svm_int_ctl_test | ||
| 27 | /x86_64/sync_regs_test | 28 | /x86_64/sync_regs_test |
| 28 | /x86_64/tsc_msrs_test | 29 | /x86_64/tsc_msrs_test |
| 29 | /x86_64/userspace_msr_exit_test | 30 | /x86_64/userspace_msr_exit_test |
| @@ -56,6 +56,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/smm_test · 55 unmodified lines | |||
| 56 | TEST_GEN_PROGS_x86_64 += x86_64/state_test | 56 | TEST_GEN_PROGS_x86_64 += x86_64/state_test |
| 57 | TEST_GEN_PROGS_x86_64 += x86_64/vmx_preemption_timer_test | 57 | TEST_GEN_PROGS_x86_64 += x86_64/vmx_preemption_timer_test |
| 58 | TEST_GEN_PROGS_x86_64 += x86_64/svm_vmcall_test | 58 | TEST_GEN_PROGS_x86_64 += x86_64/svm_vmcall_test |
| 59 | TEST_GEN_PROGS_x86_64 += x86_64/svm_int_ctl_test | ||
| 59 | TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test | 60 | TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test |
| 60 | TEST_GEN_PROGS_x86_64 += x86_64/userspace_msr_exit_test | 61 | TEST_GEN_PROGS_x86_64 += x86_64/userspace_msr_exit_test |
| 61 | TEST_GEN_PROGS_x86_64 += x86_64/vmx_apic_access_test | 62 | TEST_GEN_PROGS_x86_64 += x86_64/vmx_apic_access_test |
| @@ -371,9 +371,7 @@ static void help(char *name) · 370 unmodified lines | |||
| 371 | printf(" -v: specify the number of vCPUs to run.\n"); | 371 | printf(" -v: specify the number of vCPUs to run.\n"); |
| 372 | printf(" -o: Overlap guest memory accesses instead of partitioning\n" | 372 | printf(" -o: Overlap guest memory accesses instead of partitioning\n" |
| 373 | " them into a separate region of memory for each vCPU.\n"); | 373 | " them into a separate region of memory for each vCPU.\n"); |
| 374 | printf(" -s: specify the type of memory that should be used to\n" | 374 | backing_src_help("-s"); |
| 375 | " back the guest data region.\n\n"); | ||
| 376 | backing_src_help(); | ||
| 377 | puts(""); | 375 | puts(""); |
| 378 | exit(0); | 376 | exit(0); |
| 379 | } | 377 | } |
| @@ -381,7 +379,7 @@ static void help(char *name) · 1 unmodified line | |||
| 381 | int main(int argc, char *argv[]) | 379 | int main(int argc, char *argv[]) |
| 382 | { | 380 | { |
| 383 | struct test_params params = { | 381 | struct test_params params = { |
| 384 | .backing_src = VM_MEM_SRC_ANONYMOUS, | 382 | .backing_src = DEFAULT_VM_MEM_SRC, |
| 385 | .vcpu_memory_bytes = DEFAULT_PER_VCPU_MEM_SIZE, | 383 | .vcpu_memory_bytes = DEFAULT_PER_VCPU_MEM_SIZE, |
| 386 | .vcpus = 1, | 384 | .vcpus = 1, |
| 387 | }; | 385 | }; |
| @@ -179,7 +179,7 @@ static void *uffd_handler_thread_fn(void *arg) · 178 unmodified lines | |||
| 179 | return NULL; | 179 | return NULL; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | if (!pollfd[0].revents & POLLIN) | 182 | if (!(pollfd[0].revents & POLLIN)) |
| 183 | continue; | 183 | continue; |
| 184 | 184 | ||
| 185 | r = read(uffd, &msg, sizeof(msg)); | 185 | r = read(uffd, &msg, sizeof(msg)); |
| @@ -416,7 +416,7 @@ static void help(char *name) · 230 unmodified lines | |||
| 416 | { | 416 | { |
| 417 | puts(""); | 417 | puts(""); |
| 418 | printf("usage: %s [-h] [-m vm_mode] [-u uffd_mode] [-d uffd_delay_usec]\n" | 418 | printf("usage: %s [-h] [-m vm_mode] [-u uffd_mode] [-d uffd_delay_usec]\n" |
| 419 | " [-b memory] [-t type] [-v vcpus] [-o]\n", name); | 419 | " [-b memory] [-s type] [-v vcpus] [-o]\n", name); |
| 420 | guest_modes_help(); | 420 | guest_modes_help(); |
| 421 | printf(" -u: use userfaultfd to handle vCPU page faults. Mode is a\n" | 421 | printf(" -u: use userfaultfd to handle vCPU page faults. Mode is a\n" |
| 422 | " UFFD registration mode: 'MISSING' or 'MINOR'.\n"); | 422 | " UFFD registration mode: 'MISSING' or 'MINOR'.\n"); |
| @@ -426,8 +426,7 @@ static void help(char *name) · 3 unmodified lines | |||
| 426 | printf(" -b: specify the size of the memory region which should be\n" | 426 | printf(" -b: specify the size of the memory region which should be\n" |
| 427 | " demand paged by each vCPU. e.g. 10M or 3G.\n" | 427 | " demand paged by each vCPU. e.g. 10M or 3G.\n" |
| 428 | " Default: 1G\n"); | 428 | " Default: 1G\n"); |
| 429 | printf(" -t: The type of backing memory to use. Default: anonymous\n"); | 429 | backing_src_help("-s"); |
| 430 | backing_src_help(); | ||
| 431 | printf(" -v: specify the number of vCPUs to run.\n"); | 430 | printf(" -v: specify the number of vCPUs to run.\n"); |
| 432 | printf(" -o: Overlap guest memory accesses instead of partitioning\n" | 431 | printf(" -o: Overlap guest memory accesses instead of partitioning\n" |
| 433 | " them into a separate region of memory for each vCPU.\n"); | 432 | " them into a separate region of memory for each vCPU.\n"); |
| @@ -439,14 +438,14 @@ int main(int argc, char *argv[]) · 5 unmodified lines | |||
| 439 | { | 438 | { |
| 440 | int max_vcpus = kvm_check_cap(KVM_CAP_MAX_VCPUS); | 439 | int max_vcpus = kvm_check_cap(KVM_CAP_MAX_VCPUS); |
| 441 | struct test_params p = { | 440 | struct test_params p = { |
| 442 | .src_type = VM_MEM_SRC_ANONYMOUS, | 441 | .src_type = DEFAULT_VM_MEM_SRC, |
| 443 | .partition_vcpu_memory_access = true, | 442 | .partition_vcpu_memory_access = true, |
| 444 | }; | 443 | }; |
| 445 | int opt; | 444 | int opt; |
| 446 | 445 | ||
| 447 | guest_modes_append_default(); | 446 | guest_modes_append_default(); |
| 448 | 447 | ||
| 449 | while ((opt = getopt(argc, argv, "hm:u:d:b:t:v:o")) != -1) { | 448 | while ((opt = getopt(argc, argv, "hm:u:d:b:s:v:o")) != -1) { |
| 450 | switch (opt) { | 449 | switch (opt) { |
| 451 | case 'm': | 450 | case 'm': |
| 452 | guest_modes_cmdline(optarg); | 451 | guest_modes_cmdline(optarg); |
| @@ -465,7 +464,7 @@ int main(int argc, char *argv[]) · 12 unmodified lines | |||
| 465 | case 'b': | 464 | case 'b': |
| 466 | guest_percpu_mem_size = parse_size(optarg); | 465 | guest_percpu_mem_size = parse_size(optarg); |
| 467 | break; | 466 | break; |
| 468 | case 't': | 467 | case 's': |
| 469 | p.src_type = parse_backing_src_type(optarg); | 468 | p.src_type = parse_backing_src_type(optarg); |
| 470 | break; | 469 | break; |
| 471 | case 'v': | 470 | case 'v': |
| @@ -485,7 +484,7 @@ int main(int argc, char *argv[]) · 13 unmodified lines | |||
| 485 | 484 | ||
| 486 | if (p.uffd_mode == UFFDIO_REGISTER_MODE_MINOR && | 485 | if (p.uffd_mode == UFFDIO_REGISTER_MODE_MINOR && |
| 487 | !backing_src_is_shared(p.src_type)) { | 486 | !backing_src_is_shared(p.src_type)) { |
| 488 | TEST_FAIL("userfaultfd MINOR mode requires shared memory; pick a different -t"); | 487 | TEST_FAIL("userfaultfd MINOR mode requires shared memory; pick a different -s"); |
| 489 | } | 488 | } |
| 490 | 489 | ||
| 491 | for_each_guest_mode(run_test, &p); | 490 | for_each_guest_mode(run_test, &p); |
| @@ -118,42 +118,64 @@ static inline void disable_dirty_logging(struct kvm_vm *vm, int slots) · 117 unmodified lines | |||
| 118 | toggle_dirty_logging(vm, slots, false); | 118 | toggle_dirty_logging(vm, slots, false); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | static void get_dirty_log(struct kvm_vm *vm, int slots, unsigned long *bitmap, | 121 | static void get_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[], int slots) |
| 122 | uint64_t nr_pages) | ||
| 123 | { | 122 | { |
| 124 | uint64_t slot_pages = nr_pages / slots; | ||
| 125 | int i; | 123 | int i; |
| 126 | 124 | ||
| 127 | for (i = 0; i < slots; i++) { | 125 | for (i = 0; i < slots; i++) { |
| 128 | int slot = PERF_TEST_MEM_SLOT_INDEX + i; | 126 | int slot = PERF_TEST_MEM_SLOT_INDEX + i; |
| 129 | unsigned long *slot_bitmap = bitmap + i * slot_pages; | ||
| 130 | 127 | ||
| 131 | kvm_vm_get_dirty_log(vm, slot, slot_bitmap); | 128 | kvm_vm_get_dirty_log(vm, slot, bitmaps[i]); |
| 132 | } | 129 | } |
| 133 | } | 130 | } |
| 134 | 131 | ||
| 135 | static void clear_dirty_log(struct kvm_vm *vm, int slots, unsigned long *bitmap, | 132 | static void clear_dirty_log(struct kvm_vm *vm, unsigned long *bitmaps[], |
| 136 | uint64_t nr_pages) | 133 | int slots, uint64_t pages_per_slot) |
| 137 | { | 134 | { |
| 138 | uint64_t slot_pages = nr_pages / slots; | ||
| 139 | int i; | 135 | int i; |
| 140 | 136 | ||
| 141 | for (i = 0; i < slots; i++) { | 137 | for (i = 0; i < slots; i++) { |
| 142 | int slot = PERF_TEST_MEM_SLOT_INDEX + i; | 138 | int slot = PERF_TEST_MEM_SLOT_INDEX + i; |
| 143 | unsigned long *slot_bitmap = bitmap + i * slot_pages; | ||
| 144 | 139 | ||
| 145 | kvm_vm_clear_dirty_log(vm, slot, slot_bitmap, 0, slot_pages); | 140 | kvm_vm_clear_dirty_log(vm, slot, bitmaps[i], 0, pages_per_slot); |
| 146 | } | 141 | } |
| 147 | } | 142 | } |
| 148 | 143 | ||
| 144 | static unsigned long **alloc_bitmaps(int slots, uint64_t pages_per_slot) | ||
| 145 | { | ||
| 146 | unsigned long **bitmaps; | ||
| 147 | int i; | ||
| 148 | |||
| 149 | bitmaps = malloc(slots * sizeof(bitmaps[0])); | ||
| 150 | TEST_ASSERT(bitmaps, "Failed to allocate bitmaps array."); | ||
| 151 | |||
| 152 | for (i = 0; i < slots; i++) { | ||
| 153 | bitmaps[i] = bitmap_zalloc(pages_per_slot); | ||
| 154 | TEST_ASSERT(bitmaps[i], "Failed to allocate slot bitmap."); | ||
| 155 | } | ||
| 156 | |||
| 157 | return bitmaps; | ||
| 158 | } | ||
| 159 | |||
| 160 | static void free_bitmaps(unsigned long *bitmaps[], int slots) | ||
| 161 | { | ||
| 162 | int i; | ||
| 163 | |||
| 164 | for (i = 0; i < slots; i++) | ||
| 165 | free(bitmaps[i]); | ||
| 166 | |||
| 167 | free(bitmaps); | ||
| 168 | } | ||
| 169 | |||
| 149 | static void run_test(enum vm_guest_mode mode, void *arg) | 170 | static void run_test(enum vm_guest_mode mode, void *arg) |
| 150 | { | 171 | { |
| 151 | struct test_params *p = arg; | 172 | struct test_params *p = arg; |
| 152 | pthread_t *vcpu_threads; | 173 | pthread_t *vcpu_threads; |
| 153 | struct kvm_vm *vm; | 174 | struct kvm_vm *vm; |
| 154 | unsigned long *bmap; | 175 | unsigned long **bitmaps; |
| 155 | uint64_t guest_num_pages; | 176 | uint64_t guest_num_pages; |
| 156 | uint64_t host_num_pages; | 177 | uint64_t host_num_pages; |
| 178 | uint64_t pages_per_slot; | ||
| 157 | int vcpu_id; | 179 | int vcpu_id; |
| 158 | struct timespec start; | 180 | struct timespec start; |
| 159 | struct timespec ts_diff; | 181 | struct timespec ts_diff; |
| @@ -171,7 +193,9 @@ static void run_test(enum vm_guest_mode mode, void *arg) · 11 unmodified lines | |||
| 171 | guest_num_pages = (nr_vcpus * guest_percpu_mem_size) >> vm_get_page_shift(vm); | 193 | guest_num_pages = (nr_vcpus * guest_percpu_mem_size) >> vm_get_page_shift(vm); |
| 172 | guest_num_pages = vm_adjust_num_guest_pages(mode, guest_num_pages); | 194 | guest_num_pages = vm_adjust_num_guest_pages(mode, guest_num_pages); |
| 173 | host_num_pages = vm_num_host_pages(mode, guest_num_pages); | 195 | host_num_pages = vm_num_host_pages(mode, guest_num_pages); |
| 174 | bmap = bitmap_zalloc(host_num_pages); | 196 | pages_per_slot = host_num_pages / p->slots; |
| 197 | |||
| 198 | bitmaps = alloc_bitmaps(p->slots, pages_per_slot); | ||
| 175 | 199 | ||
| 176 | if (dirty_log_manual_caps) { | 200 | if (dirty_log_manual_caps) { |
| 177 | cap.cap = KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2; | 201 | cap.cap = KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2; |
| @@ -239,7 +263,7 @@ static void run_test(enum vm_guest_mode mode, void *arg) · 61 unmodified lines | |||
| 239 | iteration, ts_diff.tv_sec, ts_diff.tv_nsec); | 263 | iteration, ts_diff.tv_sec, ts_diff.tv_nsec); |
| 240 | 264 | ||
| 241 | clock_gettime(CLOCK_MONOTONIC, &start); | 265 | clock_gettime(CLOCK_MONOTONIC, &start); |
| 242 | get_dirty_log(vm, p->slots, bmap, host_num_pages); | 266 | get_dirty_log(vm, bitmaps, p->slots); |
| 243 | ts_diff = timespec_elapsed(start); | 267 | ts_diff = timespec_elapsed(start); |
| 244 | get_dirty_log_total = timespec_add(get_dirty_log_total, | 268 | get_dirty_log_total = timespec_add(get_dirty_log_total, |
| 245 | ts_diff); | 269 | ts_diff); |
| @@ -248,7 +272,7 @@ static void run_test(enum vm_guest_mode mode, void *arg) · 2 unmodified lines | |||
| 248 | 272 | ||
| 249 | if (dirty_log_manual_caps) { | 273 | if (dirty_log_manual_caps) { |
| 250 | clock_gettime(CLOCK_MONOTONIC, &start); | 274 | clock_gettime(CLOCK_MONOTONIC, &start); |
| 251 | clear_dirty_log(vm, p->slots, bmap, host_num_pages); | 275 | clear_dirty_log(vm, bitmaps, p->slots, pages_per_slot); |
| 252 | ts_diff = timespec_elapsed(start); | 276 | ts_diff = timespec_elapsed(start); |
| 253 | clear_dirty_log_total = timespec_add(clear_dirty_log_total, | 277 | clear_dirty_log_total = timespec_add(clear_dirty_log_total, |
| 254 | ts_diff); | 278 | ts_diff); |
| @@ -281,7 +305,7 @@ static void run_test(enum vm_guest_mode mode, void *arg) · 26 unmodified lines | |||
| 281 | clear_dirty_log_total.tv_nsec, avg.tv_sec, avg.tv_nsec); | 305 | clear_dirty_log_total.tv_nsec, avg.tv_sec, avg.tv_nsec); |
| 282 | } | 306 | } |
| 283 | 307 | ||
| 284 | free(bmap); | 308 | free_bitmaps(bitmaps, p->slots); |
| 285 | free(vcpu_threads); | 309 | free(vcpu_threads); |
| 286 | perf_test_destroy_vm(vm); | 310 | perf_test_destroy_vm(vm); |
| 287 | } | 311 | } |
| @@ -308,11 +332,9 @@ static void help(char *name) · 20 unmodified lines | |||
| 308 | printf(" -v: specify the number of vCPUs to run.\n"); | 332 | printf(" -v: specify the number of vCPUs to run.\n"); |
| 309 | printf(" -o: Overlap guest memory accesses instead of partitioning\n" | 333 | printf(" -o: Overlap guest memory accesses instead of partitioning\n" |
| 310 | " them into a separate region of memory for each vCPU.\n"); | 334 | " them into a separate region of memory for each vCPU.\n"); |
| 311 | printf(" -s: specify the type of memory that should be used to\n" | 335 | backing_src_help("-s"); |
| 312 | " back the guest data region.\n\n"); | ||
| 313 | printf(" -x: Split the memory region into this number of memslots.\n" | 336 | printf(" -x: Split the memory region into this number of memslots.\n" |
| 314 | " (default: 1)"); | 337 | " (default: 1)\n"); |
| 315 | backing_src_help(); | ||
| 316 | puts(""); | 338 | puts(""); |
| 317 | exit(0); | 339 | exit(0); |
| 318 | } | 340 | } |
| @@ -324,7 +346,7 @@ int main(int argc, char *argv[]) · 5 unmodified lines | |||
| 324 | .iterations = TEST_HOST_LOOP_N, | 346 | .iterations = TEST_HOST_LOOP_N, |
| 325 | .wr_fract = 1, | 347 | .wr_fract = 1, |
| 326 | .partition_vcpu_memory_access = true, | 348 | .partition_vcpu_memory_access = true, |
| 327 | .backing_src = VM_MEM_SRC_ANONYMOUS, | 349 | .backing_src = DEFAULT_VM_MEM_SRC, |
| 328 | .slots = 1, | 350 | .slots = 1, |
| 329 | }; | 351 | }; |
| 330 | int opt; | 352 | int opt; |
| @@ -90,6 +90,8 @@ enum vm_mem_backing_src_type { · 89 unmodified lines | |||
| 90 | NUM_SRC_TYPES, | 90 | NUM_SRC_TYPES, |
| 91 | }; | 91 | }; |
| 92 | 92 | ||
| 93 | #define DEFAULT_VM_MEM_SRC VM_MEM_SRC_ANONYMOUS | ||
| 94 | |||
| 93 | struct vm_mem_backing_src_alias { | 95 | struct vm_mem_backing_src_alias { |
| 94 | const char *name; | 96 | const char *name; |
| 95 | uint32_t flag; | 97 | uint32_t flag; |
| @@ -102,7 +104,7 @@ size_t get_trans_hugepagesz(void); · 6 unmodified lines | |||
| 102 | size_t get_def_hugetlb_pagesz(void); | 104 | size_t get_def_hugetlb_pagesz(void); |
| 103 | const struct vm_mem_backing_src_alias *vm_mem_backing_src_alias(uint32_t i); | 105 | const struct vm_mem_backing_src_alias *vm_mem_backing_src_alias(uint32_t i); |
| 104 | size_t get_backing_src_pagesz(uint32_t i); | 106 | size_t get_backing_src_pagesz(uint32_t i); |
| 105 | void backing_src_help(void); | 107 | void backing_src_help(const char *flag); |
| 106 | enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name); | 108 | enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name); |
| 107 | long get_run_delay(void); | 109 | long get_run_delay(void); |
| 108 | 110 | ||
| @@ -312,37 +312,37 @@ static inline void set_xmm(int n, unsigned long val) · 311 unmodified lines | |||
| 312 | } | 312 | } |
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | typedef unsigned long v1di __attribute__ ((vector_size (8))); | 315 | #define GET_XMM(__xmm) \ |
| 316 | ({ \ | ||
| 317 | unsigned long __val; \ | ||
| 318 | asm volatile("movq %%"#__xmm", %0" : "=r"(__val)); \ | ||
| 319 | __val; \ | ||
| 320 | }) | ||
| 321 | |||
| 316 | static inline unsigned long get_xmm(int n) | 322 | static inline unsigned long get_xmm(int n) |
| 317 | { | 323 | { |
| 318 | assert(n >= 0 && n <= 7); | 324 | assert(n >= 0 && n <= 7); |
| 319 | 325 | ||
| 320 | register v1di xmm0 __asm__("%xmm0"); | ||
| 321 | register v1di xmm1 __asm__("%xmm1"); | ||
| 322 | register v1di xmm2 __asm__("%xmm2"); | ||
| 323 | register v1di xmm3 __asm__("%xmm3"); | ||
| 324 | register v1di xmm4 __asm__("%xmm4"); | ||
| 325 | register v1di xmm5 __asm__("%xmm5"); | ||
| 326 | register v1di xmm6 __asm__("%xmm6"); | ||
| 327 | register v1di xmm7 __asm__("%xmm7"); | ||
| 328 | switch (n) { | 326 | switch (n) { |
| 329 | case 0: | 327 | case 0: |
| 330 | return (unsigned long)xmm0; | 328 | return GET_XMM(xmm0); |
| 331 | case 1: | 329 | case 1: |
| 332 | return (unsigned long)xmm1; | 330 | return GET_XMM(xmm1); |
| 333 | case 2: | 331 | case 2: |
| 334 | return (unsigned long)xmm2; | 332 | return GET_XMM(xmm2); |
| 335 | case 3: | 333 | case 3: |
| 336 | return (unsigned long)xmm3; | 334 | return GET_XMM(xmm3); |
| 337 | case 4: | 335 | case 4: |
| 338 | return (unsigned long)xmm4; | 336 | return GET_XMM(xmm4); |
| 339 | case 5: | 337 | case 5: |
| 340 | return (unsigned long)xmm5; | 338 | return GET_XMM(xmm5); |
| 341 | case 6: | 339 | case 6: |
| 342 | return (unsigned long)xmm6; | 340 | return GET_XMM(xmm6); |
| 343 | case 7: | 341 | case 7: |
| 344 | return (unsigned long)xmm7; | 342 | return GET_XMM(xmm7); |
| 345 | } | 343 | } |
| 344 | |||
| 345 | /* never reached */ | ||
| 346 | return 0; | 346 | return 0; |
| 347 | } | 347 | } |
| 348 | 348 | ||
| @@ -456,10 +456,7 @@ static void help(char *name) · 455 unmodified lines | |||
| 456 | " (default: 1G)\n"); | 456 | " (default: 1G)\n"); |
| 457 | printf(" -v: specify the number of vCPUs to run\n" | 457 | printf(" -v: specify the number of vCPUs to run\n" |
| 458 | " (default: 1)\n"); | 458 | " (default: 1)\n"); |
| 459 | printf(" -s: specify the type of memory that should be used to\n" | 459 | backing_src_help("-s"); |
| 460 | " back the guest data region.\n" | ||
| 461 | " (default: anonymous)\n\n"); | ||
| 462 | backing_src_help(); | ||
| 463 | puts(""); | 460 | puts(""); |
| 464 | } | 461 | } |
| 465 | 462 | ||
| @@ -468,7 +465,7 @@ int main(int argc, char *argv[]) · 2 unmodified lines | |||
| 468 | int max_vcpus = kvm_check_cap(KVM_CAP_MAX_VCPUS); | 465 | int max_vcpus = kvm_check_cap(KVM_CAP_MAX_VCPUS); |
| 469 | struct test_params p = { | 466 | struct test_params p = { |
| 470 | .test_mem_size = DEFAULT_TEST_MEM_SIZE, | 467 | .test_mem_size = DEFAULT_TEST_MEM_SIZE, |
| 471 | .src_type = VM_MEM_SRC_ANONYMOUS, | 468 | .src_type = DEFAULT_VM_MEM_SRC, |
| 472 | }; | 469 | }; |
| 473 | int opt; | 470 | int opt; |
| 474 | 471 | ||
| @@ -283,13 +283,22 @@ size_t get_backing_src_pagesz(uint32_t i) · 282 unmodified lines | |||
| 283 | } | 283 | } |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | void backing_src_help(void) | 286 | static void print_available_backing_src_types(const char *prefix) |
| 287 | { | 287 | { |
| 288 | int i; | 288 | int i; |
| 289 | 289 | ||
| 290 | printf("Available backing src types:\n"); | 290 | printf("%sAvailable backing src types:\n", prefix); |
| 291 | |||
| 291 | for (i = 0; i < NUM_SRC_TYPES; i++) | 292 | for (i = 0; i < NUM_SRC_TYPES; i++) |
| 292 | printf("\t%s\n", vm_mem_backing_src_alias(i)->name); | 293 | printf("%s %s\n", prefix, vm_mem_backing_src_alias(i)->name); |
| 294 | } | ||
| 295 | |||
| 296 | void backing_src_help(const char *flag) | ||
| 297 | { | ||
| 298 | printf(" %s: specify the type of memory that should be used to\n" | ||
| 299 | " back the guest data region. (default: %s)\n", | ||
| 300 | flag, vm_mem_backing_src_alias(DEFAULT_VM_MEM_SRC)->name); | ||
| 301 | print_available_backing_src_types(" "); | ||
| 293 | } | 302 | } |
| 294 | 303 | ||
| 295 | enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name) | 304 | enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name) |
| @@ -300,7 +309,7 @@ enum vm_mem_backing_src_type parse_backing_src_type(const char *type_name) · 4 unmodified lines | |||
| 300 | if (!strcmp(type_name, vm_mem_backing_src_alias(i)->name)) | 309 | if (!strcmp(type_name, vm_mem_backing_src_alias(i)->name)) |
| 301 | return i; | 310 | return i; |
| 302 | 311 | ||
| 303 | backing_src_help(); | 312 | print_available_backing_src_types(""); |
| 304 | TEST_FAIL("Unknown backing src type: %s", type_name); | 313 | TEST_FAIL("Unknown backing src type: %s", type_name); |
| 305 | return -1; | 314 | return -1; |
| 306 | } | 315 | } |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <signal.h> | 10 | #include <signal.h> |
| 11 | #include <syscall.h> | 11 | #include <syscall.h> |
| 12 | #include <sys/ioctl.h> | 12 | #include <sys/ioctl.h> |
| 13 | #include <sys/sysinfo.h> | ||
| 13 | #include <asm/barrier.h> | 14 | #include <asm/barrier.h> |
| 14 | #include <linux/atomic.h> | 15 | #include <linux/atomic.h> |
| 15 | #include <linux/rseq.h> | 16 | #include <linux/rseq.h> |
| @@ -39,6 +40,7 @@ static __thread volatile struct rseq __rseq = { · 23 unmodified lines | |||
| 39 | 40 | ||
| 40 | static pthread_t migration_thread; | 41 | static pthread_t migration_thread; |
| 41 | static cpu_set_t possible_mask; | 42 | static cpu_set_t possible_mask; |
| 43 | static int min_cpu, max_cpu; | ||
| 42 | static bool done; | 44 | static bool done; |
| 43 | 45 | ||
| 44 | static atomic_t seq_cnt; | 46 | static atomic_t seq_cnt; |
| @@ -57,20 +59,37 @@ static void sys_rseq(int flags) · 12 unmodified lines | |||
| 57 | TEST_ASSERT(!r, "rseq failed, errno = %d (%s)", errno, strerror(errno)); | 59 | TEST_ASSERT(!r, "rseq failed, errno = %d (%s)", errno, strerror(errno)); |
| 58 | } | 60 | } |
| 59 | 61 | ||
| 62 | static int next_cpu(int cpu) | ||
| 63 | { | ||
| 64 | /* | ||
| 65 | * Advance to the next CPU, skipping those that weren't in the original | ||
| 66 | * affinity set. Sadly, there is no CPU_SET_FOR_EACH, and cpu_set_t's | ||
| 67 | * data storage is considered as opaque. Note, if this task is pinned | ||
| 68 | * to a small set of discontigous CPUs, e.g. 2 and 1023, this loop will | ||
| 69 | * burn a lot cycles and the test will take longer than normal to | ||
| 70 | * complete. | ||
| 71 | */ | ||
| 72 | do { | ||
| 73 | cpu++; | ||
| 74 | if (cpu > max_cpu) { | ||
| 75 | cpu = min_cpu; | ||
| 76 | TEST_ASSERT(CPU_ISSET(cpu, &possible_mask), | ||
| 77 | "Min CPU = %d must always be usable", cpu); | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | } while (!CPU_ISSET(cpu, &possible_mask)); | ||
| 81 | |||
| 82 | return cpu; | ||
| 83 | } | ||
| 84 | |||
| 60 | static void *migration_worker(void *ign) | 85 | static void *migration_worker(void *ign) |
| 61 | { | 86 | { |
| 62 | cpu_set_t allowed_mask; | 87 | cpu_set_t allowed_mask; |
| 63 | int r, i, nr_cpus, cpu; | 88 | int r, i, cpu; |
| 64 | 89 | ||
| 65 | CPU_ZERO(&allowed_mask); | 90 | CPU_ZERO(&allowed_mask); |
| 66 | 91 | ||
| 67 | nr_cpus = CPU_COUNT(&possible_mask); | 92 | for (i = 0, cpu = min_cpu; i < NR_TASK_MIGRATIONS; i++, cpu = next_cpu(cpu)) { |
| 68 | |||
| 69 | for (i = 0; i < NR_TASK_MIGRATIONS; i++) { | ||
| 70 | cpu = i % nr_cpus; | ||
| 71 | if (!CPU_ISSET(cpu, &possible_mask)) | ||
| 72 | continue; | ||
| 73 | |||
| 74 | CPU_SET(cpu, &allowed_mask); | 93 | CPU_SET(cpu, &allowed_mask); |
| 75 | 94 | ||
| 76 | /* | 95 | /* |
| @@ -154,6 +173,36 @@ static void *migration_worker(void *ign) · 77 unmodified lines | |||
| 154 | return NULL; | 173 | return NULL; |
| 155 | } | 174 | } |
| 156 | 175 | ||
| 176 | static int calc_min_max_cpu(void) | ||
| 177 | { | ||
| 178 | int i, cnt, nproc; | ||
| 179 | |||
| 180 | if (CPU_COUNT(&possible_mask) < 2) | ||
| 181 | return -EINVAL; | ||
| 182 | |||
| 183 | /* | ||
| 184 | * CPU_SET doesn't provide a FOR_EACH helper, get the min/max CPU that | ||
| 185 | * this task is affined to in order to reduce the time spent querying | ||
| 186 | * unusable CPUs, e.g. if this task is pinned to a small percentage of | ||
| 187 | * total CPUs. | ||
| 188 | */ | ||
| 189 | nproc = get_nprocs_conf(); | ||
| 190 | min_cpu = -1; | ||
| 191 | max_cpu = -1; | ||
| 192 | cnt = 0; | ||
| 193 | |||
| 194 | for (i = 0; i < nproc; i++) { | ||
| 195 | if (!CPU_ISSET(i, &possible_mask)) | ||
| 196 | continue; | ||
| 197 | if (min_cpu == -1) | ||
| 198 | min_cpu = i; | ||
| 199 | max_cpu = i; | ||
| 200 | cnt++; | ||
| 201 | } | ||
| 202 | |||
| 203 | return (cnt < 2) ? -EINVAL : 0; | ||
| 204 | } | ||
| 205 | |||
| 157 | int main(int argc, char *argv[]) | 206 | int main(int argc, char *argv[]) |
| 158 | { | 207 | { |
| 159 | int r, i, snapshot; | 208 | int r, i, snapshot; |
| @@ -167,8 +216,8 @@ int main(int argc, char *argv[]) · 7 unmodified lines | |||
| 167 | TEST_ASSERT(!r, "sched_getaffinity failed, errno = %d (%s)", errno, | 216 | TEST_ASSERT(!r, "sched_getaffinity failed, errno = %d (%s)", errno, |
| 168 | strerror(errno)); | 217 | strerror(errno)); |
| 169 | 218 | ||
| 170 | if (CPU_COUNT(&possible_mask) < 2) { | 219 | if (calc_min_max_cpu()) { |
| 171 | print_skip("Only one CPU, task migration not possible\n"); | 220 | print_skip("Only one usable CPU, task migration not possible"); |
| 172 | exit(KSFT_SKIP); | 221 | exit(KSFT_SKIP); |
| 173 | } | 222 | } |
| 174 | 223 | ||
| @@ -180,6 +229,7 @@ int main(int argc, char *argv[]) · 5 unmodified lines | |||
| 180 | * CPU affinity. | 229 | * CPU affinity. |
| 181 | */ | 230 | */ |
| 182 | vm = vm_create_default(VCPU_ID, 0, guest_code); | 231 | vm = vm_create_default(VCPU_ID, 0, guest_code); |
| 232 | ucall_init(vm, NULL); | ||
| 183 | 233 | ||
| 184 | pthread_create(&migration_thread, NULL, migration_worker, 0); | 234 | pthread_create(&migration_thread, NULL, migration_worker, 0); |
| 185 | 235 | ||
| @@ -116,12 +116,12 @@ struct st_time { · 115 unmodified lines | |||
| 116 | uint64_t st_time; | 116 | uint64_t st_time; |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | static int64_t smccc(uint32_t func, uint32_t arg) | 119 | static int64_t smccc(uint32_t func, uint64_t arg) |
| 120 | { | 120 | { |
| 121 | unsigned long ret; | 121 | unsigned long ret; |
| 122 | 122 | ||
| 123 | asm volatile( | 123 | asm volatile( |
| 124 | "mov x0, %1\n" | 124 | "mov w0, %w1\n" |
| 125 | "mov x1, %2\n" | 125 | "mov x1, %2\n" |
| 126 | "hvc #0\n" | 126 | "hvc #0\n" |
| 127 | "mov %0, x0\n" | 127 | "mov %0, x0\n" |
| @@ -0,0 +1,128 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * svm_int_ctl_test | ||
| 4 | * | ||
| 5 | * Copyright (C) 2021, Red Hat, Inc. | ||
| 6 | * | ||
| 7 | * Nested SVM testing: test simultaneous use of V_IRQ from L1 and L0. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include "test_util.h" | ||
| 11 | #include "kvm_util.h" | ||
| 12 | #include "processor.h" | ||
| 13 | #include "svm_util.h" | ||
| 14 | #include "apic.h" | ||
| 15 | |||
| 16 | #define VCPU_ID 0 | ||
| 17 | |||
| 18 | static struct kvm_vm *vm; | ||
| 19 | |||
| 20 | bool vintr_irq_called; | ||
| 21 | bool intr_irq_called; | ||
| 22 | |||
| 23 | #define VINTR_IRQ_NUMBER 0x20 | ||
| 24 | #define INTR_IRQ_NUMBER 0x30 | ||
| 25 | |||
| 26 | static void vintr_irq_handler(struct ex_regs *regs) | ||
| 27 | { | ||
| 28 | vintr_irq_called = true; | ||
| 29 | } | ||
| 30 | |||
| 31 | static void intr_irq_handler(struct ex_regs *regs) | ||
| 32 | { | ||
| 33 | x2apic_write_reg(APIC_EOI, 0x00); | ||
| 34 | intr_irq_called = true; | ||
| 35 | } | ||
| 36 | |||
| 37 | static void l2_guest_code(struct svm_test_data *svm) | ||
| 38 | { | ||
| 39 | /* This code raises interrupt INTR_IRQ_NUMBER in the L1's LAPIC, | ||
| 40 | * and since L1 didn't enable virtual interrupt masking, | ||
| 41 | * L2 should receive it and not L1. | ||
| 42 | * | ||
| 43 | * L2 also has virtual interrupt 'VINTR_IRQ_NUMBER' pending in V_IRQ | ||
| 44 | * so it should also receive it after the following 'sti'. | ||
| 45 | */ | ||
| 46 | x2apic_write_reg(APIC_ICR, | ||
| 47 | APIC_DEST_SELF | APIC_INT_ASSERT | INTR_IRQ_NUMBER); | ||
| 48 | |||
| 49 | __asm__ __volatile__( | ||
| 50 | "sti\n" | ||
| 51 | "nop\n" | ||
| 52 | ); | ||
| 53 | |||
| 54 | GUEST_ASSERT(vintr_irq_called); | ||
| 55 | GUEST_ASSERT(intr_irq_called); | ||
| 56 | |||
| 57 | __asm__ __volatile__( | ||
| 58 | "vmcall\n" | ||
| 59 | ); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void l1_guest_code(struct svm_test_data *svm) | ||
| 63 | { | ||
| 64 | #define L2_GUEST_STACK_SIZE 64 | ||
| 65 | unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; | ||
| 66 | struct vmcb *vmcb = svm->vmcb; | ||
| 67 | |||
| 68 | x2apic_enable(); | ||
| 69 | |||
| 70 | /* Prepare for L2 execution. */ | ||
| 71 | generic_svm_setup(svm, l2_guest_code, | ||
| 72 | &l2_guest_stack[L2_GUEST_STACK_SIZE]); | ||
| 73 | |||
| 74 | /* No virtual interrupt masking */ | ||
| 75 | vmcb->control.int_ctl &= ~V_INTR_MASKING_MASK; | ||
| 76 | |||
| 77 | /* No intercepts for real and virtual interrupts */ | ||
| 78 | vmcb->control.intercept &= ~(1ULL << INTERCEPT_INTR | INTERCEPT_VINTR); | ||
| 79 | |||
| 80 | /* Make a virtual interrupt VINTR_IRQ_NUMBER pending */ | ||
| 81 | vmcb->control.int_ctl |= V_IRQ_MASK | (0x1 << V_INTR_PRIO_SHIFT); | ||
| 82 | vmcb->control.int_vector = VINTR_IRQ_NUMBER; | ||
| 83 | |||
| 84 | run_guest(vmcb, svm->vmcb_gpa); | ||
| 85 | GUEST_ASSERT(vmcb->control.exit_code == SVM_EXIT_VMMCALL); | ||
| 86 | GUEST_DONE(); | ||
| 87 | } | ||
| 88 | |||
| 89 | int main(int argc, char *argv[]) | ||
| 90 | { | ||
| 91 | vm_vaddr_t svm_gva; | ||
| 92 | |||
| 93 | nested_svm_check_supported(); | ||
| 94 | |||
| 95 | vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code); | ||
| 96 | |||
| 97 | vm_init_descriptor_tables(vm); | ||
| 98 | vcpu_init_descriptor_tables(vm, VCPU_ID); | ||
| 99 | |||
| 100 | vm_install_exception_handler(vm, VINTR_IRQ_NUMBER, vintr_irq_handler); | ||
| 101 | vm_install_exception_handler(vm, INTR_IRQ_NUMBER, intr_irq_handler); | ||
| 102 | |||
| 103 | vcpu_alloc_svm(vm, &svm_gva); | ||
| 104 | vcpu_args_set(vm, VCPU_ID, 1, svm_gva); | ||
| 105 | |||
| 106 | struct kvm_run *run = vcpu_state(vm, VCPU_ID); | ||
| 107 | struct ucall uc; | ||
| 108 | |||
| 109 | vcpu_run(vm, VCPU_ID); | ||
| 110 | TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, | ||
| 111 | "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n", | ||
| 112 | run->exit_reason, | ||
| 113 | exit_reason_str(run->exit_reason)); | ||
| 114 | |||
| 115 | switch (get_ucall(vm, VCPU_ID, &uc)) { | ||
| 116 | case UCALL_ABORT: | ||
| 117 | TEST_FAIL("%s", (const char *)uc.args[0]); | ||
| 118 | break; | ||
| 119 | /* NOT REACHED */ | ||
| 120 | case UCALL_DONE: | ||
| 121 | goto done; | ||
| 122 | default: | ||
| 123 | TEST_FAIL("Unknown ucall 0x%lx.", uc.cmd); | ||
| 124 | } | ||
| 125 | done: | ||
| 126 | kvm_vm_free(vm); | ||
| 127 | return 0; | ||
| 128 | } | ||
| @@ -0,0 +1,309 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | # | ||
| 3 | # Test connection tracking zone and NAT source port reallocation support. | ||
| 4 | # | ||
| 5 | |||
| 6 | # Kselftest framework requirement - SKIP code is 4. | ||
| 7 | ksft_skip=4 | ||
| 8 | |||
| 9 | # Don't increase too much, 2000 clients should work | ||
| 10 | # just fine but script can then take several minutes with | ||
| 11 | # KASAN/debug builds. | ||
| 12 | maxclients=100 | ||
| 13 | |||
| 14 | have_iperf=1 | ||
| 15 | ret=0 | ||
| 16 | |||
| 17 | # client1---. | ||
| 18 | # veth1-. | ||
| 19 | # | | ||
| 20 | # NAT Gateway --veth0--> Server | ||
| 21 | # | | | ||
| 22 | # veth2-' | | ||
| 23 | # client2---' | | ||
| 24 | # .... | | ||
| 25 | # clientX----vethX---' | ||
| 26 | |||
| 27 | # All clients share identical IP address. | ||
| 28 | # NAT Gateway uses policy routing and conntrack zones to isolate client | ||
| 29 | # namespaces. Each client connects to Server, each with colliding tuples: | ||
| 30 | # clientsaddr:10000 -> serveraddr:dport | ||
| 31 | # NAT Gateway is supposed to do port reallocation for each of the | ||
| 32 | # connections. | ||
| 33 | |||
| 34 | sfx=$(mktemp -u "XXXXXXXX") | ||
| 35 | gw="ns-gw-$sfx" | ||
| 36 | cl1="ns-cl1-$sfx" | ||
| 37 | cl2="ns-cl2-$sfx" | ||
| 38 | srv="ns-srv-$sfx" | ||
| 39 | |||
| 40 | v4gc1=$(sysctl -n net.ipv4.neigh.default.gc_thresh1 2>/dev/null) | ||
| 41 | v4gc2=$(sysctl -n net.ipv4.neigh.default.gc_thresh2 2>/dev/null) | ||
| 42 | v4gc3=$(sysctl -n net.ipv4.neigh.default.gc_thresh3 2>/dev/null) | ||
| 43 | v6gc1=$(sysctl -n net.ipv6.neigh.default.gc_thresh1 2>/dev/null) | ||
| 44 | v6gc2=$(sysctl -n net.ipv6.neigh.default.gc_thresh2 2>/dev/null) | ||
| 45 | v6gc3=$(sysctl -n net.ipv6.neigh.default.gc_thresh3 2>/dev/null) | ||
| 46 | |||
| 47 | cleanup() | ||
| 48 | { | ||
| 49 | ip netns del $gw | ||
| 50 | ip netns del $srv | ||
| 51 | for i in $(seq 1 $maxclients); do | ||
| 52 | ip netns del ns-cl$i-$sfx 2>/dev/null | ||
| 53 | done | ||
| 54 | |||
| 55 | sysctl -q net.ipv4.neigh.default.gc_thresh1=$v4gc1 2>/dev/null | ||
| 56 | sysctl -q net.ipv4.neigh.default.gc_thresh2=$v4gc2 2>/dev/null | ||
| 57 | sysctl -q net.ipv4.neigh.default.gc_thresh3=$v4gc3 2>/dev/null | ||
| 58 | sysctl -q net.ipv6.neigh.default.gc_thresh1=$v6gc1 2>/dev/null | ||
| 59 | sysctl -q net.ipv6.neigh.default.gc_thresh2=$v6gc2 2>/dev/null | ||
| 60 | sysctl -q net.ipv6.neigh.default.gc_thresh3=$v6gc3 2>/dev/null | ||
| 61 | } | ||
| 62 | |||
| 63 | nft --version > /dev/null 2>&1 | ||
| 64 | if [ $? -ne 0 ];then | ||
| 65 | echo "SKIP: Could not run test without nft tool" | ||
| 66 | exit $ksft_skip | ||
| 67 | fi | ||
| 68 | |||
| 69 | ip -Version > /dev/null 2>&1 | ||
| 70 | if [ $? -ne 0 ];then | ||
| 71 | echo "SKIP: Could not run test without ip tool" | ||
| 72 | exit $ksft_skip | ||
| 73 | fi | ||
| 74 | |||
| 75 | conntrack -V > /dev/null 2>&1 | ||
| 76 | if [ $? -ne 0 ];then | ||
| 77 | echo "SKIP: Could not run test without conntrack tool" | ||
| 78 | exit $ksft_skip | ||
| 79 | fi | ||
| 80 | |||
| 81 | iperf3 -v >/dev/null 2>&1 | ||
| 82 | if [ $? -ne 0 ];then | ||
| 83 | have_iperf=0 | ||
| 84 | fi | ||
| 85 | |||
| 86 | ip netns add "$gw" | ||
| 87 | if [ $? -ne 0 ];then | ||
| 88 | echo "SKIP: Could not create net namespace $gw" | ||
| 89 | exit $ksft_skip | ||
| 90 | fi | ||
| 91 | ip -net "$gw" link set lo up | ||
| 92 | |||
| 93 | trap cleanup EXIT | ||
| 94 | |||
| 95 | ip netns add "$srv" | ||
| 96 | if [ $? -ne 0 ];then | ||
| 97 | echo "SKIP: Could not create server netns $srv" | ||
| 98 | exit $ksft_skip | ||
| 99 | fi | ||
| 100 | |||
| 101 | ip link add veth0 netns "$gw" type veth peer name eth0 netns "$srv" | ||
| 102 | ip -net "$gw" link set veth0 up | ||
| 103 | ip -net "$srv" link set lo up | ||
| 104 | ip -net "$srv" link set eth0 up | ||
| 105 | |||
| 106 | sysctl -q net.ipv6.neigh.default.gc_thresh1=512 2>/dev/null | ||
| 107 | sysctl -q net.ipv6.neigh.default.gc_thresh2=1024 2>/dev/null | ||
| 108 | sysctl -q net.ipv6.neigh.default.gc_thresh3=4096 2>/dev/null | ||
| 109 | sysctl -q net.ipv4.neigh.default.gc_thresh1=512 2>/dev/null | ||
| 110 | sysctl -q net.ipv4.neigh.default.gc_thresh2=1024 2>/dev/null | ||
| 111 | sysctl -q net.ipv4.neigh.default.gc_thresh3=4096 2>/dev/null | ||
| 112 | |||
| 113 | for i in $(seq 1 $maxclients);do | ||
| 114 | cl="ns-cl$i-$sfx" | ||
| 115 | |||
| 116 | ip netns add "$cl" | ||
| 117 | if [ $? -ne 0 ];then | ||
| 118 | echo "SKIP: Could not create client netns $cl" | ||
| 119 | exit $ksft_skip | ||
| 120 | fi | ||
| 121 | ip link add veth$i netns "$gw" type veth peer name eth0 netns "$cl" > /dev/null 2>&1 | ||
| 122 | if [ $? -ne 0 ];then | ||
| 123 | echo "SKIP: No virtual ethernet pair device support in kernel" | ||
| 124 | exit $ksft_skip | ||
| 125 | fi | ||
| 126 | done | ||
| 127 | |||
| 128 | for i in $(seq 1 $maxclients);do | ||
| 129 | cl="ns-cl$i-$sfx" | ||
| 130 | echo netns exec "$cl" ip link set lo up | ||
| 131 | echo netns exec "$cl" ip link set eth0 up | ||
| 132 | echo netns exec "$cl" sysctl -q net.ipv4.tcp_syn_retries=2 | ||
| 133 | echo netns exec "$gw" ip link set veth$i up | ||
| 134 | echo netns exec "$gw" sysctl -q net.ipv4.conf.veth$i.arp_ignore=2 | ||
| 135 | echo netns exec "$gw" sysctl -q net.ipv4.conf.veth$i.rp_filter=0 | ||
| 136 | |||
| 137 | # clients have same IP addresses. | ||
| 138 | echo netns exec "$cl" ip addr add 10.1.0.3/24 dev eth0 | ||
| 139 | echo netns exec "$cl" ip addr add dead:1::3/64 dev eth0 | ||
| 140 | echo netns exec "$cl" ip route add default via 10.1.0.2 dev eth0 | ||
| 141 | echo netns exec "$cl" ip route add default via dead:1::2 dev eth0 | ||
| 142 | |||
| 143 | # NB: same addresses on client-facing interfaces. | ||
| 144 | echo netns exec "$gw" ip addr add 10.1.0.2/24 dev veth$i | ||
| 145 | echo netns exec "$gw" ip addr add dead:1::2/64 dev veth$i | ||
| 146 | |||
| 147 | # gw: policy routing | ||
| 148 | echo netns exec "$gw" ip route add 10.1.0.0/24 dev veth$i table $((1000+i)) | ||
| 149 | echo netns exec "$gw" ip route add dead:1::0/64 dev veth$i table $((1000+i)) | ||
| 150 | echo netns exec "$gw" ip route add 10.3.0.0/24 dev veth0 table $((1000+i)) | ||
| 151 | echo netns exec "$gw" ip route add dead:3::0/64 dev veth0 table $((1000+i)) | ||
| 152 | echo netns exec "$gw" ip rule add fwmark $i lookup $((1000+i)) | ||
| 153 | done | ip -batch /dev/stdin | ||
| 154 | |||
| 155 | ip -net "$gw" addr add 10.3.0.1/24 dev veth0 | ||
| 156 | ip -net "$gw" addr add dead:3::1/64 dev veth0 | ||
| 157 | |||
| 158 | ip -net "$srv" addr add 10.3.0.99/24 dev eth0 | ||
| 159 | ip -net "$srv" addr add dead:3::99/64 dev eth0 | ||
| 160 | |||
| 161 | ip netns exec $gw nft -f /dev/stdin<<EOF | ||
| 162 | table inet raw { | ||
| 163 | map iiftomark { | ||
| 164 | type ifname : mark | ||
| 165 | } | ||
| 166 | |||
| 167 | map iiftozone { | ||
| 168 | typeof iifname : ct zone | ||
| 169 | } | ||
| 170 | |||
| 171 | set inicmp { | ||
| 172 | flags dynamic | ||
| 173 | type ipv4_addr . ifname . ipv4_addr | ||
| 174 | } | ||
| 175 | set inflows { | ||
| 176 | flags dynamic | ||
| 177 | type ipv4_addr . inet_service . ifname . ipv4_addr . inet_service | ||
| 178 | } | ||
| 179 | |||
| 180 | set inflows6 { | ||
| 181 | flags dynamic | ||
| 182 | type ipv6_addr . inet_service . ifname . ipv6_addr . inet_service | ||
| 183 | } | ||
| 184 | |||
| 185 | chain prerouting { | ||
| 186 | type filter hook prerouting priority -64000; policy accept; | ||
| 187 | ct original zone set meta iifname map @iiftozone | ||
| 188 | meta mark set meta iifname map @iiftomark | ||
| 189 | |||
| 190 | tcp flags & (syn|ack) == ack add @inflows { ip saddr . tcp sport . meta iifname . ip daddr . tcp dport counter } | ||
| 191 | add @inflows6 { ip6 saddr . tcp sport . meta iifname . ip6 daddr . tcp dport counter } | ||
| 192 | ip protocol icmp add @inicmp { ip saddr . meta iifname . ip daddr counter } | ||
| 193 | } | ||
| 194 | |||
| 195 | chain nat_postrouting { | ||
| 196 | type nat hook postrouting priority 0; policy accept; | ||
| 197 | ct mark set meta mark meta oifname veth0 masquerade | ||
| 198 | } | ||
| 199 | |||
| 200 | chain mangle_prerouting { | ||
| 201 | type filter hook prerouting priority -100; policy accept; | ||
| 202 | ct direction reply meta mark set ct mark | ||
| 203 | } | ||
| 204 | } | ||
| 205 | EOF | ||
| 206 | |||
| 207 | ( echo add element inet raw iiftomark \{ | ||
| 208 | for i in $(seq 1 $((maxclients-1))); do | ||
| 209 | echo \"veth$i\" : $i, | ||
| 210 | done | ||
| 211 | echo \"veth$maxclients\" : $maxclients \} | ||
| 212 | echo add element inet raw iiftozone \{ | ||
| 213 | for i in $(seq 1 $((maxclients-1))); do | ||
| 214 | echo \"veth$i\" : $i, | ||
| 215 | done | ||
| 216 | echo \"veth$maxclients\" : $maxclients \} | ||
| 217 | ) | ip netns exec $gw nft -f /dev/stdin | ||
| 218 | |||
| 219 | ip netns exec "$gw" sysctl -q net.ipv4.conf.all.forwarding=1 > /dev/null | ||
| 220 | ip netns exec "$gw" sysctl -q net.ipv6.conf.all.forwarding=1 > /dev/null | ||
| 221 | ip netns exec "$gw" sysctl -q net.ipv4.conf.all.rp_filter=0 >/dev/null | ||
| 222 | |||
| 223 | # useful for debugging: allows to use 'ping' from clients to gateway. | ||
| 224 | ip netns exec "$gw" sysctl -q net.ipv4.fwmark_reflect=1 > /dev/null | ||
| 225 | ip netns exec "$gw" sysctl -q net.ipv6.fwmark_reflect=1 > /dev/null | ||
| 226 | |||
| 227 | for i in $(seq 1 $maxclients); do | ||
| 228 | cl="ns-cl$i-$sfx" | ||
| 229 | ip netns exec $cl ping -i 0.5 -q -c 3 10.3.0.99 > /dev/null 2>&1 & | ||
| 230 | if [ $? -ne 0 ]; then | ||
| 231 | echo FAIL: Ping failure from $cl 1>&2 | ||
| 232 | ret=1 | ||
| 233 | break | ||
| 234 | fi | ||
| 235 | done | ||
| 236 | |||
| 237 | wait | ||
| 238 | |||
| 239 | for i in $(seq 1 $maxclients); do | ||
| 240 | ip netns exec $gw nft get element inet raw inicmp "{ 10.1.0.3 . \"veth$i\" . 10.3.0.99 }" | grep -q "{ 10.1.0.3 . \"veth$i\" . 10.3.0.99 counter packets 3 bytes 252 }" | ||
| 241 | if [ $? -ne 0 ];then | ||
| 242 | ret=1 | ||
| 243 | echo "FAIL: counter icmp mismatch for veth$i" 1>&2 | ||
| 244 | ip netns exec $gw nft get element inet raw inicmp "{ 10.1.0.3 . \"veth$i\" . 10.3.0.99 }" 1>&2 | ||
| 245 | break | ||
| 246 | fi | ||
| 247 | done | ||
| 248 | |||
| 249 | ip netns exec $gw nft get element inet raw inicmp "{ 10.3.0.99 . \"veth0\" . 10.3.0.1 }" | grep -q "{ 10.3.0.99 . \"veth0\" . 10.3.0.1 counter packets $((3 * $maxclients)) bytes $((252 * $maxclients)) }" | ||
| 250 | if [ $? -ne 0 ];then | ||
| 251 | ret=1 | ||
| 252 | echo "FAIL: counter icmp mismatch for veth0: { 10.3.0.99 . \"veth0\" . 10.3.0.1 counter packets $((3 * $maxclients)) bytes $((252 * $maxclients)) }" | ||
| 253 | ip netns exec $gw nft get element inet raw inicmp "{ 10.3.99 . \"veth0\" . 10.3.0.1 }" 1>&2 | ||
| 254 | fi | ||
| 255 | |||
| 256 | if [ $ret -eq 0 ]; then | ||
| 257 | echo "PASS: ping test from all $maxclients namespaces" | ||
| 258 | fi | ||
| 259 | |||
| 260 | if [ $have_iperf -eq 0 ];then | ||
| 261 | echo "SKIP: iperf3 not installed" | ||
| 262 | if [ $ret -ne 0 ];then | ||
| 263 | exit $ret | ||
| 264 | fi | ||
| 265 | exit $ksft_skip | ||
| 266 | fi | ||
| 267 | |||
| 268 | ip netns exec $srv iperf3 -s > /dev/null 2>&1 & | ||
| 269 | iperfpid=$! | ||
| 270 | sleep 1 | ||
| 271 | |||
| 272 | for i in $(seq 1 $maxclients); do | ||
| 273 | if [ $ret -ne 0 ]; then | ||
| 274 | break | ||
| 275 | fi | ||
| 276 | cl="ns-cl$i-$sfx" | ||
| 277 | ip netns exec $cl iperf3 -c 10.3.0.99 --cport 10000 -n 1 > /dev/null | ||
| 278 | if [ $? -ne 0 ]; then | ||
| 279 | echo FAIL: Failure to connect for $cl 1>&2 | ||
| 280 | ip netns exec $gw conntrack -S 1>&2 | ||
| 281 | ret=1 | ||
| 282 | fi | ||
| 283 | done | ||
| 284 | if [ $ret -eq 0 ];then | ||
| 285 | echo "PASS: iperf3 connections for all $maxclients net namespaces" | ||
| 286 | fi | ||
| 287 | |||
| 288 | kill $iperfpid | ||
| 289 | wait | ||
| 290 | |||
| 291 | for i in $(seq 1 $maxclients); do | ||
| 292 | ip netns exec $gw nft get element inet raw inflows "{ 10.1.0.3 . 10000 . \"veth$i\" . 10.3.0.99 . 5201 }" > /dev/null | ||
| 293 | if [ $? -ne 0 ];then | ||
| 294 | ret=1 | ||
| 295 | echo "FAIL: can't find expected tcp entry for veth$i" 1>&2 | ||
| 296 | break | ||
| 297 | fi | ||
| 298 | done | ||
| 299 | if [ $ret -eq 0 ];then | ||
| 300 | echo "PASS: Found client connection for all $maxclients net namespaces" | ||
| 301 | fi | ||
| 302 | |||
| 303 | ip netns exec $gw nft get element inet raw inflows "{ 10.3.0.99 . 5201 . \"veth0\" . 10.3.0.1 . 10000 }" > /dev/null | ||
| 304 | if [ $? -ne 0 ];then | ||
| 305 | ret=1 | ||
| 306 | echo "FAIL: cannot find return entry on veth0" 1>&2 | ||
| 307 | fi | ||
| 308 | |||
| 309 | exit $ret | ||
| @@ -0,0 +1,156 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | |||
| 3 | # Test insertion speed for packets with identical addresses/ports | ||
| 4 | # that are all placed in distinct conntrack zones. | ||
| 5 | |||
| 6 | sfx=$(mktemp -u "XXXXXXXX") | ||
| 7 | ns="ns-$sfx" | ||
| 8 | |||
| 9 | # Kselftest framework requirement - SKIP code is 4. | ||
| 10 | ksft_skip=4 | ||
| 11 | |||
| 12 | zones=20000 | ||
| 13 | have_ct_tool=0 | ||
| 14 | ret=0 | ||
| 15 | |||
| 16 | cleanup() | ||
| 17 | { | ||
| 18 | ip netns del $ns | ||
| 19 | } | ||
| 20 | |||
| 21 | ip netns add $ns | ||
| 22 | if [ $? -ne 0 ];then | ||
| 23 | echo "SKIP: Could not create net namespace $gw" | ||
| 24 | exit $ksft_skip | ||
| 25 | fi | ||
| 26 | |||
| 27 | trap cleanup EXIT | ||
| 28 | |||
| 29 | conntrack -V > /dev/null 2>&1 | ||
| 30 | if [ $? -eq 0 ];then | ||
| 31 | have_ct_tool=1 | ||
| 32 | fi | ||
| 33 | |||
| 34 | ip -net "$ns" link set lo up | ||
| 35 | |||
| 36 | test_zones() { | ||
| 37 | local max_zones=$1 | ||
| 38 | |||
| 39 | ip netns exec $ns sysctl -q net.netfilter.nf_conntrack_udp_timeout=3600 | ||
| 40 | ip netns exec $ns nft -f /dev/stdin<<EOF | ||
| 41 | flush ruleset | ||
| 42 | table inet raw { | ||
| 43 | map rndzone { | ||
| 44 | typeof numgen inc mod $max_zones : ct zone | ||
| 45 | } | ||
| 46 | |||
| 47 | chain output { | ||
| 48 | type filter hook output priority -64000; policy accept; | ||
| 49 | udp dport 12345 ct zone set numgen inc mod 65536 map @rndzone | ||
| 50 | } | ||
| 51 | } | ||
| 52 | EOF | ||
| 53 | ( | ||
| 54 | echo "add element inet raw rndzone {" | ||
| 55 | for i in $(seq 1 $max_zones);do | ||
| 56 | echo -n "$i : $i" | ||
| 57 | if [ $i -lt $max_zones ]; then | ||
| 58 | echo "," | ||
| 59 | else | ||
| 60 | echo "}" | ||
| 61 | fi | ||
| 62 | done | ||
| 63 | ) | ip netns exec $ns nft -f /dev/stdin | ||
| 64 | |||
| 65 | local i=0 | ||
| 66 | local j=0 | ||
| 67 | local outerstart=$(date +%s%3N) | ||
| 68 | local stop=$outerstart | ||
| 69 | |||
| 70 | while [ $i -lt $max_zones ]; do | ||
| 71 | local start=$(date +%s%3N) | ||
| 72 | i=$((i + 10000)) | ||
| 73 | j=$((j + 1)) | ||
| 74 | dd if=/dev/zero of=/dev/stdout bs=8k count=10000 2>/dev/null | ip netns exec "$ns" nc -w 1 -q 1 -u -p 12345 127.0.0.1 12345 > /dev/null | ||
| 75 | if [ $? -ne 0 ] ;then | ||
| 76 | ret=1 | ||
| 77 | break | ||
| 78 | fi | ||
| 79 | |||
| 80 | stop=$(date +%s%3N) | ||
| 81 | local duration=$((stop-start)) | ||
| 82 | echo "PASS: added 10000 entries in $duration ms (now $i total, loop $j)" | ||
| 83 | done | ||
| 84 | |||
| 85 | if [ $have_ct_tool -eq 1 ]; then | ||
| 86 | local count=$(ip netns exec "$ns" conntrack -C) | ||
| 87 | local duration=$((stop-outerstart)) | ||
| 88 | |||
| 89 | if [ $count -eq $max_zones ]; then | ||
| 90 | echo "PASS: inserted $count entries from packet path in $duration ms total" | ||
| 91 | else | ||
| 92 | ip netns exec $ns conntrack -S 1>&2 | ||
| 93 | echo "FAIL: inserted $count entries from packet path in $duration ms total, expected $max_zones entries" | ||
| 94 | ret=1 | ||
| 95 | fi | ||
| 96 | fi | ||
| 97 | |||
| 98 | if [ $ret -ne 0 ];then | ||
| 99 | echo "FAIL: insert $max_zones entries from packet path" 1>&2 | ||
| 100 | fi | ||
| 101 | } | ||
| 102 | |||
| 103 | test_conntrack_tool() { | ||
| 104 | local max_zones=$1 | ||
| 105 | |||
| 106 | ip netns exec $ns conntrack -F >/dev/null 2>/dev/null | ||
| 107 | |||
| 108 | local outerstart=$(date +%s%3N) | ||
| 109 | local start=$(date +%s%3N) | ||
| 110 | local stop=$start | ||
| 111 | local i=0 | ||
| 112 | while [ $i -lt $max_zones ]; do | ||
| 113 | i=$((i + 1)) | ||
| 114 | ip netns exec "$ns" conntrack -I -s 1.1.1.1 -d 2.2.2.2 --protonum 6 \ | ||
| 115 | --timeout 3600 --state ESTABLISHED --sport 12345 --dport 1000 --zone $i >/dev/null 2>&1 | ||
| 116 | if [ $? -ne 0 ];then | ||
| 117 | ip netns exec "$ns" conntrack -I -s 1.1.1.1 -d 2.2.2.2 --protonum 6 \ | ||
| 118 | --timeout 3600 --state ESTABLISHED --sport 12345 --dport 1000 --zone $i > /dev/null | ||
| 119 | echo "FAIL: conntrack -I returned an error" | ||
| 120 | ret=1 | ||
| 121 | break | ||
| 122 | fi | ||
| 123 | |||
| 124 | if [ $((i%10000)) -eq 0 ];then | ||
| 125 | stop=$(date +%s%3N) | ||
| 126 | |||
| 127 | local duration=$((stop-start)) | ||
| 128 | echo "PASS: added 10000 entries in $duration ms (now $i total)" | ||
| 129 | start=$stop | ||
| 130 | fi | ||
| 131 | done | ||
| 132 | |||
| 133 | local count=$(ip netns exec "$ns" conntrack -C) | ||
| 134 | local duration=$((stop-outerstart)) | ||
| 135 | |||
| 136 | if [ $count -eq $max_zones ]; then | ||
| 137 | echo "PASS: inserted $count entries via ctnetlink in $duration ms" | ||
| 138 | else | ||
| 139 | ip netns exec $ns conntrack -S 1>&2 | ||
| 140 | echo "FAIL: inserted $count entries via ctnetlink in $duration ms, expected $max_zones entries ($duration ms)" | ||
| 141 | ret=1 | ||
| 142 | fi | ||
| 143 | } | ||
| 144 | |||
| 145 | test_zones $zones | ||
| 146 | |||
| 147 | if [ $have_ct_tool -eq 1 ];then | ||
| 148 | test_conntrack_tool $zones | ||
| 149 | else | ||
| 150 | echo "SKIP: Could not run ctnetlink insertion test without conntrack tool" | ||
| 151 | if [ $ret -eq 0 ];then | ||
| 152 | exit $ksft_skip | ||
| 153 | fi | ||
| 154 | fi | ||
| 155 | |||
| 156 | exit $ret | ||
| @@ -235,9 +235,13 @@ static void ack_flush(void *_completed) · 234 unmodified lines | |||
| 235 | { | 235 | { |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | static inline bool kvm_kick_many_cpus(const struct cpumask *cpus, bool wait) | 238 | static inline bool kvm_kick_many_cpus(cpumask_var_t tmp, bool wait) |
| 239 | { | 239 | { |
| 240 | if (unlikely(!cpus)) | 240 | const struct cpumask *cpus; |
| 241 | |||
| 242 | if (likely(cpumask_available(tmp))) | ||
| 243 | cpus = tmp; | ||
| 244 | else | ||
| 241 | cpus = cpu_online_mask; | 245 | cpus = cpu_online_mask; |
| 242 | 246 | ||
| 243 | if (cpumask_empty(cpus)) | 247 | if (cpumask_empty(cpus)) |
| @@ -263,14 +267,34 @@ bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req, · 19 unmodified lines | |||
| 263 | continue; | 267 | continue; |
| 264 | 268 | ||
| 265 | kvm_make_request(req, vcpu); | 269 | kvm_make_request(req, vcpu); |
| 266 | cpu = vcpu->cpu; | ||
| 267 | 270 | ||
| 268 | if (!(req & KVM_REQUEST_NO_WAKEUP) && kvm_vcpu_wake_up(vcpu)) | 271 | if (!(req & KVM_REQUEST_NO_WAKEUP) && kvm_vcpu_wake_up(vcpu)) |
| 269 | continue; | 272 | continue; |
| 270 | 273 | ||
| 271 | if (tmp != NULL && cpu != -1 && cpu != me && | 274 | /* |
| 272 | kvm_request_needs_ipi(vcpu, req)) | 275 | * tmp can be "unavailable" if cpumasks are allocated off stack |
| 273 | __cpumask_set_cpu(cpu, tmp); | 276 | * as allocation of the mask is deliberately not fatal and is |
| 277 | * handled by falling back to kicking all online CPUs. | ||
| 278 | */ | ||
| 279 | if (!cpumask_available(tmp)) | ||
| 280 | continue; | ||
| 281 | |||
| 282 | /* | ||
| 283 | * Note, the vCPU could get migrated to a different pCPU at any | ||
| 284 | * point after kvm_request_needs_ipi(), which could result in | ||
| 285 | * sending an IPI to the previous pCPU. But, that's ok because | ||
| 286 | * the purpose of the IPI is to ensure the vCPU returns to | ||
| 287 | * OUTSIDE_GUEST_MODE, which is satisfied if the vCPU migrates. | ||
| 288 | * Entering READING_SHADOW_PAGE_TABLES after this point is also | ||
| 289 | * ok, as the requirement is only that KVM wait for vCPUs that | ||
| 290 | * were reading SPTEs _before_ any changes were finalized. See | ||
| 291 | * kvm_vcpu_kick() for more details on handling requests. | ||
| 292 | */ | ||
| 293 | if (kvm_request_needs_ipi(vcpu, req)) { | ||
| 294 | cpu = READ_ONCE(vcpu->cpu); | ||
| 295 | if (cpu != -1 && cpu != me) | ||
| 296 | __cpumask_set_cpu(cpu, tmp); | ||
| 297 | } | ||
| 274 | } | 298 | } |
| 275 | 299 | ||
| 276 | called = kvm_kick_many_cpus(tmp, !!(req & KVM_REQUEST_WAIT)); | 300 | called = kvm_kick_many_cpus(tmp, !!(req & KVM_REQUEST_WAIT)); |
| @@ -302,13 +326,8 @@ EXPORT_SYMBOL_GPL(kvm_make_all_cpus_request); · 25 unmodified lines | |||
| 302 | #ifndef CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL | 326 | #ifndef CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL |
| 303 | void kvm_flush_remote_tlbs(struct kvm *kvm) | 327 | void kvm_flush_remote_tlbs(struct kvm *kvm) |
| 304 | { | 328 | { |
| 305 | /* | ||
| 306 | * Read tlbs_dirty before setting KVM_REQ_TLB_FLUSH in | ||
| 307 | * kvm_make_all_cpus_request. | ||
| 308 | */ | ||
| 309 | long dirty_count = smp_load_acquire(&kvm->tlbs_dirty); | ||
| 310 | |||
| 311 | ++kvm->stat.generic.remote_tlb_flush_requests; | 329 | ++kvm->stat.generic.remote_tlb_flush_requests; |
| 330 | |||
| 312 | /* | 331 | /* |
| 313 | * We want to publish modifications to the page tables before reading | 332 | * We want to publish modifications to the page tables before reading |
| 314 | * mode. Pairs with a memory barrier in arch-specific code. | 333 | * mode. Pairs with a memory barrier in arch-specific code. |
| @@ -323,7 +342,6 @@ void kvm_flush_remote_tlbs(struct kvm *kvm) · 8 unmodified lines | |||
| 323 | if (!kvm_arch_flush_remote_tlb(kvm) | 342 | if (!kvm_arch_flush_remote_tlb(kvm) |
| 324 | || kvm_make_all_cpus_request(kvm, KVM_REQ_TLB_FLUSH)) | 343 | || kvm_make_all_cpus_request(kvm, KVM_REQ_TLB_FLUSH)) |
| 325 | ++kvm->stat.generic.remote_tlb_flush; | 344 | ++kvm->stat.generic.remote_tlb_flush; |
| 326 | cmpxchg(&kvm->tlbs_dirty, dirty_count, 0); | ||
| 327 | } | 345 | } |
| 328 | EXPORT_SYMBOL_GPL(kvm_flush_remote_tlbs); | 346 | EXPORT_SYMBOL_GPL(kvm_flush_remote_tlbs); |
| 329 | #endif | 347 | #endif |
| @@ -528,7 +546,7 @@ static __always_inline int __kvm_handle_hva_range(struct kvm *kvm, · 198 unmodified lines | |||
| 528 | } | 546 | } |
| 529 | } | 547 | } |
| 530 | 548 | ||
| 531 | if (range->flush_on_ret && (ret || kvm->tlbs_dirty)) | 549 | if (range->flush_on_ret && ret) |
| 532 | kvm_flush_remote_tlbs(kvm); | 550 | kvm_flush_remote_tlbs(kvm); |
| 533 | 551 | ||
| 534 | if (locked) | 552 | if (locked) |
| @@ -3134,15 +3152,19 @@ out: · 2599 unmodified lines | |||
| 3134 | 3152 | ||
| 3135 | static void shrink_halt_poll_ns(struct kvm_vcpu *vcpu) | 3153 | static void shrink_halt_poll_ns(struct kvm_vcpu *vcpu) |
| 3136 | { | 3154 | { |
| 3137 | unsigned int old, val, shrink; | 3155 | unsigned int old, val, shrink, grow_start; |
| 3138 | 3156 | ||
| 3139 | old = val = vcpu->halt_poll_ns; | 3157 | old = val = vcpu->halt_poll_ns; |
| 3140 | shrink = READ_ONCE(halt_poll_ns_shrink); | 3158 | shrink = READ_ONCE(halt_poll_ns_shrink); |
| 3159 | grow_start = READ_ONCE(halt_poll_ns_grow_start); | ||
| 3141 | if (shrink == 0) | 3160 | if (shrink == 0) |
| 3142 | val = 0; | 3161 | val = 0; |
| 3143 | else | 3162 | else |
| 3144 | val /= shrink; | 3163 | val /= shrink; |
| 3145 | 3164 | ||
| 3165 | if (val < grow_start) | ||
| 3166 | val = 0; | ||
| 3167 | |||
| 3146 | vcpu->halt_poll_ns = val; | 3168 | vcpu->halt_poll_ns = val; |
| 3147 | trace_kvm_halt_poll_ns_shrink(vcpu->vcpu_id, val, old); | 3169 | trace_kvm_halt_poll_ns_shrink(vcpu->vcpu_id, val, old); |
| 3148 | } | 3170 | } |
| @@ -3290,16 +3312,24 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_wake_up); · 141 unmodified lines | |||
| 3290 | */ | 3312 | */ |
| 3291 | void kvm_vcpu_kick(struct kvm_vcpu *vcpu) | 3313 | void kvm_vcpu_kick(struct kvm_vcpu *vcpu) |
| 3292 | { | 3314 | { |
| 3293 | int me; | 3315 | int me, cpu; |
| 3294 | int cpu = vcpu->cpu; | ||
| 3295 | 3316 | ||
| 3296 | if (kvm_vcpu_wake_up(vcpu)) | 3317 | if (kvm_vcpu_wake_up(vcpu)) |
| 3297 | return; | 3318 | return; |
| 3298 | 3319 | ||
| 3320 | /* | ||
| 3321 | * Note, the vCPU could get migrated to a different pCPU at any point | ||
| 3322 | * after kvm_arch_vcpu_should_kick(), which could result in sending an | ||
| 3323 | * IPI to the previous pCPU. But, that's ok because the purpose of the | ||
| 3324 | * IPI is to force the vCPU to leave IN_GUEST_MODE, and migrating the | ||
| 3325 | * vCPU also requires it to leave IN_GUEST_MODE. | ||
| 3326 | */ | ||
| 3299 | me = get_cpu(); | 3327 | me = get_cpu(); |
| 3300 | if (cpu != me && (unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) | 3328 | if (kvm_arch_vcpu_should_kick(vcpu)) { |
| 3301 | if (kvm_arch_vcpu_should_kick(vcpu)) | 3329 | cpu = READ_ONCE(vcpu->cpu); |
| 3330 | if (cpu != me && (unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) | ||
| 3302 | smp_send_reschedule(cpu); | 3331 | smp_send_reschedule(cpu); |
| 3332 | } | ||
| 3303 | put_cpu(); | 3333 | put_cpu(); |
| 3304 | } | 3334 | } |
| 3305 | EXPORT_SYMBOL_GPL(kvm_vcpu_kick); | 3335 | EXPORT_SYMBOL_GPL(kvm_vcpu_kick); |