Merge tag 's390-5.8-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 25 Jun 2020 16:24:28 +0000 (09:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 25 Jun 2020 16:24:28 +0000 (09:24 -0700)
Pull s390 fixes from Heiko Carstens:

 - Fix kernel crash on system call single stepping.

 - Make sure early program check handler is executed with DAT on to
   avoid an endless program check loop.

 - Add __GFP_NOWARN flag to debug feature to avoid user triggerable
   allocation failure messages.

* tag 's390-5.8-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/debug: avoid kernel warning on too large number of pages
  s390/kasan: fix early pgm check handler execution
  s390: fix system call single stepping

83 files changed:
Documentation/ABI/testing/dev-kmsg
Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
arch/mips/kvm/mips.c
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/mwait.h
arch/x86/kernel/cpu/umwait.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.h
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/mmu/paging_tmpl.h
arch/x86/kvm/svm/svm.c
arch/x86/kvm/vmx/vmcs.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h
arch/x86/kvm/x86.c
drivers/base/regmap/regmap.c
drivers/regulator/Kconfig
drivers/regulator/da9063-regulator.c
drivers/regulator/helpers.c
drivers/regulator/pfuze100-regulator.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-rspi.c
drivers/spi/spi-sprd-adi.c
drivers/spi/spi-stm32-qspi.c
drivers/spi/spidev.c
drivers/vdpa/vdpa.c
drivers/vhost/test.c
drivers/vhost/test.h
drivers/vhost/vdpa.c
drivers/virtio/virtio_mem.c
fs/btrfs/block-group.c
fs/btrfs/ctree.h
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/tree-log.c
fs/erofs/zdata.h
include/sound/dmaengine_pcm.h
include/sound/soc.h
include/uapi/linux/spi/spidev.h
kernel/nsproxy.c
kernel/printk/printk.c
sound/hda/intel-dsp-config.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/codecs/hdac_hda.c
sound/soc/codecs/max98390.c
sound/soc/codecs/rt1015.c
sound/soc/codecs/rt1015.h
sound/soc/codecs/rt5682.c
sound/soc/fsl/fsl_asrc_common.h
sound/soc/fsl/fsl_asrc_dma.c
sound/soc/fsl/fsl_ssi.c
sound/soc/intel/boards/Kconfig
sound/soc/qcom/common.c
sound/soc/qcom/qdsp6/q6afe.c
sound/soc/qcom/qdsp6/q6afe.h
sound/soc/qcom/qdsp6/q6asm.c
sound/soc/rockchip/rockchip_pdm.c
sound/soc/soc-core.c
sound/soc/soc-devres.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/intel/Kconfig
sound/soc/sof/intel/hda-stream.c
sound/soc/sof/sof-pci-dev.c
sound/usb/format.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/quirks.c
tools/spi/spidev_test.c
tools/testing/selftests/pidfd/pidfd.h
tools/testing/selftests/pidfd/pidfd_getfd_test.c
tools/testing/selftests/pidfd/pidfd_setns_test.c
tools/virtio/linux/kernel.h
tools/virtio/linux/virtio.h
tools/virtio/virtio_test.c
tools/virtio/vringh_test.c

index 1e6c28b..f307506 100644 (file)
@@ -56,11 +56,6 @@ Description: The /dev/kmsg character device node provides userspace access
                  seek after the last record available at the time
                  the last SYSLOG_ACTION_CLEAR was issued.
 
-               Due to the record nature of this interface with a "read all"
-               behavior and the specific positions each seek operation sets,
-               SEEK_CUR is not supported, returning -ESPIPE (invalid seek) to
-               errno whenever requested.
-
                The output format consists of a prefix carrying the syslog
                prefix including priority and facility, the 64 bit message
                sequence number and the monotonic timestamp in microseconds,
index 9147df2..38efb50 100644 (file)
@@ -34,12 +34,15 @@ properties:
     maxItems: 1
 
   clocks:
-    maxItems: 1
+    minItems: 1
+    maxItems: 2
+    items:
+      - description: controller register bus clock
+      - description: baud rate generator and delay control clock
 
   clock-names:
-    description: input clock for the baud rate generator
-    items:
-      - const: core
+    minItems: 1
+    maxItems: 2
 
 if:
   properties:
@@ -51,17 +54,22 @@ if:
 then:
   properties:
     clocks:
-      contains:
-        items:
-          - description: controller register bus clock
-          - description: baud rate generator and delay control clock
+      minItems: 2
 
     clock-names:
-      minItems: 2
       items:
         - const: core
         - const: pclk
 
+else:
+  properties:
+    clocks:
+      maxItems: 1
+
+    clock-names:
+      items:
+        - const: core
+
 required:
   - compatible
   - reg
index 521bd58..666d335 100644 (file)
@@ -67,8 +67,10 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        VCPU_STAT("vz_ghfc", vz_ghfc_exits),
        VCPU_STAT("vz_gpa", vz_gpa_exits),
        VCPU_STAT("vz_resvd", vz_resvd_exits),
+#ifdef CONFIG_CPU_LOONGSON64
        VCPU_STAT("vz_cpucfg", vz_cpucfg_exits),
 #endif
+#endif
        VCPU_STAT("halt_successful_poll", halt_successful_poll),
        VCPU_STAT("halt_attempted_poll", halt_attempted_poll),
        VCPU_STAT("halt_poll_invalid", halt_poll_invalid),
index f8998e9..be5363b 100644 (file)
@@ -943,7 +943,7 @@ struct kvm_arch {
        atomic_t vapics_in_nmi_mode;
        struct mutex apic_map_lock;
        struct kvm_apic_map *apic_map;
-       bool apic_map_dirty;
+       atomic_t apic_map_dirty;
 
        bool apic_access_page_done;
        unsigned long apicv_inhibit_reasons;
@@ -1220,7 +1220,7 @@ struct kvm_x86_ops {
        void (*enable_log_dirty_pt_masked)(struct kvm *kvm,
                                           struct kvm_memory_slot *slot,
                                           gfn_t offset, unsigned long mask);
-       int (*write_log_dirty)(struct kvm_vcpu *vcpu);
+       int (*write_log_dirty)(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
 
        /* pmu operations of sub-arch */
        const struct kvm_pmu_ops *pmu_ops;
index 73d997a..e039a93 100644 (file)
@@ -25,8 +25,6 @@
 #define TPAUSE_C01_STATE               1
 #define TPAUSE_C02_STATE               0
 
-u32 get_umwait_control_msr(void);
-
 static inline void __monitor(const void *eax, unsigned long ecx,
                             unsigned long edx)
 {
index 300e3fd..ec8064c 100644 (file)
  */
 static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
 
-u32 get_umwait_control_msr(void)
-{
-       return umwait_control_cached;
-}
-EXPORT_SYMBOL_GPL(get_umwait_control_msr);
-
 /*
  * Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by
  * hardware or BIOS before kernel boot.
index 34a7e05..5bf72fc 100644 (file)
@@ -169,6 +169,18 @@ static void kvm_apic_map_free(struct rcu_head *rcu)
        kvfree(map);
 }
 
+/*
+ * CLEAN -> DIRTY and UPDATE_IN_PROGRESS -> DIRTY changes happen without a lock.
+ *
+ * DIRTY -> UPDATE_IN_PROGRESS and UPDATE_IN_PROGRESS -> CLEAN happen with
+ * apic_map_lock_held.
+ */
+enum {
+       CLEAN,
+       UPDATE_IN_PROGRESS,
+       DIRTY
+};
+
 void kvm_recalculate_apic_map(struct kvm *kvm)
 {
        struct kvm_apic_map *new, *old = NULL;
@@ -176,17 +188,17 @@ void kvm_recalculate_apic_map(struct kvm *kvm)
        int i;
        u32 max_id = 255; /* enough space for any xAPIC ID */
 
-       if (!kvm->arch.apic_map_dirty) {
-               /*
-                * Read kvm->arch.apic_map_dirty before
-                * kvm->arch.apic_map
-                */
-               smp_rmb();
+       /* Read kvm->arch.apic_map_dirty before kvm->arch.apic_map.  */
+       if (atomic_read_acquire(&kvm->arch.apic_map_dirty) == CLEAN)
                return;
-       }
 
        mutex_lock(&kvm->arch.apic_map_lock);
-       if (!kvm->arch.apic_map_dirty) {
+       /*
+        * Read kvm->arch.apic_map_dirty before kvm->arch.apic_map
+        * (if clean) or the APIC registers (if dirty).
+        */
+       if (atomic_cmpxchg_acquire(&kvm->arch.apic_map_dirty,
+                                  DIRTY, UPDATE_IN_PROGRESS) == CLEAN) {
                /* Someone else has updated the map. */
                mutex_unlock(&kvm->arch.apic_map_lock);
                return;
@@ -256,11 +268,11 @@ out:
                        lockdep_is_held(&kvm->arch.apic_map_lock));
        rcu_assign_pointer(kvm->arch.apic_map, new);
        /*
-        * Write kvm->arch.apic_map before
-        * clearing apic->apic_map_dirty
+        * Write kvm->arch.apic_map before clearing apic->apic_map_dirty.
+        * If another update has come in, leave it DIRTY.
         */
-       smp_wmb();
-       kvm->arch.apic_map_dirty = false;
+       atomic_cmpxchg_release(&kvm->arch.apic_map_dirty,
+                              UPDATE_IN_PROGRESS, CLEAN);
        mutex_unlock(&kvm->arch.apic_map_lock);
 
        if (old)
@@ -282,20 +294,20 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
                else
                        static_key_slow_inc(&apic_sw_disabled.key);
 
-               apic->vcpu->kvm->arch.apic_map_dirty = true;
+               atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
        }
 }
 
 static inline void kvm_apic_set_xapic_id(struct kvm_lapic *apic, u8 id)
 {
        kvm_lapic_set_reg(apic, APIC_ID, id << 24);
-       apic->vcpu->kvm->arch.apic_map_dirty = true;
+       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
 }
 
 static inline void kvm_apic_set_ldr(struct kvm_lapic *apic, u32 id)
 {
        kvm_lapic_set_reg(apic, APIC_LDR, id);
-       apic->vcpu->kvm->arch.apic_map_dirty = true;
+       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
 }
 
 static inline u32 kvm_apic_calc_x2apic_ldr(u32 id)
@@ -311,7 +323,7 @@ static inline void kvm_apic_set_x2apic_id(struct kvm_lapic *apic, u32 id)
 
        kvm_lapic_set_reg(apic, APIC_ID, id);
        kvm_lapic_set_reg(apic, APIC_LDR, ldr);
-       apic->vcpu->kvm->arch.apic_map_dirty = true;
+       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
 }
 
 static inline int apic_lvt_enabled(struct kvm_lapic *apic, int lvt_type)
@@ -1976,7 +1988,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
        case APIC_DFR:
                if (!apic_x2apic_mode(apic)) {
                        kvm_lapic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF);
-                       apic->vcpu->kvm->arch.apic_map_dirty = true;
+                       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
                } else
                        ret = 1;
                break;
@@ -2232,7 +2244,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
                        static_key_slow_dec_deferred(&apic_hw_disabled);
                } else {
                        static_key_slow_inc(&apic_hw_disabled.key);
-                       vcpu->kvm->arch.apic_map_dirty = true;
+                       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
                }
        }
 
@@ -2273,7 +2285,6 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
        if (!apic)
                return;
 
-       vcpu->kvm->arch.apic_map_dirty = false;
        /* Stop the timer in case it's a reset to an active apic */
        hrtimer_cancel(&apic->lapic_timer.timer);
 
@@ -2567,6 +2578,7 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
        }
        memcpy(vcpu->arch.apic->regs, s->regs, sizeof(*s));
 
+       atomic_set_release(&apic->vcpu->kvm->arch.apic_map_dirty, DIRTY);
        kvm_recalculate_apic_map(vcpu->kvm);
        kvm_apic_set_version(vcpu);
 
index 0ad06bf..444bb9c 100644 (file)
@@ -222,7 +222,7 @@ void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
 void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
 bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
                                    struct kvm_memory_slot *slot, u64 gfn);
-int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu);
+int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
 
 int kvm_mmu_post_init_vm(struct kvm *kvm);
 void kvm_mmu_pre_destroy_vm(struct kvm *kvm);
index fdd05c2..76817d1 100644 (file)
@@ -1745,10 +1745,10 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
  * Emulate arch specific page modification logging for the
  * nested hypervisor
  */
-int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu)
+int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa)
 {
        if (kvm_x86_ops.write_log_dirty)
-               return kvm_x86_ops.write_log_dirty(vcpu);
+               return kvm_x86_ops.write_log_dirty(vcpu, l2_gpa);
 
        return 0;
 }
index a6d484e..bd70ece 100644 (file)
@@ -235,7 +235,7 @@ static inline unsigned FNAME(gpte_access)(u64 gpte)
 static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
                                             struct kvm_mmu *mmu,
                                             struct guest_walker *walker,
-                                            int write_fault)
+                                            gpa_t addr, int write_fault)
 {
        unsigned level, index;
        pt_element_t pte, orig_pte;
@@ -260,7 +260,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
                                !(pte & PT_GUEST_DIRTY_MASK)) {
                        trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
 #if PTTYPE == PTTYPE_EPT
-                       if (kvm_arch_write_log_dirty(vcpu))
+                       if (kvm_arch_write_log_dirty(vcpu, addr))
                                return -EINVAL;
 #endif
                        pte |= PT_GUEST_DIRTY_MASK;
@@ -360,7 +360,6 @@ retry_walk:
        ++walker->level;
 
        do {
-               gfn_t real_gfn;
                unsigned long host_addr;
 
                pt_access = pte_access;
@@ -375,7 +374,7 @@ retry_walk:
                walker->table_gfn[walker->level - 1] = table_gfn;
                walker->pte_gpa[walker->level - 1] = pte_gpa;
 
-               real_gfn = mmu->translate_gpa(vcpu, gfn_to_gpa(table_gfn),
+               real_gpa = mmu->translate_gpa(vcpu, gfn_to_gpa(table_gfn),
                                              nested_access,
                                              &walker->fault);
 
@@ -389,12 +388,10 @@ retry_walk:
                 * information to fix the exit_qualification or exit_info_1
                 * fields.
                 */
-               if (unlikely(real_gfn == UNMAPPED_GVA))
+               if (unlikely(real_gpa == UNMAPPED_GVA))
                        return 0;
 
-               real_gfn = gpa_to_gfn(real_gfn);
-
-               host_addr = kvm_vcpu_gfn_to_hva_prot(vcpu, real_gfn,
+               host_addr = kvm_vcpu_gfn_to_hva_prot(vcpu, gpa_to_gfn(real_gpa),
                                            &walker->pte_writable[walker->level - 1]);
                if (unlikely(kvm_is_error_hva(host_addr)))
                        goto error;
@@ -457,7 +454,8 @@ retry_walk:
                        (PT_GUEST_DIRTY_SHIFT - PT_GUEST_ACCESSED_SHIFT);
 
        if (unlikely(!accessed_dirty)) {
-               ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker, write_fault);
+               ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker,
+                                                       addr, write_fault);
                if (unlikely(ret < 0))
                        goto error;
                else if (ret)
index 8ccfa41..c0da4dd 100644 (file)
@@ -3344,7 +3344,7 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
 
 void __svm_vcpu_run(unsigned long vmcb_pa, unsigned long *regs);
 
-static fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
+static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
 {
        fastpath_t exit_fastpath;
        struct vcpu_svm *svm = to_svm(vcpu);
index 5c0ff80..7a3675f 100644 (file)
@@ -72,11 +72,24 @@ struct loaded_vmcs {
        struct vmcs_controls_shadow controls_shadow;
 };
 
+static inline bool is_intr_type(u32 intr_info, u32 type)
+{
+       const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK;
+
+       return (intr_info & mask) == (INTR_INFO_VALID_MASK | type);
+}
+
+static inline bool is_intr_type_n(u32 intr_info, u32 type, u8 vector)
+{
+       const u32 mask = INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK |
+                        INTR_INFO_VECTOR_MASK;
+
+       return (intr_info & mask) == (INTR_INFO_VALID_MASK | type | vector);
+}
+
 static inline bool is_exception_n(u32 intr_info, u8 vector)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
-                            INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_HARD_EXCEPTION | vector | INTR_INFO_VALID_MASK);
+       return is_intr_type_n(intr_info, INTR_TYPE_HARD_EXCEPTION, vector);
 }
 
 static inline bool is_debug(u32 intr_info)
@@ -106,28 +119,23 @@ static inline bool is_gp_fault(u32 intr_info)
 
 static inline bool is_machine_check(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
-                            INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_HARD_EXCEPTION | MC_VECTOR | INTR_INFO_VALID_MASK);
+       return is_exception_n(intr_info, MC_VECTOR);
 }
 
 /* Undocumented: icebp/int1 */
 static inline bool is_icebp(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
-               == (INTR_TYPE_PRIV_SW_EXCEPTION | INTR_INFO_VALID_MASK);
+       return is_intr_type(intr_info, INTR_TYPE_PRIV_SW_EXCEPTION);
 }
 
 static inline bool is_nmi(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
-               == (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK);
+       return is_intr_type(intr_info, INTR_TYPE_NMI_INTR);
 }
 
 static inline bool is_external_intr(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK))
