We need the USB and Thunderbolt fixes in here to build on.
Unified · Split
| @@ -82,7 +82,12 @@ Description: · 81 unmodified lines | ||
| 82 | 82 | whether it resides in persistent capacity, volatile capacity, |
| 83 | 83 | or the LSA, is made permanently unavailable by whatever means |
| 84 | 84 | is appropriate for the media type. This functionality requires |
| 85 | − the device to be not be actively decoding any HPA ranges. | |
| 85 | + the device to be disabled, that is, not actively decoding any | |
| 86 | + HPA ranges. This permits avoiding explicit global CPU cache | |
| 87 | + management, relying instead for it to be done when a region | |
| 88 | + transitions between software programmed and hardware committed | |
| 89 | + states. If this file is not present, then there is no hardware | |
| 90 | + support for the operation. | |
| 86 | 91 | |
| 87 | 92 | |
| 88 | 93 | What /sys/bus/cxl/devices/memX/security/erase |
| @@ -92,7 +97,13 @@ Contact: linux-cxl@vger.kernel.org · 3 unmodified lines | ||
| 92 | 97 | Description: |
| 93 | 98 | (WO) Write a boolean 'true' string value to this attribute to |
| 94 | 99 | secure erase user data by changing the media encryption keys for |
| 95 | − all user data areas of the device. | |
| 100 | + all user data areas of the device. This functionality requires | |
| 101 | + the device to be disabled, that is, not actively decoding any | |
| 102 | + HPA ranges. This permits avoiding explicit global CPU cache | |
| 103 | + management, relying instead for it to be done when a region | |
| 104 | + transitions between software programmed and hardware committed | |
| 105 | + states. If this file is not present, then there is no hardware | |
| 106 | + support for the operation. | |
| 96 | 107 | |
| 97 | 108 | |
| 98 | 109 | What: /sys/bus/cxl/devices/memX/firmware/ |
| @@ -513,17 +513,18 @@ Description: information about CPUs heterogeneity. · 512 unmodified lines | ||
| 513 | 513 | cpu_capacity: capacity of cpuX. |
| 514 | 514 | |
| 515 | 515 | What: /sys/devices/system/cpu/vulnerabilities |
| 516 | + /sys/devices/system/cpu/vulnerabilities/gather_data_sampling | |
| 517 | + /sys/devices/system/cpu/vulnerabilities/itlb_multihit | |
| 518 | + /sys/devices/system/cpu/vulnerabilities/l1tf | |
| 519 | + /sys/devices/system/cpu/vulnerabilities/mds | |
| 516 | 520 | /sys/devices/system/cpu/vulnerabilities/meltdown |
| 521 | + /sys/devices/system/cpu/vulnerabilities/mmio_stale_data | |
| 522 | + /sys/devices/system/cpu/vulnerabilities/retbleed | |
| 523 | + /sys/devices/system/cpu/vulnerabilities/spec_store_bypass | |
| 517 | 524 | /sys/devices/system/cpu/vulnerabilities/spectre_v1 |
| 518 | 525 | /sys/devices/system/cpu/vulnerabilities/spectre_v2 |
| 519 | − /sys/devices/system/cpu/vulnerabilities/spec_store_bypass | |
| 520 | − /sys/devices/system/cpu/vulnerabilities/l1tf | |
| 521 | − /sys/devices/system/cpu/vulnerabilities/mds | |
| 522 | 526 | /sys/devices/system/cpu/vulnerabilities/srbds |
| 523 | 527 | /sys/devices/system/cpu/vulnerabilities/tsx_async_abort |
| 524 | − /sys/devices/system/cpu/vulnerabilities/itlb_multihit | |
| 525 | − /sys/devices/system/cpu/vulnerabilities/mmio_stale_data | |
| 526 | − /sys/devices/system/cpu/vulnerabilities/retbleed | |
| 527 | 528 | Date: January 2018 |
| 528 | 529 | Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org> |
| 529 | 530 | Description: Information about CPU vulnerabilities |
| @@ -2,7 +2,7 @@ What: /sys/devices/platform/hidma-*/chid · 1 unmodified line | ||
| 2 | 2 | /sys/devices/platform/QCOM8061:*/chid |
| 3 | 3 | Date: Dec 2015 |
| 4 | 4 | KernelVersion: 4.4 |
| 5 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 5 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 6 | 6 | Description: |
| 7 | 7 | Contains the ID of the channel within the HIDMA instance. |
| 8 | 8 | It is used to associate a given HIDMA channel with the |
| @@ -2,7 +2,7 @@ What: /sys/devices/platform/hidma-mgmt*/chanops/chan*/priority · 1 unmodified line | ||
| 2 | 2 | /sys/devices/platform/QCOM8060:*/chanops/chan*/priority |
| 3 | 3 | Date: Nov 2015 |
| 4 | 4 | KernelVersion: 4.4 |
| 5 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 5 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 6 | 6 | Description: |
| 7 | 7 | Contains either 0 or 1 and indicates if the DMA channel is a |
| 8 | 8 | low priority (0) or high priority (1) channel. |
| @@ -11,7 +11,7 @@ What: /sys/devices/platform/hidma-mgmt*/chanops/chan*/weight · 2 unmodified lines | ||
| 11 | 11 | /sys/devices/platform/QCOM8060:*/chanops/chan*/weight |
| 12 | 12 | Date: Nov 2015 |
| 13 | 13 | KernelVersion: 4.4 |
| 14 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 14 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 15 | 15 | Description: |
| 16 | 16 | Contains 0..15 and indicates the weight of the channel among |
| 17 | 17 | equal priority channels during round robin scheduling. |
| @@ -20,7 +20,7 @@ What: /sys/devices/platform/hidma-mgmt*/chreset_timeout_cycles · 2 unmodified lines | ||
| 20 | 20 | /sys/devices/platform/QCOM8060:*/chreset_timeout_cycles |
| 21 | 21 | Date: Nov 2015 |
| 22 | 22 | KernelVersion: 4.4 |
| 23 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 23 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 24 | 24 | Description: |
| 25 | 25 | Contains the platform specific cycle value to wait after a |
| 26 | 26 | reset command is issued. If the value is chosen too short, |
| @@ -32,7 +32,7 @@ What: /sys/devices/platform/hidma-mgmt*/dma_channels · 5 unmodified lines | ||
| 32 | 32 | /sys/devices/platform/QCOM8060:*/dma_channels |
| 33 | 33 | Date: Nov 2015 |
| 34 | 34 | KernelVersion: 4.4 |
| 35 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 35 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 36 | 36 | Description: |
| 37 | 37 | Contains the number of dma channels supported by one instance |
| 38 | 38 | of HIDMA hardware. The value may change from chip to chip. |
| @@ -41,7 +41,7 @@ What: /sys/devices/platform/hidma-mgmt*/hw_version_major · 2 unmodified lines | ||
| 41 | 41 | /sys/devices/platform/QCOM8060:*/hw_version_major |
| 42 | 42 | Date: Nov 2015 |
| 43 | 43 | KernelVersion: 4.4 |
| 44 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 44 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 45 | 45 | Description: |
| 46 | 46 | Version number major for the hardware. |
| 47 | 47 | |
| @@ -49,7 +49,7 @@ What: /sys/devices/platform/hidma-mgmt*/hw_version_minor · 1 unmodified line | ||
| 49 | 49 | /sys/devices/platform/QCOM8060:*/hw_version_minor |
| 50 | 50 | Date: Nov 2015 |
| 51 | 51 | KernelVersion: 4.4 |
| 52 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 52 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 53 | 53 | Description: |
| 54 | 54 | Version number minor for the hardware. |
| 55 | 55 | |
| @@ -57,7 +57,7 @@ What: /sys/devices/platform/hidma-mgmt*/max_rd_xactions · 1 unmodified line | ||
| 57 | 57 | /sys/devices/platform/QCOM8060:*/max_rd_xactions |
| 58 | 58 | Date: Nov 2015 |
| 59 | 59 | KernelVersion: 4.4 |
| 60 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 60 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 61 | 61 | Description: |
| 62 | 62 | Contains a value between 0 and 31. Maximum number of |
| 63 | 63 | read transactions that can be issued back to back. |
| @@ -69,7 +69,7 @@ What: /sys/devices/platform/hidma-mgmt*/max_read_request · 5 unmodified lines | ||
| 69 | 69 | /sys/devices/platform/QCOM8060:*/max_read_request |
| 70 | 70 | Date: Nov 2015 |
| 71 | 71 | KernelVersion: 4.4 |
| 72 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 72 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 73 | 73 | Description: |
| 74 | 74 | Size of each read request. The value needs to be a power |
| 75 | 75 | of two and can be between 128 and 1024. |
| @@ -78,7 +78,7 @@ What: /sys/devices/platform/hidma-mgmt*/max_wr_xactions · 2 unmodified lines | ||
| 78 | 78 | /sys/devices/platform/QCOM8060:*/max_wr_xactions |
| 79 | 79 | Date: Nov 2015 |
| 80 | 80 | KernelVersion: 4.4 |
| 81 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 81 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 82 | 82 | Description: |
| 83 | 83 | Contains a value between 0 and 31. Maximum number of |
| 84 | 84 | write transactions that can be issued back to back. |
| @@ -91,7 +91,7 @@ What: /sys/devices/platform/hidma-mgmt*/max_write_request · 6 unmodified lines | ||
| 91 | 91 | /sys/devices/platform/QCOM8060:*/max_write_request |
| 92 | 92 | Date: Nov 2015 |
| 93 | 93 | KernelVersion: 4.4 |
| 94 | −Contact: "Sinan Kaya <okaya@codeaurora.org>" | |
| 94 | +Contact: "Sinan Kaya <okaya@kernel.org>" | |
| 95 | 95 | Description: |
| 96 | 96 | Size of each write request. The value needs to be a power |
| 97 | 97 | of two and can be between 128 and 1024. |
| @@ -0,0 +1,109 @@ | ||
| 1 | +.. SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +GDS - Gather Data Sampling | |
| 4 | +========================== | |
| 5 | + | |
| 6 | +Gather Data Sampling is a hardware vulnerability which allows unprivileged | |
| 7 | +speculative access to data which was previously stored in vector registers. | |
| 8 | + | |
| 9 | +Problem | |
| 10 | +------- | |
| 11 | +When a gather instruction performs loads from memory, different data elements | |
| 12 | +are merged into the destination vector register. However, when a gather | |
| 13 | +instruction that is transiently executed encounters a fault, stale data from | |
| 14 | +architectural or internal vector registers may get transiently forwarded to the | |
| 15 | +destination vector register instead. This will allow a malicious attacker to | |
| 16 | +infer stale data using typical side channel techniques like cache timing | |
| 17 | +attacks. GDS is a purely sampling-based attack. | |
| 18 | + | |
| 19 | +The attacker uses gather instructions to infer the stale vector register data. | |
| 20 | +The victim does not need to do anything special other than use the vector | |
| 21 | +registers. The victim does not need to use gather instructions to be | |
| 22 | +vulnerable. | |
| 23 | + | |
| 24 | +Because the buffers are shared between Hyper-Threads cross Hyper-Thread attacks | |
| 25 | +are possible. | |
| 26 | + | |
| 27 | +Attack scenarios | |
| 28 | +---------------- | |
| 29 | +Without mitigation, GDS can infer stale data across virtually all | |
| 30 | +permission boundaries: | |
| 31 | + | |
| 32 | + Non-enclaves can infer SGX enclave data | |
| 33 | + Userspace can infer kernel data | |
| 34 | + Guests can infer data from hosts | |
| 35 | + Guest can infer guest from other guests | |
| 36 | + Users can infer data from other users | |
| 37 | + | |
| 38 | +Because of this, it is important to ensure that the mitigation stays enabled in | |
| 39 | +lower-privilege contexts like guests and when running outside SGX enclaves. | |
| 40 | + | |
| 41 | +The hardware enforces the mitigation for SGX. Likewise, VMMs should ensure | |
| 42 | +that guests are not allowed to disable the GDS mitigation. If a host erred and | |
| 43 | +allowed this, a guest could theoretically disable GDS mitigation, mount an | |
| 44 | +attack, and re-enable it. | |
| 45 | + | |
| 46 | +Mitigation mechanism | |
| 47 | +-------------------- | |
| 48 | +This issue is mitigated in microcode. The microcode defines the following new | |
| 49 | +bits: | |
| 50 | + | |
| 51 | + ================================ === ============================ | |
| 52 | + IA32_ARCH_CAPABILITIES[GDS_CTRL] R/O Enumerates GDS vulnerability | |
| 53 | + and mitigation support. | |
| 54 | + IA32_ARCH_CAPABILITIES[GDS_NO] R/O Processor is not vulnerable. | |
| 55 | + IA32_MCU_OPT_CTRL[GDS_MITG_DIS] R/W Disables the mitigation | |
| 56 | + 0 by default. | |
| 57 | + IA32_MCU_OPT_CTRL[GDS_MITG_LOCK] R/W Locks GDS_MITG_DIS=0. Writes | |
| 58 | + to GDS_MITG_DIS are ignored | |
| 59 | + Can't be cleared once set. | |
| 60 | + ================================ === ============================ | |
| 61 | + | |
| 62 | +GDS can also be mitigated on systems that don't have updated microcode by | |
| 63 | +disabling AVX. This can be done by setting gather_data_sampling="force" or | |
| 64 | +"clearcpuid=avx" on the kernel command-line. | |
| 65 | + | |
| 66 | +If used, these options will disable AVX use by turning off XSAVE YMM support. | |
| 67 | +However, the processor will still enumerate AVX support. Userspace that | |
| 68 | +does not follow proper AVX enumeration to check both AVX *and* XSAVE YMM | |
| 69 | +support will break. | |
| 70 | + | |
| 71 | +Mitigation control on the kernel command line | |
| 72 | +--------------------------------------------- | |
| 73 | +The mitigation can be disabled by setting "gather_data_sampling=off" or | |
| 74 | +"mitigations=off" on the kernel command line. Not specifying either will default | |
| 75 | +to the mitigation being enabled. Specifying "gather_data_sampling=force" will | |
| 76 | +use the microcode mitigation when available or disable AVX on affected systems | |
| 77 | +where the microcode hasn't been updated to include the mitigation. | |
| 78 | + | |
| 79 | +GDS System Information | |
| 80 | +------------------------ | |
| 81 | +The kernel provides vulnerability status information through sysfs. For | |
| 82 | +GDS this can be accessed by the following sysfs file: | |
| 83 | + | |
| 84 | +/sys/devices/system/cpu/vulnerabilities/gather_data_sampling | |
| 85 | + | |
| 86 | +The possible values contained in this file are: | |
| 87 | + | |
| 88 | + ============================== ============================================= | |
| 89 | + Not affected Processor not vulnerable. | |
| 90 | + Vulnerable Processor vulnerable and mitigation disabled. | |
| 91 | + Vulnerable: No microcode Processor vulnerable and microcode is missing | |
| 92 | + mitigation. | |
| 93 | + Mitigation: AVX disabled, | |
| 94 | + no microcode Processor is vulnerable and microcode is missing | |
| 95 | + mitigation. AVX disabled as mitigation. | |
| 96 | + Mitigation: Microcode Processor is vulnerable and mitigation is in | |
| 97 | + effect. | |
| 98 | + Mitigation: Microcode (locked) Processor is vulnerable and mitigation is in | |
| 99 | + effect and cannot be disabled. | |
| 100 | + Unknown: Dependent on | |
| 101 | + hypervisor status Running on a virtual guest processor that is | |
| 102 | + affected but with no way to know if host | |
| 103 | + processor is mitigated or vulnerable. | |
| 104 | + ============================== ============================================= | |
| 105 | + | |
| 106 | +GDS Default mitigation | |
| 107 | +---------------------- | |
| 108 | +The updated microcode will enable the mitigation by default. The kernel's | |
| 109 | +default action is to leave the mitigation enabled. | |
| @@ -13,9 +13,11 @@ are configurable at compile, boot or run time. · 12 unmodified lines | ||
| 13 | 13 | l1tf |
| 14 | 14 | mds |
| 15 | 15 | tsx_async_abort |
| 16 | − multihit.rst | |
| 17 | − special-register-buffer-data-sampling.rst | |
| 18 | − core-scheduling.rst | |
| 19 | − l1d_flush.rst | |
| 20 | − processor_mmio_stale_data.rst | |
| 21 | − cross-thread-rsb.rst | |
| 16 | + multihit | |
| 17 | + special-register-buffer-data-sampling | |
| 18 | + core-scheduling | |
| 19 | + l1d_flush | |
| 20 | + processor_mmio_stale_data | |
| 21 | + cross-thread-rsb | |
| 22 | + srso | |
| 23 | + gather_data_sampling | |
| @@ -0,0 +1,150 @@ | ||
| 1 | +.. SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +Speculative Return Stack Overflow (SRSO) | |
| 4 | +======================================== | |
| 5 | + | |
| 6 | +This is a mitigation for the speculative return stack overflow (SRSO) | |
| 7 | +vulnerability found on AMD processors. The mechanism is by now the well | |
| 8 | +known scenario of poisoning CPU functional units - the Branch Target | |
| 9 | +Buffer (BTB) and Return Address Predictor (RAP) in this case - and then | |
| 10 | +tricking the elevated privilege domain (the kernel) into leaking | |
| 11 | +sensitive data. | |
| 12 | + | |
| 13 | +AMD CPUs predict RET instructions using a Return Address Predictor (aka | |
| 14 | +Return Address Stack/Return Stack Buffer). In some cases, a non-architectural | |
| 15 | +CALL instruction (i.e., an instruction predicted to be a CALL but is | |
| 16 | +not actually a CALL) can create an entry in the RAP which may be used | |
| 17 | +to predict the target of a subsequent RET instruction. | |
| 18 | + | |
| 19 | +The specific circumstances that lead to this varies by microarchitecture | |
| 20 | +but the concern is that an attacker can mis-train the CPU BTB to predict | |
| 21 | +non-architectural CALL instructions in kernel space and use this to | |
| 22 | +control the speculative target of a subsequent kernel RET, potentially | |
| 23 | +leading to information disclosure via a speculative side-channel. | |
| 24 | + | |
| 25 | +The issue is tracked under CVE-2023-20569. | |
| 26 | + | |
| 27 | +Affected processors | |
| 28 | +------------------- | |
| 29 | + | |
| 30 | +AMD Zen, generations 1-4. That is, all families 0x17 and 0x19. Older | |
| 31 | +processors have not been investigated. | |
| 32 | + | |
| 33 | +System information and options | |
| 34 | +------------------------------ | |
| 35 | + | |
| 36 | +First of all, it is required that the latest microcode be loaded for | |
| 37 | +mitigations to be effective. | |
| 38 | + | |
| 39 | +The sysfs file showing SRSO mitigation status is: | |
| 40 | + | |
| 41 | + /sys/devices/system/cpu/vulnerabilities/spec_rstack_overflow | |
| 42 | + | |
| 43 | +The possible values in this file are: | |
| 44 | + | |
| 45 | + * 'Not affected': | |
| 46 | + | |
| 47 | + The processor is not vulnerable | |
| 48 | + | |
| 49 | + * 'Vulnerable: no microcode': | |
| 50 | + | |
| 51 | + The processor is vulnerable, no microcode extending IBPB | |
| 52 | + functionality to address the vulnerability has been applied. | |
| 53 | + | |
| 54 | + * 'Mitigation: microcode': | |
| 55 | + | |
| 56 | + Extended IBPB functionality microcode patch has been applied. It does | |
| 57 | + not address User->Kernel and Guest->Host transitions protection but it | |
| 58 | + does address User->User and VM->VM attack vectors. | |
| 59 | + | |
| 60 | + Note that User->User mitigation is controlled by how the IBPB aspect in | |
| 61 | + the Spectre v2 mitigation is selected: | |
| 62 | + | |
| 63 | + * conditional IBPB: | |
| 64 | + | |
| 65 | + where each process can select whether it needs an IBPB issued | |
| 66 | + around it PR_SPEC_DISABLE/_ENABLE etc, see :doc:`spectre` | |
| 67 | + | |
| 68 | + * strict: | |
| 69 | + | |
| 70 | + i.e., always on - by supplying spectre_v2_user=on on the kernel | |
| 71 | + command line | |
| 72 | + | |
| 73 | + (spec_rstack_overflow=microcode) | |
| 74 | + | |
| 75 | + * 'Mitigation: safe RET': | |
| 76 | + | |
| 77 | + Software-only mitigation. It complements the extended IBPB microcode | |
| 78 | + patch functionality by addressing User->Kernel and Guest->Host | |
| 79 | + transitions protection. | |
| 80 | + | |
| 81 | + Selected by default or by spec_rstack_overflow=safe-ret | |
| 82 | + | |
| 83 | + * 'Mitigation: IBPB': | |
| 84 | + | |
| 85 | + Similar protection as "safe RET" above but employs an IBPB barrier on | |
| 86 | + privilege domain crossings (User->Kernel, Guest->Host). | |
| 87 | + | |
| 88 | + (spec_rstack_overflow=ibpb) | |
| 89 | + | |
| 90 | + * 'Mitigation: IBPB on VMEXIT': | |
| 91 | + | |
| 92 | + Mitigation addressing the cloud provider scenario - the Guest->Host | |
| 93 | + transitions only. | |
| 94 | + | |
| 95 | + (spec_rstack_overflow=ibpb-vmexit) | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | +In order to exploit vulnerability, an attacker needs to: | |
| 100 | + | |
| 101 | + - gain local access on the machine | |
| 102 | + | |
| 103 | + - break kASLR | |
| 104 | + | |
| 105 | + - find gadgets in the running kernel in order to use them in the exploit | |
| 106 | + | |
| 107 | + - potentially create and pin an additional workload on the sibling | |
| 108 | + thread, depending on the microarchitecture (not necessary on fam 0x19) | |
| 109 | + | |
| 110 | + - run the exploit | |
| 111 | + | |
| 112 | +Considering the performance implications of each mitigation type, the | |
| 113 | +default one is 'Mitigation: safe RET' which should take care of most | |
| 114 | +attack vectors, including the local User->Kernel one. | |
| 115 | + | |
| 116 | +As always, the user is advised to keep her/his system up-to-date by | |
| 117 | +applying software updates regularly. | |
| 118 | + | |
| 119 | +The default setting will be reevaluated when needed and especially when | |
| 120 | +new attack vectors appear. | |
| 121 | + | |
| 122 | +As one can surmise, 'Mitigation: safe RET' does come at the cost of some | |
| 123 | +performance depending on the workload. If one trusts her/his userspace | |
| 124 | +and does not want to suffer the performance impact, one can always | |
| 125 | +disable the mitigation with spec_rstack_overflow=off. | |
| 126 | + | |
| 127 | +Similarly, 'Mitigation: IBPB' is another full mitigation type employing | |
| 128 | +an indrect branch prediction barrier after having applied the required | |
| 129 | +microcode patch for one's system. This mitigation comes also at | |
| 130 | +a performance cost. | |
| 131 | + | |
| 132 | +Mitigation: safe RET | |
| 133 | +-------------------- | |
| 134 | + | |
| 135 | +The mitigation works by ensuring all RET instructions speculate to | |
| 136 | +a controlled location, similar to how speculation is controlled in the | |
| 137 | +retpoline sequence. To accomplish this, the __x86_return_thunk forces | |
| 138 | +the CPU to mispredict every function return using a 'safe return' | |
| 139 | +sequence. | |
| 140 | + | |
| 141 | +To ensure the safety of this mitigation, the kernel must ensure that the | |
| 142 | +safe return sequence is itself free from attacker interference. In Zen3 | |
| 143 | +and Zen4, this is accomplished by creating a BTB alias between the | |
| 144 | +untraining function srso_untrain_ret_alias() and the safe return | |
| 145 | +function srso_safe_ret_alias() which results in evicting a potentially | |
| 146 | +poisoned BTB entry and using that safe one for all function returns. | |
| 147 | + | |
| 148 | +In older Zen1 and Zen2, this is accomplished using a reinterpretation | |
| 149 | +technique similar to Retbleed one: srso_untrain_ret() and | |
| 150 | +srso_safe_ret(). | |
| @@ -624,3 +624,9 @@ Used to get the correct ranges: · 623 unmodified lines | ||
| 624 | 624 | * VMALLOC_START ~ VMALLOC_END : vmalloc() / ioremap() space. |
| 625 | 625 | * VMEMMAP_START ~ VMEMMAP_END : vmemmap space, used for struct page array. |
| 626 | 626 | * KERNEL_LINK_ADDR : start address of Kernel link and BPF |
| 627 | + | |
| 628 | +va_kernel_pa_offset | |
| 629 | +------------------- | |
| 630 | + | |
| 631 | +Indicates the offset between the kernel virtual and physical mappings. | |
| 632 | +Used to translate virtual to physical addresses. | |
| @@ -1623,6 +1623,26 @@ · 1622 unmodified lines | ||
| 1623 | 1623 | Format: off | on |
| 1624 | 1624 | default: on |
| 1625 | 1625 | |
| 1626 | + gather_data_sampling= | |
| 1627 | + [X86,INTEL] Control the Gather Data Sampling (GDS) | |
| 1628 | + mitigation. | |
| 1629 | + | |
| 1630 | + Gather Data Sampling is a hardware vulnerability which | |
| 1631 | + allows unprivileged speculative access to data which was | |
| 1632 | + previously stored in vector registers. | |
| 1633 | + | |
| 1634 | + This issue is mitigated by default in updated microcode. | |
| 1635 | + The mitigation may have a performance impact but can be | |
| 1636 | + disabled. On systems without the microcode mitigation | |
| 1637 | + disabling AVX serves as a mitigation. | |
| 1638 | + | |
| 1639 | + force: Disable AVX to mitigate systems without | |
| 1640 | + microcode mitigation. No effect if the microcode | |
| 1641 | + mitigation is present. Known to cause crashes in | |
| 1642 | + userspace with buggy AVX enumeration. | |
| 1643 | + | |
| 1644 | + off: Disable GDS mitigation. | |
| 1645 | + | |
| 1626 | 1646 | gcov_persist= [GCOV] When non-zero (default), profiling data for |
| 1627 | 1647 | kernel modules is saved and remains accessible via |
| 1628 | 1648 | debugfs, even when the module is unloaded/reloaded. |
| @@ -3273,24 +3293,25 @@ · 1644 unmodified lines | ||
| 3273 | 3293 | Disable all optional CPU mitigations. This |
| 3274 | 3294 | improves system performance, but it may also |
| 3275 | 3295 | expose users to several CPU vulnerabilities. |
| 3276 | − Equivalent to: nopti [X86,PPC] | |
| 3277 | − if nokaslr then kpti=0 [ARM64] | |
| 3278 | − nospectre_v1 [X86,PPC] | |
| 3279 | − nobp=0 [S390] | |
| 3280 | − nospectre_v2 [X86,PPC,S390,ARM64] | |
| 3281 | − spectre_v2_user=off [X86] | |
| 3282 | − spec_store_bypass_disable=off [X86,PPC] | |
| 3283 | − ssbd=force-off [ARM64] | |
| 3284 | − nospectre_bhb [ARM64] | |
| 3296 | + Equivalent to: if nokaslr then kpti=0 [ARM64] | |
| 3297 | + gather_data_sampling=off [X86] | |
| 3298 | + kvm.nx_huge_pages=off [X86] | |
| 3285 | 3299 | l1tf=off [X86] |
| 3286 | 3300 | mds=off [X86] |
| 3287 | − tsx_async_abort=off [X86] | |
| 3288 | − kvm.nx_huge_pages=off [X86] | |
| 3289 | − srbds=off [X86,INTEL] | |
| 3301 | + mmio_stale_data=off [X86] | |
| 3290 | 3302 | no_entry_flush [PPC] |
| 3291 | 3303 | no_uaccess_flush [PPC] |
| 3292 | − mmio_stale_data=off [X86] | |
| 3304 | + nobp=0 [S390] | |
| 3305 | + nopti [X86,PPC] | |
| 3306 | + nospectre_bhb [ARM64] | |
| 3307 | + nospectre_v1 [X86,PPC] | |
| 3308 | + nospectre_v2 [X86,PPC,S390,ARM64] | |
| 3293 | 3309 | retbleed=off [X86] |
| 3310 | + spec_store_bypass_disable=off [X86,PPC] | |
| 3311 | + spectre_v2_user=off [X86] | |
| 3312 | + srbds=off [X86,INTEL] | |
| 3313 | + ssbd=force-off [ARM64] | |
| 3314 | + tsx_async_abort=off [X86] | |
| 3294 | 3315 | |
| 3295 | 3316 | Exceptions: |
| 3296 | 3317 | This does not have any effect on |
| @@ -5875,6 +5896,17 @@ · 2578 unmodified lines | ||
| 5875 | 5896 | Not specifying this option is equivalent to |
| 5876 | 5897 | spectre_v2_user=auto. |
| 5877 | 5898 | |
| 5899 | + spec_rstack_overflow= | |
| 5900 | + [X86] Control RAS overflow mitigation on AMD Zen CPUs | |
| 5901 | + | |
| 5902 | + off - Disable mitigation | |
| 5903 | + microcode - Enable microcode mitigation only | |
| 5904 | + safe-ret - Enable sw-only safe RET mitigation (default) | |
| 5905 | + ibpb - Enable mitigation by issuing IBPB on | |
| 5906 | + kernel entry | |
| 5907 | + ibpb-vmexit - Issue IBPB only on VMEXIT | |
| 5908 | + (cloud-specific mitigation) | |
| 5909 | + | |
| 5878 | 5910 | spec_store_bypass_disable= |
| 5879 | 5911 | [HW] Control Speculative Store Bypass (SSB) Disable mitigation |
| 5880 | 5912 | (Speculative Store Bypass vulnerability) |
| @@ -216,7 +216,6 @@ properties: · 215 unmodified lines | ||
| 216 | 216 | description: Whether to enable burnout current for EXT1. |
| 217 | 217 | |
| 218 | 218 | adi,ext1-burnout-current-nanoamp: |
| 219 | − $ref: /schemas/types.yaml#/definitions/uint32 | |
| 220 | 219 | description: |
| 221 | 220 | Burnout current in nanoamps to be applied to EXT1. |
| 222 | 221 | enum: [0, 50, 500, 1000, 10000] |
| @@ -233,7 +232,6 @@ properties: · 10 unmodified lines | ||
| 233 | 232 | description: Whether to enable burnout current for EXT2. |
| 234 | 233 | |
| 235 | 234 | adi,ext2-burnout-current-nanoamp: |
| 236 | − $ref: /schemas/types.yaml#/definitions/uint32 | |
| 237 | 235 | description: Burnout current in nanoamps to be applied to EXT2. |
| 238 | 236 | enum: [0, 50, 500, 1000, 10000] |
| 239 | 237 | default: 0 |
| @@ -249,7 +247,6 @@ properties: · 9 unmodified lines | ||
| 249 | 247 | description: Whether to enable burnout current for VIOUT. |
| 250 | 248 | |
| 251 | 249 | adi,viout-burnout-current-nanoamp: |
| 252 | − $ref: /schemas/types.yaml#/definitions/uint32 | |
| 253 | 250 | description: Burnout current in nanoamps to be applied to VIOUT. |
| 254 | 251 | enum: [0, 1000, 10000] |
| 255 | 252 | default: 0 |
| @@ -293,7 +293,7 @@ allOf: · 292 unmodified lines | ||
| 293 | 293 | patternProperties: |
| 294 | 294 | "^mac@[0-1]$": |
| 295 | 295 | type: object |
| 296 | − additionalProperties: false | |
| 296 | + unevaluatedProperties: false | |
| 297 | 297 | allOf: |
| 298 | 298 | - $ref: ethernet-controller.yaml# |
| 299 | 299 | description: |
| @@ -305,14 +305,9 @@ patternProperties: · 5 unmodified lines | ||
| 305 | 305 | reg: |
| 306 | 306 | maxItems: 1 |
| 307 | 307 | |
| 308 | − phy-handle: true | |
| 309 | − | |
| 310 | − phy-mode: true | |
| 311 | − | |
| 312 | 308 | required: |
| 313 | 309 | - reg |
| 314 | 310 | - compatible |
| 315 | − - phy-handle | |
| 316 | 311 | |
| 317 | 312 | required: |
| 318 | 313 | - compatible |
| @@ -91,12 +91,18 @@ properties: · 90 unmodified lines | ||
| 91 | 91 | $ref: /schemas/types.yaml#/definitions/phandle |
| 92 | 92 | |
| 93 | 93 | tx_delay: |
| 94 | − description: Delay value for TXD timing. Range value is 0~0x7F, 0x30 as default. | |
| 94 | + description: Delay value for TXD timing. | |
| 95 | 95 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 96 | + minimum: 0 | |
| 97 | + maximum: 0x7F | |
| 98 | + default: 0x30 | |
| 96 | 99 | |
| 97 | 100 | rx_delay: |
| 98 | − description: Delay value for RXD timing. Range value is 0~0x7F, 0x10 as default. | |
| 101 | + description: Delay value for RXD timing. | |
| 99 | 102 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 103 | + minimum: 0 | |
| 104 | + maximum: 0x7F | |
| 105 | + default: 0x10 | |
| 100 | 106 | |
| 101 | 107 | phy-supply: |
| 102 | 108 | description: PHY regulator |
| @@ -16,13 +16,15 @@ properties: · 15 unmodified lines | ||
| 16 | 16 | - enum: |
| 17 | 17 | - atmel,at91rm9200-usart |
| 18 | 18 | - atmel,at91sam9260-usart |
| 19 | − - microchip,sam9x60-usart | |
| 20 | 19 | - items: |
| 21 | 20 | - const: atmel,at91rm9200-dbgu |
| 22 | 21 | - const: atmel,at91rm9200-usart |
| 23 | 22 | - items: |
| 24 | 23 | - const: atmel,at91sam9260-dbgu |
| 25 | 24 | - const: atmel,at91sam9260-usart |
| 25 | + - items: | |
| 26 | + - const: microchip,sam9x60-usart | |
| 27 | + - const: atmel,at91sam9260-usart | |
| 26 | 28 | - items: |
| 27 | 29 | - const: microchip,sam9x60-dbgu |
| 28 | 30 | - const: microchip,sam9x60-usart |
| @@ -551,9 +551,8 @@ mutex or just to use i_size_read() instead. · 550 unmodified lines | ||
| 551 | 551 | Note: this does not protect the file->f_pos against concurrent modifications |
| 552 | 552 | since this is something the userspace has to take care about. |
| 553 | 553 | |
| 554 | −->iterate() is called with i_rwsem exclusive. | |
| 555 | − | |
| 556 | −->iterate_shared() is called with i_rwsem at least shared. | |
| 554 | +->iterate_shared() is called with i_rwsem held for reading, and with the | |
| 555 | +file f_pos_lock held exclusively | |
| 557 | 556 | |
| 558 | 557 | ->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags. |
| 559 | 558 | Most instances call fasync_helper(), which does that maintenance, so it's |
| @@ -537,7 +537,7 @@ vfs_readdir() is gone; switch to iterate_dir() instead · 536 unmodified lines | ||
| 537 | 537 | |
| 538 | 538 | **mandatory** |
| 539 | 539 | |
| 540 | −->readdir() is gone now; switch to ->iterate() | |
| 540 | +->readdir() is gone now; switch to ->iterate_shared() | |
| 541 | 541 | |
| 542 | 542 | **mandatory** |
| 543 | 543 | |
| @@ -693,24 +693,19 @@ parallel now. · 149 unmodified lines | ||
| 693 | 693 | |
| 694 | 694 | --- |
| 695 | 695 | |
| 696 | −**recommended** | |
| 696 | +**mandatory** | |
| 697 | 697 | |
| 698 | −->iterate_shared() is added; it's a parallel variant of ->iterate(). | |
| 698 | +->iterate_shared() is added. | |
| 699 | 699 | Exclusion on struct file level is still provided (as well as that |
| 700 | 700 | between it and lseek on the same struct file), but if your directory |
| 701 | 701 | has been opened several times, you can get these called in parallel. |
| 702 | 702 | Exclusion between that method and all directory-modifying ones is |
| 703 | 703 | still provided, of course. |
| 704 | 704 | |
| 705 | −Often enough ->iterate() can serve as ->iterate_shared() without any | |
| 706 | −changes - it is a read-only operation, after all. If you have any | |
| 707 | −per-inode or per-dentry in-core data structures modified by ->iterate(), | |
| 708 | −you might need something to serialize the access to them. If you | |
| 709 | −do dcache pre-seeding, you'll need to switch to d_alloc_parallel() for | |
| 710 | −that; look for in-tree examples. | |
| 711 | − | |
| 712 | −Old method is only used if the new one is absent; eventually it will | |
| 713 | −be removed. Switch while you still can; the old one won't stay. | |
| 705 | +If you have any per-inode or per-dentry in-core data structures modified | |
| 706 | +by ->iterate_shared(), you might need something to serialize the access | |
| 707 | +to them. If you do dcache pre-seeding, you'll need to switch to | |
| 708 | +d_alloc_parallel() for that; look for in-tree examples. | |
| 714 | 709 | |
| 715 | 710 | --- |
| 716 | 711 | |
| @@ -930,9 +925,9 @@ should be done by looking at FMODE_LSEEK in file->f_mode. · 213 unmodified lines | ||
| 930 | 925 | filldir_t (readdir callbacks) calling conventions have changed. Instead of |
| 931 | 926 | returning 0 or -E... it returns bool now. false means "no more" (as -E... used |
| 932 | 927 | to) and true - "keep going" (as 0 in old calling conventions). Rationale: |
| 933 | −callers never looked at specific -E... values anyway. ->iterate() and | |
| 934 | −->iterate_shared() instance require no changes at all, all filldir_t ones in | |
| 935 | −the tree converted. | |
| 928 | +callers never looked at specific -E... values anyway. -> iterate_shared() | |
| 929 | +instances require no changes at all, all filldir_t ones in the tree | |
| 930 | +converted. | |
| 936 | 931 | |
| 937 | 932 | --- |
| 938 | 933 | |
| @@ -2339,7 +2339,7 @@ F: drivers/phy/mediatek/ · 2338 unmodified lines | ||
| 2339 | 2339 | ARM/MICROCHIP (ARM64) SoC support |
| 2340 | 2340 | M: Conor Dooley <conor@kernel.org> |
| 2341 | 2341 | M: Nicolas Ferre <nicolas.ferre@microchip.com> |
| 2342 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 2342 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 2343 | 2343 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2344 | 2344 | S: Supported |
| 2345 | 2345 | T: git https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git |
| @@ -2348,7 +2348,7 @@ F: arch/arm64/boot/dts/microchip/ · 2 unmodified lines | ||
| 2348 | 2348 | ARM/Microchip (AT91) SoC support |
| 2349 | 2349 | M: Nicolas Ferre <nicolas.ferre@microchip.com> |
| 2350 | 2350 | M: Alexandre Belloni <alexandre.belloni@bootlin.com> |
| 2351 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 2351 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 2352 | 2352 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2353 | 2353 | S: Supported |
| 2354 | 2354 | W: http://www.linux4sam.org |
| @@ -3250,7 +3250,7 @@ F: include/uapi/linux/atm* · 895 unmodified lines | ||
| 3250 | 3250 | |
| 3251 | 3251 | ATMEL MACB ETHERNET DRIVER |
| 3252 | 3252 | M: Nicolas Ferre <nicolas.ferre@microchip.com> |
| 3253 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 3253 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 3254 | 3254 | S: Supported |
| 3255 | 3255 | F: drivers/net/ethernet/cadence/ |
| 3256 | 3256 | |
| @@ -3262,9 +3262,8 @@ F: Documentation/devicetree/bindings/input/atmel,maxtouch.yaml · 5 unmodified lines | ||
| 3262 | 3262 | F: drivers/input/touchscreen/atmel_mxt_ts.c |
| 3263 | 3263 | |
| 3264 | 3264 | ATMEL WIRELESS DRIVER |
| 3265 | −M: Simon Kelley <simon@thekelleys.org.uk> | |
| 3266 | 3265 | L: linux-wireless@vger.kernel.org |
| 3267 | −S: Maintained | |
| 3266 | +S: Orphan | |
| 3268 | 3267 | W: http://www.thekelleys.org.uk/atmel |
| 3269 | 3268 | W: http://atmelwlandriver.sourceforge.net/ |
| 3270 | 3269 | F: drivers/net/wireless/atmel/atmel* |
| @@ -3394,7 +3393,7 @@ F: drivers/media/radio/radio-aztech* · 123 unmodified lines | ||
| 3394 | 3393 | B43 WIRELESS DRIVER |
| 3395 | 3394 | L: linux-wireless@vger.kernel.org |
| 3396 | 3395 | L: b43-dev@lists.infradead.org |
| 3397 | −S: Odd Fixes | |
| 3396 | +S: Orphan | |
| 3398 | 3397 | W: https://wireless.wiki.kernel.org/en/users/Drivers/b43 |
| 3399 | 3398 | F: drivers/net/wireless/broadcom/b43/ |
| 3400 | 3399 | |
| @@ -5462,8 +5461,7 @@ F: Documentation/devicetree/bindings/net/can/ctu,ctucanfd.yaml · 2061 unmodified lines | ||
| 5462 | 5461 | F: drivers/net/can/ctucanfd/ |
| 5463 | 5462 | |
| 5464 | 5463 | CW1200 WLAN driver |
| 5465 | −M: Solomon Peachy <pizza@shaftnet.org> | |
| 5466 | −S: Maintained | |
| 5464 | +S: Orphan | |
| 5467 | 5465 | F: drivers/net/wireless/st/cw1200/ |
| 5468 | 5466 | |
| 5469 | 5467 | CX18 VIDEO4LINUX DRIVER |
| @@ -9377,7 +9375,6 @@ F: drivers/crypto/hisilicon/sgl.c · 3907 unmodified lines | ||
| 9377 | 9375 | F: include/linux/hisi_acc_qm.h |
| 9378 | 9376 | |
| 9379 | 9377 | HISILICON ROCE DRIVER |
| 9380 | −M: Haoyue Xu <xuhaoyue1@hisilicon.com> | |
| 9381 | 9378 | M: Junxian Huang <huangjunxian6@hisilicon.com> |
| 9382 | 9379 | L: linux-rdma@vger.kernel.org |
| 9383 | 9380 | S: Maintained |
| @@ -9662,6 +9659,7 @@ F: tools/hv/ · 278 unmodified lines | ||
| 9662 | 9659 | |
| 9663 | 9660 | HYPERBUS SUPPORT |
| 9664 | 9661 | M: Vignesh Raghavendra <vigneshr@ti.com> |
| 9662 | +R: Tudor Ambarus <tudor.ambarus@linaro.org> | |
| 9665 | 9663 | L: linux-mtd@lists.infradead.org |
| 9666 | 9664 | S: Supported |
| 9667 | 9665 | Q: http://patchwork.ozlabs.org/project/linux-mtd/list/ |
| @@ -12481,6 +12479,7 @@ F: net/mctp/ · 2813 unmodified lines | ||
| 12481 | 12479 | |
| 12482 | 12480 | MAPLE TREE |
| 12483 | 12481 | M: Liam R. Howlett <Liam.Howlett@oracle.com> |
| 12482 | +L: maple-tree@lists.infradead.org | |
| 12484 | 12483 | L: linux-mm@kvack.org |
| 12485 | 12484 | S: Supported |
| 12486 | 12485 | F: Documentation/core-api/maple_tree.rst |
| @@ -12592,18 +12591,14 @@ F: Documentation/devicetree/bindings/net/marvell,pp2.yaml · 105 unmodified lines | ||
| 12592 | 12591 | F: drivers/net/ethernet/marvell/mvpp2/ |
| 12593 | 12592 | |
| 12594 | 12593 | MARVELL MWIFIEX WIRELESS DRIVER |
| 12595 | −M: Amitkumar Karwar <amitkarwar@gmail.com> | |
| 12596 | −M: Ganapathi Bhat <ganapathi017@gmail.com> | |
| 12597 | −M: Sharvari Harisangam <sharvari.harisangam@nxp.com> | |
| 12598 | −M: Xinming Hu <huxinming820@gmail.com> | |
| 12594 | +M: Brian Norris <briannorris@chromium.org> | |
| 12599 | 12595 | L: linux-wireless@vger.kernel.org |
| 12600 | −S: Maintained | |
| 12596 | +S: Odd Fixes | |
| 12601 | 12597 | F: drivers/net/wireless/marvell/mwifiex/ |
| 12602 | 12598 | |
| 12603 | 12599 | MARVELL MWL8K WIRELESS DRIVER |
| 12604 | −M: Lennert Buytenhek <buytenh@wantstofly.org> | |
| 12605 | 12600 | L: linux-wireless@vger.kernel.org |
| 12606 | −S: Odd Fixes | |
| 12601 | +S: Orphan | |
| 12607 | 12602 | F: drivers/net/wireless/marvell/mwl8k.c |
| 12608 | 12603 | |
| 12609 | 12604 | MARVELL NAND CONTROLLER DRIVER |
| @@ -13791,7 +13786,7 @@ F: Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml · 1181 unmodified lines | ||
| 13791 | 13786 | F: drivers/spi/spi-at91-usart.c |
| 13792 | 13787 | |
| 13793 | 13788 | MICROCHIP AUDIO ASOC DRIVERS |
| 13794 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 13789 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 13795 | 13790 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
| 13796 | 13791 | S: Supported |
| 13797 | 13792 | F: Documentation/devicetree/bindings/sound/atmel* |
| @@ -13814,7 +13809,7 @@ S: Maintained · 16 unmodified lines | ||
| 13814 | 13809 | F: drivers/crypto/atmel-ecc.* |
| 13815 | 13810 | |
| 13816 | 13811 | MICROCHIP EIC DRIVER |
| 13817 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 13812 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 13818 | 13813 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13819 | 13814 | S: Supported |
| 13820 | 13815 | F: Documentation/devicetree/bindings/interrupt-controller/microchip,sama7g5-eic.yaml |
| @@ -13887,7 +13882,7 @@ F: drivers/video/fbdev/atmel_lcdfb.c · 66 unmodified lines | ||
| 13887 | 13882 | F: include/video/atmel_lcdc.h |
| 13888 | 13883 | |
| 13889 | 13884 | MICROCHIP MCP16502 PMIC DRIVER |
| 13890 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 13885 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 13891 | 13886 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13892 | 13887 | S: Supported |
| 13893 | 13888 | F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt |
| @@ -13914,7 +13909,7 @@ F: Documentation/devicetree/bindings/mtd/atmel-nand.txt · 20 unmodified lines | ||
| 13914 | 13909 | F: drivers/mtd/nand/raw/atmel/* |
| 13915 | 13910 | |
| 13916 | 13911 | MICROCHIP OTPC DRIVER |
| 13917 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 13912 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 13918 | 13913 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13919 | 13914 | S: Supported |
| 13920 | 13915 | F: Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml |
| @@ -13953,7 +13948,7 @@ F: Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml · 32 unmodified lines | ||
| 13953 | 13948 | F: drivers/fpga/microchip-spi.c |
| 13954 | 13949 | |
| 13955 | 13950 | MICROCHIP PWM DRIVER |
| 13956 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 13951 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 13957 | 13952 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13958 | 13953 | L: linux-pwm@vger.kernel.org |
| 13959 | 13954 | S: Supported |
| @@ -13969,7 +13964,7 @@ F: drivers/iio/adc/at91-sama5d2_adc.c · 9 unmodified lines | ||
| 13969 | 13964 | F: include/dt-bindings/iio/adc/at91-sama5d2_adc.h |
| 13970 | 13965 | |
| 13971 | 13966 | MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER |
| 13972 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 13967 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 13973 | 13968 | S: Supported |
| 13974 | 13969 | F: Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml |
| 13975 | 13970 | F: drivers/power/reset/at91-sama5d2_shdwc.c |
| @@ -13986,7 +13981,7 @@ S: Supported · 10 unmodified lines | ||
| 13986 | 13981 | F: drivers/spi/spi-atmel.* |
| 13987 | 13982 | |
| 13988 | 13983 | MICROCHIP SSC DRIVER |
| 13989 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 13984 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 13990 | 13985 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13991 | 13986 | S: Supported |
| 13992 | 13987 | F: Documentation/devicetree/bindings/misc/atmel-ssc.txt |
| @@ -14015,7 +14010,7 @@ F: drivers/usb/gadget/udc/atmel_usba_udc.* · 22 unmodified lines | ||
| 14015 | 14010 | |
| 14016 | 14011 | MICROCHIP WILC1000 WIFI DRIVER |
| 14017 | 14012 | M: Ajay Singh <ajay.kathat@microchip.com> |
| 14018 | −M: Claudiu Beznea <claudiu.beznea@microchip.com> | |
| 14013 | +M: Claudiu Beznea <claudiu.beznea@tuxon.dev> | |
| 14019 | 14014 | L: linux-wireless@vger.kernel.org |
| 14020 | 14015 | S: Supported |
| 14021 | 14016 | F: drivers/net/wireless/microchip/wilc1000/ |
| @@ -16298,6 +16293,7 @@ F: drivers/pci/controller/dwc/pci-exynos.c · 2276 unmodified lines | ||
| 16298 | 16293 | PCI DRIVER FOR SYNOPSYS DESIGNWARE |
| 16299 | 16294 | M: Jingoo Han <jingoohan1@gmail.com> |
| 16300 | 16295 | M: Gustavo Pimentel <gustavo.pimentel@synopsys.com> |
| 16296 | +M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | |
| 16301 | 16297 | L: linux-pci@vger.kernel.org |
| 16302 | 16298 | S: Maintained |
| 16303 | 16299 | F: Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml |
| @@ -17449,6 +17445,7 @@ F: drivers/media/tuners/qt1010* · 1145 unmodified lines | ||
| 17449 | 17445 | |
| 17450 | 17446 | QUALCOMM ATH12K WIRELESS DRIVER |
| 17451 | 17447 | M: Kalle Valo <kvalo@kernel.org> |
| 17448 | +M: Jeff Johnson <quic_jjohnson@quicinc.com> | |
| 17452 | 17449 | L: ath12k@lists.infradead.org |
| 17453 | 17450 | S: Supported |
| 17454 | 17451 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git |
| @@ -17456,6 +17453,7 @@ F: drivers/net/wireless/ath/ath12k/ · 1 unmodified line | ||
| 17456 | 17453 | |
| 17457 | 17454 | QUALCOMM ATHEROS ATH10K WIRELESS DRIVER |
| 17458 | 17455 | M: Kalle Valo <kvalo@kernel.org> |
| 17456 | +M: Jeff Johnson <quic_jjohnson@quicinc.com> | |
| 17459 | 17457 | L: ath10k@lists.infradead.org |
| 17460 | 17458 | S: Supported |
| 17461 | 17459 | W: https://wireless.wiki.kernel.org/en/users/Drivers/ath10k |
| @@ -17465,6 +17463,7 @@ F: drivers/net/wireless/ath/ath10k/ · 3 unmodified lines | ||
| 17465 | 17463 | |
| 17466 | 17464 | QUALCOMM ATHEROS ATH11K WIRELESS DRIVER |
| 17467 | 17465 | M: Kalle Valo <kvalo@kernel.org> |
| 17466 | +M: Jeff Johnson <quic_jjohnson@quicinc.com> | |
| 17468 | 17467 | L: ath11k@lists.infradead.org |
| 17469 | 17468 | S: Supported |
| 17470 | 17469 | W: https://wireless.wiki.kernel.org/en/users/Drivers/ath11k |
| @@ -17985,7 +17984,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.g · 514 unmodified lines | ||
| 17985 | 17984 | F: drivers/net/wireless/realtek/rtlwifi/ |
| 17986 | 17985 | |
| 17987 | 17986 | REALTEK WIRELESS DRIVER (rtw88) |
| 17988 | −M: Yan-Hsuan Chuang <tony0620emma@gmail.com> | |
| 17987 | +M: Ping-Ke Shih <pkshih@realtek.com> | |
| 17989 | 17988 | L: linux-wireless@vger.kernel.org |
| 17990 | 17989 | S: Maintained |
| 17991 | 17990 | F: drivers/net/wireless/realtek/rtw88/ |
| @@ -18510,17 +18509,14 @@ RTL8180 WIRELESS DRIVER · 518 unmodified lines | ||
| 18510 | 18509 | L: linux-wireless@vger.kernel.org |
| 18511 | 18510 | S: Orphan |
| 18512 | 18511 | W: https://wireless.wiki.kernel.org/ |
| 18513 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | |
| 18514 | 18512 | F: drivers/net/wireless/realtek/rtl818x/rtl8180/ |
| 18515 | 18513 | |
| 18516 | 18514 | RTL8187 WIRELESS DRIVER |
| 18517 | −M: Herton Ronaldo Krzesinski <herton@canonical.com> | |
| 18518 | −M: Hin-Tak Leung <htl10@users.sourceforge.net> | |
| 18515 | +M: Hin-Tak Leung <hintak.leung@gmail.com> | |
| 18519 | 18516 | M: Larry Finger <Larry.Finger@lwfinger.net> |
| 18520 | 18517 | L: linux-wireless@vger.kernel.org |
| 18521 | 18518 | S: Maintained |
| 18522 | 18519 | W: https://wireless.wiki.kernel.org/ |
| 18523 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | |
| 18524 | 18520 | F: drivers/net/wireless/realtek/rtl818x/rtl8187/ |
| 18525 | 18521 | |
| 18526 | 18522 | RTL8XXXU WIRELESS DRIVER (rtl8xxxu) |
| @@ -20404,7 +20400,6 @@ F: drivers/pwm/pwm-stm32* · 1877 unmodified lines | ||
| 20404 | 20400 | F: include/linux/*/stm32-*tim* |
| 20405 | 20401 | |
| 20406 | 20402 | STMMAC ETHERNET DRIVER |
| 20407 | −M: Giuseppe Cavallaro <peppe.cavallaro@st.com> | |
| 20408 | 20403 | M: Alexandre Torgue <alexandre.torgue@foss.st.com> |
| 20409 | 20404 | M: Jose Abreu <joabreu@synopsys.com> |
| 20410 | 20405 | L: netdev@vger.kernel.org |
| @@ -21681,11 +21676,14 @@ S: Orphan · 1270 unmodified lines | ||
| 21681 | 21676 | F: drivers/net/ethernet/dec/tulip/ |
| 21682 | 21677 | |
| 21683 | 21678 | TUN/TAP driver |
| 21684 | −M: Maxim Krasnyansky <maxk@qti.qualcomm.com> | |
| 21679 | +M: Willem de Bruijn <willemdebruijn.kernel@gmail.com> | |
| 21680 | +M: Jason Wang <jasowang@redhat.com> | |
| 21685 | 21681 | S: Maintained |
| 21686 | 21682 | W: http://vtun.sourceforge.net/tun |
| 21687 | 21683 | F: Documentation/networking/tuntap.rst |
| 21688 | 21684 | F: arch/um/os-Linux/drivers/ |
| 21685 | +F: drivers/net/tap.c | |
| 21686 | +F: drivers/net/tun.c | |
| 21689 | 21687 | |
| 21690 | 21688 | TURBOCHANNEL SUBSYSTEM |
| 21691 | 21689 | M: "Maciej W. Rozycki" <macro@orcam.me.uk> |
| @@ -21908,9 +21906,8 @@ S: Maintained · 216 unmodified lines | ||
| 21908 | 21906 | F: drivers/usb/misc/apple-mfi-fastcharge.c |
| 21909 | 21907 | |
| 21910 | 21908 | USB AR5523 WIRELESS DRIVER |
| 21911 | −M: Pontus Fuchs <pontus.fuchs@gmail.com> | |
| 21912 | 21909 | L: linux-wireless@vger.kernel.org |
| 21913 | −S: Maintained | |
| 21910 | +S: Orphan | |
| 21914 | 21911 | F: drivers/net/wireless/ath/ar5523/ |
| 21915 | 21912 | |
| 21916 | 21913 | USB ATTACHED SCSI |
| @@ -22187,9 +22184,8 @@ F: drivers/usb/gadget/legacy/webcam.c · 270 unmodified lines | ||
| 22187 | 22184 | F: include/uapi/linux/usb/g_uvc.h |
| 22188 | 22185 | |
| 22189 | 22186 | USB WIRELESS RNDIS DRIVER (rndis_wlan) |
| 22190 | −M: Jussi Kivilinna <jussi.kivilinna@iki.fi> | |
| 22191 | 22187 | L: linux-wireless@vger.kernel.org |
| 22192 | −S: Maintained | |
| 22188 | +S: Orphan | |
| 22193 | 22189 | F: drivers/net/wireless/legacy/rndis_wlan.c |
| 22194 | 22190 | |
| 22195 | 22191 | USB XHCI DRIVER |
| @@ -22964,7 +22960,7 @@ F: drivers/input/misc/wistron_btns.c · 768 unmodified lines | ||
| 22964 | 22960 | |
| 22965 | 22961 | WL3501 WIRELESS PCMCIA CARD DRIVER |
| 22966 | 22962 | L: linux-wireless@vger.kernel.org |
| 22967 | −S: Odd fixes | |
| 22963 | +S: Orphan | |
| 22968 | 22964 | F: drivers/net/wireless/legacy/wl3501* |
| 22969 | 22965 | |
| 22970 | 22966 | WMI BINARY MOF DRIVER |
| @@ -23535,11 +23531,8 @@ S: Maintained · 564 unmodified lines | ||
| 23535 | 23531 | F: mm/zbud.c |
| 23536 | 23532 | |
| 23537 | 23533 | ZD1211RW WIRELESS DRIVER |
| 23538 | −M: Ulrich Kunitz <kune@deine-taler.de> | |
| 23539 | 23534 | L: linux-wireless@vger.kernel.org |
| 23540 | −L: zd1211-devs@lists.sourceforge.net (subscribers-only) | |
| 23541 | −S: Maintained | |
| 23542 | −W: http://zd1211.ath.cx/wiki/DriverRewrite | |
| 23535 | +S: Orphan | |
| 23543 | 23536 | F: drivers/net/wireless/zydas/zd1211rw/ |
| 23544 | 23537 | |
| 23545 | 23538 | ZD1301 MEDIA DRIVER |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 5 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc4 | |
| 5 | +EXTRAVERSION = -rc6 | |
| 6 | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -47,12 +47,6 @@ unsigned long __get_wchan(struct task_struct *p); · 46 unmodified lines | ||
| 47 | 47 | |
| 48 | 48 | #define ARCH_HAS_PREFETCH |
| 49 | 49 | #define ARCH_HAS_PREFETCHW |
| 50 | −#define ARCH_HAS_SPINLOCK_PREFETCH | |
| 51 | − | |
| 52 | −#ifndef CONFIG_SMP | |
| 53 | −/* Nothing to prefetch. */ | |
| 54 | −#define spin_lock_prefetch(lock) do { } while (0) | |
| 55 | −#endif | |
| 56 | 50 | |
| 57 | 51 | extern inline void prefetch(const void *ptr) |
| 58 | 52 | { |
| @@ -64,11 +58,4 @@ extern inline void prefetchw(const void *ptr) · 5 unmodified lines | ||
| 64 | 58 | __builtin_prefetch(ptr, 1, 3); |
| 65 | 59 | } |
| 66 | 60 | |
| 67 | −#ifdef CONFIG_SMP | |
| 68 | −extern inline void spin_lock_prefetch(const void *ptr) | |
| 69 | −{ | |
| 70 | − __builtin_prefetch(ptr, 1, 3); | |
| 71 | −} | |
| 72 | −#endif | |
| 73 | − | |
| 74 | 61 | #endif /* __ASM_ALPHA_PROCESSOR_H */ |
| @@ -385,8 +385,7 @@ setup_memory(void *kernel_end) · 384 unmodified lines | ||
| 385 | 385 | #endif /* CONFIG_BLK_DEV_INITRD */ |
| 386 | 386 | } |
| 387 | 387 | |
| 388 | −int __init | |
| 389 | −page_is_ram(unsigned long pfn) | |
| 388 | +int page_is_ram(unsigned long pfn) | |
| 390 | 389 | { |
| 391 | 390 | struct memclust_struct * cluster; |
| 392 | 391 | struct memdesc_struct * memdesc; |
| @@ -172,7 +172,7 @@ · 171 unmodified lines | ||
| 172 | 172 | status = "disabled"; |
| 173 | 173 | |
| 174 | 174 | uart4: serial@200 { |
| 175 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 175 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 176 | 176 | reg = <0x200 0x200>; |
| 177 | 177 | interrupts = <13 IRQ_TYPE_LEVEL_HIGH 7>; |
| 178 | 178 | dmas = <&dma0 |
| @@ -240,7 +240,7 @@ · 61 unmodified lines | ||
| 240 | 240 | status = "disabled"; |
| 241 | 241 | |
| 242 | 242 | uart5: serial@200 { |
| 243 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 243 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 244 | 244 | reg = <0x200 0x200>; |
| 245 | 245 | atmel,usart-mode = <AT91_USART_MODE_SERIAL>; |
| 246 | 246 | interrupts = <14 IRQ_TYPE_LEVEL_HIGH 7>; |
| @@ -370,7 +370,7 @@ · 123 unmodified lines | ||
| 370 | 370 | status = "disabled"; |
| 371 | 371 | |
| 372 | 372 | uart11: serial@200 { |
| 373 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 373 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 374 | 374 | reg = <0x200 0x200>; |
| 375 | 375 | interrupts = <32 IRQ_TYPE_LEVEL_HIGH 7>; |
| 376 | 376 | dmas = <&dma0 |
| @@ -419,7 +419,7 @@ · 42 unmodified lines | ||
| 419 | 419 | status = "disabled"; |
| 420 | 420 | |
| 421 | 421 | uart12: serial@200 { |
| 422 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 422 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 423 | 423 | reg = <0x200 0x200>; |
| 424 | 424 | interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>; |
| 425 | 425 | dmas = <&dma0 |
| @@ -576,7 +576,7 @@ · 150 unmodified lines | ||
| 576 | 576 | status = "disabled"; |
| 577 | 577 | |
| 578 | 578 | uart6: serial@200 { |
| 579 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 579 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 580 | 580 | reg = <0x200 0x200>; |
| 581 | 581 | interrupts = <9 IRQ_TYPE_LEVEL_HIGH 7>; |
| 582 | 582 | dmas = <&dma0 |
| @@ -625,7 +625,7 @@ · 42 unmodified lines | ||
| 625 | 625 | status = "disabled"; |
| 626 | 626 | |
| 627 | 627 | uart7: serial@200 { |
| 628 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 628 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 629 | 629 | reg = <0x200 0x200>; |
| 630 | 630 | interrupts = <10 IRQ_TYPE_LEVEL_HIGH 7>; |
| 631 | 631 | dmas = <&dma0 |
| @@ -674,7 +674,7 @@ · 42 unmodified lines | ||
| 674 | 674 | status = "disabled"; |
| 675 | 675 | |
| 676 | 676 | uart8: serial@200 { |
| 677 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 677 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 678 | 678 | reg = <0x200 0x200>; |
| 679 | 679 | interrupts = <11 IRQ_TYPE_LEVEL_HIGH 7>; |
| 680 | 680 | dmas = <&dma0 |
| @@ -723,7 +723,7 @@ · 42 unmodified lines | ||
| 723 | 723 | status = "disabled"; |
| 724 | 724 | |
| 725 | 725 | uart0: serial@200 { |
| 726 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 726 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 727 | 727 | reg = <0x200 0x200>; |
| 728 | 728 | interrupts = <5 IRQ_TYPE_LEVEL_HIGH 7>; |
| 729 | 729 | dmas = <&dma0 |
| @@ -791,7 +791,7 @@ · 61 unmodified lines | ||
| 791 | 791 | status = "disabled"; |
| 792 | 792 | |
| 793 | 793 | uart1: serial@200 { |
| 794 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 794 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 795 | 795 | reg = <0x200 0x200>; |
| 796 | 796 | interrupts = <6 IRQ_TYPE_LEVEL_HIGH 7>; |
| 797 | 797 | dmas = <&dma0 |
| @@ -859,7 +859,7 @@ · 61 unmodified lines | ||
| 859 | 859 | status = "disabled"; |
| 860 | 860 | |
| 861 | 861 | uart2: serial@200 { |
| 862 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 862 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 863 | 863 | reg = <0x200 0x200>; |
| 864 | 864 | interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7>; |
| 865 | 865 | dmas = <&dma0 |
| @@ -927,7 +927,7 @@ · 61 unmodified lines | ||
| 927 | 927 | status = "disabled"; |
| 928 | 928 | |
| 929 | 929 | uart3: serial@200 { |
| 930 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 930 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 931 | 931 | reg = <0x200 0x200>; |
| 932 | 932 | interrupts = <8 IRQ_TYPE_LEVEL_HIGH 7>; |
| 933 | 933 | dmas = <&dma0 |
| @@ -1050,7 +1050,7 @@ · 116 unmodified lines | ||
| 1050 | 1050 | status = "disabled"; |
| 1051 | 1051 | |
| 1052 | 1052 | uart9: serial@200 { |
| 1053 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 1053 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 1054 | 1054 | reg = <0x200 0x200>; |
| 1055 | 1055 | interrupts = <15 IRQ_TYPE_LEVEL_HIGH 7>; |
| 1056 | 1056 | dmas = <&dma0 |
| @@ -1099,7 +1099,7 @@ · 42 unmodified lines | ||
| 1099 | 1099 | status = "disabled"; |
| 1100 | 1100 | |
| 1101 | 1101 | uart10: serial@200 { |
| 1102 | − compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart"; | |
| 1102 | + compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart"; | |
| 1103 | 1103 | reg = <0x200 0x200>; |
| 1104 | 1104 | interrupts = <16 IRQ_TYPE_LEVEL_HIGH 7>; |
| 1105 | 1105 | dmas = <&dma0 |
| @@ -161,7 +161,7 @@ · 160 unmodified lines | ||
| 161 | 161 | }; |
| 162 | 162 | |
| 163 | 163 | watchdog: watchdog@90060000 { |
| 164 | − compatible = "arm,amba-primecell"; | |
| 164 | + compatible = "arm,primecell"; | |
| 165 | 165 | reg = <0x90060000 0x1000>; |
| 166 | 166 | interrupts = <3>; |
| 167 | 167 | }; |
| @@ -60,6 +60,16 @@ · 59 unmodified lines | ||
| 60 | 60 | status = "okay"; |
| 61 | 61 | }; |
| 62 | 62 | |
| 63 | +&cpu0 { | |
| 64 | + /* CPU rated to 800 MHz, not the default 1.2GHz. */ | |
| 65 | + operating-points = < | |
| 66 | + /* kHz uV */ | |
| 67 | + 166666 850000 | |
| 68 | + 400000 900000 | |
| 69 | + 800000 1050000 | |
| 70 | + >; | |
| 71 | +}; | |
| 72 | + | |
| 63 | 73 | &ecspi1 { |
| 64 | 74 | pinctrl-names = "default"; |
| 65 | 75 | pinctrl-0 = <&pinctrl_ecspi1>; |
| @@ -552,7 +552,7 @@ · 551 unmodified lines | ||
| 552 | 552 | reg = <0x020ca000 0x1000>; |
| 553 | 553 | interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; |
| 554 | 554 | clocks = <&clks IMX6SLL_CLK_USBPHY2>; |
| 555 | − phy-reg_3p0-supply = <®_3p0>; | |
| 555 | + phy-3p0-supply = <®_3p0>; | |
| 556 | 556 | fsl,anatop = <&anatop>; |
| 557 | 557 | }; |
| 558 | 558 | |
| @@ -105,5 +105,4 @@ void sharpsl_pm_led(int val); · 104 unmodified lines | ||
| 105 | 105 | #define MAX1111_ACIN_VOLT 6u |
| 106 | 106 | int sharpsl_pm_pxa_read_max1111(int channel); |
| 107 | 107 | |
| 108 | −void corgi_lcd_limit_intensity(int limit); | |
| 109 | 108 | #endif |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/interrupt.h> |
| 16 | 16 | #include <linux/platform_device.h> |
| 17 | 17 | #include <linux/apm-emulation.h> |
| 18 | +#include <linux/spi/corgi_lcd.h> | |
| 18 | 19 | |
| 19 | 20 | #include <asm/irq.h> |
| 20 | 21 | #include <asm/mach-types.h> |
| @@ -145,7 +145,7 @@ · 144 unmodified lines | ||
| 145 | 145 | status = "okay"; |
| 146 | 146 | clock-frequency = <100000>; |
| 147 | 147 | i2c-sda-falling-time-ns = <890>; /* hcnt */ |
| 148 | − i2c-sdl-falling-time-ns = <890>; /* lcnt */ | |
| 148 | + i2c-scl-falling-time-ns = <890>; /* lcnt */ | |
| 149 | 149 | |
| 150 | 150 | pinctrl-names = "default", "gpio"; |
| 151 | 151 | pinctrl-0 = <&i2c1_pmx_func>; |
| @@ -141,7 +141,7 @@ · 140 unmodified lines | ||
| 141 | 141 | status = "okay"; |
| 142 | 142 | clock-frequency = <100000>; |
| 143 | 143 | i2c-sda-falling-time-ns = <890>; /* hcnt */ |
| 144 | − i2c-sdl-falling-time-ns = <890>; /* lcnt */ | |
| 144 | + i2c-scl-falling-time-ns = <890>; /* lcnt */ | |
| 145 | 145 | |
| 146 | 146 | adc@14 { |
| 147 | 147 | compatible = "lltc,ltc2497"; |
| @@ -1 +0,0 @@ | ||
| 1 | −../../../../arm/boot/dts/vexpress-v2m-rs1.dtsi | |
| @@ -141,7 +141,7 @@ · 140 unmodified lines | ||
| 141 | 141 | }; |
| 142 | 142 | |
| 143 | 143 | &gpio1 { |
| 144 | − gpio-line-names = "nINT_ETHPHY", "LED_RED", "WDOG_INT", "X_RTC_INT", | |
| 144 | + gpio-line-names = "", "LED_RED", "WDOG_INT", "X_RTC_INT", | |
| 145 | 145 | "", "", "", "RESET_ETHPHY", |
| 146 | 146 | "CAN_nINT", "CAN_EN", "nENABLE_FLATLINK", "", |
| 147 | 147 | "USB_OTG_VBUS_EN", "", "LED_GREEN", "LED_BLUE"; |
| @@ -111,7 +111,7 @@ · 110 unmodified lines | ||
| 111 | 111 | }; |
| 112 | 112 | |
| 113 | 113 | &gpio1 { |
| 114 | − gpio-line-names = "nINT_ETHPHY", "", "WDOG_INT", "X_RTC_INT", | |
| 114 | + gpio-line-names = "", "", "WDOG_INT", "X_RTC_INT", | |
| 115 | 115 | "", "", "", "RESET_ETHPHY", |
| 116 | 116 | "", "", "nENABLE_FLATLINK"; |
| 117 | 117 | }; |
| @@ -210,7 +210,7 @@ · 92 unmodified lines | ||
| 210 | 210 | }; |
| 211 | 211 | }; |
| 212 | 212 | |
| 213 | − reg_vdd_gpu: buck3 { | |
| 213 | + reg_vdd_vpu: buck3 { | |
| 214 | 214 | regulator-always-on; |
| 215 | 215 | regulator-boot-on; |
| 216 | 216 | regulator-max-microvolt = <1000000>; |
| @@ -567,6 +567,10 @@ · 566 unmodified lines | ||
| 567 | 567 | status = "okay"; |
| 568 | 568 | }; |
| 569 | 569 | |
| 570 | +&disp_blk_ctrl { | |
| 571 | + status = "disabled"; | |
| 572 | +}; | |
| 573 | + | |
| 570 | 574 | &pgc_mipi { |
| 571 | 575 | status = "disabled"; |
| 572 | 576 | }; |
| @@ -628,6 +628,10 @@ · 627 unmodified lines | ||
| 628 | 628 | status = "okay"; |
| 629 | 629 | }; |
| 630 | 630 | |
| 631 | +&disp_blk_ctrl { | |
| 632 | + status = "disabled"; | |
| 633 | +}; | |
| 634 | + | |
| 631 | 635 | &pgc_mipi { |
| 632 | 636 | status = "disabled"; |
| 633 | 637 | }; |
| @@ -358,7 +358,7 @@ · 357 unmodified lines | ||
| 358 | 358 | MX8MN_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 |
| 359 | 359 | MX8MN_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 |
| 360 | 360 | MX8MN_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f |
| 361 | − MX8MN_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19 | |
| 361 | + MX8MN_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x159 | |
| 362 | 362 | >; |
| 363 | 363 | }; |
| 364 | 364 | |
| @@ -772,7 +772,7 @@ · 771 unmodified lines | ||
| 772 | 772 | <&clk IMX8MQ_SYS1_PLL_800M>, |
| 773 | 773 | <&clk IMX8MQ_VPU_PLL>; |
| 774 | 774 | assigned-clock-rates = <600000000>, |
| 775 | − <600000000>, | |
| 775 | + <300000000>, | |
| 776 | 776 | <800000000>, |
| 777 | 777 | <0>; |
| 778 | 778 | }; |
| @@ -223,20 +223,20 @@ · 222 unmodified lines | ||
| 223 | 223 | <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>, |
| 224 | 224 | <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>; |
| 225 | 225 | interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", |
| 226 | − "tgiv0", "tgie0", "tgif0", | |
| 227 | − "tgia1", "tgib1", "tgiv1", "tgiu1", | |
| 228 | − "tgia2", "tgib2", "tgiv2", "tgiu2", | |
| 226 | + "tciv0", "tgie0", "tgif0", | |
| 227 | + "tgia1", "tgib1", "tciv1", "tciu1", | |
| 228 | + "tgia2", "tgib2", "tciv2", "tciu2", | |
| 229 | 229 | "tgia3", "tgib3", "tgic3", "tgid3", |
| 230 | − "tgiv3", | |
| 230 | + "tciv3", | |
| 231 | 231 | "tgia4", "tgib4", "tgic4", "tgid4", |
| 232 | − "tgiv4", | |
| 232 | + "tciv4", | |
| 233 | 233 | "tgiu5", "tgiv5", "tgiw5", |
| 234 | 234 | "tgia6", "tgib6", "tgic6", "tgid6", |
| 235 | − "tgiv6", | |
| 235 | + "tciv6", | |
| 236 | 236 | "tgia7", "tgib7", "tgic7", "tgid7", |
| 237 | − "tgiv7", | |
| 237 | + "tciv7", | |
| 238 | 238 | "tgia8", "tgib8", "tgic8", "tgid8", |
| 239 | − "tgiv8", "tgiu8"; | |
| 239 | + "tciv8", "tciu8"; | |
| 240 | 240 | clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>; |
| 241 | 241 | power-domains = <&cpg>; |
| 242 | 242 | resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>; |
| @@ -223,20 +223,20 @@ · 222 unmodified lines | ||
| 223 | 223 | <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>, |
| 224 | 224 | <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>; |
| 225 | 225 | interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", |
| 226 | − "tgiv0", "tgie0", "tgif0", | |
| 227 | − "tgia1", "tgib1", "tgiv1", "tgiu1", | |
| 228 | − "tgia2", "tgib2", "tgiv2", "tgiu2", | |
| 226 | + "tciv0", "tgie0", "tgif0", | |
| 227 | + "tgia1", "tgib1", "tciv1", "tciu1", | |
| 228 | + "tgia2", "tgib2", "tciv2", "tciu2", | |
| 229 | 229 | "tgia3", "tgib3", "tgic3", "tgid3", |
| 230 | − "tgiv3", | |
| 230 | + "tciv3", | |
| 231 | 231 | "tgia4", "tgib4", "tgic4", "tgid4", |
| 232 | − "tgiv4", | |
| 232 | + "tciv4", | |
| 233 | 233 | "tgiu5", "tgiv5", "tgiw5", |
| 234 | 234 | "tgia6", "tgib6", "tgic6", "tgid6", |
| 235 | − "tgiv6", | |
| 235 | + "tciv6", | |
| 236 | 236 | "tgia7", "tgib7", "tgic7", "tgid7", |
| 237 | − "tgiv7", | |
| 237 | + "tciv7", | |
| 238 | 238 | "tgia8", "tgib8", "tgic8", "tgid8", |
| 239 | − "tgiv8", "tgiu8"; | |
| 239 | + "tciv8", "tciu8"; | |
| 240 | 240 | clocks = <&cpg CPG_MOD R9A07G054_MTU_X_MCK_MTU3>; |
| 241 | 241 | power-domains = <&cpg>; |
| 242 | 242 | resets = <&cpg R9A07G054_MTU_X_PRESET_MTU3>; |
| @@ -31,6 +31,13 @@ · 30 unmodified lines | ||
| 31 | 31 | .Lskip_hcrx_\@: |
| 32 | 32 | .endm |
| 33 | 33 | |
| 34 | +/* Check if running in host at EL2 mode, i.e., (h)VHE. Jump to fail if not. */ | |
| 35 | +.macro __check_hvhe fail, tmp | |
| 36 | + mrs \tmp, hcr_el2 | |
| 37 | + and \tmp, \tmp, #HCR_E2H | |
| 38 | + cbz \tmp, \fail | |
| 39 | +.endm | |
| 40 | + | |
| 34 | 41 | /* |
| 35 | 42 | * Allow Non-secure EL1 and EL0 to access physical timer and counter. |
| 36 | 43 | * This is not necessary for VHE, since the host kernel runs in EL2, |
| @@ -43,9 +50,7 @@ · 6 unmodified lines | ||
| 43 | 50 | */ |
| 44 | 51 | .macro __init_el2_timers |
| 45 | 52 | mov x0, #3 // Enable EL1 physical timers |
| 46 | − mrs x1, hcr_el2 | |
| 47 | − and x1, x1, #HCR_E2H | |
| 48 | − cbz x1, .LnVHE_\@ | |
| 53 | + __check_hvhe .LnVHE_\@, x1 | |
| 49 | 54 | lsl x0, x0, #10 |
| 50 | 55 | .LnVHE_\@: |
| 51 | 56 | msr cnthctl_el2, x0 |
| @@ -139,15 +144,14 @@ · 87 unmodified lines | ||
| 139 | 144 | |
| 140 | 145 | /* Coprocessor traps */ |
| 141 | 146 | .macro __init_el2_cptr |
| 142 | − mrs x1, hcr_el2 | |
| 143 | − and x1, x1, #HCR_E2H | |
| 144 | − cbz x1, .LnVHE_\@ | |
| 147 | + __check_hvhe .LnVHE_\@, x1 | |
| 145 | 148 | mov x0, #(CPACR_EL1_FPEN_EL1EN | CPACR_EL1_FPEN_EL0EN) |
| 146 | − b .Lset_cptr_\@ | |
| 149 | + msr cpacr_el1, x0 | |
| 150 | + b .Lskip_set_cptr_\@ | |
| 147 | 151 | .LnVHE_\@: |
| 148 | 152 | mov x0, #0x33ff |
| 149 | −.Lset_cptr_\@: | |
| 150 | 153 | msr cptr_el2, x0 // Disable copro. traps to EL2 |
| 154 | +.Lskip_set_cptr_\@: | |
| 151 | 155 | .endm |
| 152 | 156 | |
| 153 | 157 | /* Disable any fine grained traps */ |
| @@ -268,19 +272,19 @@ · 114 unmodified lines | ||
| 268 | 272 | check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2 |
| 269 | 273 | |
| 270 | 274 | .Linit_sve_\@: /* SVE register access */ |
| 271 | − mrs x0, cptr_el2 // Disable SVE traps | |
| 272 | − mrs x1, hcr_el2 | |
| 273 | − and x1, x1, #HCR_E2H | |
| 274 | − cbz x1, .Lcptr_nvhe_\@ | |
| 275 | + __check_hvhe .Lcptr_nvhe_\@, x1 | |
| 275 | 276 | |
| 276 | − // VHE case | |
| 277 | + // (h)VHE case | |
| 278 | + mrs x0, cpacr_el1 // Disable SVE traps | |
| 277 | 279 | orr x0, x0, #(CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN) |
| 278 | − b .Lset_cptr_\@ | |
| 280 | + msr cpacr_el1, x0 | |
| 281 | + b .Lskip_set_cptr_\@ | |
| 279 | 282 | |
| 280 | 283 | .Lcptr_nvhe_\@: // nVHE case |
| 284 | + mrs x0, cptr_el2 // Disable SVE traps | |
| 281 | 285 | bic x0, x0, #CPTR_EL2_TZ |
| 282 | −.Lset_cptr_\@: | |
| 283 | 286 | msr cptr_el2, x0 |
| 287 | +.Lskip_set_cptr_\@: | |
| 284 | 288 | isb |
| 285 | 289 | mov x1, #ZCR_ELx_LEN_MASK // SVE: Enable full vector |
| 286 | 290 | msr_s SYS_ZCR_EL2, x1 // length for EL1. |
| @@ -289,9 +293,19 @@ · 2 unmodified lines | ||
| 289 | 293 | check_override id_aa64pfr1, ID_AA64PFR1_EL1_SME_SHIFT, .Linit_sme_\@, .Lskip_sme_\@, x1, x2 |
| 290 | 294 | |
| 291 | 295 | .Linit_sme_\@: /* SME register access and priority mapping */ |
| 296 | + __check_hvhe .Lcptr_nvhe_sme_\@, x1 | |
| 297 | + | |
| 298 | + // (h)VHE case | |
| 299 | + mrs x0, cpacr_el1 // Disable SME traps | |
| 300 | + orr x0, x0, #(CPACR_EL1_SMEN_EL0EN | CPACR_EL1_SMEN_EL1EN) | |
| 301 | + msr cpacr_el1, x0 | |
| 302 | + b .Lskip_set_cptr_sme_\@ | |
| 303 | + | |
| 304 | +.Lcptr_nvhe_sme_\@: // nVHE case | |
| 292 | 305 | mrs x0, cptr_el2 // Disable SME traps |
| 293 | 306 | bic x0, x0, #CPTR_EL2_TSM |
| 294 | 307 | msr cptr_el2, x0 |
| 308 | +.Lskip_set_cptr_sme_\@: | |
| 295 | 309 | isb |
| 296 | 310 | |
| 297 | 311 | mrs x1, sctlr_el2 |
| @@ -278,7 +278,7 @@ asmlinkage void __noreturn hyp_panic_bad_stack(void); · 277 unmodified lines | ||
| 278 | 278 | asmlinkage void kvm_unexpected_el2_exception(void); |
| 279 | 279 | struct kvm_cpu_context; |
| 280 | 280 | void handle_trap(struct kvm_cpu_context *host_ctxt); |
| 281 | −asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on); | |
| 281 | +asmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on); | |
| 282 | 282 | void __noreturn __pkvm_init_finalise(void); |
| 283 | 283 | void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc); |
| 284 | 284 | void kvm_patch_vector_branch(struct alt_instr *alt, |
| @@ -571,6 +571,14 @@ static inline bool vcpu_has_feature(struct kvm_vcpu *vcpu, int feature) · 570 unmodified lines | ||
| 571 | 571 | return test_bit(feature, vcpu->arch.features); |
| 572 | 572 | } |
| 573 | 573 | |
| 574 | +static __always_inline void kvm_write_cptr_el2(u64 val) | |
| 575 | +{ | |
| 576 | + if (has_vhe() || has_hvhe()) | |
| 577 | + write_sysreg(val, cpacr_el1); | |
| 578 | + else | |
| 579 | + write_sysreg(val, cptr_el2); | |
| 580 | +} | |
| 581 | + | |
| 574 | 582 | static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu) |
| 575 | 583 | { |
| 576 | 584 | u64 val; |
| @@ -578,8 +586,16 @@ static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu) · 1 unmodified line | ||
| 578 | 586 | if (has_vhe()) { |
| 579 | 587 | val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN | |
| 580 | 588 | CPACR_EL1_ZEN_EL1EN); |
| 589 | + if (cpus_have_final_cap(ARM64_SME)) | |
| 590 | + val |= CPACR_EL1_SMEN_EL1EN; | |
| 581 | 591 | } else if (has_hvhe()) { |
| 582 | 592 | val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN); |
| 593 | + | |
| 594 | + if (!vcpu_has_sve(vcpu) || | |
| 595 | + (vcpu->arch.fp_state != FP_STATE_GUEST_OWNED)) | |
| 596 | + val |= CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN; | |
| 597 | + if (cpus_have_final_cap(ARM64_SME)) | |
| 598 | + val |= CPACR_EL1_SMEN_EL1EN | CPACR_EL1_SMEN_EL0EN; | |
| 583 | 599 | } else { |
| 584 | 600 | val = CPTR_NVHE_EL2_RES1; |
| 585 | 601 | |
| @@ -597,9 +613,6 @@ static __always_inline void kvm_reset_cptr_el2(struct kvm_vcpu *vcpu) · 11 unmodified lines | ||
| 597 | 613 | { |
| 598 | 614 | u64 val = kvm_get_reset_cptr_el2(vcpu); |
| 599 | 615 | |
| 600 | − if (has_vhe() || has_hvhe()) | |
| 601 | − write_sysreg(val, cpacr_el1); | |
| 602 | − else | |
| 603 | − write_sysreg(val, cptr_el2); | |
| 616 | + kvm_write_cptr_el2(val); | |
| 604 | 617 | } |
| 605 | 618 | #endif /* __ARM64_KVM_EMULATE_H__ */ |
| @@ -359,14 +359,6 @@ static inline void prefetchw(const void *ptr) · 358 unmodified lines | ||
| 359 | 359 | asm volatile("prfm pstl1keep, %a0\n" : : "p" (ptr)); |
| 360 | 360 | } |
| 361 | 361 | |
| 362 | −#define ARCH_HAS_SPINLOCK_PREFETCH | |
| 363 | −static inline void spin_lock_prefetch(const void *ptr) | |
| 364 | −{ | |
| 365 | − asm volatile(ARM64_LSE_ATOMIC_INSN( | |
| 366 | − "prfm pstl1strm, %a0", | |
| 367 | − "nop") : : "p" (ptr)); | |
| 368 | −} | |
| 369 | − | |
| 370 | 362 | extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */ |
| 371 | 363 | extern void __init minsigstksz_setup(void); |
| 372 | 364 | |
| @@ -679,7 +679,7 @@ static void fpsimd_to_sve(struct task_struct *task) · 678 unmodified lines | ||
| 679 | 679 | void *sst = task->thread.sve_state; |
| 680 | 680 | struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state; |
| 681 | 681 | |
| 682 | − if (!system_supports_sve()) | |
| 682 | + if (!system_supports_sve() && !system_supports_sme()) | |
| 683 | 683 | return; |
| 684 | 684 | |
| 685 | 685 | vq = sve_vq_from_vl(thread_get_cur_vl(&task->thread)); |
| @@ -705,7 +705,7 @@ static void sve_to_fpsimd(struct task_struct *task) · 19 unmodified lines | ||
| 705 | 705 | unsigned int i; |
| 706 | 706 | __uint128_t const *p; |
| 707 | 707 | |
| 708 | − if (!system_supports_sve()) | |
| 708 | + if (!system_supports_sve() && !system_supports_sme()) | |
| 709 | 709 | return; |
| 710 | 710 | |
| 711 | 711 | vl = thread_get_cur_vl(&task->thread); |
| @@ -835,7 +835,8 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task) · 123 unmodified lines | ||
| 835 | 835 | void *sst = task->thread.sve_state; |
| 836 | 836 | struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state; |
| 837 | 837 | |
| 838 | − if (!test_tsk_thread_flag(task, TIF_SVE)) | |
| 838 | + if (!test_tsk_thread_flag(task, TIF_SVE) && | |
| 839 | + !thread_sm_enabled(&task->thread)) | |
| 839 | 840 | return; |
| 840 | 841 | |
| 841 | 842 | vq = sve_vq_from_vl(thread_get_cur_vl(&task->thread)); |
| @@ -909,7 +910,7 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type, · 67 unmodified lines | ||
| 909 | 910 | */ |
| 910 | 911 | task->thread.svcr &= ~(SVCR_SM_MASK | |
| 911 | 912 | SVCR_ZA_MASK); |
| 912 | − clear_thread_flag(TIF_SME); | |
| 913 | + clear_tsk_thread_flag(task, TIF_SME); | |
| 913 | 914 | free_sme = true; |
| 914 | 915 | } |
| 915 | 916 | } |
| @@ -932,11 +932,13 @@ static int sve_set_common(struct task_struct *target, · 931 unmodified lines | ||
| 932 | 932 | /* |
| 933 | 933 | * Ensure target->thread.sve_state is up to date with target's |
| 934 | 934 | * FPSIMD regs, so that a short copyin leaves trailing |
| 935 | − * registers unmodified. Always enable SVE even if going into | |
| 936 | − * streaming mode. | |
| 935 | + * registers unmodified. Only enable SVE if we are | |
| 936 | + * configuring normal SVE, a system with streaming SVE may not | |
| 937 | + * have normal SVE. | |
| 937 | 938 | */ |
| 938 | 939 | fpsimd_sync_to_sve(target); |
| 939 | − set_tsk_thread_flag(target, TIF_SVE); | |
| 940 | + if (type == ARM64_VEC_SVE) | |
| 941 | + set_tsk_thread_flag(target, TIF_SVE); | |
| 940 | 942 | target->thread.fp_type = FP_STATE_SVE; |
| 941 | 943 | |
| 942 | 944 | BUILD_BUG_ON(SVE_PT_SVE_OFFSET != sizeof(header)); |
| @@ -1180,6 +1182,8 @@ static int zt_set(struct task_struct *target, · 237 unmodified lines | ||
| 1180 | 1182 | if (ret == 0) |
| 1181 | 1183 | target->thread.svcr |= SVCR_ZA_MASK; |
| 1182 | 1184 | |
| 1185 | + fpsimd_flush_task_state(target); | |
| 1186 | + | |
| 1183 | 1187 | return ret; |
| 1184 | 1188 | } |
| 1185 | 1189 | |
| @@ -55,7 +55,7 @@ DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt); · 54 unmodified lines | ||
| 55 | 55 | |
| 56 | 56 | static bool vgic_present, kvm_arm_initialised; |
| 57 | 57 | |
| 58 | −static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled); | |
| 58 | +static DEFINE_PER_CPU(unsigned char, kvm_hyp_initialized); | |
| 59 | 59 | DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use); |
| 60 | 60 | |
| 61 | 61 | bool is_kvm_arm_initialised(void) |
| @@ -1864,18 +1864,24 @@ static void cpu_hyp_reinit(void) · 1802 unmodified lines | ||
| 1864 | 1864 | cpu_hyp_init_features(); |
| 1865 | 1865 | } |
| 1866 | 1866 | |
| 1867 | −static void _kvm_arch_hardware_enable(void *discard) | |
| 1867 | +static void cpu_hyp_init(void *discard) | |
| 1868 | 1868 | { |
| 1869 | − if (!__this_cpu_read(kvm_arm_hardware_enabled)) { | |
| 1869 | + if (!__this_cpu_read(kvm_hyp_initialized)) { | |
| 1870 | 1870 | cpu_hyp_reinit(); |
| 1871 | − __this_cpu_write(kvm_arm_hardware_enabled, 1); | |
| 1871 | + __this_cpu_write(kvm_hyp_initialized, 1); | |
| 1872 | 1872 | } |
| 1873 | 1873 | } |
| 1874 | 1874 | |
| 1875 | −int kvm_arch_hardware_enable(void) | |
| 1875 | +static void cpu_hyp_uninit(void *discard) | |
| 1876 | 1876 | { |
| 1877 | − int was_enabled; | |
| 1877 | + if (__this_cpu_read(kvm_hyp_initialized)) { | |
| 1878 | + cpu_hyp_reset(); | |
| 1879 | + __this_cpu_write(kvm_hyp_initialized, 0); | |
| 1880 | + } | |
| 1881 | +} | |
| 1878 | 1882 | |
| 1883 | +int kvm_arch_hardware_enable(void) | |
| 1884 | +{ | |
| 1879 | 1885 | /* |
| 1880 | 1886 | * Most calls to this function are made with migration |
| 1881 | 1887 | * disabled, but not with preemption disabled. The former is |
| @@ -1884,36 +1890,23 @@ int kvm_arch_hardware_enable(void) · 2 unmodified lines | ||
| 1884 | 1890 | */ |
| 1885 | 1891 | preempt_disable(); |
| 1886 | 1892 | |
| 1887 | − was_enabled = __this_cpu_read(kvm_arm_hardware_enabled); | |
| 1888 | − _kvm_arch_hardware_enable(NULL); | |
| 1893 | + cpu_hyp_init(NULL); | |
| 1889 | 1894 | |
| 1890 | − if (!was_enabled) { | |
| 1891 | − kvm_vgic_cpu_up(); | |
| 1892 | − kvm_timer_cpu_up(); | |
| 1893 | − } | |
| 1895 | + kvm_vgic_cpu_up(); | |
| 1896 | + kvm_timer_cpu_up(); | |
| 1894 | 1897 | |
| 1895 | 1898 | preempt_enable(); |
| 1896 | 1899 | |
| 1897 | 1900 | return 0; |
| 1898 | 1901 | } |
| 1899 | 1902 | |
| 1900 | −static void _kvm_arch_hardware_disable(void *discard) | |
| 1901 | −{ | |
| 1902 | − if (__this_cpu_read(kvm_arm_hardware_enabled)) { | |
| 1903 | − cpu_hyp_reset(); | |
| 1904 | − __this_cpu_write(kvm_arm_hardware_enabled, 0); | |
| 1905 | − } | |
| 1906 | −} | |
| 1907 | − | |
| 1908 | 1903 | void kvm_arch_hardware_disable(void) |
| 1909 | 1904 | { |
| 1910 | − if (__this_cpu_read(kvm_arm_hardware_enabled)) { | |
| 1911 | − kvm_timer_cpu_down(); | |
| 1912 | − kvm_vgic_cpu_down(); | |
| 1913 | − } | |
| 1905 | + kvm_timer_cpu_down(); | |
| 1906 | + kvm_vgic_cpu_down(); | |
| 1914 | 1907 | |
| 1915 | 1908 | if (!is_protected_kvm_enabled()) |
| 1916 | − _kvm_arch_hardware_disable(NULL); | |
| 1909 | + cpu_hyp_uninit(NULL); | |
| 1917 | 1910 | } |
| 1918 | 1911 | |
| 1919 | 1912 | #ifdef CONFIG_CPU_PM |
| @@ -1922,16 +1915,16 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, · 2 unmodified lines | ||
| 1922 | 1915 | void *v) |
| 1923 | 1916 | { |
| 1924 | 1917 | /* |
| 1925 | − * kvm_arm_hardware_enabled is left with its old value over | |
| 1918 | + * kvm_hyp_initialized is left with its old value over | |
| 1926 | 1919 | * PM_ENTER->PM_EXIT. It is used to indicate PM_EXIT should |
| 1927 | 1920 | * re-enable hyp. |
| 1928 | 1921 | */ |
| 1929 | 1922 | switch (cmd) { |
| 1930 | 1923 | case CPU_PM_ENTER: |
| 1931 | − if (__this_cpu_read(kvm_arm_hardware_enabled)) | |
| 1924 | + if (__this_cpu_read(kvm_hyp_initialized)) | |
| 1932 | 1925 | /* |
| 1933 | − * don't update kvm_arm_hardware_enabled here | |
| 1934 | − * so that the hardware will be re-enabled | |
| 1926 | + * don't update kvm_hyp_initialized here | |
| 1927 | + * so that the hyp will be re-enabled | |
| 1935 | 1928 | * when we resume. See below. |
| 1936 | 1929 | */ |
| 1937 | 1930 | cpu_hyp_reset(); |
| @@ -1939,8 +1932,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, · 1 unmodified line | ||
| 1939 | 1932 | return NOTIFY_OK; |
| 1940 | 1933 | case CPU_PM_ENTER_FAILED: |
| 1941 | 1934 | case CPU_PM_EXIT: |
| 1942 | − if (__this_cpu_read(kvm_arm_hardware_enabled)) | |
| 1943 | − /* The hardware was enabled before suspend. */ | |
| 1935 | + if (__this_cpu_read(kvm_hyp_initialized)) | |
| 1936 | + /* The hyp was enabled before suspend. */ | |
| 1944 | 1937 | cpu_hyp_reinit(); |
| 1945 | 1938 | |
| 1946 | 1939 | return NOTIFY_OK; |
| @@ -2021,7 +2014,7 @@ static int __init init_subsystems(void) · 74 unmodified lines | ||
| 2021 | 2014 | /* |
| 2022 | 2015 | * Enable hardware so that subsystem initialisation can access EL2. |
| 2023 | 2016 | */ |
| 2024 | − on_each_cpu(_kvm_arch_hardware_enable, NULL, 1); | |
| 2017 | + on_each_cpu(cpu_hyp_init, NULL, 1); | |
| 2025 | 2018 | |
| 2026 | 2019 | /* |
| 2027 | 2020 | * Register CPU lower-power notifier |
| @@ -2059,7 +2052,7 @@ out: · 31 unmodified lines | ||
| 2059 | 2052 | hyp_cpu_pm_exit(); |
| 2060 | 2053 | |
| 2061 | 2054 | if (err || !is_protected_kvm_enabled()) |
| 2062 | − on_each_cpu(_kvm_arch_hardware_disable, NULL, 1); | |
| 2055 | + on_each_cpu(cpu_hyp_uninit, NULL, 1); | |
| 2063 | 2056 | |
| 2064 | 2057 | return err; |
| 2065 | 2058 | } |
| @@ -2097,7 +2090,7 @@ static int __init do_pkvm_init(u32 hyp_va_bits) · 31 unmodified lines | ||
| 2097 | 2090 | * The stub hypercalls are now disabled, so set our local flag to |
| 2098 | 2091 | * prevent a later re-init attempt in kvm_arch_hardware_enable(). |
| 2099 | 2092 | */ |
| 2100 | − __this_cpu_write(kvm_arm_hardware_enabled, 1); | |
| 2093 | + __this_cpu_write(kvm_hyp_initialized, 1); | |
| 2101 | 2094 | preempt_enable(); |
| 2102 | 2095 | |
| 2103 | 2096 | return ret; |
| @@ -457,6 +457,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu) · 456 unmodified lines | ||
| 457 | 457 | */ |
| 458 | 458 | val &= ~(TCR_HD | TCR_HA); |
| 459 | 459 | write_sysreg_el1(val, SYS_TCR); |
| 460 | + __kvm_skip_instr(vcpu); | |
| 460 | 461 | return true; |
| 461 | 462 | } |
| 462 | 463 | |
| @@ -705,7 +705,20 @@ int hyp_ffa_init(void *pages) · 704 unmodified lines | ||
| 705 | 705 | if (res.a0 == FFA_RET_NOT_SUPPORTED) |
| 706 | 706 | return 0; |
| 707 | 707 | |
| 708 | − if (res.a0 != FFA_VERSION_1_0) | |
| 708 | + /* | |
| 709 | + * Firmware returns the maximum supported version of the FF-A | |
| 710 | + * implementation. Check that the returned version is | |
| 711 | + * backwards-compatible with the hyp according to the rules in DEN0077A | |
| 712 | + * v1.1 REL0 13.2.1. | |
| 713 | + * | |
| 714 | + * Of course, things are never simple when dealing with firmware. v1.1 | |
| 715 | + * broke ABI with v1.0 on several structures, which is itself | |
| 716 | + * incompatible with the aforementioned versioning scheme. The | |
| 717 | + * expectation is that v1.x implementations that do not support the v1.0 | |
| 718 | + * ABI return NOT_SUPPORTED rather than a version number, according to | |
| 719 | + * DEN0077A v1.1 REL0 18.6.4. | |
| 720 | + */ | |
| 721 | + if (FFA_MAJOR_VERSION(res.a0) != 1) | |
| 709 | 722 | return -EOPNOTSUPP; |
| 710 | 723 | |
| 711 | 724 | arm_smccc_1_1_smc(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0, &res); |
| @@ -63,7 +63,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu) · 62 unmodified lines | ||
| 63 | 63 | __activate_traps_fpsimd32(vcpu); |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | − write_sysreg(val, cptr_el2); | |
| 66 | + kvm_write_cptr_el2(val); | |
| 67 | 67 | write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2); |
| 68 | 68 | |
| 69 | 69 | if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { |
| @@ -634,7 +634,6 @@ ia64_imva (void *addr) · 633 unmodified lines | ||
| 634 | 634 | |
| 635 | 635 | #define ARCH_HAS_PREFETCH |
| 636 | 636 | #define ARCH_HAS_PREFETCHW |
| 637 | −#define ARCH_HAS_SPINLOCK_PREFETCH | |
| 638 | 637 | #define PREFETCH_STRIDE L1_CACHE_BYTES |
| 639 | 638 | |
| 640 | 639 | static inline void |
| @@ -649,8 +648,6 @@ prefetchw (const void *x) · 8 unmodified lines | ||
| 649 | 648 | ia64_lfetch_excl(ia64_lfhint_none, x); |
| 650 | 649 | } |
| 651 | 650 | |
| 652 | −#define spin_lock_prefetch(x) prefetchw(x) | |
| 653 | − | |
| 654 | 651 | extern unsigned long boot_option_idle_override; |
| 655 | 652 | |
| 656 | 653 | enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT, |
| @@ -58,8 +58,6 @@ · 57 unmodified lines | ||
| 58 | 58 | |
| 59 | 59 | #define cpu_has_rixi (cpu_data[0].cputype != CPU_CAVIUM_OCTEON) |
| 60 | 60 | |
| 61 | −#define ARCH_HAS_SPINLOCK_PREFETCH 1 | |
| 62 | −#define spin_lock_prefetch(x) prefetch(x) | |
| 63 | 61 | #define PREFETCH_STRIDE 128 |
| 64 | 62 | |
| 65 | 63 | #ifdef __OCTEON__ |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | # |
| 3 | 3 | config LIGHTWEIGHT_SPINLOCK_CHECK |
| 4 | 4 | bool "Enable lightweight spinlock checks" |
| 5 | − depends on SMP && !DEBUG_SPINLOCK | |
| 5 | + depends on DEBUG_KERNEL && SMP && !DEBUG_SPINLOCK | |
| 6 | 6 | default y |
| 7 | 7 | help |
| 8 | 8 | Add checks with low performance impact to the spinlock functions |
| @@ -117,7 +117,7 @@ char *strchr(const char *s, int c) · 116 unmodified lines | ||
| 117 | 117 | return NULL; |
| 118 | 118 | } |
| 119 | 119 | |
| 120 | −int puts(const char *s) | |
| 120 | +static int puts(const char *s) | |
| 121 | 121 | { |
| 122 | 122 | const char *nuline = s; |
| 123 | 123 | |
| @@ -172,7 +172,7 @@ static int print_num(unsigned long num, int base) · 48 unmodified lines | ||
| 172 | 172 | return 0; |
| 173 | 173 | } |
| 174 | 174 | |
| 175 | −int printf(const char *fmt, ...) | |
| 175 | +static int printf(const char *fmt, ...) | |
| 176 | 176 | { |
| 177 | 177 | va_list args; |
| 178 | 178 | int i = 0; |
| @@ -204,13 +204,13 @@ void abort(void) · 25 unmodified lines | ||
| 204 | 204 | } |
| 205 | 205 | |
| 206 | 206 | #undef malloc |
| 207 | −void *malloc(size_t size) | |
| 207 | +static void *malloc(size_t size) | |
| 208 | 208 | { |
| 209 | 209 | return malloc_gzip(size); |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | 212 | #undef free |
| 213 | −void free(void *ptr) | |
| 213 | +static void free(void *ptr) | |
| 214 | 214 | { |
| 215 | 215 | return free_gzip(ptr); |
| 216 | 216 | } |
| @@ -278,7 +278,7 @@ static void parse_elf(void *output) · 61 unmodified lines | ||
| 278 | 278 | free(phdrs); |
| 279 | 279 | } |
| 280 | 280 | |
| 281 | −unsigned long decompress_kernel(unsigned int started_wide, | |
| 281 | +asmlinkage unsigned long __visible decompress_kernel(unsigned int started_wide, | |
| 282 | 282 | unsigned int command_line, |
| 283 | 283 | const unsigned int rd_start, |
| 284 | 284 | const unsigned int rd_end) |
| @@ -14,6 +14,8 @@ · 13 unmodified lines | ||
| 14 | 14 | #define dma_outb outb |
| 15 | 15 | #define dma_inb inb |
| 16 | 16 | |
| 17 | +extern unsigned long pcxl_dma_start; | |
| 18 | + | |
| 17 | 19 | /* |
| 18 | 20 | ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up |
| 19 | 21 | ** (or rather not merge) DMAs into manageable chunks. |
| @@ -12,6 +12,10 @@ extern void mcount(void); · 11 unmodified lines | ||
| 12 | 12 | extern unsigned long sys_call_table[]; |
| 13 | 13 | |
| 14 | 14 | extern unsigned long return_address(unsigned int); |
| 15 | +struct ftrace_regs; | |
| 16 | +extern void ftrace_function_trampoline(unsigned long parent, | |
| 17 | + unsigned long self_addr, unsigned long org_sp_gr3, | |
| 18 | + struct ftrace_regs *fregs); | |
| 15 | 19 | |
| 16 | 20 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 17 | 21 | extern void ftrace_caller(void); |
| @@ -7,8 +7,6 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <asm/processor.h> |
| 8 | 8 | #include <asm/spinlock_types.h> |
| 9 | 9 | |
| 10 | −#define SPINLOCK_BREAK_INSN 0x0000c006 /* break 6,6 */ | |
| 11 | − | |
| 12 | 10 | static inline void arch_spin_val_check(int lock_val) |
| 13 | 11 | { |
| 14 | 12 | if (IS_ENABLED(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK)) |
| @@ -4,6 +4,10 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #define __ARCH_SPIN_LOCK_UNLOCKED_VAL 0x1a46 |
| 6 | 6 | |
| 7 | +#define SPINLOCK_BREAK_INSN 0x0000c006 /* break 6,6 */ | |
| 8 | + | |
| 9 | +#ifndef __ASSEMBLY__ | |
| 10 | + | |
| 7 | 11 | typedef struct { |
| 8 | 12 | #ifdef CONFIG_PA20 |
| 9 | 13 | volatile unsigned int slock; |
| @@ -27,6 +31,8 @@ typedef struct { · 17 unmodified lines | ||
| 27 | 31 | volatile unsigned int counter; |
| 28 | 32 | } arch_rwlock_t; |
| 29 | 33 | |
| 34 | +#endif /* __ASSEMBLY__ */ | |
| 35 | + | |
| 30 | 36 | #define __ARCH_RW_LOCK_UNLOCKED__ 0x01000000 |
| 31 | 37 | #define __ARCH_RW_LOCK_UNLOCKED { .lock_mutex = __ARCH_SPIN_LOCK_UNLOCKED, \ |
| 32 | 38 | .counter = __ARCH_RW_LOCK_UNLOCKED__ } |
| @@ -74,8 +74,8 @@ · 73 unmodified lines | ||
| 74 | 74 | static DEFINE_SPINLOCK(pdc_lock); |
| 75 | 75 | #endif |
| 76 | 76 | |
| 77 | −unsigned long pdc_result[NUM_PDC_RESULT] __aligned(8); | |
| 78 | −unsigned long pdc_result2[NUM_PDC_RESULT] __aligned(8); | |
| 77 | +static unsigned long pdc_result[NUM_PDC_RESULT] __aligned(8); | |
| 78 | +static unsigned long pdc_result2[NUM_PDC_RESULT] __aligned(8); | |
| 79 | 79 | |
| 80 | 80 | #ifdef CONFIG_64BIT |
| 81 | 81 | #define WIDE_FIRMWARE 0x1 |
| @@ -334,7 +334,7 @@ int __pdc_cpu_rendezvous(void) · 252 unmodified lines | ||
| 334 | 334 | /** |
| 335 | 335 | * pdc_cpu_rendezvous_lock - Lock PDC while transitioning to rendezvous state |
| 336 | 336 | */ |
| 337 | −void pdc_cpu_rendezvous_lock(void) | |
| 337 | +void pdc_cpu_rendezvous_lock(void) __acquires(&pdc_lock) | |
| 338 | 338 | { |
| 339 | 339 | spin_lock(&pdc_lock); |
| 340 | 340 | } |
| @@ -342,7 +342,7 @@ void pdc_cpu_rendezvous_lock(void) · 1 unmodified line | ||
| 342 | 342 | /** |
| 343 | 343 | * pdc_cpu_rendezvous_unlock - Unlock PDC after reaching rendezvous state |
| 344 | 344 | */ |
| 345 | −void pdc_cpu_rendezvous_unlock(void) | |
| 345 | +void pdc_cpu_rendezvous_unlock(void) __releases(&pdc_lock) | |
| 346 | 346 | { |
| 347 | 347 | spin_unlock(&pdc_lock); |
| 348 | 348 | } |
| @@ -53,7 +53,7 @@ static void __hot prepare_ftrace_return(unsigned long *parent, · 52 unmodified lines | ||
| 53 | 53 | |
| 54 | 54 | static ftrace_func_t ftrace_func; |
| 55 | 55 | |
| 56 | −void notrace __hot ftrace_function_trampoline(unsigned long parent, | |
| 56 | +asmlinkage void notrace __hot ftrace_function_trampoline(unsigned long parent, | |
| 57 | 57 | unsigned long self_addr, |
| 58 | 58 | unsigned long org_sp_gr3, |
| 59 | 59 | struct ftrace_regs *fregs) |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/module.h> |
| 15 | 15 | #include <linux/kernel.h> |
| 16 | 16 | #include <linux/syscalls.h> |
| 17 | +#include <linux/libgcc.h> | |
| 17 | 18 | |
| 18 | 19 | #include <linux/string.h> |
| 19 | 20 | EXPORT_SYMBOL(memset); |
| @@ -92,12 +93,6 @@ EXPORT_SYMBOL($$divI_12); · 72 unmodified lines | ||
| 92 | 93 | EXPORT_SYMBOL($$divI_14); |
| 93 | 94 | EXPORT_SYMBOL($$divI_15); |
| 94 | 95 | |
| 95 | −extern void __ashrdi3(void); | |
| 96 | −extern void __ashldi3(void); | |
| 97 | −extern void __lshrdi3(void); | |
| 98 | −extern void __muldi3(void); | |
| 99 | −extern void __ucmpdi2(void); | |
| 100 | − | |
| 101 | 96 | EXPORT_SYMBOL(__ashrdi3); |
| 102 | 97 | EXPORT_SYMBOL(__ashldi3); |
| 103 | 98 | EXPORT_SYMBOL(__lshrdi3); |
| @@ -39,7 +39,7 @@ static struct proc_dir_entry * proc_gsc_root __read_mostly = NULL; · 38 unmodified lines | ||
| 39 | 39 | static unsigned long pcxl_used_bytes __read_mostly; |
| 40 | 40 | static unsigned long pcxl_used_pages __read_mostly; |
| 41 | 41 | |
| 42 | −extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */ | |
| 42 | +unsigned long pcxl_dma_start __ro_after_init; /* pcxl dma mapping area start */ | |
| 43 | 43 | static DEFINE_SPINLOCK(pcxl_res_lock); |
| 44 | 44 | static char *pcxl_res_map; |
| 45 | 45 | static int pcxl_res_hint; |
| @@ -381,7 +381,7 @@ pcxl_dma_init(void) · 335 unmodified lines | ||
| 381 | 381 | pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL, |
| 382 | 382 | get_order(pcxl_res_size)); |
| 383 | 383 | memset(pcxl_res_map, 0, pcxl_res_size); |
| 384 | − proc_gsc_root = proc_mkdir("gsc", NULL); | |
| 384 | + proc_gsc_root = proc_mkdir("bus/gsc", NULL); | |
| 385 | 385 | if (!proc_gsc_root) |
| 386 | 386 | printk(KERN_WARNING |
| 387 | 387 | "pcxl_dma_init: Unable to create gsc /proc dir entry\n"); |
| @@ -417,14 +417,6 @@ void *arch_dma_alloc(struct device *dev, size_t size, · 29 unmodified lines | ||
| 417 | 417 | map_uncached_pages(vaddr, size, paddr); |
| 418 | 418 | *dma_handle = (dma_addr_t) paddr; |
| 419 | 419 | |
| 420 | −#if 0 | |
| 421 | −/* This probably isn't needed to support EISA cards. | |
| 422 | −** ISA cards will certainly only support 24-bit DMA addressing. | |
| 423 | −** Not clear if we can, want, or need to support ISA. | |
| 424 | −*/ | |
| 425 | − if (!dev || *dev->coherent_dma_mask < 0xffffffff) | |
| 426 | − gfp |= GFP_DMA; | |
| 427 | −#endif | |
| 428 | 420 | return (void *)vaddr; |
| 429 | 421 | } |
| 430 | 422 | |
| @@ -354,10 +354,8 @@ static int __init pdt_initcall(void) · 353 unmodified lines | ||
| 354 | 354 | return -ENODEV; |
| 355 | 355 | |
| 356 | 356 | kpdtd_task = kthread_run(pdt_mainloop, NULL, "kpdtd"); |
| 357 | − if (IS_ERR(kpdtd_task)) | |
| 358 | − return PTR_ERR(kpdtd_task); | |
| 359 | 357 | |
| 360 | − return 0; | |
| 358 | + return PTR_ERR_OR_ZERO(kpdtd_task); | |
| 361 | 359 | } |
| 362 | 360 | |
| 363 | 361 | late_initcall(pdt_initcall); |
| @@ -57,7 +57,7 @@ struct rdr_tbl_ent { · 56 unmodified lines | ||
| 57 | 57 | static int perf_processor_interface __read_mostly = UNKNOWN_INTF; |
| 58 | 58 | static int perf_enabled __read_mostly; |
| 59 | 59 | static DEFINE_SPINLOCK(perf_lock); |
| 60 | −struct parisc_device *cpu_device __read_mostly; | |
| 60 | +static struct parisc_device *cpu_device __read_mostly; | |
| 61 | 61 | |
| 62 | 62 | /* RDRs to write for PCX-W */ |
| 63 | 63 | static const int perf_rdrs_W[] = |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <asm/processor.h> |
| 27 | 27 | #include <asm/page.h> |
| 28 | 28 | #include <asm/pdc.h> |
| 29 | +#include <asm/smp.h> | |
| 29 | 30 | #include <asm/pdcpat.h> |
| 30 | 31 | #include <asm/irq.h> /* for struct irq_region */ |
| 31 | 32 | #include <asm/parisc-device.h> |
| @@ -40,11 +40,6 @@ · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | static char __initdata command_line[COMMAND_LINE_SIZE]; |
| 42 | 42 | |
| 43 | −/* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */ | |
| 44 | −struct proc_dir_entry * proc_runway_root __read_mostly = NULL; | |
| 45 | −struct proc_dir_entry * proc_gsc_root __read_mostly = NULL; | |
| 46 | −struct proc_dir_entry * proc_mckinley_root __read_mostly = NULL; | |
| 47 | − | |
| 48 | 43 | static void __init setup_cmdline(char **cmdline_p) |
| 49 | 44 | { |
| 50 | 45 | extern unsigned int boot_args[]; |
| @@ -196,48 +191,6 @@ const struct seq_operations cpuinfo_op = { · 145 unmodified lines | ||
| 196 | 191 | .show = show_cpuinfo |
| 197 | 192 | }; |
| 198 | 193 | |
| 199 | −static void __init parisc_proc_mkdir(void) | |
| 200 | −{ | |
| 201 | − /* | |
| 202 | − ** Can't call proc_mkdir() until after proc_root_init() has been | |
| 203 | − ** called by start_kernel(). In other words, this code can't | |
| 204 | − ** live in arch/.../setup.c because start_parisc() calls | |
| 205 | − ** start_kernel(). | |
| 206 | − */ | |
| 207 | − switch (boot_cpu_data.cpu_type) { | |
| 208 | − case pcxl: | |
| 209 | − case pcxl2: | |
| 210 | − if (NULL == proc_gsc_root) | |
| 211 | − { | |
| 212 | − proc_gsc_root = proc_mkdir("bus/gsc", NULL); | |
| 213 | − } | |
| 214 | − break; | |
| 215 | − case pcxt_: | |
| 216 | − case pcxu: | |
| 217 | − case pcxu_: | |
| 218 | − case pcxw: | |
| 219 | − case pcxw_: | |
| 220 | − case pcxw2: | |
| 221 | − if (NULL == proc_runway_root) | |
| 222 | − { | |
| 223 | − proc_runway_root = proc_mkdir("bus/runway", NULL); | |
| 224 | − } | |
| 225 | − break; | |
| 226 | − case mako: | |
| 227 | − case mako2: | |
| 228 | − if (NULL == proc_mckinley_root) | |
| 229 | − { | |
| 230 | − proc_mckinley_root = proc_mkdir("bus/mckinley", NULL); | |
| 231 | − } | |
| 232 | − break; | |
| 233 | − default: | |
| 234 | − /* FIXME: this was added to prevent the compiler | |
| 235 | − * complaining about missing pcx, pcxs and pcxt | |
| 236 | − * I'm assuming they have neither gsc nor runway */ | |
| 237 | − break; | |
| 238 | − } | |
| 239 | −} | |
| 240 | − | |
| 241 | 194 | static struct resource central_bus = { |
| 242 | 195 | .name = "Central Bus", |
| 243 | 196 | .start = F_EXTEND(0xfff80000), |
| @@ -294,7 +247,6 @@ static int __init parisc_init(void) · 50 unmodified lines | ||
| 294 | 247 | { |
| 295 | 248 | u32 osid = (OS_ID_LINUX << 16); |
| 296 | 249 | |
| 297 | − parisc_proc_mkdir(); | |
| 298 | 250 | parisc_init_resources(); |
| 299 | 251 | do_device_inventory(); /* probe for hardware */ |
| 300 | 252 | |
| @@ -423,7 +423,7 @@ static void check_syscallno_in_delay_branch(struct pt_regs *regs) · 422 unmodified lines | ||
| 423 | 423 | regs->gr[31] -= 8; /* delayed branching */ |
| 424 | 424 | |
| 425 | 425 | /* Get assembler opcode of code in delay branch */ |
| 426 | − uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4); | |
| 426 | + uaddr = (u32 __user *) ((regs->gr[31] & ~3) + 4); | |
| 427 | 427 | err = get_user(opcode, uaddr); |
| 428 | 428 | if (err) |
| 429 | 429 | return; |
| @@ -27,17 +27,12 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/elf-randomize.h> |
| 28 | 28 | |
| 29 | 29 | /* |
| 30 | − * Construct an artificial page offset for the mapping based on the virtual | |
| 30 | + * Construct an artificial page offset for the mapping based on the physical | |
| 31 | 31 | * address of the kernel file mapping variable. |
| 32 | − * If filp is zero the calculated pgoff value aliases the memory of the given | |
| 33 | − * address. This is useful for io_uring where the mapping shall alias a kernel | |
| 34 | − * address and a userspace adress where both the kernel and the userspace | |
| 35 | − * access the same memory region. | |
| 36 | 32 | */ |
| 37 | −#define GET_FILP_PGOFF(filp, addr) \ | |
| 38 | − ((filp ? (((unsigned long) filp->f_mapping) >> 8) \ | |
| 39 | − & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL) \ | |
| 40 | − + (addr >> PAGE_SHIFT)) | |
| 33 | +#define GET_FILP_PGOFF(filp) \ | |
| 34 | + (filp ? (((unsigned long) filp->f_mapping) >> 8) \ | |
| 35 | + & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL) | |
| 41 | 36 | |
| 42 | 37 | static unsigned long shared_align_offset(unsigned long filp_pgoff, |
| 43 | 38 | unsigned long pgoff) |
| @@ -117,7 +112,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, · 73 unmodified lines | ||
| 117 | 112 | do_color_align = 0; |
| 118 | 113 | if (filp || (flags & MAP_SHARED)) |
| 119 | 114 | do_color_align = 1; |
| 120 | − filp_pgoff = GET_FILP_PGOFF(filp, addr); | |
| 115 | + filp_pgoff = GET_FILP_PGOFF(filp); | |
| 121 | 116 | |
| 122 | 117 | if (flags & MAP_FIXED) { |
| 123 | 118 | /* Even MAP_FIXED mappings must reside within TASK_SIZE */ |
| @@ -39,6 +39,7 @@ registers). · 38 unmodified lines | ||
| 39 | 39 | #include <asm/assembly.h> |
| 40 | 40 | #include <asm/processor.h> |
| 41 | 41 | #include <asm/cache.h> |
| 42 | +#include <asm/spinlock_types.h> | |
| 42 | 43 | |
| 43 | 44 | #include <linux/linkage.h> |
| 44 | 45 | |
| @@ -66,6 +67,16 @@ registers). · 21 unmodified lines | ||
| 66 | 67 | stw \reg1, 0(%sr2,\reg2) |
| 67 | 68 | .endm |
| 68 | 69 | |
| 70 | + /* raise exception if spinlock content is not zero or | |
| 71 | + * __ARCH_SPIN_LOCK_UNLOCKED_VAL */ | |
| 72 | + .macro spinlock_check spin_val,tmpreg | |
| 73 | +#ifdef CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK | |
| 74 | + ldi __ARCH_SPIN_LOCK_UNLOCKED_VAL, \tmpreg | |
| 75 | + andcm,= \spin_val, \tmpreg, %r0 | |
| 76 | + .word SPINLOCK_BREAK_INSN | |
| 77 | +#endif | |
| 78 | + .endm | |
| 79 | + | |
| 69 | 80 | .text |
| 70 | 81 | |
| 71 | 82 | .import syscall_exit,code |
| @@ -508,7 +519,8 @@ lws_start: · 436 unmodified lines | ||
| 508 | 519 | |
| 509 | 520 | lws_exit_noerror: |
| 510 | 521 | lws_pagefault_enable %r1,%r21 |
| 511 | − stw,ma %r20, 0(%sr2,%r20) | |
| 522 | + ldi __ARCH_SPIN_LOCK_UNLOCKED_VAL, %r21 | |
| 523 | + stw,ma %r21, 0(%sr2,%r20) | |
| 512 | 524 | ssm PSW_SM_I, %r0 |
| 513 | 525 | b lws_exit |
| 514 | 526 | copy %r0, %r21 |
| @@ -521,7 +533,8 @@ lws_wouldblock: · 6 unmodified lines | ||
| 521 | 533 | |
| 522 | 534 | lws_pagefault: |
| 523 | 535 | lws_pagefault_enable %r1,%r21 |
| 524 | − stw,ma %r20, 0(%sr2,%r20) | |
| 536 | + ldi __ARCH_SPIN_LOCK_UNLOCKED_VAL, %r21 | |
| 537 | + stw,ma %r21, 0(%sr2,%r20) | |
| 525 | 538 | ssm PSW_SM_I, %r0 |
| 526 | 539 | ldo 3(%r0),%r28 |
| 527 | 540 | b lws_exit |
| @@ -619,6 +632,7 @@ lws_compare_and_swap: · 91 unmodified lines | ||
| 619 | 632 | |
| 620 | 633 | /* Try to acquire the lock */ |
| 621 | 634 | LDCW 0(%sr2,%r20), %r28 |
| 635 | + spinlock_check %r28, %r21 | |
| 622 | 636 | comclr,<> %r0, %r28, %r0 |
| 623 | 637 | b,n lws_wouldblock |
| 624 | 638 | |
| @@ -772,6 +786,7 @@ cas2_lock_start: · 147 unmodified lines | ||
| 772 | 786 | |
| 773 | 787 | /* Try to acquire the lock */ |
| 774 | 788 | LDCW 0(%sr2,%r20), %r28 |
| 789 | + spinlock_check %r28, %r21 | |
| 775 | 790 | comclr,<> %r0, %r28, %r0 |
| 776 | 791 | b,n lws_wouldblock |
| 777 | 792 | |
| @@ -1001,6 +1016,7 @@ atomic_xchg_start: · 223 unmodified lines | ||
| 1001 | 1016 | |
| 1002 | 1017 | /* Try to acquire the lock */ |
| 1003 | 1018 | LDCW 0(%sr2,%r20), %r28 |
| 1019 | + spinlock_check %r28, %r21 | |
| 1004 | 1020 | comclr,<> %r0, %r28, %r0 |
| 1005 | 1021 | b,n lws_wouldblock |
| 1006 | 1022 | |
| @@ -1199,6 +1215,7 @@ atomic_store_start: · 192 unmodified lines | ||
| 1199 | 1215 | |
| 1200 | 1216 | /* Try to acquire the lock */ |
| 1201 | 1217 | LDCW 0(%sr2,%r20), %r28 |
| 1218 | + spinlock_check %r28, %r21 | |
| 1202 | 1219 | comclr,<> %r0, %r28, %r0 |
| 1203 | 1220 | b,n lws_wouldblock |
| 1204 | 1221 | |
| @@ -1330,7 +1347,7 @@ ENTRY(lws_lock_start) · 125 unmodified lines | ||
| 1330 | 1347 | /* lws locks */ |
| 1331 | 1348 | .rept 256 |
| 1332 | 1349 | /* Keep locks aligned at 16-bytes */ |
| 1333 | − .word 1 | |
| 1350 | + .word __ARCH_SPIN_LOCK_UNLOCKED_VAL | |
| 1334 | 1351 | .word 0 |
| 1335 | 1352 | .word 0 |
| 1336 | 1353 | .word 0 |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/signal.h> |
| 12 | 12 | #include <linux/ratelimit.h> |
| 13 | 13 | #include <linux/uaccess.h> |
| 14 | +#include <linux/sysctl.h> | |
| 14 | 15 | #include <asm/unaligned.h> |
| 15 | 16 | #include <asm/hardirq.h> |
| 16 | 17 | #include <asm/traps.h> |
| @@ -337,7 +338,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) · 320 unmodified lines | ||
| 337 | 338 | : "r19", "r20", "r21", "r22", "r1" ); |
| 338 | 339 | #else |
| 339 | 340 | { |
| 340 | − unsigned long valh=(val>>32),vall=(val&0xffffffffl); | |
| 341 | + unsigned long valh = (val >> 32), vall = (val & 0xffffffffl); | |
| 341 | 342 | __asm__ __volatile__ ( |
| 342 | 343 | " mtsp %4, %%sr1\n" |
| 343 | 344 | " zdep %2, 29, 2, %%r19\n" |
| @@ -473,7 +474,7 @@ void handle_unaligned(struct pt_regs *regs) · 129 unmodified lines | ||
| 473 | 474 | case OPCODE_LDWA_I: |
| 474 | 475 | case OPCODE_LDW_S: |
| 475 | 476 | case OPCODE_LDWA_S: |
| 476 | − ret = emulate_ldw(regs, R3(regs->iir),0); | |
| 477 | + ret = emulate_ldw(regs, R3(regs->iir), 0); | |
| 477 | 478 | break; |
| 478 | 479 | |
| 479 | 480 | case OPCODE_STH: |
| @@ -482,7 +483,7 @@ void handle_unaligned(struct pt_regs *regs) · 2 unmodified lines | ||
| 482 | 483 | |
| 483 | 484 | case OPCODE_STW: |
| 484 | 485 | case OPCODE_STWA: |
| 485 | − ret = emulate_stw(regs, R2(regs->iir),0); | |
| 486 | + ret = emulate_stw(regs, R2(regs->iir), 0); | |
| 486 | 487 | break; |
| 487 | 488 | |
| 488 | 489 | #ifdef CONFIG_64BIT |
| @@ -490,12 +491,12 @@ void handle_unaligned(struct pt_regs *regs) · 1 unmodified line | ||
| 490 | 491 | case OPCODE_LDDA_I: |
| 491 | 492 | case OPCODE_LDD_S: |
| 492 | 493 | case OPCODE_LDDA_S: |
| 493 | − ret = emulate_ldd(regs, R3(regs->iir),0); | |
| 494 | + ret = emulate_ldd(regs, R3(regs->iir), 0); | |
| 494 | 495 | break; |
| 495 | 496 | |
| 496 | 497 | case OPCODE_STD: |
| 497 | 498 | case OPCODE_STDA: |
| 498 | − ret = emulate_std(regs, R2(regs->iir),0); | |
| 499 | + ret = emulate_std(regs, R2(regs->iir), 0); | |
| 499 | 500 | break; |
| 500 | 501 | #endif |
| 501 | 502 | |
| @@ -503,24 +504,24 @@ void handle_unaligned(struct pt_regs *regs) · 1 unmodified line | ||
| 503 | 504 | case OPCODE_FLDWS: |
| 504 | 505 | case OPCODE_FLDWXR: |
| 505 | 506 | case OPCODE_FLDWSR: |
| 506 | − ret = emulate_ldw(regs,FR3(regs->iir),1); | |
| 507 | + ret = emulate_ldw(regs, FR3(regs->iir), 1); | |
| 507 | 508 | break; |
| 508 | 509 | |
| 509 | 510 | case OPCODE_FLDDX: |
| 510 | 511 | case OPCODE_FLDDS: |
| 511 | − ret = emulate_ldd(regs,R3(regs->iir),1); | |
| 512 | + ret = emulate_ldd(regs, R3(regs->iir), 1); | |
| 512 | 513 | break; |
| 513 | 514 | |
| 514 | 515 | case OPCODE_FSTWX: |
| 515 | 516 | case OPCODE_FSTWS: |
| 516 | 517 | case OPCODE_FSTWXR: |
| 517 | 518 | case OPCODE_FSTWSR: |
| 518 | − ret = emulate_stw(regs,FR3(regs->iir),1); | |
| 519 | + ret = emulate_stw(regs, FR3(regs->iir), 1); | |
| 519 | 520 | break; |
| 520 | 521 | |
| 521 | 522 | case OPCODE_FSTDX: |
| 522 | 523 | case OPCODE_FSTDS: |
| 523 | − ret = emulate_std(regs,R3(regs->iir),1); | |
| 524 | + ret = emulate_std(regs, R3(regs->iir), 1); | |
| 524 | 525 | break; |
| 525 | 526 | |
| 526 | 527 | case OPCODE_LDCD_I: |
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | #include <linux/module.h> |
| 3 | +#include <linux/libgcc.h> | |
| 3 | 4 | |
| 4 | 5 | union ull_union { |
| 5 | 6 | unsigned long long ull; |
| @@ -9,7 +10,7 @@ union ull_union { · 3 unmodified lines | ||
| 9 | 10 | } ui; |
| 10 | 11 | }; |
| 11 | 12 | |
| 12 | −int __ucmpdi2(unsigned long long a, unsigned long long b) | |
| 13 | +word_type __ucmpdi2(unsigned long long a, unsigned long long b) | |
| 13 | 14 | { |
| 14 | 15 | union ull_union au = {.ull = a}; |
| 15 | 16 | union ull_union bu = {.ull = b}; |
| @@ -192,31 +192,31 @@ int fixup_exception(struct pt_regs *regs) · 191 unmodified lines | ||
| 192 | 192 | * For implementation see handle_interruption() in traps.c |
| 193 | 193 | */ |
| 194 | 194 | static const char * const trap_description[] = { |
| 195 | − [1] "High-priority machine check (HPMC)", | |
| 196 | − [2] "Power failure interrupt", | |
| 197 | − [3] "Recovery counter trap", | |
| 198 | − [5] "Low-priority machine check", | |
| 199 | − [6] "Instruction TLB miss fault", | |
| 200 | − [7] "Instruction access rights / protection trap", | |
| 201 | − [8] "Illegal instruction trap", | |
| 202 | − [9] "Break instruction trap", | |
| 203 | − [10] "Privileged operation trap", | |
| 204 | − [11] "Privileged register trap", | |
| 205 | − [12] "Overflow trap", | |
| 206 | − [13] "Conditional trap", | |
| 207 | − [14] "FP Assist Exception trap", | |
| 208 | − [15] "Data TLB miss fault", | |
| 209 | − [16] "Non-access ITLB miss fault", | |
| 210 | − [17] "Non-access DTLB miss fault", | |
| 211 | − [18] "Data memory protection/unaligned access trap", | |
| 212 | − [19] "Data memory break trap", | |
| 213 | − [20] "TLB dirty bit trap", | |
| 214 | − [21] "Page reference trap", | |
| 215 | − [22] "Assist emulation trap", | |
| 216 | − [25] "Taken branch trap", | |
| 217 | − [26] "Data memory access rights trap", | |
| 218 | − [27] "Data memory protection ID trap", | |
| 219 | − [28] "Unaligned data reference trap", | |
| 195 | + [1] = "High-priority machine check (HPMC)", | |
| 196 | + [2] = "Power failure interrupt", | |
| 197 | + [3] = "Recovery counter trap", | |
| 198 | + [5] = "Low-priority machine check", | |
| 199 | + [6] = "Instruction TLB miss fault", | |
| 200 | + [7] = "Instruction access rights / protection trap", | |
| 201 | + [8] = "Illegal instruction trap", | |
| 202 | + [9] = "Break instruction trap", | |
| 203 | + [10] = "Privileged operation trap", | |
| 204 | + [11] = "Privileged register trap", | |
| 205 | + [12] = "Overflow trap", | |
| 206 | + [13] = "Conditional trap", | |
| 207 | + [14] = "FP Assist Exception trap", | |
| 208 | + [15] = "Data TLB miss fault", | |
| 209 | + [16] = "Non-access ITLB miss fault", | |
| 210 | + [17] = "Non-access DTLB miss fault", | |
| 211 | + [18] = "Data memory protection/unaligned access trap", | |
| 212 | + [19] = "Data memory break trap", | |
| 213 | + [20] = "TLB dirty bit trap", | |
| 214 | + [21] = "Page reference trap", | |
| 215 | + [22] = "Assist emulation trap", | |
| 216 | + [25] = "Taken branch trap", | |
| 217 | + [26] = "Data memory access rights trap", | |
| 218 | + [27] = "Data memory protection ID trap", | |
| 219 | + [28] = "Unaligned data reference trap", | |
| 220 | 220 | }; |
| 221 | 221 | |
| 222 | 222 | const char *trap_name(unsigned long code) |
| @@ -19,9 +19,6 @@ void notrace set_fixmap(enum fixed_addresses idx, phys_addr_t phys) · 18 unmodified lines | ||
| 19 | 19 | pmd_t *pmd = pmd_offset(pud, vaddr); |
| 20 | 20 | pte_t *pte; |
| 21 | 21 | |
| 22 | − if (pmd_none(*pmd)) | |
| 23 | − pte = pte_alloc_kernel(pmd, vaddr); | |
| 24 | − | |
| 25 | 22 | pte = pte_offset_kernel(pmd, vaddr); |
| 26 | 23 | set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX)); |
| 27 | 24 | flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); |
| @@ -523,10 +523,6 @@ void mark_rodata_ro(void) · 522 unmodified lines | ||
| 523 | 523 | void *parisc_vmalloc_start __ro_after_init; |
| 524 | 524 | EXPORT_SYMBOL(parisc_vmalloc_start); |
| 525 | 525 | |
| 526 | −#ifdef CONFIG_PA11 | |
| 527 | −unsigned long pcxl_dma_start __ro_after_init; | |
| 528 | −#endif | |
| 529 | − | |
| 530 | 526 | void __init mem_init(void) |
| 531 | 527 | { |
| 532 | 528 | /* Do sanity checks on IPC (compat) structures */ |
| @@ -669,6 +665,39 @@ static void __init gateway_init(void) · 136 unmodified lines | ||
| 669 | 665 | PAGE_SIZE, PAGE_GATEWAY, 1); |
| 670 | 666 | } |
| 671 | 667 | |
| 668 | +static void __init fixmap_init(void) | |
| 669 | +{ | |
| 670 | + unsigned long addr = FIXMAP_START; | |
| 671 | + unsigned long end = FIXMAP_START + FIXMAP_SIZE; | |
| 672 | + pgd_t *pgd = pgd_offset_k(addr); | |
| 673 | + p4d_t *p4d = p4d_offset(pgd, addr); | |
| 674 | + pud_t *pud = pud_offset(p4d, addr); | |
| 675 | + pmd_t *pmd; | |
| 676 | + | |
| 677 | + BUILD_BUG_ON(FIXMAP_SIZE > PMD_SIZE); | |
| 678 | + | |
| 679 | +#if CONFIG_PGTABLE_LEVELS == 3 | |
| 680 | + if (pud_none(*pud)) { | |
| 681 | + pmd = memblock_alloc(PAGE_SIZE << PMD_TABLE_ORDER, | |
| 682 | + PAGE_SIZE << PMD_TABLE_ORDER); | |
| 683 | + if (!pmd) | |
| 684 | + panic("fixmap: pmd allocation failed.\n"); | |
| 685 | + pud_populate(NULL, pud, pmd); | |
| 686 | + } | |
| 687 | +#endif | |
| 688 | + | |
| 689 | + pmd = pmd_offset(pud, addr); | |
| 690 | + do { | |
| 691 | + pte_t *pte = memblock_alloc(PAGE_SIZE, PAGE_SIZE); | |
| 692 | + if (!pte) | |
| 693 | + panic("fixmap: pte allocation failed.\n"); | |
| 694 | + | |
| 695 | + pmd_populate_kernel(&init_mm, pmd, pte); | |
| 696 | + | |
| 697 | + addr += PAGE_SIZE; | |
| 698 | + } while (addr < end); | |
| 699 | +} | |
| 700 | + | |
| 672 | 701 | static void __init parisc_bootmem_free(void) |
| 673 | 702 | { |
| 674 | 703 | unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, }; |
| @@ -683,6 +712,7 @@ void __init paging_init(void) · 8 unmodified lines | ||
| 683 | 712 | setup_bootmem(); |
| 684 | 713 | pagetable_init(); |
| 685 | 714 | gateway_init(); |
| 715 | + fixmap_init(); | |
| 686 | 716 | flush_cache_all_local(); /* start with known state */ |
| 687 | 717 | flush_tlb_all_local(NULL); |
| 688 | 718 | |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | */ |
| 28 | 28 | void __iomem *ioremap(unsigned long phys_addr, unsigned long size) |
| 29 | 29 | { |
| 30 | − void __iomem *addr; | |
| 30 | + uintptr_t addr; | |
| 31 | 31 | struct vm_struct *area; |
| 32 | 32 | unsigned long offset, last_addr; |
| 33 | 33 | pgprot_t pgprot; |
| @@ -79,10 +79,9 @@ void __iomem *ioremap(unsigned long phys_addr, unsigned long size) · 45 unmodified lines | ||
| 79 | 79 | if (!area) |
| 80 | 80 | return NULL; |
| 81 | 81 | |
| 82 | − addr = (void __iomem *) area->addr; | |
| 83 | − if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, | |
| 84 | − phys_addr, pgprot)) { | |
| 85 | − vunmap(addr); | |
| 82 | + addr = (uintptr_t) area->addr; | |
| 83 | + if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { | |
| 84 | + vunmap(area->addr); | |
| 86 | 85 | return NULL; |
| 87 | 86 | } |
| 88 | 87 | |
| @@ -393,7 +393,6 @@ int validate_sp_size(unsigned long sp, struct task_struct *p, · 392 unmodified lines | ||
| 393 | 393 | */ |
| 394 | 394 | #define ARCH_HAS_PREFETCH |
| 395 | 395 | #define ARCH_HAS_PREFETCHW |
| 396 | −#define ARCH_HAS_SPINLOCK_PREFETCH | |
| 397 | 396 | |
| 398 | 397 | static inline void prefetch(const void *x) |
| 399 | 398 | { |
| @@ -411,8 +410,6 @@ static inline void prefetchw(const void *x) · 11 unmodified lines | ||
| 411 | 410 | __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (x)); |
| 412 | 411 | } |
| 413 | 412 | |
| 414 | −#define spin_lock_prefetch(x) prefetchw(x) | |
| 415 | − | |
| 416 | 413 | /* asm stubs */ |
| 417 | 414 | extern unsigned long isa300_idle_stop_noloss(unsigned long psscr_val); |
| 418 | 415 | extern unsigned long isa300_idle_stop_mayloss(unsigned long psscr_val); |
| @@ -34,7 +34,7 @@ static inline long find_zero(unsigned long mask) · 33 unmodified lines | ||
| 34 | 34 | return leading_zero_bits >> 3; |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | −static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) | |
| 37 | +static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) | |
| 38 | 38 | { |
| 39 | 39 | unsigned long rhs = val | c->low_bits; |
| 40 | 40 | *data = rhs; |
| @@ -375,8 +375,7 @@ _GLOBAL(generic_secondary_smp_init) · 374 unmodified lines | ||
| 375 | 375 | beq 20f |
| 376 | 376 | |
| 377 | 377 | /* start the specified thread */ |
| 378 | − LOAD_REG_ADDR(r5, fsl_secondary_thread_init) | |
| 379 | − ld r4, 0(r5) | |
| 378 | + LOAD_REG_ADDR(r5, DOTSYM(fsl_secondary_thread_init)) | |
| 380 | 379 | bl book3e_start_thread |
| 381 | 380 | |
| 382 | 381 | /* stop the current thread */ |
| @@ -33,6 +33,9 @@ · 32 unmodified lines | ||
| 33 | 33 | * and then arrange for the ftrace function to be called. |
| 34 | 34 | */ |
| 35 | 35 | .macro ftrace_regs_entry allregs |
| 36 | + /* Create a minimal stack frame for representing B */ | |
| 37 | + PPC_STLU r1, -STACK_FRAME_MIN_SIZE(r1) | |
| 38 | + | |
| 36 | 39 | /* Create our stack frame + pt_regs */ |
| 37 | 40 | PPC_STLU r1,-SWITCH_FRAME_SIZE(r1) |
| 38 | 41 | |
| @@ -42,7 +45,7 @@ · 3 unmodified lines | ||
| 42 | 45 | |
| 43 | 46 | #ifdef CONFIG_PPC64 |
| 44 | 47 | /* Save the original return address in A's stack frame */ |
| 45 | − std r0, LRSAVE+SWITCH_FRAME_SIZE(r1) | |
| 48 | + std r0, LRSAVE+SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE(r1) | |
| 46 | 49 | /* Ok to continue? */ |
| 47 | 50 | lbz r3, PACA_FTRACE_ENABLED(r13) |
| 48 | 51 | cmpdi r3, 0 |
| @@ -77,6 +80,8 @@ · 28 unmodified lines | ||
| 77 | 80 | mflr r7 |
| 78 | 81 | /* Save it as pt_regs->nip */ |
| 79 | 82 | PPC_STL r7, _NIP(r1) |
| 83 | + /* Also save it in B's stackframe header for proper unwind */ | |
| 84 | + PPC_STL r7, LRSAVE+SWITCH_FRAME_SIZE(r1) | |
| 80 | 85 | /* Save the read LR in pt_regs->link */ |
| 81 | 86 | PPC_STL r0, _LINK(r1) |
| 82 | 87 | |
| @@ -142,7 +147,7 @@ · 59 unmodified lines | ||
| 142 | 147 | #endif |
| 143 | 148 | |
| 144 | 149 | /* Pop our stack frame */ |
| 145 | − addi r1, r1, SWITCH_FRAME_SIZE | |
| 150 | + addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE | |
| 146 | 151 | |
| 147 | 152 | #ifdef CONFIG_LIVEPATCH_64 |
| 148 | 153 | /* Based on the cmpd above, if the NIP was altered handle livepatch */ |
| @@ -314,8 +314,7 @@ void __ref vmemmap_free(unsigned long start, unsigned long end, · 313 unmodified lines | ||
| 314 | 314 | start = ALIGN_DOWN(start, page_size); |
| 315 | 315 | if (altmap) { |
| 316 | 316 | alt_start = altmap->base_pfn; |
| 317 | − alt_end = altmap->base_pfn + altmap->reserve + | |
| 318 | − altmap->free + altmap->alloc + altmap->align; | |
| 317 | + alt_end = altmap->base_pfn + altmap->reserve + altmap->free; | |
| 319 | 318 | } |
| 320 | 319 | |
| 321 | 320 | pr_debug("vmemmap_free %lx...%lx\n", start, end); |
| @@ -180,7 +180,7 @@ static void wake_hw_thread(void *info) · 179 unmodified lines | ||
| 180 | 180 | unsigned long inia; |
| 181 | 181 | int cpu = *(const int *)info; |
| 182 | 182 | |
| 183 | − inia = *(unsigned long *)fsl_secondary_thread_init; | |
| 183 | + inia = ppc_function_entry(fsl_secondary_thread_init); | |
| 184 | 184 | book3e_start_thread(cpu_thread_in_core(cpu), inia); |
| 185 | 185 | } |
| 186 | 186 | #endif |
| @@ -26,8 +26,8 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/rtc.h> |
| 27 | 27 | #include <linux/of_address.h> |
| 28 | 28 | |
| 29 | +#include <asm/early_ioremap.h> | |
| 29 | 30 | #include <asm/sections.h> |
| 30 | −#include <asm/io.h> | |
| 31 | 31 | #include <asm/machdep.h> |
| 32 | 32 | #include <asm/time.h> |
| 33 | 33 | #include <asm/nvram.h> |
| @@ -182,7 +182,7 @@ static int __init via_calibrate_decr(void) · 148 unmodified lines | ||
| 182 | 182 | return 0; |
| 183 | 183 | } |
| 184 | 184 | of_node_put(vias); |
| 185 | − via = ioremap(rsrc.start, resource_size(&rsrc)); | |
| 185 | + via = early_ioremap(rsrc.start, resource_size(&rsrc)); | |
| 186 | 186 | if (via == NULL) { |
| 187 | 187 | printk(KERN_ERR "Failed to map VIA for timer calibration !\n"); |
| 188 | 188 | return 0; |
| @@ -207,7 +207,7 @@ static int __init via_calibrate_decr(void) · 18 unmodified lines | ||
| 207 | 207 | |
| 208 | 208 | ppc_tb_freq = (dstart - dend) * 100 / 6; |
| 209 | 209 | |
| 210 | − iounmap(via); | |
| 210 | + early_iounmap((void *)via, resource_size(&rsrc)); | |
| 211 | 211 | |
| 212 | 212 | return 1; |
| 213 | 213 | } |
| @@ -19,7 +19,7 @@ typedef u64 phys_cpuid_t; · 18 unmodified lines | ||
| 19 | 19 | #define PHYS_CPUID_INVALID INVALID_HARTID |
| 20 | 20 | |
| 21 | 21 | /* ACPI table mapping after acpi_permanent_mmap is set */ |
| 22 | −void *acpi_os_ioremap(acpi_physical_address phys, acpi_size size); | |
| 22 | +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size); | |
| 23 | 23 | #define acpi_os_ioremap acpi_os_ioremap |
| 24 | 24 | |
| 25 | 25 | #define acpi_strict 1 /* No out-of-spec workarounds on RISC-V */ |
| @@ -37,6 +37,10 @@ static inline void flush_dcache_page(struct page *page) · 36 unmodified lines | ||
| 37 | 37 | #define flush_icache_user_page(vma, pg, addr, len) \ |
| 38 | 38 | flush_icache_mm(vma->vm_mm, 0) |
| 39 | 39 | |
| 40 | +#ifdef CONFIG_64BIT | |
| 41 | +#define flush_cache_vmap(start, end) flush_tlb_kernel_range(start, end) | |
| 42 | +#endif | |
| 43 | + | |
| 40 | 44 | #ifndef CONFIG_SMP |
| 41 | 45 | |
| 42 | 46 | #define flush_icache_all() local_flush_icache_all() |
| @@ -101,9 +101,9 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) · 100 unmodified lines | ||
| 101 | 101 | * Relaxed I/O memory access primitives. These follow the Device memory |
| 102 | 102 | * ordering rules but do not guarantee any ordering relative to Normal memory |
| 103 | 103 | * accesses. These are defined to order the indicated access (either a read or |
| 104 | − * write) with all other I/O memory accesses. Since the platform specification | |
| 105 | − * defines that all I/O regions are strongly ordered on channel 2, no explicit | |
| 106 | − * fences are required to enforce this ordering. | |
| 104 | + * write) with all other I/O memory accesses to the same peripheral. Since the | |
| 105 | + * platform specification defines that all I/O regions are strongly ordered on | |
| 106 | + * channel 0, no explicit fences are required to enforce this ordering. | |
| 107 | 107 | */ |
| 108 | 108 | /* FIXME: These are now the same as asm-generic */ |
| 109 | 109 | #define __io_rbr() do {} while (0) |
| @@ -125,14 +125,14 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) · 15 unmodified lines | ||
| 125 | 125 | #endif |
| 126 | 126 | |
| 127 | 127 | /* |
| 128 | − * I/O memory access primitives. Reads are ordered relative to any | |
| 129 | − * following Normal memory access. Writes are ordered relative to any prior | |
| 130 | − * Normal memory access. The memory barriers here are necessary as RISC-V | |
| 128 | + * I/O memory access primitives. Reads are ordered relative to any following | |
| 129 | + * Normal memory read and delay() loop. Writes are ordered relative to any | |
| 130 | + * prior Normal memory write. The memory barriers here are necessary as RISC-V | |
| 131 | 131 | * doesn't define any ordering between the memory space and the I/O space. |
| 132 | 132 | */ |
| 133 | 133 | #define __io_br() do {} while (0) |
| 134 | −#define __io_ar(v) __asm__ __volatile__ ("fence i,r" : : : "memory") | |
| 135 | −#define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory") | |
| 134 | +#define __io_ar(v) ({ __asm__ __volatile__ ("fence i,ir" : : : "memory"); }) | |
| 135 | +#define __io_bw() ({ __asm__ __volatile__ ("fence w,o" : : : "memory"); }) | |
| 136 | 136 | #define __io_aw() mmiowb_set_pending() |
| 137 | 137 | |
| 138 | 138 | #define readb(c) ({ u8 __v; __io_br(); __v = readb_cpu(c); __io_ar(__v); __v; }) |
| @@ -188,6 +188,8 @@ extern struct pt_alloc_ops pt_ops __initdata; · 187 unmodified lines | ||
| 188 | 188 | #define PAGE_KERNEL_IO __pgprot(_PAGE_IOREMAP) |
| 189 | 189 | |
| 190 | 190 | extern pgd_t swapper_pg_dir[]; |
| 191 | +extern pgd_t trampoline_pg_dir[]; | |
| 192 | +extern pgd_t early_pg_dir[]; | |
| 191 | 193 | |
| 192 | 194 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 193 | 195 | static inline int pmd_present(pmd_t pmd) |
| @@ -3,12 +3,14 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP |
| 5 | 5 | |
| 6 | +extern bool pgtable_l4_enabled, pgtable_l5_enabled; | |
| 7 | + | |
| 6 | 8 | #define IOREMAP_MAX_ORDER (PUD_SHIFT) |
| 7 | 9 | |
| 8 | 10 | #define arch_vmap_pud_supported arch_vmap_pud_supported |
| 9 | 11 | static inline bool arch_vmap_pud_supported(pgprot_t prot) |
| 10 | 12 | { |
| 11 | − return true; | |
| 13 | + return pgtable_l4_enabled || pgtable_l5_enabled; | |
| 12 | 14 | } |
| 13 | 15 | |
| 14 | 16 | #define arch_vmap_pmd_supported arch_vmap_pmd_supported |
| @@ -215,9 +215,9 @@ void __init __acpi_unmap_table(void __iomem *map, unsigned long size) · 214 unmodified lines | ||
| 215 | 215 | early_iounmap(map, size); |
| 216 | 216 | } |
| 217 | 217 | |
| 218 | −void *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) | |
| 218 | +void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) | |
| 219 | 219 | { |
| 220 | − return memremap(phys, size, MEMREMAP_WB); | |
| 220 | + return (void __iomem *)memremap(phys, size, MEMREMAP_WB); | |
| 221 | 221 | } |
| 222 | 222 | |
| 223 | 223 | #ifdef CONFIG_PCI |
| @@ -17,6 +17,11 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <asm/smp.h> |
| 18 | 18 | #include <asm/pgtable.h> |
| 19 | 19 | |
| 20 | +bool arch_match_cpu_phys_id(int cpu, u64 phys_id) | |
| 21 | +{ | |
| 22 | + return phys_id == cpuid_to_hartid_map(cpu); | |
| 23 | +} | |
| 24 | + | |
| 20 | 25 | /* |
| 21 | 26 | * Returns the hart ID of the given device tree node, or -ENODEV if the node |
| 22 | 27 | * isn't an enabled and valid RISC-V hart node. |
| @@ -18,4 +18,6 @@ void arch_crash_save_vmcoreinfo(void) · 17 unmodified lines | ||
| 18 | 18 | vmcoreinfo_append_str("NUMBER(MODULES_END)=0x%lx\n", MODULES_END); |
| 19 | 19 | #endif |
| 20 | 20 | vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR); |
| 21 | + vmcoreinfo_append_str("NUMBER(va_kernel_pa_offset)=0x%lx\n", | |
| 22 | + kernel_map.va_kernel_pa_offset); | |
| 21 | 23 | } |
| @@ -281,7 +281,7 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf, · 280 unmodified lines | ||
| 281 | 281 | kbuf.buffer = initrd; |
| 282 | 282 | kbuf.bufsz = kbuf.memsz = initrd_len; |
| 283 | 283 | kbuf.buf_align = PAGE_SIZE; |
| 284 | − kbuf.top_down = false; | |
| 284 | + kbuf.top_down = true; | |
| 285 | 285 | kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; |
| 286 | 286 | ret = kexec_add_buffer(&kbuf); |
| 287 | 287 | if (ret) |
| @@ -425,6 +425,7 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, · 137 unmodified lines | ||
| 425 | 425 | * sym, instead of searching the whole relsec. |
| 426 | 426 | */ |
| 427 | 427 | case R_RISCV_PCREL_HI20: |
| 428 | + case R_RISCV_CALL_PLT: | |
| 428 | 429 | case R_RISCV_CALL: |
| 429 | 430 | *(u64 *)loc = CLEAN_IMM(UITYPE, *(u64 *)loc) | |
| 430 | 431 | ENCODE_UJTYPE_IMM(val - addr); |
| @@ -61,11 +61,6 @@ int riscv_hartid_to_cpuid(unsigned long hartid) · 60 unmodified lines | ||
| 61 | 61 | return -ENOENT; |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | −bool arch_match_cpu_phys_id(int cpu, u64 phys_id) | |
| 65 | −{ | |
| 66 | − return phys_id == cpuid_to_hartid_map(cpu); | |
| 67 | −} | |
| 68 | − | |
| 69 | 64 | static void ipi_stop(void) |
| 70 | 65 | { |
| 71 | 66 | set_cpu_online(smp_processor_id(), false); |
| @@ -26,12 +26,13 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/kfence.h> |
| 27 | 27 | |
| 28 | 28 | #include <asm/fixmap.h> |
| 29 | −#include <asm/tlbflush.h> | |
| 30 | −#include <asm/sections.h> | |
| 31 | −#include <asm/soc.h> | |
| 32 | 29 | #include <asm/io.h> |
| 33 | −#include <asm/ptdump.h> | |
| 34 | 30 | #include <asm/numa.h> |
| 31 | +#include <asm/pgtable.h> | |
| 32 | +#include <asm/ptdump.h> | |
| 33 | +#include <asm/sections.h> | |
| 34 | +#include <asm/soc.h> | |
| 35 | +#include <asm/tlbflush.h> | |
| 35 | 36 | |
| 36 | 37 | #include "../kernel/head.h" |
| 37 | 38 | |
| @@ -214,8 +215,13 @@ static void __init setup_bootmem(void) · 176 unmodified lines | ||
| 214 | 215 | memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start); |
| 215 | 216 | |
| 216 | 217 | phys_ram_end = memblock_end_of_DRAM(); |
| 218 | + | |
| 219 | + /* | |
| 220 | + * Make sure we align the start of the memory on a PMD boundary so that | |
| 221 | + * at worst, we map the linear mapping with PMD mappings. | |
| 222 | + */ | |
| 217 | 223 | if (!IS_ENABLED(CONFIG_XIP_KERNEL)) |
| 218 | − phys_ram_base = memblock_start_of_DRAM(); | |
| 224 | + phys_ram_base = memblock_start_of_DRAM() & PMD_MASK; | |
| 219 | 225 | |
| 220 | 226 | /* |
| 221 | 227 | * In 64-bit, any use of __va/__pa before this point is wrong as we |
| @@ -22,7 +22,6 @@ · 21 unmodified lines | ||
| 22 | 22 | * region is not and then we have to go down to the PUD level. |
| 23 | 23 | */ |
| 24 | 24 | |
| 25 | −extern pgd_t early_pg_dir[PTRS_PER_PGD]; | |
| 26 | 25 | pgd_t tmp_pg_dir[PTRS_PER_PGD] __page_aligned_bss; |
| 27 | 26 | p4d_t tmp_p4d[PTRS_PER_P4D] __page_aligned_bss; |
| 28 | 27 | pud_t tmp_pud[PTRS_PER_PUD] __page_aligned_bss; |
| @@ -116,7 +116,6 @@ CONFIG_UNIX=y · 115 unmodified lines | ||
| 116 | 116 | CONFIG_UNIX_DIAG=m |
| 117 | 117 | CONFIG_XFRM_USER=m |
| 118 | 118 | CONFIG_NET_KEY=m |
| 119 | −CONFIG_NET_TC_SKB_EXT=y | |
| 120 | 119 | CONFIG_SMC=m |
| 121 | 120 | CONFIG_SMC_DIAG=m |
| 122 | 121 | CONFIG_INET=y |
| @@ -193,6 +192,7 @@ CONFIG_NFT_REJECT=m · 70 unmodified lines | ||
| 193 | 192 | CONFIG_NFT_COMPAT=m |
| 194 | 193 | CONFIG_NFT_HASH=m |
| 195 | 194 | CONFIG_NFT_FIB_INET=m |
| 195 | +CONFIG_NETFILTER_XTABLES_COMPAT=y | |
| 196 | 196 | CONFIG_NETFILTER_XT_SET=m |
| 197 | 197 | CONFIG_NETFILTER_XT_TARGET_AUDIT=m |
| 198 | 198 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
| @@ -379,6 +379,7 @@ CONFIG_NET_ACT_SIMP=m · 180 unmodified lines | ||
| 379 | 379 | CONFIG_NET_ACT_SKBEDIT=m |
| 380 | 380 | CONFIG_NET_ACT_CSUM=m |
| 381 | 381 | CONFIG_NET_ACT_GATE=m |
| 382 | +CONFIG_NET_TC_SKB_EXT=y | |
| 382 | 383 | CONFIG_DNS_RESOLVER=y |
| 383 | 384 | CONFIG_OPENVSWITCH=m |
| 384 | 385 | CONFIG_VSOCKETS=m |
| @@ -395,6 +396,7 @@ CONFIG_HOTPLUG_PCI=y · 10 unmodified lines | ||
| 395 | 396 | CONFIG_HOTPLUG_PCI_S390=y |
| 396 | 397 | CONFIG_DEVTMPFS=y |
| 397 | 398 | CONFIG_DEVTMPFS_SAFE=y |
| 399 | +# CONFIG_FW_LOADER is not set | |
| 398 | 400 | CONFIG_CONNECTOR=y |
| 399 | 401 | CONFIG_ZRAM=y |
| 400 | 402 | CONFIG_BLK_DEV_LOOP=m |
| @@ -502,7 +504,6 @@ CONFIG_NLMON=m · 101 unmodified lines | ||
| 502 | 504 | # CONFIG_NET_VENDOR_GOOGLE is not set |
| 503 | 505 | # CONFIG_NET_VENDOR_HUAWEI is not set |
| 504 | 506 | # CONFIG_NET_VENDOR_INTEL is not set |
| 505 | −# CONFIG_NET_VENDOR_WANGXUN is not set | |
| 506 | 507 | # CONFIG_NET_VENDOR_LITEX is not set |
| 507 | 508 | # CONFIG_NET_VENDOR_MARVELL is not set |
| 508 | 509 | CONFIG_MLX4_EN=m |
| @@ -542,6 +543,7 @@ CONFIG_MLX5_CORE_EN=y · 33 unmodified lines | ||
| 542 | 543 | # CONFIG_NET_VENDOR_TI is not set |
| 543 | 544 | # CONFIG_NET_VENDOR_VERTEXCOM is not set |
| 544 | 545 | # CONFIG_NET_VENDOR_VIA is not set |
| 546 | +# CONFIG_NET_VENDOR_WANGXUN is not set | |
| 545 | 547 | # CONFIG_NET_VENDOR_WIZNET is not set |
| 546 | 548 | # CONFIG_NET_VENDOR_XILINX is not set |
| 547 | 549 | CONFIG_PPP=m |
| @@ -646,7 +648,6 @@ CONFIG_TMPFS=y · 98 unmodified lines | ||
| 646 | 648 | CONFIG_TMPFS_POSIX_ACL=y |
| 647 | 649 | CONFIG_TMPFS_INODE64=y |
| 648 | 650 | CONFIG_HUGETLBFS=y |
| 649 | −CONFIG_CONFIGFS_FS=m | |
| 650 | 651 | CONFIG_ECRYPT_FS=m |
| 651 | 652 | CONFIG_CRAMFS=m |
| 652 | 653 | CONFIG_SQUASHFS=m |
| @@ -690,7 +691,6 @@ CONFIG_HARDENED_USERCOPY=y · 37 unmodified lines | ||
| 690 | 691 | CONFIG_FORTIFY_SOURCE=y |
| 691 | 692 | CONFIG_SECURITY_SELINUX=y |
| 692 | 693 | CONFIG_SECURITY_SELINUX_BOOTPARAM=y |
| 693 | −CONFIG_SECURITY_SELINUX_DISABLE=y | |
| 694 | 694 | CONFIG_SECURITY_LOCKDOWN_LSM=y |
| 695 | 695 | CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y |
| 696 | 696 | CONFIG_SECURITY_LANDLOCK=y |
| @@ -744,7 +744,6 @@ CONFIG_CRYPTO_MD4=m · 47 unmodified lines | ||
| 744 | 744 | CONFIG_CRYPTO_MD5=y |
| 745 | 745 | CONFIG_CRYPTO_MICHAEL_MIC=m |
| 746 | 746 | CONFIG_CRYPTO_RMD160=m |
| 747 | −CONFIG_CRYPTO_SHA3=m | |
| 748 | 747 | CONFIG_CRYPTO_SM3_GENERIC=m |
| 749 | 748 | CONFIG_CRYPTO_VMAC=m |
| 750 | 749 | CONFIG_CRYPTO_WP512=m |
| @@ -844,6 +843,7 @@ CONFIG_PREEMPT_TRACER=y · 93 unmodified lines | ||
| 844 | 843 | CONFIG_SCHED_TRACER=y |
| 845 | 844 | CONFIG_FTRACE_SYSCALLS=y |
| 846 | 845 | CONFIG_BLK_DEV_IO_TRACE=y |
| 846 | +CONFIG_USER_EVENTS=y | |
| 847 | 847 | CONFIG_HIST_TRIGGERS=y |
| 848 | 848 | CONFIG_FTRACE_STARTUP_TEST=y |
| 849 | 849 | # CONFIG_EVENT_TRACE_STARTUP_TEST is not set |
| @@ -866,6 +866,7 @@ CONFIG_FAIL_MAKE_REQUEST=y · 16 unmodified lines | ||
| 866 | 866 | CONFIG_FAIL_IO_TIMEOUT=y |
| 867 | 867 | CONFIG_FAIL_FUTEX=y |
| 868 | 868 | CONFIG_FAULT_INJECTION_DEBUG_FS=y |
| 869 | +CONFIG_FAULT_INJECTION_CONFIGFS=y | |
| 869 | 870 | CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y |
| 870 | 871 | CONFIG_LKDTM=m |
| 871 | 872 | CONFIG_TEST_MIN_HEAP=y |
| @@ -107,7 +107,6 @@ CONFIG_UNIX=y · 106 unmodified lines | ||
| 107 | 107 | CONFIG_UNIX_DIAG=m |
| 108 | 108 | CONFIG_XFRM_USER=m |
| 109 | 109 | CONFIG_NET_KEY=m |
| 110 | −CONFIG_NET_TC_SKB_EXT=y | |
| 111 | 110 | CONFIG_SMC=m |
| 112 | 111 | CONFIG_SMC_DIAG=m |
| 113 | 112 | CONFIG_INET=y |
| @@ -184,6 +183,7 @@ CONFIG_NFT_REJECT=m · 70 unmodified lines | ||
| 184 | 183 | CONFIG_NFT_COMPAT=m |
| 185 | 184 | CONFIG_NFT_HASH=m |
| 186 | 185 | CONFIG_NFT_FIB_INET=m |
| 186 | +CONFIG_NETFILTER_XTABLES_COMPAT=y | |
| 187 | 187 | CONFIG_NETFILTER_XT_SET=m |
| 188 | 188 | CONFIG_NETFILTER_XT_TARGET_AUDIT=m |
| 189 | 189 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
| @@ -369,6 +369,7 @@ CONFIG_NET_ACT_SIMP=m · 179 unmodified lines | ||
| 369 | 369 | CONFIG_NET_ACT_SKBEDIT=m |
| 370 | 370 | CONFIG_NET_ACT_CSUM=m |
| 371 | 371 | CONFIG_NET_ACT_GATE=m |
| 372 | +CONFIG_NET_TC_SKB_EXT=y | |
| 372 | 373 | CONFIG_DNS_RESOLVER=y |
| 373 | 374 | CONFIG_OPENVSWITCH=m |
| 374 | 375 | CONFIG_VSOCKETS=m |
| @@ -385,6 +386,7 @@ CONFIG_HOTPLUG_PCI_S390=y · 10 unmodified lines | ||
| 385 | 386 | CONFIG_UEVENT_HELPER=y |
| 386 | 387 | CONFIG_DEVTMPFS=y |
| 387 | 388 | CONFIG_DEVTMPFS_SAFE=y |
| 389 | +# CONFIG_FW_LOADER is not set | |
| 388 | 390 | CONFIG_CONNECTOR=y |
| 389 | 391 | CONFIG_ZRAM=y |
| 390 | 392 | CONFIG_BLK_DEV_LOOP=m |
| @@ -492,7 +494,6 @@ CONFIG_NLMON=m · 101 unmodified lines | ||
| 492 | 494 | # CONFIG_NET_VENDOR_GOOGLE is not set |
| 493 | 495 | # CONFIG_NET_VENDOR_HUAWEI is not set |
| 494 | 496 | # CONFIG_NET_VENDOR_INTEL is not set |
| 495 | −# CONFIG_NET_VENDOR_WANGXUN is not set | |
| 496 | 497 | # CONFIG_NET_VENDOR_LITEX is not set |
| 497 | 498 | # CONFIG_NET_VENDOR_MARVELL is not set |
| 498 | 499 | CONFIG_MLX4_EN=m |
| @@ -532,6 +533,7 @@ CONFIG_MLX5_CORE_EN=y · 33 unmodified lines | ||
| 532 | 533 | # CONFIG_NET_VENDOR_TI is not set |
| 533 | 534 | # CONFIG_NET_VENDOR_VERTEXCOM is not set |
| 534 | 535 | # CONFIG_NET_VENDOR_VIA is not set |
| 536 | +# CONFIG_NET_VENDOR_WANGXUN is not set | |
| 535 | 537 | # CONFIG_NET_VENDOR_WIZNET is not set |
| 536 | 538 | # CONFIG_NET_VENDOR_XILINX is not set |
| 537 | 539 | CONFIG_PPP=m |
| @@ -673,7 +675,6 @@ CONFIG_SECURITY=y · 135 unmodified lines | ||
| 673 | 675 | CONFIG_SECURITY_NETWORK=y |
| 674 | 676 | CONFIG_SECURITY_SELINUX=y |
| 675 | 677 | CONFIG_SECURITY_SELINUX_BOOTPARAM=y |
| 676 | −CONFIG_SECURITY_SELINUX_DISABLE=y | |
| 677 | 678 | CONFIG_SECURITY_LOCKDOWN_LSM=y |
| 678 | 679 | CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y |
| 679 | 680 | CONFIG_SECURITY_LANDLOCK=y |
| @@ -729,7 +730,6 @@ CONFIG_CRYPTO_MD4=m · 49 unmodified lines | ||
| 729 | 730 | CONFIG_CRYPTO_MD5=y |
| 730 | 731 | CONFIG_CRYPTO_MICHAEL_MIC=m |
| 731 | 732 | CONFIG_CRYPTO_RMD160=m |
| 732 | −CONFIG_CRYPTO_SHA3=m | |
| 733 | 733 | CONFIG_CRYPTO_SM3_GENERIC=m |
| 734 | 734 | CONFIG_CRYPTO_VMAC=m |
| 735 | 735 | CONFIG_CRYPTO_WP512=m |
| @@ -793,6 +793,7 @@ CONFIG_STACK_TRACER=y · 57 unmodified lines | ||
| 793 | 793 | CONFIG_SCHED_TRACER=y |
| 794 | 794 | CONFIG_FTRACE_SYSCALLS=y |
| 795 | 795 | CONFIG_BLK_DEV_IO_TRACE=y |
| 796 | +CONFIG_USER_EVENTS=y | |
| 796 | 797 | CONFIG_HIST_TRIGGERS=y |
| 797 | 798 | CONFIG_SAMPLES=y |
| 798 | 799 | CONFIG_SAMPLE_TRACE_PRINTK=m |
| @@ -53,7 +53,6 @@ CONFIG_ZFCP=y · 52 unmodified lines | ||
| 53 | 53 | # CONFIG_HVC_IUCV is not set |
| 54 | 54 | # CONFIG_HW_RANDOM_S390 is not set |
| 55 | 55 | # CONFIG_HMC_DRV is not set |
| 56 | −# CONFIG_S390_UV_UAPI is not set | |
| 57 | 56 | # CONFIG_S390_TAPE is not set |
| 58 | 57 | # CONFIG_VMCP is not set |
| 59 | 58 | # CONFIG_MONWRITER is not set |
| @@ -8,6 +8,8 @@ · 7 unmodified lines | ||
| 8 | 8 | #ifndef _UAPI_S390_PTRACE_H |
| 9 | 9 | #define _UAPI_S390_PTRACE_H |
| 10 | 10 | |
| 11 | +#include <linux/const.h> | |
| 12 | + | |
| 11 | 13 | /* |
| 12 | 14 | * Offsets in the user_regs_struct. They are used for the ptrace |
| 13 | 15 | * system call and in entry.S |
| @@ -459,9 +459,9 @@ static int sthyi_update_cache(u64 *rc) · 458 unmodified lines | ||
| 459 | 459 | * |
| 460 | 460 | * Fills the destination with system information returned by the STHYI |
| 461 | 461 | * instruction. The data is generated by emulation or execution of STHYI, |
| 462 | − * if available. The return value is the condition code that would be | |
| 463 | − * returned, the rc parameter is the return code which is passed in | |
| 464 | − * register R2 + 1. | |
| 462 | + * if available. The return value is either a negative error value or | |
| 463 | + * the condition code that would be returned, the rc parameter is the | |
| 464 | + * return code which is passed in register R2 + 1. | |
| 465 | 465 | */ |
| 466 | 466 | int sthyi_fill(void *dst, u64 *rc) |
| 467 | 467 | { |
| @@ -389,8 +389,8 @@ static int handle_partial_execution(struct kvm_vcpu *vcpu) · 388 unmodified lines | ||
| 389 | 389 | */ |
| 390 | 390 | int handle_sthyi(struct kvm_vcpu *vcpu) |
| 391 | 391 | { |
| 392 | − int reg1, reg2, r = 0; | |
| 393 | − u64 code, addr, cc = 0, rc = 0; | |
| 392 | + int reg1, reg2, cc = 0, r = 0; | |
| 393 | + u64 code, addr, rc = 0; | |
| 394 | 394 | struct sthyi_sctns *sctns = NULL; |
| 395 | 395 | |
| 396 | 396 | if (!test_kvm_facility(vcpu->kvm, 74)) |
| @@ -421,7 +421,10 @@ int handle_sthyi(struct kvm_vcpu *vcpu) · 24 unmodified lines | ||
| 421 | 421 | return -ENOMEM; |
| 422 | 422 | |
| 423 | 423 | cc = sthyi_fill(sctns, &rc); |
| 424 | − | |
| 424 | + if (cc < 0) { | |
| 425 | + free_page((unsigned long)sctns); | |
| 426 | + return cc; | |
| 427 | + } | |
| 425 | 428 | out: |
| 426 | 429 | if (!cc) { |
| 427 | 430 | if (kvm_s390_pv_cpu_is_protected(vcpu)) { |
| @@ -763,6 +763,8 @@ void __init vmem_map_init(void) · 762 unmodified lines | ||
| 763 | 763 | if (static_key_enabled(&cpu_has_bear)) |
| 764 | 764 | set_memory_nx(0, 1); |
| 765 | 765 | set_memory_nx(PAGE_SIZE, 1); |
| 766 | + if (debug_pagealloc_enabled()) | |
| 767 | + set_memory_4k(0, ident_map_size >> PAGE_SHIFT); | |
| 766 | 768 | |
| 767 | 769 | pr_info("Write protected kernel read-only data: %luk\n", |
| 768 | 770 | (unsigned long)(__end_rodata - _stext) >> 10); |
| @@ -213,7 +213,6 @@ unsigned long __get_wchan(struct task_struct *task); · 212 unmodified lines | ||
| 213 | 213 | */ |
| 214 | 214 | #define ARCH_HAS_PREFETCH |
| 215 | 215 | #define ARCH_HAS_PREFETCHW |
| 216 | −#define ARCH_HAS_SPINLOCK_PREFETCH | |
| 217 | 216 | |
| 218 | 217 | static inline void prefetch(const void *x) |
| 219 | 218 | { |
| @@ -239,8 +238,6 @@ static inline void prefetchw(const void *x) · 19 unmodified lines | ||
| 239 | 238 | : "r" (x)); |
| 240 | 239 | } |
| 241 | 240 | |
| 242 | −#define spin_lock_prefetch(x) prefetchw(x) | |
| 243 | − | |
| 244 | 241 | #define HAVE_ARCH_PICK_MMAP_LAYOUT |
| 245 | 242 | |
| 246 | 243 | int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap); |
| @@ -2593,6 +2593,13 @@ config CPU_IBRS_ENTRY · 2592 unmodified lines | ||
| 2593 | 2593 | This mitigates both spectre_v2 and retbleed at great cost to |
| 2594 | 2594 | performance. |
| 2595 | 2595 | |
| 2596 | +config CPU_SRSO | |
| 2597 | + bool "Mitigate speculative RAS overflow on AMD" | |
| 2598 | + depends on CPU_SUP_AMD && X86_64 && RETHUNK | |
| 2599 | + default y | |
| 2600 | + help | |
| 2601 | + Enable the SRSO mitigation needed on AMD Zen1-4 machines. | |
| 2602 | + | |
| 2596 | 2603 | config SLS |
| 2597 | 2604 | bool "Mitigate Straight-Line-Speculation" |
| 2598 | 2605 | depends on CC_HAS_SLS && X86_64 |
| @@ -2603,6 +2610,25 @@ config SLS · 4 unmodified lines | ||
| 2603 | 2610 | against straight line speculation. The kernel image might be slightly |
| 2604 | 2611 | larger. |
| 2605 | 2612 | |
| 2613 | +config GDS_FORCE_MITIGATION | |
| 2614 | + bool "Force GDS Mitigation" | |
| 2615 | + depends on CPU_SUP_INTEL | |
| 2616 | + default n | |
| 2617 | + help | |
| 2618 | + Gather Data Sampling (GDS) is a hardware vulnerability which allows | |
| 2619 | + unprivileged speculative access to data which was previously stored in | |
| 2620 | + vector registers. | |
| 2621 | + | |
| 2622 | + This option is equivalent to setting gather_data_sampling=force on the | |
| 2623 | + command line. The microcode mitigation is used if present, otherwise | |
| 2624 | + AVX is disabled as a mitigation. On affected systems that are missing | |
| 2625 | + the microcode any userspace code that unconditionally uses AVX will | |
| 2626 | + break with this option set. | |
| 2627 | + | |
| 2628 | + Setting this option on systems not vulnerable to GDS has no effect. | |
| 2629 | + | |
| 2630 | + If in doubt, say N. | |
| 2631 | + | |
| 2606 | 2632 | endif |
| 2607 | 2633 | |
| 2608 | 2634 | config ARCH_HAS_ADD_PAGES |
| @@ -63,7 +63,14 @@ void load_stage2_idt(void) · 62 unmodified lines | ||
| 63 | 63 | set_idt_entry(X86_TRAP_PF, boot_page_fault); |
| 64 | 64 | |
| 65 | 65 | #ifdef CONFIG_AMD_MEM_ENCRYPT |
| 66 | − set_idt_entry(X86_TRAP_VC, boot_stage2_vc); | |
| 66 | + /* | |
| 67 | + * Clear the second stage #VC handler in case guest types | |
| 68 | + * needing #VC have not been detected. | |
| 69 | + */ | |
| 70 | + if (sev_status & BIT(1)) | |
| 71 | + set_idt_entry(X86_TRAP_VC, boot_stage2_vc); | |
| 72 | + else | |
| 73 | + set_idt_entry(X86_TRAP_VC, NULL); | |
| 67 | 74 | #endif |
| 68 | 75 | |
| 69 | 76 | load_boot_idt(&boot_idt_desc); |
| @@ -404,13 +404,46 @@ void sev_enable(struct boot_params *bp) · 403 unmodified lines | ||
| 404 | 404 | if (bp) |
| 405 | 405 | bp->cc_blob_address = 0; |
| 406 | 406 | |
| 407 | + /* | |
| 408 | + * Do an initial SEV capability check before snp_init() which | |
| 409 | + * loads the CPUID page and the same checks afterwards are done | |
| 410 | + * without the hypervisor and are trustworthy. | |
| 411 | + * | |
| 412 | + * If the HV fakes SEV support, the guest will crash'n'burn | |
| 413 | + * which is good enough. | |
| 414 | + */ | |
| 415 | + | |
| 416 | + /* Check for the SME/SEV support leaf */ | |
| 417 | + eax = 0x80000000; | |
| 418 | + ecx = 0; | |
| 419 | + native_cpuid(&eax, &ebx, &ecx, &edx); | |
| 420 | + if (eax < 0x8000001f) | |
| 421 | + return; | |
| 422 | + | |
| 423 | + /* | |
| 424 | + * Check for the SME/SEV feature: | |
| 425 | + * CPUID Fn8000_001F[EAX] | |
| 426 | + * - Bit 0 - Secure Memory Encryption support | |
| 427 | + * - Bit 1 - Secure Encrypted Virtualization support | |
| 428 | + * CPUID Fn8000_001F[EBX] | |
| 429 | + * - Bits 5:0 - Pagetable bit position used to indicate encryption | |
| 430 | + */ | |
| 431 | + eax = 0x8000001f; | |
| 432 | + ecx = 0; | |
| 433 | + native_cpuid(&eax, &ebx, &ecx, &edx); | |
| 434 | + /* Check whether SEV is supported */ | |
| 435 | + if (!(eax & BIT(1))) | |
| 436 | + return; | |
| 437 | + | |
| 407 | 438 | /* |
| 408 | 439 | * Setup/preliminary detection of SNP. This will be sanity-checked |
| 409 | 440 | * against CPUID/MSR values later. |
| 410 | 441 | */ |
| 411 | 442 | snp = snp_init(bp); |
| 412 | 443 | |
| 413 | − /* Check for the SME/SEV support leaf */ | |
| 444 | + /* Now repeat the checks with the SNP CPUID table. */ | |
| 445 | + | |
| 446 | + /* Recheck the SME/SEV support leaf */ | |
| 414 | 447 | eax = 0x80000000; |
| 415 | 448 | ecx = 0; |
| 416 | 449 | native_cpuid(&eax, &ebx, &ecx, &edx); |
| @@ -418,7 +451,7 @@ void sev_enable(struct boot_params *bp) · 1 unmodified line | ||
| 418 | 451 | return; |
| 419 | 452 | |
| 420 | 453 | /* |
| 421 | − * Check for the SME/SEV feature: | |
| 454 | + * Recheck for the SME/SEV feature: | |
| 422 | 455 | * CPUID Fn8000_001F[EAX] |
| 423 | 456 | * - Bit 0 - Secure Memory Encryption support |
| 424 | 457 | * - Bit 1 - Secure Encrypted Virtualization support |
| @@ -299,8 +299,8 @@ static unsigned long vdso_addr(unsigned long start, unsigned len) · 298 unmodified lines | ||
| 299 | 299 | |
| 300 | 300 | /* Round the lowest possible end address up to a PMD boundary. */ |
| 301 | 301 | end = (start + len + PMD_SIZE - 1) & PMD_MASK; |
| 302 | − if (end >= TASK_SIZE_MAX) | |
| 303 | − end = TASK_SIZE_MAX; | |
| 302 | + if (end >= DEFAULT_MAP_WINDOW) | |
| 303 | + end = DEFAULT_MAP_WINDOW; | |
| 304 | 304 | end -= len; |
| 305 | 305 | |
| 306 | 306 | if (end > start) { |
| @@ -107,7 +107,6 @@ static bool cpu_is_self(int cpu) · 106 unmodified lines | ||
| 107 | 107 | static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, |
| 108 | 108 | bool exclude_self) |
| 109 | 109 | { |
| 110 | − struct hv_send_ipi_ex **arg; | |
| 111 | 110 | struct hv_send_ipi_ex *ipi_arg; |
| 112 | 111 | unsigned long flags; |
| 113 | 112 | int nr_bank = 0; |
| @@ -117,9 +116,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, · 3 unmodified lines | ||
| 117 | 116 | return false; |
| 118 | 117 | |
| 119 | 118 | local_irq_save(flags); |
| 120 | − arg = (struct hv_send_ipi_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 119 | + ipi_arg = *this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 121 | 120 | |
| 122 | − ipi_arg = *arg; | |
| 123 | 121 | if (unlikely(!ipi_arg)) |
| 124 | 122 | goto ipi_mask_ex_done; |
| 125 | 123 | |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <asm/apic.h> |
| 15 | 15 | #include <asm/desc.h> |
| 16 | 16 | #include <asm/sev.h> |
| 17 | +#include <asm/ibt.h> | |
| 17 | 18 | #include <asm/hypervisor.h> |
| 18 | 19 | #include <asm/hyperv-tlfs.h> |
| 19 | 20 | #include <asm/mshyperv.h> |
| @@ -471,6 +472,26 @@ void __init hyperv_init(void) · 451 unmodified lines | ||
| 471 | 472 | wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); |
| 472 | 473 | } |
| 473 | 474 | |
| 475 | + /* | |
| 476 | + * Some versions of Hyper-V that provide IBT in guest VMs have a bug | |
| 477 | + * in that there's no ENDBR64 instruction at the entry to the | |
| 478 | + * hypercall page. Because hypercalls are invoked via an indirect call | |
| 479 | + * to the hypercall page, all hypercall attempts fail when IBT is | |
| 480 | + * enabled, and Linux panics. For such buggy versions, disable IBT. | |
| 481 | + * | |
| 482 | + * Fixed versions of Hyper-V always provide ENDBR64 on the hypercall | |
| 483 | + * page, so if future Linux kernel versions enable IBT for 32-bit | |
| 484 | + * builds, additional hypercall page hackery will be required here | |
| 485 | + * to provide an ENDBR32. | |
| 486 | + */ | |
| 487 | +#ifdef CONFIG_X86_KERNEL_IBT | |
| 488 | + if (cpu_feature_enabled(X86_FEATURE_IBT) && | |
| 489 | + *(u32 *)hv_hypercall_pg != gen_endbr()) { | |
| 490 | + setup_clear_cpu_cap(X86_FEATURE_IBT); | |
| 491 | + pr_warn("Hyper-V: Disabling IBT because of Hyper-V bug\n"); | |
| 492 | + } | |
| 493 | +#endif | |
| 494 | + | |
| 474 | 495 | /* |
| 475 | 496 | * hyperv_init() is called before LAPIC is initialized: see |
| 476 | 497 | * apic_intr_mode_init() -> x86_platform.apic_post_init() and |
| @@ -25,6 +25,10 @@ void __init hv_vtl_init_platform(void) · 24 unmodified lines | ||
| 25 | 25 | x86_init.irqs.pre_vector_init = x86_init_noop; |
| 26 | 26 | x86_init.timers.timer_init = x86_init_noop; |
| 27 | 27 | |
| 28 | + /* Avoid searching for BIOS MP tables */ | |
| 29 | + x86_init.mpparse.find_smp_config = x86_init_noop; | |
| 30 | + x86_init.mpparse.get_smp_config = x86_init_uint_noop; | |
| 31 | + | |
| 28 | 32 | x86_platform.get_wallclock = get_rtc_noop; |
| 29 | 33 | x86_platform.set_wallclock = set_rtc_noop; |
| 30 | 34 | x86_platform.get_nmi_reason = hv_get_nmi_reason; |
| @@ -247,7 +247,7 @@ EXPORT_SYMBOL_GPL(hv_ghcb_msr_read); · 246 unmodified lines | ||
| 247 | 247 | static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], |
| 248 | 248 | enum hv_mem_host_visibility visibility) |
| 249 | 249 | { |
| 250 | − struct hv_gpa_range_for_visibility **input_pcpu, *input; | |
| 250 | + struct hv_gpa_range_for_visibility *input; | |
| 251 | 251 | u16 pages_processed; |
| 252 | 252 | u64 hv_status; |
| 253 | 253 | unsigned long flags; |
| @@ -263,9 +263,8 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], · 9 unmodified lines | ||
| 263 | 263 | } |
| 264 | 264 | |
| 265 | 265 | local_irq_save(flags); |
| 266 | − input_pcpu = (struct hv_gpa_range_for_visibility **) | |
| 267 | − this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 268 | − input = *input_pcpu; | |
| 266 | + input = *this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 267 | + | |
| 269 | 268 | if (unlikely(!input)) { |
| 270 | 269 | local_irq_restore(flags); |
| 271 | 270 | return -EINVAL; |
| @@ -61,7 +61,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, · 60 unmodified lines | ||
| 61 | 61 | const struct flush_tlb_info *info) |
| 62 | 62 | { |
| 63 | 63 | int cpu, vcpu, gva_n, max_gvas; |
| 64 | − struct hv_tlb_flush **flush_pcpu; | |
| 65 | 64 | struct hv_tlb_flush *flush; |
| 66 | 65 | u64 status; |
| 67 | 66 | unsigned long flags; |
| @@ -74,10 +73,7 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, · 6 unmodified lines | ||
| 74 | 73 | |
| 75 | 74 | local_irq_save(flags); |
| 76 | 75 | |
| 77 | − flush_pcpu = (struct hv_tlb_flush **) | |
| 78 | − this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 79 | − | |
| 80 | − flush = *flush_pcpu; | |
| 76 | + flush = *this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 81 | 77 | |
| 82 | 78 | if (unlikely(!flush)) { |
| 83 | 79 | local_irq_restore(flags); |
| @@ -178,17 +174,13 @@ static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus, · 94 unmodified lines | ||
| 178 | 174 | const struct flush_tlb_info *info) |
| 179 | 175 | { |
| 180 | 176 | int nr_bank = 0, max_gvas, gva_n; |
| 181 | − struct hv_tlb_flush_ex **flush_pcpu; | |
| 182 | 177 | struct hv_tlb_flush_ex *flush; |
| 183 | 178 | u64 status; |
| 184 | 179 | |
| 185 | 180 | if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) |
| 186 | 181 | return HV_STATUS_INVALID_PARAMETER; |
| 187 | 182 | |
| 188 | − flush_pcpu = (struct hv_tlb_flush_ex **) | |
| 189 | − this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 190 | − | |
| 191 | − flush = *flush_pcpu; | |
| 183 | + flush = *this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 192 | 184 | |
| 193 | 185 | if (info->mm) { |
| 194 | 186 | /* |
| @@ -19,7 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | int hyperv_flush_guest_mapping(u64 as) |
| 21 | 21 | { |
| 22 | − struct hv_guest_mapping_flush **flush_pcpu; | |
| 23 | 22 | struct hv_guest_mapping_flush *flush; |
| 24 | 23 | u64 status; |
| 25 | 24 | unsigned long flags; |
| @@ -30,10 +29,7 @@ int hyperv_flush_guest_mapping(u64 as) · 4 unmodified lines | ||
| 30 | 29 | |
| 31 | 30 | local_irq_save(flags); |
| 32 | 31 | |
| 33 | − flush_pcpu = (struct hv_guest_mapping_flush **) | |
| 34 | − this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 35 | − | |
| 36 | − flush = *flush_pcpu; | |
| 32 | + flush = *this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 37 | 33 | |
| 38 | 34 | if (unlikely(!flush)) { |
| 39 | 35 | local_irq_restore(flags); |
| @@ -90,7 +86,6 @@ EXPORT_SYMBOL_GPL(hyperv_fill_flush_guest_mapping_list); · 50 unmodified lines | ||
| 90 | 86 | int hyperv_flush_guest_mapping_range(u64 as, |
| 91 | 87 | hyperv_fill_flush_list_func fill_flush_list_func, void *data) |
| 92 | 88 | { |
| 93 | − struct hv_guest_mapping_flush_list **flush_pcpu; | |
| 94 | 89 | struct hv_guest_mapping_flush_list *flush; |
| 95 | 90 | u64 status; |
| 96 | 91 | unsigned long flags; |
| @@ -102,10 +97,8 @@ int hyperv_flush_guest_mapping_range(u64 as, · 5 unmodified lines | ||
| 102 | 97 | |
| 103 | 98 | local_irq_save(flags); |
| 104 | 99 | |
| 105 | − flush_pcpu = (struct hv_guest_mapping_flush_list **) | |
| 106 | − this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 100 | + flush = *this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 107 | 101 | |
| 108 | − flush = *flush_pcpu; | |
| 109 | 102 | if (unlikely(!flush)) { |
| 110 | 103 | local_irq_restore(flags); |
| 111 | 104 | goto fault; |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <asm/mpspec.h> |
| 16 | 16 | #include <asm/x86_init.h> |
| 17 | 17 | #include <asm/cpufeature.h> |
| 18 | +#include <asm/irq_vectors.h> | |
| 18 | 19 | |
| 19 | 20 | #ifdef CONFIG_ACPI_APEI |
| 20 | 21 | # include <asm/pgtable_types.h> |
| @@ -31,6 +32,7 @@ extern int acpi_skip_timer_override; · 10 unmodified lines | ||
| 31 | 32 | extern int acpi_use_timer_override; |
| 32 | 33 | extern int acpi_fix_pin2_polarity; |
| 33 | 34 | extern int acpi_disable_cmcff; |
| 35 | +extern bool acpi_int_src_ovr[NR_IRQS_LEGACY]; | |
| 34 | 36 | |
| 35 | 37 | extern u8 acpi_sci_flags; |
| 36 | 38 | extern u32 acpi_sci_override_gsi; |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | * Defines x86 CPU feature bits |
| 15 | 15 | */ |
| 16 | 16 | #define NCAPINTS 21 /* N 32-bit words worth of info */ |
| 17 | −#define NBUGINTS 1 /* N 32-bit bug flags */ | |
| 17 | +#define NBUGINTS 2 /* N 32-bit bug flags */ | |
| 18 | 18 | |
| 19 | 19 | /* |
| 20 | 20 | * Note: If the comment begins with a quoted string, that string is used |
| @@ -309,6 +309,10 @@ · 288 unmodified lines | ||
| 309 | 309 | #define X86_FEATURE_SMBA (11*32+21) /* "" Slow Memory Bandwidth Allocation */ |
| 310 | 310 | #define X86_FEATURE_BMEC (11*32+22) /* "" Bandwidth Monitoring Event Configuration */ |
| 311 | 311 | |
| 312 | +#define X86_FEATURE_SRSO (11*32+24) /* "" AMD BTB untrain RETs */ | |
| 313 | +#define X86_FEATURE_SRSO_ALIAS (11*32+25) /* "" AMD BTB untrain RETs through aliasing */ | |
| 314 | +#define X86_FEATURE_IBPB_ON_VMEXIT (11*32+26) /* "" Issue an IBPB only on VMEXIT */ | |
| 315 | + | |
| 312 | 316 | /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ |
| 313 | 317 | #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ |
| 314 | 318 | #define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */ |
| @@ -442,6 +446,10 @@ · 127 unmodified lines | ||
| 442 | 446 | #define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */ |
| 443 | 447 | #define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* "" SMM_CTL MSR is not present */ |
| 444 | 448 | |
| 449 | +#define X86_FEATURE_SBPB (20*32+27) /* "" Selective Branch Prediction Barrier */ | |
| 450 | +#define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */ | |
| 451 | +#define X86_FEATURE_SRSO_NO (20*32+29) /* "" CPU is not affected by SRSO */ | |
| 452 | + | |
| 445 | 453 | /* |
| 446 | 454 | * BUG word(s) |
| 447 | 455 | */ |
| @@ -483,5 +491,9 @@ · 35 unmodified lines | ||
| 483 | 491 | #define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */ |
| 484 | 492 | #define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */ |
| 485 | 493 | #define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */ |
| 494 | +#define X86_BUG_GDS X86_BUG(30) /* CPU is affected by Gather Data Sampling */ | |
| 486 | 495 | |
| 496 | +/* BUG word 2 */ | |
| 497 | +#define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */ | |
| 498 | +#define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */ | |
| 487 | 499 | #endif /* _ASM_X86_CPUFEATURES_H */ |
| @@ -21,7 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #define FUNCTION_PADDING |
| 22 | 22 | #endif |
| 23 | 23 | |
| 24 | −#if (CONFIG_FUNCTION_ALIGNMENT > 8) && !defined(__DISABLE_EXPORTS) && !defined(BULID_VDSO) | |
| 24 | +#if (CONFIG_FUNCTION_ALIGNMENT > 8) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO) | |
| 25 | 25 | # define __FUNC_ALIGN __ALIGN; FUNCTION_PADDING |
| 26 | 26 | #else |
| 27 | 27 | # define __FUNC_ALIGN __ALIGN |
| @@ -5,7 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | #include <linux/types.h> |
| 6 | 6 | #include <linux/nmi.h> |
| 7 | 7 | #include <linux/msi.h> |
| 8 | −#include <asm/io.h> | |
| 8 | +#include <linux/io.h> | |
| 9 | 9 | #include <asm/hyperv-tlfs.h> |
| 10 | 10 | #include <asm/nospec-branch.h> |
| 11 | 11 | #include <asm/paravirt.h> |
| @@ -57,6 +57,7 @@ · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */ |
| 59 | 59 | #define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */ |
| 60 | +#define PRED_CMD_SBPB BIT(7) /* Selective Branch Prediction Barrier */ | |
| 60 | 61 | |
| 61 | 62 | #define MSR_PPIN_CTL 0x0000004e |
| 62 | 63 | #define MSR_PPIN 0x0000004f |
| @@ -155,6 +156,15 @@ · 92 unmodified lines | ||
| 155 | 156 | * Not susceptible to Post-Barrier |
| 156 | 157 | * Return Stack Buffer Predictions. |
| 157 | 158 | */ |
| 159 | +#define ARCH_CAP_GDS_CTRL BIT(25) /* | |
| 160 | + * CPU is vulnerable to Gather | |
| 161 | + * Data Sampling (GDS) and | |
| 162 | + * has controls for mitigation. | |
| 163 | + */ | |
| 164 | +#define ARCH_CAP_GDS_NO BIT(26) /* | |
| 165 | + * CPU is not vulnerable to Gather | |
| 166 | + * Data Sampling (GDS). | |
| 167 | + */ | |
| 158 | 168 | |
| 159 | 169 | #define ARCH_CAP_XAPIC_DISABLE BIT(21) /* |
| 160 | 170 | * IA32_XAPIC_DISABLE_STATUS MSR |
| @@ -178,6 +188,8 @@ · 17 unmodified lines | ||
| 178 | 188 | #define RNGDS_MITG_DIS BIT(0) /* SRBDS support */ |
| 179 | 189 | #define RTM_ALLOW BIT(1) /* TSX development mode */ |
| 180 | 190 | #define FB_CLEAR_DIS BIT(3) /* CPU Fill buffer clear disable */ |
| 191 | +#define GDS_MITG_DIS BIT(4) /* Disable GDS mitigation */ | |
| 192 | +#define GDS_MITG_LOCKED BIT(5) /* GDS mitigation locked */ | |
| 181 | 193 | |
| 182 | 194 | #define MSR_IA32_SYSENTER_CS 0x00000174 |
| 183 | 195 | #define MSR_IA32_SYSENTER_ESP 0x00000175 |
| @@ -211,7 +211,8 @@ · 210 unmodified lines | ||
| 211 | 211 | * eventually turn into it's own annotation. |
| 212 | 212 | */ |
| 213 | 213 | .macro VALIDATE_UNRET_END |
| 214 | −#if defined(CONFIG_NOINSTR_VALIDATION) && defined(CONFIG_CPU_UNRET_ENTRY) | |
| 214 | +#if defined(CONFIG_NOINSTR_VALIDATION) && \ | |
| 215 | + (defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_SRSO)) | |
| 215 | 216 | ANNOTATE_RETPOLINE_SAFE |
| 216 | 217 | nop |
| 217 | 218 | #endif |
| @@ -289,13 +290,18 @@ · 71 unmodified lines | ||
| 289 | 290 | */ |
| 290 | 291 | .macro UNTRAIN_RET |
| 291 | 292 | #if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_IBPB_ENTRY) || \ |
| 292 | − defined(CONFIG_CALL_DEPTH_TRACKING) | |
| 293 | + defined(CONFIG_CALL_DEPTH_TRACKING) || defined(CONFIG_CPU_SRSO) | |
| 293 | 294 | VALIDATE_UNRET_END |
| 294 | 295 | ALTERNATIVE_3 "", \ |
| 295 | 296 | CALL_ZEN_UNTRAIN_RET, X86_FEATURE_UNRET, \ |
| 296 | 297 | "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \ |
| 297 | 298 | __stringify(RESET_CALL_DEPTH), X86_FEATURE_CALL_DEPTH |
| 298 | 299 | #endif |
| 300 | + | |
| 301 | +#ifdef CONFIG_CPU_SRSO | |
| 302 | + ALTERNATIVE_2 "", "call srso_untrain_ret", X86_FEATURE_SRSO, \ | |
| 303 | + "call srso_untrain_ret_alias", X86_FEATURE_SRSO_ALIAS | |
| 304 | +#endif | |
| 299 | 305 | .endm |
| 300 | 306 | |
| 301 | 307 | .macro UNTRAIN_RET_FROM_CALL |
| @@ -307,6 +313,11 @@ · 5 unmodified lines | ||
| 307 | 313 | "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \ |
| 308 | 314 | __stringify(RESET_CALL_DEPTH_FROM_CALL), X86_FEATURE_CALL_DEPTH |
| 309 | 315 | #endif |
| 316 | + | |
| 317 | +#ifdef CONFIG_CPU_SRSO | |
| 318 | + ALTERNATIVE_2 "", "call srso_untrain_ret", X86_FEATURE_SRSO, \ | |
| 319 | + "call srso_untrain_ret_alias", X86_FEATURE_SRSO_ALIAS | |
| 320 | +#endif | |
| 310 | 321 | .endm |
| 311 | 322 | |
| 312 | 323 | |
| @@ -332,6 +343,8 @@ extern retpoline_thunk_t __x86_indirect_jump_thunk_array[]; · 19 unmodified lines | ||
| 332 | 343 | |
| 333 | 344 | extern void __x86_return_thunk(void); |
| 334 | 345 | extern void zen_untrain_ret(void); |
| 346 | +extern void srso_untrain_ret(void); | |
| 347 | +extern void srso_untrain_ret_alias(void); | |
| 335 | 348 | extern void entry_ibpb(void); |
| 336 | 349 | |
| 337 | 350 | #ifdef CONFIG_CALL_THUNKS |
| @@ -479,11 +492,11 @@ void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature) · 141 unmodified lines | ||
| 479 | 492 | : "memory"); |
| 480 | 493 | } |
| 481 | 494 | |
| 495 | +extern u64 x86_pred_cmd; | |
| 496 | + | |
| 482 | 497 | static inline void indirect_branch_prediction_barrier(void) |
| 483 | 498 | { |
| 484 | − u64 val = PRED_CMD_IBPB; | |
| 485 | − | |
| 486 | − alternative_msr_write(MSR_IA32_PRED_CMD, val, X86_FEATURE_USE_IBPB); | |
| 499 | + alternative_msr_write(MSR_IA32_PRED_CMD, x86_pred_cmd, X86_FEATURE_USE_IBPB); | |
| 487 | 500 | } |
| 488 | 501 | |
| 489 | 502 | /* The Intel SPEC CTRL MSR base value cache */ |
| @@ -586,7 +586,6 @@ extern char ignore_fpu_irq; · 585 unmodified lines | ||
| 586 | 586 | |
| 587 | 587 | #define HAVE_ARCH_PICK_MMAP_LAYOUT 1 |
| 588 | 588 | #define ARCH_HAS_PREFETCHW |
| 589 | −#define ARCH_HAS_SPINLOCK_PREFETCH | |
| 590 | 589 | |
| 591 | 590 | #ifdef CONFIG_X86_32 |
| 592 | 591 | # define BASE_PREFETCH "" |
| @@ -620,11 +619,6 @@ static __always_inline void prefetchw(const void *x) · 27 unmodified lines | ||
| 620 | 619 | "m" (*(const char *)x)); |
| 621 | 620 | } |
| 622 | 621 | |
| 623 | −static inline void spin_lock_prefetch(const void *x) | |
| 624 | −{ | |
| 625 | − prefetchw(x); | |
| 626 | −} | |
| 627 | − | |
| 628 | 622 | #define TOP_OF_INIT_STACK ((unsigned long)&init_stack + sizeof(init_stack) - \ |
| 629 | 623 | TOP_OF_KERNEL_STACK_PADDING) |
| 630 | 624 | |
| @@ -682,9 +676,13 @@ extern u16 get_llc_id(unsigned int cpu); · 51 unmodified lines | ||
| 682 | 676 | #ifdef CONFIG_CPU_SUP_AMD |
| 683 | 677 | extern u32 amd_get_nodes_per_socket(void); |
| 684 | 678 | extern u32 amd_get_highest_perf(void); |
| 679 | +extern bool cpu_has_ibpb_brtype_microcode(void); | |
| 680 | +extern void amd_clear_divider(void); | |
| 685 | 681 | #else |
| 686 | 682 | static inline u32 amd_get_nodes_per_socket(void) { return 0; } |
| 687 | 683 | static inline u32 amd_get_highest_perf(void) { return 0; } |
| 684 | +static inline bool cpu_has_ibpb_brtype_microcode(void) { return false; } | |
| 685 | +static inline void amd_clear_divider(void) { } | |
| 688 | 686 | #endif |
| 689 | 687 | |
| 690 | 688 | extern unsigned long arch_align_stack(unsigned long sp); |
| @@ -727,4 +725,6 @@ bool arch_is_platform_page(u64 paddr); · 36 unmodified lines | ||
| 727 | 725 | #define arch_is_platform_page arch_is_platform_page |
| 728 | 726 | #endif |
| 729 | 727 | |
| 728 | +extern bool gds_ucode_mitigated(void); | |
| 729 | + | |
| 730 | 730 | #endif /* _ASM_X86_PROCESSOR_H */ |
| @@ -56,7 +56,7 @@ · 55 unmodified lines | ||
| 56 | 56 | |
| 57 | 57 | #define GDT_ENTRY_INVALID_SEG 0 |
| 58 | 58 | |
| 59 | −#ifdef CONFIG_X86_32 | |
| 59 | +#if defined(CONFIG_X86_32) && !defined(BUILD_VDSO32_64) | |
| 60 | 60 | /* |
| 61 | 61 | * The layout of the per-CPU GDT under Linux: |
| 62 | 62 | * |
| @@ -52,6 +52,7 @@ int acpi_lapic; · 51 unmodified lines | ||
| 52 | 52 | int acpi_ioapic; |
| 53 | 53 | int acpi_strict; |
| 54 | 54 | int acpi_disable_cmcff; |
| 55 | +bool acpi_int_src_ovr[NR_IRQS_LEGACY]; | |
| 55 | 56 | |
| 56 | 57 | /* ACPI SCI override configuration */ |
| 57 | 58 | u8 acpi_sci_flags __initdata; |
| @@ -588,6 +589,9 @@ acpi_parse_int_src_ovr(union acpi_subtable_headers * header, · 530 unmodified lines | ||
| 588 | 589 | |
| 589 | 590 | acpi_table_print_madt_entry(&header->common); |
| 590 | 591 | |
| 592 | + if (intsrc->source_irq < NR_IRQS_LEGACY) | |
| 593 | + acpi_int_src_ovr[intsrc->source_irq] = true; | |
| 594 | + | |
| 591 | 595 | if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { |
| 592 | 596 | acpi_sci_ioapic_setup(intsrc->source_irq, |
| 593 | 597 | intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, |
| @@ -73,8 +73,13 @@ static const int amd_erratum_1054[] = · 72 unmodified lines | ||
| 73 | 73 | static const int amd_zenbleed[] = |
| 74 | 74 | AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf), |
| 75 | 75 | AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf), |
| 76 | + AMD_MODEL_RANGE(0x17, 0x90, 0x0, 0x91, 0xf), | |
| 76 | 77 | AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf)); |
| 77 | 78 | |
| 79 | +static const int amd_div0[] = | |
| 80 | + AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf), | |
| 81 | + AMD_MODEL_RANGE(0x17, 0x50, 0x0, 0x5f, 0xf)); | |
| 82 | + | |
| 78 | 83 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) |
| 79 | 84 | { |
| 80 | 85 | int osvw_id = *erratum++; |
| @@ -1130,6 +1135,11 @@ static void init_amd(struct cpuinfo_x86 *c) · 1049 unmodified lines | ||
| 1130 | 1135 | WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS)); |
| 1131 | 1136 | |
| 1132 | 1137 | zenbleed_check(c); |
| 1138 | + | |
| 1139 | + if (cpu_has_amd_erratum(c, amd_div0)) { | |
| 1140 | + pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n"); | |
| 1141 | + setup_force_cpu_bug(X86_BUG_DIV0); | |
| 1142 | + } | |
| 1133 | 1143 | } |
| 1134 | 1144 | |
| 1135 | 1145 | #ifdef CONFIG_X86_32 |
| @@ -1290,3 +1300,32 @@ void amd_check_microcode(void) · 154 unmodified lines | ||
| 1290 | 1300 | { |
| 1291 | 1301 | on_each_cpu(zenbleed_check_cpu, NULL, 1); |
| 1292 | 1302 | } |
| 1303 | + | |
| 1304 | +bool cpu_has_ibpb_brtype_microcode(void) | |
| 1305 | +{ | |
| 1306 | + switch (boot_cpu_data.x86) { | |
| 1307 | + /* Zen1/2 IBPB flushes branch type predictions too. */ | |
| 1308 | + case 0x17: | |
| 1309 | + return boot_cpu_has(X86_FEATURE_AMD_IBPB); | |
| 1310 | + case 0x19: | |
| 1311 | + /* Poke the MSR bit on Zen3/4 to check its presence. */ | |
| 1312 | + if (!wrmsrl_safe(MSR_IA32_PRED_CMD, PRED_CMD_SBPB)) { | |
| 1313 | + setup_force_cpu_cap(X86_FEATURE_SBPB); | |
| 1314 | + return true; | |
| 1315 | + } else { | |
| 1316 | + return false; | |
| 1317 | + } | |
| 1318 | + default: | |
| 1319 | + return false; | |
| 1320 | + } | |
| 1321 | +} | |
| 1322 | + | |
| 1323 | +/* | |
| 1324 | + * Issue a DIV 0/1 insn to clear any division data from previous DIV | |
| 1325 | + * operations. | |
| 1326 | + */ | |
| 1327 | +void noinstr amd_clear_divider(void) | |
| 1328 | +{ | |
| 1329 | + asm volatile(ALTERNATIVE("", "div %2\n\t", X86_BUG_DIV0) | |
| 1330 | + :: "a" (0), "d" (0), "r" (1)); | |
| 1331 | +} | |
| @@ -47,6 +47,8 @@ static void __init taa_select_mitigation(void); · 46 unmodified lines | ||
| 47 | 47 | static void __init mmio_select_mitigation(void); |
| 48 | 48 | static void __init srbds_select_mitigation(void); |
| 49 | 49 | static void __init l1d_flush_select_mitigation(void); |
| 50 | +static void __init srso_select_mitigation(void); | |
| 51 | +static void __init gds_select_mitigation(void); | |
| 50 | 52 | |
| 51 | 53 | /* The base value of the SPEC_CTRL MSR without task-specific bits set */ |
| 52 | 54 | u64 x86_spec_ctrl_base; |
| @@ -56,6 +58,9 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_base); · 3 unmodified lines | ||
| 56 | 58 | DEFINE_PER_CPU(u64, x86_spec_ctrl_current); |
| 57 | 59 | EXPORT_SYMBOL_GPL(x86_spec_ctrl_current); |
| 58 | 60 | |
| 61 | +u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB; | |
| 62 | +EXPORT_SYMBOL_GPL(x86_pred_cmd); | |
| 63 | + | |
| 59 | 64 | static DEFINE_MUTEX(spec_ctrl_mutex); |
| 60 | 65 | |
| 61 | 66 | /* Update SPEC_CTRL MSR and its cached copy unconditionally */ |
| @@ -160,6 +165,8 @@ void __init cpu_select_mitigations(void) · 98 unmodified lines | ||
| 160 | 165 | md_clear_select_mitigation(); |
| 161 | 166 | srbds_select_mitigation(); |
| 162 | 167 | l1d_flush_select_mitigation(); |
| 168 | + srso_select_mitigation(); | |
| 169 | + gds_select_mitigation(); | |
| 163 | 170 | } |
| 164 | 171 | |
| 165 | 172 | /* |
| @@ -645,6 +652,149 @@ static int __init l1d_flush_parse_cmdline(char *str) · 479 unmodified lines | ||
| 645 | 652 | } |
| 646 | 653 | early_param("l1d_flush", l1d_flush_parse_cmdline); |
| 647 | 654 | |
| 655 | +#undef pr_fmt | |
| 656 | +#define pr_fmt(fmt) "GDS: " fmt | |
| 657 | + | |
| 658 | +enum gds_mitigations { | |
| 659 | + GDS_MITIGATION_OFF, | |
| 660 | + GDS_MITIGATION_UCODE_NEEDED, | |
| 661 | + GDS_MITIGATION_FORCE, | |
| 662 | + GDS_MITIGATION_FULL, | |
| 663 | + GDS_MITIGATION_FULL_LOCKED, | |
| 664 | + GDS_MITIGATION_HYPERVISOR, | |
| 665 | +}; | |
| 666 | + | |
| 667 | +#if IS_ENABLED(CONFIG_GDS_FORCE_MITIGATION) | |
| 668 | +static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FORCE; | |
| 669 | +#else | |
| 670 | +static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FULL; | |
| 671 | +#endif | |
| 672 | + | |
| 673 | +static const char * const gds_strings[] = { | |
| 674 | + [GDS_MITIGATION_OFF] = "Vulnerable", | |
| 675 | + [GDS_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode", | |
| 676 | + [GDS_MITIGATION_FORCE] = "Mitigation: AVX disabled, no microcode", | |
| 677 | + [GDS_MITIGATION_FULL] = "Mitigation: Microcode", | |
| 678 | + [GDS_MITIGATION_FULL_LOCKED] = "Mitigation: Microcode (locked)", | |
| 679 | + [GDS_MITIGATION_HYPERVISOR] = "Unknown: Dependent on hypervisor status", | |
| 680 | +}; | |
| 681 | + | |
| 682 | +bool gds_ucode_mitigated(void) | |
| 683 | +{ | |
| 684 | + return (gds_mitigation == GDS_MITIGATION_FULL || | |
| 685 | + gds_mitigation == GDS_MITIGATION_FULL_LOCKED); | |
| 686 | +} | |
| 687 | +EXPORT_SYMBOL_GPL(gds_ucode_mitigated); | |
| 688 | + | |
| 689 | +void update_gds_msr(void) | |
| 690 | +{ | |
| 691 | + u64 mcu_ctrl_after; | |
| 692 | + u64 mcu_ctrl; | |
| 693 | + | |
| 694 | + switch (gds_mitigation) { | |
| 695 | + case GDS_MITIGATION_OFF: | |
| 696 | + rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl); | |
| 697 | + mcu_ctrl |= GDS_MITG_DIS; | |
| 698 | + break; | |
| 699 | + case GDS_MITIGATION_FULL_LOCKED: | |
| 700 | + /* | |
| 701 | + * The LOCKED state comes from the boot CPU. APs might not have | |
| 702 | + * the same state. Make sure the mitigation is enabled on all | |
| 703 | + * CPUs. | |
| 704 | + */ | |
| 705 | + case GDS_MITIGATION_FULL: | |
| 706 | + rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl); | |
| 707 | + mcu_ctrl &= ~GDS_MITG_DIS; | |
| 708 | + break; | |
| 709 | + case GDS_MITIGATION_FORCE: | |
| 710 | + case GDS_MITIGATION_UCODE_NEEDED: | |
| 711 | + case GDS_MITIGATION_HYPERVISOR: | |
| 712 | + return; | |
| 713 | + }; | |
| 714 | + | |
| 715 | + wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl); | |
| 716 | + | |
| 717 | + /* | |
| 718 | + * Check to make sure that the WRMSR value was not ignored. Writes to | |
| 719 | + * GDS_MITG_DIS will be ignored if this processor is locked but the boot | |
| 720 | + * processor was not. | |
| 721 | + */ | |
| 722 | + rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl_after); | |
| 723 | + WARN_ON_ONCE(mcu_ctrl != mcu_ctrl_after); | |
| 724 | +} | |
| 725 | + | |
| 726 | +static void __init gds_select_mitigation(void) | |
| 727 | +{ | |
| 728 | + u64 mcu_ctrl; | |
| 729 | + | |
| 730 | + if (!boot_cpu_has_bug(X86_BUG_GDS)) | |
| 731 | + return; | |
| 732 | + | |
| 733 | + if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) { | |
| 734 | + gds_mitigation = GDS_MITIGATION_HYPERVISOR; | |
| 735 | + goto out; | |
| 736 | + } | |
| 737 | + | |
| 738 | + if (cpu_mitigations_off()) | |
| 739 | + gds_mitigation = GDS_MITIGATION_OFF; | |
| 740 | + /* Will verify below that mitigation _can_ be disabled */ | |
| 741 | + | |
| 742 | + /* No microcode */ | |
| 743 | + if (!(x86_read_arch_cap_msr() & ARCH_CAP_GDS_CTRL)) { | |
| 744 | + if (gds_mitigation == GDS_MITIGATION_FORCE) { | |
| 745 | + /* | |
| 746 | + * This only needs to be done on the boot CPU so do it | |
| 747 | + * here rather than in update_gds_msr() | |
| 748 | + */ | |
| 749 | + setup_clear_cpu_cap(X86_FEATURE_AVX); | |
| 750 | + pr_warn("Microcode update needed! Disabling AVX as mitigation.\n"); | |
| 751 | + } else { | |
| 752 | + gds_mitigation = GDS_MITIGATION_UCODE_NEEDED; | |
| 753 | + } | |
| 754 | + goto out; | |
| 755 | + } | |
| 756 | + | |
| 757 | + /* Microcode has mitigation, use it */ | |
| 758 | + if (gds_mitigation == GDS_MITIGATION_FORCE) | |
| 759 | + gds_mitigation = GDS_MITIGATION_FULL; | |
| 760 | + | |
| 761 | + rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl); | |
| 762 | + if (mcu_ctrl & GDS_MITG_LOCKED) { | |
| 763 | + if (gds_mitigation == GDS_MITIGATION_OFF) | |
| 764 | + pr_warn("Mitigation locked. Disable failed.\n"); | |
| 765 | + | |
| 766 | + /* | |
| 767 | + * The mitigation is selected from the boot CPU. All other CPUs | |
| 768 | + * _should_ have the same state. If the boot CPU isn't locked | |
| 769 | + * but others are then update_gds_msr() will WARN() of the state | |
| 770 | + * mismatch. If the boot CPU is locked update_gds_msr() will | |
| 771 | + * ensure the other CPUs have the mitigation enabled. | |
| 772 | + */ | |
| 773 | + gds_mitigation = GDS_MITIGATION_FULL_LOCKED; | |
| 774 | + } | |
| 775 | + | |
| 776 | + update_gds_msr(); | |
| 777 | +out: | |
| 778 | + pr_info("%s\n", gds_strings[gds_mitigation]); | |
| 779 | +} | |
| 780 | + | |
| 781 | +static int __init gds_parse_cmdline(char *str) | |
| 782 | +{ | |
| 783 | + if (!str) | |
| 784 | + return -EINVAL; | |
| 785 | + | |
| 786 | + if (!boot_cpu_has_bug(X86_BUG_GDS)) | |
| 787 | + return 0; | |
| 788 | + | |
| 789 | + if (!strcmp(str, "off")) | |
| 790 | + gds_mitigation = GDS_MITIGATION_OFF; | |
| 791 | + else if (!strcmp(str, "force")) | |
| 792 | + gds_mitigation = GDS_MITIGATION_FORCE; | |
| 793 | + | |
| 794 | + return 0; | |
| 795 | +} | |
| 796 | +early_param("gather_data_sampling", gds_parse_cmdline); | |
| 797 | + | |
| 648 | 798 | #undef pr_fmt |
| 649 | 799 | #define pr_fmt(fmt) "Spectre V1 : " fmt |
| 650 | 800 | |
| @@ -2187,6 +2337,165 @@ static int __init l1tf_cmdline(char *str) · 1536 unmodified lines | ||
| 2187 | 2337 | } |
| 2188 | 2338 | early_param("l1tf", l1tf_cmdline); |
| 2189 | 2339 | |
| 2340 | +#undef pr_fmt | |
| 2341 | +#define pr_fmt(fmt) "Speculative Return Stack Overflow: " fmt | |
| 2342 | + | |
| 2343 | +enum srso_mitigation { | |
| 2344 | + SRSO_MITIGATION_NONE, | |
| 2345 | + SRSO_MITIGATION_MICROCODE, | |
| 2346 | + SRSO_MITIGATION_SAFE_RET, | |
| 2347 | + SRSO_MITIGATION_IBPB, | |
| 2348 | + SRSO_MITIGATION_IBPB_ON_VMEXIT, | |
| 2349 | +}; | |
| 2350 | + | |
| 2351 | +enum srso_mitigation_cmd { | |
| 2352 | + SRSO_CMD_OFF, | |
| 2353 | + SRSO_CMD_MICROCODE, | |
| 2354 | + SRSO_CMD_SAFE_RET, | |
| 2355 | + SRSO_CMD_IBPB, | |
| 2356 | + SRSO_CMD_IBPB_ON_VMEXIT, | |
| 2357 | +}; | |
| 2358 | + | |
| 2359 | +static const char * const srso_strings[] = { | |
| 2360 | + [SRSO_MITIGATION_NONE] = "Vulnerable", | |
| 2361 | + [SRSO_MITIGATION_MICROCODE] = "Mitigation: microcode", | |
| 2362 | + [SRSO_MITIGATION_SAFE_RET] = "Mitigation: safe RET", | |
| 2363 | + [SRSO_MITIGATION_IBPB] = "Mitigation: IBPB", | |
| 2364 | + [SRSO_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT only" | |
| 2365 | +}; | |
| 2366 | + | |
| 2367 | +static enum srso_mitigation srso_mitigation __ro_after_init = SRSO_MITIGATION_NONE; | |
| 2368 | +static enum srso_mitigation_cmd srso_cmd __ro_after_init = SRSO_CMD_SAFE_RET; | |
| 2369 | + | |
| 2370 | +static int __init srso_parse_cmdline(char *str) | |
| 2371 | +{ | |
| 2372 | + if (!str) | |
| 2373 | + return -EINVAL; | |
| 2374 | + | |
| 2375 | + if (!strcmp(str, "off")) | |
| 2376 | + srso_cmd = SRSO_CMD_OFF; | |
| 2377 | + else if (!strcmp(str, "microcode")) | |
| 2378 | + srso_cmd = SRSO_CMD_MICROCODE; | |
| 2379 | + else if (!strcmp(str, "safe-ret")) | |
| 2380 | + srso_cmd = SRSO_CMD_SAFE_RET; | |
| 2381 | + else if (!strcmp(str, "ibpb")) | |
| 2382 | + srso_cmd = SRSO_CMD_IBPB; | |
| 2383 | + else if (!strcmp(str, "ibpb-vmexit")) | |
| 2384 | + srso_cmd = SRSO_CMD_IBPB_ON_VMEXIT; | |
| 2385 | + else | |
| 2386 | + pr_err("Ignoring unknown SRSO option (%s).", str); | |
| 2387 | + | |
| 2388 | + return 0; | |
| 2389 | +} | |
| 2390 | +early_param("spec_rstack_overflow", srso_parse_cmdline); | |
| 2391 | + | |
| 2392 | +#define SRSO_NOTICE "WARNING: See https://kernel.org/doc/html/latest/admin-guide/hw-vuln/srso.html for mitigation options." | |
| 2393 | + | |
| 2394 | +static void __init srso_select_mitigation(void) | |
| 2395 | +{ | |
| 2396 | + bool has_microcode; | |
| 2397 | + | |
| 2398 | + if (!boot_cpu_has_bug(X86_BUG_SRSO) || cpu_mitigations_off()) | |
| 2399 | + goto pred_cmd; | |
| 2400 | + | |
| 2401 | + /* | |
| 2402 | + * The first check is for the kernel running as a guest in order | |
| 2403 | + * for guests to verify whether IBPB is a viable mitigation. | |
| 2404 | + */ | |
| 2405 | + has_microcode = boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) || cpu_has_ibpb_brtype_microcode(); | |
| 2406 | + if (!has_microcode) { | |
| 2407 | + pr_warn("IBPB-extending microcode not applied!\n"); | |
| 2408 | + pr_warn(SRSO_NOTICE); | |
| 2409 | + } else { | |
| 2410 | + /* | |
| 2411 | + * Enable the synthetic (even if in a real CPUID leaf) | |
| 2412 | + * flags for guests. | |
| 2413 | + */ | |
| 2414 | + setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE); | |
| 2415 | + | |
| 2416 | + /* | |
| 2417 | + * Zen1/2 with SMT off aren't vulnerable after the right | |
| 2418 | + * IBPB microcode has been applied. | |
| 2419 | + */ | |
| 2420 | + if ((boot_cpu_data.x86 < 0x19) && | |
| 2421 | + (!cpu_smt_possible() || (cpu_smt_control == CPU_SMT_DISABLED))) | |
| 2422 | + setup_force_cpu_cap(X86_FEATURE_SRSO_NO); | |
| 2423 | + } | |
| 2424 | + | |
| 2425 | + if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB) { | |
| 2426 | + if (has_microcode) { | |
| 2427 | + pr_err("Retbleed IBPB mitigation enabled, using same for SRSO\n"); | |
| 2428 | + srso_mitigation = SRSO_MITIGATION_IBPB; | |
| 2429 | + goto pred_cmd; | |
| 2430 | + } | |
| 2431 | + } | |
| 2432 | + | |
| 2433 | + switch (srso_cmd) { | |
| 2434 | + case SRSO_CMD_OFF: | |
| 2435 | + return; | |
| 2436 | + | |
| 2437 | + case SRSO_CMD_MICROCODE: | |
| 2438 | + if (has_microcode) { | |
| 2439 | + srso_mitigation = SRSO_MITIGATION_MICROCODE; | |
| 2440 | + pr_warn(SRSO_NOTICE); | |
| 2441 | + } | |
| 2442 | + break; | |
| 2443 | + | |
| 2444 | + case SRSO_CMD_SAFE_RET: | |
| 2445 | + if (IS_ENABLED(CONFIG_CPU_SRSO)) { | |
| 2446 | + /* | |
| 2447 | + * Enable the return thunk for generated code | |
| 2448 | + * like ftrace, static_call, etc. | |
| 2449 | + */ | |
| 2450 | + setup_force_cpu_cap(X86_FEATURE_RETHUNK); | |
| 2451 | + | |
| 2452 | + if (boot_cpu_data.x86 == 0x19) | |
| 2453 | + setup_force_cpu_cap(X86_FEATURE_SRSO_ALIAS); | |
| 2454 | + else | |
| 2455 | + setup_force_cpu_cap(X86_FEATURE_SRSO); | |
| 2456 | + srso_mitigation = SRSO_MITIGATION_SAFE_RET; | |
| 2457 | + } else { | |
| 2458 | + pr_err("WARNING: kernel not compiled with CPU_SRSO.\n"); | |
| 2459 | + goto pred_cmd; | |
| 2460 | + } | |
| 2461 | + break; | |
| 2462 | + | |
| 2463 | + case SRSO_CMD_IBPB: | |
| 2464 | + if (IS_ENABLED(CONFIG_CPU_IBPB_ENTRY)) { | |
| 2465 | + if (has_microcode) { | |
| 2466 | + setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB); | |
| 2467 | + srso_mitigation = SRSO_MITIGATION_IBPB; | |
| 2468 | + } | |
| 2469 | + } else { | |
| 2470 | + pr_err("WARNING: kernel not compiled with CPU_IBPB_ENTRY.\n"); | |
| 2471 | + goto pred_cmd; | |
| 2472 | + } | |
| 2473 | + break; | |
| 2474 | + | |
| 2475 | + case SRSO_CMD_IBPB_ON_VMEXIT: | |
| 2476 | + if (IS_ENABLED(CONFIG_CPU_SRSO)) { | |
| 2477 | + if (!boot_cpu_has(X86_FEATURE_ENTRY_IBPB) && has_microcode) { | |
| 2478 | + setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT); | |
| 2479 | + srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT; | |
| 2480 | + } | |
| 2481 | + } else { | |
| 2482 | + pr_err("WARNING: kernel not compiled with CPU_SRSO.\n"); | |
| 2483 | + goto pred_cmd; | |
| 2484 | + } | |
| 2485 | + break; | |
| 2486 | + | |
| 2487 | + default: | |
| 2488 | + break; | |
| 2489 | + } | |
| 2490 | + | |
| 2491 | + pr_info("%s%s\n", srso_strings[srso_mitigation], (has_microcode ? "" : ", no microcode")); | |
| 2492 | + | |
| 2493 | +pred_cmd: | |
| 2494 | + if ((boot_cpu_has(X86_FEATURE_SRSO_NO) || srso_cmd == SRSO_CMD_OFF) && | |
| 2495 | + boot_cpu_has(X86_FEATURE_SBPB)) | |
| 2496 | + x86_pred_cmd = PRED_CMD_SBPB; | |
| 2497 | +} | |
| 2498 | + | |
| 2190 | 2499 | #undef pr_fmt |
| 2191 | 2500 | #define pr_fmt(fmt) fmt |
| 2192 | 2501 | |
| @@ -2385,6 +2694,18 @@ static ssize_t retbleed_show_state(char *buf) · 192 unmodified lines | ||
| 2385 | 2694 | return sysfs_emit(buf, "%s\n", retbleed_strings[retbleed_mitigation]); |
| 2386 | 2695 | } |
| 2387 | 2696 | |
| 2697 | +static ssize_t srso_show_state(char *buf) | |
| 2698 | +{ | |
| 2699 | + return sysfs_emit(buf, "%s%s\n", | |
| 2700 | + srso_strings[srso_mitigation], | |
| 2701 | + (cpu_has_ibpb_brtype_microcode() ? "" : ", no microcode")); | |
| 2702 | +} | |
| 2703 | + | |
| 2704 | +static ssize_t gds_show_state(char *buf) | |
| 2705 | +{ | |
| 2706 | + return sysfs_emit(buf, "%s\n", gds_strings[gds_mitigation]); | |
| 2707 | +} | |
| 2708 | + | |
| 2388 | 2709 | static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, |
| 2389 | 2710 | char *buf, unsigned int bug) |
| 2390 | 2711 | { |
| @@ -2434,6 +2755,12 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr · 43 unmodified lines | ||
| 2434 | 2755 | case X86_BUG_RETBLEED: |
| 2435 | 2756 | return retbleed_show_state(buf); |
| 2436 | 2757 | |
| 2758 | + case X86_BUG_SRSO: | |
| 2759 | + return srso_show_state(buf); | |
| 2760 | + | |
| 2761 | + case X86_BUG_GDS: | |
| 2762 | + return gds_show_state(buf); | |
| 2763 | + | |
| 2437 | 2764 | default: |
| 2438 | 2765 | break; |
| 2439 | 2766 | } |
| @@ -2498,4 +2825,14 @@ ssize_t cpu_show_retbleed(struct device *dev, struct device_attribute *attr, cha · 58 unmodified lines | ||
| 2498 | 2825 | { |
| 2499 | 2826 | return cpu_show_common(dev, attr, buf, X86_BUG_RETBLEED); |
| 2500 | 2827 | } |
| 2828 | + | |
| 2829 | +ssize_t cpu_show_spec_rstack_overflow(struct device *dev, struct device_attribute *attr, char *buf) | |
| 2830 | +{ | |
| 2831 | + return cpu_show_common(dev, attr, buf, X86_BUG_SRSO); | |
| 2832 | +} | |
| 2833 | + | |
| 2834 | +ssize_t cpu_show_gds(struct device *dev, struct device_attribute *attr, char *buf) | |
| 2835 | +{ | |
| 2836 | + return cpu_show_common(dev, attr, buf, X86_BUG_GDS); | |
| 2837 | +} | |
| 2501 | 2838 | #endif |
| @@ -1250,6 +1250,10 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { · 1249 unmodified lines | ||
| 1250 | 1250 | #define RETBLEED BIT(3) |
| 1251 | 1251 | /* CPU is affected by SMT (cross-thread) return predictions */ |
| 1252 | 1252 | #define SMT_RSB BIT(4) |
| 1253 | +/* CPU is affected by SRSO */ | |
| 1254 | +#define SRSO BIT(5) | |
| 1255 | +/* CPU is affected by GDS */ | |
| 1256 | +#define GDS BIT(6) | |
| 1253 | 1257 | |
| 1254 | 1258 | static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { |
| 1255 | 1259 | VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS), |
| @@ -1262,27 +1266,30 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { · 6 unmodified lines | ||
| 1262 | 1266 | VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO), |
| 1263 | 1267 | VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS), |
| 1264 | 1268 | VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED), |
| 1265 | − VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPING_ANY, MMIO | RETBLEED), | |
| 1269 | + VULNBL_INTEL_STEPPINGS(SKYLAKE_X, X86_STEPPING_ANY, MMIO | RETBLEED | GDS), | |
| 1266 | 1270 | VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED), |
| 1267 | − VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED), | |
| 1268 | − VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED), | |
| 1271 | + VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED | GDS), | |
| 1272 | + VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED | GDS), | |
| 1269 | 1273 | VULNBL_INTEL_STEPPINGS(CANNONLAKE_L, X86_STEPPING_ANY, RETBLEED), |
| 1270 | − VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED), | |
| 1271 | − VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO), | |
| 1272 | − VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO), | |
| 1273 | − VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED), | |
| 1274 | + VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS), | |
| 1275 | + VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO | GDS), | |
| 1276 | + VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO | GDS), | |
| 1277 | + VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS), | |
| 1274 | 1278 | VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED), |
| 1275 | − VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED), | |
| 1279 | + VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS), | |
| 1280 | + VULNBL_INTEL_STEPPINGS(TIGERLAKE_L, X86_STEPPING_ANY, GDS), | |
| 1281 | + VULNBL_INTEL_STEPPINGS(TIGERLAKE, X86_STEPPING_ANY, GDS), | |
| 1276 | 1282 | VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED), |
| 1277 | − VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPING_ANY, MMIO | RETBLEED), | |
| 1283 | + VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS), | |
| 1278 | 1284 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPING_ANY, MMIO | MMIO_SBDS), |
| 1279 | 1285 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO), |
| 1280 | 1286 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS), |
| 1281 | 1287 | |
| 1282 | 1288 | VULNBL_AMD(0x15, RETBLEED), |
| 1283 | 1289 | VULNBL_AMD(0x16, RETBLEED), |
| 1284 | − VULNBL_AMD(0x17, RETBLEED | SMT_RSB), | |
| 1290 | + VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO), | |
| 1285 | 1291 | VULNBL_HYGON(0x18, RETBLEED | SMT_RSB), |
| 1292 | + VULNBL_AMD(0x19, SRSO), | |
| 1286 | 1293 | {} |
| 1287 | 1294 | }; |
| 1288 | 1295 | |
| @@ -1406,6 +1413,21 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) · 117 unmodified lines | ||
| 1406 | 1413 | if (cpu_matches(cpu_vuln_blacklist, SMT_RSB)) |
| 1407 | 1414 | setup_force_cpu_bug(X86_BUG_SMT_RSB); |
| 1408 | 1415 | |
| 1416 | + if (!cpu_has(c, X86_FEATURE_SRSO_NO)) { | |
| 1417 | + if (cpu_matches(cpu_vuln_blacklist, SRSO)) | |
| 1418 | + setup_force_cpu_bug(X86_BUG_SRSO); | |
| 1419 | + } | |
| 1420 | + | |
| 1421 | + /* | |
| 1422 | + * Check if CPU is vulnerable to GDS. If running in a virtual machine on | |
| 1423 | + * an affected processor, the VMM may have disabled the use of GATHER by | |
| 1424 | + * disabling AVX2. The only way to do this in HW is to clear XCR0[2], | |
| 1425 | + * which means that AVX will be disabled. | |
| 1426 | + */ | |
| 1427 | + if (cpu_matches(cpu_vuln_blacklist, GDS) && !(ia32_cap & ARCH_CAP_GDS_NO) && | |
| 1428 | + boot_cpu_has(X86_FEATURE_AVX)) | |
| 1429 | + setup_force_cpu_bug(X86_BUG_GDS); | |
| 1430 | + | |
| 1409 | 1431 | if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) |
| 1410 | 1432 | return; |
| 1411 | 1433 | |
| @@ -1962,6 +1984,8 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c) · 550 unmodified lines | ||
| 1962 | 1984 | validate_apic_and_package_id(c); |
| 1963 | 1985 | x86_spec_ctrl_setup_ap(); |
| 1964 | 1986 | update_srbds_msr(); |
| 1987 | + if (boot_cpu_has_bug(X86_BUG_GDS)) | |
| 1988 | + update_gds_msr(); | |
| 1965 | 1989 | |
| 1966 | 1990 | tsx_ap_init(); |
| 1967 | 1991 | } |
| @@ -83,6 +83,7 @@ void cpu_select_mitigations(void); · 82 unmodified lines | ||
| 83 | 83 | |
| 84 | 84 | extern void x86_spec_ctrl_setup_ap(void); |
| 85 | 85 | extern void update_srbds_msr(void); |
| 86 | +extern void update_gds_msr(void); | |
| 86 | 87 | |
| 87 | 88 | extern enum spectre_v2_mitigation spectre_v2_enabled; |
| 88 | 89 | |
| @@ -206,6 +206,8 @@ DEFINE_IDTENTRY(exc_divide_error) · 205 unmodified lines | ||
| 206 | 206 | { |
| 207 | 207 | do_error_trap(regs, 0, "divide error", X86_TRAP_DE, SIGFPE, |
| 208 | 208 | FPE_INTDIV, error_get_trap_addr(regs)); |
| 209 | + | |
| 210 | + amd_clear_divider(); | |
| 209 | 211 | } |
| 210 | 212 | |
| 211 | 213 | DEFINE_IDTENTRY(exc_overflow) |
| @@ -134,13 +134,27 @@ SECTIONS · 133 unmodified lines | ||
| 134 | 134 | SOFTIRQENTRY_TEXT |
| 135 | 135 | #ifdef CONFIG_RETPOLINE |
| 136 | 136 | __indirect_thunk_start = .; |
| 137 | − *(.text.__x86.*) | |
| 137 | + *(.text.__x86.indirect_thunk) | |
| 138 | + *(.text.__x86.return_thunk) | |
| 138 | 139 | __indirect_thunk_end = .; |
| 139 | 140 | #endif |
| 140 | 141 | STATIC_CALL_TEXT |
| 141 | 142 | |
| 142 | 143 | ALIGN_ENTRY_TEXT_BEGIN |
| 144 | +#ifdef CONFIG_CPU_SRSO | |
| 145 | + *(.text.__x86.rethunk_untrain) | |
| 146 | +#endif | |
| 147 | + | |
| 143 | 148 | ENTRY_TEXT |
| 149 | + | |
| 150 | +#ifdef CONFIG_CPU_SRSO | |
| 151 | + /* | |
| 152 | + * See the comment above srso_untrain_ret_alias()'s | |
| 153 | + * definition. | |
| 154 | + */ | |
| 155 | + . = srso_untrain_ret_alias | (1 << 2) | (1 << 8) | (1 << 14) | (1 << 20); | |
| 156 | + *(.text.__x86.rethunk_safe) | |
| 157 | +#endif | |
| 144 | 158 | ALIGN_ENTRY_TEXT_END |
| 145 | 159 | *(.gnu.warning) |
| 146 | 160 | |
| @@ -509,7 +523,24 @@ INIT_PER_CPU(irq_stack_backing_store); · 362 unmodified lines | ||
| 509 | 523 | #endif |
| 510 | 524 | |
| 511 | 525 | #ifdef CONFIG_RETHUNK |
| 512 | −. = ASSERT((__x86_return_thunk & 0x3f) == 0, "__x86_return_thunk not cacheline-aligned"); | |
| 526 | +. = ASSERT((__ret & 0x3f) == 0, "__ret not cacheline-aligned"); | |
| 527 | +. = ASSERT((srso_safe_ret & 0x3f) == 0, "srso_safe_ret not cacheline-aligned"); | |
| 528 | +#endif | |
| 529 | + | |
| 530 | +#ifdef CONFIG_CPU_SRSO | |
| 531 | +/* | |
| 532 | + * GNU ld cannot do XOR until 2.41. | |
| 533 | + * https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=f6f78318fca803c4907fb8d7f6ded8295f1947b1 | |
| 534 | + * | |
| 535 | + * LLVM lld cannot do XOR until lld-17. | |
| 536 | + * https://github.com/llvm/llvm-project/commit/fae96104d4378166cbe5c875ef8ed808a356f3fb | |
| 537 | + * | |
| 538 | + * Instead do: (A | B) - (A & B) in order to compute the XOR | |
| 539 | + * of the two function addresses: | |
| 540 | + */ | |
| 541 | +. = ASSERT(((ABSOLUTE(srso_untrain_ret_alias) | srso_safe_ret_alias) - | |
| 542 | + (ABSOLUTE(srso_untrain_ret_alias) & srso_safe_ret_alias)) == ((1 << 2) | (1 << 8) | (1 << 14) | (1 << 20)), | |
| 543 | + "SRSO function pair won't alias"); | |
| 513 | 544 | #endif |
| 514 | 545 | |
| 515 | 546 | #endif /* CONFIG_X86_64 */ |
| @@ -729,6 +729,9 @@ void kvm_set_cpu_caps(void) · 728 unmodified lines | ||
| 729 | 729 | F(NULL_SEL_CLR_BASE) | F(AUTOIBRS) | 0 /* PrefetchCtlMsr */ |
| 730 | 730 | ); |
| 731 | 731 | |
| 732 | + if (cpu_feature_enabled(X86_FEATURE_SRSO_NO)) | |
| 733 | + kvm_cpu_cap_set(X86_FEATURE_SRSO_NO); | |
| 734 | + | |
| 732 | 735 | kvm_cpu_cap_init_kvm_defined(CPUID_8000_0022_EAX, |
| 733 | 736 | F(PERFMON_V2) |
| 734 | 737 | ); |
| @@ -2417,15 +2417,18 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm) · 2416 unmodified lines | ||
| 2417 | 2417 | */ |
| 2418 | 2418 | memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs)); |
| 2419 | 2419 | |
| 2420 | − vcpu->arch.regs[VCPU_REGS_RAX] = ghcb_get_rax_if_valid(ghcb); | |
| 2421 | − vcpu->arch.regs[VCPU_REGS_RBX] = ghcb_get_rbx_if_valid(ghcb); | |
| 2422 | − vcpu->arch.regs[VCPU_REGS_RCX] = ghcb_get_rcx_if_valid(ghcb); | |
| 2423 | − vcpu->arch.regs[VCPU_REGS_RDX] = ghcb_get_rdx_if_valid(ghcb); | |
| 2424 | − vcpu->arch.regs[VCPU_REGS_RSI] = ghcb_get_rsi_if_valid(ghcb); | |
| 2420 | + BUILD_BUG_ON(sizeof(svm->sev_es.valid_bitmap) != sizeof(ghcb->save.valid_bitmap)); | |
| 2421 | + memcpy(&svm->sev_es.valid_bitmap, &ghcb->save.valid_bitmap, sizeof(ghcb->save.valid_bitmap)); | |
| 2425 | 2422 | |
| 2426 | − svm->vmcb->save.cpl = ghcb_get_cpl_if_valid(ghcb); | |
| 2423 | + vcpu->arch.regs[VCPU_REGS_RAX] = kvm_ghcb_get_rax_if_valid(svm, ghcb); | |
| 2424 | + vcpu->arch.regs[VCPU_REGS_RBX] = kvm_ghcb_get_rbx_if_valid(svm, ghcb); | |
| 2425 | + vcpu->arch.regs[VCPU_REGS_RCX] = kvm_ghcb_get_rcx_if_valid(svm, ghcb); | |
| 2426 | + vcpu->arch.regs[VCPU_REGS_RDX] = kvm_ghcb_get_rdx_if_valid(svm, ghcb); | |
| 2427 | + vcpu->arch.regs[VCPU_REGS_RSI] = kvm_ghcb_get_rsi_if_valid(svm, ghcb); | |
| 2427 | 2428 | |
| 2428 | − if (ghcb_xcr0_is_valid(ghcb)) { | |
| 2429 | + svm->vmcb->save.cpl = kvm_ghcb_get_cpl_if_valid(svm, ghcb); | |
| 2430 | + | |
| 2431 | + if (kvm_ghcb_xcr0_is_valid(svm)) { | |
| 2429 | 2432 | vcpu->arch.xcr0 = ghcb_get_xcr0(ghcb); |
| 2430 | 2433 | kvm_update_cpuid_runtime(vcpu); |
| 2431 | 2434 | } |
| @@ -2436,84 +2439,88 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm) · 4 unmodified lines | ||
| 2436 | 2439 | control->exit_code_hi = upper_32_bits(exit_code); |
| 2437 | 2440 | control->exit_info_1 = ghcb_get_sw_exit_info_1(ghcb); |
| 2438 | 2441 | control->exit_info_2 = ghcb_get_sw_exit_info_2(ghcb); |
| 2442 | + svm->sev_es.sw_scratch = kvm_ghcb_get_sw_scratch_if_valid(svm, ghcb); | |
| 2439 | 2443 | |
| 2440 | 2444 | /* Clear the valid entries fields */ |
| 2441 | 2445 | memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap)); |
| 2442 | 2446 | } |
| 2443 | 2447 | |
| 2448 | +static u64 kvm_ghcb_get_sw_exit_code(struct vmcb_control_area *control) | |
| 2449 | +{ | |
| 2450 | + return (((u64)control->exit_code_hi) << 32) | control->exit_code; | |
| 2451 | +} | |
| 2452 | + | |
| 2444 | 2453 | static int sev_es_validate_vmgexit(struct vcpu_svm *svm) |
| 2445 | 2454 | { |
| 2446 | − struct kvm_vcpu *vcpu; | |
| 2447 | − struct ghcb *ghcb; | |
| 2455 | + struct vmcb_control_area *control = &svm->vmcb->control; | |
| 2456 | + struct kvm_vcpu *vcpu = &svm->vcpu; | |
| 2448 | 2457 | u64 exit_code; |
| 2449 | 2458 | u64 reason; |
| 2450 | 2459 | |
| 2451 | − ghcb = svm->sev_es.ghcb; | |
| 2452 | − | |
| 2453 | 2460 | /* |
| 2454 | 2461 | * Retrieve the exit code now even though it may not be marked valid |
| 2455 | 2462 | * as it could help with debugging. |
| 2456 | 2463 | */ |
| 2457 | − exit_code = ghcb_get_sw_exit_code(ghcb); | |
| 2464 | + exit_code = kvm_ghcb_get_sw_exit_code(control); | |
| 2458 | 2465 | |
| 2459 | 2466 | /* Only GHCB Usage code 0 is supported */ |
| 2460 | − if (ghcb->ghcb_usage) { | |
| 2467 | + if (svm->sev_es.ghcb->ghcb_usage) { | |
| 2461 | 2468 | reason = GHCB_ERR_INVALID_USAGE; |
| 2462 | 2469 | goto vmgexit_err; |
| 2463 | 2470 | } |
| 2464 | 2471 | |
| 2465 | 2472 | reason = GHCB_ERR_MISSING_INPUT; |
| 2466 | 2473 | |
| 2467 | − if (!ghcb_sw_exit_code_is_valid(ghcb) || | |
| 2468 | − !ghcb_sw_exit_info_1_is_valid(ghcb) || | |
| 2469 | − !ghcb_sw_exit_info_2_is_valid(ghcb)) | |
| 2474 | + if (!kvm_ghcb_sw_exit_code_is_valid(svm) || | |
| 2475 | + !kvm_ghcb_sw_exit_info_1_is_valid(svm) || | |
| 2476 | + !kvm_ghcb_sw_exit_info_2_is_valid(svm)) | |
| 2470 | 2477 | goto vmgexit_err; |
| 2471 | 2478 | |
| 2472 | − switch (ghcb_get_sw_exit_code(ghcb)) { | |
| 2479 | + switch (exit_code) { | |
| 2473 | 2480 | case SVM_EXIT_READ_DR7: |
| 2474 | 2481 | break; |
| 2475 | 2482 | case SVM_EXIT_WRITE_DR7: |
| 2476 | − if (!ghcb_rax_is_valid(ghcb)) | |
| 2483 | + if (!kvm_ghcb_rax_is_valid(svm)) | |
| 2477 | 2484 | goto vmgexit_err; |
| 2478 | 2485 | break; |
| 2479 | 2486 | case SVM_EXIT_RDTSC: |
| 2480 | 2487 | break; |
| 2481 | 2488 | case SVM_EXIT_RDPMC: |
| 2482 | − if (!ghcb_rcx_is_valid(ghcb)) | |
| 2489 | + if (!kvm_ghcb_rcx_is_valid(svm)) | |
| 2483 | 2490 | goto vmgexit_err; |
| 2484 | 2491 | break; |
| 2485 | 2492 | case SVM_EXIT_CPUID: |
| 2486 | − if (!ghcb_rax_is_valid(ghcb) || | |
| 2487 | − !ghcb_rcx_is_valid(ghcb)) | |
| 2493 | + if (!kvm_ghcb_rax_is_valid(svm) || | |
| 2494 | + !kvm_ghcb_rcx_is_valid(svm)) | |
| 2488 | 2495 | goto vmgexit_err; |
| 2489 | − if (ghcb_get_rax(ghcb) == 0xd) | |
| 2490 | − if (!ghcb_xcr0_is_valid(ghcb)) | |
| 2496 | + if (vcpu->arch.regs[VCPU_REGS_RAX] == 0xd) | |
| 2497 | + if (!kvm_ghcb_xcr0_is_valid(svm)) | |
| 2491 | 2498 | goto vmgexit_err; |
| 2492 | 2499 | break; |
| 2493 | 2500 | case SVM_EXIT_INVD: |
| 2494 | 2501 | break; |
| 2495 | 2502 | case SVM_EXIT_IOIO: |
| 2496 | − if (ghcb_get_sw_exit_info_1(ghcb) & SVM_IOIO_STR_MASK) { | |
| 2497 | − if (!ghcb_sw_scratch_is_valid(ghcb)) | |
| 2503 | + if (control->exit_info_1 & SVM_IOIO_STR_MASK) { | |
| 2504 | + if (!kvm_ghcb_sw_scratch_is_valid(svm)) | |
| 2498 | 2505 | goto vmgexit_err; |
| 2499 | 2506 | } else { |
| 2500 | − if (!(ghcb_get_sw_exit_info_1(ghcb) & SVM_IOIO_TYPE_MASK)) | |
| 2501 | − if (!ghcb_rax_is_valid(ghcb)) | |
| 2507 | + if (!(control->exit_info_1 & SVM_IOIO_TYPE_MASK)) | |
| 2508 | + if (!kvm_ghcb_rax_is_valid(svm)) | |
| 2502 | 2509 | goto vmgexit_err; |
| 2503 | 2510 | } |
| 2504 | 2511 | break; |
| 2505 | 2512 | case SVM_EXIT_MSR: |
| 2506 | − if (!ghcb_rcx_is_valid(ghcb)) | |
| 2513 | + if (!kvm_ghcb_rcx_is_valid(svm)) | |
| 2507 | 2514 | goto vmgexit_err; |
| 2508 | − if (ghcb_get_sw_exit_info_1(ghcb)) { | |
| 2509 | − if (!ghcb_rax_is_valid(ghcb) || | |
| 2510 | − !ghcb_rdx_is_valid(ghcb)) | |
| 2515 | + if (control->exit_info_1) { | |
| 2516 | + if (!kvm_ghcb_rax_is_valid(svm) || | |
| 2517 | + !kvm_ghcb_rdx_is_valid(svm)) | |
| 2511 | 2518 | goto vmgexit_err; |
| 2512 | 2519 | } |
| 2513 | 2520 | break; |
| 2514 | 2521 | case SVM_EXIT_VMMCALL: |
| 2515 | − if (!ghcb_rax_is_valid(ghcb) || | |
| 2516 | − !ghcb_cpl_is_valid(ghcb)) | |
| 2522 | + if (!kvm_ghcb_rax_is_valid(svm) || | |
| 2523 | + !kvm_ghcb_cpl_is_valid(svm)) | |
| 2517 | 2524 | goto vmgexit_err; |
| 2518 | 2525 | break; |
| 2519 | 2526 | case SVM_EXIT_RDTSCP: |
| @@ -2521,19 +2528,19 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) · 1 unmodified line | ||
| 2521 | 2528 | case SVM_EXIT_WBINVD: |
| 2522 | 2529 | break; |
| 2523 | 2530 | case SVM_EXIT_MONITOR: |
| 2524 | − if (!ghcb_rax_is_valid(ghcb) || | |
| 2525 | − !ghcb_rcx_is_valid(ghcb) || | |
| 2526 | − !ghcb_rdx_is_valid(ghcb)) | |
| 2531 | + if (!kvm_ghcb_rax_is_valid(svm) || | |
| 2532 | + !kvm_ghcb_rcx_is_valid(svm) || | |
| 2533 | + !kvm_ghcb_rdx_is_valid(svm)) | |
| 2527 | 2534 | goto vmgexit_err; |
| 2528 | 2535 | break; |
| 2529 | 2536 | case SVM_EXIT_MWAIT: |
| 2530 | − if (!ghcb_rax_is_valid(ghcb) || | |
| 2531 | − !ghcb_rcx_is_valid(ghcb)) | |
| 2537 | + if (!kvm_ghcb_rax_is_valid(svm) || | |
| 2538 | + !kvm_ghcb_rcx_is_valid(svm)) | |
| 2532 | 2539 | goto vmgexit_err; |
| 2533 | 2540 | break; |
| 2534 | 2541 | case SVM_VMGEXIT_MMIO_READ: |
| 2535 | 2542 | case SVM_VMGEXIT_MMIO_WRITE: |
| 2536 | − if (!ghcb_sw_scratch_is_valid(ghcb)) | |
| 2543 | + if (!kvm_ghcb_sw_scratch_is_valid(svm)) | |
| 2537 | 2544 | goto vmgexit_err; |
| 2538 | 2545 | break; |
| 2539 | 2546 | case SVM_VMGEXIT_NMI_COMPLETE: |
| @@ -2549,11 +2556,9 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) · 9 unmodified lines | ||
| 2549 | 2556 | return 0; |
| 2550 | 2557 | |
| 2551 | 2558 | vmgexit_err: |
| 2552 | − vcpu = &svm->vcpu; | |
| 2553 | − | |
| 2554 | 2559 | if (reason == GHCB_ERR_INVALID_USAGE) { |
| 2555 | 2560 | vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n", |
| 2556 | − ghcb->ghcb_usage); | |
| 2561 | + svm->sev_es.ghcb->ghcb_usage); | |
| 2557 | 2562 | } else if (reason == GHCB_ERR_INVALID_EVENT) { |
| 2558 | 2563 | vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n", |
| 2559 | 2564 | exit_code); |
| @@ -2563,11 +2568,8 @@ vmgexit_err: · 3 unmodified lines | ||
| 2563 | 2568 | dump_ghcb(svm); |
| 2564 | 2569 | } |
| 2565 | 2570 | |
| 2566 | − /* Clear the valid entries fields */ | |
| 2567 | − memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap)); | |
| 2568 | − | |
| 2569 | − ghcb_set_sw_exit_info_1(ghcb, 2); | |
| 2570 | − ghcb_set_sw_exit_info_2(ghcb, reason); | |
| 2571 | + ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2); | |
| 2572 | + ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, reason); | |
| 2571 | 2573 | |
| 2572 | 2574 | /* Resume the guest to "return" the error code. */ |
| 2573 | 2575 | return 1; |
| @@ -2586,7 +2588,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm) · 12 unmodified lines | ||
| 2586 | 2588 | */ |
| 2587 | 2589 | if (svm->sev_es.ghcb_sa_sync) { |
| 2588 | 2590 | kvm_write_guest(svm->vcpu.kvm, |
| 2589 | − ghcb_get_sw_scratch(svm->sev_es.ghcb), | |
| 2591 | + svm->sev_es.sw_scratch, | |
| 2590 | 2592 | svm->sev_es.ghcb_sa, |
| 2591 | 2593 | svm->sev_es.ghcb_sa_len); |
| 2592 | 2594 | svm->sev_es.ghcb_sa_sync = false; |
| @@ -2632,12 +2634,11 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu) · 39 unmodified lines | ||
| 2632 | 2634 | static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) |
| 2633 | 2635 | { |
| 2634 | 2636 | struct vmcb_control_area *control = &svm->vmcb->control; |
| 2635 | − struct ghcb *ghcb = svm->sev_es.ghcb; | |
| 2636 | 2637 | u64 ghcb_scratch_beg, ghcb_scratch_end; |
| 2637 | 2638 | u64 scratch_gpa_beg, scratch_gpa_end; |
| 2638 | 2639 | void *scratch_va; |
| 2639 | 2640 | |
| 2640 | − scratch_gpa_beg = ghcb_get_sw_scratch(ghcb); | |
| 2641 | + scratch_gpa_beg = svm->sev_es.sw_scratch; | |
| 2641 | 2642 | if (!scratch_gpa_beg) { |
| 2642 | 2643 | pr_err("vmgexit: scratch gpa not provided\n"); |
| 2643 | 2644 | goto e_scratch; |
| @@ -2708,8 +2709,8 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) · 64 unmodified lines | ||
| 2708 | 2709 | return 0; |
| 2709 | 2710 | |
| 2710 | 2711 | e_scratch: |
| 2711 | − ghcb_set_sw_exit_info_1(ghcb, 2); | |
| 2712 | − ghcb_set_sw_exit_info_2(ghcb, GHCB_ERR_INVALID_SCRATCH_AREA); | |
| 2712 | + ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2); | |
| 2713 | + ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_SCRATCH_AREA); | |
| 2713 | 2714 | |
| 2714 | 2715 | return 1; |
| 2715 | 2716 | } |
| @@ -2822,7 +2823,6 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) · 106 unmodified lines | ||
| 2822 | 2823 | struct vcpu_svm *svm = to_svm(vcpu); |
| 2823 | 2824 | struct vmcb_control_area *control = &svm->vmcb->control; |
| 2824 | 2825 | u64 ghcb_gpa, exit_code; |
| 2825 | − struct ghcb *ghcb; | |
| 2826 | 2826 | int ret; |
| 2827 | 2827 | |
| 2828 | 2828 | /* Validate the GHCB */ |
| @@ -2847,20 +2847,18 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) · 18 unmodified lines | ||
| 2847 | 2847 | } |
| 2848 | 2848 | |
| 2849 | 2849 | svm->sev_es.ghcb = svm->sev_es.ghcb_map.hva; |
| 2850 | − ghcb = svm->sev_es.ghcb_map.hva; | |
| 2851 | 2850 | |
| 2852 | − trace_kvm_vmgexit_enter(vcpu->vcpu_id, ghcb); | |
| 2853 | − | |
| 2854 | − exit_code = ghcb_get_sw_exit_code(ghcb); | |
| 2851 | + trace_kvm_vmgexit_enter(vcpu->vcpu_id, svm->sev_es.ghcb); | |
| 2855 | 2852 | |
| 2853 | + sev_es_sync_from_ghcb(svm); | |
| 2856 | 2854 | ret = sev_es_validate_vmgexit(svm); |
| 2857 | 2855 | if (ret) |
| 2858 | 2856 | return ret; |
| 2859 | 2857 | |
| 2860 | − sev_es_sync_from_ghcb(svm); | |
| 2861 | − ghcb_set_sw_exit_info_1(ghcb, 0); | |
| 2862 | − ghcb_set_sw_exit_info_2(ghcb, 0); | |
| 2858 | + ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 0); | |
| 2859 | + ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, 0); | |
| 2863 | 2860 | |
| 2861 | + exit_code = kvm_ghcb_get_sw_exit_code(control); | |
| 2864 | 2862 | switch (exit_code) { |
| 2865 | 2863 | case SVM_VMGEXIT_MMIO_READ: |
| 2866 | 2864 | ret = setup_vmgexit_scratch(svm, true, control->exit_info_2); |
| @@ -2898,13 +2896,13 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) · 31 unmodified lines | ||
| 2898 | 2896 | break; |
| 2899 | 2897 | case 1: |
| 2900 | 2898 | /* Get AP jump table address */ |
| 2901 | − ghcb_set_sw_exit_info_2(ghcb, sev->ap_jump_table); | |
| 2899 | + ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, sev->ap_jump_table); | |
| 2902 | 2900 | break; |
| 2903 | 2901 | default: |
| 2904 | 2902 | pr_err("svm: vmgexit: unsupported AP jump table request - exit_info_1=%#llx\n", |
| 2905 | 2903 | control->exit_info_1); |
| 2906 | − ghcb_set_sw_exit_info_1(ghcb, 2); | |
| 2907 | − ghcb_set_sw_exit_info_2(ghcb, GHCB_ERR_INVALID_INPUT); | |
| 2904 | + ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2); | |
| 2905 | + ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT); | |
| 2908 | 2906 | } |
| 2909 | 2907 | |
| 2910 | 2908 | ret = 1; |
| @@ -1498,7 +1498,9 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) · 1497 unmodified lines | ||
| 1498 | 1498 | |
| 1499 | 1499 | if (sd->current_vmcb != svm->vmcb) { |
| 1500 | 1500 | sd->current_vmcb = svm->vmcb; |
| 1501 | − indirect_branch_prediction_barrier(); | |
| 1501 | + | |
| 1502 | + if (!cpu_feature_enabled(X86_FEATURE_IBPB_ON_VMEXIT)) | |
| 1503 | + indirect_branch_prediction_barrier(); | |
| 1502 | 1504 | } |
| 1503 | 1505 | if (kvm_vcpu_apicv_active(vcpu)) |
| 1504 | 1506 | avic_vcpu_load(vcpu, cpu); |
| @@ -190,10 +190,12 @@ struct vcpu_sev_es_state { · 189 unmodified lines | ||
| 190 | 190 | /* SEV-ES support */ |
| 191 | 191 | struct sev_es_save_area *vmsa; |
| 192 | 192 | struct ghcb *ghcb; |
| 193 | + u8 valid_bitmap[16]; | |
| 193 | 194 | struct kvm_host_map ghcb_map; |
| 194 | 195 | bool received_first_sipi; |
| 195 | 196 | |
| 196 | 197 | /* SEV-ES scratch area support */ |
| 198 | + u64 sw_scratch; | |
| 197 | 199 | void *ghcb_sa; |
| 198 | 200 | u32 ghcb_sa_len; |
| 199 | 201 | bool ghcb_sa_sync; |
| @@ -744,4 +746,28 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm); · 544 unmodified lines | ||
| 744 | 746 | void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted); |
| 745 | 747 | void __svm_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted); |
| 746 | 748 | |
| 749 | +#define DEFINE_KVM_GHCB_ACCESSORS(field) \ | |
| 750 | + static __always_inline bool kvm_ghcb_##field##_is_valid(const struct vcpu_svm *svm) \ | |
| 751 | + { \ | |
| 752 | + return test_bit(GHCB_BITMAP_IDX(field), \ | |
| 753 | + (unsigned long *)&svm->sev_es.valid_bitmap); \ | |
| 754 | + } \ | |
| 755 | + \ | |
| 756 | + static __always_inline u64 kvm_ghcb_get_##field##_if_valid(struct vcpu_svm *svm, struct ghcb *ghcb) \ | |
| 757 | + { \ | |
| 758 | + return kvm_ghcb_##field##_is_valid(svm) ? ghcb->save.field : 0; \ | |
| 759 | + } \ | |
| 760 | + | |
| 761 | +DEFINE_KVM_GHCB_ACCESSORS(cpl) | |
| 762 | +DEFINE_KVM_GHCB_ACCESSORS(rax) | |
| 763 | +DEFINE_KVM_GHCB_ACCESSORS(rcx) | |
| 764 | +DEFINE_KVM_GHCB_ACCESSORS(rdx) | |
| 765 | +DEFINE_KVM_GHCB_ACCESSORS(rbx) | |
| 766 | +DEFINE_KVM_GHCB_ACCESSORS(rsi) | |
| 767 | +DEFINE_KVM_GHCB_ACCESSORS(sw_exit_code) | |
| 768 | +DEFINE_KVM_GHCB_ACCESSORS(sw_exit_info_1) | |
| 769 | +DEFINE_KVM_GHCB_ACCESSORS(sw_exit_info_2) | |
| 770 | +DEFINE_KVM_GHCB_ACCESSORS(sw_scratch) | |
| 771 | +DEFINE_KVM_GHCB_ACCESSORS(xcr0) | |
| 772 | + | |
| 747 | 773 | #endif |
| @@ -224,6 +224,9 @@ SYM_FUNC_START(__svm_vcpu_run) · 223 unmodified lines | ||
| 224 | 224 | */ |
| 225 | 225 | UNTRAIN_RET |
| 226 | 226 | |
| 227 | + /* SRSO */ | |
| 228 | + ALTERNATIVE "", "call entry_ibpb", X86_FEATURE_IBPB_ON_VMEXIT | |
| 229 | + | |
| 227 | 230 | /* |
| 228 | 231 | * Clear all general purpose registers except RSP and RAX to prevent |
| 229 | 232 | * speculative use of the guest's values, even those that are reloaded |
| @@ -1616,7 +1616,7 @@ static bool kvm_is_immutable_feature_msr(u32 msr) · 1615 unmodified lines | ||
| 1616 | 1616 | ARCH_CAP_SKIP_VMENTRY_L1DFLUSH | ARCH_CAP_SSB_NO | ARCH_CAP_MDS_NO | \ |
| 1617 | 1617 | ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \ |
| 1618 | 1618 | ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \ |
| 1619 | − ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO) | |
| 1619 | + ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO) | |
| 1620 | 1620 | |
| 1621 | 1621 | static u64 kvm_get_arch_capabilities(void) |
| 1622 | 1622 | { |
| @@ -1673,6 +1673,9 @@ static u64 kvm_get_arch_capabilities(void) · 50 unmodified lines | ||
| 1673 | 1673 | */ |
| 1674 | 1674 | } |
| 1675 | 1675 | |
| 1676 | + if (!boot_cpu_has_bug(X86_BUG_GDS) || gds_ucode_mitigated()) | |
| 1677 | + data |= ARCH_CAP_GDS_NO; | |
| 1678 | + | |
| 1676 | 1679 | return data; |
| 1677 | 1680 | } |
| 1678 | 1681 | |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <asm/unwind_hints.h> |
| 12 | 12 | #include <asm/percpu.h> |
| 13 | 13 | #include <asm/frame.h> |
| 14 | +#include <asm/nops.h> | |
| 14 | 15 | |
| 15 | 16 | .section .text.__x86.indirect_thunk |
| 16 | 17 | |
| @@ -131,6 +132,46 @@ SYM_CODE_END(__x86_indirect_jump_thunk_array) · 114 unmodified lines | ||
| 131 | 132 | */ |
| 132 | 133 | #ifdef CONFIG_RETHUNK |
| 133 | 134 | |
| 135 | +/* | |
| 136 | + * srso_untrain_ret_alias() and srso_safe_ret_alias() are placed at | |
| 137 | + * special addresses: | |
| 138 | + * | |
| 139 | + * - srso_untrain_ret_alias() is 2M aligned | |
| 140 | + * - srso_safe_ret_alias() is also in the same 2M page but bits 2, 8, 14 | |
| 141 | + * and 20 in its virtual address are set (while those bits in the | |
| 142 | + * srso_untrain_ret_alias() function are cleared). | |
| 143 | + * | |
| 144 | + * This guarantees that those two addresses will alias in the branch | |
| 145 | + * target buffer of Zen3/4 generations, leading to any potential | |
| 146 | + * poisoned entries at that BTB slot to get evicted. | |
| 147 | + * | |
| 148 | + * As a result, srso_safe_ret_alias() becomes a safe return. | |
| 149 | + */ | |
| 150 | +#ifdef CONFIG_CPU_SRSO | |
| 151 | + .section .text.__x86.rethunk_untrain | |
| 152 | + | |
| 153 | +SYM_START(srso_untrain_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) | |
| 154 | + ANNOTATE_NOENDBR | |
| 155 | + ASM_NOP2 | |
| 156 | + lfence | |
| 157 | + jmp __x86_return_thunk | |
| 158 | +SYM_FUNC_END(srso_untrain_ret_alias) | |
| 159 | +__EXPORT_THUNK(srso_untrain_ret_alias) | |
| 160 | + | |
| 161 | + .section .text.__x86.rethunk_safe | |
| 162 | +#endif | |
| 163 | + | |
| 164 | +/* Needs a definition for the __x86_return_thunk alternative below. */ | |
| 165 | +SYM_START(srso_safe_ret_alias, SYM_L_GLOBAL, SYM_A_NONE) | |
| 166 | +#ifdef CONFIG_CPU_SRSO | |
| 167 | + add $8, %_ASM_SP | |
| 168 | + UNWIND_HINT_FUNC | |
| 169 | +#endif | |
| 170 | + ANNOTATE_UNRET_SAFE | |
| 171 | + ret | |
| 172 | + int3 | |
| 173 | +SYM_FUNC_END(srso_safe_ret_alias) | |
| 174 | + | |
| 134 | 175 | .section .text.__x86.return_thunk |
| 135 | 176 | |
| 136 | 177 | /* |
| @@ -143,7 +184,7 @@ SYM_CODE_END(__x86_indirect_jump_thunk_array) · 6 unmodified lines | ||
| 143 | 184 | * from re-poisioning the BTB prediction. |
| 144 | 185 | */ |
| 145 | 186 | .align 64 |
| 146 | − .skip 64 - (__x86_return_thunk - zen_untrain_ret), 0xcc | |
| 187 | + .skip 64 - (__ret - zen_untrain_ret), 0xcc | |
| 147 | 188 | SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) |
| 148 | 189 | ANNOTATE_NOENDBR |
| 149 | 190 | /* |
| @@ -175,10 +216,10 @@ SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) · 25 unmodified lines | ||
| 175 | 216 | * evicted, __x86_return_thunk will suffer Straight Line Speculation |
| 176 | 217 | * which will be contained safely by the INT3. |
| 177 | 218 | */ |
| 178 | −SYM_INNER_LABEL(__x86_return_thunk, SYM_L_GLOBAL) | |
| 219 | +SYM_INNER_LABEL(__ret, SYM_L_GLOBAL) | |
| 179 | 220 | ret |
| 180 | 221 | int3 |
| 181 | −SYM_CODE_END(__x86_return_thunk) | |
| 222 | +SYM_CODE_END(__ret) | |
| 182 | 223 | |
| 183 | 224 | /* |
| 184 | 225 | * Ensure the TEST decoding / BTB invalidation is complete. |
| @@ -189,11 +230,45 @@ SYM_CODE_END(__x86_return_thunk) · 4 unmodified lines | ||
| 189 | 230 | * Jump back and execute the RET in the middle of the TEST instruction. |
| 190 | 231 | * INT3 is for SLS protection. |
| 191 | 232 | */ |
| 192 | − jmp __x86_return_thunk | |
| 233 | + jmp __ret | |
| 193 | 234 | int3 |
| 194 | 235 | SYM_FUNC_END(zen_untrain_ret) |
| 195 | 236 | __EXPORT_THUNK(zen_untrain_ret) |
| 196 | 237 | |
| 238 | +/* | |
| 239 | + * SRSO untraining sequence for Zen1/2, similar to zen_untrain_ret() | |
| 240 | + * above. On kernel entry, srso_untrain_ret() is executed which is a | |
| 241 | + * | |
| 242 | + * movabs $0xccccccc308c48348,%rax | |
| 243 | + * | |
| 244 | + * and when the return thunk executes the inner label srso_safe_ret() | |
| 245 | + * later, it is a stack manipulation and a RET which is mispredicted and | |
| 246 | + * thus a "safe" one to use. | |
| 247 | + */ | |
| 248 | + .align 64 | |
| 249 | + .skip 64 - (srso_safe_ret - srso_untrain_ret), 0xcc | |
| 250 | +SYM_START(srso_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) | |
| 251 | + ANNOTATE_NOENDBR | |
| 252 | + .byte 0x48, 0xb8 | |
| 253 | + | |
| 254 | +SYM_INNER_LABEL(srso_safe_ret, SYM_L_GLOBAL) | |
| 255 | + add $8, %_ASM_SP | |
| 256 | + ret | |
| 257 | + int3 | |
| 258 | + int3 | |
| 259 | + int3 | |
| 260 | + lfence | |
| 261 | + call srso_safe_ret | |
| 262 | + int3 | |
| 263 | +SYM_CODE_END(srso_safe_ret) | |
| 264 | +SYM_FUNC_END(srso_untrain_ret) | |
| 265 | +__EXPORT_THUNK(srso_untrain_ret) | |
| 266 | + | |
| 267 | +SYM_FUNC_START(__x86_return_thunk) | |
| 268 | + ALTERNATIVE_2 "jmp __ret", "call srso_safe_ret", X86_FEATURE_SRSO, \ | |
| 269 | + "call srso_safe_ret_alias", X86_FEATURE_SRSO_ALIAS | |
| 270 | + int3 | |
| 271 | +SYM_CODE_END(__x86_return_thunk) | |
| 197 | 272 | EXPORT_SYMBOL(__x86_return_thunk) |
| 198 | 273 | |
| 199 | 274 | #endif /* CONFIG_RETHUNK */ |
| @@ -722,14 +722,9 @@ void submit_bio_noacct(struct bio *bio) · 721 unmodified lines | ||
| 722 | 722 | struct block_device *bdev = bio->bi_bdev; |
| 723 | 723 | struct request_queue *q = bdev_get_queue(bdev); |
| 724 | 724 | blk_status_t status = BLK_STS_IOERR; |
| 725 | − struct blk_plug *plug; | |
| 726 | 725 | |
| 727 | 726 | might_sleep(); |
| 728 | 727 | |
| 729 | − plug = blk_mq_plug(bio); | |
| 730 | − if (plug && plug->nowait) | |
| 731 | − bio->bi_opf |= REQ_NOWAIT; | |
| 732 | − | |
| 733 | 728 | /* |
| 734 | 729 | * For a REQ_NOWAIT based request, return -EOPNOTSUPP |
| 735 | 730 | * if queue does not support NOWAIT. |
| @@ -1059,7 +1054,6 @@ void blk_start_plug_nr_ios(struct blk_plug *plug, unsigned short nr_ios) · 323 unmodified lines | ||
| 1059 | 1054 | plug->rq_count = 0; |
| 1060 | 1055 | plug->multiple_queues = false; |
| 1061 | 1056 | plug->has_elevator = false; |
| 1062 | − plug->nowait = false; | |
| 1063 | 1057 | INIT_LIST_HEAD(&plug->cb_list); |
| 1064 | 1058 | |
| 1065 | 1059 | /* |
| @@ -3301,11 +3301,12 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input, · 3300 unmodified lines | ||
| 3301 | 3301 | if (qos[QOS_MIN] > qos[QOS_MAX]) |
| 3302 | 3302 | goto einval; |
| 3303 | 3303 | |
| 3304 | − if (enable) { | |
| 3304 | + if (enable && !ioc->enabled) { | |
| 3305 | 3305 | blk_stat_enable_accounting(disk->queue); |
| 3306 | 3306 | blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); |
| 3307 | 3307 | ioc->enabled = true; |
| 3308 | − } else { | |
| 3308 | + } else if (!enable && ioc->enabled) { | |
| 3309 | + blk_stat_disable_accounting(disk->queue); | |
| 3309 | 3310 | blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); |
| 3310 | 3311 | ioc->enabled = false; |
| 3311 | 3312 | } |
| @@ -358,13 +358,14 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb, · 357 unmodified lines | ||
| 358 | 358 | task_io_account_write(bio->bi_iter.bi_size); |
| 359 | 359 | } |
| 360 | 360 | |
| 361 | + if (iocb->ki_flags & IOCB_NOWAIT) | |
| 362 | + bio->bi_opf |= REQ_NOWAIT; | |
| 363 | + | |
| 361 | 364 | if (iocb->ki_flags & IOCB_HIPRI) { |
| 362 | − bio->bi_opf |= REQ_POLLED | REQ_NOWAIT; | |
| 365 | + bio->bi_opf |= REQ_POLLED; | |
| 363 | 366 | submit_bio(bio); |
| 364 | 367 | WRITE_ONCE(iocb->private, bio); |
| 365 | 368 | } else { |
| 366 | − if (iocb->ki_flags & IOCB_NOWAIT) | |
| 367 | − bio->bi_opf |= REQ_NOWAIT; | |
| 368 | 369 | submit_bio(bio); |
| 369 | 370 | } |
| 370 | 371 | return -EIOCBQUEUED; |
| @@ -173,6 +173,9 @@ static void internal_free_pages_locked(struct ivpu_bo *bo) · 172 unmodified lines | ||
| 173 | 173 | { |
| 174 | 174 | unsigned int i, npages = bo->base.size >> PAGE_SHIFT; |
| 175 | 175 | |
| 176 | + if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED) | |
| 177 | + set_pages_array_wb(bo->pages, bo->base.size >> PAGE_SHIFT); | |
| 178 | + | |
| 176 | 179 | for (i = 0; i < npages; i++) |
| 177 | 180 | put_page(bo->pages[i]); |
| 178 | 181 | |
| @@ -587,6 +590,11 @@ ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 fla · 408 unmodified lines | ||
| 587 | 590 | if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED) |
| 588 | 591 | drm_clflush_pages(bo->pages, bo->base.size >> PAGE_SHIFT); |
| 589 | 592 | |
| 593 | + if (bo->flags & DRM_IVPU_BO_WC) | |
| 594 | + set_pages_array_wc(bo->pages, bo->base.size >> PAGE_SHIFT); | |
| 595 | + else if (bo->flags & DRM_IVPU_BO_UNCACHED) | |
| 596 | + set_pages_array_uc(bo->pages, bo->base.size >> PAGE_SHIFT); | |
| 597 | + | |
| 590 | 598 | prot = ivpu_bo_pgprot(bo, PAGE_KERNEL); |
| 591 | 599 | bo->kvaddr = vmap(bo->pages, bo->base.size >> PAGE_SHIFT, VM_MAP, prot); |
| 592 | 600 | if (!bo->kvaddr) { |
| @@ -470,6 +470,45 @@ static const struct dmi_system_id asus_laptop[] = { · 469 unmodified lines | ||
| 470 | 470 | { } |
| 471 | 471 | }; |
| 472 | 472 | |
| 473 | +static const struct dmi_system_id tongfang_gm_rg[] = { | |
| 474 | + { | |
| 475 | + .ident = "TongFang GMxRGxx/XMG CORE 15 (M22)/TUXEDO Stellaris 15 Gen4 AMD", | |
| 476 | + .matches = { | |
| 477 | + DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"), | |
| 478 | + }, | |
| 479 | + }, | |
| 480 | + { } | |
| 481 | +}; | |
| 482 | + | |
| 483 | +static const struct dmi_system_id maingear_laptop[] = { | |
| 484 | + { | |
| 485 | + .ident = "MAINGEAR Vector Pro 2 15", | |
| 486 | + .matches = { | |
| 487 | + DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"), | |
| 488 | + DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-15A3070T"), | |
| 489 | + } | |
| 490 | + }, | |
| 491 | + { | |
| 492 | + .ident = "MAINGEAR Vector Pro 2 17", | |
| 493 | + .matches = { | |
| 494 | + DMI_MATCH(DMI_SYS_VENDOR, "Micro Electronics Inc"), | |
| 495 | + DMI_MATCH(DMI_PRODUCT_NAME, "MG-VCP2-17A3070T"), | |
| 496 | + }, | |
| 497 | + }, | |
| 498 | + { } | |
| 499 | +}; | |
| 500 | + | |
| 501 | +static const struct dmi_system_id pcspecialist_laptop[] = { | |
| 502 | + { | |
| 503 | + .ident = "PCSpecialist Elimina Pro 16 M", | |
| 504 | + .matches = { | |
| 505 | + DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"), | |
| 506 | + DMI_MATCH(DMI_PRODUCT_NAME, "Elimina Pro 16 M"), | |
| 507 | + }, | |
| 508 | + }, | |
| 509 | + { } | |
| 510 | +}; | |
| 511 | + | |
| 473 | 512 | static const struct dmi_system_id lg_laptop[] = { |
| 474 | 513 | { |
| 475 | 514 | .ident = "LG Electronics 17U70P", |
| @@ -493,6 +532,9 @@ struct irq_override_cmp { · 17 unmodified lines | ||
| 493 | 532 | static const struct irq_override_cmp override_table[] = { |
| 494 | 533 | { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, |
| 495 | 534 | { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, |
| 535 | + { tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, | |
| 536 | + { maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, | |
| 537 | + { pcspecialist_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, | |
| 496 | 538 | { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, |
| 497 | 539 | }; |
| 498 | 540 | |
| @@ -512,6 +554,28 @@ static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, · 13 unmodified lines | ||
| 512 | 554 | return entry->override; |
| 513 | 555 | } |
| 514 | 556 | |
| 557 | +#ifdef CONFIG_X86 | |
| 558 | + /* | |
| 559 | + * Always use the MADT override info, except for the i8042 PS/2 ctrl | |
| 560 | + * IRQs (1 and 12). For these the DSDT IRQ settings should sometimes | |
| 561 | + * be used otherwise PS/2 keyboards / mice will not work. | |
| 562 | + */ | |
| 563 | + if (gsi != 1 && gsi != 12) | |
| 564 | + return true; | |
| 565 | + | |
| 566 | + /* If the override comes from an INT_SRC_OVR MADT entry, honor it. */ | |
| 567 | + if (acpi_int_src_ovr[gsi]) | |
| 568 | + return true; | |
| 569 | + | |
| 570 | + /* | |
| 571 | + * IRQ override isn't needed on modern AMD Zen systems and | |
| 572 | + * this override breaks active low IRQs on AMD Ryzen 6000 and | |
| 573 | + * newer systems. Skip it. | |
| 574 | + */ | |
| 575 | + if (boot_cpu_has(X86_FEATURE_ZEN)) | |
| 576 | + return false; | |
| 577 | +#endif | |
| 578 | + | |
| 515 | 579 | return true; |
| 516 | 580 | } |
| 517 | 581 | |
| @@ -1714,6 +1714,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device) · 1713 unmodified lines | ||
| 1714 | 1714 | {"BSG1160", }, |
| 1715 | 1715 | {"BSG2150", }, |
| 1716 | 1716 | {"CSC3551", }, |
| 1717 | + {"CSC3556", }, | |
| 1717 | 1718 | {"INT33FE", }, |
| 1718 | 1719 | {"INT3515", }, |
| 1719 | 1720 | /* Non-conforming _HID for Cirrus Logic already released */ |
| @@ -6617,6 +6617,7 @@ err_init_binder_device_failed: · 6616 unmodified lines | ||
| 6617 | 6617 | |
| 6618 | 6618 | err_alloc_device_names_failed: |
| 6619 | 6619 | debugfs_remove_recursive(binder_debugfs_dir_entry_root); |
| 6620 | + binder_alloc_shrinker_exit(); | |
| 6620 | 6621 | |
| 6621 | 6622 | return ret; |
| 6622 | 6623 | } |
| @@ -1087,6 +1087,12 @@ int binder_alloc_shrinker_init(void) · 1086 unmodified lines | ||
| 1087 | 1087 | return ret; |
| 1088 | 1088 | } |
| 1089 | 1089 | |
| 1090 | +void binder_alloc_shrinker_exit(void) | |
| 1091 | +{ | |
| 1092 | + unregister_shrinker(&binder_shrinker); | |
| 1093 | + list_lru_destroy(&binder_alloc_lru); | |
| 1094 | +} | |
| 1095 | + | |
| 1090 | 1096 | /** |
| 1091 | 1097 | * check_buffer() - verify that buffer/offset is safe to access |
| 1092 | 1098 | * @alloc: binder_alloc for this proc |
| @@ -129,6 +129,7 @@ extern struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, · 128 unmodified lines | ||
| 129 | 129 | int pid); |
| 130 | 130 | extern void binder_alloc_init(struct binder_alloc *alloc); |
| 131 | 131 | extern int binder_alloc_shrinker_init(void); |
| 132 | +extern void binder_alloc_shrinker_exit(void); | |
| 132 | 133 | extern void binder_alloc_vma_close(struct binder_alloc *alloc); |
| 133 | 134 | extern struct binder_buffer * |
| 134 | 135 | binder_alloc_prepare_to_free(struct binder_alloc *alloc, |
| @@ -1100,7 +1100,14 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev) · 1099 unmodified lines | ||
| 1100 | 1100 | } |
| 1101 | 1101 | } else { |
| 1102 | 1102 | sdev->sector_size = ata_id_logical_sector_size(dev->id); |
| 1103 | + /* | |
| 1104 | + * Stop the drive on suspend but do not issue START STOP UNIT | |
| 1105 | + * on resume as this is not necessary and may fail: the device | |
| 1106 | + * will be woken up by ata_port_pm_resume() with a port reset | |
| 1107 | + * and device revalidation. | |
| 1108 | + */ | |
| 1103 | 1109 | sdev->manage_start_stop = 1; |
| 1110 | + sdev->no_start_on_resume = 1; | |
| 1104 | 1111 | } |
| 1105 | 1112 | |
| 1106 | 1113 | /* |
| @@ -509,73 +509,30 @@ static void __init cpu_dev_register_generic(void) · 508 unmodified lines | ||
| 509 | 509 | } |
| 510 | 510 | |
| 511 | 511 | #ifdef CONFIG_GENERIC_CPU_VULNERABILITIES |
| 512 | − | |
| 513 | −ssize_t __weak cpu_show_meltdown(struct device *dev, | |
| 514 | − struct device_attribute *attr, char *buf) | |
| 515 | −{ | |
| 516 | − return sysfs_emit(buf, "Not affected\n"); | |
| 517 | −} | |
| 518 | − | |
| 519 | −ssize_t __weak cpu_show_spectre_v1(struct device *dev, | |
| 520 | − struct device_attribute *attr, char *buf) | |
| 521 | −{ | |
| 522 | − return sysfs_emit(buf, "Not affected\n"); | |
| 523 | −} | |
| 524 | − | |
| 525 | −ssize_t __weak cpu_show_spectre_v2(struct device *dev, | |
| 526 | − struct device_attribute *attr, char *buf) | |
| 527 | −{ | |
| 528 | − return sysfs_emit(buf, "Not affected\n"); | |
| 529 | −} | |
| 530 | − | |
| 531 | −ssize_t __weak cpu_show_spec_store_bypass(struct device *dev, | |
| 532 | − struct device_attribute *attr, char *buf) | |
| 533 | −{ | |
| 534 | − return sysfs_emit(buf, "Not affected\n"); | |
| 535 | −} | |
| 536 | − | |
| 537 | −ssize_t __weak cpu_show_l1tf(struct device *dev, | |
| 538 | − struct device_attribute *attr, char *buf) | |
| 539 | −{ | |
| 540 | − return sysfs_emit(buf, "Not affected\n"); | |
| 541 | −} | |
| 542 | − | |
| 543 | −ssize_t __weak cpu_show_mds(struct device *dev, | |
| 544 | − struct device_attribute *attr, char *buf) | |
| 545 | −{ | |
| 546 | − return sysfs_emit(buf, "Not affected\n"); | |
| 547 | −} | |
| 548 | − | |
| 549 | −ssize_t __weak cpu_show_tsx_async_abort(struct device *dev, | |
| 550 | − struct device_attribute *attr, | |
| 551 | − char *buf) | |
| 552 | −{ | |
| 553 | − return sysfs_emit(buf, "Not affected\n"); | |
| 554 | −} | |
| 555 | − | |
| 556 | −ssize_t __weak cpu_show_itlb_multihit(struct device *dev, | |
| 557 | − struct device_attribute *attr, char *buf) | |
| 558 | −{ | |
| 559 | − return sysfs_emit(buf, "Not affected\n"); | |
| 560 | −} | |
| 561 | − | |
| 562 | −ssize_t __weak cpu_show_srbds(struct device *dev, | |
| 512 | +static ssize_t cpu_show_not_affected(struct device *dev, | |
| 563 | 513 | struct device_attribute *attr, char *buf) |
| 564 | 514 | { |
| 565 | 515 | return sysfs_emit(buf, "Not affected\n"); |
| 566 | 516 | } |
| 567 | 517 | |
| 568 | −ssize_t __weak cpu_show_mmio_stale_data(struct device *dev, | |
| 569 | − struct device_attribute *attr, char *buf) | |
| 570 | −{ | |
| 571 | − return sysfs_emit(buf, "Not affected\n"); | |
| 572 | −} | |
| 573 | − | |
| 574 | −ssize_t __weak cpu_show_retbleed(struct device *dev, | |
| 575 | − struct device_attribute *attr, char *buf) | |
| 576 | −{ | |
| 577 | − return sysfs_emit(buf, "Not affected\n"); | |
| 578 | −} | |
| 518 | +#define CPU_SHOW_VULN_FALLBACK(func) \ | |
| 519 | + ssize_t cpu_show_##func(struct device *, \ | |
| 520 | + struct device_attribute *, char *) \ | |
| 521 | + __attribute__((weak, alias("cpu_show_not_affected"))) | |
| 522 | + | |
| 523 | +CPU_SHOW_VULN_FALLBACK(meltdown); | |
| 524 | +CPU_SHOW_VULN_FALLBACK(spectre_v1); | |
| 525 | +CPU_SHOW_VULN_FALLBACK(spectre_v2); | |
| 526 | +CPU_SHOW_VULN_FALLBACK(spec_store_bypass); | |
| 527 | +CPU_SHOW_VULN_FALLBACK(l1tf); | |
| 528 | +CPU_SHOW_VULN_FALLBACK(mds); | |
| 529 | +CPU_SHOW_VULN_FALLBACK(tsx_async_abort); | |
| 530 | +CPU_SHOW_VULN_FALLBACK(itlb_multihit); | |
| 531 | +CPU_SHOW_VULN_FALLBACK(srbds); | |
| 532 | +CPU_SHOW_VULN_FALLBACK(mmio_stale_data); | |
| 533 | +CPU_SHOW_VULN_FALLBACK(retbleed); | |
| 534 | +CPU_SHOW_VULN_FALLBACK(spec_rstack_overflow); | |
| 535 | +CPU_SHOW_VULN_FALLBACK(gds); | |
| 579 | 536 | |
| 580 | 537 | static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); |
| 581 | 538 | static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); |
| @@ -588,6 +545,8 @@ static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL); · 6 unmodified lines | ||
| 588 | 545 | static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL); |
| 589 | 546 | static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL); |
| 590 | 547 | static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL); |
| 548 | +static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL); | |
| 549 | +static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL); | |
| 591 | 550 | |
| 592 | 551 | static struct attribute *cpu_root_vulnerabilities_attrs[] = { |
| 593 | 552 | &dev_attr_meltdown.attr, |
| @@ -601,6 +560,8 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = { · 7 unmodified lines | ||
| 601 | 560 | &dev_attr_srbds.attr, |
| 602 | 561 | &dev_attr_mmio_stale_data.attr, |
| 603 | 562 | &dev_attr_retbleed.attr, |
| 563 | + &dev_attr_spec_rstack_overflow.attr, | |
| 564 | + &dev_attr_gather_data_sampling.attr, | |
| 604 | 565 | NULL |
| 605 | 566 | }; |
| 606 | 567 | |
| @@ -3675,7 +3675,7 @@ static int rbd_lock(struct rbd_device *rbd_dev) · 3674 unmodified lines | ||
| 3675 | 3675 | ret = ceph_cls_lock(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc, |
| 3676 | 3676 | RBD_LOCK_NAME, CEPH_CLS_LOCK_EXCLUSIVE, cookie, |
| 3677 | 3677 | RBD_LOCK_TAG, "", 0); |
| 3678 | − if (ret) | |
| 3678 | + if (ret && ret != -EEXIST) | |
| 3679 | 3679 | return ret; |
| 3680 | 3680 | |
| 3681 | 3681 | __rbd_lock(rbd_dev, cookie); |
| @@ -3878,7 +3878,7 @@ static struct ceph_locker *get_lock_owner_info(struct rbd_device *rbd_dev) · 196 unmodified lines | ||
| 3878 | 3878 | &rbd_dev->header_oloc, RBD_LOCK_NAME, |
| 3879 | 3879 | &lock_type, &lock_tag, &lockers, &num_lockers); |
| 3880 | 3880 | if (ret) { |
| 3881 | − rbd_warn(rbd_dev, "failed to retrieve lockers: %d", ret); | |
| 3881 | + rbd_warn(rbd_dev, "failed to get header lockers: %d", ret); | |
| 3882 | 3882 | return ERR_PTR(ret); |
| 3883 | 3883 | } |
| 3884 | 3884 | |
| @@ -3940,8 +3940,10 @@ static int find_watcher(struct rbd_device *rbd_dev, · 55 unmodified lines | ||
| 3940 | 3940 | ret = ceph_osdc_list_watchers(osdc, &rbd_dev->header_oid, |
| 3941 | 3941 | &rbd_dev->header_oloc, &watchers, |
| 3942 | 3942 | &num_watchers); |
| 3943 | − if (ret) | |
| 3943 | + if (ret) { | |
| 3944 | + rbd_warn(rbd_dev, "failed to get watchers: %d", ret); | |
| 3944 | 3945 | return ret; |
| 3946 | + } | |
| 3945 | 3947 | |
| 3946 | 3948 | sscanf(locker->id.cookie, RBD_LOCK_COOKIE_PREFIX " %llu", &cookie); |
| 3947 | 3949 | for (i = 0; i < num_watchers; i++) { |
| @@ -3985,8 +3987,12 @@ static int rbd_try_lock(struct rbd_device *rbd_dev) · 37 unmodified lines | ||
| 3985 | 3987 | locker = refreshed_locker = NULL; |
| 3986 | 3988 | |
| 3987 | 3989 | ret = rbd_lock(rbd_dev); |
| 3988 | − if (ret != -EBUSY) | |
| 3990 | + if (!ret) | |
| 3991 | + goto out; | |
| 3992 | + if (ret != -EBUSY) { | |
| 3993 | + rbd_warn(rbd_dev, "failed to lock header: %d", ret); | |
| 3989 | 3994 | goto out; |
| 3995 | + } | |
| 3990 | 3996 | |
| 3991 | 3997 | /* determine if the current lock holder is still alive */ |
| 3992 | 3998 | locker = get_lock_owner_info(rbd_dev); |
| @@ -4089,11 +4095,8 @@ static int rbd_try_acquire_lock(struct rbd_device *rbd_dev) · 96 unmodified lines | ||
| 4089 | 4095 | |
| 4090 | 4096 | ret = rbd_try_lock(rbd_dev); |
| 4091 | 4097 | if (ret < 0) { |
| 4092 | − rbd_warn(rbd_dev, "failed to lock header: %d", ret); | |
| 4093 | − if (ret == -EBLOCKLISTED) | |
| 4094 | − goto out; | |
| 4095 | − | |
| 4096 | − ret = 1; /* request lock anyway */ | |
| 4098 | + rbd_warn(rbd_dev, "failed to acquire lock: %d", ret); | |
| 4099 | + goto out; | |
| 4097 | 4100 | } |
| 4098 | 4101 | if (ret > 0) { |
| 4099 | 4102 | up_write(&rbd_dev->lock_rwsem); |
| @@ -6627,12 +6630,11 @@ static int rbd_add_acquire_lock(struct rbd_device *rbd_dev) · 2527 unmodified lines | ||
| 6627 | 6630 | cancel_delayed_work_sync(&rbd_dev->lock_dwork); |
| 6628 | 6631 | if (!ret) |
| 6629 | 6632 | ret = -ETIMEDOUT; |
| 6630 | − } | |
| 6631 | 6633 | |
| 6632 | − if (ret) { | |
| 6633 | − rbd_warn(rbd_dev, "failed to acquire exclusive lock: %ld", ret); | |
| 6634 | − return ret; | |
| 6634 | + rbd_warn(rbd_dev, "failed to acquire lock: %ld", ret); | |
| 6635 | 6635 | } |
| 6636 | + if (ret) | |
| 6637 | + return ret; | |
| 6636 | 6638 | |
| 6637 | 6639 | /* |
| 6638 | 6640 | * The lock may have been released by now, unless automatic lock |
| @@ -1870,15 +1870,16 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) · 1869 unmodified lines | ||
| 1870 | 1870 | |
| 1871 | 1871 | static void zram_bio_read(struct zram *zram, struct bio *bio) |
| 1872 | 1872 | { |
| 1873 | − struct bvec_iter iter; | |
| 1874 | − struct bio_vec bv; | |
| 1875 | − unsigned long start_time; | |
| 1873 | + unsigned long start_time = bio_start_io_acct(bio); | |
| 1874 | + struct bvec_iter iter = bio->bi_iter; | |
| 1876 | 1875 | |
| 1877 | − start_time = bio_start_io_acct(bio); | |
| 1878 | − bio_for_each_segment(bv, bio, iter) { | |
| 1876 | + do { | |
| 1879 | 1877 | u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; |
| 1880 | 1878 | u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) << |
| 1881 | 1879 | SECTOR_SHIFT; |
| 1880 | + struct bio_vec bv = bio_iter_iovec(bio, iter); | |
| 1881 | + | |
| 1882 | + bv.bv_len = min_t(u32, bv.bv_len, PAGE_SIZE - offset); | |
| 1882 | 1883 | |
| 1883 | 1884 | if (zram_bvec_read(zram, &bv, index, offset, bio) < 0) { |
| 1884 | 1885 | atomic64_inc(&zram->stats.failed_reads); |
| @@ -1890,22 +1891,26 @@ static void zram_bio_read(struct zram *zram, struct bio *bio) · 5 unmodified lines | ||
| 1890 | 1891 | zram_slot_lock(zram, index); |
| 1891 | 1892 | zram_accessed(zram, index); |
| 1892 | 1893 | zram_slot_unlock(zram, index); |
| 1893 | − } | |
| 1894 | + | |
| 1895 | + bio_advance_iter_single(bio, &iter, bv.bv_len); | |
| 1896 | + } while (iter.bi_size); | |
| 1897 | + | |
| 1894 | 1898 | bio_end_io_acct(bio, start_time); |
| 1895 | 1899 | bio_endio(bio); |
| 1896 | 1900 | } |
| 1897 | 1901 | |
| 1898 | 1902 | static void zram_bio_write(struct zram *zram, struct bio *bio) |
| 1899 | 1903 | { |
| 1900 | − struct bvec_iter iter; | |
| 1901 | − struct bio_vec bv; | |
| 1902 | − unsigned long start_time; | |
| 1904 | + unsigned long start_time = bio_start_io_acct(bio); | |
| 1905 | + struct bvec_iter iter = bio->bi_iter; | |
| 1903 | 1906 | |
| 1904 | − start_time = bio_start_io_acct(bio); | |
| 1905 | − bio_for_each_segment(bv, bio, iter) { | |
| 1907 | + do { | |
| 1906 | 1908 | u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; |
| 1907 | 1909 | u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) << |
| 1908 | 1910 | SECTOR_SHIFT; |
| 1911 | + struct bio_vec bv = bio_iter_iovec(bio, iter); | |
| 1912 | + | |
| 1913 | + bv.bv_len = min_t(u32, bv.bv_len, PAGE_SIZE - offset); | |
| 1909 | 1914 | |
| 1910 | 1915 | if (zram_bvec_write(zram, &bv, index, offset, bio) < 0) { |
| 1911 | 1916 | atomic64_inc(&zram->stats.failed_writes); |
| @@ -1916,7 +1921,10 @@ static void zram_bio_write(struct zram *zram, struct bio *bio) · 4 unmodified lines | ||
| 1916 | 1921 | zram_slot_lock(zram, index); |
| 1917 | 1922 | zram_accessed(zram, index); |
| 1918 | 1923 | zram_slot_unlock(zram, index); |
| 1919 | − } | |
| 1924 | + | |
| 1925 | + bio_advance_iter_single(bio, &iter, bv.bv_len); | |
| 1926 | + } while (iter.bi_size); | |
| 1927 | + | |
| 1920 | 1928 | bio_end_io_acct(bio, start_time); |
| 1921 | 1929 | bio_endio(bio); |
| 1922 | 1930 | } |
| @@ -510,70 +510,6 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip) · 509 unmodified lines | ||
| 510 | 510 | return 0; |
| 511 | 511 | } |
| 512 | 512 | |
| 513 | −/* | |
| 514 | − * Some AMD fTPM versions may cause stutter | |
| 515 | − * https://www.amd.com/en/support/kb/faq/pa-410 | |
| 516 | − * | |
| 517 | − * Fixes are available in two series of fTPM firmware: | |
| 518 | − * 6.x.y.z series: 6.0.18.6 + | |
| 519 | − * 3.x.y.z series: 3.57.y.5 + | |
| 520 | − */ | |
| 521 | −#ifdef CONFIG_X86 | |
| 522 | −static bool tpm_amd_is_rng_defective(struct tpm_chip *chip) | |
| 523 | −{ | |
| 524 | − u32 val1, val2; | |
| 525 | − u64 version; | |
| 526 | − int ret; | |
| 527 | − | |
| 528 | − if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) | |
| 529 | − return false; | |
| 530 | − | |
| 531 | − ret = tpm_request_locality(chip); | |
| 532 | − if (ret) | |
| 533 | − return false; | |
| 534 | − | |
| 535 | − ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val1, NULL); | |
| 536 | − if (ret) | |
| 537 | − goto release; | |
| 538 | − if (val1 != 0x414D4400U /* AMD */) { | |
| 539 | − ret = -ENODEV; | |
| 540 | − goto release; | |
| 541 | − } | |
| 542 | − ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_1, &val1, NULL); | |
| 543 | − if (ret) | |
| 544 | − goto release; | |
| 545 | − ret = tpm2_get_tpm_pt(chip, TPM2_PT_FIRMWARE_VERSION_2, &val2, NULL); | |
| 546 | − | |
| 547 | −release: | |
| 548 | − tpm_relinquish_locality(chip); | |
| 549 | − | |
| 550 | − if (ret) | |
| 551 | − return false; | |
| 552 | − | |
| 553 | − version = ((u64)val1 << 32) | val2; | |
| 554 | − if ((version >> 48) == 6) { | |
| 555 | − if (version >= 0x0006000000180006ULL) | |
| 556 | − return false; | |
| 557 | − } else if ((version >> 48) == 3) { | |
| 558 | − if (version >= 0x0003005700000005ULL) | |
| 559 | − return false; | |
| 560 | − } else { | |
| 561 | − return false; | |
| 562 | − } | |
| 563 | − | |
| 564 | − dev_warn(&chip->dev, | |
| 565 | − "AMD fTPM version 0x%llx causes system stutter; hwrng disabled\n", | |
| 566 | − version); | |
| 567 | − | |
| 568 | − return true; | |
| 569 | −} | |
| 570 | −#else | |
| 571 | −static inline bool tpm_amd_is_rng_defective(struct tpm_chip *chip) | |
| 572 | −{ | |
| 573 | − return false; | |
| 574 | −} | |
| 575 | −#endif /* CONFIG_X86 */ | |
| 576 | − | |
| 577 | 513 | static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) |
| 578 | 514 | { |
| 579 | 515 | struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng); |
| @@ -585,10 +521,20 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) · 5 unmodified lines | ||
| 585 | 521 | return tpm_get_random(chip, data, max); |
| 586 | 522 | } |
| 587 | 523 | |
| 524 | +static bool tpm_is_hwrng_enabled(struct tpm_chip *chip) | |
| 525 | +{ | |
| 526 | + if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM)) | |
| 527 | + return false; | |
| 528 | + if (tpm_is_firmware_upgrade(chip)) | |
| 529 | + return false; | |
| 530 | + if (chip->flags & TPM_CHIP_FLAG_HWRNG_DISABLED) | |
| 531 | + return false; | |
| 532 | + return true; | |
| 533 | +} | |
| 534 | + | |
| 588 | 535 | static int tpm_add_hwrng(struct tpm_chip *chip) |
| 589 | 536 | { |
| 590 | − if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM) || tpm_is_firmware_upgrade(chip) || | |
| 591 | − tpm_amd_is_rng_defective(chip)) | |
| 537 | + if (!tpm_is_hwrng_enabled(chip)) | |
| 592 | 538 | return 0; |
| 593 | 539 | |
| 594 | 540 | snprintf(chip->hwrng_name, sizeof(chip->hwrng_name), |
| @@ -693,7 +639,7 @@ int tpm_chip_register(struct tpm_chip *chip) · 98 unmodified lines | ||
| 693 | 639 | return 0; |
| 694 | 640 | |
| 695 | 641 | out_hwrng: |
| 696 | − if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip)) | |
| 642 | + if (tpm_is_hwrng_enabled(chip)) | |
| 697 | 643 | hwrng_unregister(&chip->hwrng); |
| 698 | 644 | out_ppi: |
| 699 | 645 | tpm_bios_log_teardown(chip); |
| @@ -718,8 +664,7 @@ EXPORT_SYMBOL_GPL(tpm_chip_register); · 18 unmodified lines | ||
| 718 | 664 | void tpm_chip_unregister(struct tpm_chip *chip) |
| 719 | 665 | { |
| 720 | 666 | tpm_del_legacy_sysfs(chip); |
| 721 | − if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip) && | |
| 722 | − !tpm_amd_is_rng_defective(chip)) | |
| 667 | + if (tpm_is_hwrng_enabled(chip)) | |
| 723 | 668 | hwrng_unregister(&chip->hwrng); |
| 724 | 669 | tpm_bios_log_teardown(chip); |
| 725 | 670 | if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip)) |
| @@ -463,6 +463,28 @@ static bool crb_req_canceled(struct tpm_chip *chip, u8 status) · 462 unmodified lines | ||
| 463 | 463 | return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; |
| 464 | 464 | } |
| 465 | 465 | |
| 466 | +static int crb_check_flags(struct tpm_chip *chip) | |
| 467 | +{ | |
| 468 | + u32 val; | |
| 469 | + int ret; | |
| 470 | + | |
| 471 | + ret = crb_request_locality(chip, 0); | |
| 472 | + if (ret) | |
| 473 | + return ret; | |
| 474 | + | |
| 475 | + ret = tpm2_get_tpm_pt(chip, TPM2_PT_MANUFACTURER, &val, NULL); | |
| 476 | + if (ret) | |
| 477 | + goto release; | |
| 478 | + | |
| 479 | + if (val == 0x414D4400U /* AMD */) | |
| 480 | + chip->flags |= TPM_CHIP_FLAG_HWRNG_DISABLED; | |
| 481 | + | |
| 482 | +release: | |
| 483 | + crb_relinquish_locality(chip, 0); | |
| 484 | + | |
| 485 | + return ret; | |
| 486 | +} | |
| 487 | + | |
| 466 | 488 | static const struct tpm_class_ops tpm_crb = { |
| 467 | 489 | .flags = TPM_OPS_AUTO_STARTUP, |
| 468 | 490 | .status = crb_status, |
| @@ -800,6 +822,14 @@ static int crb_acpi_add(struct acpi_device *device) · 331 unmodified lines | ||
| 800 | 822 | chip->acpi_dev_handle = device->handle; |
| 801 | 823 | chip->flags = TPM_CHIP_FLAG_TPM2; |
| 802 | 824 | |
| 825 | + rc = tpm_chip_bootstrap(chip); | |
| 826 | + if (rc) | |
| 827 | + goto out; | |
| 828 | + | |
| 829 | + rc = crb_check_flags(chip); | |
| 830 | + if (rc) | |
| 831 | + goto out; | |
| 832 | + | |
| 803 | 833 | rc = tpm_chip_register(chip); |
| 804 | 834 | |
| 805 | 835 | out: |
| @@ -89,7 +89,7 @@ static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr) · 88 unmodified lines | ||
| 89 | 89 | tpm_tis_flush(iobase); |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | −static int interrupts = -1; | |
| 92 | +static int interrupts; | |
| 93 | 93 | module_param(interrupts, int, 0444); |
| 94 | 94 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); |
| 95 | 95 | |
| @@ -162,12 +162,28 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = { · 66 unmodified lines | ||
| 162 | 162 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L590"), |
| 163 | 163 | }, |
| 164 | 164 | }, |
| 165 | + { | |
| 166 | + .callback = tpm_tis_disable_irq, | |
| 167 | + .ident = "ThinkStation P620", | |
| 168 | + .matches = { | |
| 169 | + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | |
| 170 | + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P620"), | |
| 171 | + }, | |
| 172 | + }, | |
| 173 | + { | |
| 174 | + .callback = tpm_tis_disable_irq, | |
| 175 | + .ident = "TUXEDO InfinityBook S 15/17 Gen7", | |
| 176 | + .matches = { | |
| 177 | + DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), | |
| 178 | + DMI_MATCH(DMI_PRODUCT_NAME, "TUXEDO InfinityBook S 15/17 Gen7"), | |
| 179 | + }, | |
| 180 | + }, | |
| 165 | 181 | { |
| 166 | 182 | .callback = tpm_tis_disable_irq, |
| 167 | 183 | .ident = "UPX-TGL", |
| 168 | 184 | .matches = { |
| 169 | 185 | DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), |
| 170 | − DMI_MATCH(DMI_PRODUCT_VERSION, "UPX-TGL"), | |
| 186 | + DMI_MATCH(DMI_PRODUCT_NAME, "UPX-TGL01"), | |
| 171 | 187 | }, |
| 172 | 188 | }, |
| 173 | 189 | {} |
| @@ -444,6 +444,7 @@ config COMMON_CLK_BD718XX · 443 unmodified lines | ||
| 444 | 444 | config COMMON_CLK_FIXED_MMIO |
| 445 | 445 | bool "Clock driver for Memory Mapped Fixed values" |
| 446 | 446 | depends on COMMON_CLK && OF |
| 447 | + depends on HAS_IOMEM | |
| 447 | 448 | help |
| 448 | 449 | Support for Memory Mapped IO Fixed clocks |
| 449 | 450 | |
| @@ -291,7 +291,7 @@ static int imx93_clocks_probe(struct platform_device *pdev) · 290 unmodified lines | ||
| 291 | 291 | anatop_base = devm_of_iomap(dev, np, 0, NULL); |
| 292 | 292 | of_node_put(np); |
| 293 | 293 | if (WARN_ON(IS_ERR(anatop_base))) { |
| 294 | − ret = PTR_ERR(base); | |
| 294 | + ret = PTR_ERR(anatop_base); | |
| 295 | 295 | goto unregister_hws; |
| 296 | 296 | } |
| 297 | 297 | |
| @@ -328,6 +328,14 @@ static const char * const atb_parents[] = { · 327 unmodified lines | ||
| 328 | 328 | "syspll_d5" |
| 329 | 329 | }; |
| 330 | 330 | |
| 331 | +static const char * const sspm_parents[] = { | |
| 332 | + "clk26m", | |
| 333 | + "univpll_d2_d4", | |
| 334 | + "syspll_d2_d2", | |
| 335 | + "univpll_d2_d2", | |
| 336 | + "syspll_d3" | |
| 337 | +}; | |
| 338 | + | |
| 331 | 339 | static const char * const dpi0_parents[] = { |
| 332 | 340 | "clk26m", |
| 333 | 341 | "tvdpll_d2", |
| @@ -507,6 +515,9 @@ static const struct mtk_mux top_muxes[] = { · 173 unmodified lines | ||
| 507 | 515 | /* CLK_CFG_6 */ |
| 508 | 516 | MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_ATB, "atb_sel", |
| 509 | 517 | atb_parents, 0xa0, 0xa4, 0xa8, 0, 2, 7, 0x004, 24), |
| 518 | + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_SSPM, "sspm_sel", | |
| 519 | + sspm_parents, 0xa0, 0xa4, 0xa8, 8, 3, 15, 0x004, 25, | |
| 520 | + CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), | |
| 510 | 521 | MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DPI0, "dpi0_sel", |
| 511 | 522 | dpi0_parents, 0xa0, 0xa4, 0xa8, 16, 4, 23, 0x004, 26), |
| 512 | 523 | MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SCAM, "scam_sel", |
| @@ -673,10 +684,18 @@ static const struct mtk_gate_regs infra3_cg_regs = { · 160 unmodified lines | ||
| 673 | 684 | GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, \ |
| 674 | 685 | &mtk_clk_gate_ops_setclr) |
| 675 | 686 | |
| 687 | +#define GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, _flag) \ | |
| 688 | + GATE_MTK_FLAGS(_id, _name, _parent, &infra2_cg_regs, \ | |
| 689 | + _shift, &mtk_clk_gate_ops_setclr, _flag) | |
| 690 | + | |
| 676 | 691 | #define GATE_INFRA3(_id, _name, _parent, _shift) \ |
| 677 | 692 | GATE_MTK(_id, _name, _parent, &infra3_cg_regs, _shift, \ |
| 678 | 693 | &mtk_clk_gate_ops_setclr) |
| 679 | 694 | |
| 695 | +#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flag) \ | |
| 696 | + GATE_MTK_FLAGS(_id, _name, _parent, &infra3_cg_regs, \ | |
| 697 | + _shift, &mtk_clk_gate_ops_setclr, _flag) | |
| 698 | + | |
| 680 | 699 | static const struct mtk_gate infra_clks[] = { |
| 681 | 700 | /* INFRA0 */ |
| 682 | 701 | GATE_INFRA0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "axi_sel", 0), |
| @@ -748,7 +767,11 @@ static const struct mtk_gate infra_clks[] = { · 65 unmodified lines | ||
| 748 | 767 | GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick", "fufs_sel", 12), |
| 749 | 768 | GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_BCLK, "infra_ufs_mp_sap_bck", "fufs_sel", 13), |
| 750 | 769 | GATE_INFRA2(CLK_INFRA_MD32_BCLK, "infra_md32_bclk", "axi_sel", 14), |
| 770 | + /* infra_sspm is main clock in co-processor, should not be closed in Linux. */ | |
| 771 | + GATE_INFRA2_FLAGS(CLK_INFRA_SSPM, "infra_sspm", "sspm_sel", 15, CLK_IS_CRITICAL), | |
| 751 | 772 | GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, "infra_unipro_mbist", "axi_sel", 16), |
| 773 | + /* infra_sspm_bus_hclk is main clock in co-processor, should not be closed in Linux. */ | |
| 774 | + GATE_INFRA2_FLAGS(CLK_INFRA_SSPM_BUS_HCLK, "infra_sspm_bus_hclk", "axi_sel", 17, CLK_IS_CRITICAL), | |
| 752 | 775 | GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5", "i2c_sel", 18), |
| 753 | 776 | GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter", "i2c_sel", 19), |
| 754 | 777 | GATE_INFRA2(CLK_INFRA_I2C5_IMM, "infra_i2c5_imm", "i2c_sel", 20), |
| @@ -766,6 +789,10 @@ static const struct mtk_gate infra_clks[] = { · 11 unmodified lines | ||
| 766 | 789 | GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self", "msdc50_0_sel", 0), |
| 767 | 790 | GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self", "msdc50_0_sel", 1), |
| 768 | 791 | GATE_INFRA3(CLK_INFRA_MSDC2_SELF, "infra_msdc2_self", "msdc50_0_sel", 2), |
| 792 | + /* infra_sspm_26m_self is main clock in co-processor, should not be closed in Linux. */ | |
| 793 | + GATE_INFRA3_FLAGS(CLK_INFRA_SSPM_26M_SELF, "infra_sspm_26m_self", "f_f26m_ck", 3, CLK_IS_CRITICAL), | |
| 794 | + /* infra_sspm_32k_self is main clock in co-processor, should not be closed in Linux. */ | |
| 795 | + GATE_INFRA3_FLAGS(CLK_INFRA_SSPM_32K_SELF, "infra_sspm_32k_self", "f_f26m_ck", 4, CLK_IS_CRITICAL), | |
| 769 | 796 | GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", "axi_sel", 5), |
| 770 | 797 | GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", "i2c_sel", 6), |
| 771 | 798 | GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0", "msdc50_hclk_sel", 7), |
| @@ -367,9 +367,9 @@ static int meson_clk_pll_enable(struct clk_hw *hw) · 366 unmodified lines | ||
| 367 | 367 | * 3. enable the lock detect module |
| 368 | 368 | */ |
| 369 | 369 | if (MESON_PARM_APPLICABLE(&pll->current_en)) { |
| 370 | − usleep_range(10, 20); | |
| 370 | + udelay(10); | |
| 371 | 371 | meson_parm_write(clk->map, &pll->current_en, 1); |
| 372 | − usleep_range(40, 50); | |
| 372 | + udelay(40); | |
| 373 | 373 | } |
| 374 | 374 | |
| 375 | 375 | if (MESON_PARM_APPLICABLE(&pll->l_detect)) { |
| @@ -3,13 +3,6 @@ · 2 unmodified lines | ||
| 3 | 3 | # Counter devices |
| 4 | 4 | # |
| 5 | 5 | |
| 6 | −menuconfig COUNTER | |
| 7 | − tristate "Counter support" | |
| 8 | − help | |
| 9 | − This enables counter device support through the Generic Counter | |
| 10 | − interface. You only need to enable this, if you also want to enable | |
| 11 | − one or more of the counter device drivers below. | |
| 12 | − | |
| 13 | 6 | config I8254 |
| 14 | 7 | tristate |
| 15 | 8 | select COUNTER |
| @@ -25,6 +18,13 @@ config I8254 · 9 unmodified lines | ||
| 25 | 18 | |
| 26 | 19 | If built as a module its name will be i8254. |
| 27 | 20 | |
| 21 | +menuconfig COUNTER | |
| 22 | + tristate "Counter support" | |
| 23 | + help | |
| 24 | + This enables counter device support through the Generic Counter | |
| 25 | + interface. You only need to enable this, if you also want to enable | |
| 26 | + one or more of the counter device drivers below. | |
| 27 | + | |
| 28 | 28 | if COUNTER |
| 29 | 29 | |
| 30 | 30 | config 104_QUAD_8 |
| @@ -1012,8 +1012,8 @@ static int amd_pstate_update_status(const char *buf, size_t size) · 1011 unmodified lines | ||
| 1012 | 1012 | return 0; |
| 1013 | 1013 | } |
| 1014 | 1014 | |
| 1015 | −static ssize_t show_status(struct kobject *kobj, | |
| 1016 | − struct kobj_attribute *attr, char *buf) | |
| 1015 | +static ssize_t status_show(struct device *dev, | |
| 1016 | + struct device_attribute *attr, char *buf) | |
| 1017 | 1017 | { |
| 1018 | 1018 | ssize_t ret; |
| 1019 | 1019 | |
| @@ -1024,7 +1024,7 @@ static ssize_t show_status(struct kobject *kobj, · 4 unmodified lines | ||
| 1024 | 1024 | return ret; |
| 1025 | 1025 | } |
| 1026 | 1026 | |
| 1027 | −static ssize_t store_status(struct kobject *a, struct kobj_attribute *b, | |
| 1027 | +static ssize_t status_store(struct device *a, struct device_attribute *b, | |
| 1028 | 1028 | const char *buf, size_t count) |
| 1029 | 1029 | { |
| 1030 | 1030 | char *p = memchr(buf, '\n', count); |
| @@ -1043,7 +1043,7 @@ cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq); · 12 unmodified lines | ||
| 1043 | 1043 | cpufreq_freq_attr_ro(amd_pstate_highest_perf); |
| 1044 | 1044 | cpufreq_freq_attr_rw(energy_performance_preference); |
| 1045 | 1045 | cpufreq_freq_attr_ro(energy_performance_available_preferences); |
| 1046 | −define_one_global_rw(status); | |
| 1046 | +static DEVICE_ATTR_RW(status); | |
| 1047 | 1047 | |
| 1048 | 1048 | static struct freq_attr *amd_pstate_attr[] = { |
| 1049 | 1049 | &amd_pstate_max_freq, |
| @@ -1062,7 +1062,7 @@ static struct freq_attr *amd_pstate_epp_attr[] = { · 12 unmodified lines | ||
| 1062 | 1062 | }; |
| 1063 | 1063 | |
| 1064 | 1064 | static struct attribute *pstate_global_attributes[] = { |
| 1065 | − &status.attr, | |
| 1065 | + &dev_attr_status.attr, | |
| 1066 | 1066 | NULL |
| 1067 | 1067 | }; |
| 1068 | 1068 | |
| @@ -120,20 +120,6 @@ static void psci_pd_remove(void) · 119 unmodified lines | ||
| 120 | 120 | } |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | −static bool psci_pd_try_set_osi_mode(void) | |
| 124 | −{ | |
| 125 | − int ret; | |
| 126 | − | |
| 127 | − if (!psci_has_osi_support()) | |
| 128 | − return false; | |
| 129 | − | |
| 130 | − ret = psci_set_osi_mode(true); | |
| 131 | − if (ret) | |
| 132 | − return false; | |
| 133 | − | |
| 134 | − return true; | |
| 135 | −} | |
| 136 | − | |
| 137 | 123 | static void psci_cpuidle_domain_sync_state(struct device *dev) |
| 138 | 124 | { |
| 139 | 125 | /* |
| @@ -152,15 +138,12 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev) · 12 unmodified lines | ||
| 152 | 138 | { |
| 153 | 139 | struct device_node *np = pdev->dev.of_node; |
| 154 | 140 | struct device_node *node; |
| 155 | − bool use_osi; | |
| 141 | + bool use_osi = psci_has_osi_support(); | |
| 156 | 142 | int ret = 0, pd_count = 0; |
| 157 | 143 | |
| 158 | 144 | if (!np) |
| 159 | 145 | return -ENODEV; |
| 160 | 146 | |
| 161 | − /* If OSI mode is supported, let's try to enable it. */ | |
| 162 | − use_osi = psci_pd_try_set_osi_mode(); | |
| 163 | − | |
| 164 | 147 | /* |
| 165 | 148 | * Parse child nodes for the "#power-domain-cells" property and |
| 166 | 149 | * initialize a genpd/genpd-of-provider pair when it's found. |
| @@ -170,33 +153,37 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 170 | 153 | continue; |
| 171 | 154 | |
| 172 | 155 | ret = psci_pd_init(node, use_osi); |
| 173 | − if (ret) | |
| 174 | − goto put_node; | |
| 156 | + if (ret) { | |
| 157 | + of_node_put(node); | |
| 158 | + goto exit; | |
| 159 | + } | |
| 175 | 160 | |
| 176 | 161 | pd_count++; |
| 177 | 162 | } |
| 178 | 163 | |
| 179 | 164 | /* Bail out if not using the hierarchical CPU topology. */ |
| 180 | 165 | if (!pd_count) |
| 181 | − goto no_pd; | |
| 166 | + return 0; | |
| 182 | 167 | |
| 183 | 168 | /* Link genpd masters/subdomains to model the CPU topology. */ |
| 184 | 169 | ret = dt_idle_pd_init_topology(np); |
| 185 | 170 | if (ret) |
| 186 | 171 | goto remove_pd; |
| 187 | 172 | |
| 173 | + /* let's try to enable OSI. */ | |
| 174 | + ret = psci_set_osi_mode(use_osi); | |
| 175 | + if (ret) | |
| 176 | + goto remove_pd; | |
| 177 | + | |
| 188 | 178 | pr_info("Initialized CPU PM domain topology using %s mode\n", |
| 189 | 179 | use_osi ? "OSI" : "PC"); |
| 190 | 180 | return 0; |
| 191 | 181 | |
| 192 | −put_node: | |
| 193 | − of_node_put(node); | |
| 194 | 182 | remove_pd: |
| 183 | + dt_idle_pd_remove_topology(np); | |
| 195 | 184 | psci_pd_remove(); |
| 185 | +exit: | |
| 196 | 186 | pr_err("failed to create CPU PM domains ret=%d\n", ret); |
| 197 | −no_pd: | |
| 198 | − if (use_osi) | |
| 199 | − psci_set_osi_mode(false); | |
| 200 | 187 | return ret; |
| 201 | 188 | } |
| 202 | 189 | |
| @@ -152,6 +152,30 @@ int dt_idle_pd_init_topology(struct device_node *np) · 151 unmodified lines | ||
| 152 | 152 | return 0; |
| 153 | 153 | } |
| 154 | 154 | |
| 155 | +int dt_idle_pd_remove_topology(struct device_node *np) | |
| 156 | +{ | |
| 157 | + struct device_node *node; | |
| 158 | + struct of_phandle_args child, parent; | |
| 159 | + int ret; | |
| 160 | + | |
| 161 | + for_each_child_of_node(np, node) { | |
| 162 | + if (of_parse_phandle_with_args(node, "power-domains", | |
| 163 | + "#power-domain-cells", 0, &parent)) | |
| 164 | + continue; | |
| 165 | + | |
| 166 | + child.np = node; | |
| 167 | + child.args_count = 0; | |
| 168 | + ret = of_genpd_remove_subdomain(&parent, &child); | |
| 169 | + of_node_put(parent.np); | |
| 170 | + if (ret) { | |
| 171 | + of_node_put(node); | |
| 172 | + return ret; | |
| 173 | + } | |
| 174 | + } | |
| 175 | + | |
| 176 | + return 0; | |
| 177 | +} | |
| 178 | + | |
| 155 | 179 | struct device *dt_idle_attach_cpu(int cpu, const char *name) |
| 156 | 180 | { |
| 157 | 181 | struct device *dev; |
| @@ -14,6 +14,8 @@ struct generic_pm_domain *dt_idle_pd_alloc(struct device_node *np, · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | int dt_idle_pd_init_topology(struct device_node *np); |
| 16 | 16 | |
| 17 | +int dt_idle_pd_remove_topology(struct device_node *np); | |
| 18 | + | |
| 17 | 19 | struct device *dt_idle_attach_cpu(int cpu, const char *name); |
| 18 | 20 | |
| 19 | 21 | void dt_idle_detach_cpu(struct device *dev); |
| @@ -36,6 +38,11 @@ static inline int dt_idle_pd_init_topology(struct device_node *np) · 16 unmodified lines | ||
| 36 | 38 | return 0; |
| 37 | 39 | } |
| 38 | 40 | |
| 41 | +static inline int dt_idle_pd_remove_topology(struct device_node *np) | |
| 42 | +{ | |
| 43 | + return 0; | |
| 44 | +} | |
| 45 | + | |
| 39 | 46 | static inline struct device *dt_idle_attach_cpu(int cpu, const char *name) |
| 40 | 47 | { |
| 41 | 48 | return NULL; |
| @@ -121,6 +121,45 @@ static bool cxl_is_security_command(u16 opcode) · 120 unmodified lines | ||
| 121 | 121 | return false; |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | +static void cxl_set_security_cmd_enabled(struct cxl_security_state *security, | |
| 125 | + u16 opcode) | |
| 126 | +{ | |
| 127 | + switch (opcode) { | |
| 128 | + case CXL_MBOX_OP_SANITIZE: | |
| 129 | + set_bit(CXL_SEC_ENABLED_SANITIZE, security->enabled_cmds); | |
| 130 | + break; | |
| 131 | + case CXL_MBOX_OP_SECURE_ERASE: | |
| 132 | + set_bit(CXL_SEC_ENABLED_SECURE_ERASE, | |
| 133 | + security->enabled_cmds); | |
| 134 | + break; | |
| 135 | + case CXL_MBOX_OP_GET_SECURITY_STATE: | |
| 136 | + set_bit(CXL_SEC_ENABLED_GET_SECURITY_STATE, | |
| 137 | + security->enabled_cmds); | |
| 138 | + break; | |
| 139 | + case CXL_MBOX_OP_SET_PASSPHRASE: | |
| 140 | + set_bit(CXL_SEC_ENABLED_SET_PASSPHRASE, | |
| 141 | + security->enabled_cmds); | |
| 142 | + break; | |
| 143 | + case CXL_MBOX_OP_DISABLE_PASSPHRASE: | |
| 144 | + set_bit(CXL_SEC_ENABLED_DISABLE_PASSPHRASE, | |
| 145 | + security->enabled_cmds); | |
| 146 | + break; | |
| 147 | + case CXL_MBOX_OP_UNLOCK: | |
| 148 | + set_bit(CXL_SEC_ENABLED_UNLOCK, security->enabled_cmds); | |
| 149 | + break; | |
| 150 | + case CXL_MBOX_OP_FREEZE_SECURITY: | |
| 151 | + set_bit(CXL_SEC_ENABLED_FREEZE_SECURITY, | |
| 152 | + security->enabled_cmds); | |
| 153 | + break; | |
| 154 | + case CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE: | |
| 155 | + set_bit(CXL_SEC_ENABLED_PASSPHRASE_SECURE_ERASE, | |
| 156 | + security->enabled_cmds); | |
| 157 | + break; | |
| 158 | + default: | |
| 159 | + break; | |
| 160 | + } | |
| 161 | +} | |
| 162 | + | |
| 124 | 163 | static bool cxl_is_poison_command(u16 opcode) |
| 125 | 164 | { |
| 126 | 165 | #define CXL_MBOX_OP_POISON_CMDS 0x43 |
| @@ -677,7 +716,8 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel) · 550 unmodified lines | ||
| 677 | 716 | u16 opcode = le16_to_cpu(cel_entry[i].opcode); |
| 678 | 717 | struct cxl_mem_command *cmd = cxl_mem_find_command(opcode); |
| 679 | 718 | |
| 680 | − if (!cmd && !cxl_is_poison_command(opcode)) { | |
| 719 | + if (!cmd && (!cxl_is_poison_command(opcode) || | |
| 720 | + !cxl_is_security_command(opcode))) { | |
| 681 | 721 | dev_dbg(dev, |
| 682 | 722 | "Opcode 0x%04x unsupported by driver\n", opcode); |
| 683 | 723 | continue; |
| @@ -689,6 +729,9 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel) · 5 unmodified lines | ||
| 689 | 729 | if (cxl_is_poison_command(opcode)) |
| 690 | 730 | cxl_set_poison_cmd_enabled(&mds->poison, opcode); |
| 691 | 731 | |
| 732 | + if (cxl_is_security_command(opcode)) | |
| 733 | + cxl_set_security_cmd_enabled(&mds->security, opcode); | |
| 734 | + | |
| 692 | 735 | dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode); |
| 693 | 736 | } |
| 694 | 737 | } |
| @@ -477,9 +477,28 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = { · 476 unmodified lines | ||
| 477 | 477 | .attrs = cxl_memdev_pmem_attributes, |
| 478 | 478 | }; |
| 479 | 479 | |
| 480 | +static umode_t cxl_memdev_security_visible(struct kobject *kobj, | |
| 481 | + struct attribute *a, int n) | |
| 482 | +{ | |
| 483 | + struct device *dev = kobj_to_dev(kobj); | |
| 484 | + struct cxl_memdev *cxlmd = to_cxl_memdev(dev); | |
| 485 | + struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); | |
| 486 | + | |
| 487 | + if (a == &dev_attr_security_sanitize.attr && | |
| 488 | + !test_bit(CXL_SEC_ENABLED_SANITIZE, mds->security.enabled_cmds)) | |
| 489 | + return 0; | |
| 490 | + | |
| 491 | + if (a == &dev_attr_security_erase.attr && | |
| 492 | + !test_bit(CXL_SEC_ENABLED_SECURE_ERASE, mds->security.enabled_cmds)) | |
| 493 | + return 0; | |
| 494 | + | |
| 495 | + return a->mode; | |
| 496 | +} | |
| 497 | + | |
| 480 | 498 | static struct attribute_group cxl_memdev_security_attribute_group = { |
| 481 | 499 | .name = "security", |
| 482 | 500 | .attrs = cxl_memdev_security_attributes, |
| 501 | + .is_visible = cxl_memdev_security_visible, | |
| 483 | 502 | }; |
| 484 | 503 | |
| 485 | 504 | static const struct attribute_group *cxl_memdev_attribute_groups[] = { |
| @@ -244,6 +244,19 @@ enum poison_cmd_enabled_bits { · 243 unmodified lines | ||
| 244 | 244 | CXL_POISON_ENABLED_MAX |
| 245 | 245 | }; |
| 246 | 246 | |
| 247 | +/* Device enabled security commands */ | |
| 248 | +enum security_cmd_enabled_bits { | |
| 249 | + CXL_SEC_ENABLED_SANITIZE, | |
| 250 | + CXL_SEC_ENABLED_SECURE_ERASE, | |
| 251 | + CXL_SEC_ENABLED_GET_SECURITY_STATE, | |
| 252 | + CXL_SEC_ENABLED_SET_PASSPHRASE, | |
| 253 | + CXL_SEC_ENABLED_DISABLE_PASSPHRASE, | |
| 254 | + CXL_SEC_ENABLED_UNLOCK, | |
| 255 | + CXL_SEC_ENABLED_FREEZE_SECURITY, | |
| 256 | + CXL_SEC_ENABLED_PASSPHRASE_SECURE_ERASE, | |
| 257 | + CXL_SEC_ENABLED_MAX | |
| 258 | +}; | |
| 259 | + | |
| 247 | 260 | /** |
| 248 | 261 | * struct cxl_poison_state - Driver poison state info |
| 249 | 262 | * |
| @@ -346,6 +359,7 @@ struct cxl_fw_state { · 96 unmodified lines | ||
| 346 | 359 | * struct cxl_security_state - Device security state |
| 347 | 360 | * |
| 348 | 361 | * @state: state of last security operation |
| 362 | + * @enabled_cmds: All security commands enabled in the CEL | |
| 349 | 363 | * @poll: polling for sanitization is enabled, device has no mbox irq support |
| 350 | 364 | * @poll_tmo_secs: polling timeout |
| 351 | 365 | * @poll_dwork: polling work item |
| @@ -353,6 +367,7 @@ struct cxl_fw_state { · 1 unmodified line | ||
| 353 | 367 | */ |
| 354 | 368 | struct cxl_security_state { |
| 355 | 369 | unsigned long state; |
| 370 | + DECLARE_BITMAP(enabled_cmds, CXL_SEC_ENABLED_MAX); | |
| 356 | 371 | bool poll; |
| 357 | 372 | int poll_tmo_secs; |
| 358 | 373 | struct delayed_work poll_dwork; |
| @@ -434,6 +449,7 @@ struct cxl_dev_state { · 75 unmodified lines | ||
| 434 | 449 | * @next_persistent_bytes: persistent capacity change pending device reset |
| 435 | 450 | * @event: event log driver state |
| 436 | 451 | * @poison: poison driver state info |
| 452 | + * @security: security driver state info | |
| 437 | 453 | * @fw: firmware upload / activation state |
| 438 | 454 | * @mbox_send: @dev specific transport for transmitting mailbox commands |
| 439 | 455 | * |
| @@ -211,6 +211,7 @@ config FSL_DMA · 210 unmodified lines | ||
| 211 | 211 | config FSL_EDMA |
| 212 | 212 | tristate "Freescale eDMA engine support" |
| 213 | 213 | depends on OF |
| 214 | + depends on HAS_IOMEM | |
| 214 | 215 | select DMA_ENGINE |
| 215 | 216 | select DMA_VIRTUAL_CHANNELS |
| 216 | 217 | help |
| @@ -280,6 +281,7 @@ config IMX_SDMA · 63 unmodified lines | ||
| 280 | 281 | |
| 281 | 282 | config INTEL_IDMA64 |
| 282 | 283 | tristate "Intel integrated DMA 64-bit support" |
| 284 | + depends on HAS_IOMEM | |
| 283 | 285 | select DMA_ENGINE |
| 284 | 286 | select DMA_VIRTUAL_CHANNELS |
| 285 | 287 | help |
| @@ -384,9 +384,7 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq) · 383 unmodified lines | ||
| 384 | 384 | wq->threshold = 0; |
| 385 | 385 | wq->priority = 0; |
| 386 | 386 | wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; |
| 387 | − clear_bit(WQ_FLAG_DEDICATED, &wq->flags); | |
| 388 | − clear_bit(WQ_FLAG_BLOCK_ON_FAULT, &wq->flags); | |
| 389 | − clear_bit(WQ_FLAG_ATS_DISABLE, &wq->flags); | |
| 387 | + wq->flags = 0; | |
| 390 | 388 | memset(wq->name, 0, WQ_NAME_SIZE); |
| 391 | 389 | wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER; |
| 392 | 390 | idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH); |
| @@ -190,7 +190,13 @@ static int mcf_edma_probe(struct platform_device *pdev) · 189 unmodified lines | ||
| 190 | 190 | return -EINVAL; |
| 191 | 191 | } |
| 192 | 192 | |
| 193 | − chans = pdata->dma_channels; | |
| 193 | + if (!pdata->dma_channels) { | |
| 194 | + dev_info(&pdev->dev, "setting default channel number to 64"); | |
| 195 | + chans = 64; | |
| 196 | + } else { | |
| 197 | + chans = pdata->dma_channels; | |
| 198 | + } | |
| 199 | + | |
| 194 | 200 | len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans; |
| 195 | 201 | mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); |
| 196 | 202 | if (!mcf_edma) |
| @@ -202,11 +208,6 @@ static int mcf_edma_probe(struct platform_device *pdev) · 5 unmodified lines | ||
| 202 | 208 | mcf_edma->drvdata = &mcf_data; |
| 203 | 209 | mcf_edma->big_endian = 1; |
| 204 | 210 | |
| 205 | − if (!mcf_edma->n_chans) { | |
| 206 | − dev_info(&pdev->dev, "setting default channel number to 64"); | |
| 207 | − mcf_edma->n_chans = 64; | |
| 208 | − } | |
| 209 | − | |
| 210 | 211 | mutex_init(&mcf_edma->fsl_edma_mutex); |
| 211 | 212 | |
| 212 | 213 | mcf_edma->membase = devm_platform_ioremap_resource(pdev, 0); |
| @@ -192,7 +192,7 @@ struct owl_dma_pchan { · 191 unmodified lines | ||
| 192 | 192 | }; |
| 193 | 193 | |
| 194 | 194 | /** |
| 195 | − * struct owl_dma_pchan - Wrapper for DMA ENGINE channel | |
| 195 | + * struct owl_dma_vchan - Wrapper for DMA ENGINE channel | |
| 196 | 196 | * @vc: wrapped virtual channel |
| 197 | 197 | * @pchan: the physical channel utilized by this channel |
| 198 | 198 | * @txd: active transaction on this channel |
| @@ -403,6 +403,12 @@ enum desc_status { · 402 unmodified lines | ||
| 403 | 403 | * of a channel can be BUSY at any time. |
| 404 | 404 | */ |
| 405 | 405 | BUSY, |
| 406 | + /* | |
| 407 | + * Pause was called while descriptor was BUSY. Due to hardware | |
| 408 | + * limitations, only termination is possible for descriptors | |
| 409 | + * that have been paused. | |
| 410 | + */ | |
| 411 | + PAUSED, | |
| 406 | 412 | /* |
| 407 | 413 | * Sitting on the channel work_list but xfer done |
| 408 | 414 | * by PL330 core |
| @@ -2041,7 +2047,7 @@ static inline void fill_queue(struct dma_pl330_chan *pch) · 1632 unmodified lines | ||
| 2041 | 2047 | list_for_each_entry(desc, &pch->work_list, node) { |
| 2042 | 2048 | |
| 2043 | 2049 | /* If already submitted */ |
| 2044 | − if (desc->status == BUSY) | |
| 2050 | + if (desc->status == BUSY || desc->status == PAUSED) | |
| 2045 | 2051 | continue; |
| 2046 | 2052 | |
| 2047 | 2053 | ret = pl330_submit_req(pch->thread, desc); |
| @@ -2326,6 +2332,7 @@ static int pl330_pause(struct dma_chan *chan) · 278 unmodified lines | ||
| 2326 | 2332 | { |
| 2327 | 2333 | struct dma_pl330_chan *pch = to_pchan(chan); |
| 2328 | 2334 | struct pl330_dmac *pl330 = pch->dmac; |
| 2335 | + struct dma_pl330_desc *desc; | |
| 2329 | 2336 | unsigned long flags; |
| 2330 | 2337 | |
| 2331 | 2338 | pm_runtime_get_sync(pl330->ddma.dev); |
| @@ -2335,6 +2342,10 @@ static int pl330_pause(struct dma_chan *chan) · 3 unmodified lines | ||
| 2335 | 2342 | _stop(pch->thread); |
| 2336 | 2343 | spin_unlock(&pl330->lock); |
| 2337 | 2344 | |
| 2345 | + list_for_each_entry(desc, &pch->work_list, node) { | |
| 2346 | + if (desc->status == BUSY) | |
| 2347 | + desc->status = PAUSED; | |
| 2348 | + } | |
| 2338 | 2349 | spin_unlock_irqrestore(&pch->lock, flags); |
| 2339 | 2350 | pm_runtime_mark_last_busy(pl330->ddma.dev); |
| 2340 | 2351 | pm_runtime_put_autosuspend(pl330->ddma.dev); |
| @@ -2425,7 +2436,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, · 84 unmodified lines | ||
| 2425 | 2436 | else if (running && desc == running) |
| 2426 | 2437 | transferred = |
| 2427 | 2438 | pl330_get_current_xferred_count(pch, desc); |
| 2428 | − else if (desc->status == BUSY) | |
| 2439 | + else if (desc->status == BUSY || desc->status == PAUSED) | |
| 2429 | 2440 | /* |
| 2430 | 2441 | * Busy but not running means either just enqueued, |
| 2431 | 2442 | * or finished and not yet marked done |
| @@ -2442,6 +2453,9 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, · 10 unmodified lines | ||
| 2442 | 2453 | case DONE: |
| 2443 | 2454 | ret = DMA_COMPLETE; |
| 2444 | 2455 | break; |
| 2456 | + case PAUSED: | |
| 2457 | + ret = DMA_PAUSED; | |
| 2458 | + break; | |
| 2445 | 2459 | case PREP: |
| 2446 | 2460 | case BUSY: |
| 2447 | 2461 | ret = DMA_IN_PROGRESS; |
| @@ -668,6 +668,8 @@ static int xdma_set_vector_reg(struct xdma_device *xdev, u32 vec_tbl_start, · 667 unmodified lines | ||
| 668 | 668 | val |= irq_start << shift; |
| 669 | 669 | irq_start++; |
| 670 | 670 | irq_num--; |
| 671 | + if (!irq_num) | |
| 672 | + break; | |
| 671 | 673 | } |
| 672 | 674 | |
| 673 | 675 | /* write IRQ register */ |
| @@ -715,7 +717,7 @@ static int xdma_irq_init(struct xdma_device *xdev) · 41 unmodified lines | ||
| 715 | 717 | ret = request_irq(irq, xdma_channel_isr, 0, |
| 716 | 718 | "xdma-c2h-channel", &xdev->c2h_chans[j]); |
| 717 | 719 | if (ret) { |
| 718 | − xdma_err(xdev, "H2C channel%d request irq%d failed: %d", | |
| 720 | + xdma_err(xdev, "C2H channel%d request irq%d failed: %d", | |
| 719 | 721 | j, irq, ret); |
| 720 | 722 | goto failed_init_c2h; |
| 721 | 723 | } |
| @@ -892,7 +894,7 @@ static int xdma_probe(struct platform_device *pdev) · 170 unmodified lines | ||
| 892 | 894 | } |
| 893 | 895 | |
| 894 | 896 | reg_base = devm_ioremap_resource(&pdev->dev, res); |
| 895 | − if (!reg_base) { | |
| 897 | + if (IS_ERR(reg_base)) { | |
| 896 | 898 | xdma_err(xdev, "ioremap failed"); |
| 897 | 899 | goto failed; |
| 898 | 900 | } |
| @@ -166,8 +166,10 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, · 165 unmodified lines | ||
| 166 | 166 | return -ENOMEM; |
| 167 | 167 | |
| 168 | 168 | shmem = of_parse_phandle(cdev->of_node, "shmem", idx); |
| 169 | − if (!of_device_is_compatible(shmem, "arm,scmi-shmem")) | |
| 169 | + if (!of_device_is_compatible(shmem, "arm,scmi-shmem")) { | |
| 170 | + of_node_put(shmem); | |
| 170 | 171 | return -ENXIO; |
| 172 | + } | |
| 171 | 173 | |
| 172 | 174 | ret = of_address_to_resource(shmem, 0, &res); |
| 173 | 175 | of_node_put(shmem); |
| @@ -818,10 +818,13 @@ static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp, · 817 unmodified lines | ||
| 818 | 818 | * before sending it with a single RAW xfer. |
| 819 | 819 | */ |
| 820 | 820 | if (rd->tx_size < rd->tx_req_size) { |
| 821 | − size_t cnt; | |
| 821 | + ssize_t cnt; | |
| 822 | 822 | |
| 823 | 823 | cnt = simple_write_to_buffer(rd->tx.buf, rd->tx.len, ppos, |
| 824 | 824 | buf, count); |
| 825 | + if (cnt < 0) | |
| 826 | + return cnt; | |
| 827 | + | |
| 825 | 828 | rd->tx_size += cnt; |
| 826 | 829 | if (cnt < count) |
| 827 | 830 | return cnt; |
| @@ -40,6 +40,7 @@ · 39 unmodified lines | ||
| 40 | 40 | /** |
| 41 | 41 | * struct scmi_smc - Structure representing a SCMI smc transport |
| 42 | 42 | * |
| 43 | + * @irq: An optional IRQ for completion | |
| 43 | 44 | * @cinfo: SCMI channel info |
| 44 | 45 | * @shmem: Transmit/Receive shared memory area |
| 45 | 46 | * @shmem_lock: Lock to protect access to Tx/Rx shared memory area. |
| @@ -52,6 +53,7 @@ · 6 unmodified lines | ||
| 52 | 53 | */ |
| 53 | 54 | |
| 54 | 55 | struct scmi_smc { |
| 56 | + int irq; | |
| 55 | 57 | struct scmi_chan_info *cinfo; |
| 56 | 58 | struct scmi_shared_mem __iomem *shmem; |
| 57 | 59 | /* Protect access to shmem area */ |
| @@ -127,7 +129,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, · 69 unmodified lines | ||
| 127 | 129 | struct resource res; |
| 128 | 130 | struct device_node *np; |
| 129 | 131 | u32 func_id; |
| 130 | − int ret, irq; | |
| 132 | + int ret; | |
| 131 | 133 | |
| 132 | 134 | if (!tx) |
| 133 | 135 | return -ENODEV; |
| @@ -137,8 +139,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, · 3 unmodified lines | ||
| 137 | 139 | return -ENOMEM; |
| 138 | 140 | |
| 139 | 141 | np = of_parse_phandle(cdev->of_node, "shmem", 0); |
| 140 | − if (!of_device_is_compatible(np, "arm,scmi-shmem")) | |
| 142 | + if (!of_device_is_compatible(np, "arm,scmi-shmem")) { | |
| 143 | + of_node_put(np); | |
| 141 | 144 | return -ENXIO; |
| 145 | + } | |
| 142 | 146 | |
| 143 | 147 | ret = of_address_to_resource(np, 0, &res); |
| 144 | 148 | of_node_put(np); |
| @@ -167,11 +171,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, · 22 unmodified lines | ||
| 167 | 171 | * completion of a message is signaled by an interrupt rather than by |
| 168 | 172 | * the return of the SMC call. |
| 169 | 173 | */ |
| 170 | − irq = of_irq_get_byname(cdev->of_node, "a2p"); | |
| 171 | − if (irq > 0) { | |
| 172 | − ret = devm_request_irq(dev, irq, smc_msg_done_isr, | |
| 173 | − IRQF_NO_SUSPEND, | |
| 174 | − dev_name(dev), scmi_info); | |
| 174 | + scmi_info->irq = of_irq_get_byname(cdev->of_node, "a2p"); | |
| 175 | + if (scmi_info->irq > 0) { | |
| 176 | + ret = request_irq(scmi_info->irq, smc_msg_done_isr, | |
| 177 | + IRQF_NO_SUSPEND, dev_name(dev), scmi_info); | |
| 175 | 178 | if (ret) { |
| 176 | 179 | dev_err(dev, "failed to setup SCMI smc irq\n"); |
| 177 | 180 | return ret; |
| @@ -193,6 +196,10 @@ static int smc_chan_free(int id, void *p, void *data) · 15 unmodified lines | ||
| 193 | 196 | struct scmi_chan_info *cinfo = p; |
| 194 | 197 | struct scmi_smc *scmi_info = cinfo->transport_info; |
| 195 | 198 | |
| 199 | + /* Ignore any possible further reception on the IRQ path */ | |
| 200 | + if (scmi_info->irq > 0) | |
| 201 | + free_irq(scmi_info->irq, scmi_info); | |
| 202 | + | |
| 196 | 203 | cinfo->transport_info = NULL; |
| 197 | 204 | scmi_info->cinfo = NULL; |
| 198 | 205 | |
| @@ -34,7 +34,6 @@ static struct soc_device_attribute *soc_dev_attr; · 33 unmodified lines | ||
| 34 | 34 | |
| 35 | 35 | static int __init smccc_soc_init(void) |
| 36 | 36 | { |
| 37 | − struct arm_smccc_res res; | |
| 38 | 37 | int soc_id_rev, soc_id_version; |
| 39 | 38 | static char soc_id_str[20], soc_id_rev_str[12]; |
| 40 | 39 | static char soc_id_jep106_id_str[12]; |
| @@ -49,13 +48,13 @@ static int __init smccc_soc_init(void) · 8 unmodified lines | ||
| 49 | 48 | } |
| 50 | 49 | |
| 51 | 50 | if (soc_id_version < 0) { |
| 52 | − pr_err("ARCH_SOC_ID(0) returned error: %lx\n", res.a0); | |
| 51 | + pr_err("Invalid SoC Version: %x\n", soc_id_version); | |
| 53 | 52 | return -EINVAL; |
| 54 | 53 | } |
| 55 | 54 | |
| 56 | 55 | soc_id_rev = arm_smccc_get_soc_id_revision(); |
| 57 | 56 | if (soc_id_rev < 0) { |
| 58 | − pr_err("ARCH_SOC_ID(1) returned error: %lx\n", res.a0); | |
| 57 | + pr_err("Invalid SoC Revision: %x\n", soc_id_rev); | |
| 59 | 58 | return -EINVAL; |
| 60 | 59 | } |
| 61 | 60 | |
| @@ -429,6 +429,7 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev) · 428 unmodified lines | ||
| 429 | 429 | gc->set_config = gpio_sim_set_config; |
| 430 | 430 | gc->to_irq = gpio_sim_to_irq; |
| 431 | 431 | gc->free = gpio_sim_free; |
| 432 | + gc->can_sleep = true; | |
| 432 | 433 | |
| 433 | 434 | ret = devm_gpiochip_add_data(dev, gc, chip); |
| 434 | 435 | if (ret) |
| @@ -18,7 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/spinlock.h> |
| 19 | 19 | #include <linux/types.h> |
| 20 | 20 | |
| 21 | −#define WS16C48_EXTENT 10 | |
| 21 | +#define WS16C48_EXTENT 11 | |
| 22 | 22 | #define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT) |
| 23 | 23 | |
| 24 | 24 | static unsigned int base[MAX_NUM_WS16C48]; |
| @@ -1296,6 +1296,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, · 1295 unmodified lines | ||
| 1296 | 1296 | void amdgpu_device_pci_config_reset(struct amdgpu_device *adev); |
| 1297 | 1297 | int amdgpu_device_pci_reset(struct amdgpu_device *adev); |
| 1298 | 1298 | bool amdgpu_device_need_post(struct amdgpu_device *adev); |
| 1299 | +bool amdgpu_sg_display_supported(struct amdgpu_device *adev); | |
| 1299 | 1300 | bool amdgpu_device_pcie_dynamic_switching_supported(void); |
| 1300 | 1301 | bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev); |
| 1301 | 1302 | bool amdgpu_device_aspm_support_quirk(void); |
| @@ -295,7 +295,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p, · 294 unmodified lines | ||
| 295 | 295 | |
| 296 | 296 | if (!p->gang_size) { |
| 297 | 297 | ret = -EINVAL; |
| 298 | − goto free_partial_kdata; | |
| 298 | + goto free_all_kdata; | |
| 299 | 299 | } |
| 300 | 300 | |
| 301 | 301 | for (i = 0; i < p->gang_size; ++i) { |
| @@ -1458,6 +1458,32 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev) · 1457 unmodified lines | ||
| 1458 | 1458 | return true; |
| 1459 | 1459 | } |
| 1460 | 1460 | |
| 1461 | +/* | |
| 1462 | + * On APUs with >= 64GB white flickering has been observed w/ SG enabled. | |
| 1463 | + * Disable S/G on such systems until we have a proper fix. | |
| 1464 | + * https://gitlab.freedesktop.org/drm/amd/-/issues/2354 | |
| 1465 | + * https://gitlab.freedesktop.org/drm/amd/-/issues/2735 | |
| 1466 | + */ | |
| 1467 | +bool amdgpu_sg_display_supported(struct amdgpu_device *adev) | |
| 1468 | +{ | |
| 1469 | + switch (amdgpu_sg_display) { | |
| 1470 | + case -1: | |
| 1471 | + break; | |
| 1472 | + case 0: | |
| 1473 | + return false; | |
| 1474 | + case 1: | |
| 1475 | + return true; | |
| 1476 | + default: | |
| 1477 | + return false; | |
| 1478 | + } | |
| 1479 | + if ((totalram_pages() << (PAGE_SHIFT - 10)) + | |
| 1480 | + (adev->gmc.real_vram_size / 1024) >= 64000000) { | |
| 1481 | + DRM_WARN("Disabling S/G due to >=64GB RAM\n"); | |
| 1482 | + return false; | |
| 1483 | + } | |
| 1484 | + return true; | |
| 1485 | +} | |
| 1486 | + | |
| 1461 | 1487 | /* |
| 1462 | 1488 | * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic |
| 1463 | 1489 | * speed switching. Until we have confirmation from Intel that a specific host |
| @@ -471,8 +471,12 @@ static void gfx_v11_0_check_fw_cp_gfx_shadow(struct amdgpu_device *adev) · 470 unmodified lines | ||
| 471 | 471 | case IP_VERSION(11, 0, 3): |
| 472 | 472 | if ((adev->gfx.me_fw_version >= 1505) && |
| 473 | 473 | (adev->gfx.pfp_fw_version >= 1600) && |
| 474 | − (adev->gfx.mec_fw_version >= 512)) | |
| 475 | − adev->gfx.cp_gfx_shadow = true; | |
| 474 | + (adev->gfx.mec_fw_version >= 512)) { | |
| 475 | + if (amdgpu_sriov_vf(adev)) | |
| 476 | + adev->gfx.cp_gfx_shadow = true; | |
| 477 | + else | |
| 478 | + adev->gfx.cp_gfx_shadow = false; | |
| 479 | + } | |
| 476 | 480 | break; |
| 477 | 481 | default: |
| 478 | 482 | adev->gfx.cp_gfx_shadow = false; |
| @@ -137,14 +137,15 @@ static int psp_v13_0_wait_for_bootloader(struct psp_context *psp) · 136 unmodified lines | ||
| 137 | 137 | int ret; |
| 138 | 138 | int retry_loop; |
| 139 | 139 | |
| 140 | + /* Wait for bootloader to signify that it is ready having bit 31 of | |
| 141 | + * C2PMSG_35 set to 1. All other bits are expected to be cleared. | |
| 142 | + * If there is an error in processing command, bits[7:0] will be set. | |
| 143 | + * This is applicable for PSP v13.0.6 and newer. | |
| 144 | + */ | |
| 140 | 145 | for (retry_loop = 0; retry_loop < 10; retry_loop++) { |
| 141 | − /* Wait for bootloader to signify that is | |
| 142 | − ready having bit 31 of C2PMSG_35 set to 1 */ | |
| 143 | − ret = psp_wait_for(psp, | |
| 144 | − SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35), | |
| 145 | − 0x80000000, | |
| 146 | − 0x80000000, | |
| 147 | − false); | |
| 146 | + ret = psp_wait_for( | |
| 147 | + psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35), | |
| 148 | + 0x80000000, 0xffffffff, false); | |
| 148 | 149 | |
| 149 | 150 | if (ret == 0) |
| 150 | 151 | return 0; |
| @@ -1543,11 +1543,7 @@ static bool kfd_ignore_crat(void) · 1542 unmodified lines | ||
| 1543 | 1543 | if (ignore_crat) |
| 1544 | 1544 | return true; |
| 1545 | 1545 | |
| 1546 | −#ifndef KFD_SUPPORT_IOMMU_V2 | |
| 1547 | 1546 | ret = true; |
| 1548 | −#else | |
| 1549 | − ret = false; | |
| 1550 | −#endif | |
| 1551 | 1547 | |
| 1552 | 1548 | return ret; |
| 1553 | 1549 | } |
| @@ -194,11 +194,6 @@ static void kfd_device_info_init(struct kfd_dev *kfd, · 193 unmodified lines | ||
| 194 | 194 | |
| 195 | 195 | kfd_device_info_set_event_interrupt_class(kfd); |
| 196 | 196 | |
| 197 | − /* Raven */ | |
| 198 | − if (gc_version == IP_VERSION(9, 1, 0) || | |
| 199 | − gc_version == IP_VERSION(9, 2, 2)) | |
| 200 | − kfd->device_info.needs_iommu_device = true; | |
| 201 | − | |
| 202 | 197 | if (gc_version < IP_VERSION(11, 0, 0)) { |
| 203 | 198 | /* Navi2x+, Navi1x+ */ |
| 204 | 199 | if (gc_version == IP_VERSION(10, 3, 6)) |
| @@ -233,10 +228,6 @@ static void kfd_device_info_init(struct kfd_dev *kfd, · 28 unmodified lines | ||
| 233 | 228 | asic_type != CHIP_TONGA) |
| 234 | 229 | kfd->device_info.supports_cwsr = true; |
| 235 | 230 | |
| 236 | − if (asic_type == CHIP_KAVERI || | |
| 237 | − asic_type == CHIP_CARRIZO) | |
| 238 | − kfd->device_info.needs_iommu_device = true; | |
| 239 | − | |
| 240 | 231 | if (asic_type != CHIP_HAWAII && !vf) |
| 241 | 232 | kfd->device_info.needs_pci_atomics = true; |
| 242 | 233 | } |
| @@ -249,7 +240,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) · 6 unmodified lines | ||
| 249 | 240 | uint32_t gfx_target_version = 0; |
| 250 | 241 | |
| 251 | 242 | switch (adev->asic_type) { |
| 252 | −#ifdef KFD_SUPPORT_IOMMU_V2 | |
| 253 | 243 | #ifdef CONFIG_DRM_AMDGPU_CIK |
| 254 | 244 | case CHIP_KAVERI: |
| 255 | 245 | gfx_target_version = 70000; |
| @@ -262,7 +252,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) · 6 unmodified lines | ||
| 262 | 252 | if (!vf) |
| 263 | 253 | f2g = &gfx_v8_kfd2kgd; |
| 264 | 254 | break; |
| 265 | −#endif | |
| 266 | 255 | #ifdef CONFIG_DRM_AMDGPU_CIK |
| 267 | 256 | case CHIP_HAWAII: |
| 268 | 257 | gfx_target_version = 70001; |
| @@ -298,7 +287,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) · 29 unmodified lines | ||
| 298 | 287 | gfx_target_version = 90000; |
| 299 | 288 | f2g = &gfx_v9_kfd2kgd; |
| 300 | 289 | break; |
| 301 | −#ifdef KFD_SUPPORT_IOMMU_V2 | |
| 302 | 290 | /* Raven */ |
| 303 | 291 | case IP_VERSION(9, 1, 0): |
| 304 | 292 | case IP_VERSION(9, 2, 2): |
| @@ -306,7 +294,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) · 1 unmodified line | ||
| 306 | 294 | if (!vf) |
| 307 | 295 | f2g = &gfx_v9_kfd2kgd; |
| 308 | 296 | break; |
| 309 | −#endif | |
| 310 | 297 | /* Vega12 */ |
| 311 | 298 | case IP_VERSION(9, 2, 1): |
| 312 | 299 | gfx_target_version = 90004; |
| @@ -2538,18 +2538,12 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev) · 2537 unmodified lines | ||
| 2538 | 2538 | } |
| 2539 | 2539 | |
| 2540 | 2540 | switch (dev->adev->asic_type) { |
| 2541 | − case CHIP_CARRIZO: | |
| 2542 | − device_queue_manager_init_vi(&dqm->asic_ops); | |
| 2543 | − break; | |
| 2544 | − | |
| 2545 | 2541 | case CHIP_KAVERI: |
| 2546 | − device_queue_manager_init_cik(&dqm->asic_ops); | |
| 2547 | − break; | |
| 2548 | − | |
| 2549 | 2542 | case CHIP_HAWAII: |
| 2550 | 2543 | device_queue_manager_init_cik_hawaii(&dqm->asic_ops); |
| 2551 | 2544 | break; |
| 2552 | 2545 | |
| 2546 | + case CHIP_CARRIZO: | |
| 2553 | 2547 | case CHIP_TONGA: |
| 2554 | 2548 | case CHIP_FIJI: |
| 2555 | 2549 | case CHIP_POLARIS10: |
| @@ -1638,9 +1638,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) · 1637 unmodified lines | ||
| 1638 | 1638 | } |
| 1639 | 1639 | break; |
| 1640 | 1640 | } |
| 1641 | − if (init_data.flags.gpu_vm_support && | |
| 1642 | − (amdgpu_sg_display == 0)) | |
| 1643 | − init_data.flags.gpu_vm_support = false; | |
| 1641 | + if (init_data.flags.gpu_vm_support) | |
| 1642 | + init_data.flags.gpu_vm_support = amdgpu_sg_display_supported(adev); | |
| 1644 | 1643 | |
| 1645 | 1644 | if (init_data.flags.gpu_vm_support) |
| 1646 | 1645 | adev->mode_info.gpu_vm_support = true; |
| @@ -1320,7 +1320,7 @@ int compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, · 1319 unmodified lines | ||
| 1320 | 1320 | if (computed_streams[i]) |
| 1321 | 1321 | continue; |
| 1322 | 1322 | |
| 1323 | − if (!res_pool->funcs->remove_stream_from_ctx || | |
| 1323 | + if (res_pool->funcs->remove_stream_from_ctx && | |
| 1324 | 1324 | res_pool->funcs->remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK) |
| 1325 | 1325 | return -EINVAL; |
| 1326 | 1326 | |
| @@ -777,7 +777,8 @@ void dce110_edp_wait_for_hpd_ready( · 776 unmodified lines | ||
| 777 | 777 | dal_gpio_destroy_irq(&hpd); |
| 778 | 778 | |
| 779 | 779 | /* ensure that the panel is detected */ |
| 780 | − ASSERT(edp_hpd_high); | |
| 780 | + if (!edp_hpd_high) | |
| 781 | + DC_LOG_DC("%s: wait timed out!\n", __func__); | |
| 781 | 782 | } |
| 782 | 783 | |
| 783 | 784 | void dce110_edp_power_control( |
| @@ -357,8 +357,11 @@ void dpp3_set_cursor_attributes( · 356 unmodified lines | ||
| 357 | 357 | int cur_rom_en = 0; |
| 358 | 358 | |
| 359 | 359 | if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA || |
| 360 | − color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) | |
| 361 | − cur_rom_en = 1; | |
| 360 | + color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) { | |
| 361 | + if (cursor_attributes->attribute_flags.bits.ENABLE_CURSOR_DEGAMMA) { | |
| 362 | + cur_rom_en = 1; | |
| 363 | + } | |
| 364 | + } | |
| 362 | 365 | |
| 363 | 366 | REG_UPDATE_3(CURSOR0_CONTROL, |
| 364 | 367 | CUR0_MODE, color_format, |
| @@ -1581,9 +1581,9 @@ static int smu_disable_dpms(struct smu_context *smu) · 1580 unmodified lines | ||
| 1581 | 1581 | |
| 1582 | 1582 | /* |
| 1583 | 1583 | * For SMU 13.0.4/11, PMFW will handle the features disablement properly |
| 1584 | − * for gpu reset case. Driver involvement is unnecessary. | |
| 1584 | + * for gpu reset and S0i3 cases. Driver involvement is unnecessary. | |
| 1585 | 1585 | */ |
| 1586 | − if (amdgpu_in_reset(adev)) { | |
| 1586 | + if (amdgpu_in_reset(adev) || adev->in_s0ix) { | |
| 1587 | 1587 | switch (adev->ip_versions[MP1_HWIP][0]) { |
| 1588 | 1588 | case IP_VERSION(13, 0, 4): |
| 1589 | 1589 | case IP_VERSION(13, 0, 11): |
| @@ -331,11 +331,13 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu) · 330 unmodified lines | ||
| 331 | 331 | struct smu_13_0_0_powerplay_table *powerplay_table = |
| 332 | 332 | table_context->power_play_table; |
| 333 | 333 | struct smu_baco_context *smu_baco = &smu->smu_baco; |
| 334 | +#if 0 | |
| 334 | 335 | PPTable_t *pptable = smu->smu_table.driver_pptable; |
| 335 | 336 | const OverDriveLimits_t * const overdrive_upperlimits = |
| 336 | 337 | &pptable->SkuTable.OverDriveLimitsBasicMax; |
| 337 | 338 | const OverDriveLimits_t * const overdrive_lowerlimits = |
| 338 | 339 | &pptable->SkuTable.OverDriveLimitsMin; |
| 340 | +#endif | |
| 339 | 341 | |
| 340 | 342 | if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC) |
| 341 | 343 | smu->dc_controlled_by_gpio = true; |
| @@ -347,18 +349,27 @@ static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu) · 5 unmodified lines | ||
| 347 | 349 | if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO) |
| 348 | 350 | smu_baco->maco_support = true; |
| 349 | 351 | |
| 352 | + /* | |
| 353 | + * We are in the transition to a new OD mechanism. | |
| 354 | + * Disable the OD feature support for SMU13 temporarily. | |
| 355 | + * TODO: get this reverted when new OD mechanism online | |
| 356 | + */ | |
| 357 | +#if 0 | |
| 350 | 358 | if (!overdrive_lowerlimits->FeatureCtrlMask || |
| 351 | 359 | !overdrive_upperlimits->FeatureCtrlMask) |
| 352 | 360 | smu->od_enabled = false; |
| 353 | 361 | |
| 354 | − table_context->thermal_controller_type = | |
| 355 | − powerplay_table->thermal_controller_type; | |
| 356 | − | |
| 357 | 362 | /* |
| 358 | 363 | * Instead of having its own buffer space and get overdrive_table copied, |
| 359 | 364 | * smu->od_settings just points to the actual overdrive_table |
| 360 | 365 | */ |
| 361 | 366 | smu->od_settings = &powerplay_table->overdrive_table; |
| 367 | +#else | |
| 368 | + smu->od_enabled = false; | |
| 369 | +#endif | |
| 370 | + | |
| 371 | + table_context->thermal_controller_type = | |
| 372 | + powerplay_table->thermal_controller_type; | |
| 362 | 373 | |
| 363 | 374 | return 0; |
| 364 | 375 | } |
| @@ -1140,7 +1151,6 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu, · 775 unmodified lines | ||
| 1140 | 1151 | (OverDriveTableExternal_t *)smu->smu_table.overdrive_table; |
| 1141 | 1152 | struct smu_13_0_dpm_table *single_dpm_table; |
| 1142 | 1153 | struct smu_13_0_pcie_table *pcie_table; |
| 1143 | − const int link_width[] = {0, 1, 2, 4, 8, 12, 16}; | |
| 1144 | 1154 | uint32_t gen_speed, lane_width; |
| 1145 | 1155 | int i, curr_freq, size = 0; |
| 1146 | 1156 | int32_t min_value, max_value; |
| @@ -1256,7 +1266,7 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu, · 109 unmodified lines | ||
| 1256 | 1266 | (pcie_table->pcie_lane[i] == 6) ? "x16" : "", |
| 1257 | 1267 | pcie_table->clk_freq[i], |
| 1258 | 1268 | (gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) && |
| 1259 | − (lane_width == DECODE_LANE_WIDTH(link_width[pcie_table->pcie_lane[i]])) ? | |
| 1269 | + (lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ? | |
| 1260 | 1270 | "*" : ""); |
| 1261 | 1271 | break; |
| 1262 | 1272 | |
| @@ -1993,9 +1993,8 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table · 1992 unmodified lines | ||
| 1993 | 1993 | |
| 1994 | 1994 | gpu_metrics->average_socket_power = |
| 1995 | 1995 | SMUQ10_TO_UINT(metrics->SocketPower); |
| 1996 | − /* Energy is reported in 15.625mJ units */ | |
| 1997 | − gpu_metrics->energy_accumulator = | |
| 1998 | − SMUQ10_TO_UINT(metrics->SocketEnergyAcc); | |
| 1996 | + /* Energy counter reported in 15.259uJ (2^-16) units */ | |
| 1997 | + gpu_metrics->energy_accumulator = metrics->SocketEnergyAcc; | |
| 1999 | 1998 | |
| 2000 | 1999 | gpu_metrics->current_gfxclk = |
| 2001 | 2000 | SMUQ10_TO_UINT(metrics->GfxclkFrequency[xcc0]); |
| @@ -323,10 +323,12 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu) · 322 unmodified lines | ||
| 323 | 323 | struct smu_baco_context *smu_baco = &smu->smu_baco; |
| 324 | 324 | PPTable_t *smc_pptable = table_context->driver_pptable; |
| 325 | 325 | BoardTable_t *BoardTable = &smc_pptable->BoardTable; |
| 326 | +#if 0 | |
| 326 | 327 | const OverDriveLimits_t * const overdrive_upperlimits = |
| 327 | 328 | &smc_pptable->SkuTable.OverDriveLimitsBasicMax; |
| 328 | 329 | const OverDriveLimits_t * const overdrive_lowerlimits = |
| 329 | 330 | &smc_pptable->SkuTable.OverDriveLimitsMin; |
| 331 | +#endif | |
| 330 | 332 | |
| 331 | 333 | if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC) |
| 332 | 334 | smu->dc_controlled_by_gpio = true; |
| @@ -338,18 +340,22 @@ static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu) · 5 unmodified lines | ||
| 338 | 340 | if (smu_baco->platform_support && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled)) |
| 339 | 341 | smu_baco->maco_support = true; |
| 340 | 342 | |
| 343 | +#if 0 | |
| 341 | 344 | if (!overdrive_lowerlimits->FeatureCtrlMask || |
| 342 | 345 | !overdrive_upperlimits->FeatureCtrlMask) |
| 343 | 346 | smu->od_enabled = false; |
| 344 | 347 | |
| 345 | − table_context->thermal_controller_type = | |
| 346 | − powerplay_table->thermal_controller_type; | |
| 347 | − | |
| 348 | 348 | /* |
| 349 | 349 | * Instead of having its own buffer space and get overdrive_table copied, |
| 350 | 350 | * smu->od_settings just points to the actual overdrive_table |
| 351 | 351 | */ |
| 352 | 352 | smu->od_settings = &powerplay_table->overdrive_table; |
| 353 | +#else | |
| 354 | + smu->od_enabled = false; | |
| 355 | +#endif | |
| 356 | + | |
| 357 | + table_context->thermal_controller_type = | |
| 358 | + powerplay_table->thermal_controller_type; | |
| 353 | 359 | |
| 354 | 360 | return 0; |
| 355 | 361 | } |
| @@ -2517,9 +2517,11 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data) · 2516 unmodified lines | ||
| 2517 | 2517 | }; |
| 2518 | 2518 | int int_status[3], i; |
| 2519 | 2519 | |
| 2520 | − if (it6505->enable_drv_hold || pm_runtime_get_if_in_use(dev) <= 0) | |
| 2520 | + if (it6505->enable_drv_hold || !it6505->powered) | |
| 2521 | 2521 | return IRQ_HANDLED; |
| 2522 | 2522 | |
| 2523 | + pm_runtime_get_sync(dev); | |
| 2524 | + | |
| 2523 | 2525 | int_status[0] = it6505_read(it6505, INT_STATUS_01); |
| 2524 | 2526 | int_status[1] = it6505_read(it6505, INT_STATUS_02); |
| 2525 | 2527 | int_status[2] = it6505_read(it6505, INT_STATUS_03); |
| @@ -774,9 +774,7 @@ static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611, · 773 unmodified lines | ||
| 774 | 774 | dsi->lanes = 4; |
| 775 | 775 | dsi->format = MIPI_DSI_FMT_RGB888; |
| 776 | 776 | dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | |
| 777 | − MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA | | |
| 778 | − MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP | | |
| 779 | − MIPI_DSI_MODE_NO_EOT_PACKET; | |
| 777 | + MIPI_DSI_MODE_VIDEO_HSE; | |
| 780 | 778 | |
| 781 | 779 | ret = devm_mipi_dsi_attach(dev, dsi); |
| 782 | 780 | if (ret < 0) { |
| @@ -623,7 +623,13 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct · 622 unmodified lines | ||
| 623 | 623 | int ret; |
| 624 | 624 | |
| 625 | 625 | if (obj->import_attach) { |
| 626 | + /* Reset both vm_ops and vm_private_data, so we don't end up with | |
| 627 | + * vm_ops pointing to our implementation if the dma-buf backend | |
| 628 | + * doesn't set those fields. | |
| 629 | + */ | |
| 626 | 630 | vma->vm_private_data = NULL; |
| 631 | + vma->vm_ops = NULL; | |
| 632 | + | |
| 627 | 633 | ret = dma_buf_mmap(obj->dma_buf, vma, 0); |
| 628 | 634 | |
| 629 | 635 | /* Drop the reference drm_gem_mmap_obj() acquired.*/ |
| @@ -165,14 +165,60 @@ static u32 preparser_disable(bool state) · 164 unmodified lines | ||
| 165 | 165 | return MI_ARB_CHECK | 1 << 8 | state; |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | −u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv_reg) | |
| 168 | +static i915_reg_t gen12_get_aux_inv_reg(struct intel_engine_cs *engine) | |
| 169 | 169 | { |
| 170 | − u32 gsi_offset = gt->uncore->gsi_offset; | |
| 170 | + switch (engine->id) { | |
| 171 | + case RCS0: | |
| 172 | + return GEN12_CCS_AUX_INV; | |
| 173 | + case BCS0: | |
| 174 | + return GEN12_BCS0_AUX_INV; | |
| 175 | + case VCS0: | |
| 176 | + return GEN12_VD0_AUX_INV; | |
| 177 | + case VCS2: | |
| 178 | + return GEN12_VD2_AUX_INV; | |
| 179 | + case VECS0: | |
| 180 | + return GEN12_VE0_AUX_INV; | |
| 181 | + case CCS0: | |
| 182 | + return GEN12_CCS0_AUX_INV; | |
| 183 | + default: | |
| 184 | + return INVALID_MMIO_REG; | |
| 185 | + } | |
| 186 | +} | |
| 187 | + | |
| 188 | +static bool gen12_needs_ccs_aux_inv(struct intel_engine_cs *engine) | |
| 189 | +{ | |
| 190 | + i915_reg_t reg = gen12_get_aux_inv_reg(engine); | |
| 191 | + | |
| 192 | + if (IS_PONTEVECCHIO(engine->i915)) | |
| 193 | + return false; | |
| 194 | + | |
| 195 | + /* | |
| 196 | + * So far platforms supported by i915 having flat ccs do not require | |
| 197 | + * AUX invalidation. Check also whether the engine requires it. | |
| 198 | + */ | |
| 199 | + return i915_mmio_reg_valid(reg) && !HAS_FLAT_CCS(engine->i915); | |
| 200 | +} | |
| 201 | + | |
| 202 | +u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs) | |
| 203 | +{ | |
| 204 | + i915_reg_t inv_reg = gen12_get_aux_inv_reg(engine); | |
| 205 | + u32 gsi_offset = engine->gt->uncore->gsi_offset; | |
| 206 | + | |
| 207 | + if (!gen12_needs_ccs_aux_inv(engine)) | |
| 208 | + return cs; | |
| 171 | 209 | |
| 172 | 210 | *cs++ = MI_LOAD_REGISTER_IMM(1) | MI_LRI_MMIO_REMAP_EN; |
| 173 | 211 | *cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset; |
| 174 | 212 | *cs++ = AUX_INV; |
| 175 | − *cs++ = MI_NOOP; | |
| 213 | + | |
| 214 | + *cs++ = MI_SEMAPHORE_WAIT_TOKEN | | |
| 215 | + MI_SEMAPHORE_REGISTER_POLL | | |
| 216 | + MI_SEMAPHORE_POLL | | |
| 217 | + MI_SEMAPHORE_SAD_EQ_SDD; | |
| 218 | + *cs++ = 0; | |
| 219 | + *cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset; | |
| 220 | + *cs++ = 0; | |
| 221 | + *cs++ = 0; | |
| 176 | 222 | |
| 177 | 223 | return cs; |
| 178 | 224 | } |
| @@ -202,8 +248,13 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) · 23 unmodified lines | ||
| 202 | 248 | { |
| 203 | 249 | struct intel_engine_cs *engine = rq->engine; |
| 204 | 250 | |
| 205 | − if (mode & EMIT_FLUSH) { | |
| 206 | − u32 flags = 0; | |
| 251 | + /* | |
| 252 | + * On Aux CCS platforms the invalidation of the Aux | |
| 253 | + * table requires quiescing memory traffic beforehand | |
| 254 | + */ | |
| 255 | + if (mode & EMIT_FLUSH || gen12_needs_ccs_aux_inv(engine)) { | |
| 256 | + u32 bit_group_0 = 0; | |
| 257 | + u32 bit_group_1 = 0; | |
| 207 | 258 | int err; |
| 208 | 259 | u32 *cs; |
| 209 | 260 | |
| @@ -211,32 +262,40 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) · 1 unmodified line | ||
| 211 | 262 | if (err) |
| 212 | 263 | return err; |
| 213 | 264 | |
| 214 | − flags |= PIPE_CONTROL_TILE_CACHE_FLUSH; | |
| 215 | − flags |= PIPE_CONTROL_FLUSH_L3; | |
| 216 | − flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; | |
| 217 | − flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; | |
| 265 | + bit_group_0 |= PIPE_CONTROL0_HDC_PIPELINE_FLUSH; | |
| 266 | + | |
| 267 | + /* | |
| 268 | + * When required, in MTL and beyond platforms we | |
| 269 | + * need to set the CCS_FLUSH bit in the pipe control | |
| 270 | + */ | |
| 271 | + if (GRAPHICS_VER_FULL(rq->i915) >= IP_VER(12, 70)) | |
| 272 | + bit_group_0 |= PIPE_CONTROL_CCS_FLUSH; | |
| 273 | + | |
| 274 | + bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH; | |
| 275 | + bit_group_1 |= PIPE_CONTROL_FLUSH_L3; | |
| 276 | + bit_group_1 |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; | |
| 277 | + bit_group_1 |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; | |
| 218 | 278 | /* Wa_1409600907:tgl,adl-p */ |
| 219 | − flags |= PIPE_CONTROL_DEPTH_STALL; | |
| 220 | − flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; | |
| 221 | − flags |= PIPE_CONTROL_FLUSH_ENABLE; | |
| 279 | + bit_group_1 |= PIPE_CONTROL_DEPTH_STALL; | |
| 280 | + bit_group_1 |= PIPE_CONTROL_DC_FLUSH_ENABLE; | |
| 281 | + bit_group_1 |= PIPE_CONTROL_FLUSH_ENABLE; | |
| 222 | 282 | |
| 223 | − flags |= PIPE_CONTROL_STORE_DATA_INDEX; | |
| 224 | − flags |= PIPE_CONTROL_QW_WRITE; | |
| 283 | + bit_group_1 |= PIPE_CONTROL_STORE_DATA_INDEX; | |
| 284 | + bit_group_1 |= PIPE_CONTROL_QW_WRITE; | |
| 225 | 285 | |
| 226 | − flags |= PIPE_CONTROL_CS_STALL; | |
| 286 | + bit_group_1 |= PIPE_CONTROL_CS_STALL; | |
| 227 | 287 | |
| 228 | 288 | if (!HAS_3D_PIPELINE(engine->i915)) |
| 229 | − flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS; | |
| 289 | + bit_group_1 &= ~PIPE_CONTROL_3D_ARCH_FLAGS; | |
| 230 | 290 | else if (engine->class == COMPUTE_CLASS) |
| 231 | − flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS; | |
| 291 | + bit_group_1 &= ~PIPE_CONTROL_3D_ENGINE_FLAGS; | |
| 232 | 292 | |
| 233 | 293 | cs = intel_ring_begin(rq, 6); |
| 234 | 294 | if (IS_ERR(cs)) |
| 235 | 295 | return PTR_ERR(cs); |
| 236 | 296 | |
| 237 | − cs = gen12_emit_pipe_control(cs, | |
| 238 | − PIPE_CONTROL0_HDC_PIPELINE_FLUSH, | |
| 239 | − flags, LRC_PPHWSP_SCRATCH_ADDR); | |
| 297 | + cs = gen12_emit_pipe_control(cs, bit_group_0, bit_group_1, | |
| 298 | + LRC_PPHWSP_SCRATCH_ADDR); | |
| 240 | 299 | intel_ring_advance(rq, cs); |
| 241 | 300 | } |
| 242 | 301 | |
| @@ -267,10 +326,9 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) · 24 unmodified lines | ||
| 267 | 326 | else if (engine->class == COMPUTE_CLASS) |
| 268 | 327 | flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS; |
| 269 | 328 | |
| 270 | − if (!HAS_FLAT_CCS(rq->engine->i915)) | |
| 271 | − count = 8 + 4; | |
| 272 | − else | |
| 273 | − count = 8; | |
| 329 | + count = 8; | |
| 330 | + if (gen12_needs_ccs_aux_inv(rq->engine)) | |
| 331 | + count += 8; | |
| 274 | 332 | |
| 275 | 333 | cs = intel_ring_begin(rq, count); |
| 276 | 334 | if (IS_ERR(cs)) |
| @@ -285,11 +343,7 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) · 8 unmodified lines | ||
| 285 | 343 | |
| 286 | 344 | cs = gen8_emit_pipe_control(cs, flags, LRC_PPHWSP_SCRATCH_ADDR); |
| 287 | 345 | |
| 288 | − if (!HAS_FLAT_CCS(rq->engine->i915)) { | |
| 289 | − /* hsdes: 1809175790 */ | |
| 290 | − cs = gen12_emit_aux_table_inv(rq->engine->gt, | |
| 291 | − cs, GEN12_GFX_CCS_AUX_NV); | |
| 292 | − } | |
| 346 | + cs = gen12_emit_aux_table_inv(engine, cs); | |
| 293 | 347 | |
| 294 | 348 | *cs++ = preparser_disable(false); |
| 295 | 349 | intel_ring_advance(rq, cs); |
| @@ -300,21 +354,14 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) · 4 unmodified lines | ||
| 300 | 354 | |
| 301 | 355 | int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) |
| 302 | 356 | { |
| 303 | − intel_engine_mask_t aux_inv = 0; | |
| 304 | − u32 cmd, *cs; | |
| 357 | + u32 cmd = 4; | |
| 358 | + u32 *cs; | |
| 305 | 359 | |
| 306 | − cmd = 4; | |
| 307 | 360 | if (mode & EMIT_INVALIDATE) { |
| 308 | 361 | cmd += 2; |
| 309 | 362 | |
| 310 | − if (!HAS_FLAT_CCS(rq->engine->i915) && | |
| 311 | − (rq->engine->class == VIDEO_DECODE_CLASS || | |
| 312 | − rq->engine->class == VIDEO_ENHANCEMENT_CLASS)) { | |
| 313 | − aux_inv = rq->engine->mask & | |
| 314 | − ~GENMASK(_BCS(I915_MAX_BCS - 1), BCS0); | |
| 315 | − if (aux_inv) | |
| 316 | − cmd += 4; | |
| 317 | − } | |
| 363 | + if (gen12_needs_ccs_aux_inv(rq->engine)) | |
| 364 | + cmd += 8; | |
| 318 | 365 | } |
| 319 | 366 | |
| 320 | 367 | cs = intel_ring_begin(rq, cmd); |
| @@ -338,6 +385,10 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) · 17 unmodified lines | ||
| 338 | 385 | cmd |= MI_INVALIDATE_TLB; |
| 339 | 386 | if (rq->engine->class == VIDEO_DECODE_CLASS) |
| 340 | 387 | cmd |= MI_INVALIDATE_BSD; |
| 388 | + | |
| 389 | + if (gen12_needs_ccs_aux_inv(rq->engine) && | |
| 390 | + rq->engine->class == COPY_ENGINE_CLASS) | |
| 391 | + cmd |= MI_FLUSH_DW_CCS; | |
| 341 | 392 | } |
| 342 | 393 | |
| 343 | 394 | *cs++ = cmd; |
| @@ -345,14 +396,7 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) · 1 unmodified line | ||
| 345 | 396 | *cs++ = 0; /* upper addr */ |
| 346 | 397 | *cs++ = 0; /* value */ |
| 347 | 398 | |
| 348 | − if (aux_inv) { /* hsdes: 1809175790 */ | |
| 349 | − if (rq->engine->class == VIDEO_DECODE_CLASS) | |
| 350 | − cs = gen12_emit_aux_table_inv(rq->engine->gt, | |
| 351 | − cs, GEN12_VD0_AUX_NV); | |
| 352 | − else | |
| 353 | − cs = gen12_emit_aux_table_inv(rq->engine->gt, | |
| 354 | − cs, GEN12_VE0_AUX_NV); | |
| 355 | − } | |
| 399 | + cs = gen12_emit_aux_table_inv(rq->engine, cs); | |
| 356 | 400 | |
| 357 | 401 | if (mode & EMIT_INVALIDATE) |
| 358 | 402 | *cs++ = preparser_disable(false); |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "intel_gt_regs.h" |
| 14 | 14 | #include "intel_gpu_commands.h" |
| 15 | 15 | |
| 16 | +struct intel_engine_cs; | |
| 16 | 17 | struct intel_gt; |
| 17 | 18 | struct i915_request; |
| 18 | 19 | |
| @@ -46,28 +47,32 @@ u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); · 27 unmodified lines | ||
| 46 | 47 | u32 *gen11_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); |
| 47 | 48 | u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); |
| 48 | 49 | |
| 49 | −u32 *gen12_emit_aux_table_inv(struct intel_gt *gt, u32 *cs, const i915_reg_t inv_reg); | |
| 50 | +u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs); | |
| 50 | 51 | |
| 51 | 52 | static inline u32 * |
| 52 | −__gen8_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset) | |
| 53 | +__gen8_emit_pipe_control(u32 *batch, u32 bit_group_0, | |
| 54 | + u32 bit_group_1, u32 offset) | |
| 53 | 55 | { |
| 54 | 56 | memset(batch, 0, 6 * sizeof(u32)); |
| 55 | 57 | |
| 56 | − batch[0] = GFX_OP_PIPE_CONTROL(6) | flags0; | |
| 57 | − batch[1] = flags1; | |
| 58 | + batch[0] = GFX_OP_PIPE_CONTROL(6) | bit_group_0; | |
| 59 | + batch[1] = bit_group_1; | |
| 58 | 60 | batch[2] = offset; |
| 59 | 61 | |
| 60 | 62 | return batch + 6; |
| 61 | 63 | } |
| 62 | 64 | |
| 63 | −static inline u32 *gen8_emit_pipe_control(u32 *batch, u32 flags, u32 offset) | |
| 65 | +static inline u32 *gen8_emit_pipe_control(u32 *batch, | |
| 66 | + u32 bit_group_1, u32 offset) | |
| 64 | 67 | { |
| 65 | − return __gen8_emit_pipe_control(batch, 0, flags, offset); | |
| 68 | + return __gen8_emit_pipe_control(batch, 0, bit_group_1, offset); | |
| 66 | 69 | } |
| 67 | 70 | |
| 68 | −static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset) | |
| 71 | +static inline u32 *gen12_emit_pipe_control(u32 *batch, u32 bit_group_0, | |
| 72 | + u32 bit_group_1, u32 offset) | |
| 69 | 73 | { |
| 70 | − return __gen8_emit_pipe_control(batch, flags0, flags1, offset); | |
| 74 | + return __gen8_emit_pipe_control(batch, bit_group_0, | |
| 75 | + bit_group_1, offset); | |
| 71 | 76 | } |
| 72 | 77 | |
| 73 | 78 | static inline u32 * |
| @@ -121,6 +121,7 @@ · 120 unmodified lines | ||
| 121 | 121 | #define MI_SEMAPHORE_TARGET(engine) ((engine)<<15) |
| 122 | 122 | #define MI_SEMAPHORE_WAIT MI_INSTR(0x1c, 2) /* GEN8+ */ |
| 123 | 123 | #define MI_SEMAPHORE_WAIT_TOKEN MI_INSTR(0x1c, 3) /* GEN12+ */ |
| 124 | +#define MI_SEMAPHORE_REGISTER_POLL (1 << 16) | |
| 124 | 125 | #define MI_SEMAPHORE_POLL (1 << 15) |
| 125 | 126 | #define MI_SEMAPHORE_SAD_GT_SDD (0 << 12) |
| 126 | 127 | #define MI_SEMAPHORE_SAD_GTE_SDD (1 << 12) |
| @@ -299,6 +300,7 @@ · 172 unmodified lines | ||
| 299 | 300 | #define PIPE_CONTROL_QW_WRITE (1<<14) |
| 300 | 301 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) |
| 301 | 302 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) |
| 303 | +#define PIPE_CONTROL_CCS_FLUSH (1<<13) /* MTL+ */ | |
| 302 | 304 | #define PIPE_CONTROL_WRITE_FLUSH (1<<12) |
| 303 | 305 | #define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */ |
| 304 | 306 | #define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on ILK */ |
| @@ -332,9 +332,11 @@ · 331 unmodified lines | ||
| 332 | 332 | #define GEN8_PRIVATE_PAT_HI _MMIO(0x40e0 + 4) |
| 333 | 333 | #define GEN10_PAT_INDEX(index) _MMIO(0x40e0 + (index) * 4) |
| 334 | 334 | #define BSD_HWS_PGA_GEN7 _MMIO(0x4180) |
| 335 | −#define GEN12_GFX_CCS_AUX_NV _MMIO(0x4208) | |
| 336 | −#define GEN12_VD0_AUX_NV _MMIO(0x4218) | |
| 337 | −#define GEN12_VD1_AUX_NV _MMIO(0x4228) | |
| 335 | + | |
| 336 | +#define GEN12_CCS_AUX_INV _MMIO(0x4208) | |
| 337 | +#define GEN12_VD0_AUX_INV _MMIO(0x4218) | |
| 338 | +#define GEN12_VE0_AUX_INV _MMIO(0x4238) | |
| 339 | +#define GEN12_BCS0_AUX_INV _MMIO(0x4248) | |
| 338 | 340 | |
| 339 | 341 | #define GEN8_RTCR _MMIO(0x4260) |
| 340 | 342 | #define GEN8_M1TCR _MMIO(0x4264) |
| @@ -342,14 +344,12 @@ · 1 unmodified line | ||
| 342 | 344 | #define GEN8_BTCR _MMIO(0x426c) |
| 343 | 345 | #define GEN8_VTCR _MMIO(0x4270) |
| 344 | 346 | |
| 345 | −#define GEN12_VD2_AUX_NV _MMIO(0x4298) | |
| 346 | −#define GEN12_VD3_AUX_NV _MMIO(0x42a8) | |
| 347 | −#define GEN12_VE0_AUX_NV _MMIO(0x4238) | |
| 348 | − | |
| 349 | 347 | #define BLT_HWS_PGA_GEN7 _MMIO(0x4280) |
| 350 | 348 | |
| 351 | −#define GEN12_VE1_AUX_NV _MMIO(0x42b8) | |
| 349 | +#define GEN12_VD2_AUX_INV _MMIO(0x4298) | |
| 350 | +#define GEN12_CCS0_AUX_INV _MMIO(0x42c8) | |
| 352 | 351 | #define AUX_INV REG_BIT(0) |
| 352 | + | |
| 353 | 353 | #define VEBOX_HWS_PGA_GEN7 _MMIO(0x4380) |
| 354 | 354 | |
| 355 | 355 | #define GEN12_AUX_ERR_DBG _MMIO(0x43f4) |
| @@ -1364,10 +1364,7 @@ gen12_emit_indirect_ctx_rcs(const struct intel_context *ce, u32 *cs) · 1363 unmodified lines | ||
| 1364 | 1364 | IS_DG2_G11(ce->engine->i915)) |
| 1365 | 1365 | cs = gen8_emit_pipe_control(cs, PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, 0); |
| 1366 | 1366 | |
| 1367 | − /* hsdes: 1809175790 */ | |
| 1368 | − if (!HAS_FLAT_CCS(ce->engine->i915)) | |
| 1369 | − cs = gen12_emit_aux_table_inv(ce->engine->gt, | |
| 1370 | − cs, GEN12_GFX_CCS_AUX_NV); | |
| 1367 | + cs = gen12_emit_aux_table_inv(ce->engine, cs); | |
| 1371 | 1368 | |
| 1372 | 1369 | /* Wa_16014892111 */ |
| 1373 | 1370 | if (IS_MTL_GRAPHICS_STEP(ce->engine->i915, M, STEP_A0, STEP_B0) || |
| @@ -1392,17 +1389,7 @@ gen12_emit_indirect_ctx_xcs(const struct intel_context *ce, u32 *cs) · 18 unmodified lines | ||
| 1392 | 1389 | PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, |
| 1393 | 1390 | 0); |
| 1394 | 1391 | |
| 1395 | − /* hsdes: 1809175790 */ | |
| 1396 | − if (!HAS_FLAT_CCS(ce->engine->i915)) { | |
| 1397 | − if (ce->engine->class == VIDEO_DECODE_CLASS) | |
| 1398 | − cs = gen12_emit_aux_table_inv(ce->engine->gt, | |
| 1399 | − cs, GEN12_VD0_AUX_NV); | |
| 1400 | − else if (ce->engine->class == VIDEO_ENHANCEMENT_CLASS) | |
| 1401 | − cs = gen12_emit_aux_table_inv(ce->engine->gt, | |
| 1402 | − cs, GEN12_VE0_AUX_NV); | |
| 1403 | − } | |
| 1404 | − | |
| 1405 | − return cs; | |
| 1392 | + return gen12_emit_aux_table_inv(ce->engine, cs); | |
| 1406 | 1393 | } |
| 1407 | 1394 | |
| 1408 | 1395 | static void |
| @@ -491,7 +491,7 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu, · 490 unmodified lines | ||
| 491 | 491 | return; |
| 492 | 492 | } |
| 493 | 493 | |
| 494 | − msg_length = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, reg); | |
| 494 | + msg_length = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, value); | |
| 495 | 495 | |
| 496 | 496 | // check the msg in DATA register. |
| 497 | 497 | msg = vgpu_vreg(vgpu, offset + 4); |
| @@ -449,8 +449,11 @@ int i915_active_add_request(struct i915_active *ref, struct i915_request *rq) · 448 unmodified lines | ||
| 449 | 449 | } |
| 450 | 450 | } while (unlikely(is_barrier(active))); |
| 451 | 451 | |
| 452 | − if (!__i915_active_fence_set(active, fence)) | |
| 452 | + fence = __i915_active_fence_set(active, fence); | |
| 453 | + if (!fence) | |
| 453 | 454 | __i915_active_acquire(ref); |
| 455 | + else | |
| 456 | + dma_fence_put(fence); | |
| 454 | 457 | |
| 455 | 458 | out: |
| 456 | 459 | i915_active_release(ref); |
| @@ -469,13 +472,9 @@ __i915_active_set_fence(struct i915_active *ref, · 12 unmodified lines | ||
| 469 | 472 | return NULL; |
| 470 | 473 | } |
| 471 | 474 | |
| 472 | − rcu_read_lock(); | |
| 473 | 475 | prev = __i915_active_fence_set(active, fence); |
| 474 | − if (prev) | |
| 475 | − prev = dma_fence_get_rcu(prev); | |
| 476 | − else | |
| 476 | + if (!prev) | |
| 477 | 477 | __i915_active_acquire(ref); |
| 478 | − rcu_read_unlock(); | |
| 479 | 478 | |
| 480 | 479 | return prev; |
| 481 | 480 | } |
| @@ -1019,10 +1018,11 @@ void i915_request_add_active_barriers(struct i915_request *rq) · 537 unmodified lines | ||
| 1019 | 1018 | * |
| 1020 | 1019 | * Records the new @fence as the last active fence along its timeline in |
| 1021 | 1020 | * this active tracker, moving the tracking callbacks from the previous |
| 1022 | − * fence onto this one. Returns the previous fence (if not already completed), | |
| 1023 | − * which the caller must ensure is executed before the new fence. To ensure | |
| 1024 | − * that the order of fences within the timeline of the i915_active_fence is | |
| 1025 | − * understood, it should be locked by the caller. | |
| 1021 | + * fence onto this one. Gets and returns a reference to the previous fence | |
| 1022 | + * (if not already completed), which the caller must put after making sure | |
| 1023 | + * that it is executed before the new fence. To ensure that the order of | |
| 1024 | + * fences within the timeline of the i915_active_fence is understood, it | |
| 1025 | + * should be locked by the caller. | |
| 1026 | 1026 | */ |
| 1027 | 1027 | struct dma_fence * |
| 1028 | 1028 | __i915_active_fence_set(struct i915_active_fence *active, |
| @@ -1031,7 +1031,23 @@ __i915_active_fence_set(struct i915_active_fence *active, · 2 unmodified lines | ||
| 1031 | 1031 | struct dma_fence *prev; |
| 1032 | 1032 | unsigned long flags; |
| 1033 | 1033 | |
| 1034 | − if (fence == rcu_access_pointer(active->fence)) | |
| 1034 | + /* | |
| 1035 | + * In case of fences embedded in i915_requests, their memory is | |
| 1036 | + * SLAB_FAILSAFE_BY_RCU, then it can be reused right after release | |
| 1037 | + * by new requests. Then, there is a risk of passing back a pointer | |
| 1038 | + * to a new, completely unrelated fence that reuses the same memory | |
| 1039 | + * while tracked under a different active tracker. Combined with i915 | |
| 1040 | + * perf open/close operations that build await dependencies between | |
| 1041 | + * engine kernel context requests and user requests from different | |
| 1042 | + * timelines, this can lead to dependency loops and infinite waits. | |
| 1043 | + * | |
| 1044 | + * As a countermeasure, we try to get a reference to the active->fence | |
| 1045 | + * first, so if we succeed and pass it back to our user then it is not | |
| 1046 | + * released and potentially reused by an unrelated request before the | |
| 1047 | + * user has a chance to set up an await dependency on it. | |
| 1048 | + */ | |
| 1049 | + prev = i915_active_fence_get(active); | |
| 1050 | + if (fence == prev) | |
| 1035 | 1051 | return fence; |
| 1036 | 1052 | |
| 1037 | 1053 | GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)); |
| @@ -1040,27 +1056,56 @@ __i915_active_fence_set(struct i915_active_fence *active, · 2 unmodified lines | ||
| 1040 | 1056 | * Consider that we have two threads arriving (A and B), with |
| 1041 | 1057 | * C already resident as the active->fence. |
| 1042 | 1058 | * |
| 1043 | − * A does the xchg first, and so it sees C or NULL depending | |
| 1044 | − * on the timing of the interrupt handler. If it is NULL, the | |
| 1045 | − * previous fence must have been signaled and we know that | |
| 1046 | − * we are first on the timeline. If it is still present, | |
| 1047 | − * we acquire the lock on that fence and serialise with the interrupt | |
| 1048 | − * handler, in the process removing it from any future interrupt | |
| 1049 | − * callback. A will then wait on C before executing (if present). | |
| 1050 | − * | |
| 1051 | − * As B is second, it sees A as the previous fence and so waits for | |
| 1052 | − * it to complete its transition and takes over the occupancy for | |
| 1053 | − * itself -- remembering that it needs to wait on A before executing. | |
| 1059 | + * Both A and B have got a reference to C or NULL, depending on the | |
| 1060 | + * timing of the interrupt handler. Let's assume that if A has got C | |
| 1061 | + * then it has locked C first (before B). | |
| 1054 | 1062 | * |
| 1055 | 1063 | * Note the strong ordering of the timeline also provides consistent |
| 1056 | 1064 | * nesting rules for the fence->lock; the inner lock is always the |
| 1057 | 1065 | * older lock. |
| 1058 | 1066 | */ |
| 1059 | 1067 | spin_lock_irqsave(fence->lock, flags); |
| 1060 | − prev = xchg(__active_fence_slot(active), fence); | |
| 1061 | − if (prev) { | |
| 1062 | − GEM_BUG_ON(prev == fence); | |
| 1068 | + if (prev) | |
| 1063 | 1069 | spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING); |
| 1070 | + | |
| 1071 | + /* | |
| 1072 | + * A does the cmpxchg first, and so it sees C or NULL, as before, or | |
| 1073 | + * something else, depending on the timing of other threads and/or | |
| 1074 | + * interrupt handler. If not the same as before then A unlocks C if | |
| 1075 | + * applicable and retries, starting from an attempt to get a new | |
| 1076 | + * active->fence. Meanwhile, B follows the same path as A. | |
| 1077 | + * Once A succeeds with cmpxch, B fails again, retires, gets A from | |
| 1078 | + * active->fence, locks it as soon as A completes, and possibly | |
| 1079 | + * succeeds with cmpxchg. | |
| 1080 | + */ | |
| 1081 | + while (cmpxchg(__active_fence_slot(active), prev, fence) != prev) { | |
| 1082 | + if (prev) { | |
| 1083 | + spin_unlock(prev->lock); | |
| 1084 | + dma_fence_put(prev); | |
| 1085 | + } | |
| 1086 | + spin_unlock_irqrestore(fence->lock, flags); | |
| 1087 | + | |
| 1088 | + prev = i915_active_fence_get(active); | |
| 1089 | + GEM_BUG_ON(prev == fence); | |
| 1090 | + | |
| 1091 | + spin_lock_irqsave(fence->lock, flags); | |
| 1092 | + if (prev) | |
| 1093 | + spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING); | |
| 1094 | + } | |
| 1095 | + | |
| 1096 | + /* | |
| 1097 | + * If prev is NULL then the previous fence must have been signaled | |
| 1098 | + * and we know that we are first on the timeline. If it is still | |
| 1099 | + * present then, having the lock on that fence already acquired, we | |
| 1100 | + * serialise with the interrupt handler, in the process of removing it | |
| 1101 | + * from any future interrupt callback. A will then wait on C before | |
| 1102 | + * executing (if present). | |
| 1103 | + * | |
| 1104 | + * As B is second, it sees A as the previous fence and so waits for | |
| 1105 | + * it to complete its transition and takes over the occupancy for | |
| 1106 | + * itself -- remembering that it needs to wait on A before executing. | |
| 1107 | + */ | |
| 1108 | + if (prev) { | |
| 1064 | 1109 | __list_del_entry(&active->cb.node); |
| 1065 | 1110 | spin_unlock(prev->lock); /* serialise with prev->cb_list */ |
| 1066 | 1111 | } |
| @@ -1077,11 +1122,7 @@ int i915_active_fence_set(struct i915_active_fence *active, · 10 unmodified lines | ||
| 1077 | 1122 | int err = 0; |
| 1078 | 1123 | |
| 1079 | 1124 | /* Must maintain timeline ordering wrt previous active requests */ |
| 1080 | − rcu_read_lock(); | |
| 1081 | 1125 | fence = __i915_active_fence_set(active, &rq->fence); |
| 1082 | − if (fence) /* but the previous fence may not belong to that timeline! */ | |
| 1083 | − fence = dma_fence_get_rcu(fence); | |
| 1084 | − rcu_read_unlock(); | |
| 1085 | 1126 | if (fence) { |
| 1086 | 1127 | err = i915_request_await_dma_fence(rq, fence); |
| 1087 | 1128 | dma_fence_put(fence); |
| @@ -1661,6 +1661,11 @@ __i915_request_ensure_parallel_ordering(struct i915_request *rq, · 1660 unmodified lines | ||
| 1661 | 1661 | |
| 1662 | 1662 | request_to_parent(rq)->parallel.last_rq = i915_request_get(rq); |
| 1663 | 1663 | |
| 1664 | + /* | |
| 1665 | + * Users have to put a reference potentially got by | |
| 1666 | + * __i915_active_fence_set() to the returned request | |
| 1667 | + * when no longer needed | |
| 1668 | + */ | |
| 1664 | 1669 | return to_request(__i915_active_fence_set(&timeline->last_request, |
| 1665 | 1670 | &rq->fence)); |
| 1666 | 1671 | } |
| @@ -1707,6 +1712,10 @@ __i915_request_ensure_ordering(struct i915_request *rq, · 40 unmodified lines | ||
| 1707 | 1712 | 0); |
| 1708 | 1713 | } |
| 1709 | 1714 | |
| 1715 | + /* | |
| 1716 | + * Users have to put the reference to prev potentially got | |
| 1717 | + * by __i915_active_fence_set() when no longer needed | |
| 1718 | + */ | |
| 1710 | 1719 | return prev; |
| 1711 | 1720 | } |
| 1712 | 1721 | |
| @@ -1760,6 +1769,8 @@ __i915_request_add_to_timeline(struct i915_request *rq) · 47 unmodified lines | ||
| 1760 | 1769 | prev = __i915_request_ensure_ordering(rq, timeline); |
| 1761 | 1770 | else |
| 1762 | 1771 | prev = __i915_request_ensure_parallel_ordering(rq, timeline); |
| 1772 | + if (prev) | |
| 1773 | + i915_request_put(prev); | |
| 1763 | 1774 | |
| 1764 | 1775 | /* |
| 1765 | 1776 | * Make sure that no request gazumped us - if it was allocated after |
| @@ -310,7 +310,7 @@ static void ipu_crtc_mode_set_nofb(struct drm_crtc *crtc) · 309 unmodified lines | ||
| 310 | 310 | dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n", |
| 311 | 311 | sig_cfg.mode.hactive, new_hactive); |
| 312 | 312 | |
| 313 | − sig_cfg.mode.hfront_porch = new_hactive - sig_cfg.mode.hactive; | |
| 313 | + sig_cfg.mode.hfront_porch -= new_hactive - sig_cfg.mode.hactive; | |
| 314 | 314 | sig_cfg.mode.hactive = new_hactive; |
| 315 | 315 | } |
| 316 | 316 | |
| @@ -967,7 +967,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) · 966 unmodified lines | ||
| 967 | 967 | /* Determine display colour depth for everything except LVDS now, |
| 968 | 968 | * DP requires this before mode_valid() is called. |
| 969 | 969 | */ |
| 970 | − if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && nv_connector->native_mode) | |
| 970 | + if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) | |
| 971 | 971 | nouveau_connector_detect_depth(connector); |
| 972 | 972 | |
| 973 | 973 | /* Find the native mode if this is a digital panel, if we didn't |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | ||
| 26 | 26 | #include "head.h" |
| 27 | 27 | #include "ior.h" |
| 28 | 28 | |
| 29 | +#include <drm/display/drm_dp.h> | |
| 30 | + | |
| 29 | 31 | #include <subdev/bios.h> |
| 30 | 32 | #include <subdev/bios/init.h> |
| 31 | 33 | #include <subdev/gpio.h> |
| @@ -634,6 +636,50 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp) · 602 unmodified lines | ||
| 634 | 636 | return outp->dp.rates != 0; |
| 635 | 637 | } |
| 636 | 638 | |
| 639 | +/* XXX: This is a big fat hack, and this is just drm_dp_read_dpcd_caps() | |
| 640 | + * converted to work inside nvkm. This is a temporary holdover until we start | |
| 641 | + * passing the drm_dp_aux device through NVKM | |
| 642 | + */ | |
| 643 | +static int | |
| 644 | +nvkm_dp_read_dpcd_caps(struct nvkm_outp *outp) | |
| 645 | +{ | |
| 646 | + struct nvkm_i2c_aux *aux = outp->dp.aux; | |
| 647 | + u8 dpcd_ext[DP_RECEIVER_CAP_SIZE]; | |
| 648 | + int ret; | |
| 649 | + | |
| 650 | + ret = nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, DP_RECEIVER_CAP_SIZE); | |
| 651 | + if (ret < 0) | |
| 652 | + return ret; | |
| 653 | + | |
| 654 | + /* | |
| 655 | + * Prior to DP1.3 the bit represented by | |
| 656 | + * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved. | |
| 657 | + * If it is set DP_DPCD_REV at 0000h could be at a value less than | |
| 658 | + * the true capability of the panel. The only way to check is to | |
| 659 | + * then compare 0000h and 2200h. | |
| 660 | + */ | |
| 661 | + if (!(outp->dp.dpcd[DP_TRAINING_AUX_RD_INTERVAL] & | |
| 662 | + DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT)) | |
| 663 | + return 0; | |
| 664 | + | |
| 665 | + ret = nvkm_rdaux(aux, DP_DP13_DPCD_REV, dpcd_ext, sizeof(dpcd_ext)); | |
| 666 | + if (ret < 0) | |
| 667 | + return ret; | |
| 668 | + | |
| 669 | + if (outp->dp.dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) { | |
| 670 | + OUTP_DBG(outp, "Extended DPCD rev less than base DPCD rev (%d > %d)\n", | |
| 671 | + outp->dp.dpcd[DP_DPCD_REV], dpcd_ext[DP_DPCD_REV]); | |
| 672 | + return 0; | |
| 673 | + } | |
| 674 | + | |
| 675 | + if (!memcmp(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext))) | |
| 676 | + return 0; | |
| 677 | + | |
| 678 | + memcpy(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext)); | |
| 679 | + | |
| 680 | + return 0; | |
| 681 | +} | |
| 682 | + | |
| 637 | 683 | void |
| 638 | 684 | nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) |
| 639 | 685 | { |
| @@ -689,7 +735,7 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) · 49 unmodified lines | ||
| 689 | 735 | memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr)); |
| 690 | 736 | } |
| 691 | 737 | |
| 692 | − if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) { | |
| 738 | + if (!nvkm_dp_read_dpcd_caps(outp)) { | |
| 693 | 739 | const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 }; |
| 694 | 740 | const u8 *rate; |
| 695 | 741 | int rate_max; |
| @@ -117,6 +117,7 @@ void gk104_grctx_generate_r418800(struct gf100_gr *); · 116 unmodified lines | ||
| 117 | 117 | |
| 118 | 118 | extern const struct gf100_grctx_func gk110_grctx; |
| 119 | 119 | void gk110_grctx_generate_r419eb0(struct gf100_gr *); |
| 120 | +void gk110_grctx_generate_r419f78(struct gf100_gr *); | |
| 120 | 121 | |
| 121 | 122 | extern const struct gf100_grctx_func gk110b_grctx; |
| 122 | 123 | extern const struct gf100_grctx_func gk208_grctx; |
| @@ -906,7 +906,9 @@ static void · 905 unmodified lines | ||
| 906 | 906 | gk104_grctx_generate_r419f78(struct gf100_gr *gr) |
| 907 | 907 | { |
| 908 | 908 | struct nvkm_device *device = gr->base.engine.subdev.device; |
| 909 | − nvkm_mask(device, 0x419f78, 0x00000001, 0x00000000); | |
| 909 | + | |
| 910 | + /* bit 3 set disables loads in fp helper invocations, we need it enabled */ | |
| 911 | + nvkm_mask(device, 0x419f78, 0x00000009, 0x00000000); | |
| 910 | 912 | } |
| 911 | 913 | |
| 912 | 914 | void |
| @@ -820,6 +820,15 @@ gk110_grctx_generate_r419eb0(struct gf100_gr *gr) · 819 unmodified lines | ||
| 820 | 820 | nvkm_mask(device, 0x419eb0, 0x00001000, 0x00001000); |
| 821 | 821 | } |
| 822 | 822 | |
| 823 | +void | |
| 824 | +gk110_grctx_generate_r419f78(struct gf100_gr *gr) | |
| 825 | +{ | |
| 826 | + struct nvkm_device *device = gr->base.engine.subdev.device; | |
| 827 | + | |
| 828 | + /* bit 3 set disables loads in fp helper invocations, we need it enabled */ | |
| 829 | + nvkm_mask(device, 0x419f78, 0x00000008, 0x00000000); | |
| 830 | +} | |
| 831 | + | |
| 823 | 832 | const struct gf100_grctx_func |
| 824 | 833 | gk110_grctx = { |
| 825 | 834 | .main = gf100_grctx_generate_main, |
| @@ -854,4 +863,5 @@ gk110_grctx = { · 28 unmodified lines | ||
| 854 | 863 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, |
| 855 | 864 | .r418800 = gk104_grctx_generate_r418800, |
| 856 | 865 | .r419eb0 = gk110_grctx_generate_r419eb0, |
| 866 | + .r419f78 = gk110_grctx_generate_r419f78, | |
| 857 | 867 | }; |
| @@ -103,4 +103,5 @@ gk110b_grctx = { · 102 unmodified lines | ||
| 103 | 103 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, |
| 104 | 104 | .r418800 = gk104_grctx_generate_r418800, |
| 105 | 105 | .r419eb0 = gk110_grctx_generate_r419eb0, |
| 106 | + .r419f78 = gk110_grctx_generate_r419f78, | |
| 106 | 107 | }; |
| @@ -568,4 +568,5 @@ gk208_grctx = { · 567 unmodified lines | ||
| 568 | 568 | .dist_skip_table = gf117_grctx_generate_dist_skip_table, |
| 569 | 569 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, |
| 570 | 570 | .r418800 = gk104_grctx_generate_r418800, |
| 571 | + .r419f78 = gk110_grctx_generate_r419f78, | |
| 571 | 572 | }; |
| @@ -988,4 +988,5 @@ gm107_grctx = { · 987 unmodified lines | ||
| 988 | 988 | .r406500 = gm107_grctx_generate_r406500, |
| 989 | 989 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, |
| 990 | 990 | .r419e00 = gm107_grctx_generate_r419e00, |
| 991 | + .r419f78 = gk110_grctx_generate_r419f78, | |
| 991 | 992 | }; |
| @@ -206,19 +206,6 @@ tu102_gr_av_to_init_veid(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) · 205 unmodified lines | ||
| 206 | 206 | return gk20a_gr_av_to_init_(blob, 64, 0x00100000, ppack); |
| 207 | 207 | } |
| 208 | 208 | |
| 209 | −int | |
| 210 | −tu102_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) | |
| 211 | −{ | |
| 212 | − int ret; | |
| 213 | − | |
| 214 | − ret = gm200_gr_load(gr, ver, fwif); | |
| 215 | − if (ret) | |
| 216 | − return ret; | |
| 217 | − | |
| 218 | − return gk20a_gr_load_net(gr, "gr/", "sw_veid_bundle_init", ver, tu102_gr_av_to_init_veid, | |
| 219 | − &gr->bundle_veid); | |
| 220 | −} | |
| 221 | − | |
| 222 | 209 | static const struct gf100_gr_fwif |
| 223 | 210 | tu102_gr_fwif[] = { |
| 224 | 211 | { 0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr }, |
| @@ -569,6 +569,7 @@ static const struct of_device_id s6d7aa0_of_match[] = { · 568 unmodified lines | ||
| 569 | 569 | }, |
| 570 | 570 | { /* sentinel */ } |
| 571 | 571 | }; |
| 572 | +MODULE_DEVICE_TABLE(of, s6d7aa0_of_match); | |
| 572 | 573 | |
| 573 | 574 | static struct mipi_dsi_driver s6d7aa0_driver = { |
| 574 | 575 | .probe = s6d7aa0_probe, |
| @@ -833,12 +833,12 @@ static int vop_plane_atomic_check(struct drm_plane *plane, · 832 unmodified lines | ||
| 833 | 833 | * need align with 2 pixel. |
| 834 | 834 | */ |
| 835 | 835 | if (fb->format->is_yuv && ((new_plane_state->src.x1 >> 16) % 2)) { |
| 836 | − DRM_ERROR("Invalid Source: Yuv format not support odd xpos\n"); | |
| 836 | + DRM_DEBUG_KMS("Invalid Source: Yuv format not support odd xpos\n"); | |
| 837 | 837 | return -EINVAL; |
| 838 | 838 | } |
| 839 | 839 | |
| 840 | 840 | if (fb->format->is_yuv && new_plane_state->rotation & DRM_MODE_REFLECT_Y) { |
| 841 | − DRM_ERROR("Invalid Source: Yuv format does not support this rotation\n"); | |
| 841 | + DRM_DEBUG_KMS("Invalid Source: Yuv format does not support this rotation\n"); | |
| 842 | 842 | return -EINVAL; |
| 843 | 843 | } |
| 844 | 844 | |
| @@ -846,7 +846,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane, · 1 unmodified line | ||
| 846 | 846 | struct vop *vop = to_vop(crtc); |
| 847 | 847 | |
| 848 | 848 | if (!vop->data->afbc) { |
| 849 | − DRM_ERROR("vop does not support AFBC\n"); | |
| 849 | + DRM_DEBUG_KMS("vop does not support AFBC\n"); | |
| 850 | 850 | return -EINVAL; |
| 851 | 851 | } |
| 852 | 852 | |
| @@ -855,15 +855,16 @@ static int vop_plane_atomic_check(struct drm_plane *plane, · 2 unmodified lines | ||
| 855 | 855 | return ret; |
| 856 | 856 | |
| 857 | 857 | if (new_plane_state->src.x1 || new_plane_state->src.y1) { |
| 858 | − DRM_ERROR("AFBC does not support offset display, xpos=%d, ypos=%d, offset=%d\n", | |
| 859 | − new_plane_state->src.x1, | |
| 860 | − new_plane_state->src.y1, fb->offsets[0]); | |
| 858 | + DRM_DEBUG_KMS("AFBC does not support offset display, " \ | |
| 859 | + "xpos=%d, ypos=%d, offset=%d\n", | |
| 860 | + new_plane_state->src.x1, new_plane_state->src.y1, | |
| 861 | + fb->offsets[0]); | |
| 861 | 862 | return -EINVAL; |
| 862 | 863 | } |
| 863 | 864 | |
| 864 | 865 | if (new_plane_state->rotation && new_plane_state->rotation != DRM_MODE_ROTATE_0) { |
| 865 | − DRM_ERROR("No rotation support in AFBC, rotation=%d\n", | |
| 866 | − new_plane_state->rotation); | |
| 866 | + DRM_DEBUG_KMS("No rotation support in AFBC, rotation=%d\n", | |
| 867 | + new_plane_state->rotation); | |
| 867 | 868 | return -EINVAL; |
| 868 | 869 | } |
| 869 | 870 | } |
| @@ -519,7 +519,8 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, · 518 unmodified lines | ||
| 519 | 519 | |
| 520 | 520 | if (bo->pin_count) { |
| 521 | 521 | *locked = false; |
| 522 | − *busy = false; | |
| 522 | + if (busy) | |
| 523 | + *busy = false; | |
| 523 | 524 | return false; |
| 524 | 525 | } |
| 525 | 526 | |
| @@ -209,8 +209,7 @@ int vmbus_connect(void) · 208 unmodified lines | ||
| 209 | 209 | * Setup the vmbus event connection for channel interrupt |
| 210 | 210 | * abstraction stuff |
| 211 | 211 | */ |
| 212 | − vmbus_connection.int_page = | |
| 213 | − (void *)hv_alloc_hyperv_zeroed_page(); | |
| 212 | + vmbus_connection.int_page = hv_alloc_hyperv_zeroed_page(); | |
| 214 | 213 | if (vmbus_connection.int_page == NULL) { |
| 215 | 214 | ret = -ENOMEM; |
| 216 | 215 | goto cleanup; |
| @@ -225,8 +224,8 @@ int vmbus_connect(void) · 8 unmodified lines | ||
| 225 | 224 | * Setup the monitor notification facility. The 1st page for |
| 226 | 225 | * parent->child and the 2nd page for child->parent |
| 227 | 226 | */ |
| 228 | − vmbus_connection.monitor_pages[0] = (void *)hv_alloc_hyperv_page(); | |
| 229 | − vmbus_connection.monitor_pages[1] = (void *)hv_alloc_hyperv_page(); | |
| 227 | + vmbus_connection.monitor_pages[0] = hv_alloc_hyperv_page(); | |
| 228 | + vmbus_connection.monitor_pages[1] = hv_alloc_hyperv_page(); | |
| 230 | 229 | if ((vmbus_connection.monitor_pages[0] == NULL) || |
| 231 | 230 | (vmbus_connection.monitor_pages[1] == NULL)) { |
| 232 | 231 | ret = -ENOMEM; |
| @@ -333,15 +332,15 @@ void vmbus_disconnect(void) · 100 unmodified lines | ||
| 333 | 332 | destroy_workqueue(vmbus_connection.work_queue); |
| 334 | 333 | |
| 335 | 334 | if (vmbus_connection.int_page) { |
| 336 | − hv_free_hyperv_page((unsigned long)vmbus_connection.int_page); | |
| 335 | + hv_free_hyperv_page(vmbus_connection.int_page); | |
| 337 | 336 | vmbus_connection.int_page = NULL; |
| 338 | 337 | } |
| 339 | 338 | |
| 340 | 339 | set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1); |
| 341 | 340 | set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1); |
| 342 | 341 | |
| 343 | − hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[0]); | |
| 344 | − hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[1]); | |
| 342 | + hv_free_hyperv_page(vmbus_connection.monitor_pages[0]); | |
| 343 | + hv_free_hyperv_page(vmbus_connection.monitor_pages[1]); | |
| 345 | 344 | vmbus_connection.monitor_pages[0] = NULL; |
| 346 | 345 | vmbus_connection.monitor_pages[1] = NULL; |
| 347 | 346 | } |
| @@ -1628,7 +1628,7 @@ static int hv_free_page_report(struct page_reporting_dev_info *pr_dev_info, · 1627 unmodified lines | ||
| 1628 | 1628 | WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES); |
| 1629 | 1629 | WARN_ON_ONCE(sgl->length < (HV_HYP_PAGE_SIZE << page_reporting_order)); |
| 1630 | 1630 | local_irq_save(flags); |
| 1631 | − hint = *(struct hv_memory_hint **)this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 1631 | + hint = *this_cpu_ptr(hyperv_pcpu_input_arg); | |
| 1632 | 1632 | if (!hint) { |
| 1633 | 1633 | local_irq_restore(flags); |
| 1634 | 1634 | return -ENOSPC; |
| @@ -115,12 +115,12 @@ void *hv_alloc_hyperv_zeroed_page(void) · 114 unmodified lines | ||
| 115 | 115 | } |
| 116 | 116 | EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page); |
| 117 | 117 | |
| 118 | −void hv_free_hyperv_page(unsigned long addr) | |
| 118 | +void hv_free_hyperv_page(void *addr) | |
| 119 | 119 | { |
| 120 | 120 | if (PAGE_SIZE == HV_HYP_PAGE_SIZE) |
| 121 | − free_page(addr); | |
| 121 | + free_page((unsigned long)addr); | |
| 122 | 122 | else |
| 123 | − kfree((void *)addr); | |
| 123 | + kfree(addr); | |
| 124 | 124 | } |
| 125 | 125 | EXPORT_SYMBOL_GPL(hv_free_hyperv_page); |
| 126 | 126 | |
| @@ -253,7 +253,7 @@ static void hv_kmsg_dump_unregister(void) · 126 unmodified lines | ||
| 253 | 253 | atomic_notifier_chain_unregister(&panic_notifier_list, |
| 254 | 254 | &hyperv_panic_report_block); |
| 255 | 255 | |
| 256 | − hv_free_hyperv_page((unsigned long)hv_panic_page); | |
| 256 | + hv_free_hyperv_page(hv_panic_page); | |
| 257 | 257 | hv_panic_page = NULL; |
| 258 | 258 | } |
| 259 | 259 | |
| @@ -270,7 +270,7 @@ static void hv_kmsg_dump_register(void) · 10 unmodified lines | ||
| 270 | 270 | ret = kmsg_dump_register(&hv_kmsg_dumper); |
| 271 | 271 | if (ret) { |
| 272 | 272 | pr_err("Hyper-V: kmsg dump register error 0x%x\n", ret); |
| 273 | − hv_free_hyperv_page((unsigned long)hv_panic_page); | |
| 273 | + hv_free_hyperv_page(hv_panic_page); | |
| 274 | 274 | hv_panic_page = NULL; |
| 275 | 275 | } |
| 276 | 276 | } |
| @@ -13,9 +13,11 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | #include <linux/crc16.h> |
| 15 | 15 | #include <linux/debugfs.h> |
| 16 | +#include <linux/delay.h> | |
| 16 | 17 | #include <linux/hid.h> |
| 17 | 18 | #include <linux/hwmon.h> |
| 18 | 19 | #include <linux/jiffies.h> |
| 20 | +#include <linux/ktime.h> | |
| 19 | 21 | #include <linux/module.h> |
| 20 | 22 | #include <linux/mutex.h> |
| 21 | 23 | #include <linux/seq_file.h> |
| @@ -63,6 +65,8 @@ static const char *const aqc_device_names[] = { · 41 unmodified lines | ||
| 63 | 65 | #define CTRL_REPORT_ID 0x03 |
| 64 | 66 | #define AQUAERO_CTRL_REPORT_ID 0x0b |
| 65 | 67 | |
| 68 | +#define CTRL_REPORT_DELAY 200 /* ms */ | |
| 69 | + | |
| 66 | 70 | /* The HID report that the official software always sends |
| 67 | 71 | * after writing values, currently same for all devices |
| 68 | 72 | */ |
| @@ -527,6 +531,9 @@ struct aqc_data { · 458 unmodified lines | ||
| 527 | 531 | int secondary_ctrl_report_size; |
| 528 | 532 | u8 *secondary_ctrl_report; |
| 529 | 533 | |
| 534 | + ktime_t last_ctrl_report_op; | |
| 535 | + int ctrl_report_delay; /* Delay between two ctrl report operations, in ms */ | |
| 536 | + | |
| 530 | 537 | int buffer_size; |
| 531 | 538 | u8 *buffer; |
| 532 | 539 | int checksum_start; |
| @@ -611,17 +618,35 @@ static int aqc_aquastreamxt_convert_fan_rpm(u16 val) · 78 unmodified lines | ||
| 611 | 618 | return 0; |
| 612 | 619 | } |
| 613 | 620 | |
| 621 | +static void aqc_delay_ctrl_report(struct aqc_data *priv) | |
| 622 | +{ | |
| 623 | + /* | |
| 624 | + * If previous read or write is too close to this one, delay the current operation | |
| 625 | + * to give the device enough time to process the previous one. | |
| 626 | + */ | |
| 627 | + if (priv->ctrl_report_delay) { | |
| 628 | + s64 delta = ktime_ms_delta(ktime_get(), priv->last_ctrl_report_op); | |
| 629 | + | |
| 630 | + if (delta < priv->ctrl_report_delay) | |
| 631 | + msleep(priv->ctrl_report_delay - delta); | |
| 632 | + } | |
| 633 | +} | |
| 634 | + | |
| 614 | 635 | /* Expects the mutex to be locked */ |
| 615 | 636 | static int aqc_get_ctrl_data(struct aqc_data *priv) |
| 616 | 637 | { |
| 617 | 638 | int ret; |
| 618 | 639 | |
| 640 | + aqc_delay_ctrl_report(priv); | |
| 641 | + | |
| 619 | 642 | memset(priv->buffer, 0x00, priv->buffer_size); |
| 620 | 643 | ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size, |
| 621 | 644 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
| 622 | 645 | if (ret < 0) |
| 623 | 646 | ret = -ENODATA; |
| 624 | 647 | |
| 648 | + priv->last_ctrl_report_op = ktime_get(); | |
| 649 | + | |
| 625 | 650 | return ret; |
| 626 | 651 | } |
| 627 | 652 | |
| @@ -631,6 +656,8 @@ static int aqc_send_ctrl_data(struct aqc_data *priv) · 3 unmodified lines | ||
| 631 | 656 | int ret; |
| 632 | 657 | u16 checksum; |
| 633 | 658 | |
| 659 | + aqc_delay_ctrl_report(priv); | |
| 660 | + | |
| 634 | 661 | /* Checksum is not needed for Aquaero */ |
| 635 | 662 | if (priv->kind != aquaero) { |
| 636 | 663 | /* Init and xorout value for CRC-16/USB is 0xffff */ |
| @@ -646,12 +673,16 @@ static int aqc_send_ctrl_data(struct aqc_data *priv) · 9 unmodified lines | ||
| 646 | 673 | ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size, |
| 647 | 674 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); |
| 648 | 675 | if (ret < 0) |
| 649 | − return ret; | |
| 676 | + goto record_access_and_ret; | |
| 650 | 677 | |
| 651 | 678 | /* The official software sends this report after every change, so do it here as well */ |
| 652 | 679 | ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id, |
| 653 | 680 | priv->secondary_ctrl_report, priv->secondary_ctrl_report_size, |
| 654 | 681 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); |
| 682 | + | |
| 683 | +record_access_and_ret: | |
| 684 | + priv->last_ctrl_report_op = ktime_get(); | |
| 685 | + | |
| 655 | 686 | return ret; |
| 656 | 687 | } |
| 657 | 688 | |
| @@ -1524,6 +1555,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) · 866 unmodified lines | ||
| 1524 | 1555 | |
| 1525 | 1556 | priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE; |
| 1526 | 1557 | priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET; |
| 1558 | + priv->ctrl_report_delay = CTRL_REPORT_DELAY; | |
| 1527 | 1559 | |
| 1528 | 1560 | priv->temp_label = label_temp_sensors; |
| 1529 | 1561 | priv->virtual_temp_label = label_virtual_temp_sensors; |
| @@ -1547,6 +1579,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) · 17 unmodified lines | ||
| 1547 | 1579 | priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET; |
| 1548 | 1580 | |
| 1549 | 1581 | priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE; |
| 1582 | + priv->ctrl_report_delay = CTRL_REPORT_DELAY; | |
| 1550 | 1583 | |
| 1551 | 1584 | priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES; |
| 1552 | 1585 | |
| @@ -1597,6 +1630,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) · 44 unmodified lines | ||
| 1597 | 1630 | priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET; |
| 1598 | 1631 | |
| 1599 | 1632 | priv->buffer_size = OCTO_CTRL_REPORT_SIZE; |
| 1633 | + priv->ctrl_report_delay = CTRL_REPORT_DELAY; | |
| 1600 | 1634 | |
| 1601 | 1635 | priv->power_cycle_count_offset = OCTO_POWER_CYCLES; |
| 1602 | 1636 | |
| @@ -1624,6 +1658,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id) · 21 unmodified lines | ||
| 1624 | 1658 | priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET; |
| 1625 | 1659 | |
| 1626 | 1660 | priv->buffer_size = QUADRO_CTRL_REPORT_SIZE; |
| 1661 | + priv->ctrl_report_delay = CTRL_REPORT_DELAY; | |
| 1627 | 1662 | |
| 1628 | 1663 | priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET; |
| 1629 | 1664 | priv->power_cycle_count_offset = QUADRO_POWER_CYCLES; |
| @@ -17,12 +17,13 @@ · 16 unmodified lines | ||
| 17 | 17 | enum chips {pfe1100, pfe3000}; |
| 18 | 18 | |
| 19 | 19 | /* |
| 20 | − * Disable status check for pfe3000 devices, because some devices report | |
| 21 | − * communication error (invalid command) for VOUT_MODE command (0x20) | |
| 22 | − * although correct VOUT_MODE (0x16) is returned: it leads to incorrect | |
| 23 | − * exponent in linear mode. | |
| 20 | + * Disable status check because some devices report communication error | |
| 21 | + * (invalid command) for VOUT_MODE command (0x20) although the correct | |
| 22 | + * VOUT_MODE (0x16) is returned: it leads to incorrect exponent in linear | |
| 23 | + * mode. | |
| 24 | + * This affects both pfe3000 and pfe1100. | |
| 24 | 25 | */ |
| 25 | −static struct pmbus_platform_data pfe3000_plat_data = { | |
| 26 | +static struct pmbus_platform_data pfe_plat_data = { | |
| 26 | 27 | .flags = PMBUS_SKIP_STATUS_CHECK, |
| 27 | 28 | }; |
| 28 | 29 | |
| @@ -94,16 +95,15 @@ static int pfe_pmbus_probe(struct i2c_client *client) · 65 unmodified lines | ||
| 94 | 95 | int model; |
| 95 | 96 | |
| 96 | 97 | model = (int)i2c_match_id(pfe_device_id, client)->driver_data; |
| 98 | + client->dev.platform_data = &pfe_plat_data; | |
| 97 | 99 | |
| 98 | 100 | /* |
| 99 | 101 | * PFE3000-12-069RA devices may not stay in page 0 during device |
| 100 | 102 | * probe which leads to probe failure (read status word failed). |
| 101 | 103 | * So let's set the device to page 0 at the beginning. |
| 102 | 104 | */ |
| 103 | − if (model == pfe3000) { | |
| 104 | − client->dev.platform_data = &pfe3000_plat_data; | |
| 105 | + if (model == pfe3000) | |
| 105 | 106 | i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0); |
| 106 | − } | |
| 107 | 107 | |
| 108 | 108 | return pmbus_do_probe(client, &pfe_driver_info[model]); |
| 109 | 109 | } |
| @@ -62,7 +62,6 @@ · 61 unmodified lines | ||
| 62 | 62 | #define AD7192_MODE_STA_MASK BIT(20) /* Status Register transmission Mask */ |
| 63 | 63 | #define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */ |
| 64 | 64 | #define AD7192_MODE_SINC3 BIT(15) /* SINC3 Filter Select */ |
| 65 | −#define AD7192_MODE_ACX BIT(14) /* AC excitation enable(AD7195 only)*/ | |
| 66 | 65 | #define AD7192_MODE_ENPAR BIT(13) /* Parity Enable */ |
| 67 | 66 | #define AD7192_MODE_CLKDIV BIT(12) /* Clock divide by 2 (AD7190/2 only)*/ |
| 68 | 67 | #define AD7192_MODE_SCYCLE BIT(11) /* Single cycle conversion */ |
| @@ -91,6 +90,7 @@ · 22 unmodified lines | ||
| 91 | 90 | /* Configuration Register Bit Designations (AD7192_REG_CONF) */ |
| 92 | 91 | |
| 93 | 92 | #define AD7192_CONF_CHOP BIT(23) /* CHOP enable */ |
| 93 | +#define AD7192_CONF_ACX BIT(22) /* AC excitation enable(AD7195 only) */ | |
| 94 | 94 | #define AD7192_CONF_REFSEL BIT(20) /* REFIN1/REFIN2 Reference Select */ |
| 95 | 95 | #define AD7192_CONF_CHAN(x) ((x) << 8) /* Channel select */ |
| 96 | 96 | #define AD7192_CONF_CHAN_MASK (0x7FF << 8) /* Channel select mask */ |
| @@ -472,7 +472,7 @@ static ssize_t ad7192_show_ac_excitation(struct device *dev, · 375 unmodified lines | ||
| 472 | 472 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 473 | 473 | struct ad7192_state *st = iio_priv(indio_dev); |
| 474 | 474 | |
| 475 | − return sysfs_emit(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX)); | |
| 475 | + return sysfs_emit(buf, "%d\n", !!(st->conf & AD7192_CONF_ACX)); | |
| 476 | 476 | } |
| 477 | 477 | |
| 478 | 478 | static ssize_t ad7192_show_bridge_switch(struct device *dev, |
| @@ -513,13 +513,13 @@ static ssize_t ad7192_set(struct device *dev, · 34 unmodified lines | ||
| 513 | 513 | |
| 514 | 514 | ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon); |
| 515 | 515 | break; |
| 516 | − case AD7192_REG_MODE: | |
| 516 | + case AD7192_REG_CONF: | |
| 517 | 517 | if (val) |
| 518 | − st->mode |= AD7192_MODE_ACX; | |
| 518 | + st->conf |= AD7192_CONF_ACX; | |
| 519 | 519 | else |
| 520 | − st->mode &= ~AD7192_MODE_ACX; | |
| 520 | + st->conf &= ~AD7192_CONF_ACX; | |
| 521 | 521 | |
| 522 | − ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); | |
| 522 | + ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); | |
| 523 | 523 | break; |
| 524 | 524 | default: |
| 525 | 525 | ret = -EINVAL; |
| @@ -579,12 +579,11 @@ static IIO_DEVICE_ATTR(bridge_switch_en, 0644, · 53 unmodified lines | ||
| 579 | 579 | |
| 580 | 580 | static IIO_DEVICE_ATTR(ac_excitation_en, 0644, |
| 581 | 581 | ad7192_show_ac_excitation, ad7192_set, |
| 582 | − AD7192_REG_MODE); | |
| 582 | + AD7192_REG_CONF); | |
| 583 | 583 | |
| 584 | 584 | static struct attribute *ad7192_attributes[] = { |
| 585 | 585 | &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, |
| 586 | 586 | &iio_dev_attr_bridge_switch_en.dev_attr.attr, |
| 587 | − &iio_dev_attr_ac_excitation_en.dev_attr.attr, | |
| 588 | 587 | NULL |
| 589 | 588 | }; |
| 590 | 589 | |
| @@ -595,6 +594,7 @@ static const struct attribute_group ad7192_attribute_group = { · 4 unmodified lines | ||
| 595 | 594 | static struct attribute *ad7195_attributes[] = { |
| 596 | 595 | &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, |
| 597 | 596 | &iio_dev_attr_bridge_switch_en.dev_attr.attr, |
| 597 | + &iio_dev_attr_ac_excitation_en.dev_attr.attr, | |
| 598 | 598 | NULL |
| 599 | 599 | }; |
| 600 | 600 | |
| @@ -124,6 +124,7 @@ static const struct regmap_config ina2xx_regmap_config = { · 123 unmodified lines | ||
| 124 | 124 | enum ina2xx_ids { ina219, ina226 }; |
| 125 | 125 | |
| 126 | 126 | struct ina2xx_config { |
| 127 | + const char *name; | |
| 127 | 128 | u16 config_default; |
| 128 | 129 | int calibration_value; |
| 129 | 130 | int shunt_voltage_lsb; /* nV */ |
| @@ -155,6 +156,7 @@ struct ina2xx_chip_info { · 25 unmodified lines | ||
| 155 | 156 | |
| 156 | 157 | static const struct ina2xx_config ina2xx_config[] = { |
| 157 | 158 | [ina219] = { |
| 159 | + .name = "ina219", | |
| 158 | 160 | .config_default = INA219_CONFIG_DEFAULT, |
| 159 | 161 | .calibration_value = 4096, |
| 160 | 162 | .shunt_voltage_lsb = 10000, |
| @@ -164,6 +166,7 @@ static const struct ina2xx_config ina2xx_config[] = { · 3 unmodified lines | ||
| 164 | 166 | .chip_id = ina219, |
| 165 | 167 | }, |
| 166 | 168 | [ina226] = { |
| 169 | + .name = "ina226", | |
| 167 | 170 | .config_default = INA226_CONFIG_DEFAULT, |
| 168 | 171 | .calibration_value = 2048, |
| 169 | 172 | .shunt_voltage_lsb = 2500, |
| @@ -996,7 +999,7 @@ static int ina2xx_probe(struct i2c_client *client) · 826 unmodified lines | ||
| 996 | 999 | /* Patch the current config register with default. */ |
| 997 | 1000 | val = chip->config->config_default; |
| 998 | 1001 | |
| 999 | − if (id->driver_data == ina226) { | |
| 1002 | + if (type == ina226) { | |
| 1000 | 1003 | ina226_set_average(chip, INA226_DEFAULT_AVG, &val); |
| 1001 | 1004 | ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val); |
| 1002 | 1005 | ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val); |
| @@ -1015,7 +1018,7 @@ static int ina2xx_probe(struct i2c_client *client) · 12 unmodified lines | ||
| 1015 | 1018 | } |
| 1016 | 1019 | |
| 1017 | 1020 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1018 | − if (id->driver_data == ina226) { | |
| 1021 | + if (type == ina226) { | |
| 1019 | 1022 | indio_dev->channels = ina226_channels; |
| 1020 | 1023 | indio_dev->num_channels = ARRAY_SIZE(ina226_channels); |
| 1021 | 1024 | indio_dev->info = &ina226_info; |
| @@ -1024,7 +1027,7 @@ static int ina2xx_probe(struct i2c_client *client) · 2 unmodified lines | ||
| 1024 | 1027 | indio_dev->num_channels = ARRAY_SIZE(ina219_channels); |
| 1025 | 1028 | indio_dev->info = &ina219_info; |
| 1026 | 1029 | } |
| 1027 | − indio_dev->name = id->name; | |
| 1030 | + indio_dev->name = id ? id->name : chip->config->name; | |
| 1028 | 1031 | |
| 1029 | 1032 | ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev, |
| 1030 | 1033 | &ina2xx_setup_ops); |
| @@ -916,12 +916,6 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) · 915 unmodified lines | ||
| 916 | 916 | goto err_vref; |
| 917 | 917 | } |
| 918 | 918 | |
| 919 | − ret = clk_prepare_enable(priv->core_clk); | |
| 920 | − if (ret) { | |
| 921 | − dev_err(dev, "failed to enable core clk\n"); | |
| 922 | − goto err_core_clk; | |
| 923 | − } | |
| 924 | − | |
| 925 | 919 | regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); |
| 926 | 920 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, |
| 927 | 921 | MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); |
| @@ -948,8 +942,6 @@ err_adc_clk: · 20 unmodified lines | ||
| 948 | 942 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, |
| 949 | 943 | MESON_SAR_ADC_REG3_ADC_EN, 0); |
| 950 | 944 | meson_sar_adc_set_bandgap(indio_dev, false); |
| 951 | − clk_disable_unprepare(priv->core_clk); | |
| 952 | −err_core_clk: | |
| 953 | 945 | regulator_disable(priv->vref); |
| 954 | 946 | err_vref: |
| 955 | 947 | meson_sar_adc_unlock(indio_dev); |
| @@ -977,8 +969,6 @@ static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev) · 21 unmodified lines | ||
| 977 | 969 | |
| 978 | 970 | meson_sar_adc_set_bandgap(indio_dev, false); |
| 979 | 971 | |
| 980 | − clk_disable_unprepare(priv->core_clk); | |
| 981 | − | |
| 982 | 972 | regulator_disable(priv->vref); |
| 983 | 973 | |
| 984 | 974 | if (!ret) |
| @@ -1211,7 +1201,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev) · 226 unmodified lines | ||
| 1211 | 1201 | if (IS_ERR(priv->clkin)) |
| 1212 | 1202 | return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n"); |
| 1213 | 1203 | |
| 1214 | − priv->core_clk = devm_clk_get(dev, "core"); | |
| 1204 | + priv->core_clk = devm_clk_get_enabled(dev, "core"); | |
| 1215 | 1205 | if (IS_ERR(priv->core_clk)) |
| 1216 | 1206 | return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n"); |
| 1217 | 1207 | |
| @@ -1294,15 +1284,26 @@ static int meson_sar_adc_remove(struct platform_device *pdev) · 76 unmodified lines | ||
| 1294 | 1284 | static int meson_sar_adc_suspend(struct device *dev) |
| 1295 | 1285 | { |
| 1296 | 1286 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
| 1287 | + struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
| 1297 | 1288 | |
| 1298 | 1289 | meson_sar_adc_hw_disable(indio_dev); |
| 1299 | 1290 | |
| 1291 | + clk_disable_unprepare(priv->core_clk); | |
| 1292 | + | |
| 1300 | 1293 | return 0; |
| 1301 | 1294 | } |
| 1302 | 1295 | |
| 1303 | 1296 | static int meson_sar_adc_resume(struct device *dev) |
| 1304 | 1297 | { |
| 1305 | 1298 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
| 1299 | + struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | |
| 1300 | + int ret; | |
| 1301 | + | |
| 1302 | + ret = clk_prepare_enable(priv->core_clk); | |
| 1303 | + if (ret) { | |
| 1304 | + dev_err(dev, "failed to enable core clk\n"); | |
| 1305 | + return ret; | |
| 1306 | + } | |
| 1306 | 1307 | |
| 1307 | 1308 | return meson_sar_adc_hw_enable(indio_dev); |
| 1308 | 1309 | } |
| @@ -253,7 +253,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, · 252 unmodified lines | ||
| 253 | 253 | platform_set_drvdata(pdev, indio_dev); |
| 254 | 254 | |
| 255 | 255 | state->ec = ec->ec_dev; |
| 256 | − state->msg = devm_kzalloc(&pdev->dev, | |
| 256 | + state->msg = devm_kzalloc(&pdev->dev, sizeof(*state->msg) + | |
| 257 | 257 | max((u16)sizeof(struct ec_params_motion_sense), |
| 258 | 258 | state->ec->max_response), GFP_KERNEL); |
| 259 | 259 | if (!state->msg) |
| @@ -344,9 +344,12 @@ static int admv1013_update_quad_filters(struct admv1013_state *st) · 343 unmodified lines | ||
| 344 | 344 | |
| 345 | 345 | static int admv1013_update_mixer_vgate(struct admv1013_state *st) |
| 346 | 346 | { |
| 347 | − unsigned int vcm, mixer_vgate; | |
| 347 | + unsigned int mixer_vgate; | |
| 348 | + int vcm; | |
| 348 | 349 | |
| 349 | 350 | vcm = regulator_get_voltage(st->reg); |
| 351 | + if (vcm < 0) | |
| 352 | + return vcm; | |
| 350 | 353 | |
| 351 | 354 | if (vcm < 1800000) |
| 352 | 355 | mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100; |
| @@ -2687,7 +2687,7 @@ unknown_format: · 2686 unmodified lines | ||
| 2687 | 2687 | static int lsm6dsx_get_acpi_mount_matrix(struct device *dev, |
| 2688 | 2688 | struct iio_mount_matrix *orientation) |
| 2689 | 2689 | { |
| 2690 | − return false; | |
| 2690 | + return -EOPNOTSUPP; | |
| 2691 | 2691 | } |
| 2692 | 2692 | |
| 2693 | 2693 | #endif |
| @@ -1888,7 +1888,7 @@ static const struct iio_buffer_setup_ops noop_ring_setup_ops; · 1887 unmodified lines | ||
| 1888 | 1888 | int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) |
| 1889 | 1889 | { |
| 1890 | 1890 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); |
| 1891 | − struct fwnode_handle *fwnode; | |
| 1891 | + struct fwnode_handle *fwnode = NULL; | |
| 1892 | 1892 | int ret; |
| 1893 | 1893 | |
| 1894 | 1894 | if (!indio_dev->info) |
| @@ -1899,7 +1899,8 @@ int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) · 4 unmodified lines | ||
| 1899 | 1899 | /* If the calling driver did not initialize firmware node, do it here */ |
| 1900 | 1900 | if (dev_fwnode(&indio_dev->dev)) |
| 1901 | 1901 | fwnode = dev_fwnode(&indio_dev->dev); |
| 1902 | − else | |
| 1902 | + /* The default dummy IIO device has no parent */ | |
| 1903 | + else if (indio_dev->dev.parent) | |
| 1903 | 1904 | fwnode = dev_fwnode(indio_dev->dev.parent); |
| 1904 | 1905 | device_set_node(&indio_dev->dev, fwnode); |
| 1905 | 1906 | |
| @@ -190,7 +190,7 @@ static const struct iio_itime_sel_mul bu27008_itimes[] = { · 189 unmodified lines | ||
| 190 | 190 | .address = BU27008_REG_##data##_LO, \ |
| 191 | 191 | .scan_index = BU27008_##color, \ |
| 192 | 192 | .scan_type = { \ |
| 193 | − .sign = 's', \ | |
| 193 | + .sign = 'u', \ | |
| 194 | 194 | .realbits = 16, \ |
| 195 | 195 | .storagebits = 16, \ |
| 196 | 196 | .endianness = IIO_LE, \ |
| @@ -633,7 +633,7 @@ static int bu27008_try_find_new_time_gain(struct bu27008_data *data, int val, · 436 unmodified lines | ||
| 633 | 633 | for (i = 0; i < data->gts.num_itime; i++) { |
| 634 | 634 | new_time_sel = data->gts.itime_table[i].sel; |
| 635 | 635 | ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, |
| 636 | − new_time_sel, val, val2 * 1000, gain_sel); | |
| 636 | + new_time_sel, val, val2, gain_sel); | |
| 637 | 637 | if (!ret) |
| 638 | 638 | break; |
| 639 | 639 | } |
| @@ -662,7 +662,7 @@ static int bu27008_set_scale(struct bu27008_data *data, · 22 unmodified lines | ||
| 662 | 662 | goto unlock_out; |
| 663 | 663 | |
| 664 | 664 | ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel, |
| 665 | − val, val2 * 1000, &gain_sel); | |
| 665 | + val, val2, &gain_sel); | |
| 666 | 666 | if (ret) { |
| 667 | 667 | ret = bu27008_try_find_new_time_gain(data, val, val2, &gain_sel); |
| 668 | 668 | if (ret) |
| @@ -677,6 +677,21 @@ unlock_out: · 8 unmodified lines | ||
| 677 | 677 | return ret; |
| 678 | 678 | } |
| 679 | 679 | |
| 680 | +static int bu27008_write_raw_get_fmt(struct iio_dev *indio_dev, | |
| 681 | + struct iio_chan_spec const *chan, | |
| 682 | + long mask) | |
| 683 | +{ | |
| 684 | + | |
| 685 | + switch (mask) { | |
| 686 | + case IIO_CHAN_INFO_SCALE: | |
| 687 | + return IIO_VAL_INT_PLUS_NANO; | |
| 688 | + case IIO_CHAN_INFO_INT_TIME: | |
| 689 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 690 | + default: | |
| 691 | + return -EINVAL; | |
| 692 | + } | |
| 693 | +} | |
| 694 | + | |
| 680 | 695 | static int bu27008_write_raw(struct iio_dev *idev, |
| 681 | 696 | struct iio_chan_spec const *chan, |
| 682 | 697 | int val, int val2, long mask) |
| @@ -756,6 +771,7 @@ static int bu27008_update_scan_mode(struct iio_dev *idev, · 73 unmodified lines | ||
| 756 | 771 | static const struct iio_info bu27008_info = { |
| 757 | 772 | .read_raw = &bu27008_read_raw, |
| 758 | 773 | .write_raw = &bu27008_write_raw, |
| 774 | + .write_raw_get_fmt = &bu27008_write_raw_get_fmt, | |
| 759 | 775 | .read_avail = &bu27008_read_avail, |
| 760 | 776 | .update_scan_mode = bu27008_update_scan_mode, |
| 761 | 777 | .validate_trigger = iio_validate_own_trigger, |
| @@ -575,7 +575,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan, · 574 unmodified lines | ||
| 575 | 575 | return -EINVAL; |
| 576 | 576 | |
| 577 | 577 | if (chan == BU27034_CHAN_ALS) { |
| 578 | − if (val == 0 && val2 == 1000) | |
| 578 | + if (val == 0 && val2 == 1000000) | |
| 579 | 579 | return 0; |
| 580 | 580 | |
| 581 | 581 | return -EINVAL; |
| @@ -587,7 +587,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan, · 5 unmodified lines | ||
| 587 | 587 | goto unlock_out; |
| 588 | 588 | |
| 589 | 589 | ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel, |
| 590 | − val, val2 * 1000, &gain_sel); | |
| 590 | + val, val2, &gain_sel); | |
| 591 | 591 | if (ret) { |
| 592 | 592 | /* |
| 593 | 593 | * Could not support scale with given time. Need to change time. |
| @@ -624,7 +624,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan, · 30 unmodified lines | ||
| 624 | 624 | |
| 625 | 625 | /* Can we provide requested scale with this time? */ |
| 626 | 626 | ret = iio_gts_find_gain_sel_for_scale_using_time( |
| 627 | − &data->gts, new_time_sel, val, val2 * 1000, | |
| 627 | + &data->gts, new_time_sel, val, val2, | |
| 628 | 628 | &gain_sel); |
| 629 | 629 | if (ret) |
| 630 | 630 | continue; |
| @@ -1217,6 +1217,21 @@ static int bu27034_read_raw(struct iio_dev *idev, · 586 unmodified lines | ||
| 1217 | 1217 | } |
| 1218 | 1218 | } |
| 1219 | 1219 | |
| 1220 | +static int bu27034_write_raw_get_fmt(struct iio_dev *indio_dev, | |
| 1221 | + struct iio_chan_spec const *chan, | |
| 1222 | + long mask) | |
| 1223 | +{ | |
| 1224 | + | |
| 1225 | + switch (mask) { | |
| 1226 | + case IIO_CHAN_INFO_SCALE: | |
| 1227 | + return IIO_VAL_INT_PLUS_NANO; | |
| 1228 | + case IIO_CHAN_INFO_INT_TIME: | |
| 1229 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 1230 | + default: | |
| 1231 | + return -EINVAL; | |
| 1232 | + } | |
| 1233 | +} | |
| 1234 | + | |
| 1220 | 1235 | static int bu27034_write_raw(struct iio_dev *idev, |
| 1221 | 1236 | struct iio_chan_spec const *chan, |
| 1222 | 1237 | int val, int val2, long mask) |
| @@ -1267,6 +1282,7 @@ static int bu27034_read_avail(struct iio_dev *idev, · 44 unmodified lines | ||
| 1267 | 1282 | static const struct iio_info bu27034_info = { |
| 1268 | 1283 | .read_raw = &bu27034_read_raw, |
| 1269 | 1284 | .write_raw = &bu27034_write_raw, |
| 1285 | + .write_raw_get_fmt = &bu27034_write_raw_get_fmt, | |
| 1270 | 1286 | .read_avail = &bu27034_read_avail, |
| 1271 | 1287 | }; |
| 1272 | 1288 | |
| @@ -85,6 +85,8 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem, · 84 unmodified lines | ||
| 85 | 85 | dma_addr_t mask; |
| 86 | 86 | int i; |
| 87 | 87 | |
| 88 | + umem->iova = va = virt; | |
| 89 | + | |
| 88 | 90 | if (umem->is_odp) { |
| 89 | 91 | unsigned int page_size = BIT(to_ib_umem_odp(umem)->page_shift); |
| 90 | 92 | |
| @@ -100,7 +102,6 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem, · 9 unmodified lines | ||
| 100 | 102 | */ |
| 101 | 103 | pgsz_bitmap &= GENMASK(BITS_PER_LONG - 1, PAGE_SHIFT); |
| 102 | 104 | |
| 103 | − umem->iova = va = virt; | |
| 104 | 105 | /* The best result is the smallest page size that results in the minimum |
| 105 | 106 | * number of required pages. Compute the largest page size that could |
| 106 | 107 | * work based on VA address bits that don't change. |
| @@ -1253,6 +1253,8 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode) · 1252 unmodified lines | ||
| 1253 | 1253 | |
| 1254 | 1254 | rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode); |
| 1255 | 1255 | if (rc) { |
| 1256 | + bnxt_unregister_dev(rdev->en_dev); | |
| 1257 | + clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags); | |
| 1256 | 1258 | ibdev_err(&rdev->ibdev, "Failed to get chip context\n"); |
| 1257 | 1259 | return -EINVAL; |
| 1258 | 1260 | } |
| @@ -1526,8 +1528,8 @@ static void bnxt_re_remove(struct auxiliary_device *adev) · 267 unmodified lines | ||
| 1526 | 1528 | } |
| 1527 | 1529 | bnxt_re_setup_cc(rdev, false); |
| 1528 | 1530 | ib_unregister_device(&rdev->ibdev); |
| 1529 | − ib_dealloc_device(&rdev->ibdev); | |
| 1530 | 1531 | bnxt_re_dev_uninit(rdev); |
| 1532 | + ib_dealloc_device(&rdev->ibdev); | |
| 1531 | 1533 | skip_remove: |
| 1532 | 1534 | mutex_unlock(&bnxt_re_mutex); |
| 1533 | 1535 | } |
| @@ -819,6 +819,7 @@ static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res, · 818 unmodified lines | ||
| 819 | 819 | } |
| 820 | 820 | |
| 821 | 821 | memset((u8 *)dpit->tbl, 0xFF, bytes); |
| 822 | + mutex_init(&res->dpi_tbl_lock); | |
| 822 | 823 | dpit->priv_db = dpit->ucreg.bar_reg + dpit->ucreg.offset; |
| 823 | 824 | |
| 824 | 825 | return 0; |
| @@ -12307,6 +12307,7 @@ static void free_cntrs(struct hfi1_devdata *dd) · 12306 unmodified lines | ||
| 12307 | 12307 | |
| 12308 | 12308 | if (dd->synth_stats_timer.function) |
| 12309 | 12309 | del_timer_sync(&dd->synth_stats_timer); |
| 12310 | + cancel_work_sync(&dd->update_cntr_work); | |
| 12310 | 12311 | ppd = (struct hfi1_pportdata *)(dd + 1); |
| 12311 | 12312 | for (i = 0; i < dd->num_pports; i++, ppd++) { |
| 12312 | 12313 | kfree(ppd->cntrs); |
| @@ -83,6 +83,11 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm) · 82 unmodified lines | ||
| 83 | 83 | |
| 84 | 84 | temp = agg_peak[bucket] * bcm->vote_scale; |
| 85 | 85 | bcm->vote_y[bucket] = bcm_div(temp, bcm->aux_data.unit); |
| 86 | + | |
| 87 | + if (bcm->enable_mask && (bcm->vote_x[bucket] || bcm->vote_y[bucket])) { | |
| 88 | + bcm->vote_x[bucket] = 0; | |
| 89 | + bcm->vote_y[bucket] = bcm->enable_mask; | |
| 90 | + } | |
| 86 | 91 | } |
| 87 | 92 | |
| 88 | 93 | if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 && |
| @@ -81,6 +81,7 @@ struct qcom_icc_node { · 80 unmodified lines | ||
| 81 | 81 | * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm |
| 82 | 82 | * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm |
| 83 | 83 | * @vote_scale: scaling factor for vote_x and vote_y |
| 84 | + * @enable_mask: optional mask to send as vote instead of vote_x/vote_y | |
| 84 | 85 | * @dirty: flag used to indicate whether the bcm needs to be committed |
| 85 | 86 | * @keepalive: flag used to indicate whether a keepalive is required |
| 86 | 87 | * @aux_data: auxiliary data used when calculating threshold values and |
| @@ -97,6 +98,7 @@ struct qcom_icc_bcm { · 10 unmodified lines | ||
| 97 | 98 | u64 vote_x[QCOM_ICC_NUM_BUCKETS]; |
| 98 | 99 | u64 vote_y[QCOM_ICC_NUM_BUCKETS]; |
| 99 | 100 | u64 vote_scale; |
| 101 | + u32 enable_mask; | |
| 100 | 102 | bool dirty; |
| 101 | 103 | bool keepalive; |
| 102 | 104 | struct bcm_db aux_data; |
| @@ -1873,6 +1873,7 @@ static struct qcom_icc_node srvc_snoc = { · 1872 unmodified lines | ||
| 1873 | 1873 | |
| 1874 | 1874 | static struct qcom_icc_bcm bcm_acv = { |
| 1875 | 1875 | .name = "ACV", |
| 1876 | + .enable_mask = 0x8, | |
| 1876 | 1877 | .num_nodes = 1, |
| 1877 | 1878 | .nodes = { &ebi }, |
| 1878 | 1879 | }; |
| @@ -1337,6 +1337,7 @@ static struct qcom_icc_node qns_mem_noc_sf_disp = { · 1336 unmodified lines | ||
| 1337 | 1337 | |
| 1338 | 1338 | static struct qcom_icc_bcm bcm_acv = { |
| 1339 | 1339 | .name = "ACV", |
| 1340 | + .enable_mask = 0x8, | |
| 1340 | 1341 | .num_nodes = 1, |
| 1341 | 1342 | .nodes = { &ebi }, |
| 1342 | 1343 | }; |
| @@ -1349,6 +1350,7 @@ static struct qcom_icc_bcm bcm_ce0 = { · 6 unmodified lines | ||
| 1349 | 1350 | |
| 1350 | 1351 | static struct qcom_icc_bcm bcm_cn0 = { |
| 1351 | 1352 | .name = "CN0", |
| 1353 | + .enable_mask = 0x1, | |
| 1352 | 1354 | .keepalive = true, |
| 1353 | 1355 | .num_nodes = 55, |
| 1354 | 1356 | .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie, |
| @@ -1383,6 +1385,7 @@ static struct qcom_icc_bcm bcm_cn0 = { · 28 unmodified lines | ||
| 1383 | 1385 | |
| 1384 | 1386 | static struct qcom_icc_bcm bcm_co0 = { |
| 1385 | 1387 | .name = "CO0", |
| 1388 | + .enable_mask = 0x1, | |
| 1386 | 1389 | .num_nodes = 2, |
| 1387 | 1390 | .nodes = { &qxm_nsp, &qns_nsp_gemnoc }, |
| 1388 | 1391 | }; |
| @@ -1403,6 +1406,7 @@ static struct qcom_icc_bcm bcm_mm0 = { · 14 unmodified lines | ||
| 1403 | 1406 | |
| 1404 | 1407 | static struct qcom_icc_bcm bcm_mm1 = { |
| 1405 | 1408 | .name = "MM1", |
| 1409 | + .enable_mask = 0x1, | |
| 1406 | 1410 | .num_nodes = 12, |
| 1407 | 1411 | .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp, |
| 1408 | 1412 | &qnm_camnoc_sf, &qnm_mdp, |
| @@ -1445,6 +1449,7 @@ static struct qcom_icc_bcm bcm_sh0 = { · 36 unmodified lines | ||
| 1445 | 1449 | |
| 1446 | 1450 | static struct qcom_icc_bcm bcm_sh1 = { |
| 1447 | 1451 | .name = "SH1", |
| 1452 | + .enable_mask = 0x1, | |
| 1448 | 1453 | .num_nodes = 7, |
| 1449 | 1454 | .nodes = { &alm_gpu_tcu, &alm_sys_tcu, |
| 1450 | 1455 | &qnm_nsp_gemnoc, &qnm_pcie, |
| @@ -1461,6 +1466,7 @@ static struct qcom_icc_bcm bcm_sn0 = { · 10 unmodified lines | ||
| 1461 | 1466 | |
| 1462 | 1467 | static struct qcom_icc_bcm bcm_sn1 = { |
| 1463 | 1468 | .name = "SN1", |
| 1469 | + .enable_mask = 0x1, | |
| 1464 | 1470 | .num_nodes = 4, |
| 1465 | 1471 | .nodes = { &qhm_gic, &qxm_pimem, |
| 1466 | 1472 | &xm_gic, &qns_gemnoc_gc }, |
| @@ -1492,6 +1498,7 @@ static struct qcom_icc_bcm bcm_sn7 = { · 25 unmodified lines | ||
| 1492 | 1498 | |
| 1493 | 1499 | static struct qcom_icc_bcm bcm_acv_disp = { |
| 1494 | 1500 | .name = "ACV", |
| 1501 | + .enable_mask = 0x1, | |
| 1495 | 1502 | .num_nodes = 1, |
| 1496 | 1503 | .nodes = { &ebi_disp }, |
| 1497 | 1504 | }; |
| @@ -1510,6 +1517,7 @@ static struct qcom_icc_bcm bcm_mm0_disp = { · 12 unmodified lines | ||
| 1510 | 1517 | |
| 1511 | 1518 | static struct qcom_icc_bcm bcm_mm1_disp = { |
| 1512 | 1519 | .name = "MM1", |
| 1520 | + .enable_mask = 0x1, | |
| 1513 | 1521 | .num_nodes = 3, |
| 1514 | 1522 | .nodes = { &qnm_mdp_disp, &qnm_rot_disp, |
| 1515 | 1523 | &qns_mem_noc_sf_disp }, |
| @@ -1523,6 +1531,7 @@ static struct qcom_icc_bcm bcm_sh0_disp = { · 7 unmodified lines | ||
| 1523 | 1531 | |
| 1524 | 1532 | static struct qcom_icc_bcm bcm_sh1_disp = { |
| 1525 | 1533 | .name = "SH1", |
| 1534 | + .enable_mask = 0x1, | |
| 1526 | 1535 | .num_nodes = 1, |
| 1527 | 1536 | .nodes = { &qnm_pcie_disp }, |
| 1528 | 1537 | }; |
| @@ -1473,6 +1473,7 @@ static struct qcom_icc_node qns_mem_noc_sf_cam_ife_2 = { · 1472 unmodified lines | ||
| 1473 | 1473 | |
| 1474 | 1474 | static struct qcom_icc_bcm bcm_acv = { |
| 1475 | 1475 | .name = "ACV", |
| 1476 | + .enable_mask = 0x8, | |
| 1476 | 1477 | .num_nodes = 1, |
| 1477 | 1478 | .nodes = { &ebi }, |
| 1478 | 1479 | }; |
| @@ -1485,6 +1486,7 @@ static struct qcom_icc_bcm bcm_ce0 = { · 6 unmodified lines | ||
| 1485 | 1486 | |
| 1486 | 1487 | static struct qcom_icc_bcm bcm_cn0 = { |
| 1487 | 1488 | .name = "CN0", |
| 1489 | + .enable_mask = 0x1, | |
| 1488 | 1490 | .keepalive = true, |
| 1489 | 1491 | .num_nodes = 54, |
| 1490 | 1492 | .nodes = { &qsm_cfg, &qhs_ahb2phy0, |
| @@ -1524,6 +1526,7 @@ static struct qcom_icc_bcm bcm_cn1 = { · 33 unmodified lines | ||
| 1524 | 1526 | |
| 1525 | 1527 | static struct qcom_icc_bcm bcm_co0 = { |
| 1526 | 1528 | .name = "CO0", |
| 1529 | + .enable_mask = 0x1, | |
| 1527 | 1530 | .num_nodes = 2, |
| 1528 | 1531 | .nodes = { &qxm_nsp, &qns_nsp_gemnoc }, |
| 1529 | 1532 | }; |
| @@ -1549,6 +1552,7 @@ static struct qcom_icc_bcm bcm_mm0 = { · 19 unmodified lines | ||
| 1549 | 1552 | |
| 1550 | 1553 | static struct qcom_icc_bcm bcm_mm1 = { |
| 1551 | 1554 | .name = "MM1", |
| 1555 | + .enable_mask = 0x1, | |
| 1552 | 1556 | .num_nodes = 8, |
| 1553 | 1557 | .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp, |
| 1554 | 1558 | &qnm_camnoc_sf, &qnm_vapss_hcp, |
| @@ -1589,6 +1593,7 @@ static struct qcom_icc_bcm bcm_sh0 = { · 34 unmodified lines | ||
| 1589 | 1593 | |
| 1590 | 1594 | static struct qcom_icc_bcm bcm_sh1 = { |
| 1591 | 1595 | .name = "SH1", |
| 1596 | + .enable_mask = 0x1, | |
| 1592 | 1597 | .num_nodes = 13, |
| 1593 | 1598 | .nodes = { &alm_gpu_tcu, &alm_sys_tcu, |
| 1594 | 1599 | &chm_apps, &qnm_gpu, |
| @@ -1608,6 +1613,7 @@ static struct qcom_icc_bcm bcm_sn0 = { · 13 unmodified lines | ||
| 1608 | 1613 | |
| 1609 | 1614 | static struct qcom_icc_bcm bcm_sn1 = { |
| 1610 | 1615 | .name = "SN1", |
| 1616 | + .enable_mask = 0x1, | |
| 1611 | 1617 | .num_nodes = 3, |
| 1612 | 1618 | .nodes = { &qhm_gic, &xm_gic, |
| 1613 | 1619 | &qns_gemnoc_gc }, |
| @@ -1633,6 +1639,7 @@ static struct qcom_icc_bcm bcm_sn7 = { · 19 unmodified lines | ||
| 1633 | 1639 | |
| 1634 | 1640 | static struct qcom_icc_bcm bcm_acv_disp = { |
| 1635 | 1641 | .name = "ACV", |
| 1642 | + .enable_mask = 0x1, | |
| 1636 | 1643 | .num_nodes = 1, |
| 1637 | 1644 | .nodes = { &ebi_disp }, |
| 1638 | 1645 | }; |
| @@ -1657,12 +1664,14 @@ static struct qcom_icc_bcm bcm_sh0_disp = { · 18 unmodified lines | ||
| 1657 | 1664 | |
| 1658 | 1665 | static struct qcom_icc_bcm bcm_sh1_disp = { |
| 1659 | 1666 | .name = "SH1", |
| 1667 | + .enable_mask = 0x1, | |
| 1660 | 1668 | .num_nodes = 2, |
| 1661 | 1669 | .nodes = { &qnm_mnoc_hf_disp, &qnm_pcie_disp }, |
| 1662 | 1670 | }; |
| 1663 | 1671 | |
| 1664 | 1672 | static struct qcom_icc_bcm bcm_acv_cam_ife_0 = { |
| 1665 | 1673 | .name = "ACV", |
| 1674 | + .enable_mask = 0x0, | |
| 1666 | 1675 | .num_nodes = 1, |
| 1667 | 1676 | .nodes = { &ebi_cam_ife_0 }, |
| 1668 | 1677 | }; |
| @@ -1681,6 +1690,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_0 = { · 12 unmodified lines | ||
| 1681 | 1690 | |
| 1682 | 1691 | static struct qcom_icc_bcm bcm_mm1_cam_ife_0 = { |
| 1683 | 1692 | .name = "MM1", |
| 1693 | + .enable_mask = 0x1, | |
| 1684 | 1694 | .num_nodes = 4, |
| 1685 | 1695 | .nodes = { &qnm_camnoc_hf_cam_ife_0, &qnm_camnoc_icp_cam_ife_0, |
| 1686 | 1696 | &qnm_camnoc_sf_cam_ife_0, &qns_mem_noc_sf_cam_ife_0 }, |
| @@ -1694,6 +1704,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_0 = { · 7 unmodified lines | ||
| 1694 | 1704 | |
| 1695 | 1705 | static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = { |
| 1696 | 1706 | .name = "SH1", |
| 1707 | + .enable_mask = 0x1, | |
| 1697 | 1708 | .num_nodes = 3, |
| 1698 | 1709 | .nodes = { &qnm_mnoc_hf_cam_ife_0, &qnm_mnoc_sf_cam_ife_0, |
| 1699 | 1710 | &qnm_pcie_cam_ife_0 }, |
| @@ -1701,6 +1712,7 @@ static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = { · 1 unmodified line | ||
| 1701 | 1712 | |
| 1702 | 1713 | static struct qcom_icc_bcm bcm_acv_cam_ife_1 = { |
| 1703 | 1714 | .name = "ACV", |
| 1715 | + .enable_mask = 0x0, | |
| 1704 | 1716 | .num_nodes = 1, |
| 1705 | 1717 | .nodes = { &ebi_cam_ife_1 }, |
| 1706 | 1718 | }; |
| @@ -1719,6 +1731,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_1 = { · 12 unmodified lines | ||
| 1719 | 1731 | |
| 1720 | 1732 | static struct qcom_icc_bcm bcm_mm1_cam_ife_1 = { |
| 1721 | 1733 | .name = "MM1", |
| 1734 | + .enable_mask = 0x1, | |
| 1722 | 1735 | .num_nodes = 4, |
| 1723 | 1736 | .nodes = { &qnm_camnoc_hf_cam_ife_1, &qnm_camnoc_icp_cam_ife_1, |
| 1724 | 1737 | &qnm_camnoc_sf_cam_ife_1, &qns_mem_noc_sf_cam_ife_1 }, |
| @@ -1732,6 +1745,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_1 = { · 7 unmodified lines | ||
| 1732 | 1745 | |
| 1733 | 1746 | static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = { |
| 1734 | 1747 | .name = "SH1", |
| 1748 | + .enable_mask = 0x1, | |
| 1735 | 1749 | .num_nodes = 3, |
| 1736 | 1750 | .nodes = { &qnm_mnoc_hf_cam_ife_1, &qnm_mnoc_sf_cam_ife_1, |
| 1737 | 1751 | &qnm_pcie_cam_ife_1 }, |
| @@ -1739,6 +1753,7 @@ static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = { · 1 unmodified line | ||
| 1739 | 1753 | |
| 1740 | 1754 | static struct qcom_icc_bcm bcm_acv_cam_ife_2 = { |
| 1741 | 1755 | .name = "ACV", |
| 1756 | + .enable_mask = 0x0, | |
| 1742 | 1757 | .num_nodes = 1, |
| 1743 | 1758 | .nodes = { &ebi_cam_ife_2 }, |
| 1744 | 1759 | }; |
| @@ -1757,6 +1772,7 @@ static struct qcom_icc_bcm bcm_mm0_cam_ife_2 = { · 12 unmodified lines | ||
| 1757 | 1772 | |
| 1758 | 1773 | static struct qcom_icc_bcm bcm_mm1_cam_ife_2 = { |
| 1759 | 1774 | .name = "MM1", |
| 1775 | + .enable_mask = 0x1, | |
| 1760 | 1776 | .num_nodes = 4, |
| 1761 | 1777 | .nodes = { &qnm_camnoc_hf_cam_ife_2, &qnm_camnoc_icp_cam_ife_2, |
| 1762 | 1778 | &qnm_camnoc_sf_cam_ife_2, &qns_mem_noc_sf_cam_ife_2 }, |
| @@ -1770,6 +1786,7 @@ static struct qcom_icc_bcm bcm_sh0_cam_ife_2 = { · 7 unmodified lines | ||
| 1770 | 1786 | |
| 1771 | 1787 | static struct qcom_icc_bcm bcm_sh1_cam_ife_2 = { |
| 1772 | 1788 | .name = "SH1", |
| 1789 | + .enable_mask = 0x1, | |
| 1773 | 1790 | .num_nodes = 3, |
| 1774 | 1791 | .nodes = { &qnm_mnoc_hf_cam_ife_2, &qnm_mnoc_sf_cam_ife_2, |
| 1775 | 1792 | &qnm_pcie_cam_ife_2 }, |
| @@ -839,7 +839,7 @@ hfcpci_fill_fifo(struct bchannel *bch) · 838 unmodified lines | ||
| 839 | 839 | *z1t = cpu_to_le16(new_z1); /* now send data */ |
| 840 | 840 | if (bch->tx_idx < bch->tx_skb->len) |
| 841 | 841 | return; |
| 842 | − dev_kfree_skb(bch->tx_skb); | |
| 842 | + dev_kfree_skb_any(bch->tx_skb); | |
| 843 | 843 | if (get_next_bframe(bch)) |
| 844 | 844 | goto next_t_frame; |
| 845 | 845 | return; |
| @@ -895,7 +895,7 @@ hfcpci_fill_fifo(struct bchannel *bch) · 49 unmodified lines | ||
| 895 | 895 | } |
| 896 | 896 | bz->za[new_f1].z1 = cpu_to_le16(new_z1); /* for next buffer */ |
| 897 | 897 | bz->f1 = new_f1; /* next frame */ |
| 898 | − dev_kfree_skb(bch->tx_skb); | |
| 898 | + dev_kfree_skb_any(bch->tx_skb); | |
| 899 | 899 | get_next_bframe(bch); |
| 900 | 900 | } |
| 901 | 901 | |
| @@ -1119,7 +1119,7 @@ tx_birq(struct bchannel *bch) · 217 unmodified lines | ||
| 1119 | 1119 | if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) |
| 1120 | 1120 | hfcpci_fill_fifo(bch); |
| 1121 | 1121 | else { |
| 1122 | − dev_kfree_skb(bch->tx_skb); | |
| 1122 | + dev_kfree_skb_any(bch->tx_skb); | |
| 1123 | 1123 | if (get_next_bframe(bch)) |
| 1124 | 1124 | hfcpci_fill_fifo(bch); |
| 1125 | 1125 | } |
| @@ -2277,7 +2277,7 @@ _hfcpci_softirq(struct device *dev, void *unused) · 1151 unmodified lines | ||
| 2277 | 2277 | return 0; |
| 2278 | 2278 | |
| 2279 | 2279 | if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) { |
| 2280 | − spin_lock(&hc->lock); | |
| 2280 | + spin_lock_irq(&hc->lock); | |
| 2281 | 2281 | bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1); |
| 2282 | 2282 | if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */ |
| 2283 | 2283 | main_rec_hfcpci(bch); |
| @@ -2288,7 +2288,7 @@ _hfcpci_softirq(struct device *dev, void *unused) · 4 unmodified lines | ||
| 2288 | 2288 | main_rec_hfcpci(bch); |
| 2289 | 2289 | tx_birq(bch); |
| 2290 | 2290 | } |
| 2291 | − spin_unlock(&hc->lock); | |
| 2291 | + spin_unlock_irq(&hc->lock); | |
| 2292 | 2292 | } |
| 2293 | 2293 | return 0; |
| 2294 | 2294 | } |
| @@ -247,7 +247,7 @@ extern void dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp); · 246 unmodified lines | ||
| 247 | 247 | extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id); |
| 248 | 248 | extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb); |
| 249 | 249 | extern void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb); |
| 250 | −extern void dsp_cmx_send(void *arg); | |
| 250 | +extern void dsp_cmx_send(struct timer_list *arg); | |
| 251 | 251 | extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb); |
| 252 | 252 | extern int dsp_cmx_del_conf_member(struct dsp *dsp); |
| 253 | 253 | extern int dsp_cmx_del_conf(struct dsp_conf *conf); |
| @@ -1614,7 +1614,7 @@ static u16 dsp_count; /* last sample count */ · 1613 unmodified lines | ||
| 1614 | 1614 | static int dsp_count_valid; /* if we have last sample count */ |
| 1615 | 1615 | |
| 1616 | 1616 | void |
| 1617 | −dsp_cmx_send(void *arg) | |
| 1617 | +dsp_cmx_send(struct timer_list *arg) | |
| 1618 | 1618 | { |
| 1619 | 1619 | struct dsp_conf *conf; |
| 1620 | 1620 | struct dsp_conf_member *member; |
| @@ -1195,7 +1195,7 @@ static int __init dsp_init(void) · 1194 unmodified lines | ||
| 1195 | 1195 | } |
| 1196 | 1196 | |
| 1197 | 1197 | /* set sample timer */ |
| 1198 | − timer_setup(&dsp_spl_tl, (void *)dsp_cmx_send, 0); | |
| 1198 | + timer_setup(&dsp_spl_tl, dsp_cmx_send, 0); | |
| 1199 | 1199 | dsp_spl_tl.expires = jiffies + dsp_tics; |
| 1200 | 1200 | dsp_spl_jiffies = dsp_spl_tl.expires; |
| 1201 | 1201 | add_timer(&dsp_spl_tl); |
| @@ -251,8 +251,8 @@ int pkt_session_unset_buffers(struct hfi_session_release_buffer_pkt *pkt, · 250 unmodified lines | ||
| 251 | 251 | |
| 252 | 252 | pkt->extradata_size = 0; |
| 253 | 253 | pkt->shdr.hdr.size = |
| 254 | − struct_size((struct hfi_session_set_buffers_pkt *)0, | |
| 255 | − buffer_info, bd->num_buffers); | |
| 254 | + struct_size_t(struct hfi_session_set_buffers_pkt, | |
| 255 | + buffer_info, bd->num_buffers); | |
| 256 | 256 | } |
| 257 | 257 | |
| 258 | 258 | pkt->response_req = bd->response_required; |
| @@ -755,6 +755,43 @@ const char *const tegra_mc_error_names[8] = { · 754 unmodified lines | ||
| 755 | 755 | [6] = "SMMU translation error", |
| 756 | 756 | }; |
| 757 | 757 | |
| 758 | +struct icc_node *tegra_mc_icc_xlate(struct of_phandle_args *spec, void *data) | |
| 759 | +{ | |
| 760 | + struct tegra_mc *mc = icc_provider_to_tegra_mc(data); | |
| 761 | + struct icc_node *node; | |
| 762 | + | |
| 763 | + list_for_each_entry(node, &mc->provider.nodes, node_list) { | |
| 764 | + if (node->id == spec->args[0]) | |
| 765 | + return node; | |
| 766 | + } | |
| 767 | + | |
| 768 | + /* | |
| 769 | + * If a client driver calls devm_of_icc_get() before the MC driver | |
| 770 | + * is probed, then return EPROBE_DEFER to the client driver. | |
| 771 | + */ | |
| 772 | + return ERR_PTR(-EPROBE_DEFER); | |
| 773 | +} | |
| 774 | + | |
| 775 | +static int tegra_mc_icc_get(struct icc_node *node, u32 *average, u32 *peak) | |
| 776 | +{ | |
| 777 | + *average = 0; | |
| 778 | + *peak = 0; | |
| 779 | + | |
| 780 | + return 0; | |
| 781 | +} | |
| 782 | + | |
| 783 | +static int tegra_mc_icc_set(struct icc_node *src, struct icc_node *dst) | |
| 784 | +{ | |
| 785 | + return 0; | |
| 786 | +} | |
| 787 | + | |
| 788 | +const struct tegra_mc_icc_ops tegra_mc_icc_ops = { | |
| 789 | + .xlate = tegra_mc_icc_xlate, | |
| 790 | + .aggregate = icc_std_aggregate, | |
| 791 | + .get_bw = tegra_mc_icc_get, | |
| 792 | + .set = tegra_mc_icc_set, | |
| 793 | +}; | |
| 794 | + | |
| 758 | 795 | /* |
| 759 | 796 | * Memory Controller (MC) has few Memory Clients that are issuing memory |
| 760 | 797 | * bandwidth allocation requests to the MC interconnect provider. The MC |
| @@ -1355,6 +1355,7 @@ const struct tegra_mc_soc tegra194_mc_soc = { · 1354 unmodified lines | ||
| 1355 | 1355 | MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, |
| 1356 | 1356 | .has_addr_hi_reg = true, |
| 1357 | 1357 | .ops = &tegra186_mc_ops, |
| 1358 | + .icc_ops = &tegra_mc_icc_ops, | |
| 1358 | 1359 | .ch_intmask = 0x00000f00, |
| 1359 | 1360 | .global_intstatus_channel_shift = 8, |
| 1360 | 1361 | }; |
| @@ -827,7 +827,7 @@ static int tegra234_mc_icc_set(struct icc_node *src, struct icc_node *dst) · 826 unmodified lines | ||
| 827 | 827 | return 0; |
| 828 | 828 | |
| 829 | 829 | if (!mc->bwmgr_mrq_supported) |
| 830 | − return -EINVAL; | |
| 830 | + return 0; | |
| 831 | 831 | |
| 832 | 832 | if (!mc->bpmp) { |
| 833 | 833 | dev_err(mc->dev, "BPMP reference NULL\n"); |
| @@ -874,7 +874,7 @@ static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, · 40 unmodified lines | ||
| 874 | 874 | struct tegra_mc *mc = icc_provider_to_tegra_mc(p); |
| 875 | 875 | |
| 876 | 876 | if (!mc->bwmgr_mrq_supported) |
| 877 | − return -EINVAL; | |
| 877 | + return 0; | |
| 878 | 878 | |
| 879 | 879 | if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 || |
| 880 | 880 | node->id == TEGRA_ICC_MC_CPU_CLUSTER1 || |
| @@ -889,27 +889,6 @@ static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw, · 8 unmodified lines | ||
| 889 | 889 | return 0; |
| 890 | 890 | } |
| 891 | 891 | |
| 892 | −static struct icc_node* | |
| 893 | −tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data) | |
| 894 | −{ | |
| 895 | − struct tegra_mc *mc = icc_provider_to_tegra_mc(data); | |
| 896 | − unsigned int cl_id = spec->args[0]; | |
| 897 | − struct icc_node *node; | |
| 898 | − | |
| 899 | − list_for_each_entry(node, &mc->provider.nodes, node_list) { | |
| 900 | − if (node->id != cl_id) | |
| 901 | − continue; | |
| 902 | − | |
| 903 | − return node; | |
| 904 | − } | |
| 905 | − | |
| 906 | − /* | |
| 907 | − * If a client driver calls devm_of_icc_get() before the MC driver | |
| 908 | − * is probed, then return EPROBE_DEFER to the client driver. | |
| 909 | − */ | |
| 910 | − return ERR_PTR(-EPROBE_DEFER); | |
| 911 | −} | |
| 912 | − | |
| 913 | 892 | static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) |
| 914 | 893 | { |
| 915 | 894 | *avg = 0; |
| @@ -919,7 +898,7 @@ static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea · 3 unmodified lines | ||
| 919 | 898 | } |
| 920 | 899 | |
| 921 | 900 | static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = { |
| 922 | − .xlate = tegra234_mc_of_icc_xlate, | |
| 901 | + .xlate = tegra_mc_icc_xlate, | |
| 923 | 902 | .aggregate = tegra234_mc_icc_aggregate, |
| 924 | 903 | .get_bw = tegra234_mc_icc_get_init_bw, |
| 925 | 904 | .set = tegra234_mc_icc_set, |
| @@ -195,7 +195,7 @@ static int rts5227_extra_init_hw(struct rtsx_pcr *pcr) · 194 unmodified lines | ||
| 195 | 195 | } |
| 196 | 196 | } |
| 197 | 197 | |
| 198 | − if (option->force_clkreq_0) | |
| 198 | + if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG) | |
| 199 | 199 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, |
| 200 | 200 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); |
| 201 | 201 | else |
| @@ -435,17 +435,10 @@ static void rts5228_init_from_cfg(struct rtsx_pcr *pcr) · 434 unmodified lines | ||
| 435 | 435 | option->ltr_enabled = false; |
| 436 | 436 | } |
| 437 | 437 | } |
| 438 | − | |
| 439 | − if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
| 440 | − | PM_L1_1_EN | PM_L1_2_EN)) | |
| 441 | − option->force_clkreq_0 = false; | |
| 442 | − else | |
| 443 | − option->force_clkreq_0 = true; | |
| 444 | 438 | } |
| 445 | 439 | |
| 446 | 440 | static int rts5228_extra_init_hw(struct rtsx_pcr *pcr) |
| 447 | 441 | { |
| 448 | − struct rtsx_cr_option *option = &pcr->option; | |
| 449 | 442 | |
| 450 | 443 | rtsx_pci_write_register(pcr, RTS5228_AUTOLOAD_CFG1, |
| 451 | 444 | CD_RESUME_EN_MASK, CD_RESUME_EN_MASK); |
| @@ -476,17 +469,6 @@ static int rts5228_extra_init_hw(struct rtsx_pcr *pcr) · 24 unmodified lines | ||
| 476 | 469 | else |
| 477 | 470 | rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00); |
| 478 | 471 | |
| 479 | − /* | |
| 480 | − * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced | |
| 481 | − * to drive low, and we forcibly request clock. | |
| 482 | − */ | |
| 483 | − if (option->force_clkreq_0) | |
| 484 | − rtsx_pci_write_register(pcr, PETXCFG, | |
| 485 | − FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); | |
| 486 | − else | |
| 487 | − rtsx_pci_write_register(pcr, PETXCFG, | |
| 488 | − FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); | |
| 489 | − | |
| 490 | 472 | rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); |
| 491 | 473 | |
| 492 | 474 | if (pcr->rtd3_en) { |
| @@ -327,12 +327,11 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) · 326 unmodified lines | ||
| 327 | 327 | } |
| 328 | 328 | } |
| 329 | 329 | |
| 330 | − | |
| 331 | 330 | /* |
| 332 | 331 | * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced |
| 333 | 332 | * to drive low, and we forcibly request clock. |
| 334 | 333 | */ |
| 335 | − if (option->force_clkreq_0) | |
| 334 | + if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG) | |
| 336 | 335 | rtsx_pci_write_register(pcr, PETXCFG, |
| 337 | 336 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); |
| 338 | 337 | else |
| @@ -517,17 +517,10 @@ static void rts5260_init_from_cfg(struct rtsx_pcr *pcr) · 516 unmodified lines | ||
| 517 | 517 | option->ltr_enabled = false; |
| 518 | 518 | } |
| 519 | 519 | } |
| 520 | − | |
| 521 | − if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
| 522 | − | PM_L1_1_EN | PM_L1_2_EN)) | |
| 523 | − option->force_clkreq_0 = false; | |
| 524 | − else | |
| 525 | − option->force_clkreq_0 = true; | |
| 526 | 520 | } |
| 527 | 521 | |
| 528 | 522 | static int rts5260_extra_init_hw(struct rtsx_pcr *pcr) |
| 529 | 523 | { |
| 530 | − struct rtsx_cr_option *option = &pcr->option; | |
| 531 | 524 | |
| 532 | 525 | /* Set mcu_cnt to 7 to ensure data can be sampled properly */ |
| 533 | 526 | rtsx_pci_write_register(pcr, 0xFC03, 0x7F, 0x07); |
| @@ -546,17 +539,6 @@ static int rts5260_extra_init_hw(struct rtsx_pcr *pcr) · 12 unmodified lines | ||
| 546 | 539 | |
| 547 | 540 | rts5260_init_hw(pcr); |
| 548 | 541 | |
| 549 | − /* | |
| 550 | − * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced | |
| 551 | − * to drive low, and we forcibly request clock. | |
| 552 | − */ | |
| 553 | − if (option->force_clkreq_0) | |
| 554 | − rtsx_pci_write_register(pcr, PETXCFG, | |
| 555 | − FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); | |
| 556 | − else | |
| 557 | − rtsx_pci_write_register(pcr, PETXCFG, | |
| 558 | − FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); | |
| 559 | − | |
| 560 | 542 | rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00); |
| 561 | 543 | |
| 562 | 544 | return 0; |
| @@ -498,17 +498,10 @@ static void rts5261_init_from_cfg(struct rtsx_pcr *pcr) · 497 unmodified lines | ||
| 498 | 498 | option->ltr_enabled = false; |
| 499 | 499 | } |
| 500 | 500 | } |
| 501 | − | |
| 502 | − if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN | |
| 503 | − | PM_L1_1_EN | PM_L1_2_EN)) | |
| 504 | − option->force_clkreq_0 = false; | |
| 505 | − else | |
| 506 | − option->force_clkreq_0 = true; | |
| 507 | 501 | } |
| 508 | 502 | |
| 509 | 503 | static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) |
| 510 | 504 | { |
| 511 | − struct rtsx_cr_option *option = &pcr->option; | |
| 512 | 505 | u32 val; |
| 513 | 506 | |
| 514 | 507 | rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1, |
| @@ -554,17 +547,6 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) · 39 unmodified lines | ||
| 554 | 547 | else |
| 555 | 548 | rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00); |
| 556 | 549 | |
| 557 | − /* | |
| 558 | − * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced | |
| 559 | − * to drive low, and we forcibly request clock. | |
| 560 | − */ | |
| 561 | − if (option->force_clkreq_0) | |
| 562 | − rtsx_pci_write_register(pcr, PETXCFG, | |
| 563 | − FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); | |
| 564 | − else | |
| 565 | − rtsx_pci_write_register(pcr, PETXCFG, | |
| 566 | − FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); | |
| 567 | − | |
| 568 | 550 | rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); |
| 569 | 551 | |
| 570 | 552 | if (pcr->rtd3_en) { |
| @@ -1326,8 +1326,11 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) · 1325 unmodified lines | ||
| 1326 | 1326 | return err; |
| 1327 | 1327 | } |
| 1328 | 1328 | |
| 1329 | − if (pcr->aspm_mode == ASPM_MODE_REG) | |
| 1329 | + if (pcr->aspm_mode == ASPM_MODE_REG) { | |
| 1330 | 1330 | rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0x30, 0x30); |
| 1331 | + rtsx_pci_write_register(pcr, PETXCFG, | |
| 1332 | + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); | |
| 1333 | + } | |
| 1331 | 1334 | |
| 1332 | 1335 | /* No CD interrupt if probing driver with card inserted. |
| 1333 | 1336 | * So we need to initialize pcr->card_exist here. |
| @@ -13,6 +13,8 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | #include <linux/mfd/tps6594.h> |
| 15 | 15 | |
| 16 | +#define TPS6594_DEV_REV_1 0x08 | |
| 17 | + | |
| 16 | 18 | static irqreturn_t tps6594_esm_isr(int irq, void *dev_id) |
| 17 | 19 | { |
| 18 | 20 | struct platform_device *pdev = dev_id; |
| @@ -32,11 +34,26 @@ static int tps6594_esm_probe(struct platform_device *pdev) · 13 unmodified lines | ||
| 32 | 34 | { |
| 33 | 35 | struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); |
| 34 | 36 | struct device *dev = &pdev->dev; |
| 37 | + unsigned int rev; | |
| 35 | 38 | int irq; |
| 36 | 39 | int ret; |
| 37 | 40 | int i; |
| 38 | 41 | |
| 39 | − for (i = 0 ; i < pdev->num_resources ; i++) { | |
| 42 | + /* | |
| 43 | + * Due to a bug in revision 1 of the PMIC, the GPIO3 used for the | |
| 44 | + * SoC ESM function is used to power the load switch instead. | |
| 45 | + * As a consequence, ESM can not be used on those PMIC. | |
| 46 | + * Check the version and return an error in case of revision 1. | |
| 47 | + */ | |
| 48 | + ret = regmap_read(tps->regmap, TPS6594_REG_DEV_REV, &rev); | |
| 49 | + if (ret) | |
| 50 | + return dev_err_probe(dev, ret, | |
| 51 | + "Failed to read PMIC revision\n"); | |
| 52 | + if (rev == TPS6594_DEV_REV_1) | |
| 53 | + return dev_err_probe(dev, -ENODEV, | |
| 54 | + "ESM not supported for revision 1 PMIC\n"); | |
| 55 | + | |
| 56 | + for (i = 0; i < pdev->num_resources; i++) { | |
| 40 | 57 | irq = platform_get_irq_byname(pdev, pdev->resource[i].name); |
| 41 | 58 | if (irq < 0) |
| 42 | 59 | return dev_err_probe(dev, irq, "Failed to get %s irq\n", |
| @@ -338,13 +338,7 @@ static void moxart_transfer_pio(struct moxart_host *host) · 337 unmodified lines | ||
| 338 | 338 | return; |
| 339 | 339 | } |
| 340 | 340 | for (len = 0; len < remain && len < host->fifo_width;) { |
| 341 | − /* SCR data must be read in big endian. */ | |
| 342 | − if (data->mrq->cmd->opcode == SD_APP_SEND_SCR) | |
| 343 | − *sgp = ioread32be(host->base + | |
| 344 | − REG_DATA_WINDOW); | |
| 345 | − else | |
| 346 | − *sgp = ioread32(host->base + | |
| 347 | − REG_DATA_WINDOW); | |
| 341 | + *sgp = ioread32(host->base + REG_DATA_WINDOW); | |
| 348 | 342 | sgp++; |
| 349 | 343 | len += 4; |
| 350 | 344 | } |
| @@ -29,9 +29,16 @@ struct f_sdhost_priv { · 28 unmodified lines | ||
| 29 | 29 | bool enable_cmd_dat_delay; |
| 30 | 30 | }; |
| 31 | 31 | |
| 32 | +static void *sdhci_f_sdhost_priv(struct sdhci_host *host) | |
| 33 | +{ | |
| 34 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
| 35 | + | |
| 36 | + return sdhci_pltfm_priv(pltfm_host); | |
| 37 | +} | |
| 38 | + | |
| 32 | 39 | static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host) |
| 33 | 40 | { |
| 34 | − struct f_sdhost_priv *priv = sdhci_priv(host); | |
| 41 | + struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); | |
| 35 | 42 | u32 ctrl = 0; |
| 36 | 43 | |
| 37 | 44 | usleep_range(2500, 3000); |
| @@ -64,7 +71,7 @@ static unsigned int sdhci_f_sdh30_get_min_clock(struct sdhci_host *host) · 26 unmodified lines | ||
| 64 | 71 | |
| 65 | 72 | static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask) |
| 66 | 73 | { |
| 67 | − struct f_sdhost_priv *priv = sdhci_priv(host); | |
| 74 | + struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); | |
| 68 | 75 | u32 ctl; |
| 69 | 76 | |
| 70 | 77 | if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0) |
| @@ -95,30 +102,32 @@ static const struct sdhci_ops sdhci_f_sdh30_ops = { · 24 unmodified lines | ||
| 95 | 102 | .set_uhs_signaling = sdhci_set_uhs_signaling, |
| 96 | 103 | }; |
| 97 | 104 | |
| 105 | +static const struct sdhci_pltfm_data sdhci_f_sdh30_pltfm_data = { | |
| 106 | + .ops = &sdhci_f_sdh30_ops, | |
| 107 | + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | |
| 108 | + | SDHCI_QUIRK_INVERTED_WRITE_PROTECT, | |
| 109 | + .quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE | |
| 110 | + | SDHCI_QUIRK2_TUNING_WORK_AROUND, | |
| 111 | +}; | |
| 112 | + | |
| 98 | 113 | static int sdhci_f_sdh30_probe(struct platform_device *pdev) |
| 99 | 114 | { |
| 100 | 115 | struct sdhci_host *host; |
| 101 | 116 | struct device *dev = &pdev->dev; |
| 102 | − int irq, ctrl = 0, ret = 0; | |
| 117 | + int ctrl = 0, ret = 0; | |
| 103 | 118 | struct f_sdhost_priv *priv; |
| 119 | + struct sdhci_pltfm_host *pltfm_host; | |
| 104 | 120 | u32 reg = 0; |
| 105 | 121 | |
| 106 | − irq = platform_get_irq(pdev, 0); | |
| 107 | − if (irq < 0) | |
| 108 | − return irq; | |
| 109 | − | |
| 110 | − host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv)); | |
| 122 | + host = sdhci_pltfm_init(pdev, &sdhci_f_sdh30_pltfm_data, | |
| 123 | + sizeof(struct f_sdhost_priv)); | |
| 111 | 124 | if (IS_ERR(host)) |
| 112 | 125 | return PTR_ERR(host); |
| 113 | 126 | |
| 114 | − priv = sdhci_priv(host); | |
| 127 | + pltfm_host = sdhci_priv(host); | |
| 128 | + priv = sdhci_pltfm_priv(pltfm_host); | |
| 115 | 129 | priv->dev = dev; |
| 116 | 130 | |
| 117 | − host->quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | | |
| 118 | − SDHCI_QUIRK_INVERTED_WRITE_PROTECT; | |
| 119 | − host->quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE | | |
| 120 | − SDHCI_QUIRK2_TUNING_WORK_AROUND; | |
| 121 | − | |
| 122 | 131 | priv->enable_cmd_dat_delay = device_property_read_bool(dev, |
| 123 | 132 | "fujitsu,cmd-dat-delay-select"); |
| 124 | 133 | |
| @@ -126,18 +135,6 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 126 | 135 | if (ret) |
| 127 | 136 | goto err; |
| 128 | 137 | |
| 129 | − platform_set_drvdata(pdev, host); | |
| 130 | − | |
| 131 | − host->hw_name = "f_sdh30"; | |
| 132 | − host->ops = &sdhci_f_sdh30_ops; | |
| 133 | − host->irq = irq; | |
| 134 | − | |
| 135 | − host->ioaddr = devm_platform_ioremap_resource(pdev, 0); | |
| 136 | − if (IS_ERR(host->ioaddr)) { | |
| 137 | − ret = PTR_ERR(host->ioaddr); | |
| 138 | − goto err; | |
| 139 | − } | |
| 140 | − | |
| 141 | 138 | if (dev_of_node(dev)) { |
| 142 | 139 | sdhci_get_of_property(pdev); |
| 143 | 140 | |
| @@ -204,24 +201,21 @@ err_rst: · 60 unmodified lines | ||
| 204 | 201 | err_clk: |
| 205 | 202 | clk_disable_unprepare(priv->clk_iface); |
| 206 | 203 | err: |
| 207 | − sdhci_free_host(host); | |
| 204 | + sdhci_pltfm_free(pdev); | |
| 205 | + | |
| 208 | 206 | return ret; |
| 209 | 207 | } |
| 210 | 208 | |
| 211 | 209 | static int sdhci_f_sdh30_remove(struct platform_device *pdev) |
| 212 | 210 | { |
| 213 | 211 | struct sdhci_host *host = platform_get_drvdata(pdev); |
| 214 | − struct f_sdhost_priv *priv = sdhci_priv(host); | |
| 215 | − | |
| 216 | − sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) == | |
| 217 | − 0xffffffff); | |
| 212 | + struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); | |
| 218 | 213 | |
| 219 | 214 | reset_control_assert(priv->rst); |
| 220 | 215 | clk_disable_unprepare(priv->clk); |
| 221 | 216 | clk_disable_unprepare(priv->clk_iface); |
| 222 | 217 | |
| 223 | − sdhci_free_host(host); | |
| 224 | − platform_set_drvdata(pdev, NULL); | |
| 218 | + sdhci_pltfm_unregister(pdev); | |
| 225 | 219 | |
| 226 | 220 | return 0; |
| 227 | 221 | } |
| @@ -135,7 +135,7 @@ static int fun_exec_op(struct nand_chip *chip, const struct nand_operation *op, · 134 unmodified lines | ||
| 135 | 135 | unsigned int i; |
| 136 | 136 | int ret; |
| 137 | 137 | |
| 138 | − if (op->cs > NAND_MAX_CHIPS) | |
| 138 | + if (op->cs >= NAND_MAX_CHIPS) | |
| 139 | 139 | return -EINVAL; |
| 140 | 140 | |
| 141 | 141 | if (check_only) |
| @@ -1278,7 +1278,6 @@ static int meson_nand_attach_chip(struct nand_chip *nand) · 1277 unmodified lines | ||
| 1278 | 1278 | struct meson_nfc *nfc = nand_get_controller_data(nand); |
| 1279 | 1279 | struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); |
| 1280 | 1280 | struct mtd_info *mtd = nand_to_mtd(nand); |
| 1281 | − int nsectors = mtd->writesize / 1024; | |
| 1282 | 1281 | int raw_writesize; |
| 1283 | 1282 | int ret; |
| 1284 | 1283 | |
| @@ -1304,7 +1303,7 @@ static int meson_nand_attach_chip(struct nand_chip *nand) · 19 unmodified lines | ||
| 1304 | 1303 | nand->options |= NAND_NO_SUBPAGE_WRITE; |
| 1305 | 1304 | |
| 1306 | 1305 | ret = nand_ecc_choose_conf(nand, nfc->data->ecc_caps, |
| 1307 | − mtd->oobsize - 2 * nsectors); | |
| 1306 | + mtd->oobsize - 2); | |
| 1308 | 1307 | if (ret) { |
| 1309 | 1308 | dev_err(nfc->dev, "failed to ECC init\n"); |
| 1310 | 1309 | return -EINVAL; |
| @@ -177,17 +177,17 @@ static void elm_load_syndrome(struct elm_info *info, · 176 unmodified lines | ||
| 177 | 177 | switch (info->bch_type) { |
| 178 | 178 | case BCH8_ECC: |
| 179 | 179 | /* syndrome fragment 0 = ecc[9-12B] */ |
| 180 | − val = cpu_to_be32(*(u32 *) &ecc[9]); | |
| 180 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[9]); | |
| 181 | 181 | elm_write_reg(info, offset, val); |
| 182 | 182 | |
| 183 | 183 | /* syndrome fragment 1 = ecc[5-8B] */ |
| 184 | 184 | offset += 4; |
| 185 | − val = cpu_to_be32(*(u32 *) &ecc[5]); | |
| 185 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[5]); | |
| 186 | 186 | elm_write_reg(info, offset, val); |
| 187 | 187 | |
| 188 | 188 | /* syndrome fragment 2 = ecc[1-4B] */ |
| 189 | 189 | offset += 4; |
| 190 | − val = cpu_to_be32(*(u32 *) &ecc[1]); | |
| 190 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[1]); | |
| 191 | 191 | elm_write_reg(info, offset, val); |
| 192 | 192 | |
| 193 | 193 | /* syndrome fragment 3 = ecc[0B] */ |
| @@ -197,35 +197,35 @@ static void elm_load_syndrome(struct elm_info *info, · 3 unmodified lines | ||
| 197 | 197 | break; |
| 198 | 198 | case BCH4_ECC: |
| 199 | 199 | /* syndrome fragment 0 = ecc[20-52b] bits */ |
| 200 | − val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) | | |
| 200 | + val = ((__force u32)cpu_to_be32(*(u32 *)&ecc[3]) >> 4) | | |
| 201 | 201 | ((ecc[2] & 0xf) << 28); |
| 202 | 202 | elm_write_reg(info, offset, val); |
| 203 | 203 | |
| 204 | 204 | /* syndrome fragment 1 = ecc[0-20b] bits */ |
| 205 | 205 | offset += 4; |
| 206 | − val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12; | |
| 206 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 12; | |
| 207 | 207 | elm_write_reg(info, offset, val); |
| 208 | 208 | break; |
| 209 | 209 | case BCH16_ECC: |
| 210 | − val = cpu_to_be32(*(u32 *) &ecc[22]); | |
| 210 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[22]); | |
| 211 | 211 | elm_write_reg(info, offset, val); |
| 212 | 212 | offset += 4; |
| 213 | − val = cpu_to_be32(*(u32 *) &ecc[18]); | |
| 213 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[18]); | |
| 214 | 214 | elm_write_reg(info, offset, val); |
| 215 | 215 | offset += 4; |
| 216 | − val = cpu_to_be32(*(u32 *) &ecc[14]); | |
| 216 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[14]); | |
| 217 | 217 | elm_write_reg(info, offset, val); |
| 218 | 218 | offset += 4; |
| 219 | − val = cpu_to_be32(*(u32 *) &ecc[10]); | |
| 219 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[10]); | |
| 220 | 220 | elm_write_reg(info, offset, val); |
| 221 | 221 | offset += 4; |
| 222 | − val = cpu_to_be32(*(u32 *) &ecc[6]); | |
| 222 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[6]); | |
| 223 | 223 | elm_write_reg(info, offset, val); |
| 224 | 224 | offset += 4; |
| 225 | − val = cpu_to_be32(*(u32 *) &ecc[2]); | |
| 225 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[2]); | |
| 226 | 226 | elm_write_reg(info, offset, val); |
| 227 | 227 | offset += 4; |
| 228 | − val = cpu_to_be32(*(u32 *) &ecc[0]) >> 16; | |
| 228 | + val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 16; | |
| 229 | 229 | elm_write_reg(info, offset, val); |
| 230 | 230 | break; |
| 231 | 231 | default: |
| @@ -562,9 +562,10 @@ static int rk_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf, · 561 unmodified lines | ||
| 562 | 562 | * BBM OOB1 OOB2 OOB3 |......| PA0 PA1 PA2 PA3 |
| 563 | 563 | * |
| 564 | 564 | * The rk_nfc_ooblayout_free() function already has reserved |
| 565 | − * these 4 bytes with: | |
| 565 | + * these 4 bytes together with 2 bytes for BBM | |
| 566 | + * by reducing it's length: | |
| 566 | 567 | * |
| 567 | − * oob_region->offset = NFC_SYS_DATA_SIZE + 2; | |
| 568 | + * oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2; | |
| 568 | 569 | */ |
| 569 | 570 | if (!i) |
| 570 | 571 | memcpy(rk_nfc_oob_ptr(chip, i), |
| @@ -597,7 +598,7 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf, · 26 unmodified lines | ||
| 597 | 598 | int pages_per_blk = mtd->erasesize / mtd->writesize; |
| 598 | 599 | int ret = 0, i, boot_rom_mode = 0; |
| 599 | 600 | dma_addr_t dma_data, dma_oob; |
| 600 | − u32 reg; | |
| 601 | + u32 tmp; | |
| 601 | 602 | u8 *oob; |
| 602 | 603 | |
| 603 | 604 | nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
| @@ -624,6 +625,13 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf, · 20 unmodified lines | ||
| 624 | 625 | * |
| 625 | 626 | * 0xFF 0xFF 0xFF 0xFF | BBM OOB1 OOB2 OOB3 | ... |
| 626 | 627 | * |
| 628 | + * The code here just swaps the first 4 bytes with the last | |
| 629 | + * 4 bytes without losing any data. | |
| 630 | + * | |
| 631 | + * The chip->oob_poi data layout: | |
| 632 | + * | |
| 633 | + * BBM OOB1 OOB2 OOB3 |......| PA0 PA1 PA2 PA3 | |
| 634 | + * | |
| 627 | 635 | * Configure the ECC algorithm supported by the boot ROM. |
| 628 | 636 | */ |
| 629 | 637 | if ((page < (pages_per_blk * rknand->boot_blks)) && |
| @@ -634,21 +642,17 @@ static int rk_nfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf, · 4 unmodified lines | ||
| 634 | 642 | } |
| 635 | 643 | |
| 636 | 644 | for (i = 0; i < ecc->steps; i++) { |
| 637 | − if (!i) { | |
| 638 | − reg = 0xFFFFFFFF; | |
| 639 | − } else { | |
| 645 | + if (!i) | |
| 646 | + oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE; | |
| 647 | + else | |
| 640 | 648 | oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; |
| 641 | − reg = oob[0] | oob[1] << 8 | oob[2] << 16 | | |
| 642 | − oob[3] << 24; | |
| 643 | − } | |
| 644 | 649 | |
| 645 | − if (!i && boot_rom_mode) | |
| 646 | − reg = (page & (pages_per_blk - 1)) * 4; | |
| 650 | + tmp = oob[0] | oob[1] << 8 | oob[2] << 16 | oob[3] << 24; | |
| 647 | 651 | |
| 648 | 652 | if (nfc->cfg->type == NFC_V9) |
| 649 | − nfc->oob_buf[i] = reg; | |
| 653 | + nfc->oob_buf[i] = tmp; | |
| 650 | 654 | else |
| 651 | − nfc->oob_buf[i * (oob_step / 4)] = reg; | |
| 655 | + nfc->oob_buf[i * (oob_step / 4)] = tmp; | |
| 652 | 656 | } |
| 653 | 657 | |
| 654 | 658 | dma_data = dma_map_single(nfc->dev, (void *)nfc->page_buf, |
| @@ -811,12 +815,17 @@ static int rk_nfc_read_page_hwecc(struct nand_chip *chip, u8 *buf, int oob_on, · 156 unmodified lines | ||
| 811 | 815 | goto timeout_err; |
| 812 | 816 | } |
| 813 | 817 | |
| 814 | − for (i = 1; i < ecc->steps; i++) { | |
| 815 | − oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; | |
| 818 | + for (i = 0; i < ecc->steps; i++) { | |
| 819 | + if (!i) | |
| 820 | + oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE; | |
| 821 | + else | |
| 822 | + oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; | |
| 823 | + | |
| 816 | 824 | if (nfc->cfg->type == NFC_V9) |
| 817 | 825 | tmp = nfc->oob_buf[i]; |
| 818 | 826 | else |
| 819 | 827 | tmp = nfc->oob_buf[i * (oob_step / 4)]; |
| 828 | + | |
| 820 | 829 | *oob++ = (u8)tmp; |
| 821 | 830 | *oob++ = (u8)(tmp >> 8); |
| 822 | 831 | *oob++ = (u8)(tmp >> 16); |
| @@ -933,12 +942,8 @@ static int rk_nfc_ooblayout_free(struct mtd_info *mtd, int section, · 110 unmodified lines | ||
| 933 | 942 | if (section) |
| 934 | 943 | return -ERANGE; |
| 935 | 944 | |
| 936 | − /* | |
| 937 | − * The beginning of the OOB area stores the reserved data for the NFC, | |
| 938 | − * the size of the reserved data is NFC_SYS_DATA_SIZE bytes. | |
| 939 | − */ | |
| 940 | 945 | oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2; |
| 941 | − oob_region->offset = NFC_SYS_DATA_SIZE + 2; | |
| 946 | + oob_region->offset = 2; | |
| 942 | 947 | |
| 943 | 948 | return 0; |
| 944 | 949 | } |
| @@ -73,7 +73,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand, · 72 unmodified lines | ||
| 73 | 73 | { |
| 74 | 74 | struct nand_device *nand = spinand_to_nand(spinand); |
| 75 | 75 | u8 mbf = 0; |
| 76 | − struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); | |
| 76 | + struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf); | |
| 77 | 77 | |
| 78 | 78 | switch (status & STATUS_ECC_MASK) { |
| 79 | 79 | case STATUS_ECC_NO_BITFLIPS: |
| @@ -92,7 +92,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand, · 12 unmodified lines | ||
| 92 | 92 | if (spi_mem_exec_op(spinand->spimem, &op)) |
| 93 | 93 | return nanddev_get_ecc_conf(nand)->strength; |
| 94 | 94 | |
| 95 | − mbf >>= 4; | |
| 95 | + mbf = *(spinand->scratchbuf) >> 4; | |
| 96 | 96 | |
| 97 | 97 | if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) |
| 98 | 98 | return nanddev_get_ecc_conf(nand)->strength; |
| @@ -108,7 +108,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand, · 107 unmodified lines | ||
| 108 | 108 | { |
| 109 | 109 | struct nand_device *nand = spinand_to_nand(spinand); |
| 110 | 110 | u8 mbf = 0; |
| 111 | − struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf); | |
| 111 | + struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf); | |
| 112 | 112 | |
| 113 | 113 | switch (status & STATUS_ECC_MASK) { |
| 114 | 114 | case STATUS_ECC_NO_BITFLIPS: |
| @@ -126,7 +126,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand, · 11 unmodified lines | ||
| 126 | 126 | if (spi_mem_exec_op(spinand->spimem, &op)) |
| 127 | 127 | return nanddev_get_ecc_conf(nand)->strength; |
| 128 | 128 | |
| 129 | − mbf >>= 4; | |
| 129 | + mbf = *(spinand->scratchbuf) >> 4; | |
| 130 | 130 | |
| 131 | 131 | if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) |
| 132 | 132 | return nanddev_get_ecc_conf(nand)->strength; |
| @@ -361,7 +361,7 @@ static int cypress_nor_determine_addr_mode_by_sr1(struct spi_nor *nor, · 360 unmodified lines | ||
| 361 | 361 | */ |
| 362 | 362 | static int cypress_nor_set_addr_mode_nbytes(struct spi_nor *nor) |
| 363 | 363 | { |
| 364 | − struct spi_mem_op op = {}; | |
| 364 | + struct spi_mem_op op; | |
| 365 | 365 | u8 addr_mode; |
| 366 | 366 | int ret; |
| 367 | 367 | |
| @@ -492,7 +492,7 @@ s25fs256t_post_bfpt_fixup(struct spi_nor *nor, · 124 unmodified lines | ||
| 492 | 492 | const struct sfdp_parameter_header *bfpt_header, |
| 493 | 493 | const struct sfdp_bfpt *bfpt) |
| 494 | 494 | { |
| 495 | − struct spi_mem_op op = {}; | |
| 495 | + struct spi_mem_op op; | |
| 496 | 496 | int ret; |
| 497 | 497 | |
| 498 | 498 | ret = cypress_nor_set_addr_mode_nbytes(nor); |
| @@ -5901,7 +5901,9 @@ void bond_setup(struct net_device *bond_dev) · 5900 unmodified lines | ||
| 5901 | 5901 | |
| 5902 | 5902 | bond_dev->hw_features = BOND_VLAN_FEATURES | |
| 5903 | 5903 | NETIF_F_HW_VLAN_CTAG_RX | |
| 5904 | − NETIF_F_HW_VLAN_CTAG_FILTER; | |
| 5904 | + NETIF_F_HW_VLAN_CTAG_FILTER | | |
| 5905 | + NETIF_F_HW_VLAN_STAG_RX | | |
| 5906 | + NETIF_F_HW_VLAN_STAG_FILTER; | |
| 5905 | 5907 | |
| 5906 | 5908 | bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL; |
| 5907 | 5909 | bond_dev->features |= bond_dev->hw_features; |
| @@ -1436,7 +1436,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) · 1435 unmodified lines | ||
| 1436 | 1436 | if (IS_ERR(priv->clk)) |
| 1437 | 1437 | return PTR_ERR(priv->clk); |
| 1438 | 1438 | |
| 1439 | − clk_prepare_enable(priv->clk); | |
| 1439 | + ret = clk_prepare_enable(priv->clk); | |
| 1440 | + if (ret) | |
| 1441 | + return ret; | |
| 1440 | 1442 | |
| 1441 | 1443 | priv->clk_mdiv = devm_clk_get_optional(&pdev->dev, "sw_switch_mdiv"); |
| 1442 | 1444 | if (IS_ERR(priv->clk_mdiv)) { |
| @@ -1444,7 +1446,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 1444 | 1446 | goto out_clk; |
| 1445 | 1447 | } |
| 1446 | 1448 | |
| 1447 | − clk_prepare_enable(priv->clk_mdiv); | |
| 1449 | + ret = clk_prepare_enable(priv->clk_mdiv); | |
| 1450 | + if (ret) | |
| 1451 | + goto out_clk; | |
| 1448 | 1452 | |
| 1449 | 1453 | ret = bcm_sf2_sw_rst(priv); |
| 1450 | 1454 | if (ret) { |
| @@ -635,10 +635,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 634 unmodified lines | ||
| 635 | 635 | regmap_reg_range(0x1030, 0x1030), |
| 636 | 636 | regmap_reg_range(0x1100, 0x1115), |
| 637 | 637 | regmap_reg_range(0x111a, 0x111f), |
| 638 | − regmap_reg_range(0x1122, 0x1127), | |
| 639 | − regmap_reg_range(0x112a, 0x112b), | |
| 640 | − regmap_reg_range(0x1136, 0x1139), | |
| 641 | − regmap_reg_range(0x113e, 0x113f), | |
| 638 | + regmap_reg_range(0x1120, 0x112b), | |
| 639 | + regmap_reg_range(0x1134, 0x113b), | |
| 640 | + regmap_reg_range(0x113c, 0x113f), | |
| 642 | 641 | regmap_reg_range(0x1400, 0x1401), |
| 643 | 642 | regmap_reg_range(0x1403, 0x1403), |
| 644 | 643 | regmap_reg_range(0x1410, 0x1417), |
| @@ -669,10 +668,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 24 unmodified lines | ||
| 669 | 668 | regmap_reg_range(0x2030, 0x2030), |
| 670 | 669 | regmap_reg_range(0x2100, 0x2115), |
| 671 | 670 | regmap_reg_range(0x211a, 0x211f), |
| 672 | − regmap_reg_range(0x2122, 0x2127), | |
| 673 | − regmap_reg_range(0x212a, 0x212b), | |
| 674 | − regmap_reg_range(0x2136, 0x2139), | |
| 675 | − regmap_reg_range(0x213e, 0x213f), | |
| 671 | + regmap_reg_range(0x2120, 0x212b), | |
| 672 | + regmap_reg_range(0x2134, 0x213b), | |
| 673 | + regmap_reg_range(0x213c, 0x213f), | |
| 676 | 674 | regmap_reg_range(0x2400, 0x2401), |
| 677 | 675 | regmap_reg_range(0x2403, 0x2403), |
| 678 | 676 | regmap_reg_range(0x2410, 0x2417), |
| @@ -703,10 +701,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 24 unmodified lines | ||
| 703 | 701 | regmap_reg_range(0x3030, 0x3030), |
| 704 | 702 | regmap_reg_range(0x3100, 0x3115), |
| 705 | 703 | regmap_reg_range(0x311a, 0x311f), |
| 706 | − regmap_reg_range(0x3122, 0x3127), | |
| 707 | − regmap_reg_range(0x312a, 0x312b), | |
| 708 | − regmap_reg_range(0x3136, 0x3139), | |
| 709 | − regmap_reg_range(0x313e, 0x313f), | |
| 704 | + regmap_reg_range(0x3120, 0x312b), | |
| 705 | + regmap_reg_range(0x3134, 0x313b), | |
| 706 | + regmap_reg_range(0x313c, 0x313f), | |
| 710 | 707 | regmap_reg_range(0x3400, 0x3401), |
| 711 | 708 | regmap_reg_range(0x3403, 0x3403), |
| 712 | 709 | regmap_reg_range(0x3410, 0x3417), |
| @@ -737,10 +734,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 24 unmodified lines | ||
| 737 | 734 | regmap_reg_range(0x4030, 0x4030), |
| 738 | 735 | regmap_reg_range(0x4100, 0x4115), |
| 739 | 736 | regmap_reg_range(0x411a, 0x411f), |
| 740 | − regmap_reg_range(0x4122, 0x4127), | |
| 741 | − regmap_reg_range(0x412a, 0x412b), | |
| 742 | − regmap_reg_range(0x4136, 0x4139), | |
| 743 | − regmap_reg_range(0x413e, 0x413f), | |
| 737 | + regmap_reg_range(0x4120, 0x412b), | |
| 738 | + regmap_reg_range(0x4134, 0x413b), | |
| 739 | + regmap_reg_range(0x413c, 0x413f), | |
| 744 | 740 | regmap_reg_range(0x4400, 0x4401), |
| 745 | 741 | regmap_reg_range(0x4403, 0x4403), |
| 746 | 742 | regmap_reg_range(0x4410, 0x4417), |
| @@ -771,10 +767,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 24 unmodified lines | ||
| 771 | 767 | regmap_reg_range(0x5030, 0x5030), |
| 772 | 768 | regmap_reg_range(0x5100, 0x5115), |
| 773 | 769 | regmap_reg_range(0x511a, 0x511f), |
| 774 | − regmap_reg_range(0x5122, 0x5127), | |
| 775 | − regmap_reg_range(0x512a, 0x512b), | |
| 776 | − regmap_reg_range(0x5136, 0x5139), | |
| 777 | − regmap_reg_range(0x513e, 0x513f), | |
| 770 | + regmap_reg_range(0x5120, 0x512b), | |
| 771 | + regmap_reg_range(0x5134, 0x513b), | |
| 772 | + regmap_reg_range(0x513c, 0x513f), | |
| 778 | 773 | regmap_reg_range(0x5400, 0x5401), |
| 779 | 774 | regmap_reg_range(0x5403, 0x5403), |
| 780 | 775 | regmap_reg_range(0x5410, 0x5417), |
| @@ -1625,8 +1625,10 @@ static void felix_teardown(struct dsa_switch *ds) · 1624 unmodified lines | ||
| 1625 | 1625 | struct felix *felix = ocelot_to_felix(ocelot); |
| 1626 | 1626 | struct dsa_port *dp; |
| 1627 | 1627 | |
| 1628 | + rtnl_lock(); | |
| 1628 | 1629 | if (felix->tag_proto_ops) |
| 1629 | 1630 | felix->tag_proto_ops->teardown(ds); |
| 1631 | + rtnl_unlock(); | |
| 1630 | 1632 | |
| 1631 | 1633 | dsa_switch_for_each_available_port(dp, ds) |
| 1632 | 1634 | ocelot_deinit_port(ocelot, dp->index); |
| @@ -633,12 +633,13 @@ tx_kick_pending: · 632 unmodified lines | ||
| 633 | 633 | return NETDEV_TX_OK; |
| 634 | 634 | } |
| 635 | 635 | |
| 636 | −static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) | |
| 636 | +static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) | |
| 637 | 637 | { |
| 638 | 638 | struct bnxt_tx_ring_info *txr = bnapi->tx_ring; |
| 639 | 639 | struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index); |
| 640 | 640 | u16 cons = txr->tx_cons; |
| 641 | 641 | struct pci_dev *pdev = bp->pdev; |
| 642 | + int nr_pkts = bnapi->tx_pkts; | |
| 642 | 643 | int i; |
| 643 | 644 | unsigned int tx_bytes = 0; |
| 644 | 645 | |
| @@ -688,6 +689,7 @@ next_tx_int: · 43 unmodified lines | ||
| 688 | 689 | dev_kfree_skb_any(skb); |
| 689 | 690 | } |
| 690 | 691 | |
| 692 | + bnapi->tx_pkts = 0; | |
| 691 | 693 | WRITE_ONCE(txr->tx_cons, cons); |
| 692 | 694 | |
| 693 | 695 | __netif_txq_completed_wake(txq, nr_pkts, tx_bytes, |
| @@ -697,17 +699,24 @@ next_tx_int: · 3 unmodified lines | ||
| 697 | 699 | |
| 698 | 700 | static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping, |
| 699 | 701 | struct bnxt_rx_ring_info *rxr, |
| 702 | + unsigned int *offset, | |
| 700 | 703 | gfp_t gfp) |
| 701 | 704 | { |
| 702 | 705 | struct device *dev = &bp->pdev->dev; |
| 703 | 706 | struct page *page; |
| 704 | 707 | |
| 705 | − page = page_pool_dev_alloc_pages(rxr->page_pool); | |
| 708 | + if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) { | |
| 709 | + page = page_pool_dev_alloc_frag(rxr->page_pool, offset, | |
| 710 | + BNXT_RX_PAGE_SIZE); | |
| 711 | + } else { | |
| 712 | + page = page_pool_dev_alloc_pages(rxr->page_pool); | |
| 713 | + *offset = 0; | |
| 714 | + } | |
| 706 | 715 | if (!page) |
| 707 | 716 | return NULL; |
| 708 | 717 | |
| 709 | − *mapping = dma_map_page_attrs(dev, page, 0, PAGE_SIZE, bp->rx_dir, | |
| 710 | − DMA_ATTR_WEAK_ORDERING); | |
| 718 | + *mapping = dma_map_page_attrs(dev, page, *offset, BNXT_RX_PAGE_SIZE, | |
| 719 | + bp->rx_dir, DMA_ATTR_WEAK_ORDERING); | |
| 711 | 720 | if (dma_mapping_error(dev, *mapping)) { |
| 712 | 721 | page_pool_recycle_direct(rxr->page_pool, page); |
| 713 | 722 | return NULL; |
| @@ -747,15 +756,16 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, · 33 unmodified lines | ||
| 747 | 756 | dma_addr_t mapping; |
| 748 | 757 | |
| 749 | 758 | if (BNXT_RX_PAGE_MODE(bp)) { |
| 759 | + unsigned int offset; | |
| 750 | 760 | struct page *page = |
| 751 | − __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp); | |
| 761 | + __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp); | |
| 752 | 762 | |
| 753 | 763 | if (!page) |
| 754 | 764 | return -ENOMEM; |
| 755 | 765 | |
| 756 | 766 | mapping += bp->rx_dma_offset; |
| 757 | 767 | rx_buf->data = page; |
| 758 | − rx_buf->data_ptr = page_address(page) + bp->rx_offset; | |
| 768 | + rx_buf->data_ptr = page_address(page) + offset + bp->rx_offset; | |
| 759 | 769 | } else { |
| 760 | 770 | u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, gfp); |
| 761 | 771 | |
| @@ -815,7 +825,7 @@ static inline int bnxt_alloc_rx_page(struct bnxt *bp, · 53 unmodified lines | ||
| 815 | 825 | unsigned int offset = 0; |
| 816 | 826 | |
| 817 | 827 | if (BNXT_RX_PAGE_MODE(bp)) { |
| 818 | − page = __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp); | |
| 828 | + page = __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp); | |
| 819 | 829 | |
| 820 | 830 | if (!page) |
| 821 | 831 | return -ENOMEM; |
| @@ -962,15 +972,15 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp, · 140 unmodified lines | ||
| 962 | 972 | return NULL; |
| 963 | 973 | } |
| 964 | 974 | dma_addr -= bp->rx_dma_offset; |
| 965 | − dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir, | |
| 966 | − DMA_ATTR_WEAK_ORDERING); | |
| 967 | − skb = build_skb(page_address(page), PAGE_SIZE); | |
| 975 | + dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE, | |
| 976 | + bp->rx_dir, DMA_ATTR_WEAK_ORDERING); | |
| 977 | + skb = build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE); | |
| 968 | 978 | if (!skb) { |
| 969 | 979 | page_pool_recycle_direct(rxr->page_pool, page); |
| 970 | 980 | return NULL; |
| 971 | 981 | } |
| 972 | 982 | skb_mark_for_recycle(skb); |
| 973 | − skb_reserve(skb, bp->rx_dma_offset); | |
| 983 | + skb_reserve(skb, bp->rx_offset); | |
| 974 | 984 | __skb_put(skb, len); |
| 975 | 985 | |
| 976 | 986 | return skb; |
| @@ -996,8 +1006,8 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp, · 19 unmodified lines | ||
| 996 | 1006 | return NULL; |
| 997 | 1007 | } |
| 998 | 1008 | dma_addr -= bp->rx_dma_offset; |
| 999 | − dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir, | |
| 1000 | − DMA_ATTR_WEAK_ORDERING); | |
| 1009 | + dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE, | |
| 1010 | + bp->rx_dir, DMA_ATTR_WEAK_ORDERING); | |
| 1001 | 1011 | |
| 1002 | 1012 | if (unlikely(!payload)) |
| 1003 | 1013 | payload = eth_get_headlen(bp->dev, data_ptr, len); |
| @@ -1010,7 +1020,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp, · 6 unmodified lines | ||
| 1010 | 1020 | |
| 1011 | 1021 | skb_mark_for_recycle(skb); |
| 1012 | 1022 | off = (void *)data_ptr - page_address(page); |
| 1013 | − skb_add_rx_frag(skb, 0, page, off, len, PAGE_SIZE); | |
| 1023 | + skb_add_rx_frag(skb, 0, page, off, len, BNXT_RX_PAGE_SIZE); | |
| 1014 | 1024 | memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN, |
| 1015 | 1025 | payload + NET_IP_ALIGN); |
| 1016 | 1026 | |
| @@ -1141,7 +1151,7 @@ static struct sk_buff *bnxt_rx_agg_pages_skb(struct bnxt *bp, · 124 unmodified lines | ||
| 1141 | 1151 | |
| 1142 | 1152 | skb->data_len += total_frag_len; |
| 1143 | 1153 | skb->len += total_frag_len; |
| 1144 | − skb->truesize += PAGE_SIZE * agg_bufs; | |
| 1154 | + skb->truesize += BNXT_RX_PAGE_SIZE * agg_bufs; | |
| 1145 | 1155 | return skb; |
| 1146 | 1156 | } |
| 1147 | 1157 | |
| @@ -2569,12 +2579,11 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, · 1421 unmodified lines | ||
| 2569 | 2579 | return rx_pkts; |
| 2570 | 2580 | } |
| 2571 | 2581 | |
| 2572 | −static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi) | |
| 2582 | +static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi, | |
| 2583 | + int budget) | |
| 2573 | 2584 | { |
| 2574 | − if (bnapi->tx_pkts) { | |
| 2575 | − bnapi->tx_int(bp, bnapi, bnapi->tx_pkts); | |
| 2576 | − bnapi->tx_pkts = 0; | |
| 2577 | − } | |
| 2585 | + if (bnapi->tx_pkts) | |
| 2586 | + bnapi->tx_int(bp, bnapi, budget); | |
| 2578 | 2587 | |
| 2579 | 2588 | if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) { |
| 2580 | 2589 | struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; |
| @@ -2603,7 +2612,7 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, · 22 unmodified lines | ||
| 2603 | 2612 | */ |
| 2604 | 2613 | bnxt_db_cq(bp, &cpr->cp_db, cpr->cp_raw_cons); |
| 2605 | 2614 | |
| 2606 | − __bnxt_poll_work_done(bp, bnapi); | |
| 2615 | + __bnxt_poll_work_done(bp, bnapi, budget); | |
| 2607 | 2616 | return rx_pkts; |
| 2608 | 2617 | } |
| 2609 | 2618 | |
| @@ -2734,7 +2743,7 @@ static int __bnxt_poll_cqs(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) · 124 unmodified lines | ||
| 2734 | 2743 | } |
| 2735 | 2744 | |
| 2736 | 2745 | static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi, |
| 2737 | − u64 dbr_type) | |
| 2746 | + u64 dbr_type, int budget) | |
| 2738 | 2747 | { |
| 2739 | 2748 | struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; |
| 2740 | 2749 | int i; |
| @@ -2750,7 +2759,7 @@ static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi, · 9 unmodified lines | ||
| 2750 | 2759 | cpr2->had_work_done = 0; |
| 2751 | 2760 | } |
| 2752 | 2761 | } |
| 2753 | − __bnxt_poll_work_done(bp, bnapi); | |
| 2762 | + __bnxt_poll_work_done(bp, bnapi, budget); | |
| 2754 | 2763 | } |
| 2755 | 2764 | |
| 2756 | 2765 | static int bnxt_poll_p5(struct napi_struct *napi, int budget) |
| @@ -2780,7 +2789,8 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget) · 23 unmodified lines | ||
| 2780 | 2789 | if (cpr->has_more_work) |
| 2781 | 2790 | break; |
| 2782 | 2791 | |
| 2783 | − __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL); | |
| 2792 | + __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL, | |
| 2793 | + budget); | |
| 2784 | 2794 | cpr->cp_raw_cons = raw_cons; |
| 2785 | 2795 | if (napi_complete_done(napi, work_done)) |
| 2786 | 2796 | BNXT_DB_NQ_ARM_P5(&cpr->cp_db, |
| @@ -2810,7 +2820,7 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget) · 23 unmodified lines | ||
| 2810 | 2820 | } |
| 2811 | 2821 | raw_cons = NEXT_RAW_CMP(raw_cons); |
| 2812 | 2822 | } |
| 2813 | − __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ); | |
| 2823 | + __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ, budget); | |
| 2814 | 2824 | if (raw_cons != cpr->cp_raw_cons) { |
| 2815 | 2825 | cpr->cp_raw_cons = raw_cons; |
| 2816 | 2826 | BNXT_DB_NQ_P5(&cpr->cp_db, raw_cons); |
| @@ -2943,8 +2953,8 @@ skip_rx_tpa_free: · 126 unmodified lines | ||
| 2943 | 2953 | rx_buf->data = NULL; |
| 2944 | 2954 | if (BNXT_RX_PAGE_MODE(bp)) { |
| 2945 | 2955 | mapping -= bp->rx_dma_offset; |
| 2946 | − dma_unmap_page_attrs(&pdev->dev, mapping, PAGE_SIZE, | |
| 2947 | − bp->rx_dir, | |
| 2956 | + dma_unmap_page_attrs(&pdev->dev, mapping, | |
| 2957 | + BNXT_RX_PAGE_SIZE, bp->rx_dir, | |
| 2948 | 2958 | DMA_ATTR_WEAK_ORDERING); |
| 2949 | 2959 | page_pool_recycle_direct(rxr->page_pool, data); |
| 2950 | 2960 | } else { |
| @@ -3213,6 +3223,8 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp, · 262 unmodified lines | ||
| 3213 | 3223 | pp.napi = &rxr->bnapi->napi; |
| 3214 | 3224 | pp.dev = &bp->pdev->dev; |
| 3215 | 3225 | pp.dma_dir = DMA_BIDIRECTIONAL; |
| 3226 | + if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) | |
| 3227 | + pp.flags |= PP_FLAG_PAGE_FRAG; | |
| 3216 | 3228 | |
| 3217 | 3229 | rxr->page_pool = page_pool_create(&pp); |
| 3218 | 3230 | if (IS_ERR(rxr->page_pool)) { |
| @@ -3989,26 +4001,29 @@ void bnxt_set_ring_params(struct bnxt *bp) · 770 unmodified lines | ||
| 3989 | 4001 | */ |
| 3990 | 4002 | int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode) |
| 3991 | 4003 | { |
| 4004 | + struct net_device *dev = bp->dev; | |
| 4005 | + | |
| 3992 | 4006 | if (page_mode) { |
| 3993 | 4007 | bp->flags &= ~BNXT_FLAG_AGG_RINGS; |
| 3994 | 4008 | bp->flags |= BNXT_FLAG_RX_PAGE_MODE; |
| 3995 | 4009 | |
| 3996 | − if (bp->dev->mtu > BNXT_MAX_PAGE_MODE_MTU) { | |
| 4010 | + if (bp->xdp_prog->aux->xdp_has_frags) | |
| 4011 | + dev->max_mtu = min_t(u16, bp->max_mtu, BNXT_MAX_MTU); | |
| 4012 | + else | |
| 4013 | + dev->max_mtu = | |
| 4014 | + min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU); | |
| 4015 | + if (dev->mtu > BNXT_MAX_PAGE_MODE_MTU) { | |
| 3997 | 4016 | bp->flags |= BNXT_FLAG_JUMBO; |
| 3998 | 4017 | bp->rx_skb_func = bnxt_rx_multi_page_skb; |
| 3999 | − bp->dev->max_mtu = | |
| 4000 | − min_t(u16, bp->max_mtu, BNXT_MAX_MTU); | |
| 4001 | 4018 | } else { |
| 4002 | 4019 | bp->flags |= BNXT_FLAG_NO_AGG_RINGS; |
| 4003 | 4020 | bp->rx_skb_func = bnxt_rx_page_skb; |
| 4004 | − bp->dev->max_mtu = | |
| 4005 | − min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU); | |
| 4006 | 4021 | } |
| 4007 | 4022 | bp->rx_dir = DMA_BIDIRECTIONAL; |
| 4008 | 4023 | /* Disable LRO or GRO_HW */ |
| 4009 | − netdev_update_features(bp->dev); | |
| 4024 | + netdev_update_features(dev); | |
| 4010 | 4025 | } else { |
| 4011 | − bp->dev->max_mtu = bp->max_mtu; | |
| 4026 | + dev->max_mtu = bp->max_mtu; | |
| 4012 | 4027 | bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE; |
| 4013 | 4028 | bp->rx_dir = DMA_FROM_DEVICE; |
| 4014 | 4029 | bp->rx_skb_func = bnxt_rx_skb; |
| @@ -9429,6 +9444,8 @@ static void bnxt_enable_napi(struct bnxt *bp) · 5414 unmodified lines | ||
| 9429 | 9444 | cpr->sw_stats.rx.rx_resets++; |
| 9430 | 9445 | bnapi->in_reset = false; |
| 9431 | 9446 | |
| 9447 | + bnapi->tx_pkts = 0; | |
| 9448 | + | |
| 9432 | 9449 | if (bnapi->rx_ring) { |
| 9433 | 9450 | INIT_WORK(&cpr->dim.work, bnxt_dim_work); |
| 9434 | 9451 | cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; |
| @@ -1005,7 +1005,7 @@ struct bnxt_napi { · 1004 unmodified lines | ||
| 1005 | 1005 | struct bnxt_tx_ring_info *tx_ring; |
| 1006 | 1006 | |
| 1007 | 1007 | void (*tx_int)(struct bnxt *, struct bnxt_napi *, |
| 1008 | − int); | |
| 1008 | + int budget); | |
| 1009 | 1009 | int tx_pkts; |
| 1010 | 1010 | u8 events; |
| 1011 | 1011 | |
| @@ -125,16 +125,20 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp, · 124 unmodified lines | ||
| 125 | 125 | dma_unmap_len_set(tx_buf, len, 0); |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | −void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) | |
| 128 | +void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) | |
| 129 | 129 | { |
| 130 | 130 | struct bnxt_tx_ring_info *txr = bnapi->tx_ring; |
| 131 | 131 | struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; |
| 132 | 132 | bool rx_doorbell_needed = false; |
| 133 | + int nr_pkts = bnapi->tx_pkts; | |
| 133 | 134 | struct bnxt_sw_tx_bd *tx_buf; |
| 134 | 135 | u16 tx_cons = txr->tx_cons; |
| 135 | 136 | u16 last_tx_cons = tx_cons; |
| 136 | 137 | int i, j, frags; |
| 137 | 138 | |
| 139 | + if (!budget) | |
| 140 | + return; | |
| 141 | + | |
| 138 | 142 | for (i = 0; i < nr_pkts; i++) { |
| 139 | 143 | tx_buf = &txr->tx_buf_ring[tx_cons]; |
| 140 | 144 | |
| @@ -161,6 +165,8 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) · 20 unmodified lines | ||
| 161 | 165 | } |
| 162 | 166 | tx_cons = NEXT_TX(tx_cons); |
| 163 | 167 | } |
| 168 | + | |
| 169 | + bnapi->tx_pkts = 0; | |
| 164 | 170 | WRITE_ONCE(txr->tx_cons, tx_cons); |
| 165 | 171 | if (rx_doorbell_needed) { |
| 166 | 172 | tx_buf = &txr->tx_buf_ring[last_tx_cons]; |
| @@ -180,8 +186,8 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, · 13 unmodified lines | ||
| 180 | 186 | u16 cons, u8 *data_ptr, unsigned int len, |
| 181 | 187 | struct xdp_buff *xdp) |
| 182 | 188 | { |
| 189 | + u32 buflen = BNXT_RX_PAGE_SIZE; | |
| 183 | 190 | struct bnxt_sw_rx_bd *rx_buf; |
| 184 | − u32 buflen = PAGE_SIZE; | |
| 185 | 191 | struct pci_dev *pdev; |
| 186 | 192 | dma_addr_t mapping; |
| 187 | 193 | u32 offset; |
| @@ -297,7 +303,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, · 109 unmodified lines | ||
| 297 | 303 | rx_buf = &rxr->rx_buf_ring[cons]; |
| 298 | 304 | mapping = rx_buf->mapping - bp->rx_dma_offset; |
| 299 | 305 | dma_unmap_page_attrs(&pdev->dev, mapping, |
| 300 | − PAGE_SIZE, bp->rx_dir, | |
| 306 | + BNXT_RX_PAGE_SIZE, bp->rx_dir, | |
| 301 | 307 | DMA_ATTR_WEAK_ORDERING); |
| 302 | 308 | |
| 303 | 309 | /* if we are unable to allocate a new buffer, abort and reuse */ |
| @@ -480,7 +486,7 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags, · 176 unmodified lines | ||
| 480 | 486 | } |
| 481 | 487 | xdp_update_skb_shared_info(skb, num_frags, |
| 482 | 488 | sinfo->xdp_frags_size, |
| 483 | − PAGE_SIZE * sinfo->nr_frags, | |
| 489 | + BNXT_RX_PAGE_SIZE * sinfo->nr_frags, | |
| 484 | 490 | xdp_buff_is_frag_pfmemalloc(xdp)); |
| 485 | 491 | return skb; |
| 486 | 492 | } |
| @@ -16,7 +16,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp, · 15 unmodified lines | ||
| 16 | 16 | struct bnxt_tx_ring_info *txr, |
| 17 | 17 | dma_addr_t mapping, u32 len, |
| 18 | 18 | struct xdp_buff *xdp); |
| 19 | −void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts); | |
| 19 | +void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget); | |
| 20 | 20 | bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, |
| 21 | 21 | struct xdp_buff xdp, struct page *page, u8 **data_ptr, |
| 22 | 22 | unsigned int *len, u8 *event); |
| @@ -1186,14 +1186,9 @@ static int enetc_init_port_rss_memory(struct enetc_si *si) · 1185 unmodified lines | ||
| 1186 | 1186 | |
| 1187 | 1187 | static int enetc_pf_register_with_ierb(struct pci_dev *pdev) |
| 1188 | 1188 | { |
| 1189 | − struct device_node *node = pdev->dev.of_node; | |
| 1190 | 1189 | struct platform_device *ierb_pdev; |
| 1191 | 1190 | struct device_node *ierb_node; |
| 1192 | 1191 | |
| 1193 | − /* Don't register with the IERB if the PF itself is disabled */ | |
| 1194 | − if (!node || !of_device_is_available(node)) | |
| 1195 | − return 0; | |
| 1196 | − | |
| 1197 | 1192 | ierb_node = of_find_compatible_node(NULL, NULL, |
| 1198 | 1193 | "fsl,ls1028a-enetc-ierb"); |
| 1199 | 1194 | if (!ierb_node || !of_device_is_available(ierb_node)) |
| @@ -1208,56 +1203,81 @@ static int enetc_pf_register_with_ierb(struct pci_dev *pdev) · 8 unmodified lines | ||
| 1208 | 1203 | return enetc_ierb_register_pf(ierb_pdev, pdev); |
| 1209 | 1204 | } |
| 1210 | 1205 | |
| 1211 | −static int enetc_pf_probe(struct pci_dev *pdev, | |
| 1212 | − const struct pci_device_id *ent) | |
| 1206 | +static struct enetc_si *enetc_psi_create(struct pci_dev *pdev) | |
| 1213 | 1207 | { |
| 1214 | − struct device_node *node = pdev->dev.of_node; | |
| 1215 | − struct enetc_ndev_priv *priv; | |
| 1216 | − struct net_device *ndev; | |
| 1217 | 1208 | struct enetc_si *si; |
| 1218 | − struct enetc_pf *pf; | |
| 1219 | 1209 | int err; |
| 1220 | 1210 | |
| 1221 | − err = enetc_pf_register_with_ierb(pdev); | |
| 1222 | − if (err == -EPROBE_DEFER) | |
| 1223 | − return err; | |
| 1224 | − if (err) | |
| 1225 | − dev_warn(&pdev->dev, | |
| 1226 | − "Could not register with IERB driver: %pe, please update the device tree\n", | |
| 1227 | − ERR_PTR(err)); | |
| 1228 | − | |
| 1229 | − err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf)); | |
| 1230 | − if (err) | |
| 1231 | − return dev_err_probe(&pdev->dev, err, "PCI probing failed\n"); | |
| 1211 | + err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(struct enetc_pf)); | |
| 1212 | + if (err) { | |
| 1213 | + dev_err_probe(&pdev->dev, err, "PCI probing failed\n"); | |
| 1214 | + goto out; | |
| 1215 | + } | |
| 1232 | 1216 | |
| 1233 | 1217 | si = pci_get_drvdata(pdev); |
| 1234 | 1218 | if (!si->hw.port || !si->hw.global) { |
| 1235 | 1219 | err = -ENODEV; |
| 1236 | 1220 | dev_err(&pdev->dev, "could not map PF space, probing a VF?\n"); |
| 1237 | − goto err_map_pf_space; | |
| 1221 | + goto out_pci_remove; | |
| 1238 | 1222 | } |
| 1239 | 1223 | |
| 1240 | 1224 | err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE, |
| 1241 | 1225 | &si->cbd_ring); |
| 1242 | 1226 | if (err) |
| 1243 | − goto err_setup_cbdr; | |
| 1227 | + goto out_pci_remove; | |
| 1244 | 1228 | |
| 1245 | 1229 | err = enetc_init_port_rfs_memory(si); |
| 1246 | 1230 | if (err) { |
| 1247 | 1231 | dev_err(&pdev->dev, "Failed to initialize RFS memory\n"); |
| 1248 | − goto err_init_port_rfs; | |
| 1232 | + goto out_teardown_cbdr; | |
| 1249 | 1233 | } |
| 1250 | 1234 | |
| 1251 | 1235 | err = enetc_init_port_rss_memory(si); |
| 1252 | 1236 | if (err) { |
| 1253 | 1237 | dev_err(&pdev->dev, "Failed to initialize RSS memory\n"); |
| 1254 | − goto err_init_port_rss; | |
| 1238 | + goto out_teardown_cbdr; | |
| 1255 | 1239 | } |
| 1256 | 1240 | |
| 1257 | − if (node && !of_device_is_available(node)) { | |
| 1258 | − dev_info(&pdev->dev, "device is disabled, skipping\n"); | |
| 1259 | − err = -ENODEV; | |
| 1260 | − goto err_device_disabled; | |
| 1241 | + return si; | |
| 1242 | + | |
| 1243 | +out_teardown_cbdr: | |
| 1244 | + enetc_teardown_cbdr(&si->cbd_ring); | |
| 1245 | +out_pci_remove: | |
| 1246 | + enetc_pci_remove(pdev); | |
| 1247 | +out: | |
| 1248 | + return ERR_PTR(err); | |
| 1249 | +} | |
| 1250 | + | |
| 1251 | +static void enetc_psi_destroy(struct pci_dev *pdev) | |
| 1252 | +{ | |
| 1253 | + struct enetc_si *si = pci_get_drvdata(pdev); | |
| 1254 | + | |
| 1255 | + enetc_teardown_cbdr(&si->cbd_ring); | |
| 1256 | + enetc_pci_remove(pdev); | |
| 1257 | +} | |
| 1258 | + | |
| 1259 | +static int enetc_pf_probe(struct pci_dev *pdev, | |
| 1260 | + const struct pci_device_id *ent) | |
| 1261 | +{ | |
| 1262 | + struct device_node *node = pdev->dev.of_node; | |
| 1263 | + struct enetc_ndev_priv *priv; | |
| 1264 | + struct net_device *ndev; | |
| 1265 | + struct enetc_si *si; | |
| 1266 | + struct enetc_pf *pf; | |
| 1267 | + int err; | |
| 1268 | + | |
| 1269 | + err = enetc_pf_register_with_ierb(pdev); | |
| 1270 | + if (err == -EPROBE_DEFER) | |
| 1271 | + return err; | |
| 1272 | + if (err) | |
| 1273 | + dev_warn(&pdev->dev, | |
| 1274 | + "Could not register with IERB driver: %pe, please update the device tree\n", | |
| 1275 | + ERR_PTR(err)); | |
| 1276 | + | |
| 1277 | + si = enetc_psi_create(pdev); | |
| 1278 | + if (IS_ERR(si)) { | |
| 1279 | + err = PTR_ERR(si); | |
| 1280 | + goto err_psi_create; | |
| 1261 | 1281 | } |
| 1262 | 1282 | |
| 1263 | 1283 | pf = enetc_si_priv(si); |
| @@ -1339,15 +1359,9 @@ err_alloc_si_res: · 75 unmodified lines | ||
| 1339 | 1359 | si->ndev = NULL; |
| 1340 | 1360 | free_netdev(ndev); |
| 1341 | 1361 | err_alloc_netdev: |
| 1342 | −err_init_port_rss: | |
| 1343 | −err_init_port_rfs: | |
| 1344 | −err_device_disabled: | |
| 1345 | 1362 | err_setup_mac_addresses: |
| 1346 | − enetc_teardown_cbdr(&si->cbd_ring); | |
| 1347 | −err_setup_cbdr: | |
| 1348 | −err_map_pf_space: | |
| 1349 | − enetc_pci_remove(pdev); | |
| 1350 | − | |
| 1363 | + enetc_psi_destroy(pdev); | |
| 1364 | +err_psi_create: | |
| 1351 | 1365 | return err; |
| 1352 | 1366 | } |
| 1353 | 1367 | |
| @@ -1370,12 +1384,29 @@ static void enetc_pf_remove(struct pci_dev *pdev) · 16 unmodified lines | ||
| 1370 | 1384 | enetc_free_msix(priv); |
| 1371 | 1385 | |
| 1372 | 1386 | enetc_free_si_resources(priv); |
| 1373 | − enetc_teardown_cbdr(&si->cbd_ring); | |
| 1374 | 1387 | |
| 1375 | 1388 | free_netdev(si->ndev); |
| 1376 | 1389 | |
| 1377 | − enetc_pci_remove(pdev); | |
| 1390 | + enetc_psi_destroy(pdev); | |
| 1391 | +} | |
| 1392 | + | |
| 1393 | +static void enetc_fixup_clear_rss_rfs(struct pci_dev *pdev) | |
| 1394 | +{ | |
| 1395 | + struct device_node *node = pdev->dev.of_node; | |
| 1396 | + struct enetc_si *si; | |
| 1397 | + | |
| 1398 | + /* Only apply quirk for disabled functions. For the ones | |
| 1399 | + * that are enabled, enetc_pf_probe() will apply it. | |
| 1400 | + */ | |
| 1401 | + if (node && of_device_is_available(node)) | |
| 1402 | + return; | |
| 1403 | + | |
| 1404 | + si = enetc_psi_create(pdev); | |
| 1405 | + if (si) | |
| 1406 | + enetc_psi_destroy(pdev); | |
| 1378 | 1407 | } |
| 1408 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF, | |
| 1409 | + enetc_fixup_clear_rss_rfs); | |
| 1379 | 1410 | |
| 1380 | 1411 | static const struct pci_device_id enetc_pf_id_table[] = { |
| 1381 | 1412 | { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) }, |
| @@ -464,9 +464,9 @@ static void hns3_dbg_fill_content(char *content, u16 len, · 463 unmodified lines | ||
| 464 | 464 | if (result) { |
| 465 | 465 | if (item_len < strlen(result[i])) |
| 466 | 466 | break; |
| 467 | − strscpy(pos, result[i], strlen(result[i])); | |
| 467 | + memcpy(pos, result[i], strlen(result[i])); | |
| 468 | 468 | } else { |
| 469 | − strscpy(pos, items[i].name, strlen(items[i].name)); | |
| 469 | + memcpy(pos, items[i].name, strlen(items[i].name)); | |
| 470 | 470 | } |
| 471 | 471 | pos += item_len; |
| 472 | 472 | len -= item_len; |
| @@ -5854,6 +5854,9 @@ void hns3_external_lb_prepare(struct net_device *ndev, bool if_running) · 5853 unmodified lines | ||
| 5854 | 5854 | if (!if_running) |
| 5855 | 5855 | return; |
| 5856 | 5856 | |
| 5857 | + if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state)) | |
| 5858 | + return; | |
| 5859 | + | |
| 5857 | 5860 | netif_carrier_off(ndev); |
| 5858 | 5861 | netif_tx_disable(ndev); |
| 5859 | 5862 | |
| @@ -5882,7 +5885,16 @@ void hns3_external_lb_restore(struct net_device *ndev, bool if_running) · 22 unmodified lines | ||
| 5882 | 5885 | if (!if_running) |
| 5883 | 5886 | return; |
| 5884 | 5887 | |
| 5885 | − hns3_nic_reset_all_ring(priv->ae_handle); | |
| 5888 | + if (hns3_nic_resetting(ndev)) | |
| 5889 | + return; | |
| 5890 | + | |
| 5891 | + if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) | |
| 5892 | + return; | |
| 5893 | + | |
| 5894 | + if (hns3_nic_reset_all_ring(priv->ae_handle)) | |
| 5895 | + return; | |
| 5896 | + | |
| 5897 | + clear_bit(HNS3_NIC_STATE_DOWN, &priv->state); | |
| 5886 | 5898 | |
| 5887 | 5899 | for (i = 0; i < priv->vector_num; i++) |
| 5888 | 5900 | hns3_vector_enable(&priv->tqp_vector[i]); |
| @@ -111,9 +111,9 @@ static void hclge_dbg_fill_content(char *content, u16 len, · 110 unmodified lines | ||
| 111 | 111 | if (result) { |
| 112 | 112 | if (item_len < strlen(result[i])) |
| 113 | 113 | break; |
| 114 | − strscpy(pos, result[i], strlen(result[i])); | |
| 114 | + memcpy(pos, result[i], strlen(result[i])); | |
| 115 | 115 | } else { |
| 116 | − strscpy(pos, items[i].name, strlen(items[i].name)); | |
| 116 | + memcpy(pos, items[i].name, strlen(items[i].name)); | |
| 117 | 117 | } |
| 118 | 118 | pos += item_len; |
| 119 | 119 | len -= item_len; |
| @@ -72,6 +72,8 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev); · 71 unmodified lines | ||
| 72 | 72 | static void hclge_sync_promisc_mode(struct hclge_dev *hdev); |
| 73 | 73 | static void hclge_sync_fd_table(struct hclge_dev *hdev); |
| 74 | 74 | static void hclge_update_fec_stats(struct hclge_dev *hdev); |
| 75 | +static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret, | |
| 76 | + int wait_cnt); | |
| 75 | 77 | |
| 76 | 78 | static struct hnae3_ae_algo ae_algo; |
| 77 | 79 | |
| @@ -7558,6 +7560,8 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable) · 7480 unmodified lines | ||
| 7558 | 7560 | |
| 7559 | 7561 | static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable) |
| 7560 | 7562 | { |
| 7563 | +#define HCLGE_LINK_STATUS_WAIT_CNT 3 | |
| 7564 | + | |
| 7561 | 7565 | struct hclge_desc desc; |
| 7562 | 7566 | struct hclge_config_mac_mode_cmd *req = |
| 7563 | 7567 | (struct hclge_config_mac_mode_cmd *)desc.data; |
| @@ -7582,9 +7586,15 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable) · 18 unmodified lines | ||
| 7582 | 7586 | req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en); |
| 7583 | 7587 | |
| 7584 | 7588 | ret = hclge_cmd_send(&hdev->hw, &desc, 1); |
| 7585 | − if (ret) | |
| 7589 | + if (ret) { | |
| 7586 | 7590 | dev_err(&hdev->pdev->dev, |
| 7587 | 7591 | "mac enable fail, ret =%d.\n", ret); |
| 7592 | + return; | |
| 7593 | + } | |
| 7594 | + | |
| 7595 | + if (!enable) | |
| 7596 | + hclge_mac_link_status_wait(hdev, HCLGE_LINK_STATUS_DOWN, | |
| 7597 | + HCLGE_LINK_STATUS_WAIT_CNT); | |
| 7588 | 7598 | } |
| 7589 | 7599 | |
| 7590 | 7600 | static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid, |
| @@ -7647,10 +7657,9 @@ static void hclge_phy_link_status_wait(struct hclge_dev *hdev, · 56 unmodified lines | ||
| 7647 | 7657 | } while (++i < HCLGE_PHY_LINK_STATUS_NUM); |
| 7648 | 7658 | } |
| 7649 | 7659 | |
| 7650 | −static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret) | |
| 7660 | +static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret, | |
| 7661 | + int wait_cnt) | |
| 7651 | 7662 | { |
| 7652 | −#define HCLGE_MAC_LINK_STATUS_NUM 100 | |
| 7653 | − | |
| 7654 | 7663 | int link_status; |
| 7655 | 7664 | int i = 0; |
| 7656 | 7665 | int ret; |
| @@ -7663,13 +7672,15 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret) · 6 unmodified lines | ||
| 7663 | 7672 | return 0; |
| 7664 | 7673 | |
| 7665 | 7674 | msleep(HCLGE_LINK_STATUS_MS); |
| 7666 | − } while (++i < HCLGE_MAC_LINK_STATUS_NUM); | |
| 7675 | + } while (++i < wait_cnt); | |
| 7667 | 7676 | return -EBUSY; |
| 7668 | 7677 | } |
| 7669 | 7678 | |
| 7670 | 7679 | static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en, |
| 7671 | 7680 | bool is_phy) |
| 7672 | 7681 | { |
| 7682 | +#define HCLGE_MAC_LINK_STATUS_NUM 100 | |
| 7683 | + | |
| 7673 | 7684 | int link_ret; |
| 7674 | 7685 | |
| 7675 | 7686 | link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN; |
| @@ -7677,7 +7688,8 @@ static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en, · 1 unmodified line | ||
| 7677 | 7688 | if (is_phy) |
| 7678 | 7689 | hclge_phy_link_status_wait(hdev, link_ret); |
| 7679 | 7690 | |
| 7680 | − return hclge_mac_link_status_wait(hdev, link_ret); | |
| 7691 | + return hclge_mac_link_status_wait(hdev, link_ret, | |
| 7692 | + HCLGE_MAC_LINK_STATUS_NUM); | |
| 7681 | 7693 | } |
| 7682 | 7694 | |
| 7683 | 7695 | static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en) |
| @@ -10915,9 +10927,12 @@ int hclge_cfg_flowctrl(struct hclge_dev *hdev) · 3231 unmodified lines | ||
| 10915 | 10927 | u32 rx_pause, tx_pause; |
| 10916 | 10928 | u8 flowctl; |
| 10917 | 10929 | |
| 10918 | − if (!phydev->link || !phydev->autoneg) | |
| 10930 | + if (!phydev->link) | |
| 10919 | 10931 | return 0; |
| 10920 | 10932 | |
| 10933 | + if (!phydev->autoneg) | |
| 10934 | + return hclge_mac_pause_setup_hw(hdev); | |
| 10935 | + | |
| 10921 | 10936 | local_advertising = linkmode_adv_to_lcl_adv_t(phydev->advertising); |
| 10922 | 10937 | |
| 10923 | 10938 | if (phydev->pause) |
| @@ -1553,7 +1553,7 @@ static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc) · 1552 unmodified lines | ||
| 1553 | 1553 | return 0; |
| 1554 | 1554 | } |
| 1555 | 1555 | |
| 1556 | −static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev) | |
| 1556 | +int hclge_mac_pause_setup_hw(struct hclge_dev *hdev) | |
| 1557 | 1557 | { |
| 1558 | 1558 | bool tx_en, rx_en; |
| 1559 | 1559 | |
| @@ -245,6 +245,7 @@ int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap, · 244 unmodified lines | ||
| 245 | 245 | u8 pfc_bitmap); |
| 246 | 246 | int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx); |
| 247 | 247 | int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr); |
| 248 | +int hclge_mac_pause_setup_hw(struct hclge_dev *hdev); | |
| 248 | 249 | void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); |
| 249 | 250 | void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats); |
| 250 | 251 | int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate); |
| @@ -97,6 +97,8 @@ static int pending_scrq(struct ibmvnic_adapter *, · 96 unmodified lines | ||
| 97 | 97 | static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *, |
| 98 | 98 | struct ibmvnic_sub_crq_queue *); |
| 99 | 99 | static int ibmvnic_poll(struct napi_struct *napi, int data); |
| 100 | +static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter); | |
| 101 | +static inline void reinit_init_done(struct ibmvnic_adapter *adapter); | |
| 100 | 102 | static void send_query_map(struct ibmvnic_adapter *adapter); |
| 101 | 103 | static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, u32, u8); |
| 102 | 104 | static int send_request_unmap(struct ibmvnic_adapter *, u8); |
| @@ -114,6 +116,7 @@ static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter, · 11 unmodified lines | ||
| 114 | 116 | static void free_long_term_buff(struct ibmvnic_adapter *adapter, |
| 115 | 117 | struct ibmvnic_long_term_buff *ltb); |
| 116 | 118 | static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter); |
| 119 | +static void flush_reset_queue(struct ibmvnic_adapter *adapter); | |
| 117 | 120 | |
| 118 | 121 | struct ibmvnic_stat { |
| 119 | 122 | char name[ETH_GSTRING_LEN]; |
| @@ -1505,8 +1508,8 @@ static const char *adapter_state_to_string(enum vnic_state state) · 1385 unmodified lines | ||
| 1505 | 1508 | |
| 1506 | 1509 | static int ibmvnic_login(struct net_device *netdev) |
| 1507 | 1510 | { |
| 1511 | + unsigned long flags, timeout = msecs_to_jiffies(20000); | |
| 1508 | 1512 | struct ibmvnic_adapter *adapter = netdev_priv(netdev); |
| 1509 | − unsigned long timeout = msecs_to_jiffies(20000); | |
| 1510 | 1513 | int retry_count = 0; |
| 1511 | 1514 | int retries = 10; |
| 1512 | 1515 | bool retry; |
| @@ -1527,11 +1530,9 @@ static int ibmvnic_login(struct net_device *netdev) · 14 unmodified lines | ||
| 1527 | 1530 | |
| 1528 | 1531 | if (!wait_for_completion_timeout(&adapter->init_done, |
| 1529 | 1532 | timeout)) { |
| 1530 | − netdev_warn(netdev, "Login timed out, retrying...\n"); | |
| 1531 | − retry = true; | |
| 1532 | − adapter->init_done_rc = 0; | |
| 1533 | − retry_count++; | |
| 1534 | − continue; | |
| 1533 | + netdev_warn(netdev, "Login timed out\n"); | |
| 1534 | + adapter->login_pending = false; | |
| 1535 | + goto partial_reset; | |
| 1535 | 1536 | } |
| 1536 | 1537 | |
| 1537 | 1538 | if (adapter->init_done_rc == ABORTED) { |
| @@ -1573,10 +1574,69 @@ static int ibmvnic_login(struct net_device *netdev) · 35 unmodified lines | ||
| 1573 | 1574 | "SCRQ irq initialization failed\n"); |
| 1574 | 1575 | return rc; |
| 1575 | 1576 | } |
| 1577 | + /* Default/timeout error handling, reset and start fresh */ | |
| 1576 | 1578 | } else if (adapter->init_done_rc) { |
| 1577 | 1579 | netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n", |
| 1578 | 1580 | adapter->init_done_rc); |
| 1579 | − return -EIO; | |
| 1581 | + | |
| 1582 | +partial_reset: | |
| 1583 | + /* adapter login failed, so free any CRQs or sub-CRQs | |
| 1584 | + * and register again before attempting to login again. | |
| 1585 | + * If we don't do this then the VIOS may think that | |
| 1586 | + * we are already logged in and reject any subsequent | |
| 1587 | + * attempts | |
| 1588 | + */ | |
| 1589 | + netdev_warn(netdev, | |
| 1590 | + "Freeing and re-registering CRQs before attempting to login again\n"); | |
| 1591 | + retry = true; | |
| 1592 | + adapter->init_done_rc = 0; | |
| 1593 | + release_sub_crqs(adapter, true); | |
| 1594 | + /* Much of this is similar logic as ibmvnic_probe(), | |
| 1595 | + * we are essentially re-initializing communication | |
| 1596 | + * with the server. We really should not run any | |
| 1597 | + * resets/failovers here because this is already a form | |
| 1598 | + * of reset and we do not want parallel resets occurring | |
| 1599 | + */ | |
| 1600 | + do { | |
| 1601 | + reinit_init_done(adapter); | |
| 1602 | + /* Clear any failovers we got in the previous | |
| 1603 | + * pass since we are re-initializing the CRQ | |
| 1604 | + */ | |
| 1605 | + adapter->failover_pending = false; | |
| 1606 | + release_crq_queue(adapter); | |
| 1607 | + /* If we don't sleep here then we risk an | |
| 1608 | + * unnecessary failover event from the VIOS. | |
| 1609 | + * This is a known VIOS issue caused by a vnic | |
| 1610 | + * device freeing and registering a CRQ too | |
| 1611 | + * quickly. | |
| 1612 | + */ | |
| 1613 | + msleep(1500); | |
| 1614 | + /* Avoid any resets, since we are currently | |
| 1615 | + * resetting. | |
| 1616 | + */ | |
| 1617 | + spin_lock_irqsave(&adapter->rwi_lock, flags); | |
| 1618 | + flush_reset_queue(adapter); | |
| 1619 | + spin_unlock_irqrestore(&adapter->rwi_lock, | |
| 1620 | + flags); | |
| 1621 | + | |
| 1622 | + rc = init_crq_queue(adapter); | |
| 1623 | + if (rc) { | |
| 1624 | + netdev_err(netdev, "login recovery: init CRQ failed %d\n", | |
| 1625 | + rc); | |
| 1626 | + return -EIO; | |
| 1627 | + } | |
| 1628 | + | |
| 1629 | + rc = ibmvnic_reset_init(adapter, false); | |
| 1630 | + if (rc) | |
| 1631 | + netdev_err(netdev, "login recovery: Reset init failed %d\n", | |
| 1632 | + rc); | |
| 1633 | + /* IBMVNIC_CRQ_INIT will return EAGAIN if it | |
| 1634 | + * fails, since ibmvnic_reset_init will free | |
| 1635 | + * irq's in failure, we won't be able to receive | |
| 1636 | + * new CRQs so we need to keep trying. probe() | |
| 1637 | + * handles this similarly. | |
| 1638 | + */ | |
| 1639 | + } while (rc == -EAGAIN && retry_count++ < retries); | |
| 1580 | 1640 | } |
| 1581 | 1641 | } while (retry); |
| 1582 | 1642 | |
| @@ -1588,12 +1648,22 @@ static int ibmvnic_login(struct net_device *netdev) · 5 unmodified lines | ||
| 1588 | 1648 | |
| 1589 | 1649 | static void release_login_buffer(struct ibmvnic_adapter *adapter) |
| 1590 | 1650 | { |
| 1651 | + if (!adapter->login_buf) | |
| 1652 | + return; | |
| 1653 | + | |
| 1654 | + dma_unmap_single(&adapter->vdev->dev, adapter->login_buf_token, | |
| 1655 | + adapter->login_buf_sz, DMA_TO_DEVICE); | |
| 1591 | 1656 | kfree(adapter->login_buf); |
| 1592 | 1657 | adapter->login_buf = NULL; |
| 1593 | 1658 | } |
| 1594 | 1659 | |
| 1595 | 1660 | static void release_login_rsp_buffer(struct ibmvnic_adapter *adapter) |
| 1596 | 1661 | { |
| 1662 | + if (!adapter->login_rsp_buf) | |
| 1663 | + return; | |
| 1664 | + | |
| 1665 | + dma_unmap_single(&adapter->vdev->dev, adapter->login_rsp_buf_token, | |
| 1666 | + adapter->login_rsp_buf_sz, DMA_FROM_DEVICE); | |
| 1597 | 1667 | kfree(adapter->login_rsp_buf); |
| 1598 | 1668 | adapter->login_rsp_buf = NULL; |
| 1599 | 1669 | } |
| @@ -4830,11 +4900,14 @@ static int send_login(struct ibmvnic_adapter *adapter) · 3230 unmodified lines | ||
| 4830 | 4900 | if (rc) { |
| 4831 | 4901 | adapter->login_pending = false; |
| 4832 | 4902 | netdev_err(adapter->netdev, "Failed to send login, rc=%d\n", rc); |
| 4833 | − goto buf_rsp_map_failed; | |
| 4903 | + goto buf_send_failed; | |
| 4834 | 4904 | } |
| 4835 | 4905 | |
| 4836 | 4906 | return 0; |
| 4837 | 4907 | |
| 4908 | +buf_send_failed: | |
| 4909 | + dma_unmap_single(dev, rsp_buffer_token, rsp_buffer_size, | |
| 4910 | + DMA_FROM_DEVICE); | |
| 4838 | 4911 | buf_rsp_map_failed: |
| 4839 | 4912 | kfree(login_rsp_buffer); |
| 4840 | 4913 | adapter->login_rsp_buf = NULL; |
| @@ -5396,6 +5469,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, · 555 unmodified lines | ||
| 5396 | 5469 | int num_tx_pools; |
| 5397 | 5470 | int num_rx_pools; |
| 5398 | 5471 | u64 *size_array; |
| 5472 | + u32 rsp_len; | |
| 5399 | 5473 | int i; |
| 5400 | 5474 | |
| 5401 | 5475 | /* CHECK: Test/set of login_pending does not need to be atomic |
| @@ -5407,11 +5481,6 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, · 5 unmodified lines | ||
| 5407 | 5481 | } |
| 5408 | 5482 | adapter->login_pending = false; |
| 5409 | 5483 | |
| 5410 | − dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz, | |
| 5411 | − DMA_TO_DEVICE); | |
| 5412 | − dma_unmap_single(dev, adapter->login_rsp_buf_token, | |
| 5413 | − adapter->login_rsp_buf_sz, DMA_FROM_DEVICE); | |
| 5414 | − | |
| 5415 | 5484 | /* If the number of queues requested can't be allocated by the |
| 5416 | 5485 | * server, the login response will return with code 1. We will need |
| 5417 | 5486 | * to resend the login buffer with fewer queues requested. |
| @@ -5447,6 +5516,23 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, · 29 unmodified lines | ||
| 5447 | 5516 | ibmvnic_reset(adapter, VNIC_RESET_FATAL); |
| 5448 | 5517 | return -EIO; |
| 5449 | 5518 | } |
| 5519 | + | |
| 5520 | + rsp_len = be32_to_cpu(login_rsp->len); | |
| 5521 | + if (be32_to_cpu(login->login_rsp_len) < rsp_len || | |
| 5522 | + rsp_len <= be32_to_cpu(login_rsp->off_txsubm_subcrqs) || | |
| 5523 | + rsp_len <= be32_to_cpu(login_rsp->off_rxadd_subcrqs) || | |
| 5524 | + rsp_len <= be32_to_cpu(login_rsp->off_rxadd_buff_size) || | |
| 5525 | + rsp_len <= be32_to_cpu(login_rsp->off_supp_tx_desc)) { | |
| 5526 | + /* This can happen if a login request times out and there are | |
| 5527 | + * 2 outstanding login requests sent, the LOGIN_RSP crq | |
| 5528 | + * could have been for the older login request. So we are | |
| 5529 | + * parsing the newer response buffer which may be incomplete | |
| 5530 | + */ | |
| 5531 | + dev_err(dev, "FATAL: Login rsp offsets/lengths invalid\n"); | |
| 5532 | + ibmvnic_reset(adapter, VNIC_RESET_FATAL); | |
| 5533 | + return -EIO; | |
| 5534 | + } | |
| 5535 | + | |
| 5450 | 5536 | size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) + |
| 5451 | 5537 | be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size)); |
| 5452 | 5538 | /* variable buffer sizes are not supported, so just read the |
| @@ -1401,14 +1401,15 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx · 1400 unmodified lines | ||
| 1401 | 1401 | if (fsp->flow_type & FLOW_MAC_EXT) |
| 1402 | 1402 | return -EINVAL; |
| 1403 | 1403 | |
| 1404 | + spin_lock_bh(&adapter->fdir_fltr_lock); | |
| 1404 | 1405 | if (adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS) { |
| 1406 | + spin_unlock_bh(&adapter->fdir_fltr_lock); | |
| 1405 | 1407 | dev_err(&adapter->pdev->dev, |
| 1406 | 1408 | "Unable to add Flow Director filter because VF reached the limit of max allowed filters (%u)\n", |
| 1407 | 1409 | IAVF_MAX_FDIR_FILTERS); |
| 1408 | 1410 | return -ENOSPC; |
| 1409 | 1411 | } |
| 1410 | 1412 | |
| 1411 | − spin_lock_bh(&adapter->fdir_fltr_lock); | |
| 1412 | 1413 | if (iavf_find_fdir_fltr_by_loc(adapter, fsp->location)) { |
| 1413 | 1414 | dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n"); |
| 1414 | 1415 | spin_unlock_bh(&adapter->fdir_fltr_lock); |
| @@ -1781,7 +1782,9 @@ static int iavf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, · 366 unmodified lines | ||
| 1781 | 1782 | case ETHTOOL_GRXCLSRLCNT: |
| 1782 | 1783 | if (!FDIR_FLTR_SUPPORT(adapter)) |
| 1783 | 1784 | break; |
| 1785 | + spin_lock_bh(&adapter->fdir_fltr_lock); | |
| 1784 | 1786 | cmd->rule_cnt = adapter->fdir_active_fltr; |
| 1787 | + spin_unlock_bh(&adapter->fdir_fltr_lock); | |
| 1785 | 1788 | cmd->data = IAVF_MAX_FDIR_FILTERS; |
| 1786 | 1789 | ret = 0; |
| 1787 | 1790 | break; |
| @@ -722,7 +722,9 @@ void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *f · 721 unmodified lines | ||
| 722 | 722 | bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr) |
| 723 | 723 | { |
| 724 | 724 | struct iavf_fdir_fltr *tmp; |
| 725 | + bool ret = false; | |
| 725 | 726 | |
| 727 | + spin_lock_bh(&adapter->fdir_fltr_lock); | |
| 726 | 728 | list_for_each_entry(tmp, &adapter->fdir_list_head, list) { |
| 727 | 729 | if (tmp->flow_type != fltr->flow_type) |
| 728 | 730 | continue; |
| @@ -732,11 +734,14 @@ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr * · 3 unmodified lines | ||
| 732 | 734 | !memcmp(&tmp->ip_data, &fltr->ip_data, |
| 733 | 735 | sizeof(fltr->ip_data)) && |
| 734 | 736 | !memcmp(&tmp->ext_data, &fltr->ext_data, |
| 735 | − sizeof(fltr->ext_data))) | |
| 736 | − return true; | |
| 737 | + sizeof(fltr->ext_data))) { | |
| 738 | + ret = true; | |
| 739 | + break; | |
| 740 | + } | |
| 737 | 741 | } |
| 742 | + spin_unlock_bh(&adapter->fdir_fltr_lock); | |
| 738 | 743 | |
| 739 | − return false; | |
| 744 | + return ret; | |
| 740 | 745 | } |
| 741 | 746 | |
| 742 | 747 | /** |
| @@ -8813,6 +8813,7 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type, · 8812 unmodified lines | ||
| 8813 | 8813 | { |
| 8814 | 8814 | struct ice_netdev_priv *np = netdev_priv(netdev); |
| 8815 | 8815 | struct ice_pf *pf = np->vsi->back; |
| 8816 | + bool locked = false; | |
| 8816 | 8817 | int err; |
| 8817 | 8818 | |
| 8818 | 8819 | switch (type) { |
| @@ -8822,10 +8823,27 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type, · 3 unmodified lines | ||
| 8822 | 8823 | ice_setup_tc_block_cb, |
| 8823 | 8824 | np, np, true); |
| 8824 | 8825 | case TC_SETUP_QDISC_MQPRIO: |
| 8826 | + if (pf->adev) { | |
| 8827 | + mutex_lock(&pf->adev_mutex); | |
| 8828 | + device_lock(&pf->adev->dev); | |
| 8829 | + locked = true; | |
| 8830 | + if (pf->adev->dev.driver) { | |
| 8831 | + netdev_err(netdev, "Cannot change qdisc when RDMA is active\n"); | |
| 8832 | + err = -EBUSY; | |
| 8833 | + goto adev_unlock; | |
| 8834 | + } | |
| 8835 | + } | |
| 8836 | + | |
| 8825 | 8837 | /* setup traffic classifier for receive side */ |
| 8826 | 8838 | mutex_lock(&pf->tc_mutex); |
| 8827 | 8839 | err = ice_setup_tc_mqprio_qdisc(netdev, type_data); |
| 8828 | 8840 | mutex_unlock(&pf->tc_mutex); |
| 8841 | + | |
| 8842 | +adev_unlock: | |
| 8843 | + if (locked) { | |
| 8844 | + device_unlock(&pf->adev->dev); | |
| 8845 | + mutex_unlock(&pf->adev_mutex); | |
| 8846 | + } | |
| 8829 | 8847 | return err; |
| 8830 | 8848 | default: |
| 8831 | 8849 | return -EOPNOTSUPP; |
| @@ -195,6 +195,10 @@ struct igc_adapter { · 194 unmodified lines | ||
| 195 | 195 | u32 qbv_config_change_errors; |
| 196 | 196 | bool qbv_transition; |
| 197 | 197 | unsigned int qbv_count; |
| 198 | + /* Access to oper_gate_closed, admin_gate_closed and qbv_transition | |
| 199 | + * are protected by the qbv_tx_lock. | |
| 200 | + */ | |
| 201 | + spinlock_t qbv_tx_lock; | |
| 198 | 202 | |
| 199 | 203 | /* OS defined structs */ |
| 200 | 204 | struct pci_dev *pdev; |
| @@ -4801,6 +4801,7 @@ static int igc_sw_init(struct igc_adapter *adapter) · 4800 unmodified lines | ||
| 4801 | 4801 | adapter->nfc_rule_count = 0; |
| 4802 | 4802 | |
| 4803 | 4803 | spin_lock_init(&adapter->stats64_lock); |
| 4804 | + spin_lock_init(&adapter->qbv_tx_lock); | |
| 4804 | 4805 | /* Assume MSI-X interrupts, will be checked during IRQ allocation */ |
| 4805 | 4806 | adapter->flags |= IGC_FLAG_HAS_MSIX; |
| 4806 | 4807 | |
| @@ -6119,15 +6120,15 @@ static int igc_tsn_enable_launchtime(struct igc_adapter *adapter, · 1312 unmodified lines | ||
| 6119 | 6120 | return igc_tsn_offload_apply(adapter); |
| 6120 | 6121 | } |
| 6121 | 6122 | |
| 6122 | −static int igc_tsn_clear_schedule(struct igc_adapter *adapter) | |
| 6123 | +static int igc_qbv_clear_schedule(struct igc_adapter *adapter) | |
| 6123 | 6124 | { |
| 6125 | + unsigned long flags; | |
| 6124 | 6126 | int i; |
| 6125 | 6127 | |
| 6126 | 6128 | adapter->base_time = 0; |
| 6127 | 6129 | adapter->cycle_time = NSEC_PER_SEC; |
| 6128 | 6130 | adapter->taprio_offload_enable = false; |
| 6129 | 6131 | adapter->qbv_config_change_errors = 0; |
| 6130 | − adapter->qbv_transition = false; | |
| 6131 | 6132 | adapter->qbv_count = 0; |
| 6132 | 6133 | |
| 6133 | 6134 | for (i = 0; i < adapter->num_tx_queues; i++) { |
| @@ -6136,10 +6137,28 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter) · 2 unmodified lines | ||
| 6136 | 6137 | ring->start_time = 0; |
| 6137 | 6138 | ring->end_time = NSEC_PER_SEC; |
| 6138 | 6139 | ring->max_sdu = 0; |
| 6140 | + } | |
| 6141 | + | |
| 6142 | + spin_lock_irqsave(&adapter->qbv_tx_lock, flags); | |
| 6143 | + | |
| 6144 | + adapter->qbv_transition = false; | |
| 6145 | + | |
| 6146 | + for (i = 0; i < adapter->num_tx_queues; i++) { | |
| 6147 | + struct igc_ring *ring = adapter->tx_ring[i]; | |
| 6148 | + | |
| 6139 | 6149 | ring->oper_gate_closed = false; |
| 6140 | 6150 | ring->admin_gate_closed = false; |
| 6141 | 6151 | } |
| 6142 | 6152 | |
| 6153 | + spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags); | |
| 6154 | + | |
| 6155 | + return 0; | |
| 6156 | +} | |
| 6157 | + | |
| 6158 | +static int igc_tsn_clear_schedule(struct igc_adapter *adapter) | |
| 6159 | +{ | |
| 6160 | + igc_qbv_clear_schedule(adapter); | |
| 6161 | + | |
| 6143 | 6162 | return 0; |
| 6144 | 6163 | } |
| 6145 | 6164 | |
| @@ -6150,6 +6169,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, · 4 unmodified lines | ||
| 6150 | 6169 | struct igc_hw *hw = &adapter->hw; |
| 6151 | 6170 | u32 start_time = 0, end_time = 0; |
| 6152 | 6171 | struct timespec64 now; |
| 6172 | + unsigned long flags; | |
| 6153 | 6173 | size_t n; |
| 6154 | 6174 | int i; |
| 6155 | 6175 | |
| @@ -6217,6 +6237,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, · 61 unmodified lines | ||
| 6217 | 6237 | start_time += e->interval; |
| 6218 | 6238 | } |
| 6219 | 6239 | |
| 6240 | + spin_lock_irqsave(&adapter->qbv_tx_lock, flags); | |
| 6241 | + | |
| 6220 | 6242 | /* Check whether a queue gets configured. |
| 6221 | 6243 | * If not, set the start and end time to be end time. |
| 6222 | 6244 | */ |
| @@ -6241,6 +6263,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, · 18 unmodified lines | ||
| 6241 | 6263 | } |
| 6242 | 6264 | } |
| 6243 | 6265 | |
| 6266 | + spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags); | |
| 6267 | + | |
| 6244 | 6268 | for (i = 0; i < adapter->num_tx_queues; i++) { |
| 6245 | 6269 | struct igc_ring *ring = adapter->tx_ring[i]; |
| 6246 | 6270 | struct net_device *dev = adapter->netdev; |
| @@ -6619,8 +6643,11 @@ static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer) · 372 unmodified lines | ||
| 6619 | 6643 | { |
| 6620 | 6644 | struct igc_adapter *adapter = container_of(timer, struct igc_adapter, |
| 6621 | 6645 | hrtimer); |
| 6646 | + unsigned long flags; | |
| 6622 | 6647 | unsigned int i; |
| 6623 | 6648 | |
| 6649 | + spin_lock_irqsave(&adapter->qbv_tx_lock, flags); | |
| 6650 | + | |
| 6624 | 6651 | adapter->qbv_transition = true; |
| 6625 | 6652 | for (i = 0; i < adapter->num_tx_queues; i++) { |
| 6626 | 6653 | struct igc_ring *tx_ring = adapter->tx_ring[i]; |
| @@ -6633,6 +6660,9 @@ static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer) · 6 unmodified lines | ||
| 6633 | 6660 | } |
| 6634 | 6661 | } |
| 6635 | 6662 | adapter->qbv_transition = false; |
| 6663 | + | |
| 6664 | + spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags); | |
| 6665 | + | |
| 6636 | 6666 | return HRTIMER_NORESTART; |
| 6637 | 6667 | } |
| 6638 | 6668 | |
| @@ -1302,11 +1302,10 @@ static int korina_probe(struct platform_device *pdev) · 1301 unmodified lines | ||
| 1302 | 1302 | else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0) |
| 1303 | 1303 | eth_hw_addr_random(dev); |
| 1304 | 1304 | |
| 1305 | − clk = devm_clk_get_optional(&pdev->dev, "mdioclk"); | |
| 1305 | + clk = devm_clk_get_optional_enabled(&pdev->dev, "mdioclk"); | |
| 1306 | 1306 | if (IS_ERR(clk)) |
| 1307 | 1307 | return PTR_ERR(clk); |
| 1308 | 1308 | if (clk) { |
| 1309 | − clk_prepare_enable(clk); | |
| 1310 | 1309 | lp->mii_clock_freq = clk_get_rate(clk); |
| 1311 | 1310 | } else { |
| 1312 | 1311 | lp->mii_clock_freq = 200000000; /* max possible input clk */ |
| @@ -98,6 +98,9 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox) · 97 unmodified lines | ||
| 98 | 98 | writeq(OCTEP_CTRL_MBOX_STATUS_INIT, |
| 99 | 99 | OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem)); |
| 100 | 100 | |
| 101 | + mutex_init(&mbox->h2fq_lock); | |
| 102 | + mutex_init(&mbox->f2hq_lock); | |
| 103 | + | |
| 101 | 104 | mbox->h2fq.sz = readl(OCTEP_CTRL_MBOX_H2FQ_SZ(mbox->barmem)); |
| 102 | 105 | mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD(mbox->barmem); |
| 103 | 106 | mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS(mbox->barmem); |
| @@ -727,7 +727,8 @@ pick_fw_ver: · 726 unmodified lines | ||
| 727 | 727 | |
| 728 | 728 | err = request_firmware_direct(&fw->bin, fw_path, fw->dev.dev); |
| 729 | 729 | if (err) { |
| 730 | − if (ver_maj == PRESTERA_SUPP_FW_MAJ_VER) { | |
| 730 | + if (ver_maj != PRESTERA_PREV_FW_MAJ_VER || | |
| 731 | + ver_min != PRESTERA_PREV_FW_MIN_VER) { | |
| 731 | 732 | ver_maj = PRESTERA_PREV_FW_MAJ_VER; |
| 732 | 733 | ver_min = PRESTERA_PREV_FW_MIN_VER; |
| 733 | 734 | |
| @@ -166,11 +166,11 @@ prestera_util_neigh2nc_key(struct prestera_switch *sw, struct neighbour *n, · 165 unmodified lines | ||
| 166 | 166 | |
| 167 | 167 | static bool __prestera_fi_is_direct(struct fib_info *fi) |
| 168 | 168 | { |
| 169 | − struct fib_nh *fib_nh; | |
| 169 | + struct fib_nh_common *fib_nhc; | |
| 170 | 170 | |
| 171 | 171 | if (fib_info_num_path(fi) == 1) { |
| 172 | − fib_nh = fib_info_nh(fi, 0); | |
| 173 | − if (fib_nh->fib_nh_gw_family == AF_UNSPEC) | |
| 172 | + fib_nhc = fib_info_nhc(fi, 0); | |
| 173 | + if (fib_nhc->nhc_gw_family == AF_UNSPEC) | |
| 174 | 174 | return true; |
| 175 | 175 | } |
| 176 | 176 | |
| @@ -261,7 +261,7 @@ static bool · 84 unmodified lines | ||
| 261 | 261 | __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr, |
| 262 | 262 | struct net_device *dev) |
| 263 | 263 | { |
| 264 | − struct fib_nh *fib_nh; | |
| 264 | + struct fib_nh_common *fib_nhc; | |
| 265 | 265 | struct fib_result res; |
| 266 | 266 | bool reachable; |
| 267 | 267 | |
| @@ -269,8 +269,8 @@ __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr, · 1 unmodified line | ||
| 269 | 269 | |
| 270 | 270 | if (!prestera_util_kern_get_route(&res, tb_id, addr)) |
| 271 | 271 | if (prestera_fi_is_direct(res.fi)) { |
| 272 | − fib_nh = fib_info_nh(res.fi, 0); | |
| 273 | − if (dev == fib_nh->fib_nh_dev) | |
| 272 | + fib_nhc = fib_info_nhc(res.fi, 0); | |
| 273 | + if (dev == fib_nhc->nhc_dev) | |
| 274 | 274 | reachable = true; |
| 275 | 275 | } |
| 276 | 276 | |
| @@ -324,7 +324,7 @@ prestera_kern_fib_info_nhc(struct fib_notifier_info *info, int n) · 47 unmodified lines | ||
| 324 | 324 | if (info->family == AF_INET) { |
| 325 | 325 | fen4_info = container_of(info, struct fib_entry_notifier_info, |
| 326 | 326 | info); |
| 327 | − return &fib_info_nh(fen4_info->fi, n)->nh_common; | |
| 327 | + return fib_info_nhc(fen4_info->fi, n); | |
| 328 | 328 | } else if (info->family == AF_INET6) { |
| 329 | 329 | fen6_info = container_of(info, struct fib6_entry_notifier_info, |
| 330 | 330 | info); |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. */ |
| 3 | 3 | |
| 4 | 4 | #include "reporter_vnic.h" |
| 5 | +#include "en_stats.h" | |
| 5 | 6 | #include "devlink.h" |
| 6 | 7 | |
| 7 | 8 | #define VNIC_ENV_GET64(vnic_env_stats, c) \ |
| @@ -36,55 +37,72 @@ int mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev, · 28 unmodified lines | ||
| 36 | 37 | if (err) |
| 37 | 38 | return err; |
| 38 | 39 | |
| 39 | − err = devlink_fmsg_u64_pair_put(fmsg, "total_error_queues", | |
| 40 | − VNIC_ENV_GET64(&vnic, total_error_queues)); | |
| 41 | − if (err) | |
| 42 | − return err; | |
| 43 | − | |
| 44 | − err = devlink_fmsg_u64_pair_put(fmsg, "send_queue_priority_update_flow", | |
| 45 | − VNIC_ENV_GET64(&vnic, send_queue_priority_update_flow)); | |
| 46 | − if (err) | |
| 47 | − return err; | |
| 48 | − | |
| 49 | − err = devlink_fmsg_u64_pair_put(fmsg, "comp_eq_overrun", | |
| 50 | − VNIC_ENV_GET64(&vnic, comp_eq_overrun)); | |
| 51 | − if (err) | |
| 52 | − return err; | |
| 53 | − | |
| 54 | − err = devlink_fmsg_u64_pair_put(fmsg, "async_eq_overrun", | |
| 55 | − VNIC_ENV_GET64(&vnic, async_eq_overrun)); | |
| 56 | − if (err) | |
| 57 | − return err; | |
| 58 | − | |
| 59 | − err = devlink_fmsg_u64_pair_put(fmsg, "cq_overrun", | |
| 60 | − VNIC_ENV_GET64(&vnic, cq_overrun)); | |
| 61 | − if (err) | |
| 62 | − return err; | |
| 63 | − | |
| 64 | − err = devlink_fmsg_u64_pair_put(fmsg, "invalid_command", | |
| 65 | − VNIC_ENV_GET64(&vnic, invalid_command)); | |
| 66 | − if (err) | |
| 67 | − return err; | |
| 68 | − | |
| 69 | − err = devlink_fmsg_u64_pair_put(fmsg, "quota_exceeded_command", | |
| 70 | − VNIC_ENV_GET64(&vnic, quota_exceeded_command)); | |
| 71 | − if (err) | |
| 72 | − return err; | |
| 73 | − | |
| 74 | − err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard", | |
| 75 | − VNIC_ENV_GET64(&vnic, nic_receive_steering_discard)); | |
| 76 | − if (err) | |
| 77 | − return err; | |
| 78 | − | |
| 79 | − err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail", | |
| 80 | − VNIC_ENV_GET64(&vnic, generated_pkt_steering_fail)); | |
| 81 | − if (err) | |
| 82 | − return err; | |
| 83 | − | |
| 84 | − err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail", | |
| 85 | − VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail)); | |
| 86 | − if (err) | |
| 87 | − return err; | |
| 40 | + if (MLX5_CAP_GEN(dev, vnic_env_queue_counters)) { | |
| 41 | + err = devlink_fmsg_u32_pair_put(fmsg, "total_error_queues", | |
| 42 | + VNIC_ENV_GET(&vnic, total_error_queues)); | |
| 43 | + if (err) | |
| 44 | + return err; | |
| 45 | + | |
| 46 | + err = devlink_fmsg_u32_pair_put(fmsg, "send_queue_priority_update_flow", | |
| 47 | + VNIC_ENV_GET(&vnic, | |
| 48 | + send_queue_priority_update_flow)); | |
| 49 | + if (err) | |
| 50 | + return err; | |
| 51 | + } | |
| 52 | + | |
| 53 | + if (MLX5_CAP_GEN(dev, eq_overrun_count)) { | |
| 54 | + err = devlink_fmsg_u32_pair_put(fmsg, "comp_eq_overrun", | |
| 55 | + VNIC_ENV_GET(&vnic, comp_eq_overrun)); | |
| 56 | + if (err) | |
| 57 | + return err; | |
| 58 | + | |
| 59 | + err = devlink_fmsg_u32_pair_put(fmsg, "async_eq_overrun", | |
| 60 | + VNIC_ENV_GET(&vnic, async_eq_overrun)); | |
| 61 | + if (err) | |
| 62 | + return err; | |
| 63 | + } | |
| 64 | + | |
| 65 | + if (MLX5_CAP_GEN(dev, vnic_env_cq_overrun)) { | |
| 66 | + err = devlink_fmsg_u32_pair_put(fmsg, "cq_overrun", | |
| 67 | + VNIC_ENV_GET(&vnic, cq_overrun)); | |
| 68 | + if (err) | |
| 69 | + return err; | |
| 70 | + } | |
| 71 | + | |
| 72 | + if (MLX5_CAP_GEN(dev, invalid_command_count)) { | |
| 73 | + err = devlink_fmsg_u32_pair_put(fmsg, "invalid_command", | |
| 74 | + VNIC_ENV_GET(&vnic, invalid_command)); | |
| 75 | + if (err) | |
| 76 | + return err; | |
| 77 | + } | |
| 78 | + | |
| 79 | + if (MLX5_CAP_GEN(dev, quota_exceeded_count)) { | |
| 80 | + err = devlink_fmsg_u32_pair_put(fmsg, "quota_exceeded_command", | |
| 81 | + VNIC_ENV_GET(&vnic, quota_exceeded_command)); | |
| 82 | + if (err) | |
| 83 | + return err; | |
| 84 | + } | |
| 85 | + | |
| 86 | + if (MLX5_CAP_GEN(dev, nic_receive_steering_discard)) { | |
| 87 | + err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard", | |
| 88 | + VNIC_ENV_GET64(&vnic, | |
| 89 | + nic_receive_steering_discard)); | |
| 90 | + if (err) | |
| 91 | + return err; | |
| 92 | + } | |
| 93 | + | |
| 94 | + if (MLX5_CAP_GEN(dev, vnic_env_cnt_steering_fail)) { | |
| 95 | + err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail", | |
| 96 | + VNIC_ENV_GET64(&vnic, | |
| 97 | + generated_pkt_steering_fail)); | |
| 98 | + if (err) | |
| 99 | + return err; | |
| 100 | + | |
| 101 | + err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail", | |
| 102 | + VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail)); | |
| 103 | + if (err) | |
| 104 | + return err; | |
| 105 | + } | |
| 88 | 106 | |
| 89 | 107 | err = devlink_fmsg_obj_nest_end(fmsg); |
| 90 | 108 | if (err) |
| @@ -1030,9 +1030,6 @@ int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv, · 1029 unmodified lines | ||
| 1030 | 1030 | int out_index; |
| 1031 | 1031 | int err = 0; |
| 1032 | 1032 | |
| 1033 | − if (!mlx5e_is_eswitch_flow(flow)) | |
| 1034 | − return 0; | |
| 1035 | − | |
| 1036 | 1033 | parse_attr = attr->parse_attr; |
| 1037 | 1034 | esw_attr = attr->esw_attr; |
| 1038 | 1035 | *vf_tun = false; |
| @@ -1464,10 +1461,12 @@ static void mlx5e_invalidate_encap(struct mlx5e_priv *priv, · 425 unmodified lines | ||
| 1464 | 1461 | attr = mlx5e_tc_get_encap_attr(flow); |
| 1465 | 1462 | esw_attr = attr->esw_attr; |
| 1466 | 1463 | |
| 1467 | − if (flow_flag_test(flow, SLOW)) | |
| 1464 | + if (flow_flag_test(flow, SLOW)) { | |
| 1468 | 1465 | mlx5e_tc_unoffload_from_slow_path(esw, flow); |
| 1469 | − else | |
| 1466 | + } else { | |
| 1470 | 1467 | mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr); |
| 1468 | + mlx5e_tc_unoffload_flow_post_acts(flow); | |
| 1469 | + } | |
| 1471 | 1470 | |
| 1472 | 1471 | mlx5e_tc_detach_mod_hdr(priv, flow, attr); |
| 1473 | 1472 | attr->modify_hdr = NULL; |
| @@ -323,8 +323,11 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_linear(struct mlx5e_rq *rq, · 322 unmodified lines | ||
| 323 | 323 | net_prefetch(mxbuf->xdp.data); |
| 324 | 324 | |
| 325 | 325 | prog = rcu_dereference(rq->xdp_prog); |
| 326 | − if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf))) | |
| 326 | + if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf))) { | |
| 327 | + if (likely(__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))) | |
| 328 | + wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE); | |
| 327 | 329 | return NULL; /* page/packet was consumed by XDP */ |
| 330 | + } | |
| 328 | 331 | |
| 329 | 332 | /* XDP_PASS: copy the data from the UMEM to a new SKB. The frame reuse |
| 330 | 333 | * will be handled by mlx5e_free_rx_wqe. |
| @@ -808,9 +808,9 @@ static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upsp · 807 unmodified lines | ||
| 808 | 808 | } |
| 809 | 809 | |
| 810 | 810 | if (upspec->sport) { |
| 811 | − MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_dport, | |
| 811 | + MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_sport, | |
| 812 | 812 | upspec->sport_mask); |
| 813 | − MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_dport, upspec->sport); | |
| 813 | + MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_sport, upspec->sport); | |
| 814 | 814 | } |
| 815 | 815 | } |
| 816 | 816 | |
| @@ -58,7 +58,9 @@ static int mlx5e_ipsec_remove_trailer(struct sk_buff *skb, struct xfrm_state *x) · 57 unmodified lines | ||
| 58 | 58 | |
| 59 | 59 | trailer_len = alen + plen + 2; |
| 60 | 60 | |
| 61 | − pskb_trim(skb, skb->len - trailer_len); | |
| 61 | + ret = pskb_trim(skb, skb->len - trailer_len); | |
| 62 | + if (unlikely(ret)) | |
| 63 | + return ret; | |
| 62 | 64 | if (skb->protocol == htons(ETH_P_IP)) { |
| 63 | 65 | ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len); |
| 64 | 66 | ip_send_check(ipv4hdr); |
| @@ -188,7 +188,6 @@ static void mlx5e_tls_debugfs_init(struct mlx5e_tls *tls, · 187 unmodified lines | ||
| 188 | 188 | |
| 189 | 189 | int mlx5e_ktls_init(struct mlx5e_priv *priv) |
| 190 | 190 | { |
| 191 | − struct mlx5_crypto_dek_pool *dek_pool; | |
| 192 | 191 | struct mlx5e_tls *tls; |
| 193 | 192 | |
| 194 | 193 | if (!mlx5e_is_ktls_device(priv->mdev)) |
| @@ -199,12 +198,6 @@ int mlx5e_ktls_init(struct mlx5e_priv *priv) · 4 unmodified lines | ||
| 199 | 198 | return -ENOMEM; |
| 200 | 199 | tls->mdev = priv->mdev; |
| 201 | 200 | |
| 202 | − dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY); | |
| 203 | − if (IS_ERR(dek_pool)) { | |
| 204 | − kfree(tls); | |
| 205 | − return PTR_ERR(dek_pool); | |
| 206 | − } | |
| 207 | − tls->dek_pool = dek_pool; | |
| 208 | 201 | priv->tls = tls; |
| 209 | 202 | |
| 210 | 203 | mlx5e_tls_debugfs_init(tls, priv->dfs_root); |
| @@ -222,7 +215,6 @@ void mlx5e_ktls_cleanup(struct mlx5e_priv *priv) · 11 unmodified lines | ||
| 222 | 215 | debugfs_remove_recursive(tls->debugfs.dfs); |
| 223 | 216 | tls->debugfs.dfs = NULL; |
| 224 | 217 | |
| 225 | − mlx5_crypto_dek_pool_destroy(tls->dek_pool); | |
| 226 | 218 | kfree(priv->tls); |
| 227 | 219 | priv->tls = NULL; |
| 228 | 220 | } |
| @@ -908,28 +908,51 @@ static void mlx5e_tls_tx_debugfs_init(struct mlx5e_tls *tls, · 907 unmodified lines | ||
| 908 | 908 | |
| 909 | 909 | int mlx5e_ktls_init_tx(struct mlx5e_priv *priv) |
| 910 | 910 | { |
| 911 | + struct mlx5_crypto_dek_pool *dek_pool; | |
| 911 | 912 | struct mlx5e_tls *tls = priv->tls; |
| 913 | + int err; | |
| 914 | + | |
| 915 | + if (!mlx5e_is_ktls_device(priv->mdev)) | |
| 916 | + return 0; | |
| 917 | + | |
| 918 | + /* DEK pool could be used by either or both of TX and RX. But we have to | |
| 919 | + * put the creation here to avoid syndrome when doing devlink reload. | |
| 920 | + */ | |
| 921 | + dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY); | |
| 922 | + if (IS_ERR(dek_pool)) | |
| 923 | + return PTR_ERR(dek_pool); | |
| 924 | + tls->dek_pool = dek_pool; | |
| 912 | 925 | |
| 913 | 926 | if (!mlx5e_is_ktls_tx(priv->mdev)) |
| 914 | 927 | return 0; |
| 915 | 928 | |
| 916 | 929 | priv->tls->tx_pool = mlx5e_tls_tx_pool_init(priv->mdev, &priv->tls->sw_stats); |
| 917 | − if (!priv->tls->tx_pool) | |
| 918 | − return -ENOMEM; | |
| 930 | + if (!priv->tls->tx_pool) { | |
| 931 | + err = -ENOMEM; | |
| 932 | + goto err_tx_pool_init; | |
| 933 | + } | |
| 919 | 934 | |
| 920 | 935 | mlx5e_tls_tx_debugfs_init(tls, tls->debugfs.dfs); |
| 921 | 936 | |
| 922 | 937 | return 0; |
| 938 | + | |
| 939 | +err_tx_pool_init: | |
| 940 | + mlx5_crypto_dek_pool_destroy(dek_pool); | |
| 941 | + return err; | |
| 923 | 942 | } |
| 924 | 943 | |
| 925 | 944 | void mlx5e_ktls_cleanup_tx(struct mlx5e_priv *priv) |
| 926 | 945 | { |
| 927 | 946 | if (!mlx5e_is_ktls_tx(priv->mdev)) |
| 928 | − return; | |
| 947 | + goto dek_pool_destroy; | |
| 929 | 948 | |
| 930 | 949 | debugfs_remove_recursive(priv->tls->debugfs.dfs_tx); |
| 931 | 950 | priv->tls->debugfs.dfs_tx = NULL; |
| 932 | 951 | |
| 933 | 952 | mlx5e_tls_tx_pool_cleanup(priv->tls->tx_pool); |
| 934 | 953 | priv->tls->tx_pool = NULL; |
| 954 | + | |
| 955 | +dek_pool_destroy: | |
| 956 | + if (mlx5e_is_ktls_device(priv->mdev)) | |
| 957 | + mlx5_crypto_dek_pool_destroy(priv->tls->dek_pool); | |
| 935 | 958 | } |
| @@ -161,6 +161,7 @@ static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft) · 160 unmodified lines | ||
| 161 | 161 | |
| 162 | 162 | if (!in) { |
| 163 | 163 | kfree(ft->g); |
| 164 | + ft->g = NULL; | |
| 164 | 165 | return -ENOMEM; |
| 165 | 166 | } |
| 166 | 167 | |
| @@ -135,6 +135,16 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs); · 134 unmodified lines | ||
| 135 | 135 | |
| 136 | 136 | int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs) |
| 137 | 137 | { |
| 138 | + /* Moving to switchdev mode, fs->arfs is freed by mlx5e_nic_profile | |
| 139 | + * cleanup_rx callback and it is not recreated when | |
| 140 | + * mlx5e_uplink_rep_profile is loaded as mlx5e_create_flow_steering() | |
| 141 | + * is not called by the uplink_rep profile init_rx callback. Thus, if | |
| 142 | + * ntuple is set, moving to switchdev flow will enter this function | |
| 143 | + * with fs->arfs nullified. | |
| 144 | + */ | |
| 145 | + if (!mlx5e_fs_get_arfs(fs)) | |
| 146 | + return 0; | |
| 147 | + | |
| 138 | 148 | arfs_del_rules(fs); |
| 139 | 149 | |
| 140 | 150 | return arfs_disable(fs); |
| @@ -1036,7 +1036,23 @@ static int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, int next_s · 1035 unmodified lines | ||
| 1036 | 1036 | return err; |
| 1037 | 1037 | } |
| 1038 | 1038 | |
| 1039 | −static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state) | |
| 1039 | +static void mlx5e_flush_rq_cq(struct mlx5e_rq *rq) | |
| 1040 | +{ | |
| 1041 | + struct mlx5_cqwq *cqwq = &rq->cq.wq; | |
| 1042 | + struct mlx5_cqe64 *cqe; | |
| 1043 | + | |
| 1044 | + if (test_bit(MLX5E_RQ_STATE_MINI_CQE_ENHANCED, &rq->state)) { | |
| 1045 | + while ((cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq))) | |
| 1046 | + mlx5_cqwq_pop(cqwq); | |
| 1047 | + } else { | |
| 1048 | + while ((cqe = mlx5_cqwq_get_cqe(cqwq))) | |
| 1049 | + mlx5_cqwq_pop(cqwq); | |
| 1050 | + } | |
| 1051 | + | |
| 1052 | + mlx5_cqwq_update_db_record(cqwq); | |
| 1053 | +} | |
| 1054 | + | |
| 1055 | +int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state) | |
| 1040 | 1056 | { |
| 1041 | 1057 | struct net_device *dev = rq->netdev; |
| 1042 | 1058 | int err; |
| @@ -1046,6 +1062,10 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state) · 3 unmodified lines | ||
| 1046 | 1062 | netdev_err(dev, "Failed to move rq 0x%x to reset\n", rq->rqn); |
| 1047 | 1063 | return err; |
| 1048 | 1064 | } |
| 1065 | + | |
| 1066 | + mlx5e_free_rx_descs(rq); | |
| 1067 | + mlx5e_flush_rq_cq(rq); | |
| 1068 | + | |
| 1049 | 1069 | err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY); |
| 1050 | 1070 | if (err) { |
| 1051 | 1071 | netdev_err(dev, "Failed to move rq 0x%x to ready\n", rq->rqn); |
| @@ -1055,13 +1075,6 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state) · 3 unmodified lines | ||
| 1055 | 1075 | return 0; |
| 1056 | 1076 | } |
| 1057 | 1077 | |
| 1058 | −int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state) | |
| 1059 | −{ | |
| 1060 | − mlx5e_free_rx_descs(rq); | |
| 1061 | − | |
| 1062 | − return mlx5e_rq_to_ready(rq, curr_state); | |
| 1063 | −} | |
| 1064 | − | |
| 1065 | 1078 | static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd) |
| 1066 | 1079 | { |
| 1067 | 1080 | struct mlx5_core_dev *mdev = rq->mdev; |
| @@ -5253,6 +5266,7 @@ void mlx5e_destroy_q_counters(struct mlx5e_priv *priv) · 4185 unmodified lines | ||
| 5253 | 5266 | static int mlx5e_nic_init(struct mlx5_core_dev *mdev, |
| 5254 | 5267 | struct net_device *netdev) |
| 5255 | 5268 | { |
| 5269 | + const bool take_rtnl = netdev->reg_state == NETREG_REGISTERED; | |
| 5256 | 5270 | struct mlx5e_priv *priv = netdev_priv(netdev); |
| 5257 | 5271 | struct mlx5e_flow_steering *fs; |
| 5258 | 5272 | int err; |
| @@ -5281,9 +5295,19 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev, · 22 unmodified lines | ||
| 5281 | 5295 | mlx5_core_err(mdev, "TLS initialization failed, %d\n", err); |
| 5282 | 5296 | |
| 5283 | 5297 | mlx5e_health_create_reporters(priv); |
| 5298 | + | |
| 5299 | + /* If netdev is already registered (e.g. move from uplink to nic profile), | |
| 5300 | + * RTNL lock must be held before triggering netdev notifiers. | |
| 5301 | + */ | |
| 5302 | + if (take_rtnl) | |
| 5303 | + rtnl_lock(); | |
| 5304 | + | |
| 5284 | 5305 | /* update XDP supported features */ |
| 5285 | 5306 | mlx5e_set_xdp_feature(netdev); |
| 5286 | 5307 | |
| 5308 | + if (take_rtnl) | |
| 5309 | + rtnl_unlock(); | |
| 5310 | + | |
| 5287 | 5311 | return 0; |
| 5288 | 5312 | } |
| 5289 | 5313 | |
| @@ -1012,7 +1012,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv) · 1011 unmodified lines | ||
| 1012 | 1012 | err = mlx5e_open_drop_rq(priv, &priv->drop_rq); |
| 1013 | 1013 | if (err) { |
| 1014 | 1014 | mlx5_core_err(mdev, "open drop rq failed, %d\n", err); |
| 1015 | − return err; | |
| 1015 | + goto err_rx_res_free; | |
| 1016 | 1016 | } |
| 1017 | 1017 | |
| 1018 | 1018 | err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, |
| @@ -1046,6 +1046,7 @@ err_destroy_rx_res: · 27 unmodified lines | ||
| 1046 | 1046 | mlx5e_rx_res_destroy(priv->rx_res); |
| 1047 | 1047 | err_close_drop_rq: |
| 1048 | 1048 | mlx5e_close_drop_rq(&priv->drop_rq); |
| 1049 | +err_rx_res_free: | |
| 1049 | 1050 | mlx5e_rx_res_free(priv->rx_res); |
| 1050 | 1051 | priv->rx_res = NULL; |
| 1051 | 1052 | err_free_fs: |
| @@ -1159,6 +1160,10 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) · 107 unmodified lines | ||
| 1159 | 1160 | return err; |
| 1160 | 1161 | } |
| 1161 | 1162 | |
| 1163 | + err = mlx5e_rep_neigh_init(rpriv); | |
| 1164 | + if (err) | |
| 1165 | + goto err_neigh_init; | |
| 1166 | + | |
| 1162 | 1167 | if (rpriv->rep->vport == MLX5_VPORT_UPLINK) { |
| 1163 | 1168 | err = mlx5e_init_uplink_rep_tx(rpriv); |
| 1164 | 1169 | if (err) |
| @@ -1175,6 +1180,8 @@ err_ht_init: · 10 unmodified lines | ||
| 1175 | 1180 | if (rpriv->rep->vport == MLX5_VPORT_UPLINK) |
| 1176 | 1181 | mlx5e_cleanup_uplink_rep_tx(rpriv); |
| 1177 | 1182 | err_init_tx: |
| 1183 | + mlx5e_rep_neigh_cleanup(rpriv); | |
| 1184 | +err_neigh_init: | |
| 1178 | 1185 | mlx5e_destroy_tises(priv); |
| 1179 | 1186 | return err; |
| 1180 | 1187 | } |
| @@ -1188,22 +1195,17 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv) · 7 unmodified lines | ||
| 1188 | 1195 | if (rpriv->rep->vport == MLX5_VPORT_UPLINK) |
| 1189 | 1196 | mlx5e_cleanup_uplink_rep_tx(rpriv); |
| 1190 | 1197 | |
| 1198 | + mlx5e_rep_neigh_cleanup(rpriv); | |
| 1191 | 1199 | mlx5e_destroy_tises(priv); |
| 1192 | 1200 | } |
| 1193 | 1201 | |
| 1194 | 1202 | static void mlx5e_rep_enable(struct mlx5e_priv *priv) |
| 1195 | 1203 | { |
| 1196 | − struct mlx5e_rep_priv *rpriv = priv->ppriv; | |
| 1197 | − | |
| 1198 | 1204 | mlx5e_set_netdev_mtu_boundaries(priv); |
| 1199 | − mlx5e_rep_neigh_init(rpriv); | |
| 1200 | 1205 | } |
| 1201 | 1206 | |
| 1202 | 1207 | static void mlx5e_rep_disable(struct mlx5e_priv *priv) |
| 1203 | 1208 | { |
| 1204 | − struct mlx5e_rep_priv *rpriv = priv->ppriv; | |
| 1205 | − | |
| 1206 | − mlx5e_rep_neigh_cleanup(rpriv); | |
| 1207 | 1209 | } |
| 1208 | 1210 | |
| 1209 | 1211 | static int mlx5e_update_rep_rx(struct mlx5e_priv *priv) |
| @@ -1253,7 +1255,6 @@ static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event · 43 unmodified lines | ||
| 1253 | 1255 | |
| 1254 | 1256 | static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) |
| 1255 | 1257 | { |
| 1256 | − struct mlx5e_rep_priv *rpriv = priv->ppriv; | |
| 1257 | 1258 | struct net_device *netdev = priv->netdev; |
| 1258 | 1259 | struct mlx5_core_dev *mdev = priv->mdev; |
| 1259 | 1260 | u16 max_mtu; |
| @@ -1275,7 +1276,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) · 15 unmodified lines | ||
| 1275 | 1276 | mlx5_notifier_register(mdev, &priv->events_nb); |
| 1276 | 1277 | mlx5e_dcbnl_initialize(priv); |
| 1277 | 1278 | mlx5e_dcbnl_init_app(priv); |
| 1278 | − mlx5e_rep_neigh_init(rpriv); | |
| 1279 | 1279 | mlx5e_rep_bridge_init(priv); |
| 1280 | 1280 | |
| 1281 | 1281 | netdev->wanted_features |= NETIF_F_HW_TC; |
| @@ -1290,7 +1290,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) · 8 unmodified lines | ||
| 1290 | 1290 | |
| 1291 | 1291 | static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) |
| 1292 | 1292 | { |
| 1293 | − struct mlx5e_rep_priv *rpriv = priv->ppriv; | |
| 1294 | 1293 | struct mlx5_core_dev *mdev = priv->mdev; |
| 1295 | 1294 | |
| 1296 | 1295 | rtnl_lock(); |
| @@ -1300,7 +1299,6 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) · 3 unmodified lines | ||
| 1300 | 1299 | rtnl_unlock(); |
| 1301 | 1300 | |
| 1302 | 1301 | mlx5e_rep_bridge_cleanup(priv); |
| 1303 | − mlx5e_rep_neigh_cleanup(rpriv); | |
| 1304 | 1302 | mlx5e_dcbnl_delete_app(priv); |
| 1305 | 1303 | mlx5_notifier_unregister(mdev, &priv->events_nb); |
| 1306 | 1304 | mlx5e_rep_tc_disable(priv); |
| @@ -1725,6 +1725,19 @@ verify_attr_actions(u32 actions, struct netlink_ext_ack *extack) · 1724 unmodified lines | ||
| 1725 | 1725 | return 0; |
| 1726 | 1726 | } |
| 1727 | 1727 | |
| 1728 | +static bool | |
| 1729 | +has_encap_dests(struct mlx5_flow_attr *attr) | |
| 1730 | +{ | |
| 1731 | + struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; | |
| 1732 | + int out_index; | |
| 1733 | + | |
| 1734 | + for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) | |
| 1735 | + if (esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP) | |
| 1736 | + return true; | |
| 1737 | + | |
| 1738 | + return false; | |
| 1739 | +} | |
| 1740 | + | |
| 1728 | 1741 | static int |
| 1729 | 1742 | post_process_attr(struct mlx5e_tc_flow *flow, |
| 1730 | 1743 | struct mlx5_flow_attr *attr, |
| @@ -1737,9 +1750,11 @@ post_process_attr(struct mlx5e_tc_flow *flow, · 6 unmodified lines | ||
| 1737 | 1750 | if (err) |
| 1738 | 1751 | goto err_out; |
| 1739 | 1752 | |
| 1740 | − err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun); | |
| 1741 | − if (err) | |
| 1742 | − goto err_out; | |
| 1753 | + if (mlx5e_is_eswitch_flow(flow) && has_encap_dests(attr)) { | |
| 1754 | + err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun); | |
| 1755 | + if (err) | |
| 1756 | + goto err_out; | |
| 1757 | + } | |
| 1743 | 1758 | |
| 1744 | 1759 | if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { |
| 1745 | 1760 | err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr); |
| @@ -1928,9 +1943,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, · 182 unmodified lines | ||
| 1928 | 1943 | { |
| 1929 | 1944 | struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; |
| 1930 | 1945 | struct mlx5_flow_attr *attr = flow->attr; |
| 1931 | − struct mlx5_esw_flow_attr *esw_attr; | |
| 1932 | 1946 | |
| 1933 | − esw_attr = attr->esw_attr; | |
| 1934 | 1947 | mlx5e_put_flow_tunnel_id(flow); |
| 1935 | 1948 | |
| 1936 | 1949 | remove_unready_flow(flow); |
| @@ -1951,12 +1964,6 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, · 14 unmodified lines | ||
| 1951 | 1964 | |
| 1952 | 1965 | mlx5_tc_ct_match_del(get_ct_priv(priv), &flow->attr->ct_attr); |
| 1953 | 1966 | |
| 1954 | − if (esw_attr->int_port) | |
| 1955 | − mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->int_port); | |
| 1956 | − | |
| 1957 | − if (esw_attr->dest_int_port) | |
| 1958 | − mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(priv), esw_attr->dest_int_port); | |
| 1959 | − | |
| 1960 | 1967 | if (flow_flag_test(flow, L3_TO_L2_DECAP)) |
| 1961 | 1968 | mlx5e_detach_decap(priv, flow); |
| 1962 | 1969 | |
| @@ -4253,6 +4260,7 @@ static void · 2290 unmodified lines | ||
| 4253 | 4260 | mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr) |
| 4254 | 4261 | { |
| 4255 | 4262 | struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow); |
| 4263 | + struct mlx5_esw_flow_attr *esw_attr; | |
| 4256 | 4264 | |
| 4257 | 4265 | if (!attr) |
| 4258 | 4266 | return; |
| @@ -4270,6 +4278,18 @@ mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *a · 11 unmodified lines | ||
| 4270 | 4278 | mlx5e_tc_detach_mod_hdr(flow->priv, flow, attr); |
| 4271 | 4279 | } |
| 4272 | 4280 | |
| 4281 | + if (mlx5e_is_eswitch_flow(flow)) { | |
| 4282 | + esw_attr = attr->esw_attr; | |
| 4283 | + | |
| 4284 | + if (esw_attr->int_port) | |
| 4285 | + mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv), | |
| 4286 | + esw_attr->int_port); | |
| 4287 | + | |
| 4288 | + if (esw_attr->dest_int_port) | |
| 4289 | + mlx5e_tc_int_port_put(mlx5e_get_int_port_priv(flow->priv), | |
| 4290 | + esw_attr->dest_int_port); | |
| 4291 | + } | |
| 4292 | + | |
| 4273 | 4293 | mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr); |
| 4274 | 4294 | |
| 4275 | 4295 | free_branch_attr(flow, attr->branch_true); |
| @@ -64,7 +64,7 @@ void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_ · 63 unmodified lines | ||
| 64 | 64 | |
| 65 | 65 | bridge->debugfs_dir = debugfs_create_dir(br_netdev->name, |
| 66 | 66 | bridge->br_offloads->debugfs_root); |
| 67 | − debugfs_create_file("fdb", 0444, bridge->debugfs_dir, bridge, | |
| 67 | + debugfs_create_file("fdb", 0400, bridge->debugfs_dir, bridge, | |
| 68 | 68 | &mlx5_esw_bridge_debugfs_fops); |
| 69 | 69 | } |
| 70 | 70 | |
| @@ -60,7 +60,7 @@ static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 · 59 unmodified lines | ||
| 60 | 60 | } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) { |
| 61 | 61 | memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len); |
| 62 | 62 | dl_port->attrs.switch_id.id_len = ppid.id_len; |
| 63 | − devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum, | |
| 63 | + devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum, | |
| 64 | 64 | vport_num - 1, false); |
| 65 | 65 | } |
| 66 | 66 | return dl_port; |
| @@ -1436,7 +1436,6 @@ esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb) · 1435 unmodified lines | ||
| 1436 | 1436 | |
| 1437 | 1437 | esw_init_chains_offload_flags(esw, &attr.flags); |
| 1438 | 1438 | attr.ns = MLX5_FLOW_NAMESPACE_FDB; |
| 1439 | − attr.fs_base_prio = FDB_TC_OFFLOAD; | |
| 1440 | 1439 | attr.max_grp_num = esw->params.large_group_num; |
| 1441 | 1440 | attr.default_ft = miss_fdb; |
| 1442 | 1441 | attr.mapping = esw->offloads.reg_c0_obj_pool; |
| @@ -2779,9 +2778,9 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw, · 1336 unmodified lines | ||
| 2779 | 2778 | struct mlx5_eswitch *peer_esw, |
| 2780 | 2779 | bool pair) |
| 2781 | 2780 | { |
| 2782 | − u8 peer_idx = mlx5_get_dev_index(peer_esw->dev); | |
| 2781 | + u16 peer_vhca_id = MLX5_CAP_GEN(peer_esw->dev, vhca_id); | |
| 2782 | + u16 vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id); | |
| 2783 | 2783 | struct mlx5_flow_root_namespace *peer_ns; |
| 2784 | − u8 idx = mlx5_get_dev_index(esw->dev); | |
| 2785 | 2784 | struct mlx5_flow_root_namespace *ns; |
| 2786 | 2785 | int err; |
| 2787 | 2786 | |
| @@ -2789,18 +2788,18 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw, · 1 unmodified line | ||
| 2789 | 2788 | ns = esw->dev->priv.steering->fdb_root_ns; |
| 2790 | 2789 | |
| 2791 | 2790 | if (pair) { |
| 2792 | − err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_idx); | |
| 2791 | + err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_vhca_id); | |
| 2793 | 2792 | if (err) |
| 2794 | 2793 | return err; |
| 2795 | 2794 | |
| 2796 | − err = mlx5_flow_namespace_set_peer(peer_ns, ns, idx); | |
| 2795 | + err = mlx5_flow_namespace_set_peer(peer_ns, ns, vhca_id); | |
| 2797 | 2796 | if (err) { |
| 2798 | − mlx5_flow_namespace_set_peer(ns, NULL, peer_idx); | |
| 2797 | + mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id); | |
| 2799 | 2798 | return err; |
| 2800 | 2799 | } |
| 2801 | 2800 | } else { |
| 2802 | − mlx5_flow_namespace_set_peer(ns, NULL, peer_idx); | |
| 2803 | − mlx5_flow_namespace_set_peer(peer_ns, NULL, idx); | |
| 2801 | + mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id); | |
| 2802 | + mlx5_flow_namespace_set_peer(peer_ns, NULL, vhca_id); | |
| 2804 | 2803 | } |
| 2805 | 2804 | |
| 2806 | 2805 | return 0; |
| @@ -4196,7 +4195,7 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, · 1389 unmodified lines | ||
| 4196 | 4195 | } |
| 4197 | 4196 | |
| 4198 | 4197 | hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); |
| 4199 | − MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, 1); | |
| 4198 | + MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, enable); | |
| 4200 | 4199 | |
| 4201 | 4200 | err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport, |
| 4202 | 4201 | MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE2); |
| @@ -140,7 +140,7 @@ static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace · 139 unmodified lines | ||
| 140 | 140 | |
| 141 | 141 | static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns, |
| 142 | 142 | struct mlx5_flow_root_namespace *peer_ns, |
| 143 | − u8 peer_idx) | |
| 143 | + u16 peer_vhca_id) | |
| 144 | 144 | { |
| 145 | 145 | return 0; |
| 146 | 146 | } |
| @@ -94,7 +94,7 @@ struct mlx5_flow_cmds { · 93 unmodified lines | ||
| 94 | 94 | |
| 95 | 95 | int (*set_peer)(struct mlx5_flow_root_namespace *ns, |
| 96 | 96 | struct mlx5_flow_root_namespace *peer_ns, |
| 97 | − u8 peer_idx); | |
| 97 | + u16 peer_vhca_id); | |
| 98 | 98 | |
| 99 | 99 | int (*create_ns)(struct mlx5_flow_root_namespace *ns); |
| 100 | 100 | int (*destroy_ns)(struct mlx5_flow_root_namespace *ns); |
| @@ -889,7 +889,7 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node *root, · 888 unmodified lines | ||
| 889 | 889 | struct fs_node *iter = list_entry(start, struct fs_node, list); |
| 890 | 890 | struct mlx5_flow_table *ft = NULL; |
| 891 | 891 | |
| 892 | − if (!root || root->type == FS_TYPE_PRIO_CHAINS) | |
| 892 | + if (!root) | |
| 893 | 893 | return NULL; |
| 894 | 894 | |
| 895 | 895 | list_for_each_advance_continue(iter, &root->children, reverse) { |
| @@ -905,20 +905,42 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node *root, · 9 unmodified lines | ||
| 905 | 905 | return ft; |
| 906 | 906 | } |
| 907 | 907 | |
| 908 | −/* If reverse is false then return the first flow table in next priority of | |
| 909 | − * prio in the tree, else return the last flow table in the previous priority | |
| 910 | − * of prio in the tree. | |
| 908 | +static struct fs_node *find_prio_chains_parent(struct fs_node *parent, | |
| 909 | + struct fs_node **child) | |
| 910 | +{ | |
| 911 | + struct fs_node *node = NULL; | |
| 912 | + | |
| 913 | + while (parent && parent->type != FS_TYPE_PRIO_CHAINS) { | |
| 914 | + node = parent; | |
| 915 | + parent = parent->parent; | |
| 916 | + } | |
| 917 | + | |
| 918 | + if (child) | |
| 919 | + *child = node; | |
| 920 | + | |
| 921 | + return parent; | |
| 922 | +} | |
| 923 | + | |
| 924 | +/* If reverse is false then return the first flow table next to the passed node | |
| 925 | + * in the tree, else return the last flow table before the node in the tree. | |
| 926 | + * If skip is true, skip the flow tables in the same prio_chains prio. | |
| 911 | 927 | */ |
| 912 | −static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse) | |
| 928 | +static struct mlx5_flow_table *find_closest_ft(struct fs_node *node, bool reverse, | |
| 929 | + bool skip) | |
| 913 | 930 | { |
| 931 | + struct fs_node *prio_chains_parent = NULL; | |
| 914 | 932 | struct mlx5_flow_table *ft = NULL; |
| 915 | 933 | struct fs_node *curr_node; |
| 916 | 934 | struct fs_node *parent; |
| 917 | 935 | |
| 918 | − parent = prio->node.parent; | |
| 919 | − curr_node = &prio->node; | |
| 936 | + if (skip) | |
| 937 | + prio_chains_parent = find_prio_chains_parent(node, NULL); | |
| 938 | + parent = node->parent; | |
| 939 | + curr_node = node; | |
| 920 | 940 | while (!ft && parent) { |
| 921 | − ft = find_closest_ft_recursive(parent, &curr_node->list, reverse); | |
| 941 | + if (parent != prio_chains_parent) | |
| 942 | + ft = find_closest_ft_recursive(parent, &curr_node->list, | |
| 943 | + reverse); | |
| 922 | 944 | curr_node = parent; |
| 923 | 945 | parent = curr_node->parent; |
| 924 | 946 | } |
| @@ -926,15 +948,15 @@ static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool revers · 1 unmodified line | ||
| 926 | 948 | } |
| 927 | 949 | |
| 928 | 950 | /* Assuming all the tree is locked by mutex chain lock */ |
| 929 | −static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio) | |
| 951 | +static struct mlx5_flow_table *find_next_chained_ft(struct fs_node *node) | |
| 930 | 952 | { |
| 931 | − return find_closest_ft(prio, false); | |
| 953 | + return find_closest_ft(node, false, true); | |
| 932 | 954 | } |
| 933 | 955 | |
| 934 | 956 | /* Assuming all the tree is locked by mutex chain lock */ |
| 935 | −static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio) | |
| 957 | +static struct mlx5_flow_table *find_prev_chained_ft(struct fs_node *node) | |
| 936 | 958 | { |
| 937 | − return find_closest_ft(prio, true); | |
| 959 | + return find_closest_ft(node, true, true); | |
| 938 | 960 | } |
| 939 | 961 | |
| 940 | 962 | static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft, |
| @@ -946,7 +968,7 @@ static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft, · 5 unmodified lines | ||
| 946 | 968 | next_ns = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS; |
| 947 | 969 | fs_get_obj(prio, next_ns ? ft->ns->node.parent : ft->node.parent); |
| 948 | 970 | |
| 949 | − return find_next_chained_ft(prio); | |
| 971 | + return find_next_chained_ft(&prio->node); | |
| 950 | 972 | } |
| 951 | 973 | |
| 952 | 974 | static int connect_fts_in_prio(struct mlx5_core_dev *dev, |
| @@ -970,21 +992,55 @@ static int connect_fts_in_prio(struct mlx5_core_dev *dev, · 17 unmodified lines | ||
| 970 | 992 | return 0; |
| 971 | 993 | } |
| 972 | 994 | |
| 995 | +static struct mlx5_flow_table *find_closet_ft_prio_chains(struct fs_node *node, | |
| 996 | + struct fs_node *parent, | |
| 997 | + struct fs_node **child, | |
| 998 | + bool reverse) | |
| 999 | +{ | |
| 1000 | + struct mlx5_flow_table *ft; | |
| 1001 | + | |
| 1002 | + ft = find_closest_ft(node, reverse, false); | |
| 1003 | + | |
| 1004 | + if (ft && parent == find_prio_chains_parent(&ft->node, child)) | |
| 1005 | + return ft; | |
| 1006 | + | |
| 1007 | + return NULL; | |
| 1008 | +} | |
| 1009 | + | |
| 973 | 1010 | /* Connect flow tables from previous priority of prio to ft */ |
| 974 | 1011 | static int connect_prev_fts(struct mlx5_core_dev *dev, |
| 975 | 1012 | struct mlx5_flow_table *ft, |
| 976 | 1013 | struct fs_prio *prio) |
| 977 | 1014 | { |
| 1015 | + struct fs_node *prio_parent, *parent = NULL, *child, *node; | |
| 978 | 1016 | struct mlx5_flow_table *prev_ft; |
| 1017 | + int err = 0; | |
| 1018 | + | |
| 1019 | + prio_parent = find_prio_chains_parent(&prio->node, &child); | |
| 1020 | + | |
| 1021 | + /* return directly if not under the first sub ns of prio_chains prio */ | |
| 1022 | + if (prio_parent && !list_is_first(&child->list, &prio_parent->children)) | |
| 1023 | + return 0; | |
| 979 | 1024 | |
| 980 | − prev_ft = find_prev_chained_ft(prio); | |
| 981 | − if (prev_ft) { | |
| 1025 | + prev_ft = find_prev_chained_ft(&prio->node); | |
| 1026 | + while (prev_ft) { | |
| 982 | 1027 | struct fs_prio *prev_prio; |
| 983 | 1028 | |
| 984 | 1029 | fs_get_obj(prev_prio, prev_ft->node.parent); |
| 985 | − return connect_fts_in_prio(dev, prev_prio, ft); | |
| 1030 | + err = connect_fts_in_prio(dev, prev_prio, ft); | |
| 1031 | + if (err) | |
| 1032 | + break; | |
| 1033 | + | |
| 1034 | + if (!parent) { | |
| 1035 | + parent = find_prio_chains_parent(&prev_prio->node, &child); | |
| 1036 | + if (!parent) | |
| 1037 | + break; | |
| 1038 | + } | |
| 1039 | + | |
| 1040 | + node = child; | |
| 1041 | + prev_ft = find_closet_ft_prio_chains(node, parent, &child, true); | |
| 986 | 1042 | } |
| 987 | − return 0; | |
| 1043 | + return err; | |
| 988 | 1044 | } |
| 989 | 1045 | |
| 990 | 1046 | static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio |
| @@ -1123,7 +1179,7 @@ static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table · 132 unmodified lines | ||
| 1123 | 1179 | if (err) |
| 1124 | 1180 | return err; |
| 1125 | 1181 | |
| 1126 | − next_ft = first_ft ? first_ft : find_next_chained_ft(prio); | |
| 1182 | + next_ft = first_ft ? first_ft : find_next_chained_ft(&prio->node); | |
| 1127 | 1183 | err = connect_fwd_rules(dev, ft, next_ft); |
| 1128 | 1184 | if (err) |
| 1129 | 1185 | return err; |
| @@ -1198,7 +1254,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa · 68 unmodified lines | ||
| 1198 | 1254 | |
| 1199 | 1255 | tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table); |
| 1200 | 1256 | next_ft = unmanaged ? ft_attr->next_ft : |
| 1201 | − find_next_chained_ft(fs_prio); | |
| 1257 | + find_next_chained_ft(&fs_prio->node); | |
| 1202 | 1258 | ft->def_miss_action = ns->def_miss_action; |
| 1203 | 1259 | ft->ns = ns; |
| 1204 | 1260 | err = root->cmds->create_flow_table(root, ft, ft_attr, next_ft); |
| @@ -2195,13 +2251,20 @@ EXPORT_SYMBOL(mlx5_del_flow_rules); · 990 unmodified lines | ||
| 2195 | 2251 | /* Assuming prio->node.children(flow tables) is sorted by level */ |
| 2196 | 2252 | static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft) |
| 2197 | 2253 | { |
| 2254 | + struct fs_node *prio_parent, *child; | |
| 2198 | 2255 | struct fs_prio *prio; |
| 2199 | 2256 | |
| 2200 | 2257 | fs_get_obj(prio, ft->node.parent); |
| 2201 | 2258 | |
| 2202 | 2259 | if (!list_is_last(&ft->node.list, &prio->node.children)) |
| 2203 | 2260 | return list_next_entry(ft, node.list); |
| 2204 | − return find_next_chained_ft(prio); | |
| 2261 | + | |
| 2262 | + prio_parent = find_prio_chains_parent(&prio->node, &child); | |
| 2263 | + | |
| 2264 | + if (prio_parent && list_is_first(&child->list, &prio_parent->children)) | |
| 2265 | + return find_closest_ft(&prio->node, false, false); | |
| 2266 | + | |
| 2267 | + return find_next_chained_ft(&prio->node); | |
| 2205 | 2268 | } |
| 2206 | 2269 | |
| 2207 | 2270 | static int update_root_ft_destroy(struct mlx5_flow_table *ft) |
| @@ -3621,7 +3684,7 @@ void mlx5_destroy_match_definer(struct mlx5_core_dev *dev, · 1413 unmodified lines | ||
| 3621 | 3684 | |
| 3622 | 3685 | int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, |
| 3623 | 3686 | struct mlx5_flow_root_namespace *peer_ns, |
| 3624 | − u8 peer_idx) | |
| 3687 | + u16 peer_vhca_id) | |
| 3625 | 3688 | { |
| 3626 | 3689 | if (peer_ns && ns->mode != peer_ns->mode) { |
| 3627 | 3690 | mlx5_core_err(ns->dev, |
| @@ -3629,7 +3692,7 @@ int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, · 1 unmodified line | ||
| 3629 | 3692 | return -EINVAL; |
| 3630 | 3693 | } |
| 3631 | 3694 | |
| 3632 | − return ns->cmds->set_peer(ns, peer_ns, peer_idx); | |
| 3695 | + return ns->cmds->set_peer(ns, peer_ns, peer_vhca_id); | |
| 3633 | 3696 | } |
| 3634 | 3697 | |
| 3635 | 3698 | /* This function should be called only at init stage of the namespace. |
| @@ -303,7 +303,7 @@ const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void); · 302 unmodified lines | ||
| 303 | 303 | |
| 304 | 304 | int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, |
| 305 | 305 | struct mlx5_flow_root_namespace *peer_ns, |
| 306 | − u8 peer_idx); | |
| 306 | + u16 peer_vhca_id); | |
| 307 | 307 | |
| 308 | 308 | int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns, |
| 309 | 309 | enum mlx5_flow_steering_mode mode); |
| @@ -574,7 +574,7 @@ static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev, · 573 unmodified lines | ||
| 574 | 574 | for (i = 0; i < ldev->ports; i++) { |
| 575 | 575 | for (j = 0; j < ldev->buckets; j++) { |
| 576 | 576 | idx = i * ldev->buckets + j; |
| 577 | − if (ldev->v2p_map[i] == ports[i]) | |
| 577 | + if (ldev->v2p_map[idx] == ports[idx]) | |
| 578 | 578 | continue; |
| 579 | 579 | |
| 580 | 580 | dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev, |
| @@ -227,10 +227,15 @@ static void mlx5_timestamp_overflow(struct work_struct *work) · 226 unmodified lines | ||
| 227 | 227 | clock = container_of(timer, struct mlx5_clock, timer); |
| 228 | 228 | mdev = container_of(clock, struct mlx5_core_dev, clock); |
| 229 | 229 | |
| 230 | + if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) | |
| 231 | + goto out; | |
| 232 | + | |
| 230 | 233 | write_seqlock_irqsave(&clock->lock, flags); |
| 231 | 234 | timecounter_read(&timer->tc); |
| 232 | 235 | mlx5_update_clock_info_page(mdev); |
| 233 | 236 | write_sequnlock_irqrestore(&clock->lock, flags); |
| 237 | + | |
| 238 | +out: | |
| 234 | 239 | schedule_delayed_work(&timer->overflow_work, timer->overflow_period); |
| 235 | 240 | } |
| 236 | 241 | |
| @@ -178,7 +178,7 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains, · 177 unmodified lines | ||
| 178 | 178 | if (!mlx5_chains_ignore_flow_level_supported(chains) || |
| 179 | 179 | (chain == 0 && prio == 1 && level == 0)) { |
| 180 | 180 | ft_attr.level = chains->fs_base_level; |
| 181 | − ft_attr.prio = chains->fs_base_prio; | |
| 181 | + ft_attr.prio = chains->fs_base_prio + prio - 1; | |
| 182 | 182 | ns = (chains->ns == MLX5_FLOW_NAMESPACE_FDB) ? |
| 183 | 183 | mlx5_get_fdb_sub_ns(chains->dev, chain) : |
| 184 | 184 | mlx5_get_flow_namespace(chains->dev, chains->ns); |
| @@ -1506,6 +1506,7 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev) · 1505 unmodified lines | ||
| 1506 | 1506 | if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { |
| 1507 | 1507 | mlx5_core_warn(dev, "%s: interface is down, NOP\n", |
| 1508 | 1508 | __func__); |
| 1509 | + mlx5_devlink_params_unregister(priv_to_devlink(dev)); | |
| 1509 | 1510 | mlx5_cleanup_once(dev); |
| 1510 | 1511 | goto out; |
| 1511 | 1512 | } |
| @@ -1988,7 +1989,7 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev, · 476 unmodified lines | ||
| 1988 | 1989 | |
| 1989 | 1990 | mlx5_enter_error_state(dev, false); |
| 1990 | 1991 | mlx5_error_sw_reset(dev); |
| 1991 | − mlx5_unload_one(dev, true); | |
| 1992 | + mlx5_unload_one(dev, false); | |
| 1992 | 1993 | mlx5_drain_health_wq(dev); |
| 1993 | 1994 | mlx5_pci_disable_device(dev); |
| 1994 | 1995 | |
| @@ -361,7 +361,7 @@ static inline bool mlx5_core_is_ec_vf_vport(const struct mlx5_core_dev *dev, u16 · 360 unmodified lines | ||
| 361 | 361 | |
| 362 | 362 | static inline int mlx5_vport_to_func_id(const struct mlx5_core_dev *dev, u16 vport, bool ec_vf_func) |
| 363 | 363 | { |
| 364 | − return ec_vf_func ? vport - mlx5_core_ec_vf_vport_base(dev) | |
| 364 | + return ec_vf_func ? vport - mlx5_core_ec_vf_vport_base(dev) + 1 | |
| 365 | 365 | : vport; |
| 366 | 366 | } |
| 367 | 367 | |
| @@ -285,8 +285,7 @@ static u16 mlx5_get_max_vfs(struct mlx5_core_dev *dev) · 284 unmodified lines | ||
| 285 | 285 | host_total_vfs = MLX5_GET(query_esw_functions_out, out, |
| 286 | 286 | host_params_context.host_total_vfs); |
| 287 | 287 | kvfree(out); |
| 288 | − if (host_total_vfs) | |
| 289 | − return host_total_vfs; | |
| 288 | + return host_total_vfs; | |
| 290 | 289 | } |
| 291 | 290 | |
| 292 | 291 | done: |
| @@ -2079,7 +2079,7 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn, · 2078 unmodified lines | ||
| 2079 | 2079 | |
| 2080 | 2080 | peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) && |
| 2081 | 2081 | (vhca_id != dmn->info.caps.gvmi); |
| 2082 | − vport_dmn = peer_vport ? dmn->peer_dmn[vhca_id] : dmn; | |
| 2082 | + vport_dmn = peer_vport ? xa_load(&dmn->peer_dmn_xa, vhca_id) : dmn; | |
| 2083 | 2083 | if (!vport_dmn) { |
| 2084 | 2084 | mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n"); |
| 2085 | 2085 | return NULL; |
| @@ -564,11 +564,12 @@ int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev, · 563 unmodified lines | ||
| 564 | 564 | |
| 565 | 565 | err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out)); |
| 566 | 566 | if (err) |
| 567 | − return err; | |
| 567 | + goto err_free_in; | |
| 568 | 568 | |
| 569 | 569 | *reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id); |
| 570 | − kvfree(in); | |
| 571 | 570 | |
| 571 | +err_free_in: | |
| 572 | + kvfree(in); | |
| 572 | 573 | return err; |
| 573 | 574 | } |
| 574 | 575 | |
| @@ -475,6 +475,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type) · 474 unmodified lines | ||
| 475 | 475 | mutex_init(&dmn->info.rx.mutex); |
| 476 | 476 | mutex_init(&dmn->info.tx.mutex); |
| 477 | 477 | xa_init(&dmn->definers_xa); |
| 478 | + xa_init(&dmn->peer_dmn_xa); | |
| 478 | 479 | |
| 479 | 480 | if (dr_domain_caps_init(mdev, dmn)) { |
| 480 | 481 | mlx5dr_err(dmn, "Failed init domain, no caps\n"); |
| @@ -507,6 +508,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type) · 26 unmodified lines | ||
| 507 | 508 | uninit_caps: |
| 508 | 509 | dr_domain_caps_uninit(dmn); |
| 509 | 510 | def_xa_destroy: |
| 511 | + xa_destroy(&dmn->peer_dmn_xa); | |
| 510 | 512 | xa_destroy(&dmn->definers_xa); |
| 511 | 513 | kfree(dmn); |
| 512 | 514 | return NULL; |
| @@ -547,6 +549,7 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn) · 34 unmodified lines | ||
| 547 | 549 | dr_domain_uninit_csum_recalc_fts(dmn); |
| 548 | 550 | dr_domain_uninit_resources(dmn); |
| 549 | 551 | dr_domain_caps_uninit(dmn); |
| 552 | + xa_destroy(&dmn->peer_dmn_xa); | |
| 550 | 553 | xa_destroy(&dmn->definers_xa); |
| 551 | 554 | mutex_destroy(&dmn->info.tx.mutex); |
| 552 | 555 | mutex_destroy(&dmn->info.rx.mutex); |
| @@ -556,17 +559,21 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn) · 3 unmodified lines | ||
| 556 | 559 | |
| 557 | 560 | void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, |
| 558 | 561 | struct mlx5dr_domain *peer_dmn, |
| 559 | − u8 peer_idx) | |
| 562 | + u16 peer_vhca_id) | |
| 560 | 563 | { |
| 564 | + struct mlx5dr_domain *peer; | |
| 565 | + | |
| 561 | 566 | mlx5dr_domain_lock(dmn); |
| 562 | 567 | |
| 563 | − if (dmn->peer_dmn[peer_idx]) | |
| 564 | − refcount_dec(&dmn->peer_dmn[peer_idx]->refcount); | |
| 568 | + peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id); | |
| 569 | + if (peer) | |
| 570 | + refcount_dec(&peer->refcount); | |
| 565 | 571 | |
| 566 | − dmn->peer_dmn[peer_idx] = peer_dmn; | |
| 572 | + WARN_ON(xa_err(xa_store(&dmn->peer_dmn_xa, peer_vhca_id, peer_dmn, GFP_KERNEL))); | |
| 567 | 573 | |
| 568 | − if (dmn->peer_dmn[peer_idx]) | |
| 569 | − refcount_inc(&dmn->peer_dmn[peer_idx]->refcount); | |
| 574 | + peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id); | |
| 575 | + if (peer) | |
| 576 | + refcount_inc(&peer->refcount); | |
| 570 | 577 | |
| 571 | 578 | mlx5dr_domain_unlock(dmn); |
| 572 | 579 | } |
| @@ -82,7 +82,7 @@ dr_ptrn_alloc_pattern(struct mlx5dr_ptrn_mgr *mgr, · 81 unmodified lines | ||
| 82 | 82 | u32 chunk_size; |
| 83 | 83 | u32 index; |
| 84 | 84 | |
| 85 | − chunk_size = ilog2(num_of_actions); | |
| 85 | + chunk_size = ilog2(roundup_pow_of_two(num_of_actions)); | |
| 86 | 86 | /* HW modify action index granularity is at least 64B */ |
| 87 | 87 | chunk_size = max_t(u32, chunk_size, DR_CHUNK_SIZE_8); |
| 88 | 88 | |
| @@ -1652,17 +1652,18 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, · 1651 unmodified lines | ||
| 1652 | 1652 | struct mlx5dr_domain *dmn = sb->dmn; |
| 1653 | 1653 | struct mlx5dr_domain *vport_dmn; |
| 1654 | 1654 | u8 *bit_mask = sb->bit_mask; |
| 1655 | + struct mlx5dr_domain *peer; | |
| 1655 | 1656 | bool source_gvmi_set; |
| 1656 | 1657 | |
| 1657 | 1658 | DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn); |
| 1658 | 1659 | |
| 1659 | 1660 | if (sb->vhca_id_valid) { |
| 1661 | + peer = xa_load(&dmn->peer_dmn_xa, id); | |
| 1660 | 1662 | /* Find port GVMI based on the eswitch_owner_vhca_id */ |
| 1661 | 1663 | if (id == dmn->info.caps.gvmi) |
| 1662 | 1664 | vport_dmn = dmn; |
| 1663 | − else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && | |
| 1664 | − (id == dmn->peer_dmn[id]->info.caps.gvmi)) | |
| 1665 | − vport_dmn = dmn->peer_dmn[id]; | |
| 1665 | + else if (peer && (id == peer->info.caps.gvmi)) | |
| 1666 | + vport_dmn = peer; | |
| 1666 | 1667 | else |
| 1667 | 1668 | return -EINVAL; |
| 1668 | 1669 | |
| @@ -1984,16 +1984,17 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, · 1983 unmodified lines | ||
| 1984 | 1984 | struct mlx5dr_domain *dmn = sb->dmn; |
| 1985 | 1985 | struct mlx5dr_domain *vport_dmn; |
| 1986 | 1986 | u8 *bit_mask = sb->bit_mask; |
| 1987 | + struct mlx5dr_domain *peer; | |
| 1987 | 1988 | |
| 1988 | 1989 | DR_STE_SET_TAG(src_gvmi_qp_v1, tag, source_qp, misc, source_sqn); |
| 1989 | 1990 | |
| 1990 | 1991 | if (sb->vhca_id_valid) { |
| 1992 | + peer = xa_load(&dmn->peer_dmn_xa, id); | |
| 1991 | 1993 | /* Find port GVMI based on the eswitch_owner_vhca_id */ |
| 1992 | 1994 | if (id == dmn->info.caps.gvmi) |
| 1993 | 1995 | vport_dmn = dmn; |
| 1994 | − else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && | |
| 1995 | − (id == dmn->peer_dmn[id]->info.caps.gvmi)) | |
| 1996 | − vport_dmn = dmn->peer_dmn[id]; | |
| 1996 | + else if (peer && (id == peer->info.caps.gvmi)) | |
| 1997 | + vport_dmn = peer; | |
| 1997 | 1998 | else |
| 1998 | 1999 | return -EINVAL; |
| 1999 | 2000 | |
| @@ -935,7 +935,6 @@ struct mlx5dr_domain_info { · 934 unmodified lines | ||
| 935 | 935 | }; |
| 936 | 936 | |
| 937 | 937 | struct mlx5dr_domain { |
| 938 | − struct mlx5dr_domain *peer_dmn[MLX5_MAX_PORTS]; | |
| 939 | 938 | struct mlx5_core_dev *mdev; |
| 940 | 939 | u32 pdn; |
| 941 | 940 | struct mlx5_uars_page *uar; |
| @@ -956,6 +955,7 @@ struct mlx5dr_domain { · 14 unmodified lines | ||
| 956 | 955 | struct list_head dbg_tbl_list; |
| 957 | 956 | struct mlx5dr_dbg_dump_info dump_info; |
| 958 | 957 | struct xarray definers_xa; |
| 958 | + struct xarray peer_dmn_xa; | |
| 959 | 959 | /* memory management statistics */ |
| 960 | 960 | u32 num_buddies[DR_ICM_TYPE_MAX]; |
| 961 | 961 | }; |
| @@ -781,14 +781,14 @@ restore_fte: · 780 unmodified lines | ||
| 781 | 781 | |
| 782 | 782 | static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns, |
| 783 | 783 | struct mlx5_flow_root_namespace *peer_ns, |
| 784 | − u8 peer_idx) | |
| 784 | + u16 peer_vhca_id) | |
| 785 | 785 | { |
| 786 | 786 | struct mlx5dr_domain *peer_domain = NULL; |
| 787 | 787 | |
| 788 | 788 | if (peer_ns) |
| 789 | 789 | peer_domain = peer_ns->fs_dr_domain.dr_domain; |
| 790 | 790 | mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain, |
| 791 | − peer_domain, peer_idx); | |
| 791 | + peer_domain, peer_vhca_id); | |
| 792 | 792 | return 0; |
| 793 | 793 | } |
| 794 | 794 | |
| @@ -49,7 +49,7 @@ int mlx5dr_domain_sync(struct mlx5dr_domain *domain, u32 flags); · 48 unmodified lines | ||
| 49 | 49 | |
| 50 | 50 | void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, |
| 51 | 51 | struct mlx5dr_domain *peer_dmn, |
| 52 | − u8 peer_idx); | |
| 52 | + u16 peer_vhca_id); | |
| 53 | 53 | |
| 54 | 54 | struct mlx5dr_table * |
| 55 | 55 | mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags, |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/ethtool.h> |
| 9 | 9 | #include <linux/filter.h> |
| 10 | 10 | #include <linux/mm.h> |
| 11 | +#include <linux/pci.h> | |
| 11 | 12 | |
| 12 | 13 | #include <net/checksum.h> |
| 13 | 14 | #include <net/ip6_checksum.h> |
| @@ -2345,9 +2346,12 @@ int mana_attach(struct net_device *ndev) · 2331 unmodified lines | ||
| 2345 | 2346 | static int mana_dealloc_queues(struct net_device *ndev) |
| 2346 | 2347 | { |
| 2347 | 2348 | struct mana_port_context *apc = netdev_priv(ndev); |
| 2349 | + unsigned long timeout = jiffies + 120 * HZ; | |
| 2348 | 2350 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 2349 | 2351 | struct mana_txq *txq; |
| 2352 | + struct sk_buff *skb; | |
| 2350 | 2353 | int i, err; |
| 2354 | + u32 tsleep; | |
| 2351 | 2355 | |
| 2352 | 2356 | if (apc->port_is_up) |
| 2353 | 2357 | return -EINVAL; |
| @@ -2363,15 +2367,40 @@ static int mana_dealloc_queues(struct net_device *ndev) · 9 unmodified lines | ||
| 2363 | 2367 | * to false, but it doesn't matter since mana_start_xmit() drops any |
| 2364 | 2368 | * new packets due to apc->port_is_up being false. |
| 2365 | 2369 | * |
| 2366 | − * Drain all the in-flight TX packets | |
| 2370 | + * Drain all the in-flight TX packets. | |
| 2371 | + * A timeout of 120 seconds for all the queues is used. | |
| 2372 | + * This will break the while loop when h/w is not responding. | |
| 2373 | + * This value of 120 has been decided here considering max | |
| 2374 | + * number of queues. | |
| 2367 | 2375 | */ |
| 2376 | + | |
| 2368 | 2377 | for (i = 0; i < apc->num_queues; i++) { |
| 2369 | 2378 | txq = &apc->tx_qp[i].txq; |
| 2370 | − | |
| 2371 | − while (atomic_read(&txq->pending_sends) > 0) | |
| 2372 | − usleep_range(1000, 2000); | |
| 2379 | + tsleep = 1000; | |
| 2380 | + while (atomic_read(&txq->pending_sends) > 0 && | |
| 2381 | + time_before(jiffies, timeout)) { | |
| 2382 | + usleep_range(tsleep, tsleep + 1000); | |
| 2383 | + tsleep <<= 1; | |
| 2384 | + } | |
| 2385 | + if (atomic_read(&txq->pending_sends)) { | |
| 2386 | + err = pcie_flr(to_pci_dev(gd->gdma_context->dev)); | |
| 2387 | + if (err) { | |
| 2388 | + netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n", | |
| 2389 | + err, atomic_read(&txq->pending_sends), | |
| 2390 | + txq->gdma_txq_id); | |
| 2391 | + } | |
| 2392 | + break; | |
| 2393 | + } | |
| 2373 | 2394 | } |
| 2374 | 2395 | |
| 2396 | + for (i = 0; i < apc->num_queues; i++) { | |
| 2397 | + txq = &apc->tx_qp[i].txq; | |
| 2398 | + while ((skb = skb_dequeue(&txq->pending_skbs))) { | |
| 2399 | + mana_unmap_skb(skb, apc); | |
| 2400 | + dev_kfree_skb_any(skb); | |
| 2401 | + } | |
| 2402 | + atomic_set(&txq->pending_sends, 0); | |
| 2403 | + } | |
| 2375 | 2404 | /* We're 100% sure the queues can no longer be woken up, because |
| 2376 | 2405 | * we're sure now mana_poll_tx_cq() can't be running. |
| 2377 | 2406 | */ |
| @@ -1817,6 +1817,7 @@ static int ionic_change_mtu(struct net_device *netdev, int new_mtu) · 1816 unmodified lines | ||
| 1817 | 1817 | static void ionic_tx_timeout_work(struct work_struct *ws) |
| 1818 | 1818 | { |
| 1819 | 1819 | struct ionic_lif *lif = container_of(ws, struct ionic_lif, tx_timeout_work); |
| 1820 | + int err; | |
| 1820 | 1821 | |
| 1821 | 1822 | if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) |
| 1822 | 1823 | return; |
| @@ -1829,8 +1830,11 @@ static void ionic_tx_timeout_work(struct work_struct *ws) · 6 unmodified lines | ||
| 1829 | 1830 | |
| 1830 | 1831 | mutex_lock(&lif->queue_lock); |
| 1831 | 1832 | ionic_stop_queues_reconfig(lif); |
| 1832 | − ionic_start_queues_reconfig(lif); | |
| 1833 | + err = ionic_start_queues_reconfig(lif); | |
| 1833 | 1834 | mutex_unlock(&lif->queue_lock); |
| 1835 | + | |
| 1836 | + if (err) | |
| 1837 | + dev_err(lif->ionic->dev, "%s: Restarting queues failed\n", __func__); | |
| 1834 | 1838 | } |
| 1835 | 1839 | |
| 1836 | 1840 | static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue) |
| @@ -2800,17 +2804,22 @@ static int ionic_cmb_reconfig(struct ionic_lif *lif, · 963 unmodified lines | ||
| 2800 | 2804 | if (err) { |
| 2801 | 2805 | dev_err(lif->ionic->dev, |
| 2802 | 2806 | "CMB restore failed: %d\n", err); |
| 2803 | − goto errout; | |
| 2807 | + goto err_out; | |
| 2804 | 2808 | } |
| 2805 | 2809 | } |
| 2806 | 2810 | |
| 2807 | − ionic_start_queues_reconfig(lif); | |
| 2808 | − } else { | |
| 2809 | − /* This was detached in ionic_stop_queues_reconfig() */ | |
| 2810 | − netif_device_attach(lif->netdev); | |
| 2811 | + err = ionic_start_queues_reconfig(lif); | |
| 2812 | + if (err) { | |
| 2813 | + dev_err(lif->ionic->dev, | |
| 2814 | + "CMB reconfig failed: %d\n", err); | |
| 2815 | + goto err_out; | |
| 2816 | + } | |
| 2811 | 2817 | } |
| 2812 | 2818 | |
| 2813 | −errout: | |
| 2819 | +err_out: | |
| 2820 | + /* This was detached in ionic_stop_queues_reconfig() */ | |
| 2821 | + netif_device_attach(lif->netdev); | |
| 2822 | + | |
| 2814 | 2823 | return err; |
| 2815 | 2824 | } |
| 2816 | 2825 | |
| @@ -193,6 +193,22 @@ void qed_hw_remove(struct qed_dev *cdev); · 192 unmodified lines | ||
| 193 | 193 | */ |
| 194 | 194 | struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn); |
| 195 | 195 | |
| 196 | +/** | |
| 197 | + * qed_ptt_acquire_context(): Allocate a PTT window honoring the context | |
| 198 | + * atomicy. | |
| 199 | + * | |
| 200 | + * @p_hwfn: HW device data. | |
| 201 | + * @is_atomic: Hint from the caller - if the func can sleep or not. | |
| 202 | + * | |
| 203 | + * Context: The function should not sleep in case is_atomic == true. | |
| 204 | + * Return: struct qed_ptt. | |
| 205 | + * | |
| 206 | + * Should be called at the entry point to the driver | |
| 207 | + * (at the beginning of an exported function). | |
| 208 | + */ | |
| 209 | +struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn, | |
| 210 | + bool is_atomic); | |
| 211 | + | |
| 196 | 212 | /** |
| 197 | 213 | * qed_ptt_release(): Release PTT Window. |
| 198 | 214 | * |
| @@ -693,13 +693,14 @@ static void _qed_fcoe_get_pstats(struct qed_hwfn *p_hwfn, · 692 unmodified lines | ||
| 693 | 693 | } |
| 694 | 694 | |
| 695 | 695 | static int qed_fcoe_get_stats(struct qed_hwfn *p_hwfn, |
| 696 | − struct qed_fcoe_stats *p_stats) | |
| 696 | + struct qed_fcoe_stats *p_stats, | |
| 697 | + bool is_atomic) | |
| 697 | 698 | { |
| 698 | 699 | struct qed_ptt *p_ptt; |
| 699 | 700 | |
| 700 | 701 | memset(p_stats, 0, sizeof(*p_stats)); |
| 701 | 702 | |
| 702 | − p_ptt = qed_ptt_acquire(p_hwfn); | |
| 703 | + p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic); | |
| 703 | 704 | |
| 704 | 705 | if (!p_ptt) { |
| 705 | 706 | DP_ERR(p_hwfn, "Failed to acquire ptt\n"); |
| @@ -973,19 +974,27 @@ static int qed_fcoe_destroy_conn(struct qed_dev *cdev, · 267 unmodified lines | ||
| 973 | 974 | QED_SPQ_MODE_EBLOCK, NULL); |
| 974 | 975 | } |
| 975 | 976 | |
| 977 | +static int qed_fcoe_stats_context(struct qed_dev *cdev, | |
| 978 | + struct qed_fcoe_stats *stats, | |
| 979 | + bool is_atomic) | |
| 980 | +{ | |
| 981 | + return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic); | |
| 982 | +} | |
| 983 | + | |
| 976 | 984 | static int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats) |
| 977 | 985 | { |
| 978 | − return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats); | |
| 986 | + return qed_fcoe_stats_context(cdev, stats, false); | |
| 979 | 987 | } |
| 980 | 988 | |
| 981 | 989 | void qed_get_protocol_stats_fcoe(struct qed_dev *cdev, |
| 982 | − struct qed_mcp_fcoe_stats *stats) | |
| 990 | + struct qed_mcp_fcoe_stats *stats, | |
| 991 | + bool is_atomic) | |
| 983 | 992 | { |
| 984 | 993 | struct qed_fcoe_stats proto_stats; |
| 985 | 994 | |
| 986 | 995 | /* Retrieve FW statistics */ |
| 987 | 996 | memset(&proto_stats, 0, sizeof(proto_stats)); |
| 988 | − if (qed_fcoe_stats(cdev, &proto_stats)) { | |
| 997 | + if (qed_fcoe_stats_context(cdev, &proto_stats, is_atomic)) { | |
| 989 | 998 | DP_VERBOSE(cdev, QED_MSG_STORAGE, |
| 990 | 999 | "Failed to collect FCoE statistics\n"); |
| 991 | 1000 | return; |
| @@ -28,8 +28,20 @@ int qed_fcoe_alloc(struct qed_hwfn *p_hwfn); · 27 unmodified lines | ||
| 28 | 28 | void qed_fcoe_setup(struct qed_hwfn *p_hwfn); |
| 29 | 29 | |
| 30 | 30 | void qed_fcoe_free(struct qed_hwfn *p_hwfn); |
| 31 | +/** | |
| 32 | + * qed_get_protocol_stats_fcoe(): Fills provided statistics | |
| 33 | + * struct with statistics. | |
| 34 | + * | |
| 35 | + * @cdev: Qed dev pointer. | |
| 36 | + * @stats: Points to struct that will be filled with statistics. | |
| 37 | + * @is_atomic: Hint from the caller - if the func can sleep or not. | |
| 38 | + * | |
| 39 | + * Context: The function should not sleep in case is_atomic == true. | |
| 40 | + * Return: Void. | |
| 41 | + */ | |
| 31 | 42 | void qed_get_protocol_stats_fcoe(struct qed_dev *cdev, |
| 32 | − struct qed_mcp_fcoe_stats *stats); | |
| 43 | + struct qed_mcp_fcoe_stats *stats, | |
| 44 | + bool is_atomic); | |
| 33 | 45 | #else /* CONFIG_QED_FCOE */ |
| 34 | 46 | static inline int qed_fcoe_alloc(struct qed_hwfn *p_hwfn) |
| 35 | 47 | { |
| @@ -40,7 +52,8 @@ static inline void qed_fcoe_setup(struct qed_hwfn *p_hwfn) {} · 4 unmodified lines | ||
| 40 | 52 | static inline void qed_fcoe_free(struct qed_hwfn *p_hwfn) {} |
| 41 | 53 | |
| 42 | 54 | static inline void qed_get_protocol_stats_fcoe(struct qed_dev *cdev, |
| 43 | − struct qed_mcp_fcoe_stats *stats) | |
| 55 | + struct qed_mcp_fcoe_stats *stats, | |
| 56 | + bool is_atomic) | |
| 44 | 57 | { |
| 45 | 58 | } |
| 46 | 59 | #endif /* CONFIG_QED_FCOE */ |
| @@ -23,7 +23,10 @@ · 22 unmodified lines | ||
| 23 | 23 | #include "qed_reg_addr.h" |
| 24 | 24 | #include "qed_sriov.h" |
| 25 | 25 | |
| 26 | −#define QED_BAR_ACQUIRE_TIMEOUT 1000 | |
| 26 | +#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT 1000 | |
| 27 | +#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP 1000 | |
| 28 | +#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT 100000 | |
| 29 | +#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY 10 | |
| 27 | 30 | |
| 28 | 31 | /* Invalid values */ |
| 29 | 32 | #define QED_BAR_INVALID_OFFSET (cpu_to_le32(-1)) |
| @@ -84,12 +87,22 @@ void qed_ptt_pool_free(struct qed_hwfn *p_hwfn) · 54 unmodified lines | ||
| 84 | 87 | } |
| 85 | 88 | |
| 86 | 89 | struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn) |
| 90 | +{ | |
| 91 | + return qed_ptt_acquire_context(p_hwfn, false); | |
| 92 | +} | |
| 93 | + | |
| 94 | +struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn, bool is_atomic) | |
| 87 | 95 | { |
| 88 | 96 | struct qed_ptt *p_ptt; |
| 89 | − unsigned int i; | |
| 97 | + unsigned int i, count; | |
| 98 | + | |
| 99 | + if (is_atomic) | |
| 100 | + count = QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT; | |
| 101 | + else | |
| 102 | + count = QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT; | |
| 90 | 103 | |
| 91 | 104 | /* Take the free PTT from the list */ |
| 92 | − for (i = 0; i < QED_BAR_ACQUIRE_TIMEOUT; i++) { | |
| 105 | + for (i = 0; i < count; i++) { | |
| 93 | 106 | spin_lock_bh(&p_hwfn->p_ptt_pool->lock); |
| 94 | 107 | |
| 95 | 108 | if (!list_empty(&p_hwfn->p_ptt_pool->free_list)) { |
| @@ -105,7 +118,12 @@ struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn) · 9 unmodified lines | ||
| 105 | 118 | } |
| 106 | 119 | |
| 107 | 120 | spin_unlock_bh(&p_hwfn->p_ptt_pool->lock); |
| 108 | − usleep_range(1000, 2000); | |
| 121 | + | |
| 122 | + if (is_atomic) | |
| 123 | + udelay(QED_BAR_ACQUIRE_TIMEOUT_UDELAY); | |
| 124 | + else | |
| 125 | + usleep_range(QED_BAR_ACQUIRE_TIMEOUT_USLEEP, | |
| 126 | + QED_BAR_ACQUIRE_TIMEOUT_USLEEP * 2); | |
| 109 | 127 | } |
| 110 | 128 | |
| 111 | 129 | DP_NOTICE(p_hwfn, "PTT acquire timeout - failed to allocate PTT\n"); |
| @@ -999,13 +999,14 @@ static void _qed_iscsi_get_pstats(struct qed_hwfn *p_hwfn, · 998 unmodified lines | ||
| 999 | 999 | } |
| 1000 | 1000 | |
| 1001 | 1001 | static int qed_iscsi_get_stats(struct qed_hwfn *p_hwfn, |
| 1002 | − struct qed_iscsi_stats *stats) | |
| 1002 | + struct qed_iscsi_stats *stats, | |
| 1003 | + bool is_atomic) | |
| 1003 | 1004 | { |
| 1004 | 1005 | struct qed_ptt *p_ptt; |
| 1005 | 1006 | |
| 1006 | 1007 | memset(stats, 0, sizeof(*stats)); |
| 1007 | 1008 | |
| 1008 | − p_ptt = qed_ptt_acquire(p_hwfn); | |
| 1009 | + p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic); | |
| 1009 | 1010 | if (!p_ptt) { |
| 1010 | 1011 | DP_ERR(p_hwfn, "Failed to acquire ptt\n"); |
| 1011 | 1012 | return -EAGAIN; |
| @@ -1336,9 +1337,16 @@ static int qed_iscsi_destroy_conn(struct qed_dev *cdev, · 324 unmodified lines | ||
| 1336 | 1337 | QED_SPQ_MODE_EBLOCK, NULL); |
| 1337 | 1338 | } |
| 1338 | 1339 | |
| 1340 | +static int qed_iscsi_stats_context(struct qed_dev *cdev, | |
| 1341 | + struct qed_iscsi_stats *stats, | |
| 1342 | + bool is_atomic) | |
| 1343 | +{ | |
| 1344 | + return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic); | |
| 1345 | +} | |
| 1346 | + | |
| 1339 | 1347 | static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats) |
| 1340 | 1348 | { |
| 1341 | − return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats); | |
| 1349 | + return qed_iscsi_stats_context(cdev, stats, false); | |
| 1342 | 1350 | } |
| 1343 | 1351 | |
| 1344 | 1352 | static int qed_iscsi_change_mac(struct qed_dev *cdev, |
| @@ -1358,13 +1366,14 @@ static int qed_iscsi_change_mac(struct qed_dev *cdev, · 13 unmodified lines | ||
| 1358 | 1366 | } |
| 1359 | 1367 | |
| 1360 | 1368 | void qed_get_protocol_stats_iscsi(struct qed_dev *cdev, |
| 1361 | − struct qed_mcp_iscsi_stats *stats) | |
| 1369 | + struct qed_mcp_iscsi_stats *stats, | |
| 1370 | + bool is_atomic) | |
| 1362 | 1371 | { |
| 1363 | 1372 | struct qed_iscsi_stats proto_stats; |
| 1364 | 1373 | |
| 1365 | 1374 | /* Retrieve FW statistics */ |
| 1366 | 1375 | memset(&proto_stats, 0, sizeof(proto_stats)); |
| 1367 | − if (qed_iscsi_stats(cdev, &proto_stats)) { | |
| 1376 | + if (qed_iscsi_stats_context(cdev, &proto_stats, is_atomic)) { | |
| 1368 | 1377 | DP_VERBOSE(cdev, QED_MSG_STORAGE, |
| 1369 | 1378 | "Failed to collect ISCSI statistics\n"); |
| 1370 | 1379 | return; |
| @@ -39,11 +39,14 @@ void qed_iscsi_free(struct qed_hwfn *p_hwfn); · 38 unmodified lines | ||
| 39 | 39 | * |
| 40 | 40 | * @cdev: Qed dev pointer. |
| 41 | 41 | * @stats: Points to struct that will be filled with statistics. |
| 42 | + * @is_atomic: Hint from the caller - if the func can sleep or not. | |
| 42 | 43 | * |
| 44 | + * Context: The function should not sleep in case is_atomic == true. | |
| 43 | 45 | * Return: Void. |
| 44 | 46 | */ |
| 45 | 47 | void qed_get_protocol_stats_iscsi(struct qed_dev *cdev, |
| 46 | − struct qed_mcp_iscsi_stats *stats); | |
| 48 | + struct qed_mcp_iscsi_stats *stats, | |
| 49 | + bool is_atomic); | |
| 47 | 50 | #else /* IS_ENABLED(CONFIG_QED_ISCSI) */ |
| 48 | 51 | static inline int qed_iscsi_alloc(struct qed_hwfn *p_hwfn) |
| 49 | 52 | { |
| @@ -56,7 +59,8 @@ static inline void qed_iscsi_free(struct qed_hwfn *p_hwfn) {} · 6 unmodified lines | ||
| 56 | 59 | |
| 57 | 60 | static inline void |
| 58 | 61 | qed_get_protocol_stats_iscsi(struct qed_dev *cdev, |
| 59 | − struct qed_mcp_iscsi_stats *stats) {} | |
| 62 | + struct qed_mcp_iscsi_stats *stats, | |
| 63 | + bool is_atomic) {} | |
| 60 | 64 | #endif /* IS_ENABLED(CONFIG_QED_ISCSI) */ |
| 61 | 65 | |
| 62 | 66 | #endif |
| @@ -1863,7 +1863,8 @@ static void __qed_get_vport_stats(struct qed_hwfn *p_hwfn, · 1862 unmodified lines | ||
| 1863 | 1863 | } |
| 1864 | 1864 | |
| 1865 | 1865 | static void _qed_get_vport_stats(struct qed_dev *cdev, |
| 1866 | − struct qed_eth_stats *stats) | |
| 1866 | + struct qed_eth_stats *stats, | |
| 1867 | + bool is_atomic) | |
| 1867 | 1868 | { |
| 1868 | 1869 | u8 fw_vport = 0; |
| 1869 | 1870 | int i; |
| @@ -1872,10 +1873,11 @@ static void _qed_get_vport_stats(struct qed_dev *cdev, · 2 unmodified lines | ||
| 1872 | 1873 | |
| 1873 | 1874 | for_each_hwfn(cdev, i) { |
| 1874 | 1875 | struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; |
| 1875 | − struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn) | |
| 1876 | − : NULL; | |
| 1876 | + struct qed_ptt *p_ptt; | |
| 1877 | 1877 | bool b_get_port_stats; |
| 1878 | 1878 | |
| 1879 | + p_ptt = IS_PF(cdev) ? qed_ptt_acquire_context(p_hwfn, is_atomic) | |
| 1880 | + : NULL; | |
| 1879 | 1881 | if (IS_PF(cdev)) { |
| 1880 | 1882 | /* The main vport index is relative first */ |
| 1881 | 1883 | if (qed_fw_vport(p_hwfn, 0, &fw_vport)) { |
| @@ -1900,6 +1902,13 @@ out: · 18 unmodified lines | ||
| 1900 | 1902 | } |
| 1901 | 1903 | |
| 1902 | 1904 | void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats) |
| 1905 | +{ | |
| 1906 | + qed_get_vport_stats_context(cdev, stats, false); | |
| 1907 | +} | |
| 1908 | + | |
| 1909 | +void qed_get_vport_stats_context(struct qed_dev *cdev, | |
| 1910 | + struct qed_eth_stats *stats, | |
| 1911 | + bool is_atomic) | |
| 1903 | 1912 | { |
| 1904 | 1913 | u32 i; |
| 1905 | 1914 | |
| @@ -1908,7 +1917,7 @@ void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats) · 2 unmodified lines | ||
| 1908 | 1917 | return; |
| 1909 | 1918 | } |
| 1910 | 1919 | |
| 1911 | − _qed_get_vport_stats(cdev, stats); | |
| 1920 | + _qed_get_vport_stats(cdev, stats, is_atomic); | |
| 1912 | 1921 | |
| 1913 | 1922 | if (!cdev->reset_stats) |
| 1914 | 1923 | return; |
| @@ -1960,7 +1969,7 @@ void qed_reset_vport_stats(struct qed_dev *cdev) · 45 unmodified lines | ||
| 1960 | 1969 | if (!cdev->reset_stats) { |
| 1961 | 1970 | DP_INFO(cdev, "Reset stats not allocated\n"); |
| 1962 | 1971 | } else { |
| 1963 | − _qed_get_vport_stats(cdev, cdev->reset_stats); | |
| 1972 | + _qed_get_vport_stats(cdev, cdev->reset_stats, false); | |
| 1964 | 1973 | cdev->reset_stats->common.link_change_count = 0; |
| 1965 | 1974 | } |
| 1966 | 1975 | } |
| @@ -249,8 +249,32 @@ qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn, · 248 unmodified lines | ||
| 249 | 249 | enum spq_mode comp_mode, |
| 250 | 250 | struct qed_spq_comp_cb *p_comp_data); |
| 251 | 251 | |
| 252 | +/** | |
| 253 | + * qed_get_vport_stats(): Fills provided statistics | |
| 254 | + * struct with statistics. | |
| 255 | + * | |
| 256 | + * @cdev: Qed dev pointer. | |
| 257 | + * @stats: Points to struct that will be filled with statistics. | |
| 258 | + * | |
| 259 | + * Return: Void. | |
| 260 | + */ | |
| 252 | 261 | void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats); |
| 253 | 262 | |
| 263 | +/** | |
| 264 | + * qed_get_vport_stats_context(): Fills provided statistics | |
| 265 | + * struct with statistics. | |
| 266 | + * | |
| 267 | + * @cdev: Qed dev pointer. | |
| 268 | + * @stats: Points to struct that will be filled with statistics. | |
| 269 | + * @is_atomic: Hint from the caller - if the func can sleep or not. | |
| 270 | + * | |
| 271 | + * Context: The function should not sleep in case is_atomic == true. | |
| 272 | + * Return: Void. | |
| 273 | + */ | |
| 274 | +void qed_get_vport_stats_context(struct qed_dev *cdev, | |
| 275 | + struct qed_eth_stats *stats, | |
| 276 | + bool is_atomic); | |
| 277 | + | |
| 254 | 278 | void qed_reset_vport_stats(struct qed_dev *cdev); |
| 255 | 279 | |
| 256 | 280 | /** |
| @@ -3092,7 +3092,7 @@ void qed_get_protocol_stats(struct qed_dev *cdev, · 3091 unmodified lines | ||
| 3092 | 3092 | |
| 3093 | 3093 | switch (type) { |
| 3094 | 3094 | case QED_MCP_LAN_STATS: |
| 3095 | − qed_get_vport_stats(cdev, ð_stats); | |
| 3095 | + qed_get_vport_stats_context(cdev, ð_stats, true); | |
| 3096 | 3096 | stats->lan_stats.ucast_rx_pkts = |
| 3097 | 3097 | eth_stats.common.rx_ucast_pkts; |
| 3098 | 3098 | stats->lan_stats.ucast_tx_pkts = |
| @@ -3100,10 +3100,10 @@ void qed_get_protocol_stats(struct qed_dev *cdev, · 1 unmodified line | ||
| 3100 | 3100 | stats->lan_stats.fcs_err = -1; |
| 3101 | 3101 | break; |
| 3102 | 3102 | case QED_MCP_FCOE_STATS: |
| 3103 | − qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats); | |
| 3103 | + qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats, true); | |
| 3104 | 3104 | break; |
| 3105 | 3105 | case QED_MCP_ISCSI_STATS: |
| 3106 | − qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats); | |
| 3106 | + qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats, true); | |
| 3107 | 3107 | break; |
| 3108 | 3108 | default: |
| 3109 | 3109 | DP_VERBOSE(cdev, QED_MSG_SP, |
| @@ -40,15 +40,16 @@ · 39 unmodified lines | ||
| 40 | 40 | */ |
| 41 | 41 | struct ef4_loopback_payload { |
| 42 | 42 | char pad[2]; /* Ensures ip is 4-byte aligned */ |
| 43 | − struct ethhdr header; | |
| 44 | − struct iphdr ip; | |
| 45 | − struct udphdr udp; | |
| 46 | − __be16 iteration; | |
| 47 | − char msg[64]; | |
| 43 | + struct_group_attr(packet, __packed, | |
| 44 | + struct ethhdr header; | |
| 45 | + struct iphdr ip; | |
| 46 | + struct udphdr udp; | |
| 47 | + __be16 iteration; | |
| 48 | + char msg[64]; | |
| 49 | + ); | |
| 48 | 50 | } __packed __aligned(4); |
| 49 | −#define EF4_LOOPBACK_PAYLOAD_LEN (sizeof(struct ef4_loopback_payload) - \ | |
| 50 | − offsetof(struct ef4_loopback_payload, \ | |
| 51 | − header)) | |
| 51 | +#define EF4_LOOPBACK_PAYLOAD_LEN \ | |
| 52 | + sizeof_field(struct ef4_loopback_payload, packet) | |
| 52 | 53 | |
| 53 | 54 | /* Loopback test source MAC address */ |
| 54 | 55 | static const u8 payload_source[ETH_ALEN] __aligned(2) = { |
| @@ -299,7 +300,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, · 244 unmodified lines | ||
| 299 | 300 | |
| 300 | 301 | payload = &state->payload; |
| 301 | 302 | |
| 302 | − memcpy(&received.header, buf_ptr, | |
| 303 | + memcpy(&received.packet, buf_ptr, | |
| 303 | 304 | min_t(int, pkt_len, EF4_LOOPBACK_PAYLOAD_LEN)); |
| 304 | 305 | received.ip.saddr = payload->ip.saddr; |
| 305 | 306 | if (state->offload_csum) |
| @@ -370,7 +371,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, · 64 unmodified lines | ||
| 370 | 371 | buf_ptr, pkt_len, 0); |
| 371 | 372 | netif_err(efx, drv, efx->net_dev, "expected packet:\n"); |
| 372 | 373 | print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, |
| 373 | − &state->payload.header, EF4_LOOPBACK_PAYLOAD_LEN, | |
| 374 | + &state->payload.packet, EF4_LOOPBACK_PAYLOAD_LEN, | |
| 374 | 375 | 0); |
| 375 | 376 | } |
| 376 | 377 | #endif |
| @@ -440,6 +441,8 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue) · 63 unmodified lines | ||
| 440 | 441 | payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); |
| 441 | 442 | /* Strip off the leading padding */ |
| 442 | 443 | skb_pull(skb, offsetof(struct ef4_loopback_payload, header)); |
| 444 | + /* Strip off the trailing padding */ | |
| 445 | + skb_trim(skb, EF4_LOOPBACK_PAYLOAD_LEN); | |
| 443 | 446 | |
| 444 | 447 | /* Ensure everything we've written is visible to the |
| 445 | 448 | * interrupt handler. */ |
| @@ -43,15 +43,16 @@ · 42 unmodified lines | ||
| 43 | 43 | */ |
| 44 | 44 | struct efx_loopback_payload { |
| 45 | 45 | char pad[2]; /* Ensures ip is 4-byte aligned */ |
| 46 | − struct ethhdr header; | |
| 47 | − struct iphdr ip; | |
| 48 | − struct udphdr udp; | |
| 49 | − __be16 iteration; | |
| 50 | − char msg[64]; | |
| 46 | + struct_group_attr(packet, __packed, | |
| 47 | + struct ethhdr header; | |
| 48 | + struct iphdr ip; | |
| 49 | + struct udphdr udp; | |
| 50 | + __be16 iteration; | |
| 51 | + char msg[64]; | |
| 52 | + ); | |
| 51 | 53 | } __packed __aligned(4); |
| 52 | −#define EFX_LOOPBACK_PAYLOAD_LEN (sizeof(struct efx_loopback_payload) - \ | |
| 53 | − offsetof(struct efx_loopback_payload, \ | |
| 54 | − header)) | |
| 54 | +#define EFX_LOOPBACK_PAYLOAD_LEN \ | |
| 55 | + sizeof_field(struct efx_loopback_payload, packet) | |
| 55 | 56 | |
| 56 | 57 | /* Loopback test source MAC address */ |
| 57 | 58 | static const u8 payload_source[ETH_ALEN] __aligned(2) = { |
| @@ -297,7 +298,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, · 239 unmodified lines | ||
| 297 | 298 | |
| 298 | 299 | payload = &state->payload; |
| 299 | 300 | |
| 300 | − memcpy(&received.header, buf_ptr, | |
| 301 | + memcpy(&received.packet, buf_ptr, | |
| 301 | 302 | min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); |
| 302 | 303 | received.ip.saddr = payload->ip.saddr; |
| 303 | 304 | if (state->offload_csum) |
| @@ -368,7 +369,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, · 64 unmodified lines | ||
| 368 | 369 | buf_ptr, pkt_len, 0); |
| 369 | 370 | netif_err(efx, drv, efx->net_dev, "expected packet:\n"); |
| 370 | 371 | print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, |
| 371 | − &state->payload.header, EFX_LOOPBACK_PAYLOAD_LEN, | |
| 372 | + &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN, | |
| 372 | 373 | 0); |
| 373 | 374 | } |
| 374 | 375 | #endif |
| @@ -438,6 +439,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) · 63 unmodified lines | ||
| 438 | 439 | payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); |
| 439 | 440 | /* Strip off the leading padding */ |
| 440 | 441 | skb_pull(skb, offsetof(struct efx_loopback_payload, header)); |
| 442 | + /* Strip off the trailing padding */ | |
| 443 | + skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN); | |
| 441 | 444 | |
| 442 | 445 | /* Ensure everything we've written is visible to the |
| 443 | 446 | * interrupt handler. */ |
| @@ -43,15 +43,16 @@ · 42 unmodified lines | ||
| 43 | 43 | */ |
| 44 | 44 | struct efx_loopback_payload { |
| 45 | 45 | char pad[2]; /* Ensures ip is 4-byte aligned */ |
| 46 | − struct ethhdr header; | |
| 47 | − struct iphdr ip; | |
| 48 | − struct udphdr udp; | |
| 49 | − __be16 iteration; | |
| 50 | − char msg[64]; | |
| 46 | + struct_group_attr(packet, __packed, | |
| 47 | + struct ethhdr header; | |
| 48 | + struct iphdr ip; | |
| 49 | + struct udphdr udp; | |
| 50 | + __be16 iteration; | |
| 51 | + char msg[64]; | |
| 52 | + ); | |
| 51 | 53 | } __packed __aligned(4); |
| 52 | −#define EFX_LOOPBACK_PAYLOAD_LEN (sizeof(struct efx_loopback_payload) - \ | |
| 53 | − offsetof(struct efx_loopback_payload, \ | |
| 54 | − header)) | |
| 54 | +#define EFX_LOOPBACK_PAYLOAD_LEN \ | |
| 55 | + sizeof_field(struct efx_loopback_payload, packet) | |
| 55 | 56 | |
| 56 | 57 | /* Loopback test source MAC address */ |
| 57 | 58 | static const u8 payload_source[ETH_ALEN] __aligned(2) = { |
| @@ -297,7 +298,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, · 239 unmodified lines | ||
| 297 | 298 | |
| 298 | 299 | payload = &state->payload; |
| 299 | 300 | |
| 300 | − memcpy(&received.header, buf_ptr, | |
| 301 | + memcpy(&received.packet, buf_ptr, | |
| 301 | 302 | min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); |
| 302 | 303 | received.ip.saddr = payload->ip.saddr; |
| 303 | 304 | if (state->offload_csum) |
| @@ -368,7 +369,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, · 64 unmodified lines | ||
| 368 | 369 | buf_ptr, pkt_len, 0); |
| 369 | 370 | netif_err(efx, drv, efx->net_dev, "expected packet:\n"); |
| 370 | 371 | print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, |
| 371 | − &state->payload.header, EFX_LOOPBACK_PAYLOAD_LEN, | |
| 372 | + &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN, | |
| 372 | 373 | 0); |
| 373 | 374 | } |
| 374 | 375 | #endif |
| @@ -438,6 +439,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) · 63 unmodified lines | ||
| 438 | 439 | payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); |
| 439 | 440 | /* Strip off the leading padding */ |
| 440 | 441 | skb_pull(skb, offsetof(struct efx_loopback_payload, header)); |
| 442 | + /* Strip off the trailing padding */ | |
| 443 | + skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN); | |
| 441 | 444 | |
| 442 | 445 | /* Ensure everything we've written is visible to the |
| 443 | 446 | * interrupt handler. */ |
| @@ -1851,6 +1851,17 @@ static int netsec_of_probe(struct platform_device *pdev, · 1850 unmodified lines | ||
| 1851 | 1851 | return err; |
| 1852 | 1852 | } |
| 1853 | 1853 | |
| 1854 | + /* | |
| 1855 | + * SynQuacer is physically configured with TX and RX delays | |
| 1856 | + * but the standard firmware claimed otherwise for a long | |
| 1857 | + * time, ignore it. | |
| 1858 | + */ | |
| 1859 | + if (of_machine_is_compatible("socionext,developer-box") && | |
| 1860 | + priv->phy_interface != PHY_INTERFACE_MODE_RGMII_ID) { | |
| 1861 | + dev_warn(&pdev->dev, "Outdated firmware reports incorrect PHY mode, overriding\n"); | |
| 1862 | + priv->phy_interface = PHY_INTERFACE_MODE_RGMII_ID; | |
| 1863 | + } | |
| 1864 | + | |
| 1854 | 1865 | priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); |
| 1855 | 1866 | if (!priv->phy_np) { |
| 1856 | 1867 | dev_err(&pdev->dev, "missing required property 'phy-handle'\n"); |
| @@ -234,7 +234,8 @@ static int tegra_mgbe_probe(struct platform_device *pdev) · 233 unmodified lines | ||
| 234 | 234 | res.addr = mgbe->regs; |
| 235 | 235 | res.irq = irq; |
| 236 | 236 | |
| 237 | − mgbe->clks = devm_kzalloc(&pdev->dev, sizeof(*mgbe->clks), GFP_KERNEL); | |
| 237 | + mgbe->clks = devm_kcalloc(&pdev->dev, ARRAY_SIZE(mgbe_clks), | |
| 238 | + sizeof(*mgbe->clks), GFP_KERNEL); | |
| 238 | 239 | if (!mgbe->clks) |
| 239 | 240 | return -ENOMEM; |
| 240 | 241 | |
| @@ -1567,12 +1567,16 @@ static int temac_probe(struct platform_device *pdev) · 1566 unmodified lines | ||
| 1567 | 1567 | } |
| 1568 | 1568 | |
| 1569 | 1569 | /* Error handle returned DMA RX and TX interrupts */ |
| 1570 | − if (lp->rx_irq < 0) | |
| 1571 | − return dev_err_probe(&pdev->dev, lp->rx_irq, | |
| 1570 | + if (lp->rx_irq <= 0) { | |
| 1571 | + rc = lp->rx_irq ?: -EINVAL; | |
| 1572 | + return dev_err_probe(&pdev->dev, rc, | |
| 1572 | 1573 | "could not get DMA RX irq\n"); |
| 1573 | − if (lp->tx_irq < 0) | |
| 1574 | − return dev_err_probe(&pdev->dev, lp->tx_irq, | |
| 1574 | + } | |
| 1575 | + if (lp->tx_irq <= 0) { | |
| 1576 | + rc = lp->tx_irq ?: -EINVAL; | |
| 1577 | + return dev_err_probe(&pdev->dev, rc, | |
| 1575 | 1578 | "could not get DMA TX irq\n"); |
| 1579 | + } | |
| 1576 | 1580 | |
| 1577 | 1581 | if (temac_np) { |
| 1578 | 1582 | /* Retrieve the MAC address */ |
| @@ -743,7 +743,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u · 742 unmodified lines | ||
| 743 | 743 | u64_stats_update_begin(&rxsc_stats->syncp); |
| 744 | 744 | rxsc_stats->stats.InPktsLate++; |
| 745 | 745 | u64_stats_update_end(&rxsc_stats->syncp); |
| 746 | − secy->netdev->stats.rx_dropped++; | |
| 746 | + DEV_STATS_INC(secy->netdev, rx_dropped); | |
| 747 | 747 | return false; |
| 748 | 748 | } |
| 749 | 749 | |
| @@ -767,7 +767,7 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u · 17 unmodified lines | ||
| 767 | 767 | rxsc_stats->stats.InPktsNotValid++; |
| 768 | 768 | u64_stats_update_end(&rxsc_stats->syncp); |
| 769 | 769 | this_cpu_inc(rx_sa->stats->InPktsNotValid); |
| 770 | − secy->netdev->stats.rx_errors++; | |
| 770 | + DEV_STATS_INC(secy->netdev, rx_errors); | |
| 771 | 771 | return false; |
| 772 | 772 | } |
| 773 | 773 | |
| @@ -1069,7 +1069,7 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb) · 295 unmodified lines | ||
| 1069 | 1069 | u64_stats_update_begin(&secy_stats->syncp); |
| 1070 | 1070 | secy_stats->stats.InPktsNoTag++; |
| 1071 | 1071 | u64_stats_update_end(&secy_stats->syncp); |
| 1072 | − macsec->secy.netdev->stats.rx_dropped++; | |
| 1072 | + DEV_STATS_INC(macsec->secy.netdev, rx_dropped); | |
| 1073 | 1073 | continue; |
| 1074 | 1074 | } |
| 1075 | 1075 | |
| @@ -1179,7 +1179,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) · 103 unmodified lines | ||
| 1179 | 1179 | u64_stats_update_begin(&secy_stats->syncp); |
| 1180 | 1180 | secy_stats->stats.InPktsBadTag++; |
| 1181 | 1181 | u64_stats_update_end(&secy_stats->syncp); |
| 1182 | − secy->netdev->stats.rx_errors++; | |
| 1182 | + DEV_STATS_INC(secy->netdev, rx_errors); | |
| 1183 | 1183 | goto drop_nosa; |
| 1184 | 1184 | } |
| 1185 | 1185 | |
| @@ -1196,7 +1196,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) · 10 unmodified lines | ||
| 1196 | 1196 | u64_stats_update_begin(&rxsc_stats->syncp); |
| 1197 | 1197 | rxsc_stats->stats.InPktsNotUsingSA++; |
| 1198 | 1198 | u64_stats_update_end(&rxsc_stats->syncp); |
| 1199 | − secy->netdev->stats.rx_errors++; | |
| 1199 | + DEV_STATS_INC(secy->netdev, rx_errors); | |
| 1200 | 1200 | if (active_rx_sa) |
| 1201 | 1201 | this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA); |
| 1202 | 1202 | goto drop_nosa; |
| @@ -1230,7 +1230,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) · 27 unmodified lines | ||
| 1230 | 1230 | u64_stats_update_begin(&rxsc_stats->syncp); |
| 1231 | 1231 | rxsc_stats->stats.InPktsLate++; |
| 1232 | 1232 | u64_stats_update_end(&rxsc_stats->syncp); |
| 1233 | − macsec->secy.netdev->stats.rx_dropped++; | |
| 1233 | + DEV_STATS_INC(macsec->secy.netdev, rx_dropped); | |
| 1234 | 1234 | goto drop; |
| 1235 | 1235 | } |
| 1236 | 1236 | } |
| @@ -1271,7 +1271,7 @@ deliver: · 34 unmodified lines | ||
| 1271 | 1271 | if (ret == NET_RX_SUCCESS) |
| 1272 | 1272 | count_rx(dev, len); |
| 1273 | 1273 | else |
| 1274 | − macsec->secy.netdev->stats.rx_dropped++; | |
| 1274 | + DEV_STATS_INC(macsec->secy.netdev, rx_dropped); | |
| 1275 | 1275 | |
| 1276 | 1276 | rcu_read_unlock(); |
| 1277 | 1277 | |
| @@ -1308,7 +1308,7 @@ nosci: · 30 unmodified lines | ||
| 1308 | 1308 | u64_stats_update_begin(&secy_stats->syncp); |
| 1309 | 1309 | secy_stats->stats.InPktsNoSCI++; |
| 1310 | 1310 | u64_stats_update_end(&secy_stats->syncp); |
| 1311 | − macsec->secy.netdev->stats.rx_errors++; | |
| 1311 | + DEV_STATS_INC(macsec->secy.netdev, rx_errors); | |
| 1312 | 1312 | continue; |
| 1313 | 1313 | } |
| 1314 | 1314 | |
| @@ -1327,7 +1327,7 @@ nosci: · 12 unmodified lines | ||
| 1327 | 1327 | secy_stats->stats.InPktsUnknownSCI++; |
| 1328 | 1328 | u64_stats_update_end(&secy_stats->syncp); |
| 1329 | 1329 | } else { |
| 1330 | − macsec->secy.netdev->stats.rx_dropped++; | |
| 1330 | + DEV_STATS_INC(macsec->secy.netdev, rx_dropped); | |
| 1331 | 1331 | } |
| 1332 | 1332 | } |
| 1333 | 1333 | |
| @@ -3422,7 +3422,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, · 2088 unmodified lines | ||
| 3422 | 3422 | |
| 3423 | 3423 | if (!secy->operational) { |
| 3424 | 3424 | kfree_skb(skb); |
| 3425 | − dev->stats.tx_dropped++; | |
| 3425 | + DEV_STATS_INC(dev, tx_dropped); | |
| 3426 | 3426 | return NETDEV_TX_OK; |
| 3427 | 3427 | } |
| 3428 | 3428 | |
| @@ -3430,7 +3430,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb, · 1 unmodified line | ||
| 3430 | 3430 | skb = macsec_encrypt(skb, dev); |
| 3431 | 3431 | if (IS_ERR(skb)) { |
| 3432 | 3432 | if (PTR_ERR(skb) != -EINPROGRESS) |
| 3433 | − dev->stats.tx_dropped++; | |
| 3433 | + DEV_STATS_INC(dev, tx_dropped); | |
| 3434 | 3434 | return NETDEV_TX_OK; |
| 3435 | 3435 | } |
| 3436 | 3436 | |
| @@ -3667,9 +3667,9 @@ static void macsec_get_stats64(struct net_device *dev, · 230 unmodified lines | ||
| 3667 | 3667 | |
| 3668 | 3668 | dev_fetch_sw_netstats(s, dev->tstats); |
| 3669 | 3669 | |
| 3670 | − s->rx_dropped = dev->stats.rx_dropped; | |
| 3671 | − s->tx_dropped = dev->stats.tx_dropped; | |
| 3672 | − s->rx_errors = dev->stats.rx_errors; | |
| 3670 | + s->rx_dropped = atomic_long_read(&dev->stats.__rx_dropped); | |
| 3671 | + s->tx_dropped = atomic_long_read(&dev->stats.__tx_dropped); | |
| 3672 | + s->rx_errors = atomic_long_read(&dev->stats.__rx_errors); | |
| 3673 | 3673 | } |
| 3674 | 3674 | |
| 3675 | 3675 | static int macsec_get_iflink(const struct net_device *dev) |
| @@ -459,21 +459,27 @@ static int at803x_set_wol(struct phy_device *phydev, · 458 unmodified lines | ||
| 459 | 459 | phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], |
| 460 | 460 | mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); |
| 461 | 461 | |
| 462 | − /* Enable WOL function */ | |
| 463 | − ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL, | |
| 464 | − 0, AT803X_WOL_EN); | |
| 465 | − if (ret) | |
| 466 | − return ret; | |
| 462 | + /* Enable WOL function for 1588 */ | |
| 463 | + if (phydev->drv->phy_id == ATH8031_PHY_ID) { | |
| 464 | + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, | |
| 465 | + AT803X_PHY_MMD3_WOL_CTRL, | |
| 466 | + 0, AT803X_WOL_EN); | |
| 467 | + if (ret) | |
| 468 | + return ret; | |
| 469 | + } | |
| 467 | 470 | /* Enable WOL interrupt */ |
| 468 | 471 | ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); |
| 469 | 472 | if (ret) |
| 470 | 473 | return ret; |
| 471 | 474 | } else { |
| 472 | − /* Disable WoL function */ | |
| 473 | − ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL, | |
| 474 | − AT803X_WOL_EN, 0); | |
| 475 | − if (ret) | |
| 476 | − return ret; | |
| 475 | + /* Disable WoL function for 1588 */ | |
| 476 | + if (phydev->drv->phy_id == ATH8031_PHY_ID) { | |
| 477 | + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, | |
| 478 | + AT803X_PHY_MMD3_WOL_CTRL, | |
| 479 | + AT803X_WOL_EN, 0); | |
| 480 | + if (ret) | |
| 481 | + return ret; | |
| 482 | + } | |
| 477 | 483 | /* Disable WOL interrupt */ |
| 478 | 484 | ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); |
| 479 | 485 | if (ret) |
| @@ -508,11 +514,11 @@ static void at803x_get_wol(struct phy_device *phydev, · 28 unmodified lines | ||
| 508 | 514 | wol->supported = WAKE_MAGIC; |
| 509 | 515 | wol->wolopts = 0; |
| 510 | 516 | |
| 511 | − value = phy_read_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL); | |
| 517 | + value = phy_read(phydev, AT803X_INTR_ENABLE); | |
| 512 | 518 | if (value < 0) |
| 513 | 519 | return; |
| 514 | 520 | |
| 515 | − if (value & AT803X_WOL_EN) | |
| 521 | + if (value & AT803X_INTR_ENABLE_WOL) | |
| 516 | 522 | wol->wolopts |= WAKE_MAGIC; |
| 517 | 523 | } |
| 518 | 524 | |
| @@ -858,9 +864,6 @@ static int at803x_probe(struct phy_device *phydev) · 339 unmodified lines | ||
| 858 | 864 | if (phydev->drv->phy_id == ATH8031_PHY_ID) { |
| 859 | 865 | int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); |
| 860 | 866 | int mode_cfg; |
| 861 | − struct ethtool_wolinfo wol = { | |
| 862 | − .wolopts = 0, | |
| 863 | − }; | |
| 864 | 867 | |
| 865 | 868 | if (ccr < 0) |
| 866 | 869 | return ccr; |
| @@ -877,12 +880,14 @@ static int at803x_probe(struct phy_device *phydev) · 10 unmodified lines | ||
| 877 | 880 | break; |
| 878 | 881 | } |
| 879 | 882 | |
| 880 | − /* Disable WOL by default */ | |
| 881 | − ret = at803x_set_wol(phydev, &wol); | |
| 882 | − if (ret < 0) { | |
| 883 | − phydev_err(phydev, "failed to disable WOL on probe: %d\n", ret); | |
| 883 | + /* Disable WoL in 1588 register which is enabled | |
| 884 | + * by default | |
| 885 | + */ | |
| 886 | + ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, | |
| 887 | + AT803X_PHY_MMD3_WOL_CTRL, | |
| 888 | + AT803X_WOL_EN, 0); | |
| 889 | + if (ret) | |
| 884 | 890 | return ret; |
| 885 | − } | |
| 886 | 891 | } |
| 887 | 892 | |
| 888 | 893 | return 0; |
| @@ -2059,8 +2064,6 @@ static struct phy_driver at803x_driver[] = { · 1170 unmodified lines | ||
| 2059 | 2064 | .flags = PHY_POLL_CABLE_TEST, |
| 2060 | 2065 | .config_init = at803x_config_init, |
| 2061 | 2066 | .link_change_notify = at803x_link_change_notify, |
| 2062 | − .set_wol = at803x_set_wol, | |
| 2063 | − .get_wol = at803x_get_wol, | |
| 2064 | 2067 | .suspend = at803x_suspend, |
| 2065 | 2068 | .resume = at803x_resume, |
| 2066 | 2069 | /* PHY_BASIC_FEATURES */ |
| @@ -534,7 +534,7 @@ static int tap_open(struct inode *inode, struct file *file) · 533 unmodified lines | ||
| 534 | 534 | q->sock.state = SS_CONNECTED; |
| 535 | 535 | q->sock.file = file; |
| 536 | 536 | q->sock.ops = &tap_socket_ops; |
| 537 | − sock_init_data_uid(&q->sock, &q->sk, inode->i_uid); | |
| 537 | + sock_init_data_uid(&q->sock, &q->sk, current_fsuid()); | |
| 538 | 538 | q->sk.sk_write_space = tap_sock_write_space; |
| 539 | 539 | q->sk.sk_destruct = tap_sock_destruct; |
| 540 | 540 | q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; |
| @@ -1594,7 +1594,7 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile, · 1593 unmodified lines | ||
| 1594 | 1594 | if (zerocopy) |
| 1595 | 1595 | return false; |
| 1596 | 1596 | |
| 1597 | − if (SKB_DATA_ALIGN(len + TUN_RX_PAD) + | |
| 1597 | + if (SKB_DATA_ALIGN(len + TUN_RX_PAD + XDP_PACKET_HEADROOM) + | |
| 1598 | 1598 | SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PAGE_SIZE) |
| 1599 | 1599 | return false; |
| 1600 | 1600 | |
| @@ -3469,7 +3469,7 @@ static int tun_chr_open(struct inode *inode, struct file * file) · 1868 unmodified lines | ||
| 3469 | 3469 | tfile->socket.file = file; |
| 3470 | 3470 | tfile->socket.ops = &tun_socket_ops; |
| 3471 | 3471 | |
| 3472 | − sock_init_data_uid(&tfile->socket, &tfile->sk, inode->i_uid); | |
| 3472 | + sock_init_data_uid(&tfile->socket, &tfile->sk, current_fsuid()); | |
| 3473 | 3473 | |
| 3474 | 3474 | tfile->sk.sk_write_space = tun_sock_write_space; |
| 3475 | 3475 | tfile->sk.sk_sndbuf = INT_MAX; |
| @@ -618,9 +618,23 @@ static const struct usb_device_id products[] = { · 617 unmodified lines | ||
| 618 | 618 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 619 | 619 | | USB_DEVICE_ID_MATCH_DEVICE, |
| 620 | 620 | .idVendor = 0x04DD, |
| 621 | + .idProduct = 0x8005, /* A-300 */ | |
| 622 | + ZAURUS_FAKE_INTERFACE, | |
| 623 | + .driver_info = 0, | |
| 624 | +}, { | |
| 625 | + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | |
| 626 | + | USB_DEVICE_ID_MATCH_DEVICE, | |
| 627 | + .idVendor = 0x04DD, | |
| 621 | 628 | .idProduct = 0x8006, /* B-500/SL-5600 */ |
| 622 | 629 | ZAURUS_MASTER_INTERFACE, |
| 623 | 630 | .driver_info = 0, |
| 631 | +}, { | |
| 632 | + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | |
| 633 | + | USB_DEVICE_ID_MATCH_DEVICE, | |
| 634 | + .idVendor = 0x04DD, | |
| 635 | + .idProduct = 0x8006, /* B-500/SL-5600 */ | |
| 636 | + ZAURUS_FAKE_INTERFACE, | |
| 637 | + .driver_info = 0, | |
| 624 | 638 | }, { |
| 625 | 639 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 626 | 640 | | USB_DEVICE_ID_MATCH_DEVICE, |
| @@ -628,6 +642,13 @@ static const struct usb_device_id products[] = { · 1 unmodified line | ||
| 628 | 642 | .idProduct = 0x8007, /* C-700 */ |
| 629 | 643 | ZAURUS_MASTER_INTERFACE, |
| 630 | 644 | .driver_info = 0, |
| 645 | +}, { | |
| 646 | + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | |
| 647 | + | USB_DEVICE_ID_MATCH_DEVICE, | |
| 648 | + .idVendor = 0x04DD, | |
| 649 | + .idProduct = 0x8007, /* C-700 */ | |
| 650 | + ZAURUS_FAKE_INTERFACE, | |
| 651 | + .driver_info = 0, | |
| 631 | 652 | }, { |
| 632 | 653 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 633 | 654 | | USB_DEVICE_ID_MATCH_DEVICE, |
| @@ -4224,8 +4224,6 @@ static void lan78xx_disconnect(struct usb_interface *intf) · 4223 unmodified lines | ||
| 4224 | 4224 | if (!dev) |
| 4225 | 4225 | return; |
| 4226 | 4226 | |
| 4227 | − set_bit(EVENT_DEV_DISCONNECT, &dev->flags); | |
| 4228 | − | |
| 4229 | 4227 | netif_napi_del(&dev->napi); |
| 4230 | 4228 | |
| 4231 | 4229 | udev = interface_to_usbdev(intf); |
| @@ -4233,6 +4231,8 @@ static void lan78xx_disconnect(struct usb_interface *intf) · 1 unmodified line | ||
| 4233 | 4231 | |
| 4234 | 4232 | unregister_netdev(net); |
| 4235 | 4233 | |
| 4234 | + timer_shutdown_sync(&dev->stat_monitor); | |
| 4235 | + set_bit(EVENT_DEV_DISCONNECT, &dev->flags); | |
| 4236 | 4236 | cancel_delayed_work_sync(&dev->wq); |
| 4237 | 4237 | |
| 4238 | 4238 | phydev = net->phydev; |
| @@ -4247,9 +4247,6 @@ static void lan78xx_disconnect(struct usb_interface *intf) · 8 unmodified lines | ||
| 4247 | 4247 | |
| 4248 | 4248 | usb_scuttle_anchored_urbs(&dev->deferred); |
| 4249 | 4249 | |
| 4250 | − if (timer_pending(&dev->stat_monitor)) | |
| 4251 | − del_timer_sync(&dev->stat_monitor); | |
| 4252 | − | |
| 4253 | 4250 | lan78xx_unbind(dev, intf); |
| 4254 | 4251 | |
| 4255 | 4252 | lan78xx_free_tx_resources(dev); |
| @@ -1423,6 +1423,7 @@ static const struct usb_device_id products[] = { · 1422 unmodified lines | ||
| 1423 | 1423 | {QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */ |
| 1424 | 1424 | {QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */ |
| 1425 | 1425 | {QMI_FIXED_INTF(0x2c7c, 0x0296, 4)}, /* Quectel BG96 */ |
| 1426 | + {QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)}, /* Quectel EM05GV2 */ | |
| 1426 | 1427 | {QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */ |
| 1427 | 1428 | {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */ |
| 1428 | 1429 | {QMI_FIXED_INTF(0x0489, 0xe0b5, 0)}, /* Foxconn T77W968 LTE with eSIM support*/ |
| @@ -289,9 +289,23 @@ static const struct usb_device_id products [] = { · 288 unmodified lines | ||
| 289 | 289 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 290 | 290 | | USB_DEVICE_ID_MATCH_DEVICE, |
| 291 | 291 | .idVendor = 0x04DD, |
| 292 | + .idProduct = 0x8005, /* A-300 */ | |
| 293 | + ZAURUS_FAKE_INTERFACE, | |
| 294 | + .driver_info = (unsigned long)&bogus_mdlm_info, | |
| 295 | +}, { | |
| 296 | + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | |
| 297 | + | USB_DEVICE_ID_MATCH_DEVICE, | |
| 298 | + .idVendor = 0x04DD, | |
| 292 | 299 | .idProduct = 0x8006, /* B-500/SL-5600 */ |
| 293 | 300 | ZAURUS_MASTER_INTERFACE, |
| 294 | 301 | .driver_info = ZAURUS_PXA_INFO, |
| 302 | +}, { | |
| 303 | + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | |
| 304 | + | USB_DEVICE_ID_MATCH_DEVICE, | |
| 305 | + .idVendor = 0x04DD, | |
| 306 | + .idProduct = 0x8006, /* B-500/SL-5600 */ | |
| 307 | + ZAURUS_FAKE_INTERFACE, | |
| 308 | + .driver_info = (unsigned long)&bogus_mdlm_info, | |
| 295 | 309 | }, { |
| 296 | 310 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 297 | 311 | | USB_DEVICE_ID_MATCH_DEVICE, |
| @@ -299,6 +313,13 @@ static const struct usb_device_id products [] = { · 1 unmodified line | ||
| 299 | 313 | .idProduct = 0x8007, /* C-700 */ |
| 300 | 314 | ZAURUS_MASTER_INTERFACE, |
| 301 | 315 | .driver_info = ZAURUS_PXA_INFO, |
| 316 | +}, { | |
| 317 | + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | |
| 318 | + | USB_DEVICE_ID_MATCH_DEVICE, | |
| 319 | + .idVendor = 0x04DD, | |
| 320 | + .idProduct = 0x8007, /* C-700 */ | |
| 321 | + ZAURUS_FAKE_INTERFACE, | |
| 322 | + .driver_info = (unsigned long)&bogus_mdlm_info, | |
| 302 | 323 | }, { |
| 303 | 324 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 304 | 325 | | USB_DEVICE_ID_MATCH_DEVICE, |
| @@ -713,6 +713,12 @@ static struct vxlan_vni_node *vxlan_vni_alloc(struct vxlan_dev *vxlan, · 712 unmodified lines | ||
| 713 | 713 | return vninode; |
| 714 | 714 | } |
| 715 | 715 | |
| 716 | +static void vxlan_vni_free(struct vxlan_vni_node *vninode) | |
| 717 | +{ | |
| 718 | + free_percpu(vninode->stats); | |
| 719 | + kfree(vninode); | |
| 720 | +} | |
| 721 | + | |
| 716 | 722 | static int vxlan_vni_add(struct vxlan_dev *vxlan, |
| 717 | 723 | struct vxlan_vni_group *vg, |
| 718 | 724 | u32 vni, union vxlan_addr *group, |
| @@ -740,7 +746,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan, · 21 unmodified lines | ||
| 740 | 746 | &vninode->vnode, |
| 741 | 747 | vxlan_vni_rht_params); |
| 742 | 748 | if (err) { |
| 743 | − kfree(vninode); | |
| 749 | + vxlan_vni_free(vninode); | |
| 744 | 750 | return err; |
| 745 | 751 | } |
| 746 | 752 | |
| @@ -763,8 +769,7 @@ static void vxlan_vni_node_rcu_free(struct rcu_head *rcu) · 16 unmodified lines | ||
| 763 | 769 | struct vxlan_vni_node *v; |
| 764 | 770 | |
| 765 | 771 | v = container_of(rcu, struct vxlan_vni_node, rcu); |
| 766 | − free_percpu(v->stats); | |
| 767 | − kfree(v); | |
| 772 | + vxlan_vni_free(v); | |
| 768 | 773 | } |
| 769 | 774 | |
| 770 | 775 | static int vxlan_vni_del(struct vxlan_dev *vxlan, |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include "allowedips.h" |
| 7 | 7 | #include "peer.h" |
| 8 | 8 | |
| 9 | −enum { MAX_ALLOWEDIPS_BITS = 128 }; | |
| 9 | +enum { MAX_ALLOWEDIPS_DEPTH = 129 }; | |
| 10 | 10 | |
| 11 | 11 | static struct kmem_cache *node_cache; |
| 12 | 12 | |
| @@ -42,7 +42,7 @@ static void push_rcu(struct allowedips_node **stack, · 29 unmodified lines | ||
| 42 | 42 | struct allowedips_node __rcu *p, unsigned int *len) |
| 43 | 43 | { |
| 44 | 44 | if (rcu_access_pointer(p)) { |
| 45 | − if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_BITS)) | |
| 45 | + if (WARN_ON(IS_ENABLED(DEBUG) && *len >= MAX_ALLOWEDIPS_DEPTH)) | |
| 46 | 46 | return; |
| 47 | 47 | stack[(*len)++] = rcu_dereference_raw(p); |
| 48 | 48 | } |
| @@ -55,7 +55,7 @@ static void node_free_rcu(struct rcu_head *rcu) · 6 unmodified lines | ||
| 55 | 55 | |
| 56 | 56 | static void root_free_rcu(struct rcu_head *rcu) |
| 57 | 57 | { |
| 58 | − struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = { | |
| 58 | + struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = { | |
| 59 | 59 | container_of(rcu, struct allowedips_node, rcu) }; |
| 60 | 60 | unsigned int len = 1; |
| 61 | 61 | |
| @@ -68,7 +68,7 @@ static void root_free_rcu(struct rcu_head *rcu) · 6 unmodified lines | ||
| 68 | 68 | |
| 69 | 69 | static void root_remove_peer_lists(struct allowedips_node *root) |
| 70 | 70 | { |
| 71 | − struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_BITS] = { root }; | |
| 71 | + struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = { root }; | |
| 72 | 72 | unsigned int len = 1; |
| 73 | 73 | |
| 74 | 74 | while (len > 0 && (node = stack[--len])) { |
| @@ -593,16 +593,20 @@ bool __init wg_allowedips_selftest(void) · 592 unmodified lines | ||
| 593 | 593 | wg_allowedips_remove_by_peer(&t, a, &mutex); |
| 594 | 594 | test_negative(4, a, 192, 168, 0, 1); |
| 595 | 595 | |
| 596 | − /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_BITS) in free_node | |
| 596 | + /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_DEPTH) in free_node | |
| 597 | 597 | * if something goes wrong. |
| 598 | 598 | */ |
| 599 | − for (i = 0; i < MAX_ALLOWEDIPS_BITS; ++i) { | |
| 600 | − part = cpu_to_be64(~(1LLU << (i % 64))); | |
| 601 | − memset(&ip, 0xff, 16); | |
| 602 | − memcpy((u8 *)&ip + (i < 64) * 8, &part, 8); | |
| 599 | + for (i = 0; i < 64; ++i) { | |
| 600 | + part = cpu_to_be64(~0LLU << i); | |
| 601 | + memset(&ip, 0xff, 8); | |
| 602 | + memcpy((u8 *)&ip + 8, &part, 8); | |
| 603 | + wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex); | |
| 604 | + memcpy(&ip, &part, 8); | |
| 605 | + memset((u8 *)&ip + 8, 0, 8); | |
| 603 | 606 | wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex); |
| 604 | 607 | } |
| 605 | − | |
| 608 | + memset(&ip, 0, 16); | |
| 609 | + wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex); | |
| 606 | 610 | wg_allowedips_free(&t, &mutex); |
| 607 | 611 | |
| 608 | 612 | wg_allowedips_init(&t); |
| @@ -376,7 +376,6 @@ static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab) · 375 unmodified lines | ||
| 376 | 376 | struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; |
| 377 | 377 | |
| 378 | 378 | if (!irq_grp->napi_enabled) { |
| 379 | − dev_set_threaded(&irq_grp->napi_ndev, true); | |
| 380 | 379 | napi_enable(&irq_grp->napi); |
| 381 | 380 | irq_grp->napi_enabled = true; |
| 382 | 381 | } |
| @@ -466,7 +466,6 @@ void ath11k_pcic_ext_irq_enable(struct ath11k_base *ab) · 465 unmodified lines | ||
| 466 | 466 | struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; |
| 467 | 467 | |
| 468 | 468 | if (!irq_grp->napi_enabled) { |
| 469 | − dev_set_threaded(&irq_grp->napi_ndev, true); | |
| 470 | 469 | napi_enable(&irq_grp->napi); |
| 471 | 470 | irq_grp->napi_enabled = true; |
| 472 | 471 | } |
| @@ -2144,8 +2144,7 @@ int ath12k_wmi_send_scan_start_cmd(struct ath12k *ar, · 2143 unmodified lines | ||
| 2144 | 2144 | struct wmi_tlv *tlv; |
| 2145 | 2145 | void *ptr; |
| 2146 | 2146 | int i, ret, len; |
| 2147 | − u32 *tmp_ptr; | |
| 2148 | − u8 extraie_len_with_pad = 0; | |
| 2147 | + u32 *tmp_ptr, extraie_len_with_pad = 0; | |
| 2149 | 2148 | struct ath12k_wmi_hint_short_ssid_arg *s_ssid = NULL; |
| 2150 | 2149 | struct ath12k_wmi_hint_bssid_arg *hint_bssid = NULL; |
| 2151 | 2150 | |
| @@ -36,11 +36,6 @@ ath6kl_core-y += wmi.o · 35 unmodified lines | ||
| 36 | 36 | ath6kl_core-y += core.o |
| 37 | 37 | ath6kl_core-y += recovery.o |
| 38 | 38 | |
| 39 | −# FIXME: temporarily silence -Wdangling-pointer on non W=1+ builds | |
| 40 | −ifndef KBUILD_EXTRA_WARN | |
| 41 | −CFLAGS_htc_mbox.o += $(call cc-disable-warning, dangling-pointer) | |
| 42 | −endif | |
| 43 | − | |
| 44 | 39 | ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o |
| 45 | 40 | ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o |
| 46 | 41 | |
| @@ -1456,6 +1456,10 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, · 1455 unmodified lines | ||
| 1456 | 1456 | params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE; |
| 1457 | 1457 | params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE; |
| 1458 | 1458 | params_v1 = kzalloc(params_size, GFP_KERNEL); |
| 1459 | + if (!params_v1) { | |
| 1460 | + err = -ENOMEM; | |
| 1461 | + goto exit_params; | |
| 1462 | + } | |
| 1459 | 1463 | params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); |
| 1460 | 1464 | brcmf_scan_params_v2_to_v1(¶ms->params_v2_le, ¶ms_v1->params_le); |
| 1461 | 1465 | kfree(params); |
| @@ -1473,6 +1477,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, · 11 unmodified lines | ||
| 1473 | 1477 | bphy_err(drvr, "error (%d)\n", err); |
| 1474 | 1478 | } |
| 1475 | 1479 | |
| 1480 | +exit_params: | |
| 1476 | 1481 | kfree(params); |
| 1477 | 1482 | exit: |
| 1478 | 1483 | return err; |
| @@ -398,7 +398,12 @@ struct brcmf_scan_params_le { · 397 unmodified lines | ||
| 398 | 398 | * fixed parameter portion is assumed, otherwise |
| 399 | 399 | * ssid in the fixed portion is ignored |
| 400 | 400 | */ |
| 401 | − __le16 channel_list[1]; /* list of chanspecs */ | |
| 401 | + union { | |
| 402 | + __le16 padding; /* Reserve space for at least 1 entry for abort | |
| 403 | + * which uses an on stack brcmf_scan_params_le | |
| 404 | + */ | |
| 405 | + DECLARE_FLEX_ARRAY(__le16, channel_list); /* chanspecs */ | |
| 406 | + }; | |
| 402 | 407 | }; |
| 403 | 408 | |
| 404 | 409 | struct brcmf_scan_params_v2_le { |
| @@ -577,7 +577,7 @@ struct tx_msg { · 576 unmodified lines | ||
| 577 | 577 | struct tib_structure tib; |
| 578 | 578 | struct phy_header phy; |
| 579 | 579 | struct mac_header mac; |
| 580 | − UCHAR var[1]; | |
| 580 | + UCHAR var[]; | |
| 581 | 581 | }; |
| 582 | 582 | |
| 583 | 583 | /****** ECF Receive Control Structure (RCS) Area at Shared RAM offset 0x0800 */ |
| @@ -128,12 +128,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev) · 127 unmodified lines | ||
| 128 | 128 | case MT_EE_5GHZ: |
| 129 | 129 | dev->mphy.cap.has_5ghz = true; |
| 130 | 130 | break; |
| 131 | − case MT_EE_2GHZ: | |
| 132 | − dev->mphy.cap.has_2ghz = true; | |
| 133 | − break; | |
| 134 | 131 | case MT_EE_DBDC: |
| 135 | 132 | dev->dbdc_support = true; |
| 136 | 133 | fallthrough; |
| 134 | + case MT_EE_2GHZ: | |
| 135 | + dev->mphy.cap.has_2ghz = true; | |
| 136 | + break; | |
| 137 | 137 | default: |
| 138 | 138 | dev->mphy.cap.has_2ghz = true; |
| 139 | 139 | dev->mphy.cap.has_5ghz = true; |
| @@ -2524,7 +2524,7 @@ static int cmac_dma_init(struct rtw89_dev *rtwdev, u8 mac_idx) · 2523 unmodified lines | ||
| 2524 | 2524 | u32 reg; |
| 2525 | 2525 | int ret; |
| 2526 | 2526 | |
| 2527 | − if (chip_id != RTL8852A && chip_id != RTL8852B) | |
| 2527 | + if (chip_id != RTL8852B) | |
| 2528 | 2528 | return 0; |
| 2529 | 2529 | |
| 2530 | 2530 | ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); |
| @@ -396,7 +396,7 @@ static void xenvif_get_requests(struct xenvif_queue *queue, · 395 unmodified lines | ||
| 396 | 396 | struct gnttab_map_grant_ref *gop = queue->tx_map_ops + *map_ops; |
| 397 | 397 | struct xen_netif_tx_request *txp = first; |
| 398 | 398 | |
| 399 | − nr_slots = shinfo->nr_frags + 1; | |
| 399 | + nr_slots = shinfo->nr_frags + frag_overflow + 1; | |
| 400 | 400 | |
| 401 | 401 | copy_count(skb) = 0; |
| 402 | 402 | XENVIF_TX_CB(skb)->split_mask = 0; |
| @@ -462,8 +462,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue, · 59 unmodified lines | ||
| 462 | 462 | } |
| 463 | 463 | } |
| 464 | 464 | |
| 465 | − for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; | |
| 466 | − shinfo->nr_frags++, gop++) { | |
| 465 | + for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS; | |
| 466 | + shinfo->nr_frags++, gop++, nr_slots--) { | |
| 467 | 467 | index = pending_index(queue->pending_cons++); |
| 468 | 468 | pending_idx = queue->pending_ring[index]; |
| 469 | 469 | xenvif_tx_create_map_op(queue, pending_idx, txp, |
| @@ -476,12 +476,12 @@ static void xenvif_get_requests(struct xenvif_queue *queue, · 6 unmodified lines | ||
| 476 | 476 | txp++; |
| 477 | 477 | } |
| 478 | 478 | |
| 479 | − if (frag_overflow) { | |
| 479 | + if (nr_slots > 0) { | |
| 480 | 480 | |
| 481 | 481 | shinfo = skb_shinfo(nskb); |
| 482 | 482 | frags = shinfo->frags; |
| 483 | 483 | |
| 484 | − for (shinfo->nr_frags = 0; shinfo->nr_frags < frag_overflow; | |
| 484 | + for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; | |
| 485 | 485 | shinfo->nr_frags++, txp++, gop++) { |
| 486 | 486 | index = pending_index(queue->pending_cons++); |
| 487 | 487 | pending_idx = queue->pending_ring[index]; |
| @@ -492,6 +492,11 @@ static void xenvif_get_requests(struct xenvif_queue *queue, · 4 unmodified lines | ||
| 492 | 492 | } |
| 493 | 493 | |
| 494 | 494 | skb_shinfo(skb)->frag_list = nskb; |
| 495 | + } else if (nskb) { | |
| 496 | + /* A frag_list skb was allocated but it is no longer needed | |
| 497 | + * because enough slots were converted to copy ops above. | |
| 498 | + */ | |
| 499 | + kfree_skb(nskb); | |
| 495 | 500 | } |
| 496 | 501 | |
| 497 | 502 | (*copy_ops) = cop - queue->tx_copy_ops; |
| @@ -3933,6 +3933,12 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl) · 3932 unmodified lines | ||
| 3933 | 3933 | */ |
| 3934 | 3934 | nvme_mpath_clear_ctrl_paths(ctrl); |
| 3935 | 3935 | |
| 3936 | + /* | |
| 3937 | + * Unquiesce io queues so any pending IO won't hang, especially | |
| 3938 | + * those submitted from scan work | |
| 3939 | + */ | |
| 3940 | + nvme_unquiesce_io_queues(ctrl); | |
| 3941 | + | |
| 3936 | 3942 | /* prevent racing with ns scanning */ |
| 3937 | 3943 | flush_work(&ctrl->scan_work); |
| 3938 | 3944 | |
| @@ -3942,10 +3948,8 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl) · 3 unmodified lines | ||
| 3942 | 3948 | * removing the namespaces' disks; fail all the queues now to avoid |
| 3943 | 3949 | * potentially having to clean up the failed sync later. |
| 3944 | 3950 | */ |
| 3945 | − if (ctrl->state == NVME_CTRL_DEAD) { | |
| 3951 | + if (ctrl->state == NVME_CTRL_DEAD) | |
| 3946 | 3952 | nvme_mark_namespaces_dead(ctrl); |
| 3947 | − nvme_unquiesce_io_queues(ctrl); | |
| 3948 | − } | |
| 3949 | 3953 | |
| 3950 | 3954 | /* this is a no-op when called from the controller reset handler */ |
| 3951 | 3955 | nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING_NOIO); |
| @@ -786,11 +786,9 @@ int nvme_ns_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd, · 785 unmodified lines | ||
| 786 | 786 | if (!(ioucmd->flags & IORING_URING_CMD_POLLED)) |
| 787 | 787 | return 0; |
| 788 | 788 | |
| 789 | − rcu_read_lock(); | |
| 790 | 789 | req = READ_ONCE(ioucmd->cookie); |
| 791 | 790 | if (req && blk_rq_is_poll(req)) |
| 792 | 791 | ret = blk_rq_poll(req, iob, poll_flags); |
| 793 | − rcu_read_unlock(); | |
| 794 | 792 | return ret; |
| 795 | 793 | } |
| 796 | 794 | #ifdef CONFIG_NVME_MULTIPATH |
| @@ -3402,7 +3402,8 @@ static const struct pci_device_id nvme_id_table[] = { · 3401 unmodified lines | ||
| 3402 | 3402 | { PCI_DEVICE(0x1d97, 0x2263), /* SPCC */ |
| 3403 | 3403 | .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, |
| 3404 | 3404 | { PCI_DEVICE(0x144d, 0xa80b), /* Samsung PM9B1 256G and 512G */ |
| 3405 | − .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, | |
| 3405 | + .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES | | |
| 3406 | + NVME_QUIRK_BOGUS_NID, }, | |
| 3406 | 3407 | { PCI_DEVICE(0x144d, 0xa809), /* Samsung MZALQ256HBJD 256G */ |
| 3407 | 3408 | .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, |
| 3408 | 3409 | { PCI_DEVICE(0x144d, 0xa802), /* Samsung SM953 */ |
| @@ -883,6 +883,7 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new) · 882 unmodified lines | ||
| 883 | 883 | goto out_cleanup_tagset; |
| 884 | 884 | |
| 885 | 885 | if (!new) { |
| 886 | + nvme_start_freeze(&ctrl->ctrl); | |
| 886 | 887 | nvme_unquiesce_io_queues(&ctrl->ctrl); |
| 887 | 888 | if (!nvme_wait_freeze_timeout(&ctrl->ctrl, NVME_IO_TIMEOUT)) { |
| 888 | 889 | /* |
| @@ -891,6 +892,7 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new) · 2 unmodified lines | ||
| 891 | 892 | * to be safe. |
| 892 | 893 | */ |
| 893 | 894 | ret = -ENODEV; |
| 895 | + nvme_unfreeze(&ctrl->ctrl); | |
| 894 | 896 | goto out_wait_freeze_timed_out; |
| 895 | 897 | } |
| 896 | 898 | blk_mq_update_nr_hw_queues(ctrl->ctrl.tagset, |
| @@ -940,7 +942,6 @@ static void nvme_rdma_teardown_io_queues(struct nvme_rdma_ctrl *ctrl, · 43 unmodified lines | ||
| 940 | 942 | bool remove) |
| 941 | 943 | { |
| 942 | 944 | if (ctrl->ctrl.queue_count > 1) { |
| 943 | − nvme_start_freeze(&ctrl->ctrl); | |
| 944 | 945 | nvme_quiesce_io_queues(&ctrl->ctrl); |
| 945 | 946 | nvme_sync_io_queues(&ctrl->ctrl); |
| 946 | 947 | nvme_rdma_stop_io_queues(ctrl); |
| @@ -1868,6 +1868,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new) · 1867 unmodified lines | ||
| 1868 | 1868 | goto out_cleanup_connect_q; |
| 1869 | 1869 | |
| 1870 | 1870 | if (!new) { |
| 1871 | + nvme_start_freeze(ctrl); | |
| 1871 | 1872 | nvme_unquiesce_io_queues(ctrl); |
| 1872 | 1873 | if (!nvme_wait_freeze_timeout(ctrl, NVME_IO_TIMEOUT)) { |
| 1873 | 1874 | /* |
| @@ -1876,6 +1877,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new) · 2 unmodified lines | ||
| 1876 | 1877 | * to be safe. |
| 1877 | 1878 | */ |
| 1878 | 1879 | ret = -ENODEV; |
| 1880 | + nvme_unfreeze(ctrl); | |
| 1879 | 1881 | goto out_wait_freeze_timed_out; |
| 1880 | 1882 | } |
| 1881 | 1883 | blk_mq_update_nr_hw_queues(ctrl->tagset, |
| @@ -1980,7 +1982,6 @@ static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl, · 98 unmodified lines | ||
| 1980 | 1982 | if (ctrl->queue_count <= 1) |
| 1981 | 1983 | return; |
| 1982 | 1984 | nvme_quiesce_admin_queue(ctrl); |
| 1983 | − nvme_start_freeze(ctrl); | |
| 1984 | 1985 | nvme_quiesce_io_queues(ctrl); |
| 1985 | 1986 | nvme_sync_io_queues(ctrl); |
| 1986 | 1987 | nvme_tcp_stop_io_queues(ctrl); |
| @@ -121,6 +121,8 @@ module_param(sba_reserve_agpgart, int, 0444); · 120 unmodified lines | ||
| 121 | 121 | MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART"); |
| 122 | 122 | #endif |
| 123 | 123 | |
| 124 | +struct proc_dir_entry *proc_runway_root __ro_after_init; | |
| 125 | +struct proc_dir_entry *proc_mckinley_root __ro_after_init; | |
| 124 | 126 | |
| 125 | 127 | /************************************ |
| 126 | 128 | ** SBA register read and write support |
| @@ -1968,11 +1970,15 @@ static int __init sba_driver_callback(struct parisc_device *dev) · 1841 unmodified lines | ||
| 1968 | 1970 | #ifdef CONFIG_PROC_FS |
| 1969 | 1971 | switch (dev->id.hversion) { |
| 1970 | 1972 | case PLUTO_MCKINLEY_PORT: |
| 1973 | + if (!proc_mckinley_root) | |
| 1974 | + proc_mckinley_root = proc_mkdir("bus/mckinley", NULL); | |
| 1971 | 1975 | root = proc_mckinley_root; |
| 1972 | 1976 | break; |
| 1973 | 1977 | case ASTRO_RUNWAY_PORT: |
| 1974 | 1978 | case IKE_MERCED_PORT: |
| 1975 | 1979 | default: |
| 1980 | + if (!proc_runway_root) | |
| 1981 | + proc_runway_root = proc_mkdir("bus/runway", NULL); | |
| 1976 | 1982 | root = proc_runway_root; |
| 1977 | 1983 | break; |
| 1978 | 1984 | } |
| @@ -28,7 +28,6 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <linux/sysctl.h> |
| 29 | 29 | |
| 30 | 30 | #include <asm/io.h> |
| 31 | −#include <asm/dma.h> | |
| 32 | 31 | #include <linux/uaccess.h> |
| 33 | 32 | #include <asm/superio.h> |
| 34 | 33 | |
| @@ -226,9 +225,9 @@ static int parport_PS2_supported(struct parport *pb) · 191 unmodified lines | ||
| 226 | 225 | |
| 227 | 226 | /* --- Initialisation code -------------------------------- */ |
| 228 | 227 | |
| 229 | −struct parport *parport_gsc_probe_port(unsigned long base, | |
| 228 | +static struct parport *parport_gsc_probe_port(unsigned long base, | |
| 230 | 229 | unsigned long base_hi, int irq, |
| 231 | − int dma, struct parisc_device *padev) | |
| 230 | + struct parisc_device *padev) | |
| 232 | 231 | { |
| 233 | 232 | struct parport_gsc_private *priv; |
| 234 | 233 | struct parport_operations *ops; |
| @@ -250,12 +249,9 @@ struct parport *parport_gsc_probe_port(unsigned long base, · 15 unmodified lines | ||
| 250 | 249 | } |
| 251 | 250 | priv->ctr = 0xc; |
| 252 | 251 | priv->ctr_writable = 0xff; |
| 253 | − priv->dma_buf = NULL; | |
| 254 | − priv->dma_handle = 0; | |
| 255 | 252 | p->base = base; |
| 256 | 253 | p->base_hi = base_hi; |
| 257 | 254 | p->irq = irq; |
| 258 | − p->dma = dma; | |
| 259 | 255 | p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; |
| 260 | 256 | p->ops = ops; |
| 261 | 257 | p->private_data = priv; |
| @@ -286,17 +282,9 @@ struct parport *parport_gsc_probe_port(unsigned long base, · 24 unmodified lines | ||
| 286 | 282 | if (p->irq == PARPORT_IRQ_AUTO) { |
| 287 | 283 | p->irq = PARPORT_IRQ_NONE; |
| 288 | 284 | } |
| 289 | − if (p->irq != PARPORT_IRQ_NONE) { | |
| 285 | + if (p->irq != PARPORT_IRQ_NONE) | |
| 290 | 286 | pr_cont(", irq %d", p->irq); |
| 291 | 287 | |
| 292 | − if (p->dma == PARPORT_DMA_AUTO) { | |
| 293 | − p->dma = PARPORT_DMA_NONE; | |
| 294 | − } | |
| 295 | − } | |
| 296 | − if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq | |
| 297 | − is mandatory (see above) */ | |
| 298 | − p->dma = PARPORT_DMA_NONE; | |
| 299 | − | |
| 300 | 288 | pr_cont(" ["); |
| 301 | 289 | #define printmode(x) \ |
| 302 | 290 | do { \ |
| @@ -321,7 +309,6 @@ do { \ · 18 unmodified lines | ||
| 321 | 309 | pr_warn("%s: irq %d in use, resorting to polled operation\n", |
| 322 | 310 | p->name, p->irq); |
| 323 | 311 | p->irq = PARPORT_IRQ_NONE; |
| 324 | − p->dma = PARPORT_DMA_NONE; | |
| 325 | 312 | } |
| 326 | 313 | } |
| 327 | 314 | |
| @@ -369,8 +356,7 @@ static int __init parport_init_chip(struct parisc_device *dev) · 41 unmodified lines | ||
| 369 | 356 | pr_info("%s: enhanced parport-modes not supported\n", __func__); |
| 370 | 357 | } |
| 371 | 358 | |
| 372 | − p = parport_gsc_probe_port(port, 0, dev->irq, | |
| 373 | − /* PARPORT_IRQ_NONE */ PARPORT_DMA_NONE, dev); | |
| 359 | + p = parport_gsc_probe_port(port, 0, dev->irq, dev); | |
| 374 | 360 | if (p) |
| 375 | 361 | parport_count++; |
| 376 | 362 | dev_set_drvdata(&dev->dev, p); |
| @@ -382,16 +368,10 @@ static void __exit parport_remove_chip(struct parisc_device *dev) · 5 unmodified lines | ||
| 382 | 368 | { |
| 383 | 369 | struct parport *p = dev_get_drvdata(&dev->dev); |
| 384 | 370 | if (p) { |
| 385 | − struct parport_gsc_private *priv = p->private_data; | |
| 386 | 371 | struct parport_operations *ops = p->ops; |
| 387 | 372 | parport_remove_port(p); |
| 388 | − if (p->dma != PARPORT_DMA_NONE) | |
| 389 | − free_dma(p->dma); | |
| 390 | 373 | if (p->irq != PARPORT_IRQ_NONE) |
| 391 | 374 | free_irq(p->irq, p); |
| 392 | − if (priv->dma_buf) | |
| 393 | − dma_free_coherent(&priv->dev->dev, PAGE_SIZE, | |
| 394 | − priv->dma_buf, priv->dma_handle); | |
| 395 | 375 | kfree (p->private_data); |
| 396 | 376 | parport_put_port(p); |
| 397 | 377 | kfree (ops); /* hope no-one cached it */ |
| @@ -63,8 +63,6 @@ struct parport_gsc_private { · 62 unmodified lines | ||
| 63 | 63 | int writeIntrThreshold; |
| 64 | 64 | |
| 65 | 65 | /* buffer suitable for DMA, if DMA enabled */ |
| 66 | − char *dma_buf; | |
| 67 | − dma_addr_t dma_handle; | |
| 68 | 66 | struct pci_dev *dev; |
| 69 | 67 | }; |
| 70 | 68 | |
| @@ -199,9 +197,4 @@ extern void parport_gsc_inc_use_count(void); · 128 unmodified lines | ||
| 199 | 197 | |
| 200 | 198 | extern void parport_gsc_dec_use_count(void); |
| 201 | 199 | |
| 202 | −extern struct parport *parport_gsc_probe_port(unsigned long base, | |
| 203 | − unsigned long base_hi, | |
| 204 | − int irq, int dma, | |
| 205 | − struct parisc_device *padev); | |
| 206 | − | |
| 207 | 200 | #endif /* __DRIVERS_PARPORT_PARPORT_GSC_H */ |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/pci.h> |
| 12 | 12 | #include <linux/errno.h> |
| 13 | 13 | #include <linux/ioport.h> |
| 14 | +#include <linux/of.h> | |
| 14 | 15 | #include <linux/proc_fs.h> |
| 15 | 16 | #include <linux/slab.h> |
| 16 | 17 | |
| @@ -332,6 +333,7 @@ void __weak pcibios_bus_add_device(struct pci_dev *pdev) { } · 315 unmodified lines | ||
| 332 | 333 | */ |
| 333 | 334 | void pci_bus_add_device(struct pci_dev *dev) |
| 334 | 335 | { |
| 336 | + struct device_node *dn = dev->dev.of_node; | |
| 335 | 337 | int retval; |
| 336 | 338 | |
| 337 | 339 | /* |
| @@ -344,7 +346,7 @@ void pci_bus_add_device(struct pci_dev *dev) · 6 unmodified lines | ||
| 344 | 346 | pci_proc_attach_device(dev); |
| 345 | 347 | pci_bridge_d3_update(dev); |
| 346 | 348 | |
| 347 | − dev->match_driver = true; | |
| 349 | + dev->match_driver = !dn || of_device_is_available(dn); | |
| 348 | 350 | retval = device_attach(&dev->dev); |
| 349 | 351 | if (retval < 0 && retval != -EPROBE_DEFER) |
| 350 | 352 | pci_warn(dev, "device attach failed (%d)\n", retval); |
| @@ -179,7 +179,6 @@ config PCI_MVEBU · 178 unmodified lines | ||
| 179 | 179 | depends on MVEBU_MBUS |
| 180 | 180 | depends on ARM |
| 181 | 181 | depends on OF |
| 182 | − depends on BROKEN | |
| 183 | 182 | select PCI_BRIDGE_EMUL |
| 184 | 183 | help |
| 185 | 184 | Add support for Marvell EBU PCIe controller. This PCIe controller |
| @@ -485,20 +485,15 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) · 484 unmodified lines | ||
| 485 | 485 | if (ret) |
| 486 | 486 | goto err_remove_edma; |
| 487 | 487 | |
| 488 | − if (dw_pcie_link_up(pci)) { | |
| 489 | − dw_pcie_print_link_status(pci); | |
| 490 | − } else { | |
| 488 | + if (!dw_pcie_link_up(pci)) { | |
| 491 | 489 | ret = dw_pcie_start_link(pci); |
| 492 | 490 | if (ret) |
| 493 | 491 | goto err_remove_edma; |
| 494 | − | |
| 495 | − if (pci->ops && pci->ops->start_link) { | |
| 496 | − ret = dw_pcie_wait_for_link(pci); | |
| 497 | − if (ret) | |
| 498 | − goto err_stop_link; | |
| 499 | − } | |
| 500 | 492 | } |
| 501 | 493 | |
| 494 | + /* Ignore errors, the link may come up later */ | |
| 495 | + dw_pcie_wait_for_link(pci); | |
| 496 | + | |
| 502 | 497 | bridge->sysdata = pp; |
| 503 | 498 | |
| 504 | 499 | ret = pci_host_probe(bridge); |
| @@ -644,20 +644,9 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index) · 643 unmodified lines | ||
| 644 | 644 | dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0); |
| 645 | 645 | } |
| 646 | 646 | |
| 647 | −void dw_pcie_print_link_status(struct dw_pcie *pci) | |
| 648 | −{ | |
| 649 | − u32 offset, val; | |
| 650 | − | |
| 651 | − offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); | |
| 652 | − val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); | |
| 653 | − | |
| 654 | − dev_info(pci->dev, "PCIe Gen.%u x%u link up\n", | |
| 655 | − FIELD_GET(PCI_EXP_LNKSTA_CLS, val), | |
| 656 | − FIELD_GET(PCI_EXP_LNKSTA_NLW, val)); | |
| 657 | −} | |
| 658 | − | |
| 659 | 647 | int dw_pcie_wait_for_link(struct dw_pcie *pci) |
| 660 | 648 | { |
| 649 | + u32 offset, val; | |
| 661 | 650 | int retries; |
| 662 | 651 | |
| 663 | 652 | /* Check if the link is up or not */ |
| @@ -673,7 +662,12 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci) · 9 unmodified lines | ||
| 673 | 662 | return -ETIMEDOUT; |
| 674 | 663 | } |
| 675 | 664 | |
| 676 | − dw_pcie_print_link_status(pci); | |
| 665 | + offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); | |
| 666 | + val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); | |
| 667 | + | |
| 668 | + dev_info(pci->dev, "PCIe Gen.%u x%u link up\n", | |
| 669 | + FIELD_GET(PCI_EXP_LNKSTA_CLS, val), | |
| 670 | + FIELD_GET(PCI_EXP_LNKSTA_NLW, val)); | |
| 677 | 671 | |
| 678 | 672 | return 0; |
| 679 | 673 | } |
| @@ -429,7 +429,6 @@ void dw_pcie_setup(struct dw_pcie *pci); · 428 unmodified lines | ||
| 429 | 429 | void dw_pcie_iatu_detect(struct dw_pcie *pci); |
| 430 | 430 | int dw_pcie_edma_detect(struct dw_pcie *pci); |
| 431 | 431 | void dw_pcie_edma_remove(struct dw_pcie *pci); |
| 432 | −void dw_pcie_print_link_status(struct dw_pcie *pci); | |
| 433 | 432 | |
| 434 | 433 | static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val) |
| 435 | 434 | { |
| @@ -498,6 +498,7 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge) · 497 unmodified lines | ||
| 498 | 498 | acpiphp_native_scan_bridge(dev); |
| 499 | 499 | } |
| 500 | 500 | } else { |
| 501 | + LIST_HEAD(add_list); | |
| 501 | 502 | int max, pass; |
| 502 | 503 | |
| 503 | 504 | acpiphp_rescan_slot(slot); |
| @@ -511,10 +512,15 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge) · 7 unmodified lines | ||
| 511 | 512 | if (pass && dev->subordinate) { |
| 512 | 513 | check_hotplug_bridge(slot, dev); |
| 513 | 514 | pcibios_resource_survey_bus(dev->subordinate); |
| 515 | + if (pci_is_root_bus(bus)) | |
| 516 | + __pci_bus_size_bridges(dev->subordinate, &add_list); | |
| 514 | 517 | } |
| 515 | 518 | } |
| 516 | 519 | } |
| 517 | − pci_assign_unassigned_bridge_resources(bus->self); | |
| 520 | + if (pci_is_root_bus(bus)) | |
| 521 | + __pci_bus_assign_resources(bus, &add_list, NULL); | |
| 522 | + else | |
| 523 | + pci_assign_unassigned_bridge_resources(bus->self); | |
| 518 | 524 | } |
| 519 | 525 | |
| 520 | 526 | acpiphp_sanitize_bus(bus); |
| @@ -34,11 +34,6 @@ int pci_set_of_node(struct pci_dev *dev) · 33 unmodified lines | ||
| 34 | 34 | if (!node) |
| 35 | 35 | return 0; |
| 36 | 36 | |
| 37 | − if (!of_device_is_available(node)) { | |
| 38 | − of_node_put(node); | |
| 39 | − return -ENODEV; | |
| 40 | − } | |
| 41 | − | |
| 42 | 37 | device_set_node(&dev->dev, of_fwnode_handle(node)); |
| 43 | 38 | return 0; |
| 44 | 39 | } |
| @@ -176,7 +176,8 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf) · 175 unmodified lines | ||
| 176 | 176 | |
| 177 | 177 | int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev) |
| 178 | 178 | { |
| 179 | − u8 mode, flag = 0; | |
| 179 | + u8 flag = 0; | |
| 180 | + int mode; | |
| 180 | 181 | int src; |
| 181 | 182 | |
| 182 | 183 | mode = amd_pmf_get_pprof_modes(dev); |
| @@ -335,8 +335,8 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn · 334 unmodified lines | ||
| 335 | 335 | |
| 336 | 336 | node = dev_to_node(&_pci_dev->dev); |
| 337 | 337 | if (node == NUMA_NO_NODE) { |
| 338 | − pr_info("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n", | |
| 339 | − cpu, bus_no, dev, fn); | |
| 338 | + pr_info_once("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n", | |
| 339 | + cpu, bus_no, dev, fn); | |
| 340 | 340 | continue; |
| 341 | 341 | } |
| 342 | 342 | |
| @@ -24,6 +24,10 @@ static bool ec_trigger __read_mostly; · 23 unmodified lines | ||
| 24 | 24 | module_param(ec_trigger, bool, 0444); |
| 25 | 25 | MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events"); |
| 26 | 26 | |
| 27 | +static bool force; | |
| 28 | +module_param(force, bool, 0444); | |
| 29 | +MODULE_PARM_DESC(force, "Force loading on boards without a convertible DMI chassis-type"); | |
| 30 | + | |
| 27 | 31 | static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = { |
| 28 | 32 | { |
| 29 | 33 | /* Lenovo Yoga 7 14ARB7 */ |
| @@ -35,6 +39,20 @@ static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = { · 5 unmodified lines | ||
| 35 | 39 | { } |
| 36 | 40 | }; |
| 37 | 41 | |
| 42 | +static const struct dmi_system_id allowed_chasis_types_dmi_table[] = { | |
| 43 | + { | |
| 44 | + .matches = { | |
| 45 | + DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31" /* Convertible */), | |
| 46 | + }, | |
| 47 | + }, | |
| 48 | + { | |
| 49 | + .matches = { | |
| 50 | + DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32" /* Detachable */), | |
| 51 | + }, | |
| 52 | + }, | |
| 53 | + { } | |
| 54 | +}; | |
| 55 | + | |
| 38 | 56 | struct lenovo_ymc_private { |
| 39 | 57 | struct input_dev *input_dev; |
| 40 | 58 | struct acpi_device *ec_acpi_dev; |
| @@ -111,6 +129,13 @@ static int lenovo_ymc_probe(struct wmi_device *wdev, const void *ctx) · 70 unmodified lines | ||
| 111 | 129 | struct input_dev *input_dev; |
| 112 | 130 | int err; |
| 113 | 131 | |
| 132 | + if (!dmi_check_system(allowed_chasis_types_dmi_table)) { | |
| 133 | + if (force) | |
| 134 | + dev_info(&wdev->dev, "Force loading Lenovo YMC support\n"); | |
| 135 | + else | |
| 136 | + return -ENODEV; | |
| 137 | + } | |
| 138 | + | |
| 114 | 139 | ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table); |
| 115 | 140 | |
| 116 | 141 | priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL); |
| @@ -62,10 +62,6 @@ · 61 unmodified lines | ||
| 62 | 62 | #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 |
| 63 | 63 | #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a |
| 64 | 64 | #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b |
| 65 | −#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0x3c | |
| 66 | −#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0x3d | |
| 67 | −#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0x3e | |
| 68 | −#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0x3f | |
| 69 | 65 | #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 |
| 70 | 66 | #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 |
| 71 | 67 | #define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET 0x42 |
| @@ -126,6 +122,10 @@ · 54 unmodified lines | ||
| 126 | 122 | #define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa |
| 127 | 123 | #define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab |
| 128 | 124 | #define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON 0xb2 |
| 125 | +#define MLXPLAT_CPLD_LPC_REG_DBG1_OFFSET 0xb6 | |
| 126 | +#define MLXPLAT_CPLD_LPC_REG_DBG2_OFFSET 0xb7 | |
| 127 | +#define MLXPLAT_CPLD_LPC_REG_DBG3_OFFSET 0xb8 | |
| 128 | +#define MLXPLAT_CPLD_LPC_REG_DBG4_OFFSET 0xb9 | |
| 129 | 129 | #define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2 |
| 130 | 130 | #define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3 |
| 131 | 131 | #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7 |
| @@ -222,7 +222,7 @@ · 90 unmodified lines | ||
| 222 | 222 | MLXPLAT_CPLD_AGGR_MASK_LC_SDWN) |
| 223 | 223 | #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1 |
| 224 | 224 | #define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2 BIT(2) |
| 225 | −#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT BIT(4) | |
| 225 | +#define MLXPLAT_CPLD_LOW_AGGR_MASK_PWR_BUT GENMASK(5, 4) | |
| 226 | 226 | #define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6) |
| 227 | 227 | #define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0) |
| 228 | 228 | #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) |
| @@ -237,7 +237,7 @@ · 8 unmodified lines | ||
| 237 | 237 | #define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0) |
| 238 | 238 | #define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0) |
| 239 | 239 | #define MLXPLAT_CPLD_PWR_BUTTON_MASK BIT(0) |
| 240 | −#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(5) | |
| 240 | +#define MLXPLAT_CPLD_LATCH_RST_MASK BIT(6) | |
| 241 | 241 | #define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3) |
| 242 | 242 | #define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4) |
| 243 | 243 | #define MLXPLAT_CPLD_INTRUSION_MASK BIT(6) |
| @@ -2356,7 +2356,7 @@ mlxplat_mlxcpld_l1_switch_pwr_events_handler(void *handle, enum mlxreg_hotplug_k · 2112 unmodified lines | ||
| 2356 | 2356 | u8 action) |
| 2357 | 2357 | { |
| 2358 | 2358 | dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button"); |
| 2359 | − kernel_halt(); | |
| 2359 | + kernel_power_off(); | |
| 2360 | 2360 | return 0; |
| 2361 | 2361 | } |
| 2362 | 2362 | |
| @@ -2475,7 +2475,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = { · 112 unmodified lines | ||
| 2475 | 2475 | .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET, |
| 2476 | 2476 | .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK, |
| 2477 | 2477 | .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data), |
| 2478 | − .inversed = 0, | |
| 2478 | + .inversed = 1, | |
| 2479 | 2479 | .health = false, |
| 2480 | 2480 | }, |
| 2481 | 2481 | { |
| @@ -2484,7 +2484,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_l1_switch_events_items[] = { · 2 unmodified lines | ||
| 2484 | 2484 | .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, |
| 2485 | 2485 | .mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK, |
| 2486 | 2486 | .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data), |
| 2487 | − .inversed = 0, | |
| 2487 | + .inversed = 1, | |
| 2488 | 2488 | .health = false, |
| 2489 | 2489 | .ind = 8, |
| 2490 | 2490 | }, |
| @@ -3677,7 +3677,7 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_regs_io_data[] = { · 1186 unmodified lines | ||
| 3677 | 3677 | { |
| 3678 | 3678 | .label = "latch_reset", |
| 3679 | 3679 | .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, |
| 3680 | − .mask = GENMASK(7, 0) & ~BIT(5), | |
| 3680 | + .mask = GENMASK(7, 0) & ~BIT(6), | |
| 3681 | 3681 | .mode = 0200, |
| 3682 | 3682 | }, |
| 3683 | 3683 | { |
| @@ -6238,8 +6238,6 @@ static void mlxplat_i2c_mux_topolgy_exit(struct mlxplat_priv *priv) · 2554 unmodified lines | ||
| 6238 | 6238 | if (priv->pdev_mux[i]) |
| 6239 | 6239 | platform_device_unregister(priv->pdev_mux[i]); |
| 6240 | 6240 | } |
| 6241 | − | |
| 6242 | − mlxplat_post_exit(); | |
| 6243 | 6241 | } |
| 6244 | 6242 | |
| 6245 | 6243 | static int mlxplat_i2c_main_complition_notify(void *handle, int id) |
| @@ -6369,6 +6367,7 @@ static void __exit mlxplat_exit(void) · 123 unmodified lines | ||
| 6369 | 6367 | pm_power_off = NULL; |
| 6370 | 6368 | mlxplat_pre_exit(priv); |
| 6371 | 6369 | mlxplat_i2c_main_exit(priv); |
| 6370 | + mlxplat_post_exit(); | |
| 6372 | 6371 | } |
| 6373 | 6372 | module_exit(mlxplat_exit); |
| 6374 | 6373 | |
| @@ -27,15 +27,15 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/seq_file.h> |
| 28 | 28 | #include <linux/string.h> |
| 29 | 29 | |
| 30 | −static const char *const SM_ECO_NAME = "eco"; | |
| 31 | −static const char *const SM_COMFORT_NAME = "comfort"; | |
| 32 | −static const char *const SM_SPORT_NAME = "sport"; | |
| 33 | −static const char *const SM_TURBO_NAME = "turbo"; | |
| 34 | − | |
| 35 | −static const char *const FM_AUTO_NAME = "auto"; | |
| 36 | −static const char *const FM_SILENT_NAME = "silent"; | |
| 37 | −static const char *const FM_BASIC_NAME = "basic"; | |
| 38 | −static const char *const FM_ADVANCED_NAME = "advanced"; | |
| 30 | +#define SM_ECO_NAME "eco" | |
| 31 | +#define SM_COMFORT_NAME "comfort" | |
| 32 | +#define SM_SPORT_NAME "sport" | |
| 33 | +#define SM_TURBO_NAME "turbo" | |
| 34 | + | |
| 35 | +#define FM_AUTO_NAME "auto" | |
| 36 | +#define FM_SILENT_NAME "silent" | |
| 37 | +#define FM_BASIC_NAME "basic" | |
| 38 | +#define FM_ADVANCED_NAME "advanced" | |
| 39 | 39 | |
| 40 | 40 | static const char * const ALLOWED_FW_0[] __initconst = { |
| 41 | 41 | "14C1EMS1.012", |
| @@ -329,6 +329,19 @@ static const struct smi_node cs35l41_hda = { · 328 unmodified lines | ||
| 329 | 329 | .bus_type = SMI_AUTO_DETECT, |
| 330 | 330 | }; |
| 331 | 331 | |
| 332 | +static const struct smi_node cs35l56_hda = { | |
| 333 | + .instances = { | |
| 334 | + { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 }, | |
| 335 | + { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 }, | |
| 336 | + { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 }, | |
| 337 | + { "cs35l56-hda", IRQ_RESOURCE_AUTO, 0 }, | |
| 338 | + /* a 5th entry is an alias address, not a real device */ | |
| 339 | + { "cs35l56-hda_dummy_dev" }, | |
| 340 | + {} | |
| 341 | + }, | |
| 342 | + .bus_type = SMI_AUTO_DETECT, | |
| 343 | +}; | |
| 344 | + | |
| 332 | 345 | /* |
| 333 | 346 | * Note new device-ids must also be added to ignore_serial_bus_ids in |
| 334 | 347 | * drivers/acpi/scan.c: acpi_device_enumeration_by_parent(). |
| @@ -337,6 +350,7 @@ static const struct acpi_device_id smi_acpi_ids[] = { · 2 unmodified lines | ||
| 337 | 350 | { "BSG1160", (unsigned long)&bsg1160_data }, |
| 338 | 351 | { "BSG2150", (unsigned long)&bsg2150_data }, |
| 339 | 352 | { "CSC3551", (unsigned long)&cs35l41_hda }, |
| 353 | + { "CSC3556", (unsigned long)&cs35l56_hda }, | |
| 340 | 354 | { "INT3515", (unsigned long)&int3515_data }, |
| 341 | 355 | /* Non-conforming _HID for Cirrus Logic already released */ |
| 342 | 356 | { "CLSA0100", (unsigned long)&cs35l41_hda }, |
| @@ -818,7 +818,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd, · 817 unmodified lines | ||
| 818 | 818 | return -EINVAL; |
| 819 | 819 | |
| 820 | 820 | ra.reg = rd->regs[rpi->id]; |
| 821 | − if (!ra.reg) | |
| 821 | + if (!ra.reg.val) | |
| 822 | 822 | return -EINVAL; |
| 823 | 823 | |
| 824 | 824 | /* non-hardware data are collected by the polling thread */ |
| @@ -830,7 +830,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd, · 5 unmodified lines | ||
| 830 | 830 | ra.mask = rpi->mask; |
| 831 | 831 | |
| 832 | 832 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { |
| 833 | − pr_debug("failed to read reg 0x%llx for %s:%s\n", ra.reg, rd->rp->name, rd->name); | |
| 833 | + pr_debug("failed to read reg 0x%llx for %s:%s\n", ra.reg.val, rd->rp->name, rd->name); | |
| 834 | 834 | return -EIO; |
| 835 | 835 | } |
| 836 | 836 | |
| @@ -920,7 +920,7 @@ static int rapl_check_unit_core(struct rapl_domain *rd) · 83 unmodified lines | ||
| 920 | 920 | ra.mask = ~0; |
| 921 | 921 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { |
| 922 | 922 | pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n", |
| 923 | − ra.reg, rd->rp->name, rd->name); | |
| 923 | + ra.reg.val, rd->rp->name, rd->name); | |
| 924 | 924 | return -ENODEV; |
| 925 | 925 | } |
| 926 | 926 | |
| @@ -948,7 +948,7 @@ static int rapl_check_unit_atom(struct rapl_domain *rd) · 21 unmodified lines | ||
| 948 | 948 | ra.mask = ~0; |
| 949 | 949 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { |
| 950 | 950 | pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n", |
| 951 | − ra.reg, rd->rp->name, rd->name); | |
| 951 | + ra.reg.val, rd->rp->name, rd->name); | |
| 952 | 952 | return -ENODEV; |
| 953 | 953 | } |
| 954 | 954 | |
| @@ -1135,7 +1135,7 @@ static int rapl_check_unit_tpmi(struct rapl_domain *rd) · 180 unmodified lines | ||
| 1135 | 1135 | ra.mask = ~0; |
| 1136 | 1136 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { |
| 1137 | 1137 | pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n", |
| 1138 | − ra.reg, rd->rp->name, rd->name); | |
| 1138 | + ra.reg.val, rd->rp->name, rd->name); | |
| 1139 | 1139 | return -ENODEV; |
| 1140 | 1140 | } |
| 1141 | 1141 | |
| @@ -1411,8 +1411,8 @@ static int rapl_get_domain_unit(struct rapl_domain *rd) · 269 unmodified lines | ||
| 1411 | 1411 | struct rapl_defaults *defaults = get_defaults(rd->rp); |
| 1412 | 1412 | int ret; |
| 1413 | 1413 | |
| 1414 | − if (!rd->regs[RAPL_DOMAIN_REG_UNIT]) { | |
| 1415 | − if (!rd->rp->priv->reg_unit) { | |
| 1414 | + if (!rd->regs[RAPL_DOMAIN_REG_UNIT].val) { | |
| 1415 | + if (!rd->rp->priv->reg_unit.val) { | |
| 1416 | 1416 | pr_err("No valid Unit register found\n"); |
| 1417 | 1417 | return -ENODEV; |
| 1418 | 1418 | } |
| @@ -34,28 +34,32 @@ static struct rapl_if_priv *rapl_msr_priv; · 33 unmodified lines | ||
| 34 | 34 | |
| 35 | 35 | static struct rapl_if_priv rapl_msr_priv_intel = { |
| 36 | 36 | .type = RAPL_IF_MSR, |
| 37 | − .reg_unit = MSR_RAPL_POWER_UNIT, | |
| 38 | − .regs[RAPL_DOMAIN_PACKAGE] = { | |
| 39 | − MSR_PKG_POWER_LIMIT, MSR_PKG_ENERGY_STATUS, MSR_PKG_PERF_STATUS, 0, MSR_PKG_POWER_INFO }, | |
| 40 | − .regs[RAPL_DOMAIN_PP0] = { | |
| 41 | − MSR_PP0_POWER_LIMIT, MSR_PP0_ENERGY_STATUS, 0, MSR_PP0_POLICY, 0 }, | |
| 42 | − .regs[RAPL_DOMAIN_PP1] = { | |
| 43 | − MSR_PP1_POWER_LIMIT, MSR_PP1_ENERGY_STATUS, 0, MSR_PP1_POLICY, 0 }, | |
| 44 | − .regs[RAPL_DOMAIN_DRAM] = { | |
| 45 | − MSR_DRAM_POWER_LIMIT, MSR_DRAM_ENERGY_STATUS, MSR_DRAM_PERF_STATUS, 0, MSR_DRAM_POWER_INFO }, | |
| 46 | − .regs[RAPL_DOMAIN_PLATFORM] = { | |
| 47 | − MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0}, | |
| 37 | + .reg_unit.msr = MSR_RAPL_POWER_UNIT, | |
| 38 | + .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PKG_POWER_LIMIT, | |
| 39 | + .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr = MSR_PKG_ENERGY_STATUS, | |
| 40 | + .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PERF].msr = MSR_PKG_PERF_STATUS, | |
| 41 | + .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_INFO].msr = MSR_PKG_POWER_INFO, | |
| 42 | + .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PP0_POWER_LIMIT, | |
| 43 | + .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr = MSR_PP0_ENERGY_STATUS, | |
| 44 | + .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_POLICY].msr = MSR_PP0_POLICY, | |
| 45 | + .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PP1_POWER_LIMIT, | |
| 46 | + .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_STATUS].msr = MSR_PP1_ENERGY_STATUS, | |
| 47 | + .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_POLICY].msr = MSR_PP1_POLICY, | |
| 48 | + .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_LIMIT].msr = MSR_DRAM_POWER_LIMIT, | |
| 49 | + .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_STATUS].msr = MSR_DRAM_ENERGY_STATUS, | |
| 50 | + .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_PERF].msr = MSR_DRAM_PERF_STATUS, | |
| 51 | + .regs[RAPL_DOMAIN_DRAM][RAPL_DOMAIN_REG_INFO].msr = MSR_DRAM_POWER_INFO, | |
| 52 | + .regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PLATFORM_POWER_LIMIT, | |
| 53 | + .regs[RAPL_DOMAIN_PLATFORM][RAPL_DOMAIN_REG_STATUS].msr = MSR_PLATFORM_ENERGY_STATUS, | |
| 48 | 54 | .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2), |
| 49 | 55 | .limits[RAPL_DOMAIN_PLATFORM] = BIT(POWER_LIMIT2), |
| 50 | 56 | }; |
| 51 | 57 | |
| 52 | 58 | static struct rapl_if_priv rapl_msr_priv_amd = { |
| 53 | 59 | .type = RAPL_IF_MSR, |
| 54 | − .reg_unit = MSR_AMD_RAPL_POWER_UNIT, | |
| 55 | − .regs[RAPL_DOMAIN_PACKAGE] = { | |
| 56 | − 0, MSR_AMD_PKG_ENERGY_STATUS, 0, 0, 0 }, | |
| 57 | − .regs[RAPL_DOMAIN_PP0] = { | |
| 58 | − 0, MSR_AMD_CORE_ENERGY_STATUS, 0, 0, 0 }, | |
| 60 | + .reg_unit.msr = MSR_AMD_RAPL_POWER_UNIT, | |
| 61 | + .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr = MSR_AMD_PKG_ENERGY_STATUS, | |
| 62 | + .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr = MSR_AMD_CORE_ENERGY_STATUS, | |
| 59 | 63 | }; |
| 60 | 64 | |
| 61 | 65 | /* Handles CPU hotplug on multi-socket systems. |
| @@ -99,10 +103,8 @@ static int rapl_cpu_down_prep(unsigned int cpu) · 37 unmodified lines | ||
| 99 | 103 | |
| 100 | 104 | static int rapl_msr_read_raw(int cpu, struct reg_action *ra) |
| 101 | 105 | { |
| 102 | − u32 msr = (u32)ra->reg; | |
| 103 | − | |
| 104 | − if (rdmsrl_safe_on_cpu(cpu, msr, &ra->value)) { | |
| 105 | − pr_debug("failed to read msr 0x%x on cpu %d\n", msr, cpu); | |
| 106 | + if (rdmsrl_safe_on_cpu(cpu, ra->reg.msr, &ra->value)) { | |
| 107 | + pr_debug("failed to read msr 0x%x on cpu %d\n", ra->reg.msr, cpu); | |
| 106 | 108 | return -EIO; |
| 107 | 109 | } |
| 108 | 110 | ra->value &= ra->mask; |
| @@ -112,17 +114,16 @@ static int rapl_msr_read_raw(int cpu, struct reg_action *ra) · 3 unmodified lines | ||
| 112 | 114 | static void rapl_msr_update_func(void *info) |
| 113 | 115 | { |
| 114 | 116 | struct reg_action *ra = info; |
| 115 | − u32 msr = (u32)ra->reg; | |
| 116 | 117 | u64 val; |
| 117 | 118 | |
| 118 | − ra->err = rdmsrl_safe(msr, &val); | |
| 119 | + ra->err = rdmsrl_safe(ra->reg.msr, &val); | |
| 119 | 120 | if (ra->err) |
| 120 | 121 | return; |
| 121 | 122 | |
| 122 | 123 | val &= ~ra->mask; |
| 123 | 124 | val |= ra->value; |
| 124 | 125 | |
| 125 | − ra->err = wrmsrl_safe(msr, val); | |
| 126 | + ra->err = wrmsrl_safe(ra->reg.msr, val); | |
| 126 | 127 | } |
| 127 | 128 | |
| 128 | 129 | static int rapl_msr_write_raw(int cpu, struct reg_action *ra) |
| @@ -171,7 +172,7 @@ static int rapl_msr_probe(struct platform_device *pdev) · 42 unmodified lines | ||
| 171 | 172 | |
| 172 | 173 | if (id) { |
| 173 | 174 | rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] |= BIT(POWER_LIMIT4); |
| 174 | − rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] = | |
| 175 | + rapl_msr_priv->regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4].msr = | |
| 175 | 176 | MSR_VR_CURRENT_CONFIG; |
| 176 | 177 | pr_info("PL4 support detected.\n"); |
| 177 | 178 | } |
| @@ -59,10 +59,10 @@ static struct powercap_control_type *tpmi_control_type; · 58 unmodified lines | ||
| 59 | 59 | |
| 60 | 60 | static int tpmi_rapl_read_raw(int id, struct reg_action *ra) |
| 61 | 61 | { |
| 62 | − if (!ra->reg) | |
| 62 | + if (!ra->reg.mmio) | |
| 63 | 63 | return -EINVAL; |
| 64 | 64 | |
| 65 | − ra->value = readq((void __iomem *)ra->reg); | |
| 65 | + ra->value = readq(ra->reg.mmio); | |
| 66 | 66 | |
| 67 | 67 | ra->value &= ra->mask; |
| 68 | 68 | return 0; |
| @@ -72,15 +72,15 @@ static int tpmi_rapl_write_raw(int id, struct reg_action *ra) · 3 unmodified lines | ||
| 72 | 72 | { |
| 73 | 73 | u64 val; |
| 74 | 74 | |
| 75 | − if (!ra->reg) | |
| 75 | + if (!ra->reg.mmio) | |
| 76 | 76 | return -EINVAL; |
| 77 | 77 | |
| 78 | − val = readq((void __iomem *)ra->reg); | |
| 78 | + val = readq(ra->reg.mmio); | |
| 79 | 79 | |
| 80 | 80 | val &= ~ra->mask; |
| 81 | 81 | val |= ra->value; |
| 82 | 82 | |
| 83 | − writeq(val, (void __iomem *)ra->reg); | |
| 83 | + writeq(val, ra->reg.mmio); | |
| 84 | 84 | return 0; |
| 85 | 85 | } |
| 86 | 86 | |
| @@ -138,8 +138,7 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset) · 51 unmodified lines | ||
| 138 | 138 | enum tpmi_rapl_register reg_index; |
| 139 | 139 | enum rapl_domain_reg_id reg_id; |
| 140 | 140 | int tpmi_domain_size, tpmi_domain_flags; |
| 141 | − u64 *tpmi_rapl_regs = trp->base + offset; | |
| 142 | − u64 tpmi_domain_header = readq((void __iomem *)tpmi_rapl_regs); | |
| 141 | + u64 tpmi_domain_header = readq(trp->base + offset); | |
| 143 | 142 | |
| 144 | 143 | /* Domain Parent bits are ignored for now */ |
| 145 | 144 | tpmi_domain_version = tpmi_domain_header & 0xff; |
| @@ -180,7 +179,7 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset) · 34 unmodified lines | ||
| 180 | 179 | return -EINVAL; |
| 181 | 180 | } |
| 182 | 181 | |
| 183 | − if (trp->priv.regs[domain_type][RAPL_DOMAIN_REG_UNIT]) { | |
| 182 | + if (trp->priv.regs[domain_type][RAPL_DOMAIN_REG_UNIT].mmio) { | |
| 184 | 183 | pr_warn(FW_BUG "Duplicate Domain type %d\n", tpmi_domain_type); |
| 185 | 184 | return -EINVAL; |
| 186 | 185 | } |
| @@ -218,7 +217,7 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset) · 31 unmodified lines | ||
| 218 | 217 | default: |
| 219 | 218 | continue; |
| 220 | 219 | } |
| 221 | − trp->priv.regs[domain_type][reg_id] = (u64)&tpmi_rapl_regs[reg_index]; | |
| 220 | + trp->priv.regs[domain_type][reg_id].mmio = trp->base + offset + reg_index * 8; | |
| 222 | 221 | } |
| 223 | 222 | |
| 224 | 223 | return 0; |
| @@ -716,7 +716,6 @@ struct qeth_card_info { · 715 unmodified lines | ||
| 716 | 716 | u16 chid; |
| 717 | 717 | u8 ids_valid:1; /* cssid,iid,chid */ |
| 718 | 718 | u8 dev_addr_is_registered:1; |
| 719 | − u8 open_when_online:1; | |
| 720 | 719 | u8 promisc_mode:1; |
| 721 | 720 | u8 use_v1_blkt:1; |
| 722 | 721 | u8 is_vm_nic:1; |
| @@ -5373,8 +5373,6 @@ int qeth_set_offline(struct qeth_card *card, const struct qeth_discipline *disc, · 5372 unmodified lines | ||
| 5373 | 5373 | qeth_clear_ipacmd_list(card); |
| 5374 | 5374 | |
| 5375 | 5375 | rtnl_lock(); |
| 5376 | − card->info.open_when_online = card->dev->flags & IFF_UP; | |
| 5377 | − dev_close(card->dev); | |
| 5378 | 5376 | netif_device_detach(card->dev); |
| 5379 | 5377 | netif_carrier_off(card->dev); |
| 5380 | 5378 | rtnl_unlock(); |
| @@ -2388,9 +2388,12 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok) · 2387 unmodified lines | ||
| 2388 | 2388 | qeth_enable_hw_features(dev); |
| 2389 | 2389 | qeth_l2_enable_brport_features(card); |
| 2390 | 2390 | |
| 2391 | − if (card->info.open_when_online) { | |
| 2392 | − card->info.open_when_online = 0; | |
| 2393 | − dev_open(dev, NULL); | |
| 2391 | + if (netif_running(dev)) { | |
| 2392 | + local_bh_disable(); | |
| 2393 | + napi_schedule(&card->napi); | |
| 2394 | + /* kick-start the NAPI softirq: */ | |
| 2395 | + local_bh_enable(); | |
| 2396 | + qeth_l2_set_rx_mode(dev); | |
| 2394 | 2397 | } |
| 2395 | 2398 | rtnl_unlock(); |
| 2396 | 2399 | } |
| @@ -2018,9 +2018,11 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok) · 2017 unmodified lines | ||
| 2018 | 2018 | netif_device_attach(dev); |
| 2019 | 2019 | qeth_enable_hw_features(dev); |
| 2020 | 2020 | |
| 2021 | − if (card->info.open_when_online) { | |
| 2022 | − card->info.open_when_online = 0; | |
| 2023 | − dev_open(dev, NULL); | |
| 2021 | + if (netif_running(dev)) { | |
| 2022 | + local_bh_disable(); | |
| 2023 | + napi_schedule(&card->napi); | |
| 2024 | + /* kick-start the NAPI softirq: */ | |
| 2025 | + local_bh_enable(); | |
| 2024 | 2026 | } |
| 2025 | 2027 | rtnl_unlock(); |
| 2026 | 2028 | } |
| @@ -534,8 +534,7 @@ static void zfcp_fc_adisc_handler(void *data) · 533 unmodified lines | ||
| 534 | 534 | |
| 535 | 535 | /* re-init to undo drop from zfcp_fc_adisc() */ |
| 536 | 536 | port->d_id = ntoh24(adisc_resp->adisc_port_id); |
| 537 | − /* port is good, unblock rport without going through erp */ | |
| 538 | − zfcp_scsi_schedule_rport_register(port); | |
| 537 | + /* port is still good, nothing to do */ | |
| 539 | 538 | out: |
| 540 | 539 | atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status); |
| 541 | 540 | put_device(&port->dev); |
| @@ -595,9 +594,6 @@ void zfcp_fc_link_test_work(struct work_struct *work) · 53 unmodified lines | ||
| 595 | 594 | int retval; |
| 596 | 595 | |
| 597 | 596 | set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */ |
| 598 | − get_device(&port->dev); | |
| 599 | − port->rport_task = RPORT_DEL; | |
| 600 | − zfcp_scsi_rport_work(&port->rport_work); | |
| 601 | 597 | |
| 602 | 598 | /* only issue one test command at one time per port */ |
| 603 | 599 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST) |
| @@ -1598,7 +1598,7 @@ NCR_700_intr(int irq, void *dev_id) · 1597 unmodified lines | ||
| 1598 | 1598 | printk("scsi%d (%d:%d) PHASE MISMATCH IN SEND MESSAGE %d remain, return %p[%04x], phase %s\n", host->host_no, pun, lun, count, (void *)temp, temp - hostdata->pScript, sbcl_to_string(NCR_700_readb(host, SBCL_REG))); |
| 1599 | 1599 | #endif |
| 1600 | 1600 | resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch; |
| 1601 | − } else if(dsp >= to32bit(&slot->pSG[0].ins) && | |
| 1601 | + } else if (slot && dsp >= to32bit(&slot->pSG[0].ins) && | |
| 1602 | 1602 | dsp <= to32bit(&slot->pSG[NCR_700_SG_SEGMENTS].ins)) { |
| 1603 | 1603 | int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff; |
| 1604 | 1604 | int SGcount = (dsp - to32bit(&slot->pSG[0].ins))/sizeof(struct NCR_700_SG_List); |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | |
| 28 | 28 | #define DRV_NAME "fnic" |
| 29 | 29 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" |
| 30 | −#define DRV_VERSION "1.6.0.54" | |
| 30 | +#define DRV_VERSION "1.6.0.55" | |
| 31 | 31 | #define PFX DRV_NAME ": " |
| 32 | 32 | #define DFX DRV_NAME "%d: " |
| 33 | 33 | |
| @@ -2139,7 +2139,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, · 2138 unmodified lines | ||
| 2139 | 2139 | bool new_sc) |
| 2140 | 2140 | |
| 2141 | 2141 | { |
| 2142 | − int ret = SUCCESS; | |
| 2142 | + int ret = 0; | |
| 2143 | 2143 | struct fnic_pending_aborts_iter_data iter_data = { |
| 2144 | 2144 | .fnic = fnic, |
| 2145 | 2145 | .lun_dev = lr_sc->device, |
| @@ -2159,9 +2159,11 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, · 13 unmodified lines | ||
| 2159 | 2159 | |
| 2160 | 2160 | /* walk again to check, if IOs are still pending in fw */ |
| 2161 | 2161 | if (fnic_is_abts_pending(fnic, lr_sc)) |
| 2162 | − ret = FAILED; | |
| 2162 | + ret = 1; | |
| 2163 | 2163 | |
| 2164 | 2164 | clean_pending_aborts_end: |
| 2165 | + FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, | |
| 2166 | + "%s: exit status: %d\n", __func__, ret); | |
| 2165 | 2167 | return ret; |
| 2166 | 2168 | } |
| 2167 | 2169 | |
| @@ -109,8 +109,6 @@ lpfc_sli4_set_rsp_sgl_last(struct lpfc_hba *phba, · 108 unmodified lines | ||
| 109 | 109 | } |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | −#define LPFC_INVALID_REFTAG ((u32)-1) | |
| 113 | − | |
| 114 | 112 | /** |
| 115 | 113 | * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread |
| 116 | 114 | * @phba: The Hba for which this call is being executed. |
| @@ -978,8 +976,6 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, · 861 unmodified lines | ||
| 978 | 976 | |
| 979 | 977 | sgpe = scsi_prot_sglist(sc); |
| 980 | 978 | lba = scsi_prot_ref_tag(sc); |
| 981 | − if (lba == LPFC_INVALID_REFTAG) | |
| 982 | − return 0; | |
| 983 | 979 | |
| 984 | 980 | /* First check if we need to match the LBA */ |
| 985 | 981 | if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) { |
| @@ -1560,8 +1556,6 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, · 574 unmodified lines | ||
| 1560 | 1556 | |
| 1561 | 1557 | /* extract some info from the scsi command for pde*/ |
| 1562 | 1558 | reftag = scsi_prot_ref_tag(sc); |
| 1563 | − if (reftag == LPFC_INVALID_REFTAG) | |
| 1564 | − goto out; | |
| 1565 | 1559 | |
| 1566 | 1560 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
| 1567 | 1561 | rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1); |
| @@ -1723,8 +1717,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, · 155 unmodified lines | ||
| 1723 | 1717 | /* extract some info from the scsi command */ |
| 1724 | 1718 | blksize = scsi_prot_interval(sc); |
| 1725 | 1719 | reftag = scsi_prot_ref_tag(sc); |
| 1726 | − if (reftag == LPFC_INVALID_REFTAG) | |
| 1727 | − goto out; | |
| 1728 | 1720 | |
| 1729 | 1721 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
| 1730 | 1722 | rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1); |
| @@ -1953,8 +1945,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, · 222 unmodified lines | ||
| 1953 | 1945 | |
| 1954 | 1946 | /* extract some info from the scsi command for pde*/ |
| 1955 | 1947 | reftag = scsi_prot_ref_tag(sc); |
| 1956 | − if (reftag == LPFC_INVALID_REFTAG) | |
| 1957 | − goto out; | |
| 1958 | 1948 | |
| 1959 | 1949 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
| 1960 | 1950 | rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1); |
| @@ -2154,8 +2144,6 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, · 193 unmodified lines | ||
| 2154 | 2144 | /* extract some info from the scsi command */ |
| 2155 | 2145 | blksize = scsi_prot_interval(sc); |
| 2156 | 2146 | reftag = scsi_prot_ref_tag(sc); |
| 2157 | − if (reftag == LPFC_INVALID_REFTAG) | |
| 2158 | − goto out; | |
| 2159 | 2147 | |
| 2160 | 2148 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
| 2161 | 2149 | rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1); |
| @@ -2746,8 +2734,6 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) · 584 unmodified lines | ||
| 2746 | 2734 | |
| 2747 | 2735 | src = (struct scsi_dif_tuple *)sg_virt(sgpe); |
| 2748 | 2736 | start_ref_tag = scsi_prot_ref_tag(cmd); |
| 2749 | − if (start_ref_tag == LPFC_INVALID_REFTAG) | |
| 2750 | − goto out; | |
| 2751 | 2737 | start_app_tag = src->app_tag; |
| 2752 | 2738 | len = sgpe->length; |
| 2753 | 2739 | while (src && protsegcnt) { |
| @@ -3493,11 +3479,11 @@ err: · 739 unmodified lines | ||
| 3493 | 3479 | scsi_cmnd->sc_data_direction); |
| 3494 | 3480 | |
| 3495 | 3481 | lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, |
| 3496 | − "9084 Cannot setup S/G List for HBA" | |
| 3497 | − "IO segs %d/%d SGL %d SCSI %d: %d %d\n", | |
| 3482 | + "9084 Cannot setup S/G List for HBA " | |
| 3483 | + "IO segs %d/%d SGL %d SCSI %d: %d %d %d\n", | |
| 3498 | 3484 | lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt, |
| 3499 | 3485 | phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt, |
| 3500 | − prot_group_type, num_sge); | |
| 3486 | + prot_group_type, num_sge, ret); | |
| 3501 | 3487 | |
| 3502 | 3488 | lpfc_cmd->seg_cnt = 0; |
| 3503 | 3489 | lpfc_cmd->prot_seg_cnt = 0; |
| @@ -1181,7 +1181,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, · 1180 unmodified lines | ||
| 1181 | 1181 | pm80xx_set_thermal_config(pm8001_ha); |
| 1182 | 1182 | } |
| 1183 | 1183 | |
| 1184 | − if (pm8001_init_sas_add(pm8001_ha)) | |
| 1184 | + rc = pm8001_init_sas_add(pm8001_ha); | |
| 1185 | + if (rc) | |
| 1185 | 1186 | goto err_out_shost; |
| 1186 | 1187 | /* phy setting support for motherboard controller */ |
| 1187 | 1188 | rc = pm8001_configure_phy_settings(pm8001_ha); |
| @@ -31,6 +31,7 @@ static void qedf_remove(struct pci_dev *pdev); · 30 unmodified lines | ||
| 31 | 31 | static void qedf_shutdown(struct pci_dev *pdev); |
| 32 | 32 | static void qedf_schedule_recovery_handler(void *dev); |
| 33 | 33 | static void qedf_recovery_handler(struct work_struct *work); |
| 34 | +static int qedf_suspend(struct pci_dev *pdev, pm_message_t state); | |
| 34 | 35 | |
| 35 | 36 | /* |
| 36 | 37 | * Driver module parameters. |
| @@ -3271,6 +3272,7 @@ static struct pci_driver qedf_pci_driver = { · 3234 unmodified lines | ||
| 3271 | 3272 | .probe = qedf_probe, |
| 3272 | 3273 | .remove = qedf_remove, |
| 3273 | 3274 | .shutdown = qedf_shutdown, |
| 3275 | + .suspend = qedf_suspend, | |
| 3274 | 3276 | }; |
| 3275 | 3277 | |
| 3276 | 3278 | static int __qedf_probe(struct pci_dev *pdev, int mode) |
| @@ -4000,6 +4002,22 @@ static void qedf_shutdown(struct pci_dev *pdev) · 723 unmodified lines | ||
| 4000 | 4002 | __qedf_remove(pdev, QEDF_MODE_NORMAL); |
| 4001 | 4003 | } |
| 4002 | 4004 | |
| 4005 | +static int qedf_suspend(struct pci_dev *pdev, pm_message_t state) | |
| 4006 | +{ | |
| 4007 | + struct qedf_ctx *qedf; | |
| 4008 | + | |
| 4009 | + if (!pdev) { | |
| 4010 | + QEDF_ERR(NULL, "pdev is NULL.\n"); | |
| 4011 | + return -ENODEV; | |
| 4012 | + } | |
| 4013 | + | |
| 4014 | + qedf = pci_get_drvdata(pdev); | |
| 4015 | + | |
| 4016 | + QEDF_ERR(&qedf->dbg_ctx, "%s: Device does not support suspend operation\n", __func__); | |
| 4017 | + | |
| 4018 | + return -EPERM; | |
| 4019 | +} | |
| 4020 | + | |
| 4003 | 4021 | /* |
| 4004 | 4022 | * Recovery handler code |
| 4005 | 4023 | */ |
| @@ -69,6 +69,7 @@ static struct nvm_iscsi_block *qedi_get_nvram_block(struct qedi_ctx *qedi); · 68 unmodified lines | ||
| 69 | 69 | static void qedi_recovery_handler(struct work_struct *work); |
| 70 | 70 | static void qedi_schedule_hw_err_handler(void *dev, |
| 71 | 71 | enum qed_hw_err_type err_type); |
| 72 | +static int qedi_suspend(struct pci_dev *pdev, pm_message_t state); | |
| 72 | 73 | |
| 73 | 74 | static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle) |
| 74 | 75 | { |
| @@ -1976,8 +1977,9 @@ static int qedi_cpu_offline(unsigned int cpu) · 1901 unmodified lines | ||
| 1976 | 1977 | struct qedi_percpu_s *p = this_cpu_ptr(&qedi_percpu); |
| 1977 | 1978 | struct qedi_work *work, *tmp; |
| 1978 | 1979 | struct task_struct *thread; |
| 1980 | + unsigned long flags; | |
| 1979 | 1981 | |
| 1980 | − spin_lock_bh(&p->p_work_lock); | |
| 1982 | + spin_lock_irqsave(&p->p_work_lock, flags); | |
| 1981 | 1983 | thread = p->iothread; |
| 1982 | 1984 | p->iothread = NULL; |
| 1983 | 1985 | |
| @@ -1988,7 +1990,7 @@ static int qedi_cpu_offline(unsigned int cpu) · 4 unmodified lines | ||
| 1988 | 1990 | kfree(work); |
| 1989 | 1991 | } |
| 1990 | 1992 | |
| 1991 | − spin_unlock_bh(&p->p_work_lock); | |
| 1993 | + spin_unlock_irqrestore(&p->p_work_lock, flags); | |
| 1992 | 1994 | if (thread) |
| 1993 | 1995 | kthread_stop(thread); |
| 1994 | 1996 | return 0; |
| @@ -2510,6 +2512,22 @@ static void qedi_shutdown(struct pci_dev *pdev) · 515 unmodified lines | ||
| 2510 | 2512 | __qedi_remove(pdev, QEDI_MODE_SHUTDOWN); |
| 2511 | 2513 | } |
| 2512 | 2514 | |
| 2515 | +static int qedi_suspend(struct pci_dev *pdev, pm_message_t state) | |
| 2516 | +{ | |
| 2517 | + struct qedi_ctx *qedi; | |
| 2518 | + | |
| 2519 | + if (!pdev) { | |
| 2520 | + QEDI_ERR(NULL, "pdev is NULL.\n"); | |
| 2521 | + return -ENODEV; | |
| 2522 | + } | |
| 2523 | + | |
| 2524 | + qedi = pci_get_drvdata(pdev); | |
| 2525 | + | |
| 2526 | + QEDI_ERR(&qedi->dbg_ctx, "%s: Device does not support suspend operation\n", __func__); | |
| 2527 | + | |
| 2528 | + return -EPERM; | |
| 2529 | +} | |
| 2530 | + | |
| 2513 | 2531 | static int __qedi_probe(struct pci_dev *pdev, int mode) |
| 2514 | 2532 | { |
| 2515 | 2533 | struct qedi_ctx *qedi; |
| @@ -2868,6 +2886,7 @@ static struct pci_driver qedi_pci_driver = { · 352 unmodified lines | ||
| 2868 | 2886 | .remove = qedi_remove, |
| 2869 | 2887 | .shutdown = qedi_shutdown, |
| 2870 | 2888 | .err_handler = &qedi_err_handler, |
| 2889 | + .suspend = qedi_suspend, | |
| 2871 | 2890 | }; |
| 2872 | 2891 | |
| 2873 | 2892 | static int __init qedi_init(void) |
| @@ -248,6 +248,7 @@ int raid_component_add(struct raid_template *r,struct device *raid_dev, · 247 unmodified lines | ||
| 248 | 248 | return 0; |
| 249 | 249 | |
| 250 | 250 | err_out: |
| 251 | + put_device(&rc->dev); | |
| 251 | 252 | list_del(&rc->node); |
| 252 | 253 | rd->component_count--; |
| 253 | 254 | put_device(component_dev); |
| @@ -406,7 +406,7 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, · 405 unmodified lines | ||
| 406 | 406 | size_t length, loff_t *ppos) |
| 407 | 407 | { |
| 408 | 408 | int host, channel, id, lun; |
| 409 | − char *buffer, *p; | |
| 409 | + char *buffer, *end, *p; | |
| 410 | 410 | int err; |
| 411 | 411 | |
| 412 | 412 | if (!buf || length > PAGE_SIZE) |
| @@ -421,10 +421,14 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, · 8 unmodified lines | ||
| 421 | 421 | goto out; |
| 422 | 422 | |
| 423 | 423 | err = -EINVAL; |
| 424 | − if (length < PAGE_SIZE) | |
| 425 | − buffer[length] = '\0'; | |
| 426 | − else if (buffer[PAGE_SIZE-1]) | |
| 427 | − goto out; | |
| 424 | + if (length < PAGE_SIZE) { | |
| 425 | + end = buffer + length; | |
| 426 | + *end = '\0'; | |
| 427 | + } else { | |
| 428 | + end = buffer + PAGE_SIZE - 1; | |
| 429 | + if (*end) | |
| 430 | + goto out; | |
| 431 | + } | |
| 428 | 432 | |
| 429 | 433 | /* |
| 430 | 434 | * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi |
| @@ -433,10 +437,10 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, · 2 unmodified lines | ||
| 433 | 437 | if (!strncmp("scsi add-single-device", buffer, 22)) { |
| 434 | 438 | p = buffer + 23; |
| 435 | 439 | |
| 436 | − host = simple_strtoul(p, &p, 0); | |
| 437 | − channel = simple_strtoul(p + 1, &p, 0); | |
| 438 | − id = simple_strtoul(p + 1, &p, 0); | |
| 439 | − lun = simple_strtoul(p + 1, &p, 0); | |
| 440 | + host = (p < end) ? simple_strtoul(p, &p, 0) : 0; | |
| 441 | + channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; | |
| 442 | + id = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; | |
| 443 | + lun = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; | |
| 440 | 444 | |
| 441 | 445 | err = scsi_add_single_device(host, channel, id, lun); |
| 442 | 446 | |
| @@ -447,10 +451,10 @@ static ssize_t proc_scsi_write(struct file *file, const char __user *buf, · 4 unmodified lines | ||
| 447 | 451 | } else if (!strncmp("scsi remove-single-device", buffer, 25)) { |
| 448 | 452 | p = buffer + 26; |
| 449 | 453 | |
| 450 | − host = simple_strtoul(p, &p, 0); | |
| 451 | − channel = simple_strtoul(p + 1, &p, 0); | |
| 452 | − id = simple_strtoul(p + 1, &p, 0); | |
| 453 | − lun = simple_strtoul(p + 1, &p, 0); | |
| 454 | + host = (p < end) ? simple_strtoul(p, &p, 0) : 0; | |
| 455 | + channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; | |
| 456 | + id = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; | |
| 457 | + lun = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; | |
| 454 | 458 | |
| 455 | 459 | err = scsi_remove_single_device(host, channel, id, lun); |
| 456 | 460 | } |
| @@ -3876,7 +3876,7 @@ static int sd_suspend_runtime(struct device *dev) · 3875 unmodified lines | ||
| 3876 | 3876 | static int sd_resume(struct device *dev) |
| 3877 | 3877 | { |
| 3878 | 3878 | struct scsi_disk *sdkp = dev_get_drvdata(dev); |
| 3879 | − int ret; | |
| 3879 | + int ret = 0; | |
| 3880 | 3880 | |
| 3881 | 3881 | if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ |
| 3882 | 3882 | return 0; |
| @@ -3884,8 +3884,11 @@ static int sd_resume(struct device *dev) · 1 unmodified line | ||
| 3884 | 3884 | if (!sdkp->device->manage_start_stop) |
| 3885 | 3885 | return 0; |
| 3886 | 3886 | |
| 3887 | − sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); | |
| 3888 | − ret = sd_start_stop_device(sdkp, 1); | |
| 3887 | + if (!sdkp->device->no_start_on_resume) { | |
| 3888 | + sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); | |
| 3889 | + ret = sd_start_stop_device(sdkp, 1); | |
| 3890 | + } | |
| 3891 | + | |
| 3889 | 3892 | if (!ret) |
| 3890 | 3893 | opal_unlock_from_suspend(sdkp->opal_dev); |
| 3891 | 3894 | return ret; |
| @@ -303,6 +303,7 @@ snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid) · 302 unmodified lines | ||
| 303 | 303 | "Snic Tgt: device_add, with err = %d\n", |
| 304 | 304 | ret); |
| 305 | 305 | |
| 306 | + put_device(&tgt->dev); | |
| 306 | 307 | put_device(&snic->shost->shost_gendev); |
| 307 | 308 | spin_lock_irqsave(snic->shost->host_lock, flags); |
| 308 | 309 | list_del(&tgt->list); |
| @@ -366,6 +366,7 @@ static void storvsc_on_channel_callback(void *context); · 365 unmodified lines | ||
| 366 | 366 | #define STORVSC_FC_MAX_LUNS_PER_TARGET 255 |
| 367 | 367 | #define STORVSC_FC_MAX_TARGETS 128 |
| 368 | 368 | #define STORVSC_FC_MAX_CHANNELS 8 |
| 369 | +#define STORVSC_FC_MAX_XFER_SIZE ((u32)(512 * 1024)) | |
| 369 | 370 | |
| 370 | 371 | #define STORVSC_IDE_MAX_LUNS_PER_TARGET 64 |
| 371 | 372 | #define STORVSC_IDE_MAX_TARGETS 1 |
| @@ -1673,10 +1674,6 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) · 1301 unmodified lines | ||
| 1673 | 1674 | */ |
| 1674 | 1675 | static enum scsi_timeout_action storvsc_eh_timed_out(struct scsi_cmnd *scmnd) |
| 1675 | 1676 | { |
| 1676 | −#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) | |
| 1677 | − if (scmnd->device->host->transportt == fc_transport_template) | |
| 1678 | − return fc_eh_timed_out(scmnd); | |
| 1679 | −#endif | |
| 1680 | 1677 | return SCSI_EH_RESET_TIMER; |
| 1681 | 1678 | } |
| 1682 | 1679 | |
| @@ -2006,6 +2003,9 @@ static int storvsc_probe(struct hv_device *device, · 323 unmodified lines | ||
| 2006 | 2003 | * protecting it from any weird value. |
| 2007 | 2004 | */ |
| 2008 | 2005 | max_xfer_bytes = round_down(stor_device->max_transfer_bytes, HV_HYP_PAGE_SIZE); |
| 2006 | + if (is_fc) | |
| 2007 | + max_xfer_bytes = min(max_xfer_bytes, STORVSC_FC_MAX_XFER_SIZE); | |
| 2008 | + | |
| 2009 | 2009 | /* max_hw_sectors_kb */ |
| 2010 | 2010 | host->max_sectors = max_xfer_bytes >> 9; |
| 2011 | 2011 | /* |
| @@ -164,7 +164,7 @@ static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc) · 163 unmodified lines | ||
| 164 | 164 | clk_hsio_pll->hw.init = &init; |
| 165 | 165 | |
| 166 | 166 | hw = &clk_hsio_pll->hw; |
| 167 | − ret = devm_clk_hw_register(bc->dev, hw); | |
| 167 | + ret = devm_clk_hw_register(bc->bus_power_dev, hw); | |
| 168 | 168 | if (ret) |
| 169 | 169 | return ret; |
| 170 | 170 | |
| @@ -57,10 +57,10 @@ static int rapl_mmio_cpu_down_prep(unsigned int cpu) · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | static int rapl_mmio_read_raw(int cpu, struct reg_action *ra) |
| 59 | 59 | { |
| 60 | − if (!ra->reg) | |
| 60 | + if (!ra->reg.mmio) | |
| 61 | 61 | return -EINVAL; |
| 62 | 62 | |
| 63 | − ra->value = readq((void __iomem *)ra->reg); | |
| 63 | + ra->value = readq(ra->reg.mmio); | |
| 64 | 64 | ra->value &= ra->mask; |
| 65 | 65 | return 0; |
| 66 | 66 | } |
| @@ -69,13 +69,13 @@ static int rapl_mmio_write_raw(int cpu, struct reg_action *ra) · 2 unmodified lines | ||
| 69 | 69 | { |
| 70 | 70 | u64 val; |
| 71 | 71 | |
| 72 | − if (!ra->reg) | |
| 72 | + if (!ra->reg.mmio) | |
| 73 | 73 | return -EINVAL; |
| 74 | 74 | |
| 75 | − val = readq((void __iomem *)ra->reg); | |
| 75 | + val = readq(ra->reg.mmio); | |
| 76 | 76 | val &= ~ra->mask; |
| 77 | 77 | val |= ra->value; |
| 78 | − writeq(val, (void __iomem *)ra->reg); | |
| 78 | + writeq(val, ra->reg.mmio); | |
| 79 | 79 | return 0; |
| 80 | 80 | } |
| 81 | 81 | |
| @@ -92,13 +92,13 @@ int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc · 10 unmodified lines | ||
| 92 | 92 | for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) { |
| 93 | 93 | for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++) |
| 94 | 94 | if (rapl_regs->regs[domain][reg]) |
| 95 | − rapl_mmio_priv.regs[domain][reg] = | |
| 96 | − (u64)proc_priv->mmio_base + | |
| 95 | + rapl_mmio_priv.regs[domain][reg].mmio = | |
| 96 | + proc_priv->mmio_base + | |
| 97 | 97 | rapl_regs->regs[domain][reg]; |
| 98 | 98 | rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain]; |
| 99 | 99 | } |
| 100 | 100 | rapl_mmio_priv.type = RAPL_IF_MMIO; |
| 101 | − rapl_mmio_priv.reg_unit = (u64)proc_priv->mmio_base + rapl_regs->reg_unit; | |
| 101 | + rapl_mmio_priv.reg_unit.mmio = proc_priv->mmio_base + rapl_regs->reg_unit; | |
| 102 | 102 | |
| 103 | 103 | rapl_mmio_priv.read_raw = rapl_mmio_read_raw; |
| 104 | 104 | rapl_mmio_priv.write_raw = rapl_mmio_write_raw; |
| @@ -1964,6 +1964,8 @@ unlock: · 1963 unmodified lines | ||
| 1964 | 1964 | |
| 1965 | 1965 | pm_runtime_mark_last_busy(&tb->dev); |
| 1966 | 1966 | pm_runtime_put_autosuspend(&tb->dev); |
| 1967 | + | |
| 1968 | + kfree(ev); | |
| 1967 | 1969 | } |
| 1968 | 1970 | |
| 1969 | 1971 | static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port) |
| @@ -579,7 +579,9 @@ int tb_switch_tmu_disable(struct tb_switch *sw) · 578 unmodified lines | ||
| 579 | 579 | * uni-directional mode and we don't want to change it's TMU |
| 580 | 580 | * mode. |
| 581 | 581 | */ |
| 582 | − tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]); | |
| 582 | + ret = tb_switch_tmu_rate_write(sw, tmu_rates[TB_SWITCH_TMU_MODE_OFF]); | |
| 583 | + if (ret) | |
| 584 | + return ret; | |
| 583 | 585 | |
| 584 | 586 | tb_port_tmu_time_sync_disable(up); |
| 585 | 587 | ret = tb_port_tmu_time_sync_disable(down); |
| @@ -359,7 +359,7 @@ static int ufs_renesas_init(struct ufs_hba *hba) · 358 unmodified lines | ||
| 359 | 359 | { |
| 360 | 360 | struct ufs_renesas_priv *priv; |
| 361 | 361 | |
| 362 | − priv = devm_kmalloc(hba->dev, sizeof(*priv), GFP_KERNEL); | |
| 362 | + priv = devm_kzalloc(hba->dev, sizeof(*priv), GFP_KERNEL); | |
| 363 | 363 | if (!priv) |
| 364 | 364 | return -ENOMEM; |
| 365 | 365 | ufshcd_set_variant(hba, priv); |
| @@ -42,6 +42,7 @@ struct usb_conn_info { · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | struct power_supply_desc desc; |
| 44 | 44 | struct power_supply *charger; |
| 45 | + bool initial_detection; | |
| 45 | 46 | }; |
| 46 | 47 | |
| 47 | 48 | /* |
| @@ -86,11 +87,13 @@ static void usb_conn_detect_cable(struct work_struct *work) · 38 unmodified lines | ||
| 86 | 87 | dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n", |
| 87 | 88 | usb_role_string(info->last_role), usb_role_string(role), id, vbus); |
| 88 | 89 | |
| 89 | − if (info->last_role == role) { | |
| 90 | + if (!info->initial_detection && info->last_role == role) { | |
| 90 | 91 | dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role)); |
| 91 | 92 | return; |
| 92 | 93 | } |
| 93 | 94 | |
| 95 | + info->initial_detection = false; | |
| 96 | + | |
| 94 | 97 | if (info->last_role == USB_ROLE_HOST && info->vbus) |
| 95 | 98 | regulator_disable(info->vbus); |
| 96 | 99 | |
| @@ -258,6 +261,7 @@ static int usb_conn_probe(struct platform_device *pdev) · 161 unmodified lines | ||
| 258 | 261 | device_set_wakeup_capable(&pdev->dev, true); |
| 259 | 262 | |
| 260 | 263 | /* Perform initial detection */ |
| 264 | + info->initial_detection = true; | |
| 261 | 265 | usb_conn_queue_dwork(info, 0); |
| 262 | 266 | |
| 263 | 267 | return 0; |
| @@ -4455,9 +4455,14 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) · 4454 unmodified lines | ||
| 4455 | 4455 | u32 count; |
| 4456 | 4456 | |
| 4457 | 4457 | if (pm_runtime_suspended(dwc->dev)) { |
| 4458 | + dwc->pending_events = true; | |
| 4459 | + /* | |
| 4460 | + * Trigger runtime resume. The get() function will be balanced | |
| 4461 | + * after processing the pending events in dwc3_process_pending | |
| 4462 | + * events(). | |
| 4463 | + */ | |
| 4458 | 4464 | pm_runtime_get(dwc->dev); |
| 4459 | 4465 | disable_irq_nosync(dwc->irq_gadget); |
| 4460 | − dwc->pending_events = true; | |
| 4461 | 4466 | return IRQ_HANDLED; |
| 4462 | 4467 | } |
| 4463 | 4468 | |
| @@ -4718,6 +4723,8 @@ void dwc3_gadget_process_pending_events(struct dwc3 *dwc) · 254 unmodified lines | ||
| 4718 | 4723 | { |
| 4719 | 4724 | if (dwc->pending_events) { |
| 4720 | 4725 | dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf); |
| 4726 | + dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf); | |
| 4727 | + pm_runtime_put(dwc->dev); | |
| 4721 | 4728 | dwc->pending_events = false; |
| 4722 | 4729 | enable_irq(dwc->irq_gadget); |
| 4723 | 4730 | } |
| @@ -823,6 +823,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect); · 822 unmodified lines | ||
| 823 | 823 | * usb_gadget_activate() is called. For example, user mode components may |
| 824 | 824 | * need to be activated before the system can talk to hosts. |
| 825 | 825 | * |
| 826 | + * This routine may sleep; it must not be called in interrupt context | |
| 827 | + * (such as from within a gadget driver's disconnect() callback). | |
| 828 | + * | |
| 826 | 829 | * Returns zero on success, else negative errno. |
| 827 | 830 | */ |
| 828 | 831 | int usb_gadget_deactivate(struct usb_gadget *gadget) |
| @@ -861,6 +864,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate); · 32 unmodified lines | ||
| 861 | 864 | * This routine activates gadget which was previously deactivated with |
| 862 | 865 | * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed. |
| 863 | 866 | * |
| 867 | + * This routine may sleep; it must not be called in interrupt context. | |
| 868 | + * | |
| 864 | 869 | * Returns zero on success, else negative errno. |
| 865 | 870 | */ |
| 866 | 871 | int usb_gadget_activate(struct usb_gadget *gadget) |
| @@ -1639,7 +1644,11 @@ static void gadget_unbind_driver(struct device *dev) · 772 unmodified lines | ||
| 1639 | 1644 | usb_gadget_disable_async_callbacks(udc); |
| 1640 | 1645 | if (gadget->irq) |
| 1641 | 1646 | synchronize_irq(gadget->irq); |
| 1647 | + mutex_unlock(&udc->connect_lock); | |
| 1648 | + | |
| 1642 | 1649 | udc->driver->unbind(gadget); |
| 1650 | + | |
| 1651 | + mutex_lock(&udc->connect_lock); | |
| 1643 | 1652 | usb_gadget_udc_stop_locked(udc); |
| 1644 | 1653 | mutex_unlock(&udc->connect_lock); |
| 1645 | 1654 | |
| @@ -318,7 +318,8 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data) · 317 unmodified lines | ||
| 318 | 318 | rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, |
| 319 | 319 | command, 0xc0, 0, 1, data, 2); |
| 320 | 320 | |
| 321 | − usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]); | |
| 321 | + if (rc == USB_STOR_XFER_GOOD) | |
| 322 | + usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]); | |
| 322 | 323 | |
| 323 | 324 | return rc; |
| 324 | 325 | } |
| @@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us) · 129 unmodified lines | ||
| 454 | 455 | static int alauda_check_media(struct us_data *us) |
| 455 | 456 | { |
| 456 | 457 | struct alauda_info *info = (struct alauda_info *) us->extra; |
| 457 | − unsigned char status[2]; | |
| 458 | + unsigned char *status = us->iobuf; | |
| 459 | + int rc; | |
| 458 | 460 | |
| 459 | − alauda_get_media_status(us, status); | |
| 461 | + rc = alauda_get_media_status(us, status); | |
| 462 | + if (rc != USB_STOR_XFER_GOOD) { | |
| 463 | + status[0] = 0xF0; /* Pretend there's no media */ | |
| 464 | + status[1] = 0; | |
| 465 | + } | |
| 460 | 466 | |
| 461 | 467 | /* Check for no media or door open */ |
| 462 | 468 | if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10) |
| @@ -60,6 +60,7 @@ struct dp_altmode { · 59 unmodified lines | ||
| 60 | 60 | |
| 61 | 61 | enum dp_state state; |
| 62 | 62 | bool hpd; |
| 63 | + bool pending_hpd; | |
| 63 | 64 | |
| 64 | 65 | struct mutex lock; /* device lock */ |
| 65 | 66 | struct work_struct work; |
| @@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp) · 78 unmodified lines | ||
| 144 | 145 | dp->state = DP_STATE_EXIT; |
| 145 | 146 | } else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) { |
| 146 | 147 | ret = dp_altmode_configure(dp, con); |
| 147 | − if (!ret) | |
| 148 | + if (!ret) { | |
| 148 | 149 | dp->state = DP_STATE_CONFIGURE; |
| 150 | + if (dp->hpd != hpd) { | |
| 151 | + dp->hpd = hpd; | |
| 152 | + dp->pending_hpd = true; | |
| 153 | + } | |
| 154 | + } | |
| 149 | 155 | } else { |
| 150 | 156 | if (dp->hpd != hpd) { |
| 151 | 157 | drm_connector_oob_hotplug_event(dp->connector_fwnode); |
| @@ -161,6 +167,16 @@ static int dp_altmode_configured(struct dp_altmode *dp) · 9 unmodified lines | ||
| 161 | 167 | { |
| 162 | 168 | sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); |
| 163 | 169 | sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment"); |
| 170 | + /* | |
| 171 | + * If the DFP_D/UFP_D sends a change in HPD when first notifying the | |
| 172 | + * DisplayPort driver that it is connected, then we wait until | |
| 173 | + * configuration is complete to signal HPD. | |
| 174 | + */ | |
| 175 | + if (dp->pending_hpd) { | |
| 176 | + drm_connector_oob_hotplug_event(dp->connector_fwnode); | |
| 177 | + sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); | |
| 178 | + dp->pending_hpd = false; | |
| 179 | + } | |
| 164 | 180 | |
| 165 | 181 | return dp_altmode_notify(dp); |
| 166 | 182 | } |
| @@ -29,6 +29,7 @@ config TYPEC_MUX_INTEL_PMC · 28 unmodified lines | ||
| 29 | 29 | tristate "Intel PMC mux control" |
| 30 | 30 | depends on ACPI |
| 31 | 31 | depends on INTEL_SCU_IPC |
| 32 | + select USB_COMMON | |
| 32 | 33 | select USB_ROLE_SWITCH |
| 33 | 34 | help |
| 34 | 35 | Driver for USB muxes controlled by Intel PMC FW. Intel PMC FW can |
| @@ -463,16 +463,18 @@ static int nb7vpq904m_probe(struct i2c_client *client) · 462 unmodified lines | ||
| 463 | 463 | |
| 464 | 464 | ret = nb7vpq904m_register_bridge(nb7); |
| 465 | 465 | if (ret) |
| 466 | − return ret; | |
| 466 | + goto err_disable_gpio; | |
| 467 | 467 | |
| 468 | 468 | sw_desc.drvdata = nb7; |
| 469 | 469 | sw_desc.fwnode = dev->fwnode; |
| 470 | 470 | sw_desc.set = nb7vpq904m_sw_set; |
| 471 | 471 | |
| 472 | 472 | nb7->sw = typec_switch_register(dev, &sw_desc); |
| 473 | − if (IS_ERR(nb7->sw)) | |
| 474 | − return dev_err_probe(dev, PTR_ERR(nb7->sw), | |
| 475 | − "Error registering typec switch\n"); | |
| 473 | + if (IS_ERR(nb7->sw)) { | |
| 474 | + ret = dev_err_probe(dev, PTR_ERR(nb7->sw), | |
| 475 | + "Error registering typec switch\n"); | |
| 476 | + goto err_disable_gpio; | |
| 477 | + } | |
| 476 | 478 | |
| 477 | 479 | retimer_desc.drvdata = nb7; |
| 478 | 480 | retimer_desc.fwnode = dev->fwnode; |
| @@ -480,12 +482,21 @@ static int nb7vpq904m_probe(struct i2c_client *client) · 1 unmodified line | ||
| 480 | 482 | |
| 481 | 483 | nb7->retimer = typec_retimer_register(dev, &retimer_desc); |
| 482 | 484 | if (IS_ERR(nb7->retimer)) { |
| 483 | − typec_switch_unregister(nb7->sw); | |
| 484 | − return dev_err_probe(dev, PTR_ERR(nb7->retimer), | |
| 485 | − "Error registering typec retimer\n"); | |
| 485 | + ret = dev_err_probe(dev, PTR_ERR(nb7->retimer), | |
| 486 | + "Error registering typec retimer\n"); | |
| 487 | + goto err_switch_unregister; | |
| 486 | 488 | } |
| 487 | 489 | |
| 488 | 490 | return 0; |
| 491 | + | |
| 492 | +err_switch_unregister: | |
| 493 | + typec_switch_unregister(nb7->sw); | |
| 494 | + | |
| 495 | +err_disable_gpio: | |
| 496 | + gpiod_set_value(nb7->enable_gpio, 0); | |
| 497 | + regulator_disable(nb7->vcc_supply); | |
| 498 | + | |
| 499 | + return ret; | |
| 489 | 500 | } |
| 490 | 501 | |
| 491 | 502 | static void nb7vpq904m_remove(struct i2c_client *client) |
| @@ -5282,6 +5282,10 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port) · 5281 unmodified lines | ||
| 5282 | 5282 | /* Do nothing, vbus drop expected */ |
| 5283 | 5283 | break; |
| 5284 | 5284 | |
| 5285 | + case SNK_HARD_RESET_WAIT_VBUS: | |
| 5286 | + /* Do nothing, its OK to receive vbus off events */ | |
| 5287 | + break; | |
| 5288 | + | |
| 5285 | 5289 | default: |
| 5286 | 5290 | if (port->pwr_role == TYPEC_SINK && port->attached) |
| 5287 | 5291 | tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port)); |
| @@ -5328,6 +5332,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port) · 40 unmodified lines | ||
| 5328 | 5332 | case SNK_DEBOUNCED: |
| 5329 | 5333 | /*Do nothing, still waiting for VSAFE5V for connect */ |
| 5330 | 5334 | break; |
| 5335 | + case SNK_HARD_RESET_WAIT_VBUS: | |
| 5336 | + /* Do nothing, its OK to receive vbus off events */ | |
| 5337 | + break; | |
| 5331 | 5338 | default: |
| 5332 | 5339 | if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled) |
| 5333 | 5340 | tcpm_set_state(port, SNK_UNATTACHED, 0); |
| @@ -441,13 +441,23 @@ void btrfs_wait_block_group_cache_progress(struct btrfs_block_group *cache, · 440 unmodified lines | ||
| 441 | 441 | u64 num_bytes) |
| 442 | 442 | { |
| 443 | 443 | struct btrfs_caching_control *caching_ctl; |
| 444 | + int progress; | |
| 444 | 445 | |
| 445 | 446 | caching_ctl = btrfs_get_caching_control(cache); |
| 446 | 447 | if (!caching_ctl) |
| 447 | 448 | return; |
| 448 | 449 | |
| 450 | + /* | |
| 451 | + * We've already failed to allocate from this block group, so even if | |
| 452 | + * there's enough space in the block group it isn't contiguous enough to | |
| 453 | + * allow for an allocation, so wait for at least the next wakeup tick, | |
| 454 | + * or for the thing to be done. | |
| 455 | + */ | |
| 456 | + progress = atomic_read(&caching_ctl->progress); | |
| 457 | + | |
| 449 | 458 | wait_event(caching_ctl->wait, btrfs_block_group_done(cache) || |
| 450 | − (cache->free_space_ctl->free_space >= num_bytes)); | |
| 459 | + (progress != atomic_read(&caching_ctl->progress) && | |
| 460 | + (cache->free_space_ctl->free_space >= num_bytes))); | |
| 451 | 461 | |
| 452 | 462 | btrfs_put_caching_control(caching_ctl); |
| 453 | 463 | } |
| @@ -802,8 +812,10 @@ next: · 348 unmodified lines | ||
| 802 | 812 | |
| 803 | 813 | if (total_found > CACHING_CTL_WAKE_UP) { |
| 804 | 814 | total_found = 0; |
| 805 | − if (wakeup) | |
| 815 | + if (wakeup) { | |
| 816 | + atomic_inc(&caching_ctl->progress); | |
| 806 | 817 | wake_up(&caching_ctl->wait); |
| 818 | + } | |
| 807 | 819 | } |
| 808 | 820 | } |
| 809 | 821 | path->slots[0]++; |
| @@ -910,6 +922,7 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait) · 100 unmodified lines | ||
| 910 | 922 | init_waitqueue_head(&caching_ctl->wait); |
| 911 | 923 | caching_ctl->block_group = cache; |
| 912 | 924 | refcount_set(&caching_ctl->count, 2); |
| 925 | + atomic_set(&caching_ctl->progress, 0); | |
| 913 | 926 | btrfs_init_work(&caching_ctl->work, caching_thread, NULL, NULL); |
| 914 | 927 | |
| 915 | 928 | spin_lock(&cache->lock); |
| @@ -90,6 +90,8 @@ struct btrfs_caching_control { · 89 unmodified lines | ||
| 90 | 90 | wait_queue_head_t wait; |
| 91 | 91 | struct btrfs_work work; |
| 92 | 92 | struct btrfs_block_group *block_group; |
| 93 | + /* Track progress of caching during allocation. */ | |
| 94 | + atomic_t progress; | |
| 93 | 95 | refcount_t count; |
| 94 | 96 | }; |
| 95 | 97 | |
| @@ -1103,7 +1103,8 @@ static int btrfs_init_fs_root(struct btrfs_root *root, dev_t anon_dev) · 1102 unmodified lines | ||
| 1103 | 1103 | btrfs_drew_lock_init(&root->snapshot_lock); |
| 1104 | 1104 | |
| 1105 | 1105 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID && |
| 1106 | − !btrfs_is_data_reloc_root(root)) { | |
| 1106 | + !btrfs_is_data_reloc_root(root) && | |
| 1107 | + is_fstree(root->root_key.objectid)) { | |
| 1107 | 1108 | set_bit(BTRFS_ROOT_SHAREABLE, &root->state); |
| 1108 | 1109 | btrfs_check_and_init_root_item(&root->root_item); |
| 1109 | 1110 | } |
| @@ -1300,6 +1301,16 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info, · 190 unmodified lines | ||
| 1300 | 1301 | root = btrfs_get_global_root(fs_info, objectid); |
| 1301 | 1302 | if (root) |
| 1302 | 1303 | return root; |
| 1304 | + | |
| 1305 | + /* | |
| 1306 | + * If we're called for non-subvolume trees, and above function didn't | |
| 1307 | + * find one, do not try to read it from disk. | |
| 1308 | + * | |
| 1309 | + * This is namely for free-space-tree and quota tree, which can change | |
| 1310 | + * at runtime and should only be grabbed from fs_info. | |
| 1311 | + */ | |
| 1312 | + if (!is_fstree(objectid) && objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) | |
| 1313 | + return ERR_PTR(-ENOENT); | |
| 1303 | 1314 | again: |
| 1304 | 1315 | root = btrfs_lookup_fs_root(fs_info, objectid); |
| 1305 | 1316 | if (root) { |
| @@ -4310,8 +4310,11 @@ have_block_group: · 4309 unmodified lines | ||
| 4310 | 4310 | ret = 0; |
| 4311 | 4311 | } |
| 4312 | 4312 | |
| 4313 | − if (unlikely(block_group->cached == BTRFS_CACHE_ERROR)) | |
| 4313 | + if (unlikely(block_group->cached == BTRFS_CACHE_ERROR)) { | |
| 4314 | + if (!cache_block_group_error) | |
| 4315 | + cache_block_group_error = -EIO; | |
| 4314 | 4316 | goto loop; |
| 4317 | + } | |
| 4315 | 4318 | |
| 4316 | 4319 | if (!find_free_extent_check_size_class(ffe_ctl, block_group)) |
| 4317 | 4320 | goto loop; |
| @@ -2145,6 +2145,12 @@ retry: · 2144 unmodified lines | ||
| 2145 | 2145 | continue; |
| 2146 | 2146 | } |
| 2147 | 2147 | |
| 2148 | + if (!folio_test_dirty(folio)) { | |
| 2149 | + /* Someone wrote it for us. */ | |
| 2150 | + folio_unlock(folio); | |
| 2151 | + continue; | |
| 2152 | + } | |
| 2153 | + | |
| 2148 | 2154 | if (wbc->sync_mode != WB_SYNC_NONE) { |
| 2149 | 2155 | if (folio_test_writeback(folio)) |
| 2150 | 2156 | submit_write_bio(bio_ctrl, 0); |
| @@ -2164,11 +2170,12 @@ retry: · 13 unmodified lines | ||
| 2164 | 2170 | } |
| 2165 | 2171 | |
| 2166 | 2172 | /* |
| 2167 | − * the filesystem may choose to bump up nr_to_write. | |
| 2173 | + * The filesystem may choose to bump up nr_to_write. | |
| 2168 | 2174 | * We have to make sure to honor the new nr_to_write |
| 2169 | − * at any time | |
| 2175 | + * at any time. | |
| 2170 | 2176 | */ |
| 2171 | − nr_to_write_done = wbc->nr_to_write <= 0; | |
| 2177 | + nr_to_write_done = (wbc->sync_mode == WB_SYNC_NONE && | |
| 2178 | + wbc->nr_to_write <= 0); | |
| 2172 | 2179 | } |
| 2173 | 2180 | folio_batch_release(&fbatch); |
| 2174 | 2181 | cond_resched(); |
| @@ -1654,8 +1654,6 @@ out_unlock: · 1653 unmodified lines | ||
| 1654 | 1654 | clear_bits, |
| 1655 | 1655 | page_ops); |
| 1656 | 1656 | start += cur_alloc_size; |
| 1657 | − if (start >= end) | |
| 1658 | − return ret; | |
| 1659 | 1657 | } |
| 1660 | 1658 | |
| 1661 | 1659 | /* |
| @@ -1664,9 +1662,11 @@ out_unlock: · 2 unmodified lines | ||
| 1664 | 1662 | * space_info's bytes_may_use counter, reserved in |
| 1665 | 1663 | * btrfs_check_data_free_space(). |
| 1666 | 1664 | */ |
| 1667 | − extent_clear_unlock_delalloc(inode, start, end, locked_page, | |
| 1668 | − clear_bits | EXTENT_CLEAR_DATA_RESV, | |
| 1669 | − page_ops); | |
| 1665 | + if (start < end) { | |
| 1666 | + clear_bits |= EXTENT_CLEAR_DATA_RESV; | |
| 1667 | + extent_clear_unlock_delalloc(inode, start, end, locked_page, | |
| 1668 | + clear_bits, page_ops); | |
| 1669 | + } | |
| 1670 | 1670 | return ret; |
| 1671 | 1671 | } |
| 1672 | 1672 | |
| @@ -1916,7 +1916,39 @@ again: · 1915 unmodified lines | ||
| 1916 | 1916 | err = PTR_ERR(root); |
| 1917 | 1917 | break; |
| 1918 | 1918 | } |
| 1919 | − ASSERT(root->reloc_root == reloc_root); | |
| 1919 | + | |
| 1920 | + if (unlikely(root->reloc_root != reloc_root)) { | |
| 1921 | + if (root->reloc_root) { | |
| 1922 | + btrfs_err(fs_info, | |
| 1923 | +"reloc tree mismatch, root %lld has reloc root key (%lld %u %llu) gen %llu, expect reloc root key (%lld %u %llu) gen %llu", | |
| 1924 | + root->root_key.objectid, | |
| 1925 | + root->reloc_root->root_key.objectid, | |
| 1926 | + root->reloc_root->root_key.type, | |
| 1927 | + root->reloc_root->root_key.offset, | |
| 1928 | + btrfs_root_generation( | |
| 1929 | + &root->reloc_root->root_item), | |
| 1930 | + reloc_root->root_key.objectid, | |
| 1931 | + reloc_root->root_key.type, | |
| 1932 | + reloc_root->root_key.offset, | |
| 1933 | + btrfs_root_generation( | |
| 1934 | + &reloc_root->root_item)); | |
| 1935 | + } else { | |
| 1936 | + btrfs_err(fs_info, | |
| 1937 | +"reloc tree mismatch, root %lld has no reloc root, expect reloc root key (%lld %u %llu) gen %llu", | |
| 1938 | + root->root_key.objectid, | |
| 1939 | + reloc_root->root_key.objectid, | |
| 1940 | + reloc_root->root_key.type, | |
| 1941 | + reloc_root->root_key.offset, | |
| 1942 | + btrfs_root_generation( | |
| 1943 | + &reloc_root->root_item)); | |
| 1944 | + } | |
| 1945 | + list_add(&reloc_root->root_list, &reloc_roots); | |
| 1946 | + btrfs_put_root(root); | |
| 1947 | + btrfs_abort_transaction(trans, -EUCLEAN); | |
| 1948 | + if (!err) | |
| 1949 | + err = -EUCLEAN; | |
| 1950 | + break; | |
| 1951 | + } | |
| 1920 | 1952 | |
| 1921 | 1953 | /* |
| 1922 | 1954 | * set reference count to 1, so btrfs_recover_relocation |
| @@ -1989,7 +2021,7 @@ again: · 66 unmodified lines | ||
| 1989 | 2021 | root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset, |
| 1990 | 2022 | false); |
| 1991 | 2023 | if (btrfs_root_refs(&reloc_root->root_item) > 0) { |
| 1992 | − if (IS_ERR(root)) { | |
| 2024 | + if (WARN_ON(IS_ERR(root))) { | |
| 1993 | 2025 | /* |
| 1994 | 2026 | * For recovery we read the fs roots on mount, |
| 1995 | 2027 | * and if we didn't find the root then we marked |
| @@ -1998,17 +2030,14 @@ again: · 2 unmodified lines | ||
| 1998 | 2030 | * memory. However there's no reason we can't |
| 1999 | 2031 | * handle the error properly here just in case. |
| 2000 | 2032 | */ |
| 2001 | − ASSERT(0); | |
| 2002 | 2033 | ret = PTR_ERR(root); |
| 2003 | 2034 | goto out; |
| 2004 | 2035 | } |
| 2005 | − if (root->reloc_root != reloc_root) { | |
| 2036 | + if (WARN_ON(root->reloc_root != reloc_root)) { | |
| 2006 | 2037 | /* |
| 2007 | − * This is actually impossible without something | |
| 2008 | − * going really wrong (like weird race condition | |
| 2009 | − * or cosmic rays). | |
| 2038 | + * This can happen if on-disk metadata has some | |
| 2039 | + * corruption, e.g. bad reloc tree key offset. | |
| 2010 | 2040 | */ |
| 2011 | − ASSERT(0); | |
| 2012 | 2041 | ret = -EINVAL; |
| 2013 | 2042 | goto out; |
| 2014 | 2043 | } |
| @@ -446,6 +446,20 @@ static int check_root_key(struct extent_buffer *leaf, struct btrfs_key *key, · 445 unmodified lines | ||
| 446 | 446 | btrfs_item_key_to_cpu(leaf, &item_key, slot); |
| 447 | 447 | is_root_item = (item_key.type == BTRFS_ROOT_ITEM_KEY); |
| 448 | 448 | |
| 449 | + /* | |
| 450 | + * Bad rootid for reloc trees. | |
| 451 | + * | |
| 452 | + * Reloc trees are only for subvolume trees, other trees only need | |
| 453 | + * to be COWed to be relocated. | |
| 454 | + */ | |
| 455 | + if (unlikely(is_root_item && key->objectid == BTRFS_TREE_RELOC_OBJECTID && | |
| 456 | + !is_fstree(key->offset))) { | |
| 457 | + generic_err(leaf, slot, | |
| 458 | + "invalid reloc tree for root %lld, root id is not a subvolume tree", | |
| 459 | + key->offset); | |
| 460 | + return -EUCLEAN; | |
| 461 | + } | |
| 462 | + | |
| 449 | 463 | /* No such tree id */ |
| 450 | 464 | if (unlikely(key->objectid == 0)) { |
| 451 | 465 | if (is_root_item) |
| @@ -2019,9 +2019,10 @@ unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn) · 2018 unmodified lines | ||
| 2019 | 2019 | } |
| 2020 | 2020 | } |
| 2021 | 2021 | |
| 2022 | +WRAP_DIR_ITER(ceph_readdir) // FIXME! | |
| 2022 | 2023 | const struct file_operations ceph_dir_fops = { |
| 2023 | 2024 | .read = ceph_read_dir, |
| 2024 | − .iterate = ceph_readdir, | |
| 2025 | + .iterate_shared = shared_ceph_readdir, | |
| 2025 | 2026 | .llseek = ceph_dir_llseek, |
| 2026 | 2027 | .open = ceph_open, |
| 2027 | 2028 | .release = ceph_release, |
| @@ -2033,7 +2034,7 @@ const struct file_operations ceph_dir_fops = { · 5 unmodified lines | ||
| 2033 | 2034 | }; |
| 2034 | 2035 | |
| 2035 | 2036 | const struct file_operations ceph_snapdir_fops = { |
| 2036 | − .iterate = ceph_readdir, | |
| 2037 | + .iterate_shared = shared_ceph_readdir, | |
| 2037 | 2038 | .llseek = ceph_dir_llseek, |
| 2038 | 2039 | .open = ceph_open, |
| 2039 | 2040 | .release = ceph_release, |
| @@ -4764,7 +4764,7 @@ static void delayed_work(struct work_struct *work) · 4763 unmodified lines | ||
| 4764 | 4764 | |
| 4765 | 4765 | dout("mdsc delayed_work\n"); |
| 4766 | 4766 | |
| 4767 | − if (mdsc->stopping) | |
| 4767 | + if (mdsc->stopping >= CEPH_MDSC_STOPPING_FLUSHED) | |
| 4768 | 4768 | return; |
| 4769 | 4769 | |
| 4770 | 4770 | mutex_lock(&mdsc->mutex); |
| @@ -4943,7 +4943,7 @@ void send_flush_mdlog(struct ceph_mds_session *s) · 172 unmodified lines | ||
| 4943 | 4943 | void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc) |
| 4944 | 4944 | { |
| 4945 | 4945 | dout("pre_umount\n"); |
| 4946 | − mdsc->stopping = 1; | |
| 4946 | + mdsc->stopping = CEPH_MDSC_STOPPING_BEGIN; | |
| 4947 | 4947 | |
| 4948 | 4948 | ceph_mdsc_iterate_sessions(mdsc, send_flush_mdlog, true); |
| 4949 | 4949 | ceph_mdsc_iterate_sessions(mdsc, lock_unlock_session, false); |
| @@ -380,6 +380,11 @@ struct cap_wait { · 379 unmodified lines | ||
| 380 | 380 | int want; |
| 381 | 381 | }; |
| 382 | 382 | |
| 383 | +enum { | |
| 384 | + CEPH_MDSC_STOPPING_BEGIN = 1, | |
| 385 | + CEPH_MDSC_STOPPING_FLUSHED = 2, | |
| 386 | +}; | |
| 387 | + | |
| 383 | 388 | /* |
| 384 | 389 | * mds client state |
| 385 | 390 | */ |
| @@ -1374,6 +1374,16 @@ static void ceph_kill_sb(struct super_block *s) · 1373 unmodified lines | ||
| 1374 | 1374 | ceph_mdsc_pre_umount(fsc->mdsc); |
| 1375 | 1375 | flush_fs_workqueues(fsc); |
| 1376 | 1376 | |
| 1377 | + /* | |
| 1378 | + * Though the kill_anon_super() will finally trigger the | |
| 1379 | + * sync_filesystem() anyway, we still need to do it here | |
| 1380 | + * and then bump the stage of shutdown to stop the work | |
| 1381 | + * queue as earlier as possible. | |
| 1382 | + */ | |
| 1383 | + sync_filesystem(s); | |
| 1384 | + | |
| 1385 | + fsc->mdsc->stopping = CEPH_MDSC_STOPPING_FLUSHED; | |
| 1386 | + | |
| 1377 | 1387 | kill_anon_super(s); |
| 1378 | 1388 | |
| 1379 | 1389 | fsc->client->extra_mon_dispatch = NULL; |
| @@ -429,21 +429,14 @@ static int coda_readdir(struct file *coda_file, struct dir_context *ctx) · 428 unmodified lines | ||
| 429 | 429 | cfi = coda_ftoc(coda_file); |
| 430 | 430 | host_file = cfi->cfi_container; |
| 431 | 431 | |
| 432 | − if (host_file->f_op->iterate || host_file->f_op->iterate_shared) { | |
| 432 | + if (host_file->f_op->iterate_shared) { | |
| 433 | 433 | struct inode *host_inode = file_inode(host_file); |
| 434 | 434 | ret = -ENOENT; |
| 435 | 435 | if (!IS_DEADDIR(host_inode)) { |
| 436 | − if (host_file->f_op->iterate_shared) { | |
| 437 | − inode_lock_shared(host_inode); | |
| 438 | − ret = host_file->f_op->iterate_shared(host_file, ctx); | |
| 439 | − file_accessed(host_file); | |
| 440 | − inode_unlock_shared(host_inode); | |
| 441 | − } else { | |
| 442 | − inode_lock(host_inode); | |
| 443 | − ret = host_file->f_op->iterate(host_file, ctx); | |
| 444 | − file_accessed(host_file); | |
| 445 | − inode_unlock(host_inode); | |
| 446 | − } | |
| 436 | + inode_lock_shared(host_inode); | |
| 437 | + ret = host_file->f_op->iterate_shared(host_file, ctx); | |
| 438 | + file_accessed(host_file); | |
| 439 | + inode_unlock_shared(host_inode); | |
| 447 | 440 | } |
| 448 | 441 | return ret; |
| 449 | 442 | } |
| @@ -585,10 +578,11 @@ const struct inode_operations coda_dir_inode_operations = { · 135 unmodified lines | ||
| 585 | 578 | .setattr = coda_setattr, |
| 586 | 579 | }; |
| 587 | 580 | |
| 581 | +WRAP_DIR_ITER(coda_readdir) // FIXME! | |
| 588 | 582 | const struct file_operations coda_dir_operations = { |
| 589 | 583 | .llseek = generic_file_llseek, |
| 590 | 584 | .read = generic_read_dir, |
| 591 | − .iterate = coda_readdir, | |
| 585 | + .iterate_shared = shared_coda_readdir, | |
| 592 | 586 | .open = coda_open, |
| 593 | 587 | .release = coda_release, |
| 594 | 588 | .fsync = coda_fsync, |
| @@ -889,8 +889,6 @@ static void erofs_kill_sb(struct super_block *sb) · 888 unmodified lines | ||
| 889 | 889 | { |
| 890 | 890 | struct erofs_sb_info *sbi; |
| 891 | 891 | |
| 892 | − WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); | |
| 893 | − | |
| 894 | 892 | /* pseudo mount for anon inodes */ |
| 895 | 893 | if (sb->s_flags & SB_KERNMOUNT) { |
| 896 | 894 | kill_anon_super(sb); |
| @@ -1144,10 +1144,11 @@ static void z_erofs_do_decompressed_bvec(struct z_erofs_decompress_backend *be, · 1143 unmodified lines | ||
| 1144 | 1144 | struct z_erofs_bvec *bvec) |
| 1145 | 1145 | { |
| 1146 | 1146 | struct z_erofs_bvec_item *item; |
| 1147 | + unsigned int pgnr; | |
| 1147 | 1148 | |
| 1148 | − if (!((bvec->offset + be->pcl->pageofs_out) & ~PAGE_MASK)) { | |
| 1149 | − unsigned int pgnr; | |
| 1150 | − | |
| 1149 | + if (!((bvec->offset + be->pcl->pageofs_out) & ~PAGE_MASK) && | |
| 1150 | + (bvec->end == PAGE_SIZE || | |
| 1151 | + bvec->offset + bvec->end == be->pcl->length)) { | |
| 1151 | 1152 | pgnr = (bvec->offset + be->pcl->pageofs_out) >> PAGE_SHIFT; |
| 1152 | 1153 | DBG_BUGON(pgnr >= be->nr_pages); |
| 1153 | 1154 | if (!be->decompressed_pages[pgnr]) { |
| @@ -69,7 +69,7 @@ static int exfat_allocate_bitmap(struct super_block *sb, · 68 unmodified lines | ||
| 69 | 69 | } |
| 70 | 70 | sbi->map_sectors = ((need_map_size - 1) >> |
| 71 | 71 | (sb->s_blocksize_bits)) + 1; |
| 72 | − sbi->vol_amap = kmalloc_array(sbi->map_sectors, | |
| 72 | + sbi->vol_amap = kvmalloc_array(sbi->map_sectors, | |
| 73 | 73 | sizeof(struct buffer_head *), GFP_KERNEL); |
| 74 | 74 | if (!sbi->vol_amap) |
| 75 | 75 | return -ENOMEM; |
| @@ -84,7 +84,7 @@ static int exfat_allocate_bitmap(struct super_block *sb, · 8 unmodified lines | ||
| 84 | 84 | while (j < i) |
| 85 | 85 | brelse(sbi->vol_amap[j++]); |
| 86 | 86 | |
| 87 | − kfree(sbi->vol_amap); | |
| 87 | + kvfree(sbi->vol_amap); | |
| 88 | 88 | sbi->vol_amap = NULL; |
| 89 | 89 | return -EIO; |
| 90 | 90 | } |
| @@ -138,7 +138,7 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi) · 47 unmodified lines | ||
| 138 | 138 | for (i = 0; i < sbi->map_sectors; i++) |
| 139 | 139 | __brelse(sbi->vol_amap[i]); |
| 140 | 140 | |
| 141 | − kfree(sbi->vol_amap); | |
| 141 | + kvfree(sbi->vol_amap); | |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | 144 | int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync) |
| @@ -34,6 +34,7 @@ static int exfat_get_uniname_from_ext_entry(struct super_block *sb, · 33 unmodified lines | ||
| 34 | 34 | { |
| 35 | 35 | int i, err; |
| 36 | 36 | struct exfat_entry_set_cache es; |
| 37 | + unsigned int uni_len = 0, len; | |
| 37 | 38 | |
| 38 | 39 | err = exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES); |
| 39 | 40 | if (err) |
| @@ -52,7 +53,10 @@ static int exfat_get_uniname_from_ext_entry(struct super_block *sb, · 12 unmodified lines | ||
| 52 | 53 | if (exfat_get_entry_type(ep) != TYPE_EXTEND) |
| 53 | 54 | break; |
| 54 | 55 | |
| 55 | − exfat_extract_uni_name(ep, uniname); | |
| 56 | + len = exfat_extract_uni_name(ep, uniname); | |
| 57 | + uni_len += len; | |
| 58 | + if (len != EXFAT_FILE_NAME_LEN || uni_len >= MAX_NAME_LENGTH) | |
| 59 | + break; | |
| 56 | 60 | uniname += EXFAT_FILE_NAME_LEN; |
| 57 | 61 | } |
| 58 | 62 | |
| @@ -214,7 +218,10 @@ static void exfat_free_namebuf(struct exfat_dentry_namebuf *nb) · 155 unmodified lines | ||
| 214 | 218 | exfat_init_namebuf(nb); |
| 215 | 219 | } |
| 216 | 220 | |
| 217 | −/* skip iterating emit_dots when dir is empty */ | |
| 221 | +/* | |
| 222 | + * Before calling dir_emit*(), sbi->s_lock should be released | |
| 223 | + * because page fault can occur in dir_emit*(). | |
| 224 | + */ | |
| 218 | 225 | #define ITER_POS_FILLED_DOTS (2) |
| 219 | 226 | static int exfat_iterate(struct file *file, struct dir_context *ctx) |
| 220 | 227 | { |
| @@ -229,11 +236,10 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx) · 8 unmodified lines | ||
| 229 | 236 | int err = 0, fake_offset = 0; |
| 230 | 237 | |
| 231 | 238 | exfat_init_namebuf(nb); |
| 232 | − mutex_lock(&EXFAT_SB(sb)->s_lock); | |
| 233 | 239 | |
| 234 | 240 | cpos = ctx->pos; |
| 235 | 241 | if (!dir_emit_dots(file, ctx)) |
| 236 | − goto unlock; | |
| 242 | + goto out; | |
| 237 | 243 | |
| 238 | 244 | if (ctx->pos == ITER_POS_FILLED_DOTS) { |
| 239 | 245 | cpos = 0; |
| @@ -245,16 +251,18 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx) · 5 unmodified lines | ||
| 245 | 251 | /* name buffer should be allocated before use */ |
| 246 | 252 | err = exfat_alloc_namebuf(nb); |
| 247 | 253 | if (err) |
| 248 | − goto unlock; | |
| 254 | + goto out; | |
| 249 | 255 | get_new: |
| 256 | + mutex_lock(&EXFAT_SB(sb)->s_lock); | |
| 257 | + | |
| 250 | 258 | if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode)) |
| 251 | 259 | goto end_of_dir; |
| 252 | 260 | |
| 253 | 261 | err = exfat_readdir(inode, &cpos, &de); |
| 254 | 262 | if (err) { |
| 255 | 263 | /* |
| 256 | − * At least we tried to read a sector. Move cpos to next sector | |
| 257 | − * position (should be aligned). | |
| 264 | + * At least we tried to read a sector. | |
| 265 | + * Move cpos to next sector position (should be aligned). | |
| 258 | 266 | */ |
| 259 | 267 | if (err == -EIO) { |
| 260 | 268 | cpos += 1 << (sb->s_blocksize_bits); |
| @@ -277,16 +285,10 @@ get_new: · 16 unmodified lines | ||
| 277 | 285 | inum = iunique(sb, EXFAT_ROOT_INO); |
| 278 | 286 | } |
| 279 | 287 | |
| 280 | − /* | |
| 281 | − * Before calling dir_emit(), sb_lock should be released. | |
| 282 | − * Because page fault can occur in dir_emit() when the size | |
| 283 | − * of buffer given from user is larger than one page size. | |
| 284 | − */ | |
| 285 | 288 | mutex_unlock(&EXFAT_SB(sb)->s_lock); |
| 286 | 289 | if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum, |
| 287 | 290 | (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) |
| 288 | − goto out_unlocked; | |
| 289 | − mutex_lock(&EXFAT_SB(sb)->s_lock); | |
| 291 | + goto out; | |
| 290 | 292 | ctx->pos = cpos; |
| 291 | 293 | goto get_new; |
| 292 | 294 | |
| @@ -294,9 +296,8 @@ end_of_dir: · 1 unmodified line | ||
| 294 | 296 | if (!cpos && fake_offset) |
| 295 | 297 | cpos = ITER_POS_FILLED_DOTS; |
| 296 | 298 | ctx->pos = cpos; |
| 297 | −unlock: | |
| 298 | 299 | mutex_unlock(&EXFAT_SB(sb)->s_lock); |
| 299 | −out_unlocked: | |
| 300 | +out: | |
| 300 | 301 | /* |
| 301 | 302 | * To improve performance, free namebuf after unlock sb_lock. |
| 302 | 303 | * If namebuf is not allocated, this function do nothing |
| @@ -305,10 +306,11 @@ out_unlocked: · 2 unmodified lines | ||
| 305 | 306 | return err; |
| 306 | 307 | } |
| 307 | 308 | |
| 309 | +WRAP_DIR_ITER(exfat_iterate) // FIXME! | |
| 308 | 310 | const struct file_operations exfat_dir_operations = { |
| 309 | 311 | .llseek = generic_file_llseek, |
| 310 | 312 | .read = generic_read_dir, |
| 311 | − .iterate = exfat_iterate, | |
| 313 | + .iterate_shared = shared_exfat_iterate, | |
| 312 | 314 | .unlocked_ioctl = exfat_ioctl, |
| 313 | 315 | #ifdef CONFIG_COMPAT |
| 314 | 316 | .compat_ioctl = exfat_compat_ioctl, |
| @@ -1079,7 +1081,8 @@ rewind: · 764 unmodified lines | ||
| 1079 | 1081 | if (entry_type == TYPE_EXTEND) { |
| 1080 | 1082 | unsigned short entry_uniname[16], unichar; |
| 1081 | 1083 | |
| 1082 | − if (step != DIRENT_STEP_NAME) { | |
| 1084 | + if (step != DIRENT_STEP_NAME || | |
| 1085 | + name_len >= MAX_NAME_LENGTH) { | |
| 1083 | 1086 | step = DIRENT_STEP_FILE; |
| 1084 | 1087 | continue; |
| 1085 | 1088 | } |
| @@ -315,7 +315,7 @@ static int get_name(const struct path *path, char *name, struct dentry *child) · 314 unmodified lines | ||
| 315 | 315 | goto out; |
| 316 | 316 | |
| 317 | 317 | error = -EINVAL; |
| 318 | − if (!file->f_op->iterate && !file->f_op->iterate_shared) | |
| 318 | + if (!file->f_op->iterate_shared) | |
| 319 | 319 | goto out_close; |
| 320 | 320 | |
| 321 | 321 | buffer.sequence = 0; |
| @@ -1036,12 +1036,28 @@ unsigned long __fdget_raw(unsigned int fd) · 1035 unmodified lines | ||
| 1036 | 1036 | return __fget_light(fd, 0); |
| 1037 | 1037 | } |
| 1038 | 1038 | |
| 1039 | +/* | |
| 1040 | + * Try to avoid f_pos locking. We only need it if the | |
| 1041 | + * file is marked for FMODE_ATOMIC_POS, and it can be | |
| 1042 | + * accessed multiple ways. | |
| 1043 | + * | |
| 1044 | + * Always do it for directories, because pidfd_getfd() | |
| 1045 | + * can make a file accessible even if it otherwise would | |
| 1046 | + * not be, and for directories this is a correctness | |
| 1047 | + * issue, not a "POSIX requirement". | |
| 1048 | + */ | |
| 1049 | +static inline bool file_needs_f_pos_lock(struct file *file) | |
| 1050 | +{ | |
| 1051 | + return (file->f_mode & FMODE_ATOMIC_POS) && | |
| 1052 | + (file_count(file) > 1 || file->f_op->iterate_shared); | |
| 1053 | +} | |
| 1054 | + | |
| 1039 | 1055 | unsigned long __fdget_pos(unsigned int fd) |
| 1040 | 1056 | { |
| 1041 | 1057 | unsigned long v = __fdget(fd); |
| 1042 | 1058 | struct file *file = (struct file *)(v & ~3); |
| 1043 | 1059 | |
| 1044 | − if (file && (file->f_mode & FMODE_ATOMIC_POS)) { | |
| 1060 | + if (file && file_needs_f_pos_lock(file)) { | |
| 1045 | 1061 | v |= FDPUT_POS_UNLOCK; |
| 1046 | 1062 | mutex_lock(&file->f_pos_lock); |
| 1047 | 1063 | } |
| @@ -1578,7 +1578,7 @@ const struct file_operations gfs2_file_fops = { · 1577 unmodified lines | ||
| 1578 | 1578 | .fsync = gfs2_fsync, |
| 1579 | 1579 | .lock = gfs2_lock, |
| 1580 | 1580 | .flock = gfs2_flock, |
| 1581 | − .splice_read = filemap_splice_read, | |
| 1581 | + .splice_read = copy_splice_read, | |
| 1582 | 1582 | .splice_write = gfs2_file_splice_write, |
| 1583 | 1583 | .setlease = simple_nosetlease, |
| 1584 | 1584 | .fallocate = gfs2_fallocate, |
| @@ -1609,7 +1609,7 @@ const struct file_operations gfs2_file_fops_nolock = { · 24 unmodified lines | ||
| 1609 | 1609 | .open = gfs2_open, |
| 1610 | 1610 | .release = gfs2_release, |
| 1611 | 1611 | .fsync = gfs2_fsync, |
| 1612 | − .splice_read = filemap_splice_read, | |
| 1612 | + .splice_read = copy_splice_read, | |
| 1613 | 1613 | .splice_write = gfs2_file_splice_write, |
| 1614 | 1614 | .setlease = generic_setlease, |
| 1615 | 1615 | .fallocate = gfs2_fallocate, |
| @@ -230,9 +230,11 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) · 229 unmodified lines | ||
| 230 | 230 | { |
| 231 | 231 | |
| 232 | 232 | struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; |
| 233 | + struct super_block *sb = sdp->sd_vfs; | |
| 233 | 234 | struct gfs2_bufdata *bd; |
| 234 | 235 | struct gfs2_meta_header *mh; |
| 235 | 236 | struct gfs2_trans *tr = current->journal_info; |
| 237 | + bool withdraw = false; | |
| 236 | 238 | |
| 237 | 239 | lock_buffer(bh); |
| 238 | 240 | if (buffer_pinned(bh)) { |
| @@ -266,13 +268,15 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) · 27 unmodified lines | ||
| 266 | 268 | (unsigned long long)bd->bd_bh->b_blocknr); |
| 267 | 269 | BUG(); |
| 268 | 270 | } |
| 269 | − if (unlikely(test_bit(SDF_FROZEN, &sdp->sd_flags))) { | |
| 270 | − fs_info(sdp, "GFS2:adding buf while frozen\n"); | |
| 271 | − gfs2_assert_withdraw(sdp, 0); | |
| 272 | − } | |
| 273 | 271 | if (unlikely(gfs2_withdrawn(sdp))) { |
| 274 | 272 | fs_info(sdp, "GFS2:adding buf while withdrawn! 0x%llx\n", |
| 275 | 273 | (unsigned long long)bd->bd_bh->b_blocknr); |
| 274 | + goto out_unlock; | |
| 275 | + } | |
| 276 | + if (unlikely(sb->s_writers.frozen == SB_FREEZE_COMPLETE)) { | |
| 277 | + fs_info(sdp, "GFS2:adding buf while frozen\n"); | |
| 278 | + withdraw = true; | |
| 279 | + goto out_unlock; | |
| 276 | 280 | } |
| 277 | 281 | gfs2_pin(sdp, bd->bd_bh); |
| 278 | 282 | mh->__pad0 = cpu_to_be64(0); |
| @@ -281,6 +285,8 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh) · 2 unmodified lines | ||
| 281 | 285 | tr->tr_num_buf_new++; |
| 282 | 286 | out_unlock: |
| 283 | 287 | gfs2_log_unlock(sdp); |
| 288 | + if (withdraw) | |
| 289 | + gfs2_assert_withdraw(sdp, 0); | |
| 284 | 290 | out: |
| 285 | 291 | unlock_buffer(bh); |
| 286 | 292 | } |
| @@ -16,7 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/fsnotify.h> |
| 17 | 17 | #include <linux/mount.h> |
| 18 | 18 | #include <linux/posix_acl.h> |
| 19 | −#include <linux/prefetch.h> | |
| 20 | 19 | #include <linux/buffer_head.h> /* for inode_has_buffers */ |
| 21 | 20 | #include <linux/ratelimit.h> |
| 22 | 21 | #include <linux/list_lru.h> |
| @@ -1041,8 +1040,6 @@ struct inode *new_inode(struct super_block *sb) · 1018 unmodified lines | ||
| 1041 | 1040 | { |
| 1042 | 1041 | struct inode *inode; |
| 1043 | 1042 | |
| 1044 | − spin_lock_prefetch(&sb->s_inode_list_lock); | |
| 1045 | − | |
| 1046 | 1043 | inode = new_inode_pseudo(sb); |
| 1047 | 1044 | if (inode) |
| 1048 | 1045 | inode_sb_list_add(inode); |
| @@ -1535,9 +1535,10 @@ const struct inode_operations jfs_dir_inode_operations = { · 1534 unmodified lines | ||
| 1535 | 1535 | #endif |
| 1536 | 1536 | }; |
| 1537 | 1537 | |
| 1538 | +WRAP_DIR_ITER(jfs_readdir) // FIXME! | |
| 1538 | 1539 | const struct file_operations jfs_dir_operations = { |
| 1539 | 1540 | .read = generic_read_dir, |
| 1540 | − .iterate = jfs_readdir, | |
| 1541 | + .iterate_shared = shared_jfs_readdir, | |
| 1541 | 1542 | .fsync = jfs_fsync, |
| 1542 | 1543 | .unlocked_ioctl = jfs_ioctl, |
| 1543 | 1544 | .compat_ioctl = compat_ptr_ioctl, |
| @@ -956,10 +956,13 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, · 955 unmodified lines | ||
| 956 | 956 | last_page = page + (offset + sd->len - 1) / PAGE_SIZE; |
| 957 | 957 | for (page += offset / PAGE_SIZE; page <= last_page; page++) { |
| 958 | 958 | /* |
| 959 | − * Skip page replacement when extending the contents | |
| 960 | − * of the current page. | |
| 959 | + * Skip page replacement when extending the contents of the | |
| 960 | + * current page. But note that we may get two zero_pages in a | |
| 961 | + * row from shmem. | |
| 961 | 962 | */ |
| 962 | − if (page == *(rqstp->rq_next_page - 1)) | |
| 963 | + if (page == *(rqstp->rq_next_page - 1) && | |
| 964 | + offset_in_page(rqstp->rq_res.page_base + | |
| 965 | + rqstp->rq_res.page_len)) | |
| 963 | 966 | continue; |
| 964 | 967 | if (unlikely(!svc_rqst_replace_page(rqstp, page))) |
| 965 | 968 | return -EIO; |
| @@ -1101,9 +1101,17 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned int nr_dirty) · 1100 unmodified lines | ||
| 1101 | 1101 | |
| 1102 | 1102 | int __nilfs_mark_inode_dirty(struct inode *inode, int flags) |
| 1103 | 1103 | { |
| 1104 | + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; | |
| 1104 | 1105 | struct buffer_head *ibh; |
| 1105 | 1106 | int err; |
| 1106 | 1107 | |
| 1108 | + /* | |
| 1109 | + * Do not dirty inodes after the log writer has been detached | |
| 1110 | + * and its nilfs_root struct has been freed. | |
| 1111 | + */ | |
| 1112 | + if (unlikely(nilfs_purging(nilfs))) | |
| 1113 | + return 0; | |
| 1114 | + | |
| 1107 | 1115 | err = nilfs_load_inode_block(inode, &ibh); |
| 1108 | 1116 | if (unlikely(err)) { |
| 1109 | 1117 | nilfs_warn(inode->i_sb, |
| @@ -2845,6 +2845,7 @@ void nilfs_detach_log_writer(struct super_block *sb) · 2844 unmodified lines | ||
| 2845 | 2845 | nilfs_segctor_destroy(nilfs->ns_writer); |
| 2846 | 2846 | nilfs->ns_writer = NULL; |
| 2847 | 2847 | } |
| 2848 | + set_nilfs_purging(nilfs); | |
| 2848 | 2849 | |
| 2849 | 2850 | /* Force to free the list of dirty files */ |
| 2850 | 2851 | spin_lock(&nilfs->ns_inode_lock); |
| @@ -2857,4 +2858,5 @@ void nilfs_detach_log_writer(struct super_block *sb) · 6 unmodified lines | ||
| 2857 | 2858 | up_write(&nilfs->ns_segctor_sem); |
| 2858 | 2859 | |
| 2859 | 2860 | nilfs_dispose_list(nilfs, &garbage_list, 1); |
| 2861 | + clear_nilfs_purging(nilfs); | |
| 2860 | 2862 | } |
| @@ -29,6 +29,7 @@ enum { · 28 unmodified lines | ||
| 29 | 29 | THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */ |
| 30 | 30 | THE_NILFS_GC_RUNNING, /* gc process is running */ |
| 31 | 31 | THE_NILFS_SB_DIRTY, /* super block is dirty */ |
| 32 | + THE_NILFS_PURGING, /* disposing dirty files for cleanup */ | |
| 32 | 33 | }; |
| 33 | 34 | |
| 34 | 35 | /** |
| @@ -208,6 +209,7 @@ THE_NILFS_FNS(INIT, init) · 173 unmodified lines | ||
| 208 | 209 | THE_NILFS_FNS(DISCONTINUED, discontinued) |
| 209 | 210 | THE_NILFS_FNS(GC_RUNNING, gc_running) |
| 210 | 211 | THE_NILFS_FNS(SB_DIRTY, sb_dirty) |
| 212 | +THE_NILFS_FNS(PURGING, purging) | |
| 211 | 213 | |
| 212 | 214 | /* |
| 213 | 215 | * Mount option operations |
| @@ -1525,10 +1525,11 @@ static int ntfs_dir_fsync(struct file *filp, loff_t start, loff_t end, · 1524 unmodified lines | ||
| 1525 | 1525 | |
| 1526 | 1526 | #endif /* NTFS_RW */ |
| 1527 | 1527 | |
| 1528 | +WRAP_DIR_ITER(ntfs_readdir) // FIXME! | |
| 1528 | 1529 | const struct file_operations ntfs_dir_ops = { |
| 1529 | 1530 | .llseek = generic_file_llseek, /* Seek inside directory. */ |
| 1530 | 1531 | .read = generic_read_dir, /* Return -EISDIR. */ |
| 1531 | − .iterate = ntfs_readdir, /* Read directory contents. */ | |
| 1532 | + .iterate_shared = shared_ntfs_readdir, /* Read directory contents. */ | |
| 1532 | 1533 | #ifdef NTFS_RW |
| 1533 | 1534 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ |
| 1534 | 1535 | #endif /* NTFS_RW */ |
| @@ -2793,10 +2793,11 @@ const struct file_operations ocfs2_fops = { · 2792 unmodified lines | ||
| 2793 | 2793 | .remap_file_range = ocfs2_remap_file_range, |
| 2794 | 2794 | }; |
| 2795 | 2795 | |
| 2796 | +WRAP_DIR_ITER(ocfs2_readdir) // FIXME! | |
| 2796 | 2797 | const struct file_operations ocfs2_dops = { |
| 2797 | 2798 | .llseek = generic_file_llseek, |
| 2798 | 2799 | .read = generic_read_dir, |
| 2799 | − .iterate = ocfs2_readdir, | |
| 2800 | + .iterate_shared = shared_ocfs2_readdir, | |
| 2800 | 2801 | .fsync = ocfs2_sync_file, |
| 2801 | 2802 | .release = ocfs2_dir_release, |
| 2802 | 2803 | .open = ocfs2_dir_open, |
| @@ -2842,7 +2843,7 @@ const struct file_operations ocfs2_fops_no_plocks = { · 39 unmodified lines | ||
| 2842 | 2843 | const struct file_operations ocfs2_dops_no_plocks = { |
| 2843 | 2844 | .llseek = generic_file_llseek, |
| 2844 | 2845 | .read = generic_read_dir, |
| 2845 | − .iterate = ocfs2_readdir, | |
| 2846 | + .iterate_shared = shared_ocfs2_readdir, | |
| 2846 | 2847 | .fsync = ocfs2_sync_file, |
| 2847 | 2848 | .release = ocfs2_dir_release, |
| 2848 | 2849 | .open = ocfs2_dir_open, |
| @@ -1322,7 +1322,7 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op) · 1321 unmodified lines | ||
| 1322 | 1322 | lookup_flags |= LOOKUP_IN_ROOT; |
| 1323 | 1323 | if (how->resolve & RESOLVE_CACHED) { |
| 1324 | 1324 | /* Don't bother even trying for create/truncate/tmpfile open */ |
| 1325 | − if (flags & (O_TRUNC | O_CREAT | O_TMPFILE)) | |
| 1325 | + if (flags & (O_TRUNC | O_CREAT | __O_TMPFILE)) | |
| 1326 | 1326 | return -EAGAIN; |
| 1327 | 1327 | lookup_flags |= LOOKUP_CACHED; |
| 1328 | 1328 | } |
| @@ -954,10 +954,11 @@ static int ovl_dir_open(struct inode *inode, struct file *file) · 953 unmodified lines | ||
| 954 | 954 | return 0; |
| 955 | 955 | } |
| 956 | 956 | |
| 957 | +WRAP_DIR_ITER(ovl_iterate) // FIXME! | |
| 957 | 958 | const struct file_operations ovl_dir_operations = { |
| 958 | 959 | .read = generic_read_dir, |
| 959 | 960 | .open = ovl_dir_open, |
| 960 | − .iterate = ovl_iterate, | |
| 961 | + .iterate_shared = shared_ovl_iterate, | |
| 961 | 962 | .llseek = ovl_dir_llseek, |
| 962 | 963 | .fsync = ovl_dir_fsync, |
| 963 | 964 | .release = ovl_dir_release, |
| @@ -2817,7 +2817,7 @@ static int proc_##LSM##_attr_dir_iterate(struct file *filp, \ · 2816 unmodified lines | ||
| 2817 | 2817 | \ |
| 2818 | 2818 | static const struct file_operations proc_##LSM##_attr_dir_ops = { \ |
| 2819 | 2819 | .read = generic_read_dir, \ |
| 2820 | − .iterate = proc_##LSM##_attr_dir_iterate, \ | |
| 2820 | + .iterate_shared = proc_##LSM##_attr_dir_iterate, \ | |
| 2821 | 2821 | .llseek = default_llseek, \ |
| 2822 | 2822 | }; \ |
| 2823 | 2823 | \ |
| @@ -309,6 +309,8 @@ static void append_kcore_note(char *notes, size_t *i, const char *name, · 308 unmodified lines | ||
| 309 | 309 | |
| 310 | 310 | static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter) |
| 311 | 311 | { |
| 312 | + struct file *file = iocb->ki_filp; | |
| 313 | + char *buf = file->private_data; | |
| 312 | 314 | loff_t *fpos = &iocb->ki_pos; |
| 313 | 315 | size_t phdrs_offset, notes_offset, data_offset; |
| 314 | 316 | size_t page_offline_frozen = 1; |
| @@ -555,10 +557,21 @@ static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter) · 240 unmodified lines | ||
| 555 | 557 | case KCORE_VMEMMAP: |
| 556 | 558 | case KCORE_TEXT: |
| 557 | 559 | /* |
| 558 | − * We use _copy_to_iter() to bypass usermode hardening | |
| 559 | − * which would otherwise prevent this operation. | |
| 560 | + * Sadly we must use a bounce buffer here to be able to | |
| 561 | + * make use of copy_from_kernel_nofault(), as these | |
| 562 | + * memory regions might not always be mapped on all | |
| 563 | + * architectures. | |
| 560 | 564 | */ |
| 561 | − if (_copy_to_iter((char *)start, tsz, iter) != tsz) { | |
| 565 | + if (copy_from_kernel_nofault(buf, (void *)start, tsz)) { | |
| 566 | + if (iov_iter_zero(tsz, iter) != tsz) { | |
| 567 | + ret = -EFAULT; | |
| 568 | + goto out; | |
| 569 | + } | |
| 570 | + /* | |
| 571 | + * We know the bounce buffer is safe to copy from, so | |
| 572 | + * use _copy_to_iter() directly. | |
| 573 | + */ | |
| 574 | + } else if (_copy_to_iter(buf, tsz, iter) != tsz) { | |
| 562 | 575 | ret = -EFAULT; |
| 563 | 576 | goto out; |
| 564 | 577 | } |
| @@ -595,6 +608,10 @@ static int open_kcore(struct inode *inode, struct file *filp) · 30 unmodified lines | ||
| 595 | 608 | if (ret) |
| 596 | 609 | return ret; |
| 597 | 610 | |
| 611 | + filp->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL); | |
| 612 | + if (!filp->private_data) | |
| 613 | + return -ENOMEM; | |
| 614 | + | |
| 598 | 615 | if (kcore_need_update) |
| 599 | 616 | kcore_update_ram(); |
| 600 | 617 | if (i_size_read(inode) != proc_root_kcore->size) { |
| @@ -605,9 +622,16 @@ static int open_kcore(struct inode *inode, struct file *filp) · 4 unmodified lines | ||
| 605 | 622 | return 0; |
| 606 | 623 | } |
| 607 | 624 | |
| 625 | +static int release_kcore(struct inode *inode, struct file *file) | |
| 626 | +{ | |
| 627 | + kfree(file->private_data); | |
| 628 | + return 0; | |
| 629 | +} | |
| 630 | + | |
| 608 | 631 | static const struct proc_ops kcore_proc_ops = { |
| 609 | 632 | .proc_read_iter = read_kcore_iter, |
| 610 | 633 | .proc_open = open_kcore, |
| 634 | + .proc_release = release_kcore, | |
| 611 | 635 | .proc_lseek = default_llseek, |
| 612 | 636 | }; |
| 613 | 637 | |
| @@ -24,6 +24,53 @@ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | #include <asm/unaligned.h> |
| 26 | 26 | |
| 27 | +/* | |
| 28 | + * Some filesystems were never converted to '->iterate_shared()' | |
| 29 | + * and their directory iterators want the inode lock held for | |
| 30 | + * writing. This wrapper allows for converting from the shared | |
| 31 | + * semantics to the exclusive inode use. | |
| 32 | + */ | |
| 33 | +int wrap_directory_iterator(struct file *file, | |
| 34 | + struct dir_context *ctx, | |
| 35 | + int (*iter)(struct file *, struct dir_context *)) | |
| 36 | +{ | |
| 37 | + struct inode *inode = file_inode(file); | |
| 38 | + int ret; | |
| 39 | + | |
| 40 | + /* | |
| 41 | + * We'd love to have an 'inode_upgrade_trylock()' operation, | |
| 42 | + * see the comment in mmap_upgrade_trylock() in mm/memory.c. | |
| 43 | + * | |
| 44 | + * But considering this is for "filesystems that never got | |
| 45 | + * converted", it really doesn't matter. | |
| 46 | + * | |
| 47 | + * Also note that since we have to return with the lock held | |
| 48 | + * for reading, we can't use the "killable()" locking here, | |
| 49 | + * since we do need to get the lock even if we're dying. | |
| 50 | + * | |
| 51 | + * We could do the write part killably and then get the read | |
| 52 | + * lock unconditionally if it mattered, but see above on why | |
| 53 | + * this does the very simplistic conversion. | |
| 54 | + */ | |
| 55 | + up_read(&inode->i_rwsem); | |
| 56 | + down_write(&inode->i_rwsem); | |
| 57 | + | |
| 58 | + /* | |
| 59 | + * Since we dropped the inode lock, we should do the | |
| 60 | + * DEADDIR test again. See 'iterate_dir()' below. | |
| 61 | + * | |
| 62 | + * Note that we don't need to re-do the f_pos games, | |
| 63 | + * since the file must be locked wrt f_pos anyway. | |
| 64 | + */ | |
| 65 | + ret = -ENOENT; | |
| 66 | + if (!IS_DEADDIR(inode)) | |
| 67 | + ret = iter(file, ctx); | |
| 68 | + | |
| 69 | + downgrade_write(&inode->i_rwsem); | |
| 70 | + return ret; | |
| 71 | +} | |
| 72 | +EXPORT_SYMBOL(wrap_directory_iterator); | |
| 73 | + | |
| 27 | 74 | /* |
| 28 | 75 | * Note the "unsafe_put_user() semantics: we goto a |
| 29 | 76 | * label for errors. |
| @@ -40,39 +87,28 @@ · 10 unmodified lines | ||
| 40 | 87 | int iterate_dir(struct file *file, struct dir_context *ctx) |
| 41 | 88 | { |
| 42 | 89 | struct inode *inode = file_inode(file); |
| 43 | − bool shared = false; | |
| 44 | 90 | int res = -ENOTDIR; |
| 45 | − if (file->f_op->iterate_shared) | |
| 46 | − shared = true; | |
| 47 | − else if (!file->f_op->iterate) | |
| 91 | + | |
| 92 | + if (!file->f_op->iterate_shared) | |
| 48 | 93 | goto out; |
| 49 | 94 | |
| 50 | 95 | res = security_file_permission(file, MAY_READ); |
| 51 | 96 | if (res) |
| 52 | 97 | goto out; |
| 53 | 98 | |
| 54 | − if (shared) | |
| 55 | − res = down_read_killable(&inode->i_rwsem); | |
| 56 | − else | |
| 57 | − res = down_write_killable(&inode->i_rwsem); | |
| 99 | + res = down_read_killable(&inode->i_rwsem); | |
| 58 | 100 | if (res) |
| 59 | 101 | goto out; |
| 60 | 102 | |
| 61 | 103 | res = -ENOENT; |
| 62 | 104 | if (!IS_DEADDIR(inode)) { |
| 63 | 105 | ctx->pos = file->f_pos; |
| 64 | − if (shared) | |
| 65 | − res = file->f_op->iterate_shared(file, ctx); | |
| 66 | − else | |
| 67 | − res = file->f_op->iterate(file, ctx); | |
| 106 | + res = file->f_op->iterate_shared(file, ctx); | |
| 68 | 107 | file->f_pos = ctx->pos; |
| 69 | 108 | fsnotify_access(file); |
| 70 | 109 | file_accessed(file); |
| 71 | 110 | } |
| 72 | − if (shared) | |
| 73 | − inode_unlock_shared(inode); | |
| 74 | − else | |
| 75 | − inode_unlock(inode); | |
| 111 | + inode_unlock_shared(inode); | |
| 76 | 112 | out: |
| 77 | 113 | return res; |
| 78 | 114 | } |
| @@ -177,8 +177,12 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) · 176 unmodified lines | ||
| 177 | 177 | struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl); |
| 178 | 178 | |
| 179 | 179 | rc = dfs_get_referral(mnt_ctx, ref_path + 1, NULL, &tl); |
| 180 | − if (rc) | |
| 180 | + if (rc) { | |
| 181 | + rc = cifs_mount_get_tcon(mnt_ctx); | |
| 182 | + if (!rc) | |
| 183 | + rc = cifs_is_path_remote(mnt_ctx); | |
| 181 | 184 | break; |
| 185 | + } | |
| 182 | 186 | |
| 183 | 187 | tit = dfs_cache_get_tgt_iterator(&tl); |
| 184 | 188 | if (!tit) { |
| @@ -380,13 +380,13 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) · 379 unmodified lines | ||
| 380 | 380 | } |
| 381 | 381 | |
| 382 | 382 | if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { |
| 383 | − if (command == SMB2_OPLOCK_BREAK_HE && | |
| 384 | − le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 && | |
| 385 | − le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) { | |
| 383 | + if (!(command == SMB2_OPLOCK_BREAK_HE && | |
| 384 | + (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 || | |
| 385 | + le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_21))) { | |
| 386 | 386 | /* special case for SMB2.1 lease break message */ |
| 387 | 387 | ksmbd_debug(SMB, |
| 388 | − "Illegal request size %d for oplock break\n", | |
| 389 | − le16_to_cpu(pdu->StructureSize2)); | |
| 388 | + "Illegal request size %u for command %d\n", | |
| 389 | + le16_to_cpu(pdu->StructureSize2), command); | |
| 390 | 390 | return 1; |
| 391 | 391 | } |
| 392 | 392 | } |
| @@ -2324,9 +2324,16 @@ next: · 2323 unmodified lines | ||
| 2324 | 2324 | break; |
| 2325 | 2325 | buf_len -= next; |
| 2326 | 2326 | eabuf = (struct smb2_ea_info *)((char *)eabuf + next); |
| 2327 | − if (next < (u32)eabuf->EaNameLength + le16_to_cpu(eabuf->EaValueLength)) | |
| 2327 | + if (buf_len < sizeof(struct smb2_ea_info)) { | |
| 2328 | + rc = -EINVAL; | |
| 2328 | 2329 | break; |
| 2330 | + } | |
| 2329 | 2331 | |
| 2332 | + if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + | |
| 2333 | + le16_to_cpu(eabuf->EaValueLength)) { | |
| 2334 | + rc = -EINVAL; | |
| 2335 | + break; | |
| 2336 | + } | |
| 2330 | 2337 | } while (next != 0); |
| 2331 | 2338 | |
| 2332 | 2339 | kfree(attr_name); |
| @@ -179,9 +179,10 @@ static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx) · 178 unmodified lines | ||
| 179 | 179 | return 0; |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | +WRAP_DIR_ITER(vboxsf_dir_iterate) // FIXME! | |
| 182 | 183 | const struct file_operations vboxsf_dir_fops = { |
| 183 | 184 | .open = vboxsf_dir_open, |
| 184 | − .iterate = vboxsf_dir_iterate, | |
| 185 | + .iterate_shared = shared_vboxsf_dir_iterate, | |
| 185 | 186 | .release = vboxsf_dir_release, |
| 186 | 187 | .read = generic_read_dir, |
| 187 | 188 | .llseek = generic_file_llseek, |
| @@ -68,9 +68,9 @@ struct shfl_string { · 67 unmodified lines | ||
| 68 | 68 | |
| 69 | 69 | /** UTF-8 or UTF-16 string. Nul terminated. */ |
| 70 | 70 | union { |
| 71 | − u8 utf8[2]; | |
| 72 | − u16 utf16[1]; | |
| 73 | − u16 ucs2[1]; /* misnomer, use utf16. */ | |
| 71 | + u8 legacy_padding[2]; | |
| 72 | + DECLARE_FLEX_ARRAY(u8, utf8); | |
| 73 | + DECLARE_FLEX_ARRAY(u16, utf16); | |
| 74 | 74 | } string; |
| 75 | 75 | }; |
| 76 | 76 | VMMDEV_ASSERT_SIZE(shfl_string, 6); |
| @@ -341,77 +341,6 @@ static loff_t zonefs_file_llseek(struct file *file, loff_t offset, int whence) · 340 unmodified lines | ||
| 341 | 341 | return generic_file_llseek_size(file, offset, whence, isize, isize); |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | −struct zonefs_zone_append_bio { | |
| 345 | − /* The target inode of the BIO */ | |
| 346 | − struct inode *inode; | |
| 347 | − | |
| 348 | − /* For sync writes, the target append write offset */ | |
| 349 | − u64 append_offset; | |
| 350 | − | |
| 351 | − /* | |
| 352 | − * This member must come last, bio_alloc_bioset will allocate enough | |
| 353 | − * bytes for entire zonefs_bio but relies on bio being last. | |
| 354 | − */ | |
| 355 | − struct bio bio; | |
| 356 | −}; | |
| 357 | − | |
| 358 | −static inline struct zonefs_zone_append_bio * | |
| 359 | −zonefs_zone_append_bio(struct bio *bio) | |
| 360 | −{ | |
| 361 | − return container_of(bio, struct zonefs_zone_append_bio, bio); | |
| 362 | −} | |
| 363 | − | |
| 364 | −static void zonefs_file_zone_append_dio_bio_end_io(struct bio *bio) | |
| 365 | −{ | |
| 366 | − struct zonefs_zone_append_bio *za_bio = zonefs_zone_append_bio(bio); | |
| 367 | − struct zonefs_zone *z = zonefs_inode_zone(za_bio->inode); | |
| 368 | − sector_t za_sector; | |
| 369 | − | |
| 370 | − if (bio->bi_status != BLK_STS_OK) | |
| 371 | − goto bio_end; | |
| 372 | − | |
| 373 | − /* | |
| 374 | − * If the file zone was written underneath the file system, the zone | |
| 375 | − * append operation can still succedd (if the zone is not full) but | |
| 376 | − * the write append location will not be where we expect it to be. | |
| 377 | − * Check that we wrote where we intended to, that is, at z->z_wpoffset. | |
| 378 | − */ | |
| 379 | − za_sector = z->z_sector + (za_bio->append_offset >> SECTOR_SHIFT); | |
| 380 | − if (bio->bi_iter.bi_sector != za_sector) { | |
| 381 | − zonefs_warn(za_bio->inode->i_sb, | |
| 382 | − "Invalid write sector %llu for zone at %llu\n", | |
| 383 | − bio->bi_iter.bi_sector, z->z_sector); | |
| 384 | − bio->bi_status = BLK_STS_IOERR; | |
| 385 | − } | |
| 386 | − | |
| 387 | −bio_end: | |
| 388 | − iomap_dio_bio_end_io(bio); | |
| 389 | −} | |
| 390 | − | |
| 391 | −static void zonefs_file_zone_append_dio_submit_io(const struct iomap_iter *iter, | |
| 392 | − struct bio *bio, | |
| 393 | − loff_t file_offset) | |
| 394 | −{ | |
| 395 | − struct zonefs_zone_append_bio *za_bio = zonefs_zone_append_bio(bio); | |
| 396 | − struct inode *inode = iter->inode; | |
| 397 | − struct zonefs_zone *z = zonefs_inode_zone(inode); | |
| 398 | − | |
| 399 | − /* | |
| 400 | − * Issue a zone append BIO to process sync dio writes. The append | |
| 401 | − * file offset is saved to check the zone append write location | |
| 402 | − * on completion of the BIO. | |
| 403 | − */ | |
| 404 | − za_bio->inode = inode; | |
| 405 | − za_bio->append_offset = file_offset; | |
| 406 | − | |
| 407 | − bio->bi_opf &= ~REQ_OP_WRITE; | |
| 408 | − bio->bi_opf |= REQ_OP_ZONE_APPEND; | |
| 409 | − bio->bi_iter.bi_sector = z->z_sector; | |
| 410 | − bio->bi_end_io = zonefs_file_zone_append_dio_bio_end_io; | |
| 411 | − | |
| 412 | − submit_bio(bio); | |
| 413 | −} | |
| 414 | − | |
| 415 | 344 | static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size, |
| 416 | 345 | int error, unsigned int flags) |
| 417 | 346 | { |
| @@ -442,14 +371,6 @@ static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size, · 24 unmodified lines | ||
| 442 | 371 | return 0; |
| 443 | 372 | } |
| 444 | 373 | |
| 445 | −static struct bio_set zonefs_zone_append_bio_set; | |
| 446 | − | |
| 447 | −static const struct iomap_dio_ops zonefs_zone_append_dio_ops = { | |
| 448 | − .submit_io = zonefs_file_zone_append_dio_submit_io, | |
| 449 | − .end_io = zonefs_file_write_dio_end_io, | |
| 450 | − .bio_set = &zonefs_zone_append_bio_set, | |
| 451 | −}; | |
| 452 | − | |
| 453 | 374 | static const struct iomap_dio_ops zonefs_write_dio_ops = { |
| 454 | 375 | .end_io = zonefs_file_write_dio_end_io, |
| 455 | 376 | }; |
| @@ -533,9 +454,6 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from) · 77 unmodified lines | ||
| 533 | 454 | struct zonefs_inode_info *zi = ZONEFS_I(inode); |
| 534 | 455 | struct zonefs_zone *z = zonefs_inode_zone(inode); |
| 535 | 456 | struct super_block *sb = inode->i_sb; |
| 536 | − const struct iomap_dio_ops *dio_ops; | |
| 537 | − bool sync = is_sync_kiocb(iocb); | |
| 538 | − bool append = false; | |
| 539 | 457 | ssize_t ret, count; |
| 540 | 458 | |
| 541 | 459 | /* |
| @@ -543,7 +461,8 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from) · 1 unmodified line | ||
| 543 | 461 | * as this can cause write reordering (e.g. the first aio gets EAGAIN |
| 544 | 462 | * on the inode lock but the second goes through but is now unaligned). |
| 545 | 463 | */ |
| 546 | − if (zonefs_zone_is_seq(z) && !sync && (iocb->ki_flags & IOCB_NOWAIT)) | |
| 464 | + if (zonefs_zone_is_seq(z) && !is_sync_kiocb(iocb) && | |
| 465 | + (iocb->ki_flags & IOCB_NOWAIT)) | |
| 547 | 466 | return -EOPNOTSUPP; |
| 548 | 467 | |
| 549 | 468 | if (iocb->ki_flags & IOCB_NOWAIT) { |
| @@ -573,18 +492,6 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from) · 23 unmodified lines | ||
| 573 | 492 | goto inode_unlock; |
| 574 | 493 | } |
| 575 | 494 | mutex_unlock(&zi->i_truncate_mutex); |
| 576 | − append = sync; | |
| 577 | − } | |
| 578 | − | |
| 579 | − if (append) { | |
| 580 | − unsigned int max = bdev_max_zone_append_sectors(sb->s_bdev); | |
| 581 | − | |
| 582 | − max = ALIGN_DOWN(max << SECTOR_SHIFT, sb->s_blocksize); | |
| 583 | − iov_iter_truncate(from, max); | |
| 584 | − | |
| 585 | − dio_ops = &zonefs_zone_append_dio_ops; | |
| 586 | − } else { | |
| 587 | − dio_ops = &zonefs_write_dio_ops; | |
| 588 | 495 | } |
| 589 | 496 | |
| 590 | 497 | /* |
| @@ -593,7 +500,7 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from) · 2 unmodified lines | ||
| 593 | 500 | * the user can make sense of the error. |
| 594 | 501 | */ |
| 595 | 502 | ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops, |
| 596 | − dio_ops, 0, NULL, 0); | |
| 503 | + &zonefs_write_dio_ops, 0, NULL, 0); | |
| 597 | 504 | if (ret == -ENOTBLK) |
| 598 | 505 | ret = -EBUSY; |
| 599 | 506 | |
| @@ -938,15 +845,3 @@ const struct file_operations zonefs_file_operations = { · 338 unmodified lines | ||
| 938 | 845 | .splice_write = iter_file_splice_write, |
| 939 | 846 | .iopoll = iocb_bio_iopoll, |
| 940 | 847 | }; |
| 941 | − | |
| 942 | −int zonefs_file_bioset_init(void) | |
| 943 | −{ | |
| 944 | − return bioset_init(&zonefs_zone_append_bio_set, BIO_POOL_SIZE, | |
| 945 | − offsetof(struct zonefs_zone_append_bio, bio), | |
| 946 | − BIOSET_NEED_BVECS); | |
| 947 | −} | |
| 948 | − | |
| 949 | −void zonefs_file_bioset_exit(void) | |
| 950 | −{ | |
| 951 | − bioset_exit(&zonefs_zone_append_bio_set); | |
| 952 | −} | |
| @@ -1412,13 +1412,9 @@ static int __init zonefs_init(void) · 1411 unmodified lines | ||
| 1412 | 1412 | |
| 1413 | 1413 | BUILD_BUG_ON(sizeof(struct zonefs_super) != ZONEFS_SUPER_SIZE); |
| 1414 | 1414 | |
| 1415 | − ret = zonefs_file_bioset_init(); | |
| 1416 | − if (ret) | |
| 1417 | − return ret; | |
| 1418 | − | |
| 1419 | 1415 | ret = zonefs_init_inodecache(); |
| 1420 | 1416 | if (ret) |
| 1421 | − goto destroy_bioset; | |
| 1417 | + return ret; | |
| 1422 | 1418 | |
| 1423 | 1419 | ret = zonefs_sysfs_init(); |
| 1424 | 1420 | if (ret) |
| @@ -1434,8 +1430,6 @@ sysfs_exit: · 9 unmodified lines | ||
| 1434 | 1430 | zonefs_sysfs_exit(); |
| 1435 | 1431 | destroy_inodecache: |
| 1436 | 1432 | zonefs_destroy_inodecache(); |
| 1437 | −destroy_bioset: | |
| 1438 | − zonefs_file_bioset_exit(); | |
| 1439 | 1433 | |
| 1440 | 1434 | return ret; |
| 1441 | 1435 | } |
| @@ -1445,7 +1439,6 @@ static void __exit zonefs_exit(void) · 3 unmodified lines | ||
| 1445 | 1439 | unregister_filesystem(&zonefs_type); |
| 1446 | 1440 | zonefs_sysfs_exit(); |
| 1447 | 1441 | zonefs_destroy_inodecache(); |
| 1448 | − zonefs_file_bioset_exit(); | |
| 1449 | 1442 | } |
| 1450 | 1443 | |
| 1451 | 1444 | MODULE_AUTHOR("Damien Le Moal"); |
| @@ -279,8 +279,6 @@ extern const struct file_operations zonefs_dir_operations; · 278 unmodified lines | ||
| 279 | 279 | extern const struct address_space_operations zonefs_file_aops; |
| 280 | 280 | extern const struct file_operations zonefs_file_operations; |
| 281 | 281 | int zonefs_file_truncate(struct inode *inode, loff_t isize); |
| 282 | −int zonefs_file_bioset_init(void); | |
| 283 | −void zonefs_file_bioset_exit(void); | |
| 284 | 282 | |
| 285 | 283 | /* In sysfs.c */ |
| 286 | 284 | int zonefs_sysfs_register(struct super_block *sb); |
| @@ -190,7 +190,7 @@ int hv_common_cpu_die(unsigned int cpu); · 189 unmodified lines | ||
| 190 | 190 | |
| 191 | 191 | void *hv_alloc_hyperv_page(void); |
| 192 | 192 | void *hv_alloc_hyperv_zeroed_page(void); |
| 193 | −void hv_free_hyperv_page(unsigned long addr); | |
| 193 | +void hv_free_hyperv_page(void *addr); | |
| 194 | 194 | |
| 195 | 195 | /** |
| 196 | 196 | * hv_cpu_number_to_vp_number() - Map CPU to VP. |
| @@ -38,7 +38,7 @@ static inline long find_zero(unsigned long mask) · 37 unmodified lines | ||
| 38 | 38 | return (mask >> 8) ? byte : byte + 1; |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | −static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) | |
| 41 | +static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c) | |
| 42 | 42 | { |
| 43 | 43 | unsigned long rhs = val | c->low_bits; |
| 44 | 44 | *data = rhs; |
| @@ -791,7 +791,7 @@ static inline int bio_integrity_add_page(struct bio *bio, struct page *page, · 790 unmodified lines | ||
| 791 | 791 | static inline void bio_set_polled(struct bio *bio, struct kiocb *kiocb) |
| 792 | 792 | { |
| 793 | 793 | bio->bi_opf |= REQ_POLLED; |
| 794 | − if (!is_sync_kiocb(kiocb)) | |
| 794 | + if (kiocb->ki_flags & IOCB_NOWAIT) | |
| 795 | 795 | bio->bi_opf |= REQ_NOWAIT; |
| 796 | 796 | } |
| 797 | 797 | |
| @@ -969,7 +969,6 @@ struct blk_plug { · 968 unmodified lines | ||
| 969 | 969 | |
| 970 | 970 | bool multiple_queues; |
| 971 | 971 | bool has_elevator; |
| 972 | − bool nowait; | |
| 973 | 972 | |
| 974 | 973 | struct list_head cb_list; /* md requires an unplug callback */ |
| 975 | 974 | }; |
| @@ -70,6 +70,10 @@ extern ssize_t cpu_show_mmio_stale_data(struct device *dev, · 69 unmodified lines | ||
| 70 | 70 | char *buf); |
| 71 | 71 | extern ssize_t cpu_show_retbleed(struct device *dev, |
| 72 | 72 | struct device_attribute *attr, char *buf); |
| 73 | +extern ssize_t cpu_show_spec_rstack_overflow(struct device *dev, | |
| 74 | + struct device_attribute *attr, char *buf); | |
| 75 | +extern ssize_t cpu_show_gds(struct device *dev, | |
| 76 | + struct device_attribute *attr, char *buf); | |
| 73 | 77 | |
| 74 | 78 | extern __printf(4, 5) |
| 75 | 79 | struct device *cpu_device_create(struct device *parent, void *drvdata, |
| @@ -175,8 +175,8 @@ static inline unsigned int cpumask_first_zero(const struct cpumask *srcp) · 174 unmodified lines | ||
| 175 | 175 | |
| 176 | 176 | /** |
| 177 | 177 | * cpumask_first_and - return the first cpu from *srcp1 & *srcp2 |
| 178 | − * @src1p: the first input | |
| 179 | − * @src2p: the second input | |
| 178 | + * @srcp1: the first input | |
| 179 | + * @srcp2: the second input | |
| 180 | 180 | * |
| 181 | 181 | * Returns >= nr_cpu_ids if no cpus set in both. See also cpumask_next_and(). |
| 182 | 182 | */ |
| @@ -1197,6 +1197,10 @@ cpumap_print_bitmask_to_buf(char *buf, const struct cpumask *mask, · 1014 unmodified lines | ||
| 1197 | 1197 | /** |
| 1198 | 1198 | * cpumap_print_list_to_buf - copies the cpumask into the buffer as |
| 1199 | 1199 | * comma-separated list of cpus |
| 1200 | + * @buf: the buffer to copy into | |
| 1201 | + * @mask: the cpumask to copy | |
| 1202 | + * @off: in the string from which we are copying, we copy to @buf | |
| 1203 | + * @count: the maximum number of bytes to print | |
| 1200 | 1204 | * |
| 1201 | 1205 | * Everything is same with the above cpumap_print_bitmask_to_buf() |
| 1202 | 1206 | * except the print format. |
| @@ -1780,7 +1780,6 @@ struct file_operations { · 1779 unmodified lines | ||
| 1780 | 1780 | ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); |
| 1781 | 1781 | int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *, |
| 1782 | 1782 | unsigned int flags); |
| 1783 | − int (*iterate) (struct file *, struct dir_context *); | |
| 1784 | 1783 | int (*iterate_shared) (struct file *, struct dir_context *); |
| 1785 | 1784 | __poll_t (*poll) (struct file *, struct poll_table_struct *); |
| 1786 | 1785 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); |
| @@ -1817,6 +1816,13 @@ struct file_operations { · 30 unmodified lines | ||
| 1817 | 1816 | unsigned int poll_flags); |
| 1818 | 1817 | } __randomize_layout; |
| 1819 | 1818 | |
| 1819 | +/* Wrap a directory iterator that needs exclusive inode access */ | |
| 1820 | +int wrap_directory_iterator(struct file *, struct dir_context *, | |
| 1821 | + int (*) (struct file *, struct dir_context *)); | |
| 1822 | +#define WRAP_DIR_ITER(x) \ | |
| 1823 | + static int shared_##x(struct file *file , struct dir_context *ctx) \ | |
| 1824 | + { return wrap_directory_iterator(file, ctx, x); } | |
| 1825 | + | |
| 1820 | 1826 | struct inode_operations { |
| 1821 | 1827 | struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); |
| 1822 | 1828 | const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); |
| @@ -1239,9 +1239,6 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel, · 1238 unmodified lines | ||
| 1239 | 1239 | u32 *buffer_actual_len, |
| 1240 | 1240 | u64 *requestid); |
| 1241 | 1241 | |
| 1242 | − | |
| 1243 | −extern void vmbus_ontimer(unsigned long data); | |
| 1244 | − | |
| 1245 | 1242 | /* Base driver object */ |
| 1246 | 1243 | struct hv_driver { |
| 1247 | 1244 | const char *name; |
| @@ -100,10 +100,16 @@ struct rapl_package; · 99 unmodified lines | ||
| 100 | 100 | |
| 101 | 101 | #define RAPL_DOMAIN_NAME_LENGTH 16 |
| 102 | 102 | |
| 103 | +union rapl_reg { | |
| 104 | + void __iomem *mmio; | |
| 105 | + u32 msr; | |
| 106 | + u64 val; | |
| 107 | +}; | |
| 108 | + | |
| 103 | 109 | struct rapl_domain { |
| 104 | 110 | char name[RAPL_DOMAIN_NAME_LENGTH]; |
| 105 | 111 | enum rapl_domain_type id; |
| 106 | − u64 regs[RAPL_DOMAIN_REG_MAX]; | |
| 112 | + union rapl_reg regs[RAPL_DOMAIN_REG_MAX]; | |
| 107 | 113 | struct powercap_zone power_zone; |
| 108 | 114 | struct rapl_domain_data rdd; |
| 109 | 115 | struct rapl_power_limit rpl[NR_POWER_LIMITS]; |
| @@ -116,7 +122,7 @@ struct rapl_domain { · 6 unmodified lines | ||
| 116 | 122 | }; |
| 117 | 123 | |
| 118 | 124 | struct reg_action { |
| 119 | − u64 reg; | |
| 125 | + union rapl_reg reg; | |
| 120 | 126 | u64 mask; |
| 121 | 127 | u64 value; |
| 122 | 128 | int err; |
| @@ -143,8 +149,8 @@ struct rapl_if_priv { · 20 unmodified lines | ||
| 143 | 149 | enum rapl_if_type type; |
| 144 | 150 | struct powercap_control_type *control_type; |
| 145 | 151 | enum cpuhp_state pcap_rapl_online; |
| 146 | − u64 reg_unit; | |
| 147 | − u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX]; | |
| 152 | + union rapl_reg reg_unit; | |
| 153 | + union rapl_reg regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX]; | |
| 148 | 154 | int limits[RAPL_DOMAIN_MAX]; |
| 149 | 155 | int (*read_raw)(int id, struct reg_action *ra); |
| 150 | 156 | int (*write_raw)(int id, struct reg_action *ra); |
| @@ -25,11 +25,10 @@ struct page; · 24 unmodified lines | ||
| 25 | 25 | prefetch() should be defined by the architecture, if not, the |
| 26 | 26 | #define below provides a no-op define. |
| 27 | 27 | |
| 28 | − There are 3 prefetch() macros: | |
| 28 | + There are 2 prefetch() macros: | |
| 29 | 29 | |
| 30 | 30 | prefetch(x) - prefetches the cacheline at "x" for read |
| 31 | 31 | prefetchw(x) - prefetches the cacheline at "x" for write |
| 32 | − spin_lock_prefetch(x) - prefetches the spinlock *x for taking | |
| 33 | 32 | |
| 34 | 33 | there is also PREFETCH_STRIDE which is the architecure-preferred |
| 35 | 34 | "lookahead" size for prefetching streamed operations. |
| @@ -44,10 +43,6 @@ struct page; · 8 unmodified lines | ||
| 44 | 43 | #define prefetchw(x) __builtin_prefetch(x,1) |
| 45 | 44 | #endif |
| 46 | 45 | |
| 47 | −#ifndef ARCH_HAS_SPINLOCK_PREFETCH | |
| 48 | −#define spin_lock_prefetch(x) prefetchw(x) | |
| 49 | −#endif | |
| 50 | − | |
| 51 | 46 | #ifndef PREFETCH_STRIDE |
| 52 | 47 | #define PREFETCH_STRIDE (4*L1_CACHE_BYTES) |
| 53 | 48 | #endif |
| @@ -62,6 +62,7 @@ struct sk_psock_progs { · 61 unmodified lines | ||
| 62 | 62 | |
| 63 | 63 | enum sk_psock_state_bits { |
| 64 | 64 | SK_PSOCK_TX_ENABLED, |
| 65 | + SK_PSOCK_RX_STRP_ENABLED, | |
| 65 | 66 | }; |
| 66 | 67 | |
| 67 | 68 | struct sk_psock_link { |
| @@ -15,4 +15,6 @@ struct corgi_lcd_platform_data { · 14 unmodified lines | ||
| 15 | 15 | void (*kick_battery)(void); |
| 16 | 16 | }; |
| 17 | 17 | |
| 18 | +void corgi_lcd_limit_intensity(int limit); | |
| 19 | + | |
| 18 | 20 | #endif /* __LINUX_SPI_CORGI_LCD_H */ |
| @@ -101,6 +101,7 @@ struct spi_mem_op { · 100 unmodified lines | ||
| 101 | 101 | u8 nbytes; |
| 102 | 102 | u8 buswidth; |
| 103 | 103 | u8 dtr : 1; |
| 104 | + u8 __pad : 7; | |
| 104 | 105 | u16 opcode; |
| 105 | 106 | } cmd; |
| 106 | 107 | |
| @@ -108,6 +109,7 @@ struct spi_mem_op { · 1 unmodified line | ||
| 108 | 109 | u8 nbytes; |
| 109 | 110 | u8 buswidth; |
| 110 | 111 | u8 dtr : 1; |
| 112 | + u8 __pad : 7; | |
| 111 | 113 | u64 val; |
| 112 | 114 | } addr; |
| 113 | 115 | |
| @@ -115,12 +117,14 @@ struct spi_mem_op { · 1 unmodified line | ||
| 115 | 117 | u8 nbytes; |
| 116 | 118 | u8 buswidth; |
| 117 | 119 | u8 dtr : 1; |
| 120 | + u8 __pad : 7; | |
| 118 | 121 | } dummy; |
| 119 | 122 | |
| 120 | 123 | struct { |
| 121 | 124 | u8 buswidth; |
| 122 | 125 | u8 dtr : 1; |
| 123 | 126 | u8 ecc : 1; |
| 127 | + u8 __pad : 6; | |
| 124 | 128 | enum spi_mem_data_dir dir; |
| 125 | 129 | unsigned int nbytes; |
| 126 | 130 | union { |
| @@ -283,6 +283,7 @@ enum tpm_chip_flags { · 282 unmodified lines | ||
| 283 | 283 | TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED = BIT(6), |
| 284 | 284 | TPM_CHIP_FLAG_FIRMWARE_UPGRADE = BIT(7), |
| 285 | 285 | TPM_CHIP_FLAG_SUSPENDED = BIT(8), |
| 286 | + TPM_CHIP_FLAG_HWRNG_DISABLED = BIT(9), | |
| 286 | 287 | }; |
| 287 | 288 | |
| 288 | 289 | #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) |
| @@ -562,6 +562,9 @@ ieee80211_get_sband_iftype_data(const struct ieee80211_supported_band *sband, · 561 unmodified lines | ||
| 562 | 562 | if (WARN_ON(iftype >= NL80211_IFTYPE_MAX)) |
| 563 | 563 | return NULL; |
| 564 | 564 | |
| 565 | + if (iftype == NL80211_IFTYPE_AP_VLAN) | |
| 566 | + iftype = NL80211_IFTYPE_AP; | |
| 567 | + | |
| 565 | 568 | for (i = 0; i < sband->n_iftype_data; i++) { |
| 566 | 569 | const struct ieee80211_sband_iftype_data *data = |
| 567 | 570 | &sband->iftype_data[i]; |
| @@ -452,6 +452,49 @@ static inline void gro_normal_one(struct napi_struct *napi, struct sk_buff *skb, · 451 unmodified lines | ||
| 452 | 452 | gro_normal_list(napi); |
| 453 | 453 | } |
| 454 | 454 | |
| 455 | +/* This function is the alternative of 'inet_iif' and 'inet_sdif' | |
| 456 | + * functions in case we can not rely on fields of IPCB. | |
| 457 | + * | |
| 458 | + * The caller must verify skb_valid_dst(skb) is false and skb->dev is initialized. | |
| 459 | + * The caller must hold the RCU read lock. | |
| 460 | + */ | |
| 461 | +static inline void inet_get_iif_sdif(const struct sk_buff *skb, int *iif, int *sdif) | |
| 462 | +{ | |
| 463 | + *iif = inet_iif(skb) ?: skb->dev->ifindex; | |
| 464 | + *sdif = 0; | |
| 465 | + | |
| 466 | +#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) | |
| 467 | + if (netif_is_l3_slave(skb->dev)) { | |
| 468 | + struct net_device *master = netdev_master_upper_dev_get_rcu(skb->dev); | |
| 469 | + | |
| 470 | + *sdif = *iif; | |
| 471 | + *iif = master ? master->ifindex : 0; | |
| 472 | + } | |
| 473 | +#endif | |
| 474 | +} | |
| 475 | + | |
| 476 | +/* This function is the alternative of 'inet6_iif' and 'inet6_sdif' | |
| 477 | + * functions in case we can not rely on fields of IP6CB. | |
| 478 | + * | |
| 479 | + * The caller must verify skb_valid_dst(skb) is false and skb->dev is initialized. | |
| 480 | + * The caller must hold the RCU read lock. | |
| 481 | + */ | |
| 482 | +static inline void inet6_get_iif_sdif(const struct sk_buff *skb, int *iif, int *sdif) | |
| 483 | +{ | |
| 484 | + /* using skb->dev->ifindex because skb_dst(skb) is not initialized */ | |
| 485 | + *iif = skb->dev->ifindex; | |
| 486 | + *sdif = 0; | |
| 487 | + | |
| 488 | +#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) | |
| 489 | + if (netif_is_l3_slave(skb->dev)) { | |
| 490 | + struct net_device *master = netdev_master_upper_dev_get_rcu(skb->dev); | |
| 491 | + | |
| 492 | + *sdif = *iif; | |
| 493 | + *iif = master ? master->ifindex : 0; | |
| 494 | + } | |
| 495 | +#endif | |
| 496 | +} | |
| 497 | + | |
| 455 | 498 | extern struct list_head offload_base; |
| 456 | 499 | |
| 457 | 500 | #endif /* _NET_IPV6_GRO_H */ |
| @@ -107,11 +107,12 @@ static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk) · 106 unmodified lines | ||
| 107 | 107 | |
| 108 | 108 | static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb) |
| 109 | 109 | { |
| 110 | − if (!sk->sk_mark && | |
| 111 | − READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept)) | |
| 110 | + u32 mark = READ_ONCE(sk->sk_mark); | |
| 111 | + | |
| 112 | + if (!mark && READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept)) | |
| 112 | 113 | return skb->mark; |
| 113 | 114 | |
| 114 | − return sk->sk_mark; | |
| 115 | + return mark; | |
| 115 | 116 | } |
| 116 | 117 | |
| 117 | 118 | static inline int inet_request_bound_dev_if(const struct sock *sk, |
| @@ -93,7 +93,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm, · 92 unmodified lines | ||
| 93 | 93 | { |
| 94 | 94 | ipcm_init(ipcm); |
| 95 | 95 | |
| 96 | − ipcm->sockc.mark = inet->sk.sk_mark; | |
| 96 | + ipcm->sockc.mark = READ_ONCE(inet->sk.sk_mark); | |
| 97 | 97 | ipcm->sockc.tsflags = inet->sk.sk_tsflags; |
| 98 | 98 | ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if); |
| 99 | 99 | ipcm->addr = inet->inet_saddr; |
| @@ -512,6 +512,7 @@ struct nft_set_elem_expr { · 511 unmodified lines | ||
| 512 | 512 | * |
| 513 | 513 | * @list: table set list node |
| 514 | 514 | * @bindings: list of set bindings |
| 515 | + * @refs: internal refcounting for async set destruction | |
| 515 | 516 | * @table: table this set belongs to |
| 516 | 517 | * @net: netnamespace this set belongs to |
| 517 | 518 | * @name: name of the set |
| @@ -541,6 +542,7 @@ struct nft_set_elem_expr { · 23 unmodified lines | ||
| 541 | 542 | struct nft_set { |
| 542 | 543 | struct list_head list; |
| 543 | 544 | struct list_head bindings; |
| 545 | + refcount_t refs; | |
| 544 | 546 | struct nft_table *table; |
| 545 | 547 | possible_net_t net; |
| 546 | 548 | char *name; |
| @@ -562,7 +564,8 @@ struct nft_set { · 15 unmodified lines | ||
| 562 | 564 | struct list_head pending_update; |
| 563 | 565 | /* runtime data below here */ |
| 564 | 566 | const struct nft_set_ops *ops ____cacheline_aligned; |
| 565 | − u16 flags:14, | |
| 567 | + u16 flags:13, | |
| 568 | + dead:1, | |
| 566 | 569 | genmask:2; |
| 567 | 570 | u8 klen; |
| 568 | 571 | u8 dlen; |
| @@ -596,7 +599,6 @@ struct nft_set *nft_set_lookup_global(const struct net *net, · 27 unmodified lines | ||
| 596 | 599 | |
| 597 | 600 | struct nft_set_ext *nft_set_catchall_lookup(const struct net *net, |
| 598 | 601 | const struct nft_set *set); |
| 599 | −void *nft_set_catchall_gc(const struct nft_set *set); | |
| 600 | 602 | |
| 601 | 603 | static inline unsigned long nft_set_gc_interval(const struct nft_set *set) |
| 602 | 604 | { |
| @@ -813,62 +815,6 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem, · 210 unmodified lines | ||
| 813 | 815 | void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, |
| 814 | 816 | const struct nft_set *set, void *elem); |
| 815 | 817 | |
| 816 | −/** | |
| 817 | − * struct nft_set_gc_batch_head - nf_tables set garbage collection batch | |
| 818 | − * | |
| 819 | − * @rcu: rcu head | |
| 820 | − * @set: set the elements belong to | |
| 821 | − * @cnt: count of elements | |
| 822 | − */ | |
| 823 | −struct nft_set_gc_batch_head { | |
| 824 | − struct rcu_head rcu; | |
| 825 | − const struct nft_set *set; | |
| 826 | − unsigned int cnt; | |
| 827 | −}; | |
| 828 | − | |
| 829 | −#define NFT_SET_GC_BATCH_SIZE ((PAGE_SIZE - \ | |
| 830 | − sizeof(struct nft_set_gc_batch_head)) / \ | |
| 831 | − sizeof(void *)) | |
| 832 | − | |
| 833 | −/** | |
| 834 | − * struct nft_set_gc_batch - nf_tables set garbage collection batch | |
| 835 | − * | |
| 836 | − * @head: GC batch head | |
| 837 | − * @elems: garbage collection elements | |
| 838 | − */ | |
| 839 | −struct nft_set_gc_batch { | |
| 840 | − struct nft_set_gc_batch_head head; | |
| 841 | − void *elems[NFT_SET_GC_BATCH_SIZE]; | |
| 842 | −}; | |
| 843 | − | |
| 844 | −struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set, | |
| 845 | − gfp_t gfp); | |
| 846 | −void nft_set_gc_batch_release(struct rcu_head *rcu); | |
| 847 | − | |
| 848 | −static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb) | |
| 849 | −{ | |
| 850 | − if (gcb != NULL) | |
| 851 | − call_rcu(&gcb->head.rcu, nft_set_gc_batch_release); | |
| 852 | −} | |
| 853 | − | |
| 854 | −static inline struct nft_set_gc_batch * | |
| 855 | −nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb, | |
| 856 | − gfp_t gfp) | |
| 857 | −{ | |
| 858 | − if (gcb != NULL) { | |
| 859 | − if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems)) | |
| 860 | − return gcb; | |
| 861 | − nft_set_gc_batch_complete(gcb); | |
| 862 | − } | |
| 863 | − return nft_set_gc_batch_alloc(set, gfp); | |
| 864 | −} | |
| 865 | − | |
| 866 | −static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb, | |
| 867 | − void *elem) | |
| 868 | −{ | |
| 869 | − gcb->elems[gcb->head.cnt++] = elem; | |
| 870 | −} | |
| 871 | − | |
| 872 | 818 | struct nft_expr_ops; |
| 873 | 819 | /** |
| 874 | 820 | * struct nft_expr_type - nf_tables expression type |
| @@ -1557,39 +1503,30 @@ static inline void nft_set_elem_change_active(const struct net *net, · 682 unmodified lines | ||
| 1557 | 1503 | |
| 1558 | 1504 | #endif /* IS_ENABLED(CONFIG_NF_TABLES) */ |
| 1559 | 1505 | |
| 1560 | −/* | |
| 1561 | − * We use a free bit in the genmask field to indicate the element | |
| 1562 | − * is busy, meaning it is currently being processed either by | |
| 1563 | − * the netlink API or GC. | |
| 1564 | − * | |
| 1565 | − * Even though the genmask is only a single byte wide, this works | |
| 1566 | − * because the extension structure if fully constant once initialized, | |
| 1567 | − * so there are no non-atomic write accesses unless it is already | |
| 1568 | − * marked busy. | |
| 1569 | − */ | |
| 1570 | −#define NFT_SET_ELEM_BUSY_MASK (1 << 2) | |
| 1506 | +#define NFT_SET_ELEM_DEAD_MASK (1 << 2) | |
| 1571 | 1507 | |
| 1572 | 1508 | #if defined(__LITTLE_ENDIAN_BITFIELD) |
| 1573 | −#define NFT_SET_ELEM_BUSY_BIT 2 | |
| 1509 | +#define NFT_SET_ELEM_DEAD_BIT 2 | |
| 1574 | 1510 | #elif defined(__BIG_ENDIAN_BITFIELD) |
| 1575 | −#define NFT_SET_ELEM_BUSY_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2) | |
| 1511 | +#define NFT_SET_ELEM_DEAD_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2) | |
| 1576 | 1512 | #else |
| 1577 | 1513 | #error |
| 1578 | 1514 | #endif |
| 1579 | 1515 | |
| 1580 | −static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext) | |
| 1516 | +static inline void nft_set_elem_dead(struct nft_set_ext *ext) | |
| 1581 | 1517 | { |
| 1582 | 1518 | unsigned long *word = (unsigned long *)ext; |
| 1583 | 1519 | |
| 1584 | 1520 | BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0); |
| 1585 | − return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word); | |
| 1521 | + set_bit(NFT_SET_ELEM_DEAD_BIT, word); | |
| 1586 | 1522 | } |
| 1587 | 1523 | |
| 1588 | −static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext) | |
| 1524 | +static inline int nft_set_elem_is_dead(const struct nft_set_ext *ext) | |
| 1589 | 1525 | { |
| 1590 | 1526 | unsigned long *word = (unsigned long *)ext; |
| 1591 | 1527 | |
| 1592 | − clear_bit(NFT_SET_ELEM_BUSY_BIT, word); | |
| 1528 | + BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0); | |
| 1529 | + return test_bit(NFT_SET_ELEM_DEAD_BIT, word); | |
| 1593 | 1530 | } |
| 1594 | 1531 | |
| 1595 | 1532 | /** |
| @@ -1732,6 +1669,38 @@ struct nft_trans_flowtable { · 136 unmodified lines | ||
| 1732 | 1669 | #define nft_trans_flowtable_flags(trans) \ |
| 1733 | 1670 | (((struct nft_trans_flowtable *)trans->data)->flags) |
| 1734 | 1671 | |
| 1672 | +#define NFT_TRANS_GC_BATCHCOUNT 256 | |
| 1673 | + | |
| 1674 | +struct nft_trans_gc { | |
| 1675 | + struct list_head list; | |
| 1676 | + struct net *net; | |
| 1677 | + struct nft_set *set; | |
| 1678 | + u32 seq; | |
| 1679 | + u8 count; | |
| 1680 | + void *priv[NFT_TRANS_GC_BATCHCOUNT]; | |
| 1681 | + struct rcu_head rcu; | |
| 1682 | +}; | |
| 1683 | + | |
| 1684 | +struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set, | |
| 1685 | + unsigned int gc_seq, gfp_t gfp); | |
| 1686 | +void nft_trans_gc_destroy(struct nft_trans_gc *trans); | |
| 1687 | + | |
| 1688 | +struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc, | |
| 1689 | + unsigned int gc_seq, gfp_t gfp); | |
| 1690 | +void nft_trans_gc_queue_async_done(struct nft_trans_gc *gc); | |
| 1691 | + | |
| 1692 | +struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp); | |
| 1693 | +void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans); | |
| 1694 | + | |
| 1695 | +void nft_trans_gc_elem_add(struct nft_trans_gc *gc, void *priv); | |
| 1696 | + | |
| 1697 | +struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc, | |
| 1698 | + unsigned int gc_seq); | |
| 1699 | + | |
| 1700 | +void nft_setelem_data_deactivate(const struct net *net, | |
| 1701 | + const struct nft_set *set, | |
| 1702 | + struct nft_set_elem *elem); | |
| 1703 | + | |
| 1735 | 1704 | int __init nft_chain_filter_init(void); |
| 1736 | 1705 | void nft_chain_filter_fini(void); |
| 1737 | 1706 | |
| @@ -1758,6 +1727,7 @@ struct nftables_pernet { · 20 unmodified lines | ||
| 1758 | 1727 | struct mutex commit_mutex; |
| 1759 | 1728 | u64 table_handle; |
| 1760 | 1729 | unsigned int base_seq; |
| 1730 | + unsigned int gc_seq; | |
| 1761 | 1731 | }; |
| 1762 | 1732 | |
| 1763 | 1733 | extern unsigned int nf_tables_net_id; |
| @@ -168,7 +168,7 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi · 167 unmodified lines | ||
| 168 | 168 | __be16 dport, __be16 sport, |
| 169 | 169 | __u8 proto, __u8 tos, int oif) |
| 170 | 170 | { |
| 171 | − flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos, | |
| 171 | + flowi4_init_output(fl4, oif, sk ? READ_ONCE(sk->sk_mark) : 0, tos, | |
| 172 | 172 | RT_SCOPE_UNIVERSE, proto, |
| 173 | 173 | sk ? inet_sk_flowi_flags(sk) : 0, |
| 174 | 174 | daddr, saddr, dport, sport, sock_net_uid(net, sk)); |
| @@ -301,7 +301,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, · 126 unmodified lines | ||
| 301 | 301 | if (inet_sk(sk)->transparent) |
| 302 | 302 | flow_flags |= FLOWI_FLAG_ANYSRC; |
| 303 | 303 | |
| 304 | − flowi4_init_output(fl4, oif, sk->sk_mark, ip_sock_rt_tos(sk), | |
| 304 | + flowi4_init_output(fl4, oif, READ_ONCE(sk->sk_mark), ip_sock_rt_tos(sk), | |
| 305 | 305 | ip_sock_rt_scope(sk), protocol, flow_flags, dst, |
| 306 | 306 | src, dport, sport, sk->sk_uid); |
| 307 | 307 | } |
| @@ -556,12 +556,12 @@ static inline void vxlan_flag_attr_error(int attrtype, · 555 unmodified lines | ||
| 556 | 556 | } |
| 557 | 557 | |
| 558 | 558 | static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh, |
| 559 | − int hash, | |
| 559 | + u32 hash, | |
| 560 | 560 | struct vxlan_rdst *rdst) |
| 561 | 561 | { |
| 562 | 562 | struct fib_nh_common *nhc; |
| 563 | 563 | |
| 564 | − nhc = nexthop_path_fdb_result(nh, hash); | |
| 564 | + nhc = nexthop_path_fdb_result(nh, hash >> 1); | |
| 565 | 565 | if (unlikely(!nhc)) |
| 566 | 566 | return false; |
| 567 | 567 | |
| @@ -194,6 +194,7 @@ struct scsi_device { · 193 unmodified lines | ||
| 194 | 194 | unsigned no_start_on_add:1; /* do not issue start on add */ |
| 195 | 195 | unsigned allow_restart:1; /* issue START_UNIT in error handler */ |
| 196 | 196 | unsigned manage_start_stop:1; /* Let HLD (sd) manage start/stop */ |
| 197 | + unsigned no_start_on_resume:1; /* Do not issue START_STOP_UNIT on resume */ | |
| 197 | 198 | unsigned start_stop_pwr_cond:1; /* Set power cond. in START_STOP_UNIT */ |
| 198 | 199 | unsigned no_uld_attach:1; /* disable connecting to upper level drivers */ |
| 199 | 200 | unsigned select_no_atn:1; |
| @@ -175,6 +175,9 @@ struct tegra_mc_icc_ops { · 174 unmodified lines | ||
| 175 | 175 | int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak); |
| 176 | 176 | }; |
| 177 | 177 | |
| 178 | +struct icc_node *tegra_mc_icc_xlate(struct of_phandle_args *spec, void *data); | |
| 179 | +extern const struct tegra_mc_icc_ops tegra_mc_icc_ops; | |
| 180 | + | |
| 178 | 181 | struct tegra_mc_ops { |
| 179 | 182 | /* |
| 180 | 183 | * @probe: Callback to set up SoC-specific bits of the memory controller. This is called |
| @@ -381,6 +381,7 @@ TRACE_EVENT(tcp_cong_state_set, · 380 unmodified lines | ||
| 381 | 381 | __field(const void *, skaddr) |
| 382 | 382 | __field(__u16, sport) |
| 383 | 383 | __field(__u16, dport) |
| 384 | + __field(__u16, family) | |
| 384 | 385 | __array(__u8, saddr, 4) |
| 385 | 386 | __array(__u8, daddr, 4) |
| 386 | 387 | __array(__u8, saddr_v6, 16) |
| @@ -396,6 +397,7 @@ TRACE_EVENT(tcp_cong_state_set, · 9 unmodified lines | ||
| 396 | 397 | |
| 397 | 398 | __entry->sport = ntohs(inet->inet_sport); |
| 398 | 399 | __entry->dport = ntohs(inet->inet_dport); |
| 400 | + __entry->family = sk->sk_family; | |
| 399 | 401 | |
| 400 | 402 | p32 = (__be32 *) __entry->saddr; |
| 401 | 403 | *p32 = inet->inet_saddr; |
| @@ -409,7 +411,8 @@ TRACE_EVENT(tcp_cong_state_set, · 7 unmodified lines | ||
| 409 | 411 | __entry->cong_state = ca_state; |
| 410 | 412 | ), |
| 411 | 413 | |
| 412 | − TP_printk("sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c cong_state=%u", | |
| 414 | + TP_printk("family=%s sport=%hu dport=%hu saddr=%pI4 daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c cong_state=%u", | |
| 415 | + show_family_name(__entry->family), | |
| 413 | 416 | __entry->sport, __entry->dport, |
| 414 | 417 | __entry->saddr, __entry->daddr, |
| 415 | 418 | __entry->saddr_v6, __entry->daddr_v6, |
| @@ -710,9 +710,11 @@ enum { · 709 unmodified lines | ||
| 710 | 710 | TCA_FLOWER_KEY_CFM_OPT_UNSPEC, |
| 711 | 711 | TCA_FLOWER_KEY_CFM_MD_LEVEL, |
| 712 | 712 | TCA_FLOWER_KEY_CFM_OPCODE, |
| 713 | − TCA_FLOWER_KEY_CFM_OPT_MAX, | |
| 713 | + __TCA_FLOWER_KEY_CFM_OPT_MAX, | |
| 714 | 714 | }; |
| 715 | 715 | |
| 716 | +#define TCA_FLOWER_KEY_CFM_OPT_MAX (__TCA_FLOWER_KEY_CFM_OPT_MAX - 1) | |
| 717 | + | |
| 716 | 718 | #define TCA_FLOWER_MASK_FLAGS_RANGE (1 << 0) /* Range-based match */ |
| 717 | 719 | |
| 718 | 720 | /* Match-all classifier */ |
| @@ -3470,6 +3470,8 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp, · 3469 unmodified lines | ||
| 3470 | 3470 | * - use the kernel virtual address of the shared io_uring context |
| 3471 | 3471 | * (instead of the userspace-provided address, which has to be 0UL |
| 3472 | 3472 | * anyway). |
| 3473 | + * - use the same pgoff which the get_unmapped_area() uses to | |
| 3474 | + * calculate the page colouring. | |
| 3473 | 3475 | * For architectures without such aliasing requirements, the |
| 3474 | 3476 | * architecture will return any suitable mapping because addr is 0. |
| 3475 | 3477 | */ |
| @@ -3478,6 +3480,7 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp, · 2 unmodified lines | ||
| 3478 | 3480 | pgoff = 0; /* has been translated to ptr above */ |
| 3479 | 3481 | #ifdef SHM_COLOUR |
| 3480 | 3482 | addr = (uintptr_t) ptr; |
| 3483 | + pgoff = addr >> PAGE_SHIFT; | |
| 3481 | 3484 | #else |
| 3482 | 3485 | addr = 0UL; |
| 3483 | 3486 | #endif |
| @@ -35,9 +35,11 @@ static bool io_openat_force_async(struct io_open *open) · 34 unmodified lines | ||
| 35 | 35 | { |
| 36 | 36 | /* |
| 37 | 37 | * Don't bother trying for O_TRUNC, O_CREAT, or O_TMPFILE open, |
| 38 | − * it'll always -EAGAIN | |
| 38 | + * it'll always -EAGAIN. Note that we test for __O_TMPFILE because | |
| 39 | + * O_TMPFILE includes O_DIRECTORY, which isn't a flag we need to force | |
| 40 | + * async for. | |
| 39 | 41 | */ |
| 40 | − return open->how.flags & (O_TRUNC | O_CREAT | O_TMPFILE); | |
| 42 | + return open->how.flags & (O_TRUNC | O_CREAT | __O_TMPFILE); | |
| 41 | 43 | } |
| 42 | 44 | |
| 43 | 45 | static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
| @@ -28,6 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <linux/sched.h> |
| 29 | 29 | #include <linux/workqueue.h> |
| 30 | 30 | #include <linux/kthread.h> |
| 31 | +#include <linux/completion.h> | |
| 31 | 32 | #include <trace/events/xdp.h> |
| 32 | 33 | #include <linux/btf_ids.h> |
| 33 | 34 | |
| @@ -73,6 +74,7 @@ struct bpf_cpu_map_entry { · 39 unmodified lines | ||
| 73 | 74 | struct rcu_head rcu; |
| 74 | 75 | |
| 75 | 76 | struct work_struct kthread_stop_wq; |
| 77 | + struct completion kthread_running; | |
| 76 | 78 | }; |
| 77 | 79 | |
| 78 | 80 | struct bpf_cpu_map { |
| @@ -129,11 +131,17 @@ static void __cpu_map_ring_cleanup(struct ptr_ring *ring) · 50 unmodified lines | ||
| 129 | 131 | * invoked cpu_map_kthread_stop(). Catch any broken behaviour |
| 130 | 132 | * gracefully and warn once. |
| 131 | 133 | */ |
| 132 | − struct xdp_frame *xdpf; | |
| 134 | + void *ptr; | |
| 133 | 135 | |
| 134 | − while ((xdpf = ptr_ring_consume(ring))) | |
| 135 | − if (WARN_ON_ONCE(xdpf)) | |
| 136 | − xdp_return_frame(xdpf); | |
| 136 | + while ((ptr = ptr_ring_consume(ring))) { | |
| 137 | + WARN_ON_ONCE(1); | |
| 138 | + if (unlikely(__ptr_test_bit(0, &ptr))) { | |
| 139 | + __ptr_clear_bit(0, &ptr); | |
| 140 | + kfree_skb(ptr); | |
| 141 | + continue; | |
| 142 | + } | |
| 143 | + xdp_return_frame(ptr); | |
| 144 | + } | |
| 137 | 145 | } |
| 138 | 146 | |
| 139 | 147 | static void put_cpu_map_entry(struct bpf_cpu_map_entry *rcpu) |
| @@ -153,7 +161,6 @@ static void put_cpu_map_entry(struct bpf_cpu_map_entry *rcpu) · 13 unmodified lines | ||
| 153 | 161 | static void cpu_map_kthread_stop(struct work_struct *work) |
| 154 | 162 | { |
| 155 | 163 | struct bpf_cpu_map_entry *rcpu; |
| 156 | − int err; | |
| 157 | 164 | |
| 158 | 165 | rcpu = container_of(work, struct bpf_cpu_map_entry, kthread_stop_wq); |
| 159 | 166 | |
| @@ -163,14 +170,7 @@ static void cpu_map_kthread_stop(struct work_struct *work) · 3 unmodified lines | ||
| 163 | 170 | rcu_barrier(); |
| 164 | 171 | |
| 165 | 172 | /* kthread_stop will wake_up_process and wait for it to complete */ |
| 166 | − err = kthread_stop(rcpu->kthread); | |
| 167 | − if (err) { | |
| 168 | − /* kthread_stop may be called before cpu_map_kthread_run | |
| 169 | − * is executed, so we need to release the memory related | |
| 170 | − * to rcpu. | |
| 171 | − */ | |
| 172 | − put_cpu_map_entry(rcpu); | |
| 173 | − } | |
| 173 | + kthread_stop(rcpu->kthread); | |
| 174 | 174 | } |
| 175 | 175 | |
| 176 | 176 | static void cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu, |
| @@ -298,11 +298,11 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames, · 121 unmodified lines | ||
| 298 | 298 | return nframes; |
| 299 | 299 | } |
| 300 | 300 | |
| 301 | − | |
| 302 | 301 | static int cpu_map_kthread_run(void *data) |
| 303 | 302 | { |
| 304 | 303 | struct bpf_cpu_map_entry *rcpu = data; |
| 305 | 304 | |
| 305 | + complete(&rcpu->kthread_running); | |
| 306 | 306 | set_current_state(TASK_INTERRUPTIBLE); |
| 307 | 307 | |
| 308 | 308 | /* When kthread gives stop order, then rcpu have been disconnected |
| @@ -467,6 +467,7 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value, · 158 unmodified lines | ||
| 467 | 467 | goto free_ptr_ring; |
| 468 | 468 | |
| 469 | 469 | /* Setup kthread */ |
| 470 | + init_completion(&rcpu->kthread_running); | |
| 470 | 471 | rcpu->kthread = kthread_create_on_node(cpu_map_kthread_run, rcpu, numa, |
| 471 | 472 | "cpumap/%d/map:%d", cpu, |
| 472 | 473 | map->id); |
| @@ -480,6 +481,12 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value, · 7 unmodified lines | ||
| 480 | 481 | kthread_bind(rcpu->kthread, cpu); |
| 481 | 482 | wake_up_process(rcpu->kthread); |
| 482 | 483 | |
| 484 | + /* Make sure kthread has been running, so kthread_stop() will not | |
| 485 | + * stop the kthread prematurely and all pending frames or skbs | |
| 486 | + * will be handled by the kthread before kthread_stop() returns. | |
| 487 | + */ | |
| 488 | + wait_for_completion(&rcpu->kthread_running); | |
| 489 | + | |
| 483 | 490 | return rcpu; |
| 484 | 491 | |
| 485 | 492 | free_prog: |
| @@ -1166,7 +1166,7 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, · 1165 unmodified lines | ||
| 1166 | 1166 | int error; |
| 1167 | 1167 | |
| 1168 | 1168 | if (!hibernation_available()) |
| 1169 | − return 0; | |
| 1169 | + return n; | |
| 1170 | 1170 | |
| 1171 | 1171 | if (len && buf[len-1] == '\n') |
| 1172 | 1172 | len--; |
| @@ -661,8 +661,7 @@ static DEFINE_PER_CPU(int, bpf_trace_nest_level); · 660 unmodified lines | ||
| 661 | 661 | BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map, |
| 662 | 662 | u64, flags, void *, data, u64, size) |
| 663 | 663 | { |
| 664 | − struct bpf_trace_sample_data *sds = this_cpu_ptr(&bpf_trace_sds); | |
| 665 | − int nest_level = this_cpu_inc_return(bpf_trace_nest_level); | |
| 664 | + struct bpf_trace_sample_data *sds; | |
| 666 | 665 | struct perf_raw_record raw = { |
| 667 | 666 | .frag = { |
| 668 | 667 | .size = size, |
| @@ -670,7 +669,11 @@ BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map, · 1 unmodified line | ||
| 670 | 669 | }, |
| 671 | 670 | }; |
| 672 | 671 | struct perf_sample_data *sd; |
| 673 | − int err; | |
| 672 | + int nest_level, err; | |
| 673 | + | |
| 674 | + preempt_disable(); | |
| 675 | + sds = this_cpu_ptr(&bpf_trace_sds); | |
| 676 | + nest_level = this_cpu_inc_return(bpf_trace_nest_level); | |
| 674 | 677 | |
| 675 | 678 | if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(sds->sds))) { |
| 676 | 679 | err = -EBUSY; |
| @@ -688,9 +691,9 @@ BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map, · 11 unmodified lines | ||
| 688 | 691 | perf_sample_save_raw_data(sd, &raw); |
| 689 | 692 | |
| 690 | 693 | err = __bpf_perf_event_output(regs, map, flags, sd); |
| 691 | − | |
| 692 | 694 | out: |
| 693 | 695 | this_cpu_dec(bpf_trace_nest_level); |
| 696 | + preempt_enable(); | |
| 694 | 697 | return err; |
| 695 | 698 | } |
| 696 | 699 | |
| @@ -715,7 +718,6 @@ static DEFINE_PER_CPU(struct bpf_trace_sample_data, bpf_misc_sds); · 18 unmodified lines | ||
| 715 | 718 | u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size, |
| 716 | 719 | void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy) |
| 717 | 720 | { |
| 718 | − int nest_level = this_cpu_inc_return(bpf_event_output_nest_level); | |
| 719 | 721 | struct perf_raw_frag frag = { |
| 720 | 722 | .copy = ctx_copy, |
| 721 | 723 | .size = ctx_size, |
| @@ -732,8 +734,12 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size, · 10 unmodified lines | ||
| 732 | 734 | }; |
| 733 | 735 | struct perf_sample_data *sd; |
| 734 | 736 | struct pt_regs *regs; |
| 737 | + int nest_level; | |
| 735 | 738 | u64 ret; |
| 736 | 739 | |
| 740 | + preempt_disable(); | |
| 741 | + nest_level = this_cpu_inc_return(bpf_event_output_nest_level); | |
| 742 | + | |
| 737 | 743 | if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(bpf_misc_sds.sds))) { |
| 738 | 744 | ret = -EBUSY; |
| 739 | 745 | goto out; |
| @@ -748,6 +754,7 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size, · 8 unmodified lines | ||
| 748 | 754 | ret = __bpf_perf_event_output(regs, map, flags, sd); |
| 749 | 755 | out: |
| 750 | 756 | this_cpu_dec(bpf_event_output_nest_level); |
| 757 | + preempt_enable(); | |
| 751 | 758 | return ret; |
| 752 | 759 | } |
| 753 | 760 | |
| @@ -52,6 +52,7 @@ · 51 unmodified lines | ||
| 52 | 52 | #include <linux/sched/debug.h> |
| 53 | 53 | #include <linux/nmi.h> |
| 54 | 54 | #include <linux/kvm_para.h> |
| 55 | +#include <linux/delay.h> | |
| 55 | 56 | |
| 56 | 57 | #include "workqueue_internal.h" |
| 57 | 58 | |
| @@ -338,8 +339,10 @@ static cpumask_var_t *wq_numa_possible_cpumask; · 280 unmodified lines | ||
| 338 | 339 | * Per-cpu work items which run for longer than the following threshold are |
| 339 | 340 | * automatically considered CPU intensive and excluded from concurrency |
| 340 | 341 | * management to prevent them from noticeably delaying other per-cpu work items. |
| 342 | + * ULONG_MAX indicates that the user hasn't overridden it with a boot parameter. | |
| 343 | + * The actual value is initialized in wq_cpu_intensive_thresh_init(). | |
| 341 | 344 | */ |
| 342 | −static unsigned long wq_cpu_intensive_thresh_us = 10000; | |
| 345 | +static unsigned long wq_cpu_intensive_thresh_us = ULONG_MAX; | |
| 343 | 346 | module_param_named(cpu_intensive_thresh_us, wq_cpu_intensive_thresh_us, ulong, 0644); |
| 344 | 347 | |
| 345 | 348 | static bool wq_disable_numa; |
| @@ -6513,6 +6516,42 @@ void __init workqueue_init_early(void) · 6167 unmodified lines | ||
| 6513 | 6516 | !system_freezable_power_efficient_wq); |
| 6514 | 6517 | } |
| 6515 | 6518 | |
| 6519 | +static void __init wq_cpu_intensive_thresh_init(void) | |
| 6520 | +{ | |
| 6521 | + unsigned long thresh; | |
| 6522 | + unsigned long bogo; | |
| 6523 | + | |
| 6524 | + /* if the user set it to a specific value, keep it */ | |
| 6525 | + if (wq_cpu_intensive_thresh_us != ULONG_MAX) | |
| 6526 | + return; | |
| 6527 | + | |
| 6528 | + /* | |
| 6529 | + * The default of 10ms is derived from the fact that most modern (as of | |
| 6530 | + * 2023) processors can do a lot in 10ms and that it's just below what | |
| 6531 | + * most consider human-perceivable. However, the kernel also runs on a | |
| 6532 | + * lot slower CPUs including microcontrollers where the threshold is way | |
| 6533 | + * too low. | |
| 6534 | + * | |
| 6535 | + * Let's scale up the threshold upto 1 second if BogoMips is below 4000. | |
| 6536 | + * This is by no means accurate but it doesn't have to be. The mechanism | |
| 6537 | + * is still useful even when the threshold is fully scaled up. Also, as | |
| 6538 | + * the reports would usually be applicable to everyone, some machines | |
| 6539 | + * operating on longer thresholds won't significantly diminish their | |
| 6540 | + * usefulness. | |
| 6541 | + */ | |
| 6542 | + thresh = 10 * USEC_PER_MSEC; | |
| 6543 | + | |
| 6544 | + /* see init/calibrate.c for lpj -> BogoMIPS calculation */ | |
| 6545 | + bogo = max_t(unsigned long, loops_per_jiffy / 500000 * HZ, 1); | |
| 6546 | + if (bogo < 4000) | |
| 6547 | + thresh = min_t(unsigned long, thresh * 4000 / bogo, USEC_PER_SEC); | |
| 6548 | + | |
| 6549 | + pr_debug("wq_cpu_intensive_thresh: lpj=%lu BogoMIPS=%lu thresh_us=%lu\n", | |
| 6550 | + loops_per_jiffy, bogo, thresh); | |
| 6551 | + | |
| 6552 | + wq_cpu_intensive_thresh_us = thresh; | |
| 6553 | +} | |
| 6554 | + | |
| 6516 | 6555 | /** |
| 6517 | 6556 | * workqueue_init - bring workqueue subsystem fully online |
| 6518 | 6557 | * |
| @@ -6528,6 +6567,8 @@ void __init workqueue_init(void) · 9 unmodified lines | ||
| 6528 | 6567 | struct worker_pool *pool; |
| 6529 | 6568 | int cpu, bkt; |
| 6530 | 6569 | |
| 6570 | + wq_cpu_intensive_thresh_init(); | |
| 6571 | + | |
| 6531 | 6572 | /* |
| 6532 | 6573 | * It'd be simpler to initialize NUMA in workqueue_init_early() but |
| 6533 | 6574 | * CPU to node mapping may not be available that early on some |
| @@ -1200,7 +1200,7 @@ config WQ_CPU_INTENSIVE_REPORT · 1199 unmodified lines | ||
| 1200 | 1200 | help |
| 1201 | 1201 | Say Y here to enable reporting of concurrency-managed per-cpu work |
| 1202 | 1202 | items that hog CPUs for longer than |
| 1203 | − workqueue.cpu_intensive_threshold_us. Workqueue automatically | |
| 1203 | + workqueue.cpu_intensive_thresh_us. Workqueue automatically | |
| 1204 | 1204 | detects and excludes them from concurrency management to prevent |
| 1205 | 1205 | them from stalling other per-cpu work items. Occassional |
| 1206 | 1206 | triggering may not necessarily indicate a problem. Repeated |
| @@ -82,7 +82,13 @@ obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o · 81 unmodified lines | ||
| 82 | 82 | obj-$(CONFIG_TEST_DYNAMIC_DEBUG) += test_dynamic_debug.o |
| 83 | 83 | obj-$(CONFIG_TEST_PRINTF) += test_printf.o |
| 84 | 84 | obj-$(CONFIG_TEST_SCANF) += test_scanf.o |
| 85 | + | |
| 85 | 86 | obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o |
| 87 | +ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_KASAN),yy) | |
| 88 | +# FIXME: Clang breaks test_bitmap_const_eval when KASAN and GCOV are enabled | |
| 89 | +GCOV_PROFILE_test_bitmap.o := n | |
| 90 | +endif | |
| 91 | + | |
| 86 | 92 | obj-$(CONFIG_TEST_UUID) += test_uuid.o |
| 87 | 93 | obj-$(CONFIG_TEST_XARRAY) += test_xarray.o |
| 88 | 94 | obj-$(CONFIG_TEST_MAPLE_TREE) += test_maple_tree.o |
| @@ -45,6 +45,7 @@ EXPORT_SYMBOL(cpumask_next_wrap); · 44 unmodified lines | ||
| 45 | 45 | * alloc_cpumask_var_node - allocate a struct cpumask on a given node |
| 46 | 46 | * @mask: pointer to cpumask_var_t where the cpumask is returned |
| 47 | 47 | * @flags: GFP_ flags |
| 48 | + * @node: memory node from which to allocate or %NUMA_NO_NODE | |
| 48 | 49 | * |
| 49 | 50 | * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is |
| 50 | 51 | * a nop returning a constant 1 (in <linux/cpumask.h>) |
| @@ -157,7 +158,9 @@ EXPORT_SYMBOL(cpumask_local_spread); · 106 unmodified lines | ||
| 157 | 158 | static DEFINE_PER_CPU(int, distribute_cpu_mask_prev); |
| 158 | 159 | |
| 159 | 160 | /** |
| 160 | − * cpumask_any_and_distribute - Return an arbitrary cpu within srcp1 & srcp2. | |
| 161 | + * cpumask_any_and_distribute - Return an arbitrary cpu within src1p & src2p. | |
| 162 | + * @src1p: first &cpumask for intersection | |
| 163 | + * @src2p: second &cpumask for intersection | |
| 161 | 164 | * |
| 162 | 165 | * Iterated calls using the same srcp1 and srcp2 will be distributed within |
| 163 | 166 | * their intersection. |
| @@ -1148,7 +1148,7 @@ static ssize_t extract_user_to_sg(struct iov_iter *iter, · 1147 unmodified lines | ||
| 1148 | 1148 | |
| 1149 | 1149 | failed: |
| 1150 | 1150 | while (sgtable->nents > sgtable->orig_nents) |
| 1151 | − put_page(sg_page(&sgtable->sgl[--sgtable->nents])); | |
| 1151 | + unpin_user_page(sg_page(&sgtable->sgl[--sgtable->nents])); | |
| 1152 | 1152 | return res; |
| 1153 | 1153 | } |
| 1154 | 1154 | |
| @@ -1161,6 +1161,10 @@ static void __init test_bitmap_print_buf(void) · 1160 unmodified lines | ||
| 1161 | 1161 | } |
| 1162 | 1162 | } |
| 1163 | 1163 | |
| 1164 | +/* | |
| 1165 | + * FIXME: Clang breaks compile-time evaluations when KASAN and GCOV are enabled. | |
| 1166 | + * To workaround it, GCOV is force-disabled in Makefile for this configuration. | |
| 1167 | + */ | |
| 1164 | 1168 | static void __init test_bitmap_const_eval(void) |
| 1165 | 1169 | { |
| 1166 | 1170 | DECLARE_BITMAP(bitmap, BITS_PER_LONG); |
| @@ -1186,11 +1190,7 @@ static void __init test_bitmap_const_eval(void) · 19 unmodified lines | ||
| 1186 | 1190 | * the compiler is fixed. |
| 1187 | 1191 | */ |
| 1188 | 1192 | bitmap_clear(bitmap, 0, BITS_PER_LONG); |
| 1189 | −#if defined(__s390__) && defined(__clang__) | |
| 1190 | − if (!const_test_bit(7, bitmap)) | |
| 1191 | −#else | |
| 1192 | 1193 | if (!test_bit(7, bitmap)) |
| 1193 | −#endif | |
| 1194 | 1194 | bitmap_set(bitmap, 5, 2); |
| 1195 | 1195 | |
| 1196 | 1196 | /* Equals to `unsigned long bitopvar = BIT(20)` */ |
| @@ -912,11 +912,12 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn, · 911 unmodified lines | ||
| 912 | 912 | |
| 913 | 913 | /* |
| 914 | 914 | * Check if the pageblock has already been marked skipped. |
| 915 | − * Only the aligned PFN is checked as the caller isolates | |
| 915 | + * Only the first PFN is checked as the caller isolates | |
| 916 | 916 | * COMPACT_CLUSTER_MAX at a time so the second call must |
| 917 | 917 | * not falsely conclude that the block should be skipped. |
| 918 | 918 | */ |
| 919 | − if (!valid_page && pageblock_aligned(low_pfn)) { | |
| 919 | + if (!valid_page && (pageblock_aligned(low_pfn) || | |
| 920 | + low_pfn == cc->zone->zone_start_pfn)) { | |
| 920 | 921 | if (!isolation_suitable(cc, page)) { |
| 921 | 922 | low_pfn = end_pfn; |
| 922 | 923 | folio = NULL; |
| @@ -2002,7 +2003,8 @@ static isolate_migrate_t isolate_migratepages(struct compact_control *cc) · 1079 unmodified lines | ||
| 2002 | 2003 | * before making it "skip" so other compaction instances do |
| 2003 | 2004 | * not scan the same block. |
| 2004 | 2005 | */ |
| 2005 | − if (pageblock_aligned(low_pfn) && | |
| 2006 | + if ((pageblock_aligned(low_pfn) || | |
| 2007 | + low_pfn == cc->zone->zone_start_pfn) && | |
| 2006 | 2008 | !fast_find_block && !isolation_suitable(cc, page)) |
| 2007 | 2009 | continue; |
| 2008 | 2010 | |
| @@ -273,6 +273,7 @@ struct damos_filter *damos_new_filter(enum damos_filter_type type, · 272 unmodified lines | ||
| 273 | 273 | return NULL; |
| 274 | 274 | filter->type = type; |
| 275 | 275 | filter->matching = matching; |
| 276 | + INIT_LIST_HEAD(&filter->list); | |
| 276 | 277 | return filter; |
| 277 | 278 | } |
| 278 | 279 | |
| @@ -1579,9 +1579,37 @@ static inline void destroy_compound_gigantic_folio(struct folio *folio, · 1578 unmodified lines | ||
| 1579 | 1579 | unsigned int order) { } |
| 1580 | 1580 | #endif |
| 1581 | 1581 | |
| 1582 | +static inline void __clear_hugetlb_destructor(struct hstate *h, | |
| 1583 | + struct folio *folio) | |
| 1584 | +{ | |
| 1585 | + lockdep_assert_held(&hugetlb_lock); | |
| 1586 | + | |
| 1587 | + /* | |
| 1588 | + * Very subtle | |
| 1589 | + * | |
| 1590 | + * For non-gigantic pages set the destructor to the normal compound | |
| 1591 | + * page dtor. This is needed in case someone takes an additional | |
| 1592 | + * temporary ref to the page, and freeing is delayed until they drop | |
| 1593 | + * their reference. | |
| 1594 | + * | |
| 1595 | + * For gigantic pages set the destructor to the null dtor. This | |
| 1596 | + * destructor will never be called. Before freeing the gigantic | |
| 1597 | + * page destroy_compound_gigantic_folio will turn the folio into a | |
| 1598 | + * simple group of pages. After this the destructor does not | |
| 1599 | + * apply. | |
| 1600 | + * | |
| 1601 | + */ | |
| 1602 | + if (hstate_is_gigantic(h)) | |
| 1603 | + folio_set_compound_dtor(folio, NULL_COMPOUND_DTOR); | |
| 1604 | + else | |
| 1605 | + folio_set_compound_dtor(folio, COMPOUND_PAGE_DTOR); | |
| 1606 | +} | |
| 1607 | + | |
| 1582 | 1608 | /* |
| 1583 | − * Remove hugetlb folio from lists, and update dtor so that the folio appears | |
| 1584 | − * as just a compound page. | |
| 1609 | + * Remove hugetlb folio from lists. | |
| 1610 | + * If vmemmap exists for the folio, update dtor so that the folio appears | |
| 1611 | + * as just a compound page. Otherwise, wait until after allocating vmemmap | |
| 1612 | + * to update dtor. | |
| 1585 | 1613 | * |
| 1586 | 1614 | * A reference is held on the folio, except in the case of demote. |
| 1587 | 1615 | * |
| @@ -1612,31 +1640,19 @@ static void __remove_hugetlb_folio(struct hstate *h, struct folio *folio, · 24 unmodified lines | ||
| 1612 | 1640 | } |
| 1613 | 1641 | |
| 1614 | 1642 | /* |
| 1615 | − * Very subtle | |
| 1616 | − * | |
| 1617 | − * For non-gigantic pages set the destructor to the normal compound | |
| 1618 | − * page dtor. This is needed in case someone takes an additional | |
| 1619 | − * temporary ref to the page, and freeing is delayed until they drop | |
| 1620 | − * their reference. | |
| 1621 | − * | |
| 1622 | − * For gigantic pages set the destructor to the null dtor. This | |
| 1623 | − * destructor will never be called. Before freeing the gigantic | |
| 1624 | − * page destroy_compound_gigantic_folio will turn the folio into a | |
| 1625 | − * simple group of pages. After this the destructor does not | |
| 1626 | − * apply. | |
| 1627 | − * | |
| 1628 | − * This handles the case where more than one ref is held when and | |
| 1629 | − * after update_and_free_hugetlb_folio is called. | |
| 1630 | − * | |
| 1631 | − * In the case of demote we do not ref count the page as it will soon | |
| 1632 | − * be turned into a page of smaller size. | |
| 1643 | + * We can only clear the hugetlb destructor after allocating vmemmap | |
| 1644 | + * pages. Otherwise, someone (memory error handling) may try to write | |
| 1645 | + * to tail struct pages. | |
| 1646 | + */ | |
| 1647 | + if (!folio_test_hugetlb_vmemmap_optimized(folio)) | |
| 1648 | + __clear_hugetlb_destructor(h, folio); | |
| 1649 | + | |
| 1650 | + /* | |
| 1651 | + * In the case of demote we do not ref count the page as it will soon | |
| 1652 | + * be turned into a page of smaller size. | |
| 1633 | 1653 | */ |
| 1634 | 1654 | if (!demote) |
| 1635 | 1655 | folio_ref_unfreeze(folio, 1); |
| 1636 | − if (hstate_is_gigantic(h)) | |
| 1637 | − folio_set_compound_dtor(folio, NULL_COMPOUND_DTOR); | |
| 1638 | − else | |
| 1639 | − folio_set_compound_dtor(folio, COMPOUND_PAGE_DTOR); | |
| 1640 | 1656 | |
| 1641 | 1657 | h->nr_huge_pages--; |
| 1642 | 1658 | h->nr_huge_pages_node[nid]--; |
| @@ -1705,6 +1721,7 @@ static void __update_and_free_hugetlb_folio(struct hstate *h, · 62 unmodified lines | ||
| 1705 | 1721 | { |
| 1706 | 1722 | int i; |
| 1707 | 1723 | struct page *subpage; |
| 1724 | + bool clear_dtor = folio_test_hugetlb_vmemmap_optimized(folio); | |
| 1708 | 1725 | |
| 1709 | 1726 | if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported()) |
| 1710 | 1727 | return; |
| @@ -1735,6 +1752,16 @@ static void __update_and_free_hugetlb_folio(struct hstate *h, · 24 unmodified lines | ||
| 1735 | 1752 | if (unlikely(folio_test_hwpoison(folio))) |
| 1736 | 1753 | folio_clear_hugetlb_hwpoison(folio); |
| 1737 | 1754 | |
| 1755 | + /* | |
| 1756 | + * If vmemmap pages were allocated above, then we need to clear the | |
| 1757 | + * hugetlb destructor under the hugetlb lock. | |
| 1758 | + */ | |
| 1759 | + if (clear_dtor) { | |
| 1760 | + spin_lock_irq(&hugetlb_lock); | |
| 1761 | + __clear_hugetlb_destructor(h, folio); | |
| 1762 | + spin_unlock_irq(&hugetlb_lock); | |
| 1763 | + } | |
| 1764 | + | |
| 1738 | 1765 | for (i = 0; i < pages_per_huge_page(h); i++) { |
| 1739 | 1766 | subpage = folio_page(folio, i); |
| 1740 | 1767 | subpage->flags &= ~(1 << PG_locked | 1 << PG_error | |
| @@ -2784,6 +2784,8 @@ struct page *ksm_might_need_to_copy(struct page *page, · 2783 unmodified lines | ||
| 2784 | 2784 | anon_vma->root == vma->anon_vma->root) { |
| 2785 | 2785 | return page; /* still no need to copy it */ |
| 2786 | 2786 | } |
| 2787 | + if (PageHWPoison(page)) | |
| 2788 | + return ERR_PTR(-EHWPOISON); | |
| 2787 | 2789 | if (!PageUptodate(page)) |
| 2788 | 2790 | return page; /* let do_swap_page report the error */ |
| 2789 | 2791 | |
| @@ -2466,7 +2466,7 @@ int unpoison_memory(unsigned long pfn) · 2465 unmodified lines | ||
| 2466 | 2466 | { |
| 2467 | 2467 | struct folio *folio; |
| 2468 | 2468 | struct page *p; |
| 2469 | − int ret = -EBUSY; | |
| 2469 | + int ret = -EBUSY, ghp; | |
| 2470 | 2470 | unsigned long count = 1; |
| 2471 | 2471 | bool huge = false; |
| 2472 | 2472 | static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL, |
| @@ -2499,6 +2499,13 @@ int unpoison_memory(unsigned long pfn) · 26 unmodified lines | ||
| 2499 | 2499 | goto unlock_mutex; |
| 2500 | 2500 | } |
| 2501 | 2501 | |
| 2502 | + if (folio_test_slab(folio) || PageTable(&folio->page) || folio_test_reserved(folio)) | |
| 2503 | + goto unlock_mutex; | |
| 2504 | + | |
| 2505 | + /* | |
| 2506 | + * Note that folio->_mapcount is overloaded in SLAB, so the simple test | |
| 2507 | + * in folio_mapped() has to be done after folio_test_slab() is checked. | |
| 2508 | + */ | |
| 2502 | 2509 | if (folio_mapped(folio)) { |
| 2503 | 2510 | unpoison_pr_info("Unpoison: Someone maps the hwpoison page %#lx\n", |
| 2504 | 2511 | pfn, &unpoison_rs); |
| @@ -2511,32 +2518,28 @@ int unpoison_memory(unsigned long pfn) · 6 unmodified lines | ||
| 2511 | 2518 | goto unlock_mutex; |
| 2512 | 2519 | } |
| 2513 | 2520 | |
| 2514 | − if (folio_test_slab(folio) || PageTable(&folio->page) || folio_test_reserved(folio)) | |
| 2515 | − goto unlock_mutex; | |
| 2516 | − | |
| 2517 | − ret = get_hwpoison_page(p, MF_UNPOISON); | |
| 2518 | − if (!ret) { | |
| 2521 | + ghp = get_hwpoison_page(p, MF_UNPOISON); | |
| 2522 | + if (!ghp) { | |
| 2519 | 2523 | if (PageHuge(p)) { |
| 2520 | 2524 | huge = true; |
| 2521 | 2525 | count = folio_free_raw_hwp(folio, false); |
| 2522 | − if (count == 0) { | |
| 2523 | − ret = -EBUSY; | |
| 2526 | + if (count == 0) | |
| 2524 | 2527 | goto unlock_mutex; |
| 2525 | − } | |
| 2526 | 2528 | } |
| 2527 | 2529 | ret = folio_test_clear_hwpoison(folio) ? 0 : -EBUSY; |
| 2528 | − } else if (ret < 0) { | |
| 2529 | − if (ret == -EHWPOISON) { | |
| 2530 | + } else if (ghp < 0) { | |
| 2531 | + if (ghp == -EHWPOISON) { | |
| 2530 | 2532 | ret = put_page_back_buddy(p) ? 0 : -EBUSY; |
| 2531 | − } else | |
| 2533 | + } else { | |
| 2534 | + ret = ghp; | |
| 2532 | 2535 | unpoison_pr_info("Unpoison: failed to grab page %#lx\n", |
| 2533 | 2536 | pfn, &unpoison_rs); |
| 2537 | + } | |
| 2534 | 2538 | } else { |
| 2535 | 2539 | if (PageHuge(p)) { |
| 2536 | 2540 | huge = true; |
| 2537 | 2541 | count = folio_free_raw_hwp(folio, false); |
| 2538 | 2542 | if (count == 0) { |
| 2539 | − ret = -EBUSY; | |
| 2540 | 2543 | folio_put(folio); |
| 2541 | 2544 | goto unlock_mutex; |
| 2542 | 2545 | } |
| @@ -5705,6 +5705,9 @@ int __access_remote_vm(struct mm_struct *mm, unsigned long addr, void *buf, · 5704 unmodified lines | ||
| 5705 | 5705 | if (mmap_read_lock_killable(mm)) |
| 5706 | 5706 | return 0; |
| 5707 | 5707 | |
| 5708 | + /* Untag the address before looking up the VMA */ | |
| 5709 | + addr = untagged_addr_remote(mm, addr); | |
| 5710 | + | |
| 5708 | 5711 | /* Avoid triggering the temporary warning in __get_user_pages */ |
| 5709 | 5712 | if (!vma_lookup(mm, addr) && !expand_stack(mm, addr)) |
| 5710 | 5713 | return 0; |
| @@ -1746,7 +1746,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, · 1745 unmodified lines | ||
| 1746 | 1746 | struct page *swapcache; |
| 1747 | 1747 | spinlock_t *ptl; |
| 1748 | 1748 | pte_t *pte, new_pte, old_pte; |
| 1749 | − bool hwposioned = false; | |
| 1749 | + bool hwpoisoned = PageHWPoison(page); | |
| 1750 | 1750 | int ret = 1; |
| 1751 | 1751 | |
| 1752 | 1752 | swapcache = page; |
| @@ -1754,7 +1754,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, · 1 unmodified line | ||
| 1754 | 1754 | if (unlikely(!page)) |
| 1755 | 1755 | return -ENOMEM; |
| 1756 | 1756 | else if (unlikely(PTR_ERR(page) == -EHWPOISON)) |
| 1757 | − hwposioned = true; | |
| 1757 | + hwpoisoned = true; | |
| 1758 | 1758 | |
| 1759 | 1759 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); |
| 1760 | 1760 | if (unlikely(!pte || !pte_same_as_swp(ptep_get(pte), |
| @@ -1765,11 +1765,11 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, · 4 unmodified lines | ||
| 1765 | 1765 | |
| 1766 | 1766 | old_pte = ptep_get(pte); |
| 1767 | 1767 | |
| 1768 | − if (unlikely(hwposioned || !PageUptodate(page))) { | |
| 1768 | + if (unlikely(hwpoisoned || !PageUptodate(page))) { | |
| 1769 | 1769 | swp_entry_t swp_entry; |
| 1770 | 1770 | |
| 1771 | 1771 | dec_mm_counter(vma->vm_mm, MM_SWAPENTS); |
| 1772 | − if (hwposioned) { | |
| 1772 | + if (hwpoisoned) { | |
| 1773 | 1773 | swp_entry = make_hwpoison_entry(swapcache); |
| 1774 | 1774 | page = swapcache; |
| 1775 | 1775 | } else { |
| @@ -1798,6 +1798,7 @@ static void replace_sub_page(struct size_class *class, struct zspage *zspage, · 1797 unmodified lines | ||
| 1798 | 1798 | |
| 1799 | 1799 | static bool zs_page_isolate(struct page *page, isolate_mode_t mode) |
| 1800 | 1800 | { |
| 1801 | + struct zs_pool *pool; | |
| 1801 | 1802 | struct zspage *zspage; |
| 1802 | 1803 | |
| 1803 | 1804 | /* |
| @@ -1807,9 +1808,10 @@ static bool zs_page_isolate(struct page *page, isolate_mode_t mode) · 3 unmodified lines | ||
| 1807 | 1808 | VM_BUG_ON_PAGE(PageIsolated(page), page); |
| 1808 | 1809 | |
| 1809 | 1810 | zspage = get_zspage(page); |
| 1810 | − migrate_write_lock(zspage); | |
| 1811 | + pool = zspage->pool; | |
| 1812 | + spin_lock(&pool->lock); | |
| 1811 | 1813 | inc_zspage_isolation(zspage); |
| 1812 | − migrate_write_unlock(zspage); | |
| 1814 | + spin_unlock(&pool->lock); | |
| 1813 | 1815 | |
| 1814 | 1816 | return true; |
| 1815 | 1817 | } |
| @@ -1875,12 +1877,12 @@ static int zs_page_migrate(struct page *newpage, struct page *page, · 59 unmodified lines | ||
| 1875 | 1877 | kunmap_atomic(s_addr); |
| 1876 | 1878 | |
| 1877 | 1879 | replace_sub_page(class, zspage, newpage, page); |
| 1880 | + dec_zspage_isolation(zspage); | |
| 1878 | 1881 | /* |
| 1879 | 1882 | * Since we complete the data copy and set up new zspage structure, |
| 1880 | 1883 | * it's okay to release the pool's lock. |
| 1881 | 1884 | */ |
| 1882 | 1885 | spin_unlock(&pool->lock); |
| 1883 | − dec_zspage_isolation(zspage); | |
| 1884 | 1886 | migrate_write_unlock(zspage); |
| 1885 | 1887 | |
| 1886 | 1888 | get_page(newpage); |
| @@ -1897,14 +1899,16 @@ static int zs_page_migrate(struct page *newpage, struct page *page, · 10 unmodified lines | ||
| 1897 | 1899 | |
| 1898 | 1900 | static void zs_page_putback(struct page *page) |
| 1899 | 1901 | { |
| 1902 | + struct zs_pool *pool; | |
| 1900 | 1903 | struct zspage *zspage; |
| 1901 | 1904 | |
| 1902 | 1905 | VM_BUG_ON_PAGE(!PageIsolated(page), page); |
| 1903 | 1906 | |
| 1904 | 1907 | zspage = get_zspage(page); |
| 1905 | − migrate_write_lock(zspage); | |
| 1908 | + pool = zspage->pool; | |
| 1909 | + spin_lock(&pool->lock); | |
| 1906 | 1910 | dec_zspage_isolation(zspage); |
| 1907 | − migrate_write_unlock(zspage); | |
| 1911 | + spin_unlock(&pool->lock); | |
| 1908 | 1912 | } |
| 1909 | 1913 | |
| 1910 | 1914 | static const struct movable_operations zsmalloc_mops = { |
| @@ -384,8 +384,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, · 383 unmodified lines | ||
| 384 | 384 | dev->name); |
| 385 | 385 | vlan_vid_add(dev, htons(ETH_P_8021Q), 0); |
| 386 | 386 | } |
| 387 | − if (event == NETDEV_DOWN && | |
| 388 | − (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) | |
| 387 | + if (event == NETDEV_DOWN) | |
| 389 | 388 | vlan_vid_del(dev, htons(ETH_P_8021Q), 0); |
| 390 | 389 | |
| 391 | 390 | vlan_info = rtnl_dereference(dev->vlan_info); |
| @@ -865,7 +865,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) · 864 unmodified lines | ||
| 865 | 865 | |
| 866 | 866 | skb->dev = dev; |
| 867 | 867 | skb->priority = sk->sk_priority; |
| 868 | − skb->mark = sk->sk_mark; | |
| 868 | + skb->mark = READ_ONCE(sk->sk_mark); | |
| 869 | 869 | skb->tstamp = sockc.transmit_time; |
| 870 | 870 | |
| 871 | 871 | skb_setup_tx_timestamp(skb, sockc.tsflags); |
| @@ -3334,17 +3334,24 @@ static int linger_reg_commit_wait(struct ceph_osd_linger_request *lreq) · 3333 unmodified lines | ||
| 3334 | 3334 | int ret; |
| 3335 | 3335 | |
| 3336 | 3336 | dout("%s lreq %p linger_id %llu\n", __func__, lreq, lreq->linger_id); |
| 3337 | − ret = wait_for_completion_interruptible(&lreq->reg_commit_wait); | |
| 3337 | + ret = wait_for_completion_killable(&lreq->reg_commit_wait); | |
| 3338 | 3338 | return ret ?: lreq->reg_commit_error; |
| 3339 | 3339 | } |
| 3340 | 3340 | |
| 3341 | −static int linger_notify_finish_wait(struct ceph_osd_linger_request *lreq) | |
| 3341 | +static int linger_notify_finish_wait(struct ceph_osd_linger_request *lreq, | |
| 3342 | + unsigned long timeout) | |
| 3342 | 3343 | { |
| 3343 | − int ret; | |
| 3344 | + long left; | |
| 3344 | 3345 | |
| 3345 | 3346 | dout("%s lreq %p linger_id %llu\n", __func__, lreq, lreq->linger_id); |
| 3346 | − ret = wait_for_completion_interruptible(&lreq->notify_finish_wait); | |
| 3347 | − return ret ?: lreq->notify_finish_error; | |
| 3347 | + left = wait_for_completion_killable_timeout(&lreq->notify_finish_wait, | |
| 3348 | + ceph_timeout_jiffies(timeout)); | |
| 3349 | + if (left <= 0) | |
| 3350 | + left = left ?: -ETIMEDOUT; | |
| 3351 | + else | |
| 3352 | + left = lreq->notify_finish_error; /* completed */ | |
| 3353 | + | |
| 3354 | + return left; | |
| 3348 | 3355 | } |
| 3349 | 3356 | |
| 3350 | 3357 | /* |
| @@ -4896,7 +4903,8 @@ int ceph_osdc_notify(struct ceph_osd_client *osdc, · 1545 unmodified lines | ||
| 4896 | 4903 | linger_submit(lreq); |
| 4897 | 4904 | ret = linger_reg_commit_wait(lreq); |
| 4898 | 4905 | if (!ret) |
| 4899 | − ret = linger_notify_finish_wait(lreq); | |
| 4906 | + ret = linger_notify_finish_wait(lreq, | |
| 4907 | + msecs_to_jiffies(2 * timeout * MSEC_PER_SEC)); | |
| 4900 | 4908 | else |
| 4901 | 4909 | dout("lreq %p failed to initiate notify %d\n", lreq, ret); |
| 4902 | 4910 | |
| @@ -496,8 +496,11 @@ bpf_sk_storage_diag_alloc(const struct nlattr *nla_stgs) · 495 unmodified lines | ||
| 496 | 496 | return ERR_PTR(-EPERM); |
| 497 | 497 | |
| 498 | 498 | nla_for_each_nested(nla, nla_stgs, rem) { |
| 499 | − if (nla_type(nla) == SK_DIAG_BPF_STORAGE_REQ_MAP_FD) | |
| 499 | + if (nla_type(nla) == SK_DIAG_BPF_STORAGE_REQ_MAP_FD) { | |
| 500 | + if (nla_len(nla) != sizeof(u32)) | |
| 501 | + return ERR_PTR(-EINVAL); | |
| 500 | 502 | nr_maps++; |
| 503 | + } | |
| 501 | 504 | } |
| 502 | 505 | |
| 503 | 506 | diag = kzalloc(struct_size(diag, maps, nr_maps), GFP_KERNEL); |
| @@ -4116,12 +4116,6 @@ BPF_CALL_2(bpf_xdp_adjust_tail, struct xdp_buff *, xdp, int, offset) · 4115 unmodified lines | ||
| 4116 | 4116 | if (unlikely(data_end > data_hard_end)) |
| 4117 | 4117 | return -EINVAL; |
| 4118 | 4118 | |
| 4119 | − /* ALL drivers MUST init xdp->frame_sz, chicken check below */ | |
| 4120 | − if (unlikely(xdp->frame_sz > PAGE_SIZE)) { | |
| 4121 | − WARN_ONCE(1, "Too BIG xdp->frame_sz = %d\n", xdp->frame_sz); | |
| 4122 | − return -EINVAL; | |
| 4123 | − } | |
| 4124 | − | |
| 4125 | 4119 | if (unlikely(data_end < xdp->data + ETH_HLEN)) |
| 4126 | 4120 | return -EINVAL; |
| 4127 | 4121 | |
| @@ -5140,13 +5140,17 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, · 5139 unmodified lines | ||
| 5140 | 5140 | br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); |
| 5141 | 5141 | if (br_spec) { |
| 5142 | 5142 | nla_for_each_nested(attr, br_spec, rem) { |
| 5143 | − if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { | |
| 5143 | + if (nla_type(attr) == IFLA_BRIDGE_FLAGS && !have_flags) { | |
| 5144 | 5144 | if (nla_len(attr) < sizeof(flags)) |
| 5145 | 5145 | return -EINVAL; |
| 5146 | 5146 | |
| 5147 | 5147 | have_flags = true; |
| 5148 | 5148 | flags = nla_get_u16(attr); |
| 5149 | − break; | |
| 5149 | + } | |
| 5150 | + | |
| 5151 | + if (nla_type(attr) == IFLA_BRIDGE_MODE) { | |
| 5152 | + if (nla_len(attr) < sizeof(u16)) | |
| 5153 | + return -EINVAL; | |
| 5150 | 5154 | } |
| 5151 | 5155 | } |
| 5152 | 5156 | } |
| @@ -1120,13 +1120,19 @@ static void sk_psock_strp_data_ready(struct sock *sk) · 1119 unmodified lines | ||
| 1120 | 1120 | |
| 1121 | 1121 | int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock) |
| 1122 | 1122 | { |
| 1123 | + int ret; | |
| 1124 | + | |
| 1123 | 1125 | static const struct strp_callbacks cb = { |
| 1124 | 1126 | .rcv_msg = sk_psock_strp_read, |
| 1125 | 1127 | .read_sock_done = sk_psock_strp_read_done, |
| 1126 | 1128 | .parse_msg = sk_psock_strp_parse, |
| 1127 | 1129 | }; |
| 1128 | 1130 | |
| 1129 | − return strp_init(&psock->strp, sk, &cb); | |
| 1131 | + ret = strp_init(&psock->strp, sk, &cb); | |
| 1132 | + if (!ret) | |
| 1133 | + sk_psock_set_state(psock, SK_PSOCK_RX_STRP_ENABLED); | |
| 1134 | + | |
| 1135 | + return ret; | |
| 1130 | 1136 | } |
| 1131 | 1137 | |
| 1132 | 1138 | void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock) |
| @@ -1154,7 +1160,7 @@ void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) · 21 unmodified lines | ||
| 1154 | 1160 | static void sk_psock_done_strp(struct sk_psock *psock) |
| 1155 | 1161 | { |
| 1156 | 1162 | /* Parser has been stopped */ |
| 1157 | − if (psock->progs.stream_parser) | |
| 1163 | + if (sk_psock_test_state(psock, SK_PSOCK_RX_STRP_ENABLED)) | |
| 1158 | 1164 | strp_done(&psock->strp); |
| 1159 | 1165 | } |
| 1160 | 1166 | #else |
| @@ -429,6 +429,7 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen, · 428 unmodified lines | ||
| 429 | 429 | { |
| 430 | 430 | struct __kernel_sock_timeval tv; |
| 431 | 431 | int err = sock_copy_user_timeval(&tv, optval, optlen, old_timeval); |
| 432 | + long val; | |
| 432 | 433 | |
| 433 | 434 | if (err) |
| 434 | 435 | return err; |
| @@ -439,7 +440,7 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen, · 4 unmodified lines | ||
| 439 | 440 | if (tv.tv_sec < 0) { |
| 440 | 441 | static int warned __read_mostly; |
| 441 | 442 | |
| 442 | − *timeo_p = 0; | |
| 443 | + WRITE_ONCE(*timeo_p, 0); | |
| 443 | 444 | if (warned < 10 && net_ratelimit()) { |
| 444 | 445 | warned++; |
| 445 | 446 | pr_info("%s: `%s' (pid %d) tries to set negative timeout\n", |
| @@ -447,11 +448,12 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen, · 1 unmodified line | ||
| 447 | 448 | } |
| 448 | 449 | return 0; |
| 449 | 450 | } |
| 450 | − *timeo_p = MAX_SCHEDULE_TIMEOUT; | |
| 451 | − if (tv.tv_sec == 0 && tv.tv_usec == 0) | |
| 452 | − return 0; | |
| 453 | − if (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1)) | |
| 454 | − *timeo_p = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec, USEC_PER_SEC / HZ); | |
| 451 | + val = MAX_SCHEDULE_TIMEOUT; | |
| 452 | + if ((tv.tv_sec || tv.tv_usec) && | |
| 453 | + (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1))) | |
| 454 | + val = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec, | |
| 455 | + USEC_PER_SEC / HZ); | |
| 456 | + WRITE_ONCE(*timeo_p, val); | |
| 455 | 457 | return 0; |
| 456 | 458 | } |
| 457 | 459 | |
| @@ -804,7 +806,7 @@ EXPORT_SYMBOL(sock_no_linger); · 346 unmodified lines | ||
| 804 | 806 | void sock_set_priority(struct sock *sk, u32 priority) |
| 805 | 807 | { |
| 806 | 808 | lock_sock(sk); |
| 807 | − sk->sk_priority = priority; | |
| 809 | + WRITE_ONCE(sk->sk_priority, priority); | |
| 808 | 810 | release_sock(sk); |
| 809 | 811 | } |
| 810 | 812 | EXPORT_SYMBOL(sock_set_priority); |
| @@ -813,9 +815,9 @@ void sock_set_sndtimeo(struct sock *sk, s64 secs) · 2 unmodified lines | ||
| 813 | 815 | { |
| 814 | 816 | lock_sock(sk); |
| 815 | 817 | if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1) |
| 816 | − sk->sk_sndtimeo = secs * HZ; | |
| 818 | + WRITE_ONCE(sk->sk_sndtimeo, secs * HZ); | |
| 817 | 819 | else |
| 818 | − sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; | |
| 820 | + WRITE_ONCE(sk->sk_sndtimeo, MAX_SCHEDULE_TIMEOUT); | |
| 819 | 821 | release_sock(sk); |
| 820 | 822 | } |
| 821 | 823 | EXPORT_SYMBOL(sock_set_sndtimeo); |
| @@ -988,7 +990,7 @@ EXPORT_SYMBOL(sock_set_rcvbuf); · 166 unmodified lines | ||
| 988 | 990 | static void __sock_set_mark(struct sock *sk, u32 val) |
| 989 | 991 | { |
| 990 | 992 | if (val != sk->sk_mark) { |
| 991 | − sk->sk_mark = val; | |
| 993 | + WRITE_ONCE(sk->sk_mark, val); | |
| 992 | 994 | sk_dst_reset(sk); |
| 993 | 995 | } |
| 994 | 996 | } |
| @@ -1007,7 +1009,7 @@ static void sock_release_reserved_memory(struct sock *sk, int bytes) · 12 unmodified lines | ||
| 1007 | 1009 | bytes = round_down(bytes, PAGE_SIZE); |
| 1008 | 1010 | |
| 1009 | 1011 | WARN_ON(bytes > sk->sk_reserved_mem); |
| 1010 | − sk->sk_reserved_mem -= bytes; | |
| 1012 | + WRITE_ONCE(sk->sk_reserved_mem, sk->sk_reserved_mem - bytes); | |
| 1011 | 1013 | sk_mem_reclaim(sk); |
| 1012 | 1014 | } |
| 1013 | 1015 | |
| @@ -1044,7 +1046,8 @@ static int sock_reserve_memory(struct sock *sk, int bytes) · 30 unmodified lines | ||
| 1044 | 1046 | } |
| 1045 | 1047 | sk->sk_forward_alloc += pages << PAGE_SHIFT; |
| 1046 | 1048 | |
| 1047 | − sk->sk_reserved_mem += pages << PAGE_SHIFT; | |
| 1049 | + WRITE_ONCE(sk->sk_reserved_mem, | |
| 1050 | + sk->sk_reserved_mem + (pages << PAGE_SHIFT)); | |
| 1048 | 1051 | |
| 1049 | 1052 | return 0; |
| 1050 | 1053 | } |
| @@ -1213,7 +1216,7 @@ set_sndbuf: · 162 unmodified lines | ||
| 1213 | 1216 | if ((val >= 0 && val <= 6) || |
| 1214 | 1217 | sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) || |
| 1215 | 1218 | sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) |
| 1216 | − sk->sk_priority = val; | |
| 1219 | + WRITE_ONCE(sk->sk_priority, val); | |
| 1217 | 1220 | else |
| 1218 | 1221 | ret = -EPERM; |
| 1219 | 1222 | break; |
| @@ -1438,7 +1441,8 @@ set_sndbuf: · 218 unmodified lines | ||
| 1438 | 1441 | cmpxchg(&sk->sk_pacing_status, |
| 1439 | 1442 | SK_PACING_NONE, |
| 1440 | 1443 | SK_PACING_NEEDED); |
| 1441 | − sk->sk_max_pacing_rate = ulval; | |
| 1444 | + /* Pairs with READ_ONCE() from sk_getsockopt() */ | |
| 1445 | + WRITE_ONCE(sk->sk_max_pacing_rate, ulval); | |
| 1442 | 1446 | sk->sk_pacing_rate = min(sk->sk_pacing_rate, ulval); |
| 1443 | 1447 | break; |
| 1444 | 1448 | } |
| @@ -1533,7 +1537,9 @@ set_sndbuf: · 88 unmodified lines | ||
| 1533 | 1537 | } |
| 1534 | 1538 | if ((u8)val == SOCK_TXREHASH_DEFAULT) |
| 1535 | 1539 | val = READ_ONCE(sock_net(sk)->core.sysctl_txrehash); |
| 1536 | − /* Paired with READ_ONCE() in tcp_rtx_synack() */ | |
| 1540 | + /* Paired with READ_ONCE() in tcp_rtx_synack() | |
| 1541 | + * and sk_getsockopt(). | |
| 1542 | + */ | |
| 1537 | 1543 | WRITE_ONCE(sk->sk_txrehash, (u8)val); |
| 1538 | 1544 | break; |
| 1539 | 1545 | |
| @@ -1633,11 +1639,11 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 93 unmodified lines | ||
| 1633 | 1639 | break; |
| 1634 | 1640 | |
| 1635 | 1641 | case SO_SNDBUF: |
| 1636 | − v.val = sk->sk_sndbuf; | |
| 1642 | + v.val = READ_ONCE(sk->sk_sndbuf); | |
| 1637 | 1643 | break; |
| 1638 | 1644 | |
| 1639 | 1645 | case SO_RCVBUF: |
| 1640 | − v.val = sk->sk_rcvbuf; | |
| 1646 | + v.val = READ_ONCE(sk->sk_rcvbuf); | |
| 1641 | 1647 | break; |
| 1642 | 1648 | |
| 1643 | 1649 | case SO_REUSEADDR: |
| @@ -1679,7 +1685,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 35 unmodified lines | ||
| 1679 | 1685 | break; |
| 1680 | 1686 | |
| 1681 | 1687 | case SO_PRIORITY: |
| 1682 | − v.val = sk->sk_priority; | |
| 1688 | + v.val = READ_ONCE(sk->sk_priority); | |
| 1683 | 1689 | break; |
| 1684 | 1690 | |
| 1685 | 1691 | case SO_LINGER: |
| @@ -1717,16 +1723,18 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 31 unmodified lines | ||
| 1717 | 1723 | |
| 1718 | 1724 | case SO_RCVTIMEO_OLD: |
| 1719 | 1725 | case SO_RCVTIMEO_NEW: |
| 1720 | − lv = sock_get_timeout(sk->sk_rcvtimeo, &v, SO_RCVTIMEO_OLD == optname); | |
| 1726 | + lv = sock_get_timeout(READ_ONCE(sk->sk_rcvtimeo), &v, | |
| 1727 | + SO_RCVTIMEO_OLD == optname); | |
| 1721 | 1728 | break; |
| 1722 | 1729 | |
| 1723 | 1730 | case SO_SNDTIMEO_OLD: |
| 1724 | 1731 | case SO_SNDTIMEO_NEW: |
| 1725 | − lv = sock_get_timeout(sk->sk_sndtimeo, &v, SO_SNDTIMEO_OLD == optname); | |
| 1732 | + lv = sock_get_timeout(READ_ONCE(sk->sk_sndtimeo), &v, | |
| 1733 | + SO_SNDTIMEO_OLD == optname); | |
| 1726 | 1734 | break; |
| 1727 | 1735 | |
| 1728 | 1736 | case SO_RCVLOWAT: |
| 1729 | − v.val = sk->sk_rcvlowat; | |
| 1737 | + v.val = READ_ONCE(sk->sk_rcvlowat); | |
| 1730 | 1738 | break; |
| 1731 | 1739 | |
| 1732 | 1740 | case SO_SNDLOWAT: |
| @@ -1770,7 +1778,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 37 unmodified lines | ||
| 1770 | 1778 | spin_unlock(&sk->sk_peer_lock); |
| 1771 | 1779 | |
| 1772 | 1780 | if (!peer_pid) |
| 1773 | − return -ESRCH; | |
| 1781 | + return -ENODATA; | |
| 1774 | 1782 | |
| 1775 | 1783 | pidfd = pidfd_prepare(peer_pid, 0, &pidfd_file); |
| 1776 | 1784 | put_pid(peer_pid); |
| @@ -1843,7 +1851,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 66 unmodified lines | ||
| 1843 | 1851 | optval, optlen, len); |
| 1844 | 1852 | |
| 1845 | 1853 | case SO_MARK: |
| 1846 | − v.val = sk->sk_mark; | |
| 1854 | + v.val = READ_ONCE(sk->sk_mark); | |
| 1847 | 1855 | break; |
| 1848 | 1856 | |
| 1849 | 1857 | case SO_RCVMARK: |
| @@ -1862,7 +1870,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 12 unmodified lines | ||
| 1862 | 1870 | if (!sock->ops->set_peek_off) |
| 1863 | 1871 | return -EOPNOTSUPP; |
| 1864 | 1872 | |
| 1865 | − v.val = sk->sk_peek_off; | |
| 1873 | + v.val = READ_ONCE(sk->sk_peek_off); | |
| 1866 | 1874 | break; |
| 1867 | 1875 | case SO_NOFCS: |
| 1868 | 1876 | v.val = sock_flag(sk, SOCK_NOFCS); |
| @@ -1892,7 +1900,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 23 unmodified lines | ||
| 1892 | 1900 | |
| 1893 | 1901 | #ifdef CONFIG_NET_RX_BUSY_POLL |
| 1894 | 1902 | case SO_BUSY_POLL: |
| 1895 | − v.val = sk->sk_ll_usec; | |
| 1903 | + v.val = READ_ONCE(sk->sk_ll_usec); | |
| 1896 | 1904 | break; |
| 1897 | 1905 | case SO_PREFER_BUSY_POLL: |
| 1898 | 1906 | v.val = READ_ONCE(sk->sk_prefer_busy_poll); |
| @@ -1900,12 +1908,14 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 1 unmodified line | ||
| 1900 | 1908 | #endif |
| 1901 | 1909 | |
| 1902 | 1910 | case SO_MAX_PACING_RATE: |
| 1911 | + /* The READ_ONCE() pair with the WRITE_ONCE() in sk_setsockopt() */ | |
| 1903 | 1912 | if (sizeof(v.ulval) != sizeof(v.val) && len >= sizeof(v.ulval)) { |
| 1904 | 1913 | lv = sizeof(v.ulval); |
| 1905 | − v.ulval = sk->sk_max_pacing_rate; | |
| 1914 | + v.ulval = READ_ONCE(sk->sk_max_pacing_rate); | |
| 1906 | 1915 | } else { |
| 1907 | 1916 | /* 32bit version */ |
| 1908 | − v.val = min_t(unsigned long, sk->sk_max_pacing_rate, ~0U); | |
| 1917 | + v.val = min_t(unsigned long, ~0U, | |
| 1918 | + READ_ONCE(sk->sk_max_pacing_rate)); | |
| 1909 | 1919 | } |
| 1910 | 1920 | break; |
| 1911 | 1921 | |
| @@ -1973,11 +1983,12 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 61 unmodified lines | ||
| 1973 | 1983 | break; |
| 1974 | 1984 | |
| 1975 | 1985 | case SO_RESERVE_MEM: |
| 1976 | − v.val = sk->sk_reserved_mem; | |
| 1986 | + v.val = READ_ONCE(sk->sk_reserved_mem); | |
| 1977 | 1987 | break; |
| 1978 | 1988 | |
| 1979 | 1989 | case SO_TXREHASH: |
| 1980 | − v.val = sk->sk_txrehash; | |
| 1990 | + /* Paired with WRITE_ONCE() in sk_setsockopt() */ | |
| 1991 | + v.val = READ_ONCE(sk->sk_txrehash); | |
| 1981 | 1992 | break; |
| 1982 | 1993 | |
| 1983 | 1994 | default: |
| @@ -3168,7 +3179,7 @@ EXPORT_SYMBOL(__sk_mem_reclaim); · 1184 unmodified lines | ||
| 3168 | 3179 | |
| 3169 | 3180 | int sk_set_peek_off(struct sock *sk, int val) |
| 3170 | 3181 | { |
| 3171 | − sk->sk_peek_off = val; | |
| 3182 | + WRITE_ONCE(sk->sk_peek_off, val); | |
| 3172 | 3183 | return 0; |
| 3173 | 3184 | } |
| 3174 | 3185 | EXPORT_SYMBOL_GPL(sk_set_peek_off); |
| @@ -115,7 +115,6 @@ static void sock_map_sk_acquire(struct sock *sk) · 114 unmodified lines | ||
| 115 | 115 | __acquires(&sk->sk_lock.slock) |
| 116 | 116 | { |
| 117 | 117 | lock_sock(sk); |
| 118 | − preempt_disable(); | |
| 119 | 118 | rcu_read_lock(); |
| 120 | 119 | } |
| 121 | 120 | |
| @@ -123,7 +122,6 @@ static void sock_map_sk_release(struct sock *sk) · 1 unmodified line | ||
| 123 | 122 | __releases(&sk->sk_lock.slock) |
| 124 | 123 | { |
| 125 | 124 | rcu_read_unlock(); |
| 126 | − preempt_enable(); | |
| 127 | 125 | release_sock(sk); |
| 128 | 126 | } |
| 129 | 127 | |
| @@ -148,13 +146,13 @@ static void sock_map_del_link(struct sock *sk, · 18 unmodified lines | ||
| 148 | 146 | list_for_each_entry_safe(link, tmp, &psock->link, list) { |
| 149 | 147 | if (link->link_raw == link_raw) { |
| 150 | 148 | struct bpf_map *map = link->map; |
| 151 | − struct bpf_stab *stab = container_of(map, struct bpf_stab, | |
| 152 | − map); | |
| 153 | − if (psock->saved_data_ready && stab->progs.stream_parser) | |
| 149 | + struct sk_psock_progs *progs = sock_map_progs(map); | |
| 150 | + | |
| 151 | + if (psock->saved_data_ready && progs->stream_parser) | |
| 154 | 152 | strp_stop = true; |
| 155 | − if (psock->saved_data_ready && stab->progs.stream_verdict) | |
| 153 | + if (psock->saved_data_ready && progs->stream_verdict) | |
| 156 | 154 | verdict_stop = true; |
| 157 | − if (psock->saved_data_ready && stab->progs.skb_verdict) | |
| 155 | + if (psock->saved_data_ready && progs->skb_verdict) | |
| 158 | 156 | verdict_stop = true; |
| 159 | 157 | list_del(&link->list); |
| 160 | 158 | sk_psock_free_link(link); |
| @@ -980,7 +980,7 @@ static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, · 979 unmodified lines | ||
| 980 | 980 | return -EOPNOTSUPP; |
| 981 | 981 | |
| 982 | 982 | ret = nla_parse_nested_deprecated(data, DCB_BCN_ATTR_MAX, |
| 983 | − tb[DCB_ATTR_BCN], dcbnl_pfc_up_nest, | |
| 983 | + tb[DCB_ATTR_BCN], dcbnl_bcn_nest, | |
| 984 | 984 | NULL); |
| 985 | 985 | if (ret) |
| 986 | 986 | return ret; |
| @@ -238,8 +238,8 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req · 237 unmodified lines | ||
| 238 | 238 | opt = ireq->ipv6_opt; |
| 239 | 239 | if (!opt) |
| 240 | 240 | opt = rcu_dereference(np->opt); |
| 241 | − err = ip6_xmit(sk, skb, &fl6, sk->sk_mark, opt, np->tclass, | |
| 242 | − sk->sk_priority); | |
| 241 | + err = ip6_xmit(sk, skb, &fl6, READ_ONCE(sk->sk_mark), opt, | |
| 242 | + np->tclass, sk->sk_priority); | |
| 243 | 243 | rcu_read_unlock(); |
| 244 | 244 | err = net_xmit_eval(err); |
| 245 | 245 | } |
| @@ -187,7 +187,7 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu) · 186 unmodified lines | ||
| 187 | 187 | |
| 188 | 188 | /* And store cached results */ |
| 189 | 189 | icsk->icsk_pmtu_cookie = pmtu; |
| 190 | − dp->dccps_mss_cache = cur_mps; | |
| 190 | + WRITE_ONCE(dp->dccps_mss_cache, cur_mps); | |
| 191 | 191 | |
| 192 | 192 | return cur_mps; |
| 193 | 193 | } |
| @@ -630,7 +630,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname, · 629 unmodified lines | ||
| 630 | 630 | return dccp_getsockopt_service(sk, len, |
| 631 | 631 | (__be32 __user *)optval, optlen); |
| 632 | 632 | case DCCP_SOCKOPT_GET_CUR_MPS: |
| 633 | − val = dp->dccps_mss_cache; | |
| 633 | + val = READ_ONCE(dp->dccps_mss_cache); | |
| 634 | 634 | break; |
| 635 | 635 | case DCCP_SOCKOPT_AVAILABLE_CCIDS: |
| 636 | 636 | return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen); |
| @@ -739,7 +739,7 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 102 unmodified lines | ||
| 739 | 739 | |
| 740 | 740 | trace_dccp_probe(sk, len); |
| 741 | 741 | |
| 742 | − if (len > dp->dccps_mss_cache) | |
| 742 | + if (len > READ_ONCE(dp->dccps_mss_cache)) | |
| 743 | 743 | return -EMSGSIZE; |
| 744 | 744 | |
| 745 | 745 | lock_sock(sk); |
| @@ -772,6 +772,12 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 26 unmodified lines | ||
| 772 | 772 | goto out_discard; |
| 773 | 773 | } |
| 774 | 774 | |
| 775 | + /* We need to check dccps_mss_cache after socket is locked. */ | |
| 776 | + if (len > dp->dccps_mss_cache) { | |
| 777 | + rc = -EMSGSIZE; | |
| 778 | + goto out_discard; | |
| 779 | + } | |
| 780 | + | |
| 775 | 781 | skb_reserve(skb, sk->sk_prot->max_header); |
| 776 | 782 | rc = memcpy_from_msg(skb_put(skb, len), msg, len); |
| 777 | 783 | if (rc != 0) |
| @@ -1727,8 +1727,15 @@ int dsa_port_phylink_create(struct dsa_port *dp) · 1726 unmodified lines | ||
| 1727 | 1727 | ds->ops->phylink_mac_an_restart) |
| 1728 | 1728 | dp->pl_config.legacy_pre_march2020 = true; |
| 1729 | 1729 | |
| 1730 | − if (ds->ops->phylink_get_caps) | |
| 1730 | + if (ds->ops->phylink_get_caps) { | |
| 1731 | 1731 | ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config); |
| 1732 | + } else { | |
| 1733 | + /* For legacy drivers */ | |
| 1734 | + __set_bit(PHY_INTERFACE_MODE_INTERNAL, | |
| 1735 | + dp->pl_config.supported_interfaces); | |
| 1736 | + __set_bit(PHY_INTERFACE_MODE_GMII, | |
| 1737 | + dp->pl_config.supported_interfaces); | |
| 1738 | + } | |
| 1732 | 1739 | |
| 1733 | 1740 | pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), |
| 1734 | 1741 | mode, &dsa_port_phylink_mac_ops); |
| @@ -150,7 +150,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, · 149 unmodified lines | ||
| 150 | 150 | } |
| 151 | 151 | #endif |
| 152 | 152 | |
| 153 | − if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, sk->sk_mark)) | |
| 153 | + if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, READ_ONCE(sk->sk_mark))) | |
| 154 | 154 | goto errout; |
| 155 | 155 | |
| 156 | 156 | if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) || |
| @@ -799,7 +799,7 @@ int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk) · 642 unmodified lines | ||
| 799 | 799 | entry.ifindex = sk->sk_bound_dev_if; |
| 800 | 800 | entry.userlocks = sk_fullsock(sk) ? sk->sk_userlocks : 0; |
| 801 | 801 | if (sk_fullsock(sk)) |
| 802 | − entry.mark = sk->sk_mark; | |
| 802 | + entry.mark = READ_ONCE(sk->sk_mark); | |
| 803 | 803 | else if (sk->sk_state == TCP_NEW_SYN_RECV) |
| 804 | 804 | entry.mark = inet_rsk(inet_reqsk(sk))->ir_mark; |
| 805 | 805 | else if (sk->sk_state == TCP_TIME_WAIT) |
| @@ -184,9 +184,9 @@ int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk, · 183 unmodified lines | ||
| 184 | 184 | ip_options_build(skb, &opt->opt, daddr, rt); |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | − skb->priority = sk->sk_priority; | |
| 187 | + skb->priority = READ_ONCE(sk->sk_priority); | |
| 188 | 188 | if (!skb->mark) |
| 189 | − skb->mark = sk->sk_mark; | |
| 189 | + skb->mark = READ_ONCE(sk->sk_mark); | |
| 190 | 190 | |
| 191 | 191 | /* Send it out. */ |
| 192 | 192 | return ip_local_out(net, skb->sk, skb); |
| @@ -528,8 +528,8 @@ packet_routed: · 335 unmodified lines | ||
| 528 | 528 | skb_shinfo(skb)->gso_segs ?: 1); |
| 529 | 529 | |
| 530 | 530 | /* TODO : should we use skb->sk here instead of sk ? */ |
| 531 | − skb->priority = sk->sk_priority; | |
| 532 | − skb->mark = sk->sk_mark; | |
| 531 | + skb->priority = READ_ONCE(sk->sk_priority); | |
| 532 | + skb->mark = READ_ONCE(sk->sk_mark); | |
| 533 | 533 | |
| 534 | 534 | res = ip_local_out(net, sk, skb); |
| 535 | 535 | rcu_read_unlock(); |
| @@ -1158,10 +1158,15 @@ alloc_new_skb: · 622 unmodified lines | ||
| 1158 | 1158 | } |
| 1159 | 1159 | |
| 1160 | 1160 | copy = datalen - transhdrlen - fraggap - pagedlen; |
| 1161 | + /* [!] NOTE: copy will be negative if pagedlen>0 | |
| 1162 | + * because then the equation reduces to -fraggap. | |
| 1163 | + */ | |
| 1161 | 1164 | if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { |
| 1162 | 1165 | err = -EFAULT; |
| 1163 | 1166 | kfree_skb(skb); |
| 1164 | 1167 | goto error; |
| 1168 | + } else if (flags & MSG_SPLICE_PAGES) { | |
| 1169 | + copy = 0; | |
| 1165 | 1170 | } |
| 1166 | 1171 | |
| 1167 | 1172 | offset += copy; |
| @@ -1209,6 +1214,10 @@ alloc_new_skb: · 41 unmodified lines | ||
| 1209 | 1214 | } else if (flags & MSG_SPLICE_PAGES) { |
| 1210 | 1215 | struct msghdr *msg = from; |
| 1211 | 1216 | |
| 1217 | + err = -EIO; | |
| 1218 | + if (WARN_ON_ONCE(copy > msg->msg_iter.count)) | |
| 1219 | + goto error; | |
| 1220 | + | |
| 1212 | 1221 | err = skb_splice_from_iter(skb, &msg->msg_iter, copy, |
| 1213 | 1222 | sk->sk_allocation); |
| 1214 | 1223 | if (err < 0) |
| @@ -592,7 +592,7 @@ void __ip_sock_set_tos(struct sock *sk, int val) · 591 unmodified lines | ||
| 592 | 592 | } |
| 593 | 593 | if (inet_sk(sk)->tos != val) { |
| 594 | 594 | inet_sk(sk)->tos = val; |
| 595 | − sk->sk_priority = rt_tos2priority(val); | |
| 595 | + WRITE_ONCE(sk->sk_priority, rt_tos2priority(val)); | |
| 596 | 596 | sk_dst_reset(sk); |
| 597 | 597 | } |
| 598 | 598 | } |
| @@ -224,7 +224,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu) · 223 unmodified lines | ||
| 224 | 224 | .un.frag.__unused = 0, |
| 225 | 225 | .un.frag.mtu = htons(mtu), |
| 226 | 226 | }; |
| 227 | − icmph->checksum = ip_compute_csum(icmph, len); | |
| 227 | + icmph->checksum = csum_fold(skb_checksum(skb, 0, len, 0)); | |
| 228 | 228 | skb_reset_transport_header(skb); |
| 229 | 229 | |
| 230 | 230 | niph = skb_push(skb, sizeof(*niph)); |
| @@ -3221,13 +3221,9 @@ static int rtm_dump_nexthop(struct sk_buff *skb, struct netlink_callback *cb) · 3220 unmodified lines | ||
| 3221 | 3221 | &rtm_dump_nexthop_cb, &filter); |
| 3222 | 3222 | if (err < 0) { |
| 3223 | 3223 | if (likely(skb->len)) |
| 3224 | − goto out; | |
| 3225 | − goto out_err; | |
| 3224 | + err = skb->len; | |
| 3226 | 3225 | } |
| 3227 | 3226 | |
| 3228 | −out: | |
| 3229 | − err = skb->len; | |
| 3230 | −out_err: | |
| 3231 | 3227 | cb->seq = net->nexthop.seq; |
| 3232 | 3228 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
| 3233 | 3229 | return err; |
| @@ -3367,25 +3363,19 @@ static int rtm_dump_nexthop_bucket_nh(struct sk_buff *skb, · 133 unmodified lines | ||
| 3367 | 3363 | dd->filter.res_bucket_nh_id != nhge->nh->id) |
| 3368 | 3364 | continue; |
| 3369 | 3365 | |
| 3366 | + dd->ctx->bucket_index = bucket_index; | |
| 3370 | 3367 | err = nh_fill_res_bucket(skb, nh, bucket, bucket_index, |
| 3371 | 3368 | RTM_NEWNEXTHOPBUCKET, portid, |
| 3372 | 3369 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| 3373 | 3370 | cb->extack); |
| 3374 | − if (err < 0) { | |
| 3375 | − if (likely(skb->len)) | |
| 3376 | − goto out; | |
| 3377 | − goto out_err; | |
| 3378 | − } | |
| 3371 | + if (err) | |
| 3372 | + return err; | |
| 3379 | 3373 | } |
| 3380 | 3374 | |
| 3381 | 3375 | dd->ctx->done_nh_idx = dd->ctx->nh.idx + 1; |
| 3382 | − bucket_index = 0; | |
| 3376 | + dd->ctx->bucket_index = 0; | |
| 3383 | 3377 | |
| 3384 | −out: | |
| 3385 | − err = skb->len; | |
| 3386 | −out_err: | |
| 3387 | − dd->ctx->bucket_index = bucket_index; | |
| 3388 | − return err; | |
| 3378 | + return 0; | |
| 3389 | 3379 | } |
| 3390 | 3380 | |
| 3391 | 3381 | static int rtm_dump_nexthop_bucket_cb(struct sk_buff *skb, |
| @@ -3434,13 +3424,9 @@ static int rtm_dump_nexthop_bucket(struct sk_buff *skb, · 42 unmodified lines | ||
| 3434 | 3424 | |
| 3435 | 3425 | if (err < 0) { |
| 3436 | 3426 | if (likely(skb->len)) |
| 3437 | − goto out; | |
| 3438 | − goto out_err; | |
| 3427 | + err = skb->len; | |
| 3439 | 3428 | } |
| 3440 | 3429 | |
| 3441 | −out: | |
| 3442 | − err = skb->len; | |
| 3443 | −out_err: | |
| 3444 | 3430 | cb->seq = net->nexthop.seq; |
| 3445 | 3431 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
| 3446 | 3432 | return err; |
| @@ -348,7 +348,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, · 347 unmodified lines | ||
| 348 | 348 | goto error; |
| 349 | 349 | skb_reserve(skb, hlen); |
| 350 | 350 | |
| 351 | − skb->priority = sk->sk_priority; | |
| 351 | + skb->priority = READ_ONCE(sk->sk_priority); | |
| 352 | 352 | skb->mark = sockc->mark; |
| 353 | 353 | skb->tstamp = sockc->transmit_time; |
| 354 | 354 | skb_dst_set(skb, &rt->dst); |
| @@ -518,7 +518,7 @@ static void __build_flow_key(const struct net *net, struct flowi4 *fl4, · 517 unmodified lines | ||
| 518 | 518 | const struct inet_sock *inet = inet_sk(sk); |
| 519 | 519 | |
| 520 | 520 | oif = sk->sk_bound_dev_if; |
| 521 | − mark = sk->sk_mark; | |
| 521 | + mark = READ_ONCE(sk->sk_mark); | |
| 522 | 522 | tos = ip_sock_rt_tos(sk); |
| 523 | 523 | scope = ip_sock_rt_scope(sk); |
| 524 | 524 | prot = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol; |
| @@ -552,7 +552,7 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk) · 27 unmodified lines | ||
| 552 | 552 | inet_opt = rcu_dereference(inet->inet_opt); |
| 553 | 553 | if (inet_opt && inet_opt->opt.srr) |
| 554 | 554 | daddr = inet_opt->opt.faddr; |
| 555 | − flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, | |
| 555 | + flowi4_init_output(fl4, sk->sk_bound_dev_if, READ_ONCE(sk->sk_mark), | |
| 556 | 556 | ip_sock_rt_tos(sk) & IPTOS_RT_MASK, |
| 557 | 557 | ip_sock_rt_scope(sk), |
| 558 | 558 | inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, |
| @@ -931,9 +931,9 @@ static void tcp_v4_send_ack(const struct sock *sk, · 930 unmodified lines | ||
| 931 | 931 | ctl_sk = this_cpu_read(ipv4_tcp_sk); |
| 932 | 932 | sock_net_set(ctl_sk, net); |
| 933 | 933 | ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ? |
| 934 | − inet_twsk(sk)->tw_mark : sk->sk_mark; | |
| 934 | + inet_twsk(sk)->tw_mark : READ_ONCE(sk->sk_mark); | |
| 935 | 935 | ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ? |
| 936 | − inet_twsk(sk)->tw_priority : sk->sk_priority; | |
| 936 | + inet_twsk(sk)->tw_priority : READ_ONCE(sk->sk_priority); | |
| 937 | 937 | transmit_time = tcp_transmit_time(sk); |
| 938 | 938 | ip_send_unicast_reply(ctl_sk, |
| 939 | 939 | skb, &TCP_SKB_CB(skb)->header.h4.opt, |
| @@ -40,7 +40,7 @@ struct tcp_fastopen_metrics { · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | struct tcp_metrics_block { |
| 42 | 42 | struct tcp_metrics_block __rcu *tcpm_next; |
| 43 | − possible_net_t tcpm_net; | |
| 43 | + struct net *tcpm_net; | |
| 44 | 44 | struct inetpeer_addr tcpm_saddr; |
| 45 | 45 | struct inetpeer_addr tcpm_daddr; |
| 46 | 46 | unsigned long tcpm_stamp; |
| @@ -51,34 +51,38 @@ struct tcp_metrics_block { · 4 unmodified lines | ||
| 51 | 51 | struct rcu_head rcu_head; |
| 52 | 52 | }; |
| 53 | 53 | |
| 54 | −static inline struct net *tm_net(struct tcp_metrics_block *tm) | |
| 54 | +static inline struct net *tm_net(const struct tcp_metrics_block *tm) | |
| 55 | 55 | { |
| 56 | − return read_pnet(&tm->tcpm_net); | |
| 56 | + /* Paired with the WRITE_ONCE() in tcpm_new() */ | |
| 57 | + return READ_ONCE(tm->tcpm_net); | |
| 57 | 58 | } |
| 58 | 59 | |
| 59 | 60 | static bool tcp_metric_locked(struct tcp_metrics_block *tm, |
| 60 | 61 | enum tcp_metric_index idx) |
| 61 | 62 | { |
| 62 | − return tm->tcpm_lock & (1 << idx); | |
| 63 | + /* Paired with WRITE_ONCE() in tcpm_suck_dst() */ | |
| 64 | + return READ_ONCE(tm->tcpm_lock) & (1 << idx); | |
| 63 | 65 | } |
| 64 | 66 | |
| 65 | −static u32 tcp_metric_get(struct tcp_metrics_block *tm, | |
| 67 | +static u32 tcp_metric_get(const struct tcp_metrics_block *tm, | |
| 66 | 68 | enum tcp_metric_index idx) |
| 67 | 69 | { |
| 68 | − return tm->tcpm_vals[idx]; | |
| 70 | + /* Paired with WRITE_ONCE() in tcp_metric_set() */ | |
| 71 | + return READ_ONCE(tm->tcpm_vals[idx]); | |
| 69 | 72 | } |
| 70 | 73 | |
| 71 | 74 | static void tcp_metric_set(struct tcp_metrics_block *tm, |
| 72 | 75 | enum tcp_metric_index idx, |
| 73 | 76 | u32 val) |
| 74 | 77 | { |
| 75 | − tm->tcpm_vals[idx] = val; | |
| 78 | + /* Paired with READ_ONCE() in tcp_metric_get() */ | |
| 79 | + WRITE_ONCE(tm->tcpm_vals[idx], val); | |
| 76 | 80 | } |
| 77 | 81 | |
| 78 | 82 | static bool addr_same(const struct inetpeer_addr *a, |
| 79 | 83 | const struct inetpeer_addr *b) |
| 80 | 84 | { |
| 81 | − return inetpeer_addr_cmp(a, b) == 0; | |
| 85 | + return (a->family == b->family) && !inetpeer_addr_cmp(a, b); | |
| 82 | 86 | } |
| 83 | 87 | |
| 84 | 88 | struct tcpm_hash_bucket { |
| @@ -89,6 +93,7 @@ static struct tcpm_hash_bucket *tcp_metrics_hash __read_mostly; · 4 unmodified lines | ||
| 89 | 93 | static unsigned int tcp_metrics_hash_log __read_mostly; |
| 90 | 94 | |
| 91 | 95 | static DEFINE_SPINLOCK(tcp_metrics_lock); |
| 96 | +static DEFINE_SEQLOCK(fastopen_seqlock); | |
| 92 | 97 | |
| 93 | 98 | static void tcpm_suck_dst(struct tcp_metrics_block *tm, |
| 94 | 99 | const struct dst_entry *dst, |
| @@ -97,7 +102,7 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, · 2 unmodified lines | ||
| 97 | 102 | u32 msval; |
| 98 | 103 | u32 val; |
| 99 | 104 | |
| 100 | − tm->tcpm_stamp = jiffies; | |
| 105 | + WRITE_ONCE(tm->tcpm_stamp, jiffies); | |
| 101 | 106 | |
| 102 | 107 | val = 0; |
| 103 | 108 | if (dst_metric_locked(dst, RTAX_RTT)) |
| @@ -110,30 +115,42 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, · 6 unmodified lines | ||
| 110 | 115 | val |= 1 << TCP_METRIC_CWND; |
| 111 | 116 | if (dst_metric_locked(dst, RTAX_REORDERING)) |
| 112 | 117 | val |= 1 << TCP_METRIC_REORDERING; |
| 113 | − tm->tcpm_lock = val; | |
| 118 | + /* Paired with READ_ONCE() in tcp_metric_locked() */ | |
| 119 | + WRITE_ONCE(tm->tcpm_lock, val); | |
| 114 | 120 | |
| 115 | 121 | msval = dst_metric_raw(dst, RTAX_RTT); |
| 116 | − tm->tcpm_vals[TCP_METRIC_RTT] = msval * USEC_PER_MSEC; | |
| 122 | + tcp_metric_set(tm, TCP_METRIC_RTT, msval * USEC_PER_MSEC); | |
| 117 | 123 | |
| 118 | 124 | msval = dst_metric_raw(dst, RTAX_RTTVAR); |
| 119 | − tm->tcpm_vals[TCP_METRIC_RTTVAR] = msval * USEC_PER_MSEC; | |
| 120 | − tm->tcpm_vals[TCP_METRIC_SSTHRESH] = dst_metric_raw(dst, RTAX_SSTHRESH); | |
| 121 | − tm->tcpm_vals[TCP_METRIC_CWND] = dst_metric_raw(dst, RTAX_CWND); | |
| 122 | − tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING); | |
| 125 | + tcp_metric_set(tm, TCP_METRIC_RTTVAR, msval * USEC_PER_MSEC); | |
| 126 | + tcp_metric_set(tm, TCP_METRIC_SSTHRESH, | |
| 127 | + dst_metric_raw(dst, RTAX_SSTHRESH)); | |
| 128 | + tcp_metric_set(tm, TCP_METRIC_CWND, | |
| 129 | + dst_metric_raw(dst, RTAX_CWND)); | |
| 130 | + tcp_metric_set(tm, TCP_METRIC_REORDERING, | |
| 131 | + dst_metric_raw(dst, RTAX_REORDERING)); | |
| 123 | 132 | if (fastopen_clear) { |
| 133 | + write_seqlock(&fastopen_seqlock); | |
| 124 | 134 | tm->tcpm_fastopen.mss = 0; |
| 125 | 135 | tm->tcpm_fastopen.syn_loss = 0; |
| 126 | 136 | tm->tcpm_fastopen.try_exp = 0; |
| 127 | 137 | tm->tcpm_fastopen.cookie.exp = false; |
| 128 | 138 | tm->tcpm_fastopen.cookie.len = 0; |
| 139 | + write_sequnlock(&fastopen_seqlock); | |
| 129 | 140 | } |
| 130 | 141 | } |
| 131 | 142 | |
| 132 | 143 | #define TCP_METRICS_TIMEOUT (60 * 60 * HZ) |
| 133 | 144 | |
| 134 | −static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst) | |
| 145 | +static void tcpm_check_stamp(struct tcp_metrics_block *tm, | |
| 146 | + const struct dst_entry *dst) | |
| 135 | 147 | { |
| 136 | − if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT))) | |
| 148 | + unsigned long limit; | |
| 149 | + | |
| 150 | + if (!tm) | |
| 151 | + return; | |
| 152 | + limit = READ_ONCE(tm->tcpm_stamp) + TCP_METRICS_TIMEOUT; | |
| 153 | + if (unlikely(time_after(jiffies, limit))) | |
| 137 | 154 | tcpm_suck_dst(tm, dst, false); |
| 138 | 155 | } |
| 139 | 156 | |
| @@ -174,20 +191,23 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst, · 34 unmodified lines | ||
| 174 | 191 | oldest = deref_locked(tcp_metrics_hash[hash].chain); |
| 175 | 192 | for (tm = deref_locked(oldest->tcpm_next); tm; |
| 176 | 193 | tm = deref_locked(tm->tcpm_next)) { |
| 177 | − if (time_before(tm->tcpm_stamp, oldest->tcpm_stamp)) | |
| 194 | + if (time_before(READ_ONCE(tm->tcpm_stamp), | |
| 195 | + READ_ONCE(oldest->tcpm_stamp))) | |
| 178 | 196 | oldest = tm; |
| 179 | 197 | } |
| 180 | 198 | tm = oldest; |
| 181 | 199 | } else { |
| 182 | − tm = kmalloc(sizeof(*tm), GFP_ATOMIC); | |
| 200 | + tm = kzalloc(sizeof(*tm), GFP_ATOMIC); | |
| 183 | 201 | if (!tm) |
| 184 | 202 | goto out_unlock; |
| 185 | 203 | } |
| 186 | − write_pnet(&tm->tcpm_net, net); | |
| 204 | + /* Paired with the READ_ONCE() in tm_net() */ | |
| 205 | + WRITE_ONCE(tm->tcpm_net, net); | |
| 206 | + | |
| 187 | 207 | tm->tcpm_saddr = *saddr; |
| 188 | 208 | tm->tcpm_daddr = *daddr; |
| 189 | 209 | |
| 190 | − tcpm_suck_dst(tm, dst, true); | |
| 210 | + tcpm_suck_dst(tm, dst, reclaim); | |
| 191 | 211 | |
| 192 | 212 | if (likely(!reclaim)) { |
| 193 | 213 | tm->tcpm_next = tcp_metrics_hash[hash].chain; |
| @@ -434,7 +454,7 @@ void tcp_update_metrics(struct sock *sk) · 240 unmodified lines | ||
| 434 | 454 | tp->reordering); |
| 435 | 455 | } |
| 436 | 456 | } |
| 437 | − tm->tcpm_stamp = jiffies; | |
| 457 | + WRITE_ONCE(tm->tcpm_stamp, jiffies); | |
| 438 | 458 | out_unlock: |
| 439 | 459 | rcu_read_unlock(); |
| 440 | 460 | } |
| @@ -539,8 +559,6 @@ bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst) · 98 unmodified lines | ||
| 539 | 559 | return ret; |
| 540 | 560 | } |
| 541 | 561 | |
| 542 | −static DEFINE_SEQLOCK(fastopen_seqlock); | |
| 543 | − | |
| 544 | 562 | void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, |
| 545 | 563 | struct tcp_fastopen_cookie *cookie) |
| 546 | 564 | { |
| @@ -647,7 +665,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg, · 100 unmodified lines | ||
| 647 | 665 | } |
| 648 | 666 | |
| 649 | 667 | if (nla_put_msecs(msg, TCP_METRICS_ATTR_AGE, |
| 650 | − jiffies - tm->tcpm_stamp, | |
| 668 | + jiffies - READ_ONCE(tm->tcpm_stamp), | |
| 651 | 669 | TCP_METRICS_ATTR_PAD) < 0) |
| 652 | 670 | goto nla_put_failure; |
| 653 | 671 | |
| @@ -658,7 +676,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg, · 4 unmodified lines | ||
| 658 | 676 | if (!nest) |
| 659 | 677 | goto nla_put_failure; |
| 660 | 678 | for (i = 0; i < TCP_METRIC_MAX_KERNEL + 1; i++) { |
| 661 | − u32 val = tm->tcpm_vals[i]; | |
| 679 | + u32 val = tcp_metric_get(tm, i); | |
| 662 | 680 | |
| 663 | 681 | if (!val) |
| 664 | 682 | continue; |
| @@ -114,6 +114,7 @@ · 113 unmodified lines | ||
| 114 | 114 | #include <net/sock_reuseport.h> |
| 115 | 115 | #include <net/addrconf.h> |
| 116 | 116 | #include <net/udp_tunnel.h> |
| 117 | +#include <net/gro.h> | |
| 117 | 118 | #if IS_ENABLED(CONFIG_IPV6) |
| 118 | 119 | #include <net/ipv6_stubs.h> |
| 119 | 120 | #endif |
| @@ -555,10 +556,13 @@ struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb, · 435 unmodified lines | ||
| 555 | 556 | { |
| 556 | 557 | const struct iphdr *iph = ip_hdr(skb); |
| 557 | 558 | struct net *net = dev_net(skb->dev); |
| 559 | + int iif, sdif; | |
| 560 | + | |
| 561 | + inet_get_iif_sdif(skb, &iif, &sdif); | |
| 558 | 562 | |
| 559 | 563 | return __udp4_lib_lookup(net, iph->saddr, sport, |
| 560 | − iph->daddr, dport, inet_iif(skb), | |
| 561 | − inet_sdif(skb), net->ipv4.udp_table, NULL); | |
| 564 | + iph->daddr, dport, iif, | |
| 565 | + sdif, net->ipv4.udp_table, NULL); | |
| 562 | 566 | } |
| 563 | 567 | |
| 564 | 568 | /* Must be called under rcu_read_lock(). |
| @@ -609,10 +609,13 @@ static struct sock *udp4_gro_lookup_skb(struct sk_buff *skb, __be16 sport, · 608 unmodified lines | ||
| 609 | 609 | { |
| 610 | 610 | const struct iphdr *iph = skb_gro_network_header(skb); |
| 611 | 611 | struct net *net = dev_net(skb->dev); |
| 612 | + int iif, sdif; | |
| 613 | + | |
| 614 | + inet_get_iif_sdif(skb, &iif, &sdif); | |
| 612 | 615 | |
| 613 | 616 | return __udp4_lib_lookup(net, iph->saddr, sport, |
| 614 | − iph->daddr, dport, inet_iif(skb), | |
| 615 | − inet_sdif(skb), net->ipv4.udp_table, NULL); | |
| 617 | + iph->daddr, dport, iif, | |
| 618 | + sdif, net->ipv4.udp_table, NULL); | |
| 616 | 619 | } |
| 617 | 620 | |
| 618 | 621 | INDIRECT_CALLABLE_SCOPE |
| @@ -1073,7 +1073,7 @@ static int ip6mr_cache_report(const struct mr_table *mrt, struct sk_buff *pkt, · 1072 unmodified lines | ||
| 1073 | 1073 | And all this only to mangle msg->im6_msgtype and |
| 1074 | 1074 | to set msg->im6_mbz to "mbz" :-) |
| 1075 | 1075 | */ |
| 1076 | − skb_push(skb, -skb_network_offset(pkt)); | |
| 1076 | + __skb_pull(skb, skb_network_offset(pkt)); | |
| 1077 | 1077 | |
| 1078 | 1078 | skb_push(skb, sizeof(*msg)); |
| 1079 | 1079 | skb_reset_transport_header(skb); |
| @@ -197,7 +197,8 @@ static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur, · 196 unmodified lines | ||
| 197 | 197 | static inline int ndisc_is_useropt(const struct net_device *dev, |
| 198 | 198 | struct nd_opt_hdr *opt) |
| 199 | 199 | { |
| 200 | − return opt->nd_opt_type == ND_OPT_RDNSS || | |
| 200 | + return opt->nd_opt_type == ND_OPT_PREFIX_INFO || | |
| 201 | + opt->nd_opt_type == ND_OPT_RDNSS || | |
| 201 | 202 | opt->nd_opt_type == ND_OPT_DNSSL || |
| 202 | 203 | opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL || |
| 203 | 204 | opt->nd_opt_type == ND_OPT_PREF64 || |
| @@ -120,7 +120,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 119 unmodified lines | ||
| 120 | 120 | |
| 121 | 121 | ipcm6_init_sk(&ipc6, np); |
| 122 | 122 | ipc6.sockc.tsflags = sk->sk_tsflags; |
| 123 | − ipc6.sockc.mark = sk->sk_mark; | |
| 123 | + ipc6.sockc.mark = READ_ONCE(sk->sk_mark); | |
| 124 | 124 | |
| 125 | 125 | fl6.flowi6_oif = oif; |
| 126 | 126 | |
| @@ -614,7 +614,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length, · 613 unmodified lines | ||
| 614 | 614 | skb_reserve(skb, hlen); |
| 615 | 615 | |
| 616 | 616 | skb->protocol = htons(ETH_P_IPV6); |
| 617 | − skb->priority = sk->sk_priority; | |
| 617 | + skb->priority = READ_ONCE(sk->sk_priority); | |
| 618 | 618 | skb->mark = sockc->mark; |
| 619 | 619 | skb->tstamp = sockc->transmit_time; |
| 620 | 620 | |
| @@ -774,12 +774,12 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 153 unmodified lines | ||
| 774 | 774 | */ |
| 775 | 775 | memset(&fl6, 0, sizeof(fl6)); |
| 776 | 776 | |
| 777 | − fl6.flowi6_mark = sk->sk_mark; | |
| 777 | + fl6.flowi6_mark = READ_ONCE(sk->sk_mark); | |
| 778 | 778 | fl6.flowi6_uid = sk->sk_uid; |
| 779 | 779 | |
| 780 | 780 | ipcm6_init(&ipc6); |
| 781 | 781 | ipc6.sockc.tsflags = sk->sk_tsflags; |
| 782 | − ipc6.sockc.mark = sk->sk_mark; | |
| 782 | + ipc6.sockc.mark = fl6.flowi6_mark; | |
| 783 | 783 | |
| 784 | 784 | if (sin6) { |
| 785 | 785 | if (addr_len < SIN6_LEN_RFC2133) |
| @@ -2951,7 +2951,8 @@ void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) · 2950 unmodified lines | ||
| 2951 | 2951 | if (!oif && skb->dev) |
| 2952 | 2952 | oif = l3mdev_master_ifindex(skb->dev); |
| 2953 | 2953 | |
| 2954 | − ip6_update_pmtu(skb, sock_net(sk), mtu, oif, sk->sk_mark, sk->sk_uid); | |
| 2954 | + ip6_update_pmtu(skb, sock_net(sk), mtu, oif, READ_ONCE(sk->sk_mark), | |
| 2955 | + sk->sk_uid); | |
| 2955 | 2956 | |
| 2956 | 2957 | dst = __sk_dst_get(sk); |
| 2957 | 2958 | if (!dst || !dst->obsolete || |
| @@ -3172,8 +3173,8 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif) · 214 unmodified lines | ||
| 3172 | 3173 | |
| 3173 | 3174 | void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) |
| 3174 | 3175 | { |
| 3175 | − ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark, | |
| 3176 | − sk->sk_uid); | |
| 3176 | + ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, | |
| 3177 | + READ_ONCE(sk->sk_mark), sk->sk_uid); | |
| 3177 | 3178 | } |
| 3178 | 3179 | EXPORT_SYMBOL_GPL(ip6_sk_redirect); |
| 3179 | 3180 | |
| @@ -564,8 +564,8 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst, · 563 unmodified lines | ||
| 564 | 564 | opt = ireq->ipv6_opt; |
| 565 | 565 | if (!opt) |
| 566 | 566 | opt = rcu_dereference(np->opt); |
| 567 | − err = ip6_xmit(sk, skb, fl6, skb->mark ? : sk->sk_mark, opt, | |
| 568 | − tclass, sk->sk_priority); | |
| 567 | + err = ip6_xmit(sk, skb, fl6, skb->mark ? : READ_ONCE(sk->sk_mark), | |
| 568 | + opt, tclass, sk->sk_priority); | |
| 569 | 569 | rcu_read_unlock(); |
| 570 | 570 | err = net_xmit_eval(err); |
| 571 | 571 | } |
| @@ -939,7 +939,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 · 367 unmodified lines | ||
| 939 | 939 | if (sk->sk_state == TCP_TIME_WAIT) |
| 940 | 940 | mark = inet_twsk(sk)->tw_mark; |
| 941 | 941 | else |
| 942 | − mark = sk->sk_mark; | |
| 942 | + mark = READ_ONCE(sk->sk_mark); | |
| 943 | 943 | skb_set_delivery_time(buff, tcp_transmit_time(sk), true); |
| 944 | 944 | } |
| 945 | 945 | if (txhash) { |
| @@ -1128,7 +1128,8 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, · 182 unmodified lines | ||
| 1128 | 1128 | tcp_time_stamp_raw() + tcp_rsk(req)->ts_off, |
| 1129 | 1129 | READ_ONCE(req->ts_recent), sk->sk_bound_dev_if, |
| 1130 | 1130 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, l3index), |
| 1131 | − ipv6_get_dsfield(ipv6_hdr(skb)), 0, sk->sk_priority, | |
| 1131 | + ipv6_get_dsfield(ipv6_hdr(skb)), 0, | |
| 1132 | + READ_ONCE(sk->sk_priority), | |
| 1132 | 1133 | READ_ONCE(tcp_rsk(req)->txhash)); |
| 1133 | 1134 | } |
| 1134 | 1135 | |
| @@ -51,6 +51,7 @@ · 50 unmodified lines | ||
| 51 | 51 | #include <net/inet6_hashtables.h> |
| 52 | 52 | #include <net/busy_poll.h> |
| 53 | 53 | #include <net/sock_reuseport.h> |
| 54 | +#include <net/gro.h> | |
| 54 | 55 | |
| 55 | 56 | #include <linux/proc_fs.h> |
| 56 | 57 | #include <linux/seq_file.h> |
| @@ -300,10 +301,13 @@ struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb, · 243 unmodified lines | ||
| 300 | 301 | { |
| 301 | 302 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
| 302 | 303 | struct net *net = dev_net(skb->dev); |
| 304 | + int iif, sdif; | |
| 305 | + | |
| 306 | + inet6_get_iif_sdif(skb, &iif, &sdif); | |
| 303 | 307 | |
| 304 | 308 | return __udp6_lib_lookup(net, &iph->saddr, sport, |
| 305 | − &iph->daddr, dport, inet6_iif(skb), | |
| 306 | − inet6_sdif(skb), net->ipv4.udp_table, NULL); | |
| 309 | + &iph->daddr, dport, iif, | |
| 310 | + sdif, net->ipv4.udp_table, NULL); | |
| 307 | 311 | } |
| 308 | 312 | |
| 309 | 313 | /* Must be called under rcu_read_lock(). |
| @@ -624,7 +628,7 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, · 314 unmodified lines | ||
| 624 | 628 | if (type == NDISC_REDIRECT) { |
| 625 | 629 | if (tunnel) { |
| 626 | 630 | ip6_redirect(skb, sock_net(sk), inet6_iif(skb), |
| 627 | − sk->sk_mark, sk->sk_uid); | |
| 631 | + READ_ONCE(sk->sk_mark), sk->sk_uid); | |
| 628 | 632 | } else { |
| 629 | 633 | ip6_sk_redirect(skb, sk); |
| 630 | 634 | } |
| @@ -1356,7 +1360,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 725 unmodified lines | ||
| 1356 | 1360 | ipcm6_init(&ipc6); |
| 1357 | 1361 | ipc6.gso_size = READ_ONCE(up->gso_size); |
| 1358 | 1362 | ipc6.sockc.tsflags = sk->sk_tsflags; |
| 1359 | − ipc6.sockc.mark = sk->sk_mark; | |
| 1363 | + ipc6.sockc.mark = READ_ONCE(sk->sk_mark); | |
| 1360 | 1364 | |
| 1361 | 1365 | /* destination address check */ |
| 1362 | 1366 | if (sin6) { |
| @@ -118,10 +118,13 @@ static struct sock *udp6_gro_lookup_skb(struct sk_buff *skb, __be16 sport, · 117 unmodified lines | ||
| 118 | 118 | { |
| 119 | 119 | const struct ipv6hdr *iph = skb_gro_network_header(skb); |
| 120 | 120 | struct net *net = dev_net(skb->dev); |
| 121 | + int iif, sdif; | |
| 122 | + | |
| 123 | + inet6_get_iif_sdif(skb, &iif, &sdif); | |
| 121 | 124 | |
| 122 | 125 | return __udp6_lib_lookup(net, &iph->saddr, sport, |
| 123 | − &iph->daddr, dport, inet6_iif(skb), | |
| 124 | − inet6_sdif(skb), net->ipv4.udp_table, NULL); | |
| 126 | + &iph->daddr, dport, iif, | |
| 127 | + sdif, net->ipv4.udp_table, NULL); | |
| 125 | 128 | } |
| 126 | 129 | |
| 127 | 130 | INDIRECT_CALLABLE_SCOPE |
| @@ -519,7 +519,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 518 unmodified lines | ||
| 519 | 519 | /* Get and verify the address */ |
| 520 | 520 | memset(&fl6, 0, sizeof(fl6)); |
| 521 | 521 | |
| 522 | − fl6.flowi6_mark = sk->sk_mark; | |
| 522 | + fl6.flowi6_mark = READ_ONCE(sk->sk_mark); | |
| 523 | 523 | fl6.flowi6_uid = sk->sk_uid; |
| 524 | 524 | |
| 525 | 525 | ipcm6_init(&ipc6); |
| @@ -2335,7 +2335,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, · 2334 unmodified lines | ||
| 2335 | 2335 | |
| 2336 | 2336 | lock_sock_nested(ssk, SINGLE_DEPTH_NESTING); |
| 2337 | 2337 | |
| 2338 | − if (flags & MPTCP_CF_FASTCLOSE) { | |
| 2338 | + if ((flags & MPTCP_CF_FASTCLOSE) && !__mptcp_check_fallback(msk)) { | |
| 2339 | 2339 | /* be sure to force the tcp_disconnect() path, |
| 2340 | 2340 | * to generate the egress reset |
| 2341 | 2341 | */ |
| @@ -3328,7 +3328,7 @@ static void mptcp_release_cb(struct sock *sk) · 986 unmodified lines | ||
| 3328 | 3328 | |
| 3329 | 3329 | if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags)) |
| 3330 | 3330 | __mptcp_clean_una_wakeup(sk); |
| 3331 | − if (unlikely(&msk->cb_flags)) { | |
| 3331 | + if (unlikely(msk->cb_flags)) { | |
| 3332 | 3332 | /* be sure to set the current sk state before tacking actions |
| 3333 | 3333 | * depending on sk_state, that is processing MPTCP_ERROR_REPORT |
| 3334 | 3334 | */ |
| @@ -325,7 +325,6 @@ struct mptcp_sock { · 324 unmodified lines | ||
| 325 | 325 | u32 subflow_id; |
| 326 | 326 | u32 setsockopt_seq; |
| 327 | 327 | char ca_name[TCP_CA_NAME_MAX]; |
| 328 | − struct mptcp_sock *dl_next; | |
| 329 | 328 | }; |
| 330 | 329 | |
| 331 | 330 | #define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock) |
| @@ -103,7 +103,7 @@ static void mptcp_sol_socket_sync_intval(struct mptcp_sock *msk, int optname, in · 102 unmodified lines | ||
| 103 | 103 | break; |
| 104 | 104 | case SO_MARK: |
| 105 | 105 | if (READ_ONCE(ssk->sk_mark) != sk->sk_mark) { |
| 106 | − ssk->sk_mark = sk->sk_mark; | |
| 106 | + WRITE_ONCE(ssk->sk_mark, sk->sk_mark); | |
| 107 | 107 | sk_dst_reset(ssk); |
| 108 | 108 | } |
| 109 | 109 | break; |
| @@ -1793,16 +1793,31 @@ static void subflow_state_change(struct sock *sk) · 1792 unmodified lines | ||
| 1793 | 1793 | void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk) |
| 1794 | 1794 | { |
| 1795 | 1795 | struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue; |
| 1796 | − struct mptcp_sock *msk, *next, *head = NULL; | |
| 1797 | − struct request_sock *req; | |
| 1798 | − struct sock *sk; | |
| 1796 | + struct request_sock *req, *head, *tail; | |
| 1797 | + struct mptcp_subflow_context *subflow; | |
| 1798 | + struct sock *sk, *ssk; | |
| 1799 | 1799 | |
| 1800 | − /* build a list of all unaccepted mptcp sockets */ | |
| 1800 | + /* Due to lock dependencies no relevant lock can be acquired under rskq_lock. | |
| 1801 | + * Splice the req list, so that accept() can not reach the pending ssk after | |
| 1802 | + * the listener socket is released below. | |
| 1803 | + */ | |
| 1801 | 1804 | spin_lock_bh(&queue->rskq_lock); |
| 1802 | − for (req = queue->rskq_accept_head; req; req = req->dl_next) { | |
| 1803 | − struct mptcp_subflow_context *subflow; | |
| 1804 | − struct sock *ssk = req->sk; | |
| 1805 | + head = queue->rskq_accept_head; | |
| 1806 | + tail = queue->rskq_accept_tail; | |
| 1807 | + queue->rskq_accept_head = NULL; | |
| 1808 | + queue->rskq_accept_tail = NULL; | |
| 1809 | + spin_unlock_bh(&queue->rskq_lock); | |
| 1810 | + | |
| 1811 | + if (!head) | |
| 1812 | + return; | |
| 1805 | 1813 | |
| 1814 | + /* can't acquire the msk socket lock under the subflow one, | |
| 1815 | + * or will cause ABBA deadlock | |
| 1816 | + */ | |
| 1817 | + release_sock(listener_ssk); | |
| 1818 | + | |
| 1819 | + for (req = head; req; req = req->dl_next) { | |
| 1820 | + ssk = req->sk; | |
| 1806 | 1821 | if (!sk_is_mptcp(ssk)) |
| 1807 | 1822 | continue; |
| 1808 | 1823 | |
| @@ -1810,32 +1825,10 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s · 1 unmodified line | ||
| 1810 | 1825 | if (!subflow || !subflow->conn) |
| 1811 | 1826 | continue; |
| 1812 | 1827 | |
| 1813 | − /* skip if already in list */ | |
| 1814 | 1828 | sk = subflow->conn; |
| 1815 | − msk = mptcp_sk(sk); | |
| 1816 | − if (msk->dl_next || msk == head) | |
| 1817 | − continue; | |
| 1818 | − | |
| 1819 | 1829 | sock_hold(sk); |
| 1820 | − msk->dl_next = head; | |
| 1821 | − head = msk; | |
| 1822 | − } | |
| 1823 | − spin_unlock_bh(&queue->rskq_lock); | |
| 1824 | − if (!head) | |
| 1825 | − return; | |
| 1826 | − | |
| 1827 | − /* can't acquire the msk socket lock under the subflow one, | |
| 1828 | − * or will cause ABBA deadlock | |
| 1829 | − */ | |
| 1830 | − release_sock(listener_ssk); | |
| 1831 | − | |
| 1832 | − for (msk = head; msk; msk = next) { | |
| 1833 | − sk = (struct sock *)msk; | |
| 1834 | 1830 | |
| 1835 | 1831 | lock_sock_nested(sk, SINGLE_DEPTH_NESTING); |
| 1836 | − next = msk->dl_next; | |
| 1837 | − msk->dl_next = NULL; | |
| 1838 | − | |
| 1839 | 1832 | __mptcp_unaccepted_force_close(sk); |
| 1840 | 1833 | release_sock(sk); |
| 1841 | 1834 | |
| @@ -1859,6 +1852,13 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s · 17 unmodified lines | ||
| 1859 | 1852 | |
| 1860 | 1853 | /* we are still under the listener msk socket lock */ |
| 1861 | 1854 | lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING); |
| 1855 | + | |
| 1856 | + /* restore the listener queue, to let the TCP code clean it up */ | |
| 1857 | + spin_lock_bh(&queue->rskq_lock); | |
| 1858 | + WARN_ON_ONCE(queue->rskq_accept_head); | |
| 1859 | + queue->rskq_accept_head = head; | |
| 1860 | + queue->rskq_accept_tail = tail; | |
| 1861 | + spin_unlock_bh(&queue->rskq_lock); | |
| 1862 | 1862 | } |
| 1863 | 1863 | |
| 1864 | 1864 | static int subflow_ulp_init(struct sock *sk) |
| @@ -31,7 +31,9 @@ static LIST_HEAD(nf_tables_expressions); · 30 unmodified lines | ||
| 31 | 31 | static LIST_HEAD(nf_tables_objects); |
| 32 | 32 | static LIST_HEAD(nf_tables_flowtables); |
| 33 | 33 | static LIST_HEAD(nf_tables_destroy_list); |
| 34 | +static LIST_HEAD(nf_tables_gc_list); | |
| 34 | 35 | static DEFINE_SPINLOCK(nf_tables_destroy_list_lock); |
| 36 | +static DEFINE_SPINLOCK(nf_tables_gc_list_lock); | |
| 35 | 37 | |
| 36 | 38 | enum { |
| 37 | 39 | NFT_VALIDATE_SKIP = 0, |
| @@ -120,6 +122,9 @@ static void nft_validate_state_update(struct nft_table *table, u8 new_validate_s · 82 unmodified lines | ||
| 120 | 122 | static void nf_tables_trans_destroy_work(struct work_struct *w); |
| 121 | 123 | static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work); |
| 122 | 124 | |
| 125 | +static void nft_trans_gc_work(struct work_struct *work); | |
| 126 | +static DECLARE_WORK(trans_gc_work, nft_trans_gc_work); | |
| 127 | + | |
| 123 | 128 | static void nft_ctx_init(struct nft_ctx *ctx, |
| 124 | 129 | struct net *net, |
| 125 | 130 | const struct sk_buff *skb, |
| @@ -582,10 +587,6 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type, · 456 unmodified lines | ||
| 582 | 587 | return __nft_trans_set_add(ctx, msg_type, set, NULL); |
| 583 | 588 | } |
| 584 | 589 | |
| 585 | −static void nft_setelem_data_deactivate(const struct net *net, | |
| 586 | − const struct nft_set *set, | |
| 587 | − struct nft_set_elem *elem); | |
| 588 | − | |
| 589 | 590 | static int nft_mapelem_deactivate(const struct nft_ctx *ctx, |
| 590 | 591 | struct nft_set *set, |
| 591 | 592 | const struct nft_set_iter *iter, |
| @@ -5055,6 +5056,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, · 4463 unmodified lines | ||
| 5055 | 5056 | |
| 5056 | 5057 | INIT_LIST_HEAD(&set->bindings); |
| 5057 | 5058 | INIT_LIST_HEAD(&set->catchall_list); |
| 5059 | + refcount_set(&set->refs, 1); | |
| 5058 | 5060 | set->table = table; |
| 5059 | 5061 | write_pnet(&set->net, net); |
| 5060 | 5062 | set->ops = ops; |
| @@ -5122,6 +5124,14 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx, · 61 unmodified lines | ||
| 5122 | 5124 | } |
| 5123 | 5125 | } |
| 5124 | 5126 | |
| 5127 | +static void nft_set_put(struct nft_set *set) | |
| 5128 | +{ | |
| 5129 | + if (refcount_dec_and_test(&set->refs)) { | |
| 5130 | + kfree(set->name); | |
| 5131 | + kvfree(set); | |
| 5132 | + } | |
| 5133 | +} | |
| 5134 | + | |
| 5125 | 5135 | static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) |
| 5126 | 5136 | { |
| 5127 | 5137 | int i; |
| @@ -5134,8 +5144,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) · 6 unmodified lines | ||
| 5134 | 5144 | |
| 5135 | 5145 | set->ops->destroy(ctx, set); |
| 5136 | 5146 | nft_set_catchall_destroy(ctx, set); |
| 5137 | − kfree(set->name); | |
| 5138 | − kvfree(set); | |
| 5147 | + nft_set_put(set); | |
| 5139 | 5148 | } |
| 5140 | 5149 | |
| 5141 | 5150 | static int nf_tables_delset(struct sk_buff *skb, const struct nfnl_info *info, |
| @@ -5602,8 +5611,12 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx, · 460 unmodified lines | ||
| 5602 | 5611 | const struct nft_set_iter *iter, |
| 5603 | 5612 | struct nft_set_elem *elem) |
| 5604 | 5613 | { |
| 5614 | + const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); | |
| 5605 | 5615 | struct nft_set_dump_args *args; |
| 5606 | 5616 | |
| 5617 | + if (nft_set_elem_expired(ext)) | |
| 5618 | + return 0; | |
| 5619 | + | |
| 5607 | 5620 | args = container_of(iter, struct nft_set_dump_args, iter); |
| 5608 | 5621 | return nf_tables_fill_setelem(args->skb, set, elem, args->reset); |
| 5609 | 5622 | } |
| @@ -6274,7 +6287,8 @@ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net, · 664 unmodified lines | ||
| 6274 | 6287 | list_for_each_entry_rcu(catchall, &set->catchall_list, list) { |
| 6275 | 6288 | ext = nft_set_elem_ext(set, catchall->elem); |
| 6276 | 6289 | if (nft_set_elem_active(ext, genmask) && |
| 6277 | − !nft_set_elem_expired(ext)) | |
| 6290 | + !nft_set_elem_expired(ext) && | |
| 6291 | + !nft_set_elem_is_dead(ext)) | |
| 6278 | 6292 | return ext; |
| 6279 | 6293 | } |
| 6280 | 6294 | |
| @@ -6282,29 +6296,6 @@ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net, · 1 unmodified line | ||
| 6282 | 6296 | } |
| 6283 | 6297 | EXPORT_SYMBOL_GPL(nft_set_catchall_lookup); |
| 6284 | 6298 | |
| 6285 | −void *nft_set_catchall_gc(const struct nft_set *set) | |
| 6286 | −{ | |
| 6287 | − struct nft_set_elem_catchall *catchall, *next; | |
| 6288 | − struct nft_set_ext *ext; | |
| 6289 | − void *elem = NULL; | |
| 6290 | − | |
| 6291 | − list_for_each_entry_safe(catchall, next, &set->catchall_list, list) { | |
| 6292 | − ext = nft_set_elem_ext(set, catchall->elem); | |
| 6293 | − | |
| 6294 | − if (!nft_set_elem_expired(ext) || | |
| 6295 | − nft_set_elem_mark_busy(ext)) | |
| 6296 | − continue; | |
| 6297 | − | |
| 6298 | − elem = catchall->elem; | |
| 6299 | − list_del_rcu(&catchall->list); | |
| 6300 | − kfree_rcu(catchall, rcu); | |
| 6301 | − break; | |
| 6302 | − } | |
| 6303 | − | |
| 6304 | − return elem; | |
| 6305 | −} | |
| 6306 | −EXPORT_SYMBOL_GPL(nft_set_catchall_gc); | |
| 6307 | − | |
| 6308 | 6299 | static int nft_setelem_catchall_insert(const struct net *net, |
| 6309 | 6300 | struct nft_set *set, |
| 6310 | 6301 | const struct nft_set_elem *elem, |
| @@ -6366,7 +6357,6 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set, · 55 unmodified lines | ||
| 6366 | 6357 | |
| 6367 | 6358 | if (nft_setelem_is_catchall(set, elem)) { |
| 6368 | 6359 | nft_set_elem_change_active(net, set, ext); |
| 6369 | − nft_set_elem_clear_busy(ext); | |
| 6370 | 6360 | } else { |
| 6371 | 6361 | set->ops->activate(net, set, elem); |
| 6372 | 6362 | } |
| @@ -6381,8 +6371,7 @@ static int nft_setelem_catchall_deactivate(const struct net *net, · 8 unmodified lines | ||
| 6381 | 6371 | |
| 6382 | 6372 | list_for_each_entry(catchall, &set->catchall_list, list) { |
| 6383 | 6373 | ext = nft_set_elem_ext(set, catchall->elem); |
| 6384 | − if (!nft_is_active(net, ext) || | |
| 6385 | − nft_set_elem_mark_busy(ext)) | |
| 6374 | + if (!nft_is_active(net, ext)) | |
| 6386 | 6375 | continue; |
| 6387 | 6376 | |
| 6388 | 6377 | kfree(elem->priv); |
| @@ -6777,7 +6766,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 388 unmodified lines | ||
| 6777 | 6766 | goto err_elem_free; |
| 6778 | 6767 | } |
| 6779 | 6768 | |
| 6780 | − ext->genmask = nft_genmask_cur(ctx->net) | NFT_SET_ELEM_BUSY_MASK; | |
| 6769 | + ext->genmask = nft_genmask_cur(ctx->net); | |
| 6781 | 6770 | |
| 6782 | 6771 | err = nft_setelem_insert(ctx->net, set, &elem, &ext2, flags); |
| 6783 | 6772 | if (err) { |
| @@ -6929,9 +6918,9 @@ static void nft_setelem_data_activate(const struct net *net, · 145 unmodified lines | ||
| 6929 | 6918 | nft_use_inc_restore(&(*nft_set_ext_obj(ext))->use); |
| 6930 | 6919 | } |
| 6931 | 6920 | |
| 6932 | −static void nft_setelem_data_deactivate(const struct net *net, | |
| 6933 | − const struct nft_set *set, | |
| 6934 | − struct nft_set_elem *elem) | |
| 6921 | +void nft_setelem_data_deactivate(const struct net *net, | |
| 6922 | + const struct nft_set *set, | |
| 6923 | + struct nft_set_elem *elem) | |
| 6935 | 6924 | { |
| 6936 | 6925 | const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); |
| 6937 | 6926 | |
| @@ -7095,8 +7084,7 @@ static int nft_set_catchall_flush(const struct nft_ctx *ctx, · 157 unmodified lines | ||
| 7095 | 7084 | |
| 7096 | 7085 | list_for_each_entry_rcu(catchall, &set->catchall_list, list) { |
| 7097 | 7086 | ext = nft_set_elem_ext(set, catchall->elem); |
| 7098 | − if (!nft_set_elem_active(ext, genmask) || | |
| 7099 | − nft_set_elem_mark_busy(ext)) | |
| 7087 | + if (!nft_set_elem_active(ext, genmask)) | |
| 7100 | 7088 | continue; |
| 7101 | 7089 | |
| 7102 | 7090 | elem.priv = catchall->elem; |
| @@ -7170,29 +7158,6 @@ static int nf_tables_delsetelem(struct sk_buff *skb, · 67 unmodified lines | ||
| 7170 | 7158 | return err; |
| 7171 | 7159 | } |
| 7172 | 7160 | |
| 7173 | −void nft_set_gc_batch_release(struct rcu_head *rcu) | |
| 7174 | −{ | |
| 7175 | − struct nft_set_gc_batch *gcb; | |
| 7176 | − unsigned int i; | |
| 7177 | − | |
| 7178 | − gcb = container_of(rcu, struct nft_set_gc_batch, head.rcu); | |
| 7179 | − for (i = 0; i < gcb->head.cnt; i++) | |
| 7180 | − nft_set_elem_destroy(gcb->head.set, gcb->elems[i], true); | |
| 7181 | − kfree(gcb); | |
| 7182 | −} | |
| 7183 | − | |
| 7184 | −struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set, | |
| 7185 | − gfp_t gfp) | |
| 7186 | −{ | |
| 7187 | − struct nft_set_gc_batch *gcb; | |
| 7188 | − | |
| 7189 | − gcb = kzalloc(sizeof(*gcb), gfp); | |
| 7190 | − if (gcb == NULL) | |
| 7191 | − return gcb; | |
| 7192 | − gcb->head.set = set; | |
| 7193 | − return gcb; | |
| 7194 | −} | |
| 7195 | − | |
| 7196 | 7161 | /* |
| 7197 | 7162 | * Stateful objects |
| 7198 | 7163 | */ |
| @@ -9414,6 +9379,207 @@ void nft_chain_del(struct nft_chain *chain) · 2215 unmodified lines | ||
| 9414 | 9379 | list_del_rcu(&chain->list); |
| 9415 | 9380 | } |
| 9416 | 9381 | |
| 9382 | +static void nft_trans_gc_setelem_remove(struct nft_ctx *ctx, | |
| 9383 | + struct nft_trans_gc *trans) | |
| 9384 | +{ | |
| 9385 | + void **priv = trans->priv; | |
| 9386 | + unsigned int i; | |
| 9387 | + | |
| 9388 | + for (i = 0; i < trans->count; i++) { | |
| 9389 | + struct nft_set_elem elem = { | |
| 9390 | + .priv = priv[i], | |
| 9391 | + }; | |
| 9392 | + | |
| 9393 | + nft_setelem_data_deactivate(ctx->net, trans->set, &elem); | |
| 9394 | + nft_setelem_remove(ctx->net, trans->set, &elem); | |
| 9395 | + } | |
| 9396 | +} | |
| 9397 | + | |
| 9398 | +void nft_trans_gc_destroy(struct nft_trans_gc *trans) | |
| 9399 | +{ | |
| 9400 | + nft_set_put(trans->set); | |
| 9401 | + put_net(trans->net); | |
| 9402 | + kfree(trans); | |
| 9403 | +} | |
| 9404 | + | |
| 9405 | +static void nft_trans_gc_trans_free(struct rcu_head *rcu) | |
| 9406 | +{ | |
| 9407 | + struct nft_set_elem elem = {}; | |
| 9408 | + struct nft_trans_gc *trans; | |
| 9409 | + struct nft_ctx ctx = {}; | |
| 9410 | + unsigned int i; | |
| 9411 | + | |
| 9412 | + trans = container_of(rcu, struct nft_trans_gc, rcu); | |
| 9413 | + ctx.net = read_pnet(&trans->set->net); | |
| 9414 | + | |
| 9415 | + for (i = 0; i < trans->count; i++) { | |
| 9416 | + elem.priv = trans->priv[i]; | |
| 9417 | + if (!nft_setelem_is_catchall(trans->set, &elem)) | |
| 9418 | + atomic_dec(&trans->set->nelems); | |
| 9419 | + | |
| 9420 | + nf_tables_set_elem_destroy(&ctx, trans->set, elem.priv); | |
| 9421 | + } | |
| 9422 | + | |
| 9423 | + nft_trans_gc_destroy(trans); | |
| 9424 | +} | |
| 9425 | + | |
| 9426 | +static bool nft_trans_gc_work_done(struct nft_trans_gc *trans) | |
| 9427 | +{ | |
| 9428 | + struct nftables_pernet *nft_net; | |
| 9429 | + struct nft_ctx ctx = {}; | |
| 9430 | + | |
| 9431 | + nft_net = nft_pernet(trans->net); | |
| 9432 | + | |
| 9433 | + mutex_lock(&nft_net->commit_mutex); | |
| 9434 | + | |
| 9435 | + /* Check for race with transaction, otherwise this batch refers to | |
| 9436 | + * stale objects that might not be there anymore. Skip transaction if | |
| 9437 | + * set has been destroyed from control plane transaction in case gc | |
| 9438 | + * worker loses race. | |
| 9439 | + */ | |
| 9440 | + if (READ_ONCE(nft_net->gc_seq) != trans->seq || trans->set->dead) { | |
| 9441 | + mutex_unlock(&nft_net->commit_mutex); | |
| 9442 | + return false; | |
| 9443 | + } | |
| 9444 | + | |
| 9445 | + ctx.net = trans->net; | |
| 9446 | + ctx.table = trans->set->table; | |
| 9447 | + | |
| 9448 | + nft_trans_gc_setelem_remove(&ctx, trans); | |
| 9449 | + mutex_unlock(&nft_net->commit_mutex); | |
| 9450 | + | |
| 9451 | + return true; | |
| 9452 | +} | |
| 9453 | + | |
| 9454 | +static void nft_trans_gc_work(struct work_struct *work) | |
| 9455 | +{ | |
| 9456 | + struct nft_trans_gc *trans, *next; | |
| 9457 | + LIST_HEAD(trans_gc_list); | |
| 9458 | + | |
| 9459 | + spin_lock(&nf_tables_destroy_list_lock); | |
| 9460 | + list_splice_init(&nf_tables_gc_list, &trans_gc_list); | |
| 9461 | + spin_unlock(&nf_tables_destroy_list_lock); | |
| 9462 | + | |
| 9463 | + list_for_each_entry_safe(trans, next, &trans_gc_list, list) { | |
| 9464 | + list_del(&trans->list); | |
| 9465 | + if (!nft_trans_gc_work_done(trans)) { | |
| 9466 | + nft_trans_gc_destroy(trans); | |
| 9467 | + continue; | |
| 9468 | + } | |
| 9469 | + call_rcu(&trans->rcu, nft_trans_gc_trans_free); | |
| 9470 | + } | |
| 9471 | +} | |
| 9472 | + | |
| 9473 | +struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set, | |
| 9474 | + unsigned int gc_seq, gfp_t gfp) | |
| 9475 | +{ | |
| 9476 | + struct net *net = read_pnet(&set->net); | |
| 9477 | + struct nft_trans_gc *trans; | |
| 9478 | + | |
| 9479 | + trans = kzalloc(sizeof(*trans), gfp); | |
| 9480 | + if (!trans) | |
| 9481 | + return NULL; | |
| 9482 | + | |
| 9483 | + refcount_inc(&set->refs); | |
| 9484 | + trans->set = set; | |
| 9485 | + trans->net = get_net(net); | |
| 9486 | + trans->seq = gc_seq; | |
| 9487 | + | |
| 9488 | + return trans; | |
| 9489 | +} | |
| 9490 | + | |
| 9491 | +void nft_trans_gc_elem_add(struct nft_trans_gc *trans, void *priv) | |
| 9492 | +{ | |
| 9493 | + trans->priv[trans->count++] = priv; | |
| 9494 | +} | |
| 9495 | + | |
| 9496 | +static void nft_trans_gc_queue_work(struct nft_trans_gc *trans) | |
| 9497 | +{ | |
| 9498 | + spin_lock(&nf_tables_gc_list_lock); | |
| 9499 | + list_add_tail(&trans->list, &nf_tables_gc_list); | |
| 9500 | + spin_unlock(&nf_tables_gc_list_lock); | |
| 9501 | + | |
| 9502 | + schedule_work(&trans_gc_work); | |
| 9503 | +} | |
| 9504 | + | |
| 9505 | +static int nft_trans_gc_space(struct nft_trans_gc *trans) | |
| 9506 | +{ | |
| 9507 | + return NFT_TRANS_GC_BATCHCOUNT - trans->count; | |
| 9508 | +} | |
| 9509 | + | |
| 9510 | +struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc, | |
| 9511 | + unsigned int gc_seq, gfp_t gfp) | |
| 9512 | +{ | |
| 9513 | + if (nft_trans_gc_space(gc)) | |
| 9514 | + return gc; | |
| 9515 | + | |
| 9516 | + nft_trans_gc_queue_work(gc); | |
| 9517 | + | |
| 9518 | + return nft_trans_gc_alloc(gc->set, gc_seq, gfp); | |
| 9519 | +} | |
| 9520 | + | |
| 9521 | +void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans) | |
| 9522 | +{ | |
| 9523 | + if (trans->count == 0) { | |
| 9524 | + nft_trans_gc_destroy(trans); | |
| 9525 | + return; | |
| 9526 | + } | |
| 9527 | + | |
| 9528 | + nft_trans_gc_queue_work(trans); | |
| 9529 | +} | |
| 9530 | + | |
| 9531 | +struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp) | |
| 9532 | +{ | |
| 9533 | + if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net))) | |
| 9534 | + return NULL; | |
| 9535 | + | |
| 9536 | + if (nft_trans_gc_space(gc)) | |
| 9537 | + return gc; | |
| 9538 | + | |
| 9539 | + call_rcu(&gc->rcu, nft_trans_gc_trans_free); | |
| 9540 | + | |
| 9541 | + return nft_trans_gc_alloc(gc->set, 0, gfp); | |
| 9542 | +} | |
| 9543 | + | |
| 9544 | +void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans) | |
| 9545 | +{ | |
| 9546 | + WARN_ON_ONCE(!lockdep_commit_lock_is_held(trans->net)); | |
| 9547 | + | |
| 9548 | + if (trans->count == 0) { | |
| 9549 | + nft_trans_gc_destroy(trans); | |
| 9550 | + return; | |
| 9551 | + } | |
| 9552 | + | |
| 9553 | + call_rcu(&trans->rcu, nft_trans_gc_trans_free); | |
| 9554 | +} | |
| 9555 | + | |
| 9556 | +struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc, | |
| 9557 | + unsigned int gc_seq) | |
| 9558 | +{ | |
| 9559 | + struct nft_set_elem_catchall *catchall; | |
| 9560 | + const struct nft_set *set = gc->set; | |
| 9561 | + struct nft_set_ext *ext; | |
| 9562 | + | |
| 9563 | + list_for_each_entry_rcu(catchall, &set->catchall_list, list) { | |
| 9564 | + ext = nft_set_elem_ext(set, catchall->elem); | |
| 9565 | + | |
| 9566 | + if (!nft_set_elem_expired(ext)) | |
| 9567 | + continue; | |
| 9568 | + if (nft_set_elem_is_dead(ext)) | |
| 9569 | + goto dead_elem; | |
| 9570 | + | |
| 9571 | + nft_set_elem_dead(ext); | |
| 9572 | +dead_elem: | |
| 9573 | + gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); | |
| 9574 | + if (!gc) | |
| 9575 | + return NULL; | |
| 9576 | + | |
| 9577 | + nft_trans_gc_elem_add(gc, catchall->elem); | |
| 9578 | + } | |
| 9579 | + | |
| 9580 | + return gc; | |
| 9581 | +} | |
| 9582 | + | |
| 9417 | 9583 | static void nf_tables_module_autoload_cleanup(struct net *net) |
| 9418 | 9584 | { |
| 9419 | 9585 | struct nftables_pernet *nft_net = nft_pernet(net); |
| @@ -9576,11 +9742,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) · 156 unmodified lines | ||
| 9576 | 9742 | { |
| 9577 | 9743 | struct nftables_pernet *nft_net = nft_pernet(net); |
| 9578 | 9744 | struct nft_trans *trans, *next; |
| 9745 | + unsigned int base_seq, gc_seq; | |
| 9579 | 9746 | LIST_HEAD(set_update_list); |
| 9580 | 9747 | struct nft_trans_elem *te; |
| 9581 | 9748 | struct nft_chain *chain; |
| 9582 | 9749 | struct nft_table *table; |
| 9583 | − unsigned int base_seq; | |
| 9584 | 9750 | LIST_HEAD(adl); |
| 9585 | 9751 | int err; |
| 9586 | 9752 | |
| @@ -9657,6 +9823,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) · 70 unmodified lines | ||
| 9657 | 9823 | |
| 9658 | 9824 | WRITE_ONCE(nft_net->base_seq, base_seq); |
| 9659 | 9825 | |
| 9826 | + /* Bump gc counter, it becomes odd, this is the busy mark. */ | |
| 9827 | + gc_seq = READ_ONCE(nft_net->gc_seq); | |
| 9828 | + WRITE_ONCE(nft_net->gc_seq, ++gc_seq); | |
| 9829 | + | |
| 9660 | 9830 | /* step 3. Start new generation, rules_gen_X now in use. */ |
| 9661 | 9831 | net->nft.gencursor = nft_gencursor_next(net); |
| 9662 | 9832 | |
| @@ -9764,6 +9934,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) · 101 unmodified lines | ||
| 9764 | 9934 | break; |
| 9765 | 9935 | case NFT_MSG_DELSET: |
| 9766 | 9936 | case NFT_MSG_DESTROYSET: |
| 9937 | + nft_trans_set(trans)->dead = 1; | |
| 9767 | 9938 | list_del_rcu(&nft_trans_set(trans)->list); |
| 9768 | 9939 | nf_tables_set_notify(&trans->ctx, nft_trans_set(trans), |
| 9769 | 9940 | trans->msg_type, GFP_KERNEL); |
| @@ -9866,6 +10037,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) · 96 unmodified lines | ||
| 9866 | 10037 | nft_commit_notify(net, NETLINK_CB(skb).portid); |
| 9867 | 10038 | nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); |
| 9868 | 10039 | nf_tables_commit_audit_log(&adl, nft_net->base_seq); |
| 10040 | + | |
| 10041 | + WRITE_ONCE(nft_net->gc_seq, ++gc_seq); | |
| 9869 | 10042 | nf_tables_commit_release(net); |
| 9870 | 10043 | |
| 9871 | 10044 | return 0; |
| @@ -10915,6 +11088,7 @@ static int __net_init nf_tables_init_net(struct net *net) · 1043 unmodified lines | ||
| 10915 | 11088 | INIT_LIST_HEAD(&nft_net->notify_list); |
| 10916 | 11089 | mutex_init(&nft_net->commit_mutex); |
| 10917 | 11090 | nft_net->base_seq = 1; |
| 11091 | + nft_net->gc_seq = 0; | |
| 10918 | 11092 | |
| 10919 | 11093 | return 0; |
| 10920 | 11094 | } |
| @@ -10943,10 +11117,16 @@ static void __net_exit nf_tables_exit_net(struct net *net) · 22 unmodified lines | ||
| 10943 | 11117 | WARN_ON_ONCE(!list_empty(&nft_net->notify_list)); |
| 10944 | 11118 | } |
| 10945 | 11119 | |
| 11120 | +static void nf_tables_exit_batch(struct list_head *net_exit_list) | |
| 11121 | +{ | |
| 11122 | + flush_work(&trans_gc_work); | |
| 11123 | +} | |
| 11124 | + | |
| 10946 | 11125 | static struct pernet_operations nf_tables_net_ops = { |
| 10947 | 11126 | .init = nf_tables_init_net, |
| 10948 | 11127 | .pre_exit = nf_tables_pre_exit_net, |
| 10949 | 11128 | .exit = nf_tables_exit_net, |
| 11129 | + .exit_batch = nf_tables_exit_batch, | |
| 10950 | 11130 | .id = &nf_tables_net_id, |
| 10951 | 11131 | .size = sizeof(struct nftables_pernet), |
| 10952 | 11132 | }; |
| @@ -11018,6 +11198,7 @@ static void __exit nf_tables_module_exit(void) · 65 unmodified lines | ||
| 11018 | 11198 | nft_chain_filter_fini(); |
| 11019 | 11199 | nft_chain_route_fini(); |
| 11020 | 11200 | unregister_pernet_subsys(&nf_tables_net_ops); |
| 11201 | + cancel_work_sync(&trans_gc_work); | |
| 11021 | 11202 | cancel_work_sync(&trans_destroy_work); |
| 11022 | 11203 | rcu_barrier(); |
| 11023 | 11204 | rhltable_destroy(&nft_objname_ht); |
| @@ -59,6 +59,8 @@ static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg, · 58 unmodified lines | ||
| 59 | 59 | |
| 60 | 60 | if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) |
| 61 | 61 | return 1; |
| 62 | + if (nft_set_elem_is_dead(&he->ext)) | |
| 63 | + return 1; | |
| 62 | 64 | if (nft_set_elem_expired(&he->ext)) |
| 63 | 65 | return 1; |
| 64 | 66 | if (!nft_set_elem_active(&he->ext, x->genmask)) |
| @@ -188,7 +190,6 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set, · 123 unmodified lines | ||
| 188 | 190 | struct nft_rhash_elem *he = elem->priv; |
| 189 | 191 | |
| 190 | 192 | nft_set_elem_change_active(net, set, &he->ext); |
| 191 | − nft_set_elem_clear_busy(&he->ext); | |
| 192 | 193 | } |
| 193 | 194 | |
| 194 | 195 | static bool nft_rhash_flush(const struct net *net, |
| @@ -196,12 +197,9 @@ static bool nft_rhash_flush(const struct net *net, · 1 unmodified line | ||
| 196 | 197 | { |
| 197 | 198 | struct nft_rhash_elem *he = priv; |
| 198 | 199 | |
| 199 | − if (!nft_set_elem_mark_busy(&he->ext) || | |
| 200 | − !nft_is_active(net, &he->ext)) { | |
| 201 | − nft_set_elem_change_active(net, set, &he->ext); | |
| 202 | − return true; | |
| 203 | − } | |
| 204 | − return false; | |
| 200 | + nft_set_elem_change_active(net, set, &he->ext); | |
| 201 | + | |
| 202 | + return true; | |
| 205 | 203 | } |
| 206 | 204 | |
| 207 | 205 | static void *nft_rhash_deactivate(const struct net *net, |
| @@ -218,9 +216,8 @@ static void *nft_rhash_deactivate(const struct net *net, · 10 unmodified lines | ||
| 218 | 216 | |
| 219 | 217 | rcu_read_lock(); |
| 220 | 218 | he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params); |
| 221 | − if (he != NULL && | |
| 222 | − !nft_rhash_flush(net, set, he)) | |
| 223 | − he = NULL; | |
| 219 | + if (he) | |
| 220 | + nft_set_elem_change_active(net, set, &he->ext); | |
| 224 | 221 | |
| 225 | 222 | rcu_read_unlock(); |
| 226 | 223 | |
| @@ -252,7 +249,9 @@ static bool nft_rhash_delete(const struct nft_set *set, · 25 unmodified lines | ||
| 252 | 249 | if (he == NULL) |
| 253 | 250 | return false; |
| 254 | 251 | |
| 255 | − return rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params) == 0; | |
| 252 | + nft_set_elem_dead(&he->ext); | |
| 253 | + | |
| 254 | + return true; | |
| 256 | 255 | } |
| 257 | 256 | |
| 258 | 257 | static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, |
| @@ -278,8 +277,6 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, · 19 unmodified lines | ||
| 278 | 277 | |
| 279 | 278 | if (iter->count < iter->skip) |
| 280 | 279 | goto cont; |
| 281 | − if (nft_set_elem_expired(&he->ext)) | |
| 282 | − goto cont; | |
| 283 | 280 | if (!nft_set_elem_active(&he->ext, iter->genmask)) |
| 284 | 281 | goto cont; |
| 285 | 282 | |
| @@ -314,25 +311,48 @@ static bool nft_rhash_expr_needs_gc_run(const struct nft_set *set, · 28 unmodified lines | ||
| 314 | 311 | |
| 315 | 312 | static void nft_rhash_gc(struct work_struct *work) |
| 316 | 313 | { |
| 314 | + struct nftables_pernet *nft_net; | |
| 317 | 315 | struct nft_set *set; |
| 318 | 316 | struct nft_rhash_elem *he; |
| 319 | 317 | struct nft_rhash *priv; |
| 320 | − struct nft_set_gc_batch *gcb = NULL; | |
| 321 | 318 | struct rhashtable_iter hti; |
| 319 | + struct nft_trans_gc *gc; | |
| 320 | + struct net *net; | |
| 321 | + u32 gc_seq; | |
| 322 | 322 | |
| 323 | 323 | priv = container_of(work, struct nft_rhash, gc_work.work); |
| 324 | 324 | set = nft_set_container_of(priv); |
| 325 | + net = read_pnet(&set->net); | |
| 326 | + nft_net = nft_pernet(net); | |
| 327 | + gc_seq = READ_ONCE(nft_net->gc_seq); | |
| 328 | + | |
| 329 | + gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL); | |
| 330 | + if (!gc) | |
| 331 | + goto done; | |
| 325 | 332 | |
| 326 | 333 | rhashtable_walk_enter(&priv->ht, &hti); |
| 327 | 334 | rhashtable_walk_start(&hti); |
| 328 | 335 | |
| 329 | 336 | while ((he = rhashtable_walk_next(&hti))) { |
| 330 | 337 | if (IS_ERR(he)) { |
| 331 | − if (PTR_ERR(he) != -EAGAIN) | |
| 332 | − break; | |
| 338 | + if (PTR_ERR(he) != -EAGAIN) { | |
| 339 | + nft_trans_gc_destroy(gc); | |
| 340 | + gc = NULL; | |
| 341 | + goto try_later; | |
| 342 | + } | |
| 333 | 343 | continue; |
| 334 | 344 | } |
| 335 | 345 | |
| 346 | + /* Ruleset has been updated, try later. */ | |
| 347 | + if (READ_ONCE(nft_net->gc_seq) != gc_seq) { | |
| 348 | + nft_trans_gc_destroy(gc); | |
| 349 | + gc = NULL; | |
| 350 | + goto try_later; | |
| 351 | + } | |
| 352 | + | |
| 353 | + if (nft_set_elem_is_dead(&he->ext)) | |
| 354 | + goto dead_elem; | |
| 355 | + | |
| 336 | 356 | if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPRESSIONS) && |
| 337 | 357 | nft_rhash_expr_needs_gc_run(set, &he->ext)) |
| 338 | 358 | goto needs_gc_run; |
| @@ -340,26 +360,26 @@ static void nft_rhash_gc(struct work_struct *work) · 1 unmodified line | ||
| 340 | 360 | if (!nft_set_elem_expired(&he->ext)) |
| 341 | 361 | continue; |
| 342 | 362 | needs_gc_run: |
| 343 | − if (nft_set_elem_mark_busy(&he->ext)) | |
| 344 | − continue; | |
| 363 | + nft_set_elem_dead(&he->ext); | |
| 364 | +dead_elem: | |
| 365 | + gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); | |
| 366 | + if (!gc) | |
| 367 | + goto try_later; | |
| 345 | 368 | |
| 346 | − gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); | |
| 347 | − if (gcb == NULL) | |
| 348 | − break; | |
| 349 | − rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params); | |
| 350 | − atomic_dec(&set->nelems); | |
| 351 | − nft_set_gc_batch_add(gcb, he); | |
| 369 | + nft_trans_gc_elem_add(gc, he); | |
| 352 | 370 | } |
| 371 | + | |
| 372 | + gc = nft_trans_gc_catchall(gc, gc_seq); | |
| 373 | + | |
| 374 | +try_later: | |
| 375 | + /* catchall list iteration requires rcu read side lock. */ | |
| 353 | 376 | rhashtable_walk_stop(&hti); |
| 354 | 377 | rhashtable_walk_exit(&hti); |
| 355 | 378 | |
| 356 | − he = nft_set_catchall_gc(set); | |
| 357 | − if (he) { | |
| 358 | − gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); | |
| 359 | − if (gcb) | |
| 360 | − nft_set_gc_batch_add(gcb, he); | |
| 361 | − } | |
| 362 | − nft_set_gc_batch_complete(gcb); | |
| 379 | + if (gc) | |
| 380 | + nft_trans_gc_queue_async_done(gc); | |
| 381 | + | |
| 382 | +done: | |
| 363 | 383 | queue_delayed_work(system_power_efficient_wq, &priv->gc_work, |
| 364 | 384 | nft_set_gc_interval(set)); |
| 365 | 385 | } |
| @@ -394,7 +414,7 @@ static int nft_rhash_init(const struct nft_set *set, · 28 unmodified lines | ||
| 394 | 414 | return err; |
| 395 | 415 | |
| 396 | 416 | INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc); |
| 397 | − if (set->flags & NFT_SET_TIMEOUT) | |
| 417 | + if (set->flags & (NFT_SET_TIMEOUT | NFT_SET_EVAL)) | |
| 398 | 418 | nft_rhash_gc_init(set); |
| 399 | 419 | |
| 400 | 420 | return 0; |
| @@ -422,7 +442,6 @@ static void nft_rhash_destroy(const struct nft_ctx *ctx, · 21 unmodified lines | ||
| 422 | 442 | }; |
| 423 | 443 | |
| 424 | 444 | cancel_delayed_work_sync(&priv->gc_work); |
| 425 | − rcu_barrier(); | |
| 426 | 445 | rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy, |
| 427 | 446 | (void *)&rhash_ctx); |
| 428 | 447 | } |
| @@ -566,8 +566,7 @@ next_match: · 565 unmodified lines | ||
| 566 | 566 | goto out; |
| 567 | 567 | |
| 568 | 568 | if (last) { |
| 569 | − if (nft_set_elem_expired(&f->mt[b].e->ext) || | |
| 570 | − (genmask && | |
| 569 | + if ((genmask && | |
| 571 | 570 | !nft_set_elem_active(&f->mt[b].e->ext, genmask))) |
| 572 | 571 | goto next_match; |
| 573 | 572 | |
| @@ -601,8 +600,17 @@ out: · 27 unmodified lines | ||
| 601 | 600 | static void *nft_pipapo_get(const struct net *net, const struct nft_set *set, |
| 602 | 601 | const struct nft_set_elem *elem, unsigned int flags) |
| 603 | 602 | { |
| 604 | − return pipapo_get(net, set, (const u8 *)elem->key.val.data, | |
| 605 | − nft_genmask_cur(net)); | |
| 603 | + struct nft_pipapo_elem *ret; | |
| 604 | + | |
| 605 | + ret = pipapo_get(net, set, (const u8 *)elem->key.val.data, | |
| 606 | + nft_genmask_cur(net)); | |
| 607 | + if (IS_ERR(ret)) | |
| 608 | + return ret; | |
| 609 | + | |
| 610 | + if (nft_set_elem_expired(&ret->ext)) | |
| 611 | + return ERR_PTR(-ENOENT); | |
| 612 | + | |
| 613 | + return ret; | |
| 606 | 614 | } |
| 607 | 615 | |
| 608 | 616 | /** |
| @@ -1528,16 +1536,34 @@ static void pipapo_drop(struct nft_pipapo_match *m, · 919 unmodified lines | ||
| 1528 | 1536 | } |
| 1529 | 1537 | } |
| 1530 | 1538 | |
| 1539 | +static void nft_pipapo_gc_deactivate(struct net *net, struct nft_set *set, | |
| 1540 | + struct nft_pipapo_elem *e) | |
| 1541 | + | |
| 1542 | +{ | |
| 1543 | + struct nft_set_elem elem = { | |
| 1544 | + .priv = e, | |
| 1545 | + }; | |
| 1546 | + | |
| 1547 | + nft_setelem_data_deactivate(net, set, &elem); | |
| 1548 | +} | |
| 1549 | + | |
| 1531 | 1550 | /** |
| 1532 | 1551 | * pipapo_gc() - Drop expired entries from set, destroy start and end elements |
| 1533 | 1552 | * @set: nftables API set representation |
| 1534 | 1553 | * @m: Matching data |
| 1535 | 1554 | */ |
| 1536 | −static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m) | |
| 1555 | +static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m) | |
| 1537 | 1556 | { |
| 1557 | + struct nft_set *set = (struct nft_set *) _set; | |
| 1538 | 1558 | struct nft_pipapo *priv = nft_set_priv(set); |
| 1559 | + struct net *net = read_pnet(&set->net); | |
| 1539 | 1560 | int rules_f0, first_rule = 0; |
| 1540 | 1561 | struct nft_pipapo_elem *e; |
| 1562 | + struct nft_trans_gc *gc; | |
| 1563 | + | |
| 1564 | + gc = nft_trans_gc_alloc(set, 0, GFP_KERNEL); | |
| 1565 | + if (!gc) | |
| 1566 | + return; | |
| 1541 | 1567 | |
| 1542 | 1568 | while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) { |
| 1543 | 1569 | union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS]; |
| @@ -1561,13 +1587,20 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m) · 17 unmodified lines | ||
| 1561 | 1587 | f--; |
| 1562 | 1588 | i--; |
| 1563 | 1589 | e = f->mt[rulemap[i].to].e; |
| 1564 | − if (nft_set_elem_expired(&e->ext) && | |
| 1565 | − !nft_set_elem_mark_busy(&e->ext)) { | |
| 1590 | + | |
| 1591 | + /* synchronous gc never fails, there is no need to set on | |
| 1592 | + * NFT_SET_ELEM_DEAD_BIT. | |
| 1593 | + */ | |
| 1594 | + if (nft_set_elem_expired(&e->ext)) { | |
| 1566 | 1595 | priv->dirty = true; |
| 1567 | − pipapo_drop(m, rulemap); | |
| 1568 | 1596 | |
| 1569 | − rcu_barrier(); | |
| 1570 | − nft_set_elem_destroy(set, e, true); | |
| 1597 | + gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); | |
| 1598 | + if (!gc) | |
| 1599 | + break; | |
| 1600 | + | |
| 1601 | + nft_pipapo_gc_deactivate(net, set, e); | |
| 1602 | + pipapo_drop(m, rulemap); | |
| 1603 | + nft_trans_gc_elem_add(gc, e); | |
| 1571 | 1604 | |
| 1572 | 1605 | /* And check again current first rule, which is now the |
| 1573 | 1606 | * first we haven't checked. |
| @@ -1577,11 +1610,11 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m) · 3 unmodified lines | ||
| 1577 | 1610 | } |
| 1578 | 1611 | } |
| 1579 | 1612 | |
| 1580 | − e = nft_set_catchall_gc(set); | |
| 1581 | − if (e) | |
| 1582 | − nft_set_elem_destroy(set, e, true); | |
| 1583 | − | |
| 1584 | − priv->last_gc = jiffies; | |
| 1613 | + gc = nft_trans_gc_catchall(gc, 0); | |
| 1614 | + if (gc) { | |
| 1615 | + nft_trans_gc_queue_sync_done(gc); | |
| 1616 | + priv->last_gc = jiffies; | |
| 1617 | + } | |
| 1585 | 1618 | } |
| 1586 | 1619 | |
| 1587 | 1620 | /** |
| @@ -1706,7 +1739,6 @@ static void nft_pipapo_activate(const struct net *net, · 118 unmodified lines | ||
| 1706 | 1739 | return; |
| 1707 | 1740 | |
| 1708 | 1741 | nft_set_elem_change_active(net, set, &e->ext); |
| 1709 | − nft_set_elem_clear_busy(&e->ext); | |
| 1710 | 1742 | } |
| 1711 | 1743 | |
| 1712 | 1744 | /** |
| @@ -2005,8 +2037,6 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set, · 292 unmodified lines | ||
| 2005 | 2037 | goto cont; |
| 2006 | 2038 | |
| 2007 | 2039 | e = f->mt[r].e; |
| 2008 | − if (nft_set_elem_expired(&e->ext)) | |
| 2009 | − goto cont; | |
| 2010 | 2040 | |
| 2011 | 2041 | elem.priv = e; |
| 2012 | 2042 | |
| @@ -46,6 +46,12 @@ static int nft_rbtree_cmp(const struct nft_set *set, · 45 unmodified lines | ||
| 46 | 46 | set->klen); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | +static bool nft_rbtree_elem_expired(const struct nft_rbtree_elem *rbe) | |
| 50 | +{ | |
| 51 | + return nft_set_elem_expired(&rbe->ext) || | |
| 52 | + nft_set_elem_is_dead(&rbe->ext); | |
| 53 | +} | |
| 54 | + | |
| 49 | 55 | static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set, |
| 50 | 56 | const u32 *key, const struct nft_set_ext **ext, |
| 51 | 57 | unsigned int seq) |
| @@ -80,7 +86,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set · 28 unmodified lines | ||
| 80 | 86 | continue; |
| 81 | 87 | } |
| 82 | 88 | |
| 83 | − if (nft_set_elem_expired(&rbe->ext)) | |
| 89 | + if (nft_rbtree_elem_expired(rbe)) | |
| 84 | 90 | return false; |
| 85 | 91 | |
| 86 | 92 | if (nft_rbtree_interval_end(rbe)) { |
| @@ -98,7 +104,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set · 11 unmodified lines | ||
| 98 | 104 | |
| 99 | 105 | if (set->flags & NFT_SET_INTERVAL && interval != NULL && |
| 100 | 106 | nft_set_elem_active(&interval->ext, genmask) && |
| 101 | − !nft_set_elem_expired(&interval->ext) && | |
| 107 | + !nft_rbtree_elem_expired(interval) && | |
| 102 | 108 | nft_rbtree_interval_start(interval)) { |
| 103 | 109 | *ext = &interval->ext; |
| 104 | 110 | return true; |
| @@ -215,6 +221,18 @@ static void *nft_rbtree_get(const struct net *net, const struct nft_set *set, · 110 unmodified lines | ||
| 215 | 221 | return rbe; |
| 216 | 222 | } |
| 217 | 223 | |
| 224 | +static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set, | |
| 225 | + struct nft_rbtree *priv, | |
| 226 | + struct nft_rbtree_elem *rbe) | |
| 227 | +{ | |
| 228 | + struct nft_set_elem elem = { | |
| 229 | + .priv = rbe, | |
| 230 | + }; | |
| 231 | + | |
| 232 | + nft_setelem_data_deactivate(net, set, &elem); | |
| 233 | + rb_erase(&rbe->node, &priv->root); | |
| 234 | +} | |
| 235 | + | |
| 218 | 236 | static int nft_rbtree_gc_elem(const struct nft_set *__set, |
| 219 | 237 | struct nft_rbtree *priv, |
| 220 | 238 | struct nft_rbtree_elem *rbe, |
| @@ -222,11 +240,12 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 1 unmodified line | ||
| 222 | 240 | { |
| 223 | 241 | struct nft_set *set = (struct nft_set *)__set; |
| 224 | 242 | struct rb_node *prev = rb_prev(&rbe->node); |
| 243 | + struct net *net = read_pnet(&set->net); | |
| 225 | 244 | struct nft_rbtree_elem *rbe_prev; |
| 226 | − struct nft_set_gc_batch *gcb; | |
| 245 | + struct nft_trans_gc *gc; | |
| 227 | 246 | |
| 228 | − gcb = nft_set_gc_batch_check(set, NULL, GFP_ATOMIC); | |
| 229 | − if (!gcb) | |
| 247 | + gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); | |
| 248 | + if (!gc) | |
| 230 | 249 | return -ENOMEM; |
| 231 | 250 | |
| 232 | 251 | /* search for end interval coming before this element. |
| @@ -244,17 +263,28 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 11 unmodified lines | ||
| 244 | 263 | |
| 245 | 264 | if (prev) { |
| 246 | 265 | rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); |
| 266 | + nft_rbtree_gc_remove(net, set, priv, rbe_prev); | |
| 247 | 267 | |
| 248 | − rb_erase(&rbe_prev->node, &priv->root); | |
| 249 | − atomic_dec(&set->nelems); | |
| 250 | − nft_set_gc_batch_add(gcb, rbe_prev); | |
| 268 | + /* There is always room in this trans gc for this element, | |
| 269 | + * memory allocation never actually happens, hence, the warning | |
| 270 | + * splat in such case. No need to set NFT_SET_ELEM_DEAD_BIT, | |
| 271 | + * this is synchronous gc which never fails. | |
| 272 | + */ | |
| 273 | + gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); | |
| 274 | + if (WARN_ON_ONCE(!gc)) | |
| 275 | + return -ENOMEM; | |
| 276 | + | |
| 277 | + nft_trans_gc_elem_add(gc, rbe_prev); | |
| 251 | 278 | } |
| 252 | 279 | |
| 253 | − rb_erase(&rbe->node, &priv->root); | |
| 254 | − atomic_dec(&set->nelems); | |
| 280 | + nft_rbtree_gc_remove(net, set, priv, rbe); | |
| 281 | + gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); | |
| 282 | + if (WARN_ON_ONCE(!gc)) | |
| 283 | + return -ENOMEM; | |
| 284 | + | |
| 285 | + nft_trans_gc_elem_add(gc, rbe); | |
| 255 | 286 | |
| 256 | − nft_set_gc_batch_add(gcb, rbe); | |
| 257 | − nft_set_gc_batch_complete(gcb); | |
| 287 | + nft_trans_gc_queue_sync_done(gc); | |
| 258 | 288 | |
| 259 | 289 | return 0; |
| 260 | 290 | } |
| @@ -482,7 +512,6 @@ static void nft_rbtree_activate(const struct net *net, · 221 unmodified lines | ||
| 482 | 512 | struct nft_rbtree_elem *rbe = elem->priv; |
| 483 | 513 | |
| 484 | 514 | nft_set_elem_change_active(net, set, &rbe->ext); |
| 485 | − nft_set_elem_clear_busy(&rbe->ext); | |
| 486 | 515 | } |
| 487 | 516 | |
| 488 | 517 | static bool nft_rbtree_flush(const struct net *net, |
| @@ -490,12 +519,9 @@ static bool nft_rbtree_flush(const struct net *net, · 1 unmodified line | ||
| 490 | 519 | { |
| 491 | 520 | struct nft_rbtree_elem *rbe = priv; |
| 492 | 521 | |
| 493 | − if (!nft_set_elem_mark_busy(&rbe->ext) || | |
| 494 | − !nft_is_active(net, &rbe->ext)) { | |
| 495 | − nft_set_elem_change_active(net, set, &rbe->ext); | |
| 496 | − return true; | |
| 497 | − } | |
| 498 | − return false; | |
| 522 | + nft_set_elem_change_active(net, set, &rbe->ext); | |
| 523 | + | |
| 524 | + return true; | |
| 499 | 525 | } |
| 500 | 526 | |
| 501 | 527 | static void *nft_rbtree_deactivate(const struct net *net, |
| @@ -552,8 +578,6 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx, · 50 unmodified lines | ||
| 552 | 578 | |
| 553 | 579 | if (iter->count < iter->skip) |
| 554 | 580 | goto cont; |
| 555 | − if (nft_set_elem_expired(&rbe->ext)) | |
| 556 | − goto cont; | |
| 557 | 581 | if (!nft_set_elem_active(&rbe->ext, iter->genmask)) |
| 558 | 582 | goto cont; |
| 559 | 583 | |
| @@ -572,26 +596,40 @@ cont: · 12 unmodified lines | ||
| 572 | 596 | |
| 573 | 597 | static void nft_rbtree_gc(struct work_struct *work) |
| 574 | 598 | { |
| 575 | − struct nft_rbtree_elem *rbe, *rbe_end = NULL, *rbe_prev = NULL; | |
| 576 | − struct nft_set_gc_batch *gcb = NULL; | |
| 599 | + struct nft_rbtree_elem *rbe, *rbe_end = NULL; | |
| 600 | + struct nftables_pernet *nft_net; | |
| 577 | 601 | struct nft_rbtree *priv; |
| 602 | + struct nft_trans_gc *gc; | |
| 578 | 603 | struct rb_node *node; |
| 579 | 604 | struct nft_set *set; |
| 605 | + unsigned int gc_seq; | |
| 580 | 606 | struct net *net; |
| 581 | − u8 genmask; | |
| 582 | 607 | |
| 583 | 608 | priv = container_of(work, struct nft_rbtree, gc_work.work); |
| 584 | 609 | set = nft_set_container_of(priv); |
| 585 | 610 | net = read_pnet(&set->net); |
| 586 | − genmask = nft_genmask_cur(net); | |
| 611 | + nft_net = nft_pernet(net); | |
| 612 | + gc_seq = READ_ONCE(nft_net->gc_seq); | |
| 613 | + | |
| 614 | + gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL); | |
| 615 | + if (!gc) | |
| 616 | + goto done; | |
| 587 | 617 | |
| 588 | 618 | write_lock_bh(&priv->lock); |
| 589 | 619 | write_seqcount_begin(&priv->count); |
| 590 | 620 | for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) { |
| 621 | + | |
| 622 | + /* Ruleset has been updated, try later. */ | |
| 623 | + if (READ_ONCE(nft_net->gc_seq) != gc_seq) { | |
| 624 | + nft_trans_gc_destroy(gc); | |
| 625 | + gc = NULL; | |
| 626 | + goto try_later; | |
| 627 | + } | |
| 628 | + | |
| 591 | 629 | rbe = rb_entry(node, struct nft_rbtree_elem, node); |
| 592 | 630 | |
| 593 | − if (!nft_set_elem_active(&rbe->ext, genmask)) | |
| 594 | − continue; | |
| 631 | + if (nft_set_elem_is_dead(&rbe->ext)) | |
| 632 | + goto dead_elem; | |
| 595 | 633 | |
| 596 | 634 | /* elements are reversed in the rbtree for historical reasons, |
| 597 | 635 | * from highest to lowest value, that is why end element is |
| @@ -604,46 +642,36 @@ static void nft_rbtree_gc(struct work_struct *work) · 6 unmodified lines | ||
| 604 | 642 | if (!nft_set_elem_expired(&rbe->ext)) |
| 605 | 643 | continue; |
| 606 | 644 | |
| 607 | − if (nft_set_elem_mark_busy(&rbe->ext)) { | |
| 608 | − rbe_end = NULL; | |
| 645 | + nft_set_elem_dead(&rbe->ext); | |
| 646 | + | |
| 647 | + if (!rbe_end) | |
| 609 | 648 | continue; |
| 610 | − } | |
| 611 | 649 | |
| 612 | − if (rbe_prev) { | |
| 613 | − rb_erase(&rbe_prev->node, &priv->root); | |
| 614 | − rbe_prev = NULL; | |
| 615 | − } | |
| 616 | − gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); | |
| 617 | − if (!gcb) | |
| 618 | − break; | |
| 650 | + nft_set_elem_dead(&rbe_end->ext); | |
| 619 | 651 | |
| 620 | − atomic_dec(&set->nelems); | |
| 621 | − nft_set_gc_batch_add(gcb, rbe); | |
| 622 | − rbe_prev = rbe; | |
| 652 | + gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); | |
| 653 | + if (!gc) | |
| 654 | + goto try_later; | |
| 623 | 655 | |
| 624 | − if (rbe_end) { | |
| 625 | − atomic_dec(&set->nelems); | |
| 626 | − nft_set_gc_batch_add(gcb, rbe_end); | |
| 627 | − rb_erase(&rbe_end->node, &priv->root); | |
| 628 | − rbe_end = NULL; | |
| 629 | − } | |
| 630 | − node = rb_next(node); | |
| 631 | − if (!node) | |
| 632 | − break; | |
| 656 | + nft_trans_gc_elem_add(gc, rbe_end); | |
| 657 | + rbe_end = NULL; | |
| 658 | +dead_elem: | |
| 659 | + gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); | |
| 660 | + if (!gc) | |
| 661 | + goto try_later; | |
| 662 | + | |
| 663 | + nft_trans_gc_elem_add(gc, rbe); | |
| 633 | 664 | } |
| 634 | − if (rbe_prev) | |
| 635 | − rb_erase(&rbe_prev->node, &priv->root); | |
| 665 | + | |
| 666 | + gc = nft_trans_gc_catchall(gc, gc_seq); | |
| 667 | + | |
| 668 | +try_later: | |
| 636 | 669 | write_seqcount_end(&priv->count); |
| 637 | 670 | write_unlock_bh(&priv->lock); |
| 638 | 671 | |
| 639 | − rbe = nft_set_catchall_gc(set); | |
| 640 | − if (rbe) { | |
| 641 | − gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); | |
| 642 | − if (gcb) | |
| 643 | − nft_set_gc_batch_add(gcb, rbe); | |
| 644 | − } | |
| 645 | − nft_set_gc_batch_complete(gcb); | |
| 646 | − | |
| 672 | + if (gc) | |
| 673 | + nft_trans_gc_queue_async_done(gc); | |
| 674 | +done: | |
| 647 | 675 | queue_delayed_work(system_power_efficient_wq, &priv->gc_work, |
| 648 | 676 | nft_set_gc_interval(set)); |
| 649 | 677 | } |
| @@ -107,7 +107,7 @@ static void nft_socket_eval(const struct nft_expr *expr, · 106 unmodified lines | ||
| 107 | 107 | break; |
| 108 | 108 | case NFT_SOCKET_MARK: |
| 109 | 109 | if (sk_fullsock(sk)) { |
| 110 | − *dest = sk->sk_mark; | |
| 110 | + *dest = READ_ONCE(sk->sk_mark); | |
| 111 | 111 | } else { |
| 112 | 112 | regs->verdict.code = NFT_BREAK; |
| 113 | 113 | return; |
| @@ -77,7 +77,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, · 76 unmodified lines | ||
| 77 | 77 | |
| 78 | 78 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && |
| 79 | 79 | transparent && sk_fullsock(sk)) |
| 80 | − pskb->mark = sk->sk_mark; | |
| 80 | + pskb->mark = READ_ONCE(sk->sk_mark); | |
| 81 | 81 | |
| 82 | 82 | if (sk != skb->sk) |
| 83 | 83 | sock_gen_put(sk); |
| @@ -138,7 +138,7 @@ socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par) · 54 unmodified lines | ||
| 138 | 138 | |
| 139 | 139 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && |
| 140 | 140 | transparent && sk_fullsock(sk)) |
| 141 | − pskb->mark = sk->sk_mark; | |
| 141 | + pskb->mark = READ_ONCE(sk->sk_mark); | |
| 142 | 142 | |
| 143 | 143 | if (sk != skb->sk) |
| 144 | 144 | sock_gen_put(sk); |
| @@ -401,18 +401,20 @@ static void __packet_set_status(struct packet_sock *po, void *frame, int status) · 400 unmodified lines | ||
| 401 | 401 | { |
| 402 | 402 | union tpacket_uhdr h; |
| 403 | 403 | |
| 404 | + /* WRITE_ONCE() are paired with READ_ONCE() in __packet_get_status */ | |
| 405 | + | |
| 404 | 406 | h.raw = frame; |
| 405 | 407 | switch (po->tp_version) { |
| 406 | 408 | case TPACKET_V1: |
| 407 | − h.h1->tp_status = status; | |
| 409 | + WRITE_ONCE(h.h1->tp_status, status); | |
| 408 | 410 | flush_dcache_page(pgv_to_page(&h.h1->tp_status)); |
| 409 | 411 | break; |
| 410 | 412 | case TPACKET_V2: |
| 411 | − h.h2->tp_status = status; | |
| 413 | + WRITE_ONCE(h.h2->tp_status, status); | |
| 412 | 414 | flush_dcache_page(pgv_to_page(&h.h2->tp_status)); |
| 413 | 415 | break; |
| 414 | 416 | case TPACKET_V3: |
| 415 | − h.h3->tp_status = status; | |
| 417 | + WRITE_ONCE(h.h3->tp_status, status); | |
| 416 | 418 | flush_dcache_page(pgv_to_page(&h.h3->tp_status)); |
| 417 | 419 | break; |
| 418 | 420 | default: |
| @@ -429,17 +431,19 @@ static int __packet_get_status(const struct packet_sock *po, void *frame) · 10 unmodified lines | ||
| 429 | 431 | |
| 430 | 432 | smp_rmb(); |
| 431 | 433 | |
| 434 | + /* READ_ONCE() are paired with WRITE_ONCE() in __packet_set_status */ | |
| 435 | + | |
| 432 | 436 | h.raw = frame; |
| 433 | 437 | switch (po->tp_version) { |
| 434 | 438 | case TPACKET_V1: |
| 435 | 439 | flush_dcache_page(pgv_to_page(&h.h1->tp_status)); |
| 436 | − return h.h1->tp_status; | |
| 440 | + return READ_ONCE(h.h1->tp_status); | |
| 437 | 441 | case TPACKET_V2: |
| 438 | 442 | flush_dcache_page(pgv_to_page(&h.h2->tp_status)); |
| 439 | − return h.h2->tp_status; | |
| 443 | + return READ_ONCE(h.h2->tp_status); | |
| 440 | 444 | case TPACKET_V3: |
| 441 | 445 | flush_dcache_page(pgv_to_page(&h.h3->tp_status)); |
| 442 | − return h.h3->tp_status; | |
| 446 | + return READ_ONCE(h.h3->tp_status); | |
| 443 | 447 | default: |
| 444 | 448 | WARN(1, "TPACKET version not supported.\n"); |
| 445 | 449 | BUG(); |
| @@ -2050,8 +2054,8 @@ retry: · 1604 unmodified lines | ||
| 2050 | 2054 | |
| 2051 | 2055 | skb->protocol = proto; |
| 2052 | 2056 | skb->dev = dev; |
| 2053 | − skb->priority = sk->sk_priority; | |
| 2054 | − skb->mark = sk->sk_mark; | |
| 2057 | + skb->priority = READ_ONCE(sk->sk_priority); | |
| 2058 | + skb->mark = READ_ONCE(sk->sk_mark); | |
| 2055 | 2059 | skb->tstamp = sockc.transmit_time; |
| 2056 | 2060 | |
| 2057 | 2061 | skb_setup_tx_timestamp(skb, sockc.tsflags); |
| @@ -2585,8 +2589,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, · 527 unmodified lines | ||
| 2585 | 2589 | |
| 2586 | 2590 | skb->protocol = proto; |
| 2587 | 2591 | skb->dev = dev; |
| 2588 | − skb->priority = po->sk.sk_priority; | |
| 2589 | − skb->mark = po->sk.sk_mark; | |
| 2592 | + skb->priority = READ_ONCE(po->sk.sk_priority); | |
| 2593 | + skb->mark = READ_ONCE(po->sk.sk_mark); | |
| 2590 | 2594 | skb->tstamp = sockc->transmit_time; |
| 2591 | 2595 | skb_setup_tx_timestamp(skb, sockc->tsflags); |
| 2592 | 2596 | skb_zcopy_set_nouarg(skb, ph.raw); |
| @@ -2988,7 +2992,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) · 395 unmodified lines | ||
| 2988 | 2992 | goto out_unlock; |
| 2989 | 2993 | |
| 2990 | 2994 | sockcm_init(&sockc, sk); |
| 2991 | − sockc.mark = sk->sk_mark; | |
| 2995 | + sockc.mark = READ_ONCE(sk->sk_mark); | |
| 2992 | 2996 | if (msg->msg_controllen) { |
| 2993 | 2997 | err = sock_cmsg_send(sk, msg, &sockc); |
| 2994 | 2998 | if (unlikely(err)) |
| @@ -3061,7 +3065,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) · 66 unmodified lines | ||
| 3061 | 3065 | |
| 3062 | 3066 | skb->protocol = proto; |
| 3063 | 3067 | skb->dev = dev; |
| 3064 | − skb->priority = sk->sk_priority; | |
| 3068 | + skb->priority = READ_ONCE(sk->sk_priority); | |
| 3065 | 3069 | skb->mark = sockc.mark; |
| 3066 | 3070 | skb->tstamp = sockc.transmit_time; |
| 3067 | 3071 | |
| @@ -776,7 +776,8 @@ mpls_stack_entry_policy[TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX + 1] = { · 775 unmodified lines | ||
| 776 | 776 | [TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL] = { .type = NLA_U32 }, |
| 777 | 777 | }; |
| 778 | 778 | |
| 779 | −static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = { | |
| 779 | +static const struct nla_policy | |
| 780 | +cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX + 1] = { | |
| 780 | 781 | [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, |
| 781 | 782 | FLOW_DIS_CFM_MDL_MAX), |
| 782 | 783 | [TCA_FLOWER_KEY_CFM_OPCODE] = { .type = NLA_U8 }, |
| @@ -1709,7 +1710,7 @@ static int fl_set_key_cfm(struct nlattr **tb, · 926 unmodified lines | ||
| 1709 | 1710 | struct fl_flow_key *mask, |
| 1710 | 1711 | struct netlink_ext_ack *extack) |
| 1711 | 1712 | { |
| 1712 | − struct nlattr *nla_cfm_opt[TCA_FLOWER_KEY_CFM_OPT_MAX]; | |
| 1713 | + struct nlattr *nla_cfm_opt[TCA_FLOWER_KEY_CFM_OPT_MAX + 1]; | |
| 1713 | 1714 | int err; |
| 1714 | 1715 | |
| 1715 | 1716 | if (!tb[TCA_FLOWER_KEY_CFM]) |
| @@ -267,7 +267,6 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, · 266 unmodified lines | ||
| 267 | 267 | return -ENOBUFS; |
| 268 | 268 | |
| 269 | 269 | fnew->id = f->id; |
| 270 | − fnew->res = f->res; | |
| 271 | 270 | fnew->ifindex = f->ifindex; |
| 272 | 271 | fnew->tp = f->tp; |
| 273 | 272 | |
| @@ -513,7 +513,6 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, · 512 unmodified lines | ||
| 513 | 513 | if (fold) { |
| 514 | 514 | f->id = fold->id; |
| 515 | 515 | f->iif = fold->iif; |
| 516 | − f->res = fold->res; | |
| 517 | 516 | f->handle = fold->handle; |
| 518 | 517 | |
| 519 | 518 | f->tp = fold->tp; |
| @@ -826,7 +826,6 @@ static struct tc_u_knode *u32_init_knode(struct net *net, struct tcf_proto *tp, · 825 unmodified lines | ||
| 826 | 826 | |
| 827 | 827 | new->ifindex = n->ifindex; |
| 828 | 828 | new->fshift = n->fshift; |
| 829 | − new->res = n->res; | |
| 830 | 829 | new->flags = n->flags; |
| 831 | 830 | RCU_INIT_POINTER(new->ht_down, ht); |
| 832 | 831 | |
| @@ -1024,18 +1023,62 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, · 191 unmodified lines | ||
| 1024 | 1023 | return -EINVAL; |
| 1025 | 1024 | } |
| 1026 | 1025 | |
| 1026 | + /* At this point, we need to derive the new handle that will be used to | |
| 1027 | + * uniquely map the identity of this table match entry. The | |
| 1028 | + * identity of the entry that we need to construct is 32 bits made of: | |
| 1029 | + * htid(12b):bucketid(8b):node/entryid(12b) | |
| 1030 | + * | |
| 1031 | + * At this point _we have the table(ht)_ in which we will insert this | |
| 1032 | + * entry. We carry the table's id in variable "htid". | |
| 1033 | + * Note that earlier code picked the ht selection either by a) the user | |
| 1034 | + * providing the htid specified via TCA_U32_HASH attribute or b) when | |
| 1035 | + * no such attribute is passed then the root ht, is default to at ID | |
| 1036 | + * 0x[800][00][000]. Rule: the root table has a single bucket with ID 0. | |
| 1037 | + * If OTOH the user passed us the htid, they may also pass a bucketid of | |
| 1038 | + * choice. 0 is fine. For example a user htid is 0x[600][01][000] it is | |
| 1039 | + * indicating hash bucketid of 1. Rule: the entry/node ID _cannot_ be | |
| 1040 | + * passed via the htid, so even if it was non-zero it will be ignored. | |
| 1041 | + * | |
| 1042 | + * We may also have a handle, if the user passed one. The handle also | |
| 1043 | + * carries the same addressing of htid(12b):bucketid(8b):node/entryid(12b). | |
| 1044 | + * Rule: the bucketid on the handle is ignored even if one was passed; | |
| 1045 | + * rather the value on "htid" is always assumed to be the bucketid. | |
| 1046 | + */ | |
| 1027 | 1047 | if (handle) { |
| 1048 | + /* Rule: The htid from handle and tableid from htid must match */ | |
| 1028 | 1049 | if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid)) { |
| 1029 | 1050 | NL_SET_ERR_MSG_MOD(extack, "Handle specified hash table address mismatch"); |
| 1030 | 1051 | return -EINVAL; |
| 1031 | 1052 | } |
| 1032 | − handle = htid | TC_U32_NODE(handle); | |
| 1033 | − err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, handle, | |
| 1034 | − GFP_KERNEL); | |
| 1035 | − if (err) | |
| 1036 | − return err; | |
| 1037 | − } else | |
| 1053 | + /* Ok, so far we have a valid htid(12b):bucketid(8b) but we | |
| 1054 | + * need to finalize the table entry identification with the last | |
| 1055 | + * part - the node/entryid(12b)). Rule: Nodeid _cannot be 0_ for | |
| 1056 | + * entries. Rule: nodeid of 0 is reserved only for tables(see | |
| 1057 | + * earlier code which processes TC_U32_DIVISOR attribute). | |
| 1058 | + * Rule: The nodeid can only be derived from the handle (and not | |
| 1059 | + * htid). | |
| 1060 | + * Rule: if the handle specified zero for the node id example | |
| 1061 | + * 0x60000000, then pick a new nodeid from the pool of IDs | |
| 1062 | + * this hash table has been allocating from. | |
| 1063 | + * If OTOH it is specified (i.e for example the user passed a | |
| 1064 | + * handle such as 0x60000123), then we use it generate our final | |
| 1065 | + * handle which is used to uniquely identify the match entry. | |
| 1066 | + */ | |
| 1067 | + if (!TC_U32_NODE(handle)) { | |
| 1068 | + handle = gen_new_kid(ht, htid); | |
| 1069 | + } else { | |
| 1070 | + handle = htid | TC_U32_NODE(handle); | |
| 1071 | + err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, | |
| 1072 | + handle, GFP_KERNEL); | |
| 1073 | + if (err) | |
| 1074 | + return err; | |
| 1075 | + } | |
| 1076 | + } else { | |
| 1077 | + /* The user did not give us a handle; lets just generate one | |
| 1078 | + * from the table's pool of nodeids. | |
| 1079 | + */ | |
| 1038 | 1080 | handle = gen_new_kid(ht, htid); |
| 1081 | + } | |
| 1039 | 1082 | |
| 1040 | 1083 | if (tb[TCA_U32_SEL] == NULL) { |
| 1041 | 1084 | NL_SET_ERR_MSG_MOD(extack, "Selector not specified"); |
| @@ -568,7 +568,7 @@ META_COLLECTOR(int_sk_rcvtimeo) · 567 unmodified lines | ||
| 568 | 568 | *err = -1; |
| 569 | 569 | return; |
| 570 | 570 | } |
| 571 | − dst->value = sk->sk_rcvtimeo / HZ; | |
| 571 | + dst->value = READ_ONCE(sk->sk_rcvtimeo) / HZ; | |
| 572 | 572 | } |
| 573 | 573 | |
| 574 | 574 | META_COLLECTOR(int_sk_sndtimeo) |
| @@ -579,7 +579,7 @@ META_COLLECTOR(int_sk_sndtimeo) · 4 unmodified lines | ||
| 579 | 579 | *err = -1; |
| 580 | 580 | return; |
| 581 | 581 | } |
| 582 | − dst->value = sk->sk_sndtimeo / HZ; | |
| 582 | + dst->value = READ_ONCE(sk->sk_sndtimeo) / HZ; | |
| 583 | 583 | } |
| 584 | 584 | |
| 585 | 585 | META_COLLECTOR(int_sk_sendmsg_off) |
| @@ -1015,6 +1015,11 @@ static const struct nla_policy taprio_tc_policy[TCA_TAPRIO_TC_ENTRY_MAX + 1] = { · 1014 unmodified lines | ||
| 1015 | 1015 | TC_FP_PREEMPTIBLE), |
| 1016 | 1016 | }; |
| 1017 | 1017 | |
| 1018 | +static struct netlink_range_validation_signed taprio_cycle_time_range = { | |
| 1019 | + .min = 0, | |
| 1020 | + .max = INT_MAX, | |
| 1021 | +}; | |
| 1022 | + | |
| 1018 | 1023 | static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = { |
| 1019 | 1024 | [TCA_TAPRIO_ATTR_PRIOMAP] = { |
| 1020 | 1025 | .len = sizeof(struct tc_mqprio_qopt) |
| @@ -1023,7 +1028,8 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = { · 2 unmodified lines | ||
| 1023 | 1028 | [TCA_TAPRIO_ATTR_SCHED_BASE_TIME] = { .type = NLA_S64 }, |
| 1024 | 1029 | [TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY] = { .type = NLA_NESTED }, |
| 1025 | 1030 | [TCA_TAPRIO_ATTR_SCHED_CLOCKID] = { .type = NLA_S32 }, |
| 1026 | − [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME] = { .type = NLA_S64 }, | |
| 1031 | + [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME] = | |
| 1032 | + NLA_POLICY_FULL_RANGE_SIGNED(NLA_S64, &taprio_cycle_time_range), | |
| 1027 | 1033 | [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 }, |
| 1028 | 1034 | [TCA_TAPRIO_ATTR_FLAGS] = { .type = NLA_U32 }, |
| 1029 | 1035 | [TCA_TAPRIO_ATTR_TXTIME_DELAY] = { .type = NLA_U32 }, |
| @@ -1159,6 +1165,11 @@ static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb, · 129 unmodified lines | ||
| 1159 | 1165 | return -EINVAL; |
| 1160 | 1166 | } |
| 1161 | 1167 | |
| 1168 | + if (cycle < 0 || cycle > INT_MAX) { | |
| 1169 | + NL_SET_ERR_MSG(extack, "'cycle_time' is too big"); | |
| 1170 | + return -EINVAL; | |
| 1171 | + } | |
| 1172 | + | |
| 1162 | 1173 | new->cycle_time = cycle; |
| 1163 | 1174 | } |
| 1164 | 1175 | |
| @@ -1347,7 +1358,7 @@ static void setup_txtime(struct taprio_sched *q, · 182 unmodified lines | ||
| 1347 | 1358 | struct sched_gate_list *sched, ktime_t base) |
| 1348 | 1359 | { |
| 1349 | 1360 | struct sched_entry *entry; |
| 1350 | − u32 interval = 0; | |
| 1361 | + u64 interval = 0; | |
| 1351 | 1362 | |
| 1352 | 1363 | list_for_each_entry(entry, &sched->entries, list) { |
| 1353 | 1364 | entry->next_txtime = ktime_add_ns(base, interval); |
| @@ -378,8 +378,8 @@ static struct sock *smc_sock_alloc(struct net *net, struct socket *sock, · 377 unmodified lines | ||
| 378 | 378 | sk->sk_state = SMC_INIT; |
| 379 | 379 | sk->sk_destruct = smc_destruct; |
| 380 | 380 | sk->sk_protocol = protocol; |
| 381 | − WRITE_ONCE(sk->sk_sndbuf, READ_ONCE(net->smc.sysctl_wmem)); | |
| 382 | − WRITE_ONCE(sk->sk_rcvbuf, READ_ONCE(net->smc.sysctl_rmem)); | |
| 381 | + WRITE_ONCE(sk->sk_sndbuf, 2 * READ_ONCE(net->smc.sysctl_wmem)); | |
| 382 | + WRITE_ONCE(sk->sk_rcvbuf, 2 * READ_ONCE(net->smc.sysctl_rmem)); | |
| 383 | 383 | smc = smc_sk(sk); |
| 384 | 384 | INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work); |
| 385 | 385 | INIT_WORK(&smc->connect_work, smc_connect_work); |
| @@ -436,24 +436,9 @@ out: · 50 unmodified lines | ||
| 436 | 436 | return rc; |
| 437 | 437 | } |
| 438 | 438 | |
| 439 | −static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk, | |
| 440 | − unsigned long mask) | |
| 441 | −{ | |
| 442 | − /* options we don't get control via setsockopt for */ | |
| 443 | − nsk->sk_type = osk->sk_type; | |
| 444 | − nsk->sk_sndbuf = osk->sk_sndbuf; | |
| 445 | − nsk->sk_rcvbuf = osk->sk_rcvbuf; | |
| 446 | − nsk->sk_sndtimeo = osk->sk_sndtimeo; | |
| 447 | − nsk->sk_rcvtimeo = osk->sk_rcvtimeo; | |
| 448 | − nsk->sk_mark = osk->sk_mark; | |
| 449 | − nsk->sk_priority = osk->sk_priority; | |
| 450 | − nsk->sk_rcvlowat = osk->sk_rcvlowat; | |
| 451 | − nsk->sk_bound_dev_if = osk->sk_bound_dev_if; | |
| 452 | − nsk->sk_err = osk->sk_err; | |
| 453 | − | |
| 454 | − nsk->sk_flags &= ~mask; | |
| 455 | − nsk->sk_flags |= osk->sk_flags & mask; | |
| 456 | −} | |
| 439 | +/* copy only relevant settings and flags of SOL_SOCKET level from smc to | |
| 440 | + * clc socket (since smc is not called for these options from net/core) | |
| 441 | + */ | |
| 457 | 442 | |
| 458 | 443 | #define SK_FLAGS_SMC_TO_CLC ((1UL << SOCK_URGINLINE) | \ |
| 459 | 444 | (1UL << SOCK_KEEPOPEN) | \ |
| @@ -470,9 +455,55 @@ static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk, · 10 unmodified lines | ||
| 470 | 455 | (1UL << SOCK_NOFCS) | \ |
| 471 | 456 | (1UL << SOCK_FILTER_LOCKED) | \ |
| 472 | 457 | (1UL << SOCK_TSTAMP_NEW)) |
| 473 | −/* copy only relevant settings and flags of SOL_SOCKET level from smc to | |
| 474 | − * clc socket (since smc is not called for these options from net/core) | |
| 475 | − */ | |
| 458 | + | |
| 459 | +/* if set, use value set by setsockopt() - else use IPv4 or SMC sysctl value */ | |
| 460 | +static void smc_adjust_sock_bufsizes(struct sock *nsk, struct sock *osk, | |
| 461 | + unsigned long mask) | |
| 462 | +{ | |
| 463 | + struct net *nnet = sock_net(nsk); | |
| 464 | + | |
| 465 | + nsk->sk_userlocks = osk->sk_userlocks; | |
| 466 | + if (osk->sk_userlocks & SOCK_SNDBUF_LOCK) { | |
| 467 | + nsk->sk_sndbuf = osk->sk_sndbuf; | |
| 468 | + } else { | |
| 469 | + if (mask == SK_FLAGS_SMC_TO_CLC) | |
| 470 | + WRITE_ONCE(nsk->sk_sndbuf, | |
| 471 | + READ_ONCE(nnet->ipv4.sysctl_tcp_wmem[1])); | |
| 472 | + else | |
| 473 | + WRITE_ONCE(nsk->sk_sndbuf, | |
| 474 | + 2 * READ_ONCE(nnet->smc.sysctl_wmem)); | |
| 475 | + } | |
| 476 | + if (osk->sk_userlocks & SOCK_RCVBUF_LOCK) { | |
| 477 | + nsk->sk_rcvbuf = osk->sk_rcvbuf; | |
| 478 | + } else { | |
| 479 | + if (mask == SK_FLAGS_SMC_TO_CLC) | |
| 480 | + WRITE_ONCE(nsk->sk_rcvbuf, | |
| 481 | + READ_ONCE(nnet->ipv4.sysctl_tcp_rmem[1])); | |
| 482 | + else | |
| 483 | + WRITE_ONCE(nsk->sk_rcvbuf, | |
| 484 | + 2 * READ_ONCE(nnet->smc.sysctl_rmem)); | |
| 485 | + } | |
| 486 | +} | |
| 487 | + | |
| 488 | +static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk, | |
| 489 | + unsigned long mask) | |
| 490 | +{ | |
| 491 | + /* options we don't get control via setsockopt for */ | |
| 492 | + nsk->sk_type = osk->sk_type; | |
| 493 | + nsk->sk_sndtimeo = osk->sk_sndtimeo; | |
| 494 | + nsk->sk_rcvtimeo = osk->sk_rcvtimeo; | |
| 495 | + nsk->sk_mark = READ_ONCE(osk->sk_mark); | |
| 496 | + nsk->sk_priority = osk->sk_priority; | |
| 497 | + nsk->sk_rcvlowat = osk->sk_rcvlowat; | |
| 498 | + nsk->sk_bound_dev_if = osk->sk_bound_dev_if; | |
| 499 | + nsk->sk_err = osk->sk_err; | |
| 500 | + | |
| 501 | + nsk->sk_flags &= ~mask; | |
| 502 | + nsk->sk_flags |= osk->sk_flags & mask; | |
| 503 | + | |
| 504 | + smc_adjust_sock_bufsizes(nsk, osk, mask); | |
| 505 | +} | |
| 506 | + | |
| 476 | 507 | static void smc_copy_sock_settings_to_clc(struct smc_sock *smc) |
| 477 | 508 | { |
| 478 | 509 | smc_copy_sock_settings(smc->clcsock->sk, &smc->sk, SK_FLAGS_SMC_TO_CLC); |
| @@ -2479,8 +2510,6 @@ static void smc_tcp_listen_work(struct work_struct *work) · 2000 unmodified lines | ||
| 2479 | 2510 | sock_hold(lsk); /* sock_put in smc_listen_work */ |
| 2480 | 2511 | INIT_WORK(&new_smc->smc_listen_work, smc_listen_work); |
| 2481 | 2512 | smc_copy_sock_settings_to_smc(new_smc); |
| 2482 | − new_smc->sk.sk_sndbuf = lsmc->sk.sk_sndbuf; | |
| 2483 | − new_smc->sk.sk_rcvbuf = lsmc->sk.sk_rcvbuf; | |
| 2484 | 2513 | sock_hold(&new_smc->sk); /* sock_put in passive closing */ |
| 2485 | 2514 | if (!queue_work(smc_hs_wq, &new_smc->smc_listen_work)) |
| 2486 | 2515 | sock_put(&new_smc->sk); |
| @@ -161,7 +161,7 @@ struct smc_connection { · 160 unmodified lines | ||
| 161 | 161 | |
| 162 | 162 | struct smc_buf_desc *sndbuf_desc; /* send buffer descriptor */ |
| 163 | 163 | struct smc_buf_desc *rmb_desc; /* RMBE descriptor */ |
| 164 | − int rmbe_size_short;/* compressed notation */ | |
| 164 | + int rmbe_size_comp; /* compressed notation */ | |
| 165 | 165 | int rmbe_update_limit; |
| 166 | 166 | /* lower limit for consumer |
| 167 | 167 | * cursor update |
| @@ -1007,7 +1007,7 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc, · 1006 unmodified lines | ||
| 1007 | 1007 | clc->d0.gid = |
| 1008 | 1008 | conn->lgr->smcd->ops->get_local_gid(conn->lgr->smcd); |
| 1009 | 1009 | clc->d0.token = conn->rmb_desc->token; |
| 1010 | − clc->d0.dmbe_size = conn->rmbe_size_short; | |
| 1010 | + clc->d0.dmbe_size = conn->rmbe_size_comp; | |
| 1011 | 1011 | clc->d0.dmbe_idx = 0; |
| 1012 | 1012 | memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE); |
| 1013 | 1013 | if (version == SMC_V1) { |
| @@ -1050,7 +1050,7 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc, · 36 unmodified lines | ||
| 1050 | 1050 | clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu); |
| 1051 | 1051 | break; |
| 1052 | 1052 | } |
| 1053 | − clc->r0.rmbe_size = conn->rmbe_size_short; | |
| 1053 | + clc->r0.rmbe_size = conn->rmbe_size_comp; | |
| 1054 | 1054 | clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ? |
| 1055 | 1055 | cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) : |
| 1056 | 1056 | cpu_to_be64((u64)sg_dma_address |
| @@ -2309,31 +2309,30 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb) · 2308 unmodified lines | ||
| 2309 | 2309 | struct smc_connection *conn = &smc->conn; |
| 2310 | 2310 | struct smc_link_group *lgr = conn->lgr; |
| 2311 | 2311 | struct list_head *buf_list; |
| 2312 | − int bufsize, bufsize_short; | |
| 2312 | + int bufsize, bufsize_comp; | |
| 2313 | 2313 | struct rw_semaphore *lock; /* lock buffer list */ |
| 2314 | 2314 | bool is_dgraded = false; |
| 2315 | − int sk_buf_size; | |
| 2316 | 2315 | |
| 2317 | 2316 | if (is_rmb) |
| 2318 | 2317 | /* use socket recv buffer size (w/o overhead) as start value */ |
| 2319 | − sk_buf_size = smc->sk.sk_rcvbuf; | |
| 2318 | + bufsize = smc->sk.sk_rcvbuf / 2; | |
| 2320 | 2319 | else |
| 2321 | 2320 | /* use socket send buffer size (w/o overhead) as start value */ |
| 2322 | − sk_buf_size = smc->sk.sk_sndbuf; | |
| 2321 | + bufsize = smc->sk.sk_sndbuf / 2; | |
| 2323 | 2322 | |
| 2324 | − for (bufsize_short = smc_compress_bufsize(sk_buf_size, is_smcd, is_rmb); | |
| 2325 | − bufsize_short >= 0; bufsize_short--) { | |
| 2323 | + for (bufsize_comp = smc_compress_bufsize(bufsize, is_smcd, is_rmb); | |
| 2324 | + bufsize_comp >= 0; bufsize_comp--) { | |
| 2326 | 2325 | if (is_rmb) { |
| 2327 | 2326 | lock = &lgr->rmbs_lock; |
| 2328 | − buf_list = &lgr->rmbs[bufsize_short]; | |
| 2327 | + buf_list = &lgr->rmbs[bufsize_comp]; | |
| 2329 | 2328 | } else { |
| 2330 | 2329 | lock = &lgr->sndbufs_lock; |
| 2331 | − buf_list = &lgr->sndbufs[bufsize_short]; | |
| 2330 | + buf_list = &lgr->sndbufs[bufsize_comp]; | |
| 2332 | 2331 | } |
| 2333 | − bufsize = smc_uncompress_bufsize(bufsize_short); | |
| 2332 | + bufsize = smc_uncompress_bufsize(bufsize_comp); | |
| 2334 | 2333 | |
| 2335 | 2334 | /* check for reusable slot in the link group */ |
| 2336 | − buf_desc = smc_buf_get_slot(bufsize_short, lock, buf_list); | |
| 2335 | + buf_desc = smc_buf_get_slot(bufsize_comp, lock, buf_list); | |
| 2337 | 2336 | if (buf_desc) { |
| 2338 | 2337 | buf_desc->is_dma_need_sync = 0; |
| 2339 | 2338 | SMC_STAT_RMB_SIZE(smc, is_smcd, is_rmb, bufsize); |
| @@ -2377,8 +2376,8 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb) · 37 unmodified lines | ||
| 2377 | 2376 | |
| 2378 | 2377 | if (is_rmb) { |
| 2379 | 2378 | conn->rmb_desc = buf_desc; |
| 2380 | − conn->rmbe_size_short = bufsize_short; | |
| 2381 | − smc->sk.sk_rcvbuf = bufsize; | |
| 2379 | + conn->rmbe_size_comp = bufsize_comp; | |
| 2380 | + smc->sk.sk_rcvbuf = bufsize * 2; | |
| 2382 | 2381 | atomic_set(&conn->bytes_to_rcv, 0); |
| 2383 | 2382 | conn->rmbe_update_limit = |
| 2384 | 2383 | smc_rmb_wnd_update_limit(buf_desc->len); |
| @@ -2386,7 +2385,7 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb) · 1 unmodified line | ||
| 2386 | 2385 | smc_ism_set_conn(conn); /* map RMB/smcd_dev to conn */ |
| 2387 | 2386 | } else { |
| 2388 | 2387 | conn->sndbuf_desc = buf_desc; |
| 2389 | − smc->sk.sk_sndbuf = bufsize; | |
| 2388 | + smc->sk.sk_sndbuf = bufsize * 2; | |
| 2390 | 2389 | atomic_set(&conn->sndbuf_space, bufsize); |
| 2391 | 2390 | } |
| 2392 | 2391 | return 0; |
| @@ -21,6 +21,10 @@ · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 22 | static int min_sndbuf = SMC_BUF_MIN_SIZE; |
| 23 | 23 | static int min_rcvbuf = SMC_BUF_MIN_SIZE; |
| 24 | +static int max_sndbuf = INT_MAX / 2; | |
| 25 | +static int max_rcvbuf = INT_MAX / 2; | |
| 26 | +static const int net_smc_wmem_init = (64 * 1024); | |
| 27 | +static const int net_smc_rmem_init = (64 * 1024); | |
| 24 | 28 | |
| 25 | 29 | static struct ctl_table smc_table[] = { |
| 26 | 30 | { |
| @@ -53,6 +57,7 @@ static struct ctl_table smc_table[] = { · 26 unmodified lines | ||
| 53 | 57 | .mode = 0644, |
| 54 | 58 | .proc_handler = proc_dointvec_minmax, |
| 55 | 59 | .extra1 = &min_sndbuf, |
| 60 | + .extra2 = &max_sndbuf, | |
| 56 | 61 | }, |
| 57 | 62 | { |
| 58 | 63 | .procname = "rmem", |
| @@ -61,6 +66,7 @@ static struct ctl_table smc_table[] = { · 2 unmodified lines | ||
| 61 | 66 | .mode = 0644, |
| 62 | 67 | .proc_handler = proc_dointvec_minmax, |
| 63 | 68 | .extra1 = &min_rcvbuf, |
| 69 | + .extra2 = &max_rcvbuf, | |
| 64 | 70 | }, |
| 65 | 71 | { } |
| 66 | 72 | }; |
| @@ -88,8 +94,8 @@ int __net_init smc_sysctl_net_init(struct net *net) · 21 unmodified lines | ||
| 88 | 94 | net->smc.sysctl_autocorking_size = SMC_AUTOCORKING_DEFAULT_SIZE; |
| 89 | 95 | net->smc.sysctl_smcr_buf_type = SMCR_PHYS_CONT_BUFS; |
| 90 | 96 | net->smc.sysctl_smcr_testlink_time = SMC_LLC_TESTLINK_DEFAULT_TIME; |
| 91 | − WRITE_ONCE(net->smc.sysctl_wmem, READ_ONCE(net->ipv4.sysctl_tcp_wmem[1])); | |
| 92 | − WRITE_ONCE(net->smc.sysctl_rmem, READ_ONCE(net->ipv4.sysctl_tcp_rmem[1])); | |
| 97 | + WRITE_ONCE(net->smc.sysctl_wmem, net_smc_wmem_init); | |
| 98 | + WRITE_ONCE(net->smc.sysctl_rmem, net_smc_rmem_init); | |
| 93 | 99 | |
| 94 | 100 | return 0; |
| 95 | 101 | |
| @@ -52,6 +52,8 @@ static LIST_HEAD(tls_device_list); · 51 unmodified lines | ||
| 52 | 52 | static LIST_HEAD(tls_device_down_list); |
| 53 | 53 | static DEFINE_SPINLOCK(tls_device_lock); |
| 54 | 54 | |
| 55 | +static struct page *dummy_page; | |
| 56 | + | |
| 55 | 57 | static void tls_device_free_ctx(struct tls_context *ctx) |
| 56 | 58 | { |
| 57 | 59 | if (ctx->tx_conf == TLS_HW) { |
| @@ -312,36 +314,33 @@ static int tls_push_record(struct sock *sk, · 254 unmodified lines | ||
| 312 | 314 | return tls_push_sg(sk, ctx, offload_ctx->sg_tx_data, 0, flags); |
| 313 | 315 | } |
| 314 | 316 | |
| 315 | −static int tls_device_record_close(struct sock *sk, | |
| 316 | − struct tls_context *ctx, | |
| 317 | − struct tls_record_info *record, | |
| 318 | − struct page_frag *pfrag, | |
| 319 | − unsigned char record_type) | |
| 317 | +static void tls_device_record_close(struct sock *sk, | |
| 318 | + struct tls_context *ctx, | |
| 319 | + struct tls_record_info *record, | |
| 320 | + struct page_frag *pfrag, | |
| 321 | + unsigned char record_type) | |
| 320 | 322 | { |
| 321 | 323 | struct tls_prot_info *prot = &ctx->prot_info; |
| 322 | − int ret; | |
| 324 | + struct page_frag dummy_tag_frag; | |
| 323 | 325 | |
| 324 | 326 | /* append tag |
| 325 | 327 | * device will fill in the tag, we just need to append a placeholder |
| 326 | 328 | * use socket memory to improve coalescing (re-using a single buffer |
| 327 | 329 | * increases frag count) |
| 328 | − * if we can't allocate memory now, steal some back from data | |
| 330 | + * if we can't allocate memory now use the dummy page | |
| 329 | 331 | */ |
| 330 | − if (likely(skb_page_frag_refill(prot->tag_size, pfrag, | |
| 331 | − sk->sk_allocation))) { | |
| 332 | − ret = 0; | |
| 333 | − tls_append_frag(record, pfrag, prot->tag_size); | |
| 334 | − } else { | |
| 335 | − ret = prot->tag_size; | |
| 336 | − if (record->len <= prot->overhead_size) | |
| 337 | − return -ENOMEM; | |
| 332 | + if (unlikely(pfrag->size - pfrag->offset < prot->tag_size) && | |
| 333 | + !skb_page_frag_refill(prot->tag_size, pfrag, sk->sk_allocation)) { | |
| 334 | + dummy_tag_frag.page = dummy_page; | |
| 335 | + dummy_tag_frag.offset = 0; | |
| 336 | + pfrag = &dummy_tag_frag; | |
| 338 | 337 | } |
| 338 | + tls_append_frag(record, pfrag, prot->tag_size); | |
| 339 | 339 | |
| 340 | 340 | /* fill prepend */ |
| 341 | 341 | tls_fill_prepend(ctx, skb_frag_address(&record->frags[0]), |
| 342 | 342 | record->len - prot->overhead_size, |
| 343 | 343 | record_type); |
| 344 | − return ret; | |
| 345 | 344 | } |
| 346 | 345 | |
| 347 | 346 | static int tls_create_new_record(struct tls_offload_context_tx *offload_ctx, |
| @@ -541,18 +540,8 @@ last_record: · 193 unmodified lines | ||
| 541 | 540 | |
| 542 | 541 | if (done || record->len >= max_open_record_len || |
| 543 | 542 | (record->num_frags >= MAX_SKB_FRAGS - 1)) { |
| 544 | − rc = tls_device_record_close(sk, tls_ctx, record, | |
| 545 | − pfrag, record_type); | |
| 546 | − if (rc) { | |
| 547 | − if (rc > 0) { | |
| 548 | − size += rc; | |
| 549 | − } else { | |
| 550 | − size = orig_size; | |
| 551 | − destroy_record(record); | |
| 552 | − ctx->open_record = NULL; | |
| 553 | − break; | |
| 554 | − } | |
| 555 | − } | |
| 543 | + tls_device_record_close(sk, tls_ctx, record, | |
| 544 | + pfrag, record_type); | |
| 556 | 545 | |
| 557 | 546 | rc = tls_push_record(sk, |
| 558 | 547 | tls_ctx, |
| @@ -1450,14 +1439,26 @@ int __init tls_device_init(void) · 891 unmodified lines | ||
| 1450 | 1439 | { |
| 1451 | 1440 | int err; |
| 1452 | 1441 | |
| 1453 | − destruct_wq = alloc_workqueue("ktls_device_destruct", 0, 0); | |
| 1454 | − if (!destruct_wq) | |
| 1442 | + dummy_page = alloc_page(GFP_KERNEL); | |
| 1443 | + if (!dummy_page) | |
| 1455 | 1444 | return -ENOMEM; |
| 1456 | 1445 | |
| 1446 | + destruct_wq = alloc_workqueue("ktls_device_destruct", 0, 0); | |
| 1447 | + if (!destruct_wq) { | |
| 1448 | + err = -ENOMEM; | |
| 1449 | + goto err_free_dummy; | |
| 1450 | + } | |
| 1451 | + | |
| 1457 | 1452 | err = register_netdevice_notifier(&tls_dev_notifier); |
| 1458 | 1453 | if (err) |
| 1459 | − destroy_workqueue(destruct_wq); | |
| 1454 | + goto err_destroy_wq; | |
| 1460 | 1455 | |
| 1456 | + return 0; | |
| 1457 | + | |
| 1458 | +err_destroy_wq: | |
| 1459 | + destroy_workqueue(destruct_wq); | |
| 1460 | +err_free_dummy: | |
| 1461 | + put_page(dummy_page); | |
| 1461 | 1462 | return err; |
| 1462 | 1463 | } |
| 1463 | 1464 | |
| @@ -1466,4 +1467,5 @@ void __exit tls_device_cleanup(void) · 2 unmodified lines | ||
| 1466 | 1467 | unregister_netdevice_notifier(&tls_dev_notifier); |
| 1467 | 1468 | destroy_workqueue(destruct_wq); |
| 1468 | 1469 | clean_acked_data_flush(); |
| 1470 | + put_page(dummy_page); | |
| 1469 | 1471 | } |
| @@ -139,9 +139,6 @@ int tls_push_sg(struct sock *sk, · 138 unmodified lines | ||
| 139 | 139 | |
| 140 | 140 | ctx->splicing_pages = true; |
| 141 | 141 | while (1) { |
| 142 | − if (sg_is_last(sg)) | |
| 143 | − msg.msg_flags = flags; | |
| 144 | − | |
| 145 | 142 | /* is sending application-limited? */ |
| 146 | 143 | tcp_rate_check_app_limited(sk); |
| 147 | 144 | p = sg_page(sg); |
| @@ -790,7 +790,7 @@ static int unix_set_peek_off(struct sock *sk, int val) · 789 unmodified lines | ||
| 790 | 790 | if (mutex_lock_interruptible(&u->iolock)) |
| 791 | 791 | return -EINTR; |
| 792 | 792 | |
| 793 | − sk->sk_peek_off = val; | |
| 793 | + WRITE_ONCE(sk->sk_peek_off, val); | |
| 794 | 794 | mutex_unlock(&u->iolock); |
| 795 | 795 | |
| 796 | 796 | return 0; |
| @@ -5430,8 +5430,11 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) · 5429 unmodified lines | ||
| 5430 | 5430 | if (!wiphy->mbssid_max_interfaces) |
| 5431 | 5431 | return ERR_PTR(-EINVAL); |
| 5432 | 5432 | |
| 5433 | − nla_for_each_nested(nl_elems, attrs, rem_elems) | |
| 5433 | + nla_for_each_nested(nl_elems, attrs, rem_elems) { | |
| 5434 | + if (num_elems >= 255) | |
| 5435 | + return ERR_PTR(-EINVAL); | |
| 5434 | 5436 | num_elems++; |
| 5437 | + } | |
| 5435 | 5438 | |
| 5436 | 5439 | elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL); |
| 5437 | 5440 | if (!elems) |
| @@ -657,7 +657,7 @@ static int cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies, · 656 unmodified lines | ||
| 657 | 657 | |
| 658 | 658 | ret = cfg80211_calc_short_ssid(ies, &ssid_elem, &s_ssid_tmp); |
| 659 | 659 | if (ret) |
| 660 | − return ret; | |
| 660 | + return 0; | |
| 661 | 661 | |
| 662 | 662 | for_each_element_id(elem, WLAN_EID_REDUCED_NEIGHBOR_REPORT, |
| 663 | 663 | ies->data, ies->len) { |
| @@ -505,7 +505,7 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, · 504 unmodified lines | ||
| 505 | 505 | |
| 506 | 506 | skb->dev = dev; |
| 507 | 507 | skb->priority = xs->sk.sk_priority; |
| 508 | − skb->mark = xs->sk.sk_mark; | |
| 508 | + skb->mark = READ_ONCE(xs->sk.sk_mark); | |
| 509 | 509 | skb_shinfo(skb)->destructor_arg = (void *)(long)desc->addr; |
| 510 | 510 | skb->destructor = xsk_destruct_skb; |
| 511 | 511 | |
| @@ -994,6 +994,7 @@ static int xsk_bind(struct socket *sock, struct sockaddr *addr, int addr_len) · 482 unmodified lines | ||
| 994 | 994 | err = xp_alloc_tx_descs(xs->pool, xs); |
| 995 | 995 | if (err) { |
| 996 | 996 | xp_put_pool(xs->pool); |
| 997 | + xs->pool = NULL; | |
| 997 | 998 | sockfd_put(sock); |
| 998 | 999 | goto out_unlock; |
| 999 | 1000 | } |
| @@ -2250,7 +2250,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir, · 2249 unmodified lines | ||
| 2250 | 2250 | |
| 2251 | 2251 | match = xfrm_selector_match(&pol->selector, fl, family); |
| 2252 | 2252 | if (match) { |
| 2253 | − if ((sk->sk_mark & pol->mark.m) != pol->mark.v || | |
| 2253 | + if ((READ_ONCE(sk->sk_mark) & pol->mark.m) != pol->mark.v || | |
| 2254 | 2254 | pol->if_id != if_id) { |
| 2255 | 2255 | pol = NULL; |
| 2256 | 2256 | goto out; |
| @@ -257,7 +257,7 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \ · 256 unmodified lines | ||
| 257 | 257 | -fno-partial-inlining -fplugin-arg-arm_ssp_per_task_plugin-% \ |
| 258 | 258 | -fno-reorder-blocks -fno-allow-store-data-races -fasan-shadow-offset=% \ |
| 259 | 259 | -fzero-call-used-regs=% -fno-stack-clash-protection \ |
| 260 | − -fno-inline-functions-called-once \ | |
| 260 | + -fno-inline-functions-called-once -fsanitize=bounds-strict \ | |
| 261 | 261 | --param=% --param asan-% |
| 262 | 262 | |
| 263 | 263 | # Derived from `scripts/Makefile.clang`. |
| @@ -13,5 +13,6 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/sched.h> |
| 14 | 14 | |
| 15 | 15 | /* `bindgen` gets confused at certain things. */ |
| 16 | +const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; | |
| 16 | 17 | const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; |
| 17 | 18 | const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO; |
| @@ -9,6 +9,36 @@ use crate::bindings; · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | struct KernelAllocator; |
| 11 | 11 | |
| 12 | +/// Calls `krealloc` with a proper size to alloc a new object aligned to `new_layout`'s alignment. | |
| 13 | +/// | |
| 14 | +/// # Safety | |
| 15 | +/// | |
| 16 | +/// - `ptr` can be either null or a pointer which has been allocated by this allocator. | |
| 17 | +/// - `new_layout` must have a non-zero size. | |
| 18 | +unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: bindings::gfp_t) -> *mut u8 { | |
| 19 | + // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first. | |
| 20 | + let layout = new_layout.pad_to_align(); | |
| 21 | + | |
| 22 | + let mut size = layout.size(); | |
| 23 | + | |
| 24 | + if layout.align() > bindings::BINDINGS_ARCH_SLAB_MINALIGN { | |
| 25 | + // The alignment requirement exceeds the slab guarantee, thus try to enlarge the size | |
| 26 | + // to use the "power-of-two" size/alignment guarantee (see comments in `kmalloc()` for | |
| 27 | + // more information). | |
| 28 | + // | |
| 29 | + // Note that `layout.size()` (after padding) is guaranteed to be a multiple of | |
| 30 | + // `layout.align()`, so `next_power_of_two` gives enough alignment guarantee. | |
| 31 | + size = size.next_power_of_two(); | |
| 32 | + } | |
| 33 | + | |
| 34 | + // SAFETY: | |
| 35 | + // - `ptr` is either null or a pointer returned from a previous `k{re}alloc()` by the | |
| 36 | + // function safety requirement. | |
| 37 | + // - `size` is greater than 0 since it's either a `layout.size()` (which cannot be zero | |
| 38 | + // according to the function safety requirement) or a result from `next_power_of_two()`. | |
| 39 | + unsafe { bindings::krealloc(ptr as *const core::ffi::c_void, size, flags) as *mut u8 } | |
| 40 | +} | |
| 41 | + | |
| 12 | 42 | unsafe impl GlobalAlloc for KernelAllocator { |
| 13 | 43 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { |
| 14 | 44 | // `krealloc()` is used instead of `kmalloc()` because the latter is |
| @@ -30,10 +60,20 @@ static ALLOCATOR: KernelAllocator = KernelAllocator; · 15 unmodified lines | ||
| 30 | 60 | // to extract the object file that has them from the archive. For the moment, |
| 31 | 61 | // let's generate them ourselves instead. |
| 32 | 62 | // |
| 63 | +// Note: Although these are *safe* functions, they are called by the compiler | |
| 64 | +// with parameters that obey the same `GlobalAlloc` function safety | |
| 65 | +// requirements: size and align should form a valid layout, and size is | |
| 66 | +// greater than 0. | |
| 67 | +// | |
| 33 | 68 | // Note that `#[no_mangle]` implies exported too, nowadays. |
| 34 | 69 | #[no_mangle] |
| 35 | −fn __rust_alloc(size: usize, _align: usize) -> *mut u8 { | |
| 36 | − unsafe { bindings::krealloc(core::ptr::null(), size, bindings::GFP_KERNEL) as *mut u8 } | |
| 70 | +fn __rust_alloc(size: usize, align: usize) -> *mut u8 { | |
| 71 | + // SAFETY: See assumption above. | |
| 72 | + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; | |
| 73 | + | |
| 74 | + // SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater | |
| 75 | + // than 0. | |
| 76 | + unsafe { krealloc_aligned(ptr::null_mut(), layout, bindings::GFP_KERNEL) } | |
| 37 | 77 | } |
| 38 | 78 | |
| 39 | 79 | #[no_mangle] |
| @@ -42,23 +82,27 @@ fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) { · 2 unmodified lines | ||
| 42 | 82 | } |
| 43 | 83 | |
| 44 | 84 | #[no_mangle] |
| 45 | −fn __rust_realloc(ptr: *mut u8, _old_size: usize, _align: usize, new_size: usize) -> *mut u8 { | |
| 46 | − unsafe { | |
| 47 | − bindings::krealloc( | |
| 48 | − ptr as *const core::ffi::c_void, | |
| 49 | − new_size, | |
| 50 | − bindings::GFP_KERNEL, | |
| 51 | − ) as *mut u8 | |
| 52 | − } | |
| 85 | +fn __rust_realloc(ptr: *mut u8, _old_size: usize, align: usize, new_size: usize) -> *mut u8 { | |
| 86 | + // SAFETY: See assumption above. | |
| 87 | + let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, align) }; | |
| 88 | + | |
| 89 | + // SAFETY: Per assumption above, `ptr` is allocated by `__rust_*` before, and the size of | |
| 90 | + // `new_layout` is greater than 0. | |
| 91 | + unsafe { krealloc_aligned(ptr, new_layout, bindings::GFP_KERNEL) } | |
| 53 | 92 | } |
| 54 | 93 | |
| 55 | 94 | #[no_mangle] |
| 56 | −fn __rust_alloc_zeroed(size: usize, _align: usize) -> *mut u8 { | |
| 95 | +fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8 { | |
| 96 | + // SAFETY: See assumption above. | |
| 97 | + let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; | |
| 98 | + | |
| 99 | + // SAFETY: `ptr::null_mut()` is null, per assumption above the size of `layout` is greater | |
| 100 | + // than 0. | |
| 57 | 101 | unsafe { |
| 58 | − bindings::krealloc( | |
| 59 | − core::ptr::null(), | |
| 60 | − size, | |
| 102 | + krealloc_aligned( | |
| 103 | + ptr::null_mut(), | |
| 104 | + layout, | |
| 61 | 105 | bindings::GFP_KERNEL | bindings::__GFP_ZERO, |
| 62 | − ) as *mut u8 | |
| 106 | + ) | |
| 63 | 107 | } |
| 64 | 108 | } |
| @@ -243,8 +243,7 @@ impl<T: 'static> ForeignOwnable for Arc<T> { · 242 unmodified lines | ||
| 243 | 243 | let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap(); |
| 244 | 244 | |
| 245 | 245 | // SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive |
| 246 | − // for the lifetime of the returned value. Additionally, the safety requirements of | |
| 247 | − // `ForeignOwnable::borrow_mut` ensure that no new mutable references are created. | |
| 246 | + // for the lifetime of the returned value. | |
| 248 | 247 | unsafe { ArcBorrow::new(inner) } |
| 249 | 248 | } |
| 250 | 249 | |
| @@ -35,34 +35,16 @@ pub trait ForeignOwnable: Sized { · 34 unmodified lines | ||
| 35 | 35 | /// |
| 36 | 36 | /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for |
| 37 | 37 | /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. |
| 38 | − /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow_mut`] | |
| 39 | − /// for this object must have been dropped. | |
| 40 | 38 | unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>; |
| 41 | 39 | |
| 42 | − /// Mutably borrows a foreign-owned object. | |
| 43 | − /// | |
| 44 | − /// # Safety | |
| 45 | − /// | |
| 46 | − /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for | |
| 47 | − /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. | |
| 48 | − /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and | |
| 49 | − /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped. | |
| 50 | − unsafe fn borrow_mut(ptr: *const core::ffi::c_void) -> ScopeGuard<Self, fn(Self)> { | |
| 51 | − // SAFETY: The safety requirements ensure that `ptr` came from a previous call to | |
| 52 | − // `into_foreign`. | |
| 53 | − ScopeGuard::new_with_data(unsafe { Self::from_foreign(ptr) }, |d| { | |
| 54 | − d.into_foreign(); | |
| 55 | − }) | |
| 56 | − } | |
| 57 | − | |
| 58 | 40 | /// Converts a foreign-owned object back to a Rust-owned one. |
| 59 | 41 | /// |
| 60 | 42 | /// # Safety |
| 61 | 43 | /// |
| 62 | 44 | /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for |
| 63 | 45 | /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. |
| 64 | − /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] and | |
| 65 | − /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped. | |
| 46 | + /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] for | |
| 47 | + /// this object must have been dropped. | |
| 66 | 48 | unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self; |
| 67 | 49 | } |
| 68 | 50 | |
| @@ -129,6 +129,7 @@ static struct sym_entry *read_symbol(FILE *in, char **buf, size_t *buf_len) · 128 unmodified lines | ||
| 129 | 129 | ssize_t readlen; |
| 130 | 130 | struct sym_entry *sym; |
| 131 | 131 | |
| 132 | + errno = 0; | |
| 132 | 133 | readlen = getline(buf, buf_len, in); |
| 133 | 134 | if (readlen < 0) { |
| 134 | 135 | if (errno) { |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/sysctl.h> |
| 10 | 10 | #include "internal.h" |
| 11 | 11 | |
| 12 | −struct ctl_table key_sysctls[] = { | |
| 12 | +static struct ctl_table key_sysctls[] = { | |
| 13 | 13 | { |
| 14 | 14 | .procname = "maxkeys", |
| 15 | 15 | .data = &key_quota_maxkeys, |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | * Defines x86 CPU feature bits |
| 15 | 15 | */ |
| 16 | 16 | #define NCAPINTS 21 /* N 32-bit words worth of info */ |
| 17 | −#define NBUGINTS 1 /* N 32-bit bug flags */ | |
| 17 | +#define NBUGINTS 2 /* N 32-bit bug flags */ | |
| 18 | 18 | |
| 19 | 19 | /* |
| 20 | 20 | * Note: If the comment begins with a quoted string, that string is used |
| @@ -545,6 +545,7 @@ · 544 unmodified lines | ||
| 545 | 545 | #define MSR_AMD64_DE_CFG 0xc0011029 |
| 546 | 546 | #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT 1 |
| 547 | 547 | #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE BIT_ULL(MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT) |
| 548 | +#define MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT 9 | |
| 548 | 549 | |
| 549 | 550 | #define MSR_AMD64_BU_CFG2 0xc001102a |
| 550 | 551 | #define MSR_AMD64_IBSFETCHCTL 0xc0011030 |
| @@ -40,7 +40,8 @@ $(OUTPUT)counter_example: $(COUNTER_EXAMPLE) · 39 unmodified lines | ||
| 40 | 40 | clean: |
| 41 | 41 | rm -f $(ALL_PROGRAMS) |
| 42 | 42 | rm -rf $(OUTPUT)include/linux/counter.h |
| 43 | − rmdir -p $(OUTPUT)include/linux | |
| 43 | + rm -df $(OUTPUT)include/linux | |
| 44 | + rm -df $(OUTPUT)include | |
| 44 | 45 | find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete |
| 45 | 46 | |
| 46 | 47 | install: $(ALL_PROGRAMS) |
| @@ -164,7 +164,7 @@ def recursive_file_lookup(path, file_map): · 163 unmodified lines | ||
| 164 | 164 | def get_all_devices_test_status(file_map): |
| 165 | 165 | |
| 166 | 166 | for device in file_map: |
| 167 | − if (get_test_state(locate_state(device, file_map)) is 1): | |
| 167 | + if (get_test_state(locate_state(device, file_map)) == 1): | |
| 168 | 168 | print("Testing = ON for: {}" |
| 169 | 169 | .format(device.split("/")[5])) |
| 170 | 170 | else: |
| @@ -203,7 +203,7 @@ def write_test_files(path, value): · 32 unmodified lines | ||
| 203 | 203 | def set_test_state(state_path, state_value, quiet): |
| 204 | 204 | |
| 205 | 205 | write_test_files(state_path, state_value) |
| 206 | − if (get_test_state(state_path) is 1): | |
| 206 | + if (get_test_state(state_path) == 1): | |
| 207 | 207 | if (not quiet): |
| 208 | 208 | print("Testing = ON for device: {}" |
| 209 | 209 | .format(state_path.split("/")[5])) |
| @@ -824,5 +824,8 @@ bool arch_is_retpoline(struct symbol *sym) · 823 unmodified lines | ||
| 824 | 824 | |
| 825 | 825 | bool arch_is_rethunk(struct symbol *sym) |
| 826 | 826 | { |
| 827 | − return !strcmp(sym->name, "__x86_return_thunk"); | |
| 827 | + return !strcmp(sym->name, "__x86_return_thunk") || | |
| 828 | + !strcmp(sym->name, "srso_untrain_ret") || | |
| 829 | + !strcmp(sym->name, "srso_safe_ret") || | |
| 830 | + !strcmp(sym->name, "__ret"); | |
| 828 | 831 | } |
| @@ -54,10 +54,11 @@ double perf_pmu__cpu_slots_per_cycle(void) · 53 unmodified lines | ||
| 54 | 54 | perf_pmu__pathname_scnprintf(path, sizeof(path), |
| 55 | 55 | pmu->name, "caps/slots"); |
| 56 | 56 | /* |
| 57 | − * The value of slots is not greater than 32 bits, but sysfs__read_int | |
| 58 | − * can't read value with 0x prefix, so use sysfs__read_ull instead. | |
| 57 | + * The value of slots is not greater than 32 bits, but | |
| 58 | + * filename__read_int can't read value with 0x prefix, | |
| 59 | + * so use filename__read_ull instead. | |
| 59 | 60 | */ |
| 60 | − sysfs__read_ull(path, &slots); | |
| 61 | + filename__read_ull(path, &slots); | |
| 61 | 62 | } |
| 62 | 63 | |
| 63 | 64 | return slots ? (double)slots : NAN; |
| @@ -250,6 +250,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain) · 249 unmodified lines | ||
| 250 | 250 | if (!chain || chain->nr < 3) |
| 251 | 251 | return skip_slot; |
| 252 | 252 | |
| 253 | + addr_location__init(&al); | |
| 253 | 254 | ip = chain->ips[1]; |
| 254 | 255 | |
| 255 | 256 | thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); |
| @@ -259,6 +260,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain) · 3 unmodified lines | ||
| 259 | 260 | |
| 260 | 261 | if (!dso) { |
| 261 | 262 | pr_debug("%" PRIx64 " dso is NULL\n", ip); |
| 263 | + addr_location__exit(&al); | |
| 262 | 264 | return skip_slot; |
| 263 | 265 | } |
| 264 | 266 | |
| @@ -279,5 +281,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain) · 14 unmodified lines | ||
| 279 | 281 | */ |
| 280 | 282 | skip_slot = 3; |
| 281 | 283 | } |
| 284 | + | |
| 285 | + addr_location__exit(&al); | |
| 282 | 286 | return skip_slot; |
| 283 | 287 | } |
| @@ -1631,6 +1631,16 @@ static bool test__pmu_cpu_valid(void) · 1630 unmodified lines | ||
| 1631 | 1631 | return !!perf_pmus__find("cpu"); |
| 1632 | 1632 | } |
| 1633 | 1633 | |
| 1634 | +static bool test__pmu_cpu_event_valid(void) | |
| 1635 | +{ | |
| 1636 | + struct perf_pmu *pmu = perf_pmus__find("cpu"); | |
| 1637 | + | |
| 1638 | + if (!pmu) | |
| 1639 | + return false; | |
| 1640 | + | |
| 1641 | + return perf_pmu__has_format(pmu, "event"); | |
| 1642 | +} | |
| 1643 | + | |
| 1634 | 1644 | static bool test__intel_pt_valid(void) |
| 1635 | 1645 | { |
| 1636 | 1646 | return !!perf_pmus__find("intel_pt"); |
| @@ -2179,7 +2189,7 @@ static const struct evlist_test test__events_pmu[] = { · 542 unmodified lines | ||
| 2179 | 2189 | }, |
| 2180 | 2190 | { |
| 2181 | 2191 | .name = "cpu/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp", |
| 2182 | − .valid = test__pmu_cpu_valid, | |
| 2192 | + .valid = test__pmu_cpu_event_valid, | |
| 2183 | 2193 | .check = test__checkevent_complex_name, |
| 2184 | 2194 | /* 3 */ |
| 2185 | 2195 | }, |
| @@ -4,6 +4,12 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | set -e |
| 6 | 6 | |
| 7 | +# skip if there's no gcc | |
| 8 | +if ! [ -x "$(command -v gcc)" ]; then | |
| 9 | + echo "failed: no gcc compiler" | |
| 10 | + exit 2 | |
| 11 | +fi | |
| 12 | + | |
| 7 | 13 | temp_dir=$(mktemp -d /tmp/perf-uprobe-different-cu-sh.XXXXXXXXXX) |
| 8 | 14 | |
| 9 | 15 | cleanup() |
| @@ -11,7 +17,7 @@ cleanup() · 1 unmodified line | ||
| 11 | 17 | trap - EXIT TERM INT |
| 12 | 18 | if [[ "${temp_dir}" =~ ^/tmp/perf-uprobe-different-cu-sh.*$ ]]; then |
| 13 | 19 | echo "--- Cleaning up ---" |
| 14 | − perf probe -x ${temp_dir}/testfile -d foo | |
| 20 | + perf probe -x ${temp_dir}/testfile -d foo || true | |
| 15 | 21 | rm -f "${temp_dir}/"* |
| 16 | 22 | rmdir "${temp_dir}" |
| 17 | 23 | fi |
| @@ -45,7 +45,6 @@ · 44 unmodified lines | ||
| 45 | 45 | |
| 46 | 46 | static void __machine__remove_thread(struct machine *machine, struct thread_rb_node *nd, |
| 47 | 47 | struct thread *th, bool lock); |
| 48 | −static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip); | |
| 49 | 48 | |
| 50 | 49 | static struct dso *machine__kernel_dso(struct machine *machine) |
| 51 | 50 | { |
| @@ -2385,10 +2384,6 @@ static int add_callchain_ip(struct thread *thread, · 2333 unmodified lines | ||
| 2385 | 2384 | ms.maps = maps__get(al.maps); |
| 2386 | 2385 | ms.map = map__get(al.map); |
| 2387 | 2386 | ms.sym = al.sym; |
| 2388 | − | |
| 2389 | − if (!branch && append_inlines(cursor, &ms, ip) == 0) | |
| 2390 | − goto out; | |
| 2391 | − | |
| 2392 | 2387 | srcline = callchain_srcline(&ms, al.addr); |
| 2393 | 2388 | err = callchain_cursor_append(cursor, ip, &ms, |
| 2394 | 2389 | branch, flags, nr_loop_iter, |
| @@ -2100,16 +2100,16 @@ __weak int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs) · 2099 unmodified lines | ||
| 2100 | 2100 | return lhs->core.idx - rhs->core.idx; |
| 2101 | 2101 | } |
| 2102 | 2102 | |
| 2103 | −static int evlist__cmp(void *state, const struct list_head *l, const struct list_head *r) | |
| 2103 | +static int evlist__cmp(void *_fg_idx, const struct list_head *l, const struct list_head *r) | |
| 2104 | 2104 | { |
| 2105 | 2105 | const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node); |
| 2106 | 2106 | const struct evsel *lhs = container_of(lhs_core, struct evsel, core); |
| 2107 | 2107 | const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node); |
| 2108 | 2108 | const struct evsel *rhs = container_of(rhs_core, struct evsel, core); |
| 2109 | − int *leader_idx = state; | |
| 2110 | − int lhs_leader_idx = *leader_idx, rhs_leader_idx = *leader_idx, ret; | |
| 2109 | + int *force_grouped_idx = _fg_idx; | |
| 2110 | + int lhs_sort_idx, rhs_sort_idx, ret; | |
| 2111 | 2111 | const char *lhs_pmu_name, *rhs_pmu_name; |
| 2112 | − bool lhs_has_group = false, rhs_has_group = false; | |
| 2112 | + bool lhs_has_group, rhs_has_group; | |
| 2113 | 2113 | |
| 2114 | 2114 | /* |
| 2115 | 2115 | * First sort by grouping/leader. Read the leader idx only if the evsel |
| @@ -2121,15 +2121,25 @@ static int evlist__cmp(void *state, const struct list_head *l, const struct list · 5 unmodified lines | ||
| 2121 | 2121 | */ |
| 2122 | 2122 | if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) { |
| 2123 | 2123 | lhs_has_group = true; |
| 2124 | − lhs_leader_idx = lhs_core->leader->idx; | |
| 2124 | + lhs_sort_idx = lhs_core->leader->idx; | |
| 2125 | + } else { | |
| 2126 | + lhs_has_group = false; | |
| 2127 | + lhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(lhs) | |
| 2128 | + ? *force_grouped_idx | |
| 2129 | + : lhs_core->idx; | |
| 2125 | 2130 | } |
| 2126 | 2131 | if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) { |
| 2127 | 2132 | rhs_has_group = true; |
| 2128 | − rhs_leader_idx = rhs_core->leader->idx; | |
| 2133 | + rhs_sort_idx = rhs_core->leader->idx; | |
| 2134 | + } else { | |
| 2135 | + rhs_has_group = false; | |
| 2136 | + rhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(rhs) | |
| 2137 | + ? *force_grouped_idx | |
| 2138 | + : rhs_core->idx; | |
| 2129 | 2139 | } |
| 2130 | 2140 | |
| 2131 | − if (lhs_leader_idx != rhs_leader_idx) | |
| 2132 | − return lhs_leader_idx - rhs_leader_idx; | |
| 2141 | + if (lhs_sort_idx != rhs_sort_idx) | |
| 2142 | + return lhs_sort_idx - rhs_sort_idx; | |
| 2133 | 2143 | |
| 2134 | 2144 | /* Group by PMU if there is a group. Groups can't span PMUs. */ |
| 2135 | 2145 | if (lhs_has_group && rhs_has_group) { |
| @@ -2146,10 +2156,10 @@ static int evlist__cmp(void *state, const struct list_head *l, const struct list · 10 unmodified lines | ||
| 2146 | 2156 | |
| 2147 | 2157 | static int parse_events__sort_events_and_fix_groups(struct list_head *list) |
| 2148 | 2158 | { |
| 2149 | − int idx = 0, unsorted_idx = -1; | |
| 2159 | + int idx = 0, force_grouped_idx = -1; | |
| 2150 | 2160 | struct evsel *pos, *cur_leader = NULL; |
| 2151 | 2161 | struct perf_evsel *cur_leaders_grp = NULL; |
| 2152 | − bool idx_changed = false; | |
| 2162 | + bool idx_changed = false, cur_leader_force_grouped = false; | |
| 2153 | 2163 | int orig_num_leaders = 0, num_leaders = 0; |
| 2154 | 2164 | int ret; |
| 2155 | 2165 | |
| @@ -2174,12 +2184,14 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list) · 18 unmodified lines | ||
| 2174 | 2184 | */ |
| 2175 | 2185 | pos->core.idx = idx++; |
| 2176 | 2186 | |
| 2177 | − if (unsorted_idx == -1 && pos == pos_leader && pos->core.nr_members < 2) | |
| 2178 | − unsorted_idx = pos->core.idx; | |
| 2187 | + /* Remember an index to sort all forced grouped events together to. */ | |
| 2188 | + if (force_grouped_idx == -1 && pos == pos_leader && pos->core.nr_members < 2 && | |
| 2189 | + arch_evsel__must_be_in_group(pos)) | |
| 2190 | + force_grouped_idx = pos->core.idx; | |
| 2179 | 2191 | } |
| 2180 | 2192 | |
| 2181 | 2193 | /* Sort events. */ |
| 2182 | − list_sort(&unsorted_idx, list, evlist__cmp); | |
| 2194 | + list_sort(&force_grouped_idx, list, evlist__cmp); | |
| 2183 | 2195 | |
| 2184 | 2196 | /* |
| 2185 | 2197 | * Recompute groups, splitting for PMUs and adding groups for events |
| @@ -2189,8 +2201,9 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list) · 3 unmodified lines | ||
| 2189 | 2201 | list_for_each_entry(pos, list, core.node) { |
| 2190 | 2202 | const struct evsel *pos_leader = evsel__leader(pos); |
| 2191 | 2203 | const char *pos_pmu_name = pos->group_pmu_name; |
| 2192 | − const char *cur_leader_pmu_name, *pos_leader_pmu_name; | |
| 2193 | − bool force_grouped = arch_evsel__must_be_in_group(pos); | |
| 2204 | + const char *cur_leader_pmu_name; | |
| 2205 | + bool pos_force_grouped = force_grouped_idx != -1 && | |
| 2206 | + arch_evsel__must_be_in_group(pos); | |
| 2194 | 2207 | |
| 2195 | 2208 | /* Reset index and nr_members. */ |
| 2196 | 2209 | if (pos->core.idx != idx) |
| @@ -2206,7 +2219,8 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list) · 9 unmodified lines | ||
| 2206 | 2219 | cur_leader = pos; |
| 2207 | 2220 | |
| 2208 | 2221 | cur_leader_pmu_name = cur_leader->group_pmu_name; |
| 2209 | − if ((cur_leaders_grp != pos->core.leader && !force_grouped) || | |
| 2222 | + if ((cur_leaders_grp != pos->core.leader && | |
| 2223 | + (!pos_force_grouped || !cur_leader_force_grouped)) || | |
| 2210 | 2224 | strcmp(cur_leader_pmu_name, pos_pmu_name)) { |
| 2211 | 2225 | /* Event is for a different group/PMU than last. */ |
| 2212 | 2226 | cur_leader = pos; |
| @@ -2216,14 +2230,14 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list) · 3 unmodified lines | ||
| 2216 | 2230 | * group. |
| 2217 | 2231 | */ |
| 2218 | 2232 | cur_leaders_grp = pos->core.leader; |
| 2219 | − } | |
| 2220 | − pos_leader_pmu_name = pos_leader->group_pmu_name; | |
| 2221 | − if (strcmp(pos_leader_pmu_name, pos_pmu_name) || force_grouped) { | |
| 2222 | 2233 | /* |
| 2223 | − * Event's PMU differs from its leader's. Groups can't | |
| 2224 | − * span PMUs, so update leader from the group/PMU | |
| 2225 | − * tracker. | |
| 2234 | + * Avoid forcing events into groups with events that | |
| 2235 | + * don't need to be in the group. | |
| 2226 | 2236 | */ |
| 2237 | + cur_leader_force_grouped = pos_force_grouped; | |
| 2238 | + } | |
| 2239 | + if (pos_leader != cur_leader) { | |
| 2240 | + /* The leader changed so update it. */ | |
| 2227 | 2241 | evsel__set_leader(pos, cur_leader); |
| 2228 | 2242 | } |
| 2229 | 2243 | } |
| @@ -1440,6 +1440,17 @@ void perf_pmu__del_formats(struct list_head *formats) · 1439 unmodified lines | ||
| 1440 | 1440 | } |
| 1441 | 1441 | } |
| 1442 | 1442 | |
| 1443 | +bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name) | |
| 1444 | +{ | |
| 1445 | + struct perf_pmu_format *format; | |
| 1446 | + | |
| 1447 | + list_for_each_entry(format, &pmu->format, list) { | |
| 1448 | + if (!strcmp(format->name, name)) | |
| 1449 | + return true; | |
| 1450 | + } | |
| 1451 | + return false; | |
| 1452 | +} | |
| 1453 | + | |
| 1443 | 1454 | bool is_pmu_core(const char *name) |
| 1444 | 1455 | { |
| 1445 | 1456 | return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name); |
| @@ -234,6 +234,7 @@ int perf_pmu__new_format(struct list_head *list, char *name, · 233 unmodified lines | ||
| 234 | 234 | void perf_pmu__set_format(unsigned long *bits, long from, long to); |
| 235 | 235 | int perf_pmu__format_parse(int dirfd, struct list_head *head); |
| 236 | 236 | void perf_pmu__del_formats(struct list_head *formats); |
| 237 | +bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name); | |
| 237 | 238 | |
| 238 | 239 | bool is_pmu_core(const char *name); |
| 239 | 240 | bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu); |
| @@ -152,16 +152,14 @@ static void pmu_read_sysfs(bool core_only) · 151 unmodified lines | ||
| 152 | 152 | } |
| 153 | 153 | |
| 154 | 154 | closedir(dir); |
| 155 | − if (core_only) { | |
| 156 | − if (!list_empty(&core_pmus)) | |
| 157 | − read_sysfs_core_pmus = true; | |
| 158 | − else { | |
| 159 | − if (perf_pmu__create_placeholder_core_pmu(&core_pmus)) | |
| 160 | − read_sysfs_core_pmus = true; | |
| 161 | − } | |
| 162 | − } else { | |
| 155 | + if (list_empty(&core_pmus)) { | |
| 156 | + if (!perf_pmu__create_placeholder_core_pmu(&core_pmus)) | |
| 157 | + pr_err("Failure to set up any core PMUs\n"); | |
| 158 | + } | |
| 159 | + if (!list_empty(&core_pmus)) { | |
| 163 | 160 | read_sysfs_core_pmus = true; |
| 164 | − read_sysfs_all_pmus = true; | |
| 161 | + if (!core_only) | |
| 162 | + read_sysfs_all_pmus = true; | |
| 165 | 163 | } |
| 166 | 164 | } |
| 167 | 165 | |
| @@ -931,6 +931,11 @@ static bool should_skip_zero_counter(struct perf_stat_config *config, · 930 unmodified lines | ||
| 931 | 931 | */ |
| 932 | 932 | if (config->aggr_mode == AGGR_THREAD && config->system_wide) |
| 933 | 933 | return true; |
| 934 | + | |
| 935 | + /* Tool events have the software PMU but are only gathered on 1. */ | |
| 936 | + if (evsel__is_tool(counter)) | |
| 937 | + return true; | |
| 938 | + | |
| 934 | 939 | /* |
| 935 | 940 | * Skip value 0 when it's an uncore event and the given aggr id |
| 936 | 941 | * does not belong to the PMU cpumask. |
| @@ -177,7 +177,7 @@ void regression1_test(void) · 176 unmodified lines | ||
| 177 | 177 | nr_threads = 2; |
| 178 | 178 | pthread_barrier_init(&worker_barrier, NULL, nr_threads); |
| 179 | 179 | |
| 180 | − threads = malloc(nr_threads * sizeof(pthread_t *)); | |
| 180 | + threads = malloc(nr_threads * sizeof(*threads)); | |
| 181 | 181 | |
| 182 | 182 | for (i = 0; i < nr_threads; i++) { |
| 183 | 183 | arg = i; |
| @@ -869,6 +869,77 @@ static void test_msg_redir_to_listening(struct test_sockmap_listen *skel, · 868 unmodified lines | ||
| 869 | 869 | xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT); |
| 870 | 870 | } |
| 871 | 871 | |
| 872 | +static void redir_partial(int family, int sotype, int sock_map, int parser_map) | |
| 873 | +{ | |
| 874 | + int s, c0, c1, p0, p1; | |
| 875 | + int err, n, key, value; | |
| 876 | + char buf[] = "abc"; | |
| 877 | + | |
| 878 | + key = 0; | |
| 879 | + value = sizeof(buf) - 1; | |
| 880 | + err = xbpf_map_update_elem(parser_map, &key, &value, 0); | |
| 881 | + if (err) | |
| 882 | + return; | |
| 883 | + | |
| 884 | + s = socket_loopback(family, sotype | SOCK_NONBLOCK); | |
| 885 | + if (s < 0) | |
| 886 | + goto clean_parser_map; | |
| 887 | + | |
| 888 | + err = create_socket_pairs(s, family, sotype, &c0, &c1, &p0, &p1); | |
| 889 | + if (err) | |
| 890 | + goto close_srv; | |
| 891 | + | |
| 892 | + err = add_to_sockmap(sock_map, p0, p1); | |
| 893 | + if (err) | |
| 894 | + goto close; | |
| 895 | + | |
| 896 | + n = xsend(c1, buf, sizeof(buf), 0); | |
| 897 | + if (n < sizeof(buf)) | |
| 898 | + FAIL("incomplete write"); | |
| 899 | + | |
| 900 | + n = xrecv_nonblock(c0, buf, sizeof(buf), 0); | |
| 901 | + if (n != sizeof(buf) - 1) | |
| 902 | + FAIL("expect %zu, received %d", sizeof(buf) - 1, n); | |
| 903 | + | |
| 904 | +close: | |
| 905 | + xclose(c0); | |
| 906 | + xclose(p0); | |
| 907 | + xclose(c1); | |
| 908 | + xclose(p1); | |
| 909 | +close_srv: | |
| 910 | + xclose(s); | |
| 911 | + | |
| 912 | +clean_parser_map: | |
| 913 | + key = 0; | |
| 914 | + value = 0; | |
| 915 | + xbpf_map_update_elem(parser_map, &key, &value, 0); | |
| 916 | +} | |
| 917 | + | |
| 918 | +static void test_skb_redir_partial(struct test_sockmap_listen *skel, | |
| 919 | + struct bpf_map *inner_map, int family, | |
| 920 | + int sotype) | |
| 921 | +{ | |
| 922 | + int verdict = bpf_program__fd(skel->progs.prog_stream_verdict); | |
| 923 | + int parser = bpf_program__fd(skel->progs.prog_stream_parser); | |
| 924 | + int parser_map = bpf_map__fd(skel->maps.parser_map); | |
| 925 | + int sock_map = bpf_map__fd(inner_map); | |
| 926 | + int err; | |
| 927 | + | |
| 928 | + err = xbpf_prog_attach(parser, sock_map, BPF_SK_SKB_STREAM_PARSER, 0); | |
| 929 | + if (err) | |
| 930 | + return; | |
| 931 | + | |
| 932 | + err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT, 0); | |
| 933 | + if (err) | |
| 934 | + goto detach; | |
| 935 | + | |
| 936 | + redir_partial(family, sotype, sock_map, parser_map); | |
| 937 | + | |
| 938 | + xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT); | |
| 939 | +detach: | |
| 940 | + xbpf_prog_detach2(parser, sock_map, BPF_SK_SKB_STREAM_PARSER); | |
| 941 | +} | |
| 942 | + | |
| 872 | 943 | static void test_reuseport_select_listening(int family, int sotype, |
| 873 | 944 | int sock_map, int verd_map, |
| 874 | 945 | int reuseport_prog) |
| @@ -1243,6 +1314,7 @@ static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map, · 368 unmodified lines | ||
| 1243 | 1314 | } tests[] = { |
| 1244 | 1315 | TEST(test_skb_redir_to_connected), |
| 1245 | 1316 | TEST(test_skb_redir_to_listening), |
| 1317 | + TEST(test_skb_redir_partial), | |
| 1246 | 1318 | TEST(test_msg_redir_to_connected), |
| 1247 | 1319 | TEST(test_msg_redir_to_listening), |
| 1248 | 1320 | }; |
| @@ -1432,7 +1504,7 @@ static void vsock_unix_redir_connectible(int sock_mapfd, int verd_mapfd, · 183 unmodified lines | ||
| 1432 | 1504 | if (n < 1) |
| 1433 | 1505 | goto out; |
| 1434 | 1506 | |
| 1435 | − n = recv(mode == REDIR_INGRESS ? u0 : u1, &b, sizeof(b), MSG_DONTWAIT); | |
| 1507 | + n = xrecv_nonblock(mode == REDIR_INGRESS ? u0 : u1, &b, sizeof(b), 0); | |
| 1436 | 1508 | if (n < 0) |
| 1437 | 1509 | FAIL("%s: recv() err, errno=%d", log_prefix, errno); |
| 1438 | 1510 | if (n == 0) |
| @@ -28,12 +28,26 @@ struct { · 27 unmodified lines | ||
| 28 | 28 | __type(value, unsigned int); |
| 29 | 29 | } verdict_map SEC(".maps"); |
| 30 | 30 | |
| 31 | +struct { | |
| 32 | + __uint(type, BPF_MAP_TYPE_ARRAY); | |
| 33 | + __uint(max_entries, 1); | |
| 34 | + __type(key, int); | |
| 35 | + __type(value, int); | |
| 36 | +} parser_map SEC(".maps"); | |
| 37 | + | |
| 31 | 38 | bool test_sockmap = false; /* toggled by user-space */ |
| 32 | 39 | bool test_ingress = false; /* toggled by user-space */ |
| 33 | 40 | |
| 34 | 41 | SEC("sk_skb/stream_parser") |
| 35 | 42 | int prog_stream_parser(struct __sk_buff *skb) |
| 36 | 43 | { |
| 44 | + int *value; | |
| 45 | + __u32 key = 0; | |
| 46 | + | |
| 47 | + value = bpf_map_lookup_elem(&parser_map, &key); | |
| 48 | + if (value && *value) | |
| 49 | + return *value; | |
| 50 | + | |
| 37 | 51 | return skb->len; |
| 38 | 52 | } |
| 39 | 53 | |
| @@ -70,6 +70,10 @@ static int test_kmem_basic(const char *root) · 69 unmodified lines | ||
| 70 | 70 | goto cleanup; |
| 71 | 71 | |
| 72 | 72 | cg_write(cg, "memory.high", "1M"); |
| 73 | + | |
| 74 | + /* wait for RCU freeing */ | |
| 75 | + sleep(1); | |
| 76 | + | |
| 73 | 77 | slab1 = cg_read_key_long(cg, "memory.stat", "slab "); |
| 74 | 78 | if (slab1 <= 0) |
| 75 | 79 | goto cleanup; |
| @@ -831,6 +831,7 @@ int main(int argc, char *argv[]) · 830 unmodified lines | ||
| 831 | 831 | printf("Size must be greater than 0\n"); |
| 832 | 832 | return KSFT_FAIL; |
| 833 | 833 | } |
| 834 | + break; | |
| 834 | 835 | case 't': |
| 835 | 836 | { |
| 836 | 837 | int tmp = atoi(optarg); |
| @@ -1981,6 +1981,11 @@ basic() · 1980 unmodified lines | ||
| 1981 | 1981 | |
| 1982 | 1982 | run_cmd "$IP link set dev lo up" |
| 1983 | 1983 | |
| 1984 | + # Dump should not loop endlessly when maximum nexthop ID is configured. | |
| 1985 | + run_cmd "$IP nexthop add id $((2**32-1)) blackhole" | |
| 1986 | + run_cmd "timeout 5 $IP nexthop" | |
| 1987 | + log_test $? 0 "Maximum nexthop ID dump" | |
| 1988 | + | |
| 1984 | 1989 | # |
| 1985 | 1990 | # groups |
| 1986 | 1991 | # |
| @@ -2201,6 +2206,11 @@ basic_res() · 214 unmodified lines | ||
| 2201 | 2206 | run_cmd "$IP nexthop bucket list fdb" |
| 2202 | 2207 | log_test $? 255 "Dump all nexthop buckets with invalid 'fdb' keyword" |
| 2203 | 2208 | |
| 2209 | + # Dump should not loop endlessly when maximum nexthop ID is configured. | |
| 2210 | + run_cmd "$IP nexthop add id $((2**32-1)) group 1/2 type resilient buckets 4" | |
| 2211 | + run_cmd "timeout 5 $IP nexthop bucket" | |
| 2212 | + log_test $? 0 "Maximum nexthop ID dump" | |
| 2213 | + | |
| 2204 | 2214 | # |
| 2205 | 2215 | # resilient nexthop buckets get requests |
| 2206 | 2216 | # |
| @@ -617,7 +617,7 @@ __cfg_test_port_ip_sg() · 616 unmodified lines | ||
| 617 | 617 | grep -q "permanent" |
| 618 | 618 | check_err $? "Entry not added as \"permanent\" when should" |
| 619 | 619 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ |
| 620 | − grep -q "0.00" | |
| 620 | + grep -q " 0.00" | |
| 621 | 621 | check_err $? "\"permanent\" entry has a pending group timer" |
| 622 | 622 | bridge mdb del dev br0 port $swp1 $grp_key vid 10 |
| 623 | 623 | |
| @@ -626,7 +626,7 @@ __cfg_test_port_ip_sg() · 2 unmodified lines | ||
| 626 | 626 | grep -q "temp" |
| 627 | 627 | check_err $? "Entry not added as \"temp\" when should" |
| 628 | 628 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ |
| 629 | − grep -q "0.00" | |
| 629 | + grep -q " 0.00" | |
| 630 | 630 | check_fail $? "\"temp\" entry has an unpending group timer" |
| 631 | 631 | bridge mdb del dev br0 port $swp1 $grp_key vid 10 |
| 632 | 632 | |
| @@ -659,7 +659,7 @@ __cfg_test_port_ip_sg() · 26 unmodified lines | ||
| 659 | 659 | grep -q "permanent" |
| 660 | 660 | check_err $? "Entry not marked as \"permanent\" after replace" |
| 661 | 661 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ |
| 662 | − grep -q "0.00" | |
| 662 | + grep -q " 0.00" | |
| 663 | 663 | check_err $? "Entry has a pending group timer after replace" |
| 664 | 664 | |
| 665 | 665 | bridge mdb replace dev br0 port $swp1 $grp_key vid 10 temp |
| @@ -667,7 +667,7 @@ __cfg_test_port_ip_sg() · 1 unmodified line | ||
| 667 | 667 | grep -q "temp" |
| 668 | 668 | check_err $? "Entry not marked as \"temp\" after replace" |
| 669 | 669 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ |
| 670 | − grep -q "0.00" | |
179 more lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 2 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.