mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
Merge f71077a4d8 ("Merge tag 'mmc-v5.17-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc") into android-mainline
Steps on the way to 5.17-rc5 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I1e7ac2a07640b6cb46b7052cd57bc68af4cf0368
This commit is contained in:
@@ -248,6 +248,8 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
|
||||
IRQCHIP_STATE_PENDING,
|
||||
&val);
|
||||
WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
|
||||
} else if (vgic_irq_is_mapped_level(irq)) {
|
||||
val = vgic_get_phys_line_level(irq);
|
||||
} else {
|
||||
val = irq_is_pending(irq);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
#include <asm/barrier.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
/* compiler build environment sanity checks: */
|
||||
#if !defined(CONFIG_64BIT) && defined(__LP64__)
|
||||
#error "Please use 'ARCH=parisc' to build the 32-bit kernel."
|
||||
#endif
|
||||
#if defined(CONFIG_64BIT) && !defined(__LP64__)
|
||||
#error "Please use 'ARCH=parisc64' to build the 64-bit kernel."
|
||||
#endif
|
||||
|
||||
/* See http://marc.theaimsgroup.com/?t=108826637900003 for discussion
|
||||
* on use of volatile and __*_bit() (set/clear/change):
|
||||
* *_bit() want use of volatile.
|
||||
|
||||
@@ -89,8 +89,8 @@ struct exception_table_entry {
|
||||
__asm__("1: " ldx " 0(" sr "%2),%0\n" \
|
||||
"9:\n" \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
|
||||
: "=r"(__gu_val), "=r"(__gu_err) \
|
||||
: "r"(ptr), "1"(__gu_err)); \
|
||||
: "=r"(__gu_val), "+r"(__gu_err) \
|
||||
: "r"(ptr)); \
|
||||
\
|
||||
(val) = (__force __typeof__(*(ptr))) __gu_val; \
|
||||
}
|
||||
@@ -123,8 +123,8 @@ struct exception_table_entry {
|
||||
"9:\n" \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
|
||||
: "=&r"(__gu_tmp.l), "=r"(__gu_err) \
|
||||
: "r"(ptr), "1"(__gu_err)); \
|
||||
: "=&r"(__gu_tmp.l), "+r"(__gu_err) \
|
||||
: "r"(ptr)); \
|
||||
\
|
||||
(val) = __gu_tmp.t; \
|
||||
}
|
||||
@@ -135,13 +135,12 @@ struct exception_table_entry {
|
||||
#define __put_user_internal(sr, x, ptr) \
|
||||
({ \
|
||||
ASM_EXCEPTIONTABLE_VAR(__pu_err); \
|
||||
__typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \
|
||||
\
|
||||
switch (sizeof(*(ptr))) { \
|
||||
case 1: __put_user_asm(sr, "stb", __x, ptr); break; \
|
||||
case 2: __put_user_asm(sr, "sth", __x, ptr); break; \
|
||||
case 4: __put_user_asm(sr, "stw", __x, ptr); break; \
|
||||
case 8: STD_USER(sr, __x, ptr); break; \
|
||||
case 1: __put_user_asm(sr, "stb", x, ptr); break; \
|
||||
case 2: __put_user_asm(sr, "sth", x, ptr); break; \
|
||||
case 4: __put_user_asm(sr, "stw", x, ptr); break; \
|
||||
case 8: STD_USER(sr, x, ptr); break; \
|
||||
default: BUILD_BUG(); \
|
||||
} \
|
||||
\
|
||||
@@ -150,7 +149,9 @@ struct exception_table_entry {
|
||||
|
||||
#define __put_user(x, ptr) \
|
||||
({ \
|
||||
__put_user_internal("%%sr3,", x, ptr); \
|
||||
__typeof__(&*(ptr)) __ptr = ptr; \
|
||||
__typeof__(*(__ptr)) __x = (__typeof__(*(__ptr)))(x); \
|
||||
__put_user_internal("%%sr3,", __x, __ptr); \
|
||||
})
|
||||
|
||||
#define __put_kernel_nofault(dst, src, type, err_label) \
|
||||
@@ -180,8 +181,8 @@ struct exception_table_entry {
|
||||
"1: " stx " %2,0(" sr "%1)\n" \
|
||||
"9:\n" \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
|
||||
: "=r"(__pu_err) \
|
||||
: "r"(ptr), "r"(x), "0"(__pu_err))
|
||||
: "+r"(__pu_err) \
|
||||
: "r"(ptr), "r"(x))
|
||||
|
||||
|
||||
#if !defined(CONFIG_64BIT)
|
||||
@@ -193,8 +194,8 @@ struct exception_table_entry {
|
||||
"9:\n" \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \
|
||||
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \
|
||||
: "=r"(__pu_err) \
|
||||
: "r"(ptr), "r"(__val), "0"(__pu_err)); \
|
||||
: "+r"(__pu_err) \
|
||||
: "r"(ptr), "r"(__val)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* !defined(CONFIG_64BIT) */
|
||||
|
||||
@@ -346,6 +346,16 @@ u64 ioread64be(const void __iomem *addr)
|
||||
return *((u64 *)addr);
|
||||
}
|
||||
|
||||
u64 ioread64_lo_hi(const void __iomem *addr)
|
||||
{
|
||||
u32 low, high;
|
||||
|
||||
low = ioread32(addr);
|
||||
high = ioread32(addr + sizeof(u32));
|
||||
|
||||
return low + ((u64)high << 32);
|
||||
}
|
||||
|
||||
u64 ioread64_hi_lo(const void __iomem *addr)
|
||||
{
|
||||
u32 low, high;
|
||||
@@ -419,6 +429,12 @@ void iowrite64be(u64 datum, void __iomem *addr)
|
||||
}
|
||||
}
|
||||
|
||||
void iowrite64_lo_hi(u64 val, void __iomem *addr)
|
||||
{
|
||||
iowrite32(val, addr);
|
||||
iowrite32(val >> 32, addr + sizeof(u32));
|
||||
}
|
||||
|
||||
void iowrite64_hi_lo(u64 val, void __iomem *addr)
|
||||
{
|
||||
iowrite32(val >> 32, addr + sizeof(u32));
|
||||
@@ -530,6 +546,7 @@ EXPORT_SYMBOL(ioread32);
|
||||
EXPORT_SYMBOL(ioread32be);
|
||||
EXPORT_SYMBOL(ioread64);
|
||||
EXPORT_SYMBOL(ioread64be);
|
||||
EXPORT_SYMBOL(ioread64_lo_hi);
|
||||
EXPORT_SYMBOL(ioread64_hi_lo);
|
||||
EXPORT_SYMBOL(iowrite8);
|
||||
EXPORT_SYMBOL(iowrite16);
|
||||
@@ -538,6 +555,7 @@ EXPORT_SYMBOL(iowrite32);
|
||||
EXPORT_SYMBOL(iowrite32be);
|
||||
EXPORT_SYMBOL(iowrite64);
|
||||
EXPORT_SYMBOL(iowrite64be);
|
||||
EXPORT_SYMBOL(iowrite64_lo_hi);
|
||||
EXPORT_SYMBOL(iowrite64_hi_lo);
|
||||
EXPORT_SYMBOL(ioread8_rep);
|
||||
EXPORT_SYMBOL(ioread16_rep);
|
||||
|
||||
@@ -337,9 +337,9 @@ static void __init setup_bootmem(void)
|
||||
|
||||
static bool kernel_set_to_readonly;
|
||||
|
||||
static void __init map_pages(unsigned long start_vaddr,
|
||||
unsigned long start_paddr, unsigned long size,
|
||||
pgprot_t pgprot, int force)
|
||||
static void __ref map_pages(unsigned long start_vaddr,
|
||||
unsigned long start_paddr, unsigned long size,
|
||||
pgprot_t pgprot, int force)
|
||||
{
|
||||
pmd_t *pmd;
|
||||
pte_t *pg_table;
|
||||
@@ -449,7 +449,7 @@ void __init set_kernel_text_rw(int enable_read_write)
|
||||
flush_tlb_all();
|
||||
}
|
||||
|
||||
void __ref free_initmem(void)
|
||||
void free_initmem(void)
|
||||
{
|
||||
unsigned long init_begin = (unsigned long)__init_begin;
|
||||
unsigned long init_end = (unsigned long)__init_end;
|
||||
@@ -463,7 +463,6 @@ void __ref free_initmem(void)
|
||||
/* The init text pages are marked R-X. We have to
|
||||
* flush the icache and mark them RW-
|
||||
*
|
||||
* This is tricky, because map_pages is in the init section.
|
||||
* Do a dummy remap of the data section first (the data
|
||||
* section is already PAGE_KERNEL) to pull in the TLB entries
|
||||
* for map_kernel */
|
||||
|
||||
@@ -476,6 +476,7 @@
|
||||
#define MSR_AMD64_ICIBSEXTDCTL 0xc001103c
|
||||
#define MSR_AMD64_IBSOPDATA4 0xc001103d
|
||||
#define MSR_AMD64_IBS_REG_COUNT_MAX 8 /* includes MSR_AMD64_IBSBRTARGET */
|
||||
#define MSR_AMD64_SVM_AVIC_DOORBELL 0xc001011b
|
||||
#define MSR_AMD64_VM_PAGE_FLUSH 0xc001011e
|
||||
#define MSR_AMD64_SEV_ES_GHCB 0xc0010130
|
||||
#define MSR_AMD64_SEV 0xc0010131
|
||||
|
||||
@@ -220,6 +220,42 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
|
||||
#define SVM_NESTED_CTL_SEV_ENABLE BIT(1)
|
||||
#define SVM_NESTED_CTL_SEV_ES_ENABLE BIT(2)
|
||||
|
||||
|
||||
/* AVIC */
|
||||
#define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK (0xFF)
|
||||
#define AVIC_LOGICAL_ID_ENTRY_VALID_BIT 31
|
||||
#define AVIC_LOGICAL_ID_ENTRY_VALID_MASK (1 << 31)
|
||||
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK (0xFFULL)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK (0xFFFFFFFFFFULL << 12)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK (1ULL << 62)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK (1ULL << 63)
|
||||
#define AVIC_PHYSICAL_ID_TABLE_SIZE_MASK (0xFF)
|
||||
|
||||
#define AVIC_DOORBELL_PHYSICAL_ID_MASK (0xFF)
|
||||
|
||||
#define AVIC_UNACCEL_ACCESS_WRITE_MASK 1
|
||||
#define AVIC_UNACCEL_ACCESS_OFFSET_MASK 0xFF0
|
||||
#define AVIC_UNACCEL_ACCESS_VECTOR_MASK 0xFFFFFFFF
|
||||
|
||||
enum avic_ipi_failure_cause {
|
||||
AVIC_IPI_FAILURE_INVALID_INT_TYPE,
|
||||
AVIC_IPI_FAILURE_TARGET_NOT_RUNNING,
|
||||
AVIC_IPI_FAILURE_INVALID_TARGET,
|
||||
AVIC_IPI_FAILURE_INVALID_BACKING_PAGE,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 0xff is broadcast, so the max index allowed for physical APIC ID
|
||||
* table is 0xfe. APIC IDs above 0xff are reserved.
|
||||
*/
|
||||
#define AVIC_MAX_PHYSICAL_ID_COUNT 0xff
|
||||
|
||||
#define AVIC_HPA_MASK ~((0xFFFULL << 52) | 0xFFF)
|
||||
#define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL
|
||||
|
||||
|
||||
struct vmcb_seg {
|
||||
u16 selector;
|
||||
u16 attrib;
|
||||
|
||||
@@ -2306,7 +2306,12 @@ void kvm_apic_update_apicv(struct kvm_vcpu *vcpu)
|
||||
apic->irr_pending = true;
|
||||
apic->isr_count = 1;
|
||||
} else {
|
||||
apic->irr_pending = (apic_search_irr(apic) != -1);
|
||||
/*
|
||||
* Don't clear irr_pending, searching the IRR can race with
|
||||
* updates from the CPU as APICv is still active from hardware's
|
||||
* perspective. The flag will be cleared as appropriate when
|
||||
* KVM injects the interrupt.
|
||||
*/
|
||||
apic->isr_count = count_vectors(apic->regs + APIC_ISR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ static void kvm_perf_overflow(struct perf_event *perf_event,
|
||||
}
|
||||
|
||||
static void pmc_reprogram_counter(struct kvm_pmc *pmc, u32 type,
|
||||
unsigned config, bool exclude_user,
|
||||
u64 config, bool exclude_user,
|
||||
bool exclude_kernel, bool intr,
|
||||
bool in_tx, bool in_tx_cp)
|
||||
{
|
||||
@@ -181,7 +181,8 @@ static int cmp_u64(const void *a, const void *b)
|
||||
|
||||
void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
|
||||
{
|
||||
unsigned config, type = PERF_TYPE_RAW;
|
||||
u64 config;
|
||||
u32 type = PERF_TYPE_RAW;
|
||||
struct kvm *kvm = pmc->vcpu->kvm;
|
||||
struct kvm_pmu_event_filter *filter;
|
||||
bool allow_event = true;
|
||||
@@ -220,7 +221,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
|
||||
}
|
||||
|
||||
if (type == PERF_TYPE_RAW)
|
||||
config = eventsel & X86_RAW_EVENT_MASK;
|
||||
config = eventsel & AMD64_RAW_EVENT_MASK;
|
||||
|
||||
if (pmc->current_config == eventsel && pmc_resume_counter(pmc))
|
||||
return;
|
||||
|
||||
@@ -27,20 +27,6 @@
|
||||
#include "irq.h"
|
||||
#include "svm.h"
|
||||
|
||||
#define SVM_AVIC_DOORBELL 0xc001011b
|
||||
|
||||
#define AVIC_HPA_MASK ~((0xFFFULL << 52) | 0xFFF)
|
||||
|
||||
/*
|
||||
* 0xff is broadcast, so the max index allowed for physical APIC ID
|
||||
* table is 0xfe. APIC IDs above 0xff are reserved.
|
||||
*/
|
||||
#define AVIC_MAX_PHYSICAL_ID_COUNT 255
|
||||
|
||||
#define AVIC_UNACCEL_ACCESS_WRITE_MASK 1
|
||||
#define AVIC_UNACCEL_ACCESS_OFFSET_MASK 0xFF0
|
||||
#define AVIC_UNACCEL_ACCESS_VECTOR_MASK 0xFFFFFFFF
|
||||
|
||||
/* AVIC GATAG is encoded using VM and VCPU IDs */
|
||||
#define AVIC_VCPU_ID_BITS 8
|
||||
#define AVIC_VCPU_ID_MASK ((1 << AVIC_VCPU_ID_BITS) - 1)
|
||||
@@ -73,12 +59,6 @@ struct amd_svm_iommu_ir {
|
||||
void *data; /* Storing pointer to struct amd_ir_data */
|
||||
};
|
||||
|
||||
enum avic_ipi_failure_cause {
|
||||
AVIC_IPI_FAILURE_INVALID_INT_TYPE,
|
||||
AVIC_IPI_FAILURE_TARGET_NOT_RUNNING,
|
||||
AVIC_IPI_FAILURE_INVALID_TARGET,
|
||||
AVIC_IPI_FAILURE_INVALID_BACKING_PAGE,
|
||||
};
|
||||
|
||||
/* Note:
|
||||
* This function is called from IOMMU driver to notify
|
||||
@@ -289,6 +269,22 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void avic_ring_doorbell(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/*
|
||||
* Note, the vCPU could get migrated to a different pCPU at any point,
|
||||
* which could result in signalling the wrong/previous pCPU. But if
|
||||
* that happens the vCPU is guaranteed to do a VMRUN (after being
|
||||
* migrated) and thus will process pending interrupts, i.e. a doorbell
|
||||
* is not needed (and the spurious one is harmless).
|
||||
*/
|
||||
int cpu = READ_ONCE(vcpu->cpu);
|
||||
|
||||
if (cpu != get_cpu())
|
||||
wrmsrl(MSR_AMD64_SVM_AVIC_DOORBELL, kvm_cpu_get_apicid(cpu));
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
static void avic_kick_target_vcpus(struct kvm *kvm, struct kvm_lapic *source,
|
||||
u32 icrl, u32 icrh)
|
||||
{
|
||||
@@ -304,8 +300,13 @@ static void avic_kick_target_vcpus(struct kvm *kvm, struct kvm_lapic *source,
|
||||
kvm_for_each_vcpu(i, vcpu, kvm) {
|
||||
if (kvm_apic_match_dest(vcpu, source, icrl & APIC_SHORT_MASK,
|
||||
GET_APIC_DEST_FIELD(icrh),
|
||||
icrl & APIC_DEST_MASK))
|
||||
kvm_vcpu_wake_up(vcpu);
|
||||
icrl & APIC_DEST_MASK)) {
|
||||
vcpu->arch.apic->irr_pending = true;
|
||||
svm_complete_interrupt_delivery(vcpu,
|
||||
icrl & APIC_MODE_MASK,
|
||||
icrl & APIC_INT_LEVELTRIG,
|
||||
icrl & APIC_VECTOR_MASK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,8 +346,6 @@ int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu)
|
||||
avic_kick_target_vcpus(vcpu->kvm, apic, icrl, icrh);
|
||||
break;
|
||||
case AVIC_IPI_FAILURE_INVALID_TARGET:
|
||||
WARN_ONCE(1, "Invalid IPI target: index=%u, vcpu=%d, icr=%#0x:%#0x\n",
|
||||
index, vcpu->vcpu_id, icrh, icrl);
|
||||
break;
|
||||
case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE:
|
||||
WARN_ONCE(1, "Invalid backing page\n");
|
||||
@@ -669,52 +668,6 @@ void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
|
||||
return;
|
||||
}
|
||||
|
||||
int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
|
||||
{
|
||||
if (!vcpu->arch.apicv_active)
|
||||
return -1;
|
||||
|
||||
kvm_lapic_set_irr(vec, vcpu->arch.apic);
|
||||
|
||||
/*
|
||||
* Pairs with the smp_mb_*() after setting vcpu->guest_mode in
|
||||
* vcpu_enter_guest() to ensure the write to the vIRR is ordered before
|
||||
* the read of guest_mode, which guarantees that either VMRUN will see
|
||||
* and process the new vIRR entry, or that the below code will signal
|
||||
* the doorbell if the vCPU is already running in the guest.
|
||||
*/
|
||||
smp_mb__after_atomic();
|
||||
|
||||
/*
|
||||
* Signal the doorbell to tell hardware to inject the IRQ if the vCPU
|
||||
* is in the guest. If the vCPU is not in the guest, hardware will
|
||||
* automatically process AVIC interrupts at VMRUN.
|
||||
*/
|
||||
if (vcpu->mode == IN_GUEST_MODE) {
|
||||
int cpu = READ_ONCE(vcpu->cpu);
|
||||
|
||||
/*
|
||||
* Note, the vCPU could get migrated to a different pCPU at any
|
||||
* point, which could result in signalling the wrong/previous
|
||||
* pCPU. But if that happens the vCPU is guaranteed to do a
|
||||
* VMRUN (after being migrated) and thus will process pending
|
||||
* interrupts, i.e. a doorbell is not needed (and the spurious
|
||||
* one is harmless).
|
||||
*/
|
||||
if (cpu != get_cpu())
|
||||
wrmsrl(SVM_AVIC_DOORBELL, kvm_cpu_get_apicid(cpu));
|
||||
put_cpu();
|
||||
} else {
|
||||
/*
|
||||
* Wake the vCPU if it was blocking. KVM will then detect the
|
||||
* pending IRQ when checking if the vCPU has a wake event.
|
||||
*/
|
||||
kvm_vcpu_wake_up(vcpu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -1457,18 +1457,6 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu,
|
||||
!__nested_vmcb_check_save(vcpu, &save_cached))
|
||||
goto out_free;
|
||||
|
||||
/*
|
||||
* While the nested guest CR3 is already checked and set by
|
||||
* KVM_SET_SREGS, it was set when nested state was yet loaded,
|
||||
* thus MMU might not be initialized correctly.
|
||||
* Set it again to fix this.
|
||||
*/
|
||||
|
||||
ret = nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3,
|
||||
nested_npt_enabled(svm), false);
|
||||
if (WARN_ON_ONCE(ret))
|
||||
goto out_free;
|
||||
|
||||
|
||||
/*
|
||||
* All checks done, we can enter guest mode. Userspace provides
|
||||
@@ -1494,6 +1482,20 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu,
|
||||
|
||||
svm_switch_vmcb(svm, &svm->nested.vmcb02);
|
||||
nested_vmcb02_prepare_control(svm);
|
||||
|
||||
/*
|
||||
* While the nested guest CR3 is already checked and set by
|
||||
* KVM_SET_SREGS, it was set when nested state was yet loaded,
|
||||
* thus MMU might not be initialized correctly.
|
||||
* Set it again to fix this.
|
||||
*/
|
||||
|
||||
ret = nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3,
|
||||
nested_npt_enabled(svm), false);
|
||||
if (WARN_ON_ONCE(ret))
|
||||
goto out_free;
|
||||
|
||||
|
||||
kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu);
|
||||
ret = 0;
|
||||
out_free:
|
||||
|
||||
@@ -1585,6 +1585,7 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
u64 hcr0 = cr0;
|
||||
bool old_paging = is_paging(vcpu);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
if (vcpu->arch.efer & EFER_LME && !vcpu->arch.guest_state_protected) {
|
||||
@@ -1601,8 +1602,11 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
|
||||
#endif
|
||||
vcpu->arch.cr0 = cr0;
|
||||
|
||||
if (!npt_enabled)
|
||||
if (!npt_enabled) {
|
||||
hcr0 |= X86_CR0_PG | X86_CR0_WP;
|
||||
if (old_paging != is_paging(vcpu))
|
||||
svm_set_cr4(vcpu, kvm_read_cr4(vcpu));
|
||||
}
|
||||
|
||||
/*
|
||||
* re-enable caching here because the QEMU bios
|
||||
@@ -1646,8 +1650,12 @@ void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
|
||||
svm_flush_tlb(vcpu);
|
||||
|
||||
vcpu->arch.cr4 = cr4;
|
||||
if (!npt_enabled)
|
||||
if (!npt_enabled) {
|
||||
cr4 |= X86_CR4_PAE;
|
||||
|
||||
if (!is_paging(vcpu))
|
||||
cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE);
|
||||
}
|
||||
cr4 |= host_cr4_mce;
|
||||
to_svm(vcpu)->vmcb->save.cr4 = cr4;
|
||||
vmcb_mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
|
||||
@@ -3291,19 +3299,53 @@ static void svm_set_irq(struct kvm_vcpu *vcpu)
|
||||
SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR;
|
||||
}
|
||||
|
||||
static void svm_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,
|
||||
int trig_mode, int vector)
|
||||
void svm_complete_interrupt_delivery(struct kvm_vcpu *vcpu, int delivery_mode,
|
||||
int trig_mode, int vector)
|
||||
{
|
||||
struct kvm_vcpu *vcpu = apic->vcpu;
|
||||
/*
|
||||
* vcpu->arch.apicv_active must be read after vcpu->mode.
|
||||
* Pairs with smp_store_release in vcpu_enter_guest.
|
||||
*/
|
||||
bool in_guest_mode = (smp_load_acquire(&vcpu->mode) == IN_GUEST_MODE);
|
||||
|
||||
if (svm_deliver_avic_intr(vcpu, vector)) {
|
||||
kvm_lapic_set_irr(vector, apic);
|
||||
if (!READ_ONCE(vcpu->arch.apicv_active)) {
|
||||
/* Process the interrupt via inject_pending_event */
|
||||
kvm_make_request(KVM_REQ_EVENT, vcpu);
|
||||
kvm_vcpu_kick(vcpu);
|
||||
} else {
|
||||
trace_kvm_apicv_accept_irq(vcpu->vcpu_id, delivery_mode,
|
||||
trig_mode, vector);
|
||||
return;
|
||||
}
|
||||
|
||||
trace_kvm_apicv_accept_irq(vcpu->vcpu_id, delivery_mode, trig_mode, vector);
|
||||
if (in_guest_mode) {
|
||||
/*
|
||||
* Signal the doorbell to tell hardware to inject the IRQ. If
|
||||
* the vCPU exits the guest before the doorbell chimes, hardware
|
||||
* will automatically process AVIC interrupts at the next VMRUN.
|
||||
*/
|
||||
avic_ring_doorbell(vcpu);
|
||||
} else {
|
||||
/*
|
||||
* Wake the vCPU if it was blocking. KVM will then detect the
|
||||
* pending IRQ when checking if the vCPU has a wake event.
|
||||
*/
|
||||
kvm_vcpu_wake_up(vcpu);
|
||||
}
|
||||
}
|
||||
|
||||
static void svm_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,
|
||||
int trig_mode, int vector)
|
||||
{
|
||||
kvm_lapic_set_irr(vector, apic);
|
||||
|
||||
/*
|
||||
* Pairs with the smp_mb_*() after setting vcpu->guest_mode in
|
||||
* vcpu_enter_guest() to ensure the write to the vIRR is ordered before
|
||||
* the read of guest_mode. This guarantees that either VMRUN will see
|
||||
* and process the new vIRR entry, or that svm_complete_interrupt_delivery
|
||||
* will signal the doorbell if the CPU has already entered the guest.
|
||||
*/
|
||||
smp_mb__after_atomic();
|
||||
svm_complete_interrupt_delivery(apic->vcpu, delivery_mode, trig_mode, vector);
|
||||
}
|
||||
|
||||
static void svm_update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
|
||||
@@ -3353,11 +3395,13 @@ static int svm_nmi_allowed(struct kvm_vcpu *vcpu, bool for_injection)
|
||||
if (svm->nested.nested_run_pending)
|
||||
return -EBUSY;
|
||||
|
||||
if (svm_nmi_blocked(vcpu))
|
||||
return 0;
|
||||
|
||||
/* An NMI must not be injected into L2 if it's supposed to VM-Exit. */
|
||||
if (for_injection && is_guest_mode(vcpu) && nested_exit_on_nmi(svm))
|
||||
return -EBUSY;
|
||||
|
||||
return !svm_nmi_blocked(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool svm_get_nmi_mask(struct kvm_vcpu *vcpu)
|
||||
@@ -3409,9 +3453,13 @@ bool svm_interrupt_blocked(struct kvm_vcpu *vcpu)
|
||||
static int svm_interrupt_allowed(struct kvm_vcpu *vcpu, bool for_injection)
|
||||
{
|
||||
struct vcpu_svm *svm = to_svm(vcpu);
|
||||
|
||||
if (svm->nested.nested_run_pending)
|
||||
return -EBUSY;
|
||||
|
||||
if (svm_interrupt_blocked(vcpu))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* An IRQ must not be injected into L2 if it's supposed to VM-Exit,
|
||||
* e.g. if the IRQ arrived asynchronously after checking nested events.
|
||||
@@ -3419,7 +3467,7 @@ static int svm_interrupt_allowed(struct kvm_vcpu *vcpu, bool for_injection)
|
||||
if (for_injection && is_guest_mode(vcpu) && nested_exit_on_intr(svm))
|
||||
return -EBUSY;
|
||||
|
||||
return !svm_interrupt_blocked(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void svm_enable_irq_window(struct kvm_vcpu *vcpu)
|
||||
@@ -4150,11 +4198,14 @@ static int svm_smi_allowed(struct kvm_vcpu *vcpu, bool for_injection)
|
||||
if (svm->nested.nested_run_pending)
|
||||
return -EBUSY;
|
||||
|
||||
if (svm_smi_blocked(vcpu))
|
||||
return 0;
|
||||
|
||||
/* An SMI must not be injected into L2 if it's supposed to VM-Exit. */
|
||||
if (for_injection && is_guest_mode(vcpu) && nested_exit_on_smi(svm))
|
||||
return -EBUSY;
|
||||
|
||||
return !svm_smi_blocked(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int svm_enter_smm(struct kvm_vcpu *vcpu, char *smstate)
|
||||
@@ -4248,11 +4299,18 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
|
||||
* Enter the nested guest now
|
||||
*/
|
||||
|
||||
vmcb_mark_all_dirty(svm->vmcb01.ptr);
|
||||
|
||||
vmcb12 = map.hva;
|
||||
nested_copy_vmcb_control_to_cache(svm, &vmcb12->control);
|
||||
nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);
|
||||
ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, false);
|
||||
|
||||
if (ret)
|
||||
goto unmap_save;
|
||||
|
||||
svm->nested.nested_run_pending = 1;
|
||||
|
||||
unmap_save:
|
||||
kvm_vcpu_unmap(vcpu, &map_save, true);
|
||||
unmap_map:
|
||||
@@ -4637,6 +4695,7 @@ static __init void svm_set_cpu_caps(void)
|
||||
/* CPUID 0x80000001 and 0x8000000A (SVM features) */
|
||||
if (nested) {
|
||||
kvm_cpu_cap_set(X86_FEATURE_SVM);
|
||||
kvm_cpu_cap_set(X86_FEATURE_VMCBCLEAN);
|
||||
|
||||
if (nrips)
|
||||
kvm_cpu_cap_set(X86_FEATURE_NRIPS);
|
||||
|
||||
@@ -489,6 +489,8 @@ void svm_set_gif(struct vcpu_svm *svm, bool value);
|
||||
int svm_invoke_exit_handler(struct kvm_vcpu *vcpu, u64 exit_code);
|
||||
void set_msr_interception(struct kvm_vcpu *vcpu, u32 *msrpm, u32 msr,
|
||||
int read, int write);
|
||||
void svm_complete_interrupt_delivery(struct kvm_vcpu *vcpu, int delivery_mode,
|
||||
int trig_mode, int vec);
|
||||
|
||||
/* nested.c */
|
||||
|
||||
@@ -556,17 +558,6 @@ extern struct kvm_x86_nested_ops svm_nested_ops;
|
||||
|
||||
/* avic.c */
|
||||
|
||||
#define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK (0xFF)
|
||||
#define AVIC_LOGICAL_ID_ENTRY_VALID_BIT 31
|
||||
#define AVIC_LOGICAL_ID_ENTRY_VALID_MASK (1 << 31)
|
||||
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK (0xFFULL)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK (0xFFFFFFFFFFULL << 12)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK (1ULL << 62)
|
||||
#define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK (1ULL << 63)
|
||||
|
||||
#define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL
|
||||
|
||||
int avic_ga_log_notifier(u32 ga_tag);
|
||||
void avic_vm_destroy(struct kvm *kvm);
|
||||
int avic_vm_init(struct kvm *kvm);
|
||||
@@ -583,12 +574,12 @@ bool svm_check_apicv_inhibit_reasons(ulong bit);
|
||||
void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
|
||||
void svm_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr);
|
||||
void svm_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr);
|
||||
int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec);
|
||||
bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu);
|
||||
int svm_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
|
||||
uint32_t guest_irq, bool set);
|
||||
void avic_vcpu_blocking(struct kvm_vcpu *vcpu);
|
||||
void avic_vcpu_unblocking(struct kvm_vcpu *vcpu);
|
||||
void avic_ring_doorbell(struct kvm_vcpu *vcpu);
|
||||
|
||||
/* sev.c */
|
||||
|
||||
|
||||
@@ -7659,6 +7659,7 @@ static int vmx_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vmx->nested.nested_run_pending = 1;
|
||||
vmx->nested.smm.guest_mode = false;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -9983,7 +9983,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
||||
* result in virtual interrupt delivery.
|
||||
*/
|
||||
local_irq_disable();
|
||||
vcpu->mode = IN_GUEST_MODE;
|
||||
|
||||
/* Store vcpu->apicv_active before vcpu->mode. */
|
||||
smp_store_release(&vcpu->mode, IN_GUEST_MODE);
|
||||
|
||||
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
|
||||
|
||||
|
||||
@@ -133,32 +133,57 @@ static void kvm_xen_update_runstate(struct kvm_vcpu *v, int state)
|
||||
void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
|
||||
{
|
||||
struct kvm_vcpu_xen *vx = &v->arch.xen;
|
||||
struct gfn_to_hva_cache *ghc = &vx->runstate_cache;
|
||||
struct kvm_memslots *slots = kvm_memslots(v->kvm);
|
||||
bool atomic = (state == RUNSTATE_runnable);
|
||||
uint64_t state_entry_time;
|
||||
unsigned int offset;
|
||||
int __user *user_state;
|
||||
uint64_t __user *user_times;
|
||||
|
||||
kvm_xen_update_runstate(v, state);
|
||||
|
||||
if (!vx->runstate_set)
|
||||
return;
|
||||
|
||||
if (unlikely(slots->generation != ghc->generation || kvm_is_error_hva(ghc->hva)) &&
|
||||
kvm_gfn_to_hva_cache_init(v->kvm, ghc, ghc->gpa, ghc->len))
|
||||
return;
|
||||
|
||||
/* We made sure it fits in a single page */
|
||||
BUG_ON(!ghc->memslot);
|
||||
|
||||
if (atomic)
|
||||
pagefault_disable();
|
||||
|
||||
/*
|
||||
* The only difference between 32-bit and 64-bit versions of the
|
||||
* runstate struct us the alignment of uint64_t in 32-bit, which
|
||||
* means that the 64-bit version has an additional 4 bytes of
|
||||
* padding after the first field 'state'.
|
||||
*
|
||||
* So we use 'int __user *user_state' to point to the state field,
|
||||
* and 'uint64_t __user *user_times' for runstate_entry_time. So
|
||||
* the actual array of time[] in each state starts at user_times[1].
|
||||
*/
|
||||
BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state) != 0);
|
||||
BUILD_BUG_ON(offsetof(struct compat_vcpu_runstate_info, state) != 0);
|
||||
user_state = (int __user *)ghc->hva;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct compat_vcpu_runstate_info) != 0x2c);
|
||||
|
||||
offset = offsetof(struct compat_vcpu_runstate_info, state_entry_time);
|
||||
user_times = (uint64_t __user *)(ghc->hva +
|
||||
offsetof(struct compat_vcpu_runstate_info,
|
||||
state_entry_time));
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* The only difference is alignment of uint64_t in 32-bit.
|
||||
* So the first field 'state' is accessed directly using
|
||||
* offsetof() (where its offset happens to be zero), while the
|
||||
* remaining fields which are all uint64_t, start at 'offset'
|
||||
* which we tweak here by adding 4.
|
||||
*/
|
||||
BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, state_entry_time) !=
|
||||
offsetof(struct compat_vcpu_runstate_info, state_entry_time) + 4);
|
||||
BUILD_BUG_ON(offsetof(struct vcpu_runstate_info, time) !=
|
||||
offsetof(struct compat_vcpu_runstate_info, time) + 4);
|
||||
|
||||
if (v->kvm->arch.xen.long_mode)
|
||||
offset = offsetof(struct vcpu_runstate_info, state_entry_time);
|
||||
user_times = (uint64_t __user *)(ghc->hva +
|
||||
offsetof(struct vcpu_runstate_info,
|
||||
state_entry_time));
|
||||
#endif
|
||||
/*
|
||||
* First write the updated state_entry_time at the appropriate
|
||||
@@ -172,10 +197,8 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
|
||||
BUILD_BUG_ON(sizeof_field(struct compat_vcpu_runstate_info, state_entry_time) !=
|
||||
sizeof(state_entry_time));
|
||||
|
||||
if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
|
||||
&state_entry_time, offset,
|
||||
sizeof(state_entry_time)))
|
||||
return;
|
||||
if (__put_user(state_entry_time, user_times))
|
||||
goto out;
|
||||
smp_wmb();
|
||||
|
||||
/*
|
||||
@@ -189,11 +212,8 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
|
||||
BUILD_BUG_ON(sizeof_field(struct compat_vcpu_runstate_info, state) !=
|
||||
sizeof(vx->current_runstate));
|
||||
|
||||
if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
|
||||
&vx->current_runstate,
|
||||
offsetof(struct vcpu_runstate_info, state),
|
||||
sizeof(vx->current_runstate)))
|
||||
return;
|
||||
if (__put_user(vx->current_runstate, user_state))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Write the actual runstate times immediately after the
|
||||
@@ -208,24 +228,23 @@ void kvm_xen_update_runstate_guest(struct kvm_vcpu *v, int state)
|
||||
BUILD_BUG_ON(sizeof_field(struct vcpu_runstate_info, time) !=
|
||||
sizeof(vx->runstate_times));
|
||||
|
||||
if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
|
||||
&vx->runstate_times[0],
|
||||
offset + sizeof(u64),
|
||||
sizeof(vx->runstate_times)))
|
||||
return;
|
||||
|
||||
if (__copy_to_user(user_times + 1, vx->runstate_times, sizeof(vx->runstate_times)))
|
||||
goto out;
|
||||
smp_wmb();
|
||||
|
||||
/*
|
||||
* Finally, clear the XEN_RUNSTATE_UPDATE bit in the guest's
|
||||
* runstate_entry_time field.
|
||||
*/
|
||||
|
||||
state_entry_time &= ~XEN_RUNSTATE_UPDATE;
|
||||
if (kvm_write_guest_offset_cached(v->kvm, &v->arch.xen.runstate_cache,
|
||||
&state_entry_time, offset,
|
||||
sizeof(state_entry_time)))
|
||||
return;
|
||||
__put_user(state_entry_time, user_times);
|
||||
smp_wmb();
|
||||
|
||||
out:
|
||||
mark_page_dirty_in_slot(v->kvm, ghc->memslot, ghc->gpa >> PAGE_SHIFT);
|
||||
|
||||
if (atomic)
|
||||
pagefault_enable();
|
||||
}
|
||||
|
||||
int __kvm_xen_has_interrupt(struct kvm_vcpu *v)
|
||||
@@ -443,6 +462,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
|
||||
break;
|
||||
}
|
||||
|
||||
/* It must fit within a single page */
|
||||
if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct vcpu_info) > PAGE_SIZE) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
r = kvm_gfn_to_hva_cache_init(vcpu->kvm,
|
||||
&vcpu->arch.xen.vcpu_info_cache,
|
||||
data->u.gpa,
|
||||
@@ -460,6 +485,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
|
||||
break;
|
||||
}
|
||||
|
||||
/* It must fit within a single page */
|
||||
if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct pvclock_vcpu_time_info) > PAGE_SIZE) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
r = kvm_gfn_to_hva_cache_init(vcpu->kvm,
|
||||
&vcpu->arch.xen.vcpu_time_info_cache,
|
||||
data->u.gpa,
|
||||
@@ -481,6 +512,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
|
||||
break;
|
||||
}
|
||||
|
||||
/* It must fit within a single page */
|
||||
if ((data->u.gpa & ~PAGE_MASK) + sizeof(struct vcpu_runstate_info) > PAGE_SIZE) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
r = kvm_gfn_to_hva_cache_init(vcpu->kvm,
|
||||
&vcpu->arch.xen.runstate_cache,
|
||||
data->u.gpa,
|
||||
|
||||
@@ -37,11 +37,11 @@ static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_
|
||||
{
|
||||
union cmd_response cmd_resp;
|
||||
|
||||
/* Get response with status within a max of 800 ms timeout */
|
||||
/* Get response with status within a max of 1600 ms timeout */
|
||||
if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
|
||||
(cmd_resp.response_v2.response == sensor_sts &&
|
||||
cmd_resp.response_v2.status == 0 && (sid == 0xff ||
|
||||
cmd_resp.response_v2.sensor_id == sid)), 500, 800000))
|
||||
cmd_resp.response_v2.sensor_id == sid)), 500, 1600000))
|
||||
return cmd_resp.response_v2.response;
|
||||
|
||||
return SENSOR_DISABLED;
|
||||
@@ -53,6 +53,7 @@ static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sen
|
||||
|
||||
cmd_base.ul = 0;
|
||||
cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR;
|
||||
cmd_base.cmd_v2.intr_disable = 1;
|
||||
cmd_base.cmd_v2.period = info.period;
|
||||
cmd_base.cmd_v2.sensor_id = info.sensor_idx;
|
||||
cmd_base.cmd_v2.length = 16;
|
||||
@@ -70,6 +71,7 @@ static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx)
|
||||
|
||||
cmd_base.ul = 0;
|
||||
cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR;
|
||||
cmd_base.cmd_v2.intr_disable = 1;
|
||||
cmd_base.cmd_v2.period = 0;
|
||||
cmd_base.cmd_v2.sensor_id = sensor_idx;
|
||||
cmd_base.cmd_v2.length = 16;
|
||||
@@ -83,12 +85,51 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
|
||||
union sfh_cmd_base cmd_base;
|
||||
|
||||
cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS;
|
||||
cmd_base.cmd_v2.intr_disable = 1;
|
||||
cmd_base.cmd_v2.period = 0;
|
||||
cmd_base.cmd_v2.sensor_id = 0;
|
||||
|
||||
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
|
||||
}
|
||||
|
||||
static void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
if (readl(privdata->mmio + AMD_P2C_MSG(4))) {
|
||||
writel(0, privdata->mmio + AMD_P2C_MSG(4));
|
||||
writel(0xf, privdata->mmio + AMD_P2C_MSG(5));
|
||||
}
|
||||
}
|
||||
|
||||
static void amd_sfh_clear_intr(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
if (privdata->mp2_ops->clear_intr)
|
||||
privdata->mp2_ops->clear_intr(privdata);
|
||||
}
|
||||
|
||||
static irqreturn_t amd_sfh_irq_handler(int irq, void *data)
|
||||
{
|
||||
amd_sfh_clear_intr(data);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
int rc;
|
||||
|
||||
pci_intx(privdata->pdev, true);
|
||||
|
||||
rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq,
|
||||
amd_sfh_irq_handler, 0, DRIVER_NAME, privdata);
|
||||
if (rc) {
|
||||
dev_err(&privdata->pdev->dev, "failed to request irq %d err=%d\n",
|
||||
privdata->pdev->irq, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
|
||||
{
|
||||
union sfh_cmd_param cmd_param;
|
||||
@@ -193,6 +234,8 @@ static void amd_mp2_pci_remove(void *privdata)
|
||||
struct amd_mp2_dev *mp2 = privdata;
|
||||
amd_sfh_hid_client_deinit(privdata);
|
||||
mp2->mp2_ops->stop_all(mp2);
|
||||
pci_intx(mp2->pdev, false);
|
||||
amd_sfh_clear_intr(mp2);
|
||||
}
|
||||
|
||||
static const struct amd_mp2_ops amd_sfh_ops_v2 = {
|
||||
@@ -200,6 +243,8 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
|
||||
.stop = amd_stop_sensor_v2,
|
||||
.stop_all = amd_stop_all_sensor_v2,
|
||||
.response = amd_sfh_wait_response_v2,
|
||||
.clear_intr = amd_sfh_clear_intr_v2,
|
||||
.init_intr = amd_sfh_irq_init_v2,
|
||||
};
|
||||
|
||||
static const struct amd_mp2_ops amd_sfh_ops = {
|
||||
@@ -225,6 +270,14 @@ static void mp2_select_ops(struct amd_mp2_dev *privdata)
|
||||
}
|
||||
}
|
||||
|
||||
static int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
if (privdata->mp2_ops->init_intr)
|
||||
return privdata->mp2_ops->init_intr(privdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct amd_mp2_dev *privdata;
|
||||
@@ -261,9 +314,20 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
|
||||
|
||||
mp2_select_ops(privdata);
|
||||
|
||||
rc = amd_sfh_hid_client_init(privdata);
|
||||
if (rc)
|
||||
rc = amd_sfh_irq_init(privdata);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "amd_sfh_irq_init failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = amd_sfh_hid_client_init(privdata);
|
||||
if (rc) {
|
||||
amd_sfh_clear_intr(privdata);
|
||||
dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
amd_sfh_clear_intr(privdata);
|
||||
|
||||
return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
|
||||
}
|
||||
@@ -290,6 +354,9 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
|
||||
amd_sfh_clear_intr(mp2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -312,6 +379,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
cancel_delayed_work_sync(&cl_data->work_buffer);
|
||||
amd_sfh_clear_intr(mp2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ union sfh_cmd_base {
|
||||
} s;
|
||||
struct {
|
||||
u32 cmd_id : 4;
|
||||
u32 intr_enable : 1;
|
||||
u32 intr_disable : 1;
|
||||
u32 rsvd1 : 3;
|
||||
u32 length : 7;
|
||||
u32 mem_type : 1;
|
||||
@@ -141,5 +141,7 @@ struct amd_mp2_ops {
|
||||
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
|
||||
void (*stop_all)(struct amd_mp2_dev *privdata);
|
||||
int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
|
||||
void (*clear_intr)(struct amd_mp2_dev *privdata);
|
||||
int (*init_intr)(struct amd_mp2_dev *privdata);
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define HID_USAGE_SENSOR_STATE_READY_ENUM 0x02
|
||||
#define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM 0x05
|
||||
#define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM 0x04
|
||||
#define ILLUMINANCE_MASK GENMASK(14, 0)
|
||||
|
||||
int get_report_descriptor(int sensor_idx, u8 *rep_desc)
|
||||
{
|
||||
@@ -246,7 +247,8 @@ u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_
|
||||
get_common_inputs(&als_input.common_property, report_id);
|
||||
/* For ALS ,V2 Platforms uses C2P_MSG5 register instead of DRAM access method */
|
||||
if (supported_input == V2_STATUS)
|
||||
als_input.illuminance_value = (int)readl(privdata->mmio + AMD_C2P_MSG(5));
|
||||
als_input.illuminance_value =
|
||||
readl(privdata->mmio + AMD_C2P_MSG(5)) & ILLUMINANCE_MASK;
|
||||
else
|
||||
als_input.illuminance_value =
|
||||
(int)sensor_virt_addr[0] / AMD_SFH_FW_MULTIPLIER;
|
||||
|
||||
@@ -691,49 +691,49 @@ static const struct hid_device_id apple_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
|
||||
.driver_data = APPLE_HAS_FN },
|
||||
.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
|
||||
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
|
||||
|
||||
@@ -262,6 +262,7 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
|
||||
return 0;
|
||||
err_free:
|
||||
usb_put_dev(udev);
|
||||
kfree(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1369,6 +1369,7 @@
|
||||
#define USB_VENDOR_ID_UGTIZER 0x2179
|
||||
#define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053
|
||||
#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040 0x0077
|
||||
#define USB_DEVICE_ID_UGTIZER_TABLET_WP5540 0x0004
|
||||
|
||||
#define USB_VENDOR_ID_VIEWSONIC 0x0543
|
||||
#define USB_DEVICE_ID_VIEWSONIC_PD1011 0xe621
|
||||
|
||||
@@ -187,6 +187,7 @@ static const struct hid_device_id hid_quirks[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD), HID_QUIRK_NOGET },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_WP5540), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
|
||||
|
||||
@@ -27,7 +27,6 @@ struct i2c_hid_of_goodix {
|
||||
|
||||
struct regulator *vdd;
|
||||
struct notifier_block nb;
|
||||
struct mutex regulator_mutex;
|
||||
struct gpio_desc *reset_gpio;
|
||||
const struct goodix_i2c_hid_timing_data *timings;
|
||||
};
|
||||
@@ -67,8 +66,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb,
|
||||
container_of(nb, struct i2c_hid_of_goodix, nb);
|
||||
int ret = NOTIFY_OK;
|
||||
|
||||
mutex_lock(&ihid_goodix->regulator_mutex);
|
||||
|
||||
switch (event) {
|
||||
case REGULATOR_EVENT_PRE_DISABLE:
|
||||
gpiod_set_value_cansleep(ihid_goodix->reset_gpio, 1);
|
||||
@@ -87,8 +84,6 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb,
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ihid_goodix->regulator_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -102,8 +97,6 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client,
|
||||
if (!ihid_goodix)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&ihid_goodix->regulator_mutex);
|
||||
|
||||
ihid_goodix->ops.power_up = goodix_i2c_hid_power_up;
|
||||
ihid_goodix->ops.power_down = goodix_i2c_hid_power_down;
|
||||
|
||||
@@ -130,25 +123,28 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client,
|
||||
* long. Holding the controller in reset apparently draws extra
|
||||
* power.
|
||||
*/
|
||||
mutex_lock(&ihid_goodix->regulator_mutex);
|
||||
ihid_goodix->nb.notifier_call = ihid_goodix_vdd_notify;
|
||||
ret = devm_regulator_register_notifier(ihid_goodix->vdd, &ihid_goodix->nb);
|
||||
if (ret) {
|
||||
mutex_unlock(&ihid_goodix->regulator_mutex);
|
||||
if (ret)
|
||||
return dev_err_probe(&client->dev, ret,
|
||||
"regulator notifier request failed\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* If someone else is holding the regulator on (or the regulator is
|
||||
* an always-on one) we might never be told to deassert reset. Do it
|
||||
* now. Here we'll assume that someone else might have _just
|
||||
* barely_ turned the regulator on so we'll do the full
|
||||
* "post_power_delay" just in case.
|
||||
* now... and temporarily bump the regulator reference count just to
|
||||
* make sure it is impossible for this to race with our own notifier!
|
||||
* We also assume that someone else might have _just barely_ turned
|
||||
* the regulator on so we'll do the full "post_power_delay" just in
|
||||
* case.
|
||||
*/
|
||||
if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd))
|
||||
if (ihid_goodix->reset_gpio && regulator_is_enabled(ihid_goodix->vdd)) {
|
||||
ret = regulator_enable(ihid_goodix->vdd);
|
||||
if (ret)
|
||||
return ret;
|
||||
goodix_i2c_hid_deassert_reset(ihid_goodix, true);
|
||||
mutex_unlock(&ihid_goodix->regulator_mutex);
|
||||
regulator_disable(ihid_goodix->vdd);
|
||||
}
|
||||
|
||||
return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "hv_utils_transport.h"
|
||||
|
||||
static DEFINE_SPINLOCK(hvt_list_lock);
|
||||
static struct list_head hvt_list = LIST_HEAD_INIT(hvt_list);
|
||||
static LIST_HEAD(hvt_list);
|
||||
|
||||
static void hvt_reset(struct hvutil_transport *hvt)
|
||||
{
|
||||
|
||||
@@ -2028,8 +2028,10 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
|
||||
kobj->kset = dev->channels_kset;
|
||||
ret = kobject_init_and_add(kobj, &vmbus_chan_ktype, NULL,
|
||||
"%u", relid);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
kobject_put(kobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(kobj, &vmbus_chan_group);
|
||||
|
||||
@@ -2038,6 +2040,7 @@ int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel)
|
||||
* The calling functions' error handling paths will cleanup the
|
||||
* empty channel directory.
|
||||
*/
|
||||
kobject_put(kobj);
|
||||
dev_err(device, "Unable to set up channel sysfs files\n");
|
||||
return ret;
|
||||
}
|
||||
@@ -2079,7 +2082,6 @@ struct hv_device *vmbus_device_create(const guid_t *type,
|
||||
return child_device_obj;
|
||||
}
|
||||
|
||||
static u64 vmbus_dma_mask = DMA_BIT_MASK(64);
|
||||
/*
|
||||
* vmbus_device_register - Register the child device
|
||||
*/
|
||||
@@ -2120,8 +2122,9 @@ int vmbus_device_register(struct hv_device *child_device_obj)
|
||||
}
|
||||
hv_debug_add_dev_dir(child_device_obj);
|
||||
|
||||
child_device_obj->device.dma_mask = &vmbus_dma_mask;
|
||||
child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
|
||||
child_device_obj->device.dma_mask = &child_device_obj->dma_mask;
|
||||
dma_set_mask(&child_device_obj->device, DMA_BIT_MASK(64));
|
||||
return 0;
|
||||
|
||||
err_kset_unregister:
|
||||
|
||||
@@ -1682,32 +1682,32 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req)
|
||||
struct mmc_card *card = mq->card;
|
||||
struct mmc_host *host = card->host;
|
||||
blk_status_t error = BLK_STS_OK;
|
||||
int retries = 0;
|
||||
|
||||
do {
|
||||
u32 status;
|
||||
int err;
|
||||
int retries = 0;
|
||||
|
||||
mmc_blk_rw_rq_prep(mqrq, card, 1, mq);
|
||||
while (retries++ <= MMC_READ_SINGLE_RETRIES) {
|
||||
mmc_blk_rw_rq_prep(mqrq, card, 1, mq);
|
||||
|
||||
mmc_wait_for_req(host, mrq);
|
||||
mmc_wait_for_req(host, mrq);
|
||||
|
||||
err = mmc_send_status(card, &status);
|
||||
if (err)
|
||||
goto error_exit;
|
||||
|
||||
if (!mmc_host_is_spi(host) &&
|
||||
!mmc_ready_for_data(status)) {
|
||||
err = mmc_blk_fix_state(card, req);
|
||||
err = mmc_send_status(card, &status);
|
||||
if (err)
|
||||
goto error_exit;
|
||||
|
||||
if (!mmc_host_is_spi(host) &&
|
||||
!mmc_ready_for_data(status)) {
|
||||
err = mmc_blk_fix_state(card, req);
|
||||
if (err)
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (!mrq->cmd->error)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mrq->cmd->error && retries++ < MMC_READ_SINGLE_RETRIES)
|
||||
continue;
|
||||
|
||||
retries = 0;
|
||||
|
||||
if (mrq->cmd->error ||
|
||||
mrq->data->error ||
|
||||
(!mmc_host_is_spi(host) &&
|
||||
|
||||
@@ -1003,7 +1003,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
|
||||
ioc->usg_calls++;
|
||||
#endif
|
||||
|
||||
while(sg_dma_len(sglist) && nents--) {
|
||||
while (nents && sg_dma_len(sglist)) {
|
||||
|
||||
#ifdef CCIO_COLLECT_STATS
|
||||
ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
|
||||
@@ -1011,6 +1011,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
|
||||
ccio_unmap_page(dev, sg_dma_address(sglist),
|
||||
sg_dma_len(sglist), direction, 0);
|
||||
++sglist;
|
||||
nents--;
|
||||
}
|
||||
|
||||
DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents);
|
||||
|
||||
@@ -1047,7 +1047,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
|
||||
spin_unlock_irqrestore(&ioc->res_lock, flags);
|
||||
#endif
|
||||
|
||||
while (sg_dma_len(sglist) && nents--) {
|
||||
while (nents && sg_dma_len(sglist)) {
|
||||
|
||||
sba_unmap_page(dev, sg_dma_address(sglist), sg_dma_len(sglist),
|
||||
direction, 0);
|
||||
@@ -1056,6 +1056,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
|
||||
ioc->usingle_calls--; /* kluge since call is unmap_sg() */
|
||||
#endif
|
||||
++sglist;
|
||||
nents--;
|
||||
}
|
||||
|
||||
DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents);
|
||||
|
||||
@@ -2155,8 +2155,17 @@ static void hv_pci_assign_numa_node(struct hv_pcibus_device *hbus)
|
||||
if (!hv_dev)
|
||||
continue;
|
||||
|
||||
if (hv_dev->desc.flags & HV_PCI_DEVICE_FLAG_NUMA_AFFINITY)
|
||||
set_dev_node(&dev->dev, hv_dev->desc.virtual_numa_node);
|
||||
if (hv_dev->desc.flags & HV_PCI_DEVICE_FLAG_NUMA_AFFINITY &&
|
||||
hv_dev->desc.virtual_numa_node < num_possible_nodes())
|
||||
/*
|
||||
* The kernel may boot with some NUMA nodes offline
|
||||
* (e.g. in a KDUMP kernel) or with NUMA disabled via
|
||||
* "numa=off". In those cases, adjust the host provided
|
||||
* NUMA node to a valid NUMA node used by the kernel.
|
||||
*/
|
||||
set_dev_node(&dev->dev,
|
||||
numa_map_to_online_node(
|
||||
hv_dev->desc.virtual_numa_node));
|
||||
|
||||
put_pcichild(hv_dev);
|
||||
}
|
||||
|
||||
@@ -6014,9 +6014,8 @@ core_initcall(regulator_init);
|
||||
static int regulator_late_cleanup(struct device *dev, void *data)
|
||||
{
|
||||
struct regulator_dev *rdev = dev_to_rdev(dev);
|
||||
const struct regulator_ops *ops = rdev->desc->ops;
|
||||
struct regulation_constraints *c = rdev->constraints;
|
||||
int enabled, ret;
|
||||
int ret;
|
||||
|
||||
if (c && c->always_on)
|
||||
return 0;
|
||||
@@ -6029,14 +6028,8 @@ static int regulator_late_cleanup(struct device *dev, void *data)
|
||||
if (rdev->use_count)
|
||||
goto unlock;
|
||||
|
||||
/* If we can't read the status assume it's always on. */
|
||||
if (ops->is_enabled)
|
||||
enabled = ops->is_enabled(rdev);
|
||||
else
|
||||
enabled = 1;
|
||||
|
||||
/* But if reading the status failed, assume that it's off. */
|
||||
if (enabled <= 0)
|
||||
/* If reading the status failed, assume that it's off. */
|
||||
if (_regulator_is_enabled(rdev) <= 0)
|
||||
goto unlock;
|
||||
|
||||
if (have_full_constraints()) {
|
||||
|
||||
@@ -1926,7 +1926,7 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty,
|
||||
return false;
|
||||
|
||||
canon_head = smp_load_acquire(&ldata->canon_head);
|
||||
n = min(*nr + 1, canon_head - ldata->read_tail);
|
||||
n = min(*nr, canon_head - ldata->read_tail);
|
||||
|
||||
tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1);
|
||||
size = min_t(size_t, tail + n, N_TTY_BUF_SIZE);
|
||||
@@ -1948,10 +1948,8 @@ static bool canon_copy_from_read_buf(struct tty_struct *tty,
|
||||
n += N_TTY_BUF_SIZE;
|
||||
c = n + found;
|
||||
|
||||
if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) {
|
||||
c = min(*nr, c);
|
||||
if (!found || read_buf(ldata, eol) != __DISABLED_CHAR)
|
||||
n = c;
|
||||
}
|
||||
|
||||
n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu\n",
|
||||
__func__, eol, found, n, c, tail, more);
|
||||
|
||||
@@ -26,7 +26,7 @@ static int __init serial_init_chip(struct parisc_device *dev)
|
||||
unsigned long address;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_IOSAPIC)
|
||||
if (!dev->irq && (dev->id.sversion == 0xad))
|
||||
dev->irq = iosapic_serial_irq(dev);
|
||||
#endif
|
||||
|
||||
@@ -1210,6 +1210,10 @@ static int defrag_collect_targets(struct btrfs_inode *inode,
|
||||
if (em->generation < newer_than)
|
||||
goto next;
|
||||
|
||||
/* This em is under writeback, no need to defrag */
|
||||
if (em->generation == (u64)-1)
|
||||
goto next;
|
||||
|
||||
/*
|
||||
* Our start offset might be in the middle of an existing extent
|
||||
* map, so take that into account.
|
||||
@@ -1629,6 +1633,7 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
if (ra_allocated)
|
||||
|
||||
@@ -4999,6 +4999,10 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
|
||||
lock_page(page);
|
||||
if (!PageUptodate(page)) {
|
||||
unlock_page(page);
|
||||
btrfs_err(fs_info,
|
||||
"send: IO error at offset %llu for inode %llu root %llu",
|
||||
page_offset(page), sctx->cur_ino,
|
||||
sctx->send_root->root_key.objectid);
|
||||
put_page(page);
|
||||
ret = -EIO;
|
||||
break;
|
||||
|
||||
@@ -1981,16 +1981,24 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)
|
||||
static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
/*
|
||||
* We use writeback_inodes_sb here because if we used
|
||||
* We use try_to_writeback_inodes_sb() here because if we used
|
||||
* btrfs_start_delalloc_roots we would deadlock with fs freeze.
|
||||
* Currently are holding the fs freeze lock, if we do an async flush
|
||||
* we'll do btrfs_join_transaction() and deadlock because we need to
|
||||
* wait for the fs freeze lock. Using the direct flushing we benefit
|
||||
* from already being in a transaction and our join_transaction doesn't
|
||||
* have to re-take the fs freeze lock.
|
||||
*
|
||||
* Note that try_to_writeback_inodes_sb() will only trigger writeback
|
||||
* if it can read lock sb->s_umount. It will always be able to lock it,
|
||||
* except when the filesystem is being unmounted or being frozen, but in
|
||||
* those cases sync_filesystem() is called, which results in calling
|
||||
* writeback_inodes_sb() while holding a write lock on sb->s_umount.
|
||||
* Note that we don't call writeback_inodes_sb() directly, because it
|
||||
* will emit a warning if sb->s_umount is not locked.
|
||||
*/
|
||||
if (btrfs_test_opt(fs_info, FLUSHONCOMMIT))
|
||||
writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC);
|
||||
try_to_writeback_inodes_sb(fs_info->sb, WB_REASON_SYNC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1262,6 +1262,7 @@ struct hv_device {
|
||||
struct vmbus_channel *channel;
|
||||
struct kset *channels_kset;
|
||||
struct device_dma_parameters dma_parms;
|
||||
u64 dma_mask;
|
||||
|
||||
/* place holder to keep track of the dir for hv device in debugfs */
|
||||
struct dentry *debug_dir;
|
||||
|
||||
@@ -82,7 +82,6 @@ TEST_GEN_PROGS_x86_64 += x86_64/tsc_msrs_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/vmx_pmu_msrs_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/xen_shinfo_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/xen_vmcall_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/vmx_pi_mmio_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/sev_migrate_tests
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/amx_test
|
||||
TEST_GEN_PROGS_x86_64 += access_tracking_perf_test
|
||||
|
||||
Reference in New Issue
Block a user