-               == (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR);
+       return is_intr_type(intr_info, INTR_TYPE_EXT_INTR);
 }
 
 enum vmcs_field_width {
index 36c7717..cb22f33 100644 (file)
@@ -6606,23 +6606,6 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
                                        msrs[i].host, false);
 }
 
-static void atomic_switch_umwait_control_msr(struct vcpu_vmx *vmx)
-{
-       u32 host_umwait_control;
-
-       if (!vmx_has_waitpkg(vmx))
-               return;
-
-       host_umwait_control = get_umwait_control_msr();
-
-       if (vmx->msr_ia32_umwait_control != host_umwait_control)
-               add_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL,
-                       vmx->msr_ia32_umwait_control,
-                       host_umwait_control, false);
-       else
-               clear_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL);
-}
-
 static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -6728,9 +6711,7 @@ reenter_guest:
 
        pt_guest_enter(vmx);
 
-       if (vcpu_to_pmu(vcpu)->version)
-               atomic_switch_perf_msrs(vmx);
-       atomic_switch_umwait_control_msr(vmx);
+       atomic_switch_perf_msrs(vmx);
 
        if (enable_preemption_timer)
                vmx_update_hv_timer(vcpu);
@@ -7501,11 +7482,11 @@ static void vmx_flush_log_dirty(struct kvm *kvm)
        kvm_flush_pml_buffers(kvm);
 }
 
