Merge 5.10-rc7 into android-mainline

Linux 5.10-rc7

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Ie61b3510311a825ee57bee12610e25bc1500b350
This commit is contained in:
Greg Kroah-Hartman
2020-12-07 09:18:08 +01:00
190 changed files with 1353 additions and 1694 deletions
+2
View File
@@ -322,6 +322,8 @@ TripleX Chung <xxx.phy@gmail.com> <zhongyu@18mail.cn>
Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
Tycho Andersen <tycho@tycho.pizza> <tycho@tycho.ws>
Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Uwe Kleine-König <ukleinek@strlen.de>
Uwe Kleine-König <ukl@pengutronix.de>
Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
+5
View File
@@ -740,6 +740,11 @@ S: (ask for current address)
S: Portland, Oregon
S: USA
N: Jason Cooper
D: ARM/Marvell SOC co-maintainer
D: irqchip co-maintainer
D: MVEBU PCI DRIVER co-maintainer
N: Robin Cornelius
E: robincornelius@users.sourceforge.net
D: Ralink rt2x00 WLAN driver
@@ -33,7 +33,7 @@ tcan4x5x: tcan4x5x@0 {
spi-max-frequency = <10000000>;
bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>;
interrupt-parent = <&gpio1>;
interrupts = <14 GPIO_ACTIVE_LOW>;
interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
@@ -25,7 +25,7 @@ Example (for ARM-based BeagleBone with NPC100 NFC controller on I2C2):
clock-frequency = <100000>;
interrupt-parent = <&gpio1>;
interrupts = <29 GPIO_ACTIVE_HIGH>;
interrupts = <29 IRQ_TYPE_LEVEL_HIGH>;
enable-gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>;
firmware-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
@@ -25,7 +25,7 @@ Example (for ARM-based BeagleBone with PN544 on I2C2):
clock-frequency = <400000>;
interrupt-parent = <&gpio1>;
interrupts = <17 GPIO_ACTIVE_HIGH>;
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
enable-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
firmware-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+22 -9
View File
@@ -2014,7 +2014,6 @@ M: Philipp Zabel <philipp.zabel@gmail.com>
S: Maintained
ARM/Marvell Dove/MV78xx0/Orion SOC support
M: Jason Cooper <jason@lakedaemon.net>
M: Andrew Lunn <andrew@lunn.ch>
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
M: Gregory Clement <gregory.clement@bootlin.com>
@@ -2031,7 +2030,6 @@ F: arch/arm/plat-orion/
F: drivers/soc/dove/
ARM/Marvell Kirkwood and Armada 370, 375, 38x, 39x, XP, 3700, 7K/8K, CN9130 SOC support
M: Jason Cooper <jason@lakedaemon.net>
M: Andrew Lunn <andrew@lunn.ch>
M: Gregory Clement <gregory.clement@bootlin.com>
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
@@ -3357,6 +3355,17 @@ S: Supported
F: arch/x86/net/
X: arch/x86/net/bpf_jit_comp32.c
BPF LSM (Security Audit and Enforcement using BPF)
M: KP Singh <kpsingh@chromium.org>
R: Florent Revest <revest@chromium.org>
R: Brendan Jackman <jackmanb@chromium.org>
L: bpf@vger.kernel.org
S: Maintained
F: Documentation/bpf/bpf_lsm.rst
F: include/linux/bpf_lsm.h
F: kernel/bpf/bpf_lsm.c
F: security/bpf/
BROADCOM B44 10/100 ETHERNET DRIVER
M: Michael Chan <michael.chan@broadcom.com>
L: netdev@vger.kernel.org
@@ -4276,6 +4285,7 @@ B: https://github.com/ClangBuiltLinux/linux/issues
C: irc://chat.freenode.net/clangbuiltlinux
F: Documentation/kbuild/llvm.rst
F: scripts/clang-tools/
F: scripts/lld-version.sh
K: \b(?i:clang|llvm)\b
CLEANCACHE API
@@ -9076,10 +9086,7 @@ S: Supported
F: drivers/net/wireless/intel/iwlegacy/
INTEL WIRELESS WIFI LINK (iwlwifi)
M: Johannes Berg <johannes.berg@intel.com>
M: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
M: Luca Coelho <luciano.coelho@intel.com>
M: Intel Linux Wireless <linuxwifi@intel.com>
L: linux-wireless@vger.kernel.org
S: Supported
W: https://wireless.wiki.kernel.org/en/users/drivers/iwlwifi
@@ -9255,7 +9262,6 @@ F: kernel/irq/
IRQCHIP DRIVERS
M: Thomas Gleixner <tglx@linutronix.de>
M: Jason Cooper <jason@lakedaemon.net>
M: Marc Zyngier <maz@kernel.org>
L: linux-kernel@vger.kernel.org
S: Maintained
@@ -13407,7 +13413,6 @@ F: drivers/pci/controller/mobiveil/pcie-mobiveil*
PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
M: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
M: Jason Cooper <jason@lakedaemon.net>
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@@ -19127,12 +19132,17 @@ L: netdev@vger.kernel.org
L: bpf@vger.kernel.org
S: Supported
F: include/net/xdp.h
F: include/net/xdp_priv.h
F: include/trace/events/xdp.h
F: kernel/bpf/cpumap.c
F: kernel/bpf/devmap.c
F: net/core/xdp.c
N: xdp
K: xdp
F: samples/bpf/xdp*
F: tools/testing/selftests/bpf/*xdp*
F: tools/testing/selftests/bpf/*/*xdp*
F: drivers/net/ethernet/*/*/*/*/*xdp*
F: drivers/net/ethernet/*/*/*xdp*
K: (?:\b|_)xdp(?:\b|_)
XDP SOCKETS (AF_XDP)
M: Björn Töpel <bjorn.topel@intel.com>
@@ -19141,9 +19151,12 @@ R: Jonathan Lemon <jonathan.lemon@gmail.com>
L: netdev@vger.kernel.org
L: bpf@vger.kernel.org
S: Maintained
F: Documentation/networking/af_xdp.rst
F: include/net/xdp_sock*
F: include/net/xsk_buff_pool.h
F: include/uapi/linux/if_xdp.h
F: include/uapi/linux/xdp_diag.h
F: include/net/netns/xdp.h
F: net/xdp/
F: samples/bpf/xdpsock*
F: tools/lib/bpf/xsk*
+8 -2
View File
@@ -2,7 +2,7 @@
VERSION = 5
PATCHLEVEL = 10
SUBLEVEL = 0
EXTRAVERSION = -rc6
EXTRAVERSION = -rc7
NAME = Kleptomaniac Octopus
# *DOCUMENTATION*
@@ -947,7 +947,7 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types)
KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init)
# change __FILE__ to the relative path from the srctree
KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
# ensure -fcf-protection is disabled when using retpoline as it is
# incompatible with -mindirect-branch=thunk-extern
@@ -985,6 +985,12 @@ ifeq ($(CONFIG_RELR),y)
LDFLAGS_vmlinux += --pack-dyn-relocs=relr
endif
# We never want expected sections to be placed heuristically by the
# linker. All sections should be explicitly named in the linker script.
ifdef CONFIG_LD_ORPHAN_WARN
LDFLAGS_vmlinux += --orphan-handling=warn
endif
# Align the bit size of userspace programs with the kernel
KBUILD_USERCFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS))
KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CFLAGS))
+9
View File
@@ -1028,6 +1028,15 @@ config HAVE_STATIC_CALL_INLINE
bool
depends on HAVE_STATIC_CALL
config ARCH_WANT_LD_ORPHAN_WARN
bool
help
An arch should select this symbol once all linker sections are explicitly
included, size-asserted, or discarded in the linker scripts. This is
important because we never want expected sections to be placed heuristically
by the linker, since the locations of such sections can change between linker
versions.
source "kernel/gcov/Kconfig"
source "scripts/gcc-plugins/Kconfig"
+1
View File
@@ -35,6 +35,7 @@ config ARM
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
select ARCH_WANT_IPC_PARSE_VERSION
select ARCH_WANT_LD_ORPHAN_WARN
select BINFMT_FLAT_ARGVP_ENVP_ON_STACK
select BUILDTIME_TABLE_SORT if MMU
select CLONE_BACKWARDS
-4
View File
@@ -16,10 +16,6 @@ LDFLAGS_vmlinux += --be8
KBUILD_LDFLAGS_MODULE += --be8
endif
# We never want expected sections to be placed heuristically by the
# linker. All sections should be explicitly named in the linker script.
LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
GZFLAGS :=-9
#KBUILD_CFLAGS +=-pipe
+3 -1
View File
@@ -129,7 +129,9 @@ LDFLAGS_vmlinux += --no-undefined
# Delete all temporary local symbols
LDFLAGS_vmlinux += -X
# Report orphan sections
LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
ifdef CONFIG_LD_ORPHAN_WARN
LDFLAGS_vmlinux += --orphan-handling=warn
endif
# Next argument is a linker script
LDFLAGS_vmlinux += -T
-1
View File
@@ -81,7 +81,6 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_BINFMT_MISC=y
CONFIG_CMA=y
CONFIG_ZSMALLOC=m
CONFIG_ZSMALLOC_PGTABLE_MAPPING=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
+1 -1
View File
@@ -288,7 +288,7 @@ static struct gpiod_lookup_table osk_usb_gpio_table = {
.dev_id = "ohci",
.table = {
/* Power GPIO on the I2C-attached TPS65010 */
GPIO_LOOKUP("i2c-tps65010", 1, "power", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("tps65010", 0, "power", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP(OMAP_GPIO_LABEL, 9, "overcurrent",
GPIO_ACTIVE_HIGH),
},
+1
View File
@@ -81,6 +81,7 @@ config ARM64
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
select ARCH_WANT_FRAME_POINTERS
select ARCH_WANT_HUGE_PMD_SHARE if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36)
select ARCH_WANT_LD_ORPHAN_WARN
select ARCH_HAS_UBSAN_SANITIZE_ALL
select ARM_AMBA
select ARM_ARCH_TIMER
-4
View File
@@ -28,10 +28,6 @@ LDFLAGS_vmlinux += --fix-cortex-a53-843419
endif
endif
# We never want expected sections to be placed heuristically by the
# linker. All sections should be explicitly named in the linker script.
LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
ifeq ($(CONFIG_ARM64_USE_LSE_ATOMICS), y)
ifneq ($(CONFIG_ARM64_LSE_ATOMICS), y)
$(warning LSE atomics not supported by binutils)
+1
View File
@@ -152,6 +152,7 @@ config PPC
select ARCH_USE_QUEUED_SPINLOCKS if PPC_QUEUED_SPINLOCKS
select ARCH_WANT_IPC_PARSE_VERSION
select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
select ARCH_WANT_LD_ORPHAN_WARN
select ARCH_WEAK_RELEASE_ACQUIRE
select BINFMT_ELF
select BUILDTIME_TABLE_SORT
-1
View File
@@ -123,7 +123,6 @@ endif
LDFLAGS_vmlinux-y := -Bstatic
LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y)
LDFLAGS_vmlinux += $(call ld-option,--orphan-handling=warn)
ifdef CONFIG_PPC64
ifeq ($(call cc-option-yn,-mcmodel=medium),y)
+12
View File
@@ -242,6 +242,18 @@ extern void radix_init_pseries(void);
static inline void radix_init_pseries(void) { };
#endif
#ifdef CONFIG_HOTPLUG_CPU
#define arch_clear_mm_cpumask_cpu(cpu, mm) \
do { \
if (cpumask_test_cpu(cpu, mm_cpumask(mm))) { \
atomic_dec(&(mm)->context.active_cpus); \
cpumask_clear_cpu(cpu, mm_cpumask(mm)); \
} \
} while (0)
void cleanup_cpu_mmu_context(void);
#endif
static inline int get_user_context(mm_context_t *ctx, unsigned long ea)
{
int index = ea >> MAX_EA_BITS_PER_CONTEXT;
+2 -5
View File
@@ -1214,12 +1214,9 @@ void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu)
static bool kvmppc_xive_vcpu_id_valid(struct kvmppc_xive *xive, u32 cpu)
{
/* We have a block of xive->nr_servers VPs. We just need to check
* raw vCPU ids are below the expected limit for this guest's
* core stride ; kvmppc_pack_vcpu_id() will pack them down to an
* index that can be safely used to compute a VP id that belongs
* to the VP block.
* packed vCPU ids are below that.
*/
return cpu < xive->nr_servers * xive->kvm->arch.emul_smt_mode;
return kvmppc_pack_vcpu_id(xive->kvm, cpu) < xive->nr_servers;
}
int kvmppc_xive_compute_vp_id(struct kvmppc_xive *xive, u32 cpu, u32 *vp)
+15 -8
View File
@@ -68,7 +68,7 @@ static __always_inline void tlbiel_hash_set_isa300(unsigned int set, unsigned in
rs = ((unsigned long)pid << PPC_BITLSHIFT(31));
asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4)
: : "r"(rb), "r"(rs), "i"(ric), "i"(prs), "r"(r)
: : "r"(rb), "r"(rs), "i"(ric), "i"(prs), "i"(r)
: "memory");
}
@@ -92,16 +92,15 @@ static void tlbiel_all_isa300(unsigned int num_sets, unsigned int is)
asm volatile("ptesync": : :"memory");
/*
* Flush the first set of the TLB, and any caching of partition table
* entries. Then flush the remaining sets of the TLB. Hash mode uses
* partition scoped TLB translations.
* Flush the partition table cache if this is HV mode.
*/
tlbiel_hash_set_isa300(0, is, 0, 2, 0);
for (set = 1; set < num_sets; set++)
tlbiel_hash_set_isa300(set, is, 0, 0, 0);
if (early_cpu_has_feature(CPU_FTR_HVMODE))
tlbiel_hash_set_isa300(0, is, 0, 2, 0);
/*
* Now invalidate the process table cache.
* Now invalidate the process table cache. UPRT=0 HPT modes (what
* current hardware implements) do not use the process table, but
* add the flushes anyway.
*
* From ISA v3.0B p. 1078:
* The following forms are invalid.
@@ -110,6 +109,14 @@ static void tlbiel_all_isa300(unsigned int num_sets, unsigned int is)
*/
tlbiel_hash_set_isa300(0, is, 0, 2, 1);
/*
* Then flush the sets of the TLB proper. Hash mode uses
* partition scoped TLB translations, which may be flushed
* in !HV mode.
*/
for (set = 0; set < num_sets; set++)
tlbiel_hash_set_isa300(set, is, 0, 0, 0);
ppc_after_tlbiel_barrier();
asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT "; isync" : : :"memory");
+20
View File
@@ -17,6 +17,7 @@
#include <linux/export.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/cpu.h>
#include <asm/mmu_context.h>
#include <asm/pgalloc.h>
@@ -307,3 +308,22 @@ void radix__switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
isync();
}
#endif
/**
* cleanup_cpu_mmu_context - Clean up MMU details for this CPU (newly offlined)
*
* This clears the CPU from mm_cpumask for all processes, and then flushes the
* local TLB to ensure TLB coherency in case the CPU is onlined again.
*
* KVM guest translations are not necessarily flushed here. If KVM started
* using mm_cpumask or the Linux APIs which do, this would have to be resolved.
*/
#ifdef CONFIG_HOTPLUG_CPU
void cleanup_cpu_mmu_context(void)
{
int cpu = smp_processor_id();
clear_tasks_mm_cpumask(cpu);
tlbiel_all();
}
#endif
+1 -2
View File
@@ -742,8 +742,7 @@ static int __init parse_numa_properties(void)
of_node_put(cpu);
}
if (likely(nid > 0))
node_set_online(nid);
node_set_online(nid);
}
get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
+2
View File
@@ -911,6 +911,8 @@ static int smp_core99_cpu_disable(void)
mpic_cpu_set_priority(0xf);
cleanup_cpu_mmu_context();
return 0;
}
+7 -2
View File
@@ -211,11 +211,16 @@ static void __init pnv_init(void)
add_preferred_console("hvc", 0, NULL);
if (!radix_enabled()) {
size_t size = sizeof(struct slb_entry) * mmu_slb_size;
int i;
/* Allocate per cpu area to save old slb contents during MCE */
for_each_possible_cpu(i)
paca_ptrs[i]->mce_faulty_slbs = memblock_alloc_node(mmu_slb_size, __alignof__(*paca_ptrs[i]->mce_faulty_slbs), cpu_to_node(i));
for_each_possible_cpu(i) {
paca_ptrs[i]->mce_faulty_slbs =
memblock_alloc_node(size,
__alignof__(struct slb_entry),
cpu_to_node(i));
}
}
}
+3
View File
@@ -143,6 +143,9 @@ static int pnv_smp_cpu_disable(void)
xive_smp_disable_cpu();
else
xics_migrate_irqs_away();
cleanup_cpu_mmu_context();
return 0;
}
@@ -90,6 +90,9 @@ static int pseries_cpu_disable(void)
xive_smp_disable_cpu();
else
xics_migrate_irqs_away();
cleanup_cpu_mmu_context();
return 0;
}
+2 -1
View File
@@ -458,7 +458,8 @@ again:
return hwirq;
}
virq = irq_create_mapping(NULL, hwirq);
virq = irq_create_mapping_affinity(NULL, hwirq,
entry->affinity);
if (!virq) {
pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq);
-15
View File
@@ -763,12 +763,7 @@ ENTRY(io_int_handler)
xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
TSTMSK __LC_CPU_FLAGS,_CIF_IGNORE_IRQ
jo .Lio_restore
#if IS_ENABLED(CONFIG_TRACE_IRQFLAGS)
tmhh %r8,0x300
jz 1f
TRACE_IRQS_OFF
1:
#endif
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
.Lio_loop:
lgr %r2,%r11 # pass pointer to pt_regs
@@ -791,12 +786,7 @@ ENTRY(io_int_handler)
TSTMSK __LC_CPU_FLAGS,_CIF_WORK
jnz .Lio_work
.Lio_restore:
#if IS_ENABLED(CONFIG_TRACE_IRQFLAGS)
tm __PT_PSW(%r11),3
jno 0f
TRACE_IRQS_ON
0:
#endif
mvc __LC_RETURN_PSW(16),__PT_PSW(%r11)
tm __PT_PSW+1(%r11),0x01 # returning to user ?
jno .Lio_exit_kernel
@@ -976,12 +966,7 @@ ENTRY(ext_int_handler)
xc __PT_FLAGS(8,%r11),__PT_FLAGS(%r11)
TSTMSK __LC_CPU_FLAGS,_CIF_IGNORE_IRQ
jo .Lio_restore
#if IS_ENABLED(CONFIG_TRACE_IRQFLAGS)
tmhh %r8,0x300
jz 1f
TRACE_IRQS_OFF
1:
#endif
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
lgr %r2,%r11 # pass pointer to pt_regs
lghi %r3,EXT_INTERRUPT
+2 -3
View File
@@ -33,7 +33,7 @@ EXPORT_SYMBOL(__delay);
static void __udelay_disabled(unsigned long long usecs)
{
unsigned long cr0, cr0_new, psw_mask, flags;
unsigned long cr0, cr0_new, psw_mask;
struct s390_idle_data idle;
u64 end;
@@ -45,9 +45,8 @@ static void __udelay_disabled(unsigned long long usecs)
psw_mask = __extract_psw() | PSW_MASK_EXT | PSW_MASK_WAIT;
set_clock_comparator(end);
set_cpu_flag(CIF_IGNORE_IRQ);
local_irq_save(flags);
psw_idle(&idle, psw_mask);
local_irq_restore(flags);
trace_hardirqs_off();
clear_cpu_flag(CIF_IGNORE_IRQ);
set_clock_comparator(S390_lowcore.clock_comparator);
__ctl_load(cr0, 0, 0);
+11 -3
View File
@@ -103,9 +103,10 @@ static int zpci_set_irq_affinity(struct irq_data *data, const struct cpumask *de
{
struct msi_desc *entry = irq_get_msi_desc(data->irq);
struct msi_msg msg = entry->msg;
int cpu_addr = smp_cpu_get_cpu_address(cpumask_first(dest));
msg.address_lo &= 0xff0000ff;
msg.address_lo |= (cpumask_first(dest) << 8);
msg.address_lo |= (cpu_addr << 8);
pci_write_msi_msg(data->irq, &msg);
return IRQ_SET_MASK_OK;
@@ -238,6 +239,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
unsigned long bit;
struct msi_desc *msi;
struct msi_msg msg;
int cpu_addr;
int rc, irq;
zdev->aisb = -1UL;
@@ -287,9 +289,15 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
handle_percpu_irq);
msg.data = hwirq - bit;
if (irq_delivery == DIRECTED) {
if (msi->affinity)
cpu = cpumask_first(&msi->affinity->mask);
else
cpu = 0;
cpu_addr = smp_cpu_get_cpu_address(cpu);
msg.address_lo = zdev->msi_addr & 0xff0000ff;
msg.address_lo |= msi->affinity ?
(cpumask_first(&msi->affinity->mask) << 8) : 0;
msg.address_lo |= (cpu_addr << 8);
for_each_possible_cpu(cpu) {
airq_iv_set_data(zpci_ibv[cpu], hwirq, irq);
}
+1
View File
@@ -100,6 +100,7 @@ config X86
select ARCH_WANT_DEFAULT_BPF_JIT if X86_64
select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select ARCH_WANT_HUGE_PMD_SHARE
select ARCH_WANT_LD_ORPHAN_WARN
select ARCH_WANTS_THP_SWAP if X86_64
select BUILDTIME_TABLE_SORT
select CLKEVT_I8253
-3
View File
@@ -209,9 +209,6 @@ ifdef CONFIG_X86_64
LDFLAGS_vmlinux += -z max-page-size=0x200000
endif
# We never want expected sections to be placed heuristically by the
# linker. All sections should be explicitly named in the linker script.
LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
archscripts: scripts_basic
$(Q)$(MAKE) $(build)=arch/x86/tools relocs
+3 -1
View File
@@ -61,7 +61,9 @@ KBUILD_LDFLAGS += $(call ld-option,--no-ld-generated-unwind-info)
# Compressed kernel should be built as PIE since it may be loaded at any
# address by the bootloader.
LDFLAGS_vmlinux := -pie $(call ld-option, --no-dynamic-linker)
LDFLAGS_vmlinux += $(call ld-option, --orphan-handling=warn)
ifdef CONFIG_LD_ORPHAN_WARN
LDFLAGS_vmlinux += --orphan-handling=warn
endif
LDFLAGS_vmlinux += -T
hostprogs := mkpiggy
+2 -3
View File
@@ -32,13 +32,12 @@ struct ghcb *boot_ghcb;
*/
static bool insn_has_rep_prefix(struct insn *insn)
{
insn_byte_t p;
int i;
insn_get_prefixes(insn);
for (i = 0; i < insn->prefixes.nbytes; i++) {
insn_byte_t p = insn->prefixes.bytes[i];
for_each_insn_prefix(insn, i, p) {
if (p == 0xf2 || p == 0xf3)
return true;
}
+2 -2
View File
@@ -1916,7 +1916,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
* that caused the PEBS record. It's called collision.
* If collision happened, the record will be dropped.
*/
if (p->status != (1ULL << bit)) {
if (pebs_status != (1ULL << bit)) {
for_each_set_bit(i, (unsigned long *)&pebs_status, size)
error[i]++;
continue;
@@ -1940,7 +1940,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
if (error[bit]) {
perf_log_lost_samples(event, error[bit]);
if (perf_event_account_interrupt(event))
if (iregs && perf_event_account_interrupt(event))
x86_pmu_stop(event, 0);
}
+15
View File
@@ -201,6 +201,21 @@ static inline int insn_offset_immediate(struct insn *insn)
return insn_offset_displacement(insn) + insn->displacement.nbytes;
}
/**
* for_each_insn_prefix() -- Iterate prefixes in the instruction
* @insn: Pointer to struct insn.
* @idx: Index storage.
* @prefix: Prefix byte.
*
* Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix
* and the index is stored in @idx (note that this @idx is just for a cursor,
* do not change it.)
* Since prefixes.nbytes can be bigger than 4 if some prefixes
* are repeated, it cannot be used for looping over the prefixes.
*/
#define for_each_insn_prefix(insn, idx, prefix) \
for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++)
#define POP_SS_OPCODE 0x1f
#define MOV_SREG_OPCODE 0x8e
+1 -1
View File
@@ -161,7 +161,7 @@ static int __init early_set_hub_type(void)
/* UV4/4A only have a revision difference */
case UV4_HUB_PART_NUMBER:
uv_min_hub_revision_id = node_id.s.revision
+ UV4_HUB_REVISION_BASE;
+ UV4_HUB_REVISION_BASE - 1;
uv_hub_type_set(UV4);
if (uv_min_hub_revision_id == UV4A_HUB_REVISION_BASE)
uv_hub_type_set(UV4|UV4A);
+4
View File
@@ -570,6 +570,8 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
if (d) {
cpumask_set_cpu(cpu, &d->cpu_mask);
if (r->cache.arch_has_per_cpu_cfg)
rdt_domain_reconfigure_cdp(r);
return;
}
@@ -923,6 +925,7 @@ static __init void rdt_init_res_defs_intel(void)
r->rid == RDT_RESOURCE_L2CODE) {
r->cache.arch_has_sparse_bitmaps = false;
r->cache.arch_has_empty_bitmaps = false;
r->cache.arch_has_per_cpu_cfg = false;
} else if (r->rid == RDT_RESOURCE_MBA) {
r->msr_base = MSR_IA32_MBA_THRTL_BASE;
r->msr_update = mba_wrmsr_intel;
@@ -943,6 +946,7 @@ static __init void rdt_init_res_defs_amd(void)
r->rid == RDT_RESOURCE_L2CODE) {
r->cache.arch_has_sparse_bitmaps = true;
r->cache.arch_has_empty_bitmaps = true;
r->cache.arch_has_per_cpu_cfg = true;
} else if (r->rid == RDT_RESOURCE_MBA) {
r->msr_base = MSR_IA32_MBA_BW_BASE;
r->msr_update = mba_wrmsr_amd;
+3
View File
@@ -360,6 +360,8 @@ struct msr_param {
* executing entities
* @arch_has_sparse_bitmaps: True if a bitmap like f00f is valid.
* @arch_has_empty_bitmaps: True if the '0' bitmap is valid.
* @arch_has_per_cpu_cfg: True if QOS_CFG register for this cache
* level has CPU scope.
*/
struct rdt_cache {
unsigned int cbm_len;
@@ -369,6 +371,7 @@ struct rdt_cache {
unsigned int shareable_bits;
bool arch_has_sparse_bitmaps;
bool arch_has_empty_bitmaps;
bool arch_has_per_cpu_cfg;
};
/**
+7 -2
View File
@@ -1909,8 +1909,13 @@ static int set_cache_qos_cfg(int level, bool enable)
r_l = &rdt_resources_all[level];
list_for_each_entry(d, &r_l->domains, list) {
/* Pick one CPU from each domain instance to update MSR */
cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
if (r_l->cache.arch_has_per_cpu_cfg)
/* Pick all the CPUs in the domain instance */
for_each_cpu(cpu, &d->cpu_mask)
cpumask_set_cpu(cpu, cpu_mask);
else
/* Pick one CPU from each domain instance to update MSR */
cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
}
cpu = get_cpu();
/* Update QOS_CFG MSR on this cpu if it's in cpu_mask. */
+6 -4
View File
@@ -255,12 +255,13 @@ static volatile u32 good_2byte_insns[256 / 32] = {
static bool is_prefix_bad(struct insn *insn)
{
insn_byte_t p;
int i;
for (i = 0; i < insn->prefixes.nbytes; i++) {
for_each_insn_prefix(insn, i, p) {
insn_attr_t attr;
attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]);
attr = inat_get_opcode_attribute(p);
switch (attr) {
case INAT_MAKE_PREFIX(INAT_PFX_ES):
case INAT_MAKE_PREFIX(INAT_PFX_CS):
@@ -715,6 +716,7 @@ static const struct uprobe_xol_ops push_xol_ops = {
static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
{
u8 opc1 = OPCODE1(insn);
insn_byte_t p;
int i;
switch (opc1) {
@@ -746,8 +748,8 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
* Intel and AMD behavior differ in 64-bit mode: Intel ignores 66 prefix.
* No one uses these insns, reject any branch insns with such prefix.
*/
for (i = 0; i < insn->prefixes.nbytes; i++) {
if (insn->prefixes.bytes[i] == 0x66)
for_each_insn_prefix(insn, i, p) {
if (p == 0x66)
return -ENOTSUPP;
}
+5 -5
View File
@@ -63,13 +63,12 @@ static bool is_string_insn(struct insn *insn)
*/
bool insn_has_rep_prefix(struct insn *insn)
{
insn_byte_t p;
int i;
insn_get_prefixes(insn);
for (i = 0; i < insn->prefixes.nbytes; i++) {
insn_byte_t p = insn->prefixes.bytes[i];
for_each_insn_prefix(insn, i, p) {
if (p == 0xf2 || p == 0xf3)
return true;
}
@@ -95,14 +94,15 @@ static int get_seg_reg_override_idx(struct insn *insn)
{
int idx = INAT_SEG_REG_DEFAULT;
int num_overrides = 0, i;
insn_byte_t p;
insn_get_prefixes(insn);
/* Look for any segment override prefixes. */
for (i = 0; i < insn->prefixes.nbytes; i++) {
for_each_insn_prefix(insn, i, p) {
insn_attr_t attr;
attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]);
attr = inat_get_opcode_attribute(p);
switch (attr) {
case INAT_MAKE_PREFIX(INAT_PFX_CS):
idx = INAT_SEG_REG_CS;
+1 -1
View File
@@ -144,7 +144,7 @@ static struct bio *blk_bio_write_same_split(struct request_queue *q,
static inline unsigned get_max_io_size(struct request_queue *q,
struct bio *bio)
{
unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector);
unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector, 0);
unsigned max_sectors = sectors;
unsigned pbs = queue_physical_block_size(q) >> SECTOR_SHIFT;
unsigned lbs = queue_logical_block_size(q) >> SECTOR_SHIFT;
+4 -1
View File
@@ -547,7 +547,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->io_min = max(t->io_min, b->io_min);
t->io_opt = lcm_not_zero(t->io_opt, b->io_opt);
t->chunk_sectors = lcm_not_zero(t->chunk_sectors, b->chunk_sectors);
/* Set non-power-of-2 compatible chunk_sectors boundary */
if (b->chunk_sectors)
t->chunk_sectors = gcd(t->chunk_sectors, b->chunk_sectors);
/* Physical block size a multiple of the logical block size? */
if (t->physical_block_size & (t->logical_block_size - 1)) {
+23 -14
View File
@@ -47,27 +47,20 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty)
{
struct spk_ldisc_data *ldisc_data;
if (tty != speakup_tty)
/* Somebody tried to use this line discipline outside speakup */
return -ENODEV;
if (!tty->ops->write)
return -EOPNOTSUPP;
mutex_lock(&speakup_tty_mutex);
if (speakup_tty) {
mutex_unlock(&speakup_tty_mutex);
return -EBUSY;
}
speakup_tty = tty;
ldisc_data = kmalloc(sizeof(*ldisc_data), GFP_KERNEL);
if (!ldisc_data) {
speakup_tty = NULL;
mutex_unlock(&speakup_tty_mutex);
if (!ldisc_data)
return -ENOMEM;
}
init_completion(&ldisc_data->completion);
ldisc_data->buf_free = true;
speakup_tty->disc_data = ldisc_data;
mutex_unlock(&speakup_tty_mutex);
tty->disc_data = ldisc_data;
return 0;
}
@@ -191,9 +184,25 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
tty_unlock(tty);
mutex_lock(&speakup_tty_mutex);
speakup_tty = tty;
ret = tty_set_ldisc(tty, N_SPEAKUP);
if (ret)
pr_err("speakup: Failed to set N_SPEAKUP on tty\n");
speakup_tty = NULL;
mutex_unlock(&speakup_tty_mutex);
if (!ret)
/* Success */
return 0;
pr_err("speakup: Failed to set N_SPEAKUP on tty\n");
tty_lock(tty);
if (tty->ops->close)
tty->ops->close(tty, NULL);
tty_unlock(tty);
tty_kclose(tty);
return ret;
}
+1
View File
@@ -142,6 +142,7 @@ config FPGA_DFL
tristate "FPGA Device Feature List (DFL) support"
select FPGA_BRIDGE
select FPGA_REGION
depends on HAS_IOMEM
help
Device Feature List (DFL) defines a feature list structure that
creates a linked list of feature headers within the MMIO space
+19 -6
View File
@@ -1011,6 +1011,11 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
WREG32_SOC15(VCN, inst_idx, mmUVD_RBC_RB_CNTL, tmp);
/* Stall DPG before WPTR/RPTR reset */
WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, mmUVD_POWER_STATUS),
UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK,
~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
/* set the write pointer delay */
WREG32_SOC15(VCN, inst_idx, mmUVD_RBC_RB_WPTR_CNTL, 0);
@@ -1033,6 +1038,10 @@ static int vcn_v3_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
WREG32_SOC15(VCN, inst_idx, mmUVD_RBC_RB_WPTR,
lower_32_bits(ring->wptr));
/* Unstall DPG */
WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, mmUVD_POWER_STATUS),
0, ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
return 0;
}
@@ -1556,8 +1565,14 @@ static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
/* Stall DPG before WPTR/RPTR reset */
WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, mmUVD_POWER_STATUS),
UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK,
~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
/* Restore */
ring = &adev->vcn.inst[inst_idx].ring_enc[0];
ring->wptr = 0;
WREG32_SOC15(VCN, inst_idx, mmUVD_RB_BASE_LO, ring->gpu_addr);
WREG32_SOC15(VCN, inst_idx, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
WREG32_SOC15(VCN, inst_idx, mmUVD_RB_SIZE, ring->ring_size / 4);
@@ -1565,14 +1580,16 @@ static int vcn_v3_0_pause_dpg_mode(struct amdgpu_device *adev,
WREG32_SOC15(VCN, inst_idx, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
ring = &adev->vcn.inst[inst_idx].ring_enc[1];
ring->wptr = 0;
WREG32_SOC15(VCN, inst_idx, mmUVD_RB_BASE_LO2, ring->gpu_addr);
WREG32_SOC15(VCN, inst_idx, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
WREG32_SOC15(VCN, inst_idx, mmUVD_RB_SIZE2, ring->ring_size / 4);
WREG32_SOC15(VCN, inst_idx, mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));
WREG32_SOC15(VCN, inst_idx, mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));
WREG32_SOC15(VCN, inst_idx, mmUVD_RBC_RB_WPTR,
RREG32_SOC15(VCN, inst_idx, mmUVD_SCRATCH2) & 0x7FFFFFFF);
/* Unstall DPG */
WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, mmUVD_POWER_STATUS),
0, ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
SOC15_WAIT_ON_RREG(VCN, inst_idx, mmUVD_POWER_STATUS,
UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
@@ -1630,10 +1647,6 @@ static void vcn_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
WREG32_SOC15(VCN, ring->me, mmUVD_SCRATCH2,
lower_32_bits(ring->wptr) | 0x80000000);
if (ring->use_doorbell) {
adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
@@ -163,8 +163,17 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
new_clocks->dppclk_khz = 100000;
}
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
/*
* Temporally ignore thew 0 cases for disp and dpp clks.
* We may have a new feature that requires 0 clks in the future.
*/
if (new_clocks->dppclk_khz == 0 || new_clocks->dispclk_khz == 0) {
new_clocks->dppclk_khz = clk_mgr_base->clks.dppclk_khz;
new_clocks->dispclk_khz = clk_mgr_base->clks.dispclk_khz;
}
if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) {
if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz)
dpp_clock_lowered = true;
clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
update_dppclk = true;
@@ -1164,7 +1164,12 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
if (ret)
return ret;
crystal_clock_freq = amdgpu_asic_get_xclk(adev);
/*
* crystal_clock_freq div by 4 is required since the fan control
* module refers to 25MHz
*/
crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
+12 -12
View File
@@ -18021,16 +18021,6 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
if (!HAS_GMCH(i915))
sanitize_watermarks(i915);
/*
* Force all active planes to recompute their states. So that on
* mode_setcrtc after probe, all the intel_plane_state variables
* are already calculated and there is no assert_plane warnings
* during bootup.
*/
ret = intel_initial_commit(dev);
if (ret)
drm_dbg_kms(&i915->drm, "Initial commit in probe failed.\n");
return 0;
}
@@ -18039,11 +18029,21 @@ int intel_modeset_init(struct drm_i915_private *i915)
{
int ret;
intel_overlay_setup(i915);
if (!HAS_DISPLAY(i915))
return 0;
/*
* Force all active planes to recompute their states. So that on
* mode_setcrtc after probe, all the intel_plane_state variables
* are already calculated and there is no assert_plane warnings
* during bootup.
*/
ret = intel_initial_commit(&i915->drm);
if (ret)
return ret;
intel_overlay_setup(i915);
ret = intel_fbdev_init(&i915->drm);
if (ret)
return ret;
+74 -94
View File
@@ -101,18 +101,37 @@ static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
intel_gt_pm_put_async(b->irq_engine->gt);
}
static void intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
{
spin_lock(&b->irq_lock);
if (b->irq_armed)
__intel_breadcrumbs_disarm_irq(b);
spin_unlock(&b->irq_lock);
}
static void add_signaling_context(struct intel_breadcrumbs *b,
struct intel_context *ce)
{
intel_context_get(ce);
list_add_tail(&ce->signal_link, &b->signalers);
lockdep_assert_held(&ce->signal_lock);
spin_lock(&b->signalers_lock);
list_add_rcu(&ce->signal_link, &b->signalers);
spin_unlock(&b->signalers_lock);
}
static void remove_signaling_context(struct intel_breadcrumbs *b,
static bool remove_signaling_context(struct intel_breadcrumbs *b,
struct intel_context *ce)
{
list_del(&ce->signal_link);
intel_context_put(ce);
lockdep_assert_held(&ce->signal_lock);
if (!list_empty(&ce->signals))
return false;
spin_lock(&b->signalers_lock);
list_del_rcu(&ce->signal_link);
spin_unlock(&b->signalers_lock);
return true;
}
static inline bool __request_completed(const struct i915_request *rq)
@@ -175,6 +194,8 @@ static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl)
static bool __signal_request(struct i915_request *rq)
{
GEM_BUG_ON(test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags));
if (!__dma_fence_signal(&rq->fence)) {
i915_request_put(rq);
return false;
@@ -195,15 +216,12 @@ static void signal_irq_work(struct irq_work *work)
struct intel_breadcrumbs *b = container_of(work, typeof(*b), irq_work);
const ktime_t timestamp = ktime_get();
struct llist_node *signal, *sn;
struct intel_context *ce, *cn;
struct list_head *pos, *next;
struct intel_context *ce;
signal = NULL;
if (unlikely(!llist_empty(&b->signaled_requests)))
signal = llist_del_all(&b->signaled_requests);
spin_lock(&b->irq_lock);
/*
* Keep the irq armed until the interrupt after all listeners are gone.
*
@@ -229,47 +247,44 @@ static void signal_irq_work(struct irq_work *work)
* interrupt draw less ire from other users of the system and tools
* like powertop.
*/
if (!signal && b->irq_armed && list_empty(&b->signalers))
__intel_breadcrumbs_disarm_irq(b);
if (!signal && READ_ONCE(b->irq_armed) && list_empty(&b->signalers))
intel_breadcrumbs_disarm_irq(b);
list_for_each_entry_safe(ce, cn, &b->signalers, signal_link) {
GEM_BUG_ON(list_empty(&ce->signals));
rcu_read_lock();
list_for_each_entry_rcu(ce, &b->signalers, signal_link) {
struct i915_request *rq;
list_for_each_safe(pos, next, &ce->signals) {
struct i915_request *rq =
list_entry(pos, typeof(*rq), signal_link);
list_for_each_entry_rcu(rq, &ce->signals, signal_link) {
bool release;
GEM_BUG_ON(!check_signal_order(ce, rq));
if (!__request_completed(rq))
break;
if (!test_and_clear_bit(I915_FENCE_FLAG_SIGNAL,
&rq->fence.flags))
break;
/*
* Queue for execution after dropping the signaling
* spinlock as the callback chain may end up adding
* more signalers to the same context or engine.
*/
clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags);
spin_lock(&ce->signal_lock);
list_del_rcu(&rq->signal_link);
release = remove_signaling_context(b, ce);
spin_unlock(&ce->signal_lock);
if (__signal_request(rq))
/* We own signal_node now, xfer to local list */
signal = slist_add(&rq->signal_node, signal);
}
/*
* We process the list deletion in bulk, only using a list_add
* (not list_move) above but keeping the status of
* rq->signal_link known with the I915_FENCE_FLAG_SIGNAL bit.
*/
if (!list_is_first(pos, &ce->signals)) {
/* Advance the list to the first incomplete request */
__list_del_many(&ce->signals, pos);
if (&ce->signals == pos) { /* now empty */
if (release) {
add_retire(b, ce->timeline);
remove_signaling_context(b, ce);
intel_context_put(ce);
}
}
}
spin_unlock(&b->irq_lock);
rcu_read_unlock();
llist_for_each_safe(signal, sn, signal) {
struct i915_request *rq =
@@ -298,14 +313,15 @@ intel_breadcrumbs_create(struct intel_engine_cs *irq_engine)
if (!b)
return NULL;
spin_lock_init(&b->irq_lock);
b->irq_engine = irq_engine;
spin_lock_init(&b->signalers_lock);
INIT_LIST_HEAD(&b->signalers);
init_llist_head(&b->signaled_requests);
spin_lock_init(&b->irq_lock);
init_irq_work(&b->irq_work, signal_irq_work);
b->irq_engine = irq_engine;
return b;
}
@@ -347,9 +363,9 @@ void intel_breadcrumbs_free(struct intel_breadcrumbs *b)
kfree(b);
}
static void insert_breadcrumb(struct i915_request *rq,
struct intel_breadcrumbs *b)
static void insert_breadcrumb(struct i915_request *rq)
{
struct intel_breadcrumbs *b = READ_ONCE(rq->engine)->breadcrumbs;
struct intel_context *ce = rq->context;
struct list_head *pos;
@@ -371,6 +387,7 @@ static void insert_breadcrumb(struct i915_request *rq,
}
if (list_empty(&ce->signals)) {
intel_context_get(ce);
add_signaling_context(b, ce);
pos = &ce->signals;
} else {
@@ -396,8 +413,9 @@ static void insert_breadcrumb(struct i915_request *rq,
break;
}
}
list_add(&rq->signal_link, pos);
list_add_rcu(&rq->signal_link, pos);
GEM_BUG_ON(!check_signal_order(ce, rq));
GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags));
set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags);
/*
@@ -410,7 +428,7 @@ static void insert_breadcrumb(struct i915_request *rq,
bool i915_request_enable_breadcrumb(struct i915_request *rq)
{
struct intel_breadcrumbs *b;
struct intel_context *ce = rq->context;
/* Serialises with i915_request_retire() using rq->lock */
if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags))
@@ -425,67 +443,30 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq)
if (!test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags))
return true;
/*
* rq->engine is locked by rq->engine->active.lock. That however
* is not known until after rq->engine has been dereferenced and
* the lock acquired. Hence we acquire the lock and then validate
* that rq->engine still matches the lock we hold for it.
*
* Here, we are using the breadcrumb lock as a proxy for the
* rq->engine->active.lock, and we know that since the breadcrumb
* will be serialised within i915_request_submit/i915_request_unsubmit,
* the engine cannot change while active as long as we hold the
* breadcrumb lock on that engine.
*
* From the dma_fence_enable_signaling() path, we are outside of the
* request submit/unsubmit path, and so we must be more careful to
* acquire the right lock.
*/
b = READ_ONCE(rq->engine)->breadcrumbs;
spin_lock(&b->irq_lock);
while (unlikely(b != READ_ONCE(rq->engine)->breadcrumbs)) {
spin_unlock(&b->irq_lock);
b = READ_ONCE(rq->engine)->breadcrumbs;
spin_lock(&b->irq_lock);
}
/*
* Now that we are finally serialised with request submit/unsubmit,
* [with b->irq_lock] and with i915_request_retire() [via checking
* SIGNALED with rq->lock] confirm the request is indeed active. If
* it is no longer active, the breadcrumb will be attached upon
* i915_request_submit().
*/
spin_lock(&ce->signal_lock);
if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags))
insert_breadcrumb(rq, b);
spin_unlock(&b->irq_lock);
insert_breadcrumb(rq);
spin_unlock(&ce->signal_lock);
return true;
}
void i915_request_cancel_breadcrumb(struct i915_request *rq)
{
struct intel_breadcrumbs *b = rq->engine->breadcrumbs;
struct intel_context *ce = rq->context;
bool release;
/*
* We must wait for b->irq_lock so that we know the interrupt handler
* has released its reference to the intel_context and has completed
* the DMA_FENCE_FLAG_SIGNALED_BIT/I915_FENCE_FLAG_SIGNAL dance (if
* required).
*/
spin_lock(&b->irq_lock);
if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) {
struct intel_context *ce = rq->context;
if (!test_and_clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags))
return;
list_del(&rq->signal_link);
if (list_empty(&ce->signals))
remove_signaling_context(b, ce);
spin_lock(&ce->signal_lock);
list_del_rcu(&rq->signal_link);
release = remove_signaling_context(rq->engine->breadcrumbs, ce);
spin_unlock(&ce->signal_lock);
if (release)
intel_context_put(ce);
clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags);
i915_request_put(rq);
}
spin_unlock(&b->irq_lock);
i915_request_put(rq);
}
static void print_signals(struct intel_breadcrumbs *b, struct drm_printer *p)
@@ -495,18 +476,17 @@ static void print_signals(struct intel_breadcrumbs *b, struct drm_printer *p)
drm_printf(p, "Signals:\n");
spin_lock_irq(&b->irq_lock);
list_for_each_entry(ce, &b->signalers, signal_link) {
list_for_each_entry(rq, &ce->signals, signal_link) {
rcu_read_lock();
list_for_each_entry_rcu(ce, &b->signalers, signal_link) {
list_for_each_entry_rcu(rq, &ce->signals, signal_link)
drm_printf(p, "\t[%llx:%llx%s] @ %dms\n",
rq->fence.context, rq->fence.seqno,
i915_request_completed(rq) ? "!" :
i915_request_started(rq) ? "*" :
"",
jiffies_to_msecs(jiffies - rq->emitted_jiffies));
}
}
spin_unlock_irq(&b->irq_lock);
rcu_read_unlock();
}
void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine,
@@ -29,18 +29,16 @@
* the overhead of waking that client is much preferred.
*/
struct intel_breadcrumbs {
spinlock_t irq_lock; /* protects the lists used in hardirq context */
/* Not all breadcrumbs are attached to physical HW */
struct intel_engine_cs *irq_engine;
spinlock_t signalers_lock; /* protects the list of signalers */
struct list_head signalers;
struct llist_head signaled_requests;
spinlock_t irq_lock; /* protects the interrupt from hardirq context */
struct irq_work irq_work; /* for use from inside irq_lock */
unsigned int irq_enabled;
bool irq_armed;
};
+11 -4
View File
@@ -25,9 +25,16 @@ static struct intel_context *intel_context_alloc(void)
return kmem_cache_zalloc(global.slab_ce, GFP_KERNEL);
}
static void rcu_context_free(struct rcu_head *rcu)
{
struct intel_context *ce = container_of(rcu, typeof(*ce), rcu);
kmem_cache_free(global.slab_ce, ce);
}
void intel_context_free(struct intel_context *ce)
{
kmem_cache_free(global.slab_ce, ce);
call_rcu(&ce->rcu, rcu_context_free);
}
struct intel_context *
@@ -356,8 +363,7 @@ static int __intel_context_active(struct i915_active *active)
}
void
intel_context_init(struct intel_context *ce,
struct intel_engine_cs *engine)
intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
{
GEM_BUG_ON(!engine->cops);
GEM_BUG_ON(!engine->gt->vm);
@@ -373,7 +379,8 @@ intel_context_init(struct intel_context *ce,
ce->vm = i915_vm_get(engine->gt->vm);
INIT_LIST_HEAD(&ce->signal_link);
/* NB ce->signal_link/lock is used under RCU */
spin_lock_init(&ce->signal_lock);
INIT_LIST_HEAD(&ce->signals);
mutex_init(&ce->pin_mutex);
+20 -3
View File
@@ -25,6 +25,7 @@ DECLARE_EWMA(runtime, 3, 8);
struct i915_gem_context;
struct i915_gem_ww_ctx;
struct i915_vma;
struct intel_breadcrumbs;
struct intel_context;
struct intel_ring;
@@ -44,7 +45,16 @@ struct intel_context_ops {
};
struct intel_context {
struct kref ref;
/*
* Note: Some fields may be accessed under RCU.
*
* Unless otherwise noted a field can safely be assumed to be protected
* by strong reference counting.
*/
union {
struct kref ref; /* no kref_get_unless_zero()! */
struct rcu_head rcu;
};
struct intel_engine_cs *engine;
struct intel_engine_cs *inflight;
@@ -54,8 +64,15 @@ struct intel_context {
struct i915_address_space *vm;
struct i915_gem_context __rcu *gem_context;
struct list_head signal_link;
struct list_head signals;
/*
* @signal_lock protects the list of requests that need signaling,
* @signals. While there are any requests that need signaling,
* we add the context to the breadcrumbs worker, and remove it
* upon completion/cancellation of the last request.
*/
struct list_head signal_link; /* Accessed under RCU */
struct list_head signals; /* Guarded by signal_lock */
spinlock_t signal_lock; /* protects signals, the list of requests */
struct i915_vma *state;
struct intel_ring *ring;
+13 -1
View File
@@ -131,7 +131,19 @@ static const struct drm_i915_mocs_entry skl_mocs_table[] = {
GEN9_MOCS_ENTRIES,
MOCS_ENTRY(I915_MOCS_CACHED,
LE_3_WB | LE_TC_2_LLC_ELLC | LE_LRUM(3),
L3_3_WB)
L3_3_WB),
/*
* mocs:63
* - used by the L3 for all of its evictions.
* Thus it is expected to allow LLC cacheability to enable coherent
* flows to be maintained.
* - used to force L3 uncachable cycles.
* Thus it is expected to make the surface L3 uncacheable.
*/
MOCS_ENTRY(63,
LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
L3_1_UC)
};
/* NOTE: the LE_TGT_CACHE is not used on Broxton */
+4
View File
@@ -883,6 +883,10 @@ void intel_rps_park(struct intel_rps *rps)
adj = -2;
rps->last_adj = adj;
rps->cur_freq = max_t(int, rps->cur_freq + adj, rps->min_freq);
if (rps->cur_freq < rps->efficient_freq) {
rps->cur_freq = rps->efficient_freq;
rps->last_adj = 0;
}
GT_TRACE(rps_to_gt(rps), "park:%x\n", rps->cur_freq);
}
+5 -2
View File
@@ -103,10 +103,13 @@ static int __shmem_rw(struct file *file, loff_t off,
return PTR_ERR(page);
vaddr = kmap(page);
if (write)
if (write) {
memcpy(vaddr + offset_in_page(off), ptr, this);
else
set_page_dirty(page);
} else {
memcpy(ptr, vaddr + offset_in_page(off), this);
}
mark_page_accessed(page);
kunmap(page);
put_page(page);
+2 -4
View File
@@ -177,10 +177,8 @@ struct i915_request {
struct intel_ring *ring;
struct intel_timeline __rcu *timeline;
union {
struct list_head signal_link;
struct llist_node signal_node;
};
struct list_head signal_link;
struct llist_node signal_node;
/*
* The rcu epoch of when this request was allocated. Used to judiciously
+11
View File
@@ -22,6 +22,7 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_plane.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_vblank.h>
@@ -484,17 +485,27 @@ static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
writel(ctrl, mxsfb->base + LCDC_AS_CTRL);
}
static bool mxsfb_format_mod_supported(struct drm_plane *plane,
uint32_t format,
uint64_t modifier)
{
return modifier == DRM_FORMAT_MOD_LINEAR;
}
static const struct drm_plane_helper_funcs mxsfb_plane_primary_helper_funcs = {
.prepare_fb = drm_gem_fb_prepare_fb,
.atomic_check = mxsfb_plane_atomic_check,
.atomic_update = mxsfb_plane_primary_atomic_update,
};
static const struct drm_plane_helper_funcs mxsfb_plane_overlay_helper_funcs = {
.prepare_fb = drm_gem_fb_prepare_fb,
.atomic_check = mxsfb_plane_atomic_check,
.atomic_update = mxsfb_plane_overlay_atomic_update,
};
static const struct drm_plane_funcs mxsfb_plane_funcs = {
.format_mod_supported = mxsfb_format_mod_supported,
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup,
+1 -1
View File
@@ -1214,8 +1214,8 @@ retry:
}
reg->bus.offset = handle;
ret = 0;
}
ret = 0;
break;
default:
ret = -EINVAL;
+4 -6
View File
@@ -195,8 +195,7 @@ static void sdi_bridge_mode_set(struct drm_bridge *bridge,
sdi->pixelclock = adjusted_mode->clock * 1000;
}
static void sdi_bridge_enable(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state)
static void sdi_bridge_enable(struct drm_bridge *bridge)
{
struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
struct dispc_clock_info dispc_cinfo;
@@ -259,8 +258,7 @@ err_get_dispc:
regulator_disable(sdi->vdds_sdi_reg);
}
static void sdi_bridge_disable(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state)
static void sdi_bridge_disable(struct drm_bridge *bridge)
{
struct sdi_device *sdi = drm_bridge_to_sdi(bridge);
@@ -278,8 +276,8 @@ static const struct drm_bridge_funcs sdi_bridge_funcs = {
.mode_valid = sdi_bridge_mode_valid,
.mode_fixup = sdi_bridge_mode_fixup,
.mode_set = sdi_bridge_mode_set,
.atomic_enable = sdi_bridge_enable,
.atomic_disable = sdi_bridge_disable,
.enable = sdi_bridge_enable,
.disable = sdi_bridge_disable,
};
static void sdi_bridge_init(struct sdi_device *sdi)
+1 -1
View File
@@ -629,7 +629,7 @@ static int acx565akm_probe(struct spi_device *spi)
lcd->spi = spi;
mutex_init(&lcd->mutex);
lcd->reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW);
lcd->reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(lcd->reset_gpio)) {
dev_err(&spi->dev, "failed to get reset GPIO\n");
return PTR_ERR(lcd->reset_gpio);
+1 -1
View File
@@ -544,7 +544,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
struct device_node *port, *endpoint;
int ret = 0, child_count = 0;
const char *name;
u32 endpoint_id;
u32 endpoint_id = 0;
lvds->drm_dev = drm_dev;
port = of_graph_get_port_by_id(dev->of_node, 1);
+1 -1
View File
@@ -90,7 +90,7 @@ static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
if (!fpriv)
return -ENOMEM;
idr_init(&fpriv->contexts);
idr_init_base(&fpriv->contexts, 1);
mutex_init(&fpriv->lock);
filp->driver_priv = fpriv;
-1
View File
@@ -129,7 +129,6 @@ int tegra_output_probe(struct tegra_output *output)
if (!output->ddc) {
err = -EPROBE_DEFER;
of_node_put(ddc);
return err;
}
}
+35 -41
View File
@@ -397,7 +397,6 @@ struct tegra_sor;
struct tegra_sor_ops {
const char *name;
int (*probe)(struct tegra_sor *sor);
int (*remove)(struct tegra_sor *sor);
void (*audio_enable)(struct tegra_sor *sor);
void (*audio_disable)(struct tegra_sor *sor);
};
@@ -2942,6 +2941,24 @@ static const struct drm_encoder_helper_funcs tegra_sor_dp_helpers = {
.atomic_check = tegra_sor_encoder_atomic_check,
};
static void tegra_sor_disable_regulator(void *data)
{
struct regulator *reg = data;
regulator_disable(reg);
}
static int tegra_sor_enable_regulator(struct tegra_sor *sor, struct regulator *reg)
{
int err;
err = regulator_enable(reg);
if (err)
return err;
return devm_add_action_or_reset(sor->dev, tegra_sor_disable_regulator, reg);
}
static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
{
int err;
@@ -2953,7 +2970,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
return PTR_ERR(sor->avdd_io_supply);
}
err = regulator_enable(sor->avdd_io_supply);
err = tegra_sor_enable_regulator(sor, sor->avdd_io_supply);
if (err < 0) {
dev_err(sor->dev, "failed to enable AVDD I/O supply: %d\n",
err);
@@ -2967,7 +2984,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
return PTR_ERR(sor->vdd_pll_supply);
}
err = regulator_enable(sor->vdd_pll_supply);
err = tegra_sor_enable_regulator(sor, sor->vdd_pll_supply);
if (err < 0) {
dev_err(sor->dev, "failed to enable VDD PLL supply: %d\n",
err);
@@ -2981,7 +2998,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
return PTR_ERR(sor->hdmi_supply);
}
err = regulator_enable(sor->hdmi_supply);
err = tegra_sor_enable_regulator(sor, sor->hdmi_supply);
if (err < 0) {
dev_err(sor->dev, "failed to enable HDMI supply: %d\n", err);
return err;
@@ -2992,19 +3009,9 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
return 0;
}
static int tegra_sor_hdmi_remove(struct tegra_sor *sor)
{
regulator_disable(sor->hdmi_supply);
regulator_disable(sor->vdd_pll_supply);
regulator_disable(sor->avdd_io_supply);
return 0;
}
static const struct tegra_sor_ops tegra_sor_hdmi_ops = {
.name = "HDMI",
.probe = tegra_sor_hdmi_probe,
.remove = tegra_sor_hdmi_remove,
.audio_enable = tegra_sor_hdmi_audio_enable,
.audio_disable = tegra_sor_hdmi_audio_disable,
};
@@ -3017,7 +3024,7 @@ static int tegra_sor_dp_probe(struct tegra_sor *sor)
if (IS_ERR(sor->avdd_io_supply))
return PTR_ERR(sor->avdd_io_supply);
err = regulator_enable(sor->avdd_io_supply);
err = tegra_sor_enable_regulator(sor, sor->avdd_io_supply);
if (err < 0)
return err;
@@ -3025,25 +3032,16 @@ static int tegra_sor_dp_probe(struct tegra_sor *sor)
if (IS_ERR(sor->vdd_pll_supply))
return PTR_ERR(sor->vdd_pll_supply);
err = regulator_enable(sor->vdd_pll_supply);
err = tegra_sor_enable_regulator(sor, sor->vdd_pll_supply);
if (err < 0)
return err;
return 0;
}
static int tegra_sor_dp_remove(struct tegra_sor *sor)
{
regulator_disable(sor->vdd_pll_supply);
regulator_disable(sor->avdd_io_supply);
return 0;
}
static const struct tegra_sor_ops tegra_sor_dp_ops = {
.name = "DP",
.probe = tegra_sor_dp_probe,
.remove = tegra_sor_dp_remove,
};
static int tegra_sor_init(struct host1x_client *client)
@@ -3145,6 +3143,7 @@ static int tegra_sor_init(struct host1x_client *client)
if (err < 0) {
dev_err(sor->dev, "failed to deassert SOR reset: %d\n",
err);
clk_disable_unprepare(sor->clk);
return err;
}
@@ -3152,12 +3151,17 @@ static int tegra_sor_init(struct host1x_client *client)
}
err = clk_prepare_enable(sor->clk_safe);
if (err < 0)
if (err < 0) {
clk_disable_unprepare(sor->clk);
return err;
}
err = clk_prepare_enable(sor->clk_dp);
if (err < 0)
if (err < 0) {
clk_disable_unprepare(sor->clk_safe);
clk_disable_unprepare(sor->clk);
return err;
}
return 0;
}
@@ -3764,17 +3768,16 @@ static int tegra_sor_probe(struct platform_device *pdev)
return err;
err = tegra_output_probe(&sor->output);
if (err < 0) {
dev_err(&pdev->dev, "failed to probe output: %d\n", err);
return err;
}
if (err < 0)
return dev_err_probe(&pdev->dev, err,
"failed to probe output\n");
if (sor->ops && sor->ops->probe) {
err = sor->ops->probe(sor);
if (err < 0) {
dev_err(&pdev->dev, "failed to probe %s: %d\n",
sor->ops->name, err);
goto output;
goto remove;
}
}
@@ -3955,9 +3958,6 @@ unregister:
rpm_disable:
pm_runtime_disable(&pdev->dev);
remove:
if (sor->ops && sor->ops->remove)
sor->ops->remove(sor);
output:
tegra_output_remove(&sor->output);
return err;
}
@@ -3976,12 +3976,6 @@ static int tegra_sor_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
if (sor->ops && sor->ops->remove) {
err = sor->ops->remove(sor);
if (err < 0)
dev_err(&pdev->dev, "failed to remove SOR: %d\n", err);
}
tegra_output_remove(&sor->output);
return 0;
+1
View File
@@ -734,6 +734,7 @@ config I2C_LPC2K
config I2C_MLXBF
tristate "Mellanox BlueField I2C controller"
depends on MELLANOX_PLATFORM && ARM64
select I2C_SLAVE
help
Enabling this option will add I2C SMBus support for Mellanox BlueField
system.
+36 -8
View File
@@ -412,6 +412,19 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
dma->chan_using = NULL;
}
static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
{
unsigned int temp;
/*
* i2sr_clr_opcode is the value to clear all interrupts. Here we want to
* clear only <bits>, so we write ~i2sr_clr_opcode with just <bits>
* toggled. This is required because i.MX needs W0C and Vybrid uses W1C.
*/
temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
}
static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
{
unsigned long orig_jiffies = jiffies;
@@ -424,8 +437,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool a
/* check for arbitration lost */
if (temp & I2SR_IAL) {
temp &= ~I2SR_IAL;
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
return -EAGAIN;
}
@@ -469,7 +481,7 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
*/
readb_poll_timeout_atomic(addr, regval, regval & I2SR_IIF, 5, 1000 + 100);
i2c_imx->i2csr = regval;
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL);
} else {
wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
}
@@ -478,6 +490,16 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx, bool atomic)
dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
return -ETIMEDOUT;
}
/* check for arbitration lost */
if (i2c_imx->i2csr & I2SR_IAL) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__);
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
i2c_imx->i2csr = 0;
return -EAGAIN;
}
dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__);
i2c_imx->i2csr = 0;
return 0;
@@ -593,6 +615,8 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic)
/* Stop I2C transaction */
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
if (!(temp & I2CR_MSTA))
i2c_imx->stopped = 1;
temp &= ~(I2CR_MSTA | I2CR_MTX);
if (i2c_imx->dma)
temp &= ~I2CR_DMAEN;
@@ -623,9 +647,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
if (temp & I2SR_IIF) {
/* save status register */
i2c_imx->i2csr = temp;
temp &= ~I2SR_IIF;
temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
wake_up(&i2c_imx->queue);
return IRQ_HANDLED;
}
@@ -758,9 +780,12 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
*/
dev_dbg(dev, "<%s> clear MSTA\n", __func__);
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
if (!(temp & I2CR_MSTA))
i2c_imx->stopped = 1;
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
i2c_imx_bus_busy(i2c_imx, 0, false);
if (!i2c_imx->stopped)
i2c_imx_bus_busy(i2c_imx, 0, false);
} else {
/*
* For i2c master receiver repeat restart operation like:
@@ -885,9 +910,12 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
dev_dbg(&i2c_imx->adapter.dev,
"<%s> clear MSTA\n", __func__);
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
if (!(temp & I2CR_MSTA))
i2c_imx->stopped = 1;
temp &= ~(I2CR_MSTA | I2CR_MTX);
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
i2c_imx_bus_busy(i2c_imx, 0, atomic);
if (!i2c_imx->stopped)
i2c_imx_bus_busy(i2c_imx, 0, atomic);
} else {
/*
* For i2c master receiver repeat restart operation like:
+6 -6
View File
@@ -1258,9 +1258,9 @@ static int mlxbf_i2c_get_gpio(struct platform_device *pdev,
return -EFAULT;
gpio_res->io = devm_ioremap(dev, params->start, size);
if (IS_ERR(gpio_res->io)) {
if (!gpio_res->io) {
devm_release_mem_region(dev, params->start, size);
return PTR_ERR(gpio_res->io);
return -ENOMEM;
}
return 0;
@@ -1323,9 +1323,9 @@ static int mlxbf_i2c_get_corepll(struct platform_device *pdev,
return -EFAULT;
corepll_res->io = devm_ioremap(dev, params->start, size);
if (IS_ERR(corepll_res->io)) {
if (!corepll_res->io) {
devm_release_mem_region(dev, params->start, size);
return PTR_ERR(corepll_res->io);
return -ENOMEM;
}
return 0;
@@ -1717,9 +1717,9 @@ static int mlxbf_i2c_init_coalesce(struct platform_device *pdev,
return -EFAULT;
coalesce_res->io = ioremap(params->start, size);
if (IS_ERR(coalesce_res->io)) {
if (!coalesce_res->io) {
release_mem_region(params->start, size);
return PTR_ERR(coalesce_res->io);
return -ENOMEM;
}
priv->coalesce = coalesce_res;
+2 -2
View File
@@ -194,9 +194,9 @@ static irqreturn_t cci_isr(int irq, void *dev)
if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M1_ERROR)) {
if (val & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR ||
val & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR)
cci->master[0].status = -ENXIO;
cci->master[1].status = -ENXIO;
else
cci->master[0].status = -EIO;
cci->master[1].status = -EIO;
writel(CCI_HALT_REQ_I2C_M1_Q0Q1, cci->base + CCI_HALT_REQ);
ret = IRQ_HANDLED;
+2 -1
View File
@@ -801,7 +801,8 @@ static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup)
if (ret || qup->bus_err || qup->qup_err) {
reinit_completion(&qup->xfer);
if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
if (ret) {
dev_err(qup->dev, "change to run state timed out");
goto desc_err;
}
+14 -14
View File
@@ -1140,6 +1140,20 @@ static bool __init intel_idle_max_cstate_reached(int cstate)
return false;
}
static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
{
unsigned long eax = flg2MWAIT(state->flags);
if (boot_cpu_has(X86_FEATURE_ARAT))
return false;
/*
* Switch over to one-shot tick broadcast if the target C-state
* is deeper than C1.
*/
return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
}
#ifdef CONFIG_ACPI_PROCESSOR_CSTATE
#include <acpi/processor.h>
@@ -1210,20 +1224,6 @@ static bool __init intel_idle_acpi_cst_extract(void)
return false;
}
static bool __init intel_idle_state_needs_timer_stop(struct cpuidle_state *state)
{
unsigned long eax = flg2MWAIT(state->flags);
if (boot_cpu_has(X86_FEATURE_ARAT))
return false;
/*
* Switch over to one-shot tick broadcast if the target C-state
* is deeper than C1.
*/
return !!((eax >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK);
}
static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
{
int cstate, limit = min_t(int, CPUIDLE_STATE_MAX, acpi_state_table.count);
+2
View File
@@ -241,6 +241,7 @@ static const struct xpad_device {
{ 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
{ 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
{ 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
{ 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 },
{ 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
{ 0x12ab, 0x0303, "Mortal Kombat Klassic FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
@@ -418,6 +419,7 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */
XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */
XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */
XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */
XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
+1
View File
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
+4
View File
@@ -219,6 +219,10 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
},
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "ByteSpeed LLC"),
DMI_MATCH(DMI_PRODUCT_NAME, "ByteSpeed Laptop C15B"),
},
},
{ }
};
+2 -1
View File
@@ -1471,7 +1471,8 @@ static int __init i8042_setup_aux(void)
if (error)
goto err_free_ports;
if (aux_enable())
error = aux_enable();
if (error)
goto err_free_irq;
i8042_aux_irq_registered = true;
+2 -2
View File
@@ -2183,11 +2183,11 @@ static int mxt_initialize(struct mxt_data *data)
msleep(MXT_FW_RESET_TIME);
}
error = mxt_acquire_irq(data);
error = mxt_check_retrigen(data);
if (error)
return error;
error = mxt_check_retrigen(data);
error = mxt_acquire_irq(data);
if (error)
return error;
-4
View File
@@ -712,10 +712,6 @@ static bool block_size_is_power_of_two(struct cache *cache)
return cache->sectors_per_block_shift >= 0;
}
/* gcc on ARM generates spurious references to __udivdi3 and __umoddi3 */
#if defined(CONFIG_ARM) && __GNUC__ == 4 && __GNUC_MINOR__ <= 6
__always_inline
#endif
static dm_block_t block_div(dm_block_t b, uint32_t n)
{
do_div(b, n);
+2 -2
View File
@@ -3462,7 +3462,7 @@ static int get_mac(struct crypto_shash **hash, struct alg_spec *a, char **error,
int r;
if (a->alg_string) {
*hash = crypto_alloc_shash(a->alg_string, 0, 0);
*hash = crypto_alloc_shash(a->alg_string, 0, CRYPTO_ALG_ALLOCATES_MEMORY);
if (IS_ERR(*hash)) {
*error = error_alg;
r = PTR_ERR(*hash);
@@ -3519,7 +3519,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
struct journal_completion comp;
comp.ic = ic;
ic->journal_crypt = crypto_alloc_skcipher(ic->journal_crypt_alg.alg_string, 0, 0);
ic->journal_crypt = crypto_alloc_skcipher(ic->journal_crypt_alg.alg_string, 0, CRYPTO_ALG_ALLOCATES_MEMORY);
if (IS_ERR(ic->journal_crypt)) {
*error = "Invalid journal cipher";
r = PTR_ERR(ic->journal_crypt);
-11
View File
@@ -18,7 +18,6 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/atomic.h>
#include <linux/lcm.h>
#include <linux/blk-mq.h>
#include <linux/mount.h>
#include <linux/dax.h>
@@ -1249,12 +1248,6 @@ void dm_table_event_callback(struct dm_table *t,
void dm_table_event(struct dm_table *t)
{
/*
* You can no longer call dm_table_event() from interrupt
* context, use a bottom half instead.
*/
BUG_ON(in_interrupt());
mutex_lock(&_event_lock);
if (t->event_fn)
t->event_fn(t->event_context);
@@ -1457,10 +1450,6 @@ int dm_calculate_queue_limits(struct dm_table *table,
zone_sectors = ti_limits.chunk_sectors;
}
/* Stack chunk_sectors if target-specific splitting is required */
if (ti->max_io_len)
ti_limits.chunk_sectors = lcm_not_zero(ti->max_io_len,
ti_limits.chunk_sectors);
/* Set I/O hints portion of queue limits */
if (ti->type->io_hints)
ti->type->io_hints(ti, &ti_limits);
+4 -2
View File
@@ -319,7 +319,7 @@ err1:
#else
static int persistent_memory_claim(struct dm_writecache *wc)
{
BUG();
return -EOPNOTSUPP;
}
#endif
@@ -2041,7 +2041,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
struct wc_memory_superblock s;
static struct dm_arg _args[] = {
{0, 10, "Invalid number of feature args"},
{0, 16, "Invalid number of feature args"},
};
as.argc = argc;
@@ -2479,6 +2479,8 @@ static void writecache_status(struct dm_target *ti, status_type_t type,
extra_args += 2;
if (wc->autocommit_time_set)
extra_args += 2;
if (wc->max_age != MAX_AGE_UNSPECIFIED)
extra_args += 2;
if (wc->cleaner)
extra_args++;
if (wc->writeback_fua_set)
+15 -14
View File
@@ -477,8 +477,10 @@ static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
return -EAGAIN;
map = dm_get_live_table(md, &srcu_idx);
if (!map)
return -EIO;
if (!map) {
ret = -EIO;
goto out;
}
do {
struct dm_target *tgt;
@@ -508,7 +510,6 @@ out:
static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx,
struct block_device **bdev)
__acquires(md->io_barrier)
{
struct dm_target *tgt;
struct dm_table *map;
@@ -542,7 +543,6 @@ retry:
}
static void dm_unprepare_ioctl(struct mapped_device *md, int srcu_idx)
__releases(md->io_barrier)
{
dm_put_live_table(md, srcu_idx);
}
@@ -1038,15 +1038,18 @@ static sector_t max_io_len(struct dm_target *ti, sector_t sector)
sector_t max_len;
/*
* Does the target need to split even further?
* - q->limits.chunk_sectors reflects ti->max_io_len so
* blk_max_size_offset() provides required splitting.
* - blk_max_size_offset() also respects q->limits.max_sectors
* Does the target need to split IO even further?
* - varied (per target) IO splitting is a tenet of DM; this
* explains why stacked chunk_sectors based splitting via
* blk_max_size_offset() isn't possible here. So pass in
* ti->max_io_len to override stacked chunk_sectors.
*/
max_len = blk_max_size_offset(ti->table->md->queue,
target_offset);
if (len > max_len)
len = max_len;
if (ti->max_io_len) {
max_len = blk_max_size_offset(ti->table->md->queue,
target_offset, ti->max_io_len);
if (len > max_len)
len = max_len;
}
return len;
}
@@ -1197,11 +1200,9 @@ static int dm_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
* ->zero_page_range() is mandatory dax operation. If we are
* here, something is wrong.
*/
dm_put_live_table(md, srcu_idx);
goto out;
}
ret = ti->type->dax_zero_page_range(ti, pgoff, nr_pages);
out:
dm_put_live_table(md, srcu_idx);
+8 -8
View File
@@ -231,16 +231,16 @@ delete_cdev_device:
static void device_cdev_sysfs_del(struct hl_device *hdev)
{
/* device_release() won't be called so must free devices explicitly */
if (!hdev->cdev_sysfs_created) {
kfree(hdev->dev_ctrl);
kfree(hdev->dev);
return;
}
if (!hdev->cdev_sysfs_created)
goto put_devices;
hl_sysfs_fini(hdev);
cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
cdev_device_del(&hdev->cdev, hdev->dev);
put_devices:
put_device(hdev->dev);
put_device(hdev->dev_ctrl);
}
/*
@@ -1371,9 +1371,9 @@ sw_fini:
early_fini:
device_early_fini(hdev);
free_dev_ctrl:
kfree(hdev->dev_ctrl);
put_device(hdev->dev_ctrl);
free_dev:
kfree(hdev->dev);
put_device(hdev->dev);
out_disabled:
hdev->disabled = true;
if (add_cdev_sysfs_on_err)
+1
View File
@@ -1626,6 +1626,7 @@ static int vm_ctx_init_with_ranges(struct hl_ctx *ctx,
goto host_hpage_range_err;
}
} else {
kfree(ctx->host_huge_va_range);
ctx->host_huge_va_range = ctx->host_va_range;
}
-10
View File
@@ -46,14 +46,4 @@ config INTEL_MEI_TXE
Supported SoCs:
Intel Bay Trail
config INTEL_MEI_VIRTIO
tristate "Intel MEI interface emulation with virtio framework"
select INTEL_MEI
depends on X86 && PCI && VIRTIO_PCI
help
This module implements mei hw emulation over virtio transport.
The module will be called mei_virtio.
Enable this if your virtual machine supports virtual mei
device over virtio.
source "drivers/misc/mei/hdcp/Kconfig"
-3
View File
@@ -22,9 +22,6 @@ obj-$(CONFIG_INTEL_MEI_TXE) += mei-txe.o
mei-txe-objs := pci-txe.o
mei-txe-objs += hw-txe.o
obj-$(CONFIG_INTEL_MEI_VIRTIO) += mei-virtio.o
mei-virtio-objs := hw-virtio.o
mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
CFLAGS_mei-trace.o = -I$(src)
-874
View File
@@ -1,874 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Intel Management Engine Interface (Intel MEI) Linux driver
* Copyright (c) 2018-2020, Intel Corporation.
*/
#include <linux/err.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/scatterlist.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/virtio.h>
#include <linux/virtio_config.h>
#include <linux/virtio_ids.h>
#include <linux/atomic.h>
#include "mei_dev.h"
#include "hbm.h"
#include "client.h"
#define MEI_VIRTIO_RPM_TIMEOUT 500
/* ACRN virtio device types */
#ifndef VIRTIO_ID_MEI
#define VIRTIO_ID_MEI 0xFFFE /* virtio mei */
#endif
/**
* struct mei_virtio_cfg - settings passed from the virtio backend
* @buf_depth: read buffer depth in slots (4bytes)
* @hw_ready: hw is ready for operation
* @host_reset: synchronize reset with virtio backend
* @reserved: reserved for alignment
* @fw_status: FW status
*/
struct mei_virtio_cfg {
u32 buf_depth;
u8 hw_ready;
u8 host_reset;
u8 reserved[2];
u32 fw_status[MEI_FW_STATUS_MAX];
} __packed;
struct mei_virtio_hw {
struct mei_device mdev;
char name[32];
struct virtqueue *in;
struct virtqueue *out;
bool host_ready;
struct work_struct intr_handler;
u32 *recv_buf;
u8 recv_rdy;
size_t recv_sz;
u32 recv_idx;
u32 recv_len;
/* send buffer */
atomic_t hbuf_ready;
const void *send_hdr;
const void *send_buf;
struct mei_virtio_cfg cfg;
};
#define to_virtio_hw(_dev) container_of(_dev, struct mei_virtio_hw, mdev)
/**
* mei_virtio_fw_status() - read status register of mei
* @dev: mei device
* @fw_status: fw status register values
*
* Return: always 0
*/
static int mei_virtio_fw_status(struct mei_device *dev,
struct mei_fw_status *fw_status)
{
struct virtio_device *vdev = dev_to_virtio(dev->dev);
fw_status->count = MEI_FW_STATUS_MAX;
virtio_cread_bytes(vdev, offsetof(struct mei_virtio_cfg, fw_status),
fw_status->status, sizeof(fw_status->status));
return 0;
}
/**
* mei_virtio_pg_state() - translate internal pg state
* to the mei power gating state
* There is no power management in ACRN mode always return OFF
* @dev: mei device
*
* Return:
* * MEI_PG_OFF - if aliveness is on (always)
* * MEI_PG_ON - (never)
*/
static inline enum mei_pg_state mei_virtio_pg_state(struct mei_device *dev)
{
return MEI_PG_OFF;
}
/**
* mei_virtio_hw_config() - configure hw dependent settings
*
* @dev: mei device
*
* Return: always 0
*/
static int mei_virtio_hw_config(struct mei_device *dev)
{
return 0;
}
/**
* mei_virtio_hbuf_empty_slots() - counts write empty slots.
* @dev: the device structure
*
* Return: always return frontend buf size if buffer is ready, 0 otherwise
*/
static int mei_virtio_hbuf_empty_slots(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
return (atomic_read(&hw->hbuf_ready) == 1) ? hw->cfg.buf_depth : 0;
}
/**
* mei_virtio_hbuf_is_ready() - checks if write buffer is ready
* @dev: the device structure
*
* Return: true if hbuf is ready
*/
static bool mei_virtio_hbuf_is_ready(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
return atomic_read(&hw->hbuf_ready) == 1;
}
/**
* mei_virtio_hbuf_max_depth() - returns depth of FE write buffer.
* @dev: the device structure
*
* Return: size of frontend write buffer in bytes
*/
static u32 mei_virtio_hbuf_depth(const struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
return hw->cfg.buf_depth;
}
/**
* mei_virtio_intr_clear() - clear and stop interrupts
* @dev: the device structure
*/
static void mei_virtio_intr_clear(struct mei_device *dev)
{
/*
* In our virtio solution, there are two types of interrupts,
* vq interrupt and config change interrupt.
* 1) start/reset rely on virtio config changed interrupt;
* 2) send/recv rely on virtio virtqueue interrupts.
* They are all virtual interrupts. So, we don't have corresponding
* operation to do here.
*/
}
/**
* mei_virtio_intr_enable() - enables mei BE virtqueues callbacks
* @dev: the device structure
*/
static void mei_virtio_intr_enable(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
struct virtio_device *vdev = dev_to_virtio(dev->dev);
virtio_config_enable(vdev);
virtqueue_enable_cb(hw->in);
virtqueue_enable_cb(hw->out);
}
/**
* mei_virtio_intr_disable() - disables mei BE virtqueues callbacks
*
* @dev: the device structure
*/
static void mei_virtio_intr_disable(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
struct virtio_device *vdev = dev_to_virtio(dev->dev);
virtio_config_disable(vdev);
virtqueue_disable_cb(hw->in);
virtqueue_disable_cb(hw->out);
}
/**
* mei_virtio_synchronize_irq() - wait for pending IRQ handlers for all
* virtqueue
* @dev: the device structure
*/
static void mei_virtio_synchronize_irq(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
/*
* Now, all IRQ handlers are converted to workqueue.
* Change synchronize irq to flush this work.
*/
flush_work(&hw->intr_handler);
}
static void mei_virtio_free_outbufs(struct mei_virtio_hw *hw)
{
kfree(hw->send_hdr);
kfree(hw->send_buf);
hw->send_hdr = NULL;
hw->send_buf = NULL;
}
/**
* mei_virtio_write_message() - writes a message to mei virtio back-end service.
* @dev: the device structure
* @hdr: mei header of message
* @hdr_len: header length
* @data: message payload will be written
* @data_len: message payload length
*
* Return:
* * 0: on success
* * -EIO: if write has failed
* * -ENOMEM: on memory allocation failure
*/
static int mei_virtio_write_message(struct mei_device *dev,
const void *hdr, size_t hdr_len,
const void *data, size_t data_len)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
struct scatterlist sg[2];
const void *hbuf, *dbuf;
int ret;
if (WARN_ON(!atomic_add_unless(&hw->hbuf_ready, -1, 0)))
return -EIO;
hbuf = kmemdup(hdr, hdr_len, GFP_KERNEL);
hw->send_hdr = hbuf;
dbuf = kmemdup(data, data_len, GFP_KERNEL);
hw->send_buf = dbuf;
if (!hbuf || !dbuf) {
ret = -ENOMEM;
goto fail;
}
sg_init_table(sg, 2);
sg_set_buf(&sg[0], hbuf, hdr_len);
sg_set_buf(&sg[1], dbuf, data_len);
ret = virtqueue_add_outbuf(hw->out, sg, 2, hw, GFP_KERNEL);
if (ret) {
dev_err(dev->dev, "failed to add outbuf\n");
goto fail;
}
virtqueue_kick(hw->out);
return 0;
fail:
mei_virtio_free_outbufs(hw);
return ret;
}
/**
* mei_virtio_count_full_read_slots() - counts read full slots.
* @dev: the device structure
*
* Return: -EOVERFLOW if overflow, otherwise filled slots count
*/
static int mei_virtio_count_full_read_slots(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
if (hw->recv_idx > hw->recv_len)
return -EOVERFLOW;
return hw->recv_len - hw->recv_idx;
}
/**
* mei_virtio_read_hdr() - Reads 32bit dword from mei virtio receive buffer
*
* @dev: the device structure
*
* Return: 32bit dword of receive buffer (u32)
*/
static inline u32 mei_virtio_read_hdr(const struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
WARN_ON(hw->cfg.buf_depth < hw->recv_idx + 1);
return hw->recv_buf[hw->recv_idx++];
}
static int mei_virtio_read(struct mei_device *dev, unsigned char *buffer,
unsigned long len)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
u32 slots = mei_data2slots(len);
if (WARN_ON(hw->cfg.buf_depth < hw->recv_idx + slots))
return -EOVERFLOW;
/*
* Assumption: There is only one MEI message in recv_buf each time.
* Backend service need follow this rule too.
*/
memcpy(buffer, hw->recv_buf + hw->recv_idx, len);
hw->recv_idx += slots;
return 0;
}
static bool mei_virtio_pg_is_enabled(struct mei_device *dev)
{
return false;
}
static bool mei_virtio_pg_in_transition(struct mei_device *dev)
{
return false;
}
static void mei_virtio_add_recv_buf(struct mei_virtio_hw *hw)
{
struct scatterlist sg;
if (hw->recv_rdy) /* not needed */
return;
/* refill the recv_buf to IN virtqueue to get next message */
sg_init_one(&sg, hw->recv_buf, mei_slots2data(hw->cfg.buf_depth));
hw->recv_len = 0;
hw->recv_idx = 0;
hw->recv_rdy = 1;
virtqueue_add_inbuf(hw->in, &sg, 1, hw->recv_buf, GFP_KERNEL);
virtqueue_kick(hw->in);
}
/**
* mei_virtio_hw_is_ready() - check whether the BE(hw) has turned ready
* @dev: mei device
* Return: bool
*/
static bool mei_virtio_hw_is_ready(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
struct virtio_device *vdev = dev_to_virtio(dev->dev);
virtio_cread(vdev, struct mei_virtio_cfg,
hw_ready, &hw->cfg.hw_ready);
dev_dbg(dev->dev, "hw ready %d\n", hw->cfg.hw_ready);
return hw->cfg.hw_ready;
}
/**
* mei_virtio_hw_reset - resets virtio hw.
*
* @dev: the device structure
* @intr_enable: virtio use data/config callbacks
*
* Return: 0 on success an error code otherwise
*/
static int mei_virtio_hw_reset(struct mei_device *dev, bool intr_enable)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
struct virtio_device *vdev = dev_to_virtio(dev->dev);
dev_dbg(dev->dev, "hw reset\n");
dev->recvd_hw_ready = false;
hw->host_ready = false;
atomic_set(&hw->hbuf_ready, 0);
hw->recv_len = 0;
hw->recv_idx = 0;
hw->cfg.host_reset = 1;
virtio_cwrite(vdev, struct mei_virtio_cfg,
host_reset, &hw->cfg.host_reset);
mei_virtio_hw_is_ready(dev);
if (intr_enable)
mei_virtio_intr_enable(dev);
return 0;
}
/**
* mei_virtio_hw_reset_release() - release device from the reset
* @dev: the device structure
*/
static void mei_virtio_hw_reset_release(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
struct virtio_device *vdev = dev_to_virtio(dev->dev);
dev_dbg(dev->dev, "hw reset release\n");
hw->cfg.host_reset = 0;
virtio_cwrite(vdev, struct mei_virtio_cfg,
host_reset, &hw->cfg.host_reset);
}
/**
* mei_virtio_hw_ready_wait() - wait until the virtio(hw) has turned ready
* or timeout is reached
* @dev: mei device
*
* Return: 0 on success, error otherwise
*/
static int mei_virtio_hw_ready_wait(struct mei_device *dev)
{
mutex_unlock(&dev->device_lock);
wait_event_timeout(dev->wait_hw_ready,
dev->recvd_hw_ready,
mei_secs_to_jiffies(MEI_HW_READY_TIMEOUT));
mutex_lock(&dev->device_lock);
if (!dev->recvd_hw_ready) {
dev_err(dev->dev, "wait hw ready failed\n");
return -ETIMEDOUT;
}
dev->recvd_hw_ready = false;
return 0;
}
/**
* mei_virtio_hw_start() - hw start routine
* @dev: mei device
*
* Return: 0 on success, error otherwise
*/
static int mei_virtio_hw_start(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
int ret;
dev_dbg(dev->dev, "hw start\n");
mei_virtio_hw_reset_release(dev);
ret = mei_virtio_hw_ready_wait(dev);
if (ret)
return ret;
mei_virtio_add_recv_buf(hw);
atomic_set(&hw->hbuf_ready, 1);
dev_dbg(dev->dev, "hw is ready\n");
hw->host_ready = true;
return 0;
}
/**
* mei_virtio_host_is_ready() - check whether the FE has turned ready
* @dev: mei device
*
* Return: bool
*/
static bool mei_virtio_host_is_ready(struct mei_device *dev)
{
struct mei_virtio_hw *hw = to_virtio_hw(dev);
dev_dbg(dev->dev, "host ready %d\n", hw->host_ready);
return hw->host_ready;
}
/**
* mei_virtio_data_in() - The callback of recv virtqueue of virtio mei
* @vq: receiving virtqueue
*/
static void mei_virtio_data_in(struct virtqueue *vq)
{
struct mei_virtio_hw *hw = vq->vdev->priv;
/* disable interrupts (enabled again from in the interrupt worker) */
virtqueue_disable_cb(hw->in);
schedule_work(&hw->intr_handler);
}
/**
* mei_virtio_data_out() - The callback of send virtqueue of virtio mei
* @vq: transmitting virtqueue
*/
static void mei_virtio_data_out(struct virtqueue *vq)
{
struct mei_virtio_hw *hw = vq->vdev->priv;
schedule_work(&hw->intr_handler);
}
static void mei_virtio_intr_handler(struct work_struct *work)
{
struct mei_virtio_hw *hw =
container_of(work, struct mei_virtio_hw, intr_handler);
struct mei_device *dev = &hw->mdev;
LIST_HEAD(complete_list);
s32 slots;
int rets = 0;
void *data;
unsigned int len;
mutex_lock(&dev->device_lock);
if (dev->dev_state == MEI_DEV_DISABLED) {
dev_warn(dev->dev, "Interrupt in disabled state.\n");
mei_virtio_intr_disable(dev);
goto end;
}
/* check if ME wants a reset */
if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) {
dev_warn(dev->dev, "BE service not ready: resetting.\n");
schedule_work(&dev->reset_work);
goto end;
}
/* check if we need to start the dev */
if (!mei_host_is_ready(dev)) {
if (mei_hw_is_ready(dev)) {
dev_dbg(dev->dev, "we need to start the dev.\n");
dev->recvd_hw_ready = true;
wake_up(&dev->wait_hw_ready);
} else {
dev_warn(dev->dev, "Spurious Interrupt\n");
}
goto end;
}
/* read */
if (hw->recv_rdy) {
data = virtqueue_get_buf(hw->in, &len);
if (!data || !len) {
dev_dbg(dev->dev, "No data %d", len);
} else {
dev_dbg(dev->dev, "data_in %d\n", len);
WARN_ON(data != hw->recv_buf);
hw->recv_len = mei_data2slots(len);
hw->recv_rdy = 0;
}
}
/* write */
if (!atomic_read(&hw->hbuf_ready)) {
if (!virtqueue_get_buf(hw->out, &len)) {
dev_warn(dev->dev, "Failed to getbuf\n");
} else {
mei_virtio_free_outbufs(hw);
atomic_inc(&hw->hbuf_ready);
}
}
/* check slots available for reading */
slots = mei_count_full_read_slots(dev);
while (slots > 0) {
dev_dbg(dev->dev, "slots to read = %08x\n", slots);
rets = mei_irq_read_handler(dev, &complete_list, &slots);
if (rets &&
(dev->dev_state != MEI_DEV_RESETTING &&
dev->dev_state != MEI_DEV_POWER_DOWN)) {
dev_err(dev->dev, "mei_irq_read_handler ret = %d.\n",
rets);
schedule_work(&dev->reset_work);
goto end;
}
}
dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
mei_irq_write_handler(dev, &complete_list);
dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
mei_irq_compl_handler(dev, &complete_list);
mei_virtio_add_recv_buf(hw);
end:
if (dev->dev_state != MEI_DEV_DISABLED) {
if (!virtqueue_enable_cb(hw->in))
schedule_work(&hw->intr_handler);
}
mutex_unlock(&dev->device_lock);
}
static void mei_virtio_config_changed(struct virtio_device *vdev)
{
struct mei_virtio_hw *hw = vdev->priv;
struct mei_device *dev = &hw->mdev;
virtio_cread(vdev, struct mei_virtio_cfg,
hw_ready, &hw->cfg.hw_ready);
if (dev->dev_state == MEI_DEV_DISABLED) {
dev_dbg(dev->dev, "disabled state don't start\n");
return;
}
/* Run intr handler once to handle reset notify */
schedule_work(&hw->intr_handler);
}
static void mei_virtio_remove_vqs(struct virtio_device *vdev)
{
struct mei_virtio_hw *hw = vdev->priv;
virtqueue_detach_unused_buf(hw->in);
hw->recv_len = 0;
hw->recv_idx = 0;
hw->recv_rdy = 0;
virtqueue_detach_unused_buf(hw->out);
mei_virtio_free_outbufs(hw);
vdev->config->del_vqs(vdev);
}
/*
* There are two virtqueues, one is for send and another is for recv.
*/
static int mei_virtio_init_vqs(struct mei_virtio_hw *hw,
struct virtio_device *vdev)
{
struct virtqueue *vqs[2];
vq_callback_t *cbs[] = {
mei_virtio_data_in,
mei_virtio_data_out,
};
static const char * const names[] = {
"in",
"out",
};
int ret;
ret = virtio_find_vqs(vdev, 2, vqs, cbs, names, NULL);
if (ret)
return ret;
hw->in = vqs[0];
hw->out = vqs[1];
return 0;
}
static const struct mei_hw_ops mei_virtio_ops = {
.fw_status = mei_virtio_fw_status,
.pg_state = mei_virtio_pg_state,
.host_is_ready = mei_virtio_host_is_ready,
.hw_is_ready = mei_virtio_hw_is_ready,
.hw_reset = mei_virtio_hw_reset,
.hw_config = mei_virtio_hw_config,
.hw_start = mei_virtio_hw_start,
.pg_in_transition = mei_virtio_pg_in_transition,
.pg_is_enabled = mei_virtio_pg_is_enabled,
.intr_clear = mei_virtio_intr_clear,
.intr_enable = mei_virtio_intr_enable,
.intr_disable = mei_virtio_intr_disable,
.synchronize_irq = mei_virtio_synchronize_irq,
.hbuf_free_slots = mei_virtio_hbuf_empty_slots,
.hbuf_is_ready = mei_virtio_hbuf_is_ready,
.hbuf_depth = mei_virtio_hbuf_depth,
.write = mei_virtio_write_message,
.rdbuf_full_slots = mei_virtio_count_full_read_slots,
.read_hdr = mei_virtio_read_hdr,
.read = mei_virtio_read,
};
static int mei_virtio_probe(struct virtio_device *vdev)
{
struct mei_virtio_hw *hw;
int ret;
hw = devm_kzalloc(&vdev->dev, sizeof(*hw), GFP_KERNEL);
if (!hw)
return -ENOMEM;
vdev->priv = hw;
INIT_WORK(&hw->intr_handler, mei_virtio_intr_handler);
ret = mei_virtio_init_vqs(hw, vdev);
if (ret)
goto vqs_failed;
virtio_cread(vdev, struct mei_virtio_cfg,
buf_depth, &hw->cfg.buf_depth);
hw->recv_buf = kzalloc(mei_slots2data(hw->cfg.buf_depth), GFP_KERNEL);
if (!hw->recv_buf) {
ret = -ENOMEM;
goto hbuf_failed;
}
atomic_set(&hw->hbuf_ready, 0);
virtio_device_ready(vdev);
mei_device_init(&hw->mdev, &vdev->dev, &mei_virtio_ops);
pm_runtime_get_noresume(&vdev->dev);
pm_runtime_set_active(&vdev->dev);
pm_runtime_enable(&vdev->dev);
ret = mei_start(&hw->mdev);
if (ret)
goto mei_start_failed;
pm_runtime_set_autosuspend_delay(&vdev->dev, MEI_VIRTIO_RPM_TIMEOUT);
pm_runtime_use_autosuspend(&vdev->dev);
ret = mei_register(&hw->mdev, &vdev->dev);
if (ret)
goto mei_failed;
pm_runtime_put(&vdev->dev);
return 0;
mei_failed:
mei_stop(&hw->mdev);
mei_start_failed:
mei_cancel_work(&hw->mdev);
mei_disable_interrupts(&hw->mdev);
kfree(hw->recv_buf);
hbuf_failed:
vdev->config->del_vqs(vdev);
vqs_failed:
return ret;
}
static int __maybe_unused mei_virtio_pm_runtime_idle(struct device *device)
{
struct virtio_device *vdev = dev_to_virtio(device);
struct mei_virtio_hw *hw = vdev->priv;
dev_dbg(&vdev->dev, "rpm: mei_virtio : runtime_idle\n");
if (!hw)
return -ENODEV;
if (mei_write_is_idle(&hw->mdev))
pm_runtime_autosuspend(device);
return -EBUSY;
}
static int __maybe_unused mei_virtio_pm_runtime_suspend(struct device *device)
{
return 0;
}
static int __maybe_unused mei_virtio_pm_runtime_resume(struct device *device)
{
return 0;
}
static int __maybe_unused mei_virtio_freeze(struct virtio_device *vdev)
{
struct mei_virtio_hw *hw = vdev->priv;
dev_dbg(&vdev->dev, "freeze\n");
if (!hw)
return -ENODEV;
mei_stop(&hw->mdev);
mei_disable_interrupts(&hw->mdev);
cancel_work_sync(&hw->intr_handler);
vdev->config->reset(vdev);
mei_virtio_remove_vqs(vdev);
return 0;
}
static int __maybe_unused mei_virtio_restore(struct virtio_device *vdev)
{
struct mei_virtio_hw *hw = vdev->priv;
int ret;
dev_dbg(&vdev->dev, "restore\n");
if (!hw)
return -ENODEV;
ret = mei_virtio_init_vqs(hw, vdev);
if (ret)
return ret;
virtio_device_ready(vdev);
ret = mei_restart(&hw->mdev);
if (ret)
return ret;
/* Start timer if stopped in suspend */
schedule_delayed_work(&hw->mdev.timer_work, HZ);
return 0;
}
static const struct dev_pm_ops mei_virtio_pm_ops = {
SET_RUNTIME_PM_OPS(mei_virtio_pm_runtime_suspend,
mei_virtio_pm_runtime_resume,
mei_virtio_pm_runtime_idle)
};
static void mei_virtio_remove(struct virtio_device *vdev)
{
struct mei_virtio_hw *hw = vdev->priv;
mei_stop(&hw->mdev);
mei_disable_interrupts(&hw->mdev);
cancel_work_sync(&hw->intr_handler);
mei_deregister(&hw->mdev);
vdev->config->reset(vdev);
mei_virtio_remove_vqs(vdev);
kfree(hw->recv_buf);
pm_runtime_disable(&vdev->dev);
}
static struct virtio_device_id id_table[] = {
{ VIRTIO_ID_MEI, VIRTIO_DEV_ANY_ID },
{ }
};
static struct virtio_driver mei_virtio_driver = {
.id_table = id_table,
.probe = mei_virtio_probe,
.remove = mei_virtio_remove,
.config_changed = mei_virtio_config_changed,
.driver = {
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
.pm = &mei_virtio_pm_ops,
},
#ifdef CONFIG_PM_SLEEP
.freeze = mei_virtio_freeze,
.restore = mei_virtio_restore,
#endif
};
module_virtio_driver(mei_virtio_driver);
MODULE_DEVICE_TABLE(virtio, id_table);
MODULE_DESCRIPTION("Virtio MEI frontend driver");
MODULE_LICENSE("GPL v2");
+14 -4
View File
@@ -1295,12 +1295,22 @@ int c_can_power_up(struct net_device *dev)
time_after(time_out, jiffies))
cpu_relax();
if (time_after(jiffies, time_out))
return -ETIMEDOUT;
if (time_after(jiffies, time_out)) {
ret = -ETIMEDOUT;
goto err_out;
}
ret = c_can_start(dev);
if (!ret)
c_can_irq_control(priv, true);
if (ret)
goto err_out;
c_can_irq_control(priv, true);
return 0;
err_out:
c_can_reset_ram(priv, false);
c_can_pm_runtime_put_sync(priv);
return ret;
}
+3 -1
View File
@@ -692,8 +692,10 @@ static int kvaser_pciefd_open(struct net_device *netdev)
return err;
err = kvaser_pciefd_bus_on(can);
if (err)
if (err) {
close_candev(netdev);
return err;
}
return 0;
}
+3 -8
View File
@@ -489,18 +489,18 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
spi->bits_per_word = 32;
ret = spi_setup(spi);
if (ret)
goto out_clk;
goto out_m_can_class_free_dev;
priv->regmap = devm_regmap_init(&spi->dev, &tcan4x5x_bus,
&spi->dev, &tcan4x5x_regmap);
if (IS_ERR(priv->regmap)) {
ret = PTR_ERR(priv->regmap);
goto out_clk;
goto out_m_can_class_free_dev;
}
ret = tcan4x5x_power_enable(priv->power, 1);
if (ret)
goto out_clk;
goto out_m_can_class_free_dev;
ret = tcan4x5x_parse_config(mcan_class);
if (ret)
@@ -519,11 +519,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
out_power:
tcan4x5x_power_enable(priv->power, 0);
out_clk:
if (!IS_ERR(mcan_class->cclk)) {
clk_disable_unprepare(mcan_class->cclk);
clk_disable_unprepare(mcan_class->hclk);
}
out_m_can_class_free_dev:
m_can_class_free_dev(mcan_class->net);
dev_err(&spi->dev, "Probe failed, err=%d\n", ret);
-1
View File
@@ -474,7 +474,6 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
netdev_dbg(dev, "arbitration lost interrupt\n");
alc = priv->read_reg(priv, SJA1000_ALC);
priv->can.can_stats.arbitration_lost++;
stats->tx_errors++;
cf->can_id |= CAN_ERR_LOSTARB;
cf->data[0] = alc & 0x1f;
}
-1
View File
@@ -604,7 +604,6 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
netdev_dbg(dev, "arbitration lost interrupt\n");
alc = readl(priv->base + SUN4I_REG_STA_ADDR);
priv->can.can_stats.arbitration_lost++;
stats->tx_errors++;
if (likely(skb)) {
cf->can_id |= CAN_ERR_LOSTARB;
cf->data[0] = (alc >> 8) & 0x1f;
+1
View File
@@ -88,6 +88,7 @@ config BNX2
config CNIC
tristate "QLogic CNIC support"
depends on PCI && (IPV6 || IPV6=n)
depends on MMU
select BNX2
select UIO
help
+1
View File
@@ -3175,6 +3175,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
GFP_KERNEL | __GFP_COMP);
if (!avail) {
CH_ALERT(adapter, "free list queue 0 initialization failed\n");
ret = -ENOMEM;
goto err;
}
if (avail < q->fl[0].size)
@@ -1206,6 +1206,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
sk_setup_caps(newsk, dst);
ctx = tls_get_ctx(lsk);
newsk->sk_destruct = ctx->sk_destruct;
newsk->sk_prot_creator = lsk->sk_prot_creator;
csk->sk = newsk;
csk->passive_reap_next = oreq;
csk->tx_chan = cxgb4_port_chan(ndev);
@@ -391,6 +391,7 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen,
csk->wr_unacked += DIV_ROUND_UP(len, 16);
enqueue_wr(csk, skb);
cxgb4_ofld_send(csk->egress_dev, skb);
skb = NULL;
chtls_set_scmd(csk);
/* Clear quiesce for Rx key */
@@ -2120,6 +2120,15 @@ workaround:
skb_copy_header(new_skb, skb);
new_skb->dev = skb->dev;
/* Copy relevant timestamp info from the old skb to the new */
if (priv->tx_tstamp) {
skb_shinfo(new_skb)->tx_flags = skb_shinfo(skb)->tx_flags;
skb_shinfo(new_skb)->hwtstamps = skb_shinfo(skb)->hwtstamps;
skb_shinfo(new_skb)->tskey = skb_shinfo(skb)->tskey;
if (skb->sk)
skb_set_owner_w(new_skb, skb->sk);
}
/* We move the headroom when we align it so we have to reset the
* network and transport header offsets relative to the new data
* pointer. The checksum offload relies on these offsets.
@@ -2127,7 +2136,6 @@ workaround:
skb_set_network_header(new_skb, skb_network_offset(skb));
skb_set_transport_header(new_skb, skb_transport_offset(skb));
/* TODO: does timestamping need the result in the old skb? */
dev_kfree_skb(skb);
*s = new_skb;
+122 -68
View File
@@ -834,7 +834,7 @@ static void release_napi(struct ibmvnic_adapter *adapter)
static int ibmvnic_login(struct net_device *netdev)
{
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
unsigned long timeout = msecs_to_jiffies(30000);
unsigned long timeout = msecs_to_jiffies(20000);
int retry_count = 0;
int retries = 10;
bool retry;
@@ -850,10 +850,8 @@ static int ibmvnic_login(struct net_device *netdev)
adapter->init_done_rc = 0;
reinit_completion(&adapter->init_done);
rc = send_login(adapter);
if (rc) {
netdev_warn(netdev, "Unable to login\n");
if (rc)
return rc;
}
if (!wait_for_completion_timeout(&adapter->init_done,
timeout)) {
@@ -940,7 +938,7 @@ static void release_resources(struct ibmvnic_adapter *adapter)
static int set_link_state(struct ibmvnic_adapter *adapter, u8 link_state)
{
struct net_device *netdev = adapter->netdev;
unsigned long timeout = msecs_to_jiffies(30000);
unsigned long timeout = msecs_to_jiffies(20000);
union ibmvnic_crq crq;
bool resend;
int rc;
@@ -1857,7 +1855,7 @@ static int do_change_param_reset(struct ibmvnic_adapter *adapter,
if (reset_state == VNIC_OPEN) {
rc = __ibmvnic_close(netdev);
if (rc)
return rc;
goto out;
}
release_resources(adapter);
@@ -1875,24 +1873,25 @@ static int do_change_param_reset(struct ibmvnic_adapter *adapter,
}
rc = ibmvnic_reset_init(adapter, true);
if (rc)
return IBMVNIC_INIT_FAILED;
if (rc) {
rc = IBMVNIC_INIT_FAILED;
goto out;
}
/* If the adapter was in PROBE state prior to the reset,
* exit here.
*/
if (reset_state == VNIC_PROBED)
return 0;
goto out;
rc = ibmvnic_login(netdev);
if (rc) {
adapter->state = reset_state;
return rc;
goto out;
}
rc = init_resources(adapter);
if (rc)
return rc;
goto out;
ibmvnic_disable_irqs(adapter);
@@ -1902,8 +1901,10 @@ static int do_change_param_reset(struct ibmvnic_adapter *adapter,
return 0;
rc = __ibmvnic_open(netdev);
if (rc)
return IBMVNIC_OPEN_FAILED;
if (rc) {
rc = IBMVNIC_OPEN_FAILED;
goto out;
}
/* refresh device's multicast list */
ibmvnic_set_multi(netdev);
@@ -1912,7 +1913,10 @@ static int do_change_param_reset(struct ibmvnic_adapter *adapter,
for (i = 0; i < adapter->req_rx_queues; i++)
napi_schedule(&adapter->napi[i]);
return 0;
out:
if (rc)
adapter->state = reset_state;
return rc;
}
/**
@@ -2015,7 +2019,6 @@ static int do_reset(struct ibmvnic_adapter *adapter,
rc = ibmvnic_login(netdev);
if (rc) {
adapter->state = reset_state;
goto out;
}
@@ -2083,6 +2086,9 @@ static int do_reset(struct ibmvnic_adapter *adapter,
rc = 0;
out:
/* restore the adapter state if reset failed */
if (rc)
adapter->state = reset_state;
rtnl_unlock();
return rc;
@@ -2115,43 +2121,46 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,
if (rc) {
netdev_err(adapter->netdev,
"Couldn't initialize crq. rc=%d\n", rc);
return rc;
goto out;
}
rc = ibmvnic_reset_init(adapter, false);
if (rc)
return rc;
goto out;
/* If the adapter was in PROBE state prior to the reset,
* exit here.
*/
if (reset_state == VNIC_PROBED)
return 0;
goto out;
rc = ibmvnic_login(netdev);
if (rc) {
adapter->state = VNIC_PROBED;
return 0;
}
if (rc)
goto out;
rc = init_resources(adapter);
if (rc)
return rc;
goto out;
ibmvnic_disable_irqs(adapter);
adapter->state = VNIC_CLOSED;
if (reset_state == VNIC_CLOSED)
return 0;
goto out;
rc = __ibmvnic_open(netdev);
if (rc)
return IBMVNIC_OPEN_FAILED;
if (rc) {
rc = IBMVNIC_OPEN_FAILED;
goto out;
}
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev);
call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev);
return 0;
out:
/* restore adapter state if reset failed */
if (rc)
adapter->state = reset_state;
return rc;
}
static struct ibmvnic_rwi *get_next_rwi(struct ibmvnic_adapter *adapter)
@@ -2173,17 +2182,6 @@ static struct ibmvnic_rwi *get_next_rwi(struct ibmvnic_adapter *adapter)
return rwi;
}
static void free_all_rwi(struct ibmvnic_adapter *adapter)
{
struct ibmvnic_rwi *rwi;
rwi = get_next_rwi(adapter);
while (rwi) {
kfree(rwi);
rwi = get_next_rwi(adapter);
}
}
static void __ibmvnic_reset(struct work_struct *work)
{
struct ibmvnic_rwi *rwi;
@@ -2241,20 +2239,23 @@ static void __ibmvnic_reset(struct work_struct *work)
rc = do_hard_reset(adapter, rwi, reset_state);
rtnl_unlock();
}
if (rc) {
/* give backing device time to settle down */
netdev_dbg(adapter->netdev,
"[S:%d] Hard reset failed, waiting 60 secs\n",
adapter->state);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(60 * HZ);
}
} else if (!(rwi->reset_reason == VNIC_RESET_FATAL &&
adapter->from_passive_init)) {
rc = do_reset(adapter, rwi, reset_state);
}
kfree(rwi);
if (rc == IBMVNIC_OPEN_FAILED) {
if (list_empty(&adapter->rwi_list))
adapter->state = VNIC_CLOSED;
else
adapter->state = reset_state;
rc = 0;
} else if (rc && rc != IBMVNIC_INIT_FAILED &&
!adapter->force_reset_recovery)
break;
adapter->last_reset_time = jiffies;
if (rc)
netdev_dbg(adapter->netdev, "Reset failed, rc=%d\n", rc);
rwi = get_next_rwi(adapter);
@@ -2268,11 +2269,6 @@ static void __ibmvnic_reset(struct work_struct *work)
complete(&adapter->reset_done);
}
if (rc) {
netdev_dbg(adapter->netdev, "Reset failed\n");
free_all_rwi(adapter);
}
clear_bit_unlock(0, &adapter->resetting);
}
@@ -2360,7 +2356,13 @@ static void ibmvnic_tx_timeout(struct net_device *dev, unsigned int txqueue)
"Adapter is resetting, skip timeout reset\n");
return;
}
/* No queuing up reset until at least 5 seconds (default watchdog val)
* after last reset
*/
if (time_before(jiffies, (adapter->last_reset_time + dev->watchdog_timeo))) {
netdev_dbg(dev, "Not yet time to tx timeout.\n");
return;
}
ibmvnic_reset(adapter, VNIC_RESET_TIMEOUT);
}
@@ -2402,6 +2404,12 @@ restart_poll:
if (!pending_scrq(adapter, adapter->rx_scrq[scrq_num]))
break;
/* The queue entry at the current index is peeked at above
* to determine that there is a valid descriptor awaiting
* processing. We want to be sure that the current slot
* holds a valid descriptor before reading its contents.
*/
dma_rmb();
next = ibmvnic_next_scrq(adapter, adapter->rx_scrq[scrq_num]);
rx_buff =
(struct ibmvnic_rx_buff *)be64_to_cpu(next->
@@ -2860,15 +2868,26 @@ static int reset_one_sub_crq_queue(struct ibmvnic_adapter *adapter,
{
int rc;
if (!scrq) {
netdev_dbg(adapter->netdev,
"Invalid scrq reset. irq (%d) or msgs (%p).\n",
scrq->irq, scrq->msgs);
return -EINVAL;
}
if (scrq->irq) {
free_irq(scrq->irq, scrq);
irq_dispose_mapping(scrq->irq);
scrq->irq = 0;
}
memset(scrq->msgs, 0, 4 * PAGE_SIZE);
atomic_set(&scrq->used, 0);
scrq->cur = 0;
if (scrq->msgs) {
memset(scrq->msgs, 0, 4 * PAGE_SIZE);
atomic_set(&scrq->used, 0);
scrq->cur = 0;
} else {
netdev_dbg(adapter->netdev, "Invalid scrq reset\n");
return -EINVAL;
}
rc = h_reg_sub_crq(adapter->vdev->unit_address, scrq->msg_token,
4 * PAGE_SIZE, &scrq->crq_num, &scrq->hw_irq);
@@ -3100,13 +3119,18 @@ restart_loop:
unsigned int pool = scrq->pool_index;
int num_entries = 0;
/* The queue entry at the current index is peeked at above
* to determine that there is a valid descriptor awaiting
* processing. We want to be sure that the current slot
* holds a valid descriptor before reading its contents.
*/
dma_rmb();
next = ibmvnic_next_scrq(adapter, scrq);
for (i = 0; i < next->tx_comp.num_comps; i++) {
if (next->tx_comp.rcs[i]) {
if (next->tx_comp.rcs[i])
dev_err(dev, "tx error %x\n",
next->tx_comp.rcs[i]);
continue;
}
index = be32_to_cpu(next->tx_comp.correlators[i]);
if (index & IBMVNIC_TSO_POOL_MASK) {
tx_pool = &adapter->tso_pool[pool];
@@ -3500,6 +3524,11 @@ static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *adapter,
}
spin_unlock_irqrestore(&scrq->lock, flags);
/* Ensure that the entire buffer descriptor has been
* loaded before reading its contents
*/
dma_rmb();
return entry;
}
@@ -3721,15 +3750,16 @@ static int send_login(struct ibmvnic_adapter *adapter)
struct ibmvnic_login_rsp_buffer *login_rsp_buffer;
struct ibmvnic_login_buffer *login_buffer;
struct device *dev = &adapter->vdev->dev;
struct vnic_login_client_data *vlcd;
dma_addr_t rsp_buffer_token;
dma_addr_t buffer_token;
size_t rsp_buffer_size;
union ibmvnic_crq crq;
int client_data_len;
size_t buffer_size;
__be64 *tx_list_p;
__be64 *rx_list_p;
int client_data_len;
struct vnic_login_client_data *vlcd;
int rc;
int i;
if (!adapter->tx_scrq || !adapter->rx_scrq) {
@@ -3833,16 +3863,25 @@ static int send_login(struct ibmvnic_adapter *adapter)
crq.login.cmd = LOGIN;
crq.login.ioba = cpu_to_be32(buffer_token);
crq.login.len = cpu_to_be32(buffer_size);
ibmvnic_send_crq(adapter, &crq);
adapter->login_pending = true;
rc = ibmvnic_send_crq(adapter, &crq);
if (rc) {
adapter->login_pending = false;
netdev_err(adapter->netdev, "Failed to send login, rc=%d\n", rc);
goto buf_rsp_map_failed;
}
return 0;
buf_rsp_map_failed:
kfree(login_rsp_buffer);
adapter->login_rsp_buf = NULL;
buf_rsp_alloc_failed:
dma_unmap_single(dev, buffer_token, buffer_size, DMA_TO_DEVICE);
buf_map_failed:
kfree(login_buffer);
adapter->login_buf = NULL;
buf_alloc_failed:
return -1;
}
@@ -4385,6 +4424,15 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
u64 *size_array;
int i;
/* CHECK: Test/set of login_pending does not need to be atomic
* because only ibmvnic_tasklet tests/clears this.
*/
if (!adapter->login_pending) {
netdev_warn(netdev, "Ignoring unexpected login response\n");
return 0;
}
adapter->login_pending = false;
dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz,
DMA_TO_DEVICE);
dma_unmap_single(dev, adapter->login_rsp_buf_token,
@@ -4414,7 +4462,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
adapter->req_rx_add_queues !=
be32_to_cpu(login_rsp->num_rxadd_subcrqs))) {
dev_err(dev, "FATAL: Inconsistent login and login rsp\n");
ibmvnic_remove(adapter->vdev);
ibmvnic_reset(adapter, VNIC_RESET_FATAL);
return -EIO;
}
size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
@@ -4756,6 +4804,11 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
case IBMVNIC_CRQ_INIT:
dev_info(dev, "Partner initialized\n");
adapter->from_passive_init = true;
/* Discard any stale login responses from prev reset.
* CHECK: should we clear even on INIT_COMPLETE?
*/
adapter->login_pending = false;
if (!completion_done(&adapter->init_done)) {
complete(&adapter->init_done);
adapter->init_done_rc = -EIO;
@@ -5093,7 +5146,7 @@ map_failed:
static int ibmvnic_reset_init(struct ibmvnic_adapter *adapter, bool reset)
{
struct device *dev = &adapter->vdev->dev;
unsigned long timeout = msecs_to_jiffies(30000);
unsigned long timeout = msecs_to_jiffies(20000);
u64 old_num_rx_queues, old_num_tx_queues;
int rc;
@@ -5188,6 +5241,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
dev_set_drvdata(&dev->dev, netdev);
adapter->vdev = dev;
adapter->netdev = netdev;
adapter->login_pending = false;
ether_addr_copy(adapter->mac_addr, mac_addr_p);
ether_addr_copy(netdev->dev_addr, adapter->mac_addr);
@@ -5251,7 +5305,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
adapter->state = VNIC_PROBED;
adapter->wait_for_reset = false;
adapter->last_reset_time = jiffies;
return 0;
ibmvnic_register_fail:
+3
View File
@@ -1086,6 +1086,9 @@ struct ibmvnic_adapter {
struct delayed_work ibmvnic_delayed_reset;
unsigned long resetting;
bool napi_enabled, from_passive_init;
bool login_pending;
/* last device reset time */
unsigned long last_reset_time;
bool failover_pending;
bool force_reset_recovery;
@@ -4426,6 +4426,7 @@ static int mvpp2_open(struct net_device *dev)
if (!valid) {
netdev_err(port->dev,
"invalid configuration: no dt or link IRQ");
err = -ENOENT;
goto err_free_irq;
}

Some files were not shown because too many files have changed in this diff Show More