* Re: [PATCH v3 3/5] KVM: arm64: Add support for FEAT_HDBSS
From: Marc Zyngier @ 2026-06-01 8:58 UTC (permalink / raw)
To: Inochi Amaoto
Cc: Tian Zheng, oupton, catalin.marinas, corbet, pbonzini, will,
yuzenghui, wangzhou1, liuyonglong, Jonathan.Cameron, yezhenyu2,
linuxarm, joey.gouly, kvmarm, kvm, linux-arm-kernel, linux-doc,
linux-kernel, skhan, suzuki.poulose, leo.bras
In-Reply-To: <ahzUUDAMoHtDFJD3@inochi.infowork>
On Mon, 01 Jun 2026 01:50:22 +0100,
Inochi Amaoto <inochiama@gmail.com> wrote:
>
> On Wed, Feb 25, 2026 at 12:04:19PM +0800, Tian Zheng wrote:
> > From: eillon <yezhenyu2@huawei.com>
> >
> > Armv9.5 introduces the Hardware Dirty Bit State Structure (HDBSS) feature,
> > indicated by ID_AA64MMFR1_EL1.HAFDBS == 0b0100. A CPU capability is added
> > to notify the user of the feature.
> >
> > Add KVM_CAP_ARM_HW_DIRTY_STATE_TRACK ioctl and basic framework for
> > ARM64 HDBSS support. Since the HDBSS buffer size is configurable and
> > cannot be determined at KVM initialization, an IOCTL interface is
> > required.
> >
> > Actually exposing the new capability to user space happens in a later
> > patch.
> >
> > Signed-off-by: eillon <yezhenyu2@huawei.com>
> > Signed-off-by: Tian Zheng <zhengtian10@huawei.com>
> > ---
> > arch/arm64/include/asm/cpufeature.h | 5 +++++
> > arch/arm64/kernel/cpufeature.c | 12 ++++++++++++
> > arch/arm64/tools/cpucaps | 1 +
> > include/uapi/linux/kvm.h | 1 +
> > tools/include/uapi/linux/kvm.h | 1 +
> > 5 files changed, 20 insertions(+)
> >
> > diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> > index 4de51f8d92cb..dcc2e2cad5ad 100644
> > --- a/arch/arm64/include/asm/cpufeature.h
> > +++ b/arch/arm64/include/asm/cpufeature.h
> > @@ -856,6 +856,11 @@ static inline bool system_supports_haft(void)
> > return cpus_have_final_cap(ARM64_HAFT);
> > }
> >
> > +static inline bool system_supports_hdbss(void)
> > +{
> > + return cpus_have_final_cap(ARM64_HAS_HDBSS);
> > +}
> > +
> > static __always_inline bool system_supports_mpam(void)
> > {
> > return alternative_has_cap_unlikely(ARM64_MPAM);
> > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > index c31f8e17732a..348b0afffc3e 100644
> > --- a/arch/arm64/kernel/cpufeature.c
> > +++ b/arch/arm64/kernel/cpufeature.c
> > @@ -2124,6 +2124,11 @@ static bool hvhe_possible(const struct arm64_cpu_capabilities *entry,
> > return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_HVHE);
> > }
> >
> > +static bool has_vhe_hdbss(const struct arm64_cpu_capabilities *entry, int cope)
> > +{
> > + return is_kernel_in_hyp_mode() && has_cpuid_feature(entry, cope);
> > +}
> > +
> > bool cpu_supports_bbml2_noabort(void)
> > {
> > /*
> > @@ -2759,6 +2764,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
> > ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HAFDBS, HAFT)
> > },
> > #endif
> > + {
> > + .desc = "Hardware Dirty state tracking structure (HDBSS)",
> > + .type = ARM64_CPUCAP_SYSTEM_FEATURE,
> > + .capability = ARM64_HAS_HDBSS,
> > + .matches = has_vhe_hdbss,
> > + ARM64_CPUID_FIELDS(ID_AA64MMFR1_EL1, HAFDBS, HDBSS)
> > + },
> > {
> > .desc = "CRC32 instructions",
> > .capability = ARM64_HAS_CRC32,
> > diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
> > index 7261553b644b..f6ece5b85532 100644
> > --- a/arch/arm64/tools/cpucaps
> > +++ b/arch/arm64/tools/cpucaps
> > @@ -68,6 +68,7 @@ HAS_VA52
> > HAS_VIRT_HOST_EXTN
> > HAS_WFXT
> > HAS_XNX
> > +HAS_HDBSS
> > HAFT
> > HW_DBM
> > KVM_HVHE
>
>
> > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> > index 65500f5db379..15ee42cdbd51 100644
> > --- a/include/uapi/linux/kvm.h
> > +++ b/include/uapi/linux/kvm.h
> > @@ -985,6 +985,7 @@ struct kvm_enable_cap {
> > #define KVM_CAP_ARM_SEA_TO_USER 245
> > #define KVM_CAP_S390_USER_OPEREXEC 246
> > #define KVM_CAP_S390_KEYOP 247
> > +#define KVM_CAP_ARM_HW_DIRTY_STATE_TRACK 248
> >
> > struct kvm_irq_routing_irqchip {
> > __u32 irqchip;
> > diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
> > index dddb781b0507..93e0a1e14dc7 100644
> > --- a/tools/include/uapi/linux/kvm.h
> > +++ b/tools/include/uapi/linux/kvm.h
> > @@ -974,6 +974,7 @@ struct kvm_enable_cap {
> > #define KVM_CAP_GUEST_MEMFD_FLAGS 244
> > #define KVM_CAP_ARM_SEA_TO_USER 245
> > #define KVM_CAP_S390_USER_OPEREXEC 246
> > +#define KVM_CAP_ARM_HW_DIRTY_STATE_TRACK 248
> >
> > struct kvm_irq_routing_irqchip {
> > __u32 irqchip;
> > --
> > 2.33.0
> >
>
> Instead of having these architecture specific capability, I wonder if
> we can add a generic capability like "KVM_CAP_HW_DIRTY_STATE", so
> other architecture supports similar things can reuse this capability,
What of the existing stuff doing the same thing? x86's PML, to start
with?
> For this generic thing I suggest, the getter returns the max support
> entry count (or the buffer size) it supports like the dirty ring
> capability. And the setter just let the architecture set the parameters
> based on the user request.
This looks wrong on a number of levels.
- If you want something generic, there is the existing dirty
log/bitmap. How this stuff is populated is none of the user's
business (trapping write accesses, dirty bit collection from the
PTs, or HW-generated log), and we don't need an extra feature for
it. Performance will obviously suck, but that's what you pay for
something abstracted and cross-architecture.
- If you want something architecture specific, then it can't be
generic, by definition. You get the raw speed and compatibility with
other arch-specific extensions.
> This should do no harm to this implement, as everything still depends
> on the architecture behavior, and leave room for other architecture
> to reuse this.
Again, the generic framework exists, you just have to implement the
backend you want.
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v2] arm64: kernel: Unify CNP disable workaround into ARM64_WORKAROUND_DISABLE_CNP
From: Zeng Heng @ 2026-06-01 8:50 UTC (permalink / raw)
To: Vladimir Murzin, xuwei5, wangyushan12, maz, skhan,
miko.lenczewski, lucaswei, broonie, thuth, ryan.roberts,
tongtiangen, oupton, kuninori.morimoto.gx, mark.rutland, will,
corbet, catalin.marinas, kevin.brodsky, lpieralisi, yangyicong,
james.clark, yeoreum.yun
Cc: linux-doc, wangkefeng.wang, linux-arm-kernel, linux-kernel
In-Reply-To: <1e107eba-e28c-4fbf-80dc-808b8c3f4bb5@arm.com>
Hi Vladimir,
On 2026/5/29 17:17, Vladimir Murzin wrote:
> Hi,
>
> On 5/29/26 07:31, Zeng Heng wrote:
>> From: Zeng Heng <zengheng4@huawei.com>
>>
>> HiSilicon HIP09 implements TLB entry matching behavior that deviates
>> from the ARM architecture specification when the CnP (Common not Private)
>> bit is set in TTBRx_ELx.
>>
>> When TTBRx.CNP=1, TLB entries may be incorrectly shared between CPU
>> cores, leading to TLB conflicts and stale mappings. This breaks
>> coherency and can result in incorrect translations.
>>
>> Add the hardware erratum workaround (Hisilicon erratum 162100125) to
>> disable CNP on affected HIP09 cores.
>>
>> Merge the existing NVIDIA Carmel and the HiSilicon HIP09 CNP errata
>> workarounds into a single generic capability ARM64_WORKAROUND_DISABLE_CNP.
>>
>> Both NVIDIA Carmel and HiSilicon HIP09 have hardware errata where
>> CNP (Common Not Private) behavior differs from the ARM specification,
>> causing incorrect TLB entry sharing between cores. The existing
>> NVIDIA_CARMEL_CNP_ERRATUM and the newly added HISILICON_ERRATUM_162100125
>> are now both handled by the unified ARM64_WORKAROUND_DISABLE_CNP.
>>
>> Co-developed-by: Tong Tiangen <tongtiangen@huawei.com>
>> Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
>> Signed-off-by: Zeng Heng <zengheng4@huawei.com>
>> ---
>> v1: https://lore.kernel.org/all/20260526015720.206854-1-zengheng@huaweicloud.com/
>>
>> Changes in v2:
>> - Unify CNP disable workaround into ARM64_WORKAROUND_DISABLE_CNP
>> ---
>>
>> Documentation/arch/arm64/silicon-errata.rst | 4 +++-
>> arch/arm64/Kconfig | 17 ++++++++++++-----
>> arch/arm64/include/asm/cpucaps.h | 4 ++--
>> arch/arm64/kernel/cpu_errata.c | 17 ++++++++++++-----
>> arch/arm64/kernel/cpufeature.c | 2 +-
>> arch/arm64/tools/cpucaps | 2 +-
>> 6 files changed, 31 insertions(+), 15 deletions(-)
>>
>> diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
>> index 211119ce7adc..b4565e1a726d 100644
>> --- a/Documentation/arch/arm64/silicon-errata.rst
>> +++ b/Documentation/arch/arm64/silicon-errata.rst
>> @@ -254,7 +254,7 @@ stable kernels.
>> | Marvell | ARM-MMU-500 | #582743 | N/A |
>> +----------------+-----------------+-----------------+-----------------------------+
>> +----------------+-----------------+-----------------+-----------------------------+
>> -| NVIDIA | Carmel Core | N/A | NVIDIA_CARMEL_CNP_ERRATUM |
>> +| NVIDIA | Carmel Core | N/A | ARM64_WORKAROUND_DISABLE_CNP|
>> +----------------+-----------------+-----------------+-----------------------------+
>> | NVIDIA | T241 GICv3/4.x | T241-FABRIC-4 | N/A |
>> +----------------+-----------------+-----------------+-----------------------------+
>> @@ -284,6 +284,8 @@ stable kernels.
>> +----------------+-----------------+-----------------+-----------------------------+
>> | Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_162100801 |
>> +----------------+-----------------+-----------------+-----------------------------+
>> +| Hisilicon | Hip09 | #162100125 | ARM64_WORKAROUND_DISABLE_CNP|
>> ++----------------+-----------------+-----------------+-----------------------------+
>> +----------------+-----------------+-----------------+-----------------------------+
>> | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
>> +----------------+-----------------+-----------------+-----------------------------+
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index fe60738e5943..dc0bd32ea2d1 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -1315,13 +1315,20 @@ config QCOM_FALKOR_ERRATUM_E1041
>>
>> If unsure, say Y.
>>
>> -config NVIDIA_CARMEL_CNP_ERRATUM
>> - bool "NVIDIA Carmel CNP: CNP on Carmel semantically different than ARM cores"
>> +config ARM64_WORKAROUND_DISABLE_CNP
>> + bool "Disable CNP on affected CPUs"
>> default y
>> help
>> - If CNP is enabled on Carmel cores, non-sharable TLBIs on a core will not
>> - invalidate shared TLB entries installed by a different core, as it would
>> - on standard ARM cores.
>> + This option disables the CNP (Common Not Private) feature on CPUs
>> + that have hardware errata affecting CNP behavior.
>> +
>> + On NVIDIA Carmel cores, CNP behaves differently than on standard ARM
>> + cores: non-shareable TLBIs on a core may not invalidate shared TLB
>> + entries installed by a different core.
>> +
>> + On Hisilicon HIP09 cores, TLB entries may be incorrectly shared
>> + between cores when TTBRx.CNP=1, leading to TLB conflicts and
>> + stale mappings.
>>
>> If unsure, say Y.
>>
> I'm afraid we cannot swap one config with another. Instead, we need to follow
> established pattern for sharing workaround, something like
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 378e50fef247..68eb2993cfd3 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -1315,9 +1315,13 @@ config QCOM_FALKOR_ERRATUM_E1041
>
> If unsure, say Y.
>
> +config ARM64_WORKAROUND_DISABLE_CNP
> + bool
> +
> config NVIDIA_CARMEL_CNP_ERRATUM
> bool "NVIDIA Carmel CNP: CNP on Carmel semantically different than ARM cores"
> default y
> + select ARM64_WORKAROUND_DISABLE_CNP
> help
> If CNP is enabled on Carmel cores, non-sharable TLBIs on a core will not
> invalidate shared TLB entries installed by a different core, as it would
>
>
> and related changes for generalisation of the workaround - that would to be patch 1/2.
>
> Then we can easily wire-up your errata with something like
>
> +config HISILICON_ERRATUM_162100125
> + bool "Hisilicon erratum 162100125"
> + default y
> + select ARM64_WORKAROUND_DISABLE_CNP
> + help
> + On HiSilicon HIP09, TLB entry matching behavior when CNP
> + (TTBRx.CNP=1) is enabled differs from the ARM architecture
> + specification.
> +
> + TLB entries may be incorrectly shared between CPUs, potentially
> + causing TLB conflicts and stale mappings.
> +
> + Disable CNP support for affected HiSilicon HIP09 cores.
> +
> + If unsure, say Y.
>
> and related update in documentation and MIDR list - that would be patch 2/2
>
> Thanks
> Vladimir
>
>> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
>> index d0d3cdd5763c..25c61cda901c 100644
>> --- a/arch/arm64/include/asm/cpucaps.h
>> +++ b/arch/arm64/include/asm/cpucaps.h
>> @@ -58,8 +58,8 @@ cpucap_is_possible(const unsigned int cap)
>> return IS_ENABLED(CONFIG_ARM64_ERRATUM_2658417);
>> case ARM64_WORKAROUND_CAVIUM_23154:
>> return IS_ENABLED(CONFIG_CAVIUM_ERRATUM_23154);
>> - case ARM64_WORKAROUND_NVIDIA_CARMEL_CNP:
>> - return IS_ENABLED(CONFIG_NVIDIA_CARMEL_CNP_ERRATUM);
>> + case ARM64_WORKAROUND_DISABLE_CNP:
>> + return IS_ENABLED(CONFIG_ARM64_WORKAROUND_DISABLE_CNP);
>> case ARM64_WORKAROUND_REPEAT_TLBI:
>> return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
>> case ARM64_WORKAROUND_SPECULATIVE_SSBS:
>> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
>> index 5377e4c2eba2..675cd059165c 100644
>> --- a/arch/arm64/kernel/cpu_errata.c
>> +++ b/arch/arm64/kernel/cpu_errata.c
>> @@ -394,6 +394,14 @@ static const struct arm64_cpu_capabilities qcom_erratum_1003_list[] = {
>> };
>> #endif
>>
>> +#ifdef CONFIG_ARM64_WORKAROUND_DISABLE_CNP
>> +static const struct midr_range cnp_erratum_cpus[] = {
>> + MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
>> + MIDR_ALL_VERSIONS(MIDR_HISI_HIP09),
>> + {},
>> +};
>> +#endif
>> +
>> #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
>> static const struct midr_range workaround_clean_cache[] = {
>> #if defined(CONFIG_ARM64_ERRATUM_826319) || \
>> @@ -801,12 +809,11 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>> 1, 0),
>> },
>> #endif
>> -#ifdef CONFIG_NVIDIA_CARMEL_CNP_ERRATUM
>> +#ifdef CONFIG_ARM64_WORKAROUND_DISABLE_CNP
>> {
>> - /* NVIDIA Carmel */
>> - .desc = "NVIDIA Carmel CNP erratum",
>> - .capability = ARM64_WORKAROUND_NVIDIA_CARMEL_CNP,
>> - ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
>> + .desc = "NVIDIA Carmel CNP erratum, or Hisilicon erratum 162100125",
>> + .capability = ARM64_WORKAROUND_DISABLE_CNP,
>> + ERRATA_MIDR_RANGE_LIST(cnp_erratum_cpus),
>> },
>> #endif
>> #ifdef CONFIG_ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 6d53bb15cf7b..20c5f24f74a9 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1785,7 +1785,7 @@ has_useable_cnp(const struct arm64_cpu_capabilities *entry, int scope)
>> if (is_kdump_kernel())
>> return false;
>>
>> - if (cpus_have_cap(ARM64_WORKAROUND_NVIDIA_CARMEL_CNP))
>> + if (cpus_have_cap(ARM64_WORKAROUND_DISABLE_CNP))
Here, ARM64_WORKAROUND_DISABLE_CNP comes from arch/arm64/tools/cpucaps,
not from arch/arm64/Kconfig. Therefore, if we do not replace WORKAROUND_NVIDIA_CARMEL_CNP
in arch/arm64/tools/cpucaps, we will have to continue adding a redundant
WORKAROUND_DISABLE_CNP along with its corresponding redundant logic.
I prefer to keep CONFIG_ARM64_WORKAROUND_NVIDIA_CARMEL_CNP in arch/arm64/Kconfig
and replace WORKAROUND_NVIDIA_CARMEL_CNP in arch/arm64/tools/cpucaps.
I would like to confirm whether the above aligns with your expectations.
Best regards,
Zeng Heng
>> return false;
>>
>> return has_cpuid_feature(entry, scope);
>> diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
>> index 811c2479e82d..9b85a84f6fd4 100644
>> --- a/arch/arm64/tools/cpucaps
>> +++ b/arch/arm64/tools/cpucaps
>> @@ -120,7 +120,7 @@ WORKAROUND_CAVIUM_TX2_219_PRFM
>> WORKAROUND_CAVIUM_TX2_219_TVM
>> WORKAROUND_CLEAN_CACHE
>> WORKAROUND_DEVICE_LOAD_ACQUIRE
>> -WORKAROUND_NVIDIA_CARMEL_CNP
>> +WORKAROUND_DISABLE_CNP
>> WORKAROUND_PMUV3_IMPDEF_TRAPS
>> WORKAROUND_QCOM_FALKOR_E1003
>> WORKAROUND_QCOM_ORYON_CNTVOFF
>> --
>> 2.43.0
>>
^ permalink raw reply
* Re: [PATCH mm-unstable v18 06/14] mm/khugepaged: generalize collapse_huge_page for mTHP collapse
From: Lance Yang @ 2026-06-01 8:44 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: npache, linux-doc, linux-kernel, linux-mm, linux-trace-kernel,
aarcange, akpm, anshuman.khandual, apopple, baohua, baolin.wang,
byungchul, catalin.marinas, cl, corbet, dave.hansen, dev.jain,
gourry, hannes, hughd, jack, jackmanb, jannh, jglisse,
joshua.hahnjy, kas, liam, ljs, mathieu.desnoyers, matthew.brost,
mhiramat, mhocko, peterx, pfalcato, rakie.kim, raquini, rdunlap,
richard.weiyang, rientjes, rostedt, rppt, ryan.roberts, shivankg,
sunnanyong, surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
zokeefe, usama.arif
In-Reply-To: <1c99294c-9ebe-4856-bfde-09801701d75c@kernel.org>
On 2026/6/1 16:15, David Hildenbrand (Arm) wrote:
> On 6/1/26 09:49, Lance Yang wrote:
>>
>>
>> On 2026/6/1 14:54, David Hildenbrand (Arm) wrote:
>>> On 6/1/26 05:28, Lance Yang wrote:
>>>>
>>>>
>>>> Ah, fair point.
>>>>
>>>> I was mostly worried about arch hooks that walk vma->vm_mm again, rather
>>>> than only using the pte pointer passed in. For example, mips does:
>>>
>>> Right, a re-walk would be the real problem.
>>>
>>>>
>>>> update_mmu_cache_range()
>>>> -> __update_tlb()
>>>> -> pgd_offset(vma->vm_mm, address)
>>>> -> pte_offset_map(...)
>>>>
>>>> and __update_tlb() has this assumption:
>>>>
>>>> /*
>>>> * update_mmu_cache() is called between pte_offset_map_lock()
>>>> * and pte_unmap_unlock(), so we can assume that ptep is not
>>>> * NULL here: and what should be done below if it were NULL?
>>>> */
>>>>
>>>> So if khugepaged happens to run with current->active_mm == vma->vm_mm
>>>> here, could __update_tlb() hit the none PMD, get NULL from
>>>> pte_offset_map(), and then dereference it?
>>>
>>> Likely yes -- that MIPS code is horrible. And the comment in MIPS code
>>> even spells that out. :(
>>>
>>> Do you know about other code like that, or is MIPS the only one doing a
>>> re-walk and crossing fingers?
>>
>> I had Codex do the boring grep-work through the arch update_mmu_cache*
>> code :D
>>
>> MIPS doesn't seem to be the only code doing a re-walk, but it is the
>> only one I found that appears to assume the PMD/PTE walk cannot fail,
>> without checking whether the PMD is none ...
>
> Okay, but likely the other code that tries to handle it is also problematic.
>
> Best to make sure the page table is already installed when updating the entries.
Neat, makes sense to me :D
That way the page talbe is back in place before any arch hook gets to
look at it :)
^ permalink raw reply
* Re: [PATCH] Documentation: drm: Add entry for removing spsc_queue to TODO list
From: Christian König @ 2026-06-01 8:30 UTC (permalink / raw)
To: Philipp Stanner, avid Airlie, Simona Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Jonathan Corbet, Shuah Khan,
dakr, Tvrtko Ursulin
Cc: dri-devel, linux-doc, linux-kernel
In-Reply-To: <20260529215207.115513-2-phasta@kernel.org>
On 5/29/26 23:52, Philipp Stanner wrote:
> drm_sched contains a lockless queue (spsc_queue) that seems to be
> useless and potentially unsound.
>
> Add a TODO list entry for replacing spsc_queue with a locked list.
>
> Signed-off-by: Philipp Stanner <phasta@kernel.org>
Reviewed-by: Christian König <christian.koenig@amd.com>
> ---
> Documentation/gpu/todo.rst | 41 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 41 insertions(+)
>
> diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
> index cdddf8db35f5..87e082b0eb48 100644
> --- a/Documentation/gpu/todo.rst
> +++ b/Documentation/gpu/todo.rst
> @@ -948,6 +948,47 @@ Contact: Philipp Stanner <phasta@kernel.org>
>
> Level: Intermediate
>
> +Replace the lockless queue with a locked list
> +---------------------------------------------
> +
> +drm_sched is the only user in the entire kernel of a special lockless queue, the
> +spsc_queue. This queue utilizes:
> +
> +- preempt_disable()
> +- atomic instructions
> +- memory barriers
> +- ACCESS_ONCE()
> +
> +whereas a conventional spinlock utilizes:
> +
> +- preempt_disable()
> +- 1 atomic instruction for taking / releasing the lock
> +- memory barriers
> +
> +Moreover, drm_sched_entity_push_job(), the only user of spsc_queue_push(), has
> +to take a lock in some situations anyways and calls to it are often serialized
> +with a driver lock.
> +
> +It is, thus, highly questionable whether the lockless queue grants any advantage
> +at all. Considering that its internals are not well documented and its correctness
> +is not formally proven, it seems desirable to replace the queue with a mere list
> +or hlist that is protected by a spinlock.
> +
> +Tasks:
> +
> +- Replace the spsc_queue in drm/sched (and those who might access the scheduler's
> + internal queue) with a spinlock + (h)list.
> +- Ideally, check with some micro benchmarks and real world tests (preferably
> + with amdgpu) for relevant performance regressions.
> +- Remove the spsc_queue from the kernel altogether.
> +
> +Contact:
> +
> +- Philipp Stanner <phasta@kernel.org>
> +- Christian König <christian.koenig@amd.com>
> +
> +Level: Beginner
> +
> Outside DRM
> ===========
>
^ permalink raw reply
* Re: [PATCH v2 03/10] riscv: Standardize extension capitalization
From: Anup Patel @ 2026-06-01 8:28 UTC (permalink / raw)
To: Paul Walmsley
Cc: Jonathan Corbet, Palmer Dabbelt, Conor Dooley, Albert Ou,
Alexandre Ghiti, Shuah Khan, Atish Patra, Shuah Khan,
Deepak Gupta, Zong Li, Christian Brauner, Andrew Jones,
Charlie Jenkins, Samuel Holland, linux-doc, linux-riscv,
linux-kernel, linux-kselftest, kvm, kvm-riscv, Charlie Jenkins,
Guodong Xu
In-Reply-To: <20260511-rva23u64-hwprobe-v2-v2-3-21c5a544f1dc@riscstar.com>
On Mon, May 11, 2026 at 7:06 PM Guodong Xu <guodong@riscstar.com> wrote:
>
> From: Charlie Jenkins <charlie@rivosinc.com>
>
> The base extensions are often lowercase and were written as lowercase in
> hwcap, but other references to these extensions in the kernel are
> uppercase. Standardize the case to make it easier to handle macro
> expansion.
>
> Signed-off-by: Charlie Jenkins <thecharlesjenkins@gmail.com>
> [Apply KVM_ISA_EXT_ARR(), fixup all KVM use.]
> Signed-off-by: Andrew Jones <andrew.jones@oss.qualcomm.com>
> Signed-off-by: Guodong Xu <guodong@riscstar.com>
LGTM.
Acked-by: Anup Patel <anup@brainfault.org>
Reviewed-by: Anup Patel <anup@brainfault.org>
@Paul, This patch is independent of other changes
in this series. If you are okay then I can take this single
patch through KVM RISC-V tree.
Regards,
Anup
>
> ---
> v2:
> - Rebased onto v7.1-rc2.
> - KVM_ISA_EXT_ARR() consolidation moved to its new upstream location
> (kvm/isa.c); host-side checks now use kvm_riscv_isa_check_host().
> ---
> arch/riscv/include/asm/hwcap.h | 18 +++++++++---------
> arch/riscv/include/asm/switch_to.h | 4 ++--
> arch/riscv/kernel/cpufeature.c | 32 ++++++++++++++++----------------
> arch/riscv/kernel/sys_hwprobe.c | 4 ++--
> arch/riscv/kvm/isa.c | 16 ++++++++--------
> arch/riscv/kvm/main.c | 2 +-
> arch/riscv/kvm/vcpu_fp.c | 20 ++++++++++----------
> arch/riscv/kvm/vcpu_onereg.c | 6 +++---
> arch/riscv/kvm/vcpu_vector.c | 10 +++++-----
> 9 files changed, 56 insertions(+), 56 deletions(-)
>
> diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
> index 7ef8e5f55c8dc..44bf8c7d8acc5 100644
> --- a/arch/riscv/include/asm/hwcap.h
> +++ b/arch/riscv/include/asm/hwcap.h
> @@ -10,15 +10,15 @@
>
> #include <uapi/asm/hwcap.h>
>
> -#define RISCV_ISA_EXT_a ('a' - 'a')
> -#define RISCV_ISA_EXT_c ('c' - 'a')
> -#define RISCV_ISA_EXT_d ('d' - 'a')
> -#define RISCV_ISA_EXT_f ('f' - 'a')
> -#define RISCV_ISA_EXT_h ('h' - 'a')
> -#define RISCV_ISA_EXT_i ('i' - 'a')
> -#define RISCV_ISA_EXT_m ('m' - 'a')
> -#define RISCV_ISA_EXT_q ('q' - 'a')
> -#define RISCV_ISA_EXT_v ('v' - 'a')
> +#define RISCV_ISA_EXT_A ('a' - 'a')
> +#define RISCV_ISA_EXT_C ('c' - 'a')
> +#define RISCV_ISA_EXT_D ('d' - 'a')
> +#define RISCV_ISA_EXT_F ('f' - 'a')
> +#define RISCV_ISA_EXT_H ('h' - 'a')
> +#define RISCV_ISA_EXT_I ('i' - 'a')
> +#define RISCV_ISA_EXT_M ('m' - 'a')
> +#define RISCV_ISA_EXT_Q ('q' - 'a')
> +#define RISCV_ISA_EXT_V ('v' - 'a')
>
> /*
> * These macros represent the logical IDs of each multi-letter RISC-V ISA
> diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
> index 0e71eb82f920c..ff35a4d04f85a 100644
> --- a/arch/riscv/include/asm/switch_to.h
> +++ b/arch/riscv/include/asm/switch_to.h
> @@ -60,8 +60,8 @@ static inline void __switch_to_fpu(struct task_struct *prev,
>
> static __always_inline bool has_fpu(void)
> {
> - return riscv_has_extension_likely(RISCV_ISA_EXT_f) ||
> - riscv_has_extension_likely(RISCV_ISA_EXT_d);
> + return riscv_has_extension_likely(RISCV_ISA_EXT_F) ||
> + riscv_has_extension_likely(RISCV_ISA_EXT_D);
> }
> #else
> static __always_inline bool has_fpu(void) { return false; }
> diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
> index 1734f9a4c2fd7..5cf463570229d 100644
> --- a/arch/riscv/kernel/cpufeature.c
> +++ b/arch/riscv/kernel/cpufeature.c
> @@ -84,7 +84,7 @@ EXPORT_SYMBOL_GPL(__riscv_isa_extension_available);
> static int riscv_ext_f_depends(const struct riscv_isa_ext_data *data,
> const unsigned long *isa_bitmap)
> {
> - if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_f))
> + if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_F))
> return 0;
>
> return -EPROBE_DEFER;
> @@ -146,7 +146,7 @@ static int riscv_ext_f_validate(const struct riscv_isa_ext_data *data,
> * Due to extension ordering, d is checked before f, so no deferral
> * is required.
> */
> - if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_d)) {
> + if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_D)) {
> pr_warn_once("This kernel does not support systems with F but not D\n");
> return -EINVAL;
> }
> @@ -189,7 +189,7 @@ static int riscv_ext_vector_float_validate(const struct riscv_isa_ext_data *data
> * Since this function validates vector only, and v/Zve* are probed
> * after f/d, there's no need for a deferral here.
> */
> - if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_d))
> + if (!__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_D))
> return -EINVAL;
>
> return 0;
> @@ -224,7 +224,7 @@ static int riscv_ext_zcd_validate(const struct riscv_isa_ext_data *data,
> const unsigned long *isa_bitmap)
> {
> if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZCA) &&
> - __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_d))
> + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_D))
> return 0;
>
> return -EPROBE_DEFER;
> @@ -237,7 +237,7 @@ static int riscv_ext_zcf_validate(const struct riscv_isa_ext_data *data,
> return -EINVAL;
>
> if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_ZCA) &&
> - __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_f))
> + __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_F))
> return 0;
>
> return -EPROBE_DEFER;
> @@ -490,15 +490,15 @@ static const unsigned int riscv_c_exts[] = {
> * New entries to this struct should follow the ordering rules described above.
> */
> const struct riscv_isa_ext_data riscv_isa_ext[] = {
> - __RISCV_ISA_EXT_DATA(i, RISCV_ISA_EXT_i),
> - __RISCV_ISA_EXT_DATA(m, RISCV_ISA_EXT_m),
> - __RISCV_ISA_EXT_SUPERSET(a, RISCV_ISA_EXT_a, riscv_a_exts),
> - __RISCV_ISA_EXT_DATA_VALIDATE(f, RISCV_ISA_EXT_f, riscv_ext_f_validate),
> - __RISCV_ISA_EXT_DATA_VALIDATE(d, RISCV_ISA_EXT_d, riscv_ext_d_validate),
> - __RISCV_ISA_EXT_DATA(q, RISCV_ISA_EXT_q),
> - __RISCV_ISA_EXT_SUPERSET(c, RISCV_ISA_EXT_c, riscv_c_exts),
> - __RISCV_ISA_EXT_SUPERSET_VALIDATE(v, RISCV_ISA_EXT_v, riscv_v_exts, riscv_ext_vector_float_validate),
> - __RISCV_ISA_EXT_DATA(h, RISCV_ISA_EXT_h),
> + __RISCV_ISA_EXT_DATA(i, RISCV_ISA_EXT_I),
> + __RISCV_ISA_EXT_DATA(m, RISCV_ISA_EXT_M),
> + __RISCV_ISA_EXT_SUPERSET(a, RISCV_ISA_EXT_A, riscv_a_exts),
> + __RISCV_ISA_EXT_DATA_VALIDATE(f, RISCV_ISA_EXT_F, riscv_ext_f_validate),
> + __RISCV_ISA_EXT_DATA_VALIDATE(d, RISCV_ISA_EXT_D, riscv_ext_d_validate),
> + __RISCV_ISA_EXT_DATA(q, RISCV_ISA_EXT_Q),
> + __RISCV_ISA_EXT_SUPERSET(c, RISCV_ISA_EXT_C, riscv_c_exts),
> + __RISCV_ISA_EXT_SUPERSET_VALIDATE(v, RISCV_ISA_EXT_V, riscv_v_exts, riscv_ext_vector_float_validate),
> + __RISCV_ISA_EXT_DATA(h, RISCV_ISA_EXT_H),
> __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicbom, RISCV_ISA_EXT_ZICBOM, riscv_xlinuxenvcfg_exts, riscv_ext_zicbom_validate),
> __RISCV_ISA_EXT_DATA_VALIDATE(zicbop, RISCV_ISA_EXT_ZICBOP, riscv_ext_zicbop_validate),
> __RISCV_ISA_EXT_SUPERSET_VALIDATE(zicboz, RISCV_ISA_EXT_ZICBOZ, riscv_xlinuxenvcfg_exts, riscv_ext_zicboz_validate),
> @@ -897,8 +897,8 @@ static void __init riscv_fill_hwcap_from_isa_string(unsigned long *isa2hwcap)
> * marchid.
> */
> if (acpi_disabled && boot_vendorid == THEAD_VENDOR_ID && boot_archid == 0x0) {
> - this_hwcap &= ~isa2hwcap[RISCV_ISA_EXT_v];
> - clear_bit(RISCV_ISA_EXT_v, source_isa);
> + this_hwcap &= ~isa2hwcap[RISCV_ISA_EXT_V];
> + clear_bit(RISCV_ISA_EXT_V, source_isa);
> }
>
> riscv_resolve_isa(source_isa, isainfo->isa, &this_hwcap, isa2hwcap);
> diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
> index 1659d31fd288f..f8f68ba781b45 100644
> --- a/arch/riscv/kernel/sys_hwprobe.c
> +++ b/arch/riscv/kernel/sys_hwprobe.c
> @@ -88,10 +88,10 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
> if (has_fpu())
> pair->value |= RISCV_HWPROBE_IMA_FD;
>
> - if (riscv_isa_extension_available(NULL, c))
> + if (riscv_isa_extension_available(NULL, C))
> pair->value |= RISCV_HWPROBE_IMA_C;
>
> - if (has_vector() && riscv_isa_extension_available(NULL, v))
> + if (has_vector() && riscv_isa_extension_available(NULL, V))
> pair->value |= RISCV_HWPROBE_IMA_V;
>
> /*
> diff --git a/arch/riscv/kvm/isa.c b/arch/riscv/kvm/isa.c
> index 1132d909cc25c..94077117d1136 100644
> --- a/arch/riscv/kvm/isa.c
> +++ b/arch/riscv/kvm/isa.c
> @@ -17,14 +17,14 @@
> /* Mapping between KVM ISA Extension ID & guest ISA extension ID */
> static const unsigned long kvm_isa_ext_arr[] = {
> /* Single letter extensions (alphabetically sorted) */
> - [KVM_RISCV_ISA_EXT_A] = RISCV_ISA_EXT_a,
> - [KVM_RISCV_ISA_EXT_C] = RISCV_ISA_EXT_c,
> - [KVM_RISCV_ISA_EXT_D] = RISCV_ISA_EXT_d,
> - [KVM_RISCV_ISA_EXT_F] = RISCV_ISA_EXT_f,
> - [KVM_RISCV_ISA_EXT_H] = RISCV_ISA_EXT_h,
> - [KVM_RISCV_ISA_EXT_I] = RISCV_ISA_EXT_i,
> - [KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m,
> - [KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v,
> + KVM_ISA_EXT_ARR(A),
> + KVM_ISA_EXT_ARR(C),
> + KVM_ISA_EXT_ARR(D),
> + KVM_ISA_EXT_ARR(F),
> + KVM_ISA_EXT_ARR(H),
> + KVM_ISA_EXT_ARR(I),
> + KVM_ISA_EXT_ARR(M),
> + KVM_ISA_EXT_ARR(V),
> /* Multi letter extensions (alphabetically sorted) */
> KVM_ISA_EXT_ARR(SMNPM),
> KVM_ISA_EXT_ARR(SMSTATEEN),
> diff --git a/arch/riscv/kvm/main.c b/arch/riscv/kvm/main.c
> index cb8a65273c1f0..70640701310c8 100644
> --- a/arch/riscv/kvm/main.c
> +++ b/arch/riscv/kvm/main.c
> @@ -85,7 +85,7 @@ static int __init riscv_kvm_init(void)
> char slist[64];
> const char *str;
>
> - if (!riscv_isa_extension_available(NULL, h)) {
> + if (!riscv_isa_extension_available(NULL, H)) {
> kvm_info("hypervisor extension not available\n");
> return -ENODEV;
> }
> diff --git a/arch/riscv/kvm/vcpu_fp.c b/arch/riscv/kvm/vcpu_fp.c
> index 6ad6df26a2fd4..bb11e6757d349 100644
> --- a/arch/riscv/kvm/vcpu_fp.c
> +++ b/arch/riscv/kvm/vcpu_fp.c
> @@ -21,8 +21,8 @@ void kvm_riscv_vcpu_fp_reset(struct kvm_vcpu *vcpu)
> struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
>
> cntx->sstatus &= ~SR_FS;
> - if (riscv_isa_extension_available(vcpu->arch.isa, f) ||
> - riscv_isa_extension_available(vcpu->arch.isa, d))
> + if (riscv_isa_extension_available(vcpu->arch.isa, F) ||
> + riscv_isa_extension_available(vcpu->arch.isa, D))
> cntx->sstatus |= SR_FS_INITIAL;
> else
> cntx->sstatus |= SR_FS_OFF;
> @@ -38,9 +38,9 @@ void kvm_riscv_vcpu_guest_fp_save(struct kvm_cpu_context *cntx,
> const unsigned long *isa)
> {
> if ((cntx->sstatus & SR_FS) == SR_FS_DIRTY) {
> - if (riscv_isa_extension_available(isa, d))
> + if (riscv_isa_extension_available(isa, D))
> __kvm_riscv_fp_d_save(cntx);
> - else if (riscv_isa_extension_available(isa, f))
> + else if (riscv_isa_extension_available(isa, F))
> __kvm_riscv_fp_f_save(cntx);
> kvm_riscv_vcpu_fp_clean(cntx);
> }
> @@ -50,9 +50,9 @@ void kvm_riscv_vcpu_guest_fp_restore(struct kvm_cpu_context *cntx,
> const unsigned long *isa)
> {
> if ((cntx->sstatus & SR_FS) != SR_FS_OFF) {
> - if (riscv_isa_extension_available(isa, d))
> + if (riscv_isa_extension_available(isa, D))
> __kvm_riscv_fp_d_restore(cntx);
> - else if (riscv_isa_extension_available(isa, f))
> + else if (riscv_isa_extension_available(isa, F))
> __kvm_riscv_fp_f_restore(cntx);
> kvm_riscv_vcpu_fp_clean(cntx);
> }
> @@ -89,7 +89,7 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
> void *reg_val;
>
> if ((rtype == KVM_REG_RISCV_FP_F) &&
> - riscv_isa_extension_available(vcpu->arch.isa, f)) {
> + riscv_isa_extension_available(vcpu->arch.isa, F)) {
> if (KVM_REG_SIZE(reg->id) != sizeof(u32))
> return -EINVAL;
> if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr))
> @@ -102,7 +102,7 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
> } else
> return -ENOENT;
> } else if ((rtype == KVM_REG_RISCV_FP_D) &&
> - riscv_isa_extension_available(vcpu->arch.isa, d)) {
> + riscv_isa_extension_available(vcpu->arch.isa, D)) {
> if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) {
> if (KVM_REG_SIZE(reg->id) != sizeof(u32))
> return -EINVAL;
> @@ -138,7 +138,7 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
> void *reg_val;
>
> if ((rtype == KVM_REG_RISCV_FP_F) &&
> - riscv_isa_extension_available(vcpu->arch.isa, f)) {
> + riscv_isa_extension_available(vcpu->arch.isa, F)) {
> if (KVM_REG_SIZE(reg->id) != sizeof(u32))
> return -EINVAL;
> if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr))
> @@ -151,7 +151,7 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
> } else
> return -ENOENT;
> } else if ((rtype == KVM_REG_RISCV_FP_D) &&
> - riscv_isa_extension_available(vcpu->arch.isa, d)) {
> + riscv_isa_extension_available(vcpu->arch.isa, D)) {
> if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) {
> if (KVM_REG_SIZE(reg->id) != sizeof(u32))
> return -EINVAL;
> diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
> index bb920e8923c93..5cc7ddd4aa276 100644
> --- a/arch/riscv/kvm/vcpu_onereg.c
> +++ b/arch/riscv/kvm/vcpu_onereg.c
> @@ -770,7 +770,7 @@ static inline unsigned long num_fp_f_regs(const struct kvm_vcpu *vcpu)
> {
> const struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
>
> - if (riscv_isa_extension_available(vcpu->arch.isa, f))
> + if (riscv_isa_extension_available(vcpu->arch.isa, F))
> return sizeof(cntx->fp.f) / sizeof(u32);
> else
> return 0;
> @@ -799,7 +799,7 @@ static inline unsigned long num_fp_d_regs(const struct kvm_vcpu *vcpu)
> {
> const struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
>
> - if (riscv_isa_extension_available(vcpu->arch.isa, d))
> + if (riscv_isa_extension_available(vcpu->arch.isa, D))
> return sizeof(cntx->fp.d.f) / sizeof(u64) + 1;
> else
> return 0;
> @@ -878,7 +878,7 @@ static inline unsigned long num_sbi_regs(struct kvm_vcpu *vcpu)
>
> static inline unsigned long num_vector_regs(const struct kvm_vcpu *vcpu)
> {
> - if (!riscv_isa_extension_available(vcpu->arch.isa, v))
> + if (!riscv_isa_extension_available(vcpu->arch.isa, V))
> return 0;
>
> /* vstart, vl, vtype, vcsr, vlenb and 32 vector regs */
> diff --git a/arch/riscv/kvm/vcpu_vector.c b/arch/riscv/kvm/vcpu_vector.c
> index 62d2fb77bb9b9..f26108a4e601e 100644
> --- a/arch/riscv/kvm/vcpu_vector.c
> +++ b/arch/riscv/kvm/vcpu_vector.c
> @@ -26,7 +26,7 @@ void kvm_riscv_vcpu_vector_reset(struct kvm_vcpu *vcpu)
>
> cntx->vector.vlenb = riscv_v_vsize / 32;
>
> - if (riscv_isa_extension_available(isa, v)) {
> + if (riscv_isa_extension_available(isa, V)) {
> cntx->sstatus |= SR_VS_INITIAL;
> WARN_ON(!cntx->vector.datap);
> memset(cntx->vector.datap, 0, riscv_v_vsize);
> @@ -45,7 +45,7 @@ void kvm_riscv_vcpu_guest_vector_save(struct kvm_cpu_context *cntx,
> unsigned long *isa)
> {
> if ((cntx->sstatus & SR_VS) == SR_VS_DIRTY) {
> - if (riscv_isa_extension_available(isa, v))
> + if (riscv_isa_extension_available(isa, V))
> __kvm_riscv_vector_save(cntx);
> kvm_riscv_vcpu_vector_clean(cntx);
> }
> @@ -55,7 +55,7 @@ void kvm_riscv_vcpu_guest_vector_restore(struct kvm_cpu_context *cntx,
> unsigned long *isa)
> {
> if ((cntx->sstatus & SR_VS) != SR_VS_OFF) {
> - if (riscv_isa_extension_available(isa, v))
> + if (riscv_isa_extension_available(isa, V))
> __kvm_riscv_vector_restore(cntx);
> kvm_riscv_vcpu_vector_clean(cntx);
> }
> @@ -154,7 +154,7 @@ int kvm_riscv_vcpu_get_reg_vector(struct kvm_vcpu *vcpu,
> void *reg_addr;
> int rc;
>
> - if (!riscv_isa_extension_available(isa, v))
> + if (!riscv_isa_extension_available(isa, V))
> return -ENOENT;
>
> rc = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size, ®_addr);
> @@ -180,7 +180,7 @@ int kvm_riscv_vcpu_set_reg_vector(struct kvm_vcpu *vcpu,
> void *reg_addr;
> int rc;
>
> - if (!riscv_isa_extension_available(isa, v))
> + if (!riscv_isa_extension_available(isa, V))
> return -ENOENT;
>
> if (reg_num == KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)) {
>
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH mm-unstable v18 06/14] mm/khugepaged: generalize collapse_huge_page for mTHP collapse
From: David Hildenbrand (Arm) @ 2026-06-01 8:15 UTC (permalink / raw)
To: Lance Yang
Cc: npache, linux-doc, linux-kernel, linux-mm, linux-trace-kernel,
aarcange, akpm, anshuman.khandual, apopple, baohua, baolin.wang,
byungchul, catalin.marinas, cl, corbet, dave.hansen, dev.jain,
gourry, hannes, hughd, jack, jackmanb, jannh, jglisse,
joshua.hahnjy, kas, liam, ljs, mathieu.desnoyers, matthew.brost,
mhiramat, mhocko, peterx, pfalcato, rakie.kim, raquini, rdunlap,
richard.weiyang, rientjes, rostedt, rppt, ryan.roberts, shivankg,
sunnanyong, surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
zokeefe, usama.arif
In-Reply-To: <fb8f24b1-ce8e-4f06-bbd8-f148a9bcaeee@linux.dev>
On 6/1/26 09:49, Lance Yang wrote:
>
>
> On 2026/6/1 14:54, David Hildenbrand (Arm) wrote:
>> On 6/1/26 05:28, Lance Yang wrote:
>>>
>>>
>>> Ah, fair point.
>>>
>>> I was mostly worried about arch hooks that walk vma->vm_mm again, rather
>>> than only using the pte pointer passed in. For example, mips does:
>>
>> Right, a re-walk would be the real problem.
>>
>>>
>>> update_mmu_cache_range()
>>> -> __update_tlb()
>>> -> pgd_offset(vma->vm_mm, address)
>>> -> pte_offset_map(...)
>>>
>>> and __update_tlb() has this assumption:
>>>
>>> /*
>>> * update_mmu_cache() is called between pte_offset_map_lock()
>>> * and pte_unmap_unlock(), so we can assume that ptep is not
>>> * NULL here: and what should be done below if it were NULL?
>>> */
>>>
>>> So if khugepaged happens to run with current->active_mm == vma->vm_mm
>>> here, could __update_tlb() hit the none PMD, get NULL from
>>> pte_offset_map(), and then dereference it?
>>
>> Likely yes -- that MIPS code is horrible. And the comment in MIPS code
>> even spells that out. :(
>>
>> Do you know about other code like that, or is MIPS the only one doing a
>> re-walk and crossing fingers?
>
> I had Codex do the boring grep-work through the arch update_mmu_cache*
> code :D
>
> MIPS doesn't seem to be the only code doing a re-walk, but it is the
> only one I found that appears to assume the PMD/PTE walk cannot fail,
> without checking whether the PMD is none ...
Okay, but likely the other code that tries to handle it is also problematic.
Best to make sure the page table is already installed when updating the entries.
--
Cheers,
David
^ permalink raw reply
* Re: [PATCH mm-unstable v18 11/14] mm/khugepaged: Introduce mTHP collapse support
From: David Hildenbrand (Arm) @ 2026-06-01 8:11 UTC (permalink / raw)
To: Nico Pache, linux-doc, linux-kernel, linux-mm, linux-trace-kernel
Cc: aarcange, akpm, anshuman.khandual, apopple, baohua, baolin.wang,
byungchul, catalin.marinas, cl, corbet, dave.hansen, dev.jain,
gourry, hannes, hughd, jack, jackmanb, jannh, jglisse,
joshua.hahnjy, kas, lance.yang, liam, ljs, mathieu.desnoyers,
matthew.brost, mhiramat, mhocko, peterx, pfalcato, rakie.kim,
raquini, rdunlap, richard.weiyang, rientjes, rostedt, rppt,
ryan.roberts, shivankg, sunnanyong, surenb, thomas.hellstrom,
tiwai, usamaarif642, vbabka, vishal.moola, wangkefeng.wang, will,
willy, yang, ying.huang, ziy, zokeefe
In-Reply-To: <20260522150009.121603-12-npache@redhat.com>
On 5/22/26 17:00, Nico Pache wrote:
Finally time for the core piece :)
> Enable khugepaged to collapse to mTHP orders. This patch implements the
> main scanning logic using a bitmap to track occupied pages and a stack
> structure that allows us to find optimal collapse sizes.
>
> Previous to this patch, PMD collapse had 3 main phases, a light weight
> scanning phase (mmap_read_lock) that determines a potential PMD
> collapse, an alloc phase (mmap unlocked), then finally heavier collapse
> phase (mmap_write_lock).
>
> To enabled mTHP collapse we make the following changes:
>
> During PMD scan phase, track occupied pages in a bitmap. When mTHP
> orders are enabled, we remove the restriction of max_ptes_none during the
> scan phase to avoid missing potential mTHP collapse candidates. Once we
> have scanned the full PMD range and updated the bitmap to track occupied
> pages, we use the bitmap to find the optimal mTHP size.
>
> Implement collapse_scan_bitmap() to perform binary recursion on the bitmap
> and determine the best eligible order for the collapse. A stack structure
> is used instead of traditional recursion to manage the search. This also
> prevents a traditional recursive approach when the kernel stack struct is
> limited. The algorithm recursively splits the bitmap into smaller chunks to
> find the highest order mTHPs that satisfy the collapse criteria. We start
> by attempting the PMD order, then moved on the consecutively lower orders
> (mTHP collapse). The stack maintains a pair of variables (offset, order),
> indicating the number of PTEs from the start of the PMD, and the order of
> the potential collapse candidate.
>
> The algorithm for consuming the bitmap works as such:
> 1) push (0, HPAGE_PMD_ORDER) onto the stack
> 2) pop the stack
> 3) check if the number of set bits in that (offset,order) pair
> statisfy the max_ptes_none threshold for that order
> 4) if yes, attempt collapse
> 5) if no (or collapse fails), push two new stack items representing
> the left and right halves of the current bitmap range, at the
> next lower order
> 6) repeat at step (2) until stack is empty.
>
> Below is a diagram representing the algorithm and stack items:
>
> offset mid_offset
> | |
> | |
> v v
> ____________________________________
> | PTE Page Table |
> --------------------------------------
> <-------><------->
> order-1 order-1
Reading this, it is unclear why exactly do we need the stack.
Why can't you work with offset + cur_order?
Initially,
offset = 0;
cur_order = HPAGE_PMD_ORDER;
If collapse succeeded, advance to next range.
If collapse failed, try next smaller order, keeping offset unchanged.
if (failed && cur_order > KHUGEPAGED_MIN_MTHP_ORDER) {
/* Try next smaller order. */
cur_order = cur_order - 1;
} else {
/* Skip to next chunk. */
offset += 1 << cur_order;
cur_order = max_order_from_offset(offset);
}
Of course, handling disabled orders. max_order_from_offset() is rather trivial
(natural buddy order, capped at HPAGE_PMD_ORDER).
What's the benefit of the stack?
>
> mTHP collapses reject regions containing swapped out or shared pages.
> This is because adding new entries can lead to new none pages, and these
> may lead to constant promotion into a higher order mTHP. A similar
> issue can occur with "max_ptes_none > HPAGE_PMD_NR/2" due to a collapse
> introducing at least 2x the number of pages, and on a future scan will
> satisfy the promotion condition once again. This issue is prevented via
> the collapse_max_ptes_none() function which imposes the max_ptes_none
> restrictions above.
>
> We currently only support mTHP collapse for max_ptes_none values of 0
> and HPAGE_PMD_NR - 1. resulting in the following behavior:
>
> - max_ptes_none=0: Never introduce new empty pages during collapse
> - max_ptes_none=HPAGE_PMD_NR-1: Always try collapse to the highest
> available mTHP order
>
> Any other max_ptes_none value will emit a warning and default mTHP
> collapse to max_ptes_none=0. There should be no behavior change for PMD
> collapse.
>
> Once we determine what mTHP sizes fits best in that PMD range a collapse
> is attempted. A minimum collapse order of 2 is used as this is the lowest
> order supported by anon memory as defined by THP_ORDERS_ALL_ANON.
>
> Currently madv_collapse is not supported and will only attempt PMD
> collapse.
>
> We can also remove the check for is_khugepaged inside the PMD scan as
> the collapse_max_ptes_none() function handles this logic now.
>
> Signed-off-by: Nico Pache <npache@redhat.com>
> ---
> mm/khugepaged.c | 181 +++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 172 insertions(+), 9 deletions(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 64ceebc9d8a7..d3d7db8be26c 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -99,6 +99,30 @@ static DEFINE_READ_MOSTLY_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS);
>
> static struct kmem_cache *mm_slot_cache __ro_after_init;
>
> +#define KHUGEPAGED_MIN_MTHP_ORDER 2
> +/*
> + * mthp_collapse() does an iterative DFS over a binary tree, from
> + * HPAGE_PMD_ORDER down to KHUGEPAGED_MIN_MTHP_ORDER. The max stack
> + * size needed for a DFS on a binary tree is height + 1, where
> + * height = HPAGE_PMD_ORDER - KHUGEPAGED_MIN_MTHP_ORDER.
> + *
> + * ilog2 is used in place of HPAGE_PMD_ORDER because some architectures
> + * (e.g. ppc64le) do not define HPAGE_PMD_ORDER until after build time.
I was confused there for a second why you mention ilog2, when it's really "We
cannot use HPAGE_PMD_ORDER.".
Best to simplify to:
"Note that we cannot use HPAGE_PMD_ORDER, because it is variable on some
architectures".
> + */
> +#define MTHP_STACK_SIZE (ilog2(MAX_PTRS_PER_PTE) - KHUGEPAGED_MIN_MTHP_ORDER + 1)
> +
> +/*
> + * Defines a range of PTE entries in a PTE page table which are being
> + * considered for mTHP collapse.
> + *
> + * @offset: the offset of the first PTE entry in a PMD range.
> + * @order: the order of the PTE entries being considered for collapse.
> + */
> +struct mthp_range {
> + u16 offset;
> + u8 order;
> +};
> +
> struct collapse_control {
> bool is_khugepaged;
>
> @@ -110,6 +134,12 @@ struct collapse_control {
>
> /* nodemask for allocation fallback */
> nodemask_t alloc_nmask;
> +
> + /* Each bit represents a single occupied (!none/zero) page. */
> + DECLARE_BITMAP(mthp_bitmap, MAX_PTRS_PER_PTE);
This should just be called something like "present_ptes"
> + /* A mask of the current range being considered for mTHP collapse. */
> + DECLARE_BITMAP(mthp_bitmap_mask, MAX_PTRS_PER_PTE);
> + struct mthp_range mthp_bitmap_stack[MTHP_STACK_SIZE];
This is really just a temporary bitmap used for collapse_mthp_count_present()
only. Either rename it, or better, avoid it completely.
> };
>
> /**
> @@ -1411,20 +1441,137 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long s
> return result;
> }
>
> +static void collapse_mthp_stack_push(struct collapse_control *cc, int *stack_size,
> + u16 offset, u8 order)
> +{
> + const int size = *stack_size;
> + struct mthp_range *stack = &cc->mthp_bitmap_stack[size];
> +
> + VM_WARN_ON_ONCE(size >= MTHP_STACK_SIZE);
> + stack->order = order;
> + stack->offset = offset;
> + (*stack_size)++;
> +}
> +
> +static struct mthp_range collapse_mthp_stack_pop(struct collapse_control *cc,
> + int *stack_size)
> +{
> + const int size = *stack_size;
> +
> + VM_WARN_ON_ONCE(size <= 0);
> + (*stack_size)--;
> + return cc->mthp_bitmap_stack[size - 1];
> +}
> +
> +static unsigned int collapse_mthp_count_present(struct collapse_control *cc,
> + u16 offset, unsigned int nr_ptes)
> +{
> + bitmap_zero(cc->mthp_bitmap_mask, MAX_PTRS_PER_PTE);
> + bitmap_set(cc->mthp_bitmap_mask, offset, nr_ptes);
> + return bitmap_weight_and(cc->mthp_bitmap, cc->mthp_bitmap_mask, MAX_PTRS_PER_PTE);
You really just want to count the number of set bits? You don't need a temporary
bitmap for that.
Assume you want to check an order-2 (4 bits), bitmap_weight_and() would check
all bits ...
I'd suggest starting simple here, and avoiding the temporary bitmap.
Can we simply use bitmap_weight_from(cc->mthp_bitmap, offset, nr_ptes)?
> +}
> +
> +/*
> + * mthp_collapse() consumes the bitmap that is generated during
> + * collapse_scan_pmd() to determine what regions and mTHP orders fit best.
> + *
> + * Each bit in cc->mthp_bitmap represents a single occupied (!none/zero) page.
> + * A stack structure cc->mthp_bitmap_stack is used to check different regions
> + * of the bitmap for collapse eligibility. The stack maintains a pair of
> + * variables (offset, order), indicating the number of PTEs from the start of
> + * the PMD, and the order of the potential collapse candidate respectively. We
> + * start at the PMD order and check if it is eligible for collapse; if not, we
> + * add two entries to the stack at a lower order to represent the left and right
> + * halves of the PTE page table we are examining.
> + *
> + * offset mid_offset
> + * | |
> + * | |
> + * v v
> + * --------------------------------------
> + * | cc->mthp_bitmap |
> + * --------------------------------------
> + * <-------><------->
> + * order-1 order-1
> + *
> + * For each of these, we determine how many PTE entries are occupied in the
> + * range of PTE entries we propose to collapse, then we compare this to a
> + * threshold number of PTE entries which would need to be occupied for a
> + * collapse to be permitted at that order (accounting for max_ptes_none).
> + *
> + * If a collapse is permitted, we attempt to collapse the PTE range into a
> + * mTHP.
> + */
> +static int mthp_collapse(struct mm_struct *mm, struct vm_area_struct *vma,
> + unsigned long address, int referenced, int unmapped,
> + struct collapse_control *cc, unsigned long enabled_orders)
> +{
> + unsigned int nr_occupied_ptes, nr_ptes, max_ptes_none;
> + int collapsed = 0, stack_size = 0;
> + unsigned long collapse_address;
> + struct mthp_range range;
> + u16 offset;
> + u8 order;
> +
> + collapse_mthp_stack_push(cc, &stack_size, 0, HPAGE_PMD_ORDER);
> +
> + while (stack_size) {
> + range = collapse_mthp_stack_pop(cc, &stack_size);
> + order = range.order;
> + offset = range.offset;
> + nr_ptes = 1UL << order;
> +
> + if (!test_bit(order, &enabled_orders))
> + goto next_order;
> +
> + max_ptes_none = collapse_max_ptes_none(cc, vma, order);
> +
> + nr_occupied_ptes = collapse_mthp_count_present(cc, offset,
> + nr_ptes);
> +
> + if (nr_occupied_ptes >= nr_ptes - max_ptes_none) {
> + int ret;
> +
> + collapse_address = address + offset * PAGE_SIZE;
> + ret = collapse_huge_page(mm, collapse_address, referenced,
> + unmapped, cc, order);
> + if (ret == SCAN_SUCCEED) {
> + collapsed += nr_ptes;
> + continue;
> + }
> + }
> +
> +next_order:
> + if ((BIT(order) - 1) & enabled_orders) {
> + const u8 next_order = order - 1;
> + const u16 mid_offset = offset + (nr_ptes / 2);
> +
> + collapse_mthp_stack_push(cc, &stack_size, mid_offset,
> + next_order);
> + collapse_mthp_stack_push(cc, &stack_size, offset,
> + next_order);
> + }
> + }
> + return collapsed;
> +}
> +
> static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> struct vm_area_struct *vma, unsigned long start_addr,
> bool *lock_dropped, struct collapse_control *cc)
> {
> - const unsigned int max_ptes_none = collapse_max_ptes_none(cc, vma, HPAGE_PMD_ORDER);
> const unsigned int max_ptes_shared = collapse_max_ptes_shared(cc, HPAGE_PMD_ORDER);
> const unsigned int max_ptes_swap = collapse_max_ptes_swap(cc, HPAGE_PMD_ORDER);
> + unsigned int max_ptes_none = collapse_max_ptes_none(cc, vma, HPAGE_PMD_ORDER);
> + enum tva_type tva_flags = cc->is_khugepaged ? TVA_KHUGEPAGED : TVA_FORCED_COLLAPSE;
> pmd_t *pmd;
> - pte_t *pte, *_pte;
> - int none_or_zero = 0, shared = 0, referenced = 0;
> + pte_t *pte, *_pte, pteval;
> + int i;
> + int none_or_zero = 0, shared = 0, nr_collapsed = 0, referenced = 0;
> enum scan_result result = SCAN_FAIL;
> struct page *page = NULL;
> struct folio *folio = NULL;
> unsigned long addr;
> + unsigned long enabled_orders;
> spinlock_t *ptl;
> int node = NUMA_NO_NODE, unmapped = 0;
>
> @@ -1436,8 +1583,19 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> goto out;
> }
>
> + bitmap_zero(cc->mthp_bitmap, MAX_PTRS_PER_PTE);
> memset(cc->node_load, 0, sizeof(cc->node_load));
> nodes_clear(cc->alloc_nmask);
> +
> + enabled_orders = collapse_allowable_orders(vma, vma->vm_flags, tva_flags);
> +
> + /*
> + * If PMD is the only enabled order, enforce max_ptes_none, otherwise
> + * scan all pages to populate the bitmap for mTHP collapse.
> + */
You should note here, that we re-verify in mthp_collapse().
But the question is, whether we should relocate the check completely into
mthp_collapse(), instead of conditionally duplicating it.
What speaks against always populating the bitmap and making the decision in
mthp_collapse()?
Sure, we might scan a page table a bit longer, but the code gets clearer ... and
I am not sure if scanning some more page table entries is really that critical here.
> + if (enabled_orders != BIT(HPAGE_PMD_ORDER))
> + max_ptes_none = KHUGEPAGED_MAX_PTES_LIMIT;
> +
> pte = pte_offset_map_lock(mm, pmd, start_addr, &ptl);
> if (!pte) {
> cc->progress++;
> @@ -1445,11 +1603,13 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> goto out;
> }
>
> - for (addr = start_addr, _pte = pte; _pte < pte + HPAGE_PMD_NR;
> - _pte++, addr += PAGE_SIZE) {
> + for (i = 0; i < HPAGE_PMD_NR; i++) {
> + _pte = pte + i;
> + addr = start_addr + i * PAGE_SIZE;
> + pteval = ptep_get(_pte);
> +
> cc->progress++;
>
> - pte_t pteval = ptep_get(_pte);
> if (pte_none_or_zero(pteval)) {
> if (++none_or_zero > max_ptes_none) {
> result = SCAN_EXCEED_NONE_PTE;
> @@ -1529,6 +1689,8 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> }
> }
>
> + /* Set bit for occupied pages */
> + __set_bit(i, cc->mthp_bitmap);
> /*
> * Record which node the original page is from and save this
> * information to cc->node_load[].
> @@ -1587,10 +1749,11 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> if (result == SCAN_SUCCEED) {
> /* collapse_huge_page expects the lock to be dropped before calling */
> mmap_read_unlock(mm);
> - result = collapse_huge_page(mm, start_addr, referenced,
> - unmapped, cc, HPAGE_PMD_ORDER);
> - /* collapse_huge_page will return with the mmap_lock released */
> + nr_collapsed = mthp_collapse(mm, vma, start_addr, referenced,
> + unmapped, cc, enabled_orders);
> + /* mmap_lock was released above, set lock_dropped */
> *lock_dropped = true;
> + result = nr_collapsed ? SCAN_SUCCEED : SCAN_FAIL;
As Lance says, this error handling likely needs some thought.
--
Cheers,
David
^ permalink raw reply
* Re: [PATCH mm-unstable v18 06/14] mm/khugepaged: generalize collapse_huge_page for mTHP collapse
From: Lance Yang @ 2026-06-01 7:49 UTC (permalink / raw)
To: David Hildenbrand (Arm)
Cc: npache, linux-doc, linux-kernel, linux-mm, linux-trace-kernel,
aarcange, akpm, anshuman.khandual, apopple, baohua, baolin.wang,
byungchul, catalin.marinas, cl, corbet, dave.hansen, dev.jain,
gourry, hannes, hughd, jack, jackmanb, jannh, jglisse,
joshua.hahnjy, kas, liam, ljs, mathieu.desnoyers, matthew.brost,
mhiramat, mhocko, peterx, pfalcato, rakie.kim, raquini, rdunlap,
richard.weiyang, rientjes, rostedt, rppt, ryan.roberts, shivankg,
sunnanyong, surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
zokeefe, usama.arif
In-Reply-To: <f5d38f64-ab92-496d-afd3-29ccc17fec2b@kernel.org>
On 2026/6/1 14:54, David Hildenbrand (Arm) wrote:
> On 6/1/26 05:28, Lance Yang wrote:
>>
>> On Sun, May 31, 2026 at 10:00:17PM +0200, David Hildenbrand (Arm) wrote:
>>> On 5/31/26 11:39, Lance Yang wrote:
>>>>
>>>>
>>>> Emm ... is it safe to use map_anon_folio_pte_nopf() here?
>>>>
>>>> At this point pmdp_collapse_flush() has cleared the PMD from the page
>>>> tables. The PTE table we are updating is only reachable through the saved
>>>> old PMD value, _pmd, until pmd_populate() below.
>>>>
>>>> map_anon_folio_pte_nopf() does set_ptes() and then calls
>>>> update_mmu_cache_range(). Documentation/core-api/cachetlb.rst describes
>>>> that hook as:
>>>>
>>>> "
>>>> At the end of every page fault, this routine is invoked to tell
>>>> the architecture specific code that translations now exists
>>>> in the software page tables for address space "vma->vm_mm"
>>>> at virtual address "address" for "nr" consecutive pages.
>>>> "
>>>>
>>>> But that does not seem true here yet, since the PTE table is not
>>>> reachable from vma->vm_mm when update_mmu_cache_range() is called.
>>>>
>>>> Should we avoid calling update_mmu_cache_range() until after the PTE
>>>> table is reinstalled with pmd_populate()?
>>>
>>> I recall that update_mmu_cache* users mostly care about updating folios flags,
>>> for the folio derived from the PTE ... or flushing caches for the user address.
>>>
>>> So intuitively I would say "the architecture code doesn't care that the PMD
>>> table will only be visible to HW shortly after". The important thing should be
>>> that it will definetly happen, and that nothing else is curently there or can be
>>> there?
>>
>> Ah, fair point.
>>
>> I was mostly worried about arch hooks that walk vma->vm_mm again, rather
>> than only using the pte pointer passed in. For example, mips does:
>
> Right, a re-walk would be the real problem.
>
>>
>> update_mmu_cache_range()
>> -> __update_tlb()
>> -> pgd_offset(vma->vm_mm, address)
>> -> pte_offset_map(...)
>>
>> and __update_tlb() has this assumption:
>>
>> /*
>> * update_mmu_cache() is called between pte_offset_map_lock()
>> * and pte_unmap_unlock(), so we can assume that ptep is not
>> * NULL here: and what should be done below if it were NULL?
>> */
>>
>> So if khugepaged happens to run with current->active_mm == vma->vm_mm
>> here, could __update_tlb() hit the none PMD, get NULL from
>> pte_offset_map(), and then dereference it?
>
> Likely yes -- that MIPS code is horrible. And the comment in MIPS code
> even spells that out. :(
>
> Do you know about other code like that, or is MIPS the only one doing a
> re-walk and crossing fingers?
I had Codex do the boring grep-work through the arch update_mmu_cache*
code :D
MIPS doesn't seem to be the only code doing a re-walk, but it is the
only one I found that appears to assume the PMD/PTE walk cannot fail,
without checking whether the PMD is none ...
Cheers, Lance
>>
>> Just wanted to raise it since some arch code may still have assumptions
>> like this, and the always-enable-mTHP work is getting closer ...
>
> Right. I assume set_pte_at() couldn't trigger something similar (re-walk) in arch code,
> because we simply provide the ptep. update_mmu_cache_range() only consumes the pte.
>
>>
>> Probably very very very hard to hit, though :)
>
> Delaying update_mmu_cache_range() is nasty, as we'd have to make sure that
> nobody can interfere in the meantime ... and the PMD lock will not be sufficient.
>
> Maybe we could reinstall the page table with the cleared (none) entries while
> still holding the PTL?
>
> Thinking out loud:
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 5ba298d420b7..e39b750b1e6f 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -1413,13 +1413,17 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long s
> map_anon_folio_pmd_nopf(folio, pmd, vma, pmd_addr);
> } else {
> /*
> - * set_ptes is called in map_anon_folio_pte_nopf with the
> - * pmd_ptl lock still held; this is safe as the PMD is expected
> - * to be none. The pmd entry is then repopulated below.
> + * Re-insert the page table with the cleared entries, but
> + * hold the PTL, such that no one can mess with the re-installed
> + * page table until we updated the temporarily-cleared entries
> + * through map_anon_folio_pte_nopf().
> */
> - map_anon_folio_pte_nopf(folio, pte, vma, start_addr, /*uffd_wp=*/ false);
> - smp_wmb(); /* make PTEs visible before PMD. See pmd_install() */
> + if (pte_ptl != pmd_ptl)
> + spin_lock(pte_ptl);
> pmd_populate(mm, pmd, pmd_pgtable(_pmd));
> + map_anon_folio_pte_nopf(folio, pte, vma, start_addr, /*uffd_wp=*/ false);
> + if (pte_ptl != pmd_ptl)
> + spin_unlock(pte_ptl);
> }
> spin_unlock(pmd_ptl);
>
>
>
^ permalink raw reply
* Re: [PATCH v5 04/18] mm: skip out-of-range bits in mk_vma_flags()
From: Lorenzo Stoakes @ 2026-06-01 7:42 UTC (permalink / raw)
To: Mike Rapoport
Cc: Kiryl Shutsemau, akpm, peterx, david, surenb, vbabka,
Liam.Howlett, ziy, corbet, skhan, seanjc, pbonzini, jthoughton,
aarcange, sj, usama.arif, linux-mm, linux-kernel, linux-doc,
linux-kselftest, kvm, kernel-team, Kiryl Shutsemau (Meta), stable
In-Reply-To: <ahsVyQZ5UXhJLct2@kernel.org>
On Sat, May 30, 2026 at 07:52:25PM +0300, Mike Rapoport wrote:
> On Fri, May 29, 2026 at 03:00:14PM +0100, Lorenzo Stoakes wrote:
> > On Tue, May 26, 2026 at 02:04:52PM +0100, Kiryl Shutsemau wrote:
> > > From: "Kiryl Shutsemau (Meta)" <kas@kernel.org>
> > >
> > > vma_flags_t is one unsigned long on 32-bit -- NUM_VMA_FLAG_BITS ==
> > > BITS_PER_LONG by design, so VM_xxx-declared bits sit in the first
> > > word and hit the single-long fast path. But the bit enum declares
> > > some bits unconditionally above BITS_PER_LONG (VMA_UFFD_MINOR_BIT
> > > == 41 today, with VM_UFFD_MINOR == VM_NONE on 32-bit so no VMA
> > > actually carries the bit).
> >
> > Yeah ugh.
> >
> > > Passing such a bit to mk_vma_flags() goes through __set_bit(41,
> > > &one_long) and writes one word past the end. The compiler folds
> > > the OOB store with wraparound (1UL << (41 % 32) == bit 9) into
> > > the first word. Bit 9 is already in __VMA_UFFD_FLAGS so the mask
> > > happens to come out right today, but any high-numbered bit whose
> >
> > That is... helpful :) but not great that this is the situation, an
> > oversight, clearly! How I hate 32-bit kernels :)
> >
> > > mod-BITS_PER_LONG position is otherwise unused would silently OR
> > > an extra bit into the mask.
> > >
> > > Add VMA_NO_BIT and have DECLARE_VMA_BIT() resolve any bitnum out
> > > of range to it. vma_flags_set_flag() drops negative bit values.
> > > The ternary collapses at compile time, the runtime check folds
> > > away when the bit is in range, and the common path is unchanged.
> >
> > Hmm are you sure it does?
> >
> > A key design goal was that mk_vma_flags() generates compile-time constants
> > the same as if the bitmap were constructed independently.
> >
> > This surely must generate code? Or at least runs a significant risk of it?
>
> ...
>
> > A simple solution that doesn't require change to the core is to just uglify
> > userfaultfd_k.h a bit with:
> >
> > #ifdef HAVE_ARCH_USERFAULTFD_MINOR
> > #define __VMA_UFFD_FLAGS mk_vma_flags(VMA_UFFD_MISSING_BIT, VMA_UFFD_WP_BIT, \
> > VMA_UFFD_MINOR_BIT)
> > #else
> > #define __VMA_UFFD_FLAGS mk_vma_flags(VMA_UFFD_MISSING_BIT, VMA_UFFD_WP_BIT)
> > #endif
> >
> > But of course that becomes much more horrible with your changes...
> >
> > Another alternative, which I used for VMA_DROPPABLE is to add something
> > like this in mm.h:
> >
> > #ifdef CONFIG_HAVE_ARCH_USERFAULTFD_MINOR
> > #define VM_UFFD_MINOR INIT_VM_FLAG(UFFD_MINOR)
> > +define VMA_UFFD_MINOR mk_vma_flags(VMA_UFFD_MINOR_BIT)
> > #else
> > #define VM_UFFD_MINOR VM_NONE
> > +define VMA_UFFD_MINOR EMPTY_VMA_FLAGS
> > #endif
>
> I have a PoC of yet another alternative:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/rppt/linux.git/log/?h=uffd/vm-flags
>
> The idea there is to keep a single VMA flag, VMA_UFFD_BIT/VM_UFFD and move
> all the rest into what's now struct vm_userfaultfd_ctx.
*Gives Mike a big kiss*
YES PLEASE!
>
> --
> Sincerely yours,
> Mike.
Thanks, Lorenzo
^ permalink raw reply
* Re: [RFC PATCH 0/5] mm, swap: Virtual Swap Space (Swap Table Edition)
From: Kairui Song @ 2026-06-01 7:34 UTC (permalink / raw)
To: Nhat Pham
Cc: kasong, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
corbet, david, dev.jain, gourry, hannes, hughd, jannh,
joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
muchun.song, npache, pavel, peterx, peterz, pfalcato, rafael,
rakie.kim, roman.gushchin, rppt, ryan.roberts, shakeel.butt,
shikemeng, surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed,
yuanchu, zhengqi.arch, ziy, kernel-team, riel, haowenchao22
In-Reply-To: <20260528212955.1912856-1-nphamcs@gmail.com>
On Thu, May 28, 2026 at 02:29:24PM +0800, Nhat Pham wrote:
> Based on: mm-unstable @ 444fc9435e57 + swap-table phase IV v5 [2].
>
> I manually adapted Kairui's ghost device implementation (from [4])
> for my vswap device. I've credited him as Co-developed-by on Patch I
> since a substantial portion of the dynamic-cluster infrastructure is
> his (I did propose the idea of using xarray/radix tree for dynamic
> swap clusters allocation and management though :P).
>
> >From here on out, for simplicity, I will refer to swap table phase IV
> as "P4", and the older v6 virtual swap space implementation as "v6".
>
...
>
> This series reimplements the virtual swap space concept (see [1])
> on top of Kairui Song's swap table infrastructure, on top of [2]
> and in accordance with his proposal in [3]. The proposal's idea
> is interesting, so I decided to give it a shot myself. I'm still not
> 100% sure that this is bug-proof, but hey, it compiles, and has
> not crashed in my simple stress testing :)
>
> The prototype here is feature-complete relative to the swap-table P4
> baseline — swapout, swapin, freeing, swapoff, zswap writeback, zswap
> shrinker, memcg charging, and THP swapin all work for
> both vswap and direct-physical entries — and satisfies all three
> requirements above: no backend coupling (zswap/zero entries hold no
> physical slot), dynamic swap space (clusters allocated on demand via
> xarray, no static provisioning), and efficient backend transfer
> (in-place vtable updates, no PTE/rmap walking).
>
> II. Design
>
> With vswap, pages are assigned virtual swap entries on a ghost device
> with no backing storage. These entries are backed by zswap, zero pages,
> or (lazily) physical swap slots. Physical backing is allocated only
> when needed — on zswap writeback or reclaim writeout, after the rmap
> step.
>
> Compared to the standalone v6 implementation [1], which introduces a
> 24-byte per-entry swap descriptor and its own cluster allocator, this
> edition uses swap_table infrastructure, and share a lot of the allocator
> logic. Per-slot metadata is stored in a tag-encoded virtual_table
> (atomic_long_t, 8 bytes per slot), and physical clusters store
> Pointer-tagged rmap entries in the swap_table for reverse lookup back to
> the virtual cluster.
>
> Here are some data layout diagrams:
>
> Case 1: vswap entry (virtualized)
>
> PTE swap_cluster_info_dynamic
> vswap_entry +-------------------------+
> (swp_entry_t) ------>| swap_cluster_info (ci) |
> | +--------------------+ |
> | | swap_table | |
> | | PFN / Shadow | |
> | | memcg_table | |
> | | count,flags,order | |
> | | lock, list | |
> | +--------------------+ |
> | |
> | virtual_table |
> | +--------------------+ |
> | | NONE | |
> | | PHYS | |
> | | ZERO | |
> | | ZSWAP(entry*) | |
> | | FOLIO(folio*) | |
> | +--------------------+ |
> +-------------------------+
> |
> | PHYS resolves to
> v
> PHYSICAL CLUSTER (swap_cluster_info)
> +--------------------------+
> | swap_table per-slot: |
> | NULL - free |
> | PFN - cached folio |
> | Shadow - swapped out |
> | Pointer- vswap rmap |
> | Bad - unusable |
> | |
> | Vswap-backing slot: |
> | Pointer(C|swp_entry_t) |
> | rmap back to vswap |
> +--------------------------+
>
> Case 2: direct-mapped physical entry (no vswap)
>
> PTE PHYSICAL CLUSTER (swap_cluster_info)
> phys_entry +--------------------------+
> (swp_entry_t) ------>| swap_table per-slot: |
> | NULL - free |
> | PFN - cached folio |
> | Shadow - swapped out |
> | Bad - unusable |
> +--------------------------+
>
> struct swap_cluster_info_dynamic {
> struct swap_cluster_info ci; /* swap_table, lock, etc. */
> unsigned int index; /* position in xarray */
> struct rcu_head rcu; /* kfree_rcu deferred free */
> atomic_long_t *virtual_table; /* backend info, 8 B/slot */
> };
>
> Each vswap cluster (swap_cluster_info_dynamic) extends the classic
> swap_cluster_info struct with a virtual_table array that stores the
> backend information for each virtual swap entry in the cluster. Each
> entry is tag-encoded in the low 3 bits to indicate backend types:
>
> NONE: |----- 0000 ------|000| free / unbacked
> PHYS: |-- (type:5,off:N)|001| on a physical swapfile (shifted)
> ZERO: |----- 0000 ------|010| zero-filled page
> ZSWAP: |--- zswap_entry* |011| compressed in zswap
> FOLIO: |--- folio* ------|100| in-memory folio
Thanks for trying this approach!
For the format part, PHYS don't need that much bits I think,
so by slightly adjust the format vswap device could be share
mostly the same format with ordinary device.
For example typical modern system don't have a address space larger
than 52 bit. (Even with full 64 bits used for addressing, shift it
by 12 we get 52). Plus 5 for type, you get 57, so you can have a
marker that should work as long as it shorter than 1000000 for PHYS,
and shared for all table format since it's not in conflict with
anything. You have also use a few extra bits so a single swap space
can be 8 times larger than RAM space, and since we can help
multiple swap type I think that should be far than enough?
Then you have Shadow back at 001, and zero bit in shadow. The only
special one is Zswap, which will be 100 now, and that's exactly the
reserved pointer format in current swap table format, on seeing
si->flags & VSWAP && is_pointer(swp_tb) you know that's zswap :)
Folio / PFN can still be 010 as in the current swap table format.
Then everything seems clean and aligned, no more special handling
for vswap needed, there are detailed to sort out, but it should work.
> - Pointer-tagged swap_table on physical clusters for rmap (physical
> -> virtual) lookup.
Or reuse the PHYS format (rename it maybe) since point back to vswap
is also pointing to a si.
> III. Follow-ups:
>
> In no particular order (and most of which can be done as follow-up
> patch series rather than shoving everything in the initial landing):
>
> - More thorough stress testing is very much needed.
>
> - Performance benchmarks to make sure I don't accidentally regress
> the vswap-less case, and that the vswap's case performance is
> good. I suspect I will have to port a lot of the
> optimizations I implemented in v6 over here - some of the
> inefficiencies are inherent in any swap virtualization, and
> would require the same fix (for e.g the MRU cluster caching
> for faster cluster lookup - see [8] and [9]).
This could be imporved by per-si percpu cluster. Both YoungJun's
tiering and Baoquan's previous swap ops mentioned this is needed,
and now vswap also need that. If the vswap is also a si, then it will
make use of this too.
YoungJun posted this a few month before:
https://lore.kernel.org/linux-mm/20260131125454.3187546-5-youngjun.park@lge.com/
The concern is that some locking contention could be heavier, or maybe
that's just a hypothetical problem though.
>
> - Runtime enable/disable of the vswap device. To be honest, I don't
> know if there is a value in this. My preference is vswap can be
> optimized to the point that any overhead is negligible. Failing that,
> maybe we can come up with some simple heuristics that automatically
> decides for users?
>
> In this RFC, CONFIG_VSWAP=y means the vswap device is always created at
> boot, and CONFIG_VSWAP=n means the vswap device is never created. This
> *might* be enough just on its own.
>
> Is a runtime knob (sysfs or sysctl) worth the complexity beyond
> these heuristics? I'm not sure yet. Maintaining both cases
I checked the code and I think it's not hard to do, patch 1 already
handling the meta data dynamically, everything will still just work
even if you remove vswap at runtime. The rest of patches need adaption
but might not end up being complex, it other comments here
are considered.
For patch 2, a few routines like vswap_can_swapin_thp seems not
needed or should be moved to __swap_cache_alloc? VSWAP_FOLIO is
same as swap cache folio check, which is already covered. Same for
zero checking, and VSWAP_NONE which is same as swap count check
I think. That way we not only save a lot of code, we also no
longer need to treat vswap specially.
If you keep the format compatible with what we already have
as the earlier comment mentions, a large portion of this part
might be unneeded.
> at runtime also has overhead for checking as well, and some of the
> checks are not cheap :)
I also noticed the new introduced swap_read_folio_phys in patch 3, so
this actually can be done using Baoquan's swapops idea which is now
part of Christoph's swap batching:
https://lore.kernel.org/linux-mm/20260528124559.2566481-9-hch@lst.de/#r
That series is focusing on batching and better performance but swapops
was also proposed as a way to solve the virtual layer, makes it possible
to have vswap as one kind of swapops which is Chris talked a lot about:
https://lore.kernel.org/linux-mm/aZiFvzlBJiYBUDre@MiWiFi-R3L-srv/
Following this, we could have something like:
const struct swap_ops swap_vswap_ops = {
.submit_write = swap_vswap_submit_write,
.submit_read = swap_vswap_submit_read,
};
The move the folio_realloc_swap in swap_vswap_submit_write.
Merge of IO might be moved to lower phyiscal level for vswap.
Another gain is that the memory usage and CPU overhead will be
lower with only one layer. As I'm recently trying to offload swap
dataplane off CPU so the CPU won't touch the data at all, the
overhead will be purely by swap itself, plus some mm overhead.
Things like that and IO optimization above and could make swap
subsystem more and more performance sensitive so we have cases
that needs only one layer.
>
> - Defer per-cluster memcg_table and zeromap allocation on physical
> clusters. A physical swap cluster backing vswap entries only do
> not really need their memcg_table, but the current design forces
> us to allocate it anyway. This is a waste of memory, and is an
> overhead regression compared to my older design on the zswap-only
> case, which Johannes has pointed out multiple times (see [6]),
> and is one of the biggest reasons why I have not been satisfied
> with this approach thus far. It honestly is a bit of a
> deal-breaker...
>
> That said, I think I might be able to allocate them on demand, i.e
> only when the first direct-mapped slot is allocated on that cluster.
> That will give us the best of BOTH worlds, for both the vswap and
> directly-mapped physical swap cases. No promises, but I will try
> (if this approach is good enough for all parties).
Zero map is not really a problem when it's just a inlined bit I think.
For memcg table allocation, on demand seems a good idea, and actually
we are not far from there, I tried to generalize the
alloc-then-retry-sleep-alloc in swap_alloc_table but still not generic
enough I guess.. Good new is the allocation of the table is already
kind of ondemand, just need to split the detection of these two kind
of table.
Mean while I also remember we once discussed about splitting the
accounting for vswap / physical swap? If we went that approach we
don't need to treat memcg_table specially.
> - Widen swap_info_struct->max to unsigned long. The vswap device's
> max is currently clamped to ALIGN_DOWN(UINT_MAX, SWAPFILE_CLUSTER)
> (~16 TiB) to fit in unsigned int. 16 TiB is small for vswap,
> especially when we're getting increasingly big machines memory-wise.
This should be very easy to do, just replace unsigned int with
unsigned long, a lot of place to touch though :)
^ permalink raw reply
* Re: [PATCH v1] docs: real-time: Fix duplicated sched(7) text
From: Sebastian Andrzej Siewior @ 2026-06-01 7:00 UTC (permalink / raw)
To: Costa Shulyupin
Cc: Clark Williams, Steven Rostedt, Jonathan Corbet, Shuah Khan,
Randy Dunlap, linux-rt-devel, linux-doc, linux-kernel
In-Reply-To: <20260531141823.4118954-1-costa.shul@redhat.com>
On 2026-05-31 17:18:22 [+0300], Costa Shulyupin wrote:
> The man page reference appeared twice - once as plain text and
> once as a hyperlink. Remove the plain text duplicate.
>
> Assisted-by: Claude:claude-opus-4-6
> Signed-off-by: Costa Shulyupin <costa.shul@redhat.com>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Sebastian
^ permalink raw reply
* Re: [PATCH v2] arm64: kernel: Unify CNP disable workaround into ARM64_WORKAROUND_DISABLE_CNP
From: Zeng Heng @ 2026-06-01 7:00 UTC (permalink / raw)
To: Vladimir Murzin, xuwei5, wangyushan12, maz, skhan,
miko.lenczewski, lucaswei, broonie, thuth, ryan.roberts,
tongtiangen, oupton, kuninori.morimoto.gx, mark.rutland, will,
corbet, catalin.marinas, kevin.brodsky, lpieralisi, yangyicong,
james.clark, yeoreum.yun
Cc: linux-doc, wangkefeng.wang, linux-arm-kernel, linux-kernel
In-Reply-To: <1e107eba-e28c-4fbf-80dc-808b8c3f4bb5@arm.com>
Hi Vladimir,
On 2026/5/29 17:17, Vladimir Murzin wrote:
> Hi,
>
> On 5/29/26 07:31, Zeng Heng wrote:
>> From: Zeng Heng <zengheng4@huawei.com>
>>
>> HiSilicon HIP09 implements TLB entry matching behavior that deviates
>> from the ARM architecture specification when the CnP (Common not Private)
>> bit is set in TTBRx_ELx.
>>
>> When TTBRx.CNP=1, TLB entries may be incorrectly shared between CPU
>> cores, leading to TLB conflicts and stale mappings. This breaks
>> coherency and can result in incorrect translations.
>>
>> Add the hardware erratum workaround (Hisilicon erratum 162100125) to
>> disable CNP on affected HIP09 cores.
>>
>> Merge the existing NVIDIA Carmel and the HiSilicon HIP09 CNP errata
>> workarounds into a single generic capability ARM64_WORKAROUND_DISABLE_CNP.
>>
>> Both NVIDIA Carmel and HiSilicon HIP09 have hardware errata where
>> CNP (Common Not Private) behavior differs from the ARM specification,
>> causing incorrect TLB entry sharing between cores. The existing
>> NVIDIA_CARMEL_CNP_ERRATUM and the newly added HISILICON_ERRATUM_162100125
>> are now both handled by the unified ARM64_WORKAROUND_DISABLE_CNP.
>>
>> Co-developed-by: Tong Tiangen <tongtiangen@huawei.com>
>> Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
>> Signed-off-by: Zeng Heng <zengheng4@huawei.com>
>> ---
>> v1: https://lore.kernel.org/all/20260526015720.206854-1-zengheng@huaweicloud.com/
>>
>> Changes in v2:
>> - Unify CNP disable workaround into ARM64_WORKAROUND_DISABLE_CNP
>> ---
>>
>> Documentation/arch/arm64/silicon-errata.rst | 4 +++-
>> arch/arm64/Kconfig | 17 ++++++++++++-----
>> arch/arm64/include/asm/cpucaps.h | 4 ++--
>> arch/arm64/kernel/cpu_errata.c | 17 ++++++++++++-----
>> arch/arm64/kernel/cpufeature.c | 2 +-
>> arch/arm64/tools/cpucaps | 2 +-
>> 6 files changed, 31 insertions(+), 15 deletions(-)
>>
>> diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
>> index 211119ce7adc..b4565e1a726d 100644
>> --- a/Documentation/arch/arm64/silicon-errata.rst
>> +++ b/Documentation/arch/arm64/silicon-errata.rst
>> @@ -254,7 +254,7 @@ stable kernels.
>> | Marvell | ARM-MMU-500 | #582743 | N/A |
>> +----------------+-----------------+-----------------+-----------------------------+
>> +----------------+-----------------+-----------------+-----------------------------+
>> -| NVIDIA | Carmel Core | N/A | NVIDIA_CARMEL_CNP_ERRATUM |
>> +| NVIDIA | Carmel Core | N/A | ARM64_WORKAROUND_DISABLE_CNP|
>> +----------------+-----------------+-----------------+-----------------------------+
>> | NVIDIA | T241 GICv3/4.x | T241-FABRIC-4 | N/A |
>> +----------------+-----------------+-----------------+-----------------------------+
>> @@ -284,6 +284,8 @@ stable kernels.
>> +----------------+-----------------+-----------------+-----------------------------+
>> | Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_162100801 |
>> +----------------+-----------------+-----------------+-----------------------------+
>> +| Hisilicon | Hip09 | #162100125 | ARM64_WORKAROUND_DISABLE_CNP|
>> ++----------------+-----------------+-----------------+-----------------------------+
>> +----------------+-----------------+-----------------+-----------------------------+
>> | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
>> +----------------+-----------------+-----------------+-----------------------------+
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index fe60738e5943..dc0bd32ea2d1 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -1315,13 +1315,20 @@ config QCOM_FALKOR_ERRATUM_E1041
>>
>> If unsure, say Y.
>>
>> -config NVIDIA_CARMEL_CNP_ERRATUM
>> - bool "NVIDIA Carmel CNP: CNP on Carmel semantically different than ARM cores"
>> +config ARM64_WORKAROUND_DISABLE_CNP
>> + bool "Disable CNP on affected CPUs"
>> default y
>> help
>> - If CNP is enabled on Carmel cores, non-sharable TLBIs on a core will not
>> - invalidate shared TLB entries installed by a different core, as it would
>> - on standard ARM cores.
>> + This option disables the CNP (Common Not Private) feature on CPUs
>> + that have hardware errata affecting CNP behavior.
>> +
>> + On NVIDIA Carmel cores, CNP behaves differently than on standard ARM
>> + cores: non-shareable TLBIs on a core may not invalidate shared TLB
>> + entries installed by a different core.
>> +
>> + On Hisilicon HIP09 cores, TLB entries may be incorrectly shared
>> + between cores when TTBRx.CNP=1, leading to TLB conflicts and
>> + stale mappings.
>>
>> If unsure, say Y.
>>
> I'm afraid we cannot swap one config with another. Instead, we need to follow
> established pattern for sharing workaround, something like
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 378e50fef247..68eb2993cfd3 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -1315,9 +1315,13 @@ config QCOM_FALKOR_ERRATUM_E1041
>
> If unsure, say Y.
>
> +config ARM64_WORKAROUND_DISABLE_CNP
> + bool
> +
> config NVIDIA_CARMEL_CNP_ERRATUM
> bool "NVIDIA Carmel CNP: CNP on Carmel semantically different than ARM cores"
> default y
> + select ARM64_WORKAROUND_DISABLE_CNP
> help
> If CNP is enabled on Carmel cores, non-sharable TLBIs on a core will not
> invalidate shared TLB entries installed by a different core, as it would
>
>
> and related changes for generalisation of the workaround - that would to be patch 1/2.
>
> Then we can easily wire-up your errata with something like
>
> +config HISILICON_ERRATUM_162100125
> + bool "Hisilicon erratum 162100125"
> + default y
> + select ARM64_WORKAROUND_DISABLE_CNP
> + help
> + On HiSilicon HIP09, TLB entry matching behavior when CNP
> + (TTBRx.CNP=1) is enabled differs from the ARM architecture
> + specification.
> +
> + TLB entries may be incorrectly shared between CPUs, potentially
> + causing TLB conflicts and stale mappings.
> +
> + Disable CNP support for affected HiSilicon HIP09 cores.
> +
> + If unsure, say Y.
>
> and related update in documentation and MIDR list - that would be patch 2/2
>
> Thanks
> Vladimir
I mistakenly over-merged and replaced CONFIG_NVIDIA_CARMEL_CNP_ERRATUM.
Thank you for your review and for providing the detailed suggestions.
Best regards,
Zeng Heng
>
>> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
>> index d0d3cdd5763c..25c61cda901c 100644
>> --- a/arch/arm64/include/asm/cpucaps.h
>> +++ b/arch/arm64/include/asm/cpucaps.h
>> @@ -58,8 +58,8 @@ cpucap_is_possible(const unsigned int cap)
>> return IS_ENABLED(CONFIG_ARM64_ERRATUM_2658417);
>> case ARM64_WORKAROUND_CAVIUM_23154:
>> return IS_ENABLED(CONFIG_CAVIUM_ERRATUM_23154);
>> - case ARM64_WORKAROUND_NVIDIA_CARMEL_CNP:
>> - return IS_ENABLED(CONFIG_NVIDIA_CARMEL_CNP_ERRATUM);
>> + case ARM64_WORKAROUND_DISABLE_CNP:
>> + return IS_ENABLED(CONFIG_ARM64_WORKAROUND_DISABLE_CNP);
>> case ARM64_WORKAROUND_REPEAT_TLBI:
>> return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
>> case ARM64_WORKAROUND_SPECULATIVE_SSBS:
>> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
>> index 5377e4c2eba2..675cd059165c 100644
>> --- a/arch/arm64/kernel/cpu_errata.c
>> +++ b/arch/arm64/kernel/cpu_errata.c
>> @@ -394,6 +394,14 @@ static const struct arm64_cpu_capabilities qcom_erratum_1003_list[] = {
>> };
>> #endif
>>
>> +#ifdef CONFIG_ARM64_WORKAROUND_DISABLE_CNP
>> +static const struct midr_range cnp_erratum_cpus[] = {
>> + MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
>> + MIDR_ALL_VERSIONS(MIDR_HISI_HIP09),
>> + {},
>> +};
>> +#endif
>> +
>> #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
>> static const struct midr_range workaround_clean_cache[] = {
>> #if defined(CONFIG_ARM64_ERRATUM_826319) || \
>> @@ -801,12 +809,11 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>> 1, 0),
>> },
>> #endif
>> -#ifdef CONFIG_NVIDIA_CARMEL_CNP_ERRATUM
>> +#ifdef CONFIG_ARM64_WORKAROUND_DISABLE_CNP
>> {
>> - /* NVIDIA Carmel */
>> - .desc = "NVIDIA Carmel CNP erratum",
>> - .capability = ARM64_WORKAROUND_NVIDIA_CARMEL_CNP,
>> - ERRATA_MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL),
>> + .desc = "NVIDIA Carmel CNP erratum, or Hisilicon erratum 162100125",
>> + .capability = ARM64_WORKAROUND_DISABLE_CNP,
>> + ERRATA_MIDR_RANGE_LIST(cnp_erratum_cpus),
>> },
>> #endif
>> #ifdef CONFIG_ARM64_WORKAROUND_TRBE_OVERWRITE_FILL_MODE
>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>> index 6d53bb15cf7b..20c5f24f74a9 100644
>> --- a/arch/arm64/kernel/cpufeature.c
>> +++ b/arch/arm64/kernel/cpufeature.c
>> @@ -1785,7 +1785,7 @@ has_useable_cnp(const struct arm64_cpu_capabilities *entry, int scope)
>> if (is_kdump_kernel())
>> return false;
>>
>> - if (cpus_have_cap(ARM64_WORKAROUND_NVIDIA_CARMEL_CNP))
>> + if (cpus_have_cap(ARM64_WORKAROUND_DISABLE_CNP))
>> return false;
>>
>> return has_cpuid_feature(entry, scope);
>> diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
>> index 811c2479e82d..9b85a84f6fd4 100644
>> --- a/arch/arm64/tools/cpucaps
>> +++ b/arch/arm64/tools/cpucaps
>> @@ -120,7 +120,7 @@ WORKAROUND_CAVIUM_TX2_219_PRFM
>> WORKAROUND_CAVIUM_TX2_219_TVM
>> WORKAROUND_CLEAN_CACHE
>> WORKAROUND_DEVICE_LOAD_ACQUIRE
>> -WORKAROUND_NVIDIA_CARMEL_CNP
>> +WORKAROUND_DISABLE_CNP
>> WORKAROUND_PMUV3_IMPDEF_TRAPS
>> WORKAROUND_QCOM_FALKOR_E1003
>> WORKAROUND_QCOM_ORYON_CNTVOFF
>> --
>> 2.43.0
>>
^ permalink raw reply
* Re: [PATCH mm-unstable v18 06/14] mm/khugepaged: generalize collapse_huge_page for mTHP collapse
From: David Hildenbrand (Arm) @ 2026-06-01 6:54 UTC (permalink / raw)
To: Lance Yang
Cc: npache, linux-doc, linux-kernel, linux-mm, linux-trace-kernel,
aarcange, akpm, anshuman.khandual, apopple, baohua, baolin.wang,
byungchul, catalin.marinas, cl, corbet, dave.hansen, dev.jain,
gourry, hannes, hughd, jack, jackmanb, jannh, jglisse,
joshua.hahnjy, kas, liam, ljs, mathieu.desnoyers, matthew.brost,
mhiramat, mhocko, peterx, pfalcato, rakie.kim, raquini, rdunlap,
richard.weiyang, rientjes, rostedt, rppt, ryan.roberts, shivankg,
sunnanyong, surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
zokeefe, usama.arif
In-Reply-To: <20260601032804.96122-1-lance.yang@linux.dev>
On 6/1/26 05:28, Lance Yang wrote:
>
> On Sun, May 31, 2026 at 10:00:17PM +0200, David Hildenbrand (Arm) wrote:
>> On 5/31/26 11:39, Lance Yang wrote:
>>>
>>>
>>> Emm ... is it safe to use map_anon_folio_pte_nopf() here?
>>>
>>> At this point pmdp_collapse_flush() has cleared the PMD from the page
>>> tables. The PTE table we are updating is only reachable through the saved
>>> old PMD value, _pmd, until pmd_populate() below.
>>>
>>> map_anon_folio_pte_nopf() does set_ptes() and then calls
>>> update_mmu_cache_range(). Documentation/core-api/cachetlb.rst describes
>>> that hook as:
>>>
>>> "
>>> At the end of every page fault, this routine is invoked to tell
>>> the architecture specific code that translations now exists
>>> in the software page tables for address space "vma->vm_mm"
>>> at virtual address "address" for "nr" consecutive pages.
>>> "
>>>
>>> But that does not seem true here yet, since the PTE table is not
>>> reachable from vma->vm_mm when update_mmu_cache_range() is called.
>>>
>>> Should we avoid calling update_mmu_cache_range() until after the PTE
>>> table is reinstalled with pmd_populate()?
>>
>> I recall that update_mmu_cache* users mostly care about updating folios flags,
>> for the folio derived from the PTE ... or flushing caches for the user address.
>>
>> So intuitively I would say "the architecture code doesn't care that the PMD
>> table will only be visible to HW shortly after". The important thing should be
>> that it will definetly happen, and that nothing else is curently there or can be
>> there?
>
> Ah, fair point.
>
> I was mostly worried about arch hooks that walk vma->vm_mm again, rather
> than only using the pte pointer passed in. For example, mips does:
Right, a re-walk would be the real problem.
>
> update_mmu_cache_range()
> -> __update_tlb()
> -> pgd_offset(vma->vm_mm, address)
> -> pte_offset_map(...)
>
> and __update_tlb() has this assumption:
>
> /*
> * update_mmu_cache() is called between pte_offset_map_lock()
> * and pte_unmap_unlock(), so we can assume that ptep is not
> * NULL here: and what should be done below if it were NULL?
> */
>
> So if khugepaged happens to run with current->active_mm == vma->vm_mm
> here, could __update_tlb() hit the none PMD, get NULL from
> pte_offset_map(), and then dereference it?
Likely yes -- that MIPS code is horrible. And the comment in MIPS code
even spells that out. :(
Do you know about other code like that, or is MIPS the only one doing a
re-walk and crossing fingers?
>
> Just wanted to raise it since some arch code may still have assumptions
> like this, and the always-enable-mTHP work is getting closer ...
Right. I assume set_pte_at() couldn't trigger something similar (re-walk) in arch code,
because we simply provide the ptep. update_mmu_cache_range() only consumes the pte.
>
> Probably very very very hard to hit, though :)
Delaying update_mmu_cache_range() is nasty, as we'd have to make sure that
nobody can interfere in the meantime ... and the PMD lock will not be sufficient.
Maybe we could reinstall the page table with the cleared (none) entries while
still holding the PTL?
Thinking out loud:
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 5ba298d420b7..e39b750b1e6f 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1413,13 +1413,17 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long s
map_anon_folio_pmd_nopf(folio, pmd, vma, pmd_addr);
} else {
/*
- * set_ptes is called in map_anon_folio_pte_nopf with the
- * pmd_ptl lock still held; this is safe as the PMD is expected
- * to be none. The pmd entry is then repopulated below.
+ * Re-insert the page table with the cleared entries, but
+ * hold the PTL, such that no one can mess with the re-installed
+ * page table until we updated the temporarily-cleared entries
+ * through map_anon_folio_pte_nopf().
*/
- map_anon_folio_pte_nopf(folio, pte, vma, start_addr, /*uffd_wp=*/ false);
- smp_wmb(); /* make PTEs visible before PMD. See pmd_install() */
+ if (pte_ptl != pmd_ptl)
+ spin_lock(pte_ptl);
pmd_populate(mm, pmd, pmd_pgtable(_pmd));
+ map_anon_folio_pte_nopf(folio, pte, vma, start_addr, /*uffd_wp=*/ false);
+ if (pte_ptl != pmd_ptl)
+ spin_unlock(pte_ptl);
}
spin_unlock(pmd_ptl);
--
Cheers,
David
^ permalink raw reply related
* Re: [PATCH v4 2/5] tools/lib/mm: add shared file helpers
From: Sarthak Sharma @ 2026-06-01 6:10 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand
Cc: Lorenzo Stoakes, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Shuah Khan, Zi Yan, Baolin Wang,
Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
Jason Gunthorpe, John Hubbard, Peter Xu, Leon Romanovsky,
Jonathan Corbet, Shuah Khan, Mark Brown, linux-mm,
linux-kselftest, linux-doc, linux-kernel
In-Reply-To: <20260527142432.230127-3-sarthak.sharma@arm.com>
On 5/27/26 7:54 PM, Sarthak Sharma wrote:
> Move read_file(), write_file(), read_num(), and write_num() out of
> tools/testing/selftests/mm/vm_util.c into a new shared helper under
> tools/lib/mm/.
>
> These helpers are used by mm selftests today and will also be needed by
> shared hugepage helpers in subsequent patches. Move them to a generic
> location so they can be reused outside selftests as well.
>
> Keep the helpers exposed to mm selftests through vm_util.h by including
> the new shared header there, and link the new helper into the
> selftests/mm build.
>
> Add tools/lib/mm/ to the MEMORY MANAGEMENT - MISC entry in MAINTAINERS.
>
> Signed-off-by: Sarthak Sharma <sarthak.sharma@arm.com>
> ---
Hi Andrew!
Can you please fold the below fixlet into patch 2, as suggested by
Sashiko.
This moves the x86 Makefile prerequisite path fix earlier in the series,
so patch 2 remains buildable on its own. The same hunk is already
present in patch 3 of v4, so if this is folded into patch 2, the
duplicate hunk and the corresponding commit message sentence should be
dropped from patch 3.
If a larger respin is needed after reviewer feedback, I will fold this
into patch 2 in v5 myself.
---
From 1ce0654749f17ae55d7fefefe86bbc55eb3c06d5 Mon Sep 17 00:00:00 2001
From: Sarthak Sharma <sarthak.sharma@arm.com>
Date: Mon, 1 Jun 2026 05:03:53 +0000
Subject: [PATCH v4 fix] selftests/mm: preserve prerequisite paths in x86
build rules
Patch 2 adds tools/lib/mm/file_utils.c as a prerequisite using its full
path. The explicit x86 protection_keys build rules still use $(notdir
$^), which strips that path and makes the compiler look for file_utils.c
in tools/testing/selftests/mm/.
Use $^ instead so pathful prerequisites are preserved.
This fixes the patch 2 bisectability issue reported by Sashiko. The same
hunk is already present in patch 3 of v4. If this is folded into patch
2, that duplicate hunk should be dropped from patch 3.
Signed-off-by: Sarthak Sharma <sarthak.sharma@arm.com>
---
tools/testing/selftests/mm/Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/mm/Makefile
b/tools/testing/selftests/mm/Makefile
index b5fb4b6ab31b..4254200d1cef 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -217,7 +217,7 @@ $(BINARIES_32): CFLAGS += -m32 -mxsave
$(BINARIES_32): LDLIBS += -lrt -ldl -lm
$(BINARIES_32): $(OUTPUT)/%_32: %.c
$(call msg,CC,,$@)
- $(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
+ $(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $^ $(LDLIBS) -o $@
$(foreach t,$(VMTARGETS),$(eval $(call gen-target-rule-32,$(t))))
endif
@@ -226,7 +226,7 @@ $(BINARIES_64): CFLAGS += -m64 -mxsave
$(BINARIES_64): LDLIBS += -lrt -ldl
$(BINARIES_64): $(OUTPUT)/%_64: %.c
$(call msg,CC,,$@)
- $(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(notdir $^) $(LDLIBS) -o $@
+ $(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $^ $(LDLIBS) -o $@
$(foreach t,$(VMTARGETS),$(eval $(call gen-target-rule-64,$(t))))
endif
--
2.39.5
^ permalink raw reply related
* Re: [PATCH net-next 04/11] mptcp: introduce add_addr_v6_port_drop_ts sysctl knob
From: Matthieu Baerts @ 2026-06-01 6:04 UTC (permalink / raw)
To: Eric Dumazet
Cc: Mat Martineau, Geliang Tang, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, netdev, mptcp, linux-kernel,
Jonathan Corbet, Shuah Khan, linux-doc, linux-kselftest
In-Reply-To: <CANn89iL=os-60kDKqMDdyiXuPF5CG=eejS0vmthwpDGXz_Bp8A@mail.gmail.com>
Hi Eric,
On 01/06/2026 15:44, Eric Dumazet wrote:
> On Sun, May 31, 2026 at 10:24 PM Matthieu Baerts (NGI0)
> <matttbe@kernel.org> wrote:
>>
>> This sysctl is going to be used in the next commits to drop TCP
>> timestamps option, to be able to send an ADD_ADDR with a v6 IP address
>> and a port number. It is enabled by default.
>>
>> This knob is explicitly disabled in the MPTCP Join selftest, with the
>> "signal addr list progresses after tx drop" subtest, to continue
>> verifying the previous behaviour where the ADD_ADDR is not sent due to a
>> lack of space.
>>
>> While at it, move syn_retrans_before_tcp_fallback down from struct
>> mptcp_pernet, to avoid creating another 3 bytes hole.
>>
>> Reviewed-by: Mat Martineau <martineau@kernel.org>
>> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
>
> ...
>
>> };
>> @@ -94,6 +95,11 @@ const char *mptcp_get_scheduler(const struct net *net)
>> return mptcp_get_pernet(net)->scheduler;
>> }
>>
>> +unsigned int mptcp_add_addr_v6_port_drop_ts(const struct net *net)
>> +{
>> + return mptcp_get_pernet(net)->add_addr_v6_port_drop_ts;
>> +}
>
> Please use READ_ONCE() over sysctls.
> This will avoid future patches from KCSAN bots.
Good point, I will do that.
I see READ_ONCE() should be used over all other MPTCP sysctls. I can
send fixes to net for those.
Cheers,
Matt
--
Sponsored by the NGI0 Core fund.
^ permalink raw reply
* Re: [PATCH net-next 04/11] mptcp: introduce add_addr_v6_port_drop_ts sysctl knob
From: Eric Dumazet @ 2026-06-01 5:44 UTC (permalink / raw)
To: Matthieu Baerts (NGI0)
Cc: Mat Martineau, Geliang Tang, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, netdev, mptcp, linux-kernel,
Jonathan Corbet, Shuah Khan, linux-doc, linux-kselftest
In-Reply-To: <20260601-net-next-mptcp-add-addr6-port-ts-v1-4-4fc25dfef62e@kernel.org>
On Sun, May 31, 2026 at 10:24 PM Matthieu Baerts (NGI0)
<matttbe@kernel.org> wrote:
>
> This sysctl is going to be used in the next commits to drop TCP
> timestamps option, to be able to send an ADD_ADDR with a v6 IP address
> and a port number. It is enabled by default.
>
> This knob is explicitly disabled in the MPTCP Join selftest, with the
> "signal addr list progresses after tx drop" subtest, to continue
> verifying the previous behaviour where the ADD_ADDR is not sent due to a
> lack of space.
>
> While at it, move syn_retrans_before_tcp_fallback down from struct
> mptcp_pernet, to avoid creating another 3 bytes hole.
>
> Reviewed-by: Mat Martineau <martineau@kernel.org>
> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
...
> };
> @@ -94,6 +95,11 @@ const char *mptcp_get_scheduler(const struct net *net)
> return mptcp_get_pernet(net)->scheduler;
> }
>
> +unsigned int mptcp_add_addr_v6_port_drop_ts(const struct net *net)
> +{
> + return mptcp_get_pernet(net)->add_addr_v6_port_drop_ts;
> +}
Please use READ_ONCE() over sysctls.
This will avoid future patches from KCSAN bots.
^ permalink raw reply
* [PATCH net-next 04/11] mptcp: introduce add_addr_v6_port_drop_ts sysctl knob
From: Matthieu Baerts (NGI0) @ 2026-06-01 5:22 UTC (permalink / raw)
To: Mat Martineau, Geliang Tang, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman
Cc: netdev, mptcp, linux-kernel, Matthieu Baerts (NGI0),
Jonathan Corbet, Shuah Khan, linux-doc, linux-kselftest
In-Reply-To: <20260601-net-next-mptcp-add-addr6-port-ts-v1-0-4fc25dfef62e@kernel.org>
This sysctl is going to be used in the next commits to drop TCP
timestamps option, to be able to send an ADD_ADDR with a v6 IP address
and a port number. It is enabled by default.
This knob is explicitly disabled in the MPTCP Join selftest, with the
"signal addr list progresses after tx drop" subtest, to continue
verifying the previous behaviour where the ADD_ADDR is not sent due to a
lack of space.
While at it, move syn_retrans_before_tcp_fallback down from struct
mptcp_pernet, to avoid creating another 3 bytes hole.
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
To: Jonathan Corbet <corbet@lwn.net>
To: Shuah Khan <skhan@linuxfoundation.org>
Cc: linux-doc@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org
---
Documentation/networking/mptcp-sysctl.rst | 13 +++++++++++++
net/mptcp/ctrl.c | 18 +++++++++++++++++-
net/mptcp/protocol.h | 1 +
tools/testing/selftests/net/mptcp/mptcp_join.sh | 1 +
4 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/Documentation/networking/mptcp-sysctl.rst b/Documentation/networking/mptcp-sysctl.rst
index 1eb6af26b4a7..b9b5f58e0625 100644
--- a/Documentation/networking/mptcp-sysctl.rst
+++ b/Documentation/networking/mptcp-sysctl.rst
@@ -21,6 +21,19 @@ add_addr_timeout - INTEGER (seconds)
Default: 120
+add_addr_v6_port_drop_ts - BOOLEAN
+ Control whether preparing an ADD_ADDR with an IPv6 address and a port
+ should drop the TCP timestamps option to have enough option space to
+ send the signal.
+
+ If there is not enough option space, and the TCP timestamps option
+ cannot be dropped, the signal cannot be sent. Note that dropping the TCP
+ timestamps option for one packet of the connection could disrupt some
+ middleboxes: even if it should be unlikely, they could drop the packet
+ or block the connection. This is a per-namespace sysctl.
+
+ Default: 1 (enabled)
+
allow_join_initial_addr_port - BOOLEAN
Allow peers to send join requests to the IP address and port number used
by the initial subflow if the value is 1. This controls a flag that is
diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
index d96130e49942..c94a192f4118 100644
--- a/net/mptcp/ctrl.c
+++ b/net/mptcp/ctrl.c
@@ -32,12 +32,13 @@ struct mptcp_pernet {
unsigned int close_timeout;
unsigned int stale_loss_cnt;
atomic_t active_disable_times;
- u8 syn_retrans_before_tcp_fallback;
unsigned long active_disable_stamp;
+ u8 syn_retrans_before_tcp_fallback;
u8 mptcp_enabled;
u8 checksum_enabled;
u8 allow_join_initial_addr_port;
u8 pm_type;
+ u8 add_addr_v6_port_drop_ts;
char scheduler[MPTCP_SCHED_NAME_MAX];
char path_manager[MPTCP_PM_NAME_MAX];
};
@@ -94,6 +95,11 @@ const char *mptcp_get_scheduler(const struct net *net)
return mptcp_get_pernet(net)->scheduler;
}
+unsigned int mptcp_add_addr_v6_port_drop_ts(const struct net *net)
+{
+ return mptcp_get_pernet(net)->add_addr_v6_port_drop_ts;
+}
+
static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
{
pernet->mptcp_enabled = 1;
@@ -108,6 +114,7 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
pernet->pm_type = MPTCP_PM_TYPE_KERNEL;
strscpy(pernet->scheduler, "default", sizeof(pernet->scheduler));
strscpy(pernet->path_manager, "kernel", sizeof(pernet->path_manager));
+ pernet->add_addr_v6_port_drop_ts = 1;
}
#ifdef CONFIG_SYSCTL
@@ -362,6 +369,14 @@ static struct ctl_table mptcp_sysctl_table[] = {
.mode = 0444,
.proc_handler = proc_available_path_managers,
},
+ {
+ .procname = "add_addr_v6_port_drop_ts",
+ .maxlen = sizeof(u8),
+ .mode = 0644,
+ .proc_handler = proc_dou8vec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE
+ },
};
static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
@@ -389,6 +404,7 @@ static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
table[10].data = &pernet->syn_retrans_before_tcp_fallback;
table[11].data = &pernet->path_manager;
/* table[12] is for available_path_managers which is read-only info */
+ table[13].data = &pernet->add_addr_v6_port_drop_ts;
hdr = register_net_sysctl_sz(net, MPTCP_SYSCTL_PATH, table,
ARRAY_SIZE(mptcp_sysctl_table));
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index e0ffebaa6795..f4276980d78a 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -798,6 +798,7 @@ unsigned int mptcp_close_timeout(const struct sock *sk);
int mptcp_get_pm_type(const struct net *net);
const char *mptcp_get_path_manager(const struct net *net);
const char *mptcp_get_scheduler(const struct net *net);
+unsigned int mptcp_add_addr_v6_port_drop_ts(const struct net *net);
void mptcp_active_disable(struct sock *sk);
bool mptcp_active_should_disable(struct sock *ssk);
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 5d4d0f127f79..23b17957686a 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -3313,6 +3313,7 @@ add_addr_ports_tests()
if reset "signal addr list progresses after tx drop"; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 1 0
+ ip netns exec $ns1 sysctl -q net.mptcp.add_addr_v6_port_drop_ts=0 2>/dev/null || true
ip netns exec $ns1 sysctl -q net.ipv4.tcp_timestamps=1
ip netns exec $ns2 sysctl -q net.ipv4.tcp_timestamps=1
--
2.53.0
^ permalink raw reply related
* [PATCH net-next 00/11] mptcp: pm: drop TCP TS with ADD_ADDRv6 + port
From: Matthieu Baerts (NGI0) @ 2026-06-01 5:22 UTC (permalink / raw)
To: Mat Martineau, Geliang Tang, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman
Cc: netdev, mptcp, linux-kernel, Matthieu Baerts (NGI0),
Jonathan Corbet, Shuah Khan, linux-doc, linux-kselftest,
Neal Cardwell, Kuniyuki Iwashima, Shuah Khan
Up to this series, it was possible to add a "signal" MPTCP endpoint with
an IPv6 address and a port, or to directly request to send an ADD_ADDR
with a v6 address and a port, but the expected ADD_ADDR wasn't sent when
TCP timestamps was used for the connection.
In fact, such signalling option cannot be sent when TCP timestamps is
used due to a lack of option space: the limit is at 40 bytes, and, with
padding, TCP timestamps is taking 12 bytes, while an ADD_ADDR IPv6 +
port is taking 30 bytes. The selected solution here is to simply drop
the TCP timestamps option when such ADD_ADDR of 30 bytes needs to be
sent.
- Patches 1-3: small cleanups to avoid computing ADD/RM_ADDR twice.
- Patches 4-7: the new feature, controlled by a new sysctl knob.
- Patch 8: extra checks in the MPTCP Join selftests.
- Patches 9-11: small pcap-related improvements in the selftests.
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
Matthieu Baerts (NGI0) (11):
mptcp: options: suboptions sizes can be negative
mptcp: pm: avoid computing rm_addr size twice
mptcp: pm: avoid computing add_addr size twice
mptcp: introduce add_addr_v6_port_drop_ts sysctl knob
tcp: allow mptcp to drop TS for some packets
mptcp: pm: drop TCP TS with ADD_ADDRv6 + port
selftests: mptcp: validate ADD_ADDRv6 + TS + port
selftests: mptcp: always check sent/dropped ADD_ADDRs
selftests: mptcp: connect: test name in pcap file
selftests: mptcp: simult_flow: test name in pcap file
selftests: mptcp: pcap: drop most of the payload
Documentation/networking/mptcp-sysctl.rst | 13 ++++
include/net/mptcp.h | 3 +-
net/ipv4/tcp_output.c | 6 +-
net/mptcp/ctrl.c | 18 ++++-
net/mptcp/options.c | 64 ++++++----------
net/mptcp/pm.c | 49 +++++++++++--
net/mptcp/protocol.h | 30 +-------
tools/testing/selftests/net/mptcp/mptcp_connect.sh | 8 +-
tools/testing/selftests/net/mptcp/mptcp_join.sh | 85 ++++++++++------------
tools/testing/selftests/net/mptcp/simult_flows.sh | 11 ++-
10 files changed, 159 insertions(+), 128 deletions(-)
---
base-commit: 8415598365503ced2e3d019491b0a2756c85c494
change-id: 20260601-net-next-mptcp-add-addr6-port-ts-40d8d74d8e20
Best regards,
--
Matthieu Baerts (NGI0) <matttbe@kernel.org>
^ permalink raw reply
* Re: [PATCH v3] docs/zh_CN: usb: refine translated wording and formatting
From: Alex Shi @ 2026-06-01 4:00 UTC (permalink / raw)
To: Kefan Bai, linux-usb, si.yanteng, gregkh
Cc: dzm91, corbet, skhan, linux-doc, linux-kernel, doubled, alexs
In-Reply-To: <20260601033945.555210-1-baikefan@leap-io-kernel.com>
Hi Kefan,
It looks fine.
BTW, like any other kernel patches, document patch also requires a line
length limit of either 80 or 100 English characters per line (which
corresponds to 40 or 50 Chinese characters). Within the same document,
you should keep it consistent by using either the 80-character or the
100-character limit throughout.
You should try your best to align your patch accordingly, as this makes
it look much cleaner and more readable. To make this easier, you can use
a text editor with a column indicator (ruler) to help you align the
text, or you can use the command :set cc=80 in Vim to check your formatting.
Thanks
Alex
On 2026/6/1 11:39, Kefan Bai wrote:
> Refine the zh_CN USB translations for clarity and consistency.
>
> Improve wording, wrapping, and formatting across the translated
> USB documents.
>
> Link:https://lore.kernel.org/r/2026053149-flaky-shallow-2460@gregkh
> Suggested-by: Alex Shi<seakeel@gmail.com>
> Signed-off-by: Kefan Bai<baikefan@leap-io-kernel.com>
> ---
> v3:
> - refine the subject and commit message
> - add a Link trailer to the cleanup request thread
> - move revision notes below the cut line
>
> v2:
> - replace the obsolete FSF mailing address reference in acm.rst
> - trim the commit message to satisfy checkpatch
>
> Documentation/translations/zh_CN/usb/CREDITS | 146 ++++---
> Documentation/translations/zh_CN/usb/acm.rst | 62 ++-
> .../translations/zh_CN/usb/authorization.rst | 79 ++--
> .../translations/zh_CN/usb/chipidea.rst | 58 ++-
> Documentation/translations/zh_CN/usb/dwc3.rst | 37 +-
> Documentation/translations/zh_CN/usb/ehci.rst | 247 +++++-------
> .../translations/zh_CN/usb/index.rst | 18 +-
> .../translations/zh_CN/usb/usbmon.rst | 363 ++++++++----------
> 8 files changed, 442 insertions(+), 568 deletions(-)
>
> diff --git a/Documentation/translations/zh_CN/usb/CREDITS b/Documentation/translations/zh_CN/usb/CREDITS
> index c133b1a5daff..a37958d139cc 100644
> --- a/Documentation/translations/zh_CN/usb/CREDITS
> +++ b/Documentation/translations/zh_CN/usb/CREDITS
> @@ -10,12 +10,10 @@
> :校译:
>
>
> -简易 Linux USB 驱动的致谢名单:
> +Simple Linux USB 驱动项目致谢名单:
>
> -以下人员都为 Linux USB 驱动代码作出了贡献
> -(按姓氏字母顺序排列)。我相信这份名单本应
> -更长一些,但确实不容易维护。
> -如需将自己加入名单,请提交补丁。
> +以下人员都为 Linux USB 驱动代码作出过贡献(按姓氏字母顺序排列)。这份名
> +单本该更长,只是确实不易维护;如果你也应列名其中,欢迎提交补丁把自己加上。
>
> Georg Acher<acher@informatik.tu-muenchen.de>
> David Brownell<dbrownell@users.sourceforge.net>
> @@ -41,123 +39,123 @@
> 特别感谢:
>
> Inaky Perez Gonzalez<inaky@peloncho.fis.ucm.es>
> - 感谢他发起了 Linux USB 驱动开发工作,并编写了体量较大的 uusbd
> - 驱动中的大部分代码。我们从那项工作中学到了很多。
> + 感谢他牵头开发 Linux USB 驱动,并编写了 uusbd 驱动的大部分代码,我们
> + 从中学到了很多。
>
> NetBSD 和 FreeBSD 的 USB 开发者们
> 感谢他们加入 Linux USB 邮件列表,提供建议并分享实现经验。
>
> -附加感谢:
> - 还要感谢以下公司与个人在硬件、支持、时间投入和开发方面提供的捐赠与帮助
> - (摘自 Inaky 驱动原始的 THANKS 文件):
> +另外还要感谢:
>
> - 以下公司曾帮助我们开发 Linux USB / UUSBD:
> + 以下公司和个人在硬件、支持、时间和开发工作上给予了帮助(摘自 Inaky
> + 驱动原始的 THANKS 文件):
>
> - - 3Com GmbH 捐赠了一台 ISDN Pro TA,并在技术问题和测试设备方面为我
> - 提供支持。没想到能得到这么大的帮助。
> + 以下公司曾为 Linux USB / UUSBD 的开发提供帮助:
>
> - - USAR Systems 向我们提供了他们出色的 USB 评估套件,
> - 使我们能够测试 Linux USB 驱动对最新 USB 规范的符合性。
> - USAR Systems 认识到保持开放操作系统与时俱进的重要性,
> - 并以硬件支持这个项目。感谢!
> + - 3Com GmbH 捐赠了一台 ISDN Pro TA,并在技术问题和测试设备方面提供
> + 了大力支持。
> +
> + - USAR Systems 向我们提供了出色的 USB 评估套件,使我们得以测试
> + Linux USB 驱动对最新 USB 规范的符合性。USAR Systems 也认识到,
> + 让开放操作系统跟上时代很重要,因此以硬件支持了这个项目,在此
> + 致谢。
>
> - 感谢英特尔提供的宝贵帮助。
>
> - 我们与 Cherry 合作,使 Linux 成为首个内置 USB 支持的操作系统。
> Cherry 是全球最大的键盘制造商之一。
>
> - - CMD Technology, Inc. 慷慨捐赠了一块 CSA-6700 PCI-to-USB
> - 控制卡,用于测试 OHCI 实现。
> + - CMD Technology, Inc. 慷慨捐赠了一块 CSA-6700 PCI 转 USB 控制卡,
> + 用于测试 OHCI 实现。
>
> - - 由于他们对我们的支持,Keytronic 可以放心,
> - 他们的键盘能卖给至少 300 万 Linux 用户中的一部分。
> + - 有了他们的支持,Keytronic 至少可以确信,其键盘能够销售给 300 万
> + Linux 用户中的一部分。
>
> - - ing büro h doran [http://www.ibhdoran.com]!
> - 在欧洲,想给主板买一个 PC 背板 USB 连接器几乎是不可能的
> - (我自己做的那个相当糟糕 :))。现在我知道该去哪里买漂亮的 USB
> - 配件了!
> + - 特别感谢 ing büro h doran [http://www.ibhdoran.com]。
> + 在欧洲,想给主板配一个 PC 背板 USB 连接器几乎是不可能的(我自己
> + 做的那个效果并不好)。现在我知道该去哪里购买合适的 USB 配件了。
>
> - Genius Germany 捐赠了一只 USB 鼠标,用于测试鼠标启动协议;
> - 他们还捐赠了 F-23 数字摇杆和 NetMouse Pro。感谢!
> + 他们还捐赠了 F-23 数字摇杆和 NetMouse Pro,在此致谢。
>
> - - AVM GmbH Berlin 支持我们开发 Linux 下的 AVM ISDN Controller B1 USB 驱动。
> - AVM 是领先的 ISDN 控制器制造商,其主动式设计对包括 Linux 在内的
> - 所有操作系统平台开放。
> + - AVM GmbH Berlin 支持我们开发 Linux 下的 AVM ISDN Controller B1 USB
> + 驱动。AVM 是领先的 ISDN 控制器制造商,其开放式设计适用于包括
> + Linux 在内的所有操作系统平台。
>
> - - 非常感谢 Y-E Data, Inc 捐赠的 FlashBuster-U USB 软驱,
> - 使我们能够测试批量传输代码。
> + - 非常感谢 Y-E Data, Inc 捐赠的 FlashBuster-U USB 软驱,使我们能够测试
> + 批量传输代码。
>
> - 感谢 Logitech 捐赠了一只三轴 USB 鼠标。
>
> - Logitech 负责设计、制造并销售各种人机接口设备,
> - 在键盘、鼠标、轨迹球、摄像头、扬声器,以及面向游戏和专业用途的
> - 控制设备方面拥有悠久历史和丰富经验。
> + Logitech 负责设计、制造并销售各种人机接口设备,在键盘、鼠标、轨迹球、
> + 摄像头、扬声器,以及面向游戏和专业用途的控制设备方面拥有悠久历史和
> + 丰富经验。
>
> - 作为这些设备广为人知的供应商和销售商,他们捐赠了 USB 鼠标、
> - 摇杆和扫描仪,以表明 Linux 的重要性,也让 Logitech 的客户
> - 能在自己喜欢的操作系统上获得支持,并让所有 Linux 用户都能使用
> - Logitech 以及其他 USB 硬件。
> + 作为这些设备广为人知的供应商和销售商,他们捐赠了 USB 鼠标、摇杆和
> + 扫描仪,以表明 Linux 的重要性,也让 Logitech 的客户能在自己偏爱的
> + 操作系统上获得支持,并让所有 Linux 用户都能使用 Logitech 及其他
> + USB 硬件。
>
> Logitech 也是 1999 年 2 月 11 日维也纳 Linux 大会的官方赞助商,
> 我们将在会上展示 Linux USB 工作的最新进展。
>
> - - 感谢 CATC 提供 USB Inspector,帮助我们揭开 UHCI 内部实现中
> - 那些不为人知的角落。
> + - 感谢 CATC 提供 USB Inspector,帮助我们看到 UHCI 内部实现中的那些
> + 隐秘角落。
>
> - 感谢 Entrega 为开发工作提供 PCI 转 USB 卡、集线器和转换器产品。
>
> - - 感谢 ConnectTech 提供 WhiteHEAT USB 转串口转换器以及相关文档,
> - 让这个驱动得以写成。
> + - 感谢 ConnectTech 提供 WhiteHEAT USB 转串口转换器以及相关文档,让
> + 这个驱动得以写成。
>
> - - 感谢 ADMtek 提供 Pegasus 和 Pegasus II 评估板、规格说明,
> - 以及驱动开发过程中的宝贵建议。
> + - 感谢 ADMtek 提供 Pegasus 和 Pegasus II 评估板、规格说明,以及驱动
> + 开发过程中的宝贵建议。
>
> - 另外还要感谢以下个人(嘿,顺序不分先后 :))
> + 另外还要感谢以下个人(排名不分先后):
>
> - - Oren Tirosh<orenti@hishome.net>,
> - 他非常耐心地听我唠叨各种 USB 疑问,还给了很多很酷的想法。
> + - Oren Tirosh<orenti@hishome.net>
> + 他非常耐心地解答我反复提出的各种 USB 问题,并提供了许多有价值的
> + 想法。
>
> - - Jochen Karrer<karrer@wpfd25.physik.uni-wuerzburg.de>,
> - 指出了致命 bug,并给出了宝贵建议。
> + - Jochen Karrer<karrer@wpfd25.physik.uni-wuerzburg.de>
> + 指出了严重问题,并给出了宝贵建议。
>
> - - Edmund Humemberger<ed@atnet.at>,他在公共关系与项目管理方面
> - 为 Linux-USB 项目付出了巨大的努力。
> + - Edmund Humemberger<ed@atnet.at>,他在公共关系与项目管理方面为
> + Linux-USB 项目付出了巨大的努力。
>
> - - Alberto Menegazzi<flash@flash.iol.it> 正在着手编写 UUSBD 文档,加油!
> + - Alberto Menegazzi<flash@flash.iol.it> 正在着手编写 UUSBD 文档。
>
> - - Ric Klaren<ia_ric@cs.utwente.nl> 编写了很好的入门文档,
> - 与 Alberto 的作品形成良性竞争:)。
> + - Ric Klaren<ia_ric@cs.utwente.nl> 编写了很好的入门文档,与
> + Alberto 的作品形成了良性互补。
>
> - - Christian Groessler<cpg@aladdin.de>,感谢他在那些棘手细节上的帮助。
> + - Christian Groessler<cpg@aladdin.de>,感谢他在诸多复杂细节上的帮助。
>
> - - Paul MacKerras 改进了 OHCI 实现,推动了对 iMac 的支持,
> - 并提供了大量的改进意见。
> + - Paul MacKerras 改进了 OHCI 实现,推动了对 iMac 的支持,并提供了
> + 大量的改进意见。
>
> - - Fernando Herrera<fherrera@eurielec.etsit.upm.es>
> - 负责撰写、维护并不断补充那份期待已久、独一无二又精彩的
> - UUSBD FAQ!太棒了!
> + - Fernando Herrera<fherrera@eurielec.etsit.upm.es> 负责撰写、维护并
> + 持续补充那份期待已久、内容翔实的 UUSBD FAQ。
>
> - - Rasca Gmelch<thron@gmx.de> 重新启用了 raw 驱动,
> - 指出了一些错误,并启动了 uusbd-utils 软件包。
> + - Rasca Gmelch<thron@gmx.de> 重新启用了 raw 驱动,指出了一些错误,并
> + 启动了 uusbd-utils 软件包。
>
> - - Peter Dettori<dettori@ozy.dec.com>,像疯了一样挖掘 bug,
> - 还提出了很多很酷的建议,太棒了!
> + - Peter Dettori<dettori@ozy.dec.com>,持续发现问题,并提出了许多
> + 有价值的建议。
>
> - - 自由软件与 Linux 社区的所有成员,包括 FSF、GNU 项目、
> - MIT X 联盟、TeX 社区等等,谢谢你们!
> + - 自由软件与 Linux 社区的所有成员,包括 FSF、GNU 项目、MIT X 联盟、
> + TeX 社区等,在此一并致谢。
>
> - - 特别感谢 Richard Stallman 创造了 Emacs!
> + - 特别感谢 Richard Stallman 创造了 Emacs。
>
> - - 感谢 linux-usb 邮件列表的所有成员,读了那么多邮件——不开玩笑了,
> - 感谢你们提出的所有建议!
> + - 感谢 linux-usb 邮件列表的所有成员阅读了大量邮件,并提出了诸多
> + 建议。
>
> - 感谢 USB Implementers Forum 成员们的帮助与支持。
>
> - - Nathan Myers<ncm@cantrip.org>,感谢他的建议!
> - (希望你喜欢 Cibeles 的派对。)
> + - Nathan Myers<ncm@cantrip.org>,感谢他的建议。(也希望你喜欢
> + Cibeles 的派对。)
>
> - - 感谢 Linus Torvalds 创建、开发并管理 Linux。
> + - 感谢 Linus Torvalds 创立、开发并维护 Linux。
>
> - Mike Smith、Craig Keithley、Thierry Giron 和 Janet Schank
> - 感谢他们让我认识到标准 USB 集线器其实也没那么“标准”,
> - 这有助于我们在标准集线器驱动中加入厂商特定的特殊处理。
> + 感谢他们让我认识到,标准 USB 集线器其实一点也不“标准”;也正因
> + 如此,我们才能在标准集线器驱动中加入厂商特定的处理。
> diff --git a/Documentation/translations/zh_CN/usb/acm.rst b/Documentation/translations/zh_CN/usb/acm.rst
> index 51d6eb8f5660..b2e35787af45 100644
> --- a/Documentation/translations/zh_CN/usb/acm.rst
> +++ b/Documentation/translations/zh_CN/usb/acm.rst
> @@ -20,33 +20,26 @@ Linux ACM 驱动 v0.16
>
> 0. 免责声明
> ~~~~~~~~~~~
> -本程序是自由软件;你可以在自由软件基金会发布的
> -GNU 通用公共许可证第 2 版,或者(按你的选择)
> -任何后续版本的条款下重新发布和/或修改它。
> +本程序是自由软件;你可以在自由软件基金会发布的 GNU 通用公共许可证第 2 版,
> +或者(按你的选择)任何后续版本的条款下重新发布和/或修改它。
>
> -发布本程序是希望它能发挥作用,但它不附带任何担保;
> -甚至不包括对适销性或特定用途适用性的默示担保。
> -详情见 GNU 通用公共许可证。
> +发布本程序是希望它能发挥作用,但它不附带任何担保;甚至不包括对适销性或
> +特定用途适用性的默示担保。详情见 GNU 通用公共许可证。
>
> -你应该已经随本程序收到了 GNU 通用公共许可证的副本;
> -如果没有,请致信:Free Software Foundation, Inc., 59
> -Temple Place, Suite 330, Boston, MA 02111-1307 USA。
> +你应该已经随本程序收到了 GNU 通用公共许可证的副本;如果没有,请参见
> +COPYING 文件。
>
> -如需联系作者,可发送电子邮件至vojtech@suse.cz,
> -或邮寄至:
> -Vojtech Pavlik, Ucitelska 1576, Prague 8,
> -182 00, Czech Republic。
> +如需联系作者,可发送电子邮件至vojtech@suse.cz,或邮寄至:
> +Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00, Czech Republic。
>
> -为方便起见,软件包中已附带 GNU 通用公共许可证
> -第 2 版:见 COPYING 文件。
> +为方便起见,软件包中已附带 GNU 通用公共许可证第 2 版:见 COPYING 文件。
>
> 1. 使用方法
> ~~~~~~~~~~~
> -``drivers/usb/class/cdc-acm.c`` 驱动可用于符合 USB
> -通信设备类抽象控制模型(USB CDC ACM)规范的
> -USB 调制解调器和 USB ISDN 终端适配器。
> +``drivers/usb/class/cdc-acm.c`` 驱动适用于符合 USB 通信设备类抽象控制模型
> +(USB CDC ACM)规范的 USB 调制解调器和 USB ISDN 终端适配器。
>
> -许多调制解调器支持此驱动,以下是我所知道的一些型号:
> +已知支持该驱动的调制解调器包括:
>
> - 3Com OfficeConnect 56k
> - 3Com Voice FaxModem Pro
> @@ -56,17 +49,16 @@ USB 调制解调器和 USB ISDN 终端适配器。
> - Compaq 56k FaxModem
> - ELSA Microlink 56k
>
> -我知道有一款 ISDN 终端适配器可以与 ACM 驱动一起使用:
> +已知有一款 ISDN 终端适配器可以配合 ACM 驱动使用:
>
> - 3Com USR ISDN Pro TA
>
> -一些手机也可以通过 USB 连接。
> -我知道以下机型可以正常工作:
> +一些手机也可以通过 USB 连接,已知可用的机型有:
>
> - SonyEricsson K800i
>
> -遗憾的是,许多调制解调器和大多数 ISDN TA
> -都使用专有接口,因此无法与此驱动配合工作。
> +遗憾的是,很多调制解调器和大多数 ISDN TA 都使用专有接口,因此无法配合该
> +驱动工作。
> 购买前请先确认设备是否符合 ACM 规范。
>
> 要使用这些调制解调器,需要加载以下模块::
> @@ -75,15 +67,13 @@ USB 调制解调器和 USB ISDN 终端适配器。
> uhci-hcd.ko ohci-hcd.ko or ehci-hcd.ko
> cdc-acm.ko
>
> -之后就应该可以访问这些调制解调器了。
> -应当可以使用 ``minicom``、``ppp`` 和 ``mgetty``
> -与它们通信。
> +之后就应该能访问这些调制解调器,并用 ``minicom``、``ppp`` 和
> +``mgetty`` 与它们通信。
>
> 2. 验证驱动是否正常工作
> ~~~~~~~~~~~~~~~~~~~~~~~
>
> -第一步是检查 ``/sys/kernel/debug/usb/devices``,
> -其内容应该类似如下::
> +第一步是查看 ``/sys/kernel/debug/usb/devices``,其内容应当类似下面这样::
>
> T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
> B: Alloc= 0/900 us ( 0%), #Int= 0, #Iso= 0
> @@ -112,11 +102,10 @@ USB 调制解调器和 USB ISDN 终端适配器。
> E: Ad=85(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
> E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
>
> -这三行的存在很关键(以及 ``Cls=`` 字段里出现的
> -``comm`` 和 ``data`` 类);它说明这是一个 ACM
> -设备。``Driver=acm`` 表示该设备正在使用 acm 驱动。
> -如果只看到 ``Cls=ff(vend.)``,那就无能为力了:
> -这说明你手上的设备使用的是厂商专有接口::
> +关键是看这三行,再结合 ``Cls=`` 字段里出现的 ``comm`` 和 ``data`` 类,就
> +能判断这是一台 ACM 设备。``Driver=acm`` 表示该设备正在使用 acm 驱动。如果
> +只看到 ``Cls=ff(vend.)``,那就说明这台设备使用的是厂商专有接口,ACM 驱动
> +无法处理::
>
> D: Ver= 1.00 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs= 2
> I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=acm
> @@ -142,6 +131,5 @@ USB 调制解调器和 USB ISDN 终端适配器。
> usb.c: acm driver claimed interface c7b5f3f8
> usb.c: acm driver claimed interface c7691fa0
>
> -如果以上都正常,请启动 ``minicom``,
> -把它配置为连接 ``ttyACM`` 设备,然后
> -尝试输入 ``at``。如果返回 ``OK``,说明一切工作正常。
> +如果这些都正常,请启动 ``minicom``,把它配置为连接到 ``ttyACM`` 设备,然后
> +尝试输入 ``at``。如果返回 ``OK``,说明驱动工作正常。
> diff --git a/Documentation/translations/zh_CN/usb/authorization.rst b/Documentation/translations/zh_CN/usb/authorization.rst
> index 2aa311f6b967..e2ff2282bd03 100644
> --- a/Documentation/translations/zh_CN/usb/authorization.rst
> +++ b/Documentation/translations/zh_CN/usb/authorization.rst
> @@ -10,34 +10,32 @@
> :校译:
>
>
> -=============================
> -授权或禁止 USB 设备连接到系统
> -=============================
> +===========================
> +允许或禁止 USB 设备接入系统
> +===========================
>
> 版权 (C) 2007 Inaky Perez-Gonzalez
> <inaky@linux.intel.com> 英特尔公司
>
> -此功能允许你控制 USB 设备是否可以在系统中使用。
> -借助它,你可以完全通过用户空间实现对 USB 设备的锁定。
> +有了这项功能,你就可以控制 USB 设备是否允许在系统中使用,并把 USB 设备锁
> +定机制完全放在用户空间实现。
>
> -目前,当插入一个 USB 设备时,系统会对其进行配置,
> -其接口会立即向用户开放。
> -有了这项改动,只有在 root 授权设备完成配置后,
> -设备才可被使用。
> +目前,USB 设备一接入系统就会被立即配置,其接口也会立刻向用户开放。引入
> +这项机制后,只有在 root 明确授权后,设备才会完成配置并允许使用。
>
>
> 用法
> ====
>
> -授权设备接入::
> +授权设备接入系统::
>
> $ echo 1 > /sys/bus/usb/devices/DEVICE/authorized
>
> -取消对设备的授权::
> +取消设备授权::
>
> $ echo 0 > /sys/bus/usb/devices/DEVICE/authorized
>
> -将新连接到 ``hostX`` 的设备默认设为未授权(即锁定)::
> +将连接到 ``hostX`` 的新设备默认设为未授权(即锁定)::
>
> $ echo 0 > /sys/bus/usb/devices/usbX/authorized_default
>
> @@ -45,15 +43,14 @@
>
> $ echo 1 > /sys/bus/usb/devices/usbX/authorized_default
>
> -默认情况下,所有 USB 设备都是授权的。
> -向 ``authorized_default`` 属性写入 ``2`` 会使内核
> -默认只授权连接到内部 USB 端口的设备。
> +默认情况下,所有 USB 设备都是授权的。向 ``authorized_default`` 属性写入
> +``2`` 会使内核默认只授权连接到内部 USB 端口的设备。
>
> -系统锁定示例(比较粗糙)
> -------------------------
> +系统锁定示例(简化版)
> +----------------------
>
> -假设你想实现一个锁定功能,只允许类型为 XYZ 的设备接入
> -(例如某台带有外露 USB 端口的自助服务终端)::
> +假设你想做一个锁定机制,只允许 XYZ 类型的设备接入(例如一台带有外露 USB
> +端口的自助终端)::
>
> 启动系统
> rc.local ->
> @@ -63,21 +60,18 @@
> echo 0 > $host/authorized_default
> done
>
> -给 udev 挂一个脚本,用于处理新插入的 USB 设备::
> +为 udev 配置一个脚本,用于处理新插入的 USB 设备::
>
> if device_is_my_type $DEV
> then
> echo 1 > $device_path/authorized
> - done
> + fi
>
>
> -``device_is_my_type()`` 才是锁定方案真正见功夫的
> -地方。仅仅检查 class、type 和 protocol 是否匹配
> -某个值,是你能做出的最糟糕的安全验证之一;
> -对想绕过它的人来说,这反而是最容易利用的方案。
> -如果你需要真正安全的办法,那就该使用加密、
> -证书认证之类的机制。把 USB 存储设备当作
> -“钥匙”的一个简单例子可以是::
> +锁定方案是否可靠,关键全在 ``device_is_my_type()`` 的实现。仅仅检查
> +class、type 和 protocol 是否匹配,几乎是最差的一种安全校验方式;对想绕过
> +它的人来说,这种做法反而最容易伪造。如果你真要做安全控制,就该使用加密、
> +证书认证之类的机制。把 USB 存储设备当作“钥匙”的一个简单示例可以写成::
>
> function device_is_my_type()
> {
> @@ -87,7 +81,7 @@
> sum=$(md5sum/mntpoint/.signature)
> if [ $sum = $(cat /etc/lockdown/keysum) ]
> then
> - echo "We are good, connected"
> + echo "验证通过,已连接"
> umount /mntpoint
> # 再做一些额外处理,让其他人也能使用它
> else
> @@ -96,17 +90,16 @@
> }
>
>
> -当然,这个例子很粗糙;真正要做的话,
> -你会想用基于 PKI 的证书校验,这样就不必依赖
> -共享密钥之类的东西。不过你应该已经明白意思了。
> -任何拿到设备仿真工具包的人都能伪造描述符和设备信息。
> -别信这个。
> +当然,这个例子仍然比较简化。真正落地时,更合适的做法是使用基于 PKI 的证
> +书校验,这样就不必依赖共享密钥之类的机制了。不过意思已经很清楚:任何拿到
> +设备仿真工具包的人,都能伪造描述符和设备信息,所以别把这类检查当成真正
> +的安全保障。
>
> 接口授权
> --------
>
> -也有类似的方法用于允许或拒绝特定 USB 接口。
> -这使得你可以只阻止某个 USB 设备中的部分接口。
> +也可以用类似的方法允许或拒绝特定的 USB 接口。这样一来,你只需要阻止某个
> +USB 设备中的部分接口。
>
> 授权接口::
>
> @@ -126,14 +119,12 @@
>
> $ echo 0 > /sys/bus/usb/devices/usbX/interface_authorized_default
>
> -默认情况下,
> -``interface_authorized_default`` 位为 ``1``,
> -因此所有接口默认都处于已授权状态。
> +默认情况下,``interface_authorized_default`` 位为 ``1``,因此所有接口默认
> +都会处于授权状态。
>
> 注意:
> - 如果把一个先前未授权的接口改为已授权,
> - 则必须通过将 ``INTERFACE`` 写入 ``/sys/bus/usb/drivers_probe``
> - 来手动触发驱动探测。
> + 如果把一个先前未授权的接口改为已授权,则必须通过将 ``INTERFACE`` 写入
> + ``/sys/bus/usb/drivers_probe`` 来手动触发驱动探测。
>
> -对于需要多个接口的驱动程序,应先授权所有必需接口,
> -然后再触发驱动探测。这样做可以避免副作用。
> +对于需要多个接口的驱动程序,应先授权所有必需接口,然后再触发驱动探测。
> +这样做可以避免副作用。
> diff --git a/Documentation/translations/zh_CN/usb/chipidea.rst b/Documentation/translations/zh_CN/usb/chipidea.rst
> index ea0dc3043189..011fb16f3350 100644
> --- a/Documentation/translations/zh_CN/usb/chipidea.rst
> +++ b/Documentation/translations/zh_CN/usb/chipidea.rst
> @@ -17,18 +17,17 @@ ChipIdea 高速双角色控制器驱动
> 1. 如何测试 OTG FSM(HNP 和 SRP)
> ---------------------------------
>
> -下面以两块 Freescale i.MX6Q Sabre SD 开发板为例,
> -说明如何通过 sysfs 输入文件演示 OTG 的 HNP 和 SRP 功能。
> +下面以两块 Freescale i.MX6Q Sabre SD 开发板为例,演示如何通过 sysfs 属性
> +测试 OTG 的 HNP 和 SRP 功能。
>
> -1.1 如何使能 OTG FSM
> +1.1 如何启用 OTG FSM
> --------------------
>
> 1.1.1 在 ``menuconfig`` 中选择 ``CONFIG_USB_OTG_FSM``,并重新编译内核
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> -重新构建内核镜像和模块。如果想查看 OTG FSM 的
> -一些内部变量,可以挂载 ``debugfs``;其中有两个文件
> -可以显示 OTG FSM 变量以及部分控制器寄存器的值::
> +重新构建内核镜像和模块。如果想查看 OTG FSM 的内部变量,可以挂载
> +``debugfs``;其中有两个文件,分别显示 OTG FSM 的变量和部分控制器寄存器值::
>
> cat /sys/kernel/debug/ci_hdrc.0/otg
> cat /sys/kernel/debug/ci_hdrc.0/registers
> @@ -44,11 +43,10 @@ ChipIdea 高速双角色控制器驱动
> 1.2 测试步骤
> ------------
>
> -1) 给两块 Freescale i.MX6Q Sabre SD 开发板上电,
> - 并加载 gadget 类驱动(例如 ``g_mass_storage``)。
> +1) 给两块 Freescale i.MX6Q Sabre SD 开发板上电,并加载 gadget 类驱动(例如
> + ``g_mass_storage``)。
>
> -2) 用 USB 线连接两块开发板:
> - 一端是 micro A 插头,另一端是 micro B 插头。
> +2) 用 USB 线连接两块开发板:一端是 micro A 插头,另一端是 micro B 插头。
>
> 插入 micro A 插头的一端是 A 设备,它应枚举另一端的 B 设备。
>
> @@ -66,32 +64,28 @@ ChipIdea 高速双角色控制器驱动
>
> echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
>
> - 或者,通过引入 HNP 轮询,B 端主机可以知道
> - A 端外设希望切换为主机角色,因此这次角色切换
> - 也可以通过 A 端外设响应 B 端主机的轮询,
> - 在 A 侧触发。
> - 这可以通过在 A 设备上执行下面的命令来完成::
> + 或者,也可以借助 HNP 轮询,让 B 端主机知道 A 端外设希望切回主机角色。
> + 因此,这次切换也可以由 A 侧触发,也就是由 A 端外设响应 B 端主机的轮询
> + 来完成。可在 A 设备上执行下面的命令::
>
> echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
>
> A 设备应切回主机角色并枚举 B 设备。
>
> -5) 拔掉 B 设备(拔掉 micro B 插头),
> - 并在 10 秒内重新插入;
> +5) 拔掉 B 设备(拔掉 micro B 插头),并在 10 秒内重新插入。
> A 设备应重新枚举 B 设备。
>
> -6) 拔掉 B 设备(拔掉 micro B 插头),
> - 并在 10 秒后重新插入;
> +6) 拔掉 B 设备(拔掉 micro B 插头),并在 10 秒后重新插入。
> A 设备不应重新枚举 B 设备。
>
> - 如果 A 设备希望使用总线:
> + 如果 A 设备还想继续使用总线:
>
> 在 A 设备上执行::
>
> echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_drop
> echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
>
> - 如果 B 设备希望使用总线:
> + 如果 B 设备想使用总线:
>
> 在 B 设备上执行::
>
> @@ -111,40 +105,38 @@ ChipIdea 高速双角色控制器驱动
>
> echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
>
> - A 设备应恢复 USB 总线并枚举 B 设备。
> + A 设备应恢复 USB 总线,并枚举 B 设备。
>
> 1.3 参考文档
> ------------
> -《On-The-Go and Embedded Host Supplement
> -to the USB Revision 2.0 Specification
> +《On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Specification
> July 27, 2012 Revision 2.0 version 1.1a》
>
> 2. 如何将 USB 用作系统唤醒源
> ----------------------------
> -下面是在 i.MX6 平台上把 USB 用作系统唤醒源的示例。
> +下面给出在 i.MX6 平台上将 USB 用作系统唤醒源的示例。
>
> -2.1 使能核心控制器的唤醒功能::
> +2.1 启用核心控制器的唤醒功能::
>
> echo enabled > /sys/bus/platform/devices/ci_hdrc.0/power/wakeup
>
> -2.2 使能 glue 层的唤醒功能::
> +2.2 启用 glue 层的唤醒功能::
>
> echo enabled > /sys/bus/platform/devices/2184000.usb/power/wakeup
>
> -2.3 使能 PHY 的唤醒功能(可选)::
> +2.3 启用 PHY 的唤醒功能(可选)::
>
> echo enabled > /sys/bus/platform/devices/20c9000.usbphy/power/wakeup
>
> -2.4 使能根集线器的唤醒功能::
> +2.4 启用根集线器的唤醒功能::
>
> echo enabled > /sys/bus/usb/devices/usb1/power/wakeup
>
> -2.5 使能相关设备的唤醒功能::
> +2.5 启用相关设备的唤醒功能::
>
> echo enabled > /sys/bus/usb/devices/1-1/power/wakeup
>
> -如果系统只有一个 USB 端口,
> -而你希望在该端口上启用 USB 唤醒功能,
> -可以使用下面的脚本::
> +如果系统只有一个 USB 端口,而你希望在该端口上启用 USB 唤醒功能,可以使用
> +下面的脚本::
>
> for i in $(find /sys -name wakeup | grep usb);do echo enabled > $i;done;
> diff --git a/Documentation/translations/zh_CN/usb/dwc3.rst b/Documentation/translations/zh_CN/usb/dwc3.rst
> index 3468ce50c5ba..9584cbbf6d03 100644
> --- a/Documentation/translations/zh_CN/usb/dwc3.rst
> +++ b/Documentation/translations/zh_CN/usb/dwc3.rst
> @@ -18,46 +18,43 @@ DWC3 驱动
> 待办
> ~~~~
>
> -阅读时如果想顺手认领点任务,可以从下面挑一项 :)
> +如果你愿意接手其中一项任务,可以从下面选择:
>
> - 将中断处理程序改为每个端点各自使用线程化 IRQ
>
> - 事实证明,有些 DWC3 命令大约需要 ``~1 ms`` 才能完成。
> - 当前代码会一直自旋等待命令完成,这种设计并不好。
> + 实践表明,某些 DWC3 命令大约需要 ``~1 ms`` 才能完成。当前代码会一直自旋
> + 等待命令完成,这并不是好办法。
>
> 实现思路:
>
> - - DWC 核心实现了一个按端点对中断进行解复用的 IRQ 控制器。
> - 中断号在探测(``probe``)阶段分配,并归属于该设备。
> - 如果硬件通过 ``MSI`` 为每个端点提供独立中断,
> - 那么这个“虚拟”IRQ 控制器就可以被真实的端点中断取代。
> + - DWC 核心实现了一个按端点分发中断的 IRQ 控制器。中断号在探测
> + (``probe``)阶段分配,并归属于该设备。如果硬件通过 ``MSI`` 为每个
> + 端点提供独立中断,那么这个“虚拟”IRQ 控制器就可以被真实的端点中断
> + 取代。
>
> - - 在调用 ``usb_ep_enable()`` 时请求并分配中断资源,
> - 在调用 ``usb_ep_disable()`` 时释放中断资源。
> - 最坏情况下需要 32 个中断,最少是 ``ep0/1`` 的两个中断。
> + - 在调用 ``usb_ep_enable()`` 时请求并分配中断资源,在调用
> + ``usb_ep_disable()`` 时释放中断资源。最坏情况下需要 32 个中断,最少是
> + ``ep0/1`` 的两个中断。
> - ``dwc3_send_gadget_ep_cmd()`` 将在 ``wait_for_completion_timeout()``
> 中休眠,直到命令完成。
> - 中断处理程序分为以下几个部分:
>
> - 设备级主中断处理程序
> - 遍历每个事件,并对其调用 ``generic_handle_irq()``。
> - 从 ``generic_handle_irq()`` 返回后,确认事件计数器,使中断最终消失。
> + 遍历每个事件,并调用 ``generic_handle_irq()`` 处理。返回后再确认
> + 事件计数器,让中断最终消失。
>
> - 设备级线程化处理程序
> 无。
>
> - 端点中断的主处理程序
> - 读取事件并尽量处理它。凡是需要睡眠的操作都交给线程处理。
> - 事件保存在每个端点的数据结构中。
> - 还要注意,一旦把某项工作交给线程处理,
> - 就不要再在主处理程序里处理它,
> - 以免出现优先级反转之类的问题。
> + 读取事件并尽量处理;凡是需要睡眠的操作都交给线程处理。事件保存在
> + 每个端点的数据结构中。一旦某项工作已经交给线程处理,主处理程序里就
> + 不要再碰它,以免出现优先级反转之类的问题。
>
> - 端点中断的线程化处理程序
> 处理剩余的端点工作,这些工作可能会睡眠,例如等待命令完成。
>
> - 延迟:
> + 延迟:
>
> - 不应增加延迟,因为中断线程具有较高优先级,
> - 会在普通用户态任务之前运行
> + 不应增加额外延迟,因为中断线程优先级较高,会在普通用户任务之前运行
> (除非用户更改了调度优先级)。
> diff --git a/Documentation/translations/zh_CN/usb/ehci.rst b/Documentation/translations/zh_CN/usb/ehci.rst
> index e05e493a30d3..c4c52303b13e 100644
> --- a/Documentation/translations/zh_CN/usb/ehci.rst
> +++ b/Documentation/translations/zh_CN/usb/ehci.rst
> @@ -14,45 +14,37 @@
> EHCI 驱动
> =========
>
> -2002年12月27日
> +2002 年 12 月 27 日
>
> -EHCI 驱动用于通过支持 USB 2.0 的主机控制器
> -硬件与高速 USB 2.0 设备通信。USB 2.0 兼容
> -USB 1.1 标准,它定义了三种传输速率:
> +EHCI 驱动用于借助支持 USB 2.0 的主机控制器,与高速 USB 2.0 设备通信。USB
> +2.0 向下兼容 USB 1.1,并定义了三种传输速率:
>
> - “高速”(High Speed)480 Mbit/sec(60 MByte/sec)
> - “全速”(Full Speed)12 Mbit/sec(1.5 MByte/sec)
> - “低速”(Low Speed)1.5 Mbit/sec
>
> -USB 1.1 仅支持全速与低速。
> -高速设备可以在 USB 1.1 系统上使用,
> -但速度会降到 USB 1.1 的速率。
> +USB 1.1 仅支持全速与低速。高速设备可以在 USB 1.1 系统上使用,但速度会
> +降到 USB 1.1 的速率。
>
> -USB 1.1 设备也可以在 USB 2.0 系统上使用。当它们
> -插入 EHCI 控制器时,会被交由 USB 1.1 的伴随
> -(companion)控制器处理,该控制器通常是 OHCI 或 UHCI。
> +USB 1.1 设备也可以在 USB 2.0 系统上使用。当它们插入 EHCI 控制器时,会交给
> +USB 1.1 的伴随(companion)控制器处理,该控制器通常是 OHCI 或 UHCI。
>
> -当 USB 1.1 设备插入 USB 2.0 集线器时,它们通过
> -集线器中的事务转换器(Transaction Translator,TT)
> -与 EHCI 控制器交互,该转换器将低速或全速事务转换为
> -高速分割事务,从而避免浪费传输带宽。
> +当 USB 1.1 设备插入 USB 2.0 集线器时,它们会通过集线器里的事务转换器
> +(Transaction Translator,TT)与 EHCI 控制器通信。该转换器会把低速或全
> +速事务转换为高速分割事务,从而避免浪费传输带宽。
>
> -截至本文撰写时,该驱动已在以下 EHCI 实现上成功运行
> -(按字母顺序):Intel、NEC、Philips 和 VIA。
> -其他供应商的 EHCI 实现正在陆续问世;
> -预计该驱动在这些实现上也可正常运行。
> +截至本文撰写时,该驱动已在以下 EHCI 实现上成功运行(按字母顺序):
> +Intel、NEC、Philips 和 VIA。随着其他供应商的 EHCI 实现陆续问世,预计该
> +驱动在那些实现上也能正常运行。
>
> -自 2001 年年中起,usb-storage 设备就已可用
> -(在 2.4 版该驱动上速度相当不错),
> -集线器则直到 2001 年底才开始可用,而其他类型的高速设备
> -似乎要等到更多系统内置 USB 2.0 后才会出现。
> -这类新系统从 2002 年初开始上市,
> -并在 2002 年下半年变得更加常见。
> +自 2001 年年中起,usb-storage 设备就已可用(在 2.4 版该驱动上速度表现相当
> +不错),集线器则直到 2001 年底才开始可用。其他类型的高速设备似乎要等到
> +更多系统内置 USB 2.0 后才会出现。这类新系统从 2002 年初开始上市,并在
> +2002 年下半年变得更加常见。
>
> -注意,USB 2.0 支持并不只是 EHCI 本身。
> -它还需要对 Linux-USB 核心 API 作出其他修改,
> -包括 hub 驱动;不过这些修改并不需要真正改变
> -暴露给 USB 设备驱动的基本 ``usbcore`` API。
> +注意,USB 2.0 的支持并不只靠 EHCI 本身。它还需要对 Linux-USB 核心 API
> +做其他修改,包括 hub 驱动;不过这些修改并不需要真正改变向 USB 设备驱动
> +暴露的基本 ``usbcore`` API。
>
> - David Brownell
> <dbrownell@users.sourceforge.net>
> @@ -61,58 +53,46 @@ USB 1.1 设备也可以在 USB 2.0 系统上使用。当它们
> 功能
> ====
>
> -该驱动会定期在 x86 硬件上进行测试,
> -也已在 PPC 硬件上使用,因此大小端问题应当已经解决。
> -因此可以认为,它已经处理好了所有必要的 PCI 细节,
> -所以即便在 DMA 映射有些特殊的系统上,
> -I/O 也应能正常运行。
> +该驱动长期在 x86 硬件上接受测试,也在 PPC 平台上使用过,因此大小端问题应
> +该都已解决。再加上各种必要的 PCI 细节都已处理妥当,即便在 DMA 映射较特
> +殊的系统上,I/O 也应能正常工作。
>
> 传输类型
> --------
>
> -截至本文撰写时,该驱动应当已经能够很好地处理
> -所有控制传输、批量传输和中断传输,
> -包括通过 USB 2.0 集线器中的事务转换器
> -与 USB 1.1 设备通信;但仍可能存在 bug。
> +截至本文撰写时,该驱动应当已经能够稳定处理所有控制传输、批量传输和中断传
> +输,包括经由 USB 2.0 集线器里的事务转换器访问 USB 1.1 设备;不过仍可能
> +存在 bug。
>
> -高速等时(ISO)传输支持也已可用,但截至本文撰写时,
> -还没有 Linux 驱动使用这项支持。
> +高速等时(ISO)传输支持也已可用,不过截至本文撰写时,还没有 Linux 驱动真
> +正使用它。
>
> -目前尚不支持通过事务转换器实现全速等时传输。
> -需要注意,ISO 传输的 split transaction 支持
> -与高速 ISO 传输几乎无法共用代码,
> -因为 EHCI 用不同的数据结构表示它们。
> -因此,目前大多数 USB 音频和视频设备
> -还不能通过高速总线连接使用。
> +目前尚不支持通过事务转换器实现全速等时传输。需要注意,ISO 传输的分割
> +事务支持与高速 ISO 传输几乎无法共用代码,因为 EHCI 用不同的数据结构表示
> +它们。因此,目前大多数 USB 音频和视频设备还无法在高速总线上使用。
>
> 驱动行为
> --------
>
> -所有类型的传输都可以排队。
> -这意味着来自一个接口驱动的控制传输
> -(或通过 usbfs 发出的控制传输)不会干扰
> -另一个驱动的控制传输,而且中断传输可以使用 1 帧的周期,
> -而不必担心中断处理开销导致的数据丢失。
> +所有类型的传输都可以排队提交。这意味着某个接口驱动发出的控制传输(或经由
> +usbfs 提交的控制传输)不会干扰其他驱动的控制传输,而中断传输可以按 1 帧
> +周期运行,不必担心中断处理开销导致数据丢失。
>
>
> -EHCI 根集线器代码会将 USB 1.1 设备移交给其伴随控制器。
> -该驱动不需要了解那些驱动的任何细节;
> -一个原本就能正常工作的 OHCI 或 UHCI 驱动,
> -并不会因为 EHCI 驱动也存在而需要更改。
> +EHCI 根集线器代码会将 USB 1.1 设备交给其伴随控制器处理。该驱动无需了解
> +那些驱动的任何细节;一个原本就能正常工作的 OHCI 或 UHCI 驱动,也不会因为
> +EHCI 驱动存在而需要修改。
>
> -电源管理方面还有一些问题;
> -当前挂起/恢复的行为还不完全正确。
> +电源管理方面仍有一些问题;当前挂起/恢复行为还不完全正确。
>
> -此外,在调度周期性事务
> -(中断和等时传输)时还采取了一些简化处理。
> -这些简化会限制可调度的周期性事务数量,
> -并且无法使用小于一帧的轮询间隔。
> +此外,在调度周期性事务(中断和等时传输)时还采取了一些简化处理。这些
> +简化会限制可调度的周期性事务数量,并且无法使用小于一帧的轮询间隔。
>
> 使用方式
> ========
>
> -假设有一个 EHCI 控制器(位于 PCI 卡或主板上),
> -并且已将此驱动编译为模块,可这样加载::
> +假设系统中有一个 EHCI 控制器(位于 PCI 卡或主板上),并且此驱动是以模块形
> +式编译的,那么可以这样加载::
>
> # modprobe ehci-hcd
>
> @@ -120,27 +100,24 @@ EHCI 根集线器代码会将 USB 1.1 设备移交给其伴随控制器。
>
> # rmmod ehci-hcd
>
> -还应加载一个伴随控制器驱动,
> -例如 ``ohci-hcd`` 或 ``uhci-hcd``。
> -如果 EHCI 驱动出现任何问题,只需卸载它的模块,
> -随后该伴随控制器驱动就会接手
> -此前由 EHCI 驱动处理的所有设备
> -(但速度会降低)。
> +还应加载一个伴随控制器驱动,例如 ``ohci-hcd`` 或 ``uhci-hcd``。如果 EHCI
> +驱动出了问题,只要卸载它的模块,伴随控制器驱动就会接管此前由 EHCI 驱动处
> +理的全部设备(只是速度会降低)。
>
> 模块参数(传给 ``modprobe``)包括:
>
> log2_irq_thresh(默认值 0):
> - 默认中断延迟的 log2 值,单位是微帧。默认值 0 表示 1 个微帧
> - (125 微秒)。最大值 6 表示 2^6 = 64 个微帧。
> + 默认中断延迟的 log2 值,单位为微帧。默认值 0 表示 1 个微帧
> + (125 微秒),最大值 6 表示 2^6 = 64 个微帧。
> 该值控制 EHCI 控制器发出中断的频率。
>
> -如果在 2.5 内核上使用此驱动,并且启用了 USB 调试支持,
> -则会在任一 EHCI 控制器的 ``sysfs`` 目录中看到三个文件:
> +如果你在 2.5 内核上使用此驱动,并且启用了 USB 调试支持,那么任一 EHCI 控
> +制器对应的 ``sysfs`` 目录下都会看到三个文件:
>
> ``async``
> 转储异步调度,用于控制传输和批量传输。它会显示每个活动的 ``qh``
> 以及待处理的 ``qtd``,通常每个 ``urb`` 对应一个 ``qtd``。
> - (可以在 ``usb-storage`` 做磁盘 I/O 时看它;顺便观察请求队列!)
> + (可以在 ``usb-storage`` 执行磁盘 I/O 时查看;也可顺便观察请求队列。)
>
> ``periodic``
> 转储周期性调度,用于中断传输和等时传输。不显示 ``qtd``。
> @@ -151,111 +128,81 @@ EHCI 根集线器代码会将 USB 1.1 设备移交给其伴随控制器。
> 这些文件的内容有助于定位驱动问题。
>
>
> -设备驱动通常不需要关心自己是否运行在 EHCI 之上,
> -但它们可能想检查
> -``usb_device->speed == USB_SPEED_HIGH``。
> -高速设备能做到全速(或低速)设备做不到的事,
> -例如高带宽的周期性传输(中断或 ISO 传输)。
> -另外,设备描述符中的某些值
> -(例如周期性传输的轮询间隔)
> -在高速模式下使用不同的编码方式。
> +设备驱动通常不需要关心自己是否运行在 EHCI 之上,但有时可能会想检查
> +``usb_device->speed == USB_SPEED_HIGH``。高速设备能做到全速(或低速)设备
> +做不到的事,例如高带宽的周期性传输(中断或 ISO 传输)。另外,设备描述符
> +中的某些值(例如周期性传输的轮询间隔)在高速模式下使用不同的编码方式。
>
> -不过,一定要让设备驱动经过 USB 2.0 集线器的测试。
> -当使用事务转换器时,这些集线器报告某些故障
> -(例如断开连接)的方式会不同;
> -已经见过一些驱动在遇到与 OHCI 或 UHCI
> -所报告的不同故障时表现不佳。
> +不过,设备驱动一定要在 USB 2.0 集线器后面测一遍。使用事务转换器时,这些
> +集线器报告某些故障(例如断开连接)的方式会有所不同;已经见过一些驱动在
> +遇到与 OHCI 或 UHCI 不同的故障时表现不佳。
>
> 性能
> ====
>
> -USB 2.0 吞吐量主要受两个因素制约:
> -主机控制器处理请求的速度,以及设备响应这些请求的速度。
> -480 Mbit/sec 的“原始传输率”对所有设备都成立,
> -但总吞吐量还会受到诸如单个高速包之间的延迟、
> -驱动是否足够聪明,以及系统整体负载等因素的影响。
> -延迟也是性能考量因素。
> +USB 2.0 的吞吐量主要受两个因素制约:主机控制器处理请求的速度,以及设备响
> +应这些请求的速度。480 Mbit/sec 的“原始传输率”对所有设备都一样,但整体吞
> +吐量还会受到诸如高速包之间的间隔、驱动实现是否足够高效以及系统总体负载等
> +因素影响。延迟同样是需要考虑的性能指标。
>
> -批量传输最常用于关注吞吐量的场景。
> -需要记住的是,批量传输总是以 512 字节包为单位,
> -而一个 USB 2.0 微帧中最多只能容纳 13 个这样的包。
> -8 个 USB 2.0 微帧构成一个 USB 1.1 帧;
> -一个微帧的时长是 1 毫秒 / 8 = 125 微秒。
> +批量传输通常用于看重吞吐量的场景。需要记住的是,批量传输总是以 512 字节包
> +为单位,而一个 USB 2.0 微帧中最多只能容纳 13 个这样的包。8 个 USB 2.0 微
> +帧构成一个 USB 1.1 帧,因此一个微帧的时长就是 125 微秒。
>
> -因此,只要硬件和设备驱动软件都允许,
> -批量传输可提供超过 50 MByte/sec 的带宽。
> -周期性传输模式(等时和中断)允许使用更大的包大小,
> -从而可以逼近所宣称的 480 Mbit/sec 传输率。
> +因此,只要硬件和驱动实现都足够成熟,批量传输就可以提供 50 MByte/sec 以上
> +的带宽。周期性传输模式(等时和中断)允许使用更大的包大小,从而可以逼近所
> +宣称的 480 Mbit/sec 传输率。
>
> 硬件性能
> --------
>
> -截至本文撰写时,单个 USB 2.0 设备的最大传输速率
> -通常约为 20 MByte/sec。
> -这当然会随着时间改变:一些设备现在更快,一些更慢。
> +截至本文撰写时,单个 USB 2.0 设备的最大传输速率通常约为 20 MByte/sec。
> +这种情况当然会随时间变化:有些设备现在更快,有些则更慢。
>
> -第一代 NEC EHCI 实现似乎存在
> -大约 28 MByte/sec 的硬件瓶颈。
> -虽然这对单个 20 MByte/sec 的设备显然已经够用,
> -但把三个这样的设备挂到同一总线上,
> -并不能得到 60 MByte/sec。
> -问题似乎在于控制器硬件无法并发进行 USB 与 PCI 访问,
> -因此它每个微帧只会尝试 6 次(也许是 7 次)
> -USB 事务,而不是 13 次。
> -(对一个比其他产品早上市一年的芯片来说,
> -这是个合理的妥协!)
> +第一代 NEC EHCI 实现似乎存在大约 28 MByte/sec 的硬件瓶颈。虽然这对单个
> +20 MByte/sec 的设备显然已经够用,但把三个这样的设备挂到同一总线上,并不
> +能得到 60 MByte/sec。问题似乎在于控制器硬件无法并发进行 USB 与 PCI 访问,
> +因此它每个微帧只会尝试 6 次(也许是 7 次)USB 事务,而不是 13 次。
> +(对一款比其他产品早上市一年的芯片来说,这样的取舍也算合理。)
>
>
> -预计较新的实现会在这方面做得更好,
> -通过投入更多芯片面积来解决这个问题,
> -使新的主板芯片组更接近 60 MByte/sec 的目标。
> -这既包括 NEC 的更新实现,也包括其他厂商的芯片。
> +预计较新的实现会在这方面做得更好,通过投入更多芯片面积来解决这个问题,
> +使新的主板芯片组更接近 60 MByte/sec 的目标。这既包括 NEC 的更新实现,也
> +包括其他厂商的芯片。
>
>
> -主机从 EHCI 控制器收到“请求已完成”中断的最小延迟
> -为一个微帧(125 微秒)。该延迟可以调节;
> -驱动提供了一个模块选项。默认情况下,
> -``ehci-hcd`` 使用最小延迟,这意味着当发出一个控制
> -或批量请求时,通常可以在不到 250 微秒内得知它已完成
> -(具体取决于传输大小)。
> +主机从 EHCI 控制器收到“请求已完成”中断的最小延迟为一个微帧
> +(125 微秒)。该延迟可以调节;驱动提供了一个模块选项。
> +默认情况下,``ehci-hcd`` 使用最小延迟,这意味着发出控制或批量请求后,通
> +常不到 250 微秒就能得知它已经完成(具体取决于传输大小)。
>
> 软件性能
> --------
>
> -即便只是要达到 20 MByte/sec 的传输速率,
> -Linux-USB 设备驱动也必须让 EHCI 队列始终保持满载。
> -这意味着要发出较大的请求,
> -或者在需要发出一连串小请求时使用批量请求排队。
> -如果驱动未做到这一点,那么会直接从性能结果上表现出来。
> +即便只是要达到 20 MByte/sec 的传输速率,Linux-USB 设备驱动也必须让 EHCI
> +队列始终保持满载。这意味着要发出较大的请求,或者在需要发出一连串小请求
> +时使用批量请求排队。如果驱动做不到这一点,性能就会明显受影响。
>
>
> -在典型情况下,使用 ``usb_bulk_msg()``
> -以 4 KB 块循环写出,
> -会浪费超过一半的 USB 2.0 带宽。
> -I/O 完成与驱动发出下一次请求之间的延迟,
> -通常会比一次 I/O 本身耗时更长。
> -如果同样的循环改用 16 KB 块,会好一些;
> -若使用一连串 128 KB 块,则浪费会少得多。
> +在典型场景下,如果使用 ``usb_bulk_msg()`` 以 4 KB 块循环写出,会浪费超过
> +一半的 USB 2.0 带宽。I/O 完成与驱动发出下一次请求之间的空档,往往比一次
> +I/O 本身耗时还长。如果同样的循环改用 16 KB 块,情况会好一些;若使用一连串
> +128 KB 块,则浪费会少得多。
>
> +但与其依赖这么大的 I/O 缓冲区来提升同步 I/O 的效率,不如直接向主机控制器
> +排队提交多个(批量)请求,然后等待它们全部完成(或在出错时取消)。这种
> +URB 排队方式对所有 USB 1.1 主机控制器驱动同样适用。
>
> -但与其依赖这么大的 I/O 缓冲区来让同步 I/O 高效,
> -不如直接向主机控制器排入多个(批量)请求,
> -然后等待它们全部完成(或在出错时取消)。
> -这种 URB 排队方式对所有 USB 1.1
> -主机控制器驱动也同样适用。
>
> -
> -在 Linux 2.5 内核中,定义了新的 ``usb_sg_*()`` API;
> -它们会把 scatterlist 中的所有缓冲区都排入队列。
> -它们还使用 scatterlist 的 DMA 映射
> -(其中可能应用 IOMMU)并减少中断次数,
> -这些都有助于让高速传输尽可能快地运行。
> +在 Linux 2.5 内核中,定义了新的 ``usb_sg_*()`` API;它们会把 scatterlist
> +中的所有缓冲区都排入队列。它们还使用 scatterlist 的 DMA 映射(其中可能
> +应用 IOMMU)并减少中断次数,这些都有助于让高速传输尽可能快地运行。
>
> 待办:
> 中断传输和等时(ISO)传输的性能问题。
> - 这些周期性传输都是完全调度的,因此,主要问题可能在于如何触发高带宽模式。
> + 这些周期性传输都是完全调度的,因此主要问题可能在于如何触发高带宽模式。
>
> 待办:
> - 通过 ``sysfs`` 中的 ``uframe_periodic_max`` 参数,
> - 可以分配超过标准 80% 的周期性带宽。
> + 通过 ``sysfs`` 中的 ``uframe_periodic_max`` 参数,可以分配超过标准
> + 80% 的周期性带宽。
> 后续将对此进行说明。
> diff --git a/Documentation/translations/zh_CN/usb/index.rst b/Documentation/translations/zh_CN/usb/index.rst
> index eb5aca0c13ec..df99814c6497 100644
> --- a/Documentation/translations/zh_CN/usb/index.rst
> +++ b/Documentation/translations/zh_CN/usb/index.rst
> @@ -1,4 +1,14 @@
> .. SPDX-License-Identifier: GPL-2.0
> +
> +.. only:: subproject and latex
> +
> + .. raw:: latex
> +
> + \renewcommand{\thesection}{}
> + \renewcommand{\thesubsection}{}
> + \kerneldocCJKon
> + \kerneldocBeginSC{
> +
> .. include:: ../disclaimer-zh_CN.rst
>
> :Original: Documentation/usb/index.rst
> @@ -24,7 +34,7 @@ USB 支持
> ehci
> usbmon
>
> -Todolist:
> +待翻译文档:
>
> * functionfs
> * functionfs-desc
> @@ -52,3 +62,9 @@ Todolist:
> ====
>
> * :ref:`genindex`
> +
> +.. only:: subproject and latex
> +
> + .. raw:: latex
> +
> + }\kerneldocEndSC
> diff --git a/Documentation/translations/zh_CN/usb/usbmon.rst b/Documentation/translations/zh_CN/usb/usbmon.rst
> index 11b6d5b59dce..bbfcbf875e26 100644
> --- a/Documentation/translations/zh_CN/usb/usbmon.rst
> +++ b/Documentation/translations/zh_CN/usb/usbmon.rst
> @@ -16,67 +16,56 @@ usbmon
>
> 简介
> ====
> -小写形式的 ``usbmon`` 指的是内核中的一项功能,
> -用于收集 USB 总线上的 I/O 跟踪信息。它类似于网络监控工具
> -``tcpdump(1)`` 或 Ethereal 所使用的数据包套接字。
> -类似地,人们希望使用 usbdump 或 USBMon
> -(首字母大写)之类的工具来检查
> -usbmon 生成的原始跟踪数据。
> -
> -usbmon 报告的是各个外设驱动
> -向主机控制器驱动(HCD)发出的请求。
> -因此,如果 HCD 本身有 bug,那么 usbmon 报告的跟踪信息
> -可能无法精确对应实际的总线事务。
> -这和 tcpdump 的情况是一样的。
> -
> -目前实现了两种 API: ``text`` 和 ``binary``。
> -二进制 API 通过 ``/dev`` 命名空间中的字符设备提供,
> -并且属于 ABI。文本 API 自内核 2.6.35 起已废弃,
> -但为了方便仍然可用。
> +小写的 ``usbmon`` 指的是内核中的一项功能,用于收集 USB 总线上的 I/O 跟踪
> +信息。它类似于网络监控工具 ``tcpdump(1)`` 或 Ethereal 使用的数据包套接
> +字。通常会用 usbdump 或 USBMon(首字母大写)之类的工具来查看 usbmon 生成
> +的原始跟踪数据。
> +
> +usbmon 记录的是各个设备驱动向主机控制器驱动(HCD)发出的请求。因此,如果
> +HCD 自身有 bug,usbmon 输出的跟踪信息就未必能和真实的总线事务一一对应。
> +这和 tcpdump 的情况类似。
> +
> +目前实现了两种 API:``text`` 和 ``binary``。二进制 API 通过 ``/dev`` 下的
> +字符设备提供,是 ABI 的一部分。文本 API 自内核 2.6.35 起已废弃,但为了
> +兼容和使用方便,至今仍然保留。
>
> 如何使用 usbmon 收集原始文本跟踪信息
> ====================================
>
> -与数据包套接字不同,usbmon 提供了一种接口,
> -可以输出文本格式的跟踪信息。这样做有两个目的:
> -第一,在更完善的格式最终确定之前,
> -它作为工具间通用的跟踪交换格式;
> -第二,在不使用工具的情况下,人们也可以直接阅读这些信息。
> +与数据包套接字不同,usbmon 还提供了一个输出文本格式跟踪信息的接口。这样
> +做主要有两个目的:一是在更完善的格式最终确定之前,将其作为工具间通用的跟
> +踪交换格式;二是在没有工具时也能直接阅读这些信息。
>
> -要收集原始文本跟踪信息,请按以下步骤进行操作。
> +要收集原始文本跟踪信息,按下面的步骤做即可。
>
> 1. 准备
> -------
>
> -挂载 debugfs(内核配置中必须启用它),并加载 usbmon 模块
> -(如果它是作为模块构建的)。如果 usbmon 已经编入内核,
> -那么第二步可以省略。
> +挂载 debugfs(内核配置里必须启用它),并加载 usbmon 模块(如果它是以模块
> +方式构建的)。如果 usbmon 已经编译进内核,这一步就可以省略。
>
> 命令示例::
>
> - # mount -t debugfs none_debugs /sys/kernel/debug
> + # mount -t debugfs none /sys/kernel/debug
> # modprobe usbmon
> #
>
> -确认总线套接字是否存在::
> +确认 ``usbmon`` 目录下是否有这些条目::
>
> # ls /sys/kernel/debug/usb/usbmon
> 0s 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u
> #
>
> -现在,你可以选择使用 ``0u`` 捕获所有总线上的数据包,
> -并跳到第 3 步;
> -也可以先按第 2 步找到目标设备所在的总线。
> -这样可以过滤掉那些持续输出数据的烦人设备。
> +现在,你可以直接用 ``0u`` 捕获所有总线上的数据包,然后跳到第 3 步;也可
> +以先按第 2 步找出目标设备所在的总线。这样可以把那些持续产生流量的设备过
> +滤掉。
>
> 2. 查找目标设备连接的是哪条总线
> -------------------------------
>
> -运行 ``cat /sys/kernel/debug/usb/devices``,
> -找到对应设备的 T 行。通常可以通过厂商字符串来查找。
> -如果有许多类似设备,可以拔掉其中一个,
> -再比较前后两次 ``/sys/kernel/debug/usb/devices``
> -的输出。T 行里会包含总线编号。
> +运行 ``cat /sys/kernel/debug/usb/devices``,找到对应设备的 T 行。通常可以通过
> +厂商字符串来查找。如果有很多相似设备,可以拔掉其中一个,再比较前后两次
> +``/sys/kernel/debug/usb/devices`` 的输出。T 行里会包含总线编号。
>
> 示例::
>
> @@ -86,8 +75,8 @@ usbmon 报告的是各个外设驱动
> S: Manufacturer=ATEN
> S: Product=UC100KM V2.00
>
> -``Bus=03`` 表示它位于 3 号总线上。或者,
> -也可以查看 ``lsusb`` 的输出,并从对应行得到总线编号。
> +``Bus=03`` 表示它位于 3 号总线上。或者,也可以查看 ``lsusb`` 的输出,并从
> +对应条目里找到总线编号。
>
> 示例如下::
>
> @@ -97,133 +86,108 @@ usbmon 报告的是各个外设驱动
> 3. 启动 cat 命令
> ----------------
>
> -如果只监听单条总线,可执行::
> +如果只监听单条总线,执行::
>
> # cat /sys/kernel/debug/usb/usbmon/3u > /tmp/1.mon.out
>
> -否则,如果要监听所有总线,则执行::
> +否则,如果要监听所有总线,执行::
>
> # cat /sys/kernel/debug/usb/usbmon/0u > /tmp/1.mon.out
>
> -此进程会一直读取,直到被终止。
> -由于输出通常会很长,因此更推荐将输出重定向到某个位置。
> +这个进程会一直运行到被终止为止。由于输出通常会很长,最好把它重定向到文件
> +或其他位置。
>
>
> 4. 在 USB 总线上执行期望的操作
> ------------------------------
>
> -此处需要执行一些会产生 USB 流量的动作,
> -比如插入 U 盘、拷贝文件、操作摄像头等。
> +这里做一些会产生 USB 流量的操作即可,比如插入 U 盘、拷贝文件、操作摄像头
> +等。
>
>
> 5. 停止 cat
> -----------
>
> -这一步通常通过键盘中断(Control-C)完成。
> +这一步通常按下键盘中断(Control-C)即可完成。
>
> -此时输出文件(本例中为 ``/tmp/1.mon.out``)
> -可以保存、通过电子邮件发送,或使用文本编辑器查看。
> -如果使用最后一种方式,请确保文件不会大到编辑器无法打开。
> +此时,输出文件(本例中为 ``/tmp/1.mon.out``)可以保存下来,通过电子邮件发
> +送,也可以用文本编辑器查看。如果要用文本编辑器查看,请确保文件大小不会
> +大到编辑器无法处理。
>
>
> 原始文本数据格式
> ================
>
> -目前支持两种格式:原始格式,也就是 ``1t`` 格式,
> -以及 ``1u`` 格式。``1t`` 格式在内核 2.6.21 中已被废弃。
> -``1u`` 格式增加了一些字段,例如 ISO 帧描述符、
> -``interval`` 等。它生成的行会稍长一些,
> -但在其他方面是 ``1t`` 格式的完整超集。
> -
> -如果程序需要区分上述两种格式,
> -可以查看 ``address`` 字段(见下文)。
> -如果其中有两个冒号,就是 ``1t`` 格式;
> -否则是 ``1u`` 格式。
> -
> -任何文本格式的数据由一系列事件组成,
> -如 URB 提交、URB 回调、提交错误等。
> -每个事件对应单独的一行文本,
> -由使用空白符间隔的若干字段组成。
> -字段的数量与位置可能取决于事件类型,
> -但以下字段对所有类型都通用:
> -
> -下面按从左到右的顺序列出这些共有字段:
> -
> -- URB Tag。用于标识 URB,通常是 URB 结构体在内核中的地址
> - (以十六进制表示),
> - 但也可能是序号或其他合理的唯一字符串。
> -
> -- 时间戳(微秒),十进制数字。
> - 时间戳的精度取决于可用时钟,
> - 因此可能远差于
> - 1 微秒(例如实现使用的是 jiffies)。
> -
> -- 事件类型。它表示的是事件的格式,而不是 URB 的类型。
> - 可用值为:``S`` 表示提交,``C`` 表示回调,``E`` 表示提交错误。
> -
> -- ``Address`` 字段(以前称作 ``pipe``)。
> - 它包含四个由冒号分隔的字段:
> - URB 类型及方向、总线号、设备地址和端点号。类型与方向的编码如下:
> -
> - == == ==========================
> - Ci Co 控制输入和输出
> - Zi Zo 等时输入和输出
> - Ii Io 中断输入和输出
> - Bi Bo 批量输入和输出
> - == == ==========================
> -
> - 总线号、设备地址和端点号使用十进制,但可能有前导零。
> -
> -- URB 状态字段。这个字段要么是一个字母,
> - 要么是几个由冒号分隔的数字:
> - URB 状态、``interval``、``start frame`` 和 ``error count``。
> - 与 ``address`` 字段不同,除了状态外,其余字段都是可选的。
> - ``interval`` 只会为中断和等时 URB 打印;``start frame`` 只会为
> - 等时 URB 打印;错误计数只会在等时回调事件中打印。
> -
> - 状态字段是一个十进制数字,有时为负数,
> - 对应 URB 的 ``status`` 字段。
> - 对于提交事件,这个字段本身没有实际意义,
> - 但为了便于脚本解析,它仍然存在。
> - 当发生错误时,该字段包含错误码。
> -
> - 在提交控制包时,这个字段包含的是 ``Setup Tag``,
> - 而不是一组数字。
> - 判断 ``Setup Tag`` 是否存在很容易,因为它从来不是数字。
> - 因此,如果脚本在这个字段里发现的是一组数字,
> - 就会继续读取数据长度(等时 URB 除外)。
> - 如果发现的是其他内容,比如一个字母,
> - 那么脚本会先读取 ``Setup`` 包,再读取数据长度或等时描述符。
> -
> -- ``Setup`` 包由 5 个字段组成:
> - ``bmRequestType``、``bRequest``、``wValue``、
> - ``wIndex`` 和 ``wLength``。这些字段由 USB 2.0 规范定义。
> - 如果 ``Setup Tag`` 为 ``s``,就可以安全地解码这些字段。
> - 否则,说明 Setup 包虽然存在,但并未被捕获,此时各字段中会填入占位内容。
> +目前支持两种格式:原始的 ``1t`` 格式和 ``1u`` 格式。``1t`` 格式在内核
> +2.6.21 中已被废弃。``1u`` 格式增加了一些字段,例如 ISO 帧描述符和
> +``interval``。它生成的行会稍长一些,但除此之外,它是 ``1t`` 格式的完整
> +超集。
> +
> +如果程序需要区分上述两种格式,可以查看 ``address`` 字段(见下文)。如果
> +其中有两个冒号,就是 ``1t`` 格式;否则是 ``1u`` 格式。
> +
> +任何文本格式的数据都由一系列事件构成,例如 URB 提交、URB 回调和提交错
> +误。每个事件占一行,由若干以空白符分隔的字段组成。字段数量和位置会随事件
> +类型变化,但下面这些字段对所有类型都通用:
> +
> +下面按从左到右的顺序说明这些通用字段:
> +
> +- URB 标识(URB Tag)。用于标识 URB,通常是 URB 结构体在内核中的地址
> + (十六进制),也可能是序号或其他足以唯一标识 URB 的字符串。
> +
> +- 时间戳(微秒),十进制数字。时间戳的精度取决于可用时钟,所以可能远低于
> + 1 微秒(例如实现使用 jiffies 时)。
> +
> +- 事件类型。它表示的是这一行事件的格式,而不是 URB 的类型。可用值为:
> + ``S`` 表示提交,``C`` 表示回调,``E`` 表示提交错误。
> +
> +- ``Address`` 字段(以前称为 ``pipe``)。它包含四个由冒号分隔的字段:URB
> + 类型及方向、总线号、设备地址和端点号。类型与方向的编码如下:
> +
> + - ``Ci`` / ``Co``:控制输入 / 输出
> + - ``Zi`` / ``Zo``:等时输入 / 输出
> + - ``Ii`` / ``Io``:中断输入 / 输出
> + - ``Bi`` / ``Bo``:批量输入 / 输出
> +
> + 总线号、设备地址和端点号都是十进制数,但可能有前导零,方便人阅读。
> +
> +- URB 状态字段。这个字段要么是一个字母,要么是几个用冒号分隔的数字,依次
> + 表示 URB 状态、``interval``、``start frame`` 和 ``error count``。与
> + ``address`` 字段不同,除状态外,其余字段都可能省略。``interval`` 只会在
> + 中断和等时 URB 中打印;``start frame`` 只会在等时 URB 中打印;错误计数只
> + 会在等时回调事件中打印。
> +
> + 状态字段是一个十进制数,有时为负数,对应 URB 的 ``status`` 字段。对于提
> + 交事件,这个字段本身并无实际语义,但为了便于脚本解析仍会保留。发生错误
> + 时,这里填的是错误码。
> +
> + 如果是控制包的提交事件,这个字段里放的不是一组数字,而是 ``Setup Tag``。
> + 这很容易分辨,因为 ``Setup Tag`` 永远不是数字。所以脚本如果在这里读到一
> + 组数字,就会继续读取数据长度(等时 URB 除外);如果读到的是字母之类的内
> + 容,就要先读取 ``Setup`` 包,再读取数据长度或等时描述符。
> +
> +- ``Setup`` 包由 5 个字段组成:``bmRequestType``、``bRequest``、``wValue``、
> + ``wIndex`` 和 ``wLength``。这些字段由 USB 2.0 规范定义。如果 ``Setup Tag``
> + 是 ``s``,就可以安全解码这些字段。否则,说明 Setup 包虽然存在,但并未被
> + 捕获,此时各字段中会填入占位内容。
>
> - 等时传输帧描述符的数量及其内容:
> - 如果一个等时传输事件带有一组描述符,首先打印该 URB 中描述符的总数,
> - 然后为每个描述符打印一个字段,最多打印 5 个字段。
> - 每个字段由三个用冒号分隔的十进制数字组成,
> - 分别表示状态(status)、偏移(offset)和长度(length)。
> - 对于提交(submission),报告的是初始长度;
> - 对于回调(callback),报告的是实际长度。
> + 如果某个等时传输事件带有描述符,会先打印该 URB 的描述符总数,再为每个描
> + 述符打印一个字段,最多 5 个。每个字段由三个用冒号分隔的十进制数组成,依
> + 次表示状态(status)、偏移(offset)和长度(length)。对于提交事件,报
> + 告的是初始长度;对于回调事件,报告的是实际长度。
>
> -- 数据长度:
> - 对于提交,表示请求的长度;对于回调,表示实际传输的长度。
> +- 数据长度:对于提交,表示请求的长度;对于回调,表示实际传输的长度。
>
> -- 数据标签:
> - 即使数据长度非零,usbmon 也不一定会捕获数据。
> - 仅当标签为 ``=`` 时,才会有数据字段。
> +- 数据标签:即使数据长度非零,usbmon 也不一定会捕获数据。只有标签为
> + ``=`` 时,才会有数据字段。
>
> -- 数据字段:
> - 以大端十六进制格式显示。注意,这些并不是真正的机器字,
> - 而只是把字节流拆成若干“字”以便阅读。因此最后一个字可能只包含
> - 1 到 4 个字节。
> - 收集的数据长度是有限的,可能小于数据长度字段中报告的值。
> - 因为数据长度字段只统计实际接收到的字节,而数据字段包含整个传输缓冲区,
> - 所以,在等时输入(Zi)完成且缓冲区中接收到的数据稀疏的情况下,
> - 收集的数据长度可能大于数据长度字段的值。
> +- 数据字段:以大端十六进制格式显示。注意,这些并不是真正的机器字,只是为
> + 了便于阅读,把字节流按“字”分组显示。因此最后一个字可能只包含 1 到 4 个
> + 字节。捕获的数据长度是有限的,可能小于数据长度字段中报告的值。对于等时
> + 输入(Zi)完成事件,如果缓冲区里的接收数据比较稀疏,捕获数据的长度甚至
> + 可能大于数据长度字段,因为后者只统计实际接收到的字节,而数据字段展示的
> + 是整个传输缓冲区。
>
>
>
> @@ -234,18 +198,16 @@ usbmon 报告的是各个外设驱动
> d5ea89a0 3575914555 SCi:1:001:0 s a3 00 0000 0003 0004 4 <
> d5ea89a0 3575914560 CCi:1:001:0 0 4 = 01050000
>
> -向地址为 5 的存储设备发送
> -31 字节 Bulk 包装的 SCSI 命令 ``0x28``
> -(``READ_10``)的输出批量传输::
> +向地址为 5 的存储设备发送一个输出批量传输,其中 31 字节的 Bulk 封装用于承
> +载 SCSI 命令 ``0x28``(``READ_10``)::
>
> dd65f0e8 4128379752 SBo:1:005:2 -115 31 = 55534243 ad000000 00800000 80010a28 20000000 20000040 00000000 000000
> dd65f0e8 4128379808 CBo:1:005:2 0 31 >
>
> 原始二进制格式与 API
> ====================
> -API 的整体架构与前文大体相同,只是事件以二进制格式传递。
> -每个事件都通过下面的结构发送
> -(这个名字是为了叙述方便而虚构的)::
> +API 的整体架构与前文大体相同,只是事件以二进制格式传递。每个事件都通过
> +下面的结构发送(这个结构名只是为了叙述方便而虚构的)::
>
>
> struct usbmon_packet {
> @@ -275,29 +237,22 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
> unsigned int ndesc; /* 60: 实际 ISO 描述符数量 */
> }; /* 64 总长度 */
>
> -可以用 ``read(2)``、``ioctl(2)``,
> -或者通过 ``mmap`` 访问缓冲区,
> -从字符设备接收这些事件。
> -不过,出于兼容性原因,``read(2)``
> -只返回前 48 个字节。
> +可以用 ``read(2)``、``ioctl(2)``,或者通过 ``mmap`` 访问缓冲区,从字符设
> +备接收这些事件。不过,出于兼容性原因,``read(2)`` 只返回前 48 个字节。
>
> -字符设备通常命名为 ``/dev/usbmonN``,
> -其中 ``N`` 是 USB 总线号。
> -编号为零的设备(``/dev/usbmon0``)比较特殊,
> -表示“所有总线”。
> -请注意,具体命名策略由 Linux 发行版决定。
> +字符设备通常命名为 ``/dev/usbmonN``,其中 ``N`` 是 USB 总线号。编号为零的
> +设备(``/dev/usbmon0``)比较特殊,表示“所有总线”。具体命名策略由 Linux
> +发行版决定。
>
> -如果你手动创建 ``/dev/usbmon0``,
> -请确保它归 root 所有,并且权限为 ``0600``。
> -否则,非特权用户将能够窃听键盘流量。
> +如果你手动创建 ``/dev/usbmon0``,请确保它归 root 所有,并且权限为 ``0600``。
> +否则,非特权用户就能窃听键盘输入流量。
>
> 以下 ``MON_IOC_MAGIC`` 为 ``0x92`` 的 ioctl 调用可用:
>
> ``MON_IOCQ_URB_LEN``,定义为 ``_IO(MON_IOC_MAGIC, 1)``
>
> -该调用返回下一个事件的数据长度。
> -注意大多数事件不包含数据,
> -因此如果该调用返回零,并不意味着没有事件。
> +该调用返回下一个事件的数据长度。注意大多数事件不包含数据,因此如果它返回
> +零,并不意味着没有事件。
>
> ``MON_IOCG_STATS``,定义为
> ``_IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)``
> @@ -309,31 +264,28 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
> u32 dropped;
> };
>
> -成员 ``queued`` 表示当前缓冲区中已经排队的事件数量,
> -而不是自上次重置以来处理过的事件数量。
> +成员 ``queued`` 表示当前缓冲区中已经排队的事件数量,而不是自上次重置以来
> +处理过的事件数量。
>
> -成员 ``dropped`` 表示自上次调用
> -``MON_IOCG_STATS`` 以来丢失的事件数量。
> +成员 ``dropped`` 表示自上次调用 ``MON_IOCG_STATS`` 以来丢失的事件数量。
>
> ``MON_IOCT_RING_SIZE``,定义为 ``_IO(MON_IOC_MAGIC, 4)``
>
> -此调用设置缓冲区大小。参数为以字节为单位的缓冲区大小。
> -大小可能会向下取整到下一个块(或页)。
> -如果请求的大小超出该内核的 [未指定] 范围,
> -则调用会失败并返回 ``-EINVAL``。
> +此调用设置缓冲区大小。参数是以字节为单位的缓冲区大小。大小可能会向下取整
> +到下一个块(或页)。如果请求的大小超出当前内核允许的范围,则调用会失败并
> +返回 ``-EINVAL``。
>
> ``MON_IOCQ_RING_SIZE``,定义为 ``_IO(MON_IOC_MAGIC, 5)``
>
> 该调用返回缓冲区当前大小(以字节为单位)。
>
> -``MON_IOCX_GET``,定义为
> -``_IOW(MON_IOC_MAGIC, 6, struct mon_get_arg)``
> -``MON_IOCX_GETX``,定义为
> -``_IOW(MON_IOC_MAGIC, 10, struct mon_get_arg)``
> +``MON_IOCX_GET`` 和 ``MON_IOCX_GETX`` 的定义分别如下:
> +
> +- ``MON_IOCX_GET``:``_IOW(MON_IOC_MAGIC, 6, struct mon_get_arg)``
> +- ``MON_IOCX_GETX``:``_IOW(MON_IOC_MAGIC, 10, struct mon_get_arg)``
>
> -如果内核缓冲区中没有事件,
> -这些调用就会一直等待,直到有事件到达,
> -然后返回第一个事件。
> +如果内核缓冲区中没有事件,这些调用就会一直等待,直到有事件到达,然后返回
> +第一个事件。
> 参数是指向以下结构的指针::
>
> struct mon_get_arg {
> @@ -343,20 +295,18 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
> };
>
>
> -调用前,应填好 ``hdr``、``data`` 和 ``alloc``。
> -调用返回后,``hdr`` 指向的区域中包含下一个事件的结构;
> -如果存在数据,那么数据缓冲区中也会包含相应数据。
> -该事件会从内核缓冲区中移除。
> +调用前,应填好 ``hdr``、``data`` 和 ``alloc``。调用返回后,``hdr`` 指向的
> +内存区域中会写入下一个事件的结构;如果存在数据,数据缓冲区中也会填入相应
> +内容。该事件会从内核缓冲区中移除。
>
> -``MON_IOCX_GET`` 会将 48 字节的数据复制到 ``hdr`` 区域,
> -``MON_IOCX_GETX`` 会复制 64 字节。
> +``MON_IOCX_GET`` 会将 48 字节的数据复制到 ``hdr`` 区域,``MON_IOCX_GETX``
> +会复制 64 字节。
>
> ``MON_IOCX_MFETCH``,定义为
> ``_IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg)``
>
> -当应用程序通过 ``mmap(2)`` 访问缓冲区时,
> -主要使用这个 ioctl。
> -其参数是指向以下结构的指针::
> +应用程序通过 ``mmap(2)`` 访问缓冲区时,主要使用这个 ioctl。其参数是指向
> +以下结构的指针::
>
> struct mon_mfetch_arg {
> uint32_t *offvec; /* 获取的事件偏移向量 */
> @@ -365,41 +315,36 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
> };
>
>
> -该 ioctl 的操作分为三个阶段:
> +这个 ioctl 的流程分为三个阶段:
>
> -首先,从内核缓冲区移除并丢弃最多 ``nflush`` 个事件。
> -实际丢弃的事件数量会写回 ``nflush``。
> +首先,从内核缓冲区移除并丢弃最多 ``nflush`` 个事件。实际丢弃的事件数量会
> +写回 ``nflush``。
>
> -其次,除非伪设备以 ``O_NONBLOCK`` 打开,否则会一直等待,
> -直到缓冲区中出现事件。
> +其次,除非设备以 ``O_NONBLOCK`` 打开,否则会一直等待,直到缓冲区中出现
> +事件。
>
> -第三,将最多 ``nfetch`` 个偏移量提取到 mmap
> -缓冲区,并存入 ``offvec`` 中。
> -实际提取到的事件偏移数量会存回 ``nfetch``。
> +第三,将最多 ``nfetch`` 个偏移量提取到 mmap 缓冲区,并存入 ``offvec`` 中。
> +实际提取到的事件偏移数量会写回 ``nfetch``。
>
> ``MON_IOCH_MFLUSH``,定义为 ``_IO(MON_IOC_MAGIC, 8)``
>
> -此调用从内核缓冲区移除若干事件。
> -其参数为要移除的事件数量。
> -如果缓冲区中的事件少于请求数量,
> -则移除所有事件,且不报告错误。
> -当没有事件时也可使用。
> +此调用从内核缓冲区移除若干事件。其参数是要移除的事件数量。如果缓冲区中的
> +事件少于请求数量,则移除全部现有事件,且不报告错误。即使当前没有事件,也
> +可以调用。
>
> ``FIONBIO``
>
> 如果有需要,将来可能会实现 ``FIONBIO`` ioctl。
>
> -除了 ``ioctl(2)`` 和 ``read(2)`` 之外,
> -二进制 API 的特殊文件也可以用 ``select(2)`` 和
> -``poll(2)`` 轮询。
> -但 ``lseek(2)`` 不起作用。
> +除了 ``ioctl(2)`` 和 ``read(2)`` 之外,二进制 API 对应的特殊文件还可以用
> +``select(2)`` 和 ``poll(2)`` 轮询,但 ``lseek(2)`` 不可用。
>
> * 二进制 API 的内核缓冲区内存映射访问
>
> -基本思想很简单:
> +基本思路很简单:
>
> -准备时,先获取当前大小,再用 ``mmap(2)`` 映射缓冲区。
> -然后执行类似下面伪代码的循环::
> +准备时,先查询当前大小,再用 ``mmap(2)`` 映射缓冲区。之后运行与下面伪代码
> +类似的循环::
>
> struct mon_mfetch_arg fetch;
> struct usbmon_packet *hdr;
> @@ -411,7 +356,7 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
> ioctl(fd, MON_IOCX_MFETCH, &fetch); // 同时处理错误
> nflush = fetch.nfetch; // 完成后要刷新这么多包
> for (i = 0; i < nflush; i++) {
> - hdr = (struct ubsmon_packet *) &mmap_area[vec[i]];
> + hdr = (struct usbmon_packet *) &mmap_area[vec[i]];
> if (hdr->type == '@') // 填充包
> continue;
> caddr_t data = &mmap_area[vec[i]] + 64;
> @@ -421,7 +366,7 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
>
>
>
> -因此,主要思想是每 N 个事件只执行一次 ioctl。
> +因此,这里的核心思路就是每 N 个事件只执行一次 ioctl。
>
> -虽然缓冲区是环形的,但返回的头和数据不会跨越缓冲区末端,
> -因此上面的伪代码无需任何合并操作。
> +虽然缓冲区是环形的,但返回的头部和数据不会跨越缓冲区末端,因此上面的伪代
> +码无需做任何拼接。
> -- 2.34.1
>
^ permalink raw reply
* [PATCH v3] docs/zh_CN: usb: refine translated wording and formatting
From: Kefan Bai @ 2026-06-01 3:39 UTC (permalink / raw)
To: linux-usb, si.yanteng, gregkh, seakeel
Cc: dzm91, corbet, skhan, linux-doc, linux-kernel, doubled, alexs,
Kefan Bai
In-Reply-To: <2026053149-flaky-shallow-2460@gregkh>
Refine the zh_CN USB translations for clarity and consistency.
Improve wording, wrapping, and formatting across the translated
USB documents.
Link: https://lore.kernel.org/r/2026053149-flaky-shallow-2460@gregkh
Suggested-by: Alex Shi <seakeel@gmail.com>
Signed-off-by: Kefan Bai <baikefan@leap-io-kernel.com>
---
v3:
- refine the subject and commit message
- add a Link trailer to the cleanup request thread
- move revision notes below the cut line
v2:
- replace the obsolete FSF mailing address reference in acm.rst
- trim the commit message to satisfy checkpatch
Documentation/translations/zh_CN/usb/CREDITS | 146 ++++---
Documentation/translations/zh_CN/usb/acm.rst | 62 ++-
.../translations/zh_CN/usb/authorization.rst | 79 ++--
.../translations/zh_CN/usb/chipidea.rst | 58 ++-
Documentation/translations/zh_CN/usb/dwc3.rst | 37 +-
Documentation/translations/zh_CN/usb/ehci.rst | 247 +++++-------
.../translations/zh_CN/usb/index.rst | 18 +-
.../translations/zh_CN/usb/usbmon.rst | 363 ++++++++----------
8 files changed, 442 insertions(+), 568 deletions(-)
diff --git a/Documentation/translations/zh_CN/usb/CREDITS b/Documentation/translations/zh_CN/usb/CREDITS
index c133b1a5daff..a37958d139cc 100644
--- a/Documentation/translations/zh_CN/usb/CREDITS
+++ b/Documentation/translations/zh_CN/usb/CREDITS
@@ -10,12 +10,10 @@
:校译:
-简易 Linux USB 驱动的致谢名单:
+Simple Linux USB 驱动项目致谢名单:
-以下人员都为 Linux USB 驱动代码作出了贡献
-(按姓氏字母顺序排列)。我相信这份名单本应
-更长一些,但确实不容易维护。
-如需将自己加入名单,请提交补丁。
+以下人员都为 Linux USB 驱动代码作出过贡献(按姓氏字母顺序排列)。这份名
+单本该更长,只是确实不易维护;如果你也应列名其中,欢迎提交补丁把自己加上。
Georg Acher <acher@informatik.tu-muenchen.de>
David Brownell <dbrownell@users.sourceforge.net>
@@ -41,123 +39,123 @@
特别感谢:
Inaky Perez Gonzalez <inaky@peloncho.fis.ucm.es>
- 感谢他发起了 Linux USB 驱动开发工作,并编写了体量较大的 uusbd
- 驱动中的大部分代码。我们从那项工作中学到了很多。
+ 感谢他牵头开发 Linux USB 驱动,并编写了 uusbd 驱动的大部分代码,我们
+ 从中学到了很多。
NetBSD 和 FreeBSD 的 USB 开发者们
感谢他们加入 Linux USB 邮件列表,提供建议并分享实现经验。
-附加感谢:
- 还要感谢以下公司与个人在硬件、支持、时间投入和开发方面提供的捐赠与帮助
- (摘自 Inaky 驱动原始的 THANKS 文件):
+另外还要感谢:
- 以下公司曾帮助我们开发 Linux USB / UUSBD:
+ 以下公司和个人在硬件、支持、时间和开发工作上给予了帮助(摘自 Inaky
+ 驱动原始的 THANKS 文件):
- - 3Com GmbH 捐赠了一台 ISDN Pro TA,并在技术问题和测试设备方面为我
- 提供支持。没想到能得到这么大的帮助。
+ 以下公司曾为 Linux USB / UUSBD 的开发提供帮助:
- - USAR Systems 向我们提供了他们出色的 USB 评估套件,
- 使我们能够测试 Linux USB 驱动对最新 USB 规范的符合性。
- USAR Systems 认识到保持开放操作系统与时俱进的重要性,
- 并以硬件支持这个项目。感谢!
+ - 3Com GmbH 捐赠了一台 ISDN Pro TA,并在技术问题和测试设备方面提供
+ 了大力支持。
+
+ - USAR Systems 向我们提供了出色的 USB 评估套件,使我们得以测试
+ Linux USB 驱动对最新 USB 规范的符合性。USAR Systems 也认识到,
+ 让开放操作系统跟上时代很重要,因此以硬件支持了这个项目,在此
+ 致谢。
- 感谢英特尔提供的宝贵帮助。
- 我们与 Cherry 合作,使 Linux 成为首个内置 USB 支持的操作系统。
Cherry 是全球最大的键盘制造商之一。
- - CMD Technology, Inc. 慷慨捐赠了一块 CSA-6700 PCI-to-USB
- 控制卡,用于测试 OHCI 实现。
+ - CMD Technology, Inc. 慷慨捐赠了一块 CSA-6700 PCI 转 USB 控制卡,
+ 用于测试 OHCI 实现。
- - 由于他们对我们的支持,Keytronic 可以放心,
- 他们的键盘能卖给至少 300 万 Linux 用户中的一部分。
+ - 有了他们的支持,Keytronic 至少可以确信,其键盘能够销售给 300 万
+ Linux 用户中的一部分。
- - ing büro h doran [http://www.ibhdoran.com]!
- 在欧洲,想给主板买一个 PC 背板 USB 连接器几乎是不可能的
- (我自己做的那个相当糟糕 :))。现在我知道该去哪里买漂亮的 USB
- 配件了!
+ - 特别感谢 ing büro h doran [http://www.ibhdoran.com]。
+ 在欧洲,想给主板配一个 PC 背板 USB 连接器几乎是不可能的(我自己
+ 做的那个效果并不好)。现在我知道该去哪里购买合适的 USB 配件了。
- Genius Germany 捐赠了一只 USB 鼠标,用于测试鼠标启动协议;
- 他们还捐赠了 F-23 数字摇杆和 NetMouse Pro。感谢!
+ 他们还捐赠了 F-23 数字摇杆和 NetMouse Pro,在此致谢。
- - AVM GmbH Berlin 支持我们开发 Linux 下的 AVM ISDN Controller B1 USB 驱动。
- AVM 是领先的 ISDN 控制器制造商,其主动式设计对包括 Linux 在内的
- 所有操作系统平台开放。
+ - AVM GmbH Berlin 支持我们开发 Linux 下的 AVM ISDN Controller B1 USB
+ 驱动。AVM 是领先的 ISDN 控制器制造商,其开放式设计适用于包括
+ Linux 在内的所有操作系统平台。
- - 非常感谢 Y-E Data, Inc 捐赠的 FlashBuster-U USB 软驱,
- 使我们能够测试批量传输代码。
+ - 非常感谢 Y-E Data, Inc 捐赠的 FlashBuster-U USB 软驱,使我们能够测试
+ 批量传输代码。
- 感谢 Logitech 捐赠了一只三轴 USB 鼠标。
- Logitech 负责设计、制造并销售各种人机接口设备,
- 在键盘、鼠标、轨迹球、摄像头、扬声器,以及面向游戏和专业用途的
- 控制设备方面拥有悠久历史和丰富经验。
+ Logitech 负责设计、制造并销售各种人机接口设备,在键盘、鼠标、轨迹球、
+ 摄像头、扬声器,以及面向游戏和专业用途的控制设备方面拥有悠久历史和
+ 丰富经验。
- 作为这些设备广为人知的供应商和销售商,他们捐赠了 USB 鼠标、
- 摇杆和扫描仪,以表明 Linux 的重要性,也让 Logitech 的客户
- 能在自己喜欢的操作系统上获得支持,并让所有 Linux 用户都能使用
- Logitech 以及其他 USB 硬件。
+ 作为这些设备广为人知的供应商和销售商,他们捐赠了 USB 鼠标、摇杆和
+ 扫描仪,以表明 Linux 的重要性,也让 Logitech 的客户能在自己偏爱的
+ 操作系统上获得支持,并让所有 Linux 用户都能使用 Logitech 及其他
+ USB 硬件。
Logitech 也是 1999 年 2 月 11 日维也纳 Linux 大会的官方赞助商,
我们将在会上展示 Linux USB 工作的最新进展。
- - 感谢 CATC 提供 USB Inspector,帮助我们揭开 UHCI 内部实现中
- 那些不为人知的角落。
+ - 感谢 CATC 提供 USB Inspector,帮助我们看到 UHCI 内部实现中的那些
+ 隐秘角落。
- 感谢 Entrega 为开发工作提供 PCI 转 USB 卡、集线器和转换器产品。
- - 感谢 ConnectTech 提供 WhiteHEAT USB 转串口转换器以及相关文档,
- 让这个驱动得以写成。
+ - 感谢 ConnectTech 提供 WhiteHEAT USB 转串口转换器以及相关文档,让
+ 这个驱动得以写成。
- - 感谢 ADMtek 提供 Pegasus 和 Pegasus II 评估板、规格说明,
- 以及驱动开发过程中的宝贵建议。
+ - 感谢 ADMtek 提供 Pegasus 和 Pegasus II 评估板、规格说明,以及驱动
+ 开发过程中的宝贵建议。
- 另外还要感谢以下个人(嘿,顺序不分先后 :))
+ 另外还要感谢以下个人(排名不分先后):
- - Oren Tirosh <orenti@hishome.net>,
- 他非常耐心地听我唠叨各种 USB 疑问,还给了很多很酷的想法。
+ - Oren Tirosh <orenti@hishome.net>
+ 他非常耐心地解答我反复提出的各种 USB 问题,并提供了许多有价值的
+ 想法。
- - Jochen Karrer <karrer@wpfd25.physik.uni-wuerzburg.de>,
- 指出了致命 bug,并给出了宝贵建议。
+ - Jochen Karrer <karrer@wpfd25.physik.uni-wuerzburg.de>
+ 指出了严重问题,并给出了宝贵建议。
- - Edmund Humemberger <ed@atnet.at>,他在公共关系与项目管理方面
- 为 Linux-USB 项目付出了巨大的努力。
+ - Edmund Humemberger <ed@atnet.at>,他在公共关系与项目管理方面为
+ Linux-USB 项目付出了巨大的努力。
- - Alberto Menegazzi <flash@flash.iol.it> 正在着手编写 UUSBD 文档,加油!
+ - Alberto Menegazzi <flash@flash.iol.it> 正在着手编写 UUSBD 文档。
- - Ric Klaren <ia_ric@cs.utwente.nl> 编写了很好的入门文档,
- 与 Alberto 的作品形成良性竞争:)。
+ - Ric Klaren <ia_ric@cs.utwente.nl> 编写了很好的入门文档,与
+ Alberto 的作品形成了良性互补。
- - Christian Groessler <cpg@aladdin.de>,感谢他在那些棘手细节上的帮助。
+ - Christian Groessler <cpg@aladdin.de>,感谢他在诸多复杂细节上的帮助。
- - Paul MacKerras 改进了 OHCI 实现,推动了对 iMac 的支持,
- 并提供了大量的改进意见。
+ - Paul MacKerras 改进了 OHCI 实现,推动了对 iMac 的支持,并提供了
+ 大量的改进意见。
- - Fernando Herrera <fherrera@eurielec.etsit.upm.es>
- 负责撰写、维护并不断补充那份期待已久、独一无二又精彩的
- UUSBD FAQ!太棒了!
+ - Fernando Herrera <fherrera@eurielec.etsit.upm.es> 负责撰写、维护并
+ 持续补充那份期待已久、内容翔实的 UUSBD FAQ。
- - Rasca Gmelch <thron@gmx.de> 重新启用了 raw 驱动,
- 指出了一些错误,并启动了 uusbd-utils 软件包。
+ - Rasca Gmelch <thron@gmx.de> 重新启用了 raw 驱动,指出了一些错误,并
+ 启动了 uusbd-utils 软件包。
- - Peter Dettori <dettori@ozy.dec.com>,像疯了一样挖掘 bug,
- 还提出了很多很酷的建议,太棒了!
+ - Peter Dettori <dettori@ozy.dec.com>,持续发现问题,并提出了许多
+ 有价值的建议。
- - 自由软件与 Linux 社区的所有成员,包括 FSF、GNU 项目、
- MIT X 联盟、TeX 社区等等,谢谢你们!
+ - 自由软件与 Linux 社区的所有成员,包括 FSF、GNU 项目、MIT X 联盟、
+ TeX 社区等,在此一并致谢。
- - 特别感谢 Richard Stallman 创造了 Emacs!
+ - 特别感谢 Richard Stallman 创造了 Emacs。
- - 感谢 linux-usb 邮件列表的所有成员,读了那么多邮件——不开玩笑了,
- 感谢你们提出的所有建议!
+ - 感谢 linux-usb 邮件列表的所有成员阅读了大量邮件,并提出了诸多
+ 建议。
- 感谢 USB Implementers Forum 成员们的帮助与支持。
- - Nathan Myers <ncm@cantrip.org>,感谢他的建议!
- (希望你喜欢 Cibeles 的派对。)
+ - Nathan Myers <ncm@cantrip.org>,感谢他的建议。(也希望你喜欢
+ Cibeles 的派对。)
- - 感谢 Linus Torvalds 创建、开发并管理 Linux。
+ - 感谢 Linus Torvalds 创立、开发并维护 Linux。
- Mike Smith、Craig Keithley、Thierry Giron 和 Janet Schank
- 感谢他们让我认识到标准 USB 集线器其实也没那么“标准”,
- 这有助于我们在标准集线器驱动中加入厂商特定的特殊处理。
+ 感谢他们让我认识到,标准 USB 集线器其实一点也不“标准”;也正因
+ 如此,我们才能在标准集线器驱动中加入厂商特定的处理。
diff --git a/Documentation/translations/zh_CN/usb/acm.rst b/Documentation/translations/zh_CN/usb/acm.rst
index 51d6eb8f5660..b2e35787af45 100644
--- a/Documentation/translations/zh_CN/usb/acm.rst
+++ b/Documentation/translations/zh_CN/usb/acm.rst
@@ -20,33 +20,26 @@ Linux ACM 驱动 v0.16
0. 免责声明
~~~~~~~~~~~
-本程序是自由软件;你可以在自由软件基金会发布的
-GNU 通用公共许可证第 2 版,或者(按你的选择)
-任何后续版本的条款下重新发布和/或修改它。
+本程序是自由软件;你可以在自由软件基金会发布的 GNU 通用公共许可证第 2 版,
+或者(按你的选择)任何后续版本的条款下重新发布和/或修改它。
-发布本程序是希望它能发挥作用,但它不附带任何担保;
-甚至不包括对适销性或特定用途适用性的默示担保。
-详情见 GNU 通用公共许可证。
+发布本程序是希望它能发挥作用,但它不附带任何担保;甚至不包括对适销性或
+特定用途适用性的默示担保。详情见 GNU 通用公共许可证。
-你应该已经随本程序收到了 GNU 通用公共许可证的副本;
-如果没有,请致信:Free Software Foundation, Inc., 59
-Temple Place, Suite 330, Boston, MA 02111-1307 USA。
+你应该已经随本程序收到了 GNU 通用公共许可证的副本;如果没有,请参见
+COPYING 文件。
-如需联系作者,可发送电子邮件至 vojtech@suse.cz,
-或邮寄至:
-Vojtech Pavlik, Ucitelska 1576, Prague 8,
-182 00, Czech Republic。
+如需联系作者,可发送电子邮件至 vojtech@suse.cz,或邮寄至:
+Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00, Czech Republic。
-为方便起见,软件包中已附带 GNU 通用公共许可证
-第 2 版:见 COPYING 文件。
+为方便起见,软件包中已附带 GNU 通用公共许可证第 2 版:见 COPYING 文件。
1. 使用方法
~~~~~~~~~~~
-``drivers/usb/class/cdc-acm.c`` 驱动可用于符合 USB
-通信设备类抽象控制模型(USB CDC ACM)规范的
-USB 调制解调器和 USB ISDN 终端适配器。
+``drivers/usb/class/cdc-acm.c`` 驱动适用于符合 USB 通信设备类抽象控制模型
+(USB CDC ACM)规范的 USB 调制解调器和 USB ISDN 终端适配器。
-许多调制解调器支持此驱动,以下是我所知道的一些型号:
+已知支持该驱动的调制解调器包括:
- 3Com OfficeConnect 56k
- 3Com Voice FaxModem Pro
@@ -56,17 +49,16 @@ USB 调制解调器和 USB ISDN 终端适配器。
- Compaq 56k FaxModem
- ELSA Microlink 56k
-我知道有一款 ISDN 终端适配器可以与 ACM 驱动一起使用:
+已知有一款 ISDN 终端适配器可以配合 ACM 驱动使用:
- 3Com USR ISDN Pro TA
-一些手机也可以通过 USB 连接。
-我知道以下机型可以正常工作:
+一些手机也可以通过 USB 连接,已知可用的机型有:
- SonyEricsson K800i
-遗憾的是,许多调制解调器和大多数 ISDN TA
-都使用专有接口,因此无法与此驱动配合工作。
+遗憾的是,很多调制解调器和大多数 ISDN TA 都使用专有接口,因此无法配合该
+驱动工作。
购买前请先确认设备是否符合 ACM 规范。
要使用这些调制解调器,需要加载以下模块::
@@ -75,15 +67,13 @@ USB 调制解调器和 USB ISDN 终端适配器。
uhci-hcd.ko ohci-hcd.ko or ehci-hcd.ko
cdc-acm.ko
-之后就应该可以访问这些调制解调器了。
-应当可以使用 ``minicom``、``ppp`` 和 ``mgetty``
-与它们通信。
+之后就应该能访问这些调制解调器,并用 ``minicom``、``ppp`` 和
+``mgetty`` 与它们通信。
2. 验证驱动是否正常工作
~~~~~~~~~~~~~~~~~~~~~~~
-第一步是检查 ``/sys/kernel/debug/usb/devices``,
-其内容应该类似如下::
+第一步是查看 ``/sys/kernel/debug/usb/devices``,其内容应当类似下面这样::
T: Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
B: Alloc= 0/900 us ( 0%), #Int= 0, #Iso= 0
@@ -112,11 +102,10 @@ USB 调制解调器和 USB ISDN 终端适配器。
E: Ad=85(I) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 64 Ivl= 0ms
-这三行的存在很关键(以及 ``Cls=`` 字段里出现的
-``comm`` 和 ``data`` 类);它说明这是一个 ACM
-设备。``Driver=acm`` 表示该设备正在使用 acm 驱动。
-如果只看到 ``Cls=ff(vend.)``,那就无能为力了:
-这说明你手上的设备使用的是厂商专有接口::
+关键是看这三行,再结合 ``Cls=`` 字段里出现的 ``comm`` 和 ``data`` 类,就
+能判断这是一台 ACM 设备。``Driver=acm`` 表示该设备正在使用 acm 驱动。如果
+只看到 ``Cls=ff(vend.)``,那就说明这台设备使用的是厂商专有接口,ACM 驱动
+无法处理::
D: Ver= 1.00 Cls=02(comm.) Sub=00 Prot=00 MxPS= 8 #Cfgs= 2
I: If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=acm
@@ -142,6 +131,5 @@ USB 调制解调器和 USB ISDN 终端适配器。
usb.c: acm driver claimed interface c7b5f3f8
usb.c: acm driver claimed interface c7691fa0
-如果以上都正常,请启动 ``minicom``,
-把它配置为连接 ``ttyACM`` 设备,然后
-尝试输入 ``at``。如果返回 ``OK``,说明一切工作正常。
+如果这些都正常,请启动 ``minicom``,把它配置为连接到 ``ttyACM`` 设备,然后
+尝试输入 ``at``。如果返回 ``OK``,说明驱动工作正常。
diff --git a/Documentation/translations/zh_CN/usb/authorization.rst b/Documentation/translations/zh_CN/usb/authorization.rst
index 2aa311f6b967..e2ff2282bd03 100644
--- a/Documentation/translations/zh_CN/usb/authorization.rst
+++ b/Documentation/translations/zh_CN/usb/authorization.rst
@@ -10,34 +10,32 @@
:校译:
-=============================
-授权或禁止 USB 设备连接到系统
-=============================
+===========================
+允许或禁止 USB 设备接入系统
+===========================
版权 (C) 2007 Inaky Perez-Gonzalez
<inaky@linux.intel.com> 英特尔公司
-此功能允许你控制 USB 设备是否可以在系统中使用。
-借助它,你可以完全通过用户空间实现对 USB 设备的锁定。
+有了这项功能,你就可以控制 USB 设备是否允许在系统中使用,并把 USB 设备锁
+定机制完全放在用户空间实现。
-目前,当插入一个 USB 设备时,系统会对其进行配置,
-其接口会立即向用户开放。
-有了这项改动,只有在 root 授权设备完成配置后,
-设备才可被使用。
+目前,USB 设备一接入系统就会被立即配置,其接口也会立刻向用户开放。引入
+这项机制后,只有在 root 明确授权后,设备才会完成配置并允许使用。
用法
====
-授权设备接入::
+授权设备接入系统::
$ echo 1 > /sys/bus/usb/devices/DEVICE/authorized
-取消对设备的授权::
+取消设备授权::
$ echo 0 > /sys/bus/usb/devices/DEVICE/authorized
-将新连接到 ``hostX`` 的设备默认设为未授权(即锁定)::
+将连接到 ``hostX`` 的新设备默认设为未授权(即锁定)::
$ echo 0 > /sys/bus/usb/devices/usbX/authorized_default
@@ -45,15 +43,14 @@
$ echo 1 > /sys/bus/usb/devices/usbX/authorized_default
-默认情况下,所有 USB 设备都是授权的。
-向 ``authorized_default`` 属性写入 ``2`` 会使内核
-默认只授权连接到内部 USB 端口的设备。
+默认情况下,所有 USB 设备都是授权的。向 ``authorized_default`` 属性写入
+``2`` 会使内核默认只授权连接到内部 USB 端口的设备。
-系统锁定示例(比较粗糙)
-------------------------
+系统锁定示例(简化版)
+----------------------
-假设你想实现一个锁定功能,只允许类型为 XYZ 的设备接入
-(例如某台带有外露 USB 端口的自助服务终端)::
+假设你想做一个锁定机制,只允许 XYZ 类型的设备接入(例如一台带有外露 USB
+端口的自助终端)::
启动系统
rc.local ->
@@ -63,21 +60,18 @@
echo 0 > $host/authorized_default
done
-给 udev 挂一个脚本,用于处理新插入的 USB 设备::
+为 udev 配置一个脚本,用于处理新插入的 USB 设备::
if device_is_my_type $DEV
then
echo 1 > $device_path/authorized
- done
+ fi
-``device_is_my_type()`` 才是锁定方案真正见功夫的
-地方。仅仅检查 class、type 和 protocol 是否匹配
-某个值,是你能做出的最糟糕的安全验证之一;
-对想绕过它的人来说,这反而是最容易利用的方案。
-如果你需要真正安全的办法,那就该使用加密、
-证书认证之类的机制。把 USB 存储设备当作
-“钥匙”的一个简单例子可以是::
+锁定方案是否可靠,关键全在 ``device_is_my_type()`` 的实现。仅仅检查
+class、type 和 protocol 是否匹配,几乎是最差的一种安全校验方式;对想绕过
+它的人来说,这种做法反而最容易伪造。如果你真要做安全控制,就该使用加密、
+证书认证之类的机制。把 USB 存储设备当作“钥匙”的一个简单示例可以写成::
function device_is_my_type()
{
@@ -87,7 +81,7 @@
sum=$(md5sum /mntpoint/.signature)
if [ $sum = $(cat /etc/lockdown/keysum) ]
then
- echo "We are good, connected"
+ echo "验证通过,已连接"
umount /mntpoint
# 再做一些额外处理,让其他人也能使用它
else
@@ -96,17 +90,16 @@
}
-当然,这个例子很粗糙;真正要做的话,
-你会想用基于 PKI 的证书校验,这样就不必依赖
-共享密钥之类的东西。不过你应该已经明白意思了。
-任何拿到设备仿真工具包的人都能伪造描述符和设备信息。
-别信这个。
+当然,这个例子仍然比较简化。真正落地时,更合适的做法是使用基于 PKI 的证
+书校验,这样就不必依赖共享密钥之类的机制了。不过意思已经很清楚:任何拿到
+设备仿真工具包的人,都能伪造描述符和设备信息,所以别把这类检查当成真正
+的安全保障。
接口授权
--------
-也有类似的方法用于允许或拒绝特定 USB 接口。
-这使得你可以只阻止某个 USB 设备中的部分接口。
+也可以用类似的方法允许或拒绝特定的 USB 接口。这样一来,你只需要阻止某个
+USB 设备中的部分接口。
授权接口::
@@ -126,14 +119,12 @@
$ echo 0 > /sys/bus/usb/devices/usbX/interface_authorized_default
-默认情况下,
-``interface_authorized_default`` 位为 ``1``,
-因此所有接口默认都处于已授权状态。
+默认情况下,``interface_authorized_default`` 位为 ``1``,因此所有接口默认
+都会处于授权状态。
注意:
- 如果把一个先前未授权的接口改为已授权,
- 则必须通过将 ``INTERFACE`` 写入 ``/sys/bus/usb/drivers_probe``
- 来手动触发驱动探测。
+ 如果把一个先前未授权的接口改为已授权,则必须通过将 ``INTERFACE`` 写入
+ ``/sys/bus/usb/drivers_probe`` 来手动触发驱动探测。
-对于需要多个接口的驱动程序,应先授权所有必需接口,
-然后再触发驱动探测。这样做可以避免副作用。
+对于需要多个接口的驱动程序,应先授权所有必需接口,然后再触发驱动探测。
+这样做可以避免副作用。
diff --git a/Documentation/translations/zh_CN/usb/chipidea.rst b/Documentation/translations/zh_CN/usb/chipidea.rst
index ea0dc3043189..011fb16f3350 100644
--- a/Documentation/translations/zh_CN/usb/chipidea.rst
+++ b/Documentation/translations/zh_CN/usb/chipidea.rst
@@ -17,18 +17,17 @@ ChipIdea 高速双角色控制器驱动
1. 如何测试 OTG FSM(HNP 和 SRP)
---------------------------------
-下面以两块 Freescale i.MX6Q Sabre SD 开发板为例,
-说明如何通过 sysfs 输入文件演示 OTG 的 HNP 和 SRP 功能。
+下面以两块 Freescale i.MX6Q Sabre SD 开发板为例,演示如何通过 sysfs 属性
+测试 OTG 的 HNP 和 SRP 功能。
-1.1 如何使能 OTG FSM
+1.1 如何启用 OTG FSM
--------------------
1.1.1 在 ``menuconfig`` 中选择 ``CONFIG_USB_OTG_FSM``,并重新编译内核
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-重新构建内核镜像和模块。如果想查看 OTG FSM 的
-一些内部变量,可以挂载 ``debugfs``;其中有两个文件
-可以显示 OTG FSM 变量以及部分控制器寄存器的值::
+重新构建内核镜像和模块。如果想查看 OTG FSM 的内部变量,可以挂载
+``debugfs``;其中有两个文件,分别显示 OTG FSM 的变量和部分控制器寄存器值::
cat /sys/kernel/debug/ci_hdrc.0/otg
cat /sys/kernel/debug/ci_hdrc.0/registers
@@ -44,11 +43,10 @@ ChipIdea 高速双角色控制器驱动
1.2 测试步骤
------------
-1) 给两块 Freescale i.MX6Q Sabre SD 开发板上电,
- 并加载 gadget 类驱动(例如 ``g_mass_storage``)。
+1) 给两块 Freescale i.MX6Q Sabre SD 开发板上电,并加载 gadget 类驱动(例如
+ ``g_mass_storage``)。
-2) 用 USB 线连接两块开发板:
- 一端是 micro A 插头,另一端是 micro B 插头。
+2) 用 USB 线连接两块开发板:一端是 micro A 插头,另一端是 micro B 插头。
插入 micro A 插头的一端是 A 设备,它应枚举另一端的 B 设备。
@@ -66,32 +64,28 @@ ChipIdea 高速双角色控制器驱动
echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
- 或者,通过引入 HNP 轮询,B 端主机可以知道
- A 端外设希望切换为主机角色,因此这次角色切换
- 也可以通过 A 端外设响应 B 端主机的轮询,
- 在 A 侧触发。
- 这可以通过在 A 设备上执行下面的命令来完成::
+ 或者,也可以借助 HNP 轮询,让 B 端主机知道 A 端外设希望切回主机角色。
+ 因此,这次切换也可以由 A 侧触发,也就是由 A 端外设响应 B 端主机的轮询
+ 来完成。可在 A 设备上执行下面的命令::
echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
A 设备应切回主机角色并枚举 B 设备。
-5) 拔掉 B 设备(拔掉 micro B 插头),
- 并在 10 秒内重新插入;
+5) 拔掉 B 设备(拔掉 micro B 插头),并在 10 秒内重新插入。
A 设备应重新枚举 B 设备。
-6) 拔掉 B 设备(拔掉 micro B 插头),
- 并在 10 秒后重新插入;
+6) 拔掉 B 设备(拔掉 micro B 插头),并在 10 秒后重新插入。
A 设备不应重新枚举 B 设备。
- 如果 A 设备希望使用总线:
+ 如果 A 设备还想继续使用总线:
在 A 设备上执行::
echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_drop
echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
- 如果 B 设备希望使用总线:
+ 如果 B 设备想使用总线:
在 B 设备上执行::
@@ -111,40 +105,38 @@ ChipIdea 高速双角色控制器驱动
echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
- A 设备应恢复 USB 总线并枚举 B 设备。
+ A 设备应恢复 USB 总线,并枚举 B 设备。
1.3 参考文档
------------
-《On-The-Go and Embedded Host Supplement
-to the USB Revision 2.0 Specification
+《On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Specification
July 27, 2012 Revision 2.0 version 1.1a》
2. 如何将 USB 用作系统唤醒源
----------------------------
-下面是在 i.MX6 平台上把 USB 用作系统唤醒源的示例。
+下面给出在 i.MX6 平台上将 USB 用作系统唤醒源的示例。
-2.1 使能核心控制器的唤醒功能::
+2.1 启用核心控制器的唤醒功能::
echo enabled > /sys/bus/platform/devices/ci_hdrc.0/power/wakeup
-2.2 使能 glue 层的唤醒功能::
+2.2 启用 glue 层的唤醒功能::
echo enabled > /sys/bus/platform/devices/2184000.usb/power/wakeup
-2.3 使能 PHY 的唤醒功能(可选)::
+2.3 启用 PHY 的唤醒功能(可选)::
echo enabled > /sys/bus/platform/devices/20c9000.usbphy/power/wakeup
-2.4 使能根集线器的唤醒功能::
+2.4 启用根集线器的唤醒功能::
echo enabled > /sys/bus/usb/devices/usb1/power/wakeup
-2.5 使能相关设备的唤醒功能::
+2.5 启用相关设备的唤醒功能::
echo enabled > /sys/bus/usb/devices/1-1/power/wakeup
-如果系统只有一个 USB 端口,
-而你希望在该端口上启用 USB 唤醒功能,
-可以使用下面的脚本::
+如果系统只有一个 USB 端口,而你希望在该端口上启用 USB 唤醒功能,可以使用
+下面的脚本::
for i in $(find /sys -name wakeup | grep usb);do echo enabled > $i;done;
diff --git a/Documentation/translations/zh_CN/usb/dwc3.rst b/Documentation/translations/zh_CN/usb/dwc3.rst
index 3468ce50c5ba..9584cbbf6d03 100644
--- a/Documentation/translations/zh_CN/usb/dwc3.rst
+++ b/Documentation/translations/zh_CN/usb/dwc3.rst
@@ -18,46 +18,43 @@ DWC3 驱动
待办
~~~~
-阅读时如果想顺手认领点任务,可以从下面挑一项 :)
+如果你愿意接手其中一项任务,可以从下面选择:
- 将中断处理程序改为每个端点各自使用线程化 IRQ
- 事实证明,有些 DWC3 命令大约需要 ``~1 ms`` 才能完成。
- 当前代码会一直自旋等待命令完成,这种设计并不好。
+ 实践表明,某些 DWC3 命令大约需要 ``~1 ms`` 才能完成。当前代码会一直自旋
+ 等待命令完成,这并不是好办法。
实现思路:
- - DWC 核心实现了一个按端点对中断进行解复用的 IRQ 控制器。
- 中断号在探测(``probe``)阶段分配,并归属于该设备。
- 如果硬件通过 ``MSI`` 为每个端点提供独立中断,
- 那么这个“虚拟”IRQ 控制器就可以被真实的端点中断取代。
+ - DWC 核心实现了一个按端点分发中断的 IRQ 控制器。中断号在探测
+ (``probe``)阶段分配,并归属于该设备。如果硬件通过 ``MSI`` 为每个
+ 端点提供独立中断,那么这个“虚拟”IRQ 控制器就可以被真实的端点中断
+ 取代。
- - 在调用 ``usb_ep_enable()`` 时请求并分配中断资源,
- 在调用 ``usb_ep_disable()`` 时释放中断资源。
- 最坏情况下需要 32 个中断,最少是 ``ep0/1`` 的两个中断。
+ - 在调用 ``usb_ep_enable()`` 时请求并分配中断资源,在调用
+ ``usb_ep_disable()`` 时释放中断资源。最坏情况下需要 32 个中断,最少是
+ ``ep0/1`` 的两个中断。
- ``dwc3_send_gadget_ep_cmd()`` 将在 ``wait_for_completion_timeout()``
中休眠,直到命令完成。
- 中断处理程序分为以下几个部分:
- 设备级主中断处理程序
- 遍历每个事件,并对其调用 ``generic_handle_irq()``。
- 从 ``generic_handle_irq()`` 返回后,确认事件计数器,使中断最终消失。
+ 遍历每个事件,并调用 ``generic_handle_irq()`` 处理。返回后再确认
+ 事件计数器,让中断最终消失。
- 设备级线程化处理程序
无。
- 端点中断的主处理程序
- 读取事件并尽量处理它。凡是需要睡眠的操作都交给线程处理。
- 事件保存在每个端点的数据结构中。
- 还要注意,一旦把某项工作交给线程处理,
- 就不要再在主处理程序里处理它,
- 以免出现优先级反转之类的问题。
+ 读取事件并尽量处理;凡是需要睡眠的操作都交给线程处理。事件保存在
+ 每个端点的数据结构中。一旦某项工作已经交给线程处理,主处理程序里就
+ 不要再碰它,以免出现优先级反转之类的问题。
- 端点中断的线程化处理程序
处理剩余的端点工作,这些工作可能会睡眠,例如等待命令完成。
- 延迟:
+ 延迟:
- 不应增加延迟,因为中断线程具有较高优先级,
- 会在普通用户态任务之前运行
+ 不应增加额外延迟,因为中断线程优先级较高,会在普通用户任务之前运行
(除非用户更改了调度优先级)。
diff --git a/Documentation/translations/zh_CN/usb/ehci.rst b/Documentation/translations/zh_CN/usb/ehci.rst
index e05e493a30d3..c4c52303b13e 100644
--- a/Documentation/translations/zh_CN/usb/ehci.rst
+++ b/Documentation/translations/zh_CN/usb/ehci.rst
@@ -14,45 +14,37 @@
EHCI 驱动
=========
-2002年12月27日
+2002 年 12 月 27 日
-EHCI 驱动用于通过支持 USB 2.0 的主机控制器
-硬件与高速 USB 2.0 设备通信。USB 2.0 兼容
-USB 1.1 标准,它定义了三种传输速率:
+EHCI 驱动用于借助支持 USB 2.0 的主机控制器,与高速 USB 2.0 设备通信。USB
+2.0 向下兼容 USB 1.1,并定义了三种传输速率:
- “高速”(High Speed)480 Mbit/sec(60 MByte/sec)
- “全速”(Full Speed)12 Mbit/sec(1.5 MByte/sec)
- “低速”(Low Speed)1.5 Mbit/sec
-USB 1.1 仅支持全速与低速。
-高速设备可以在 USB 1.1 系统上使用,
-但速度会降到 USB 1.1 的速率。
+USB 1.1 仅支持全速与低速。高速设备可以在 USB 1.1 系统上使用,但速度会
+降到 USB 1.1 的速率。
-USB 1.1 设备也可以在 USB 2.0 系统上使用。当它们
-插入 EHCI 控制器时,会被交由 USB 1.1 的伴随
-(companion)控制器处理,该控制器通常是 OHCI 或 UHCI。
+USB 1.1 设备也可以在 USB 2.0 系统上使用。当它们插入 EHCI 控制器时,会交给
+USB 1.1 的伴随(companion)控制器处理,该控制器通常是 OHCI 或 UHCI。
-当 USB 1.1 设备插入 USB 2.0 集线器时,它们通过
-集线器中的事务转换器(Transaction Translator,TT)
-与 EHCI 控制器交互,该转换器将低速或全速事务转换为
-高速分割事务,从而避免浪费传输带宽。
+当 USB 1.1 设备插入 USB 2.0 集线器时,它们会通过集线器里的事务转换器
+(Transaction Translator,TT)与 EHCI 控制器通信。该转换器会把低速或全
+速事务转换为高速分割事务,从而避免浪费传输带宽。
-截至本文撰写时,该驱动已在以下 EHCI 实现上成功运行
-(按字母顺序):Intel、NEC、Philips 和 VIA。
-其他供应商的 EHCI 实现正在陆续问世;
-预计该驱动在这些实现上也可正常运行。
+截至本文撰写时,该驱动已在以下 EHCI 实现上成功运行(按字母顺序):
+Intel、NEC、Philips 和 VIA。随着其他供应商的 EHCI 实现陆续问世,预计该
+驱动在那些实现上也能正常运行。
-自 2001 年年中起,usb-storage 设备就已可用
-(在 2.4 版该驱动上速度相当不错),
-集线器则直到 2001 年底才开始可用,而其他类型的高速设备
-似乎要等到更多系统内置 USB 2.0 后才会出现。
-这类新系统从 2002 年初开始上市,
-并在 2002 年下半年变得更加常见。
+自 2001 年年中起,usb-storage 设备就已可用(在 2.4 版该驱动上速度表现相当
+不错),集线器则直到 2001 年底才开始可用。其他类型的高速设备似乎要等到
+更多系统内置 USB 2.0 后才会出现。这类新系统从 2002 年初开始上市,并在
+2002 年下半年变得更加常见。
-注意,USB 2.0 支持并不只是 EHCI 本身。
-它还需要对 Linux-USB 核心 API 作出其他修改,
-包括 hub 驱动;不过这些修改并不需要真正改变
-暴露给 USB 设备驱动的基本 ``usbcore`` API。
+注意,USB 2.0 的支持并不只靠 EHCI 本身。它还需要对 Linux-USB 核心 API
+做其他修改,包括 hub 驱动;不过这些修改并不需要真正改变向 USB 设备驱动
+暴露的基本 ``usbcore`` API。
- David Brownell
<dbrownell@users.sourceforge.net>
@@ -61,58 +53,46 @@ USB 1.1 设备也可以在 USB 2.0 系统上使用。当它们
功能
====
-该驱动会定期在 x86 硬件上进行测试,
-也已在 PPC 硬件上使用,因此大小端问题应当已经解决。
-因此可以认为,它已经处理好了所有必要的 PCI 细节,
-所以即便在 DMA 映射有些特殊的系统上,
-I/O 也应能正常运行。
+该驱动长期在 x86 硬件上接受测试,也在 PPC 平台上使用过,因此大小端问题应
+该都已解决。再加上各种必要的 PCI 细节都已处理妥当,即便在 DMA 映射较特
+殊的系统上,I/O 也应能正常工作。
传输类型
--------
-截至本文撰写时,该驱动应当已经能够很好地处理
-所有控制传输、批量传输和中断传输,
-包括通过 USB 2.0 集线器中的事务转换器
-与 USB 1.1 设备通信;但仍可能存在 bug。
+截至本文撰写时,该驱动应当已经能够稳定处理所有控制传输、批量传输和中断传
+输,包括经由 USB 2.0 集线器里的事务转换器访问 USB 1.1 设备;不过仍可能
+存在 bug。
-高速等时(ISO)传输支持也已可用,但截至本文撰写时,
-还没有 Linux 驱动使用这项支持。
+高速等时(ISO)传输支持也已可用,不过截至本文撰写时,还没有 Linux 驱动真
+正使用它。
-目前尚不支持通过事务转换器实现全速等时传输。
-需要注意,ISO 传输的 split transaction 支持
-与高速 ISO 传输几乎无法共用代码,
-因为 EHCI 用不同的数据结构表示它们。
-因此,目前大多数 USB 音频和视频设备
-还不能通过高速总线连接使用。
+目前尚不支持通过事务转换器实现全速等时传输。需要注意,ISO 传输的分割
+事务支持与高速 ISO 传输几乎无法共用代码,因为 EHCI 用不同的数据结构表示
+它们。因此,目前大多数 USB 音频和视频设备还无法在高速总线上使用。
驱动行为
--------
-所有类型的传输都可以排队。
-这意味着来自一个接口驱动的控制传输
-(或通过 usbfs 发出的控制传输)不会干扰
-另一个驱动的控制传输,而且中断传输可以使用 1 帧的周期,
-而不必担心中断处理开销导致的数据丢失。
+所有类型的传输都可以排队提交。这意味着某个接口驱动发出的控制传输(或经由
+usbfs 提交的控制传输)不会干扰其他驱动的控制传输,而中断传输可以按 1 帧
+周期运行,不必担心中断处理开销导致数据丢失。
-EHCI 根集线器代码会将 USB 1.1 设备移交给其伴随控制器。
-该驱动不需要了解那些驱动的任何细节;
-一个原本就能正常工作的 OHCI 或 UHCI 驱动,
-并不会因为 EHCI 驱动也存在而需要更改。
+EHCI 根集线器代码会将 USB 1.1 设备交给其伴随控制器处理。该驱动无需了解
+那些驱动的任何细节;一个原本就能正常工作的 OHCI 或 UHCI 驱动,也不会因为
+EHCI 驱动存在而需要修改。
-电源管理方面还有一些问题;
-当前挂起/恢复的行为还不完全正确。
+电源管理方面仍有一些问题;当前挂起/恢复行为还不完全正确。
-此外,在调度周期性事务
-(中断和等时传输)时还采取了一些简化处理。
-这些简化会限制可调度的周期性事务数量,
-并且无法使用小于一帧的轮询间隔。
+此外,在调度周期性事务(中断和等时传输)时还采取了一些简化处理。这些
+简化会限制可调度的周期性事务数量,并且无法使用小于一帧的轮询间隔。
使用方式
========
-假设有一个 EHCI 控制器(位于 PCI 卡或主板上),
-并且已将此驱动编译为模块,可这样加载::
+假设系统中有一个 EHCI 控制器(位于 PCI 卡或主板上),并且此驱动是以模块形
+式编译的,那么可以这样加载::
# modprobe ehci-hcd
@@ -120,27 +100,24 @@ EHCI 根集线器代码会将 USB 1.1 设备移交给其伴随控制器。
# rmmod ehci-hcd
-还应加载一个伴随控制器驱动,
-例如 ``ohci-hcd`` 或 ``uhci-hcd``。
-如果 EHCI 驱动出现任何问题,只需卸载它的模块,
-随后该伴随控制器驱动就会接手
-此前由 EHCI 驱动处理的所有设备
-(但速度会降低)。
+还应加载一个伴随控制器驱动,例如 ``ohci-hcd`` 或 ``uhci-hcd``。如果 EHCI
+驱动出了问题,只要卸载它的模块,伴随控制器驱动就会接管此前由 EHCI 驱动处
+理的全部设备(只是速度会降低)。
模块参数(传给 ``modprobe``)包括:
log2_irq_thresh(默认值 0):
- 默认中断延迟的 log2 值,单位是微帧。默认值 0 表示 1 个微帧
- (125 微秒)。最大值 6 表示 2^6 = 64 个微帧。
+ 默认中断延迟的 log2 值,单位为微帧。默认值 0 表示 1 个微帧
+ (125 微秒),最大值 6 表示 2^6 = 64 个微帧。
该值控制 EHCI 控制器发出中断的频率。
-如果在 2.5 内核上使用此驱动,并且启用了 USB 调试支持,
-则会在任一 EHCI 控制器的 ``sysfs`` 目录中看到三个文件:
+如果你在 2.5 内核上使用此驱动,并且启用了 USB 调试支持,那么任一 EHCI 控
+制器对应的 ``sysfs`` 目录下都会看到三个文件:
``async``
转储异步调度,用于控制传输和批量传输。它会显示每个活动的 ``qh``
以及待处理的 ``qtd``,通常每个 ``urb`` 对应一个 ``qtd``。
- (可以在 ``usb-storage`` 做磁盘 I/O 时看它;顺便观察请求队列!)
+ (可以在 ``usb-storage`` 执行磁盘 I/O 时查看;也可顺便观察请求队列。)
``periodic``
转储周期性调度,用于中断传输和等时传输。不显示 ``qtd``。
@@ -151,111 +128,81 @@ EHCI 根集线器代码会将 USB 1.1 设备移交给其伴随控制器。
这些文件的内容有助于定位驱动问题。
-设备驱动通常不需要关心自己是否运行在 EHCI 之上,
-但它们可能想检查
-``usb_device->speed == USB_SPEED_HIGH``。
-高速设备能做到全速(或低速)设备做不到的事,
-例如高带宽的周期性传输(中断或 ISO 传输)。
-另外,设备描述符中的某些值
-(例如周期性传输的轮询间隔)
-在高速模式下使用不同的编码方式。
+设备驱动通常不需要关心自己是否运行在 EHCI 之上,但有时可能会想检查
+``usb_device->speed == USB_SPEED_HIGH``。高速设备能做到全速(或低速)设备
+做不到的事,例如高带宽的周期性传输(中断或 ISO 传输)。另外,设备描述符
+中的某些值(例如周期性传输的轮询间隔)在高速模式下使用不同的编码方式。
-不过,一定要让设备驱动经过 USB 2.0 集线器的测试。
-当使用事务转换器时,这些集线器报告某些故障
-(例如断开连接)的方式会不同;
-已经见过一些驱动在遇到与 OHCI 或 UHCI
-所报告的不同故障时表现不佳。
+不过,设备驱动一定要在 USB 2.0 集线器后面测一遍。使用事务转换器时,这些
+集线器报告某些故障(例如断开连接)的方式会有所不同;已经见过一些驱动在
+遇到与 OHCI 或 UHCI 不同的故障时表现不佳。
性能
====
-USB 2.0 吞吐量主要受两个因素制约:
-主机控制器处理请求的速度,以及设备响应这些请求的速度。
-480 Mbit/sec 的“原始传输率”对所有设备都成立,
-但总吞吐量还会受到诸如单个高速包之间的延迟、
-驱动是否足够聪明,以及系统整体负载等因素的影响。
-延迟也是性能考量因素。
+USB 2.0 的吞吐量主要受两个因素制约:主机控制器处理请求的速度,以及设备响
+应这些请求的速度。480 Mbit/sec 的“原始传输率”对所有设备都一样,但整体吞
+吐量还会受到诸如高速包之间的间隔、驱动实现是否足够高效以及系统总体负载等
+因素影响。延迟同样是需要考虑的性能指标。
-批量传输最常用于关注吞吐量的场景。
-需要记住的是,批量传输总是以 512 字节包为单位,
-而一个 USB 2.0 微帧中最多只能容纳 13 个这样的包。
-8 个 USB 2.0 微帧构成一个 USB 1.1 帧;
-一个微帧的时长是 1 毫秒 / 8 = 125 微秒。
+批量传输通常用于看重吞吐量的场景。需要记住的是,批量传输总是以 512 字节包
+为单位,而一个 USB 2.0 微帧中最多只能容纳 13 个这样的包。8 个 USB 2.0 微
+帧构成一个 USB 1.1 帧,因此一个微帧的时长就是 125 微秒。
-因此,只要硬件和设备驱动软件都允许,
-批量传输可提供超过 50 MByte/sec 的带宽。
-周期性传输模式(等时和中断)允许使用更大的包大小,
-从而可以逼近所宣称的 480 Mbit/sec 传输率。
+因此,只要硬件和驱动实现都足够成熟,批量传输就可以提供 50 MByte/sec 以上
+的带宽。周期性传输模式(等时和中断)允许使用更大的包大小,从而可以逼近所
+宣称的 480 Mbit/sec 传输率。
硬件性能
--------
-截至本文撰写时,单个 USB 2.0 设备的最大传输速率
-通常约为 20 MByte/sec。
-这当然会随着时间改变:一些设备现在更快,一些更慢。
+截至本文撰写时,单个 USB 2.0 设备的最大传输速率通常约为 20 MByte/sec。
+这种情况当然会随时间变化:有些设备现在更快,有些则更慢。
-第一代 NEC EHCI 实现似乎存在
-大约 28 MByte/sec 的硬件瓶颈。
-虽然这对单个 20 MByte/sec 的设备显然已经够用,
-但把三个这样的设备挂到同一总线上,
-并不能得到 60 MByte/sec。
-问题似乎在于控制器硬件无法并发进行 USB 与 PCI 访问,
-因此它每个微帧只会尝试 6 次(也许是 7 次)
-USB 事务,而不是 13 次。
-(对一个比其他产品早上市一年的芯片来说,
-这是个合理的妥协!)
+第一代 NEC EHCI 实现似乎存在大约 28 MByte/sec 的硬件瓶颈。虽然这对单个
+20 MByte/sec 的设备显然已经够用,但把三个这样的设备挂到同一总线上,并不
+能得到 60 MByte/sec。问题似乎在于控制器硬件无法并发进行 USB 与 PCI 访问,
+因此它每个微帧只会尝试 6 次(也许是 7 次)USB 事务,而不是 13 次。
+(对一款比其他产品早上市一年的芯片来说,这样的取舍也算合理。)
-预计较新的实现会在这方面做得更好,
-通过投入更多芯片面积来解决这个问题,
-使新的主板芯片组更接近 60 MByte/sec 的目标。
-这既包括 NEC 的更新实现,也包括其他厂商的芯片。
+预计较新的实现会在这方面做得更好,通过投入更多芯片面积来解决这个问题,
+使新的主板芯片组更接近 60 MByte/sec 的目标。这既包括 NEC 的更新实现,也
+包括其他厂商的芯片。
-主机从 EHCI 控制器收到“请求已完成”中断的最小延迟
-为一个微帧(125 微秒)。该延迟可以调节;
-驱动提供了一个模块选项。默认情况下,
-``ehci-hcd`` 使用最小延迟,这意味着当发出一个控制
-或批量请求时,通常可以在不到 250 微秒内得知它已完成
-(具体取决于传输大小)。
+主机从 EHCI 控制器收到“请求已完成”中断的最小延迟为一个微帧
+(125 微秒)。该延迟可以调节;驱动提供了一个模块选项。
+默认情况下,``ehci-hcd`` 使用最小延迟,这意味着发出控制或批量请求后,通
+常不到 250 微秒就能得知它已经完成(具体取决于传输大小)。
软件性能
--------
-即便只是要达到 20 MByte/sec 的传输速率,
-Linux-USB 设备驱动也必须让 EHCI 队列始终保持满载。
-这意味着要发出较大的请求,
-或者在需要发出一连串小请求时使用批量请求排队。
-如果驱动未做到这一点,那么会直接从性能结果上表现出来。
+即便只是要达到 20 MByte/sec 的传输速率,Linux-USB 设备驱动也必须让 EHCI
+队列始终保持满载。这意味着要发出较大的请求,或者在需要发出一连串小请求
+时使用批量请求排队。如果驱动做不到这一点,性能就会明显受影响。
-在典型情况下,使用 ``usb_bulk_msg()``
-以 4 KB 块循环写出,
-会浪费超过一半的 USB 2.0 带宽。
-I/O 完成与驱动发出下一次请求之间的延迟,
-通常会比一次 I/O 本身耗时更长。
-如果同样的循环改用 16 KB 块,会好一些;
-若使用一连串 128 KB 块,则浪费会少得多。
+在典型场景下,如果使用 ``usb_bulk_msg()`` 以 4 KB 块循环写出,会浪费超过
+一半的 USB 2.0 带宽。I/O 完成与驱动发出下一次请求之间的空档,往往比一次
+I/O 本身耗时还长。如果同样的循环改用 16 KB 块,情况会好一些;若使用一连串
+128 KB 块,则浪费会少得多。
+但与其依赖这么大的 I/O 缓冲区来提升同步 I/O 的效率,不如直接向主机控制器
+排队提交多个(批量)请求,然后等待它们全部完成(或在出错时取消)。这种
+URB 排队方式对所有 USB 1.1 主机控制器驱动同样适用。
-但与其依赖这么大的 I/O 缓冲区来让同步 I/O 高效,
-不如直接向主机控制器排入多个(批量)请求,
-然后等待它们全部完成(或在出错时取消)。
-这种 URB 排队方式对所有 USB 1.1
-主机控制器驱动也同样适用。
-
-在 Linux 2.5 内核中,定义了新的 ``usb_sg_*()`` API;
-它们会把 scatterlist 中的所有缓冲区都排入队列。
-它们还使用 scatterlist 的 DMA 映射
-(其中可能应用 IOMMU)并减少中断次数,
-这些都有助于让高速传输尽可能快地运行。
+在 Linux 2.5 内核中,定义了新的 ``usb_sg_*()`` API;它们会把 scatterlist
+中的所有缓冲区都排入队列。它们还使用 scatterlist 的 DMA 映射(其中可能
+应用 IOMMU)并减少中断次数,这些都有助于让高速传输尽可能快地运行。
待办:
中断传输和等时(ISO)传输的性能问题。
- 这些周期性传输都是完全调度的,因此,主要问题可能在于如何触发高带宽模式。
+ 这些周期性传输都是完全调度的,因此主要问题可能在于如何触发高带宽模式。
待办:
- 通过 ``sysfs`` 中的 ``uframe_periodic_max`` 参数,
- 可以分配超过标准 80% 的周期性带宽。
+ 通过 ``sysfs`` 中的 ``uframe_periodic_max`` 参数,可以分配超过标准
+ 80% 的周期性带宽。
后续将对此进行说明。
diff --git a/Documentation/translations/zh_CN/usb/index.rst b/Documentation/translations/zh_CN/usb/index.rst
index eb5aca0c13ec..df99814c6497 100644
--- a/Documentation/translations/zh_CN/usb/index.rst
+++ b/Documentation/translations/zh_CN/usb/index.rst
@@ -1,4 +1,14 @@
.. SPDX-License-Identifier: GPL-2.0
+
+.. only:: subproject and latex
+
+ .. raw:: latex
+
+ \renewcommand{\thesection}{}
+ \renewcommand{\thesubsection}{}
+ \kerneldocCJKon
+ \kerneldocBeginSC{
+
.. include:: ../disclaimer-zh_CN.rst
:Original: Documentation/usb/index.rst
@@ -24,7 +34,7 @@ USB 支持
ehci
usbmon
-Todolist:
+待翻译文档:
* functionfs
* functionfs-desc
@@ -52,3 +62,9 @@ Todolist:
====
* :ref:`genindex`
+
+.. only:: subproject and latex
+
+ .. raw:: latex
+
+ }\kerneldocEndSC
diff --git a/Documentation/translations/zh_CN/usb/usbmon.rst b/Documentation/translations/zh_CN/usb/usbmon.rst
index 11b6d5b59dce..bbfcbf875e26 100644
--- a/Documentation/translations/zh_CN/usb/usbmon.rst
+++ b/Documentation/translations/zh_CN/usb/usbmon.rst
@@ -16,67 +16,56 @@ usbmon
简介
====
-小写形式的 ``usbmon`` 指的是内核中的一项功能,
-用于收集 USB 总线上的 I/O 跟踪信息。它类似于网络监控工具
-``tcpdump(1)`` 或 Ethereal 所使用的数据包套接字。
-类似地,人们希望使用 usbdump 或 USBMon
-(首字母大写)之类的工具来检查
-usbmon 生成的原始跟踪数据。
-
-usbmon 报告的是各个外设驱动
-向主机控制器驱动(HCD)发出的请求。
-因此,如果 HCD 本身有 bug,那么 usbmon 报告的跟踪信息
-可能无法精确对应实际的总线事务。
-这和 tcpdump 的情况是一样的。
-
-目前实现了两种 API: ``text`` 和 ``binary``。
-二进制 API 通过 ``/dev`` 命名空间中的字符设备提供,
-并且属于 ABI。文本 API 自内核 2.6.35 起已废弃,
-但为了方便仍然可用。
+小写的 ``usbmon`` 指的是内核中的一项功能,用于收集 USB 总线上的 I/O 跟踪
+信息。它类似于网络监控工具 ``tcpdump(1)`` 或 Ethereal 使用的数据包套接
+字。通常会用 usbdump 或 USBMon(首字母大写)之类的工具来查看 usbmon 生成
+的原始跟踪数据。
+
+usbmon 记录的是各个设备驱动向主机控制器驱动(HCD)发出的请求。因此,如果
+HCD 自身有 bug,usbmon 输出的跟踪信息就未必能和真实的总线事务一一对应。
+这和 tcpdump 的情况类似。
+
+目前实现了两种 API:``text`` 和 ``binary``。二进制 API 通过 ``/dev`` 下的
+字符设备提供,是 ABI 的一部分。文本 API 自内核 2.6.35 起已废弃,但为了
+兼容和使用方便,至今仍然保留。
如何使用 usbmon 收集原始文本跟踪信息
====================================
-与数据包套接字不同,usbmon 提供了一种接口,
-可以输出文本格式的跟踪信息。这样做有两个目的:
-第一,在更完善的格式最终确定之前,
-它作为工具间通用的跟踪交换格式;
-第二,在不使用工具的情况下,人们也可以直接阅读这些信息。
+与数据包套接字不同,usbmon 还提供了一个输出文本格式跟踪信息的接口。这样
+做主要有两个目的:一是在更完善的格式最终确定之前,将其作为工具间通用的跟
+踪交换格式;二是在没有工具时也能直接阅读这些信息。
-要收集原始文本跟踪信息,请按以下步骤进行操作。
+要收集原始文本跟踪信息,按下面的步骤做即可。
1. 准备
-------
-挂载 debugfs(内核配置中必须启用它),并加载 usbmon 模块
-(如果它是作为模块构建的)。如果 usbmon 已经编入内核,
-那么第二步可以省略。
+挂载 debugfs(内核配置里必须启用它),并加载 usbmon 模块(如果它是以模块
+方式构建的)。如果 usbmon 已经编译进内核,这一步就可以省略。
命令示例::
- # mount -t debugfs none_debugs /sys/kernel/debug
+ # mount -t debugfs none /sys/kernel/debug
# modprobe usbmon
#
-确认总线套接字是否存在::
+确认 ``usbmon`` 目录下是否有这些条目::
# ls /sys/kernel/debug/usb/usbmon
0s 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u
#
-现在,你可以选择使用 ``0u`` 捕获所有总线上的数据包,
-并跳到第 3 步;
-也可以先按第 2 步找到目标设备所在的总线。
-这样可以过滤掉那些持续输出数据的烦人设备。
+现在,你可以直接用 ``0u`` 捕获所有总线上的数据包,然后跳到第 3 步;也可
+以先按第 2 步找出目标设备所在的总线。这样可以把那些持续产生流量的设备过
+滤掉。
2. 查找目标设备连接的是哪条总线
-------------------------------
-运行 ``cat /sys/kernel/debug/usb/devices``,
-找到对应设备的 T 行。通常可以通过厂商字符串来查找。
-如果有许多类似设备,可以拔掉其中一个,
-再比较前后两次 ``/sys/kernel/debug/usb/devices``
-的输出。T 行里会包含总线编号。
+运行 ``cat /sys/kernel/debug/usb/devices``,找到对应设备的 T 行。通常可以通过
+厂商字符串来查找。如果有很多相似设备,可以拔掉其中一个,再比较前后两次
+``/sys/kernel/debug/usb/devices`` 的输出。T 行里会包含总线编号。
示例::
@@ -86,8 +75,8 @@ usbmon 报告的是各个外设驱动
S: Manufacturer=ATEN
S: Product=UC100KM V2.00
-``Bus=03`` 表示它位于 3 号总线上。或者,
-也可以查看 ``lsusb`` 的输出,并从对应行得到总线编号。
+``Bus=03`` 表示它位于 3 号总线上。或者,也可以查看 ``lsusb`` 的输出,并从
+对应条目里找到总线编号。
示例如下::
@@ -97,133 +86,108 @@ usbmon 报告的是各个外设驱动
3. 启动 cat 命令
----------------
-如果只监听单条总线,可执行::
+如果只监听单条总线,执行::
# cat /sys/kernel/debug/usb/usbmon/3u > /tmp/1.mon.out
-否则,如果要监听所有总线,则执行::
+否则,如果要监听所有总线,执行::
# cat /sys/kernel/debug/usb/usbmon/0u > /tmp/1.mon.out
-此进程会一直读取,直到被终止。
-由于输出通常会很长,因此更推荐将输出重定向到某个位置。
+这个进程会一直运行到被终止为止。由于输出通常会很长,最好把它重定向到文件
+或其他位置。
4. 在 USB 总线上执行期望的操作
------------------------------
-此处需要执行一些会产生 USB 流量的动作,
-比如插入 U 盘、拷贝文件、操作摄像头等。
+这里做一些会产生 USB 流量的操作即可,比如插入 U 盘、拷贝文件、操作摄像头
+等。
5. 停止 cat
-----------
-这一步通常通过键盘中断(Control-C)完成。
+这一步通常按下键盘中断(Control-C)即可完成。
-此时输出文件(本例中为 ``/tmp/1.mon.out``)
-可以保存、通过电子邮件发送,或使用文本编辑器查看。
-如果使用最后一种方式,请确保文件不会大到编辑器无法打开。
+此时,输出文件(本例中为 ``/tmp/1.mon.out``)可以保存下来,通过电子邮件发
+送,也可以用文本编辑器查看。如果要用文本编辑器查看,请确保文件大小不会
+大到编辑器无法处理。
原始文本数据格式
================
-目前支持两种格式:原始格式,也就是 ``1t`` 格式,
-以及 ``1u`` 格式。``1t`` 格式在内核 2.6.21 中已被废弃。
-``1u`` 格式增加了一些字段,例如 ISO 帧描述符、
-``interval`` 等。它生成的行会稍长一些,
-但在其他方面是 ``1t`` 格式的完整超集。
-
-如果程序需要区分上述两种格式,
-可以查看 ``address`` 字段(见下文)。
-如果其中有两个冒号,就是 ``1t`` 格式;
-否则是 ``1u`` 格式。
-
-任何文本格式的数据由一系列事件组成,
-如 URB 提交、URB 回调、提交错误等。
-每个事件对应单独的一行文本,
-由使用空白符间隔的若干字段组成。
-字段的数量与位置可能取决于事件类型,
-但以下字段对所有类型都通用:
-
-下面按从左到右的顺序列出这些共有字段:
-
-- URB Tag。用于标识 URB,通常是 URB 结构体在内核中的地址
- (以十六进制表示),
- 但也可能是序号或其他合理的唯一字符串。
-
-- 时间戳(微秒),十进制数字。
- 时间戳的精度取决于可用时钟,
- 因此可能远差于
- 1 微秒(例如实现使用的是 jiffies)。
-
-- 事件类型。它表示的是事件的格式,而不是 URB 的类型。
- 可用值为:``S`` 表示提交,``C`` 表示回调,``E`` 表示提交错误。
-
-- ``Address`` 字段(以前称作 ``pipe``)。
- 它包含四个由冒号分隔的字段:
- URB 类型及方向、总线号、设备地址和端点号。类型与方向的编码如下:
-
- == == ==========================
- Ci Co 控制输入和输出
- Zi Zo 等时输入和输出
- Ii Io 中断输入和输出
- Bi Bo 批量输入和输出
- == == ==========================
-
- 总线号、设备地址和端点号使用十进制,但可能有前导零。
-
-- URB 状态字段。这个字段要么是一个字母,
- 要么是几个由冒号分隔的数字:
- URB 状态、``interval``、``start frame`` 和 ``error count``。
- 与 ``address`` 字段不同,除了状态外,其余字段都是可选的。
- ``interval`` 只会为中断和等时 URB 打印;``start frame`` 只会为
- 等时 URB 打印;错误计数只会在等时回调事件中打印。
-
- 状态字段是一个十进制数字,有时为负数,
- 对应 URB 的 ``status`` 字段。
- 对于提交事件,这个字段本身没有实际意义,
- 但为了便于脚本解析,它仍然存在。
- 当发生错误时,该字段包含错误码。
-
- 在提交控制包时,这个字段包含的是 ``Setup Tag``,
- 而不是一组数字。
- 判断 ``Setup Tag`` 是否存在很容易,因为它从来不是数字。
- 因此,如果脚本在这个字段里发现的是一组数字,
- 就会继续读取数据长度(等时 URB 除外)。
- 如果发现的是其他内容,比如一个字母,
- 那么脚本会先读取 ``Setup`` 包,再读取数据长度或等时描述符。
-
-- ``Setup`` 包由 5 个字段组成:
- ``bmRequestType``、``bRequest``、``wValue``、
- ``wIndex`` 和 ``wLength``。这些字段由 USB 2.0 规范定义。
- 如果 ``Setup Tag`` 为 ``s``,就可以安全地解码这些字段。
- 否则,说明 Setup 包虽然存在,但并未被捕获,此时各字段中会填入占位内容。
+目前支持两种格式:原始的 ``1t`` 格式和 ``1u`` 格式。``1t`` 格式在内核
+2.6.21 中已被废弃。``1u`` 格式增加了一些字段,例如 ISO 帧描述符和
+``interval``。它生成的行会稍长一些,但除此之外,它是 ``1t`` 格式的完整
+超集。
+
+如果程序需要区分上述两种格式,可以查看 ``address`` 字段(见下文)。如果
+其中有两个冒号,就是 ``1t`` 格式;否则是 ``1u`` 格式。
+
+任何文本格式的数据都由一系列事件构成,例如 URB 提交、URB 回调和提交错
+误。每个事件占一行,由若干以空白符分隔的字段组成。字段数量和位置会随事件
+类型变化,但下面这些字段对所有类型都通用:
+
+下面按从左到右的顺序说明这些通用字段:
+
+- URB 标识(URB Tag)。用于标识 URB,通常是 URB 结构体在内核中的地址
+ (十六进制),也可能是序号或其他足以唯一标识 URB 的字符串。
+
+- 时间戳(微秒),十进制数字。时间戳的精度取决于可用时钟,所以可能远低于
+ 1 微秒(例如实现使用 jiffies 时)。
+
+- 事件类型。它表示的是这一行事件的格式,而不是 URB 的类型。可用值为:
+ ``S`` 表示提交,``C`` 表示回调,``E`` 表示提交错误。
+
+- ``Address`` 字段(以前称为 ``pipe``)。它包含四个由冒号分隔的字段:URB
+ 类型及方向、总线号、设备地址和端点号。类型与方向的编码如下:
+
+ - ``Ci`` / ``Co``:控制输入 / 输出
+ - ``Zi`` / ``Zo``:等时输入 / 输出
+ - ``Ii`` / ``Io``:中断输入 / 输出
+ - ``Bi`` / ``Bo``:批量输入 / 输出
+
+ 总线号、设备地址和端点号都是十进制数,但可能有前导零,方便人阅读。
+
+- URB 状态字段。这个字段要么是一个字母,要么是几个用冒号分隔的数字,依次
+ 表示 URB 状态、``interval``、``start frame`` 和 ``error count``。与
+ ``address`` 字段不同,除状态外,其余字段都可能省略。``interval`` 只会在
+ 中断和等时 URB 中打印;``start frame`` 只会在等时 URB 中打印;错误计数只
+ 会在等时回调事件中打印。
+
+ 状态字段是一个十进制数,有时为负数,对应 URB 的 ``status`` 字段。对于提
+ 交事件,这个字段本身并无实际语义,但为了便于脚本解析仍会保留。发生错误
+ 时,这里填的是错误码。
+
+ 如果是控制包的提交事件,这个字段里放的不是一组数字,而是 ``Setup Tag``。
+ 这很容易分辨,因为 ``Setup Tag`` 永远不是数字。所以脚本如果在这里读到一
+ 组数字,就会继续读取数据长度(等时 URB 除外);如果读到的是字母之类的内
+ 容,就要先读取 ``Setup`` 包,再读取数据长度或等时描述符。
+
+- ``Setup`` 包由 5 个字段组成:``bmRequestType``、``bRequest``、``wValue``、
+ ``wIndex`` 和 ``wLength``。这些字段由 USB 2.0 规范定义。如果 ``Setup Tag``
+ 是 ``s``,就可以安全解码这些字段。否则,说明 Setup 包虽然存在,但并未被
+ 捕获,此时各字段中会填入占位内容。
- 等时传输帧描述符的数量及其内容:
- 如果一个等时传输事件带有一组描述符,首先打印该 URB 中描述符的总数,
- 然后为每个描述符打印一个字段,最多打印 5 个字段。
- 每个字段由三个用冒号分隔的十进制数字组成,
- 分别表示状态(status)、偏移(offset)和长度(length)。
- 对于提交(submission),报告的是初始长度;
- 对于回调(callback),报告的是实际长度。
+ 如果某个等时传输事件带有描述符,会先打印该 URB 的描述符总数,再为每个描
+ 述符打印一个字段,最多 5 个。每个字段由三个用冒号分隔的十进制数组成,依
+ 次表示状态(status)、偏移(offset)和长度(length)。对于提交事件,报
+ 告的是初始长度;对于回调事件,报告的是实际长度。
-- 数据长度:
- 对于提交,表示请求的长度;对于回调,表示实际传输的长度。
+- 数据长度:对于提交,表示请求的长度;对于回调,表示实际传输的长度。
-- 数据标签:
- 即使数据长度非零,usbmon 也不一定会捕获数据。
- 仅当标签为 ``=`` 时,才会有数据字段。
+- 数据标签:即使数据长度非零,usbmon 也不一定会捕获数据。只有标签为
+ ``=`` 时,才会有数据字段。
-- 数据字段:
- 以大端十六进制格式显示。注意,这些并不是真正的机器字,
- 而只是把字节流拆成若干“字”以便阅读。因此最后一个字可能只包含
- 1 到 4 个字节。
- 收集的数据长度是有限的,可能小于数据长度字段中报告的值。
- 因为数据长度字段只统计实际接收到的字节,而数据字段包含整个传输缓冲区,
- 所以,在等时输入(Zi)完成且缓冲区中接收到的数据稀疏的情况下,
- 收集的数据长度可能大于数据长度字段的值。
+- 数据字段:以大端十六进制格式显示。注意,这些并不是真正的机器字,只是为
+ 了便于阅读,把字节流按“字”分组显示。因此最后一个字可能只包含 1 到 4 个
+ 字节。捕获的数据长度是有限的,可能小于数据长度字段中报告的值。对于等时
+ 输入(Zi)完成事件,如果缓冲区里的接收数据比较稀疏,捕获数据的长度甚至
+ 可能大于数据长度字段,因为后者只统计实际接收到的字节,而数据字段展示的
+ 是整个传输缓冲区。
@@ -234,18 +198,16 @@ usbmon 报告的是各个外设驱动
d5ea89a0 3575914555 S Ci:1:001:0 s a3 00 0000 0003 0004 4 <
d5ea89a0 3575914560 C Ci:1:001:0 0 4 = 01050000
-向地址为 5 的存储设备发送
-31 字节 Bulk 包装的 SCSI 命令 ``0x28``
-(``READ_10``)的输出批量传输::
+向地址为 5 的存储设备发送一个输出批量传输,其中 31 字节的 Bulk 封装用于承
+载 SCSI 命令 ``0x28``(``READ_10``)::
dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 ad000000 00800000 80010a28 20000000 20000040 00000000 000000
dd65f0e8 4128379808 C Bo:1:005:2 0 31 >
原始二进制格式与 API
====================
-API 的整体架构与前文大体相同,只是事件以二进制格式传递。
-每个事件都通过下面的结构发送
-(这个名字是为了叙述方便而虚构的)::
+API 的整体架构与前文大体相同,只是事件以二进制格式传递。每个事件都通过
+下面的结构发送(这个结构名只是为了叙述方便而虚构的)::
struct usbmon_packet {
@@ -275,29 +237,22 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
unsigned int ndesc; /* 60: 实际 ISO 描述符数量 */
}; /* 64 总长度 */
-可以用 ``read(2)``、``ioctl(2)``,
-或者通过 ``mmap`` 访问缓冲区,
-从字符设备接收这些事件。
-不过,出于兼容性原因,``read(2)``
-只返回前 48 个字节。
+可以用 ``read(2)``、``ioctl(2)``,或者通过 ``mmap`` 访问缓冲区,从字符设
+备接收这些事件。不过,出于兼容性原因,``read(2)`` 只返回前 48 个字节。
-字符设备通常命名为 ``/dev/usbmonN``,
-其中 ``N`` 是 USB 总线号。
-编号为零的设备(``/dev/usbmon0``)比较特殊,
-表示“所有总线”。
-请注意,具体命名策略由 Linux 发行版决定。
+字符设备通常命名为 ``/dev/usbmonN``,其中 ``N`` 是 USB 总线号。编号为零的
+设备(``/dev/usbmon0``)比较特殊,表示“所有总线”。具体命名策略由 Linux
+发行版决定。
-如果你手动创建 ``/dev/usbmon0``,
-请确保它归 root 所有,并且权限为 ``0600``。
-否则,非特权用户将能够窃听键盘流量。
+如果你手动创建 ``/dev/usbmon0``,请确保它归 root 所有,并且权限为 ``0600``。
+否则,非特权用户就能窃听键盘输入流量。
以下 ``MON_IOC_MAGIC`` 为 ``0x92`` 的 ioctl 调用可用:
``MON_IOCQ_URB_LEN``,定义为 ``_IO(MON_IOC_MAGIC, 1)``
-该调用返回下一个事件的数据长度。
-注意大多数事件不包含数据,
-因此如果该调用返回零,并不意味着没有事件。
+该调用返回下一个事件的数据长度。注意大多数事件不包含数据,因此如果它返回
+零,并不意味着没有事件。
``MON_IOCG_STATS``,定义为
``_IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)``
@@ -309,31 +264,28 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
u32 dropped;
};
-成员 ``queued`` 表示当前缓冲区中已经排队的事件数量,
-而不是自上次重置以来处理过的事件数量。
+成员 ``queued`` 表示当前缓冲区中已经排队的事件数量,而不是自上次重置以来
+处理过的事件数量。
-成员 ``dropped`` 表示自上次调用
-``MON_IOCG_STATS`` 以来丢失的事件数量。
+成员 ``dropped`` 表示自上次调用 ``MON_IOCG_STATS`` 以来丢失的事件数量。
``MON_IOCT_RING_SIZE``,定义为 ``_IO(MON_IOC_MAGIC, 4)``
-此调用设置缓冲区大小。参数为以字节为单位的缓冲区大小。
-大小可能会向下取整到下一个块(或页)。
-如果请求的大小超出该内核的 [未指定] 范围,
-则调用会失败并返回 ``-EINVAL``。
+此调用设置缓冲区大小。参数是以字节为单位的缓冲区大小。大小可能会向下取整
+到下一个块(或页)。如果请求的大小超出当前内核允许的范围,则调用会失败并
+返回 ``-EINVAL``。
``MON_IOCQ_RING_SIZE``,定义为 ``_IO(MON_IOC_MAGIC, 5)``
该调用返回缓冲区当前大小(以字节为单位)。
-``MON_IOCX_GET``,定义为
-``_IOW(MON_IOC_MAGIC, 6, struct mon_get_arg)``
-``MON_IOCX_GETX``,定义为
-``_IOW(MON_IOC_MAGIC, 10, struct mon_get_arg)``
+``MON_IOCX_GET`` 和 ``MON_IOCX_GETX`` 的定义分别如下:
+
+- ``MON_IOCX_GET``:``_IOW(MON_IOC_MAGIC, 6, struct mon_get_arg)``
+- ``MON_IOCX_GETX``:``_IOW(MON_IOC_MAGIC, 10, struct mon_get_arg)``
-如果内核缓冲区中没有事件,
-这些调用就会一直等待,直到有事件到达,
-然后返回第一个事件。
+如果内核缓冲区中没有事件,这些调用就会一直等待,直到有事件到达,然后返回
+第一个事件。
参数是指向以下结构的指针::
struct mon_get_arg {
@@ -343,20 +295,18 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
};
-调用前,应填好 ``hdr``、``data`` 和 ``alloc``。
-调用返回后,``hdr`` 指向的区域中包含下一个事件的结构;
-如果存在数据,那么数据缓冲区中也会包含相应数据。
-该事件会从内核缓冲区中移除。
+调用前,应填好 ``hdr``、``data`` 和 ``alloc``。调用返回后,``hdr`` 指向的
+内存区域中会写入下一个事件的结构;如果存在数据,数据缓冲区中也会填入相应
+内容。该事件会从内核缓冲区中移除。
-``MON_IOCX_GET`` 会将 48 字节的数据复制到 ``hdr`` 区域,
-``MON_IOCX_GETX`` 会复制 64 字节。
+``MON_IOCX_GET`` 会将 48 字节的数据复制到 ``hdr`` 区域,``MON_IOCX_GETX``
+会复制 64 字节。
``MON_IOCX_MFETCH``,定义为
``_IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg)``
-当应用程序通过 ``mmap(2)`` 访问缓冲区时,
-主要使用这个 ioctl。
-其参数是指向以下结构的指针::
+应用程序通过 ``mmap(2)`` 访问缓冲区时,主要使用这个 ioctl。其参数是指向
+以下结构的指针::
struct mon_mfetch_arg {
uint32_t *offvec; /* 获取的事件偏移向量 */
@@ -365,41 +315,36 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
};
-该 ioctl 的操作分为三个阶段:
+这个 ioctl 的流程分为三个阶段:
-首先,从内核缓冲区移除并丢弃最多 ``nflush`` 个事件。
-实际丢弃的事件数量会写回 ``nflush``。
+首先,从内核缓冲区移除并丢弃最多 ``nflush`` 个事件。实际丢弃的事件数量会
+写回 ``nflush``。
-其次,除非伪设备以 ``O_NONBLOCK`` 打开,否则会一直等待,
-直到缓冲区中出现事件。
+其次,除非设备以 ``O_NONBLOCK`` 打开,否则会一直等待,直到缓冲区中出现
+事件。
-第三,将最多 ``nfetch`` 个偏移量提取到 mmap
-缓冲区,并存入 ``offvec`` 中。
-实际提取到的事件偏移数量会存回 ``nfetch``。
+第三,将最多 ``nfetch`` 个偏移量提取到 mmap 缓冲区,并存入 ``offvec`` 中。
+实际提取到的事件偏移数量会写回 ``nfetch``。
``MON_IOCH_MFLUSH``,定义为 ``_IO(MON_IOC_MAGIC, 8)``
-此调用从内核缓冲区移除若干事件。
-其参数为要移除的事件数量。
-如果缓冲区中的事件少于请求数量,
-则移除所有事件,且不报告错误。
-当没有事件时也可使用。
+此调用从内核缓冲区移除若干事件。其参数是要移除的事件数量。如果缓冲区中的
+事件少于请求数量,则移除全部现有事件,且不报告错误。即使当前没有事件,也
+可以调用。
``FIONBIO``
如果有需要,将来可能会实现 ``FIONBIO`` ioctl。
-除了 ``ioctl(2)`` 和 ``read(2)`` 之外,
-二进制 API 的特殊文件也可以用 ``select(2)`` 和
-``poll(2)`` 轮询。
-但 ``lseek(2)`` 不起作用。
+除了 ``ioctl(2)`` 和 ``read(2)`` 之外,二进制 API 对应的特殊文件还可以用
+``select(2)`` 和 ``poll(2)`` 轮询,但 ``lseek(2)`` 不可用。
* 二进制 API 的内核缓冲区内存映射访问
-基本思想很简单:
+基本思路很简单:
-准备时,先获取当前大小,再用 ``mmap(2)`` 映射缓冲区。
-然后执行类似下面伪代码的循环::
+准备时,先查询当前大小,再用 ``mmap(2)`` 映射缓冲区。之后运行与下面伪代码
+类似的循环::
struct mon_mfetch_arg fetch;
struct usbmon_packet *hdr;
@@ -411,7 +356,7 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
ioctl(fd, MON_IOCX_MFETCH, &fetch); // 同时处理错误
nflush = fetch.nfetch; // 完成后要刷新这么多包
for (i = 0; i < nflush; i++) {
- hdr = (struct ubsmon_packet *) &mmap_area[vec[i]];
+ hdr = (struct usbmon_packet *) &mmap_area[vec[i]];
if (hdr->type == '@') // 填充包
continue;
caddr_t data = &mmap_area[vec[i]] + 64;
@@ -421,7 +366,7 @@ API 的整体架构与前文大体相同,只是事件以二进制格式传递
-因此,主要思想是每 N 个事件只执行一次 ioctl。
+因此,这里的核心思路就是每 N 个事件只执行一次 ioctl。
-虽然缓冲区是环形的,但返回的头和数据不会跨越缓冲区末端,
-因此上面的伪代码无需任何合并操作。
+虽然缓冲区是环形的,但返回的头部和数据不会跨越缓冲区末端,因此上面的伪代
+码无需做任何拼接。
--
2.34.1
^ permalink raw reply related
* Re: [PATCH mm-unstable v18 06/14] mm/khugepaged: generalize collapse_huge_page for mTHP collapse
From: Lance Yang @ 2026-06-01 3:28 UTC (permalink / raw)
To: david
Cc: lance.yang, npache, linux-doc, linux-kernel, linux-mm,
linux-trace-kernel, aarcange, akpm, anshuman.khandual, apopple,
baohua, baolin.wang, byungchul, catalin.marinas, cl, corbet,
dave.hansen, dev.jain, gourry, hannes, hughd, jack, jackmanb,
jannh, jglisse, joshua.hahnjy, kas, liam, ljs, mathieu.desnoyers,
matthew.brost, mhiramat, mhocko, peterx, pfalcato, rakie.kim,
raquini, rdunlap, richard.weiyang, rientjes, rostedt, rppt,
ryan.roberts, shivankg, sunnanyong, surenb, thomas.hellstrom,
tiwai, usamaarif642, vbabka, vishal.moola, wangkefeng.wang, will,
willy, yang, ying.huang, ziy, zokeefe, usama.arif
In-Reply-To: <2024af56-5e99-4799-a586-e9ba756cecb9@kernel.org>
On Sun, May 31, 2026 at 10:00:17PM +0200, David Hildenbrand (Arm) wrote:
>On 5/31/26 11:39, Lance Yang wrote:
>>
>> On Fri, May 22, 2026 at 09:00:01AM -0600, Nico Pache wrote:
>>> Pass an order and offset to collapse_huge_page to support collapsing anon
>>> memory to arbitrary orders within a PMD. order indicates what mTHP size we
>>> are attempting to collapse to, and offset indicates were in the PMD to
>>> start the collapse attempt.
>>>
>>> For non-PMD collapse we must leave the anon VMA write locked until after
>>> we collapse the mTHP-- in the PMD case all the pages are isolated, but in
>>> the mTHP case this is not true, and we must keep the lock to prevent
>>> access/changes to the page tables. This can happen if the rmap walkers hit
>>> a pmd_none while the PMD entry is currently unavailable due to being
>>> temporarily removed during the collapse phase.
>>>
>>> Acked-by: Usama Arif <usama.arif@linux.dev>
>>> Signed-off-by: Nico Pache <npache@redhat.com>
>>> ---
>>> mm/khugepaged.c | 93 +++++++++++++++++++++++++++++--------------------
>>> 1 file changed, 55 insertions(+), 38 deletions(-)
>>>
>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>>> index fab35d318641..d64f42f66236 100644
>>> --- a/mm/khugepaged.c
>>> +++ b/mm/khugepaged.c
>>> @@ -1214,34 +1214,36 @@ static enum scan_result alloc_charge_folio(struct folio **foliop, struct mm_stru
>>> * while allocating a THP, as that could trigger direct reclaim/compaction.
>>> * Note that the VMA must be rechecked after grabbing the mmap_lock again.
>>> */
>>> -static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long address,
>>> - int referenced, int unmapped, struct collapse_control *cc)
>>> +static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long start_addr,
>>> + int referenced, int unmapped, struct collapse_control *cc,
>>> + unsigned int order)
>>> {
>>> + const unsigned long pmd_addr = start_addr & HPAGE_PMD_MASK;
>>> + const unsigned long end_addr = start_addr + (PAGE_SIZE << order);
>>> LIST_HEAD(compound_pagelist);
>>> pmd_t *pmd, _pmd;
>>> - pte_t *pte;
>>> + pte_t *pte = NULL;
>>> pgtable_t pgtable;
>>> struct folio *folio;
>>> spinlock_t *pmd_ptl, *pte_ptl;
>>> enum scan_result result = SCAN_FAIL;
>>> struct vm_area_struct *vma;
>>> struct mmu_notifier_range range;
>>> + bool anon_vma_locked = false;
>>>
>>> - VM_BUG_ON(address & ~HPAGE_PMD_MASK);
>>> -
>>> - result = alloc_charge_folio(&folio, mm, cc, HPAGE_PMD_ORDER);
>>> + result = alloc_charge_folio(&folio, mm, cc, order);
>>> if (result != SCAN_SUCCEED)
>>> goto out_nolock;
>>>
>>> mmap_read_lock(mm);
>>> - result = hugepage_vma_revalidate(mm, address, true, &vma, cc,
>>> - HPAGE_PMD_ORDER);
>>> + result = hugepage_vma_revalidate(mm, pmd_addr, /*expect_anon=*/ true,
>>> + &vma, cc, order);
>>> if (result != SCAN_SUCCEED) {
>>> mmap_read_unlock(mm);
>>> goto out_nolock;
>>> }
>>>
>>> - result = find_pmd_or_thp_or_none(mm, address, &pmd);
>>> + result = find_pmd_or_thp_or_none(mm, pmd_addr, &pmd);
>>> if (result != SCAN_SUCCEED) {
>>> mmap_read_unlock(mm);
>>> goto out_nolock;
>>> @@ -1253,8 +1255,8 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long a
>>> * released when it fails. So we jump out_nolock directly in
>>> * that case. Continuing to collapse causes inconsistency.
>>> */
>>> - result = __collapse_huge_page_swapin(mm, vma, address, pmd,
>>> - referenced, HPAGE_PMD_ORDER);
>>> + result = __collapse_huge_page_swapin(mm, vma, start_addr, pmd,
>>> + referenced, order);
>>> if (result != SCAN_SUCCEED)
>>> goto out_nolock;
>>> }
>>> @@ -1269,20 +1271,21 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long a
>>> * mmap_lock.
>>> */
>>> mmap_write_lock(mm);
>>> - result = hugepage_vma_revalidate(mm, address, true, &vma, cc,
>>> - HPAGE_PMD_ORDER);
>>> + result = hugepage_vma_revalidate(mm, pmd_addr, /*expect_anon=*/ true,
>>> + &vma, cc, order);
>>> if (result != SCAN_SUCCEED)
>>> goto out_up_write;
>>> /* check if the pmd is still valid */
>>> vma_start_write(vma);
>>> - result = check_pmd_still_valid(mm, address, pmd);
>>> + result = check_pmd_still_valid(mm, pmd_addr, pmd);
>>> if (result != SCAN_SUCCEED)
>>> goto out_up_write;
>>>
>>> anon_vma_lock_write(vma->anon_vma);
>>> + anon_vma_locked = true;
>>>
>>> - mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, address,
>>> - address + HPAGE_PMD_SIZE);
>>> + mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm, start_addr,
>>> + end_addr);
>>> mmu_notifier_invalidate_range_start(&range);
>>>
>>> pmd_ptl = pmd_lock(mm, pmd); /* probably unnecessary */
>>> @@ -1294,26 +1297,23 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long a
>>> * Parallel GUP-fast is fine since GUP-fast will back off when
>>> * it detects PMD is changed.
>>> */
>>> - _pmd = pmdp_collapse_flush(vma, address, pmd);
>>> + _pmd = pmdp_collapse_flush(vma, pmd_addr, pmd);
>>> spin_unlock(pmd_ptl);
>>> mmu_notifier_invalidate_range_end(&range);
>>> tlb_remove_table_sync_one();
>>>
>>> - pte = pte_offset_map_lock(mm, &_pmd, address, &pte_ptl);
>>> + pte = pte_offset_map_lock(mm, &_pmd, start_addr, &pte_ptl);
>>> if (pte) {
>>> - result = __collapse_huge_page_isolate(vma, address, pte, cc,
>>> - HPAGE_PMD_ORDER,
>>> - &compound_pagelist);
>>> + result = __collapse_huge_page_isolate(vma, start_addr, pte, cc,
>>> + order, &compound_pagelist);
>>> spin_unlock(pte_ptl);
>>> } else {
>>> result = SCAN_NO_PTE_TABLE;
>>> }
>>>
>>> if (unlikely(result != SCAN_SUCCEED)) {
>>> - if (pte)
>>> - pte_unmap(pte);
>>> spin_lock(pmd_ptl);
>>> - BUG_ON(!pmd_none(*pmd));
>>> + WARN_ON_ONCE(!pmd_none(*pmd));
>>> /*
>>> * We can only use set_pmd_at when establishing
>>> * hugepmds and never for establishing regular pmds that
>>> @@ -1321,21 +1321,24 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long a
>>> */
>>> pmd_populate(mm, pmd, pmd_pgtable(_pmd));
>>> spin_unlock(pmd_ptl);
>>> - anon_vma_unlock_write(vma->anon_vma);
>>> goto out_up_write;
>>> }
>>>
>>> /*
>>> - * All pages are isolated and locked so anon_vma rmap
>>> - * can't run anymore.
>>> + * For PMD collapse all pages are isolated and locked so anon_vma
>>> + * rmap can't run anymore. For mTHP collapse the PMD entry has been
>>> + * removed and not all pages are isolated and locked, so we must hold
>>> + * the lock to prevent neighboring folios from attempting to access
>>> + * this PMD until its reinstalled.
>>> */
>>> - anon_vma_unlock_write(vma->anon_vma);
>>> + if (is_pmd_order(order)) {
>>> + anon_vma_unlock_write(vma->anon_vma);
>>> + anon_vma_locked = false;
>>> + }
>>>
>>> result = __collapse_huge_page_copy(pte, folio, pmd, _pmd,
>>> - vma, address, pte_ptl,
>>> - HPAGE_PMD_ORDER,
>>> - &compound_pagelist);
>>> - pte_unmap(pte);
>>> + vma, start_addr, pte_ptl,
>>> + order, &compound_pagelist);
>>> if (unlikely(result != SCAN_SUCCEED))
>>> goto out_up_write;
>>>
>>> @@ -1345,18 +1348,32 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long a
>>> * write.
>>> */
>>> __folio_mark_uptodate(folio);
>>> - pgtable = pmd_pgtable(_pmd);
>>> -
>>> spin_lock(pmd_ptl);
>>> - BUG_ON(!pmd_none(*pmd));
>>> - pgtable_trans_huge_deposit(mm, pmd, pgtable);
>>> - map_anon_folio_pmd_nopf(folio, pmd, vma, address);
>>> + WARN_ON_ONCE(!pmd_none(*pmd));
>>> + if (is_pmd_order(order)) {
>>> + pgtable = pmd_pgtable(_pmd);
>>> + pgtable_trans_huge_deposit(mm, pmd, pgtable);
>>> + map_anon_folio_pmd_nopf(folio, pmd, vma, pmd_addr);
>>> + } else {
>>> + /*
>>> + * set_ptes is called in map_anon_folio_pte_nopf with the
>>> + * pmd_ptl lock still held; this is safe as the PMD is expected
>>> + * to be none. The pmd entry is then repopulated below.
>>> + */
>>> + map_anon_folio_pte_nopf(folio, pte, vma, start_addr, /*uffd_wp=*/ false);
>>
>> Emm ... is it safe to use map_anon_folio_pte_nopf() here?
>>
>> At this point pmdp_collapse_flush() has cleared the PMD from the page
>> tables. The PTE table we are updating is only reachable through the saved
>> old PMD value, _pmd, until pmd_populate() below.
>>
>> map_anon_folio_pte_nopf() does set_ptes() and then calls
>> update_mmu_cache_range(). Documentation/core-api/cachetlb.rst describes
>> that hook as:
>>
>> "
>> At the end of every page fault, this routine is invoked to tell
>> the architecture specific code that translations now exists
>> in the software page tables for address space "vma->vm_mm"
>> at virtual address "address" for "nr" consecutive pages.
>> "
>>
>> But that does not seem true here yet, since the PTE table is not
>> reachable from vma->vm_mm when update_mmu_cache_range() is called.
>>
>> Should we avoid calling update_mmu_cache_range() until after the PTE
>> table is reinstalled with pmd_populate()?
>
>I recall that update_mmu_cache* users mostly care about updating folios flags,
>for the folio derived from the PTE ... or flushing caches for the user address.
>
>So intuitively I would say "the architecture code doesn't care that the PMD
>table will only be visible to HW shortly after". The important thing should be
>that it will definetly happen, and that nothing else is curently there or can be
>there?
Ah, fair point.
I was mostly worried about arch hooks that walk vma->vm_mm again, rather
than only using the pte pointer passed in. For example, mips does:
update_mmu_cache_range()
-> __update_tlb()
-> pgd_offset(vma->vm_mm, address)
-> pte_offset_map(...)
and __update_tlb() has this assumption:
/*
* update_mmu_cache() is called between pte_offset_map_lock()
* and pte_unmap_unlock(), so we can assume that ptep is not
* NULL here: and what should be done below if it were NULL?
*/
So if khugepaged happens to run with current->active_mm == vma->vm_mm
here, could __update_tlb() hit the none PMD, get NULL from
pte_offset_map(), and then dereference it?
Just wanted to raise it since some arch code may still have assumptions
like this, and the always-enable-mTHP work is getting closer ...
Probably very very very hard to hit, though :)
Cheers, Lance
^ permalink raw reply
* Re: [RFC PATCH v1 00/13] exec: add spawn templates for repeated executable startup
From: Li Chen @ 2026-06-01 2:47 UTC (permalink / raw)
To: Christian Brauner
Cc: Kees Cook, Alexander Viro, linux-fsdevel, linux-api, linux-kernel,
linux-mm, linux-arch, linux-doc, linux-kselftest, x86,
Arnd Bergmann, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, H. Peter Anvin, Jan Kara,
Jonathan Corbet, Shuah Khan
In-Reply-To: <20260528-madig-fachrichtung-fehlinformation-61117ba640da@brauner>
Hi Christian,
Thanks a lot for your great review!
---- On Thu, 28 May 2026 19:02:53 +0800 Christian Brauner <brauner@kernel.org> wrote ---
> On Thu, May 28, 2026 at 05:52:21PM +0800, Li Chen wrote:
> > Hi,
> >
> > This is an early RFC for an idea that is probably still rough in both the
> > UAPI and implementation details. Sorry for the rough edges; I am sending
> > it now to check whether this direction is worth pursuing and to get
> > feedback on the kernel/userspace boundary.
>
> The idea of having a builder api for exec isn't all that crazy. But it
> should simply be built on top of pidfds and thus pidfs itself instead.
> It has all the basic infrastructure in place already.
Yes, that makes a lot more sense. I was staring too hard at the "hot
executable" part and made the cache/template the API, which was probably
the wrong thing to expose. Sorry about that.
> Any implementation
> should also allow userspace to implement posix_spawn() on top of it.
That's so cool, and this is a really useful point. I had not thought about this as
something that could sit under posix_spawn(), but that makes the target
much clearer. It should be a generic exec/spawn builder first, and the
agent use case should just be one user of it.
> fd = pidfd_open(0, PIDFD_EMPTY /* or better name */)
>
> pidfd_config(fd, ...) // modeled similar to fsconfig()
Reusing pidfd_open() with an empty target is nice because it keeps the API close
to pidfds, but I wonder if a separate entry point such as
pidfd_spawn_open() or pidfd_create() would make the "new process
builder" case a bit more explicit? Either way, the configuration side
being fsconfig-like makes sense to me.
Thanks again for pointing me in this direction. It helps a lot.
Regards,
Li
^ permalink raw reply
* Re: [PATCH] cpufreq: Documentation: fix freq_step description
From: Pengjie Zhang @ 2026-06-01 2:04 UTC (permalink / raw)
To: Zhongqiu Han, rafael, viresh.kumar, corbet, skhan
Cc: linux-pm, linux-doc, linux-kernel, zhanjie9, prime.zeng,
wanghuiqiang, xuwei5, lihuisong, zhenglifeng1, yubowen8,
wangzhi12
In-Reply-To: <f598e862-8120-4922-9d04-6e3729187420@oss.qualcomm.com>
On 5/30/2026 10:36 PM, Zhongqiu Han wrote:
> On 5/29/2026 7:11 PM, Pengjie Zhang wrote:
>> The conservative governor documentation incorrectly states that setting
>> freq_step to 0 will use the default 5% frequency step. In reality, since
>> the governor's initial implementation
>> commit b9170836d1aa ("[CPUFREQ] Conservative cpufreq governer"),
>> freq_step=0 has always caused the governor to skip frequency updates
>> entirely.
>
> Hi Pengjie,
>
> Thanks for the patch.
>
> The documentation fix looks correct: in the current code,
> cs_dbs_update() has an early goto out when freq_step == 0, which skips
> the call to get_freq_step() and all subsequent frequency change logic.
>
> However, the commit message's historical claim appears to be inaccurate.
> In the original implementation (b9170836d1aa), freq_step=0 had
> asymmetric behavior: frequency decreases were skipped (early return),
> but frequency increases still used the hardcoded 5% fallback (freq_step
> = 5 after the unlikely(freq_step == 0) check).
>
> If so, would it make sense to remove/update the historical claim to
> avoid the incorrect historical claim?
>
Thanks for the careful review.
Agreed. The correct commit for the symmetric freq_step=0 behavior
should be 8e677ce83bf4 ("[CPUFREQ] conservative: fixup governor to
function more like ondemand logic"), not b9170836d1aa.
I'll fix the commit message in v2.
On a related note, I have a quick question regarding code readability in
this area. Currently, the code uses the name "freq_step" for two different
concepts:
1. `cs_tuners->freq_step`: The tunable exposed via sysfs/documentation,
which represents a percentage.
2. `freq_step = get_freq_step(...)`: The local variable representing the
actual calculated frequency step (in kHz). The `if
(unlikely(freq_step == 0))`
check also applies to this absolute value.
Since mixing a percentage and an absolute kHz value under the same name
might be slightly confusing for readers, would it make sense to rename the
local variable (e.g., to `freq_step_khz`) to clearly distinguish the two?
Cheers,
Pengjie
>>
>> Correct the documentation to reflect the actual behavior: freq_step=0
>> disables frequency changes by the governor entirely.
>>
>> Fixes: 2a0e49279850 ("cpufreq: User/admin documentation update and
>> consolidation")
>> Signed-off-by: Pengjie Zhang <zhangpengjie2@huawei.com>
>> ---
>> Documentation/admin-guide/pm/cpufreq.rst | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/pm/cpufreq.rst
>> b/Documentation/admin-guide/pm/cpufreq.rst
>> index dbe6d23a5d67..98c724d49047 100644
>> --- a/Documentation/admin-guide/pm/cpufreq.rst
>> +++ b/Documentation/admin-guide/pm/cpufreq.rst
>> @@ -586,8 +586,8 @@ This governor exposes the following tunables:
>> 100 (5 by default).
>> This is how much the frequency is allowed to change in one
>> go. Setting
>> - it to 0 will cause the default frequency step (5 percent) to be
>> used
>> - and setting it to 100 effectively causes the governor to
>> periodically
>> + it to 0 disables frequency changes by the governor entirely and
>> setting
>> + it to 100 effectively causes the governor to periodically
>> switch the frequency between the ``scaling_min_freq`` and
>> ``scaling_max_freq`` policy limits.
>
>
^ permalink raw reply
* Re: [PATCH mm-unstable v18 12/14] mm/khugepaged: avoid unnecessary mTHP collapse attempts
From: Lance Yang @ 2026-06-01 1:53 UTC (permalink / raw)
To: David Hildenbrand (Arm), npache
Cc: linux-doc, linux-kernel, linux-mm, linux-trace-kernel, aarcange,
akpm, anshuman.khandual, apopple, baohua, baolin.wang, byungchul,
catalin.marinas, cl, corbet, dave.hansen, dev.jain, gourry,
hannes, hughd, jack, jackmanb, jannh, jglisse, joshua.hahnjy, kas,
liam, ljs, mathieu.desnoyers, matthew.brost, mhiramat, mhocko,
peterx, pfalcato, rakie.kim, raquini, rdunlap, richard.weiyang,
rientjes, rostedt, rppt, ryan.roberts, shivankg, sunnanyong,
surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
zokeefe, usama.arif
In-Reply-To: <65e201dd-10d6-43f6-8758-0fc313158fe7@kernel.org>
On 2026/6/1 04:02, David Hildenbrand (Arm) wrote:
> On 5/31/26 09:31, Lance Yang wrote:
>>
>> On Fri, May 22, 2026 at 09:00:07AM -0600, Nico Pache wrote:
>>> There are cases where, if an attempted collapse fails, all subsequent
>>> orders are guaranteed to also fail. Avoid these collapse attempts by
>>> bailing out early.
>>>
>>> Reviewed-by: Lorenzo Stoakes <ljs@kernel.org>
>>> Acked-by: Usama Arif <usama.arif@linux.dev>
>>> Acked-by: David Hildenbrand (Arm) <david@kernel.org>
>>> Signed-off-by: Nico Pache <npache@redhat.com>
>>> ---
>>> mm/khugepaged.c | 24 +++++++++++++++++++++++-
>>> 1 file changed, 23 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>>> index d3d7db8be26c..15b7298bc225 100644
>>> --- a/mm/khugepaged.c
>>> +++ b/mm/khugepaged.c
>>> @@ -1535,9 +1535,31 @@ static int mthp_collapse(struct mm_struct *mm, struct vm_area_struct *vma,
>>> collapse_address = address + offset * PAGE_SIZE;
>>> ret = collapse_huge_page(mm, collapse_address, referenced,
>>> unmapped, cc, order);
>>> - if (ret == SCAN_SUCCEED) {
>>> +
>>> + switch (ret) {
>>> + /* Cases where we continue to next collapse candidate */
>>> + case SCAN_SUCCEED:
>>> collapsed += nr_ptes;
>>> + fallthrough;
>>> + case SCAN_PTE_MAPPED_HUGEPAGE:
>>> continue;
>>> + /* Cases where lower orders might still succeed */
>>> + case SCAN_LACK_REFERENCED_PAGE:
>>> + case SCAN_EXCEED_NONE_PTE:
>>> + case SCAN_EXCEED_SWAP_PTE:
>>> + case SCAN_EXCEED_SHARED_PTE:
>>> + case SCAN_PAGE_LOCK:
>>> + case SCAN_PAGE_COUNT:
>>> + case SCAN_PAGE_NULL:
>>> + case SCAN_DEL_PAGE_LRU:
>>> + case SCAN_PTE_NON_PRESENT:
>>> + case SCAN_PTE_UFFD_WP:
>>> + case SCAN_ALLOC_HUGE_PAGE_FAIL:
>>
>> Nit: shouldn't SCAN_CGROUP_CHARGE_FAIL go with SCAN_ALLOC_HUGE_PAGE_FAIL
>> here?
>>
>> If charging the current order fails, a smaller order might still fit :)
>
> I think the reasoning was here, that if we are already that close to our mem
> limit, we should just give up instead of trying to squeeze it in .. :)
Fair point. Just a nit, nevermind :)
^ permalink raw reply
* Re: [PATCH v2] docs/zh_CN: update admin-guide/index.rst translation
From: Dongliang Mu @ 2026-06-01 1:45 UTC (permalink / raw)
To: Yan Zhu, corbet, alexs, si.yanteng, kees
Cc: skhan, tony.luck, gpiccoli, frederic, jani.nikula, longman,
mchehab+huawei, linux-doc, linux-kernel
In-Reply-To: <tencent_FCA3F4312E849777081742CBAF2CD6BBA007@qq.com>
On 5/29/26 11:37 PM, Yan Zhu wrote:
> update Documentation/admin-guide/index.rst Chinese translation
>
> Update the translation through commit f0efd29aa60c
> ("doc: Add CPU Isolation documentation")
Reviewed-by: Dongliang Mu <dzm91@hust.edu.cn>
> Signed-off-by: Yan Zhu <zhuyan2015@qq.com>
> ---
> v1->v2:
> - Remove any unnecessary blank lines.
> - Add necessary blank lines.
> ---
> .../translations/zh_CN/admin-guide/index.rst | 202 +++++++++++++-----
> 1 file changed, 152 insertions(+), 50 deletions(-)
>
> diff --git a/Documentation/translations/zh_CN/admin-guide/index.rst b/Documentation/translations/zh_CN/admin-guide/index.rst
> index 15d9ab5993a7..bd01cf6474c8 100644
> --- a/Documentation/translations/zh_CN/admin-guide/index.rst
> +++ b/Documentation/translations/zh_CN/admin-guide/index.rst
> @@ -1,7 +1,13 @@
> +.. SPDX-License-Identifier: GPL-2.0
> .. include:: ../disclaimer-zh_CN.rst
>
> -:Original: :doc:`../../../admin-guide/index`
> -:Translator: Alex Shi <alex.shi@linux.alibaba.com>
> +:Original: Documentation/admin-guide/index.rst
> +
> +:翻译:
> +
> + 时奎亮 Alex Shi <alex.shi@linux.alibaba.com>
> +
> + 朱岩 Yan Zhu <zhuyan2015@qq.com>
>
>
> Linux 内核用户和管理员指南
> @@ -11,7 +17,11 @@ Linux 内核用户和管理员指南
> 整体的顺序或组织 - 这些材料不是一个单一的,连贯的文件!幸运的话,情况会随着
> 时间的推移而迅速改善。
>
> -这个初始部分包含总体信息,包括描述内核的README, 关于内核参数的文档等。
> +
> +内核管理通用指南
> +----------------
> +
> +本节包含总体信息,包括描述内核整体的 README 文件、内核参数文档等。
>
> .. toctree::
> :maxdepth: 1
> @@ -20,17 +30,54 @@ Linux 内核用户和管理员指南
>
> Todolist:
>
> -* kernel-parameters
> * devices
> +* features
> +
> +内核管理接口的重要组成部分是 /proc 和 sysfs 虚拟文件系统;这些文档描述了如何
> +与之交互。
> +
> +.. toctree::
> + :maxdepth: 1
> +
> + cputopology
> +
> +Todolist:
> +
> +* sysfs-rules
> * sysctl/index
> +* abi
>
> -本节介绍CPU漏洞及其缓解措施。
> +安全相关文档:
> +
> +.. toctree::
> + :maxdepth: 1
>
> Todolist:
>
> * hw-vuln/index
> +* LSM/index
> +* perf-security
> +
> +
> +内核启动
> +--------
> +
> +.. toctree::
> + :maxdepth: 1
> +
> + bootconfig
> +
> +Todolist:
> +
> +* kernel-parameters
> +* efi-stub
> +* initrd
> +
>
> -下面的一组文档,针对的是试图跟踪问题和bug的用户。
> +追踪和识别问题
> +--------------
> +
> +以下是一组面向试图追踪特定问题和 bug 的用户的文档。
>
> .. toctree::
> :maxdepth: 1
> @@ -39,94 +86,149 @@ Todolist:
> reporting-regressions
> bug-hunting
> bug-bisect
> - tainted-kernels
> init
> + clearing-warn-once
> + lockup-watchdogs
> + sysrq
>
> Todolist:
>
> +* quickly-build-trimmed-linux
> +* verify-bugs-and-bisect-regressions
> +* tainted-kernels
> * ramoops
> * dynamic-debug-howto
> * kdump/index
> * perf/index
> +* pstore-blk
> +* kernel-per-CPU-kthreads
> +* RAS/index
> +
> +
> +核心内核子系统
> +--------------
> +
> +这些文档描述了核心内核管理接口,这些接口几乎在任何系统上都值得关注。
> +
> +.. toctree::
> + :maxdepth: 1
>
> -这是应用程序开发人员感兴趣的章节的开始。可以在这里找到涵盖内核ABI各个
> -方面的文档。
> + cpu-load
> + mm/index
> + module-signing
> + numastat
>
> Todolist:
>
> -* sysfs-rules
> +* cgroup-v2
> +* cgroup-v1/index
> +* namespaces/index
> +* pm/index
> +* syscall-user-dispatch
>
> -本手册的其余部分包括各种指南,介绍如何根据您的喜好配置内核的特定行为。
>
> +对非原生二进制格式的支持。请注意,其中一些文档相当 **古老**。
>
> .. toctree::
> :maxdepth: 1
>
> - bootconfig
> - clearing-warn-once
> - cpu-load
> - cputopology
> - lockup-watchdogs
> - numastat
> - unicode
> - sysrq
> - mm/index
> +Todolist:
> +
> +* binfmt-misc
> +* java
> +* mono
> +
> +
> +块设备和文件系统管理
> +--------------------
> +
> +.. toctree::
> + :maxdepth: 1
>
> Todolist:
>
> -* acpi/index
> -* aoe/index
> -* auxdisplay/index
> * bcache
> * binderfs
> -* binfmt-misc
> * blockdev/index
> -* braille-console
> -* btmrvl
> -* cgroup-v1/index
> -* cgroup-v2
> * cifs/index
> -* dell_rbu
> * device-mapper/index
> -* edid
> -* efi-stub
> * ext4
> +* filesystem-monitoring
> * nfs/index
> -* gpio/index
> -* highuid
> -* hw_random
> -* initrd
> * iostats
> -* java
> * jfs
> -* kernel-per-CPU-kthreads
> +* md
> +* ufs
> +* xfs
> +
> +
> +专用设备指南
> +------------
> +
> +如何在 Linux 系统中配置硬件。
> +
> +.. toctree::
> + :maxdepth: 1
> +
> +Todolist:
> +
> +* acpi/index
> +* aoe/index
> +* auxdisplay/index
> +* braille-console
> +* btmrvl
> +* dell_rbu
> +* edid
> +* gpio/index
> +* hw_random
> * laptops/index
> * lcd-panel-cgram
> -* ldm
> -* LSM/index
> -* md
> * media/index
> -* module-signing
> -* mono
> -* namespaces/index
> +* nvme-multipath
> * parport
> -* perf-security
> -* pm/index
> * pnp
> * rapidio
> -* ras
> * rtc
> * serial-console
> * svga
> +* thermal/index
> * thunderbolt
> -* ufs
> * vga-softcursor
> * video-output
> -* xfs
> +
> +
> +工作负载分析
> +------------
> +
> +这是一个章节的开始,其中包含对从事 Linux 内核安全关键性分析的应用程序开发人员
> +和系统集成商感兴趣的信息。这里可以找到支持分析内核与应用程序交互以及关键内核
> +子系统预期的文档。
> +
> +.. toctree::
> + :maxdepth: 1
> +
> +Todolist:
> +
> +* workload-tracing
> +
> +
> +其他内容
> +--------
> +
> +一些难以分类且通常已过时的文档。
> +
> +.. toctree::
> + :maxdepth: 1
> +
> +Todolist:
> +
> +* highuid
> +* ldm
> +* unicode
>
> .. only:: subproject and html
>
> - Indices
> - =======
> + 索引
> + ====
>
> * :ref:`genindex`
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox