We need the USB and Thunderbolt fixes in here to build on.
Unified · Split
| @@ -82,7 +82,12 @@ Description: · 81 unmodified lines | |||
| 82 | whether it resides in persistent capacity, volatile capacity, | 82 | whether it resides in persistent capacity, volatile capacity, |
| 83 | or the LSA, is made permanently unavailable by whatever means | 83 | or the LSA, is made permanently unavailable by whatever means |
| 84 | is appropriate for the media type. This functionality requires | 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 | What /sys/bus/cxl/devices/memX/security/erase | 93 | What /sys/bus/cxl/devices/memX/security/erase |
| @@ -92,7 +97,13 @@ Contact: linux-cxl@vger.kernel.org · 3 unmodified lines | |||
| 92 | Description: | 97 | Description: |
| 93 | (WO) Write a boolean 'true' string value to this attribute to | 98 | (WO) Write a boolean 'true' string value to this attribute to |
| 94 | secure erase user data by changing the media encryption keys for | 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 | What: /sys/bus/cxl/devices/memX/firmware/ | 109 | What: /sys/bus/cxl/devices/memX/firmware/ |
| @@ -513,17 +513,18 @@ Description: information about CPUs heterogeneity. · 512 unmodified lines | |||
| 513 | cpu_capacity: capacity of cpuX. | 513 | cpu_capacity: capacity of cpuX. |
| 514 | 514 | ||
| 515 | What: /sys/devices/system/cpu/vulnerabilities | 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 | /sys/devices/system/cpu/vulnerabilities/meltdown | 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 | /sys/devices/system/cpu/vulnerabilities/spectre_v1 | 524 | /sys/devices/system/cpu/vulnerabilities/spectre_v1 |
| 518 | /sys/devices/system/cpu/vulnerabilities/spectre_v2 | 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 | /sys/devices/system/cpu/vulnerabilities/srbds | 526 | /sys/devices/system/cpu/vulnerabilities/srbds |
| 523 | /sys/devices/system/cpu/vulnerabilities/tsx_async_abort | 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 | Date: January 2018 | 528 | Date: January 2018 |
| 528 | Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org> | 529 | Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org> |
| 529 | Description: Information about CPU vulnerabilities | 530 | Description: Information about CPU vulnerabilities |
| @@ -2,7 +2,7 @@ What: /sys/devices/platform/hidma-*/chid · 1 unmodified line | |||
| 2 | /sys/devices/platform/QCOM8061:*/chid | 2 | /sys/devices/platform/QCOM8061:*/chid |
| 3 | Date: Dec 2015 | 3 | Date: Dec 2015 |
| 4 | KernelVersion: 4.4 | 4 | KernelVersion: 4.4 |
| 5 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 5 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 6 | Description: | 6 | Description: |
| 7 | Contains the ID of the channel within the HIDMA instance. | 7 | Contains the ID of the channel within the HIDMA instance. |
| 8 | It is used to associate a given HIDMA channel with the | 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 | /sys/devices/platform/QCOM8060:*/chanops/chan*/priority | 2 | /sys/devices/platform/QCOM8060:*/chanops/chan*/priority |
| 3 | Date: Nov 2015 | 3 | Date: Nov 2015 |
| 4 | KernelVersion: 4.4 | 4 | KernelVersion: 4.4 |
| 5 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 5 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 6 | Description: | 6 | Description: |
| 7 | Contains either 0 or 1 and indicates if the DMA channel is a | 7 | Contains either 0 or 1 and indicates if the DMA channel is a |
| 8 | low priority (0) or high priority (1) channel. | 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 | /sys/devices/platform/QCOM8060:*/chanops/chan*/weight | 11 | /sys/devices/platform/QCOM8060:*/chanops/chan*/weight |
| 12 | Date: Nov 2015 | 12 | Date: Nov 2015 |
| 13 | KernelVersion: 4.4 | 13 | KernelVersion: 4.4 |
| 14 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 14 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 15 | Description: | 15 | Description: |
| 16 | Contains 0..15 and indicates the weight of the channel among | 16 | Contains 0..15 and indicates the weight of the channel among |
| 17 | equal priority channels during round robin scheduling. | 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 | /sys/devices/platform/QCOM8060:*/chreset_timeout_cycles | 20 | /sys/devices/platform/QCOM8060:*/chreset_timeout_cycles |
| 21 | Date: Nov 2015 | 21 | Date: Nov 2015 |
| 22 | KernelVersion: 4.4 | 22 | KernelVersion: 4.4 |
| 23 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 23 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 24 | Description: | 24 | Description: |
| 25 | Contains the platform specific cycle value to wait after a | 25 | Contains the platform specific cycle value to wait after a |
| 26 | reset command is issued. If the value is chosen too short, | 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 | /sys/devices/platform/QCOM8060:*/dma_channels | 32 | /sys/devices/platform/QCOM8060:*/dma_channels |
| 33 | Date: Nov 2015 | 33 | Date: Nov 2015 |
| 34 | KernelVersion: 4.4 | 34 | KernelVersion: 4.4 |
| 35 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 35 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 36 | Description: | 36 | Description: |
| 37 | Contains the number of dma channels supported by one instance | 37 | Contains the number of dma channels supported by one instance |
| 38 | of HIDMA hardware. The value may change from chip to chip. | 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 | /sys/devices/platform/QCOM8060:*/hw_version_major | 41 | /sys/devices/platform/QCOM8060:*/hw_version_major |
| 42 | Date: Nov 2015 | 42 | Date: Nov 2015 |
| 43 | KernelVersion: 4.4 | 43 | KernelVersion: 4.4 |
| 44 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 44 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 45 | Description: | 45 | Description: |
| 46 | Version number major for the hardware. | 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 | /sys/devices/platform/QCOM8060:*/hw_version_minor | 49 | /sys/devices/platform/QCOM8060:*/hw_version_minor |
| 50 | Date: Nov 2015 | 50 | Date: Nov 2015 |
| 51 | KernelVersion: 4.4 | 51 | KernelVersion: 4.4 |
| 52 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 52 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 53 | Description: | 53 | Description: |
| 54 | Version number minor for the hardware. | 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 | /sys/devices/platform/QCOM8060:*/max_rd_xactions | 57 | /sys/devices/platform/QCOM8060:*/max_rd_xactions |
| 58 | Date: Nov 2015 | 58 | Date: Nov 2015 |
| 59 | KernelVersion: 4.4 | 59 | KernelVersion: 4.4 |
| 60 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 60 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 61 | Description: | 61 | Description: |
| 62 | Contains a value between 0 and 31. Maximum number of | 62 | Contains a value between 0 and 31. Maximum number of |
| 63 | read transactions that can be issued back to back. | 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 | /sys/devices/platform/QCOM8060:*/max_read_request | 69 | /sys/devices/platform/QCOM8060:*/max_read_request |
| 70 | Date: Nov 2015 | 70 | Date: Nov 2015 |
| 71 | KernelVersion: 4.4 | 71 | KernelVersion: 4.4 |
| 72 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 72 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 73 | Description: | 73 | Description: |
| 74 | Size of each read request. The value needs to be a power | 74 | Size of each read request. The value needs to be a power |
| 75 | of two and can be between 128 and 1024. | 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 | /sys/devices/platform/QCOM8060:*/max_wr_xactions | 78 | /sys/devices/platform/QCOM8060:*/max_wr_xactions |
| 79 | Date: Nov 2015 | 79 | Date: Nov 2015 |
| 80 | KernelVersion: 4.4 | 80 | KernelVersion: 4.4 |
| 81 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 81 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 82 | Description: | 82 | Description: |
| 83 | Contains a value between 0 and 31. Maximum number of | 83 | Contains a value between 0 and 31. Maximum number of |
| 84 | write transactions that can be issued back to back. | 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 | /sys/devices/platform/QCOM8060:*/max_write_request | 91 | /sys/devices/platform/QCOM8060:*/max_write_request |
| 92 | Date: Nov 2015 | 92 | Date: Nov 2015 |
| 93 | KernelVersion: 4.4 | 93 | KernelVersion: 4.4 |
| 94 | Contact: "Sinan Kaya <okaya@codeaurora.org>" | 94 | Contact: "Sinan Kaya <okaya@kernel.org>" |
| 95 | Description: | 95 | Description: |
| 96 | Size of each write request. The value needs to be a power | 96 | Size of each write request. The value needs to be a power |
| 97 | of two and can be between 128 and 1024. | 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 | l1tf | 13 | l1tf |
| 14 | mds | 14 | mds |
| 15 | tsx_async_abort | 15 | tsx_async_abort |
| 16 | multihit.rst | 16 | multihit |
| 17 | special-register-buffer-data-sampling.rst | 17 | special-register-buffer-data-sampling |
| 18 | core-scheduling.rst | 18 | core-scheduling |
| 19 | l1d_flush.rst | 19 | l1d_flush |
| 20 | processor_mmio_stale_data.rst | 20 | processor_mmio_stale_data |
| 21 | cross-thread-rsb.rst | 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 | * VMALLOC_START ~ VMALLOC_END : vmalloc() / ioremap() space. | 624 | * VMALLOC_START ~ VMALLOC_END : vmalloc() / ioremap() space. |
| 625 | * VMEMMAP_START ~ VMEMMAP_END : vmemmap space, used for struct page array. | 625 | * VMEMMAP_START ~ VMEMMAP_END : vmemmap space, used for struct page array. |
| 626 | * KERNEL_LINK_ADDR : start address of Kernel link and BPF | 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 | Format: off | on | 1623 | Format: off | on |
| 1624 | default: on | 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 | gcov_persist= [GCOV] When non-zero (default), profiling data for | 1646 | gcov_persist= [GCOV] When non-zero (default), profiling data for |
| 1627 | kernel modules is saved and remains accessible via | 1647 | kernel modules is saved and remains accessible via |
| 1628 | debugfs, even when the module is unloaded/reloaded. | 1648 | debugfs, even when the module is unloaded/reloaded. |
| @@ -3273,24 +3293,25 @@ · 1644 unmodified lines | |||
| 3273 | Disable all optional CPU mitigations. This | 3293 | Disable all optional CPU mitigations. This |
| 3274 | improves system performance, but it may also | 3294 | improves system performance, but it may also |
| 3275 | expose users to several CPU vulnerabilities. | 3295 | expose users to several CPU vulnerabilities. |
| 3276 | Equivalent to: nopti [X86,PPC] | 3296 | Equivalent to: if nokaslr then kpti=0 [ARM64] |
| 3277 | if nokaslr then kpti=0 [ARM64] | 3297 | gather_data_sampling=off [X86] |
| 3278 | nospectre_v1 [X86,PPC] | 3298 | kvm.nx_huge_pages=off [X86] |
| 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] | ||
| 3285 | l1tf=off [X86] | 3299 | l1tf=off [X86] |
| 3286 | mds=off [X86] | 3300 | mds=off [X86] |
| 3287 | tsx_async_abort=off [X86] | 3301 | mmio_stale_data=off [X86] |
| 3288 | kvm.nx_huge_pages=off [X86] | ||
| 3289 | srbds=off [X86,INTEL] | ||
| 3290 | no_entry_flush [PPC] | 3302 | no_entry_flush [PPC] |
| 3291 | no_uaccess_flush [PPC] | 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 | retbleed=off [X86] | 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 | Exceptions: | 3316 | Exceptions: |
| 3296 | This does not have any effect on | 3317 | This does not have any effect on |
| @@ -5875,6 +5896,17 @@ · 2578 unmodified lines | |||
| 5875 | Not specifying this option is equivalent to | 5896 | Not specifying this option is equivalent to |
| 5876 | spectre_v2_user=auto. | 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 | spec_store_bypass_disable= | 5910 | spec_store_bypass_disable= |
| 5879 | [HW] Control Speculative Store Bypass (SSB) Disable mitigation | 5911 | [HW] Control Speculative Store Bypass (SSB) Disable mitigation |
| 5880 | (Speculative Store Bypass vulnerability) | 5912 | (Speculative Store Bypass vulnerability) |
| @@ -216,7 +216,6 @@ properties: · 215 unmodified lines | |||
| 216 | description: Whether to enable burnout current for EXT1. | 216 | description: Whether to enable burnout current for EXT1. |
| 217 | 217 | ||
| 218 | adi,ext1-burnout-current-nanoamp: | 218 | adi,ext1-burnout-current-nanoamp: |
| 219 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 220 | description: | 219 | description: |
| 221 | Burnout current in nanoamps to be applied to EXT1. | 220 | Burnout current in nanoamps to be applied to EXT1. |
| 222 | enum: [0, 50, 500, 1000, 10000] | 221 | enum: [0, 50, 500, 1000, 10000] |
| @@ -233,7 +232,6 @@ properties: · 10 unmodified lines | |||
| 233 | description: Whether to enable burnout current for EXT2. | 232 | description: Whether to enable burnout current for EXT2. |
| 234 | 233 | ||
| 235 | adi,ext2-burnout-current-nanoamp: | 234 | adi,ext2-burnout-current-nanoamp: |
| 236 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 237 | description: Burnout current in nanoamps to be applied to EXT2. | 235 | description: Burnout current in nanoamps to be applied to EXT2. |
| 238 | enum: [0, 50, 500, 1000, 10000] | 236 | enum: [0, 50, 500, 1000, 10000] |
| 239 | default: 0 | 237 | default: 0 |
| @@ -249,7 +247,6 @@ properties: · 9 unmodified lines | |||
| 249 | description: Whether to enable burnout current for VIOUT. | 247 | description: Whether to enable burnout current for VIOUT. |
| 250 | 248 | ||
| 251 | adi,viout-burnout-current-nanoamp: | 249 | adi,viout-burnout-current-nanoamp: |
| 252 | $ref: /schemas/types.yaml#/definitions/uint32 | ||
| 253 | description: Burnout current in nanoamps to be applied to VIOUT. | 250 | description: Burnout current in nanoamps to be applied to VIOUT. |
| 254 | enum: [0, 1000, 10000] | 251 | enum: [0, 1000, 10000] |
| 255 | default: 0 | 252 | default: 0 |
| @@ -293,7 +293,7 @@ allOf: · 292 unmodified lines | |||
| 293 | patternProperties: | 293 | patternProperties: |
| 294 | "^mac@[0-1]$": | 294 | "^mac@[0-1]$": |
| 295 | type: object | 295 | type: object |
| 296 | additionalProperties: false | 296 | unevaluatedProperties: false |
| 297 | allOf: | 297 | allOf: |
| 298 | - $ref: ethernet-controller.yaml# | 298 | - $ref: ethernet-controller.yaml# |
| 299 | description: | 299 | description: |
| @@ -305,14 +305,9 @@ patternProperties: · 5 unmodified lines | |||
| 305 | reg: | 305 | reg: |
| 306 | maxItems: 1 | 306 | maxItems: 1 |
| 307 | 307 | ||
| 308 | phy-handle: true | ||
| 309 | |||
| 310 | phy-mode: true | ||
| 311 | |||
| 312 | required: | 308 | required: |
| 313 | - reg | 309 | - reg |
| 314 | - compatible | 310 | - compatible |
| 315 | - phy-handle | ||
| 316 | 311 | ||
| 317 | required: | 312 | required: |
| 318 | - compatible | 313 | - compatible |
| @@ -91,12 +91,18 @@ properties: · 90 unmodified lines | |||
| 91 | $ref: /schemas/types.yaml#/definitions/phandle | 91 | $ref: /schemas/types.yaml#/definitions/phandle |
| 92 | 92 | ||
| 93 | tx_delay: | 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 | $ref: /schemas/types.yaml#/definitions/uint32 | 95 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 96 | minimum: 0 | ||
| 97 | maximum: 0x7F | ||
| 98 | default: 0x30 | ||
| 96 | 99 | ||
| 97 | rx_delay: | 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 | $ref: /schemas/types.yaml#/definitions/uint32 | 102 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 103 | minimum: 0 | ||
| 104 | maximum: 0x7F | ||
| 105 | default: 0x10 | ||
| 100 | 106 | ||
| 101 | phy-supply: | 107 | phy-supply: |
| 102 | description: PHY regulator | 108 | description: PHY regulator |
| @@ -16,13 +16,15 @@ properties: · 15 unmodified lines | |||
| 16 | - enum: | 16 | - enum: |
| 17 | - atmel,at91rm9200-usart | 17 | - atmel,at91rm9200-usart |
| 18 | - atmel,at91sam9260-usart | 18 | - atmel,at91sam9260-usart |
| 19 | - microchip,sam9x60-usart | ||
| 20 | - items: | 19 | - items: |
| 21 | - const: atmel,at91rm9200-dbgu | 20 | - const: atmel,at91rm9200-dbgu |
| 22 | - const: atmel,at91rm9200-usart | 21 | - const: atmel,at91rm9200-usart |
| 23 | - items: | 22 | - items: |
| 24 | - const: atmel,at91sam9260-dbgu | 23 | - const: atmel,at91sam9260-dbgu |
| 25 | - const: atmel,at91sam9260-usart | 24 | - const: atmel,at91sam9260-usart |
| 25 | - items: | ||
| 26 | - const: microchip,sam9x60-usart | ||
| 27 | - const: atmel,at91sam9260-usart | ||
| 26 | - items: | 28 | - items: |
| 27 | - const: microchip,sam9x60-dbgu | 29 | - const: microchip,sam9x60-dbgu |
| 28 | - const: microchip,sam9x60-usart | 30 | - const: microchip,sam9x60-usart |
| @@ -551,9 +551,8 @@ mutex or just to use i_size_read() instead. · 550 unmodified lines | |||
| 551 | Note: this does not protect the file->f_pos against concurrent modifications | 551 | Note: this does not protect the file->f_pos against concurrent modifications |
| 552 | since this is something the userspace has to take care about. | 552 | since this is something the userspace has to take care about. |
| 553 | 553 | ||
| 554 | ->iterate() is called with i_rwsem exclusive. | 554 | ->iterate_shared() is called with i_rwsem held for reading, and with the |
| 555 | 555 | file f_pos_lock held exclusively | |
| 556 | ->iterate_shared() is called with i_rwsem at least shared. | ||
| 557 | 556 | ||
| 558 | ->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags. | 557 | ->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags. |
| 559 | Most instances call fasync_helper(), which does that maintenance, so it's | 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 | **mandatory** | 538 | **mandatory** |
| 539 | 539 | ||
| 540 | ->readdir() is gone now; switch to ->iterate() | 540 | ->readdir() is gone now; switch to ->iterate_shared() |
| 541 | 541 | ||
| 542 | **mandatory** | 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 | Exclusion on struct file level is still provided (as well as that | 699 | Exclusion on struct file level is still provided (as well as that |
| 700 | between it and lseek on the same struct file), but if your directory | 700 | between it and lseek on the same struct file), but if your directory |
| 701 | has been opened several times, you can get these called in parallel. | 701 | has been opened several times, you can get these called in parallel. |
| 702 | Exclusion between that method and all directory-modifying ones is | 702 | Exclusion between that method and all directory-modifying ones is |
| 703 | still provided, of course. | 703 | still provided, of course. |
| 704 | 704 | ||
| 705 | Often enough ->iterate() can serve as ->iterate_shared() without any | 705 | If you have any per-inode or per-dentry in-core data structures modified |
| 706 | changes - it is a read-only operation, after all. If you have any | 706 | by ->iterate_shared(), you might need something to serialize the access |
| 707 | per-inode or per-dentry in-core data structures modified by ->iterate(), | 707 | to them. If you do dcache pre-seeding, you'll need to switch to |
| 708 | you might need something to serialize the access to them. If you | 708 | d_alloc_parallel() for that; look for in-tree examples. |
| 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. | ||
| 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 | filldir_t (readdir callbacks) calling conventions have changed. Instead of | 925 | filldir_t (readdir callbacks) calling conventions have changed. Instead of |
| 931 | returning 0 or -E... it returns bool now. false means "no more" (as -E... used | 926 | returning 0 or -E... it returns bool now. false means "no more" (as -E... used |
| 932 | to) and true - "keep going" (as 0 in old calling conventions). Rationale: | 927 | to) and true - "keep going" (as 0 in old calling conventions). Rationale: |
| 933 | callers never looked at specific -E... values anyway. ->iterate() and | 928 | callers never looked at specific -E... values anyway. -> iterate_shared() |
| 934 | ->iterate_shared() instance require no changes at all, all filldir_t ones in | 929 | instances require no changes at all, all filldir_t ones in the tree |
| 935 | the tree converted. | 930 | converted. |
| 936 | 931 | ||
| 937 | --- | 932 | --- |
| 938 | 933 | ||
| @@ -2339,7 +2339,7 @@ F: drivers/phy/mediatek/ · 2338 unmodified lines | |||
| 2339 | ARM/MICROCHIP (ARM64) SoC support | 2339 | ARM/MICROCHIP (ARM64) SoC support |
| 2340 | M: Conor Dooley <conor@kernel.org> | 2340 | M: Conor Dooley <conor@kernel.org> |
| 2341 | M: Nicolas Ferre <nicolas.ferre@microchip.com> | 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 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 2343 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2344 | S: Supported | 2344 | S: Supported |
| 2345 | T: git https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git | 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 | ARM/Microchip (AT91) SoC support | 2348 | ARM/Microchip (AT91) SoC support |
| 2349 | M: Nicolas Ferre <nicolas.ferre@microchip.com> | 2349 | M: Nicolas Ferre <nicolas.ferre@microchip.com> |
| 2350 | M: Alexandre Belloni <alexandre.belloni@bootlin.com> | 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 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 2352 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2353 | S: Supported | 2353 | S: Supported |
| 2354 | W: http://www.linux4sam.org | 2354 | W: http://www.linux4sam.org |
| @@ -3250,7 +3250,7 @@ F: include/uapi/linux/atm* · 895 unmodified lines | |||
| 3250 | 3250 | ||
| 3251 | ATMEL MACB ETHERNET DRIVER | 3251 | ATMEL MACB ETHERNET DRIVER |
| 3252 | M: Nicolas Ferre <nicolas.ferre@microchip.com> | 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 | S: Supported | 3254 | S: Supported |
| 3255 | F: drivers/net/ethernet/cadence/ | 3255 | F: drivers/net/ethernet/cadence/ |
| 3256 | 3256 | ||
| @@ -3262,9 +3262,8 @@ F: Documentation/devicetree/bindings/input/atmel,maxtouch.yaml · 5 unmodified lines | |||
| 3262 | F: drivers/input/touchscreen/atmel_mxt_ts.c | 3262 | F: drivers/input/touchscreen/atmel_mxt_ts.c |
| 3263 | 3263 | ||
| 3264 | ATMEL WIRELESS DRIVER | 3264 | ATMEL WIRELESS DRIVER |
| 3265 | M: Simon Kelley <simon@thekelleys.org.uk> | ||
| 3266 | L: linux-wireless@vger.kernel.org | 3265 | L: linux-wireless@vger.kernel.org |
| 3267 | S: Maintained | 3266 | S: Orphan |
| 3268 | W: http://www.thekelleys.org.uk/atmel | 3267 | W: http://www.thekelleys.org.uk/atmel |
| 3269 | W: http://atmelwlandriver.sourceforge.net/ | 3268 | W: http://atmelwlandriver.sourceforge.net/ |
| 3270 | F: drivers/net/wireless/atmel/atmel* | 3269 | F: drivers/net/wireless/atmel/atmel* |
| @@ -3394,7 +3393,7 @@ F: drivers/media/radio/radio-aztech* · 123 unmodified lines | |||
| 3394 | B43 WIRELESS DRIVER | 3393 | B43 WIRELESS DRIVER |
| 3395 | L: linux-wireless@vger.kernel.org | 3394 | L: linux-wireless@vger.kernel.org |
| 3396 | L: b43-dev@lists.infradead.org | 3395 | L: b43-dev@lists.infradead.org |
| 3397 | S: Odd Fixes | 3396 | S: Orphan |
| 3398 | W: https://wireless.wiki.kernel.org/en/users/Drivers/b43 | 3397 | W: https://wireless.wiki.kernel.org/en/users/Drivers/b43 |
| 3399 | F: drivers/net/wireless/broadcom/b43/ | 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 | F: drivers/net/can/ctucanfd/ | 5461 | F: drivers/net/can/ctucanfd/ |
| 5463 | 5462 | ||
| 5464 | CW1200 WLAN driver | 5463 | CW1200 WLAN driver |
| 5465 | M: Solomon Peachy <pizza@shaftnet.org> | 5464 | S: Orphan |
| 5466 | S: Maintained | ||
| 5467 | F: drivers/net/wireless/st/cw1200/ | 5465 | F: drivers/net/wireless/st/cw1200/ |
| 5468 | 5466 | ||
| 5469 | CX18 VIDEO4LINUX DRIVER | 5467 | CX18 VIDEO4LINUX DRIVER |
| @@ -9377,7 +9375,6 @@ F: drivers/crypto/hisilicon/sgl.c · 3907 unmodified lines | |||
| 9377 | F: include/linux/hisi_acc_qm.h | 9375 | F: include/linux/hisi_acc_qm.h |
| 9378 | 9376 | ||
| 9379 | HISILICON ROCE DRIVER | 9377 | HISILICON ROCE DRIVER |
| 9380 | M: Haoyue Xu <xuhaoyue1@hisilicon.com> | ||
| 9381 | M: Junxian Huang <huangjunxian6@hisilicon.com> | 9378 | M: Junxian Huang <huangjunxian6@hisilicon.com> |
| 9382 | L: linux-rdma@vger.kernel.org | 9379 | L: linux-rdma@vger.kernel.org |
| 9383 | S: Maintained | 9380 | S: Maintained |
| @@ -9662,6 +9659,7 @@ F: tools/hv/ · 278 unmodified lines | |||
| 9662 | 9659 | ||
| 9663 | HYPERBUS SUPPORT | 9660 | HYPERBUS SUPPORT |
| 9664 | M: Vignesh Raghavendra <vigneshr@ti.com> | 9661 | M: Vignesh Raghavendra <vigneshr@ti.com> |
| 9662 | R: Tudor Ambarus <tudor.ambarus@linaro.org> | ||
| 9665 | L: linux-mtd@lists.infradead.org | 9663 | L: linux-mtd@lists.infradead.org |
| 9666 | S: Supported | 9664 | S: Supported |
| 9667 | Q: http://patchwork.ozlabs.org/project/linux-mtd/list/ | 9665 | Q: http://patchwork.ozlabs.org/project/linux-mtd/list/ |
| @@ -12481,6 +12479,7 @@ F: net/mctp/ · 2813 unmodified lines | |||
| 12481 | 12479 | ||
| 12482 | MAPLE TREE | 12480 | MAPLE TREE |
| 12483 | M: Liam R. Howlett <Liam.Howlett@oracle.com> | 12481 | M: Liam R. Howlett <Liam.Howlett@oracle.com> |
| 12482 | L: maple-tree@lists.infradead.org | ||
| 12484 | L: linux-mm@kvack.org | 12483 | L: linux-mm@kvack.org |
| 12485 | S: Supported | 12484 | S: Supported |
| 12486 | F: Documentation/core-api/maple_tree.rst | 12485 | F: Documentation/core-api/maple_tree.rst |
| @@ -12592,18 +12591,14 @@ F: Documentation/devicetree/bindings/net/marvell,pp2.yaml · 105 unmodified lines | |||
| 12592 | F: drivers/net/ethernet/marvell/mvpp2/ | 12591 | F: drivers/net/ethernet/marvell/mvpp2/ |
| 12593 | 12592 | ||
| 12594 | MARVELL MWIFIEX WIRELESS DRIVER | 12593 | MARVELL MWIFIEX WIRELESS DRIVER |
| 12595 | M: Amitkumar Karwar <amitkarwar@gmail.com> | 12594 | M: Brian Norris <briannorris@chromium.org> |
| 12596 | M: Ganapathi Bhat <ganapathi017@gmail.com> | ||
| 12597 | M: Sharvari Harisangam <sharvari.harisangam@nxp.com> | ||
| 12598 | M: Xinming Hu <huxinming820@gmail.com> | ||
| 12599 | L: linux-wireless@vger.kernel.org | 12595 | L: linux-wireless@vger.kernel.org |
| 12600 | S: Maintained | 12596 | S: Odd Fixes |
| 12601 | F: drivers/net/wireless/marvell/mwifiex/ | 12597 | F: drivers/net/wireless/marvell/mwifiex/ |
| 12602 | 12598 | ||
| 12603 | MARVELL MWL8K WIRELESS DRIVER | 12599 | MARVELL MWL8K WIRELESS DRIVER |
| 12604 | M: Lennert Buytenhek <buytenh@wantstofly.org> | ||
| 12605 | L: linux-wireless@vger.kernel.org | 12600 | L: linux-wireless@vger.kernel.org |
| 12606 | S: Odd Fixes | 12601 | S: Orphan |
| 12607 | F: drivers/net/wireless/marvell/mwl8k.c | 12602 | F: drivers/net/wireless/marvell/mwl8k.c |
| 12608 | 12603 | ||
| 12609 | MARVELL NAND CONTROLLER DRIVER | 12604 | MARVELL NAND CONTROLLER DRIVER |
| @@ -13791,7 +13786,7 @@ F: Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml · 1181 unmodified lines | |||
| 13791 | F: drivers/spi/spi-at91-usart.c | 13786 | F: drivers/spi/spi-at91-usart.c |
| 13792 | 13787 | ||
| 13793 | MICROCHIP AUDIO ASOC DRIVERS | 13788 | MICROCHIP AUDIO ASOC DRIVERS |
| 13794 | M: Claudiu Beznea <claudiu.beznea@microchip.com> | 13789 | M: Claudiu Beznea <claudiu.beznea@tuxon.dev> |
| 13795 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 13790 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
| 13796 | S: Supported | 13791 | S: Supported |
| 13797 | F: Documentation/devicetree/bindings/sound/atmel* | 13792 | F: Documentation/devicetree/bindings/sound/atmel* |
| @@ -13814,7 +13809,7 @@ S: Maintained · 16 unmodified lines | |||
| 13814 | F: drivers/crypto/atmel-ecc.* | 13809 | F: drivers/crypto/atmel-ecc.* |
| 13815 | 13810 | ||
| 13816 | MICROCHIP EIC DRIVER | 13811 | MICROCHIP EIC DRIVER |
| 13817 | M: Claudiu Beznea <claudiu.beznea@microchip.com> | 13812 | M: Claudiu Beznea <claudiu.beznea@tuxon.dev> |
| 13818 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 13813 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13819 | S: Supported | 13814 | S: Supported |
| 13820 | F: Documentation/devicetree/bindings/interrupt-controller/microchip,sama7g5-eic.yaml | 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 | F: include/video/atmel_lcdc.h | 13882 | F: include/video/atmel_lcdc.h |
| 13888 | 13883 | ||
| 13889 | MICROCHIP MCP16502 PMIC DRIVER | 13884 | MICROCHIP MCP16502 PMIC DRIVER |
| 13890 | M: Claudiu Beznea <claudiu.beznea@microchip.com> | 13885 | M: Claudiu Beznea <claudiu.beznea@tuxon.dev> |
| 13891 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 13886 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13892 | S: Supported | 13887 | S: Supported |
| 13893 | F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt | 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 | F: drivers/mtd/nand/raw/atmel/* | 13909 | F: drivers/mtd/nand/raw/atmel/* |
| 13915 | 13910 | ||
| 13916 | MICROCHIP OTPC DRIVER | 13911 | MICROCHIP OTPC DRIVER |
| 13917 | M: Claudiu Beznea <claudiu.beznea@microchip.com> | 13912 | M: Claudiu Beznea <claudiu.beznea@tuxon.dev> |
| 13918 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 13913 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13919 | S: Supported | 13914 | S: Supported |
| 13920 | F: Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml | 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 | F: drivers/fpga/microchip-spi.c | 13948 | F: drivers/fpga/microchip-spi.c |
| 13954 | 13949 | ||
| 13955 | MICROCHIP PWM DRIVER | 13950 | MICROCHIP PWM DRIVER |
| 13956 | M: Claudiu Beznea <claudiu.beznea@microchip.com> | 13951 | M: Claudiu Beznea <claudiu.beznea@tuxon.dev> |
| 13957 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 13952 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13958 | L: linux-pwm@vger.kernel.org | 13953 | L: linux-pwm@vger.kernel.org |
| 13959 | S: Supported | 13954 | S: Supported |
| @@ -13969,7 +13964,7 @@ F: drivers/iio/adc/at91-sama5d2_adc.c · 9 unmodified lines | |||
| 13969 | F: include/dt-bindings/iio/adc/at91-sama5d2_adc.h | 13964 | F: include/dt-bindings/iio/adc/at91-sama5d2_adc.h |
| 13970 | 13965 | ||
| 13971 | MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER | 13966 | MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER |
| 13972 | M: Claudiu Beznea <claudiu.beznea@microchip.com> | 13967 | M: Claudiu Beznea <claudiu.beznea@tuxon.dev> |
| 13973 | S: Supported | 13968 | S: Supported |
| 13974 | F: Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml | 13969 | F: Documentation/devicetree/bindings/power/reset/atmel,sama5d2-shdwc.yaml |
| 13975 | F: drivers/power/reset/at91-sama5d2_shdwc.c | 13970 | F: drivers/power/reset/at91-sama5d2_shdwc.c |
| @@ -13986,7 +13981,7 @@ S: Supported · 10 unmodified lines | |||
| 13986 | F: drivers/spi/spi-atmel.* | 13981 | F: drivers/spi/spi-atmel.* |
| 13987 | 13982 | ||
| 13988 | MICROCHIP SSC DRIVER | 13983 | MICROCHIP SSC DRIVER |
| 13989 | M: Claudiu Beznea <claudiu.beznea@microchip.com> | 13984 | M: Claudiu Beznea <claudiu.beznea@tuxon.dev> |
| 13990 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 13985 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 13991 | S: Supported | 13986 | S: Supported |
| 13992 | F: Documentation/devicetree/bindings/misc/atmel-ssc.txt | 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 | MICROCHIP WILC1000 WIFI DRIVER | 14011 | MICROCHIP WILC1000 WIFI DRIVER |
| 14017 | M: Ajay Singh <ajay.kathat@microchip.com> | 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 | L: linux-wireless@vger.kernel.org | 14014 | L: linux-wireless@vger.kernel.org |
| 14020 | S: Supported | 14015 | S: Supported |
| 14021 | F: drivers/net/wireless/microchip/wilc1000/ | 14016 | F: drivers/net/wireless/microchip/wilc1000/ |
| @@ -16298,6 +16293,7 @@ F: drivers/pci/controller/dwc/pci-exynos.c · 2276 unmodified lines | |||
| 16298 | PCI DRIVER FOR SYNOPSYS DESIGNWARE | 16293 | PCI DRIVER FOR SYNOPSYS DESIGNWARE |
| 16299 | M: Jingoo Han <jingoohan1@gmail.com> | 16294 | M: Jingoo Han <jingoohan1@gmail.com> |
| 16300 | M: Gustavo Pimentel <gustavo.pimentel@synopsys.com> | 16295 | M: Gustavo Pimentel <gustavo.pimentel@synopsys.com> |
| 16296 | M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | ||
| 16301 | L: linux-pci@vger.kernel.org | 16297 | L: linux-pci@vger.kernel.org |
| 16302 | S: Maintained | 16298 | S: Maintained |
| 16303 | F: Documentation/devicetree/bindings/pci/snps,dw-pcie-ep.yaml | 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 | QUALCOMM ATH12K WIRELESS DRIVER | 17446 | QUALCOMM ATH12K WIRELESS DRIVER |
| 17451 | M: Kalle Valo <kvalo@kernel.org> | 17447 | M: Kalle Valo <kvalo@kernel.org> |
| 17448 | M: Jeff Johnson <quic_jjohnson@quicinc.com> | ||
| 17452 | L: ath12k@lists.infradead.org | 17449 | L: ath12k@lists.infradead.org |
| 17453 | S: Supported | 17450 | S: Supported |
| 17454 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git | 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 | QUALCOMM ATHEROS ATH10K WIRELESS DRIVER | 17454 | QUALCOMM ATHEROS ATH10K WIRELESS DRIVER |
| 17458 | M: Kalle Valo <kvalo@kernel.org> | 17455 | M: Kalle Valo <kvalo@kernel.org> |
| 17456 | M: Jeff Johnson <quic_jjohnson@quicinc.com> | ||
| 17459 | L: ath10k@lists.infradead.org | 17457 | L: ath10k@lists.infradead.org |
| 17460 | S: Supported | 17458 | S: Supported |
| 17461 | W: https://wireless.wiki.kernel.org/en/users/Drivers/ath10k | 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 | QUALCOMM ATHEROS ATH11K WIRELESS DRIVER | 17464 | QUALCOMM ATHEROS ATH11K WIRELESS DRIVER |
| 17467 | M: Kalle Valo <kvalo@kernel.org> | 17465 | M: Kalle Valo <kvalo@kernel.org> |
| 17466 | M: Jeff Johnson <quic_jjohnson@quicinc.com> | ||
| 17468 | L: ath11k@lists.infradead.org | 17467 | L: ath11k@lists.infradead.org |
| 17469 | S: Supported | 17468 | S: Supported |
| 17470 | W: https://wireless.wiki.kernel.org/en/users/Drivers/ath11k | 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 | F: drivers/net/wireless/realtek/rtlwifi/ | 17984 | F: drivers/net/wireless/realtek/rtlwifi/ |
| 17986 | 17985 | ||
| 17987 | REALTEK WIRELESS DRIVER (rtw88) | 17986 | REALTEK WIRELESS DRIVER (rtw88) |
| 17988 | M: Yan-Hsuan Chuang <tony0620emma@gmail.com> | 17987 | M: Ping-Ke Shih <pkshih@realtek.com> |
| 17989 | L: linux-wireless@vger.kernel.org | 17988 | L: linux-wireless@vger.kernel.org |
| 17990 | S: Maintained | 17989 | S: Maintained |
| 17991 | F: drivers/net/wireless/realtek/rtw88/ | 17990 | F: drivers/net/wireless/realtek/rtw88/ |
| @@ -18510,17 +18509,14 @@ RTL8180 WIRELESS DRIVER · 518 unmodified lines | |||
| 18510 | L: linux-wireless@vger.kernel.org | 18509 | L: linux-wireless@vger.kernel.org |
| 18511 | S: Orphan | 18510 | S: Orphan |
| 18512 | W: https://wireless.wiki.kernel.org/ | 18511 | W: https://wireless.wiki.kernel.org/ |
| 18513 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | ||
| 18514 | F: drivers/net/wireless/realtek/rtl818x/rtl8180/ | 18512 | F: drivers/net/wireless/realtek/rtl818x/rtl8180/ |
| 18515 | 18513 | ||
| 18516 | RTL8187 WIRELESS DRIVER | 18514 | RTL8187 WIRELESS DRIVER |
| 18517 | M: Herton Ronaldo Krzesinski <herton@canonical.com> | 18515 | M: Hin-Tak Leung <hintak.leung@gmail.com> |
| 18518 | M: Hin-Tak Leung <htl10@users.sourceforge.net> | ||
| 18519 | M: Larry Finger <Larry.Finger@lwfinger.net> | 18516 | M: Larry Finger <Larry.Finger@lwfinger.net> |
| 18520 | L: linux-wireless@vger.kernel.org | 18517 | L: linux-wireless@vger.kernel.org |
| 18521 | S: Maintained | 18518 | S: Maintained |
| 18522 | W: https://wireless.wiki.kernel.org/ | 18519 | W: https://wireless.wiki.kernel.org/ |
| 18523 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | ||
| 18524 | F: drivers/net/wireless/realtek/rtl818x/rtl8187/ | 18520 | F: drivers/net/wireless/realtek/rtl818x/rtl8187/ |
| 18525 | 18521 | ||
| 18526 | RTL8XXXU WIRELESS DRIVER (rtl8xxxu) | 18522 | RTL8XXXU WIRELESS DRIVER (rtl8xxxu) |
| @@ -20404,7 +20400,6 @@ F: drivers/pwm/pwm-stm32* · 1877 unmodified lines | |||
| 20404 | F: include/linux/*/stm32-*tim* | 20400 | F: include/linux/*/stm32-*tim* |
| 20405 | 20401 | ||
| 20406 | STMMAC ETHERNET DRIVER | 20402 | STMMAC ETHERNET DRIVER |
| 20407 | M: Giuseppe Cavallaro <peppe.cavallaro@st.com> | ||
| 20408 | M: Alexandre Torgue <alexandre.torgue@foss.st.com> | 20403 | M: Alexandre Torgue <alexandre.torgue@foss.st.com> |
| 20409 | M: Jose Abreu <joabreu@synopsys.com> | 20404 | M: Jose Abreu <joabreu@synopsys.com> |
| 20410 | L: netdev@vger.kernel.org | 20405 | L: netdev@vger.kernel.org |
| @@ -21681,11 +21676,14 @@ S: Orphan · 1270 unmodified lines | |||
| 21681 | F: drivers/net/ethernet/dec/tulip/ | 21676 | F: drivers/net/ethernet/dec/tulip/ |
| 21682 | 21677 | ||
| 21683 | TUN/TAP driver | 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 | S: Maintained | 21681 | S: Maintained |
| 21686 | W: http://vtun.sourceforge.net/tun | 21682 | W: http://vtun.sourceforge.net/tun |
| 21687 | F: Documentation/networking/tuntap.rst | 21683 | F: Documentation/networking/tuntap.rst |
| 21688 | F: arch/um/os-Linux/drivers/ | 21684 | F: arch/um/os-Linux/drivers/ |
| 21685 | F: drivers/net/tap.c | ||
| 21686 | F: drivers/net/tun.c | ||
| 21689 | 21687 | ||
| 21690 | TURBOCHANNEL SUBSYSTEM | 21688 | TURBOCHANNEL SUBSYSTEM |
| 21691 | M: "Maciej W. Rozycki" <macro@orcam.me.uk> | 21689 | M: "Maciej W. Rozycki" <macro@orcam.me.uk> |
| @@ -21908,9 +21906,8 @@ S: Maintained · 216 unmodified lines | |||
| 21908 | F: drivers/usb/misc/apple-mfi-fastcharge.c | 21906 | F: drivers/usb/misc/apple-mfi-fastcharge.c |
| 21909 | 21907 | ||
| 21910 | USB AR5523 WIRELESS DRIVER | 21908 | USB AR5523 WIRELESS DRIVER |
| 21911 | M: Pontus Fuchs <pontus.fuchs@gmail.com> | ||
| 21912 | L: linux-wireless@vger.kernel.org | 21909 | L: linux-wireless@vger.kernel.org |
| 21913 | S: Maintained | 21910 | S: Orphan |
| 21914 | F: drivers/net/wireless/ath/ar5523/ | 21911 | F: drivers/net/wireless/ath/ar5523/ |
| 21915 | 21912 | ||
| 21916 | USB ATTACHED SCSI | 21913 | USB ATTACHED SCSI |
| @@ -22187,9 +22184,8 @@ F: drivers/usb/gadget/legacy/webcam.c · 270 unmodified lines | |||
| 22187 | F: include/uapi/linux/usb/g_uvc.h | 22184 | F: include/uapi/linux/usb/g_uvc.h |
| 22188 | 22185 | ||
| 22189 | USB WIRELESS RNDIS DRIVER (rndis_wlan) | 22186 | USB WIRELESS RNDIS DRIVER (rndis_wlan) |
| 22190 | M: Jussi Kivilinna <jussi.kivilinna@iki.fi> | ||
| 22191 | L: linux-wireless@vger.kernel.org | 22187 | L: linux-wireless@vger.kernel.org |
| 22192 | S: Maintained | 22188 | S: Orphan |
| 22193 | F: drivers/net/wireless/legacy/rndis_wlan.c | 22189 | F: drivers/net/wireless/legacy/rndis_wlan.c |
| 22194 | 22190 | ||
| 22195 | USB XHCI DRIVER | 22191 | USB XHCI DRIVER |
| @@ -22964,7 +22960,7 @@ F: drivers/input/misc/wistron_btns.c · 768 unmodified lines | |||
| 22964 | 22960 | ||
| 22965 | WL3501 WIRELESS PCMCIA CARD DRIVER | 22961 | WL3501 WIRELESS PCMCIA CARD DRIVER |
| 22966 | L: linux-wireless@vger.kernel.org | 22962 | L: linux-wireless@vger.kernel.org |
| 22967 | S: Odd fixes | 22963 | S: Orphan |
| 22968 | F: drivers/net/wireless/legacy/wl3501* | 22964 | F: drivers/net/wireless/legacy/wl3501* |
| 22969 | 22965 | ||
| 22970 | WMI BINARY MOF DRIVER | 22966 | WMI BINARY MOF DRIVER |
| @@ -23535,11 +23531,8 @@ S: Maintained · 564 unmodified lines | |||
| 23535 | F: mm/zbud.c | 23531 | F: mm/zbud.c |
| 23536 | 23532 | ||
| 23537 | ZD1211RW WIRELESS DRIVER | 23533 | ZD1211RW WIRELESS DRIVER |
| 23538 | M: Ulrich Kunitz <kune@deine-taler.de> | ||
| 23539 | L: linux-wireless@vger.kernel.org | 23534 | L: linux-wireless@vger.kernel.org |
| 23540 | L: zd1211-devs@lists.sourceforge.net (subscribers-only) | 23535 | S: Orphan |
| 23541 | S: Maintained | ||
| 23542 | W: http://zd1211.ath.cx/wiki/DriverRewrite | ||
| 23543 | F: drivers/net/wireless/zydas/zd1211rw/ | 23536 | F: drivers/net/wireless/zydas/zd1211rw/ |
| 23544 | 23537 | ||
| 23545 | ZD1301 MEDIA DRIVER | 23538 | ZD1301 MEDIA DRIVER |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 6 | 2 | VERSION = 6 |
| 3 | PATCHLEVEL = 5 | 3 | PATCHLEVEL = 5 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc4 | 5 | EXTRAVERSION = -rc6 |
| 6 | NAME = Hurr durr I'ma ninja sloth | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -47,12 +47,6 @@ unsigned long __get_wchan(struct task_struct *p); · 46 unmodified lines | |||
| 47 | 47 | ||
| 48 | #define ARCH_HAS_PREFETCH | 48 | #define ARCH_HAS_PREFETCH |
| 49 | #define ARCH_HAS_PREFETCHW | 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 | extern inline void prefetch(const void *ptr) | 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 | __builtin_prefetch(ptr, 1, 3); | 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 | #endif /* __ASM_ALPHA_PROCESSOR_H */ | 61 | #endif /* __ASM_ALPHA_PROCESSOR_H */ |
| @@ -385,8 +385,7 @@ setup_memory(void *kernel_end) · 384 unmodified lines | |||
| 385 | #endif /* CONFIG_BLK_DEV_INITRD */ | 385 | #endif /* CONFIG_BLK_DEV_INITRD */ |
| 386 | } | 386 | } |
| 387 | 387 | ||
| 388 | int __init | 388 | int page_is_ram(unsigned long pfn) |
| 389 | page_is_ram(unsigned long pfn) | ||
| 390 | { | 389 | { |
| 391 | struct memclust_struct * cluster; | 390 | struct memclust_struct * cluster; |
| 392 | struct memdesc_struct * memdesc; | 391 | struct memdesc_struct * memdesc; |
| @@ -172,7 +172,7 @@ · 171 unmodified lines | |||
| 172 | status = "disabled"; | 172 | status = "disabled"; |
| 173 | 173 | ||
| 174 | uart4: serial@200 { | 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 | reg = <0x200 0x200>; | 176 | reg = <0x200 0x200>; |
| 177 | interrupts = <13 IRQ_TYPE_LEVEL_HIGH 7>; | 177 | interrupts = <13 IRQ_TYPE_LEVEL_HIGH 7>; |
| 178 | dmas = <&dma0 | 178 | dmas = <&dma0 |
| @@ -240,7 +240,7 @@ · 61 unmodified lines | |||
| 240 | status = "disabled"; | 240 | status = "disabled"; |
| 241 | 241 | ||
| 242 | uart5: serial@200 { | 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 | reg = <0x200 0x200>; | 244 | reg = <0x200 0x200>; |
| 245 | atmel,usart-mode = <AT91_USART_MODE_SERIAL>; | 245 | atmel,usart-mode = <AT91_USART_MODE_SERIAL>; |
| 246 | interrupts = <14 IRQ_TYPE_LEVEL_HIGH 7>; | 246 | interrupts = <14 IRQ_TYPE_LEVEL_HIGH 7>; |
| @@ -370,7 +370,7 @@ · 123 unmodified lines | |||
| 370 | status = "disabled"; | 370 | status = "disabled"; |
| 371 | 371 | ||
| 372 | uart11: serial@200 { | 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 | reg = <0x200 0x200>; | 374 | reg = <0x200 0x200>; |
| 375 | interrupts = <32 IRQ_TYPE_LEVEL_HIGH 7>; | 375 | interrupts = <32 IRQ_TYPE_LEVEL_HIGH 7>; |
| 376 | dmas = <&dma0 | 376 | dmas = <&dma0 |
| @@ -419,7 +419,7 @@ · 42 unmodified lines | |||
| 419 | status = "disabled"; | 419 | status = "disabled"; |
| 420 | 420 | ||
| 421 | uart12: serial@200 { | 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 | reg = <0x200 0x200>; | 423 | reg = <0x200 0x200>; |
| 424 | interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>; | 424 | interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>; |
| 425 | dmas = <&dma0 | 425 | dmas = <&dma0 |
| @@ -576,7 +576,7 @@ · 150 unmodified lines | |||
| 576 | status = "disabled"; | 576 | status = "disabled"; |
| 577 | 577 | ||
| 578 | uart6: serial@200 { | 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 | reg = <0x200 0x200>; | 580 | reg = <0x200 0x200>; |
| 581 | interrupts = <9 IRQ_TYPE_LEVEL_HIGH 7>; | 581 | interrupts = <9 IRQ_TYPE_LEVEL_HIGH 7>; |
| 582 | dmas = <&dma0 | 582 | dmas = <&dma0 |
| @@ -625,7 +625,7 @@ · 42 unmodified lines | |||
| 625 | status = "disabled"; | 625 | status = "disabled"; |
| 626 | 626 | ||
| 627 | uart7: serial@200 { | 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 | reg = <0x200 0x200>; | 629 | reg = <0x200 0x200>; |
| 630 | interrupts = <10 IRQ_TYPE_LEVEL_HIGH 7>; | 630 | interrupts = <10 IRQ_TYPE_LEVEL_HIGH 7>; |
| 631 | dmas = <&dma0 | 631 | dmas = <&dma0 |
| @@ -674,7 +674,7 @@ · 42 unmodified lines | |||
| 674 | status = "disabled"; | 674 | status = "disabled"; |
| 675 | 675 | ||
| 676 | uart8: serial@200 { | 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 | reg = <0x200 0x200>; | 678 | reg = <0x200 0x200>; |
| 679 | interrupts = <11 IRQ_TYPE_LEVEL_HIGH 7>; | 679 | interrupts = <11 IRQ_TYPE_LEVEL_HIGH 7>; |
| 680 | dmas = <&dma0 | 680 | dmas = <&dma0 |
| @@ -723,7 +723,7 @@ · 42 unmodified lines | |||
| 723 | status = "disabled"; | 723 | status = "disabled"; |
| 724 | 724 | ||
| 725 | uart0: serial@200 { | 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 | reg = <0x200 0x200>; | 727 | reg = <0x200 0x200>; |
| 728 | interrupts = <5 IRQ_TYPE_LEVEL_HIGH 7>; | 728 | interrupts = <5 IRQ_TYPE_LEVEL_HIGH 7>; |
| 729 | dmas = <&dma0 | 729 | dmas = <&dma0 |
| @@ -791,7 +791,7 @@ · 61 unmodified lines | |||
| 791 | status = "disabled"; | 791 | status = "disabled"; |
| 792 | 792 | ||
| 793 | uart1: serial@200 { | 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 | reg = <0x200 0x200>; | 795 | reg = <0x200 0x200>; |
| 796 | interrupts = <6 IRQ_TYPE_LEVEL_HIGH 7>; | 796 | interrupts = <6 IRQ_TYPE_LEVEL_HIGH 7>; |
| 797 | dmas = <&dma0 | 797 | dmas = <&dma0 |
| @@ -859,7 +859,7 @@ · 61 unmodified lines | |||
| 859 | status = "disabled"; | 859 | status = "disabled"; |
| 860 | 860 | ||
| 861 | uart2: serial@200 { | 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 | reg = <0x200 0x200>; | 863 | reg = <0x200 0x200>; |
| 864 | interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7>; | 864 | interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7>; |
| 865 | dmas = <&dma0 | 865 | dmas = <&dma0 |
| @@ -927,7 +927,7 @@ · 61 unmodified lines | |||
| 927 | status = "disabled"; | 927 | status = "disabled"; |
| 928 | 928 | ||
| 929 | uart3: serial@200 { | 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 | reg = <0x200 0x200>; | 931 | reg = <0x200 0x200>; |
| 932 | interrupts = <8 IRQ_TYPE_LEVEL_HIGH 7>; | 932 | interrupts = <8 IRQ_TYPE_LEVEL_HIGH 7>; |
| 933 | dmas = <&dma0 | 933 | dmas = <&dma0 |
| @@ -1050,7 +1050,7 @@ · 116 unmodified lines | |||
| 1050 | status = "disabled"; | 1050 | status = "disabled"; |
| 1051 | 1051 | ||
| 1052 | uart9: serial@200 { | 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 | reg = <0x200 0x200>; | 1054 | reg = <0x200 0x200>; |
| 1055 | interrupts = <15 IRQ_TYPE_LEVEL_HIGH 7>; | 1055 | interrupts = <15 IRQ_TYPE_LEVEL_HIGH 7>; |
| 1056 | dmas = <&dma0 | 1056 | dmas = <&dma0 |
| @@ -1099,7 +1099,7 @@ · 42 unmodified lines | |||
| 1099 | status = "disabled"; | 1099 | status = "disabled"; |
| 1100 | 1100 | ||
| 1101 | uart10: serial@200 { | 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 | reg = <0x200 0x200>; | 1103 | reg = <0x200 0x200>; |
| 1104 | interrupts = <16 IRQ_TYPE_LEVEL_HIGH 7>; | 1104 | interrupts = <16 IRQ_TYPE_LEVEL_HIGH 7>; |
| 1105 | dmas = <&dma0 | 1105 | dmas = <&dma0 |
| @@ -161,7 +161,7 @@ · 160 unmodified lines | |||
| 161 | }; | 161 | }; |
| 162 | 162 | ||
| 163 | watchdog: watchdog@90060000 { | 163 | watchdog: watchdog@90060000 { |
| 164 | compatible = "arm,amba-primecell"; | 164 | compatible = "arm,primecell"; |
| 165 | reg = <0x90060000 0x1000>; | 165 | reg = <0x90060000 0x1000>; |
| 166 | interrupts = <3>; | 166 | interrupts = <3>; |
| 167 | }; | 167 | }; |
| @@ -60,6 +60,16 @@ · 59 unmodified lines | |||
| 60 | status = "okay"; | 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 | &ecspi1 { | 73 | &ecspi1 { |
| 64 | pinctrl-names = "default"; | 74 | pinctrl-names = "default"; |
| 65 | pinctrl-0 = <&pinctrl_ecspi1>; | 75 | pinctrl-0 = <&pinctrl_ecspi1>; |
| @@ -552,7 +552,7 @@ · 551 unmodified lines | |||
| 552 | reg = <0x020ca000 0x1000>; | 552 | reg = <0x020ca000 0x1000>; |
| 553 | interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; | 553 | interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>; |
| 554 | clocks = <&clks IMX6SLL_CLK_USBPHY2>; | 554 | clocks = <&clks IMX6SLL_CLK_USBPHY2>; |
| 555 | phy-reg_3p0-supply = <®_3p0>; | 555 | phy-3p0-supply = <®_3p0>; |
| 556 | fsl,anatop = <&anatop>; | 556 | fsl,anatop = <&anatop>; |
| 557 | }; | 557 | }; |
| 558 | 558 | ||
| @@ -105,5 +105,4 @@ void sharpsl_pm_led(int val); · 104 unmodified lines | |||
| 105 | #define MAX1111_ACIN_VOLT 6u | 105 | #define MAX1111_ACIN_VOLT 6u |
| 106 | int sharpsl_pm_pxa_read_max1111(int channel); | 106 | int sharpsl_pm_pxa_read_max1111(int channel); |
| 107 | 107 | ||
| 108 | void corgi_lcd_limit_intensity(int limit); | ||
| 109 | #endif | 108 | #endif |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/apm-emulation.h> | 17 | #include <linux/apm-emulation.h> |
| 18 | #include <linux/spi/corgi_lcd.h> | ||
| 18 | 19 | ||
| 19 | #include <asm/irq.h> | 20 | #include <asm/irq.h> |
| 20 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
| @@ -145,7 +145,7 @@ · 144 unmodified lines | |||
| 145 | status = "okay"; | 145 | status = "okay"; |
| 146 | clock-frequency = <100000>; | 146 | clock-frequency = <100000>; |
| 147 | i2c-sda-falling-time-ns = <890>; /* hcnt */ | 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 | pinctrl-names = "default", "gpio"; | 150 | pinctrl-names = "default", "gpio"; |
| 151 | pinctrl-0 = <&i2c1_pmx_func>; | 151 | pinctrl-0 = <&i2c1_pmx_func>; |
| @@ -141,7 +141,7 @@ · 140 unmodified lines | |||
| 141 | status = "okay"; | 141 | status = "okay"; |
| 142 | clock-frequency = <100000>; | 142 | clock-frequency = <100000>; |
| 143 | i2c-sda-falling-time-ns = <890>; /* hcnt */ | 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 | adc@14 { | 146 | adc@14 { |
| 147 | compatible = "lltc,ltc2497"; | 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 | &gpio1 { | 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 | "", "", "", "RESET_ETHPHY", | 145 | "", "", "", "RESET_ETHPHY", |
| 146 | "CAN_nINT", "CAN_EN", "nENABLE_FLATLINK", "", | 146 | "CAN_nINT", "CAN_EN", "nENABLE_FLATLINK", "", |
| 147 | "USB_OTG_VBUS_EN", "", "LED_GREEN", "LED_BLUE"; | 147 | "USB_OTG_VBUS_EN", "", "LED_GREEN", "LED_BLUE"; |
| @@ -111,7 +111,7 @@ · 110 unmodified lines | |||
| 111 | }; | 111 | }; |
| 112 | 112 | ||
| 113 | &gpio1 { | 113 | &gpio1 { |
| 114 | gpio-line-names = "nINT_ETHPHY", "", "WDOG_INT", "X_RTC_INT", | 114 | gpio-line-names = "", "", "WDOG_INT", "X_RTC_INT", |
| 115 | "", "", "", "RESET_ETHPHY", | 115 | "", "", "", "RESET_ETHPHY", |
| 116 | "", "", "nENABLE_FLATLINK"; | 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 | regulator-always-on; | 214 | regulator-always-on; |
| 215 | regulator-boot-on; | 215 | regulator-boot-on; |
| 216 | regulator-max-microvolt = <1000000>; | 216 | regulator-max-microvolt = <1000000>; |
| @@ -567,6 +567,10 @@ · 566 unmodified lines | |||
| 567 | status = "okay"; | 567 | status = "okay"; |
| 568 | }; | 568 | }; |
| 569 | 569 | ||
| 570 | &disp_blk_ctrl { | ||
| 571 | status = "disabled"; | ||
| 572 | }; | ||
| 573 | |||
| 570 | &pgc_mipi { | 574 | &pgc_mipi { |
| 571 | status = "disabled"; | 575 | status = "disabled"; |
| 572 | }; | 576 | }; |
| @@ -628,6 +628,10 @@ · 627 unmodified lines | |||
| 628 | status = "okay"; | 628 | status = "okay"; |
| 629 | }; | 629 | }; |
| 630 | 630 | ||
| 631 | &disp_blk_ctrl { | ||
| 632 | status = "disabled"; | ||
| 633 | }; | ||
| 634 | |||
| 631 | &pgc_mipi { | 635 | &pgc_mipi { |
| 632 | status = "disabled"; | 636 | status = "disabled"; |
| 633 | }; | 637 | }; |
| @@ -358,7 +358,7 @@ · 357 unmodified lines | |||
| 358 | MX8MN_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 | 358 | MX8MN_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 |
| 359 | MX8MN_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 | 359 | MX8MN_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 |
| 360 | MX8MN_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f | 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 | <&clk IMX8MQ_SYS1_PLL_800M>, | 772 | <&clk IMX8MQ_SYS1_PLL_800M>, |
| 773 | <&clk IMX8MQ_VPU_PLL>; | 773 | <&clk IMX8MQ_VPU_PLL>; |
| 774 | assigned-clock-rates = <600000000>, | 774 | assigned-clock-rates = <600000000>, |
| 775 | <600000000>, | 775 | <300000000>, |
| 776 | <800000000>, | 776 | <800000000>, |
| 777 | <0>; | 777 | <0>; |
| 778 | }; | 778 | }; |
| @@ -223,20 +223,20 @@ · 222 unmodified lines | |||
| 223 | <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>, | 223 | <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>, |
| 224 | <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>; | 224 | <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>; |
| 225 | interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", | 225 | interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", |
| 226 | "tgiv0", "tgie0", "tgif0", | 226 | "tciv0", "tgie0", "tgif0", |
| 227 | "tgia1", "tgib1", "tgiv1", "tgiu1", | 227 | "tgia1", "tgib1", "tciv1", "tciu1", |
| 228 | "tgia2", "tgib2", "tgiv2", "tgiu2", | 228 | "tgia2", "tgib2", "tciv2", "tciu2", |
| 229 | "tgia3", "tgib3", "tgic3", "tgid3", | 229 | "tgia3", "tgib3", "tgic3", "tgid3", |
| 230 | "tgiv3", | 230 | "tciv3", |
| 231 | "tgia4", "tgib4", "tgic4", "tgid4", | 231 | "tgia4", "tgib4", "tgic4", "tgid4", |
| 232 | "tgiv4", | 232 | "tciv4", |
| 233 | "tgiu5", "tgiv5", "tgiw5", | 233 | "tgiu5", "tgiv5", "tgiw5", |
| 234 | "tgia6", "tgib6", "tgic6", "tgid6", | 234 | "tgia6", "tgib6", "tgic6", "tgid6", |
| 235 | "tgiv6", | 235 | "tciv6", |
| 236 | "tgia7", "tgib7", "tgic7", "tgid7", | 236 | "tgia7", "tgib7", "tgic7", "tgid7", |
| 237 | "tgiv7", | 237 | "tciv7", |
| 238 | "tgia8", "tgib8", "tgic8", "tgid8", | 238 | "tgia8", "tgib8", "tgic8", "tgid8", |
| 239 | "tgiv8", "tgiu8"; | 239 | "tciv8", "tciu8"; |
| 240 | clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>; | 240 | clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>; |
| 241 | power-domains = <&cpg>; | 241 | power-domains = <&cpg>; |
| 242 | resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>; | 242 | resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>; |
| @@ -223,20 +223,20 @@ · 222 unmodified lines | |||
| 223 | <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>, | 223 | <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>, |
| 224 | <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>; | 224 | <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>; |
| 225 | interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", | 225 | interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0", |
| 226 | "tgiv0", "tgie0", "tgif0", | 226 | "tciv0", "tgie0", "tgif0", |
| 227 | "tgia1", "tgib1", "tgiv1", "tgiu1", | 227 | "tgia1", "tgib1", "tciv1", "tciu1", |
| 228 | "tgia2", "tgib2", "tgiv2", "tgiu2", | 228 | "tgia2", "tgib2", "tciv2", "tciu2", |
| 229 | "tgia3", "tgib3", "tgic3", "tgid3", | 229 | "tgia3", "tgib3", "tgic3", "tgid3", |
| 230 | "tgiv3", | 230 | "tciv3", |
| 231 | "tgia4", "tgib4", "tgic4", "tgid4", | 231 | "tgia4", "tgib4", "tgic4", "tgid4", |
| 232 | "tgiv4", | 232 | "tciv4", |
| 233 | "tgiu5", "tgiv5", "tgiw5", | 233 | "tgiu5", "tgiv5", "tgiw5", |
| 234 | "tgia6", "tgib6", "tgic6", "tgid6", | 234 | "tgia6", "tgib6", "tgic6", "tgid6", |
| 235 | "tgiv6", | 235 | "tciv6", |
| 236 | "tgia7", "tgib7", "tgic7", "tgid7", | 236 | "tgia7", "tgib7", "tgic7", "tgid7", |
| 237 | "tgiv7", | 237 | "tciv7", |
| 238 | "tgia8", "tgib8", "tgic8", "tgid8", | 238 | "tgia8", "tgib8", "tgic8", "tgid8", |
| 239 | "tgiv8", "tgiu8"; | 239 | "tciv8", "tciu8"; |
| 240 | clocks = <&cpg CPG_MOD R9A07G054_MTU_X_MCK_MTU3>; | 240 | clocks = <&cpg CPG_MOD R9A07G054_MTU_X_MCK_MTU3>; |
| 241 | power-domains = <&cpg>; | 241 | power-domains = <&cpg>; |
| 242 | resets = <&cpg R9A07G054_MTU_X_PRESET_MTU3>; | 242 | resets = <&cpg R9A07G054_MTU_X_PRESET_MTU3>; |
| @@ -31,6 +31,13 @@ · 30 unmodified lines | |||
| 31 | .Lskip_hcrx_\@: | 31 | .Lskip_hcrx_\@: |
| 32 | .endm | 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 | * Allow Non-secure EL1 and EL0 to access physical timer and counter. | 42 | * Allow Non-secure EL1 and EL0 to access physical timer and counter. |
| 36 | * This is not necessary for VHE, since the host kernel runs in EL2, | 43 | * This is not necessary for VHE, since the host kernel runs in EL2, |
| @@ -43,9 +50,7 @@ · 6 unmodified lines | |||
| 43 | */ | 50 | */ |
| 44 | .macro __init_el2_timers | 51 | .macro __init_el2_timers |
| 45 | mov x0, #3 // Enable EL1 physical timers | 52 | mov x0, #3 // Enable EL1 physical timers |
| 46 | mrs x1, hcr_el2 | 53 | __check_hvhe .LnVHE_\@, x1 |
| 47 | and x1, x1, #HCR_E2H | ||
| 48 | cbz x1, .LnVHE_\@ | ||
| 49 | lsl x0, x0, #10 | 54 | lsl x0, x0, #10 |
| 50 | .LnVHE_\@: | 55 | .LnVHE_\@: |
| 51 | msr cnthctl_el2, x0 | 56 | msr cnthctl_el2, x0 |
| @@ -139,15 +144,14 @@ · 87 unmodified lines | |||
| 139 | 144 | ||
| 140 | /* Coprocessor traps */ | 145 | /* Coprocessor traps */ |
| 141 | .macro __init_el2_cptr | 146 | .macro __init_el2_cptr |
| 142 | mrs x1, hcr_el2 | 147 | __check_hvhe .LnVHE_\@, x1 |
| 143 | and x1, x1, #HCR_E2H | ||
| 144 | cbz x1, .LnVHE_\@ | ||
| 145 | mov x0, #(CPACR_EL1_FPEN_EL1EN | CPACR_EL1_FPEN_EL0EN) | 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 | .LnVHE_\@: | 151 | .LnVHE_\@: |
| 148 | mov x0, #0x33ff | 152 | mov x0, #0x33ff |
| 149 | .Lset_cptr_\@: | ||
| 150 | msr cptr_el2, x0 // Disable copro. traps to EL2 | 153 | msr cptr_el2, x0 // Disable copro. traps to EL2 |
| 154 | .Lskip_set_cptr_\@: | ||
| 151 | .endm | 155 | .endm |
| 152 | 156 | ||
| 153 | /* Disable any fine grained traps */ | 157 | /* Disable any fine grained traps */ |
| @@ -268,19 +272,19 @@ · 114 unmodified lines | |||
| 268 | check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2 | 272 | check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2 |
| 269 | 273 | ||
| 270 | .Linit_sve_\@: /* SVE register access */ | 274 | .Linit_sve_\@: /* SVE register access */ |
| 271 | mrs x0, cptr_el2 // Disable SVE traps | 275 | __check_hvhe .Lcptr_nvhe_\@, x1 |
| 272 | mrs x1, hcr_el2 | ||
| 273 | and x1, x1, #HCR_E2H | ||
| 274 | cbz x1, .Lcptr_nvhe_\@ | ||
| 275 | 276 | ||
| 276 | // VHE case | 277 | // (h)VHE case |
| 278 | mrs x0, cpacr_el1 // Disable SVE traps | ||
| 277 | orr x0, x0, #(CPACR_EL1_ZEN_EL1EN | CPACR_EL1_ZEN_EL0EN) | 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 | .Lcptr_nvhe_\@: // nVHE case | 283 | .Lcptr_nvhe_\@: // nVHE case |
| 284 | mrs x0, cptr_el2 // Disable SVE traps | ||
| 281 | bic x0, x0, #CPTR_EL2_TZ | 285 | bic x0, x0, #CPTR_EL2_TZ |
| 282 | .Lset_cptr_\@: | ||
| 283 | msr cptr_el2, x0 | 286 | msr cptr_el2, x0 |
| 287 | .Lskip_set_cptr_\@: | ||
| 284 | isb | 288 | isb |
| 285 | mov x1, #ZCR_ELx_LEN_MASK // SVE: Enable full vector | 289 | mov x1, #ZCR_ELx_LEN_MASK // SVE: Enable full vector |
| 286 | msr_s SYS_ZCR_EL2, x1 // length for EL1. | 290 | msr_s SYS_ZCR_EL2, x1 // length for EL1. |
| @@ -289,9 +293,19 @@ · 2 unmodified lines | |||
| 289 | check_override id_aa64pfr1, ID_AA64PFR1_EL1_SME_SHIFT, .Linit_sme_\@, .Lskip_sme_\@, x1, x2 | 293 | check_override id_aa64pfr1, ID_AA64PFR1_EL1_SME_SHIFT, .Linit_sme_\@, .Lskip_sme_\@, x1, x2 |
| 290 | 294 | ||
| 291 | .Linit_sme_\@: /* SME register access and priority mapping */ | 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 | mrs x0, cptr_el2 // Disable SME traps | 305 | mrs x0, cptr_el2 // Disable SME traps |
| 293 | bic x0, x0, #CPTR_EL2_TSM | 306 | bic x0, x0, #CPTR_EL2_TSM |
| 294 | msr cptr_el2, x0 | 307 | msr cptr_el2, x0 |
| 308 | .Lskip_set_cptr_sme_\@: | ||
| 295 | isb | 309 | isb |
| 296 | 310 | ||
| 297 | mrs x1, sctlr_el2 | 311 | mrs x1, sctlr_el2 |
| @@ -278,7 +278,7 @@ asmlinkage void __noreturn hyp_panic_bad_stack(void); · 277 unmodified lines | |||
| 278 | asmlinkage void kvm_unexpected_el2_exception(void); | 278 | asmlinkage void kvm_unexpected_el2_exception(void); |
| 279 | struct kvm_cpu_context; | 279 | struct kvm_cpu_context; |
| 280 | void handle_trap(struct kvm_cpu_context *host_ctxt); | 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 | void __noreturn __pkvm_init_finalise(void); | 282 | void __noreturn __pkvm_init_finalise(void); |
| 283 | void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc); | 283 | void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc); |
| 284 | void kvm_patch_vector_branch(struct alt_instr *alt, | 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 | return test_bit(feature, vcpu->arch.features); | 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 | static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu) | 582 | static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu) |
| 575 | { | 583 | { |
| 576 | u64 val; | 584 | u64 val; |
| @@ -578,8 +586,16 @@ static __always_inline u64 kvm_get_reset_cptr_el2(struct kvm_vcpu *vcpu) · 1 unmodified line | |||
| 578 | if (has_vhe()) { | 586 | if (has_vhe()) { |
| 579 | val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN | | 587 | val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN | |
| 580 | CPACR_EL1_ZEN_EL1EN); | 588 | CPACR_EL1_ZEN_EL1EN); |
| 589 | if (cpus_have_final_cap(ARM64_SME)) | ||
| 590 | val |= CPACR_EL1_SMEN_EL1EN; | ||
| 581 | } else if (has_hvhe()) { | 591 | } else if (has_hvhe()) { |
| 582 | val = (CPACR_EL1_FPEN_EL0EN | CPACR_EL1_FPEN_EL1EN); | 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 | } else { | 599 | } else { |
| 584 | val = CPTR_NVHE_EL2_RES1; | 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 | u64 val = kvm_get_reset_cptr_el2(vcpu); | 614 | u64 val = kvm_get_reset_cptr_el2(vcpu); |
| 599 | 615 | ||
| 600 | if (has_vhe() || has_hvhe()) | 616 | kvm_write_cptr_el2(val); |
| 601 | write_sysreg(val, cpacr_el1); | ||
| 602 | else | ||
| 603 | write_sysreg(val, cptr_el2); | ||
| 604 | } | 617 | } |
| 605 | #endif /* __ARM64_KVM_EMULATE_H__ */ | 618 | #endif /* __ARM64_KVM_EMULATE_H__ */ |
| @@ -359,14 +359,6 @@ static inline void prefetchw(const void *ptr) · 358 unmodified lines | |||
| 359 | asm volatile("prfm pstl1keep, %a0\n" : : "p" (ptr)); | 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 | extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */ | 362 | extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */ |
| 371 | extern void __init minsigstksz_setup(void); | 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 | void *sst = task->thread.sve_state; | 679 | void *sst = task->thread.sve_state; |
| 680 | struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state; | 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 | return; | 683 | return; |
| 684 | 684 | ||
| 685 | vq = sve_vq_from_vl(thread_get_cur_vl(&task->thread)); | 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 | unsigned int i; | 705 | unsigned int i; |
| 706 | __uint128_t const *p; | 706 | __uint128_t const *p; |
| 707 | 707 | ||
| 708 | if (!system_supports_sve()) | 708 | if (!system_supports_sve() && !system_supports_sme()) |
| 709 | return; | 709 | return; |
| 710 | 710 | ||
| 711 | vl = thread_get_cur_vl(&task->thread); | 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 | void *sst = task->thread.sve_state; | 835 | void *sst = task->thread.sve_state; |
| 836 | struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state; | 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 | return; | 840 | return; |
| 840 | 841 | ||
| 841 | vq = sve_vq_from_vl(thread_get_cur_vl(&task->thread)); | 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 | task->thread.svcr &= ~(SVCR_SM_MASK | | 911 | task->thread.svcr &= ~(SVCR_SM_MASK | |
| 911 | SVCR_ZA_MASK); | 912 | SVCR_ZA_MASK); |
| 912 | clear_thread_flag(TIF_SME); | 913 | clear_tsk_thread_flag(task, TIF_SME); |
| 913 | free_sme = true; | 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 | * Ensure target->thread.sve_state is up to date with target's | 933 | * Ensure target->thread.sve_state is up to date with target's |
| 934 | * FPSIMD regs, so that a short copyin leaves trailing | 934 | * FPSIMD regs, so that a short copyin leaves trailing |
| 935 | * registers unmodified. Always enable SVE even if going into | 935 | * registers unmodified. Only enable SVE if we are |
| 936 | * streaming mode. | 936 | * configuring normal SVE, a system with streaming SVE may not |
| 937 | * have normal SVE. | ||
| 937 | */ | 938 | */ |
| 938 | fpsimd_sync_to_sve(target); | 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 | target->thread.fp_type = FP_STATE_SVE; | 942 | target->thread.fp_type = FP_STATE_SVE; |
| 941 | 943 | ||
| 942 | BUILD_BUG_ON(SVE_PT_SVE_OFFSET != sizeof(header)); | 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 | if (ret == 0) | 1182 | if (ret == 0) |
| 1181 | target->thread.svcr |= SVCR_ZA_MASK; | 1183 | target->thread.svcr |= SVCR_ZA_MASK; |
| 1182 | 1184 | ||
| 1185 | fpsimd_flush_task_state(target); | ||
| 1186 | |||
| 1183 | return ret; | 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 | static bool vgic_present, kvm_arm_initialised; | 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 | DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use); | 59 | DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use); |
| 60 | 60 | ||
| 61 | bool is_kvm_arm_initialised(void) | 61 | bool is_kvm_arm_initialised(void) |
| @@ -1864,18 +1864,24 @@ static void cpu_hyp_reinit(void) · 1802 unmodified lines | |||
| 1864 | cpu_hyp_init_features(); | 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 | cpu_hyp_reinit(); | 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 | * Most calls to this function are made with migration | 1886 | * Most calls to this function are made with migration |
| 1881 | * disabled, but not with preemption disabled. The former is | 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 | preempt_disable(); | 1891 | preempt_disable(); |
| 1886 | 1892 | ||
| 1887 | was_enabled = __this_cpu_read(kvm_arm_hardware_enabled); | 1893 | cpu_hyp_init(NULL); |
| 1888 | _kvm_arch_hardware_enable(NULL); | ||
| 1889 | 1894 | ||
| 1890 | if (!was_enabled) { | 1895 | kvm_vgic_cpu_up(); |
| 1891 | kvm_vgic_cpu_up(); | 1896 | kvm_timer_cpu_up(); |
| 1892 | kvm_timer_cpu_up(); | ||
| 1893 | } | ||
| 1894 | 1897 | ||
| 1895 | preempt_enable(); | 1898 | preempt_enable(); |
| 1896 | 1899 | ||
| 1897 | return 0; | 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 | void kvm_arch_hardware_disable(void) | 1903 | void kvm_arch_hardware_disable(void) |
| 1909 | { | 1904 | { |
| 1910 | if (__this_cpu_read(kvm_arm_hardware_enabled)) { | 1905 | kvm_timer_cpu_down(); |
| 1911 | kvm_timer_cpu_down(); | 1906 | kvm_vgic_cpu_down(); |
| 1912 | kvm_vgic_cpu_down(); | ||
| 1913 | } | ||
| 1914 | 1907 | ||
| 1915 | if (!is_protected_kvm_enabled()) | 1908 | if (!is_protected_kvm_enabled()) |
| 1916 | _kvm_arch_hardware_disable(NULL); | 1909 | cpu_hyp_uninit(NULL); |
| 1917 | } | 1910 | } |
| 1918 | 1911 | ||
| 1919 | #ifdef CONFIG_CPU_PM | 1912 | #ifdef CONFIG_CPU_PM |
| @@ -1922,16 +1915,16 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, · 2 unmodified lines | |||
| 1922 | void *v) | 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 | * PM_ENTER->PM_EXIT. It is used to indicate PM_EXIT should | 1919 | * PM_ENTER->PM_EXIT. It is used to indicate PM_EXIT should |
| 1927 | * re-enable hyp. | 1920 | * re-enable hyp. |
| 1928 | */ | 1921 | */ |
| 1929 | switch (cmd) { | 1922 | switch (cmd) { |
| 1930 | case CPU_PM_ENTER: | 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 | 1926 | * don't update kvm_hyp_initialized here |
| 1934 | * so that the hardware will be re-enabled | 1927 | * so that the hyp will be re-enabled |
| 1935 | * when we resume. See below. | 1928 | * when we resume. See below. |
| 1936 | */ | 1929 | */ |
| 1937 | cpu_hyp_reset(); | 1930 | cpu_hyp_reset(); |
| @@ -1939,8 +1932,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, · 1 unmodified line | |||
| 1939 | return NOTIFY_OK; | 1932 | return NOTIFY_OK; |
| 1940 | case CPU_PM_ENTER_FAILED: | 1933 | case CPU_PM_ENTER_FAILED: |
| 1941 | case CPU_PM_EXIT: | 1934 | case CPU_PM_EXIT: |
| 1942 | if (__this_cpu_read(kvm_arm_hardware_enabled)) | 1935 | if (__this_cpu_read(kvm_hyp_initialized)) |
| 1943 | /* The hardware was enabled before suspend. */ | 1936 | /* The hyp was enabled before suspend. */ |
| 1944 | cpu_hyp_reinit(); | 1937 | cpu_hyp_reinit(); |
| 1945 | 1938 | ||
| 1946 | return NOTIFY_OK; | 1939 | return NOTIFY_OK; |
| @@ -2021,7 +2014,7 @@ static int __init init_subsystems(void) · 74 unmodified lines | |||
| 2021 | /* | 2014 | /* |
| 2022 | * Enable hardware so that subsystem initialisation can access EL2. | 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 | * Register CPU lower-power notifier | 2020 | * Register CPU lower-power notifier |
| @@ -2059,7 +2052,7 @@ out: · 31 unmodified lines | |||
| 2059 | hyp_cpu_pm_exit(); | 2052 | hyp_cpu_pm_exit(); |
| 2060 | 2053 | ||
| 2061 | if (err || !is_protected_kvm_enabled()) | 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 | return err; | 2057 | return err; |
| 2065 | } | 2058 | } |
| @@ -2097,7 +2090,7 @@ static int __init do_pkvm_init(u32 hyp_va_bits) · 31 unmodified lines | |||
| 2097 | * The stub hypercalls are now disabled, so set our local flag to | 2090 | * The stub hypercalls are now disabled, so set our local flag to |
| 2098 | * prevent a later re-init attempt in kvm_arch_hardware_enable(). | 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 | preempt_enable(); | 2094 | preempt_enable(); |
| 2102 | 2095 | ||
| 2103 | return ret; | 2096 | return ret; |
| @@ -457,6 +457,7 @@ static bool handle_ampere1_tcr(struct kvm_vcpu *vcpu) · 456 unmodified lines | |||
| 457 | */ | 457 | */ |
| 458 | val &= ~(TCR_HD | TCR_HA); | 458 | val &= ~(TCR_HD | TCR_HA); |
| 459 | write_sysreg_el1(val, SYS_TCR); | 459 | write_sysreg_el1(val, SYS_TCR); |
| 460 | __kvm_skip_instr(vcpu); | ||
| 460 | return true; | 461 | return true; |
| 461 | } | 462 | } |
| 462 | 463 | ||
| @@ -705,7 +705,20 @@ int hyp_ffa_init(void *pages) · 704 unmodified lines | |||
| 705 | if (res.a0 == FFA_RET_NOT_SUPPORTED) | 705 | if (res.a0 == FFA_RET_NOT_SUPPORTED) |
| 706 | return 0; | 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 | return -EOPNOTSUPP; | 722 | return -EOPNOTSUPP; |
| 710 | 723 | ||
| 711 | arm_smccc_1_1_smc(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0, &res); | 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 | __activate_traps_fpsimd32(vcpu); | 63 | __activate_traps_fpsimd32(vcpu); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | write_sysreg(val, cptr_el2); | 66 | kvm_write_cptr_el2(val); |
| 67 | write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2); | 67 | write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2); |
| 68 | 68 | ||
| 69 | if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { | 69 | if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) { |
| @@ -634,7 +634,6 @@ ia64_imva (void *addr) · 633 unmodified lines | |||
| 634 | 634 | ||
| 635 | #define ARCH_HAS_PREFETCH | 635 | #define ARCH_HAS_PREFETCH |
| 636 | #define ARCH_HAS_PREFETCHW | 636 | #define ARCH_HAS_PREFETCHW |
| 637 | #define ARCH_HAS_SPINLOCK_PREFETCH | ||
| 638 | #define PREFETCH_STRIDE L1_CACHE_BYTES | 637 | #define PREFETCH_STRIDE L1_CACHE_BYTES |
| 639 | 638 | ||
| 640 | static inline void | 639 | static inline void |
| @@ -649,8 +648,6 @@ prefetchw (const void *x) · 8 unmodified lines | |||
| 649 | ia64_lfetch_excl(ia64_lfhint_none, x); | 648 | ia64_lfetch_excl(ia64_lfhint_none, x); |
| 650 | } | 649 | } |
| 651 | 650 | ||
| 652 | #define spin_lock_prefetch(x) prefetchw(x) | ||
| 653 | |||
| 654 | extern unsigned long boot_option_idle_override; | 651 | extern unsigned long boot_option_idle_override; |
| 655 | 652 | ||
| 656 | enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT, | 653 | enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_FORCE_MWAIT, |
| @@ -58,8 +58,6 @@ · 57 unmodified lines | |||
| 58 | 58 | ||
| 59 | #define cpu_has_rixi (cpu_data[0].cputype != CPU_CAVIUM_OCTEON) | 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 | #define PREFETCH_STRIDE 128 | 61 | #define PREFETCH_STRIDE 128 |
| 64 | 62 | ||
| 65 | #ifdef __OCTEON__ | 63 | #ifdef __OCTEON__ |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | # | 2 | # |
| 3 | config LIGHTWEIGHT_SPINLOCK_CHECK | 3 | config LIGHTWEIGHT_SPINLOCK_CHECK |
| 4 | bool "Enable lightweight spinlock checks" | 4 | bool "Enable lightweight spinlock checks" |
| 5 | depends on SMP && !DEBUG_SPINLOCK | 5 | depends on DEBUG_KERNEL && SMP && !DEBUG_SPINLOCK |
| 6 | default y | 6 | default y |
| 7 | help | 7 | help |
| 8 | Add checks with low performance impact to the spinlock functions | 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 | return NULL; | 117 | return NULL; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | int puts(const char *s) | 120 | static int puts(const char *s) |
| 121 | { | 121 | { |
| 122 | const char *nuline = s; | 122 | const char *nuline = s; |
| 123 | 123 | ||
| @@ -172,7 +172,7 @@ static int print_num(unsigned long num, int base) · 48 unmodified lines | |||
| 172 | return 0; | 172 | return 0; |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | int printf(const char *fmt, ...) | 175 | static int printf(const char *fmt, ...) |
| 176 | { | 176 | { |
| 177 | va_list args; | 177 | va_list args; |
| 178 | int i = 0; | 178 | int i = 0; |
| @@ -204,13 +204,13 @@ void abort(void) · 25 unmodified lines | |||
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | #undef malloc | 206 | #undef malloc |
| 207 | void *malloc(size_t size) | 207 | static void *malloc(size_t size) |
| 208 | { | 208 | { |
| 209 | return malloc_gzip(size); | 209 | return malloc_gzip(size); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | #undef free | 212 | #undef free |
| 213 | void free(void *ptr) | 213 | static void free(void *ptr) |
| 214 | { | 214 | { |
| 215 | return free_gzip(ptr); | 215 | return free_gzip(ptr); |
| 216 | } | 216 | } |
| @@ -278,7 +278,7 @@ static void parse_elf(void *output) · 61 unmodified lines | |||
| 278 | free(phdrs); | 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 | unsigned int command_line, | 282 | unsigned int command_line, |
| 283 | const unsigned int rd_start, | 283 | const unsigned int rd_start, |
| 284 | const unsigned int rd_end) | 284 | const unsigned int rd_end) |
| @@ -14,6 +14,8 @@ · 13 unmodified lines | |||
| 14 | #define dma_outb outb | 14 | #define dma_outb outb |
| 15 | #define dma_inb inb | 15 | #define dma_inb inb |
| 16 | 16 | ||
| 17 | extern unsigned long pcxl_dma_start; | ||
| 18 | |||
| 17 | /* | 19 | /* |
| 18 | ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up | 20 | ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up |
| 19 | ** (or rather not merge) DMAs into manageable chunks. | 21 | ** (or rather not merge) DMAs into manageable chunks. |
| @@ -12,6 +12,10 @@ extern void mcount(void); · 11 unmodified lines | |||
| 12 | extern unsigned long sys_call_table[]; | 12 | extern unsigned long sys_call_table[]; |
| 13 | 13 | ||
| 14 | extern unsigned long return_address(unsigned int); | 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 | #ifdef CONFIG_DYNAMIC_FTRACE | 20 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 17 | extern void ftrace_caller(void); | 21 | extern void ftrace_caller(void); |
| @@ -7,8 +7,6 @@ · 6 unmodified lines | |||
| 7 | #include <asm/processor.h> | 7 | #include <asm/processor.h> |
| 8 | #include <asm/spinlock_types.h> | 8 | #include <asm/spinlock_types.h> |
| 9 | 9 | ||
| 10 | #define SPINLOCK_BREAK_INSN 0x0000c006 /* break 6,6 */ | ||
| 11 | |||
| 12 | static inline void arch_spin_val_check(int lock_val) | 10 | static inline void arch_spin_val_check(int lock_val) |
| 13 | { | 11 | { |
| 14 | if (IS_ENABLED(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK)) | 12 | if (IS_ENABLED(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK)) |
| @@ -4,6 +4,10 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #define __ARCH_SPIN_LOCK_UNLOCKED_VAL 0x1a46 | 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 | typedef struct { | 11 | typedef struct { |
| 8 | #ifdef CONFIG_PA20 | 12 | #ifdef CONFIG_PA20 |
| 9 | volatile unsigned int slock; | 13 | volatile unsigned int slock; |
| @@ -27,6 +31,8 @@ typedef struct { · 17 unmodified lines | |||
| 27 | volatile unsigned int counter; | 31 | volatile unsigned int counter; |
| 28 | } arch_rwlock_t; | 32 | } arch_rwlock_t; |
| 29 | 33 | ||
| 34 | #endif /* __ASSEMBLY__ */ | ||
| 35 | |||
| 30 | #define __ARCH_RW_LOCK_UNLOCKED__ 0x01000000 | 36 | #define __ARCH_RW_LOCK_UNLOCKED__ 0x01000000 |
| 31 | #define __ARCH_RW_LOCK_UNLOCKED { .lock_mutex = __ARCH_SPIN_LOCK_UNLOCKED, \ | 37 | #define __ARCH_RW_LOCK_UNLOCKED { .lock_mutex = __ARCH_SPIN_LOCK_UNLOCKED, \ |
| 32 | .counter = __ARCH_RW_LOCK_UNLOCKED__ } | 38 | .counter = __ARCH_RW_LOCK_UNLOCKED__ } |
| @@ -74,8 +74,8 @@ · 73 unmodified lines | |||
| 74 | static DEFINE_SPINLOCK(pdc_lock); | 74 | static DEFINE_SPINLOCK(pdc_lock); |
| 75 | #endif | 75 | #endif |
| 76 | 76 | ||
| 77 | unsigned long pdc_result[NUM_PDC_RESULT] __aligned(8); | 77 | static unsigned long pdc_result[NUM_PDC_RESULT] __aligned(8); |
| 78 | unsigned long pdc_result2[NUM_PDC_RESULT] __aligned(8); | 78 | static unsigned long pdc_result2[NUM_PDC_RESULT] __aligned(8); |
| 79 | 79 | ||
| 80 | #ifdef CONFIG_64BIT | 80 | #ifdef CONFIG_64BIT |
| 81 | #define WIDE_FIRMWARE 0x1 | 81 | #define WIDE_FIRMWARE 0x1 |
| @@ -334,7 +334,7 @@ int __pdc_cpu_rendezvous(void) · 252 unmodified lines | |||
| 334 | /** | 334 | /** |
| 335 | * pdc_cpu_rendezvous_lock - Lock PDC while transitioning to rendezvous state | 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 | spin_lock(&pdc_lock); | 339 | spin_lock(&pdc_lock); |
| 340 | } | 340 | } |
| @@ -342,7 +342,7 @@ void pdc_cpu_rendezvous_lock(void) · 1 unmodified line | |||
| 342 | /** | 342 | /** |
| 343 | * pdc_cpu_rendezvous_unlock - Unlock PDC after reaching rendezvous state | 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 | spin_unlock(&pdc_lock); | 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 | static ftrace_func_t ftrace_func; | 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 | unsigned long self_addr, | 57 | unsigned long self_addr, |
| 58 | unsigned long org_sp_gr3, | 58 | unsigned long org_sp_gr3, |
| 59 | struct ftrace_regs *fregs) | 59 | struct ftrace_regs *fregs) |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/syscalls.h> | 16 | #include <linux/syscalls.h> |
| 17 | #include <linux/libgcc.h> | ||
| 17 | 18 | ||
| 18 | #include <linux/string.h> | 19 | #include <linux/string.h> |
| 19 | EXPORT_SYMBOL(memset); | 20 | EXPORT_SYMBOL(memset); |
| @@ -92,12 +93,6 @@ EXPORT_SYMBOL($$divI_12); · 72 unmodified lines | |||
| 92 | EXPORT_SYMBOL($$divI_14); | 93 | EXPORT_SYMBOL($$divI_14); |
| 93 | EXPORT_SYMBOL($$divI_15); | 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 | EXPORT_SYMBOL(__ashrdi3); | 96 | EXPORT_SYMBOL(__ashrdi3); |
| 102 | EXPORT_SYMBOL(__ashldi3); | 97 | EXPORT_SYMBOL(__ashldi3); |
| 103 | EXPORT_SYMBOL(__lshrdi3); | 98 | EXPORT_SYMBOL(__lshrdi3); |
| @@ -39,7 +39,7 @@ static struct proc_dir_entry * proc_gsc_root __read_mostly = NULL; · 38 unmodified lines | |||
| 39 | static unsigned long pcxl_used_bytes __read_mostly; | 39 | static unsigned long pcxl_used_bytes __read_mostly; |
| 40 | static unsigned long pcxl_used_pages __read_mostly; | 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 | static DEFINE_SPINLOCK(pcxl_res_lock); | 43 | static DEFINE_SPINLOCK(pcxl_res_lock); |
| 44 | static char *pcxl_res_map; | 44 | static char *pcxl_res_map; |
| 45 | static int pcxl_res_hint; | 45 | static int pcxl_res_hint; |
| @@ -381,7 +381,7 @@ pcxl_dma_init(void) · 335 unmodified lines | |||
| 381 | pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL, | 381 | pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL, |
| 382 | get_order(pcxl_res_size)); | 382 | get_order(pcxl_res_size)); |
| 383 | memset(pcxl_res_map, 0, pcxl_res_size); | 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 | if (!proc_gsc_root) | 385 | if (!proc_gsc_root) |
| 386 | printk(KERN_WARNING | 386 | printk(KERN_WARNING |
| 387 | "pcxl_dma_init: Unable to create gsc /proc dir entry\n"); | 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 | map_uncached_pages(vaddr, size, paddr); | 417 | map_uncached_pages(vaddr, size, paddr); |
| 418 | *dma_handle = (dma_addr_t) paddr; | 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 | return (void *)vaddr; | 420 | return (void *)vaddr; |
| 429 | } | 421 | } |
| 430 | 422 | ||
| @@ -354,10 +354,8 @@ static int __init pdt_initcall(void) · 353 unmodified lines | |||
| 354 | return -ENODEV; | 354 | return -ENODEV; |
| 355 | 355 | ||
| 356 | kpdtd_task = kthread_run(pdt_mainloop, NULL, "kpdtd"); | 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 | late_initcall(pdt_initcall); | 361 | late_initcall(pdt_initcall); |
| @@ -57,7 +57,7 @@ struct rdr_tbl_ent { · 56 unmodified lines | |||
| 57 | static int perf_processor_interface __read_mostly = UNKNOWN_INTF; | 57 | static int perf_processor_interface __read_mostly = UNKNOWN_INTF; |
| 58 | static int perf_enabled __read_mostly; | 58 | static int perf_enabled __read_mostly; |
| 59 | static DEFINE_SPINLOCK(perf_lock); | 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 | /* RDRs to write for PCX-W */ | 62 | /* RDRs to write for PCX-W */ |
| 63 | static const int perf_rdrs_W[] = | 63 | static const int perf_rdrs_W[] = |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | |||
| 26 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
| 27 | #include <asm/page.h> | 27 | #include <asm/page.h> |
| 28 | #include <asm/pdc.h> | 28 | #include <asm/pdc.h> |
| 29 | #include <asm/smp.h> | ||
| 29 | #include <asm/pdcpat.h> | 30 | #include <asm/pdcpat.h> |
| 30 | #include <asm/irq.h> /* for struct irq_region */ | 31 | #include <asm/irq.h> /* for struct irq_region */ |
| 31 | #include <asm/parisc-device.h> | 32 | #include <asm/parisc-device.h> |
| @@ -40,11 +40,6 @@ · 39 unmodified lines | |||
| 40 | 40 | ||
| 41 | static char __initdata command_line[COMMAND_LINE_SIZE]; | 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 | static void __init setup_cmdline(char **cmdline_p) | 43 | static void __init setup_cmdline(char **cmdline_p) |
| 49 | { | 44 | { |
| 50 | extern unsigned int boot_args[]; | 45 | extern unsigned int boot_args[]; |
| @@ -196,48 +191,6 @@ const struct seq_operations cpuinfo_op = { · 145 unmodified lines | |||
| 196 | .show = show_cpuinfo | 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 | static struct resource central_bus = { | 194 | static struct resource central_bus = { |
| 242 | .name = "Central Bus", | 195 | .name = "Central Bus", |
| 243 | .start = F_EXTEND(0xfff80000), | 196 | .start = F_EXTEND(0xfff80000), |
| @@ -294,7 +247,6 @@ static int __init parisc_init(void) · 50 unmodified lines | |||
| 294 | { | 247 | { |
| 295 | u32 osid = (OS_ID_LINUX << 16); | 248 | u32 osid = (OS_ID_LINUX << 16); |
| 296 | 249 | ||
| 297 | parisc_proc_mkdir(); | ||
| 298 | parisc_init_resources(); | 250 | parisc_init_resources(); |
| 299 | do_device_inventory(); /* probe for hardware */ | 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 | regs->gr[31] -= 8; /* delayed branching */ | 423 | regs->gr[31] -= 8; /* delayed branching */ |
| 424 | 424 | ||
| 425 | /* Get assembler opcode of code in delay branch */ | 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 | err = get_user(opcode, uaddr); | 427 | err = get_user(opcode, uaddr); |
| 428 | if (err) | 428 | if (err) |
| 429 | return; | 429 | return; |
| @@ -27,17 +27,12 @@ · 26 unmodified lines | |||
| 27 | #include <linux/elf-randomize.h> | 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 | * address of the kernel file mapping variable. | 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) \ | 33 | #define GET_FILP_PGOFF(filp) \ |
| 38 | ((filp ? (((unsigned long) filp->f_mapping) >> 8) \ | 34 | (filp ? (((unsigned long) filp->f_mapping) >> 8) \ |
| 39 | & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL) \ | 35 | & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL) |
| 40 | + (addr >> PAGE_SHIFT)) | ||
| 41 | 36 | ||
| 42 | static unsigned long shared_align_offset(unsigned long filp_pgoff, | 37 | static unsigned long shared_align_offset(unsigned long filp_pgoff, |
| 43 | unsigned long pgoff) | 38 | unsigned long pgoff) |
| @@ -117,7 +112,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp, · 73 unmodified lines | |||
| 117 | do_color_align = 0; | 112 | do_color_align = 0; |
| 118 | if (filp || (flags & MAP_SHARED)) | 113 | if (filp || (flags & MAP_SHARED)) |
| 119 | do_color_align = 1; | 114 | do_color_align = 1; |
| 120 | filp_pgoff = GET_FILP_PGOFF(filp, addr); | 115 | filp_pgoff = GET_FILP_PGOFF(filp); |
| 121 | 116 | ||
| 122 | if (flags & MAP_FIXED) { | 117 | if (flags & MAP_FIXED) { |
| 123 | /* Even MAP_FIXED mappings must reside within TASK_SIZE */ | 118 | /* Even MAP_FIXED mappings must reside within TASK_SIZE */ |
| @@ -39,6 +39,7 @@ registers). · 38 unmodified lines | |||
| 39 | #include <asm/assembly.h> | 39 | #include <asm/assembly.h> |
| 40 | #include <asm/processor.h> | 40 | #include <asm/processor.h> |
| 41 | #include <asm/cache.h> | 41 | #include <asm/cache.h> |
| 42 | #include <asm/spinlock_types.h> | ||
| 42 | 43 | ||
| 43 | #include <linux/linkage.h> | 44 | #include <linux/linkage.h> |
| 44 | 45 | ||
| @@ -66,6 +67,16 @@ registers). · 21 unmodified lines | |||
| 66 | stw \reg1, 0(%sr2,\reg2) | 67 | stw \reg1, 0(%sr2,\reg2) |
| 67 | .endm | 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 | .text | 80 | .text |
| 70 | 81 | ||
| 71 | .import syscall_exit,code | 82 | .import syscall_exit,code |
| @@ -508,7 +519,8 @@ lws_start: · 436 unmodified lines | |||
| 508 | 519 | ||
| 509 | lws_exit_noerror: | 520 | lws_exit_noerror: |
| 510 | lws_pagefault_enable %r1,%r21 | 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 | ssm PSW_SM_I, %r0 | 524 | ssm PSW_SM_I, %r0 |
| 513 | b lws_exit | 525 | b lws_exit |
| 514 | copy %r0, %r21 | 526 | copy %r0, %r21 |
| @@ -521,7 +533,8 @@ lws_wouldblock: · 6 unmodified lines | |||
| 521 | 533 | ||
| 522 | lws_pagefault: | 534 | lws_pagefault: |
| 523 | lws_pagefault_enable %r1,%r21 | 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 | ssm PSW_SM_I, %r0 | 538 | ssm PSW_SM_I, %r0 |
| 526 | ldo 3(%r0),%r28 | 539 | ldo 3(%r0),%r28 |
| 527 | b lws_exit | 540 | b lws_exit |
| @@ -619,6 +632,7 @@ lws_compare_and_swap: · 91 unmodified lines | |||
| 619 | 632 | ||
| 620 | /* Try to acquire the lock */ | 633 | /* Try to acquire the lock */ |
| 621 | LDCW 0(%sr2,%r20), %r28 | 634 | LDCW 0(%sr2,%r20), %r28 |
| 635 | spinlock_check %r28, %r21 | ||
| 622 | comclr,<> %r0, %r28, %r0 | 636 | comclr,<> %r0, %r28, %r0 |
| 623 | b,n lws_wouldblock | 637 | b,n lws_wouldblock |
| 624 | 638 | ||
| @@ -772,6 +786,7 @@ cas2_lock_start: · 147 unmodified lines | |||
| 772 | 786 | ||
| 773 | /* Try to acquire the lock */ | 787 | /* Try to acquire the lock */ |
| 774 | LDCW 0(%sr2,%r20), %r28 | 788 | LDCW 0(%sr2,%r20), %r28 |
| 789 | spinlock_check %r28, %r21 | ||
| 775 | comclr,<> %r0, %r28, %r0 | 790 | comclr,<> %r0, %r28, %r0 |
| 776 | b,n lws_wouldblock | 791 | b,n lws_wouldblock |
| 777 | 792 | ||
| @@ -1001,6 +1016,7 @@ atomic_xchg_start: · 223 unmodified lines | |||
| 1001 | 1016 | ||
| 1002 | /* Try to acquire the lock */ | 1017 | /* Try to acquire the lock */ |
| 1003 | LDCW 0(%sr2,%r20), %r28 | 1018 | LDCW 0(%sr2,%r20), %r28 |
| 1019 | spinlock_check %r28, %r21 | ||
| 1004 | comclr,<> %r0, %r28, %r0 | 1020 | comclr,<> %r0, %r28, %r0 |
| 1005 | b,n lws_wouldblock | 1021 | b,n lws_wouldblock |
| 1006 | 1022 | ||
| @@ -1199,6 +1215,7 @@ atomic_store_start: · 192 unmodified lines | |||
| 1199 | 1215 | ||
| 1200 | /* Try to acquire the lock */ | 1216 | /* Try to acquire the lock */ |
| 1201 | LDCW 0(%sr2,%r20), %r28 | 1217 | LDCW 0(%sr2,%r20), %r28 |
| 1218 | spinlock_check %r28, %r21 | ||
| 1202 | comclr,<> %r0, %r28, %r0 | 1219 | comclr,<> %r0, %r28, %r0 |
| 1203 | b,n lws_wouldblock | 1220 | b,n lws_wouldblock |
| 1204 | 1221 | ||
| @@ -1330,7 +1347,7 @@ ENTRY(lws_lock_start) · 125 unmodified lines | |||
| 1330 | /* lws locks */ | 1347 | /* lws locks */ |
| 1331 | .rept 256 | 1348 | .rept 256 |
| 1332 | /* Keep locks aligned at 16-bytes */ | 1349 | /* Keep locks aligned at 16-bytes */ |
| 1333 | .word 1 | 1350 | .word __ARCH_SPIN_LOCK_UNLOCKED_VAL |
| 1334 | .word 0 | 1351 | .word 0 |
| 1335 | .word 0 | 1352 | .word 0 |
| 1336 | .word 0 | 1353 | .word 0 |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <linux/signal.h> | 11 | #include <linux/signal.h> |
| 12 | #include <linux/ratelimit.h> | 12 | #include <linux/ratelimit.h> |
| 13 | #include <linux/uaccess.h> | 13 | #include <linux/uaccess.h> |
| 14 | #include <linux/sysctl.h> | ||
| 14 | #include <asm/unaligned.h> | 15 | #include <asm/unaligned.h> |
| 15 | #include <asm/hardirq.h> | 16 | #include <asm/hardirq.h> |
| 16 | #include <asm/traps.h> | 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 | : "r19", "r20", "r21", "r22", "r1" ); | 338 | : "r19", "r20", "r21", "r22", "r1" ); |
| 338 | #else | 339 | #else |
| 339 | { | 340 | { |
| 340 | unsigned long valh=(val>>32),vall=(val&0xffffffffl); | 341 | unsigned long valh = (val >> 32), vall = (val & 0xffffffffl); |
| 341 | __asm__ __volatile__ ( | 342 | __asm__ __volatile__ ( |
| 342 | " mtsp %4, %%sr1\n" | 343 | " mtsp %4, %%sr1\n" |
| 343 | " zdep %2, 29, 2, %%r19\n" | 344 | " zdep %2, 29, 2, %%r19\n" |
| @@ -473,7 +474,7 @@ void handle_unaligned(struct pt_regs *regs) · 129 unmodified lines | |||
| 473 | case OPCODE_LDWA_I: | 474 | case OPCODE_LDWA_I: |
| 474 | case OPCODE_LDW_S: | 475 | case OPCODE_LDW_S: |
| 475 | case OPCODE_LDWA_S: | 476 | case OPCODE_LDWA_S: |
| 476 | ret = emulate_ldw(regs, R3(regs->iir),0); | 477 | ret = emulate_ldw(regs, R3(regs->iir), 0); |
| 477 | break; | 478 | break; |
| 478 | 479 | ||
| 479 | case OPCODE_STH: | 480 | case OPCODE_STH: |
| @@ -482,7 +483,7 @@ void handle_unaligned(struct pt_regs *regs) · 2 unmodified lines | |||
| 482 | 483 | ||
| 483 | case OPCODE_STW: | 484 | case OPCODE_STW: |
| 484 | case OPCODE_STWA: | 485 | case OPCODE_STWA: |
| 485 | ret = emulate_stw(regs, R2(regs->iir),0); | 486 | ret = emulate_stw(regs, R2(regs->iir), 0); |
| 486 | break; | 487 | break; |
| 487 | 488 | ||
| 488 | #ifdef CONFIG_64BIT | 489 | #ifdef CONFIG_64BIT |
| @@ -490,12 +491,12 @@ void handle_unaligned(struct pt_regs *regs) · 1 unmodified line | |||
| 490 | case OPCODE_LDDA_I: | 491 | case OPCODE_LDDA_I: |
| 491 | case OPCODE_LDD_S: | 492 | case OPCODE_LDD_S: |
| 492 | case OPCODE_LDDA_S: | 493 | case OPCODE_LDDA_S: |
| 493 | ret = emulate_ldd(regs, R3(regs->iir),0); | 494 | ret = emulate_ldd(regs, R3(regs->iir), 0); |
| 494 | break; | 495 | break; |
| 495 | 496 | ||
| 496 | case OPCODE_STD: | 497 | case OPCODE_STD: |
| 497 | case OPCODE_STDA: | 498 | case OPCODE_STDA: |
| 498 | ret = emulate_std(regs, R2(regs->iir),0); | 499 | ret = emulate_std(regs, R2(regs->iir), 0); |
| 499 | break; | 500 | break; |
| 500 | #endif | 501 | #endif |
| 501 | 502 | ||
| @@ -503,24 +504,24 @@ void handle_unaligned(struct pt_regs *regs) · 1 unmodified line | |||
| 503 | case OPCODE_FLDWS: | 504 | case OPCODE_FLDWS: |
| 504 | case OPCODE_FLDWXR: | 505 | case OPCODE_FLDWXR: |
| 505 | case OPCODE_FLDWSR: | 506 | case OPCODE_FLDWSR: |
| 506 | ret = emulate_ldw(regs,FR3(regs->iir),1); | 507 | ret = emulate_ldw(regs, FR3(regs->iir), 1); |
| 507 | break; | 508 | break; |
| 508 | 509 | ||
| 509 | case OPCODE_FLDDX: | 510 | case OPCODE_FLDDX: |
| 510 | case OPCODE_FLDDS: | 511 | case OPCODE_FLDDS: |
| 511 | ret = emulate_ldd(regs,R3(regs->iir),1); | 512 | ret = emulate_ldd(regs, R3(regs->iir), 1); |
| 512 | break; | 513 | break; |
| 513 | 514 | ||
| 514 | case OPCODE_FSTWX: | 515 | case OPCODE_FSTWX: |
| 515 | case OPCODE_FSTWS: | 516 | case OPCODE_FSTWS: |
| 516 | case OPCODE_FSTWXR: | 517 | case OPCODE_FSTWXR: |
| 517 | case OPCODE_FSTWSR: | 518 | case OPCODE_FSTWSR: |
| 518 | ret = emulate_stw(regs,FR3(regs->iir),1); | 519 | ret = emulate_stw(regs, FR3(regs->iir), 1); |
| 519 | break; | 520 | break; |
| 520 | 521 | ||
| 521 | case OPCODE_FSTDX: | 522 | case OPCODE_FSTDX: |
| 522 | case OPCODE_FSTDS: | 523 | case OPCODE_FSTDS: |
| 523 | ret = emulate_std(regs,R3(regs->iir),1); | 524 | ret = emulate_std(regs, R3(regs->iir), 1); |
| 524 | break; | 525 | break; |
| 525 | 526 | ||
| 526 | case OPCODE_LDCD_I: | 527 | case OPCODE_LDCD_I: |
| @@ -1,5 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | #include <linux/module.h> | 2 | #include <linux/module.h> |
| 3 | #include <linux/libgcc.h> | ||
| 3 | 4 | ||
| 4 | union ull_union { | 5 | union ull_union { |
| 5 | unsigned long long ull; | 6 | unsigned long long ull; |
| @@ -9,7 +10,7 @@ union ull_union { · 3 unmodified lines | |||
| 9 | } ui; | 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 | union ull_union au = {.ull = a}; | 15 | union ull_union au = {.ull = a}; |
| 15 | union ull_union bu = {.ull = b}; | 16 | union ull_union bu = {.ull = b}; |
| @@ -192,31 +192,31 @@ int fixup_exception(struct pt_regs *regs) · 191 unmodified lines | |||
| 192 | * For implementation see handle_interruption() in traps.c | 192 | * For implementation see handle_interruption() in traps.c |
| 193 | */ | 193 | */ |
| 194 | static const char * const trap_description[] = { | 194 | static const char * const trap_description[] = { |
| 195 | [1] "High-priority machine check (HPMC)", | 195 | [1] = "High-priority machine check (HPMC)", |
| 196 | [2] "Power failure interrupt", | 196 | [2] = "Power failure interrupt", |
| 197 | [3] "Recovery counter trap", | 197 | [3] = "Recovery counter trap", |
| 198 | [5] "Low-priority machine check", | 198 | [5] = "Low-priority machine check", |
| 199 | [6] "Instruction TLB miss fault", | 199 | [6] = "Instruction TLB miss fault", |
| 200 | [7] "Instruction access rights / protection trap", | 200 | [7] = "Instruction access rights / protection trap", |
| 201 | [8] "Illegal instruction trap", | 201 | [8] = "Illegal instruction trap", |
| 202 | [9] "Break instruction trap", | 202 | [9] = "Break instruction trap", |
| 203 | [10] "Privileged operation trap", | 203 | [10] = "Privileged operation trap", |
| 204 | [11] "Privileged register trap", | 204 | [11] = "Privileged register trap", |
| 205 | [12] "Overflow trap", | 205 | [12] = "Overflow trap", |
| 206 | [13] "Conditional trap", | 206 | [13] = "Conditional trap", |
| 207 | [14] "FP Assist Exception trap", | 207 | [14] = "FP Assist Exception trap", |
| 208 | [15] "Data TLB miss fault", | 208 | [15] = "Data TLB miss fault", |
| 209 | [16] "Non-access ITLB miss fault", | 209 | [16] = "Non-access ITLB miss fault", |
| 210 | [17] "Non-access DTLB miss fault", | 210 | [17] = "Non-access DTLB miss fault", |
| 211 | [18] "Data memory protection/unaligned access trap", | 211 | [18] = "Data memory protection/unaligned access trap", |
| 212 | [19] "Data memory break trap", | 212 | [19] = "Data memory break trap", |
| 213 | [20] "TLB dirty bit trap", | 213 | [20] = "TLB dirty bit trap", |
| 214 | [21] "Page reference trap", | 214 | [21] = "Page reference trap", |
| 215 | [22] "Assist emulation trap", | 215 | [22] = "Assist emulation trap", |
| 216 | [25] "Taken branch trap", | 216 | [25] = "Taken branch trap", |
| 217 | [26] "Data memory access rights trap", | 217 | [26] = "Data memory access rights trap", |
| 218 | [27] "Data memory protection ID trap", | 218 | [27] = "Data memory protection ID trap", |
| 219 | [28] "Unaligned data reference trap", | 219 | [28] = "Unaligned data reference trap", |
| 220 | }; | 220 | }; |
| 221 | 221 | ||
| 222 | const char *trap_name(unsigned long code) | 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 | pmd_t *pmd = pmd_offset(pud, vaddr); | 19 | pmd_t *pmd = pmd_offset(pud, vaddr); |
| 20 | pte_t *pte; | 20 | pte_t *pte; |
| 21 | 21 | ||
| 22 | if (pmd_none(*pmd)) | ||
| 23 | pte = pte_alloc_kernel(pmd, vaddr); | ||
| 24 | |||
| 25 | pte = pte_offset_kernel(pmd, vaddr); | 22 | pte = pte_offset_kernel(pmd, vaddr); |
| 26 | set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX)); | 23 | set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX)); |
| 27 | flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); | 24 | flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE); |
| @@ -523,10 +523,6 @@ void mark_rodata_ro(void) · 522 unmodified lines | |||
| 523 | void *parisc_vmalloc_start __ro_after_init; | 523 | void *parisc_vmalloc_start __ro_after_init; |
| 524 | EXPORT_SYMBOL(parisc_vmalloc_start); | 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 | void __init mem_init(void) | 526 | void __init mem_init(void) |
| 531 | { | 527 | { |
| 532 | /* Do sanity checks on IPC (compat) structures */ | 528 | /* Do sanity checks on IPC (compat) structures */ |
| @@ -669,6 +665,39 @@ static void __init gateway_init(void) · 136 unmodified lines | |||
| 669 | PAGE_SIZE, PAGE_GATEWAY, 1); | 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 | static void __init parisc_bootmem_free(void) | 701 | static void __init parisc_bootmem_free(void) |
| 673 | { | 702 | { |
| 674 | unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, }; | 703 | unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, }; |
| @@ -683,6 +712,7 @@ void __init paging_init(void) · 8 unmodified lines | |||
| 683 | setup_bootmem(); | 712 | setup_bootmem(); |
| 684 | pagetable_init(); | 713 | pagetable_init(); |
| 685 | gateway_init(); | 714 | gateway_init(); |
| 715 | fixmap_init(); | ||
| 686 | flush_cache_all_local(); /* start with known state */ | 716 | flush_cache_all_local(); /* start with known state */ |
| 687 | flush_tlb_all_local(NULL); | 717 | flush_tlb_all_local(NULL); |
| 688 | 718 | ||
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | */ | 27 | */ |
| 28 | void __iomem *ioremap(unsigned long phys_addr, unsigned long size) | 28 | void __iomem *ioremap(unsigned long phys_addr, unsigned long size) |
| 29 | { | 29 | { |
| 30 | void __iomem *addr; | 30 | uintptr_t addr; |
| 31 | struct vm_struct *area; | 31 | struct vm_struct *area; |
| 32 | unsigned long offset, last_addr; | 32 | unsigned long offset, last_addr; |
| 33 | pgprot_t pgprot; | 33 | pgprot_t pgprot; |
| @@ -79,10 +79,9 @@ void __iomem *ioremap(unsigned long phys_addr, unsigned long size) · 45 unmodified lines | |||
| 79 | if (!area) | 79 | if (!area) |
| 80 | return NULL; | 80 | return NULL; |
| 81 | 81 | ||
| 82 | addr = (void __iomem *) area->addr; | 82 | addr = (uintptr_t) area->addr; |
| 83 | if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, | 83 | if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { |
| 84 | phys_addr, pgprot)) { | 84 | vunmap(area->addr); |
| 85 | vunmap(addr); | ||
| 86 | return NULL; | 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 | #define ARCH_HAS_PREFETCH | 394 | #define ARCH_HAS_PREFETCH |
| 395 | #define ARCH_HAS_PREFETCHW | 395 | #define ARCH_HAS_PREFETCHW |
| 396 | #define ARCH_HAS_SPINLOCK_PREFETCH | ||
| 397 | 396 | ||
| 398 | static inline void prefetch(const void *x) | 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 | __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (x)); | 410 | __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (x)); |
| 412 | } | 411 | } |
| 413 | 412 | ||
| 414 | #define spin_lock_prefetch(x) prefetchw(x) | ||
| 415 | |||
| 416 | /* asm stubs */ | 413 | /* asm stubs */ |
| 417 | extern unsigned long isa300_idle_stop_noloss(unsigned long psscr_val); | 414 | extern unsigned long isa300_idle_stop_noloss(unsigned long psscr_val); |
| 418 | extern unsigned long isa300_idle_stop_mayloss(unsigned long psscr_val); | 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 | return leading_zero_bits >> 3; | 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 | unsigned long rhs = val | c->low_bits; | 39 | unsigned long rhs = val | c->low_bits; |
| 40 | *data = rhs; | 40 | *data = rhs; |
| @@ -375,8 +375,7 @@ _GLOBAL(generic_secondary_smp_init) · 374 unmodified lines | |||
| 375 | beq 20f | 375 | beq 20f |
| 376 | 376 | ||
| 377 | /* start the specified thread */ | 377 | /* start the specified thread */ |
| 378 | LOAD_REG_ADDR(r5, fsl_secondary_thread_init) | 378 | LOAD_REG_ADDR(r5, DOTSYM(fsl_secondary_thread_init)) |
| 379 | ld r4, 0(r5) | ||
| 380 | bl book3e_start_thread | 379 | bl book3e_start_thread |
| 381 | 380 | ||
| 382 | /* stop the current thread */ | 381 | /* stop the current thread */ |
| @@ -33,6 +33,9 @@ · 32 unmodified lines | |||
| 33 | * and then arrange for the ftrace function to be called. | 33 | * and then arrange for the ftrace function to be called. |
| 34 | */ | 34 | */ |
| 35 | .macro ftrace_regs_entry allregs | 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 | /* Create our stack frame + pt_regs */ | 39 | /* Create our stack frame + pt_regs */ |
| 37 | PPC_STLU r1,-SWITCH_FRAME_SIZE(r1) | 40 | PPC_STLU r1,-SWITCH_FRAME_SIZE(r1) |
| 38 | 41 | ||
| @@ -42,7 +45,7 @@ · 3 unmodified lines | |||
| 42 | 45 | ||
| 43 | #ifdef CONFIG_PPC64 | 46 | #ifdef CONFIG_PPC64 |
| 44 | /* Save the original return address in A's stack frame */ | 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 | /* Ok to continue? */ | 49 | /* Ok to continue? */ |
| 47 | lbz r3, PACA_FTRACE_ENABLED(r13) | 50 | lbz r3, PACA_FTRACE_ENABLED(r13) |
| 48 | cmpdi r3, 0 | 51 | cmpdi r3, 0 |
| @@ -77,6 +80,8 @@ · 28 unmodified lines | |||
| 77 | mflr r7 | 80 | mflr r7 |
| 78 | /* Save it as pt_regs->nip */ | 81 | /* Save it as pt_regs->nip */ |
| 79 | PPC_STL r7, _NIP(r1) | 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 | /* Save the read LR in pt_regs->link */ | 85 | /* Save the read LR in pt_regs->link */ |
| 81 | PPC_STL r0, _LINK(r1) | 86 | PPC_STL r0, _LINK(r1) |
| 82 | 87 | ||
| @@ -142,7 +147,7 @@ · 59 unmodified lines | |||
| 142 | #endif | 147 | #endif |
| 143 | 148 | ||
| 144 | /* Pop our stack frame */ | 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 | #ifdef CONFIG_LIVEPATCH_64 | 152 | #ifdef CONFIG_LIVEPATCH_64 |
| 148 | /* Based on the cmpd above, if the NIP was altered handle livepatch */ | 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 | start = ALIGN_DOWN(start, page_size); | 314 | start = ALIGN_DOWN(start, page_size); |
| 315 | if (altmap) { | 315 | if (altmap) { |
| 316 | alt_start = altmap->base_pfn; | 316 | alt_start = altmap->base_pfn; |
| 317 | alt_end = altmap->base_pfn + altmap->reserve + | 317 | alt_end = altmap->base_pfn + altmap->reserve + altmap->free; |
| 318 | altmap->free + altmap->alloc + altmap->align; | ||
| 319 | } | 318 | } |
| 320 | 319 | ||
| 321 | pr_debug("vmemmap_free %lx...%lx\n", start, end); | 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 | unsigned long inia; | 180 | unsigned long inia; |
| 181 | int cpu = *(const int *)info; | 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 | book3e_start_thread(cpu_thread_in_core(cpu), inia); | 184 | book3e_start_thread(cpu_thread_in_core(cpu), inia); |
| 185 | } | 185 | } |
| 186 | #endif | 186 | #endif |
| @@ -26,8 +26,8 @@ · 25 unmodified lines | |||
| 26 | #include <linux/rtc.h> | 26 | #include <linux/rtc.h> |
| 27 | #include <linux/of_address.h> | 27 | #include <linux/of_address.h> |
| 28 | 28 | ||
| 29 | #include <asm/early_ioremap.h> | ||
| 29 | #include <asm/sections.h> | 30 | #include <asm/sections.h> |
| 30 | #include <asm/io.h> | ||
| 31 | #include <asm/machdep.h> | 31 | #include <asm/machdep.h> |
| 32 | #include <asm/time.h> | 32 | #include <asm/time.h> |
| 33 | #include <asm/nvram.h> | 33 | #include <asm/nvram.h> |
| @@ -182,7 +182,7 @@ static int __init via_calibrate_decr(void) · 148 unmodified lines | |||
| 182 | return 0; | 182 | return 0; |
| 183 | } | 183 | } |
| 184 | of_node_put(vias); | 184 | of_node_put(vias); |
| 185 | via = ioremap(rsrc.start, resource_size(&rsrc)); | 185 | via = early_ioremap(rsrc.start, resource_size(&rsrc)); |
| 186 | if (via == NULL) { | 186 | if (via == NULL) { |
| 187 | printk(KERN_ERR "Failed to map VIA for timer calibration !\n"); | 187 | printk(KERN_ERR "Failed to map VIA for timer calibration !\n"); |
| 188 | return 0; | 188 | return 0; |
| @@ -207,7 +207,7 @@ static int __init via_calibrate_decr(void) · 18 unmodified lines | |||
| 207 | 207 | ||
| 208 | ppc_tb_freq = (dstart - dend) * 100 / 6; | 208 | ppc_tb_freq = (dstart - dend) * 100 / 6; |
| 209 | 209 | ||
| 210 | iounmap(via); | 210 | early_iounmap((void *)via, resource_size(&rsrc)); |
| 211 | 211 | ||
| 212 | return 1; | 212 | return 1; |
| 213 | } | 213 | } |
| @@ -19,7 +19,7 @@ typedef u64 phys_cpuid_t; · 18 unmodified lines | |||
| 19 | #define PHYS_CPUID_INVALID INVALID_HARTID | 19 | #define PHYS_CPUID_INVALID INVALID_HARTID |
| 20 | 20 | ||
| 21 | /* ACPI table mapping after acpi_permanent_mmap is set */ | 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 | #define acpi_os_ioremap acpi_os_ioremap | 23 | #define acpi_os_ioremap acpi_os_ioremap |
| 24 | 24 | ||
| 25 | #define acpi_strict 1 /* No out-of-spec workarounds on RISC-V */ | 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 | #define flush_icache_user_page(vma, pg, addr, len) \ | 37 | #define flush_icache_user_page(vma, pg, addr, len) \ |
| 38 | flush_icache_mm(vma->vm_mm, 0) | 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 | #ifndef CONFIG_SMP | 44 | #ifndef CONFIG_SMP |
| 41 | 45 | ||
| 42 | #define flush_icache_all() local_flush_icache_all() | 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 | * Relaxed I/O memory access primitives. These follow the Device memory | 101 | * Relaxed I/O memory access primitives. These follow the Device memory |
| 102 | * ordering rules but do not guarantee any ordering relative to Normal memory | 102 | * ordering rules but do not guarantee any ordering relative to Normal memory |
| 103 | * accesses. These are defined to order the indicated access (either a read or | 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 | 104 | * write) with all other I/O memory accesses to the same peripheral. Since the |
| 105 | * defines that all I/O regions are strongly ordered on channel 2, no explicit | 105 | * platform specification defines that all I/O regions are strongly ordered on |
| 106 | * fences are required to enforce this ordering. | 106 | * channel 0, no explicit fences are required to enforce this ordering. |
| 107 | */ | 107 | */ |
| 108 | /* FIXME: These are now the same as asm-generic */ | 108 | /* FIXME: These are now the same as asm-generic */ |
| 109 | #define __io_rbr() do {} while (0) | 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 | #endif | 125 | #endif |
| 126 | 126 | ||
| 127 | /* | 127 | /* |
| 128 | * I/O memory access primitives. Reads are ordered relative to any | 128 | * I/O memory access primitives. Reads are ordered relative to any following |
| 129 | * following Normal memory access. Writes are ordered relative to any prior | 129 | * Normal memory read and delay() loop. Writes are ordered relative to any |
| 130 | * Normal memory access. The memory barriers here are necessary as RISC-V | 130 | * prior Normal memory write. The memory barriers here are necessary as RISC-V |
| 131 | * doesn't define any ordering between the memory space and the I/O space. | 131 | * doesn't define any ordering between the memory space and the I/O space. |
| 132 | */ | 132 | */ |
| 133 | #define __io_br() do {} while (0) | 133 | #define __io_br() do {} while (0) |
| 134 | #define __io_ar(v) __asm__ __volatile__ ("fence i,r" : : : "memory") | 134 | #define __io_ar(v) ({ __asm__ __volatile__ ("fence i,ir" : : : "memory"); }) |
| 135 | #define __io_bw() __asm__ __volatile__ ("fence w,o" : : : "memory") | 135 | #define __io_bw() ({ __asm__ __volatile__ ("fence w,o" : : : "memory"); }) |
| 136 | #define __io_aw() mmiowb_set_pending() | 136 | #define __io_aw() mmiowb_set_pending() |
| 137 | 137 | ||
| 138 | #define readb(c) ({ u8 __v; __io_br(); __v = readb_cpu(c); __io_ar(__v); __v; }) | 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 | #define PAGE_KERNEL_IO __pgprot(_PAGE_IOREMAP) | 188 | #define PAGE_KERNEL_IO __pgprot(_PAGE_IOREMAP) |
| 189 | 189 | ||
| 190 | extern pgd_t swapper_pg_dir[]; | 190 | extern pgd_t swapper_pg_dir[]; |
| 191 | extern pgd_t trampoline_pg_dir[]; | ||
| 192 | extern pgd_t early_pg_dir[]; | ||
| 191 | 193 | ||
| 192 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 194 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 193 | static inline int pmd_present(pmd_t pmd) | 195 | static inline int pmd_present(pmd_t pmd) |
| @@ -3,12 +3,14 @@ · 2 unmodified lines | |||
| 3 | 3 | ||
| 4 | #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP | 4 | #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP |
| 5 | 5 | ||
| 6 | extern bool pgtable_l4_enabled, pgtable_l5_enabled; | ||
| 7 | |||
| 6 | #define IOREMAP_MAX_ORDER (PUD_SHIFT) | 8 | #define IOREMAP_MAX_ORDER (PUD_SHIFT) |
| 7 | 9 | ||
| 8 | #define arch_vmap_pud_supported arch_vmap_pud_supported | 10 | #define arch_vmap_pud_supported arch_vmap_pud_supported |
| 9 | static inline bool arch_vmap_pud_supported(pgprot_t prot) | 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 | #define arch_vmap_pmd_supported arch_vmap_pmd_supported | 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 | early_iounmap(map, size); | 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 | #ifdef CONFIG_PCI | 223 | #ifdef CONFIG_PCI |
| @@ -17,6 +17,11 @@ · 16 unmodified lines | |||
| 17 | #include <asm/smp.h> | 17 | #include <asm/smp.h> |
| 18 | #include <asm/pgtable.h> | 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 | * Returns the hart ID of the given device tree node, or -ENODEV if the node | 26 | * Returns the hart ID of the given device tree node, or -ENODEV if the node |
| 22 | * isn't an enabled and valid RISC-V hart node. | 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 | vmcoreinfo_append_str("NUMBER(MODULES_END)=0x%lx\n", MODULES_END); | 18 | vmcoreinfo_append_str("NUMBER(MODULES_END)=0x%lx\n", MODULES_END); |
| 19 | #endif | 19 | #endif |
| 20 | vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR); | 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 | kbuf.buffer = initrd; | 281 | kbuf.buffer = initrd; |
| 282 | kbuf.bufsz = kbuf.memsz = initrd_len; | 282 | kbuf.bufsz = kbuf.memsz = initrd_len; |
| 283 | kbuf.buf_align = PAGE_SIZE; | 283 | kbuf.buf_align = PAGE_SIZE; |
| 284 | kbuf.top_down = false; | 284 | kbuf.top_down = true; |
| 285 | kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; | 285 | kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; |
| 286 | ret = kexec_add_buffer(&kbuf); | 286 | ret = kexec_add_buffer(&kbuf); |
| 287 | if (ret) | 287 | if (ret) |
| @@ -425,6 +425,7 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, · 137 unmodified lines | |||
| 425 | * sym, instead of searching the whole relsec. | 425 | * sym, instead of searching the whole relsec. |
| 426 | */ | 426 | */ |
| 427 | case R_RISCV_PCREL_HI20: | 427 | case R_RISCV_PCREL_HI20: |
| 428 | case R_RISCV_CALL_PLT: | ||
| 428 | case R_RISCV_CALL: | 429 | case R_RISCV_CALL: |
| 429 | *(u64 *)loc = CLEAN_IMM(UITYPE, *(u64 *)loc) | | 430 | *(u64 *)loc = CLEAN_IMM(UITYPE, *(u64 *)loc) | |
| 430 | ENCODE_UJTYPE_IMM(val - addr); | 431 | ENCODE_UJTYPE_IMM(val - addr); |
| @@ -61,11 +61,6 @@ int riscv_hartid_to_cpuid(unsigned long hartid) · 60 unmodified lines | |||
| 61 | return -ENOENT; | 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 | static void ipi_stop(void) | 64 | static void ipi_stop(void) |
| 70 | { | 65 | { |
| 71 | set_cpu_online(smp_processor_id(), false); | 66 | set_cpu_online(smp_processor_id(), false); |
| @@ -26,12 +26,13 @@ · 25 unmodified lines | |||
| 26 | #include <linux/kfence.h> | 26 | #include <linux/kfence.h> |
| 27 | 27 | ||
| 28 | #include <asm/fixmap.h> | 28 | #include <asm/fixmap.h> |
| 29 | #include <asm/tlbflush.h> | ||
| 30 | #include <asm/sections.h> | ||
| 31 | #include <asm/soc.h> | ||
| 32 | #include <asm/io.h> | 29 | #include <asm/io.h> |
| 33 | #include <asm/ptdump.h> | ||
| 34 | #include <asm/numa.h> | 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 | #include "../kernel/head.h" | 37 | #include "../kernel/head.h" |
| 37 | 38 | ||
| @@ -214,8 +215,13 @@ static void __init setup_bootmem(void) · 176 unmodified lines | |||
| 214 | memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start); | 215 | memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start); |
| 215 | 216 | ||
| 216 | phys_ram_end = memblock_end_of_DRAM(); | 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 | if (!IS_ENABLED(CONFIG_XIP_KERNEL)) | 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 | * In 64-bit, any use of __va/__pa before this point is wrong as we | 227 | * In 64-bit, any use of __va/__pa before this point is wrong as we |
| @@ -22,7 +22,6 @@ · 21 unmodified lines | |||
| 22 | * region is not and then we have to go down to the PUD level. | 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 | pgd_t tmp_pg_dir[PTRS_PER_PGD] __page_aligned_bss; | 25 | pgd_t tmp_pg_dir[PTRS_PER_PGD] __page_aligned_bss; |
| 27 | p4d_t tmp_p4d[PTRS_PER_P4D] __page_aligned_bss; | 26 | p4d_t tmp_p4d[PTRS_PER_P4D] __page_aligned_bss; |
| 28 | pud_t tmp_pud[PTRS_PER_PUD] __page_aligned_bss; | 27 | pud_t tmp_pud[PTRS_PER_PUD] __page_aligned_bss; |
| @@ -116,7 +116,6 @@ CONFIG_UNIX=y · 115 unmodified lines | |||
| 116 | CONFIG_UNIX_DIAG=m | 116 | CONFIG_UNIX_DIAG=m |
| 117 | CONFIG_XFRM_USER=m | 117 | CONFIG_XFRM_USER=m |
| 118 | CONFIG_NET_KEY=m | 118 | CONFIG_NET_KEY=m |
| 119 | CONFIG_NET_TC_SKB_EXT=y | ||
| 120 | CONFIG_SMC=m | 119 | CONFIG_SMC=m |
| 121 | CONFIG_SMC_DIAG=m | 120 | CONFIG_SMC_DIAG=m |
| 122 | CONFIG_INET=y | 121 | CONFIG_INET=y |
| @@ -193,6 +192,7 @@ CONFIG_NFT_REJECT=m · 70 unmodified lines | |||
| 193 | CONFIG_NFT_COMPAT=m | 192 | CONFIG_NFT_COMPAT=m |
| 194 | CONFIG_NFT_HASH=m | 193 | CONFIG_NFT_HASH=m |
| 195 | CONFIG_NFT_FIB_INET=m | 194 | CONFIG_NFT_FIB_INET=m |
| 195 | CONFIG_NETFILTER_XTABLES_COMPAT=y | ||
| 196 | CONFIG_NETFILTER_XT_SET=m | 196 | CONFIG_NETFILTER_XT_SET=m |
| 197 | CONFIG_NETFILTER_XT_TARGET_AUDIT=m | 197 | CONFIG_NETFILTER_XT_TARGET_AUDIT=m |
| 198 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 198 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
| @@ -379,6 +379,7 @@ CONFIG_NET_ACT_SIMP=m · 180 unmodified lines | |||
| 379 | CONFIG_NET_ACT_SKBEDIT=m | 379 | CONFIG_NET_ACT_SKBEDIT=m |
| 380 | CONFIG_NET_ACT_CSUM=m | 380 | CONFIG_NET_ACT_CSUM=m |
| 381 | CONFIG_NET_ACT_GATE=m | 381 | CONFIG_NET_ACT_GATE=m |
| 382 | CONFIG_NET_TC_SKB_EXT=y | ||
| 382 | CONFIG_DNS_RESOLVER=y | 383 | CONFIG_DNS_RESOLVER=y |
| 383 | CONFIG_OPENVSWITCH=m | 384 | CONFIG_OPENVSWITCH=m |
| 384 | CONFIG_VSOCKETS=m | 385 | CONFIG_VSOCKETS=m |
| @@ -395,6 +396,7 @@ CONFIG_HOTPLUG_PCI=y · 10 unmodified lines | |||
| 395 | CONFIG_HOTPLUG_PCI_S390=y | 396 | CONFIG_HOTPLUG_PCI_S390=y |
| 396 | CONFIG_DEVTMPFS=y | 397 | CONFIG_DEVTMPFS=y |
| 397 | CONFIG_DEVTMPFS_SAFE=y | 398 | CONFIG_DEVTMPFS_SAFE=y |
| 399 | # CONFIG_FW_LOADER is not set | ||
| 398 | CONFIG_CONNECTOR=y | 400 | CONFIG_CONNECTOR=y |
| 399 | CONFIG_ZRAM=y | 401 | CONFIG_ZRAM=y |
| 400 | CONFIG_BLK_DEV_LOOP=m | 402 | CONFIG_BLK_DEV_LOOP=m |
| @@ -502,7 +504,6 @@ CONFIG_NLMON=m · 101 unmodified lines | |||
| 502 | # CONFIG_NET_VENDOR_GOOGLE is not set | 504 | # CONFIG_NET_VENDOR_GOOGLE is not set |
| 503 | # CONFIG_NET_VENDOR_HUAWEI is not set | 505 | # CONFIG_NET_VENDOR_HUAWEI is not set |
| 504 | # CONFIG_NET_VENDOR_INTEL is not set | 506 | # CONFIG_NET_VENDOR_INTEL is not set |
| 505 | # CONFIG_NET_VENDOR_WANGXUN is not set | ||
| 506 | # CONFIG_NET_VENDOR_LITEX is not set | 507 | # CONFIG_NET_VENDOR_LITEX is not set |
| 507 | # CONFIG_NET_VENDOR_MARVELL is not set | 508 | # CONFIG_NET_VENDOR_MARVELL is not set |
| 508 | CONFIG_MLX4_EN=m | 509 | CONFIG_MLX4_EN=m |
| @@ -542,6 +543,7 @@ CONFIG_MLX5_CORE_EN=y · 33 unmodified lines | |||
| 542 | # CONFIG_NET_VENDOR_TI is not set | 543 | # CONFIG_NET_VENDOR_TI is not set |
| 543 | # CONFIG_NET_VENDOR_VERTEXCOM is not set | 544 | # CONFIG_NET_VENDOR_VERTEXCOM is not set |
| 544 | # CONFIG_NET_VENDOR_VIA is not set | 545 | # CONFIG_NET_VENDOR_VIA is not set |
| 546 | # CONFIG_NET_VENDOR_WANGXUN is not set | ||
| 545 | # CONFIG_NET_VENDOR_WIZNET is not set | 547 | # CONFIG_NET_VENDOR_WIZNET is not set |
| 546 | # CONFIG_NET_VENDOR_XILINX is not set | 548 | # CONFIG_NET_VENDOR_XILINX is not set |
| 547 | CONFIG_PPP=m | 549 | CONFIG_PPP=m |
| @@ -646,7 +648,6 @@ CONFIG_TMPFS=y · 98 unmodified lines | |||
| 646 | CONFIG_TMPFS_POSIX_ACL=y | 648 | CONFIG_TMPFS_POSIX_ACL=y |
| 647 | CONFIG_TMPFS_INODE64=y | 649 | CONFIG_TMPFS_INODE64=y |
| 648 | CONFIG_HUGETLBFS=y | 650 | CONFIG_HUGETLBFS=y |
| 649 | CONFIG_CONFIGFS_FS=m | ||
| 650 | CONFIG_ECRYPT_FS=m | 651 | CONFIG_ECRYPT_FS=m |
| 651 | CONFIG_CRAMFS=m | 652 | CONFIG_CRAMFS=m |
| 652 | CONFIG_SQUASHFS=m | 653 | CONFIG_SQUASHFS=m |
| @@ -690,7 +691,6 @@ CONFIG_HARDENED_USERCOPY=y · 37 unmodified lines | |||
| 690 | CONFIG_FORTIFY_SOURCE=y | 691 | CONFIG_FORTIFY_SOURCE=y |
| 691 | CONFIG_SECURITY_SELINUX=y | 692 | CONFIG_SECURITY_SELINUX=y |
| 692 | CONFIG_SECURITY_SELINUX_BOOTPARAM=y | 693 | CONFIG_SECURITY_SELINUX_BOOTPARAM=y |
| 693 | CONFIG_SECURITY_SELINUX_DISABLE=y | ||
| 694 | CONFIG_SECURITY_LOCKDOWN_LSM=y | 694 | CONFIG_SECURITY_LOCKDOWN_LSM=y |
| 695 | CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y | 695 | CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y |
| 696 | CONFIG_SECURITY_LANDLOCK=y | 696 | CONFIG_SECURITY_LANDLOCK=y |
| @@ -744,7 +744,6 @@ CONFIG_CRYPTO_MD4=m · 47 unmodified lines | |||
| 744 | CONFIG_CRYPTO_MD5=y | 744 | CONFIG_CRYPTO_MD5=y |
| 745 | CONFIG_CRYPTO_MICHAEL_MIC=m | 745 | CONFIG_CRYPTO_MICHAEL_MIC=m |
| 746 | CONFIG_CRYPTO_RMD160=m | 746 | CONFIG_CRYPTO_RMD160=m |
| 747 | CONFIG_CRYPTO_SHA3=m | ||
| 748 | CONFIG_CRYPTO_SM3_GENERIC=m | 747 | CONFIG_CRYPTO_SM3_GENERIC=m |
| 749 | CONFIG_CRYPTO_VMAC=m | 748 | CONFIG_CRYPTO_VMAC=m |
| 750 | CONFIG_CRYPTO_WP512=m | 749 | CONFIG_CRYPTO_WP512=m |
| @@ -844,6 +843,7 @@ CONFIG_PREEMPT_TRACER=y · 93 unmodified lines | |||
| 844 | CONFIG_SCHED_TRACER=y | 843 | CONFIG_SCHED_TRACER=y |
| 845 | CONFIG_FTRACE_SYSCALLS=y | 844 | CONFIG_FTRACE_SYSCALLS=y |
| 846 | CONFIG_BLK_DEV_IO_TRACE=y | 845 | CONFIG_BLK_DEV_IO_TRACE=y |
| 846 | CONFIG_USER_EVENTS=y | ||
| 847 | CONFIG_HIST_TRIGGERS=y | 847 | CONFIG_HIST_TRIGGERS=y |
| 848 | CONFIG_FTRACE_STARTUP_TEST=y | 848 | CONFIG_FTRACE_STARTUP_TEST=y |
| 849 | # CONFIG_EVENT_TRACE_STARTUP_TEST is not set | 849 | # CONFIG_EVENT_TRACE_STARTUP_TEST is not set |
| @@ -866,6 +866,7 @@ CONFIG_FAIL_MAKE_REQUEST=y · 16 unmodified lines | |||
| 866 | CONFIG_FAIL_IO_TIMEOUT=y | 866 | CONFIG_FAIL_IO_TIMEOUT=y |
| 867 | CONFIG_FAIL_FUTEX=y | 867 | CONFIG_FAIL_FUTEX=y |
| 868 | CONFIG_FAULT_INJECTION_DEBUG_FS=y | 868 | CONFIG_FAULT_INJECTION_DEBUG_FS=y |
| 869 | CONFIG_FAULT_INJECTION_CONFIGFS=y | ||
| 869 | CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y | 870 | CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y |
| 870 | CONFIG_LKDTM=m | 871 | CONFIG_LKDTM=m |
| 871 | CONFIG_TEST_MIN_HEAP=y | 872 | CONFIG_TEST_MIN_HEAP=y |
| @@ -107,7 +107,6 @@ CONFIG_UNIX=y · 106 unmodified lines | |||
| 107 | CONFIG_UNIX_DIAG=m | 107 | CONFIG_UNIX_DIAG=m |
| 108 | CONFIG_XFRM_USER=m | 108 | CONFIG_XFRM_USER=m |
| 109 | CONFIG_NET_KEY=m | 109 | CONFIG_NET_KEY=m |
| 110 | CONFIG_NET_TC_SKB_EXT=y | ||
| 111 | CONFIG_SMC=m | 110 | CONFIG_SMC=m |
| 112 | CONFIG_SMC_DIAG=m | 111 | CONFIG_SMC_DIAG=m |
| 113 | CONFIG_INET=y | 112 | CONFIG_INET=y |
| @@ -184,6 +183,7 @@ CONFIG_NFT_REJECT=m · 70 unmodified lines | |||
| 184 | CONFIG_NFT_COMPAT=m | 183 | CONFIG_NFT_COMPAT=m |
| 185 | CONFIG_NFT_HASH=m | 184 | CONFIG_NFT_HASH=m |
| 186 | CONFIG_NFT_FIB_INET=m | 185 | CONFIG_NFT_FIB_INET=m |
| 186 | CONFIG_NETFILTER_XTABLES_COMPAT=y | ||
| 187 | CONFIG_NETFILTER_XT_SET=m | 187 | CONFIG_NETFILTER_XT_SET=m |
| 188 | CONFIG_NETFILTER_XT_TARGET_AUDIT=m | 188 | CONFIG_NETFILTER_XT_TARGET_AUDIT=m |
| 189 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m | 189 | CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m |
| @@ -369,6 +369,7 @@ CONFIG_NET_ACT_SIMP=m · 179 unmodified lines | |||
| 369 | CONFIG_NET_ACT_SKBEDIT=m | 369 | CONFIG_NET_ACT_SKBEDIT=m |
| 370 | CONFIG_NET_ACT_CSUM=m | 370 | CONFIG_NET_ACT_CSUM=m |
| 371 | CONFIG_NET_ACT_GATE=m | 371 | CONFIG_NET_ACT_GATE=m |
| 372 | CONFIG_NET_TC_SKB_EXT=y | ||
| 372 | CONFIG_DNS_RESOLVER=y | 373 | CONFIG_DNS_RESOLVER=y |
| 373 | CONFIG_OPENVSWITCH=m | 374 | CONFIG_OPENVSWITCH=m |
| 374 | CONFIG_VSOCKETS=m | 375 | CONFIG_VSOCKETS=m |
| @@ -385,6 +386,7 @@ CONFIG_HOTPLUG_PCI_S390=y · 10 unmodified lines | |||
| 385 | CONFIG_UEVENT_HELPER=y | 386 | CONFIG_UEVENT_HELPER=y |
| 386 | CONFIG_DEVTMPFS=y | 387 | CONFIG_DEVTMPFS=y |
| 387 | CONFIG_DEVTMPFS_SAFE=y | 388 | CONFIG_DEVTMPFS_SAFE=y |
| 389 | # CONFIG_FW_LOADER is not set | ||
| 388 | CONFIG_CONNECTOR=y | 390 | CONFIG_CONNECTOR=y |
| 389 | CONFIG_ZRAM=y | 391 | CONFIG_ZRAM=y |
| 390 | CONFIG_BLK_DEV_LOOP=m | 392 | CONFIG_BLK_DEV_LOOP=m |
| @@ -492,7 +494,6 @@ CONFIG_NLMON=m · 101 unmodified lines | |||
| 492 | # CONFIG_NET_VENDOR_GOOGLE is not set | 494 | # CONFIG_NET_VENDOR_GOOGLE is not set |
| 493 | # CONFIG_NET_VENDOR_HUAWEI is not set | 495 | # CONFIG_NET_VENDOR_HUAWEI is not set |
| 494 | # CONFIG_NET_VENDOR_INTEL is not set | 496 | # CONFIG_NET_VENDOR_INTEL is not set |
| 495 | # CONFIG_NET_VENDOR_WANGXUN is not set | ||
| 496 | # CONFIG_NET_VENDOR_LITEX is not set | 497 | # CONFIG_NET_VENDOR_LITEX is not set |
| 497 | # CONFIG_NET_VENDOR_MARVELL is not set | 498 | # CONFIG_NET_VENDOR_MARVELL is not set |
| 498 | CONFIG_MLX4_EN=m | 499 | CONFIG_MLX4_EN=m |
| @@ -532,6 +533,7 @@ CONFIG_MLX5_CORE_EN=y · 33 unmodified lines | |||
| 532 | # CONFIG_NET_VENDOR_TI is not set | 533 | # CONFIG_NET_VENDOR_TI is not set |
| 533 | # CONFIG_NET_VENDOR_VERTEXCOM is not set | 534 | # CONFIG_NET_VENDOR_VERTEXCOM is not set |
| 534 | # CONFIG_NET_VENDOR_VIA is not set | 535 | # CONFIG_NET_VENDOR_VIA is not set |
| 536 | # CONFIG_NET_VENDOR_WANGXUN is not set | ||
| 535 | # CONFIG_NET_VENDOR_WIZNET is not set | 537 | # CONFIG_NET_VENDOR_WIZNET is not set |
| 536 | # CONFIG_NET_VENDOR_XILINX is not set | 538 | # CONFIG_NET_VENDOR_XILINX is not set |
| 537 | CONFIG_PPP=m | 539 | CONFIG_PPP=m |
| @@ -673,7 +675,6 @@ CONFIG_SECURITY=y · 135 unmodified lines | |||
| 673 | CONFIG_SECURITY_NETWORK=y | 675 | CONFIG_SECURITY_NETWORK=y |
| 674 | CONFIG_SECURITY_SELINUX=y | 676 | CONFIG_SECURITY_SELINUX=y |
| 675 | CONFIG_SECURITY_SELINUX_BOOTPARAM=y | 677 | CONFIG_SECURITY_SELINUX_BOOTPARAM=y |
| 676 | CONFIG_SECURITY_SELINUX_DISABLE=y | ||
| 677 | CONFIG_SECURITY_LOCKDOWN_LSM=y | 678 | CONFIG_SECURITY_LOCKDOWN_LSM=y |
| 678 | CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y | 679 | CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y |
| 679 | CONFIG_SECURITY_LANDLOCK=y | 680 | CONFIG_SECURITY_LANDLOCK=y |
| @@ -729,7 +730,6 @@ CONFIG_CRYPTO_MD4=m · 49 unmodified lines | |||
| 729 | CONFIG_CRYPTO_MD5=y | 730 | CONFIG_CRYPTO_MD5=y |
| 730 | CONFIG_CRYPTO_MICHAEL_MIC=m | 731 | CONFIG_CRYPTO_MICHAEL_MIC=m |
| 731 | CONFIG_CRYPTO_RMD160=m | 732 | CONFIG_CRYPTO_RMD160=m |
| 732 | CONFIG_CRYPTO_SHA3=m | ||
| 733 | CONFIG_CRYPTO_SM3_GENERIC=m | 733 | CONFIG_CRYPTO_SM3_GENERIC=m |
| 734 | CONFIG_CRYPTO_VMAC=m | 734 | CONFIG_CRYPTO_VMAC=m |
| 735 | CONFIG_CRYPTO_WP512=m | 735 | CONFIG_CRYPTO_WP512=m |
| @@ -793,6 +793,7 @@ CONFIG_STACK_TRACER=y · 57 unmodified lines | |||
| 793 | CONFIG_SCHED_TRACER=y | 793 | CONFIG_SCHED_TRACER=y |
| 794 | CONFIG_FTRACE_SYSCALLS=y | 794 | CONFIG_FTRACE_SYSCALLS=y |
| 795 | CONFIG_BLK_DEV_IO_TRACE=y | 795 | CONFIG_BLK_DEV_IO_TRACE=y |
| 796 | CONFIG_USER_EVENTS=y | ||
| 796 | CONFIG_HIST_TRIGGERS=y | 797 | CONFIG_HIST_TRIGGERS=y |
| 797 | CONFIG_SAMPLES=y | 798 | CONFIG_SAMPLES=y |
| 798 | CONFIG_SAMPLE_TRACE_PRINTK=m | 799 | CONFIG_SAMPLE_TRACE_PRINTK=m |
| @@ -53,7 +53,6 @@ CONFIG_ZFCP=y · 52 unmodified lines | |||
| 53 | # CONFIG_HVC_IUCV is not set | 53 | # CONFIG_HVC_IUCV is not set |
| 54 | # CONFIG_HW_RANDOM_S390 is not set | 54 | # CONFIG_HW_RANDOM_S390 is not set |
| 55 | # CONFIG_HMC_DRV is not set | 55 | # CONFIG_HMC_DRV is not set |
| 56 | # CONFIG_S390_UV_UAPI is not set | ||
| 57 | # CONFIG_S390_TAPE is not set | 56 | # CONFIG_S390_TAPE is not set |
| 58 | # CONFIG_VMCP is not set | 57 | # CONFIG_VMCP is not set |
| 59 | # CONFIG_MONWRITER is not set | 58 | # CONFIG_MONWRITER is not set |
| @@ -8,6 +8,8 @@ · 7 unmodified lines | |||
| 8 | #ifndef _UAPI_S390_PTRACE_H | 8 | #ifndef _UAPI_S390_PTRACE_H |
| 9 | #define _UAPI_S390_PTRACE_H | 9 | #define _UAPI_S390_PTRACE_H |
| 10 | 10 | ||
| 11 | #include <linux/const.h> | ||
| 12 | |||
| 11 | /* | 13 | /* |
| 12 | * Offsets in the user_regs_struct. They are used for the ptrace | 14 | * Offsets in the user_regs_struct. They are used for the ptrace |
| 13 | * system call and in entry.S | 15 | * system call and in entry.S |
| @@ -459,9 +459,9 @@ static int sthyi_update_cache(u64 *rc) · 458 unmodified lines | |||
| 459 | * | 459 | * |
| 460 | * Fills the destination with system information returned by the STHYI | 460 | * Fills the destination with system information returned by the STHYI |
| 461 | * instruction. The data is generated by emulation or execution of STHYI, | 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 | 462 | * if available. The return value is either a negative error value or |
| 463 | * returned, the rc parameter is the return code which is passed in | 463 | * the condition code that would be returned, the rc parameter is the |
| 464 | * register R2 + 1. | 464 | * return code which is passed in register R2 + 1. |
| 465 | */ | 465 | */ |
| 466 | int sthyi_fill(void *dst, u64 *rc) | 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 | int handle_sthyi(struct kvm_vcpu *vcpu) | 390 | int handle_sthyi(struct kvm_vcpu *vcpu) |
| 391 | { | 391 | { |
| 392 | int reg1, reg2, r = 0; | 392 | int reg1, reg2, cc = 0, r = 0; |
| 393 | u64 code, addr, cc = 0, rc = 0; | 393 | u64 code, addr, rc = 0; |
| 394 | struct sthyi_sctns *sctns = NULL; | 394 | struct sthyi_sctns *sctns = NULL; |
| 395 | 395 | ||
| 396 | if (!test_kvm_facility(vcpu->kvm, 74)) | 396 | if (!test_kvm_facility(vcpu->kvm, 74)) |
| @@ -421,7 +421,10 @@ int handle_sthyi(struct kvm_vcpu *vcpu) · 24 unmodified lines | |||
| 421 | return -ENOMEM; | 421 | return -ENOMEM; |
| 422 | 422 | ||
| 423 | cc = sthyi_fill(sctns, &rc); | 423 | cc = sthyi_fill(sctns, &rc); |
| 424 | 424 | if (cc < 0) { | |
| 425 | free_page((unsigned long)sctns); | ||
| 426 | return cc; | ||
| 427 | } | ||
| 425 | out: | 428 | out: |
| 426 | if (!cc) { | 429 | if (!cc) { |
| 427 | if (kvm_s390_pv_cpu_is_protected(vcpu)) { | 430 | if (kvm_s390_pv_cpu_is_protected(vcpu)) { |
| @@ -763,6 +763,8 @@ void __init vmem_map_init(void) · 762 unmodified lines | |||
| 763 | if (static_key_enabled(&cpu_has_bear)) | 763 | if (static_key_enabled(&cpu_has_bear)) |
| 764 | set_memory_nx(0, 1); | 764 | set_memory_nx(0, 1); |
| 765 | set_memory_nx(PAGE_SIZE, 1); | 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 | pr_info("Write protected kernel read-only data: %luk\n", | 769 | pr_info("Write protected kernel read-only data: %luk\n", |
| 768 | (unsigned long)(__end_rodata - _stext) >> 10); | 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 | #define ARCH_HAS_PREFETCH | 214 | #define ARCH_HAS_PREFETCH |
| 215 | #define ARCH_HAS_PREFETCHW | 215 | #define ARCH_HAS_PREFETCHW |
| 216 | #define ARCH_HAS_SPINLOCK_PREFETCH | ||
| 217 | 216 | ||
| 218 | static inline void prefetch(const void *x) | 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 | : "r" (x)); | 238 | : "r" (x)); |
| 240 | } | 239 | } |
| 241 | 240 | ||
| 242 | #define spin_lock_prefetch(x) prefetchw(x) | ||
| 243 | |||
| 244 | #define HAVE_ARCH_PICK_MMAP_LAYOUT | 241 | #define HAVE_ARCH_PICK_MMAP_LAYOUT |
| 245 | 242 | ||
| 246 | int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap); | 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 | This mitigates both spectre_v2 and retbleed at great cost to | 2593 | This mitigates both spectre_v2 and retbleed at great cost to |
| 2594 | performance. | 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 | config SLS | 2603 | config SLS |
| 2597 | bool "Mitigate Straight-Line-Speculation" | 2604 | bool "Mitigate Straight-Line-Speculation" |
| 2598 | depends on CC_HAS_SLS && X86_64 | 2605 | depends on CC_HAS_SLS && X86_64 |
| @@ -2603,6 +2610,25 @@ config SLS · 4 unmodified lines | |||
| 2603 | against straight line speculation. The kernel image might be slightly | 2610 | against straight line speculation. The kernel image might be slightly |
| 2604 | larger. | 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 | endif | 2632 | endif |
| 2607 | 2633 | ||
| 2608 | config ARCH_HAS_ADD_PAGES | 2634 | config ARCH_HAS_ADD_PAGES |
| @@ -63,7 +63,14 @@ void load_stage2_idt(void) · 62 unmodified lines | |||
| 63 | set_idt_entry(X86_TRAP_PF, boot_page_fault); | 63 | set_idt_entry(X86_TRAP_PF, boot_page_fault); |
| 64 | 64 | ||
| 65 | #ifdef CONFIG_AMD_MEM_ENCRYPT | 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 | #endif | 74 | #endif |
| 68 | 75 | ||
| 69 | load_boot_idt(&boot_idt_desc); | 76 | load_boot_idt(&boot_idt_desc); |
| @@ -404,13 +404,46 @@ void sev_enable(struct boot_params *bp) · 403 unmodified lines | |||
| 404 | if (bp) | 404 | if (bp) |
| 405 | bp->cc_blob_address = 0; | 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 | * Setup/preliminary detection of SNP. This will be sanity-checked | 439 | * Setup/preliminary detection of SNP. This will be sanity-checked |
| 409 | * against CPUID/MSR values later. | 440 | * against CPUID/MSR values later. |
| 410 | */ | 441 | */ |
| 411 | snp = snp_init(bp); | 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 | eax = 0x80000000; | 447 | eax = 0x80000000; |
| 415 | ecx = 0; | 448 | ecx = 0; |
| 416 | native_cpuid(&eax, &ebx, &ecx, &edx); | 449 | native_cpuid(&eax, &ebx, &ecx, &edx); |
| @@ -418,7 +451,7 @@ void sev_enable(struct boot_params *bp) · 1 unmodified line | |||
| 418 | return; | 451 | return; |
| 419 | 452 | ||
| 420 | /* | 453 | /* |
| 421 | * Check for the SME/SEV feature: | 454 | * Recheck for the SME/SEV feature: |
| 422 | * CPUID Fn8000_001F[EAX] | 455 | * CPUID Fn8000_001F[EAX] |
| 423 | * - Bit 0 - Secure Memory Encryption support | 456 | * - Bit 0 - Secure Memory Encryption support |
| 424 | * - Bit 1 - Secure Encrypted Virtualization support | 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 | /* Round the lowest possible end address up to a PMD boundary. */ | 300 | /* Round the lowest possible end address up to a PMD boundary. */ |
| 301 | end = (start + len + PMD_SIZE - 1) & PMD_MASK; | 301 | end = (start + len + PMD_SIZE - 1) & PMD_MASK; |
| 302 | if (end >= TASK_SIZE_MAX) | 302 | if (end >= DEFAULT_MAP_WINDOW) |
| 303 | end = TASK_SIZE_MAX; | 303 | end = DEFAULT_MAP_WINDOW; |
| 304 | end -= len; | 304 | end -= len; |
| 305 | 305 | ||
| 306 | if (end > start) { | 306 | if (end > start) { |
| @@ -107,7 +107,6 @@ static bool cpu_is_self(int cpu) · 106 unmodified lines | |||
| 107 | static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, | 107 | static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, |
| 108 | bool exclude_self) | 108 | bool exclude_self) |
| 109 | { | 109 | { |
| 110 | struct hv_send_ipi_ex **arg; | ||
| 111 | struct hv_send_ipi_ex *ipi_arg; | 110 | struct hv_send_ipi_ex *ipi_arg; |
| 112 | unsigned long flags; | 111 | unsigned long flags; |
| 113 | int nr_bank = 0; | 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 | return false; | 116 | return false; |
| 118 | 117 | ||
| 119 | local_irq_save(flags); | 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 | if (unlikely(!ipi_arg)) | 121 | if (unlikely(!ipi_arg)) |
| 124 | goto ipi_mask_ex_done; | 122 | goto ipi_mask_ex_done; |
| 125 | 123 | ||
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <asm/apic.h> | 14 | #include <asm/apic.h> |
| 15 | #include <asm/desc.h> | 15 | #include <asm/desc.h> |
| 16 | #include <asm/sev.h> | 16 | #include <asm/sev.h> |
| 17 | #include <asm/ibt.h> | ||
| 17 | #include <asm/hypervisor.h> | 18 | #include <asm/hypervisor.h> |
| 18 | #include <asm/hyperv-tlfs.h> | 19 | #include <asm/hyperv-tlfs.h> |
| 19 | #include <asm/mshyperv.h> | 20 | #include <asm/mshyperv.h> |
| @@ -471,6 +472,26 @@ void __init hyperv_init(void) · 451 unmodified lines | |||
| 471 | wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); | 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 | * hyperv_init() is called before LAPIC is initialized: see | 496 | * hyperv_init() is called before LAPIC is initialized: see |
| 476 | * apic_intr_mode_init() -> x86_platform.apic_post_init() and | 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 | x86_init.irqs.pre_vector_init = x86_init_noop; | 25 | x86_init.irqs.pre_vector_init = x86_init_noop; |
| 26 | x86_init.timers.timer_init = x86_init_noop; | 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 | x86_platform.get_wallclock = get_rtc_noop; | 32 | x86_platform.get_wallclock = get_rtc_noop; |
| 29 | x86_platform.set_wallclock = set_rtc_noop; | 33 | x86_platform.set_wallclock = set_rtc_noop; |
| 30 | x86_platform.get_nmi_reason = hv_get_nmi_reason; | 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 | static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], | 247 | static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], |
| 248 | enum hv_mem_host_visibility visibility) | 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 | u16 pages_processed; | 251 | u16 pages_processed; |
| 252 | u64 hv_status; | 252 | u64 hv_status; |
| 253 | unsigned long flags; | 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 | local_irq_save(flags); | 265 | local_irq_save(flags); |
| 266 | input_pcpu = (struct hv_gpa_range_for_visibility **) | 266 | input = *this_cpu_ptr(hyperv_pcpu_input_arg); |
| 267 | this_cpu_ptr(hyperv_pcpu_input_arg); | 267 | |
| 268 | input = *input_pcpu; | ||
| 269 | if (unlikely(!input)) { | 268 | if (unlikely(!input)) { |
| 270 | local_irq_restore(flags); | 269 | local_irq_restore(flags); |
| 271 | return -EINVAL; | 270 | return -EINVAL; |
| @@ -61,7 +61,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, · 60 unmodified lines | |||
| 61 | const struct flush_tlb_info *info) | 61 | const struct flush_tlb_info *info) |
| 62 | { | 62 | { |
| 63 | int cpu, vcpu, gva_n, max_gvas; | 63 | int cpu, vcpu, gva_n, max_gvas; |
| 64 | struct hv_tlb_flush **flush_pcpu; | ||
| 65 | struct hv_tlb_flush *flush; | 64 | struct hv_tlb_flush *flush; |
| 66 | u64 status; | 65 | u64 status; |
| 67 | unsigned long flags; | 66 | unsigned long flags; |
| @@ -74,10 +73,7 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus, · 6 unmodified lines | |||
| 74 | 73 | ||
| 75 | local_irq_save(flags); | 74 | local_irq_save(flags); |
| 76 | 75 | ||
| 77 | flush_pcpu = (struct hv_tlb_flush **) | 76 | flush = *this_cpu_ptr(hyperv_pcpu_input_arg); |
| 78 | this_cpu_ptr(hyperv_pcpu_input_arg); | ||
| 79 | |||
| 80 | flush = *flush_pcpu; | ||
| 81 | 77 | ||
| 82 | if (unlikely(!flush)) { | 78 | if (unlikely(!flush)) { |
| 83 | local_irq_restore(flags); | 79 | local_irq_restore(flags); |
| @@ -178,17 +174,13 @@ static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus, · 94 unmodified lines | |||
| 178 | const struct flush_tlb_info *info) | 174 | const struct flush_tlb_info *info) |
| 179 | { | 175 | { |
| 180 | int nr_bank = 0, max_gvas, gva_n; | 176 | int nr_bank = 0, max_gvas, gva_n; |
| 181 | struct hv_tlb_flush_ex **flush_pcpu; | ||
| 182 | struct hv_tlb_flush_ex *flush; | 177 | struct hv_tlb_flush_ex *flush; |
| 183 | u64 status; | 178 | u64 status; |
| 184 | 179 | ||
| 185 | if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) | 180 | if (!(ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED)) |
| 186 | return HV_STATUS_INVALID_PARAMETER; | 181 | return HV_STATUS_INVALID_PARAMETER; |
| 187 | 182 | ||
| 188 | flush_pcpu = (struct hv_tlb_flush_ex **) | 183 | flush = *this_cpu_ptr(hyperv_pcpu_input_arg); |
| 189 | this_cpu_ptr(hyperv_pcpu_input_arg); | ||
| 190 | |||
| 191 | flush = *flush_pcpu; | ||
| 192 | 184 | ||
| 193 | if (info->mm) { | 185 | if (info->mm) { |
| 194 | /* | 186 | /* |
| @@ -19,7 +19,6 @@ · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | int hyperv_flush_guest_mapping(u64 as) | 20 | int hyperv_flush_guest_mapping(u64 as) |
| 21 | { | 21 | { |
| 22 | struct hv_guest_mapping_flush **flush_pcpu; | ||
| 23 | struct hv_guest_mapping_flush *flush; | 22 | struct hv_guest_mapping_flush *flush; |
| 24 | u64 status; | 23 | u64 status; |
| 25 | unsigned long flags; | 24 | unsigned long flags; |
| @@ -30,10 +29,7 @@ int hyperv_flush_guest_mapping(u64 as) · 4 unmodified lines | |||
| 30 | 29 | ||
| 31 | local_irq_save(flags); | 30 | local_irq_save(flags); |
| 32 | 31 | ||
| 33 | flush_pcpu = (struct hv_guest_mapping_flush **) | 32 | flush = *this_cpu_ptr(hyperv_pcpu_input_arg); |
| 34 | this_cpu_ptr(hyperv_pcpu_input_arg); | ||
| 35 | |||
| 36 | flush = *flush_pcpu; | ||
| 37 | 33 | ||
| 38 | if (unlikely(!flush)) { | 34 | if (unlikely(!flush)) { |
| 39 | local_irq_restore(flags); | 35 | local_irq_restore(flags); |
| @@ -90,7 +86,6 @@ EXPORT_SYMBOL_GPL(hyperv_fill_flush_guest_mapping_list); · 50 unmodified lines | |||
| 90 | int hyperv_flush_guest_mapping_range(u64 as, | 86 | int hyperv_flush_guest_mapping_range(u64 as, |
| 91 | hyperv_fill_flush_list_func fill_flush_list_func, void *data) | 87 | hyperv_fill_flush_list_func fill_flush_list_func, void *data) |
| 92 | { | 88 | { |
| 93 | struct hv_guest_mapping_flush_list **flush_pcpu; | ||
| 94 | struct hv_guest_mapping_flush_list *flush; | 89 | struct hv_guest_mapping_flush_list *flush; |
| 95 | u64 status; | 90 | u64 status; |
| 96 | unsigned long flags; | 91 | unsigned long flags; |
| @@ -102,10 +97,8 @@ int hyperv_flush_guest_mapping_range(u64 as, · 5 unmodified lines | |||
| 102 | 97 | ||
| 103 | local_irq_save(flags); | 98 | local_irq_save(flags); |
| 104 | 99 | ||
| 105 | flush_pcpu = (struct hv_guest_mapping_flush_list **) | 100 | flush = *this_cpu_ptr(hyperv_pcpu_input_arg); |
| 106 | this_cpu_ptr(hyperv_pcpu_input_arg); | ||
| 107 | 101 | ||
| 108 | flush = *flush_pcpu; | ||
| 109 | if (unlikely(!flush)) { | 102 | if (unlikely(!flush)) { |
| 110 | local_irq_restore(flags); | 103 | local_irq_restore(flags); |
| 111 | goto fault; | 104 | goto fault; |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <asm/mpspec.h> | 15 | #include <asm/mpspec.h> |
| 16 | #include <asm/x86_init.h> | 16 | #include <asm/x86_init.h> |
| 17 | #include <asm/cpufeature.h> | 17 | #include <asm/cpufeature.h> |
| 18 | #include <asm/irq_vectors.h> | ||
| 18 | 19 | ||
| 19 | #ifdef CONFIG_ACPI_APEI | 20 | #ifdef CONFIG_ACPI_APEI |
| 20 | # include <asm/pgtable_types.h> | 21 | # include <asm/pgtable_types.h> |
| @@ -31,6 +32,7 @@ extern int acpi_skip_timer_override; · 10 unmodified lines | |||
| 31 | extern int acpi_use_timer_override; | 32 | extern int acpi_use_timer_override; |
| 32 | extern int acpi_fix_pin2_polarity; | 33 | extern int acpi_fix_pin2_polarity; |
| 33 | extern int acpi_disable_cmcff; | 34 | extern int acpi_disable_cmcff; |
| 35 | extern bool acpi_int_src_ovr[NR_IRQS_LEGACY]; | ||
| 34 | 36 | ||
| 35 | extern u8 acpi_sci_flags; | 37 | extern u8 acpi_sci_flags; |
| 36 | extern u32 acpi_sci_override_gsi; | 38 | extern u32 acpi_sci_override_gsi; |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | |||
| 14 | * Defines x86 CPU feature bits | 14 | * Defines x86 CPU feature bits |
| 15 | */ | 15 | */ |
| 16 | #define NCAPINTS 21 /* N 32-bit words worth of info */ | 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 | * Note: If the comment begins with a quoted string, that string is used | 20 | * Note: If the comment begins with a quoted string, that string is used |
| @@ -309,6 +309,10 @@ · 288 unmodified lines | |||
| 309 | #define X86_FEATURE_SMBA (11*32+21) /* "" Slow Memory Bandwidth Allocation */ | 309 | #define X86_FEATURE_SMBA (11*32+21) /* "" Slow Memory Bandwidth Allocation */ |
| 310 | #define X86_FEATURE_BMEC (11*32+22) /* "" Bandwidth Monitoring Event Configuration */ | 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 | /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ | 316 | /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ |
| 313 | #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ | 317 | #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ |
| 314 | #define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */ | 318 | #define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */ |
| @@ -442,6 +446,10 @@ · 127 unmodified lines | |||
| 442 | #define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */ | 446 | #define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */ |
| 443 | #define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* "" SMM_CTL MSR is not present */ | 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 | * BUG word(s) | 454 | * BUG word(s) |
| 447 | */ | 455 | */ |
| @@ -483,5 +491,9 @@ · 35 unmodified lines | |||
| 483 | #define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */ | 491 | #define X86_BUG_RETBLEED X86_BUG(27) /* CPU is affected by RETBleed */ |
| 484 | #define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */ | 492 | #define X86_BUG_EIBRS_PBRSB X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */ |
| 485 | #define X86_BUG_SMT_RSB X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */ | 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 | #endif /* _ASM_X86_CPUFEATURES_H */ | 499 | #endif /* _ASM_X86_CPUFEATURES_H */ |
| @@ -21,7 +21,7 @@ · 20 unmodified lines | |||
| 21 | #define FUNCTION_PADDING | 21 | #define FUNCTION_PADDING |
| 22 | #endif | 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 | # define __FUNC_ALIGN __ALIGN; FUNCTION_PADDING | 25 | # define __FUNC_ALIGN __ALIGN; FUNCTION_PADDING |
| 26 | #else | 26 | #else |
| 27 | # define __FUNC_ALIGN __ALIGN | 27 | # define __FUNC_ALIGN __ALIGN |
| @@ -5,7 +5,7 @@ · 4 unmodified lines | |||
| 5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
| 6 | #include <linux/nmi.h> | 6 | #include <linux/nmi.h> |
| 7 | #include <linux/msi.h> | 7 | #include <linux/msi.h> |
| 8 | #include <asm/io.h> | 8 | #include <linux/io.h> |
| 9 | #include <asm/hyperv-tlfs.h> | 9 | #include <asm/hyperv-tlfs.h> |
| 10 | #include <asm/nospec-branch.h> | 10 | #include <asm/nospec-branch.h> |
| 11 | #include <asm/paravirt.h> | 11 | #include <asm/paravirt.h> |
| @@ -57,6 +57,7 @@ · 56 unmodified lines | |||
| 57 | 57 | ||
| 58 | #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */ | 58 | #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */ |
| 59 | #define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */ | 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 | #define MSR_PPIN_CTL 0x0000004e | 62 | #define MSR_PPIN_CTL 0x0000004e |
| 62 | #define MSR_PPIN 0x0000004f | 63 | #define MSR_PPIN 0x0000004f |
| @@ -155,6 +156,15 @@ · 92 unmodified lines | |||
| 155 | * Not susceptible to Post-Barrier | 156 | * Not susceptible to Post-Barrier |
| 156 | * Return Stack Buffer Predictions. | 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 | #define ARCH_CAP_XAPIC_DISABLE BIT(21) /* | 169 | #define ARCH_CAP_XAPIC_DISABLE BIT(21) /* |
| 160 | * IA32_XAPIC_DISABLE_STATUS MSR | 170 | * IA32_XAPIC_DISABLE_STATUS MSR |
| @@ -178,6 +188,8 @@ · 17 unmodified lines | |||
| 178 | #define RNGDS_MITG_DIS BIT(0) /* SRBDS support */ | 188 | #define RNGDS_MITG_DIS BIT(0) /* SRBDS support */ |
| 179 | #define RTM_ALLOW BIT(1) /* TSX development mode */ | 189 | #define RTM_ALLOW BIT(1) /* TSX development mode */ |
| 180 | #define FB_CLEAR_DIS BIT(3) /* CPU Fill buffer clear disable */ | 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 | #define MSR_IA32_SYSENTER_CS 0x00000174 | 194 | #define MSR_IA32_SYSENTER_CS 0x00000174 |
| 183 | #define MSR_IA32_SYSENTER_ESP 0x00000175 | 195 | #define MSR_IA32_SYSENTER_ESP 0x00000175 |
| @@ -211,7 +211,8 @@ · 210 unmodified lines | |||
| 211 | * eventually turn into it's own annotation. | 211 | * eventually turn into it's own annotation. |
| 212 | */ | 212 | */ |
| 213 | .macro VALIDATE_UNRET_END | 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 | ANNOTATE_RETPOLINE_SAFE | 216 | ANNOTATE_RETPOLINE_SAFE |
| 216 | nop | 217 | nop |
| 217 | #endif | 218 | #endif |
| @@ -289,13 +290,18 @@ · 71 unmodified lines | |||
| 289 | */ | 290 | */ |
| 290 | .macro UNTRAIN_RET | 291 | .macro UNTRAIN_RET |
| 291 | #if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_IBPB_ENTRY) || \ | 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 | VALIDATE_UNRET_END | 294 | VALIDATE_UNRET_END |
| 294 | ALTERNATIVE_3 "", \ | 295 | ALTERNATIVE_3 "", \ |
| 295 | CALL_ZEN_UNTRAIN_RET, X86_FEATURE_UNRET, \ | 296 | CALL_ZEN_UNTRAIN_RET, X86_FEATURE_UNRET, \ |
| 296 | "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \ | 297 | "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \ |
| 297 | __stringify(RESET_CALL_DEPTH), X86_FEATURE_CALL_DEPTH | 298 | __stringify(RESET_CALL_DEPTH), X86_FEATURE_CALL_DEPTH |
| 298 | #endif | 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 | .endm | 305 | .endm |
| 300 | 306 | ||
| 301 | .macro UNTRAIN_RET_FROM_CALL | 307 | .macro UNTRAIN_RET_FROM_CALL |
| @@ -307,6 +313,11 @@ · 5 unmodified lines | |||
| 307 | "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \ | 313 | "call entry_ibpb", X86_FEATURE_ENTRY_IBPB, \ |
| 308 | __stringify(RESET_CALL_DEPTH_FROM_CALL), X86_FEATURE_CALL_DEPTH | 314 | __stringify(RESET_CALL_DEPTH_FROM_CALL), X86_FEATURE_CALL_DEPTH |
| 309 | #endif | 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 | .endm | 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 | extern void __x86_return_thunk(void); | 344 | extern void __x86_return_thunk(void); |
| 334 | extern void zen_untrain_ret(void); | 345 | extern void zen_untrain_ret(void); |
| 346 | extern void srso_untrain_ret(void); | ||
| 347 | extern void srso_untrain_ret_alias(void); | ||
| 335 | extern void entry_ibpb(void); | 348 | extern void entry_ibpb(void); |
| 336 | 349 | ||
| 337 | #ifdef CONFIG_CALL_THUNKS | 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 | : "memory"); | 492 | : "memory"); |
| 480 | } | 493 | } |
| 481 | 494 | ||
| 495 | extern u64 x86_pred_cmd; | ||
| 496 | |||
| 482 | static inline void indirect_branch_prediction_barrier(void) | 497 | static inline void indirect_branch_prediction_barrier(void) |
| 483 | { | 498 | { |
| 484 | u64 val = PRED_CMD_IBPB; | 499 | alternative_msr_write(MSR_IA32_PRED_CMD, x86_pred_cmd, X86_FEATURE_USE_IBPB); |
| 485 | |||
| 486 | alternative_msr_write(MSR_IA32_PRED_CMD, val, X86_FEATURE_USE_IBPB); | ||
| 487 | } | 500 | } |
| 488 | 501 | ||
| 489 | /* The Intel SPEC CTRL MSR base value cache */ | 502 | /* The Intel SPEC CTRL MSR base value cache */ |
| @@ -586,7 +586,6 @@ extern char ignore_fpu_irq; · 585 unmodified lines | |||
| 586 | 586 | ||
| 587 | #define HAVE_ARCH_PICK_MMAP_LAYOUT 1 | 587 | #define HAVE_ARCH_PICK_MMAP_LAYOUT 1 |
| 588 | #define ARCH_HAS_PREFETCHW | 588 | #define ARCH_HAS_PREFETCHW |
| 589 | #define ARCH_HAS_SPINLOCK_PREFETCH | ||
| 590 | 589 | ||
| 591 | #ifdef CONFIG_X86_32 | 590 | #ifdef CONFIG_X86_32 |
| 592 | # define BASE_PREFETCH "" | 591 | # define BASE_PREFETCH "" |
| @@ -620,11 +619,6 @@ static __always_inline void prefetchw(const void *x) · 27 unmodified lines | |||
| 620 | "m" (*(const char *)x)); | 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 | #define TOP_OF_INIT_STACK ((unsigned long)&init_stack + sizeof(init_stack) - \ | 622 | #define TOP_OF_INIT_STACK ((unsigned long)&init_stack + sizeof(init_stack) - \ |
| 629 | TOP_OF_KERNEL_STACK_PADDING) | 623 | TOP_OF_KERNEL_STACK_PADDING) |
| 630 | 624 | ||
| @@ -682,9 +676,13 @@ extern u16 get_llc_id(unsigned int cpu); · 51 unmodified lines | |||
| 682 | #ifdef CONFIG_CPU_SUP_AMD | 676 | #ifdef CONFIG_CPU_SUP_AMD |
| 683 | extern u32 amd_get_nodes_per_socket(void); | 677 | extern u32 amd_get_nodes_per_socket(void); |
| 684 | extern u32 amd_get_highest_perf(void); | 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 | #else | 681 | #else |
| 686 | static inline u32 amd_get_nodes_per_socket(void) { return 0; } | 682 | static inline u32 amd_get_nodes_per_socket(void) { return 0; } |
| 687 | static inline u32 amd_get_highest_perf(void) { return 0; } | 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 | #endif | 686 | #endif |
| 689 | 687 | ||
| 690 | extern unsigned long arch_align_stack(unsigned long sp); | 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 | #define arch_is_platform_page arch_is_platform_page | 725 | #define arch_is_platform_page arch_is_platform_page |
| 728 | #endif | 726 | #endif |
| 729 | 727 | ||
| 728 | extern bool gds_ucode_mitigated(void); | ||
| 729 | |||
| 730 | #endif /* _ASM_X86_PROCESSOR_H */ | 730 | #endif /* _ASM_X86_PROCESSOR_H */ |
| @@ -56,7 +56,7 @@ · 55 unmodified lines | |||
| 56 | 56 | ||
| 57 | #define GDT_ENTRY_INVALID_SEG 0 | 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 | * The layout of the per-CPU GDT under Linux: | 61 | * The layout of the per-CPU GDT under Linux: |
| 62 | * | 62 | * |
| @@ -52,6 +52,7 @@ int acpi_lapic; · 51 unmodified lines | |||
| 52 | int acpi_ioapic; | 52 | int acpi_ioapic; |
| 53 | int acpi_strict; | 53 | int acpi_strict; |
| 54 | int acpi_disable_cmcff; | 54 | int acpi_disable_cmcff; |
| 55 | bool acpi_int_src_ovr[NR_IRQS_LEGACY]; | ||
| 55 | 56 | ||
| 56 | /* ACPI SCI override configuration */ | 57 | /* ACPI SCI override configuration */ |
| 57 | u8 acpi_sci_flags __initdata; | 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 | acpi_table_print_madt_entry(&header->common); | 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 | if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { | 595 | if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { |
| 592 | acpi_sci_ioapic_setup(intsrc->source_irq, | 596 | acpi_sci_ioapic_setup(intsrc->source_irq, |
| 593 | intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, | 597 | intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, |
| @@ -73,8 +73,13 @@ static const int amd_erratum_1054[] = · 72 unmodified lines | |||
| 73 | static const int amd_zenbleed[] = | 73 | static const int amd_zenbleed[] = |
| 74 | AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf), | 74 | AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf), |
| 75 | AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf), | 75 | AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf), |
| 76 | AMD_MODEL_RANGE(0x17, 0x90, 0x0, 0x91, 0xf), | ||
| 76 | AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf)); | 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 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) | 83 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) |
| 79 | { | 84 | { |
| 80 | int osvw_id = *erratum++; | 85 | int osvw_id = *erratum++; |
| @@ -1130,6 +1135,11 @@ static void init_amd(struct cpuinfo_x86 *c) · 1049 unmodified lines | |||
| 1130 | WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS)); | 1135 | WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS)); |
| 1131 | 1136 | ||
| 1132 | zenbleed_check(c); | 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 | #ifdef CONFIG_X86_32 | 1145 | #ifdef CONFIG_X86_32 |
| @@ -1290,3 +1300,32 @@ void amd_check_microcode(void) · 154 unmodified lines | |||
| 1290 | { | 1300 | { |
| 1291 | on_each_cpu(zenbleed_check_cpu, NULL, 1); | 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 | static void __init mmio_select_mitigation(void); | 47 | static void __init mmio_select_mitigation(void); |
| 48 | static void __init srbds_select_mitigation(void); | 48 | static void __init srbds_select_mitigation(void); |
| 49 | static void __init l1d_flush_select_mitigation(void); | 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 | /* The base value of the SPEC_CTRL MSR without task-specific bits set */ | 53 | /* The base value of the SPEC_CTRL MSR without task-specific bits set */ |
| 52 | u64 x86_spec_ctrl_base; | 54 | u64 x86_spec_ctrl_base; |
| @@ -56,6 +58,9 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_base); · 3 unmodified lines | |||
| 56 | DEFINE_PER_CPU(u64, x86_spec_ctrl_current); | 58 | DEFINE_PER_CPU(u64, x86_spec_ctrl_current); |
| 57 | EXPORT_SYMBOL_GPL(x86_spec_ctrl_current); | 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 | static DEFINE_MUTEX(spec_ctrl_mutex); | 64 | static DEFINE_MUTEX(spec_ctrl_mutex); |
| 60 | 65 | ||
| 61 | /* Update SPEC_CTRL MSR and its cached copy unconditionally */ | 66 | /* Update SPEC_CTRL MSR and its cached copy unconditionally */ |
| @@ -160,6 +165,8 @@ void __init cpu_select_mitigations(void) · 98 unmodified lines | |||
| 160 | md_clear_select_mitigation(); | 165 | md_clear_select_mitigation(); |
| 161 | srbds_select_mitigation(); | 166 | srbds_select_mitigation(); |
| 162 | l1d_flush_select_mitigation(); | 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 | early_param("l1d_flush", l1d_flush_parse_cmdline); | 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 | #undef pr_fmt | 798 | #undef pr_fmt |
| 649 | #define pr_fmt(fmt) "Spectre V1 : " fmt | 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 | early_param("l1tf", l1tf_cmdline); | 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 | #undef pr_fmt | 2499 | #undef pr_fmt |
| 2191 | #define pr_fmt(fmt) fmt | 2500 | #define pr_fmt(fmt) fmt |
| 2192 | 2501 | ||
| @@ -2385,6 +2694,18 @@ static ssize_t retbleed_show_state(char *buf) · 192 unmodified lines | |||
| 2385 | return sysfs_emit(buf, "%s\n", retbleed_strings[retbleed_mitigation]); | 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 | static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, | 2709 | static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, |
| 2389 | char *buf, unsigned int bug) | 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 | case X86_BUG_RETBLEED: | 2755 | case X86_BUG_RETBLEED: |
| 2435 | return retbleed_show_state(buf); | 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 | default: | 2764 | default: |
| 2438 | break; | 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 | return cpu_show_common(dev, attr, buf, X86_BUG_RETBLEED); | 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 | #endif | 2838 | #endif |
| @@ -1250,6 +1250,10 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { · 1249 unmodified lines | |||
| 1250 | #define RETBLEED BIT(3) | 1250 | #define RETBLEED BIT(3) |
| 1251 | /* CPU is affected by SMT (cross-thread) return predictions */ | 1251 | /* CPU is affected by SMT (cross-thread) return predictions */ |
| 1252 | #define SMT_RSB BIT(4) | 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 | static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { | 1258 | static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { |
| 1255 | VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS), | 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 | VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO), | 1266 | VULNBL_INTEL_STEPPINGS(BROADWELL_X, X86_STEPPING_ANY, MMIO), |
| 1263 | VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS), | 1267 | VULNBL_INTEL_STEPPINGS(BROADWELL, X86_STEPPING_ANY, SRBDS), |
| 1264 | VULNBL_INTEL_STEPPINGS(SKYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED), | 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 | VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED), | 1270 | VULNBL_INTEL_STEPPINGS(SKYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED), |
| 1267 | VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED), | 1271 | VULNBL_INTEL_STEPPINGS(KABYLAKE_L, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED | GDS), |
| 1268 | VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED), | 1272 | VULNBL_INTEL_STEPPINGS(KABYLAKE, X86_STEPPING_ANY, SRBDS | MMIO | RETBLEED | GDS), |
| 1269 | VULNBL_INTEL_STEPPINGS(CANNONLAKE_L, X86_STEPPING_ANY, RETBLEED), | 1273 | VULNBL_INTEL_STEPPINGS(CANNONLAKE_L, X86_STEPPING_ANY, RETBLEED), |
| 1270 | VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED), | 1274 | VULNBL_INTEL_STEPPINGS(ICELAKE_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS), |
| 1271 | VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO), | 1275 | VULNBL_INTEL_STEPPINGS(ICELAKE_D, X86_STEPPING_ANY, MMIO | GDS), |
| 1272 | VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO), | 1276 | VULNBL_INTEL_STEPPINGS(ICELAKE_X, X86_STEPPING_ANY, MMIO | GDS), |
| 1273 | VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED), | 1277 | VULNBL_INTEL_STEPPINGS(COMETLAKE, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED | GDS), |
| 1274 | VULNBL_INTEL_STEPPINGS(COMETLAKE_L, X86_STEPPINGS(0x0, 0x0), MMIO | RETBLEED), | 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 | VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED), | 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 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPING_ANY, MMIO | MMIO_SBDS), | 1284 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPING_ANY, MMIO | MMIO_SBDS), |
| 1279 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO), | 1285 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO), |
| 1280 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS), | 1286 | VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS), |
| 1281 | 1287 | ||
| 1282 | VULNBL_AMD(0x15, RETBLEED), | 1288 | VULNBL_AMD(0x15, RETBLEED), |
| 1283 | VULNBL_AMD(0x16, RETBLEED), | 1289 | VULNBL_AMD(0x16, RETBLEED), |
| 1284 | VULNBL_AMD(0x17, RETBLEED | SMT_RSB), | 1290 | VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO), |
| 1285 | VULNBL_HYGON(0x18, RETBLEED | SMT_RSB), | 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 | if (cpu_matches(cpu_vuln_blacklist, SMT_RSB)) | 1413 | if (cpu_matches(cpu_vuln_blacklist, SMT_RSB)) |
| 1407 | setup_force_cpu_bug(X86_BUG_SMT_RSB); | 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 | if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) | 1431 | if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) |
| 1410 | return; | 1432 | return; |
| 1411 | 1433 | ||
| @@ -1962,6 +1984,8 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c) · 550 unmodified lines | |||
| 1962 | validate_apic_and_package_id(c); | 1984 | validate_apic_and_package_id(c); |
| 1963 | x86_spec_ctrl_setup_ap(); | 1985 | x86_spec_ctrl_setup_ap(); |
| 1964 | update_srbds_msr(); | 1986 | update_srbds_msr(); |
| 1987 | if (boot_cpu_has_bug(X86_BUG_GDS)) | ||
| 1988 | update_gds_msr(); | ||
| 1965 | 1989 | ||
| 1966 | tsx_ap_init(); | 1990 | tsx_ap_init(); |
| 1967 | } | 1991 | } |
| @@ -83,6 +83,7 @@ void cpu_select_mitigations(void); · 82 unmodified lines | |||
| 83 | 83 | ||
| 84 | extern void x86_spec_ctrl_setup_ap(void); | 84 | extern void x86_spec_ctrl_setup_ap(void); |
| 85 | extern void update_srbds_msr(void); | 85 | extern void update_srbds_msr(void); |
| 86 | extern void update_gds_msr(void); | ||
| 86 | 87 | ||
| 87 | extern enum spectre_v2_mitigation spectre_v2_enabled; | 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 | do_error_trap(regs, 0, "divide error", X86_TRAP_DE, SIGFPE, | 207 | do_error_trap(regs, 0, "divide error", X86_TRAP_DE, SIGFPE, |
| 208 | FPE_INTDIV, error_get_trap_addr(regs)); | 208 | FPE_INTDIV, error_get_trap_addr(regs)); |
| 209 | |||
| 210 | amd_clear_divider(); | ||
| 209 | } | 211 | } |
| 210 | 212 | ||
| 211 | DEFINE_IDTENTRY(exc_overflow) | 213 | DEFINE_IDTENTRY(exc_overflow) |
| @@ -134,13 +134,27 @@ SECTIONS · 133 unmodified lines | |||
| 134 | SOFTIRQENTRY_TEXT | 134 | SOFTIRQENTRY_TEXT |
| 135 | #ifdef CONFIG_RETPOLINE | 135 | #ifdef CONFIG_RETPOLINE |
| 136 | __indirect_thunk_start = .; | 136 | __indirect_thunk_start = .; |
| 137 | *(.text.__x86.*) | 137 | *(.text.__x86.indirect_thunk) |
| 138 | *(.text.__x86.return_thunk) | ||
| 138 | __indirect_thunk_end = .; | 139 | __indirect_thunk_end = .; |
| 139 | #endif | 140 | #endif |
| 140 | STATIC_CALL_TEXT | 141 | STATIC_CALL_TEXT |
| 141 | 142 | ||
| 142 | ALIGN_ENTRY_TEXT_BEGIN | 143 | ALIGN_ENTRY_TEXT_BEGIN |
| 144 | #ifdef CONFIG_CPU_SRSO | ||
| 145 | *(.text.__x86.rethunk_untrain) | ||
| 146 | #endif | ||
| 147 | |||
| 143 | ENTRY_TEXT | 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 | ALIGN_ENTRY_TEXT_END | 158 | ALIGN_ENTRY_TEXT_END |
| 145 | *(.gnu.warning) | 159 | *(.gnu.warning) |
| 146 | 160 | ||
| @@ -509,7 +523,24 @@ INIT_PER_CPU(irq_stack_backing_store); · 362 unmodified lines | |||
| 509 | #endif | 523 | #endif |
| 510 | 524 | ||
| 511 | #ifdef CONFIG_RETHUNK | 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 | #endif | 544 | #endif |
| 514 | 545 | ||
| 515 | #endif /* CONFIG_X86_64 */ | 546 | #endif /* CONFIG_X86_64 */ |
| @@ -729,6 +729,9 @@ void kvm_set_cpu_caps(void) · 728 unmodified lines | |||
| 729 | F(NULL_SEL_CLR_BASE) | F(AUTOIBRS) | 0 /* PrefetchCtlMsr */ | 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 | kvm_cpu_cap_init_kvm_defined(CPUID_8000_0022_EAX, | 735 | kvm_cpu_cap_init_kvm_defined(CPUID_8000_0022_EAX, |
| 733 | F(PERFMON_V2) | 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 | memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs)); | 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); | 2420 | BUILD_BUG_ON(sizeof(svm->sev_es.valid_bitmap) != sizeof(ghcb->save.valid_bitmap)); |
| 2421 | vcpu->arch.regs[VCPU_REGS_RBX] = ghcb_get_rbx_if_valid(ghcb); | 2421 | memcpy(&svm->sev_es.valid_bitmap, &ghcb->save.valid_bitmap, sizeof(ghcb->save.valid_bitmap)); |
| 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); | ||
| 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 | vcpu->arch.xcr0 = ghcb_get_xcr0(ghcb); | 2432 | vcpu->arch.xcr0 = ghcb_get_xcr0(ghcb); |
| 2430 | kvm_update_cpuid_runtime(vcpu); | 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 | control->exit_code_hi = upper_32_bits(exit_code); | 2439 | control->exit_code_hi = upper_32_bits(exit_code); |
| 2437 | control->exit_info_1 = ghcb_get_sw_exit_info_1(ghcb); | 2440 | control->exit_info_1 = ghcb_get_sw_exit_info_1(ghcb); |
| 2438 | control->exit_info_2 = ghcb_get_sw_exit_info_2(ghcb); | 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 | /* Clear the valid entries fields */ | 2444 | /* Clear the valid entries fields */ |
| 2441 | memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap)); | 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 | static int sev_es_validate_vmgexit(struct vcpu_svm *svm) | 2453 | static int sev_es_validate_vmgexit(struct vcpu_svm *svm) |
| 2445 | { | 2454 | { |
| 2446 | struct kvm_vcpu *vcpu; | 2455 | struct vmcb_control_area *control = &svm->vmcb->control; |
| 2447 | struct ghcb *ghcb; | 2456 | struct kvm_vcpu *vcpu = &svm->vcpu; |
| 2448 | u64 exit_code; | 2457 | u64 exit_code; |
| 2449 | u64 reason; | 2458 | u64 reason; |
| 2450 | 2459 | ||
| 2451 | ghcb = svm->sev_es.ghcb; | ||
| 2452 | |||
| 2453 | /* | 2460 | /* |
| 2454 | * Retrieve the exit code now even though it may not be marked valid | 2461 | * Retrieve the exit code now even though it may not be marked valid |
| 2455 | * as it could help with debugging. | 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 | /* Only GHCB Usage code 0 is supported */ | 2466 | /* Only GHCB Usage code 0 is supported */ |
| 2460 | if (ghcb->ghcb_usage) { | 2467 | if (svm->sev_es.ghcb->ghcb_usage) { |
| 2461 | reason = GHCB_ERR_INVALID_USAGE; | 2468 | reason = GHCB_ERR_INVALID_USAGE; |
| 2462 | goto vmgexit_err; | 2469 | goto vmgexit_err; |
| 2463 | } | 2470 | } |
| 2464 | 2471 | ||
| 2465 | reason = GHCB_ERR_MISSING_INPUT; | 2472 | reason = GHCB_ERR_MISSING_INPUT; |
| 2466 | 2473 | ||
| 2467 | if (!ghcb_sw_exit_code_is_valid(ghcb) || | 2474 | if (!kvm_ghcb_sw_exit_code_is_valid(svm) || |
| 2468 | !ghcb_sw_exit_info_1_is_valid(ghcb) || | 2475 | !kvm_ghcb_sw_exit_info_1_is_valid(svm) || |
| 2469 | !ghcb_sw_exit_info_2_is_valid(ghcb)) | 2476 | !kvm_ghcb_sw_exit_info_2_is_valid(svm)) |
| 2470 | goto vmgexit_err; | 2477 | goto vmgexit_err; |
| 2471 | 2478 | ||
| 2472 | switch (ghcb_get_sw_exit_code(ghcb)) { | 2479 | switch (exit_code) { |
| 2473 | case SVM_EXIT_READ_DR7: | 2480 | case SVM_EXIT_READ_DR7: |
| 2474 | break; | 2481 | break; |
| 2475 | case SVM_EXIT_WRITE_DR7: | 2482 | case SVM_EXIT_WRITE_DR7: |
| 2476 | if (!ghcb_rax_is_valid(ghcb)) | 2483 | if (!kvm_ghcb_rax_is_valid(svm)) |
| 2477 | goto vmgexit_err; | 2484 | goto vmgexit_err; |
| 2478 | break; | 2485 | break; |
| 2479 | case SVM_EXIT_RDTSC: | 2486 | case SVM_EXIT_RDTSC: |
| 2480 | break; | 2487 | break; |
| 2481 | case SVM_EXIT_RDPMC: | 2488 | case SVM_EXIT_RDPMC: |
| 2482 | if (!ghcb_rcx_is_valid(ghcb)) | 2489 | if (!kvm_ghcb_rcx_is_valid(svm)) |
| 2483 | goto vmgexit_err; | 2490 | goto vmgexit_err; |
| 2484 | break; | 2491 | break; |
| 2485 | case SVM_EXIT_CPUID: | 2492 | case SVM_EXIT_CPUID: |
| 2486 | if (!ghcb_rax_is_valid(ghcb) || | 2493 | if (!kvm_ghcb_rax_is_valid(svm) || |
| 2487 | !ghcb_rcx_is_valid(ghcb)) | 2494 | !kvm_ghcb_rcx_is_valid(svm)) |
| 2488 | goto vmgexit_err; | 2495 | goto vmgexit_err; |
| 2489 | if (ghcb_get_rax(ghcb) == 0xd) | 2496 | if (vcpu->arch.regs[VCPU_REGS_RAX] == 0xd) |
| 2490 | if (!ghcb_xcr0_is_valid(ghcb)) | 2497 | if (!kvm_ghcb_xcr0_is_valid(svm)) |
| 2491 | goto vmgexit_err; | 2498 | goto vmgexit_err; |
| 2492 | break; | 2499 | break; |
| 2493 | case SVM_EXIT_INVD: | 2500 | case SVM_EXIT_INVD: |
| 2494 | break; | 2501 | break; |
| 2495 | case SVM_EXIT_IOIO: | 2502 | case SVM_EXIT_IOIO: |
| 2496 | if (ghcb_get_sw_exit_info_1(ghcb) & SVM_IOIO_STR_MASK) { | 2503 | if (control->exit_info_1 & SVM_IOIO_STR_MASK) { |
| 2497 | if (!ghcb_sw_scratch_is_valid(ghcb)) | 2504 | if (!kvm_ghcb_sw_scratch_is_valid(svm)) |
| 2498 | goto vmgexit_err; | 2505 | goto vmgexit_err; |
| 2499 | } else { | 2506 | } else { |
| 2500 | if (!(ghcb_get_sw_exit_info_1(ghcb) & SVM_IOIO_TYPE_MASK)) | 2507 | if (!(control->exit_info_1 & SVM_IOIO_TYPE_MASK)) |
| 2501 | if (!ghcb_rax_is_valid(ghcb)) | 2508 | if (!kvm_ghcb_rax_is_valid(svm)) |
| 2502 | goto vmgexit_err; | 2509 | goto vmgexit_err; |
| 2503 | } | 2510 | } |
| 2504 | break; | 2511 | break; |
| 2505 | case SVM_EXIT_MSR: | 2512 | case SVM_EXIT_MSR: |
| 2506 | if (!ghcb_rcx_is_valid(ghcb)) | 2513 | if (!kvm_ghcb_rcx_is_valid(svm)) |
| 2507 | goto vmgexit_err; | 2514 | goto vmgexit_err; |
| 2508 | if (ghcb_get_sw_exit_info_1(ghcb)) { | 2515 | if (control->exit_info_1) { |
| 2509 | if (!ghcb_rax_is_valid(ghcb) || | 2516 | if (!kvm_ghcb_rax_is_valid(svm) || |
| 2510 | !ghcb_rdx_is_valid(ghcb)) | 2517 | !kvm_ghcb_rdx_is_valid(svm)) |
| 2511 | goto vmgexit_err; | 2518 | goto vmgexit_err; |
| 2512 | } | 2519 | } |
| 2513 | break; | 2520 | break; |
| 2514 | case SVM_EXIT_VMMCALL: | 2521 | case SVM_EXIT_VMMCALL: |
| 2515 | if (!ghcb_rax_is_valid(ghcb) || | 2522 | if (!kvm_ghcb_rax_is_valid(svm) || |
| 2516 | !ghcb_cpl_is_valid(ghcb)) | 2523 | !kvm_ghcb_cpl_is_valid(svm)) |
| 2517 | goto vmgexit_err; | 2524 | goto vmgexit_err; |
| 2518 | break; | 2525 | break; |
| 2519 | case SVM_EXIT_RDTSCP: | 2526 | case SVM_EXIT_RDTSCP: |
| @@ -2521,19 +2528,19 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) · 1 unmodified line | |||
| 2521 | case SVM_EXIT_WBINVD: | 2528 | case SVM_EXIT_WBINVD: |
| 2522 | break; | 2529 | break; |
| 2523 | case SVM_EXIT_MONITOR: | 2530 | case SVM_EXIT_MONITOR: |
| 2524 | if (!ghcb_rax_is_valid(ghcb) || | 2531 | if (!kvm_ghcb_rax_is_valid(svm) || |
| 2525 | !ghcb_rcx_is_valid(ghcb) || | 2532 | !kvm_ghcb_rcx_is_valid(svm) || |
| 2526 | !ghcb_rdx_is_valid(ghcb)) | 2533 | !kvm_ghcb_rdx_is_valid(svm)) |
| 2527 | goto vmgexit_err; | 2534 | goto vmgexit_err; |
| 2528 | break; | 2535 | break; |
| 2529 | case SVM_EXIT_MWAIT: | 2536 | case SVM_EXIT_MWAIT: |
| 2530 | if (!ghcb_rax_is_valid(ghcb) || | 2537 | if (!kvm_ghcb_rax_is_valid(svm) || |
| 2531 | !ghcb_rcx_is_valid(ghcb)) | 2538 | !kvm_ghcb_rcx_is_valid(svm)) |
| 2532 | goto vmgexit_err; | 2539 | goto vmgexit_err; |
| 2533 | break; | 2540 | break; |
| 2534 | case SVM_VMGEXIT_MMIO_READ: | 2541 | case SVM_VMGEXIT_MMIO_READ: |
| 2535 | case SVM_VMGEXIT_MMIO_WRITE: | 2542 | case SVM_VMGEXIT_MMIO_WRITE: |
| 2536 | if (!ghcb_sw_scratch_is_valid(ghcb)) | 2543 | if (!kvm_ghcb_sw_scratch_is_valid(svm)) |
| 2537 | goto vmgexit_err; | 2544 | goto vmgexit_err; |
| 2538 | break; | 2545 | break; |
| 2539 | case SVM_VMGEXIT_NMI_COMPLETE: | 2546 | case SVM_VMGEXIT_NMI_COMPLETE: |
| @@ -2549,11 +2556,9 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) · 9 unmodified lines | |||
| 2549 | return 0; | 2556 | return 0; |
| 2550 | 2557 | ||
| 2551 | vmgexit_err: | 2558 | vmgexit_err: |
| 2552 | vcpu = &svm->vcpu; | ||
| 2553 | |||
| 2554 | if (reason == GHCB_ERR_INVALID_USAGE) { | 2559 | if (reason == GHCB_ERR_INVALID_USAGE) { |
| 2555 | vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n", | 2560 | vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n", |
| 2556 | ghcb->ghcb_usage); | 2561 | svm->sev_es.ghcb->ghcb_usage); |
| 2557 | } else if (reason == GHCB_ERR_INVALID_EVENT) { | 2562 | } else if (reason == GHCB_ERR_INVALID_EVENT) { |
| 2558 | vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n", | 2563 | vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n", |
| 2559 | exit_code); | 2564 | exit_code); |
| @@ -2563,11 +2568,8 @@ vmgexit_err: · 3 unmodified lines | |||
| 2563 | dump_ghcb(svm); | 2568 | dump_ghcb(svm); |
| 2564 | } | 2569 | } |
| 2565 | 2570 | ||
| 2566 | /* Clear the valid entries fields */ | 2571 | ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2); |
| 2567 | memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap)); | 2572 | ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, reason); |
| 2568 | |||
| 2569 | ghcb_set_sw_exit_info_1(ghcb, 2); | ||
| 2570 | ghcb_set_sw_exit_info_2(ghcb, reason); | ||
| 2571 | 2573 | ||
| 2572 | /* Resume the guest to "return" the error code. */ | 2574 | /* Resume the guest to "return" the error code. */ |
| 2573 | return 1; | 2575 | return 1; |
| @@ -2586,7 +2588,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm) · 12 unmodified lines | |||
| 2586 | */ | 2588 | */ |
| 2587 | if (svm->sev_es.ghcb_sa_sync) { | 2589 | if (svm->sev_es.ghcb_sa_sync) { |
| 2588 | kvm_write_guest(svm->vcpu.kvm, | 2590 | kvm_write_guest(svm->vcpu.kvm, |
| 2589 | ghcb_get_sw_scratch(svm->sev_es.ghcb), | 2591 | svm->sev_es.sw_scratch, |
| 2590 | svm->sev_es.ghcb_sa, | 2592 | svm->sev_es.ghcb_sa, |
| 2591 | svm->sev_es.ghcb_sa_len); | 2593 | svm->sev_es.ghcb_sa_len); |
| 2592 | svm->sev_es.ghcb_sa_sync = false; | 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 | static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) | 2634 | static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) |
| 2633 | { | 2635 | { |
| 2634 | struct vmcb_control_area *control = &svm->vmcb->control; | 2636 | struct vmcb_control_area *control = &svm->vmcb->control; |
| 2635 | struct ghcb *ghcb = svm->sev_es.ghcb; | ||
| 2636 | u64 ghcb_scratch_beg, ghcb_scratch_end; | 2637 | u64 ghcb_scratch_beg, ghcb_scratch_end; |
| 2637 | u64 scratch_gpa_beg, scratch_gpa_end; | 2638 | u64 scratch_gpa_beg, scratch_gpa_end; |
| 2638 | void *scratch_va; | 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 | if (!scratch_gpa_beg) { | 2642 | if (!scratch_gpa_beg) { |
| 2642 | pr_err("vmgexit: scratch gpa not provided\n"); | 2643 | pr_err("vmgexit: scratch gpa not provided\n"); |
| 2643 | goto e_scratch; | 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 | return 0; | 2709 | return 0; |
| 2709 | 2710 | ||
| 2710 | e_scratch: | 2711 | e_scratch: |
| 2711 | ghcb_set_sw_exit_info_1(ghcb, 2); | 2712 | ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2); |
| 2712 | ghcb_set_sw_exit_info_2(ghcb, GHCB_ERR_INVALID_SCRATCH_AREA); | 2713 | ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_SCRATCH_AREA); |
| 2713 | 2714 | ||
| 2714 | return 1; | 2715 | return 1; |
| 2715 | } | 2716 | } |
| @@ -2822,7 +2823,6 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) · 106 unmodified lines | |||
| 2822 | struct vcpu_svm *svm = to_svm(vcpu); | 2823 | struct vcpu_svm *svm = to_svm(vcpu); |
| 2823 | struct vmcb_control_area *control = &svm->vmcb->control; | 2824 | struct vmcb_control_area *control = &svm->vmcb->control; |
| 2824 | u64 ghcb_gpa, exit_code; | 2825 | u64 ghcb_gpa, exit_code; |
| 2825 | struct ghcb *ghcb; | ||
| 2826 | int ret; | 2826 | int ret; |
| 2827 | 2827 | ||
| 2828 | /* Validate the GHCB */ | 2828 | /* Validate the GHCB */ |
| @@ -2847,20 +2847,18 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) · 18 unmodified lines | |||
| 2847 | } | 2847 | } |
| 2848 | 2848 | ||
| 2849 | svm->sev_es.ghcb = svm->sev_es.ghcb_map.hva; | 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); | 2851 | trace_kvm_vmgexit_enter(vcpu->vcpu_id, svm->sev_es.ghcb); |
| 2853 | |||
| 2854 | exit_code = ghcb_get_sw_exit_code(ghcb); | ||
| 2855 | 2852 | ||
| 2853 | sev_es_sync_from_ghcb(svm); | ||
| 2856 | ret = sev_es_validate_vmgexit(svm); | 2854 | ret = sev_es_validate_vmgexit(svm); |
| 2857 | if (ret) | 2855 | if (ret) |
| 2858 | return ret; | 2856 | return ret; |
| 2859 | 2857 | ||
| 2860 | sev_es_sync_from_ghcb(svm); | 2858 | ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 0); |
| 2861 | ghcb_set_sw_exit_info_1(ghcb, 0); | 2859 | ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, 0); |
| 2862 | ghcb_set_sw_exit_info_2(ghcb, 0); | ||
| 2863 | 2860 | ||
| 2861 | exit_code = kvm_ghcb_get_sw_exit_code(control); | ||
| 2864 | switch (exit_code) { | 2862 | switch (exit_code) { |
| 2865 | case SVM_VMGEXIT_MMIO_READ: | 2863 | case SVM_VMGEXIT_MMIO_READ: |
| 2866 | ret = setup_vmgexit_scratch(svm, true, control->exit_info_2); | 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 | break; | 2896 | break; |
| 2899 | case 1: | 2897 | case 1: |
| 2900 | /* Get AP jump table address */ | 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 | break; | 2900 | break; |
| 2903 | default: | 2901 | default: |
| 2904 | pr_err("svm: vmgexit: unsupported AP jump table request - exit_info_1=%#llx\n", | 2902 | pr_err("svm: vmgexit: unsupported AP jump table request - exit_info_1=%#llx\n", |
| 2905 | control->exit_info_1); | 2903 | control->exit_info_1); |
| 2906 | ghcb_set_sw_exit_info_1(ghcb, 2); | 2904 | ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 2); |
| 2907 | ghcb_set_sw_exit_info_2(ghcb, GHCB_ERR_INVALID_INPUT); | 2905 | ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, GHCB_ERR_INVALID_INPUT); |
| 2908 | } | 2906 | } |
| 2909 | 2907 | ||
| 2910 | ret = 1; | 2908 | ret = 1; |
| @@ -1498,7 +1498,9 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) · 1497 unmodified lines | |||
| 1498 | 1498 | ||
| 1499 | if (sd->current_vmcb != svm->vmcb) { | 1499 | if (sd->current_vmcb != svm->vmcb) { |
| 1500 | sd->current_vmcb = svm->vmcb; | 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 | if (kvm_vcpu_apicv_active(vcpu)) | 1505 | if (kvm_vcpu_apicv_active(vcpu)) |
| 1504 | avic_vcpu_load(vcpu, cpu); | 1506 | avic_vcpu_load(vcpu, cpu); |
| @@ -190,10 +190,12 @@ struct vcpu_sev_es_state { · 189 unmodified lines | |||
| 190 | /* SEV-ES support */ | 190 | /* SEV-ES support */ |
| 191 | struct sev_es_save_area *vmsa; | 191 | struct sev_es_save_area *vmsa; |
| 192 | struct ghcb *ghcb; | 192 | struct ghcb *ghcb; |
| 193 | u8 valid_bitmap[16]; | ||
| 193 | struct kvm_host_map ghcb_map; | 194 | struct kvm_host_map ghcb_map; |
| 194 | bool received_first_sipi; | 195 | bool received_first_sipi; |
| 195 | 196 | ||
| 196 | /* SEV-ES scratch area support */ | 197 | /* SEV-ES scratch area support */ |
| 198 | u64 sw_scratch; | ||
| 197 | void *ghcb_sa; | 199 | void *ghcb_sa; |
| 198 | u32 ghcb_sa_len; | 200 | u32 ghcb_sa_len; |
| 199 | bool ghcb_sa_sync; | 201 | bool ghcb_sa_sync; |
| @@ -744,4 +746,28 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm); · 544 unmodified lines | |||
| 744 | void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted); | 746 | void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted); |
| 745 | void __svm_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted); | 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 | #endif | 773 | #endif |
| @@ -224,6 +224,9 @@ SYM_FUNC_START(__svm_vcpu_run) · 223 unmodified lines | |||
| 224 | */ | 224 | */ |
| 225 | UNTRAIN_RET | 225 | UNTRAIN_RET |
| 226 | 226 | ||
| 227 | /* SRSO */ | ||
| 228 | ALTERNATIVE "", "call entry_ibpb", X86_FEATURE_IBPB_ON_VMEXIT | ||
| 229 | |||
| 227 | /* | 230 | /* |
| 228 | * Clear all general purpose registers except RSP and RAX to prevent | 231 | * Clear all general purpose registers except RSP and RAX to prevent |
| 229 | * speculative use of the guest's values, even those that are reloaded | 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 | ARCH_CAP_SKIP_VMENTRY_L1DFLUSH | ARCH_CAP_SSB_NO | ARCH_CAP_MDS_NO | \ | 1616 | ARCH_CAP_SKIP_VMENTRY_L1DFLUSH | ARCH_CAP_SSB_NO | ARCH_CAP_MDS_NO | \ |
| 1617 | ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \ | 1617 | ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \ |
| 1618 | ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \ | 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 | static u64 kvm_get_arch_capabilities(void) | 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 | return data; | 1679 | return data; |
| 1677 | } | 1680 | } |
| 1678 | 1681 | ||
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <asm/unwind_hints.h> | 11 | #include <asm/unwind_hints.h> |
| 12 | #include <asm/percpu.h> | 12 | #include <asm/percpu.h> |
| 13 | #include <asm/frame.h> | 13 | #include <asm/frame.h> |
| 14 | #include <asm/nops.h> | ||
| 14 | 15 | ||
| 15 | .section .text.__x86.indirect_thunk | 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 | #ifdef CONFIG_RETHUNK | 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 | .section .text.__x86.return_thunk | 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 | * from re-poisioning the BTB prediction. | 184 | * from re-poisioning the BTB prediction. |
| 144 | */ | 185 | */ |
| 145 | .align 64 | 186 | .align 64 |
| 146 | .skip 64 - (__x86_return_thunk - zen_untrain_ret), 0xcc | 187 | .skip 64 - (__ret - zen_untrain_ret), 0xcc |
| 147 | SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) | 188 | SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) |
| 148 | ANNOTATE_NOENDBR | 189 | ANNOTATE_NOENDBR |
| 149 | /* | 190 | /* |
| @@ -175,10 +216,10 @@ SYM_START(zen_untrain_ret, SYM_L_GLOBAL, SYM_A_NONE) · 25 unmodified lines | |||
| 175 | * evicted, __x86_return_thunk will suffer Straight Line Speculation | 216 | * evicted, __x86_return_thunk will suffer Straight Line Speculation |
| 176 | * which will be contained safely by the INT3. | 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 | ret | 220 | ret |
| 180 | int3 | 221 | int3 |
| 181 | SYM_CODE_END(__x86_return_thunk) | 222 | SYM_CODE_END(__ret) |
| 182 | 223 | ||
| 183 | /* | 224 | /* |
| 184 | * Ensure the TEST decoding / BTB invalidation is complete. | 225 | * Ensure the TEST decoding / BTB invalidation is complete. |
| @@ -189,11 +230,45 @@ SYM_CODE_END(__x86_return_thunk) · 4 unmodified lines | |||
| 189 | * Jump back and execute the RET in the middle of the TEST instruction. | 230 | * Jump back and execute the RET in the middle of the TEST instruction. |
| 190 | * INT3 is for SLS protection. | 231 | * INT3 is for SLS protection. |
| 191 | */ | 232 | */ |
| 192 | jmp __x86_return_thunk | 233 | jmp __ret |
| 193 | int3 | 234 | int3 |
| 194 | SYM_FUNC_END(zen_untrain_ret) | 235 | SYM_FUNC_END(zen_untrain_ret) |
| 195 | __EXPORT_THUNK(zen_untrain_ret) | 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 | EXPORT_SYMBOL(__x86_return_thunk) | 272 | EXPORT_SYMBOL(__x86_return_thunk) |
| 198 | 273 | ||
| 199 | #endif /* CONFIG_RETHUNK */ | 274 | #endif /* CONFIG_RETHUNK */ |
| @@ -722,14 +722,9 @@ void submit_bio_noacct(struct bio *bio) · 721 unmodified lines | |||
| 722 | struct block_device *bdev = bio->bi_bdev; | 722 | struct block_device *bdev = bio->bi_bdev; |
| 723 | struct request_queue *q = bdev_get_queue(bdev); | 723 | struct request_queue *q = bdev_get_queue(bdev); |
| 724 | blk_status_t status = BLK_STS_IOERR; | 724 | blk_status_t status = BLK_STS_IOERR; |
| 725 | struct blk_plug *plug; | ||
| 726 | 725 | ||
| 727 | might_sleep(); | 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 | * For a REQ_NOWAIT based request, return -EOPNOTSUPP | 729 | * For a REQ_NOWAIT based request, return -EOPNOTSUPP |
| 735 | * if queue does not support NOWAIT. | 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 | plug->rq_count = 0; | 1054 | plug->rq_count = 0; |
| 1060 | plug->multiple_queues = false; | 1055 | plug->multiple_queues = false; |
| 1061 | plug->has_elevator = false; | 1056 | plug->has_elevator = false; |
| 1062 | plug->nowait = false; | ||
| 1063 | INIT_LIST_HEAD(&plug->cb_list); | 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 | if (qos[QOS_MIN] > qos[QOS_MAX]) | 3301 | if (qos[QOS_MIN] > qos[QOS_MAX]) |
| 3302 | goto einval; | 3302 | goto einval; |
| 3303 | 3303 | ||
| 3304 | if (enable) { | 3304 | if (enable && !ioc->enabled) { |
| 3305 | blk_stat_enable_accounting(disk->queue); | 3305 | blk_stat_enable_accounting(disk->queue); |
| 3306 | blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); | 3306 | blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); |
| 3307 | ioc->enabled = true; | 3307 | ioc->enabled = true; |
| 3308 | } else { | 3308 | } else if (!enable && ioc->enabled) { |
| 3309 | blk_stat_disable_accounting(disk->queue); | ||
| 3309 | blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); | 3310 | blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue); |
| 3310 | ioc->enabled = false; | 3311 | ioc->enabled = false; |
| 3311 | } | 3312 | } |
| @@ -358,13 +358,14 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb, · 357 unmodified lines | |||
| 358 | task_io_account_write(bio->bi_iter.bi_size); | 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 | if (iocb->ki_flags & IOCB_HIPRI) { | 364 | if (iocb->ki_flags & IOCB_HIPRI) { |
| 362 | bio->bi_opf |= REQ_POLLED | REQ_NOWAIT; | 365 | bio->bi_opf |= REQ_POLLED; |
| 363 | submit_bio(bio); | 366 | submit_bio(bio); |
| 364 | WRITE_ONCE(iocb->private, bio); | 367 | WRITE_ONCE(iocb->private, bio); |
| 365 | } else { | 368 | } else { |
| 366 | if (iocb->ki_flags & IOCB_NOWAIT) | ||
| 367 | bio->bi_opf |= REQ_NOWAIT; | ||
| 368 | submit_bio(bio); | 369 | submit_bio(bio); |
| 369 | } | 370 | } |
| 370 | return -EIOCBQUEUED; | 371 | return -EIOCBQUEUED; |
| @@ -173,6 +173,9 @@ static void internal_free_pages_locked(struct ivpu_bo *bo) · 172 unmodified lines | |||
| 173 | { | 173 | { |
| 174 | unsigned int i, npages = bo->base.size >> PAGE_SHIFT; | 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 | for (i = 0; i < npages; i++) | 179 | for (i = 0; i < npages; i++) |
| 177 | put_page(bo->pages[i]); | 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 | if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED) | 590 | if (ivpu_bo_cache_mode(bo) != DRM_IVPU_BO_CACHED) |
| 588 | drm_clflush_pages(bo->pages, bo->base.size >> PAGE_SHIFT); | 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 | prot = ivpu_bo_pgprot(bo, PAGE_KERNEL); | 598 | prot = ivpu_bo_pgprot(bo, PAGE_KERNEL); |
| 591 | bo->kvaddr = vmap(bo->pages, bo->base.size >> PAGE_SHIFT, VM_MAP, prot); | 599 | bo->kvaddr = vmap(bo->pages, bo->base.size >> PAGE_SHIFT, VM_MAP, prot); |
| 592 | if (!bo->kvaddr) { | 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 | static const struct dmi_system_id lg_laptop[] = { | 512 | static const struct dmi_system_id lg_laptop[] = { |
| 474 | { | 513 | { |
| 475 | .ident = "LG Electronics 17U70P", | 514 | .ident = "LG Electronics 17U70P", |
| @@ -493,6 +532,9 @@ struct irq_override_cmp { · 17 unmodified lines | |||
| 493 | static const struct irq_override_cmp override_table[] = { | 532 | static const struct irq_override_cmp override_table[] = { |
| 494 | { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, | 533 | { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, |
| 495 | { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, | 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 | { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, | 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 | return entry->override; | 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 | return true; | 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 | {"BSG1160", }, | 1714 | {"BSG1160", }, |
| 1715 | {"BSG2150", }, | 1715 | {"BSG2150", }, |
| 1716 | {"CSC3551", }, | 1716 | {"CSC3551", }, |
| 1717 | {"CSC3556", }, | ||
| 1717 | {"INT33FE", }, | 1718 | {"INT33FE", }, |
| 1718 | {"INT3515", }, | 1719 | {"INT3515", }, |
| 1719 | /* Non-conforming _HID for Cirrus Logic already released */ | 1720 | /* Non-conforming _HID for Cirrus Logic already released */ |
| @@ -6617,6 +6617,7 @@ err_init_binder_device_failed: · 6616 unmodified lines | |||
| 6617 | 6617 | ||
| 6618 | err_alloc_device_names_failed: | 6618 | err_alloc_device_names_failed: |
| 6619 | debugfs_remove_recursive(binder_debugfs_dir_entry_root); | 6619 | debugfs_remove_recursive(binder_debugfs_dir_entry_root); |
| 6620 | binder_alloc_shrinker_exit(); | ||
| 6620 | 6621 | ||
| 6621 | return ret; | 6622 | return ret; |
| 6622 | } | 6623 | } |
| @@ -1087,6 +1087,12 @@ int binder_alloc_shrinker_init(void) · 1086 unmodified lines | |||
| 1087 | return ret; | 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 | * check_buffer() - verify that buffer/offset is safe to access | 1097 | * check_buffer() - verify that buffer/offset is safe to access |
| 1092 | * @alloc: binder_alloc for this proc | 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 | int pid); | 129 | int pid); |
| 130 | extern void binder_alloc_init(struct binder_alloc *alloc); | 130 | extern void binder_alloc_init(struct binder_alloc *alloc); |
| 131 | extern int binder_alloc_shrinker_init(void); | 131 | extern int binder_alloc_shrinker_init(void); |
| 132 | extern void binder_alloc_shrinker_exit(void); | ||
| 132 | extern void binder_alloc_vma_close(struct binder_alloc *alloc); | 133 | extern void binder_alloc_vma_close(struct binder_alloc *alloc); |
| 133 | extern struct binder_buffer * | 134 | extern struct binder_buffer * |
| 134 | binder_alloc_prepare_to_free(struct binder_alloc *alloc, | 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 | } else { | 1101 | } else { |
| 1102 | sdev->sector_size = ata_id_logical_sector_size(dev->id); | 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 | sdev->manage_start_stop = 1; | 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 | #ifdef CONFIG_GENERIC_CPU_VULNERABILITIES | 511 | #ifdef CONFIG_GENERIC_CPU_VULNERABILITIES |
| 512 | 512 | static ssize_t cpu_show_not_affected(struct device *dev, | |
| 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, | ||
| 563 | struct device_attribute *attr, char *buf) | 513 | struct device_attribute *attr, char *buf) |
| 564 | { | 514 | { |
| 565 | return sysfs_emit(buf, "Not affected\n"); | 515 | return sysfs_emit(buf, "Not affected\n"); |
| 566 | } | 516 | } |
| 567 | 517 | ||
| 568 | ssize_t __weak cpu_show_mmio_stale_data(struct device *dev, | 518 | #define CPU_SHOW_VULN_FALLBACK(func) \ |
| 569 | struct device_attribute *attr, char *buf) | 519 | ssize_t cpu_show_##func(struct device *, \ |
| 570 | { | 520 | struct device_attribute *, char *) \ |
| 571 | return sysfs_emit(buf, "Not affected\n"); | 521 | __attribute__((weak, alias("cpu_show_not_affected"))) |
| 572 | } | 522 | |
| 573 | 523 | CPU_SHOW_VULN_FALLBACK(meltdown); | |
| 574 | ssize_t __weak cpu_show_retbleed(struct device *dev, | 524 | CPU_SHOW_VULN_FALLBACK(spectre_v1); |
| 575 | struct device_attribute *attr, char *buf) | 525 | CPU_SHOW_VULN_FALLBACK(spectre_v2); |
| 576 | { | 526 | CPU_SHOW_VULN_FALLBACK(spec_store_bypass); |
| 577 | return sysfs_emit(buf, "Not affected\n"); | 527 | CPU_SHOW_VULN_FALLBACK(l1tf); |
| 578 | } | 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 | static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); | 537 | static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); |
| 581 | static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); | 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 | static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL); | 545 | static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL); |
| 589 | static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL); | 546 | static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL); |
| 590 | static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL); | 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 | static struct attribute *cpu_root_vulnerabilities_attrs[] = { | 551 | static struct attribute *cpu_root_vulnerabilities_attrs[] = { |
| 593 | &dev_attr_meltdown.attr, | 552 | &dev_attr_meltdown.attr, |
| @@ -601,6 +560,8 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = { · 7 unmodified lines | |||
| 601 | &dev_attr_srbds.attr, | 560 | &dev_attr_srbds.attr, |
| 602 | &dev_attr_mmio_stale_data.attr, | 561 | &dev_attr_mmio_stale_data.attr, |
| 603 | &dev_attr_retbleed.attr, | 562 | &dev_attr_retbleed.attr, |
| 563 | &dev_attr_spec_rstack_overflow.attr, | ||
| 564 | &dev_attr_gather_data_sampling.attr, | ||
| 604 | NULL | 565 | NULL |
| 605 | }; | 566 | }; |
| 606 | 567 | ||
| @@ -3675,7 +3675,7 @@ static int rbd_lock(struct rbd_device *rbd_dev) · 3674 unmodified lines | |||
| 3675 | ret = ceph_cls_lock(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc, | 3675 | ret = ceph_cls_lock(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc, |
| 3676 | RBD_LOCK_NAME, CEPH_CLS_LOCK_EXCLUSIVE, cookie, | 3676 | RBD_LOCK_NAME, CEPH_CLS_LOCK_EXCLUSIVE, cookie, |
| 3677 | RBD_LOCK_TAG, "", 0); | 3677 | RBD_LOCK_TAG, "", 0); |
| 3678 | if (ret) | 3678 | if (ret && ret != -EEXIST) |
| 3679 | return ret; | 3679 | return ret; |
| 3680 | 3680 | ||
| 3681 | __rbd_lock(rbd_dev, cookie); | 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 | &rbd_dev->header_oloc, RBD_LOCK_NAME, | 3878 | &rbd_dev->header_oloc, RBD_LOCK_NAME, |
| 3879 | &lock_type, &lock_tag, &lockers, &num_lockers); | 3879 | &lock_type, &lock_tag, &lockers, &num_lockers); |
| 3880 | if (ret) { | 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 | return ERR_PTR(ret); | 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 | ret = ceph_osdc_list_watchers(osdc, &rbd_dev->header_oid, | 3940 | ret = ceph_osdc_list_watchers(osdc, &rbd_dev->header_oid, |
| 3941 | &rbd_dev->header_oloc, &watchers, | 3941 | &rbd_dev->header_oloc, &watchers, |
| 3942 | &num_watchers); | 3942 | &num_watchers); |
| 3943 | if (ret) | 3943 | if (ret) { |
| 3944 | rbd_warn(rbd_dev, "failed to get watchers: %d", ret); | ||
| 3944 | return ret; | 3945 | return ret; |
| 3946 | } | ||
| 3945 | 3947 | ||
| 3946 | sscanf(locker->id.cookie, RBD_LOCK_COOKIE_PREFIX " %llu", &cookie); | 3948 | sscanf(locker->id.cookie, RBD_LOCK_COOKIE_PREFIX " %llu", &cookie); |
| 3947 | for (i = 0; i < num_watchers; i++) { | 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 | locker = refreshed_locker = NULL; | 3987 | locker = refreshed_locker = NULL; |
| 3986 | 3988 | ||
| 3987 | ret = rbd_lock(rbd_dev); | 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 | goto out; | 3994 | goto out; |
| 3995 | } | ||
| 3990 | 3996 | ||
| 3991 | /* determine if the current lock holder is still alive */ | 3997 | /* determine if the current lock holder is still alive */ |
| 3992 | locker = get_lock_owner_info(rbd_dev); | 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 | ret = rbd_try_lock(rbd_dev); | 4096 | ret = rbd_try_lock(rbd_dev); |
| 4091 | if (ret < 0) { | 4097 | if (ret < 0) { |
| 4092 | rbd_warn(rbd_dev, "failed to lock header: %d", ret); | 4098 | rbd_warn(rbd_dev, "failed to acquire lock: %d", ret); |
| 4093 | if (ret == -EBLOCKLISTED) | 4099 | goto out; |
| 4094 | goto out; | ||
| 4095 | |||
| 4096 | ret = 1; /* request lock anyway */ | ||
| 4097 | } | 4100 | } |
| 4098 | if (ret > 0) { | 4101 | if (ret > 0) { |
| 4099 | up_write(&rbd_dev->lock_rwsem); | 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 | cancel_delayed_work_sync(&rbd_dev->lock_dwork); | 6630 | cancel_delayed_work_sync(&rbd_dev->lock_dwork); |
| 6628 | if (!ret) | 6631 | if (!ret) |
| 6629 | ret = -ETIMEDOUT; | 6632 | ret = -ETIMEDOUT; |
| 6630 | } | ||
| 6631 | 6633 | ||
| 6632 | if (ret) { | 6634 | rbd_warn(rbd_dev, "failed to acquire lock: %ld", ret); |
| 6633 | rbd_warn(rbd_dev, "failed to acquire exclusive lock: %ld", ret); | ||
| 6634 | return ret; | ||
| 6635 | } | 6635 | } |
| 6636 | if (ret) | ||
| 6637 | return ret; | ||
| 6636 | 6638 | ||
| 6637 | /* | 6639 | /* |
| 6638 | * The lock may have been released by now, unless automatic lock | 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 | static void zram_bio_read(struct zram *zram, struct bio *bio) | 1871 | static void zram_bio_read(struct zram *zram, struct bio *bio) |
| 1872 | { | 1872 | { |
| 1873 | struct bvec_iter iter; | 1873 | unsigned long start_time = bio_start_io_acct(bio); |
| 1874 | struct bio_vec bv; | 1874 | struct bvec_iter iter = bio->bi_iter; |
| 1875 | unsigned long start_time; | ||
| 1876 | 1875 | ||
| 1877 | start_time = bio_start_io_acct(bio); | 1876 | do { |
| 1878 | bio_for_each_segment(bv, bio, iter) { | ||
| 1879 | u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; | 1877 | u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; |
| 1880 | u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) << | 1878 | u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) << |
| 1881 | SECTOR_SHIFT; | 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 | if (zram_bvec_read(zram, &bv, index, offset, bio) < 0) { | 1884 | if (zram_bvec_read(zram, &bv, index, offset, bio) < 0) { |
| 1884 | atomic64_inc(&zram->stats.failed_reads); | 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 | zram_slot_lock(zram, index); | 1891 | zram_slot_lock(zram, index); |
| 1891 | zram_accessed(zram, index); | 1892 | zram_accessed(zram, index); |
| 1892 | zram_slot_unlock(zram, index); | 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 | bio_end_io_acct(bio, start_time); | 1898 | bio_end_io_acct(bio, start_time); |
| 1895 | bio_endio(bio); | 1899 | bio_endio(bio); |
| 1896 | } | 1900 | } |
| 1897 | 1901 | ||
| 1898 | static void zram_bio_write(struct zram *zram, struct bio *bio) | 1902 | static void zram_bio_write(struct zram *zram, struct bio *bio) |
| 1899 | { | 1903 | { |
| 1900 | struct bvec_iter iter; | 1904 | unsigned long start_time = bio_start_io_acct(bio); |
| 1901 | struct bio_vec bv; | 1905 | struct bvec_iter iter = bio->bi_iter; |
| 1902 | unsigned long start_time; | ||
| 1903 | 1906 | ||
| 1904 | start_time = bio_start_io_acct(bio); | 1907 | do { |
| 1905 | bio_for_each_segment(bv, bio, iter) { | ||
| 1906 | u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; | 1908 | u32 index = iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; |
| 1907 | u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) << | 1909 | u32 offset = (iter.bi_sector & (SECTORS_PER_PAGE - 1)) << |
| 1908 | SECTOR_SHIFT; | 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 | if (zram_bvec_write(zram, &bv, index, offset, bio) < 0) { | 1915 | if (zram_bvec_write(zram, &bv, index, offset, bio) < 0) { |
| 1911 | atomic64_inc(&zram->stats.failed_writes); | 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 | zram_slot_lock(zram, index); | 1921 | zram_slot_lock(zram, index); |
| 1917 | zram_accessed(zram, index); | 1922 | zram_accessed(zram, index); |
| 1918 | zram_slot_unlock(zram, index); | 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 | bio_end_io_acct(bio, start_time); | 1928 | bio_end_io_acct(bio, start_time); |
| 1921 | bio_endio(bio); | 1929 | bio_endio(bio); |
| 1922 | } | 1930 | } |
| @@ -510,70 +510,6 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip) · 509 unmodified lines | |||
| 510 | return 0; | 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 | static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) | 513 | static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) |
| 578 | { | 514 | { |
| 579 | struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng); | 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 | return tpm_get_random(chip, data, max); | 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 | static int tpm_add_hwrng(struct tpm_chip *chip) | 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) || | 537 | if (!tpm_is_hwrng_enabled(chip)) |
| 591 | tpm_amd_is_rng_defective(chip)) | ||
| 592 | return 0; | 538 | return 0; |
| 593 | 539 | ||
| 594 | snprintf(chip->hwrng_name, sizeof(chip->hwrng_name), | 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 | return 0; | 639 | return 0; |
| 694 | 640 | ||
| 695 | out_hwrng: | 641 | out_hwrng: |
| 696 | if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip)) | 642 | if (tpm_is_hwrng_enabled(chip)) |
| 697 | hwrng_unregister(&chip->hwrng); | 643 | hwrng_unregister(&chip->hwrng); |
| 698 | out_ppi: | 644 | out_ppi: |
| 699 | tpm_bios_log_teardown(chip); | 645 | tpm_bios_log_teardown(chip); |
| @@ -718,8 +664,7 @@ EXPORT_SYMBOL_GPL(tpm_chip_register); · 18 unmodified lines | |||
| 718 | void tpm_chip_unregister(struct tpm_chip *chip) | 664 | void tpm_chip_unregister(struct tpm_chip *chip) |
| 719 | { | 665 | { |
| 720 | tpm_del_legacy_sysfs(chip); | 666 | tpm_del_legacy_sysfs(chip); |
| 721 | if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip) && | 667 | if (tpm_is_hwrng_enabled(chip)) |
| 722 | !tpm_amd_is_rng_defective(chip)) | ||
| 723 | hwrng_unregister(&chip->hwrng); | 668 | hwrng_unregister(&chip->hwrng); |
| 724 | tpm_bios_log_teardown(chip); | 669 | tpm_bios_log_teardown(chip); |
| 725 | if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip)) | 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 | return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; | 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 | static const struct tpm_class_ops tpm_crb = { | 488 | static const struct tpm_class_ops tpm_crb = { |
| 467 | .flags = TPM_OPS_AUTO_STARTUP, | 489 | .flags = TPM_OPS_AUTO_STARTUP, |
| 468 | .status = crb_status, | 490 | .status = crb_status, |
| @@ -800,6 +822,14 @@ static int crb_acpi_add(struct acpi_device *device) · 331 unmodified lines | |||
| 800 | chip->acpi_dev_handle = device->handle; | 822 | chip->acpi_dev_handle = device->handle; |
| 801 | chip->flags = TPM_CHIP_FLAG_TPM2; | 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 | rc = tpm_chip_register(chip); | 833 | rc = tpm_chip_register(chip); |
| 804 | 834 | ||
| 805 | out: | 835 | out: |
| @@ -89,7 +89,7 @@ static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr) · 88 unmodified lines | |||
| 89 | tpm_tis_flush(iobase); | 89 | tpm_tis_flush(iobase); |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | static int interrupts = -1; | 92 | static int interrupts; |
| 93 | module_param(interrupts, int, 0444); | 93 | module_param(interrupts, int, 0444); |
| 94 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | 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 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L590"), | 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 | .callback = tpm_tis_disable_irq, | 182 | .callback = tpm_tis_disable_irq, |
| 167 | .ident = "UPX-TGL", | 183 | .ident = "UPX-TGL", |
| 168 | .matches = { | 184 | .matches = { |
| 169 | DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), | 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 | config COMMON_CLK_FIXED_MMIO | 444 | config COMMON_CLK_FIXED_MMIO |
| 445 | bool "Clock driver for Memory Mapped Fixed values" | 445 | bool "Clock driver for Memory Mapped Fixed values" |
| 446 | depends on COMMON_CLK && OF | 446 | depends on COMMON_CLK && OF |
| 447 | depends on HAS_IOMEM | ||
| 447 | help | 448 | help |
| 448 | Support for Memory Mapped IO Fixed clocks | 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 | anatop_base = devm_of_iomap(dev, np, 0, NULL); | 291 | anatop_base = devm_of_iomap(dev, np, 0, NULL); |
| 292 | of_node_put(np); | 292 | of_node_put(np); |
| 293 | if (WARN_ON(IS_ERR(anatop_base))) { | 293 | if (WARN_ON(IS_ERR(anatop_base))) { |
| 294 | ret = PTR_ERR(base); | 294 | ret = PTR_ERR(anatop_base); |
| 295 | goto unregister_hws; | 295 | goto unregister_hws; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| @@ -328,6 +328,14 @@ static const char * const atb_parents[] = { · 327 unmodified lines | |||
| 328 | "syspll_d5" | 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 | static const char * const dpi0_parents[] = { | 339 | static const char * const dpi0_parents[] = { |
| 332 | "clk26m", | 340 | "clk26m", |
| 333 | "tvdpll_d2", | 341 | "tvdpll_d2", |
| @@ -507,6 +515,9 @@ static const struct mtk_mux top_muxes[] = { · 173 unmodified lines | |||
| 507 | /* CLK_CFG_6 */ | 515 | /* CLK_CFG_6 */ |
| 508 | MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_ATB, "atb_sel", | 516 | MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_ATB, "atb_sel", |
| 509 | atb_parents, 0xa0, 0xa4, 0xa8, 0, 2, 7, 0x004, 24), | 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 | MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DPI0, "dpi0_sel", | 521 | MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DPI0, "dpi0_sel", |
| 511 | dpi0_parents, 0xa0, 0xa4, 0xa8, 16, 4, 23, 0x004, 26), | 522 | dpi0_parents, 0xa0, 0xa4, 0xa8, 16, 4, 23, 0x004, 26), |
| 512 | MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SCAM, "scam_sel", | 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 | GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, \ | 684 | GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, \ |
| 674 | &mtk_clk_gate_ops_setclr) | 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 | #define GATE_INFRA3(_id, _name, _parent, _shift) \ | 691 | #define GATE_INFRA3(_id, _name, _parent, _shift) \ |
| 677 | GATE_MTK(_id, _name, _parent, &infra3_cg_regs, _shift, \ | 692 | GATE_MTK(_id, _name, _parent, &infra3_cg_regs, _shift, \ |
| 678 | &mtk_clk_gate_ops_setclr) | 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 | static const struct mtk_gate infra_clks[] = { | 699 | static const struct mtk_gate infra_clks[] = { |
| 681 | /* INFRA0 */ | 700 | /* INFRA0 */ |
| 682 | GATE_INFRA0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "axi_sel", 0), | 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 | GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick", "fufs_sel", 12), | 767 | GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick", "fufs_sel", 12), |
| 749 | GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_BCLK, "infra_ufs_mp_sap_bck", "fufs_sel", 13), | 768 | GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_BCLK, "infra_ufs_mp_sap_bck", "fufs_sel", 13), |
| 750 | GATE_INFRA2(CLK_INFRA_MD32_BCLK, "infra_md32_bclk", "axi_sel", 14), | 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 | GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, "infra_unipro_mbist", "axi_sel", 16), | 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 | GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5", "i2c_sel", 18), | 775 | GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5", "i2c_sel", 18), |
| 753 | GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter", "i2c_sel", 19), | 776 | GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter", "i2c_sel", 19), |
| 754 | GATE_INFRA2(CLK_INFRA_I2C5_IMM, "infra_i2c5_imm", "i2c_sel", 20), | 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 | GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self", "msdc50_0_sel", 0), | 789 | GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self", "msdc50_0_sel", 0), |
| 767 | GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self", "msdc50_0_sel", 1), | 790 | GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self", "msdc50_0_sel", 1), |
| 768 | GATE_INFRA3(CLK_INFRA_MSDC2_SELF, "infra_msdc2_self", "msdc50_0_sel", 2), | 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 | GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", "axi_sel", 5), | 796 | GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", "axi_sel", 5), |
| 770 | GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", "i2c_sel", 6), | 797 | GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", "i2c_sel", 6), |
| 771 | GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0", "msdc50_hclk_sel", 7), | 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 | * 3. enable the lock detect module | 367 | * 3. enable the lock detect module |
| 368 | */ | 368 | */ |
| 369 | if (MESON_PARM_APPLICABLE(&pll->current_en)) { | 369 | if (MESON_PARM_APPLICABLE(&pll->current_en)) { |
| 370 | usleep_range(10, 20); | 370 | udelay(10); |
| 371 | meson_parm_write(clk->map, &pll->current_en, 1); | 371 | meson_parm_write(clk->map, &pll->current_en, 1); |
| 372 | usleep_range(40, 50); | 372 | udelay(40); |
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | if (MESON_PARM_APPLICABLE(&pll->l_detect)) { | 375 | if (MESON_PARM_APPLICABLE(&pll->l_detect)) { |
| @@ -3,13 +3,6 @@ · 2 unmodified lines | |||
| 3 | # Counter devices | 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 | config I8254 | 6 | config I8254 |
| 14 | tristate | 7 | tristate |
| 15 | select COUNTER | 8 | select COUNTER |
| @@ -25,6 +18,13 @@ config I8254 · 9 unmodified lines | |||
| 25 | 18 | ||
| 26 | If built as a module its name will be i8254. | 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 | if COUNTER | 28 | if COUNTER |
| 29 | 29 | ||
| 30 | config 104_QUAD_8 | 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 | return 0; | 1012 | return 0; |
| 1013 | } | 1013 | } |
| 1014 | 1014 | ||
| 1015 | static ssize_t show_status(struct kobject *kobj, | 1015 | static ssize_t status_show(struct device *dev, |
| 1016 | struct kobj_attribute *attr, char *buf) | 1016 | struct device_attribute *attr, char *buf) |
| 1017 | { | 1017 | { |
| 1018 | ssize_t ret; | 1018 | ssize_t ret; |
| 1019 | 1019 | ||
| @@ -1024,7 +1024,7 @@ static ssize_t show_status(struct kobject *kobj, · 4 unmodified lines | |||
| 1024 | return ret; | 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 | const char *buf, size_t count) | 1028 | const char *buf, size_t count) |
| 1029 | { | 1029 | { |
| 1030 | char *p = memchr(buf, '\n', count); | 1030 | char *p = memchr(buf, '\n', count); |
| @@ -1043,7 +1043,7 @@ cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq); · 12 unmodified lines | |||
| 1043 | cpufreq_freq_attr_ro(amd_pstate_highest_perf); | 1043 | cpufreq_freq_attr_ro(amd_pstate_highest_perf); |
| 1044 | cpufreq_freq_attr_rw(energy_performance_preference); | 1044 | cpufreq_freq_attr_rw(energy_performance_preference); |
| 1045 | cpufreq_freq_attr_ro(energy_performance_available_preferences); | 1045 | cpufreq_freq_attr_ro(energy_performance_available_preferences); |
| 1046 | define_one_global_rw(status); | 1046 | static DEVICE_ATTR_RW(status); |
| 1047 | 1047 | ||
| 1048 | static struct freq_attr *amd_pstate_attr[] = { | 1048 | static struct freq_attr *amd_pstate_attr[] = { |
| 1049 | &amd_pstate_max_freq, | 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 | static struct attribute *pstate_global_attributes[] = { | 1064 | static struct attribute *pstate_global_attributes[] = { |
| 1065 | &status.attr, | 1065 | &dev_attr_status.attr, |
| 1066 | NULL | 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 | static void psci_cpuidle_domain_sync_state(struct device *dev) | 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 | struct device_node *np = pdev->dev.of_node; | 139 | struct device_node *np = pdev->dev.of_node; |
| 154 | struct device_node *node; | 140 | struct device_node *node; |
| 155 | bool use_osi; | 141 | bool use_osi = psci_has_osi_support(); |
| 156 | int ret = 0, pd_count = 0; | 142 | int ret = 0, pd_count = 0; |
| 157 | 143 | ||
| 158 | if (!np) | 144 | if (!np) |
| 159 | return -ENODEV; | 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 | * Parse child nodes for the "#power-domain-cells" property and | 148 | * Parse child nodes for the "#power-domain-cells" property and |
| 166 | * initialize a genpd/genpd-of-provider pair when it's found. | 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 | continue; | 153 | continue; |
| 171 | 154 | ||
| 172 | ret = psci_pd_init(node, use_osi); | 155 | ret = psci_pd_init(node, use_osi); |
| 173 | if (ret) | 156 | if (ret) { |
| 174 | goto put_node; | 157 | of_node_put(node); |
| 158 | goto exit; | ||
| 159 | } | ||
| 175 | 160 | ||
| 176 | pd_count++; | 161 | pd_count++; |
| 177 | } | 162 | } |
| 178 | 163 | ||
| 179 | /* Bail out if not using the hierarchical CPU topology. */ | 164 | /* Bail out if not using the hierarchical CPU topology. */ |
| 180 | if (!pd_count) | 165 | if (!pd_count) |
| 181 | goto no_pd; | 166 | return 0; |
| 182 | 167 | ||
| 183 | /* Link genpd masters/subdomains to model the CPU topology. */ | 168 | /* Link genpd masters/subdomains to model the CPU topology. */ |
| 184 | ret = dt_idle_pd_init_topology(np); | 169 | ret = dt_idle_pd_init_topology(np); |
| 185 | if (ret) | 170 | if (ret) |
| 186 | goto remove_pd; | 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 | pr_info("Initialized CPU PM domain topology using %s mode\n", | 178 | pr_info("Initialized CPU PM domain topology using %s mode\n", |
| 189 | use_osi ? "OSI" : "PC"); | 179 | use_osi ? "OSI" : "PC"); |
| 190 | return 0; | 180 | return 0; |
| 191 | 181 | ||
| 192 | put_node: | ||
| 193 | of_node_put(node); | ||
| 194 | remove_pd: | 182 | remove_pd: |
| 183 | dt_idle_pd_remove_topology(np); | ||
| 195 | psci_pd_remove(); | 184 | psci_pd_remove(); |
| 185 | exit: | ||
| 196 | pr_err("failed to create CPU PM domains ret=%d\n", ret); | 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 | return ret; | 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 | return 0; | 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 | struct device *dt_idle_attach_cpu(int cpu, const char *name) | 179 | struct device *dt_idle_attach_cpu(int cpu, const char *name) |
| 156 | { | 180 | { |
| 157 | struct device *dev; | 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 | int dt_idle_pd_init_topology(struct device_node *np); | 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 | struct device *dt_idle_attach_cpu(int cpu, const char *name); | 19 | struct device *dt_idle_attach_cpu(int cpu, const char *name); |
| 18 | 20 | ||
| 19 | void dt_idle_detach_cpu(struct device *dev); | 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 | return 0; | 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 | static inline struct device *dt_idle_attach_cpu(int cpu, const char *name) | 46 | static inline struct device *dt_idle_attach_cpu(int cpu, const char *name) |
| 40 | { | 47 | { |
| 41 | return NULL; | 48 | return NULL; |
| @@ -121,6 +121,45 @@ static bool cxl_is_security_command(u16 opcode) · 120 unmodified lines | |||
| 121 | return false; | 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 | static bool cxl_is_poison_command(u16 opcode) | 163 | static bool cxl_is_poison_command(u16 opcode) |
| 125 | { | 164 | { |
| 126 | #define CXL_MBOX_OP_POISON_CMDS 0x43 | 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 | u16 opcode = le16_to_cpu(cel_entry[i].opcode); | 716 | u16 opcode = le16_to_cpu(cel_entry[i].opcode); |
| 678 | struct cxl_mem_command *cmd = cxl_mem_find_command(opcode); | 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 | dev_dbg(dev, | 721 | dev_dbg(dev, |
| 682 | "Opcode 0x%04x unsupported by driver\n", opcode); | 722 | "Opcode 0x%04x unsupported by driver\n", opcode); |
| 683 | continue; | 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 | if (cxl_is_poison_command(opcode)) | 729 | if (cxl_is_poison_command(opcode)) |
| 690 | cxl_set_poison_cmd_enabled(&mds->poison, opcode); | 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 | dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode); | 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 | .attrs = cxl_memdev_pmem_attributes, | 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 | static struct attribute_group cxl_memdev_security_attribute_group = { | 498 | static struct attribute_group cxl_memdev_security_attribute_group = { |
| 481 | .name = "security", | 499 | .name = "security", |
| 482 | .attrs = cxl_memdev_security_attributes, | 500 | .attrs = cxl_memdev_security_attributes, |
| 501 | .is_visible = cxl_memdev_security_visible, | ||
| 483 | }; | 502 | }; |
| 484 | 503 | ||
| 485 | static const struct attribute_group *cxl_memdev_attribute_groups[] = { | 504 | static const struct attribute_group *cxl_memdev_attribute_groups[] = { |
| @@ -244,6 +244,19 @@ enum poison_cmd_enabled_bits { · 243 unmodified lines | |||
| 244 | CXL_POISON_ENABLED_MAX | 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 | * struct cxl_poison_state - Driver poison state info | 261 | * struct cxl_poison_state - Driver poison state info |
| 249 | * | 262 | * |
| @@ -346,6 +359,7 @@ struct cxl_fw_state { · 96 unmodified lines | |||
| 346 | * struct cxl_security_state - Device security state | 359 | * struct cxl_security_state - Device security state |
| 347 | * | 360 | * |
| 348 | * @state: state of last security operation | 361 | * @state: state of last security operation |
| 362 | * @enabled_cmds: All security commands enabled in the CEL | ||
| 349 | * @poll: polling for sanitization is enabled, device has no mbox irq support | 363 | * @poll: polling for sanitization is enabled, device has no mbox irq support |
| 350 | * @poll_tmo_secs: polling timeout | 364 | * @poll_tmo_secs: polling timeout |
| 351 | * @poll_dwork: polling work item | 365 | * @poll_dwork: polling work item |
| @@ -353,6 +367,7 @@ struct cxl_fw_state { · 1 unmodified line | |||
| 353 | */ | 367 | */ |
| 354 | struct cxl_security_state { | 368 | struct cxl_security_state { |
| 355 | unsigned long state; | 369 | unsigned long state; |
| 370 | DECLARE_BITMAP(enabled_cmds, CXL_SEC_ENABLED_MAX); | ||
| 356 | bool poll; | 371 | bool poll; |
| 357 | int poll_tmo_secs; | 372 | int poll_tmo_secs; |
| 358 | struct delayed_work poll_dwork; | 373 | struct delayed_work poll_dwork; |
| @@ -434,6 +449,7 @@ struct cxl_dev_state { · 75 unmodified lines | |||
| 434 | * @next_persistent_bytes: persistent capacity change pending device reset | 449 | * @next_persistent_bytes: persistent capacity change pending device reset |
| 435 | * @event: event log driver state | 450 | * @event: event log driver state |
| 436 | * @poison: poison driver state info | 451 | * @poison: poison driver state info |
| 452 | * @security: security driver state info | ||
| 437 | * @fw: firmware upload / activation state | 453 | * @fw: firmware upload / activation state |
| 438 | * @mbox_send: @dev specific transport for transmitting mailbox commands | 454 | * @mbox_send: @dev specific transport for transmitting mailbox commands |
| 439 | * | 455 | * |
| @@ -211,6 +211,7 @@ config FSL_DMA · 210 unmodified lines | |||
| 211 | config FSL_EDMA | 211 | config FSL_EDMA |
| 212 | tristate "Freescale eDMA engine support" | 212 | tristate "Freescale eDMA engine support" |
| 213 | depends on OF | 213 | depends on OF |
| 214 | depends on HAS_IOMEM | ||
| 214 | select DMA_ENGINE | 215 | select DMA_ENGINE |
| 215 | select DMA_VIRTUAL_CHANNELS | 216 | select DMA_VIRTUAL_CHANNELS |
| 216 | help | 217 | help |
| @@ -280,6 +281,7 @@ config IMX_SDMA · 63 unmodified lines | |||
| 280 | 281 | ||
| 281 | config INTEL_IDMA64 | 282 | config INTEL_IDMA64 |
| 282 | tristate "Intel integrated DMA 64-bit support" | 283 | tristate "Intel integrated DMA 64-bit support" |
| 284 | depends on HAS_IOMEM | ||
| 283 | select DMA_ENGINE | 285 | select DMA_ENGINE |
| 284 | select DMA_VIRTUAL_CHANNELS | 286 | select DMA_VIRTUAL_CHANNELS |
| 285 | help | 287 | help |
| @@ -384,9 +384,7 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq) · 383 unmodified lines | |||
| 384 | wq->threshold = 0; | 384 | wq->threshold = 0; |
| 385 | wq->priority = 0; | 385 | wq->priority = 0; |
| 386 | wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; | 386 | wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; |
| 387 | clear_bit(WQ_FLAG_DEDICATED, &wq->flags); | 387 | wq->flags = 0; |
| 388 | clear_bit(WQ_FLAG_BLOCK_ON_FAULT, &wq->flags); | ||
| 389 | clear_bit(WQ_FLAG_ATS_DISABLE, &wq->flags); | ||
| 390 | memset(wq->name, 0, WQ_NAME_SIZE); | 388 | memset(wq->name, 0, WQ_NAME_SIZE); |
| 391 | wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER; | 389 | wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER; |
| 392 | idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH); | 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 | return -EINVAL; | 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 | len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans; | 200 | len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans; |
| 195 | mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); | 201 | mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); |
| 196 | if (!mcf_edma) | 202 | if (!mcf_edma) |
| @@ -202,11 +208,6 @@ static int mcf_edma_probe(struct platform_device *pdev) · 5 unmodified lines | |||
| 202 | mcf_edma->drvdata = &mcf_data; | 208 | mcf_edma->drvdata = &mcf_data; |
| 203 | mcf_edma->big_endian = 1; | 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 | mutex_init(&mcf_edma->fsl_edma_mutex); | 211 | mutex_init(&mcf_edma->fsl_edma_mutex); |
| 211 | 212 | ||
| 212 | mcf_edma->membase = devm_platform_ioremap_resource(pdev, 0); | 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 | * @vc: wrapped virtual channel | 196 | * @vc: wrapped virtual channel |
| 197 | * @pchan: the physical channel utilized by this channel | 197 | * @pchan: the physical channel utilized by this channel |
| 198 | * @txd: active transaction on this channel | 198 | * @txd: active transaction on this channel |
| @@ -403,6 +403,12 @@ enum desc_status { · 402 unmodified lines | |||
| 403 | * of a channel can be BUSY at any time. | 403 | * of a channel can be BUSY at any time. |
| 404 | */ | 404 | */ |
| 405 | BUSY, | 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 | * Sitting on the channel work_list but xfer done | 413 | * Sitting on the channel work_list but xfer done |
| 408 | * by PL330 core | 414 | * by PL330 core |
| @@ -2041,7 +2047,7 @@ static inline void fill_queue(struct dma_pl330_chan *pch) · 1632 unmodified lines | |||
| 2041 | list_for_each_entry(desc, &pch->work_list, node) { | 2047 | list_for_each_entry(desc, &pch->work_list, node) { |
| 2042 | 2048 | ||
| 2043 | /* If already submitted */ | 2049 | /* If already submitted */ |
| 2044 | if (desc->status == BUSY) | 2050 | if (desc->status == BUSY || desc->status == PAUSED) |
| 2045 | continue; | 2051 | continue; |
| 2046 | 2052 | ||
| 2047 | ret = pl330_submit_req(pch->thread, desc); | 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 | struct dma_pl330_chan *pch = to_pchan(chan); | 2333 | struct dma_pl330_chan *pch = to_pchan(chan); |
| 2328 | struct pl330_dmac *pl330 = pch->dmac; | 2334 | struct pl330_dmac *pl330 = pch->dmac; |
| 2335 | struct dma_pl330_desc *desc; | ||
| 2329 | unsigned long flags; | 2336 | unsigned long flags; |
| 2330 | 2337 | ||
| 2331 | pm_runtime_get_sync(pl330->ddma.dev); | 2338 | pm_runtime_get_sync(pl330->ddma.dev); |
| @@ -2335,6 +2342,10 @@ static int pl330_pause(struct dma_chan *chan) · 3 unmodified lines | |||
| 2335 | _stop(pch->thread); | 2342 | _stop(pch->thread); |
| 2336 | spin_unlock(&pl330->lock); | 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 | spin_unlock_irqrestore(&pch->lock, flags); | 2349 | spin_unlock_irqrestore(&pch->lock, flags); |
| 2339 | pm_runtime_mark_last_busy(pl330->ddma.dev); | 2350 | pm_runtime_mark_last_busy(pl330->ddma.dev); |
| 2340 | pm_runtime_put_autosuspend(pl330->ddma.dev); | 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 | else if (running && desc == running) | 2436 | else if (running && desc == running) |
| 2426 | transferred = | 2437 | transferred = |
| 2427 | pl330_get_current_xferred_count(pch, desc); | 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 | * Busy but not running means either just enqueued, | 2441 | * Busy but not running means either just enqueued, |
| 2431 | * or finished and not yet marked done | 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 | case DONE: | 2453 | case DONE: |
| 2443 | ret = DMA_COMPLETE; | 2454 | ret = DMA_COMPLETE; |
| 2444 | break; | 2455 | break; |
| 2456 | case PAUSED: | ||
| 2457 | ret = DMA_PAUSED; | ||
| 2458 | break; | ||
| 2445 | case PREP: | 2459 | case PREP: |
| 2446 | case BUSY: | 2460 | case BUSY: |
| 2447 | ret = DMA_IN_PROGRESS; | 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 | val |= irq_start << shift; | 668 | val |= irq_start << shift; |
| 669 | irq_start++; | 669 | irq_start++; |
| 670 | irq_num--; | 670 | irq_num--; |
| 671 | if (!irq_num) | ||
| 672 | break; | ||
| 671 | } | 673 | } |
| 672 | 674 | ||
| 673 | /* write IRQ register */ | 675 | /* write IRQ register */ |
| @@ -715,7 +717,7 @@ static int xdma_irq_init(struct xdma_device *xdev) · 41 unmodified lines | |||
| 715 | ret = request_irq(irq, xdma_channel_isr, 0, | 717 | ret = request_irq(irq, xdma_channel_isr, 0, |
| 716 | "xdma-c2h-channel", &xdev->c2h_chans[j]); | 718 | "xdma-c2h-channel", &xdev->c2h_chans[j]); |
| 717 | if (ret) { | 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 | j, irq, ret); | 721 | j, irq, ret); |
| 720 | goto failed_init_c2h; | 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 | reg_base = devm_ioremap_resource(&pdev->dev, res); | 896 | reg_base = devm_ioremap_resource(&pdev->dev, res); |
| 895 | if (!reg_base) { | 897 | if (IS_ERR(reg_base)) { |
| 896 | xdma_err(xdev, "ioremap failed"); | 898 | xdma_err(xdev, "ioremap failed"); |
| 897 | goto failed; | 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 | return -ENOMEM; | 166 | return -ENOMEM; |
| 167 | 167 | ||
| 168 | shmem = of_parse_phandle(cdev->of_node, "shmem", idx); | 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 | return -ENXIO; | 171 | return -ENXIO; |
| 172 | } | ||
| 171 | 173 | ||
| 172 | ret = of_address_to_resource(shmem, 0, &res); | 174 | ret = of_address_to_resource(shmem, 0, &res); |
| 173 | of_node_put(shmem); | 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 | * before sending it with a single RAW xfer. | 818 | * before sending it with a single RAW xfer. |
| 819 | */ | 819 | */ |
| 820 | if (rd->tx_size < rd->tx_req_size) { | 820 | if (rd->tx_size < rd->tx_req_size) { |
| 821 | size_t cnt; | 821 | ssize_t cnt; |
| 822 | 822 | ||
| 823 | cnt = simple_write_to_buffer(rd->tx.buf, rd->tx.len, ppos, | 823 | cnt = simple_write_to_buffer(rd->tx.buf, rd->tx.len, ppos, |
| 824 | buf, count); | 824 | buf, count); |
| 825 | if (cnt < 0) | ||
| 826 | return cnt; | ||
| 827 | |||
| 825 | rd->tx_size += cnt; | 828 | rd->tx_size += cnt; |
| 826 | if (cnt < count) | 829 | if (cnt < count) |
| 827 | return cnt; | 830 | return cnt; |
| @@ -40,6 +40,7 @@ · 39 unmodified lines | |||
| 40 | /** | 40 | /** |
| 41 | * struct scmi_smc - Structure representing a SCMI smc transport | 41 | * struct scmi_smc - Structure representing a SCMI smc transport |
| 42 | * | 42 | * |
| 43 | * @irq: An optional IRQ for completion | ||
| 43 | * @cinfo: SCMI channel info | 44 | * @cinfo: SCMI channel info |
| 44 | * @shmem: Transmit/Receive shared memory area | 45 | * @shmem: Transmit/Receive shared memory area |
| 45 | * @shmem_lock: Lock to protect access to Tx/Rx shared memory area. | 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 | struct scmi_smc { | 55 | struct scmi_smc { |
| 56 | int irq; | ||
| 55 | struct scmi_chan_info *cinfo; | 57 | struct scmi_chan_info *cinfo; |
| 56 | struct scmi_shared_mem __iomem *shmem; | 58 | struct scmi_shared_mem __iomem *shmem; |
| 57 | /* Protect access to shmem area */ | 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 | struct resource res; | 129 | struct resource res; |
| 128 | struct device_node *np; | 130 | struct device_node *np; |
| 129 | u32 func_id; | 131 | u32 func_id; |
| 130 | int ret, irq; | 132 | int ret; |
| 131 | 133 | ||
| 132 | if (!tx) | 134 | if (!tx) |
| 133 | return -ENODEV; | 135 | return -ENODEV; |
| @@ -137,8 +139,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, · 3 unmodified lines | |||
| 137 | return -ENOMEM; | 139 | return -ENOMEM; |
| 138 | 140 | ||
| 139 | np = of_parse_phandle(cdev->of_node, "shmem", 0); | 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 | return -ENXIO; | 144 | return -ENXIO; |
| 145 | } | ||
| 142 | 146 | ||
| 143 | ret = of_address_to_resource(np, 0, &res); | 147 | ret = of_address_to_resource(np, 0, &res); |
| 144 | of_node_put(np); | 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 | * completion of a message is signaled by an interrupt rather than by | 171 | * completion of a message is signaled by an interrupt rather than by |
| 168 | * the return of the SMC call. | 172 | * the return of the SMC call. |
| 169 | */ | 173 | */ |
| 170 | irq = of_irq_get_byname(cdev->of_node, "a2p"); | 174 | scmi_info->irq = of_irq_get_byname(cdev->of_node, "a2p"); |
| 171 | if (irq > 0) { | 175 | if (scmi_info->irq > 0) { |
| 172 | ret = devm_request_irq(dev, irq, smc_msg_done_isr, | 176 | ret = request_irq(scmi_info->irq, smc_msg_done_isr, |
| 173 | IRQF_NO_SUSPEND, | 177 | IRQF_NO_SUSPEND, dev_name(dev), scmi_info); |
| 174 | dev_name(dev), scmi_info); | ||
| 175 | if (ret) { | 178 | if (ret) { |
| 176 | dev_err(dev, "failed to setup SCMI smc irq\n"); | 179 | dev_err(dev, "failed to setup SCMI smc irq\n"); |
| 177 | return ret; | 180 | return ret; |
| @@ -193,6 +196,10 @@ static int smc_chan_free(int id, void *p, void *data) · 15 unmodified lines | |||
| 193 | struct scmi_chan_info *cinfo = p; | 196 | struct scmi_chan_info *cinfo = p; |
| 194 | struct scmi_smc *scmi_info = cinfo->transport_info; | 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 | cinfo->transport_info = NULL; | 203 | cinfo->transport_info = NULL; |
| 197 | scmi_info->cinfo = NULL; | 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 | static int __init smccc_soc_init(void) | 35 | static int __init smccc_soc_init(void) |
| 36 | { | 36 | { |
| 37 | struct arm_smccc_res res; | ||
| 38 | int soc_id_rev, soc_id_version; | 37 | int soc_id_rev, soc_id_version; |
| 39 | static char soc_id_str[20], soc_id_rev_str[12]; | 38 | static char soc_id_str[20], soc_id_rev_str[12]; |
| 40 | static char soc_id_jep106_id_str[12]; | 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 | if (soc_id_version < 0) { | 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 | return -EINVAL; | 52 | return -EINVAL; |
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | soc_id_rev = arm_smccc_get_soc_id_revision(); | 55 | soc_id_rev = arm_smccc_get_soc_id_revision(); |
| 57 | if (soc_id_rev < 0) { | 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 | return -EINVAL; | 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 | gc->set_config = gpio_sim_set_config; | 429 | gc->set_config = gpio_sim_set_config; |
| 430 | gc->to_irq = gpio_sim_to_irq; | 430 | gc->to_irq = gpio_sim_to_irq; |
| 431 | gc->free = gpio_sim_free; | 431 | gc->free = gpio_sim_free; |
| 432 | gc->can_sleep = true; | ||
| 432 | 433 | ||
| 433 | ret = devm_gpiochip_add_data(dev, gc, chip); | 434 | ret = devm_gpiochip_add_data(dev, gc, chip); |
| 434 | if (ret) | 435 | if (ret) |
| @@ -18,7 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
| 19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
| 20 | 20 | ||
| 21 | #define WS16C48_EXTENT 10 | 21 | #define WS16C48_EXTENT 11 |
| 22 | #define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT) | 22 | #define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT) |
| 23 | 23 | ||
| 24 | static unsigned int base[MAX_NUM_WS16C48]; | 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 | void amdgpu_device_pci_config_reset(struct amdgpu_device *adev); | 1296 | void amdgpu_device_pci_config_reset(struct amdgpu_device *adev); |
| 1297 | int amdgpu_device_pci_reset(struct amdgpu_device *adev); | 1297 | int amdgpu_device_pci_reset(struct amdgpu_device *adev); |
| 1298 | bool amdgpu_device_need_post(struct amdgpu_device *adev); | 1298 | bool amdgpu_device_need_post(struct amdgpu_device *adev); |
| 1299 | bool amdgpu_sg_display_supported(struct amdgpu_device *adev); | ||
| 1299 | bool amdgpu_device_pcie_dynamic_switching_supported(void); | 1300 | bool amdgpu_device_pcie_dynamic_switching_supported(void); |
| 1300 | bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev); | 1301 | bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev); |
| 1301 | bool amdgpu_device_aspm_support_quirk(void); | 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 | if (!p->gang_size) { | 296 | if (!p->gang_size) { |
| 297 | ret = -EINVAL; | 297 | ret = -EINVAL; |
| 298 | goto free_partial_kdata; | 298 | goto free_all_kdata; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | for (i = 0; i < p->gang_size; ++i) { | 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 | return true; | 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 | * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic | 1488 | * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic |
| 1463 | * speed switching. Until we have confirmation from Intel that a specific host | 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 | case IP_VERSION(11, 0, 3): | 471 | case IP_VERSION(11, 0, 3): |
| 472 | if ((adev->gfx.me_fw_version >= 1505) && | 472 | if ((adev->gfx.me_fw_version >= 1505) && |
| 473 | (adev->gfx.pfp_fw_version >= 1600) && | 473 | (adev->gfx.pfp_fw_version >= 1600) && |
| 474 | (adev->gfx.mec_fw_version >= 512)) | 474 | (adev->gfx.mec_fw_version >= 512)) { |
| 475 | adev->gfx.cp_gfx_shadow = true; | 475 | if (amdgpu_sriov_vf(adev)) |
| 476 | adev->gfx.cp_gfx_shadow = true; | ||
| 477 | else | ||
| 478 | adev->gfx.cp_gfx_shadow = false; | ||
| 479 | } | ||
| 476 | break; | 480 | break; |
| 477 | default: | 481 | default: |
| 478 | adev->gfx.cp_gfx_shadow = false; | 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 | int ret; | 137 | int ret; |
| 138 | int retry_loop; | 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 | for (retry_loop = 0; retry_loop < 10; retry_loop++) { | 145 | for (retry_loop = 0; retry_loop < 10; retry_loop++) { |
| 141 | /* Wait for bootloader to signify that is | 146 | ret = psp_wait_for( |
| 142 | ready having bit 31 of C2PMSG_35 set to 1 */ | 147 | psp, SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35), |
| 143 | ret = psp_wait_for(psp, | 148 | 0x80000000, 0xffffffff, false); |
| 144 | SOC15_REG_OFFSET(MP0, 0, regMP0_SMN_C2PMSG_35), | ||
| 145 | 0x80000000, | ||
| 146 | 0x80000000, | ||
| 147 | false); | ||
| 148 | 149 | ||
| 149 | if (ret == 0) | 150 | if (ret == 0) |
| 150 | return 0; | 151 | return 0; |
| @@ -1543,11 +1543,7 @@ static bool kfd_ignore_crat(void) · 1542 unmodified lines | |||
| 1543 | if (ignore_crat) | 1543 | if (ignore_crat) |
| 1544 | return true; | 1544 | return true; |
| 1545 | 1545 | ||
| 1546 | #ifndef KFD_SUPPORT_IOMMU_V2 | ||
| 1547 | ret = true; | 1546 | ret = true; |
| 1548 | #else | ||
| 1549 | ret = false; | ||
| 1550 | #endif | ||
| 1551 | 1547 | ||
| 1552 | return ret; | 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 | kfd_device_info_set_event_interrupt_class(kfd); | 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 | if (gc_version < IP_VERSION(11, 0, 0)) { | 197 | if (gc_version < IP_VERSION(11, 0, 0)) { |
| 203 | /* Navi2x+, Navi1x+ */ | 198 | /* Navi2x+, Navi1x+ */ |
| 204 | if (gc_version == IP_VERSION(10, 3, 6)) | 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 | asic_type != CHIP_TONGA) | 228 | asic_type != CHIP_TONGA) |
| 234 | kfd->device_info.supports_cwsr = true; | 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 | if (asic_type != CHIP_HAWAII && !vf) | 231 | if (asic_type != CHIP_HAWAII && !vf) |
| 241 | kfd->device_info.needs_pci_atomics = true; | 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 | uint32_t gfx_target_version = 0; | 240 | uint32_t gfx_target_version = 0; |
| 250 | 241 | ||
| 251 | switch (adev->asic_type) { | 242 | switch (adev->asic_type) { |
| 252 | #ifdef KFD_SUPPORT_IOMMU_V2 | ||
| 253 | #ifdef CONFIG_DRM_AMDGPU_CIK | 243 | #ifdef CONFIG_DRM_AMDGPU_CIK |
| 254 | case CHIP_KAVERI: | 244 | case CHIP_KAVERI: |
| 255 | gfx_target_version = 70000; | 245 | gfx_target_version = 70000; |
| @@ -262,7 +252,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) · 6 unmodified lines | |||
| 262 | if (!vf) | 252 | if (!vf) |
| 263 | f2g = &gfx_v8_kfd2kgd; | 253 | f2g = &gfx_v8_kfd2kgd; |
| 264 | break; | 254 | break; |
| 265 | #endif | ||
| 266 | #ifdef CONFIG_DRM_AMDGPU_CIK | 255 | #ifdef CONFIG_DRM_AMDGPU_CIK |
| 267 | case CHIP_HAWAII: | 256 | case CHIP_HAWAII: |
| 268 | gfx_target_version = 70001; | 257 | gfx_target_version = 70001; |
| @@ -298,7 +287,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) · 29 unmodified lines | |||
| 298 | gfx_target_version = 90000; | 287 | gfx_target_version = 90000; |
| 299 | f2g = &gfx_v9_kfd2kgd; | 288 | f2g = &gfx_v9_kfd2kgd; |
| 300 | break; | 289 | break; |
| 301 | #ifdef KFD_SUPPORT_IOMMU_V2 | ||
| 302 | /* Raven */ | 290 | /* Raven */ |
| 303 | case IP_VERSION(9, 1, 0): | 291 | case IP_VERSION(9, 1, 0): |
| 304 | case IP_VERSION(9, 2, 2): | 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 | if (!vf) | 294 | if (!vf) |
| 307 | f2g = &gfx_v9_kfd2kgd; | 295 | f2g = &gfx_v9_kfd2kgd; |
| 308 | break; | 296 | break; |
| 309 | #endif | ||
| 310 | /* Vega12 */ | 297 | /* Vega12 */ |
| 311 | case IP_VERSION(9, 2, 1): | 298 | case IP_VERSION(9, 2, 1): |
| 312 | gfx_target_version = 90004; | 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 | switch (dev->adev->asic_type) { | 2540 | switch (dev->adev->asic_type) { |
| 2541 | case CHIP_CARRIZO: | ||
| 2542 | device_queue_manager_init_vi(&dqm->asic_ops); | ||
| 2543 | break; | ||
| 2544 | |||
| 2545 | case CHIP_KAVERI: | 2541 | case CHIP_KAVERI: |
| 2546 | device_queue_manager_init_cik(&dqm->asic_ops); | ||
| 2547 | break; | ||
| 2548 | |||
| 2549 | case CHIP_HAWAII: | 2542 | case CHIP_HAWAII: |
| 2550 | device_queue_manager_init_cik_hawaii(&dqm->asic_ops); | 2543 | device_queue_manager_init_cik_hawaii(&dqm->asic_ops); |
| 2551 | break; | 2544 | break; |
| 2552 | 2545 | ||
| 2546 | case CHIP_CARRIZO: | ||
| 2553 | case CHIP_TONGA: | 2547 | case CHIP_TONGA: |
| 2554 | case CHIP_FIJI: | 2548 | case CHIP_FIJI: |
| 2555 | case CHIP_POLARIS10: | 2549 | case CHIP_POLARIS10: |
| @@ -1638,9 +1638,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) · 1637 unmodified lines | |||
| 1638 | } | 1638 | } |
| 1639 | break; | 1639 | break; |
| 1640 | } | 1640 | } |
| 1641 | if (init_data.flags.gpu_vm_support && | 1641 | if (init_data.flags.gpu_vm_support) |
| 1642 | (amdgpu_sg_display == 0)) | 1642 | init_data.flags.gpu_vm_support = amdgpu_sg_display_supported(adev); |
| 1643 | init_data.flags.gpu_vm_support = false; | ||
| 1644 | 1643 | ||
| 1645 | if (init_data.flags.gpu_vm_support) | 1644 | if (init_data.flags.gpu_vm_support) |
| 1646 | adev->mode_info.gpu_vm_support = true; | 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 | if (computed_streams[i]) | 1320 | if (computed_streams[i]) |
| 1321 | continue; | 1321 | continue; |
| 1322 | 1322 | ||
| 1323 | if (!res_pool->funcs->remove_stream_from_ctx || | 1323 | if (res_pool->funcs->remove_stream_from_ctx && |
| 1324 | res_pool->funcs->remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK) | 1324 | res_pool->funcs->remove_stream_from_ctx(stream->ctx->dc, dc_state, stream) != DC_OK) |
| 1325 | return -EINVAL; | 1325 | return -EINVAL; |
| 1326 | 1326 | ||
| @@ -777,7 +777,8 @@ void dce110_edp_wait_for_hpd_ready( · 776 unmodified lines | |||
| 777 | dal_gpio_destroy_irq(&hpd); | 777 | dal_gpio_destroy_irq(&hpd); |
| 778 | 778 | ||
| 779 | /* ensure that the panel is detected */ | 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 | void dce110_edp_power_control( | 784 | void dce110_edp_power_control( |
| @@ -357,8 +357,11 @@ void dpp3_set_cursor_attributes( · 356 unmodified lines | |||
| 357 | int cur_rom_en = 0; | 357 | int cur_rom_en = 0; |
| 358 | 358 | ||
| 359 | if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA || | 359 | if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA || |
| 360 | color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) | 360 | color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) { |
| 361 | cur_rom_en = 1; | 361 | if (cursor_attributes->attribute_flags.bits.ENABLE_CURSOR_DEGAMMA) { |
| 362 | cur_rom_en = 1; | ||
| 363 | } | ||
| 364 | } | ||
| 362 | 365 | ||
| 363 | REG_UPDATE_3(CURSOR0_CONTROL, | 366 | REG_UPDATE_3(CURSOR0_CONTROL, |
| 364 | CUR0_MODE, color_format, | 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 | * For SMU 13.0.4/11, PMFW will handle the features disablement properly | 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 | switch (adev->ip_versions[MP1_HWIP][0]) { | 1587 | switch (adev->ip_versions[MP1_HWIP][0]) { |
| 1588 | case IP_VERSION(13, 0, 4): | 1588 | case IP_VERSION(13, 0, 4): |
| 1589 | case IP_VERSION(13, 0, 11): | 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 | struct smu_13_0_0_powerplay_table *powerplay_table = | 331 | struct smu_13_0_0_powerplay_table *powerplay_table = |
| 332 | table_context->power_play_table; | 332 | table_context->power_play_table; |
| 333 | struct smu_baco_context *smu_baco = &smu->smu_baco; | 333 | struct smu_baco_context *smu_baco = &smu->smu_baco; |
| 334 | #if 0 | ||
| 334 | PPTable_t *pptable = smu->smu_table.driver_pptable; | 335 | PPTable_t *pptable = smu->smu_table.driver_pptable; |
| 335 | const OverDriveLimits_t * const overdrive_upperlimits = | 336 | const OverDriveLimits_t * const overdrive_upperlimits = |
| 336 | &pptable->SkuTable.OverDriveLimitsBasicMax; | 337 | &pptable->SkuTable.OverDriveLimitsBasicMax; |
| 337 | const OverDriveLimits_t * const overdrive_lowerlimits = | 338 | const OverDriveLimits_t * const overdrive_lowerlimits = |
| 338 | &pptable->SkuTable.OverDriveLimitsMin; | 339 | &pptable->SkuTable.OverDriveLimitsMin; |
| 340 | #endif | ||
| 339 | 341 | ||
| 340 | if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC) | 342 | if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC) |
| 341 | smu->dc_controlled_by_gpio = true; | 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 | if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO) | 349 | if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO) |
| 348 | smu_baco->maco_support = true; | 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 | if (!overdrive_lowerlimits->FeatureCtrlMask || | 358 | if (!overdrive_lowerlimits->FeatureCtrlMask || |
| 351 | !overdrive_upperlimits->FeatureCtrlMask) | 359 | !overdrive_upperlimits->FeatureCtrlMask) |
| 352 | smu->od_enabled = false; | 360 | smu->od_enabled = false; |
| 353 | 361 | ||
| 354 | table_context->thermal_controller_type = | ||
| 355 | powerplay_table->thermal_controller_type; | ||
| 356 | |||
| 357 | /* | 362 | /* |
| 358 | * Instead of having its own buffer space and get overdrive_table copied, | 363 | * Instead of having its own buffer space and get overdrive_table copied, |
| 359 | * smu->od_settings just points to the actual overdrive_table | 364 | * smu->od_settings just points to the actual overdrive_table |
| 360 | */ | 365 | */ |
| 361 | smu->od_settings = &powerplay_table->overdrive_table; | 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 | return 0; | 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 | (OverDriveTableExternal_t *)smu->smu_table.overdrive_table; | 1151 | (OverDriveTableExternal_t *)smu->smu_table.overdrive_table; |
| 1141 | struct smu_13_0_dpm_table *single_dpm_table; | 1152 | struct smu_13_0_dpm_table *single_dpm_table; |
| 1142 | struct smu_13_0_pcie_table *pcie_table; | 1153 | struct smu_13_0_pcie_table *pcie_table; |
| 1143 | const int link_width[] = {0, 1, 2, 4, 8, 12, 16}; | ||
| 1144 | uint32_t gen_speed, lane_width; | 1154 | uint32_t gen_speed, lane_width; |
| 1145 | int i, curr_freq, size = 0; | 1155 | int i, curr_freq, size = 0; |
| 1146 | int32_t min_value, max_value; | 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 | (pcie_table->pcie_lane[i] == 6) ? "x16" : "", | 1266 | (pcie_table->pcie_lane[i] == 6) ? "x16" : "", |
| 1257 | pcie_table->clk_freq[i], | 1267 | pcie_table->clk_freq[i], |
| 1258 | (gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) && | 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 | break; | 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 | gpu_metrics->average_socket_power = | 1994 | gpu_metrics->average_socket_power = |
| 1995 | SMUQ10_TO_UINT(metrics->SocketPower); | 1995 | SMUQ10_TO_UINT(metrics->SocketPower); |
| 1996 | /* Energy is reported in 15.625mJ units */ | 1996 | /* Energy counter reported in 15.259uJ (2^-16) units */ |
| 1997 | gpu_metrics->energy_accumulator = | 1997 | gpu_metrics->energy_accumulator = metrics->SocketEnergyAcc; |
| 1998 | SMUQ10_TO_UINT(metrics->SocketEnergyAcc); | ||
| 1999 | 1998 | ||
| 2000 | gpu_metrics->current_gfxclk = | 1999 | gpu_metrics->current_gfxclk = |
| 2001 | SMUQ10_TO_UINT(metrics->GfxclkFrequency[xcc0]); | 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 | struct smu_baco_context *smu_baco = &smu->smu_baco; | 323 | struct smu_baco_context *smu_baco = &smu->smu_baco; |
| 324 | PPTable_t *smc_pptable = table_context->driver_pptable; | 324 | PPTable_t *smc_pptable = table_context->driver_pptable; |
| 325 | BoardTable_t *BoardTable = &smc_pptable->BoardTable; | 325 | BoardTable_t *BoardTable = &smc_pptable->BoardTable; |
| 326 | #if 0 | ||
| 326 | const OverDriveLimits_t * const overdrive_upperlimits = | 327 | const OverDriveLimits_t * const overdrive_upperlimits = |
| 327 | &smc_pptable->SkuTable.OverDriveLimitsBasicMax; | 328 | &smc_pptable->SkuTable.OverDriveLimitsBasicMax; |
| 328 | const OverDriveLimits_t * const overdrive_lowerlimits = | 329 | const OverDriveLimits_t * const overdrive_lowerlimits = |
| 329 | &smc_pptable->SkuTable.OverDriveLimitsMin; | 330 | &smc_pptable->SkuTable.OverDriveLimitsMin; |
| 331 | #endif | ||
| 330 | 332 | ||
| 331 | if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC) | 333 | if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC) |
| 332 | smu->dc_controlled_by_gpio = true; | 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 | if (smu_baco->platform_support && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled)) | 340 | if (smu_baco->platform_support && (BoardTable->HsrEnabled || BoardTable->VddqOffEnabled)) |
| 339 | smu_baco->maco_support = true; | 341 | smu_baco->maco_support = true; |
| 340 | 342 | ||
| 343 | #if 0 | ||
| 341 | if (!overdrive_lowerlimits->FeatureCtrlMask || | 344 | if (!overdrive_lowerlimits->FeatureCtrlMask || |
| 342 | !overdrive_upperlimits->FeatureCtrlMask) | 345 | !overdrive_upperlimits->FeatureCtrlMask) |
| 343 | smu->od_enabled = false; | 346 | smu->od_enabled = false; |
| 344 | 347 | ||
| 345 | table_context->thermal_controller_type = | ||
| 346 | powerplay_table->thermal_controller_type; | ||
| 347 | |||
| 348 | /* | 348 | /* |
| 349 | * Instead of having its own buffer space and get overdrive_table copied, | 349 | * Instead of having its own buffer space and get overdrive_table copied, |
| 350 | * smu->od_settings just points to the actual overdrive_table | 350 | * smu->od_settings just points to the actual overdrive_table |
| 351 | */ | 351 | */ |
| 352 | smu->od_settings = &powerplay_table->overdrive_table; | 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 | return 0; | 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 | int int_status[3], i; | 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 | return IRQ_HANDLED; | 2521 | return IRQ_HANDLED; |
| 2522 | 2522 | ||
| 2523 | pm_runtime_get_sync(dev); | ||
| 2524 | |||
| 2523 | int_status[0] = it6505_read(it6505, INT_STATUS_01); | 2525 | int_status[0] = it6505_read(it6505, INT_STATUS_01); |
| 2524 | int_status[1] = it6505_read(it6505, INT_STATUS_02); | 2526 | int_status[1] = it6505_read(it6505, INT_STATUS_02); |
| 2525 | int_status[2] = it6505_read(it6505, INT_STATUS_03); | 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 | dsi->lanes = 4; | 774 | dsi->lanes = 4; |
| 775 | dsi->format = MIPI_DSI_FMT_RGB888; | 775 | dsi->format = MIPI_DSI_FMT_RGB888; |
| 776 | dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | | 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 | | 777 | MIPI_DSI_MODE_VIDEO_HSE; |
| 778 | MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP | | ||
| 779 | MIPI_DSI_MODE_NO_EOT_PACKET; | ||
| 780 | 778 | ||
| 781 | ret = devm_mipi_dsi_attach(dev, dsi); | 779 | ret = devm_mipi_dsi_attach(dev, dsi); |
| 782 | if (ret < 0) { | 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 | int ret; | 623 | int ret; |
| 624 | 624 | ||
| 625 | if (obj->import_attach) { | 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 | vma->vm_private_data = NULL; | 630 | vma->vm_private_data = NULL; |
| 631 | vma->vm_ops = NULL; | ||
| 632 | |||
| 627 | ret = dma_buf_mmap(obj->dma_buf, vma, 0); | 633 | ret = dma_buf_mmap(obj->dma_buf, vma, 0); |
| 628 | 634 | ||
| 629 | /* Drop the reference drm_gem_mmap_obj() acquired.*/ | 635 | /* Drop the reference drm_gem_mmap_obj() acquired.*/ |
| @@ -165,14 +165,60 @@ static u32 preparser_disable(bool state) · 164 unmodified lines | |||
| 165 | return MI_ARB_CHECK | 1 << 8 | state; | 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 | *cs++ = MI_LOAD_REGISTER_IMM(1) | MI_LRI_MMIO_REMAP_EN; | 210 | *cs++ = MI_LOAD_REGISTER_IMM(1) | MI_LRI_MMIO_REMAP_EN; |
| 173 | *cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset; | 211 | *cs++ = i915_mmio_reg_offset(inv_reg) + gsi_offset; |
| 174 | *cs++ = AUX_INV; | 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 | return cs; | 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 | struct intel_engine_cs *engine = rq->engine; | 249 | struct intel_engine_cs *engine = rq->engine; |
| 204 | 250 | ||
| 205 | if (mode & EMIT_FLUSH) { | 251 | /* |
| 206 | u32 flags = 0; | 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 | int err; | 258 | int err; |
| 208 | u32 *cs; | 259 | u32 *cs; |
| 209 | 260 | ||
| @@ -211,32 +262,40 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) · 1 unmodified line | |||
| 211 | if (err) | 262 | if (err) |
| 212 | return err; | 263 | return err; |
| 213 | 264 | ||
| 214 | flags |= PIPE_CONTROL_TILE_CACHE_FLUSH; | 265 | bit_group_0 |= PIPE_CONTROL0_HDC_PIPELINE_FLUSH; |
| 215 | flags |= PIPE_CONTROL_FLUSH_L3; | 266 | |
| 216 | flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; | 267 | /* |
| 217 | flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; | 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 | /* Wa_1409600907:tgl,adl-p */ | 278 | /* Wa_1409600907:tgl,adl-p */ |
| 219 | flags |= PIPE_CONTROL_DEPTH_STALL; | 279 | bit_group_1 |= PIPE_CONTROL_DEPTH_STALL; |
| 220 | flags |= PIPE_CONTROL_DC_FLUSH_ENABLE; | 280 | bit_group_1 |= PIPE_CONTROL_DC_FLUSH_ENABLE; |
| 221 | flags |= PIPE_CONTROL_FLUSH_ENABLE; | 281 | bit_group_1 |= PIPE_CONTROL_FLUSH_ENABLE; |
| 222 | 282 | ||
| 223 | flags |= PIPE_CONTROL_STORE_DATA_INDEX; | 283 | bit_group_1 |= PIPE_CONTROL_STORE_DATA_INDEX; |
| 224 | flags |= PIPE_CONTROL_QW_WRITE; | 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 | if (!HAS_3D_PIPELINE(engine->i915)) | 288 | if (!HAS_3D_PIPELINE(engine->i915)) |
| 229 | flags &= ~PIPE_CONTROL_3D_ARCH_FLAGS; | 289 | bit_group_1 &= ~PIPE_CONTROL_3D_ARCH_FLAGS; |
| 230 | else if (engine->class == COMPUTE_CLASS) | 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 | cs = intel_ring_begin(rq, 6); | 293 | cs = intel_ring_begin(rq, 6); |
| 234 | if (IS_ERR(cs)) | 294 | if (IS_ERR(cs)) |
| 235 | return PTR_ERR(cs); | 295 | return PTR_ERR(cs); |
| 236 | 296 | ||
| 237 | cs = gen12_emit_pipe_control(cs, | 297 | cs = gen12_emit_pipe_control(cs, bit_group_0, bit_group_1, |
| 238 | PIPE_CONTROL0_HDC_PIPELINE_FLUSH, | 298 | LRC_PPHWSP_SCRATCH_ADDR); |
| 239 | flags, LRC_PPHWSP_SCRATCH_ADDR); | ||
| 240 | intel_ring_advance(rq, cs); | 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 | else if (engine->class == COMPUTE_CLASS) | 326 | else if (engine->class == COMPUTE_CLASS) |
| 268 | flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS; | 327 | flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS; |
| 269 | 328 | ||
| 270 | if (!HAS_FLAT_CCS(rq->engine->i915)) | 329 | count = 8; |
| 271 | count = 8 + 4; | 330 | if (gen12_needs_ccs_aux_inv(rq->engine)) |
| 272 | else | 331 | count += 8; |
| 273 | count = 8; | ||
| 274 | 332 | ||
| 275 | cs = intel_ring_begin(rq, count); | 333 | cs = intel_ring_begin(rq, count); |
| 276 | if (IS_ERR(cs)) | 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 | cs = gen8_emit_pipe_control(cs, flags, LRC_PPHWSP_SCRATCH_ADDR); | 344 | cs = gen8_emit_pipe_control(cs, flags, LRC_PPHWSP_SCRATCH_ADDR); |
| 287 | 345 | ||
| 288 | if (!HAS_FLAT_CCS(rq->engine->i915)) { | 346 | cs = gen12_emit_aux_table_inv(engine, cs); |
| 289 | /* hsdes: 1809175790 */ | ||
| 290 | cs = gen12_emit_aux_table_inv(rq->engine->gt, | ||
| 291 | cs, GEN12_GFX_CCS_AUX_NV); | ||
| 292 | } | ||
| 293 | 347 | ||
| 294 | *cs++ = preparser_disable(false); | 348 | *cs++ = preparser_disable(false); |
| 295 | intel_ring_advance(rq, cs); | 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 | int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) | 355 | int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) |
| 302 | { | 356 | { |
| 303 | intel_engine_mask_t aux_inv = 0; | 357 | u32 cmd = 4; |
| 304 | u32 cmd, *cs; | 358 | u32 *cs; |
| 305 | 359 | ||
| 306 | cmd = 4; | ||
| 307 | if (mode & EMIT_INVALIDATE) { | 360 | if (mode & EMIT_INVALIDATE) { |
| 308 | cmd += 2; | 361 | cmd += 2; |
| 309 | 362 | ||
| 310 | if (!HAS_FLAT_CCS(rq->engine->i915) && | 363 | if (gen12_needs_ccs_aux_inv(rq->engine)) |
| 311 | (rq->engine->class == VIDEO_DECODE_CLASS || | 364 | cmd += 8; |
| 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 | } | ||
| 318 | } | 365 | } |
| 319 | 366 | ||
| 320 | cs = intel_ring_begin(rq, cmd); | 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 | cmd |= MI_INVALIDATE_TLB; | 385 | cmd |= MI_INVALIDATE_TLB; |
| 339 | if (rq->engine->class == VIDEO_DECODE_CLASS) | 386 | if (rq->engine->class == VIDEO_DECODE_CLASS) |
| 340 | cmd |= MI_INVALIDATE_BSD; | 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 | *cs++ = cmd; | 394 | *cs++ = cmd; |
| @@ -345,14 +396,7 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) · 1 unmodified line | |||
| 345 | *cs++ = 0; /* upper addr */ | 396 | *cs++ = 0; /* upper addr */ |
| 346 | *cs++ = 0; /* value */ | 397 | *cs++ = 0; /* value */ |
| 347 | 398 | ||
| 348 | if (aux_inv) { /* hsdes: 1809175790 */ | 399 | cs = gen12_emit_aux_table_inv(rq->engine, cs); |
| 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 | } | ||
| 356 | 400 | ||
| 357 | if (mode & EMIT_INVALIDATE) | 401 | if (mode & EMIT_INVALIDATE) |
| 358 | *cs++ = preparser_disable(false); | 402 | *cs++ = preparser_disable(false); |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include "intel_gt_regs.h" | 13 | #include "intel_gt_regs.h" |
| 14 | #include "intel_gpu_commands.h" | 14 | #include "intel_gpu_commands.h" |
| 15 | 15 | ||
| 16 | struct intel_engine_cs; | ||
| 16 | struct intel_gt; | 17 | struct intel_gt; |
| 17 | struct i915_request; | 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 | u32 *gen11_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); | 47 | u32 *gen11_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); |
| 47 | u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); | 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 | static inline u32 * | 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 | memset(batch, 0, 6 * sizeof(u32)); | 56 | memset(batch, 0, 6 * sizeof(u32)); |
| 55 | 57 | ||
| 56 | batch[0] = GFX_OP_PIPE_CONTROL(6) | flags0; | 58 | batch[0] = GFX_OP_PIPE_CONTROL(6) | bit_group_0; |
| 57 | batch[1] = flags1; | 59 | batch[1] = bit_group_1; |
| 58 | batch[2] = offset; | 60 | batch[2] = offset; |
| 59 | 61 | ||
| 60 | return batch + 6; | 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 | static inline u32 * | 78 | static inline u32 * |
| @@ -121,6 +121,7 @@ · 120 unmodified lines | |||
| 121 | #define MI_SEMAPHORE_TARGET(engine) ((engine)<<15) | 121 | #define MI_SEMAPHORE_TARGET(engine) ((engine)<<15) |
| 122 | #define MI_SEMAPHORE_WAIT MI_INSTR(0x1c, 2) /* GEN8+ */ | 122 | #define MI_SEMAPHORE_WAIT MI_INSTR(0x1c, 2) /* GEN8+ */ |
| 123 | #define MI_SEMAPHORE_WAIT_TOKEN MI_INSTR(0x1c, 3) /* GEN12+ */ | 123 | #define MI_SEMAPHORE_WAIT_TOKEN MI_INSTR(0x1c, 3) /* GEN12+ */ |
| 124 | #define MI_SEMAPHORE_REGISTER_POLL (1 << 16) | ||
| 124 | #define MI_SEMAPHORE_POLL (1 << 15) | 125 | #define MI_SEMAPHORE_POLL (1 << 15) |
| 125 | #define MI_SEMAPHORE_SAD_GT_SDD (0 << 12) | 126 | #define MI_SEMAPHORE_SAD_GT_SDD (0 << 12) |
| 126 | #define MI_SEMAPHORE_SAD_GTE_SDD (1 << 12) | 127 | #define MI_SEMAPHORE_SAD_GTE_SDD (1 << 12) |
| @@ -299,6 +300,7 @@ · 172 unmodified lines | |||
| 299 | #define PIPE_CONTROL_QW_WRITE (1<<14) | 300 | #define PIPE_CONTROL_QW_WRITE (1<<14) |
| 300 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) | 301 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) |
| 301 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) | 302 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) |
| 303 | #define PIPE_CONTROL_CCS_FLUSH (1<<13) /* MTL+ */ | ||
| 302 | #define PIPE_CONTROL_WRITE_FLUSH (1<<12) | 304 | #define PIPE_CONTROL_WRITE_FLUSH (1<<12) |
| 303 | #define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */ | 305 | #define PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH (1<<12) /* gen6+ */ |
| 304 | #define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on ILK */ | 306 | #define PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE (1<<11) /* MBZ on ILK */ |
| @@ -332,9 +332,11 @@ · 331 unmodified lines | |||
| 332 | #define GEN8_PRIVATE_PAT_HI _MMIO(0x40e0 + 4) | 332 | #define GEN8_PRIVATE_PAT_HI _MMIO(0x40e0 + 4) |
| 333 | #define GEN10_PAT_INDEX(index) _MMIO(0x40e0 + (index) * 4) | 333 | #define GEN10_PAT_INDEX(index) _MMIO(0x40e0 + (index) * 4) |
| 334 | #define BSD_HWS_PGA_GEN7 _MMIO(0x4180) | 334 | #define BSD_HWS_PGA_GEN7 _MMIO(0x4180) |
| 335 | #define GEN12_GFX_CCS_AUX_NV _MMIO(0x4208) | 335 | |
| 336 | #define GEN12_VD0_AUX_NV _MMIO(0x4218) | 336 | #define GEN12_CCS_AUX_INV _MMIO(0x4208) |
| 337 | #define GEN12_VD1_AUX_NV _MMIO(0x4228) | 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 | #define GEN8_RTCR _MMIO(0x4260) | 341 | #define GEN8_RTCR _MMIO(0x4260) |
| 340 | #define GEN8_M1TCR _MMIO(0x4264) | 342 | #define GEN8_M1TCR _MMIO(0x4264) |
| @@ -342,14 +344,12 @@ · 1 unmodified line | |||
| 342 | #define GEN8_BTCR _MMIO(0x426c) | 344 | #define GEN8_BTCR _MMIO(0x426c) |
| 343 | #define GEN8_VTCR _MMIO(0x4270) | 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 | #define BLT_HWS_PGA_GEN7 _MMIO(0x4280) | 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 | #define AUX_INV REG_BIT(0) | 351 | #define AUX_INV REG_BIT(0) |
| 352 | |||
| 353 | #define VEBOX_HWS_PGA_GEN7 _MMIO(0x4380) | 353 | #define VEBOX_HWS_PGA_GEN7 _MMIO(0x4380) |
| 354 | 354 | ||
| 355 | #define GEN12_AUX_ERR_DBG _MMIO(0x43f4) | 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 | IS_DG2_G11(ce->engine->i915)) | 1364 | IS_DG2_G11(ce->engine->i915)) |
| 1365 | cs = gen8_emit_pipe_control(cs, PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, 0); | 1365 | cs = gen8_emit_pipe_control(cs, PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, 0); |
| 1366 | 1366 | ||
| 1367 | /* hsdes: 1809175790 */ | 1367 | cs = gen12_emit_aux_table_inv(ce->engine, cs); |
| 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); | ||
| 1371 | 1368 | ||
| 1372 | /* Wa_16014892111 */ | 1369 | /* Wa_16014892111 */ |
| 1373 | if (IS_MTL_GRAPHICS_STEP(ce->engine->i915, M, STEP_A0, STEP_B0) || | 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 | PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, | 1389 | PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, |
| 1393 | 0); | 1390 | 0); |
| 1394 | 1391 | ||
| 1395 | /* hsdes: 1809175790 */ | 1392 | return gen12_emit_aux_table_inv(ce->engine, cs); |
| 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; | ||
| 1406 | } | 1393 | } |
| 1407 | 1394 | ||
| 1408 | static void | 1395 | static void |
| @@ -491,7 +491,7 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu, · 490 unmodified lines | |||
| 491 | return; | 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 | // check the msg in DATA register. | 496 | // check the msg in DATA register. |
| 497 | msg = vgpu_vreg(vgpu, offset + 4); | 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 | } while (unlikely(is_barrier(active))); | 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 | __i915_active_acquire(ref); | 454 | __i915_active_acquire(ref); |
| 455 | else | ||
| 456 | dma_fence_put(fence); | ||
| 454 | 457 | ||
| 455 | out: | 458 | out: |
| 456 | i915_active_release(ref); | 459 | i915_active_release(ref); |
| @@ -469,13 +472,9 @@ __i915_active_set_fence(struct i915_active *ref, · 12 unmodified lines | |||
| 469 | return NULL; | 472 | return NULL; |
| 470 | } | 473 | } |
| 471 | 474 | ||
| 472 | rcu_read_lock(); | ||
| 473 | prev = __i915_active_fence_set(active, fence); | 475 | prev = __i915_active_fence_set(active, fence); |
| 474 | if (prev) | 476 | if (!prev) |
| 475 | prev = dma_fence_get_rcu(prev); | ||
| 476 | else | ||
| 477 | __i915_active_acquire(ref); | 477 | __i915_active_acquire(ref); |
| 478 | rcu_read_unlock(); | ||
| 479 | 478 | ||
| 480 | return prev; | 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 | * Records the new @fence as the last active fence along its timeline in | 1019 | * Records the new @fence as the last active fence along its timeline in |
| 1021 | * this active tracker, moving the tracking callbacks from the previous | 1020 | * this active tracker, moving the tracking callbacks from the previous |
| 1022 | * fence onto this one. Returns the previous fence (if not already completed), | 1021 | * fence onto this one. Gets and returns a reference to the previous fence |
| 1023 | * which the caller must ensure is executed before the new fence. To ensure | 1022 | * (if not already completed), which the caller must put after making sure |
| 1024 | * that the order of fences within the timeline of the i915_active_fence is | 1023 | * that it is executed before the new fence. To ensure that the order of |
| 1025 | * understood, it should be locked by the caller. | 1024 | * fences within the timeline of the i915_active_fence is understood, it |
| 1025 | * should be locked by the caller. | ||
| 1026 | */ | 1026 | */ |
| 1027 | struct dma_fence * | 1027 | struct dma_fence * |
| 1028 | __i915_active_fence_set(struct i915_active_fence *active, | 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 | struct dma_fence *prev; | 1031 | struct dma_fence *prev; |
| 1032 | unsigned long flags; | 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 | return fence; | 1051 | return fence; |
| 1036 | 1052 | ||
| 1037 | GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)); | 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 | * Consider that we have two threads arriving (A and B), with | 1056 | * Consider that we have two threads arriving (A and B), with |
| 1041 | * C already resident as the active->fence. | 1057 | * C already resident as the active->fence. |
| 1042 | * | 1058 | * |
| 1043 | * A does the xchg first, and so it sees C or NULL depending | 1059 | * Both A and B have got a reference to C or NULL, depending on the |
| 1044 | * on the timing of the interrupt handler. If it is NULL, the | 1060 | * timing of the interrupt handler. Let's assume that if A has got C |
| 1045 | * previous fence must have been signaled and we know that | 1061 | * then it has locked C first (before B). |
| 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. | ||
| 1054 | * | 1062 | * |
| 1055 | * Note the strong ordering of the timeline also provides consistent | 1063 | * Note the strong ordering of the timeline also provides consistent |
| 1056 | * nesting rules for the fence->lock; the inner lock is always the | 1064 | * nesting rules for the fence->lock; the inner lock is always the |
| 1057 | * older lock. | 1065 | * older lock. |
| 1058 | */ | 1066 | */ |
| 1059 | spin_lock_irqsave(fence->lock, flags); | 1067 | spin_lock_irqsave(fence->lock, flags); |
| 1060 | prev = xchg(__active_fence_slot(active), fence); | 1068 | if (prev) |
| 1061 | if (prev) { | ||
| 1062 | GEM_BUG_ON(prev == fence); | ||
| 1063 | spin_lock_nested(prev->lock, SINGLE_DEPTH_NESTING); | 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 | __list_del_entry(&active->cb.node); | 1109 | __list_del_entry(&active->cb.node); |
| 1065 | spin_unlock(prev->lock); /* serialise with prev->cb_list */ | 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 | int err = 0; | 1122 | int err = 0; |
| 1078 | 1123 | ||
| 1079 | /* Must maintain timeline ordering wrt previous active requests */ | 1124 | /* Must maintain timeline ordering wrt previous active requests */ |
| 1080 | rcu_read_lock(); | ||
| 1081 | fence = __i915_active_fence_set(active, &rq->fence); | 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 | if (fence) { | 1126 | if (fence) { |
| 1086 | err = i915_request_await_dma_fence(rq, fence); | 1127 | err = i915_request_await_dma_fence(rq, fence); |
| 1087 | dma_fence_put(fence); | 1128 | dma_fence_put(fence); |
| @@ -1661,6 +1661,11 @@ __i915_request_ensure_parallel_ordering(struct i915_request *rq, · 1660 unmodified lines | |||
| 1661 | 1661 | ||
| 1662 | request_to_parent(rq)->parallel.last_rq = i915_request_get(rq); | 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 | return to_request(__i915_active_fence_set(&timeline->last_request, | 1669 | return to_request(__i915_active_fence_set(&timeline->last_request, |
| 1665 | &rq->fence)); | 1670 | &rq->fence)); |
| 1666 | } | 1671 | } |
| @@ -1707,6 +1712,10 @@ __i915_request_ensure_ordering(struct i915_request *rq, · 40 unmodified lines | |||
| 1707 | 0); | 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 | return prev; | 1719 | return prev; |
| 1711 | } | 1720 | } |
| 1712 | 1721 | ||
| @@ -1760,6 +1769,8 @@ __i915_request_add_to_timeline(struct i915_request *rq) · 47 unmodified lines | |||
| 1760 | prev = __i915_request_ensure_ordering(rq, timeline); | 1769 | prev = __i915_request_ensure_ordering(rq, timeline); |
| 1761 | else | 1770 | else |
| 1762 | prev = __i915_request_ensure_parallel_ordering(rq, timeline); | 1771 | prev = __i915_request_ensure_parallel_ordering(rq, timeline); |
| 1772 | if (prev) | ||
| 1773 | i915_request_put(prev); | ||
| 1763 | 1774 | ||
| 1764 | /* | 1775 | /* |
| 1765 | * Make sure that no request gazumped us - if it was allocated after | 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 | dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n", | 310 | dev_warn(ipu_crtc->dev, "8-pixel align hactive %d -> %d\n", |
| 311 | sig_cfg.mode.hactive, new_hactive); | 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 | sig_cfg.mode.hactive = new_hactive; | 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 | /* Determine display colour depth for everything except LVDS now, | 967 | /* Determine display colour depth for everything except LVDS now, |
| 968 | * DP requires this before mode_valid() is called. | 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 | nouveau_connector_detect_depth(connector); | 971 | nouveau_connector_detect_depth(connector); |
| 972 | 972 | ||
| 973 | /* Find the native mode if this is a digital panel, if we didn't | 973 | /* Find the native mode if this is a digital panel, if we didn't |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | |||
| 26 | #include "head.h" | 26 | #include "head.h" |
| 27 | #include "ior.h" | 27 | #include "ior.h" |
| 28 | 28 | ||
| 29 | #include <drm/display/drm_dp.h> | ||
| 30 | |||
| 29 | #include <subdev/bios.h> | 31 | #include <subdev/bios.h> |
| 30 | #include <subdev/bios/init.h> | 32 | #include <subdev/bios/init.h> |
| 31 | #include <subdev/gpio.h> | 33 | #include <subdev/gpio.h> |
| @@ -634,6 +636,50 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp) · 602 unmodified lines | |||
| 634 | return outp->dp.rates != 0; | 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 | void | 683 | void |
| 638 | nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr) | 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 | memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr)); | 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 | const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 }; | 739 | const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 }; |
| 694 | const u8 *rate; | 740 | const u8 *rate; |
| 695 | int rate_max; | 741 | int rate_max; |
| @@ -117,6 +117,7 @@ void gk104_grctx_generate_r418800(struct gf100_gr *); · 116 unmodified lines | |||
| 117 | 117 | ||
| 118 | extern const struct gf100_grctx_func gk110_grctx; | 118 | extern const struct gf100_grctx_func gk110_grctx; |
| 119 | void gk110_grctx_generate_r419eb0(struct gf100_gr *); | 119 | void gk110_grctx_generate_r419eb0(struct gf100_gr *); |
| 120 | void gk110_grctx_generate_r419f78(struct gf100_gr *); | ||
| 120 | 121 | ||
| 121 | extern const struct gf100_grctx_func gk110b_grctx; | 122 | extern const struct gf100_grctx_func gk110b_grctx; |
| 122 | extern const struct gf100_grctx_func gk208_grctx; | 123 | extern const struct gf100_grctx_func gk208_grctx; |
| @@ -906,7 +906,9 @@ static void · 905 unmodified lines | |||
| 906 | gk104_grctx_generate_r419f78(struct gf100_gr *gr) | 906 | gk104_grctx_generate_r419f78(struct gf100_gr *gr) |
| 907 | { | 907 | { |
| 908 | struct nvkm_device *device = gr->base.engine.subdev.device; | 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 | void | 914 | void |
| @@ -820,6 +820,15 @@ gk110_grctx_generate_r419eb0(struct gf100_gr *gr) · 819 unmodified lines | |||
| 820 | nvkm_mask(device, 0x419eb0, 0x00001000, 0x00001000); | 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 | const struct gf100_grctx_func | 832 | const struct gf100_grctx_func |
| 824 | gk110_grctx = { | 833 | gk110_grctx = { |
| 825 | .main = gf100_grctx_generate_main, | 834 | .main = gf100_grctx_generate_main, |
| @@ -854,4 +863,5 @@ gk110_grctx = { · 28 unmodified lines | |||
| 854 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, | 863 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, |
| 855 | .r418800 = gk104_grctx_generate_r418800, | 864 | .r418800 = gk104_grctx_generate_r418800, |
| 856 | .r419eb0 = gk110_grctx_generate_r419eb0, | 865 | .r419eb0 = gk110_grctx_generate_r419eb0, |
| 866 | .r419f78 = gk110_grctx_generate_r419f78, | ||
| 857 | }; | 867 | }; |
| @@ -103,4 +103,5 @@ gk110b_grctx = { · 102 unmodified lines | |||
| 103 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, | 103 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, |
| 104 | .r418800 = gk104_grctx_generate_r418800, | 104 | .r418800 = gk104_grctx_generate_r418800, |
| 105 | .r419eb0 = gk110_grctx_generate_r419eb0, | 105 | .r419eb0 = gk110_grctx_generate_r419eb0, |
| 106 | .r419f78 = gk110_grctx_generate_r419f78, | ||
| 106 | }; | 107 | }; |
| @@ -568,4 +568,5 @@ gk208_grctx = { · 567 unmodified lines | |||
| 568 | .dist_skip_table = gf117_grctx_generate_dist_skip_table, | 568 | .dist_skip_table = gf117_grctx_generate_dist_skip_table, |
| 569 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, | 569 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, |
| 570 | .r418800 = gk104_grctx_generate_r418800, | 570 | .r418800 = gk104_grctx_generate_r418800, |
| 571 | .r419f78 = gk110_grctx_generate_r419f78, | ||
| 571 | }; | 572 | }; |
| @@ -988,4 +988,5 @@ gm107_grctx = { · 987 unmodified lines | |||
| 988 | .r406500 = gm107_grctx_generate_r406500, | 988 | .r406500 = gm107_grctx_generate_r406500, |
| 989 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, | 989 | .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, |
| 990 | .r419e00 = gm107_grctx_generate_r419e00, | 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 | return gk20a_gr_av_to_init_(blob, 64, 0x00100000, ppack); | 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 | static const struct gf100_gr_fwif | 209 | static const struct gf100_gr_fwif |
| 223 | tu102_gr_fwif[] = { | 210 | tu102_gr_fwif[] = { |
| 224 | { 0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr }, | 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 | { /* sentinel */ } | 570 | { /* sentinel */ } |
| 571 | }; | 571 | }; |
| 572 | MODULE_DEVICE_TABLE(of, s6d7aa0_of_match); | ||
| 572 | 573 | ||
| 573 | static struct mipi_dsi_driver s6d7aa0_driver = { | 574 | static struct mipi_dsi_driver s6d7aa0_driver = { |
| 574 | .probe = s6d7aa0_probe, | 575 | .probe = s6d7aa0_probe, |
| @@ -833,12 +833,12 @@ static int vop_plane_atomic_check(struct drm_plane *plane, · 832 unmodified lines | |||
| 833 | * need align with 2 pixel. | 833 | * need align with 2 pixel. |
| 834 | */ | 834 | */ |
| 835 | if (fb->format->is_yuv && ((new_plane_state->src.x1 >> 16) % 2)) { | 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 | return -EINVAL; | 837 | return -EINVAL; |
| 838 | } | 838 | } |
| 839 | 839 | ||
| 840 | if (fb->format->is_yuv && new_plane_state->rotation & DRM_MODE_REFLECT_Y) { | 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 | return -EINVAL; | 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 | struct vop *vop = to_vop(crtc); | 846 | struct vop *vop = to_vop(crtc); |
| 847 | 847 | ||
| 848 | if (!vop->data->afbc) { | 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 | return -EINVAL; | 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 | return ret; | 855 | return ret; |
| 856 | 856 | ||
| 857 | if (new_plane_state->src.x1 || new_plane_state->src.y1) { | 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", | 858 | DRM_DEBUG_KMS("AFBC does not support offset display, " \ |
| 859 | new_plane_state->src.x1, | 859 | "xpos=%d, ypos=%d, offset=%d\n", |
| 860 | new_plane_state->src.y1, fb->offsets[0]); | 860 | new_plane_state->src.x1, new_plane_state->src.y1, |
| 861 | fb->offsets[0]); | ||
| 861 | return -EINVAL; | 862 | return -EINVAL; |
| 862 | } | 863 | } |
| 863 | 864 | ||
| 864 | if (new_plane_state->rotation && new_plane_state->rotation != DRM_MODE_ROTATE_0) { | 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 | DRM_DEBUG_KMS("No rotation support in AFBC, rotation=%d\n", |
| 866 | new_plane_state->rotation); | 867 | new_plane_state->rotation); |
| 867 | return -EINVAL; | 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 | if (bo->pin_count) { | 520 | if (bo->pin_count) { |
| 521 | *locked = false; | 521 | *locked = false; |
| 522 | *busy = false; | 522 | if (busy) |
| 523 | *busy = false; | ||
| 523 | return false; | 524 | return false; |
| 524 | } | 525 | } |
| 525 | 526 | ||
| @@ -209,8 +209,7 @@ int vmbus_connect(void) · 208 unmodified lines | |||
| 209 | * Setup the vmbus event connection for channel interrupt | 209 | * Setup the vmbus event connection for channel interrupt |
| 210 | * abstraction stuff | 210 | * abstraction stuff |
| 211 | */ | 211 | */ |
| 212 | vmbus_connection.int_page = | 212 | vmbus_connection.int_page = hv_alloc_hyperv_zeroed_page(); |
| 213 | (void *)hv_alloc_hyperv_zeroed_page(); | ||
| 214 | if (vmbus_connection.int_page == NULL) { | 213 | if (vmbus_connection.int_page == NULL) { |
| 215 | ret = -ENOMEM; | 214 | ret = -ENOMEM; |
| 216 | goto cleanup; | 215 | goto cleanup; |
| @@ -225,8 +224,8 @@ int vmbus_connect(void) · 8 unmodified lines | |||
| 225 | * Setup the monitor notification facility. The 1st page for | 224 | * Setup the monitor notification facility. The 1st page for |
| 226 | * parent->child and the 2nd page for child->parent | 225 | * parent->child and the 2nd page for child->parent |
| 227 | */ | 226 | */ |
| 228 | vmbus_connection.monitor_pages[0] = (void *)hv_alloc_hyperv_page(); | 227 | vmbus_connection.monitor_pages[0] = hv_alloc_hyperv_page(); |
| 229 | vmbus_connection.monitor_pages[1] = (void *)hv_alloc_hyperv_page(); | 228 | vmbus_connection.monitor_pages[1] = hv_alloc_hyperv_page(); |
| 230 | if ((vmbus_connection.monitor_pages[0] == NULL) || | 229 | if ((vmbus_connection.monitor_pages[0] == NULL) || |
| 231 | (vmbus_connection.monitor_pages[1] == NULL)) { | 230 | (vmbus_connection.monitor_pages[1] == NULL)) { |
| 232 | ret = -ENOMEM; | 231 | ret = -ENOMEM; |
| @@ -333,15 +332,15 @@ void vmbus_disconnect(void) · 100 unmodified lines | |||
| 333 | destroy_workqueue(vmbus_connection.work_queue); | 332 | destroy_workqueue(vmbus_connection.work_queue); |
| 334 | 333 | ||
| 335 | if (vmbus_connection.int_page) { | 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 | vmbus_connection.int_page = NULL; | 336 | vmbus_connection.int_page = NULL; |
| 338 | } | 337 | } |
| 339 | 338 | ||
| 340 | set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1); | 339 | set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1); |
| 341 | set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1); | 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]); | 342 | hv_free_hyperv_page(vmbus_connection.monitor_pages[0]); |
| 344 | hv_free_hyperv_page((unsigned long)vmbus_connection.monitor_pages[1]); | 343 | hv_free_hyperv_page(vmbus_connection.monitor_pages[1]); |
| 345 | vmbus_connection.monitor_pages[0] = NULL; | 344 | vmbus_connection.monitor_pages[0] = NULL; |
| 346 | vmbus_connection.monitor_pages[1] = NULL; | 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 | WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES); | 1628 | WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES); |
| 1629 | WARN_ON_ONCE(sgl->length < (HV_HYP_PAGE_SIZE << page_reporting_order)); | 1629 | WARN_ON_ONCE(sgl->length < (HV_HYP_PAGE_SIZE << page_reporting_order)); |
| 1630 | local_irq_save(flags); | 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 | if (!hint) { | 1632 | if (!hint) { |
| 1633 | local_irq_restore(flags); | 1633 | local_irq_restore(flags); |
| 1634 | return -ENOSPC; | 1634 | return -ENOSPC; |
| @@ -115,12 +115,12 @@ void *hv_alloc_hyperv_zeroed_page(void) · 114 unmodified lines | |||
| 115 | } | 115 | } |
| 116 | EXPORT_SYMBOL_GPL(hv_alloc_hyperv_zeroed_page); | 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 | if (PAGE_SIZE == HV_HYP_PAGE_SIZE) | 120 | if (PAGE_SIZE == HV_HYP_PAGE_SIZE) |
| 121 | free_page(addr); | 121 | free_page((unsigned long)addr); |
| 122 | else | 122 | else |
| 123 | kfree((void *)addr); | 123 | kfree(addr); |
| 124 | } | 124 | } |
| 125 | EXPORT_SYMBOL_GPL(hv_free_hyperv_page); | 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 | atomic_notifier_chain_unregister(&panic_notifier_list, | 253 | atomic_notifier_chain_unregister(&panic_notifier_list, |
| 254 | &hyperv_panic_report_block); | 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 | hv_panic_page = NULL; | 257 | hv_panic_page = NULL; |
| 258 | } | 258 | } |
| 259 | 259 | ||
| @@ -270,7 +270,7 @@ static void hv_kmsg_dump_register(void) · 10 unmodified lines | |||
| 270 | ret = kmsg_dump_register(&hv_kmsg_dumper); | 270 | ret = kmsg_dump_register(&hv_kmsg_dumper); |
| 271 | if (ret) { | 271 | if (ret) { |
| 272 | pr_err("Hyper-V: kmsg dump register error 0x%x\n", ret); | 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 | hv_panic_page = NULL; | 274 | hv_panic_page = NULL; |
| 275 | } | 275 | } |
| 276 | } | 276 | } |
| @@ -13,9 +13,11 @@ · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | #include <linux/crc16.h> | 14 | #include <linux/crc16.h> |
| 15 | #include <linux/debugfs.h> | 15 | #include <linux/debugfs.h> |
| 16 | #include <linux/delay.h> | ||
| 16 | #include <linux/hid.h> | 17 | #include <linux/hid.h> |
| 17 | #include <linux/hwmon.h> | 18 | #include <linux/hwmon.h> |
| 18 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
| 20 | #include <linux/ktime.h> | ||
| 19 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 20 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
| 21 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
| @@ -63,6 +65,8 @@ static const char *const aqc_device_names[] = { · 41 unmodified lines | |||
| 63 | #define CTRL_REPORT_ID 0x03 | 65 | #define CTRL_REPORT_ID 0x03 |
| 64 | #define AQUAERO_CTRL_REPORT_ID 0x0b | 66 | #define AQUAERO_CTRL_REPORT_ID 0x0b |
| 65 | 67 | ||
| 68 | #define CTRL_REPORT_DELAY 200 /* ms */ | ||
| 69 | |||
| 66 | /* The HID report that the official software always sends | 70 | /* The HID report that the official software always sends |
| 67 | * after writing values, currently same for all devices | 71 | * after writing values, currently same for all devices |
| 68 | */ | 72 | */ |
| @@ -527,6 +531,9 @@ struct aqc_data { · 458 unmodified lines | |||
| 527 | int secondary_ctrl_report_size; | 531 | int secondary_ctrl_report_size; |
| 528 | u8 *secondary_ctrl_report; | 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 | int buffer_size; | 537 | int buffer_size; |
| 531 | u8 *buffer; | 538 | u8 *buffer; |
| 532 | int checksum_start; | 539 | int checksum_start; |
| @@ -611,17 +618,35 @@ static int aqc_aquastreamxt_convert_fan_rpm(u16 val) · 78 unmodified lines | |||
| 611 | return 0; | 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 | /* Expects the mutex to be locked */ | 635 | /* Expects the mutex to be locked */ |
| 615 | static int aqc_get_ctrl_data(struct aqc_data *priv) | 636 | static int aqc_get_ctrl_data(struct aqc_data *priv) |
| 616 | { | 637 | { |
| 617 | int ret; | 638 | int ret; |
| 618 | 639 | ||
| 640 | aqc_delay_ctrl_report(priv); | ||
| 641 | |||
| 619 | memset(priv->buffer, 0x00, priv->buffer_size); | 642 | memset(priv->buffer, 0x00, priv->buffer_size); |
| 620 | ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size, | 643 | ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size, |
| 621 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | 644 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
| 622 | if (ret < 0) | 645 | if (ret < 0) |
| 623 | ret = -ENODATA; | 646 | ret = -ENODATA; |
| 624 | 647 | ||
| 648 | priv->last_ctrl_report_op = ktime_get(); | ||
| 649 | |||
| 625 | return ret; | 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 | int ret; | 656 | int ret; |
| 632 | u16 checksum; | 657 | u16 checksum; |
| 633 | 658 | ||
| 659 | aqc_delay_ctrl_report(priv); | ||
| 660 | |||
| 634 | /* Checksum is not needed for Aquaero */ | 661 | /* Checksum is not needed for Aquaero */ |
| 635 | if (priv->kind != aquaero) { | 662 | if (priv->kind != aquaero) { |
| 636 | /* Init and xorout value for CRC-16/USB is 0xffff */ | 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 | ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size, | 673 | ret = hid_hw_raw_request(priv->hdev, priv->ctrl_report_id, priv->buffer, priv->buffer_size, |
| 647 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); | 674 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); |
| 648 | if (ret < 0) | 675 | if (ret < 0) |
| 649 | return ret; | 676 | goto record_access_and_ret; |
| 650 | 677 | ||
| 651 | /* The official software sends this report after every change, so do it here as well */ | 678 | /* The official software sends this report after every change, so do it here as well */ |
| 652 | ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id, | 679 | ret = hid_hw_raw_request(priv->hdev, priv->secondary_ctrl_report_id, |
| 653 | priv->secondary_ctrl_report, priv->secondary_ctrl_report_size, | 680 | priv->secondary_ctrl_report, priv->secondary_ctrl_report_size, |
| 654 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); | 681 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); |
| 682 | |||
| 683 | record_access_and_ret: | ||
| 684 | priv->last_ctrl_report_op = ktime_get(); | ||
| 685 | |||
| 655 | return ret; | 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 | priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE; | 1556 | priv->buffer_size = AQUAERO_CTRL_REPORT_SIZE; |
| 1526 | priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET; | 1557 | priv->temp_ctrl_offset = AQUAERO_TEMP_CTRL_OFFSET; |
| 1558 | priv->ctrl_report_delay = CTRL_REPORT_DELAY; | ||
| 1527 | 1559 | ||
| 1528 | priv->temp_label = label_temp_sensors; | 1560 | priv->temp_label = label_temp_sensors; |
| 1529 | priv->virtual_temp_label = label_virtual_temp_sensors; | 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 | priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET; | 1579 | priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET; |
| 1548 | 1580 | ||
| 1549 | priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE; | 1581 | priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE; |
| 1582 | priv->ctrl_report_delay = CTRL_REPORT_DELAY; | ||
| 1550 | 1583 | ||
| 1551 | priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES; | 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 | priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET; | 1630 | priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET; |
| 1598 | 1631 | ||
| 1599 | priv->buffer_size = OCTO_CTRL_REPORT_SIZE; | 1632 | priv->buffer_size = OCTO_CTRL_REPORT_SIZE; |
| 1633 | priv->ctrl_report_delay = CTRL_REPORT_DELAY; | ||
| 1600 | 1634 | ||
| 1601 | priv->power_cycle_count_offset = OCTO_POWER_CYCLES; | 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 | priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET; | 1658 | priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET; |
| 1625 | 1659 | ||
| 1626 | priv->buffer_size = QUADRO_CTRL_REPORT_SIZE; | 1660 | priv->buffer_size = QUADRO_CTRL_REPORT_SIZE; |
| 1661 | priv->ctrl_report_delay = CTRL_REPORT_DELAY; | ||
| 1627 | 1662 | ||
| 1628 | priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET; | 1663 | priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET; |
| 1629 | priv->power_cycle_count_offset = QUADRO_POWER_CYCLES; | 1664 | priv->power_cycle_count_offset = QUADRO_POWER_CYCLES; |
| @@ -17,12 +17,13 @@ · 16 unmodified lines | |||
| 17 | enum chips {pfe1100, pfe3000}; | 17 | enum chips {pfe1100, pfe3000}; |
| 18 | 18 | ||
| 19 | /* | 19 | /* |
| 20 | * Disable status check for pfe3000 devices, because some devices report | 20 | * Disable status check because some devices report communication error |
| 21 | * communication error (invalid command) for VOUT_MODE command (0x20) | 21 | * (invalid command) for VOUT_MODE command (0x20) although the correct |
| 22 | * although correct VOUT_MODE (0x16) is returned: it leads to incorrect | 22 | * VOUT_MODE (0x16) is returned: it leads to incorrect exponent in linear |
| 23 | * exponent in linear mode. | 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 | .flags = PMBUS_SKIP_STATUS_CHECK, | 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 | int model; | 95 | int model; |
| 95 | 96 | ||
| 96 | model = (int)i2c_match_id(pfe_device_id, client)->driver_data; | 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 | * PFE3000-12-069RA devices may not stay in page 0 during device | 101 | * PFE3000-12-069RA devices may not stay in page 0 during device |
| 100 | * probe which leads to probe failure (read status word failed). | 102 | * probe which leads to probe failure (read status word failed). |
| 101 | * So let's set the device to page 0 at the beginning. | 103 | * So let's set the device to page 0 at the beginning. |
| 102 | */ | 104 | */ |
| 103 | if (model == pfe3000) { | 105 | if (model == pfe3000) |
| 104 | client->dev.platform_data = &pfe3000_plat_data; | ||
| 105 | i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0); | 106 | i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0); |
| 106 | } | ||
| 107 | 107 | ||
| 108 | return pmbus_do_probe(client, &pfe_driver_info[model]); | 108 | return pmbus_do_probe(client, &pfe_driver_info[model]); |
| 109 | } | 109 | } |
| @@ -62,7 +62,6 @@ · 61 unmodified lines | |||
| 62 | #define AD7192_MODE_STA_MASK BIT(20) /* Status Register transmission Mask */ | 62 | #define AD7192_MODE_STA_MASK BIT(20) /* Status Register transmission Mask */ |
| 63 | #define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */ | 63 | #define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */ |
| 64 | #define AD7192_MODE_SINC3 BIT(15) /* SINC3 Filter Select */ | 64 | #define AD7192_MODE_SINC3 BIT(15) /* SINC3 Filter Select */ |
| 65 | #define AD7192_MODE_ACX BIT(14) /* AC excitation enable(AD7195 only)*/ | ||
| 66 | #define AD7192_MODE_ENPAR BIT(13) /* Parity Enable */ | 65 | #define AD7192_MODE_ENPAR BIT(13) /* Parity Enable */ |
| 67 | #define AD7192_MODE_CLKDIV BIT(12) /* Clock divide by 2 (AD7190/2 only)*/ | 66 | #define AD7192_MODE_CLKDIV BIT(12) /* Clock divide by 2 (AD7190/2 only)*/ |
| 68 | #define AD7192_MODE_SCYCLE BIT(11) /* Single cycle conversion */ | 67 | #define AD7192_MODE_SCYCLE BIT(11) /* Single cycle conversion */ |
| @@ -91,6 +90,7 @@ · 22 unmodified lines | |||
| 91 | /* Configuration Register Bit Designations (AD7192_REG_CONF) */ | 90 | /* Configuration Register Bit Designations (AD7192_REG_CONF) */ |
| 92 | 91 | ||
| 93 | #define AD7192_CONF_CHOP BIT(23) /* CHOP enable */ | 92 | #define AD7192_CONF_CHOP BIT(23) /* CHOP enable */ |
| 93 | #define AD7192_CONF_ACX BIT(22) /* AC excitation enable(AD7195 only) */ | ||
| 94 | #define AD7192_CONF_REFSEL BIT(20) /* REFIN1/REFIN2 Reference Select */ | 94 | #define AD7192_CONF_REFSEL BIT(20) /* REFIN1/REFIN2 Reference Select */ |
| 95 | #define AD7192_CONF_CHAN(x) ((x) << 8) /* Channel select */ | 95 | #define AD7192_CONF_CHAN(x) ((x) << 8) /* Channel select */ |
| 96 | #define AD7192_CONF_CHAN_MASK (0x7FF << 8) /* Channel select mask */ | 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 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 472 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
| 473 | struct ad7192_state *st = iio_priv(indio_dev); | 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 | static ssize_t ad7192_show_bridge_switch(struct device *dev, | 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 | ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon); | 514 | ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon); |
| 515 | break; | 515 | break; |
| 516 | case AD7192_REG_MODE: | 516 | case AD7192_REG_CONF: |
| 517 | if (val) | 517 | if (val) |
| 518 | st->mode |= AD7192_MODE_ACX; | 518 | st->conf |= AD7192_CONF_ACX; |
| 519 | else | 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 | break; | 523 | break; |
| 524 | default: | 524 | default: |
| 525 | ret = -EINVAL; | 525 | ret = -EINVAL; |
| @@ -579,12 +579,11 @@ static IIO_DEVICE_ATTR(bridge_switch_en, 0644, · 53 unmodified lines | |||
| 579 | 579 | ||
| 580 | static IIO_DEVICE_ATTR(ac_excitation_en, 0644, | 580 | static IIO_DEVICE_ATTR(ac_excitation_en, 0644, |
| 581 | ad7192_show_ac_excitation, ad7192_set, | 581 | ad7192_show_ac_excitation, ad7192_set, |
| 582 | AD7192_REG_MODE); | 582 | AD7192_REG_CONF); |
| 583 | 583 | ||
| 584 | static struct attribute *ad7192_attributes[] = { | 584 | static struct attribute *ad7192_attributes[] = { |
| 585 | &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, | 585 | &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, |
| 586 | &iio_dev_attr_bridge_switch_en.dev_attr.attr, | 586 | &iio_dev_attr_bridge_switch_en.dev_attr.attr, |
| 587 | &iio_dev_attr_ac_excitation_en.dev_attr.attr, | ||
| 588 | NULL | 587 | NULL |
| 589 | }; | 588 | }; |
| 590 | 589 | ||
| @@ -595,6 +594,7 @@ static const struct attribute_group ad7192_attribute_group = { · 4 unmodified lines | |||
| 595 | static struct attribute *ad7195_attributes[] = { | 594 | static struct attribute *ad7195_attributes[] = { |
| 596 | &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, | 595 | &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, |
| 597 | &iio_dev_attr_bridge_switch_en.dev_attr.attr, | 596 | &iio_dev_attr_bridge_switch_en.dev_attr.attr, |
| 597 | &iio_dev_attr_ac_excitation_en.dev_attr.attr, | ||
| 598 | NULL | 598 | NULL |
| 599 | }; | 599 | }; |
| 600 | 600 | ||
| @@ -124,6 +124,7 @@ static const struct regmap_config ina2xx_regmap_config = { · 123 unmodified lines | |||
| 124 | enum ina2xx_ids { ina219, ina226 }; | 124 | enum ina2xx_ids { ina219, ina226 }; |
| 125 | 125 | ||
| 126 | struct ina2xx_config { | 126 | struct ina2xx_config { |
| 127 | const char *name; | ||
| 127 | u16 config_default; | 128 | u16 config_default; |
| 128 | int calibration_value; | 129 | int calibration_value; |
| 129 | int shunt_voltage_lsb; /* nV */ | 130 | int shunt_voltage_lsb; /* nV */ |
| @@ -155,6 +156,7 @@ struct ina2xx_chip_info { · 25 unmodified lines | |||
| 155 | 156 | ||
| 156 | static const struct ina2xx_config ina2xx_config[] = { | 157 | static const struct ina2xx_config ina2xx_config[] = { |
| 157 | [ina219] = { | 158 | [ina219] = { |
| 159 | .name = "ina219", | ||
| 158 | .config_default = INA219_CONFIG_DEFAULT, | 160 | .config_default = INA219_CONFIG_DEFAULT, |
| 159 | .calibration_value = 4096, | 161 | .calibration_value = 4096, |
| 160 | .shunt_voltage_lsb = 10000, | 162 | .shunt_voltage_lsb = 10000, |
| @@ -164,6 +166,7 @@ static const struct ina2xx_config ina2xx_config[] = { · 3 unmodified lines | |||
| 164 | .chip_id = ina219, | 166 | .chip_id = ina219, |
| 165 | }, | 167 | }, |
| 166 | [ina226] = { | 168 | [ina226] = { |
| 169 | .name = "ina226", | ||
| 167 | .config_default = INA226_CONFIG_DEFAULT, | 170 | .config_default = INA226_CONFIG_DEFAULT, |
| 168 | .calibration_value = 2048, | 171 | .calibration_value = 2048, |
| 169 | .shunt_voltage_lsb = 2500, | 172 | .shunt_voltage_lsb = 2500, |
| @@ -996,7 +999,7 @@ static int ina2xx_probe(struct i2c_client *client) · 826 unmodified lines | |||
| 996 | /* Patch the current config register with default. */ | 999 | /* Patch the current config register with default. */ |
| 997 | val = chip->config->config_default; | 1000 | val = chip->config->config_default; |
| 998 | 1001 | ||
| 999 | if (id->driver_data == ina226) { | 1002 | if (type == ina226) { |
| 1000 | ina226_set_average(chip, INA226_DEFAULT_AVG, &val); | 1003 | ina226_set_average(chip, INA226_DEFAULT_AVG, &val); |
| 1001 | ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val); | 1004 | ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val); |
| 1002 | ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val); | 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 | indio_dev->modes = INDIO_DIRECT_MODE; | 1020 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1018 | if (id->driver_data == ina226) { | 1021 | if (type == ina226) { |
| 1019 | indio_dev->channels = ina226_channels; | 1022 | indio_dev->channels = ina226_channels; |
| 1020 | indio_dev->num_channels = ARRAY_SIZE(ina226_channels); | 1023 | indio_dev->num_channels = ARRAY_SIZE(ina226_channels); |
| 1021 | indio_dev->info = &ina226_info; | 1024 | indio_dev->info = &ina226_info; |
| @@ -1024,7 +1027,7 @@ static int ina2xx_probe(struct i2c_client *client) · 2 unmodified lines | |||
| 1024 | indio_dev->num_channels = ARRAY_SIZE(ina219_channels); | 1027 | indio_dev->num_channels = ARRAY_SIZE(ina219_channels); |
| 1025 | indio_dev->info = &ina219_info; | 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 | ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev, | 1032 | ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev, |
| 1030 | &ina2xx_setup_ops); | 1033 | &ina2xx_setup_ops); |
| @@ -916,12 +916,6 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) · 915 unmodified lines | |||
| 916 | goto err_vref; | 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 | regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); | 919 | regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); |
| 926 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, | 920 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, |
| 927 | MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); | 921 | MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); |
| @@ -948,8 +942,6 @@ err_adc_clk: · 20 unmodified lines | |||
| 948 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, | 942 | regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, |
| 949 | MESON_SAR_ADC_REG3_ADC_EN, 0); | 943 | MESON_SAR_ADC_REG3_ADC_EN, 0); |
| 950 | meson_sar_adc_set_bandgap(indio_dev, false); | 944 | meson_sar_adc_set_bandgap(indio_dev, false); |
| 951 | clk_disable_unprepare(priv->core_clk); | ||
| 952 | err_core_clk: | ||
| 953 | regulator_disable(priv->vref); | 945 | regulator_disable(priv->vref); |
| 954 | err_vref: | 946 | err_vref: |
| 955 | meson_sar_adc_unlock(indio_dev); | 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 | meson_sar_adc_set_bandgap(indio_dev, false); | 970 | meson_sar_adc_set_bandgap(indio_dev, false); |
| 979 | 971 | ||
| 980 | clk_disable_unprepare(priv->core_clk); | ||
| 981 | |||
| 982 | regulator_disable(priv->vref); | 972 | regulator_disable(priv->vref); |
| 983 | 973 | ||
| 984 | if (!ret) | 974 | if (!ret) |
| @@ -1211,7 +1201,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev) · 226 unmodified lines | |||
| 1211 | if (IS_ERR(priv->clkin)) | 1201 | if (IS_ERR(priv->clkin)) |
| 1212 | return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n"); | 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 | if (IS_ERR(priv->core_clk)) | 1205 | if (IS_ERR(priv->core_clk)) |
| 1216 | return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n"); | 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 | static int meson_sar_adc_suspend(struct device *dev) | 1284 | static int meson_sar_adc_suspend(struct device *dev) |
| 1295 | { | 1285 | { |
| 1296 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | 1286 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
| 1287 | struct meson_sar_adc_priv *priv = iio_priv(indio_dev); | ||
| 1297 | 1288 | ||
| 1298 | meson_sar_adc_hw_disable(indio_dev); | 1289 | meson_sar_adc_hw_disable(indio_dev); |
| 1299 | 1290 | ||
| 1291 | clk_disable_unprepare(priv->core_clk); | ||
| 1292 | |||
| 1300 | return 0; | 1293 | return 0; |
| 1301 | } | 1294 | } |
| 1302 | 1295 | ||
| 1303 | static int meson_sar_adc_resume(struct device *dev) | 1296 | static int meson_sar_adc_resume(struct device *dev) |
| 1304 | { | 1297 | { |
| 1305 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | 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 | return meson_sar_adc_hw_enable(indio_dev); | 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 | platform_set_drvdata(pdev, indio_dev); | 253 | platform_set_drvdata(pdev, indio_dev); |
| 254 | 254 | ||
| 255 | state->ec = ec->ec_dev; | 255 | state->ec = ec->ec_dev; |
| 256 | state->msg = devm_kzalloc(&pdev->dev, | 256 | state->msg = devm_kzalloc(&pdev->dev, sizeof(*state->msg) + |
| 257 | max((u16)sizeof(struct ec_params_motion_sense), | 257 | max((u16)sizeof(struct ec_params_motion_sense), |
| 258 | state->ec->max_response), GFP_KERNEL); | 258 | state->ec->max_response), GFP_KERNEL); |
| 259 | if (!state->msg) | 259 | if (!state->msg) |
| @@ -344,9 +344,12 @@ static int admv1013_update_quad_filters(struct admv1013_state *st) · 343 unmodified lines | |||
| 344 | 344 | ||
| 345 | static int admv1013_update_mixer_vgate(struct admv1013_state *st) | 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 | vcm = regulator_get_voltage(st->reg); | 350 | vcm = regulator_get_voltage(st->reg); |
| 351 | if (vcm < 0) | ||
| 352 | return vcm; | ||
| 350 | 353 | ||
| 351 | if (vcm < 1800000) | 354 | if (vcm < 1800000) |
| 352 | mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100; | 355 | mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100; |
| @@ -2687,7 +2687,7 @@ unknown_format: · 2686 unmodified lines | |||
| 2687 | static int lsm6dsx_get_acpi_mount_matrix(struct device *dev, | 2687 | static int lsm6dsx_get_acpi_mount_matrix(struct device *dev, |
| 2688 | struct iio_mount_matrix *orientation) | 2688 | struct iio_mount_matrix *orientation) |
| 2689 | { | 2689 | { |
| 2690 | return false; | 2690 | return -EOPNOTSUPP; |
| 2691 | } | 2691 | } |
| 2692 | 2692 | ||
| 2693 | #endif | 2693 | #endif |
| @@ -1888,7 +1888,7 @@ static const struct iio_buffer_setup_ops noop_ring_setup_ops; · 1887 unmodified lines | |||
| 1888 | int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) | 1888 | int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) |
| 1889 | { | 1889 | { |
| 1890 | struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); | 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 | int ret; | 1892 | int ret; |
| 1893 | 1893 | ||
| 1894 | if (!indio_dev->info) | 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 | /* If the calling driver did not initialize firmware node, do it here */ | 1899 | /* If the calling driver did not initialize firmware node, do it here */ |
| 1900 | if (dev_fwnode(&indio_dev->dev)) | 1900 | if (dev_fwnode(&indio_dev->dev)) |
| 1901 | fwnode = dev_fwnode(&indio_dev->dev); | 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 | fwnode = dev_fwnode(indio_dev->dev.parent); | 1904 | fwnode = dev_fwnode(indio_dev->dev.parent); |
| 1904 | device_set_node(&indio_dev->dev, fwnode); | 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 | .address = BU27008_REG_##data##_LO, \ | 190 | .address = BU27008_REG_##data##_LO, \ |
| 191 | .scan_index = BU27008_##color, \ | 191 | .scan_index = BU27008_##color, \ |
| 192 | .scan_type = { \ | 192 | .scan_type = { \ |
| 193 | .sign = 's', \ | 193 | .sign = 'u', \ |
| 194 | .realbits = 16, \ | 194 | .realbits = 16, \ |
| 195 | .storagebits = 16, \ | 195 | .storagebits = 16, \ |
| 196 | .endianness = IIO_LE, \ | 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 | for (i = 0; i < data->gts.num_itime; i++) { | 633 | for (i = 0; i < data->gts.num_itime; i++) { |
| 634 | new_time_sel = data->gts.itime_table[i].sel; | 634 | new_time_sel = data->gts.itime_table[i].sel; |
| 635 | ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, | 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 | if (!ret) | 637 | if (!ret) |
| 638 | break; | 638 | break; |
| 639 | } | 639 | } |
| @@ -662,7 +662,7 @@ static int bu27008_set_scale(struct bu27008_data *data, · 22 unmodified lines | |||
| 662 | goto unlock_out; | 662 | goto unlock_out; |
| 663 | 663 | ||
| 664 | ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel, | 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 | if (ret) { | 666 | if (ret) { |
| 667 | ret = bu27008_try_find_new_time_gain(data, val, val2, &gain_sel); | 667 | ret = bu27008_try_find_new_time_gain(data, val, val2, &gain_sel); |
| 668 | if (ret) | 668 | if (ret) |
| @@ -677,6 +677,21 @@ unlock_out: · 8 unmodified lines | |||
| 677 | return ret; | 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 | static int bu27008_write_raw(struct iio_dev *idev, | 695 | static int bu27008_write_raw(struct iio_dev *idev, |
| 681 | struct iio_chan_spec const *chan, | 696 | struct iio_chan_spec const *chan, |
| 682 | int val, int val2, long mask) | 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 | static const struct iio_info bu27008_info = { | 771 | static const struct iio_info bu27008_info = { |
| 757 | .read_raw = &bu27008_read_raw, | 772 | .read_raw = &bu27008_read_raw, |
| 758 | .write_raw = &bu27008_write_raw, | 773 | .write_raw = &bu27008_write_raw, |
| 774 | .write_raw_get_fmt = &bu27008_write_raw_get_fmt, | ||
| 759 | .read_avail = &bu27008_read_avail, | 775 | .read_avail = &bu27008_read_avail, |
| 760 | .update_scan_mode = bu27008_update_scan_mode, | 776 | .update_scan_mode = bu27008_update_scan_mode, |
| 761 | .validate_trigger = iio_validate_own_trigger, | 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 | return -EINVAL; | 575 | return -EINVAL; |
| 576 | 576 | ||
| 577 | if (chan == BU27034_CHAN_ALS) { | 577 | if (chan == BU27034_CHAN_ALS) { |
| 578 | if (val == 0 && val2 == 1000) | 578 | if (val == 0 && val2 == 1000000) |
| 579 | return 0; | 579 | return 0; |
| 580 | 580 | ||
| 581 | return -EINVAL; | 581 | return -EINVAL; |
| @@ -587,7 +587,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan, · 5 unmodified lines | |||
| 587 | goto unlock_out; | 587 | goto unlock_out; |
| 588 | 588 | ||
| 589 | ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel, | 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 | if (ret) { | 591 | if (ret) { |
| 592 | /* | 592 | /* |
| 593 | * Could not support scale with given time. Need to change time. | 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 | /* Can we provide requested scale with this time? */ | 625 | /* Can we provide requested scale with this time? */ |
| 626 | ret = iio_gts_find_gain_sel_for_scale_using_time( | 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 | &gain_sel); | 628 | &gain_sel); |
| 629 | if (ret) | 629 | if (ret) |
| 630 | continue; | 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 | static int bu27034_write_raw(struct iio_dev *idev, | 1235 | static int bu27034_write_raw(struct iio_dev *idev, |
| 1221 | struct iio_chan_spec const *chan, | 1236 | struct iio_chan_spec const *chan, |
| 1222 | int val, int val2, long mask) | 1237 | int val, int val2, long mask) |
| @@ -1267,6 +1282,7 @@ static int bu27034_read_avail(struct iio_dev *idev, · 44 unmodified lines | |||
| 1267 | static const struct iio_info bu27034_info = { | 1282 | static const struct iio_info bu27034_info = { |
| 1268 | .read_raw = &bu27034_read_raw, | 1283 | .read_raw = &bu27034_read_raw, |
| 1269 | .write_raw = &bu27034_write_raw, | 1284 | .write_raw = &bu27034_write_raw, |
| 1285 | .write_raw_get_fmt = &bu27034_write_raw_get_fmt, | ||
| 1270 | .read_avail = &bu27034_read_avail, | 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 | dma_addr_t mask; | 85 | dma_addr_t mask; |
| 86 | int i; | 86 | int i; |
| 87 | 87 | ||
| 88 | umem->iova = va = virt; | ||
| 89 | |||
| 88 | if (umem->is_odp) { | 90 | if (umem->is_odp) { |
| 89 | unsigned int page_size = BIT(to_ib_umem_odp(umem)->page_shift); | 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 | pgsz_bitmap &= GENMASK(BITS_PER_LONG - 1, PAGE_SHIFT); | 103 | pgsz_bitmap &= GENMASK(BITS_PER_LONG - 1, PAGE_SHIFT); |
| 102 | 104 | ||
| 103 | umem->iova = va = virt; | ||
| 104 | /* The best result is the smallest page size that results in the minimum | 105 | /* The best result is the smallest page size that results in the minimum |
| 105 | * number of required pages. Compute the largest page size that could | 106 | * number of required pages. Compute the largest page size that could |
| 106 | * work based on VA address bits that don't change. | 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 | rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode); | 1254 | rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode); |
| 1255 | if (rc) { | 1255 | if (rc) { |
| 1256 | bnxt_unregister_dev(rdev->en_dev); | ||
| 1257 | clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags); | ||
| 1256 | ibdev_err(&rdev->ibdev, "Failed to get chip context\n"); | 1258 | ibdev_err(&rdev->ibdev, "Failed to get chip context\n"); |
| 1257 | return -EINVAL; | 1259 | return -EINVAL; |
| 1258 | } | 1260 | } |
| @@ -1526,8 +1528,8 @@ static void bnxt_re_remove(struct auxiliary_device *adev) · 267 unmodified lines | |||
| 1526 | } | 1528 | } |
| 1527 | bnxt_re_setup_cc(rdev, false); | 1529 | bnxt_re_setup_cc(rdev, false); |
| 1528 | ib_unregister_device(&rdev->ibdev); | 1530 | ib_unregister_device(&rdev->ibdev); |
| 1529 | ib_dealloc_device(&rdev->ibdev); | ||
| 1530 | bnxt_re_dev_uninit(rdev); | 1531 | bnxt_re_dev_uninit(rdev); |
| 1532 | ib_dealloc_device(&rdev->ibdev); | ||
| 1531 | skip_remove: | 1533 | skip_remove: |
| 1532 | mutex_unlock(&bnxt_re_mutex); | 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 | memset((u8 *)dpit->tbl, 0xFF, bytes); | 821 | memset((u8 *)dpit->tbl, 0xFF, bytes); |
| 822 | mutex_init(&res->dpi_tbl_lock); | ||
| 822 | dpit->priv_db = dpit->ucreg.bar_reg + dpit->ucreg.offset; | 823 | dpit->priv_db = dpit->ucreg.bar_reg + dpit->ucreg.offset; |
| 823 | 824 | ||
| 824 | return 0; | 825 | return 0; |
| @@ -12307,6 +12307,7 @@ static void free_cntrs(struct hfi1_devdata *dd) · 12306 unmodified lines | |||
| 12307 | 12307 | ||
| 12308 | if (dd->synth_stats_timer.function) | 12308 | if (dd->synth_stats_timer.function) |
| 12309 | del_timer_sync(&dd->synth_stats_timer); | 12309 | del_timer_sync(&dd->synth_stats_timer); |
| 12310 | cancel_work_sync(&dd->update_cntr_work); | ||
| 12310 | ppd = (struct hfi1_pportdata *)(dd + 1); | 12311 | ppd = (struct hfi1_pportdata *)(dd + 1); |
| 12311 | for (i = 0; i < dd->num_pports; i++, ppd++) { | 12312 | for (i = 0; i < dd->num_pports; i++, ppd++) { |
| 12312 | kfree(ppd->cntrs); | 12313 | kfree(ppd->cntrs); |
| @@ -83,6 +83,11 @@ static void bcm_aggregate(struct qcom_icc_bcm *bcm) · 82 unmodified lines | |||
| 83 | 83 | ||
| 84 | temp = agg_peak[bucket] * bcm->vote_scale; | 84 | temp = agg_peak[bucket] * bcm->vote_scale; |
| 85 | bcm->vote_y[bucket] = bcm_div(temp, bcm->aux_data.unit); | 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 | if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 && | 93 | if (bcm->keepalive && bcm->vote_x[QCOM_ICC_BUCKET_AMC] == 0 && |
| @@ -81,6 +81,7 @@ struct qcom_icc_node { · 80 unmodified lines | |||
| 81 | * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm | 81 | * @vote_x: aggregated threshold values, represents sum_bw when @type is bw bcm |
| 82 | * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm | 82 | * @vote_y: aggregated threshold values, represents peak_bw when @type is bw bcm |
| 83 | * @vote_scale: scaling factor for vote_x and vote_y | 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 | * @dirty: flag used to indicate whether the bcm needs to be committed | 85 | * @dirty: flag used to indicate whether the bcm needs to be committed |
| 85 | * @keepalive: flag used to indicate whether a keepalive is required | 86 | * @keepalive: flag used to indicate whether a keepalive is required |
| 86 | * @aux_data: auxiliary data used when calculating threshold values and | 87 | * @aux_data: auxiliary data used when calculating threshold values and |
| @@ -97,6 +98,7 @@ struct qcom_icc_bcm { · 10 unmodified lines | |||
| 97 | u64 vote_x[QCOM_ICC_NUM_BUCKETS]; | 98 | u64 vote_x[QCOM_ICC_NUM_BUCKETS]; |
| 98 | u64 vote_y[QCOM_ICC_NUM_BUCKETS]; | 99 | u64 vote_y[QCOM_ICC_NUM_BUCKETS]; |
| 99 | u64 vote_scale; | 100 | u64 vote_scale; |
| 101 | u32 enable_mask; | ||
| 100 | bool dirty; | 102 | bool dirty; |
| 101 | bool keepalive; | 103 | bool keepalive; |
| 102 | struct bcm_db aux_data; | 104 | struct bcm_db aux_data; |
| @@ -1873,6 +1873,7 @@ static struct qcom_icc_node srvc_snoc = { · 1872 unmodified lines | |||
| 1873 | 1873 | ||
| 1874 | static struct qcom_icc_bcm bcm_acv = { | 1874 | static struct qcom_icc_bcm bcm_acv = { |
| 1875 | .name = "ACV", | 1875 | .name = "ACV", |
| 1876 | .enable_mask = 0x8, | ||
| 1876 | .num_nodes = 1, | 1877 | .num_nodes = 1, |
| 1877 | .nodes = { &ebi }, | 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 | static struct qcom_icc_bcm bcm_acv = { | 1338 | static struct qcom_icc_bcm bcm_acv = { |
| 1339 | .name = "ACV", | 1339 | .name = "ACV", |
| 1340 | .enable_mask = 0x8, | ||
| 1340 | .num_nodes = 1, | 1341 | .num_nodes = 1, |
| 1341 | .nodes = { &ebi }, | 1342 | .nodes = { &ebi }, |
| 1342 | }; | 1343 | }; |
| @@ -1349,6 +1350,7 @@ static struct qcom_icc_bcm bcm_ce0 = { · 6 unmodified lines | |||
| 1349 | 1350 | ||
| 1350 | static struct qcom_icc_bcm bcm_cn0 = { | 1351 | static struct qcom_icc_bcm bcm_cn0 = { |
| 1351 | .name = "CN0", | 1352 | .name = "CN0", |
| 1353 | .enable_mask = 0x1, | ||
| 1352 | .keepalive = true, | 1354 | .keepalive = true, |
| 1353 | .num_nodes = 55, | 1355 | .num_nodes = 55, |
| 1354 | .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie, | 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 | static struct qcom_icc_bcm bcm_co0 = { | 1386 | static struct qcom_icc_bcm bcm_co0 = { |
| 1385 | .name = "CO0", | 1387 | .name = "CO0", |
| 1388 | .enable_mask = 0x1, | ||
| 1386 | .num_nodes = 2, | 1389 | .num_nodes = 2, |
| 1387 | .nodes = { &qxm_nsp, &qns_nsp_gemnoc }, | 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 | static struct qcom_icc_bcm bcm_mm1 = { | 1407 | static struct qcom_icc_bcm bcm_mm1 = { |
| 1405 | .name = "MM1", | 1408 | .name = "MM1", |
| 1409 | .enable_mask = 0x1, | ||
| 1406 | .num_nodes = 12, | 1410 | .num_nodes = 12, |
| 1407 | .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp, | 1411 | .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp, |
| 1408 | &qnm_camnoc_sf, &qnm_mdp, | 1412 | &qnm_camnoc_sf, &qnm_mdp, |
| @@ -1445,6 +1449,7 @@ static struct qcom_icc_bcm bcm_sh0 = { · 36 unmodified lines | |||
| 1445 | 1449 | ||
| 1446 | static struct qcom_icc_bcm bcm_sh1 = { | 1450 | static struct qcom_icc_bcm bcm_sh1 = { |
| 1447 | .name = "SH1", | 1451 | .name = "SH1", |
| 1452 | .enable_mask = 0x1, | ||
| 1448 | .num_nodes = 7, | 1453 | .num_nodes = 7, |
| 1449 | .nodes = { &alm_gpu_tcu, &alm_sys_tcu, | 1454 | .nodes = { &alm_gpu_tcu, &alm_sys_tcu, |
| 1450 | &qnm_nsp_gemnoc, &qnm_pcie, | 1455 | &qnm_nsp_gemnoc, &qnm_pcie, |
| @@ -1461,6 +1466,7 @@ static struct qcom_icc_bcm bcm_sn0 = { · 10 unmodified lines | |||
| 1461 | 1466 | ||
| 1462 | static struct qcom_icc_bcm bcm_sn1 = { | 1467 | static struct qcom_icc_bcm bcm_sn1 = { |
| 1463 | .name = "SN1", | 1468 | .name = "SN1", |
| 1469 | .enable_mask = 0x1, | ||
| 1464 | .num_nodes = 4, | 1470 | .num_nodes = 4, |
| 1465 | .nodes = { &qhm_gic, &qxm_pimem, | 1471 | .nodes = { &qhm_gic, &qxm_pimem, |
| 1466 | &xm_gic, &qns_gemnoc_gc }, | 1472 | &xm_gic, &qns_gemnoc_gc }, |
| @@ -1492,6 +1498,7 @@ static struct qcom_icc_bcm bcm_sn7 = { · 25 unmodified lines | |||
| 1492 | 1498 | ||
| 1493 | static struct qcom_icc_bcm bcm_acv_disp = { | 1499 | static struct qcom_icc_bcm bcm_acv_disp = { |
| 1494 | .name = "ACV", | 1500 | .name = "ACV", |
| 1501 | .enable_mask = 0x1, | ||
| 1495 | .num_nodes = 1, | 1502 | .num_nodes = 1, |
| 1496 | .nodes = { &ebi_disp }, | 1503 | .nodes = { &ebi_disp }, |
| 1497 | }; | 1504 | }; |
| @@ -1510,6 +1517,7 @@ static struct qcom_icc_bcm bcm_mm0_disp = { · 12 unmodified lines | |||
| 1510 | 1517 | ||
| 1511 | static struct qcom_icc_bcm bcm_mm1_disp = { | 1518 | static struct qcom_icc_bcm bcm_mm1_disp = { |
| 1512 | .name = "MM1", | 1519 | .name = "MM1", |
| 1520 | .enable_mask = 0x1, | ||
| 1513 | .num_nodes = 3, | 1521 | .num_nodes = 3, |
| 1514 | .nodes = { &qnm_mdp_disp, &qnm_rot_disp, | 1522 | .nodes = { &qnm_mdp_disp, &qnm_rot_disp, |
| 1515 | &qns_mem_noc_sf_disp }, | 1523 | &qns_mem_noc_sf_disp }, |
| @@ -1523,6 +1531,7 @@ static struct qcom_icc_bcm bcm_sh0_disp = { · 7 unmodified lines | |||
| 1523 | 1531 | ||
| 1524 | static struct qcom_icc_bcm bcm_sh1_disp = { | 1532 | static struct qcom_icc_bcm bcm_sh1_disp = { |
| 1525 | .name = "SH1", | 1533 | .name = "SH1", |
| 1534 | .enable_mask = 0x1, | ||
| 1526 | .num_nodes = 1, | 1535 | .num_nodes = 1, |
| 1527 | .nodes = { &qnm_pcie_disp }, | 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 | static struct qcom_icc_bcm bcm_acv = { | 1474 | static struct qcom_icc_bcm bcm_acv = { |
| 1475 | .name = "ACV", | 1475 | .name = "ACV", |
| 1476 | .enable_mask = 0x8, | ||
| 1476 | .num_nodes = 1, | 1477 | .num_nodes = 1, |
| 1477 | .nodes = { &ebi }, | 1478 | .nodes = { &ebi }, |
| 1478 | }; | 1479 | }; |
| @@ -1485,6 +1486,7 @@ static struct qcom_icc_bcm bcm_ce0 = { · 6 unmodified lines | |||
| 1485 | 1486 | ||
| 1486 | static struct qcom_icc_bcm bcm_cn0 = { | 1487 | static struct qcom_icc_bcm bcm_cn0 = { |
| 1487 | .name = "CN0", | 1488 | .name = "CN0", |
| 1489 | .enable_mask = 0x1, | ||
| 1488 | .keepalive = true, | 1490 | .keepalive = true, |
| 1489 | .num_nodes = 54, | 1491 | .num_nodes = 54, |
| 1490 | .nodes = { &qsm_cfg, &qhs_ahb2phy0, | 1492 | .nodes = { &qsm_cfg, &qhs_ahb2phy0, |
| @@ -1524,6 +1526,7 @@ static struct qcom_icc_bcm bcm_cn1 = { · 33 unmodified lines | |||
| 1524 | 1526 | ||
| 1525 | static struct qcom_icc_bcm bcm_co0 = { | 1527 | static struct qcom_icc_bcm bcm_co0 = { |
| 1526 | .name = "CO0", | 1528 | .name = "CO0", |
| 1529 | .enable_mask = 0x1, | ||
| 1527 | .num_nodes = 2, | 1530 | .num_nodes = 2, |
| 1528 | .nodes = { &qxm_nsp, &qns_nsp_gemnoc }, | 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 | static struct qcom_icc_bcm bcm_mm1 = { | 1553 | static struct qcom_icc_bcm bcm_mm1 = { |
| 1551 | .name = "MM1", | 1554 | .name = "MM1", |
| 1555 | .enable_mask = 0x1, | ||
| 1552 | .num_nodes = 8, | 1556 | .num_nodes = 8, |
| 1553 | .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp, | 1557 | .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp, |
| 1554 | &qnm_camnoc_sf, &qnm_vapss_hcp, | 1558 | &qnm_camnoc_sf, &qnm_vapss_hcp, |
| @@ -1589,6 +1593,7 @@ static struct qcom_icc_bcm bcm_sh0 = { · 34 unmodified lines | |||
| 1589 | 1593 | ||
| 1590 | static struct qcom_icc_bcm bcm_sh1 = { | 1594 | static struct qcom_icc_bcm bcm_sh1 = { |
| 1591 | .name = "SH1", | 1595 | .name = "SH1", |
| 1596 | .enable_mask = 0x1, | ||
| 1592 | .num_nodes = 13, | 1597 | .num_nodes = 13, |
| 1593 | .nodes = { &alm_gpu_tcu, &alm_sys_tcu, | 1598 | .nodes = { &alm_gpu_tcu, &alm_sys_tcu, |
| 1594 | &chm_apps, &qnm_gpu, | 1599 | &chm_apps, &qnm_gpu, |
| @@ -1608,6 +1613,7 @@ static struct qcom_icc_bcm bcm_sn0 = { · 13 unmodified lines | |||
| 1608 | 1613 | ||
| 1609 | static struct qcom_icc_bcm bcm_sn1 = { | 1614 | static struct qcom_icc_bcm bcm_sn1 = { |
| 1610 | .name = "SN1", | 1615 | .name = "SN1", |
| 1616 | .enable_mask = 0x1, | ||
| 1611 | .num_nodes = 3, | 1617 | .num_nodes = 3, |
| 1612 | .nodes = { &qhm_gic, &xm_gic, | 1618 | .nodes = { &qhm_gic, &xm_gic, |
| 1613 | &qns_gemnoc_gc }, | 1619 | &qns_gemnoc_gc }, |
| @@ -1633,6 +1639,7 @@ static struct qcom_icc_bcm bcm_sn7 = { · 19 unmodified lines | |||
| 1633 | 1639 | ||
| 1634 | static struct qcom_icc_bcm bcm_acv_disp = { | 1640 | static struct qcom_icc_bcm bcm_acv_disp = { |
| 1635 | .name = "ACV", | 1641 | .name = "ACV", |
| 1642 | .enable_mask = 0x1, | ||
| 1636 | .num_nodes = 1, | 1643 | .num_nodes = 1, |
| 1637 | .nodes = { &ebi_disp }, | 1644 | .nodes = { &ebi_disp }, |
| 1638 | }; | 1645 | }; |
| @@ -1657,12 +1664,14 @@ static struct qcom_icc_bcm bcm_sh0_disp = { · 18 unmodified lines | |||
| 1657 | 1664 | ||
| 1658 | static struct qcom_icc_bcm bcm_sh1_disp = { | 1665 | static struct qcom_icc_bcm bcm_sh1_disp = { |
| 1659 | .name = "SH1", | 1666 | .name = "SH1", |
| 1667 | .enable_mask = 0x1, | ||
| 1660 | .num_nodes = 2, | 1668 | .num_nodes = 2, |
| 1661 | .nodes = { &qnm_mnoc_hf_disp, &qnm_pcie_disp }, | 1669 | .nodes = { &qnm_mnoc_hf_disp, &qnm_pcie_disp }, |
| 1662 | }; | 1670 | }; |
| 1663 | 1671 | ||
| 1664 | static struct qcom_icc_bcm bcm_acv_cam_ife_0 = { | 1672 | static struct qcom_icc_bcm bcm_acv_cam_ife_0 = { |
| 1665 | .name = "ACV", | 1673 | .name = "ACV", |
| 1674 | .enable_mask = 0x0, | ||
| 1666 | .num_nodes = 1, | 1675 | .num_nodes = 1, |
| 1667 | .nodes = { &ebi_cam_ife_0 }, | 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 | static struct qcom_icc_bcm bcm_mm1_cam_ife_0 = { | 1691 | static struct qcom_icc_bcm bcm_mm1_cam_ife_0 = { |
| 1683 | .name = "MM1", | 1692 | .name = "MM1", |
| 1693 | .enable_mask = 0x1, | ||
| 1684 | .num_nodes = 4, | 1694 | .num_nodes = 4, |
| 1685 | .nodes = { &qnm_camnoc_hf_cam_ife_0, &qnm_camnoc_icp_cam_ife_0, | 1695 | .nodes = { &qnm_camnoc_hf_cam_ife_0, &qnm_camnoc_icp_cam_ife_0, |
| 1686 | &qnm_camnoc_sf_cam_ife_0, &qns_mem_noc_sf_cam_ife_0 }, | 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 | static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = { | 1705 | static struct qcom_icc_bcm bcm_sh1_cam_ife_0 = { |
| 1696 | .name = "SH1", | 1706 | .name = "SH1", |
| 1707 | .enable_mask = 0x1, | ||
| 1697 | .num_nodes = 3, | 1708 | .num_nodes = 3, |
| 1698 | .nodes = { &qnm_mnoc_hf_cam_ife_0, &qnm_mnoc_sf_cam_ife_0, | 1709 | .nodes = { &qnm_mnoc_hf_cam_ife_0, &qnm_mnoc_sf_cam_ife_0, |
| 1699 | &qnm_pcie_cam_ife_0 }, | 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 | static struct qcom_icc_bcm bcm_acv_cam_ife_1 = { | 1713 | static struct qcom_icc_bcm bcm_acv_cam_ife_1 = { |
| 1703 | .name = "ACV", | 1714 | .name = "ACV", |
| 1715 | .enable_mask = 0x0, | ||
| 1704 | .num_nodes = 1, | 1716 | .num_nodes = 1, |
| 1705 | .nodes = { &ebi_cam_ife_1 }, | 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 | static struct qcom_icc_bcm bcm_mm1_cam_ife_1 = { | 1732 | static struct qcom_icc_bcm bcm_mm1_cam_ife_1 = { |
| 1721 | .name = "MM1", | 1733 | .name = "MM1", |
| 1734 | .enable_mask = 0x1, | ||
| 1722 | .num_nodes = 4, | 1735 | .num_nodes = 4, |
| 1723 | .nodes = { &qnm_camnoc_hf_cam_ife_1, &qnm_camnoc_icp_cam_ife_1, | 1736 | .nodes = { &qnm_camnoc_hf_cam_ife_1, &qnm_camnoc_icp_cam_ife_1, |
| 1724 | &qnm_camnoc_sf_cam_ife_1, &qns_mem_noc_sf_cam_ife_1 }, | 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 | static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = { | 1746 | static struct qcom_icc_bcm bcm_sh1_cam_ife_1 = { |
| 1734 | .name = "SH1", | 1747 | .name = "SH1", |
| 1748 | .enable_mask = 0x1, | ||
| 1735 | .num_nodes = 3, | 1749 | .num_nodes = 3, |
| 1736 | .nodes = { &qnm_mnoc_hf_cam_ife_1, &qnm_mnoc_sf_cam_ife_1, | 1750 | .nodes = { &qnm_mnoc_hf_cam_ife_1, &qnm_mnoc_sf_cam_ife_1, |
| 1737 | &qnm_pcie_cam_ife_1 }, | 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 | static struct qcom_icc_bcm bcm_acv_cam_ife_2 = { | 1754 | static struct qcom_icc_bcm bcm_acv_cam_ife_2 = { |
| 1741 | .name = "ACV", | 1755 | .name = "ACV", |
| 1756 | .enable_mask = 0x0, | ||
| 1742 | .num_nodes = 1, | 1757 | .num_nodes = 1, |
| 1743 | .nodes = { &ebi_cam_ife_2 }, | 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 | static struct qcom_icc_bcm bcm_mm1_cam_ife_2 = { | 1773 | static struct qcom_icc_bcm bcm_mm1_cam_ife_2 = { |
| 1759 | .name = "MM1", | 1774 | .name = "MM1", |
| 1775 | .enable_mask = 0x1, | ||
| 1760 | .num_nodes = 4, | 1776 | .num_nodes = 4, |
| 1761 | .nodes = { &qnm_camnoc_hf_cam_ife_2, &qnm_camnoc_icp_cam_ife_2, | 1777 | .nodes = { &qnm_camnoc_hf_cam_ife_2, &qnm_camnoc_icp_cam_ife_2, |
| 1762 | &qnm_camnoc_sf_cam_ife_2, &qns_mem_noc_sf_cam_ife_2 }, | 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 | static struct qcom_icc_bcm bcm_sh1_cam_ife_2 = { | 1787 | static struct qcom_icc_bcm bcm_sh1_cam_ife_2 = { |
| 1772 | .name = "SH1", | 1788 | .name = "SH1", |
| 1789 | .enable_mask = 0x1, | ||
| 1773 | .num_nodes = 3, | 1790 | .num_nodes = 3, |
| 1774 | .nodes = { &qnm_mnoc_hf_cam_ife_2, &qnm_mnoc_sf_cam_ife_2, | 1791 | .nodes = { &qnm_mnoc_hf_cam_ife_2, &qnm_mnoc_sf_cam_ife_2, |
| 1775 | &qnm_pcie_cam_ife_2 }, | 1792 | &qnm_pcie_cam_ife_2 }, |
| @@ -839,7 +839,7 @@ hfcpci_fill_fifo(struct bchannel *bch) · 838 unmodified lines | |||
| 839 | *z1t = cpu_to_le16(new_z1); /* now send data */ | 839 | *z1t = cpu_to_le16(new_z1); /* now send data */ |
| 840 | if (bch->tx_idx < bch->tx_skb->len) | 840 | if (bch->tx_idx < bch->tx_skb->len) |
| 841 | return; | 841 | return; |
| 842 | dev_kfree_skb(bch->tx_skb); | 842 | dev_kfree_skb_any(bch->tx_skb); |
| 843 | if (get_next_bframe(bch)) | 843 | if (get_next_bframe(bch)) |
| 844 | goto next_t_frame; | 844 | goto next_t_frame; |
| 845 | return; | 845 | return; |
| @@ -895,7 +895,7 @@ hfcpci_fill_fifo(struct bchannel *bch) · 49 unmodified lines | |||
| 895 | } | 895 | } |
| 896 | bz->za[new_f1].z1 = cpu_to_le16(new_z1); /* for next buffer */ | 896 | bz->za[new_f1].z1 = cpu_to_le16(new_z1); /* for next buffer */ |
| 897 | bz->f1 = new_f1; /* next frame */ | 897 | bz->f1 = new_f1; /* next frame */ |
| 898 | dev_kfree_skb(bch->tx_skb); | 898 | dev_kfree_skb_any(bch->tx_skb); |
| 899 | get_next_bframe(bch); | 899 | get_next_bframe(bch); |
| 900 | } | 900 | } |
| 901 | 901 | ||
| @@ -1119,7 +1119,7 @@ tx_birq(struct bchannel *bch) · 217 unmodified lines | |||
| 1119 | if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) | 1119 | if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) |
| 1120 | hfcpci_fill_fifo(bch); | 1120 | hfcpci_fill_fifo(bch); |
| 1121 | else { | 1121 | else { |
| 1122 | dev_kfree_skb(bch->tx_skb); | 1122 | dev_kfree_skb_any(bch->tx_skb); |
| 1123 | if (get_next_bframe(bch)) | 1123 | if (get_next_bframe(bch)) |
| 1124 | hfcpci_fill_fifo(bch); | 1124 | hfcpci_fill_fifo(bch); |
| 1125 | } | 1125 | } |
| @@ -2277,7 +2277,7 @@ _hfcpci_softirq(struct device *dev, void *unused) · 1151 unmodified lines | |||
| 2277 | return 0; | 2277 | return 0; |
| 2278 | 2278 | ||
| 2279 | if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) { | 2279 | if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) { |
| 2280 | spin_lock(&hc->lock); | 2280 | spin_lock_irq(&hc->lock); |
| 2281 | bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1); | 2281 | bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1); |
| 2282 | if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */ | 2282 | if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */ |
| 2283 | main_rec_hfcpci(bch); | 2283 | main_rec_hfcpci(bch); |
| @@ -2288,7 +2288,7 @@ _hfcpci_softirq(struct device *dev, void *unused) · 4 unmodified lines | |||
| 2288 | main_rec_hfcpci(bch); | 2288 | main_rec_hfcpci(bch); |
| 2289 | tx_birq(bch); | 2289 | tx_birq(bch); |
| 2290 | } | 2290 | } |
| 2291 | spin_unlock(&hc->lock); | 2291 | spin_unlock_irq(&hc->lock); |
| 2292 | } | 2292 | } |
| 2293 | return 0; | 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 | extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id); | 247 | extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id); |
| 248 | extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb); | 248 | extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb); |
| 249 | extern void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb); | 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 | extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb); | 251 | extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb); |
| 252 | extern int dsp_cmx_del_conf_member(struct dsp *dsp); | 252 | extern int dsp_cmx_del_conf_member(struct dsp *dsp); |
| 253 | extern int dsp_cmx_del_conf(struct dsp_conf *conf); | 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 | static int dsp_count_valid; /* if we have last sample count */ | 1614 | static int dsp_count_valid; /* if we have last sample count */ |
| 1615 | 1615 | ||
| 1616 | void | 1616 | void |
| 1617 | dsp_cmx_send(void *arg) | 1617 | dsp_cmx_send(struct timer_list *arg) |
| 1618 | { | 1618 | { |
| 1619 | struct dsp_conf *conf; | 1619 | struct dsp_conf *conf; |
| 1620 | struct dsp_conf_member *member; | 1620 | struct dsp_conf_member *member; |
| @@ -1195,7 +1195,7 @@ static int __init dsp_init(void) · 1194 unmodified lines | |||
| 1195 | } | 1195 | } |
| 1196 | 1196 | ||
| 1197 | /* set sample timer */ | 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 | dsp_spl_tl.expires = jiffies + dsp_tics; | 1199 | dsp_spl_tl.expires = jiffies + dsp_tics; |
| 1200 | dsp_spl_jiffies = dsp_spl_tl.expires; | 1200 | dsp_spl_jiffies = dsp_spl_tl.expires; |
| 1201 | add_timer(&dsp_spl_tl); | 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 | pkt->extradata_size = 0; | 252 | pkt->extradata_size = 0; |
| 253 | pkt->shdr.hdr.size = | 253 | pkt->shdr.hdr.size = |
| 254 | struct_size((struct hfi_session_set_buffers_pkt *)0, | 254 | struct_size_t(struct hfi_session_set_buffers_pkt, |
| 255 | buffer_info, bd->num_buffers); | 255 | buffer_info, bd->num_buffers); |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | pkt->response_req = bd->response_required; | 258 | pkt->response_req = bd->response_required; |
| @@ -755,6 +755,43 @@ const char *const tegra_mc_error_names[8] = { · 754 unmodified lines | |||
| 755 | [6] = "SMMU translation error", | 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 | * Memory Controller (MC) has few Memory Clients that are issuing memory | 796 | * Memory Controller (MC) has few Memory Clients that are issuing memory |
| 760 | * bandwidth allocation requests to the MC interconnect provider. The MC | 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 | MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, | 1355 | MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM, |
| 1356 | .has_addr_hi_reg = true, | 1356 | .has_addr_hi_reg = true, |
| 1357 | .ops = &tegra186_mc_ops, | 1357 | .ops = &tegra186_mc_ops, |
| 1358 | .icc_ops = &tegra_mc_icc_ops, | ||
| 1358 | .ch_intmask = 0x00000f00, | 1359 | .ch_intmask = 0x00000f00, |
| 1359 | .global_intstatus_channel_shift = 8, | 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 | return 0; | 827 | return 0; |
| 828 | 828 | ||
| 829 | if (!mc->bwmgr_mrq_supported) | 829 | if (!mc->bwmgr_mrq_supported) |
| 830 | return -EINVAL; | 830 | return 0; |
| 831 | 831 | ||
| 832 | if (!mc->bpmp) { | 832 | if (!mc->bpmp) { |
| 833 | dev_err(mc->dev, "BPMP reference NULL\n"); | 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 | struct tegra_mc *mc = icc_provider_to_tegra_mc(p); | 874 | struct tegra_mc *mc = icc_provider_to_tegra_mc(p); |
| 875 | 875 | ||
| 876 | if (!mc->bwmgr_mrq_supported) | 876 | if (!mc->bwmgr_mrq_supported) |
| 877 | return -EINVAL; | 877 | return 0; |
| 878 | 878 | ||
| 879 | if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 || | 879 | if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 || |
| 880 | node->id == TEGRA_ICC_MC_CPU_CLUSTER1 || | 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 | return 0; | 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 | static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) | 892 | static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak) |
| 914 | { | 893 | { |
| 915 | *avg = 0; | 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 | static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = { | 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 | .aggregate = tegra234_mc_icc_aggregate, | 902 | .aggregate = tegra234_mc_icc_aggregate, |
| 924 | .get_bw = tegra234_mc_icc_get_init_bw, | 903 | .get_bw = tegra234_mc_icc_get_init_bw, |
| 925 | .set = tegra234_mc_icc_set, | 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 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, | 199 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, |
| 200 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); | 200 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); |
| 201 | else | 201 | else |
| @@ -435,17 +435,10 @@ static void rts5228_init_from_cfg(struct rtsx_pcr *pcr) · 434 unmodified lines | |||
| 435 | option->ltr_enabled = false; | 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 | static int rts5228_extra_init_hw(struct rtsx_pcr *pcr) | 440 | static int rts5228_extra_init_hw(struct rtsx_pcr *pcr) |
| 447 | { | 441 | { |
| 448 | struct rtsx_cr_option *option = &pcr->option; | ||
| 449 | 442 | ||
| 450 | rtsx_pci_write_register(pcr, RTS5228_AUTOLOAD_CFG1, | 443 | rtsx_pci_write_register(pcr, RTS5228_AUTOLOAD_CFG1, |
| 451 | CD_RESUME_EN_MASK, CD_RESUME_EN_MASK); | 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 | else | 469 | else |
| 477 | rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00); | 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 | rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); | 472 | rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); |
| 491 | 473 | ||
| 492 | if (pcr->rtd3_en) { | 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 | * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced | 331 | * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced |
| 333 | * to drive low, and we forcibly request clock. | 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 | rtsx_pci_write_register(pcr, PETXCFG, | 335 | rtsx_pci_write_register(pcr, PETXCFG, |
| 337 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); | 336 | FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); |
| 338 | else | 337 | else |
| @@ -517,17 +517,10 @@ static void rts5260_init_from_cfg(struct rtsx_pcr *pcr) · 516 unmodified lines | |||
| 517 | option->ltr_enabled = false; | 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 | static int rts5260_extra_init_hw(struct rtsx_pcr *pcr) | 522 | static int rts5260_extra_init_hw(struct rtsx_pcr *pcr) |
| 529 | { | 523 | { |
| 530 | struct rtsx_cr_option *option = &pcr->option; | ||
| 531 | 524 | ||
| 532 | /* Set mcu_cnt to 7 to ensure data can be sampled properly */ | 525 | /* Set mcu_cnt to 7 to ensure data can be sampled properly */ |
| 533 | rtsx_pci_write_register(pcr, 0xFC03, 0x7F, 0x07); | 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 | rts5260_init_hw(pcr); | 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 | rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00); | 542 | rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00); |
| 561 | 543 | ||
| 562 | return 0; | 544 | return 0; |
| @@ -498,17 +498,10 @@ static void rts5261_init_from_cfg(struct rtsx_pcr *pcr) · 497 unmodified lines | |||
| 498 | option->ltr_enabled = false; | 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 | static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) | 503 | static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) |
| 510 | { | 504 | { |
| 511 | struct rtsx_cr_option *option = &pcr->option; | ||
| 512 | u32 val; | 505 | u32 val; |
| 513 | 506 | ||
| 514 | rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1, | 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 | else | 547 | else |
| 555 | rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00); | 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 | rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); | 550 | rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); |
| 569 | 551 | ||
| 570 | if (pcr->rtd3_en) { | 552 | if (pcr->rtd3_en) { |
| @@ -1326,8 +1326,11 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) · 1325 unmodified lines | |||
| 1326 | return err; | 1326 | return err; |
| 1327 | } | 1327 | } |
| 1328 | 1328 | ||
| 1329 | if (pcr->aspm_mode == ASPM_MODE_REG) | 1329 | if (pcr->aspm_mode == ASPM_MODE_REG) { |
| 1330 | rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0x30, 0x30); | 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 | /* No CD interrupt if probing driver with card inserted. | 1335 | /* No CD interrupt if probing driver with card inserted. |
| 1333 | * So we need to initialize pcr->card_exist here. | 1336 | * So we need to initialize pcr->card_exist here. |
| @@ -13,6 +13,8 @@ · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | #include <linux/mfd/tps6594.h> | 14 | #include <linux/mfd/tps6594.h> |
| 15 | 15 | ||
| 16 | #define TPS6594_DEV_REV_1 0x08 | ||
| 17 | |||
| 16 | static irqreturn_t tps6594_esm_isr(int irq, void *dev_id) | 18 | static irqreturn_t tps6594_esm_isr(int irq, void *dev_id) |
| 17 | { | 19 | { |
| 18 | struct platform_device *pdev = dev_id; | 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 | struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); | 35 | struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); |
| 34 | struct device *dev = &pdev->dev; | 36 | struct device *dev = &pdev->dev; |
| 37 | unsigned int rev; | ||
| 35 | int irq; | 38 | int irq; |
| 36 | int ret; | 39 | int ret; |
| 37 | int i; | 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 | irq = platform_get_irq_byname(pdev, pdev->resource[i].name); | 57 | irq = platform_get_irq_byname(pdev, pdev->resource[i].name); |
| 41 | if (irq < 0) | 58 | if (irq < 0) |
| 42 | return dev_err_probe(dev, irq, "Failed to get %s irq\n", | 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 | return; | 338 | return; |
| 339 | } | 339 | } |
| 340 | for (len = 0; len < remain && len < host->fifo_width;) { | 340 | for (len = 0; len < remain && len < host->fifo_width;) { |
| 341 | /* SCR data must be read in big endian. */ | 341 | *sgp = ioread32(host->base + REG_DATA_WINDOW); |
| 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); | ||
| 348 | sgp++; | 342 | sgp++; |
| 349 | len += 4; | 343 | len += 4; |
| 350 | } | 344 | } |
| @@ -29,9 +29,16 @@ struct f_sdhost_priv { · 28 unmodified lines | |||
| 29 | bool enable_cmd_dat_delay; | 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 | static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host) | 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 | u32 ctrl = 0; | 42 | u32 ctrl = 0; |
| 36 | 43 | ||
| 37 | usleep_range(2500, 3000); | 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 | static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask) | 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 | u32 ctl; | 75 | u32 ctl; |
| 69 | 76 | ||
| 70 | if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0) | 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 | .set_uhs_signaling = sdhci_set_uhs_signaling, | 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 | static int sdhci_f_sdh30_probe(struct platform_device *pdev) | 113 | static int sdhci_f_sdh30_probe(struct platform_device *pdev) |
| 99 | { | 114 | { |
| 100 | struct sdhci_host *host; | 115 | struct sdhci_host *host; |
| 101 | struct device *dev = &pdev->dev; | 116 | struct device *dev = &pdev->dev; |
| 102 | int irq, ctrl = 0, ret = 0; | 117 | int ctrl = 0, ret = 0; |
| 103 | struct f_sdhost_priv *priv; | 118 | struct f_sdhost_priv *priv; |
| 119 | struct sdhci_pltfm_host *pltfm_host; | ||
| 104 | u32 reg = 0; | 120 | u32 reg = 0; |
| 105 | 121 | ||
| 106 | irq = platform_get_irq(pdev, 0); | 122 | host = sdhci_pltfm_init(pdev, &sdhci_f_sdh30_pltfm_data, |
| 107 | if (irq < 0) | 123 | sizeof(struct f_sdhost_priv)); |
| 108 | return irq; | ||
| 109 | |||
| 110 | host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv)); | ||
| 111 | if (IS_ERR(host)) | 124 | if (IS_ERR(host)) |
| 112 | return PTR_ERR(host); | 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 | priv->dev = dev; | 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 | priv->enable_cmd_dat_delay = device_property_read_bool(dev, | 131 | priv->enable_cmd_dat_delay = device_property_read_bool(dev, |
| 123 | "fujitsu,cmd-dat-delay-select"); | 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 | if (ret) | 135 | if (ret) |
| 127 | goto err; | 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 | if (dev_of_node(dev)) { | 138 | if (dev_of_node(dev)) { |
| 142 | sdhci_get_of_property(pdev); | 139 | sdhci_get_of_property(pdev); |
| 143 | 140 | ||
| @@ -204,24 +201,21 @@ err_rst: · 60 unmodified lines | |||
| 204 | err_clk: | 201 | err_clk: |
| 205 | clk_disable_unprepare(priv->clk_iface); | 202 | clk_disable_unprepare(priv->clk_iface); |
| 206 | err: | 203 | err: |
| 207 | sdhci_free_host(host); | 204 | sdhci_pltfm_free(pdev); |
| 205 | |||
| 208 | return ret; | 206 | return ret; |
| 209 | } | 207 | } |
| 210 | 208 | ||
| 211 | static int sdhci_f_sdh30_remove(struct platform_device *pdev) | 209 | static int sdhci_f_sdh30_remove(struct platform_device *pdev) |
| 212 | { | 210 | { |
| 213 | struct sdhci_host *host = platform_get_drvdata(pdev); | 211 | struct sdhci_host *host = platform_get_drvdata(pdev); |
| 214 | struct f_sdhost_priv *priv = sdhci_priv(host); | 212 | struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); |
| 215 | |||
| 216 | sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) == | ||
| 217 | 0xffffffff); | ||
| 218 | 213 | ||
| 219 | reset_control_assert(priv->rst); | 214 | reset_control_assert(priv->rst); |
| 220 | clk_disable_unprepare(priv->clk); | 215 | clk_disable_unprepare(priv->clk); |
| 221 | clk_disable_unprepare(priv->clk_iface); | 216 | clk_disable_unprepare(priv->clk_iface); |
| 222 | 217 | ||
| 223 | sdhci_free_host(host); | 218 | sdhci_pltfm_unregister(pdev); |
| 224 | platform_set_drvdata(pdev, NULL); | ||
| 225 | 219 | ||
| 226 | return 0; | 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 | unsigned int i; | 135 | unsigned int i; |
| 136 | int ret; | 136 | int ret; |
| 137 | 137 | ||
| 138 | if (op->cs > NAND_MAX_CHIPS) | 138 | if (op->cs >= NAND_MAX_CHIPS) |
| 139 | return -EINVAL; | 139 | return -EINVAL; |
| 140 | 140 | ||
| 141 | if (check_only) | 141 | if (check_only) |
| @@ -1278,7 +1278,6 @@ static int meson_nand_attach_chip(struct nand_chip *nand) · 1277 unmodified lines | |||
| 1278 | struct meson_nfc *nfc = nand_get_controller_data(nand); | 1278 | struct meson_nfc *nfc = nand_get_controller_data(nand); |
| 1279 | struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); | 1279 | struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); |
| 1280 | struct mtd_info *mtd = nand_to_mtd(nand); | 1280 | struct mtd_info *mtd = nand_to_mtd(nand); |
| 1281 | int nsectors = mtd->writesize / 1024; | ||
| 1282 | int raw_writesize; | 1281 | int raw_writesize; |
| 1283 | int ret; | 1282 | int ret; |
| 1284 | 1283 | ||
| @@ -1304,7 +1303,7 @@ static int meson_nand_attach_chip(struct nand_chip *nand) · 19 unmodified lines | |||
| 1304 | nand->options |= NAND_NO_SUBPAGE_WRITE; | 1303 | nand->options |= NAND_NO_SUBPAGE_WRITE; |
| 1305 | 1304 | ||
| 1306 | ret = nand_ecc_choose_conf(nand, nfc->data->ecc_caps, | 1305 | ret = nand_ecc_choose_conf(nand, nfc->data->ecc_caps, |
| 1307 | mtd->oobsize - 2 * nsectors); | 1306 | mtd->oobsize - 2); |
| 1308 | if (ret) { | 1307 | if (ret) { |
| 1309 | dev_err(nfc->dev, "failed to ECC init\n"); | 1308 | dev_err(nfc->dev, "failed to ECC init\n"); |
| 1310 | return -EINVAL; | 1309 | return -EINVAL; |
| @@ -177,17 +177,17 @@ static void elm_load_syndrome(struct elm_info *info, · 176 unmodified lines | |||
| 177 | switch (info->bch_type) { | 177 | switch (info->bch_type) { |
| 178 | case BCH8_ECC: | 178 | case BCH8_ECC: |
| 179 | /* syndrome fragment 0 = ecc[9-12B] */ | 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 | elm_write_reg(info, offset, val); | 181 | elm_write_reg(info, offset, val); |
| 182 | 182 | ||
| 183 | /* syndrome fragment 1 = ecc[5-8B] */ | 183 | /* syndrome fragment 1 = ecc[5-8B] */ |
| 184 | offset += 4; | 184 | offset += 4; |
| 185 | val = cpu_to_be32(*(u32 *) &ecc[5]); | 185 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[5]); |
| 186 | elm_write_reg(info, offset, val); | 186 | elm_write_reg(info, offset, val); |
| 187 | 187 | ||
| 188 | /* syndrome fragment 2 = ecc[1-4B] */ | 188 | /* syndrome fragment 2 = ecc[1-4B] */ |
| 189 | offset += 4; | 189 | offset += 4; |
| 190 | val = cpu_to_be32(*(u32 *) &ecc[1]); | 190 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[1]); |
| 191 | elm_write_reg(info, offset, val); | 191 | elm_write_reg(info, offset, val); |
| 192 | 192 | ||
| 193 | /* syndrome fragment 3 = ecc[0B] */ | 193 | /* syndrome fragment 3 = ecc[0B] */ |
| @@ -197,35 +197,35 @@ static void elm_load_syndrome(struct elm_info *info, · 3 unmodified lines | |||
| 197 | break; | 197 | break; |
| 198 | case BCH4_ECC: | 198 | case BCH4_ECC: |
| 199 | /* syndrome fragment 0 = ecc[20-52b] bits */ | 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 | ((ecc[2] & 0xf) << 28); | 201 | ((ecc[2] & 0xf) << 28); |
| 202 | elm_write_reg(info, offset, val); | 202 | elm_write_reg(info, offset, val); |
| 203 | 203 | ||
| 204 | /* syndrome fragment 1 = ecc[0-20b] bits */ | 204 | /* syndrome fragment 1 = ecc[0-20b] bits */ |
| 205 | offset += 4; | 205 | offset += 4; |
| 206 | val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12; | 206 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 12; |
| 207 | elm_write_reg(info, offset, val); | 207 | elm_write_reg(info, offset, val); |
| 208 | break; | 208 | break; |
| 209 | case BCH16_ECC: | 209 | case BCH16_ECC: |
| 210 | val = cpu_to_be32(*(u32 *) &ecc[22]); | 210 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[22]); |
| 211 | elm_write_reg(info, offset, val); | 211 | elm_write_reg(info, offset, val); |
| 212 | offset += 4; | 212 | offset += 4; |
| 213 | val = cpu_to_be32(*(u32 *) &ecc[18]); | 213 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[18]); |
| 214 | elm_write_reg(info, offset, val); | 214 | elm_write_reg(info, offset, val); |
| 215 | offset += 4; | 215 | offset += 4; |
| 216 | val = cpu_to_be32(*(u32 *) &ecc[14]); | 216 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[14]); |
| 217 | elm_write_reg(info, offset, val); | 217 | elm_write_reg(info, offset, val); |
| 218 | offset += 4; | 218 | offset += 4; |
| 219 | val = cpu_to_be32(*(u32 *) &ecc[10]); | 219 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[10]); |
| 220 | elm_write_reg(info, offset, val); | 220 | elm_write_reg(info, offset, val); |
| 221 | offset += 4; | 221 | offset += 4; |
| 222 | val = cpu_to_be32(*(u32 *) &ecc[6]); | 222 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[6]); |
| 223 | elm_write_reg(info, offset, val); | 223 | elm_write_reg(info, offset, val); |
| 224 | offset += 4; | 224 | offset += 4; |
| 225 | val = cpu_to_be32(*(u32 *) &ecc[2]); | 225 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[2]); |
| 226 | elm_write_reg(info, offset, val); | 226 | elm_write_reg(info, offset, val); |
| 227 | offset += 4; | 227 | offset += 4; |
| 228 | val = cpu_to_be32(*(u32 *) &ecc[0]) >> 16; | 228 | val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 16; |
| 229 | elm_write_reg(info, offset, val); | 229 | elm_write_reg(info, offset, val); |
| 230 | break; | 230 | break; |
| 231 | default: | 231 | default: |
| @@ -562,9 +562,10 @@ static int rk_nfc_write_page_raw(struct nand_chip *chip, const u8 *buf, · 561 unmodified lines | |||
| 562 | * BBM OOB1 OOB2 OOB3 |......| PA0 PA1 PA2 PA3 | 562 | * BBM OOB1 OOB2 OOB3 |......| PA0 PA1 PA2 PA3 |
| 563 | * | 563 | * |
| 564 | * The rk_nfc_ooblayout_free() function already has reserved | 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 | if (!i) | 570 | if (!i) |
| 570 | memcpy(rk_nfc_oob_ptr(chip, i), | 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 | int pages_per_blk = mtd->erasesize / mtd->writesize; | 598 | int pages_per_blk = mtd->erasesize / mtd->writesize; |
| 598 | int ret = 0, i, boot_rom_mode = 0; | 599 | int ret = 0, i, boot_rom_mode = 0; |
| 599 | dma_addr_t dma_data, dma_oob; | 600 | dma_addr_t dma_data, dma_oob; |
| 600 | u32 reg; | 601 | u32 tmp; |
| 601 | u8 *oob; | 602 | u8 *oob; |
| 602 | 603 | ||
| 603 | nand_prog_page_begin_op(chip, page, 0, NULL, 0); | 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 | * 0xFF 0xFF 0xFF 0xFF | BBM OOB1 OOB2 OOB3 | ... | 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 | * Configure the ECC algorithm supported by the boot ROM. | 635 | * Configure the ECC algorithm supported by the boot ROM. |
| 628 | */ | 636 | */ |
| 629 | if ((page < (pages_per_blk * rknand->boot_blks)) && | 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 | for (i = 0; i < ecc->steps; i++) { | 644 | for (i = 0; i < ecc->steps; i++) { |
| 637 | if (!i) { | 645 | if (!i) |
| 638 | reg = 0xFFFFFFFF; | 646 | oob = chip->oob_poi + (ecc->steps - 1) * NFC_SYS_DATA_SIZE; |
| 639 | } else { | 647 | else |
| 640 | oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; | 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) | 650 | tmp = oob[0] | oob[1] << 8 | oob[2] << 16 | oob[3] << 24; |
| 646 | reg = (page & (pages_per_blk - 1)) * 4; | ||
| 647 | 651 | ||
| 648 | if (nfc->cfg->type == NFC_V9) | 652 | if (nfc->cfg->type == NFC_V9) |
| 649 | nfc->oob_buf[i] = reg; | 653 | nfc->oob_buf[i] = tmp; |
| 650 | else | 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 | dma_data = dma_map_single(nfc->dev, (void *)nfc->page_buf, | 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 | goto timeout_err; | 815 | goto timeout_err; |
| 812 | } | 816 | } |
| 813 | 817 | ||
| 814 | for (i = 1; i < ecc->steps; i++) { | 818 | for (i = 0; i < ecc->steps; i++) { |
| 815 | oob = chip->oob_poi + (i - 1) * NFC_SYS_DATA_SIZE; | 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 | if (nfc->cfg->type == NFC_V9) | 824 | if (nfc->cfg->type == NFC_V9) |
| 817 | tmp = nfc->oob_buf[i]; | 825 | tmp = nfc->oob_buf[i]; |
| 818 | else | 826 | else |
| 819 | tmp = nfc->oob_buf[i * (oob_step / 4)]; | 827 | tmp = nfc->oob_buf[i * (oob_step / 4)]; |
| 828 | |||
| 820 | *oob++ = (u8)tmp; | 829 | *oob++ = (u8)tmp; |
| 821 | *oob++ = (u8)(tmp >> 8); | 830 | *oob++ = (u8)(tmp >> 8); |
| 822 | *oob++ = (u8)(tmp >> 16); | 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 | if (section) | 942 | if (section) |
| 934 | return -ERANGE; | 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 | oob_region->length = rknand->metadata_size - NFC_SYS_DATA_SIZE - 2; | 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 | return 0; | 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 | struct nand_device *nand = spinand_to_nand(spinand); | 74 | struct nand_device *nand = spinand_to_nand(spinand); |
| 75 | u8 mbf = 0; | 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 | switch (status & STATUS_ECC_MASK) { | 78 | switch (status & STATUS_ECC_MASK) { |
| 79 | case STATUS_ECC_NO_BITFLIPS: | 79 | case STATUS_ECC_NO_BITFLIPS: |
| @@ -92,7 +92,7 @@ static int tx58cxgxsxraix_ecc_get_status(struct spinand_device *spinand, · 12 unmodified lines | |||
| 92 | if (spi_mem_exec_op(spinand->spimem, &op)) | 92 | if (spi_mem_exec_op(spinand->spimem, &op)) |
| 93 | return nanddev_get_ecc_conf(nand)->strength; | 93 | return nanddev_get_ecc_conf(nand)->strength; |
| 94 | 94 | ||
| 95 | mbf >>= 4; | 95 | mbf = *(spinand->scratchbuf) >> 4; |
| 96 | 96 | ||
| 97 | if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) | 97 | if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) |
| 98 | return nanddev_get_ecc_conf(nand)->strength; | 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 | struct nand_device *nand = spinand_to_nand(spinand); | 109 | struct nand_device *nand = spinand_to_nand(spinand); |
| 110 | u8 mbf = 0; | 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 | switch (status & STATUS_ECC_MASK) { | 113 | switch (status & STATUS_ECC_MASK) { |
| 114 | case STATUS_ECC_NO_BITFLIPS: | 114 | case STATUS_ECC_NO_BITFLIPS: |
| @@ -126,7 +126,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand, · 11 unmodified lines | |||
| 126 | if (spi_mem_exec_op(spinand->spimem, &op)) | 126 | if (spi_mem_exec_op(spinand->spimem, &op)) |
| 127 | return nanddev_get_ecc_conf(nand)->strength; | 127 | return nanddev_get_ecc_conf(nand)->strength; |
| 128 | 128 | ||
| 129 | mbf >>= 4; | 129 | mbf = *(spinand->scratchbuf) >> 4; |
| 130 | 130 | ||
| 131 | if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) | 131 | if (WARN_ON(mbf > nanddev_get_ecc_conf(nand)->strength || !mbf)) |
| 132 | return nanddev_get_ecc_conf(nand)->strength; | 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 | static int cypress_nor_set_addr_mode_nbytes(struct spi_nor *nor) | 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 | u8 addr_mode; | 365 | u8 addr_mode; |
| 366 | int ret; | 366 | int ret; |
| 367 | 367 | ||
| @@ -492,7 +492,7 @@ s25fs256t_post_bfpt_fixup(struct spi_nor *nor, · 124 unmodified lines | |||
| 492 | const struct sfdp_parameter_header *bfpt_header, | 492 | const struct sfdp_parameter_header *bfpt_header, |
| 493 | const struct sfdp_bfpt *bfpt) | 493 | const struct sfdp_bfpt *bfpt) |
| 494 | { | 494 | { |
| 495 | struct spi_mem_op op = {}; | 495 | struct spi_mem_op op; |
| 496 | int ret; | 496 | int ret; |
| 497 | 497 | ||
| 498 | ret = cypress_nor_set_addr_mode_nbytes(nor); | 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 | bond_dev->hw_features = BOND_VLAN_FEATURES | | 5902 | bond_dev->hw_features = BOND_VLAN_FEATURES | |
| 5903 | NETIF_F_HW_VLAN_CTAG_RX | | 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 | bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL; | 5908 | bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL; |
| 5907 | bond_dev->features |= bond_dev->hw_features; | 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 | if (IS_ERR(priv->clk)) | 1436 | if (IS_ERR(priv->clk)) |
| 1437 | return PTR_ERR(priv->clk); | 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 | priv->clk_mdiv = devm_clk_get_optional(&pdev->dev, "sw_switch_mdiv"); | 1443 | priv->clk_mdiv = devm_clk_get_optional(&pdev->dev, "sw_switch_mdiv"); |
| 1442 | if (IS_ERR(priv->clk_mdiv)) { | 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 | goto out_clk; | 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 | ret = bcm_sf2_sw_rst(priv); | 1453 | ret = bcm_sf2_sw_rst(priv); |
| 1450 | if (ret) { | 1454 | if (ret) { |
| @@ -635,10 +635,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 634 unmodified lines | |||
| 635 | regmap_reg_range(0x1030, 0x1030), | 635 | regmap_reg_range(0x1030, 0x1030), |
| 636 | regmap_reg_range(0x1100, 0x1115), | 636 | regmap_reg_range(0x1100, 0x1115), |
| 637 | regmap_reg_range(0x111a, 0x111f), | 637 | regmap_reg_range(0x111a, 0x111f), |
| 638 | regmap_reg_range(0x1122, 0x1127), | 638 | regmap_reg_range(0x1120, 0x112b), |
| 639 | regmap_reg_range(0x112a, 0x112b), | 639 | regmap_reg_range(0x1134, 0x113b), |
| 640 | regmap_reg_range(0x1136, 0x1139), | 640 | regmap_reg_range(0x113c, 0x113f), |
| 641 | regmap_reg_range(0x113e, 0x113f), | ||
| 642 | regmap_reg_range(0x1400, 0x1401), | 641 | regmap_reg_range(0x1400, 0x1401), |
| 643 | regmap_reg_range(0x1403, 0x1403), | 642 | regmap_reg_range(0x1403, 0x1403), |
| 644 | regmap_reg_range(0x1410, 0x1417), | 643 | regmap_reg_range(0x1410, 0x1417), |
| @@ -669,10 +668,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 24 unmodified lines | |||
| 669 | regmap_reg_range(0x2030, 0x2030), | 668 | regmap_reg_range(0x2030, 0x2030), |
| 670 | regmap_reg_range(0x2100, 0x2115), | 669 | regmap_reg_range(0x2100, 0x2115), |
| 671 | regmap_reg_range(0x211a, 0x211f), | 670 | regmap_reg_range(0x211a, 0x211f), |
| 672 | regmap_reg_range(0x2122, 0x2127), | 671 | regmap_reg_range(0x2120, 0x212b), |
| 673 | regmap_reg_range(0x212a, 0x212b), | 672 | regmap_reg_range(0x2134, 0x213b), |
| 674 | regmap_reg_range(0x2136, 0x2139), | 673 | regmap_reg_range(0x213c, 0x213f), |
| 675 | regmap_reg_range(0x213e, 0x213f), | ||
| 676 | regmap_reg_range(0x2400, 0x2401), | 674 | regmap_reg_range(0x2400, 0x2401), |
| 677 | regmap_reg_range(0x2403, 0x2403), | 675 | regmap_reg_range(0x2403, 0x2403), |
| 678 | regmap_reg_range(0x2410, 0x2417), | 676 | regmap_reg_range(0x2410, 0x2417), |
| @@ -703,10 +701,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 24 unmodified lines | |||
| 703 | regmap_reg_range(0x3030, 0x3030), | 701 | regmap_reg_range(0x3030, 0x3030), |
| 704 | regmap_reg_range(0x3100, 0x3115), | 702 | regmap_reg_range(0x3100, 0x3115), |
| 705 | regmap_reg_range(0x311a, 0x311f), | 703 | regmap_reg_range(0x311a, 0x311f), |
| 706 | regmap_reg_range(0x3122, 0x3127), | 704 | regmap_reg_range(0x3120, 0x312b), |
| 707 | regmap_reg_range(0x312a, 0x312b), | 705 | regmap_reg_range(0x3134, 0x313b), |
| 708 | regmap_reg_range(0x3136, 0x3139), | 706 | regmap_reg_range(0x313c, 0x313f), |
| 709 | regmap_reg_range(0x313e, 0x313f), | ||
| 710 | regmap_reg_range(0x3400, 0x3401), | 707 | regmap_reg_range(0x3400, 0x3401), |
| 711 | regmap_reg_range(0x3403, 0x3403), | 708 | regmap_reg_range(0x3403, 0x3403), |
| 712 | regmap_reg_range(0x3410, 0x3417), | 709 | regmap_reg_range(0x3410, 0x3417), |
| @@ -737,10 +734,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 24 unmodified lines | |||
| 737 | regmap_reg_range(0x4030, 0x4030), | 734 | regmap_reg_range(0x4030, 0x4030), |
| 738 | regmap_reg_range(0x4100, 0x4115), | 735 | regmap_reg_range(0x4100, 0x4115), |
| 739 | regmap_reg_range(0x411a, 0x411f), | 736 | regmap_reg_range(0x411a, 0x411f), |
| 740 | regmap_reg_range(0x4122, 0x4127), | 737 | regmap_reg_range(0x4120, 0x412b), |
| 741 | regmap_reg_range(0x412a, 0x412b), | 738 | regmap_reg_range(0x4134, 0x413b), |
| 742 | regmap_reg_range(0x4136, 0x4139), | 739 | regmap_reg_range(0x413c, 0x413f), |
| 743 | regmap_reg_range(0x413e, 0x413f), | ||
| 744 | regmap_reg_range(0x4400, 0x4401), | 740 | regmap_reg_range(0x4400, 0x4401), |
| 745 | regmap_reg_range(0x4403, 0x4403), | 741 | regmap_reg_range(0x4403, 0x4403), |
| 746 | regmap_reg_range(0x4410, 0x4417), | 742 | regmap_reg_range(0x4410, 0x4417), |
| @@ -771,10 +767,9 @@ static const struct regmap_range ksz9477_valid_regs[] = { · 24 unmodified lines | |||
| 771 | regmap_reg_range(0x5030, 0x5030), | 767 | regmap_reg_range(0x5030, 0x5030), |
| 772 | regmap_reg_range(0x5100, 0x5115), | 768 | regmap_reg_range(0x5100, 0x5115), |
| 773 | regmap_reg_range(0x511a, 0x511f), | 769 | regmap_reg_range(0x511a, 0x511f), |
| 774 | regmap_reg_range(0x5122, 0x5127), | 770 | regmap_reg_range(0x5120, 0x512b), |
| 775 | regmap_reg_range(0x512a, 0x512b), | 771 | regmap_reg_range(0x5134, 0x513b), |
| 776 | regmap_reg_range(0x5136, 0x5139), | 772 | regmap_reg_range(0x513c, 0x513f), |
| 777 | regmap_reg_range(0x513e, 0x513f), | ||
| 778 | regmap_reg_range(0x5400, 0x5401), | 773 | regmap_reg_range(0x5400, 0x5401), |
| 779 | regmap_reg_range(0x5403, 0x5403), | 774 | regmap_reg_range(0x5403, 0x5403), |
| 780 | regmap_reg_range(0x5410, 0x5417), | 775 | regmap_reg_range(0x5410, 0x5417), |
| @@ -1625,8 +1625,10 @@ static void felix_teardown(struct dsa_switch *ds) · 1624 unmodified lines | |||
| 1625 | struct felix *felix = ocelot_to_felix(ocelot); | 1625 | struct felix *felix = ocelot_to_felix(ocelot); |
| 1626 | struct dsa_port *dp; | 1626 | struct dsa_port *dp; |
| 1627 | 1627 | ||
| 1628 | rtnl_lock(); | ||
| 1628 | if (felix->tag_proto_ops) | 1629 | if (felix->tag_proto_ops) |
| 1629 | felix->tag_proto_ops->teardown(ds); | 1630 | felix->tag_proto_ops->teardown(ds); |
| 1631 | rtnl_unlock(); | ||
| 1630 | 1632 | ||
| 1631 | dsa_switch_for_each_available_port(dp, ds) | 1633 | dsa_switch_for_each_available_port(dp, ds) |
| 1632 | ocelot_deinit_port(ocelot, dp->index); | 1634 | ocelot_deinit_port(ocelot, dp->index); |
| @@ -633,12 +633,13 @@ tx_kick_pending: · 632 unmodified lines | |||
| 633 | return NETDEV_TX_OK; | 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 | struct bnxt_tx_ring_info *txr = bnapi->tx_ring; | 638 | struct bnxt_tx_ring_info *txr = bnapi->tx_ring; |
| 639 | struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index); | 639 | struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index); |
| 640 | u16 cons = txr->tx_cons; | 640 | u16 cons = txr->tx_cons; |
| 641 | struct pci_dev *pdev = bp->pdev; | 641 | struct pci_dev *pdev = bp->pdev; |
| 642 | int nr_pkts = bnapi->tx_pkts; | ||
| 642 | int i; | 643 | int i; |
| 643 | unsigned int tx_bytes = 0; | 644 | unsigned int tx_bytes = 0; |
| 644 | 645 | ||
| @@ -688,6 +689,7 @@ next_tx_int: · 43 unmodified lines | |||
| 688 | dev_kfree_skb_any(skb); | 689 | dev_kfree_skb_any(skb); |
| 689 | } | 690 | } |
| 690 | 691 | ||
| 692 | bnapi->tx_pkts = 0; | ||
| 691 | WRITE_ONCE(txr->tx_cons, cons); | 693 | WRITE_ONCE(txr->tx_cons, cons); |
| 692 | 694 | ||
| 693 | __netif_txq_completed_wake(txq, nr_pkts, tx_bytes, | 695 | __netif_txq_completed_wake(txq, nr_pkts, tx_bytes, |
| @@ -697,17 +699,24 @@ next_tx_int: · 3 unmodified lines | |||
| 697 | 699 | ||
| 698 | static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping, | 700 | static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping, |
| 699 | struct bnxt_rx_ring_info *rxr, | 701 | struct bnxt_rx_ring_info *rxr, |
| 702 | unsigned int *offset, | ||
| 700 | gfp_t gfp) | 703 | gfp_t gfp) |
| 701 | { | 704 | { |
| 702 | struct device *dev = &bp->pdev->dev; | 705 | struct device *dev = &bp->pdev->dev; |
| 703 | struct page *page; | 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 | if (!page) | 715 | if (!page) |
| 707 | return NULL; | 716 | return NULL; |
| 708 | 717 | ||
| 709 | *mapping = dma_map_page_attrs(dev, page, 0, PAGE_SIZE, bp->rx_dir, | 718 | *mapping = dma_map_page_attrs(dev, page, *offset, BNXT_RX_PAGE_SIZE, |
| 710 | DMA_ATTR_WEAK_ORDERING); | 719 | bp->rx_dir, DMA_ATTR_WEAK_ORDERING); |
| 711 | if (dma_mapping_error(dev, *mapping)) { | 720 | if (dma_mapping_error(dev, *mapping)) { |
| 712 | page_pool_recycle_direct(rxr->page_pool, page); | 721 | page_pool_recycle_direct(rxr->page_pool, page); |
| 713 | return NULL; | 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 | dma_addr_t mapping; | 756 | dma_addr_t mapping; |
| 748 | 757 | ||
| 749 | if (BNXT_RX_PAGE_MODE(bp)) { | 758 | if (BNXT_RX_PAGE_MODE(bp)) { |
| 759 | unsigned int offset; | ||
| 750 | struct page *page = | 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 | if (!page) | 763 | if (!page) |
| 754 | return -ENOMEM; | 764 | return -ENOMEM; |
| 755 | 765 | ||
| 756 | mapping += bp->rx_dma_offset; | 766 | mapping += bp->rx_dma_offset; |
| 757 | rx_buf->data = page; | 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 | } else { | 769 | } else { |
| 760 | u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, gfp); | 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 | unsigned int offset = 0; | 825 | unsigned int offset = 0; |
| 816 | 826 | ||
| 817 | if (BNXT_RX_PAGE_MODE(bp)) { | 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 | if (!page) | 830 | if (!page) |
| 821 | return -ENOMEM; | 831 | return -ENOMEM; |
| @@ -962,15 +972,15 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp, · 140 unmodified lines | |||
| 962 | return NULL; | 972 | return NULL; |
| 963 | } | 973 | } |
| 964 | dma_addr -= bp->rx_dma_offset; | 974 | dma_addr -= bp->rx_dma_offset; |
| 965 | dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir, | 975 | dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE, |
| 966 | DMA_ATTR_WEAK_ORDERING); | 976 | bp->rx_dir, DMA_ATTR_WEAK_ORDERING); |
| 967 | skb = build_skb(page_address(page), PAGE_SIZE); | 977 | skb = build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE); |
| 968 | if (!skb) { | 978 | if (!skb) { |
| 969 | page_pool_recycle_direct(rxr->page_pool, page); | 979 | page_pool_recycle_direct(rxr->page_pool, page); |
| 970 | return NULL; | 980 | return NULL; |
| 971 | } | 981 | } |
| 972 | skb_mark_for_recycle(skb); | 982 | skb_mark_for_recycle(skb); |
| 973 | skb_reserve(skb, bp->rx_dma_offset); | 983 | skb_reserve(skb, bp->rx_offset); |
| 974 | __skb_put(skb, len); | 984 | __skb_put(skb, len); |
| 975 | 985 | ||
| 976 | return skb; | 986 | return skb; |
| @@ -996,8 +1006,8 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp, · 19 unmodified lines | |||
| 996 | return NULL; | 1006 | return NULL; |
| 997 | } | 1007 | } |
| 998 | dma_addr -= bp->rx_dma_offset; | 1008 | dma_addr -= bp->rx_dma_offset; |
| 999 | dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir, | 1009 | dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE, |
| 1000 | DMA_ATTR_WEAK_ORDERING); | 1010 | bp->rx_dir, DMA_ATTR_WEAK_ORDERING); |
| 1001 | 1011 | ||
| 1002 | if (unlikely(!payload)) | 1012 | if (unlikely(!payload)) |
| 1003 | payload = eth_get_headlen(bp->dev, data_ptr, len); | 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 | skb_mark_for_recycle(skb); | 1021 | skb_mark_for_recycle(skb); |
| 1012 | off = (void *)data_ptr - page_address(page); | 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 | memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN, | 1024 | memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN, |
| 1015 | payload + NET_IP_ALIGN); | 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 | skb->data_len += total_frag_len; | 1152 | skb->data_len += total_frag_len; |
| 1143 | skb->len += total_frag_len; | 1153 | skb->len += total_frag_len; |
| 1144 | skb->truesize += PAGE_SIZE * agg_bufs; | 1154 | skb->truesize += BNXT_RX_PAGE_SIZE * agg_bufs; |
| 1145 | return skb; | 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 | return rx_pkts; | 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) { | 2585 | if (bnapi->tx_pkts) |
| 2575 | bnapi->tx_int(bp, bnapi, bnapi->tx_pkts); | 2586 | bnapi->tx_int(bp, bnapi, budget); |
| 2576 | bnapi->tx_pkts = 0; | ||
| 2577 | } | ||
| 2578 | 2587 | ||
| 2579 | if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) { | 2588 | if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) { |
| 2580 | struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; | 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 | bnxt_db_cq(bp, &cpr->cp_db, cpr->cp_raw_cons); | 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 | return rx_pkts; | 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 | static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi, | 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 | struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; | 2748 | struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; |
| 2740 | int i; | 2749 | int i; |
| @@ -2750,7 +2759,7 @@ static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi, · 9 unmodified lines | |||
| 2750 | cpr2->had_work_done = 0; | 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 | static int bnxt_poll_p5(struct napi_struct *napi, int budget) | 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 | if (cpr->has_more_work) | 2789 | if (cpr->has_more_work) |
| 2781 | break; | 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 | cpr->cp_raw_cons = raw_cons; | 2794 | cpr->cp_raw_cons = raw_cons; |
| 2785 | if (napi_complete_done(napi, work_done)) | 2795 | if (napi_complete_done(napi, work_done)) |
| 2786 | BNXT_DB_NQ_ARM_P5(&cpr->cp_db, | 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 | raw_cons = NEXT_RAW_CMP(raw_cons); | 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 | if (raw_cons != cpr->cp_raw_cons) { | 2824 | if (raw_cons != cpr->cp_raw_cons) { |
| 2815 | cpr->cp_raw_cons = raw_cons; | 2825 | cpr->cp_raw_cons = raw_cons; |
| 2816 | BNXT_DB_NQ_P5(&cpr->cp_db, raw_cons); | 2826 | BNXT_DB_NQ_P5(&cpr->cp_db, raw_cons); |
| @@ -2943,8 +2953,8 @@ skip_rx_tpa_free: · 126 unmodified lines | |||
| 2943 | rx_buf->data = NULL; | 2953 | rx_buf->data = NULL; |
| 2944 | if (BNXT_RX_PAGE_MODE(bp)) { | 2954 | if (BNXT_RX_PAGE_MODE(bp)) { |
| 2945 | mapping -= bp->rx_dma_offset; | 2955 | mapping -= bp->rx_dma_offset; |
| 2946 | dma_unmap_page_attrs(&pdev->dev, mapping, PAGE_SIZE, | 2956 | dma_unmap_page_attrs(&pdev->dev, mapping, |
| 2947 | bp->rx_dir, | 2957 | BNXT_RX_PAGE_SIZE, bp->rx_dir, |
| 2948 | DMA_ATTR_WEAK_ORDERING); | 2958 | DMA_ATTR_WEAK_ORDERING); |
| 2949 | page_pool_recycle_direct(rxr->page_pool, data); | 2959 | page_pool_recycle_direct(rxr->page_pool, data); |
| 2950 | } else { | 2960 | } else { |
| @@ -3213,6 +3223,8 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp, · 262 unmodified lines | |||
| 3213 | pp.napi = &rxr->bnapi->napi; | 3223 | pp.napi = &rxr->bnapi->napi; |
| 3214 | pp.dev = &bp->pdev->dev; | 3224 | pp.dev = &bp->pdev->dev; |
| 3215 | pp.dma_dir = DMA_BIDIRECTIONAL; | 3225 | pp.dma_dir = DMA_BIDIRECTIONAL; |
| 3226 | if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) | ||
| 3227 | pp.flags |= PP_FLAG_PAGE_FRAG; | ||
| 3216 | 3228 | ||
| 3217 | rxr->page_pool = page_pool_create(&pp); | 3229 | rxr->page_pool = page_pool_create(&pp); |
| 3218 | if (IS_ERR(rxr->page_pool)) { | 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 | int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode) | 4002 | int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode) |
| 3991 | { | 4003 | { |
| 4004 | struct net_device *dev = bp->dev; | ||
| 4005 | |||
| 3992 | if (page_mode) { | 4006 | if (page_mode) { |
| 3993 | bp->flags &= ~BNXT_FLAG_AGG_RINGS; | 4007 | bp->flags &= ~BNXT_FLAG_AGG_RINGS; |
| 3994 | bp->flags |= BNXT_FLAG_RX_PAGE_MODE; | 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 | bp->flags |= BNXT_FLAG_JUMBO; | 4016 | bp->flags |= BNXT_FLAG_JUMBO; |
| 3998 | bp->rx_skb_func = bnxt_rx_multi_page_skb; | 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 | } else { | 4018 | } else { |
| 4002 | bp->flags |= BNXT_FLAG_NO_AGG_RINGS; | 4019 | bp->flags |= BNXT_FLAG_NO_AGG_RINGS; |
| 4003 | bp->rx_skb_func = bnxt_rx_page_skb; | 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 | bp->rx_dir = DMA_BIDIRECTIONAL; | 4022 | bp->rx_dir = DMA_BIDIRECTIONAL; |
| 4008 | /* Disable LRO or GRO_HW */ | 4023 | /* Disable LRO or GRO_HW */ |
| 4009 | netdev_update_features(bp->dev); | 4024 | netdev_update_features(dev); |
| 4010 | } else { | 4025 | } else { |
| 4011 | bp->dev->max_mtu = bp->max_mtu; | 4026 | dev->max_mtu = bp->max_mtu; |
| 4012 | bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE; | 4027 | bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE; |
| 4013 | bp->rx_dir = DMA_FROM_DEVICE; | 4028 | bp->rx_dir = DMA_FROM_DEVICE; |
| 4014 | bp->rx_skb_func = bnxt_rx_skb; | 4029 | bp->rx_skb_func = bnxt_rx_skb; |
| @@ -9429,6 +9444,8 @@ static void bnxt_enable_napi(struct bnxt *bp) · 5414 unmodified lines | |||
| 9429 | cpr->sw_stats.rx.rx_resets++; | 9444 | cpr->sw_stats.rx.rx_resets++; |
| 9430 | bnapi->in_reset = false; | 9445 | bnapi->in_reset = false; |
| 9431 | 9446 | ||
| 9447 | bnapi->tx_pkts = 0; | ||
| 9448 | |||
| 9432 | if (bnapi->rx_ring) { | 9449 | if (bnapi->rx_ring) { |
| 9433 | INIT_WORK(&cpr->dim.work, bnxt_dim_work); | 9450 | INIT_WORK(&cpr->dim.work, bnxt_dim_work); |
| 9434 | cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; | 9451 | cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; |
| @@ -1005,7 +1005,7 @@ struct bnxt_napi { · 1004 unmodified lines | |||
| 1005 | struct bnxt_tx_ring_info *tx_ring; | 1005 | struct bnxt_tx_ring_info *tx_ring; |
| 1006 | 1006 | ||
| 1007 | void (*tx_int)(struct bnxt *, struct bnxt_napi *, | 1007 | void (*tx_int)(struct bnxt *, struct bnxt_napi *, |
| 1008 | int); | 1008 | int budget); |
| 1009 | int tx_pkts; | 1009 | int tx_pkts; |
| 1010 | u8 events; | 1010 | u8 events; |
| 1011 | 1011 | ||
| @@ -125,16 +125,20 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp, · 124 unmodified lines | |||
| 125 | dma_unmap_len_set(tx_buf, len, 0); | 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 | struct bnxt_tx_ring_info *txr = bnapi->tx_ring; | 130 | struct bnxt_tx_ring_info *txr = bnapi->tx_ring; |
| 131 | struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; | 131 | struct bnxt_rx_ring_info *rxr = bnapi->rx_ring; |
| 132 | bool rx_doorbell_needed = false; | 132 | bool rx_doorbell_needed = false; |
| 133 | int nr_pkts = bnapi->tx_pkts; | ||
| 133 | struct bnxt_sw_tx_bd *tx_buf; | 134 | struct bnxt_sw_tx_bd *tx_buf; |
| 134 | u16 tx_cons = txr->tx_cons; | 135 | u16 tx_cons = txr->tx_cons; |
| 135 | u16 last_tx_cons = tx_cons; | 136 | u16 last_tx_cons = tx_cons; |
| 136 | int i, j, frags; | 137 | int i, j, frags; |
| 137 | 138 | ||
| 139 | if (!budget) | ||
| 140 | return; | ||
| 141 | |||
| 138 | for (i = 0; i < nr_pkts; i++) { | 142 | for (i = 0; i < nr_pkts; i++) { |
| 139 | tx_buf = &txr->tx_buf_ring[tx_cons]; | 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 | tx_cons = NEXT_TX(tx_cons); | 166 | tx_cons = NEXT_TX(tx_cons); |
| 163 | } | 167 | } |
| 168 | |||
| 169 | bnapi->tx_pkts = 0; | ||
| 164 | WRITE_ONCE(txr->tx_cons, tx_cons); | 170 | WRITE_ONCE(txr->tx_cons, tx_cons); |
| 165 | if (rx_doorbell_needed) { | 171 | if (rx_doorbell_needed) { |
| 166 | tx_buf = &txr->tx_buf_ring[last_tx_cons]; | 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 | u16 cons, u8 *data_ptr, unsigned int len, | 186 | u16 cons, u8 *data_ptr, unsigned int len, |
| 181 | struct xdp_buff *xdp) | 187 | struct xdp_buff *xdp) |
| 182 | { | 188 | { |
| 189 | u32 buflen = BNXT_RX_PAGE_SIZE; | ||
| 183 | struct bnxt_sw_rx_bd *rx_buf; | 190 | struct bnxt_sw_rx_bd *rx_buf; |
| 184 | u32 buflen = PAGE_SIZE; | ||
| 185 | struct pci_dev *pdev; | 191 | struct pci_dev *pdev; |
| 186 | dma_addr_t mapping; | 192 | dma_addr_t mapping; |
| 187 | u32 offset; | 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 | rx_buf = &rxr->rx_buf_ring[cons]; | 303 | rx_buf = &rxr->rx_buf_ring[cons]; |
| 298 | mapping = rx_buf->mapping - bp->rx_dma_offset; | 304 | mapping = rx_buf->mapping - bp->rx_dma_offset; |
| 299 | dma_unmap_page_attrs(&pdev->dev, mapping, | 305 | dma_unmap_page_attrs(&pdev->dev, mapping, |
| 300 | PAGE_SIZE, bp->rx_dir, | 306 | BNXT_RX_PAGE_SIZE, bp->rx_dir, |
| 301 | DMA_ATTR_WEAK_ORDERING); | 307 | DMA_ATTR_WEAK_ORDERING); |
| 302 | 308 | ||
| 303 | /* if we are unable to allocate a new buffer, abort and reuse */ | 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 | xdp_update_skb_shared_info(skb, num_frags, | 487 | xdp_update_skb_shared_info(skb, num_frags, |
| 482 | sinfo->xdp_frags_size, | 488 | sinfo->xdp_frags_size, |
| 483 | PAGE_SIZE * sinfo->nr_frags, | 489 | BNXT_RX_PAGE_SIZE * sinfo->nr_frags, |
| 484 | xdp_buff_is_frag_pfmemalloc(xdp)); | 490 | xdp_buff_is_frag_pfmemalloc(xdp)); |
| 485 | return skb; | 491 | return skb; |
| 486 | } | 492 | } |
| @@ -16,7 +16,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp, · 15 unmodified lines | |||
| 16 | struct bnxt_tx_ring_info *txr, | 16 | struct bnxt_tx_ring_info *txr, |
| 17 | dma_addr_t mapping, u32 len, | 17 | dma_addr_t mapping, u32 len, |
| 18 | struct xdp_buff *xdp); | 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 | bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, | 20 | bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, |
| 21 | struct xdp_buff xdp, struct page *page, u8 **data_ptr, | 21 | struct xdp_buff xdp, struct page *page, u8 **data_ptr, |
| 22 | unsigned int *len, u8 *event); | 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 | static int enetc_pf_register_with_ierb(struct pci_dev *pdev) | 1187 | static int enetc_pf_register_with_ierb(struct pci_dev *pdev) |
| 1188 | { | 1188 | { |
| 1189 | struct device_node *node = pdev->dev.of_node; | ||
| 1190 | struct platform_device *ierb_pdev; | 1189 | struct platform_device *ierb_pdev; |
| 1191 | struct device_node *ierb_node; | 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 | ierb_node = of_find_compatible_node(NULL, NULL, | 1192 | ierb_node = of_find_compatible_node(NULL, NULL, |
| 1198 | "fsl,ls1028a-enetc-ierb"); | 1193 | "fsl,ls1028a-enetc-ierb"); |
| 1199 | if (!ierb_node || !of_device_is_available(ierb_node)) | 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 | return enetc_ierb_register_pf(ierb_pdev, pdev); | 1203 | return enetc_ierb_register_pf(ierb_pdev, pdev); |
| 1209 | } | 1204 | } |
| 1210 | 1205 | ||
| 1211 | static int enetc_pf_probe(struct pci_dev *pdev, | 1206 | static struct enetc_si *enetc_psi_create(struct pci_dev *pdev) |
| 1212 | const struct pci_device_id *ent) | ||
| 1213 | { | 1207 | { |
| 1214 | struct device_node *node = pdev->dev.of_node; | ||
| 1215 | struct enetc_ndev_priv *priv; | ||
| 1216 | struct net_device *ndev; | ||
| 1217 | struct enetc_si *si; | 1208 | struct enetc_si *si; |
| 1218 | struct enetc_pf *pf; | ||
| 1219 | int err; | 1209 | int err; |
| 1220 | 1210 | ||
| 1221 | err = enetc_pf_register_with_ierb(pdev); | 1211 | err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(struct enetc_pf)); |
| 1222 | if (err == -EPROBE_DEFER) | 1212 | if (err) { |
| 1223 | return err; | 1213 | dev_err_probe(&pdev->dev, err, "PCI probing failed\n"); |
| 1224 | if (err) | 1214 | goto out; |
| 1225 | dev_warn(&pdev->dev, | 1215 | } |
| 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"); | ||
| 1232 | 1216 | ||
| 1233 | si = pci_get_drvdata(pdev); | 1217 | si = pci_get_drvdata(pdev); |
| 1234 | if (!si->hw.port || !si->hw.global) { | 1218 | if (!si->hw.port || !si->hw.global) { |
| 1235 | err = -ENODEV; | 1219 | err = -ENODEV; |
| 1236 | dev_err(&pdev->dev, "could not map PF space, probing a VF?\n"); | 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 | err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE, | 1224 | err = enetc_setup_cbdr(&pdev->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE, |
| 1241 | &si->cbd_ring); | 1225 | &si->cbd_ring); |
| 1242 | if (err) | 1226 | if (err) |
| 1243 | goto err_setup_cbdr; | 1227 | goto out_pci_remove; |
| 1244 | 1228 | ||
| 1245 | err = enetc_init_port_rfs_memory(si); | 1229 | err = enetc_init_port_rfs_memory(si); |
| 1246 | if (err) { | 1230 | if (err) { |
| 1247 | dev_err(&pdev->dev, "Failed to initialize RFS memory\n"); | 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 | err = enetc_init_port_rss_memory(si); | 1235 | err = enetc_init_port_rss_memory(si); |
| 1252 | if (err) { | 1236 | if (err) { |
| 1253 | dev_err(&pdev->dev, "Failed to initialize RSS memory\n"); | 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)) { | 1241 | return si; |
| 1258 | dev_info(&pdev->dev, "device is disabled, skipping\n"); | 1242 | |
| 1259 | err = -ENODEV; | 1243 | out_teardown_cbdr: |
| 1260 | goto err_device_disabled; | 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 | pf = enetc_si_priv(si); | 1283 | pf = enetc_si_priv(si); |
| @@ -1339,15 +1359,9 @@ err_alloc_si_res: · 75 unmodified lines | |||
| 1339 | si->ndev = NULL; | 1359 | si->ndev = NULL; |
| 1340 | free_netdev(ndev); | 1360 | free_netdev(ndev); |
| 1341 | err_alloc_netdev: | 1361 | err_alloc_netdev: |
| 1342 | err_init_port_rss: | ||
| 1343 | err_init_port_rfs: | ||
| 1344 | err_device_disabled: | ||
| 1345 | err_setup_mac_addresses: | 1362 | err_setup_mac_addresses: |
| 1346 | enetc_teardown_cbdr(&si->cbd_ring); | 1363 | enetc_psi_destroy(pdev); |
| 1347 | err_setup_cbdr: | 1364 | err_psi_create: |
| 1348 | err_map_pf_space: | ||
| 1349 | enetc_pci_remove(pdev); | ||
| 1350 | |||
| 1351 | return err; | 1365 | return err; |
| 1352 | } | 1366 | } |
| 1353 | 1367 | ||
| @@ -1370,12 +1384,29 @@ static void enetc_pf_remove(struct pci_dev *pdev) · 16 unmodified lines | |||
| 1370 | enetc_free_msix(priv); | 1384 | enetc_free_msix(priv); |
| 1371 | 1385 | ||
| 1372 | enetc_free_si_resources(priv); | 1386 | enetc_free_si_resources(priv); |
| 1373 | enetc_teardown_cbdr(&si->cbd_ring); | ||
| 1374 | 1387 | ||
| 1375 | free_netdev(si->ndev); | 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 | static const struct pci_device_id enetc_pf_id_table[] = { | 1411 | static const struct pci_device_id enetc_pf_id_table[] = { |
| 1381 | { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_PF) }, | 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 | if (result) { | 464 | if (result) { |
| 465 | if (item_len < strlen(result[i])) | 465 | if (item_len < strlen(result[i])) |
| 466 | break; | 466 | break; |
| 467 | strscpy(pos, result[i], strlen(result[i])); | 467 | memcpy(pos, result[i], strlen(result[i])); |
| 468 | } else { | 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 | pos += item_len; | 471 | pos += item_len; |
| 472 | len -= item_len; | 472 | len -= item_len; |
| @@ -5854,6 +5854,9 @@ void hns3_external_lb_prepare(struct net_device *ndev, bool if_running) · 5853 unmodified lines | |||
| 5854 | if (!if_running) | 5854 | if (!if_running) |
| 5855 | return; | 5855 | return; |
| 5856 | 5856 | ||
| 5857 | if (test_and_set_bit(HNS3_NIC_STATE_DOWN, &priv->state)) | ||
| 5858 | return; | ||
| 5859 | |||
| 5857 | netif_carrier_off(ndev); | 5860 | netif_carrier_off(ndev); |
| 5858 | netif_tx_disable(ndev); | 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 | if (!if_running) | 5885 | if (!if_running) |
| 5883 | return; | 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 | for (i = 0; i < priv->vector_num; i++) | 5899 | for (i = 0; i < priv->vector_num; i++) |
| 5888 | hns3_vector_enable(&priv->tqp_vector[i]); | 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 | if (result) { | 111 | if (result) { |
| 112 | if (item_len < strlen(result[i])) | 112 | if (item_len < strlen(result[i])) |
| 113 | break; | 113 | break; |
| 114 | strscpy(pos, result[i], strlen(result[i])); | 114 | memcpy(pos, result[i], strlen(result[i])); |
| 115 | } else { | 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 | pos += item_len; | 118 | pos += item_len; |
| 119 | len -= item_len; | 119 | len -= item_len; |
| @@ -72,6 +72,8 @@ static void hclge_restore_hw_table(struct hclge_dev *hdev); · 71 unmodified lines | |||
| 72 | static void hclge_sync_promisc_mode(struct hclge_dev *hdev); | 72 | static void hclge_sync_promisc_mode(struct hclge_dev *hdev); |
| 73 | static void hclge_sync_fd_table(struct hclge_dev *hdev); | 73 | static void hclge_sync_fd_table(struct hclge_dev *hdev); |
| 74 | static void hclge_update_fec_stats(struct hclge_dev *hdev); | 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 | static struct hnae3_ae_algo ae_algo; | 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 | static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable) | 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 | struct hclge_desc desc; | 7565 | struct hclge_desc desc; |
| 7562 | struct hclge_config_mac_mode_cmd *req = | 7566 | struct hclge_config_mac_mode_cmd *req = |
| 7563 | (struct hclge_config_mac_mode_cmd *)desc.data; | 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 | req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en); | 7586 | req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en); |
| 7583 | 7587 | ||
| 7584 | ret = hclge_cmd_send(&hdev->hw, &desc, 1); | 7588 | ret = hclge_cmd_send(&hdev->hw, &desc, 1); |
| 7585 | if (ret) | 7589 | if (ret) { |
| 7586 | dev_err(&hdev->pdev->dev, | 7590 | dev_err(&hdev->pdev->dev, |
| 7587 | "mac enable fail, ret =%d.\n", ret); | 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 | static int hclge_config_switch_param(struct hclge_dev *hdev, int vfid, | 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 | } while (++i < HCLGE_PHY_LINK_STATUS_NUM); | 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 | int link_status; | 7663 | int link_status; |
| 7655 | int i = 0; | 7664 | int i = 0; |
| 7656 | int ret; | 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 | return 0; | 7672 | return 0; |
| 7664 | 7673 | ||
| 7665 | msleep(HCLGE_LINK_STATUS_MS); | 7674 | msleep(HCLGE_LINK_STATUS_MS); |
| 7666 | } while (++i < HCLGE_MAC_LINK_STATUS_NUM); | 7675 | } while (++i < wait_cnt); |
| 7667 | return -EBUSY; | 7676 | return -EBUSY; |
| 7668 | } | 7677 | } |
| 7669 | 7678 | ||
| 7670 | static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en, | 7679 | static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en, |
| 7671 | bool is_phy) | 7680 | bool is_phy) |
| 7672 | { | 7681 | { |
| 7682 | #define HCLGE_MAC_LINK_STATUS_NUM 100 | ||
| 7683 | |||
| 7673 | int link_ret; | 7684 | int link_ret; |
| 7674 | 7685 | ||
| 7675 | link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN; | 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 | if (is_phy) | 7688 | if (is_phy) |
| 7678 | hclge_phy_link_status_wait(hdev, link_ret); | 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 | static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en) | 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 | u32 rx_pause, tx_pause; | 10927 | u32 rx_pause, tx_pause; |
| 10916 | u8 flowctl; | 10928 | u8 flowctl; |
| 10917 | 10929 | ||
| 10918 | if (!phydev->link || !phydev->autoneg) | 10930 | if (!phydev->link) |
| 10919 | return 0; | 10931 | return 0; |
| 10920 | 10932 | ||
| 10933 | if (!phydev->autoneg) | ||
| 10934 | return hclge_mac_pause_setup_hw(hdev); | ||
| 10935 | |||
| 10921 | local_advertising = linkmode_adv_to_lcl_adv_t(phydev->advertising); | 10936 | local_advertising = linkmode_adv_to_lcl_adv_t(phydev->advertising); |
| 10922 | 10937 | ||
| 10923 | if (phydev->pause) | 10938 | if (phydev->pause) |
| @@ -1553,7 +1553,7 @@ static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc) · 1552 unmodified lines | |||
| 1553 | return 0; | 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 | bool tx_en, rx_en; | 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 | u8 pfc_bitmap); | 245 | u8 pfc_bitmap); |
| 246 | int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx); | 246 | int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx); |
| 247 | int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr); | 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 | void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); | 249 | void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats); |
| 249 | void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats); | 250 | void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats); |
| 250 | int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate); | 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 | static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *, | 97 | static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *, |
| 98 | struct ibmvnic_sub_crq_queue *); | 98 | struct ibmvnic_sub_crq_queue *); |
| 99 | static int ibmvnic_poll(struct napi_struct *napi, int data); | 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 | static void send_query_map(struct ibmvnic_adapter *adapter); | 102 | static void send_query_map(struct ibmvnic_adapter *adapter); |
| 101 | static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, u32, u8); | 103 | static int send_request_map(struct ibmvnic_adapter *, dma_addr_t, u32, u8); |
| 102 | static int send_request_unmap(struct ibmvnic_adapter *, u8); | 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 | static void free_long_term_buff(struct ibmvnic_adapter *adapter, | 116 | static void free_long_term_buff(struct ibmvnic_adapter *adapter, |
| 115 | struct ibmvnic_long_term_buff *ltb); | 117 | struct ibmvnic_long_term_buff *ltb); |
| 116 | static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter); | 118 | static void ibmvnic_disable_irqs(struct ibmvnic_adapter *adapter); |
| 119 | static void flush_reset_queue(struct ibmvnic_adapter *adapter); | ||
| 117 | 120 | ||
| 118 | struct ibmvnic_stat { | 121 | struct ibmvnic_stat { |
| 119 | char name[ETH_GSTRING_LEN]; | 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 | static int ibmvnic_login(struct net_device *netdev) | 1509 | static int ibmvnic_login(struct net_device *netdev) |
| 1507 | { | 1510 | { |
| 1511 | unsigned long flags, timeout = msecs_to_jiffies(20000); | ||
| 1508 | struct ibmvnic_adapter *adapter = netdev_priv(netdev); | 1512 | struct ibmvnic_adapter *adapter = netdev_priv(netdev); |
| 1509 | unsigned long timeout = msecs_to_jiffies(20000); | ||
| 1510 | int retry_count = 0; | 1513 | int retry_count = 0; |
| 1511 | int retries = 10; | 1514 | int retries = 10; |
| 1512 | bool retry; | 1515 | bool retry; |
| @@ -1527,11 +1530,9 @@ static int ibmvnic_login(struct net_device *netdev) · 14 unmodified lines | |||
| 1527 | 1530 | ||
| 1528 | if (!wait_for_completion_timeout(&adapter->init_done, | 1531 | if (!wait_for_completion_timeout(&adapter->init_done, |
| 1529 | timeout)) { | 1532 | timeout)) { |
| 1530 | netdev_warn(netdev, "Login timed out, retrying...\n"); | 1533 | netdev_warn(netdev, "Login timed out\n"); |
| 1531 | retry = true; | 1534 | adapter->login_pending = false; |
| 1532 | adapter->init_done_rc = 0; | 1535 | goto partial_reset; |
| 1533 | retry_count++; | ||
| 1534 | continue; | ||
| 1535 | } | 1536 | } |
| 1536 | 1537 | ||
| 1537 | if (adapter->init_done_rc == ABORTED) { | 1538 | if (adapter->init_done_rc == ABORTED) { |
| @@ -1573,10 +1574,69 @@ static int ibmvnic_login(struct net_device *netdev) · 35 unmodified lines | |||
| 1573 | "SCRQ irq initialization failed\n"); | 1574 | "SCRQ irq initialization failed\n"); |
| 1574 | return rc; | 1575 | return rc; |
| 1575 | } | 1576 | } |
| 1577 | /* Default/timeout error handling, reset and start fresh */ | ||
| 1576 | } else if (adapter->init_done_rc) { | 1578 | } else if (adapter->init_done_rc) { |
| 1577 | netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n", | 1579 | netdev_warn(netdev, "Adapter login failed, init_done_rc = %d\n", |
| 1578 | adapter->init_done_rc); | 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 | } while (retry); | 1641 | } while (retry); |
| 1582 | 1642 | ||
| @@ -1588,12 +1648,22 @@ static int ibmvnic_login(struct net_device *netdev) · 5 unmodified lines | |||
| 1588 | 1648 | ||
| 1589 | static void release_login_buffer(struct ibmvnic_adapter *adapter) | 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 | kfree(adapter->login_buf); | 1656 | kfree(adapter->login_buf); |
| 1592 | adapter->login_buf = NULL; | 1657 | adapter->login_buf = NULL; |
| 1593 | } | 1658 | } |
| 1594 | 1659 | ||
| 1595 | static void release_login_rsp_buffer(struct ibmvnic_adapter *adapter) | 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 | kfree(adapter->login_rsp_buf); | 1667 | kfree(adapter->login_rsp_buf); |
| 1598 | adapter->login_rsp_buf = NULL; | 1668 | adapter->login_rsp_buf = NULL; |
| 1599 | } | 1669 | } |
| @@ -4830,11 +4900,14 @@ static int send_login(struct ibmvnic_adapter *adapter) · 3230 unmodified lines | |||
| 4830 | if (rc) { | 4900 | if (rc) { |
| 4831 | adapter->login_pending = false; | 4901 | adapter->login_pending = false; |
| 4832 | netdev_err(adapter->netdev, "Failed to send login, rc=%d\n", rc); | 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 | return 0; | 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 | buf_rsp_map_failed: | 4911 | buf_rsp_map_failed: |
| 4839 | kfree(login_rsp_buffer); | 4912 | kfree(login_rsp_buffer); |
| 4840 | adapter->login_rsp_buf = NULL; | 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 | int num_tx_pools; | 5469 | int num_tx_pools; |
| 5397 | int num_rx_pools; | 5470 | int num_rx_pools; |
| 5398 | u64 *size_array; | 5471 | u64 *size_array; |
| 5472 | u32 rsp_len; | ||
| 5399 | int i; | 5473 | int i; |
| 5400 | 5474 | ||
| 5401 | /* CHECK: Test/set of login_pending does not need to be atomic | 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 | adapter->login_pending = false; | 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 | /* If the number of queues requested can't be allocated by the | 5484 | /* If the number of queues requested can't be allocated by the |
| 5416 | * server, the login response will return with code 1. We will need | 5485 | * server, the login response will return with code 1. We will need |
| 5417 | * to resend the login buffer with fewer queues requested. | 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 | ibmvnic_reset(adapter, VNIC_RESET_FATAL); | 5516 | ibmvnic_reset(adapter, VNIC_RESET_FATAL); |
| 5448 | return -EIO; | 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 | size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) + | 5536 | size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) + |
| 5451 | be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size)); | 5537 | be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size)); |
| 5452 | /* variable buffer sizes are not supported, so just read the | 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 | if (fsp->flow_type & FLOW_MAC_EXT) | 1401 | if (fsp->flow_type & FLOW_MAC_EXT) |
| 1402 | return -EINVAL; | 1402 | return -EINVAL; |
| 1403 | 1403 | ||
| 1404 | spin_lock_bh(&adapter->fdir_fltr_lock); | ||
| 1404 | if (adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS) { | 1405 | if (adapter->fdir_active_fltr >= IAVF_MAX_FDIR_FILTERS) { |
| 1406 | spin_unlock_bh(&adapter->fdir_fltr_lock); | ||
| 1405 | dev_err(&adapter->pdev->dev, | 1407 | dev_err(&adapter->pdev->dev, |
| 1406 | "Unable to add Flow Director filter because VF reached the limit of max allowed filters (%u)\n", | 1408 | "Unable to add Flow Director filter because VF reached the limit of max allowed filters (%u)\n", |
| 1407 | IAVF_MAX_FDIR_FILTERS); | 1409 | IAVF_MAX_FDIR_FILTERS); |
| 1408 | return -ENOSPC; | 1410 | return -ENOSPC; |
| 1409 | } | 1411 | } |
| 1410 | 1412 | ||
| 1411 | spin_lock_bh(&adapter->fdir_fltr_lock); | ||
| 1412 | if (iavf_find_fdir_fltr_by_loc(adapter, fsp->location)) { | 1413 | if (iavf_find_fdir_fltr_by_loc(adapter, fsp->location)) { |
| 1413 | dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n"); | 1414 | dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, it already exists\n"); |
| 1414 | spin_unlock_bh(&adapter->fdir_fltr_lock); | 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 | case ETHTOOL_GRXCLSRLCNT: | 1782 | case ETHTOOL_GRXCLSRLCNT: |
| 1782 | if (!FDIR_FLTR_SUPPORT(adapter)) | 1783 | if (!FDIR_FLTR_SUPPORT(adapter)) |
| 1783 | break; | 1784 | break; |
| 1785 | spin_lock_bh(&adapter->fdir_fltr_lock); | ||
| 1784 | cmd->rule_cnt = adapter->fdir_active_fltr; | 1786 | cmd->rule_cnt = adapter->fdir_active_fltr; |
| 1787 | spin_unlock_bh(&adapter->fdir_fltr_lock); | ||
| 1785 | cmd->data = IAVF_MAX_FDIR_FILTERS; | 1788 | cmd->data = IAVF_MAX_FDIR_FILTERS; |
| 1786 | ret = 0; | 1789 | ret = 0; |
| 1787 | break; | 1790 | break; |
| @@ -722,7 +722,9 @@ void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *f · 721 unmodified lines | |||
| 722 | bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr) | 722 | bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr) |
| 723 | { | 723 | { |
| 724 | struct iavf_fdir_fltr *tmp; | 724 | struct iavf_fdir_fltr *tmp; |
| 725 | bool ret = false; | ||
| 725 | 726 | ||
| 727 | spin_lock_bh(&adapter->fdir_fltr_lock); | ||
| 726 | list_for_each_entry(tmp, &adapter->fdir_list_head, list) { | 728 | list_for_each_entry(tmp, &adapter->fdir_list_head, list) { |
| 727 | if (tmp->flow_type != fltr->flow_type) | 729 | if (tmp->flow_type != fltr->flow_type) |
| 728 | continue; | 730 | continue; |
| @@ -732,11 +734,14 @@ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr * · 3 unmodified lines | |||
| 732 | !memcmp(&tmp->ip_data, &fltr->ip_data, | 734 | !memcmp(&tmp->ip_data, &fltr->ip_data, |
| 733 | sizeof(fltr->ip_data)) && | 735 | sizeof(fltr->ip_data)) && |
| 734 | !memcmp(&tmp->ext_data, &fltr->ext_data, | 736 | !memcmp(&tmp->ext_data, &fltr->ext_data, |
| 735 | sizeof(fltr->ext_data))) | 737 | sizeof(fltr->ext_data))) { |
| 736 | return true; | 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 | struct ice_netdev_priv *np = netdev_priv(netdev); | 8814 | struct ice_netdev_priv *np = netdev_priv(netdev); |
| 8815 | struct ice_pf *pf = np->vsi->back; | 8815 | struct ice_pf *pf = np->vsi->back; |
| 8816 | bool locked = false; | ||
| 8816 | int err; | 8817 | int err; |
| 8817 | 8818 | ||
| 8818 | switch (type) { | 8819 | switch (type) { |
| @@ -8822,10 +8823,27 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type, · 3 unmodified lines | |||
| 8822 | ice_setup_tc_block_cb, | 8823 | ice_setup_tc_block_cb, |
| 8823 | np, np, true); | 8824 | np, np, true); |
| 8824 | case TC_SETUP_QDISC_MQPRIO: | 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 | /* setup traffic classifier for receive side */ | 8837 | /* setup traffic classifier for receive side */ |
| 8826 | mutex_lock(&pf->tc_mutex); | 8838 | mutex_lock(&pf->tc_mutex); |
| 8827 | err = ice_setup_tc_mqprio_qdisc(netdev, type_data); | 8839 | err = ice_setup_tc_mqprio_qdisc(netdev, type_data); |
| 8828 | mutex_unlock(&pf->tc_mutex); | 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 | return err; | 8847 | return err; |
| 8830 | default: | 8848 | default: |
| 8831 | return -EOPNOTSUPP; | 8849 | return -EOPNOTSUPP; |
| @@ -195,6 +195,10 @@ struct igc_adapter { · 194 unmodified lines | |||
| 195 | u32 qbv_config_change_errors; | 195 | u32 qbv_config_change_errors; |
| 196 | bool qbv_transition; | 196 | bool qbv_transition; |
| 197 | unsigned int qbv_count; | 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 | /* OS defined structs */ | 203 | /* OS defined structs */ |
| 200 | struct pci_dev *pdev; | 204 | struct pci_dev *pdev; |
| @@ -4801,6 +4801,7 @@ static int igc_sw_init(struct igc_adapter *adapter) · 4800 unmodified lines | |||
| 4801 | adapter->nfc_rule_count = 0; | 4801 | adapter->nfc_rule_count = 0; |
| 4802 | 4802 | ||
| 4803 | spin_lock_init(&adapter->stats64_lock); | 4803 | spin_lock_init(&adapter->stats64_lock); |
| 4804 | spin_lock_init(&adapter->qbv_tx_lock); | ||
| 4804 | /* Assume MSI-X interrupts, will be checked during IRQ allocation */ | 4805 | /* Assume MSI-X interrupts, will be checked during IRQ allocation */ |
| 4805 | adapter->flags |= IGC_FLAG_HAS_MSIX; | 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 | return igc_tsn_offload_apply(adapter); | 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 | int i; | 6126 | int i; |
| 6125 | 6127 | ||
| 6126 | adapter->base_time = 0; | 6128 | adapter->base_time = 0; |
| 6127 | adapter->cycle_time = NSEC_PER_SEC; | 6129 | adapter->cycle_time = NSEC_PER_SEC; |
| 6128 | adapter->taprio_offload_enable = false; | 6130 | adapter->taprio_offload_enable = false; |
| 6129 | adapter->qbv_config_change_errors = 0; | 6131 | adapter->qbv_config_change_errors = 0; |
| 6130 | adapter->qbv_transition = false; | ||
| 6131 | adapter->qbv_count = 0; | 6132 | adapter->qbv_count = 0; |
| 6132 | 6133 | ||
| 6133 | for (i = 0; i < adapter->num_tx_queues; i++) { | 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 | ring->start_time = 0; | 6137 | ring->start_time = 0; |
| 6137 | ring->end_time = NSEC_PER_SEC; | 6138 | ring->end_time = NSEC_PER_SEC; |
| 6138 | ring->max_sdu = 0; | 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 | ring->oper_gate_closed = false; | 6149 | ring->oper_gate_closed = false; |
| 6140 | ring->admin_gate_closed = false; | 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 | return 0; | 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 | struct igc_hw *hw = &adapter->hw; | 6169 | struct igc_hw *hw = &adapter->hw; |
| 6151 | u32 start_time = 0, end_time = 0; | 6170 | u32 start_time = 0, end_time = 0; |
| 6152 | struct timespec64 now; | 6171 | struct timespec64 now; |
| 6172 | unsigned long flags; | ||
| 6153 | size_t n; | 6173 | size_t n; |
| 6154 | int i; | 6174 | int i; |
| 6155 | 6175 | ||
| @@ -6217,6 +6237,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, · 61 unmodified lines | |||
| 6217 | start_time += e->interval; | 6237 | start_time += e->interval; |
| 6218 | } | 6238 | } |
| 6219 | 6239 | ||
| 6240 | spin_lock_irqsave(&adapter->qbv_tx_lock, flags); | ||
| 6241 | |||
| 6220 | /* Check whether a queue gets configured. | 6242 | /* Check whether a queue gets configured. |
| 6221 | * If not, set the start and end time to be end time. | 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 | for (i = 0; i < adapter->num_tx_queues; i++) { | 6268 | for (i = 0; i < adapter->num_tx_queues; i++) { |
| 6245 | struct igc_ring *ring = adapter->tx_ring[i]; | 6269 | struct igc_ring *ring = adapter->tx_ring[i]; |
| 6246 | struct net_device *dev = adapter->netdev; | 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 | struct igc_adapter *adapter = container_of(timer, struct igc_adapter, | 6644 | struct igc_adapter *adapter = container_of(timer, struct igc_adapter, |
| 6621 | hrtimer); | 6645 | hrtimer); |
| 6646 | unsigned long flags; | ||
| 6622 | unsigned int i; | 6647 | unsigned int i; |
| 6623 | 6648 | ||
| 6649 | spin_lock_irqsave(&adapter->qbv_tx_lock, flags); | ||
| 6650 | |||
| 6624 | adapter->qbv_transition = true; | 6651 | adapter->qbv_transition = true; |
| 6625 | for (i = 0; i < adapter->num_tx_queues; i++) { | 6652 | for (i = 0; i < adapter->num_tx_queues; i++) { |
| 6626 | struct igc_ring *tx_ring = adapter->tx_ring[i]; | 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 | adapter->qbv_transition = false; | 6662 | adapter->qbv_transition = false; |
| 6663 | |||
| 6664 | spin_unlock_irqrestore(&adapter->qbv_tx_lock, flags); | ||
| 6665 | |||
| 6636 | return HRTIMER_NORESTART; | 6666 | return HRTIMER_NORESTART; |
| 6637 | } | 6667 | } |
| 6638 | 6668 | ||
| @@ -1302,11 +1302,10 @@ static int korina_probe(struct platform_device *pdev) · 1301 unmodified lines | |||
| 1302 | else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0) | 1302 | else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0) |
| 1303 | eth_hw_addr_random(dev); | 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 | if (IS_ERR(clk)) | 1306 | if (IS_ERR(clk)) |
| 1307 | return PTR_ERR(clk); | 1307 | return PTR_ERR(clk); |
| 1308 | if (clk) { | 1308 | if (clk) { |
| 1309 | clk_prepare_enable(clk); | ||
| 1310 | lp->mii_clock_freq = clk_get_rate(clk); | 1309 | lp->mii_clock_freq = clk_get_rate(clk); |
| 1311 | } else { | 1310 | } else { |
| 1312 | lp->mii_clock_freq = 200000000; /* max possible input clk */ | 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 | writeq(OCTEP_CTRL_MBOX_STATUS_INIT, | 98 | writeq(OCTEP_CTRL_MBOX_STATUS_INIT, |
| 99 | OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem)); | 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 | mbox->h2fq.sz = readl(OCTEP_CTRL_MBOX_H2FQ_SZ(mbox->barmem)); | 104 | mbox->h2fq.sz = readl(OCTEP_CTRL_MBOX_H2FQ_SZ(mbox->barmem)); |
| 102 | mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD(mbox->barmem); | 105 | mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD(mbox->barmem); |
| 103 | mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS(mbox->barmem); | 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 | err = request_firmware_direct(&fw->bin, fw_path, fw->dev.dev); | 728 | err = request_firmware_direct(&fw->bin, fw_path, fw->dev.dev); |
| 729 | if (err) { | 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 | ver_maj = PRESTERA_PREV_FW_MAJ_VER; | 732 | ver_maj = PRESTERA_PREV_FW_MAJ_VER; |
| 732 | ver_min = PRESTERA_PREV_FW_MIN_VER; | 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 | static bool __prestera_fi_is_direct(struct fib_info *fi) | 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 | if (fib_info_num_path(fi) == 1) { | 171 | if (fib_info_num_path(fi) == 1) { |
| 172 | fib_nh = fib_info_nh(fi, 0); | 172 | fib_nhc = fib_info_nhc(fi, 0); |
| 173 | if (fib_nh->fib_nh_gw_family == AF_UNSPEC) | 173 | if (fib_nhc->nhc_gw_family == AF_UNSPEC) |
| 174 | return true; | 174 | return true; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| @@ -261,7 +261,7 @@ static bool · 84 unmodified lines | |||
| 261 | __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr, | 261 | __prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr, |
| 262 | struct net_device *dev) | 262 | struct net_device *dev) |
| 263 | { | 263 | { |
| 264 | struct fib_nh *fib_nh; | 264 | struct fib_nh_common *fib_nhc; |
| 265 | struct fib_result res; | 265 | struct fib_result res; |
| 266 | bool reachable; | 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 | if (!prestera_util_kern_get_route(&res, tb_id, addr)) | 270 | if (!prestera_util_kern_get_route(&res, tb_id, addr)) |
| 271 | if (prestera_fi_is_direct(res.fi)) { | 271 | if (prestera_fi_is_direct(res.fi)) { |
| 272 | fib_nh = fib_info_nh(res.fi, 0); | 272 | fib_nhc = fib_info_nhc(res.fi, 0); |
| 273 | if (dev == fib_nh->fib_nh_dev) | 273 | if (dev == fib_nhc->nhc_dev) |
| 274 | reachable = true; | 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 | if (info->family == AF_INET) { | 324 | if (info->family == AF_INET) { |
| 325 | fen4_info = container_of(info, struct fib_entry_notifier_info, | 325 | fen4_info = container_of(info, struct fib_entry_notifier_info, |
| 326 | info); | 326 | info); |
| 327 | return &fib_info_nh(fen4_info->fi, n)->nh_common; | 327 | return fib_info_nhc(fen4_info->fi, n); |
| 328 | } else if (info->family == AF_INET6) { | 328 | } else if (info->family == AF_INET6) { |
| 329 | fen6_info = container_of(info, struct fib6_entry_notifier_info, | 329 | fen6_info = container_of(info, struct fib6_entry_notifier_info, |
| 330 | info); | 330 | info); |
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. */ | 2 | /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. */ |
| 3 | 3 | ||
| 4 | #include "reporter_vnic.h" | 4 | #include "reporter_vnic.h" |
| 5 | #include "en_stats.h" | ||
| 5 | #include "devlink.h" | 6 | #include "devlink.h" |
| 6 | 7 | ||
| 7 | #define VNIC_ENV_GET64(vnic_env_stats, c) \ | 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 | if (err) | 37 | if (err) |
| 37 | return err; | 38 | return err; |
| 38 | 39 | ||
| 39 | err = devlink_fmsg_u64_pair_put(fmsg, "total_error_queues", | 40 | if (MLX5_CAP_GEN(dev, vnic_env_queue_counters)) { |
| 40 | VNIC_ENV_GET64(&vnic, total_error_queues)); | 41 | err = devlink_fmsg_u32_pair_put(fmsg, "total_error_queues", |
| 41 | if (err) | 42 | VNIC_ENV_GET(&vnic, total_error_queues)); |
| 42 | return err; | 43 | if (err) |
| 43 | 44 | return err; | |
| 44 | err = devlink_fmsg_u64_pair_put(fmsg, "send_queue_priority_update_flow", | 45 | |
| 45 | VNIC_ENV_GET64(&vnic, send_queue_priority_update_flow)); | 46 | err = devlink_fmsg_u32_pair_put(fmsg, "send_queue_priority_update_flow", |
| 46 | if (err) | 47 | VNIC_ENV_GET(&vnic, |
| 47 | return err; | 48 | send_queue_priority_update_flow)); |
| 48 | 49 | if (err) | |
| 49 | err = devlink_fmsg_u64_pair_put(fmsg, "comp_eq_overrun", | 50 | return err; |
| 50 | VNIC_ENV_GET64(&vnic, comp_eq_overrun)); | 51 | } |
| 51 | if (err) | 52 | |
| 52 | return err; | 53 | if (MLX5_CAP_GEN(dev, eq_overrun_count)) { |
| 53 | 54 | err = devlink_fmsg_u32_pair_put(fmsg, "comp_eq_overrun", | |
| 54 | err = devlink_fmsg_u64_pair_put(fmsg, "async_eq_overrun", | 55 | VNIC_ENV_GET(&vnic, comp_eq_overrun)); |
| 55 | VNIC_ENV_GET64(&vnic, async_eq_overrun)); | 56 | if (err) |
| 56 | if (err) | 57 | return err; |
| 57 | return err; | 58 | |
| 58 | 59 | err = devlink_fmsg_u32_pair_put(fmsg, "async_eq_overrun", | |
| 59 | err = devlink_fmsg_u64_pair_put(fmsg, "cq_overrun", | 60 | VNIC_ENV_GET(&vnic, async_eq_overrun)); |
| 60 | VNIC_ENV_GET64(&vnic, cq_overrun)); | 61 | if (err) |
| 61 | if (err) | 62 | return err; |
| 62 | return err; | 63 | } |
| 63 | 64 | ||
| 64 | err = devlink_fmsg_u64_pair_put(fmsg, "invalid_command", | 65 | if (MLX5_CAP_GEN(dev, vnic_env_cq_overrun)) { |
| 65 | VNIC_ENV_GET64(&vnic, invalid_command)); | 66 | err = devlink_fmsg_u32_pair_put(fmsg, "cq_overrun", |
| 66 | if (err) | 67 | VNIC_ENV_GET(&vnic, cq_overrun)); |
| 67 | return err; | 68 | if (err) |
| 68 | 69 | return err; | |
| 69 | err = devlink_fmsg_u64_pair_put(fmsg, "quota_exceeded_command", | 70 | } |
| 70 | VNIC_ENV_GET64(&vnic, quota_exceeded_command)); | 71 | |
| 71 | if (err) | 72 | if (MLX5_CAP_GEN(dev, invalid_command_count)) { |
| 72 | return err; | 73 | err = devlink_fmsg_u32_pair_put(fmsg, "invalid_command", |
| 73 | 74 | VNIC_ENV_GET(&vnic, invalid_command)); | |
| 74 | err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard", | 75 | if (err) |
| 75 | VNIC_ENV_GET64(&vnic, nic_receive_steering_discard)); | 76 | return err; |
| 76 | if (err) | 77 | } |
| 77 | return err; | 78 | |
| 78 | 79 | if (MLX5_CAP_GEN(dev, quota_exceeded_count)) { | |
| 79 | err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail", | 80 | err = devlink_fmsg_u32_pair_put(fmsg, "quota_exceeded_command", |
| 80 | VNIC_ENV_GET64(&vnic, generated_pkt_steering_fail)); | 81 | VNIC_ENV_GET(&vnic, quota_exceeded_command)); |
| 81 | if (err) | 82 | if (err) |
| 82 | return err; | 83 | return err; |
| 83 | 84 | } | |
| 84 | err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail", | 85 | |
| 85 | VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail)); | 86 | if (MLX5_CAP_GEN(dev, nic_receive_steering_discard)) { |
| 86 | if (err) | 87 | err = devlink_fmsg_u64_pair_put(fmsg, "nic_receive_steering_discard", |
| 87 | return err; | 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 | err = devlink_fmsg_obj_nest_end(fmsg); | 107 | err = devlink_fmsg_obj_nest_end(fmsg); |
| 90 | if (err) | 108 | if (err) |
| @@ -1030,9 +1030,6 @@ int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv, · 1029 unmodified lines | |||
| 1030 | int out_index; | 1030 | int out_index; |
| 1031 | int err = 0; | 1031 | int err = 0; |
| 1032 | 1032 | ||
| 1033 | if (!mlx5e_is_eswitch_flow(flow)) | ||
| 1034 | return 0; | ||
| 1035 | |||
| 1036 | parse_attr = attr->parse_attr; | 1033 | parse_attr = attr->parse_attr; |
| 1037 | esw_attr = attr->esw_attr; | 1034 | esw_attr = attr->esw_attr; |
| 1038 | *vf_tun = false; | 1035 | *vf_tun = false; |
| @@ -1464,10 +1461,12 @@ static void mlx5e_invalidate_encap(struct mlx5e_priv *priv, · 425 unmodified lines | |||
| 1464 | attr = mlx5e_tc_get_encap_attr(flow); | 1461 | attr = mlx5e_tc_get_encap_attr(flow); |
| 1465 | esw_attr = attr->esw_attr; | 1462 | esw_attr = attr->esw_attr; |
| 1466 | 1463 | ||
| 1467 | if (flow_flag_test(flow, SLOW)) | 1464 | if (flow_flag_test(flow, SLOW)) { |
| 1468 | mlx5e_tc_unoffload_from_slow_path(esw, flow); | 1465 | mlx5e_tc_unoffload_from_slow_path(esw, flow); |
| 1469 | else | 1466 | } else { |
| 1470 | mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr); | 1467 | mlx5e_tc_unoffload_fdb_rules(esw, flow, flow->attr); |
| 1468 | mlx5e_tc_unoffload_flow_post_acts(flow); | ||
| 1469 | } | ||
| 1471 | 1470 | ||
| 1472 | mlx5e_tc_detach_mod_hdr(priv, flow, attr); | 1471 | mlx5e_tc_detach_mod_hdr(priv, flow, attr); |
| 1473 | attr->modify_hdr = NULL; | 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 | net_prefetch(mxbuf->xdp.data); | 323 | net_prefetch(mxbuf->xdp.data); |
| 324 | 324 | ||
| 325 | prog = rcu_dereference(rq->xdp_prog); | 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 | return NULL; /* page/packet was consumed by XDP */ | 329 | return NULL; /* page/packet was consumed by XDP */ |
| 330 | } | ||
| 328 | 331 | ||
| 329 | /* XDP_PASS: copy the data from the UMEM to a new SKB. The frame reuse | 332 | /* XDP_PASS: copy the data from the UMEM to a new SKB. The frame reuse |
| 330 | * will be handled by mlx5e_free_rx_wqe. | 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 | if (upspec->sport) { | 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 | upspec->sport_mask); | 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 | trailer_len = alen + plen + 2; | 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 | if (skb->protocol == htons(ETH_P_IP)) { | 64 | if (skb->protocol == htons(ETH_P_IP)) { |
| 63 | ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len); | 65 | ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len); |
| 64 | ip_send_check(ipv4hdr); | 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 | int mlx5e_ktls_init(struct mlx5e_priv *priv) | 189 | int mlx5e_ktls_init(struct mlx5e_priv *priv) |
| 190 | { | 190 | { |
| 191 | struct mlx5_crypto_dek_pool *dek_pool; | ||
| 192 | struct mlx5e_tls *tls; | 191 | struct mlx5e_tls *tls; |
| 193 | 192 | ||
| 194 | if (!mlx5e_is_ktls_device(priv->mdev)) | 193 | if (!mlx5e_is_ktls_device(priv->mdev)) |
| @@ -199,12 +198,6 @@ int mlx5e_ktls_init(struct mlx5e_priv *priv) · 4 unmodified lines | |||
| 199 | return -ENOMEM; | 198 | return -ENOMEM; |
| 200 | tls->mdev = priv->mdev; | 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 | priv->tls = tls; | 201 | priv->tls = tls; |
| 209 | 202 | ||
| 210 | mlx5e_tls_debugfs_init(tls, priv->dfs_root); | 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 | debugfs_remove_recursive(tls->debugfs.dfs); | 215 | debugfs_remove_recursive(tls->debugfs.dfs); |
| 223 | tls->debugfs.dfs = NULL; | 216 | tls->debugfs.dfs = NULL; |
| 224 | 217 | ||
| 225 | mlx5_crypto_dek_pool_destroy(tls->dek_pool); | ||
| 226 | kfree(priv->tls); | 218 | kfree(priv->tls); |
| 227 | priv->tls = NULL; | 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 | int mlx5e_ktls_init_tx(struct mlx5e_priv *priv) | 909 | int mlx5e_ktls_init_tx(struct mlx5e_priv *priv) |
| 910 | { | 910 | { |
| 911 | struct mlx5_crypto_dek_pool *dek_pool; | ||
| 911 | struct mlx5e_tls *tls = priv->tls; | 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 | if (!mlx5e_is_ktls_tx(priv->mdev)) | 926 | if (!mlx5e_is_ktls_tx(priv->mdev)) |
| 914 | return 0; | 927 | return 0; |
| 915 | 928 | ||
| 916 | priv->tls->tx_pool = mlx5e_tls_tx_pool_init(priv->mdev, &priv->tls->sw_stats); | 929 | priv->tls->tx_pool = mlx5e_tls_tx_pool_init(priv->mdev, &priv->tls->sw_stats); |
| 917 | if (!priv->tls->tx_pool) | 930 | if (!priv->tls->tx_pool) { |
| 918 | return -ENOMEM; | 931 | err = -ENOMEM; |
| 932 | goto err_tx_pool_init; | ||
| 933 | } | ||
| 919 | 934 | ||
| 920 | mlx5e_tls_tx_debugfs_init(tls, tls->debugfs.dfs); | 935 | mlx5e_tls_tx_debugfs_init(tls, tls->debugfs.dfs); |
| 921 | 936 | ||
| 922 | return 0; | 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 | void mlx5e_ktls_cleanup_tx(struct mlx5e_priv *priv) | 944 | void mlx5e_ktls_cleanup_tx(struct mlx5e_priv *priv) |
| 926 | { | 945 | { |
| 927 | if (!mlx5e_is_ktls_tx(priv->mdev)) | 946 | if (!mlx5e_is_ktls_tx(priv->mdev)) |
| 928 | return; | 947 | goto dek_pool_destroy; |
| 929 | 948 | ||
| 930 | debugfs_remove_recursive(priv->tls->debugfs.dfs_tx); | 949 | debugfs_remove_recursive(priv->tls->debugfs.dfs_tx); |
| 931 | priv->tls->debugfs.dfs_tx = NULL; | 950 | priv->tls->debugfs.dfs_tx = NULL; |
| 932 | 951 | ||
| 933 | mlx5e_tls_tx_pool_cleanup(priv->tls->tx_pool); | 952 | mlx5e_tls_tx_pool_cleanup(priv->tls->tx_pool); |
| 934 | priv->tls->tx_pool = NULL; | 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 | if (!in) { | 162 | if (!in) { |
| 163 | kfree(ft->g); | 163 | kfree(ft->g); |
| 164 | ft->g = NULL; | ||
| 164 | return -ENOMEM; | 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 | int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs) | 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 | arfs_del_rules(fs); | 148 | arfs_del_rules(fs); |
| 139 | 149 | ||
| 140 | return arfs_disable(fs); | 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 | return err; | 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 | struct net_device *dev = rq->netdev; | 1057 | struct net_device *dev = rq->netdev; |
| 1042 | int err; | 1058 | int err; |
| @@ -1046,6 +1062,10 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state) · 3 unmodified lines | |||
| 1046 | netdev_err(dev, "Failed to move rq 0x%x to reset\n", rq->rqn); | 1062 | netdev_err(dev, "Failed to move rq 0x%x to reset\n", rq->rqn); |
| 1047 | return err; | 1063 | return err; |
| 1048 | } | 1064 | } |
| 1065 | |||
| 1066 | mlx5e_free_rx_descs(rq); | ||
| 1067 | mlx5e_flush_rq_cq(rq); | ||
| 1068 | |||
| 1049 | err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY); | 1069 | err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY); |
| 1050 | if (err) { | 1070 | if (err) { |
| 1051 | netdev_err(dev, "Failed to move rq 0x%x to ready\n", rq->rqn); | 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 | return 0; | 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 | static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd) | 1078 | static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd) |
| 1066 | { | 1079 | { |
| 1067 | struct mlx5_core_dev *mdev = rq->mdev; | 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 | static int mlx5e_nic_init(struct mlx5_core_dev *mdev, | 5266 | static int mlx5e_nic_init(struct mlx5_core_dev *mdev, |
| 5254 | struct net_device *netdev) | 5267 | struct net_device *netdev) |
| 5255 | { | 5268 | { |
| 5269 | const bool take_rtnl = netdev->reg_state == NETREG_REGISTERED; | ||
| 5256 | struct mlx5e_priv *priv = netdev_priv(netdev); | 5270 | struct mlx5e_priv *priv = netdev_priv(netdev); |
| 5257 | struct mlx5e_flow_steering *fs; | 5271 | struct mlx5e_flow_steering *fs; |
| 5258 | int err; | 5272 | int err; |
| @@ -5281,9 +5295,19 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev, · 22 unmodified lines | |||
| 5281 | mlx5_core_err(mdev, "TLS initialization failed, %d\n", err); | 5295 | mlx5_core_err(mdev, "TLS initialization failed, %d\n", err); |
| 5282 | 5296 | ||
| 5283 | mlx5e_health_create_reporters(priv); | 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 | /* update XDP supported features */ | 5305 | /* update XDP supported features */ |
| 5285 | mlx5e_set_xdp_feature(netdev); | 5306 | mlx5e_set_xdp_feature(netdev); |
| 5286 | 5307 | ||
| 5308 | if (take_rtnl) | ||
| 5309 | rtnl_unlock(); | ||
| 5310 | |||
| 5287 | return 0; | 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 | err = mlx5e_open_drop_rq(priv, &priv->drop_rq); | 1012 | err = mlx5e_open_drop_rq(priv, &priv->drop_rq); |
| 1013 | if (err) { | 1013 | if (err) { |
| 1014 | mlx5_core_err(mdev, "open drop rq failed, %d\n", err); | 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 | err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, | 1018 | err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0, |
| @@ -1046,6 +1046,7 @@ err_destroy_rx_res: · 27 unmodified lines | |||
| 1046 | mlx5e_rx_res_destroy(priv->rx_res); | 1046 | mlx5e_rx_res_destroy(priv->rx_res); |
| 1047 | err_close_drop_rq: | 1047 | err_close_drop_rq: |
| 1048 | mlx5e_close_drop_rq(&priv->drop_rq); | 1048 | mlx5e_close_drop_rq(&priv->drop_rq); |
| 1049 | err_rx_res_free: | ||
| 1049 | mlx5e_rx_res_free(priv->rx_res); | 1050 | mlx5e_rx_res_free(priv->rx_res); |
| 1050 | priv->rx_res = NULL; | 1051 | priv->rx_res = NULL; |
| 1051 | err_free_fs: | 1052 | err_free_fs: |
| @@ -1159,6 +1160,10 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv) · 107 unmodified lines | |||
| 1159 | return err; | 1160 | return err; |
| 1160 | } | 1161 | } |
| 1161 | 1162 | ||
| 1163 | err = mlx5e_rep_neigh_init(rpriv); | ||
| 1164 | if (err) | ||
| 1165 | goto err_neigh_init; | ||
| 1166 | |||
| 1162 | if (rpriv->rep->vport == MLX5_VPORT_UPLINK) { | 1167 | if (rpriv->rep->vport == MLX5_VPORT_UPLINK) { |
| 1163 | err = mlx5e_init_uplink_rep_tx(rpriv); | 1168 | err = mlx5e_init_uplink_rep_tx(rpriv); |
| 1164 | if (err) | 1169 | if (err) |
| @@ -1175,6 +1180,8 @@ err_ht_init: · 10 unmodified lines | |||
| 1175 | if (rpriv->rep->vport == MLX5_VPORT_UPLINK) | 1180 | if (rpriv->rep->vport == MLX5_VPORT_UPLINK) |
| 1176 | mlx5e_cleanup_uplink_rep_tx(rpriv); | 1181 | mlx5e_cleanup_uplink_rep_tx(rpriv); |
| 1177 | err_init_tx: | 1182 | err_init_tx: |
| 1183 | mlx5e_rep_neigh_cleanup(rpriv); | ||
| 1184 | err_neigh_init: | ||
| 1178 | mlx5e_destroy_tises(priv); | 1185 | mlx5e_destroy_tises(priv); |
| 1179 | return err; | 1186 | return err; |
| 1180 | } | 1187 | } |
| @@ -1188,22 +1195,17 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv) · 7 unmodified lines | |||
| 1188 | if (rpriv->rep->vport == MLX5_VPORT_UPLINK) | 1195 | if (rpriv->rep->vport == MLX5_VPORT_UPLINK) |
| 1189 | mlx5e_cleanup_uplink_rep_tx(rpriv); | 1196 | mlx5e_cleanup_uplink_rep_tx(rpriv); |
| 1190 | 1197 | ||
| 1198 | mlx5e_rep_neigh_cleanup(rpriv); | ||
| 1191 | mlx5e_destroy_tises(priv); | 1199 | mlx5e_destroy_tises(priv); |
| 1192 | } | 1200 | } |
| 1193 | 1201 | ||
| 1194 | static void mlx5e_rep_enable(struct mlx5e_priv *priv) | 1202 | static void mlx5e_rep_enable(struct mlx5e_priv *priv) |
| 1195 | { | 1203 | { |
| 1196 | struct mlx5e_rep_priv *rpriv = priv->ppriv; | ||
| 1197 | |||
| 1198 | mlx5e_set_netdev_mtu_boundaries(priv); | 1204 | mlx5e_set_netdev_mtu_boundaries(priv); |
| 1199 | mlx5e_rep_neigh_init(rpriv); | ||
| 1200 | } | 1205 | } |
| 1201 | 1206 | ||
| 1202 | static void mlx5e_rep_disable(struct mlx5e_priv *priv) | 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 | static int mlx5e_update_rep_rx(struct mlx5e_priv *priv) | 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 | static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) | 1256 | static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) |
| 1255 | { | 1257 | { |
| 1256 | struct mlx5e_rep_priv *rpriv = priv->ppriv; | ||
| 1257 | struct net_device *netdev = priv->netdev; | 1258 | struct net_device *netdev = priv->netdev; |
| 1258 | struct mlx5_core_dev *mdev = priv->mdev; | 1259 | struct mlx5_core_dev *mdev = priv->mdev; |
| 1259 | u16 max_mtu; | 1260 | u16 max_mtu; |
| @@ -1275,7 +1276,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) · 15 unmodified lines | |||
| 1275 | mlx5_notifier_register(mdev, &priv->events_nb); | 1276 | mlx5_notifier_register(mdev, &priv->events_nb); |
| 1276 | mlx5e_dcbnl_initialize(priv); | 1277 | mlx5e_dcbnl_initialize(priv); |
| 1277 | mlx5e_dcbnl_init_app(priv); | 1278 | mlx5e_dcbnl_init_app(priv); |
| 1278 | mlx5e_rep_neigh_init(rpriv); | ||
| 1279 | mlx5e_rep_bridge_init(priv); | 1279 | mlx5e_rep_bridge_init(priv); |
| 1280 | 1280 | ||
| 1281 | netdev->wanted_features |= NETIF_F_HW_TC; | 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 | static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) | 1291 | static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) |
| 1292 | { | 1292 | { |
| 1293 | struct mlx5e_rep_priv *rpriv = priv->ppriv; | ||
| 1294 | struct mlx5_core_dev *mdev = priv->mdev; | 1293 | struct mlx5_core_dev *mdev = priv->mdev; |
| 1295 | 1294 | ||
| 1296 | rtnl_lock(); | 1295 | rtnl_lock(); |
| @@ -1300,7 +1299,6 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv) · 3 unmodified lines | |||
| 1300 | rtnl_unlock(); | 1299 | rtnl_unlock(); |
| 1301 | 1300 | ||
| 1302 | mlx5e_rep_bridge_cleanup(priv); | 1301 | mlx5e_rep_bridge_cleanup(priv); |
| 1303 | mlx5e_rep_neigh_cleanup(rpriv); | ||
| 1304 | mlx5e_dcbnl_delete_app(priv); | 1302 | mlx5e_dcbnl_delete_app(priv); |
| 1305 | mlx5_notifier_unregister(mdev, &priv->events_nb); | 1303 | mlx5_notifier_unregister(mdev, &priv->events_nb); |
| 1306 | mlx5e_rep_tc_disable(priv); | 1304 | mlx5e_rep_tc_disable(priv); |
| @@ -1725,6 +1725,19 @@ verify_attr_actions(u32 actions, struct netlink_ext_ack *extack) · 1724 unmodified lines | |||
| 1725 | return 0; | 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 | static int | 1741 | static int |
| 1729 | post_process_attr(struct mlx5e_tc_flow *flow, | 1742 | post_process_attr(struct mlx5e_tc_flow *flow, |
| 1730 | struct mlx5_flow_attr *attr, | 1743 | struct mlx5_flow_attr *attr, |
| @@ -1737,9 +1750,11 @@ post_process_attr(struct mlx5e_tc_flow *flow, · 6 unmodified lines | |||
| 1737 | if (err) | 1750 | if (err) |
| 1738 | goto err_out; | 1751 | goto err_out; |
| 1739 | 1752 | ||
| 1740 | err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun); | 1753 | if (mlx5e_is_eswitch_flow(flow) && has_encap_dests(attr)) { |
| 1741 | if (err) | 1754 | err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun); |
| 1742 | goto err_out; | 1755 | if (err) |
| 1756 | goto err_out; | ||
| 1757 | } | ||
| 1743 | 1758 | ||
| 1744 | if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { | 1759 | if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { |
| 1745 | err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr); | 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 | struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; | 1944 | struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; |
| 1930 | struct mlx5_flow_attr *attr = flow->attr; | 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 | mlx5e_put_flow_tunnel_id(flow); | 1947 | mlx5e_put_flow_tunnel_id(flow); |
| 1935 | 1948 | ||
| 1936 | remove_unready_flow(flow); | 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 | mlx5_tc_ct_match_del(get_ct_priv(priv), &flow->attr->ct_attr); | 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 | if (flow_flag_test(flow, L3_TO_L2_DECAP)) | 1967 | if (flow_flag_test(flow, L3_TO_L2_DECAP)) |
| 1961 | mlx5e_detach_decap(priv, flow); | 1968 | mlx5e_detach_decap(priv, flow); |
| 1962 | 1969 | ||
| @@ -4253,6 +4260,7 @@ static void · 2290 unmodified lines | |||
| 4253 | mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr) | 4260 | mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr) |
| 4254 | { | 4261 | { |
| 4255 | struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow); | 4262 | struct mlx5_core_dev *counter_dev = get_flow_counter_dev(flow); |
| 4263 | struct mlx5_esw_flow_attr *esw_attr; | ||
| 4256 | 4264 | ||
| 4257 | if (!attr) | 4265 | if (!attr) |
| 4258 | return; | 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 | mlx5e_tc_detach_mod_hdr(flow->priv, flow, attr); | 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 | mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr); | 4293 | mlx5_tc_ct_delete_flow(get_ct_priv(flow->priv), attr); |
| 4274 | 4294 | ||
| 4275 | free_branch_attr(flow, attr->branch_true); | 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 | bridge->debugfs_dir = debugfs_create_dir(br_netdev->name, | 65 | bridge->debugfs_dir = debugfs_create_dir(br_netdev->name, |
| 66 | bridge->br_offloads->debugfs_root); | 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 | &mlx5_esw_bridge_debugfs_fops); | 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 | } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) { | 60 | } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) { |
| 61 | memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len); | 61 | memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len); |
| 62 | dl_port->attrs.switch_id.id_len = ppid.id_len; | 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 | vport_num - 1, false); | 64 | vport_num - 1, false); |
| 65 | } | 65 | } |
| 66 | return dl_port; | 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 | esw_init_chains_offload_flags(esw, &attr.flags); | 1437 | esw_init_chains_offload_flags(esw, &attr.flags); |
| 1438 | attr.ns = MLX5_FLOW_NAMESPACE_FDB; | 1438 | attr.ns = MLX5_FLOW_NAMESPACE_FDB; |
| 1439 | attr.fs_base_prio = FDB_TC_OFFLOAD; | ||
| 1440 | attr.max_grp_num = esw->params.large_group_num; | 1439 | attr.max_grp_num = esw->params.large_group_num; |
| 1441 | attr.default_ft = miss_fdb; | 1440 | attr.default_ft = miss_fdb; |
| 1442 | attr.mapping = esw->offloads.reg_c0_obj_pool; | 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 | struct mlx5_eswitch *peer_esw, | 2778 | struct mlx5_eswitch *peer_esw, |
| 2780 | bool pair) | 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 | struct mlx5_flow_root_namespace *peer_ns; | 2783 | struct mlx5_flow_root_namespace *peer_ns; |
| 2784 | u8 idx = mlx5_get_dev_index(esw->dev); | ||
| 2785 | struct mlx5_flow_root_namespace *ns; | 2784 | struct mlx5_flow_root_namespace *ns; |
| 2786 | int err; | 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 | ns = esw->dev->priv.steering->fdb_root_ns; | 2788 | ns = esw->dev->priv.steering->fdb_root_ns; |
| 2790 | 2789 | ||
| 2791 | if (pair) { | 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 | if (err) | 2792 | if (err) |
| 2794 | return err; | 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 | if (err) { | 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 | return err; | 2798 | return err; |
| 2800 | } | 2799 | } |
| 2801 | } else { | 2800 | } else { |
| 2802 | mlx5_flow_namespace_set_peer(ns, NULL, peer_idx); | 2801 | mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id); |
| 2803 | mlx5_flow_namespace_set_peer(peer_ns, NULL, idx); | 2802 | mlx5_flow_namespace_set_peer(peer_ns, NULL, vhca_id); |
| 2804 | } | 2803 | } |
| 2805 | 2804 | ||
| 2806 | return 0; | 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 | hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); | 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 | err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport, | 4200 | err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport, |
| 4202 | MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE2); | 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 | static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns, | 141 | static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns, |
| 142 | struct mlx5_flow_root_namespace *peer_ns, | 142 | struct mlx5_flow_root_namespace *peer_ns, |
| 143 | u8 peer_idx) | 143 | u16 peer_vhca_id) |
| 144 | { | 144 | { |
| 145 | return 0; | 145 | return 0; |
| 146 | } | 146 | } |
| @@ -94,7 +94,7 @@ struct mlx5_flow_cmds { · 93 unmodified lines | |||
| 94 | 94 | ||
| 95 | int (*set_peer)(struct mlx5_flow_root_namespace *ns, | 95 | int (*set_peer)(struct mlx5_flow_root_namespace *ns, |
| 96 | struct mlx5_flow_root_namespace *peer_ns, | 96 | struct mlx5_flow_root_namespace *peer_ns, |
| 97 | u8 peer_idx); | 97 | u16 peer_vhca_id); |
| 98 | 98 | ||
| 99 | int (*create_ns)(struct mlx5_flow_root_namespace *ns); | 99 | int (*create_ns)(struct mlx5_flow_root_namespace *ns); |
| 100 | int (*destroy_ns)(struct mlx5_flow_root_namespace *ns); | 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 | struct fs_node *iter = list_entry(start, struct fs_node, list); | 889 | struct fs_node *iter = list_entry(start, struct fs_node, list); |
| 890 | struct mlx5_flow_table *ft = NULL; | 890 | struct mlx5_flow_table *ft = NULL; |
| 891 | 891 | ||
| 892 | if (!root || root->type == FS_TYPE_PRIO_CHAINS) | 892 | if (!root) |
| 893 | return NULL; | 893 | return NULL; |
| 894 | 894 | ||
| 895 | list_for_each_advance_continue(iter, &root->children, reverse) { | 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 | return ft; | 905 | return ft; |
| 906 | } | 906 | } |
| 907 | 907 | ||
| 908 | /* If reverse is false then return the first flow table in next priority of | 908 | static struct fs_node *find_prio_chains_parent(struct fs_node *parent, |
| 909 | * prio in the tree, else return the last flow table in the previous priority | 909 | struct fs_node **child) |
| 910 | * of prio in the tree. | 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 | struct mlx5_flow_table *ft = NULL; | 932 | struct mlx5_flow_table *ft = NULL; |
| 915 | struct fs_node *curr_node; | 933 | struct fs_node *curr_node; |
| 916 | struct fs_node *parent; | 934 | struct fs_node *parent; |
| 917 | 935 | ||
| 918 | parent = prio->node.parent; | 936 | if (skip) |
| 919 | curr_node = &prio->node; | 937 | prio_chains_parent = find_prio_chains_parent(node, NULL); |
| 938 | parent = node->parent; | ||
| 939 | curr_node = node; | ||
| 920 | while (!ft && parent) { | 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 | curr_node = parent; | 944 | curr_node = parent; |
| 923 | parent = curr_node->parent; | 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 | /* Assuming all the tree is locked by mutex chain lock */ | 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 | /* Assuming all the tree is locked by mutex chain lock */ | 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 | static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft, | 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 | next_ns = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS; | 968 | next_ns = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS; |
| 947 | fs_get_obj(prio, next_ns ? ft->ns->node.parent : ft->node.parent); | 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 | static int connect_fts_in_prio(struct mlx5_core_dev *dev, | 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 | return 0; | 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 | /* Connect flow tables from previous priority of prio to ft */ | 1010 | /* Connect flow tables from previous priority of prio to ft */ |
| 974 | static int connect_prev_fts(struct mlx5_core_dev *dev, | 1011 | static int connect_prev_fts(struct mlx5_core_dev *dev, |
| 975 | struct mlx5_flow_table *ft, | 1012 | struct mlx5_flow_table *ft, |
| 976 | struct fs_prio *prio) | 1013 | struct fs_prio *prio) |
| 977 | { | 1014 | { |
| 1015 | struct fs_node *prio_parent, *parent = NULL, *child, *node; | ||
| 978 | struct mlx5_flow_table *prev_ft; | 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); | 1025 | prev_ft = find_prev_chained_ft(&prio->node); |
| 981 | if (prev_ft) { | 1026 | while (prev_ft) { |
| 982 | struct fs_prio *prev_prio; | 1027 | struct fs_prio *prev_prio; |
| 983 | 1028 | ||
| 984 | fs_get_obj(prev_prio, prev_ft->node.parent); | 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 | static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio | 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 | if (err) | 1179 | if (err) |
| 1124 | return err; | 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 | err = connect_fwd_rules(dev, ft, next_ft); | 1183 | err = connect_fwd_rules(dev, ft, next_ft); |
| 1128 | if (err) | 1184 | if (err) |
| 1129 | return err; | 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 | tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table); | 1255 | tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table); |
| 1200 | next_ft = unmanaged ? ft_attr->next_ft : | 1256 | next_ft = unmanaged ? ft_attr->next_ft : |
| 1201 | find_next_chained_ft(fs_prio); | 1257 | find_next_chained_ft(&fs_prio->node); |
| 1202 | ft->def_miss_action = ns->def_miss_action; | 1258 | ft->def_miss_action = ns->def_miss_action; |
| 1203 | ft->ns = ns; | 1259 | ft->ns = ns; |
| 1204 | err = root->cmds->create_flow_table(root, ft, ft_attr, next_ft); | 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 | /* Assuming prio->node.children(flow tables) is sorted by level */ | 2251 | /* Assuming prio->node.children(flow tables) is sorted by level */ |
| 2196 | static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft) | 2252 | static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft) |
| 2197 | { | 2253 | { |
| 2254 | struct fs_node *prio_parent, *child; | ||
| 2198 | struct fs_prio *prio; | 2255 | struct fs_prio *prio; |
| 2199 | 2256 | ||
| 2200 | fs_get_obj(prio, ft->node.parent); | 2257 | fs_get_obj(prio, ft->node.parent); |
| 2201 | 2258 | ||
| 2202 | if (!list_is_last(&ft->node.list, &prio->node.children)) | 2259 | if (!list_is_last(&ft->node.list, &prio->node.children)) |
| 2203 | return list_next_entry(ft, node.list); | 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 | static int update_root_ft_destroy(struct mlx5_flow_table *ft) | 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 | int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, | 3685 | int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, |
| 3623 | struct mlx5_flow_root_namespace *peer_ns, | 3686 | struct mlx5_flow_root_namespace *peer_ns, |
| 3624 | u8 peer_idx) | 3687 | u16 peer_vhca_id) |
| 3625 | { | 3688 | { |
| 3626 | if (peer_ns && ns->mode != peer_ns->mode) { | 3689 | if (peer_ns && ns->mode != peer_ns->mode) { |
| 3627 | mlx5_core_err(ns->dev, | 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 | return -EINVAL; | 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 | /* This function should be called only at init stage of the namespace. | 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 | int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, | 304 | int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, |
| 305 | struct mlx5_flow_root_namespace *peer_ns, | 305 | struct mlx5_flow_root_namespace *peer_ns, |
| 306 | u8 peer_idx); | 306 | u16 peer_vhca_id); |
| 307 | 307 | ||
| 308 | int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns, | 308 | int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns, |
| 309 | enum mlx5_flow_steering_mode mode); | 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 | for (i = 0; i < ldev->ports; i++) { | 574 | for (i = 0; i < ldev->ports; i++) { |
| 575 | for (j = 0; j < ldev->buckets; j++) { | 575 | for (j = 0; j < ldev->buckets; j++) { |
| 576 | idx = i * ldev->buckets + j; | 576 | idx = i * ldev->buckets + j; |
| 577 | if (ldev->v2p_map[i] == ports[i]) | 577 | if (ldev->v2p_map[idx] == ports[idx]) |
| 578 | continue; | 578 | continue; |
| 579 | 579 | ||
| 580 | dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev, | 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 | clock = container_of(timer, struct mlx5_clock, timer); | 227 | clock = container_of(timer, struct mlx5_clock, timer); |
| 228 | mdev = container_of(clock, struct mlx5_core_dev, clock); | 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 | write_seqlock_irqsave(&clock->lock, flags); | 233 | write_seqlock_irqsave(&clock->lock, flags); |
| 231 | timecounter_read(&timer->tc); | 234 | timecounter_read(&timer->tc); |
| 232 | mlx5_update_clock_info_page(mdev); | 235 | mlx5_update_clock_info_page(mdev); |
| 233 | write_sequnlock_irqrestore(&clock->lock, flags); | 236 | write_sequnlock_irqrestore(&clock->lock, flags); |
| 237 | |||
| 238 | out: | ||
| 234 | schedule_delayed_work(&timer->overflow_work, timer->overflow_period); | 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 | if (!mlx5_chains_ignore_flow_level_supported(chains) || | 178 | if (!mlx5_chains_ignore_flow_level_supported(chains) || |
| 179 | (chain == 0 && prio == 1 && level == 0)) { | 179 | (chain == 0 && prio == 1 && level == 0)) { |
| 180 | ft_attr.level = chains->fs_base_level; | 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 | ns = (chains->ns == MLX5_FLOW_NAMESPACE_FDB) ? | 182 | ns = (chains->ns == MLX5_FLOW_NAMESPACE_FDB) ? |
| 183 | mlx5_get_fdb_sub_ns(chains->dev, chain) : | 183 | mlx5_get_fdb_sub_ns(chains->dev, chain) : |
| 184 | mlx5_get_flow_namespace(chains->dev, chains->ns); | 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 | if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { | 1506 | if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { |
| 1507 | mlx5_core_warn(dev, "%s: interface is down, NOP\n", | 1507 | mlx5_core_warn(dev, "%s: interface is down, NOP\n", |
| 1508 | __func__); | 1508 | __func__); |
| 1509 | mlx5_devlink_params_unregister(priv_to_devlink(dev)); | ||
| 1509 | mlx5_cleanup_once(dev); | 1510 | mlx5_cleanup_once(dev); |
| 1510 | goto out; | 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 | mlx5_enter_error_state(dev, false); | 1990 | mlx5_enter_error_state(dev, false); |
| 1990 | mlx5_error_sw_reset(dev); | 1991 | mlx5_error_sw_reset(dev); |
| 1991 | mlx5_unload_one(dev, true); | 1992 | mlx5_unload_one(dev, false); |
| 1992 | mlx5_drain_health_wq(dev); | 1993 | mlx5_drain_health_wq(dev); |
| 1993 | mlx5_pci_disable_device(dev); | 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 | static inline int mlx5_vport_to_func_id(const struct mlx5_core_dev *dev, u16 vport, bool ec_vf_func) | 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 | : vport; | 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 | host_total_vfs = MLX5_GET(query_esw_functions_out, out, | 285 | host_total_vfs = MLX5_GET(query_esw_functions_out, out, |
| 286 | host_params_context.host_total_vfs); | 286 | host_params_context.host_total_vfs); |
| 287 | kvfree(out); | 287 | kvfree(out); |
| 288 | if (host_total_vfs) | 288 | return host_total_vfs; |
| 289 | return host_total_vfs; | ||
| 290 | } | 289 | } |
| 291 | 290 | ||
| 292 | done: | 291 | done: |
| @@ -2079,7 +2079,7 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn, · 2078 unmodified lines | |||
| 2079 | 2079 | ||
| 2080 | peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) && | 2080 | peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) && |
| 2081 | (vhca_id != dmn->info.caps.gvmi); | 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 | if (!vport_dmn) { | 2083 | if (!vport_dmn) { |
| 2084 | mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n"); | 2084 | mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n"); |
| 2085 | return NULL; | 2085 | return NULL; |
| @@ -564,11 +564,12 @@ int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev, · 563 unmodified lines | |||
| 564 | 564 | ||
| 565 | err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out)); | 565 | err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out)); |
| 566 | if (err) | 566 | if (err) |
| 567 | return err; | 567 | goto err_free_in; |
| 568 | 568 | ||
| 569 | *reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id); | 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 | return err; | 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 | mutex_init(&dmn->info.rx.mutex); | 475 | mutex_init(&dmn->info.rx.mutex); |
| 476 | mutex_init(&dmn->info.tx.mutex); | 476 | mutex_init(&dmn->info.tx.mutex); |
| 477 | xa_init(&dmn->definers_xa); | 477 | xa_init(&dmn->definers_xa); |
| 478 | xa_init(&dmn->peer_dmn_xa); | ||
| 478 | 479 | ||
| 479 | if (dr_domain_caps_init(mdev, dmn)) { | 480 | if (dr_domain_caps_init(mdev, dmn)) { |
| 480 | mlx5dr_err(dmn, "Failed init domain, no caps\n"); | 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 | uninit_caps: | 508 | uninit_caps: |
| 508 | dr_domain_caps_uninit(dmn); | 509 | dr_domain_caps_uninit(dmn); |
| 509 | def_xa_destroy: | 510 | def_xa_destroy: |
| 511 | xa_destroy(&dmn->peer_dmn_xa); | ||
| 510 | xa_destroy(&dmn->definers_xa); | 512 | xa_destroy(&dmn->definers_xa); |
| 511 | kfree(dmn); | 513 | kfree(dmn); |
| 512 | return NULL; | 514 | return NULL; |
| @@ -547,6 +549,7 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn) · 34 unmodified lines | |||
| 547 | dr_domain_uninit_csum_recalc_fts(dmn); | 549 | dr_domain_uninit_csum_recalc_fts(dmn); |
| 548 | dr_domain_uninit_resources(dmn); | 550 | dr_domain_uninit_resources(dmn); |
| 549 | dr_domain_caps_uninit(dmn); | 551 | dr_domain_caps_uninit(dmn); |
| 552 | xa_destroy(&dmn->peer_dmn_xa); | ||
| 550 | xa_destroy(&dmn->definers_xa); | 553 | xa_destroy(&dmn->definers_xa); |
| 551 | mutex_destroy(&dmn->info.tx.mutex); | 554 | mutex_destroy(&dmn->info.tx.mutex); |
| 552 | mutex_destroy(&dmn->info.rx.mutex); | 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 | void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, | 560 | void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, |
| 558 | struct mlx5dr_domain *peer_dmn, | 561 | struct mlx5dr_domain *peer_dmn, |
| 559 | u8 peer_idx) | 562 | u16 peer_vhca_id) |
| 560 | { | 563 | { |
| 564 | struct mlx5dr_domain *peer; | ||
| 565 | |||
| 561 | mlx5dr_domain_lock(dmn); | 566 | mlx5dr_domain_lock(dmn); |
| 562 | 567 | ||
| 563 | if (dmn->peer_dmn[peer_idx]) | 568 | peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id); |
| 564 | refcount_dec(&dmn->peer_dmn[peer_idx]->refcount); | 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]) | 574 | peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id); |
| 569 | refcount_inc(&dmn->peer_dmn[peer_idx]->refcount); | 575 | if (peer) |
| 576 | refcount_inc(&peer->refcount); | ||
| 570 | 577 | ||
| 571 | mlx5dr_domain_unlock(dmn); | 578 | mlx5dr_domain_unlock(dmn); |
| 572 | } | 579 | } |
| @@ -82,7 +82,7 @@ dr_ptrn_alloc_pattern(struct mlx5dr_ptrn_mgr *mgr, · 81 unmodified lines | |||
| 82 | u32 chunk_size; | 82 | u32 chunk_size; |
| 83 | u32 index; | 83 | u32 index; |
| 84 | 84 | ||
| 85 | chunk_size = ilog2(num_of_actions); | 85 | chunk_size = ilog2(roundup_pow_of_two(num_of_actions)); |
| 86 | /* HW modify action index granularity is at least 64B */ | 86 | /* HW modify action index granularity is at least 64B */ |
| 87 | chunk_size = max_t(u32, chunk_size, DR_CHUNK_SIZE_8); | 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 | struct mlx5dr_domain *dmn = sb->dmn; | 1652 | struct mlx5dr_domain *dmn = sb->dmn; |
| 1653 | struct mlx5dr_domain *vport_dmn; | 1653 | struct mlx5dr_domain *vport_dmn; |
| 1654 | u8 *bit_mask = sb->bit_mask; | 1654 | u8 *bit_mask = sb->bit_mask; |
| 1655 | struct mlx5dr_domain *peer; | ||
| 1655 | bool source_gvmi_set; | 1656 | bool source_gvmi_set; |
| 1656 | 1657 | ||
| 1657 | DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn); | 1658 | DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn); |
| 1658 | 1659 | ||
| 1659 | if (sb->vhca_id_valid) { | 1660 | if (sb->vhca_id_valid) { |
| 1661 | peer = xa_load(&dmn->peer_dmn_xa, id); | ||
| 1660 | /* Find port GVMI based on the eswitch_owner_vhca_id */ | 1662 | /* Find port GVMI based on the eswitch_owner_vhca_id */ |
| 1661 | if (id == dmn->info.caps.gvmi) | 1663 | if (id == dmn->info.caps.gvmi) |
| 1662 | vport_dmn = dmn; | 1664 | vport_dmn = dmn; |
| 1663 | else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && | 1665 | else if (peer && (id == peer->info.caps.gvmi)) |
| 1664 | (id == dmn->peer_dmn[id]->info.caps.gvmi)) | 1666 | vport_dmn = peer; |
| 1665 | vport_dmn = dmn->peer_dmn[id]; | ||
| 1666 | else | 1667 | else |
| 1667 | return -EINVAL; | 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 | struct mlx5dr_domain *dmn = sb->dmn; | 1984 | struct mlx5dr_domain *dmn = sb->dmn; |
| 1985 | struct mlx5dr_domain *vport_dmn; | 1985 | struct mlx5dr_domain *vport_dmn; |
| 1986 | u8 *bit_mask = sb->bit_mask; | 1986 | u8 *bit_mask = sb->bit_mask; |
| 1987 | struct mlx5dr_domain *peer; | ||
| 1987 | 1988 | ||
| 1988 | DR_STE_SET_TAG(src_gvmi_qp_v1, tag, source_qp, misc, source_sqn); | 1989 | DR_STE_SET_TAG(src_gvmi_qp_v1, tag, source_qp, misc, source_sqn); |
| 1989 | 1990 | ||
| 1990 | if (sb->vhca_id_valid) { | 1991 | if (sb->vhca_id_valid) { |
| 1992 | peer = xa_load(&dmn->peer_dmn_xa, id); | ||
| 1991 | /* Find port GVMI based on the eswitch_owner_vhca_id */ | 1993 | /* Find port GVMI based on the eswitch_owner_vhca_id */ |
| 1992 | if (id == dmn->info.caps.gvmi) | 1994 | if (id == dmn->info.caps.gvmi) |
| 1993 | vport_dmn = dmn; | 1995 | vport_dmn = dmn; |
| 1994 | else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && | 1996 | else if (peer && (id == peer->info.caps.gvmi)) |
| 1995 | (id == dmn->peer_dmn[id]->info.caps.gvmi)) | 1997 | vport_dmn = peer; |
| 1996 | vport_dmn = dmn->peer_dmn[id]; | ||
| 1997 | else | 1998 | else |
| 1998 | return -EINVAL; | 1999 | return -EINVAL; |
| 1999 | 2000 | ||
| @@ -935,7 +935,6 @@ struct mlx5dr_domain_info { · 934 unmodified lines | |||
| 935 | }; | 935 | }; |
| 936 | 936 | ||
| 937 | struct mlx5dr_domain { | 937 | struct mlx5dr_domain { |
| 938 | struct mlx5dr_domain *peer_dmn[MLX5_MAX_PORTS]; | ||
| 939 | struct mlx5_core_dev *mdev; | 938 | struct mlx5_core_dev *mdev; |
| 940 | u32 pdn; | 939 | u32 pdn; |
| 941 | struct mlx5_uars_page *uar; | 940 | struct mlx5_uars_page *uar; |
| @@ -956,6 +955,7 @@ struct mlx5dr_domain { · 14 unmodified lines | |||
| 956 | struct list_head dbg_tbl_list; | 955 | struct list_head dbg_tbl_list; |
| 957 | struct mlx5dr_dbg_dump_info dump_info; | 956 | struct mlx5dr_dbg_dump_info dump_info; |
| 958 | struct xarray definers_xa; | 957 | struct xarray definers_xa; |
| 958 | struct xarray peer_dmn_xa; | ||
| 959 | /* memory management statistics */ | 959 | /* memory management statistics */ |
| 960 | u32 num_buddies[DR_ICM_TYPE_MAX]; | 960 | u32 num_buddies[DR_ICM_TYPE_MAX]; |
| 961 | }; | 961 | }; |
| @@ -781,14 +781,14 @@ restore_fte: · 780 unmodified lines | |||
| 781 | 781 | ||
| 782 | static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns, | 782 | static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns, |
| 783 | struct mlx5_flow_root_namespace *peer_ns, | 783 | struct mlx5_flow_root_namespace *peer_ns, |
| 784 | u8 peer_idx) | 784 | u16 peer_vhca_id) |
| 785 | { | 785 | { |
| 786 | struct mlx5dr_domain *peer_domain = NULL; | 786 | struct mlx5dr_domain *peer_domain = NULL; |
| 787 | 787 | ||
| 788 | if (peer_ns) | 788 | if (peer_ns) |
| 789 | peer_domain = peer_ns->fs_dr_domain.dr_domain; | 789 | peer_domain = peer_ns->fs_dr_domain.dr_domain; |
| 790 | mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain, | 790 | mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain, |
| 791 | peer_domain, peer_idx); | 791 | peer_domain, peer_vhca_id); |
| 792 | return 0; | 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 | void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, | 50 | void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, |
| 51 | struct mlx5dr_domain *peer_dmn, | 51 | struct mlx5dr_domain *peer_dmn, |
| 52 | u8 peer_idx); | 52 | u16 peer_vhca_id); |
| 53 | 53 | ||
| 54 | struct mlx5dr_table * | 54 | struct mlx5dr_table * |
| 55 | mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags, | 55 | mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags, |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include <linux/ethtool.h> | 8 | #include <linux/ethtool.h> |
| 9 | #include <linux/filter.h> | 9 | #include <linux/filter.h> |
| 10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
| 11 | #include <linux/pci.h> | ||
| 11 | 12 | ||
| 12 | #include <net/checksum.h> | 13 | #include <net/checksum.h> |
| 13 | #include <net/ip6_checksum.h> | 14 | #include <net/ip6_checksum.h> |
| @@ -2345,9 +2346,12 @@ int mana_attach(struct net_device *ndev) · 2331 unmodified lines | |||
| 2345 | static int mana_dealloc_queues(struct net_device *ndev) | 2346 | static int mana_dealloc_queues(struct net_device *ndev) |
| 2346 | { | 2347 | { |
| 2347 | struct mana_port_context *apc = netdev_priv(ndev); | 2348 | struct mana_port_context *apc = netdev_priv(ndev); |
| 2349 | unsigned long timeout = jiffies + 120 * HZ; | ||
| 2348 | struct gdma_dev *gd = apc->ac->gdma_dev; | 2350 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 2349 | struct mana_txq *txq; | 2351 | struct mana_txq *txq; |
| 2352 | struct sk_buff *skb; | ||
| 2350 | int i, err; | 2353 | int i, err; |
| 2354 | u32 tsleep; | ||
| 2351 | 2355 | ||
| 2352 | if (apc->port_is_up) | 2356 | if (apc->port_is_up) |
| 2353 | return -EINVAL; | 2357 | return -EINVAL; |
| @@ -2363,15 +2367,40 @@ static int mana_dealloc_queues(struct net_device *ndev) · 9 unmodified lines | |||
| 2363 | * to false, but it doesn't matter since mana_start_xmit() drops any | 2367 | * to false, but it doesn't matter since mana_start_xmit() drops any |
| 2364 | * new packets due to apc->port_is_up being false. | 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 | for (i = 0; i < apc->num_queues; i++) { | 2377 | for (i = 0; i < apc->num_queues; i++) { |
| 2369 | txq = &apc->tx_qp[i].txq; | 2378 | txq = &apc->tx_qp[i].txq; |
| 2370 | 2379 | tsleep = 1000; | |
| 2371 | while (atomic_read(&txq->pending_sends) > 0) | 2380 | while (atomic_read(&txq->pending_sends) > 0 && |
| 2372 | usleep_range(1000, 2000); | 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 | /* We're 100% sure the queues can no longer be woken up, because | 2404 | /* We're 100% sure the queues can no longer be woken up, because |
| 2376 | * we're sure now mana_poll_tx_cq() can't be running. | 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 | static void ionic_tx_timeout_work(struct work_struct *ws) | 1817 | static void ionic_tx_timeout_work(struct work_struct *ws) |
| 1818 | { | 1818 | { |
| 1819 | struct ionic_lif *lif = container_of(ws, struct ionic_lif, tx_timeout_work); | 1819 | struct ionic_lif *lif = container_of(ws, struct ionic_lif, tx_timeout_work); |
| 1820 | int err; | ||
| 1820 | 1821 | ||
| 1821 | if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) | 1822 | if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) |
| 1822 | return; | 1823 | return; |
| @@ -1829,8 +1830,11 @@ static void ionic_tx_timeout_work(struct work_struct *ws) · 6 unmodified lines | |||
| 1829 | 1830 | ||
| 1830 | mutex_lock(&lif->queue_lock); | 1831 | mutex_lock(&lif->queue_lock); |
| 1831 | ionic_stop_queues_reconfig(lif); | 1832 | ionic_stop_queues_reconfig(lif); |
| 1832 | ionic_start_queues_reconfig(lif); | 1833 | err = ionic_start_queues_reconfig(lif); |
| 1833 | mutex_unlock(&lif->queue_lock); | 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 | static void ionic_tx_timeout(struct net_device *netdev, unsigned int txqueue) | 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 | if (err) { | 2804 | if (err) { |
| 2801 | dev_err(lif->ionic->dev, | 2805 | dev_err(lif->ionic->dev, |
| 2802 | "CMB restore failed: %d\n", err); | 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); | 2811 | err = ionic_start_queues_reconfig(lif); |
| 2808 | } else { | 2812 | if (err) { |
| 2809 | /* This was detached in ionic_stop_queues_reconfig() */ | 2813 | dev_err(lif->ionic->dev, |
| 2810 | netif_device_attach(lif->netdev); | 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 | return err; | 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 | struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn); | 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 | * qed_ptt_release(): Release PTT Window. | 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 | static int qed_fcoe_get_stats(struct qed_hwfn *p_hwfn, | 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 | struct qed_ptt *p_ptt; | 699 | struct qed_ptt *p_ptt; |
| 699 | 700 | ||
| 700 | memset(p_stats, 0, sizeof(*p_stats)); | 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 | if (!p_ptt) { | 705 | if (!p_ptt) { |
| 705 | DP_ERR(p_hwfn, "Failed to acquire ptt\n"); | 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 | QED_SPQ_MODE_EBLOCK, NULL); | 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 | static int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats) | 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 | void qed_get_protocol_stats_fcoe(struct qed_dev *cdev, | 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 | struct qed_fcoe_stats proto_stats; | 993 | struct qed_fcoe_stats proto_stats; |
| 985 | 994 | ||
| 986 | /* Retrieve FW statistics */ | 995 | /* Retrieve FW statistics */ |
| 987 | memset(&proto_stats, 0, sizeof(proto_stats)); | 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 | DP_VERBOSE(cdev, QED_MSG_STORAGE, | 998 | DP_VERBOSE(cdev, QED_MSG_STORAGE, |
| 990 | "Failed to collect FCoE statistics\n"); | 999 | "Failed to collect FCoE statistics\n"); |
| 991 | return; | 1000 | return; |
| @@ -28,8 +28,20 @@ int qed_fcoe_alloc(struct qed_hwfn *p_hwfn); · 27 unmodified lines | |||
| 28 | void qed_fcoe_setup(struct qed_hwfn *p_hwfn); | 28 | void qed_fcoe_setup(struct qed_hwfn *p_hwfn); |
| 29 | 29 | ||
| 30 | void qed_fcoe_free(struct qed_hwfn *p_hwfn); | 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 | void qed_get_protocol_stats_fcoe(struct qed_dev *cdev, | 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 | #else /* CONFIG_QED_FCOE */ | 45 | #else /* CONFIG_QED_FCOE */ |
| 34 | static inline int qed_fcoe_alloc(struct qed_hwfn *p_hwfn) | 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 | static inline void qed_fcoe_free(struct qed_hwfn *p_hwfn) {} | 52 | static inline void qed_fcoe_free(struct qed_hwfn *p_hwfn) {} |
| 41 | 53 | ||
| 42 | static inline void qed_get_protocol_stats_fcoe(struct qed_dev *cdev, | 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 | #endif /* CONFIG_QED_FCOE */ | 59 | #endif /* CONFIG_QED_FCOE */ |
| @@ -23,7 +23,10 @@ · 22 unmodified lines | |||
| 23 | #include "qed_reg_addr.h" | 23 | #include "qed_reg_addr.h" |
| 24 | #include "qed_sriov.h" | 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 | /* Invalid values */ | 31 | /* Invalid values */ |
| 29 | #define QED_BAR_INVALID_OFFSET (cpu_to_le32(-1)) | 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 | struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn) | 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 | struct qed_ptt *p_ptt; | 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 | /* Take the free PTT from the list */ | 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 | spin_lock_bh(&p_hwfn->p_ptt_pool->lock); | 106 | spin_lock_bh(&p_hwfn->p_ptt_pool->lock); |
| 94 | 107 | ||
| 95 | if (!list_empty(&p_hwfn->p_ptt_pool->free_list)) { | 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 | spin_unlock_bh(&p_hwfn->p_ptt_pool->lock); | 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 | DP_NOTICE(p_hwfn, "PTT acquire timeout - failed to allocate PTT\n"); | 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 | static int qed_iscsi_get_stats(struct qed_hwfn *p_hwfn, | 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 | struct qed_ptt *p_ptt; | 1005 | struct qed_ptt *p_ptt; |
| 1005 | 1006 | ||
| 1006 | memset(stats, 0, sizeof(*stats)); | 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 | if (!p_ptt) { | 1010 | if (!p_ptt) { |
| 1010 | DP_ERR(p_hwfn, "Failed to acquire ptt\n"); | 1011 | DP_ERR(p_hwfn, "Failed to acquire ptt\n"); |
| 1011 | return -EAGAIN; | 1012 | return -EAGAIN; |
| @@ -1336,9 +1337,16 @@ static int qed_iscsi_destroy_conn(struct qed_dev *cdev, · 324 unmodified lines | |||
| 1336 | QED_SPQ_MODE_EBLOCK, NULL); | 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 | static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats) | 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 | static int qed_iscsi_change_mac(struct qed_dev *cdev, | 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 | void qed_get_protocol_stats_iscsi(struct qed_dev *cdev, | 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 | struct qed_iscsi_stats proto_stats; | 1372 | struct qed_iscsi_stats proto_stats; |
| 1364 | 1373 | ||
| 1365 | /* Retrieve FW statistics */ | 1374 | /* Retrieve FW statistics */ |
| 1366 | memset(&proto_stats, 0, sizeof(proto_stats)); | 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 | DP_VERBOSE(cdev, QED_MSG_STORAGE, | 1377 | DP_VERBOSE(cdev, QED_MSG_STORAGE, |
| 1369 | "Failed to collect ISCSI statistics\n"); | 1378 | "Failed to collect ISCSI statistics\n"); |
| 1370 | return; | 1379 | return; |
| @@ -39,11 +39,14 @@ void qed_iscsi_free(struct qed_hwfn *p_hwfn); · 38 unmodified lines | |||
| 39 | * | 39 | * |
| 40 | * @cdev: Qed dev pointer. | 40 | * @cdev: Qed dev pointer. |
| 41 | * @stats: Points to struct that will be filled with statistics. | 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 | * Return: Void. | 45 | * Return: Void. |
| 44 | */ | 46 | */ |
| 45 | void qed_get_protocol_stats_iscsi(struct qed_dev *cdev, | 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 | #else /* IS_ENABLED(CONFIG_QED_ISCSI) */ | 50 | #else /* IS_ENABLED(CONFIG_QED_ISCSI) */ |
| 48 | static inline int qed_iscsi_alloc(struct qed_hwfn *p_hwfn) | 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 | static inline void | 60 | static inline void |
| 58 | qed_get_protocol_stats_iscsi(struct qed_dev *cdev, | 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 | #endif /* IS_ENABLED(CONFIG_QED_ISCSI) */ | 64 | #endif /* IS_ENABLED(CONFIG_QED_ISCSI) */ |
| 61 | 65 | ||
| 62 | #endif | 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 | static void _qed_get_vport_stats(struct qed_dev *cdev, | 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 | u8 fw_vport = 0; | 1869 | u8 fw_vport = 0; |
| 1869 | int i; | 1870 | int i; |
| @@ -1872,10 +1873,11 @@ static void _qed_get_vport_stats(struct qed_dev *cdev, · 2 unmodified lines | |||
| 1872 | 1873 | ||
| 1873 | for_each_hwfn(cdev, i) { | 1874 | for_each_hwfn(cdev, i) { |
| 1874 | struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; | 1875 | struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; |
| 1875 | struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn) | 1876 | struct qed_ptt *p_ptt; |
| 1876 | : NULL; | ||
| 1877 | bool b_get_port_stats; | 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 | if (IS_PF(cdev)) { | 1881 | if (IS_PF(cdev)) { |
| 1880 | /* The main vport index is relative first */ | 1882 | /* The main vport index is relative first */ |
| 1881 | if (qed_fw_vport(p_hwfn, 0, &fw_vport)) { | 1883 | if (qed_fw_vport(p_hwfn, 0, &fw_vport)) { |
| @@ -1900,6 +1902,13 @@ out: · 18 unmodified lines | |||
| 1900 | } | 1902 | } |
| 1901 | 1903 | ||
| 1902 | void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats) | 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 | u32 i; | 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 | return; | 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 | if (!cdev->reset_stats) | 1922 | if (!cdev->reset_stats) |
| 1914 | return; | 1923 | return; |
| @@ -1960,7 +1969,7 @@ void qed_reset_vport_stats(struct qed_dev *cdev) · 45 unmodified lines | |||
| 1960 | if (!cdev->reset_stats) { | 1969 | if (!cdev->reset_stats) { |
| 1961 | DP_INFO(cdev, "Reset stats not allocated\n"); | 1970 | DP_INFO(cdev, "Reset stats not allocated\n"); |
| 1962 | } else { | 1971 | } else { |
| 1963 | _qed_get_vport_stats(cdev, cdev->reset_stats); | 1972 | _qed_get_vport_stats(cdev, cdev->reset_stats, false); |
| 1964 | cdev->reset_stats->common.link_change_count = 0; | 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 | enum spq_mode comp_mode, | 249 | enum spq_mode comp_mode, |
| 250 | struct qed_spq_comp_cb *p_comp_data); | 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 | void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats); | 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 | void qed_reset_vport_stats(struct qed_dev *cdev); | 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 | switch (type) { | 3093 | switch (type) { |
| 3094 | case QED_MCP_LAN_STATS: | 3094 | case QED_MCP_LAN_STATS: |
| 3095 | qed_get_vport_stats(cdev, ð_stats); | 3095 | qed_get_vport_stats_context(cdev, ð_stats, true); |
| 3096 | stats->lan_stats.ucast_rx_pkts = | 3096 | stats->lan_stats.ucast_rx_pkts = |
| 3097 | eth_stats.common.rx_ucast_pkts; | 3097 | eth_stats.common.rx_ucast_pkts; |
| 3098 | stats->lan_stats.ucast_tx_pkts = | 3098 | stats->lan_stats.ucast_tx_pkts = |
| @@ -3100,10 +3100,10 @@ void qed_get_protocol_stats(struct qed_dev *cdev, · 1 unmodified line | |||
| 3100 | stats->lan_stats.fcs_err = -1; | 3100 | stats->lan_stats.fcs_err = -1; |
| 3101 | break; | 3101 | break; |
| 3102 | case QED_MCP_FCOE_STATS: | 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 | break; | 3104 | break; |
| 3105 | case QED_MCP_ISCSI_STATS: | 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 | break; | 3107 | break; |
| 3108 | default: | 3108 | default: |
| 3109 | DP_VERBOSE(cdev, QED_MSG_SP, | 3109 | DP_VERBOSE(cdev, QED_MSG_SP, |
| @@ -40,15 +40,16 @@ · 39 unmodified lines | |||
| 40 | */ | 40 | */ |
| 41 | struct ef4_loopback_payload { | 41 | struct ef4_loopback_payload { |
| 42 | char pad[2]; /* Ensures ip is 4-byte aligned */ | 42 | char pad[2]; /* Ensures ip is 4-byte aligned */ |
| 43 | struct ethhdr header; | 43 | struct_group_attr(packet, __packed, |
| 44 | struct iphdr ip; | 44 | struct ethhdr header; |
| 45 | struct udphdr udp; | 45 | struct iphdr ip; |
| 46 | __be16 iteration; | 46 | struct udphdr udp; |
| 47 | char msg[64]; | 47 | __be16 iteration; |
| 48 | char msg[64]; | ||
| 49 | ); | ||
| 48 | } __packed __aligned(4); | 50 | } __packed __aligned(4); |
| 49 | #define EF4_LOOPBACK_PAYLOAD_LEN (sizeof(struct ef4_loopback_payload) - \ | 51 | #define EF4_LOOPBACK_PAYLOAD_LEN \ |
| 50 | offsetof(struct ef4_loopback_payload, \ | 52 | sizeof_field(struct ef4_loopback_payload, packet) |
| 51 | header)) | ||
| 52 | 53 | ||
| 53 | /* Loopback test source MAC address */ | 54 | /* Loopback test source MAC address */ |
| 54 | static const u8 payload_source[ETH_ALEN] __aligned(2) = { | 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 | payload = &state->payload; | 301 | payload = &state->payload; |
| 301 | 302 | ||
| 302 | memcpy(&received.header, buf_ptr, | 303 | memcpy(&received.packet, buf_ptr, |
| 303 | min_t(int, pkt_len, EF4_LOOPBACK_PAYLOAD_LEN)); | 304 | min_t(int, pkt_len, EF4_LOOPBACK_PAYLOAD_LEN)); |
| 304 | received.ip.saddr = payload->ip.saddr; | 305 | received.ip.saddr = payload->ip.saddr; |
| 305 | if (state->offload_csum) | 306 | if (state->offload_csum) |
| @@ -370,7 +371,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx, · 64 unmodified lines | |||
| 370 | buf_ptr, pkt_len, 0); | 371 | buf_ptr, pkt_len, 0); |
| 371 | netif_err(efx, drv, efx->net_dev, "expected packet:\n"); | 372 | netif_err(efx, drv, efx->net_dev, "expected packet:\n"); |
| 372 | print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, | 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 | 0); | 375 | 0); |
| 375 | } | 376 | } |
| 376 | #endif | 377 | #endif |
| @@ -440,6 +441,8 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue) · 63 unmodified lines | |||
| 440 | payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); | 441 | payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); |
| 441 | /* Strip off the leading padding */ | 442 | /* Strip off the leading padding */ |
| 442 | skb_pull(skb, offsetof(struct ef4_loopback_payload, header)); | 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 | /* Ensure everything we've written is visible to the | 447 | /* Ensure everything we've written is visible to the |
| 445 | * interrupt handler. */ | 448 | * interrupt handler. */ |
| @@ -43,15 +43,16 @@ · 42 unmodified lines | |||
| 43 | */ | 43 | */ |
| 44 | struct efx_loopback_payload { | 44 | struct efx_loopback_payload { |
| 45 | char pad[2]; /* Ensures ip is 4-byte aligned */ | 45 | char pad[2]; /* Ensures ip is 4-byte aligned */ |
| 46 | struct ethhdr header; | 46 | struct_group_attr(packet, __packed, |
| 47 | struct iphdr ip; | 47 | struct ethhdr header; |
| 48 | struct udphdr udp; | 48 | struct iphdr ip; |
| 49 | __be16 iteration; | 49 | struct udphdr udp; |
| 50 | char msg[64]; | 50 | __be16 iteration; |
| 51 | char msg[64]; | ||
| 52 | ); | ||
| 51 | } __packed __aligned(4); | 53 | } __packed __aligned(4); |
| 52 | #define EFX_LOOPBACK_PAYLOAD_LEN (sizeof(struct efx_loopback_payload) - \ | 54 | #define EFX_LOOPBACK_PAYLOAD_LEN \ |
| 53 | offsetof(struct efx_loopback_payload, \ | 55 | sizeof_field(struct efx_loopback_payload, packet) |
| 54 | header)) | ||
| 55 | 56 | ||
| 56 | /* Loopback test source MAC address */ | 57 | /* Loopback test source MAC address */ |
| 57 | static const u8 payload_source[ETH_ALEN] __aligned(2) = { | 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 | payload = &state->payload; | 299 | payload = &state->payload; |
| 299 | 300 | ||
| 300 | memcpy(&received.header, buf_ptr, | 301 | memcpy(&received.packet, buf_ptr, |
| 301 | min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); | 302 | min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); |
| 302 | received.ip.saddr = payload->ip.saddr; | 303 | received.ip.saddr = payload->ip.saddr; |
| 303 | if (state->offload_csum) | 304 | if (state->offload_csum) |
| @@ -368,7 +369,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, · 64 unmodified lines | |||
| 368 | buf_ptr, pkt_len, 0); | 369 | buf_ptr, pkt_len, 0); |
| 369 | netif_err(efx, drv, efx->net_dev, "expected packet:\n"); | 370 | netif_err(efx, drv, efx->net_dev, "expected packet:\n"); |
| 370 | print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, | 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 | 0); | 373 | 0); |
| 373 | } | 374 | } |
| 374 | #endif | 375 | #endif |
| @@ -438,6 +439,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) · 63 unmodified lines | |||
| 438 | payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); | 439 | payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); |
| 439 | /* Strip off the leading padding */ | 440 | /* Strip off the leading padding */ |
| 440 | skb_pull(skb, offsetof(struct efx_loopback_payload, header)); | 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 | /* Ensure everything we've written is visible to the | 445 | /* Ensure everything we've written is visible to the |
| 443 | * interrupt handler. */ | 446 | * interrupt handler. */ |
| @@ -43,15 +43,16 @@ · 42 unmodified lines | |||
| 43 | */ | 43 | */ |
| 44 | struct efx_loopback_payload { | 44 | struct efx_loopback_payload { |
| 45 | char pad[2]; /* Ensures ip is 4-byte aligned */ | 45 | char pad[2]; /* Ensures ip is 4-byte aligned */ |
| 46 | struct ethhdr header; | 46 | struct_group_attr(packet, __packed, |
| 47 | struct iphdr ip; | 47 | struct ethhdr header; |
| 48 | struct udphdr udp; | 48 | struct iphdr ip; |
| 49 | __be16 iteration; | 49 | struct udphdr udp; |
| 50 | char msg[64]; | 50 | __be16 iteration; |
| 51 | char msg[64]; | ||
| 52 | ); | ||
| 51 | } __packed __aligned(4); | 53 | } __packed __aligned(4); |
| 52 | #define EFX_LOOPBACK_PAYLOAD_LEN (sizeof(struct efx_loopback_payload) - \ | 54 | #define EFX_LOOPBACK_PAYLOAD_LEN \ |
| 53 | offsetof(struct efx_loopback_payload, \ | 55 | sizeof_field(struct efx_loopback_payload, packet) |
| 54 | header)) | ||
| 55 | 56 | ||
| 56 | /* Loopback test source MAC address */ | 57 | /* Loopback test source MAC address */ |
| 57 | static const u8 payload_source[ETH_ALEN] __aligned(2) = { | 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 | payload = &state->payload; | 299 | payload = &state->payload; |
| 299 | 300 | ||
| 300 | memcpy(&received.header, buf_ptr, | 301 | memcpy(&received.packet, buf_ptr, |
| 301 | min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); | 302 | min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN)); |
| 302 | received.ip.saddr = payload->ip.saddr; | 303 | received.ip.saddr = payload->ip.saddr; |
| 303 | if (state->offload_csum) | 304 | if (state->offload_csum) |
| @@ -368,7 +369,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx, · 64 unmodified lines | |||
| 368 | buf_ptr, pkt_len, 0); | 369 | buf_ptr, pkt_len, 0); |
| 369 | netif_err(efx, drv, efx->net_dev, "expected packet:\n"); | 370 | netif_err(efx, drv, efx->net_dev, "expected packet:\n"); |
| 370 | print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, | 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 | 0); | 373 | 0); |
| 373 | } | 374 | } |
| 374 | #endif | 375 | #endif |
| @@ -438,6 +439,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue) · 63 unmodified lines | |||
| 438 | payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); | 439 | payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); |
| 439 | /* Strip off the leading padding */ | 440 | /* Strip off the leading padding */ |
| 440 | skb_pull(skb, offsetof(struct efx_loopback_payload, header)); | 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 | /* Ensure everything we've written is visible to the | 445 | /* Ensure everything we've written is visible to the |
| 443 | * interrupt handler. */ | 446 | * interrupt handler. */ |
| @@ -1851,6 +1851,17 @@ static int netsec_of_probe(struct platform_device *pdev, · 1850 unmodified lines | |||
| 1851 | return err; | 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 | priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); | 1865 | priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); |
| 1855 | if (!priv->phy_np) { | 1866 | if (!priv->phy_np) { |
| 1856 | dev_err(&pdev->dev, "missing required property 'phy-handle'\n"); | 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 | res.addr = mgbe->regs; | 234 | res.addr = mgbe->regs; |
| 235 | res.irq = irq; | 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 | if (!mgbe->clks) | 239 | if (!mgbe->clks) |
| 239 | return -ENOMEM; | 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 | /* Error handle returned DMA RX and TX interrupts */ | 1569 | /* Error handle returned DMA RX and TX interrupts */ |
| 1570 | if (lp->rx_irq < 0) | 1570 | if (lp->rx_irq <= 0) { |
| 1571 | return dev_err_probe(&pdev->dev, lp->rx_irq, | 1571 | rc = lp->rx_irq ?: -EINVAL; |
| 1572 | return dev_err_probe(&pdev->dev, rc, | ||
| 1572 | "could not get DMA RX irq\n"); | 1573 | "could not get DMA RX irq\n"); |
| 1573 | if (lp->tx_irq < 0) | 1574 | } |
| 1574 | return dev_err_probe(&pdev->dev, lp->tx_irq, | 1575 | if (lp->tx_irq <= 0) { |
| 1576 | rc = lp->tx_irq ?: -EINVAL; | ||
| 1577 | return dev_err_probe(&pdev->dev, rc, | ||
| 1575 | "could not get DMA TX irq\n"); | 1578 | "could not get DMA TX irq\n"); |
| 1579 | } | ||
| 1576 | 1580 | ||
| 1577 | if (temac_np) { | 1581 | if (temac_np) { |
| 1578 | /* Retrieve the MAC address */ | 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 | u64_stats_update_begin(&rxsc_stats->syncp); | 743 | u64_stats_update_begin(&rxsc_stats->syncp); |
| 744 | rxsc_stats->stats.InPktsLate++; | 744 | rxsc_stats->stats.InPktsLate++; |
| 745 | u64_stats_update_end(&rxsc_stats->syncp); | 745 | u64_stats_update_end(&rxsc_stats->syncp); |
| 746 | secy->netdev->stats.rx_dropped++; | 746 | DEV_STATS_INC(secy->netdev, rx_dropped); |
| 747 | return false; | 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 | rxsc_stats->stats.InPktsNotValid++; | 767 | rxsc_stats->stats.InPktsNotValid++; |
| 768 | u64_stats_update_end(&rxsc_stats->syncp); | 768 | u64_stats_update_end(&rxsc_stats->syncp); |
| 769 | this_cpu_inc(rx_sa->stats->InPktsNotValid); | 769 | this_cpu_inc(rx_sa->stats->InPktsNotValid); |
| 770 | secy->netdev->stats.rx_errors++; | 770 | DEV_STATS_INC(secy->netdev, rx_errors); |
| 771 | return false; | 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 | u64_stats_update_begin(&secy_stats->syncp); | 1069 | u64_stats_update_begin(&secy_stats->syncp); |
| 1070 | secy_stats->stats.InPktsNoTag++; | 1070 | secy_stats->stats.InPktsNoTag++; |
| 1071 | u64_stats_update_end(&secy_stats->syncp); | 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 | continue; | 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 | u64_stats_update_begin(&secy_stats->syncp); | 1179 | u64_stats_update_begin(&secy_stats->syncp); |
| 1180 | secy_stats->stats.InPktsBadTag++; | 1180 | secy_stats->stats.InPktsBadTag++; |
| 1181 | u64_stats_update_end(&secy_stats->syncp); | 1181 | u64_stats_update_end(&secy_stats->syncp); |
| 1182 | secy->netdev->stats.rx_errors++; | 1182 | DEV_STATS_INC(secy->netdev, rx_errors); |
| 1183 | goto drop_nosa; | 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 | u64_stats_update_begin(&rxsc_stats->syncp); | 1196 | u64_stats_update_begin(&rxsc_stats->syncp); |
| 1197 | rxsc_stats->stats.InPktsNotUsingSA++; | 1197 | rxsc_stats->stats.InPktsNotUsingSA++; |
| 1198 | u64_stats_update_end(&rxsc_stats->syncp); | 1198 | u64_stats_update_end(&rxsc_stats->syncp); |
| 1199 | secy->netdev->stats.rx_errors++; | 1199 | DEV_STATS_INC(secy->netdev, rx_errors); |
| 1200 | if (active_rx_sa) | 1200 | if (active_rx_sa) |
| 1201 | this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA); | 1201 | this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA); |
| 1202 | goto drop_nosa; | 1202 | goto drop_nosa; |
| @@ -1230,7 +1230,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) · 27 unmodified lines | |||
| 1230 | u64_stats_update_begin(&rxsc_stats->syncp); | 1230 | u64_stats_update_begin(&rxsc_stats->syncp); |
| 1231 | rxsc_stats->stats.InPktsLate++; | 1231 | rxsc_stats->stats.InPktsLate++; |
| 1232 | u64_stats_update_end(&rxsc_stats->syncp); | 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 | goto drop; | 1234 | goto drop; |
| 1235 | } | 1235 | } |
| 1236 | } | 1236 | } |
| @@ -1271,7 +1271,7 @@ deliver: · 34 unmodified lines | |||
| 1271 | if (ret == NET_RX_SUCCESS) | 1271 | if (ret == NET_RX_SUCCESS) |
| 1272 | count_rx(dev, len); | 1272 | count_rx(dev, len); |
| 1273 | else | 1273 | else |
| 1274 | macsec->secy.netdev->stats.rx_dropped++; | 1274 | DEV_STATS_INC(macsec->secy.netdev, rx_dropped); |
| 1275 | 1275 | ||
| 1276 | rcu_read_unlock(); | 1276 | rcu_read_unlock(); |
| 1277 | 1277 | ||
| @@ -1308,7 +1308,7 @@ nosci: · 30 unmodified lines | |||
| 1308 | u64_stats_update_begin(&secy_stats->syncp); | 1308 | u64_stats_update_begin(&secy_stats->syncp); |
| 1309 | secy_stats->stats.InPktsNoSCI++; | 1309 | secy_stats->stats.InPktsNoSCI++; |
| 1310 | u64_stats_update_end(&secy_stats->syncp); | 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 | continue; | 1312 | continue; |
| 1313 | } | 1313 | } |
| 1314 | 1314 | ||
| @@ -1327,7 +1327,7 @@ nosci: · 12 unmodified lines | |||
| 1327 | secy_stats->stats.InPktsUnknownSCI++; | 1327 | secy_stats->stats.InPktsUnknownSCI++; |
| 1328 | u64_stats_update_end(&secy_stats->syncp); | 1328 | u64_stats_update_end(&secy_stats->syncp); |
| 1329 | } else { | 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 | if (!secy->operational) { | 3423 | if (!secy->operational) { |
| 3424 | kfree_skb(skb); | 3424 | kfree_skb(skb); |
| 3425 | dev->stats.tx_dropped++; | 3425 | DEV_STATS_INC(dev, tx_dropped); |
| 3426 | return NETDEV_TX_OK; | 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 | skb = macsec_encrypt(skb, dev); | 3430 | skb = macsec_encrypt(skb, dev); |
| 3431 | if (IS_ERR(skb)) { | 3431 | if (IS_ERR(skb)) { |
| 3432 | if (PTR_ERR(skb) != -EINPROGRESS) | 3432 | if (PTR_ERR(skb) != -EINPROGRESS) |
| 3433 | dev->stats.tx_dropped++; | 3433 | DEV_STATS_INC(dev, tx_dropped); |
| 3434 | return NETDEV_TX_OK; | 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 | dev_fetch_sw_netstats(s, dev->tstats); | 3668 | dev_fetch_sw_netstats(s, dev->tstats); |
| 3669 | 3669 | ||
| 3670 | s->rx_dropped = dev->stats.rx_dropped; | 3670 | s->rx_dropped = atomic_long_read(&dev->stats.__rx_dropped); |
| 3671 | s->tx_dropped = dev->stats.tx_dropped; | 3671 | s->tx_dropped = atomic_long_read(&dev->stats.__tx_dropped); |
| 3672 | s->rx_errors = dev->stats.rx_errors; | 3672 | s->rx_errors = atomic_long_read(&dev->stats.__rx_errors); |
| 3673 | } | 3673 | } |
| 3674 | 3674 | ||
| 3675 | static int macsec_get_iflink(const struct net_device *dev) | 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 | phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], | 459 | phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i], |
| 460 | mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); | 460 | mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); |
| 461 | 461 | ||
| 462 | /* Enable WOL function */ | 462 | /* Enable WOL function for 1588 */ |
| 463 | ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL, | 463 | if (phydev->drv->phy_id == ATH8031_PHY_ID) { |
| 464 | 0, AT803X_WOL_EN); | 464 | ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, |
| 465 | if (ret) | 465 | AT803X_PHY_MMD3_WOL_CTRL, |
| 466 | return ret; | 466 | 0, AT803X_WOL_EN); |
| 467 | if (ret) | ||
| 468 | return ret; | ||
| 469 | } | ||
| 467 | /* Enable WOL interrupt */ | 470 | /* Enable WOL interrupt */ |
| 468 | ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); | 471 | ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL); |
| 469 | if (ret) | 472 | if (ret) |
| 470 | return ret; | 473 | return ret; |
| 471 | } else { | 474 | } else { |
| 472 | /* Disable WoL function */ | 475 | /* Disable WoL function for 1588 */ |
| 473 | ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL, | 476 | if (phydev->drv->phy_id == ATH8031_PHY_ID) { |
| 474 | AT803X_WOL_EN, 0); | 477 | ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, |
| 475 | if (ret) | 478 | AT803X_PHY_MMD3_WOL_CTRL, |
| 476 | return ret; | 479 | AT803X_WOL_EN, 0); |
| 480 | if (ret) | ||
| 481 | return ret; | ||
| 482 | } | ||
| 477 | /* Disable WOL interrupt */ | 483 | /* Disable WOL interrupt */ |
| 478 | ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); | 484 | ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0); |
| 479 | if (ret) | 485 | if (ret) |
| @@ -508,11 +514,11 @@ static void at803x_get_wol(struct phy_device *phydev, · 28 unmodified lines | |||
| 508 | wol->supported = WAKE_MAGIC; | 514 | wol->supported = WAKE_MAGIC; |
| 509 | wol->wolopts = 0; | 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 | if (value < 0) | 518 | if (value < 0) |
| 513 | return; | 519 | return; |
| 514 | 520 | ||
| 515 | if (value & AT803X_WOL_EN) | 521 | if (value & AT803X_INTR_ENABLE_WOL) |
| 516 | wol->wolopts |= WAKE_MAGIC; | 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 | if (phydev->drv->phy_id == ATH8031_PHY_ID) { | 864 | if (phydev->drv->phy_id == ATH8031_PHY_ID) { |
| 859 | int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); | 865 | int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); |
| 860 | int mode_cfg; | 866 | int mode_cfg; |
| 861 | struct ethtool_wolinfo wol = { | ||
| 862 | .wolopts = 0, | ||
| 863 | }; | ||
| 864 | 867 | ||
| 865 | if (ccr < 0) | 868 | if (ccr < 0) |
| 866 | return ccr; | 869 | return ccr; |
| @@ -877,12 +880,14 @@ static int at803x_probe(struct phy_device *phydev) · 10 unmodified lines | |||
| 877 | break; | 880 | break; |
| 878 | } | 881 | } |
| 879 | 882 | ||
| 880 | /* Disable WOL by default */ | 883 | /* Disable WoL in 1588 register which is enabled |
| 881 | ret = at803x_set_wol(phydev, &wol); | 884 | * by default |
| 882 | if (ret < 0) { | 885 | */ |
| 883 | phydev_err(phydev, "failed to disable WOL on probe: %d\n", ret); | 886 | ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, |
| 887 | AT803X_PHY_MMD3_WOL_CTRL, | ||
| 888 | AT803X_WOL_EN, 0); | ||
| 889 | if (ret) | ||
| 884 | return ret; | 890 | return ret; |
| 885 | } | ||
| 886 | } | 891 | } |
| 887 | 892 | ||
| 888 | return 0; | 893 | return 0; |
| @@ -2059,8 +2064,6 @@ static struct phy_driver at803x_driver[] = { · 1170 unmodified lines | |||
| 2059 | .flags = PHY_POLL_CABLE_TEST, | 2064 | .flags = PHY_POLL_CABLE_TEST, |
| 2060 | .config_init = at803x_config_init, | 2065 | .config_init = at803x_config_init, |
| 2061 | .link_change_notify = at803x_link_change_notify, | 2066 | .link_change_notify = at803x_link_change_notify, |
| 2062 | .set_wol = at803x_set_wol, | ||
| 2063 | .get_wol = at803x_get_wol, | ||
| 2064 | .suspend = at803x_suspend, | 2067 | .suspend = at803x_suspend, |
| 2065 | .resume = at803x_resume, | 2068 | .resume = at803x_resume, |
| 2066 | /* PHY_BASIC_FEATURES */ | 2069 | /* PHY_BASIC_FEATURES */ |
| @@ -534,7 +534,7 @@ static int tap_open(struct inode *inode, struct file *file) · 533 unmodified lines | |||
| 534 | q->sock.state = SS_CONNECTED; | 534 | q->sock.state = SS_CONNECTED; |
| 535 | q->sock.file = file; | 535 | q->sock.file = file; |
| 536 | q->sock.ops = &tap_socket_ops; | 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 | q->sk.sk_write_space = tap_sock_write_space; | 538 | q->sk.sk_write_space = tap_sock_write_space; |
| 539 | q->sk.sk_destruct = tap_sock_destruct; | 539 | q->sk.sk_destruct = tap_sock_destruct; |
| 540 | q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; | 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 | if (zerocopy) | 1594 | if (zerocopy) |
| 1595 | return false; | 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 | SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PAGE_SIZE) | 1598 | SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PAGE_SIZE) |
| 1599 | return false; | 1599 | return false; |
| 1600 | 1600 | ||
| @@ -3469,7 +3469,7 @@ static int tun_chr_open(struct inode *inode, struct file * file) · 1868 unmodified lines | |||
| 3469 | tfile->socket.file = file; | 3469 | tfile->socket.file = file; |
| 3470 | tfile->socket.ops = &tun_socket_ops; | 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 | tfile->sk.sk_write_space = tun_sock_write_space; | 3474 | tfile->sk.sk_write_space = tun_sock_write_space; |
| 3475 | tfile->sk.sk_sndbuf = INT_MAX; | 3475 | tfile->sk.sk_sndbuf = INT_MAX; |
| @@ -618,9 +618,23 @@ static const struct usb_device_id products[] = { · 617 unmodified lines | |||
| 618 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | 618 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 619 | | USB_DEVICE_ID_MATCH_DEVICE, | 619 | | USB_DEVICE_ID_MATCH_DEVICE, |
| 620 | .idVendor = 0x04DD, | 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 | .idProduct = 0x8006, /* B-500/SL-5600 */ | 628 | .idProduct = 0x8006, /* B-500/SL-5600 */ |
| 622 | ZAURUS_MASTER_INTERFACE, | 629 | ZAURUS_MASTER_INTERFACE, |
| 623 | .driver_info = 0, | 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 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | 639 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 626 | | USB_DEVICE_ID_MATCH_DEVICE, | 640 | | USB_DEVICE_ID_MATCH_DEVICE, |
| @@ -628,6 +642,13 @@ static const struct usb_device_id products[] = { · 1 unmodified line | |||
| 628 | .idProduct = 0x8007, /* C-700 */ | 642 | .idProduct = 0x8007, /* C-700 */ |
| 629 | ZAURUS_MASTER_INTERFACE, | 643 | ZAURUS_MASTER_INTERFACE, |
| 630 | .driver_info = 0, | 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 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | 653 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 633 | | USB_DEVICE_ID_MATCH_DEVICE, | 654 | | USB_DEVICE_ID_MATCH_DEVICE, |
| @@ -4224,8 +4224,6 @@ static void lan78xx_disconnect(struct usb_interface *intf) · 4223 unmodified lines | |||
| 4224 | if (!dev) | 4224 | if (!dev) |
| 4225 | return; | 4225 | return; |
| 4226 | 4226 | ||
| 4227 | set_bit(EVENT_DEV_DISCONNECT, &dev->flags); | ||
| 4228 | |||
| 4229 | netif_napi_del(&dev->napi); | 4227 | netif_napi_del(&dev->napi); |
| 4230 | 4228 | ||
| 4231 | udev = interface_to_usbdev(intf); | 4229 | udev = interface_to_usbdev(intf); |
| @@ -4233,6 +4231,8 @@ static void lan78xx_disconnect(struct usb_interface *intf) · 1 unmodified line | |||
| 4233 | 4231 | ||
| 4234 | unregister_netdev(net); | 4232 | unregister_netdev(net); |
| 4235 | 4233 | ||
| 4234 | timer_shutdown_sync(&dev->stat_monitor); | ||
| 4235 | set_bit(EVENT_DEV_DISCONNECT, &dev->flags); | ||
| 4236 | cancel_delayed_work_sync(&dev->wq); | 4236 | cancel_delayed_work_sync(&dev->wq); |
| 4237 | 4237 | ||
| 4238 | phydev = net->phydev; | 4238 | phydev = net->phydev; |
| @@ -4247,9 +4247,6 @@ static void lan78xx_disconnect(struct usb_interface *intf) · 8 unmodified lines | |||
| 4247 | 4247 | ||
| 4248 | usb_scuttle_anchored_urbs(&dev->deferred); | 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 | lan78xx_unbind(dev, intf); | 4250 | lan78xx_unbind(dev, intf); |
| 4254 | 4251 | ||
| 4255 | lan78xx_free_tx_resources(dev); | 4252 | lan78xx_free_tx_resources(dev); |
| @@ -1423,6 +1423,7 @@ static const struct usb_device_id products[] = { · 1422 unmodified lines | |||
| 1423 | {QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */ | 1423 | {QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */ |
| 1424 | {QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */ | 1424 | {QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */ |
| 1425 | {QMI_FIXED_INTF(0x2c7c, 0x0296, 4)}, /* Quectel BG96 */ | 1425 | {QMI_FIXED_INTF(0x2c7c, 0x0296, 4)}, /* Quectel BG96 */ |
| 1426 | {QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)}, /* Quectel EM05GV2 */ | ||
| 1426 | {QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */ | 1427 | {QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */ |
| 1427 | {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */ | 1428 | {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */ |
| 1428 | {QMI_FIXED_INTF(0x0489, 0xe0b5, 0)}, /* Foxconn T77W968 LTE with eSIM support*/ | 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 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | 289 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 290 | | USB_DEVICE_ID_MATCH_DEVICE, | 290 | | USB_DEVICE_ID_MATCH_DEVICE, |
| 291 | .idVendor = 0x04DD, | 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 | .idProduct = 0x8006, /* B-500/SL-5600 */ | 299 | .idProduct = 0x8006, /* B-500/SL-5600 */ |
| 293 | ZAURUS_MASTER_INTERFACE, | 300 | ZAURUS_MASTER_INTERFACE, |
| 294 | .driver_info = ZAURUS_PXA_INFO, | 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 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | 310 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 297 | | USB_DEVICE_ID_MATCH_DEVICE, | 311 | | USB_DEVICE_ID_MATCH_DEVICE, |
| @@ -299,6 +313,13 @@ static const struct usb_device_id products [] = { · 1 unmodified line | |||
| 299 | .idProduct = 0x8007, /* C-700 */ | 313 | .idProduct = 0x8007, /* C-700 */ |
| 300 | ZAURUS_MASTER_INTERFACE, | 314 | ZAURUS_MASTER_INTERFACE, |
| 301 | .driver_info = ZAURUS_PXA_INFO, | 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 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | 324 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
| 304 | | USB_DEVICE_ID_MATCH_DEVICE, | 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 | return vninode; | 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 | static int vxlan_vni_add(struct vxlan_dev *vxlan, | 722 | static int vxlan_vni_add(struct vxlan_dev *vxlan, |
| 717 | struct vxlan_vni_group *vg, | 723 | struct vxlan_vni_group *vg, |
| 718 | u32 vni, union vxlan_addr *group, | 724 | u32 vni, union vxlan_addr *group, |
| @@ -740,7 +746,7 @@ static int vxlan_vni_add(struct vxlan_dev *vxlan, · 21 unmodified lines | |||
| 740 | &vninode->vnode, | 746 | &vninode->vnode, |
| 741 | vxlan_vni_rht_params); | 747 | vxlan_vni_rht_params); |
| 742 | if (err) { | 748 | if (err) { |
| 743 | kfree(vninode); | 749 | vxlan_vni_free(vninode); |
| 744 | return err; | 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 | struct vxlan_vni_node *v; | 769 | struct vxlan_vni_node *v; |
| 764 | 770 | ||
| 765 | v = container_of(rcu, struct vxlan_vni_node, rcu); | 771 | v = container_of(rcu, struct vxlan_vni_node, rcu); |
| 766 | free_percpu(v->stats); | 772 | vxlan_vni_free(v); |
| 767 | kfree(v); | ||
| 768 | } | 773 | } |
| 769 | 774 | ||
| 770 | static int vxlan_vni_del(struct vxlan_dev *vxlan, | 775 | static int vxlan_vni_del(struct vxlan_dev *vxlan, |
| @@ -6,7 +6,7 @@ · 5 unmodified lines | |||
| 6 | #include "allowedips.h" | 6 | #include "allowedips.h" |
| 7 | #include "peer.h" | 7 | #include "peer.h" |
| 8 | 8 | ||
| 9 | enum { MAX_ALLOWEDIPS_BITS = 128 }; | 9 | enum { MAX_ALLOWEDIPS_DEPTH = 129 }; |
| 10 | 10 | ||
| 11 | static struct kmem_cache *node_cache; | 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 | struct allowedips_node __rcu *p, unsigned int *len) | 42 | struct allowedips_node __rcu *p, unsigned int *len) |
| 43 | { | 43 | { |
| 44 | if (rcu_access_pointer(p)) { | 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 | return; | 46 | return; |
| 47 | stack[(*len)++] = rcu_dereference_raw(p); | 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 | static void root_free_rcu(struct rcu_head *rcu) | 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 | container_of(rcu, struct allowedips_node, rcu) }; | 59 | container_of(rcu, struct allowedips_node, rcu) }; |
| 60 | unsigned int len = 1; | 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 | static void root_remove_peer_lists(struct allowedips_node *root) | 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 | unsigned int len = 1; | 72 | unsigned int len = 1; |
| 73 | 73 | ||
| 74 | while (len > 0 && (node = stack[--len])) { | 74 | while (len > 0 && (node = stack[--len])) { |
| @@ -593,16 +593,20 @@ bool __init wg_allowedips_selftest(void) · 592 unmodified lines | |||
| 593 | wg_allowedips_remove_by_peer(&t, a, &mutex); | 593 | wg_allowedips_remove_by_peer(&t, a, &mutex); |
| 594 | test_negative(4, a, 192, 168, 0, 1); | 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 | * if something goes wrong. | 597 | * if something goes wrong. |
| 598 | */ | 598 | */ |
| 599 | for (i = 0; i < MAX_ALLOWEDIPS_BITS; ++i) { | 599 | for (i = 0; i < 64; ++i) { |
| 600 | part = cpu_to_be64(~(1LLU << (i % 64))); | 600 | part = cpu_to_be64(~0LLU << i); |
| 601 | memset(&ip, 0xff, 16); | 601 | memset(&ip, 0xff, 8); |
| 602 | memcpy((u8 *)&ip + (i < 64) * 8, &part, 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 | wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex); | 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 | wg_allowedips_free(&t, &mutex); | 610 | wg_allowedips_free(&t, &mutex); |
| 607 | 611 | ||
| 608 | wg_allowedips_init(&t); | 612 | wg_allowedips_init(&t); |
| @@ -376,7 +376,6 @@ static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab) · 375 unmodified lines | |||
| 376 | struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; | 376 | struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; |
| 377 | 377 | ||
| 378 | if (!irq_grp->napi_enabled) { | 378 | if (!irq_grp->napi_enabled) { |
| 379 | dev_set_threaded(&irq_grp->napi_ndev, true); | ||
| 380 | napi_enable(&irq_grp->napi); | 379 | napi_enable(&irq_grp->napi); |
| 381 | irq_grp->napi_enabled = true; | 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 | struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; | 466 | struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; |
| 467 | 467 | ||
| 468 | if (!irq_grp->napi_enabled) { | 468 | if (!irq_grp->napi_enabled) { |
| 469 | dev_set_threaded(&irq_grp->napi_ndev, true); | ||
| 470 | napi_enable(&irq_grp->napi); | 469 | napi_enable(&irq_grp->napi); |
| 471 | irq_grp->napi_enabled = true; | 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 | struct wmi_tlv *tlv; | 2144 | struct wmi_tlv *tlv; |
| 2145 | void *ptr; | 2145 | void *ptr; |
| 2146 | int i, ret, len; | 2146 | int i, ret, len; |
| 2147 | u32 *tmp_ptr; | 2147 | u32 *tmp_ptr, extraie_len_with_pad = 0; |
| 2148 | u8 extraie_len_with_pad = 0; | ||
| 2149 | struct ath12k_wmi_hint_short_ssid_arg *s_ssid = NULL; | 2148 | struct ath12k_wmi_hint_short_ssid_arg *s_ssid = NULL; |
| 2150 | struct ath12k_wmi_hint_bssid_arg *hint_bssid = NULL; | 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 | ath6kl_core-y += core.o | 36 | ath6kl_core-y += core.o |
| 37 | ath6kl_core-y += recovery.o | 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 | ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o | 39 | ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o |
| 45 | ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o | 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 | params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE; | 1456 | params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE; |
| 1457 | params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE; | 1457 | params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE; |
| 1458 | params_v1 = kzalloc(params_size, GFP_KERNEL); | 1458 | params_v1 = kzalloc(params_size, GFP_KERNEL); |
| 1459 | if (!params_v1) { | ||
| 1460 | err = -ENOMEM; | ||
| 1461 | goto exit_params; | ||
| 1462 | } | ||
| 1459 | params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); | 1463 | params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); |
| 1460 | brcmf_scan_params_v2_to_v1(¶ms->params_v2_le, ¶ms_v1->params_le); | 1464 | brcmf_scan_params_v2_to_v1(¶ms->params_v2_le, ¶ms_v1->params_le); |
| 1461 | kfree(params); | 1465 | kfree(params); |
| @@ -1473,6 +1477,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, · 11 unmodified lines | |||
| 1473 | bphy_err(drvr, "error (%d)\n", err); | 1477 | bphy_err(drvr, "error (%d)\n", err); |
| 1474 | } | 1478 | } |
| 1475 | 1479 | ||
| 1480 | exit_params: | ||
| 1476 | kfree(params); | 1481 | kfree(params); |
| 1477 | exit: | 1482 | exit: |
| 1478 | return err; | 1483 | return err; |
| @@ -398,7 +398,12 @@ struct brcmf_scan_params_le { · 397 unmodified lines | |||
| 398 | * fixed parameter portion is assumed, otherwise | 398 | * fixed parameter portion is assumed, otherwise |
| 399 | * ssid in the fixed portion is ignored | 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 | struct brcmf_scan_params_v2_le { | 409 | struct brcmf_scan_params_v2_le { |
| @@ -577,7 +577,7 @@ struct tx_msg { · 576 unmodified lines | |||
| 577 | struct tib_structure tib; | 577 | struct tib_structure tib; |
| 578 | struct phy_header phy; | 578 | struct phy_header phy; |
| 579 | struct mac_header mac; | 579 | struct mac_header mac; |
| 580 | UCHAR var[1]; | 580 | UCHAR var[]; |
| 581 | }; | 581 | }; |
| 582 | 582 | ||
| 583 | /****** ECF Receive Control Structure (RCS) Area at Shared RAM offset 0x0800 */ | 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 | case MT_EE_5GHZ: | 128 | case MT_EE_5GHZ: |
| 129 | dev->mphy.cap.has_5ghz = true; | 129 | dev->mphy.cap.has_5ghz = true; |
| 130 | break; | 130 | break; |
| 131 | case MT_EE_2GHZ: | ||
| 132 | dev->mphy.cap.has_2ghz = true; | ||
| 133 | break; | ||
| 134 | case MT_EE_DBDC: | 131 | case MT_EE_DBDC: |
| 135 | dev->dbdc_support = true; | 132 | dev->dbdc_support = true; |
| 136 | fallthrough; | 133 | fallthrough; |
| 134 | case MT_EE_2GHZ: | ||
| 135 | dev->mphy.cap.has_2ghz = true; | ||
| 136 | break; | ||
| 137 | default: | 137 | default: |
| 138 | dev->mphy.cap.has_2ghz = true; | 138 | dev->mphy.cap.has_2ghz = true; |
| 139 | dev->mphy.cap.has_5ghz = true; | 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 | u32 reg; | 2524 | u32 reg; |
| 2525 | int ret; | 2525 | int ret; |
| 2526 | 2526 | ||
| 2527 | if (chip_id != RTL8852A && chip_id != RTL8852B) | 2527 | if (chip_id != RTL8852B) |
| 2528 | return 0; | 2528 | return 0; |
| 2529 | 2529 | ||
| 2530 | ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL); | 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 | struct gnttab_map_grant_ref *gop = queue->tx_map_ops + *map_ops; | 396 | struct gnttab_map_grant_ref *gop = queue->tx_map_ops + *map_ops; |
| 397 | struct xen_netif_tx_request *txp = first; | 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 | copy_count(skb) = 0; | 401 | copy_count(skb) = 0; |
| 402 | XENVIF_TX_CB(skb)->split_mask = 0; | 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; | 465 | for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS; |
| 466 | shinfo->nr_frags++, gop++) { | 466 | shinfo->nr_frags++, gop++, nr_slots--) { |
| 467 | index = pending_index(queue->pending_cons++); | 467 | index = pending_index(queue->pending_cons++); |
| 468 | pending_idx = queue->pending_ring[index]; | 468 | pending_idx = queue->pending_ring[index]; |
| 469 | xenvif_tx_create_map_op(queue, pending_idx, txp, | 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 | txp++; | 476 | txp++; |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | if (frag_overflow) { | 479 | if (nr_slots > 0) { |
| 480 | 480 | ||
| 481 | shinfo = skb_shinfo(nskb); | 481 | shinfo = skb_shinfo(nskb); |
| 482 | frags = shinfo->frags; | 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 | shinfo->nr_frags++, txp++, gop++) { | 485 | shinfo->nr_frags++, txp++, gop++) { |
| 486 | index = pending_index(queue->pending_cons++); | 486 | index = pending_index(queue->pending_cons++); |
| 487 | pending_idx = queue->pending_ring[index]; | 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 | skb_shinfo(skb)->frag_list = nskb; | 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 | (*copy_ops) = cop - queue->tx_copy_ops; | 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 | nvme_mpath_clear_ctrl_paths(ctrl); | 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 | /* prevent racing with ns scanning */ | 3942 | /* prevent racing with ns scanning */ |
| 3937 | flush_work(&ctrl->scan_work); | 3943 | flush_work(&ctrl->scan_work); |
| 3938 | 3944 | ||
| @@ -3942,10 +3948,8 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl) · 3 unmodified lines | |||
| 3942 | * removing the namespaces' disks; fail all the queues now to avoid | 3948 | * removing the namespaces' disks; fail all the queues now to avoid |
| 3943 | * potentially having to clean up the failed sync later. | 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 | nvme_mark_namespaces_dead(ctrl); | 3952 | nvme_mark_namespaces_dead(ctrl); |
| 3947 | nvme_unquiesce_io_queues(ctrl); | ||
| 3948 | } | ||
| 3949 | 3953 | ||
| 3950 | /* this is a no-op when called from the controller reset handler */ | 3954 | /* this is a no-op when called from the controller reset handler */ |
| 3951 | nvme_change_ctrl_state(ctrl, NVME_CTRL_DELETING_NOIO); | 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 | if (!(ioucmd->flags & IORING_URING_CMD_POLLED)) | 786 | if (!(ioucmd->flags & IORING_URING_CMD_POLLED)) |
| 787 | return 0; | 787 | return 0; |
| 788 | 788 | ||
| 789 | rcu_read_lock(); | ||
| 790 | req = READ_ONCE(ioucmd->cookie); | 789 | req = READ_ONCE(ioucmd->cookie); |
| 791 | if (req && blk_rq_is_poll(req)) | 790 | if (req && blk_rq_is_poll(req)) |
| 792 | ret = blk_rq_poll(req, iob, poll_flags); | 791 | ret = blk_rq_poll(req, iob, poll_flags); |
| 793 | rcu_read_unlock(); | ||
| 794 | return ret; | 792 | return ret; |
| 795 | } | 793 | } |
| 796 | #ifdef CONFIG_NVME_MULTIPATH | 794 | #ifdef CONFIG_NVME_MULTIPATH |
| @@ -3402,7 +3402,8 @@ static const struct pci_device_id nvme_id_table[] = { · 3401 unmodified lines | |||
| 3402 | { PCI_DEVICE(0x1d97, 0x2263), /* SPCC */ | 3402 | { PCI_DEVICE(0x1d97, 0x2263), /* SPCC */ |
| 3403 | .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, | 3403 | .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, |
| 3404 | { PCI_DEVICE(0x144d, 0xa80b), /* Samsung PM9B1 256G and 512G */ | 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 | { PCI_DEVICE(0x144d, 0xa809), /* Samsung MZALQ256HBJD 256G */ | 3407 | { PCI_DEVICE(0x144d, 0xa809), /* Samsung MZALQ256HBJD 256G */ |
| 3407 | .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, | 3408 | .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, |
| 3408 | { PCI_DEVICE(0x144d, 0xa802), /* Samsung SM953 */ | 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 | goto out_cleanup_tagset; | 883 | goto out_cleanup_tagset; |
| 884 | 884 | ||
| 885 | if (!new) { | 885 | if (!new) { |
| 886 | nvme_start_freeze(&ctrl->ctrl); | ||
| 886 | nvme_unquiesce_io_queues(&ctrl->ctrl); | 887 | nvme_unquiesce_io_queues(&ctrl->ctrl); |
| 887 | if (!nvme_wait_freeze_timeout(&ctrl->ctrl, NVME_IO_TIMEOUT)) { | 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 | * to be safe. | 892 | * to be safe. |
| 892 | */ | 893 | */ |
| 893 | ret = -ENODEV; | 894 | ret = -ENODEV; |
| 895 | nvme_unfreeze(&ctrl->ctrl); | ||
| 894 | goto out_wait_freeze_timed_out; | 896 | goto out_wait_freeze_timed_out; |
| 895 | } | 897 | } |
| 896 | blk_mq_update_nr_hw_queues(ctrl->ctrl.tagset, | 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 | bool remove) | 942 | bool remove) |
| 941 | { | 943 | { |
| 942 | if (ctrl->ctrl.queue_count > 1) { | 944 | if (ctrl->ctrl.queue_count > 1) { |
| 943 | nvme_start_freeze(&ctrl->ctrl); | ||
| 944 | nvme_quiesce_io_queues(&ctrl->ctrl); | 945 | nvme_quiesce_io_queues(&ctrl->ctrl); |
| 945 | nvme_sync_io_queues(&ctrl->ctrl); | 946 | nvme_sync_io_queues(&ctrl->ctrl); |
| 946 | nvme_rdma_stop_io_queues(ctrl); | 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 | goto out_cleanup_connect_q; | 1868 | goto out_cleanup_connect_q; |
| 1869 | 1869 | ||
| 1870 | if (!new) { | 1870 | if (!new) { |
| 1871 | nvme_start_freeze(ctrl); | ||
| 1871 | nvme_unquiesce_io_queues(ctrl); | 1872 | nvme_unquiesce_io_queues(ctrl); |
| 1872 | if (!nvme_wait_freeze_timeout(ctrl, NVME_IO_TIMEOUT)) { | 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 | * to be safe. | 1877 | * to be safe. |
| 1877 | */ | 1878 | */ |
| 1878 | ret = -ENODEV; | 1879 | ret = -ENODEV; |
| 1880 | nvme_unfreeze(ctrl); | ||
| 1879 | goto out_wait_freeze_timed_out; | 1881 | goto out_wait_freeze_timed_out; |
| 1880 | } | 1882 | } |
| 1881 | blk_mq_update_nr_hw_queues(ctrl->tagset, | 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 | if (ctrl->queue_count <= 1) | 1982 | if (ctrl->queue_count <= 1) |
| 1981 | return; | 1983 | return; |
| 1982 | nvme_quiesce_admin_queue(ctrl); | 1984 | nvme_quiesce_admin_queue(ctrl); |
| 1983 | nvme_start_freeze(ctrl); | ||
| 1984 | nvme_quiesce_io_queues(ctrl); | 1985 | nvme_quiesce_io_queues(ctrl); |
| 1985 | nvme_sync_io_queues(ctrl); | 1986 | nvme_sync_io_queues(ctrl); |
| 1986 | nvme_tcp_stop_io_queues(ctrl); | 1987 | nvme_tcp_stop_io_queues(ctrl); |
| @@ -121,6 +121,8 @@ module_param(sba_reserve_agpgart, int, 0444); · 120 unmodified lines | |||
| 121 | MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART"); | 121 | MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART"); |
| 122 | #endif | 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 | ** SBA register read and write support | 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 | #ifdef CONFIG_PROC_FS | 1970 | #ifdef CONFIG_PROC_FS |
| 1969 | switch (dev->id.hversion) { | 1971 | switch (dev->id.hversion) { |
| 1970 | case PLUTO_MCKINLEY_PORT: | 1972 | case PLUTO_MCKINLEY_PORT: |
| 1973 | if (!proc_mckinley_root) | ||
| 1974 | proc_mckinley_root = proc_mkdir("bus/mckinley", NULL); | ||
| 1971 | root = proc_mckinley_root; | 1975 | root = proc_mckinley_root; |
| 1972 | break; | 1976 | break; |
| 1973 | case ASTRO_RUNWAY_PORT: | 1977 | case ASTRO_RUNWAY_PORT: |
| 1974 | case IKE_MERCED_PORT: | 1978 | case IKE_MERCED_PORT: |
| 1975 | default: | 1979 | default: |
| 1980 | if (!proc_runway_root) | ||
| 1981 | proc_runway_root = proc_mkdir("bus/runway", NULL); | ||
| 1976 | root = proc_runway_root; | 1982 | root = proc_runway_root; |
| 1977 | break; | 1983 | break; |
| 1978 | } | 1984 | } |
| @@ -28,7 +28,6 @@ · 27 unmodified lines | |||
| 28 | #include <linux/sysctl.h> | 28 | #include <linux/sysctl.h> |
| 29 | 29 | ||
| 30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
| 31 | #include <asm/dma.h> | ||
| 32 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
| 33 | #include <asm/superio.h> | 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 | /* --- Initialisation code -------------------------------- */ | 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 | unsigned long base_hi, int irq, | 229 | unsigned long base_hi, int irq, |
| 231 | int dma, struct parisc_device *padev) | 230 | struct parisc_device *padev) |
| 232 | { | 231 | { |
| 233 | struct parport_gsc_private *priv; | 232 | struct parport_gsc_private *priv; |
| 234 | struct parport_operations *ops; | 233 | struct parport_operations *ops; |
| @@ -250,12 +249,9 @@ struct parport *parport_gsc_probe_port(unsigned long base, · 15 unmodified lines | |||
| 250 | } | 249 | } |
| 251 | priv->ctr = 0xc; | 250 | priv->ctr = 0xc; |
| 252 | priv->ctr_writable = 0xff; | 251 | priv->ctr_writable = 0xff; |
| 253 | priv->dma_buf = NULL; | ||
| 254 | priv->dma_handle = 0; | ||
| 255 | p->base = base; | 252 | p->base = base; |
| 256 | p->base_hi = base_hi; | 253 | p->base_hi = base_hi; |
| 257 | p->irq = irq; | 254 | p->irq = irq; |
| 258 | p->dma = dma; | ||
| 259 | p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; | 255 | p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; |
| 260 | p->ops = ops; | 256 | p->ops = ops; |
| 261 | p->private_data = priv; | 257 | p->private_data = priv; |
| @@ -286,17 +282,9 @@ struct parport *parport_gsc_probe_port(unsigned long base, · 24 unmodified lines | |||
| 286 | if (p->irq == PARPORT_IRQ_AUTO) { | 282 | if (p->irq == PARPORT_IRQ_AUTO) { |
| 287 | p->irq = PARPORT_IRQ_NONE; | 283 | p->irq = PARPORT_IRQ_NONE; |
| 288 | } | 284 | } |
| 289 | if (p->irq != PARPORT_IRQ_NONE) { | 285 | if (p->irq != PARPORT_IRQ_NONE) |
| 290 | pr_cont(", irq %d", p->irq); | 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 | pr_cont(" ["); | 288 | pr_cont(" ["); |
| 301 | #define printmode(x) \ | 289 | #define printmode(x) \ |
| 302 | do { \ | 290 | do { \ |
| @@ -321,7 +309,6 @@ do { \ · 18 unmodified lines | |||
| 321 | pr_warn("%s: irq %d in use, resorting to polled operation\n", | 309 | pr_warn("%s: irq %d in use, resorting to polled operation\n", |
| 322 | p->name, p->irq); | 310 | p->name, p->irq); |
| 323 | p->irq = PARPORT_IRQ_NONE; | 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 | pr_info("%s: enhanced parport-modes not supported\n", __func__); | 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, | 359 | p = parport_gsc_probe_port(port, 0, dev->irq, dev); |
| 373 | /* PARPORT_IRQ_NONE */ PARPORT_DMA_NONE, dev); | ||
| 374 | if (p) | 360 | if (p) |
| 375 | parport_count++; | 361 | parport_count++; |
| 376 | dev_set_drvdata(&dev->dev, p); | 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 | struct parport *p = dev_get_drvdata(&dev->dev); | 369 | struct parport *p = dev_get_drvdata(&dev->dev); |
| 384 | if (p) { | 370 | if (p) { |
| 385 | struct parport_gsc_private *priv = p->private_data; | ||
| 386 | struct parport_operations *ops = p->ops; | 371 | struct parport_operations *ops = p->ops; |
| 387 | parport_remove_port(p); | 372 | parport_remove_port(p); |
| 388 | if (p->dma != PARPORT_DMA_NONE) | ||
| 389 | free_dma(p->dma); | ||
| 390 | if (p->irq != PARPORT_IRQ_NONE) | 373 | if (p->irq != PARPORT_IRQ_NONE) |
| 391 | free_irq(p->irq, p); | 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 | kfree (p->private_data); | 375 | kfree (p->private_data); |
| 396 | parport_put_port(p); | 376 | parport_put_port(p); |
| 397 | kfree (ops); /* hope no-one cached it */ | 377 | kfree (ops); /* hope no-one cached it */ |
| @@ -63,8 +63,6 @@ struct parport_gsc_private { · 62 unmodified lines | |||
| 63 | int writeIntrThreshold; | 63 | int writeIntrThreshold; |
| 64 | 64 | ||
| 65 | /* buffer suitable for DMA, if DMA enabled */ | 65 | /* buffer suitable for DMA, if DMA enabled */ |
| 66 | char *dma_buf; | ||
| 67 | dma_addr_t dma_handle; | ||
| 68 | struct pci_dev *dev; | 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 | extern void parport_gsc_dec_use_count(void); | 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 | #endif /* __DRIVERS_PARPORT_PARPORT_GSC_H */ | 200 | #endif /* __DRIVERS_PARPORT_PARPORT_GSC_H */ |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
| 12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| 13 | #include <linux/ioport.h> | 13 | #include <linux/ioport.h> |
| 14 | #include <linux/of.h> | ||
| 14 | #include <linux/proc_fs.h> | 15 | #include <linux/proc_fs.h> |
| 15 | #include <linux/slab.h> | 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 | void pci_bus_add_device(struct pci_dev *dev) | 334 | void pci_bus_add_device(struct pci_dev *dev) |
| 334 | { | 335 | { |
| 336 | struct device_node *dn = dev->dev.of_node; | ||
| 335 | int retval; | 337 | int retval; |
| 336 | 338 | ||
| 337 | /* | 339 | /* |
| @@ -344,7 +346,7 @@ void pci_bus_add_device(struct pci_dev *dev) · 6 unmodified lines | |||
| 344 | pci_proc_attach_device(dev); | 346 | pci_proc_attach_device(dev); |
| 345 | pci_bridge_d3_update(dev); | 347 | pci_bridge_d3_update(dev); |
| 346 | 348 | ||
| 347 | dev->match_driver = true; | 349 | dev->match_driver = !dn || of_device_is_available(dn); |
| 348 | retval = device_attach(&dev->dev); | 350 | retval = device_attach(&dev->dev); |
| 349 | if (retval < 0 && retval != -EPROBE_DEFER) | 351 | if (retval < 0 && retval != -EPROBE_DEFER) |
| 350 | pci_warn(dev, "device attach failed (%d)\n", retval); | 352 | pci_warn(dev, "device attach failed (%d)\n", retval); |
| @@ -179,7 +179,6 @@ config PCI_MVEBU · 178 unmodified lines | |||
| 179 | depends on MVEBU_MBUS | 179 | depends on MVEBU_MBUS |
| 180 | depends on ARM | 180 | depends on ARM |
| 181 | depends on OF | 181 | depends on OF |
| 182 | depends on BROKEN | ||
| 183 | select PCI_BRIDGE_EMUL | 182 | select PCI_BRIDGE_EMUL |
| 184 | help | 183 | help |
| 185 | Add support for Marvell EBU PCIe controller. This PCIe controller | 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 | if (ret) | 485 | if (ret) |
| 486 | goto err_remove_edma; | 486 | goto err_remove_edma; |
| 487 | 487 | ||
| 488 | if (dw_pcie_link_up(pci)) { | 488 | if (!dw_pcie_link_up(pci)) { |
| 489 | dw_pcie_print_link_status(pci); | ||
| 490 | } else { | ||
| 491 | ret = dw_pcie_start_link(pci); | 489 | ret = dw_pcie_start_link(pci); |
| 492 | if (ret) | 490 | if (ret) |
| 493 | goto err_remove_edma; | 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 | bridge->sysdata = pp; | 497 | bridge->sysdata = pp; |
| 503 | 498 | ||
| 504 | ret = pci_host_probe(bridge); | 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 | dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0); | 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 | int dw_pcie_wait_for_link(struct dw_pcie *pci) | 647 | int dw_pcie_wait_for_link(struct dw_pcie *pci) |
| 660 | { | 648 | { |
| 649 | u32 offset, val; | ||
| 661 | int retries; | 650 | int retries; |
| 662 | 651 | ||
| 663 | /* Check if the link is up or not */ | 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 | return -ETIMEDOUT; | 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 | return 0; | 672 | return 0; |
| 679 | } | 673 | } |
| @@ -429,7 +429,6 @@ void dw_pcie_setup(struct dw_pcie *pci); · 428 unmodified lines | |||
| 429 | void dw_pcie_iatu_detect(struct dw_pcie *pci); | 429 | void dw_pcie_iatu_detect(struct dw_pcie *pci); |
| 430 | int dw_pcie_edma_detect(struct dw_pcie *pci); | 430 | int dw_pcie_edma_detect(struct dw_pcie *pci); |
| 431 | void dw_pcie_edma_remove(struct dw_pcie *pci); | 431 | void dw_pcie_edma_remove(struct dw_pcie *pci); |
| 432 | void dw_pcie_print_link_status(struct dw_pcie *pci); | ||
| 433 | 432 | ||
| 434 | static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val) | 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 | acpiphp_native_scan_bridge(dev); | 498 | acpiphp_native_scan_bridge(dev); |
| 499 | } | 499 | } |
| 500 | } else { | 500 | } else { |
| 501 | LIST_HEAD(add_list); | ||
| 501 | int max, pass; | 502 | int max, pass; |
| 502 | 503 | ||
| 503 | acpiphp_rescan_slot(slot); | 504 | acpiphp_rescan_slot(slot); |
| @@ -511,10 +512,15 @@ static void enable_slot(struct acpiphp_slot *slot, bool bridge) · 7 unmodified lines | |||
| 511 | if (pass && dev->subordinate) { | 512 | if (pass && dev->subordinate) { |
| 512 | check_hotplug_bridge(slot, dev); | 513 | check_hotplug_bridge(slot, dev); |
| 513 | pcibios_resource_survey_bus(dev->subordinate); | 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 | acpiphp_sanitize_bus(bus); | 526 | acpiphp_sanitize_bus(bus); |
| @@ -34,11 +34,6 @@ int pci_set_of_node(struct pci_dev *dev) · 33 unmodified lines | |||
| 34 | if (!node) | 34 | if (!node) |
| 35 | return 0; | 35 | return 0; |
| 36 | 36 | ||
| 37 | if (!of_device_is_available(node)) { | ||
| 38 | of_node_put(node); | ||
| 39 | return -ENODEV; | ||
| 40 | } | ||
| 41 | |||
| 42 | device_set_node(&dev->dev, of_fwnode_handle(node)); | 37 | device_set_node(&dev->dev, of_fwnode_handle(node)); |
| 43 | return 0; | 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 | int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev) | 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 | int src; | 181 | int src; |
| 181 | 182 | ||
| 182 | mode = amd_pmf_get_pprof_modes(dev); | 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 | node = dev_to_node(&_pci_dev->dev); | 336 | node = dev_to_node(&_pci_dev->dev); |
| 337 | if (node == NUMA_NO_NODE) { | 337 | if (node == NUMA_NO_NODE) { |
| 338 | pr_info("Fail to get numa node for CPU:%d bus:%d dev:%d fn:%d\n", | 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); | 339 | cpu, bus_no, dev, fn); |
| 340 | continue; | 340 | continue; |
| 341 | } | 341 | } |
| 342 | 342 | ||
| @@ -24,6 +24,10 @@ static bool ec_trigger __read_mostly; · 23 unmodified lines | |||
| 24 | module_param(ec_trigger, bool, 0444); | 24 | module_param(ec_trigger, bool, 0444); |
| 25 | MODULE_PARM_DESC(ec_trigger, "Enable EC triggering work-around to force emitting tablet mode events"); | 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 | static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = { | 31 | static const struct dmi_system_id ec_trigger_quirk_dmi_table[] = { |
| 28 | { | 32 | { |
| 29 | /* Lenovo Yoga 7 14ARB7 */ | 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 | struct lenovo_ymc_private { | 56 | struct lenovo_ymc_private { |
| 39 | struct input_dev *input_dev; | 57 | struct input_dev *input_dev; |
| 40 | struct acpi_device *ec_acpi_dev; | 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 | struct input_dev *input_dev; | 129 | struct input_dev *input_dev; |
| 112 | int err; | 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 | ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table); | 139 | ec_trigger |= dmi_check_system(ec_trigger_quirk_dmi_table); |
| 115 | 140 | ||
| 116 | priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL); | 141 | priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL); |
| @@ -62,10 +62,6 @@ · 61 unmodified lines | |||
| 62 | #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 | 62 | #define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 |
| 63 | #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a | 63 | #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a |
| 64 | #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b | 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 | #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 | 65 | #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 |
| 70 | #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 | 66 | #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 |
| 71 | #define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET 0x42 | 67 | #define MLXPLAT_CPLD_LPC_REG_AGGRCO_OFFSET 0x42 |
| @@ -126,6 +122,10 @@ · 54 unmodified lines | |||
| 126 | #define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa | 122 | #define MLXPLAT_CPLD_LPC_REG_LC_SD_EVENT_OFFSET 0xaa |
| 127 | #define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab | 123 | #define MLXPLAT_CPLD_LPC_REG_LC_SD_MASK_OFFSET 0xab |
| 128 | #define MLXPLAT_CPLD_LPC_REG_LC_PWR_ON 0xb2 | 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 | #define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2 | 129 | #define MLXPLAT_CPLD_LPC_REG_GP4_RO_OFFSET 0xc2 |
| 130 | #define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3 | 130 | #define MLXPLAT_CPLD_LPC_REG_SPI_CHNL_SELECT 0xc3 |
| 131 | #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7 | 131 | #define MLXPLAT_CPLD_LPC_REG_WD_CLEAR_OFFSET 0xc7 |
| @@ -222,7 +222,7 @@ · 90 unmodified lines | |||
| 222 | MLXPLAT_CPLD_AGGR_MASK_LC_SDWN) | 222 | MLXPLAT_CPLD_AGGR_MASK_LC_SDWN) |
| 223 | #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1 | 223 | #define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1 |
| 224 | #define MLXPLAT_CPLD_LOW_AGGR_MASK_ASIC2 BIT(2) | 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 | #define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6) | 226 | #define MLXPLAT_CPLD_LOW_AGGR_MASK_I2C BIT(6) |
| 227 | #define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0) | 227 | #define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0) |
| 228 | #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) | 228 | #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) |
| @@ -237,7 +237,7 @@ · 8 unmodified lines | |||
| 237 | #define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0) | 237 | #define MLXPLAT_CPLD_GWP_MASK GENMASK(0, 0) |
| 238 | #define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0) | 238 | #define MLXPLAT_CPLD_EROT_MASK GENMASK(1, 0) |
| 239 | #define MLXPLAT_CPLD_PWR_BUTTON_MASK BIT(0) | 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 | #define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3) | 241 | #define MLXPLAT_CPLD_THERMAL1_PDB_MASK BIT(3) |
| 242 | #define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4) | 242 | #define MLXPLAT_CPLD_THERMAL2_PDB_MASK BIT(4) |
| 243 | #define MLXPLAT_CPLD_INTRUSION_MASK BIT(6) | 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 | u8 action) | 2356 | u8 action) |
| 2357 | { | 2357 | { |
| 2358 | dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button"); | 2358 | dev_info(&mlxplat_dev->dev, "System shutdown due to short press of power button"); |
| 2359 | kernel_halt(); | 2359 | kernel_power_off(); |
| 2360 | return 0; | 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 | .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET, | 2475 | .reg = MLXPLAT_CPLD_LPC_REG_PWRB_OFFSET, |
| 2476 | .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK, | 2476 | .mask = MLXPLAT_CPLD_PWR_BUTTON_MASK, |
| 2477 | .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data), | 2477 | .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_pwr_events_items_data), |
| 2478 | .inversed = 0, | 2478 | .inversed = 1, |
| 2479 | .health = false, | 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 | .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, | 2484 | .reg = MLXPLAT_CPLD_LPC_REG_BRD_OFFSET, |
| 2485 | .mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK, | 2485 | .mask = MLXPLAT_CPLD_L1_CHA_HEALTH_MASK, |
| 2486 | .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data), | 2486 | .count = ARRAY_SIZE(mlxplat_mlxcpld_l1_switch_health_events_items_data), |
| 2487 | .inversed = 0, | 2487 | .inversed = 1, |
| 2488 | .health = false, | 2488 | .health = false, |
| 2489 | .ind = 8, | 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 | .label = "latch_reset", | 3678 | .label = "latch_reset", |
| 3679 | .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, | 3679 | .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, |
| 3680 | .mask = GENMASK(7, 0) & ~BIT(5), | 3680 | .mask = GENMASK(7, 0) & ~BIT(6), |
| 3681 | .mode = 0200, | 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 | if (priv->pdev_mux[i]) | 6238 | if (priv->pdev_mux[i]) |
| 6239 | platform_device_unregister(priv->pdev_mux[i]); | 6239 | platform_device_unregister(priv->pdev_mux[i]); |
| 6240 | } | 6240 | } |
| 6241 | |||
| 6242 | mlxplat_post_exit(); | ||
| 6243 | } | 6241 | } |
| 6244 | 6242 | ||
| 6245 | static int mlxplat_i2c_main_complition_notify(void *handle, int id) | 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 | pm_power_off = NULL; | 6367 | pm_power_off = NULL; |
| 6370 | mlxplat_pre_exit(priv); | 6368 | mlxplat_pre_exit(priv); |
| 6371 | mlxplat_i2c_main_exit(priv); | 6369 | mlxplat_i2c_main_exit(priv); |
| 6370 | mlxplat_post_exit(); | ||
| 6372 | } | 6371 | } |
| 6373 | module_exit(mlxplat_exit); | 6372 | module_exit(mlxplat_exit); |
| 6374 | 6373 | ||
| @@ -27,15 +27,15 @@ · 26 unmodified lines | |||
| 27 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
| 28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
| 29 | 29 | ||
| 30 | static const char *const SM_ECO_NAME = "eco"; | 30 | #define SM_ECO_NAME "eco" |
| 31 | static const char *const SM_COMFORT_NAME = "comfort"; | 31 | #define SM_COMFORT_NAME "comfort" |
| 32 | static const char *const SM_SPORT_NAME = "sport"; | 32 | #define SM_SPORT_NAME "sport" |
| 33 | static const char *const SM_TURBO_NAME = "turbo"; | 33 | #define SM_TURBO_NAME "turbo" |
| 34 | 34 | ||
| 35 | static const char *const FM_AUTO_NAME = "auto"; | 35 | #define FM_AUTO_NAME "auto" |
| 36 | static const char *const FM_SILENT_NAME = "silent"; | 36 | #define FM_SILENT_NAME "silent" |
| 37 | static const char *const FM_BASIC_NAME = "basic"; | 37 | #define FM_BASIC_NAME "basic" |
| 38 | static const char *const FM_ADVANCED_NAME = "advanced"; | 38 | #define FM_ADVANCED_NAME "advanced" |
| 39 | 39 | ||
| 40 | static const char * const ALLOWED_FW_0[] __initconst = { | 40 | static const char * const ALLOWED_FW_0[] __initconst = { |
| 41 | "14C1EMS1.012", | 41 | "14C1EMS1.012", |
| @@ -329,6 +329,19 @@ static const struct smi_node cs35l41_hda = { · 328 unmodified lines | |||
| 329 | .bus_type = SMI_AUTO_DETECT, | 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 | * Note new device-ids must also be added to ignore_serial_bus_ids in | 346 | * Note new device-ids must also be added to ignore_serial_bus_ids in |
| 334 | * drivers/acpi/scan.c: acpi_device_enumeration_by_parent(). | 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 | { "BSG1160", (unsigned long)&bsg1160_data }, | 350 | { "BSG1160", (unsigned long)&bsg1160_data }, |
| 338 | { "BSG2150", (unsigned long)&bsg2150_data }, | 351 | { "BSG2150", (unsigned long)&bsg2150_data }, |
| 339 | { "CSC3551", (unsigned long)&cs35l41_hda }, | 352 | { "CSC3551", (unsigned long)&cs35l41_hda }, |
| 353 | { "CSC3556", (unsigned long)&cs35l56_hda }, | ||
| 340 | { "INT3515", (unsigned long)&int3515_data }, | 354 | { "INT3515", (unsigned long)&int3515_data }, |
| 341 | /* Non-conforming _HID for Cirrus Logic already released */ | 355 | /* Non-conforming _HID for Cirrus Logic already released */ |
| 342 | { "CLSA0100", (unsigned long)&cs35l41_hda }, | 356 | { "CLSA0100", (unsigned long)&cs35l41_hda }, |
| @@ -818,7 +818,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd, · 817 unmodified lines | |||
| 818 | return -EINVAL; | 818 | return -EINVAL; |
| 819 | 819 | ||
| 820 | ra.reg = rd->regs[rpi->id]; | 820 | ra.reg = rd->regs[rpi->id]; |
| 821 | if (!ra.reg) | 821 | if (!ra.reg.val) |
| 822 | return -EINVAL; | 822 | return -EINVAL; |
| 823 | 823 | ||
| 824 | /* non-hardware data are collected by the polling thread */ | 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 | ra.mask = rpi->mask; | 830 | ra.mask = rpi->mask; |
| 831 | 831 | ||
| 832 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { | 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 | return -EIO; | 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 | ra.mask = ~0; | 920 | ra.mask = ~0; |
| 921 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { | 921 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { |
| 922 | pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n", | 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 | return -ENODEV; | 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 | ra.mask = ~0; | 948 | ra.mask = ~0; |
| 949 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { | 949 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { |
| 950 | pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n", | 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 | return -ENODEV; | 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 | ra.mask = ~0; | 1135 | ra.mask = ~0; |
| 1136 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { | 1136 | if (rd->rp->priv->read_raw(get_rid(rd->rp), &ra)) { |
| 1137 | pr_err("Failed to read power unit REG 0x%llx on %s:%s, exit.\n", | 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 | return -ENODEV; | 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 | struct rapl_defaults *defaults = get_defaults(rd->rp); | 1411 | struct rapl_defaults *defaults = get_defaults(rd->rp); |
| 1412 | int ret; | 1412 | int ret; |
| 1413 | 1413 | ||
| 1414 | if (!rd->regs[RAPL_DOMAIN_REG_UNIT]) { | 1414 | if (!rd->regs[RAPL_DOMAIN_REG_UNIT].val) { |
| 1415 | if (!rd->rp->priv->reg_unit) { | 1415 | if (!rd->rp->priv->reg_unit.val) { |
| 1416 | pr_err("No valid Unit register found\n"); | 1416 | pr_err("No valid Unit register found\n"); |
| 1417 | return -ENODEV; | 1417 | return -ENODEV; |
| 1418 | } | 1418 | } |
| @@ -34,28 +34,32 @@ static struct rapl_if_priv *rapl_msr_priv; · 33 unmodified lines | |||
| 34 | 34 | ||
| 35 | static struct rapl_if_priv rapl_msr_priv_intel = { | 35 | static struct rapl_if_priv rapl_msr_priv_intel = { |
| 36 | .type = RAPL_IF_MSR, | 36 | .type = RAPL_IF_MSR, |
| 37 | .reg_unit = MSR_RAPL_POWER_UNIT, | 37 | .reg_unit.msr = MSR_RAPL_POWER_UNIT, |
| 38 | .regs[RAPL_DOMAIN_PACKAGE] = { | 38 | .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PKG_POWER_LIMIT, |
| 39 | MSR_PKG_POWER_LIMIT, MSR_PKG_ENERGY_STATUS, MSR_PKG_PERF_STATUS, 0, MSR_PKG_POWER_INFO }, | 39 | .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr = MSR_PKG_ENERGY_STATUS, |
| 40 | .regs[RAPL_DOMAIN_PP0] = { | 40 | .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PERF].msr = MSR_PKG_PERF_STATUS, |
| 41 | MSR_PP0_POWER_LIMIT, MSR_PP0_ENERGY_STATUS, 0, MSR_PP0_POLICY, 0 }, | 41 | .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_INFO].msr = MSR_PKG_POWER_INFO, |
| 42 | .regs[RAPL_DOMAIN_PP1] = { | 42 | .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PP0_POWER_LIMIT, |
| 43 | MSR_PP1_POWER_LIMIT, MSR_PP1_ENERGY_STATUS, 0, MSR_PP1_POLICY, 0 }, | 43 | .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr = MSR_PP0_ENERGY_STATUS, |
| 44 | .regs[RAPL_DOMAIN_DRAM] = { | 44 | .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_POLICY].msr = MSR_PP0_POLICY, |
| 45 | MSR_DRAM_POWER_LIMIT, MSR_DRAM_ENERGY_STATUS, MSR_DRAM_PERF_STATUS, 0, MSR_DRAM_POWER_INFO }, | 45 | .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_LIMIT].msr = MSR_PP1_POWER_LIMIT, |
| 46 | .regs[RAPL_DOMAIN_PLATFORM] = { | 46 | .regs[RAPL_DOMAIN_PP1][RAPL_DOMAIN_REG_STATUS].msr = MSR_PP1_ENERGY_STATUS, |
| 47 | MSR_PLATFORM_POWER_LIMIT, MSR_PLATFORM_ENERGY_STATUS, 0, 0, 0}, | 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 | .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2), | 54 | .limits[RAPL_DOMAIN_PACKAGE] = BIT(POWER_LIMIT2), |
| 49 | .limits[RAPL_DOMAIN_PLATFORM] = BIT(POWER_LIMIT2), | 55 | .limits[RAPL_DOMAIN_PLATFORM] = BIT(POWER_LIMIT2), |
| 50 | }; | 56 | }; |
| 51 | 57 | ||
| 52 | static struct rapl_if_priv rapl_msr_priv_amd = { | 58 | static struct rapl_if_priv rapl_msr_priv_amd = { |
| 53 | .type = RAPL_IF_MSR, | 59 | .type = RAPL_IF_MSR, |
| 54 | .reg_unit = MSR_AMD_RAPL_POWER_UNIT, | 60 | .reg_unit.msr = MSR_AMD_RAPL_POWER_UNIT, |
| 55 | .regs[RAPL_DOMAIN_PACKAGE] = { | 61 | .regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_STATUS].msr = MSR_AMD_PKG_ENERGY_STATUS, |
| 56 | 0, MSR_AMD_PKG_ENERGY_STATUS, 0, 0, 0 }, | 62 | .regs[RAPL_DOMAIN_PP0][RAPL_DOMAIN_REG_STATUS].msr = MSR_AMD_CORE_ENERGY_STATUS, |
| 57 | .regs[RAPL_DOMAIN_PP0] = { | ||
| 58 | 0, MSR_AMD_CORE_ENERGY_STATUS, 0, 0, 0 }, | ||
| 59 | }; | 63 | }; |
| 60 | 64 | ||
| 61 | /* Handles CPU hotplug on multi-socket systems. | 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 | static int rapl_msr_read_raw(int cpu, struct reg_action *ra) | 104 | static int rapl_msr_read_raw(int cpu, struct reg_action *ra) |
| 101 | { | 105 | { |
| 102 | u32 msr = (u32)ra->reg; | 106 | if (rdmsrl_safe_on_cpu(cpu, ra->reg.msr, &ra->value)) { |
| 103 | 107 | pr_debug("failed to read msr 0x%x on cpu %d\n", ra->reg.msr, cpu); | |
| 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 | return -EIO; | 108 | return -EIO; |
| 107 | } | 109 | } |
| 108 | ra->value &= ra->mask; | 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 | static void rapl_msr_update_func(void *info) | 114 | static void rapl_msr_update_func(void *info) |
| 113 | { | 115 | { |
| 114 | struct reg_action *ra = info; | 116 | struct reg_action *ra = info; |
| 115 | u32 msr = (u32)ra->reg; | ||
| 116 | u64 val; | 117 | u64 val; |
| 117 | 118 | ||
| 118 | ra->err = rdmsrl_safe(msr, &val); | 119 | ra->err = rdmsrl_safe(ra->reg.msr, &val); |
| 119 | if (ra->err) | 120 | if (ra->err) |
| 120 | return; | 121 | return; |
| 121 | 122 | ||
| 122 | val &= ~ra->mask; | 123 | val &= ~ra->mask; |
| 123 | val |= ra->value; | 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 | static int rapl_msr_write_raw(int cpu, struct reg_action *ra) | 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 | if (id) { | 173 | if (id) { |
| 173 | rapl_msr_priv->limits[RAPL_DOMAIN_PACKAGE] |= BIT(POWER_LIMIT4); | 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 | MSR_VR_CURRENT_CONFIG; | 176 | MSR_VR_CURRENT_CONFIG; |
| 176 | pr_info("PL4 support detected.\n"); | 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 | static int tpmi_rapl_read_raw(int id, struct reg_action *ra) | 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 | return -EINVAL; | 63 | return -EINVAL; |
| 64 | 64 | ||
| 65 | ra->value = readq((void __iomem *)ra->reg); | 65 | ra->value = readq(ra->reg.mmio); |
| 66 | 66 | ||
| 67 | ra->value &= ra->mask; | 67 | ra->value &= ra->mask; |
| 68 | return 0; | 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 | u64 val; | 73 | u64 val; |
| 74 | 74 | ||
| 75 | if (!ra->reg) | 75 | if (!ra->reg.mmio) |
| 76 | return -EINVAL; | 76 | return -EINVAL; |
| 77 | 77 | ||
| 78 | val = readq((void __iomem *)ra->reg); | 78 | val = readq(ra->reg.mmio); |
| 79 | 79 | ||
| 80 | val &= ~ra->mask; | 80 | val &= ~ra->mask; |
| 81 | val |= ra->value; | 81 | val |= ra->value; |
| 82 | 82 | ||
| 83 | writeq(val, (void __iomem *)ra->reg); | 83 | writeq(val, ra->reg.mmio); |
| 84 | return 0; | 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 | enum tpmi_rapl_register reg_index; | 138 | enum tpmi_rapl_register reg_index; |
| 139 | enum rapl_domain_reg_id reg_id; | 139 | enum rapl_domain_reg_id reg_id; |
| 140 | int tpmi_domain_size, tpmi_domain_flags; | 140 | int tpmi_domain_size, tpmi_domain_flags; |
| 141 | u64 *tpmi_rapl_regs = trp->base + offset; | 141 | u64 tpmi_domain_header = readq(trp->base + offset); |
| 142 | u64 tpmi_domain_header = readq((void __iomem *)tpmi_rapl_regs); | ||
| 143 | 142 | ||
| 144 | /* Domain Parent bits are ignored for now */ | 143 | /* Domain Parent bits are ignored for now */ |
| 145 | tpmi_domain_version = tpmi_domain_header & 0xff; | 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 | return -EINVAL; | 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 | pr_warn(FW_BUG "Duplicate Domain type %d\n", tpmi_domain_type); | 183 | pr_warn(FW_BUG "Duplicate Domain type %d\n", tpmi_domain_type); |
| 185 | return -EINVAL; | 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 | default: | 217 | default: |
| 219 | continue; | 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 | return 0; | 223 | return 0; |
| @@ -716,7 +716,6 @@ struct qeth_card_info { · 715 unmodified lines | |||
| 716 | u16 chid; | 716 | u16 chid; |
| 717 | u8 ids_valid:1; /* cssid,iid,chid */ | 717 | u8 ids_valid:1; /* cssid,iid,chid */ |
| 718 | u8 dev_addr_is_registered:1; | 718 | u8 dev_addr_is_registered:1; |
| 719 | u8 open_when_online:1; | ||
| 720 | u8 promisc_mode:1; | 719 | u8 promisc_mode:1; |
| 721 | u8 use_v1_blkt:1; | 720 | u8 use_v1_blkt:1; |
| 722 | u8 is_vm_nic:1; | 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 | qeth_clear_ipacmd_list(card); | 5373 | qeth_clear_ipacmd_list(card); |
| 5374 | 5374 | ||
| 5375 | rtnl_lock(); | 5375 | rtnl_lock(); |
| 5376 | card->info.open_when_online = card->dev->flags & IFF_UP; | ||
| 5377 | dev_close(card->dev); | ||
| 5378 | netif_device_detach(card->dev); | 5376 | netif_device_detach(card->dev); |
| 5379 | netif_carrier_off(card->dev); | 5377 | netif_carrier_off(card->dev); |
| 5380 | rtnl_unlock(); | 5378 | rtnl_unlock(); |
| @@ -2388,9 +2388,12 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok) · 2387 unmodified lines | |||
| 2388 | qeth_enable_hw_features(dev); | 2388 | qeth_enable_hw_features(dev); |
| 2389 | qeth_l2_enable_brport_features(card); | 2389 | qeth_l2_enable_brport_features(card); |
| 2390 | 2390 | ||
| 2391 | if (card->info.open_when_online) { | 2391 | if (netif_running(dev)) { |
| 2392 | card->info.open_when_online = 0; | 2392 | local_bh_disable(); |
| 2393 | dev_open(dev, NULL); | 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 | rtnl_unlock(); | 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 | netif_device_attach(dev); | 2018 | netif_device_attach(dev); |
| 2019 | qeth_enable_hw_features(dev); | 2019 | qeth_enable_hw_features(dev); |
| 2020 | 2020 | ||
| 2021 | if (card->info.open_when_online) { | 2021 | if (netif_running(dev)) { |
| 2022 | card->info.open_when_online = 0; | 2022 | local_bh_disable(); |
| 2023 | dev_open(dev, NULL); | 2023 | napi_schedule(&card->napi); |
| 2024 | /* kick-start the NAPI softirq: */ | ||
| 2025 | local_bh_enable(); | ||
| 2024 | } | 2026 | } |
| 2025 | rtnl_unlock(); | 2027 | rtnl_unlock(); |
| 2026 | } | 2028 | } |
| @@ -534,8 +534,7 @@ static void zfcp_fc_adisc_handler(void *data) · 533 unmodified lines | |||
| 534 | 534 | ||
| 535 | /* re-init to undo drop from zfcp_fc_adisc() */ | 535 | /* re-init to undo drop from zfcp_fc_adisc() */ |
| 536 | port->d_id = ntoh24(adisc_resp->adisc_port_id); | 536 | port->d_id = ntoh24(adisc_resp->adisc_port_id); |
| 537 | /* port is good, unblock rport without going through erp */ | 537 | /* port is still good, nothing to do */ |
| 538 | zfcp_scsi_schedule_rport_register(port); | ||
| 539 | out: | 538 | out: |
| 540 | atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status); | 539 | atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status); |
| 541 | put_device(&port->dev); | 540 | put_device(&port->dev); |
| @@ -595,9 +594,6 @@ void zfcp_fc_link_test_work(struct work_struct *work) · 53 unmodified lines | |||
| 595 | int retval; | 594 | int retval; |
| 596 | 595 | ||
| 597 | set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */ | 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 | /* only issue one test command at one time per port */ | 598 | /* only issue one test command at one time per port */ |
| 603 | if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST) | 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 | 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))); | 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 | #endif | 1599 | #endif |
| 1600 | resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch; | 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 | dsp <= to32bit(&slot->pSG[NCR_700_SG_SEGMENTS].ins)) { | 1602 | dsp <= to32bit(&slot->pSG[NCR_700_SG_SEGMENTS].ins)) { |
| 1603 | int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff; | 1603 | int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff; |
| 1604 | int SGcount = (dsp - to32bit(&slot->pSG[0].ins))/sizeof(struct NCR_700_SG_List); | 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 | #define DRV_NAME "fnic" | 28 | #define DRV_NAME "fnic" |
| 29 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" | 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 | #define PFX DRV_NAME ": " | 31 | #define PFX DRV_NAME ": " |
| 32 | #define DFX DRV_NAME "%d: " | 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 | bool new_sc) | 2139 | bool new_sc) |
| 2140 | 2140 | ||
| 2141 | { | 2141 | { |
| 2142 | int ret = SUCCESS; | 2142 | int ret = 0; |
| 2143 | struct fnic_pending_aborts_iter_data iter_data = { | 2143 | struct fnic_pending_aborts_iter_data iter_data = { |
| 2144 | .fnic = fnic, | 2144 | .fnic = fnic, |
| 2145 | .lun_dev = lr_sc->device, | 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 | /* walk again to check, if IOs are still pending in fw */ | 2160 | /* walk again to check, if IOs are still pending in fw */ |
| 2161 | if (fnic_is_abts_pending(fnic, lr_sc)) | 2161 | if (fnic_is_abts_pending(fnic, lr_sc)) |
| 2162 | ret = FAILED; | 2162 | ret = 1; |
| 2163 | 2163 | ||
| 2164 | clean_pending_aborts_end: | 2164 | clean_pending_aborts_end: |
| 2165 | FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, | ||
| 2166 | "%s: exit status: %d\n", __func__, ret); | ||
| 2165 | return ret; | 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 | * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread | 113 | * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread |
| 116 | * @phba: The Hba for which this call is being executed. | 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 | sgpe = scsi_prot_sglist(sc); | 977 | sgpe = scsi_prot_sglist(sc); |
| 980 | lba = scsi_prot_ref_tag(sc); | 978 | lba = scsi_prot_ref_tag(sc); |
| 981 | if (lba == LPFC_INVALID_REFTAG) | ||
| 982 | return 0; | ||
| 983 | 979 | ||
| 984 | /* First check if we need to match the LBA */ | 980 | /* First check if we need to match the LBA */ |
| 985 | if (phba->lpfc_injerr_lba != LPFC_INJERR_LBA_OFF) { | 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 | /* extract some info from the scsi command for pde*/ | 1557 | /* extract some info from the scsi command for pde*/ |
| 1562 | reftag = scsi_prot_ref_tag(sc); | 1558 | reftag = scsi_prot_ref_tag(sc); |
| 1563 | if (reftag == LPFC_INVALID_REFTAG) | ||
| 1564 | goto out; | ||
| 1565 | 1559 | ||
| 1566 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS | 1560 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
| 1567 | rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1); | 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 | /* extract some info from the scsi command */ | 1717 | /* extract some info from the scsi command */ |
| 1724 | blksize = scsi_prot_interval(sc); | 1718 | blksize = scsi_prot_interval(sc); |
| 1725 | reftag = scsi_prot_ref_tag(sc); | 1719 | reftag = scsi_prot_ref_tag(sc); |
| 1726 | if (reftag == LPFC_INVALID_REFTAG) | ||
| 1727 | goto out; | ||
| 1728 | 1720 | ||
| 1729 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS | 1721 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
| 1730 | rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1); | 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 | /* extract some info from the scsi command for pde*/ | 1946 | /* extract some info from the scsi command for pde*/ |
| 1955 | reftag = scsi_prot_ref_tag(sc); | 1947 | reftag = scsi_prot_ref_tag(sc); |
| 1956 | if (reftag == LPFC_INVALID_REFTAG) | ||
| 1957 | goto out; | ||
| 1958 | 1948 | ||
| 1959 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS | 1949 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
| 1960 | rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1); | 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 | /* extract some info from the scsi command */ | 2144 | /* extract some info from the scsi command */ |
| 2155 | blksize = scsi_prot_interval(sc); | 2145 | blksize = scsi_prot_interval(sc); |
| 2156 | reftag = scsi_prot_ref_tag(sc); | 2146 | reftag = scsi_prot_ref_tag(sc); |
| 2157 | if (reftag == LPFC_INVALID_REFTAG) | ||
| 2158 | goto out; | ||
| 2159 | 2147 | ||
| 2160 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS | 2148 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
| 2161 | rc = lpfc_bg_err_inject(phba, sc, &reftag, NULL, 1); | 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 | src = (struct scsi_dif_tuple *)sg_virt(sgpe); | 2735 | src = (struct scsi_dif_tuple *)sg_virt(sgpe); |
| 2748 | start_ref_tag = scsi_prot_ref_tag(cmd); | 2736 | start_ref_tag = scsi_prot_ref_tag(cmd); |
| 2749 | if (start_ref_tag == LPFC_INVALID_REFTAG) | ||
| 2750 | goto out; | ||
| 2751 | start_app_tag = src->app_tag; | 2737 | start_app_tag = src->app_tag; |
| 2752 | len = sgpe->length; | 2738 | len = sgpe->length; |
| 2753 | while (src && protsegcnt) { | 2739 | while (src && protsegcnt) { |
| @@ -3493,11 +3479,11 @@ err: · 739 unmodified lines | |||
| 3493 | scsi_cmnd->sc_data_direction); | 3479 | scsi_cmnd->sc_data_direction); |
| 3494 | 3480 | ||
| 3495 | lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, | 3481 | lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, |
| 3496 | "9084 Cannot setup S/G List for HBA" | 3482 | "9084 Cannot setup S/G List for HBA " |
| 3497 | "IO segs %d/%d SGL %d SCSI %d: %d %d\n", | 3483 | "IO segs %d/%d SGL %d SCSI %d: %d %d %d\n", |
| 3498 | lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt, | 3484 | lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt, |
| 3499 | phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt, | 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 | lpfc_cmd->seg_cnt = 0; | 3488 | lpfc_cmd->seg_cnt = 0; |
| 3503 | lpfc_cmd->prot_seg_cnt = 0; | 3489 | lpfc_cmd->prot_seg_cnt = 0; |
| @@ -1181,7 +1181,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, · 1180 unmodified lines | |||
| 1181 | pm80xx_set_thermal_config(pm8001_ha); | 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 | goto err_out_shost; | 1186 | goto err_out_shost; |
| 1186 | /* phy setting support for motherboard controller */ | 1187 | /* phy setting support for motherboard controller */ |
| 1187 | rc = pm8001_configure_phy_settings(pm8001_ha); | 1188 | rc = pm8001_configure_phy_settings(pm8001_ha); |
| @@ -31,6 +31,7 @@ static void qedf_remove(struct pci_dev *pdev); · 30 unmodified lines | |||
| 31 | static void qedf_shutdown(struct pci_dev *pdev); | 31 | static void qedf_shutdown(struct pci_dev *pdev); |
| 32 | static void qedf_schedule_recovery_handler(void *dev); | 32 | static void qedf_schedule_recovery_handler(void *dev); |
| 33 | static void qedf_recovery_handler(struct work_struct *work); | 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 | * Driver module parameters. | 37 | * Driver module parameters. |
| @@ -3271,6 +3272,7 @@ static struct pci_driver qedf_pci_driver = { · 3234 unmodified lines | |||
| 3271 | .probe = qedf_probe, | 3272 | .probe = qedf_probe, |
| 3272 | .remove = qedf_remove, | 3273 | .remove = qedf_remove, |
| 3273 | .shutdown = qedf_shutdown, | 3274 | .shutdown = qedf_shutdown, |
| 3275 | .suspend = qedf_suspend, | ||
| 3274 | }; | 3276 | }; |
| 3275 | 3277 | ||
| 3276 | static int __qedf_probe(struct pci_dev *pdev, int mode) | 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 | __qedf_remove(pdev, QEDF_MODE_NORMAL); | 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 | * Recovery handler code | 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 | static void qedi_recovery_handler(struct work_struct *work); | 69 | static void qedi_recovery_handler(struct work_struct *work); |
| 70 | static void qedi_schedule_hw_err_handler(void *dev, | 70 | static void qedi_schedule_hw_err_handler(void *dev, |
| 71 | enum qed_hw_err_type err_type); | 71 | enum qed_hw_err_type err_type); |
| 72 | static int qedi_suspend(struct pci_dev *pdev, pm_message_t state); | ||
| 72 | 73 | ||
| 73 | static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle) | 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 | struct qedi_percpu_s *p = this_cpu_ptr(&qedi_percpu); | 1977 | struct qedi_percpu_s *p = this_cpu_ptr(&qedi_percpu); |
| 1977 | struct qedi_work *work, *tmp; | 1978 | struct qedi_work *work, *tmp; |
| 1978 | struct task_struct *thread; | 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 | thread = p->iothread; | 1983 | thread = p->iothread; |
| 1982 | p->iothread = NULL; | 1984 | p->iothread = NULL; |
| 1983 | 1985 | ||
| @@ -1988,7 +1990,7 @@ static int qedi_cpu_offline(unsigned int cpu) · 4 unmodified lines | |||
| 1988 | kfree(work); | 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 | if (thread) | 1994 | if (thread) |
| 1993 | kthread_stop(thread); | 1995 | kthread_stop(thread); |
| 1994 | return 0; | 1996 | return 0; |
| @@ -2510,6 +2512,22 @@ static void qedi_shutdown(struct pci_dev *pdev) · 515 unmodified lines | |||
| 2510 | __qedi_remove(pdev, QEDI_MODE_SHUTDOWN); | 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 | static int __qedi_probe(struct pci_dev *pdev, int mode) | 2531 | static int __qedi_probe(struct pci_dev *pdev, int mode) |
| 2514 | { | 2532 | { |
| 2515 | struct qedi_ctx *qedi; | 2533 | struct qedi_ctx *qedi; |
| @@ -2868,6 +2886,7 @@ static struct pci_driver qedi_pci_driver = { · 352 unmodified lines | |||
| 2868 | .remove = qedi_remove, | 2886 | .remove = qedi_remove, |
| 2869 | .shutdown = qedi_shutdown, | 2887 | .shutdown = qedi_shutdown, |
| 2870 | .err_handler = &qedi_err_handler, | 2888 | .err_handler = &qedi_err_handler, |
| 2889 | .suspend = qedi_suspend, | ||
| 2871 | }; | 2890 | }; |
| 2872 | 2891 | ||
| 2873 | static int __init qedi_init(void) | 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 | return 0; | 248 | return 0; |
| 249 | 249 | ||
| 250 | err_out: | 250 | err_out: |
| 251 | put_device(&rc->dev); | ||
| 251 | list_del(&rc->node); | 252 | list_del(&rc->node); |
| 252 | rd->component_count--; | 253 | rd->component_count--; |
| 253 | put_device(component_dev); | 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 | size_t length, loff_t *ppos) | 406 | size_t length, loff_t *ppos) |
| 407 | { | 407 | { |
| 408 | int host, channel, id, lun; | 408 | int host, channel, id, lun; |
| 409 | char *buffer, *p; | 409 | char *buffer, *end, *p; |
| 410 | int err; | 410 | int err; |
| 411 | 411 | ||
| 412 | if (!buf || length > PAGE_SIZE) | 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 | goto out; | 421 | goto out; |
| 422 | 422 | ||
| 423 | err = -EINVAL; | 423 | err = -EINVAL; |
| 424 | if (length < PAGE_SIZE) | 424 | if (length < PAGE_SIZE) { |
| 425 | buffer[length] = '\0'; | 425 | end = buffer + length; |
| 426 | else if (buffer[PAGE_SIZE-1]) | 426 | *end = '\0'; |
| 427 | goto out; | 427 | } else { |
| 428 | end = buffer + PAGE_SIZE - 1; | ||
| 429 | if (*end) | ||
| 430 | goto out; | ||
| 431 | } | ||
| 428 | 432 | ||
| 429 | /* | 433 | /* |
| 430 | * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi | 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 | if (!strncmp("scsi add-single-device", buffer, 22)) { | 437 | if (!strncmp("scsi add-single-device", buffer, 22)) { |
| 434 | p = buffer + 23; | 438 | p = buffer + 23; |
| 435 | 439 | ||
| 436 | host = simple_strtoul(p, &p, 0); | 440 | host = (p < end) ? simple_strtoul(p, &p, 0) : 0; |
| 437 | channel = simple_strtoul(p + 1, &p, 0); | 441 | channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; |
| 438 | id = simple_strtoul(p + 1, &p, 0); | 442 | id = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; |
| 439 | lun = simple_strtoul(p + 1, &p, 0); | 443 | lun = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; |
| 440 | 444 | ||
| 441 | err = scsi_add_single_device(host, channel, id, lun); | 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 | } else if (!strncmp("scsi remove-single-device", buffer, 25)) { | 451 | } else if (!strncmp("scsi remove-single-device", buffer, 25)) { |
| 448 | p = buffer + 26; | 452 | p = buffer + 26; |
| 449 | 453 | ||
| 450 | host = simple_strtoul(p, &p, 0); | 454 | host = (p < end) ? simple_strtoul(p, &p, 0) : 0; |
| 451 | channel = simple_strtoul(p + 1, &p, 0); | 455 | channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; |
| 452 | id = simple_strtoul(p + 1, &p, 0); | 456 | id = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; |
| 453 | lun = simple_strtoul(p + 1, &p, 0); | 457 | lun = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0; |
| 454 | 458 | ||
| 455 | err = scsi_remove_single_device(host, channel, id, lun); | 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 | static int sd_resume(struct device *dev) | 3876 | static int sd_resume(struct device *dev) |
| 3877 | { | 3877 | { |
| 3878 | struct scsi_disk *sdkp = dev_get_drvdata(dev); | 3878 | struct scsi_disk *sdkp = dev_get_drvdata(dev); |
| 3879 | int ret; | 3879 | int ret = 0; |
| 3880 | 3880 | ||
| 3881 | if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ | 3881 | if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ |
| 3882 | return 0; | 3882 | return 0; |
| @@ -3884,8 +3884,11 @@ static int sd_resume(struct device *dev) · 1 unmodified line | |||
| 3884 | if (!sdkp->device->manage_start_stop) | 3884 | if (!sdkp->device->manage_start_stop) |
| 3885 | return 0; | 3885 | return 0; |
| 3886 | 3886 | ||
| 3887 | sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); | 3887 | if (!sdkp->device->no_start_on_resume) { |
| 3888 | ret = sd_start_stop_device(sdkp, 1); | 3888 | sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); |
| 3889 | ret = sd_start_stop_device(sdkp, 1); | ||
| 3890 | } | ||
| 3891 | |||
| 3889 | if (!ret) | 3892 | if (!ret) |
| 3890 | opal_unlock_from_suspend(sdkp->opal_dev); | 3893 | opal_unlock_from_suspend(sdkp->opal_dev); |
| 3891 | return ret; | 3894 | return ret; |
| @@ -303,6 +303,7 @@ snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid) · 302 unmodified lines | |||
| 303 | "Snic Tgt: device_add, with err = %d\n", | 303 | "Snic Tgt: device_add, with err = %d\n", |
| 304 | ret); | 304 | ret); |
| 305 | 305 | ||
| 306 | put_device(&tgt->dev); | ||
| 306 | put_device(&snic->shost->shost_gendev); | 307 | put_device(&snic->shost->shost_gendev); |
| 307 | spin_lock_irqsave(snic->shost->host_lock, flags); | 308 | spin_lock_irqsave(snic->shost->host_lock, flags); |
| 308 | list_del(&tgt->list); | 309 | list_del(&tgt->list); |
| @@ -366,6 +366,7 @@ static void storvsc_on_channel_callback(void *context); · 365 unmodified lines | |||
| 366 | #define STORVSC_FC_MAX_LUNS_PER_TARGET 255 | 366 | #define STORVSC_FC_MAX_LUNS_PER_TARGET 255 |
| 367 | #define STORVSC_FC_MAX_TARGETS 128 | 367 | #define STORVSC_FC_MAX_TARGETS 128 |
| 368 | #define STORVSC_FC_MAX_CHANNELS 8 | 368 | #define STORVSC_FC_MAX_CHANNELS 8 |
| 369 | #define STORVSC_FC_MAX_XFER_SIZE ((u32)(512 * 1024)) | ||
| 369 | 370 | ||
| 370 | #define STORVSC_IDE_MAX_LUNS_PER_TARGET 64 | 371 | #define STORVSC_IDE_MAX_LUNS_PER_TARGET 64 |
| 371 | #define STORVSC_IDE_MAX_TARGETS 1 | 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 | static enum scsi_timeout_action storvsc_eh_timed_out(struct scsi_cmnd *scmnd) | 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 | return SCSI_EH_RESET_TIMER; | 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 | * protecting it from any weird value. | 2003 | * protecting it from any weird value. |
| 2007 | */ | 2004 | */ |
| 2008 | max_xfer_bytes = round_down(stor_device->max_transfer_bytes, HV_HYP_PAGE_SIZE); | 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 | /* max_hw_sectors_kb */ | 2009 | /* max_hw_sectors_kb */ |
| 2010 | host->max_sectors = max_xfer_bytes >> 9; | 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 | clk_hsio_pll->hw.init = &init; | 164 | clk_hsio_pll->hw.init = &init; |
| 165 | 165 | ||
| 166 | hw = &clk_hsio_pll->hw; | 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 | if (ret) | 168 | if (ret) |
| 169 | return ret; | 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 | static int rapl_mmio_read_raw(int cpu, struct reg_action *ra) | 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 | return -EINVAL; | 61 | return -EINVAL; |
| 62 | 62 | ||
| 63 | ra->value = readq((void __iomem *)ra->reg); | 63 | ra->value = readq(ra->reg.mmio); |
| 64 | ra->value &= ra->mask; | 64 | ra->value &= ra->mask; |
| 65 | return 0; | 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 | u64 val; | 70 | u64 val; |
| 71 | 71 | ||
| 72 | if (!ra->reg) | 72 | if (!ra->reg.mmio) |
| 73 | return -EINVAL; | 73 | return -EINVAL; |
| 74 | 74 | ||
| 75 | val = readq((void __iomem *)ra->reg); | 75 | val = readq(ra->reg.mmio); |
| 76 | val &= ~ra->mask; | 76 | val &= ~ra->mask; |
| 77 | val |= ra->value; | 77 | val |= ra->value; |
| 78 | writeq(val, (void __iomem *)ra->reg); | 78 | writeq(val, ra->reg.mmio); |
| 79 | return 0; | 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 | for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) { | 92 | for (domain = RAPL_DOMAIN_PACKAGE; domain < RAPL_DOMAIN_MAX; domain++) { |
| 93 | for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++) | 93 | for (reg = RAPL_DOMAIN_REG_LIMIT; reg < RAPL_DOMAIN_REG_MAX; reg++) |
| 94 | if (rapl_regs->regs[domain][reg]) | 94 | if (rapl_regs->regs[domain][reg]) |
| 95 | rapl_mmio_priv.regs[domain][reg] = | 95 | rapl_mmio_priv.regs[domain][reg].mmio = |
| 96 | (u64)proc_priv->mmio_base + | 96 | proc_priv->mmio_base + |
| 97 | rapl_regs->regs[domain][reg]; | 97 | rapl_regs->regs[domain][reg]; |
| 98 | rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain]; | 98 | rapl_mmio_priv.limits[domain] = rapl_regs->limits[domain]; |
| 99 | } | 99 | } |
| 100 | rapl_mmio_priv.type = RAPL_IF_MMIO; | 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 | rapl_mmio_priv.read_raw = rapl_mmio_read_raw; | 103 | rapl_mmio_priv.read_raw = rapl_mmio_read_raw; |
| 104 | rapl_mmio_priv.write_raw = rapl_mmio_write_raw; | 104 | rapl_mmio_priv.write_raw = rapl_mmio_write_raw; |
| @@ -1964,6 +1964,8 @@ unlock: · 1963 unmodified lines | |||
| 1964 | 1964 | ||
| 1965 | pm_runtime_mark_last_busy(&tb->dev); | 1965 | pm_runtime_mark_last_busy(&tb->dev); |
| 1966 | pm_runtime_put_autosuspend(&tb->dev); | 1966 | pm_runtime_put_autosuspend(&tb->dev); |
| 1967 | |||
| 1968 | kfree(ev); | ||
| 1967 | } | 1969 | } |
| 1968 | 1970 | ||
| 1969 | static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port) | 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 | * uni-directional mode and we don't want to change it's TMU | 579 | * uni-directional mode and we don't want to change it's TMU |
| 580 | * mode. | 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 | tb_port_tmu_time_sync_disable(up); | 586 | tb_port_tmu_time_sync_disable(up); |
| 585 | ret = tb_port_tmu_time_sync_disable(down); | 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 | struct ufs_renesas_priv *priv; | 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 | if (!priv) | 363 | if (!priv) |
| 364 | return -ENOMEM; | 364 | return -ENOMEM; |
| 365 | ufshcd_set_variant(hba, priv); | 365 | ufshcd_set_variant(hba, priv); |
| @@ -42,6 +42,7 @@ struct usb_conn_info { · 41 unmodified lines | |||
| 42 | 42 | ||
| 43 | struct power_supply_desc desc; | 43 | struct power_supply_desc desc; |
| 44 | struct power_supply *charger; | 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 | dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n", | 87 | dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n", |
| 87 | usb_role_string(info->last_role), usb_role_string(role), id, vbus); | 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 | dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role)); | 91 | dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role)); |
| 91 | return; | 92 | return; |
| 92 | } | 93 | } |
| 93 | 94 | ||
| 95 | info->initial_detection = false; | ||
| 96 | |||
| 94 | if (info->last_role == USB_ROLE_HOST && info->vbus) | 97 | if (info->last_role == USB_ROLE_HOST && info->vbus) |
| 95 | regulator_disable(info->vbus); | 98 | regulator_disable(info->vbus); |
| 96 | 99 | ||
| @@ -258,6 +261,7 @@ static int usb_conn_probe(struct platform_device *pdev) · 161 unmodified lines | |||
| 258 | device_set_wakeup_capable(&pdev->dev, true); | 261 | device_set_wakeup_capable(&pdev->dev, true); |
| 259 | 262 | ||
| 260 | /* Perform initial detection */ | 263 | /* Perform initial detection */ |
| 264 | info->initial_detection = true; | ||
| 261 | usb_conn_queue_dwork(info, 0); | 265 | usb_conn_queue_dwork(info, 0); |
| 262 | 266 | ||
| 263 | return 0; | 267 | return 0; |
| @@ -4455,9 +4455,14 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) · 4454 unmodified lines | |||
| 4455 | u32 count; | 4455 | u32 count; |
| 4456 | 4456 | ||
| 4457 | if (pm_runtime_suspended(dwc->dev)) { | 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 | pm_runtime_get(dwc->dev); | 4464 | pm_runtime_get(dwc->dev); |
| 4459 | disable_irq_nosync(dwc->irq_gadget); | 4465 | disable_irq_nosync(dwc->irq_gadget); |
| 4460 | dwc->pending_events = true; | ||
| 4461 | return IRQ_HANDLED; | 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 | if (dwc->pending_events) { | 4724 | if (dwc->pending_events) { |
| 4720 | dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf); | 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 | dwc->pending_events = false; | 4728 | dwc->pending_events = false; |
| 4722 | enable_irq(dwc->irq_gadget); | 4729 | enable_irq(dwc->irq_gadget); |
| 4723 | } | 4730 | } |
| @@ -823,6 +823,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect); · 822 unmodified lines | |||
| 823 | * usb_gadget_activate() is called. For example, user mode components may | 823 | * usb_gadget_activate() is called. For example, user mode components may |
| 824 | * need to be activated before the system can talk to hosts. | 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 | * Returns zero on success, else negative errno. | 829 | * Returns zero on success, else negative errno. |
| 827 | */ | 830 | */ |
| 828 | int usb_gadget_deactivate(struct usb_gadget *gadget) | 831 | int usb_gadget_deactivate(struct usb_gadget *gadget) |
| @@ -861,6 +864,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate); · 32 unmodified lines | |||
| 861 | * This routine activates gadget which was previously deactivated with | 864 | * This routine activates gadget which was previously deactivated with |
| 862 | * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed. | 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 | * Returns zero on success, else negative errno. | 869 | * Returns zero on success, else negative errno. |
| 865 | */ | 870 | */ |
| 866 | int usb_gadget_activate(struct usb_gadget *gadget) | 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 | usb_gadget_disable_async_callbacks(udc); | 1644 | usb_gadget_disable_async_callbacks(udc); |
| 1640 | if (gadget->irq) | 1645 | if (gadget->irq) |
| 1641 | synchronize_irq(gadget->irq); | 1646 | synchronize_irq(gadget->irq); |
| 1647 | mutex_unlock(&udc->connect_lock); | ||
| 1648 | |||
| 1642 | udc->driver->unbind(gadget); | 1649 | udc->driver->unbind(gadget); |
| 1650 | |||
| 1651 | mutex_lock(&udc->connect_lock); | ||
| 1643 | usb_gadget_udc_stop_locked(udc); | 1652 | usb_gadget_udc_stop_locked(udc); |
| 1644 | mutex_unlock(&udc->connect_lock); | 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 | rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, | 318 | rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, |
| 319 | command, 0xc0, 0, 1, data, 2); | 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 | return rc; | 324 | return rc; |
| 324 | } | 325 | } |
| @@ -454,9 +455,14 @@ static int alauda_init_media(struct us_data *us) · 129 unmodified lines | |||
| 454 | static int alauda_check_media(struct us_data *us) | 455 | static int alauda_check_media(struct us_data *us) |
| 455 | { | 456 | { |
| 456 | struct alauda_info *info = (struct alauda_info *) us->extra; | 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 | /* Check for no media or door open */ | 467 | /* Check for no media or door open */ |
| 462 | if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10) | 468 | if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10) |
| @@ -60,6 +60,7 @@ struct dp_altmode { · 59 unmodified lines | |||
| 60 | 60 | ||
| 61 | enum dp_state state; | 61 | enum dp_state state; |
| 62 | bool hpd; | 62 | bool hpd; |
| 63 | bool pending_hpd; | ||
| 63 | 64 | ||
| 64 | struct mutex lock; /* device lock */ | 65 | struct mutex lock; /* device lock */ |
| 65 | struct work_struct work; | 66 | struct work_struct work; |
| @@ -144,8 +145,13 @@ static int dp_altmode_status_update(struct dp_altmode *dp) · 78 unmodified lines | |||
| 144 | dp->state = DP_STATE_EXIT; | 145 | dp->state = DP_STATE_EXIT; |
| 145 | } else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) { | 146 | } else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) { |
| 146 | ret = dp_altmode_configure(dp, con); | 147 | ret = dp_altmode_configure(dp, con); |
| 147 | if (!ret) | 148 | if (!ret) { |
| 148 | dp->state = DP_STATE_CONFIGURE; | 149 | dp->state = DP_STATE_CONFIGURE; |
| 150 | if (dp->hpd != hpd) { | ||
| 151 | dp->hpd = hpd; | ||
| 152 | dp->pending_hpd = true; | ||
| 153 | } | ||
| 154 | } | ||
| 149 | } else { | 155 | } else { |
| 150 | if (dp->hpd != hpd) { | 156 | if (dp->hpd != hpd) { |
| 151 | drm_connector_oob_hotplug_event(dp->connector_fwnode); | 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 | sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); | 168 | sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); |
| 163 | sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment"); | 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 | return dp_altmode_notify(dp); | 181 | return dp_altmode_notify(dp); |
| 166 | } | 182 | } |
| @@ -29,6 +29,7 @@ config TYPEC_MUX_INTEL_PMC · 28 unmodified lines | |||
| 29 | tristate "Intel PMC mux control" | 29 | tristate "Intel PMC mux control" |
| 30 | depends on ACPI | 30 | depends on ACPI |
| 31 | depends on INTEL_SCU_IPC | 31 | depends on INTEL_SCU_IPC |
| 32 | select USB_COMMON | ||
| 32 | select USB_ROLE_SWITCH | 33 | select USB_ROLE_SWITCH |
| 33 | help | 34 | help |
| 34 | Driver for USB muxes controlled by Intel PMC FW. Intel PMC FW can | 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 | ret = nb7vpq904m_register_bridge(nb7); | 464 | ret = nb7vpq904m_register_bridge(nb7); |
| 465 | if (ret) | 465 | if (ret) |
| 466 | return ret; | 466 | goto err_disable_gpio; |
| 467 | 467 | ||
| 468 | sw_desc.drvdata = nb7; | 468 | sw_desc.drvdata = nb7; |
| 469 | sw_desc.fwnode = dev->fwnode; | 469 | sw_desc.fwnode = dev->fwnode; |
| 470 | sw_desc.set = nb7vpq904m_sw_set; | 470 | sw_desc.set = nb7vpq904m_sw_set; |
| 471 | 471 | ||
| 472 | nb7->sw = typec_switch_register(dev, &sw_desc); | 472 | nb7->sw = typec_switch_register(dev, &sw_desc); |
| 473 | if (IS_ERR(nb7->sw)) | 473 | if (IS_ERR(nb7->sw)) { |
| 474 | return dev_err_probe(dev, PTR_ERR(nb7->sw), | 474 | ret = dev_err_probe(dev, PTR_ERR(nb7->sw), |
| 475 | "Error registering typec switch\n"); | 475 | "Error registering typec switch\n"); |
| 476 | goto err_disable_gpio; | ||
| 477 | } | ||
| 476 | 478 | ||
| 477 | retimer_desc.drvdata = nb7; | 479 | retimer_desc.drvdata = nb7; |
| 478 | retimer_desc.fwnode = dev->fwnode; | 480 | retimer_desc.fwnode = dev->fwnode; |
| @@ -480,12 +482,21 @@ static int nb7vpq904m_probe(struct i2c_client *client) · 1 unmodified line | |||
| 480 | 482 | ||
| 481 | nb7->retimer = typec_retimer_register(dev, &retimer_desc); | 483 | nb7->retimer = typec_retimer_register(dev, &retimer_desc); |
| 482 | if (IS_ERR(nb7->retimer)) { | 484 | if (IS_ERR(nb7->retimer)) { |
| 483 | typec_switch_unregister(nb7->sw); | 485 | ret = dev_err_probe(dev, PTR_ERR(nb7->retimer), |
| 484 | return dev_err_probe(dev, PTR_ERR(nb7->retimer), | 486 | "Error registering typec retimer\n"); |
| 485 | "Error registering typec retimer\n"); | 487 | goto err_switch_unregister; |
| 486 | } | 488 | } |
| 487 | 489 | ||
| 488 | return 0; | 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 | static void nb7vpq904m_remove(struct i2c_client *client) | 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 | /* Do nothing, vbus drop expected */ | 5282 | /* Do nothing, vbus drop expected */ |
| 5283 | break; | 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 | default: | 5289 | default: |
| 5286 | if (port->pwr_role == TYPEC_SINK && port->attached) | 5290 | if (port->pwr_role == TYPEC_SINK && port->attached) |
| 5287 | tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port)); | 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 | case SNK_DEBOUNCED: | 5332 | case SNK_DEBOUNCED: |
| 5329 | /*Do nothing, still waiting for VSAFE5V for connect */ | 5333 | /*Do nothing, still waiting for VSAFE5V for connect */ |
| 5330 | break; | 5334 | break; |
| 5335 | case SNK_HARD_RESET_WAIT_VBUS: | ||
| 5336 | /* Do nothing, its OK to receive vbus off events */ | ||
| 5337 | break; | ||
| 5331 | default: | 5338 | default: |
| 5332 | if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled) | 5339 | if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled) |
| 5333 | tcpm_set_state(port, SNK_UNATTACHED, 0); | 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 | u64 num_bytes) | 441 | u64 num_bytes) |
| 442 | { | 442 | { |
| 443 | struct btrfs_caching_control *caching_ctl; | 443 | struct btrfs_caching_control *caching_ctl; |
| 444 | int progress; | ||
| 444 | 445 | ||
| 445 | caching_ctl = btrfs_get_caching_control(cache); | 446 | caching_ctl = btrfs_get_caching_control(cache); |
| 446 | if (!caching_ctl) | 447 | if (!caching_ctl) |
| 447 | return; | 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 | wait_event(caching_ctl->wait, btrfs_block_group_done(cache) || | 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 | btrfs_put_caching_control(caching_ctl); | 462 | btrfs_put_caching_control(caching_ctl); |
| 453 | } | 463 | } |
| @@ -802,8 +812,10 @@ next: · 348 unmodified lines | |||
| 802 | 812 | ||
| 803 | if (total_found > CACHING_CTL_WAKE_UP) { | 813 | if (total_found > CACHING_CTL_WAKE_UP) { |
| 804 | total_found = 0; | 814 | total_found = 0; |
| 805 | if (wakeup) | 815 | if (wakeup) { |
| 816 | atomic_inc(&caching_ctl->progress); | ||
| 806 | wake_up(&caching_ctl->wait); | 817 | wake_up(&caching_ctl->wait); |
| 818 | } | ||
| 807 | } | 819 | } |
| 808 | } | 820 | } |
| 809 | path->slots[0]++; | 821 | path->slots[0]++; |
| @@ -910,6 +922,7 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait) · 100 unmodified lines | |||
| 910 | init_waitqueue_head(&caching_ctl->wait); | 922 | init_waitqueue_head(&caching_ctl->wait); |
| 911 | caching_ctl->block_group = cache; | 923 | caching_ctl->block_group = cache; |
| 912 | refcount_set(&caching_ctl->count, 2); | 924 | refcount_set(&caching_ctl->count, 2); |
| 925 | atomic_set(&caching_ctl->progress, 0); | ||
| 913 | btrfs_init_work(&caching_ctl->work, caching_thread, NULL, NULL); | 926 | btrfs_init_work(&caching_ctl->work, caching_thread, NULL, NULL); |
| 914 | 927 | ||
| 915 | spin_lock(&cache->lock); | 928 | spin_lock(&cache->lock); |
| @@ -90,6 +90,8 @@ struct btrfs_caching_control { · 89 unmodified lines | |||
| 90 | wait_queue_head_t wait; | 90 | wait_queue_head_t wait; |
| 91 | struct btrfs_work work; | 91 | struct btrfs_work work; |
| 92 | struct btrfs_block_group *block_group; | 92 | struct btrfs_block_group *block_group; |
| 93 | /* Track progress of caching during allocation. */ | ||
| 94 | atomic_t progress; | ||
| 93 | refcount_t count; | 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 | btrfs_drew_lock_init(&root->snapshot_lock); | 1103 | btrfs_drew_lock_init(&root->snapshot_lock); |
| 1104 | 1104 | ||
| 1105 | if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID && | 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 | set_bit(BTRFS_ROOT_SHAREABLE, &root->state); | 1108 | set_bit(BTRFS_ROOT_SHAREABLE, &root->state); |
| 1108 | btrfs_check_and_init_root_item(&root->root_item); | 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 | root = btrfs_get_global_root(fs_info, objectid); | 1301 | root = btrfs_get_global_root(fs_info, objectid); |
| 1301 | if (root) | 1302 | if (root) |
| 1302 | return root; | 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 | again: | 1314 | again: |
| 1304 | root = btrfs_lookup_fs_root(fs_info, objectid); | 1315 | root = btrfs_lookup_fs_root(fs_info, objectid); |
| 1305 | if (root) { | 1316 | if (root) { |
| @@ -4310,8 +4310,11 @@ have_block_group: · 4309 unmodified lines | |||
| 4310 | ret = 0; | 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 | goto loop; | 4316 | goto loop; |
| 4317 | } | ||
| 4315 | 4318 | ||
| 4316 | if (!find_free_extent_check_size_class(ffe_ctl, block_group)) | 4319 | if (!find_free_extent_check_size_class(ffe_ctl, block_group)) |
| 4317 | goto loop; | 4320 | goto loop; |
| @@ -2145,6 +2145,12 @@ retry: · 2144 unmodified lines | |||
| 2145 | continue; | 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 | if (wbc->sync_mode != WB_SYNC_NONE) { | 2154 | if (wbc->sync_mode != WB_SYNC_NONE) { |
| 2149 | if (folio_test_writeback(folio)) | 2155 | if (folio_test_writeback(folio)) |
| 2150 | submit_write_bio(bio_ctrl, 0); | 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 | * We have to make sure to honor the new nr_to_write | 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 | folio_batch_release(&fbatch); | 2180 | folio_batch_release(&fbatch); |
| 2174 | cond_resched(); | 2181 | cond_resched(); |
| @@ -1654,8 +1654,6 @@ out_unlock: · 1653 unmodified lines | |||
| 1654 | clear_bits, | 1654 | clear_bits, |
| 1655 | page_ops); | 1655 | page_ops); |
| 1656 | start += cur_alloc_size; | 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 | * space_info's bytes_may_use counter, reserved in | 1662 | * space_info's bytes_may_use counter, reserved in |
| 1665 | * btrfs_check_data_free_space(). | 1663 | * btrfs_check_data_free_space(). |
| 1666 | */ | 1664 | */ |
| 1667 | extent_clear_unlock_delalloc(inode, start, end, locked_page, | 1665 | if (start < end) { |
| 1668 | clear_bits | EXTENT_CLEAR_DATA_RESV, | 1666 | clear_bits |= EXTENT_CLEAR_DATA_RESV; |
| 1669 | page_ops); | 1667 | extent_clear_unlock_delalloc(inode, start, end, locked_page, |
| 1668 | clear_bits, page_ops); | ||
| 1669 | } | ||
| 1670 | return ret; | 1670 | return ret; |
| 1671 | } | 1671 | } |
| 1672 | 1672 | ||
| @@ -1916,7 +1916,39 @@ again: · 1915 unmodified lines | |||
| 1916 | err = PTR_ERR(root); | 1916 | err = PTR_ERR(root); |
| 1917 | break; | 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 | * set reference count to 1, so btrfs_recover_relocation | 1954 | * set reference count to 1, so btrfs_recover_relocation |
| @@ -1989,7 +2021,7 @@ again: · 66 unmodified lines | |||
| 1989 | root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset, | 2021 | root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset, |
| 1990 | false); | 2022 | false); |
| 1991 | if (btrfs_root_refs(&reloc_root->root_item) > 0) { | 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 | * For recovery we read the fs roots on mount, | 2026 | * For recovery we read the fs roots on mount, |
| 1995 | * and if we didn't find the root then we marked | 2027 | * and if we didn't find the root then we marked |
| @@ -1998,17 +2030,14 @@ again: · 2 unmodified lines | |||
| 1998 | * memory. However there's no reason we can't | 2030 | * memory. However there's no reason we can't |
| 1999 | * handle the error properly here just in case. | 2031 | * handle the error properly here just in case. |
| 2000 | */ | 2032 | */ |
| 2001 | ASSERT(0); | ||
| 2002 | ret = PTR_ERR(root); | 2033 | ret = PTR_ERR(root); |
| 2003 | goto out; | 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 | 2038 | * This can happen if on-disk metadata has some |
| 2008 | * going really wrong (like weird race condition | 2039 | * corruption, e.g. bad reloc tree key offset. |
| 2009 | * or cosmic rays). | ||
| 2010 | */ | 2040 | */ |
| 2011 | ASSERT(0); | ||
| 2012 | ret = -EINVAL; | 2041 | ret = -EINVAL; |
| 2013 | goto out; | 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 | btrfs_item_key_to_cpu(leaf, &item_key, slot); | 446 | btrfs_item_key_to_cpu(leaf, &item_key, slot); |
| 447 | is_root_item = (item_key.type == BTRFS_ROOT_ITEM_KEY); | 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 | /* No such tree id */ | 463 | /* No such tree id */ |
| 450 | if (unlikely(key->objectid == 0)) { | 464 | if (unlikely(key->objectid == 0)) { |
| 451 | if (is_root_item) | 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 | const struct file_operations ceph_dir_fops = { | 2023 | const struct file_operations ceph_dir_fops = { |
| 2023 | .read = ceph_read_dir, | 2024 | .read = ceph_read_dir, |
| 2024 | .iterate = ceph_readdir, | 2025 | .iterate_shared = shared_ceph_readdir, |
| 2025 | .llseek = ceph_dir_llseek, | 2026 | .llseek = ceph_dir_llseek, |
| 2026 | .open = ceph_open, | 2027 | .open = ceph_open, |
| 2027 | .release = ceph_release, | 2028 | .release = ceph_release, |
| @@ -2033,7 +2034,7 @@ const struct file_operations ceph_dir_fops = { · 5 unmodified lines | |||
| 2033 | }; | 2034 | }; |
| 2034 | 2035 | ||
| 2035 | const struct file_operations ceph_snapdir_fops = { | 2036 | const struct file_operations ceph_snapdir_fops = { |
| 2036 | .iterate = ceph_readdir, | 2037 | .iterate_shared = shared_ceph_readdir, |
| 2037 | .llseek = ceph_dir_llseek, | 2038 | .llseek = ceph_dir_llseek, |
| 2038 | .open = ceph_open, | 2039 | .open = ceph_open, |
| 2039 | .release = ceph_release, | 2040 | .release = ceph_release, |
| @@ -4764,7 +4764,7 @@ static void delayed_work(struct work_struct *work) · 4763 unmodified lines | |||
| 4764 | 4764 | ||
| 4765 | dout("mdsc delayed_work\n"); | 4765 | dout("mdsc delayed_work\n"); |
| 4766 | 4766 | ||
| 4767 | if (mdsc->stopping) | 4767 | if (mdsc->stopping >= CEPH_MDSC_STOPPING_FLUSHED) |
| 4768 | return; | 4768 | return; |
| 4769 | 4769 | ||
| 4770 | mutex_lock(&mdsc->mutex); | 4770 | mutex_lock(&mdsc->mutex); |
| @@ -4943,7 +4943,7 @@ void send_flush_mdlog(struct ceph_mds_session *s) · 172 unmodified lines | |||
| 4943 | void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc) | 4943 | void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc) |
| 4944 | { | 4944 | { |
| 4945 | dout("pre_umount\n"); | 4945 | dout("pre_umount\n"); |
| 4946 | mdsc->stopping = 1; | 4946 | mdsc->stopping = CEPH_MDSC_STOPPING_BEGIN; |
| 4947 | 4947 | ||
| 4948 | ceph_mdsc_iterate_sessions(mdsc, send_flush_mdlog, true); | 4948 | ceph_mdsc_iterate_sessions(mdsc, send_flush_mdlog, true); |
| 4949 | ceph_mdsc_iterate_sessions(mdsc, lock_unlock_session, false); | 4949 | ceph_mdsc_iterate_sessions(mdsc, lock_unlock_session, false); |
| @@ -380,6 +380,11 @@ struct cap_wait { · 379 unmodified lines | |||
| 380 | int want; | 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 | * mds client state | 389 | * mds client state |
| 385 | */ | 390 | */ |
| @@ -1374,6 +1374,16 @@ static void ceph_kill_sb(struct super_block *s) · 1373 unmodified lines | |||
| 1374 | ceph_mdsc_pre_umount(fsc->mdsc); | 1374 | ceph_mdsc_pre_umount(fsc->mdsc); |
| 1375 | flush_fs_workqueues(fsc); | 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 | kill_anon_super(s); | 1387 | kill_anon_super(s); |
| 1378 | 1388 | ||
| 1379 | fsc->client->extra_mon_dispatch = NULL; | 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 | cfi = coda_ftoc(coda_file); | 429 | cfi = coda_ftoc(coda_file); |
| 430 | host_file = cfi->cfi_container; | 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 | struct inode *host_inode = file_inode(host_file); | 433 | struct inode *host_inode = file_inode(host_file); |
| 434 | ret = -ENOENT; | 434 | ret = -ENOENT; |
| 435 | if (!IS_DEADDIR(host_inode)) { | 435 | if (!IS_DEADDIR(host_inode)) { |
| 436 | if (host_file->f_op->iterate_shared) { | 436 | inode_lock_shared(host_inode); |
| 437 | inode_lock_shared(host_inode); | 437 | ret = host_file->f_op->iterate_shared(host_file, ctx); |
| 438 | ret = host_file->f_op->iterate_shared(host_file, ctx); | 438 | file_accessed(host_file); |
| 439 | file_accessed(host_file); | 439 | inode_unlock_shared(host_inode); |
| 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 | } | ||
| 447 | } | 440 | } |
| 448 | return ret; | 441 | return ret; |
| 449 | } | 442 | } |
| @@ -585,10 +578,11 @@ const struct inode_operations coda_dir_inode_operations = { · 135 unmodified lines | |||
| 585 | .setattr = coda_setattr, | 578 | .setattr = coda_setattr, |
| 586 | }; | 579 | }; |
| 587 | 580 | ||
| 581 | WRAP_DIR_ITER(coda_readdir) // FIXME! | ||
| 588 | const struct file_operations coda_dir_operations = { | 582 | const struct file_operations coda_dir_operations = { |
| 589 | .llseek = generic_file_llseek, | 583 | .llseek = generic_file_llseek, |
| 590 | .read = generic_read_dir, | 584 | .read = generic_read_dir, |
| 591 | .iterate = coda_readdir, | 585 | .iterate_shared = shared_coda_readdir, |
| 592 | .open = coda_open, | 586 | .open = coda_open, |
| 593 | .release = coda_release, | 587 | .release = coda_release, |
| 594 | .fsync = coda_fsync, | 588 | .fsync = coda_fsync, |
| @@ -889,8 +889,6 @@ static void erofs_kill_sb(struct super_block *sb) · 888 unmodified lines | |||
| 889 | { | 889 | { |
| 890 | struct erofs_sb_info *sbi; | 890 | struct erofs_sb_info *sbi; |
| 891 | 891 | ||
| 892 | WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); | ||
| 893 | |||
| 894 | /* pseudo mount for anon inodes */ | 892 | /* pseudo mount for anon inodes */ |
| 895 | if (sb->s_flags & SB_KERNMOUNT) { | 893 | if (sb->s_flags & SB_KERNMOUNT) { |
| 896 | kill_anon_super(sb); | 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 | struct z_erofs_bvec *bvec) | 1144 | struct z_erofs_bvec *bvec) |
| 1145 | { | 1145 | { |
| 1146 | struct z_erofs_bvec_item *item; | 1146 | struct z_erofs_bvec_item *item; |
| 1147 | unsigned int pgnr; | ||
| 1147 | 1148 | ||
| 1148 | if (!((bvec->offset + be->pcl->pageofs_out) & ~PAGE_MASK)) { | 1149 | if (!((bvec->offset + be->pcl->pageofs_out) & ~PAGE_MASK) && |
| 1149 | unsigned int pgnr; | 1150 | (bvec->end == PAGE_SIZE || |
| 1150 | 1151 | bvec->offset + bvec->end == be->pcl->length)) { | |
| 1151 | pgnr = (bvec->offset + be->pcl->pageofs_out) >> PAGE_SHIFT; | 1152 | pgnr = (bvec->offset + be->pcl->pageofs_out) >> PAGE_SHIFT; |
| 1152 | DBG_BUGON(pgnr >= be->nr_pages); | 1153 | DBG_BUGON(pgnr >= be->nr_pages); |
| 1153 | if (!be->decompressed_pages[pgnr]) { | 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 | sbi->map_sectors = ((need_map_size - 1) >> | 70 | sbi->map_sectors = ((need_map_size - 1) >> |
| 71 | (sb->s_blocksize_bits)) + 1; | 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 | sizeof(struct buffer_head *), GFP_KERNEL); | 73 | sizeof(struct buffer_head *), GFP_KERNEL); |
| 74 | if (!sbi->vol_amap) | 74 | if (!sbi->vol_amap) |
| 75 | return -ENOMEM; | 75 | return -ENOMEM; |
| @@ -84,7 +84,7 @@ static int exfat_allocate_bitmap(struct super_block *sb, · 8 unmodified lines | |||
| 84 | while (j < i) | 84 | while (j < i) |
| 85 | brelse(sbi->vol_amap[j++]); | 85 | brelse(sbi->vol_amap[j++]); |
| 86 | 86 | ||
| 87 | kfree(sbi->vol_amap); | 87 | kvfree(sbi->vol_amap); |
| 88 | sbi->vol_amap = NULL; | 88 | sbi->vol_amap = NULL; |
| 89 | return -EIO; | 89 | return -EIO; |
| 90 | } | 90 | } |
| @@ -138,7 +138,7 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi) · 47 unmodified lines | |||
| 138 | for (i = 0; i < sbi->map_sectors; i++) | 138 | for (i = 0; i < sbi->map_sectors; i++) |
| 139 | __brelse(sbi->vol_amap[i]); | 139 | __brelse(sbi->vol_amap[i]); |
| 140 | 140 | ||
| 141 | kfree(sbi->vol_amap); | 141 | kvfree(sbi->vol_amap); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync) | 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 | int i, err; | 35 | int i, err; |
| 36 | struct exfat_entry_set_cache es; | 36 | struct exfat_entry_set_cache es; |
| 37 | unsigned int uni_len = 0, len; | ||
| 37 | 38 | ||
| 38 | err = exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES); | 39 | err = exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES); |
| 39 | if (err) | 40 | if (err) |
| @@ -52,7 +53,10 @@ static int exfat_get_uniname_from_ext_entry(struct super_block *sb, · 12 unmodified lines | |||
| 52 | if (exfat_get_entry_type(ep) != TYPE_EXTEND) | 53 | if (exfat_get_entry_type(ep) != TYPE_EXTEND) |
| 53 | break; | 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 | uniname += EXFAT_FILE_NAME_LEN; | 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 | exfat_init_namebuf(nb); | 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 | #define ITER_POS_FILLED_DOTS (2) | 225 | #define ITER_POS_FILLED_DOTS (2) |
| 219 | static int exfat_iterate(struct file *file, struct dir_context *ctx) | 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 | int err = 0, fake_offset = 0; | 236 | int err = 0, fake_offset = 0; |
| 230 | 237 | ||
| 231 | exfat_init_namebuf(nb); | 238 | exfat_init_namebuf(nb); |
| 232 | mutex_lock(&EXFAT_SB(sb)->s_lock); | ||
| 233 | 239 | ||
| 234 | cpos = ctx->pos; | 240 | cpos = ctx->pos; |
| 235 | if (!dir_emit_dots(file, ctx)) | 241 | if (!dir_emit_dots(file, ctx)) |
| 236 | goto unlock; | 242 | goto out; |
| 237 | 243 | ||
| 238 | if (ctx->pos == ITER_POS_FILLED_DOTS) { | 244 | if (ctx->pos == ITER_POS_FILLED_DOTS) { |
| 239 | cpos = 0; | 245 | cpos = 0; |
| @@ -245,16 +251,18 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx) · 5 unmodified lines | |||
| 245 | /* name buffer should be allocated before use */ | 251 | /* name buffer should be allocated before use */ |
| 246 | err = exfat_alloc_namebuf(nb); | 252 | err = exfat_alloc_namebuf(nb); |
| 247 | if (err) | 253 | if (err) |
| 248 | goto unlock; | 254 | goto out; |
| 249 | get_new: | 255 | get_new: |
| 256 | mutex_lock(&EXFAT_SB(sb)->s_lock); | ||
| 257 | |||
| 250 | if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode)) | 258 | if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode)) |
| 251 | goto end_of_dir; | 259 | goto end_of_dir; |
| 252 | 260 | ||
| 253 | err = exfat_readdir(inode, &cpos, &de); | 261 | err = exfat_readdir(inode, &cpos, &de); |
| 254 | if (err) { | 262 | if (err) { |
| 255 | /* | 263 | /* |
| 256 | * At least we tried to read a sector. Move cpos to next sector | 264 | * At least we tried to read a sector. |
| 257 | * position (should be aligned). | 265 | * Move cpos to next sector position (should be aligned). |
| 258 | */ | 266 | */ |
| 259 | if (err == -EIO) { | 267 | if (err == -EIO) { |
| 260 | cpos += 1 << (sb->s_blocksize_bits); | 268 | cpos += 1 << (sb->s_blocksize_bits); |
| @@ -277,16 +285,10 @@ get_new: · 16 unmodified lines | |||
| 277 | inum = iunique(sb, EXFAT_ROOT_INO); | 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 | mutex_unlock(&EXFAT_SB(sb)->s_lock); | 288 | mutex_unlock(&EXFAT_SB(sb)->s_lock); |
| 286 | if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum, | 289 | if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum, |
| 287 | (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) | 290 | (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) |
| 288 | goto out_unlocked; | 291 | goto out; |
| 289 | mutex_lock(&EXFAT_SB(sb)->s_lock); | ||
| 290 | ctx->pos = cpos; | 292 | ctx->pos = cpos; |
| 291 | goto get_new; | 293 | goto get_new; |
| 292 | 294 | ||
| @@ -294,9 +296,8 @@ end_of_dir: · 1 unmodified line | |||
| 294 | if (!cpos && fake_offset) | 296 | if (!cpos && fake_offset) |
| 295 | cpos = ITER_POS_FILLED_DOTS; | 297 | cpos = ITER_POS_FILLED_DOTS; |
| 296 | ctx->pos = cpos; | 298 | ctx->pos = cpos; |
| 297 | unlock: | ||
| 298 | mutex_unlock(&EXFAT_SB(sb)->s_lock); | 299 | mutex_unlock(&EXFAT_SB(sb)->s_lock); |
| 299 | out_unlocked: | 300 | out: |
| 300 | /* | 301 | /* |
| 301 | * To improve performance, free namebuf after unlock sb_lock. | 302 | * To improve performance, free namebuf after unlock sb_lock. |
| 302 | * If namebuf is not allocated, this function do nothing | 303 | * If namebuf is not allocated, this function do nothing |
| @@ -305,10 +306,11 @@ out_unlocked: · 2 unmodified lines | |||
| 305 | return err; | 306 | return err; |
| 306 | } | 307 | } |
| 307 | 308 | ||
| 309 | WRAP_DIR_ITER(exfat_iterate) // FIXME! | ||
| 308 | const struct file_operations exfat_dir_operations = { | 310 | const struct file_operations exfat_dir_operations = { |
| 309 | .llseek = generic_file_llseek, | 311 | .llseek = generic_file_llseek, |
| 310 | .read = generic_read_dir, | 312 | .read = generic_read_dir, |
| 311 | .iterate = exfat_iterate, | 313 | .iterate_shared = shared_exfat_iterate, |
| 312 | .unlocked_ioctl = exfat_ioctl, | 314 | .unlocked_ioctl = exfat_ioctl, |
| 313 | #ifdef CONFIG_COMPAT | 315 | #ifdef CONFIG_COMPAT |
| 314 | .compat_ioctl = exfat_compat_ioctl, | 316 | .compat_ioctl = exfat_compat_ioctl, |
| @@ -1079,7 +1081,8 @@ rewind: · 764 unmodified lines | |||
| 1079 | if (entry_type == TYPE_EXTEND) { | 1081 | if (entry_type == TYPE_EXTEND) { |
| 1080 | unsigned short entry_uniname[16], unichar; | 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 | step = DIRENT_STEP_FILE; | 1086 | step = DIRENT_STEP_FILE; |
| 1084 | continue; | 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 | goto out; | 315 | goto out; |
| 316 | 316 | ||
| 317 | error = -EINVAL; | 317 | error = -EINVAL; |
| 318 | if (!file->f_op->iterate && !file->f_op->iterate_shared) | 318 | if (!file->f_op->iterate_shared) |
| 319 | goto out_close; | 319 | goto out_close; |
| 320 | 320 | ||
| 321 | buffer.sequence = 0; | 321 | buffer.sequence = 0; |
| @@ -1036,12 +1036,28 @@ unsigned long __fdget_raw(unsigned int fd) · 1035 unmodified lines | |||
| 1036 | return __fget_light(fd, 0); | 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 | unsigned long __fdget_pos(unsigned int fd) | 1055 | unsigned long __fdget_pos(unsigned int fd) |
| 1040 | { | 1056 | { |
| 1041 | unsigned long v = __fdget(fd); | 1057 | unsigned long v = __fdget(fd); |
| 1042 | struct file *file = (struct file *)(v & ~3); | 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 | v |= FDPUT_POS_UNLOCK; | 1061 | v |= FDPUT_POS_UNLOCK; |
| 1046 | mutex_lock(&file->f_pos_lock); | 1062 | mutex_lock(&file->f_pos_lock); |
| 1047 | } | 1063 | } |
| @@ -1578,7 +1578,7 @@ const struct file_operations gfs2_file_fops = { · 1577 unmodified lines | |||
| 1578 | .fsync = gfs2_fsync, | 1578 | .fsync = gfs2_fsync, |
| 1579 | .lock = gfs2_lock, | 1579 | .lock = gfs2_lock, |
| 1580 | .flock = gfs2_flock, | 1580 | .flock = gfs2_flock, |
| 1581 | .splice_read = filemap_splice_read, | 1581 | .splice_read = copy_splice_read, |
| 1582 | .splice_write = gfs2_file_splice_write, | 1582 | .splice_write = gfs2_file_splice_write, |
| 1583 | .setlease = simple_nosetlease, | 1583 | .setlease = simple_nosetlease, |
| 1584 | .fallocate = gfs2_fallocate, | 1584 | .fallocate = gfs2_fallocate, |
| @@ -1609,7 +1609,7 @@ const struct file_operations gfs2_file_fops_nolock = { · 24 unmodified lines | |||
| 1609 | .open = gfs2_open, | 1609 | .open = gfs2_open, |
| 1610 | .release = gfs2_release, | 1610 | .release = gfs2_release, |
| 1611 | .fsync = gfs2_fsync, | 1611 | .fsync = gfs2_fsync, |
| 1612 | .splice_read = filemap_splice_read, | 1612 | .splice_read = copy_splice_read, |
| 1613 | .splice_write = gfs2_file_splice_write, | 1613 | .splice_write = gfs2_file_splice_write, |
| 1614 | .setlease = generic_setlease, | 1614 | .setlease = generic_setlease, |
| 1615 | .fallocate = gfs2_fallocate, | 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 | struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; | 232 | struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; |
| 233 | struct super_block *sb = sdp->sd_vfs; | ||
| 233 | struct gfs2_bufdata *bd; | 234 | struct gfs2_bufdata *bd; |
| 234 | struct gfs2_meta_header *mh; | 235 | struct gfs2_meta_header *mh; |
| 235 | struct gfs2_trans *tr = current->journal_info; | 236 | struct gfs2_trans *tr = current->journal_info; |
| 237 | bool withdraw = false; | ||
| 236 | 238 | ||
| 237 | lock_buffer(bh); | 239 | lock_buffer(bh); |
| 238 | if (buffer_pinned(bh)) { | 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 | (unsigned long long)bd->bd_bh->b_blocknr); | 268 | (unsigned long long)bd->bd_bh->b_blocknr); |
| 267 | BUG(); | 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 | if (unlikely(gfs2_withdrawn(sdp))) { | 271 | if (unlikely(gfs2_withdrawn(sdp))) { |
| 274 | fs_info(sdp, "GFS2:adding buf while withdrawn! 0x%llx\n", | 272 | fs_info(sdp, "GFS2:adding buf while withdrawn! 0x%llx\n", |
| 275 | (unsigned long long)bd->bd_bh->b_blocknr); | 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 | gfs2_pin(sdp, bd->bd_bh); | 281 | gfs2_pin(sdp, bd->bd_bh); |
| 278 | mh->__pad0 = cpu_to_be64(0); | 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 | tr->tr_num_buf_new++; | 285 | tr->tr_num_buf_new++; |
| 282 | out_unlock: | 286 | out_unlock: |
| 283 | gfs2_log_unlock(sdp); | 287 | gfs2_log_unlock(sdp); |
| 288 | if (withdraw) | ||
| 289 | gfs2_assert_withdraw(sdp, 0); | ||
| 284 | out: | 290 | out: |
| 285 | unlock_buffer(bh); | 291 | unlock_buffer(bh); |
| 286 | } | 292 | } |
| @@ -16,7 +16,6 @@ · 15 unmodified lines | |||
| 16 | #include <linux/fsnotify.h> | 16 | #include <linux/fsnotify.h> |
| 17 | #include <linux/mount.h> | 17 | #include <linux/mount.h> |
| 18 | #include <linux/posix_acl.h> | 18 | #include <linux/posix_acl.h> |
| 19 | #include <linux/prefetch.h> | ||
| 20 | #include <linux/buffer_head.h> /* for inode_has_buffers */ | 19 | #include <linux/buffer_head.h> /* for inode_has_buffers */ |
| 21 | #include <linux/ratelimit.h> | 20 | #include <linux/ratelimit.h> |
| 22 | #include <linux/list_lru.h> | 21 | #include <linux/list_lru.h> |
| @@ -1041,8 +1040,6 @@ struct inode *new_inode(struct super_block *sb) · 1018 unmodified lines | |||
| 1041 | { | 1040 | { |
| 1042 | struct inode *inode; | 1041 | struct inode *inode; |
| 1043 | 1042 | ||
| 1044 | spin_lock_prefetch(&sb->s_inode_list_lock); | ||
| 1045 | |||
| 1046 | inode = new_inode_pseudo(sb); | 1043 | inode = new_inode_pseudo(sb); |
| 1047 | if (inode) | 1044 | if (inode) |
| 1048 | inode_sb_list_add(inode); | 1045 | inode_sb_list_add(inode); |
| @@ -1535,9 +1535,10 @@ const struct inode_operations jfs_dir_inode_operations = { · 1534 unmodified lines | |||
| 1535 | #endif | 1535 | #endif |
| 1536 | }; | 1536 | }; |
| 1537 | 1537 | ||
| 1538 | WRAP_DIR_ITER(jfs_readdir) // FIXME! | ||
| 1538 | const struct file_operations jfs_dir_operations = { | 1539 | const struct file_operations jfs_dir_operations = { |
| 1539 | .read = generic_read_dir, | 1540 | .read = generic_read_dir, |
| 1540 | .iterate = jfs_readdir, | 1541 | .iterate_shared = shared_jfs_readdir, |
| 1541 | .fsync = jfs_fsync, | 1542 | .fsync = jfs_fsync, |
| 1542 | .unlocked_ioctl = jfs_ioctl, | 1543 | .unlocked_ioctl = jfs_ioctl, |
| 1543 | .compat_ioctl = compat_ptr_ioctl, | 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 | last_page = page + (offset + sd->len - 1) / PAGE_SIZE; | 956 | last_page = page + (offset + sd->len - 1) / PAGE_SIZE; |
| 957 | for (page += offset / PAGE_SIZE; page <= last_page; page++) { | 957 | for (page += offset / PAGE_SIZE; page <= last_page; page++) { |
| 958 | /* | 958 | /* |
| 959 | * Skip page replacement when extending the contents | 959 | * Skip page replacement when extending the contents of the |
| 960 | * of the current page. | 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 | continue; | 966 | continue; |
| 964 | if (unlikely(!svc_rqst_replace_page(rqstp, page))) | 967 | if (unlikely(!svc_rqst_replace_page(rqstp, page))) |
| 965 | return -EIO; | 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 | int __nilfs_mark_inode_dirty(struct inode *inode, int flags) | 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 | struct buffer_head *ibh; | 1105 | struct buffer_head *ibh; |
| 1105 | int err; | 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 | err = nilfs_load_inode_block(inode, &ibh); | 1115 | err = nilfs_load_inode_block(inode, &ibh); |
| 1108 | if (unlikely(err)) { | 1116 | if (unlikely(err)) { |
| 1109 | nilfs_warn(inode->i_sb, | 1117 | nilfs_warn(inode->i_sb, |
| @@ -2845,6 +2845,7 @@ void nilfs_detach_log_writer(struct super_block *sb) · 2844 unmodified lines | |||
| 2845 | nilfs_segctor_destroy(nilfs->ns_writer); | 2845 | nilfs_segctor_destroy(nilfs->ns_writer); |
| 2846 | nilfs->ns_writer = NULL; | 2846 | nilfs->ns_writer = NULL; |
| 2847 | } | 2847 | } |
| 2848 | set_nilfs_purging(nilfs); | ||
| 2848 | 2849 | ||
| 2849 | /* Force to free the list of dirty files */ | 2850 | /* Force to free the list of dirty files */ |
| 2850 | spin_lock(&nilfs->ns_inode_lock); | 2851 | spin_lock(&nilfs->ns_inode_lock); |
| @@ -2857,4 +2858,5 @@ void nilfs_detach_log_writer(struct super_block *sb) · 6 unmodified lines | |||
| 2857 | up_write(&nilfs->ns_segctor_sem); | 2858 | up_write(&nilfs->ns_segctor_sem); |
| 2858 | 2859 | ||
| 2859 | nilfs_dispose_list(nilfs, &garbage_list, 1); | 2860 | nilfs_dispose_list(nilfs, &garbage_list, 1); |
| 2861 | clear_nilfs_purging(nilfs); | ||
| 2860 | } | 2862 | } |
| @@ -29,6 +29,7 @@ enum { · 28 unmodified lines | |||
| 29 | THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */ | 29 | THE_NILFS_DISCONTINUED, /* 'next' pointer chain has broken */ |
| 30 | THE_NILFS_GC_RUNNING, /* gc process is running */ | 30 | THE_NILFS_GC_RUNNING, /* gc process is running */ |
| 31 | THE_NILFS_SB_DIRTY, /* super block is dirty */ | 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 | THE_NILFS_FNS(DISCONTINUED, discontinued) | 209 | THE_NILFS_FNS(DISCONTINUED, discontinued) |
| 209 | THE_NILFS_FNS(GC_RUNNING, gc_running) | 210 | THE_NILFS_FNS(GC_RUNNING, gc_running) |
| 210 | THE_NILFS_FNS(SB_DIRTY, sb_dirty) | 211 | THE_NILFS_FNS(SB_DIRTY, sb_dirty) |
| 212 | THE_NILFS_FNS(PURGING, purging) | ||
| 211 | 213 | ||
| 212 | /* | 214 | /* |
| 213 | * Mount option operations | 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 | #endif /* NTFS_RW */ | 1526 | #endif /* NTFS_RW */ |
| 1527 | 1527 | ||
| 1528 | WRAP_DIR_ITER(ntfs_readdir) // FIXME! | ||
| 1528 | const struct file_operations ntfs_dir_ops = { | 1529 | const struct file_operations ntfs_dir_ops = { |
| 1529 | .llseek = generic_file_llseek, /* Seek inside directory. */ | 1530 | .llseek = generic_file_llseek, /* Seek inside directory. */ |
| 1530 | .read = generic_read_dir, /* Return -EISDIR. */ | 1531 | .read = generic_read_dir, /* Return -EISDIR. */ |
| 1531 | .iterate = ntfs_readdir, /* Read directory contents. */ | 1532 | .iterate_shared = shared_ntfs_readdir, /* Read directory contents. */ |
| 1532 | #ifdef NTFS_RW | 1533 | #ifdef NTFS_RW |
| 1533 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ | 1534 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ |
| 1534 | #endif /* NTFS_RW */ | 1535 | #endif /* NTFS_RW */ |
| @@ -2793,10 +2793,11 @@ const struct file_operations ocfs2_fops = { · 2792 unmodified lines | |||
| 2793 | .remap_file_range = ocfs2_remap_file_range, | 2793 | .remap_file_range = ocfs2_remap_file_range, |
| 2794 | }; | 2794 | }; |
| 2795 | 2795 | ||
| 2796 | WRAP_DIR_ITER(ocfs2_readdir) // FIXME! | ||
| 2796 | const struct file_operations ocfs2_dops = { | 2797 | const struct file_operations ocfs2_dops = { |
| 2797 | .llseek = generic_file_llseek, | 2798 | .llseek = generic_file_llseek, |
| 2798 | .read = generic_read_dir, | 2799 | .read = generic_read_dir, |
| 2799 | .iterate = ocfs2_readdir, | 2800 | .iterate_shared = shared_ocfs2_readdir, |
| 2800 | .fsync = ocfs2_sync_file, | 2801 | .fsync = ocfs2_sync_file, |
| 2801 | .release = ocfs2_dir_release, | 2802 | .release = ocfs2_dir_release, |
| 2802 | .open = ocfs2_dir_open, | 2803 | .open = ocfs2_dir_open, |
| @@ -2842,7 +2843,7 @@ const struct file_operations ocfs2_fops_no_plocks = { · 39 unmodified lines | |||
| 2842 | const struct file_operations ocfs2_dops_no_plocks = { | 2843 | const struct file_operations ocfs2_dops_no_plocks = { |
| 2843 | .llseek = generic_file_llseek, | 2844 | .llseek = generic_file_llseek, |
| 2844 | .read = generic_read_dir, | 2845 | .read = generic_read_dir, |
| 2845 | .iterate = ocfs2_readdir, | 2846 | .iterate_shared = shared_ocfs2_readdir, |
| 2846 | .fsync = ocfs2_sync_file, | 2847 | .fsync = ocfs2_sync_file, |
| 2847 | .release = ocfs2_dir_release, | 2848 | .release = ocfs2_dir_release, |
| 2848 | .open = ocfs2_dir_open, | 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 | lookup_flags |= LOOKUP_IN_ROOT; | 1322 | lookup_flags |= LOOKUP_IN_ROOT; |
| 1323 | if (how->resolve & RESOLVE_CACHED) { | 1323 | if (how->resolve & RESOLVE_CACHED) { |
| 1324 | /* Don't bother even trying for create/truncate/tmpfile open */ | 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 | return -EAGAIN; | 1326 | return -EAGAIN; |
| 1327 | lookup_flags |= LOOKUP_CACHED; | 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 | return 0; | 954 | return 0; |
| 955 | } | 955 | } |
| 956 | 956 | ||
| 957 | WRAP_DIR_ITER(ovl_iterate) // FIXME! | ||
| 957 | const struct file_operations ovl_dir_operations = { | 958 | const struct file_operations ovl_dir_operations = { |
| 958 | .read = generic_read_dir, | 959 | .read = generic_read_dir, |
| 959 | .open = ovl_dir_open, | 960 | .open = ovl_dir_open, |
| 960 | .iterate = ovl_iterate, | 961 | .iterate_shared = shared_ovl_iterate, |
| 961 | .llseek = ovl_dir_llseek, | 962 | .llseek = ovl_dir_llseek, |
| 962 | .fsync = ovl_dir_fsync, | 963 | .fsync = ovl_dir_fsync, |
| 963 | .release = ovl_dir_release, | 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 | static const struct file_operations proc_##LSM##_attr_dir_ops = { \ | 2818 | static const struct file_operations proc_##LSM##_attr_dir_ops = { \ |
| 2819 | .read = generic_read_dir, \ | 2819 | .read = generic_read_dir, \ |
| 2820 | .iterate = proc_##LSM##_attr_dir_iterate, \ | 2820 | .iterate_shared = proc_##LSM##_attr_dir_iterate, \ |
| 2821 | .llseek = default_llseek, \ | 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 | static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter) | 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 | loff_t *fpos = &iocb->ki_pos; | 314 | loff_t *fpos = &iocb->ki_pos; |
| 313 | size_t phdrs_offset, notes_offset, data_offset; | 315 | size_t phdrs_offset, notes_offset, data_offset; |
| 314 | size_t page_offline_frozen = 1; | 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 | case KCORE_VMEMMAP: | 557 | case KCORE_VMEMMAP: |
| 556 | case KCORE_TEXT: | 558 | case KCORE_TEXT: |
| 557 | /* | 559 | /* |
| 558 | * We use _copy_to_iter() to bypass usermode hardening | 560 | * Sadly we must use a bounce buffer here to be able to |
| 559 | * which would otherwise prevent this operation. | 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 | ret = -EFAULT; | 575 | ret = -EFAULT; |
| 563 | goto out; | 576 | goto out; |
| 564 | } | 577 | } |
| @@ -595,6 +608,10 @@ static int open_kcore(struct inode *inode, struct file *filp) · 30 unmodified lines | |||
| 595 | if (ret) | 608 | if (ret) |
| 596 | return ret; | 609 | return ret; |
| 597 | 610 | ||
| 611 | filp->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 612 | if (!filp->private_data) | ||
| 613 | return -ENOMEM; | ||
| 614 | |||
| 598 | if (kcore_need_update) | 615 | if (kcore_need_update) |
| 599 | kcore_update_ram(); | 616 | kcore_update_ram(); |
| 600 | if (i_size_read(inode) != proc_root_kcore->size) { | 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 | return 0; | 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 | static const struct proc_ops kcore_proc_ops = { | 631 | static const struct proc_ops kcore_proc_ops = { |
| 609 | .proc_read_iter = read_kcore_iter, | 632 | .proc_read_iter = read_kcore_iter, |
| 610 | .proc_open = open_kcore, | 633 | .proc_open = open_kcore, |
| 634 | .proc_release = release_kcore, | ||
| 611 | .proc_lseek = default_llseek, | 635 | .proc_lseek = default_llseek, |
| 612 | }; | 636 | }; |
| 613 | 637 | ||
| @@ -24,6 +24,53 @@ · 23 unmodified lines | |||
| 24 | 24 | ||
| 25 | #include <asm/unaligned.h> | 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 | * Note the "unsafe_put_user() semantics: we goto a | 75 | * Note the "unsafe_put_user() semantics: we goto a |
| 29 | * label for errors. | 76 | * label for errors. |
| @@ -40,39 +87,28 @@ · 10 unmodified lines | |||
| 40 | int iterate_dir(struct file *file, struct dir_context *ctx) | 87 | int iterate_dir(struct file *file, struct dir_context *ctx) |
| 41 | { | 88 | { |
| 42 | struct inode *inode = file_inode(file); | 89 | struct inode *inode = file_inode(file); |
| 43 | bool shared = false; | ||
| 44 | int res = -ENOTDIR; | 90 | int res = -ENOTDIR; |
| 45 | if (file->f_op->iterate_shared) | 91 | |
| 46 | shared = true; | 92 | if (!file->f_op->iterate_shared) |
| 47 | else if (!file->f_op->iterate) | ||
| 48 | goto out; | 93 | goto out; |
| 49 | 94 | ||
| 50 | res = security_file_permission(file, MAY_READ); | 95 | res = security_file_permission(file, MAY_READ); |
| 51 | if (res) | 96 | if (res) |
| 52 | goto out; | 97 | goto out; |
| 53 | 98 | ||
| 54 | if (shared) | 99 | res = down_read_killable(&inode->i_rwsem); |
| 55 | res = down_read_killable(&inode->i_rwsem); | ||
| 56 | else | ||
| 57 | res = down_write_killable(&inode->i_rwsem); | ||
| 58 | if (res) | 100 | if (res) |
| 59 | goto out; | 101 | goto out; |
| 60 | 102 | ||
| 61 | res = -ENOENT; | 103 | res = -ENOENT; |
| 62 | if (!IS_DEADDIR(inode)) { | 104 | if (!IS_DEADDIR(inode)) { |
| 63 | ctx->pos = file->f_pos; | 105 | ctx->pos = file->f_pos; |
| 64 | if (shared) | 106 | res = file->f_op->iterate_shared(file, ctx); |
| 65 | res = file->f_op->iterate_shared(file, ctx); | ||
| 66 | else | ||
| 67 | res = file->f_op->iterate(file, ctx); | ||
| 68 | file->f_pos = ctx->pos; | 107 | file->f_pos = ctx->pos; |
| 69 | fsnotify_access(file); | 108 | fsnotify_access(file); |
| 70 | file_accessed(file); | 109 | file_accessed(file); |
| 71 | } | 110 | } |
| 72 | if (shared) | 111 | inode_unlock_shared(inode); |
| 73 | inode_unlock_shared(inode); | ||
| 74 | else | ||
| 75 | inode_unlock(inode); | ||
| 76 | out: | 112 | out: |
| 77 | return res; | 113 | return res; |
| 78 | } | 114 | } |
| @@ -177,8 +177,12 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx) · 176 unmodified lines | |||
| 177 | struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl); | 177 | struct dfs_cache_tgt_list tl = DFS_CACHE_TGT_LIST_INIT(tl); |
| 178 | 178 | ||
| 179 | rc = dfs_get_referral(mnt_ctx, ref_path + 1, NULL, &tl); | 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 | break; | 184 | break; |
| 185 | } | ||
| 182 | 186 | ||
| 183 | tit = dfs_cache_get_tgt_iterator(&tl); | 187 | tit = dfs_cache_get_tgt_iterator(&tl); |
| 184 | if (!tit) { | 188 | if (!tit) { |
| @@ -380,13 +380,13 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) · 379 unmodified lines | |||
| 380 | } | 380 | } |
| 381 | 381 | ||
| 382 | if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { | 382 | if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { |
| 383 | if (command == SMB2_OPLOCK_BREAK_HE && | 383 | if (!(command == SMB2_OPLOCK_BREAK_HE && |
| 384 | le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_20 && | 384 | (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 || |
| 385 | le16_to_cpu(pdu->StructureSize2) != OP_BREAK_STRUCT_SIZE_21) { | 385 | le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_21))) { |
| 386 | /* special case for SMB2.1 lease break message */ | 386 | /* special case for SMB2.1 lease break message */ |
| 387 | ksmbd_debug(SMB, | 387 | ksmbd_debug(SMB, |
| 388 | "Illegal request size %d for oplock break\n", | 388 | "Illegal request size %u for command %d\n", |
| 389 | le16_to_cpu(pdu->StructureSize2)); | 389 | le16_to_cpu(pdu->StructureSize2), command); |
| 390 | return 1; | 390 | return 1; |
| 391 | } | 391 | } |
| 392 | } | 392 | } |
| @@ -2324,9 +2324,16 @@ next: · 2323 unmodified lines | |||
| 2324 | break; | 2324 | break; |
| 2325 | buf_len -= next; | 2325 | buf_len -= next; |
| 2326 | eabuf = (struct smb2_ea_info *)((char *)eabuf + next); | 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 | break; | 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 | } while (next != 0); | 2337 | } while (next != 0); |
| 2331 | 2338 | ||
| 2332 | kfree(attr_name); | 2339 | kfree(attr_name); |
| @@ -179,9 +179,10 @@ static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx) · 178 unmodified lines | |||
| 179 | return 0; | 179 | return 0; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | WRAP_DIR_ITER(vboxsf_dir_iterate) // FIXME! | ||
| 182 | const struct file_operations vboxsf_dir_fops = { | 183 | const struct file_operations vboxsf_dir_fops = { |
| 183 | .open = vboxsf_dir_open, | 184 | .open = vboxsf_dir_open, |
| 184 | .iterate = vboxsf_dir_iterate, | 185 | .iterate_shared = shared_vboxsf_dir_iterate, |
| 185 | .release = vboxsf_dir_release, | 186 | .release = vboxsf_dir_release, |
| 186 | .read = generic_read_dir, | 187 | .read = generic_read_dir, |
| 187 | .llseek = generic_file_llseek, | 188 | .llseek = generic_file_llseek, |
| @@ -68,9 +68,9 @@ struct shfl_string { · 67 unmodified lines | |||
| 68 | 68 | ||
| 69 | /** UTF-8 or UTF-16 string. Nul terminated. */ | 69 | /** UTF-8 or UTF-16 string. Nul terminated. */ |
| 70 | union { | 70 | union { |
| 71 | u8 utf8[2]; | 71 | u8 legacy_padding[2]; |
| 72 | u16 utf16[1]; | 72 | DECLARE_FLEX_ARRAY(u8, utf8); |
| 73 | u16 ucs2[1]; /* misnomer, use utf16. */ | 73 | DECLARE_FLEX_ARRAY(u16, utf16); |
| 74 | } string; | 74 | } string; |
| 75 | }; | 75 | }; |
| 76 | VMMDEV_ASSERT_SIZE(shfl_string, 6); | 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 | return generic_file_llseek_size(file, offset, whence, isize, isize); | 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 | static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size, | 344 | static int zonefs_file_write_dio_end_io(struct kiocb *iocb, ssize_t size, |
| 416 | int error, unsigned int flags) | 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 | return 0; | 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 | static const struct iomap_dio_ops zonefs_write_dio_ops = { | 374 | static const struct iomap_dio_ops zonefs_write_dio_ops = { |
| 454 | .end_io = zonefs_file_write_dio_end_io, | 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 | struct zonefs_inode_info *zi = ZONEFS_I(inode); | 454 | struct zonefs_inode_info *zi = ZONEFS_I(inode); |
| 534 | struct zonefs_zone *z = zonefs_inode_zone(inode); | 455 | struct zonefs_zone *z = zonefs_inode_zone(inode); |
| 535 | struct super_block *sb = inode->i_sb; | 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 | ssize_t ret, count; | 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 | * as this can cause write reordering (e.g. the first aio gets EAGAIN | 461 | * as this can cause write reordering (e.g. the first aio gets EAGAIN |
| 544 | * on the inode lock but the second goes through but is now unaligned). | 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 | return -EOPNOTSUPP; | 466 | return -EOPNOTSUPP; |
| 548 | 467 | ||
| 549 | if (iocb->ki_flags & IOCB_NOWAIT) { | 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 | goto inode_unlock; | 492 | goto inode_unlock; |
| 574 | } | 493 | } |
| 575 | mutex_unlock(&zi->i_truncate_mutex); | 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 | * the user can make sense of the error. | 500 | * the user can make sense of the error. |
| 594 | */ | 501 | */ |
| 595 | ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops, | 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 | if (ret == -ENOTBLK) | 504 | if (ret == -ENOTBLK) |
| 598 | ret = -EBUSY; | 505 | ret = -EBUSY; |
| 599 | 506 | ||
| @@ -938,15 +845,3 @@ const struct file_operations zonefs_file_operations = { · 338 unmodified lines | |||
| 938 | .splice_write = iter_file_splice_write, | 845 | .splice_write = iter_file_splice_write, |
| 939 | .iopoll = iocb_bio_iopoll, | 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 | BUILD_BUG_ON(sizeof(struct zonefs_super) != ZONEFS_SUPER_SIZE); | 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 | ret = zonefs_init_inodecache(); | 1415 | ret = zonefs_init_inodecache(); |
| 1420 | if (ret) | 1416 | if (ret) |
| 1421 | goto destroy_bioset; | 1417 | return ret; |
| 1422 | 1418 | ||
| 1423 | ret = zonefs_sysfs_init(); | 1419 | ret = zonefs_sysfs_init(); |
| 1424 | if (ret) | 1420 | if (ret) |
| @@ -1434,8 +1430,6 @@ sysfs_exit: · 9 unmodified lines | |||
| 1434 | zonefs_sysfs_exit(); | 1430 | zonefs_sysfs_exit(); |
| 1435 | destroy_inodecache: | 1431 | destroy_inodecache: |
| 1436 | zonefs_destroy_inodecache(); | 1432 | zonefs_destroy_inodecache(); |
| 1437 | destroy_bioset: | ||
| 1438 | zonefs_file_bioset_exit(); | ||
| 1439 | 1433 | ||
| 1440 | return ret; | 1434 | return ret; |
| 1441 | } | 1435 | } |
| @@ -1445,7 +1439,6 @@ static void __exit zonefs_exit(void) · 3 unmodified lines | |||
| 1445 | unregister_filesystem(&zonefs_type); | 1439 | unregister_filesystem(&zonefs_type); |
| 1446 | zonefs_sysfs_exit(); | 1440 | zonefs_sysfs_exit(); |
| 1447 | zonefs_destroy_inodecache(); | 1441 | zonefs_destroy_inodecache(); |
| 1448 | zonefs_file_bioset_exit(); | ||
| 1449 | } | 1442 | } |
| 1450 | 1443 | ||
| 1451 | MODULE_AUTHOR("Damien Le Moal"); | 1444 | MODULE_AUTHOR("Damien Le Moal"); |
| @@ -279,8 +279,6 @@ extern const struct file_operations zonefs_dir_operations; · 278 unmodified lines | |||
| 279 | extern const struct address_space_operations zonefs_file_aops; | 279 | extern const struct address_space_operations zonefs_file_aops; |
| 280 | extern const struct file_operations zonefs_file_operations; | 280 | extern const struct file_operations zonefs_file_operations; |
| 281 | int zonefs_file_truncate(struct inode *inode, loff_t isize); | 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 | /* In sysfs.c */ | 283 | /* In sysfs.c */ |
| 286 | int zonefs_sysfs_register(struct super_block *sb); | 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 | void *hv_alloc_hyperv_page(void); | 191 | void *hv_alloc_hyperv_page(void); |
| 192 | void *hv_alloc_hyperv_zeroed_page(void); | 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 | * hv_cpu_number_to_vp_number() - Map CPU to VP. | 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 | return (mask >> 8) ? byte : byte + 1; | 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 | unsigned long rhs = val | c->low_bits; | 43 | unsigned long rhs = val | c->low_bits; |
| 44 | *data = rhs; | 44 | *data = rhs; |
| @@ -791,7 +791,7 @@ static inline int bio_integrity_add_page(struct bio *bio, struct page *page, · 790 unmodified lines | |||
| 791 | static inline void bio_set_polled(struct bio *bio, struct kiocb *kiocb) | 791 | static inline void bio_set_polled(struct bio *bio, struct kiocb *kiocb) |
| 792 | { | 792 | { |
| 793 | bio->bi_opf |= REQ_POLLED; | 793 | bio->bi_opf |= REQ_POLLED; |
| 794 | if (!is_sync_kiocb(kiocb)) | 794 | if (kiocb->ki_flags & IOCB_NOWAIT) |
| 795 | bio->bi_opf |= REQ_NOWAIT; | 795 | bio->bi_opf |= REQ_NOWAIT; |
| 796 | } | 796 | } |
| 797 | 797 | ||
| @@ -969,7 +969,6 @@ struct blk_plug { · 968 unmodified lines | |||
| 969 | 969 | ||
| 970 | bool multiple_queues; | 970 | bool multiple_queues; |
| 971 | bool has_elevator; | 971 | bool has_elevator; |
| 972 | bool nowait; | ||
| 973 | 972 | ||
| 974 | struct list_head cb_list; /* md requires an unplug callback */ | 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 | char *buf); | 70 | char *buf); |
| 71 | extern ssize_t cpu_show_retbleed(struct device *dev, | 71 | extern ssize_t cpu_show_retbleed(struct device *dev, |
| 72 | struct device_attribute *attr, char *buf); | 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 | extern __printf(4, 5) | 78 | extern __printf(4, 5) |
| 75 | struct device *cpu_device_create(struct device *parent, void *drvdata, | 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 | * cpumask_first_and - return the first cpu from *srcp1 & *srcp2 | 177 | * cpumask_first_and - return the first cpu from *srcp1 & *srcp2 |
| 178 | * @src1p: the first input | 178 | * @srcp1: the first input |
| 179 | * @src2p: the second input | 179 | * @srcp2: the second input |
| 180 | * | 180 | * |
| 181 | * Returns >= nr_cpu_ids if no cpus set in both. See also cpumask_next_and(). | 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 | * cpumap_print_list_to_buf - copies the cpumask into the buffer as | 1198 | * cpumap_print_list_to_buf - copies the cpumask into the buffer as |
| 1199 | * comma-separated list of cpus | 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 | * Everything is same with the above cpumap_print_bitmask_to_buf() | 1205 | * Everything is same with the above cpumap_print_bitmask_to_buf() |
| 1202 | * except the print format. | 1206 | * except the print format. |
| @@ -1780,7 +1780,6 @@ struct file_operations { · 1779 unmodified lines | |||
| 1780 | ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); | 1780 | ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); |
| 1781 | int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *, | 1781 | int (*iopoll)(struct kiocb *kiocb, struct io_comp_batch *, |
| 1782 | unsigned int flags); | 1782 | unsigned int flags); |
| 1783 | int (*iterate) (struct file *, struct dir_context *); | ||
| 1784 | int (*iterate_shared) (struct file *, struct dir_context *); | 1783 | int (*iterate_shared) (struct file *, struct dir_context *); |
| 1785 | __poll_t (*poll) (struct file *, struct poll_table_struct *); | 1784 | __poll_t (*poll) (struct file *, struct poll_table_struct *); |
| 1786 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); | 1785 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); |
| @@ -1817,6 +1816,13 @@ struct file_operations { · 30 unmodified lines | |||
| 1817 | unsigned int poll_flags); | 1816 | unsigned int poll_flags); |
| 1818 | } __randomize_layout; | 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 | struct inode_operations { | 1826 | struct inode_operations { |
| 1821 | struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); | 1827 | struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); |
| 1822 | const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); | 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 | u32 *buffer_actual_len, | 1239 | u32 *buffer_actual_len, |
| 1240 | u64 *requestid); | 1240 | u64 *requestid); |
| 1241 | 1241 | ||
| 1242 | |||
| 1243 | extern void vmbus_ontimer(unsigned long data); | ||
| 1244 | |||
| 1245 | /* Base driver object */ | 1242 | /* Base driver object */ |
| 1246 | struct hv_driver { | 1243 | struct hv_driver { |
| 1247 | const char *name; | 1244 | const char *name; |
| @@ -100,10 +100,16 @@ struct rapl_package; · 99 unmodified lines | |||
| 100 | 100 | ||
| 101 | #define RAPL_DOMAIN_NAME_LENGTH 16 | 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 | struct rapl_domain { | 109 | struct rapl_domain { |
| 104 | char name[RAPL_DOMAIN_NAME_LENGTH]; | 110 | char name[RAPL_DOMAIN_NAME_LENGTH]; |
| 105 | enum rapl_domain_type id; | 111 | enum rapl_domain_type id; |
| 106 | u64 regs[RAPL_DOMAIN_REG_MAX]; | 112 | union rapl_reg regs[RAPL_DOMAIN_REG_MAX]; |
| 107 | struct powercap_zone power_zone; | 113 | struct powercap_zone power_zone; |
| 108 | struct rapl_domain_data rdd; | 114 | struct rapl_domain_data rdd; |
| 109 | struct rapl_power_limit rpl[NR_POWER_LIMITS]; | 115 | struct rapl_power_limit rpl[NR_POWER_LIMITS]; |
| @@ -116,7 +122,7 @@ struct rapl_domain { · 6 unmodified lines | |||
| 116 | }; | 122 | }; |
| 117 | 123 | ||
| 118 | struct reg_action { | 124 | struct reg_action { |
| 119 | u64 reg; | 125 | union rapl_reg reg; |
| 120 | u64 mask; | 126 | u64 mask; |
| 121 | u64 value; | 127 | u64 value; |
| 122 | int err; | 128 | int err; |
| @@ -143,8 +149,8 @@ struct rapl_if_priv { · 20 unmodified lines | |||
| 143 | enum rapl_if_type type; | 149 | enum rapl_if_type type; |
| 144 | struct powercap_control_type *control_type; | 150 | struct powercap_control_type *control_type; |
| 145 | enum cpuhp_state pcap_rapl_online; | 151 | enum cpuhp_state pcap_rapl_online; |
| 146 | u64 reg_unit; | 152 | union rapl_reg reg_unit; |
| 147 | u64 regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX]; | 153 | union rapl_reg regs[RAPL_DOMAIN_MAX][RAPL_DOMAIN_REG_MAX]; |
| 148 | int limits[RAPL_DOMAIN_MAX]; | 154 | int limits[RAPL_DOMAIN_MAX]; |
| 149 | int (*read_raw)(int id, struct reg_action *ra); | 155 | int (*read_raw)(int id, struct reg_action *ra); |
| 150 | int (*write_raw)(int id, struct reg_action *ra); | 156 | int (*write_raw)(int id, struct reg_action *ra); |
| @@ -25,11 +25,10 @@ struct page; · 24 unmodified lines | |||
| 25 | prefetch() should be defined by the architecture, if not, the | 25 | prefetch() should be defined by the architecture, if not, the |
| 26 | #define below provides a no-op define. | 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 | prefetch(x) - prefetches the cacheline at "x" for read | 30 | prefetch(x) - prefetches the cacheline at "x" for read |
| 31 | prefetchw(x) - prefetches the cacheline at "x" for write | 31 | prefetchw(x) - prefetches the cacheline at "x" for write |
| 32 | spin_lock_prefetch(x) - prefetches the spinlock *x for taking | ||
| 33 | 32 | ||
| 34 | there is also PREFETCH_STRIDE which is the architecure-preferred | 33 | there is also PREFETCH_STRIDE which is the architecure-preferred |
| 35 | "lookahead" size for prefetching streamed operations. | 34 | "lookahead" size for prefetching streamed operations. |
| @@ -44,10 +43,6 @@ struct page; · 8 unmodified lines | |||
| 44 | #define prefetchw(x) __builtin_prefetch(x,1) | 43 | #define prefetchw(x) __builtin_prefetch(x,1) |
| 45 | #endif | 44 | #endif |
| 46 | 45 | ||
| 47 | #ifndef ARCH_HAS_SPINLOCK_PREFETCH | ||
| 48 | #define spin_lock_prefetch(x) prefetchw(x) | ||
| 49 | #endif | ||
| 50 | |||
| 51 | #ifndef PREFETCH_STRIDE | 46 | #ifndef PREFETCH_STRIDE |
| 52 | #define PREFETCH_STRIDE (4*L1_CACHE_BYTES) | 47 | #define PREFETCH_STRIDE (4*L1_CACHE_BYTES) |
| 53 | #endif | 48 | #endif |
| @@ -62,6 +62,7 @@ struct sk_psock_progs { · 61 unmodified lines | |||
| 62 | 62 | ||
| 63 | enum sk_psock_state_bits { | 63 | enum sk_psock_state_bits { |
| 64 | SK_PSOCK_TX_ENABLED, | 64 | SK_PSOCK_TX_ENABLED, |
| 65 | SK_PSOCK_RX_STRP_ENABLED, | ||
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 67 | struct sk_psock_link { | 68 | struct sk_psock_link { |
| @@ -15,4 +15,6 @@ struct corgi_lcd_platform_data { · 14 unmodified lines | |||
| 15 | void (*kick_battery)(void); | 15 | void (*kick_battery)(void); |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | void corgi_lcd_limit_intensity(int limit); | ||
| 19 | |||
| 18 | #endif /* __LINUX_SPI_CORGI_LCD_H */ | 20 | #endif /* __LINUX_SPI_CORGI_LCD_H */ |
| @@ -101,6 +101,7 @@ struct spi_mem_op { · 100 unmodified lines | |||
| 101 | u8 nbytes; | 101 | u8 nbytes; |
| 102 | u8 buswidth; | 102 | u8 buswidth; |
| 103 | u8 dtr : 1; | 103 | u8 dtr : 1; |
| 104 | u8 __pad : 7; | ||
| 104 | u16 opcode; | 105 | u16 opcode; |
| 105 | } cmd; | 106 | } cmd; |
| 106 | 107 | ||
| @@ -108,6 +109,7 @@ struct spi_mem_op { · 1 unmodified line | |||
| 108 | u8 nbytes; | 109 | u8 nbytes; |
| 109 | u8 buswidth; | 110 | u8 buswidth; |
| 110 | u8 dtr : 1; | 111 | u8 dtr : 1; |
| 112 | u8 __pad : 7; | ||
| 111 | u64 val; | 113 | u64 val; |
| 112 | } addr; | 114 | } addr; |
| 113 | 115 | ||
| @@ -115,12 +117,14 @@ struct spi_mem_op { · 1 unmodified line | |||
| 115 | u8 nbytes; | 117 | u8 nbytes; |
| 116 | u8 buswidth; | 118 | u8 buswidth; |
| 117 | u8 dtr : 1; | 119 | u8 dtr : 1; |
| 120 | u8 __pad : 7; | ||
| 118 | } dummy; | 121 | } dummy; |
| 119 | 122 | ||
| 120 | struct { | 123 | struct { |
| 121 | u8 buswidth; | 124 | u8 buswidth; |
| 122 | u8 dtr : 1; | 125 | u8 dtr : 1; |
| 123 | u8 ecc : 1; | 126 | u8 ecc : 1; |
| 127 | u8 __pad : 6; | ||
| 124 | enum spi_mem_data_dir dir; | 128 | enum spi_mem_data_dir dir; |
| 125 | unsigned int nbytes; | 129 | unsigned int nbytes; |
| 126 | union { | 130 | union { |
| @@ -283,6 +283,7 @@ enum tpm_chip_flags { · 282 unmodified lines | |||
| 283 | TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED = BIT(6), | 283 | TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED = BIT(6), |
| 284 | TPM_CHIP_FLAG_FIRMWARE_UPGRADE = BIT(7), | 284 | TPM_CHIP_FLAG_FIRMWARE_UPGRADE = BIT(7), |
| 285 | TPM_CHIP_FLAG_SUSPENDED = BIT(8), | 285 | TPM_CHIP_FLAG_SUSPENDED = BIT(8), |
| 286 | TPM_CHIP_FLAG_HWRNG_DISABLED = BIT(9), | ||
| 286 | }; | 287 | }; |
| 287 | 288 | ||
| 288 | #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) | 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 | if (WARN_ON(iftype >= NL80211_IFTYPE_MAX)) | 562 | if (WARN_ON(iftype >= NL80211_IFTYPE_MAX)) |
| 563 | return NULL; | 563 | return NULL; |
| 564 | 564 | ||
| 565 | if (iftype == NL80211_IFTYPE_AP_VLAN) | ||
| 566 | iftype = NL80211_IFTYPE_AP; | ||
| 567 | |||
| 565 | for (i = 0; i < sband->n_iftype_data; i++) { | 568 | for (i = 0; i < sband->n_iftype_data; i++) { |
| 566 | const struct ieee80211_sband_iftype_data *data = | 569 | const struct ieee80211_sband_iftype_data *data = |
| 567 | &sband->iftype_data[i]; | 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 | gro_normal_list(napi); | 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 | extern struct list_head offload_base; | 498 | extern struct list_head offload_base; |
| 456 | 499 | ||
| 457 | #endif /* _NET_IPV6_GRO_H */ | 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 | static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb) | 108 | static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb) |
| 109 | { | 109 | { |
| 110 | if (!sk->sk_mark && | 110 | u32 mark = READ_ONCE(sk->sk_mark); |
| 111 | READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept)) | 111 | |
| 112 | if (!mark && READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept)) | ||
| 112 | return skb->mark; | 113 | return skb->mark; |
| 113 | 114 | ||
| 114 | return sk->sk_mark; | 115 | return mark; |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | static inline int inet_request_bound_dev_if(const struct sock *sk, | 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 | ipcm_init(ipcm); | 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 | ipcm->sockc.tsflags = inet->sk.sk_tsflags; | 97 | ipcm->sockc.tsflags = inet->sk.sk_tsflags; |
| 98 | ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if); | 98 | ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if); |
| 99 | ipcm->addr = inet->inet_saddr; | 99 | ipcm->addr = inet->inet_saddr; |
| @@ -512,6 +512,7 @@ struct nft_set_elem_expr { · 511 unmodified lines | |||
| 512 | * | 512 | * |
| 513 | * @list: table set list node | 513 | * @list: table set list node |
| 514 | * @bindings: list of set bindings | 514 | * @bindings: list of set bindings |
| 515 | * @refs: internal refcounting for async set destruction | ||
| 515 | * @table: table this set belongs to | 516 | * @table: table this set belongs to |
| 516 | * @net: netnamespace this set belongs to | 517 | * @net: netnamespace this set belongs to |
| 517 | * @name: name of the set | 518 | * @name: name of the set |
| @@ -541,6 +542,7 @@ struct nft_set_elem_expr { · 23 unmodified lines | |||
| 541 | struct nft_set { | 542 | struct nft_set { |
| 542 | struct list_head list; | 543 | struct list_head list; |
| 543 | struct list_head bindings; | 544 | struct list_head bindings; |
| 545 | refcount_t refs; | ||
| 544 | struct nft_table *table; | 546 | struct nft_table *table; |
| 545 | possible_net_t net; | 547 | possible_net_t net; |
| 546 | char *name; | 548 | char *name; |
| @@ -562,7 +564,8 @@ struct nft_set { · 15 unmodified lines | |||
| 562 | struct list_head pending_update; | 564 | struct list_head pending_update; |
| 563 | /* runtime data below here */ | 565 | /* runtime data below here */ |
| 564 | const struct nft_set_ops *ops ____cacheline_aligned; | 566 | const struct nft_set_ops *ops ____cacheline_aligned; |
| 565 | u16 flags:14, | 567 | u16 flags:13, |
| 568 | dead:1, | ||
| 566 | genmask:2; | 569 | genmask:2; |
| 567 | u8 klen; | 570 | u8 klen; |
| 568 | u8 dlen; | 571 | u8 dlen; |
| @@ -596,7 +599,6 @@ struct nft_set *nft_set_lookup_global(const struct net *net, · 27 unmodified lines | |||
| 596 | 599 | ||
| 597 | struct nft_set_ext *nft_set_catchall_lookup(const struct net *net, | 600 | struct nft_set_ext *nft_set_catchall_lookup(const struct net *net, |
| 598 | const struct nft_set *set); | 601 | const struct nft_set *set); |
| 599 | void *nft_set_catchall_gc(const struct nft_set *set); | ||
| 600 | 602 | ||
| 601 | static inline unsigned long nft_set_gc_interval(const struct nft_set *set) | 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 | void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, | 815 | void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, |
| 814 | const struct nft_set *set, void *elem); | 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 | struct nft_expr_ops; | 818 | struct nft_expr_ops; |
| 873 | /** | 819 | /** |
| 874 | * struct nft_expr_type - nf_tables expression type | 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 | #endif /* IS_ENABLED(CONFIG_NF_TABLES) */ | 1504 | #endif /* IS_ENABLED(CONFIG_NF_TABLES) */ |
| 1559 | 1505 | ||
| 1560 | /* | 1506 | #define NFT_SET_ELEM_DEAD_MASK (1 << 2) |
| 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) | ||
| 1571 | 1507 | ||
| 1572 | #if defined(__LITTLE_ENDIAN_BITFIELD) | 1508 | #if defined(__LITTLE_ENDIAN_BITFIELD) |
| 1573 | #define NFT_SET_ELEM_BUSY_BIT 2 | 1509 | #define NFT_SET_ELEM_DEAD_BIT 2 |
| 1574 | #elif defined(__BIG_ENDIAN_BITFIELD) | 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 | #else | 1512 | #else |
| 1577 | #error | 1513 | #error |
| 1578 | #endif | 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 | unsigned long *word = (unsigned long *)ext; | 1518 | unsigned long *word = (unsigned long *)ext; |
| 1583 | 1519 | ||
| 1584 | BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0); | 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 | unsigned long *word = (unsigned long *)ext; | 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 | #define nft_trans_flowtable_flags(trans) \ | 1669 | #define nft_trans_flowtable_flags(trans) \ |
| 1733 | (((struct nft_trans_flowtable *)trans->data)->flags) | 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 | int __init nft_chain_filter_init(void); | 1704 | int __init nft_chain_filter_init(void); |
| 1736 | void nft_chain_filter_fini(void); | 1705 | void nft_chain_filter_fini(void); |
| 1737 | 1706 | ||
| @@ -1758,6 +1727,7 @@ struct nftables_pernet { · 20 unmodified lines | |||
| 1758 | struct mutex commit_mutex; | 1727 | struct mutex commit_mutex; |
| 1759 | u64 table_handle; | 1728 | u64 table_handle; |
| 1760 | unsigned int base_seq; | 1729 | unsigned int base_seq; |
| 1730 | unsigned int gc_seq; | ||
| 1761 | }; | 1731 | }; |
| 1762 | 1732 | ||
| 1763 | extern unsigned int nf_tables_net_id; | 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 | __be16 dport, __be16 sport, | 168 | __be16 dport, __be16 sport, |
| 169 | __u8 proto, __u8 tos, int oif) | 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 | RT_SCOPE_UNIVERSE, proto, | 172 | RT_SCOPE_UNIVERSE, proto, |
| 173 | sk ? inet_sk_flowi_flags(sk) : 0, | 173 | sk ? inet_sk_flowi_flags(sk) : 0, |
| 174 | daddr, saddr, dport, sport, sock_net_uid(net, sk)); | 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 | if (inet_sk(sk)->transparent) | 301 | if (inet_sk(sk)->transparent) |
| 302 | flow_flags |= FLOWI_FLAG_ANYSRC; | 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 | ip_sock_rt_scope(sk), protocol, flow_flags, dst, | 305 | ip_sock_rt_scope(sk), protocol, flow_flags, dst, |
| 306 | src, dport, sport, sk->sk_uid); | 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 | static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh, | 558 | static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh, |
| 559 | int hash, | 559 | u32 hash, |
| 560 | struct vxlan_rdst *rdst) | 560 | struct vxlan_rdst *rdst) |
| 561 | { | 561 | { |
| 562 | struct fib_nh_common *nhc; | 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 | if (unlikely(!nhc)) | 565 | if (unlikely(!nhc)) |
| 566 | return false; | 566 | return false; |
| 567 | 567 | ||
| @@ -194,6 +194,7 @@ struct scsi_device { · 193 unmodified lines | |||
| 194 | unsigned no_start_on_add:1; /* do not issue start on add */ | 194 | unsigned no_start_on_add:1; /* do not issue start on add */ |
| 195 | unsigned allow_restart:1; /* issue START_UNIT in error handler */ | 195 | unsigned allow_restart:1; /* issue START_UNIT in error handler */ |
| 196 | unsigned manage_start_stop:1; /* Let HLD (sd) manage start/stop */ | 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 | unsigned start_stop_pwr_cond:1; /* Set power cond. in START_STOP_UNIT */ | 198 | unsigned start_stop_pwr_cond:1; /* Set power cond. in START_STOP_UNIT */ |
| 198 | unsigned no_uld_attach:1; /* disable connecting to upper level drivers */ | 199 | unsigned no_uld_attach:1; /* disable connecting to upper level drivers */ |
| 199 | unsigned select_no_atn:1; | 200 | unsigned select_no_atn:1; |
| @@ -175,6 +175,9 @@ struct tegra_mc_icc_ops { · 174 unmodified lines | |||
| 175 | int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak); | 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 | struct tegra_mc_ops { | 181 | struct tegra_mc_ops { |
| 179 | /* | 182 | /* |
| 180 | * @probe: Callback to set up SoC-specific bits of the memory controller. This is called | 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 | __field(const void *, skaddr) | 381 | __field(const void *, skaddr) |
| 382 | __field(__u16, sport) | 382 | __field(__u16, sport) |
| 383 | __field(__u16, dport) | 383 | __field(__u16, dport) |
| 384 | __field(__u16, family) | ||
| 384 | __array(__u8, saddr, 4) | 385 | __array(__u8, saddr, 4) |
| 385 | __array(__u8, daddr, 4) | 386 | __array(__u8, daddr, 4) |
| 386 | __array(__u8, saddr_v6, 16) | 387 | __array(__u8, saddr_v6, 16) |
| @@ -396,6 +397,7 @@ TRACE_EVENT(tcp_cong_state_set, · 9 unmodified lines | |||
| 396 | 397 | ||
| 397 | __entry->sport = ntohs(inet->inet_sport); | 398 | __entry->sport = ntohs(inet->inet_sport); |
| 398 | __entry->dport = ntohs(inet->inet_dport); | 399 | __entry->dport = ntohs(inet->inet_dport); |
| 400 | __entry->family = sk->sk_family; | ||
| 399 | 401 | ||
| 400 | p32 = (__be32 *) __entry->saddr; | 402 | p32 = (__be32 *) __entry->saddr; |
| 401 | *p32 = inet->inet_saddr; | 403 | *p32 = inet->inet_saddr; |
| @@ -409,7 +411,8 @@ TRACE_EVENT(tcp_cong_state_set, · 7 unmodified lines | |||
| 409 | __entry->cong_state = ca_state; | 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 | __entry->sport, __entry->dport, | 416 | __entry->sport, __entry->dport, |
| 414 | __entry->saddr, __entry->daddr, | 417 | __entry->saddr, __entry->daddr, |
| 415 | __entry->saddr_v6, __entry->daddr_v6, | 418 | __entry->saddr_v6, __entry->daddr_v6, |
| @@ -710,9 +710,11 @@ enum { · 709 unmodified lines | |||
| 710 | TCA_FLOWER_KEY_CFM_OPT_UNSPEC, | 710 | TCA_FLOWER_KEY_CFM_OPT_UNSPEC, |
| 711 | TCA_FLOWER_KEY_CFM_MD_LEVEL, | 711 | TCA_FLOWER_KEY_CFM_MD_LEVEL, |
| 712 | TCA_FLOWER_KEY_CFM_OPCODE, | 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 | #define TCA_FLOWER_MASK_FLAGS_RANGE (1 << 0) /* Range-based match */ | 718 | #define TCA_FLOWER_MASK_FLAGS_RANGE (1 << 0) /* Range-based match */ |
| 717 | 719 | ||
| 718 | /* Match-all classifier */ | 720 | /* Match-all classifier */ |
| @@ -3470,6 +3470,8 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp, · 3469 unmodified lines | |||
| 3470 | * - use the kernel virtual address of the shared io_uring context | 3470 | * - use the kernel virtual address of the shared io_uring context |
| 3471 | * (instead of the userspace-provided address, which has to be 0UL | 3471 | * (instead of the userspace-provided address, which has to be 0UL |
| 3472 | * anyway). | 3472 | * anyway). |
| 3473 | * - use the same pgoff which the get_unmapped_area() uses to | ||
| 3474 | * calculate the page colouring. | ||
| 3473 | * For architectures without such aliasing requirements, the | 3475 | * For architectures without such aliasing requirements, the |
| 3474 | * architecture will return any suitable mapping because addr is 0. | 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 | pgoff = 0; /* has been translated to ptr above */ | 3480 | pgoff = 0; /* has been translated to ptr above */ |
| 3479 | #ifdef SHM_COLOUR | 3481 | #ifdef SHM_COLOUR |
| 3480 | addr = (uintptr_t) ptr; | 3482 | addr = (uintptr_t) ptr; |
| 3483 | pgoff = addr >> PAGE_SHIFT; | ||
| 3481 | #else | 3484 | #else |
| 3482 | addr = 0UL; | 3485 | addr = 0UL; |
| 3483 | #endif | 3486 | #endif |
| @@ -35,9 +35,11 @@ static bool io_openat_force_async(struct io_open *open) · 34 unmodified lines | |||
| 35 | { | 35 | { |
| 36 | /* | 36 | /* |
| 37 | * Don't bother trying for O_TRUNC, O_CREAT, or O_TMPFILE open, | 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 | static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) | 45 | static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) |
| @@ -28,6 +28,7 @@ · 27 unmodified lines | |||
| 28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
| 29 | #include <linux/workqueue.h> | 29 | #include <linux/workqueue.h> |
| 30 | #include <linux/kthread.h> | 30 | #include <linux/kthread.h> |
| 31 | #include <linux/completion.h> | ||
| 31 | #include <trace/events/xdp.h> | 32 | #include <trace/events/xdp.h> |
| 32 | #include <linux/btf_ids.h> | 33 | #include <linux/btf_ids.h> |
| 33 | 34 | ||
| @@ -73,6 +74,7 @@ struct bpf_cpu_map_entry { · 39 unmodified lines | |||
| 73 | struct rcu_head rcu; | 74 | struct rcu_head rcu; |
| 74 | 75 | ||
| 75 | struct work_struct kthread_stop_wq; | 76 | struct work_struct kthread_stop_wq; |
| 77 | struct completion kthread_running; | ||
| 76 | }; | 78 | }; |
| 77 | 79 | ||
| 78 | struct bpf_cpu_map { | 80 | struct bpf_cpu_map { |
| @@ -129,11 +131,17 @@ static void __cpu_map_ring_cleanup(struct ptr_ring *ring) · 50 unmodified lines | |||
| 129 | * invoked cpu_map_kthread_stop(). Catch any broken behaviour | 131 | * invoked cpu_map_kthread_stop(). Catch any broken behaviour |
| 130 | * gracefully and warn once. | 132 | * gracefully and warn once. |
| 131 | */ | 133 | */ |
| 132 | struct xdp_frame *xdpf; | 134 | void *ptr; |
| 133 | 135 | ||
| 134 | while ((xdpf = ptr_ring_consume(ring))) | 136 | while ((ptr = ptr_ring_consume(ring))) { |
| 135 | if (WARN_ON_ONCE(xdpf)) | 137 | WARN_ON_ONCE(1); |
| 136 | xdp_return_frame(xdpf); | 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 | static void put_cpu_map_entry(struct bpf_cpu_map_entry *rcpu) | 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 | static void cpu_map_kthread_stop(struct work_struct *work) | 161 | static void cpu_map_kthread_stop(struct work_struct *work) |
| 154 | { | 162 | { |
| 155 | struct bpf_cpu_map_entry *rcpu; | 163 | struct bpf_cpu_map_entry *rcpu; |
| 156 | int err; | ||
| 157 | 164 | ||
| 158 | rcpu = container_of(work, struct bpf_cpu_map_entry, kthread_stop_wq); | 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 | rcu_barrier(); | 170 | rcu_barrier(); |
| 164 | 171 | ||
| 165 | /* kthread_stop will wake_up_process and wait for it to complete */ | 172 | /* kthread_stop will wake_up_process and wait for it to complete */ |
| 166 | err = kthread_stop(rcpu->kthread); | 173 | 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 | } | ||
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | static void cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu, | 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 | return nframes; | 298 | return nframes; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | |||
| 302 | static int cpu_map_kthread_run(void *data) | 301 | static int cpu_map_kthread_run(void *data) |
| 303 | { | 302 | { |
| 304 | struct bpf_cpu_map_entry *rcpu = data; | 303 | struct bpf_cpu_map_entry *rcpu = data; |
| 305 | 304 | ||
| 305 | complete(&rcpu->kthread_running); | ||
| 306 | set_current_state(TASK_INTERRUPTIBLE); | 306 | set_current_state(TASK_INTERRUPTIBLE); |
| 307 | 307 | ||
| 308 | /* When kthread gives stop order, then rcpu have been disconnected | 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 | goto free_ptr_ring; | 467 | goto free_ptr_ring; |
| 468 | 468 | ||
| 469 | /* Setup kthread */ | 469 | /* Setup kthread */ |
| 470 | init_completion(&rcpu->kthread_running); | ||
| 470 | rcpu->kthread = kthread_create_on_node(cpu_map_kthread_run, rcpu, numa, | 471 | rcpu->kthread = kthread_create_on_node(cpu_map_kthread_run, rcpu, numa, |
| 471 | "cpumap/%d/map:%d", cpu, | 472 | "cpumap/%d/map:%d", cpu, |
| 472 | map->id); | 473 | map->id); |
| @@ -480,6 +481,12 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value, · 7 unmodified lines | |||
| 480 | kthread_bind(rcpu->kthread, cpu); | 481 | kthread_bind(rcpu->kthread, cpu); |
| 481 | wake_up_process(rcpu->kthread); | 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 | return rcpu; | 490 | return rcpu; |
| 484 | 491 | ||
| 485 | free_prog: | 492 | free_prog: |
| @@ -1166,7 +1166,7 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, · 1165 unmodified lines | |||
| 1166 | int error; | 1166 | int error; |
| 1167 | 1167 | ||
| 1168 | if (!hibernation_available()) | 1168 | if (!hibernation_available()) |
| 1169 | return 0; | 1169 | return n; |
| 1170 | 1170 | ||
| 1171 | if (len && buf[len-1] == '\n') | 1171 | if (len && buf[len-1] == '\n') |
| 1172 | len--; | 1172 | len--; |
| @@ -661,8 +661,7 @@ static DEFINE_PER_CPU(int, bpf_trace_nest_level); · 660 unmodified lines | |||
| 661 | BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map, | 661 | BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map, |
| 662 | u64, flags, void *, data, u64, size) | 662 | u64, flags, void *, data, u64, size) |
| 663 | { | 663 | { |
| 664 | struct bpf_trace_sample_data *sds = this_cpu_ptr(&bpf_trace_sds); | 664 | struct bpf_trace_sample_data *sds; |
| 665 | int nest_level = this_cpu_inc_return(bpf_trace_nest_level); | ||
| 666 | struct perf_raw_record raw = { | 665 | struct perf_raw_record raw = { |
| 667 | .frag = { | 666 | .frag = { |
| 668 | .size = size, | 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 | struct perf_sample_data *sd; | 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 | if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(sds->sds))) { | 678 | if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(sds->sds))) { |
| 676 | err = -EBUSY; | 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 | perf_sample_save_raw_data(sd, &raw); | 691 | perf_sample_save_raw_data(sd, &raw); |
| 689 | 692 | ||
| 690 | err = __bpf_perf_event_output(regs, map, flags, sd); | 693 | err = __bpf_perf_event_output(regs, map, flags, sd); |
| 691 | |||
| 692 | out: | 694 | out: |
| 693 | this_cpu_dec(bpf_trace_nest_level); | 695 | this_cpu_dec(bpf_trace_nest_level); |
| 696 | preempt_enable(); | ||
| 694 | return err; | 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 | u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size, | 718 | u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size, |
| 716 | void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy) | 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 | struct perf_raw_frag frag = { | 721 | struct perf_raw_frag frag = { |
| 720 | .copy = ctx_copy, | 722 | .copy = ctx_copy, |
| 721 | .size = ctx_size, | 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 | struct perf_sample_data *sd; | 735 | struct perf_sample_data *sd; |
| 734 | struct pt_regs *regs; | 736 | struct pt_regs *regs; |
| 737 | int nest_level; | ||
| 735 | u64 ret; | 738 | u64 ret; |
| 736 | 739 | ||
| 740 | preempt_disable(); | ||
| 741 | nest_level = this_cpu_inc_return(bpf_event_output_nest_level); | ||
| 742 | |||
| 737 | if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(bpf_misc_sds.sds))) { | 743 | if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(bpf_misc_sds.sds))) { |
| 738 | ret = -EBUSY; | 744 | ret = -EBUSY; |
| 739 | goto out; | 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 | ret = __bpf_perf_event_output(regs, map, flags, sd); | 754 | ret = __bpf_perf_event_output(regs, map, flags, sd); |
| 749 | out: | 755 | out: |
| 750 | this_cpu_dec(bpf_event_output_nest_level); | 756 | this_cpu_dec(bpf_event_output_nest_level); |
| 757 | preempt_enable(); | ||
| 751 | return ret; | 758 | return ret; |
| 752 | } | 759 | } |
| 753 | 760 | ||
| @@ -52,6 +52,7 @@ · 51 unmodified lines | |||
| 52 | #include <linux/sched/debug.h> | 52 | #include <linux/sched/debug.h> |
| 53 | #include <linux/nmi.h> | 53 | #include <linux/nmi.h> |
| 54 | #include <linux/kvm_para.h> | 54 | #include <linux/kvm_para.h> |
| 55 | #include <linux/delay.h> | ||
| 55 | 56 | ||
| 56 | #include "workqueue_internal.h" | 57 | #include "workqueue_internal.h" |
| 57 | 58 | ||
| @@ -338,8 +339,10 @@ static cpumask_var_t *wq_numa_possible_cpumask; · 280 unmodified lines | |||
| 338 | * Per-cpu work items which run for longer than the following threshold are | 339 | * Per-cpu work items which run for longer than the following threshold are |
| 339 | * automatically considered CPU intensive and excluded from concurrency | 340 | * automatically considered CPU intensive and excluded from concurrency |
| 340 | * management to prevent them from noticeably delaying other per-cpu work items. | 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 | module_param_named(cpu_intensive_thresh_us, wq_cpu_intensive_thresh_us, ulong, 0644); | 346 | module_param_named(cpu_intensive_thresh_us, wq_cpu_intensive_thresh_us, ulong, 0644); |
| 344 | 347 | ||
| 345 | static bool wq_disable_numa; | 348 | static bool wq_disable_numa; |
| @@ -6513,6 +6516,42 @@ void __init workqueue_init_early(void) · 6167 unmodified lines | |||
| 6513 | !system_freezable_power_efficient_wq); | 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 | * workqueue_init - bring workqueue subsystem fully online | 6556 | * workqueue_init - bring workqueue subsystem fully online |
| 6518 | * | 6557 | * |
| @@ -6528,6 +6567,8 @@ void __init workqueue_init(void) · 9 unmodified lines | |||
| 6528 | struct worker_pool *pool; | 6567 | struct worker_pool *pool; |
| 6529 | int cpu, bkt; | 6568 | int cpu, bkt; |
| 6530 | 6569 | ||
| 6570 | wq_cpu_intensive_thresh_init(); | ||
| 6571 | |||
| 6531 | /* | 6572 | /* |
| 6532 | * It'd be simpler to initialize NUMA in workqueue_init_early() but | 6573 | * It'd be simpler to initialize NUMA in workqueue_init_early() but |
| 6533 | * CPU to node mapping may not be available that early on some | 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 | help | 1200 | help |
| 1201 | Say Y here to enable reporting of concurrency-managed per-cpu work | 1201 | Say Y here to enable reporting of concurrency-managed per-cpu work |
| 1202 | items that hog CPUs for longer than | 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 | detects and excludes them from concurrency management to prevent | 1204 | detects and excludes them from concurrency management to prevent |
| 1205 | them from stalling other per-cpu work items. Occassional | 1205 | them from stalling other per-cpu work items. Occassional |
| 1206 | triggering may not necessarily indicate a problem. Repeated | 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 | obj-$(CONFIG_TEST_DYNAMIC_DEBUG) += test_dynamic_debug.o | 82 | obj-$(CONFIG_TEST_DYNAMIC_DEBUG) += test_dynamic_debug.o |
| 83 | obj-$(CONFIG_TEST_PRINTF) += test_printf.o | 83 | obj-$(CONFIG_TEST_PRINTF) += test_printf.o |
| 84 | obj-$(CONFIG_TEST_SCANF) += test_scanf.o | 84 | obj-$(CONFIG_TEST_SCANF) += test_scanf.o |
| 85 | |||
| 85 | obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o | 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 | obj-$(CONFIG_TEST_UUID) += test_uuid.o | 92 | obj-$(CONFIG_TEST_UUID) += test_uuid.o |
| 87 | obj-$(CONFIG_TEST_XARRAY) += test_xarray.o | 93 | obj-$(CONFIG_TEST_XARRAY) += test_xarray.o |
| 88 | obj-$(CONFIG_TEST_MAPLE_TREE) += test_maple_tree.o | 94 | obj-$(CONFIG_TEST_MAPLE_TREE) += test_maple_tree.o |
| @@ -45,6 +45,7 @@ EXPORT_SYMBOL(cpumask_next_wrap); · 44 unmodified lines | |||
| 45 | * alloc_cpumask_var_node - allocate a struct cpumask on a given node | 45 | * alloc_cpumask_var_node - allocate a struct cpumask on a given node |
| 46 | * @mask: pointer to cpumask_var_t where the cpumask is returned | 46 | * @mask: pointer to cpumask_var_t where the cpumask is returned |
| 47 | * @flags: GFP_ flags | 47 | * @flags: GFP_ flags |
| 48 | * @node: memory node from which to allocate or %NUMA_NO_NODE | ||
| 48 | * | 49 | * |
| 49 | * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is | 50 | * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is |
| 50 | * a nop returning a constant 1 (in <linux/cpumask.h>) | 51 | * a nop returning a constant 1 (in <linux/cpumask.h>) |
| @@ -157,7 +158,9 @@ EXPORT_SYMBOL(cpumask_local_spread); · 106 unmodified lines | |||
| 157 | static DEFINE_PER_CPU(int, distribute_cpu_mask_prev); | 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 | * Iterated calls using the same srcp1 and srcp2 will be distributed within | 165 | * Iterated calls using the same srcp1 and srcp2 will be distributed within |
| 163 | * their intersection. | 166 | * their intersection. |
| @@ -1148,7 +1148,7 @@ static ssize_t extract_user_to_sg(struct iov_iter *iter, · 1147 unmodified lines | |||
| 1148 | 1148 | ||
| 1149 | failed: | 1149 | failed: |
| 1150 | while (sgtable->nents > sgtable->orig_nents) | 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 | return res; | 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 | static void __init test_bitmap_const_eval(void) | 1168 | static void __init test_bitmap_const_eval(void) |
| 1165 | { | 1169 | { |
| 1166 | DECLARE_BITMAP(bitmap, BITS_PER_LONG); | 1170 | DECLARE_BITMAP(bitmap, BITS_PER_LONG); |
| @@ -1186,11 +1190,7 @@ static void __init test_bitmap_const_eval(void) · 19 unmodified lines | |||
| 1186 | * the compiler is fixed. | 1190 | * the compiler is fixed. |
| 1187 | */ | 1191 | */ |
| 1188 | bitmap_clear(bitmap, 0, BITS_PER_LONG); | 1192 | bitmap_clear(bitmap, 0, BITS_PER_LONG); |
| 1189 | #if defined(__s390__) && defined(__clang__) | ||
| 1190 | if (!const_test_bit(7, bitmap)) | ||
| 1191 | #else | ||
| 1192 | if (!test_bit(7, bitmap)) | 1193 | if (!test_bit(7, bitmap)) |
| 1193 | #endif | ||
| 1194 | bitmap_set(bitmap, 5, 2); | 1194 | bitmap_set(bitmap, 5, 2); |
| 1195 | 1195 | ||
| 1196 | /* Equals to `unsigned long bitopvar = BIT(20)` */ | 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 | * Check if the pageblock has already been marked skipped. | 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 | * COMPACT_CLUSTER_MAX at a time so the second call must | 916 | * COMPACT_CLUSTER_MAX at a time so the second call must |
| 917 | * not falsely conclude that the block should be skipped. | 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 | if (!isolation_suitable(cc, page)) { | 921 | if (!isolation_suitable(cc, page)) { |
| 921 | low_pfn = end_pfn; | 922 | low_pfn = end_pfn; |
| 922 | folio = NULL; | 923 | folio = NULL; |
| @@ -2002,7 +2003,8 @@ static isolate_migrate_t isolate_migratepages(struct compact_control *cc) · 1079 unmodified lines | |||
| 2002 | * before making it "skip" so other compaction instances do | 2003 | * before making it "skip" so other compaction instances do |
| 2003 | * not scan the same block. | 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 | !fast_find_block && !isolation_suitable(cc, page)) | 2008 | !fast_find_block && !isolation_suitable(cc, page)) |
| 2007 | continue; | 2009 | continue; |
| 2008 | 2010 | ||
| @@ -273,6 +273,7 @@ struct damos_filter *damos_new_filter(enum damos_filter_type type, · 272 unmodified lines | |||
| 273 | return NULL; | 273 | return NULL; |
| 274 | filter->type = type; | 274 | filter->type = type; |
| 275 | filter->matching = matching; | 275 | filter->matching = matching; |
| 276 | INIT_LIST_HEAD(&filter->list); | ||
| 276 | return filter; | 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 | unsigned int order) { } | 1579 | unsigned int order) { } |
| 1580 | #endif | 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 | 1609 | * Remove hugetlb folio from lists. |
| 1584 | * as just a compound page. | 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 | * A reference is held on the folio, except in the case of demote. | 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 | 1643 | * We can only clear the hugetlb destructor after allocating vmemmap |
| 1616 | * | 1644 | * pages. Otherwise, someone (memory error handling) may try to write |
| 1617 | * For non-gigantic pages set the destructor to the normal compound | 1645 | * to tail struct pages. |
| 1618 | * page dtor. This is needed in case someone takes an additional | 1646 | */ |
| 1619 | * temporary ref to the page, and freeing is delayed until they drop | 1647 | if (!folio_test_hugetlb_vmemmap_optimized(folio)) |
| 1620 | * their reference. | 1648 | __clear_hugetlb_destructor(h, folio); |
| 1621 | * | 1649 | |
| 1622 | * For gigantic pages set the destructor to the null dtor. This | 1650 | /* |
| 1623 | * destructor will never be called. Before freeing the gigantic | 1651 | * In the case of demote we do not ref count the page as it will soon |
| 1624 | * page destroy_compound_gigantic_folio will turn the folio into a | 1652 | * be turned into a page of smaller size. |
| 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. | ||
| 1633 | */ | 1653 | */ |
| 1634 | if (!demote) | 1654 | if (!demote) |
| 1635 | folio_ref_unfreeze(folio, 1); | 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 | h->nr_huge_pages--; | 1657 | h->nr_huge_pages--; |
| 1642 | h->nr_huge_pages_node[nid]--; | 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 | int i; | 1722 | int i; |
| 1707 | struct page *subpage; | 1723 | struct page *subpage; |
| 1724 | bool clear_dtor = folio_test_hugetlb_vmemmap_optimized(folio); | ||
| 1708 | 1725 | ||
| 1709 | if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported()) | 1726 | if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported()) |
| 1710 | return; | 1727 | return; |
| @@ -1735,6 +1752,16 @@ static void __update_and_free_hugetlb_folio(struct hstate *h, · 24 unmodified lines | |||
| 1735 | if (unlikely(folio_test_hwpoison(folio))) | 1752 | if (unlikely(folio_test_hwpoison(folio))) |
| 1736 | folio_clear_hugetlb_hwpoison(folio); | 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 | for (i = 0; i < pages_per_huge_page(h); i++) { | 1765 | for (i = 0; i < pages_per_huge_page(h); i++) { |
| 1739 | subpage = folio_page(folio, i); | 1766 | subpage = folio_page(folio, i); |
| 1740 | subpage->flags &= ~(1 << PG_locked | 1 << PG_error | | 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 | anon_vma->root == vma->anon_vma->root) { | 2784 | anon_vma->root == vma->anon_vma->root) { |
| 2785 | return page; /* still no need to copy it */ | 2785 | return page; /* still no need to copy it */ |
| 2786 | } | 2786 | } |
| 2787 | if (PageHWPoison(page)) | ||
| 2788 | return ERR_PTR(-EHWPOISON); | ||
| 2787 | if (!PageUptodate(page)) | 2789 | if (!PageUptodate(page)) |
| 2788 | return page; /* let do_swap_page report the error */ | 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 | struct folio *folio; | 2467 | struct folio *folio; |
| 2468 | struct page *p; | 2468 | struct page *p; |
| 2469 | int ret = -EBUSY; | 2469 | int ret = -EBUSY, ghp; |
| 2470 | unsigned long count = 1; | 2470 | unsigned long count = 1; |
| 2471 | bool huge = false; | 2471 | bool huge = false; |
| 2472 | static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL, | 2472 | static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL, |
| @@ -2499,6 +2499,13 @@ int unpoison_memory(unsigned long pfn) · 26 unmodified lines | |||
| 2499 | goto unlock_mutex; | 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 | if (folio_mapped(folio)) { | 2509 | if (folio_mapped(folio)) { |
| 2503 | unpoison_pr_info("Unpoison: Someone maps the hwpoison page %#lx\n", | 2510 | unpoison_pr_info("Unpoison: Someone maps the hwpoison page %#lx\n", |
| 2504 | pfn, &unpoison_rs); | 2511 | pfn, &unpoison_rs); |
| @@ -2511,32 +2518,28 @@ int unpoison_memory(unsigned long pfn) · 6 unmodified lines | |||
| 2511 | goto unlock_mutex; | 2518 | goto unlock_mutex; |
| 2512 | } | 2519 | } |
| 2513 | 2520 | ||
| 2514 | if (folio_test_slab(folio) || PageTable(&folio->page) || folio_test_reserved(folio)) | 2521 | ghp = get_hwpoison_page(p, MF_UNPOISON); |
| 2515 | goto unlock_mutex; | 2522 | if (!ghp) { |
| 2516 | |||
| 2517 | ret = get_hwpoison_page(p, MF_UNPOISON); | ||
| 2518 | if (!ret) { | ||
| 2519 | if (PageHuge(p)) { | 2523 | if (PageHuge(p)) { |
| 2520 | huge = true; | 2524 | huge = true; |
| 2521 | count = folio_free_raw_hwp(folio, false); | 2525 | count = folio_free_raw_hwp(folio, false); |
| 2522 | if (count == 0) { | 2526 | if (count == 0) |
| 2523 | ret = -EBUSY; | ||
| 2524 | goto unlock_mutex; | 2527 | goto unlock_mutex; |
| 2525 | } | ||
| 2526 | } | 2528 | } |
| 2527 | ret = folio_test_clear_hwpoison(folio) ? 0 : -EBUSY; | 2529 | ret = folio_test_clear_hwpoison(folio) ? 0 : -EBUSY; |
| 2528 | } else if (ret < 0) { | 2530 | } else if (ghp < 0) { |
| 2529 | if (ret == -EHWPOISON) { | 2531 | if (ghp == -EHWPOISON) { |
| 2530 | ret = put_page_back_buddy(p) ? 0 : -EBUSY; | 2532 | ret = put_page_back_buddy(p) ? 0 : -EBUSY; |
| 2531 | } else | 2533 | } else { |
| 2534 | ret = ghp; | ||
| 2532 | unpoison_pr_info("Unpoison: failed to grab page %#lx\n", | 2535 | unpoison_pr_info("Unpoison: failed to grab page %#lx\n", |
| 2533 | pfn, &unpoison_rs); | 2536 | pfn, &unpoison_rs); |
| 2537 | } | ||
| 2534 | } else { | 2538 | } else { |
| 2535 | if (PageHuge(p)) { | 2539 | if (PageHuge(p)) { |
| 2536 | huge = true; | 2540 | huge = true; |
| 2537 | count = folio_free_raw_hwp(folio, false); | 2541 | count = folio_free_raw_hwp(folio, false); |
| 2538 | if (count == 0) { | 2542 | if (count == 0) { |
| 2539 | ret = -EBUSY; | ||
| 2540 | folio_put(folio); | 2543 | folio_put(folio); |
| 2541 | goto unlock_mutex; | 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 | if (mmap_read_lock_killable(mm)) | 5705 | if (mmap_read_lock_killable(mm)) |
| 5706 | return 0; | 5706 | return 0; |
| 5707 | 5707 | ||
| 5708 | /* Untag the address before looking up the VMA */ | ||
| 5709 | addr = untagged_addr_remote(mm, addr); | ||
| 5710 | |||
| 5708 | /* Avoid triggering the temporary warning in __get_user_pages */ | 5711 | /* Avoid triggering the temporary warning in __get_user_pages */ |
| 5709 | if (!vma_lookup(mm, addr) && !expand_stack(mm, addr)) | 5712 | if (!vma_lookup(mm, addr) && !expand_stack(mm, addr)) |
| 5710 | return 0; | 5713 | return 0; |
| @@ -1746,7 +1746,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, · 1745 unmodified lines | |||
| 1746 | struct page *swapcache; | 1746 | struct page *swapcache; |
| 1747 | spinlock_t *ptl; | 1747 | spinlock_t *ptl; |
| 1748 | pte_t *pte, new_pte, old_pte; | 1748 | pte_t *pte, new_pte, old_pte; |
| 1749 | bool hwposioned = false; | 1749 | bool hwpoisoned = PageHWPoison(page); |
| 1750 | int ret = 1; | 1750 | int ret = 1; |
| 1751 | 1751 | ||
| 1752 | swapcache = page; | 1752 | swapcache = page; |
| @@ -1754,7 +1754,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, · 1 unmodified line | |||
| 1754 | if (unlikely(!page)) | 1754 | if (unlikely(!page)) |
| 1755 | return -ENOMEM; | 1755 | return -ENOMEM; |
| 1756 | else if (unlikely(PTR_ERR(page) == -EHWPOISON)) | 1756 | else if (unlikely(PTR_ERR(page) == -EHWPOISON)) |
| 1757 | hwposioned = true; | 1757 | hwpoisoned = true; |
| 1758 | 1758 | ||
| 1759 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); | 1759 | pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); |
| 1760 | if (unlikely(!pte || !pte_same_as_swp(ptep_get(pte), | 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 | old_pte = ptep_get(pte); | 1766 | old_pte = ptep_get(pte); |
| 1767 | 1767 | ||
| 1768 | if (unlikely(hwposioned || !PageUptodate(page))) { | 1768 | if (unlikely(hwpoisoned || !PageUptodate(page))) { |
| 1769 | swp_entry_t swp_entry; | 1769 | swp_entry_t swp_entry; |
| 1770 | 1770 | ||
| 1771 | dec_mm_counter(vma->vm_mm, MM_SWAPENTS); | 1771 | dec_mm_counter(vma->vm_mm, MM_SWAPENTS); |
| 1772 | if (hwposioned) { | 1772 | if (hwpoisoned) { |
| 1773 | swp_entry = make_hwpoison_entry(swapcache); | 1773 | swp_entry = make_hwpoison_entry(swapcache); |
| 1774 | page = swapcache; | 1774 | page = swapcache; |
| 1775 | } else { | 1775 | } else { |
| @@ -1798,6 +1798,7 @@ static void replace_sub_page(struct size_class *class, struct zspage *zspage, · 1797 unmodified lines | |||
| 1798 | 1798 | ||
| 1799 | static bool zs_page_isolate(struct page *page, isolate_mode_t mode) | 1799 | static bool zs_page_isolate(struct page *page, isolate_mode_t mode) |
| 1800 | { | 1800 | { |
| 1801 | struct zs_pool *pool; | ||
| 1801 | struct zspage *zspage; | 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 | VM_BUG_ON_PAGE(PageIsolated(page), page); | 1808 | VM_BUG_ON_PAGE(PageIsolated(page), page); |
| 1808 | 1809 | ||
| 1809 | zspage = get_zspage(page); | 1810 | zspage = get_zspage(page); |
| 1810 | migrate_write_lock(zspage); | 1811 | pool = zspage->pool; |
| 1812 | spin_lock(&pool->lock); | ||
| 1811 | inc_zspage_isolation(zspage); | 1813 | inc_zspage_isolation(zspage); |
| 1812 | migrate_write_unlock(zspage); | 1814 | spin_unlock(&pool->lock); |
| 1813 | 1815 | ||
| 1814 | return true; | 1816 | return true; |
| 1815 | } | 1817 | } |
| @@ -1875,12 +1877,12 @@ static int zs_page_migrate(struct page *newpage, struct page *page, · 59 unmodified lines | |||
| 1875 | kunmap_atomic(s_addr); | 1877 | kunmap_atomic(s_addr); |
| 1876 | 1878 | ||
| 1877 | replace_sub_page(class, zspage, newpage, page); | 1879 | replace_sub_page(class, zspage, newpage, page); |
| 1880 | dec_zspage_isolation(zspage); | ||
| 1878 | /* | 1881 | /* |
| 1879 | * Since we complete the data copy and set up new zspage structure, | 1882 | * Since we complete the data copy and set up new zspage structure, |
| 1880 | * it's okay to release the pool's lock. | 1883 | * it's okay to release the pool's lock. |
| 1881 | */ | 1884 | */ |
| 1882 | spin_unlock(&pool->lock); | 1885 | spin_unlock(&pool->lock); |
| 1883 | dec_zspage_isolation(zspage); | ||
| 1884 | migrate_write_unlock(zspage); | 1886 | migrate_write_unlock(zspage); |
| 1885 | 1887 | ||
| 1886 | get_page(newpage); | 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 | static void zs_page_putback(struct page *page) | 1900 | static void zs_page_putback(struct page *page) |
| 1899 | { | 1901 | { |
| 1902 | struct zs_pool *pool; | ||
| 1900 | struct zspage *zspage; | 1903 | struct zspage *zspage; |
| 1901 | 1904 | ||
| 1902 | VM_BUG_ON_PAGE(!PageIsolated(page), page); | 1905 | VM_BUG_ON_PAGE(!PageIsolated(page), page); |
| 1903 | 1906 | ||
| 1904 | zspage = get_zspage(page); | 1907 | zspage = get_zspage(page); |
| 1905 | migrate_write_lock(zspage); | 1908 | pool = zspage->pool; |
| 1909 | spin_lock(&pool->lock); | ||
| 1906 | dec_zspage_isolation(zspage); | 1910 | dec_zspage_isolation(zspage); |
| 1907 | migrate_write_unlock(zspage); | 1911 | spin_unlock(&pool->lock); |
| 1908 | } | 1912 | } |
| 1909 | 1913 | ||
| 1910 | static const struct movable_operations zsmalloc_mops = { | 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 | dev->name); | 384 | dev->name); |
| 385 | vlan_vid_add(dev, htons(ETH_P_8021Q), 0); | 385 | vlan_vid_add(dev, htons(ETH_P_8021Q), 0); |
| 386 | } | 386 | } |
| 387 | if (event == NETDEV_DOWN && | 387 | if (event == NETDEV_DOWN) |
| 388 | (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) | ||
| 389 | vlan_vid_del(dev, htons(ETH_P_8021Q), 0); | 388 | vlan_vid_del(dev, htons(ETH_P_8021Q), 0); |
| 390 | 389 | ||
| 391 | vlan_info = rtnl_dereference(dev->vlan_info); | 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 | skb->dev = dev; | 866 | skb->dev = dev; |
| 867 | skb->priority = sk->sk_priority; | 867 | skb->priority = sk->sk_priority; |
| 868 | skb->mark = sk->sk_mark; | 868 | skb->mark = READ_ONCE(sk->sk_mark); |
| 869 | skb->tstamp = sockc.transmit_time; | 869 | skb->tstamp = sockc.transmit_time; |
| 870 | 870 | ||
| 871 | skb_setup_tx_timestamp(skb, sockc.tsflags); | 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 | int ret; | 3334 | int ret; |
| 3335 | 3335 | ||
| 3336 | dout("%s lreq %p linger_id %llu\n", __func__, lreq, lreq->linger_id); | 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 | return ret ?: lreq->reg_commit_error; | 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 | dout("%s lreq %p linger_id %llu\n", __func__, lreq, lreq->linger_id); | 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 | left = wait_for_completion_killable_timeout(&lreq->notify_finish_wait, |
| 3347 | return ret ?: lreq->notify_finish_error; | 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 | linger_submit(lreq); | 4903 | linger_submit(lreq); |
| 4897 | ret = linger_reg_commit_wait(lreq); | 4904 | ret = linger_reg_commit_wait(lreq); |
| 4898 | if (!ret) | 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 | else | 4908 | else |
| 4901 | dout("lreq %p failed to initiate notify %d\n", lreq, ret); | 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 | return ERR_PTR(-EPERM); | 496 | return ERR_PTR(-EPERM); |
| 497 | 497 | ||
| 498 | nla_for_each_nested(nla, nla_stgs, rem) { | 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 | nr_maps++; | 502 | nr_maps++; |
| 503 | } | ||
| 501 | } | 504 | } |
| 502 | 505 | ||
| 503 | diag = kzalloc(struct_size(diag, maps, nr_maps), GFP_KERNEL); | 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 | if (unlikely(data_end > data_hard_end)) | 4116 | if (unlikely(data_end > data_hard_end)) |
| 4117 | return -EINVAL; | 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 | if (unlikely(data_end < xdp->data + ETH_HLEN)) | 4119 | if (unlikely(data_end < xdp->data + ETH_HLEN)) |
| 4126 | return -EINVAL; | 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 | br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); | 5140 | br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); |
| 5141 | if (br_spec) { | 5141 | if (br_spec) { |
| 5142 | nla_for_each_nested(attr, br_spec, rem) { | 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 | if (nla_len(attr) < sizeof(flags)) | 5144 | if (nla_len(attr) < sizeof(flags)) |
| 5145 | return -EINVAL; | 5145 | return -EINVAL; |
| 5146 | 5146 | ||
| 5147 | have_flags = true; | 5147 | have_flags = true; |
| 5148 | flags = nla_get_u16(attr); | 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 | int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock) | 1121 | int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock) |
| 1122 | { | 1122 | { |
| 1123 | int ret; | ||
| 1124 | |||
| 1123 | static const struct strp_callbacks cb = { | 1125 | static const struct strp_callbacks cb = { |
| 1124 | .rcv_msg = sk_psock_strp_read, | 1126 | .rcv_msg = sk_psock_strp_read, |
| 1125 | .read_sock_done = sk_psock_strp_read_done, | 1127 | .read_sock_done = sk_psock_strp_read_done, |
| 1126 | .parse_msg = sk_psock_strp_parse, | 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 | void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock) | 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 | static void sk_psock_done_strp(struct sk_psock *psock) | 1160 | static void sk_psock_done_strp(struct sk_psock *psock) |
| 1155 | { | 1161 | { |
| 1156 | /* Parser has been stopped */ | 1162 | /* Parser has been stopped */ |
| 1157 | if (psock->progs.stream_parser) | 1163 | if (sk_psock_test_state(psock, SK_PSOCK_RX_STRP_ENABLED)) |
| 1158 | strp_done(&psock->strp); | 1164 | strp_done(&psock->strp); |
| 1159 | } | 1165 | } |
| 1160 | #else | 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 | struct __kernel_sock_timeval tv; | 430 | struct __kernel_sock_timeval tv; |
| 431 | int err = sock_copy_user_timeval(&tv, optval, optlen, old_timeval); | 431 | int err = sock_copy_user_timeval(&tv, optval, optlen, old_timeval); |
| 432 | long val; | ||
| 432 | 433 | ||
| 433 | if (err) | 434 | if (err) |
| 434 | return err; | 435 | return err; |
| @@ -439,7 +440,7 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen, · 4 unmodified lines | |||
| 439 | if (tv.tv_sec < 0) { | 440 | if (tv.tv_sec < 0) { |
| 440 | static int warned __read_mostly; | 441 | static int warned __read_mostly; |
| 441 | 442 | ||
| 442 | *timeo_p = 0; | 443 | WRITE_ONCE(*timeo_p, 0); |
| 443 | if (warned < 10 && net_ratelimit()) { | 444 | if (warned < 10 && net_ratelimit()) { |
| 444 | warned++; | 445 | warned++; |
| 445 | pr_info("%s: `%s' (pid %d) tries to set negative timeout\n", | 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 | return 0; | 449 | return 0; |
| 449 | } | 450 | } |
| 450 | *timeo_p = MAX_SCHEDULE_TIMEOUT; | 451 | val = MAX_SCHEDULE_TIMEOUT; |
| 451 | if (tv.tv_sec == 0 && tv.tv_usec == 0) | 452 | if ((tv.tv_sec || tv.tv_usec) && |
| 452 | return 0; | 453 | (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1))) |
| 453 | if (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1)) | 454 | val = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec, |
| 454 | *timeo_p = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec, USEC_PER_SEC / HZ); | 455 | USEC_PER_SEC / HZ); |
| 456 | WRITE_ONCE(*timeo_p, val); | ||
| 455 | return 0; | 457 | return 0; |
| 456 | } | 458 | } |
| 457 | 459 | ||
| @@ -804,7 +806,7 @@ EXPORT_SYMBOL(sock_no_linger); · 346 unmodified lines | |||
| 804 | void sock_set_priority(struct sock *sk, u32 priority) | 806 | void sock_set_priority(struct sock *sk, u32 priority) |
| 805 | { | 807 | { |
| 806 | lock_sock(sk); | 808 | lock_sock(sk); |
| 807 | sk->sk_priority = priority; | 809 | WRITE_ONCE(sk->sk_priority, priority); |
| 808 | release_sock(sk); | 810 | release_sock(sk); |
| 809 | } | 811 | } |
| 810 | EXPORT_SYMBOL(sock_set_priority); | 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 | lock_sock(sk); | 816 | lock_sock(sk); |
| 815 | if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1) | 817 | if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1) |
| 816 | sk->sk_sndtimeo = secs * HZ; | 818 | WRITE_ONCE(sk->sk_sndtimeo, secs * HZ); |
| 817 | else | 819 | else |
| 818 | sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; | 820 | WRITE_ONCE(sk->sk_sndtimeo, MAX_SCHEDULE_TIMEOUT); |
| 819 | release_sock(sk); | 821 | release_sock(sk); |
| 820 | } | 822 | } |
| 821 | EXPORT_SYMBOL(sock_set_sndtimeo); | 823 | EXPORT_SYMBOL(sock_set_sndtimeo); |
| @@ -988,7 +990,7 @@ EXPORT_SYMBOL(sock_set_rcvbuf); · 166 unmodified lines | |||
| 988 | static void __sock_set_mark(struct sock *sk, u32 val) | 990 | static void __sock_set_mark(struct sock *sk, u32 val) |
| 989 | { | 991 | { |
| 990 | if (val != sk->sk_mark) { | 992 | if (val != sk->sk_mark) { |
| 991 | sk->sk_mark = val; | 993 | WRITE_ONCE(sk->sk_mark, val); |
| 992 | sk_dst_reset(sk); | 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 | bytes = round_down(bytes, PAGE_SIZE); | 1009 | bytes = round_down(bytes, PAGE_SIZE); |
| 1008 | 1010 | ||
| 1009 | WARN_ON(bytes > sk->sk_reserved_mem); | 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 | sk_mem_reclaim(sk); | 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 | sk->sk_forward_alloc += pages << PAGE_SHIFT; | 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 | return 0; | 1052 | return 0; |
| 1050 | } | 1053 | } |
| @@ -1213,7 +1216,7 @@ set_sndbuf: · 162 unmodified lines | |||
| 1213 | if ((val >= 0 && val <= 6) || | 1216 | if ((val >= 0 && val <= 6) || |
| 1214 | sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) || | 1217 | sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) || |
| 1215 | sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) | 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 | else | 1220 | else |
| 1218 | ret = -EPERM; | 1221 | ret = -EPERM; |
| 1219 | break; | 1222 | break; |
| @@ -1438,7 +1441,8 @@ set_sndbuf: · 218 unmodified lines | |||
| 1438 | cmpxchg(&sk->sk_pacing_status, | 1441 | cmpxchg(&sk->sk_pacing_status, |
| 1439 | SK_PACING_NONE, | 1442 | SK_PACING_NONE, |
| 1440 | SK_PACING_NEEDED); | 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 | sk->sk_pacing_rate = min(sk->sk_pacing_rate, ulval); | 1446 | sk->sk_pacing_rate = min(sk->sk_pacing_rate, ulval); |
| 1443 | break; | 1447 | break; |
| 1444 | } | 1448 | } |
| @@ -1533,7 +1537,9 @@ set_sndbuf: · 88 unmodified lines | |||
| 1533 | } | 1537 | } |
| 1534 | if ((u8)val == SOCK_TXREHASH_DEFAULT) | 1538 | if ((u8)val == SOCK_TXREHASH_DEFAULT) |
| 1535 | val = READ_ONCE(sock_net(sk)->core.sysctl_txrehash); | 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 | WRITE_ONCE(sk->sk_txrehash, (u8)val); | 1543 | WRITE_ONCE(sk->sk_txrehash, (u8)val); |
| 1538 | break; | 1544 | break; |
| 1539 | 1545 | ||
| @@ -1633,11 +1639,11 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 93 unmodified lines | |||
| 1633 | break; | 1639 | break; |
| 1634 | 1640 | ||
| 1635 | case SO_SNDBUF: | 1641 | case SO_SNDBUF: |
| 1636 | v.val = sk->sk_sndbuf; | 1642 | v.val = READ_ONCE(sk->sk_sndbuf); |
| 1637 | break; | 1643 | break; |
| 1638 | 1644 | ||
| 1639 | case SO_RCVBUF: | 1645 | case SO_RCVBUF: |
| 1640 | v.val = sk->sk_rcvbuf; | 1646 | v.val = READ_ONCE(sk->sk_rcvbuf); |
| 1641 | break; | 1647 | break; |
| 1642 | 1648 | ||
| 1643 | case SO_REUSEADDR: | 1649 | case SO_REUSEADDR: |
| @@ -1679,7 +1685,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 35 unmodified lines | |||
| 1679 | break; | 1685 | break; |
| 1680 | 1686 | ||
| 1681 | case SO_PRIORITY: | 1687 | case SO_PRIORITY: |
| 1682 | v.val = sk->sk_priority; | 1688 | v.val = READ_ONCE(sk->sk_priority); |
| 1683 | break; | 1689 | break; |
| 1684 | 1690 | ||
| 1685 | case SO_LINGER: | 1691 | case SO_LINGER: |
| @@ -1717,16 +1723,18 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 31 unmodified lines | |||
| 1717 | 1723 | ||
| 1718 | case SO_RCVTIMEO_OLD: | 1724 | case SO_RCVTIMEO_OLD: |
| 1719 | case SO_RCVTIMEO_NEW: | 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 | break; | 1728 | break; |
| 1722 | 1729 | ||
| 1723 | case SO_SNDTIMEO_OLD: | 1730 | case SO_SNDTIMEO_OLD: |
| 1724 | case SO_SNDTIMEO_NEW: | 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 | break; | 1734 | break; |
| 1727 | 1735 | ||
| 1728 | case SO_RCVLOWAT: | 1736 | case SO_RCVLOWAT: |
| 1729 | v.val = sk->sk_rcvlowat; | 1737 | v.val = READ_ONCE(sk->sk_rcvlowat); |
| 1730 | break; | 1738 | break; |
| 1731 | 1739 | ||
| 1732 | case SO_SNDLOWAT: | 1740 | case SO_SNDLOWAT: |
| @@ -1770,7 +1778,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 37 unmodified lines | |||
| 1770 | spin_unlock(&sk->sk_peer_lock); | 1778 | spin_unlock(&sk->sk_peer_lock); |
| 1771 | 1779 | ||
| 1772 | if (!peer_pid) | 1780 | if (!peer_pid) |
| 1773 | return -ESRCH; | 1781 | return -ENODATA; |
| 1774 | 1782 | ||
| 1775 | pidfd = pidfd_prepare(peer_pid, 0, &pidfd_file); | 1783 | pidfd = pidfd_prepare(peer_pid, 0, &pidfd_file); |
| 1776 | put_pid(peer_pid); | 1784 | put_pid(peer_pid); |
| @@ -1843,7 +1851,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 66 unmodified lines | |||
| 1843 | optval, optlen, len); | 1851 | optval, optlen, len); |
| 1844 | 1852 | ||
| 1845 | case SO_MARK: | 1853 | case SO_MARK: |
| 1846 | v.val = sk->sk_mark; | 1854 | v.val = READ_ONCE(sk->sk_mark); |
| 1847 | break; | 1855 | break; |
| 1848 | 1856 | ||
| 1849 | case SO_RCVMARK: | 1857 | case SO_RCVMARK: |
| @@ -1862,7 +1870,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 12 unmodified lines | |||
| 1862 | if (!sock->ops->set_peek_off) | 1870 | if (!sock->ops->set_peek_off) |
| 1863 | return -EOPNOTSUPP; | 1871 | return -EOPNOTSUPP; |
| 1864 | 1872 | ||
| 1865 | v.val = sk->sk_peek_off; | 1873 | v.val = READ_ONCE(sk->sk_peek_off); |
| 1866 | break; | 1874 | break; |
| 1867 | case SO_NOFCS: | 1875 | case SO_NOFCS: |
| 1868 | v.val = sock_flag(sk, SOCK_NOFCS); | 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 | #ifdef CONFIG_NET_RX_BUSY_POLL | 1901 | #ifdef CONFIG_NET_RX_BUSY_POLL |
| 1894 | case SO_BUSY_POLL: | 1902 | case SO_BUSY_POLL: |
| 1895 | v.val = sk->sk_ll_usec; | 1903 | v.val = READ_ONCE(sk->sk_ll_usec); |
| 1896 | break; | 1904 | break; |
| 1897 | case SO_PREFER_BUSY_POLL: | 1905 | case SO_PREFER_BUSY_POLL: |
| 1898 | v.val = READ_ONCE(sk->sk_prefer_busy_poll); | 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 | #endif | 1908 | #endif |
| 1901 | 1909 | ||
| 1902 | case SO_MAX_PACING_RATE: | 1910 | case SO_MAX_PACING_RATE: |
| 1911 | /* The READ_ONCE() pair with the WRITE_ONCE() in sk_setsockopt() */ | ||
| 1903 | if (sizeof(v.ulval) != sizeof(v.val) && len >= sizeof(v.ulval)) { | 1912 | if (sizeof(v.ulval) != sizeof(v.val) && len >= sizeof(v.ulval)) { |
| 1904 | lv = sizeof(v.ulval); | 1913 | lv = sizeof(v.ulval); |
| 1905 | v.ulval = sk->sk_max_pacing_rate; | 1914 | v.ulval = READ_ONCE(sk->sk_max_pacing_rate); |
| 1906 | } else { | 1915 | } else { |
| 1907 | /* 32bit version */ | 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 | break; | 1920 | break; |
| 1911 | 1921 | ||
| @@ -1973,11 +1983,12 @@ int sk_getsockopt(struct sock *sk, int level, int optname, · 61 unmodified lines | |||
| 1973 | break; | 1983 | break; |
| 1974 | 1984 | ||
| 1975 | case SO_RESERVE_MEM: | 1985 | case SO_RESERVE_MEM: |
| 1976 | v.val = sk->sk_reserved_mem; | 1986 | v.val = READ_ONCE(sk->sk_reserved_mem); |
| 1977 | break; | 1987 | break; |
| 1978 | 1988 | ||
| 1979 | case SO_TXREHASH: | 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 | break; | 1992 | break; |
| 1982 | 1993 | ||
| 1983 | default: | 1994 | default: |
| @@ -3168,7 +3179,7 @@ EXPORT_SYMBOL(__sk_mem_reclaim); · 1184 unmodified lines | |||
| 3168 | 3179 | ||
| 3169 | int sk_set_peek_off(struct sock *sk, int val) | 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 | return 0; | 3183 | return 0; |
| 3173 | } | 3184 | } |
| 3174 | EXPORT_SYMBOL_GPL(sk_set_peek_off); | 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 | __acquires(&sk->sk_lock.slock) | 115 | __acquires(&sk->sk_lock.slock) |
| 116 | { | 116 | { |
| 117 | lock_sock(sk); | 117 | lock_sock(sk); |
| 118 | preempt_disable(); | ||
| 119 | rcu_read_lock(); | 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 | __releases(&sk->sk_lock.slock) | 122 | __releases(&sk->sk_lock.slock) |
| 124 | { | 123 | { |
| 125 | rcu_read_unlock(); | 124 | rcu_read_unlock(); |
| 126 | preempt_enable(); | ||
| 127 | release_sock(sk); | 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 | list_for_each_entry_safe(link, tmp, &psock->link, list) { | 146 | list_for_each_entry_safe(link, tmp, &psock->link, list) { |
| 149 | if (link->link_raw == link_raw) { | 147 | if (link->link_raw == link_raw) { |
| 150 | struct bpf_map *map = link->map; | 148 | struct bpf_map *map = link->map; |
| 151 | struct bpf_stab *stab = container_of(map, struct bpf_stab, | 149 | struct sk_psock_progs *progs = sock_map_progs(map); |
| 152 | map); | 150 | |
| 153 | if (psock->saved_data_ready && stab->progs.stream_parser) | 151 | if (psock->saved_data_ready && progs->stream_parser) |
| 154 | strp_stop = true; | 152 | strp_stop = true; |
| 155 | if (psock->saved_data_ready && stab->progs.stream_verdict) | 153 | if (psock->saved_data_ready && progs->stream_verdict) |
| 156 | verdict_stop = true; | 154 | verdict_stop = true; |
| 157 | if (psock->saved_data_ready && stab->progs.skb_verdict) | 155 | if (psock->saved_data_ready && progs->skb_verdict) |
| 158 | verdict_stop = true; | 156 | verdict_stop = true; |
| 159 | list_del(&link->list); | 157 | list_del(&link->list); |
| 160 | sk_psock_free_link(link); | 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 | return -EOPNOTSUPP; | 980 | return -EOPNOTSUPP; |
| 981 | 981 | ||
| 982 | ret = nla_parse_nested_deprecated(data, DCB_BCN_ATTR_MAX, | 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 | NULL); | 984 | NULL); |
| 985 | if (ret) | 985 | if (ret) |
| 986 | return ret; | 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 | opt = ireq->ipv6_opt; | 238 | opt = ireq->ipv6_opt; |
| 239 | if (!opt) | 239 | if (!opt) |
| 240 | opt = rcu_dereference(np->opt); | 240 | opt = rcu_dereference(np->opt); |
| 241 | err = ip6_xmit(sk, skb, &fl6, sk->sk_mark, opt, np->tclass, | 241 | err = ip6_xmit(sk, skb, &fl6, READ_ONCE(sk->sk_mark), opt, |
| 242 | sk->sk_priority); | 242 | np->tclass, sk->sk_priority); |
| 243 | rcu_read_unlock(); | 243 | rcu_read_unlock(); |
| 244 | err = net_xmit_eval(err); | 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 | /* And store cached results */ | 188 | /* And store cached results */ |
| 189 | icsk->icsk_pmtu_cookie = pmtu; | 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 | return cur_mps; | 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 | return dccp_getsockopt_service(sk, len, | 630 | return dccp_getsockopt_service(sk, len, |
| 631 | (__be32 __user *)optval, optlen); | 631 | (__be32 __user *)optval, optlen); |
| 632 | case DCCP_SOCKOPT_GET_CUR_MPS: | 632 | case DCCP_SOCKOPT_GET_CUR_MPS: |
| 633 | val = dp->dccps_mss_cache; | 633 | val = READ_ONCE(dp->dccps_mss_cache); |
| 634 | break; | 634 | break; |
| 635 | case DCCP_SOCKOPT_AVAILABLE_CCIDS: | 635 | case DCCP_SOCKOPT_AVAILABLE_CCIDS: |
| 636 | return ccid_getsockopt_builtin_ccids(sk, len, optval, optlen); | 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 | trace_dccp_probe(sk, len); | 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 | return -EMSGSIZE; | 743 | return -EMSGSIZE; |
| 744 | 744 | ||
| 745 | lock_sock(sk); | 745 | lock_sock(sk); |
| @@ -772,6 +772,12 @@ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 26 unmodified lines | |||
| 772 | goto out_discard; | 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 | skb_reserve(skb, sk->sk_prot->max_header); | 781 | skb_reserve(skb, sk->sk_prot->max_header); |
| 776 | rc = memcpy_from_msg(skb_put(skb, len), msg, len); | 782 | rc = memcpy_from_msg(skb_put(skb, len), msg, len); |
| 777 | if (rc != 0) | 783 | if (rc != 0) |
| @@ -1727,8 +1727,15 @@ int dsa_port_phylink_create(struct dsa_port *dp) · 1726 unmodified lines | |||
| 1727 | ds->ops->phylink_mac_an_restart) | 1727 | ds->ops->phylink_mac_an_restart) |
| 1728 | dp->pl_config.legacy_pre_march2020 = true; | 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 | ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config); | 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 | pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), | 1740 | pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), |
| 1734 | mode, &dsa_port_phylink_mac_ops); | 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 | #endif | 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 | goto errout; | 154 | goto errout; |
| 155 | 155 | ||
| 156 | if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) || | 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 | entry.ifindex = sk->sk_bound_dev_if; | 799 | entry.ifindex = sk->sk_bound_dev_if; |
| 800 | entry.userlocks = sk_fullsock(sk) ? sk->sk_userlocks : 0; | 800 | entry.userlocks = sk_fullsock(sk) ? sk->sk_userlocks : 0; |
| 801 | if (sk_fullsock(sk)) | 801 | if (sk_fullsock(sk)) |
| 802 | entry.mark = sk->sk_mark; | 802 | entry.mark = READ_ONCE(sk->sk_mark); |
| 803 | else if (sk->sk_state == TCP_NEW_SYN_RECV) | 803 | else if (sk->sk_state == TCP_NEW_SYN_RECV) |
| 804 | entry.mark = inet_rsk(inet_reqsk(sk))->ir_mark; | 804 | entry.mark = inet_rsk(inet_reqsk(sk))->ir_mark; |
| 805 | else if (sk->sk_state == TCP_TIME_WAIT) | 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 | ip_options_build(skb, &opt->opt, daddr, rt); | 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 | if (!skb->mark) | 188 | if (!skb->mark) |
| 189 | skb->mark = sk->sk_mark; | 189 | skb->mark = READ_ONCE(sk->sk_mark); |
| 190 | 190 | ||
| 191 | /* Send it out. */ | 191 | /* Send it out. */ |
| 192 | return ip_local_out(net, skb->sk, skb); | 192 | return ip_local_out(net, skb->sk, skb); |
| @@ -528,8 +528,8 @@ packet_routed: · 335 unmodified lines | |||
| 528 | skb_shinfo(skb)->gso_segs ?: 1); | 528 | skb_shinfo(skb)->gso_segs ?: 1); |
| 529 | 529 | ||
| 530 | /* TODO : should we use skb->sk here instead of sk ? */ | 530 | /* TODO : should we use skb->sk here instead of sk ? */ |
| 531 | skb->priority = sk->sk_priority; | 531 | skb->priority = READ_ONCE(sk->sk_priority); |
| 532 | skb->mark = sk->sk_mark; | 532 | skb->mark = READ_ONCE(sk->sk_mark); |
| 533 | 533 | ||
| 534 | res = ip_local_out(net, sk, skb); | 534 | res = ip_local_out(net, sk, skb); |
| 535 | rcu_read_unlock(); | 535 | rcu_read_unlock(); |
| @@ -1158,10 +1158,15 @@ alloc_new_skb: · 622 unmodified lines | |||
| 1158 | } | 1158 | } |
| 1159 | 1159 | ||
| 1160 | copy = datalen - transhdrlen - fraggap - pagedlen; | 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 | if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { | 1164 | if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { |
| 1162 | err = -EFAULT; | 1165 | err = -EFAULT; |
| 1163 | kfree_skb(skb); | 1166 | kfree_skb(skb); |
| 1164 | goto error; | 1167 | goto error; |
| 1168 | } else if (flags & MSG_SPLICE_PAGES) { | ||
| 1169 | copy = 0; | ||
| 1165 | } | 1170 | } |
| 1166 | 1171 | ||
| 1167 | offset += copy; | 1172 | offset += copy; |
| @@ -1209,6 +1214,10 @@ alloc_new_skb: · 41 unmodified lines | |||
| 1209 | } else if (flags & MSG_SPLICE_PAGES) { | 1214 | } else if (flags & MSG_SPLICE_PAGES) { |
| 1210 | struct msghdr *msg = from; | 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 | err = skb_splice_from_iter(skb, &msg->msg_iter, copy, | 1221 | err = skb_splice_from_iter(skb, &msg->msg_iter, copy, |
| 1213 | sk->sk_allocation); | 1222 | sk->sk_allocation); |
| 1214 | if (err < 0) | 1223 | if (err < 0) |
| @@ -592,7 +592,7 @@ void __ip_sock_set_tos(struct sock *sk, int val) · 591 unmodified lines | |||
| 592 | } | 592 | } |
| 593 | if (inet_sk(sk)->tos != val) { | 593 | if (inet_sk(sk)->tos != val) { |
| 594 | inet_sk(sk)->tos = val; | 594 | inet_sk(sk)->tos = val; |
| 595 | sk->sk_priority = rt_tos2priority(val); | 595 | WRITE_ONCE(sk->sk_priority, rt_tos2priority(val)); |
| 596 | sk_dst_reset(sk); | 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 | .un.frag.__unused = 0, | 224 | .un.frag.__unused = 0, |
| 225 | .un.frag.mtu = htons(mtu), | 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 | skb_reset_transport_header(skb); | 228 | skb_reset_transport_header(skb); |
| 229 | 229 | ||
| 230 | niph = skb_push(skb, sizeof(*niph)); | 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 | &rtm_dump_nexthop_cb, &filter); | 3221 | &rtm_dump_nexthop_cb, &filter); |
| 3222 | if (err < 0) { | 3222 | if (err < 0) { |
| 3223 | if (likely(skb->len)) | 3223 | if (likely(skb->len)) |
| 3224 | goto out; | 3224 | err = skb->len; |
| 3225 | goto out_err; | ||
| 3226 | } | 3225 | } |
| 3227 | 3226 | ||
| 3228 | out: | ||
| 3229 | err = skb->len; | ||
| 3230 | out_err: | ||
| 3231 | cb->seq = net->nexthop.seq; | 3227 | cb->seq = net->nexthop.seq; |
| 3232 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | 3228 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
| 3233 | return err; | 3229 | return err; |
| @@ -3367,25 +3363,19 @@ static int rtm_dump_nexthop_bucket_nh(struct sk_buff *skb, · 133 unmodified lines | |||
| 3367 | dd->filter.res_bucket_nh_id != nhge->nh->id) | 3363 | dd->filter.res_bucket_nh_id != nhge->nh->id) |
| 3368 | continue; | 3364 | continue; |
| 3369 | 3365 | ||
| 3366 | dd->ctx->bucket_index = bucket_index; | ||
| 3370 | err = nh_fill_res_bucket(skb, nh, bucket, bucket_index, | 3367 | err = nh_fill_res_bucket(skb, nh, bucket, bucket_index, |
| 3371 | RTM_NEWNEXTHOPBUCKET, portid, | 3368 | RTM_NEWNEXTHOPBUCKET, portid, |
| 3372 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 3369 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| 3373 | cb->extack); | 3370 | cb->extack); |
| 3374 | if (err < 0) { | 3371 | if (err) |
| 3375 | if (likely(skb->len)) | 3372 | return err; |
| 3376 | goto out; | ||
| 3377 | goto out_err; | ||
| 3378 | } | ||
| 3379 | } | 3373 | } |
| 3380 | 3374 | ||
| 3381 | dd->ctx->done_nh_idx = dd->ctx->nh.idx + 1; | 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: | 3378 | return 0; |
| 3385 | err = skb->len; | ||
| 3386 | out_err: | ||
| 3387 | dd->ctx->bucket_index = bucket_index; | ||
| 3388 | return err; | ||
| 3389 | } | 3379 | } |
| 3390 | 3380 | ||
| 3391 | static int rtm_dump_nexthop_bucket_cb(struct sk_buff *skb, | 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 | if (err < 0) { | 3425 | if (err < 0) { |
| 3436 | if (likely(skb->len)) | 3426 | if (likely(skb->len)) |
| 3437 | goto out; | 3427 | err = skb->len; |
| 3438 | goto out_err; | ||
| 3439 | } | 3428 | } |
| 3440 | 3429 | ||
| 3441 | out: | ||
| 3442 | err = skb->len; | ||
| 3443 | out_err: | ||
| 3444 | cb->seq = net->nexthop.seq; | 3430 | cb->seq = net->nexthop.seq; |
| 3445 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | 3431 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
| 3446 | return err; | 3432 | return err; |
| @@ -348,7 +348,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, · 347 unmodified lines | |||
| 348 | goto error; | 348 | goto error; |
| 349 | skb_reserve(skb, hlen); | 349 | skb_reserve(skb, hlen); |
| 350 | 350 | ||
| 351 | skb->priority = sk->sk_priority; | 351 | skb->priority = READ_ONCE(sk->sk_priority); |
| 352 | skb->mark = sockc->mark; | 352 | skb->mark = sockc->mark; |
| 353 | skb->tstamp = sockc->transmit_time; | 353 | skb->tstamp = sockc->transmit_time; |
| 354 | skb_dst_set(skb, &rt->dst); | 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 | const struct inet_sock *inet = inet_sk(sk); | 518 | const struct inet_sock *inet = inet_sk(sk); |
| 519 | 519 | ||
| 520 | oif = sk->sk_bound_dev_if; | 520 | oif = sk->sk_bound_dev_if; |
| 521 | mark = sk->sk_mark; | 521 | mark = READ_ONCE(sk->sk_mark); |
| 522 | tos = ip_sock_rt_tos(sk); | 522 | tos = ip_sock_rt_tos(sk); |
| 523 | scope = ip_sock_rt_scope(sk); | 523 | scope = ip_sock_rt_scope(sk); |
| 524 | prot = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol; | 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 | inet_opt = rcu_dereference(inet->inet_opt); | 552 | inet_opt = rcu_dereference(inet->inet_opt); |
| 553 | if (inet_opt && inet_opt->opt.srr) | 553 | if (inet_opt && inet_opt->opt.srr) |
| 554 | daddr = inet_opt->opt.faddr; | 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 | ip_sock_rt_tos(sk) & IPTOS_RT_MASK, | 556 | ip_sock_rt_tos(sk) & IPTOS_RT_MASK, |
| 557 | ip_sock_rt_scope(sk), | 557 | ip_sock_rt_scope(sk), |
| 558 | inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, | 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 | ctl_sk = this_cpu_read(ipv4_tcp_sk); | 931 | ctl_sk = this_cpu_read(ipv4_tcp_sk); |
| 932 | sock_net_set(ctl_sk, net); | 932 | sock_net_set(ctl_sk, net); |
| 933 | ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ? | 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 | ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ? | 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 | transmit_time = tcp_transmit_time(sk); | 937 | transmit_time = tcp_transmit_time(sk); |
| 938 | ip_send_unicast_reply(ctl_sk, | 938 | ip_send_unicast_reply(ctl_sk, |
| 939 | skb, &TCP_SKB_CB(skb)->header.h4.opt, | 939 | skb, &TCP_SKB_CB(skb)->header.h4.opt, |
| @@ -40,7 +40,7 @@ struct tcp_fastopen_metrics { · 39 unmodified lines | |||
| 40 | 40 | ||
| 41 | struct tcp_metrics_block { | 41 | struct tcp_metrics_block { |
| 42 | struct tcp_metrics_block __rcu *tcpm_next; | 42 | struct tcp_metrics_block __rcu *tcpm_next; |
| 43 | possible_net_t tcpm_net; | 43 | struct net *tcpm_net; |
| 44 | struct inetpeer_addr tcpm_saddr; | 44 | struct inetpeer_addr tcpm_saddr; |
| 45 | struct inetpeer_addr tcpm_daddr; | 45 | struct inetpeer_addr tcpm_daddr; |
| 46 | unsigned long tcpm_stamp; | 46 | unsigned long tcpm_stamp; |
| @@ -51,34 +51,38 @@ struct tcp_metrics_block { · 4 unmodified lines | |||
| 51 | struct rcu_head rcu_head; | 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 | static bool tcp_metric_locked(struct tcp_metrics_block *tm, | 60 | static bool tcp_metric_locked(struct tcp_metrics_block *tm, |
| 60 | enum tcp_metric_index idx) | 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 | enum tcp_metric_index idx) | 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 | static void tcp_metric_set(struct tcp_metrics_block *tm, | 74 | static void tcp_metric_set(struct tcp_metrics_block *tm, |
| 72 | enum tcp_metric_index idx, | 75 | enum tcp_metric_index idx, |
| 73 | u32 val) | 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 | static bool addr_same(const struct inetpeer_addr *a, | 82 | static bool addr_same(const struct inetpeer_addr *a, |
| 79 | const struct inetpeer_addr *b) | 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 | struct tcpm_hash_bucket { | 88 | struct tcpm_hash_bucket { |
| @@ -89,6 +93,7 @@ static struct tcpm_hash_bucket *tcp_metrics_hash __read_mostly; · 4 unmodified lines | |||
| 89 | static unsigned int tcp_metrics_hash_log __read_mostly; | 93 | static unsigned int tcp_metrics_hash_log __read_mostly; |
| 90 | 94 | ||
| 91 | static DEFINE_SPINLOCK(tcp_metrics_lock); | 95 | static DEFINE_SPINLOCK(tcp_metrics_lock); |
| 96 | static DEFINE_SEQLOCK(fastopen_seqlock); | ||
| 92 | 97 | ||
| 93 | static void tcpm_suck_dst(struct tcp_metrics_block *tm, | 98 | static void tcpm_suck_dst(struct tcp_metrics_block *tm, |
| 94 | const struct dst_entry *dst, | 99 | const struct dst_entry *dst, |
| @@ -97,7 +102,7 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, · 2 unmodified lines | |||
| 97 | u32 msval; | 102 | u32 msval; |
| 98 | u32 val; | 103 | u32 val; |
| 99 | 104 | ||
| 100 | tm->tcpm_stamp = jiffies; | 105 | WRITE_ONCE(tm->tcpm_stamp, jiffies); |
| 101 | 106 | ||
| 102 | val = 0; | 107 | val = 0; |
| 103 | if (dst_metric_locked(dst, RTAX_RTT)) | 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 | val |= 1 << TCP_METRIC_CWND; | 115 | val |= 1 << TCP_METRIC_CWND; |
| 111 | if (dst_metric_locked(dst, RTAX_REORDERING)) | 116 | if (dst_metric_locked(dst, RTAX_REORDERING)) |
| 112 | val |= 1 << TCP_METRIC_REORDERING; | 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 | msval = dst_metric_raw(dst, RTAX_RTT); | 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 | msval = dst_metric_raw(dst, RTAX_RTTVAR); | 124 | msval = dst_metric_raw(dst, RTAX_RTTVAR); |
| 119 | tm->tcpm_vals[TCP_METRIC_RTTVAR] = msval * USEC_PER_MSEC; | 125 | tcp_metric_set(tm, TCP_METRIC_RTTVAR, msval * USEC_PER_MSEC); |
| 120 | tm->tcpm_vals[TCP_METRIC_SSTHRESH] = dst_metric_raw(dst, RTAX_SSTHRESH); | 126 | tcp_metric_set(tm, TCP_METRIC_SSTHRESH, |
| 121 | tm->tcpm_vals[TCP_METRIC_CWND] = dst_metric_raw(dst, RTAX_CWND); | 127 | dst_metric_raw(dst, RTAX_SSTHRESH)); |
| 122 | tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING); | 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 | if (fastopen_clear) { | 132 | if (fastopen_clear) { |
| 133 | write_seqlock(&fastopen_seqlock); | ||
| 124 | tm->tcpm_fastopen.mss = 0; | 134 | tm->tcpm_fastopen.mss = 0; |
| 125 | tm->tcpm_fastopen.syn_loss = 0; | 135 | tm->tcpm_fastopen.syn_loss = 0; |
| 126 | tm->tcpm_fastopen.try_exp = 0; | 136 | tm->tcpm_fastopen.try_exp = 0; |
| 127 | tm->tcpm_fastopen.cookie.exp = false; | 137 | tm->tcpm_fastopen.cookie.exp = false; |
| 128 | tm->tcpm_fastopen.cookie.len = 0; | 138 | tm->tcpm_fastopen.cookie.len = 0; |
| 139 | write_sequnlock(&fastopen_seqlock); | ||
| 129 | } | 140 | } |
| 130 | } | 141 | } |
| 131 | 142 | ||
| 132 | #define TCP_METRICS_TIMEOUT (60 * 60 * HZ) | 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 | tcpm_suck_dst(tm, dst, false); | 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 | oldest = deref_locked(tcp_metrics_hash[hash].chain); | 191 | oldest = deref_locked(tcp_metrics_hash[hash].chain); |
| 175 | for (tm = deref_locked(oldest->tcpm_next); tm; | 192 | for (tm = deref_locked(oldest->tcpm_next); tm; |
| 176 | tm = deref_locked(tm->tcpm_next)) { | 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 | oldest = tm; | 196 | oldest = tm; |
| 179 | } | 197 | } |
| 180 | tm = oldest; | 198 | tm = oldest; |
| 181 | } else { | 199 | } else { |
| 182 | tm = kmalloc(sizeof(*tm), GFP_ATOMIC); | 200 | tm = kzalloc(sizeof(*tm), GFP_ATOMIC); |
| 183 | if (!tm) | 201 | if (!tm) |
| 184 | goto out_unlock; | 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 | tm->tcpm_saddr = *saddr; | 207 | tm->tcpm_saddr = *saddr; |
| 188 | tm->tcpm_daddr = *daddr; | 208 | tm->tcpm_daddr = *daddr; |
| 189 | 209 | ||
| 190 | tcpm_suck_dst(tm, dst, true); | 210 | tcpm_suck_dst(tm, dst, reclaim); |
| 191 | 211 | ||
| 192 | if (likely(!reclaim)) { | 212 | if (likely(!reclaim)) { |
| 193 | tm->tcpm_next = tcp_metrics_hash[hash].chain; | 213 | tm->tcpm_next = tcp_metrics_hash[hash].chain; |
| @@ -434,7 +454,7 @@ void tcp_update_metrics(struct sock *sk) · 240 unmodified lines | |||
| 434 | tp->reordering); | 454 | tp->reordering); |
| 435 | } | 455 | } |
| 436 | } | 456 | } |
| 437 | tm->tcpm_stamp = jiffies; | 457 | WRITE_ONCE(tm->tcpm_stamp, jiffies); |
| 438 | out_unlock: | 458 | out_unlock: |
| 439 | rcu_read_unlock(); | 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 | return ret; | 559 | return ret; |
| 540 | } | 560 | } |
| 541 | 561 | ||
| 542 | static DEFINE_SEQLOCK(fastopen_seqlock); | ||
| 543 | |||
| 544 | void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, | 562 | void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, |
| 545 | struct tcp_fastopen_cookie *cookie) | 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 | if (nla_put_msecs(msg, TCP_METRICS_ATTR_AGE, | 667 | if (nla_put_msecs(msg, TCP_METRICS_ATTR_AGE, |
| 650 | jiffies - tm->tcpm_stamp, | 668 | jiffies - READ_ONCE(tm->tcpm_stamp), |
| 651 | TCP_METRICS_ATTR_PAD) < 0) | 669 | TCP_METRICS_ATTR_PAD) < 0) |
| 652 | goto nla_put_failure; | 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 | if (!nest) | 676 | if (!nest) |
| 659 | goto nla_put_failure; | 677 | goto nla_put_failure; |
| 660 | for (i = 0; i < TCP_METRIC_MAX_KERNEL + 1; i++) { | 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 | if (!val) | 681 | if (!val) |
| 664 | continue; | 682 | continue; |
| @@ -114,6 +114,7 @@ · 113 unmodified lines | |||
| 114 | #include <net/sock_reuseport.h> | 114 | #include <net/sock_reuseport.h> |
| 115 | #include <net/addrconf.h> | 115 | #include <net/addrconf.h> |
| 116 | #include <net/udp_tunnel.h> | 116 | #include <net/udp_tunnel.h> |
| 117 | #include <net/gro.h> | ||
| 117 | #if IS_ENABLED(CONFIG_IPV6) | 118 | #if IS_ENABLED(CONFIG_IPV6) |
| 118 | #include <net/ipv6_stubs.h> | 119 | #include <net/ipv6_stubs.h> |
| 119 | #endif | 120 | #endif |
| @@ -555,10 +556,13 @@ struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb, · 435 unmodified lines | |||
| 555 | { | 556 | { |
| 556 | const struct iphdr *iph = ip_hdr(skb); | 557 | const struct iphdr *iph = ip_hdr(skb); |
| 557 | struct net *net = dev_net(skb->dev); | 558 | struct net *net = dev_net(skb->dev); |
| 559 | int iif, sdif; | ||
| 560 | |||
| 561 | inet_get_iif_sdif(skb, &iif, &sdif); | ||
| 558 | 562 | ||
| 559 | return __udp4_lib_lookup(net, iph->saddr, sport, | 563 | return __udp4_lib_lookup(net, iph->saddr, sport, |
| 560 | iph->daddr, dport, inet_iif(skb), | 564 | iph->daddr, dport, iif, |
| 561 | inet_sdif(skb), net->ipv4.udp_table, NULL); | 565 | sdif, net->ipv4.udp_table, NULL); |
| 562 | } | 566 | } |
| 563 | 567 | ||
| 564 | /* Must be called under rcu_read_lock(). | 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 | const struct iphdr *iph = skb_gro_network_header(skb); | 610 | const struct iphdr *iph = skb_gro_network_header(skb); |
| 611 | struct net *net = dev_net(skb->dev); | 611 | struct net *net = dev_net(skb->dev); |
| 612 | int iif, sdif; | ||
| 613 | |||
| 614 | inet_get_iif_sdif(skb, &iif, &sdif); | ||
| 612 | 615 | ||
| 613 | return __udp4_lib_lookup(net, iph->saddr, sport, | 616 | return __udp4_lib_lookup(net, iph->saddr, sport, |
| 614 | iph->daddr, dport, inet_iif(skb), | 617 | iph->daddr, dport, iif, |
| 615 | inet_sdif(skb), net->ipv4.udp_table, NULL); | 618 | sdif, net->ipv4.udp_table, NULL); |
| 616 | } | 619 | } |
| 617 | 620 | ||
| 618 | INDIRECT_CALLABLE_SCOPE | 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 | And all this only to mangle msg->im6_msgtype and | 1073 | And all this only to mangle msg->im6_msgtype and |
| 1074 | to set msg->im6_mbz to "mbz" :-) | 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 | skb_push(skb, sizeof(*msg)); | 1078 | skb_push(skb, sizeof(*msg)); |
| 1079 | skb_reset_transport_header(skb); | 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 | static inline int ndisc_is_useropt(const struct net_device *dev, | 197 | static inline int ndisc_is_useropt(const struct net_device *dev, |
| 198 | struct nd_opt_hdr *opt) | 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 | opt->nd_opt_type == ND_OPT_DNSSL || | 202 | opt->nd_opt_type == ND_OPT_DNSSL || |
| 202 | opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL || | 203 | opt->nd_opt_type == ND_OPT_CAPTIVE_PORTAL || |
| 203 | opt->nd_opt_type == ND_OPT_PREF64 || | 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 | ipcm6_init_sk(&ipc6, np); | 121 | ipcm6_init_sk(&ipc6, np); |
| 122 | ipc6.sockc.tsflags = sk->sk_tsflags; | 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 | fl6.flowi6_oif = oif; | 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 | skb_reserve(skb, hlen); | 614 | skb_reserve(skb, hlen); |
| 615 | 615 | ||
| 616 | skb->protocol = htons(ETH_P_IPV6); | 616 | skb->protocol = htons(ETH_P_IPV6); |
| 617 | skb->priority = sk->sk_priority; | 617 | skb->priority = READ_ONCE(sk->sk_priority); |
| 618 | skb->mark = sockc->mark; | 618 | skb->mark = sockc->mark; |
| 619 | skb->tstamp = sockc->transmit_time; | 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 | memset(&fl6, 0, sizeof(fl6)); | 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 | fl6.flowi6_uid = sk->sk_uid; | 778 | fl6.flowi6_uid = sk->sk_uid; |
| 779 | 779 | ||
| 780 | ipcm6_init(&ipc6); | 780 | ipcm6_init(&ipc6); |
| 781 | ipc6.sockc.tsflags = sk->sk_tsflags; | 781 | ipc6.sockc.tsflags = sk->sk_tsflags; |
| 782 | ipc6.sockc.mark = sk->sk_mark; | 782 | ipc6.sockc.mark = fl6.flowi6_mark; |
| 783 | 783 | ||
| 784 | if (sin6) { | 784 | if (sin6) { |
| 785 | if (addr_len < SIN6_LEN_RFC2133) | 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 | if (!oif && skb->dev) | 2951 | if (!oif && skb->dev) |
| 2952 | oif = l3mdev_master_ifindex(skb->dev); | 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 | dst = __sk_dst_get(sk); | 2957 | dst = __sk_dst_get(sk); |
| 2957 | if (!dst || !dst->obsolete || | 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 | void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) | 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 | ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, |
| 3176 | sk->sk_uid); | 3177 | READ_ONCE(sk->sk_mark), sk->sk_uid); |
| 3177 | } | 3178 | } |
| 3178 | EXPORT_SYMBOL_GPL(ip6_sk_redirect); | 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 | opt = ireq->ipv6_opt; | 564 | opt = ireq->ipv6_opt; |
| 565 | if (!opt) | 565 | if (!opt) |
| 566 | opt = rcu_dereference(np->opt); | 566 | opt = rcu_dereference(np->opt); |
| 567 | err = ip6_xmit(sk, skb, fl6, skb->mark ? : sk->sk_mark, opt, | 567 | err = ip6_xmit(sk, skb, fl6, skb->mark ? : READ_ONCE(sk->sk_mark), |
| 568 | tclass, sk->sk_priority); | 568 | opt, tclass, sk->sk_priority); |
| 569 | rcu_read_unlock(); | 569 | rcu_read_unlock(); |
| 570 | err = net_xmit_eval(err); | 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 | if (sk->sk_state == TCP_TIME_WAIT) | 939 | if (sk->sk_state == TCP_TIME_WAIT) |
| 940 | mark = inet_twsk(sk)->tw_mark; | 940 | mark = inet_twsk(sk)->tw_mark; |
| 941 | else | 941 | else |
| 942 | mark = sk->sk_mark; | 942 | mark = READ_ONCE(sk->sk_mark); |
| 943 | skb_set_delivery_time(buff, tcp_transmit_time(sk), true); | 943 | skb_set_delivery_time(buff, tcp_transmit_time(sk), true); |
| 944 | } | 944 | } |
| 945 | if (txhash) { | 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 | tcp_time_stamp_raw() + tcp_rsk(req)->ts_off, | 1128 | tcp_time_stamp_raw() + tcp_rsk(req)->ts_off, |
| 1129 | READ_ONCE(req->ts_recent), sk->sk_bound_dev_if, | 1129 | READ_ONCE(req->ts_recent), sk->sk_bound_dev_if, |
| 1130 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, l3index), | 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 | READ_ONCE(tcp_rsk(req)->txhash)); | 1133 | READ_ONCE(tcp_rsk(req)->txhash)); |
| 1133 | } | 1134 | } |
| 1134 | 1135 | ||
| @@ -51,6 +51,7 @@ · 50 unmodified lines | |||
| 51 | #include <net/inet6_hashtables.h> | 51 | #include <net/inet6_hashtables.h> |
| 52 | #include <net/busy_poll.h> | 52 | #include <net/busy_poll.h> |
| 53 | #include <net/sock_reuseport.h> | 53 | #include <net/sock_reuseport.h> |
| 54 | #include <net/gro.h> | ||
| 54 | 55 | ||
| 55 | #include <linux/proc_fs.h> | 56 | #include <linux/proc_fs.h> |
| 56 | #include <linux/seq_file.h> | 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 | const struct ipv6hdr *iph = ipv6_hdr(skb); | 302 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
| 302 | struct net *net = dev_net(skb->dev); | 303 | struct net *net = dev_net(skb->dev); |
| 304 | int iif, sdif; | ||
| 305 | |||
| 306 | inet6_get_iif_sdif(skb, &iif, &sdif); | ||
| 303 | 307 | ||
| 304 | return __udp6_lib_lookup(net, &iph->saddr, sport, | 308 | return __udp6_lib_lookup(net, &iph->saddr, sport, |
| 305 | &iph->daddr, dport, inet6_iif(skb), | 309 | &iph->daddr, dport, iif, |
| 306 | inet6_sdif(skb), net->ipv4.udp_table, NULL); | 310 | sdif, net->ipv4.udp_table, NULL); |
| 307 | } | 311 | } |
| 308 | 312 | ||
| 309 | /* Must be called under rcu_read_lock(). | 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 | if (type == NDISC_REDIRECT) { | 628 | if (type == NDISC_REDIRECT) { |
| 625 | if (tunnel) { | 629 | if (tunnel) { |
| 626 | ip6_redirect(skb, sock_net(sk), inet6_iif(skb), | 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 | } else { | 632 | } else { |
| 629 | ip6_sk_redirect(skb, sk); | 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 | ipcm6_init(&ipc6); | 1360 | ipcm6_init(&ipc6); |
| 1357 | ipc6.gso_size = READ_ONCE(up->gso_size); | 1361 | ipc6.gso_size = READ_ONCE(up->gso_size); |
| 1358 | ipc6.sockc.tsflags = sk->sk_tsflags; | 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 | /* destination address check */ | 1365 | /* destination address check */ |
| 1362 | if (sin6) { | 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 | const struct ipv6hdr *iph = skb_gro_network_header(skb); | 119 | const struct ipv6hdr *iph = skb_gro_network_header(skb); |
| 120 | struct net *net = dev_net(skb->dev); | 120 | struct net *net = dev_net(skb->dev); |
| 121 | int iif, sdif; | ||
| 122 | |||
| 123 | inet6_get_iif_sdif(skb, &iif, &sdif); | ||
| 121 | 124 | ||
| 122 | return __udp6_lib_lookup(net, &iph->saddr, sport, | 125 | return __udp6_lib_lookup(net, &iph->saddr, sport, |
| 123 | &iph->daddr, dport, inet6_iif(skb), | 126 | &iph->daddr, dport, iif, |
| 124 | inet6_sdif(skb), net->ipv4.udp_table, NULL); | 127 | sdif, net->ipv4.udp_table, NULL); |
| 125 | } | 128 | } |
| 126 | 129 | ||
| 127 | INDIRECT_CALLABLE_SCOPE | 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 | /* Get and verify the address */ | 519 | /* Get and verify the address */ |
| 520 | memset(&fl6, 0, sizeof(fl6)); | 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 | fl6.flowi6_uid = sk->sk_uid; | 523 | fl6.flowi6_uid = sk->sk_uid; |
| 524 | 524 | ||
| 525 | ipcm6_init(&ipc6); | 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 | lock_sock_nested(ssk, SINGLE_DEPTH_NESTING); | 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 | /* be sure to force the tcp_disconnect() path, | 2339 | /* be sure to force the tcp_disconnect() path, |
| 2340 | * to generate the egress reset | 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 | if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags)) | 3329 | if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags)) |
| 3330 | __mptcp_clean_una_wakeup(sk); | 3330 | __mptcp_clean_una_wakeup(sk); |
| 3331 | if (unlikely(&msk->cb_flags)) { | 3331 | if (unlikely(msk->cb_flags)) { |
| 3332 | /* be sure to set the current sk state before tacking actions | 3332 | /* be sure to set the current sk state before tacking actions |
| 3333 | * depending on sk_state, that is processing MPTCP_ERROR_REPORT | 3333 | * depending on sk_state, that is processing MPTCP_ERROR_REPORT |
| 3334 | */ | 3334 | */ |
| @@ -325,7 +325,6 @@ struct mptcp_sock { · 324 unmodified lines | |||
| 325 | u32 subflow_id; | 325 | u32 subflow_id; |
| 326 | u32 setsockopt_seq; | 326 | u32 setsockopt_seq; |
| 327 | char ca_name[TCP_CA_NAME_MAX]; | 327 | char ca_name[TCP_CA_NAME_MAX]; |
| 328 | struct mptcp_sock *dl_next; | ||
| 329 | }; | 328 | }; |
| 330 | 329 | ||
| 331 | #define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock) | 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 | break; | 103 | break; |
| 104 | case SO_MARK: | 104 | case SO_MARK: |
| 105 | if (READ_ONCE(ssk->sk_mark) != sk->sk_mark) { | 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 | sk_dst_reset(ssk); | 107 | sk_dst_reset(ssk); |
| 108 | } | 108 | } |
| 109 | break; | 109 | break; |
| @@ -1793,16 +1793,31 @@ static void subflow_state_change(struct sock *sk) · 1792 unmodified lines | |||
| 1793 | void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk) | 1793 | void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk) |
| 1794 | { | 1794 | { |
| 1795 | struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue; | 1795 | struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue; |
| 1796 | struct mptcp_sock *msk, *next, *head = NULL; | 1796 | struct request_sock *req, *head, *tail; |
| 1797 | struct request_sock *req; | 1797 | struct mptcp_subflow_context *subflow; |
| 1798 | struct sock *sk; | 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 | spin_lock_bh(&queue->rskq_lock); | 1804 | spin_lock_bh(&queue->rskq_lock); |
| 1802 | for (req = queue->rskq_accept_head; req; req = req->dl_next) { | 1805 | head = queue->rskq_accept_head; |
| 1803 | struct mptcp_subflow_context *subflow; | 1806 | tail = queue->rskq_accept_tail; |
| 1804 | struct sock *ssk = req->sk; | 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 | if (!sk_is_mptcp(ssk)) | 1821 | if (!sk_is_mptcp(ssk)) |
| 1807 | continue; | 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 | if (!subflow || !subflow->conn) | 1825 | if (!subflow || !subflow->conn) |
| 1811 | continue; | 1826 | continue; |
| 1812 | 1827 | ||
| 1813 | /* skip if already in list */ | ||
| 1814 | sk = subflow->conn; | 1828 | sk = subflow->conn; |
| 1815 | msk = mptcp_sk(sk); | ||
| 1816 | if (msk->dl_next || msk == head) | ||
| 1817 | continue; | ||
| 1818 | |||
| 1819 | sock_hold(sk); | 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 | lock_sock_nested(sk, SINGLE_DEPTH_NESTING); | 1831 | lock_sock_nested(sk, SINGLE_DEPTH_NESTING); |
| 1836 | next = msk->dl_next; | ||
| 1837 | msk->dl_next = NULL; | ||
| 1838 | |||
| 1839 | __mptcp_unaccepted_force_close(sk); | 1832 | __mptcp_unaccepted_force_close(sk); |
| 1840 | release_sock(sk); | 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 | /* we are still under the listener msk socket lock */ | 1853 | /* we are still under the listener msk socket lock */ |
| 1861 | lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING); | 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 | static int subflow_ulp_init(struct sock *sk) | 1864 | static int subflow_ulp_init(struct sock *sk) |
| @@ -31,7 +31,9 @@ static LIST_HEAD(nf_tables_expressions); · 30 unmodified lines | |||
| 31 | static LIST_HEAD(nf_tables_objects); | 31 | static LIST_HEAD(nf_tables_objects); |
| 32 | static LIST_HEAD(nf_tables_flowtables); | 32 | static LIST_HEAD(nf_tables_flowtables); |
| 33 | static LIST_HEAD(nf_tables_destroy_list); | 33 | static LIST_HEAD(nf_tables_destroy_list); |
| 34 | static LIST_HEAD(nf_tables_gc_list); | ||
| 34 | static DEFINE_SPINLOCK(nf_tables_destroy_list_lock); | 35 | static DEFINE_SPINLOCK(nf_tables_destroy_list_lock); |
| 36 | static DEFINE_SPINLOCK(nf_tables_gc_list_lock); | ||
| 35 | 37 | ||
| 36 | enum { | 38 | enum { |
| 37 | NFT_VALIDATE_SKIP = 0, | 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 | static void nf_tables_trans_destroy_work(struct work_struct *w); | 122 | static void nf_tables_trans_destroy_work(struct work_struct *w); |
| 121 | static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work); | 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 | static void nft_ctx_init(struct nft_ctx *ctx, | 128 | static void nft_ctx_init(struct nft_ctx *ctx, |
| 124 | struct net *net, | 129 | struct net *net, |
| 125 | const struct sk_buff *skb, | 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 | return __nft_trans_set_add(ctx, msg_type, set, NULL); | 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 | static int nft_mapelem_deactivate(const struct nft_ctx *ctx, | 590 | static int nft_mapelem_deactivate(const struct nft_ctx *ctx, |
| 590 | struct nft_set *set, | 591 | struct nft_set *set, |
| 591 | const struct nft_set_iter *iter, | 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 | INIT_LIST_HEAD(&set->bindings); | 5057 | INIT_LIST_HEAD(&set->bindings); |
| 5057 | INIT_LIST_HEAD(&set->catchall_list); | 5058 | INIT_LIST_HEAD(&set->catchall_list); |
| 5059 | refcount_set(&set->refs, 1); | ||
| 5058 | set->table = table; | 5060 | set->table = table; |
| 5059 | write_pnet(&set->net, net); | 5061 | write_pnet(&set->net, net); |
| 5060 | set->ops = ops; | 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 | static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) | 5135 | static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) |
| 5126 | { | 5136 | { |
| 5127 | int i; | 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 | set->ops->destroy(ctx, set); | 5145 | set->ops->destroy(ctx, set); |
| 5136 | nft_set_catchall_destroy(ctx, set); | 5146 | nft_set_catchall_destroy(ctx, set); |
| 5137 | kfree(set->name); | 5147 | nft_set_put(set); |
| 5138 | kvfree(set); | ||
| 5139 | } | 5148 | } |
| 5140 | 5149 | ||
| 5141 | static int nf_tables_delset(struct sk_buff *skb, const struct nfnl_info *info, | 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 | const struct nft_set_iter *iter, | 5611 | const struct nft_set_iter *iter, |
| 5603 | struct nft_set_elem *elem) | 5612 | struct nft_set_elem *elem) |
| 5604 | { | 5613 | { |
| 5614 | const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); | ||
| 5605 | struct nft_set_dump_args *args; | 5615 | struct nft_set_dump_args *args; |
| 5606 | 5616 | ||
| 5617 | if (nft_set_elem_expired(ext)) | ||
| 5618 | return 0; | ||
| 5619 | |||
| 5607 | args = container_of(iter, struct nft_set_dump_args, iter); | 5620 | args = container_of(iter, struct nft_set_dump_args, iter); |
| 5608 | return nf_tables_fill_setelem(args->skb, set, elem, args->reset); | 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 | list_for_each_entry_rcu(catchall, &set->catchall_list, list) { | 6287 | list_for_each_entry_rcu(catchall, &set->catchall_list, list) { |
| 6275 | ext = nft_set_elem_ext(set, catchall->elem); | 6288 | ext = nft_set_elem_ext(set, catchall->elem); |
| 6276 | if (nft_set_elem_active(ext, genmask) && | 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 | return ext; | 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 | EXPORT_SYMBOL_GPL(nft_set_catchall_lookup); | 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 | static int nft_setelem_catchall_insert(const struct net *net, | 6299 | static int nft_setelem_catchall_insert(const struct net *net, |
| 6309 | struct nft_set *set, | 6300 | struct nft_set *set, |
| 6310 | const struct nft_set_elem *elem, | 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 | if (nft_setelem_is_catchall(set, elem)) { | 6358 | if (nft_setelem_is_catchall(set, elem)) { |
| 6368 | nft_set_elem_change_active(net, set, ext); | 6359 | nft_set_elem_change_active(net, set, ext); |
| 6369 | nft_set_elem_clear_busy(ext); | ||
| 6370 | } else { | 6360 | } else { |
| 6371 | set->ops->activate(net, set, elem); | 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 | list_for_each_entry(catchall, &set->catchall_list, list) { | 6372 | list_for_each_entry(catchall, &set->catchall_list, list) { |
| 6383 | ext = nft_set_elem_ext(set, catchall->elem); | 6373 | ext = nft_set_elem_ext(set, catchall->elem); |
| 6384 | if (!nft_is_active(net, ext) || | 6374 | if (!nft_is_active(net, ext)) |
| 6385 | nft_set_elem_mark_busy(ext)) | ||
| 6386 | continue; | 6375 | continue; |
| 6387 | 6376 | ||
| 6388 | kfree(elem->priv); | 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 | goto err_elem_free; | 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 | err = nft_setelem_insert(ctx->net, set, &elem, &ext2, flags); | 6771 | err = nft_setelem_insert(ctx->net, set, &elem, &ext2, flags); |
| 6783 | if (err) { | 6772 | if (err) { |
| @@ -6929,9 +6918,9 @@ static void nft_setelem_data_activate(const struct net *net, · 145 unmodified lines | |||
| 6929 | nft_use_inc_restore(&(*nft_set_ext_obj(ext))->use); | 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, | 6921 | void nft_setelem_data_deactivate(const struct net *net, |
| 6933 | const struct nft_set *set, | 6922 | const struct nft_set *set, |
| 6934 | struct nft_set_elem *elem) | 6923 | struct nft_set_elem *elem) |
| 6935 | { | 6924 | { |
| 6936 | const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); | 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 | list_for_each_entry_rcu(catchall, &set->catchall_list, list) { | 7085 | list_for_each_entry_rcu(catchall, &set->catchall_list, list) { |
| 7097 | ext = nft_set_elem_ext(set, catchall->elem); | 7086 | ext = nft_set_elem_ext(set, catchall->elem); |
| 7098 | if (!nft_set_elem_active(ext, genmask) || | 7087 | if (!nft_set_elem_active(ext, genmask)) |
| 7099 | nft_set_elem_mark_busy(ext)) | ||
| 7100 | continue; | 7088 | continue; |
| 7101 | 7089 | ||
| 7102 | elem.priv = catchall->elem; | 7090 | elem.priv = catchall->elem; |
| @@ -7170,29 +7158,6 @@ static int nf_tables_delsetelem(struct sk_buff *skb, · 67 unmodified lines | |||
| 7170 | return err; | 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 | * Stateful objects | 7162 | * Stateful objects |
| 7198 | */ | 7163 | */ |
| @@ -9414,6 +9379,207 @@ void nft_chain_del(struct nft_chain *chain) · 2215 unmodified lines | |||
| 9414 | list_del_rcu(&chain->list); | 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 | static void nf_tables_module_autoload_cleanup(struct net *net) | 9583 | static void nf_tables_module_autoload_cleanup(struct net *net) |
| 9418 | { | 9584 | { |
| 9419 | struct nftables_pernet *nft_net = nft_pernet(net); | 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 | struct nftables_pernet *nft_net = nft_pernet(net); | 9743 | struct nftables_pernet *nft_net = nft_pernet(net); |
| 9578 | struct nft_trans *trans, *next; | 9744 | struct nft_trans *trans, *next; |
| 9745 | unsigned int base_seq, gc_seq; | ||
| 9579 | LIST_HEAD(set_update_list); | 9746 | LIST_HEAD(set_update_list); |
| 9580 | struct nft_trans_elem *te; | 9747 | struct nft_trans_elem *te; |
| 9581 | struct nft_chain *chain; | 9748 | struct nft_chain *chain; |
| 9582 | struct nft_table *table; | 9749 | struct nft_table *table; |
| 9583 | unsigned int base_seq; | ||
| 9584 | LIST_HEAD(adl); | 9750 | LIST_HEAD(adl); |
| 9585 | int err; | 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 | WRITE_ONCE(nft_net->base_seq, base_seq); | 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 | /* step 3. Start new generation, rules_gen_X now in use. */ | 9830 | /* step 3. Start new generation, rules_gen_X now in use. */ |
| 9661 | net->nft.gencursor = nft_gencursor_next(net); | 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 | break; | 9934 | break; |
| 9765 | case NFT_MSG_DELSET: | 9935 | case NFT_MSG_DELSET: |
| 9766 | case NFT_MSG_DESTROYSET: | 9936 | case NFT_MSG_DESTROYSET: |
| 9937 | nft_trans_set(trans)->dead = 1; | ||
| 9767 | list_del_rcu(&nft_trans_set(trans)->list); | 9938 | list_del_rcu(&nft_trans_set(trans)->list); |
| 9768 | nf_tables_set_notify(&trans->ctx, nft_trans_set(trans), | 9939 | nf_tables_set_notify(&trans->ctx, nft_trans_set(trans), |
| 9769 | trans->msg_type, GFP_KERNEL); | 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 | nft_commit_notify(net, NETLINK_CB(skb).portid); | 10037 | nft_commit_notify(net, NETLINK_CB(skb).portid); |
| 9867 | nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); | 10038 | nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); |
| 9868 | nf_tables_commit_audit_log(&adl, nft_net->base_seq); | 10039 | nf_tables_commit_audit_log(&adl, nft_net->base_seq); |
| 10040 | |||
| 10041 | WRITE_ONCE(nft_net->gc_seq, ++gc_seq); | ||
| 9869 | nf_tables_commit_release(net); | 10042 | nf_tables_commit_release(net); |
| 9870 | 10043 | ||
| 9871 | return 0; | 10044 | return 0; |
| @@ -10915,6 +11088,7 @@ static int __net_init nf_tables_init_net(struct net *net) · 1043 unmodified lines | |||
| 10915 | INIT_LIST_HEAD(&nft_net->notify_list); | 11088 | INIT_LIST_HEAD(&nft_net->notify_list); |
| 10916 | mutex_init(&nft_net->commit_mutex); | 11089 | mutex_init(&nft_net->commit_mutex); |
| 10917 | nft_net->base_seq = 1; | 11090 | nft_net->base_seq = 1; |
| 11091 | nft_net->gc_seq = 0; | ||
| 10918 | 11092 | ||
| 10919 | return 0; | 11093 | return 0; |
| 10920 | } | 11094 | } |
| @@ -10943,10 +11117,16 @@ static void __net_exit nf_tables_exit_net(struct net *net) · 22 unmodified lines | |||
| 10943 | WARN_ON_ONCE(!list_empty(&nft_net->notify_list)); | 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 | static struct pernet_operations nf_tables_net_ops = { | 11125 | static struct pernet_operations nf_tables_net_ops = { |
| 10947 | .init = nf_tables_init_net, | 11126 | .init = nf_tables_init_net, |
| 10948 | .pre_exit = nf_tables_pre_exit_net, | 11127 | .pre_exit = nf_tables_pre_exit_net, |
| 10949 | .exit = nf_tables_exit_net, | 11128 | .exit = nf_tables_exit_net, |
| 11129 | .exit_batch = nf_tables_exit_batch, | ||
| 10950 | .id = &nf_tables_net_id, | 11130 | .id = &nf_tables_net_id, |
| 10951 | .size = sizeof(struct nftables_pernet), | 11131 | .size = sizeof(struct nftables_pernet), |
| 10952 | }; | 11132 | }; |
| @@ -11018,6 +11198,7 @@ static void __exit nf_tables_module_exit(void) · 65 unmodified lines | |||
| 11018 | nft_chain_filter_fini(); | 11198 | nft_chain_filter_fini(); |
| 11019 | nft_chain_route_fini(); | 11199 | nft_chain_route_fini(); |
| 11020 | unregister_pernet_subsys(&nf_tables_net_ops); | 11200 | unregister_pernet_subsys(&nf_tables_net_ops); |
| 11201 | cancel_work_sync(&trans_gc_work); | ||
| 11021 | cancel_work_sync(&trans_destroy_work); | 11202 | cancel_work_sync(&trans_destroy_work); |
| 11022 | rcu_barrier(); | 11203 | rcu_barrier(); |
| 11023 | rhltable_destroy(&nft_objname_ht); | 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 | if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) | 60 | if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) |
| 61 | return 1; | 61 | return 1; |
| 62 | if (nft_set_elem_is_dead(&he->ext)) | ||
| 63 | return 1; | ||
| 62 | if (nft_set_elem_expired(&he->ext)) | 64 | if (nft_set_elem_expired(&he->ext)) |
| 63 | return 1; | 65 | return 1; |
| 64 | if (!nft_set_elem_active(&he->ext, x->genmask)) | 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 | struct nft_rhash_elem *he = elem->priv; | 190 | struct nft_rhash_elem *he = elem->priv; |
| 189 | 191 | ||
| 190 | nft_set_elem_change_active(net, set, &he->ext); | 192 | nft_set_elem_change_active(net, set, &he->ext); |
| 191 | nft_set_elem_clear_busy(&he->ext); | ||
| 192 | } | 193 | } |
| 193 | 194 | ||
| 194 | static bool nft_rhash_flush(const struct net *net, | 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 | struct nft_rhash_elem *he = priv; | 198 | struct nft_rhash_elem *he = priv; |
| 198 | 199 | ||
| 199 | if (!nft_set_elem_mark_busy(&he->ext) || | 200 | nft_set_elem_change_active(net, set, &he->ext); |
| 200 | !nft_is_active(net, &he->ext)) { | 201 | |
| 201 | nft_set_elem_change_active(net, set, &he->ext); | 202 | return true; |
| 202 | return true; | ||
| 203 | } | ||
| 204 | return false; | ||
| 205 | } | 203 | } |
| 206 | 204 | ||
| 207 | static void *nft_rhash_deactivate(const struct net *net, | 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 | rcu_read_lock(); | 217 | rcu_read_lock(); |
| 220 | he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params); | 218 | he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params); |
| 221 | if (he != NULL && | 219 | if (he) |
| 222 | !nft_rhash_flush(net, set, he)) | 220 | nft_set_elem_change_active(net, set, &he->ext); |
| 223 | he = NULL; | ||
| 224 | 221 | ||
| 225 | rcu_read_unlock(); | 222 | rcu_read_unlock(); |
| 226 | 223 | ||
| @@ -252,7 +249,9 @@ static bool nft_rhash_delete(const struct nft_set *set, · 25 unmodified lines | |||
| 252 | if (he == NULL) | 249 | if (he == NULL) |
| 253 | return false; | 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 | static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, | 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 | if (iter->count < iter->skip) | 278 | if (iter->count < iter->skip) |
| 280 | goto cont; | 279 | goto cont; |
| 281 | if (nft_set_elem_expired(&he->ext)) | ||
| 282 | goto cont; | ||
| 283 | if (!nft_set_elem_active(&he->ext, iter->genmask)) | 280 | if (!nft_set_elem_active(&he->ext, iter->genmask)) |
| 284 | goto cont; | 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 | static void nft_rhash_gc(struct work_struct *work) | 312 | static void nft_rhash_gc(struct work_struct *work) |
| 316 | { | 313 | { |
| 314 | struct nftables_pernet *nft_net; | ||
| 317 | struct nft_set *set; | 315 | struct nft_set *set; |
| 318 | struct nft_rhash_elem *he; | 316 | struct nft_rhash_elem *he; |
| 319 | struct nft_rhash *priv; | 317 | struct nft_rhash *priv; |
| 320 | struct nft_set_gc_batch *gcb = NULL; | ||
| 321 | struct rhashtable_iter hti; | 318 | struct rhashtable_iter hti; |
| 319 | struct nft_trans_gc *gc; | ||
| 320 | struct net *net; | ||
| 321 | u32 gc_seq; | ||
| 322 | 322 | ||
| 323 | priv = container_of(work, struct nft_rhash, gc_work.work); | 323 | priv = container_of(work, struct nft_rhash, gc_work.work); |
| 324 | set = nft_set_container_of(priv); | 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 | rhashtable_walk_enter(&priv->ht, &hti); | 333 | rhashtable_walk_enter(&priv->ht, &hti); |
| 327 | rhashtable_walk_start(&hti); | 334 | rhashtable_walk_start(&hti); |
| 328 | 335 | ||
| 329 | while ((he = rhashtable_walk_next(&hti))) { | 336 | while ((he = rhashtable_walk_next(&hti))) { |
| 330 | if (IS_ERR(he)) { | 337 | if (IS_ERR(he)) { |
| 331 | if (PTR_ERR(he) != -EAGAIN) | 338 | if (PTR_ERR(he) != -EAGAIN) { |
| 332 | break; | 339 | nft_trans_gc_destroy(gc); |
| 340 | gc = NULL; | ||
| 341 | goto try_later; | ||
| 342 | } | ||
| 333 | continue; | 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 | if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPRESSIONS) && | 356 | if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPRESSIONS) && |
| 337 | nft_rhash_expr_needs_gc_run(set, &he->ext)) | 357 | nft_rhash_expr_needs_gc_run(set, &he->ext)) |
| 338 | goto needs_gc_run; | 358 | goto needs_gc_run; |
| @@ -340,26 +360,26 @@ static void nft_rhash_gc(struct work_struct *work) · 1 unmodified line | |||
| 340 | if (!nft_set_elem_expired(&he->ext)) | 360 | if (!nft_set_elem_expired(&he->ext)) |
| 341 | continue; | 361 | continue; |
| 342 | needs_gc_run: | 362 | needs_gc_run: |
| 343 | if (nft_set_elem_mark_busy(&he->ext)) | 363 | nft_set_elem_dead(&he->ext); |
| 344 | continue; | 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); | 369 | nft_trans_gc_elem_add(gc, he); |
| 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); | ||
| 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 | rhashtable_walk_stop(&hti); | 376 | rhashtable_walk_stop(&hti); |
| 354 | rhashtable_walk_exit(&hti); | 377 | rhashtable_walk_exit(&hti); |
| 355 | 378 | ||
| 356 | he = nft_set_catchall_gc(set); | 379 | if (gc) |
| 357 | if (he) { | 380 | nft_trans_gc_queue_async_done(gc); |
| 358 | gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); | 381 | |
| 359 | if (gcb) | 382 | done: |
| 360 | nft_set_gc_batch_add(gcb, he); | ||
| 361 | } | ||
| 362 | nft_set_gc_batch_complete(gcb); | ||
| 363 | queue_delayed_work(system_power_efficient_wq, &priv->gc_work, | 383 | queue_delayed_work(system_power_efficient_wq, &priv->gc_work, |
| 364 | nft_set_gc_interval(set)); | 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 | return err; | 414 | return err; |
| 395 | 415 | ||
| 396 | INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc); | 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 | nft_rhash_gc_init(set); | 418 | nft_rhash_gc_init(set); |
| 399 | 419 | ||
| 400 | return 0; | 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 | cancel_delayed_work_sync(&priv->gc_work); | 444 | cancel_delayed_work_sync(&priv->gc_work); |
| 425 | rcu_barrier(); | ||
| 426 | rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy, | 445 | rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy, |
| 427 | (void *)&rhash_ctx); | 446 | (void *)&rhash_ctx); |
| 428 | } | 447 | } |
| @@ -566,8 +566,7 @@ next_match: · 565 unmodified lines | |||
| 566 | goto out; | 566 | goto out; |
| 567 | 567 | ||
| 568 | if (last) { | 568 | if (last) { |
| 569 | if (nft_set_elem_expired(&f->mt[b].e->ext) || | 569 | if ((genmask && |
| 570 | (genmask && | ||
| 571 | !nft_set_elem_active(&f->mt[b].e->ext, genmask))) | 570 | !nft_set_elem_active(&f->mt[b].e->ext, genmask))) |
| 572 | goto next_match; | 571 | goto next_match; |
| 573 | 572 | ||
| @@ -601,8 +600,17 @@ out: · 27 unmodified lines | |||
| 601 | static void *nft_pipapo_get(const struct net *net, const struct nft_set *set, | 600 | static void *nft_pipapo_get(const struct net *net, const struct nft_set *set, |
| 602 | const struct nft_set_elem *elem, unsigned int flags) | 601 | const struct nft_set_elem *elem, unsigned int flags) |
| 603 | { | 602 | { |
| 604 | return pipapo_get(net, set, (const u8 *)elem->key.val.data, | 603 | struct nft_pipapo_elem *ret; |
| 605 | nft_genmask_cur(net)); | 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 | * pipapo_gc() - Drop expired entries from set, destroy start and end elements | 1551 | * pipapo_gc() - Drop expired entries from set, destroy start and end elements |
| 1533 | * @set: nftables API set representation | 1552 | * @set: nftables API set representation |
| 1534 | * @m: Matching data | 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 | struct nft_pipapo *priv = nft_set_priv(set); | 1558 | struct nft_pipapo *priv = nft_set_priv(set); |
| 1559 | struct net *net = read_pnet(&set->net); | ||
| 1539 | int rules_f0, first_rule = 0; | 1560 | int rules_f0, first_rule = 0; |
| 1540 | struct nft_pipapo_elem *e; | 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 | while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) { | 1568 | while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) { |
| 1543 | union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS]; | 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 | f--; | 1587 | f--; |
| 1562 | i--; | 1588 | i--; |
| 1563 | e = f->mt[rulemap[i].to].e; | 1589 | e = f->mt[rulemap[i].to].e; |
| 1564 | if (nft_set_elem_expired(&e->ext) && | 1590 | |
| 1565 | !nft_set_elem_mark_busy(&e->ext)) { | 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 | priv->dirty = true; | 1595 | priv->dirty = true; |
| 1567 | pipapo_drop(m, rulemap); | ||
| 1568 | 1596 | ||
| 1569 | rcu_barrier(); | 1597 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); |
| 1570 | nft_set_elem_destroy(set, e, true); | 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 | /* And check again current first rule, which is now the | 1605 | /* And check again current first rule, which is now the |
| 1573 | * first we haven't checked. | 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); | 1613 | gc = nft_trans_gc_catchall(gc, 0); |
| 1581 | if (e) | 1614 | if (gc) { |
| 1582 | nft_set_elem_destroy(set, e, true); | 1615 | nft_trans_gc_queue_sync_done(gc); |
| 1583 | 1616 | priv->last_gc = jiffies; | |
| 1584 | 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 | return; | 1739 | return; |
| 1707 | 1740 | ||
| 1708 | nft_set_elem_change_active(net, set, &e->ext); | 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 | goto cont; | 2037 | goto cont; |
| 2006 | 2038 | ||
| 2007 | e = f->mt[r].e; | 2039 | e = f->mt[r].e; |
| 2008 | if (nft_set_elem_expired(&e->ext)) | ||
| 2009 | goto cont; | ||
| 2010 | 2040 | ||
| 2011 | elem.priv = e; | 2041 | elem.priv = e; |
| 2012 | 2042 | ||
| @@ -46,6 +46,12 @@ static int nft_rbtree_cmp(const struct nft_set *set, · 45 unmodified lines | |||
| 46 | set->klen); | 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 | static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set, | 55 | static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set, |
| 50 | const u32 *key, const struct nft_set_ext **ext, | 56 | const u32 *key, const struct nft_set_ext **ext, |
| 51 | unsigned int seq) | 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 | continue; | 86 | continue; |
| 81 | } | 87 | } |
| 82 | 88 | ||
| 83 | if (nft_set_elem_expired(&rbe->ext)) | 89 | if (nft_rbtree_elem_expired(rbe)) |
| 84 | return false; | 90 | return false; |
| 85 | 91 | ||
| 86 | if (nft_rbtree_interval_end(rbe)) { | 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 | if (set->flags & NFT_SET_INTERVAL && interval != NULL && | 105 | if (set->flags & NFT_SET_INTERVAL && interval != NULL && |
| 100 | nft_set_elem_active(&interval->ext, genmask) && | 106 | nft_set_elem_active(&interval->ext, genmask) && |
| 101 | !nft_set_elem_expired(&interval->ext) && | 107 | !nft_rbtree_elem_expired(interval) && |
| 102 | nft_rbtree_interval_start(interval)) { | 108 | nft_rbtree_interval_start(interval)) { |
| 103 | *ext = &interval->ext; | 109 | *ext = &interval->ext; |
| 104 | return true; | 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 | return rbe; | 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 | static int nft_rbtree_gc_elem(const struct nft_set *__set, | 236 | static int nft_rbtree_gc_elem(const struct nft_set *__set, |
| 219 | struct nft_rbtree *priv, | 237 | struct nft_rbtree *priv, |
| 220 | struct nft_rbtree_elem *rbe, | 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 | struct nft_set *set = (struct nft_set *)__set; | 241 | struct nft_set *set = (struct nft_set *)__set; |
| 224 | struct rb_node *prev = rb_prev(&rbe->node); | 242 | struct rb_node *prev = rb_prev(&rbe->node); |
| 243 | struct net *net = read_pnet(&set->net); | ||
| 225 | struct nft_rbtree_elem *rbe_prev; | 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); | 247 | gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); |
| 229 | if (!gcb) | 248 | if (!gc) |
| 230 | return -ENOMEM; | 249 | return -ENOMEM; |
| 231 | 250 | ||
| 232 | /* search for end interval coming before this element. | 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 | if (prev) { | 264 | if (prev) { |
| 246 | rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); | 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); | 268 | /* There is always room in this trans gc for this element, |
| 249 | atomic_dec(&set->nelems); | 269 | * memory allocation never actually happens, hence, the warning |
| 250 | nft_set_gc_batch_add(gcb, rbe_prev); | 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); | 280 | nft_rbtree_gc_remove(net, set, priv, rbe); |
| 254 | atomic_dec(&set->nelems); | 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); | 287 | nft_trans_gc_queue_sync_done(gc); |
| 257 | nft_set_gc_batch_complete(gcb); | ||
| 258 | 288 | ||
| 259 | return 0; | 289 | return 0; |
| 260 | } | 290 | } |
| @@ -482,7 +512,6 @@ static void nft_rbtree_activate(const struct net *net, · 221 unmodified lines | |||
| 482 | struct nft_rbtree_elem *rbe = elem->priv; | 512 | struct nft_rbtree_elem *rbe = elem->priv; |
| 483 | 513 | ||
| 484 | nft_set_elem_change_active(net, set, &rbe->ext); | 514 | nft_set_elem_change_active(net, set, &rbe->ext); |
| 485 | nft_set_elem_clear_busy(&rbe->ext); | ||
| 486 | } | 515 | } |
| 487 | 516 | ||
| 488 | static bool nft_rbtree_flush(const struct net *net, | 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 | struct nft_rbtree_elem *rbe = priv; | 520 | struct nft_rbtree_elem *rbe = priv; |
| 492 | 521 | ||
| 493 | if (!nft_set_elem_mark_busy(&rbe->ext) || | 522 | nft_set_elem_change_active(net, set, &rbe->ext); |
| 494 | !nft_is_active(net, &rbe->ext)) { | 523 | |
| 495 | nft_set_elem_change_active(net, set, &rbe->ext); | 524 | return true; |
| 496 | return true; | ||
| 497 | } | ||
| 498 | return false; | ||
| 499 | } | 525 | } |
| 500 | 526 | ||
| 501 | static void *nft_rbtree_deactivate(const struct net *net, | 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 | if (iter->count < iter->skip) | 579 | if (iter->count < iter->skip) |
| 554 | goto cont; | 580 | goto cont; |
| 555 | if (nft_set_elem_expired(&rbe->ext)) | ||
| 556 | goto cont; | ||
| 557 | if (!nft_set_elem_active(&rbe->ext, iter->genmask)) | 581 | if (!nft_set_elem_active(&rbe->ext, iter->genmask)) |
| 558 | goto cont; | 582 | goto cont; |
| 559 | 583 | ||
| @@ -572,26 +596,40 @@ cont: · 12 unmodified lines | |||
| 572 | 596 | ||
| 573 | static void nft_rbtree_gc(struct work_struct *work) | 597 | static void nft_rbtree_gc(struct work_struct *work) |
| 574 | { | 598 | { |
| 575 | struct nft_rbtree_elem *rbe, *rbe_end = NULL, *rbe_prev = NULL; | 599 | struct nft_rbtree_elem *rbe, *rbe_end = NULL; |
| 576 | struct nft_set_gc_batch *gcb = NULL; | 600 | struct nftables_pernet *nft_net; |
| 577 | struct nft_rbtree *priv; | 601 | struct nft_rbtree *priv; |
| 602 | struct nft_trans_gc *gc; | ||
| 578 | struct rb_node *node; | 603 | struct rb_node *node; |
| 579 | struct nft_set *set; | 604 | struct nft_set *set; |
| 605 | unsigned int gc_seq; | ||
| 580 | struct net *net; | 606 | struct net *net; |
| 581 | u8 genmask; | ||
| 582 | 607 | ||
| 583 | priv = container_of(work, struct nft_rbtree, gc_work.work); | 608 | priv = container_of(work, struct nft_rbtree, gc_work.work); |
| 584 | set = nft_set_container_of(priv); | 609 | set = nft_set_container_of(priv); |
| 585 | net = read_pnet(&set->net); | 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 | write_lock_bh(&priv->lock); | 618 | write_lock_bh(&priv->lock); |
| 589 | write_seqcount_begin(&priv->count); | 619 | write_seqcount_begin(&priv->count); |
| 590 | for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) { | 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 | rbe = rb_entry(node, struct nft_rbtree_elem, node); | 629 | rbe = rb_entry(node, struct nft_rbtree_elem, node); |
| 592 | 630 | ||
| 593 | if (!nft_set_elem_active(&rbe->ext, genmask)) | 631 | if (nft_set_elem_is_dead(&rbe->ext)) |
| 594 | continue; | 632 | goto dead_elem; |
| 595 | 633 | ||
| 596 | /* elements are reversed in the rbtree for historical reasons, | 634 | /* elements are reversed in the rbtree for historical reasons, |
| 597 | * from highest to lowest value, that is why end element is | 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 | if (!nft_set_elem_expired(&rbe->ext)) | 642 | if (!nft_set_elem_expired(&rbe->ext)) |
| 605 | continue; | 643 | continue; |
| 606 | 644 | ||
| 607 | if (nft_set_elem_mark_busy(&rbe->ext)) { | 645 | nft_set_elem_dead(&rbe->ext); |
| 608 | rbe_end = NULL; | 646 | |
| 647 | if (!rbe_end) | ||
| 609 | continue; | 648 | continue; |
| 610 | } | ||
| 611 | 649 | ||
| 612 | if (rbe_prev) { | 650 | nft_set_elem_dead(&rbe_end->ext); |
| 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; | ||
| 619 | 651 | ||
| 620 | atomic_dec(&set->nelems); | 652 | gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); |
| 621 | nft_set_gc_batch_add(gcb, rbe); | 653 | if (!gc) |
| 622 | rbe_prev = rbe; | 654 | goto try_later; |
| 623 | 655 | ||
| 624 | if (rbe_end) { | 656 | nft_trans_gc_elem_add(gc, rbe_end); |
| 625 | atomic_dec(&set->nelems); | 657 | rbe_end = NULL; |
| 626 | nft_set_gc_batch_add(gcb, rbe_end); | 658 | dead_elem: |
| 627 | rb_erase(&rbe_end->node, &priv->root); | 659 | gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); |
| 628 | rbe_end = NULL; | 660 | if (!gc) |
| 629 | } | 661 | goto try_later; |
| 630 | node = rb_next(node); | 662 | |
| 631 | if (!node) | 663 | nft_trans_gc_elem_add(gc, rbe); |
| 632 | break; | ||
| 633 | } | 664 | } |
| 634 | if (rbe_prev) | 665 | |
| 635 | rb_erase(&rbe_prev->node, &priv->root); | 666 | gc = nft_trans_gc_catchall(gc, gc_seq); |
| 667 | |||
| 668 | try_later: | ||
| 636 | write_seqcount_end(&priv->count); | 669 | write_seqcount_end(&priv->count); |
| 637 | write_unlock_bh(&priv->lock); | 670 | write_unlock_bh(&priv->lock); |
| 638 | 671 | ||
| 639 | rbe = nft_set_catchall_gc(set); | 672 | if (gc) |
| 640 | if (rbe) { | 673 | nft_trans_gc_queue_async_done(gc); |
| 641 | gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); | 674 | done: |
| 642 | if (gcb) | ||
| 643 | nft_set_gc_batch_add(gcb, rbe); | ||
| 644 | } | ||
| 645 | nft_set_gc_batch_complete(gcb); | ||
| 646 | |||
| 647 | queue_delayed_work(system_power_efficient_wq, &priv->gc_work, | 675 | queue_delayed_work(system_power_efficient_wq, &priv->gc_work, |
| 648 | nft_set_gc_interval(set)); | 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 | break; | 107 | break; |
| 108 | case NFT_SOCKET_MARK: | 108 | case NFT_SOCKET_MARK: |
| 109 | if (sk_fullsock(sk)) { | 109 | if (sk_fullsock(sk)) { |
| 110 | *dest = sk->sk_mark; | 110 | *dest = READ_ONCE(sk->sk_mark); |
| 111 | } else { | 111 | } else { |
| 112 | regs->verdict.code = NFT_BREAK; | 112 | regs->verdict.code = NFT_BREAK; |
| 113 | return; | 113 | return; |
| @@ -77,7 +77,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, · 76 unmodified lines | |||
| 77 | 77 | ||
| 78 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && | 78 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && |
| 79 | transparent && sk_fullsock(sk)) | 79 | transparent && sk_fullsock(sk)) |
| 80 | pskb->mark = sk->sk_mark; | 80 | pskb->mark = READ_ONCE(sk->sk_mark); |
| 81 | 81 | ||
| 82 | if (sk != skb->sk) | 82 | if (sk != skb->sk) |
| 83 | sock_gen_put(sk); | 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 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && | 139 | if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && |
| 140 | transparent && sk_fullsock(sk)) | 140 | transparent && sk_fullsock(sk)) |
| 141 | pskb->mark = sk->sk_mark; | 141 | pskb->mark = READ_ONCE(sk->sk_mark); |
| 142 | 142 | ||
| 143 | if (sk != skb->sk) | 143 | if (sk != skb->sk) |
| 144 | sock_gen_put(sk); | 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 | union tpacket_uhdr h; | 402 | union tpacket_uhdr h; |
| 403 | 403 | ||
| 404 | /* WRITE_ONCE() are paired with READ_ONCE() in __packet_get_status */ | ||
| 405 | |||
| 404 | h.raw = frame; | 406 | h.raw = frame; |
| 405 | switch (po->tp_version) { | 407 | switch (po->tp_version) { |
| 406 | case TPACKET_V1: | 408 | case TPACKET_V1: |
| 407 | h.h1->tp_status = status; | 409 | WRITE_ONCE(h.h1->tp_status, status); |
| 408 | flush_dcache_page(pgv_to_page(&h.h1->tp_status)); | 410 | flush_dcache_page(pgv_to_page(&h.h1->tp_status)); |
| 409 | break; | 411 | break; |
| 410 | case TPACKET_V2: | 412 | case TPACKET_V2: |
| 411 | h.h2->tp_status = status; | 413 | WRITE_ONCE(h.h2->tp_status, status); |
| 412 | flush_dcache_page(pgv_to_page(&h.h2->tp_status)); | 414 | flush_dcache_page(pgv_to_page(&h.h2->tp_status)); |
| 413 | break; | 415 | break; |
| 414 | case TPACKET_V3: | 416 | case TPACKET_V3: |
| 415 | h.h3->tp_status = status; | 417 | WRITE_ONCE(h.h3->tp_status, status); |
| 416 | flush_dcache_page(pgv_to_page(&h.h3->tp_status)); | 418 | flush_dcache_page(pgv_to_page(&h.h3->tp_status)); |
| 417 | break; | 419 | break; |
| 418 | default: | 420 | default: |
| @@ -429,17 +431,19 @@ static int __packet_get_status(const struct packet_sock *po, void *frame) · 10 unmodified lines | |||
| 429 | 431 | ||
| 430 | smp_rmb(); | 432 | smp_rmb(); |
| 431 | 433 | ||
| 434 | /* READ_ONCE() are paired with WRITE_ONCE() in __packet_set_status */ | ||
| 435 | |||
| 432 | h.raw = frame; | 436 | h.raw = frame; |
| 433 | switch (po->tp_version) { | 437 | switch (po->tp_version) { |
| 434 | case TPACKET_V1: | 438 | case TPACKET_V1: |
| 435 | flush_dcache_page(pgv_to_page(&h.h1->tp_status)); | 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 | case TPACKET_V2: | 441 | case TPACKET_V2: |
| 438 | flush_dcache_page(pgv_to_page(&h.h2->tp_status)); | 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 | case TPACKET_V3: | 444 | case TPACKET_V3: |
| 441 | flush_dcache_page(pgv_to_page(&h.h3->tp_status)); | 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 | default: | 447 | default: |
| 444 | WARN(1, "TPACKET version not supported.\n"); | 448 | WARN(1, "TPACKET version not supported.\n"); |
| 445 | BUG(); | 449 | BUG(); |
| @@ -2050,8 +2054,8 @@ retry: · 1604 unmodified lines | |||
| 2050 | 2054 | ||
| 2051 | skb->protocol = proto; | 2055 | skb->protocol = proto; |
| 2052 | skb->dev = dev; | 2056 | skb->dev = dev; |
| 2053 | skb->priority = sk->sk_priority; | 2057 | skb->priority = READ_ONCE(sk->sk_priority); |
| 2054 | skb->mark = sk->sk_mark; | 2058 | skb->mark = READ_ONCE(sk->sk_mark); |
| 2055 | skb->tstamp = sockc.transmit_time; | 2059 | skb->tstamp = sockc.transmit_time; |
| 2056 | 2060 | ||
| 2057 | skb_setup_tx_timestamp(skb, sockc.tsflags); | 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 | skb->protocol = proto; | 2590 | skb->protocol = proto; |
| 2587 | skb->dev = dev; | 2591 | skb->dev = dev; |
| 2588 | skb->priority = po->sk.sk_priority; | 2592 | skb->priority = READ_ONCE(po->sk.sk_priority); |
| 2589 | skb->mark = po->sk.sk_mark; | 2593 | skb->mark = READ_ONCE(po->sk.sk_mark); |
| 2590 | skb->tstamp = sockc->transmit_time; | 2594 | skb->tstamp = sockc->transmit_time; |
| 2591 | skb_setup_tx_timestamp(skb, sockc->tsflags); | 2595 | skb_setup_tx_timestamp(skb, sockc->tsflags); |
| 2592 | skb_zcopy_set_nouarg(skb, ph.raw); | 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 | goto out_unlock; | 2992 | goto out_unlock; |
| 2989 | 2993 | ||
| 2990 | sockcm_init(&sockc, sk); | 2994 | sockcm_init(&sockc, sk); |
| 2991 | sockc.mark = sk->sk_mark; | 2995 | sockc.mark = READ_ONCE(sk->sk_mark); |
| 2992 | if (msg->msg_controllen) { | 2996 | if (msg->msg_controllen) { |
| 2993 | err = sock_cmsg_send(sk, msg, &sockc); | 2997 | err = sock_cmsg_send(sk, msg, &sockc); |
| 2994 | if (unlikely(err)) | 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 | skb->protocol = proto; | 3066 | skb->protocol = proto; |
| 3063 | skb->dev = dev; | 3067 | skb->dev = dev; |
| 3064 | skb->priority = sk->sk_priority; | 3068 | skb->priority = READ_ONCE(sk->sk_priority); |
| 3065 | skb->mark = sockc.mark; | 3069 | skb->mark = sockc.mark; |
| 3066 | skb->tstamp = sockc.transmit_time; | 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 | [TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL] = { .type = NLA_U32 }, | 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 | [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, | 781 | [TCA_FLOWER_KEY_CFM_MD_LEVEL] = NLA_POLICY_MAX(NLA_U8, |
| 781 | FLOW_DIS_CFM_MDL_MAX), | 782 | FLOW_DIS_CFM_MDL_MAX), |
| 782 | [TCA_FLOWER_KEY_CFM_OPCODE] = { .type = NLA_U8 }, | 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 | struct fl_flow_key *mask, | 1710 | struct fl_flow_key *mask, |
| 1710 | struct netlink_ext_ack *extack) | 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 | int err; | 1714 | int err; |
| 1714 | 1715 | ||
| 1715 | if (!tb[TCA_FLOWER_KEY_CFM]) | 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 | return -ENOBUFS; | 267 | return -ENOBUFS; |
| 268 | 268 | ||
| 269 | fnew->id = f->id; | 269 | fnew->id = f->id; |
| 270 | fnew->res = f->res; | ||
| 271 | fnew->ifindex = f->ifindex; | 270 | fnew->ifindex = f->ifindex; |
| 272 | fnew->tp = f->tp; | 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 | if (fold) { | 513 | if (fold) { |
| 514 | f->id = fold->id; | 514 | f->id = fold->id; |
| 515 | f->iif = fold->iif; | 515 | f->iif = fold->iif; |
| 516 | f->res = fold->res; | ||
| 517 | f->handle = fold->handle; | 516 | f->handle = fold->handle; |
| 518 | 517 | ||
| 519 | f->tp = fold->tp; | 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 | new->ifindex = n->ifindex; | 827 | new->ifindex = n->ifindex; |
| 828 | new->fshift = n->fshift; | 828 | new->fshift = n->fshift; |
| 829 | new->res = n->res; | ||
| 830 | new->flags = n->flags; | 829 | new->flags = n->flags; |
| 831 | RCU_INIT_POINTER(new->ht_down, ht); | 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 | return -EINVAL; | 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 | if (handle) { | 1047 | if (handle) { |
| 1048 | /* Rule: The htid from handle and tableid from htid must match */ | ||
| 1028 | if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid)) { | 1049 | if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid)) { |
| 1029 | NL_SET_ERR_MSG_MOD(extack, "Handle specified hash table address mismatch"); | 1050 | NL_SET_ERR_MSG_MOD(extack, "Handle specified hash table address mismatch"); |
| 1030 | return -EINVAL; | 1051 | return -EINVAL; |
| 1031 | } | 1052 | } |
| 1032 | handle = htid | TC_U32_NODE(handle); | 1053 | /* Ok, so far we have a valid htid(12b):bucketid(8b) but we |
| 1033 | err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, handle, | 1054 | * need to finalize the table entry identification with the last |
| 1034 | GFP_KERNEL); | 1055 | * part - the node/entryid(12b)). Rule: Nodeid _cannot be 0_ for |
| 1035 | if (err) | 1056 | * entries. Rule: nodeid of 0 is reserved only for tables(see |
| 1036 | return err; | 1057 | * earlier code which processes TC_U32_DIVISOR attribute). |
| 1037 | } else | 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 | handle = gen_new_kid(ht, htid); | 1080 | handle = gen_new_kid(ht, htid); |
| 1081 | } | ||
| 1039 | 1082 | ||
| 1040 | if (tb[TCA_U32_SEL] == NULL) { | 1083 | if (tb[TCA_U32_SEL] == NULL) { |
| 1041 | NL_SET_ERR_MSG_MOD(extack, "Selector not specified"); | 1084 | NL_SET_ERR_MSG_MOD(extack, "Selector not specified"); |
| @@ -568,7 +568,7 @@ META_COLLECTOR(int_sk_rcvtimeo) · 567 unmodified lines | |||
| 568 | *err = -1; | 568 | *err = -1; |
| 569 | return; | 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 | META_COLLECTOR(int_sk_sndtimeo) | 574 | META_COLLECTOR(int_sk_sndtimeo) |
| @@ -579,7 +579,7 @@ META_COLLECTOR(int_sk_sndtimeo) · 4 unmodified lines | |||
| 579 | *err = -1; | 579 | *err = -1; |
| 580 | return; | 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 | META_COLLECTOR(int_sk_sendmsg_off) | 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 | TC_FP_PREEMPTIBLE), | 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 | static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = { | 1023 | static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = { |
| 1019 | [TCA_TAPRIO_ATTR_PRIOMAP] = { | 1024 | [TCA_TAPRIO_ATTR_PRIOMAP] = { |
| 1020 | .len = sizeof(struct tc_mqprio_qopt) | 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 | [TCA_TAPRIO_ATTR_SCHED_BASE_TIME] = { .type = NLA_S64 }, | 1028 | [TCA_TAPRIO_ATTR_SCHED_BASE_TIME] = { .type = NLA_S64 }, |
| 1024 | [TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY] = { .type = NLA_NESTED }, | 1029 | [TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY] = { .type = NLA_NESTED }, |
| 1025 | [TCA_TAPRIO_ATTR_SCHED_CLOCKID] = { .type = NLA_S32 }, | 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 | [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 }, | 1033 | [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 }, |
| 1028 | [TCA_TAPRIO_ATTR_FLAGS] = { .type = NLA_U32 }, | 1034 | [TCA_TAPRIO_ATTR_FLAGS] = { .type = NLA_U32 }, |
| 1029 | [TCA_TAPRIO_ATTR_TXTIME_DELAY] = { .type = NLA_U32 }, | 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 | return -EINVAL; | 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 | new->cycle_time = cycle; | 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 | struct sched_gate_list *sched, ktime_t base) | 1358 | struct sched_gate_list *sched, ktime_t base) |
| 1348 | { | 1359 | { |
| 1349 | struct sched_entry *entry; | 1360 | struct sched_entry *entry; |
| 1350 | u32 interval = 0; | 1361 | u64 interval = 0; |
| 1351 | 1362 | ||
| 1352 | list_for_each_entry(entry, &sched->entries, list) { | 1363 | list_for_each_entry(entry, &sched->entries, list) { |
| 1353 | entry->next_txtime = ktime_add_ns(base, interval); | 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 | sk->sk_state = SMC_INIT; | 378 | sk->sk_state = SMC_INIT; |
| 379 | sk->sk_destruct = smc_destruct; | 379 | sk->sk_destruct = smc_destruct; |
| 380 | sk->sk_protocol = protocol; | 380 | sk->sk_protocol = protocol; |
| 381 | WRITE_ONCE(sk->sk_sndbuf, READ_ONCE(net->smc.sysctl_wmem)); | 381 | WRITE_ONCE(sk->sk_sndbuf, 2 * READ_ONCE(net->smc.sysctl_wmem)); |
| 382 | WRITE_ONCE(sk->sk_rcvbuf, READ_ONCE(net->smc.sysctl_rmem)); | 382 | WRITE_ONCE(sk->sk_rcvbuf, 2 * READ_ONCE(net->smc.sysctl_rmem)); |
| 383 | smc = smc_sk(sk); | 383 | smc = smc_sk(sk); |
| 384 | INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work); | 384 | INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work); |
| 385 | INIT_WORK(&smc->connect_work, smc_connect_work); | 385 | INIT_WORK(&smc->connect_work, smc_connect_work); |
| @@ -436,24 +436,9 @@ out: · 50 unmodified lines | |||
| 436 | return rc; | 436 | return rc; |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk, | 439 | /* copy only relevant settings and flags of SOL_SOCKET level from smc to |
| 440 | unsigned long mask) | 440 | * clc socket (since smc is not called for these options from net/core) |
| 441 | { | 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 | } | ||
| 457 | 442 | ||
| 458 | #define SK_FLAGS_SMC_TO_CLC ((1UL << SOCK_URGINLINE) | \ | 443 | #define SK_FLAGS_SMC_TO_CLC ((1UL << SOCK_URGINLINE) | \ |
| 459 | (1UL << SOCK_KEEPOPEN) | \ | 444 | (1UL << SOCK_KEEPOPEN) | \ |
| @@ -470,9 +455,55 @@ static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk, · 10 unmodified lines | |||
| 470 | (1UL << SOCK_NOFCS) | \ | 455 | (1UL << SOCK_NOFCS) | \ |
| 471 | (1UL << SOCK_FILTER_LOCKED) | \ | 456 | (1UL << SOCK_FILTER_LOCKED) | \ |
| 472 | (1UL << SOCK_TSTAMP_NEW)) | 457 | (1UL << SOCK_TSTAMP_NEW)) |
| 473 | /* copy only relevant settings and flags of SOL_SOCKET level from smc to | 458 | |
| 474 | * clc socket (since smc is not called for these options from net/core) | 459 | /* if set, use value set by setsockopt() - else use IPv4 or SMC sysctl value */ |
| 475 | */ | 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 | static void smc_copy_sock_settings_to_clc(struct smc_sock *smc) | 507 | static void smc_copy_sock_settings_to_clc(struct smc_sock *smc) |
| 477 | { | 508 | { |
| 478 | smc_copy_sock_settings(smc->clcsock->sk, &smc->sk, SK_FLAGS_SMC_TO_CLC); | 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 | sock_hold(lsk); /* sock_put in smc_listen_work */ | 2510 | sock_hold(lsk); /* sock_put in smc_listen_work */ |
| 2480 | INIT_WORK(&new_smc->smc_listen_work, smc_listen_work); | 2511 | INIT_WORK(&new_smc->smc_listen_work, smc_listen_work); |
| 2481 | smc_copy_sock_settings_to_smc(new_smc); | 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 | sock_hold(&new_smc->sk); /* sock_put in passive closing */ | 2513 | sock_hold(&new_smc->sk); /* sock_put in passive closing */ |
| 2485 | if (!queue_work(smc_hs_wq, &new_smc->smc_listen_work)) | 2514 | if (!queue_work(smc_hs_wq, &new_smc->smc_listen_work)) |
| 2486 | sock_put(&new_smc->sk); | 2515 | sock_put(&new_smc->sk); |
| @@ -161,7 +161,7 @@ struct smc_connection { · 160 unmodified lines | |||
| 161 | 161 | ||
| 162 | struct smc_buf_desc *sndbuf_desc; /* send buffer descriptor */ | 162 | struct smc_buf_desc *sndbuf_desc; /* send buffer descriptor */ |
| 163 | struct smc_buf_desc *rmb_desc; /* RMBE descriptor */ | 163 | struct smc_buf_desc *rmb_desc; /* RMBE descriptor */ |
| 164 | int rmbe_size_short;/* compressed notation */ | 164 | int rmbe_size_comp; /* compressed notation */ |
| 165 | int rmbe_update_limit; | 165 | int rmbe_update_limit; |
| 166 | /* lower limit for consumer | 166 | /* lower limit for consumer |
| 167 | * cursor update | 167 | * cursor update |
| @@ -1007,7 +1007,7 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc, · 1006 unmodified lines | |||
| 1007 | clc->d0.gid = | 1007 | clc->d0.gid = |
| 1008 | conn->lgr->smcd->ops->get_local_gid(conn->lgr->smcd); | 1008 | conn->lgr->smcd->ops->get_local_gid(conn->lgr->smcd); |
| 1009 | clc->d0.token = conn->rmb_desc->token; | 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 | clc->d0.dmbe_idx = 0; | 1011 | clc->d0.dmbe_idx = 0; |
| 1012 | memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE); | 1012 | memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE); |
| 1013 | if (version == SMC_V1) { | 1013 | if (version == SMC_V1) { |
| @@ -1050,7 +1050,7 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc, · 36 unmodified lines | |||
| 1050 | clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu); | 1050 | clc->r0.qp_mtu = min(link->path_mtu, link->peer_mtu); |
| 1051 | break; | 1051 | break; |
| 1052 | } | 1052 | } |
| 1053 | clc->r0.rmbe_size = conn->rmbe_size_short; | 1053 | clc->r0.rmbe_size = conn->rmbe_size_comp; |
| 1054 | clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ? | 1054 | clc->r0.rmb_dma_addr = conn->rmb_desc->is_vm ? |
| 1055 | cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) : | 1055 | cpu_to_be64((uintptr_t)conn->rmb_desc->cpu_addr) : |
| 1056 | cpu_to_be64((u64)sg_dma_address | 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 | struct smc_connection *conn = &smc->conn; | 2309 | struct smc_connection *conn = &smc->conn; |
| 2310 | struct smc_link_group *lgr = conn->lgr; | 2310 | struct smc_link_group *lgr = conn->lgr; |
| 2311 | struct list_head *buf_list; | 2311 | struct list_head *buf_list; |
| 2312 | int bufsize, bufsize_short; | 2312 | int bufsize, bufsize_comp; |
| 2313 | struct rw_semaphore *lock; /* lock buffer list */ | 2313 | struct rw_semaphore *lock; /* lock buffer list */ |
| 2314 | bool is_dgraded = false; | 2314 | bool is_dgraded = false; |
| 2315 | int sk_buf_size; | ||
| 2316 | 2315 | ||
| 2317 | if (is_rmb) | 2316 | if (is_rmb) |
| 2318 | /* use socket recv buffer size (w/o overhead) as start value */ | 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 | else | 2319 | else |
| 2321 | /* use socket send buffer size (w/o overhead) as start value */ | 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); | 2323 | for (bufsize_comp = smc_compress_bufsize(bufsize, is_smcd, is_rmb); |
| 2325 | bufsize_short >= 0; bufsize_short--) { | 2324 | bufsize_comp >= 0; bufsize_comp--) { |
| 2326 | if (is_rmb) { | 2325 | if (is_rmb) { |
| 2327 | lock = &lgr->rmbs_lock; | 2326 | lock = &lgr->rmbs_lock; |
| 2328 | buf_list = &lgr->rmbs[bufsize_short]; | 2327 | buf_list = &lgr->rmbs[bufsize_comp]; |
| 2329 | } else { | 2328 | } else { |
| 2330 | lock = &lgr->sndbufs_lock; | 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 | /* check for reusable slot in the link group */ | 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 | if (buf_desc) { | 2336 | if (buf_desc) { |
| 2338 | buf_desc->is_dma_need_sync = 0; | 2337 | buf_desc->is_dma_need_sync = 0; |
| 2339 | SMC_STAT_RMB_SIZE(smc, is_smcd, is_rmb, bufsize); | 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 | if (is_rmb) { | 2377 | if (is_rmb) { |
| 2379 | conn->rmb_desc = buf_desc; | 2378 | conn->rmb_desc = buf_desc; |
| 2380 | conn->rmbe_size_short = bufsize_short; | 2379 | conn->rmbe_size_comp = bufsize_comp; |
| 2381 | smc->sk.sk_rcvbuf = bufsize; | 2380 | smc->sk.sk_rcvbuf = bufsize * 2; |
| 2382 | atomic_set(&conn->bytes_to_rcv, 0); | 2381 | atomic_set(&conn->bytes_to_rcv, 0); |
| 2383 | conn->rmbe_update_limit = | 2382 | conn->rmbe_update_limit = |
| 2384 | smc_rmb_wnd_update_limit(buf_desc->len); | 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 | smc_ism_set_conn(conn); /* map RMB/smcd_dev to conn */ | 2385 | smc_ism_set_conn(conn); /* map RMB/smcd_dev to conn */ |
| 2387 | } else { | 2386 | } else { |
| 2388 | conn->sndbuf_desc = buf_desc; | 2387 | conn->sndbuf_desc = buf_desc; |
| 2389 | smc->sk.sk_sndbuf = bufsize; | 2388 | smc->sk.sk_sndbuf = bufsize * 2; |
| 2390 | atomic_set(&conn->sndbuf_space, bufsize); | 2389 | atomic_set(&conn->sndbuf_space, bufsize); |
| 2391 | } | 2390 | } |
| 2392 | return 0; | 2391 | return 0; |
| @@ -21,6 +21,10 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | static int min_sndbuf = SMC_BUF_MIN_SIZE; | 22 | static int min_sndbuf = SMC_BUF_MIN_SIZE; |
| 23 | static int min_rcvbuf = SMC_BUF_MIN_SIZE; | 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 | static struct ctl_table smc_table[] = { | 29 | static struct ctl_table smc_table[] = { |
| 26 | { | 30 | { |
| @@ -53,6 +57,7 @@ static struct ctl_table smc_table[] = { · 26 unmodified lines | |||
| 53 | .mode = 0644, | 57 | .mode = 0644, |
| 54 | .proc_handler = proc_dointvec_minmax, | 58 | .proc_handler = proc_dointvec_minmax, |
| 55 | .extra1 = &min_sndbuf, | 59 | .extra1 = &min_sndbuf, |
| 60 | .extra2 = &max_sndbuf, | ||
| 56 | }, | 61 | }, |
| 57 | { | 62 | { |
| 58 | .procname = "rmem", | 63 | .procname = "rmem", |
| @@ -61,6 +66,7 @@ static struct ctl_table smc_table[] = { · 2 unmodified lines | |||
| 61 | .mode = 0644, | 66 | .mode = 0644, |
| 62 | .proc_handler = proc_dointvec_minmax, | 67 | .proc_handler = proc_dointvec_minmax, |
| 63 | .extra1 = &min_rcvbuf, | 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 | net->smc.sysctl_autocorking_size = SMC_AUTOCORKING_DEFAULT_SIZE; | 94 | net->smc.sysctl_autocorking_size = SMC_AUTOCORKING_DEFAULT_SIZE; |
| 89 | net->smc.sysctl_smcr_buf_type = SMCR_PHYS_CONT_BUFS; | 95 | net->smc.sysctl_smcr_buf_type = SMCR_PHYS_CONT_BUFS; |
| 90 | net->smc.sysctl_smcr_testlink_time = SMC_LLC_TESTLINK_DEFAULT_TIME; | 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])); | 97 | WRITE_ONCE(net->smc.sysctl_wmem, net_smc_wmem_init); |
| 92 | WRITE_ONCE(net->smc.sysctl_rmem, READ_ONCE(net->ipv4.sysctl_tcp_rmem[1])); | 98 | WRITE_ONCE(net->smc.sysctl_rmem, net_smc_rmem_init); |
| 93 | 99 | ||
| 94 | return 0; | 100 | return 0; |
| 95 | 101 | ||
| @@ -52,6 +52,8 @@ static LIST_HEAD(tls_device_list); · 51 unmodified lines | |||
| 52 | static LIST_HEAD(tls_device_down_list); | 52 | static LIST_HEAD(tls_device_down_list); |
| 53 | static DEFINE_SPINLOCK(tls_device_lock); | 53 | static DEFINE_SPINLOCK(tls_device_lock); |
| 54 | 54 | ||
| 55 | static struct page *dummy_page; | ||
| 56 | |||
| 55 | static void tls_device_free_ctx(struct tls_context *ctx) | 57 | static void tls_device_free_ctx(struct tls_context *ctx) |
| 56 | { | 58 | { |
| 57 | if (ctx->tx_conf == TLS_HW) { | 59 | if (ctx->tx_conf == TLS_HW) { |
| @@ -312,36 +314,33 @@ static int tls_push_record(struct sock *sk, · 254 unmodified lines | |||
| 312 | return tls_push_sg(sk, ctx, offload_ctx->sg_tx_data, 0, flags); | 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, | 317 | static void tls_device_record_close(struct sock *sk, |
| 316 | struct tls_context *ctx, | 318 | struct tls_context *ctx, |
| 317 | struct tls_record_info *record, | 319 | struct tls_record_info *record, |
| 318 | struct page_frag *pfrag, | 320 | struct page_frag *pfrag, |
| 319 | unsigned char record_type) | 321 | unsigned char record_type) |
| 320 | { | 322 | { |
| 321 | struct tls_prot_info *prot = &ctx->prot_info; | 323 | struct tls_prot_info *prot = &ctx->prot_info; |
| 322 | int ret; | 324 | struct page_frag dummy_tag_frag; |
| 323 | 325 | ||
| 324 | /* append tag | 326 | /* append tag |
| 325 | * device will fill in the tag, we just need to append a placeholder | 327 | * device will fill in the tag, we just need to append a placeholder |
| 326 | * use socket memory to improve coalescing (re-using a single buffer | 328 | * use socket memory to improve coalescing (re-using a single buffer |
| 327 | * increases frag count) | 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, | 332 | if (unlikely(pfrag->size - pfrag->offset < prot->tag_size) && |
| 331 | sk->sk_allocation))) { | 333 | !skb_page_frag_refill(prot->tag_size, pfrag, sk->sk_allocation)) { |
| 332 | ret = 0; | 334 | dummy_tag_frag.page = dummy_page; |
| 333 | tls_append_frag(record, pfrag, prot->tag_size); | 335 | dummy_tag_frag.offset = 0; |
| 334 | } else { | 336 | pfrag = &dummy_tag_frag; |
| 335 | ret = prot->tag_size; | ||
| 336 | if (record->len <= prot->overhead_size) | ||
| 337 | return -ENOMEM; | ||
| 338 | } | 337 | } |
| 338 | tls_append_frag(record, pfrag, prot->tag_size); | ||
| 339 | 339 | ||
| 340 | /* fill prepend */ | 340 | /* fill prepend */ |
| 341 | tls_fill_prepend(ctx, skb_frag_address(&record->frags[0]), | 341 | tls_fill_prepend(ctx, skb_frag_address(&record->frags[0]), |
| 342 | record->len - prot->overhead_size, | 342 | record->len - prot->overhead_size, |
| 343 | record_type); | 343 | record_type); |
| 344 | return ret; | ||
| 345 | } | 344 | } |
| 346 | 345 | ||
| 347 | static int tls_create_new_record(struct tls_offload_context_tx *offload_ctx, | 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 | if (done || record->len >= max_open_record_len || | 541 | if (done || record->len >= max_open_record_len || |
| 543 | (record->num_frags >= MAX_SKB_FRAGS - 1)) { | 542 | (record->num_frags >= MAX_SKB_FRAGS - 1)) { |
| 544 | rc = tls_device_record_close(sk, tls_ctx, record, | 543 | tls_device_record_close(sk, tls_ctx, record, |
| 545 | pfrag, record_type); | 544 | 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 | } | ||
| 556 | 545 | ||
| 557 | rc = tls_push_record(sk, | 546 | rc = tls_push_record(sk, |
| 558 | tls_ctx, | 547 | tls_ctx, |
| @@ -1450,14 +1439,26 @@ int __init tls_device_init(void) · 891 unmodified lines | |||
| 1450 | { | 1439 | { |
| 1451 | int err; | 1440 | int err; |
| 1452 | 1441 | ||
| 1453 | destruct_wq = alloc_workqueue("ktls_device_destruct", 0, 0); | 1442 | dummy_page = alloc_page(GFP_KERNEL); |
| 1454 | if (!destruct_wq) | 1443 | if (!dummy_page) |
| 1455 | return -ENOMEM; | 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 | err = register_netdevice_notifier(&tls_dev_notifier); | 1452 | err = register_netdevice_notifier(&tls_dev_notifier); |
| 1458 | if (err) | 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 | return err; | 1462 | return err; |
| 1462 | } | 1463 | } |
| 1463 | 1464 | ||
| @@ -1466,4 +1467,5 @@ void __exit tls_device_cleanup(void) · 2 unmodified lines | |||
| 1466 | unregister_netdevice_notifier(&tls_dev_notifier); | 1467 | unregister_netdevice_notifier(&tls_dev_notifier); |
| 1467 | destroy_workqueue(destruct_wq); | 1468 | destroy_workqueue(destruct_wq); |
| 1468 | clean_acked_data_flush(); | 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 | ctx->splicing_pages = true; | 140 | ctx->splicing_pages = true; |
| 141 | while (1) { | 141 | while (1) { |
| 142 | if (sg_is_last(sg)) | ||
| 143 | msg.msg_flags = flags; | ||
| 144 | |||
| 145 | /* is sending application-limited? */ | 142 | /* is sending application-limited? */ |
| 146 | tcp_rate_check_app_limited(sk); | 143 | tcp_rate_check_app_limited(sk); |
| 147 | p = sg_page(sg); | 144 | p = sg_page(sg); |
| @@ -790,7 +790,7 @@ static int unix_set_peek_off(struct sock *sk, int val) · 789 unmodified lines | |||
| 790 | if (mutex_lock_interruptible(&u->iolock)) | 790 | if (mutex_lock_interruptible(&u->iolock)) |
| 791 | return -EINTR; | 791 | return -EINTR; |
| 792 | 792 | ||
| 793 | sk->sk_peek_off = val; | 793 | WRITE_ONCE(sk->sk_peek_off, val); |
| 794 | mutex_unlock(&u->iolock); | 794 | mutex_unlock(&u->iolock); |
| 795 | 795 | ||
| 796 | return 0; | 796 | return 0; |
| @@ -5430,8 +5430,11 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) · 5429 unmodified lines | |||
| 5430 | if (!wiphy->mbssid_max_interfaces) | 5430 | if (!wiphy->mbssid_max_interfaces) |
| 5431 | return ERR_PTR(-EINVAL); | 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 | num_elems++; | 5436 | num_elems++; |
| 5437 | } | ||
| 5435 | 5438 | ||
| 5436 | elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL); | 5439 | elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL); |
| 5437 | if (!elems) | 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 | ret = cfg80211_calc_short_ssid(ies, &ssid_elem, &s_ssid_tmp); | 658 | ret = cfg80211_calc_short_ssid(ies, &ssid_elem, &s_ssid_tmp); |
| 659 | if (ret) | 659 | if (ret) |
| 660 | return ret; | 660 | return 0; |
| 661 | 661 | ||
| 662 | for_each_element_id(elem, WLAN_EID_REDUCED_NEIGHBOR_REPORT, | 662 | for_each_element_id(elem, WLAN_EID_REDUCED_NEIGHBOR_REPORT, |
| 663 | ies->data, ies->len) { | 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 | skb->dev = dev; | 506 | skb->dev = dev; |
| 507 | skb->priority = xs->sk.sk_priority; | 507 | skb->priority = xs->sk.sk_priority; |
| 508 | skb->mark = xs->sk.sk_mark; | 508 | skb->mark = READ_ONCE(xs->sk.sk_mark); |
| 509 | skb_shinfo(skb)->destructor_arg = (void *)(long)desc->addr; | 509 | skb_shinfo(skb)->destructor_arg = (void *)(long)desc->addr; |
| 510 | skb->destructor = xsk_destruct_skb; | 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 | err = xp_alloc_tx_descs(xs->pool, xs); | 994 | err = xp_alloc_tx_descs(xs->pool, xs); |
| 995 | if (err) { | 995 | if (err) { |
| 996 | xp_put_pool(xs->pool); | 996 | xp_put_pool(xs->pool); |
| 997 | xs->pool = NULL; | ||
| 997 | sockfd_put(sock); | 998 | sockfd_put(sock); |
| 998 | goto out_unlock; | 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 | match = xfrm_selector_match(&pol->selector, fl, family); | 2251 | match = xfrm_selector_match(&pol->selector, fl, family); |
| 2252 | if (match) { | 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 | pol->if_id != if_id) { | 2254 | pol->if_id != if_id) { |
| 2255 | pol = NULL; | 2255 | pol = NULL; |
| 2256 | goto out; | 2256 | goto out; |
| @@ -257,7 +257,7 @@ bindgen_skip_c_flags := -mno-fp-ret-in-387 -mpreferred-stack-boundary=% \ · 256 unmodified lines | |||
| 257 | -fno-partial-inlining -fplugin-arg-arm_ssp_per_task_plugin-% \ | 257 | -fno-partial-inlining -fplugin-arg-arm_ssp_per_task_plugin-% \ |
| 258 | -fno-reorder-blocks -fno-allow-store-data-races -fasan-shadow-offset=% \ | 258 | -fno-reorder-blocks -fno-allow-store-data-races -fasan-shadow-offset=% \ |
| 259 | -fzero-call-used-regs=% -fno-stack-clash-protection \ | 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 | --param=% --param asan-% | 261 | --param=% --param asan-% |
| 262 | 262 | ||
| 263 | # Derived from `scripts/Makefile.clang`. | 263 | # Derived from `scripts/Makefile.clang`. |
| @@ -13,5 +13,6 @@ · 12 unmodified lines | |||
| 13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
| 14 | 14 | ||
| 15 | /* `bindgen` gets confused at certain things. */ | 15 | /* `bindgen` gets confused at certain things. */ |
| 16 | const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; | ||
| 16 | const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; | 17 | const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; |
| 17 | const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO; | 18 | const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO; |
| @@ -9,6 +9,36 @@ use crate::bindings; · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | struct KernelAllocator; | 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 | unsafe impl GlobalAlloc for KernelAllocator { | 42 | unsafe impl GlobalAlloc for KernelAllocator { |
| 13 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | 43 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { |
| 14 | // `krealloc()` is used instead of `kmalloc()` because the latter is | 44 | // `krealloc()` is used instead of `kmalloc()` because the latter is |
| @@ -30,10 +60,20 @@ static ALLOCATOR: KernelAllocator = KernelAllocator; · 15 unmodified lines | |||
| 30 | // to extract the object file that has them from the archive. For the moment, | 60 | // to extract the object file that has them from the archive. For the moment, |
| 31 | // let's generate them ourselves instead. | 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 | // Note that `#[no_mangle]` implies exported too, nowadays. | 68 | // Note that `#[no_mangle]` implies exported too, nowadays. |
| 34 | #[no_mangle] | 69 | #[no_mangle] |
| 35 | fn __rust_alloc(size: usize, _align: usize) -> *mut u8 { | 70 | fn __rust_alloc(size: usize, align: usize) -> *mut u8 { |
| 36 | unsafe { bindings::krealloc(core::ptr::null(), size, bindings::GFP_KERNEL) as *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 | #[no_mangle] | 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 | #[no_mangle] | 84 | #[no_mangle] |
| 45 | fn __rust_realloc(ptr: *mut u8, _old_size: usize, _align: usize, new_size: usize) -> *mut u8 { | 85 | fn __rust_realloc(ptr: *mut u8, _old_size: usize, align: usize, new_size: usize) -> *mut u8 { |
| 46 | unsafe { | 86 | // SAFETY: See assumption above. |
| 47 | bindings::krealloc( | 87 | let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, align) }; |
| 48 | ptr as *const core::ffi::c_void, | 88 | |
| 49 | new_size, | 89 | // SAFETY: Per assumption above, `ptr` is allocated by `__rust_*` before, and the size of |
| 50 | bindings::GFP_KERNEL, | 90 | // `new_layout` is greater than 0. |
| 51 | ) as *mut u8 | 91 | unsafe { krealloc_aligned(ptr, new_layout, bindings::GFP_KERNEL) } |
| 52 | } | ||
| 53 | } | 92 | } |
| 54 | 93 | ||
| 55 | #[no_mangle] | 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 | unsafe { | 101 | unsafe { |
| 58 | bindings::krealloc( | 102 | krealloc_aligned( |
| 59 | core::ptr::null(), | 103 | ptr::null_mut(), |
| 60 | size, | 104 | layout, |
| 61 | bindings::GFP_KERNEL | bindings::__GFP_ZERO, | 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 | let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap(); | 243 | let inner = NonNull::new(ptr as *mut ArcInner<T>).unwrap(); |
| 244 | 244 | ||
| 245 | // SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive | 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 | 246 | // for the lifetime of the returned value. |
| 247 | // `ForeignOwnable::borrow_mut` ensure that no new mutable references are created. | ||
| 248 | unsafe { ArcBorrow::new(inner) } | 247 | unsafe { ArcBorrow::new(inner) } |
| 249 | } | 248 | } |
| 250 | 249 | ||
| @@ -35,34 +35,16 @@ pub trait ForeignOwnable: Sized { · 34 unmodified lines | |||
| 35 | /// | 35 | /// |
| 36 | /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for | 36 | /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for |
| 37 | /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. | 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 | unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Self::Borrowed<'a>; | 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 | /// Converts a foreign-owned object back to a Rust-owned one. | 40 | /// Converts a foreign-owned object back to a Rust-owned one. |
| 59 | /// | 41 | /// |
| 60 | /// # Safety | 42 | /// # Safety |
| 61 | /// | 43 | /// |
| 62 | /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for | 44 | /// `ptr` must have been returned by a previous call to [`ForeignOwnable::into_foreign`] for |
| 63 | /// which a previous matching [`ForeignOwnable::from_foreign`] hasn't been called yet. | 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 | 46 | /// Additionally, all instances (if any) of values returned by [`ForeignOwnable::borrow`] for |
| 65 | /// [`ForeignOwnable::borrow_mut`] for this object must have been dropped. | 47 | /// this object must have been dropped. |
| 66 | unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self; | 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 | ssize_t readlen; | 129 | ssize_t readlen; |
| 130 | struct sym_entry *sym; | 130 | struct sym_entry *sym; |
| 131 | 131 | ||
| 132 | errno = 0; | ||
| 132 | readlen = getline(buf, buf_len, in); | 133 | readlen = getline(buf, buf_len, in); |
| 133 | if (readlen < 0) { | 134 | if (readlen < 0) { |
| 134 | if (errno) { | 135 | if (errno) { |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <linux/sysctl.h> | 9 | #include <linux/sysctl.h> |
| 10 | #include "internal.h" | 10 | #include "internal.h" |
| 11 | 11 | ||
| 12 | struct ctl_table key_sysctls[] = { | 12 | static struct ctl_table key_sysctls[] = { |
| 13 | { | 13 | { |
| 14 | .procname = "maxkeys", | 14 | .procname = "maxkeys", |
| 15 | .data = &key_quota_maxkeys, | 15 | .data = &key_quota_maxkeys, |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | |||
| 14 | * Defines x86 CPU feature bits | 14 | * Defines x86 CPU feature bits |
| 15 | */ | 15 | */ |
| 16 | #define NCAPINTS 21 /* N 32-bit words worth of info */ | 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 | * Note: If the comment begins with a quoted string, that string is used | 20 | * Note: If the comment begins with a quoted string, that string is used |
| @@ -545,6 +545,7 @@ · 544 unmodified lines | |||
| 545 | #define MSR_AMD64_DE_CFG 0xc0011029 | 545 | #define MSR_AMD64_DE_CFG 0xc0011029 |
| 546 | #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT 1 | 546 | #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT 1 |
| 547 | #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE BIT_ULL(MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT) | 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 | #define MSR_AMD64_BU_CFG2 0xc001102a | 550 | #define MSR_AMD64_BU_CFG2 0xc001102a |
| 550 | #define MSR_AMD64_IBSFETCHCTL 0xc0011030 | 551 | #define MSR_AMD64_IBSFETCHCTL 0xc0011030 |
| @@ -40,7 +40,8 @@ $(OUTPUT)counter_example: $(COUNTER_EXAMPLE) · 39 unmodified lines | |||
| 40 | clean: | 40 | clean: |
| 41 | rm -f $(ALL_PROGRAMS) | 41 | rm -f $(ALL_PROGRAMS) |
| 42 | rm -rf $(OUTPUT)include/linux/counter.h | 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 | find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete | 45 | find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete |
| 45 | 46 | ||
| 46 | install: $(ALL_PROGRAMS) | 47 | install: $(ALL_PROGRAMS) |
| @@ -164,7 +164,7 @@ def recursive_file_lookup(path, file_map): · 163 unmodified lines | |||
| 164 | def get_all_devices_test_status(file_map): | 164 | def get_all_devices_test_status(file_map): |
| 165 | 165 | ||
| 166 | for device in file_map: | 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 | print("Testing = ON for: {}" | 168 | print("Testing = ON for: {}" |
| 169 | .format(device.split("/")[5])) | 169 | .format(device.split("/")[5])) |
| 170 | else: | 170 | else: |
| @@ -203,7 +203,7 @@ def write_test_files(path, value): · 32 unmodified lines | |||
| 203 | def set_test_state(state_path, state_value, quiet): | 203 | def set_test_state(state_path, state_value, quiet): |
| 204 | 204 | ||
| 205 | write_test_files(state_path, state_value) | 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 | if (not quiet): | 207 | if (not quiet): |
| 208 | print("Testing = ON for device: {}" | 208 | print("Testing = ON for device: {}" |
| 209 | .format(state_path.split("/")[5])) | 209 | .format(state_path.split("/")[5])) |
| @@ -824,5 +824,8 @@ bool arch_is_retpoline(struct symbol *sym) · 823 unmodified lines | |||
| 824 | 824 | ||
| 825 | bool arch_is_rethunk(struct symbol *sym) | 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 | perf_pmu__pathname_scnprintf(path, sizeof(path), | 54 | perf_pmu__pathname_scnprintf(path, sizeof(path), |
| 55 | pmu->name, "caps/slots"); | 55 | pmu->name, "caps/slots"); |
| 56 | /* | 56 | /* |
| 57 | * The value of slots is not greater than 32 bits, but sysfs__read_int | 57 | * The value of slots is not greater than 32 bits, but |
| 58 | * can't read value with 0x prefix, so use sysfs__read_ull instead. | 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 | return slots ? (double)slots : NAN; | 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 | if (!chain || chain->nr < 3) | 250 | if (!chain || chain->nr < 3) |
| 251 | return skip_slot; | 251 | return skip_slot; |
| 252 | 252 | ||
| 253 | addr_location__init(&al); | ||
| 253 | ip = chain->ips[1]; | 254 | ip = chain->ips[1]; |
| 254 | 255 | ||
| 255 | thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al); | 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 | if (!dso) { | 261 | if (!dso) { |
| 261 | pr_debug("%" PRIx64 " dso is NULL\n", ip); | 262 | pr_debug("%" PRIx64 " dso is NULL\n", ip); |
| 263 | addr_location__exit(&al); | ||
| 262 | return skip_slot; | 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 | skip_slot = 3; | 282 | skip_slot = 3; |
| 281 | } | 283 | } |
| 284 | |||
| 285 | addr_location__exit(&al); | ||
| 282 | return skip_slot; | 286 | return skip_slot; |
| 283 | } | 287 | } |
| @@ -1631,6 +1631,16 @@ static bool test__pmu_cpu_valid(void) · 1630 unmodified lines | |||
| 1631 | return !!perf_pmus__find("cpu"); | 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 | static bool test__intel_pt_valid(void) | 1644 | static bool test__intel_pt_valid(void) |
| 1635 | { | 1645 | { |
| 1636 | return !!perf_pmus__find("intel_pt"); | 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 | .name = "cpu/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp", | 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 | .check = test__checkevent_complex_name, | 2193 | .check = test__checkevent_complex_name, |
| 2184 | /* 3 */ | 2194 | /* 3 */ |
| 2185 | }, | 2195 | }, |
| @@ -4,6 +4,12 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | set -e | 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 | temp_dir=$(mktemp -d /tmp/perf-uprobe-different-cu-sh.XXXXXXXXXX) | 13 | temp_dir=$(mktemp -d /tmp/perf-uprobe-different-cu-sh.XXXXXXXXXX) |
| 8 | 14 | ||
| 9 | cleanup() | 15 | cleanup() |
| @@ -11,7 +17,7 @@ cleanup() · 1 unmodified line | |||
| 11 | trap - EXIT TERM INT | 17 | trap - EXIT TERM INT |
| 12 | if [[ "${temp_dir}" =~ ^/tmp/perf-uprobe-different-cu-sh.*$ ]]; then | 18 | if [[ "${temp_dir}" =~ ^/tmp/perf-uprobe-different-cu-sh.*$ ]]; then |
| 13 | echo "--- Cleaning up ---" | 19 | echo "--- Cleaning up ---" |
| 14 | perf probe -x ${temp_dir}/testfile -d foo | 20 | perf probe -x ${temp_dir}/testfile -d foo || true |
| 15 | rm -f "${temp_dir}/"* | 21 | rm -f "${temp_dir}/"* |
| 16 | rmdir "${temp_dir}" | 22 | rmdir "${temp_dir}" |
| 17 | fi | 23 | fi |
| @@ -45,7 +45,6 @@ · 44 unmodified lines | |||
| 45 | 45 | ||
| 46 | static void __machine__remove_thread(struct machine *machine, struct thread_rb_node *nd, | 46 | static void __machine__remove_thread(struct machine *machine, struct thread_rb_node *nd, |
| 47 | struct thread *th, bool lock); | 47 | struct thread *th, bool lock); |
| 48 | static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip); | ||
| 49 | 48 | ||
| 50 | static struct dso *machine__kernel_dso(struct machine *machine) | 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 | ms.maps = maps__get(al.maps); | 2384 | ms.maps = maps__get(al.maps); |
| 2386 | ms.map = map__get(al.map); | 2385 | ms.map = map__get(al.map); |
| 2387 | ms.sym = al.sym; | 2386 | ms.sym = al.sym; |
| 2388 | |||
| 2389 | if (!branch && append_inlines(cursor, &ms, ip) == 0) | ||
| 2390 | goto out; | ||
| 2391 | |||
| 2392 | srcline = callchain_srcline(&ms, al.addr); | 2387 | srcline = callchain_srcline(&ms, al.addr); |
| 2393 | err = callchain_cursor_append(cursor, ip, &ms, | 2388 | err = callchain_cursor_append(cursor, ip, &ms, |
| 2394 | branch, flags, nr_loop_iter, | 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 | return lhs->core.idx - rhs->core.idx; | 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 | const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node); | 2105 | const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node); |
| 2106 | const struct evsel *lhs = container_of(lhs_core, struct evsel, core); | 2106 | const struct evsel *lhs = container_of(lhs_core, struct evsel, core); |
| 2107 | const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node); | 2107 | const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node); |
| 2108 | const struct evsel *rhs = container_of(rhs_core, struct evsel, core); | 2108 | const struct evsel *rhs = container_of(rhs_core, struct evsel, core); |
| 2109 | int *leader_idx = state; | 2109 | int *force_grouped_idx = _fg_idx; |
| 2110 | int lhs_leader_idx = *leader_idx, rhs_leader_idx = *leader_idx, ret; | 2110 | int lhs_sort_idx, rhs_sort_idx, ret; |
| 2111 | const char *lhs_pmu_name, *rhs_pmu_name; | 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 | * First sort by grouping/leader. Read the leader idx only if the evsel | 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 | if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) { | 2122 | if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) { |
| 2123 | lhs_has_group = true; | 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 | if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) { | 2131 | if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) { |
| 2127 | rhs_has_group = true; | 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) | 2141 | if (lhs_sort_idx != rhs_sort_idx) |
| 2132 | return lhs_leader_idx - rhs_leader_idx; | 2142 | return lhs_sort_idx - rhs_sort_idx; |
| 2133 | 2143 | ||
| 2134 | /* Group by PMU if there is a group. Groups can't span PMUs. */ | 2144 | /* Group by PMU if there is a group. Groups can't span PMUs. */ |
| 2135 | if (lhs_has_group && rhs_has_group) { | 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 | static int parse_events__sort_events_and_fix_groups(struct list_head *list) | 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 | struct evsel *pos, *cur_leader = NULL; | 2160 | struct evsel *pos, *cur_leader = NULL; |
| 2151 | struct perf_evsel *cur_leaders_grp = NULL; | 2161 | struct perf_evsel *cur_leaders_grp = NULL; |
| 2152 | bool idx_changed = false; | 2162 | bool idx_changed = false, cur_leader_force_grouped = false; |
| 2153 | int orig_num_leaders = 0, num_leaders = 0; | 2163 | int orig_num_leaders = 0, num_leaders = 0; |
| 2154 | int ret; | 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 | pos->core.idx = idx++; | 2185 | pos->core.idx = idx++; |
| 2176 | 2186 | ||
| 2177 | if (unsorted_idx == -1 && pos == pos_leader && pos->core.nr_members < 2) | 2187 | /* Remember an index to sort all forced grouped events together to. */ |
| 2178 | unsorted_idx = pos->core.idx; | 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 | /* Sort events. */ | 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 | * Recompute groups, splitting for PMUs and adding groups for events | 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 | list_for_each_entry(pos, list, core.node) { | 2201 | list_for_each_entry(pos, list, core.node) { |
| 2190 | const struct evsel *pos_leader = evsel__leader(pos); | 2202 | const struct evsel *pos_leader = evsel__leader(pos); |
| 2191 | const char *pos_pmu_name = pos->group_pmu_name; | 2203 | const char *pos_pmu_name = pos->group_pmu_name; |
| 2192 | const char *cur_leader_pmu_name, *pos_leader_pmu_name; | 2204 | const char *cur_leader_pmu_name; |
| 2193 | bool force_grouped = arch_evsel__must_be_in_group(pos); | 2205 | bool pos_force_grouped = force_grouped_idx != -1 && |
| 2206 | arch_evsel__must_be_in_group(pos); | ||
| 2194 | 2207 | ||
| 2195 | /* Reset index and nr_members. */ | 2208 | /* Reset index and nr_members. */ |
| 2196 | if (pos->core.idx != idx) | 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 | cur_leader = pos; | 2219 | cur_leader = pos; |
| 2207 | 2220 | ||
| 2208 | cur_leader_pmu_name = cur_leader->group_pmu_name; | 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 | strcmp(cur_leader_pmu_name, pos_pmu_name)) { | 2224 | strcmp(cur_leader_pmu_name, pos_pmu_name)) { |
| 2211 | /* Event is for a different group/PMU than last. */ | 2225 | /* Event is for a different group/PMU than last. */ |
| 2212 | cur_leader = pos; | 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 | * group. | 2230 | * group. |
| 2217 | */ | 2231 | */ |
| 2218 | cur_leaders_grp = pos->core.leader; | 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 | 2234 | * Avoid forcing events into groups with events that |
| 2224 | * span PMUs, so update leader from the group/PMU | 2235 | * don't need to be in the group. |
| 2225 | * tracker. | ||
| 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 | evsel__set_leader(pos, cur_leader); | 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 | bool is_pmu_core(const char *name) | 1454 | bool is_pmu_core(const char *name) |
| 1444 | { | 1455 | { |
| 1445 | return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name); | 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 | void perf_pmu__set_format(unsigned long *bits, long from, long to); | 234 | void perf_pmu__set_format(unsigned long *bits, long from, long to); |
| 235 | int perf_pmu__format_parse(int dirfd, struct list_head *head); | 235 | int perf_pmu__format_parse(int dirfd, struct list_head *head); |
| 236 | void perf_pmu__del_formats(struct list_head *formats); | 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 | bool is_pmu_core(const char *name); | 239 | bool is_pmu_core(const char *name); |
| 239 | bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu); | 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 | closedir(dir); | 154 | closedir(dir); |
| 155 | if (core_only) { | 155 | if (list_empty(&core_pmus)) { |
| 156 | if (!list_empty(&core_pmus)) | 156 | if (!perf_pmu__create_placeholder_core_pmu(&core_pmus)) |
| 157 | read_sysfs_core_pmus = true; | 157 | pr_err("Failure to set up any core PMUs\n"); |
| 158 | else { | 158 | } |
| 159 | if (perf_pmu__create_placeholder_core_pmu(&core_pmus)) | 159 | if (!list_empty(&core_pmus)) { |
| 160 | read_sysfs_core_pmus = true; | ||
| 161 | } | ||
| 162 | } else { | ||
| 163 | read_sysfs_core_pmus = true; | 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 | if (config->aggr_mode == AGGR_THREAD && config->system_wide) | 932 | if (config->aggr_mode == AGGR_THREAD && config->system_wide) |
| 933 | return true; | 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 | * Skip value 0 when it's an uncore event and the given aggr id | 940 | * Skip value 0 when it's an uncore event and the given aggr id |
| 936 | * does not belong to the PMU cpumask. | 941 | * does not belong to the PMU cpumask. |
| @@ -177,7 +177,7 @@ void regression1_test(void) · 176 unmodified lines | |||
| 177 | nr_threads = 2; | 177 | nr_threads = 2; |
| 178 | pthread_barrier_init(&worker_barrier, NULL, nr_threads); | 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 | for (i = 0; i < nr_threads; i++) { | 182 | for (i = 0; i < nr_threads; i++) { |
| 183 | arg = i; | 183 | arg = i; |
| @@ -869,6 +869,77 @@ static void test_msg_redir_to_listening(struct test_sockmap_listen *skel, · 868 unmodified lines | |||
| 869 | xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT); | 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 | static void test_reuseport_select_listening(int family, int sotype, | 943 | static void test_reuseport_select_listening(int family, int sotype, |
| 873 | int sock_map, int verd_map, | 944 | int sock_map, int verd_map, |
| 874 | int reuseport_prog) | 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 | } tests[] = { | 1314 | } tests[] = { |
| 1244 | TEST(test_skb_redir_to_connected), | 1315 | TEST(test_skb_redir_to_connected), |
| 1245 | TEST(test_skb_redir_to_listening), | 1316 | TEST(test_skb_redir_to_listening), |
| 1317 | TEST(test_skb_redir_partial), | ||
| 1246 | TEST(test_msg_redir_to_connected), | 1318 | TEST(test_msg_redir_to_connected), |
| 1247 | TEST(test_msg_redir_to_listening), | 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 | if (n < 1) | 1504 | if (n < 1) |
| 1433 | goto out; | 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 | if (n < 0) | 1508 | if (n < 0) |
| 1437 | FAIL("%s: recv() err, errno=%d", log_prefix, errno); | 1509 | FAIL("%s: recv() err, errno=%d", log_prefix, errno); |
| 1438 | if (n == 0) | 1510 | if (n == 0) |
| @@ -28,12 +28,26 @@ struct { · 27 unmodified lines | |||
| 28 | __type(value, unsigned int); | 28 | __type(value, unsigned int); |
| 29 | } verdict_map SEC(".maps"); | 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 | bool test_sockmap = false; /* toggled by user-space */ | 38 | bool test_sockmap = false; /* toggled by user-space */ |
| 32 | bool test_ingress = false; /* toggled by user-space */ | 39 | bool test_ingress = false; /* toggled by user-space */ |
| 33 | 40 | ||
| 34 | SEC("sk_skb/stream_parser") | 41 | SEC("sk_skb/stream_parser") |
| 35 | int prog_stream_parser(struct __sk_buff *skb) | 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 | return skb->len; | 51 | return skb->len; |
| 38 | } | 52 | } |
| 39 | 53 | ||
| @@ -70,6 +70,10 @@ static int test_kmem_basic(const char *root) · 69 unmodified lines | |||
| 70 | goto cleanup; | 70 | goto cleanup; |
| 71 | 71 | ||
| 72 | cg_write(cg, "memory.high", "1M"); | 72 | cg_write(cg, "memory.high", "1M"); |
| 73 | |||
| 74 | /* wait for RCU freeing */ | ||
| 75 | sleep(1); | ||
| 76 | |||
| 73 | slab1 = cg_read_key_long(cg, "memory.stat", "slab "); | 77 | slab1 = cg_read_key_long(cg, "memory.stat", "slab "); |
| 74 | if (slab1 <= 0) | 78 | if (slab1 <= 0) |
| 75 | goto cleanup; | 79 | goto cleanup; |
| @@ -831,6 +831,7 @@ int main(int argc, char *argv[]) · 830 unmodified lines | |||
| 831 | printf("Size must be greater than 0\n"); | 831 | printf("Size must be greater than 0\n"); |
| 832 | return KSFT_FAIL; | 832 | return KSFT_FAIL; |
| 833 | } | 833 | } |
| 834 | break; | ||
| 834 | case 't': | 835 | case 't': |
| 835 | { | 836 | { |
| 836 | int tmp = atoi(optarg); | 837 | int tmp = atoi(optarg); |
| @@ -1981,6 +1981,11 @@ basic() · 1980 unmodified lines | |||
| 1981 | 1981 | ||
| 1982 | run_cmd "$IP link set dev lo up" | 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 | # groups | 1990 | # groups |
| 1986 | # | 1991 | # |
| @@ -2201,6 +2206,11 @@ basic_res() · 214 unmodified lines | |||
| 2201 | run_cmd "$IP nexthop bucket list fdb" | 2206 | run_cmd "$IP nexthop bucket list fdb" |
| 2202 | log_test $? 255 "Dump all nexthop buckets with invalid 'fdb' keyword" | 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 | # resilient nexthop buckets get requests | 2215 | # resilient nexthop buckets get requests |
| 2206 | # | 2216 | # |
| @@ -617,7 +617,7 @@ __cfg_test_port_ip_sg() · 616 unmodified lines | |||
| 617 | grep -q "permanent" | 617 | grep -q "permanent" |
| 618 | check_err $? "Entry not added as \"permanent\" when should" | 618 | check_err $? "Entry not added as \"permanent\" when should" |
| 619 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ | 619 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ |
| 620 | grep -q "0.00" | 620 | grep -q " 0.00" |
| 621 | check_err $? "\"permanent\" entry has a pending group timer" | 621 | check_err $? "\"permanent\" entry has a pending group timer" |
| 622 | bridge mdb del dev br0 port $swp1 $grp_key vid 10 | 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 | grep -q "temp" | 626 | grep -q "temp" |
| 627 | check_err $? "Entry not added as \"temp\" when should" | 627 | check_err $? "Entry not added as \"temp\" when should" |
| 628 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ | 628 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ |
| 629 | grep -q "0.00" | 629 | grep -q " 0.00" |
| 630 | check_fail $? "\"temp\" entry has an unpending group timer" | 630 | check_fail $? "\"temp\" entry has an unpending group timer" |
| 631 | bridge mdb del dev br0 port $swp1 $grp_key vid 10 | 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 | grep -q "permanent" | 659 | grep -q "permanent" |
| 660 | check_err $? "Entry not marked as \"permanent\" after replace" | 660 | check_err $? "Entry not marked as \"permanent\" after replace" |
| 661 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ | 661 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ |
| 662 | grep -q "0.00" | 662 | grep -q " 0.00" |
| 663 | check_err $? "Entry has a pending group timer after replace" | 663 | check_err $? "Entry has a pending group timer after replace" |
| 664 | 664 | ||
| 665 | bridge mdb replace dev br0 port $swp1 $grp_key vid 10 temp | 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 | grep -q "temp" | 667 | grep -q "temp" |
| 668 | check_err $? "Entry not marked as \"temp\" after replace" | 668 | check_err $? "Entry not marked as \"temp\" after replace" |
| 669 | bridge -d -s mdb show dev br0 vid 10 | grep "$grp_key" | \ | 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.