Re: [PATCH 2/3] KVM: vmx, svm, mmu: Process MMIO during event delivery
lp. By the way, why can't we move the call to kvm_io_bus_write into the common code (e.g. MMU)? It would remove the need of implementing KVM_FAST_MMIO_BUS specifically for each vendor. gpa_t gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS); - bool is_mmio = exit_reason.basic == EXIT_REASON_EPT_MISCONFIG; - Blank newline after variable declarations. - kvm_prepare_ev_delivery_failure_exit(vcpu, gpa, is_mmio); + kvm_prepare_ev_delivery_failure_exit(vcpu, gpa, false); return 0; } All in all, I think this is the basic gist? Definitely feel free to propose a better name than X86EMUL_UNHANDLEABLE_VECTORING. It sounds OK, but maybe something more precise would work, like X86EMUL_VECTORING_IO_NEEDED (by analogy with X86EMUL_IO_NEEDED)? Thanks a lot for the review. -- Kind regards, Ivan Orlov
Re: [PATCH 1/3] KVM: x86, vmx: Add function for event delivery error generation
On 10/16/24 22:05, Sean Christopherson wrote: On Tue, Oct 15, 2024, Ivan Orlov wrote: diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index c67e448c6ebd..afd785e7f3a3 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6550,19 +6550,10 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) exit_reason.basic != EXIT_REASON_APIC_ACCESS && exit_reason.basic != EXIT_REASON_TASK_SWITCH && exit_reason.basic != EXIT_REASON_NOTIFY)) { - int ndata = 3; + gpa_t gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS); + bool is_mmio = exit_reason.basic == EXIT_REASON_EPT_MISCONFIG; There's no need for is_mmio, just pass INVALID_GPA when the GPA isn't known. Ah alright, then we definitely don't need an is_mmio field. I assume we can't do MMIO at GPA=0, right? Wrong :-) Then getting rid of `is_mmio` will make distinguishing between vectoring error due to MMIO with GPA=0 and non-mmio vectoring error quite hard for the error reporti Passing INVALID_GPA into the userspace due to non-mmio vectoring error will change the existing internal.data order, but I can do it if it's fine. Sorry for nitpicking :) From an architectural perspective, GPA=0 is not special in any way. E.g. prior to L1TF, Linux would happily use the page with PFN=0. Cool, didn't know about this vulnerability... Thanks for the explanation! -- Kind regards, Ivan Orlov
Re: [PATCH 1/3] KVM: x86, vmx: Add function for event delivery error generation
Hi Sean, On Fri, Oct 11, 2024 at 04:20:46PM -0700, Sean Christopherson wrote: > "KVM: VMX:" for the scope. See "Shortlog" in > Documentation/process/maintainer-kvm-x86.rst > Ah, will update in the next version, thanks! > On Fri, Sep 27, 2024, Ivan Orlov wrote: > > Extract KVM_INTERNAL_ERROR_DELIVERY_EV internal error generation into > > the SVM/VMX-agnostic 'kvm_prepare_ev_delivery_failure_exit' function, as > > it is done for KVM_INTERNAL_ERROR_EMULATION. > > Use the changelog to provide a human readable summary of the change. There > are > definitely situations where calling out functions, variables, defines, etc. by > name is necessary, but this isn't one such situation. > > > The order of internal.data array entries is preserved as is, so it is going > > to be the same on VMX platforms (vectoring info, full exit reason, exit > > qualification, GPA if error happened due to MMIO and last_vmentry_cpu of the > > vcpu). > > Similar to the above, let the code speak. The "No functional change intended" > makes it clear that the intent is to preserve the order and behavior. > > > Having it as a separate function will help us to avoid code duplication > > Avoid pronouns as much as possible, and no "we" or "us" as a hard rule. E.g. > this > can all be distilled down to: > Yeah, makes sense. Will reformulate the message in the next version to consider all of the changes you suggested. > -- > Extract VMX's code for reporting an unhandleable VM-Exit during event > delivery to userspace, so that the boilerplate code can be shared by SVM. > > No functional change intended. > -- > Awesome, thanks for the example! > > Please wrap at 80 columns. While checkpatch doesn't complaing until 100, my > preference is to default to wrapping at 80, and poking past 80 only when it > yields > more readable code (which is obviously subjective, but it shouldn't be too > hard > to figure out KVM x86's preferred style). > Alright, will do, thanks! These rules vary from one subsystem to another, and I'll try to keep the style consistent in the future. > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > > index c67e448c6ebd..afd785e7f3a3 100644 > > --- a/arch/x86/kvm/vmx/vmx.c > > +++ b/arch/x86/kvm/vmx/vmx.c > > @@ -6550,19 +6550,10 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, > > fastpath_t exit_fastpath) > > exit_reason.basic != EXIT_REASON_APIC_ACCESS && > > exit_reason.basic != EXIT_REASON_TASK_SWITCH && > > exit_reason.basic != EXIT_REASON_NOTIFY)) { > > - int ndata = 3; > > + gpa_t gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS); > > + bool is_mmio = exit_reason.basic == EXIT_REASON_EPT_MISCONFIG; > > There's no need for is_mmio, just pass INVALID_GPA when the GPA isn't known. > Ah alright, then we definitely don't need an is_mmio field. I assume we can't do MMIO at GPA=0, right? > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > > index 83fe0a78146f..8ee67fc23e5d 100644 > > --- a/arch/x86/kvm/x86.c > > +++ b/arch/x86/kvm/x86.c > > @@ -8828,6 +8828,28 @@ void kvm_prepare_emulation_failure_exit(struct > > kvm_vcpu *vcpu) > > } > > EXPORT_SYMBOL_GPL(kvm_prepare_emulation_failure_exit); > > > > +void kvm_prepare_ev_delivery_failure_exit(struct kvm_vcpu *vcpu, gpa_t > > gpa, bool is_mmio) > > Hmm, I don't love the name. I really don't like that event is abbreviated, > and > I suspect many readers will be misinterpret "event delivery failure" to mean > that > _KVM_ failed to deliver an event. Which is kinda sorta true, but it's more > accurate to say that the CPU triggered a VM-Exit when vectoring/delivery an > event, > and KVM doesn't have code to robustly handle the situation. > > Maybe kvm_prepare_event_vectoring_exit()? Vectoring is quite specific in > Intel > terminology. > Yep, sounds good, I like that the name you suggested doesn't contain 'failure' part as essentially it is not a failure but an MMIO exit. Will update in V2. > > +{ > > + struct kvm_run *run = vcpu->run; > > + int ndata = 0; > > + u32 reason, intr_info, error_code; > > + u64 info1, info2; > > Reverse fir/x-mas tree for variables. See "Coding Style" in > Documentation/process/maintainer-kvm-x86.rst (which will redirect you to > Documentation/process/maintainer-tip.rst, specifically "Variable > declarations"). > Great, didn't know about that, tha
[PATCH 3/3] selftests: KVM: Add test case for MMIO during event delivery
Extend the 'set_memory_region_test' with a test case which covers the MMIO during event delivery error handling. The test case 1) Tries to set an IDT descriptor base to point to an MMIO address 2) Generates a #GP 3) Verifies that we got a correct exit reason (KVM_EXIT_INTERNAL_ERROR) and suberror code (KVM_INTERNAL_ERROR_DELIVERY_EV) 4) Verifies that we got a corrent "faulty" GPA in internal.data[3] Signed-off-by: Ivan Orlov --- .../selftests/kvm/set_memory_region_test.c| 46 +++ 1 file changed, 46 insertions(+) diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c index a8267628e9ed..e9e97346edf1 100644 --- a/tools/testing/selftests/kvm/set_memory_region_test.c +++ b/tools/testing/selftests/kvm/set_memory_region_test.c @@ -553,6 +553,51 @@ static void test_add_overlapping_private_memory_regions(void) close(memfd); kvm_vm_free(vm); } + +static const struct desc_ptr faulty_idt_desc = { + .address = MEM_REGION_GPA, + .size = 0xFFF, +}; + +static void guest_code_faulty_idt_desc(void) +{ + __asm__ __volatile__("lidt %0"::"m"(faulty_idt_desc)); + + /* Generate a #GP by dereferencing a non-canonical address */ + *((uint8_t *)0xDEADBEEFDEADBEEFULL) = 0x1; + + /* We should never reach this point */ + GUEST_ASSERT(0); +} + +/* + * This test tries to point the IDT descriptor base to an MMIO address. This action + * should cause a KVM internal error, so the VMM could handle such situations gracefully. + */ +static void test_faulty_idt_desc(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + + pr_info("Testing a faulty IDT descriptor pointing to an MMIO address\n"); + + vm = vm_create_with_one_vcpu(&vcpu, guest_code_faulty_idt_desc); + virt_map(vm, MEM_REGION_GPA, MEM_REGION_GPA, 1); + + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR); + TEST_ASSERT(vcpu->run->internal.suberror == KVM_INTERNAL_ERROR_DELIVERY_EV, + "Unexpected suberror = %d", vcpu->run->internal.suberror); + TEST_ASSERT(vcpu->run->internal.ndata > 4, "Unexpected internal error data array size = %d", + vcpu->run->internal.ndata); + + /* The "faulty" GPA address should be = IDT base + offset of the GP vector */ + TEST_ASSERT(vcpu->run->internal.data[3] == MEM_REGION_GPA + + GP_VECTOR * sizeof(struct idt_entry), + "Unexpected GPA = %llx", vcpu->run->internal.data[3]); + + kvm_vm_free(vm); +} #endif int main(int argc, char *argv[]) @@ -568,6 +613,7 @@ int main(int argc, char *argv[]) * KVM_RUN fails with ENOEXEC or EFAULT. */ test_zero_memory_regions(); + test_faulty_idt_desc(); #endif test_invalid_memory_region_flags(); -- 2.43.0
[PATCH 2/3] KVM: vmx, svm, mmu: Process MMIO during event delivery
Currently, the situation when guest accesses MMIO during event delivery is handled differently in VMX and SVM: on VMX KVM returns internal error with suberror = KVM_INTERNAL_ERROR_DELIVERY_EV, when SVM simply goes into infinite loop trying to deliver an event again and again. Such a situation could happen when the exception occurs with guest IDTR (or GDTR) descriptor base pointing to an MMIO address. Even with fixes for infinite loops on TDP failures applied, the problem still exists on SVM. Eliminate the SVM/VMX difference by returning a KVM internal error with suberror = KVM_INTERNAL_ERROR_DELIVERY_EV for both SVM and VMX. As we don't have a reliable way to detect MMIO operation on SVM before actually looking at the GPA, move the problem detection into the common KVM x86 layer (into the kvm_mmu_page_fault function) and add the PFERR_EVT_DELIVERY flag which gets set in the SVM/VMX specific vmexit handler to signal that we are in the middle of the event delivery. This way we won't introduce much overhead for VMX platform either, as the situation when the guest accesses MMIO during event delivery is quite rare and shouldn't happen frequently. Signed-off-by: Ivan Orlov --- arch/x86/include/asm/kvm_host.h | 6 ++ arch/x86/kvm/mmu/mmu.c | 15 ++- arch/x86/kvm/svm/svm.c | 4 arch/x86/kvm/vmx/vmx.c | 21 + 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 348daba424dd..a1088239c9f5 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -282,6 +282,12 @@ enum x86_intercept_stage; #define PFERR_PRIVATE_ACCESS BIT_ULL(49) #define PFERR_SYNTHETIC_MASK (PFERR_IMPLICIT_ACCESS | PFERR_PRIVATE_ACCESS) +/* + * EVT_DELIVERY is a KVM-defined flag used to indicate that a fault occurred + * during event delivery. + */ +#define PFERR_EVT_DELIVERY BIT_ULL(50) + /* apic attention bits */ #define KVM_APIC_CHECK_VAPIC 0 /* diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index e081f785fb23..36e25a6ba364 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -6120,8 +6120,21 @@ int noinline kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 err return -EFAULT; r = handle_mmio_page_fault(vcpu, cr2_or_gpa, direct); - if (r == RET_PF_EMULATE) + if (r == RET_PF_EMULATE) { + /* +* Check if the guest is accessing MMIO during event delivery. For +* instance, it could happen if the guest sets IDT / GDT descriptor +* base to point to an MMIO address. We can't deliver such an event +* without VMM intervention, so return a corresponding internal error +* instead (otherwise, vCPU will fall into infinite loop trying to +* deliver the event again and again). +*/ + if (error_code & PFERR_EVT_DELIVERY) { + kvm_prepare_ev_delivery_failure_exit(vcpu, cr2_or_gpa, true); + return 0; + } goto emulate; + } } if (r == RET_PF_INVALID) { diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 9df3e1e5ae81..93ce8c3d02f3 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2059,6 +2059,10 @@ static int npf_interception(struct kvm_vcpu *vcpu) u64 fault_address = svm->vmcb->control.exit_info_2; u64 error_code = svm->vmcb->control.exit_info_1; + /* Check if we have events awaiting delivery */ + if (svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK) + error_code |= PFERR_EVT_DELIVERY; + /* * WARN if hardware generates a fault with an error code that collides * with KVM-defined sythentic flags. Clear the flags and continue on, diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index afd785e7f3a3..bbe1126c3c7d 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -5828,6 +5828,11 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) static int handle_ept_misconfig(struct kvm_vcpu *vcpu) { gpa_t gpa; + u64 error_code = PFERR_RSVD_MASK; + + /* Do we have events awaiting delivery? */ + error_code |= (to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) +? PFERR_EVT_DELIVERY : 0; if (vmx_check_emulate_instruction(vcpu, EMULTYPE_PF, NULL, 0)) return 1; @@ -5843,7 +5848,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu) return kvm_skip_emulated_instruction(vcpu); } - return kvm_mmu_page_fault
[PATCH 1/3] KVM: x86, vmx: Add function for event delivery error generation
Extract KVM_INTERNAL_ERROR_DELIVERY_EV internal error generation into the SVM/VMX-agnostic 'kvm_prepare_ev_delivery_failure_exit' function, as it is done for KVM_INTERNAL_ERROR_EMULATION. The order of internal.data array entries is preserved as is, so it is going to be the same on VMX platforms (vectoring info, full exit reason, exit qualification, GPA if error happened due to MMIO and last_vmentry_cpu of the vcpu). Having it as a separate function will help us to avoid code duplication when handling the MMIO during event delivery error on SVM. No functional change intended. Signed-off-by: Ivan Orlov --- arch/x86/include/asm/kvm_host.h | 2 ++ arch/x86/kvm/vmx/vmx.c | 15 +++ arch/x86/kvm/x86.c | 22 ++ 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 6d9f763a7bb9..348daba424dd 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -2060,6 +2060,8 @@ void __kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu, u64 *data, u8 ndata); void kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu); +void kvm_prepare_ev_delivery_failure_exit(struct kvm_vcpu *vcpu, gpa_t gpa, bool is_mmio); + void kvm_enable_efer_bits(u64); bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer); int kvm_get_msr_with_filter(struct kvm_vcpu *vcpu, u32 index, u64 *data); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index c67e448c6ebd..afd785e7f3a3 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6550,19 +6550,10 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) exit_reason.basic != EXIT_REASON_APIC_ACCESS && exit_reason.basic != EXIT_REASON_TASK_SWITCH && exit_reason.basic != EXIT_REASON_NOTIFY)) { - int ndata = 3; + gpa_t gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS); + bool is_mmio = exit_reason.basic == EXIT_REASON_EPT_MISCONFIG; - vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; - vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV; - vcpu->run->internal.data[0] = vectoring_info; - vcpu->run->internal.data[1] = exit_reason.full; - vcpu->run->internal.data[2] = vmx_get_exit_qual(vcpu); - if (exit_reason.basic == EXIT_REASON_EPT_MISCONFIG) { - vcpu->run->internal.data[ndata++] = - vmcs_read64(GUEST_PHYSICAL_ADDRESS); - } - vcpu->run->internal.data[ndata++] = vcpu->arch.last_vmentry_cpu; - vcpu->run->internal.ndata = ndata; + kvm_prepare_ev_delivery_failure_exit(vcpu, gpa, is_mmio); return 0; } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 83fe0a78146f..8ee67fc23e5d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8828,6 +8828,28 @@ void kvm_prepare_emulation_failure_exit(struct kvm_vcpu *vcpu) } EXPORT_SYMBOL_GPL(kvm_prepare_emulation_failure_exit); +void kvm_prepare_ev_delivery_failure_exit(struct kvm_vcpu *vcpu, gpa_t gpa, bool is_mmio) +{ + struct kvm_run *run = vcpu->run; + int ndata = 0; + u32 reason, intr_info, error_code; + u64 info1, info2; + + kvm_x86_call(get_exit_info)(vcpu, &reason, &info1, &info2, &intr_info, &error_code); + + run->internal.data[ndata++] = info2; + run->internal.data[ndata++] = reason; + run->internal.data[ndata++] = info1; + if (is_mmio) + run->internal.data[ndata++] = (u64)gpa; + run->internal.data[ndata++] = vcpu->arch.last_vmentry_cpu; + + run->exit_reason = KVM_EXIT_INTERNAL_ERROR; + run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV; + run->internal.ndata = ndata; +} +EXPORT_SYMBOL_GPL(kvm_prepare_ev_delivery_failure_exit); + static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type) { struct kvm *kvm = vcpu->kvm; -- 2.43.0
[PATCH 0/3] Handle MMIO during event delivery error on SVM
Currently, the situation when guest accesses MMIO during event delivery is handled differently in VMX and SVM: on VMX KVM returns internal error with suberror = KVM_INTERNAL_ERROR_DELIVERY_EV, when SVM simply goes into infinite loop trying to deliver an event again and again. This patch series eliminates this difference by returning a KVM internal error with suberror = KVM_INTERNAL_ERROR_DELIVERY_EV when guest is performing MMIO during event delivery, for both VMX and SVM. Also, it introduces a selftest test case which covers the MMIO during event delivery error handling. Ivan Orlov (3): KVM: x86, vmx: Add function for event delivery error generation KVM: vmx, svm, mmu: Process MMIO during event delivery selftests: KVM: Add test case for MMIO during event delivery arch/x86/include/asm/kvm_host.h | 8 arch/x86/kvm/mmu/mmu.c| 15 +- arch/x86/kvm/svm/svm.c| 4 ++ arch/x86/kvm/vmx/vmx.c| 32 - arch/x86/kvm/x86.c| 22 + .../selftests/kvm/set_memory_region_test.c| 46 +++ 6 files changed, 104 insertions(+), 23 deletions(-) -- 2.43.0
Re: [PATCH 0/4] Process some MMIO-related errors without KVM exit
On Wed, Sep 25, 2024 at 05:06:45PM -0700, Sean Christopherson wrote: > > Yeah, but only because the alternative sucks worse. If KVM unconditionally > exited > with an emulation error, then unsuspecting (read: old) VMMs would likely > terminate > the guest, which gives guest userspace a way to DoS the entire VM, especially > on > older CPUs where KVM needs to emulate much more often. > > if (kvm->arch.exit_on_emulation_error || > (emulation_type & EMULTYPE_SKIP)) { > prepare_emulation_ctxt_failure_exit(vcpu); > return 0; > } > > kvm_queue_exception(vcpu, UD_VECTOR); > > if (!is_guest_mode(vcpu) && kvm_x86_call(get_cpl)(vcpu) == 0) { > prepare_emulation_ctxt_failure_exit(vcpu); > return 0; > } > > return 1; > > And that's exactly why KVM_CAP_EXIT_ON_EMULATION_FAILURE exists. VMMs that > know > they won't unintentionally give guest userspace what amounts to a privilege > escalation can trap the emulation failure, do some logging or whatever, and > then > take whatever action it wants to take. > Hi Sean, Makes sense, thank you for the explanation. > > and I believe how we do this > > is debatable. I maintain we should either set a flag in > > emulation_failure.flags > > to indicate that the error happened due to fetch from mmio (to give more > > information to VMM), > > Generally speaking, I'm not opposed to adding more information along those > lines. > Though realistically, I don't know that an extra flag is warranted in this > case, > as it shouldn't be _that_ hard for userspace to deduce what went wrong, > especially > if KVM_TRANSLATE2[*] lands (though I'm somewhat curious as to why QEMU > doesn't do > the page walks itself). > > [*] https://lore.kernel.org/all/20240910152207.38974-1-nik...@amazon.de > Fair enough, but I still believe that it would be good to provide more information about the failure to the VMM (considering the fact that KVM tries to emulate an instruction anyway, adding a flag won't introduce any performance overhead). I'll think about how we could do that without being redundant :) > > or we shouldn't return an error at all... Maybe it should be KVM_EXIT_MMIO > > with > > some flag set? What do you think? > > It'd be a breaking change and added complexity, for no benefit as far as I can > tell. KVM_EXIT_INTERNAL_ERROR is _not_ a death sentence, or at least it > doesn't > have to be. Most VMMs do terminate the guest, but nothing is stopping > userspace > from grabbing RIP and emulating the instruction. I.e. userspace doesn't need > "permission" in the form of KVM_EXIT_MMIO to try and keep the guest alive. Yeah, I just thought that "internal error" is not the best exit code for the situations when guest fetches from MMIO (since it is a perfectly legal operation from the architectural point of view). But I agree that it would be a breaking change without functional benefit ( especially if we provide a flag about what happened :) ). P.S. I tested the latest kvm/next, and if we set the IDT descriptor base to an MMIO address it still falls into the infinite loop on SVM. I'm going to send the fix in the next couple of days. Kind regards, Ivan Orlov
Re: [PATCH 0/4] Process some MMIO-related errors without KVM exit
On Mon, Sep 23, 2024 at 02:46:17PM -0700, Sean Christopherson wrote: > > > > > No. This is not architectural behavior. It's not even remotely > > > close to > > > architectural behavior. KVM's behavior isn't great, but making up > > > _guest visible_ > > > behavior is not going to happen. > > > > Is this a no to the whole series or from the cover letter? > > The whole series. > > > For patch 1 we have observed that if a guest has incorrectly set it's > > IDT base to point inside of an MMIO region it will result in a triple > > fault (bare metal Cascake Lake Intel). > > That happens because the IDT is garbage and/or the CPU is getting master abort > semantics back, not because anything in the x86 architectures says that > accessing > MMIO during exception vectoring goes straight to shutdown. > Hi Sean, thank you for the detailed reply. Yes, I ran the reproducer on my AMD Ryzen 5 once again, and it seems like pointing the IDT descriptor base to a framebuffer works perfectly fine, without any triple faults, so injecting it into guest is not a correct solution. However, I believe KVM should demonstrate consistent behaviour in handling MMIO during event delivery on vmx/svm, so either by returning an event delivery error in both cases or going into infinite loop in both cases. I'm going to test the kvm/next with the commits you mentioned, and send a fix if it still hits an infinite loop on SVM. Also, I reckon as detecting such an issue on the KVM level doesn't introduce much complexity, returning a sane error flag would be nice. For instance, we could set one of the 'internal.data' elements to identify that the problem occured due to MMIO during event delivery > > Yes a sane operating system is not really going to be doing setting it's IDT > > or GDT base to point into an MMIO region, but we've seen occurrences. > > Normally when other external things have gone horribly wrong. > > > > Ivan can clarify as to what's been seen on AMD platforms regarding the > > infinite loop for patch one. This was also tested on bare metal > > hardware. Injection of the #UD within patch 2 may be debatable but I > > believe Ivan has some more data from experiments backing this up. > > I have no problems improving KVM's handling of scenarios that KVM can't > emulate, > but there needs to be reasonable justification for taking on complexity, and > KVM > must not make up guest visible behavior. Regarding the #UD-related change: the way how I formulated it in the cover letter and the patch is confusing, sorry. We are _alredy_ enqueuing an #UD when fetching from MMIO, so I believe it is already architecturally incorrect (see handle_emulation_failure in arch/x86/kvm/x86.c). However, we return an emulation failure after that, and I believe how we do this is debatable. I maintain we should either set a flag in emulation_failure.flags to indicate that the error happened due to fetch from mmio (to give more information to VMM), or we shouldn't return an error at all... Maybe it should be KVM_EXIT_MMIO with some flag set? What do you think? Thank you! Kind regards, Ivan Orlov
[PATCH 3/4] selftests: KVM: Change expected exit code in test_zero_memory_regions
Update the set_memory_region test, test case test_zero_memory_regions to use an updated exit code if the VM starts with no RAM. Now we are issuing a triple fault in such a case, not an internal error. Signed-off-by: Ivan Orlov --- tools/testing/selftests/kvm/set_memory_region_test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c index bb8002084f52..d84d86668932 100644 --- a/tools/testing/selftests/kvm/set_memory_region_test.c +++ b/tools/testing/selftests/kvm/set_memory_region_test.c @@ -331,7 +331,8 @@ static void test_zero_memory_regions(void) vm_ioctl(vm, KVM_SET_NR_MMU_PAGES, (void *)64ul); vcpu_run(vcpu); - TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR); + /* No memory at all, we should triple fault */ + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); kvm_vm_free(vm); } -- 2.43.0
[PATCH 0/4] Process some MMIO-related errors without KVM exit
Currently, KVM may return a variety of internal errors to VMM when accessing MMIO, and some of them could be gracefully handled on the KVM level instead. Moreover, some of the MMIO-related errors are handled differently in VMX in comparison with SVM, which produces certain inconsistency and should be fixed. This patch series introduces KVM-level handling for the following situations: 1) Guest is accessing MMIO during event delivery: triple fault instead of internal error on VMX and infinite loop on SVM 2) Guest fetches an instruction from MMIO: inject #UD and resume guest execution without internal error Additionaly, this patch series includes a KVM selftest which covers different cases of MMIO misuse. Also, update the set_memory_region_test to expect the triple fault when starting VM with no RAM. Ivan Orlov (4): KVM: vmx, svm, mmu: Fix MMIO during event delivery handling KVM: x86: Inject UD when fetching from MMIO selftests: KVM: Change expected exit code in test_zero_memory_regions selftests: KVM: Add new test for faulty mmio usage arch/x86/include/asm/kvm_host.h | 6 + arch/x86/kvm/emulate.c| 3 + arch/x86/kvm/kvm_emulate.h| 1 + arch/x86/kvm/mmu/mmu.c| 13 +- arch/x86/kvm/svm/svm.c| 4 + arch/x86/kvm/vmx/vmx.c| 21 +- arch/x86/kvm/x86.c| 7 +- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/set_memory_region_test.c| 3 +- .../selftests/kvm/x86_64/faulty_mmio.c| 199 ++ 10 files changed, 242 insertions(+), 16 deletions(-) create mode 100644 tools/testing/selftests/kvm/x86_64/faulty_mmio.c -- 2.43.0
[PATCH 1/4] KVM: vmx, svm, mmu: Fix MMIO during event delivery handling
Currently, the situation when guest accesses MMIO during event delivery is handled differently in VMX and SVM: on VMX KVM returns internal error with suberror = KVM_INTERNAL_ERROR_DELIVERY_EV, when SVM simply goes into infinite loop trying to execute faulty instruction again and again. Such a situation can happen when the guest sets the IDTR (or GDTR) descriptor base to point to MMIO region, and as this issue can be triggered from the guest it is not an "internal" KVM error and it should be gracefully handled by KVM. Eliminate the SVM/VMX difference by triggering triple fault when MMIO happens during event delivery. As we don't have a reliable way to detect MMIO operation on SVM before actually looking at the GPA, move the problem detection into the common KVM x86 layer (into the kvm_mmu_page_fault function) and add the PFERR_EVT_DELIVERY flag which gets set in the SVM/VMX specific vmexit handler to signal that we are in the middle of the event delivery. Signed-off-by: Ivan Orlov --- arch/x86/include/asm/kvm_host.h | 6 ++ arch/x86/kvm/mmu/mmu.c | 13 - arch/x86/kvm/svm/svm.c | 4 arch/x86/kvm/vmx/vmx.c | 21 - 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4a68cb3eba78..292657fda063 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -284,6 +284,12 @@ enum x86_intercept_stage; PFERR_WRITE_MASK | \ PFERR_PRESENT_MASK) +/* + * EVT_DELIVERY is a KVM-defined flag used to indicate that vmexit occurred + * during event delivery. + */ +#define PFERR_EVT_DELIVERY BIT_ULL(50) + /* apic attention bits */ #define KVM_APIC_CHECK_VAPIC 0 /* diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 7813d28b082f..80db379766fb 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -5992,8 +5992,19 @@ int noinline kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 err return -EFAULT; r = handle_mmio_page_fault(vcpu, cr2_or_gpa, direct); - if (r == RET_PF_EMULATE) + if (r == RET_PF_EMULATE) { + /* +* Request triple fault if guest accesses MMIO during event delivery. +* It could happen if the guest sets the IDTR base to point to an MMIO +* range. This is not allowed and there is no way to recover after it. +*/ + if (error_code & PFERR_EVT_DELIVERY) { + pr_warn("Guest accesses MMIO during event delivery. Requesting triple fault.\n"); + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); + return 1; + } goto emulate; + } } if (r == RET_PF_INVALID) { diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 5ab2c92c7331..b83ca69b0e57 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2058,6 +2058,7 @@ static int npf_interception(struct kvm_vcpu *vcpu) u64 fault_address = svm->vmcb->control.exit_info_2; u64 error_code = svm->vmcb->control.exit_info_1; + u32 int_type = svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK; /* * WARN if hardware generates a fault with an error code that collides @@ -2071,6 +2072,9 @@ static int npf_interception(struct kvm_vcpu *vcpu) if (sev_snp_guest(vcpu->kvm) && (error_code & PFERR_GUEST_ENC_MASK)) error_code |= PFERR_PRIVATE_ACCESS; + if (int_type) + error_code |= PFERR_EVT_DELIVERY; + trace_kvm_page_fault(vcpu, fault_address, error_code); rc = kvm_mmu_page_fault(vcpu, fault_address, error_code, static_cpu_has(X86_FEATURE_DECODEASSISTS) ? diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 733a0c45d1a6..4d136fee7d63 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -5823,7 +5823,12 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu) static int handle_ept_misconfig(struct kvm_vcpu *vcpu) { + struct vcpu_vmx *vmx = to_vmx(vcpu); gpa_t gpa; + u64 error_code = PFERR_RSVD_MASK; + + if (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) + error_code |= PFERR_EVT_DELIVERY; if (vmx_check_emulate_instruction(vcpu, EMULTYPE_PF, NULL, 0)) return 1; @@ -5839,7 +5844,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu) return kvm_skip_emulated_instruction(vcpu); } - return kvm_mmu_page_fault(vcpu, gpa, PFERR_RSVD_MASK, N
[PATCH 2/4] KVM: x86: Inject UD when fetching from MMIO
Currently, we simply return a KVM internal error with suberror = KVM_INTERNAL_ERROR_EMULATION if the guest tries to fetch instruction from MMIO range as we simply can't decode it. I believe it is not the best thing to do, considering that 1) we don't give enough information to VMM about the issue we faced 2) the issue is triggered by the guest itself, so it is not the KVM "internal" error. Inject the #UD into the guest instead and resume it's execution without giving an error to VMM, as it would be if we can't find a valid instruction at MMIO address. Signed-off-by: Ivan Orlov --- arch/x86/kvm/emulate.c | 3 +++ arch/x86/kvm/kvm_emulate.h | 1 + arch/x86/kvm/x86.c | 7 ++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index e72aed25d721..d610c47fa1f4 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4742,10 +4742,13 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int ctxt->fetch.end = ctxt->fetch.data + insn_len; ctxt->opcode_len = 1; ctxt->intercept = x86_intercept_none; + ctxt->is_mmio_fetch = false; if (insn_len > 0) memcpy(ctxt->fetch.data, insn, insn_len); else { rc = __do_insn_fetch_bytes(ctxt, 1); + if (rc == X86EMUL_IO_NEEDED) + ctxt->is_mmio_fetch = true; if (rc != X86EMUL_CONTINUE) goto done; } diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h index 55a18e2f2dcd..46c0dec1 100644 --- a/arch/x86/kvm/kvm_emulate.h +++ b/arch/x86/kvm/kvm_emulate.h @@ -362,6 +362,7 @@ struct x86_emulate_ctxt { u8 seg_override; u64 d; unsigned long _eip; + bool is_mmio_fetch; /* Here begins the usercopy section. */ struct operand src; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c983c8e434b8..4fb57280ec7b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8857,7 +8857,12 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu, int emulation_type) kvm_queue_exception(vcpu, UD_VECTOR); - if (!is_guest_mode(vcpu) && kvm_x86_call(get_cpl)(vcpu) == 0) { + /* +* Don't return an internal error if the emulation error is caused by a fetch from MMIO +* address. Injecting a #UD should be enough. +*/ + if (!is_guest_mode(vcpu) && kvm_x86_call(get_cpl)(vcpu) == 0 && + !vcpu->arch.emulate_ctxt->is_mmio_fetch) { prepare_emulation_ctxt_failure_exit(vcpu); return 0; } -- 2.43.0
[PATCH 4/4] selftests: KVM: Add new test for faulty mmio usage
Implement the test which covers "weird" mmio usage. The test has 4 test cases: 1) Guest sets IDT/GDT base to point to an MMIO region. Triple fault and shutdown are expected there. 2) Guest jumps to MMIO address. Fetches from MMIO are not permitted, so UD is expected there. 3) Guest sets an IDT entry to point to MMIO range. MMIO here happens after event delivery, so UD is expected. 4) Guest points the UD IDT entry to MMIO range and causes UD after that. We should not go into infinite loop here, as we are constantly putting exception info onto the stack and it will eventually overflow. These test cases depend on previous patches in this patch series. Signed-off-by: Ivan Orlov --- tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/x86_64/faulty_mmio.c| 199 ++ 2 files changed, 200 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/faulty_mmio.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 0c4b254ab56b..d9928c54e851 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -129,6 +129,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/amx_test TEST_GEN_PROGS_x86_64 += x86_64/max_vcpuid_cap_test TEST_GEN_PROGS_x86_64 += x86_64/triple_fault_event_test TEST_GEN_PROGS_x86_64 += x86_64/recalc_apic_map_test +TEST_GEN_PROGS_x86_64 += x86_64/faulty_mmio TEST_GEN_PROGS_x86_64 += access_tracking_perf_test TEST_GEN_PROGS_x86_64 += demand_paging_test TEST_GEN_PROGS_x86_64 += dirty_log_test diff --git a/tools/testing/selftests/kvm/x86_64/faulty_mmio.c b/tools/testing/selftests/kvm/x86_64/faulty_mmio.c new file mode 100644 index ..b83c1d646696 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/faulty_mmio.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This test covers error processing when doing weird things with MMIO addresses, + * i.e. jumping into MMIO range or specifying it as IDT / GDT descriptor base. + */ +#include +#include "kvm_util.h" +#include "processor.h" +#include + +#define MMIO_ADDR 0xDEADBEE000UL +/* This address is not canonical, so any reference will result in #GP */ +#define GP_ADDR 0xDEADBEEFDEADBEEFULL + +enum test_desc_type { + TEST_DESC_IDT, + TEST_DESC_GDT, +}; + +static const struct desc_ptr faulty_desc = { + .address = MMIO_ADDR, + .size = 0xFFF, +}; + +static void faulty_desc_guest_code(enum test_desc_type dtype) +{ + if (dtype == TEST_DESC_IDT) + __asm__ __volatile__("lidt %0"::"m"(faulty_desc)); + else + __asm__ __volatile__("lgdt %0"::"m"(faulty_desc)); + + /* Generate a #GP */ + *((uint8_t *)GP_ADDR) = 0x1; + + /* We should never reach this point */ + GUEST_ASSERT(0); +} + +/* + * This test tries to point the IDT / GDT descriptor to an MMIO range. + * This action should cause a triple fault in guest, as it happens when + * your descriptors are messed up on the actual hardware. + */ +static void test_faulty_desc(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + int i; + + enum test_desc_type dtype_tests[] = { TEST_DESC_IDT, TEST_DESC_GDT }; + + for (i = 0; i < ARRAY_SIZE(dtype_tests); i++) { + vm = vm_create_with_one_vcpu(&vcpu, faulty_desc_guest_code); + vcpu_args_set(vcpu, 1, dtype_tests[i]); + virt_map(vm, MMIO_ADDR, MMIO_ADDR, 1); + + vcpu_run(vcpu); + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); + kvm_vm_free(vm); + } +} + +static void jump_to_mmio_guest_code(bool write_first) +{ + void (*f)(void) = (void *)(MMIO_ADDR); + + if (write_first) { + /* +* We get different vmexit codes when accessing the MMIO address for the second +* time with VMX. For the first time it is an EPT violation, for the second - +* EPT misconfig. We need to check that we get #UD in both cases. +*/ + *((char *)MMIO_ADDR) = 0x1; + } + + f(); + + /* We should never reach this point */ + GUEST_ASSERT(0); +} + +static void guest_ud_handler(struct ex_regs *regs) +{ + GUEST_DONE(); +} + +/* + * This test tries to jump to an MMIO address. As fetching the instructions + * from MMIO is not supported by KVM and doesn't make any practical sense, + * KVM should handle it gracefully and inject #UD into guest. + */ +static void test_jump_to_mmio(void) +{ + struct kvm_vm *vm; + struct kvm_vcpu *vcpu; + struct kvm_run *run; + struct ucall uc; + int i; + + bool test_cases_write_first[] = { false, true }; + + for (i = 0; i < ARRAY_SIZE(test_cases_write_first); i++) { + vm = vm_create_with_one_vcpu(&vcpu, jump_to_mmio_guest_code); +
Re: [PATCH] Fix typo in tpmrm class definition
On 08.09.2023 18:06, Justin M. Forbes wrote: Commit d2e8071bed0be ("tpm: make all 'class' structures const") unfortunately had a typo for the name on tpmrm. Fixes: d2e8071bed0b ("tpm: make all 'class' structures const") Signed-off-by: Justin M. Forbes --- drivers/char/tpm/tpm-chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 23f6f2eda84c..42b1062e33cd 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -33,7 +33,7 @@ const struct class tpm_class = { .shutdown_pre = tpm_class_shutdown, }; const struct class tpmrm_class = { - .name = "tmprm", + .name = "tpmrm", }; dev_t tpm_devt; Hi Justin, Thank you for fixing this mistake, it's my bad :( I'm not sure if you know this or not, but merge window is still opened, so the patch could be accidentally skipped by maintainers as they have a huge load during this period... Perhaps resending it in a few days might be a good idea. Also, probably adding 'tpm:' prefix to the commit title could make it more noticeable to the maintainers. Thank you again for doing this. -- Kind regards, Ivan Orlov
[PATCH net-next v2 3/3] net: phy: marvell-88x2222: swap 1G/10G modes on autoneg
Setting 10G without autonegotiation is invalid according to phy_ethtool_ksettings_set(). Thus, we need to set it during autonegotiation. If 1G autonegotiation can't complete for quite a time, but there is signal in line, switch line interface type to 10GBase-R, if supported, in hope for link to be established. And vice versa. If 10GBase-R link can't be established for quite a time, and autonegotiation is enabled, and there is signal in line, switch line interface type to appropriate 1G mode, i.e. 1000Base-X or SGMII, if supported. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/marvell-88x.c | 117 +++--- 1 file changed, 89 insertions(+), 28 deletions(-) diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c index 640b133f1371..9b9ac3ef735d 100644 --- a/drivers/net/phy/marvell-88x.c +++ b/drivers/net/phy/marvell-88x.c @@ -52,6 +52,8 @@ #defineMV_1GBX_PHY_STAT_SPEED100 BIT(14) #defineMV_1GBX_PHY_STAT_SPEED1000 BIT(15) +#defineAUTONEG_TIMEOUT 3 + struct mv_data { phy_interface_t line_interface; __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); @@ -173,6 +175,24 @@ static bool mv_is_1gbx_capable(struct phy_device *phydev) priv->supported); } +static bool mv_is_sgmii_capable(struct phy_device *phydev) +{ + struct mv_data *priv = phydev->priv; + + return (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, + priv->supported)); +} + static int mv_config_line(struct phy_device *phydev) { struct mv_data *priv = phydev->priv; @@ -192,7 +212,8 @@ static int mv_config_line(struct phy_device *phydev) } } -static int mv_setup_forced(struct phy_device *phydev) +/* Switch between 1G (1000Base-X/SGMII) and 10G (10GBase-R) modes */ +static int mv_swap_line_type(struct phy_device *phydev) { struct mv_data *priv = phydev->priv; bool changed = false; @@ -200,25 +221,23 @@ static int mv_setup_forced(struct phy_device *phydev) switch (priv->line_interface) { case PHY_INTERFACE_MODE_10GBASER: - if (phydev->speed == SPEED_1000 && - mv_is_1gbx_capable(phydev)) { + if (mv_is_1gbx_capable(phydev)) { priv->line_interface = PHY_INTERFACE_MODE_1000BASEX; changed = true; } - break; - case PHY_INTERFACE_MODE_1000BASEX: - if (phydev->speed == SPEED_1 && - mv_is_10g_capable(phydev)) { - priv->line_interface = PHY_INTERFACE_MODE_10GBASER; + if (mv_is_sgmii_capable(phydev)) { + priv->line_interface = PHY_INTERFACE_MODE_SGMII; changed = true; } break; + case PHY_INTERFACE_MODE_1000BASEX: case PHY_INTERFACE_MODE_SGMII: - ret = mv_set_sgmii_speed(phydev); - if (ret < 0) - return ret; + if (mv_is_10g_capable(phydev)) { + priv->line_interface = PHY_INTERFACE_MODE_10GBASER; + changed = true; + } break; default: @@ -231,6 +250,29 @@ static int mv_setup_forced(struct phy_device *phydev) return ret; } + return 0; +} + +static int mv_setup_forced(struct phy_device *phydev) +{ + struct mv_data *priv = phydev->priv; + int ret; + + if (priv->line_interface == PHY_INTERFACE_MODE_10GBASER) { + if (phydev->speed < SPEED_1 && + phydev->speed != SPEED_UNKNOWN) { + ret = mv_swap_line_type(phydev); + if (ret < 0) + return ret; + } + } + + if (priv->line_interface == PHY_INTERFACE_MODE_SGMII) { + ret = mv_set_sgmii_speed(phydev); + if (ret < 0) + return ret; + } + return mv_disable_aneg(phyd
[PATCH net-next v2 0/3] net: phy: marvell-88x2222: a couple of improvements
First, there are some SFP modules that only uses RX_LOS for link indication. Add check that link is operational before actual read of line-side status. Second, it is invalid to set 10G speed without autonegotiation, according to phy_ethtool_ksettings_set(). Implement switching between 10GBase-R and 1000Base-X/SGMII if autonegotiation can't complete but there is signal in line. Changelog: v1 -> v2: * make checking that link is operational more friendly for trancievers without SFP cages. * split swapping 1G/10G modes into non-functional and functional commits for the sake of easier review. Ivan Bornyakov (3): net: phy: marvell-88x: check that link is operational net: phy: marvell-88x: move read_status after config_aneg net: phy: marvell-88x: swap 1G/10G modes on autoneg drivers/net/phy/marvell-88x.c | 314 -- 1 file changed, 209 insertions(+), 105 deletions(-) -- 2.26.3
[PATCH net-next v2 2/3] net: phy: marvell-88x2222: move read_status after config_aneg
No functional changes, just move read link status routines below autonegotiation configuration to make future functional changes more distinct. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/marvell-88x.c | 196 +++--- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c index 28fe520228a4..640b133f1371 100644 --- a/drivers/net/phy/marvell-88x.c +++ b/drivers/net/phy/marvell-88x.c @@ -86,104 +86,6 @@ static int mv_soft_reset(struct phy_device *phydev) 5000, 100, true); } -/* Returns negative on error, 0 if link is down, 1 if link is up */ -static int mv_read_status_10g(struct phy_device *phydev) -{ - int val, link = 0; - - val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1); - if (val < 0) - return val; - - if (val & MDIO_STAT1_LSTATUS) { - link = 1; - - /* 10GBASE-R do not support auto-negotiation */ - phydev->autoneg = AUTONEG_DISABLE; - phydev->speed = SPEED_1; - phydev->duplex = DUPLEX_FULL; - } - - return link; -} - -/* Returns negative on error, 0 if link is down, 1 if link is up */ -static int mv_read_status_1g(struct phy_device *phydev) -{ - int val, link = 0; - - val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_STAT); - if (val < 0) - return val; - - if (!(val & BMSR_LSTATUS) || - (phydev->autoneg == AUTONEG_ENABLE && -!(val & BMSR_ANEGCOMPLETE))) - return 0; - - link = 1; - - val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_PHY_STAT); - if (val < 0) - return val; - - if (val & MV_1GBX_PHY_STAT_AN_RESOLVED) { - if (val & MV_1GBX_PHY_STAT_DUPLEX) - phydev->duplex = DUPLEX_FULL; - else - phydev->duplex = DUPLEX_HALF; - - if (val & MV_1GBX_PHY_STAT_SPEED1000) - phydev->speed = SPEED_1000; - else if (val & MV_1GBX_PHY_STAT_SPEED100) - phydev->speed = SPEED_100; - else - phydev->speed = SPEED_10; - } - - return link; -} - -static bool mv_link_is_operational(struct phy_device *phydev) -{ - struct mv_data *priv = phydev->priv; - int val; - - val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_RX_SIGNAL_DETECT); - if (val < 0 || !(val & MV_RX_SIGNAL_DETECT_GLOBAL)) - return false; - - if (phydev->sfp_bus && !priv->sfp_link) - return false; - - return true; -} - -static int mv_read_status(struct phy_device *phydev) -{ - struct mv_data *priv = phydev->priv; - int link; - - phydev->link = 0; - phydev->speed = SPEED_UNKNOWN; - phydev->duplex = DUPLEX_UNKNOWN; - - if (!mv_link_is_operational(phydev)) - return 0; - - if (priv->line_interface == PHY_INTERFACE_MODE_10GBASER) - link = mv_read_status_10g(phydev); - else - link = mv_read_status_1g(phydev); - - if (link < 0) - return link; - - phydev->link = link; - - return 0; -} - static int mv_disable_aneg(struct phy_device *phydev) { int ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_CTRL, @@ -386,6 +288,104 @@ static int mv_aneg_done(struct phy_device *phydev) return (ret & BMSR_ANEGCOMPLETE); } +/* Returns negative on error, 0 if link is down, 1 if link is up */ +static int mv_read_status_10g(struct phy_device *phydev) +{ + int val, link = 0; + + val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1); + if (val < 0) + return val; + + if (val & MDIO_STAT1_LSTATUS) { + link = 1; + + /* 10GBASE-R do not support auto-negotiation */ + phydev->autoneg = AUTONEG_DISABLE; + phydev->speed = SPEED_1; + phydev->duplex = DUPLEX_FULL; + } + + return link; +} + +/* Returns negative on error, 0 if link is down, 1 if link is up */ +static int mv_read_status_1g(struct phy_device *phydev) +{ + int val, link = 0; + + val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_STAT); + if (val < 0) + return val; + + if (!(val & BMSR_LSTATUS) || + (phydev->autoneg == AUTONEG_ENABLE && +!(val & BMSR_ANEGCOMPLETE))) + return 0; + + link = 1; + + val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_PHY_STAT); + if (val < 0) + return val; + + if (v
[PATCH net-next v2 1/3] net: phy: marvell-88x2222: check that link is operational
Some SFP modules uses RX_LOS for link indication. In such cases link will be always up, even without cable connected. RX_LOS changes will trigger link_up()/link_down() upstream operations. Thus, check that SFP link is operational before actual read link status. If there is no SFP cage connected to the tranciever, check only PMD Recieve Signal Detect register. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/marvell-88x.c | 43 +++ 1 file changed, 43 insertions(+) diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c index eca8c2f20684..28fe520228a4 100644 --- a/drivers/net/phy/marvell-88x.c +++ b/drivers/net/phy/marvell-88x.c @@ -32,6 +32,10 @@ #defineMV_HOST_RST_SW BIT(7) #defineMV_PORT_RST_SW (MV_LINE_RST_SW | MV_HOST_RST_SW) +/* PMD Receive Signal Detect */ +#defineMV_RX_SIGNAL_DETECT 0x000A +#defineMV_RX_SIGNAL_DETECT_GLOBAL BIT(0) + /* 1000Base-X/SGMII Control Register */ #defineMV_1GBX_CTRL(0x2000 + MII_BMCR) @@ -51,6 +55,7 @@ struct mv_data { phy_interface_t line_interface; __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); + bool sfp_link; }; /* SFI PMA transmit enable */ @@ -139,6 +144,21 @@ static int mv_read_status_1g(struct phy_device *phydev) return link; } +static bool mv_link_is_operational(struct phy_device *phydev) +{ + struct mv_data *priv = phydev->priv; + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_RX_SIGNAL_DETECT); + if (val < 0 || !(val & MV_RX_SIGNAL_DETECT_GLOBAL)) + return false; + + if (phydev->sfp_bus && !priv->sfp_link) + return false; + + return true; +} + static int mv_read_status(struct phy_device *phydev) { struct mv_data *priv = phydev->priv; @@ -148,6 +168,9 @@ static int mv_read_status(struct phy_device *phydev) phydev->speed = SPEED_UNKNOWN; phydev->duplex = DUPLEX_UNKNOWN; + if (!mv_link_is_operational(phydev)) + return 0; + if (priv->line_interface == PHY_INTERFACE_MODE_10GBASER) link = mv_read_status_10g(phydev); else @@ -446,9 +469,29 @@ static void mv_sfp_remove(void *upstream) linkmode_zero(priv->supported); } +static void mv_sfp_link_up(void *upstream) +{ + struct phy_device *phydev = upstream; + struct mv_data *priv; + + priv = phydev->priv; + priv->sfp_link = true; +} + +static void mv_sfp_link_down(void *upstream) +{ + struct phy_device *phydev = upstream; + struct mv_data *priv; + + priv = phydev->priv; + priv->sfp_link = false; +} + static const struct sfp_upstream_ops sfp_phy_ops = { .module_insert = mv_sfp_insert, .module_remove = mv_sfp_remove, + .link_up = mv_sfp_link_up, + .link_down = mv_sfp_link_down, .attach = phy_sfp_attach, .detach = phy_sfp_detach, }; -- 2.26.3
Re: [PATCH net-next 1/2] net: phy: marvell-88x2222: check that link is operational
On Tue, Apr 13, 2021 at 10:23:48AM +0100, Russell King - ARM Linux admin wrote: > On Tue, Apr 13, 2021 at 10:19:30AM +0300, Ivan Bornyakov wrote: > > On Tue, Apr 13, 2021 at 01:40:32AM +0200, Andrew Lunn wrote: > > > On Mon, Apr 12, 2021 at 03:16:59PM +0300, Ivan Bornyakov wrote: > > > > Some SFP modules uses RX_LOS for link indication. In such cases link > > > > will be always up, even without cable connected. RX_LOS changes will > > > > trigger link_up()/link_down() upstream operations. Thus, check that SFP > > > > link is operational before actual read link status. > > > > > > Sorry, but this is not making much sense to me. > > > > > > LOS just indicates some sort of light is coming into the device. You > > > have no idea what sort of light. The transceiver might be able to > > > decode that light and get sync, it might not. It is important that > > > mv_read_status() returns the line side status. Has it been able to > > > achieve sync? That should be independent of LOS. Or are you saying the > > > transceiver is reporting sync, despite no light coming in? > > > > > > Andrew > > > > Yes, with some SFP modules transceiver is reporting sync despite no > > light coming in. So, the idea is to check that link is somewhat > > operational before determing line-side status. > > Indeed - it should be a logical and operation - there is light present > _and_ the PHY recognises the signal. This is what the commit achieves, > although (iirc) doesn't cater for the case where there is no SFP cage > attached. > > -- > RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ > FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last! Correct, it does not, I only have HW with SFP cage attached.
Re: [PATCH net-next 1/2] net: phy: marvell-88x2222: check that link is operational
On Tue, Apr 13, 2021 at 01:40:32AM +0200, Andrew Lunn wrote: > On Mon, Apr 12, 2021 at 03:16:59PM +0300, Ivan Bornyakov wrote: > > Some SFP modules uses RX_LOS for link indication. In such cases link > > will be always up, even without cable connected. RX_LOS changes will > > trigger link_up()/link_down() upstream operations. Thus, check that SFP > > link is operational before actual read link status. > > Sorry, but this is not making much sense to me. > > LOS just indicates some sort of light is coming into the device. You > have no idea what sort of light. The transceiver might be able to > decode that light and get sync, it might not. It is important that > mv_read_status() returns the line side status. Has it been able to > achieve sync? That should be independent of LOS. Or are you saying the > transceiver is reporting sync, despite no light coming in? > > Andrew Yes, with some SFP modules transceiver is reporting sync despite no light coming in. So, the idea is to check that link is somewhat operational before determing line-side status.
Re: [PATCH net-next 1/2] net: phy: marvell-88x2222: check that link is operational
On Tue, Apr 13, 2021 at 01:32:12AM +0200, Marek Behún wrote: > On Mon, 12 Apr 2021 15:16:59 +0300 > Ivan Bornyakov wrote: > > > Some SFP modules uses RX_LOS for link indication. In such cases link > > will be always up, even without cable connected. RX_LOS changes will > > trigger link_up()/link_down() upstream operations. Thus, check that SFP > > link is operational before actual read link status. > > > > Signed-off-by: Ivan Bornyakov > > --- > > drivers/net/phy/marvell-88x.c | 26 ++ > > 1 file changed, 26 insertions(+) > > > > diff --git a/drivers/net/phy/marvell-88x.c > > b/drivers/net/phy/marvell-88x.c > > index eca8c2f20684..fb285ac741b2 100644 > > --- a/drivers/net/phy/marvell-88x.c > > +++ b/drivers/net/phy/marvell-88x.c > > @@ -51,6 +51,7 @@ > > struct mv_data { > > phy_interface_t line_interface; > > __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); > > + bool sfp_link; > > }; > > > > /* SFI PMA transmit enable */ > > @@ -148,6 +149,9 @@ static int mv_read_status(struct phy_device *phydev) > > phydev->speed = SPEED_UNKNOWN; > > phydev->duplex = DUPLEX_UNKNOWN; > > > > + if (!priv->sfp_link) > > + return 0; > > + > > So if SFP is not used at all, if this PHY is used in a different > usecase, this function will always return 0? Is this correct? > Yes, probably. The thing is that I only have hardware with SFP cages, so I realy don't know if this driver work in other usecases. The good thing about open source is that other developers with different hardware configurations can rework here and there and contribute back. Right? > > if (priv->line_interface == PHY_INTERFACE_MODE_10GBASER) > > link = mv_read_status_10g(phydev); > > else > > @@ -446,9 +450,31 @@ static void mv_sfp_remove(void *upstream) > > linkmode_zero(priv->supported); > > } > > > > +static void mv_sfp_link_up(void *upstream) > > +{ > > + struct phy_device *phydev = upstream; > > + struct mv_data *priv; > > + > > + priv = (struct mv_data *)phydev->priv; > > + > > + priv->sfp_link = true; > > +} > > + > > +static void mv_sfp_link_down(void *upstream) > > +{ > > + struct phy_device *phydev = upstream; > > + struct mv_data *priv; > > + > > + priv = (struct mv_data *)phydev->priv; > > This cast is redundant since the phydev->priv is (void*). You can cast > (void*) to (struct ... *). > > You can also just use > struct mv_data *priv = phydev->priv; > Yeah, I know, but reverse XMAS tree wouldn't line up. > > + > > + priv->sfp_link = false; > > +} > > + > > static const struct sfp_upstream_ops sfp_phy_ops = { > > .module_insert = mv_sfp_insert, > > .module_remove = mv_sfp_remove, > > + .link_up = mv_sfp_link_up, > > + .link_down = mv_sfp_link_down, > > .attach = phy_sfp_attach, > > .detach = phy_sfp_detach, > > }; >
[PATCH net-next 2/2] net: phy: marvell-88x2222: swap 1G/10G modes on autoneg
Setting 10G without autonegotiation is invalid according to phy_ethtool_ksettings_set(). Thus, if autonegotiation can't complete for quite a time, but there is signal in line, switch line interface type to 10GBase-R, if supported, in hope for link to be established. And vice versa. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/marvell-88x.c | 276 ++ 1 file changed, 168 insertions(+), 108 deletions(-) diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c index fb285ac741b2..d16c81f08334 100644 --- a/drivers/net/phy/marvell-88x.c +++ b/drivers/net/phy/marvell-88x.c @@ -48,6 +48,8 @@ #defineMV_1GBX_PHY_STAT_SPEED100 BIT(14) #defineMV_1GBX_PHY_STAT_SPEED1000 BIT(15) +#defineAUTONEG_TIMEOUT 3 + struct mv_data { phy_interface_t line_interface; __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); @@ -82,89 +84,6 @@ static int mv_soft_reset(struct phy_device *phydev) 5000, 100, true); } -/* Returns negative on error, 0 if link is down, 1 if link is up */ -static int mv_read_status_10g(struct phy_device *phydev) -{ - int val, link = 0; - - val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1); - if (val < 0) - return val; - - if (val & MDIO_STAT1_LSTATUS) { - link = 1; - - /* 10GBASE-R do not support auto-negotiation */ - phydev->autoneg = AUTONEG_DISABLE; - phydev->speed = SPEED_1; - phydev->duplex = DUPLEX_FULL; - } - - return link; -} - -/* Returns negative on error, 0 if link is down, 1 if link is up */ -static int mv_read_status_1g(struct phy_device *phydev) -{ - int val, link = 0; - - val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_STAT); - if (val < 0) - return val; - - if (!(val & BMSR_LSTATUS) || - (phydev->autoneg == AUTONEG_ENABLE && -!(val & BMSR_ANEGCOMPLETE))) - return 0; - - link = 1; - - val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_PHY_STAT); - if (val < 0) - return val; - - if (val & MV_1GBX_PHY_STAT_AN_RESOLVED) { - if (val & MV_1GBX_PHY_STAT_DUPLEX) - phydev->duplex = DUPLEX_FULL; - else - phydev->duplex = DUPLEX_HALF; - - if (val & MV_1GBX_PHY_STAT_SPEED1000) - phydev->speed = SPEED_1000; - else if (val & MV_1GBX_PHY_STAT_SPEED100) - phydev->speed = SPEED_100; - else - phydev->speed = SPEED_10; - } - - return link; -} - -static int mv_read_status(struct phy_device *phydev) -{ - struct mv_data *priv = phydev->priv; - int link; - - phydev->link = 0; - phydev->speed = SPEED_UNKNOWN; - phydev->duplex = DUPLEX_UNKNOWN; - - if (!priv->sfp_link) - return 0; - - if (priv->line_interface == PHY_INTERFACE_MODE_10GBASER) - link = mv_read_status_10g(phydev); - else - link = mv_read_status_1g(phydev); - - if (link < 0) - return link; - - phydev->link = link; - - return 0; -} - static int mv_disable_aneg(struct phy_device *phydev) { int ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_CTRL, @@ -252,6 +171,24 @@ static bool mv_is_1gbx_capable(struct phy_device *phydev) priv->supported); } +static bool mv_is_sgmii_capable(struct phy_device *phydev) +{ + struct mv_data *priv = phydev->priv; + + return (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, + priv->supported)); +} + static int mv_config_line(struct phy_device *phydev) { struct mv_data *priv = phydev->priv; @@ -271,7 +208,7 @@ static int mv_config_line(struct phy_device *phydev) } } -static int mv_setup_forced(struct phy_device *phydev) +static int mv_swap_line_type(struct phy_device *phydev) { st
[PATCH net-next 0/2] net: phy: marvell-88x2222: a couple of improvements
First, there are some SFP modules that only uses RX_LOS for link indication. Add check that SFP link is operational before actual read of link status. Second, it is invalid to set 10G speed without autonegotiation, according to phy_ethtool_ksettings_set(). Implement switching between 10GBase-R and 1000Base-X/SGMII if autonegotiation can't complete but there is signal in line. Ivan Bornyakov (2): net: phy: marvell-88x: check that link is operational net: phy: marvell-88x: swap 1G/10G modes on autoneg drivers/net/phy/marvell-88x.c | 296 +++--- 1 file changed, 191 insertions(+), 105 deletions(-) -- 2.26.3
[PATCH net-next 1/2] net: phy: marvell-88x2222: check that link is operational
Some SFP modules uses RX_LOS for link indication. In such cases link will be always up, even without cable connected. RX_LOS changes will trigger link_up()/link_down() upstream operations. Thus, check that SFP link is operational before actual read link status. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/marvell-88x.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c index eca8c2f20684..fb285ac741b2 100644 --- a/drivers/net/phy/marvell-88x.c +++ b/drivers/net/phy/marvell-88x.c @@ -51,6 +51,7 @@ struct mv_data { phy_interface_t line_interface; __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); + bool sfp_link; }; /* SFI PMA transmit enable */ @@ -148,6 +149,9 @@ static int mv_read_status(struct phy_device *phydev) phydev->speed = SPEED_UNKNOWN; phydev->duplex = DUPLEX_UNKNOWN; + if (!priv->sfp_link) + return 0; + if (priv->line_interface == PHY_INTERFACE_MODE_10GBASER) link = mv_read_status_10g(phydev); else @@ -446,9 +450,31 @@ static void mv_sfp_remove(void *upstream) linkmode_zero(priv->supported); } +static void mv_sfp_link_up(void *upstream) +{ + struct phy_device *phydev = upstream; + struct mv_data *priv; + + priv = (struct mv_data *)phydev->priv; + + priv->sfp_link = true; +} + +static void mv_sfp_link_down(void *upstream) +{ + struct phy_device *phydev = upstream; + struct mv_data *priv; + + priv = (struct mv_data *)phydev->priv; + + priv->sfp_link = false; +} + static const struct sfp_upstream_ops sfp_phy_ops = { .module_insert = mv_sfp_insert, .module_remove = mv_sfp_remove, + .link_up = mv_sfp_link_up, + .link_down = mv_sfp_link_down, .attach = phy_sfp_attach, .detach = phy_sfp_detach, }; -- 2.26.3
Re: [PATCH 2/2] staging:r8188eu: remove dummy handlers from OnAction()
On 4/2/21 4:04 PM, Greg Kroah-Hartman wrote: On Sun, Mar 28, 2021 at 07:33:25PM +0300, Ivan Safonov wrote: on_action_spct() do nothing, because rtw_get_stainfo() has no side effects. Other action handlers are trivial. Signed-off-by: Ivan Safonov Same here, wrong driver name :( Driver name is "r8188eu"... $ grep 'r8188eu' drivers/staging/rtl8188eu/include/drv_types.h #define DRV_NAME "r8188eu" $ grep 'r8188eu' drivers/staging/rtl8188eu/os_dep/usb_intf.c -B1 -A7 static struct usb_driver rtl8188e_usb_drv = { .name = "r8188eu", .probe = rtw_drv_init, .disconnect = rtw_dev_remove, .id_table = rtw_usb_id_tbl, .suspend = rtw_suspend, .resume = rtw_resume, .reset_resume = rtw_resume, }; $ cat drivers/staging/rtl8188eu/Kconfig # SPDX-License-Identifier: GPL-2.0 config R8188EU tristate "Realtek RTL8188EU Wireless LAN NIC driver" depends on WLAN && USB && CFG80211 depends on m select WIRELESS_EXT select WEXT_PRIV select LIB80211 select LIB80211_CRYPT_WEP select LIB80211_CRYPT_CCMP help This option adds the Realtek RTL8188EU USB device such as TP-Link TL-WN725N. If built as a module, it will be called r8188eu. if R8188EU config 88EU_AP_MODE bool "Realtek RTL8188EU AP mode" default y help This option enables Access Point mode. Unless you know that your system will never be used as an AP, or the target system has limited memory, "Y" should be selected. endif
[PATCH net] net: octeon: mgmt: fix xmit hang as busy
The issue happens only at appropriate circumstances, in my case I faced it only while running crash kernel, when basic kernel worked fine. The code inspection has shown tx_current_fill counter overflow, after one packet or couple packets were sent. That's because tx cleanup tasklet dequeued bunch of not correct packets afterwards when it should only one. As result xmit queue counter becomes more than tx ring size and xmit always returns NETDEV_TX_BUSY. The reason is in some trash got by dma after ringing the bell. The wmb() in correct place solved the issue, so reason likely in removal of mips_swiotlb_ops which had an mb() after most of the operations and the removal of the ops had broken the tx functionality of the driver implicitly. The patch has been tested on Octeon II. Fixes: a33db9ed ("MIPS: remove mips_swiotlb_ops") Change-Id: I947c359d9451c75a693bc4a3f2958489503fc0ab Signed-off-by: Ivan Khoronzhuk --- Based on net/master drivers/net/ethernet/cavium/octeon/octeon_mgmt.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c index ecffebd513be..be1c353b961c 100644 --- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c @@ -1315,6 +1315,10 @@ octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev) spin_unlock_irqrestore(&p->tx_list.lock, flags); + /* Make sure there is no reorder of filling the ring and ringing +* the bell +*/ + wmb(); dma_sync_single_for_device(p->dev, p->tx_ring_handle, ring_size_to_bytes(OCTEON_MGMT_TX_RING_SIZE), DMA_BIDIRECTIONAL); -- 2.18.2
[PATCH 1/2] staging:r8188eu: refactor OnAction(): use switch instead table lookup
The switch is easier to read and refactor. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 57 --- .../staging/rtl8188eu/include/rtw_mlme_ext.h | 6 -- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 50d3c3631be0..4d741737d671 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -3780,26 +3780,10 @@ static unsigned int DoReserved(struct adapter *padapter, return _SUCCESS; } -static struct action_handler OnAction_tbl[] = { - {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,"ACTION_SPECTRUM_MGMT", on_action_spct}, - {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos}, - {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls}, - {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back}, - {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public}, - {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved}, - {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved}, - {RTW_WLAN_CATEGORY_HT, "ACTION_HT",&OnAction_ht}, - {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved}, - {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm}, - {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p}, -}; - static unsigned int OnAction(struct adapter *padapter, struct recv_frame *precv_frame) { - int i; unsigned char category; - struct action_handler *ptable; unsigned char *frame_body; u8 *pframe = precv_frame->pkt->data; @@ -3807,11 +3791,44 @@ static unsigned int OnAction(struct adapter *padapter, category = frame_body[0]; - for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) { - ptable = &OnAction_tbl[i]; - if (category == ptable->num) - ptable->func(padapter, precv_frame); + switch (category) { + case RTW_WLAN_CATEGORY_SPECTRUM_MGMT: + on_action_spct(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_QOS: + OnAction_qos(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_DLS: + OnAction_dls(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_BACK: + OnAction_back(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_PUBLIC: + on_action_public(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_RADIO_MEASUREMENT: + DoReserved(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_FT: + DoReserved(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_HT: + OnAction_ht(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_SA_QUERY: + DoReserved(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_WMM: + OnAction_wmm(padapter, precv_frame); + break; + case RTW_WLAN_CATEGORY_P2P: + OnAction_p2p(padapter, precv_frame); + break; + default: + break; } + return _SUCCESS; } diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index b11a6886a083..aa733abad10c 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -227,12 +227,6 @@ struct mlme_handler { unsigned int (*func)(struct adapter *adapt, struct recv_frame *frame); }; -struct action_handler { - unsigned int num; - const char *str; - unsigned int (*func)(struct adapter *adapt, struct recv_frame *frame); -}; - struct ss_res { int state; int bss_cnt; -- 2.26.2
[PATCH 2/2] staging:r8188eu: remove dummy handlers from OnAction()
on_action_spct() do nothing, because rtw_get_stainfo() has no side effects. Other action handlers are trivial. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 95 --- 1 file changed, 95 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 4d741737d671..fca02f17ba98 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -3517,56 +3517,6 @@ static unsigned int OnAtim(struct adapter *padapter, return _SUCCESS; } -static unsigned int on_action_spct(struct adapter *padapter, - struct recv_frame *precv_frame) -{ - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *pframe = precv_frame->pkt->data; - u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); - u8 category; - u8 action; - - DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); - - psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); - - if (!psta) - goto exit; - - category = frame_body[0]; - if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT) - goto exit; - - action = frame_body[1]; - switch (action) { - case WLAN_ACTION_SPCT_MSR_REQ: - case WLAN_ACTION_SPCT_MSR_RPRT: - case WLAN_ACTION_SPCT_TPC_REQ: - case WLAN_ACTION_SPCT_TPC_RPRT: - break; - case WLAN_ACTION_SPCT_CHL_SWITCH: - break; - default: - break; - } - -exit: - return _FAIL; -} - -static unsigned int OnAction_qos(struct adapter *padapter, -struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static unsigned int OnAction_dls(struct adapter *padapter, -struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - static unsigned int OnAction_back(struct adapter *padapter, struct recv_frame *precv_frame) { @@ -3756,24 +3706,6 @@ static unsigned int on_action_public(struct adapter *padapter, return ret; } -static unsigned int OnAction_ht(struct adapter *padapter, - struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static unsigned int OnAction_wmm(struct adapter *padapter, -struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - -static unsigned int OnAction_p2p(struct adapter *padapter, -struct recv_frame *precv_frame) -{ - return _SUCCESS; -} - static unsigned int DoReserved(struct adapter *padapter, struct recv_frame *precv_frame) { @@ -3792,39 +3724,12 @@ static unsigned int OnAction(struct adapter *padapter, category = frame_body[0]; switch (category) { - case RTW_WLAN_CATEGORY_SPECTRUM_MGMT: - on_action_spct(padapter, precv_frame); - break; - case RTW_WLAN_CATEGORY_QOS: - OnAction_qos(padapter, precv_frame); - break; - case RTW_WLAN_CATEGORY_DLS: - OnAction_dls(padapter, precv_frame); - break; case RTW_WLAN_CATEGORY_BACK: OnAction_back(padapter, precv_frame); break; case RTW_WLAN_CATEGORY_PUBLIC: on_action_public(padapter, precv_frame); break; - case RTW_WLAN_CATEGORY_RADIO_MEASUREMENT: - DoReserved(padapter, precv_frame); - break; - case RTW_WLAN_CATEGORY_FT: - DoReserved(padapter, precv_frame); - break; - case RTW_WLAN_CATEGORY_HT: - OnAction_ht(padapter, precv_frame); - break; - case RTW_WLAN_CATEGORY_SA_QUERY: - DoReserved(padapter, precv_frame); - break; - case RTW_WLAN_CATEGORY_WMM: - OnAction_wmm(padapter, precv_frame); - break; - case RTW_WLAN_CATEGORY_P2P: - OnAction_p2p(padapter, precv_frame); - break; default: break; } -- 2.26.2
[RESEND PATCH v4 net-next] net: phy: add Marvell 88X2222 transceiver support
Add basic support for the Marvell 88X multi-speed ethernet transceiver. This PHY provides data transmission over fiber-optic as well as Twinax copper links. The 88X supports 2 ports of 10GBase-R and 1000Base-X on the line-side interface. The host-side interface supports 4 ports of 10GBase-R, RXAUI, 1000Base-X and 2 ports of XAUI. This driver, however, supports only XAUI on the host-side and 1000Base-X/10GBase-R on the line-side, for now. The SGMII is also supported over 1000Base-X. Interrupts are not supported. Internal registers access compliant with the Clause 45 specification. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/Kconfig | 6 + drivers/net/phy/Makefile | 1 + drivers/net/phy/marvell-88x.c | 519 ++ include/linux/marvell_phy.h | 1 + 4 files changed, 527 insertions(+) create mode 100644 drivers/net/phy/marvell-88x.c diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 698bea312adc..a615b3660b05 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -201,6 +201,12 @@ config MARVELL_10G_PHY help Support for the Marvell Alaska MV88X3310 and compatible PHYs. +config MARVELL_88X_PHY + tristate "Marvell 88X PHY" + help + Support for the Marvell 88X Dual-port Multi-speed Ethernet + Transceiver. + config MICREL_PHY tristate "Micrel PHYs" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index a13e402074cf..de683e3abe63 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o obj-$(CONFIG_MARVELL_PHY) += marvell.o +obj-$(CONFIG_MARVELL_88X_PHY) += marvell-88x.o obj-$(CONFIG_MESON_GXL_PHY)+= meson-gxl.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o obj-$(CONFIG_MICREL_PHY) += micrel.o diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c new file mode 100644 index ..eca8c2f20684 --- /dev/null +++ b/drivers/net/phy/marvell-88x.c @@ -0,0 +1,519 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Marvell 88x dual-port multi-speed ethernet transceiver. + * + * Supports: + * XAUI on the host side. + * 1000Base-X or 10GBase-R on the line side. + * SGMII over 1000Base-X. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Port PCS Configuration */ +#defineMV_PCS_CONFIG 0xF002 +#defineMV_PCS_HOST_XAUI0x73 +#defineMV_PCS_LINE_10GBR (0x71 << 8) +#defineMV_PCS_LINE_1GBX_AN (0x7B << 8) +#defineMV_PCS_LINE_SGMII_AN(0x7F << 8) + +/* Port Reset and Power Down */ +#defineMV_PORT_RST 0xF003 +#defineMV_LINE_RST_SW BIT(15) +#defineMV_HOST_RST_SW BIT(7) +#defineMV_PORT_RST_SW (MV_LINE_RST_SW | MV_HOST_RST_SW) + +/* 1000Base-X/SGMII Control Register */ +#defineMV_1GBX_CTRL(0x2000 + MII_BMCR) + +/* 1000BASE-X/SGMII Status Register */ +#defineMV_1GBX_STAT(0x2000 + MII_BMSR) + +/* 1000Base-X Auto-Negotiation Advertisement Register */ +#defineMV_1GBX_ADVERTISE (0x2000 + MII_ADVERTISE) + +/* 1000Base-X PHY Specific Status Register */ +#defineMV_1GBX_PHY_STAT0xA003 +#defineMV_1GBX_PHY_STAT_AN_RESOLVEDBIT(11) +#defineMV_1GBX_PHY_STAT_DUPLEX BIT(13) +#defineMV_1GBX_PHY_STAT_SPEED100 BIT(14) +#defineMV_1GBX_PHY_STAT_SPEED1000 BIT(15) + +struct mv_data { + phy_interface_t line_interface; + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); +}; + +/* SFI PMA transmit enable */ +static int mv_tx_enable(struct phy_device *phydev) +{ + return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, + MDIO_PMD_TXDIS_GLOBAL); +} + +/* SFI PMA transmit disable */ +static int mv_tx_disable(struct phy_device *phydev) +{ + return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, + MDIO_PMD_TXDIS_GLOBAL); +} + +static int mv_soft_reset(struct phy_device *phydev) +{ + int val, ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PORT_RST, + MV_PORT_RST_SW); + if (ret < 0) + return ret; + + return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND2, MV_PORT_RST, +val, !(val & MV_PORT_RST_SW), +5000, 100, true); +} + +/* Returns negative on error, 0 if link is down, 1 if link is up */ +static int mv_read_status_10g(struct phy_device *phydev) +{ + int val,
[PATCH 0/4] staging:r8188eu: remove unnecessary definitions from wifi.h
wifi.h contains unnecessary definitions. Some of them are not used at all, some can be replaced with native definitions. Ivan Safonov (4): staging:r8188eu: replace get_(d|s)a with ieee80211_get_(D|S)A staging:r8188eu: remove unused definitions from wifi.h staging:r8188eu: replace cap_* definitions with native kernel WLAN_CAPABILITY_* staging:r8188eu: use ieee80211_is_ctl instead IsFrameTypeCtrl .../staging/rtl8188eu/core/rtw_ieee80211.c| 6 +- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 12 +- drivers/staging/rtl8188eu/core/rtw_recv.c | 4 +- .../staging/rtl8188eu/hal/rtl8188e_rxdesc.c | 8 +- drivers/staging/rtl8188eu/include/wifi.h | 156 -- 5 files changed, 16 insertions(+), 170 deletions(-) -- 2.26.2
[PATCH 1/4] staging:r8188eu: replace get_(d|s)a with ieee80211_get_(D|S)A
get_da()/get_sa() duplicate native ieee80211_get_(D|S)A functions. Remove get_(d|s)a, use ieee80211_get_(D|S)A instead. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 6 +-- drivers/staging/rtl8188eu/core/rtw_recv.c | 4 +- .../staging/rtl8188eu/hal/rtl8188e_rxdesc.c | 4 +- drivers/staging/rtl8188eu/include/wifi.h | 44 --- 4 files changed, 7 insertions(+), 51 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index ebd9b96a8211..bee19d5b22c0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -2526,7 +2526,7 @@ static unsigned int OnProbeReq(struct adapter *padapter, if (check_fwstate(pmlmepriv, _FW_LINKED) && pmlmepriv->cur_network.join_res) - issue_probersp(padapter, get_sa(pframe)); + issue_probersp(padapter, ieee80211_get_SA((struct ieee80211_hdr *)pframe)); } return _SUCCESS; } @@ -2819,7 +2819,7 @@ static unsigned int OnAuthClient(struct adapter *padapter, DBG_88E("%s\n", __func__); /* check A1 matches or not */ - if (memcmp(myid(&padapter->eeprompriv), get_da(pframe), ETH_ALEN)) + if (memcmp(myid(&padapter->eeprompriv), ieee80211_get_DA((struct ieee80211_hdr *)pframe), ETH_ALEN)) return _SUCCESS; if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) @@ -3332,7 +3332,7 @@ static unsigned int OnAssocRsp(struct adapter *padapter, DBG_88E("%s\n", __func__); /* check A1 matches or not */ - if (memcmp(myid(&padapter->eeprompriv), get_da(pframe), ETH_ALEN)) + if (memcmp(myid(&padapter->eeprompriv), ieee80211_get_DA((struct ieee80211_hdr *)pframe), ETH_ALEN)) return _SUCCESS; if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 36bcbe635cf4..b9b4bc435037 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -1029,8 +1029,8 @@ static int validate_recv_data_frame(struct adapter *adapter, int ret = _SUCCESS; bretry = GetRetry(ptr); - pda = get_da(ptr); - psa = get_sa(ptr); + pda = ieee80211_get_DA((struct ieee80211_hdr *)ptr); + psa = ieee80211_get_SA((struct ieee80211_hdr *)ptr); pbssid = get_hdr_bssid(ptr); if (!pbssid) { diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index 0d06cb54b1ad..4fae75fc3dd5 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -150,7 +150,7 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, get_bssid(&padapter->mlmepriv), ETH_ALEN)); pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && -(!memcmp(get_da(wlanhdr), +(!memcmp(ieee80211_get_DA((struct ieee80211_hdr *)wlanhdr), myid(&padapter->eeprompriv), ETH_ALEN)); pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && @@ -161,7 +161,7 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, sa = padapter->mlmepriv.cur_network.network.MacAddress; /* to do Ad-hoc */ } else { - sa = get_sa(wlanhdr); + sa = ieee80211_get_SA((struct ieee80211_hdr *)wlanhdr); } pstapriv = &padapter->stapriv; diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index 1b9006879a11..5ee4d02e293c 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -201,50 +201,6 @@ enum WIFI_REG_DOMAIN { #define GetAddr4Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 24)) -static inline unsigned char *get_da(unsigned char *pframe) -{ - unsigned char *da; - unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); - - switch (to_fr_ds) { - case 0x00: /* ToDs=0, FromDs=0 */ - da = GetAddr1Ptr(pframe); - break; - case 0x01: /* ToDs=0, FromDs=1 */ - da = GetAddr1Ptr(pframe); - break; - case 0x02: /* ToDs=1, FromDs=0 */ - da = GetAddr3Ptr(pframe); - break; - default:/* ToDs=1, FromDs=1 */ - da = GetAddr3Ptr(pframe); - break; - } - return da; -} - -static inline unsigned char *get_sa(unsigned char *pframe) -{ - unsigned char *sa; -
[PATCH 4/4] staging:r8188eu: use ieee80211_is_ctl instead IsFrameTypeCtrl
IsFrameTypeCtrl() duplicate ieee80211_is_ctl(). Signed-off-by: Ivan Safonov --- drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c | 8 +--- drivers/staging/rtl8188eu/include/wifi.h| 8 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c index 4fae75fc3dd5..8669bf097479 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_rxdesc.c @@ -133,6 +133,8 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, struct rx_pkt_attrib *pattrib = &precvframe->attrib; struct odm_phy_status_info *pPHYInfo = (struct odm_phy_status_info *)(&pattrib->phy_info); u8 *wlanhdr; + struct ieee80211_hdr *hdr = + (struct ieee80211_hdr *)precvframe->pkt->data; struct odm_per_pkt_info pkt_info; u8 *sa = NULL; struct sta_priv *pstapriv; @@ -144,13 +146,13 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, wlanhdr = precvframe->pkt->data; - pkt_info.bPacketMatchBSSID = ((!IsFrameTypeCtrl(wlanhdr)) && + pkt_info.bPacketMatchBSSID = (!ieee80211_is_ctl(hdr->frame_control) && !pattrib->icv_err && !pattrib->crc_err && !memcmp(get_hdr_bssid(wlanhdr), get_bssid(&padapter->mlmepriv), ETH_ALEN)); pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && -(!memcmp(ieee80211_get_DA((struct ieee80211_hdr *)wlanhdr), +(!memcmp(ieee80211_get_DA(hdr), myid(&padapter->eeprompriv), ETH_ALEN)); pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && @@ -161,7 +163,7 @@ void update_recvframe_phyinfo_88e(struct recv_frame *precvframe, sa = padapter->mlmepriv.cur_network.network.MacAddress; /* to do Ad-hoc */ } else { - sa = ieee80211_get_SA((struct ieee80211_hdr *)wlanhdr); + sa = ieee80211_get_SA(hdr); } pstapriv = &padapter->stapriv; diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index d65a0a88a69a..84e17330628e 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -197,14 +197,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) return sa; } -static inline int IsFrameTypeCtrl(unsigned char *pframe) -{ - if (GetFrameType(pframe) == WIFI_CTRL_TYPE) - return true; - else - return false; -} - /*- Below is for the security related definition --*/ -- 2.26.2
[PATCH 3/4] staging:r8188eu: replace cap_* definitions with native kernel WLAN_CAPABILITY_*
cap_* definitions duplicate WLAN_CAPABILITY_*. Remove cap_* definitions, improve code consistency. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8188eu/core/rtw_ieee80211.c | 6 +++--- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 6 +++--- drivers/staging/rtl8188eu/include/wifi.h | 12 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index ec5b8be14c2b..7a706fe11750 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -223,13 +223,13 @@ int rtw_generate_ie(struct registry_priv *pregistrypriv) /* capability info */ *(u16 *)ie = 0; - *(__le16 *)ie |= cpu_to_le16(cap_IBSS); + *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_IBSS); if (pregistrypriv->preamble == PREAMBLE_SHORT) - *(__le16 *)ie |= cpu_to_le16(cap_ShortPremble); + *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); if (pdev_network->Privacy) - *(__le16 *)ie |= cpu_to_le16(cap_Privacy); + *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); sz += 2; ie += 2; diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index bee19d5b22c0..50d3c3631be0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -2188,7 +2188,7 @@ static void start_create_ibss(struct adapter *padapter) /* update capability */ caps = rtw_get_capability(pnetwork); update_capinfo(padapter, caps); - if (caps & cap_IBSS) {/* adhoc master */ + if (caps & WLAN_CAPABILITY_IBSS) {/* adhoc master */ val8 = 0xcf; rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); @@ -2240,7 +2240,7 @@ static void start_clnt_join(struct adapter *padapter) /* update capability */ caps = rtw_get_capability(pnetwork); update_capinfo(padapter, caps); - if (caps & cap_ESS) { + if (caps & WLAN_CAPABILITY_ESS) { Set_MSR(padapter, WIFI_FW_STATION_STATE); val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; @@ -2258,7 +2258,7 @@ static void start_clnt_join(struct adapter *padapter) msecs_to_jiffies((REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout)); pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE; - } else if (caps & cap_IBSS) { /* adhoc client */ + } else if (caps & WLAN_CAPABILITY_IBSS) { /* adhoc client */ Set_MSR(padapter, WIFI_FW_ADHOC_STATE); val8 = 0xcf; diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index f03359602db7..d65a0a88a69a 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -238,18 +238,6 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) #define AUTH_ODD_TO0 #define AUTH_EVEN_TO 1 -#define cap_ESSBIT(0) -#define cap_IBSS BIT(1) -#define cap_CFPollable BIT(2) -#define cap_CFRequest BIT(3) -#define cap_PrivacyBIT(4) -#define cap_ShortPremble BIT(5) -#define cap_PBCC BIT(6) -#define cap_ChAgility BIT(7) -#define cap_SpecMgmt BIT(8) -#define cap_QoSi BIT(9) -#define cap_ShortSlot BIT(10) - /*- Below is the definition for 802.11i / 802.1x --*/ -- 2.26.2
[PATCH 2/4] staging:r8188eu: remove unused definitions from wifi.h
These definitions are not used and will not be useful in the future. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8188eu/include/wifi.h | 92 1 file changed, 92 deletions(-) diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index 5ee4d02e293c..f03359602db7 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -7,21 +7,8 @@ #ifndef _WIFI_H_ #define _WIFI_H_ -#define WLAN_IEEE_OUI_LEN 3 -#define WLAN_CRC_LEN 4 -#define WLAN_BSSID_LEN 6 -#define WLAN_BSS_TS_LEN8 #define WLAN_HDR_A3_LEN24 -#define WLAN_HDR_A4_LEN30 #define WLAN_HDR_A3_QOS_LEN26 -#define WLAN_HDR_A4_QOS_LEN32 -#define WLAN_DATA_MAXLEN 2312 - -#define WLAN_A3_PN_OFFSET 24 -#define WLAN_A4_PN_OFFSET 30 - -#define WLAN_MIN_ETHFRM_LEN60 -#define WLAN_MAX_ETHFRM_LEN1514 #define P80211CAPTURE_VERSION 0x80211001 @@ -74,20 +61,6 @@ enum WIFI_FRAME_SUBTYPE { WIFI_QOS_DATA_NULL = (BIT(6) | WIFI_QOS_DATA_TYPE), }; -enum WIFI_REG_DOMAIN { - DOMAIN_FCC = 1, - DOMAIN_IC = 2, - DOMAIN_ETSI = 3, - DOMAIN_SPA = 4, - DOMAIN_FRANCE = 5, - DOMAIN_MKK = 6, - DOMAIN_ISRAEL = 7, - DOMAIN_MKK1 = 8, - DOMAIN_MKK2 = 9, - DOMAIN_MKK3 = 10, - DOMAIN_MAX -}; - #define SetToDs(pbuf) \ *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS) @@ -199,8 +172,6 @@ enum WIFI_REG_DOMAIN { #define GetAddr3Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 16)) -#define GetAddr4Ptr(pbuf) ((unsigned char *)((size_t)(pbuf) + 24)) - static inline unsigned char *get_hdr_bssid(unsigned char *pframe) { unsigned char *sa; @@ -237,19 +208,6 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) /*- Below is for the security related definition --*/ -#define _RESERVED_FRAME_TYPE_ 0 -#define _SKB_FRAME_TYPE_ 2 -#define _PRE_ALLOCMEM_ 1 -#define _PRE_ALLOCHDR_ 3 -#define _PRE_ALLOCLLCHDR_ 4 -#define _PRE_ALLOCICVHDR_ 5 -#define _PRE_ALLOCMICHDR_ 6 - -#define _SIFSTIME_ \ - ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) ? 16 : 10) -#define _ACKCTSLNG_14 /* 14 bytes long, including crclng */ -#define _CRCLNG_ 4 - #define _ASOCREQ_IE_OFFSET_4 /* excluding wlan_hdr */ #define_ASOCRSP_IE_OFFSET_ 6 #define _REASOCREQ_IE_OFFSET_ 10 @@ -280,10 +238,6 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) #define AUTH_ODD_TO0 #define AUTH_EVEN_TO 1 -#define WLAN_ETHCONV_ENCAP 1 -#define WLAN_ETHCONV_RFC1042 2 -#define WLAN_ETHCONV_8021h 3 - #define cap_ESSBIT(0) #define cap_IBSS BIT(1) #define cap_CFPollable BIT(2) @@ -316,7 +270,6 @@ static inline int IsFrameTypeCtrl(unsigned char *pframe) Below is the definition for WMM --*/ #define _WMM_IE_Length_7 /* for WMM STA */ -#define _WMM_Para_Element_Length_ 24 /*- Below is the definition for 802.11n @@ -388,13 +341,6 @@ enum ht_cap_ampdu_factor { #define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT((u8)BIT(3)) #define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8)BIT(4)) -#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16)BIT(6)) -#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16)BIT(7)) -#define HT_INFO_STBC_PARAM_SECONDARY_BC((u16)BIT(8)) -#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16)BIT(9)) -#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16)BIT(10)) -#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16)BIT(11)) - /* ===WPS Section=== */ /* For WPSv1.0 */ #define WPSOUI 0x0050f204 @@ -453,48 +399,10 @@ enum ht_cap_ampdu_factor { #define WPS_CONFIG_METHOD_VDISPLAY 0x2008 #define WPS_CONFIG_METHOD_PDISPLAY 0x4008 -/* Value of Category ID of WPS Primary Device Type Attribute */ -#define WPS_PDT_CID_DISPLAYS 0x0007 -#define WPS_PDT_CID_MULIT_MEDIA0x0008 -#define WPS_PDT_CID_RTK_WIDI WPS_PDT_CID_MULIT_MEDIA - -/* Value of Sub Category ID of WPS Primary Device Type Attribute */ -#define WPS_PDT_SCID_MEDIA_SERVER 0x0005 -#define WPS_PDT_SCID_RTK_DMP WPS_PDT_SCID_ME
Re: [PATCH v4] net: phy: add Marvell 88X2222 transceiver support
On Wed, Mar 03, 2021 at 07:02:11PM +0300, Ivan Bornyakov wrote: > Add basic support for the Marvell 88X multi-speed ethernet > transceiver. > > This PHY provides data transmission over fiber-optic as well as Twinax > copper links. The 88X supports 2 ports of 10GBase-R and 1000Base-X > on the line-side interface. The host-side interface supports 4 ports of > 10GBase-R, RXAUI, 1000Base-X and 2 ports of XAUI. > > This driver, however, supports only XAUI on the host-side and > 1000Base-X/10GBase-R on the line-side, for now. The SGMII is also > supported over 1000Base-X. Interrupts are not supported. > > Internal registers access compliant with the Clause 45 specification. > > Signed-off-by: Ivan Bornyakov > --- > drivers/net/phy/Kconfig | 6 + > drivers/net/phy/Makefile | 1 + > drivers/net/phy/marvell-88x.c | 519 ++ > include/linux/marvell_phy.h | 1 + > 4 files changed, 527 insertions(+) > create mode 100644 drivers/net/phy/marvell-88x.c > > diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig > index 698bea312adc..a615b3660b05 100644 > --- a/drivers/net/phy/Kconfig > +++ b/drivers/net/phy/Kconfig > @@ -201,6 +201,12 @@ config MARVELL_10G_PHY > help > Support for the Marvell Alaska MV88X3310 and compatible PHYs. > > +config MARVELL_88X_PHY > + tristate "Marvell 88X PHY" > + help > + Support for the Marvell 88X Dual-port Multi-speed Ethernet > + Transceiver. > + > config MICREL_PHY > tristate "Micrel PHYs" > help > diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile > index a13e402074cf..de683e3abe63 100644 > --- a/drivers/net/phy/Makefile > +++ b/drivers/net/phy/Makefile > @@ -63,6 +63,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o > obj-$(CONFIG_LXT_PHY)+= lxt.o > obj-$(CONFIG_MARVELL_10G_PHY)+= marvell10g.o > obj-$(CONFIG_MARVELL_PHY)+= marvell.o > +obj-$(CONFIG_MARVELL_88X_PHY)+= marvell-88x.o > obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o > obj-$(CONFIG_MICREL_KS8995MA)+= spi_ks8995.o > obj-$(CONFIG_MICREL_PHY) += micrel.o > diff --git a/drivers/net/phy/marvell-88x.c > b/drivers/net/phy/marvell-88x.c > new file mode 100644 > index ..eca8c2f20684 > --- /dev/null > +++ b/drivers/net/phy/marvell-88x.c > @@ -0,0 +1,519 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Marvell 88x dual-port multi-speed ethernet transceiver. > + * > + * Supports: > + * XAUI on the host side. > + * 1000Base-X or 10GBase-R on the line side. > + * SGMII over 1000Base-X. > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* Port PCS Configuration */ > +#define MV_PCS_CONFIG 0xF002 > +#define MV_PCS_HOST_XAUI0x73 > +#define MV_PCS_LINE_10GBR (0x71 << 8) > +#define MV_PCS_LINE_1GBX_AN (0x7B << 8) > +#define MV_PCS_LINE_SGMII_AN(0x7F << 8) > + > +/* Port Reset and Power Down */ > +#define MV_PORT_RST 0xF003 > +#define MV_LINE_RST_SW BIT(15) > +#define MV_HOST_RST_SW BIT(7) > +#define MV_PORT_RST_SW (MV_LINE_RST_SW | MV_HOST_RST_SW) > + > +/* 1000Base-X/SGMII Control Register */ > +#define MV_1GBX_CTRL(0x2000 + MII_BMCR) > + > +/* 1000BASE-X/SGMII Status Register */ > +#define MV_1GBX_STAT(0x2000 + MII_BMSR) > + > +/* 1000Base-X Auto-Negotiation Advertisement Register */ > +#define MV_1GBX_ADVERTISE (0x2000 + MII_ADVERTISE) > + > +/* 1000Base-X PHY Specific Status Register */ > +#define MV_1GBX_PHY_STAT0xA003 > +#define MV_1GBX_PHY_STAT_AN_RESOLVEDBIT(11) > +#define MV_1GBX_PHY_STAT_DUPLEX BIT(13) > +#define MV_1GBX_PHY_STAT_SPEED100 BIT(14) > +#define MV_1GBX_PHY_STAT_SPEED1000 BIT(15) > + > +struct mv_data { > + phy_interface_t line_interface; > + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); > +}; > + > +/* SFI PMA transmit enable */ > +static int mv_tx_enable(struct phy_device *phydev) > +{ > + return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, > + MDIO_PMD_TXDIS_GLOBAL); > +} > + > +/* SFI PMA transmit disable */ > +static int mv_tx_disable(struct phy_device *phydev) > +{ > + return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, > + MDIO_PMD_TXDIS_G
[PATCH v4] net: phy: add Marvell 88X2222 transceiver support
Add basic support for the Marvell 88X multi-speed ethernet transceiver. This PHY provides data transmission over fiber-optic as well as Twinax copper links. The 88X supports 2 ports of 10GBase-R and 1000Base-X on the line-side interface. The host-side interface supports 4 ports of 10GBase-R, RXAUI, 1000Base-X and 2 ports of XAUI. This driver, however, supports only XAUI on the host-side and 1000Base-X/10GBase-R on the line-side, for now. The SGMII is also supported over 1000Base-X. Interrupts are not supported. Internal registers access compliant with the Clause 45 specification. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/Kconfig | 6 + drivers/net/phy/Makefile | 1 + drivers/net/phy/marvell-88x.c | 519 ++ include/linux/marvell_phy.h | 1 + 4 files changed, 527 insertions(+) create mode 100644 drivers/net/phy/marvell-88x.c diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 698bea312adc..a615b3660b05 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -201,6 +201,12 @@ config MARVELL_10G_PHY help Support for the Marvell Alaska MV88X3310 and compatible PHYs. +config MARVELL_88X_PHY + tristate "Marvell 88X PHY" + help + Support for the Marvell 88X Dual-port Multi-speed Ethernet + Transceiver. + config MICREL_PHY tristate "Micrel PHYs" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index a13e402074cf..de683e3abe63 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o obj-$(CONFIG_MARVELL_PHY) += marvell.o +obj-$(CONFIG_MARVELL_88X_PHY) += marvell-88x.o obj-$(CONFIG_MESON_GXL_PHY)+= meson-gxl.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o obj-$(CONFIG_MICREL_PHY) += micrel.o diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c new file mode 100644 index ..eca8c2f20684 --- /dev/null +++ b/drivers/net/phy/marvell-88x.c @@ -0,0 +1,519 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Marvell 88x dual-port multi-speed ethernet transceiver. + * + * Supports: + * XAUI on the host side. + * 1000Base-X or 10GBase-R on the line side. + * SGMII over 1000Base-X. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Port PCS Configuration */ +#defineMV_PCS_CONFIG 0xF002 +#defineMV_PCS_HOST_XAUI0x73 +#defineMV_PCS_LINE_10GBR (0x71 << 8) +#defineMV_PCS_LINE_1GBX_AN (0x7B << 8) +#defineMV_PCS_LINE_SGMII_AN(0x7F << 8) + +/* Port Reset and Power Down */ +#defineMV_PORT_RST 0xF003 +#defineMV_LINE_RST_SW BIT(15) +#defineMV_HOST_RST_SW BIT(7) +#defineMV_PORT_RST_SW (MV_LINE_RST_SW | MV_HOST_RST_SW) + +/* 1000Base-X/SGMII Control Register */ +#defineMV_1GBX_CTRL(0x2000 + MII_BMCR) + +/* 1000BASE-X/SGMII Status Register */ +#defineMV_1GBX_STAT(0x2000 + MII_BMSR) + +/* 1000Base-X Auto-Negotiation Advertisement Register */ +#defineMV_1GBX_ADVERTISE (0x2000 + MII_ADVERTISE) + +/* 1000Base-X PHY Specific Status Register */ +#defineMV_1GBX_PHY_STAT0xA003 +#defineMV_1GBX_PHY_STAT_AN_RESOLVEDBIT(11) +#defineMV_1GBX_PHY_STAT_DUPLEX BIT(13) +#defineMV_1GBX_PHY_STAT_SPEED100 BIT(14) +#defineMV_1GBX_PHY_STAT_SPEED1000 BIT(15) + +struct mv_data { + phy_interface_t line_interface; + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); +}; + +/* SFI PMA transmit enable */ +static int mv_tx_enable(struct phy_device *phydev) +{ + return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, + MDIO_PMD_TXDIS_GLOBAL); +} + +/* SFI PMA transmit disable */ +static int mv_tx_disable(struct phy_device *phydev) +{ + return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, + MDIO_PMD_TXDIS_GLOBAL); +} + +static int mv_soft_reset(struct phy_device *phydev) +{ + int val, ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PORT_RST, + MV_PORT_RST_SW); + if (ret < 0) + return ret; + + return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND2, MV_PORT_RST, +val, !(val & MV_PORT_RST_SW), +5000, 100, true); +} + +/* Returns negative on error, 0 if link is down, 1 if link is up */ +static int mv_read_status_10g(struct phy_device *phydev) +{ + int val,
Re: [PATCH v3] net: phy: add Marvell 88X2222 transceiver support
On Wed, Mar 03, 2021 at 11:36:55AM +, Russell King - ARM Linux admin wrote: > > > + linkmode_set_bit(ETHTOOL_LINK_MODE_1baseKR_Full_BIT, supported); > > Does the PHY support backplane links? > It looks like it does, but our hardware only have SFP cages, so I'll drop backplane link modes.
[PATCH v3] net: phy: add Marvell 88X2222 transceiver support
Add basic support for the Marvell 88X multi-speed ethernet transceiver. This PHY provides data transmission over fiber-optic as well as Twinax copper links. The 88X supports 2 ports of 10GBase-R and 1000Base-X on the line-side interface. The host-side interface supports 4 ports of 10GBase-R, RXAUI, 1000Base-X and 2 ports of XAUI. This driver, however, supports only XAUI on the host-side and 1000Base-X/10GBase-R on the line-side, for now. The SGMII is also supported over 1000Base-X. Interrupts are not supported. Internal registers access compliant with the Clause 45 specification. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/Kconfig | 6 + drivers/net/phy/Makefile | 1 + drivers/net/phy/marvell-88x.c | 533 ++ include/linux/marvell_phy.h | 1 + 4 files changed, 541 insertions(+) create mode 100644 drivers/net/phy/marvell-88x.c diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 698bea312adc..a615b3660b05 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -201,6 +201,12 @@ config MARVELL_10G_PHY help Support for the Marvell Alaska MV88X3310 and compatible PHYs. +config MARVELL_88X_PHY + tristate "Marvell 88X PHY" + help + Support for the Marvell 88X Dual-port Multi-speed Ethernet + Transceiver. + config MICREL_PHY tristate "Micrel PHYs" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index a13e402074cf..de683e3abe63 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o obj-$(CONFIG_MARVELL_PHY) += marvell.o +obj-$(CONFIG_MARVELL_88X_PHY) += marvell-88x.o obj-$(CONFIG_MESON_GXL_PHY)+= meson-gxl.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o obj-$(CONFIG_MICREL_PHY) += micrel.o diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c new file mode 100644 index ..aec7e299c165 --- /dev/null +++ b/drivers/net/phy/marvell-88x.c @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Marvell 88x dual-port multi-speed ethernet transceiver. + * + * Supports: + * XAUI on the host side. + * 1000Base-X or 10GBase-R on the line side. + * SGMII over 1000Base-X. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Port PCS Configuration */ +#defineMV_PCS_CONFIG 0xF002 +#defineMV_PCS_HOST_XAUI0x73 +#defineMV_PCS_LINE_10GBR (0x71 << 8) +#defineMV_PCS_LINE_1GBX_AN (0x7B << 8) +#defineMV_PCS_LINE_SGMII_AN(0x7F << 8) + +/* Port Reset and Power Down */ +#defineMV_PORT_RST 0xF003 +#defineMV_LINE_RST_SW BIT(15) +#defineMV_HOST_RST_SW BIT(7) +#defineMV_PORT_RST_SW (MV_LINE_RST_SW | MV_HOST_RST_SW) + +/* 1000Base-X/SGMII Control Register */ +#defineMV_1GBX_CTRL(0x2000 + MII_BMCR) + +/* 1000BASE-X/SGMII Status Register */ +#defineMV_1GBX_STAT(0x2000 + MII_BMSR) + +/* 1000Base-X Auto-Negotiation Advertisement Register */ +#defineMV_1GBX_ADVERTISE (0x2000 + MII_ADVERTISE) + +/* 1000Base-X PHY Specific Status Register */ +#defineMV_1GBX_PHY_STAT0xA003 +#defineMV_1GBX_PHY_STAT_AN_RESOLVEDBIT(11) +#defineMV_1GBX_PHY_STAT_DUPLEX BIT(13) +#defineMV_1GBX_PHY_STAT_SPEED100 BIT(14) +#defineMV_1GBX_PHY_STAT_SPEED1000 BIT(15) + +struct mv_data { + phy_interface_t line_interface; + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); +}; + +/* SFI PMA transmit enable */ +static int mv_tx_enable(struct phy_device *phydev) +{ + return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, + MDIO_PMD_TXDIS_GLOBAL); +} + +/* SFI PMA transmit disable */ +static int mv_tx_disable(struct phy_device *phydev) +{ + return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, + MDIO_PMD_TXDIS_GLOBAL); +} + +static int mv_soft_reset(struct phy_device *phydev) +{ + int val, ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PORT_RST, + MV_PORT_RST_SW); + if (ret < 0) + return ret; + + return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND2, MV_PORT_RST, +val, !(val & MV_PORT_RST_SW), +5000, 100, true); +} + +/* Returns negative on error, 0 if link is down, 1 if link is up */ +static int mv_read_status_10g(struct phy_device *phydev) +{ + int val,
[PATCH 4/4] staging:rtl8712: replace cap_* definitions with native kernel WLAN_CAPABILITY_*
cap_* definitions duplicate WLAN_CAPABILITY_*. Remove cap_* definitions, improve code consistency. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8712/ieee80211.c | 6 +++--- drivers/staging/rtl8712/wifi.h | 7 --- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c index b4a099169c7c..13fc3c1ec0db 100644 --- a/drivers/staging/rtl8712/ieee80211.c +++ b/drivers/staging/rtl8712/ieee80211.c @@ -173,11 +173,11 @@ int r8712_generate_ie(struct registry_priv *registrypriv) ie += 2; /*capability info*/ *(u16 *)ie = 0; - *(__le16 *)ie |= cpu_to_le16(cap_IBSS); + *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_IBSS); if (registrypriv->preamble == PREAMBLE_SHORT) - *(__le16 *)ie |= cpu_to_le16(cap_ShortPremble); + *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); if (dev_network->Privacy) - *(__le16 *)ie |= cpu_to_le16(cap_Privacy); + *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); sz += 2; ie += 2; /*SSID*/ diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index b7889ac3dce9..f941efb1f4e2 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -278,13 +278,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) #define AUTH_ODD_TO0 #define AUTH_EVEN_TO 1 -#define cap_ESS BIT(0) -#define cap_IBSS BIT(1) -#define cap_CFPollable BIT(2) -#define cap_CFRequest BIT(3) -#define cap_Privacy BIT(4) -#define cap_ShortPremble BIT(5) - /*- * Below is the definition for 802.11i / 802.1x *-- -- 2.26.2
[PATCH 1/4] staging:rtl8712: replace get_(d|s)a with ieee80211_get_(D|S)A
get_da()/get_sa() duplicate native ieee80211_get_(D|S)A functions. Remove get_(d|s)a, use ieee80211_get_(D|S)A instead. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8712/rtl871x_recv.c | 4 +-- drivers/staging/rtl8712/wifi.h | 45 -- 2 files changed, 2 insertions(+), 47 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index eb4e46a7f743..efd783e7ccbc 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -466,8 +466,8 @@ static sint validate_recv_data_frame(struct _adapter *adapter, struct security_priv *psecuritypriv = &adapter->securitypriv; bretry = GetRetry(ptr); - pda = get_da(ptr); - psa = get_sa(ptr); + pda = ieee80211_get_DA((struct ieee80211_hdr *)ptr); + psa = ieee80211_get_SA((struct ieee80211_hdr *)ptr); pbssid = get_hdr_bssid(ptr); if (!pbssid) return _FAIL; diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 1b32b3510093..5de0e67b1876 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -264,51 +264,6 @@ static inline unsigned char get_tofr_ds(unsigned char *pframe) #define GetAddr4Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 24)) -static inline unsigned char *get_da(unsigned char *pframe) -{ - unsigned char *da; - unsigned intto_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); - - switch (to_fr_ds) { - case 0x00: /* ToDs=0, FromDs=0 */ - da = GetAddr1Ptr(pframe); - break; - case 0x01: /* ToDs=0, FromDs=1 */ - da = GetAddr1Ptr(pframe); - break; - case 0x02: /* ToDs=1, FromDs=0 */ - da = GetAddr3Ptr(pframe); - break; - default:/* ToDs=1, FromDs=1 */ - da = GetAddr3Ptr(pframe); - break; - } - return da; -} - -static inline unsigned char *get_sa(unsigned char *pframe) -{ - unsigned char *sa; - unsigned intto_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe); - - switch (to_fr_ds) { - case 0x00: /* ToDs=0, FromDs=0 */ - sa = GetAddr2Ptr(pframe); - break; - case 0x01: /* ToDs=0, FromDs=1 */ - sa = GetAddr3Ptr(pframe); - break; - case 0x02: /* ToDs=1, FromDs=0 */ - sa = GetAddr2Ptr(pframe); - break; - default:/* ToDs=1, FromDs=1 */ - sa = GetAddr4Ptr(pframe); - break; - } - - return sa; -} - static inline unsigned char *get_hdr_bssid(unsigned char *pframe) { unsigned char *sa; -- 2.26.2
[PATCH 2/4] staging:rtl8712: remove unused definitions from wifi.h
These definitions are not used and will not be useful in the future. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8712/wifi.h | 74 -- 1 file changed, 74 deletions(-) diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 5de0e67b1876..11fba6f9e721 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -16,22 +16,8 @@ #include -#define WLAN_IEEE_OUI_LEN 3 -#define WLAN_CRC_LEN 4 -#define WLAN_BSSID_LEN 6 -#define WLAN_BSS_TS_LEN8 #define WLAN_HDR_A3_LEN24 -#define WLAN_HDR_A4_LEN30 #define WLAN_HDR_A3_QOS_LEN26 -#define WLAN_HDR_A4_QOS_LEN32 -#define WLAN_SSID_MAXLEN 32 -#define WLAN_DATA_MAXLEN 2312 - -#define WLAN_A3_PN_OFFSET 24 -#define WLAN_A4_PN_OFFSET 30 - -#define WLAN_MIN_ETHFRM_LEN60 -#define WLAN_MAX_ETHFRM_LEN1514 #define P80211CAPTURE_VERSION 0x80211001 @@ -74,33 +60,6 @@ enum WIFI_FRAME_SUBTYPE { WIFI_CF_ACKPOLL = (BIT(6) | BIT(5) | BIT(4) | WIFI_DATA_TYPE), }; -enum WIFI_REASON_CODE { - _RSON_RESERVED_ = 0, - _RSON_UNSPECIFIED_ = 1, - _RSON_AUTH_NO_LONGER_VALID_ = 2, - _RSON_DEAUTH_STA_LEAVING_ = 3, - _RSON_INACTIVITY_ = 4, - _RSON_UNABLE_HANDLE_= 5, - _RSON_CLS2_ = 6, - _RSON_CLS3_ = 7, - _RSON_DISAOC_STA_LEAVING_ = 8, - _RSON_ASOC_NOT_AUTH_= 9, - /* WPA reason */ - _RSON_INVALID_IE_ = 13, - _RSON_MIC_FAILURE_ = 14, - _RSON_4WAY_HNDSHK_TIMEOUT_ = 15, - _RSON_GROUP_KEY_UPDATE_TIMEOUT_ = 16, - _RSON_DIFF_IE_ = 17, - _RSON_MLTCST_CIPHER_NOT_VALID_ = 18, - _RSON_UNICST_CIPHER_NOT_VALID_ = 19, - _RSON_AKMP_NOT_VALID_ = 20, - _RSON_UNSUPPORT_RSNE_VER_ = 21, - _RSON_INVALID_RSNE_CAP_ = 22, - _RSON_IEEE_802DOT1X_AUTH_FAIL_ = 23, - /* below are Realtek definitions */ - _RSON_PMK_NOT_AVAILABLE_= 24, -}; - enum WIFI_REG_DOMAIN { DOMAIN_FCC = 1, DOMAIN_IC = 2, @@ -234,11 +193,6 @@ static inline unsigned char get_tofr_ds(unsigned char *pframe) 0x000f) | (0xfff0 & (num << 4))); \ }) -#define SetDuration(pbuf, dur) ({ \ - *(__le16 *)((addr_t)(pbuf) + 2) |= \ - cpu_to_le16(0x & (dur)); \ -}) - #define SetPriority(pbuf, tid) ({ \ *(__le16 *)(pbuf) |= cpu_to_le16(tid & 0xf); \ }) @@ -253,9 +207,6 @@ static inline unsigned char get_tofr_ds(unsigned char *pframe) #define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1) -#define GetAid(pbuf) (cpu_to_le16(*(__le16 *)((addr_t)(pbuf) + 2)) \ - & 0x3fff) - #define GetAddr1Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 4)) #define GetAddr2Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 10)) @@ -290,19 +241,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) * Below is for the security related definition *- */ -#define _RESERVED_FRAME_TYPE_ 0 -#define _SKB_FRAME_TYPE_ 2 -#define _PRE_ALLOCMEM_ 1 -#define _PRE_ALLOCHDR_ 3 -#define _PRE_ALLOCLLCHDR_ 4 -#define _PRE_ALLOCICVHDR_ 5 -#define _PRE_ALLOCMICHDR_ 6 - -#define _SIFSTIME_ ((priv->pmib->BssType.net_work_type & \ - WIRELESS_11A) ? 16 : 10) -#define _ACKCTSLNG_14 /*14 bytes long, including crclng */ -#define _CRCLNG_ 4 - #define _ASOCREQ_IE_OFFSET_4 /* excluding wlan_hdr */ #define_ASOCRSP_IE_OFFSET_ 6 #define _REASOCREQ_IE_OFFSET_ 10 @@ -348,10 +286,6 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) #define AUTH_ODD_TO0 #define AUTH_EVEN_TO 1 -#define WLAN_ETHCONV_ENCAP 1 -#define WLAN_ETHCONV_RFC1042 2 -#define WLAN_ETHCONV_8021h 3 - #define cap_ESS BIT(0) #define cap_IBSS BIT(1) #define cap_CFPollable BIT(2) @@ -371,20 +305,12 @@ static inline unsigned char *get_hdr_bssid(unsigned char *pframe) *-- */ #define _WMM_IE_Length_7 /* for WMM STA */ -#define _WMM_Para_Element_Length_ 24 /*- * Below is the definition for 802.11n *-- */ -#define SetOrderBit(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(_ORDER_); \ -}) - -
[PATCH 3/4] staging:rtl8712: use IEEE80211_FCTL_* kernel definitions
_TO_DS_, _FROM_DS_, _MORE_FRAG_, _RETRY_, _PWRMGT_, _MORE_DATA_, _PRIVACY_, _ORDER_ definitions are duplicate IEEE80211_FCTL_* kernel definitions. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8712/wifi.h | 52 ++ 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 11fba6f9e721..b7889ac3dce9 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -15,6 +15,7 @@ #define _WIFI_H_ #include +#include #define WLAN_HDR_A3_LEN24 #define WLAN_HDR_A3_QOS_LEN26 @@ -74,33 +75,24 @@ enum WIFI_REG_DOMAIN { DOMAIN_MAX }; -#define _TO_DS_BIT(8) -#define _FROM_DS_ BIT(9) -#define _MORE_FRAG_BIT(10) -#define _RETRY_BIT(11) -#define _PWRMGT_ BIT(12) -#define _MORE_DATA_BIT(13) -#define _PRIVACY_ BIT(14) -#define _ORDER_BIT(15) - #define SetToDs(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(_TO_DS_); \ + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS); \ }) -#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_TO_DS_)) != 0) +#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0) #define ClearToDs(pbuf)({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_TO_DS_)); \ + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_TODS)); \ }) #define SetFrDs(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(_FROM_DS_); \ + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_FROMDS); \ }) -#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_FROM_DS_)) != 0) +#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0) #define ClearFrDs(pbuf)({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_FROM_DS_)); \ + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_FROMDS)); \ }) static inline unsigned char get_tofr_ds(unsigned char *pframe) @@ -109,56 +101,56 @@ static inline unsigned char get_tofr_ds(unsigned char *pframe) } #define SetMFrag(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_FRAG_); \ + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); \ }) -#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_MORE_FRAG_)) != 0) +#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0) #define ClearMFrag(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_MORE_FRAG_)); \ + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)); \ }) #define SetRetry(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(_RETRY_); \ + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_RETRY); \ }) -#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_RETRY_)) != 0) +#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0) #define ClearRetry(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_RETRY_)); \ + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_RETRY)); \ }) #define SetPwrMgt(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(_PWRMGT_); \ + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PM); \ }) #define GetPwrMgt(pbuf)(((*(__le16 *)(pbuf)) & \ - cpu_to_le16(_PWRMGT_)) != 0) + cpu_to_le16(IEEE80211_FCTL_PM)) != 0) #define ClearPwrMgt(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_PWRMGT_)); \ + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_PM)); \ }) #define SetMData(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_DATA_); \ + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); \ }) #define GetMData(pbuf) (((*(__le16 *)(pbuf)) & \ - cpu_to_le16(_MORE_DATA_)) != 0) + cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0) #define ClearMData(pbuf) ({ \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_MORE_DATA_)); \ + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREDATA)); \ }) #define SetPrivacy(pbuf) ({ \ - *(__le16 *)(pbuf) |= cpu_to_le16(_PRIVACY_); \ + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); \ }) #define GetPrivacy(pbuf) (((*(__le16 *)(pbuf)) & \ - cpu_to_le16(_PRIVACY_)) != 0) + cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0) #define GetOrder(pbuf) (((*(__le16 *)(pbuf)) & \ - cpu_to_le16(_ORDER_)) != 0) + cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0) #define GetFrameType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & \ (BIT(3) | BIT(2))) -- 2.26.2
[PATCH 0/4] staging:rtl8712: avoid unnecessary definitions in wifi.h
wifi.h contains unnecessary definitions. Some of them are not used at all, some can be replaced with native definitions. Ivan Safonov (4): staging:rtl8712: replace get_(d|s)a with ieee80211_get_(D|S)A staging:rtl8712: remove unused definitions from wifi.h staging:rtl8712: use IEEE80211_FCTL_* kernel definitions staging:rtl8712: replace cap_* definitions with native kernel WLAN_CAPABILITY_* drivers/staging/rtl8712/ieee80211.c| 6 +- drivers/staging/rtl8712/rtl871x_recv.c | 4 +- drivers/staging/rtl8712/wifi.h | 178 +++-- 3 files changed, 27 insertions(+), 161 deletions(-) -- 2.26.2
[PATCH v2] iio: proximity: vcnl3020: add proximity rate
Add the proximity rate optional option and handling of it for vishay vcnl3020. Signed-off-by: Ivan Mikhaylov --- drivers/iio/proximity/vcnl3020.c | 97 +++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c index 37264f801ad0..43817f6b3086 100644 --- a/drivers/iio/proximity/vcnl3020.c +++ b/drivers/iio/proximity/vcnl3020.c @@ -40,6 +40,17 @@ #define VCNL_ON_DEMAND_TIMEOUT_US 10 #define VCNL_POLL_US 2 +static const int vcnl3020_prox_sampling_frequency[][2] = { + {1, 95}, + {3, 906250}, + {7, 812500}, + {16, 625000}, + {31, 25}, + {62, 50}, + {125, 0}, + {250, 0}, +}; + /** * struct vcnl3020_data - vcnl3020 specific data. * @regmap:device register map. @@ -165,10 +176,51 @@ static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val) return rc; } +static int vcnl3020_read_proxy_samp_freq(struct vcnl3020_data *data, int *val, +int *val2) +{ + int rc; + unsigned int prox_rate; + + rc = regmap_read(data->regmap, VCNL_PROXIMITY_RATE, &prox_rate); + if (rc) + return rc; + + if (prox_rate >= ARRAY_SIZE(vcnl3020_prox_sampling_frequency)) + return -EINVAL; + + *val = vcnl3020_prox_sampling_frequency[prox_rate][0]; + *val2 = vcnl3020_prox_sampling_frequency[prox_rate][1]; + + return 0; +} + +static int vcnl3020_write_proxy_samp_freq(struct vcnl3020_data *data, int val, + int val2) +{ + unsigned int i; + int index = -1; + + for (i = 0; i < ARRAY_SIZE(vcnl3020_prox_sampling_frequency); i++) { + if (val == vcnl3020_prox_sampling_frequency[i][0] && + val2 == vcnl3020_prox_sampling_frequency[i][1]) { + index = i; + break; + } + } + + if (index < 0) + return -EINVAL; + + return regmap_write(data->regmap, VCNL_PROXIMITY_RATE, index); +} + static const struct iio_chan_spec vcnl3020_channels[] = { { .type = IIO_PROXIMITY, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_separate_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), }, }; @@ -185,6 +237,47 @@ static int vcnl3020_read_raw(struct iio_dev *indio_dev, if (rc) return rc; return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + rc = vcnl3020_read_proxy_samp_freq(data, val, val2); + if (rc < 0) + return rc; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int vcnl3020_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int rc; + struct vcnl3020_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + rc = iio_device_claim_direct_mode(indio_dev); + if (rc) + return rc; + rc = vcnl3020_write_proxy_samp_freq(data, val, val2); + iio_device_release_direct_mode(indio_dev); + return rc; + default: + return -EINVAL; + } +} + +static int vcnl3020_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = (int *)vcnl3020_prox_sampling_frequency; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = 2 * ARRAY_SIZE(vcnl3020_prox_sampling_frequency); + return IIO_AVAIL_LIST; default: return -EINVAL; } @@ -192,6 +285,8 @@ static int vcnl3020_read_raw(struct iio_dev *indio_dev, static const struct iio_info vcnl3020_info = { .read_raw = vcnl3020_read_raw, + .write_raw = vcnl3020_write_raw, + .read_avail = vcnl3020_read_avail, }; static const struct regmap_config vcnl3020_regmap_config = { -- 2.26.2
[PATCH v2 0/1] add proximity rate option for vcnl3020
Add the runtime control of proximity rate for vcnl3020 proximity sensor. Changes from v1: 1. add .read_avail method 2. remove dts and parse of it Ivan Mikhaylov (1): iio: proximity: vcnl3020: add proximity rate drivers/iio/proximity/vcnl3020.c | 97 +++- 1 file changed, 96 insertions(+), 1 deletion(-) -- 2.26.2
Memory allocation issues after "sysctl: Convert to iter interfaces"
Hello, We started seeing allocation failures on procfs reads after commit 4bd6a7353ee1 "sysctl: Convert to iter interfaces". I haven't done a full bisect, but the decoded stacks point squarely at the following piece of code which was introduced: kbuf = kzalloc(count + 1, GFP_KERNEL); Previously reading /proc/sys/net/core/somaxconn required order 1 and order 3 allocations from the kernel, which can be seen from: $ sudo perf record -g -e kmem:mm_page_alloc_zone_locked -- \ cat /proc/sys/net/core/somaxconn Now we see order 6 + order 6 allocations from cat, and even: read(3, 0x7f8d9d3f3000, 131072) = -1 ENOMEM (Cannot allocate memory) See the following gist for full allocation stacks on 5.4 and 5.10: * https://gist.github.com/bobrik/dd03cce0aaeef5acd5faecc32bd44530 This seems like a regression, and unprivileged users being able to force order 6 allocations onto the kernel doesn't feel good.
Re: [PATCH 1/2] iio: proximity: vcnl3020: add proximity rate
On Sun, 2021-02-21 at 22:34 +0200, Andy Shevchenko wrote: > > > On Tuesday, February 16, 2021, Ivan Mikhaylov wrote: > > Add the proximity rate optional option and handling of it for > > vishay vcnl3020. > > > > Signed-off-by: Ivan Mikhaylov > > --- > > drivers/iio/proximity/vcnl3020.c | 123 ++- > > 1 file changed, 120 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/iio/proximity/vcnl3020.c > > b/drivers/iio/proximity/vcnl3020.c > > index 37264f801ad0..833c5d5ac0a1 100644 > > --- a/drivers/iio/proximity/vcnl3020.c > > +++ b/drivers/iio/proximity/vcnl3020.c > > @@ -40,6 +40,17 @@ > > #define VCNL_ON_DEMAND_TIMEOUT_US 10 > > #define VCNL_POLL_US 2 > > > > +static const int vcnl3020_prox_sampling_frequency[][2] = { > > + {1, 95}, > > Can you confirm that’s the correct value and shan’t be 953125? Yes, It is described in the documentation for vcnl3020, also vcnl4000.c driver has same sampling frequency values for vcnl4020. > > + {3, 906250}, > > + {7, 812500}, > > + {16, 625000}, > > + {31, 25}, > > + {62, 50}, > > + {125, 0}, > > + {250, 0}, > > +}; > > + > > /** > > * struct vcnl3020_data - vcnl3020 specific data. > > * @regmap:device register map. > > @@ -75,12 +86,37 @@ static u32 microamp_to_reg(u32 *val) > > return *val /= 1; > > }; > >
Re: [PATCH 1/2] iio: proximity: vcnl3020: add proximity rate
On Sun, 2021-02-21 at 15:20 +, Jonathan Cameron wrote: > On Tue, 16 Feb 2021 17:53:45 +0300 > Ivan Mikhaylov wrote: > > > Add the proximity rate optional option and handling of it for > > vishay vcnl3020. > > > > Signed-off-by: Ivan Mikhaylov > Hi Ivan, > > Other than dropping the dt part this mostly looks fine. > Please also implement the read_avail callback to let userspace know the > valid set of values. > > Thanks > > Jonathan > Ok, I'll get rid of dt part then. Thanks for review. > > --- > > drivers/iio/proximity/vcnl3020.c | 123 ++- > > 1 file changed, 120 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/iio/proximity/vcnl3020.c > > b/drivers/iio/proximity/vcnl3020.c > > index 37264f801ad0..833c5d5ac0a1 100644 > > --- a/drivers/iio/proximity/vcnl3020.c > > +++ b/drivers/iio/proximity/vcnl3020.c > > @@ -40,6 +40,17 @@ > > #define VCNL_ON_DEMAND_TIMEOUT_US 10 > > #define VCNL_POLL_US 2 > > > > +static const int vcnl3020_prox_sampling_frequency[][2] = { > > + {1, 95}, > > + {3, 906250}, > > + {7, 812500}, > > + {16, 625000}, > > + {31, 25}, > > + {62, 50}, > > + {125, 0}, > > + {250, 0}, > > +}; > > + > > /** > > * struct vcnl3020_data - vcnl3020 specific data. > > * @regmap:device register map. > > @@ -75,12 +86,37 @@ static u32 microamp_to_reg(u32 *val) > > return *val /= 1; > > }; > > > > +static u32 hz_to_reg(u32 *val) > Hmm. This is rather odd in the existing driver. It makes no sense > to have callbacks like this that both modify the value passed by pointer > and return it. > > Much cleaner to just pass by value and make caller do the assignment. > > Given I've suggested you drop this anyway probably not that important! Good point anyways. > > +{ > > + unsigned int i; > > + int index = -1; > > + > > + for (i = 0; i < ARRAY_SIZE(vcnl3020_prox_sampling_frequency); i++) { > > + if (*val == vcnl3020_prox_sampling_frequency[i][0]) { > > + index = i; > > return i; > > > + break; > > + } > > + } > > + > > + *val = index; > > + if (index < 0) > > + *val = 0; > > + > > + return *val; > > +}; > > + > > static struct vcnl3020_property vcnl3020_led_current_property = { > > .name = "vishay,led-current-microamp", > > .reg = VCNL_LED_CURRENT, > > .conversion_func = microamp_to_reg, > > }; > > > > +static struct vcnl3020_property vcnl3020_proximity_rate_property = { > > + .name = "vishay,proximity-rate-hz", > > + .reg = VCNL_PROXIMITY_RATE, > > + .conversion_func = hz_to_reg, > > +}; > > + > > static int vcnl3020_get_and_apply_property(struct vcnl3020_data *data, > >struct vcnl3020_property prop) > > { > > @@ -125,8 +161,18 @@ static int vcnl3020_init(struct vcnl3020_data *data) > > data->rev = reg; > > mutex_init(&data->lock); > > > > - return vcnl3020_get_and_apply_property(data, > > - vcnl3020_led_current_property); > > + rc = vcnl3020_get_and_apply_property(data, > > +vcnl3020_led_current_property); > > + if (rc) { > > + goto err_prop_set; > > Kernel style has not brackets around single line blocks like this. > if (rc) > goto err_prop_set; > > > + } > > + > > + rc = vcnl3020_get_and_apply_property(data, > > +vcnl3020_proximity_rate_property); > > From review of binding doc, I don't think this makes a much sense as a > dt property. > > > + > > +err_prop_set: > > + > > + return rc; > > }; > > > > static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val) > > @@ -165,10 +211,50 @@ static int vcnl3020_measure_proximity(struct > > vcnl3020_data *data, int *val) > > return rc; > > } > > > > +static int vcnl3020_read_proxy_samp_freq(struct vcnl3020_data *data, int > > *val, > > +int *val2) > > +{ > > + int rc; > > + unsigned int prox_rate; > > + > > + rc = regmap_read(data->regmap,
Re: [PATCH v2] net: phy: add Marvell 88X2222 transceiver support
On Sat, Feb 20, 2021 at 11:53:04AM +, Russell King - ARM Linux admin wrote: > On Sat, Feb 20, 2021 at 12:46:23PM +0300, Ivan Bornyakov wrote: > > + > > + switch (sfp_interface) { > > + case PHY_INTERFACE_MODE_10GBASER: > > + phydev->speed = SPEED_1; > > + phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG, > > + MV_PCS_HOST_XAUI | MV_PCS_LINE_10GBR); > > + break; > > + case PHY_INTERFACE_MODE_1000BASEX: > > + phydev->speed = SPEED_1000; > > + phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG, > > + MV_PCS_HOST_XAUI | MV_PCS_LINE_1GBX_AN); > > + break; > > + case PHY_INTERFACE_MODE_SGMII: > > + phydev->speed = SPEED_1000; > > + phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG, > > + MV_PCS_HOST_XAUI | MV_PCS_LINE_SGMII_AN); > > + phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_CTRL, > > + BMCR_SPEED1000 | BMCR_SPEED100, BMCR_SPEED1000); > > Isn't this forcing 1000Mbit, but SGMII relies on AN for the slower > speeds. > It was intended as default, but you have a good point, there is no need for this, I can just trigger config_aneg() instead. > > + break; > > + default: > > + dev_err(dev, "Incompatible SFP module inserted\n"); > > + > > + return -EINVAL; > > + } > > I don't think you should set phydev->speed in this function - apart > from the rtnl lock, there is no other locking here, so this is fragile. > > > + linkmode_and(phydev->supported, priv->supported, sfp_supported); > > I don't think this is a good idea; phylink does not expect the supported > mask to change, and I suspect _no_ network device expects it to change. > One of the things that network drivers and phylink does is to adjust the > supported mask for a PHY according to the capabilities of the network > device. For example, if they don't support pause modes, or something > else. Overriding it in this way has the possibility to re-introduce > modes that the network driver does not support. > OK, but how can I exclude modes unsupported by inserted SFP? Or I shouldn't exclude any at all? > > +/* switch line-side interface between 10GBase-R and 1GBase-X > > + * according to speed */ > > +static void mv_update_interface(struct phy_device *phydev) > > +{ > > + struct mv_data *priv = phydev->priv; > > + > > + if (phydev->speed == SPEED_1 && > > + priv->line_interface == PHY_INTERFACE_MODE_1000BASEX) { > > + priv->line_interface = PHY_INTERFACE_MODE_10GBASER; > > + > > + phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG, > > + MV_PCS_HOST_XAUI | MV_PCS_LINE_10GBR); > > + mv_soft_reset(phydev); > > + } > > + > > + if (phydev->speed == SPEED_1000 && > > + priv->line_interface == PHY_INTERFACE_MODE_10GBASER) { > > + priv->line_interface = PHY_INTERFACE_MODE_1000BASEX; > > + > > + phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG, > > + MV_PCS_HOST_XAUI | MV_PCS_LINE_1GBX_AN); > > + mv_soft_reset(phydev); > > + } > > Wouldn't it be better to have a single function to set the line > interface, used by both this function and your sfp_module_insert > function? I'm thinking something like: > > static int mv_set_line_interface(struct phy_device *phydev, >phy_interface_t line_interface) > { > ... > } > > and calling that from both these locations to configure the PHY for > 10GBASE-R, 1000BASE-X and SGMII modes. > I'll think about it, thanks. > > + > > +static int mv_config_aneg(struct phy_device *phydev) > > +{ > > + struct mv_data *priv = phydev->priv; > > + int ret, adv; > > + > > + /* SFP is not present, do nothing */ > > + if (priv->line_interface == PHY_INTERFACE_MODE_NA) > > + return 0; > > + > > + if (phydev->autoneg == AUTONEG_DISABLE || > > + phydev->speed == SPEED_1) { > > + if (phydev->speed == SPEED_1 && > > + !mv_is_10g_capable(phydev)) > > + return -EINVAL; > > + > > + if (priv->line_interface == PHY_INTERFACE_MODE_SGMII) { > > + ret = mv_set_sgmii_speed(phyde
[PATCH v2] net: phy: add Marvell 88X2222 transceiver support
Add basic support for the Marvell 88X multi-speed ethernet transceiver. This PHY provides data transmission over fiber-optic as well as Twinax copper links. The 88X supports 2 ports of 10GBase-R and 1000Base-X on the line-side interface. The host-side interface supports 4 ports of 10GBase-R, RXAUI, 1000Base-X and 2 ports of XAUI. This driver, however, supports only XAUI on the host-side and 1000Base-X/10GBase-R on the line-side, for now. The SGMII is also supported over 1000Base-X. Interrupts are not supported. Internal registers access compliant with the Clause 45 specification. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/Kconfig | 6 + drivers/net/phy/Makefile | 1 + drivers/net/phy/marvell-88x.c | 510 ++ include/linux/marvell_phy.h | 1 + 4 files changed, 518 insertions(+) create mode 100644 drivers/net/phy/marvell-88x.c diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 698bea312adc..a615b3660b05 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -201,6 +201,12 @@ config MARVELL_10G_PHY help Support for the Marvell Alaska MV88X3310 and compatible PHYs. +config MARVELL_88X_PHY + tristate "Marvell 88X PHY" + help + Support for the Marvell 88X Dual-port Multi-speed Ethernet + Transceiver. + config MICREL_PHY tristate "Micrel PHYs" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index a13e402074cf..de683e3abe63 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o obj-$(CONFIG_MARVELL_PHY) += marvell.o +obj-$(CONFIG_MARVELL_88X_PHY) += marvell-88x.o obj-$(CONFIG_MESON_GXL_PHY)+= meson-gxl.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o obj-$(CONFIG_MICREL_PHY) += micrel.o diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c new file mode 100644 index ..5f1b6185e272 --- /dev/null +++ b/drivers/net/phy/marvell-88x.c @@ -0,0 +1,510 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Marvell 88x dual-port multi-speed ethernet transceiver. + * + * Supports: + * XAUI on the host side. + * 1000Base-X or 10GBase-R on the line side. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Port PCS Configuration */ +#defineMV_PCS_CONFIG 0xF002 +#defineMV_PCS_HOST_XAUI0x73 +#defineMV_PCS_LINE_10GBR (0x71 << 8) +#defineMV_PCS_LINE_1GBX_AN (0x7B << 8) +#defineMV_PCS_LINE_SGMII_AN(0x7F << 8) + +/* Port Reset and Power Down */ +#defineMV_PORT_RST 0xF003 +#defineMV_LINE_RST_SW BIT(15) +#defineMV_HOST_RST_SW BIT(7) +#defineMV_PORT_RST_SW (MV_LINE_RST_SW | MV_HOST_RST_SW) + +/* 10GBASE-R PCS Real Time Status Register */ +#defineMV_10GBR_STAT_RT0x8002 + +/* 1000Base-X/SGMII Control Register */ +#defineMV_1GBX_CTRL(0x2000 + MII_BMCR) + +/* 1000BASE-X/SGMII Status Register */ +#defineMV_1GBX_STAT(0x2000 + MII_BMSR) + +/* 1000Base-X Auto-Negotiation Advertisement Register */ +#defineMV_1GBX_ADVERTISE (0x2000 + MII_ADVERTISE) + +/* 1000Base-X PHY Specific Status Register */ +#defineMV_1GBX_PHY_STAT0xA003 +#defineMV_1GBX_PHY_STAT_AN_RESOLVEDBIT(11) +#defineMV_1GBX_PHY_STAT_DUPLEX BIT(13) +#defineMV_1GBX_PHY_STAT_SPEED100 BIT(14) +#defineMV_1GBX_PHY_STAT_SPEED1000 BIT(15) + +struct mv_data { + phy_interface_t line_interface; + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); +}; + +/* SFI PMA transmit enable */ +static int mv_tx_enable(struct phy_device *phydev) +{ + return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, + MDIO_PMD_TXDIS_GLOBAL); +} + +/* SFI PMA transmit disable */ +static int mv_tx_disable(struct phy_device *phydev) +{ + return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS, + MDIO_PMD_TXDIS_GLOBAL); +} + +static int mv_soft_reset(struct phy_device *phydev) +{ + int val, ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PORT_RST, + MV_PORT_RST_SW); + if (ret < 0) + return ret; + + return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND2, MV_PORT_RST, +val, !(val & MV_PORT_RST_SW), +5000, 100, true); +} + +static int sfp_module_insert(void *_priv, const struct sfp_eeprom_id *id) +{ + struct phy_
Re: [PATCH] staging: wlan-ng: Fixed incorrect type warning in p80211netdev.c
On 2/17/21 6:42 PM, pritthijit.nath at icloud.com (Pritthijit Nath) wrote: This change fixes a sparse warning "incorrect type in argument 1 (different address spaces)". Signed-off-by: Pritthijit Nath --- drivers/staging/wlan-ng/p80211netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index 6f9666dc0277..70570e8a5ad2 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -569,7 +569,7 @@ static int p80211knetdev_do_ioctl(struct net_device *dev, goto bail; } - msgbuf = memdup_user(req->data, req->len); + msgbuf = memdup_user((void __user *)req->data, req->len); if (IS_ERR(msgbuf)) { result = PTR_ERR(msgbuf); goto bail; Reviewed-by: Ivan Safonov
[PATCH 2/2] dt-bindings: vcnl3020: add proximity rate in hz
Describe the possible proximity values in herzes for vcnl3020. Signed-off-by: Ivan Mikhaylov --- .../devicetree/bindings/iio/proximity/vishay,vcnl3020.yaml | 6 ++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/proximity/vishay,vcnl3020.yaml b/Documentation/devicetree/bindings/iio/proximity/vishay,vcnl3020.yaml index fbd3a2e32280..1bb6ca1770f3 100644 --- a/Documentation/devicetree/bindings/iio/proximity/vishay,vcnl3020.yaml +++ b/Documentation/devicetree/bindings/iio/proximity/vishay,vcnl3020.yaml @@ -43,6 +43,12 @@ properties: 18, 19, 20] default: 2 + vishay,proximity-rate-hz: +description: + The rate of proximity measurement. +enum: [1, 3, 7, 16, 31, 62, 125, 500] +default: 1 + required: - compatible - reg -- 2.26.2
[PATCH 1/2] iio: proximity: vcnl3020: add proximity rate
Add the proximity rate optional option and handling of it for vishay vcnl3020. Signed-off-by: Ivan Mikhaylov --- drivers/iio/proximity/vcnl3020.c | 123 ++- 1 file changed, 120 insertions(+), 3 deletions(-) diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c index 37264f801ad0..833c5d5ac0a1 100644 --- a/drivers/iio/proximity/vcnl3020.c +++ b/drivers/iio/proximity/vcnl3020.c @@ -40,6 +40,17 @@ #define VCNL_ON_DEMAND_TIMEOUT_US 10 #define VCNL_POLL_US 2 +static const int vcnl3020_prox_sampling_frequency[][2] = { + {1, 95}, + {3, 906250}, + {7, 812500}, + {16, 625000}, + {31, 25}, + {62, 50}, + {125, 0}, + {250, 0}, +}; + /** * struct vcnl3020_data - vcnl3020 specific data. * @regmap:device register map. @@ -75,12 +86,37 @@ static u32 microamp_to_reg(u32 *val) return *val /= 1; }; +static u32 hz_to_reg(u32 *val) +{ + unsigned int i; + int index = -1; + + for (i = 0; i < ARRAY_SIZE(vcnl3020_prox_sampling_frequency); i++) { + if (*val == vcnl3020_prox_sampling_frequency[i][0]) { + index = i; + break; + } + } + + *val = index; + if (index < 0) + *val = 0; + + return *val; +}; + static struct vcnl3020_property vcnl3020_led_current_property = { .name = "vishay,led-current-microamp", .reg = VCNL_LED_CURRENT, .conversion_func = microamp_to_reg, }; +static struct vcnl3020_property vcnl3020_proximity_rate_property = { + .name = "vishay,proximity-rate-hz", + .reg = VCNL_PROXIMITY_RATE, + .conversion_func = hz_to_reg, +}; + static int vcnl3020_get_and_apply_property(struct vcnl3020_data *data, struct vcnl3020_property prop) { @@ -125,8 +161,18 @@ static int vcnl3020_init(struct vcnl3020_data *data) data->rev = reg; mutex_init(&data->lock); - return vcnl3020_get_and_apply_property(data, - vcnl3020_led_current_property); + rc = vcnl3020_get_and_apply_property(data, +vcnl3020_led_current_property); + if (rc) { + goto err_prop_set; + } + + rc = vcnl3020_get_and_apply_property(data, +vcnl3020_proximity_rate_property); + +err_prop_set: + + return rc; }; static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val) @@ -165,10 +211,50 @@ static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val) return rc; } +static int vcnl3020_read_proxy_samp_freq(struct vcnl3020_data *data, int *val, +int *val2) +{ + int rc; + unsigned int prox_rate; + + rc = regmap_read(data->regmap, VCNL_PROXIMITY_RATE, &prox_rate); + if (rc) + return rc; + + if (prox_rate >= ARRAY_SIZE(vcnl3020_prox_sampling_frequency)) + return -EINVAL; + + *val = vcnl3020_prox_sampling_frequency[prox_rate][0]; + *val2 = vcnl3020_prox_sampling_frequency[prox_rate][1]; + + return 0; +} + +static int vcnl3020_write_proxy_samp_freq(struct vcnl3020_data *data, int val, + int val2) +{ + unsigned int i; + int index = -1; + + for (i = 0; i < ARRAY_SIZE(vcnl3020_prox_sampling_frequency); i++) { + if (val == vcnl3020_prox_sampling_frequency[i][0] && + val2 == vcnl3020_prox_sampling_frequency[i][1]) { + index = i; + break; + } + } + + if (index < 0) + return -EINVAL; + + return regmap_write(data->regmap, VCNL_PROXIMITY_RATE, index); +} + static const struct iio_chan_spec vcnl3020_channels[] = { { .type = IIO_PROXIMITY, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SAMP_FREQ), }, }; @@ -185,13 +271,44 @@ static int vcnl3020_read_raw(struct iio_dev *indio_dev, if (rc) return rc; return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + rc = vcnl3020_read_proxy_samp_freq(data, val, val2); + if (rc < 0) + return rc; + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } } +static int vcnl3020_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ +
[PATCH 0/2] add proximity rate option for vcnl3020
Add the control of proximity rate from runtime and DTS for vcnl3020 proximity sensor. Ivan Mikhaylov (2): iio: proximity: vcnl3020: add proximity rate dt-bindings: vcnl3020: add proximity rate in hz .../iio/proximity/vishay,vcnl3020.yaml| 6 + drivers/iio/proximity/vcnl3020.c | 123 +- 2 files changed, 126 insertions(+), 3 deletions(-) -- 2.26.2
[PATCH] staging:wlan-ng: use memdup_user instead of kmalloc/copy_from_user
memdup_user() is shorter and safer equivalent of kmalloc/copy_from_user pair. Signed-off-by: Ivan Safonov --- drivers/staging/wlan-ng/p80211netdev.c | 28 -- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c index a15abb2c8f54..6f9666dc0277 100644 --- a/drivers/staging/wlan-ng/p80211netdev.c +++ b/drivers/staging/wlan-ng/p80211netdev.c @@ -569,24 +569,22 @@ static int p80211knetdev_do_ioctl(struct net_device *dev, goto bail; } - /* Allocate a buf of size req->len */ - msgbuf = kmalloc(req->len, GFP_KERNEL); - if (msgbuf) { - if (copy_from_user(msgbuf, (void __user *)req->data, req->len)) - result = -EFAULT; - else - result = p80211req_dorequest(wlandev, msgbuf); + msgbuf = memdup_user(req->data, req->len); + if (IS_ERR(msgbuf)) { + result = PTR_ERR(msgbuf); + goto bail; + } - if (result == 0) { - if (copy_to_user - ((void __user *)req->data, msgbuf, req->len)) { - result = -EFAULT; - } + result = p80211req_dorequest(wlandev, msgbuf); + + if (result == 0) { + if (copy_to_user + ((void __user *)req->data, msgbuf, req->len)) { + result = -EFAULT; } - kfree(msgbuf); - } else { - result = -ENOMEM; } + kfree(msgbuf); + bail: /* If allocate,copyfrom or copyto fails, return errno */ return result; -- 2.26.2
[PATCH] staging:r8188eu: use IEEE80211_FCTL_* kernel definitions
_TO_DS_, _FROM_DS_, _MORE_FRAG_, _RETRY_, _PWRMGT_, _MORE_DATA_, _PRIVACY_, _ORDER_ definitions are duplicate IEEE80211_FCTL_* kernel definitions. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8188eu/include/wifi.h | 51 ++-- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h index d0380f7f1bab..1b9006879a11 100644 --- a/drivers/staging/rtl8188eu/include/wifi.h +++ b/drivers/staging/rtl8188eu/include/wifi.h @@ -88,73 +88,64 @@ enum WIFI_REG_DOMAIN { DOMAIN_MAX }; -#define _TO_DS_BIT(8) -#define _FROM_DS_ BIT(9) -#define _MORE_FRAG_BIT(10) -#define _RETRY_BIT(11) -#define _PWRMGT_ BIT(12) -#define _MORE_DATA_BIT(13) -#define _PRIVACY_ BIT(14) -#define _ORDER_BIT(15) - #define SetToDs(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_TO_DS_) + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS) -#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_TO_DS_)) != 0) +#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0) #define ClearToDs(pbuf)\ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_TO_DS_)) + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_TODS)) #define SetFrDs(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_FROM_DS_) + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_FROMDS) -#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_FROM_DS_)) != 0) +#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0) #define ClearFrDs(pbuf)\ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_FROM_DS_)) + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_FROMDS)) #define get_tofr_ds(pframe)((GetToDs(pframe) << 1) | GetFrDs(pframe)) #define SetMFrag(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_FRAG_) + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS) -#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_MORE_FRAG_)) != 0) +#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0) #define ClearMFrag(pbuf) \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_MORE_FRAG_)) + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) #define SetRetry(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_RETRY_) + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_RETRY) -#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_RETRY_)) != 0) +#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0) #define ClearRetry(pbuf) \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_RETRY_)) + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_RETRY)) #define SetPwrMgt(pbuf)\ - *(__le16 *)(pbuf) |= cpu_to_le16(_PWRMGT_) + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PM) -#define GetPwrMgt(pbuf)(((*(__le16 *)(pbuf)) & cpu_to_le16(_PWRMGT_)) != 0) +#define GetPwrMgt(pbuf)(((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_PM)) != 0) #define ClearPwrMgt(pbuf) \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_PWRMGT_)) + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_PM)) #define SetMData(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_MORE_DATA_) + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREDATA) -#define GetMData(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(_MORE_DATA_)) != 0) +#define GetMData(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0) #define ClearMData(pbuf) \ - *(__le16 *)(pbuf) &= (~cpu_to_le16(_MORE_DATA_)) + *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREDATA)) #define SetPrivacy(pbuf) \ - *(__le16 *)(pbuf) |= cpu_to_le16(_PRIVACY_) + *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PROTECTED) #define GetPrivacy(pbuf) \ - (((*(__le16 *)(pbuf)) & cpu_to_le16(_PRIVACY_)) != 0) + (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0) #define GetOrder(pbuf) \ - (((*(__le16 *)(pbuf)) & cpu_to_le16(_ORDER_)) != 0) + (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0) #define GetFrameType(pbuf) \ (le16_to_cpu(*(__le16 *)(pbuf)) & (BIT(3) | BIT(2))) -- 2.26.2
Re: [PATCH] HID: sony: Support for DS4 clones that do not implement feature report 0x81
Ignore this patch, I am working on a better one. On Wed, 2021-01-13 at 22:34 +0500, Ivan Mironov wrote: > There are clones of DualShock 4 that are very similar to the originals, > except of 1) they do not support HID feature report 0x81 and 2) they do > not have any USB Audio interfaces despite they physically have audio > jack. > > Such controllers are working fine with Linux when connected via > Bluetooth, but not when connected via USB. Here is how failed USB > connection attempt looks in log: > > usb 1-5: New USB device found, idVendor=054c, idProduct=05c4, > bcdDevice= 1.00 > usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=0 > usb 1-5: Product: Wireless Controller > usb 1-5: Manufacturer: Sony Computer Entertainment > sony 0003:054C:05C4.0007: failed to retrieve feature report 0x81 with > the DualShock 4 MAC address > sony 0003:054C:05C4.0007: hidraw6: USB HID v81.11 Gamepad [Sony > Computer Entertainment Wireless Controller] on usb-:00:14.0-5/input0 > sony 0003:054C:05C4.0007: failed to claim input > > This patch adds support of using feature report 0x12 as a fallback for > Bluetooth MAC address retrieval. Feature report 0x12 also seems to be > used by DS4Windows[1] for all DS4 controllers. > > [1] > https://github.com/Ryochan7/DS4Windows/blob/1b74a4440089f38a24ee2c2483c1d733a0692b8f/DS4Windows/HidLibrary/HidDevice.cs#L479 > > Signed-off-by: Ivan Mironov > --- > Â drivers/hid/hid-sony.c | 72 ++ > Â 1 file changed, 52 insertions(+), 20 deletions(-) > > diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c > index e3a557dc9ffd..97df12180e45 100644 > --- a/drivers/hid/hid-sony.c > +++ b/drivers/hid/hid-sony.c > @@ -491,6 +491,7 @@ struct motion_output_report_02 { > Â > > Â #define DS4_FEATURE_REPORT_0x02_SIZE 37 > Â #define DS4_FEATURE_REPORT_0x05_SIZE 41 > +#define DS4_FEATURE_REPORT_0x12_SIZE 16 > Â #define DS4_FEATURE_REPORT_0x81_SIZE 7 > Â #define DS4_FEATURE_REPORT_0xA3_SIZE 49 > Â #define DS4_INPUT_REPORT_0x11_SIZE 78 > @@ -2593,6 +2594,53 @@ static int sony_get_bt_devaddr(struct sony_sc *sc) > Â return 0; > Â } > Â > > +static int sony_get_usb_ds4_devaddr(struct sony_sc *sc) > +{ > + u8 *buf = NULL; > + int ret; > + > + buf = kmalloc(max(DS4_FEATURE_REPORT_0x12_SIZE, > DS4_FEATURE_REPORT_0x81_SIZE), GFP_KERNEL); > + if (!buf) > + return -ENOMEM; > + > + /* > + * The MAC address of a DS4 controller connected via USB can be > + * retrieved with feature report 0x81. The address begins at > + * offset 1. > + */ > + ret = hid_hw_raw_request(sc->hdev, 0x81, buf, > + DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT, > + HID_REQ_GET_REPORT); > + if (ret == DS4_FEATURE_REPORT_0x81_SIZE) { > + memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); > + goto out_free; > + } > + dbg_hid("%s: hid_hw_raw_request(..., 0x81, ...) returned %d\n", > __func__, ret); > + > + /* > + * Some variants do not implement feature report 0x81 at all. > + * Fortunately, feature report 0x12 also contains the MAC address of > + * a controller. > + */ > + ret = hid_hw_raw_request(sc->hdev, 0x12, buf, > + DS4_FEATURE_REPORT_0x12_SIZE, HID_FEATURE_REPORT, > + HID_REQ_GET_REPORT); > + if (ret == DS4_FEATURE_REPORT_0x12_SIZE) { > + memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); > + goto out_free; > + } > + dbg_hid("%s: hid_hw_raw_request(..., 0x12, ...) returned %d\n", > __func__, ret); > + > + hid_err(sc->hdev, "failed to retrieve feature reports 0x81 and 0x12 > with the DualShock 4 MAC address\n"); > + ret = ret < 0 ? ret : -EINVAL; > + > +out_free: > + > + kfree(buf); > + > + return ret; > +} > + > Â static int sony_check_add(struct sony_sc *sc) > Â { > Â u8 *buf = NULL; > @@ -2613,26 +2661,9 @@ static int sony_check_add(struct sony_sc *sc) > Â return 0; > Â } > Â } else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | > DUALSHOCK4_DONGLE)) { > - buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL); > - if (!buf) > - return -ENOMEM; > - > - /* > - * The MAC address of a DS4 controller connected via USB can be > - * retrieved with feature report 0x81. The address begins at > - * offset 1. > -
Re: [PATCH 2/2] x86/unwind/orc: Silence warnings caused by missing ORC data
On Mon, Feb 8, 2021 at 11:56 AM Josh Poimboeuf wrote: > > On Fri, Feb 05, 2021 at 08:24:03AM -0600, Josh Poimboeuf wrote: > > The ORC unwinder attempts to fall back to frame pointers when ORC data > > is missing for a given instruction. It sets state->error, but then > > tries to keep going as a best-effort type of thing. That may result in > > further warnings if the unwinder gets lost. > > > > Until we have some way to register generated code with the unwinder, > > missing ORC will be expected, and occasionally going off the rails will > > also be expected. So don't warn about it. > > > > Signed-off-by: Josh Poimboeuf > > Cc: sta...@vger.kernel.org I was the one who asked for this to be backported, since it solved the warnings for me. Tested-by: Ivan Babrou
Re: [PATCH] mips: kernel: setup: fix crash kernel resource allocation
On Sun, Feb 07, 2021 at 11:18:42AM +0200, Mike Rapoport wrote: On Sat, Feb 06, 2021 at 12:59:40PM +, Ivan Khoronzhuk wrote: In order to avoid crash kernel corruption, its memory is reserved early in memblock and as result, in time when resources are inited it's not present in memblock.memory, so crash kernel memory is out of ranges listed with for_each_mem_range(). To avoid it and still keep memory reserved lets reseve it out of loop by inserting it in iomem_resource. Unless I misread the code, the crash kernel memory is actually allocated from memblock (memblock_find_in_range + memblock_reserve), but for some reason memblock_reserve() is called outside mips_parse_crashkernel(). So the crash kernel memory is surely in both memblock.memory and memblock.reserved and it will be covered by for_each_mem_range(). The mips_parse_crashkernel() function and the following reservation of crash kernel memory should be merged, IMO, and this can be further simplified with memblock_alloc() helpers. Is there a particular issue you are trying to fix? Yes, sorry, according to local code, seems like memory was not added (was reverted memblock_find_in_range for some other reson while porting), so I had only reserve. The issue is in another place, so ignoe this patch, for now. Fixes: a94e4f24ec83 ("MIPS: init: Drop boot_mem_map") Signed-off-by: Ivan Khoronzhuk --- Based on linux-next/master arch/mips/kernel/setup.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 3785c72bc3bc..25e376ef2f2a 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -473,14 +473,15 @@ static void __init mips_parse_crashkernel(void) crashk_res.end = crash_base + crash_size - 1; } -static void __init request_crashkernel(struct resource *res) +static void __init request_crashkernel(void) { int ret; if (crashk_res.start == crashk_res.end) return; - ret = request_resource(res, &crashk_res); + /* The crashk resource shoud be located in normal mem */ + ret = insert_resource(&iomem_resource, &crashk_res); if (!ret) pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n", (unsigned long)(resource_size(&crashk_res) >> 20), @@ -734,8 +735,9 @@ static void __init resource_init(void) request_resource(res, &code_resource); request_resource(res, &data_resource); request_resource(res, &bss_resource); - request_crashkernel(res); } + + request_crashkernel(); } #ifdef CONFIG_SMP -- 2.23.1 -- Sincerely yours, Mike. -- Regards, Ivan Khoronzhuk
Re: [PATCH] mips: kernel: setup: fix crash kernel resource allocation
On Sun, Feb 07, 2021 at 11:19:03AM +0800, Jinyang He wrote: On 02/06/2021 08:59 PM, Ivan Khoronzhuk wrote: In order to avoid crash kernel corruption, its memory is reserved early in memblock and as result, in time when resources are inited it's not present in memblock.memory, so crash kernel memory is out of ranges listed with for_each_mem_range(). To avoid it and still keep memory reserved lets reseve it out of loop by inserting it in iomem_resource. Hi, Ivan, I'm not familiar with memblock. If the following my ideas show my ignorance, please forgive me. First, not only the crash kernel is reserved early in memblock, but also code, data, and bss are also reserved in bootmem_init(): /* Reserve memory occupied by kernel. */ memblock_reserve(__pa_symbol(&_text), __pa_symbol(&_end) - __pa_symbol(&_text)); (CONFIG_NUMA is not enabled. NUMA platform reserved them is earlier.) If there is something unsuitable with the crash kernel, is there something unsuitable with the kernel memory? Then, for_each_mem_range() is normal memory. Although memblock_reserve() has used before that, it just adds memory to memblock.reserved. That means it will still appear in memblock.memory. Thus, here I have a question, do we need to use replace for_each_mem_range with for_each_mem_range_rev? Reserve doesn't mean it's present in memblock.memory, if it memory was not added before, like it's supposed. In my canse, seems like to local issue it wasn't, that's why it was not present. So, traverse direction won't solve this obviously. Finally, thank you for the patch, it makes me think a lot. Thanks, Jinyang Fixes: a94e4f24ec83 ("MIPS: init: Drop boot_mem_map") Signed-off-by: Ivan Khoronzhuk --- Based on linux-next/master arch/mips/kernel/setup.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 3785c72bc3bc..25e376ef2f2a 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -473,14 +473,15 @@ static void __init mips_parse_crashkernel(void) crashk_res.end = crash_base + crash_size - 1; } -static void __init request_crashkernel(struct resource *res) +static void __init request_crashkernel(void) { int ret; if (crashk_res.start == crashk_res.end) return; - ret = request_resource(res, &crashk_res); + /* The crashk resource shoud be located in normal mem */ + ret = insert_resource(&iomem_resource, &crashk_res); if (!ret) pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n", (unsigned long)(resource_size(&crashk_res) >> 20), @@ -734,8 +735,9 @@ static void __init resource_init(void) request_resource(res, &code_resource); request_resource(res, &data_resource); request_resource(res, &bss_resource); - request_crashkernel(res); } + + request_crashkernel(); } #ifdef CONFIG_SMP -- Regards, Ivan Khoronzhuk
[PATCH] mips: kernel: setup: fix crash kernel resource allocation
In order to avoid crash kernel corruption, its memory is reserved early in memblock and as result, in time when resources are inited it's not present in memblock.memory, so crash kernel memory is out of ranges listed with for_each_mem_range(). To avoid it and still keep memory reserved lets reseve it out of loop by inserting it in iomem_resource. Fixes: a94e4f24ec83 ("MIPS: init: Drop boot_mem_map") Signed-off-by: Ivan Khoronzhuk --- Based on linux-next/master arch/mips/kernel/setup.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 3785c72bc3bc..25e376ef2f2a 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -473,14 +473,15 @@ static void __init mips_parse_crashkernel(void) crashk_res.end = crash_base + crash_size - 1; } -static void __init request_crashkernel(struct resource *res) +static void __init request_crashkernel(void) { int ret; if (crashk_res.start == crashk_res.end) return; - ret = request_resource(res, &crashk_res); + /* The crashk resource shoud be located in normal mem */ + ret = insert_resource(&iomem_resource, &crashk_res); if (!ret) pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n", (unsigned long)(resource_size(&crashk_res) >> 20), @@ -734,8 +735,9 @@ static void __init resource_init(void) request_resource(res, &code_resource); request_resource(res, &data_resource); request_resource(res, &bss_resource); - request_crashkernel(res); } + + request_crashkernel(); } #ifdef CONFIG_SMP -- 2.23.1
Re: [PATCH 1/2] x86/unwind/orc: Disable KASAN checking in the ORC unwinder, part 2
On Fri, Feb 5, 2021 at 6:24 AM Josh Poimboeuf wrote: > > KASAN reserves "redzone" areas between stack frames in order to detect > stack overruns. A read or write to such an area triggers a KASAN > "stack-out-of-bounds" BUG. > > Normally, the ORC unwinder stays in-bounds and doesn't access the > redzone. But sometimes it can't find ORC metadata for a given > instruction. This can happen for code which is missing ORC metadata, or > for generated code. In such cases, the unwinder attempts to fall back > to frame pointers, as a best-effort type thing. > > This fallback often works, but when it doesn't, the unwinder can get > confused and go off into the weeds into the KASAN redzone, triggering > the aforementioned KASAN BUG. > > But in this case, the unwinder's confusion is actually harmless and > working as designed. It already has checks in place to prevent > off-stack accesses, but those checks get short-circuited by the KASAN > BUG. And a BUG is a lot more disruptive than a harmless unwinder > warning. > > Disable the KASAN checks by using READ_ONCE_NOCHECK() for all stack > accesses. This finishes the job started by commit 881125bfe65b > ("x86/unwind: Disable KASAN checking in the ORC unwinder"), which only > partially fixed the issue. > > Fixes: ee9f8fce9964 ("x86/unwind: Add the ORC unwinder") > Reported-by: Ivan Babrou > Cc: sta...@vger.kernel.org > Signed-off-by: Josh Poimboeuf I haven't seen any previously observed issues with this after a day of uptime. Tested-by: Ivan Babrou
Re: BUG: KASAN: stack-out-of-bounds in unwind_next_frame+0x1df5/0x2650
On Wed, Feb 3, 2021 at 4:17 PM Josh Poimboeuf wrote: > > On Wed, Feb 03, 2021 at 03:30:35PM -0800, Ivan Babrou wrote: > > > > > Can you recreate with this patch, and add "unwind_debug" to the > > > > > cmdline? > > > > > It will spit out a bunch of stack data. > > > > > > > > Here's the three I'm building: > > > > > > > > * https://github.com/bobrik/linux/tree/ivan/static-call-5.9 > > > > > > > > It contains: > > > > > > > > * v5.9 tag as the base > > > > * static_call-2020-10-12 tag > > > > * dm-crypt patches to reproduce the issue with KASAN > > > > * x86/unwind: Add 'unwind_debug' cmdline option > > > > * tracepoint: Fix race between tracing and removing tracepoint > > > > > > > > The very same issue can be reproduced on 5.10.11 with no patches, > > > > but I'm going with 5.9, since it boils down to static call changes. > > > > > > > > Here's the decoded stack from the kernel with unwind debug enabled: > > > > > > > > * https://gist.github.com/bobrik/ed052ac0ae44c880f3170299ad4af56b > > > > > > > > See my first email for the exact commands that trigger this. > > > > > > Thanks. Do you happen to have the original dmesg, before running it > > > through the post-processing script? > > > > Yes, here it is: > > > > * https://gist.github.com/bobrik/8c13e6a02555fb21cadabb74cdd6f9ab > > It appears the unwinder is getting lost in crypto code. No idea what > this has to do with static calls though. Or maybe you're seeing > multiple issues. > > Does this fix it? > > > diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile > index a31de0c6ccde..36c55341137c 100644 > --- a/arch/x86/crypto/Makefile > +++ b/arch/x86/crypto/Makefile > @@ -2,7 +2,14 @@ > # > # x86 crypto algorithms > > -OBJECT_FILES_NON_STANDARD := y > +OBJECT_FILES_NON_STANDARD_sha256-avx2-asm.o:= y > +OBJECT_FILES_NON_STANDARD_sha512-ssse3-asm.o := y > +OBJECT_FILES_NON_STANDARD_sha512-avx-asm.o := y > +OBJECT_FILES_NON_STANDARD_sha512-avx2-asm.o:= y > +OBJECT_FILES_NON_STANDARD_crc32c-pcl-intel-asm_64.o:= y > +OBJECT_FILES_NON_STANDARD_camellia-aesni-avx2-asm_64.o := y > +OBJECT_FILES_NON_STANDARD_sha1_avx2_x86_64_asm.o := y > +OBJECT_FILES_NON_STANDARD_sha1_ni_asm.o:= y > > obj-$(CONFIG_CRYPTO_GLUE_HELPER_X86) += glue_helper.o > > diff --git a/arch/x86/crypto/aesni-intel_avx-x86_64.S > b/arch/x86/crypto/aesni-intel_avx-x86_64.S > index 5fee47956f3b..59c36b88954f 100644 > --- a/arch/x86/crypto/aesni-intel_avx-x86_64.S > +++ b/arch/x86/crypto/aesni-intel_avx-x86_64.S > @@ -237,8 +237,8 @@ define_reg j %j > .noaltmacro > .endm > > -# need to push 4 registers into stack to maintain > -STACK_OFFSET = 8*4 > +# need to push 5 registers into stack to maintain > +STACK_OFFSET = 8*5 > > TMP1 = 16*0# Temporary storage for AAD > TMP2 = 16*1# Temporary storage for AES State 2 (State 1 is stored in > an XMM register) > @@ -257,6 +257,8 @@ VARIABLE_OFFSET = 16*8 > > .macro FUNC_SAVE > #the number of pushes must equal STACK_OFFSET > + push%rbp > + mov %rsp, %rbp > push%r12 > push%r13 > push%r14 > @@ -271,12 +273,14 @@ VARIABLE_OFFSET = 16*8 > .endm > > .macro FUNC_RESTORE > +add $VARIABLE_OFFSET, %rsp > mov %r14, %rsp > > pop %r15 > pop %r14 > pop %r13 > pop %r12 > + pop %rbp > .endm > > # Encryption of a single block > This patch seems to fix the following warning: [ 147.995699][C0] WARNING: stack going in the wrong direction? at glue_xts_req_128bit+0x21f/0x6f0 [glue_helper] Or at least I cannot see it anymore when combined with your other patch, not sure if it did the trick by itself. This sounds like a good reason to send them both.
Re: BUG: KASAN: stack-out-of-bounds in unwind_next_frame+0x1df5/0x2650
On Wed, Feb 3, 2021 at 7:10 PM Josh Poimboeuf wrote: > This line gives a big clue: > > [160676.608966][C4] RIP: 0010:0xc17d814c > > That address, without a function name, most likely means that it was > running in some generated code (mostly likely BPF) when it got > interrupted. We do have eBPF/XDP in our environment. > Right now, the ORC unwinder tries to fall back to frame pointers when it > encounters generated code: > > orc = orc_find(state->signal ? state->ip : state->ip - 1); > if (!orc) > /* > * As a fallback, try to assume this code uses a frame > pointer. > * This is useful for generated code, like BPF, which ORC > * doesn't know about. This is just a guess, so the rest of > * the unwind is no longer considered reliable. > */ > orc = &orc_fp_entry; > state->error = true; > } > > Because the ORC unwinder is guessing from that point onward, it's > possible for it to read the KASAN stack redzone, if the generated code > hasn't set up frame pointers. So the best fix may be for the unwinder > to just always bypass KASAN when reading the stack. > > The unwinder has a mechanism for detecting and warning about > out-of-bounds, and KASAN is short-circuiting that. > > This should hopefully get rid of *all* the KASAN unwinder warnings, both > crypto and networking. It definitely worked on my dm-crypt case, and I've tried it without your previous AVX related patch. I will apply it to our tree and deploy to the staging KASAN environment to see how it fares with respect to networking stacks. Feel free to ping me if I don't get back to you with the results on Monday. Thanks for looking into this!
Re: BUG: KASAN: stack-out-of-bounds in unwind_next_frame+0x1df5/0x2650
On Wed, Feb 3, 2021 at 4:17 PM Josh Poimboeuf wrote: > > On Wed, Feb 03, 2021 at 03:30:35PM -0800, Ivan Babrou wrote: > > > > > Can you recreate with this patch, and add "unwind_debug" to the > > > > > cmdline? > > > > > It will spit out a bunch of stack data. > > > > > > > > Here's the three I'm building: > > > > > > > > * https://github.com/bobrik/linux/tree/ivan/static-call-5.9 > > > > > > > > It contains: > > > > > > > > * v5.9 tag as the base > > > > * static_call-2020-10-12 tag > > > > * dm-crypt patches to reproduce the issue with KASAN > > > > * x86/unwind: Add 'unwind_debug' cmdline option > > > > * tracepoint: Fix race between tracing and removing tracepoint > > > > > > > > The very same issue can be reproduced on 5.10.11 with no patches, > > > > but I'm going with 5.9, since it boils down to static call changes. > > > > > > > > Here's the decoded stack from the kernel with unwind debug enabled: > > > > > > > > * https://gist.github.com/bobrik/ed052ac0ae44c880f3170299ad4af56b > > > > > > > > See my first email for the exact commands that trigger this. > > > > > > Thanks. Do you happen to have the original dmesg, before running it > > > through the post-processing script? > > > > Yes, here it is: > > > > * https://gist.github.com/bobrik/8c13e6a02555fb21cadabb74cdd6f9ab > > It appears the unwinder is getting lost in crypto code. No idea what > this has to do with static calls though. Or maybe you're seeing > multiple issues. > > Does this fix it? It does for the dm-crypt case! But so does the following commit in 5.11 (and 5.10.12): * https://github.com/torvalds/linux/commit/ce8f86ee94?w=1 The reason I stuck to dm-crypt reproduction is that it reproduces reliably. We also have the following stack that doesn't touch any crypto: * https://gist.github.com/bobrik/40e2559add2f0b26ae39da30dc451f1e I cannot reproduce this one, and it took 2 days of uptime for it to happen. Is there anything I can do to help diagnose it? My goal is to enable multishot KASAN in our pre-production environment, but currently it sometimes starves TX queues on the NIC due to multiple reports in a row in an interrupt about unwind_next_frame, which disables network interface, which is not something we can tolerate.
Re: BUG: KASAN: stack-out-of-bounds in unwind_next_frame+0x1df5/0x2650
On Wed, Feb 3, 2021 at 3:28 PM Josh Poimboeuf wrote: > > On Wed, Feb 03, 2021 at 02:41:53PM -0800, Ivan Babrou wrote: > > On Wed, Feb 3, 2021 at 11:05 AM Josh Poimboeuf wrote: > > > > > > On Wed, Feb 03, 2021 at 09:46:55AM -0800, Ivan Babrou wrote: > > > > > Can you pretty please not line-wrap console output? It's unreadable. > > > > > > > > GMail doesn't make it easy, I'll send a link to a pastebin next time. > > > > Let me know if you'd like me to regenerate the decoded stack. > > > > > > > > > > edfd9b7838ba5e47f19ad8466d0565aba5c59bf0 is the first bad commit > > > > > > commit edfd9b7838ba5e47f19ad8466d0565aba5c59bf0 > > > > > > > > > > Not sure what tree you're on, but that's not the upstream commit. > > > > > > > > I mentioned that it's a rebased core-static_call-2020-10-12 tag and > > > > added a link to the upstream hash right below. > > > > > > > > > > Author: Steven Rostedt (VMware) > > > > > > Date: Tue Aug 18 15:57:52 2020 +0200 > > > > > > > > > > > > tracepoint: Optimize using static_call() > > > > > > > > > > > > > > > > There's a known issue with that patch, can you try: > > > > > > > > > > http://lkml.kernel.org/r/20210202220121.435051...@goodmis.org > > > > > > > > I've tried it on top of core-static_call-2020-10-12 tag rebased on top > > > > of v5.9 (to make it reproducible), and the patch did not help. Do I > > > > need to apply the whole series or something else? > > > > > > Can you recreate with this patch, and add "unwind_debug" to the cmdline? > > > It will spit out a bunch of stack data. > > > > Here's the three I'm building: > > > > * https://github.com/bobrik/linux/tree/ivan/static-call-5.9 > > > > It contains: > > > > * v5.9 tag as the base > > * static_call-2020-10-12 tag > > * dm-crypt patches to reproduce the issue with KASAN > > * x86/unwind: Add 'unwind_debug' cmdline option > > * tracepoint: Fix race between tracing and removing tracepoint > > > > The very same issue can be reproduced on 5.10.11 with no patches, > > but I'm going with 5.9, since it boils down to static call changes. > > > > Here's the decoded stack from the kernel with unwind debug enabled: > > > > * https://gist.github.com/bobrik/ed052ac0ae44c880f3170299ad4af56b > > > > See my first email for the exact commands that trigger this. > > Thanks. Do you happen to have the original dmesg, before running it > through the post-processing script? Yes, here it is: * https://gist.github.com/bobrik/8c13e6a02555fb21cadabb74cdd6f9ab > I assume you're using decode_stacktrace.sh? It could use some > improvement, it's stripping the function offset. > > Also spaces are getting inserted in odd places, messing the alignment. > > [ 137.291837][C0] 88809c409858: d7c4f3ce817a1700 (0xd7c4f3ce817a1700) > [ 137.291837][C0] 88809c409860: (0x0) > [ 137.291839][C0] 88809c409868: (0x) > [ 137.291841][ C0] 88809c409870: a4f01a52 unwind_next_frame > (arch/x86/kernel/unwind_orc.c:380 arch/x86/kernel/unwind_orc.c:553) > [ 137.291843][ C0] 88809c409878: a4f01a52 unwind_next_frame > (arch/x86/kernel/unwind_orc.c:380 arch/x86/kernel/unwind_orc.c:553) > [ 137.291844][C0] 88809c409880: 88809c409ac8 (0x88809c409ac8) > [ 137.291845][C0] 88809c409888: 0086 (0x86) > > -- > Josh >
Re: BUG: KASAN: stack-out-of-bounds in unwind_next_frame+0x1df5/0x2650
On Wed, Feb 3, 2021 at 11:05 AM Josh Poimboeuf wrote: > > On Wed, Feb 03, 2021 at 09:46:55AM -0800, Ivan Babrou wrote: > > > Can you pretty please not line-wrap console output? It's unreadable. > > > > GMail doesn't make it easy, I'll send a link to a pastebin next time. > > Let me know if you'd like me to regenerate the decoded stack. > > > > > > edfd9b7838ba5e47f19ad8466d0565aba5c59bf0 is the first bad commit > > > > commit edfd9b7838ba5e47f19ad8466d0565aba5c59bf0 > > > > > > Not sure what tree you're on, but that's not the upstream commit. > > > > I mentioned that it's a rebased core-static_call-2020-10-12 tag and > > added a link to the upstream hash right below. > > > > > > Author: Steven Rostedt (VMware) > > > > Date: Tue Aug 18 15:57:52 2020 +0200 > > > > > > > > tracepoint: Optimize using static_call() > > > > > > > > > > There's a known issue with that patch, can you try: > > > > > > http://lkml.kernel.org/r/20210202220121.435051...@goodmis.org > > > > I've tried it on top of core-static_call-2020-10-12 tag rebased on top > > of v5.9 (to make it reproducible), and the patch did not help. Do I > > need to apply the whole series or something else? > > Can you recreate with this patch, and add "unwind_debug" to the cmdline? > It will spit out a bunch of stack data. Here's the three I'm building: * https://github.com/bobrik/linux/tree/ivan/static-call-5.9 It contains: * v5.9 tag as the base * static_call-2020-10-12 tag * dm-crypt patches to reproduce the issue with KASAN * x86/unwind: Add 'unwind_debug' cmdline option * tracepoint: Fix race between tracing and removing tracepoint The very same issue can be reproduced on 5.10.11 with no patches, but I'm going with 5.9, since it boils down to static call changes. Here's the decoded stack from the kernel with unwind debug enabled: * https://gist.github.com/bobrik/ed052ac0ae44c880f3170299ad4af56b See my first email for the exact commands that trigger this.
Re: BUG: KASAN: stack-out-of-bounds in unwind_next_frame+0x1df5/0x2650
> Can you pretty please not line-wrap console output? It's unreadable. GMail doesn't make it easy, I'll send a link to a pastebin next time. Let me know if you'd like me to regenerate the decoded stack. > > edfd9b7838ba5e47f19ad8466d0565aba5c59bf0 is the first bad commit > > commit edfd9b7838ba5e47f19ad8466d0565aba5c59bf0 > > Not sure what tree you're on, but that's not the upstream commit. I mentioned that it's a rebased core-static_call-2020-10-12 tag and added a link to the upstream hash right below. > > Author: Steven Rostedt (VMware) > > Date: Tue Aug 18 15:57:52 2020 +0200 > > > > tracepoint: Optimize using static_call() > > > > There's a known issue with that patch, can you try: > > http://lkml.kernel.org/r/20210202220121.435051...@goodmis.org I've tried it on top of core-static_call-2020-10-12 tag rebased on top of v5.9 (to make it reproducible), and the patch did not help. Do I need to apply the whole series or something else?
Re: BUG: KASAN: stack-out-of-bounds in unwind_next_frame+0x1df5/0x2650
On Thu, Jan 28, 2021 at 7:35 PM Ivan Babrou wrote: > > Hello, > > We've noticed the following regression in Linux 5.10 branch: > > [ 128.367231][C0] > == > [ 128.368523][C0] BUG: KASAN: stack-out-of-bounds in > unwind_next_frame (arch/x86/kernel/unwind_orc.c:371 > arch/x86/kernel/unwind_orc.c:544) > [ 128.369744][C0] Read of size 8 at addr 88802fceede0 by task > kworker/u2:2/591 > [ 128.370916][C0] > [ 128.371269][C0] CPU: 0 PID: 591 Comm: kworker/u2:2 Not tainted > 5.10.11-cloudflare-kasan-2021.1.15 #1 > [ 128.372626][C0] Hardware name: QEMU Standard PC (i440FX + PIIX, > 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 > [ 128.374346][C0] Workqueue: writeback wb_workfn (flush-254:0) > [ 128.375275][C0] Call Trace: > [ 128.375763][C0] > [ 128.376221][C0] dump_stack+0x7d/0xa3 > [ 128.376843][C0] print_address_description.constprop.0+0x1c/0x210 > [ 128.377827][C0] ? _raw_spin_lock_irqsave > (arch/x86/include/asm/atomic.h:202 > include/asm-generic/atomic-instrumented.h:707 > include/asm-generic/qspinlock.h:82 include/linux/spinlock.h:195 > include/linux/spinlock_api_smp.h:119 kernel/locking/spinlock.c:159) > [ 128.378624][C0] ? _raw_write_unlock_bh (kernel/locking/spinlock.c:158) > [ 128.379389][C0] ? unwind_next_frame (arch/x86/kernel/unwind_orc.c:444) > [ 128.380177][C0] ? unwind_next_frame > (arch/x86/kernel/unwind_orc.c:371 arch/x86/kernel/unwind_orc.c:544) > [ 128.380954][C0] ? unwind_next_frame > (arch/x86/kernel/unwind_orc.c:371 arch/x86/kernel/unwind_orc.c:544) > [ 128.381736][C0] kasan_report.cold+0x1f/0x37 > [ 128.382438][C0] ? unwind_next_frame > (arch/x86/kernel/unwind_orc.c:371 arch/x86/kernel/unwind_orc.c:544) > [ 128.383192][C0] unwind_next_frame+0x1df5/0x2650 > [ 128.383954][C0] ? asm_common_interrupt > (arch/x86/include/asm/idtentry.h:622) > [ 128.384726][C0] ? get_stack_info_noinstr > (arch/x86/kernel/dumpstack_64.c:157) > [ 128.385530][C0] ? glue_xts_req_128bit+0x110/0x6f0 glue_helper > [ 128.386509][C0] ? deref_stack_reg (arch/x86/kernel/unwind_orc.c:418) > [ 128.387267][C0] ? is_module_text_address (kernel/module.c:4566 > kernel/module.c:4550) > [ 128.388077][C0] ? glue_xts_req_128bit+0x110/0x6f0 glue_helper > [ 128.389048][C0] ? kernel_text_address.part.0 (kernel/extable.c:145) > [ 128.389901][C0] ? glue_xts_req_128bit+0x110/0x6f0 glue_helper > [ 128.390865][C0] ? stack_trace_save (kernel/stacktrace.c:82) > [ 128.391550][C0] arch_stack_walk+0x8d/0xf0 > [ 128.392216][C0] ? kfree (mm/slub.c:3142 mm/slub.c:4124) > [ 128.392807][C0] stack_trace_save+0x96/0xd0 > [ 128.393535][C0] ? create_prof_cpu_mask (kernel/stacktrace.c:113) > [ 128.394320][C0] ? blk_update_request (block/blk-core.c:264 > block/blk-core.c:1468) > [ 128.395113][C0] ? asm_call_irq_on_stack > (arch/x86/entry/entry_64.S:796) > [ 128.395887][C0] ? do_softirq_own_stack > (arch/x86/include/asm/irq_stack.h:27 > arch/x86/include/asm/irq_stack.h:77 arch/x86/kernel/irq_64.c:77) > [ 128.396678][C0] ? irq_exit_rcu (kernel/softirq.c:393 > kernel/softirq.c:423 kernel/softirq.c:435) > [ 128.397349][C0] ? common_interrupt (arch/x86/kernel/irq.c:239) > [ 128.398086][C0] ? asm_common_interrupt > (arch/x86/include/asm/idtentry.h:622) > [ 128.398886][C0] ? get_page_from_freelist (mm/page_alloc.c:3480 > mm/page_alloc.c:3904) > [ 128.399759][C0] kasan_save_stack+0x20/0x50 > [ 128.400453][C0] ? kasan_save_stack (mm/kasan/common.c:48) > [ 128.401175][C0] ? kasan_set_track (mm/kasan/common.c:56) > [ 128.401881][C0] ? kasan_set_free_info (mm/kasan/generic.c:360) > [ 128.402646][C0] ? __kasan_slab_free (mm/kasan/common.c:283 > mm/kasan/common.c:424) > [ 128.403375][C0] ? slab_free_freelist_hook (mm/slub.c:1577) > [ 128.404199][C0] ? kfree (mm/slub.c:3142 mm/slub.c:4124) > [ 128.404835][C0] ? nvme_pci_complete_rq+0x105/0x350 nvme > [ 128.405765][C0] ? blk_done_softirq (include/linux/list.h:282 > block/blk-mq.c:581) > [ 128.406552][C0] ? __do_softirq > (arch/x86/include/asm/jump_label.h:25 include/linux/jump_label.h:200 > include/trace/events/irq.h:142 kernel/softirq.c:299) > [ 128.407272][C0] ? asm_call_irq_on_stack > (arch/x86/entry/entry_64.S:796) > [ 128.408087][C0] ? do_softirq_own_stack > (arch/x86/include/asm/irq_stack.h:27 > arch/x86/include/asm/irq_stack.h:77 arch/x86/kernel/irq_64.c:77) > [ 128.408878][C0] ? irq_exit_rcu (kernel/softirq.c:393 > kernel/softirq.c:423 kernel/softirq.c:435) >
Re: [PATCH] net: phy: add Marvell 88X2222 transceiver support
On Tue, Feb 02, 2021 at 04:48:01PM +, Russell King - ARM Linux admin wrote: > On Mon, Feb 01, 2021 at 10:22:51PM +0300, Ivan Bornyakov wrote: > > +/* PMD Transmit Disable */ > > +#defineMV_TX_DISABLE 0x0009 > > +#defineMV_TX_DISABLE_GLOBALBIT(0) > > Please use MDIO_PMA_TXDIS and MDIO_PMD_TXDIS_GLOBAL; this is an > IEEE802.3 defined register. > > > +/* 10GBASE-R PCS Status 1 */ > > +#defineMV_10GBR_STAT MDIO_STAT1 > > Nothing Marvell specific here, please use MDIO_STAT1 directly. > > > +/* 1000Base-X/SGMII Control Register */ > > +#defineMV_1GBX_CTRL0x2000 > > + > > +/* 1000BASE-X/SGMII Status Register */ > > +#defineMV_1GBX_STAT0x2001 > > + > > +/* 1000Base-X Auto-Negotiation Advertisement Register */ > > +#defineMV_1GBX_ADVERTISE 0x2004 > > Marvell have had a habbit of placing other PHY instances within the > register space. This also looks like Clause 22 layout rather than > Clause 45 layout - please use the Clause 22 definitions for the bits > rather than Clause 45. (so BMCR_ANENABLE, BMCR_ANRESTART for > MV_1GBX_CTRL, etc). > > Please define these as: > > +#define MV_1GBX_CTRL(0x2000 + MII_BMCR) > +#define MV_1GBX_STAT(0x2000 + MII_BMSR) > +#define MV_1GBX_ADVERTISE (0x2000 + MII_ADVERTISE) > > to make it clear what is going on here. > > > +static int sfp_module_insert(void *_priv, const struct sfp_eeprom_id *id) > > +{ > > + struct phy_device *phydev = _priv; > > + struct device *dev = &phydev->mdio.dev; > > + struct mv_data *priv = phydev->priv; > > + phy_interface_t interface; > > + > > + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, }; > > + > > + sfp_parse_support(phydev->sfp_bus, id, supported); > > + interface = sfp_select_interface(phydev->sfp_bus, supported); > > + > > + dev_info(dev, "%s SFP module inserted", phy_modes(interface)); > > + > > + switch (interface) { > > + case PHY_INTERFACE_MODE_10GBASER: > > + phydev->speed = SPEED_1; > > + phydev->interface = PHY_INTERFACE_MODE_10GBASER; > > + linkmode_set_bit(ETHTOOL_LINK_MODE_1baseKR_Full_BIT, > > +phydev->supported); > > + > > + phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG, > > + MV_PCS_HOST_XAUI | MV_PCS_LINE_10GBR); > > + mv_soft_reset(phydev); > > + break; > > + case PHY_INTERFACE_MODE_1000BASEX: > > + default: > > + phydev->speed = SPEED_1000; > > + phydev->interface = PHY_INTERFACE_MODE_1000BASEX; > > + linkmode_clear_bit(ETHTOOL_LINK_MODE_1baseKR_Full_BIT, > > + phydev->supported); > > + > > + phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG, > > + MV_PCS_HOST_XAUI | MV_PCS_LINE_1GBX_AN); > > + mv_soft_reset(phydev); > > + } > > + > > + priv->sfp_inserted = true; > > + > > + if (priv->net_up) > > + mv_tx_enable(phydev); > > This is racy. priv->net_up is modified via the suspend/resume > callbacks, which are called with phydev->lock held. No other locks > are guaranteed to be held. > > However, this function is called with the SFP sm_mutex, and rtnl > held. Consequently, the use of sfp_inserted and net_up in this > function and the suspend/resume callbacks is racy. > > Why are you disabling the transmitter anyway? Is this for power > saving? > Actually, the original thought was to down the link on the other side, when network interface is down on our side. Power saving is a nice side-effect. > > +static void mv_update_interface(struct phy_device *phydev) > > +{ > > + if ((phydev->speed == SPEED_1000 || > > +phydev->speed == SPEED_100 || > > +phydev->speed == SPEED_10) && > > + phydev->interface != PHY_INTERFACE_MODE_1000BASEX) { > > + phydev->interface = PHY_INTERFACE_MODE_1000BASEX; > > + > > + phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG, > > + MV_PCS_HOST_XAUI | MV_PCS_LINE_1GBX_AN); > > + mv_soft_reset(phydev); > > + } else if (phydev->speed == SPEED_1 && > > + phydev->interface != PHY_INTERFACE_MODE_10GBASER) { > > + phydev->interface = PHY_INTERFACE_MODE_10GBASER; > > + &g
Re: [PATCH] net: phy: add Marvell 88X2222 transceiver support
On Mon, Feb 01, 2021 at 11:56:01PM +0100, Andrew Lunn wrote: > > +static int mv_config_init(struct phy_device *phydev) > > +{ > > + linkmode_zero(phydev->supported); > > + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); > > + linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported); > > + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, > > phydev->supported); > > + linkmode_set_bit(ETHTOOL_LINK_MODE_1baseKR_Full_BIT, > > phydev->supported); > > + > > + phydev->pause = 0; > > + phydev->asym_pause = 0; > > + phydev->duplex = DUPLEX_FULL; > > + phydev->autoneg = AUTONEG_DISABLE; > > + > > + return 0; > > +} > > + > > +static void mv_update_interface(struct phy_device *phydev) > > +{ > > + if ((phydev->speed == SPEED_1000 || > > +phydev->speed == SPEED_100 || > > +phydev->speed == SPEED_10) && > > + phydev->interface != PHY_INTERFACE_MODE_1000BASEX) { > > + phydev->interface = PHY_INTERFACE_MODE_1000BASEX; > > The speeds 10 and 100 seem odd here. 1000BaseX only supports 1G. It > would have to be SGMII in order to also support 10Mbps and 100Mbps. > Plus you are not listing 10 and 100 as a supported value. > > > +/* Returns negative on error, 0 if link is down, 1 if link is up */ > > +static int mv_read_status_1g(struct phy_device *phydev) > > +{ > > + int val, link = 0; > > + > > + val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_STAT); > > + if (val < 0) > > + return val; > > + > > + if (!(val & MDIO_STAT1_LSTATUS) || > > + (phydev->autoneg == AUTONEG_ENABLE && !(val & > > MDIO_AN_STAT1_COMPLETE))) > > + return 0; > > + > > + link = 1; > > + > > + if (phydev->autoneg == AUTONEG_DISABLE) { > > + phydev->speed = SPEED_1000; > > + phydev->duplex = DUPLEX_FULL; > > + > > + return link; > > + } > > + > > + val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_PHY_STAT); > > + if (val < 0) > > + return val; > > + > > + if (val & MV_1GBX_PHY_STAT_AN_RESOLVED) { > > + if (val & MV_1GBX_PHY_STAT_DUPLEX) > > + phydev->duplex = DUPLEX_FULL; > > + else > > + phydev->duplex = DUPLEX_HALF; > > + > > + if (val & MV_1GBX_PHY_STAT_SPEED1000) > > + phydev->speed = SPEED_1000; > > + else if (val & MV_1GBX_PHY_STAT_SPEED100) > > + phydev->speed = SPEED_100; > > + else > > + phydev->speed = SPEED_10; > > Are you sure it is not doing SGMII? Maybe it can do both, 1000BaseX > and SGMII? You would generally use 1000BaseX to connect to a fibre > SFP, and SGMII to connect to a copper SFP. So ideally you want to be > able to swap between these modes as needed. > > > +static int mv_read_status(struct phy_device *phydev) > > +{ > > + int link; > > + > > + linkmode_zero(phydev->lp_advertising); > > + phydev->pause = 0; > > + phydev->asym_pause = 0; > > + > > + switch (phydev->interface) { > > + case PHY_INTERFACE_MODE_10GBASER: > > + link = mv_read_status_10g(phydev); > > + break; > > + case PHY_INTERFACE_MODE_1000BASEX: > > + default: > > + link = mv_read_status_1g(phydev); > > + break; > > + } > > + > > + if (link < 0) > > + return link; > > + > > + phydev->link = link; > > + > > + if (phydev->link) > > + mv_link_led_on(phydev); > > + else > > + mv_link_led_off(phydev); > > You have to manually control the LED? That is odd for a PHY. Normally > you just select a mode and it will do it all in hardware. > > Andrew Thanks for the review, Andrew, your remarks are all valid. I'll implement 1000Base-X/SGMII swapping. As for the LED, I'll just drop it for now, as it is not essential. I'll commit LEDs config when core funtionality will be accepted.
[PATCH] net: phy: add Marvell 88X2222 transceiver support
Add basic support for the Marvell 88X multi-speed ethernet transceiver. This PHY provides data transmission over fiber-optic as well as Twinax copper links. The 88X supports 2 ports of 10GBase-R and 1000Base-X on the line-side interface. The host-side interface supports 4 ports of 10GBase-R, RXAUI, 1000Base-X and 2 ports of XAUI. This driver, however, supports only XAUI on the host-side and 1000Base-X/10GBase-R on the line-side, for now. Interrupts are not supported also. Internal registers access compliant with the Clause 45 specification. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/Kconfig | 6 + drivers/net/phy/Makefile | 1 + drivers/net/phy/marvell-88x.c | 480 ++ include/linux/marvell_phy.h | 1 + 4 files changed, 488 insertions(+) create mode 100644 drivers/net/phy/marvell-88x.c diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 698bea312adc..a615b3660b05 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -201,6 +201,12 @@ config MARVELL_10G_PHY help Support for the Marvell Alaska MV88X3310 and compatible PHYs. +config MARVELL_88X_PHY + tristate "Marvell 88X PHY" + help + Support for the Marvell 88X Dual-port Multi-speed Ethernet + Transceiver. + config MICREL_PHY tristate "Micrel PHYs" help diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index a13e402074cf..de683e3abe63 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o obj-$(CONFIG_MARVELL_PHY) += marvell.o +obj-$(CONFIG_MARVELL_88X_PHY) += marvell-88x.o obj-$(CONFIG_MESON_GXL_PHY)+= meson-gxl.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o obj-$(CONFIG_MICREL_PHY) += micrel.o diff --git a/drivers/net/phy/marvell-88x.c b/drivers/net/phy/marvell-88x.c new file mode 100644 index ..e2c55db4769f --- /dev/null +++ b/drivers/net/phy/marvell-88x.c @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Marvell 88x dual-port multi-speed ethernet transceiver. + * + * Supports: + * XAUI on the host side. + * 1000Base-X or 10GBase-R on the line side. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Port PCS Configuration */ +#defineMV_PCS_CONFIG 0xF002 +#defineMV_PCS_HOST_XAUI0x73 +#defineMV_PCS_LINE_10GBR (0x71 << 8) +#defineMV_PCS_LINE_1GBX_AN (0x7B << 8) + +/* Port Reset and Power Down */ +#defineMV_PORT_RST 0xF003 +#defineMV_LINE_RST_SW BIT(15) +#defineMV_HOST_RST_SW BIT(7) +#defineMV_PORT_RST_SW (MV_LINE_RST_SW | MV_HOST_RST_SW) + +/* LED0 Control */ +#defineMV_LED0_CTRL0xF020 +#defineMV_LED0_SOLID_MASK (0xf << 4) +#defineMV_LED0_SOLID_OFF (0x0 << 4) +#defineMV_LED0_SOLID_ON(0x7 << 4) + +/* PMD Transmit Disable */ +#defineMV_TX_DISABLE 0x0009 +#defineMV_TX_DISABLE_GLOBALBIT(0) + +/* 10GBASE-R PCS Status 1 */ +#defineMV_10GBR_STAT MDIO_STAT1 + +/* 10GBASE-R PCS Real Time Status Register */ +#defineMV_10GBR_STAT_RT0x8002 + +/* 1000Base-X/SGMII Control Register */ +#defineMV_1GBX_CTRL0x2000 + +/* 1000BASE-X/SGMII Status Register */ +#defineMV_1GBX_STAT0x2001 + +/* 1000Base-X Auto-Negotiation Advertisement Register */ +#defineMV_1GBX_ADVERTISE 0x2004 + +/* 1000Base-X PHY Specific Status Register */ +#defineMV_1GBX_PHY_STAT0xA003 +#defineMV_1GBX_PHY_STAT_LSTATUS_RT BIT(10) +#defineMV_1GBX_PHY_STAT_AN_RESOLVEDBIT(11) +#defineMV_1GBX_PHY_STAT_DUPLEX BIT(13) +#defineMV_1GBX_PHY_STAT_SPEED100 BIT(14) +#defineMV_1GBX_PHY_STAT_SPEED1000 BIT(15) + +struct mv_data { + bool sfp_inserted; + bool net_up; +}; + +/* SFI PMA transmit enable */ +static void mv_tx_enable(struct phy_device *phydev) +{ + phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MV_TX_DISABLE, + MV_TX_DISABLE_GLOBAL); +} + +/* SFI PMA transmit disable */ +static void mv_tx_disable(struct phy_device *phydev) +{ + phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MV_TX_DISABLE, +MV_TX_DISABLE_GLOBAL); +} + +static void mv_link_led_on(struct phy_device *phydev) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_LED0_CTRL, MV_LED0_SOLID_MASK, + MV_LED0_SOLID_ON); +} + +static void mv_link_led_off(struct phy_device *phydev) +{ + p
[PATCH] staging:r8188eu: replace enum WIFI_STATUS_CODE with native kernel definitions
Driver and kernel definitions are equal. Avoid code duplication, improve readability. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 44 +-- drivers/staging/rtl8188eu/include/wifi.h | 14 -- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 8794907a39f4..ebd9b96a8211 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -779,7 +779,7 @@ static void issue_auth(struct adapter *padapter, struct sta_info *psta, /* setting auth algo number */ val16 = (u16)psta->authalg; - if (status != _STATS_SUCCESSFUL_) + if (status != WLAN_STATUS_SUCCESS) val16 = 0; if (val16) { @@ -2675,13 +2675,13 @@ static unsigned int OnAuth(struct adapter *padapter, DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n", algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - status = _STATS_NO_SUPP_ALG_; + status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; goto auth_fail; } if (!rtw_access_ctrl(padapter, sa)) { - status = _STATS_UNABLE_HANDLE_STA_; + status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; goto auth_fail; } @@ -2692,7 +2692,7 @@ static unsigned int OnAuth(struct adapter *padapter, pstat = rtw_alloc_stainfo(pstapriv, sa); if (!pstat) { DBG_88E(" Exceed the upper limit of supported clients...\n"); - status = _STATS_UNABLE_HANDLE_STA_; + status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; goto auth_fail; } @@ -2724,7 +2724,7 @@ static unsigned int OnAuth(struct adapter *padapter, if ((pstat->auth_seq + 1) != seq) { DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", seq, pstat->auth_seq + 1); - status = _STATS_OUT_OF_AUTH_SEQ_; + status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; goto auth_fail; } @@ -2737,7 +2737,7 @@ static unsigned int OnAuth(struct adapter *padapter, } else { DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", seq, pstat->auth_seq + 1); - status = _STATS_OUT_OF_AUTH_SEQ_; + status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; goto auth_fail; } } else { /* shared system or auto authentication */ @@ -2757,7 +2757,7 @@ static unsigned int OnAuth(struct adapter *padapter, if (!p || ie_len <= 0) { DBG_88E("auth rejected because challenge failure!(1)\n"); - status = _STATS_CHALLENGE_FAIL_; + status = WLAN_STATUS_CHALLENGE_FAIL; goto auth_fail; } @@ -2768,13 +2768,13 @@ static unsigned int OnAuth(struct adapter *padapter, pstat->expire_to = pstapriv->assoc_to; } else { DBG_88E("auth rejected because challenge failure!\n"); - status = _STATS_CHALLENGE_FAIL_; + status = WLAN_STATUS_CHALLENGE_FAIL; goto auth_fail; } } else { DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", seq, pstat->auth_seq + 1); - status = _STATS_OUT_OF_AUTH_SEQ_; + status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; goto auth_fail; } } @@ -2782,7 +2782,7 @@ static unsigned int OnAuth(struct adapter *padapter, /* Now, we are going to issue_auth... */ pstat->auth_seq = seq + 1; - issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_)); + issue_auth(padapter, pstat, (unsigned short)(WLAN_STATUS_SUCCESS)); if (pstat->state & WIFI_FW_AUTH_SUCCESS) pstat->auth_seq = 0; @@ -2892,7 +2892,7 @@ static unsigned int OnAssocReq(struct adapter *padapter, int i, wpa_ie_len, left; unsigned char supportRate[16]; int supportRateNum; - unsigned short status = _STATS_SUCCESSFUL_; + unsigned short status = WLAN_STATUS_SUCCESS;
[PATCH] staging:rtl8712: remove unused enum WIFI_STATUS_CODE
Improve readability. Signed-off-by: Ivan Safonov --- drivers/staging/rtl8712/wifi.h | 14 -- 1 file changed, 14 deletions(-) diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h index 601d4ff607bc..1b32b3510093 100644 --- a/drivers/staging/rtl8712/wifi.h +++ b/drivers/staging/rtl8712/wifi.h @@ -101,20 +101,6 @@ enum WIFI_REASON_CODE { _RSON_PMK_NOT_AVAILABLE_= 24, }; -enum WIFI_STATUS_CODE { - _STATS_SUCCESSFUL_ = 0, - _STATS_FAILURE_ = 1, - _STATS_CAP_FAIL_= 10, - _STATS_NO_ASOC_ = 11, - _STATS_OTHER_ = 12, - _STATS_NO_SUPP_ALG_ = 13, - _STATS_OUT_OF_AUTH_SEQ_ = 14, - _STATS_CHALLENGE_FAIL_ = 15, - _STATS_AUTH_TIMEOUT_= 16, - _STATS_UNABLE_HANDLE_STA_ = 17, - _STATS_RATE_FAIL_ = 18, -}; - enum WIFI_REG_DOMAIN { DOMAIN_FCC = 1, DOMAIN_IC = 2, -- 2.26.2
BUG: KASAN: stack-out-of-bounds in unwind_next_frame+0x1df5/0x2650
Hello, We've noticed the following regression in Linux 5.10 branch: [ 128.367231][C0] == [ 128.368523][C0] BUG: KASAN: stack-out-of-bounds in unwind_next_frame (arch/x86/kernel/unwind_orc.c:371 arch/x86/kernel/unwind_orc.c:544) [ 128.369744][C0] Read of size 8 at addr 88802fceede0 by task kworker/u2:2/591 [ 128.370916][C0] [ 128.371269][C0] CPU: 0 PID: 591 Comm: kworker/u2:2 Not tainted 5.10.11-cloudflare-kasan-2021.1.15 #1 [ 128.372626][C0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 [ 128.374346][C0] Workqueue: writeback wb_workfn (flush-254:0) [ 128.375275][C0] Call Trace: [ 128.375763][C0] [ 128.376221][C0] dump_stack+0x7d/0xa3 [ 128.376843][C0] print_address_description.constprop.0+0x1c/0x210 [ 128.377827][C0] ? _raw_spin_lock_irqsave (arch/x86/include/asm/atomic.h:202 include/asm-generic/atomic-instrumented.h:707 include/asm-generic/qspinlock.h:82 include/linux/spinlock.h:195 include/linux/spinlock_api_smp.h:119 kernel/locking/spinlock.c:159) [ 128.378624][C0] ? _raw_write_unlock_bh (kernel/locking/spinlock.c:158) [ 128.379389][C0] ? unwind_next_frame (arch/x86/kernel/unwind_orc.c:444) [ 128.380177][C0] ? unwind_next_frame (arch/x86/kernel/unwind_orc.c:371 arch/x86/kernel/unwind_orc.c:544) [ 128.380954][C0] ? unwind_next_frame (arch/x86/kernel/unwind_orc.c:371 arch/x86/kernel/unwind_orc.c:544) [ 128.381736][C0] kasan_report.cold+0x1f/0x37 [ 128.382438][C0] ? unwind_next_frame (arch/x86/kernel/unwind_orc.c:371 arch/x86/kernel/unwind_orc.c:544) [ 128.383192][C0] unwind_next_frame+0x1df5/0x2650 [ 128.383954][C0] ? asm_common_interrupt (arch/x86/include/asm/idtentry.h:622) [ 128.384726][C0] ? get_stack_info_noinstr (arch/x86/kernel/dumpstack_64.c:157) [ 128.385530][C0] ? glue_xts_req_128bit+0x110/0x6f0 glue_helper [ 128.386509][C0] ? deref_stack_reg (arch/x86/kernel/unwind_orc.c:418) [ 128.387267][C0] ? is_module_text_address (kernel/module.c:4566 kernel/module.c:4550) [ 128.388077][C0] ? glue_xts_req_128bit+0x110/0x6f0 glue_helper [ 128.389048][C0] ? kernel_text_address.part.0 (kernel/extable.c:145) [ 128.389901][C0] ? glue_xts_req_128bit+0x110/0x6f0 glue_helper [ 128.390865][C0] ? stack_trace_save (kernel/stacktrace.c:82) [ 128.391550][C0] arch_stack_walk+0x8d/0xf0 [ 128.392216][C0] ? kfree (mm/slub.c:3142 mm/slub.c:4124) [ 128.392807][C0] stack_trace_save+0x96/0xd0 [ 128.393535][C0] ? create_prof_cpu_mask (kernel/stacktrace.c:113) [ 128.394320][C0] ? blk_update_request (block/blk-core.c:264 block/blk-core.c:1468) [ 128.395113][C0] ? asm_call_irq_on_stack (arch/x86/entry/entry_64.S:796) [ 128.395887][C0] ? do_softirq_own_stack (arch/x86/include/asm/irq_stack.h:27 arch/x86/include/asm/irq_stack.h:77 arch/x86/kernel/irq_64.c:77) [ 128.396678][C0] ? irq_exit_rcu (kernel/softirq.c:393 kernel/softirq.c:423 kernel/softirq.c:435) [ 128.397349][C0] ? common_interrupt (arch/x86/kernel/irq.c:239) [ 128.398086][C0] ? asm_common_interrupt (arch/x86/include/asm/idtentry.h:622) [ 128.398886][C0] ? get_page_from_freelist (mm/page_alloc.c:3480 mm/page_alloc.c:3904) [ 128.399759][C0] kasan_save_stack+0x20/0x50 [ 128.400453][C0] ? kasan_save_stack (mm/kasan/common.c:48) [ 128.401175][C0] ? kasan_set_track (mm/kasan/common.c:56) [ 128.401881][C0] ? kasan_set_free_info (mm/kasan/generic.c:360) [ 128.402646][C0] ? __kasan_slab_free (mm/kasan/common.c:283 mm/kasan/common.c:424) [ 128.403375][C0] ? slab_free_freelist_hook (mm/slub.c:1577) [ 128.404199][C0] ? kfree (mm/slub.c:3142 mm/slub.c:4124) [ 128.404835][C0] ? nvme_pci_complete_rq+0x105/0x350 nvme [ 128.405765][C0] ? blk_done_softirq (include/linux/list.h:282 block/blk-mq.c:581) [ 128.406552][C0] ? __do_softirq (arch/x86/include/asm/jump_label.h:25 include/linux/jump_label.h:200 include/trace/events/irq.h:142 kernel/softirq.c:299) [ 128.407272][C0] ? asm_call_irq_on_stack (arch/x86/entry/entry_64.S:796) [ 128.408087][C0] ? do_softirq_own_stack (arch/x86/include/asm/irq_stack.h:27 arch/x86/include/asm/irq_stack.h:77 arch/x86/kernel/irq_64.c:77) [ 128.408878][C0] ? irq_exit_rcu (kernel/softirq.c:393 kernel/softirq.c:423 kernel/softirq.c:435) [ 128.409602][C0] ? common_interrupt (arch/x86/kernel/irq.c:239) [ 128.410366][C0] ? asm_common_interrupt (arch/x86/include/asm/idtentry.h:622) [ 128.411184][C0] ? skcipher_walk_next (crypto/skcipher.c:322 crypto/skcipher.c:384) [ 128.412009][C0] ? skcipher_walk_virt (crypto/skcipher.c:487) [ 128.412811][C0] ? glue_xts_req_128bit+0x110/0x6f0 glue_helper [ 128.413792][C0] ? asm_common_interrupt (arch/x86/include/asm/idtentry.h:622) [ 128.414562][C0] ? kcry
[PATCH] w1: w1_therm: Fix conversion result for negative temperatures
DS18B20 device driver returns an incorrect value for negative temperatures due to a missing sign-extension in w1_DS18B20_convert_temp(). Fix by using s16 temperature value when converting to int. Fixes: 9ace0b4dab1c (w1: w1_therm: Add support for GXCAS GX20MH01 device.) Reported-by: Paweł Marciniak Signed-off-by: Ivan Zaentsev --- drivers/w1/slaves/w1_therm.c | 22 +- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 3712b1e6dc71..976eea28f268 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -667,28 +667,24 @@ static inline int w1_DS18B20_get_resolution(struct w1_slave *sl) */ static inline int w1_DS18B20_convert_temp(u8 rom[9]) { - int t; - u32 bv; + u16 bv; + s16 t; + + /* Signed 16-bit value to unsigned, cpu order */ + bv = le16_to_cpup((__le16 *)rom); /* Config register bit R2 = 1 - GX20MH01 in 13 or 14 bit resolution mode */ if (rom[4] & 0x80) { - /* Signed 16-bit value to unsigned, cpu order */ - bv = le16_to_cpup((__le16 *)rom); - /* Insert two temperature bits from config register */ /* Avoid arithmetic shift of signed value */ bv = (bv << 2) | (rom[4] & 3); - - t = (int) sign_extend32(bv, 17); /* Degrees, lowest bit is 2^-6 */ - return (t*1000)/64; /* Millidegrees */ + t = (s16) bv; /* Degrees, lowest bit is 2^-6 */ + return (int)t * 1000 / 64; /* Sign-extend to int; millidegrees */ } - - t = (int)le16_to_cpup((__le16 *)rom); - return t*1000/16; + t = (s16)bv;/* Degrees, lowest bit is 2^-4 */ + return (int)t * 1000 / 16; /* Sign-extend to int; millidegrees */ } - - /** * w1_DS18S20_convert_temp() - temperature computation for DS18S20 * @rom: data read from device RAM (8 data bytes + 1 CRC byte) -- 2.25.1
[PATCH net-next] sfc: reduce the number of requested xdp ev queues
Without this change the driver tries to allocate too many queues, breaching the number of available msi-x interrupts on machines with many logical cpus and default adapter settings: Insufficient resources for 12 XDP event queues (24 other channels, max 32) Which in turn triggers EINVAL on XDP processing: sfc :86:00.0 ext0: XDP TX failed (-22) Signed-off-by: Ivan Babrou --- drivers/net/ethernet/sfc/efx_channels.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx_channels.c b/drivers/net/ethernet/sfc/efx_channels.c index a4a626e9cd9a..1bfeee283ea9 100644 --- a/drivers/net/ethernet/sfc/efx_channels.c +++ b/drivers/net/ethernet/sfc/efx_channels.c @@ -17,6 +17,7 @@ #include "rx_common.h" #include "nic.h" #include "sriov.h" +#include "workarounds.h" /* This is the first interrupt mode to try out of: * 0 => MSI-X @@ -137,6 +138,7 @@ static int efx_allocate_msix_channels(struct efx_nic *efx, { unsigned int n_channels = parallelism; int vec_count; + int tx_per_ev; int n_xdp_tx; int n_xdp_ev; @@ -149,9 +151,9 @@ static int efx_allocate_msix_channels(struct efx_nic *efx, * multiple tx queues, assuming tx and ev queues are both * maximum size. */ - + tx_per_ev = EFX_MAX_EVQ_SIZE / EFX_TXQ_MAX_ENT(efx); n_xdp_tx = num_possible_cpus(); - n_xdp_ev = DIV_ROUND_UP(n_xdp_tx, EFX_MAX_TXQ_PER_CHANNEL); + n_xdp_ev = DIV_ROUND_UP(n_xdp_tx, tx_per_ev); vec_count = pci_msix_vec_count(efx->pci_dev); if (vec_count < 0) -- 2.29.2
Re: [PATCH net-next] sfc: reduce the number of requested xdp ev queues
On Thu, Dec 17, 2020 at 10:14 AM Jakub Kicinski wrote: > > On Mon, 14 Dec 2020 17:29:06 -0800 Ivan Babrou wrote: > > Without this change the driver tries to allocate too many queues, > > breaching the number of available msi-x interrupts on machines > > with many logical cpus and default adapter settings: > > > > Insufficient resources for 12 XDP event queues (24 other channels, max 32) > > > > Which in turn triggers EINVAL on XDP processing: > > > > sfc 0000:86:00.0 ext0: XDP TX failed (-22) > > > > Signed-off-by: Ivan Babrou > > Looks like the discussion may have concluded, but we don't take -next > patches during the merge window, so please repost when net-next reopens. > > Thanks! > -- > # Form letter - net-next is closed > > We have already sent the networking pull request for 5.11 and therefore > net-next is closed for new drivers, features, code refactoring and > optimizations. We are currently accepting bug fixes only. > > Please repost when net-next reopens after 5.11-rc1 is cut. Should I resend my patch now that the window is open or is bumping this thread enough? > Look out for the announcement on the mailing list or check: > http://vger.kernel.org/~davem/net-next.html > > RFC patches sent for review only are obviously welcome at any time.
[PATCH] HID: sony: Support for DS4 clones that do not implement feature report 0x81
There are clones of DualShock 4 that are very similar to the originals, except of 1) they do not support HID feature report 0x81 and 2) they do not have any USB Audio interfaces despite they physically have audio jack. Such controllers are working fine with Linux when connected via Bluetooth, but not when connected via USB. Here is how failed USB connection attempt looks in log: usb 1-5: New USB device found, idVendor=054c, idProduct=05c4, bcdDevice= 1.00 usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=0 usb 1-5: Product: Wireless Controller usb 1-5: Manufacturer: Sony Computer Entertainment sony 0003:054C:05C4.0007: failed to retrieve feature report 0x81 with the DualShock 4 MAC address sony 0003:054C:05C4.0007: hidraw6: USB HID v81.11 Gamepad [Sony Computer Entertainment Wireless Controller] on usb-:00:14.0-5/input0 sony 0003:054C:05C4.0007: failed to claim input This patch adds support of using feature report 0x12 as a fallback for Bluetooth MAC address retrieval. Feature report 0x12 also seems to be used by DS4Windows[1] for all DS4 controllers. [1] https://github.com/Ryochan7/DS4Windows/blob/1b74a4440089f38a24ee2c2483c1d733a0692b8f/DS4Windows/HidLibrary/HidDevice.cs#L479 Signed-off-by: Ivan Mironov --- drivers/hid/hid-sony.c | 72 ++ 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index e3a557dc9ffd..97df12180e45 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -491,6 +491,7 @@ struct motion_output_report_02 { #define DS4_FEATURE_REPORT_0x02_SIZE 37 #define DS4_FEATURE_REPORT_0x05_SIZE 41 +#define DS4_FEATURE_REPORT_0x12_SIZE 16 #define DS4_FEATURE_REPORT_0x81_SIZE 7 #define DS4_FEATURE_REPORT_0xA3_SIZE 49 #define DS4_INPUT_REPORT_0x11_SIZE 78 @@ -2593,6 +2594,53 @@ static int sony_get_bt_devaddr(struct sony_sc *sc) return 0; } +static int sony_get_usb_ds4_devaddr(struct sony_sc *sc) +{ + u8 *buf = NULL; + int ret; + + buf = kmalloc(max(DS4_FEATURE_REPORT_0x12_SIZE, DS4_FEATURE_REPORT_0x81_SIZE), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* +* The MAC address of a DS4 controller connected via USB can be +* retrieved with feature report 0x81. The address begins at +* offset 1. +*/ + ret = hid_hw_raw_request(sc->hdev, 0x81, buf, + DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); + if (ret == DS4_FEATURE_REPORT_0x81_SIZE) { + memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); + goto out_free; + } + dbg_hid("%s: hid_hw_raw_request(..., 0x81, ...) returned %d\n", __func__, ret); + + /* +* Some variants do not implement feature report 0x81 at all. +* Fortunately, feature report 0x12 also contains the MAC address of +* a controller. +*/ + ret = hid_hw_raw_request(sc->hdev, 0x12, buf, + DS4_FEATURE_REPORT_0x12_SIZE, HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); + if (ret == DS4_FEATURE_REPORT_0x12_SIZE) { + memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); + goto out_free; + } + dbg_hid("%s: hid_hw_raw_request(..., 0x12, ...) returned %d\n", __func__, ret); + + hid_err(sc->hdev, "failed to retrieve feature reports 0x81 and 0x12 with the DualShock 4 MAC address\n"); + ret = ret < 0 ? ret : -EINVAL; + +out_free: + + kfree(buf); + + return ret; +} + static int sony_check_add(struct sony_sc *sc) { u8 *buf = NULL; @@ -2613,26 +2661,9 @@ static int sony_check_add(struct sony_sc *sc) return 0; } } else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { - buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - /* -* The MAC address of a DS4 controller connected via USB can be -* retrieved with feature report 0x81. The address begins at -* offset 1. -*/ - ret = hid_hw_raw_request(sc->hdev, 0x81, buf, - DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT, - HID_REQ_GET_REPORT); - - if (ret != DS4_FEATURE_REPORT_0x81_SIZE) { - hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); - ret = ret < 0 ? ret : -EINVAL; - goto out_free; - } - - memcpy(sc->mac_address, &buf[1], sizeof(sc-
Re: [PATCH] cpupower: add Makefile dependencies for install targets
On Thu, Jan 7, 2021 at 12:59 PM Thomas Renninger wrote: > > Am Donnerstag, 7. Januar 2021, 18:42:25 CET schrieb Ivan Babrou: > > On Thu, Jan 7, 2021 at 2:07 AM Thomas Renninger wrote: > > > Am Dienstag, 5. Januar 2021, 00:57:18 CET schrieb Ivan Babrou: > > > > This allows building cpupower in parallel rather than serially. > > > > > > cpupower is built serially: > > > > > > [ make clean ] > > > > > > time make > > > real0m3,742s > > > user0m3,330s > > > sys 0m1,105s > > > > > > [ make clean ] > > > > > > time make -j10 > > > real0m1,045s > > > user0m3,153s > > > sys 0m1,037s > > > > > > Only advantage I see is that you can call > > > make install-xy > > > targets without calling the corresponding build target > > > make xy > > > similar to the general install target: > > > install: all install-lib ... > > > > > > Not sure anyone needs this and whether all targets > > > successfully work this way. > > > If you'd show a useful usecase example... > > > > We build a bunch of kernel related tools (perf, cpupower, bpftool, > > etc.) from our own top level Makefile, propagating parallelism > > downwards like one should. > I still do not understand why you do not simply build: > Also if I call this from /tools directory I get a quick build: > make -j20 cpupower > > Can you please show the make calls, ideally with a timing to better understand > and also to reproduce the advantages this patch introduces. > From what I can see, it only helps if one calls "sub-install" targets > directly? That's exactly what we do: make install directly: /linux-5.10.5$ make -C ./tools/power/cpupower DESTDIR=/tmp/cpupower install -j $(nproc) make: Entering directory '/state/home/ivan/linux-5.10.5/tools/power/cpupower' CC cpupower MSGFMT po/de.gmo MSGFMT po/fr.gmo MSGFMT po/it.gmo MSGFMT po/cs.gmo /usr/bin/install -c -d /tmp/cpupower/usr/lib64 MSGFMT po/pt.gmo /usr/bin/install -c -d /tmp/cpupower/usr/bin /usr/bin/install -c -m 644 -D man/cpupower.1 /tmp/cpupower/usr/man/man1/cpupower.1 /usr/bin/install -c -d /tmp/cpupower/usr/share/locale cp -fpR ./libcpupower.so* /tmp/cpupower/usr/lib64/ /usr/bin/install -c ./cpupower /tmp/cpupower/usr/bin /usr/bin/install -c -m 644 -D man/cpupower-frequency-set.1 /tmp/cpupower/usr/man/man1/cpupower-frequency-set.1 make[1]: Entering directory '/state/home/ivan/linux-5.10.5/tools/power/cpupower/bench' for HLANG in de fr it cs pt; do \ echo '/usr/bin/install -c -m 644 -D ./po/$HLANG.gmo /tmp/cpupower/usr/share/locale/$HLANG/LC_MESSAGES/cpupower.mo'; \ /usr/bin/install -c -m 644 -D ./po/$HLANG.gmo /tmp/cpupower/usr/share/locale/$HLANG/LC_MESSAGES/cpupower.mo; \ done; CC main.o /usr/bin/install -c -d /tmp/cpupower/usr/share/bash-completion/completions /usr/bin/install -c -m 644 -D ./po/$HLANG.gmo /tmp/cpupower/usr/share/locale/$HLANG/LC_MESSAGES/cpupower.mo CC parse.o /usr/bin/install -c -m 644 -D man/cpupower-frequency-info.1 /tmp/cpupower/usr/man/man1/cpupower-frequency-info.1 CC system.o /usr/bin/install: cannot stat './po/de.gmo'/usr/bin/install -c -d /tmp/cpupower/usr/include : No such file or directory make[1]: Entering directory '/state/home/ivan/linux-5.10.5/tools/power/cpupower/bench' mkdir -p /tmp/cpupower//usr/sbin /usr/bin/install -c -m 644 cpupower-completion.sh '/tmp/cpupower/usr/share/bash-completion/completions/cpupower' /usr/bin/install -c -m 644 -D ./po/$HLANG.gmo /tmp/cpupower/usr/share/locale/$HLANG/LC_MESSAGES/cpupower.mo CC benchmark.o /usr/bin/install -c -m 644 -D man/cpupower-idle-set.1 /tmp/cpupower/usr/man/man1/cpupower-idle-set.1 /usr/bin/install: cannot stat './po/fr.gmo': No such file or directory /usr/bin/install -c -m 644 -D ./po/$HLANG.gmo /tmp/cpupower/usr/share/locale/$HLANG/LC_MESSAGES/cpupower.mo mkdir -p /tmp/cpupower//usr/bin /usr/bin/install -c -m 644 lib/cpufreq.h /tmp/cpupower/usr/include/cpufreq.h /usr/bin/install -c -m 644 -D man/cpupower-idle-info.1 /tmp/cpupower/usr/man/man1/cpupower-idle-info.1 mkdir -p /tmp/cpupower//usr/share/doc/packages/cpupower /usr/bin/install -c -m 644 -D ./po/$HLANG.gmo /tmp/cpupower/usr/share/locale/$HLANG/LC_MESSAGES/cpupower.mo /usr/bin/install -c -m 644 lib/cpuidle.h /tmp/cpupower/usr/include/cpuidle.h mkdir -p /tmp/cpupower//etc/ /usr/bin/install -c -m 644 -D man/cpupower-set.1 /tmp/cpupower/usr/man/man1/cpupower-set.1 /usr/bin/install -c -m 644 -D ./po/$HLANG.gmo /tmp/cpupower/usr/share/locale/$HLANG/LC_MESSAGES/cpupower.mo install -m 755 .//cpufreq-bench /tmp/cpupower//usr/sbin/cpufreq-bench /usr/bin/install -c -m 644 -D man/cpupowe
Re: [PATCH] cpupower: add Makefile dependencies for install targets
On Thu, Jan 7, 2021 at 2:07 AM Thomas Renninger wrote: > > Am Dienstag, 5. Januar 2021, 00:57:18 CET schrieb Ivan Babrou: > > This allows building cpupower in parallel rather than serially. > > cpupower is built serially: > > [ make clean ] > > time make > real0m3,742s > user0m3,330s > sys 0m1,105s > > [ make clean ] > > time make -j10 > real0m1,045s > user0m3,153s > sys 0m1,037s > > Only advantage I see is that you can call > make install-xy > targets without calling the corresponding build target > make xy > similar to the general install target: > install: all install-lib ... > > Not sure anyone needs this and whether all targets > successfully work this way. > If you'd show a useful usecase example... We build a bunch of kernel related tools (perf, cpupower, bpftool, etc.) from our own top level Makefile, propagating parallelism downwards like one should. Without this patch we have to remove parallelism for cpupower, which doesn't seem like a very clean thing to do, especially if you consider that it's 3x faster with parallelism enabled in wall clock terms. >Thomas > > > > > Signed-off-by: Ivan Babrou > > --- > > tools/power/cpupower/Makefile | 8 > > tools/power/cpupower/bench/Makefile | 2 +- > > 2 files changed, 5 insertions(+), 5 deletions(-) > > > > diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile > > index c7bcddbd486d..3b1594447f29 100644 > > --- a/tools/power/cpupower/Makefile > > +++ b/tools/power/cpupower/Makefile > > @@ -270,14 +270,14 @@ clean: > > $(MAKE) -C bench O=$(OUTPUT) clean > > > > > > -install-lib: > > +install-lib: libcpupower > > $(INSTALL) -d $(DESTDIR)${libdir} > > $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/ > > $(INSTALL) -d $(DESTDIR)${includedir} > > $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h > > $(INSTALL_DATA) lib/cpuidle.h $(DESTDIR)${includedir}/cpuidle.h > > > > -install-tools: > > +install-tools: $(OUTPUT)cpupower > > $(INSTALL) -d $(DESTDIR)${bindir} > > $(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir} > > $(INSTALL) -d $(DESTDIR)${bash_completion_dir} > > @@ -293,14 +293,14 @@ install-man: > > $(INSTALL_DATA) -D man/cpupower-info.1 > > $(DESTDIR)${mandir}/man1/cpupower-info.1 $(INSTALL_DATA) -D > > man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1 > > > > -install-gmo: > > +install-gmo: create-gmo > > $(INSTALL) -d $(DESTDIR)${localedir} > > for HLANG in $(LANGUAGES); do \ > > echo '$(INSTALL_DATA) -D $(OUTPUT)po/$$HLANG.gmo > > $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \ $(INSTALL_DATA) > > -D $(OUTPUT)po/$$HLANG.gmo > > $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \ done; > > > > -install-bench: > > +install-bench: compile-bench > > @#DESTDIR must be set from outside to survive > > @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$ > (confdir) > > $(MAKE) -C bench O=$(OUTPUT) install > > > > diff --git a/tools/power/cpupower/bench/Makefile > > b/tools/power/cpupower/bench/Makefile index f68b4bc55273..d9d9923af85c > > 100644 > > --- a/tools/power/cpupower/bench/Makefile > > +++ b/tools/power/cpupower/bench/Makefile > > @@ -27,7 +27,7 @@ $(OUTPUT)cpufreq-bench: $(OBJS) > > > > all: $(OUTPUT)cpufreq-bench > > > > -install: > > +install: $(OUTPUT)cpufreq-bench > > mkdir -p $(DESTDIR)/$(sbindir) > > mkdir -p $(DESTDIR)/$(bindir) > > mkdir -p $(DESTDIR)/$(docdir) > > > >
[PATCH] cpupower: add Makefile dependencies for install targets
This allows building cpupower in parallel rather than serially. Signed-off-by: Ivan Babrou --- tools/power/cpupower/Makefile | 8 tools/power/cpupower/bench/Makefile | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index c7bcddbd486d..3b1594447f29 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -270,14 +270,14 @@ clean: $(MAKE) -C bench O=$(OUTPUT) clean -install-lib: +install-lib: libcpupower $(INSTALL) -d $(DESTDIR)${libdir} $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/ $(INSTALL) -d $(DESTDIR)${includedir} $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h $(INSTALL_DATA) lib/cpuidle.h $(DESTDIR)${includedir}/cpuidle.h -install-tools: +install-tools: $(OUTPUT)cpupower $(INSTALL) -d $(DESTDIR)${bindir} $(INSTALL_PROGRAM) $(OUTPUT)cpupower $(DESTDIR)${bindir} $(INSTALL) -d $(DESTDIR)${bash_completion_dir} @@ -293,14 +293,14 @@ install-man: $(INSTALL_DATA) -D man/cpupower-info.1 $(DESTDIR)${mandir}/man1/cpupower-info.1 $(INSTALL_DATA) -D man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1 -install-gmo: +install-gmo: create-gmo $(INSTALL) -d $(DESTDIR)${localedir} for HLANG in $(LANGUAGES); do \ echo '$(INSTALL_DATA) -D $(OUTPUT)po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \ $(INSTALL_DATA) -D $(OUTPUT)po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \ done; -install-bench: +install-bench: compile-bench @#DESTDIR must be set from outside to survive @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT) install diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile index f68b4bc55273..d9d9923af85c 100644 --- a/tools/power/cpupower/bench/Makefile +++ b/tools/power/cpupower/bench/Makefile @@ -27,7 +27,7 @@ $(OUTPUT)cpufreq-bench: $(OBJS) all: $(OUTPUT)cpufreq-bench -install: +install: $(OUTPUT)cpufreq-bench mkdir -p $(DESTDIR)/$(sbindir) mkdir -p $(DESTDIR)/$(bindir) mkdir -p $(DESTDIR)/$(docdir) -- 2.29.2
[PATCH] tty: serial: amba-pl011: added RS485 support [v3]
AMBA PL011 do not have hardware support for RS485. This implementation is for drive enable signal (DE), which switch direction of RS485 driver chip. This signal si drived by RTS pin. Correct multiplexor settings have to be provided to Device Tree. Usually it is 'ctsrts', which is used for enabling of HW flow control, too. DE signal is switched by starting transmition from serial core and data transfer is initiated by first hrtimer if there is delay before send enabled. There is missing FIFO empty interrupt in PL011. It is replaced by second hrtimer which is started if there are no more data in port transmit buffer. Notice that port transmit buffer is not the same as HW TX FIFO. Time of this timmer is set to char send time and it is running until fifo is empty. This kind of implementation cause that there can be unwanted delay of one timer tick before DE signal is switched. This is used to prevent data loss during transmit. Second timer can start first if there is delay after send enabled. Signed-off-by: Ivan Sistik --- Notes: This patch is ported and corrected version of my previous patches which can be reviewed here: https://lore.kernel.org/lkml/20200106235203.27256-1-sis...@3ksolutions.sk/ and here: https://lore.kernel.org/lkml/20201228164108.16508-1-sis...@3ksolutions.sk/ I have been waiting for some time to see if Lukas Wunner will create patch with his own solution. Now I am successfully running my imeplementation for almost one year in production environment. It is running 24/7 on Raspberry PI 4B which is used as modbus master. There are no problems with it. I have made corrections to patch according to notes from Greg Kroah-Hartman and Stefan Wahren . drivers/tty/serial/Kconfig | 11 + drivers/tty/serial/amba-pl011.c | 463 +++- 2 files changed, 471 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index a9751a83d..26dddab0c 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -75,6 +75,17 @@ config SERIAL_AMBA_PL011_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_AMBA_PL011_SOFT_RS485 + bool "RS485 software direction switching for ARM AMBA PL011 serial" + depends on SERIAL_AMBA_PL011=y + help + Enable RS485 software direction switching of driver enable (RTS pin) + for ARM AMBA PL011 serial. AMBA PL011 does not have HW support for + RS485. This driver use 2 hrtimers. One is used for rs485 delays. + Second one is used for polling of TX FIFO. There is not TX FIFO + empty interrupt in PL011. Secondary timer is started by empty + transmit buffer. + config SERIAL_EARLYCON_ARM_SEMIHOST bool "Early console using ARM semihosting" depends on ARM64 || ARM diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 16720c97a..6a40e5bc5 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "amba-pl011.h" @@ -60,6 +61,18 @@ #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) #define UART_DUMMY_DR_RX (1 << 16) +#ifdef CONFIG_SERIAL_AMBA_PL011_SOFT_RS485 +/* + * Enum with current status + */ +enum rs485_status { + rs485_receiving, + rs485_delay_before_send, + rs485_sending, + rs485_delay_after_send +}; +#endif + static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { [REG_DR] = UART01x_DR, [REG_FR] = UART01x_FR, @@ -270,6 +283,16 @@ struct uart_amba_port { unsigned intold_cr; /* state during shutdown */ unsigned intfixed_baud; /* vendor-set fixed baud rate */ chartype[12]; + +#ifdef CONFIG_SERIAL_AMBA_PL011_SOFT_RS485 + enum rs485_status rs485_current_status; /* status used for RTS */ + enum rs485_status rs485_next_status; /* this status after tick */ + struct hrtimer rs485_delay_timer; + struct hrtimer rs485_tx_empty_poll_timer; + unsigned long send_char_time; /* send char (nanoseconds) */ + boolrs485_last_char_sending; +#endif + #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ boolusing_tx_dma; @@ -306,6 +329,36 @@ static void pl011_write(unsigned int val, const struct uart_amba_port *uap, writew_relaxed(val, addr); } +#ifdef CONFIG_SERIAL_AMBA_PL011_SOFT_RS485 + +static void pl011_rs485_start_rts_delay(struct uart_amba_port *uap); + +static void rs485_set_rts_signal(struct uart_amba_port *uap, bool value) +{ + unsigned int rts_temp_cr; + + rts_temp_cr = pl011_read(uap, REG_CR); + +
[PATCH] tty: serial: amba-pl011: added RS485 support v2
AMBA PL011 do not have hardware support for RS485. This implementation is for drive enable signal (DE), which switch direction of RS485 driver chip. This signal si drived by RTS pin. Correct multiplexor settings have to be provided to Device Tree. Usually it is 'ctsrts', which is used for enabling of HW flow control, too. DE signal is switched by starting transmition from serial core and data transfer is initiated by first hrtimer if there is delay before send enabled. There is missing FIFO empty interrupt in PL011. It is replaced by second hrtimer which is started if there are no more data in port transmit buffer. Notice that port transmit buffer is not the same as HW TX FIFO. Time of this timmer is set to char send time and it is running until fifo is empty. This kind of implementation cause that there can be unwanted delay of one timer tick before DE signal is switched. This is used to prevent data loss during transmit. Second timer can start first if there is delay after send enabled. Signed-off-by: Ivan Sistik --- Notes: This patch is ported and corrected version of my previous patch which can be reviewed here: https://lore.kernel.org/lkml/20200106235203.27256-1-sis...@3ksolutions.sk/ I have been waiting for some time to see if Lukas Wunner will create patch with his own solution. Now I am successfully running my imeplementation for almost one year in production environment. There are no problems with it. I have made corrections to patch according to notes from Greg Kroah-Hartman . arch/arm/configs/bcm2835_defconfig | 1 + drivers/tty/serial/Kconfig | 11 + drivers/tty/serial/amba-pl011.c| 474 - 3 files changed, 483 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig index 519ff58e6..c2f630937 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig @@ -86,6 +86,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_BCM2835AUX=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011_SOFT_RS485=y CONFIG_SERIAL_DEV_BUS=y CONFIG_TTY_PRINTK=y CONFIG_I2C_CHARDEV=y diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index a9751a83d..c33461511 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -75,6 +75,17 @@ config SERIAL_AMBA_PL011_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_AMBA_PL011_SOFT_RS485 + bool "RS485 software direction switching for ARM AMBA PL011 serial" + depends on SERIAL_AMBA_PL011=y + help + Enable RS485 software direction switching of driver enable (RTS pin) + for ARM AMBA PL011 serial. AMBA PL011 does not have HW support for + RS485. This driver use 2 hrtimers. One is used for rs485 delays. + Secon one is used for polling of TX FIFO. There is not TX FIFO + empty interrupt in PL011. Secondary timer is started by empty + transmit buffer. + config SERIAL_EARLYCON_ARM_SEMIHOST bool "Early console using ARM semihosting" depends on ARM64 || ARM diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 16720c97a..f45b9042b 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "amba-pl011.h" @@ -60,6 +61,18 @@ #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) #define UART_DUMMY_DR_RX (1 << 16) +#ifdef CONFIG_SERIAL_AMBA_PL011_SOFT_RS485 +/* + * Enum with current status + */ +enum rs485_status { + rs485_receiving, + rs485_delay_before_send, + rs485_sending, + rs485_delay_after_send +}; +#endif + static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { [REG_DR] = UART01x_DR, [REG_FR] = UART01x_FR, @@ -270,6 +283,16 @@ struct uart_amba_port { unsigned intold_cr; /* state during shutdown */ unsigned intfixed_baud; /* vendor-set fixed baud rate */ chartype[12]; + +#ifdef CONFIG_SERIAL_AMBA_PL011_SOFT_RS485 + enum rs485_status rs485_current_status; /* status used for RTS */ + enum rs485_status rs485_next_status; /* this status after tick */ + struct hrtimer rs485_delay_timer; + struct hrtimer rs485_tx_empty_poll_timer; + unsigned long send_char_time; /* send char (nanoseconds) */ + boolrs485_last_char_sending; +#endif + #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ boolusing_tx_dma; @@ -280,6 +303,25 @@ struct uart_amba_port { #endif }; +#ifdef CONFIG_SERIAL_AMBA_PL011_SOFT_RS485 + +
[PATCH 0/1] media: hdmi: cec: replace broken link to HDMI specs
Hi, It's my first patch. I read a lot of materials on this topic, and tried hard to do things by the books. If, after all that trouble, I still managed to mess up, please let me know in the least polite way possible. ivan tkachenko (1): media: hdmi: cec: replace broken link to HDMI specs Documentation/driver-api/media/cec-core.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.29.2
[PATCH 1/1] media: hdmi: cec: replace broken link to HDMI specs
Current link died, according to Wayback Machine, back in 2017. And the website is completely down since 2019. Moreover, there was a custom cover on that PDF, i.e. it was modified. According to HDMI licence agreement (LA), HDMI specification and technical information are supposed to be hosted on www.hdmi.org exclusively, and not redistributed by third-parties. Sure, there are still many more or less reliable "mirrors" out there with a direct download straight from a search engine's page. However, for example, from FPGA4fun[1] website it was removed "per HDMI LA request". Unfortunately, the official download page is protected by email CAPTCHA, but that seems to be the only legit way to obtain a copy. [1] https://www.fpga4fun.com/HDMI.html Signed-off-by: ivan tkachenko --- Documentation/driver-api/media/cec-core.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/driver-api/media/cec-core.rst b/Documentation/driver-api/media/cec-core.rst index bc42982ac21e..eede201caa21 100644 --- a/Documentation/driver-api/media/cec-core.rst +++ b/Documentation/driver-api/media/cec-core.rst @@ -26,7 +26,7 @@ It is documented in the HDMI 1.4 specification with the new 2.0 bits documented in the HDMI 2.0 specification. But for most of the features the freely available HDMI 1.3a specification is sufficient: -http://www.microprocessor.org/HDMISpecification13a.pdf +https://www.hdmi.org/spec/index CEC Adapter Interface -- 2.29.2
[PATCH] tty: serial: amba-pl011: added RS485 support
This patch is ported and corrected version of my previous patch which can be reviewed here: https://lore.kernel.org/lkml/20200106235203.27256-1-sis...@3ksolutions.sk/ I have been waiting for some time to see if Lukas Wunner will create patch with his own solution. Now I am successfully running my imeplementation for almost one year in production environment. There are no problems with it. I have made corrections to patch according to notes from Greg Kroah-Hartman . Patch content: AMBA PL011 do not have hardware support for RS485. This implementation is for drive enable signal (DE), which switch direction of RS485 driver chip. This signal si drived by RTS pin. Correct multiplexor settings have to be provided to Device Tree. Usually it is 'ctsrts', which is used for enabling of HW flow control, too. DE signal is switched by starting transmition from serial core and data transfer is initiated by first hrtimer if there is delay before send enabled. There is missing FIFO empty interrupt in PL011. It is replaced by second hrtimer which is started if there are no more data in port transmit buffer. Notice that port transmit buffer is not the same as HW TX FIFO. Time of this timmer is set to char send time and it is running until fifo is empty. This kind of implementation cause that there can be unwanted delay of one timer tick before DE signal is switched. This is used to prevent data loss during transmit. Second timer can start first if there is delay after send enabled. Signed-off-by: Ivan Sistik --- arch/arm/configs/bcm2835_defconfig | 1 + drivers/tty/serial/Kconfig | 11 + drivers/tty/serial/amba-pl011.c| 474 - 3 files changed, 483 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig index 519ff58e6..c2f630937 100644 --- a/arch/arm/configs/bcm2835_defconfig +++ b/arch/arm/configs/bcm2835_defconfig @@ -86,6 +86,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_8250_BCM2835AUX=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_AMBA_PL011_SOFT_RS485=y CONFIG_SERIAL_DEV_BUS=y CONFIG_TTY_PRINTK=y CONFIG_I2C_CHARDEV=y diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index a9751a83d..c33461511 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -75,6 +75,17 @@ config SERIAL_AMBA_PL011_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_AMBA_PL011_SOFT_RS485 + bool "RS485 software direction switching for ARM AMBA PL011 serial" + depends on SERIAL_AMBA_PL011=y + help + Enable RS485 software direction switching of driver enable (RTS pin) + for ARM AMBA PL011 serial. AMBA PL011 does not have HW support for + RS485. This driver use 2 hrtimers. One is used for rs485 delays. + Secon one is used for polling of TX FIFO. There is not TX FIFO + empty interrupt in PL011. Secondary timer is started by empty + transmit buffer. + config SERIAL_EARLYCON_ARM_SEMIHOST bool "Early console using ARM semihosting" depends on ARM64 || ARM diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 16720c97a..f45b9042b 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "amba-pl011.h" @@ -60,6 +61,18 @@ #define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE) #define UART_DUMMY_DR_RX (1 << 16) +#ifdef CONFIG_SERIAL_AMBA_PL011_SOFT_RS485 +/* + * Enum with current status + */ +enum rs485_status { + rs485_receiving, + rs485_delay_before_send, + rs485_sending, + rs485_delay_after_send +}; +#endif + static u16 pl011_std_offsets[REG_ARRAY_SIZE] = { [REG_DR] = UART01x_DR, [REG_FR] = UART01x_FR, @@ -270,6 +283,16 @@ struct uart_amba_port { unsigned intold_cr; /* state during shutdown */ unsigned intfixed_baud; /* vendor-set fixed baud rate */ chartype[12]; + +#ifdef CONFIG_SERIAL_AMBA_PL011_SOFT_RS485 + enum rs485_status rs485_current_status; /* status used for RTS */ + enum rs485_status rs485_next_status; /* this status after tick */ + struct hrtimer rs485_delay_timer; + struct hrtimer rs485_tx_empty_poll_timer; + unsigned long send_char_time; /* send char (nanoseconds) */ + boolrs485_last_char_sending; +#endif + #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ boolusing_tx_dma; @@ -280,6 +303,25 @@ struct uart_amba_port { #endif }; +#ifdef CONFIG_SERIAL_AMBA_PL011_SOFT_RS485 + +static void pl011_rs485_start_rts
[PATCH net-next] sfc: reduce the number of requested xdp ev queues
Without this change the driver tries to allocate too many queues, breaching the number of available msi-x interrupts on machines with many logical cpus and default adapter settings: Insufficient resources for 12 XDP event queues (24 other channels, max 32) Which in turn triggers EINVAL on XDP processing: sfc :86:00.0 ext0: XDP TX failed (-22) Signed-off-by: Ivan Babrou --- drivers/net/ethernet/sfc/efx_channels.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx_channels.c b/drivers/net/ethernet/sfc/efx_channels.c index a4a626e9cd9a..1bfeee283ea9 100644 --- a/drivers/net/ethernet/sfc/efx_channels.c +++ b/drivers/net/ethernet/sfc/efx_channels.c @@ -17,6 +17,7 @@ #include "rx_common.h" #include "nic.h" #include "sriov.h" +#include "workarounds.h" /* This is the first interrupt mode to try out of: * 0 => MSI-X @@ -137,6 +138,7 @@ static int efx_allocate_msix_channels(struct efx_nic *efx, { unsigned int n_channels = parallelism; int vec_count; + int tx_per_ev; int n_xdp_tx; int n_xdp_ev; @@ -149,9 +151,9 @@ static int efx_allocate_msix_channels(struct efx_nic *efx, * multiple tx queues, assuming tx and ev queues are both * maximum size. */ - + tx_per_ev = EFX_MAX_EVQ_SIZE / EFX_TXQ_MAX_ENT(efx); n_xdp_tx = num_possible_cpus(); - n_xdp_ev = DIV_ROUND_UP(n_xdp_tx, EFX_MAX_TXQ_PER_CHANNEL); + n_xdp_ev = DIV_ROUND_UP(n_xdp_tx, tx_per_ev); vec_count = pci_msix_vec_count(efx->pci_dev); if (vec_count < 0) -- 2.29.2
[PATCH 0/2] Add LED mode behavior/select properties and handle
In KSZ9131 PHY it is possible to control LEDs blink behavior via LED mode behavior and select registers. Add DTS properties plus handles of them inside micrel PHY driver. I've some concerns about passing raw register values into LED mode select and behavior. It can be passed via array like in microchip driver(Documentation/devicetree/bindings/net/microchip,lan78xx.txt). There is the problem in this particular driver - there is a lot of other PHYs and led mode behavior/select states may intersect, that's the reason why I did it this way. Is there any good ways to make it look more properly? Ivan Mikhaylov (2): net: phy: micrel: add LED control on KSZ9131 dt-bindings: net: phy: micrel: add LED mode behavior and select properties .../devicetree/bindings/net/micrel.txt| 7 ++ drivers/net/phy/micrel.c | 69 ++- 2 files changed, 75 insertions(+), 1 deletion(-) -- 2.21.1
[PATCH 2/2] dt-bindings: net: phy: micrel: add LED mode behavior and select properties
Add LED mode behavior and LED mode select properties which can be used in KSZ9131 PHY. Signed-off-by: Ivan Mikhaylov --- Documentation/devicetree/bindings/net/micrel.txt | 7 +++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/net/micrel.txt b/Documentation/devicetree/bindings/net/micrel.txt index 8d157f0295a5..3022c979287a 100644 --- a/Documentation/devicetree/bindings/net/micrel.txt +++ b/Documentation/devicetree/bindings/net/micrel.txt @@ -16,9 +16,16 @@ Optional properties: KSZ8051: register 0x1f, bits 5..4 KSZ8081: register 0x1f, bits 5..4 KSZ8091: register 0x1f, bits 5..4 + KSZ9131: register 0x1a, bit 14 See the respective PHY datasheet for the mode values. + - micrel,led-mode-select + See the respective PHY datasheet for the mode select values. + + - micrel,led-mode-behavior + See the respective PHY datasheet for the mode behavior values. + - micrel,rmii-reference-clock-select-25-mhz: RMII Reference Clock Select bit selects 25 MHz mode -- 2.21.1
[PATCH 1/2] net: phy: micrel: add LED control on KSZ9131
Add the possibility to read the LED configuration via DTS properties from KSZ9131 PHY node. Add the new proprties and handle for them: micrel,led-mode-behavior micrel,led-mode-select Signed-off-by: Ivan Mikhaylov --- drivers/net/phy/micrel.c | 69 +++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 3fe552675dd2..117f3a3b9dd6 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -71,6 +71,11 @@ #define MII_KSZPHY_RX_DATA_PAD_SKEW 0x105 #define MII_KSZPHY_TX_DATA_PAD_SKEW 0x106 +/* KSZ9131 LED registers */ +#define MII_KSZPHY_LED_MODE_SELECT 0x16 +#define MII_KSZPHY_LED_BEHAVIOR0x17 +#define MII_KSZPHY_LED_MODE0x1a + #define PS_TO_REG 200 struct kszphy_hw_stat { @@ -86,6 +91,8 @@ static struct kszphy_hw_stat kszphy_hw_stats[] = { struct kszphy_type { u32 led_mode_reg; + u32 led_mode_behavior_reg; + u32 led_mode_select_reg; u16 interrupt_level_mask; bool has_broadcast_disable; bool has_nand_tree_disable; @@ -95,6 +102,8 @@ struct kszphy_type { struct kszphy_priv { const struct kszphy_type *type; int led_mode; + int led_mode_behavior; + int led_mode_select; bool rmii_ref_clk_sel; bool rmii_ref_clk_sel_val; u64 stats[ARRAY_SIZE(kszphy_hw_stats)]; @@ -131,6 +140,13 @@ static const struct kszphy_type ksz9021_type = { .interrupt_level_mask = BIT(14), }; +static const struct kszphy_type ksz9131_type = { + .led_mode_reg = MII_KSZPHY_LED_MODE, + .led_mode_behavior_reg = MII_KSZPHY_LED_BEHAVIOR, + .led_mode_select_reg= MII_KSZPHY_LED_MODE_SELECT, + .interrupt_level_mask = BIT(14), +}; + static int kszphy_extended_write(struct phy_device *phydev, u32 regnum, u16 val) { @@ -204,6 +220,7 @@ static int kszphy_setup_led(struct phy_device *phydev, u32 reg, int val) switch (reg) { case MII_KSZPHY_CTRL_1: + case MII_KSZPHY_LED_MODE: shift = 14; break; case MII_KSZPHY_CTRL_2: @@ -286,6 +303,26 @@ static int kszphy_config_reset(struct phy_device *phydev) if (priv->led_mode >= 0) kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode); + if (priv->led_mode_behavior >= 0) { + ret = phy_write(phydev, priv->type->led_mode_behavior_reg, + priv->led_mode_behavior); + if (ret) { + phydev_err(phydev, + "failed to set led mode behavior reg\n"); + return ret; + } + } + + if (priv->led_mode_select >= 0) { + ret = phy_write(phydev, priv->type->led_mode_select_reg, + priv->led_mode_select); + if (ret) { + phydev_err(phydev, + "failed to set led mode select reg\n"); + return ret; + } + } + return 0; } @@ -1122,6 +1159,36 @@ static int kszphy_probe(struct phy_device *phydev) priv->led_mode = -1; } + if (type->led_mode_behavior_reg) { + ret = of_property_read_u32(np, "micrel,led-mode-behavior", + &priv->led_mode_behavior); + if (!ret) { + ret = phy_write(phydev, type->led_mode_behavior_reg, + priv->led_mode_behavior); + if (ret) + phydev_err(phydev, + "invalid led mode behavior: 0x%x\n", + priv->led_mode_behavior); + } + } else { + priv->led_mode_behavior = -1; + } + + if (type->led_mode_select_reg) { + ret = of_property_read_u32(np, "micrel,led-mode-select", + &priv->led_mode_select); + if (!ret) { + ret = phy_write(phydev, type->led_mode_select_reg, + priv->led_mode_select); + if (ret) + phydev_err(phydev, + "invalid led mode select: 0x%x\n", + priv->led_mode_select); + } + } else { + priv->led_mode_select = -1; + } + clk = devm_clk_get(&phydev->mdio.dev, "rmii-ref")
Re: [PATCH net v2] bonding: fix feature flag setting at init time
On Wed, 2 Dec 2020 12:30:53 -0500 Jarod Wilson wrote: > Don't try to adjust XFRM support flags if the bond device isn't yet > registered. Bad things can currently happen when netdev_change_features() > is called without having wanted_features fully filled in yet. Basically, > this code was racing against register_netdevice() filling in > wanted_features, and when it got there first, the empty wanted_features > led to features also getting emptied out, which was definitely not the > intended behavior, so prevent that from happening. > > Originally, I'd hoped to stop adjusting wanted_features at all in the > bonding driver, as it's documented as being something only the network > core should touch, but we actually do need to do this to properly update > both the features and wanted_features fields when changing the bond type, > or we get to a situation where ethtool sees: > > esp-hw-offload: off [requested on] > > I do think we should be using netdev_update_features instead of > netdev_change_features here though, so we only send notifiers when the > features actually changed. > > v2: rework based on further testing and suggestions from ivecera > > Fixes: a3b658cfb664 ("bonding: allow xfrm offload setup post-module-load") > Reported-by: Ivan Vecera > Suggested-by: Ivan Vecera > Cc: Jay Vosburgh > Cc: Veaceslav Falico > Cc: Andy Gospodarek > Cc: "David S. Miller" > Cc: Jakub Kicinski > Cc: Thomas Davis > Cc: net...@vger.kernel.org > Signed-off-by: Jarod Wilson > --- > drivers/net/bonding/bond_main.c| 10 -- > drivers/net/bonding/bond_options.c | 6 +- > 2 files changed, 9 insertions(+), 7 deletions(-) > > diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c > index e0880a3840d7..5fe5232cc3f3 100644 > --- a/drivers/net/bonding/bond_main.c > +++ b/drivers/net/bonding/bond_main.c > @@ -4746,15 +4746,13 @@ void bond_setup(struct net_device *bond_dev) > NETIF_F_HW_VLAN_CTAG_FILTER; > > bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL; > -#ifdef CONFIG_XFRM_OFFLOAD > - bond_dev->hw_features |= BOND_XFRM_FEATURES; > -#endif /* CONFIG_XFRM_OFFLOAD */ > bond_dev->features |= bond_dev->hw_features; > bond_dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; > #ifdef CONFIG_XFRM_OFFLOAD > - /* Disable XFRM features if this isn't an active-backup config */ > - if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) > - bond_dev->features &= ~BOND_XFRM_FEATURES; > + bond_dev->hw_features |= BOND_XFRM_FEATURES; > + /* Only enable XFRM features if this is an active-backup config */ > + if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) > + bond_dev->features |= BOND_XFRM_FEATURES; > #endif /* CONFIG_XFRM_OFFLOAD */ > } > > diff --git a/drivers/net/bonding/bond_options.c > b/drivers/net/bonding/bond_options.c > index 9abfaae1c6f7..19205cfac751 100644 > --- a/drivers/net/bonding/bond_options.c > +++ b/drivers/net/bonding/bond_options.c > @@ -768,11 +768,15 @@ static int bond_option_mode_set(struct bonding *bond, > bond->params.tlb_dynamic_lb = 1; > > #ifdef CONFIG_XFRM_OFFLOAD > + if (bond->dev->reg_state != NETREG_REGISTERED) > + goto noreg; > + > if (newval->value == BOND_MODE_ACTIVEBACKUP) > bond->dev->wanted_features |= BOND_XFRM_FEATURES; > else > bond->dev->wanted_features &= ~BOND_XFRM_FEATURES; > - netdev_change_features(bond->dev); > + netdev_update_features(bond->dev); > +noreg: > #endif /* CONFIG_XFRM_OFFLOAD */ > > /* don't cache arp_validate between modes */ Tested-by: Ivan Vecera
Re: [PATCH net] bonding: fix feature flag setting at init time
On Sun, 22 Nov 2020 22:17:16 -0500 Jarod Wilson wrote: > Have run into a case where bond_option_mode_set() gets called before > hw_features has been filled in, and very bad things happen when > netdev_change_features() then gets called, because the empty hw_features > wipes out almost all features. Further reading of netdev feature flag > documentation suggests drivers aren't supposed to touch wanted_features, > so this changes bond_option_mode_set() to use netdev_increment_features() > and &= ~BOND_XFRM_FEATURES on mode changes and then only calling > netdev_features_change() if there was actually a change of features. This > specifically fixes bonding on top of mlxsw interfaces, and has been > regression-tested with ixgbe interfaces. This change also simplifies the > xfrm-specific code in bond_setup() a little bit as well. Hi Jarod, the reason is not correct... The problem is not with empty ->hw_features but with empty ->wanted_features. During bond device creation bond_newlink() is called. It calls bond_changelink() first and afterwards register_netdevice(). The problem is that ->wanted_features are initialized in register_netdevice() so during bond_changlink() call ->wanted_features is 0. So... bond_newlink() -> bond_changelink() -> __bond_opt_set() -> bond_option_mode_set() -> netdev_change_features() -> __netdev_update_features() features = netdev_get_wanted_features() { dev->features & ~dev->hw_features) | dev->wanted_features } dev->wanted_features is here zero so the rest of the expression clears a bunch of bits from dev->features... In case of mlxsw it is important that NETIF_F_HW_VLAN_CTAG_FILTER bit is cleared in bonding device because in this case vlan_add_rx_filter_info() does not call bond_vlan_rx_add_vid() so mlxsw_sp_port_add_vid() is not called as well. Later this causes a WARN in mlxsw_sp_inetaddr_port_vlan_event() because instance of mlxsw_sp_port_vlan does not exist as mlxsw_sp_port_add_vid() was not called. Btw. it should be enough to call existing snippet in bond_option_mode_set() only when device is already registered? E.g.: diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 9abfaae1c6f7..ca4913fee5a9 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -768,11 +768,13 @@ static int bond_option_mode_set(struct bonding *bond, bond->params.tlb_dynamic_lb = 1; #ifdef CONFIG_XFRM_OFFLOAD - if (newval->value == BOND_MODE_ACTIVEBACKUP) - bond->dev->wanted_features |= BOND_XFRM_FEATURES; - else - bond->dev->wanted_features &= ~BOND_XFRM_FEATURES; - netdev_change_features(bond->dev); + if (dev->reg_state == NETREG_REGISTERED) { + if (newval->value == BOND_MODE_ACTIVEBACKUP) + bond->dev->wanted_features |= BOND_XFRM_FEATURES; + else + bond->dev->wanted_features &= ~BOND_XFRM_FEATURES; + netdev_change_features(bond->dev); + } #endif /* CONFIG_XFRM_OFFLOAD */ Thanks, Ivan
Re: [PATCH bpf v6 1/2] lib/strncpy_from_user.c: Don't overcopy bytes after NUL terminator
On Mon, Nov 16, 2020 at 02:44:56PM -0800, Linus Torvalds wrote: > On Mon, Nov 16, 2020 at 2:15 PM Linus Torvalds > wrote: > > > > So I've verified that at least on x86-64, this doesn't really make > > code generation any worse, and I'm ok with the patch from that > > standpoint. > > .. looking closer, it will generate extra code on big-endian > architectures and on alpha, because of the added "zero_bytemask()". > But on the usual LE machines, zero_bytemask() will already be the same > as "mask", so all it adds is that "and" operation with values it > already had access to. > > I don't think anybody cares about alpha and BE - traditional BE > architectures have moved to LE anyway. And looking at the alpha > word-at-a-time code, I don't even understand how it works at all. > > Adding matt/rth/ivan to the cc, just so that maybe one of them can > educate me on how that odd alpha zero_bytemask() could possibly work. > The "2ul << .." part confuses me, I think it should be "1ul << ...". > > I get the feeling that the alpha "2ul" constant might have come from > the tile version, but in the tile version, the " __builtin_ctzl()" > counts the leading zeroes to the top bit of any bytes in 'mask'. But > the alpha version actually uses "find_zero(mask) * 8", so rather than > have values of 7/15/23/... (for zero byte in byte 0/1/2/.. > respectively), it has values 0/8/16/ > > But it's entirely possible that I'm completely confused, and alpha > does it right, and I'm just not understanding the code. No, you are right, it should be "1ul". Indeed, seems like it came from the tile version which looks incorrect either, BTW. The tile-gx ISA (https://studylib.net/doc/18755547/tile-gx-instruction-set-architecture) says that clz/ctz instructions count up to the first "1", not to the last "0", so the shift values in tile's zero_bytemask() are 0/8/16/... as well. > It's also possible that the "2ul" vs "1ul" case doesn't matter. > because the extra bit is always going to mask the byte that is > actually zero, so being one bit off in the result is a non-event. I > think that is what may actually be going on. Yes, looks like that. Ivan.
[PATCH v2] ARM: mxs: Add serial number support for i.MX23, i.MX28 SoCs
i.MX23 and i.MX28 SoCs unique identifiers are factory-programmed in On-Chip OTP memory. i.MX28's 64-bit unique id is in HW_OCOTP_OPS2:HW_OCOTP_OPS3 (see MCIMX28 Ref. Man., sec. 20.4.22-23). i.MX23 provides 32-bit long unique id in HW_OCOTP_OPS3. Though not clearly documented, there is a clue in sec. 35.9.3. The unique id is reported in /sys/devices/soc0/serial_number and in /proc/cpuinfo Signed-off-by: Ivan Zaentsev Suggested-by: Evgeny Boger --- Changes in v2: 1. Sort #includes aphabetically. 2. Use tabs instead of spaces for indent. 3. Remove unnecessary newline. arch/arm/mach-mxs/mach-mxs.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index c109f47e9cbc..25c9d184fa4c 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "pm.h" @@ -51,6 +52,9 @@ #define MXS_CLR_ADDR 0x8 #define MXS_TOG_ADDR 0xc +#define HW_OCOTP_OPS2 19 /* offset 0x150 */ +#define HW_OCOTP_OPS3 20 /* offset 0x160 */ + static u32 chipid; static u32 socid; @@ -379,6 +383,8 @@ static void __init mxs_machine_init(void) struct device *parent; struct soc_device *soc_dev; struct soc_device_attribute *soc_dev_attr; + u64 soc_uid = 0; + const u32 *ocotp = mxs_get_ocotp(); int ret; soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); @@ -394,8 +400,21 @@ static void __init mxs_machine_init(void) soc_dev_attr->soc_id = mxs_get_soc_id(); soc_dev_attr->revision = mxs_get_revision(); + if (socid == HW_DIGCTL_CHIPID_MX23) { + soc_uid = system_serial_low = ocotp[HW_OCOTP_OPS3]; + } else if (socid == HW_DIGCTL_CHIPID_MX28) { + soc_uid = system_serial_high = ocotp[HW_OCOTP_OPS2]; + soc_uid <<= 32; + system_serial_low = ocotp[HW_OCOTP_OPS3]; + soc_uid |= system_serial_low; + } + + if (soc_uid) + soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid); + soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->serial_number); kfree(soc_dev_attr->revision); kfree(soc_dev_attr); return; -- 2.25.1
[PATCH] w1: w1_therm: Rename conflicting sysfs attribute 'eeprom' to 'eeprom_cmd'
Duplicate attribute 'eeprom' is defined in: 1) Documentation/ABI/testing/sysfs-driver-w1_therm 2) Documentation/ABI/stable/sysfs-driver-w1_ds28e04 Both drivers define an attribute: /sys/bus/w1/devices/.../eeprom with conflicting behavior. Fix by renaming the newer one in w1_therm.c to 'eeprom_cmd'. Reported-by: Mauro Carvalho Chehab Suggested-by: Greg Kroah-Hartman Link: https://lore.kernel.org/lkml/20201029152845.6bbb3...@coco.lan/ Signed-off-by: Ivan Zaentsev --- Documentation/ABI/testing/sysfs-driver-w1_therm | 2 +- Documentation/w1/slaves/w1_therm.rst| 2 +- drivers/w1/slaves/w1_therm.c| 12 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-driver-w1_therm b/Documentation/ABI/testing/sysfs-driver-w1_therm index 6a37dc33ffdb..74642c73d29c 100644 --- a/Documentation/ABI/testing/sysfs-driver-w1_therm +++ b/Documentation/ABI/testing/sysfs-driver-w1_therm @@ -14,7 +14,7 @@ Users:any user space application which wants to communicate with w1_term device -What: /sys/bus/w1/devices/.../eeprom +What: /sys/bus/w1/devices/.../eeprom_cmd Date: May 2020 Contact: Akira Shimahara Description: diff --git a/Documentation/w1/slaves/w1_therm.rst b/Documentation/w1/slaves/w1_therm.rst index e39202e2b000..c3c9ed7a356c 100644 --- a/Documentation/w1/slaves/w1_therm.rst +++ b/Documentation/w1/slaves/w1_therm.rst @@ -82,7 +82,7 @@ resolution is read back from the chip and verified. Note: Changing the resolution reverts the conversion time to default. -The write-only sysfs entry ``eeprom`` is an alternative for EEPROM operations. +The write-only sysfs entry ``eeprom_cmd`` is an alternative for EEPROM operations. Write ``save`` to save device RAM to EEPROM. Write ``restore`` to restore EEPROM data in device RAM. diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index cddf60b7309c..3712b1e6dc71 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -315,7 +315,7 @@ static ssize_t resolution_show(struct device *device, static ssize_t resolution_store(struct device *device, struct device_attribute *attr, const char *buf, size_t size); -static ssize_t eeprom_store(struct device *device, +static ssize_t eeprom_cmd_store(struct device *device, struct device_attribute *attr, const char *buf, size_t size); static ssize_t alarms_store(struct device *device, @@ -350,7 +350,7 @@ static DEVICE_ATTR_RO(w1_seq); static DEVICE_ATTR_RO(temperature); static DEVICE_ATTR_RO(ext_power); static DEVICE_ATTR_RW(resolution); -static DEVICE_ATTR_WO(eeprom); +static DEVICE_ATTR_WO(eeprom_cmd); static DEVICE_ATTR_RW(alarms); static DEVICE_ATTR_RW(conv_time); static DEVICE_ATTR_RW(features); @@ -386,7 +386,7 @@ static struct attribute *w1_therm_attrs[] = { &dev_attr_temperature.attr, &dev_attr_ext_power.attr, &dev_attr_resolution.attr, - &dev_attr_eeprom.attr, + &dev_attr_eeprom_cmd.attr, &dev_attr_alarms.attr, &dev_attr_conv_time.attr, &dev_attr_features.attr, @@ -397,7 +397,7 @@ static struct attribute *w1_ds18s20_attrs[] = { &dev_attr_w1_slave.attr, &dev_attr_temperature.attr, &dev_attr_ext_power.attr, - &dev_attr_eeprom.attr, + &dev_attr_eeprom_cmd.attr, &dev_attr_alarms.attr, &dev_attr_conv_time.attr, &dev_attr_features.attr, @@ -410,7 +410,7 @@ static struct attribute *w1_ds28ea00_attrs[] = { &dev_attr_temperature.attr, &dev_attr_ext_power.attr, &dev_attr_resolution.attr, - &dev_attr_eeprom.attr, + &dev_attr_eeprom_cmd.attr, &dev_attr_alarms.attr, &dev_attr_conv_time.attr, &dev_attr_features.attr, @@ -1740,7 +1740,7 @@ static ssize_t resolution_store(struct device *device, return size; } -static ssize_t eeprom_store(struct device *device, +static ssize_t eeprom_cmd_store(struct device *device, struct device_attribute *attr, const char *buf, size_t size) { struct w1_slave *sl = dev_to_w1_slave(device); -- 2.25.1
[PATCH] ARM: mxs: Add serial number support for i.MX23, i.MX28 SoCs
i.MX23 and i.MX28 SoCs unique identifiers are factory-programmed in On-Chip OTP memory. i.MX28's 64-bit unique id is in HW_OCOTP_OPS2:HW_OCOTP_OPS3 (see MCIMX28 Ref. Man., sec. 20.4.22-23). i.MX23 provides 32-bit long unique id in HW_OCOTP_OPS3. Though not clearly documented, there is a clue in sec. 35.9.3. The unique id is reported in /sys/devices/soc0/serial_number and in /proc/cpuinfo Signed-off-by: Ivan Zaentsev Suggested-by: Evgeny Boger --- arch/arm/mach-mxs/mach-mxs.c | 20 1 file changed, 20 insertions(+) diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index c109f47e9cbc..af96368cc16a 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "pm.h" @@ -51,6 +52,9 @@ #define MXS_CLR_ADDR 0x8 #define MXS_TOG_ADDR 0xc +#define HW_OCOTP_OPS2 19 /* offset 0x150 */ +#define HW_OCOTP_OPS3 20 /* offset 0x160 */ + static u32 chipid; static u32 socid; @@ -379,6 +383,8 @@ static void __init mxs_machine_init(void) struct device *parent; struct soc_device *soc_dev; struct soc_device_attribute *soc_dev_attr; + u64 soc_uid = 0; + const u32 *ocotp = mxs_get_ocotp(); int ret; soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); @@ -394,8 +400,22 @@ static void __init mxs_machine_init(void) soc_dev_attr->soc_id = mxs_get_soc_id(); soc_dev_attr->revision = mxs_get_revision(); + if (socid == HW_DIGCTL_CHIPID_MX23) { + soc_uid = system_serial_low = ocotp[HW_OCOTP_OPS3]; + } else if (socid == HW_DIGCTL_CHIPID_MX28) { + soc_uid = system_serial_high = ocotp[HW_OCOTP_OPS2]; + soc_uid <<= 32; + system_serial_low = ocotp[HW_OCOTP_OPS3]; + soc_uid |= system_serial_low; + } + + if (soc_uid) + soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid); + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->serial_number); kfree(soc_dev_attr->revision); kfree(soc_dev_attr); return; -- 2.25.1
[PATCH v3 0/3] add ast2400/2500 phy-handle support
This patch introduces ast2400/2500 phy-handle support with an embedded MDIO controller. At the current moment it is not possible to set options with this format on ast2400/2500: mac { phy-handle = <&phy>; phy-mode = "rgmii"; mdio { #address-cells = <1>; #size-cells = <0>; phy: ethernet-phy@0 { compatible = "ethernet-phy-id."; reg = <0>; }; }; }; The patch fixes it and gets possible PHYs and register them with of_mdiobus_register. Changes from v3: 1. add dt-bindings description of MDIO node and phy-handle option with example. Changes from v2: 1. change manual phy interface type check on phy_interface_mode_is_rgmii function. 2. add err_phy_connect label. 3. split ftgmac100_destroy_mdio into ftgmac100_phy_disconnect and ftgmac100_destroy_mdio. 4. remove unneeded mdio_np checks. Changes from v1: 1. split one patch into two. Ivan Mikhaylov (3): net: ftgmac100: move phy connect out from ftgmac100_setup_mdio net: ftgmac100: add handling of mdio/phy nodes for ast2400/2500 dt-bindings: net: ftgmac100: describe phy-handle and MDIO .../devicetree/bindings/net/ftgmac100.txt | 25 drivers/net/ethernet/faraday/ftgmac100.c | 122 ++ 2 files changed, 96 insertions(+), 51 deletions(-) -- 2.21.1
[PATCH v3 2/3] net: ftgmac100: add handling of mdio/phy nodes for ast2400/2500
phy-handle can't be handled well for ast2400/2500 which has an embedded MDIO controller. Add ftgmac100_mdio_setup for ast2400/2500 and initialize PHYs from mdio child node with of_mdiobus_register. Signed-off-by: Ivan Mikhaylov --- drivers/net/ethernet/faraday/ftgmac100.c | 20 ++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index ffad79050713..62bafd4b22e1 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -1631,6 +1631,7 @@ static int ftgmac100_setup_mdio(struct net_device *netdev) struct ftgmac100 *priv = netdev_priv(netdev); struct platform_device *pdev = to_platform_device(priv->dev); struct device_node *np = pdev->dev.of_node; + struct device_node *mdio_np; int i, err = 0; u32 reg; @@ -1662,12 +1663,16 @@ static int ftgmac100_setup_mdio(struct net_device *netdev) for (i = 0; i < PHY_MAX_ADDR; i++) priv->mii_bus->irq[i] = PHY_POLL; - err = mdiobus_register(priv->mii_bus); + mdio_np = of_get_child_by_name(np, "mdio"); + + err = of_mdiobus_register(priv->mii_bus, mdio_np); if (err) { dev_err(priv->dev, "Cannot register MDIO bus!\n"); goto err_register_mdiobus; } + of_node_put(mdio_np); + return 0; err_register_mdiobus: @@ -1830,11 +1835,22 @@ static int ftgmac100_probe(struct platform_device *pdev) } else if (np && of_get_property(np, "phy-handle", NULL)) { struct phy_device *phy; + /* Support "mdio"/"phy" child nodes for ast2400/2500 with +* an embedded MDIO controller. Automatically scan the DTS for +* available PHYs and register them. +*/ + if (of_device_is_compatible(np, "aspeed,ast2400-mac") || + of_device_is_compatible(np, "aspeed,ast2500-mac")) { + err = ftgmac100_setup_mdio(netdev); + if (err) + goto err_setup_mdio; + } + phy = of_phy_get_and_connect(priv->netdev, np, &ftgmac100_adjust_link); if (!phy) { dev_err(&pdev->dev, "Failed to connect to phy\n"); - goto err_setup_mdio; + goto err_phy_connect; } /* Indicate that we support PAUSE frames (see comment in -- 2.21.1