Home Home > GIT Browse > SLE15-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKernel Build Daemon <kbuild@suse.de>2019-04-24 07:05:20 +0200
committerKernel Build Daemon <kbuild@suse.de>2019-04-24 07:05:20 +0200
commit97914dca9b00657fa590c90ad1b3054f4732ae43 (patch)
tree9897aa80e03761ce77fdf27f1b7831e9da206f28
parentc85428939ba71618154cfe5b6bd2c6655dd050ed (diff)
parent2d2424c07ad16fac2b3ba2b69b6f07bec22ce684 (diff)
Merge branch 'SLE15' into SLE15-AZURESLE15-AZURE
-rw-r--r--arch/x86/include/asm/kvm_host.h2
-rw-r--r--arch/x86/kernel/process.c8
-rw-r--r--arch/x86/kvm/mmu.c8
-rw-r--r--arch/x86/kvm/svm.c32
-rw-r--r--arch/x86/kvm/vmx.c6
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c6
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c1
-rw-r--r--drivers/gpu/drm/udl/udl_drv.c1
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h1
-rw-r--r--drivers/gpu/drm/udl/udl_main.c8
-rw-r--r--drivers/idle/intel_idle.c1
-rw-r--r--drivers/md/md.c27
-rw-r--r--drivers/md/md.h3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h5
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c27
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c97
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/l2t.c6
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sched.c3
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c4
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c70
-rw-r--r--fs/kernfs/mount.c8
-rw-r--r--kernel/cgroup/cgroup.c11
-rw-r--r--sound/core/info.c12
-rw-r--r--sound/core/init.c18
-rw-r--r--sound/pci/hda/hda_codec.c1
-rw-r--r--sound/pci/hda/patch_realtek.c6
29 files changed, 282 insertions, 99 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 3af0e5197fcc..bc96ee8c84b4 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1114,11 +1114,13 @@ struct kvm_x86_ops {
int (*mem_enc_reg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
int (*mem_enc_unreg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
+
#ifndef __GENKSYMS__
bool (*has_emulated_msr)(int index);
int (*get_msr_feature)(struct kvm_msr_entry *entry);
struct kvm *(*vm_alloc)(void);
void (*vm_free)(struct kvm *);
+ bool (*need_emulation_on_page_fault)(struct kvm_vcpu *vcpu);
#endif
};
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index f52f6b36e67d..f51bf49e350f 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -413,6 +413,8 @@ static __always_inline void __speculation_ctrl_update(unsigned long tifp,
u64 msr = x86_spec_ctrl_base;
bool updmsr = false;
+ lockdep_assert_irqs_disabled();
+
/*
* If TIF_SSBD is different, select the proper mitigation
* method. Note that if SSBD mitigation is disabled or permanentely
@@ -464,10 +466,12 @@ static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)
void speculation_ctrl_update(unsigned long tif)
{
+ unsigned long flags;
+
/* Forced update. Make sure all relevant TIF flags are different */
- preempt_disable();
+ local_irq_save(flags);
__speculation_ctrl_update(~tif, tif);
- preempt_enable();
+ local_irq_restore(flags);
}
/* Called from seccomp/prctl update */
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index ea535a2c1f6a..64bcf60e9393 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -5020,10 +5020,12 @@ emulate:
* This can happen if a guest gets a page-fault on data access but the HW
* table walker is not able to read the instruction page (e.g instruction
* page is not present in memory). In those cases we simply restart the
- * guest.
+ * guest, with the exception of AMD Erratum 1096 which is unrecoverable.
*/
- if (unlikely(insn && !insn_len))
- return 1;
+ if (unlikely(insn && !insn_len)) {
+ if (!kvm_x86_ops->need_emulation_on_page_fault(vcpu))
+ return 1;
+ }
er = x86_emulate_instruction(vcpu, cr2, emulation_type, insn, insn_len);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 2525f0d05bd3..cf43b8ad1fa3 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -6986,6 +6986,36 @@ failed:
return ret;
}
+static bool svm_need_emulation_on_page_fault(struct kvm_vcpu *vcpu)
+{
+ bool is_user, smap;
+
+ is_user = svm_get_cpl(vcpu) == 3;
+ smap = !kvm_read_cr4_bits(vcpu, X86_CR4_SMAP);
+
+ /*
+ * Detect and workaround Errata 1096 Fam_17h_00_0Fh
+ *
+ * In non SEV guest, hypervisor will be able to read the guest
+ * memory to decode the instruction pointer when insn_len is zero
+ * so we return true to indicate that decoding is possible.
+ *
+ * But in the SEV guest, the guest memory is encrypted with the
+ * guest specific key and hypervisor will not be able to decode the
+ * instruction pointer so we will not able to workaround it. Lets
+ * print the error and request to kill the guest.
+ */
+ if (is_user && smap) {
+ if (!sev_guest(vcpu->kvm))
+ return true;
+
+ pr_err_ratelimited("KVM: Guest triggered AMD Erratum 1096\n");
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+ }
+
+ return false;
+}
+
static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
.cpu_has_kvm_support = has_svm,
.disabled_by_bios = is_disabled,
@@ -7108,6 +7138,8 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
.mem_enc_op = svm_mem_enc_op,
.mem_enc_reg_region = svm_register_enc_region,
.mem_enc_unreg_region = svm_unregister_enc_region,
+
+ .need_emulation_on_page_fault = svm_need_emulation_on_page_fault,
};
static int __init svm_init(void)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d581222c4fe7..c82f029e2949 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -7084,6 +7084,11 @@ void vmx_enable_tdp(void)
kvm_enable_tdp();
}
+static bool vmx_need_emulation_on_page_fault(struct kvm_vcpu *vcpu)
+{
+ return 0;
+}
+
static __init int hardware_setup(void)
{
int r = -ENOMEM, i;
@@ -12704,6 +12709,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
.pre_enter_smm = vmx_pre_enter_smm,
.pre_leave_smm = vmx_pre_leave_smm,
.enable_smi_window = enable_smi_window,
+ .need_emulation_on_page_fault = vmx_need_emulation_on_page_fault,
};
static void vmx_cleanup_l1d_flush(void)
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index e6ce8549ca43..5fc7adc94564 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -641,7 +641,7 @@ static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu, uint64_t off)
static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t 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)) {
@@ -656,9 +656,9 @@ static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t 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);
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index f01a2c7f9eca..bcfe885c1453 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1474,7 +1474,6 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
if (IS_ERR(regmap))
ret = PTR_ERR(regmap);
if (ret) {
- ret = PTR_ERR(regmap);
dev_err(dev,
"Failed to get system configuration registers: %d\n",
ret);
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index cd8b01727734..7c7dff284200 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -53,6 +53,7 @@ static struct drm_driver driver = {
.load = udl_driver_load,
.unload = udl_driver_unload,
.set_busid = udl_driver_set_busid,
+ .release = udl_driver_release,
/* gem hooks */
.gem_free_object = udl_gem_free_object,
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index 2c149b841cf1..307455dd6526 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -101,6 +101,7 @@ void udl_urb_completion(struct urb *urb);
int udl_driver_load(struct drm_device *dev, unsigned long flags);
void udl_driver_unload(struct drm_device *dev);
+void udl_driver_release(struct drm_device *dev);
int udl_fbdev_init(struct drm_device *dev);
void udl_fbdev_cleanup(struct drm_device *dev);
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 5fff6943fa91..812359f14b0e 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -380,6 +380,12 @@ void udl_driver_unload(struct drm_device *dev)
udl_free_urb_list(dev);
udl_fbdev_cleanup(dev);
- udl_modeset_cleanup(dev);
kfree(udl);
}
+
+void udl_driver_release(struct drm_device *dev)
+{
+ udl_modeset_cleanup(dev);
+ drm_dev_fini(dev);
+ kfree(dev);
+}
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 216d7ec88c0c..008eb4d58a86 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -1099,6 +1099,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
ICPU(INTEL_FAM6_ATOM_GOLDMONT, idle_cpu_bxt),
ICPU(INTEL_FAM6_ATOM_GEMINI_LAKE, idle_cpu_bxt),
ICPU(INTEL_FAM6_ATOM_DENVERTON, idle_cpu_dnv),
+ ICPU(INTEL_FAM6_ATOM_TREMONT_X, idle_cpu_dnv),
{}
};
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 477a042c39dc..7ee20c756260 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -434,6 +434,7 @@ static void submit_flushes(struct work_struct *ws)
struct mddev *mddev = container_of(ws, struct mddev, flush_work);
struct md_rdev *rdev;
+ mddev->start_flush = ktime_get_boottime();
INIT_WORK(&mddev->flush_work, md_submit_flush_data);
atomic_set(&mddev->flush_pending, 1);
rcu_read_lock();
@@ -474,6 +475,7 @@ static void md_submit_flush_data(struct work_struct *ws)
* could wait for this and below md_handle_request could wait for those
* bios because of suspend check
*/
+ mddev->last_flush = mddev->start_flush;
mddev->flush_bio = NULL;
wake_up(&mddev->sb_wait);
@@ -488,15 +490,32 @@ static void md_submit_flush_data(struct work_struct *ws)
void md_flush_request(struct mddev *mddev, struct bio *bio)
{
+ ktime_t start = ktime_get_boottime();
spin_lock_irq(&mddev->lock);
wait_event_lock_irq(mddev->sb_wait,
- !mddev->flush_bio,
+ !mddev->flush_bio ||
+ ktime_after(mddev->last_flush, start),
mddev->lock);
- mddev->flush_bio = bio;
+ if (!ktime_after(mddev->last_flush, start)) {
+ WARN_ON(mddev->flush_bio);
+ mddev->flush_bio = bio;
+ bio = NULL;
+ }
spin_unlock_irq(&mddev->lock);
- INIT_WORK(&mddev->flush_work, submit_flushes);
- queue_work(md_wq, &mddev->flush_work);
+ if (!bio) {
+ INIT_WORK(&mddev->flush_work, submit_flushes);
+ queue_work(md_wq, &mddev->flush_work);
+ } else {
+ /* flush was performed for some other bio while we waited. */
+ if (bio->bi_iter.bi_size == 0)
+ /* an empty barrier - all done */
+ bio_endio(bio);
+ else {
+ bio->bi_opf &= ~REQ_PREFLUSH;
+ mddev->pers->make_request(mddev, bio);
+ }
+ }
}
EXPORT_SYMBOL(md_flush_request);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index d339105ef4c3..523ac64c8f31 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -474,6 +474,9 @@ struct mddev {
#ifndef __GENKSYMS__
bool has_superblocks:1;
+ ktime_t start_flush, last_flush; /* last_flush is when the last completed
+ * flush was started.
+ */
#endif
};
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index ab1f7b4544e0..779ff7b8d4e4 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -46,6 +46,7 @@
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/vmalloc.h>
+#include <linux/rhashtable.h>
#include <linux/etherdevice.h>
#include <linux/net_tstamp.h>
#include <linux/ptp_clock_kernel.h>
@@ -1000,7 +1001,9 @@ struct adapter {
struct chcr_stats_debug chcr_stats;
/* TC flower offload */
- DECLARE_HASHTABLE(flower_anymatch_tbl, 9);
+ bool tc_flower_initialized;
+ struct rhashtable flower_tbl;
+ struct rhashtable_params flower_ht_params;
struct timer_list flower_stats_timer;
/* Ethtool Dump */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
index b34f0f077a31..6ba3104ff7eb 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_dcb.c
@@ -114,6 +114,24 @@ void cxgb4_dcb_reset(struct net_device *dev)
cxgb4_dcb_state_init(dev);
}
+/* update the dcb port support, if version is IEEE then set it to
+ * FW_PORT_DCB_VER_IEEE and if DCB_CAP_DCBX_VER_CEE is already set then
+ * clear that. and if it is set to CEE then set dcb supported to
+ * DCB_CAP_DCBX_VER_CEE & if DCB_CAP_DCBX_VER_IEEE is set, clear it
+ */
+static inline void cxgb4_dcb_update_support(struct port_dcb_info *dcb)
+{
+ if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
+ if (dcb->supported & DCB_CAP_DCBX_VER_CEE)
+ dcb->supported &= ~DCB_CAP_DCBX_VER_CEE;
+ dcb->supported |= DCB_CAP_DCBX_VER_IEEE;
+ } else if (dcb->dcb_version == FW_PORT_DCB_VER_CEE1D01) {
+ if (dcb->supported & DCB_CAP_DCBX_VER_IEEE)
+ dcb->supported &= ~DCB_CAP_DCBX_VER_IEEE;
+ dcb->supported |= DCB_CAP_DCBX_VER_CEE;
+ }
+}
+
/* Finite State machine for Data Center Bridging.
*/
void cxgb4_dcb_state_fsm(struct net_device *dev,
@@ -165,6 +183,15 @@ void cxgb4_dcb_state_fsm(struct net_device *dev,
}
case CXGB4_DCB_STATE_FW_INCOMPLETE: {
+ if (transition_to != CXGB4_DCB_INPUT_FW_DISABLED) {
+ /* during this CXGB4_DCB_STATE_FW_INCOMPLETE state,
+ * check if the dcb version is changed (there can be
+ * mismatch in default config & the negotiated switch
+ * configuration at FW, so update the dcb support
+ * accordingly.
+ */
+ cxgb4_dcb_update_support(dcb);
+ }
switch (transition_to) {
case CXGB4_DCB_INPUT_FW_ENABLED: {
/* we're alreaady in firmware DCB mode */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 905c6fc4fc33..19fc550f5113 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -5814,7 +5814,9 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_warn(&pdev->dev,
"could not offload tc u32, continuing\n");
- cxgb4_init_tc_flower(adapter);
+ if (cxgb4_init_tc_flower(adapter))
+ dev_warn(&pdev->dev,
+ "could not offload tc flower, continuing\n");
}
if (is_offload(adapter) || is_hashfilter(adapter)) {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index 305df42d89ca..3cc39f83b722 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -75,13 +75,8 @@ static struct ch_tc_flower_entry *allocate_flower_entry(void)
static struct ch_tc_flower_entry *ch_flower_lookup(struct adapter *adap,
unsigned long flower_cookie)
{
- struct ch_tc_flower_entry *flower_entry;
-
- hash_for_each_possible_rcu(adap->flower_anymatch_tbl, flower_entry,
- link, flower_cookie)
- if (flower_entry->tc_flower_cookie == flower_cookie)
- return flower_entry;
- return NULL;
+ return rhashtable_lookup_fast(&adap->flower_tbl, &flower_cookie,
+ adap->flower_ht_params);
}
static void cxgb4_process_flow_match(struct net_device *dev,
@@ -713,12 +708,17 @@ int cxgb4_tc_flower_replace(struct net_device *dev,
goto free_entry;
}
- INIT_HLIST_NODE(&ch_flower->link);
ch_flower->tc_flower_cookie = cls->cookie;
ch_flower->filter_id = ctx.tid;
- hash_add_rcu(adap->flower_anymatch_tbl, &ch_flower->link, cls->cookie);
+ ret = rhashtable_insert_fast(&adap->flower_tbl, &ch_flower->node,
+ adap->flower_ht_params);
+ if (ret)
+ goto del_filter;
- return ret;
+ return 0;
+
+del_filter:
+ cxgb4_del_filter(dev, ch_flower->filter_id, &ch_flower->fs);
free_entry:
kfree(ch_flower);
@@ -740,7 +740,12 @@ int cxgb4_tc_flower_destroy(struct net_device *dev,
if (ret)
goto err;
- hash_del_rcu(&ch_flower->link);
+ ret = rhashtable_remove_fast(&adap->flower_tbl, &ch_flower->node,
+ adap->flower_ht_params);
+ if (ret) {
+ netdev_err(dev, "Flow remove from rhashtable failed");
+ goto err;
+ }
kfree_rcu(ch_flower, rcu);
err:
@@ -752,29 +757,38 @@ static void ch_flower_stats_cb(unsigned long data)
struct adapter *adap = (struct adapter *)data;
struct ch_tc_flower_entry *flower_entry;
struct ch_tc_flower_stats *ofld_stats;
- unsigned int i;
+ struct rhashtable_iter iter;
u64 packets;
u64 bytes;
int ret;
- rcu_read_lock();
- hash_for_each_rcu(adap->flower_anymatch_tbl, i, flower_entry, link) {
- ret = cxgb4_get_filter_counters(adap->port[0],
- flower_entry->filter_id,
- &packets, &bytes,
- flower_entry->fs.hash);
- if (!ret) {
- spin_lock(&flower_entry->lock);
- ofld_stats = &flower_entry->stats;
-
- if (ofld_stats->prev_packet_count != packets) {
- ofld_stats->prev_packet_count = packets;
- ofld_stats->last_used = jiffies;
+ rhashtable_walk_enter(&adap->flower_tbl, &iter);
+ do {
+ flower_entry = ERR_PTR(rhashtable_walk_start(&iter));
+ if (IS_ERR(flower_entry))
+ goto walk_stop;
+
+ while ((flower_entry = rhashtable_walk_next(&iter)) &&
+ !IS_ERR(flower_entry)) {
+ ret = cxgb4_get_filter_counters(adap->port[0],
+ flower_entry->filter_id,
+ &packets, &bytes,
+ flower_entry->fs.hash);
+ if (!ret) {
+ spin_lock(&flower_entry->lock);
+ ofld_stats = &flower_entry->stats;
+
+ if (ofld_stats->prev_packet_count != packets) {
+ ofld_stats->prev_packet_count = packets;
+ ofld_stats->last_used = jiffies;
+ }
+ spin_unlock(&flower_entry->lock);
}
- spin_unlock(&flower_entry->lock);
}
- }
- rcu_read_unlock();
+walk_stop:
+ rhashtable_walk_stop(&iter);
+ } while (flower_entry == ERR_PTR(-EAGAIN));
+ rhashtable_walk_exit(&iter);
mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
}
@@ -820,16 +834,39 @@ err:
return ret;
}
-void cxgb4_init_tc_flower(struct adapter *adap)
+static const struct rhashtable_params cxgb4_tc_flower_ht_params = {
+ .nelem_hint = 384,
+ .head_offset = offsetof(struct ch_tc_flower_entry, node),
+ .key_offset = offsetof(struct ch_tc_flower_entry, tc_flower_cookie),
+ .key_len = sizeof(((struct ch_tc_flower_entry *)0)->tc_flower_cookie),
+ .max_size = 524288,
+ .min_size = 512,
+ .automatic_shrinking = true
+};
+
+int cxgb4_init_tc_flower(struct adapter *adap)
{
- hash_init(adap->flower_anymatch_tbl);
+ int ret;
+
+ if (adap->tc_flower_initialized)
+ return -EEXIST;
+
+ adap->flower_ht_params = cxgb4_tc_flower_ht_params;
+ ret = rhashtable_init(&adap->flower_tbl, &adap->flower_ht_params);
+ if (ret)
+ return ret;
+
setup_timer(&adap->flower_stats_timer, ch_flower_stats_cb,
(unsigned long)adap);
mod_timer(&adap->flower_stats_timer, jiffies + STATS_CHECK_PERIOD);
+ adap->tc_flower_initialized = true;
+ return 0;
}
void cxgb4_cleanup_tc_flower(struct adapter *adap)
{
if (adap->flower_stats_timer.function)
del_timer_sync(&adap->flower_stats_timer);
+ rhashtable_destroy(&adap->flower_tbl);
+ adap->tc_flower_initialized = false;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
index 202d5c9ec303..050c8a50ae41 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
@@ -48,7 +48,7 @@ struct ch_tc_flower_entry {
struct ch_filter_specification fs;
struct ch_tc_flower_stats stats;
unsigned long tc_flower_cookie;
- struct hlist_node link;
+ struct rhash_head node;
struct rcu_head rcu;
spinlock_t lock; /* lock for stats */
u32 filter_id;
@@ -115,6 +115,6 @@ int cxgb4_tc_flower_destroy(struct net_device *dev,
int cxgb4_tc_flower_stats(struct net_device *dev,
struct tc_cls_flower_offload *cls);
-void cxgb4_init_tc_flower(struct adapter *adap);
+int cxgb4_init_tc_flower(struct adapter *adap);
void cxgb4_cleanup_tc_flower(struct adapter *adap);
#endif /* __CXGB4_TC_FLOWER_H */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
index f7ef8871dd0b..baf834a37c6e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -432,10 +432,12 @@ struct l2t_entry *cxgb4_l2t_get(struct l2t_data *d, struct neighbour *neigh,
else
lport = netdev2pinfo(physdev)->lport;
- if (is_vlan_dev(neigh->dev))
+ if (is_vlan_dev(neigh->dev)) {
vlan = vlan_dev_vlan_id(neigh->dev);
- else
+ vlan |= vlan_dev_get_egress_qos_mask(neigh->dev, priority);
+ } else {
vlan = VLAN_NONE;
+ }
write_lock_bh(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sched.c b/drivers/net/ethernet/chelsio/cxgb4/sched.c
index 9148abb7994c..7fc656680299 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sched.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sched.c
@@ -539,6 +539,9 @@ void t4_cleanup_sched(struct adapter *adap)
struct port_info *pi = netdev2pinfo(adap->port[j]);
s = pi->sched_tbl;
+ if (!s)
+ continue;
+
for (i = 0; i < s->sched_size; i++) {
struct sched_class *e;
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 9fc4357c3db9..2a8afff0d12c 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -99,6 +99,7 @@ struct controller {
unsigned int link_active_reporting:1;
unsigned int notification_enabled:1;
unsigned int power_fault_detected;
+ atomic_t pending_events;
};
#define INT_PRESENCE_ON 1
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index f728c0c0518c..fbd1139a656d 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -151,6 +151,10 @@ static int remove_board(struct slot *p_slot)
* 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 */
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index de69a816920f..d44b7fefd27c 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -46,7 +46,8 @@ static inline struct pci_dev *ctrl_dev(struct controller *ctrl)
return ctrl->pcie->port;
}
-static irqreturn_t pcie_isr(int irq, void *dev_id);
+static irqreturn_t pciehp_isr(int irq, void *dev_id);
+static irqreturn_t pciehp_ist(int irq, void *dev_id);
static void start_int_poll_timer(struct controller *ctrl, int sec);
/* This is the interrupt polling timeout function. */
@@ -55,7 +56,8 @@ static void int_poll_timeout(unsigned long data)
struct controller *ctrl = (struct controller *)data;
/* Poll for interrupt events. regs == NULL => polling */
- pcie_isr(0, ctrl);
+ while (pciehp_isr(IRQ_NOTCONNECTED, ctrl) == IRQ_WAKE_THREAD)
+ pciehp_ist(IRQ_NOTCONNECTED, ctrl);
init_timer(&ctrl->poll_timer);
if (!pciehp_poll_time)
@@ -89,7 +91,8 @@ static inline int pciehp_request_irq(struct controller *ctrl)
}
/* Installs the interrupt handler */
- retval = request_irq(irq, pcie_isr, IRQF_SHARED, MY_NAME, ctrl);
+ retval = request_threaded_irq(irq, pciehp_isr, pciehp_ist,
+ IRQF_SHARED, MY_NAME, ctrl);
if (retval)
ctrl_err(ctrl, "Cannot get irq %d for the hotplug controller\n",
irq);
@@ -562,12 +565,11 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
{
struct controller *ctrl = (struct controller *)dev_id;
struct pci_dev *pdev = ctrl_dev(ctrl);
- struct slot *slot = ctrl->slot;
u16 status, events;
- u8 present;
- bool link;
- /* Interrupts cannot originate from a controller that's asleep */
+ /*
+ * Interrupts only occur in D3hot or shallower (PCIe r4.0, sec 6.7.3.4).
+ */
if (pdev->current_state == PCI_D3cold)
return IRQ_NONE;
@@ -595,18 +597,22 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
if (!events)
return IRQ_NONE;
- /* Capture link status before clearing interrupts */
- if (events & PCI_EXP_SLTSTA_DLLSC)
- link = pciehp_check_link_active(ctrl);
-
pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events);
ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", events);
- /* Check Command Complete Interrupt Pending */
+ /*
+ * Command Completed notifications are not deferred to the
+ * IRQ thread because it may be waiting for their arrival.
+ */
if (events & PCI_EXP_SLTSTA_CC) {
ctrl->cmd_busy = 0;
smp_mb();
wake_up(&ctrl->queue);
+
+ if (events == PCI_EXP_SLTSTA_CC)
+ return IRQ_HANDLED;
+
+ events &= ~PCI_EXP_SLTSTA_CC;
}
if (pdev->ignore_hotplug) {
@@ -614,6 +620,24 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+ /* Save pending events for consumption by IRQ thread. */
+ atomic_or(events, &ctrl->pending_events);
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t pciehp_ist(int irq, void *dev_id)
+{
+ struct controller *ctrl = (struct controller *)dev_id;
+ struct slot *slot = ctrl->slot;
+ u32 events;
+ u8 present;
+ bool link;
+
+ synchronize_hardirq(irq);
+ events = atomic_xchg(&ctrl->pending_events, 0);
+ if (!events)
+ return IRQ_NONE;
+
/* Check Attention Button Pressed */
if (events & PCI_EXP_SLTSTA_ABP) {
ctrl_info(ctrl, "Slot(%s): Attention button pressed\n",
@@ -628,12 +652,13 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
* and cause the wrong event to queue.
*/
if (events & PCI_EXP_SLTSTA_DLLSC) {
+ link = pciehp_check_link_active(ctrl);
ctrl_info(ctrl, "Slot(%s): Link %s\n", slot_name(slot),
link ? "Up" : "Down");
pciehp_queue_interrupt_event(slot, link ? INT_LINK_UP :
INT_LINK_DOWN);
} else if (events & PCI_EXP_SLTSTA_PDC) {
- present = !!(status & PCI_EXP_SLTSTA_PDS);
+ pciehp_get_adapter_status(slot, &present);
ctrl_info(ctrl, "Slot(%s): Card %spresent\n", slot_name(slot),
present ? "" : "not ");
pciehp_queue_interrupt_event(slot, present ? INT_PRESENCE_ON :
@@ -650,25 +675,6 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static irqreturn_t pcie_isr(int irq, void *dev_id)
-{
- irqreturn_t rc, handled = IRQ_NONE;
-
- /*
- * To guarantee that all interrupt events are serviced, we need to
- * re-inspect Slot Status register after clearing what is presumed
- * to be the last pending interrupt.
- */
- do {
- rc = pciehp_isr(irq, dev_id);
- if (rc == IRQ_HANDLED)
- handled = IRQ_HANDLED;
- } while (rc == IRQ_HANDLED);
-
- /* Return IRQ_HANDLED if we handled one or more events */
- return handled;
-}
-
static void pcie_enable_notification(struct controller *ctrl)
{
u16 cmd, mask;
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index d5b149a45be1..4388ee9e6b00 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -123,8 +123,10 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
return dentry;
knparent = find_next_ancestor(kn, NULL);
- if (WARN_ON(!knparent))
+ if (WARN_ON(!knparent)) {
+ dput(dentry);
return ERR_PTR(-EINVAL);
+ }
do {
struct dentry *dtmp;
@@ -133,8 +135,10 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn,
if (kn == knparent)
return dentry;
kntmp = find_next_ancestor(kn, knparent);
- if (WARN_ON(!kntmp))
+ if (WARN_ON(!kntmp)) {
+ dput(dentry);
return ERR_PTR(-EINVAL);
+ }
dtmp = lookup_one_len_unlocked(kntmp->name, dentry,
strlen(kntmp->name));
dput(dentry);
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 482d65ae10fe..5a2cf21263be 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1747,7 +1747,7 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags,
struct cgroup_namespace *ns)
{
struct dentry *dentry;
- bool new_sb;
+ bool new_sb = false;
dentry = kernfs_mount(fs_type, flags, root->kf_root, magic, &new_sb);
@@ -1757,6 +1757,7 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags,
*/
if (!IS_ERR(dentry) && ns != &init_cgroup_ns) {
struct dentry *nsdentry;
+ struct super_block *sb = dentry->d_sb;
struct cgroup *cgrp;
mutex_lock(&cgroup_mutex);
@@ -1767,12 +1768,14 @@ struct dentry *cgroup_do_mount(struct file_system_type *fs_type, int flags,
spin_unlock_irq(&css_set_lock);
mutex_unlock(&cgroup_mutex);
- nsdentry = kernfs_node_dentry(cgrp->kn, dentry->d_sb);
+ nsdentry = kernfs_node_dentry(cgrp->kn, sb);
dput(dentry);
+ if (IS_ERR(nsdentry))
+ deactivate_locked_super(sb);
dentry = nsdentry;
}
- if (IS_ERR(dentry) || !new_sb)
+ if (!new_sb)
cgroup_put(&root->cgrp);
return dentry;
@@ -1801,7 +1804,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
cgroup_enable_task_cg_lists();
if (fs_type == &cgroup2_fs_type) {
- if (data) {
+ if (data && *(char *)data != '\0') {
pr_err("cgroup2: unknown option \"%s\"\n", (char *)data);
put_cgroup_ns(ns);
return ERR_PTR(-EINVAL);
diff --git a/sound/core/info.c b/sound/core/info.c
index 8ab72e0f5932..358a6947342d 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -724,8 +724,11 @@ snd_info_create_entry(const char *name, struct snd_info_entry *parent)
INIT_LIST_HEAD(&entry->children);
INIT_LIST_HEAD(&entry->list);
entry->parent = parent;
- if (parent)
+ if (parent) {
+ mutex_lock(&parent->access);
list_add_tail(&entry->list, &parent->children);
+ mutex_unlock(&parent->access);
+ }
return entry;
}
@@ -809,7 +812,12 @@ void snd_info_free_entry(struct snd_info_entry * entry)
list_for_each_entry_safe(p, n, &entry->children, list)
snd_info_free_entry(p);
- list_del(&entry->list);
+ p = entry->parent;
+ if (p) {
+ mutex_lock(&p->access);
+ list_del(&entry->list);
+ mutex_unlock(&p->access);
+ }
kfree(entry->name);
if (entry->private_free)
entry->private_free(entry);
diff --git a/sound/core/init.c b/sound/core/init.c
index d61d2b3cd521..430efc8424a5 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -408,14 +408,7 @@ int snd_card_disconnect(struct snd_card *card)
card->shutdown = 1;
spin_unlock(&card->files_lock);
- /* phase 1: disable fops (user space) operations for ALSA API */
- mutex_lock(&snd_card_mutex);
- snd_cards[card->number] = NULL;
- clear_bit(card->number, snd_cards_lock);
- mutex_unlock(&snd_card_mutex);
-
- /* phase 2: replace file->f_op with special dummy operations */
-
+ /* replace file->f_op with special dummy operations */
spin_lock(&card->files_lock);
list_for_each_entry(mfile, &card->files_list, list) {
/* it's critical part, use endless loop */
@@ -431,7 +424,7 @@ int snd_card_disconnect(struct snd_card *card)
}
spin_unlock(&card->files_lock);
- /* phase 3: notify all connected devices about disconnection */
+ /* notify all connected devices about disconnection */
/* at this point, they cannot respond to any calls except release() */
#if IS_ENABLED(CONFIG_SND_MIXER_OSS)
@@ -447,6 +440,13 @@ int snd_card_disconnect(struct snd_card *card)
device_del(&card->card_dev);
card->registered = false;
}
+
+ /* disable fops (user space) operations for ALSA API */
+ mutex_lock(&snd_card_mutex);
+ snd_cards[card->number] = NULL;
+ clear_bit(card->number, snd_cards_lock);
+ mutex_unlock(&snd_card_mutex);
+
#ifdef CONFIG_PM
wake_up(&card->power_sleep);
#endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index fe52c5de5bc7..fb099e44bb20 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -932,6 +932,7 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
/* power-up all before initialization */
hda_set_power_state(codec, AC_PWRST_D0);
+ codec->core.dev.power.power_state = PMSG_ON;
snd_hda_codec_proc_new(codec);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6fd1c139eea5..b3081252a86b 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -7139,6 +7139,8 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x12, 0x90a60140},
{0x14, 0x90170150},
{0x21, 0x02211020}),
+ SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x21, 0x02211020}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
{0x14, 0x90170110},
{0x21, 0x02211020}),
@@ -7249,6 +7251,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x21, 0x0221101f}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC256_STANDARD_PINS),
+ SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x14, 0x90170110},
+ {0x1b, 0x01011020},
+ {0x21, 0x0221101f}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC256_FIXUP_ASUS_MIC,
{0x14, 0x90170110},
{0x1b, 0x90a70130},