Merge branch 'drm-fixes-5.1' of git://people.freedesktop.org/~agd5f/linux into drm...
authorDave Airlie <airlied@redhat.com>
Wed, 17 Apr 2019 20:56:26 +0000 (06:56 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 17 Apr 2019 20:56:35 +0000 (06:56 +1000)
- GPUVM fixes for vega/RV and shadow buffers
- TTM fixes for hugepages
- TTM fix for refcount imbalance in error path
- DC AUX fix for some active DP-DVI dongles
- DC fix for multihead VT switch regression

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexdeucher@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190415051703.3377-1-alexander.deucher@amd.com
197 files changed:
.clang-format
MAINTAINERS
Makefile
arch/arm64/include/asm/futex.h
arch/arm64/include/asm/module.h
arch/arm64/kernel/ftrace.c
arch/arm64/kernel/traps.c
arch/mips/configs/generic/board-ocelot.config
arch/mips/kernel/kgdb.c
arch/mips/sgi-ip27/ip27-irq.c
arch/powerpc/include/asm/mmu.h
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/vdso32/gettimeofday.S
arch/sparc/kernel/pci_sun4v.c
arch/x86/events/amd/core.c
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/include/asm/bitops.h
arch/x86/kernel/cpu/resctrl/rdtgroup.c
arch/xtensa/include/asm/processor.h
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/stacktrace.c
arch/xtensa/mm/mmu.c
block/bfq-iosched.c
block/bfq-iosched.h
block/bfq-wf2q.c
block/bio.c
block/blk-mq.c
drivers/acpi/acpica/nsobject.c
drivers/block/virtio_blk.c
drivers/bluetooth/btusb.c
drivers/char/tpm/eventlog/tpm2.c
drivers/char/tpm/tpm-dev-common.c
drivers/char/tpm/tpm-interface.c
drivers/clk/at91/clk-programmable.c
drivers/clk/at91/pmc.h
drivers/clk/at91/sama5d2.c
drivers/clk/imx/clk-pll14xx.c
drivers/clk/mediatek/clk-gate.c
drivers/clk/meson/clk-pll.c
drivers/clk/meson/g12a.c
drivers/clk/meson/gxbb.c
drivers/clk/meson/vid-pll-div.c
drivers/clk/x86/clk-pmc-atom.c
drivers/crypto/caam/caamhash.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/icl_dsi.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/vlv_dsi.c
drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c
drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
drivers/gpu/drm/sun4i/sun8i_tcon_top.c
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/host1x/hw/channel_hw.c
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/qp.c
drivers/infiniband/hw/hfi1/rc.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/hns/hns_roce_hem.c
drivers/infiniband/hw/hns/hns_roce_mr.c
drivers/infiniband/hw/hns/hns_roce_qp.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
drivers/iommu/amd_iommu_init.c
drivers/irqchip/irq-ls1x.c
drivers/lightnvm/pblk-read.c
drivers/mmc/host/alcor.c
drivers/mmc/host/sdhci-omap.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/realtek/r8169.c
drivers/net/vrf.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/target/admin-cmd.c
drivers/nvme/target/discovery.c
drivers/nvme/target/nvmet.h
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/quirks.c
drivers/platform/x86/pmc_atom.c
drivers/scsi/csiostor/csio_scsi.c
drivers/scsi/virtio_scsi.c
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_ring.c
fs/aio.c
fs/block_dev.c
fs/btrfs/ioctl.c
fs/btrfs/props.c
fs/fuse/dev.c
fs/io_uring.c
fs/nfs/nfs42proc.c
fs/nfs/nfs4file.c
fs/nfs/nfs4xdr.c
fs/nfs/super.c
fs/pipe.c
fs/splice.c
include/drm/drm_modeset_helper_vtables.h
include/keys/trusted.h
include/linux/bio.h
include/linux/blk-mq.h
include/linux/bvec.h
include/linux/kernel.h
include/linux/mm.h
include/linux/nvme.h
include/linux/pipe_fs_i.h
include/linux/platform_data/x86/clk-pmc-atom.h
include/linux/sunrpc/sched.h
include/linux/virtio_ring.h
include/net/nfc/nci_core.h
include/sound/soc.h
include/uapi/linux/ethtool.h
include/uapi/sound/asound.h
kernel/dma/debug.c
kernel/events/core.c
kernel/events/ring_buffer.c
kernel/irq/chip.c
kernel/irq/irqdesc.c
kernel/locking/lockdep.c
kernel/sched/fair.c
kernel/time/alarmtimer.c
kernel/trace/trace.c
lib/iov_iter.c
mm/gup.c
mm/hugetlb.c
mm/slab.c
net/ipv4/ip_gre.c
net/ipv6/ip6_gre.c
net/nfc/nci/hci.c
net/sunrpc/clnt.c
net/sunrpc/xprtrdma/verbs.c
security/apparmor/lsm.c
security/keys/trusted.c
sound/core/seq/seq_clientmgr.c
sound/hda/ext/hdac_ext_bus.c
sound/hda/hdac_bus.c
sound/hda/hdac_component.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/Kconfig
sound/soc/codecs/ab8500-codec.c
sound/soc/codecs/cs35l35.c
sound/soc/codecs/cs4270.c
sound/soc/codecs/hdac_hda.c
sound/soc/codecs/hdac_hda.h
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/nau8810.c
sound/soc/codecs/nau8824.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/tlv320aic32x4-i2c.c
sound/soc/codecs/tlv320aic32x4-spi.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/wm_adsp.c
sound/soc/codecs/wm_adsp.h
sound/soc/fsl/fsl_asrc.c
sound/soc/fsl/fsl_esai.c
sound/soc/generic/audio-graph-card.c
sound/soc/generic/simple-card.c
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/boards/cht_bsw_max98090_ti.c
sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
sound/soc/intel/skylake/skl-messages.c
sound/soc/intel/skylake/skl-pcm.c
sound/soc/mediatek/common/mtk-btcvsd.c
sound/soc/mediatek/mt8183/mt8183-afe-clk.c
sound/soc/rockchip/rockchip_pdm.c
sound/soc/samsung/i2s.c
sound/soc/samsung/odroid.c
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/src.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/stm/stm32_adfsdm.c
sound/soc/stm/stm32_i2s.c
sound/soc/stm/stm32_sai.c
sound/soc/stm/stm32_sai_sub.c
sound/xen/xen_snd_front_alsa.c
tools/io_uring/io_uring-bench.c
tools/objtool/check.c
tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
tools/testing/selftests/tpm2/tpm2.py
tools/testing/selftests/tpm2/tpm2_tests.py

index f49620f506f17a95bda75dd4cbfd2a544ee0a8b4..f3923a1f98583bef70d7beeac5954da858079a3c 100644 (file)
@@ -78,6 +78,8 @@ ForEachMacros:
   - 'ata_qc_for_each_with_internal'
   - 'ax25_for_each'
   - 'ax25_uid_for_each'
+  - '__bio_for_each_bvec'
+  - 'bio_for_each_bvec'
   - 'bio_for_each_integrity_vec'
   - '__bio_for_each_segment'
   - 'bio_for_each_segment'
@@ -118,10 +120,12 @@ ForEachMacros:
   - 'drm_for_each_legacy_plane'
   - 'drm_for_each_plane'
   - 'drm_for_each_plane_mask'
+  - 'drm_for_each_privobj'
   - 'drm_mm_for_each_hole'
   - 'drm_mm_for_each_node'
   - 'drm_mm_for_each_node_in_range'
   - 'drm_mm_for_each_node_safe'
+  - 'flow_action_for_each'
   - 'for_each_active_drhd_unit'
   - 'for_each_active_iommu'
   - 'for_each_available_child_of_node'
@@ -158,6 +162,9 @@ ForEachMacros:
   - 'for_each_dss_dev'
   - 'for_each_efi_memory_desc'
   - 'for_each_efi_memory_desc_in_map'
+  - 'for_each_element'
+  - 'for_each_element_extid'
+  - 'for_each_element_id'
   - 'for_each_endpoint_of_node'
   - 'for_each_evictable_lru'
   - 'for_each_fib6_node_rt_rcu'
@@ -195,6 +202,7 @@ ForEachMacros:
   - 'for_each_net_rcu'
   - 'for_each_new_connector_in_state'
   - 'for_each_new_crtc_in_state'
+  - 'for_each_new_mst_mgr_in_state'
   - 'for_each_new_plane_in_state'
   - 'for_each_new_private_obj_in_state'
   - 'for_each_node'
@@ -210,8 +218,10 @@ ForEachMacros:
   - 'for_each_of_pci_range'
   - 'for_each_old_connector_in_state'
   - 'for_each_old_crtc_in_state'
+  - 'for_each_old_mst_mgr_in_state'
   - 'for_each_oldnew_connector_in_state'
   - 'for_each_oldnew_crtc_in_state'
+  - 'for_each_oldnew_mst_mgr_in_state'
   - 'for_each_oldnew_plane_in_state'
   - 'for_each_oldnew_plane_in_state_reverse'
   - 'for_each_oldnew_private_obj_in_state'
@@ -243,6 +253,9 @@ ForEachMacros:
   - 'for_each_sg_dma_page'
   - 'for_each_sg_page'
   - 'for_each_sibling_event'
+  - 'for_each_subelement'
+  - 'for_each_subelement_extid'
+  - 'for_each_subelement_id'
   - '__for_each_thread'
   - 'for_each_thread'
   - 'for_each_zone'
@@ -252,6 +265,8 @@ ForEachMacros:
   - 'fwnode_for_each_child_node'
   - 'fwnode_graph_for_each_endpoint'
   - 'gadget_for_each_ep'
+  - 'genradix_for_each'
+  - 'genradix_for_each_from'
   - 'hash_for_each'
   - 'hash_for_each_possible'
   - 'hash_for_each_possible_rcu'
@@ -293,7 +308,11 @@ ForEachMacros:
   - 'key_for_each'
   - 'key_for_each_safe'
   - 'klp_for_each_func'
+  - 'klp_for_each_func_safe'
+  - 'klp_for_each_func_static'
   - 'klp_for_each_object'
+  - 'klp_for_each_object_safe'
+  - 'klp_for_each_object_static'
   - 'kvm_for_each_memslot'
   - 'kvm_for_each_vcpu'
   - 'list_for_each'
@@ -324,6 +343,8 @@ ForEachMacros:
   - 'media_device_for_each_intf'
   - 'media_device_for_each_link'
   - 'media_device_for_each_pad'
+  - 'mp_bvec_for_each_page'
+  - 'mp_bvec_for_each_segment'
   - 'nanddev_io_for_each_page'
   - 'netdev_for_each_lower_dev'
   - 'netdev_for_each_lower_private'
@@ -375,6 +396,7 @@ ForEachMacros:
   - 'rht_for_each_rcu'
   - 'rht_for_each_rcu_continue'
   - '__rq_for_each_bio'
+  - 'rq_for_each_bvec'
   - 'rq_for_each_segment'
   - 'scsi_for_each_prot_sg'
   - 'scsi_for_each_sg'
@@ -410,6 +432,8 @@ ForEachMacros:
   - 'v4l2_m2m_for_each_src_buf_safe'
   - 'virtio_device_for_each_vq'
   - 'xa_for_each'
+  - 'xa_for_each_marked'
+  - 'xa_for_each_start'
   - 'xas_for_each'
   - 'xas_for_each_conflict'
   - 'xas_for_each_marked'
index 2359e12e4c41e6c66e46e6599fb2e7bfd0db8c03..3671fdea5010e351ff5cedabde6dee83a8db9d7c 100644 (file)
@@ -7516,7 +7516,7 @@ F:        include/net/mac802154.h
 F:     include/net/af_ieee802154.h
 F:     include/net/cfg802154.h
 F:     include/net/ieee802154_netdev.h
-F:     Documentation/networking/ieee802154.txt
+F:     Documentation/networking/ieee802154.rst
 
 IFE PROTOCOL
 M:     Yotam Gigi <yotam.gi@gmail.com>
@@ -16509,7 +16509,7 @@ F:      drivers/char/virtio_console.c
 F:     include/linux/virtio_console.h
 F:     include/uapi/linux/virtio_console.h
 
-VIRTIO CORE, NET AND BLOCK DRIVERS
+VIRTIO CORE AND NET DRIVERS
 M:     "Michael S. Tsirkin" <mst@redhat.com>
 M:     Jason Wang <jasowang@redhat.com>
 L:     virtualization@lists.linux-foundation.org
@@ -16524,6 +16524,19 @@ F:     include/uapi/linux/virtio_*.h
 F:     drivers/crypto/virtio/
 F:     mm/balloon_compaction.c
 
+VIRTIO BLOCK AND SCSI DRIVERS
+M:     "Michael S. Tsirkin" <mst@redhat.com>
+M:     Jason Wang <jasowang@redhat.com>
+R:     Paolo Bonzini <pbonzini@redhat.com>
+R:     Stefan Hajnoczi <stefanha@redhat.com>
+L:     virtualization@lists.linux-foundation.org
+S:     Maintained
+F:     drivers/block/virtio_blk.c
+F:     drivers/scsi/virtio_scsi.c
+F:     include/uapi/linux/virtio_blk.h
+F:     include/uapi/linux/virtio_scsi.h
+F:     drivers/vhost/scsi.c
+
 VIRTIO CRYPTO DRIVER
 M:     Gonglei <arei.gonglei@huawei.com>
 L:     virtualization@lists.linux-foundation.org
index 15c8251d4d5eda3fa04e7bbdd960bcc174a71c0c..71fd5c2ce06750c8f3dc19675c3e4a392f964d14 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 1
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Shy Crocodile
 
 # *DOCUMENTATION*
index cccb83ad7fa8ea2e1f4251dd724edc62c754771b..e1d95f08f8e127d2e7bf334f94b146669aab79cb 100644 (file)
@@ -30,8 +30,8 @@ do {                                                                  \
 "      prfm    pstl1strm, %2\n"                                        \
 "1:    ldxr    %w1, %2\n"                                              \
        insn "\n"                                                       \
-"2:    stlxr   %w3, %w0, %2\n"                                         \
-"      cbnz    %w3, 1b\n"                                              \
+"2:    stlxr   %w0, %w3, %2\n"                                         \
+"      cbnz    %w0, 1b\n"                                              \
 "      dmb     ish\n"                                                  \
 "3:\n"                                                                 \
 "      .pushsection .fixup,\"ax\"\n"                                   \
@@ -50,30 +50,30 @@ do {                                                                        \
 static inline int
 arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *_uaddr)
 {
-       int oldval = 0, ret, tmp;
+       int oldval, ret, tmp;
        u32 __user *uaddr = __uaccess_mask_ptr(_uaddr);
 
        pagefault_disable();
 
        switch (op) {
        case FUTEX_OP_SET:
-               __futex_atomic_op("mov  %w0, %w4",
+               __futex_atomic_op("mov  %w3, %w4",
                                  ret, oldval, uaddr, tmp, oparg);
                break;
        case FUTEX_OP_ADD:
-               __futex_atomic_op("add  %w0, %w1, %w4",
+               __futex_atomic_op("add  %w3, %w1, %w4",
                                  ret, oldval, uaddr, tmp, oparg);
                break;
        case FUTEX_OP_OR:
-               __futex_atomic_op("orr  %w0, %w1, %w4",
+               __futex_atomic_op("orr  %w3, %w1, %w4",
                                  ret, oldval, uaddr, tmp, oparg);
                break;
        case FUTEX_OP_ANDN:
-               __futex_atomic_op("and  %w0, %w1, %w4",
+               __futex_atomic_op("and  %w3, %w1, %w4",
                                  ret, oldval, uaddr, tmp, ~oparg);
                break;
        case FUTEX_OP_XOR:
-               __futex_atomic_op("eor  %w0, %w1, %w4",
+               __futex_atomic_op("eor  %w3, %w1, %w4",
                                  ret, oldval, uaddr, tmp, oparg);
                break;
        default:
index 905e1bb0e7bd023b7174da7a6a81459df87b40dc..cd9f4e9d04d3be6564843e821b2a612642717210 100644 (file)
@@ -73,4 +73,9 @@ static inline bool is_forbidden_offset_for_adrp(void *place)
 struct plt_entry get_plt_entry(u64 dst, void *pc);
 bool plt_entries_equal(const struct plt_entry *a, const struct plt_entry *b);
 
+static inline bool plt_entry_is_initialized(const struct plt_entry *e)
+{
+       return e->adrp || e->add || e->br;
+}
+
 #endif /* __ASM_MODULE_H */
index 8e4431a8821f5920e49910dd287db5882e73f330..07b298120182042d2a1dea18160ef63e5a678b9d 100644 (file)
@@ -107,8 +107,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
                trampoline = get_plt_entry(addr, mod->arch.ftrace_trampoline);
                if (!plt_entries_equal(mod->arch.ftrace_trampoline,
                                       &trampoline)) {
-                       if (!plt_entries_equal(mod->arch.ftrace_trampoline,
-                                              &(struct plt_entry){})) {
+                       if (plt_entry_is_initialized(mod->arch.ftrace_trampoline)) {
                                pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n");
                                return -EINVAL;
                        }
index 8ad119c3f665d4e8001038ccf3bd6dcb62e2e224..29755989f616c187481803b27ca9dbfcf0a7847b 100644 (file)
@@ -102,10 +102,16 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
 void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
 {
        struct stackframe frame;
-       int skip;
+       int skip = 0;
 
        pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk);
 
+       if (regs) {
+               if (user_mode(regs))
+                       return;
+               skip = 1;
+       }
+
        if (!tsk)
                tsk = current;
 
@@ -126,7 +132,6 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
        frame.graph = 0;
 #endif
 
-       skip = !!regs;
        printk("Call trace:\n");
        do {
                /* skip until specified stack frame */
@@ -176,15 +181,13 @@ static int __die(const char *str, int err, struct pt_regs *regs)
                return ret;
 
        print_modules();
-       __show_regs(regs);
        pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n",
                 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk),
                 end_of_stack(tsk));
+       show_regs(regs);
 
-       if (!user_mode(regs)) {
-               dump_backtrace(regs, tsk);
+       if (!user_mode(regs))
                dump_instr(KERN_EMERG, regs);
-       }
 
        return ret;
 }
index f607888d24838be1c7d1ecd0fe7c20736b7d2ed1..184eb65a6ba71a5bea1e6b39cbe5d389a9764416 100644 (file)
@@ -1,6 +1,10 @@
 # require CONFIG_CPU_MIPS32_R2=y
 
 CONFIG_LEGACY_BOARD_OCELOT=y
+CONFIG_FIT_IMAGE_FDT_OCELOT=y
+
+CONFIG_BRIDGE=y
+CONFIG_GENERIC_PHY=y
 
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -19,6 +23,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 
 CONFIG_NETDEVICES=y
+CONFIG_NET_SWITCHDEV=y
+CONFIG_NET_DSA=y
 CONFIG_MSCC_OCELOT_SWITCH=y
 CONFIG_MSCC_OCELOT_SWITCH_OCELOT=y
 CONFIG_MDIO_MSCC_MIIM=y
@@ -35,6 +41,8 @@ CONFIG_SPI_DESIGNWARE=y
 CONFIG_SPI_DW_MMIO=y
 CONFIG_SPI_SPIDEV=y
 
+CONFIG_PINCTRL_OCELOT=y
+
 CONFIG_GPIO_SYSFS=y
 
 CONFIG_POWER_RESET=y
index 6e574c02e4c3b81137618c97fe9bc176c5a40d52..ea781b29f7f17291d90391c87a8a250772d17a37 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/processor.h>
 #include <asm/sigcontext.h>
 #include <linux/uaccess.h>
+#include <asm/irq_regs.h>
 
 static struct hard_trap_info {
        unsigned char tt;       /* Trap type code for MIPS R3xxx and R4xxx */
@@ -214,7 +215,7 @@ void kgdb_call_nmi_hook(void *ignored)
        old_fs = get_fs();
        set_fs(KERNEL_DS);
 
-       kgdb_nmicallback(raw_smp_processor_id(), NULL);
+       kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
 
        set_fs(old_fs);
 }
index 710a59764b01c164d3ffae92f18a394224bdc153..a32f843cdbe02299e34bf7f0897ad61f6e23dce5 100644 (file)
@@ -118,7 +118,6 @@ static void shutdown_bridge_irq(struct irq_data *d)
 {
        struct hub_irq_data *hd = irq_data_get_irq_chip_data(d);
        struct bridge_controller *bc;
-       int pin = hd->pin;
 
        if (!hd)
                return;
@@ -126,7 +125,7 @@ static void shutdown_bridge_irq(struct irq_data *d)
        disable_hub_irq(d);
 
        bc = hd->bc;
-       bridge_clr(bc, b_int_enable, (1 << pin));
+       bridge_clr(bc, b_int_enable, (1 << hd->pin));
        bridge_read(bc, b_wid_tflush);
 }
 
index 598cdcdd13553dea4a80a9b72196dbee8987cd61..8ddd4a91bdc1e2fe9a2e4a617b32cc0e6e15e572 100644 (file)
@@ -352,7 +352,7 @@ static inline bool strict_kernel_rwx_enabled(void)
 #if defined(CONFIG_SPARSEMEM_VMEMMAP) && defined(CONFIG_SPARSEMEM_EXTREME) &&  \
        defined (CONFIG_PPC_64K_PAGES)
 #define MAX_PHYSMEM_BITS        51
-#elif defined(CONFIG_SPARSEMEM)
+#elif defined(CONFIG_PPC64)
 #define MAX_PHYSMEM_BITS        46
 #endif
 
index a5b8fbae56a03b491f0982562f3d590cff16ca5f..9481a117e24255173231ac687c9e99b730bff420 100644 (file)
@@ -656,11 +656,17 @@ EXC_COMMON_BEGIN(data_access_slb_common)
        ld      r4,PACA_EXSLB+EX_DAR(r13)
        std     r4,_DAR(r1)
        addi    r3,r1,STACK_FRAME_OVERHEAD
+BEGIN_MMU_FTR_SECTION
+       /* HPT case, do SLB fault */
        bl      do_slb_fault
        cmpdi   r3,0
        bne-    1f
        b       fast_exception_return
 1:     /* Error case */
+MMU_FTR_SECTION_ELSE
+       /* Radix case, access is outside page table range */
+       li      r3,-EFAULT
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
        std     r3,RESULT(r1)
        bl      save_nvgprs
        RECONCILE_IRQ_STATE(r10, r11)
@@ -705,11 +711,17 @@ EXC_COMMON_BEGIN(instruction_access_slb_common)
        EXCEPTION_PROLOG_COMMON(0x480, PACA_EXSLB)
        ld      r4,_NIP(r1)
        addi    r3,r1,STACK_FRAME_OVERHEAD
+BEGIN_MMU_FTR_SECTION
+       /* HPT case, do SLB fault */
        bl      do_slb_fault
        cmpdi   r3,0
        bne-    1f
        b       fast_exception_return
 1:     /* Error case */
+MMU_FTR_SECTION_ELSE
+       /* Radix case, access is outside page table range */
+       li      r3,-EFAULT
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
        std     r3,RESULT(r1)
        bl      save_nvgprs
        RECONCILE_IRQ_STATE(r10, r11)
index 48051c8977c5603a1ac9f8b730c0283ab04497d8..e25b615e9f9e642d34e9387aac7db652131a466f 100644 (file)
@@ -851,10 +851,6 @@ __secondary_start:
        tophys(r4,r2)
        addi    r4,r4,THREAD    /* phys address of our thread_struct */
        mtspr   SPRN_SPRG_THREAD,r4
-#ifdef CONFIG_PPC_RTAS
-       li      r3,0
-       stw     r3, RTAS_SP(r4)         /* 0 => not in RTAS */
-#endif
        lis     r4, (swapper_pg_dir - PAGE_OFFSET)@h
        ori     r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l
        mtspr   SPRN_SPRG_PGDIR, r4
@@ -941,10 +937,6 @@ start_here:
        tophys(r4,r2)
        addi    r4,r4,THREAD    /* init task's THREAD */
        mtspr   SPRN_SPRG_THREAD,r4
-#ifdef CONFIG_PPC_RTAS
-       li      r3,0
-       stw     r3, RTAS_SP(r4)         /* 0 => not in RTAS */
-#endif
        lis     r4, (swapper_pg_dir - PAGE_OFFSET)@h
        ori     r4, r4, (swapper_pg_dir - PAGE_OFFSET)@l
        mtspr   SPRN_SPRG_PGDIR, r4
index 1e0bc5955a400601b106949f14c7a0ca64d1a6a6..afd516b572f8637447315ec882c08189bcf2fb4d 100644 (file)
@@ -98,7 +98,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
         * can be used, r7 contains NSEC_PER_SEC.
         */
 
-       lwz     r5,WTOM_CLOCK_SEC(r9)
+       lwz     r5,(WTOM_CLOCK_SEC+LOPART)(r9)
        lwz     r6,WTOM_CLOCK_NSEC(r9)
 
        /* We now have our offset in r5,r6. We create a fake dependency
index a8af6023c1263f7b43a4a52f52089235493923bd..14b93c5564e3572c07993c74217fb0b89ee36573 100644 (file)
@@ -73,6 +73,11 @@ static inline void iommu_batch_start(struct device *dev, unsigned long prot, uns
        p->npages       = 0;
 }
 
+static inline bool iommu_use_atu(struct iommu *iommu, u64 mask)
+{
+       return iommu->atu && mask > DMA_BIT_MASK(32);
+}
+
 /* Interrupts must be disabled.  */
 static long iommu_batch_flush(struct iommu_batch *p, u64 mask)
 {
@@ -92,7 +97,7 @@ static long iommu_batch_flush(struct iommu_batch *p, u64 mask)
                prot &= (HV_PCI_MAP_ATTR_READ | HV_PCI_MAP_ATTR_WRITE);
 
        while (npages != 0) {
-               if (mask <= DMA_BIT_MASK(32) || !pbm->iommu->atu) {
+               if (!iommu_use_atu(pbm->iommu, mask)) {
                        num = pci_sun4v_iommu_map(devhandle,
                                                  HV_PCI_TSBID(0, entry),
                                                  npages,
@@ -179,7 +184,6 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
        unsigned long flags, order, first_page, npages, n;
        unsigned long prot = 0;
        struct iommu *iommu;
-       struct atu *atu;
        struct iommu_map_table *tbl;
        struct page *page;
        void *ret;
@@ -205,13 +209,11 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
        memset((char *)first_page, 0, PAGE_SIZE << order);
 
        iommu = dev->archdata.iommu;
-       atu = iommu->atu;
-
        mask = dev->coherent_dma_mask;
-       if (mask <= DMA_BIT_MASK(32) || !atu)
+       if (!iommu_use_atu(iommu, mask))
                tbl = &iommu->tbl;
        else
-               tbl = &atu->tbl;
+               tbl = &iommu->atu->tbl;
 
        entry = iommu_tbl_range_alloc(dev, tbl, npages, NULL,
                                      (unsigned long)(-1), 0);
@@ -333,7 +335,7 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
        atu = iommu->atu;
        devhandle = pbm->devhandle;
 
-       if (dvma <= DMA_BIT_MASK(32)) {
+       if (!iommu_use_atu(iommu, dvma)) {
                tbl = &iommu->tbl;
                iotsb_num = 0; /* we don't care for legacy iommu */
        } else {
@@ -374,7 +376,7 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
        npages >>= IO_PAGE_SHIFT;
 
        mask = *dev->dma_mask;
-       if (mask <= DMA_BIT_MASK(32))
+       if (!iommu_use_atu(iommu, mask))
                tbl = &iommu->tbl;
        else
                tbl = &atu->tbl;
@@ -510,7 +512,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
                                  IO_PAGE_SIZE) >> IO_PAGE_SHIFT;
 
        mask = *dev->dma_mask;
-       if (mask <= DMA_BIT_MASK(32))
+       if (!iommu_use_atu(iommu, mask))
                tbl = &iommu->tbl;
        else
                tbl = &atu->tbl;
index 7d2d7c801dba6abb226b630104d1f038242562cf..0ecfac84ba9111306faeb900375b6402d52afa07 100644 (file)
@@ -3,10 +3,14 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <asm/apicdef.h>
+#include <asm/nmi.h>
 
 #include "../perf_event.h"
 
+static DEFINE_PER_CPU(unsigned int, perf_nmi_counter);
+
 static __initconst const u64 amd_hw_cache_event_ids
                                [PERF_COUNT_HW_CACHE_MAX]
                                [PERF_COUNT_HW_CACHE_OP_MAX]
@@ -429,6 +433,132 @@ static void amd_pmu_cpu_dead(int cpu)
        }
 }
 
+/*
+ * When a PMC counter overflows, an NMI is used to process the event and
+ * reset the counter. NMI latency can result in the counter being updated
+ * before the NMI can run, which can result in what appear to be spurious
+ * NMIs. This function is intended to wait for the NMI to run and reset
+ * the counter to avoid possible unhandled NMI messages.
+ */
+#define OVERFLOW_WAIT_COUNT    50
+
+static void amd_pmu_wait_on_overflow(int idx)
+{
+       unsigned int i;
+       u64 counter;
+
+       /*
+        * Wait for the counter to be reset if it has overflowed. This loop
+        * should exit very, very quickly, but just in case, don't wait
+        * forever...
+        */
+       for (i = 0; i < OVERFLOW_WAIT_COUNT; i++) {
+               rdmsrl(x86_pmu_event_addr(idx), counter);
+               if (counter & (1ULL << (x86_pmu.cntval_bits - 1)))
+                       break;
+
+               /* Might be in IRQ context, so can't sleep */
+               udelay(1);
+       }
+}
+
+static void amd_pmu_disable_all(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+
+       x86_pmu_disable_all();
+
+       /*
+        * This shouldn't be called from NMI context, but add a safeguard here
+        * to return, since if we're in NMI context we can't wait for an NMI
+        * to reset an overflowed counter value.
+        */
+       if (in_nmi())
+               return;
+
+       /*
+        * Check each counter for overflow and wait for it to be reset by the
+        * NMI if it has overflowed. This relies on the fact that all active
+        * counters are always enabled when this function is caled and
+        * ARCH_PERFMON_EVENTSEL_INT is always set.
+        */
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               amd_pmu_wait_on_overflow(idx);
+       }
+}
+
+static void amd_pmu_disable_event(struct perf_event *event)
+{
+       x86_pmu_disable_event(event);
+
+       /*
+        * This can be called from NMI context (via x86_pmu_stop). The counter
+        * may have overflowed, but either way, we'll never see it get reset
+        * by the NMI if we're already in the NMI. And the NMI latency support
+        * below will take care of any pending NMI that might have been
+        * generated by the overflow.
+        */
+       if (in_nmi())
+               return;
+
+       amd_pmu_wait_on_overflow(event->hw.idx);
+}
+
+/*
+ * Because of NMI latency, if multiple PMC counters are active or other sources
+ * of NMIs are received, the perf NMI handler can handle one or more overflowed
+ * PMC counters outside of the NMI associated with the PMC overflow. If the NMI
+ * doesn't arrive at the LAPIC in time to become a pending NMI, then the kernel
+ * back-to-back NMI support won't be active. This PMC handler needs to take into
+ * account that this can occur, otherwise this could result in unknown NMI
+ * messages being issued. Examples of this is PMC overflow while in the NMI
+ * handler when multiple PMCs are active or PMC overflow while handling some
+ * other source of an NMI.
+ *
+ * Attempt to mitigate this by using the number of active PMCs to determine
+ * whether to return NMI_HANDLED if the perf NMI handler did not handle/reset
+ * any PMCs. The per-CPU perf_nmi_counter variable is set to a minimum of the
+ * number of active PMCs or 2. The value of 2 is used in case an NMI does not
+ * arrive at the LAPIC in time to be collapsed into an already pending NMI.
+ */
+static int amd_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int active, handled;
+
+       /*
+        * Obtain the active count before calling x86_pmu_handle_irq() since
+        * it is possible that x86_pmu_handle_irq() may make a counter
+        * inactive (through x86_pmu_stop).
+        */
+       active = __bitmap_weight(cpuc->active_mask, X86_PMC_IDX_MAX);
+
+       /* Process any counter overflows */
+       handled = x86_pmu_handle_irq(regs);
+
+       /*
+        * If a counter was handled, record the number of possible remaining
+        * NMIs that can occur.
+        */
+       if (handled) {
+               this_cpu_write(perf_nmi_counter,
+                              min_t(unsigned int, 2, active));
+
+               return handled;
+       }
+
+       if (!this_cpu_read(perf_nmi_counter))
+               return NMI_DONE;
+
+       this_cpu_dec(perf_nmi_counter);
+
+       return NMI_HANDLED;
+}
+
 static struct event_constraint *
 amd_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
                          struct perf_event *event)
@@ -621,11 +751,11 @@ static ssize_t amd_event_sysfs_show(char *page, u64 config)
 
 static __initconst const struct x86_pmu amd_pmu = {
        .name                   = "AMD",
-       .handle_irq             = x86_pmu_handle_irq,
-       .disable_all            = x86_pmu_disable_all,
+       .handle_irq             = amd_pmu_handle_irq,
+       .disable_all            = amd_pmu_disable_all,
        .enable_all             = x86_pmu_enable_all,
        .enable                 = x86_pmu_enable_event,
-       .disable                = x86_pmu_disable_event,
+       .disable                = amd_pmu_disable_event,
        .hw_config              = amd_pmu_hw_config,
        .schedule_events        = x86_schedule_events,
        .eventsel               = MSR_K7_EVNTSEL0,
@@ -732,7 +862,7 @@ void amd_pmu_enable_virt(void)
        cpuc->perf_ctr_virt_mask = 0;
 
        /* Reload all events */
-       x86_pmu_disable_all();
+       amd_pmu_disable_all();
        x86_pmu_enable_all(0);
 }
 EXPORT_SYMBOL_GPL(amd_pmu_enable_virt);
@@ -750,7 +880,7 @@ void amd_pmu_disable_virt(void)
        cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY;
 
        /* Reload all events */
-       x86_pmu_disable_all();
+       amd_pmu_disable_all();
        x86_pmu_enable_all(0);
 }
 EXPORT_SYMBOL_GPL(amd_pmu_disable_virt);
index e2b1447192a888ffafb2883ddbdfbbd37c1e9315..81911e11a15dfcd7cff5694d0a2a83df769a655b 100644 (file)
@@ -1349,8 +1349,9 @@ void x86_pmu_stop(struct perf_event *event, int flags)
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
 
-       if (__test_and_clear_bit(hwc->idx, cpuc->active_mask)) {
+       if (test_bit(hwc->idx, cpuc->active_mask)) {
                x86_pmu.disable(event);
+               __clear_bit(hwc->idx, cpuc->active_mask);
                cpuc->events[hwc->idx] = NULL;
                WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
                hwc->state |= PERF_HES_STOPPED;
@@ -1447,16 +1448,8 @@ int x86_pmu_handle_irq(struct pt_regs *regs)
        apic_write(APIC_LVTPC, APIC_DM_NMI);
 
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               if (!test_bit(idx, cpuc->active_mask)) {
-                       /*
-                        * Though we deactivated the counter some cpus
-                        * might still deliver spurious interrupts still
-                        * in flight. Catch them:
-                        */
-                       if (__test_and_clear_bit(idx, cpuc->running))
-                               handled++;
+               if (!test_bit(idx, cpuc->active_mask))
                        continue;
-               }
 
                event = cpuc->events[idx];
 
index 8baa441d8000f6c4efbde5afe72d4e5a518d2184..f61dcbef20ffee301a5904717846fe1d1c1c6f31 100644 (file)
@@ -3185,7 +3185,7 @@ static int intel_pmu_hw_config(struct perf_event *event)
                return ret;
 
        if (event->attr.precise_ip) {
-               if (!event->attr.freq) {
+               if (!(event->attr.freq || event->attr.wakeup_events)) {
                        event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD;
                        if (!(event->attr.sample_type &
                              ~intel_pmu_large_pebs_flags(event)))
@@ -3575,6 +3575,12 @@ static void intel_pmu_cpu_starting(int cpu)
 
        cpuc->lbr_sel = NULL;
 
+       if (x86_pmu.flags & PMU_FL_TFA) {
+               WARN_ON_ONCE(cpuc->tfa_shadow);
+               cpuc->tfa_shadow = ~0ULL;
+               intel_set_tfa(cpuc, false);
+       }
+
        if (x86_pmu.version > 1)
                flip_smm_bit(&x86_pmu.attr_freeze_on_smi);
 
index d153d570bb04755d9fb106e3375db55dd3114fd7..8e790ec219a5fd5be0e812736ff7be167a5cd20e 100644 (file)
  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  */
 
-#define BITOP_ADDR(x) "+m" (*(volatile long *) (x))
+#define RLONG_ADDR(x)                   "m" (*(volatile long *) (x))
+#define WBYTE_ADDR(x)                  "+m" (*(volatile char *) (x))
 
-#define ADDR                           BITOP_ADDR(addr)
+#define ADDR                           RLONG_ADDR(addr)
 
 /*
  * We do the locked ops that don't return the old value as
  * a mask operation on a byte.
  */
 #define IS_IMMEDIATE(nr)               (__builtin_constant_p(nr))
-#define CONST_MASK_ADDR(nr, addr)      BITOP_ADDR((void *)(addr) + ((nr)>>3))
+#define CONST_MASK_ADDR(nr, addr)      WBYTE_ADDR((void *)(addr) + ((nr)>>3))
 #define CONST_MASK(nr)                 (1 << ((nr) & 7))
 
 /**
@@ -73,7 +74,7 @@ set_bit(long nr, volatile unsigned long *addr)
                        : "memory");
        } else {
                asm volatile(LOCK_PREFIX __ASM_SIZE(bts) " %1,%0"
-                       : BITOP_ADDR(addr) : "Ir" (nr) : "memory");
+                       : : RLONG_ADDR(addr), "Ir" (nr) : "memory");
        }
 }
 
@@ -88,7 +89,7 @@ set_bit(long nr, volatile unsigned long *addr)
  */
 static __always_inline void __set_bit(long nr, volatile unsigned long *addr)
 {
-       asm volatile(__ASM_SIZE(bts) " %1,%0" : ADDR : "Ir" (nr) : "memory");
+       asm volatile(__ASM_SIZE(bts) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
 }
 
 /**
@@ -110,8 +111,7 @@ clear_bit(long nr, volatile unsigned long *addr)
                        : "iq" ((u8)~CONST_MASK(nr)));
        } else {
                asm volatile(LOCK_PREFIX __ASM_SIZE(btr) " %1,%0"
-                       : BITOP_ADDR(addr)
-                       : "Ir" (nr));
+                       : : RLONG_ADDR(addr), "Ir" (nr) : "memory");
        }
 }
 
@@ -131,7 +131,7 @@ static __always_inline void clear_bit_unlock(long nr, volatile unsigned long *ad
 
 static __always_inline void __clear_bit(long nr, volatile unsigned long *addr)
 {
-       asm volatile(__ASM_SIZE(btr) " %1,%0" : ADDR : "Ir" (nr));
+       asm volatile(__ASM_SIZE(btr) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
 }
 
 static __always_inline bool clear_bit_unlock_is_negative_byte(long nr, volatile unsigned long *addr)
@@ -139,7 +139,7 @@ static __always_inline bool clear_bit_unlock_is_negative_byte(long nr, volatile
        bool negative;
        asm volatile(LOCK_PREFIX "andb %2,%1"
                CC_SET(s)
-               : CC_OUT(s) (negative), ADDR
+               : CC_OUT(s) (negative), WBYTE_ADDR(addr)
                : "ir" ((char) ~(1 << nr)) : "memory");
        return negative;
 }
@@ -155,13 +155,9 @@ static __always_inline bool clear_bit_unlock_is_negative_byte(long nr, volatile
  * __clear_bit() is non-atomic and implies release semantics before the memory
  * operation. It can be used for an unlock if no other CPUs can concurrently
  * modify other bits in the word.
- *
- * No memory barrier is required here, because x86 cannot reorder stores past
- * older loads. Same principle as spin_unlock.
  */
 static __always_inline void __clear_bit_unlock(long nr, volatile unsigned long *addr)
 {
-       barrier();
        __clear_bit(nr, addr);
 }
 
@@ -176,7 +172,7 @@ static __always_inline void __clear_bit_unlock(long nr, volatile unsigned long *
  */
 static __always_inline void __change_bit(long nr, volatile unsigned long *addr)
 {
-       asm volatile(__ASM_SIZE(btc) " %1,%0" : ADDR : "Ir" (nr));
+       asm volatile(__ASM_SIZE(btc) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
 }
 
 /**
@@ -196,8 +192,7 @@ static __always_inline void change_bit(long nr, volatile unsigned long *addr)
                        : "iq" ((u8)CONST_MASK(nr)));
        } else {
                asm volatile(LOCK_PREFIX __ASM_SIZE(btc) " %1,%0"
-                       : BITOP_ADDR(addr)
-                       : "Ir" (nr));
+                       : : RLONG_ADDR(addr), "Ir" (nr) : "memory");
        }
 }
 
@@ -242,8 +237,8 @@ static __always_inline bool __test_and_set_bit(long nr, volatile unsigned long *
 
        asm(__ASM_SIZE(bts) " %2,%1"
            CC_SET(c)
-           : CC_OUT(c) (oldbit), ADDR
-           : "Ir" (nr));
+           : CC_OUT(c) (oldbit)
+           : ADDR, "Ir" (nr) : "memory");
        return oldbit;
 }
 
@@ -282,8 +277,8 @@ static __always_inline bool __test_and_clear_bit(long nr, volatile unsigned long
 
        asm volatile(__ASM_SIZE(btr) " %2,%1"
                     CC_SET(c)
-                    : CC_OUT(c) (oldbit), ADDR
-                    : "Ir" (nr));
+                    : CC_OUT(c) (oldbit)
+                    : ADDR, "Ir" (nr) : "memory");
        return oldbit;
 }
 
@@ -294,8 +289,8 @@ static __always_inline bool __test_and_change_bit(long nr, volatile unsigned lon
 
        asm volatile(__ASM_SIZE(btc) " %2,%1"
                     CC_SET(c)
-                    : CC_OUT(c) (oldbit), ADDR
-                    : "Ir" (nr) : "memory");
+                    : CC_OUT(c) (oldbit)
+                    : ADDR, "Ir" (nr) : "memory");
 
        return oldbit;
 }
@@ -326,7 +321,7 @@ static __always_inline bool variable_test_bit(long nr, volatile const unsigned l
        asm volatile(__ASM_SIZE(bt) " %2,%1"
                     CC_SET(c)
                     : CC_OUT(c) (oldbit)
-                    : "m" (*(unsigned long *)addr), "Ir" (nr));
+                    : "m" (*(unsigned long *)addr), "Ir" (nr) : "memory");
 
        return oldbit;
 }
index 399601eda8e43c2cf8a855b44b4dc811a247c9e5..54b9eef3eea97189a032cccf56ec4e001cc77ec5 100644 (file)
@@ -2039,14 +2039,14 @@ out:
 enum rdt_param {
        Opt_cdp,
        Opt_cdpl2,
-       Opt_mba_mpbs,
+       Opt_mba_mbps,
        nr__rdt_params
 };
 
 static const struct fs_parameter_spec rdt_param_specs[] = {
        fsparam_flag("cdp",             Opt_cdp),
        fsparam_flag("cdpl2",           Opt_cdpl2),
-       fsparam_flag("mba_mpbs",        Opt_mba_mpbs),
+       fsparam_flag("mba_MBps",        Opt_mba_mbps),
        {}
 };
 
@@ -2072,7 +2072,7 @@ static int rdt_parse_param(struct fs_context *fc, struct fs_parameter *param)
        case Opt_cdpl2:
                ctx->enable_cdpl2 = true;
                return 0;
-       case Opt_mba_mpbs:
+       case Opt_mba_mbps:
                if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
                        return -EINVAL;
                ctx->enable_mba_mbps = true;
index f7dd895b2353e0510a7199896030c8527695c130..0c14018d1c2601a63a92b2f29be1270d9919220c 100644 (file)
@@ -187,15 +187,18 @@ struct thread_struct {
 
 /* Clearing a0 terminates the backtrace. */
 #define start_thread(regs, new_pc, new_sp) \
-       memset(regs, 0, sizeof(*regs)); \
-       regs->pc = new_pc; \
-       regs->ps = USER_PS_VALUE; \
-       regs->areg[1] = new_sp; \
-       regs->areg[0] = 0; \
-       regs->wmask = 1; \
-       regs->depc = 0; \
-       regs->windowbase = 0; \
-       regs->windowstart = 1;
+       do { \
+               memset((regs), 0, sizeof(*(regs))); \
+               (regs)->pc = (new_pc); \
+               (regs)->ps = USER_PS_VALUE; \
+               (regs)->areg[1] = (new_sp); \
+               (regs)->areg[0] = 0; \
+               (regs)->wmask = 1; \
+               (regs)->depc = 0; \
+               (regs)->windowbase = 0; \
+               (regs)->windowstart = 1; \
+               (regs)->syscall = NO_SYSCALL; \
+       } while (0)
 
 /* Forward declaration */
 struct task_struct;
index e50f5124dc6f789c7457cb3b296d67f2b5cc76e1..e54af8b7e0f8c314830ae1ae5244f86af19a1682 100644 (file)
@@ -1860,6 +1860,8 @@ ENTRY(system_call)
        l32i    a7, a2, PT_SYSCALL
 
 1:
+       s32i    a7, a1, 4
+
        /* syscall = sys_call_table[syscall_nr] */
 
        movi    a4, sys_call_table
@@ -1893,8 +1895,12 @@ ENTRY(system_call)
        retw
 
 1:
+       l32i    a4, a1, 4
+       l32i    a3, a2, PT_SYSCALL
+       s32i    a4, a2, PT_SYSCALL
        mov     a6, a2
        call4   do_syscall_trace_leave
+       s32i    a3, a2, PT_SYSCALL
        retw
 
 ENDPROC(system_call)
index 174c11f13bba375472f77a02eca75b1408d5e2de..b9f82510c65019506ffb98f3f23ac494f7285efa 100644 (file)
@@ -253,10 +253,14 @@ static int return_address_cb(struct stackframe *frame, void *data)
        return 1;
 }
 
+/*
+ * level == 0 is for the return address from the caller of this function,
+ * not from this function itself.
+ */
 unsigned long return_address(unsigned level)
 {
        struct return_addr_data r = {
-               .skip = level + 1,
+               .skip = level,
        };
        walk_stackframe(stack_pointer(NULL), return_address_cb, &r);
        return r.addr;
index 2fb7d117222840da05f44cf7eed39348d27502e5..03678c4afc39b9e4ee94a3666b7ef630ad246d05 100644 (file)
@@ -33,7 +33,7 @@ static void * __init init_pmd(unsigned long vaddr, unsigned long n_pages)
 
        pte = memblock_alloc_low(n_pages * sizeof(pte_t), PAGE_SIZE);
        if (!pte)
-               panic("%s: Failed to allocate %zu bytes align=%lx\n",
+               panic("%s: Failed to allocate %lu bytes align=%lx\n",
                      __func__, n_pages * sizeof(pte_t), PAGE_SIZE);
 
        for (i = 0; i < n_pages; ++i)
index fac188dd78fa74f7a732d1bdb4023587bfaf0dc2..dfb8cb0af13a872737e07647de307e9e44017f0d 100644 (file)
@@ -2822,7 +2822,7 @@ static void bfq_dispatch_remove(struct request_queue *q, struct request *rq)
        bfq_remove_request(q, rq);
 }
 
-static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq)
+static bool __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq)
 {
        /*
         * If this bfqq is shared between multiple processes, check
@@ -2855,9 +2855,11 @@ static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq)
        /*
         * All in-service entities must have been properly deactivated
         * or requeued before executing the next function, which
-        * resets all in-service entites as no more in service.
+        * resets all in-service entities as no more in service. This
+        * may cause bfqq to be freed. If this happens, the next
+        * function returns true.
         */
-       __bfq_bfqd_reset_in_service(bfqd);
+       return __bfq_bfqd_reset_in_service(bfqd);
 }
 
 /**
@@ -3262,7 +3264,6 @@ void bfq_bfqq_expire(struct bfq_data *bfqd,
        bool slow;
        unsigned long delta = 0;
        struct bfq_entity *entity = &bfqq->entity;
-       int ref;
 
        /*
         * Check whether the process is slow (see bfq_bfqq_is_slow).
@@ -3347,10 +3348,8 @@ void bfq_bfqq_expire(struct bfq_data *bfqd,
         * reason.
         */
        __bfq_bfqq_recalc_budget(bfqd, bfqq, reason);
-       ref = bfqq->ref;
-       __bfq_bfqq_expire(bfqd, bfqq);
-
-       if (ref == 1) /* bfqq is gone, no more actions on it */
+       if (__bfq_bfqq_expire(bfqd, bfqq))
+               /* bfqq is gone, no more actions on it */
                return;
 
        bfqq->injected_service = 0;
index 062e1c4787f4a9e66ac4df54d24c17d9f92c6577..86394e503ca9c0487a66d40deaa09643148ae3df 100644 (file)
@@ -995,7 +995,7 @@ bool __bfq_deactivate_entity(struct bfq_entity *entity,
                             bool ins_into_idle_tree);
 bool next_queue_may_preempt(struct bfq_data *bfqd);
 struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd);
-void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd);
+bool __bfq_bfqd_reset_in_service(struct bfq_data *bfqd);
 void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                         bool ins_into_idle_tree, bool expiration);
 void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq);
index a11bef75483d4bf73f16cf6a535079ee836bcab9..ae4d000ac0af1c38a49c28e824ca843bfb3c531d 100644 (file)
@@ -1605,7 +1605,8 @@ struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd)
        return bfqq;
 }
 
-void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd)
+/* returns true if the in-service queue gets freed */
+bool __bfq_bfqd_reset_in_service(struct bfq_data *bfqd)
 {
        struct bfq_queue *in_serv_bfqq = bfqd->in_service_queue;
        struct bfq_entity *in_serv_entity = &in_serv_bfqq->entity;
@@ -1629,8 +1630,20 @@ void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd)
         * service tree either, then release the service reference to
         * the queue it represents (taken with bfq_get_entity).
         */
-       if (!in_serv_entity->on_st)
+       if (!in_serv_entity->on_st) {
+               /*
+                * If no process is referencing in_serv_bfqq any
+                * longer, then the service reference may be the only
+                * reference to the queue. If this is the case, then
+                * bfqq gets freed here.
+                */
+               int ref = in_serv_bfqq->ref;
                bfq_put_queue(in_serv_bfqq);
+               if (ref == 1)
+                       return true;
+       }
+
+       return false;
 }
 
 void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
index b64cedc7f87cf1cf5f24bf4c50c808ae6a59f210..716510ecd7ffa3f0535b49e3a443ea1ebe38ec12 100644 (file)
@@ -1298,8 +1298,11 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
                        }
                }
 
-               if (bio_add_pc_page(q, bio, page, bytes, offset) < bytes)
+               if (bio_add_pc_page(q, bio, page, bytes, offset) < bytes) {
+                       if (!map_data)
+                               __free_page(page);
                        break;
+               }
 
                len -= bytes;
                offset = 0;
index a9354835cf5177cc5f14bec92e754202a918d30e..9516304a38ee37c70f897185e6bfe94fc7fe79f8 100644 (file)
@@ -654,6 +654,13 @@ bool blk_mq_complete_request(struct request *rq)
 }
 EXPORT_SYMBOL(blk_mq_complete_request);
 
+void blk_mq_complete_request_sync(struct request *rq)
+{
+       WRITE_ONCE(rq->state, MQ_RQ_COMPLETE);
+       rq->q->mq_ops->complete(rq);
+}
+EXPORT_SYMBOL_GPL(blk_mq_complete_request_sync);
+
 int blk_mq_request_started(struct request *rq)
 {
        return blk_mq_rq_state(rq) != MQ_RQ_IDLE;
index 8638f43cfc3d87184c9a0cc91318f07ab5abff8a..79d86da1c8924a971bacf928008634c8aa3224ca 100644 (file)
@@ -186,6 +186,10 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node)
                }
        }
 
+       if (obj_desc->common.type == ACPI_TYPE_REGION) {
+               acpi_ut_remove_address_range(obj_desc->region.space_id, node);
+       }
+
        /* Clear the Node entry in all cases */
 
        node->object = NULL;
index 4bc083b7c9b541a0fede52156bdae003c1d678df..2a7ca4a1e6f7bd5e2730b13a30760f9506c6973c 100644 (file)
@@ -513,6 +513,8 @@ static int init_vq(struct virtio_blk *vblk)
        if (err)
                num_vqs = 1;
 
+       num_vqs = min_t(unsigned int, nr_cpu_ids, num_vqs);
+
        vblk->vqs = kmalloc_array(num_vqs, sizeof(*vblk->vqs), GFP_KERNEL);
        if (!vblk->vqs)
                return -ENOMEM;
index ded198328f216066959825950ebfbe5aef29027d..7db48ae65cd2dc946b6a1757baa20993158b903e 100644 (file)
@@ -2942,6 +2942,7 @@ static int btusb_config_oob_wake(struct hci_dev *hdev)
                return 0;
        }
 
+       irq_set_status_flags(irq, IRQ_NOAUTOEN);
        ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler,
                               0, "OOB Wake-on-BT", data);
        if (ret) {
@@ -2956,7 +2957,6 @@ static int btusb_config_oob_wake(struct hci_dev *hdev)
        }
 
        data->oob_wake_irq = irq;