-static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
+static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa)
 {
        struct vmcs12 *vmcs12;
        struct vcpu_vmx *vmx = to_vmx(vcpu);
-       gpa_t gpa, dst;
+       gpa_t dst;
 
        if (is_guest_mode(vcpu)) {
                WARN_ON_ONCE(vmx->nested.pml_full);
@@ -7524,7 +7505,7 @@ static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
                        return 1;
                }
 
-               gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS) & ~0xFFFull;
+               gpa &= ~0xFFFull;
                dst = vmcs12->pml_address + sizeof(u64) * vmcs12->guest_pml_index;
 
                if (kvm_write_guest_page(vcpu->kvm, gpa_to_gfn(dst), &gpa,
index 8a83b5e..639798e 100644 (file)
@@ -288,8 +288,6 @@ struct vcpu_vmx {
 
        u64 current_tsc_ratio;
 
-       u32 host_pkru;
-
        unsigned long host_debugctlmsr;
 
        /*
index 00c88c2..3b92db4 100644 (file)
@@ -2856,7 +2856,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                return kvm_mtrr_set_msr(vcpu, msr, data);
        case MSR_IA32_APICBASE:
                return kvm_set_apic_base(vcpu, msr_info);
-       case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
+       case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
                return kvm_x2apic_msr_write(vcpu, msr, data);
        case MSR_IA32_TSCDEADLINE:
                kvm_set_lapic_tscdeadline_msr(vcpu, data);
@@ -3196,7 +3196,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_IA32_APICBASE:
                msr_info->data = kvm_get_apic_base(vcpu);
                break;
-       case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
+       case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
                return kvm_x2apic_msr_read(vcpu, msr_info->index, &msr_info->data);
        case MSR_IA32_TSCDEADLINE:
                msr_info->data = kvm_get_lapic_tscdeadline_msr(vcpu);
@@ -4603,7 +4603,8 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = -EINVAL;
                user_tsc_khz = (u32)arg;
 
-               if (user_tsc_khz >= kvm_max_guest_tsc_khz)
+               if (kvm_has_tsc_control &&
+                   user_tsc_khz >= kvm_max_guest_tsc_khz)
                        goto out;
 
                if (user_tsc_khz == 0)
index c472f62..06a7968 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/log2.h>
 #include <linux/hwspinlock.h>
+#include <asm/unaligned.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -249,22 +250,20 @@ static void regmap_format_8(void *buf, unsigned int val, unsigned int shift)
 
 static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift)
 {
-       __be16 *b = buf;
-
-       b[0] = cpu_to_be16(val << shift);
+       put_unaligned_be16(val << shift, buf);
 }
 
 static void regmap_format_16_le(void *buf, unsigned int val, unsigned int shift)
 {
-       __le16 *b = buf;
-
-       b[0] = cpu_to_le16(val << shift);
+       put_unaligned_le16(val << shift, buf);
 }
 
 static void regmap_format_16_native(void *buf, unsigned int val,
                                    unsigned int shift)
 {
-       *(u16 *)buf = val << shift;
+       u16 v = val << shift;
+
+       memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
@@ -280,43 +279,39 @@ static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
 
 static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift)
 {
-       __be32 *b = buf;
-
-       b[0] = cpu_to_be32(val << shift);
+       put_unaligned_be32(val << shift, buf);
 }
 
 static void regmap_format_32_le(void *buf, unsigned int val, unsigned int shift)
 {
-       __le32 *b = buf;
-
-       b[0] = cpu_to_le32(val << shift);
+       put_unaligned_le32(val << shift, buf);
 }
 
 static void regmap_format_32_native(void *buf, unsigned int val,
                                    unsigned int shift)
 {
-       *(u32 *)buf = val << shift;
+       u32 v = val << shift;
+
+       memcpy(buf, &v, sizeof(v));
 }
 
 #ifdef CONFIG_64BIT
 static void regmap_format_64_be(void *buf, unsigned int val, unsigned int shift)
 {
-       __be64 *b = buf;
-
-       b[0] = cpu_to_be64((u64)val << shift);
+       put_unaligned_be64((u64) val << shift, buf);
 }
 
 static void regmap_format_64_le(void *buf, unsigned int val, unsigned int shift)
 {
-       __le64 *b = buf;
-
-       b[0] = cpu_to_le64((u64)val << shift);
+       put_unaligned_le64((u64) val << shift, buf);
 }
 
 static void regmap_format_64_native(void *buf, unsigned int val,
                                    unsigned int shift)
 {
-       *(u64 *)buf = (u64)val << shift;
+       u64 v = (u64) val << shift;
+
+       memcpy(buf, &v, sizeof(v));
 }
 #endif
 
@@ -333,35 +328,34 @@ static unsigned int regmap_parse_8(const void *buf)
 
 static unsigned int regmap_parse_16_be(const void *buf)
 {
-       const __be16 *b = buf;
-
-       return be16_to_cpu(b[0]);
+       return get_unaligned_be16(buf);
 }
 
 static unsigned int regmap_parse_16_le(const void *buf)
 {
-       const __le16 *b = buf;
-
-       return le16_to_cpu(b[0]);
+       return get_unaligned_le16(buf);
 }
 
 static void regmap_parse_16_be_inplace(void *buf)
 {
-       __be16 *b = buf;
+       u16 v = get_unaligned_be16(buf);
 
-       b[0] = be16_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_parse_16_le_inplace(void *buf)
 {
-       __le16 *b = buf;
+       u16 v = get_unaligned_le16(buf);
 
-       b[0] = le16_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static unsigned int regmap_parse_16_native(const void *buf)
 {
-       return *(u16 *)buf;
+       u16 v;
+
+       memcpy(&v, buf, sizeof(v));
+       return v;
 }
 
 static unsigned int regmap_parse_24(const void *buf)
@@ -376,69 +370,67 @@ static unsigned int regmap_parse_24(const void *buf)
 
 static unsigned int regmap_parse_32_be(const void *buf)
 {
-       const __be32 *b = buf;
-
-       return be32_to_cpu(b[0]);
+       return get_unaligned_be32(buf);
 }
 
 static unsigned int regmap_parse_32_le(const void *buf)
 {
-       const __le32 *b = buf;
-
-       return le32_to_cpu(b[0]);
+       return get_unaligned_le32(buf);
 }
 
 static void regmap_parse_32_be_inplace(void *buf)
 {
-       __be32 *b = buf;
+       u32 v = get_unaligned_be32(buf);
 
-       b[0] = be32_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_parse_32_le_inplace(void *buf)
 {
-       __le32 *b = buf;
+       u32 v = get_unaligned_le32(buf);
 
-       b[0] = le32_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static unsigned int regmap_parse_32_native(const void *buf)
 {
-       return *(u32 *)buf;
+       u32 v;
+
+       memcpy(&v, buf, sizeof(v));
+       return v;
 }
 
 #ifdef CONFIG_64BIT
 static unsigned int regmap_parse_64_be(const void *buf)
 {
-       const __be64 *b = buf;
-
-       return be64_to_cpu(b[0]);
+       return get_unaligned_be64(buf);
 }
 
 static unsigned int regmap_parse_64_le(const void *buf)
 {
-       const __le64 *b = buf;
-
-       return le64_to_cpu(b[0]);
+       return get_unaligned_le64(buf);
 }
 
 static void regmap_parse_64_be_inplace(void *buf)
 {
-       __be64 *b = buf;
+       u64 v =  get_unaligned_be64(buf);
 
-       b[0] = be64_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_parse_64_le_inplace(void *buf)
 {
-       __le64 *b = buf;
+       u64 v = get_unaligned_le64(buf);
 
-       b[0] = le64_to_cpu(b[0]);
+       memcpy(buf, &v, sizeof(v));
 }
 
 static unsigned int regmap_parse_64_native(const void *buf)
 {
-       return *(u64 *)buf;
+       u64 v;
+
+       memcpy(&v, buf, sizeof(v));
+       return v;
 }
 #endif
 
@@ -1357,6 +1349,7 @@ void regmap_exit(struct regmap *map)
        if (map->hwlock)
                hwspin_lock_free(map->hwlock);
        kfree_const(map->name);
+       kfree(map->patch);
        kfree(map);
 }
 EXPORT_SYMBOL_GPL(regmap_exit);
@@ -2944,8 +2937,9 @@ EXPORT_SYMBOL_GPL(regmap_update_bits_base);
  * @reg: Register to read from
  * @bits: Bits to test
  *
- * Returns -1 if the underlying regmap_read() fails, 0 if at least one of the
- * tested bits is not set and 1 if all tested bits are set.
+ * Returns 0 if at least one of the tested bits is not set, 1 if all tested
+ * bits are set and a negative error number if the underlying regmap_read()
+ * fails.
  */
 int regmap_test_bits(struct regmap *map, unsigned int reg, unsigned int bits)
 {
index 8f677f5..edb1c4f 100644 (file)
@@ -684,7 +684,7 @@ config REGULATOR_MT6323
 
 config REGULATOR_MT6358
        tristate "MediaTek MT6358 PMIC"
-       depends on MFD_MT6397 && BROKEN
+       depends on MFD_MT6397
        help
          Say y here to select this option to enable the power regulator of
          MediaTek MT6358 PMIC.
index e1d6c8f..fe65b5a 100644 (file)
@@ -512,7 +512,6 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
        },
        {
                DA9063_LDO(DA9063, LDO9, 950, 50, 3600),
-               .suspend = BFIELD(DA9063_REG_LDO9_CONT, DA9063_VLDO9_SEL),
        },
        {
                DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
index e970e9d..e4bb09b 100644 (file)
@@ -486,7 +486,7 @@ int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
                        continue;
                }
 
-               ret = selector + sel;
+               ret = selector + sel - range->min_sel;
 
                voltage = rdev->desc->ops->list_voltage(rdev, ret);
 
index 6895379..4c8e8b4 100644 (file)
@@ -209,6 +209,19 @@ static const struct regulator_ops pfuze100_swb_regulator_ops = {
 
 };
 
+static const struct regulator_ops pfuze3000_sw_regulator_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .list_voltage = regulator_list_voltage_table,
+       .map_voltage = regulator_map_voltage_ascend,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_time_sel = regulator_set_voltage_time_sel,
+       .set_ramp_delay = pfuze100_set_ramp_delay,
+
+};
+
 #define PFUZE100_FIXED_REG(_chip, _name, base, voltage)        \
        [_chip ## _ ## _name] = {       \
                .desc = {       \
@@ -318,23 +331,28 @@ static const struct regulator_ops pfuze100_swb_regulator_ops = {
        .stby_mask = 0x20,      \
 }
 
-
-#define PFUZE3000_SW2_REG(_chip, _name, base, min, max, step)  {       \
-       .desc = {       \
-               .name = #_name,\
-               .n_voltages = ((max) - (min)) / (step) + 1,     \
-               .ops = &pfuze100_sw_regulator_ops,      \
-               .type = REGULATOR_VOLTAGE,      \
-               .id = _chip ## _ ## _name,      \
-               .owner = THIS_MODULE,   \
-               .min_uV = (min),        \
-               .uV_step = (step),      \
-               .vsel_reg = (base) + PFUZE100_VOL_OFFSET,       \
-               .vsel_mask = 0x7,       \
-       },      \
-       .stby_reg = (base) + PFUZE100_STANDBY_OFFSET,   \
-       .stby_mask = 0x7,       \
-}
+/* No linar case for the some switches of PFUZE3000 */
+#define PFUZE3000_SW_REG(_chip, _name, base, mask, voltages)   \
+       [_chip ## _ ##  _name] = {      \
+               .desc = {       \
+                       .name = #_name, \
+                       .n_voltages = ARRAY_SIZE(voltages),     \
+                       .ops = &pfuze3000_sw_regulator_ops,     \
+                       .type = REGULATOR_VOLTAGE,      \
+                       .id = _chip ## _ ## _name,      \
+                       .owner = THIS_MODULE,   \
+                       .volt_table = voltages, \
+                       .vsel_reg = (base) + PFUZE100_VOL_OFFSET,       \
+                       .vsel_mask = (mask),    \
+                       .enable_reg = (base) + PFUZE100_MODE_OFFSET,    \
+                       .enable_mask = 0xf,     \
+                       .enable_val = 0x8,      \
+                       .enable_time = 500,     \
+               },      \
+               .stby_reg = (base) + PFUZE100_STANDBY_OFFSET,   \
+               .stby_mask = (mask),    \
+               .sw_reg = true,         \
+       }
 
 #define PFUZE3000_SW3_REG(_chip, _name, base, min, max, step)  {       \
        .desc = {       \
@@ -391,9 +409,9 @@ static struct pfuze_regulator pfuze200_regulators[] = {
 };
 
 static struct pfuze_regulator pfuze3000_regulators[] = {
-       PFUZE100_SWB_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
+       PFUZE3000_SW_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
        PFUZE100_SW_REG(PFUZE3000, SW1B, PFUZE100_SW1CVOL, 700000, 1475000, 25000),
-       PFUZE100_SWB_REG(PFUZE3000, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
+       PFUZE3000_SW_REG(PFUZE3000, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
        PFUZE3000_SW3_REG(PFUZE3000, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000),
        PFUZE100_SWB_REG(PFUZE3000, SWBST, PFUZE100_SWBSTCON1, 0x3, pfuze100_swbst),
        PFUZE100_SWB_REG(PFUZE3000, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
@@ -407,8 +425,8 @@ static struct pfuze_regulator pfuze3000_regulators[] = {
 };
 
 static struct pfuze_regulator pfuze3001_regulators[] = {
-       PFUZE100_SWB_REG(PFUZE3001, SW1, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
-       PFUZE100_SWB_REG(PFUZE3001, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
+       PFUZE3000_SW_REG(PFUZE3001, SW1, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
+       PFUZE3000_SW_REG(PFUZE3001, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
        PFUZE3000_SW3_REG(PFUZE3001, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000),
        PFUZE100_SWB_REG(PFUZE3001, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
        PFUZE100_VGEN_REG(PFUZE3001, VLDO1, PFUZE100_VGEN1VOL, 1800000, 3300000, 100000),
index a35face..58190c9 100644 (file)
@@ -588,14 +588,14 @@ static void dspi_release_dma(struct fsl_dspi *dspi)
                return;
 
        if (dma->chan_tx) {
-               dma_unmap_single(dma->chan_tx->device->dev, dma->tx_dma_phys,
-                                dma_bufsize, DMA_TO_DEVICE);
+               dma_free_coherent(dma->chan_tx->device->dev, dma_bufsize,
+                                 dma->tx_dma_buf, dma->tx_dma_phys);
                dma_release_channel(dma->chan_tx);
        }
 
        if (dma->chan_rx) {
-               dma_unmap_single(dma->chan_rx->device->dev, dma->rx_dma_phys,
-                                dma_bufsize, DMA_FROM_DEVICE);
+               dma_free_coherent(dma->chan_rx->device->dev, dma_bufsize,
+                                 dma->rx_dma_buf, dma->rx_dma_phys);
                dma_release_channel(dma->chan_rx);
        }
 }
index 06192c9..cbc2387 100644 (file)
 
 struct rspi_data {
        void __iomem *addr;
-       u32 max_speed_hz;
+       u32 speed_hz;
        struct spi_controller *ctlr;
        struct platform_device *pdev;
        wait_queue_head_t wait;
@@ -258,8 +258,7 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
        rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
 
        /* Sets transfer bit rate */
-       spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk),
-                           2 * rspi->max_speed_hz) - 1;
+       spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->speed_hz) - 1;
        rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
 
        /* Disable dummy transmission, set 16-bit word access, 1 frame */
@@ -299,14 +298,14 @@ static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
 
        clksrc = clk_get_rate(rspi->clk);
        while (div < 3) {
-               if (rspi->max_speed_hz >= clksrc/4) /* 4=(CLK/2)/2 */
+               if (rspi->speed_hz >= clksrc/4) /* 4=(CLK/2)/2 */
                        break;
                div++;
                clksrc /= 2;
        }
 
        /* Sets transfer bit rate */
-       spbr = DIV_ROUND_UP(clksrc, 2 * rspi->max_speed_hz) - 1;
+       spbr = DIV_ROUND_UP(clksrc, 2 * rspi->speed_hz) - 1;
        rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
        rspi->spcmd |= div << 2;
 
@@ -341,7 +340,7 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size)
        rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
 
        /* Sets transfer bit rate */
-       spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->max_speed_hz);
+       spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk), 2 * rspi->speed_hz);
        rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
 
        /* Disable dummy transmission, set byte access */
@@ -949,9 +948,24 @@ static int rspi_prepare_message(struct spi_controller *ctlr,
 {
        struct rspi_data *rspi = spi_controller_get_devdata(ctlr);
        struct spi_device *spi = msg->spi;
+       const struct spi_transfer *xfer;
        int ret;
 
-       rspi->max_speed_hz = spi->max_speed_hz;
+       /*
+        * As the Bit Rate Register must not be changed while the device is
+        * active, all transfers in a message must use the same bit rate.
+        * In theory, the sequencer could be enabled, and each Command Register
+        * could divide the base bit rate by a different value.
+        * However, most RSPI variants do not have Transfer Data Length
+        * Multiplier Setting Registers, so each sequence step would be limited
+        * to a single word, making this feature unsuitable for large
+        * transfers, which would gain most from it.
+        */
+       rspi->speed_hz = spi->max_speed_hz;
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               if (xfer->speed_hz < rspi->speed_hz)
+                       rspi->speed_hz = xfer->speed_hz;
+       }
 
        rspi->spcmd = SPCMD_SSLKP;
        if (spi->mode & SPI_CPOL)
index 88e6543..bd23c46 100644 (file)
@@ -389,9 +389,9 @@ static int sprd_adi_restart_handler(struct notifier_block *this,
        sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_CTRL, val);
 
        /* Load the watchdog timeout value, 50ms is always enough. */
+       sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_HIGH, 0);
        sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_LOW,
                       WDG_LOAD_VAL & WDG_LOAD_MASK);
-       sprd_adi_write(sadi, sadi->slave_pbase + REG_WDG_LOAD_HIGH, 0);
 
        /* Start the watchdog to reset system */
        sprd_adi_read(sadi, sadi->slave_pbase + REG_WDG_CTRL, &val);
index 3c44bb2..a900962 100644 (file)
@@ -553,20 +553,6 @@ static const struct spi_controller_mem_ops stm32_qspi_mem_ops = {
        .exec_op = stm32_qspi_exec_op,
 };
 
-static void stm32_qspi_release(struct stm32_qspi *qspi)
-{
-       pm_runtime_get_sync(qspi->dev);
-       /* disable qspi */
-       writel_relaxed(0, qspi->io_base + QSPI_CR);
-       stm32_qspi_dma_free(qspi);
-       mutex_destroy(&qspi->lock);
-       pm_runtime_put_noidle(qspi->dev);
-       pm_runtime_disable(qspi->dev);
-       pm_runtime_set_suspended(qspi->dev);
-       pm_runtime_dont_use_autosuspend(qspi->dev);
-       clk_disable_unprepare(qspi->clk);
-}
-
 static int stm32_qspi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -642,7 +628,7 @@ static int stm32_qspi_probe(struct platform_device *pdev)
        if (IS_ERR(rstc)) {
                ret = PTR_ERR(rstc);
                if (ret == -EPROBE_DEFER)
-                       goto err_qspi_release;
+                       goto err_clk_disable;
        } else {
                reset_control_assert(rstc);
                udelay(2);
@@ -653,7 +639,7 @@ static int stm32_qspi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, qspi);
        ret = stm32_qspi_dma_setup(qspi);
        if (ret)
-               goto err_qspi_release;
+               goto err_dma_free;
 
        mutex_init(&qspi->lock);
 
@@ -673,15 +659,26 @@ static int stm32_qspi_probe(struct platform_device *pdev)
 
        ret = devm_spi_register_master(dev, ctrl);
        if (ret)
-               goto err_qspi_release;
+               goto err_pm_runtime_free;
 
        pm_runtime_mark_last_busy(dev);
        pm_runtime_put_autosuspend(dev);
 
        return 0;
 
-err_qspi_release:
-       stm32_qspi_release(qspi);
+err_pm_runtime_free:
+       pm_runtime_get_sync(qspi->dev);
+       /* disable qspi */
+       writel_relaxed(0, qspi->io_base + QSPI_CR);
+       mutex_destroy(&qspi->lock);
+       pm_runtime_put_noidle(qspi->dev);
+       pm_runtime_disable(qspi->dev);
+       pm_runtime_set_suspended(qspi->dev);
+       pm_runtime_dont_use_autosuspend(qspi->dev);
+err_dma_free:
+       stm32_qspi_dma_free(qspi);
+err_clk_disable:
+       clk_disable_unprepare(qspi->clk);
 err_master_put:
        spi_master_put(qspi->ctrl);
 
@@ -692,7 +689,16 @@ static int stm32_qspi_remove(struct platform_device *pdev)
 {
        struct stm32_qspi *qspi = platform_get_drvdata(pdev);
 
-       stm32_qspi_release(qspi);
+       pm_runtime_get_sync(qspi->dev);
+       /* disable qspi */
+       writel_relaxed(0, qspi->io_base + QSPI_CR);
+       stm32_qspi_dma_free(qspi);
+       mutex_destroy(&qspi->lock);
+       pm_runtime_put_noidle(qspi->dev);
+       pm_runtime_disable(qspi->dev);
+       pm_runtime_set_suspended(qspi->dev);
+       pm_runtime_dont_use_autosuspend(qspi->dev);
+       clk_disable_unprepare(qspi->clk);
 
        return 0;
 }
index d753df7..59e0767 100644 (file)
@@ -609,15 +609,20 @@ err_find_dev:
 static int spidev_release(struct inode *inode, struct file *filp)
 {
        struct spidev_data      *spidev;
+       int                     dofree;
 
        mutex_lock(&device_list_lock);
        spidev = filp->private_data;
        filp->private_data = NULL;
 
+       spin_lock_irq(&spidev->spi_lock);
+       /* ... after we unbound from the underlying device? */
+       dofree = (spidev->spi == NULL);
+       spin_unlock_irq(&spidev->spi_lock);
+
        /* last close? */
        spidev->users--;
        if (!spidev->users) {
-               int             dofree;
 
                kfree(spidev->tx_buffer);
                spidev->tx_buffer = NULL;
@@ -625,19 +630,14 @@ static int spidev_release(struct inode *inode, struct file *filp)
                kfree(spidev->rx_buffer);
                spidev->rx_buffer = NULL;
 
-               spin_lock_irq(&spidev->spi_lock);
-               if (spidev->spi)
-                       spidev->speed_hz = spidev->spi->max_speed_hz;
-
-               /* ... after we unbound from the underlying device? */
-               dofree = (spidev->spi == NULL);
-               spin_unlock_irq(&spidev->spi_lock);
-
                if (dofree)
                        kfree(spidev);
+               else
+                       spidev->speed_hz = spidev->spi->max_speed_hz;
        }
 #ifdef CONFIG_SPI_SLAVE
-       spi_slave_abort(spidev->spi);
+       if (!dofree)
+               spi_slave_abort(spidev->spi);
 #endif
        mutex_unlock(&device_list_lock);
 
@@ -787,13 +787,13 @@ static int spidev_remove(struct spi_device *spi)
 {
        struct spidev_data      *spidev = spi_get_drvdata(spi);
 
+       /* prevent new opens */
+       mutex_lock(&device_list_lock);
        /* make sure ops on existing fds can abort cleanly */
        spin_lock_irq(&spidev->spi_lock);
        spidev->spi = NULL;
        spin_unlock_irq(&spidev->spi_lock);
 
-       /* prevent new opens */
-       mutex_lock(&device_list_lock);
        list_del(&spidev->device_entry);
        device_destroy(spidev_class, spidev->devt);
        clear_bit(MINOR(spidev->devt), minors);
index ff6562f..de211ef 100644 (file)
@@ -63,7 +63,7 @@ static void vdpa_release_dev(struct device *d)
  * @config: the bus operations that is supported by this device
  * @size: size of the parent structure that contains private data
  *
- * Drvier should use vdap_alloc_device() wrapper macro instead of
+ * Driver should use vdpa_alloc_device() wrapper macro instead of
  * using this directly.
  *
  * Returns an error when parent/config/dma_dev is not set or fail to get
index 0466921..a09dedc 100644 (file)
@@ -263,9 +263,62 @@ static int vhost_test_set_features(struct vhost_test *n, u64 features)
        return 0;
 }
 
+static long vhost_test_set_backend(struct vhost_test *n, unsigned index, int fd)
+{
+       static void *backend;
+
+       const bool enable = fd != -1;
+       struct vhost_virtqueue *vq;
+       int r;
+
+       mutex_lock(&n->dev.mutex);
+       r = vhost_dev_check_owner(&n->dev);
+       if (r)
+               goto err;
+
+       if (index >= VHOST_TEST_VQ_MAX) {
+               r = -ENOBUFS;
+               goto err;
+       }
+       vq = &n->vqs[index];
+       mutex_lock(&vq->mutex);
+
+       /* Verify that ring has been setup correctly. */
+       if (!vhost_vq_access_ok(vq)) {
+               r = -EFAULT;
+               goto err_vq;
+       }
+       if (!enable) {
+               vhost_poll_stop(&vq->poll);
+               backend = vhost_vq_get_backend(vq);
+               vhost_vq_set_backend(vq, NULL);
+       } else {
+               vhost_vq_set_backend(vq, backend);
+               r = vhost_vq_init_access(vq);
+               if (r == 0)
+                       r = vhost_poll_start(&vq->poll, vq->kick);
+       }
+
+       mutex_unlock(&vq->mutex);
+
+       if (enable) {
+               vhost_test_flush_vq(n, index);
+       }
+
+       mutex_unlock(&n->dev.mutex);
+       return 0;
+
+err_vq:
+       mutex_unlock(&vq->mutex);
+err:
+       mutex_unlock(&n->dev.mutex);
+       return r;
+}
+
 static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
                             unsigned long arg)
 {
+       struct vhost_vring_file backend;
        struct vhost_test *n = f->private_data;
        void __user *argp = (void __user *)arg;
        u64 __user *featurep = argp;
@@ -277,6 +330,10 @@ static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
                if (copy_from_user(&test, argp, sizeof test))
                        return -EFAULT;
                return vhost_test_run(n, test);
+       case VHOST_TEST_SET_BACKEND:
+               if (copy_from_user(&backend, argp, sizeof backend))
+                       return -EFAULT;
+               return vhost_test_set_backend(n, backend.index, backend.fd);
        case VHOST_GET_FEATURES:
                features = VHOST_FEATURES;
                if (copy_to_user(featurep, &features, sizeof features))
index 7dd265b..822bc4b 100644 (file)
@@ -4,5 +4,6 @@
 
 /* Start a given test on the virtio null device. 0 stops all tests. */
 #define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
+#define VHOST_TEST_SET_BACKEND _IOW(VHOST_VIRTIO, 0x32, int)
 
 #endif
index 7580e34..a54b60d 100644 (file)
@@ -818,7 +818,7 @@ static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma)
        struct vdpa_device *vdpa = v->vdpa;
        const struct vdpa_config_ops *ops = vdpa->config;
        struct vdpa_notification_area notify;
-       int index = vma->vm_pgoff;
+       unsigned long index = vma->vm_pgoff;
 
        if (vma->vm_end - vma->vm_start != PAGE_SIZE)
                return -EINVAL;
index 50c689f..f26f5f6 100644 (file)
@@ -101,6 +101,11 @@ struct virtio_mem {
 
        /* The parent resource for all memory added via this device. */
        struct resource *parent_resource;
+       /*
+        * Copy of "System RAM (virtio_mem)" to be used for
+        * add_memory_driver_managed().
+        */
+       const char *resource_name;
 
        /* Summary of all memory block states. */
        unsigned long nb_mb_state[VIRTIO_MEM_MB_STATE_COUNT];
@@ -414,8 +419,20 @@ static int virtio_mem_mb_add(struct virtio_mem *vm, unsigned long mb_id)
        if (nid == NUMA_NO_NODE)
                nid = memory_add_physaddr_to_nid(addr);
 
+       /*
+        * When force-unloading the driver and we still have memory added to
+        * Linux, the resource name has to stay.
+        */
+       if (!vm->resource_name) {
+               vm->resource_name = kstrdup_const("System RAM (virtio_mem)",
+                                                 GFP_KERNEL);
+               if (!vm->resource_name)
+                       return -ENOMEM;
+       }
+
        dev_dbg(&vm->vdev->dev, "adding memory block: %lu\n", mb_id);
-       return add_memory(nid, addr, memory_block_size_bytes());
+       return add_memory_driver_managed(nid, addr, memory_block_size_bytes(),
+                                        vm->resource_name);
 }
 
 /*
@@ -1192,7 +1209,7 @@ static int virtio_mem_mb_plug_any_sb(struct virtio_mem *vm, unsigned long mb_id,
                                                VIRTIO_MEM_MB_STATE_OFFLINE);
        }
 
-       return rc;
+       return 0;
 }
 
 /*
@@ -1890,10 +1907,12 @@ static void virtio_mem_remove(struct virtio_device *vdev)
            vm->nb_mb_state[VIRTIO_MEM_MB_STATE_OFFLINE_PARTIAL] ||
            vm->nb_mb_state[VIRTIO_MEM_MB_STATE_ONLINE] ||
            vm->nb_mb_state[VIRTIO_MEM_MB_STATE_ONLINE_PARTIAL] ||
-           vm->nb_mb_state[VIRTIO_MEM_MB_STATE_ONLINE_MOVABLE])
+           vm->nb_mb_state[VIRTIO_MEM_MB_STATE_ONLINE_MOVABLE]) {
                dev_warn(&vdev->dev, "device still has system memory added\n");
-       else
+       } else {
                virtio_mem_delete_resource(vm);
+               kfree_const(vm->resource_name);
+       }
 
        /* remove all tracking data - no locking needed */
        vfree(vm->mb_state);
index 176e8a2..c037ef5 100644 (file)
@@ -940,7 +940,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        path = btrfs_alloc_path();
        if (!path) {
                ret = -ENOMEM;
-               goto out_put_group;
+               goto out;
        }
 
        /*
@@ -978,7 +978,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                ret = btrfs_orphan_add(trans, BTRFS_I(inode));
                if (ret) {
                        btrfs_add_delayed_iput(inode);
-                       goto out_put_group;
+                       goto out;
                }
                clear_nlink(inode);
                /* One for the block groups ref */
@@ -1001,13 +1001,13 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
        if (ret < 0)
-               goto out_put_group;
+               goto out;
        if (ret > 0)
                btrfs_release_path(path);
        if (ret == 0) {
                ret = btrfs_del_item(trans, tree_root, path);
                if (ret)
-                       goto out_put_group;
+                       goto out;
                btrfs_release_path(path);
        }
 
@@ -1016,6 +1016,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                 &fs_info->block_group_cache_tree);
        RB_CLEAR_NODE(&block_group->cache_node);
 
+       /* Once for the block groups rbtree */
+       btrfs_put_block_group(block_group);
+
        if (fs_info->first_logical_byte == block_group->start)
                fs_info->first_logical_byte = (u64)-1;
        spin_unlock(&fs_info->block_group_cache_lock);
@@ -1089,6 +1092,25 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        spin_unlock(&block_group->space_info->lock);
 
+       /*
+        * Remove the free space for the block group from the free space tree
+        * and the block group's item from the extent tree before marking the
+        * block group as removed. This is to prevent races with tasks that
+        * freeze and unfreeze a block group, this task and another task
+        * allocating a new block group - the unfreeze task ends up removing
+        * the block group's extent map before the task calling this function
+        * deletes the block group item from the extent tree, allowing for
+        * another task to attempt to create another block group with the same
+        * item key (and failing with -EEXIST and a transaction abort).
+        */
+       ret = remove_block_group_free_space(trans, block_group);
+       if (ret)
+               goto out;
+
+       ret = remove_block_group_item(trans, path, block_group);
+       if (ret < 0)
+               goto out;
+
        mutex_lock(&fs_info->chunk_mutex);
        spin_lock(&block_group->lock);
        block_group->removed = 1;
@@ -1123,17 +1145,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
        mutex_unlock(&fs_info->chunk_mutex);
 
-       ret = remove_block_group_free_space(trans, block_group);
-       if (ret)
-               goto out_put_group;
-
-       /* Once for the block groups rbtree */
-       btrfs_put_block_group(block_group);
-
-       ret = remove_block_group_item(trans, path, block_group);
-       if (ret < 0)
-               goto out;
-
        if (remove_em) {
                struct extent_map_tree *em_tree;
 
@@ -1145,10 +1156,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                free_extent_map(em);
        }
 
-out_put_group:
+out:
        /* Once for the lookup reference */
        btrfs_put_block_group(block_group);
-out:
        if (remove_rsv)
                btrfs_delayed_refs_rsv_release(fs_info, 1);
        btrfs_free_path(path);
index 30ce703..d404cce 100644 (file)
@@ -1009,6 +1009,8 @@ enum {
        BTRFS_ROOT_DEAD_RELOC_TREE,
        /* Mark dead root stored on device whose cleanup needs to be resumed */
        BTRFS_ROOT_DEAD_TREE,
+       /* The root has a log tree. Used only for subvolume roots. */
+       BTRFS_ROOT_HAS_LOG_TREE,
 };
 
 /*
index 2c14312..2520605 100644 (file)
@@ -1533,7 +1533,7 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
 }
 
 static noinline int check_can_nocow(struct btrfs_inode *inode, loff_t pos,
-                                   size_t *write_bytes)
+                                   size_t *write_bytes, bool nowait)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
        struct btrfs_root *root = inode->root;
@@ -1541,27 +1541,43 @@ static noinline int check_can_nocow(struct btrfs_inode *inode, loff_t pos,
        u64 num_bytes;
        int ret;
 
-       if (!btrfs_drew_try_write_lock(&root->snapshot_lock))
+       if (!nowait && !btrfs_drew_try_write_lock(&root->snapshot_lock))
                return -EAGAIN;
 
        lockstart = round_down(pos, fs_info->sectorsize);
        lockend = round_up(pos + *write_bytes,
                           fs_info->sectorsize) - 1;
+       num_bytes = lockend - lockstart + 1;
 
-       btrfs_lock_and_flush_ordered_range(inode, lockstart,
-                                          lockend, NULL);
+       if (nowait) {
+               struct btrfs_ordered_extent *ordered;
+
+               if (!try_lock_extent(&inode->io_tree, lockstart, lockend))
+                       return -EAGAIN;
+
+               ordered = btrfs_lookup_ordered_range(inode, lockstart,
+                                                    num_bytes);
+               if (ordered) {
+                       btrfs_put_ordered_extent(ordered);
+                       ret = -EAGAIN;
+                       goto out_unlock;
+               }
+       } else {
+               btrfs_lock_and_flush_ordered_range(inode, lockstart,
+                                                  lockend, NULL);
+       }
 
-       num_bytes = lockend - lockstart + 1;
        ret = can_nocow_extent(&inode->vfs_inode, lockstart, &num_bytes,
                        NULL, NULL, NULL);
        if (ret <= 0) {
                ret = 0;
-               btrfs_drew_write_unlock(&root->snapshot_lock);
+               if (!nowait)
+                       btrfs_drew_write_unlock(&root->snapshot_lock);
        } else {
                *write_bytes = min_t(size_t, *write_bytes ,
                                     num_bytes - pos + lockstart);
        }
-
+out_unlock:
        unlock_extent(&inode->io_tree, lockstart, lockend);
 
        return ret;
@@ -1633,7 +1649,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
                        if ((BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
                                                      BTRFS_INODE_PREALLOC)) &&
                            check_can_nocow(BTRFS_I(inode), pos,
-                                       &write_bytes) > 0) {
+                                           &write_bytes, false) > 0) {
                                /*
                                 * For nodata cow case, no need to reserve
                                 * data space.
@@ -1904,13 +1920,25 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
        pos = iocb->ki_pos;
        count = iov_iter_count(from);
        if (iocb->ki_flags & IOCB_NOWAIT) {
+               size_t nocow_bytes = count;
+
                /*
                 * We will allocate space in case nodatacow is not set,
                 * so bail
                 */
                if (!(BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
                                              BTRFS_INODE_PREALLOC)) ||
-                   check_can_nocow(BTRFS_I(inode), pos, &count) <= 0) {
+                   check_can_nocow(BTRFS_I(inode), pos, &nocow_bytes,
+                                   true) <= 0) {
+                       inode_unlock(inode);
+                       return -EAGAIN;
+               }
+               /*
+                * There are holes in the range or parts of the range that must
+                * be COWed (shared extents, RO block groups, etc), so just bail
+                * out.
+                */
+               if (nocow_bytes < count) {
                        inode_unlock(inode);
                        return -EAGAIN;
                }
index d04c82c..18d384f 100644 (file)
@@ -985,6 +985,7 @@ static noinline int cow_file_range(struct inode *inode,
        u64 num_bytes;
        unsigned long ram_size;
        u64 cur_alloc_size = 0;
+       u64 min_alloc_size;
        u64 blocksize = fs_info->sectorsize;
        struct btrfs_key ins;
        struct extent_map *em;
@@ -1035,10 +1036,26 @@ static noinline int cow_file_range(struct inode *inode,
        btrfs_drop_extent_cache(BTRFS_I(inode), start,
                        start + num_bytes - 1, 0);
 
+       /*
+        * Relocation relies on the relocated extents to have exactly the same
+        * size as the original extents. Normally writeback for relocation data
+        * extents follows a NOCOW path because relocation preallocates the
+        * extents. However, due to an operation such as scrub turning a block
+        * group to RO mode, it may fallback to COW mode, so we must make sure
+        * an extent allocated during COW has exactly the requested size and can
+        * not be split into smaller extents, otherwise relocation breaks and
+        * fails during the stage where it updates the bytenr of file extent
+        * items.
+        */
+       if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
+               min_alloc_size = num_bytes;
+       else
+               min_alloc_size = fs_info->sectorsize;
+
        while (num_bytes > 0) {
                cur_alloc_size = num_bytes;
                ret = btrfs_reserve_extent(root, cur_alloc_size, cur_alloc_size,
-                                          fs_info->sectorsize, 0, alloc_hint,
+                                          min_alloc_size, 0, alloc_hint,
                                           &ins, 1, 1);
                if (ret < 0)
                        goto out_unlock;
@@ -1361,6 +1378,8 @@ static int fallback_to_cow(struct inode *inode, struct page *locked_page,
                           int *page_started, unsigned long *nr_written)
 {
        const bool is_space_ino = btrfs_is_free_space_inode(BTRFS_I(inode));
+       const bool is_reloc_ino = (BTRFS_I(inode)->root->root_key.objectid ==
+                                  BTRFS_DATA_RELOC_TREE_OBJECTID);
        const u64 range_bytes = end + 1 - start;
        struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
        u64 range_start = start;
@@ -1391,18 +1410,23 @@ static int fallback_to_cow(struct inode *inode, struct page *locked_page,
         *    data space info, which we incremented in the step above.
         *
         * If we need to fallback to cow and the inode corresponds to a free
-        * space cache inode, we must also increment bytes_may_use of the data
-        * space_info for the same reason. Space caches always get a prealloc
+        * space cache inode or an inode of the data relocation tree, we must
+        * also increment bytes_may_use of the data space_info for the same
+        * reason. Space caches and relocated data extents always get a prealloc
         * extent for them, however scrub or balance may have set the block
-        * group that contains that extent to RO mode.
+        * group that contains that extent to RO mode and therefore force COW
+        * when starting writeback.
         */
        count = count_range_bits(io_tree, &range_start, end, range_bytes,
                                 EXTENT_NORESERVE, 0);
-       if (count > 0 || is_space_ino) {
-               const u64 bytes = is_space_ino ? range_bytes : count;
+       if (count > 0 || is_space_ino || is_reloc_ino) {
+               u64 bytes = count;
                struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
                struct btrfs_space_info *sinfo = fs_info->data_sinfo;
 
+               if (is_space_ino || is_reloc_ino)
+                       bytes = range_bytes;
+
                spin_lock(&sinfo->lock);
                btrfs_space_info_update_bytes_may_use(fs_info, sinfo, bytes);
                spin_unlock(&sinfo->lock);
@@ -7865,9 +7889,6 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                        dio_data.overwrite = 1;
                        inode_unlock(inode);
                        relock = true;
-               } else if (iocb->ki_flags & IOCB_NOWAIT) {
-                       ret = -EAGAIN;
-                       goto out;
                }
                ret = btrfs_delalloc_reserve_space(inode, &data_reserved,
                                                   offset, count);
index 168deb8..e8f7c5f 100644 (file)
@@ -2692,7 +2692,7 @@ out:
        btrfs_put_root(root);
 out_free:
        btrfs_free_path(path);
-       kzfree(subvol_info);
+       kfree(subvol_info);
        return ret;
 }
 
index 920cee3..cd5348f 100644 (file)
@@ -169,6 +169,7 @@ static int start_log_trans(struct btrfs_trans_handle *trans,
                if (ret)
                        goto out;
 
+               set_bit(BTRFS_ROOT_HAS_LOG_TREE, &root->state);
                clear_bit(BTRFS_ROOT_MULTI_LOG_TASKS, &root->state);
                root->log_start_pid = current->pid;
        }
@@ -195,6 +196,9 @@ static int join_running_log_trans(struct btrfs_root *root)
 {
        int ret = -ENOENT;
 
+       if (!test_bit(BTRFS_ROOT_HAS_LOG_TREE, &root->state))
+               return ret;
+
        mutex_lock(&root->log_mutex);
        if (root->log_root) {
                ret = 0;
@@ -3303,6 +3307,7 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root)
        if (root->log_root) {
                free_log_tree(trans, root->log_root);
                root->log_root = NULL;
+               clear_bit(BTRFS_ROOT_HAS_LOG_TREE, &root->state);
        }
        return 0;
 }
index 7824f55..9b66c28 100644 (file)
@@ -144,22 +144,22 @@ static inline void z_erofs_onlinepage_init(struct page *page)
 static inline void z_erofs_onlinepage_fixup(struct page *page,
        uintptr_t index, bool down)
 {
-       unsigned long *p, o, v, id;
-repeat:
-       p = &page_private(page);
-       o = READ_ONCE(*p);
+       union z_erofs_onlinepage_converter u = { .v = &page_private(page) };
+       int orig, orig_index, val;
 
-       id = o >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
-       if (id) {
+repeat:
+       orig = atomic_read(u.o);
+       orig_index = orig >> Z_EROFS_ONLINEPAGE_INDEX_SHIFT;
+       if (orig_index) {
                if (!index)
                        return;
 
-               DBG_BUGON(id != index);
+               DBG_BUGON(orig_index != index);
        }
 
-       v = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
-               ((o & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
-       if (cmpxchg(p, o, v) != o)
+       val = (index << Z_EROFS_ONLINEPAGE_INDEX_SHIFT) |
+               ((orig & Z_EROFS_ONLINEPAGE_COUNT_MASK) + (unsigned int)down);
+       if (atomic_cmpxchg(u.o, orig, val) != orig)
                goto repeat;
 }
 
index b652206..8c5e381 100644 (file)
@@ -161,4 +161,15 @@ int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
 
 #define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm"
 
+struct dmaengine_pcm {
+       struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
+       const struct snd_dmaengine_pcm_config *config;
+       struct snd_soc_component component;
+       unsigned int flags;
+};
+
+static inline struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p)
+{
+       return container_of(p, struct dmaengine_pcm, component);
+}
 #endif
index ef5dd28..2756f9b 100644 (file)
@@ -444,6 +444,8 @@ int devm_snd_soc_register_component(struct device *dev,
                         const struct snd_soc_component_driver *component_driver,
                         struct snd_soc_dai_driver *dai_drv, int num_dai);
 void snd_soc_unregister_component(struct device *dev);
+struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev,
+                                                           const char *driver_name);
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
                                                   const char *driver_name);
 
@@ -1361,6 +1363,10 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card,
 struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component,
                                         struct snd_soc_dai_driver *dai_drv,
                                         bool legacy_dai_naming);
+struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev,
+                                             struct snd_soc_component *component,
+                                             struct snd_soc_dai_driver *dai_drv,
+                                             bool legacy_dai_naming);
 void snd_soc_unregister_dai(struct snd_soc_dai *dai);
 
 struct snd_soc_dai *snd_soc_find_dai(
index ee0f246..d56427c 100644 (file)
 #define SPI_TX_QUAD            0x200
 #define SPI_RX_DUAL            0x400
 #define SPI_RX_QUAD            0x800
+#define SPI_CS_WORD            0x1000
+#define SPI_TX_OCTAL           0x2000
+#define SPI_RX_OCTAL           0x4000
+#define SPI_3WIRE_HIZ          0x8000
 
 /*---------------------------------------------------------------------------*/
 
index b03df67..cd35663 100644 (file)
@@ -531,7 +531,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, flags)
        } else if (!IS_ERR(pidfd_pid(file))) {
                err = check_setns_flags(flags);
        } else {
-               err = -EBADF;
+               err = -EINVAL;
        }
        if (err)
                goto out;
index 8c14835..b71eaf5 100644 (file)
@@ -974,16 +974,6 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
                user->idx = log_next_idx;
                user->seq = log_next_seq;
                break;
-       case SEEK_CUR:
-               /*
-                * It isn't supported due to the record nature of this
-                * interface: _SET _DATA and _END point to very specific
-                * record positions, while _CUR would be more useful in case
-                * of a byte-based log. Because of that, return the default
-                * errno value for invalid seek operation.
-                */
-               ret = -ESPIPE;
-               break;
        default:
                ret = -EINVAL;
        }
index 20b8f6c..99aec73 100644 (file)
@@ -208,8 +208,8 @@ static const struct config_entry config_table[] = {
        },
 #endif
 
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE)
 /* Cometlake-LP */
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP)
        {
                .flags = FLAG_SOF,
                .device = 0x02c8,
@@ -240,9 +240,7 @@ static const struct config_entry config_table[] = {
                .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
                .device = 0x02c8,
        },
-#endif
 /* Cometlake-H */
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
        {
                .flags = FLAG_SOF,
                .device = 0x06c8,
index d20aedd..3565e2a 100644 (file)
@@ -2470,6 +2470,9 @@ static const struct pci_device_id azx_ids[] = {
        /* Icelake */
        { PCI_DEVICE(0x8086, 0x34c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* Icelake-H */
+       { PCI_DEVICE(0x8086, 0x3dc8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Jasperlake */
        { PCI_DEVICE(0x8086, 0x38c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
@@ -2478,9 +2481,14 @@ static const struct pci_device_id azx_ids[] = {
        /* Tigerlake */
        { PCI_DEVICE(0x8086, 0xa0c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       /* Tigerlake-H */
+       { PCI_DEVICE(0x8086, 0x43c8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Elkhart Lake */
        { PCI_DEVICE(0x8086, 0x4b55),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       { PCI_DEVICE(0x8086, 0x4b58),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Broxton-P(Apollolake) */
        { PCI_DEVICE(0x8086, 0x5a98),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON },
index fbd7cc6..e2b21ef 100644 (file)
@@ -4145,6 +4145,11 @@ HDA_CODEC_ENTRY(0x10de0095, "GPU 95 HDMI/DP",    patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0097, "GPU 97 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0098, "GPU 98 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de0099, "GPU 99 HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de009a, "GPU 9a HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de009d, "GPU 9d HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de009e, "GPU 9e HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de009f, "GPU 9f HDMI/DP",  patch_nvhdmi),
+HDA_CODEC_ENTRY(0x10de00a0, "GPU a0 HDMI/DP",  patch_nvhdmi),
 HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI",      patch_nvhdmi_2ch),
 HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI",   patch_nvhdmi_2ch),
 HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP",   patch_via_hdmi),
index 6d73f8b..737ef82 100644 (file)
@@ -2461,6 +2461,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
        SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
@@ -7470,6 +7471,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+       SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+       SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
index d8f554f..e6386de 100644 (file)
@@ -342,11 +342,34 @@ static int acp3x_dma_close(struct snd_soc_component *component,
 {
        struct snd_soc_pcm_runtime *prtd;
        struct i2s_dev_data *adata;
+       struct i2s_stream_instance *ins;
 
        prtd = substream->private_data;
        component = snd_soc_rtdcom_lookup(prtd, DRV_NAME);
        adata = dev_get_drvdata(component->dev);
+       ins = substream->runtime->private_data;
+       if (!ins)
+               return -EINVAL;
 
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               switch (ins->i2s_instance) {
+               case I2S_BT_INSTANCE:
+                       adata->play_stream = NULL;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       adata->i2ssp_play_stream = NULL;
+               }
+       } else {
+               switch (ins->i2s_instance) {
+               case I2S_BT_INSTANCE:
+                       adata->capture_stream = NULL;
+                       break;
+               case I2S_SP_INSTANCE:
+               default:
+                       adata->i2ssp_capture_stream = NULL;
+               }
+       }
 
        /* Disable ACP irq, when the current stream is being closed and
         * another stream is also not active.
@@ -354,13 +377,6 @@ static int acp3x_dma_close(struct snd_soc_component *component,
        if (!adata->play_stream && !adata->capture_stream &&
                !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
                rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               adata->play_stream = NULL;
-               adata->i2ssp_play_stream = NULL;
-       } else {
-               adata->capture_stream = NULL;
-               adata->i2ssp_capture_stream = NULL;
-       }
        return 0;
 }
 
index de003ac..473efe9 100644 (file)
@@ -441,13 +441,13 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
        ret = snd_hda_codec_set_name(hcodec, hcodec->preset->name);
        if (ret < 0) {
                dev_err(&hdev->dev, "name failed %s\n", hcodec->preset->name);
-               goto error;
+               goto error_pm;
        }
 
        ret = snd_hdac_regmap_init(&hcodec->core);
        if (ret < 0) {
                dev_err(&hdev->dev, "regmap init failed\n");
-               goto error;
+               goto error_pm;
        }
 
        patch = (hda_codec_patch_t)hcodec->preset->driver_data;
@@ -455,7 +455,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
                ret = patch(hcodec);
                if (ret < 0) {
                        dev_err(&hdev->dev, "patch failed %d\n", ret);
-                       goto error;
+                       goto error_regmap;
                }
        } else {
                dev_dbg(&hdev->dev, "no patch file found\n");
@@ -467,7 +467,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
        ret = snd_hda_codec_parse_pcms(hcodec);
        if (ret < 0) {
                dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);
-               goto error;
+               goto error_regmap;
        }
 
        /* HDMI controls need to be created in machine drivers */
@@ -476,7 +476,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
                if (ret < 0) {
                        dev_err(&hdev->dev, "unable to create controls %d\n",
                                ret);
-                       goto error;
+                       goto error_regmap;
                }
        }
 
@@ -496,7 +496,9 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
 
        return 0;
 
-error:
+error_regmap:
+       snd_hdac_regmap_exit(hdev);
+error_pm:
        pm_runtime_put(&hdev->dev);
 error_no_pm:
        snd_hdac_ext_bus_link_put(hdev->bus, hlink);
@@ -518,6 +520,8 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component)
 
        pm_runtime_disable(&hdev->dev);
        snd_hdac_ext_bus_link_put(hdev->bus, hlink);
+
+       snd_hdac_regmap_exit(hdev);
 }
 
 static const struct snd_soc_dapm_route hdac_hda_dapm_routes[] = {
index 0d63ebf..e6613b5 100644 (file)
@@ -700,8 +700,8 @@ static bool max98390_readable_register(struct device *dev, unsigned int reg)
        case MAX98390_IRQ_CTRL ... MAX98390_WDOG_CTRL:
        case MAX98390_MEAS_ADC_THERM_WARN_THRESH
                ... MAX98390_BROWNOUT_INFINITE_HOLD:
-       case MAX98390_BROWNOUT_LVL_HOLD ... THERMAL_COILTEMP_RD_BACK_BYTE0:
-       case DSMIG_DEBUZZER_THRESHOLD ... MAX98390_R24FF_REV_ID:
+       case MAX98390_BROWNOUT_LVL_HOLD ... DSMIG_DEBUZZER_THRESHOLD:
+       case DSM_VOL_ENA ... MAX98390_R24FF_REV_ID:
                return true;
        default:
                return false;
@@ -717,7 +717,7 @@ static bool max98390_volatile_reg(struct device *dev, unsigned int reg)
        case MAX98390_BROWNOUT_LOWEST_STATUS:
        case MAX98390_ENV_TRACK_BOOST_VOUT_READ:
        case DSM_STBASS_HPF_B0_BYTE0 ... DSM_DEBUZZER_ATTACK_TIME_BYTE2:
-       case THERMAL_RDC_RD_BACK_BYTE1 ... THERMAL_COILTEMP_RD_BACK_BYTE0:
+       case THERMAL_RDC_RD_BACK_BYTE1 ... DSMIG_DEBUZZER_THRESHOLD:
        case DSM_THERMAL_GAIN ... DSM_WBDRC_GAIN:
                return true;
        default:
index 67e2e94..2cccb31 100644 (file)
@@ -34,30 +34,32 @@ static const struct reg_default rt1015_reg[] = {
        { 0x0000, 0x0000 },
        { 0x0004, 0xa000 },
        { 0x0006, 0x0003 },
-       { 0x000a, 0x0802 },
-       { 0x000c, 0x0020 },
+       { 0x000a, 0x081e },
+       { 0x000c, 0x0006 },
        { 0x000e, 0x0000 },
        { 0x0010, 0x0000 },
        { 0x0012, 0x0000 },
+       { 0x0014, 0x0000 },
+       { 0x0016, 0x0000 },
+       { 0x0018, 0x0000 },
        { 0x0020, 0x8000 },
-       { 0x0022, 0x471b },
-       { 0x006a, 0x0000 },
-       { 0x006c, 0x4020 },
+       { 0x0022, 0x8043 },
        { 0x0076, 0x0000 },
        { 0x0078, 0x0000 },
-       { 0x007a, 0x0000 },
+       { 0x007a, 0x0002 },
        { 0x007c, 0x10ec },
        { 0x007d, 0x1015 },
        { 0x00f0, 0x5000 },
-       { 0x00f2, 0x0774 },
-       { 0x00f3, 0x8400 },
+       { 0x00f2, 0x004c },
+       { 0x00f3, 0xecfe },
        { 0x00f4, 0x0000 },
+       { 0x00f6, 0x0400 },
        { 0x0100, 0x0028 },
        { 0x0102, 0xff02 },
-       { 0x0104, 0x8232 },
+       { 0x0104, 0xa213 },
        { 0x0106, 0x200c },
-       { 0x010c, 0x002f },
-       { 0x010e, 0xc000 },
+       { 0x010c, 0x0000 },
+       { 0x010e, 0x0058 },
        { 0x0111, 0x0200 },
        { 0x0112, 0x0400 },
        { 0x0114, 0x0022 },
@@ -65,38 +67,46 @@ static const struct reg_default rt1015_reg[] = {
        { 0x0118, 0x0000 },
        { 0x011a, 0x0123 },
        { 0x011c, 0x4567 },
-       { 0x0300, 0xdddd },
-       { 0x0302, 0x0000 },
-       { 0x0311, 0x9330 },
-       { 0x0313, 0x0000 },
-       { 0x0314, 0x0000 },
+       { 0x0300, 0x203d },
+       { 0x0302, 0x001e },
+       { 0x0311, 0x0000 },
+       { 0x0313, 0x6014 },
+       { 0x0314, 0x00a2 },
        { 0x031a, 0x00a0 },
        { 0x031c, 0x001f },
        { 0x031d, 0xffff },
        { 0x031e, 0x0000 },
        { 0x031f, 0x0000 },
+       { 0x0320, 0x0000 },
        { 0x0321, 0x0000 },
-       { 0x0322, 0x0000 },
-       { 0x0328, 0x0000 },
-       { 0x0329, 0x0000 },
-       { 0x032a, 0x0000 },
-       { 0x032b, 0x0000 },
-       { 0x032c, 0x0000 },
-       { 0x032d, 0x0000 },
-       { 0x032e, 0x030e },
-       { 0x0330, 0x0080 },
+       { 0x0322, 0xd7df },
+       { 0x0328, 0x10b2 },
+       { 0x0329, 0x0175 },
+       { 0x032a, 0x36ad },
+       { 0x032b, 0x7e55 },
+       { 0x032c, 0x0520 },
+       { 0x032d, 0xaa00 },
+       { 0x032e, 0x570e },
+       { 0x0330, 0xe180 },
        { 0x0332, 0x0034 },
-       { 0x0334, 0x0000 },
-       { 0x0336, 0x0000 },
+       { 0x0334, 0x0001 },
+       { 0x0336, 0x0010 },
+       { 0x0338, 0x0000 },
+       { 0x04fa, 0x0030 },
+       { 0x04fc, 0x35c8 },
+       { 0x04fe, 0x0800 },
+       { 0x0500, 0x0400 },
+       { 0x0502, 0x1000 },
+       { 0x0504, 0x0000 },
        { 0x0506, 0x04ff },
-       { 0x0508, 0x0030 },
-       { 0x050a, 0x0018 },
-       { 0x0519, 0x307f },
-       { 0x051a, 0xffff },
-       { 0x051b, 0x4000 },
+       { 0x0508, 0x0010 },
+       { 0x050a, 0x001a },
+       { 0x0519, 0x1c68 },
+       { 0x051a, 0x0ccc },
+       { 0x051b, 0x0666 },
        { 0x051d, 0x0000 },
        { 0x051f, 0x0000 },
-       { 0x0536, 0x1000 },
+       { 0x0536, 0x061c },
        { 0x0538, 0x0000 },
        { 0x053a, 0x0000 },
        { 0x053c, 0x0000 },
@@ -110,19 +120,18 @@ static const struct reg_default rt1015_reg[] = {
        { 0x0544, 0x0000 },
        { 0x0568, 0x0000 },
        { 0x056a, 0x0000 },
-       { 0x1000, 0x0000 },
-       { 0x1002, 0x6505 },
+       { 0x1000, 0x0040 },
+       { 0x1002, 0x5405 },
        { 0x1006, 0x5515 },
-       { 0x1007, 0x003f },
-       { 0x1009, 0x770f },
-       { 0x100a, 0x01ff },
-       { 0x100c, 0x0000 },
+       { 0x1007, 0x05f7 },
+       { 0x1009, 0x0b0a },
+       { 0x100a, 0x00ef },
        { 0x100d, 0x0003 },
        { 0x1010, 0xa433 },
        { 0x1020, 0x0000 },
-       { 0x1200, 0x3d02 },
-       { 0x1202, 0x0813 },
-       { 0x1204, 0x0211 },
+       { 0x1200, 0x5a01 },
+       { 0x1202, 0x6524 },
+       { 0x1204, 0x1f00 },
        { 0x1206, 0x0000 },
        { 0x1208, 0x0000 },
        { 0x120a, 0x0000 },
@@ -130,16 +139,16 @@ static const struct reg_default rt1015_reg[] = {
        { 0x120e, 0x0000 },
        { 0x1210, 0x0000 },
        { 0x1212, 0x0000 },
-       { 0x1300, 0x0701 },
-       { 0x1302, 0x12f9 },
-       { 0x1304, 0x3405 },
+       { 0x1300, 0x10a1 },
+       { 0x1302, 0x12ff },
+       { 0x1304, 0x0400 },
        { 0x1305, 0x0844 },
-       { 0x1306, 0x1611 },
+       { 0x1306, 0x4611 },
        { 0x1308, 0x555e },
        { 0x130a, 0x0000 },
-       { 0x130c, 0x2400},
-       { 0x130e, 0x7700 },
-       { 0x130f, 0x0000 },
+       { 0x130c, 0x2000 },
+       { 0x130e, 0x0100 },
+       { 0x130f, 0x0001 },
        { 0x1310, 0x0000 },
        { 0x1312, 0x0000 },
        { 0x1314, 0x0000 },
@@ -209,6 +218,9 @@ static bool rt1015_volatile_register(struct device *dev, unsigned int reg)
        case RT1015_DC_CALIB_CLSD7:
        case RT1015_DC_CALIB_CLSD8:
        case RT1015_S_BST_TIMING_INTER1:
+       case RT1015_OSCK_STA:
+       case RT1015_MONO_DYNA_CTRL1:
+       case RT1015_MONO_DYNA_CTRL5:
                return true;
 
        default:
@@ -224,6 +236,12 @@ static bool rt1015_readable_register(struct device *dev, unsigned int reg)
        case RT1015_CLK3:
        case RT1015_PLL1:
        case RT1015_PLL2:
+       case RT1015_DUM_RW1:
+       case RT1015_DUM_RW2:
+       case RT1015_DUM_RW3:
+       case RT1015_DUM_RW4:
+       case RT1015_DUM_RW5:
+       case RT1015_DUM_RW6:
        case RT1015_CLK_DET:
        case RT1015_SIL_DET:
        case RT1015_CUSTOMER_ID:
@@ -235,6 +253,7 @@ static bool rt1015_readable_register(struct device *dev, unsigned int reg)
        case RT1015_PAD_DRV2:
        case RT1015_GAT_BOOST:
        case RT1015_PRO_ALT:
+       case RT1015_OSCK_STA:
        case RT1015_MAN_I2C:
        case RT1015_DAC1:
        case RT1015_DAC2:
@@ -272,6 +291,13 @@ static bool rt1015_readable_register(struct device *dev, unsigned int reg)
        case RT1015_SMART_BST_CTRL2:
        case RT1015_ANA_CTRL1:
        case RT1015_ANA_CTRL2:
+       case RT1015_PWR_STATE_CTRL:
+       case RT1015_MONO_DYNA_CTRL:
+       case RT1015_MONO_DYNA_CTRL1:
+       case RT1015_MONO_DYNA_CTRL2:
+       case RT1015_MONO_DYNA_CTRL3:
+       case RT1015_MONO_DYNA_CTRL4:
+       case RT1015_MONO_DYNA_CTRL5:
        case RT1015_SPK_VOL:
        case RT1015_SHORT_DETTOP1:
        case RT1015_SHORT_DETTOP2:
index 6fbe802..8169962 100644 (file)
 #define RT1015_CLK3                            0x0006
 #define RT1015_PLL1                            0x000a
 #define RT1015_PLL2                            0x000c
+#define RT1015_DUM_RW1                         0x000e
+#define RT1015_DUM_RW2                         0x0010
+#define RT1015_DUM_RW3                         0x0012
+#define RT1015_DUM_RW4                         0x0014
+#define RT1015_DUM_RW5                         0x0016
+#define RT1015_DUM_RW6                         0x0018
 #define RT1015_CLK_DET                         0x0020
 #define RT1015_SIL_DET                         0x0022
 #define RT1015_CUSTOMER_ID                     0x0076
@@ -32,6 +38,7 @@
 #define RT1015_PAD_DRV2                                0x00f2
 #define RT1015_GAT_BOOST                       0x00f3
 #define RT1015_PRO_ALT                         0x00f4
+#define RT1015_OSCK_STA                                0x00f6
 #define RT1015_MAN_I2C                         0x0100
 #define RT1015_DAC1                            0x0102
 #define RT1015_DAC2                            0x0104
 #define RT1015_ANA_CTRL1                       0x0334
 #define RT1015_ANA_CTRL2                       0x0336
 #define RT1015_PWR_STATE_CTRL                  0x0338
-#define RT1015_SPK_VOL                         0x0506
+#define RT1015_MONO_DYNA_CTRL                  0x04fa
+#define RT1015_MONO_DYNA_CTRL1                 0x04fc
+#define RT1015_MONO_DYNA_CTRL2                 0x04fe
+#define RT1015_MONO_DYNA_CTRL3                 0x0500
+#define RT1015_MONO_DYNA_CTRL4                 0x0502
+#define RT1015_MONO_DYNA_CTRL5                 0x0504
+#define RT1015_SPK_VOL                                 0x0506
 #define RT1015_SHORT_DETTOP1                   0x0508
 #define RT1015_SHORT_DETTOP2                   0x050a
 #define RT1015_SPK_DC_DETECT1                  0x0519
index d324512..3e9d2c6 100644 (file)
@@ -2829,12 +2829,13 @@ static int rt5682_probe(struct snd_soc_component *component)
                                return ret;
                        }
                        rt5682->mclk = NULL;
-               } else {
-                       /* Register CCF DAI clock control */
-                       ret = rt5682_register_dai_clks(component);
-                       if (ret)
-                               return ret;
                }
+
+               /* Register CCF DAI clock control */
+               ret = rt5682_register_dai_clks(component);
+               if (ret)
+                       return ret;
+
                /* Initial setup for CCF */
                rt5682->lrck[RT5682_AIF1] = CLK_48;
 #endif
index 77665b1..7e1c13c 100644 (file)
@@ -32,6 +32,7 @@ enum asrc_pair_index {
  * @dma_chan: inputer and output DMA channels
  * @dma_data: private dma data
  * @pos: hardware pointer position
+ * @req_dma_chan: flag to release dev_to_dev chan
  * @private: pair private area
  */
 struct fsl_asrc_pair {
@@ -45,6 +46,7 @@ struct fsl_asrc_pair {
        struct dma_chan *dma_chan[2];
        struct imx_dma_data dma_data;
        unsigned int pos;
+       bool req_dma_chan;
 
        void *private;
 };
index d6a3fc5..5f01a58 100644 (file)
@@ -135,6 +135,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
        struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct fsl_asrc_pair *pair = runtime->private_data;
+       struct dma_chan *tmp_chan = NULL, *be_chan = NULL;
+       struct snd_soc_component *component_be = NULL;
        struct fsl_asrc *asrc = pair->asrc;
        struct dma_slave_config config_fe, config_be;
        enum asrc_pair_index index = pair->index;
@@ -142,7 +144,6 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
        int stream = substream->stream;
        struct imx_dma_data *tmp_data;
        struct snd_soc_dpcm *dpcm;
-       struct dma_chan *tmp_chan;
        struct device *dev_be;
        u8 dir = tx ? OUT : IN;
        dma_cap_mask_t mask;
@@ -198,17 +199,29 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
        dma_cap_set(DMA_CYCLIC, mask);
 
        /*
+        * The Back-End device might have already requested a DMA channel,
+        * so try to reuse it first, and then request a new one upon NULL.
+        */
+       component_be = snd_soc_lookup_component_nolocked(dev_be, SND_DMAENGINE_PCM_DRV_NAME);
+       if (component_be) {
+               be_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
+               tmp_chan = be_chan;
+       }
+       if (!tmp_chan)
+               tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+
+       /*
         * An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
         * peripheral, unlike SDMA channel that is allocated dynamically. So no
-        * need to configure dma_request and dma_request2, but get dma_chan via
-        * dma_request_slave_channel directly with dma name of Front-End device
+        * need to configure dma_request and dma_request2, but get dma_chan of
+        * Back-End device directly via dma_request_slave_channel.
         */
        if (!asrc->use_edma) {
                /* Get DMA request of Back-End */
-               tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
                tmp_data = tmp_chan->private;
                pair->dma_data.dma_request = tmp_data->dma_request;
-               dma_release_channel(tmp_chan);
+               if (!be_chan)
+                       dma_release_channel(tmp_chan);
 
                /* Get DMA request of Front-End */
                tmp_chan = asrc->get_dma_channel(pair, dir);
@@ -220,9 +233,11 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
 
                pair->dma_chan[dir] =
                        dma_request_channel(mask, filter, &pair->dma_data);
+               pair->req_dma_chan = true;
        } else {
-               pair->dma_chan[dir] =
-                       asrc->get_dma_channel(pair, dir);
+               pair->dma_chan[dir] = tmp_chan;
+               /* Do not flag to release if we are reusing the Back-End one */
+               pair->req_dma_chan = !be_chan;
        }
 
        if (!pair->dma_chan[dir]) {
@@ -261,7 +276,8 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
        ret = dmaengine_slave_config(pair->dma_chan[dir], &config_be);
        if (ret) {
                dev_err(dev, "failed to config DMA channel for Back-End\n");
-               dma_release_channel(pair->dma_chan[dir]);
+               if (pair->req_dma_chan)
+                       dma_release_channel(pair->dma_chan[dir]);
                return ret;
        }
 
@@ -273,19 +289,22 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
 static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
                                struct snd_pcm_substream *substream)
 {
+       bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct fsl_asrc_pair *pair = runtime->private_data;
+       u8 dir = tx ? OUT : IN;
 
        snd_pcm_set_runtime_buffer(substream, NULL);
 
-       if (pair->dma_chan[IN])
-               dma_release_channel(pair->dma_chan[IN]);
+       if (pair->dma_chan[!dir])
+               dma_release_channel(pair->dma_chan[!dir]);
 
-       if (pair->dma_chan[OUT])
-               dma_release_channel(pair->dma_chan[OUT]);
+       /* release dev_to_dev chan if we aren't reusing the Back-End one */
+       if (pair->dma_chan[dir] && pair->req_dma_chan)
+               dma_release_channel(pair->dma_chan[dir]);
 
-       pair->dma_chan[IN] = NULL;
-       pair->dma_chan[OUT] = NULL;
+       pair->dma_chan[!dir] = NULL;
+       pair->dma_chan[dir] = NULL;
 
        return 0;
 }
index bad89b0..1a2fa7f 100644 (file)
@@ -678,8 +678,9 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
        struct regmap *regs = ssi->regs;
        u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
        unsigned long clkrate, baudrate, tmprate;
-       unsigned int slots = params_channels(hw_params);
-       unsigned int slot_width = 32;
+       unsigned int channels = params_channels(hw_params);
+       unsigned int slot_width = params_width(hw_params);
+       unsigned int slots = 2;
        u64 sub, savesub = 100000;
        unsigned int freq;
        bool baudclk_is_used;
@@ -688,10 +689,14 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream,
        /* Override slots and slot_width if being specifically set... */
        if (ssi->slots)
                slots = ssi->slots;
-       /* ...but keep 32 bits if slots is 2 -- I2S Master mode */
-       if (ssi->slot_width && slots != 2)
+       if (ssi->slot_width)
                slot_width = ssi->slot_width;
 
+       /* ...but force 32 bits for stereo audio using I2S Master Mode */
+       if (channels == 2 &&
+           (ssi->i2s_net & SSI_SCR_I2S_MODE_MASK) == SSI_SCR_I2S_MODE_MASTER)
+               slot_width = 32;
+
        /* Generate bit clock based on the slot number and slot width */
        freq = slots * slot_width * params_rate(hw_params);
 
index a2a5798..5dc489a 100644 (file)
@@ -492,7 +492,7 @@ config SND_SOC_INTEL_SOF_PCM512x_MACH
 
 endif ## SND_SOC_SOF_HDA_LINK || SND_SOC_SOF_BAYTRAIL
 
-if (SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK)
+if (SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK)
 
 config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH
        tristate "CML_LP with DA7219 and MAX98357A in I2S Mode"
@@ -520,7 +520,7 @@ config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH
          Say Y if you have such a device.
          If unsure select "N".
 
-endif ## SND_SOC_SOF_COMETLAKE_LP && SND_SOC_SOF_HDA_LINK
+endif ## SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK
 
 if SND_SOC_SOF_JASPERLAKE
 
index 6c20bdd..8ada4ec 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/module.h>
 #include "common.h"
+#include "qdsp6/q6afe.h"
 
 int qcom_snd_parse_of(struct snd_soc_card *card)
 {
@@ -101,6 +102,15 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
                        }
                        link->no_pcm = 1;
                        link->ignore_pmdown_time = 1;
+
+                       if (q6afe_is_rx_port(link->id)) {
+                               link->dpcm_playback = 1;
+                               link->dpcm_capture = 0;
+                       } else {
+                               link->dpcm_playback = 0;
+                               link->dpcm_capture = 1;
+                       }
+
                } else {
                        dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL);
                        if (!dlc)
@@ -113,12 +123,12 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
                        link->codecs->dai_name = "snd-soc-dummy-dai";
                        link->codecs->name = "snd-soc-dummy";
                        link->dynamic = 1;
+                       link->dpcm_playback = 1;
+                       link->dpcm_capture = 1;
                }
 
                link->ignore_suspend = 1;
                link->nonatomic = 1;
-               link->dpcm_playback = 1;
-               link->dpcm_capture = 1;
                link->stream_name = link->name;
                link++;
 
index e0945f7..0ce4eb6 100644 (file)
@@ -800,6 +800,14 @@ int q6afe_get_port_id(int index)
 }
 EXPORT_SYMBOL_GPL(q6afe_get_port_id);
 
+int q6afe_is_rx_port(int index)
+{
+       if (index < 0 || index >= AFE_PORT_MAX)
+               return -EINVAL;
+
+       return port_maps[index].is_rx;
+}
+EXPORT_SYMBOL_GPL(q6afe_is_rx_port);
 static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt,
                            struct q6afe_port *port)
 {
index c7ed542..1a0f80a 100644 (file)
@@ -198,6 +198,7 @@ int q6afe_port_start(struct q6afe_port *port);
 int q6afe_port_stop(struct q6afe_port *port);
 void q6afe_port_put(struct q6afe_port *port);
 int q6afe_get_port_id(int index);
+int q6afe_is_rx_port(int index);
 void q6afe_hdmi_port_prepare(struct q6afe_port *port,
                            struct q6afe_hdmi_cfg *cfg);
 void q6afe_slim_port_prepare(struct q6afe_port *port,
index 0e0e8f7..ae4b2ca 100644 (file)
@@ -25,6 +25,7 @@
 #define ASM_STREAM_CMD_FLUSH                   0x00010BCE
 #define ASM_SESSION_CMD_PAUSE                  0x00010BD3
 #define ASM_DATA_CMD_EOS                       0x00010BDB
+#define ASM_DATA_EVENT_RENDERED_EOS            0x00010C1C
 #define ASM_NULL_POPP_TOPOLOGY                 0x00010C68
 #define ASM_STREAM_CMD_FLUSH_READBUFS          0x00010C09
 #define ASM_STREAM_CMD_SET_ENCDEC_PARAM                0x00010C10
@@ -622,9 +623,6 @@ static int32_t q6asm_stream_callback(struct apr_device *adev,
                case ASM_SESSION_CMD_SUSPEND:
                        client_event = ASM_CLIENT_EVENT_CMD_SUSPEND_DONE;
                        break;
-               case ASM_DATA_CMD_EOS:
-                       client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE;
-                       break;
                case ASM_STREAM_CMD_FLUSH:
                        client_event = ASM_CLIENT_EVENT_CMD_FLUSH_DONE;
                        break;
@@ -728,6 +726,9 @@ static int32_t q6asm_stream_callback(struct apr_device *adev,
                }
 
                break;
+       case ASM_DATA_EVENT_RENDERED_EOS:
+               client_event = ASM_CLIENT_EVENT_CMD_EOS_DONE;
+               break;
        }
 
        if (ac->cb)
index 7cd42fc..1707414 100644 (file)
@@ -590,8 +590,10 @@ static int rockchip_pdm_resume(struct device *dev)
        int ret;
 
        ret = pm_runtime_get_sync(dev);
-       if (ret < 0)
+       if (ret < 0) {
+               pm_runtime_put(dev);
                return ret;
+       }
 
        ret = regcache_sync(pdm->regmap);
 
index 7b38720..0f30f5a 100644 (file)
@@ -310,7 +310,7 @@ struct snd_soc_component *snd_soc_rtdcom_lookup(struct snd_soc_pcm_runtime *rtd,
 }
 EXPORT_SYMBOL_GPL(snd_soc_rtdcom_lookup);
 
-static struct snd_soc_component
+struct snd_soc_component
 *snd_soc_lookup_component_nolocked(struct device *dev, const char *driver_name)
 {
        struct snd_soc_component *component;
@@ -329,6 +329,7 @@ static struct snd_soc_component
 
        return found_component;
 }
+EXPORT_SYMBOL_GPL(snd_soc_lookup_component_nolocked);
 
 struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
                                                   const char *driver_name)
index a9ea172..11e5d79 100644 (file)
@@ -9,6 +9,43 @@
 #include <sound/soc.h>
 #include <sound/dmaengine_pcm.h>
 
+static void devm_dai_release(struct device *dev, void *res)
+{
+       snd_soc_unregister_dai(*(struct snd_soc_dai **)res);
+}
+
+/**
+ * devm_snd_soc_register_dai - resource-managed dai registration
+ * @dev: Device used to manage component
+ * @component: The component the DAIs are registered for
+ * @dai_drv: DAI driver to use for the DAI
+ * @legacy_dai_naming: if %true, use legacy single-name format;
+ *     if %false, use multiple-name format;
+ */
+struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev,
+                                             struct snd_soc_component *component,
+                                             struct snd_soc_dai_driver *dai_drv,
+                                             bool legacy_dai_naming)
+{
+       struct snd_soc_dai **ptr;
+       struct snd_soc_dai *dai;
+
+       ptr = devres_alloc(devm_dai_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return NULL;
+
+       dai = snd_soc_register_dai(component, dai_drv, legacy_dai_naming);
+       if (dai) {
+               *ptr = dai;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return dai;
+}
+EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai);
+
 static void devm_component_release(struct device *dev, void *res)
 {
        snd_soc_unregister_component(*(struct device **)res);
index f728309..80a4e71 100644 (file)
  */
 #define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(31)
 
-struct dmaengine_pcm {
-       struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1];
-       const struct snd_dmaengine_pcm_config *config;
-       struct snd_soc_component component;
-       unsigned int flags;
-};
-
-static struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p)
-{
-       return container_of(p, struct dmaengine_pcm, component);
-}
-
 static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm,
        struct snd_pcm_substream *substream)
 {
index 2c114b4..c517064 100644 (file)
@@ -2630,15 +2630,15 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new)
        int count, paths;
        int ret;
 
+       if (!fe->dai_link->dynamic)
+               return 0;
+
        if (fe->num_cpus > 1) {
                dev_err(fe->dev,
                        "%s doesn't support Multi CPU yet\n", __func__);
                return -EINVAL;
        }
 
-       if (!fe->dai_link->dynamic)
-               return 0;
-
        /* only check active links */
        if (!snd_soc_dai_active(asoc_rtd_to_cpu(fe, 0)))
                return 0;
index 9e89633..43e5745 100644 (file)
@@ -1851,7 +1851,7 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
        list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list);
 
        /* register the DAI to the component */
-       dai = snd_soc_register_dai(tplg->comp, dai_drv, false);
+       dai = devm_snd_soc_register_dai(tplg->comp->dev, tplg->comp, dai_drv, false);
        if (!dai)
                return -ENOMEM;
 
@@ -1859,7 +1859,6 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
        ret = snd_soc_dapm_new_dai_widgets(dapm, dai);
        if (ret != 0) {
                dev_err(dai->dev, "Failed to create DAI widgets %d\n", ret);
-               snd_soc_unregister_dai(dai);
                return ret;
        }
 
index c9a2bee..3aaf25e 100644 (file)
@@ -25,8 +25,7 @@ config SND_SOC_SOF_INTEL_PCI
        select SND_SOC_SOF_CANNONLAKE  if SND_SOC_SOF_CANNONLAKE_SUPPORT
        select SND_SOC_SOF_COFFEELAKE  if SND_SOC_SOF_COFFEELAKE_SUPPORT
        select SND_SOC_SOF_ICELAKE     if SND_SOC_SOF_ICELAKE_SUPPORT
-       select SND_SOC_SOF_COMETLAKE_LP if SND_SOC_SOF_COMETLAKE_LP_SUPPORT
-       select SND_SOC_SOF_COMETLAKE_H if SND_SOC_SOF_COMETLAKE_H_SUPPORT
+       select SND_SOC_SOF_COMETLAKE   if SND_SOC_SOF_COMETLAKE_SUPPORT
        select SND_SOC_SOF_TIGERLAKE   if SND_SOC_SOF_TIGERLAKE_SUPPORT
        select SND_SOC_SOF_ELKHARTLAKE if SND_SOC_SOF_ELKHARTLAKE_SUPPORT
        select SND_SOC_SOF_JASPERLAKE  if SND_SOC_SOF_JASPERLAKE_SUPPORT
@@ -201,34 +200,22 @@ config SND_SOC_SOF_ICELAKE
          This option is not user-selectable but automagically handled by
          'select' statements at a higher level
 
-config SND_SOC_SOF_COMETLAKE_LP
+config SND_SOC_SOF_COMETLAKE
        tristate
        select SND_SOC_SOF_HDA_COMMON
        help
          This option is not user-selectable but automagically handled by
          'select' statements at a higher level
 
-config SND_SOC_SOF_COMETLAKE_LP_SUPPORT
-       bool "SOF support for CometLake-LP"
-       help
-         This adds support for Sound Open Firmware for Intel(R) platforms
-         using the Cometlake-LP processors.
-         Say Y if you have such a device.
-         If unsure select "N".
+config SND_SOC_SOF_COMETLAKE_SUPPORT
+       bool
 
-config SND_SOC_SOF_COMETLAKE_H
-       tristate
-       select SND_SOC_SOF_HDA_COMMON
-       help
-         This option is not user-selectable but automagically handled by
-         'select' statements at a higher level
-
-config SND_SOC_SOF_COMETLAKE_H_SUPPORT
-       bool "SOF support for CometLake-H"
+config SND_SOC_SOF_COMETLAKE_LP_SUPPORT
+       bool "SOF support for CometLake"
+       select SND_SOC_SOF_COMETLAKE_SUPPORT
        help
          This adds support for Sound Open Firmware for Intel(R) platforms
-         using the Cometlake-H processors.
-         Say Y if you have such a device.
+         using the Cometlake processors.
          If unsure select "N".
 
 config SND_SOC_SOF_TIGERLAKE_SUPPORT
index 7f65dcc..1bda14c 100644 (file)
@@ -653,11 +653,16 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context)
                if (status & AZX_INT_CTRL_EN) {
                        rirb_status = snd_hdac_chip_readb(bus, RIRBSTS);
                        if (rirb_status & RIRB_INT_MASK) {
+                               /*
+                                * Clearing the interrupt status here ensures
+                                * that no interrupt gets masked after the RIRB
+                                * wp is read in snd_hdac_bus_update_rirb.
+                                */
+                               snd_hdac_chip_writeb(bus, RIRBSTS,
+                                                    RIRB_INT_MASK);
                                active = true;
                                if (rirb_status & RIRB_INT_RESPONSE)
                                        snd_hdac_bus_update_rirb(bus);
-                               snd_hdac_chip_writeb(bus, RIRBSTS,
-                                                    RIRB_INT_MASK);
                        }
                }
 #endif
index b13697d..aa3532b 100644 (file)
@@ -151,9 +151,7 @@ static const struct sof_dev_desc cfl_desc = {
 };
 #endif
 
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP) || \
-       IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
-
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE)
 static const struct sof_dev_desc cml_desc = {
        .machines               = snd_soc_acpi_intel_cml_machines,
        .alt_machines           = snd_soc_acpi_intel_cml_sdw_machines,
@@ -411,8 +409,11 @@ static const struct pci_device_id sof_pci_ids[] = {
                .driver_data = (unsigned long)&cfl_desc},
 #endif
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ICELAKE)
-       { PCI_DEVICE(0x8086, 0x34C8),
+       { PCI_DEVICE(0x8086, 0x34C8), /* ICL-LP */
+               .driver_data = (unsigned long)&icl_desc},
+       { PCI_DEVICE(0x8086, 0x3dc8), /* ICL-H */
                .driver_data = (unsigned long)&icl_desc},
+
 #endif
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_JASPERLAKE)
        { PCI_DEVICE(0x8086, 0x38c8),
@@ -420,17 +421,20 @@ static const struct pci_device_id sof_pci_ids[] = {
        { PCI_DEVICE(0x8086, 0x4dc8),
                .driver_data = (unsigned long)&jsl_desc},
 #endif
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_LP)
-       { PCI_DEVICE(0x8086, 0x02c8),
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE)
+       { PCI_DEVICE(0x8086, 0x02c8), /* CML-LP */
                .driver_data = (unsigned long)&cml_desc},
-#endif
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMETLAKE_H)
-       { PCI_DEVICE(0x8086, 0x06c8),
+       { PCI_DEVICE(0x8086, 0x06c8), /* CML-H */
+               .driver_data = (unsigned long)&cml_desc},
+       { PCI_DEVICE(0x8086, 0xa3f0), /* CML-S */
                .driver_data = (unsigned long)&cml_desc},
 #endif
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_TIGERLAKE)
-       { PCI_DEVICE(0x8086, 0xa0c8),
+       { PCI_DEVICE(0x8086, 0xa0c8), /* TGL-LP */
+               .driver_data = (unsigned long)&tgl_desc},
+       { PCI_DEVICE(0x8086, 0x43c8), /* TGL-H */
                .driver_data = (unsigned long)&tgl_desc},
+
 #endif
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_ELKHARTLAKE)
        { PCI_DEVICE(0x8086, 0x4b55),
index 5ffb457..1b28d01 100644 (file)
@@ -394,8 +394,9 @@ skip_rate:
        return nr_rates;
 }
 
-/* Line6 Helix series don't support the UAC2_CS_RANGE usb function
- * call. Return a static table of known clock rates.
+/* Line6 Helix series and the Rode Rodecaster Pro don't support the
+ * UAC2_CS_RANGE usb function call. Return a static table of known
+ * clock rates.
  */
 static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip,
                                                struct audioformat *fp)
@@ -408,6 +409,7 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip,
        case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */
        case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */
        case USB_ID(0x0e41, 0x424a): /* Line6 Helix LT >= fw 2.82 */
+       case USB_ID(0x19f7, 0x0011): /* Rode Rodecaster Pro */
                return set_fixed_rate(fp, 48000, SNDRV_PCM_RATE_48000);
        }
 
index 15769f2..eab0fd4 100644 (file)
@@ -581,8 +581,9 @@ static int check_matrix_bitmap(unsigned char *bmap,
  * if failed, give up and free the control instance.
  */
 
-int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
-                             struct snd_kcontrol *kctl)
+int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list,
+                          struct snd_kcontrol *kctl,
+                          bool is_std_info)
 {
        struct usb_mixer_interface *mixer = list->mixer;
        int err;
@@ -596,6 +597,7 @@ int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
                return err;
        }
        list->kctl = kctl;
+       list->is_std_info = is_std_info;
        list->next_id_elem = mixer->id_elems[list->id];
        mixer->id_elems[list->id] = list;
        return 0;
@@ -3234,8 +3236,11 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
        unitid = delegate_notify(mixer, unitid, NULL, NULL);
 
        for_each_mixer_elem(list, mixer, unitid) {
-               struct usb_mixer_elem_info *info =
-                       mixer_elem_list_to_info(list);
+               struct usb_mixer_elem_info *info;
+
+               if (!list->is_std_info)
+                       continue;
+               info = mixer_elem_list_to_info(list);
                /* invalidate cache, so the value is read from the device */
                info->cached = 0;
                snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
@@ -3315,6 +3320,8 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
 
                if (!list->kctl)
                        continue;
+               if (!list->is_std_info)
+                       continue;
 
                info = mixer_elem_list_to_info(list);
                if (count > 1 && info->control != control)
index 41ec9dc..c29e27a 100644 (file)
@@ -66,6 +66,7 @@ struct usb_mixer_elem_list {
        struct usb_mixer_elem_list *next_id_elem; /* list of controls with same id */
        struct snd_kcontrol *kctl;
        unsigned int id;
+       bool is_std_info;
        usb_mixer_elem_dump_func_t dump;
        usb_mixer_elem_resume_func_t resume;
 };
@@ -103,8 +104,12 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
 int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
                                int request, int validx, int value_set);
 
-int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
-                             struct snd_kcontrol *kctl);
+int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list,
+                          struct snd_kcontrol *kctl,
+                          bool is_std_info);
+
+#define snd_usb_mixer_add_control(list, kctl) \
+       snd_usb_mixer_add_list(list, kctl, true)
 
 void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
                                 struct usb_mixer_interface *mixer,
index b6bcf2f..cec1cfd 100644 (file)
@@ -158,7 +158,8 @@ static int add_single_ctl_with_resume(struct usb_mixer_interface *mixer,
                return -ENOMEM;
        }
        kctl->private_free = snd_usb_mixer_elem_free;
-       return snd_usb_mixer_add_control(list, kctl);
+       /* don't use snd_usb_mixer_add_control() here, this is a special list element */
+       return snd_usb_mixer_add_list(list, kctl, false);
 }
 
 /*
index 8a05dcb..a777d36 100644 (file)
@@ -367,6 +367,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                ifnum = 0;
                goto add_sync_ep_from_ifnum;
        case USB_ID(0x07fd, 0x0008): /* MOTU M Series */
+       case USB_ID(0x31e9, 0x0002): /* Solid State Logic SSL2+ */
                ep = 0x81;
                ifnum = 2;
                goto add_sync_ep_from_ifnum;
@@ -1786,6 +1787,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
                return 0;
        case SNDRV_PCM_TRIGGER_STOP:
                stop_endpoints(subs);
+               subs->data_endpoint->retire_data_urb = NULL;
                subs->running = 0;
                return 0;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
index bca0179..fca7273 100644 (file)
@@ -1532,6 +1532,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
 static bool is_itf_usb_dsd_dac(unsigned int id)
 {
        switch (id) {
+       case USB_ID(0x154e, 0x1002): /* Denon DCD-1500RE */
        case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */
        case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
        case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
@@ -1673,6 +1674,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
             chip->usb_id == USB_ID(0x0951, 0x16ad)) &&
            (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
                usleep_range(1000, 2000);
+
+       /*
+        * Samsung USBC Headset (AKG) need a tiny delay after each
+        * class compliant request. (Model number: AAM625R or AAM627R)
+        */
+       if (chip->usb_id == USB_ID(0x04e8, 0xa051) &&
+           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+               usleep_range(5000, 6000);
 }
 
 /*
@@ -1856,6 +1865,7 @@ struct registration_quirk {
 static const struct registration_quirk registration_quirks[] = {
        REG_QUIRK_ENTRY(0x0951, 0x16d8, 2),     /* Kingston HyperX AMP */
        REG_QUIRK_ENTRY(0x0951, 0x16ed, 2),     /* Kingston HyperX Cloud Alpha S */
+       REG_QUIRK_ENTRY(0x0951, 0x16ea, 2),     /* Kingston HyperX Cloud Flight S */
        { 0 }                                   /* terminator */
 };
 
index eec23fa..83844f8 100644 (file)
@@ -47,7 +47,7 @@ static int transfer_size;
 static int iterations;
 static int interval = 5; /* interval in seconds for showing transfer rate */
 
-uint8_t default_tx[] = {
+static uint8_t default_tx[] = {
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
        0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -56,8 +56,8 @@ uint8_t default_tx[] = {
        0xF0, 0x0D,
 };
 
-uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
-char *input_tx;
+static uint8_t default_rx[ARRAY_SIZE(default_tx)] = {0, };
+static char *input_tx;
 
 static void hex_dump(const void *src, size_t length, size_t line_size,
                     char *prefix)
@@ -461,8 +461,8 @@ int main(int argc, char *argv[])
                pabort("can't get max speed hz");
 
        printf("spi mode: 0x%x\n", mode);
-       printf("bits per word: %d\n", bits);
-       printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
+       printf("bits per word: %u\n", bits);
+       printf("max speed: %u Hz (%u kHz)\n", speed, speed/1000);
 
        if (input_tx)
                transfer_escaped_string(fd, input_tx);
index c1921a5..8d728ed 100644 (file)
@@ -95,4 +95,9 @@ static inline int sys_pidfd_getfd(int pidfd, int fd, int flags)
        return syscall(__NR_pidfd_getfd, pidfd, fd, flags);
 }
 
+static inline int sys_memfd_create(const char *name, unsigned int flags)
+{
+       return syscall(__NR_memfd_create, name, flags);
+}
+
 #endif /* __PIDFD_H */
index 401a7c1..84b65ec 100644 (file)
@@ -34,11 +34,6 @@ static int sys_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1,
        return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
 }
 
-static int sys_memfd_create(const char *name, unsigned int flags)
-{
-       return syscall(__NR_memfd_create, name, flags);
-}
-
 static int __child(int sk, int memfd)
 {
        int ret;
index 133ec5b..9418108 100644 (file)
@@ -470,4 +470,16 @@ TEST_F(current_nsset, no_foul_play)
        }
 }
 
+TEST(setns_einval)
+{
+       int fd;
+
+       fd = sys_memfd_create("rostock", 0);
+       EXPECT_GT(fd, 0);
+
+       ASSERT_NE(setns(fd, 0), 0);
+       EXPECT_EQ(errno, EINVAL);
+       close(fd);
+}
+
 TEST_HARNESS_MAIN
index 6683b4a..caab980 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <linux/list.h>
 #include <linux/printk.h>
 #include <linux/bug.h>
 #include <errno.h>
@@ -135,10 +136,4 @@ static inline void free_page(unsigned long addr)
        (void) (&_min1 == &_min2);              \
        _min1 < _min2 ? _min1 : _min2; })
 
-/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
-#define list_add_tail(a, b) do {} while (0)
-#define list_del(a) do {} while (0)
-#define list_for_each_entry(a, b, c) while (0)
-/* end of stubs */
-
 #endif /* KERNEL_H */
index b751350..5d90254 100644 (file)
@@ -11,12 +11,11 @@ struct device {
 struct virtio_device {
        struct device dev;
        u64 features;
+       struct list_head vqs;
 };
 
 struct virtqueue {
-       /* TODO: commented as list macros are empty stubs for now.
-        * Broken but enough for virtio_ring.c
-        * struct list_head list; */
+       struct list_head list;
        void (*callback)(struct virtqueue *vq);
        const char *name;
        struct virtio_device *vdev;
index b427def..cb3f29c 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #define _GNU_SOURCE
 #include <getopt.h>
+#include <limits.h>
 #include <string.h>
 #include <poll.h>
 #include <sys/eventfd.h>
@@ -18,6 +19,8 @@
 #include <linux/virtio_ring.h>
 #include "../../drivers/vhost/test.h"
 
+#define RANDOM_BATCH -1
+
 /* Unused */
 void *__kmalloc_fake, *__kfree_ignore_start, *__kfree_ignore_end;
 
@@ -43,6 +46,10 @@ struct vdev_info {
        struct vhost_memory *mem;
 };
 
+static const struct vhost_vring_file no_backend = { .fd = -1 },
+                                    backend = { .fd = 1 };
+static const struct vhost_vring_state null_state = {};
+
 bool vq_notify(struct virtqueue *vq)
 {
        struct vq_info *info = vq->priv;
@@ -88,6 +95,19 @@ void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info)
        assert(r >= 0);
 }
 
+static void vq_reset(struct vq_info *info, int num, struct virtio_device *vdev)
+{
+       if (info->vq)
+               vring_del_virtqueue(info->vq);
+
+       memset(info->ring, 0, vring_size(num, 4096));
+       vring_init(&info->vring, num, info->ring, 4096);
+       info->vq = __vring_new_virtqueue(info->idx, info->vring, vdev, true,
+                                        false, vq_notify, vq_callback, "test");
+       assert(info->vq);
+       info->vq->priv = info;
+}
+
 static void vq_info_add(struct vdev_info *dev, int num)
 {
        struct vq_info *info = &dev->vqs[dev->nvqs];
@@ -97,14 +117,7 @@ static void vq_info_add(struct vdev_info *dev, int num)
        info->call = eventfd(0, EFD_NONBLOCK);
        r = posix_memalign(&info->ring, 4096, vring_size(num, 4096));
        assert(r >= 0);
-       memset(info->ring, 0, vring_size(num, 4096));
-       vring_init(&info->vring, num, info->ring, 4096);
-       info->vq = vring_new_virtqueue(info->idx,
-                                      info->vring.num, 4096, &dev->vdev,
-                                      true, false, info->ring,
-                                      vq_notify, vq_callback, "test");
-       assert(info->vq);
-       info->vq->priv = info;
+       vq_reset(info, num, &dev->vdev);
        vhost_vq_setup(dev, info);
        dev->fds[info->idx].fd = info->call;
        dev->fds[info->idx].events = POLLIN;
@@ -116,6 +129,7 @@ static void vdev_info_init(struct vdev_info* dev, unsigned long long features)
        int r;
        memset(dev, 0, sizeof *dev);
        dev->vdev.features = features;
+       INIT_LIST_HEAD(&dev->vdev.vqs);
        dev->buf_size = 1024;
        dev->buf = malloc(dev->buf_size);
        assert(dev->buf);
@@ -152,41 +166,93 @@ static void wait_for_interrupt(struct vdev_info *dev)
 }
 
 static void run_test(struct vdev_info *dev, struct vq_info *vq,
-                    bool delayed, int bufs)
+                    bool delayed, int batch, int reset_n, int bufs)
 {
        struct scatterlist sl;
-       long started = 0, completed = 0;
-       long completed_before;
+       long started = 0, completed = 0, next_reset = reset_n;
+       long completed_before, started_before;
        int r, test = 1;
        unsigned len;
        long long spurious = 0;
+       const bool random_batch = batch == RANDOM_BATCH;
+
        r = ioctl(dev->control, VHOST_TEST_RUN, &test);
        assert(r >= 0);
+       if (!reset_n) {
+               next_reset = INT_MAX;
+       }
+
        for (;;) {
                virtqueue_disable_cb(vq->vq);
                completed_before = completed;
+               started_before = started;
                do {
-                       if (started < bufs) {
+                       const bool reset = completed > next_reset;
+                       if (random_batch)
+                               batch = (random() % vq->vring.num) + 1;
+
+                       while (started < bufs &&
+                              (started - completed) < batch) {
                                sg_init_one(&sl, dev->buf, dev->buf_size);
                                r = virtqueue_add_outbuf(vq->vq, &sl, 1,
                                                         dev->buf + started,
                                                         GFP_ATOMIC);
-                               if (likely(r == 0)) {
-                                       ++started;
-                                       if (unlikely(!virtqueue_kick(vq->vq)))
+                               if (unlikely(r != 0)) {
+                                       if (r == -ENOSPC &&
+                                           started > started_before)
+                                               r = 0;
+                                       else
                                                r = -1;
+                                       break;
                                }
-                       } else
+
+                               ++started;
+
+                               if (unlikely(!virtqueue_kick(vq->vq))) {
+                                       r = -1;
+                                       break;
+                               }
+                       }
+
+                       if (started >= bufs)
                                r = -1;
 
+                       if (reset) {
+                               r = ioctl(dev->control, VHOST_TEST_SET_BACKEND,
+                                         &no_backend);
+                               assert(!r);
+                       }
+
                        /* Flush out completed bufs if any */
-                       if (virtqueue_get_buf(vq->vq, &len)) {
+                       while (virtqueue_get_buf(vq->vq, &len)) {
                                ++completed;
                                r = 0;
                        }
 
+                       if (reset) {
+                               struct vhost_vring_state s = { .index = 0 };
+
+                               vq_reset(vq, vq->vring.num, &dev->vdev);
+
+                               r = ioctl(dev->control, VHOST_GET_VRING_BASE,
+                                         &s);
+                               assert(!r);
+
+                               s.num = 0;
+                               r = ioctl(dev->control, VHOST_SET_VRING_BASE,
+                                         &null_state);
+                               assert(!r);
+
+                               r = ioctl(dev->control, VHOST_TEST_SET_BACKEND,
+                                         &backend);
+                               assert(!r);
+
+                               started = completed;
+                               while (completed > next_reset)
+                                       next_reset += completed;
+                       }
                } while (r == 0);
-               if (completed == completed_before)
+               if (completed == completed_before && started == started_before)
                        ++spurious;
                assert(completed <= bufs);
                assert(started <= bufs);
@@ -203,7 +269,9 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
        test = 0;
        r = ioctl(dev->control, VHOST_TEST_RUN, &test);
        assert(r >= 0);
-       fprintf(stderr, "spurious wakeups: 0x%llx\n", spurious);
+       fprintf(stderr,
+               "spurious wakeups: 0x%llx started=0x%lx completed=0x%lx\n",
+               spurious, started, completed);
 }
 
 const char optstring[] = "h";
@@ -245,6 +313,16 @@ const struct option longopts[] = {
                .val = 'd',
        },
        {
+               .name = "batch",
+               .val = 'b',
+               .has_arg = required_argument,
+       },
+       {
+               .name = "reset",
+               .val = 'r',
+               .has_arg = optional_argument,
+       },
+       {
        }
 };
 
@@ -255,6 +333,8 @@ static void help(void)
                " [--no-event-idx]"
                " [--no-virtio-1]"
                " [--delayed-interrupt]"
+               " [--batch=random/N]"
+               " [--reset=N]"
                "\n");
 }
 
@@ -263,6 +343,7 @@ int main(int argc, char **argv)
        struct vdev_info dev;
        unsigned long long features = (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
                (1ULL << VIRTIO_RING_F_EVENT_IDX) | (1ULL << VIRTIO_F_VERSION_1);
+       long batch = 1, reset = 0;
        int o;
        bool delayed = false;
 
@@ -289,6 +370,24 @@ int main(int argc, char **argv)
                case 'D':
                        delayed = true;
                        break;
+               case 'b':
+                       if (0 == strcmp(optarg, "random")) {
+                               batch = RANDOM_BATCH;
+                       } else {
+                               batch = strtol(optarg, NULL, 10);
+                               assert(batch > 0);
+                               assert(batch < (long)INT_MAX + 1);
+                       }
+                       break;
+               case 'r':
+                       if (!optarg) {
+                               reset = 1;
+                       } else {
+                               reset = strtol(optarg, NULL, 10);
+                               assert(reset > 0);
+                               assert(reset < (long)INT_MAX + 1);
+                       }
+                       break;
                default:
                        assert(0);
                        break;
@@ -298,6 +397,6 @@ int main(int argc, char **argv)
 done:
        vdev_info_init(&dev, features);
        vq_info_add(&dev, 256);
-       run_test(&dev, &dev.vqs[0], delayed, 0x100000);
+       run_test(&dev, &dev.vqs[0], delayed, batch, reset, 0x100000);
        return 0;
 }
index 2936534..fa87b58 100644 (file)
@@ -307,6 +307,7 @@ static int parallel_test(u64 features,
                close(to_host[0]);
 
                gvdev.vdev.features = features;
+               INIT_LIST_HEAD(&gvdev.vdev.vqs);
                gvdev.to_host_fd = to_host[1];
                gvdev.notifies = 0;
 
@@ -453,6 +454,7 @@ int main(int argc, char *argv[])
 
        getrange = getrange_iov;
        vdev.features = 0;
+       INIT_LIST_HEAD(&vdev.vqs);
 
        while (argv[1]) {
                if (strcmp(argv[1], "--indirect") == 0)