-       disable_irq(irq);
        bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u", irq);
        return 0;
 }
index d8b77133a83a2a2c59d3d7873db8d4d110f5dfb0..f824563fc28dd091303f89de651589ea5350a64b 100644 (file)
@@ -37,8 +37,8 @@
  *
  * Returns size of the event. If it is an invalid event, returns 0.
  */
-static int calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
-                               struct tcg_pcr_event *event_header)
+static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
+                                  struct tcg_pcr_event *event_header)
 {
        struct tcg_efi_specid_event_head *efispecid;
        struct tcg_event_field *event_field;
index 8856cce5a23b2858b58b69373f4cd89e2f898abb..817ae09a369ec2ba192a68f302205eaef7aadeb5 100644 (file)
@@ -233,12 +233,19 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait)
        __poll_t mask = 0;
 
        poll_wait(file, &priv->async_wait, wait);
+       mutex_lock(&priv->buffer_mutex);
 
-       if (!priv->response_read || priv->response_length)
+       /*
+        * The response_length indicates if there is still response
+        * (or part of it) to be consumed. Partial reads decrease it
+        * by the number of bytes read, and write resets it the zero.
+        */
+       if (priv->response_length)
                mask = EPOLLIN | EPOLLRDNORM;
        else
                mask = EPOLLOUT | EPOLLWRNORM;
 
+       mutex_unlock(&priv->buffer_mutex);
        return mask;
 }
 
index 83ece5639f8639e7bb397ec4feeb121006073208..ae1030c9b086de511aa5c2bd0800fdcf6c2a1051 100644 (file)
@@ -402,15 +402,13 @@ int tpm_pm_suspend(struct device *dev)
        if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
                return 0;
 
-       if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-               mutex_lock(&chip->tpm_mutex);
-               if (!tpm_chip_start(chip)) {
+       if (!tpm_chip_start(chip)) {
+               if (chip->flags & TPM_CHIP_FLAG_TPM2)
                        tpm2_shutdown(chip, TPM2_SU_STATE);
-                       tpm_chip_stop(chip);
-               }
-               mutex_unlock(&chip->tpm_mutex);
-       } else {
-               rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
+               else
+                       rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
+
+               tpm_chip_stop(chip);
        }
 
        return rc;
index 89d6f3736dbf605036e4eefb70efd2ef2ee4f386..f8edbb65eda3564cf99623c852fe474a93803123 100644 (file)
@@ -20,8 +20,7 @@
 #define PROG_ID_MAX            7
 
 #define PROG_STATUS_MASK(id)   (1 << ((id) + 8))
-#define PROG_PRES_MASK         0x7
-#define PROG_PRES(layout, pckr)        ((pckr >> layout->pres_shift) & PROG_PRES_MASK)
+#define PROG_PRES(layout, pckr)        ((pckr >> layout->pres_shift) & layout->pres_mask)
 #define PROG_MAX_RM9200_CSS    3
 
 struct clk_programmable {
@@ -37,20 +36,29 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
                                                  unsigned long parent_rate)
 {
        struct clk_programmable *prog = to_clk_programmable(hw);
+       const struct clk_programmable_layout *layout = prog->layout;
        unsigned int pckr;
+       unsigned long rate;
 
        regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr);
 
-       return parent_rate >> PROG_PRES(prog->layout, pckr);
+       if (layout->is_pres_direct)
+               rate = parent_rate / (PROG_PRES(layout, pckr) + 1);
+       else
+               rate = parent_rate >> PROG_PRES(layout, pckr);
+
+       return rate;
 }
 
 static int clk_programmable_determine_rate(struct clk_hw *hw,
                                           struct clk_rate_request *req)
 {
+       struct clk_programmable *prog = to_clk_programmable(hw);
+       const struct clk_programmable_layout *layout = prog->layout;
        struct clk_hw *parent;
        long best_rate = -EINVAL;
        unsigned long parent_rate;
-       unsigned long tmp_rate;
+       unsigned long tmp_rate = 0;
        int shift;
        int i;
 
@@ -60,10 +68,18 @@ static int clk_programmable_determine_rate(struct clk_hw *hw,
                        continue;
 
                parent_rate = clk_hw_get_rate(parent);
-               for (shift = 0; shift < PROG_PRES_MASK; shift++) {
-                       tmp_rate = parent_rate >> shift;
-                       if (tmp_rate <= req->rate)
-                               break;
+               if (layout->is_pres_direct) {
+                       for (shift = 0; shift <= layout->pres_mask; shift++) {
+                               tmp_rate = parent_rate / (shift + 1);
+                               if (tmp_rate <= req->rate)
+                                       break;
+                       }
+               } else {
+                       for (shift = 0; shift < layout->pres_mask; shift++) {
+                               tmp_rate = parent_rate >> shift;
+                               if (tmp_rate <= req->rate)
+                                       break;
+                       }
                }
 
                if (tmp_rate > req->rate)
@@ -137,16 +153,23 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!div)
                return -EINVAL;
 
-       shift = fls(div) - 1;
+       if (layout->is_pres_direct) {
+               shift = div - 1;
 
-       if (div != (1 << shift))
-               return -EINVAL;
+               if (shift > layout->pres_mask)
+                       return -EINVAL;
+       } else {
+               shift = fls(div) - 1;
 
-       if (shift >= PROG_PRES_MASK)
-               return -EINVAL;
+               if (div != (1 << shift))
+                       return -EINVAL;
+
+               if (shift >= layout->pres_mask)
+                       return -EINVAL;
+       }
 
        regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id),
-                          PROG_PRES_MASK << layout->pres_shift,
+                          layout->pres_mask << layout->pres_shift,
                           shift << layout->pres_shift);
 
        return 0;
@@ -202,19 +225,25 @@ at91_clk_register_programmable(struct regmap *regmap,
 }
 
 const struct clk_programmable_layout at91rm9200_programmable_layout = {
+       .pres_mask = 0x7,
        .pres_shift = 2,
        .css_mask = 0x3,
        .have_slck_mck = 0,
+       .is_pres_direct = 0,
 };
 
 const struct clk_programmable_layout at91sam9g45_programmable_layout = {
+       .pres_mask = 0x7,
        .pres_shift = 2,
        .css_mask = 0x3,
        .have_slck_mck = 1,
+       .is_pres_direct = 0,
 };
 
 const struct clk_programmable_layout at91sam9x5_programmable_layout = {
+       .pres_mask = 0x7,
        .pres_shift = 4,
        .css_mask = 0x7,
        .have_slck_mck = 0,
+       .is_pres_direct = 0,
 };
index 672a79bda88c960d7655a600834705152f5a4eaf..a0e5ce9c9b9ea6981948ed102be4f8a870e6a99c 100644 (file)
@@ -71,9 +71,11 @@ struct clk_pll_characteristics {
 };
 
 struct clk_programmable_layout {
+       u8 pres_mask;
        u8 pres_shift;
        u8 css_mask;
        u8 have_slck_mck;
+       u8 is_pres_direct;
 };
 
 extern const struct clk_programmable_layout at91rm9200_programmable_layout;
index 1f70cb164b06f310d867d54797dfd0d87be0a1d3..81943fac4537ef3c8e8d0f611a897b2dd6b8171f 100644 (file)
@@ -125,6 +125,14 @@ static const struct {
          .pll = true },
 };
 
+static const struct clk_programmable_layout sama5d2_programmable_layout = {
+       .pres_mask = 0xff,
+       .pres_shift = 4,
+       .css_mask = 0x7,
+       .have_slck_mck = 0,
+       .is_pres_direct = 1,
+};
+
 static void __init sama5d2_pmc_setup(struct device_node *np)
 {
        struct clk_range range = CLK_RANGE(0, 0);
@@ -249,7 +257,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
 
                hw = at91_clk_register_programmable(regmap, name,
                                                    parent_names, 6, i,
-                                                   &at91sam9x5_programmable_layout);
+                                                   &sama5d2_programmable_layout);
                if (IS_ERR(hw))
                        goto err_free;
        }
index 1acfa3e3cfb401667fbb19666f1aac2add081826..113d71042199b3d3599da84df07e932b1c7902a9 100644 (file)
@@ -362,7 +362,7 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
 
        switch (pll_clk->type) {
        case PLL_1416X:
-               if (!pll->rate_table)
+               if (!pll_clk->rate_table)
                        init.ops = &clk_pll1416x_min_ops;
                else
                        init.ops = &clk_pll1416x_ops;
index 9628d4e7690bbdc632f2930bd6feb9653347595b..85daf826619ab4fe707b03211243279a06464625 100644 (file)
@@ -169,11 +169,10 @@ struct clk *mtk_clk_register_gate(
                return ERR_PTR(-ENOMEM);
 
        init.name = name;
-       init.flags = CLK_SET_RATE_PARENT;
+       init.flags = flags | CLK_SET_RATE_PARENT;
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
        init.ops = ops;
-       init.flags = flags;
 
        cg->regmap = regmap;
        cg->set_ofs = set_ofs;
index 41e16dd7272a5943c842eda7064bd6c0394c3664..7a14ac9b2fecfece592807d72c38043bb84c12e4 100644 (file)
@@ -120,7 +120,7 @@ static bool meson_clk_pll_is_better(unsigned long rate,
                        return true;
        } else {
                /* Round down */
-               if (now < rate && best < now)
+               if (now <= rate && best < now)
                        return true;
        }
 
index 0e1ce8c03259b73221266de7aa6491be331815f3..f7b11e1eeebe894c26425067fb5cf14cab09a029 100644 (file)
@@ -960,14 +960,14 @@ static struct clk_regmap g12a_sd_emmc_c_clk0 = {
 /* VPU Clock */
 
 static const char * const g12a_vpu_parent_names[] = {
-       "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7",
+       "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7",
        "mpll1", "vid_pll", "hifi_pll", "gp0_pll",
 };
 
 static struct clk_regmap g12a_vpu_0_sel = {
        .data = &(struct clk_regmap_mux_data){
                .offset = HHI_VPU_CLK_CNTL,
-               .mask = 0x3,
+               .mask = 0x7,
                .shift = 9,
        },
        .hw.init = &(struct clk_init_data){
@@ -1011,7 +1011,7 @@ static struct clk_regmap g12a_vpu_0 = {
 static struct clk_regmap g12a_vpu_1_sel = {
        .data = &(struct clk_regmap_mux_data){
                .offset = HHI_VPU_CLK_CNTL,
-               .mask = 0x3,
+               .mask = 0x7,
                .shift = 25,
        },
        .hw.init = &(struct clk_init_data){
index 04df2e208ed6ec7a493f62debdbf9051e0528038..29ffb4fde7145adefe855c11283825e1e4ea1f11 100644 (file)
@@ -2216,6 +2216,7 @@ static struct clk_regmap gxbb_vdec_1_div = {
                .offset = HHI_VDEC_CLK_CNTL,
                .shift = 0,
                .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "vdec_1_div",
@@ -2261,6 +2262,7 @@ static struct clk_regmap gxbb_vdec_hevc_div = {
                .offset = HHI_VDEC2_CLK_CNTL,
                .shift = 16,
                .width = 7,
+               .flags = CLK_DIVIDER_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "vdec_hevc_div",
index 08bcc01c0923863790d32dafbc1274bdf2358a28..daff235bc763348a03bebdcd9695cc8e08856744 100644 (file)
@@ -82,8 +82,8 @@ static unsigned long meson_vid_pll_div_recalc_rate(struct clk_hw *hw,
        div = _get_table_val(meson_parm_read(clk->map, &pll_div->val),
                             meson_parm_read(clk->map, &pll_div->sel));
        if (!div || !div->divider) {
-               pr_info("%s: Invalid config value for vid_pll_div\n", __func__);
-               return parent_rate;
+               pr_debug("%s: Invalid config value for vid_pll_div\n", __func__);
+               return 0;
        }
 
        return DIV_ROUND_UP_ULL(parent_rate * div->multiplier, div->divider);
index d977193842dfed1fead553dd2240013c5a0d380a..19174835693b91cd473b59c7fed787f128f268d1 100644 (file)
@@ -165,7 +165,7 @@ static const struct clk_ops plt_clk_ops = {
 };
 
 static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,
-                                       void __iomem *base,
+                                       const struct pmc_clk_data *pmc_data,
                                        const char **parent_names,
                                        int num_parents)
 {
@@ -184,9 +184,17 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,
        init.num_parents = num_parents;
 
        pclk->hw.init = &init;
-       pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
+       pclk->reg = pmc_data->base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
        spin_lock_init(&pclk->lock);
 
+       /*
+        * On some systems, the pmc_plt_clocks already enabled by the
+        * firmware are being marked as critical to avoid them being
+        * gated by the clock framework.
+        */
+       if (pmc_data->critical && plt_clk_is_enabled(&pclk->hw))
+               init.flags |= CLK_IS_CRITICAL;
+
        ret = devm_clk_hw_register(&pdev->dev, &pclk->hw);
        if (ret) {
                pclk = ERR_PTR(ret);
@@ -332,7 +340,7 @@ static int plt_clk_probe(struct platform_device *pdev)
                return PTR_ERR(parent_names);
 
        for (i = 0; i < PMC_CLK_NUM; i++) {
-               data->clks[i] = plt_clk_register(pdev, i, pmc_data->base,
+               data->clks[i] = plt_clk_register(pdev, i, pmc_data,
                                                 parent_names, data->nparents);
                if (IS_ERR(data->clks[i])) {
                        err = PTR_ERR(data->clks[i]);
index b1eadc6652b5f236897811357bd49ac364498f5e..7205d9f4029e11adb7f49d0e57bfdbf11b069fc0 100644 (file)
@@ -865,19 +865,18 @@ static int ahash_update_ctx(struct ahash_request *req)
                if (ret)
                        goto unmap_ctx;
 
-               if (mapped_nents) {
+               if (mapped_nents)
                        sg_to_sec4_sg_last(req->src, mapped_nents,
                                           edesc->sec4_sg + sec4_sg_src_index,
                                           0);
-                       if (*next_buflen)
-                               scatterwalk_map_and_copy(next_buf, req->src,
-                                                        to_hash - *buflen,
-                                                        *next_buflen, 0);
-               } else {
+               else
                        sg_to_sec4_set_last(edesc->sec4_sg + sec4_sg_src_index -
                                            1);
-               }
 
+               if (*next_buflen)
+                       scatterwalk_map_and_copy(next_buf, req->src,
+                                                to_hash - *buflen,
+                                                *next_buflen, 0);
                desc = edesc->hw_desc;
 
                edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
index a63e5f0dae56ad3de5a372ecd167a350d5b89457..db761329a1e3ef19d2fa05f86fdaf5b3b06c6b53 100644 (file)
@@ -1037,6 +1037,31 @@ void dw_hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_phy_i2c_write);
 
+/* Filter out invalid setups to avoid configuring SCDC and scrambling */
+static bool dw_hdmi_support_scdc(struct dw_hdmi *hdmi)
+{
+       struct drm_display_info *display = &hdmi->connector.display_info;
+
+       /* Completely disable SCDC support for older controllers */
+       if (hdmi->version < 0x200a)
+               return false;
+
+       /* Disable if SCDC is not supported, or if an HF-VSDB block is absent */
+       if (!display->hdmi.scdc.supported ||
+           !display->hdmi.scdc.scrambling.supported)
+               return false;
+
+       /*
+        * Disable if display only support low TMDS rates and scrambling
+        * for low rates is not supported either
+        */
+       if (!display->hdmi.scdc.scrambling.low_rates &&
+           display->max_tmds_clock <= 340000)
+               return false;
+
+       return true;
+}
+
 /*
  * HDMI2.0 Specifies the following procedure for High TMDS Bit Rates:
  * - The Source shall suspend transmission of the TMDS clock and data
@@ -1055,7 +1080,7 @@ void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi)
        unsigned long mtmdsclock = hdmi->hdmi_data.video_mode.mtmdsclock;
 
        /* Control for TMDS Bit Period/TMDS Clock-Period Ratio */
-       if (hdmi->connector.display_info.hdmi.scdc.supported) {
+       if (dw_hdmi_support_scdc(hdmi)) {
                if (mtmdsclock > HDMI14_MAX_TMDSCLK)
                        drm_scdc_set_high_tmds_clock_ratio(hdmi->ddc, 1);
                else
@@ -1579,8 +1604,9 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 
        /* Set up HDMI_FC_INVIDCONF */
        inv_val = (hdmi->hdmi_data.hdcp_enable ||
-                  vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
-                  hdmi_info->scdc.scrambling.low_rates ?
+                  (dw_hdmi_support_scdc(hdmi) &&
+                   (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
+                    hdmi_info->scdc.scrambling.low_rates)) ?
                HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
                HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
 
@@ -1646,7 +1672,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
        }
 
        /* Scrambling Control */
-       if (hdmi_info->scdc.supported) {
+       if (dw_hdmi_support_scdc(hdmi)) {
                if (vmode->mtmdsclock > HDMI14_MAX_TMDSCLK ||
                    hdmi_info->scdc.scrambling.low_rates) {
                        /*
index 40ac1984803459b7a0e8f67e09f81b61820035ef..fbb76332cc9f149c0cc037a6d35a5ed9c63d1baa 100644 (file)
@@ -1034,7 +1034,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
                        funcs->atomic_disable(crtc, old_crtc_state);
                else if (funcs->disable)
                        funcs->disable(crtc);
-               else
+               else if (funcs->dpms)
                        funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 
                if (!(dev->irq_enabled && dev->num_crtcs))
@@ -1277,10 +1277,9 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
                if (new_crtc_state->enable) {
                        DRM_DEBUG_ATOMIC("enabling [CRTC:%d:%s]\n",
                                         crtc->base.id, crtc->name);
-
                        if (funcs->atomic_enable)
                                funcs->atomic_enable(crtc, old_crtc_state);
-                       else
+                       else if (funcs->commit)
                                funcs->commit(crtc);
                }
        }
index 5d887f7cc0d5c91aebdcdb11e01569c86b891d27..69a9a1b2ea4ac44ba7d8f6530f99f59a9958076f 100644 (file)
@@ -209,7 +209,7 @@ static int vgpu_get_plane_info(struct drm_device *dev,
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_vgpu_primary_plane_format p;
        struct intel_vgpu_cursor_plane_format c;
-       int ret;
+       int ret, tile_height = 1;
 
        if (plane_id == DRM_PLANE_TYPE_PRIMARY) {
                ret = intel_vgpu_decode_primary_plane(vgpu, &p);
@@ -228,12 +228,15 @@ static int vgpu_get_plane_info(struct drm_device *dev,
                        break;
                case PLANE_CTL_TILED_X:
                        info->drm_format_mod = I915_FORMAT_MOD_X_TILED;
+                       tile_height = 8;
                        break;
                case PLANE_CTL_TILED_Y:
                        info->drm_format_mod = I915_FORMAT_MOD_Y_TILED;
+                       tile_height = 32;
                        break;
                case PLANE_CTL_TILED_YF:
                        info->drm_format_mod = I915_FORMAT_MOD_Yf_TILED;
+                       tile_height = 32;
                        break;
                default:
                        gvt_vgpu_err("invalid tiling mode: %x\n", p.tiled);
@@ -264,8 +267,8 @@ static int vgpu_get_plane_info(struct drm_device *dev,
                return -EINVAL;
        }
 
-       info->size = (info->stride * info->height + PAGE_SIZE - 1)
-                     >> PAGE_SHIFT;
+       info->size = (info->stride * roundup(info->height, tile_height)
+                     + PAGE_SIZE - 1) >> PAGE_SHIFT;
        if (info->size == 0) {
                gvt_vgpu_err("fb size is zero\n");
                return -EINVAL;
index cf133ef038735d64e6655b78c087992f5f1d1984..9814773882ec2b875ae2db00a22768deed72c618 100644 (file)
@@ -750,14 +750,20 @@ static void ppgtt_free_spt(struct intel_vgpu_ppgtt_spt *spt)
 
 static void ppgtt_free_all_spt(struct intel_vgpu *vgpu)
 {
-       struct intel_vgpu_ppgtt_spt *spt;
+       struct intel_vgpu_ppgtt_spt *spt, *spn;
        struct radix_tree_iter iter;
-       void **slot;
+       LIST_HEAD(all_spt);
+       void __rcu **slot;
 
+       rcu_read_lock();
        radix_tree_for_each_slot(slot, &vgpu->gtt.spt_tree, &iter, 0) {
                spt = radix_tree_deref_slot(slot);
-               ppgtt_free_spt(spt);
+               list_move(&spt->post_shadow_list, &all_spt);
        }
+       rcu_read_unlock();
+
+       list_for_each_entry_safe(spt, spn, &all_spt, post_shadow_list)
+               ppgtt_free_spt(spt);
 }
 
 static int ppgtt_handle_guest_write_page_table_bytes(
index d5fcc447d22f0d0663a4664c5767d72fa199cb0d..a68addf95c230f2edcc9b5b21860e9aee406bc27 100644 (file)
@@ -905,7 +905,7 @@ static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu, u64 off)
 static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, u64 off,
                void *buf, unsigned long count, bool is_write)
 {
-       void *aperture_va;
+       void __iomem *aperture_va;
 
        if (!intel_vgpu_in_aperture(vgpu, off) ||
            !intel_vgpu_in_aperture(vgpu, off + count)) {
@@ -920,9 +920,9 @@ static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, u64 off,
                return -EIO;
 
        if (is_write)
-               memcpy(aperture_va + offset_in_page(off), buf, count);
+               memcpy_toio(aperture_va + offset_in_page(off), buf, count);
        else
-               memcpy(buf, aperture_va + offset_in_page(off), count);
+               memcpy_fromio(buf, aperture_va + offset_in_page(off), count);
 
        io_mapping_unmap(aperture_va);
 
index 73a7bee24a663faa672ade21cfe7ea7cb1bc4b46..641e0778fa9c4123204f75091df3c53b5162a961 100644 (file)
@@ -323,6 +323,21 @@ static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
        }
 }
 
+static void get_dsi_io_power_domains(struct drm_i915_private *dev_priv,
+                                    struct intel_dsi *intel_dsi)
+{
+       enum port port;
+
+       for_each_dsi_port(port, intel_dsi->ports) {
+               WARN_ON(intel_dsi->io_wakeref[port]);
+               intel_dsi->io_wakeref[port] =
+                       intel_display_power_get(dev_priv,
+                                               port == PORT_A ?
+                                               POWER_DOMAIN_PORT_DDI_A_IO :
+                                               POWER_DOMAIN_PORT_DDI_B_IO);
+       }
+}
+
 static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@@ -336,13 +351,7 @@ static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
                I915_WRITE(ICL_DSI_IO_MODECTL(port), tmp);
        }
 
-       for_each_dsi_port(port, intel_dsi->ports) {
-               intel_dsi->io_wakeref[port] =
-                       intel_display_power_get(dev_priv,
-                                               port == PORT_A ?
-                                               POWER_DOMAIN_PORT_DDI_A_IO :
-                                               POWER_DOMAIN_PORT_DDI_B_IO);
-       }
+       get_dsi_io_power_domains(dev_priv, intel_dsi);
 }
 
 static void gen11_dsi_power_up_lanes(struct intel_encoder *encoder)
@@ -589,6 +598,12 @@ static void gen11_dsi_map_pll(struct intel_encoder *encoder,
                val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
        }
        I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+
+       for_each_dsi_port(port, intel_dsi->ports) {
+               val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
+       }
+       I915_WRITE(DPCLKA_CFGCR0_ICL, val);
+
        POSTING_READ(DPCLKA_CFGCR0_ICL);
 
        mutex_unlock(&dev_priv->dpll_lock);
@@ -1117,7 +1132,7 @@ static void gen11_dsi_disable_port(struct intel_encoder *encoder)
                        DRM_ERROR("DDI port:%c buffer not idle\n",
                                  port_name(port));
        }
-       gen11_dsi_ungate_clocks(encoder);
+       gen11_dsi_gate_clocks(encoder);
 }
 
 static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
@@ -1218,20 +1233,11 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder,
        return 0;
 }
 
-static u64 gen11_dsi_get_power_domains(struct intel_encoder *encoder,
-                                      struct intel_crtc_state *crtc_state)
+static void gen11_dsi_get_power_domains(struct intel_encoder *encoder,
+                                       struct intel_crtc_state *crtc_state)
 {
-       struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
-       u64 domains = 0;
-       enum port port;
-
-       for_each_dsi_port(port, intel_dsi->ports)
-               if (port == PORT_A)
-                       domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_A_IO);
-               else
-                       domains |= BIT_ULL(POWER_DOMAIN_PORT_DDI_B_IO);
-
-       return domains;
+       get_dsi_io_power_domains(to_i915(encoder->base.dev),
+                                enc_to_intel_dsi(&encoder->base));
 }
 
 static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
index 14d580cdefd3e875e08b7af0be350d4f877fb7ef..ab4e60dfd6a3460001cbcae4691f1ede8ebb230e 100644 (file)
@@ -2075,12 +2075,11 @@ intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port)
                                              intel_aux_power_domain(dig_port);
 }
 
-static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder,
-                                      struct intel_crtc_state *crtc_state)
+static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
+                                       struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_digital_port *dig_port;
-       u64 domains;
 
        /*
         * TODO: Add support for MST encoders. Atm, the following should never
@@ -2088,10 +2087,10 @@ static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder,
         * hook.
         */
        if (WARN_ON(intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)))
-               return 0;
+               return;
 
        dig_port = enc_to_dig_port(&encoder->base);
-       domains = BIT_ULL(dig_port->ddi_io_power_domain);
+       intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
 
        /*
         * AUX power is only needed for (e)DP mode, and for HDMI mode on TC
@@ -2099,15 +2098,15 @@ static u64 intel_ddi_get_power_domains(struct intel_encoder *encoder,
         */
        if (intel_crtc_has_dp_encoder(crtc_state) ||
            intel_port_is_tc(dev_priv, encoder->port))
-               domains |= BIT_ULL(intel_ddi_main_link_aux_domain(dig_port));
+               intel_display_power_get(dev_priv,
+                                       intel_ddi_main_link_aux_domain(dig_port));
 
        /*
         * VDSC power is needed when DSC is enabled
         */
        if (crtc_state->dsc_params.compression_enable)
-               domains |= BIT_ULL(intel_dsc_power_domain(crtc_state));
-
-       return domains;
+               intel_display_power_get(dev_priv,
+                                       intel_dsc_power_domain(crtc_state));
 }
 
 void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state)
@@ -2825,10 +2824,10 @@ void icl_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
                                return;
                }
                /*
-                * DSI ports should have their DDI clock ungated when disabled
-                * and gated when enabled.
+                * For DSI we keep the ddi clocks gated
+                * except during enable/disable sequence.
                 */
-               ddi_clk_needed = !encoder->base.crtc;
+               ddi_clk_needed = false;
        }
 
        val = I915_READ(DPCLKA_CFGCR0_ICL);
index ccb616351bba725052ea3a752cc5263744d58af2..421aac80a83815b9c1cfa40a7142e171cfd8bcd5 100644 (file)
@@ -15986,8 +15986,6 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)
        struct intel_encoder *encoder;
 
        for_each_intel_encoder(&dev_priv->drm, encoder) {
-               u64 get_domains;
-               enum intel_display_power_domain domain;
                struct intel_crtc_state *crtc_state;
 
                if (!encoder->get_power_domains)
@@ -16001,9 +15999,7 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)
                        continue;
 
                crtc_state = to_intel_crtc_state(encoder->base.crtc->state);
-               get_domains = encoder->get_power_domains(encoder, crtc_state);
-               for_each_power_domain(domain, get_domains)
-                       intel_display_power_get(dev_priv, domain);
+               encoder->get_power_domains(encoder, crtc_state);
        }
 }
 
index cf709835fb9a9eece3c0761c21c53c34a25b7e22..8891f29a8c7fffacad25f29e718376aa164261f7 100644 (file)
@@ -1859,42 +1859,6 @@ intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
        return -EINVAL;
 }
 
-/* Optimize link config in order: max bpp, min lanes, min clock */
-static int
-intel_dp_compute_link_config_fast(struct intel_dp *intel_dp,
-                                 struct intel_crtc_state *pipe_config,
-                                 const struct link_config_limits *limits)
-{
-       struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
-       int bpp, clock, lane_count;
-       int mode_rate, link_clock, link_avail;
-
-       for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) {
-               mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock,
-                                                  bpp);
-
-               for (lane_count = limits->min_lane_count;
-                    lane_count <= limits->max_lane_count;
-                    lane_count <<= 1) {
-                       for (clock = limits->min_clock; clock <= limits->max_clock; clock++) {
-                               link_clock = intel_dp->common_rates[clock];
-                               link_avail = intel_dp_max_data_rate(link_clock,
-                                                                   lane_count);
-
-                               if (mode_rate <= link_avail) {
-                                       pipe_config->lane_count = lane_count;
-                                       pipe_config->pipe_bpp = bpp;
-                                       pipe_config->port_clock = link_clock;
-
-                                       return 0;
-                               }
-                       }
-               }
-       }
-
-       return -EINVAL;
-}
-
 static int intel_dp_dsc_compute_bpp(struct intel_dp *intel_dp, u8 dsc_max_bpc)
 {
        int i, num_bpc;
@@ -2031,15 +1995,13 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
        limits.min_bpp = 6 * 3;
        limits.max_bpp = intel_dp_compute_bpp(intel_dp, pipe_config);
 
-       if (intel_dp_is_edp(intel_dp) && intel_dp->edp_dpcd[0] < DP_EDP_14) {
+       if (intel_dp_is_edp(intel_dp)) {
                /*
                 * Use the maximum clock and number of lanes the eDP panel
-                * advertizes being capable of. The eDP 1.3 and earlier panels
-                * are generally designed to support only a single clock and
-                * lane configuration, and typically these values correspond to
-                * the native resolution of the panel. With eDP 1.4 rate select
-                * and DSC, this is decreasingly the case, and we need to be
-                * able to select less than maximum link config.
+                * advertizes being capable of. The panels are generally
+                * designed to support only a single clock and lane
+                * configuration, and typically these values correspond to the
+                * native resolution of the panel.
                 */
                limits.min_lane_count = limits.max_lane_count;
                limits.min_clock = limits.max_clock;
@@ -2053,22 +2015,11 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
                      intel_dp->common_rates[limits.max_clock],
                      limits.max_bpp, adjusted_mode->crtc_clock);
 
-       if (intel_dp_is_edp(intel_dp))
-               /*
-                * Optimize for fast and narrow. eDP 1.3 section 3.3 and eDP 1.4
-                * section A.1: "It is recommended that the minimum number of
-                * lanes be used, using the minimum link rate allowed for that
-                * lane configuration."
-                *
-                * Note that we use the max clock and lane count for eDP 1.3 and
-                * earlier, and fast vs. wide is irrelevant.
-                */
-               ret = intel_dp_compute_link_config_fast(intel_dp, pipe_config,
-                                                       &limits);
-       else
-               /* Optimize for slow and wide. */
-               ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config,
-                                                       &limits);
+       /*
+        * Optimize for slow and wide. This is the place to add alternative
+        * optimization policy.
+        */
+       ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits);
 
        /* enable compression if the mode doesn't fit available BW */
        DRM_DEBUG_KMS("Force DSC en = %d\n", intel_dp->force_dsc_en);
index 15db41394b9ed75d9de8545c8a0faff9efbc9a9b..d5660ac1b0d60999d8788710a0140ec2f8d38570 100644 (file)
@@ -270,10 +270,12 @@ struct intel_encoder {
         * be set correctly before calling this function. */
        void (*get_config)(struct intel_encoder *,
                           struct intel_crtc_state *pipe_config);
-       /* Returns a mask of power domains that need to be referenced as part
-        * of the hardware state readout code. */
-       u64 (*get_power_domains)(struct intel_encoder *encoder,
-                                struct intel_crtc_state *crtc_state);
+       /*
+        * Acquires the power domains needed for an active encoder during
+        * hardware state readout.
+        */
+       void (*get_power_domains)(struct intel_encoder *encoder,
+                                 struct intel_crtc_state *crtc_state);
        /*
         * Called during system suspend after all pending requests for the
         * encoder are flushed (for example for DP AUX transactions) and
index 6403728fe7784f54977b0c318d790ea886553a04..31c93c3ccd00ffa62c3158d159d7cc4afd8f9ae5 100644 (file)
@@ -256,6 +256,28 @@ static void band_gap_reset(struct drm_i915_private *dev_priv)
        mutex_unlock(&dev_priv->sb_lock);
 }
 
+static int bdw_get_pipemisc_bpp(struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+       u32 tmp;
+
+       tmp = I915_READ(PIPEMISC(crtc->pipe));
+
+       switch (tmp & PIPEMISC_DITHER_BPC_MASK) {
+       case PIPEMISC_DITHER_6_BPC:
+               return 18;
+       case PIPEMISC_DITHER_8_BPC:
+               return 24;
+       case PIPEMISC_DITHER_10_BPC:
+               return 30;
+       case PIPEMISC_DITHER_12_BPC:
+               return 36;
+       default:
+               MISSING_CASE(tmp);
+               return 0;
+       }
+}
+
 static int intel_dsi_compute_config(struct intel_encoder *encoder,
                                    struct intel_crtc_state *pipe_config,
                                    struct drm_connector_state *conn_state)
@@ -1071,6 +1093,8 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
        bpp = mipi_dsi_pixel_format_to_bpp(
                        pixel_format_from_register_bits(fmt));
 
+       pipe_config->pipe_bpp = bdw_get_pipemisc_bpp(crtc);
+
        /* Enable Frame time stamo based scanline reporting */
        adjusted_mode->private_flags |=
                        I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP;
index 340383150fb98d24567b6ca74cae0298cda806b6..ebf9c96d43eee56649e510a5ca8c53a045b10c67 100644 (file)
@@ -175,6 +175,7 @@ static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
                REG_FLD_MOD(core->base, HDMI_CORE_SYS_INTR_UNMASK4, 0, 3, 3);
                hdmi_wp_clear_irqenable(core->wp, HDMI_IRQ_CORE);
                hdmi_wp_set_irqstatus(core->wp, HDMI_IRQ_CORE);
+               REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0);
                hdmi4_core_disable(core);
                return 0;
        }
@@ -182,16 +183,24 @@ static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
        if (err)
                return err;
 
+       /*
+        * Initialize CEC clock divider: CEC needs 2MHz clock hence
+        * set the divider to 24 to get 48/24=2MHz clock
+        */
+       REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0x18, 5, 0);
+
        /* Clear TX FIFO */
        if (!hdmi_cec_clear_tx_fifo(adap)) {
                pr_err("cec-%s: could not clear TX FIFO\n", adap->name);
-               return -EIO;
+               err = -EIO;
+               goto err_disable_clk;
        }
 
        /* Clear RX FIFO */
        if (!hdmi_cec_clear_rx_fifo(adap)) {
                pr_err("cec-%s: could not clear RX FIFO\n", adap->name);
-               return -EIO;
+               err = -EIO;
+               goto err_disable_clk;
        }
 
        /* Clear CEC interrupts */
@@ -236,6 +245,12 @@ static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
                hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, temp);
        }
        return 0;
+
+err_disable_clk:
+       REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0);
+       hdmi4_core_disable(core);
+
+       return err;
 }
 
 static int hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
@@ -333,11 +348,8 @@ int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core,
                return ret;
        core->wp = wp;
 
-       /*
-        * Initialize CEC clock divider: CEC needs 2MHz clock hence
-        * set the devider to 24 to get 48/24=2MHz clock
-        */
-       REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0x18, 5, 0);
+       /* Disable clock initially, hdmi_cec_adap_enable() manages it */
+       REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0, 5, 0);
 
        ret = cec_register_adapter(core->adap, &pdev->dev);
        if (ret < 0) {
index 813ba42f27539ce94b85afc20295e411f6b4c123..e384b95ad8573a7ef9ad9bb9a631432eda4a726f 100644 (file)
@@ -708,7 +708,7 @@ int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
        else
                acore.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
        /*
-        * The I2S input word length is twice the lenght given in the IEC-60958
+        * The I2S input word length is twice the length given in the IEC-60958
         * status word. If the word size is greater than
         * 20 bits, increment by one.
         */
index dc47720c99ba5689a8c12f217c7859960bfa394d..39d8509d96a0d3162f8bd7c310f4aa0a18898f6b 100644 (file)
@@ -48,8 +48,13 @@ static enum drm_mode_status
 sun8i_dw_hdmi_mode_valid_h6(struct drm_connector *connector,
                            const struct drm_display_mode *mode)
 {
-       /* This is max for HDMI 2.0b (4K@60Hz) */
-       if (mode->clock > 594000)
+       /*
+        * Controller support maximum of 594 MHz, which correlates to
+        * 4K@60Hz 4:4:4 or RGB. However, for frequencies greater than
+        * 340 MHz scrambling has to be enabled. Because scrambling is
+        * not yet implemented, just limit to 340 MHz for now.
+        */
+       if (mode->clock > 340000)
                return MODE_CLOCK_HIGH;
 
        return MODE_OK;
index fc36e0c10a374a2a33a054a4102944dfb0b03009..b1e7c76e9c17269664fddd5ab5c90c3477b80a0c 100644 (file)
@@ -227,7 +227,7 @@ static int sun8i_tcon_top_bind(struct device *dev, struct device *master,
 
 err_unregister_gates:
        for (i = 0; i < CLK_NUM; i++)
-               if (clk_data->hws[i])
+               if (!IS_ERR_OR_NULL(clk_data->hws[i]))
                        clk_hw_unregister_gate(clk_data->hws[i]);
        clk_disable_unprepare(tcon_top->bus);
 err_assert_reset:
@@ -245,7 +245,8 @@ static void sun8i_tcon_top_unbind(struct device *dev, struct device *master,
 
        of_clk_del_provider(dev->of_node);
        for (i = 0; i < CLK_NUM; i++)
-               clk_hw_unregister_gate(clk_data->hws[i]);
+               if (clk_data->hws[i])
+                       clk_hw_unregister_gate(clk_data->hws[i]);
 
        clk_disable_unprepare(tcon_top->bus);
        reset_control_assert(tcon_top->rst);
index 47c55974756d576b71193219b92d976078006b4e..d23c4bfde790ca0864722e8b1eb2907b7c9ee24f 100644 (file)
@@ -1260,9 +1260,15 @@ static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder)
 
        hdmi->dvi = !tegra_output_is_hdmi(output);
        if (!hdmi->dvi) {
-               err = tegra_hdmi_setup_audio(hdmi);
-               if (err < 0)
-                       hdmi->dvi = true;
+               /*
+                * Make sure that the audio format has been configured before
+                * enabling audio, otherwise we may try to divide by zero.
+               */
+               if (hdmi->format.sample_rate > 0) {
+                       err = tegra_hdmi_setup_audio(hdmi);
+                       if (err < 0)
+                               hdmi->dvi = true;
+               }
        }
 
        if (hdmi->config->has_hda)
index 4030d64916f004a03781fc7c5b7a36173bcf344f..0c0eb43abf657f2369872b3f5026b3a965f4a298 100644 (file)
@@ -114,9 +114,13 @@ static inline void synchronize_syncpt_base(struct host1x_job *job)
 
 static void host1x_channel_set_streamid(struct host1x_channel *channel)
 {
-#if IS_ENABLED(CONFIG_IOMMU_API) &&  HOST1X_HW >= 6
+#if HOST1X_HW >= 6
+       u32 sid = 0x7f;
+#ifdef CONFIG_IOMMU_API
        struct iommu_fwspec *spec = dev_iommu_fwspec_get(channel->dev->parent);
-       u32 sid = spec ? spec->ids[0] & 0xffff : 0x7f;
+       if (spec)
+               sid = spec->ids[0] & 0xffff;
+#endif
 
        host1x_ch_writel(channel, sid, HOST1X_CHANNEL_SMMU_STREAMID);
 #endif
index 612f04190ed8386e51ab5f8321464320140c1e77..9784c6c0d2ecfbbca031871f54fcc415602029fc 100644 (file)
@@ -13232,7 +13232,7 @@ static int set_up_context_variables(struct hfi1_devdata *dd)
        int total_contexts;
        int ret;
        unsigned ngroups;
-       int qos_rmt_count;
+       int rmt_count;
        int user_rmt_reduced;
        u32 n_usr_ctxts;
        u32 send_contexts = chip_send_contexts(dd);
@@ -13294,10 +13294,20 @@ static int set_up_context_variables(struct hfi1_devdata *dd)
                n_usr_ctxts = rcv_contexts - total_contexts;
        }
 
-       /* each user context requires an entry in the RMT */
-       qos_rmt_count = qos_rmt_entries(dd, NULL, NULL);
-       if (qos_rmt_count + n_usr_ctxts > NUM_MAP_ENTRIES) {
-               user_rmt_reduced = NUM_MAP_ENTRIES - qos_rmt_count;
+       /*
+        * The RMT entries are currently allocated as shown below:
+        * 1. QOS (0 to 128 entries);
+        * 2. FECN for PSM (num_user_contexts + num_vnic_contexts);
+        * 3. VNIC (num_vnic_contexts).
+        * It should be noted that PSM FECN oversubscribe num_vnic_contexts
+        * entries of RMT because both VNIC and PSM could allocate any receive
+        * context between dd->first_dyn_alloc_text and dd->num_rcv_contexts,
+        * and PSM FECN must reserve an RMT entry for each possible PSM receive
+        * context.
+        */
+       rmt_count = qos_rmt_entries(dd, NULL, NULL) + (num_vnic_contexts * 2);
+       if (rmt_count + n_usr_ctxts > NUM_MAP_ENTRIES) {
+               user_rmt_reduced = NUM_MAP_ENTRIES - rmt_count;
                dd_dev_err(dd,
                           "RMT size is reducing the number of user receive contexts from %u to %d\n",
                           n_usr_ctxts,
@@ -14285,9 +14295,11 @@ static void init_user_fecn_handling(struct hfi1_devdata *dd,
        u64 reg;
        int i, idx, regoff, regidx;
        u8 offset;
+       u32 total_cnt;
 
        /* there needs to be enough room in the map table */
-       if (rmt->used + dd->num_user_contexts >= NUM_MAP_ENTRIES) {
+       total_cnt = dd->num_rcv_contexts - dd->first_dyn_alloc_ctxt;
+       if (rmt->used + total_cnt >= NUM_MAP_ENTRIES) {
                dd_dev_err(dd, "User FECN handling disabled - too many user contexts allocated\n");
                return;
        }
@@ -14341,7 +14353,7 @@ static void init_user_fecn_handling(struct hfi1_devdata *dd,
        /* add rule 1 */
        add_rsm_rule(dd, RSM_INS_FECN, &rrd);
 
-       rmt->used += dd->num_user_contexts;
+       rmt->used += total_cnt;
 }
 
 /* Initialize RSM for VNIC */
index 9b643c2409cf8bee5c28084b104c2839bc5768aa..eba300330a027acdae1b97c92af5ef07ece6b605 100644 (file)
@@ -898,7 +898,9 @@ void notify_error_qp(struct rvt_qp *qp)
                if (!list_empty(&priv->s_iowait.list) &&
                    !(qp->s_flags & RVT_S_BUSY) &&
                    !(priv->s_flags & RVT_S_BUSY)) {
-                       qp->s_flags &= ~RVT_S_ANY_WAIT_IO;
+                       qp->s_flags &= ~HFI1_S_ANY_WAIT_IO;
+                       iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_IB);
+                       iowait_clear_flag(&priv->s_iowait, IOWAIT_PENDING_TID);
                        list_del_init(&priv->s_iowait.list);
                        priv->s_iowait.lock = NULL;
                        rvt_put_qp(qp);
index e6726c1ab8669a66722835b43d8b6b3481a11754..5991211d72bdd84d307ab4ebc245a011899eb4bc 100644 (file)
@@ -3088,7 +3088,7 @@ send_last:
                        update_ack_queue(qp, next);
                }
                e = &qp->s_ack_queue[qp->r_head_ack_queue];
-               if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) {
+               if (e->rdma_sge.mr) {
                        rvt_put_mr(e->rdma_sge.mr);
                        e->rdma_sge.mr = NULL;
                }
@@ -3166,7 +3166,7 @@ send_last:
                        update_ack_queue(qp, next);
                }
                e = &qp->s_ack_queue[qp->r_head_ack_queue];
-               if (e->opcode == OP(RDMA_READ_REQUEST) && e->rdma_sge.mr) {
+               if (e->rdma_sge.mr) {
                        rvt_put_mr(e->rdma_sge.mr);
                        e->rdma_sge.mr = NULL;
                }
index fdda33aca77f2031ea2357435c029de0508ffdec..43cbce7a19ea43f42af2464a782221da2ee386bf 100644 (file)
@@ -5017,24 +5017,14 @@ int hfi1_make_tid_rdma_pkt(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
            make_tid_rdma_ack(qp, ohdr, ps))
                return 1;
 
-       if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_SEND_OK)) {
-               if (!(ib_rvt_state_ops[qp->state] & RVT_FLUSH_SEND))
-                       goto bail;
-               /* We are in the error state, flush the work request. */
-               if (qp->s_last == READ_ONCE(qp->s_head))
-                       goto bail;
-               /* If DMAs are in progress, we can't flush immediately. */
-               if (iowait_sdma_pending(&priv->s_iowait)) {
-                       qp->s_flags |= RVT_S_WAIT_DMA;
-                       goto bail;
-               }
-               clear_ahg(qp);
-               wqe = rvt_get_swqe_ptr(qp, qp->s_last);
-               hfi1_trdma_send_complete(qp, wqe, qp->s_last != qp->s_acked ?
-                                        IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR);
-               /* will get called again */
-               goto done_free_tx;
-       }
+       /*
+        * Bail out if we can't send data.
+        * Be reminded that this check must been done after the call to
+        * make_tid_rdma_ack() because the responding QP could be in
+        * RTR state where it can send TID RDMA ACK, not TID RDMA WRITE DATA.
+        */
+       if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_SEND_OK))
+               goto bail;
 
        if (priv->s_flags & RVT_S_WAIT_ACK)
                goto bail;
@@ -5144,11 +5134,6 @@ int hfi1_make_tid_rdma_pkt(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
        hfi1_make_ruc_header(qp, ohdr, (opcode << 24), bth1, bth2,
                             middle, ps);
        return 1;
-done_free_tx:
-       hfi1_put_txreq(ps->s_txreq);
-       ps->s_txreq = NULL;
-       return 1;
-
 bail:
        hfi1_put_txreq(ps->s_txreq);
 bail_no_tx:
index f1fec56f3ff49047d7ade725d13b43d3dba8bbb6..8e29dbb5b5fbc3bd883384915e76155201572848 100644 (file)
@@ -792,6 +792,8 @@ void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
                idx_offset = (obj & (table->num_obj - 1)) % obj_per_chunk;
                dma_offset = offset = idx_offset * table->obj_size;
        } else {
+               u32 seg_size = 64; /* 8 bytes per BA and 8 BA per segment */
+
                hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
                /* mtt mhop */
                i = mhop.l0_idx;
@@ -803,8 +805,8 @@ void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
                        hem_idx = i;
 
                hem = table->hem[hem_idx];
-               dma_offset = offset = (obj & (table->num_obj - 1)) *
-                                      table->obj_size % mhop.bt_chunk_size;
+               dma_offset = offset = (obj & (table->num_obj - 1)) * seg_size %
+                                      mhop.bt_chunk_size;
                if (mhop.hop_num == 2)
                        dma_offset = offset = 0;
        }
index b09f1cde2ff54ca9522a60d21ba3e82967938574..08be0e4eabcd764e9af0a666cec02fad1e921f76 100644 (file)
@@ -746,7 +746,6 @@ static int hns_roce_write_mtt_chunk(struct hns_roce_dev *hr_dev,
        struct hns_roce_hem_table *table;
        dma_addr_t dma_handle;
        __le64 *mtts;
-       u32 s = start_index * sizeof(u64);
        u32 bt_page_size;
        u32 i;
 
@@ -780,7 +779,8 @@ static int hns_roce_write_mtt_chunk(struct hns_roce_dev *hr_dev,
                return -EINVAL;
 
        mtts = hns_roce_table_find(hr_dev, table,
-                               mtt->first_seg + s / hr_dev->caps.mtt_entry_sz,
+                               mtt->first_seg +
+                               start_index / HNS_ROCE_MTT_ENTRY_PER_SEG,
                                &dma_handle);
        if (!mtts)
                return -ENOMEM;
index 57c76eafef2f8a896ff336af5bfa10954c99f1e4..66cdf625534ff8901a6efdf90295eaee3cc0145f 100644 (file)
@@ -274,9 +274,6 @@ void hns_roce_qp_free(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
        wait_for_completion(&hr_qp->free);
 
        if ((hr_qp->ibqp.qp_type) != IB_QPT_GSI) {
-               if (hr_dev->caps.sccc_entry_sz)
-                       hns_roce_table_put(hr_dev, &qp_table->sccc_table,
-                                          hr_qp->qpn);
                if (hr_dev->caps.trrl_entry_sz)
                        hns_roce_table_put(hr_dev, &qp_table->trrl_table,
                                           hr_qp->qpn);
index c20bfc41ecf18602cd0f289941d49dd6d37390da..0aa10ebda5d9af2f60f5d98807a2de6ec307ad04 100644 (file)
@@ -585,7 +585,7 @@ static int pagefault_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr,
        struct ib_umem_odp *odp_mr = to_ib_umem_odp(mr->umem);
        bool downgrade = flags & MLX5_PF_FLAGS_DOWNGRADE;
        bool prefetch = flags & MLX5_PF_FLAGS_PREFETCH;
-       u64 access_mask = ODP_READ_ALLOWED_BIT;
+       u64 access_mask;
        u64 start_idx, page_mask;
        struct ib_umem_odp *odp;
        size_t size;
@@ -607,6 +607,7 @@ next_mr:
        page_shift = mr->umem->page_shift;
        page_mask = ~(BIT(page_shift) - 1);
        start_idx = (io_virt - (mr->mmkey.iova & page_mask)) >> page_shift;
+       access_mask = ODP_READ_ALLOWED_BIT;
 
        if (prefetch && !downgrade && !mr->umem->writable) {
                /* prefetch with write-access must
index 6d8b3e0de57a8e0d3e8071d9aebd0707618cebb4..ec41400fec0c01aa4d2894b7652701a90a190fff 100644 (file)
@@ -1131,6 +1131,8 @@ static void pvrdma_pci_remove(struct pci_dev *pdev)
        pvrdma_page_dir_cleanup(dev, &dev->cq_pdir);
        pvrdma_page_dir_cleanup(dev, &dev->async_pdir);
        pvrdma_free_slots(dev);
+       dma_free_coherent(&pdev->dev, sizeof(*dev->dsr), dev->dsr,
+                         dev->dsrbase);
 
        iounmap(dev->regs);
        kfree(dev->sgid_tbl);
index 1b1378619fc9ec2f0caa0bbbd262192c21de61e4..ff40ba758cf365e89ddeb2270971e1536554b817 100644 (file)
@@ -359,7 +359,7 @@ static void iommu_write_l2(struct amd_iommu *iommu, u8 address, u32 val)
 static void iommu_set_exclusion_range(struct amd_iommu *iommu)
 {
        u64 start = iommu->exclusion_start & PAGE_MASK;
-       u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
+       u64 limit = (start + iommu->exclusion_length - 1) & PAGE_MASK;
        u64 entry;
 
        if (!iommu->exclusion_start)
index 86b72fbd3b45dd63f495de36435410997740f473..353111a104133a0faeadf5d46e3e2f1bbf617d27 100644 (file)
@@ -130,6 +130,7 @@ static int __init ls1x_intc_of_init(struct device_node *node,
                                             NULL);
        if (!priv->domain) {
                pr_err("ls1x-irq: cannot add IRQ domain\n");
+               err = -ENOMEM;
                goto out_iounmap;
        }
 
index 3789185144dae34241911d3c42308e6cbad650f2..0b7d5fb4548dcd8720f86e98a2567e3d387a061d 100644 (file)
@@ -231,14 +231,14 @@ static void pblk_end_partial_read(struct nvm_rq *rqd)
        struct pblk_sec_meta *meta;
        struct bio *new_bio = rqd->bio;
        struct bio *bio = pr_ctx->orig_bio;
-       struct bio_vec src_bv, dst_bv;
        void *meta_list = rqd->meta_list;
-       int bio_init_idx = pr_ctx->bio_init_idx;
        unsigned long *read_bitmap = pr_ctx->bitmap;
+       struct bvec_iter orig_iter = BVEC_ITER_ALL_INIT;
+       struct bvec_iter new_iter = BVEC_ITER_ALL_INIT;
        int nr_secs = pr_ctx->orig_nr_secs;
        int nr_holes = nr_secs - bitmap_weight(read_bitmap, nr_secs);
        void *src_p, *dst_p;
-       int hole, i;
+       int bit, i;
 
        if (unlikely(nr_holes == 1)) {
                struct ppa_addr ppa;
@@ -257,33 +257,39 @@ static void pblk_end_partial_read(struct nvm_rq *rqd)
 
        /* Fill the holes in the original bio */
        i = 0;
-       hole = find_first_zero_bit(read_bitmap, nr_secs);
-       do {
-               struct pblk_line *line;
+       for (bit = 0; bit < nr_secs; bit++) {
+               if (!test_bit(bit, read_bitmap)) {
+                       struct bio_vec dst_bv, src_bv;
+                       struct pblk_line *line;
 
-               line = pblk_ppa_to_line(pblk, rqd->ppa_list[i]);
-               kref_put(&line->ref, pblk_line_put);
+                       line = pblk_ppa_to_line(pblk, rqd->ppa_list[i]);
+                       kref_put(&line->ref, pblk_line_put);
 
-               meta = pblk_get_meta(pblk, meta_list, hole);
-               meta->lba = cpu_to_le64(pr_ctx->lba_list_media[i]);
+                       meta = pblk_get_meta(pblk, meta_list, bit);
+                       meta->lba = cpu_to_le64(pr_ctx->lba_list_media[i]);
 
-               src_bv = new_bio->bi_io_vec[i++];
-               dst_bv = bio->bi_io_vec[bio_init_idx + hole];
+                       dst_bv = bio_iter_iovec(bio, orig_iter);
+                       src_bv = bio_iter_iovec(new_bio, new_iter);
 
-               src_p = kmap_atomic(src_bv.bv_page);
-               dst_p = kmap_atomic(dst_bv.bv_page);
+                       src_p = kmap_atomic(src_bv.bv_page);
+                       dst_p = kmap_atomic(dst_bv.bv_page);
 
-               memcpy(dst_p + dst_bv.bv_offset,
-                       src_p + src_bv.bv_offset,
-                       PBLK_EXPOSED_PAGE_SIZE);
+                       memcpy(dst_p + dst_bv.bv_offset,
+                               src_p + src_bv.bv_offset,
+                               PBLK_EXPOSED_PAGE_SIZE);
 
-               kunmap_atomic(src_p);
-               kunmap_atomic(dst_p);
+                       kunmap_atomic(src_p);
+                       kunmap_atomic(dst_p);
 
-               mempool_free(src_bv.bv_page, &pblk->page_bio_pool);
+                       flush_dcache_page(dst_bv.bv_page);
+                       mempool_free(src_bv.bv_page, &pblk->page_bio_pool);
 
-               hole = find_next_zero_bit(read_bitmap, nr_secs, hole + 1);
-       } while (hole < nr_secs);
+                       bio_advance_iter(new_bio, &new_iter,
+                                       PBLK_EXPOSED_PAGE_SIZE);
+                       i++;
+               }
+               bio_advance_iter(bio, &orig_iter, PBLK_EXPOSED_PAGE_SIZE);
+       }
 
        bio_put(new_bio);
        kfree(pr_ctx);
index 82a97866e0cf4c857cbb25c5487a3c6f80addfa0..7c8f203f9a24d38bbd1c2b870644e511a1db76d3 100644 (file)
@@ -48,7 +48,6 @@ struct alcor_sdmmc_host {
        struct mmc_command *cmd;
        struct mmc_data *data;
        unsigned int dma_on:1;
-       unsigned int early_data:1;
 
        struct mutex cmd_mutex;
 
@@ -144,8 +143,7 @@ static void alcor_data_set_dma(struct alcor_sdmmc_host *host)
        host->sg_count--;
 }
 
-static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host,
-                                       bool early)
+static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host)
 {
        struct alcor_pci_priv *priv = host->alcor_pci;
        struct mmc_data *data = host->data;
@@ -155,13 +153,6 @@ static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host,
                ctrl |= AU6601_DATA_WRITE;
 
        if (data->host_cookie == COOKIE_MAPPED) {
-               if (host->early_data) {
-                       host->early_data = false;
-                       return;
-               }
-
-               host->early_data = early;
-
                alcor_data_set_dma(host);
                ctrl |= AU6601_DATA_DMA_MODE;
                host->dma_on = 1;
@@ -231,6 +222,7 @@ static void alcor_prepare_sg_miter(struct alcor_sdmmc_host *host)
 static void alcor_prepare_data(struct alcor_sdmmc_host *host,
                               struct mmc_command *cmd)
 {
+       struct alcor_pci_priv *priv = host->alcor_pci;
        struct mmc_data *data = cmd->data;
 
        if (!data)
@@ -248,7 +240,7 @@ static void alcor_prepare_data(struct alcor_sdmmc_host *host,
        if (data->host_cookie != COOKIE_MAPPED)
                alcor_prepare_sg_miter(host);
 
-       alcor_trigger_data_transfer(host, true);
+       alcor_write8(priv, 0, AU6601_DATA_XFER_CTRL);
 }
 
 static void alcor_send_cmd(struct alcor_sdmmc_host *host,
@@ -435,7 +427,7 @@ static int alcor_cmd_irq_done(struct alcor_sdmmc_host *host, u32 intmask)
        if (!host->data)
                return false;
 
-       alcor_trigger_data_transfer(host, false);
+       alcor_trigger_data_transfer(host);
        host->cmd = NULL;
        return true;
 }
@@ -456,7 +448,7 @@ static void alcor_cmd_irq_thread(struct alcor_sdmmc_host *host, u32 intmask)
        if (!host->data)
                alcor_request_complete(host, 1);
        else
-               alcor_trigger_data_transfer(host, false);
+               alcor_trigger_data_transfer(host);
        host->cmd = NULL;
 }
 
@@ -487,15 +479,9 @@ static int alcor_data_irq_done(struct alcor_sdmmc_host *host, u32 intmask)
                break;
        case AU6601_INT_READ_BUF_RDY:
                alcor_trf_block_pio(host, true);
-               if (!host->blocks)
-                       break;
-               alcor_trigger_data_transfer(host, false);
                return 1;
        case AU6601_INT_WRITE_BUF_RDY:
                alcor_trf_block_pio(host, false);
-               if (!host->blocks)
-                       break;
-               alcor_trigger_data_transfer(host, false);
                return 1;
        case AU6601_INT_DMA_END:
                if (!host->sg_count)
@@ -508,8 +494,14 @@ static int alcor_data_irq_done(struct alcor_sdmmc_host *host, u32 intmask)
                break;
        }
 
-       if (intmask & AU6601_INT_DATA_END)
-               return 0;
+       if (intmask & AU6601_INT_DATA_END) {
+               if (!host->dma_on && host->blocks) {
+                       alcor_trigger_data_transfer(host);
+                       return 1;
+               } else {
+                       return 0;
+               }
+       }
 
        return 1;
 }
index 5bbed477c9b1ee6546f066e55fd9946ed4a160b6..9f20fff9781b0791ea36c1bd3cd657dd1b50e8c6 100644 (file)
@@ -797,6 +797,43 @@ void sdhci_omap_reset(struct sdhci_host *host, u8 mask)
        sdhci_reset(host, mask);
 }
 
+#define CMD_ERR_MASK (SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX |\
+                     SDHCI_INT_TIMEOUT)
+#define CMD_MASK (CMD_ERR_MASK | SDHCI_INT_RESPONSE)
+
+static u32 sdhci_omap_irq(struct sdhci_host *host, u32 intmask)
+{
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host);
+
+       if (omap_host->is_tuning && host->cmd && !host->data_early &&
+           (intmask & CMD_ERR_MASK)) {
+
+               /*
+                * Since we are not resetting data lines during tuning
+                * operation, data error or data complete interrupts
+                * might still arrive. Mark this request as a failure
+                * but still wait for the data interrupt
+                */
+               if (intmask & SDHCI_INT_TIMEOUT)
+                       host->cmd->error = -ETIMEDOUT;
+               else
+                       host->cmd->error = -EILSEQ;
+
+               host->cmd = NULL;
+
+               /*
+                * Sometimes command error interrupts and command complete
+                * interrupt will arrive together. Clear all command related
+                * interrupts here.
+                */
+               sdhci_writel(host, intmask & CMD_MASK, SDHCI_INT_STATUS);
+               intmask &= ~CMD_MASK;
+       }
+
+       return intmask;
+}
+
 static struct sdhci_ops sdhci_omap_ops = {
        .set_clock = sdhci_omap_set_clock,
        .set_power = sdhci_omap_set_power,
@@ -807,6 +844,7 @@ static struct sdhci_ops sdhci_omap_ops = {
        .platform_send_init_74_clocks = sdhci_omap_init_74_clocks,
        .reset = sdhci_omap_reset,
        .set_uhs_signaling = sdhci_omap_set_uhs_signaling,
+       .irq = sdhci_omap_irq,
 };
 
 static int sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host)
index 0bb9d7b3a2b622211a2d401fd81dd70f6cff4ea0..4c586ba4364bab671d011877bde4fee1a2c30083 100644 (file)
@@ -1133,6 +1133,8 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
        tpa_info = &rxr->rx_tpa[agg_id];
 
        if (unlikely(cons != rxr->rx_next_cons)) {
+               netdev_warn(bp->dev, "TPA cons %x != expected cons %x\n",
+                           cons, rxr->rx_next_cons);
                bnxt_sched_reset(bp, rxr);
                return;
        }
@@ -1585,15 +1587,17 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
        }
 
        cons = rxcmp->rx_cmp_opaque;
-       rx_buf = &rxr->rx_buf_ring[cons];
-       data = rx_buf->data;
-       data_ptr = rx_buf->data_ptr;
        if (unlikely(cons != rxr->rx_next_cons)) {
                int rc1 = bnxt_discard_rx(bp, cpr, raw_cons, rxcmp);
 
+               netdev_warn(bp->dev, "RX cons %x != expected cons %x\n",
+                           cons, rxr->rx_next_cons);
                bnxt_sched_reset(bp, rxr);
                return rc1;
        }
+       rx_buf = &rxr->rx_buf_ring[cons];
+       data = rx_buf->data;
+       data_ptr = rx_buf->data_ptr;
        prefetch(data_ptr);
 
        misc = le32_to_cpu(rxcmp->rx_cmp_misc_v1);
@@ -1610,11 +1614,17 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
 
        rx_buf->data = NULL;
        if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L2_ERRORS) {
+               u32 rx_err = le32_to_cpu(rxcmp1->rx_cmp_cfa_code_errors_v2);
+
                bnxt_reuse_rx_data(rxr, cons, data);
                if (agg_bufs)
                        bnxt_reuse_rx_agg_bufs(cpr, cp_cons, agg_bufs);
 
                rc = -EIO;
+               if (rx_err & RX_CMPL_ERRORS_BUFFER_ERROR_MASK) {
+                       netdev_warn(bp->dev, "RX buffer error %x\n", rx_err);
+                       bnxt_sched_reset(bp, rxr);
+               }
                goto next_rx;
        }
 
index 328373e0578ff83bf5d5bb336103deba33144e99..060a6f386104ac5511a381a9ef308f956fc6f551 100644 (file)
@@ -4283,7 +4283,7 @@ static void tg3_power_down(struct tg3 *tp)
        pci_set_power_state(tp->pdev, PCI_D3hot);
 }
 
-static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
+static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u32 *speed, u8 *duplex)
 {
        switch (val & MII_TG3_AUX_STAT_SPDMASK) {
        case MII_TG3_AUX_STAT_10HALF:
@@ -4787,7 +4787,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, bool force_reset)
        bool current_link_up;
        u32 bmsr, val;
        u32 lcl_adv, rmt_adv;
-       u16 current_speed;
+       u32 current_speed;
        u8 current_duplex;
        int i, err;
 
@@ -5719,7 +5719,7 @@ out:
 static int tg3_setup_fiber_phy(struct tg3 *tp, bool force_reset)
 {
        u32 orig_pause_cfg;
-       u16 orig_active_speed;
+       u32 orig_active_speed;
        u8 orig_active_duplex;
        u32 mac_status;
        bool current_link_up;
@@ -5823,7 +5823,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, bool force_reset)
 {
        int err = 0;
        u32 bmsr, bmcr;
-       u16 current_speed = SPEED_UNKNOWN;
+       u32 current_speed = SPEED_UNKNOWN;
        u8 current_duplex = DUPLEX_UNKNOWN;
        bool current_link_up = false;
        u32 local_adv, remote_adv, sgsr;
index a772a33b685c5eb8c28137107eb33cb4b6ffeb1d..6953d0546acb320196887a51d07312977d4f49ed 100644 (file)
@@ -2873,7 +2873,7 @@ struct tg3_tx_ring_info {
 struct tg3_link_config {
        /* Describes what we're trying to get. */
        u32                             advertising;
-       u16                             speed;
+       u32                             speed;
        u8                              duplex;
        u8                              autoneg;
        u8                              flowctrl;
@@ -2882,7 +2882,7 @@ struct tg3_link_config {
        u8                              active_flowctrl;
 
        u8                              active_duplex;
-       u16                             active_speed;
+       u32                             active_speed;
        u32                             rmt_adv;
 };
 
index 1522aee81884bdf702b32e1cd8cbae4316e988b5..3da2795e248638abbc8d50a194dd8061325aad41 100644 (file)
@@ -898,7 +898,9 @@ static void macb_tx_interrupt(struct macb_queue *queue)
 
                        /* First, update TX stats if needed */
                        if (skb) {
-                               if (gem_ptp_do_txstamp(queue, skb, desc) == 0) {
+                               if (unlikely(skb_shinfo(skb)->tx_flags &
+                                            SKBTX_HW_TSTAMP) &&
+                                   gem_ptp_do_txstamp(queue, skb, desc) == 0) {
                                        /* skb now belongs to timestamp buffer
                                         * and will be removed later
                                         */
index 0c443ea98479ac0971a6e36c28bd8bde2f080bfa..374a4d4371f99f23fe9d4507e0cbd33e177fbd85 100644 (file)
@@ -497,7 +497,7 @@ struct qlcnic_hardware_context {
        u16 board_type;
        u16 supported_type;
 
-       u16 link_speed;
+       u32 link_speed;
        u16 link_duplex;
        u16 link_autoneg;
        u16 module_type;
index 19efa88f3f02d4636f6711f6c360977953aac2f5..ed651dde6ef9ee8970bc68acb9c6fb9282411189 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/firmware.h>
 #include <linux/prefetch.h>
+#include <linux/pci-aspm.h>
 #include <linux/ipv6.h>
 #include <net/ip6_checksum.h>
 
@@ -7352,6 +7353,11 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
+       /* Disable ASPM completely as that cause random device stop working
+        * problems as well as full system hangs for some PCIe devices users.
+        */
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+
        /* enable device (incl. PCI PM wakeup and hotplug setup) */
        rc = pcim_enable_device(pdev);
        if (rc < 0) {
index 6d1a1abbed27e161f173f63ccb5aba5c6dca18ed..cd15c32b2e43686925161ad48b080842f00ec19c 100644 (file)
@@ -1275,8 +1275,12 @@ static void vrf_setup(struct net_device *dev)
        dev->priv_flags |= IFF_NO_QUEUE;
        dev->priv_flags |= IFF_NO_RX_HANDLER;
 
-       dev->min_mtu = 0;
-       dev->max_mtu = 0;
+       /* VRF devices do not care about MTU, but if the MTU is set
+        * too low then the ipv4 and ipv6 protocols are disabled
+        * which breaks networking.
+        */
+       dev->min_mtu = IPV6_MIN_MTU;
+       dev->max_mtu = ETH_MAX_MTU;
 }
 
 static int vrf_validate(struct nlattr *tb[], struct nlattr *data[],
index 470601980794edd9ebd803199587c62f0586fb03..2c43e12b70afccfb424e62d5099339e5056173e9 100644 (file)
@@ -288,7 +288,7 @@ bool nvme_cancel_request(struct request *req, void *data, bool reserved)
                                "Cancelling I/O %d", req->tag);
 
        nvme_req(req)->status = NVME_SC_ABORT_REQ;
-       blk_mq_complete_request(req);
+       blk_mq_complete_request_sync(req);
        return true;
 }
 EXPORT_SYMBOL_GPL(nvme_cancel_request);
index f3b9d91ba0dfd30ba7c4c3f554e14ea860c389b7..6d8451356eaca468742ecf335ee20763d6f73876 100644 (file)
@@ -1845,7 +1845,7 @@ nvme_fc_init_queue(struct nvme_fc_ctrl *ctrl, int idx)
        memset(queue, 0, sizeof(*queue));
        queue->ctrl = ctrl;
        queue->qnum = idx;
-       atomic_set(&queue->csn, 1);
+       atomic_set(&queue->csn, 0);
        queue->dev = ctrl->dev;
 
        if (idx > 0)
@@ -1887,7 +1887,7 @@ nvme_fc_free_queue(struct nvme_fc_queue *queue)
         */
 
        queue->connection_id = 0;
-       atomic_set(&queue->csn, 1);
+       atomic_set(&queue->csn, 0);
 }
 
 static void
@@ -2183,7 +2183,6 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
 {
        struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu;
        struct nvme_command *sqe = &cmdiu->sqe;
-       u32 csn;
        int ret, opstate;
 
        /*
@@ -2198,8 +2197,6 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
 
        /* format the FC-NVME CMD IU and fcp_req */
        cmdiu->connection_id = cpu_to_be64(queue->connection_id);
-       csn = atomic_inc_return(&queue->csn);
-       cmdiu->csn = cpu_to_be32(csn);
        cmdiu->data_len = cpu_to_be32(data_len);
        switch (io_dir) {
        case NVMEFC_FCP_WRITE:
@@ -2257,11 +2254,24 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
        if (!(op->flags & FCOP_FLAGS_AEN))
                blk_mq_start_request(op->rq);
 
+       cmdiu->csn = cpu_to_be32(atomic_inc_return(&queue->csn));
        ret = ctrl->lport->ops->fcp_io(&ctrl->lport->localport,
                                        &ctrl->rport->remoteport,
                                        queue->lldd_handle, &op->fcp_req);
 
        if (ret) {
+               /*
+                * If the lld fails to send the command is there an issue with
+                * the csn value?  If the command that fails is the Connect,
+                * no - as the connection won't be live.  If it is a command
+                * post-connect, it's possible a gap in csn may be created.
+                * Does this matter?  As Linux initiators don't send fused
+                * commands, no.  The gap would exist, but as there's nothing
+                * that depends on csn order to be delivered on the target
+                * side, it shouldn't hurt.  It would be difficult for a
+                * target to even detect the csn gap as it has no idea when the
+                * cmd with the csn was supposed to arrive.
+                */
                opstate = atomic_xchg(&op->state, FCPOP_STATE_COMPLETE);
                __nvme_fc_fcpop_chk_teardowns(ctrl, op, opstate);
 
index 76250181fee0555b2e576651ee67349ecb776392..9f72d515fc4b30a3785b396910660074ad076cf4 100644 (file)
@@ -24,6 +24,11 @@ u32 nvmet_get_log_page_len(struct nvme_command *cmd)
        return len;
 }
 
+u64 nvmet_get_log_page_offset(struct nvme_command *cmd)
+{
+       return le64_to_cpu(cmd->get_log_page.lpo);
+}
+
 static void nvmet_execute_get_log_page_noop(struct nvmet_req *req)
 {
        nvmet_req_complete(req, nvmet_zero_sgl(req, 0, req->data_len));
index c872b47a88f31722b358e219c403f2c2cb765988..33ed95e72d6b19598f76df0c50f6fccfdaec37bd 100644 (file)
@@ -131,54 +131,76 @@ static void nvmet_set_disc_traddr(struct nvmet_req *req, struct nvmet_port *port
                memcpy(traddr, port->disc_addr.traddr, NVMF_TRADDR_SIZE);
 }
 
+static size_t discovery_log_entries(struct nvmet_req *req)
+{
+       struct nvmet_ctrl *ctrl = req->sq->ctrl;
+       struct nvmet_subsys_link *p;
+       struct nvmet_port *r;
+       size_t entries = 0;
+
+       list_for_each_entry(p, &req->port->subsystems, entry) {
+               if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
+                       continue;
+               entries++;
+       }
+       list_for_each_entry(r, &req->port->referrals, entry)
+               entries++;
+       return entries;
+}
+
 static void nvmet_execute_get_disc_log_page(struct nvmet_req *req)
 {
        const int entry_size = sizeof(struct nvmf_disc_rsp_page_entry);
        struct nvmet_ctrl *ctrl = req->sq->ctrl;
        struct nvmf_disc_rsp_page_hdr *hdr;
+       u64 offset = nvmet_get_log_page_offset(req->cmd);
        size_t data_len = nvmet_get_log_page_len(req->cmd);
-       size_t alloc_len = max(data_len, sizeof(*hdr));
-       int residual_len = data_len - sizeof(*hdr);
+       size_t alloc_len;
        struct nvmet_subsys_link *p;
        struct nvmet_port *r;
        u32 numrec = 0;
        u16 status = 0;
+       void *buffer;
+
+       /* Spec requires dword aligned offsets */
+       if (offset & 0x3) {
+               status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
+               goto out;
+       }
 
        /*
         * Make sure we're passing at least a buffer of response header size.
         * If host provided data len is less than the header size, only the
         * number of bytes requested by host will be sent to host.
         */
-       hdr = kzalloc(alloc_len, GFP_KERNEL);
-       if (!hdr) {
+       down_read(&nvmet_config_sem);
+       alloc_len = sizeof(*hdr) + entry_size * discovery_log_entries(req);
+       buffer = kzalloc(alloc_len, GFP_KERNEL);
+       if (!buffer) {
+               up_read(&nvmet_config_sem);
                status = NVME_SC_INTERNAL;
                goto out;
        }
 
-       down_read(&nvmet_config_sem);
+       hdr = buffer;
        list_for_each_entry(p, &req->port->subsystems, entry) {
+               char traddr[NVMF_TRADDR_SIZE];
+
                if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
                        continue;
-               if (residual_len >= entry_size) {
-                       char traddr[NVMF_TRADDR_SIZE];
-
-                       nvmet_set_disc_traddr(req, req->port, traddr);
-                       nvmet_format_discovery_entry(hdr, req->port,
-                                       p->subsys->subsysnqn, traddr,
-                                       NVME_NQN_NVME, numrec);
-                       residual_len -= entry_size;
-               }
+
+               nvmet_set_disc_traddr(req, req->port, traddr);
+               nvmet_format_discovery_entry(hdr, req->port,
+                               p->subsys->subsysnqn, traddr,
+                               NVME_NQN_NVME, numrec);
                numrec++;
        }
 
        list_for_each_entry(r, &req->port->referrals, entry) {
-               if (residual_len >= entry_size) {
-                       nvmet_format_discovery_entry(hdr, r,
-                                       NVME_DISC_SUBSYS_NAME,
-                                       r->disc_addr.traddr,
-                                       NVME_NQN_DISC, numrec);
-                       residual_len -= entry_size;
-               }
+               nvmet_format_discovery_entry(hdr, r,
+                               NVME_DISC_SUBSYS_NAME,
+                               r->disc_addr.traddr,
+                               NVME_NQN_DISC, numrec);
                numrec++;
        }
 
@@ -190,8 +212,8 @@ static void nvmet_execute_get_disc_log_page(struct nvmet_req *req)
 
        up_read(&nvmet_config_sem);
 
-       status = nvmet_copy_to_sgl(req, 0, hdr, data_len);
-       kfree(hdr);
+       status = nvmet_copy_to_sgl(req, 0, buffer + offset, data_len);
+       kfree(buffer);
 out:
        nvmet_req_complete(req, status);
 }
index 51e49efd7849df640b5e7cb9fa9715ada7d373e4..1653d19b187fd5de826875cdcf5675c8fcb4431c 100644 (file)
@@ -428,6 +428,7 @@ u16 nvmet_copy_from_sgl(struct nvmet_req *req, off_t off, void *buf,
 u16 nvmet_zero_sgl(struct nvmet_req *req, off_t off, size_t len);
 
 u32 nvmet_get_log_page_len(struct nvme_command *cmd);
+u64 nvmet_get_log_page_offset(struct nvme_command *cmd);
 
 extern struct list_head *nvmet_ports;
 void nvmet_port_disc_changed(struct nvmet_port *port,
index 3f3df4c29f6e1d40112343e91f902735a6b4d535..905282a8ddaaeda2f8df06570bfb3716e2b2479c 100644 (file)
@@ -115,6 +115,10 @@ static void remove_board(struct controller *ctrl, bool safe_removal)
                 * removed from the slot/adapter.
                 */
                msleep(1000);
+
+               /* Ignore link or presence changes caused by power off */
+               atomic_and(~(PCI_EXP_SLTSTA_DLLSC | PCI_EXP_SLTSTA_PDC),
+                          &ctrl->pending_events);
        }
 
        /* turn off Green LED */
index a59ad09ce911d564c074930ea22968fcfab928e7..a077f67fe1dac17508d09e954cf4e5acead355d6 100644 (file)
@@ -3877,6 +3877,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9128,
 /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c14 */
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9130,
                         quirk_dma_func1_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9170,
+                        quirk_dma_func1_alias);
 /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c47 + c57 */
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9172,
                         quirk_dma_func1_alias);
index 8f018b3f3cd4c42ef40764d39587e7e2e11285d1..c7039f52ad51802afa773525af8eed45e5438ac1 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/device.h>
+#include <linux/dmi.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/platform_data/x86/clk-pmc-atom.h>
@@ -391,11 +392,27 @@ static int pmc_dbgfs_register(struct pmc_dev *pmc)
 }
 #endif /* CONFIG_DEBUG_FS */
 
+/*
+ * Some systems need one or more of their pmc_plt_clks to be
+ * marked as critical.
+ */
+static const struct dmi_system_id critclk_systems[] = {
+       {
+               .ident = "MPL CEC1x",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MPL AG"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CEC10 Family"),
+               },
+       },
+       { /*sentinel*/ }
+};
+
 static int pmc_setup_clks(struct pci_dev *pdev, void __iomem *pmc_regmap,
                          const struct pmc_data *pmc_data)
 {
        struct platform_device *clkdev;
        struct pmc_clk_data *clk_data;
+       const struct dmi_system_id *d = dmi_first_match(critclk_systems);
 
        clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
        if (!clk_data)
@@ -403,6 +420,10 @@ static int pmc_setup_clks(struct pci_dev *pdev, void __iomem *pmc_regmap,
 
        clk_data->base = pmc_regmap; /* offset is added by client */
        clk_data->clks = pmc_data->clks;
+       if (d) {
+               clk_data->critical = true;
+               pr_info("%s critclks quirk enabled\n", d->ident);
+       }
 
        clkdev = platform_device_register_data(&pdev->dev, "clk-pmc-atom",
                                               PLATFORM_DEVID_NONE,
index 462560b2855e25e1204064c89350fed5653bf36a..469d0bc9f5fe4db6e756e4270bf522e63cd15566 100644 (file)
@@ -1713,8 +1713,11 @@ csio_scsi_err_handler(struct csio_hw *hw, struct csio_ioreq *req)
        }
 
 out:
-       if (req->nsge > 0)
+       if (req->nsge > 0) {
                scsi_dma_unmap(cmnd);
+               if (req->dcopy && (host_status == DID_OK))
+                       host_status = csio_scsi_copy_to_sgl(hw, req);
+       }
 
        cmnd->result = (((host_status) << 16) | scsi_status);
        cmnd->scsi_done(cmnd);
index 8af01777d09c74f344ad325256dbd30248febe32..f8cb7c23305b7e984e16ba94406f1f338cb17a46 100644 (file)
@@ -793,6 +793,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
 
        /* We need to know how many queues before we allocate. */
        num_queues = virtscsi_config_get(vdev, num_queues) ? : 1;
+       num_queues = min_t(unsigned int, nr_cpu_ids, num_queues);
 
        num_targets = virtscsi_config_get(vdev, max_target) + 1;
 
index d0584c040c60f3a8f1a8b48004ec66074eebdcc8..7a0398bb84f77e520aeb8113c2ac77ef7ef6e0f2 100644 (file)
@@ -255,9 +255,11 @@ void vp_del_vqs(struct virtio_device *vdev)
        for (i = 0; i < vp_dev->msix_used_vectors; ++i)
                free_irq(pci_irq_vector(vp_dev->pci_dev, i), vp_dev);
 
-       for (i = 0; i < vp_dev->msix_vectors; i++)
-               if (vp_dev->msix_affinity_masks[i])
-                       free_cpumask_var(vp_dev->msix_affinity_masks[i]);
+       if (vp_dev->msix_affinity_masks) {
+               for (i = 0; i < vp_dev->msix_vectors; i++)
+                       if (vp_dev->msix_affinity_masks[i])
+                               free_cpumask_var(vp_dev->msix_affinity_masks[i]);
+       }
 
        if (vp_dev->msix_enabled) {
                /* Disable the vector used for configuration */
index 18846afb39da189e3f0dd0168727e0cf2865549e..5df92c308286dc0f5afe203cf279adb3d8af8185 100644 (file)
@@ -882,6 +882,8 @@ static struct virtqueue *vring_create_virtqueue_split(
                                          GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
                if (queue)
                        break;
+               if (!may_reduce_num)
+                       return NULL;
        }
 
        if (!num)
index a4cc2a1cccb7516216b23c4fe34431996616e3c3..3490d1fa0e16f4f1f189727661e18696ab3a7a08 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1034,7 +1034,7 @@ static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx)
                return NULL;
 
        if (unlikely(!get_reqs_available(ctx))) {
-               kfree(req);
+               kmem_cache_free(kiocb_cachep, req);
                return NULL;
        }
 
@@ -1794,7 +1794,7 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb,
                 */
                eventfd = eventfd_ctx_fdget(iocb->aio_resfd);
                if (IS_ERR(eventfd))
-                       return PTR_ERR(req->ki_eventfd);
+                       return PTR_ERR(eventfd);
 
                req->ki_eventfd = eventfd;
        }
index 78d3257435c00b76633ee6168a2586ccfa70118c..24615c76c1d0e20739db509d3ddde0e111994e2b 100644 (file)
@@ -307,10 +307,10 @@ static void blkdev_bio_end_io(struct bio *bio)
        struct blkdev_dio *dio = bio->bi_private;
        bool should_dirty = dio->should_dirty;
 
-       if (dio->multi_bio && !atomic_dec_and_test(&dio->ref)) {
-               if (bio->bi_status && !dio->bio.bi_status)
-                       dio->bio.bi_status = bio->bi_status;
-       } else {
+       if (bio->bi_status && !dio->bio.bi_status)
+               dio->bio.bi_status = bio->bi_status;
+
+       if (!dio->multi_bio || atomic_dec_and_test(&dio->ref)) {
                if (!dio->is_sync) {
                        struct kiocb *iocb = dio->iocb;
                        ssize_t ret;
index ec2d8919e7fb0ee63c28bcfd241d0e8a54ed05a3..cd4e693406a0e62bda2171d7d6800c8b4ef65ab0 100644 (file)
@@ -501,6 +501,16 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       /*
+        * If the fs is mounted with nologreplay, which requires it to be
+        * mounted in RO mode as well, we can not allow discard on free space
+        * inside block groups, because log trees refer to extents that are not
+        * pinned in a block group's free space cache (pinning the extents is
+        * precisely the first phase of replaying a log tree).
+        */
+       if (btrfs_test_opt(fs_info, NOLOGREPLAY))
+               return -EROFS;
+
        rcu_read_lock();
        list_for_each_entry_rcu(device, &fs_info->fs_devices->devices,
                                dev_list) {
index dc6140013ae8194739a8aa6a387f12c35794bdf9..61d22a56c0ba4e7d43f0552854f4ac4e82443218 100644 (file)
@@ -366,11 +366,11 @@ int btrfs_subvol_inherit_props(struct btrfs_trans_handle *trans,
 
 static int prop_compression_validate(const char *value, size_t len)
 {
-       if (!strncmp("lzo", value, len))
+       if (!strncmp("lzo", value, 3))
                return 0;
-       else if (!strncmp("zlib", value, len))
+       else if (!strncmp("zlib", value, 4))
                return 0;
-       else if (!strncmp("zstd", value, len))
+       else if (!strncmp("zstd", value, 4))
                return 0;
 
        return -EINVAL;
@@ -396,7 +396,7 @@ static int prop_compression_apply(struct inode *inode,
                btrfs_set_fs_incompat(fs_info, COMPRESS_LZO);
        } else if (!strncmp("zlib", value, 4)) {
                type = BTRFS_COMPRESS_ZLIB;
-       } else if (!strncmp("zstd", value, len)) {
+       } else if (!strncmp("zstd", value, 4)) {
                type = BTRFS_COMPRESS_ZSTD;
                btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD);
        } else {
index 8a63e52785e978a6792542d96c66cb202e5f1d1b..9971a35cf1ef66c960862ef550197814052b9267 100644 (file)
@@ -2056,10 +2056,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
                rem += pipe->bufs[(pipe->curbuf + idx) & (pipe->buffers - 1)].len;
 
        ret = -EINVAL;
-       if (rem < len) {
-               pipe_unlock(pipe);
-               goto out;
-       }
+       if (rem < len)
+               goto out_free;
 
        rem = len;
        while (rem) {
@@ -2077,7 +2075,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
                        pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1);
                        pipe->nrbufs--;
                } else {
-                       pipe_buf_get(pipe, ibuf);
+                       if (!pipe_buf_get(pipe, ibuf))
+                               goto out_free;
+
                        *obuf = *ibuf;
                        obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
                        obuf->len = rem;
@@ -2100,11 +2100,11 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
        ret = fuse_dev_do_write(fud, &cs, len);
 
        pipe_lock(pipe);
+out_free:
        for (idx = 0; idx < nbuf; idx++)
                pipe_buf_release(pipe, &bufs[idx]);
        pipe_unlock(pipe);
 
-out:
        kvfree(bufs);
        return ret;
 }
index 07d6ef195d05a9607d1c067ad7cdee67292f943b..89aa8412b5f5972466e79c711cee475d8d42ebfe 100644 (file)
@@ -2245,6 +2245,10 @@ static int io_sq_offload_start(struct io_ring_ctx *ctx,
                goto err;
 
        if (ctx->flags & IORING_SETUP_SQPOLL) {
+               ret = -EPERM;
+               if (!capable(CAP_SYS_ADMIN))
+                       goto err;
+
                if (p->flags & IORING_SETUP_SQ_AFF) {
                        int cpu;
 
index ff6f85fb676b7c1094878b269d35f2f127ca5fb5..5196bfa7894d21c0eb1220f4d9bb9e51e2593afb 100644 (file)
@@ -329,9 +329,6 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
        };
        ssize_t err, err2;
 
-       if (!nfs_server_capable(file_inode(dst), NFS_CAP_COPY))
-               return -EOPNOTSUPP;
-
        src_lock = nfs_get_lock_context(nfs_file_open_context(src));
        if (IS_ERR(src_lock))
                return PTR_ERR(src_lock);
index 45b2322e092d2455b508a8fdc00f5bde0b73c4e9..00d17198ee12aa7f6177bd3c1c5830fa655d1033 100644 (file)
@@ -133,8 +133,10 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
                                    struct file *file_out, loff_t pos_out,
                                    size_t count, unsigned int flags)
 {
+       if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY))
+               return -EOPNOTSUPP;
        if (file_inode(file_in) == file_inode(file_out))
-               return -EINVAL;
+               return -EOPNOTSUPP;
        return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
 }
 
index cfcabc33e24d01136ba00c336f90497f657fb0a5..602446158bfb56e1fe62b74411d276431baef8c6 100644 (file)
@@ -2589,7 +2589,7 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
                        ARRAY_SIZE(nfs4_acl_bitmap), &hdr);
 
        rpc_prepare_reply_pages(req, args->acl_pages, 0,
-                               args->acl_len, replen);
+                               args->acl_len, replen + 1);
        encode_nops(&hdr);
 }
 
@@ -2811,7 +2811,7 @@ static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req,
        }
 
        rpc_prepare_reply_pages(req, (struct page **)&args->page, 0,
-                               PAGE_SIZE, replen);
+                               PAGE_SIZE, replen + 1);
        encode_nops(&hdr);
 }
 
index 23790c7b2289d21328db2a824eef5c6484e29089..c27ac96a95bd3535bc893493492fdc7681aba1fe 100644 (file)
@@ -2041,7 +2041,8 @@ static int nfs23_validate_mount_data(void *options,
                memcpy(sap, &data->addr, sizeof(data->addr));
                args->nfs_server.addrlen = sizeof(data->addr);
                args->nfs_server.port = ntohs(data->addr.sin_port);
-               if (!nfs_verify_server_address(sap))
+               if (sap->sa_family != AF_INET ||
+                   !nfs_verify_server_address(sap))
                        goto out_no_address;
 
                if (!(data->flags & NFS_MOUNT_TCP))
index 070aad543382a4e30aa0bd5eef94b5dabba7219d..41065901106b09d4365ebc13ee6cfa7b6465339b 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -188,9 +188,9 @@ EXPORT_SYMBOL(generic_pipe_buf_steal);
  *     in the tee() system call, when we duplicate the buffers in one
  *     pipe into another.
  */
-void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
+bool generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
 {
-       get_page(buf->page);
+       return try_get_page(buf->page);
 }
 EXPORT_SYMBOL(generic_pipe_buf_get);
 
index 3ee7e82df48f2b14d09ddd3b4877879e90f8c418..98943d9b219c0cea1037770cbc6578970fbe69b6 100644 (file)
@@ -1593,7 +1593,11 @@ retry:
                         * Get a reference to this pipe buffer,
                         * so we can copy the contents over.
                         */
-                       pipe_buf_get(ipipe, ibuf);
+                       if (!pipe_buf_get(ipipe, ibuf)) {
+                               if (ret == 0)
+                                       ret = -EFAULT;
+                               break;
+                       }
                        *obuf = *ibuf;
 
                        /*
@@ -1667,7 +1671,11 @@ static int link_pipe(struct pipe_inode_info *ipipe,
                 * Get a reference to this pipe buffer,
                 * so we can copy the contents over.
                 */
-               pipe_buf_get(ipipe, ibuf);
+               if (!pipe_buf_get(ipipe, ibuf)) {
+                       if (ret == 0)
+                               ret = -EFAULT;
+                       break;
+               }
 
                obuf = opipe->bufs + nbuf;
                *obuf = *ibuf;
index cfb7be40bed7a55a453757b30bf20772590b718d..ce4de6b1e444a855d04cc9afe5c7ebca5833a1a6 100644 (file)
@@ -418,6 +418,8 @@ struct drm_crtc_helper_funcs {
         * Drivers can use the @old_crtc_state input parameter if the operations
         * needed to enable the CRTC don't depend solely on the new state but
         * also on the transition between the old state and the new state.
+        *
+        * This function is optional.
         */
        void (*atomic_enable)(struct drm_crtc *crtc,
                              struct drm_crtc_state *old_crtc_state);
@@ -441,6 +443,8 @@ struct drm_crtc_helper_funcs {
         * parameter @old_crtc_state which could be used to access the old
         * state. Atomic drivers should consider to use this one instead
         * of @disable.
+        *
+        * This function is optional.
         */
        void (*atomic_disable)(struct drm_crtc *crtc,
                               struct drm_crtc_state *old_crtc_state);
index adbcb681782604b5356a0b1db56a9a9af6177529..0071298b9b28eb41a313e7f29eb609bd84eb4785 100644 (file)
@@ -38,7 +38,7 @@ enum {
 
 int TSS_authhmac(unsigned char *digest, const unsigned char *key,
                        unsigned int keylen, unsigned char *h1,
-                       unsigned char *h2, unsigned char h3, ...);
+                       unsigned char *h2, unsigned int h3, ...);
 int TSS_checkhmac1(unsigned char *buffer,
                          const uint32_t command,
                          const unsigned char *ononce,
index bb6090aa165d362ae399194fdca8d58b7cb8f5bf..e584673c18814295e2c901ab16d69511bc5e7a37 100644 (file)
@@ -120,19 +120,23 @@ static inline bool bio_full(struct bio *bio)
        return bio->bi_vcnt >= bio->bi_max_vecs;
 }
 
-#define mp_bvec_for_each_segment(bv, bvl, i, iter_all)                 \
-       for (bv = bvec_init_iter_all(&iter_all);                        \
-               (iter_all.done < (bvl)->bv_len) &&                      \
-               (mp_bvec_next_segment((bvl), &iter_all), 1);            \
-               iter_all.done += bv->bv_len, i += 1)
+static inline bool bio_next_segment(const struct bio *bio,
+                                   struct bvec_iter_all *iter)
+{
+       if (iter->idx >= bio->bi_vcnt)
+               return false;
+
+       bvec_advance(&bio->bi_io_vec[iter->idx], iter);
+       return true;
+}
 
 /*
  * drivers should _never_ use the all version - the bio may have been split
  * before it got to the driver and the driver won't own all of it
  */
-#define bio_for_each_segment_all(bvl, bio, i, iter_all)                \
-       for (i = 0, iter_all.idx = 0; iter_all.idx < (bio)->bi_vcnt; iter_all.idx++)    \
-               mp_bvec_for_each_segment(bvl, &((bio)->bi_io_vec[iter_all.idx]), i, iter_all)
+#define bio_for_each_segment_all(bvl, bio, i, iter)                    \
+       for (i = 0, bvl = bvec_init_iter_all(&iter);                    \
+            bio_next_segment((bio), &iter); i++)
 
 static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
                                    unsigned bytes)
index cb2aa7ecafff5cb772772db11d5ee06314f60359..db29928de46741b0887e6bd13ed577a59684d180 100644 (file)
@@ -302,6 +302,7 @@ void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list);
 void blk_mq_kick_requeue_list(struct request_queue *q);
 void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs);
 bool blk_mq_complete_request(struct request *rq);
+void blk_mq_complete_request_sync(struct request *rq);
 bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list,
                           struct bio *bio);
 bool blk_mq_queue_stopped(struct request_queue *q);
index f6275c4da13a765fd60f3d34a9ca491d1d56db93..3bc91879e1e2b09ced375d4540e97094ae593f66 100644 (file)
@@ -145,18 +145,18 @@ static inline bool bvec_iter_advance(const struct bio_vec *bv,
 
 static inline struct bio_vec *bvec_init_iter_all(struct bvec_iter_all *iter_all)
 {
-       iter_all->bv.bv_page = NULL;
        iter_all->done = 0;
+       iter_all->idx = 0;
 
        return &iter_all->bv;
 }
 
-static inline void mp_bvec_next_segment(const struct bio_vec *bvec,
-                                       struct bvec_iter_all *iter_all)
+static inline void bvec_advance(const struct bio_vec *bvec,
+                               struct bvec_iter_all *iter_all)
 {
        struct bio_vec *bv = &iter_all->bv;
 
-       if (bv->bv_page) {
+       if (iter_all->done) {
                bv->bv_page = nth_page(bv->bv_page, 1);
                bv->bv_offset = 0;
        } else {
@@ -165,6 +165,12 @@ static inline void mp_bvec_next_segment(const struct bio_vec *bvec,
        }
        bv->bv_len = min_t(unsigned int, PAGE_SIZE - bv->bv_offset,
                           bvec->bv_len - iter_all->done);
+       iter_all->done += bv->bv_len;
+
+       if (iter_all->done == bvec->bv_len) {
+               iter_all->idx++;
+               iter_all->done = 0;
+       }
 }
 
 /*
index 34a5036debd341935a100b6fe4a7083db6262d5e..2d14e21c16c0b412535d00b3a537bf3353366d4a 100644 (file)
@@ -47,8 +47,8 @@
 
 #define u64_to_user_ptr(x) (           \
 {                                      \
-       typecheck(u64, x);              \
-       (void __user *)(uintptr_t)x;    \
+       typecheck(u64, (x));            \
+       (void __user *)(uintptr_t)(x);  \
 }                                      \
 )
 
index 76769749b5a5d546daf7f7513318ad65a494da4c..6b10c21630f54bdd14ddd6efa1510777165ec558 100644 (file)
@@ -966,6 +966,10 @@ static inline bool is_pci_p2pdma_page(const struct page *page)
 }
 #endif /* CONFIG_DEV_PAGEMAP_OPS */
 
+/* 127: arbitrary random number, small enough to assemble well */
+#define page_ref_zero_or_close_to_overflow(page) \
+       ((unsigned int) page_ref_count(page) + 127u <= 127u)
+
 static inline void get_page(struct page *page)
 {
        page = compound_head(page);
@@ -973,8 +977,17 @@ static inline void get_page(struct page *page)
         * Getting a normal page or the head of a compound page
         * requires to already have an elevated page->_refcount.
         */
-       VM_BUG_ON_PAGE(page_ref_count(page) <= 0, page);
+       VM_BUG_ON_PAGE(page_ref_zero_or_close_to_overflow(page), page);
+       page_ref_inc(page);
+}
+
+static inline __must_check bool try_get_page(struct page *page)
+{
+       page = compound_head(page);
+       if (WARN_ON_ONCE(page_ref_count(page) <= 0))
+               return false;
        page_ref_inc(page);
+       return true;
 }
 
 static inline void put_page(struct page *page)
index baa49e6a23cc7a16092962e4d4a6bfbba9132376..c40720cb59acc4190d40aafdfe23b42ef8159cf9 100644 (file)
@@ -967,8 +967,13 @@ struct nvme_get_log_page_command {
        __le16                  numdl;
        __le16                  numdu;
        __u16                   rsvd11;
-       __le32                  lpol;
-       __le32                  lpou;
+       union {
+               struct {
+                       __le32 lpol;
+                       __le32 lpou;
+               };
+               __le64 lpo;
+       };
        __u32                   rsvd14[2];
 };
 
index 787d224ff43e1fc72ceed0164bf26a4f2fa08794..abb2dac3da9b9cf69b477c2d3726e019a0352b7a 100644 (file)
@@ -101,18 +101,20 @@ struct pipe_buf_operations {
        /*
         * Get a reference to the pipe buffer.
         */
-       void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
+       bool (*get)(struct pipe_inode_info *, struct pipe_buffer *);
 };
 
 /**
  * pipe_buf_get - get a reference to a pipe_buffer
  * @pipe:      the pipe that the buffer belongs to
  * @buf:       the buffer to get a reference to
+ *
+ * Return: %true if the reference was successfully obtained.
  */
-static inline void pipe_buf_get(struct pipe_inode_info *pipe,
+static inline __must_check bool pipe_buf_get(struct pipe_inode_info *pipe,
                                struct pipe_buffer *buf)
 {
-       buf->ops->get(pipe, buf);
+       return buf->ops->get(pipe, buf);
 }
 
 /**
@@ -171,7 +173,7 @@ struct pipe_inode_info *alloc_pipe_info(void);
 void free_pipe_info(struct pipe_inode_info *);
 
 /* Generic pipe buffer ops functions */
-void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
+bool generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
 int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *);
 int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
 void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *);
index 3ab892208343c2d22d71a630f1097d6941534518..7a37ac27d0fb21d9f8afde973c7618e42574534b 100644 (file)
@@ -35,10 +35,13 @@ struct pmc_clk {
  *
  * @base:      PMC clock register base offset
  * @clks:      pointer to set of registered clocks, typically 0..5
+ * @critical:  flag to indicate if firmware enabled pmc_plt_clks
+ *             should be marked as critial or not
  */
 struct pmc_clk_data {
        void __iomem *base;
        const struct pmc_clk *clks;
+       bool critical;
 };
 
 #endif /* __PLATFORM_DATA_X86_CLK_PMC_ATOM_H */
index ec861cd0cfe8ce9fa5425909d243c660231f06c9..52d41d0c1ae1d54b6829a10134318ee2835b9fd5 100644 (file)
@@ -304,12 +304,4 @@ rpc_clnt_swap_deactivate(struct rpc_clnt *clnt)
 }
 #endif /* CONFIG_SUNRPC_SWAP */
 
-static inline bool
-rpc_task_need_resched(const struct rpc_task *task)
-{
-       if (RPC_IS_QUEUED(task) || task->tk_callback)
-               return true;
-       return false;
-}
-
 #endif /* _LINUX_SUNRPC_SCHED_H_ */
index fab02133a9197a43cd9df33728e657e1679c5e16..3dc70adfe5f5edbbfa6f6508849d1d3630a46e2b 100644 (file)
@@ -63,7 +63,7 @@ struct virtqueue;
 /*
  * Creates a virtqueue and allocates the descriptor ring.  If
  * may_reduce_num is set, then this may allocate a smaller ring than
- * expected.  The caller should query virtqueue_get_ring_size to learn
+ * expected.  The caller should query virtqueue_get_vring_size to learn
  * the actual size of the ring.
  */
 struct virtqueue *vring_create_virtqueue(unsigned int index,
index 87499b6b35d6dd75ea3058449c5db484e2aca611..df5c69db68afc334d0ac51c031ca6120d8b7e6e9 100644 (file)
@@ -166,7 +166,7 @@ struct nci_conn_info {
  * According to specification 102 622 chapter 4.4 Pipes,
  * the pipe identifier is 7 bits long.
  */
-#define NCI_HCI_MAX_PIPES          127
+#define NCI_HCI_MAX_PIPES          128
 
 struct nci_hci_gate {
        u8 gate;
index eb7db605955b852a469d11b62a93817f7726cf88..482b4ea87c3c4bd9fac786fa7165b30123174ea2 100644 (file)
@@ -802,8 +802,13 @@ struct snd_soc_component_driver {
        int probe_order;
        int remove_order;
 
-       /* signal if the module handling the component cannot be removed */
-       unsigned int ignore_module_refcount:1;
+       /*
+        * signal if the module handling the component should not be removed
+        * if a pcm is open. Setting this would prevent the module
+        * refcount being incremented in probe() but allow it be incremented
+        * when a pcm is opened and decremented when it is closed.
+        */
+       unsigned int module_get_upon_open:1;
 
        /* bits */
        unsigned int idle_bias_on:1;
@@ -1083,6 +1088,8 @@ struct snd_soc_card {
        struct mutex mutex;
        struct mutex dapm_mutex;
 
+       spinlock_t dpcm_lock;
+
        bool instantiated;
        bool topology_shortname_created;
 
index 3652b239dad1d7c556ff28a7a9a87129aa9b89d3..d473e5ed044c71df4e734f91c96f828952834dc3 100644 (file)
@@ -1591,7 +1591,7 @@ enum ethtool_link_mode_bit_indices {
 
 static inline int ethtool_validate_speed(__u32 speed)
 {
-       return speed <= INT_MAX || speed == SPEED_UNKNOWN;
+       return speed <= INT_MAX || speed == (__u32)SPEED_UNKNOWN;
 }
 
 /* Duplex, half or full. */
index 404d4b9ffe7644553a1b59fba043b151d935a2e9..df1153cea0b7ee2a27e19682837f81922fef353e 100644 (file)
@@ -32,6 +32,7 @@
 
 #ifndef __KERNEL__
 #include <stdlib.h>
+#include <time.h>
 #endif
 
 /*
index 45d51e8e26f62f27b8b91c3e53ddb2df20fd791b..a218e43cc38258ae6d7bed19f0d6e2ea852e2ac7 100644 (file)
@@ -706,7 +706,7 @@ static struct dma_debug_entry *dma_entry_alloc(void)
 #ifdef CONFIG_STACKTRACE
        entry->stacktrace.max_entries = DMA_DEBUG_STACKTRACE_ENTRIES;
        entry->stacktrace.entries = entry->st_entries;
-       entry->stacktrace.skip = 2;
+       entry->stacktrace.skip = 1;
        save_stack_trace(&entry->stacktrace);
 #endif
 
index 72d06e302e9938dcaee6dbf57324d3ed31397035..534e01e7bc36854877d3361fcf2683ab09025d91 100644 (file)
@@ -2009,8 +2009,8 @@ event_sched_out(struct perf_event *event,
        event->pmu->del(event, 0);
        event->oncpu = -1;
 
-       if (event->pending_disable) {
-               event->pending_disable = 0;
+       if (READ_ONCE(event->pending_disable) >= 0) {
+               WRITE_ONCE(event->pending_disable, -1);
                state = PERF_EVENT_STATE_OFF;
        }
        perf_event_set_state(event, state);
@@ -2198,7 +2198,8 @@ EXPORT_SYMBOL_GPL(perf_event_disable);
 
 void perf_event_disable_inatomic(struct perf_event *event)
 {
-       event->pending_disable = 1;
+       WRITE_ONCE(event->pending_disable, smp_processor_id());
+       /* can fail, see perf_pending_event_disable() */
        irq_work_queue(&event->pending);
 }
 
@@ -5810,10 +5811,45 @@ void perf_event_wakeup(struct perf_event *event)
        }
 }
 
+static void perf_pending_event_disable(struct perf_event *event)
+{
+       int cpu = READ_ONCE(event->pending_disable);
+
+       if (cpu < 0)
+               return;
+
+       if (cpu == smp_processor_id()) {
+               WRITE_ONCE(event->pending_disable, -1);
+               perf_event_disable_local(event);
+               return;
+       }
+
+       /*
+        *  CPU-A                       CPU-B
+        *
+        *  perf_event_disable_inatomic()
+        *    @pending_disable = CPU-A;
+        *    irq_work_queue();
+        *
+        *  sched-out
+        *    @pending_disable = -1;
+        *
+        *                              sched-in
+        *                              perf_event_disable_inatomic()
+        *                                @pending_disable = CPU-B;
+        *                                irq_work_queue(); // FAILS
+        *
+        *  irq_work_run()
+        *    perf_pending_event()
+        *
+        * But the event runs on CPU-B and wants disabling there.
+        */
+       irq_work_queue_on(&event->pending, cpu);
+}
+
 static void perf_pending_event(struct irq_work *entry)
 {
-       struct perf_event *event = container_of(entry,
-                       struct perf_event, pending);
+       struct perf_event *event = container_of(entry, struct perf_event, pending);
        int rctx;
 
        rctx = perf_swevent_get_recursion_context();
@@ -5822,10 +5858,7 @@ static void perf_pending_event(struct irq_work *entry)
         * and we won't recurse 'further'.
         */
 
-       if (event->pending_disable) {
-               event->pending_disable = 0;
-               perf_event_disable_local(event);
-       }
+       perf_pending_event_disable(event);
 
        if (event->pending_wakeup) {
                event->pending_wakeup = 0;
@@ -10236,6 +10269,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 
 
        init_waitqueue_head(&event->waitq);
+       event->pending_disable = -1;
        init_irq_work(&event->pending, perf_pending_event);
 
        mutex_init(&event->mmap_mutex);
index a4047321d7d8052b40302d4ed8c0aa8e649ba759..2545ac08cc77b0bb1df9df04be353bbe6a7a0575 100644 (file)
@@ -392,7 +392,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
                 * store that will be enabled on successful return
                 */
                if (!handle->size) { /* A, matches D */
-                       event->pending_disable = 1;
+                       event->pending_disable = smp_processor_id();
                        perf_output_wakeup(handle);
                        local_set(&rb->aux_nest, 0);
                        goto err_put;
@@ -480,7 +480,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
 
        if (wakeup) {
                if (handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)
-                       handle->event->pending_disable = 1;
+                       handle->event->pending_disable = smp_processor_id();
                perf_output_wakeup(handle);
        }
 
index 3faef4a77f7103e004c6a26f9c4074750f23fc73..51128bea3846ca1c15cd622f0889602cd1688b78 100644 (file)
@@ -1449,6 +1449,10 @@ int irq_chip_set_vcpu_affinity_parent(struct irq_data *data, void *vcpu_info)
 int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on)
 {
        data = data->parent_data;
+
+       if (data->chip->flags & IRQCHIP_SKIP_SET_WAKE)
+               return 0;
+
        if (data->chip->irq_set_wake)
                return data->chip->irq_set_wake(data, on);
 
index 13539e12cd8034279c8f324242e4996301203d1a..9f8a709337cf802f2ddbf33f90a956d851f0c5b3 100644 (file)
@@ -558,6 +558,7 @@ int __init early_irq_init(void)
                alloc_masks(&desc[i], node);
                raw_spin_lock_init(&desc[i].lock);
                lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
+               mutex_init(&desc[i].request_mutex);
                desc_set_defaults(i, &desc[i], node, NULL, NULL);
        }
        return arch_early_irq_init();
index 34cdcbedda492b84cb610af67cb11113ea04065d..e16766ff184b5e57d636e987a70a1147d3b3ecb2 100644 (file)
@@ -4689,8 +4689,8 @@ static void free_zapped_rcu(struct rcu_head *ch)
                return;
 
        raw_local_irq_save(flags);
-       if (!graph_lock())
-               goto out_irq;
+       arch_spin_lock(&lockdep_lock);
+       current->lockdep_recursion = 1;
 
        /* closed head */
        pf = delayed_free.pf + (delayed_free.index ^ 1);
@@ -4702,8 +4702,8 @@ static void free_zapped_rcu(struct rcu_head *ch)
         */
        call_rcu_zapped(delayed_free.pf + delayed_free.index);
 
-       graph_unlock();
-out_irq:
+       current->lockdep_recursion = 0;
+       arch_spin_unlock(&lockdep_lock);
        raw_local_irq_restore(flags);
 }
 
@@ -4744,21 +4744,17 @@ static void lockdep_free_key_range_reg(void *start, unsigned long size)
 {
        struct pending_free *pf;
        unsigned long flags;
-       int locked;
 
        init_data_structures_once();
 
        raw_local_irq_save(flags);
-       locked = graph_lock();
-       if (!locked)
-               goto out_irq;
-
+       arch_spin_lock(&lockdep_lock);
+       current->lockdep_recursion = 1;
        pf = get_pending_free();
        __lockdep_free_key_range(pf, start, size);
        call_rcu_zapped(pf);
-
-       graph_unlock();
-out_irq:
+       current->lockdep_recursion = 0;
+       arch_spin_unlock(&lockdep_lock);
        raw_local_irq_restore(flags);
 
        /*
@@ -4911,9 +4907,8 @@ void lockdep_unregister_key(struct lock_class_key *key)
                return;
 
        raw_local_irq_save(flags);
-       if (!graph_lock())
-               goto out_irq;
-
+       arch_spin_lock(&lockdep_lock);
+       current->lockdep_recursion = 1;
        pf = get_pending_free();
        hlist_for_each_entry_rcu(k, hash_head, hash_entry) {
                if (k == key) {
@@ -4925,8 +4920,8 @@ void lockdep_unregister_key(struct lock_class_key *key)
        WARN_ON_ONCE(!found);
        __lockdep_free_key_range(pf, key, 1);
        call_rcu_zapped(pf);
-       graph_unlock();
-out_irq:
+       current->lockdep_recursion = 0;
+       arch_spin_unlock(&lockdep_lock);
        raw_local_irq_restore(flags);
 
        /* Wait until is_dynamic_key() has finished accessing k->hash_entry. */
index fdab7eb6f3517af0ca9581a730b0771c28092fa0..40bd1e27b1b79f88e3ba23b413e5d0d7f1b28094 100644 (file)
@@ -7784,10 +7784,10 @@ static void update_cfs_rq_h_load(struct cfs_rq *cfs_rq)
        if (cfs_rq->last_h_load_update == now)
                return;
 
-       cfs_rq->h_load_next = NULL;
+       WRITE_ONCE(cfs_rq->h_load_next, NULL);
        for_each_sched_entity(se) {
                cfs_rq = cfs_rq_of(se);
-               cfs_rq->h_load_next = se;
+               WRITE_ONCE(cfs_rq->h_load_next, se);
                if (cfs_rq->last_h_load_update == now)
                        break;
        }
@@ -7797,7 +7797,7 @@ static void update_cfs_rq_h_load(struct cfs_rq *cfs_rq)
                cfs_rq->last_h_load_update = now;
        }
 
-       while ((se = cfs_rq->h_load_next) != NULL) {
+       while ((se = READ_ONCE(cfs_rq->h_load_next)) != NULL) {
                load = cfs_rq->h_load;
                load = div64_ul(load * se->avg.load_avg,
                        cfs_rq_load_avg(cfs_rq) + 1);
index 2c97e8c2d29fb3351332e447323750247d950f58..0519a8805aab3f290e3fb437ff0903a0e4722d90 100644 (file)
@@ -594,7 +594,7 @@ static ktime_t alarm_timer_remaining(struct k_itimer *timr, ktime_t now)
 {
        struct alarm *alarm = &timr->it.alarm.alarmtimer;
 
-       return ktime_sub(now, alarm->node.expires);
+       return ktime_sub(alarm->node.expires, now);
 }
 
 /**
index 21153e64bf1c366033213e90272438ba171b2822..6c24755655c752a3bf9f4bb914ddb251d9ab0d2e 100644 (file)
@@ -7041,12 +7041,16 @@ static void buffer_pipe_buf_release(struct pipe_inode_info *pipe,
        buf->private = 0;
 }
 
-static void buffer_pipe_buf_get(struct pipe_inode_info *pipe,
+static bool buffer_pipe_buf_get(struct pipe_inode_info *pipe,
                                struct pipe_buffer *buf)
 {
        struct buffer_ref *ref = (struct buffer_ref *)buf->private;
 
+       if (ref->ref > INT_MAX/2)
+               return false;
+
        ref->ref++;
+       return true;
 }
 
 /* Pipe buffer operations for a buffer. */
index ea36dc355da131b4a45b71d8be6f1bc69a53e637..b396d328a7643b7c1984b8e87df9da88c45e7470 100644 (file)
@@ -1528,6 +1528,7 @@ EXPORT_SYMBOL(csum_and_copy_to_iter);
 size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp,
                struct iov_iter *i)
 {
+#ifdef CONFIG_CRYPTO
        struct ahash_request *hash = hashp;
        struct scatterlist sg;
        size_t copied;
@@ -1537,6 +1538,9 @@ size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp,
        ahash_request_set_crypt(hash, &sg, NULL, copied);
        crypto_ahash_update(hash);
        return copied;
+#else
+       return 0;
+#endif
 }
 EXPORT_SYMBOL(hash_and_copy_to_iter);
 
index f84e22685aaaaa7ff1167697af36a16960171a7d..91819b8ad9cc511ca15a3d84ff81131cd4e2d0da 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -160,8 +160,12 @@ retry:
                goto retry;
        }
 
-       if (flags & FOLL_GET)
-               get_page(page);
+       if (flags & FOLL_GET) {
+               if (unlikely(!try_get_page(page))) {
+                       page = ERR_PTR(-ENOMEM);
+                       goto out;
+               }
+       }
        if (flags & FOLL_TOUCH) {
                if ((flags & FOLL_WRITE) &&
                    !pte_dirty(pte) && !PageDirty(page))
@@ -298,7 +302,10 @@ retry_locked:
                        if (pmd_trans_unstable(pmd))
                                ret = -EBUSY;
                } else {
-                       get_page(page);
+                       if (unlikely(!try_get_page(page))) {
+                               spin_unlock(ptl);
+                               return ERR_PTR(-ENOMEM);
+                       }
                        spin_unlock(ptl);
                        lock_page(page);
                        ret = split_huge_page(page);
@@ -500,7 +507,10 @@ static int get_gate_page(struct mm_struct *mm, unsigned long address,
                if (is_device_public_page(*page))
                        goto unmap;
        }
-       get_page(*page);
+       if (unlikely(!try_get_page(*page))) {
+               ret = -ENOMEM;
+               goto unmap;
+       }
 out:
        ret = 0;
 unmap:
@@ -1545,6 +1555,20 @@ static void undo_dev_pagemap(int *nr, int nr_start, struct page **pages)
        }
 }
 
+/*
+ * Return the compund head page with ref appropriately incremented,
+ * or NULL if that failed.
+ */
+static inline struct page *try_get_compound_head(struct page *page, int refs)
+{
+       struct page *head = compound_head(page);
+       if (WARN_ON_ONCE(page_ref_count(head) < 0))
+               return NULL;
+       if (unlikely(!page_cache_add_speculative(head, refs)))
+               return NULL;
+       return head;
+}
+
 #ifdef CONFIG_ARCH_HAS_PTE_SPECIAL
 static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
                         int write, struct page **pages, int *nr)
@@ -1579,9 +1603,9 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end,
 
                VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
                page = pte_page(pte);
-               head = compound_head(page);
 
-               if (!page_cache_get_speculative(head))
+               head = try_get_compound_head(page, 1);
+               if (!head)
                        goto pte_unmap;
 
                if (unlikely(pte_val(pte) != pte_val(*ptep))) {
@@ -1720,8 +1744,8 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr,
                refs++;
        } while (addr += PAGE_SIZE, addr != end);
 
-       head = compound_head(pmd_page(orig));
-       if (!page_cache_add_speculative(head, refs)) {
+       head = try_get_compound_head(pmd_page(orig), refs);
+       if (!head) {
                *nr -= refs;
                return 0;
        }
@@ -1758,8 +1782,8 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr,
                refs++;
        } while (addr += PAGE_SIZE, addr != end);
 
-       head = compound_head(pud_page(orig));
-       if (!page_cache_add_speculative(head, refs)) {
+       head = try_get_compound_head(pud_page(orig), refs);
+       if (!head) {
                *nr -= refs;
                return 0;
        }
@@ -1795,8 +1819,8 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr,
                refs++;
        } while (addr += PAGE_SIZE, addr != end);
 
-       head = compound_head(pgd_page(orig));
-       if (!page_cache_add_speculative(head, refs)) {
+       head = try_get_compound_head(pgd_page(orig), refs);
+       if (!head) {
                *nr -= refs;
                return 0;
        }
index 97b1e0290c66d48737cda50ccea6bbcc1782c8fc..6cdc7b2d910039a5e9f4fb4724c34ad8e2216c45 100644 (file)
@@ -4299,6 +4299,19 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
 
                pfn_offset = (vaddr & ~huge_page_mask(h)) >> PAGE_SHIFT;
                page = pte_page(huge_ptep_get(pte));
+
+               /*
+                * Instead of doing 'try_get_page()' below in the same_page
+                * loop, just check the count once here.
+                */
+               if (unlikely(page_count(page) <= 0)) {
+                       if (pages) {
+                               spin_unlock(ptl);
+                               remainder = 0;
+                               err = -ENOMEM;
+                               break;
+                       }
+               }
 same_page:
                if (pages) {
                        pages[i] = mem_map_offset(page, pfn_offset);
index 329bfe67f2cae966f07d930be7e10e2041505acb..47a380a486eefdfb2c93434c920dcecb53e272b6 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -4308,7 +4308,8 @@ static void show_symbol(struct seq_file *m, unsigned long address)
 
 static int leaks_show(struct seq_file *m, void *p)
 {
-       struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list);
+       struct kmem_cache *cachep = list_entry(p, struct kmem_cache,
+                                              root_caches_node);
        struct page *page;
        struct kmem_cache_node *n;
        const char *name;
index fd219f7bd3ea2c9263ac6d21ed3a66fd6442496c..4b052644147630fbfa8075ee623714ff5013bf94 100644 (file)
@@ -259,7 +259,6 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
        struct net *net = dev_net(skb->dev);
        struct metadata_dst *tun_dst = NULL;
        struct erspan_base_hdr *ershdr;
-       struct erspan_metadata *pkt_md;
        struct ip_tunnel_net *itn;
        struct ip_tunnel *tunnel;
        const struct iphdr *iph;
@@ -282,9 +281,6 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
                if (unlikely(!pskb_may_pull(skb, len)))
                        return PACKET_REJECT;
 
-               ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
-               pkt_md = (struct erspan_metadata *)(ershdr + 1);
-
                if (__iptunnel_pull_header(skb,
                                           len,
                                           htons(ETH_P_TEB),
@@ -292,8 +288,9 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
                        goto drop;
 
                if (tunnel->collect_md) {
+                       struct erspan_metadata *pkt_md, *md;
                        struct ip_tunnel_info *info;
-                       struct erspan_metadata *md;
+                       unsigned char *gh;
                        __be64 tun_id;
                        __be16 flags;
 
@@ -306,6 +303,14 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
                        if (!tun_dst)
                                return PACKET_REJECT;
 
+                       /* skb can be uncloned in __iptunnel_pull_header, so
+                        * old pkt_md is no longer valid and we need to reset
+                        * it
+                        */
+                       gh = skb_network_header(skb) +
+                            skb_network_header_len(skb);
+                       pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
+                                                           sizeof(*ershdr));
                        md = ip_tunnel_info_opts(&tun_dst->u.tun_info);
                        md->version = ver;
                        md2 = &md->u.md2;
index b32c95f0212809006455cb79768f96bd1c516994..655e46b227f9eb99e43369ffb96a411bd662eadb 100644 (file)
@@ -525,10 +525,10 @@ static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
 }
 
 static int ip6erspan_rcv(struct sk_buff *skb,
-                        struct tnl_ptk_info *tpi)
+                        struct tnl_ptk_info *tpi,
+                        int gre_hdr_len)
 {
        struct erspan_base_hdr *ershdr;
-       struct erspan_metadata *pkt_md;
        const struct ipv6hdr *ipv6h;
        struct erspan_md2 *md2;
        struct ip6_tnl *tunnel;
@@ -547,18 +547,16 @@ static int ip6erspan_rcv(struct sk_buff *skb,
                if (unlikely(!pskb_may_pull(skb, len)))
                        return PACKET_REJECT;
 
-               ershdr = (struct erspan_base_hdr *)skb->data;
-               pkt_md = (struct erspan_metadata *)(ershdr + 1);
-
                if (__iptunnel_pull_header(skb, len,
                                           htons(ETH_P_TEB),
                                           false, false) < 0)
                        return PACKET_REJECT;
 
                if (tunnel->parms.collect_md) {
+                       struct erspan_metadata *pkt_md, *md;
                        struct metadata_dst *tun_dst;
                        struct ip_tunnel_info *info;
-                       struct erspan_metadata *md;
+                       unsigned char *gh;
                        __be64 tun_id;
                        __be16 flags;
 
@@ -571,6 +569,14 @@ static int ip6erspan_rcv(struct sk_buff *skb,
                        if (!tun_dst)
                                return PACKET_REJECT;
 
+                       /* skb can be uncloned in __iptunnel_pull_header, so
+                        * old pkt_md is no longer valid and we need to reset
+                        * it
+                        */
+                       gh = skb_network_header(skb) +
+                            skb_network_header_len(skb);
+                       pkt_md = (struct erspan_metadata *)(gh + gre_hdr_len +
+                                                           sizeof(*ershdr));
                        info = &tun_dst->u.tun_info;
                        md = ip_tunnel_info_opts(info);
                        md->version = ver;
@@ -607,7 +613,7 @@ static int gre_rcv(struct sk_buff *skb)
 
        if (unlikely(tpi.proto == htons(ETH_P_ERSPAN) ||
                     tpi.proto == htons(ETH_P_ERSPAN2))) {
-               if (ip6erspan_rcv(skb, &tpi) == PACKET_RCVD)
+               if (ip6erspan_rcv(skb, &tpi, hdr_len) == PACKET_RCVD)
                        return 0;
                goto out;
        }
index ddfc52ac1f9b4391cb8b6e0f107658b1ee011565..c0d323b58e732318cc352be35bf940693b9bd028 100644 (file)
@@ -312,6 +312,10 @@ static void nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe,
                create_info = (struct nci_hci_create_pipe_resp *)skb->data;
                dest_gate = create_info->dest_gate;
                new_pipe = create_info->pipe;
+               if (new_pipe >= NCI_HCI_MAX_PIPES) {
+                       status = NCI_HCI_ANY_E_NOK;
+                       goto exit;
+               }
 
                /* Save the new created pipe and bind with local gate,
                 * the description for skb->data[3] is destination gate id
@@ -336,6 +340,10 @@ static void nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe,
                        goto exit;
                }
                delete_info = (struct nci_hci_delete_pipe_noti *)skb->data;
+               if (delete_info->pipe >= NCI_HCI_MAX_PIPES) {
+                       status = NCI_HCI_ANY_E_NOK;
+                       goto exit;
+               }
 
                ndev->hci_dev->pipes[delete_info->pipe].gate =
                                                NCI_HCI_INVALID_GATE;
index 187d10443a1584e196245afc9837add06daa1c86..1d0395ef62c95b9285bdaca47f96f48a3d5093bf 100644 (file)
@@ -1540,7 +1540,6 @@ call_start(struct rpc_task *task)
        clnt->cl_stats->rpccnt++;
        task->tk_action = call_reserve;
        rpc_task_set_transport(task, clnt);
-       call_reserve(task);
 }
 
 /*
@@ -1554,9 +1553,6 @@ call_reserve(struct rpc_task *task)
        task->tk_status  = 0;
        task->tk_action  = call_reserveresult;
        xprt_reserve(task);
-       if (rpc_task_need_resched(task))
-               return;
-        call_reserveresult(task);
 }
 
 static void call_retry_reserve(struct rpc_task *task);
@@ -1579,7 +1575,6 @@ call_reserveresult(struct rpc_task *task)
        if (status >= 0) {
                if (task->tk_rqstp) {
                        task->tk_action = call_refresh;
-                       call_refresh(task);
                        return;
                }
 
@@ -1605,7 +1600,6 @@ call_reserveresult(struct rpc_task *task)
                /* fall through */
        case -EAGAIN:   /* woken up; retry */
                task->tk_action = call_retry_reserve;
-               call_retry_reserve(task);
                return;
        case -EIO:      /* probably a shutdown */
                break;
@@ -1628,9 +1622,6 @@ call_retry_reserve(struct rpc_task *task)
        task->tk_status  = 0;
        task->tk_action  = call_reserveresult;
        xprt_retry_reserve(task);
-       if (rpc_task_need_resched(task))
-               return;
-       call_reserveresult(task);
 }
 
 /*
@@ -1645,9 +1636,6 @@ call_refresh(struct rpc_task *task)
        task->tk_status = 0;
        task->tk_client->cl_stats->rpcauthrefresh++;
        rpcauth_refreshcred(task);
-       if (rpc_task_need_resched(task))
-               return;
-       call_refreshresult(task);
 }
 
 /*
@@ -1666,7 +1654,6 @@ call_refreshresult(struct rpc_task *task)
        case 0:
                if (rpcauth_uptodatecred(task)) {
                        task->tk_action = call_allocate;
-                       call_allocate(task);
                        return;
                }
                /* Use rate-limiting and a max number of retries if refresh
@@ -1685,7 +1672,6 @@ call_refreshresult(struct rpc_task *task)
                task->tk_cred_retry--;
                dprintk("RPC: %5u %s: retry refresh creds\n",
                                task->tk_pid, __func__);
-               call_refresh(task);
                return;
        }
        dprintk("RPC: %5u %s: refresh creds failed with error %d\n",
@@ -1711,10 +1697,8 @@ call_allocate(struct rpc_task *task)
        task->tk_status = 0;
        task->tk_action = call_encode;
 
-       if (req->rq_buffer) {
-               call_encode(task);
+       if (req->rq_buffer)
                return;
-       }
 
        if (proc->p_proc != 0) {
                BUG_ON(proc->p_arglen == 0);
@@ -1740,12 +1724,8 @@ call_allocate(struct rpc_task *task)
 
        status = xprt->ops->buf_alloc(task);
        xprt_inject_disconnect(xprt);
-       if (status == 0) {
-               if (rpc_task_need_resched(task))
-                       return;
-               call_encode(task);
+       if (status == 0)
                return;
-       }
        if (status != -ENOMEM) {
                rpc_exit(task, status);
                return;
@@ -1828,8 +1808,12 @@ call_encode(struct rpc_task *task)
                xprt_request_enqueue_receive(task);
        xprt_request_enqueue_transmit(task);
 out:
-       task->tk_action = call_bind;
-       call_bind(task);
+       task->tk_action = call_transmit;
+       /* Check that the connection is OK */
+       if (!xprt_bound(task->tk_xprt))
+               task->tk_action = call_bind;
+       else if (!xprt_connected(task->tk_xprt))
+               task->tk_action = call_connect;
 }
 
 /*
@@ -1847,7 +1831,6 @@ rpc_task_handle_transmitted(struct rpc_task *task)
 {
        xprt_end_transmit(task);
        task->tk_action = call_transmit_status;
-       call_transmit_status(task);
 }
 
 /*
@@ -1865,7 +1848,6 @@ call_bind(struct rpc_task *task)
 
        if (xprt_bound(xprt)) {
                task->tk_action = call_connect;
-               call_connect(task);
                return;
        }
 
@@ -1896,7 +1878,6 @@ call_bind_status(struct rpc_task *task)
                dprint_status(task);
                task->tk_status = 0;
                task->tk_action = call_connect;
-               call_connect(task);
                return;
        }
 
@@ -1981,7 +1962,6 @@ call_connect(struct rpc_task *task)
 
        if (xprt_connected(xprt)) {
                task->tk_action = call_transmit;
-               call_transmit(task);
                return;
        }
 
@@ -2051,7 +2031,6 @@ call_connect_status(struct rpc_task *task)
        case 0:
                clnt->cl_stats->netreconn++;
                task->tk_action = call_transmit;
-               call_transmit(task);
                return;
        }
        rpc_exit(task, status);
@@ -2087,9 +2066,6 @@ call_transmit(struct rpc_task *task)
                xprt_transmit(task);
        }
        xprt_end_transmit(task);
-       if (rpc_task_need_resched(task))
-               return;
-       call_transmit_status(task);
 }
 
 /*
@@ -2107,9 +2083,6 @@ call_transmit_status(struct rpc_task *task)
        if (rpc_task_transmitted(task)) {
                if (task->tk_status == 0)
                        xprt_request_wait_receive(task);
-               if (rpc_task_need_resched(task))
-                       return;
-               call_status(task);
                return;
        }
 
@@ -2170,7 +2143,6 @@ call_bc_encode(struct rpc_task *task)
 {
        xprt_request_enqueue_transmit(task);
        task->tk_action = call_bc_transmit;
-       call_bc_transmit(task);
 }
 
 /*
@@ -2261,7 +2233,6 @@ call_status(struct rpc_task *task)
        status = task->tk_status;
        if (status >= 0) {
                task->tk_action = call_decode;
-               call_decode(task);
                return;
        }
 
index 89a63391d4d442f6d390556aa8cf0b5a2a41357a..30cfc0efe6990aa5f693b56c26c257bd968f43e5 100644 (file)
@@ -90,7 +90,7 @@ static void rpcrdma_xprt_drain(struct rpcrdma_xprt *r_xprt)
        /* Flush Receives, then wait for deferred Reply work
         * to complete.
         */
-       ib_drain_qp(ia->ri_id->qp);
+       ib_drain_rq(ia->ri_id->qp);
        drain_workqueue(buf->rb_completion_wq);
 
        /* Deferred Reply processing might have scheduled
index 49d664ddff444810ef9c6e8a1b0276c5ba473c53..87500bde5a92d599ccaa4e892ff12527feac58eb 100644 (file)
@@ -1336,9 +1336,16 @@ module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR);
 bool aa_g_paranoid_load = true;
 module_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO);
 
+static int param_get_aaintbool(char *buffer, const struct kernel_param *kp);
+static int param_set_aaintbool(const char *val, const struct kernel_param *kp);
+#define param_check_aaintbool param_check_int
+static const struct kernel_param_ops param_ops_aaintbool = {
+       .set = param_set_aaintbool,
+       .get = param_get_aaintbool
+};
 /* Boot time disable flag */
 static int apparmor_enabled __lsm_ro_after_init = 1;
-module_param_named(enabled, apparmor_enabled, int, 0444);
+module_param_named(enabled, apparmor_enabled, aaintbool, 0444);
 
 static int __init apparmor_enabled_setup(char *str)
 {
@@ -1413,6 +1420,46 @@ static int param_get_aauint(char *buffer, const struct kernel_param *kp)
        return param_get_uint(buffer, kp);
 }
 
+/* Can only be set before AppArmor is initialized (i.e. on boot cmdline). */
+static int param_set_aaintbool(const char *val, const struct kernel_param *kp)
+{
+       struct kernel_param kp_local;
+       bool value;
+       int error;
+
+       if (apparmor_initialized)
+               return -EPERM;
+
+       /* Create local copy, with arg pointing to bool type. */
+       value = !!*((int *)kp->arg);
+       memcpy(&kp_local, kp, sizeof(kp_local));
+       kp_local.arg = &value;
+
+       error = param_set_bool(val, &kp_local);
+       if (!error)
+               *((int *)kp->arg) = *((bool *)kp_local.arg);
+       return error;
+}
+
+/*
+ * To avoid changing /sys/module/apparmor/parameters/enabled from Y/N to
+ * 1/0, this converts the "int that is actually bool" back to bool for
+ * display in the /sys filesystem, while keeping it "int" for the LSM
+ * infrastructure.
+ */
+static int param_get_aaintbool(char *buffer, const struct kernel_param *kp)
+{
+       struct kernel_param kp_local;
+       bool value;
+
+       /* Create local copy, with arg pointing to bool type. */
+       value = !!*((int *)kp->arg);
+       memcpy(&kp_local, kp, sizeof(kp_local));
+       kp_local.arg = &value;
+
+       return param_get_bool(buffer, &kp_local);
+}
+
 static int param_get_audit(char *buffer, const struct kernel_param *kp)
 {
        if (!apparmor_enabled)
index bcc9c6ead7fd30962cf2ac3755e61d011d62c3da..efdbf17f3915259ea34ed76f5d452a4763236043 100644 (file)
@@ -125,7 +125,7 @@ out:
  */
 int TSS_authhmac(unsigned char *digest, const unsigned char *key,
                        unsigned int keylen, unsigned char *h1,
-                       unsigned char *h2, unsigned char h3, ...)
+                       unsigned char *h2, unsigned int h3, ...)
 {
        unsigned char paramdigest[SHA1_DIGEST_SIZE];
        struct sdesc *sdesc;
@@ -135,13 +135,16 @@ int TSS_authhmac(unsigned char *digest, const unsigned char *key,
        int ret;
        va_list argp;
 
+       if (!chip)
+               return -ENODEV;
+
        sdesc = init_sdesc(hashalg);
        if (IS_ERR(sdesc)) {
                pr_info("trusted_key: can't alloc %s\n", hash_alg);
                return PTR_ERR(sdesc);
        }
 
-       c = h3;
+       c = !!h3;
        ret = crypto_shash_init(&sdesc->shash);
        if (ret < 0)
                goto out;
@@ -196,6 +199,9 @@ int TSS_checkhmac1(unsigned char *buffer,
        va_list argp;
        int ret;
 
+       if (!chip)
+               return -ENODEV;
+
        bufsize = LOAD32(buffer, TPM_SIZE_OFFSET);
        tag = LOAD16(buffer, 0);
        ordinal = command;
@@ -363,6 +369,9 @@ int trusted_tpm_send(unsigned char *cmd, size_t buflen)
 {
        int rc;
 
+       if (!chip)
+               return -ENODEV;
+
        dump_tpm_buf(cmd);
        rc = tpm_send(chip, cmd, buflen);
        dump_tpm_buf(cmd);
@@ -429,6 +438,9 @@ int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
 {
        int ret;
 
+       if (!chip)
+               return -ENODEV;
+
        INIT_BUF(tb);
        store16(tb, TPM_TAG_RQU_COMMAND);
        store32(tb, TPM_OIAP_SIZE);
@@ -1245,9 +1257,13 @@ static int __init init_trusted(void)
 {
        int ret;
 
+       /* encrypted_keys.ko depends on successful load of this module even if
+        * TPM is not used.
+        */
        chip = tpm_default_chip();
        if (!chip)
-               return -ENOENT;
+               return 0;
+
        ret = init_digests();
        if (ret < 0)
                goto err_put;
@@ -1269,10 +1285,12 @@ err_put:
 
 static void __exit cleanup_trusted(void)
 {
-       put_device(&chip->dev);
-       kfree(digests);
-       trusted_shash_release();
-       unregister_key_type(&key_type_trusted);
+       if (chip) {
+               put_device(&chip->dev);
+               kfree(digests);
+               trusted_shash_release();
+               unregister_key_type(&key_type_trusted);
+       }
 }
 
 late_initcall(init_trusted);
index 7d4640d1fe9fb8a8ab8eecf045798497cb3e38f3..38e7deab638479ef9525c67fcd4f0fe37101cfb2 100644 (file)
@@ -1252,7 +1252,7 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
 
        /* fill the info fields */
        if (client_info->name[0])
-               strlcpy(client->name, client_info->name, sizeof(client->name));
+               strscpy(client->name, client_info->name, sizeof(client->name));
 
        client->filter = client_info->filter;
        client->event_lost = client_info->event_lost;
@@ -1530,7 +1530,7 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg)
        /* set queue name */
        if (!info->name[0])
                snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue);
-       strlcpy(q->name, info->name, sizeof(q->name));
+       strscpy(q->name, info->name, sizeof(q->name));
        snd_use_lock_free(&q->use_lock);
 
        return 0;
@@ -1592,7 +1592,7 @@ static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,
                queuefree(q);
                return -EPERM;
        }
-       strlcpy(q->name, info->name, sizeof(q->name));
+       strscpy(q->name, info->name, sizeof(q->name));
        queuefree(q);
 
        return 0;
index 9c37d9af3023f67bdba2ba4a3d207580cd1f70c5..ec7715c6b0c02c9bc940ed4b16f387b509bd1907 100644 (file)
@@ -107,7 +107,6 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
        INIT_LIST_HEAD(&bus->hlink_list);
        bus->idx = idx++;
 
-       mutex_init(&bus->lock);
        bus->cmd_dma_state = true;
 
        return 0;
index 012305177f68227af7bb25890a92c1ef93690221..ad8eee08013fb838e228daaa23cd974a92c34325 100644 (file)
@@ -38,6 +38,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
        INIT_WORK(&bus->unsol_work, snd_hdac_bus_process_unsol_events);
        spin_lock_init(&bus->reg_lock);
        mutex_init(&bus->cmd_mutex);
+       mutex_init(&bus->lock);
        bus->irq = -1;
        return 0;
 }
index 5c95933e739a43bc5cd30829e43c0381cff1e989..1ea51e3b942a034a1b487bb2ad7dc054893a4d39 100644 (file)
@@ -69,13 +69,15 @@ void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
 
        dev_dbg(bus->dev, "display power %s\n",
                enable ? "enable" : "disable");
+
+       mutex_lock(&bus->lock);
        if (enable)
                set_bit(idx, &bus->display_power_status);
        else
                clear_bit(idx, &bus->display_power_status);
 
        if (!acomp || !acomp->ops)
-               return;
+               goto unlock;
 
        if (bus->display_power_status) {
                if (!bus->display_power_active) {
@@ -92,6 +94,8 @@ void snd_hdac_display_power(struct hdac_bus *bus, unsigned int idx, bool enable)
                        bus->display_power_active = false;
                }
        }
+ unlock:
+       mutex_unlock(&bus->lock);
 }
 EXPORT_SYMBOL_GPL(snd_hdac_display_power);
 
index ece256a3b48f3b9108615931d8727c86d0d0ded5..2ec91085fa3e7708d27a605747213f2277b9bc2b 100644 (file)
@@ -2142,6 +2142,8 @@ static struct snd_pci_quirk power_save_blacklist[] = {
        SND_PCI_QUIRK(0x8086, 0x2040, "Intel DZ77BH-55K", 0),
        /* https://bugzilla.kernel.org/show_bug.cgi?id=199607 */
        SND_PCI_QUIRK(0x8086, 0x2057, "Intel NUC5i7RYB", 0),
+       /* https://bugs.launchpad.net/bugs/1821663 */
+       SND_PCI_QUIRK(0x8086, 0x2064, "Intel SDP 8086:2064", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1520902 */
        SND_PCI_QUIRK(0x8086, 0x2068, "Intel NUC7i3BNB", 0),
        /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */
@@ -2150,6 +2152,8 @@ static struct snd_pci_quirk power_save_blacklist[] = {
        SND_PCI_QUIRK(0x17aa, 0x367b, "Lenovo IdeaCentre B550", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */
        SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0),
+       /* https://bugs.launchpad.net/bugs/1821663 */
+       SND_PCI_QUIRK(0x1631, 0xe017, "Packard Bell NEC IMEDIA 5204", 0),
        {}
 };
 #endif /* CONFIG_PM */
index a3fb3d4c573090a156bf32534b1eed033f3ade16..810479766090376fbb2f8ecdb6da6012fb4058a3 100644 (file)
@@ -1864,8 +1864,8 @@ enum {
        ALC887_FIXUP_BASS_CHMAP,
        ALC1220_FIXUP_GB_DUAL_CODECS,
        ALC1220_FIXUP_CLEVO_P950,
-       ALC1220_FIXUP_SYSTEM76_ORYP5,
-       ALC1220_FIXUP_SYSTEM76_ORYP5_PINS,
+       ALC1220_FIXUP_CLEVO_PB51ED,
+       ALC1220_FIXUP_CLEVO_PB51ED_PINS,
 };
 
 static void alc889_fixup_coef(struct hda_codec *codec,
@@ -2070,7 +2070,7 @@ static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
 static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action);
 
-static void alc1220_fixup_system76_oryp5(struct hda_codec *codec,
+static void alc1220_fixup_clevo_pb51ed(struct hda_codec *codec,
                                     const struct hda_fixup *fix,
                                     int action)
 {
@@ -2322,18 +2322,18 @@ static const struct hda_fixup alc882_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc1220_fixup_clevo_p950,
        },
-       [ALC1220_FIXUP_SYSTEM76_ORYP5] = {
+       [ALC1220_FIXUP_CLEVO_PB51ED] = {
                .type = HDA_FIXUP_FUNC,
-               .v.func = alc1220_fixup_system76_oryp5,
+               .v.func = alc1220_fixup_clevo_pb51ed,
        },
-       [ALC1220_FIXUP_SYSTEM76_ORYP5_PINS] = {
+       [ALC1220_FIXUP_CLEVO_PB51ED_PINS] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
                        { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
                        {}
                },
                .chained = true,
-               .chain_id = ALC1220_FIXUP_SYSTEM76_ORYP5,
+               .chain_id = ALC1220_FIXUP_CLEVO_PB51ED,
        },
 };
 
@@ -2411,8 +2411,9 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
-       SND_PCI_QUIRK(0x1558, 0x96e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS),
-       SND_PCI_QUIRK(0x1558, 0x97e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS),
+       SND_PCI_QUIRK(0x1558, 0x96e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+       SND_PCI_QUIRK(0x1558, 0x97e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+       SND_PCI_QUIRK(0x1558, 0x65d1, "Tuxedo Book XC1509", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
@@ -5491,7 +5492,7 @@ static void alc_headset_btn_callback(struct hda_codec *codec,
        jack->jack->button_state = report;
 }
 
-static void alc295_fixup_chromebook(struct hda_codec *codec,
+static void alc_fixup_headset_jack(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
 {
 
@@ -5501,16 +5502,6 @@ static void alc295_fixup_chromebook(struct hda_codec *codec,
                                                    alc_headset_btn_callback);
                snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false,
                                      SND_JACK_HEADSET, alc_headset_btn_keymap);
-               switch (codec->core.vendor_id) {
-               case 0x10ec0295:
-                       alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */
-                       alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15);
-                       break;
-               case 0x10ec0236:
-                       alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */
-                       alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15);
-                       break;
-               }
                break;
        case HDA_FIXUP_ACT_INIT:
                switch (codec->core.vendor_id) {
@@ -5531,6 +5522,25 @@ static void alc295_fixup_chromebook(struct hda_codec *codec,
        }
 }
 
+static void alc295_fixup_chromebook(struct hda_codec *codec,
+                                   const struct hda_fixup *fix, int action)
+{
+       switch (action) {
+       case HDA_FIXUP_ACT_INIT:
+               switch (codec->core.vendor_id) {
+               case 0x10ec0295:
+                       alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */
+                       alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15);
+                       break;
+               case 0x10ec0236:
+                       alc_update_coef_idx(codec, 0x1b, 0x8000, 1 << 15); /* Reset HP JD */
+                       alc_update_coef_idx(codec, 0x1b, 0x8000, 0 << 15);
+                       break;
+               }
+               break;
+       }
+}
+
 static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
                                  const struct hda_fixup *fix, int action)
 {
@@ -5663,6 +5673,7 @@ enum {
        ALC233_FIXUP_ASUS_MIC_NO_PRESENCE,
        ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE,
        ALC233_FIXUP_LENOVO_MULTI_CODECS,
+       ALC233_FIXUP_ACER_HEADSET_MIC,
        ALC294_FIXUP_LENOVO_MIC_LOCATION,
        ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE,
        ALC700_FIXUP_INTEL_REFERENCE,
@@ -5684,6 +5695,7 @@ enum {
        ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
        ALC255_FIXUP_ACER_HEADSET_MIC,
        ALC295_FIXUP_CHROME_BOOK,
+       ALC225_FIXUP_HEADSET_JACK,
        ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE,
        ALC225_FIXUP_WYSE_AUTO_MUTE,
        ALC225_FIXUP_WYSE_DISABLE_MIC_VREF,
@@ -6490,6 +6502,16 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc233_alc662_fixup_lenovo_dual_codecs,
        },
+       [ALC233_FIXUP_ACER_HEADSET_MIC] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x45 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x5089 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC233_FIXUP_ASUS_MIC_NO_PRESENCE
+       },
        [ALC294_FIXUP_LENOVO_MIC_LOCATION] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -6635,6 +6657,12 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC295_FIXUP_CHROME_BOOK] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc295_fixup_chromebook,
+               .chained = true,
+               .chain_id = ALC225_FIXUP_HEADSET_JACK
+       },
+       [ALC225_FIXUP_HEADSET_JACK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_headset_jack,
        },
        [ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = {
                .type = HDA_FIXUP_PINS,
@@ -6737,6 +6765,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
@@ -7132,7 +7161,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC255_FIXUP_DUMMY_LINEOUT_VERB, .name = "alc255-dummy-lineout"},
        {.id = ALC255_FIXUP_DELL_HEADSET_MIC, .name = "alc255-dell-headset"},
        {.id = ALC295_FIXUP_HP_X360, .name = "alc295-hp-x360"},
-       {.id = ALC295_FIXUP_CHROME_BOOK, .name = "alc-sense-combo"},
+       {.id = ALC225_FIXUP_HEADSET_JACK, .name = "alc-headset-jack"},
+       {.id = ALC295_FIXUP_CHROME_BOOK, .name = "alc-chrome-book"},
        {.id = ALC299_FIXUP_PREDATOR_SPK, .name = "predator-spk"},
        {}
 };
index 419114edfd57db8f341184148fcf4d7ab7d67a0a..667fc1d59e189f599e580654c10719b96b7e74a0 100644 (file)
@@ -1151,6 +1151,7 @@ config SND_SOC_WCD9335
        tristate "WCD9335 Codec"
        depends on SLIMBUS
        select REGMAP_SLIMBUS
+       select REGMAP_IRQ
        help
          The WCD9335 is a standalone Hi-Fi audio CODEC IC, supports
          Qualcomm Technologies, Inc. (QTI) multimedia solutions,
index 03bbbcd3b6c115254a75f367c40447f012edc8c4..87616b126018b3cb9b9a5c8f4ca7a3af51b97264 100644 (file)
@@ -2129,6 +2129,7 @@ static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                dev_err(dai->component->dev,
                        "%s: ERROR: The device is either a master or a slave.\n",
                        __func__);
+               /* fall through */
        default:
                dev_err(dai->component->dev,
                        "%s: ERROR: Unsupporter master mask 0x%x\n",
index 9f4a59871cee72b2011acf20d8167e12933ec2fc..c71696146c5ec17e17751903a592038c4f8347e4 100644 (file)
@@ -1635,6 +1635,16 @@ err:
        return ret;
 }
 
+static int cs35l35_i2c_remove(struct i2c_client *i2c_client)
+{
+       struct cs35l35_private *cs35l35 = i2c_get_clientdata(i2c_client);
+
+       regulator_bulk_disable(cs35l35->num_supplies, cs35l35->supplies);
+       gpiod_set_value_cansleep(cs35l35->reset_gpio, 0);
+
+       return 0;
+}
+
 static const struct of_device_id cs35l35_of_match[] = {
        {.compatible = "cirrus,cs35l35"},
        {},
@@ -1655,6 +1665,7 @@ static struct i2c_driver cs35l35_i2c_driver = {
        },
        .id_table = cs35l35_id,
        .probe = cs35l35_i2c_probe,
+       .remove = cs35l35_i2c_remove,
 };
 
 module_i2c_driver(cs35l35_i2c_driver);
index 33d74f163bd753820bb77bd81d8f0a28461410e5..793a14d586672bc2b76b143b5756206becce28a8 100644 (file)
@@ -642,6 +642,7 @@ static const struct regmap_config cs4270_regmap = {
        .reg_defaults =         cs4270_reg_defaults,
        .num_reg_defaults =     ARRAY_SIZE(cs4270_reg_defaults),
        .cache_type =           REGCACHE_RBTREE,
+       .write_flag_mask =      CS4270_I2C_INCR,
 
        .readable_reg =         cs4270_reg_is_readable,
        .volatile_reg =         cs4270_reg_is_volatile,
index ffecdaaa8cf2bb2e69bde2de7e2acb92cbdec0a1..f889d94c8e3cf707f0bcab6cdb7f860851d7042f 100644 (file)
@@ -38,6 +38,9 @@ static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
                               struct snd_soc_dai *dai);
 static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *dai);
+static int hdac_hda_dai_hw_params(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params,
+                                 struct snd_soc_dai *dai);
 static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *dai);
 static int hdac_hda_dai_set_tdm_slot(struct snd_soc_dai *dai,
@@ -50,6 +53,7 @@ static const struct snd_soc_dai_ops hdac_hda_dai_ops = {
        .startup = hdac_hda_dai_open,
        .shutdown = hdac_hda_dai_close,
        .prepare = hdac_hda_dai_prepare,
+       .hw_params = hdac_hda_dai_hw_params,
        .hw_free = hdac_hda_dai_hw_free,
        .set_tdm_slot = hdac_hda_dai_set_tdm_slot,
 };
@@ -139,6 +143,39 @@ static int hdac_hda_dai_set_tdm_slot(struct snd_soc_dai *dai,
        return 0;
 }
 
+static int hdac_hda_dai_hw_params(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params,
+                                 struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct hdac_hda_priv *hda_pvt;
+       unsigned int format_val;
+       unsigned int maxbps;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               maxbps = dai->driver->playback.sig_bits;
+       else
+               maxbps = dai->driver->capture.sig_bits;
+
+       hda_pvt = snd_soc_component_get_drvdata(component);
+       format_val = snd_hdac_calc_stream_format(params_rate(params),
+                                                params_channels(params),
+                                                params_format(params),
+                                                maxbps,
+                                                0);
+       if (!format_val) {
+               dev_err(dai->dev,
+                       "invalid format_val, rate=%d, ch=%d, format=%d, maxbps=%d\n",
+                       params_rate(params), params_channels(params),
+                       params_format(params), maxbps);
+
+               return -EINVAL;
+       }
+
+       hda_pvt->pcm[dai->id].format_val[substream->stream] = format_val;
+       return 0;
+}
+
 static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *dai)
 {
@@ -162,10 +199,9 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *dai)
 {
        struct snd_soc_component *component = dai->component;
+       struct hda_pcm_stream *hda_stream;
        struct hdac_hda_priv *hda_pvt;
-       struct snd_pcm_runtime *runtime = substream->runtime;
        struct hdac_device *hdev;
-       struct hda_pcm_stream *hda_stream;
        unsigned int format_val;
        struct hda_pcm *pcm;
        unsigned int stream;
@@ -179,19 +215,8 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream,
 
        hda_stream = &pcm->stream[substream->stream];
 
-       format_val = snd_hdac_calc_stream_format(runtime->rate,
-                                                runtime->channels,
-                                                runtime->format,
-                                                hda_stream->maxbps,
-                                                0);
-       if (!format_val) {
-               dev_err(&hdev->dev,
-                       "invalid format_val, rate=%d, ch=%d, format=%d\n",
-                       runtime->rate, runtime->channels, runtime->format);
-               return -EINVAL;
-       }
-
        stream = hda_pvt->pcm[dai->id].stream_tag[substream->stream];
+       format_val = hda_pvt->pcm[dai->id].format_val[substream->stream];
 
        ret = snd_hda_codec_prepare(&hda_pvt->codec, hda_stream,
                                    stream, format_val, substream);
index e444ef5933606ce8689f06ba187f3e84491d6336..6b1bd4f428e70ed4037adef636ef9c42878d2865 100644 (file)
@@ -8,6 +8,7 @@
 
 struct hdac_hda_pcm {
        int stream_tag[2];
+       unsigned int format_val[2];
 };
 
 struct hdac_hda_priv {
index e5b6769b9797724ceef38f3b8132200876f227e8..35df73e42cbc5f9d7bf6af4aa954bde49e8565e2 100644 (file)
@@ -484,9 +484,6 @@ static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,
                params_width(params), params_rate(params),
                params_channels(params));
 
-       if (params_width(params) > 24)
-               params->msbits = 24;
-
        ret = snd_pcm_create_iec958_consumer_hw_params(params, hp.iec.status,
                                                       sizeof(hp.iec.status));
        if (ret < 0) {
@@ -529,73 +526,71 @@ static int hdmi_codec_set_fmt(struct snd_soc_dai *dai,
 {
        struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
        struct hdmi_codec_daifmt cf = { 0 };
-       int ret = 0;
 
        dev_dbg(dai->dev, "%s()\n", __func__);
 
-       if (dai->id == DAI_ID_SPDIF) {
-               cf.fmt = HDMI_SPDIF;
-       } else {
-               switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-               case SND_SOC_DAIFMT_CBM_CFM:
-                       cf.bit_clk_master = 1;
-                       cf.frame_clk_master = 1;
-                       break;
-               case SND_SOC_DAIFMT_CBS_CFM:
-                       cf.frame_clk_master = 1;
-                       break;
-               case SND_SOC_DAIFMT_CBM_CFS:
-                       cf.bit_clk_master = 1;
-                       break;
-               case SND_SOC_DAIFMT_CBS_CFS:
-                       break;
-               default:
-                       return -EINVAL;
-               }
+       if (dai->id == DAI_ID_SPDIF)
+               return 0;
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               cf.bit_clk_master = 1;
+               cf.frame_clk_master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               cf.frame_clk_master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               cf.bit_clk_master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       default:
+               return -EINVAL;
+       }
 
-               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-               case SND_SOC_DAIFMT_NB_NF:
-                       break;
-               case SND_SOC_DAIFMT_NB_IF:
-                       cf.frame_clk_inv = 1;
-                       break;
-               case SND_SOC_DAIFMT_IB_NF:
-                       cf.bit_clk_inv = 1;
-                       break;
-               case SND_SOC_DAIFMT_IB_IF:
-                       cf.frame_clk_inv = 1;
-                       cf.bit_clk_inv = 1;
-                       break;
-               }
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               cf.frame_clk_inv = 1;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               cf.bit_clk_inv = 1;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               cf.frame_clk_inv = 1;
+               cf.bit_clk_inv = 1;
+               break;
+       }
 
-               switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-               case SND_SOC_DAIFMT_I2S:
-                       cf.fmt = HDMI_I2S;
-                       break;
-               case SND_SOC_DAIFMT_DSP_A:
-                       cf.fmt = HDMI_DSP_A;
-                       break;
-               case SND_SOC_DAIFMT_DSP_B:
-                       cf.fmt = HDMI_DSP_B;
-                       break;
-               case SND_SOC_DAIFMT_RIGHT_J:
-                       cf.fmt = HDMI_RIGHT_J;
-                       break;
-               case SND_SOC_DAIFMT_LEFT_J:
-                       cf.fmt = HDMI_LEFT_J;
-                       break;
-               case SND_SOC_DAIFMT_AC97:
-                       cf.fmt = HDMI_AC97;
-                       break;
-               default:
-                       dev_err(dai->dev, "Invalid DAI interface format\n");
-                       return -EINVAL;
-               }
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               cf.fmt = HDMI_I2S;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               cf.fmt = HDMI_DSP_A;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               cf.fmt = HDMI_DSP_B;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               cf.fmt = HDMI_RIGHT_J;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               cf.fmt = HDMI_LEFT_J;
+               break;
+       case SND_SOC_DAIFMT_AC97:
+               cf.fmt = HDMI_AC97;
+               break;
+       default:
+               dev_err(dai->dev, "Invalid DAI interface format\n");
+               return -EINVAL;
        }
 
        hcp->daifmt[dai->id] = cf;
 
-       return ret;
+       return 0;
 }
 
 static int hdmi_codec_digital_mute(struct snd_soc_dai *dai, int mute)
@@ -792,8 +787,10 @@ static int hdmi_codec_probe(struct platform_device *pdev)
                i++;
        }
 
-       if (hcd->spdif)
+       if (hcd->spdif) {
                hcp->daidrv[i] = hdmi_spdif_dai;
+               hcp->daifmt[DAI_ID_SPDIF].fmt = HDMI_SPDIF;
+       }
 
        dev_set_drvdata(dev, hcp);
 
index bfd74b86c9d2f43b8e19d8bd4c211c6d2f3cd887..645aa07941237d13cbebdf0d4bf17130f9dae1ae 100644 (file)
@@ -411,9 +411,9 @@ static const struct snd_soc_dapm_widget nau8810_dapm_widgets[] = {
        SND_SOC_DAPM_MIXER("Mono Mixer", NAU8810_REG_POWER3,
                NAU8810_MOUTMX_EN_SFT, 0, &nau8810_mono_mixer_controls[0],
                ARRAY_SIZE(nau8810_mono_mixer_controls)),
-       SND_SOC_DAPM_DAC("DAC", "HiFi Playback", NAU8810_REG_POWER3,
+       SND_SOC_DAPM_DAC("DAC", "Playback", NAU8810_REG_POWER3,
                NAU8810_DAC_EN_SFT, 0),
-       SND_SOC_DAPM_ADC("ADC", "HiFi Capture", NAU8810_REG_POWER2,
+       SND_SOC_DAPM_ADC("ADC", "Capture", NAU8810_REG_POWER2,
                NAU8810_ADC_EN_SFT, 0),
        SND_SOC_DAPM_PGA("SpkN Out", NAU8810_REG_POWER3,
                NAU8810_NSPK_EN_SFT, 0, NULL, 0),
index 87ed3dc496dc2de72043c8dbd5c66cbed7c0f923..5ab05e75edeac61219945488a455eafdc8f785f1 100644 (file)
@@ -681,8 +681,8 @@ static const struct snd_soc_dapm_widget nau8824_dapm_widgets[] = {
        SND_SOC_DAPM_ADC("ADCR", NULL, NAU8824_REG_ANALOG_ADC_2,
                NAU8824_ADCR_EN_SFT, 0),
 
-       SND_SOC_DAPM_AIF_OUT("AIFTX", "HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
-       SND_SOC_DAPM_AIF_IN("AIFRX", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("AIFTX", "Capture", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_IN("AIFRX", "Playback", 0, SND_SOC_NOPM, 0, 0),
 
        SND_SOC_DAPM_DAC("DACL", NULL, NAU8824_REG_RDAC,
                NAU8824_DACL_EN_SFT, 0),
@@ -831,6 +831,36 @@ static void nau8824_int_status_clear_all(struct regmap *regmap)
        }
 }
 
+static void nau8824_dapm_disable_pin(struct nau8824 *nau8824, const char *pin)
+{
+       struct snd_soc_dapm_context *dapm = nau8824->dapm;
+       const char *prefix = dapm->component->name_prefix;
+       char prefixed_pin[80];
+
+       if (prefix) {
+               snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
+                        prefix, pin);
+               snd_soc_dapm_disable_pin(dapm, prefixed_pin);
+       } else {
+               snd_soc_dapm_disable_pin(dapm, pin);
+       }
+}
+
+static void nau8824_dapm_enable_pin(struct nau8824 *nau8824, const char *pin)
+{
+       struct snd_soc_dapm_context *dapm = nau8824->dapm;
+       const char *prefix = dapm->component->name_prefix;
+       char prefixed_pin[80];
+
+       if (prefix) {
+               snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
+                        prefix, pin);
+               snd_soc_dapm_force_enable_pin(dapm, prefixed_pin);
+       } else {
+               snd_soc_dapm_force_enable_pin(dapm, pin);
+       }
+}
+
 static void nau8824_eject_jack(struct nau8824 *nau8824)
 {
        struct snd_soc_dapm_context *dapm = nau8824->dapm;
@@ -839,8 +869,8 @@ static void nau8824_eject_jack(struct nau8824 *nau8824)
        /* Clear all interruption status */
        nau8824_int_status_clear_all(regmap);
 
-       snd_soc_dapm_disable_pin(dapm, "SAR");
-       snd_soc_dapm_disable_pin(dapm, "MICBIAS");
+       nau8824_dapm_disable_pin(nau8824, "SAR");
+       nau8824_dapm_disable_pin(nau8824, "MICBIAS");
        snd_soc_dapm_sync(dapm);
 
        /* Enable the insertion interruption, disable the ejection
@@ -870,8 +900,8 @@ static void nau8824_jdet_work(struct work_struct *work)
        struct regmap *regmap = nau8824->regmap;
        int adc_value, event = 0, event_mask = 0;
 
-       snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
-       snd_soc_dapm_force_enable_pin(dapm, "SAR");
+       nau8824_dapm_enable_pin(nau8824, "MICBIAS");
+       nau8824_dapm_enable_pin(nau8824, "SAR");
        snd_soc_dapm_sync(dapm);
 
        msleep(100);
@@ -882,8 +912,8 @@ static void nau8824_jdet_work(struct work_struct *work)
        if (adc_value < HEADSET_SARADC_THD) {
                event |= SND_JACK_HEADPHONE;
 
-               snd_soc_dapm_disable_pin(dapm, "SAR");
-               snd_soc_dapm_disable_pin(dapm, "MICBIAS");
+               nau8824_dapm_disable_pin(nau8824, "SAR");
+               nau8824_dapm_disable_pin(nau8824, "MICBIAS");
                snd_soc_dapm_sync(dapm);
        } else {
                event |= SND_JACK_HEADSET;
index 9d5acd2d04abd47281b26d8f81331182c0288fb8..86a7fa31c294b2d3fb00494dd3c934976c2a2044 100644 (file)
@@ -910,13 +910,21 @@ static int rt5682_headset_detect(struct snd_soc_component *component,
                int jack_insert)
 {
        struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
-       struct snd_soc_dapm_context *dapm =
-               snd_soc_component_get_dapm(component);
        unsigned int val, count;
 
        if (jack_insert) {
-               snd_soc_dapm_force_enable_pin(dapm, "CBJ Power");
-               snd_soc_dapm_sync(dapm);
+
+               snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
+                       RT5682_PWR_VREF2 | RT5682_PWR_MB,
+                       RT5682_PWR_VREF2 | RT5682_PWR_MB);
+               snd_soc_component_update_bits(component,
+                               RT5682_PWR_ANLG_1, RT5682_PWR_FV2, 0);
+               usleep_range(15000, 20000);
+               snd_soc_component_update_bits(component,
+                               RT5682_PWR_ANLG_1, RT5682_PWR_FV2, RT5682_PWR_FV2);
+               snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
+                       RT5682_PWR_CBJ, RT5682_PWR_CBJ);
+
                snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
                        RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_HIGH);
 
@@ -944,8 +952,10 @@ static int rt5682_headset_detect(struct snd_soc_component *component,
                rt5682_enable_push_button_irq(component, false);
                snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
                        RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_LOW);
-               snd_soc_dapm_disable_pin(dapm, "CBJ Power");
-               snd_soc_dapm_sync(dapm);
+               snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1,
+                       RT5682_PWR_VREF2 | RT5682_PWR_MB, 0);
+               snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
+                       RT5682_PWR_CBJ, 0);
 
                rt5682->jack_type = 0;
        }
@@ -1198,7 +1208,7 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w,
        struct snd_soc_component *component =
                snd_soc_dapm_to_component(w->dapm);
        struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
-       int ref, val, reg, sft, mask, idx = -EINVAL;
+       int ref, val, reg, idx = -EINVAL;
        static const int div_f[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48};
        static const int div_o[] = {1, 2, 4, 6, 8, 12, 16, 24, 32, 48};
 
@@ -1212,15 +1222,10 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w,
 
        idx = rt5682_div_sel(rt5682, ref, div_f, ARRAY_SIZE(div_f));
 
-       if (w->shift == RT5682_PWR_ADC_S1F_BIT) {
+       if (w->shift == RT5682_PWR_ADC_S1F_BIT)
                reg = RT5682_PLL_TRACK_3;
-               sft = RT5682_ADC_OSR_SFT;
-               mask = RT5682_ADC_OSR_MASK;
-       } else {
+       else
                reg = RT5682_PLL_TRACK_2;
-               sft = RT5682_DAC_OSR_SFT;
-               mask = RT5682_DAC_OSR_MASK;
-       }
 
        snd_soc_component_update_bits(component, reg,
                RT5682_FILTER_CLK_DIV_MASK, idx << RT5682_FILTER_CLK_DIV_SFT);
@@ -1232,7 +1237,8 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w,
        }
 
        snd_soc_component_update_bits(component, RT5682_ADDA_CLK_1,
-               mask, idx << sft);
+               RT5682_ADC_OSR_MASK | RT5682_DAC_OSR_MASK,
+               (idx << RT5682_ADC_OSR_SFT) | (idx << RT5682_DAC_OSR_SFT));
 
        return 0;
 }
@@ -1591,8 +1597,6 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
                0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("Vref1", RT5682_PWR_ANLG_1, RT5682_PWR_VREF1_BIT, 0,
                rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
-       SND_SOC_DAPM_SUPPLY("Vref2", RT5682_PWR_ANLG_1, RT5682_PWR_VREF2_BIT, 0,
-               rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 
        /* ASRC */
        SND_SOC_DAPM_SUPPLY_S("DAC STO1 ASRC", 1, RT5682_PLL_TRACK_1,
@@ -1627,9 +1631,6 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("BST1 CBJ", SND_SOC_NOPM,
                0, 0, NULL, 0),
 
-       SND_SOC_DAPM_SUPPLY("CBJ Power", RT5682_PWR_ANLG_3,
-               RT5682_PWR_CBJ_BIT, 0, NULL, 0),
-
        /* REC Mixer */
        SND_SOC_DAPM_MIXER("RECMIX1L", SND_SOC_NOPM, 0, 0, rt5682_rec1_l_mix,
                ARRAY_SIZE(rt5682_rec1_l_mix)),
@@ -1792,17 +1793,13 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
 
        /*Vref*/
        {"MICBIAS1", NULL, "Vref1"},
-       {"MICBIAS1", NULL, "Vref2"},
        {"MICBIAS2", NULL, "Vref1"},
-       {"MICBIAS2", NULL, "Vref2"},
 
        {"CLKDET SYS", NULL, "CLKDET"},
 
        {"IN1P", NULL, "LDO2"},
 
        {"BST1 CBJ", NULL, "IN1P"},
-       {"BST1 CBJ", NULL, "CBJ Power"},
-       {"CBJ Power", NULL, "Vref2"},
 
        {"RECMIX1L", "CBJ Switch", "BST1 CBJ"},
        {"RECMIX1L", NULL, "RECMIX1L Power"},
@@ -1912,9 +1909,7 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
        {"HP Amp", NULL, "Capless"},
        {"HP Amp", NULL, "Charge Pump"},
        {"HP Amp", NULL, "CLKDET SYS"},
-       {"HP Amp", NULL, "CBJ Power"},
        {"HP Amp", NULL, "Vref1"},
-       {"HP Amp", NULL, "Vref2"},
        {"HPOL Playback", "Switch", "HP Amp"},
        {"HPOR Playback", "Switch", "HP Amp"},
        {"HPOL", NULL, "HPOL Playback"},
@@ -2303,16 +2298,13 @@ static int rt5682_set_bias_level(struct snd_soc_component *component,
        switch (level) {
        case SND_SOC_BIAS_PREPARE:
                regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
-                       RT5682_PWR_MB | RT5682_PWR_BG,
-                       RT5682_PWR_MB | RT5682_PWR_BG);
+                       RT5682_PWR_BG, RT5682_PWR_BG);
                regmap_update_bits(rt5682->regmap, RT5682_PWR_DIG_1,
                        RT5682_DIG_GATE_CTRL | RT5682_PWR_LDO,
                        RT5682_DIG_GATE_CTRL | RT5682_PWR_LDO);
                break;
 
        case SND_SOC_BIAS_STANDBY:
-               regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
-                       RT5682_PWR_MB, RT5682_PWR_MB);
                regmap_update_bits(rt5682->regmap, RT5682_PWR_DIG_1,
                        RT5682_DIG_GATE_CTRL, RT5682_DIG_GATE_CTRL);
                break;
@@ -2320,7 +2312,7 @@ static int rt5682_set_bias_level(struct snd_soc_component *component,
                regmap_update_bits(rt5682->regmap, RT5682_PWR_DIG_1,
                        RT5682_DIG_GATE_CTRL | RT5682_PWR_LDO, 0);
                regmap_update_bits(rt5682->regmap, RT5682_PWR_ANLG_1,
-                       RT5682_PWR_MB | RT5682_PWR_BG, 0);
+                       RT5682_PWR_BG, 0);
                break;
 
        default:
@@ -2363,6 +2355,8 @@ static int rt5682_resume(struct snd_soc_component *component)
        regcache_cache_only(rt5682->regmap, false);
        regcache_sync(rt5682->regmap);
 
+       rt5682_irq(0, rt5682);
+
        return 0;
 }
 #else
index 385fa2e9525abe2c89fc624baef239b2541b7328..22c3a6bc0b6c47ae90de8fc435127b089fb80517 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2011 NW Digital Radio
  *
- * Author: Jeremy McDermond <nh6z@nh6z.net>
+ * Author: Annaliese McDermond <nh6z@nh6z.net>
  *
  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
  *
@@ -72,5 +72,5 @@ static struct i2c_driver aic32x4_i2c_driver = {
 module_i2c_driver(aic32x4_i2c_driver);
 
 MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver I2C");
-MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
+MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
 MODULE_LICENSE("GPL");
index 07d78ae51e05c77bbd0a93410d0df2449be5d759..aa5b7ba0254bc6b7e009ce2adb6099d2d138819c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2011 NW Digital Radio
  *
- * Author: Jeremy McDermond <nh6z@nh6z.net>
+ * Author: Annaliese McDermond <nh6z@nh6z.net>
  *
  * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
  *
@@ -74,5 +74,5 @@ static struct spi_driver aic32x4_spi_driver = {
 module_spi_driver(aic32x4_spi_driver);
 
 MODULE_DESCRIPTION("ASoC TLV320AIC32x4 codec driver SPI");
-MODULE_AUTHOR("Jeremy McDermond <nh6z@nh6z.net>");
+MODULE_AUTHOR("Annaliese McDermond <nh6z@nh6z.net>");
 MODULE_LICENSE("GPL");
index 96f1526cb258a4e718afb86712aece3608c18003..5520044929f42ff6c51d18fb8338602127c79b91 100644 (file)
@@ -490,6 +490,8 @@ static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("IN2_R"),
        SND_SOC_DAPM_INPUT("IN3_L"),
        SND_SOC_DAPM_INPUT("IN3_R"),
+       SND_SOC_DAPM_INPUT("CM_L"),
+       SND_SOC_DAPM_INPUT("CM_R"),
 };
 
 static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
index 283583d1db60555f0831229be3b2f0e1a65bafee..516d17cb2182287f8f739a072fe3128687cecd93 100644 (file)
@@ -1609,7 +1609,6 @@ static int aic3x_probe(struct snd_soc_component *component)
        struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component);
        int ret, i;
 
-       INIT_LIST_HEAD(&aic3x->list);
        aic3x->component = component;
 
        for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
@@ -1873,6 +1872,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
        if (ret != 0)
                goto err_gpio;
 
+       INIT_LIST_HEAD(&aic3x->list);
        list_add(&aic3x->list, &reset_list);
 
        return 0;
@@ -1889,6 +1889,8 @@ static int aic3x_i2c_remove(struct i2c_client *client)
 {
        struct aic3x_priv *aic3x = i2c_get_clientdata(client);
 
+       list_del(&aic3x->list);
+
        if (gpio_is_valid(aic3x->gpio_reset) &&
            !aic3x_is_shared_reset(aic3x)) {
                gpio_set_value(aic3x->gpio_reset, 0);
index b93fdc8d2d6fb76112eabc4fe2a6a302fa86b710..b0b48eb9c7c91578cb5d588955a0afa74f0ff262 100644 (file)
@@ -2905,6 +2905,8 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                if (wm_adsp_fw[dsp->fw].num_caps != 0)
                        wm_adsp_buffer_free(dsp);
 
+               dsp->fatal_error = false;
+
                mutex_unlock(&dsp->pwr_lock);
 
                adsp_dbg(dsp, "Execution stopped\n");
@@ -3000,6 +3002,9 @@ static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
 {
        struct wm_adsp_compr_buf *buf = NULL, *tmp;
 
+       if (compr->dsp->fatal_error)
+               return -EINVAL;
+
        list_for_each_entry(tmp, &compr->dsp->buffer_list, list) {
                if (!tmp->name || !strcmp(compr->name, tmp->name)) {
                        buf = tmp;
@@ -3535,11 +3540,11 @@ static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
 
        ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
        if (ret < 0) {
-               adsp_err(buf->dsp, "Failed to check buffer error: %d\n", ret);
+               compr_err(buf, "Failed to check buffer error: %d\n", ret);
                return ret;
        }
        if (buf->error != 0) {
-               adsp_err(buf->dsp, "Buffer error occurred: %d\n", buf->error);
+               compr_err(buf, "Buffer error occurred: %d\n", buf->error);
                return -EIO;
        }
 
@@ -3571,8 +3576,6 @@ int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
                if (ret < 0)
                        break;
 
-               wm_adsp_buffer_clear(compr->buf);
-
                /* Trigger the IRQ at one fragment of data */
                ret = wm_adsp_buffer_write(compr->buf,
                                           HOST_BUFFER_FIELD(high_water_mark),
@@ -3584,6 +3587,8 @@ int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
                }
                break;
        case SNDRV_PCM_TRIGGER_STOP:
+               if (wm_adsp_compr_attached(compr))
+                       wm_adsp_buffer_clear(compr->buf);
                break;
        default:
                ret = -EINVAL;
@@ -3917,22 +3922,40 @@ int wm_adsp2_lock(struct wm_adsp *dsp, unsigned int lock_regions)
 }
 EXPORT_SYMBOL_GPL(wm_adsp2_lock);
 
+static void wm_adsp_fatal_error(struct wm_adsp *dsp)
+{
+       struct wm_adsp_compr *compr;
+
+       dsp->fatal_error = true;
+
+       list_for_each_entry(compr, &dsp->compr_list, list) {
+               if (compr->stream) {
+                       snd_compr_stop_error(compr->stream,
+                                            SNDRV_PCM_STATE_XRUN);
+                       snd_compr_fragment_elapsed(compr->stream);
+               }
+       }
+}
+
 irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp)
 {
        unsigned int val;
        struct regmap *regmap = dsp->regmap;
        int ret = 0;
 
+       mutex_lock(&dsp->pwr_lock);
+
        ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val);
        if (ret) {
                adsp_err(dsp,
                        "Failed to read Region Lock Ctrl register: %d\n", ret);
-               return IRQ_HANDLED;
+               goto error;
        }
 
        if (val & ADSP2_WDT_TIMEOUT_STS_MASK) {
                adsp_err(dsp, "watchdog timeout error\n");
                wm_adsp_stop_watchdog(dsp);
+               wm_adsp_fatal_error(dsp);
        }
 
        if (val & (ADSP2_SLAVE_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) {
@@ -3946,7 +3969,7 @@ irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp)
                        adsp_err(dsp,
                                 "Failed to read Bus Err Addr register: %d\n",
                                 ret);
-                       return IRQ_HANDLED;
+                       goto error;
                }
 
                adsp_err(dsp, "bus error address = 0x%x\n",
@@ -3959,7 +3982,7 @@ irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp)
                        adsp_err(dsp,
                                 "Failed to read Pmem Xmem Err Addr register: %d\n",
                                 ret);
-                       return IRQ_HANDLED;
+                       goto error;
                }
 
                adsp_err(dsp, "xmem error address = 0x%x\n",
@@ -3972,6 +3995,9 @@ irqreturn_t wm_adsp2_bus_error(struct wm_adsp *dsp)
        regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL,
                           ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT);
 
+error:
+       mutex_unlock(&dsp->pwr_lock);
+
        return IRQ_HANDLED;
 }
 EXPORT_SYMBOL_GPL(wm_adsp2_bus_error);
index 59e07ad163296c3ff21f238ccdfca96b6af43c76..8f09b4419a914ae773558c6175529b1acebf9a82 100644 (file)
@@ -85,6 +85,7 @@ struct wm_adsp {
        bool preloaded;
        bool booted;
        bool running;
+       bool fatal_error;
 
        struct list_head ctl_list;
 
index 528e8b108422971eea52655b55642ac5cdbe575d..0b937924d2e47961d697d068edf3944772058baa 100644 (file)
@@ -445,6 +445,19 @@ struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir)
 }
 EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel);
 
+static int fsl_asrc_dai_startup(struct snd_pcm_substream *substream,
+                               struct snd_soc_dai *dai)
+{
+       struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
+
+       /* Odd channel number is not valid for older ASRC (channel_bits==3) */
+       if (asrc_priv->channel_bits == 3)
+               snd_pcm_hw_constraint_step(substream->runtime, 0,
+                                          SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+
+       return 0;
+}
+
 static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *params,
                                  struct snd_soc_dai *dai)
@@ -539,6 +552,7 @@ static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 }
 
 static const struct snd_soc_dai_ops fsl_asrc_dai_ops = {
+       .startup      = fsl_asrc_dai_startup,
        .hw_params    = fsl_asrc_dai_hw_params,
        .hw_free      = fsl_asrc_dai_hw_free,
        .trigger      = fsl_asrc_dai_trigger,
index afe67c865330e39c7b3d1b30bd6127dd764f42aa..3623aa9a6f2ea7838e2c855a5d88681436ac11c1 100644 (file)
@@ -54,6 +54,8 @@ struct fsl_esai {
        u32 fifo_depth;
        u32 slot_width;
        u32 slots;
+       u32 tx_mask;
+       u32 rx_mask;
        u32 hck_rate[2];
        u32 sck_rate[2];
        bool hck_dir[2];
@@ -361,21 +363,13 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
        regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
                           ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
 
-       regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
-                          ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
-       regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
-                          ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask));
-
        regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
                           ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
 
-       regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
-                          ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
-       regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
-                          ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
-
        esai_priv->slot_width = slot_width;
        esai_priv->slots = slots;
+       esai_priv->tx_mask = tx_mask;
+       esai_priv->rx_mask = rx_mask;
 
        return 0;
 }
@@ -596,6 +590,7 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
        u8 i, channels = substream->runtime->channels;
        u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
+       u32 mask;
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
@@ -608,15 +603,38 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
                for (i = 0; tx && i < channels; i++)
                        regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
 
+               /*
+                * When set the TE/RE in the end of enablement flow, there
+                * will be channel swap issue for multi data line case.
+                * In order to workaround this issue, we switch the bit
+                * enablement sequence to below sequence
+                * 1) clear the xSMB & xSMA: which is done in probe and
+                *                           stop state.
+                * 2) set TE/RE
+                * 3) set xSMB
+                * 4) set xSMA:  xSMA is the last one in this flow, which
+                *               will trigger esai to start.
+                */
                regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
                                   tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
                                   tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
+               mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
+
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
+                                  ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
+                                  ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
+
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
                                   tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
+                                  ESAI_xSMA_xS_MASK, 0);
+               regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
+                                  ESAI_xSMB_xS_MASK, 0);
 
                /* Disable and reset FIFO */
                regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
@@ -906,6 +924,15 @@ static int fsl_esai_probe(struct platform_device *pdev)
                return ret;
        }
 
+       esai_priv->tx_mask = 0xFFFFFFFF;
+       esai_priv->rx_mask = 0xFFFFFFFF;
+
+       /* Clear the TSMA, TSMB, RSMA, RSMB */
+       regmap_write(esai_priv->regmap, REG_ESAI_TSMA, 0);
+       regmap_write(esai_priv->regmap, REG_ESAI_TSMB, 0);
+       regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0);
+       regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0);
+
        ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
                                              &fsl_esai_dai, 1);
        if (ret) {
index bb12351330e8c0f307b0237ee2e2f1b6b2f9aeec..69bc4848d7876cec544d4ab5067230092953b806 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/string.h>
 #include <sound/simple_card_utils.h>
 
+#define DPCM_SELECTABLE 1
+
 struct graph_priv {
        struct snd_soc_card snd_card;
        struct graph_dai_props {
@@ -440,6 +442,7 @@ static int graph_for_each_link(struct graph_priv *priv,
        struct device_node *codec_port;
        struct device_node *codec_port_old = NULL;
        struct asoc_simple_card_data adata;
+       uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
        int rc, ret;
 
        /* loop for all listed CPU port */
@@ -470,8 +473,9 @@ static int graph_for_each_link(struct graph_priv *priv,
                         * if Codec port has many endpoints,
                         * or has convert-xxx property
                         */
-                       if ((of_get_child_count(codec_port) > 1) ||
-                           adata.convert_rate || adata.convert_channels)
+                       if (dpcm_selectable &&
+                           ((of_get_child_count(codec_port) > 1) ||
+                            adata.convert_rate || adata.convert_channels))
                                ret = func_dpcm(priv, cpu_ep, codec_ep, li,
                                                (codec_port_old == codec_port));
                        /* else normal sound */
@@ -732,7 +736,8 @@ static int graph_remove(struct platform_device *pdev)
 
 static const struct of_device_id graph_of_match[] = {
        { .compatible = "audio-graph-card", },
-       { .compatible = "audio-graph-scu-card", },
+       { .compatible = "audio-graph-scu-card",
+         .data = (void *)DPCM_SELECTABLE },
        {},
 };
 MODULE_DEVICE_TABLE(of, graph_of_match);
index 7147bba45a2a61b0830ed49e6057edb3935c9c03..34de32efc4c4defd14c823b904931f50886b9c69 100644 (file)
@@ -9,12 +9,15 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/string.h>
 #include <sound/simple_card.h>
 #include <sound/soc-dai.h>
 #include <sound/soc.h>
 
+#define DPCM_SELECTABLE 1
+
 struct simple_priv {
        struct snd_soc_card snd_card;
        struct simple_dai_props {
@@ -441,6 +444,7 @@ static int simple_for_each_link(struct simple_priv *priv,
        struct device *dev = simple_priv_to_dev(priv);
        struct device_node *top = dev->of_node;
        struct device_node *node;
+       uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
        bool is_top = 0;
        int ret = 0;
 
@@ -480,8 +484,9 @@ static int simple_for_each_link(struct simple_priv *priv,
                         * if it has many CPUs,
                         * or has convert-xxx property
                         */
-                       if (num > 2 ||
-                           adata.convert_rate || adata.convert_channels)
+                       if (dpcm_selectable &&
+                           (num > 2 ||
+                            adata.convert_rate || adata.convert_channels))
                                ret = func_dpcm(priv, np, codec, li, is_top);
                        /* else normal sound */
                        else
@@ -822,7 +827,8 @@ static int simple_remove(struct platform_device *pdev)
 
 static const struct of_device_id simple_of_match[] = {
        { .compatible = "simple-audio-card", },
-       { .compatible = "simple-scu-audio-card", },
+       { .compatible = "simple-scu-audio-card",
+         .data = (void *)DPCM_SELECTABLE },
        {},
 };
 MODULE_DEVICE_TABLE(of, simple_of_match);
index 08cea5b5cda9fa9f6f617213c1fba5beef4bd489..0e8b1c5eec888b4c988206a04a3a8e1ca65e14aa 100644 (file)
@@ -706,9 +706,17 @@ static int sst_soc_probe(struct snd_soc_component *component)
        return sst_dsp_init_v2_dpcm(component);
 }
 
+static void sst_soc_remove(struct snd_soc_component *component)
+{
+       struct sst_data *drv = dev_get_drvdata(component->dev);
+
+       drv->soc_card = NULL;
+}
+
 static const struct snd_soc_component_driver sst_soc_platform_drv  = {
        .name           = DRV_NAME,
        .probe          = sst_soc_probe,
+       .remove         = sst_soc_remove,
        .ops            = &sst_platform_ops,
        .compr_ops      = &sst_platform_compr_ops,
        .pcm_new        = sst_pcm_new,
index 3263b0495853c2d57e22cb1a90d6cc7515deb952..c0e0844f75b9fe891fc7352c25e957c800f5e4b6 100644 (file)
@@ -43,6 +43,7 @@ struct cht_mc_private {
        struct clk *mclk;
        struct snd_soc_jack jack;
        bool ts3a227e_present;
+       int quirks;
 };
 
 static int platform_clock_control(struct snd_soc_dapm_widget *w,
@@ -54,6 +55,10 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
        struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
        int ret;
 
+       /* See the comment in snd_cht_mc_probe() */
+       if (ctx->quirks & QUIRK_PMC_PLT_CLK_0)
+               return 0;
+
        codec_dai = snd_soc_card_get_codec_dai(card, CHT_CODEC_DAI);
        if (!codec_dai) {
                dev_err(card->dev, "Codec dai not found; Unable to set platform clock\n");
@@ -223,6 +228,10 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
                        "jack detection gpios not added, error %d\n", ret);
        }
 
+       /* See the comment in snd_cht_mc_probe() */
+       if (ctx->quirks & QUIRK_PMC_PLT_CLK_0)
+               return 0;
+
        /*
         * The firmware might enable the clock at
         * boot (this information may or may not
@@ -423,16 +432,15 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
        const char *mclk_name;
        struct snd_soc_acpi_mach *mach;
        const char *platform_name;
-       int quirks = 0;
-
-       dmi_id = dmi_first_match(cht_max98090_quirk_table);
-       if (dmi_id)
-               quirks = (unsigned long)dmi_id->driver_data;
 
        drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
        if (!drv)
                return -ENOMEM;
 
+       dmi_id = dmi_first_match(cht_max98090_quirk_table);
+       if (dmi_id)
+               drv->quirks = (unsigned long)dmi_id->driver_data;
+
        drv->ts3a227e_present = acpi_dev_found("104C227E");
        if (!drv->ts3a227e_present) {
                /* no need probe TI jack detection chip */
@@ -458,7 +466,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
        snd_soc_card_cht.dev = &pdev->dev;
        snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
 
-       if (quirks & QUIRK_PMC_PLT_CLK_0)
+       if (drv->quirks & QUIRK_PMC_PLT_CLK_0)
                mclk_name = "pmc_plt_clk_0";
        else
                mclk_name = "pmc_plt_clk_3";
@@ -471,6 +479,21 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
                return PTR_ERR(drv->mclk);
        }
 
+       /*
+        * Boards which have the MAX98090's clk connected to clk_0 do not seem
+        * to like it if we muck with the clock. If we disable the clock when
+        * it is unused we get "max98090 i2c-193C9890:00: PLL unlocked" errors
+        * and the PLL never seems to lock again.
+        * So for these boards we enable it here once and leave it at that.
+        */
+       if (drv->quirks & QUIRK_PMC_PLT_CLK_0) {
+               ret_val = clk_prepare_enable(drv->mclk);
+               if (ret_val < 0) {
+                       dev_err(&pdev->dev, "MCLK enable error: %d\n", ret_val);
+                       return ret_val;
+               }
+       }
+
        ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
        if (ret_val) {
                dev_err(&pdev->dev,
@@ -481,11 +504,23 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
        return ret_val;
 }
 
+static int snd_cht_mc_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct cht_mc_private *ctx = snd_soc_card_get_drvdata(card);
+
+       if (ctx->quirks & QUIRK_PMC_PLT_CLK_0)
+               clk_disable_unprepare(ctx->mclk);
+
+       return 0;
+}
+
 static struct platform_driver snd_cht_mc_driver = {
        .driver = {
                .name = "cht-bsw-max98090",
        },
        .probe = snd_cht_mc_probe,
+       .remove = snd_cht_mc_remove,
 };
 
 module_platform_driver(snd_cht_mc_driver)
index 7044d8c2b187375cd6fd44b3342eedf4b37fd8d1..879f14257a3ea4c8fae5eaa683c365e519ecfc17 100644 (file)
@@ -405,7 +405,7 @@ static const struct snd_pcm_hw_constraint_list constraints_dmic_channels = {
 };
 
 static const unsigned int dmic_2ch[] = {
-       4,
+       2,
 };
 
 static const struct snd_pcm_hw_constraint_list constraints_dmic_2ch = {
index 28c4806b196a2fc3505ce88e298b834cf64e1c56..4bf70b4429f03075b07d877c67f6003d15d5336d 100644 (file)
@@ -483,6 +483,7 @@ static void skl_set_base_module_format(struct skl_sst *ctx,
        base_cfg->audio_fmt.bit_depth = format->bit_depth;
        base_cfg->audio_fmt.valid_bit_depth = format->valid_bit_depth;
        base_cfg->audio_fmt.ch_cfg = format->ch_cfg;
+       base_cfg->audio_fmt.sample_type = format->sample_type;
 
        dev_dbg(ctx->dev, "bit_depth=%x valid_bd=%x ch_config=%x\n",
                        format->bit_depth, format->valid_bit_depth,
index 1ae83f4ccc3615bfa42e28d08d43f27870526ded..9735e24122514f81d9ee88002fdbdd32ade65e4e 100644 (file)
@@ -181,6 +181,7 @@ int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params)
        struct hdac_stream *hstream;
        struct hdac_ext_stream *stream;
        struct hdac_ext_link *link;
+       unsigned char stream_tag;
 
        hstream = snd_hdac_get_stream(bus, params->stream,
                                        params->link_dma_id + 1);
@@ -199,10 +200,13 @@ int skl_pcm_link_dma_prepare(struct device *dev, struct skl_pipe_params *params)
 
        snd_hdac_ext_link_stream_setup(stream, format_val);
 
-       list_for_each_entry(link, &bus->hlink_list, list) {
-               if (link->index == params->link_index)
-                       snd_hdac_ext_link_set_stream_id(link,
-                                       hstream->stream_tag);
+       stream_tag = hstream->stream_tag;
+       if (stream->hstream.direction == SNDRV_PCM_STREAM_PLAYBACK) {
+               list_for_each_entry(link, &bus->hlink_list, list) {
+                       if (link->index == params->link_index)
+                               snd_hdac_ext_link_set_stream_id(link,
+                                                               stream_tag);
+               }
        }
 
        stream->link_prepared = 1;
@@ -645,6 +649,7 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
        struct hdac_ext_stream *link_dev =
                                snd_soc_dai_get_dma_data(dai, substream);
        struct hdac_ext_link *link;
+       unsigned char stream_tag;
 
        dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
 
@@ -654,7 +659,11 @@ static int skl_link_hw_free(struct snd_pcm_substream *substream,
        if (!link)
                return -EINVAL;
 
-       snd_hdac_ext_link_clear_stream_id(link, hdac_stream(link_dev)->stream_tag);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               stream_tag = hdac_stream(link_dev)->stream_tag;
+               snd_hdac_ext_link_clear_stream_id(link, stream_tag);
+       }
+
        snd_hdac_ext_stream_release(link_dev, HDAC_EXT_STREAM_TYPE_LINK);
        return 0;
 }
@@ -1453,13 +1462,20 @@ static int skl_platform_soc_probe(struct snd_soc_component *component)
        return 0;
 }
 
+static void skl_pcm_remove(struct snd_soc_component *component)
+{
+       /* remove topology */
+       snd_soc_tplg_component_remove(component, SND_SOC_TPLG_INDEX_ALL);
+}
+
 static const struct snd_soc_component_driver skl_component  = {
        .name           = "pcm",
        .probe          = skl_platform_soc_probe,
+       .remove         = skl_pcm_remove,
        .ops            = &skl_platform_ops,
        .pcm_new        = skl_pcm_new,
        .pcm_free       = skl_pcm_free,
-       .ignore_module_refcount = 1, /* do not increase the refcount in core */
+       .module_get_upon_open = 1, /* increment refcount when a pcm is opened */
 };
 
 int skl_platform_register(struct device *dev)
index 1b8bcdaf02d116cbc124aac6597f3a8a501b468d..9a163d7064d174ff1e4142cb09b31adeaa9c6f59 100644 (file)
@@ -49,6 +49,7 @@ enum bt_sco_state {
        BT_SCO_STATE_IDLE,
        BT_SCO_STATE_RUNNING,
        BT_SCO_STATE_ENDING,
+       BT_SCO_STATE_LOOPBACK,
 };
 
 enum bt_sco_direct {
@@ -486,7 +487,8 @@ static irqreturn_t mtk_btcvsd_snd_irq_handler(int irq_id, void *dev)
        if (bt->rx->state != BT_SCO_STATE_RUNNING &&
            bt->rx->state != BT_SCO_STATE_ENDING &&
            bt->tx->state != BT_SCO_STATE_RUNNING &&
-           bt->tx->state != BT_SCO_STATE_ENDING) {
+           bt->tx->state != BT_SCO_STATE_ENDING &&
+           bt->tx->state != BT_SCO_STATE_LOOPBACK) {
                dev_warn(bt->dev, "%s(), in idle state: rx->state: %d, tx->state: %d\n",
                         __func__, bt->rx->state, bt->tx->state);
                goto irq_handler_exit;
@@ -512,6 +514,42 @@ static irqreturn_t mtk_btcvsd_snd_irq_handler(int irq_id, void *dev)
        buf_cnt_tx = btsco_packet_info[packet_type][2];
        buf_cnt_rx = btsco_packet_info[packet_type][3];
 
+       if (bt->tx->state == BT_SCO_STATE_LOOPBACK) {
+               u8 *src, *dst;
+               unsigned long connsys_addr_rx, ap_addr_rx;
+               unsigned long connsys_addr_tx, ap_addr_tx;
+
+               connsys_addr_rx = *bt->bt_reg_pkt_r;
+               ap_addr_rx = (unsigned long)bt->bt_sram_bank2_base +
+                            (connsys_addr_rx & 0xFFFF);
+
+               connsys_addr_tx = *bt->bt_reg_pkt_w;
+               ap_addr_tx = (unsigned long)bt->bt_sram_bank2_base +
+                            (connsys_addr_tx & 0xFFFF);
+
+               if (connsys_addr_tx == 0xdeadfeed ||
+                   connsys_addr_rx == 0xdeadfeed) {
+                       /* bt return 0xdeadfeed if read reg during bt sleep */
+                       dev_warn(bt->dev, "%s(), connsys_addr_tx == 0xdeadfeed\n",
+                                __func__);
+                       goto irq_handler_exit;
+               }
+
+               src = (u8 *)ap_addr_rx;
+               dst = (u8 *)ap_addr_tx;
+
+               mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_BT2ARM, src,
+                                            bt->tx->temp_packet_buf,
+                                            packet_length,
+                                            packet_num);
+               mtk_btcvsd_snd_data_transfer(BT_SCO_DIRECT_ARM2BT,
+                                            bt->tx->temp_packet_buf, dst,
+                                            packet_length,
+                                            packet_num);
+               bt->rx->rw_cnt++;
+               bt->tx->rw_cnt++;
+       }
+
        if (bt->rx->state == BT_SCO_STATE_RUNNING ||
            bt->rx->state == BT_SCO_STATE_ENDING) {
                if (bt->rx->xrun) {
@@ -1067,6 +1105,33 @@ static int btcvsd_band_set(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int btcvsd_loopback_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+       struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
+       bool lpbk_en = bt->tx->state == BT_SCO_STATE_LOOPBACK;
+
+       ucontrol->value.integer.value[0] = lpbk_en;
+       return 0;
+}
+
+static int btcvsd_loopback_set(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
+       struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(cmpnt);
+
+       if (ucontrol->value.integer.value[0]) {
+               mtk_btcvsd_snd_set_state(bt, bt->tx, BT_SCO_STATE_LOOPBACK);
+               mtk_btcvsd_snd_set_state(bt, bt->rx, BT_SCO_STATE_LOOPBACK);
+       } else {
+               mtk_btcvsd_snd_set_state(bt, bt->tx, BT_SCO_STATE_RUNNING);
+               mtk_btcvsd_snd_set_state(bt, bt->rx, BT_SCO_STATE_RUNNING);
+       }
+       return 0;
+}
+
 static int btcvsd_tx_mute_get(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol)
 {
@@ -1202,6 +1267,8 @@ static int btcvsd_tx_timestamp_get(struct snd_kcontrol *kcontrol,
 static const struct snd_kcontrol_new mtk_btcvsd_snd_controls[] = {
        SOC_ENUM_EXT("BTCVSD Band", btcvsd_enum[0],
                     btcvsd_band_get, btcvsd_band_set),
+       SOC_SINGLE_BOOL_EXT("BTCVSD Loopback Switch", 0,
+                           btcvsd_loopback_get, btcvsd_loopback_set),
        SOC_SINGLE_BOOL_EXT("BTCVSD Tx Mute Switch", 0,
                            btcvsd_tx_mute_get, btcvsd_tx_mute_set),
        SOC_SINGLE_BOOL_EXT("BTCVSD Tx Irq Received Switch", 0,
index f523ad103acc4cc9ce2bd745a24aa6f5988cc7bf..48e81c5d52fc27959d8b8215a1903764bf302fdd 100644 (file)
@@ -605,6 +605,10 @@ void mt8183_mck_disable(struct mtk_base_afe *afe, int mck_id)
        int m_sel_id = mck_div[mck_id].m_sel_id;
        int div_clk_id = mck_div[mck_id].div_clk_id;
 
+       /* i2s5 mck not support */
+       if (mck_id == MT8183_I2S5_MCK)
+               return;
+
        clk_disable_unprepare(afe_priv->clk[div_clk_id]);
        if (m_sel_id >= 0)
                clk_disable_unprepare(afe_priv->clk[m_sel_id]);
index 400e29edb1c9c4db4d3afbbad2b6a41952100a22..d0b403a0e27b830bc480935fa75df123c3375302 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "rockchip_pdm.h"
 
-#define PDM_DMA_BURST_SIZE     (16) /* size * width: 16*4 = 64 bytes */
+#define PDM_DMA_BURST_SIZE     (8) /* size * width: 8*4 = 32 bytes */
 
 struct rk_pdm_dev {
        struct device *dev;
@@ -208,7 +208,9 @@ static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai,
                return -EINVAL;
        }
 
+       pm_runtime_get_sync(cpu_dai->dev);
        regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, mask, val);
+       pm_runtime_put(cpu_dai->dev);
 
        return 0;
 }
index 4231001226f494da587a7096d27c001802fcdf9c..ab471d550d17adf682d0c5c26607e6de85885791 100644 (file)
@@ -1130,11 +1130,11 @@ static const struct snd_soc_dapm_widget samsung_i2s_widgets[] = {
 };
 
 static const struct snd_soc_dapm_route samsung_i2s_dapm_routes[] = {
-       { "Playback Mixer", NULL, "Primary" },
-       { "Playback Mixer", NULL, "Secondary" },
+       { "Playback Mixer", NULL, "Primary Playback" },
+       { "Playback Mixer", NULL, "Secondary Playback" },
 
        { "Mixer DAI TX", NULL, "Playback Mixer" },
-       { "Playback Mixer", NULL, "Mixer DAI RX" },
+       { "Primary Capture", NULL, "Mixer DAI RX" },
 };
 
 static const struct snd_soc_component_driver samsung_i2s_component = {
@@ -1155,7 +1155,8 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv,
                          int num_dais)
 {
        static const char *dai_names[] = { "samsung-i2s", "samsung-i2s-sec" };
-       static const char *stream_names[] = { "Primary", "Secondary" };
+       static const char *stream_names[] = { "Primary Playback",
+                                             "Secondary Playback" };
        struct snd_soc_dai_driver *dai_drv;
        struct i2s_dai *dai;
        int i;
@@ -1201,6 +1202,7 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv,
        dai_drv->capture.channels_max = 2;
        dai_drv->capture.rates = i2s_dai_data->pcm_rates;
        dai_drv->capture.formats = SAMSUNG_I2S_FMTS;
+       dai_drv->capture.stream_name = "Primary Capture";
 
        return 0;
 }
index 694512f980fdc207577fcd2a5a59d7a6484bfdd0..1dc54c4206f0adc1ed5250c2d9bf3f44f5c7adf2 100644 (file)
@@ -91,11 +91,11 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream,
                return ret;
 
        /*
-        *  We add 1 to the rclk_freq value in order to avoid too low clock
+        *  We add 2 to the rclk_freq value in order to avoid too low clock
         *  frequency values due to the EPLL output frequency not being exact
         *  multiple of the audio sampling rate.
         */
-       rclk_freq = params_rate(params) * rfs + 1;
+       rclk_freq = params_rate(params) * rfs + 2;
 
        ret = clk_set_rate(priv->sclk_i2s, rclk_freq);
        if (ret < 0)
index 022996d2db1301d16619ef8ead029a19fce1b75b..4fe83e611c01e0d983e5af5c79594d4c858ec610 100644 (file)
@@ -110,6 +110,8 @@ static const struct of_device_id rsnd_of_match[] = {
        { .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 },
        { .compatible = "renesas,rcar_sound-gen2", .data = (void *)RSND_GEN2 },
        { .compatible = "renesas,rcar_sound-gen3", .data = (void *)RSND_GEN3 },
+       /* Special Handling */
+       { .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) },
        {},
 };
 MODULE_DEVICE_TABLE(of, rsnd_of_match);
index 90625c57847b51281c5b38f81f8ab062a70a3785..0e6ef4e1840021d00c94089ca8522c956d4bb813 100644 (file)
@@ -607,6 +607,8 @@ struct rsnd_priv {
 #define RSND_GEN1      (1 << 0)
 #define RSND_GEN2      (2 << 0)
 #define RSND_GEN3      (3 << 0)
+#define RSND_SOC_MASK  (0xFF << 4)
+#define RSND_SOC_E     (1 << 4) /* E1/E2/E3 */
 
        /*
         * below value will be filled on rsnd_gen_probe()
@@ -679,6 +681,9 @@ struct rsnd_priv {
 #define rsnd_is_gen1(priv)     (((priv)->flags & RSND_GEN_MASK) == RSND_GEN1)
 #define rsnd_is_gen2(priv)     (((priv)->flags & RSND_GEN_MASK) == RSND_GEN2)
 #define rsnd_is_gen3(priv)     (((priv)->flags & RSND_GEN_MASK) == RSND_GEN3)
+#define rsnd_is_e3(priv)       (((priv)->flags & \
+                                       (RSND_GEN_MASK | RSND_SOC_MASK)) == \
+                                       (RSND_GEN3 | RSND_SOC_E))
 
 #define rsnd_flags_has(p, f) ((p)->flags & (f))
 #define rsnd_flags_set(p, f) ((p)->flags |= (f))
index db81e066b92ef98902d4433e939b25ab0a635625..585ffba0244b9f568685ed52323d31f7f9fcb3b4 100644 (file)
@@ -14,7 +14,6 @@
  */
 
 #include "rsnd.h"
-#include <linux/sys_soc.h>
 
 #define SRC_NAME "src"
 
@@ -135,7 +134,7 @@ unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
        return rate;
 }
 
-const static u32 bsdsr_table_pattern1[] = {
+static const u32 bsdsr_table_pattern1[] = {
        0x01800000, /* 6 - 1/6 */
        0x01000000, /* 6 - 1/4 */
        0x00c00000, /* 6 - 1/3 */
@@ -144,7 +143,7 @@ const static u32 bsdsr_table_pattern1[] = {
        0x00400000, /* 6 - 1   */
 };
 
-const static u32 bsdsr_table_pattern2[] = {
+static const u32 bsdsr_table_pattern2[] = {
        0x02400000, /* 6 - 1/6 */
        0x01800000, /* 6 - 1/4 */
        0x01200000, /* 6 - 1/3 */
@@ -153,7 +152,7 @@ const static u32 bsdsr_table_pattern2[] = {
        0x00600000, /* 6 - 1   */
 };
 
-const static u32 bsisr_table[] = {
+static const u32 bsisr_table[] = {
        0x00100060, /* 6 - 1/6 */
        0x00100040, /* 6 - 1/4 */
        0x00100030, /* 6 - 1/3 */
@@ -162,7 +161,7 @@ const static u32 bsisr_table[] = {
        0x00100020, /* 6 - 1   */
 };
 
-const static u32 chan288888[] = {
+static const u32 chan288888[] = {
        0x00000006, /* 1 to 2 */
        0x000001fe, /* 1 to 8 */
        0x000001fe, /* 1 to 8 */
@@ -171,7 +170,7 @@ const static u32 chan288888[] = {
        0x000001fe, /* 1 to 8 */
 };
 
-const static u32 chan244888[] = {
+static const u32 chan244888[] = {
        0x00000006, /* 1 to 2 */
        0x0000001e, /* 1 to 4 */
        0x0000001e, /* 1 to 4 */
@@ -180,7 +179,7 @@ const static u32 chan244888[] = {
        0x000001fe, /* 1 to 8 */
 };
 
-const static u32 chan222222[] = {
+static const u32 chan222222[] = {
        0x00000006, /* 1 to 2 */
        0x00000006, /* 1 to 2 */
        0x00000006, /* 1 to 2 */
@@ -189,18 +188,12 @@ const static u32 chan222222[] = {
        0x00000006, /* 1 to 2 */
 };
 
-static const struct soc_device_attribute ov_soc[] = {
-       { .soc_id = "r8a77990" }, /* E3 */
-       { /* sentinel */ }
-};
-
 static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
                                      struct rsnd_mod *mod)
 {
        struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
        struct device *dev = rsnd_priv_to_dev(priv);
        struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
-       const struct soc_device_attribute *soc = soc_device_match(ov_soc);
        int is_play = rsnd_io_is_play(io);
        int use_src = 0;
        u32 fin, fout;
@@ -307,7 +300,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io,
        /*
         * E3 need to overwrite
         */
-       if (soc)
+       if (rsnd_is_e3(priv))
                switch (rsnd_mod_id(mod)) {
                case 0:
                case 4:
index 93d316d5bf8e3cac63d9955cfa9e0a6b7bbbb9d0..46e3ab0fced47342be93c32f6509a79829967281 100644 (file)
@@ -947,7 +947,7 @@ static void soc_cleanup_component(struct snd_soc_component *component)
        snd_soc_dapm_free(snd_soc_component_get_dapm(component));
        soc_cleanup_component_debugfs(component);
        component->card = NULL;
-       if (!component->driver->ignore_module_refcount)
+       if (!component->driver->module_get_upon_open)
                module_put(component->dev->driver->owner);
 }
 
@@ -1381,7 +1381,7 @@ static int soc_probe_component(struct snd_soc_card *card,
                return 0;
        }
 
-       if (!component->driver->ignore_module_refcount &&
+       if (!component->driver->module_get_upon_open &&
            !try_module_get(component->dev->driver->owner))
                return -ENODEV;
 
@@ -2797,6 +2797,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
 
                ret = soc_init_dai_link(card, link);
                if (ret) {
+                       soc_cleanup_platform(card);
                        dev_err(card->dev, "ASoC: failed to init link %s\n",
                                link->name);
                        mutex_unlock(&client_mutex);
@@ -2819,6 +2820,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
        card->instantiated = 0;
        mutex_init(&card->mutex);
        mutex_init(&card->dapm_mutex);
+       spin_lock_init(&card->dpcm_lock);
 
        return snd_soc_bind_card(card);
 }
index 1ec06ef6d161606922b1a3f8d16e2e685129db62..0382a47b30bd8182d40340c839268233cd47e21b 100644 (file)
@@ -3650,6 +3650,13 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
        case snd_soc_dapm_dac:
        case snd_soc_dapm_aif_in:
        case snd_soc_dapm_pga:
+       case snd_soc_dapm_buffer:
+       case snd_soc_dapm_scheduler:
+       case snd_soc_dapm_effect:
+       case snd_soc_dapm_src:
+       case snd_soc_dapm_asrc:
+       case snd_soc_dapm_encoder:
+       case snd_soc_dapm_decoder:
        case snd_soc_dapm_out_drv:
        case snd_soc_dapm_micbias:
        case snd_soc_dapm_line:
@@ -3957,6 +3964,10 @@ snd_soc_dapm_free_kcontrol(struct snd_soc_card *card,
        int count;
 
        devm_kfree(card->dev, (void *)*private_value);
+
+       if (!w_param_text)
+               return;
+
        for (count = 0 ; count < num_params; count++)
                devm_kfree(card->dev, (void *)w_param_text[count]);
        devm_kfree(card->dev, w_param_text);
index 0d5ec68a1e50869e00ea6abb13b229c79b903329..be80a12fba27cc381b0438a95bb4987c6843cb39 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/export.h>
@@ -463,6 +464,9 @@ static int soc_pcm_components_close(struct snd_pcm_substream *substream,
                        continue;
 
                component->driver->ops->close(substream);
+
+               if (component->driver->module_get_upon_open)
+                       module_put(component->dev->driver->owner);
        }
 
        return 0;
@@ -513,6 +517,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
                    !component->driver->ops->open)
                        continue;
 
+               if (component->driver->module_get_upon_open &&
+                   !try_module_get(component->dev->driver->owner)) {
+                       ret = -ENODEV;
+                       goto module_err;
+               }
+
                ret = component->driver->ops->open(substream);
                if (ret < 0) {
                        dev_err(component->dev,
@@ -628,7 +638,7 @@ codec_dai_err:
 
 component_err:
        soc_pcm_components_close(substream, component);
-
+module_err:
        if (cpu_dai->driver->ops->shutdown)
                cpu_dai->driver->ops->shutdown(substream, cpu_dai);
 out:
@@ -954,10 +964,13 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
                codec_params = *params;
 
                /* fixup params based on TDM slot masks */
-               if (codec_dai->tx_mask)
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+                   codec_dai->tx_mask)
                        soc_pcm_codec_params_fixup(&codec_params,
                                                   codec_dai->tx_mask);
-               if (codec_dai->rx_mask)
+
+               if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
+                   codec_dai->rx_mask)
                        soc_pcm_codec_params_fixup(&codec_params,
                                                   codec_dai->rx_mask);
 
@@ -1213,6 +1226,7 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
                struct snd_soc_pcm_runtime *be, int stream)
 {
        struct snd_soc_dpcm *dpcm;
+       unsigned long flags;
 
        /* only add new dpcms */
        for_each_dpcm_be(fe, stream, dpcm) {
@@ -1228,8 +1242,10 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
        dpcm->fe = fe;
        be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
        dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW;
+       spin_lock_irqsave(&fe->card->dpcm_lock, flags);
        list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
        list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
+       spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
 
        dev_dbg(fe->dev, "connected new DPCM %s path %s %s %s\n",
                        stream ? "capture" : "playback",  fe->dai_link->name,
@@ -1275,6 +1291,7 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
 void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
 {
        struct snd_soc_dpcm *dpcm, *d;
+       unsigned long flags;
 
        for_each_dpcm_be_safe(fe, stream, dpcm, d) {
                dev_dbg(fe->dev, "ASoC: BE %s disconnect check for %s\n",
@@ -1294,8 +1311,10 @@ void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
 #ifdef CONFIG_DEBUG_FS
                debugfs_remove(dpcm->debugfs_state);
 #endif
+               spin_lock_irqsave(&fe->card->dpcm_lock, flags);
                list_del(&dpcm->list_be);
                list_del(&dpcm->list_fe);
+               spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
                kfree(dpcm);
        }
 }
@@ -1547,10 +1566,13 @@ int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
 void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
 {
        struct snd_soc_dpcm *dpcm;
+       unsigned long flags;
 
+       spin_lock_irqsave(&fe->card->dpcm_lock, flags);
        for_each_dpcm_be(fe, stream, dpcm)
                dpcm->be->dpcm[stream].runtime_update =
                                                SND_SOC_DPCM_UPDATE_NO;
+       spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
 }
 
 static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe,
@@ -1899,10 +1921,15 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream,
                struct snd_soc_pcm_runtime *be = dpcm->be;
                struct snd_pcm_substream *be_substream =
                        snd_soc_dpcm_get_substream(be, stream);
-               struct snd_soc_pcm_runtime *rtd = be_substream->private_data;
+               struct snd_soc_pcm_runtime *rtd;
                struct snd_soc_dai *codec_dai;
                int i;
 
+               /* A backend may not have the requested substream */
+               if (!be_substream)
+                       continue;
+
+               rtd = be_substream->private_data;
                if (rtd->dai_link->be_hw_params_fixup)
                        continue;
 
@@ -2571,6 +2598,7 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
        struct snd_soc_dpcm *dpcm;
        enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
        int ret;
+       unsigned long flags;
 
        dev_dbg(fe->dev, "ASoC: runtime %s open on FE %s\n",
                        stream ? "capture" : "playback", fe->dai_link->name);
@@ -2640,11 +2668,13 @@ close:
        dpcm_be_dai_shutdown(fe, stream);
 disconnect:
        /* disconnect any non started BEs */
+       spin_lock_irqsave(&fe->card->dpcm_lock, flags);
        for_each_dpcm_be(fe, stream, dpcm) {
                struct snd_soc_pcm_runtime *be = dpcm->be;
                if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
                                dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
        }
+       spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
 
        return ret;
 }
@@ -3221,7 +3251,10 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
 {
        struct snd_soc_dpcm *dpcm;
        int state;
+       int ret = 1;
+       unsigned long flags;
 
+       spin_lock_irqsave(&fe->card->dpcm_lock, flags);
        for_each_dpcm_fe(be, stream, dpcm) {
 
                if (dpcm->fe == fe)
@@ -3230,12 +3263,15 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
                state = dpcm->fe->dpcm[stream].state;
                if (state == SND_SOC_DPCM_STATE_START ||
                        state == SND_SOC_DPCM_STATE_PAUSED ||
-                       state == SND_SOC_DPCM_STATE_SUSPEND)
-                       return 0;
+                       state == SND_SOC_DPCM_STATE_SUSPEND) {
+                       ret = 0;
+                       break;
+               }
        }
+       spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
 
        /* it's safe to free/stop this BE DAI */
-       return 1;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop);
 
@@ -3248,7 +3284,10 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
 {
        struct snd_soc_dpcm *dpcm;
        int state;
+       int ret = 1;
+       unsigned long flags;
 
+       spin_lock_irqsave(&fe->card->dpcm_lock, flags);
        for_each_dpcm_fe(be, stream, dpcm) {
 
                if (dpcm->fe == fe)
@@ -3258,12 +3297,15 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
                if (state == SND_SOC_DPCM_STATE_START ||
                        state == SND_SOC_DPCM_STATE_PAUSED ||
                        state == SND_SOC_DPCM_STATE_SUSPEND ||
-                       state == SND_SOC_DPCM_STATE_PREPARE)
-                       return 0;
+                       state == SND_SOC_DPCM_STATE_PREPARE) {
+                       ret = 0;
+                       break;
+               }
        }
+       spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
 
        /* it's safe to change hw_params */
-       return 1;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
 
@@ -3302,6 +3344,7 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
        struct snd_pcm_hw_params *params = &fe->dpcm[stream].hw_params;
        struct snd_soc_dpcm *dpcm;
        ssize_t offset = 0;
+       unsigned long flags;
 
        /* FE state */
        offset += snprintf(buf + offset, size - offset,
@@ -3329,6 +3372,7 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
                goto out;
        }
 
+       spin_lock_irqsave(&fe->card->dpcm_lock, flags);
        for_each_dpcm_be(fe, stream, dpcm) {
                struct snd_soc_pcm_runtime *be = dpcm->be;
                params = &dpcm->hw_params;
@@ -3349,7 +3393,7 @@ static ssize_t dpcm_show_state(struct snd_soc_pcm_runtime *fe,
                                params_channels(params),
                                params_rate(params));
        }
-
+       spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
 out:
        return offset;
 }
index 25fca7055464a894e5e260bf872de8c410136f56..96852d25061936e1f72b9c929686a1a740bdc6a8 100644 (file)
@@ -482,10 +482,11 @@ static void remove_widget(struct snd_soc_component *comp,
 
                        snd_ctl_remove(card, kcontrol);
 
-                       kfree(dobj->control.dvalues);
+                       /* free enum kcontrol's dvalues and dtexts */
+                       kfree(se->dobj.control.dvalues);
                        for (j = 0; j < se->items; j++)
-                               kfree(dobj->control.dtexts[j]);
-                       kfree(dobj->control.dtexts);
+                               kfree(se->dobj.control.dtexts[j]);
+                       kfree(se->dobj.control.dtexts);
 
                        kfree(se);
                        kfree(w->kcontrol_news[i].name);
index 47901983a6ff88706dd847376a42d5aeb2c3a4c6..78bed97347136974d3da6b8a09d3465eaafffbdd 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/clk.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
@@ -37,6 +38,8 @@ struct stm32_adfsdm_priv {
        /* PCM buffer */
        unsigned char *pcm_buff;
        unsigned int pos;
+
+       struct mutex lock; /* protect against race condition on iio state */
 };
 
 static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = {
@@ -62,10 +65,12 @@ static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream,
 {
        struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
 
+       mutex_lock(&priv->lock);
        if (priv->iio_active) {
                iio_channel_stop_all_cb(priv->iio_cb);
                priv->iio_active = false;
        }
+       mutex_unlock(&priv->lock);
 }
 
 static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
@@ -74,13 +79,19 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
        struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
        int ret;
 
+       mutex_lock(&priv->lock);
+       if (priv->iio_active) {
+               iio_channel_stop_all_cb(priv->iio_cb);
+               priv->iio_active = false;
+       }
+
        ret = iio_write_channel_attribute(priv->iio_ch,
                                          substream->runtime->rate, 0,
                                          IIO_CHAN_INFO_SAMP_FREQ);
        if (ret < 0) {
                dev_err(dai->dev, "%s: Failed to set %d sampling rate\n",
                        __func__, substream->runtime->rate);
-               return ret;
+               goto out;
        }
 
        if (!priv->iio_active) {
@@ -92,6 +103,9 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
                                __func__, ret);
        }
 
+out:
+       mutex_unlock(&priv->lock);
+
        return ret;
 }
 
@@ -291,6 +305,7 @@ MODULE_DEVICE_TABLE(of, stm32_adfsdm_of_match);
 static int stm32_adfsdm_probe(struct platform_device *pdev)
 {
        struct stm32_adfsdm_priv *priv;
+       struct snd_soc_component *component;
        int ret;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -299,6 +314,7 @@ static int stm32_adfsdm_probe(struct platform_device *pdev)
 
        priv->dev = &pdev->dev;
        priv->dai_drv = stm32_adfsdm_dai;
+       mutex_init(&priv->lock);
 
        dev_set_drvdata(&pdev->dev, priv);
 
@@ -317,9 +333,15 @@ static int stm32_adfsdm_probe(struct platform_device *pdev)
        if (IS_ERR(priv->iio_cb))
                return PTR_ERR(priv->iio_cb);
 
-       ret = devm_snd_soc_register_component(&pdev->dev,
-                                             &stm32_adfsdm_soc_platform,
-                                             NULL, 0);
+       component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL);
+       if (!component)
+               return -ENOMEM;
+#ifdef CONFIG_DEBUG_FS
+       component->debugfs_prefix = "pcm";
+#endif
+
+       ret = snd_soc_add_component(&pdev->dev, component,
+                                   &stm32_adfsdm_soc_platform, NULL, 0);
        if (ret < 0)
                dev_err(&pdev->dev, "%s: Failed to register PCM platform\n",
                        __func__);
@@ -327,12 +349,20 @@ static int stm32_adfsdm_probe(struct platform_device *pdev)
        return ret;
 }
 
+static int stm32_adfsdm_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_component(&pdev->dev);
+
+       return 0;
+}
+
 static struct platform_driver stm32_adfsdm_driver = {
        .driver = {
                   .name = STM32_ADFSDM_DRV_NAME,
                   .of_match_table = stm32_adfsdm_of_match,
                   },
        .probe = stm32_adfsdm_probe,
+       .remove = stm32_adfsdm_remove,
 };
 
 module_platform_driver(stm32_adfsdm_driver);
index 47c334de6b0966a4e5fd4a589e8ce6fd757c1fce..8968458eec62d6b796e2eaae3df508e03c375e6d 100644 (file)
@@ -281,7 +281,6 @@ static bool stm32_i2s_readable_reg(struct device *dev, unsigned int reg)
        case STM32_I2S_CFG2_REG:
        case STM32_I2S_IER_REG:
        case STM32_I2S_SR_REG:
-       case STM32_I2S_TXDR_REG:
        case STM32_I2S_RXDR_REG:
        case STM32_I2S_CGFR_REG:
                return true;
@@ -293,7 +292,7 @@ static bool stm32_i2s_readable_reg(struct device *dev, unsigned int reg)
 static bool stm32_i2s_volatile_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
-       case STM32_I2S_TXDR_REG:
+       case STM32_I2S_SR_REG:
        case STM32_I2S_RXDR_REG:
                return true;
        default:
index 14c9591aae4260d94f6d19231aaa56ad436e5469..d68d62f12df56098214a94de25758598c9f7502f 100644 (file)
@@ -105,6 +105,7 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,
        if (!pdev) {
                dev_err(&sai_client->pdev->dev,
                        "Device not found for node %pOFn\n", np_provider);
+               of_node_put(np_provider);
                return -ENODEV;
        }
 
@@ -113,19 +114,20 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,
                dev_err(&sai_client->pdev->dev,
                        "SAI sync provider data not found\n");
                ret = -EINVAL;
-               goto out_put_dev;
+               goto error;
        }
 
        /* Configure sync client */
        ret = stm32_sai_sync_conf_client(sai_client, synci);
        if (ret < 0)
-               goto out_put_dev;
+               goto error;
 
        /* Configure sync provider */
        ret = stm32_sai_sync_conf_provider(sai_provider, synco);
 
-out_put_dev:
+error:
        put_device(&pdev->dev);
+       of_node_put(np_provider);
        return ret;
 }
 
index f9297228c41ce4412f86d9ba7010ba714d44d345..d7045aa520de56eb42d108a14e92aee810d15f08 100644 (file)
@@ -70,6 +70,7 @@
 #define SAI_IEC60958_STATUS_BYTES      24
 
 #define SAI_MCLK_NAME_LEN              32
+#define SAI_RATE_11K                   11025
 
 /**
  * struct stm32_sai_sub_data - private data of SAI sub block (block A or B)
  * @slot_mask: rx or tx active slots mask. set at init or at runtime
  * @data_size: PCM data width. corresponds to PCM substream width.
  * @spdif_frm_cnt: S/PDIF playback frame counter
- * @snd_aes_iec958: iec958 data
+ * @iec958: iec958 data
  * @ctrl_lock: control lock
+ * @irq_lock: prevent race condition with IRQ
  */
 struct stm32_sai_sub_data {
        struct platform_device *pdev;
@@ -133,6 +135,7 @@ struct stm32_sai_sub_data {
        unsigned int spdif_frm_cnt;
        struct snd_aes_iec958 iec958;
        struct mutex ctrl_lock; /* protect resources accessed by controls */
+       spinlock_t irq_lock; /* used to prevent race condition with IRQ */
 };
 
 enum stm32_sai_fifo_th {
@@ -307,6 +310,25 @@ static int stm32_sai_set_clk_div(struct stm32_sai_sub_data *sai,
        return ret;
 }
 
+static int stm32_sai_set_parent_clock(struct stm32_sai_sub_data *sai,
+                                     unsigned int rate)
+{
+       struct platform_device *pdev = sai->pdev;
+       struct clk *parent_clk = sai->pdata->clk_x8k;
+       int ret;
+
+       if (!(rate % SAI_RATE_11K))
+               parent_clk = sai->pdata->clk_x11k;
+
+       ret = clk_set_parent(sai->sai_ck, parent_clk);
+       if (ret)
+               dev_err(&pdev->dev, " Error %d setting sai_ck parent clock. %s",
+                       ret, ret == -EBUSY ?
+                       "Active stream rates conflict\n" : "\n");
+
+       return ret;
+}
+
 static long stm32_sai_mclk_round_rate(struct clk_hw *hw, unsigned long rate,
                                      unsigned long *prate)
 {
@@ -474,8 +496,10 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
                status = SNDRV_PCM_STATE_XRUN;
        }
 
-       if (status != SNDRV_PCM_STATE_RUNNING)
+       spin_lock(&sai->irq_lock);
+       if (status != SNDRV_PCM_STATE_RUNNING && sai->substream)
                snd_pcm_stop_xrun(sai->substream);
+       spin_unlock(&sai->irq_lock);
 
        return IRQ_HANDLED;
 }
@@ -486,25 +510,29 @@ static int stm32_sai_set_sysclk(struct snd_soc_dai *cpu_dai,
        struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
        int ret;
 
-       if (dir == SND_SOC_CLOCK_OUT) {
+       if (dir == SND_SOC_CLOCK_OUT && sai->sai_mclk) {
                ret = regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX,
                                         SAI_XCR1_NODIV,
                                         (unsigned int)~SAI_XCR1_NODIV);
                if (ret < 0)
                        return ret;
 
-               dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
-               sai->mclk_rate = freq;
+               /* If master clock is used, set parent clock now */
+               ret = stm32_sai_set_parent_clock(sai, freq);
+               if (ret)
+                       return ret;
 
-               if (sai->sai_mclk) {
-                       ret = clk_set_rate_exclusive(sai->sai_mclk,
-                                                    sai->mclk_rate);
-                       if (ret) {
-                               dev_err(cpu_dai->dev,
-                                       "Could not set mclk rate\n");
-                               return ret;
-                       }
+               ret = clk_set_rate_exclusive(sai->sai_mclk, freq);
+               if (ret) {
+                       dev_err(cpu_dai->dev,
+                               ret == -EBUSY ?
+                               "Active streams have incompatible rates" :
+                               "Could not set mclk rate\n");
+                       return ret;
                }
+
+               dev_dbg(cpu_dai->dev, "SAI MCLK frequency is %uHz\n", freq);
+               sai->mclk_rate = freq;
        }
 
        return 0;
@@ -679,8 +707,19 @@ static int stm32_sai_startup(struct snd_pcm_substream *substream,
 {
        struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
        int imr, cr2, ret;
+       unsigned long flags;
 
+       spin_lock_irqsave(&sai->irq_lock, flags);
        sai->substream = substream;
+       spin_unlock_irqrestore(&sai->irq_lock, flags);
+
+       if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
+               snd_pcm_hw_constraint_mask64(substream->runtime,
+                                            SNDRV_PCM_HW_PARAM_FORMAT,
+                                            SNDRV_PCM_FMTBIT_S32_LE);
+               snd_pcm_hw_constraint_single(substream->runtime,
+                                            SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+       }
 
        ret = clk_prepare_enable(sai->sai_ck);
        if (ret < 0) {
@@ -898,14 +937,16 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
                                     struct snd_pcm_hw_params *params)
 {
        struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
-       int div = 0;
+       int div = 0, cr1 = 0;
        int sai_clk_rate, mclk_ratio, den;
        unsigned int rate = params_rate(params);
+       int ret;
 
-       if (!(rate % 11025))
-               clk_set_parent(sai->sai_ck, sai->pdata->clk_x11k);
-       else
-               clk_set_parent(sai->sai_ck, sai->pdata->clk_x8k);
+       if (!sai->sai_mclk) {
+               ret = stm32_sai_set_parent_clock(sai, rate);
+               if (ret)
+                       return ret;
+       }
        sai_clk_rate = clk_get_rate(sai->sai_ck);
 
        if (STM_SAI_IS_F4(sai->pdata)) {
@@ -943,13 +984,19 @@ static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
                } else {
                        if (sai->mclk_rate) {
                                mclk_ratio = sai->mclk_rate / rate;
-                               if ((mclk_ratio != 512) &&
-                                   (mclk_ratio != 256)) {
+                               if (mclk_ratio == 512) {
+                                       cr1 = SAI_XCR1_OSR;
+                               } else if (mclk_ratio != 256) {
                                        dev_err(cpu_dai->dev,
                                                "Wrong mclk ratio %d\n",
                                                mclk_ratio);
                                        return -EINVAL;
                                }
+
+                               regmap_update_bits(sai->regmap,
+                                                  STM_SAI_CR1_REGX,
+                                                  SAI_XCR1_OSR, cr1);
+
                                div = stm32_sai_get_clk_div(sai, sai_clk_rate,
                                                            sai->mclk_rate);
                                if (div < 0)
@@ -1051,28 +1098,36 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
                               struct snd_soc_dai *cpu_dai)
 {
        struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
+       unsigned long flags;
 
        regmap_update_bits(sai->regmap, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0);
 
        regmap_update_bits(sai->regmap, STM_SAI_CR1_REGX, SAI_XCR1_NODIV,
                           SAI_XCR1_NODIV);
 
-       clk_disable_unprepare(sai->sai_ck);
+       /* Release mclk rate only if rate was actually set */
+       if (sai->mclk_rate) {
+               clk_rate_exclusive_put(sai->sai_mclk);
+               sai->mclk_rate = 0;
+       }
 
-       clk_rate_exclusive_put(sai->sai_mclk);
+       clk_disable_unprepare(sai->sai_ck);
 
+       spin_lock_irqsave(&sai->irq_lock, flags);
        sai->substream = NULL;
+       spin_unlock_irqrestore(&sai->irq_lock, flags);
 }
 
 static int stm32_sai_pcm_new(struct snd_soc_pcm_runtime *rtd,
                             struct snd_soc_dai *cpu_dai)
 {
        struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
+       struct snd_kcontrol_new knew = iec958_ctls;
 
        if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
                dev_dbg(&sai->pdev->dev, "%s: register iec controls", __func__);
-               return snd_ctl_add(rtd->pcm->card,
-                                  snd_ctl_new1(&iec958_ctls, sai));
+               knew.device = rtd->pcm->device;
+               return snd_ctl_add(rtd->pcm->card, snd_ctl_new1(&knew, sai));
        }
 
        return 0;
@@ -1081,7 +1136,7 @@ static int stm32_sai_pcm_new(struct snd_soc_pcm_runtime *rtd,
 static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
 {
        struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
-       int cr1 = 0, cr1_mask;
+       int cr1 = 0, cr1_mask, ret;
 
        sai->cpu_dai = cpu_dai;
 
@@ -1111,8 +1166,10 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
        /* Configure synchronization */
        if (sai->sync == SAI_SYNC_EXTERNAL) {
                /* Configure synchro client and provider */
-               sai->pdata->set_sync(sai->pdata, sai->np_sync_provider,
-                                    sai->synco, sai->synci);
+               ret = sai->pdata->set_sync(sai->pdata, sai->np_sync_provider,
+                                          sai->synco, sai->synci);
+               if (ret)
+                       return ret;
        }
 
        cr1_mask |= SAI_XCR1_SYNCEN_MASK;
@@ -1392,7 +1449,6 @@ static int stm32_sai_sub_dais_init(struct platform_device *pdev,
        if (!sai->cpu_dai_drv)
                return -ENOMEM;
 
-       sai->cpu_dai_drv->name = dev_name(&pdev->dev);
        if (STM_SAI_IS_PLAYBACK(sai)) {
                memcpy(sai->cpu_dai_drv, &stm32_sai_playback_dai,
                       sizeof(stm32_sai_playback_dai));
@@ -1402,6 +1458,7 @@ static int stm32_sai_sub_dais_init(struct platform_device *pdev,
                       sizeof(stm32_sai_capture_dai));
                sai->cpu_dai_drv->capture.stream_name = sai->cpu_dai_drv->name;
        }
+       sai->cpu_dai_drv->name = dev_name(&pdev->dev);
 
        return 0;
 }
@@ -1424,6 +1481,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev)
 
        sai->pdev = pdev;
        mutex_init(&sai->ctrl_lock);
+       spin_lock_init(&sai->irq_lock);
        platform_set_drvdata(pdev, sai);
 
        sai->pdata = dev_get_drvdata(pdev->dev.parent);
index a7f413cb704dc7154c42c5adf29ed242d632cfc2..b14ab512c2ce0d4ef2aceae5d673e6b528e1120c 100644 (file)
@@ -441,7 +441,7 @@ static int shbuf_setup_backstore(struct xen_snd_front_pcm_stream_info *stream,
 {
        int i;
 
-       stream->buffer = alloc_pages_exact(stream->buffer_sz, GFP_KERNEL);
+       stream->buffer = alloc_pages_exact(buffer_sz, GFP_KERNEL);
        if (!stream->buffer)
                return -ENOMEM;
 
index 512306a37531d829b880ebbe841aa87c1949b28f..0f257139b003e117eee62b82c87e2f66a20f8e36 100644 (file)
 #include "liburing.h"
 #include "barrier.h"
 
-#ifndef IOCQE_FLAG_CACHEHIT
-#define IOCQE_FLAG_CACHEHIT    (1U << 0)
-#endif
-
 #define min(a, b)              ((a < b) ? (a) : (b))
 
 struct io_sq_ring {
@@ -85,7 +81,6 @@ struct submitter {
        unsigned long reaps;
        unsigned long done;
        unsigned long calls;
-       unsigned long cachehit, cachemiss;
        volatile int finish;
 
        __s32 *fds;
@@ -270,10 +265,6 @@ static int reap_events(struct submitter *s)
                                return -1;
                        }
                }
-               if (cqe->flags & IOCQE_FLAG_CACHEHIT)
-                       s->cachehit++;
-               else
-                       s->cachemiss++;
                reaped++;
                head++;
        } while (1);
@@ -489,7 +480,7 @@ static void file_depths(char *buf)
 int main(int argc, char *argv[])
 {
        struct submitter *s = &submitters[0];
-       unsigned long done, calls, reap, cache_hit, cache_miss;
+       unsigned long done, calls, reap;
        int err, i, flags, fd;
        char *fdepths;
        void *ret;
@@ -569,44 +560,29 @@ int main(int argc, char *argv[])
        pthread_create(&s->thread, NULL, submitter_fn, s);
 
        fdepths = malloc(8 * s->nr_files);
-       cache_hit = cache_miss = reap = calls = done = 0;
+       reap = calls = done = 0;
        do {
                unsigned long this_done = 0;
                unsigned long this_reap = 0;
                unsigned long this_call = 0;
-               unsigned long this_cache_hit = 0;
-               unsigned long this_cache_miss = 0;
                unsigned long rpc = 0, ipc = 0;
-               double hit = 0.0;
 
                sleep(1);
                this_done += s->done;
                this_call += s->calls;
                this_reap += s->reaps;
-               this_cache_hit += s->cachehit;
-               this_cache_miss += s->cachemiss;
-               if (this_cache_hit && this_cache_miss) {
-                       unsigned long hits, total;
-
-                       hits = this_cache_hit - cache_hit;
-                       total = hits + this_cache_miss - cache_miss;
-                       hit = (double) hits / (double) total;
-                       hit *= 100.0;
-               }
                if (this_call - calls) {
                        rpc = (this_done - done) / (this_call - calls);
                        ipc = (this_reap - reap) / (this_call - calls);
                } else
                        rpc = ipc = -1;
                file_depths(fdepths);
-               printf("IOPS=%lu, IOS/call=%ld/%ld, inflight=%u (%s), Cachehit=%0.2f%%\n",
+               printf("IOPS=%lu, IOS/call=%ld/%ld, inflight=%u (%s)\n",
                                this_done - done, rpc, ipc, s->inflight,
-                               fdepths, hit);
+                               fdepths);
                done = this_done;
                calls = this_call;
                reap = this_reap;
-               cache_hit = s->cachehit;
-               cache_miss = s->cachemiss;
        } while (!finish);
 
        pthread_join(s->thread, &ret);
index 5dde107083c60bc8dd12538a2838de73c8b1470c..479196aeb4096efb0f0c03f6722cefcb1765326e 100644 (file)
@@ -165,6 +165,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
                "fortify_panic",
                "usercopy_abort",
                "machine_real_restart",
+               "rewind_stack_do_exit",
        };
 
        if (func->bind == STB_WEAK)
index 99a5ffca1088ad52cdac7842739eaefc40f99c07..2d096b2abf2c943064ae86e674d2a7a65f49757d 100644 (file)
             "$TC qdisc del dev $DEV1 ingress"
         ]
     },
+    {
+        "id": "2638",
+        "name": "Add matchall and try to get it",
+        "category": [
+            "filter",
+            "matchall"
+        ],
+        "setup": [
+            "$TC qdisc add dev $DEV1 clsact",
+            "$TC filter add dev $DEV1 protocol all pref 1 ingress handle 0x1234 matchall action ok"
+        ],
+        "cmdUnderTest": "$TC filter get dev $DEV1 protocol all pref 1 ingress handle 0x1234 matchall",
+        "expExitCode": "0",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "filter protocol all pref 1 matchall chain 0 handle 0x1234",
+        "matchCount": "1",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 clsact"
+        ]
+    },
     {
         "id": "d052",
         "name": "Add 1M filters with the same action",
index 40ea95ce2eadacf07f0dd8b197f94e91a9138b64..828c185846248031ff598670d393e34a38fa24df 100644 (file)
@@ -22,6 +22,7 @@ TPM2_CC_UNSEAL = 0x015E
 TPM2_CC_FLUSH_CONTEXT = 0x0165
 TPM2_CC_START_AUTH_SESSION = 0x0176
 TPM2_CC_GET_CAPABILITY = 0x017A
+TPM2_CC_GET_RANDOM = 0x017B
 TPM2_CC_PCR_READ = 0x017E
 TPM2_CC_POLICY_PCR = 0x017F
 TPM2_CC_PCR_EXTEND = 0x0182
@@ -357,9 +358,9 @@ class Client:
         self.flags = flags
 
         if (self.flags & Client.FLAG_SPACE) == 0:
-            self.tpm = open('/dev/tpm0', 'r+b')
+            self.tpm = open('/dev/tpm0', 'r+b', buffering=0)
         else:
-            self.tpm = open('/dev/tpmrm0', 'r+b')
+            self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)
 
     def close(self):
         self.tpm.close()
index 3bb066fea4a01171f31f80df653c3a046c35acdd..d4973be53493226b19dcca5e7140e997ea964e8b 100644 (file)
@@ -158,6 +158,69 @@ class SmokeTest(unittest.TestCase):
             pass
         self.assertEqual(rejected, True)
 
+    def test_read_partial_resp(self):
+        try:
+            fmt = '>HIIH'
+            cmd = struct.pack(fmt,
+                              tpm2.TPM2_ST_NO_SESSIONS,
+                              struct.calcsize(fmt),
+                              tpm2.TPM2_CC_GET_RANDOM,
+                              0x20)
+            self.client.tpm.write(cmd)
+            hdr = self.client.tpm.read(10)
+            sz = struct.unpack('>I', hdr[2:6])[0]
+            rsp = self.client.tpm.read()
+        except:
+            pass
+        self.assertEqual(sz, 10 + 2 + 32)
+        self.assertEqual(len(rsp), 2 + 32)
+
+    def test_read_partial_overwrite(self):
+        try:
+            fmt = '>HIIH'
+            cmd = struct.pack(fmt,
+                              tpm2.TPM2_ST_NO_SESSIONS,
+                              struct.calcsize(fmt),
+                              tpm2.TPM2_CC_GET_RANDOM,
+                              0x20)
+            self.client.tpm.write(cmd)
+            # Read part of the respone
+            rsp1 = self.client.tpm.read(15)
+
+            # Send a new cmd
+            self.client.tpm.write(cmd)
+
+            # Read the whole respone
+            rsp2 = self.client.tpm.read()
+        except:
+            pass
+        self.assertEqual(len(rsp1), 15)
+        self.assertEqual(len(rsp2), 10 + 2 + 32)
+
+    def test_send_two_cmds(self):
+        rejected = False
+        try:
+            fmt = '>HIIH'
+            cmd = struct.pack(fmt,
+                              tpm2.TPM2_ST_NO_SESSIONS,
+                              struct.calcsize(fmt),
+                              tpm2.TPM2_CC_GET_RANDOM,
+                              0x20)
+            self.client.tpm.write(cmd)
+
+            # expect the second one to raise -EBUSY error
+            self.client.tpm.write(cmd)
+            rsp = self.client.tpm.read()
+
+        except IOError, e:
+            # read the response
+            rsp = self.client.tpm.read()
+            rejected = True
+            pass
+        except:
+            pass
+        self.assertEqual(rejected, True)
+
 class SpaceTest(unittest.TestCase):
     def setUp(self):
         logging.basicConfig(filename='SpaceTest.log', level=logging.DEBUG)