nfsd: merge stable fix into main nfsd branch
This commit is contained in:
commit
60709c093e
@ -10195,7 +10195,6 @@ F: drivers/media/tuners/qt1010*
|
||||
QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
|
||||
M: QCA ath9k Development <ath9k-devel@qca.qualcomm.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ath9k-devel@lists.ath9k.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/ath9k
|
||||
S: Supported
|
||||
F: drivers/net/wireless/ath/ath9k/
|
||||
@ -13066,7 +13065,7 @@ F: drivers/input/serio/userio.c
|
||||
F: include/uapi/linux/userio.h
|
||||
|
||||
VIRTIO CONSOLE DRIVER
|
||||
M: Amit Shah <amit.shah@redhat.com>
|
||||
M: Amit Shah <amit@kernel.org>
|
||||
L: virtualization@lists.linux-foundation.org
|
||||
S: Maintained
|
||||
F: drivers/char/virtio_console.c
|
||||
|
4
Makefile
4
Makefile
@ -1,7 +1,7 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 10
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION = -rc7
|
||||
NAME = Fearless Coyote
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@ -797,7 +797,7 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types)
|
||||
KBUILD_ARFLAGS := $(call ar-option,D)
|
||||
|
||||
# check for 'asm goto'
|
||||
ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
|
||||
ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y)
|
||||
KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO
|
||||
KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO
|
||||
endif
|
||||
|
@ -193,15 +193,16 @@ AES_ENTRY(aes_cbc_encrypt)
|
||||
cbz w6, .Lcbcencloop
|
||||
|
||||
ld1 {v0.16b}, [x5] /* get iv */
|
||||
enc_prepare w3, x2, x5
|
||||
enc_prepare w3, x2, x6
|
||||
|
||||
.Lcbcencloop:
|
||||
ld1 {v1.16b}, [x1], #16 /* get next pt block */
|
||||
eor v0.16b, v0.16b, v1.16b /* ..and xor with iv */
|
||||
encrypt_block v0, w3, x2, x5, w6
|
||||
encrypt_block v0, w3, x2, x6, w7
|
||||
st1 {v0.16b}, [x0], #16
|
||||
subs w4, w4, #1
|
||||
bne .Lcbcencloop
|
||||
st1 {v0.16b}, [x5] /* return iv */
|
||||
ret
|
||||
AES_ENDPROC(aes_cbc_encrypt)
|
||||
|
||||
@ -211,7 +212,7 @@ AES_ENTRY(aes_cbc_decrypt)
|
||||
cbz w6, .LcbcdecloopNx
|
||||
|
||||
ld1 {v7.16b}, [x5] /* get iv */
|
||||
dec_prepare w3, x2, x5
|
||||
dec_prepare w3, x2, x6
|
||||
|
||||
.LcbcdecloopNx:
|
||||
#if INTERLEAVE >= 2
|
||||
@ -248,7 +249,7 @@ AES_ENTRY(aes_cbc_decrypt)
|
||||
.Lcbcdecloop:
|
||||
ld1 {v1.16b}, [x1], #16 /* get next ct block */
|
||||
mov v0.16b, v1.16b /* ...and copy to v0 */
|
||||
decrypt_block v0, w3, x2, x5, w6
|
||||
decrypt_block v0, w3, x2, x6, w7
|
||||
eor v0.16b, v0.16b, v7.16b /* xor with iv => pt */
|
||||
mov v7.16b, v1.16b /* ct is next iv */
|
||||
st1 {v0.16b}, [x0], #16
|
||||
@ -256,6 +257,7 @@ AES_ENTRY(aes_cbc_decrypt)
|
||||
bne .Lcbcdecloop
|
||||
.Lcbcdecout:
|
||||
FRAME_POP
|
||||
st1 {v7.16b}, [x5] /* return iv */
|
||||
ret
|
||||
AES_ENDPROC(aes_cbc_decrypt)
|
||||
|
||||
@ -267,24 +269,15 @@ AES_ENDPROC(aes_cbc_decrypt)
|
||||
|
||||
AES_ENTRY(aes_ctr_encrypt)
|
||||
FRAME_PUSH
|
||||
cbnz w6, .Lctrfirst /* 1st time around? */
|
||||
umov x5, v4.d[1] /* keep swabbed ctr in reg */
|
||||
rev x5, x5
|
||||
#if INTERLEAVE >= 2
|
||||
cmn w5, w4 /* 32 bit overflow? */
|
||||
bcs .Lctrinc
|
||||
add x5, x5, #1 /* increment BE ctr */
|
||||
b .LctrincNx
|
||||
#else
|
||||
b .Lctrinc
|
||||
#endif
|
||||
.Lctrfirst:
|
||||
cbz w6, .Lctrnotfirst /* 1st time around? */
|
||||
enc_prepare w3, x2, x6
|
||||
ld1 {v4.16b}, [x5]
|
||||
umov x5, v4.d[1] /* keep swabbed ctr in reg */
|
||||
rev x5, x5
|
||||
|
||||
.Lctrnotfirst:
|
||||
umov x8, v4.d[1] /* keep swabbed ctr in reg */
|
||||
rev x8, x8
|
||||
#if INTERLEAVE >= 2
|
||||
cmn w5, w4 /* 32 bit overflow? */
|
||||
cmn w8, w4 /* 32 bit overflow? */
|
||||
bcs .Lctrloop
|
||||
.LctrloopNx:
|
||||
subs w4, w4, #INTERLEAVE
|
||||
@ -292,11 +285,11 @@ AES_ENTRY(aes_ctr_encrypt)
|
||||
#if INTERLEAVE == 2
|
||||
mov v0.8b, v4.8b
|
||||
mov v1.8b, v4.8b
|
||||
rev x7, x5
|
||||
add x5, x5, #1
|
||||
rev x7, x8
|
||||
add x8, x8, #1
|
||||
ins v0.d[1], x7
|
||||
rev x7, x5
|
||||
add x5, x5, #1
|
||||
rev x7, x8
|
||||
add x8, x8, #1
|
||||
ins v1.d[1], x7
|
||||
ld1 {v2.16b-v3.16b}, [x1], #32 /* get 2 input blocks */
|
||||
do_encrypt_block2x
|
||||
@ -305,7 +298,7 @@ AES_ENTRY(aes_ctr_encrypt)
|
||||
st1 {v0.16b-v1.16b}, [x0], #32
|
||||
#else
|
||||
ldr q8, =0x30000000200000001 /* addends 1,2,3[,0] */
|
||||
dup v7.4s, w5
|
||||
dup v7.4s, w8
|
||||
mov v0.16b, v4.16b
|
||||
add v7.4s, v7.4s, v8.4s
|
||||
mov v1.16b, v4.16b
|
||||
@ -323,18 +316,12 @@ AES_ENTRY(aes_ctr_encrypt)
|
||||
eor v2.16b, v7.16b, v2.16b
|
||||
eor v3.16b, v5.16b, v3.16b
|
||||
st1 {v0.16b-v3.16b}, [x0], #64
|
||||
add x5, x5, #INTERLEAVE
|
||||
add x8, x8, #INTERLEAVE
|
||||
#endif
|
||||
cbz w4, .LctroutNx
|
||||
.LctrincNx:
|
||||
rev x7, x5
|
||||
rev x7, x8
|
||||
ins v4.d[1], x7
|
||||
cbz w4, .Lctrout
|
||||
b .LctrloopNx
|
||||
.LctroutNx:
|
||||
sub x5, x5, #1
|
||||
rev x7, x5
|
||||
ins v4.d[1], x7
|
||||
b .Lctrout
|
||||
.Lctr1x:
|
||||
adds w4, w4, #INTERLEAVE
|
||||
beq .Lctrout
|
||||
@ -342,30 +329,39 @@ AES_ENTRY(aes_ctr_encrypt)
|
||||
.Lctrloop:
|
||||
mov v0.16b, v4.16b
|
||||
encrypt_block v0, w3, x2, x6, w7
|
||||
|
||||
adds x8, x8, #1 /* increment BE ctr */
|
||||
rev x7, x8
|
||||
ins v4.d[1], x7
|
||||
bcs .Lctrcarry /* overflow? */
|
||||
|
||||
.Lctrcarrydone:
|
||||
subs w4, w4, #1
|
||||
bmi .Lctrhalfblock /* blocks < 0 means 1/2 block */
|
||||
ld1 {v3.16b}, [x1], #16
|
||||
eor v3.16b, v0.16b, v3.16b
|
||||
st1 {v3.16b}, [x0], #16
|
||||
beq .Lctrout
|
||||
.Lctrinc:
|
||||
adds x5, x5, #1 /* increment BE ctr */
|
||||
rev x7, x5
|
||||
ins v4.d[1], x7
|
||||
bcc .Lctrloop /* no overflow? */
|
||||
bne .Lctrloop
|
||||
|
||||
.Lctrout:
|
||||
st1 {v4.16b}, [x5] /* return next CTR value */
|
||||
FRAME_POP
|
||||
ret
|
||||
|
||||
.Lctrhalfblock:
|
||||
ld1 {v3.8b}, [x1]
|
||||
eor v3.8b, v0.8b, v3.8b
|
||||
st1 {v3.8b}, [x0]
|
||||
FRAME_POP
|
||||
ret
|
||||
|
||||
.Lctrcarry:
|
||||
umov x7, v4.d[0] /* load upper word of ctr */
|
||||
rev x7, x7 /* ... to handle the carry */
|
||||
add x7, x7, #1
|
||||
rev x7, x7
|
||||
ins v4.d[0], x7
|
||||
b .Lctrloop
|
||||
.Lctrhalfblock:
|
||||
ld1 {v3.8b}, [x1]
|
||||
eor v3.8b, v0.8b, v3.8b
|
||||
st1 {v3.8b}, [x0]
|
||||
.Lctrout:
|
||||
FRAME_POP
|
||||
ret
|
||||
b .Lctrcarrydone
|
||||
AES_ENDPROC(aes_ctr_encrypt)
|
||||
.ltorg
|
||||
|
||||
|
@ -164,7 +164,6 @@ config PPC
|
||||
select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE
|
||||
select HAVE_ARCH_HARDENED_USERCOPY
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_CC_STACKPROTECTOR
|
||||
|
||||
config GENERIC_CSUM
|
||||
def_bool CPU_LITTLE_ENDIAN
|
||||
@ -484,6 +483,7 @@ config RELOCATABLE
|
||||
bool "Build a relocatable kernel"
|
||||
depends on (PPC64 && !COMPILE_TEST) || (FLATMEM && (44x || FSL_BOOKE))
|
||||
select NONSTATIC_KERNEL
|
||||
select MODULE_REL_CRCS if MODVERSIONS
|
||||
help
|
||||
This builds a kernel image that is capable of running at the
|
||||
location the kernel is loaded at. For ppc32, there is no any
|
||||
|
@ -23,7 +23,9 @@ static __always_inline bool cpu_has_feature(unsigned long feature)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifndef __clang__ /* clang can't cope with this */
|
||||
BUILD_BUG_ON(!__builtin_constant_p(feature));
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
|
||||
if (!static_key_initialized) {
|
||||
|
@ -160,7 +160,9 @@ static __always_inline bool mmu_has_feature(unsigned long feature)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifndef __clang__ /* clang can't cope with this */
|
||||
BUILD_BUG_ON(!__builtin_constant_p(feature));
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
|
||||
if (!static_key_initialized) {
|
||||
|
@ -90,9 +90,5 @@ static inline int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sec
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64)
|
||||
#define ARCH_RELOCATES_KCRCTAB
|
||||
#define reloc_start PHYSICAL_START
|
||||
#endif
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_MODULE_H */
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* GCC stack protector support.
|
||||
*
|
||||
* Stack protector works by putting predefined pattern at the start of
|
||||
* the stack frame and verifying that it hasn't been overwritten when
|
||||
* returning from the function. The pattern is called stack canary
|
||||
* and gcc expects it to be defined by a global variable called
|
||||
* "__stack_chk_guard" on PPC. This unfortunately means that on SMP
|
||||
* we cannot have a different canary value per task.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_STACKPROTECTOR_H
|
||||
#define _ASM_STACKPROTECTOR_H
|
||||
|
||||
#include <linux/random.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/reg.h>
|
||||
|
||||
extern unsigned long __stack_chk_guard;
|
||||
|
||||
/*
|
||||
* Initialize the stackprotector canary value.
|
||||
*
|
||||
* NOTE: this must only be called from functions that never return,
|
||||
* and it must always be inlined.
|
||||
*/
|
||||
static __always_inline void boot_init_stack_canary(void)
|
||||
{
|
||||
unsigned long canary;
|
||||
|
||||
/* Try to get a semi random initial value. */
|
||||
get_random_bytes(&canary, sizeof(canary));
|
||||
canary ^= mftb();
|
||||
canary ^= LINUX_VERSION_CODE;
|
||||
|
||||
current->stack_canary = canary;
|
||||
__stack_chk_guard = current->stack_canary;
|
||||
}
|
||||
|
||||
#endif /* _ASM_STACKPROTECTOR_H */
|
@ -19,10 +19,6 @@ CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
|
||||
CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
|
||||
CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
|
||||
|
||||
# -fstack-protector triggers protection checks in this code,
|
||||
# but it is being used too early to link to meaningful stack_chk logic.
|
||||
CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector)
|
||||
|
||||
ifdef CONFIG_FUNCTION_TRACER
|
||||
# Do not trace early boot code
|
||||
CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
|
||||
|
@ -91,9 +91,6 @@ int main(void)
|
||||
DEFINE(TI_livepatch_sp, offsetof(struct thread_info, livepatch_sp));
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
||||
DEFINE(TSK_STACK_CANARY, offsetof(struct task_struct, stack_canary));
|
||||
#endif
|
||||
DEFINE(KSP, offsetof(struct thread_struct, ksp));
|
||||
DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
|
||||
#ifdef CONFIG_BOOKE
|
||||
|
@ -545,7 +545,7 @@ static void *eeh_pe_detach_dev(void *data, void *userdata)
|
||||
static void *__eeh_clear_pe_frozen_state(void *data, void *flag)
|
||||
{
|
||||
struct eeh_pe *pe = (struct eeh_pe *)data;
|
||||
bool *clear_sw_state = flag;
|
||||
bool clear_sw_state = *(bool *)flag;
|
||||
int i, rc = 1;
|
||||
|
||||
for (i = 0; rc && i < 3; i++)
|
||||
|
@ -674,11 +674,7 @@ BEGIN_FTR_SECTION
|
||||
mtspr SPRN_SPEFSCR,r0 /* restore SPEFSCR reg */
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_SPE)
|
||||
#endif /* CONFIG_SPE */
|
||||
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
|
||||
lwz r0,TSK_STACK_CANARY(r2)
|
||||
lis r4,__stack_chk_guard@ha
|
||||
stw r0,__stack_chk_guard@l(r4)
|
||||
#endif
|
||||
|
||||
lwz r0,_CCR(r1)
|
||||
mtcrf 0xFF,r0
|
||||
/* r3-r12 are destroyed -- Cort */
|
||||
|
@ -286,14 +286,6 @@ static void dedotify_versions(struct modversion_info *vers,
|
||||
for (end = (void *)vers + size; vers < end; vers++)
|
||||
if (vers->name[0] == '.') {
|
||||
memmove(vers->name, vers->name+1, strlen(vers->name));
|
||||
#ifdef ARCH_RELOCATES_KCRCTAB
|
||||
/* The TOC symbol has no CRC computed. To avoid CRC
|
||||
* check failing, we must force it to the expected
|
||||
* value (see CRC check in module.c).
|
||||
*/
|
||||
if (!strcmp(vers->name, "TOC."))
|
||||
vers->crc = -(unsigned long)reloc_start;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,12 +64,6 @@
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/kdebug.h>
|
||||
|
||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
||||
#include <linux/stackprotector.h>
|
||||
unsigned long __stack_chk_guard __read_mostly;
|
||||
EXPORT_SYMBOL(__stack_chk_guard);
|
||||
#endif
|
||||
|
||||
/* Transactional Memory debug */
|
||||
#ifdef TM_DEBUG_SW
|
||||
#define TM_DEBUG(x...) printk(KERN_INFO x)
|
||||
|
@ -2834,6 +2834,9 @@ static void __init prom_find_boot_cpu(void)
|
||||
|
||||
cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
|
||||
|
||||
if (!PHANDLE_VALID(cpu_pkg))
|
||||
return;
|
||||
|
||||
prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
|
||||
prom.cpu = be32_to_cpu(rval);
|
||||
|
||||
|
@ -65,7 +65,7 @@ int radix__map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
if (!pmdp)
|
||||
return -ENOMEM;
|
||||
if (map_page_size == PMD_SIZE) {
|
||||
ptep = (pte_t *)pudp;
|
||||
ptep = pmdp_ptep(pmdp);
|
||||
goto set_the_pte;
|
||||
}
|
||||
ptep = pte_alloc_kernel(pmdp, ea);
|
||||
@ -90,7 +90,7 @@ int radix__map_kernel_page(unsigned long ea, unsigned long pa,
|
||||
}
|
||||
pmdp = pmd_offset(pudp, ea);
|
||||
if (map_page_size == PMD_SIZE) {
|
||||
ptep = (pte_t *)pudp;
|
||||
ptep = pmdp_ptep(pmdp);
|
||||
goto set_the_pte;
|
||||
}
|
||||
if (!pmd_present(*pmdp)) {
|
||||
|
@ -35,15 +35,15 @@ void __tsb_context_switch(unsigned long pgd_pa,
|
||||
static inline void tsb_context_switch(struct mm_struct *mm)
|
||||
{
|
||||
__tsb_context_switch(__pa(mm->pgd),
|
||||
&mm->context.tsb_block[0],
|
||||
&mm->context.tsb_block[MM_TSB_BASE],
|
||||
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
|
||||
(mm->context.tsb_block[1].tsb ?
|
||||
&mm->context.tsb_block[1] :
|
||||
(mm->context.tsb_block[MM_TSB_HUGE].tsb ?
|
||||
&mm->context.tsb_block[MM_TSB_HUGE] :
|
||||
NULL)
|
||||
#else
|
||||
NULL
|
||||
#endif
|
||||
, __pa(&mm->context.tsb_descr[0]));
|
||||
, __pa(&mm->context.tsb_descr[MM_TSB_BASE]));
|
||||
}
|
||||
|
||||
void tsb_grow(struct mm_struct *mm,
|
||||
|
@ -1021,7 +1021,7 @@ static void __init alloc_one_queue(unsigned long *pa_ptr, unsigned long qmask)
|
||||
unsigned long order = get_order(size);
|
||||
unsigned long p;
|
||||
|
||||
p = __get_free_pages(GFP_KERNEL, order);
|
||||
p = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
|
||||
if (!p) {
|
||||
prom_printf("SUN4V: Error, cannot allocate queue.\n");
|
||||
prom_halt();
|
||||
|
@ -43,8 +43,8 @@ static const char poweroff_msg[32] __attribute__((aligned(32))) =
|
||||
"Linux powering off";
|
||||
static const char rebooting_msg[32] __attribute__((aligned(32))) =
|
||||
"Linux rebooting";
|
||||
static const char panicing_msg[32] __attribute__((aligned(32))) =
|
||||
"Linux panicing";
|
||||
static const char panicking_msg[32] __attribute__((aligned(32))) =
|
||||
"Linux panicking";
|
||||
|
||||
static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused)
|
||||
{
|
||||
@ -76,7 +76,7 @@ static struct notifier_block sstate_reboot_notifier = {
|
||||
|
||||
static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr)
|
||||
{
|
||||
do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg);
|
||||
do_set_sstate(HV_SOFT_STATE_TRANSITION, panicking_msg);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
@ -2051,6 +2051,73 @@ void sun4v_resum_overflow(struct pt_regs *regs)
|
||||
atomic_inc(&sun4v_resum_oflow_cnt);
|
||||
}
|
||||
|
||||
/* Given a set of registers, get the virtual addressi that was being accessed
|
||||
* by the faulting instructions at tpc.
|
||||
*/
|
||||
static unsigned long sun4v_get_vaddr(struct pt_regs *regs)
|
||||
{
|
||||
unsigned int insn;
|
||||
|
||||
if (!copy_from_user(&insn, (void __user *)regs->tpc, 4)) {
|
||||
return compute_effective_address(regs, insn,
|
||||
(insn >> 25) & 0x1f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Attempt to handle non-resumable errors generated from userspace.
|
||||
* Returns true if the signal was handled, false otherwise.
|
||||
*/
|
||||
bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,
|
||||
struct sun4v_error_entry *ent) {
|
||||
|
||||
unsigned int attrs = ent->err_attrs;
|
||||
|
||||
if (attrs & SUN4V_ERR_ATTRS_MEMORY) {
|
||||
unsigned long addr = ent->err_raddr;
|
||||
siginfo_t info;
|
||||
|
||||
if (addr == ~(u64)0) {
|
||||
/* This seems highly unlikely to ever occur */
|
||||
pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory error detected in unknown location!\n");
|
||||
} else {
|
||||
unsigned long page_cnt = DIV_ROUND_UP(ent->err_size,
|
||||
PAGE_SIZE);
|
||||
|
||||
/* Break the unfortunate news. */
|
||||
pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory failed at %016lX\n",
|
||||
addr);
|
||||
pr_emerg("SUN4V NON-RECOVERABLE ERROR: Claiming %lu ages.\n",
|
||||
page_cnt);
|
||||
|
||||
while (page_cnt-- > 0) {
|
||||
if (pfn_valid(addr >> PAGE_SHIFT))
|
||||
get_page(pfn_to_page(addr >> PAGE_SHIFT));
|
||||
addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
info.si_signo = SIGKILL;
|
||||
info.si_errno = 0;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (attrs & SUN4V_ERR_ATTRS_PIO) {
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_code = BUS_ADRERR;
|
||||
info.si_addr = (void __user *)sun4v_get_vaddr(regs);
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Default to doing nothing */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate.
|
||||
* Log the event, clear the first word of the entry, and die.
|
||||
*/
|
||||
@ -2075,6 +2142,12 @@ void sun4v_nonresum_error(struct pt_regs *regs, unsigned long offset)
|
||||
|
||||
put_cpu();
|
||||
|
||||
if (!(regs->tstate & TSTATE_PRIV) &&
|
||||
sun4v_nonresum_error_user_handled(regs, &local_copy)) {
|
||||
/* DON'T PANIC: This userspace error was handled. */
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/* Check for the special PCI poke sequence. */
|
||||
if (pci_poke_in_progress && pci_poke_cpu == cpu) {
|
||||
|
@ -161,7 +161,13 @@ static u64 rapl_timer_ms;
|
||||
|
||||
static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
|
||||
{
|
||||
return rapl_pmus->pmus[topology_logical_package_id(cpu)];
|
||||
unsigned int pkgid = topology_logical_package_id(cpu);
|
||||
|
||||
/*
|
||||
* The unsigned check also catches the '-1' return value for non
|
||||
* existent mappings in the topology map.
|
||||
*/
|
||||
return pkgid < rapl_pmus->maxpkg ? rapl_pmus->pmus[pkgid] : NULL;
|
||||
}
|
||||
|
||||
static inline u64 rapl_read_counter(struct perf_event *event)
|
||||
@ -402,6 +408,8 @@ static int rapl_pmu_event_init(struct perf_event *event)
|
||||
|
||||
/* must be done before validate_group */
|
||||
pmu = cpu_to_rapl_pmu(event->cpu);
|
||||
if (!pmu)
|
||||
return -EINVAL;
|
||||
event->cpu = pmu->cpu;
|
||||
event->pmu_private = pmu;
|
||||
event->hw.event_base = msr;
|
||||
@ -585,6 +593,20 @@ static int rapl_cpu_online(unsigned int cpu)
|
||||
struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
|
||||
int target;
|
||||
|
||||
if (!pmu) {
|
||||
pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
|
||||
if (!pmu)
|
||||
return -ENOMEM;
|
||||
|
||||
raw_spin_lock_init(&pmu->lock);
|
||||
INIT_LIST_HEAD(&pmu->active_list);
|
||||
pmu->pmu = &rapl_pmus->pmu;
|
||||
pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
|
||||
rapl_hrtimer_init(pmu);
|
||||
|
||||
rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if there is an online cpu in the package which collects rapl
|
||||
* events already.
|
||||
@ -598,27 +620,6 @@ static int rapl_cpu_online(unsigned int cpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rapl_cpu_prepare(unsigned int cpu)
|
||||
{
|
||||
struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
|
||||
|
||||
if (pmu)
|
||||
return 0;
|
||||
|
||||
pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
|
||||
if (!pmu)
|
||||
return -ENOMEM;
|
||||
|
||||
raw_spin_lock_init(&pmu->lock);
|
||||
INIT_LIST_HEAD(&pmu->active_list);
|
||||
pmu->pmu = &rapl_pmus->pmu;
|
||||
pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
|
||||
pmu->cpu = -1;
|
||||
rapl_hrtimer_init(pmu);
|
||||
rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rapl_check_hw_unit(bool apply_quirk)
|
||||
{
|
||||
u64 msr_rapl_power_unit_bits;
|
||||
@ -803,29 +804,21 @@ static int __init rapl_pmu_init(void)
|
||||
/*
|
||||
* Install callbacks. Core will call them for each online cpu.
|
||||
*/
|
||||
|
||||
ret = cpuhp_setup_state(CPUHP_PERF_X86_RAPL_PREP, "perf/x86/rapl:prepare",
|
||||
rapl_cpu_prepare, NULL);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_RAPL_ONLINE,
|
||||
"perf/x86/rapl:online",
|
||||
rapl_cpu_online, rapl_cpu_offline);
|
||||
if (ret)
|
||||
goto out1;
|
||||
goto out;
|
||||
|
||||
ret = perf_pmu_register(&rapl_pmus->pmu, "power", -1);
|
||||
if (ret)
|
||||
goto out2;
|
||||
goto out1;
|
||||
|
||||
rapl_advertise();
|
||||
return 0;
|
||||
|
||||
out2:
|
||||
cpuhp_remove_state(CPUHP_AP_PERF_X86_RAPL_ONLINE);
|
||||
out1:
|
||||
cpuhp_remove_state(CPUHP_PERF_X86_RAPL_PREP);
|
||||
cpuhp_remove_state(CPUHP_AP_PERF_X86_RAPL_ONLINE);
|
||||
out:
|
||||
pr_warn("Initialization failed (%d), disabled\n", ret);
|
||||
cleanup_rapl_pmus();
|
||||
@ -836,7 +829,6 @@ module_init(rapl_pmu_init);
|
||||
static void __exit intel_rapl_exit(void)
|
||||
{
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_RAPL_ONLINE);
|
||||
cpuhp_remove_state_nocalls(CPUHP_PERF_X86_RAPL_PREP);
|
||||
perf_pmu_unregister(&rapl_pmus->pmu);
|
||||
cleanup_rapl_pmus();
|
||||
}
|
||||
|
@ -100,7 +100,13 @@ ssize_t uncore_event_show(struct kobject *kobj,
|
||||
|
||||
struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
|
||||
{
|
||||
return pmu->boxes[topology_logical_package_id(cpu)];
|
||||
unsigned int pkgid = topology_logical_package_id(cpu);
|
||||
|
||||
/*
|
||||
* The unsigned check also catches the '-1' return value for non
|
||||
* existent mappings in the topology map.
|
||||
*/
|
||||
return pkgid < max_packages ? pmu->boxes[pkgid] : NULL;
|
||||
}
|
||||
|
||||
u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
|
||||
@ -764,30 +770,6 @@ static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu)
|
||||
pmu->registered = false;
|
||||
}
|
||||
|
||||
static void __uncore_exit_boxes(struct intel_uncore_type *type, int cpu)
|
||||
{
|
||||
struct intel_uncore_pmu *pmu = type->pmus;
|
||||
struct intel_uncore_box *box;
|
||||
int i, pkg;
|
||||
|
||||
if (pmu) {
|
||||
pkg = topology_physical_package_id(cpu);
|
||||
for (i = 0; i < type->num_boxes; i++, pmu++) {
|
||||
box = pmu->boxes[pkg];
|
||||
if (box)
|
||||
uncore_box_exit(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void uncore_exit_boxes(void *dummy)
|
||||
{
|
||||
struct intel_uncore_type **types;
|
||||
|
||||
for (types = uncore_msr_uncores; *types; types++)
|
||||
__uncore_exit_boxes(*types++, smp_processor_id());
|
||||
}
|
||||
|
||||
static void uncore_free_boxes(struct intel_uncore_pmu *pmu)
|
||||
{
|
||||
int pkg;
|
||||
@ -1058,86 +1040,6 @@ static void uncore_pci_exit(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int uncore_cpu_dying(unsigned int cpu)
|
||||
{
|
||||
struct intel_uncore_type *type, **types = uncore_msr_uncores;
|
||||
struct intel_uncore_pmu *pmu;
|
||||
struct intel_uncore_box *box;
|
||||
int i, pkg;
|
||||
|
||||
pkg = topology_logical_package_id(cpu);
|
||||
for (; *types; types++) {
|
||||
type = *types;
|
||||
pmu = type->pmus;
|
||||
for (i = 0; i < type->num_boxes; i++, pmu++) {
|
||||
box = pmu->boxes[pkg];
|
||||
if (box && atomic_dec_return(&box->refcnt) == 0)
|
||||
uncore_box_exit(box);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int first_init;
|
||||
|
||||
static int uncore_cpu_starting(unsigned int cpu)
|
||||
{
|
||||
struct intel_uncore_type *type, **types = uncore_msr_uncores;
|
||||
struct intel_uncore_pmu *pmu;
|
||||
struct intel_uncore_box *box;
|
||||
int i, pkg, ncpus = 1;
|
||||
|
||||
if (first_init) {
|
||||
/*
|
||||
* On init we get the number of online cpus in the package
|
||||
* and set refcount for all of them.
|
||||
*/
|
||||
ncpus = cpumask_weight(topology_core_cpumask(cpu));
|
||||
}
|
||||
|
||||
pkg = topology_logical_package_id(cpu);
|
||||
for (; *types; types++) {
|
||||
type = *types;
|
||||
pmu = type->pmus;
|
||||
for (i = 0; i < type->num_boxes; i++, pmu++) {
|
||||
box = pmu->boxes[pkg];
|
||||
if (!box)
|
||||
continue;
|
||||
/* The first cpu on a package activates the box */
|
||||
if (atomic_add_return(ncpus, &box->refcnt) == ncpus)
|
||||
uncore_box_init(box);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uncore_cpu_prepare(unsigned int cpu)
|
||||
{
|
||||
struct intel_uncore_type *type, **types = uncore_msr_uncores;
|
||||
struct intel_uncore_pmu *pmu;
|
||||
struct intel_uncore_box *box;
|
||||
int i, pkg;
|
||||
|
||||
pkg = topology_logical_package_id(cpu);
|
||||
for (; *types; types++) {
|
||||
type = *types;
|
||||
pmu = type->pmus;
|
||||
for (i = 0; i < type->num_boxes; i++, pmu++) {
|
||||
if (pmu->boxes[pkg])
|
||||
continue;
|
||||
/* First cpu of a package allocates the box */
|
||||
box = uncore_alloc_box(type, cpu_to_node(cpu));
|
||||
if (!box)
|
||||
return -ENOMEM;
|
||||
box->pmu = pmu;
|
||||
box->pkgid = pkg;
|
||||
pmu->boxes[pkg] = box;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_cpu,
|
||||
int new_cpu)
|
||||
{
|
||||
@ -1177,12 +1079,14 @@ static void uncore_change_context(struct intel_uncore_type **uncores,
|
||||
|
||||
static int uncore_event_cpu_offline(unsigned int cpu)
|
||||
{
|
||||
int target;
|
||||
struct intel_uncore_type *type, **types = uncore_msr_uncores;
|
||||
struct intel_uncore_pmu *pmu;
|
||||
struct intel_uncore_box *box;
|
||||
int i, pkg, target;
|
||||
|
||||
/* Check if exiting cpu is used for collecting uncore events */
|
||||
if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
|
||||
return 0;
|
||||
|
||||
goto unref;
|
||||
/* Find a new cpu to collect uncore events */
|
||||
target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
|
||||
|
||||
@ -1194,12 +1098,82 @@ static int uncore_event_cpu_offline(unsigned int cpu)
|
||||
|
||||
uncore_change_context(uncore_msr_uncores, cpu, target);
|
||||
uncore_change_context(uncore_pci_uncores, cpu, target);
|
||||
|
||||
unref:
|
||||
/* Clear the references */
|
||||
pkg = topology_logical_package_id(cpu);
|
||||
for (; *types; types++) {
|
||||
type = *types;
|
||||
pmu = type->pmus;
|
||||
for (i = 0; i < type->num_boxes; i++, pmu++) {
|
||||
box = pmu->boxes[pkg];
|
||||
if (box && atomic_dec_return(&box->refcnt) == 0)
|
||||
uncore_box_exit(box);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int allocate_boxes(struct intel_uncore_type **types,
|
||||
unsigned int pkg, unsigned int cpu)
|
||||
{
|
||||
struct intel_uncore_box *box, *tmp;
|
||||
struct intel_uncore_type *type;
|
||||
struct intel_uncore_pmu *pmu;
|
||||
LIST_HEAD(allocated);
|
||||
int i;
|
||||
|
||||
/* Try to allocate all required boxes */
|
||||
for (; *types; types++) {
|
||||
type = *types;
|
||||
pmu = type->pmus;
|
||||
for (i = 0; i < type->num_boxes; i++, pmu++) {
|
||||
if (pmu->boxes[pkg])
|
||||
continue;
|
||||
box = uncore_alloc_box(type, cpu_to_node(cpu));
|
||||
if (!box)
|
||||
goto cleanup;
|
||||
box->pmu = pmu;
|
||||
box->pkgid = pkg;
|
||||
list_add(&box->active_list, &allocated);
|
||||
}
|
||||
}
|
||||
/* Install them in the pmus */
|
||||
list_for_each_entry_safe(box, tmp, &allocated, active_list) {
|
||||
list_del_init(&box->active_list);
|
||||
box->pmu->boxes[pkg] = box;
|
||||
}
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
list_for_each_entry_safe(box, tmp, &allocated, active_list) {
|
||||
list_del_init(&box->active_list);
|
||||
kfree(box);
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int uncore_event_cpu_online(unsigned int cpu)
|
||||
{
|
||||
int target;
|
||||
struct intel_uncore_type *type, **types = uncore_msr_uncores;
|
||||
struct intel_uncore_pmu *pmu;
|
||||
struct intel_uncore_box *box;
|
||||
int i, ret, pkg, target;
|
||||
|
||||
pkg = topology_logical_package_id(cpu);
|
||||
ret = allocate_boxes(types, pkg, cpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (; *types; types++) {
|
||||
type = *types;
|
||||
pmu = type->pmus;
|
||||
for (i = 0; i < type->num_boxes; i++, pmu++) {
|
||||
box = pmu->boxes[pkg];
|
||||
if (!box && atomic_inc_return(&box->refcnt) == 1)
|
||||
uncore_box_init(box);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if there is an online cpu in the package
|
||||
@ -1389,38 +1363,16 @@ static int __init intel_uncore_init(void)
|
||||
if (cret && pret)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Install callbacks. Core will call them for each online cpu.
|
||||
*
|
||||
* The first online cpu of each package allocates and takes
|
||||
* the refcounts for all other online cpus in that package.
|
||||
* If msrs are not enabled no allocation is required and
|
||||
* uncore_cpu_prepare() is not called for each online cpu.
|
||||
*/
|
||||
if (!cret) {
|
||||
ret = cpuhp_setup_state(CPUHP_PERF_X86_UNCORE_PREP,
|
||||
"perf/x86/intel/uncore:prepare",
|
||||
uncore_cpu_prepare, NULL);
|
||||
if (ret)
|
||||
goto err;
|
||||
} else {
|
||||
cpuhp_setup_state_nocalls(CPUHP_PERF_X86_UNCORE_PREP,
|
||||
"perf/x86/intel/uncore:prepare",
|
||||
uncore_cpu_prepare, NULL);
|
||||
}
|
||||
first_init = 1;
|
||||
cpuhp_setup_state(CPUHP_AP_PERF_X86_UNCORE_STARTING,
|
||||
"perf/x86/uncore:starting",
|
||||
uncore_cpu_starting, uncore_cpu_dying);
|
||||
first_init = 0;
|
||||
cpuhp_setup_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE,
|
||||
"perf/x86/uncore:online",
|
||||
uncore_event_cpu_online, uncore_event_cpu_offline);
|
||||
/* Install hotplug callbacks to setup the targets for each package */
|
||||
ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE,
|
||||
"perf/x86/intel/uncore:online",
|
||||
uncore_event_cpu_online,
|
||||
uncore_event_cpu_offline);
|
||||
if (ret)
|
||||
goto err;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
/* Undo box->init_box() */
|
||||
on_each_cpu_mask(&uncore_cpu_mask, uncore_exit_boxes, NULL, 1);
|
||||
uncore_types_exit(uncore_msr_uncores);
|
||||
uncore_pci_exit();
|
||||
return ret;
|
||||
@ -1429,9 +1381,7 @@ module_init(intel_uncore_init);
|
||||
|
||||
static void __exit intel_uncore_exit(void)
|
||||
{
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_UNCORE_ONLINE);
|
||||
cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_UNCORE_STARTING);
|
||||
cpuhp_remove_state_nocalls(CPUHP_PERF_X86_UNCORE_PREP);
|
||||
cpuhp_remove_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE);
|
||||
uncore_types_exit(uncore_msr_uncores);
|
||||
uncore_pci_exit();
|
||||
}
|
||||
|
@ -140,6 +140,7 @@ extern void __init load_ucode_bsp(void);
|
||||
extern void load_ucode_ap(void);
|
||||
void reload_early_microcode(void);
|
||||
extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
|
||||
extern bool initrd_gone;
|
||||
#else
|
||||
static inline int __init microcode_init(void) { return 0; };
|
||||
static inline void __init load_ucode_bsp(void) { }
|
||||
|
@ -2117,6 +2117,7 @@ static inline void __init check_timer(void)
|
||||
if (idx != -1 && irq_trigger(idx))
|
||||
unmask_ioapic_irq(irq_get_chip_data(0));
|
||||
}
|
||||
irq_domain_deactivate_irq(irq_data);
|
||||
irq_domain_activate_irq(irq_data);
|
||||
if (timer_irq_works()) {
|
||||
if (disable_timer_pin_1 > 0)
|
||||
@ -2138,6 +2139,7 @@ static inline void __init check_timer(void)
|
||||
* legacy devices should be connected to IO APIC #0
|
||||
*/
|
||||
replace_pin_at_irq_node(data, node, apic1, pin1, apic2, pin2);
|
||||
irq_domain_deactivate_irq(irq_data);
|
||||
irq_domain_activate_irq(irq_data);
|
||||
legacy_pic->unmask(0);
|
||||
if (timer_irq_works()) {
|
||||
|
@ -1373,20 +1373,15 @@ static unsigned long mce_adjust_timer_default(unsigned long interval)
|
||||
|
||||
static unsigned long (*mce_adjust_timer)(unsigned long interval) = mce_adjust_timer_default;
|
||||
|
||||
static void __restart_timer(struct timer_list *t, unsigned long interval)
|
||||
static void __start_timer(struct timer_list *t, unsigned long interval)
|
||||
{
|
||||
unsigned long when = jiffies + interval;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (timer_pending(t)) {
|
||||
if (time_before(when, t->expires))
|
||||
mod_timer(t, when);
|
||||
} else {
|
||||
t->expires = round_jiffies(when);
|
||||
add_timer_on(t, smp_processor_id());
|
||||
}
|
||||
if (!timer_pending(t) || time_before(when, t->expires))
|
||||
mod_timer(t, round_jiffies(when));
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
@ -1421,7 +1416,7 @@ static void mce_timer_fn(unsigned long data)
|
||||
|
||||
done:
|
||||
__this_cpu_write(mce_next_interval, iv);
|
||||
__restart_timer(t, iv);
|
||||
__start_timer(t, iv);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1432,7 +1427,7 @@ void mce_timer_kick(unsigned long interval)
|
||||
struct timer_list *t = this_cpu_ptr(&mce_timer);
|
||||
unsigned long iv = __this_cpu_read(mce_next_interval);
|
||||
|
||||
__restart_timer(t, interval);
|
||||
__start_timer(t, interval);
|
||||
|
||||
if (interval < iv)
|
||||
__this_cpu_write(mce_next_interval, interval);
|
||||
@ -1779,17 +1774,15 @@ static void __mcheck_cpu_clear_vendor(struct cpuinfo_x86 *c)
|
||||
}
|
||||
}
|
||||
|
||||
static void mce_start_timer(unsigned int cpu, struct timer_list *t)
|
||||
static void mce_start_timer(struct timer_list *t)
|
||||
{
|
||||
unsigned long iv = check_interval * HZ;
|
||||
|
||||
if (mca_cfg.ignore_ce || !iv)
|
||||
return;
|
||||
|
||||
per_cpu(mce_next_interval, cpu) = iv;
|
||||
|
||||
t->expires = round_jiffies(jiffies + iv);
|
||||
add_timer_on(t, cpu);
|
||||
this_cpu_write(mce_next_interval, iv);
|
||||
__start_timer(t, iv);
|
||||
}
|
||||
|
||||
static void __mcheck_cpu_setup_timer(void)
|
||||
@ -1806,7 +1799,7 @@ static void __mcheck_cpu_init_timer(void)
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
setup_pinned_timer(t, mce_timer_fn, cpu);
|
||||
mce_start_timer(cpu, t);
|
||||
mce_start_timer(t);
|
||||
}
|
||||
|
||||
/* Handle unconfigured int18 (should never happen) */
|
||||
@ -2566,7 +2559,7 @@ static int mce_cpu_dead(unsigned int cpu)
|
||||
|
||||
static int mce_cpu_online(unsigned int cpu)
|
||||
{
|
||||
struct timer_list *t = &per_cpu(mce_timer, cpu);
|
||||
struct timer_list *t = this_cpu_ptr(&mce_timer);
|
||||
int ret;
|
||||
|
||||
mce_device_create(cpu);
|
||||
@ -2577,13 +2570,13 @@ static int mce_cpu_online(unsigned int cpu)
|
||||
return ret;
|
||||
}
|
||||
mce_reenable_cpu();
|
||||
mce_start_timer(cpu, t);
|
||||
mce_start_timer(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mce_cpu_pre_down(unsigned int cpu)
|
||||
{
|
||||
struct timer_list *t = &per_cpu(mce_timer, cpu);
|
||||
struct timer_list *t = this_cpu_ptr(&mce_timer);
|
||||
|
||||
mce_disable_cpu();
|
||||
del_timer_sync(t);
|
||||
|
@ -384,8 +384,9 @@ void load_ucode_amd_ap(unsigned int family)
|
||||
reget:
|
||||
if (!get_builtin_microcode(&cp, family)) {
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
cp = find_cpio_data(ucode_path, (void *)initrd_start,
|
||||
initrd_end - initrd_start, NULL);
|
||||
if (!initrd_gone)
|
||||
cp = find_cpio_data(ucode_path, (void *)initrd_start,
|
||||
initrd_end - initrd_start, NULL);
|
||||
#endif
|
||||
if (!(cp.data && cp.size)) {
|
||||
/*
|
||||
|
@ -46,6 +46,8 @@
|
||||
static struct microcode_ops *microcode_ops;
|
||||
static bool dis_ucode_ldr = true;
|
||||
|
||||
bool initrd_gone;
|
||||
|
||||
LIST_HEAD(microcode_cache);
|
||||
|
||||
/*
|
||||
@ -190,21 +192,24 @@ void load_ucode_ap(void)
|
||||
static int __init save_microcode_in_initrd(void)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
int ret = -EINVAL;
|
||||
|
||||
switch (c->x86_vendor) {
|
||||
case X86_VENDOR_INTEL:
|
||||
if (c->x86 >= 6)
|
||||
return save_microcode_in_initrd_intel();
|
||||
ret = save_microcode_in_initrd_intel();
|
||||
break;
|
||||
case X86_VENDOR_AMD:
|
||||
if (c->x86 >= 0x10)
|
||||
return save_microcode_in_initrd_amd(c->x86);
|
||||
ret = save_microcode_in_initrd_amd(c->x86);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
initrd_gone = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
|
||||
@ -247,9 +252,16 @@ struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
|
||||
* has the virtual address of the beginning of the initrd. It also
|
||||
* possibly relocates the ramdisk. In either case, initrd_start contains
|
||||
* the updated address so use that instead.
|
||||
*
|
||||
* initrd_gone is for the hotplug case where we've thrown out initrd
|
||||
* already.
|
||||
*/
|
||||
if (!use_pa && initrd_start)
|
||||
start = initrd_start;
|
||||
if (!use_pa) {
|
||||
if (initrd_gone)
|
||||
return (struct cpio_data){ NULL, 0, "" };
|
||||
if (initrd_start)
|
||||
start = initrd_start;
|
||||
}
|
||||
|
||||
return find_cpio_data(path, (void *)start, size, NULL);
|
||||
#else /* !CONFIG_BLK_DEV_INITRD */
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
|
||||
|
||||
/* Current microcode patch used in early patching */
|
||||
/* Current microcode patch used in early patching on the APs. */
|
||||
struct microcode_intel *intel_ucode_patch;
|
||||
|
||||
static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
|
||||
@ -607,12 +607,6 @@ int __init save_microcode_in_initrd_intel(void)
|
||||
struct ucode_cpu_info uci;
|
||||
struct cpio_data cp;
|
||||
|
||||
/*
|
||||
* AP loading didn't find any microcode patch, no need to save anything.
|
||||
*/
|
||||
if (!intel_ucode_patch || IS_ERR(intel_ucode_patch))
|
||||
return 0;
|
||||
|
||||
if (!load_builtin_intel_microcode(&cp))
|
||||
cp = find_microcode_in_initrd(ucode_path, false);
|
||||
|
||||
@ -628,7 +622,6 @@ int __init save_microcode_in_initrd_intel(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @res_patch, output: a pointer to the patch we found.
|
||||
*/
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <asm/fpu/regset.h>
|
||||
#include <asm/fpu/signal.h>
|
||||
#include <asm/fpu/types.h>
|
||||
#include <asm/fpu/xstate.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
#include <linux/hardirq.h>
|
||||
@ -183,7 +184,8 @@ void fpstate_init(union fpregs_state *state)
|
||||
* it will #GP. Make sure it is replaced after the memset().
|
||||
*/
|
||||
if (static_cpu_has(X86_FEATURE_XSAVES))
|
||||
state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT;
|
||||
state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT |
|
||||
xfeatures_mask;
|
||||
|
||||
if (static_cpu_has(X86_FEATURE_FXSR))
|
||||
fpstate_init_fxstate(&state->fxsave);
|
||||
|
@ -352,6 +352,7 @@ static int hpet_resume(struct clock_event_device *evt, int timer)
|
||||
} else {
|
||||
struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
|
||||
|
||||
irq_domain_deactivate_irq(irq_get_irq_data(hdev->irq));
|
||||
irq_domain_activate_irq(irq_get_irq_data(hdev->irq));
|
||||
disable_irq(hdev->irq);
|
||||
irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
|
||||
|
@ -3182,6 +3182,7 @@ static void fill_xsave(u8 *dest, struct kvm_vcpu *vcpu)
|
||||
memcpy(dest, xsave, XSAVE_HDR_OFFSET);
|
||||
|
||||
/* Set XSTATE_BV */
|
||||
xstate_bv &= vcpu->arch.guest_supported_xcr0 | XFEATURE_MASK_FPSSE;
|
||||
*(u64 *)(dest + XSAVE_HDR_OFFSET) = xstate_bv;
|
||||
|
||||
/*
|
||||
|
@ -268,6 +268,22 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
|
||||
|
||||
efi_scratch.use_pgd = true;
|
||||
|
||||
/*
|
||||
* Certain firmware versions are way too sentimential and still believe
|
||||
* they are exclusive and unquestionable owners of the first physical page,
|
||||
* even though they explicitly mark it as EFI_CONVENTIONAL_MEMORY
|
||||
* (but then write-access it later during SetVirtualAddressMap()).
|
||||
*
|
||||
* Create a 1:1 mapping for this page, to avoid triple faults during early
|
||||
* boot with such firmware. We are free to hand this page to the BIOS,
|
||||
* as trim_bios_range() will reserve the first page and isolate it away
|
||||
* from memory allocators anyway.
|
||||
*/
|
||||
if (kernel_map_pages_in_pgd(pgd, 0x0, 0x0, 1, _PAGE_RW)) {
|
||||
pr_err("Failed to create 1:1 mapping for the first page!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* When making calls to the firmware everything needs to be 1:1
|
||||
* mapped and addressable with 32-bit pointers. Map the kernel
|
||||
|
@ -419,7 +419,7 @@ subsys_initcall(topology_init);
|
||||
|
||||
void cpu_reset(void)
|
||||
{
|
||||
#if XCHAL_HAVE_PTP_MMU
|
||||
#if XCHAL_HAVE_PTP_MMU && IS_ENABLED(CONFIG_MMU)
|
||||
local_irq_disable();
|
||||
/*
|
||||
* We have full MMU: all autoload ways, ways 7, 8 and 9 of DTLB must
|
||||
|
@ -356,6 +356,7 @@ int crypto_register_alg(struct crypto_alg *alg)
|
||||
struct crypto_larval *larval;
|
||||
int err;
|
||||
|
||||
alg->cra_flags &= ~CRYPTO_ALG_DEAD;
|
||||
err = crypto_check_alg(alg);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -1702,6 +1702,8 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
|
||||
|
||||
if (qc->err_mask & ~AC_ERR_OTHER)
|
||||
qc->err_mask &= ~AC_ERR_OTHER;
|
||||
} else if (qc->tf.command == ATA_CMD_REQ_SENSE_DATA) {
|
||||
qc->result_tf.command |= ATA_SENSE;
|
||||
}
|
||||
|
||||
/* finish up */
|
||||
@ -4356,10 +4358,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
||||
{ "ST380013AS", "3.20", ATA_HORKAGE_MAX_SEC_1024 },
|
||||
|
||||
/*
|
||||
* Device times out with higher max sects.
|
||||
* These devices time out with higher max sects.
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=121671
|
||||
*/
|
||||
{ "LITEON CX1-JB256-HP", NULL, ATA_HORKAGE_MAX_SEC_1024 },
|
||||
{ "LITEON CX1-JB*-HP", NULL, ATA_HORKAGE_MAX_SEC_1024 },
|
||||
|
||||
/* Devices we expect to fail diagnostics */
|
||||
|
||||
|
@ -4132,6 +4132,9 @@ static int mv_platform_probe(struct platform_device *pdev)
|
||||
host->iomap = NULL;
|
||||
hpriv->base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!hpriv->base)
|
||||
return -ENOMEM;
|
||||
|
||||
hpriv->base -= SATAHC0_REG_BASE;
|
||||
|
||||
hpriv->clk = clk_get(&pdev->dev, NULL);
|
||||
|
@ -558,9 +558,6 @@ static void fw_load_abort(struct firmware_priv *fw_priv)
|
||||
struct firmware_buf *buf = fw_priv->buf;
|
||||
|
||||
__fw_load_abort(buf);
|
||||
|
||||
/* avoid user action after loading abort */
|
||||
fw_priv->buf = NULL;
|
||||
}
|
||||
|
||||
static LIST_HEAD(pending_fw_head);
|
||||
@ -713,7 +710,7 @@ static ssize_t firmware_loading_store(struct device *dev,
|
||||
|
||||
mutex_lock(&fw_lock);
|
||||
fw_buf = fw_priv->buf;
|
||||
if (!fw_buf)
|
||||
if (fw_state_is_aborted(&fw_buf->fw_st))
|
||||
goto out;
|
||||
|
||||
switch (loading) {
|
||||
|
@ -389,33 +389,33 @@ static ssize_t show_valid_zones(struct device *dev,
|
||||
{
|
||||
struct memory_block *mem = to_memory_block(dev);
|
||||
unsigned long start_pfn, end_pfn;
|
||||
unsigned long valid_start, valid_end, valid_pages;
|
||||
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
|
||||
struct page *first_page;
|
||||
struct zone *zone;
|
||||
int zone_shift = 0;
|
||||
|
||||
start_pfn = section_nr_to_pfn(mem->start_section_nr);
|
||||
end_pfn = start_pfn + nr_pages;
|
||||
first_page = pfn_to_page(start_pfn);
|
||||
|
||||
/* The block contains more than one zone can not be offlined. */
|
||||
if (!test_pages_in_a_zone(start_pfn, end_pfn))
|
||||
if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end))
|
||||
return sprintf(buf, "none\n");
|
||||
|
||||
zone = page_zone(first_page);
|
||||
zone = page_zone(pfn_to_page(valid_start));
|
||||
valid_pages = valid_end - valid_start;
|
||||
|
||||
/* MMOP_ONLINE_KEEP */
|
||||
sprintf(buf, "%s", zone->name);
|
||||
|
||||
/* MMOP_ONLINE_KERNEL */
|
||||
zone_can_shift(start_pfn, nr_pages, ZONE_NORMAL, &zone_shift);
|
||||
zone_can_shift(valid_start, valid_pages, ZONE_NORMAL, &zone_shift);
|
||||
if (zone_shift) {
|
||||
strcat(buf, " ");
|
||||
strcat(buf, (zone + zone_shift)->name);
|
||||
}
|
||||
|
||||
/* MMOP_ONLINE_MOVABLE */
|
||||
zone_can_shift(start_pfn, nr_pages, ZONE_MOVABLE, &zone_shift);
|
||||
zone_can_shift(valid_start, valid_pages, ZONE_MOVABLE, &zone_shift);
|
||||
if (zone_shift) {
|
||||
strcat(buf, " ");
|
||||
strcat(buf, (zone + zone_shift)->name);
|
||||
|
@ -45,6 +45,9 @@ int bcma_sprom_get(struct bcma_bus *bus);
|
||||
void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc);
|
||||
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
|
||||
void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
|
||||
/* driver_chipcommon_b.c */
|
||||
int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb);
|
||||
|
@ -15,8 +15,6 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
static void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
|
||||
|
||||
static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
|
||||
u32 mask, u32 value)
|
||||
{
|
||||
@ -186,9 +184,6 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
|
||||
if (cc->capabilities & BCMA_CC_CAP_PMU)
|
||||
bcma_pmu_early_init(cc);
|
||||
|
||||
if (IS_BUILTIN(CONFIG_BCM47XX) && bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
bcma_chipco_serial_init(cc);
|
||||
|
||||
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
bcma_core_chipcommon_flash_detect(cc);
|
||||
|
||||
@ -378,9 +373,9 @@ u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
#if IS_BUILTIN(CONFIG_BCM47XX)
|
||||
unsigned int irq;
|
||||
u32 baud_base;
|
||||
u32 i;
|
||||
@ -422,5 +417,5 @@ static void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
|
||||
ports[i].baud_base = baud_base;
|
||||
ports[i].reg_shift = 0;
|
||||
}
|
||||
#endif /* CONFIG_BCM47XX */
|
||||
}
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
|
@ -278,9 +278,12 @@ static void bcma_core_mips_nvram_init(struct bcma_drv_mips *mcore)
|
||||
|
||||
void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
|
||||
{
|
||||
struct bcma_bus *bus = mcore->core->bus;
|
||||
|
||||
if (mcore->early_setup_done)
|
||||
return;
|
||||
|
||||
bcma_chipco_serial_init(&bus->drv_cc);
|
||||
bcma_core_mips_nvram_init(mcore);
|
||||
|
||||
mcore->early_setup_done = true;
|
||||
|
@ -153,6 +153,8 @@ struct cppi41_dd {
|
||||
|
||||
/* context for suspend/resume */
|
||||
unsigned int dma_tdfdq;
|
||||
|
||||
bool is_suspended;
|
||||
};
|
||||
|
||||
#define FIST_COMPLETION_QUEUE 93
|
||||
@ -257,6 +259,10 @@ static struct cppi41_channel *desc_to_chan(struct cppi41_dd *cdd, u32 desc)
|
||||
BUG_ON(desc_num >= ALLOC_DECS_NUM);
|
||||
c = cdd->chan_busy[desc_num];
|
||||
cdd->chan_busy[desc_num] = NULL;
|
||||
|
||||
/* Usecount for chan_busy[], paired with push_desc_queue() */
|
||||
pm_runtime_put(cdd->ddev.dev);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -317,12 +323,12 @@ static irqreturn_t cppi41_irq(int irq, void *data)
|
||||
|
||||
while (val) {
|
||||
u32 desc, len;
|
||||
int error;
|
||||
|
||||
error = pm_runtime_get(cdd->ddev.dev);
|
||||
if (error < 0)
|
||||
dev_err(cdd->ddev.dev, "%s pm runtime get: %i\n",
|
||||
__func__, error);
|
||||
/*
|
||||
* This should never trigger, see the comments in
|
||||
* push_desc_queue()
|
||||
*/
|
||||
WARN_ON(cdd->is_suspended);
|
||||
|
||||
q_num = __fls(val);
|
||||
val &= ~(1 << q_num);
|
||||
@ -343,9 +349,6 @@ static irqreturn_t cppi41_irq(int irq, void *data)
|
||||
c->residue = pd_trans_len(c->desc->pd6) - len;
|
||||
dma_cookie_complete(&c->txd);
|
||||
dmaengine_desc_get_callback_invoke(&c->txd, NULL);
|
||||
|
||||
pm_runtime_mark_last_busy(cdd->ddev.dev);
|
||||
pm_runtime_put_autosuspend(cdd->ddev.dev);
|
||||
}
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
@ -447,6 +450,15 @@ static void push_desc_queue(struct cppi41_channel *c)
|
||||
*/
|
||||
__iowmb();
|
||||
|
||||
/*
|
||||
* DMA transfers can take at least 200ms to complete with USB mass
|
||||
* storage connected. To prevent autosuspend timeouts, we must use
|
||||
* pm_runtime_get/put() when chan_busy[] is modified. This will get
|
||||
* cleared in desc_to_chan() or cppi41_stop_chan() depending on the
|
||||
* outcome of the transfer.
|
||||
*/
|
||||
pm_runtime_get(cdd->ddev.dev);
|
||||
|
||||
desc_phys = lower_32_bits(c->desc_phys);
|
||||
desc_num = (desc_phys - cdd->descs_phys) / sizeof(struct cppi41_desc);
|
||||
WARN_ON(cdd->chan_busy[desc_num]);
|
||||
@ -457,20 +469,26 @@ static void push_desc_queue(struct cppi41_channel *c)
|
||||
cppi_writel(reg, cdd->qmgr_mem + QMGR_QUEUE_D(c->q_num));
|
||||
}
|
||||
|
||||
static void pending_desc(struct cppi41_channel *c)
|
||||
/*
|
||||
* Caller must hold cdd->lock to prevent push_desc_queue()
|
||||
* getting called out of order. We have both cppi41_dma_issue_pending()
|
||||
* and cppi41_runtime_resume() call this function.
|
||||
*/
|
||||
static void cppi41_run_queue(struct cppi41_dd *cdd)
|
||||
{
|
||||
struct cppi41_dd *cdd = c->cdd;
|
||||
unsigned long flags;
|
||||
struct cppi41_channel *c, *_c;
|
||||
|
||||
spin_lock_irqsave(&cdd->lock, flags);
|
||||
list_add_tail(&c->node, &cdd->pending);
|
||||
spin_unlock_irqrestore(&cdd->lock, flags);
|
||||
list_for_each_entry_safe(c, _c, &cdd->pending, node) {
|
||||
push_desc_queue(c);
|
||||
list_del(&c->node);
|
||||
}
|
||||
}
|
||||
|
||||
static void cppi41_dma_issue_pending(struct dma_chan *chan)
|
||||
{
|
||||
struct cppi41_channel *c = to_cpp41_chan(chan);
|
||||
struct cppi41_dd *cdd = c->cdd;
|
||||
unsigned long flags;
|
||||
int error;
|
||||
|
||||
error = pm_runtime_get(cdd->ddev.dev);
|
||||
@ -482,10 +500,11 @@ static void cppi41_dma_issue_pending(struct dma_chan *chan)
|
||||
return;
|
||||
}
|
||||
|
||||
if (likely(pm_runtime_active(cdd->ddev.dev)))
|
||||
push_desc_queue(c);
|
||||
else
|
||||
pending_desc(c);
|
||||
spin_lock_irqsave(&cdd->lock, flags);
|
||||
list_add_tail(&c->node, &cdd->pending);
|
||||
if (!cdd->is_suspended)
|
||||
cppi41_run_queue(cdd);
|
||||
spin_unlock_irqrestore(&cdd->lock, flags);
|
||||
|
||||
pm_runtime_mark_last_busy(cdd->ddev.dev);
|
||||
pm_runtime_put_autosuspend(cdd->ddev.dev);
|
||||
@ -705,6 +724,9 @@ static int cppi41_stop_chan(struct dma_chan *chan)
|
||||
WARN_ON(!cdd->chan_busy[desc_num]);
|
||||
cdd->chan_busy[desc_num] = NULL;
|
||||
|
||||
/* Usecount for chan_busy[], paired with push_desc_queue() */
|
||||
pm_runtime_put(cdd->ddev.dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1150,8 +1172,12 @@ static int __maybe_unused cppi41_resume(struct device *dev)
|
||||
static int __maybe_unused cppi41_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct cppi41_dd *cdd = dev_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cdd->lock, flags);
|
||||
cdd->is_suspended = true;
|
||||
WARN_ON(!list_empty(&cdd->pending));
|
||||
spin_unlock_irqrestore(&cdd->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1159,14 +1185,11 @@ static int __maybe_unused cppi41_runtime_suspend(struct device *dev)
|
||||
static int __maybe_unused cppi41_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct cppi41_dd *cdd = dev_get_drvdata(dev);
|
||||
struct cppi41_channel *c, *_c;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&cdd->lock, flags);
|
||||
list_for_each_entry_safe(c, _c, &cdd->pending, node) {
|
||||
push_desc_queue(c);
|
||||
list_del(&c->node);
|
||||
}
|
||||
cdd->is_suspended = false;
|
||||
cppi41_run_queue(cdd);
|
||||
spin_unlock_irqrestore(&cdd->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -1699,7 +1699,6 @@ static bool _chan_ns(const struct pl330_dmac *pl330, int i)
|
||||
static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
|
||||
{
|
||||
struct pl330_thread *thrd = NULL;
|
||||
unsigned long flags;
|
||||
int chans, i;
|
||||
|
||||
if (pl330->state == DYING)
|
||||
@ -1707,8 +1706,6 @@ static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
|
||||
|
||||
chans = pl330->pcfg.num_chan;
|
||||
|
||||
spin_lock_irqsave(&pl330->lock, flags);
|
||||
|
||||
for (i = 0; i < chans; i++) {
|
||||
thrd = &pl330->channels[i];
|
||||
if ((thrd->free) && (!_manager_ns(thrd) ||
|
||||
@ -1726,8 +1723,6 @@ static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
|
||||
thrd = NULL;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&pl330->lock, flags);
|
||||
|
||||
return thrd;
|
||||
}
|
||||
|
||||
@ -1745,7 +1740,6 @@ static inline void _free_event(struct pl330_thread *thrd, int ev)
|
||||
static void pl330_release_channel(struct pl330_thread *thrd)
|
||||
{
|
||||
struct pl330_dmac *pl330;
|
||||
unsigned long flags;
|
||||
|
||||
if (!thrd || thrd->free)
|
||||
return;
|
||||
@ -1757,10 +1751,8 @@ static void pl330_release_channel(struct pl330_thread *thrd)
|
||||
|
||||
pl330 = thrd->dmac;
|
||||
|
||||
spin_lock_irqsave(&pl330->lock, flags);
|
||||
_free_event(thrd, thrd->ev);
|
||||
thrd->free = true;
|
||||
spin_unlock_irqrestore(&pl330->lock, flags);
|
||||
}
|
||||
|
||||
/* Initialize the structure for PL330 configuration, that can be used
|
||||
@ -2122,20 +2114,20 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
|
||||
struct pl330_dmac *pl330 = pch->dmac;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
spin_lock_irqsave(&pl330->lock, flags);
|
||||
|
||||
dma_cookie_init(chan);
|
||||
pch->cyclic = false;
|
||||
|
||||
pch->thread = pl330_request_channel(pl330);
|
||||
if (!pch->thread) {
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
spin_unlock_irqrestore(&pl330->lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch);
|
||||
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
spin_unlock_irqrestore(&pl330->lock, flags);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -2238,12 +2230,13 @@ static int pl330_pause(struct dma_chan *chan)
|
||||
static void pl330_free_chan_resources(struct dma_chan *chan)
|
||||
{
|
||||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||||
struct pl330_dmac *pl330 = pch->dmac;
|
||||
unsigned long flags;
|
||||
|
||||
tasklet_kill(&pch->task);
|
||||
|
||||
pm_runtime_get_sync(pch->dmac->ddma.dev);
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
spin_lock_irqsave(&pl330->lock, flags);
|
||||
|
||||
pl330_release_channel(pch->thread);
|
||||
pch->thread = NULL;
|
||||
@ -2251,7 +2244,7 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
|
||||
if (pch->cyclic)
|
||||
list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
|
||||
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
spin_unlock_irqrestore(&pl330->lock, flags);
|
||||
pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
|
||||
pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
|
||||
}
|
||||
|
@ -187,6 +187,7 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
|
||||
struct exit_boot_struct {
|
||||
efi_memory_desc_t *runtime_map;
|
||||
int *runtime_entry_count;
|
||||
void *new_fdt_addr;
|
||||
};
|
||||
|
||||
static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
|
||||
@ -202,7 +203,7 @@ static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
|
||||
efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
|
||||
p->runtime_map, p->runtime_entry_count);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
return update_fdt_memmap(p->new_fdt_addr, map);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -300,22 +301,13 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
|
||||
|
||||
priv.runtime_map = runtime_map;
|
||||
priv.runtime_entry_count = &runtime_entry_count;
|
||||
priv.new_fdt_addr = (void *)*new_fdt_addr;
|
||||
status = efi_exit_boot_services(sys_table, handle, &map, &priv,
|
||||
exit_boot_func);
|
||||
|
||||
if (status == EFI_SUCCESS) {
|
||||
efi_set_virtual_address_map_t *svam;
|
||||
|
||||
status = update_fdt_memmap((void *)*new_fdt_addr, &map);
|
||||
if (status != EFI_SUCCESS) {
|
||||
/*
|
||||
* The kernel won't get far without the memory map, but
|
||||
* may still be able to print something meaningful so
|
||||
* return success here.
|
||||
*/
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Install the new virtual address map */
|
||||
svam = sys_table->runtime->set_virtual_address_map;
|
||||
status = svam(runtime_entry_count * desc_size, desc_size,
|
||||
|
@ -254,6 +254,9 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
|
||||
}
|
||||
WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0);
|
||||
|
||||
if (adev->mode_info.num_crtc)
|
||||
amdgpu_display_set_vga_render_state(adev, false);
|
||||
|
||||
gmc_v6_0_mc_stop(adev, &save);
|
||||
|
||||
if (gmc_v6_0_wait_for_idle((void *)adev)) {
|
||||
@ -283,7 +286,6 @@ static void gmc_v6_0_mc_program(struct amdgpu_device *adev)
|
||||
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
|
||||
}
|
||||
gmc_v6_0_mc_resume(adev, &save);
|
||||
amdgpu_display_set_vga_render_state(adev, false);
|
||||
}
|
||||
|
||||
static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
|
||||
|
@ -2032,13 +2032,16 @@ static void complete_crtc_signaling(struct drm_device *dev,
|
||||
}
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
struct drm_pending_vblank_event *event = crtc_state->event;
|
||||
/*
|
||||
* TEST_ONLY and PAGE_FLIP_EVENT are mutually
|
||||
* exclusive, if they weren't, this code should be
|
||||
* called on success for TEST_ONLY too.
|
||||
* Free the allocated event. drm_atomic_helper_setup_commit
|
||||
* can allocate an event too, so only free it if it's ours
|
||||
* to prevent a double free in drm_atomic_state_clear.
|
||||
*/
|
||||
if (crtc_state->event)
|
||||
drm_event_cancel_free(dev, &crtc_state->event->base);
|
||||
if (event && (event->base.fence || event->base.file_priv)) {
|
||||
drm_event_cancel_free(dev, &event->base);
|
||||
crtc_state->event = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fence_state)
|
||||
|
@ -1666,9 +1666,6 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
|
||||
|
||||
funcs = plane->helper_private;
|
||||
|
||||
if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
|
||||
continue;
|
||||
|
||||
if (funcs->prepare_fb) {
|
||||
ret = funcs->prepare_fb(plane, plane_state);
|
||||
if (ret)
|
||||
@ -1685,9 +1682,6 @@ fail:
|
||||
if (j >= i)
|
||||
continue;
|
||||
|
||||
if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
|
||||
continue;
|
||||
|
||||
funcs = plane->helper_private;
|
||||
|
||||
if (funcs->cleanup_fb)
|
||||
@ -1954,9 +1948,6 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
|
||||
for_each_plane_in_state(old_state, plane, plane_state, i) {
|
||||
const struct drm_plane_helper_funcs *funcs;
|
||||
|
||||
if (!drm_atomic_helper_framebuffer_changed(dev, old_state, plane_state->crtc))
|
||||
continue;
|
||||
|
||||
funcs = plane->helper_private;
|
||||
|
||||
if (funcs->cleanup_fb)
|
||||
|
@ -225,6 +225,7 @@ int drm_connector_init(struct drm_device *dev,
|
||||
|
||||
INIT_LIST_HEAD(&connector->probed_modes);
|
||||
INIT_LIST_HEAD(&connector->modes);
|
||||
mutex_init(&connector->mutex);
|
||||
connector->edid_blob_ptr = NULL;
|
||||
connector->status = connector_status_unknown;
|
||||
|
||||
@ -359,6 +360,8 @@ void drm_connector_cleanup(struct drm_connector *connector)
|
||||
connector->funcs->atomic_destroy_state(connector,
|
||||
connector->state);
|
||||
|
||||
mutex_destroy(&connector->mutex);
|
||||
|
||||
memset(connector, 0, sizeof(*connector));
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_cleanup);
|
||||
@ -374,14 +377,18 @@ EXPORT_SYMBOL(drm_connector_cleanup);
|
||||
*/
|
||||
int drm_connector_register(struct drm_connector *connector)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (connector->registered)
|
||||
if (!connector->dev->registered)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&connector->mutex);
|
||||
if (connector->registered)
|
||||
goto unlock;
|
||||
|
||||
ret = drm_sysfs_connector_add(connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto unlock;
|
||||
|
||||
ret = drm_debugfs_connector_add(connector);
|
||||
if (ret) {
|
||||
@ -397,12 +404,14 @@ int drm_connector_register(struct drm_connector *connector)
|
||||
drm_mode_object_register(connector->dev, &connector->base);
|
||||
|
||||
connector->registered = true;
|
||||
return 0;
|
||||
goto unlock;
|
||||
|
||||
err_debugfs:
|
||||
drm_debugfs_connector_remove(connector);
|
||||
err_sysfs:
|
||||
drm_sysfs_connector_remove(connector);
|
||||
unlock:
|
||||
mutex_unlock(&connector->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_register);
|
||||
@ -415,8 +424,11 @@ EXPORT_SYMBOL(drm_connector_register);
|
||||
*/
|
||||
void drm_connector_unregister(struct drm_connector *connector)
|
||||
{
|
||||
if (!connector->registered)
|
||||
mutex_lock(&connector->mutex);
|
||||
if (!connector->registered) {
|
||||
mutex_unlock(&connector->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connector->funcs->early_unregister)
|
||||
connector->funcs->early_unregister(connector);
|
||||
@ -425,6 +437,7 @@ void drm_connector_unregister(struct drm_connector *connector)
|
||||
drm_debugfs_connector_remove(connector);
|
||||
|
||||
connector->registered = false;
|
||||
mutex_unlock(&connector->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_unregister);
|
||||
|
||||
|
@ -745,6 +745,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
|
||||
if (ret)
|
||||
goto err_minors;
|
||||
|
||||
dev->registered = true;
|
||||
|
||||
if (dev->driver->load) {
|
||||
ret = dev->driver->load(dev, flags);
|
||||
if (ret)
|
||||
@ -785,6 +787,8 @@ void drm_dev_unregister(struct drm_device *dev)
|
||||
|
||||
drm_lastclose(dev);
|
||||
|
||||
dev->registered = false;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_modeset_unregister_all(dev);
|
||||
|
||||
|
@ -1012,6 +1012,8 @@ struct intel_fbc {
|
||||
struct work_struct underrun_work;
|
||||
|
||||
struct intel_fbc_state_cache {
|
||||
struct i915_vma *vma;
|
||||
|
||||
struct {
|
||||
unsigned int mode_flags;
|
||||
uint32_t hsw_bdw_pixel_rate;
|
||||
@ -1025,15 +1027,14 @@ struct intel_fbc {
|
||||
} plane;
|
||||
|
||||
struct {
|
||||
u64 ilk_ggtt_offset;
|
||||
uint32_t pixel_format;
|
||||
unsigned int stride;
|
||||
int fence_reg;
|
||||
unsigned int tiling_mode;
|
||||
} fb;
|
||||
} state_cache;
|
||||
|
||||
struct intel_fbc_reg_params {
|
||||
struct i915_vma *vma;
|
||||
|
||||
struct {
|
||||
enum pipe pipe;
|
||||
enum plane plane;
|
||||
@ -1041,10 +1042,8 @@ struct intel_fbc {
|
||||
} crtc;
|
||||
|
||||
struct {
|
||||
u64 ggtt_offset;
|
||||
uint32_t pixel_format;
|
||||
unsigned int stride;
|
||||
int fence_reg;
|
||||
} fb;
|
||||
|
||||
int cfb_size;
|
||||
@ -3168,13 +3167,6 @@ i915_gem_object_to_ggtt(struct drm_i915_gem_object *obj,
|
||||
return i915_gem_obj_to_vma(obj, &to_i915(obj->base.dev)->ggtt.base, view);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
|
||||
const struct i915_ggtt_view *view)
|
||||
{
|
||||
return i915_ggtt_offset(i915_gem_object_to_ggtt(o, view));
|
||||
}
|
||||
|
||||
/* i915_gem_fence_reg.c */
|
||||
int __must_check i915_vma_get_fence(struct i915_vma *vma);
|
||||
int __must_check i915_vma_put_fence(struct i915_vma *vma);
|
||||
|
@ -85,6 +85,8 @@ intel_plane_duplicate_state(struct drm_plane *plane)
|
||||
|
||||
__drm_atomic_helper_plane_duplicate_state(plane, state);
|
||||
|
||||
intel_state->vma = NULL;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -100,6 +102,24 @@ void
|
||||
intel_plane_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct i915_vma *vma;
|
||||
|
||||
vma = fetch_and_zero(&to_intel_plane_state(state)->vma);
|
||||
|
||||
/*
|
||||
* FIXME: Normally intel_cleanup_plane_fb handles destruction of vma.
|
||||
* We currently don't clear all planes during driver unload, so we have
|
||||
* to be able to unpin vma here for now.
|
||||
*
|
||||
* Normally this can only happen during unload when kmscon is disabled
|
||||
* and userspace doesn't attempt to set a framebuffer at all.
|
||||
*/
|
||||
if (vma) {
|
||||
mutex_lock(&plane->dev->struct_mutex);
|
||||
intel_unpin_fb_vma(vma);
|
||||
mutex_unlock(&plane->dev->struct_mutex);
|
||||
}
|
||||
|
||||
drm_atomic_helper_plane_destroy_state(plane, state);
|
||||
}
|
||||
|
||||
|
@ -2235,27 +2235,22 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
|
||||
i915_vma_pin_fence(vma);
|
||||
}
|
||||
|
||||
i915_vma_get(vma);
|
||||
err:
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
return vma;
|
||||
}
|
||||
|
||||
void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
|
||||
void intel_unpin_fb_vma(struct i915_vma *vma)
|
||||
{
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
struct i915_ggtt_view view;
|
||||
struct i915_vma *vma;
|
||||
|
||||
WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
|
||||
|
||||
intel_fill_fb_ggtt_view(&view, fb, rotation);
|
||||
vma = i915_gem_object_to_ggtt(obj, &view);
|
||||
lockdep_assert_held(&vma->vm->dev->struct_mutex);
|
||||
|
||||
if (WARN_ON_ONCE(!vma))
|
||||
return;
|
||||
|
||||
i915_vma_unpin_fence(vma);
|
||||
i915_gem_object_unpin_from_display_plane(vma);
|
||||
i915_vma_put(vma);
|
||||
}
|
||||
|
||||
static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
|
||||
@ -2750,7 +2745,6 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
||||
struct drm_device *dev = intel_crtc->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_crtc *c;
|
||||
struct intel_crtc *i;
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct drm_plane *primary = intel_crtc->base.primary;
|
||||
struct drm_plane_state *plane_state = primary->state;
|
||||
@ -2775,20 +2769,20 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
||||
* an fb with another CRTC instead
|
||||
*/
|
||||
for_each_crtc(dev, c) {
|
||||
i = to_intel_crtc(c);
|
||||
struct intel_plane_state *state;
|
||||
|
||||
if (c == &intel_crtc->base)
|
||||
continue;
|
||||
|
||||
if (!i->active)
|
||||
if (!to_intel_crtc(c)->active)
|
||||
continue;
|
||||
|
||||
fb = c->primary->fb;
|
||||
if (!fb)
|
||||
state = to_intel_plane_state(c->primary->state);
|
||||
if (!state->vma)
|
||||
continue;
|
||||
|
||||
obj = intel_fb_obj(fb);
|
||||
if (i915_gem_object_ggtt_offset(obj, NULL) == plane_config->base) {
|
||||
if (intel_plane_ggtt_offset(state) == plane_config->base) {
|
||||
fb = c->primary->fb;
|
||||
drm_framebuffer_reference(fb);
|
||||
goto valid_fb;
|
||||
}
|
||||
@ -2809,6 +2803,19 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
|
||||
return;
|
||||
|
||||
valid_fb:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
intel_state->vma =
|
||||
intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
if (IS_ERR(intel_state->vma)) {
|
||||
DRM_ERROR("failed to pin boot fb on pipe %d: %li\n",
|
||||
intel_crtc->pipe, PTR_ERR(intel_state->vma));
|
||||
|
||||
intel_state->vma = NULL;
|
||||
drm_framebuffer_unreference(fb);
|
||||
return;
|
||||
}
|
||||
|
||||
plane_state->src_x = 0;
|
||||
plane_state->src_y = 0;
|
||||
plane_state->src_w = fb->width << 16;
|
||||
@ -3104,13 +3111,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
|
||||
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
|
||||
if (INTEL_GEN(dev_priv) >= 4) {
|
||||
I915_WRITE(DSPSURF(plane),
|
||||
intel_fb_gtt_offset(fb, rotation) +
|
||||
intel_plane_ggtt_offset(plane_state) +
|
||||
intel_crtc->dspaddr_offset);
|
||||
I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
|
||||
I915_WRITE(DSPLINOFF(plane), linear_offset);
|
||||
} else {
|
||||
I915_WRITE(DSPADDR(plane),
|
||||
intel_fb_gtt_offset(fb, rotation) +
|
||||
intel_plane_ggtt_offset(plane_state) +
|
||||
intel_crtc->dspaddr_offset);
|
||||
}
|
||||
POSTING_READ(reg);
|
||||
@ -3207,7 +3214,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary,
|
||||
|
||||
I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
|
||||
I915_WRITE(DSPSURF(plane),
|
||||
intel_fb_gtt_offset(fb, rotation) +
|
||||
intel_plane_ggtt_offset(plane_state) +
|
||||
intel_crtc->dspaddr_offset);
|
||||
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
|
||||
I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
|
||||
@ -3230,23 +3237,6 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv,
|
||||
}
|
||||
}
|
||||
|
||||
u32 intel_fb_gtt_offset(struct drm_framebuffer *fb,
|
||||
unsigned int rotation)
|
||||
{
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
|
||||
struct i915_ggtt_view view;
|
||||
struct i915_vma *vma;
|
||||
|
||||
intel_fill_fb_ggtt_view(&view, fb, rotation);
|
||||
|
||||
vma = i915_gem_object_to_ggtt(obj, &view);
|
||||
if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
|
||||
view.type))
|
||||
return -1;
|
||||
|
||||
return i915_ggtt_offset(vma);
|
||||
}
|
||||
|
||||
static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
|
||||
{
|
||||
struct drm_device *dev = intel_crtc->base.dev;
|
||||
@ -3441,7 +3431,7 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
I915_WRITE(PLANE_SURF(pipe, 0),
|
||||
intel_fb_gtt_offset(fb, rotation) + surf_addr);
|
||||
intel_plane_ggtt_offset(plane_state) + surf_addr);
|
||||
|
||||
POSTING_READ(PLANE_SURF(pipe, 0));
|
||||
}
|
||||
@ -11536,7 +11526,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)
|
||||
flush_work(&work->mmio_work);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
intel_unpin_fb_obj(work->old_fb, primary->state->rotation);
|
||||
intel_unpin_fb_vma(work->old_vma);
|
||||
i915_gem_object_put(work->pending_flip_obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
@ -12246,8 +12236,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
||||
goto cleanup_pending;
|
||||
}
|
||||
|
||||
work->gtt_offset = intel_fb_gtt_offset(fb, primary->state->rotation);
|
||||
work->gtt_offset += intel_crtc->dspaddr_offset;
|
||||
work->old_vma = to_intel_plane_state(primary->state)->vma;
|
||||
to_intel_plane_state(primary->state)->vma = vma;
|
||||
|
||||
work->gtt_offset = i915_ggtt_offset(vma) + intel_crtc->dspaddr_offset;
|
||||
work->rotation = crtc->primary->state->rotation;
|
||||
|
||||
/*
|
||||
@ -12301,7 +12293,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
||||
cleanup_request:
|
||||
i915_add_request_no_flush(request);
|
||||
cleanup_unpin:
|
||||
intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
|
||||
to_intel_plane_state(primary->state)->vma = work->old_vma;
|
||||
intel_unpin_fb_vma(vma);
|
||||
cleanup_pending:
|
||||
atomic_dec(&intel_crtc->unpin_work_count);
|
||||
unlock:
|
||||
@ -14794,6 +14787,8 @@ intel_prepare_plane_fb(struct drm_plane *plane,
|
||||
DRM_DEBUG_KMS("failed to pin object\n");
|
||||
return PTR_ERR(vma);
|
||||
}
|
||||
|
||||
to_intel_plane_state(new_state)->vma = vma;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -14812,19 +14807,12 @@ void
|
||||
intel_cleanup_plane_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(plane->dev);
|
||||
struct intel_plane_state *old_intel_state;
|
||||
struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
|
||||
struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);
|
||||
struct i915_vma *vma;
|
||||
|
||||
old_intel_state = to_intel_plane_state(old_state);
|
||||
|
||||
if (!obj && !old_obj)
|
||||
return;
|
||||
|
||||
if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
|
||||
!INTEL_INFO(dev_priv)->cursor_needs_physical))
|
||||
intel_unpin_fb_obj(old_state->fb, old_state->rotation);
|
||||
/* Should only be called after a successful intel_prepare_plane_fb()! */
|
||||
vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
|
||||
if (vma)
|
||||
intel_unpin_fb_vma(vma);
|
||||
}
|
||||
|
||||
int
|
||||
@ -15166,7 +15154,7 @@ intel_update_cursor_plane(struct drm_plane *plane,
|
||||
if (!obj)
|
||||
addr = 0;
|
||||
else if (!INTEL_INFO(dev_priv)->cursor_needs_physical)
|
||||
addr = i915_gem_object_ggtt_offset(obj, NULL);
|
||||
addr = intel_plane_ggtt_offset(state);
|
||||
else
|
||||
addr = obj->phys_handle->busaddr;
|
||||
|
||||
@ -17066,41 +17054,12 @@ void intel_display_resume(struct drm_device *dev)
|
||||
void intel_modeset_gem_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct drm_crtc *c;
|
||||
struct drm_i915_gem_object *obj;
|
||||
|
||||
intel_init_gt_powersave(dev_priv);
|
||||
|
||||
intel_modeset_init_hw(dev);
|
||||
|
||||
intel_setup_overlay(dev_priv);
|
||||
|
||||
/*
|
||||
* Make sure any fbs we allocated at startup are properly
|
||||
* pinned & fenced. When we do the allocation it's too early
|
||||
* for this.
|
||||
*/
|
||||
for_each_crtc(dev, c) {
|
||||
struct i915_vma *vma;
|
||||
|
||||
obj = intel_fb_obj(c->primary->fb);
|
||||
if (obj == NULL)
|
||||
continue;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
vma = intel_pin_and_fence_fb_obj(c->primary->fb,
|
||||
c->primary->state->rotation);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
if (IS_ERR(vma)) {
|
||||
DRM_ERROR("failed to pin boot fb on pipe %d\n",
|
||||
to_intel_crtc(c)->pipe);
|
||||
drm_framebuffer_unreference(c->primary->fb);
|
||||
c->primary->fb = NULL;
|
||||
c->primary->crtc = c->primary->state->crtc = NULL;
|
||||
update_state_fb(c->primary);
|
||||
c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int intel_connector_register(struct drm_connector *connector)
|
||||
|
@ -377,6 +377,7 @@ struct intel_atomic_state {
|
||||
struct intel_plane_state {
|
||||
struct drm_plane_state base;
|
||||
struct drm_rect clip;
|
||||
struct i915_vma *vma;
|
||||
|
||||
struct {
|
||||
u32 offset;
|
||||
@ -1046,6 +1047,7 @@ struct intel_flip_work {
|
||||
struct work_struct mmio_work;
|
||||
|
||||
struct drm_crtc *crtc;
|
||||
struct i915_vma *old_vma;
|
||||
struct drm_framebuffer *old_fb;
|
||||
struct drm_i915_gem_object *pending_flip_obj;
|
||||
struct drm_pending_vblank_event *event;
|
||||
@ -1273,7 +1275,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
struct i915_vma *
|
||||
intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
|
||||
void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
|
||||
void intel_unpin_fb_vma(struct i915_vma *vma);
|
||||
struct drm_framebuffer *
|
||||
__intel_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
@ -1362,7 +1364,10 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
|
||||
int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
|
||||
int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
|
||||
|
||||
u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, unsigned int rotation);
|
||||
static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
|
||||
{
|
||||
return i915_ggtt_offset(state->vma);
|
||||
}
|
||||
|
||||
u32 skl_plane_ctl_format(uint32_t pixel_format);
|
||||
u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
|
||||
|
@ -173,7 +173,7 @@ static void i8xx_fbc_activate(struct drm_i915_private *dev_priv)
|
||||
if (IS_I945GM(dev_priv))
|
||||
fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
|
||||
fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
|
||||
fbc_ctl |= params->fb.fence_reg;
|
||||
fbc_ctl |= params->vma->fence->id;
|
||||
I915_WRITE(FBC_CONTROL, fbc_ctl);
|
||||
}
|
||||
|
||||
@ -193,8 +193,8 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
|
||||
else
|
||||
dpfc_ctl |= DPFC_CTL_LIMIT_1X;
|
||||
|
||||
if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
|
||||
dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg;
|
||||
if (params->vma->fence) {
|
||||
dpfc_ctl |= DPFC_CTL_FENCE_EN | params->vma->fence->id;
|
||||
I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
|
||||
} else {
|
||||
I915_WRITE(DPFC_FENCE_YOFF, 0);
|
||||
@ -251,13 +251,14 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
|
||||
if (params->vma->fence) {
|
||||
dpfc_ctl |= DPFC_CTL_FENCE_EN;
|
||||
if (IS_GEN5(dev_priv))
|
||||
dpfc_ctl |= params->fb.fence_reg;
|
||||
dpfc_ctl |= params->vma->fence->id;
|
||||
if (IS_GEN6(dev_priv)) {
|
||||
I915_WRITE(SNB_DPFC_CTL_SA,
|
||||
SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
|
||||
SNB_CPU_FENCE_ENABLE |
|
||||
params->vma->fence->id);
|
||||
I915_WRITE(DPFC_CPU_FENCE_OFFSET,
|
||||
params->crtc.fence_y_offset);
|
||||
}
|
||||
@ -269,7 +270,8 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
|
||||
}
|
||||
|
||||
I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
|
||||
I915_WRITE(ILK_FBC_RT_BASE, params->fb.ggtt_offset | ILK_FBC_RT_VALID);
|
||||
I915_WRITE(ILK_FBC_RT_BASE,
|
||||
i915_ggtt_offset(params->vma) | ILK_FBC_RT_VALID);
|
||||
/* enable it... */
|
||||
I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
|
||||
|
||||
@ -319,10 +321,11 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
|
||||
if (params->vma->fence) {
|
||||
dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
|
||||
I915_WRITE(SNB_DPFC_CTL_SA,
|
||||
SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
|
||||
SNB_CPU_FENCE_ENABLE |
|
||||
params->vma->fence->id);
|
||||
I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
|
||||
} else {
|
||||
I915_WRITE(SNB_DPFC_CTL_SA,0);
|
||||
@ -727,14 +730,6 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
|
||||
return effective_w <= max_w && effective_h <= max_h;
|
||||
}
|
||||
|
||||
/* XXX replace me when we have VMA tracking for intel_plane_state */
|
||||
static int get_fence_id(struct drm_framebuffer *fb)
|
||||
{
|
||||
struct i915_vma *vma = i915_gem_object_to_ggtt(intel_fb_obj(fb), NULL);
|
||||
|
||||
return vma && vma->fence ? vma->fence->id : I915_FENCE_REG_NONE;
|
||||
}
|
||||
|
||||
static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct intel_plane_state *plane_state)
|
||||
@ -743,7 +738,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
|
||||
struct intel_fbc *fbc = &dev_priv->fbc;
|
||||
struct intel_fbc_state_cache *cache = &fbc->state_cache;
|
||||
struct drm_framebuffer *fb = plane_state->base.fb;
|
||||
struct drm_i915_gem_object *obj;
|
||||
|
||||
cache->vma = NULL;
|
||||
|
||||
cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
|
||||
if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
@ -758,16 +754,10 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
|
||||
if (!cache->plane.visible)
|
||||
return;
|
||||
|
||||
obj = intel_fb_obj(fb);
|
||||
|
||||
/* FIXME: We lack the proper locking here, so only run this on the
|
||||
* platforms that need. */
|
||||
if (IS_GEN(dev_priv, 5, 6))
|
||||
cache->fb.ilk_ggtt_offset = i915_gem_object_ggtt_offset(obj, NULL);
|
||||
cache->fb.pixel_format = fb->pixel_format;
|
||||
cache->fb.stride = fb->pitches[0];
|
||||
cache->fb.fence_reg = get_fence_id(fb);
|
||||
cache->fb.tiling_mode = i915_gem_object_get_tiling(obj);
|
||||
|
||||
cache->vma = plane_state->vma;
|
||||
}
|
||||
|
||||
static bool intel_fbc_can_activate(struct intel_crtc *crtc)
|
||||
@ -784,7 +774,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cache->plane.visible) {
|
||||
if (!cache->vma) {
|
||||
fbc->no_fbc_reason = "primary plane not visible";
|
||||
return false;
|
||||
}
|
||||
@ -807,8 +797,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
|
||||
* so have no fence associated with it) due to aperture constaints
|
||||
* at the time of pinning.
|
||||
*/
|
||||
if (cache->fb.tiling_mode != I915_TILING_X ||
|
||||
cache->fb.fence_reg == I915_FENCE_REG_NONE) {
|
||||
if (!cache->vma->fence) {
|
||||
fbc->no_fbc_reason = "framebuffer not tiled or fenced";
|
||||
return false;
|
||||
}
|
||||
@ -888,17 +877,16 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
|
||||
* zero. */
|
||||
memset(params, 0, sizeof(*params));
|
||||
|
||||
params->vma = cache->vma;
|
||||
|
||||
params->crtc.pipe = crtc->pipe;
|
||||
params->crtc.plane = crtc->plane;
|
||||
params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc);
|
||||
|
||||
params->fb.pixel_format = cache->fb.pixel_format;
|
||||
params->fb.stride = cache->fb.stride;
|
||||
params->fb.fence_reg = cache->fb.fence_reg;
|
||||
|
||||
params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);
|
||||
|
||||
params->fb.ggtt_offset = cache->fb.ilk_ggtt_offset;
|
||||
}
|
||||
|
||||
static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1,
|
||||
|
@ -284,7 +284,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
||||
out_destroy_fbi:
|
||||
drm_fb_helper_release_fbi(helper);
|
||||
out_unpin:
|
||||
intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0);
|
||||
intel_unpin_fb_vma(vma);
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
@ -549,7 +549,7 @@ static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
|
||||
|
||||
if (ifbdev->fb) {
|
||||
mutex_lock(&ifbdev->helper.dev->struct_mutex);
|
||||
intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0);
|
||||
intel_unpin_fb_vma(ifbdev->vma);
|
||||
mutex_unlock(&ifbdev->helper.dev->struct_mutex);
|
||||
|
||||
drm_framebuffer_remove(&ifbdev->fb->base);
|
||||
|
@ -273,7 +273,7 @@ skl_update_plane(struct drm_plane *drm_plane,
|
||||
|
||||
I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
|
||||
I915_WRITE(PLANE_SURF(pipe, plane),
|
||||
intel_fb_gtt_offset(fb, rotation) + surf_addr);
|
||||
intel_plane_ggtt_offset(plane_state) + surf_addr);
|
||||
POSTING_READ(PLANE_SURF(pipe, plane));
|
||||
}
|
||||
|
||||
@ -458,7 +458,7 @@ vlv_update_plane(struct drm_plane *dplane,
|
||||
I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
|
||||
I915_WRITE(SPCNTR(pipe, plane), sprctl);
|
||||
I915_WRITE(SPSURF(pipe, plane),
|
||||
intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
|
||||
intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
|
||||
POSTING_READ(SPSURF(pipe, plane));
|
||||
}
|
||||
|
||||
@ -594,7 +594,7 @@ ivb_update_plane(struct drm_plane *plane,
|
||||
I915_WRITE(SPRSCALE(pipe), sprscale);
|
||||
I915_WRITE(SPRCTL(pipe), sprctl);
|
||||
I915_WRITE(SPRSURF(pipe),
|
||||
intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
|
||||
intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
|
||||
POSTING_READ(SPRSURF(pipe));
|
||||
}
|
||||
|
||||
@ -721,7 +721,7 @@ ilk_update_plane(struct drm_plane *plane,
|
||||
I915_WRITE(DVSSCALE(pipe), dvsscale);
|
||||
I915_WRITE(DVSCNTR(pipe), dvscntr);
|
||||
I915_WRITE(DVSSURF(pipe),
|
||||
intel_fb_gtt_offset(fb, rotation) + dvssurf_offset);
|
||||
intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
|
||||
POSTING_READ(DVSSURF(pipe));
|
||||
}
|
||||
|
||||
|
@ -222,6 +222,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)
|
||||
uint32_t mpllP;
|
||||
|
||||
pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP);
|
||||
mpllP = (mpllP >> 8) & 0xf;
|
||||
if (!mpllP)
|
||||
mpllP = 4;
|
||||
|
||||
@ -232,7 +233,7 @@ nouveau_hw_get_clock(struct drm_device *dev, enum nvbios_pll_type plltype)
|
||||
uint32_t clock;
|
||||
|
||||
pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock);
|
||||
return clock;
|
||||
return clock / 1000;
|
||||
}
|
||||
|
||||
ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals);
|
||||
|
@ -99,6 +99,7 @@ struct nv84_fence_priv {
|
||||
struct nouveau_bo *bo;
|
||||
struct nouveau_bo *bo_gart;
|
||||
u32 *suspend;
|
||||
struct mutex mutex;
|
||||
};
|
||||
|
||||
int nv84_fence_context_new(struct nouveau_channel *);
|
||||
|
@ -42,7 +42,7 @@ nouveau_led(struct drm_device *dev)
|
||||
}
|
||||
|
||||
/* nouveau_led.c */
|
||||
#if IS_ENABLED(CONFIG_LEDS_CLASS)
|
||||
#if IS_REACHABLE(CONFIG_LEDS_CLASS)
|
||||
int nouveau_led_init(struct drm_device *dev);
|
||||
void nouveau_led_suspend(struct drm_device *dev);
|
||||
void nouveau_led_resume(struct drm_device *dev);
|
||||
|
@ -313,7 +313,8 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
|
||||
if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) {
|
||||
/* block access to objects not created via this interface */
|
||||
owner = argv->v0.owner;
|
||||
if (argv->v0.object == 0ULL)
|
||||
if (argv->v0.object == 0ULL &&
|
||||
argv->v0.type != NVIF_IOCTL_V0_DEL)
|
||||
argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */
|
||||
else
|
||||
argv->v0.owner = NVDRM_OBJECT_USIF;
|
||||
|
@ -4052,6 +4052,11 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
}
|
||||
}
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
if (crtc->state->event)
|
||||
drm_crtc_vblank_get(crtc);
|
||||
}
|
||||
|
||||
/* Update plane(s). */
|
||||
for_each_plane_in_state(state, plane, plane_state, i) {
|
||||
struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state);
|
||||
@ -4101,6 +4106,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
drm_crtc_send_vblank_event(crtc, crtc->state->event);
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
crtc->state->event = NULL;
|
||||
drm_crtc_vblank_put(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,8 +107,10 @@ nv84_fence_context_del(struct nouveau_channel *chan)
|
||||
struct nv84_fence_chan *fctx = chan->fence;
|
||||
|
||||
nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
|
||||
mutex_lock(&priv->mutex);
|
||||
nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
|
||||
nouveau_bo_vma_del(priv->bo, &fctx->vma);
|
||||
mutex_unlock(&priv->mutex);
|
||||
nouveau_fence_context_del(&fctx->base);
|
||||
chan->fence = NULL;
|
||||
nouveau_fence_context_free(&fctx->base);
|
||||
@ -134,11 +136,13 @@ nv84_fence_context_new(struct nouveau_channel *chan)
|
||||
fctx->base.sync32 = nv84_fence_sync32;
|
||||
fctx->base.sequence = nv84_fence_read(chan);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
|
||||
if (ret == 0) {
|
||||
ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
|
||||
&fctx->vma_gart);
|
||||
}
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
if (ret)
|
||||
nv84_fence_context_del(chan);
|
||||
@ -212,6 +216,8 @@ nv84_fence_create(struct nouveau_drm *drm)
|
||||
priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
|
||||
priv->base.uevent = true;
|
||||
|
||||
mutex_init(&priv->mutex);
|
||||
|
||||
/* Use VRAM if there is any ; otherwise fallback to system memory */
|
||||
domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
|
||||
/*
|
||||
|
@ -59,7 +59,7 @@ gt215_hda_eld(NV50_DISP_MTHD_V1)
|
||||
);
|
||||
}
|
||||
for (i = 0; i < size; i++)
|
||||
nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[0]);
|
||||
nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[i]);
|
||||
for (; i < 0x60; i++)
|
||||
nvkm_wr32(device, 0x61c440 + soff, (i << 8));
|
||||
nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000003);
|
||||
|
@ -433,8 +433,6 @@ nv50_disp_dptmds_war(struct nvkm_device *device)
|
||||
case 0x94:
|
||||
case 0x96:
|
||||
case 0x98:
|
||||
case 0xaa:
|
||||
case 0xac:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
@ -97,9 +97,10 @@
|
||||
* 2.46.0 - Add PFP_SYNC_ME support on evergreen
|
||||
* 2.47.0 - Add UVD_NO_OP register support
|
||||
* 2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI
|
||||
* 2.49.0 - DRM_RADEON_GEM_INFO ioctl returns correct vram_size/visible values
|
||||
*/
|
||||
#define KMS_DRIVER_MAJOR 2
|
||||
#define KMS_DRIVER_MINOR 48
|
||||
#define KMS_DRIVER_MINOR 49
|
||||
#define KMS_DRIVER_PATCHLEVEL 0
|
||||
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
|
||||
int radeon_driver_unload_kms(struct drm_device *dev);
|
||||
|
@ -220,8 +220,8 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
man = &rdev->mman.bdev.man[TTM_PL_VRAM];
|
||||
|
||||
args->vram_size = rdev->mc.real_vram_size;
|
||||
args->vram_visible = (u64)man->size << PAGE_SHIFT;
|
||||
args->vram_size = (u64)man->size << PAGE_SHIFT;
|
||||
args->vram_visible = rdev->mc.visible_vram_size;
|
||||
args->vram_visible -= rdev->vram_pin_size;
|
||||
args->gart_size = rdev->mc.gtt_size;
|
||||
args->gart_size -= rdev->gart_pin_size;
|
||||
|
@ -168,7 +168,7 @@ struct cp2112_device {
|
||||
atomic_t xfer_avail;
|
||||
struct gpio_chip gc;
|
||||
u8 *in_out_buffer;
|
||||
spinlock_t lock;
|
||||
struct mutex lock;
|
||||
|
||||
struct gpio_desc *desc[8];
|
||||
bool gpio_poll;
|
||||
@ -186,10 +186,9 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
struct cp2112_device *dev = gpiochip_get_data(chip);
|
||||
struct hid_device *hdev = dev->hdev;
|
||||
u8 *buf = dev->in_out_buffer;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
mutex_lock(&dev->lock);
|
||||
|
||||
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
|
||||
CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
|
||||
@ -213,8 +212,8 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
ret = 0;
|
||||
|
||||
exit:
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
return ret <= 0 ? ret : -EIO;
|
||||
mutex_unlock(&dev->lock);
|
||||
return ret < 0 ? ret : -EIO;
|
||||
}
|
||||
|
||||
static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
@ -222,10 +221,9 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
struct cp2112_device *dev = gpiochip_get_data(chip);
|
||||
struct hid_device *hdev = dev->hdev;
|
||||
u8 *buf = dev->in_out_buffer;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
mutex_lock(&dev->lock);
|
||||
|
||||
buf[0] = CP2112_GPIO_SET;
|
||||
buf[1] = value ? 0xff : 0;
|
||||
@ -237,7 +235,7 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
if (ret < 0)
|
||||
hid_err(hdev, "error setting GPIO values: %d\n", ret);
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
mutex_unlock(&dev->lock);
|
||||
}
|
||||
|
||||
static int cp2112_gpio_get_all(struct gpio_chip *chip)
|
||||
@ -245,10 +243,9 @@ static int cp2112_gpio_get_all(struct gpio_chip *chip)
|
||||
struct cp2112_device *dev = gpiochip_get_data(chip);
|
||||
struct hid_device *hdev = dev->hdev;
|
||||
u8 *buf = dev->in_out_buffer;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
mutex_lock(&dev->lock);
|
||||
|
||||
ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf,
|
||||
CP2112_GPIO_GET_LENGTH, HID_FEATURE_REPORT,
|
||||
@ -262,7 +259,7 @@ static int cp2112_gpio_get_all(struct gpio_chip *chip)
|
||||
ret = buf[1];
|
||||
|
||||
exit:
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
mutex_unlock(&dev->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -284,10 +281,9 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
|
||||
struct cp2112_device *dev = gpiochip_get_data(chip);
|
||||
struct hid_device *hdev = dev->hdev;
|
||||
u8 *buf = dev->in_out_buffer;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
mutex_lock(&dev->lock);
|
||||
|
||||
ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
|
||||
CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
|
||||
@ -308,7 +304,7 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
mutex_unlock(&dev->lock);
|
||||
|
||||
/*
|
||||
* Set gpio value when output direction is already set,
|
||||
@ -319,7 +315,7 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
mutex_unlock(&dev->lock);
|
||||
return ret < 0 ? ret : -EIO;
|
||||
}
|
||||
|
||||
@ -1235,7 +1231,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
if (!dev->in_out_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&dev->lock);
|
||||
mutex_init(&dev->lock);
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
|
@ -76,6 +76,9 @@
|
||||
#define USB_VENDOR_ID_ALPS_JP 0x044E
|
||||
#define HID_DEVICE_ID_ALPS_U1_DUAL 0x120B
|
||||
|
||||
#define USB_VENDOR_ID_AMI 0x046b
|
||||
#define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE 0xff10
|
||||
|
||||
#define USB_VENDOR_ID_ANTON 0x1130
|
||||
#define USB_DEVICE_ID_ANTON_TOUCH_PAD 0x3101
|
||||
|
||||
|
@ -872,7 +872,7 @@ static const struct hid_device_id lg_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
|
||||
.driver_data = LG_NOGET | LG_FF4 },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
|
||||
.driver_data = LG_FF2 },
|
||||
.driver_data = LG_NOGET | LG_FF2 },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
|
||||
.driver_data = LG_FF3 },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
|
||||
|
@ -57,6 +57,7 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2, HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX, HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE, HID_QUIRK_ALWAYS_POLL },
|
||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
|
||||
|
@ -166,19 +166,21 @@ static int wacom_pl_irq(struct wacom_wac *wacom)
|
||||
wacom->id[0] = STYLUS_DEVICE_ID;
|
||||
}
|
||||
|
||||
pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
|
||||
if (features->pressure_max > 255)
|
||||
pressure = (pressure << 1) | ((data[4] >> 6) & 1);
|
||||
pressure += (features->pressure_max + 1) / 2;
|
||||
if (prox) {
|
||||
pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
|
||||
if (features->pressure_max > 255)
|
||||
pressure = (pressure << 1) | ((data[4] >> 6) & 1);
|
||||
pressure += (features->pressure_max + 1) / 2;
|
||||
|
||||
input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
|
||||
input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
|
||||
input_report_abs(input, ABS_PRESSURE, pressure);
|
||||
input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
|
||||
input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
|
||||
input_report_abs(input, ABS_PRESSURE, pressure);
|
||||
|
||||
input_report_key(input, BTN_TOUCH, data[4] & 0x08);
|
||||
input_report_key(input, BTN_STYLUS, data[4] & 0x10);
|
||||
/* Only allow the stylus2 button to be reported for the pen tool. */
|
||||
input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
|
||||
input_report_key(input, BTN_TOUCH, data[4] & 0x08);
|
||||
input_report_key(input, BTN_STYLUS, data[4] & 0x10);
|
||||
/* Only allow the stylus2 button to be reported for the pen tool. */
|
||||
input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
|
||||
}
|
||||
|
||||
if (!prox)
|
||||
wacom->id[0] = 0;
|
||||
|
@ -383,6 +383,7 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
|
||||
return ret;
|
||||
}
|
||||
|
||||
init_cached_read_index(channel);
|
||||
next_read_location = hv_get_next_read_location(inring_info);
|
||||
next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc,
|
||||
sizeof(desc),
|
||||
|
@ -775,7 +775,7 @@ static int palmas_adc_wakeup_reset(struct palmas_gpadc *adc)
|
||||
|
||||
static int palmas_gpadc_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct palmas_gpadc *adc = iio_priv(indio_dev);
|
||||
int wakeup = adc->wakeup1_enable || adc->wakeup2_enable;
|
||||
int ret;
|
||||
@ -798,7 +798,7 @@ static int palmas_gpadc_suspend(struct device *dev)
|
||||
|
||||
static int palmas_gpadc_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct palmas_gpadc *adc = iio_priv(indio_dev);
|
||||
int wakeup = adc->wakeup1_enable || adc->wakeup2_enable;
|
||||
int ret;
|
||||
|
@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, afe4403_of_match);
|
||||
|
||||
static int __maybe_unused afe4403_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));
|
||||
struct afe4403_data *afe = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
@ -443,7 +443,7 @@ static int __maybe_unused afe4403_suspend(struct device *dev)
|
||||
|
||||
static int __maybe_unused afe4403_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));
|
||||
struct afe4403_data *afe = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
|
@ -428,7 +428,7 @@ MODULE_DEVICE_TABLE(of, afe4404_of_match);
|
||||
|
||||
static int __maybe_unused afe4404_suspend(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct afe4404_data *afe = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
@ -449,7 +449,7 @@ static int __maybe_unused afe4404_suspend(struct device *dev)
|
||||
|
||||
static int __maybe_unused afe4404_resume(struct device *dev)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct afe4404_data *afe = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
|
@ -238,7 +238,7 @@ static irqreturn_t max30100_interrupt_handler(int irq, void *private)
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
|
||||
while (cnt || (cnt = max30100_fifo_count(data) > 0)) {
|
||||
while (cnt || (cnt = max30100_fifo_count(data)) > 0) {
|
||||
ret = max30100_read_measurement(data);
|
||||
if (ret)
|
||||
break;
|
||||
|
@ -71,7 +71,8 @@
|
||||
* a) select an implementation using busy loop polling on those systems
|
||||
* b) use the checksum to do some probabilistic decoding
|
||||
*/
|
||||
#define DHT11_START_TRANSMISSION 18 /* ms */
|
||||
#define DHT11_START_TRANSMISSION_MIN 18000 /* us */
|
||||
#define DHT11_START_TRANSMISSION_MAX 20000 /* us */
|
||||
#define DHT11_MIN_TIMERES 34000 /* ns */
|
||||
#define DHT11_THRESHOLD 49000 /* ns */
|
||||
#define DHT11_AMBIG_LOW 23000 /* ns */
|
||||
@ -228,7 +229,8 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
|
||||
ret = gpio_direction_output(dht11->gpio, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
msleep(DHT11_START_TRANSMISSION);
|
||||
usleep_range(DHT11_START_TRANSMISSION_MIN,
|
||||
DHT11_START_TRANSMISSION_MAX);
|
||||
ret = gpio_direction_input(dht11->gpio);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -901,7 +901,7 @@ void rmi_enable_irq(struct rmi_device *rmi_dev, bool clear_wake)
|
||||
data->enabled = true;
|
||||
if (clear_wake && device_may_wakeup(rmi_dev->xport->dev)) {
|
||||
retval = disable_irq_wake(irq);
|
||||
if (!retval)
|
||||
if (retval)
|
||||
dev_warn(&rmi_dev->dev,
|
||||
"Failed to disable irq for wake: %d\n",
|
||||
retval);
|
||||
@ -936,7 +936,7 @@ void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake)
|
||||
disable_irq(irq);
|
||||
if (enable_wake && device_may_wakeup(rmi_dev->xport->dev)) {
|
||||
retval = enable_irq_wake(irq);
|
||||
if (!retval)
|
||||
if (retval)
|
||||
dev_warn(&rmi_dev->dev,
|
||||
"Failed to enable irq for wake: %d\n",
|
||||
retval);
|
||||
|
@ -682,7 +682,7 @@ static int wm97xx_probe(struct device *dev)
|
||||
}
|
||||
platform_set_drvdata(wm->battery_dev, wm);
|
||||
wm->battery_dev->dev.parent = dev;
|
||||
wm->battery_dev->dev.platform_data = pdata->batt_pdata;
|
||||
wm->battery_dev->dev.platform_data = pdata ? pdata->batt_pdata : NULL;
|
||||
ret = platform_device_add(wm->battery_dev);
|
||||
if (ret < 0)
|
||||
goto batt_reg_err;
|
||||
|
@ -2733,7 +2733,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
|
||||
if (intmask & SDHCI_INT_RETUNE)
|
||||
mmc_retune_needed(host->mmc);
|
||||
|
||||
if (intmask & SDHCI_INT_CARD_INT) {
|
||||
if ((intmask & SDHCI_INT_CARD_INT) &&
|
||||
(host->ier & SDHCI_INT_CARD_INT)) {
|
||||
sdhci_enable_sdio_irq_nolock(host, false);
|
||||
host->thread_isr |= SDHCI_INT_CARD_INT;
|
||||
result = IRQ_WAKE_THREAD;
|
||||
|
@ -1152,6 +1152,12 @@ static void init_ring(struct net_device *dev)
|
||||
if (skb == NULL)
|
||||
break;
|
||||
np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
||||
if (pci_dma_mapping_error(np->pci_dev,
|
||||
np->rx_info[i].mapping)) {
|
||||
dev_kfree_skb(skb);
|
||||
np->rx_info[i].skb = NULL;
|
||||
break;
|
||||
}
|
||||
/* Grrr, we cannot offset to correctly align the IP header. */
|
||||
np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
|
||||
}
|
||||
@ -1182,8 +1188,9 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct netdev_private *np = netdev_priv(dev);
|
||||
unsigned int entry;
|
||||
unsigned int prev_tx;
|
||||
u32 status;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* be cautious here, wrapping the queue has weird semantics
|
||||
@ -1201,6 +1208,7 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
#endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
|
||||
|
||||
prev_tx = np->cur_tx;
|
||||
entry = np->cur_tx % TX_RING_SIZE;
|
||||
for (i = 0; i < skb_num_frags(skb); i++) {
|
||||
int wrap_ring = 0;
|
||||
@ -1234,6 +1242,11 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
skb_frag_size(this_frag),
|
||||
PCI_DMA_TODEVICE);
|
||||
}
|
||||
if (pci_dma_mapping_error(np->pci_dev,
|
||||
np->tx_info[entry].mapping)) {
|
||||
dev->stats.tx_dropped++;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
|
||||
np->tx_ring[entry].status = cpu_to_le32(status);
|
||||
@ -1268,8 +1281,30 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
netif_stop_queue(dev);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
err_out:
|
||||
entry = prev_tx % TX_RING_SIZE;
|
||||
np->tx_info[entry].skb = NULL;
|
||||
if (i > 0) {
|
||||
pci_unmap_single(np->pci_dev,
|
||||
np->tx_info[entry].mapping,
|
||||
skb_first_frag_len(skb),
|
||||
PCI_DMA_TODEVICE);
|
||||
np->tx_info[entry].mapping = 0;
|
||||
entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
|
||||
for (j = 1; j < i; j++) {
|
||||
pci_unmap_single(np->pci_dev,
|
||||
np->tx_info[entry].mapping,
|
||||
skb_frag_size(
|
||||
&skb_shinfo(skb)->frags[j-1]),
|
||||
PCI_DMA_TODEVICE);
|
||||
entry++;
|
||||
}
|
||||
}
|
||||
dev_kfree_skb_any(skb);
|
||||
np->cur_tx = prev_tx;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/* The interrupt handler does all of the Rx thread work and cleans up
|
||||
after the Tx thread. */
|
||||
@ -1569,6 +1604,12 @@ static void refill_rx_ring(struct net_device *dev)
|
||||
break; /* Better luck next round. */
|
||||
np->rx_info[entry].mapping =
|
||||
pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
||||
if (pci_dma_mapping_error(np->pci_dev,
|
||||
np->rx_info[entry].mapping)) {
|
||||
dev_kfree_skb(skb);
|
||||
np->rx_info[entry].skb = NULL;
|
||||
break;
|
||||
}
|
||||
np->rx_ring[entry].rxaddr =
|
||||
cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
|
||||
}
|
||||
|
@ -43,13 +43,13 @@
|
||||
#define DEFAULT_RX_RING_SIZE 512 /* must be power of 2 */
|
||||
#define MIN_RX_RING_SIZE 64
|
||||
#define MAX_RX_RING_SIZE 8192
|
||||
#define RX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \
|
||||
#define RX_RING_BYTES(bp) (macb_dma_desc_get_size(bp) \
|
||||
* (bp)->rx_ring_size)
|
||||
|
||||
#define DEFAULT_TX_RING_SIZE 512 /* must be power of 2 */
|
||||
#define MIN_TX_RING_SIZE 64
|
||||
#define MAX_TX_RING_SIZE 4096
|
||||
#define TX_RING_BYTES(bp) (sizeof(struct macb_dma_desc) \
|
||||
#define TX_RING_BYTES(bp) (macb_dma_desc_get_size(bp) \
|
||||
* (bp)->tx_ring_size)
|
||||
|
||||
/* level of occupied TX descriptors under which we wake up TX process */
|
||||
@ -78,6 +78,37 @@
|
||||
*/
|
||||
#define MACB_HALT_TIMEOUT 1230
|
||||
|
||||
/* DMA buffer descriptor might be different size
|
||||
* depends on hardware configuration.
|
||||
*/
|
||||
static unsigned int macb_dma_desc_get_size(struct macb *bp)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B)
|
||||
return sizeof(struct macb_dma_desc) + sizeof(struct macb_dma_desc_64);
|
||||
#endif
|
||||
return sizeof(struct macb_dma_desc);
|
||||
}
|
||||
|
||||
static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int idx)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
/* Dma buffer descriptor is 4 words length (instead of 2 words)
|
||||
* for 64b GEM.
|
||||
*/
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B)
|
||||
idx <<= 1;
|
||||
#endif
|
||||
return idx;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)
|
||||
{
|
||||
return (struct macb_dma_desc_64 *)((void *)desc + sizeof(struct macb_dma_desc));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ring buffer accessors */
|
||||
static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
|
||||
{
|
||||
@ -87,7 +118,9 @@ static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
|
||||
static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue,
|
||||
unsigned int index)
|
||||
{
|
||||
return &queue->tx_ring[macb_tx_ring_wrap(queue->bp, index)];
|
||||
index = macb_tx_ring_wrap(queue->bp, index);
|
||||
index = macb_adj_dma_desc_idx(queue->bp, index);
|
||||
return &queue->tx_ring[index];
|
||||
}
|
||||
|
||||
static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue,
|
||||
@ -101,7 +134,7 @@ static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index)
|
||||
dma_addr_t offset;
|
||||
|
||||
offset = macb_tx_ring_wrap(queue->bp, index) *
|
||||
sizeof(struct macb_dma_desc);
|
||||
macb_dma_desc_get_size(queue->bp);
|
||||
|
||||
return queue->tx_ring_dma + offset;
|
||||
}
|
||||
@ -113,7 +146,9 @@ static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index)
|
||||
|
||||
static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
|
||||
{
|
||||
return &bp->rx_ring[macb_rx_ring_wrap(bp, index)];
|
||||
index = macb_rx_ring_wrap(bp, index);
|
||||
index = macb_adj_dma_desc_idx(bp, index);
|
||||
return &bp->rx_ring[index];
|
||||
}
|
||||
|
||||
static void *macb_rx_buffer(struct macb *bp, unsigned int index)
|
||||
@ -560,12 +595,32 @@ static void macb_tx_unmap(struct macb *bp, struct macb_tx_skb *tx_skb)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void macb_set_addr(struct macb_dma_desc *desc, dma_addr_t addr)
|
||||
static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_t addr)
|
||||
{
|
||||
desc->addr = (u32)addr;
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
desc->addrh = (u32)(addr >> 32);
|
||||
struct macb_dma_desc_64 *desc_64;
|
||||
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
|
||||
desc_64 = macb_64b_desc(bp, desc);
|
||||
desc_64->addrh = upper_32_bits(addr);
|
||||
}
|
||||
#endif
|
||||
desc->addr = lower_32_bits(addr);
|
||||
}
|
||||
|
||||
static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc *desc)
|
||||
{
|
||||
dma_addr_t addr = 0;
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
struct macb_dma_desc_64 *desc_64;
|
||||
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
|
||||
desc_64 = macb_64b_desc(bp, desc);
|
||||
addr = ((u64)(desc_64->addrh) << 32);
|
||||
}
|
||||
#endif
|
||||
addr |= MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void macb_tx_error_task(struct work_struct *work)
|
||||
@ -649,16 +704,17 @@ static void macb_tx_error_task(struct work_struct *work)
|
||||
|
||||
/* Set end of TX queue */
|
||||
desc = macb_tx_desc(queue, 0);
|
||||
macb_set_addr(desc, 0);
|
||||
macb_set_addr(bp, desc, 0);
|
||||
desc->ctrl = MACB_BIT(TX_USED);
|
||||
|
||||
/* Make descriptor updates visible to hardware */
|
||||
wmb();
|
||||
|
||||
/* Reinitialize the TX desc queue */
|
||||
queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
|
||||
queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B)
|
||||
queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
|
||||
#endif
|
||||
/* Make TX ring reflect state of hardware */
|
||||
queue->tx_head = 0;
|
||||
@ -750,6 +806,7 @@ static void gem_rx_refill(struct macb *bp)
|
||||
unsigned int entry;
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t paddr;
|
||||
struct macb_dma_desc *desc;
|
||||
|
||||
while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail,
|
||||
bp->rx_ring_size) > 0) {
|
||||
@ -759,6 +816,7 @@ static void gem_rx_refill(struct macb *bp)
|
||||
rmb();
|
||||
|
||||
bp->rx_prepared_head++;
|
||||
desc = macb_rx_desc(bp, entry);
|
||||
|
||||
if (!bp->rx_skbuff[entry]) {
|
||||
/* allocate sk_buff for this free entry in ring */
|
||||
@ -782,14 +840,14 @@ static void gem_rx_refill(struct macb *bp)
|
||||
|
||||
if (entry == bp->rx_ring_size - 1)
|
||||
paddr |= MACB_BIT(RX_WRAP);
|
||||
macb_set_addr(&(bp->rx_ring[entry]), paddr);
|
||||
bp->rx_ring[entry].ctrl = 0;
|
||||
macb_set_addr(bp, desc, paddr);
|
||||
desc->ctrl = 0;
|
||||
|
||||
/* properly align Ethernet header */
|
||||
skb_reserve(skb, NET_IP_ALIGN);
|
||||
} else {
|
||||
bp->rx_ring[entry].addr &= ~MACB_BIT(RX_USED);
|
||||
bp->rx_ring[entry].ctrl = 0;
|
||||
desc->addr &= ~MACB_BIT(RX_USED);
|
||||
desc->ctrl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -835,16 +893,13 @@ static int gem_rx(struct macb *bp, int budget)
|
||||
bool rxused;
|
||||
|
||||
entry = macb_rx_ring_wrap(bp, bp->rx_tail);
|
||||
desc = &bp->rx_ring[entry];
|
||||
desc = macb_rx_desc(bp, entry);
|
||||
|
||||
/* Make hw descriptor updates visible to CPU */
|
||||
rmb();
|
||||
|
||||
rxused = (desc->addr & MACB_BIT(RX_USED)) ? true : false;
|
||||
addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
addr |= ((u64)(desc->addrh) << 32);
|
||||
#endif
|
||||
addr = macb_get_addr(bp, desc);
|
||||
ctrl = desc->ctrl;
|
||||
|
||||
if (!rxused)
|
||||
@ -987,15 +1042,17 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
|
||||
static inline void macb_init_rx_ring(struct macb *bp)
|
||||
{
|
||||
dma_addr_t addr;
|
||||
struct macb_dma_desc *desc = NULL;
|
||||
int i;
|
||||
|
||||
addr = bp->rx_buffers_dma;
|
||||
for (i = 0; i < bp->rx_ring_size; i++) {
|
||||
bp->rx_ring[i].addr = addr;
|
||||
bp->rx_ring[i].ctrl = 0;
|
||||
desc = macb_rx_desc(bp, i);
|
||||
macb_set_addr(bp, desc, addr);
|
||||
desc->ctrl = 0;
|
||||
addr += bp->rx_buffer_size;
|
||||
}
|
||||
bp->rx_ring[bp->rx_ring_size - 1].addr |= MACB_BIT(RX_WRAP);
|
||||
desc->addr |= MACB_BIT(RX_WRAP);
|
||||
bp->rx_tail = 0;
|
||||
}
|
||||
|
||||
@ -1008,15 +1065,14 @@ static int macb_rx(struct macb *bp, int budget)
|
||||
|
||||
for (tail = bp->rx_tail; budget > 0; tail++) {
|
||||
struct macb_dma_desc *desc = macb_rx_desc(bp, tail);
|
||||
u32 addr, ctrl;
|
||||
u32 ctrl;
|
||||
|
||||
/* Make hw descriptor updates visible to CPU */
|
||||
rmb();
|
||||
|
||||
addr = desc->addr;
|
||||
ctrl = desc->ctrl;
|
||||
|
||||
if (!(addr & MACB_BIT(RX_USED)))
|
||||
if (!(desc->addr & MACB_BIT(RX_USED)))
|
||||
break;
|
||||
|
||||
if (ctrl & MACB_BIT(RX_SOF)) {
|
||||
@ -1336,7 +1392,7 @@ static unsigned int macb_tx_map(struct macb *bp,
|
||||
i = tx_head;
|
||||
entry = macb_tx_ring_wrap(bp, i);
|
||||
ctrl = MACB_BIT(TX_USED);
|
||||
desc = &queue->tx_ring[entry];
|
||||
desc = macb_tx_desc(queue, entry);
|
||||
desc->ctrl = ctrl;
|
||||
|
||||
if (lso_ctrl) {
|
||||
@ -1358,7 +1414,7 @@ static unsigned int macb_tx_map(struct macb *bp,
|
||||
i--;
|
||||
entry = macb_tx_ring_wrap(bp, i);
|
||||
tx_skb = &queue->tx_skb[entry];
|
||||
desc = &queue->tx_ring[entry];
|
||||
desc = macb_tx_desc(queue, entry);
|
||||
|
||||
ctrl = (u32)tx_skb->size;
|
||||
if (eof) {
|
||||
@ -1379,7 +1435,7 @@ static unsigned int macb_tx_map(struct macb *bp,
|
||||
ctrl |= MACB_BF(MSS_MFS, mss_mfs);
|
||||
|
||||
/* Set TX buffer descriptor */
|
||||
macb_set_addr(desc, tx_skb->mapping);
|
||||
macb_set_addr(bp, desc, tx_skb->mapping);
|
||||
/* desc->addr must be visible to hardware before clearing
|
||||
* 'TX_USED' bit in desc->ctrl.
|
||||
*/
|
||||
@ -1586,11 +1642,9 @@ static void gem_free_rx_buffers(struct macb *bp)
|
||||
if (!skb)
|
||||
continue;
|
||||
|
||||
desc = &bp->rx_ring[i];
|
||||
addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
addr |= ((u64)(desc->addrh) << 32);
|
||||
#endif
|
||||
desc = macb_rx_desc(bp, i);
|
||||
addr = macb_get_addr(bp, desc);
|
||||
|
||||
dma_unmap_single(&bp->pdev->dev, addr, bp->rx_buffer_size,
|
||||
DMA_FROM_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
@ -1711,15 +1765,17 @@ out_err:
|
||||
static void gem_init_rings(struct macb *bp)
|
||||
{
|
||||
struct macb_queue *queue;
|
||||
struct macb_dma_desc *desc = NULL;
|
||||
unsigned int q;
|
||||
int i;
|
||||
|
||||
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
|
||||
for (i = 0; i < bp->tx_ring_size; i++) {
|
||||
queue->tx_ring[i].addr = 0;
|
||||
queue->tx_ring[i].ctrl = MACB_BIT(TX_USED);
|
||||
desc = macb_tx_desc(queue, i);
|
||||
macb_set_addr(bp, desc, 0);
|
||||
desc->ctrl = MACB_BIT(TX_USED);
|
||||
}
|
||||
queue->tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
|
||||
desc->ctrl |= MACB_BIT(TX_WRAP);
|
||||
queue->tx_head = 0;
|
||||
queue->tx_tail = 0;
|
||||
}
|
||||
@ -1733,16 +1789,18 @@ static void gem_init_rings(struct macb *bp)
|
||||
static void macb_init_rings(struct macb *bp)
|
||||
{
|
||||
int i;
|
||||
struct macb_dma_desc *desc = NULL;
|
||||
|
||||
macb_init_rx_ring(bp);
|
||||
|
||||
for (i = 0; i < bp->tx_ring_size; i++) {
|
||||
bp->queues[0].tx_ring[i].addr = 0;
|
||||
bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED);
|
||||
desc = macb_tx_desc(&bp->queues[0], i);
|
||||
macb_set_addr(bp, desc, 0);
|
||||
desc->ctrl = MACB_BIT(TX_USED);
|
||||
}
|
||||
bp->queues[0].tx_head = 0;
|
||||
bp->queues[0].tx_tail = 0;
|
||||
bp->queues[0].tx_ring[bp->tx_ring_size - 1].ctrl |= MACB_BIT(TX_WRAP);
|
||||
desc->ctrl |= MACB_BIT(TX_WRAP);
|
||||
}
|
||||
|
||||
static void macb_reset_hw(struct macb *bp)
|
||||
@ -1863,7 +1921,8 @@ static void macb_configure_dma(struct macb *bp)
|
||||
dmacfg &= ~GEM_BIT(TXCOEN);
|
||||
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
dmacfg |= GEM_BIT(ADDR64);
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B)
|
||||
dmacfg |= GEM_BIT(ADDR64);
|
||||
#endif
|
||||
netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
|
||||
dmacfg);
|
||||
@ -1910,14 +1969,16 @@ static void macb_init_hw(struct macb *bp)
|
||||
macb_configure_dma(bp);
|
||||
|
||||
/* Initialize TX and RX buffers */
|
||||
macb_writel(bp, RBQP, (u32)(bp->rx_ring_dma));
|
||||
macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma));
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
macb_writel(bp, RBQPH, (u32)(bp->rx_ring_dma >> 32));
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B)
|
||||
macb_writel(bp, RBQPH, upper_32_bits(bp->rx_ring_dma));
|
||||
#endif
|
||||
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
|
||||
queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
|
||||
queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B)
|
||||
queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
|
||||
#endif
|
||||
|
||||
/* Enable interrupts */
|
||||
@ -2627,7 +2688,8 @@ static int macb_init(struct platform_device *pdev)
|
||||
queue->IMR = GEM_IMR(hw_q - 1);
|
||||
queue->TBQP = GEM_TBQP(hw_q - 1);
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
queue->TBQPH = GEM_TBQPH(hw_q -1);
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B)
|
||||
queue->TBQPH = GEM_TBQPH(hw_q - 1);
|
||||
#endif
|
||||
} else {
|
||||
/* queue0 uses legacy registers */
|
||||
@ -2637,7 +2699,8 @@ static int macb_init(struct platform_device *pdev)
|
||||
queue->IMR = MACB_IMR;
|
||||
queue->TBQP = MACB_TBQP;
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
queue->TBQPH = MACB_TBQPH;
|
||||
if (bp->hw_dma_cap == HW_DMA_CAP_64B)
|
||||
queue->TBQPH = MACB_TBQPH;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2730,13 +2793,14 @@ static int macb_init(struct platform_device *pdev)
|
||||
static int at91ether_start(struct net_device *dev)
|
||||
{
|
||||
struct macb *lp = netdev_priv(dev);
|
||||
struct macb_dma_desc *desc;
|
||||
dma_addr_t addr;
|
||||
u32 ctl;
|
||||
int i;
|
||||
|
||||
lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
|
||||
(AT91ETHER_MAX_RX_DESCR *
|
||||
sizeof(struct macb_dma_desc)),
|
||||
macb_dma_desc_get_size(lp)),
|
||||
&lp->rx_ring_dma, GFP_KERNEL);
|
||||
if (!lp->rx_ring)
|
||||
return -ENOMEM;
|
||||
@ -2748,7 +2812,7 @@ static int at91ether_start(struct net_device *dev)
|
||||
if (!lp->rx_buffers) {
|
||||
dma_free_coherent(&lp->pdev->dev,
|
||||
AT91ETHER_MAX_RX_DESCR *
|
||||
sizeof(struct macb_dma_desc),
|
||||
macb_dma_desc_get_size(lp),
|
||||
lp->rx_ring, lp->rx_ring_dma);
|
||||
lp->rx_ring = NULL;
|
||||
return -ENOMEM;
|
||||
@ -2756,13 +2820,14 @@ static int at91ether_start(struct net_device *dev)
|
||||
|
||||
addr = lp->rx_buffers_dma;
|
||||
for (i = 0; i < AT91ETHER_MAX_RX_DESCR; i++) {
|
||||
lp->rx_ring[i].addr = addr;
|
||||
lp->rx_ring[i].ctrl = 0;
|
||||
desc = macb_rx_desc(lp, i);
|
||||
macb_set_addr(lp, desc, addr);
|
||||
desc->ctrl = 0;
|
||||
addr += AT91ETHER_MAX_RBUFF_SZ;
|
||||
}
|
||||
|
||||
/* Set the Wrap bit on the last descriptor */
|
||||
lp->rx_ring[AT91ETHER_MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
|
||||
desc->addr |= MACB_BIT(RX_WRAP);
|
||||
|
||||
/* Reset buffer index */
|
||||
lp->rx_tail = 0;
|
||||
@ -2834,7 +2899,7 @@ static int at91ether_close(struct net_device *dev)
|
||||
|
||||
dma_free_coherent(&lp->pdev->dev,
|
||||
AT91ETHER_MAX_RX_DESCR *
|
||||
sizeof(struct macb_dma_desc),
|
||||
macb_dma_desc_get_size(lp),
|
||||
lp->rx_ring, lp->rx_ring_dma);
|
||||
lp->rx_ring = NULL;
|
||||
|
||||
@ -2885,13 +2950,15 @@ static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static void at91ether_rx(struct net_device *dev)
|
||||
{
|
||||
struct macb *lp = netdev_priv(dev);
|
||||
struct macb_dma_desc *desc;
|
||||
unsigned char *p_recv;
|
||||
struct sk_buff *skb;
|
||||
unsigned int pktlen;
|
||||
|
||||
while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
|
||||
desc = macb_rx_desc(lp, lp->rx_tail);
|
||||
while (desc->addr & MACB_BIT(RX_USED)) {
|
||||
p_recv = lp->rx_buffers + lp->rx_tail * AT91ETHER_MAX_RBUFF_SZ;
|
||||
pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
|
||||
pktlen = MACB_BF(RX_FRMLEN, desc->ctrl);
|
||||
skb = netdev_alloc_skb(dev, pktlen + 2);
|
||||
if (skb) {
|
||||
skb_reserve(skb, 2);
|
||||
@ -2905,17 +2972,19 @@ static void at91ether_rx(struct net_device *dev)
|
||||
lp->stats.rx_dropped++;
|
||||
}
|
||||
|
||||
if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
|
||||
if (desc->ctrl & MACB_BIT(RX_MHASH_MATCH))
|
||||
lp->stats.multicast++;
|
||||
|
||||
/* reset ownership bit */
|
||||
lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
|
||||
desc->addr &= ~MACB_BIT(RX_USED);
|
||||
|
||||
/* wrap after last buffer */
|
||||
if (lp->rx_tail == AT91ETHER_MAX_RX_DESCR - 1)
|
||||
lp->rx_tail = 0;
|
||||
else
|
||||
lp->rx_tail++;
|
||||
|
||||
desc = macb_rx_desc(lp, lp->rx_tail);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3211,8 +3280,11 @@ static int macb_probe(struct platform_device *pdev)
|
||||
device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
|
||||
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
if (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1)) > GEM_DBW32)
|
||||
if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
|
||||
dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
|
||||
bp->hw_dma_cap = HW_DMA_CAP_64B;
|
||||
} else
|
||||
bp->hw_dma_cap = HW_DMA_CAP_32B;
|
||||
#endif
|
||||
|
||||
spin_lock_init(&bp->lock);
|
||||
|
@ -385,6 +385,8 @@
|
||||
/* Bitfields in DCFG6. */
|
||||
#define GEM_PBUF_LSO_OFFSET 27
|
||||
#define GEM_PBUF_LSO_SIZE 1
|
||||
#define GEM_DAW64_OFFSET 23
|
||||
#define GEM_DAW64_SIZE 1
|
||||
|
||||
/* Constants for CLK */
|
||||
#define MACB_CLK_DIV8 0
|
||||
@ -487,12 +489,20 @@
|
||||
struct macb_dma_desc {
|
||||
u32 addr;
|
||||
u32 ctrl;
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
u32 addrh;
|
||||
u32 resvd;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
enum macb_hw_dma_cap {
|
||||
HW_DMA_CAP_32B,
|
||||
HW_DMA_CAP_64B,
|
||||
};
|
||||
|
||||
struct macb_dma_desc_64 {
|
||||
u32 addrh;
|
||||
u32 resvd;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* DMA descriptor bitfields */
|
||||
#define MACB_RX_USED_OFFSET 0
|
||||
#define MACB_RX_USED_SIZE 1
|
||||
@ -874,6 +884,10 @@ struct macb {
|
||||
unsigned int jumbo_max_len;
|
||||
|
||||
u32 wol;
|
||||
|
||||
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
|
||||
enum macb_hw_dma_cap hw_dma_cap;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline bool macb_is_gem(struct macb *bp)
|
||||
|
@ -116,8 +116,7 @@ void xcv_setup_link(bool link_up, int link_speed)
|
||||
int speed = 2;
|
||||
|
||||
if (!xcv) {
|
||||
dev_err(&xcv->pdev->dev,
|
||||
"XCV init not done, probe may have failed\n");
|
||||
pr_err("XCV init not done, probe may have failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -362,8 +362,10 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
|
||||
status = -EPERM;
|
||||
goto err;
|
||||
}
|
||||
done:
|
||||
|
||||
/* Remember currently programmed MAC */
|
||||
ether_addr_copy(adapter->dev_mac, addr->sa_data);
|
||||
done:
|
||||
ether_addr_copy(netdev->dev_addr, addr->sa_data);
|
||||
dev_info(dev, "MAC address changed to %pM\n", addr->sa_data);
|
||||
return 0;
|
||||
@ -3618,8 +3620,10 @@ static void be_disable_if_filters(struct be_adapter *adapter)
|
||||
{
|
||||
/* Don't delete MAC on BE3 VFs without FILTMGMT privilege */
|
||||
if (!BEx_chip(adapter) || !be_virtfn(adapter) ||
|
||||
check_privilege(adapter, BE_PRIV_FILTMGMT))
|
||||
check_privilege(adapter, BE_PRIV_FILTMGMT)) {
|
||||
be_dev_mac_del(adapter, adapter->pmac_id[0]);
|
||||
eth_zero_addr(adapter->dev_mac);
|
||||
}
|
||||
|
||||
be_clear_uc_list(adapter);
|
||||
be_clear_mc_list(adapter);
|
||||
@ -3773,12 +3777,27 @@ static int be_enable_if_filters(struct be_adapter *adapter)
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Don't add MAC on BE3 VFs without FILTMGMT privilege */
|
||||
if (!BEx_chip(adapter) || !be_virtfn(adapter) ||
|
||||
check_privilege(adapter, BE_PRIV_FILTMGMT)) {
|
||||
/* Normally this condition usually true as the ->dev_mac is zeroed.
|
||||
* But on BE3 VFs the initial MAC is pre-programmed by PF and
|
||||
* subsequent be_dev_mac_add() can fail (after fresh boot)
|
||||
*/
|
||||
if (!ether_addr_equal(adapter->dev_mac, adapter->netdev->dev_addr)) {
|
||||
int old_pmac_id = -1;
|
||||
|
||||
/* Remember old programmed MAC if any - can happen on BE3 VF */
|
||||
if (!is_zero_ether_addr(adapter->dev_mac))
|
||||
old_pmac_id = adapter->pmac_id[0];
|
||||
|
||||
status = be_dev_mac_add(adapter, adapter->netdev->dev_addr);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Delete the old programmed MAC as we successfully programmed
|
||||
* a new MAC
|
||||
*/
|
||||
if (old_pmac_id >= 0 && old_pmac_id != adapter->pmac_id[0])
|
||||
be_dev_mac_del(adapter, old_pmac_id);
|
||||
|
||||
ether_addr_copy(adapter->dev_mac, adapter->netdev->dev_addr);
|
||||
}
|
||||
|
||||
@ -4552,6 +4571,10 @@ static int be_mac_setup(struct be_adapter *adapter)
|
||||
|
||||
memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
|
||||
memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
|
||||
|
||||
/* Initial MAC for BE3 VFs is already programmed by PF */
|
||||
if (BEx_chip(adapter) && be_virtfn(adapter))
|
||||
memcpy(adapter->dev_mac, mac, ETH_ALEN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2010,8 +2010,8 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
|
||||
if (!rxb->page)
|
||||
continue;
|
||||
|
||||
dma_unmap_single(rx_queue->dev, rxb->dma,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
dma_unmap_page(rx_queue->dev, rxb->dma,
|
||||
PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
__free_page(rxb->page);
|
||||
|
||||
rxb->page = NULL;
|
||||
|
@ -158,7 +158,7 @@ static int mlx4_reset_slave(struct mlx4_dev *dev)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int mlx4_comm_internal_err(u32 slave_read)
|
||||
int mlx4_comm_internal_err(u32 slave_read)
|
||||
{
|
||||
return (u32)COMM_CHAN_EVENT_INTERNAL_ERR ==
|
||||
(slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0;
|
||||
|
@ -222,6 +222,18 @@ void mlx4_unregister_device(struct mlx4_dev *dev)
|
||||
return;
|
||||
|
||||
mlx4_stop_catas_poll(dev);
|
||||
if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION &&
|
||||
mlx4_is_slave(dev)) {
|
||||
/* In mlx4_remove_one on a VF */
|
||||
u32 slave_read =
|
||||
swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read));
|
||||
|
||||
if (mlx4_comm_internal_err(slave_read)) {
|
||||
mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n",
|
||||
__func__);
|
||||
mlx4_enter_error_state(dev->persist);
|
||||
}
|
||||
}
|
||||
mutex_lock(&intf_mutex);
|
||||
|
||||
list_for_each_entry(intf, &intf_list, list)
|
||||
|
@ -1220,6 +1220,7 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type);
|
||||
void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
|
||||
|
||||
void mlx4_enter_error_state(struct mlx4_dev_persistent *persist);
|
||||
int mlx4_comm_internal_err(u32 slave_read);
|
||||
|
||||
int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
|
||||
enum mlx4_port_type *type);
|
||||
|
@ -1728,7 +1728,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
|
||||
if (cmd->cmdif_rev > CMD_IF_REV) {
|
||||
dev_err(&dev->pdev->dev, "driver does not support command interface version. driver %d, firmware %d\n",
|
||||
CMD_IF_REV, cmd->cmdif_rev);
|
||||
err = -ENOTSUPP;
|
||||
err = -EOPNOTSUPP;
|
||||
goto err_free_page;
|
||||
}
|
||||
|
||||
|
@ -791,7 +791,8 @@ void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv);
|
||||
int mlx5e_modify_rqs_vsd(struct mlx5e_priv *priv, bool vsd);
|
||||
|
||||
int mlx5e_redirect_rqt(struct mlx5e_priv *priv, u32 rqtn, int sz, int ix);
|
||||
void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv);
|
||||
void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_priv *priv, void *tirc,
|
||||
enum mlx5e_traffic_types tt);
|
||||
|
||||
int mlx5e_open_locked(struct net_device *netdev);
|
||||
int mlx5e_close_locked(struct net_device *netdev);
|
||||
@ -863,12 +864,12 @@ static inline void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv) {}
|
||||
|
||||
static inline int mlx5e_arfs_enable(struct mlx5e_priv *priv)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int mlx5e_arfs_disable(struct mlx5e_priv *priv)
|
||||
{
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#else
|
||||
int mlx5e_arfs_create_tables(struct mlx5e_priv *priv);
|
||||
|
@ -89,7 +89,7 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
|
||||
int i;
|
||||
|
||||
if (!MLX5_CAP_GEN(priv->mdev, ets))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
|
||||
for (i = 0; i < ets->ets_cap; i++) {
|
||||
@ -236,7 +236,7 @@ static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
|
||||
int err;
|
||||
|
||||
if (!MLX5_CAP_GEN(priv->mdev, ets))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = mlx5e_dbcnl_validate_ets(netdev, ets);
|
||||
if (err)
|
||||
@ -402,7 +402,7 @@ static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
struct ieee_ets ets;
|
||||
struct ieee_pfc pfc;
|
||||
int err = -ENOTSUPP;
|
||||
int err = -EOPNOTSUPP;
|
||||
int i;
|
||||
|
||||
if (!MLX5_CAP_GEN(mdev, ets))
|
||||
@ -511,6 +511,11 @@ static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
|
||||
if (!MLX5_CAP_GEN(priv->mdev, ets)) {
|
||||
netdev_err(netdev, "%s, ets is not supported\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (priority >= CEE_DCBX_MAX_PRIO) {
|
||||
netdev_err(netdev,
|
||||
"%s, priority is out of range\n", __func__);
|
||||
|
@ -595,7 +595,7 @@ static int mlx5e_get_coalesce(struct net_device *netdev,
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
||||
if (!MLX5_CAP_GEN(priv->mdev, cq_moderation))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
coal->rx_coalesce_usecs = priv->params.rx_cq_moderation.usec;
|
||||
coal->rx_max_coalesced_frames = priv->params.rx_cq_moderation.pkts;
|
||||
@ -620,7 +620,7 @@ static int mlx5e_set_coalesce(struct net_device *netdev,
|
||||
int i;
|
||||
|
||||
if (!MLX5_CAP_GEN(mdev, cq_moderation))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
|
||||
@ -980,15 +980,18 @@ static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
|
||||
|
||||
static void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
|
||||
int i;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int ctxlen = MLX5_ST_SZ_BYTES(tirc);
|
||||
int tt;
|
||||
|
||||
MLX5_SET(modify_tir_in, in, bitmask.hash, 1);
|
||||
mlx5e_build_tir_ctx_hash(tirc, priv);
|
||||
|
||||
for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
|
||||
mlx5_core_modify_tir(mdev, priv->indir_tir[i].tirn, in, inlen);
|
||||
for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
|
||||
memset(tirc, 0, ctxlen);
|
||||
mlx5e_build_indir_tir_ctx_hash(priv, tirc, tt);
|
||||
mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen);
|
||||
}
|
||||
}
|
||||
|
||||
static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
|
||||
@ -996,6 +999,7 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
int inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
|
||||
bool hash_changed = false;
|
||||
void *in;
|
||||
|
||||
if ((hfunc != ETH_RSS_HASH_NO_CHANGE) &&
|
||||
@ -1017,14 +1021,21 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
|
||||
mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, 0);
|
||||
}
|
||||
|
||||
if (key)
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE &&
|
||||
hfunc != priv->params.rss_hfunc) {
|
||||
priv->params.rss_hfunc = hfunc;
|
||||
hash_changed = true;
|
||||
}
|
||||
|
||||
if (key) {
|
||||
memcpy(priv->params.toeplitz_hash_key, key,
|
||||
sizeof(priv->params.toeplitz_hash_key));
|
||||
hash_changed = hash_changed ||
|
||||
priv->params.rss_hfunc == ETH_RSS_HASH_TOP;
|
||||
}
|
||||
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE)
|
||||
priv->params.rss_hfunc = hfunc;
|
||||
|
||||
mlx5e_modify_tirs_hash(priv, in, inlen);
|
||||
if (hash_changed)
|
||||
mlx5e_modify_tirs_hash(priv, in, inlen);
|
||||
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
@ -1296,7 +1307,7 @@ static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
|
||||
u32 mlx5_wol_mode;
|
||||
|
||||
if (!wol_supported)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (wol->wolopts & ~wol_supported)
|
||||
return -EINVAL;
|
||||
@ -1426,7 +1437,7 @@ static int set_pflag_rx_cqe_based_moder(struct net_device *netdev, bool enable)
|
||||
|
||||
if (rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE &&
|
||||
!MLX5_CAP_GEN(mdev, cq_period_start_from_cqe))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!rx_mode_changed)
|
||||
return 0;
|
||||
@ -1452,7 +1463,7 @@ static int set_pflag_rx_cqe_compress(struct net_device *netdev,
|
||||
bool reset;
|
||||
|
||||
if (!MLX5_CAP_GEN(mdev, cqe_compression))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (enable && priv->tstamp.hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) {
|
||||
netdev_err(netdev, "Can't enable cqe compression while timestamping is enabled.\n");
|
||||
|
@ -1089,7 +1089,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
|
||||
MLX5_FLOW_NAMESPACE_KERNEL);
|
||||
|
||||
if (!priv->fs.ns)
|
||||
return -EINVAL;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = mlx5e_arfs_create_tables(priv);
|
||||
if (err) {
|
||||
|
@ -92,7 +92,7 @@ static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv,
|
||||
ns = mlx5_get_flow_namespace(priv->mdev,
|
||||
MLX5_FLOW_NAMESPACE_ETHTOOL);
|
||||
if (!ns)
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
table_size = min_t(u32, BIT(MLX5_CAP_FLOWTABLE(priv->mdev,
|
||||
flow_table_properties_nic_receive.log_max_ft_size)),
|
||||
|
@ -2022,8 +2022,23 @@ static void mlx5e_build_tir_ctx_lro(void *tirc, struct mlx5e_priv *priv)
|
||||
MLX5_SET(tirc, tirc, lro_timeout_period_usecs, priv->params.lro_timeout);
|
||||
}
|
||||
|
||||
void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
|
||||
void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_priv *priv, void *tirc,
|
||||
enum mlx5e_traffic_types tt)
|
||||
{
|
||||
void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
|
||||
|
||||
#define MLX5_HASH_IP (MLX5_HASH_FIELD_SEL_SRC_IP |\
|
||||
MLX5_HASH_FIELD_SEL_DST_IP)
|
||||
|
||||
#define MLX5_HASH_IP_L4PORTS (MLX5_HASH_FIELD_SEL_SRC_IP |\
|
||||
MLX5_HASH_FIELD_SEL_DST_IP |\
|
||||
MLX5_HASH_FIELD_SEL_L4_SPORT |\
|
||||
MLX5_HASH_FIELD_SEL_L4_DPORT)
|
||||
|
||||
#define MLX5_HASH_IP_IPSEC_SPI (MLX5_HASH_FIELD_SEL_SRC_IP |\
|
||||
MLX5_HASH_FIELD_SEL_DST_IP |\
|
||||
MLX5_HASH_FIELD_SEL_IPSEC_SPI)
|
||||
|
||||
MLX5_SET(tirc, tirc, rx_hash_fn,
|
||||
mlx5e_rx_hash_fn(priv->params.rss_hfunc));
|
||||
if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
|
||||
@ -2035,6 +2050,88 @@ void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
|
||||
MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
|
||||
memcpy(rss_key, priv->params.toeplitz_hash_key, len);
|
||||
}
|
||||
|
||||
switch (tt) {
|
||||
case MLX5E_TT_IPV4_TCP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
|
||||
MLX5_L4_PROT_TYPE_TCP);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_L4PORTS);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6_TCP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
|
||||
MLX5_L4_PROT_TYPE_TCP);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_L4PORTS);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV4_UDP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
|
||||
MLX5_L4_PROT_TYPE_UDP);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_L4PORTS);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6_UDP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
|
||||
MLX5_L4_PROT_TYPE_UDP);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_L4PORTS);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV4_IPSEC_AH:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_IPSEC_SPI);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6_IPSEC_AH:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_IPSEC_SPI);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV4_IPSEC_ESP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_IPSEC_SPI);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6_IPSEC_ESP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_IPSEC_SPI);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV4:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(true, "%s: bad traffic type!\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
|
||||
@ -2404,110 +2501,13 @@ void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv)
|
||||
static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
|
||||
enum mlx5e_traffic_types tt)
|
||||
{
|
||||
void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
|
||||
|
||||
MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
|
||||
|
||||
#define MLX5_HASH_IP (MLX5_HASH_FIELD_SEL_SRC_IP |\
|
||||
MLX5_HASH_FIELD_SEL_DST_IP)
|
||||
|
||||
#define MLX5_HASH_IP_L4PORTS (MLX5_HASH_FIELD_SEL_SRC_IP |\
|
||||
MLX5_HASH_FIELD_SEL_DST_IP |\
|
||||
MLX5_HASH_FIELD_SEL_L4_SPORT |\
|
||||
MLX5_HASH_FIELD_SEL_L4_DPORT)
|
||||
|
||||
#define MLX5_HASH_IP_IPSEC_SPI (MLX5_HASH_FIELD_SEL_SRC_IP |\
|
||||
MLX5_HASH_FIELD_SEL_DST_IP |\
|
||||
MLX5_HASH_FIELD_SEL_IPSEC_SPI)
|
||||
|
||||
mlx5e_build_tir_ctx_lro(tirc, priv);
|
||||
|
||||
MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
|
||||
MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
|
||||
mlx5e_build_tir_ctx_hash(tirc, priv);
|
||||
|
||||
switch (tt) {
|
||||
case MLX5E_TT_IPV4_TCP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
|
||||
MLX5_L4_PROT_TYPE_TCP);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_L4PORTS);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6_TCP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
|
||||
MLX5_L4_PROT_TYPE_TCP);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_L4PORTS);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV4_UDP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
|
||||
MLX5_L4_PROT_TYPE_UDP);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_L4PORTS);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6_UDP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
|
||||
MLX5_L4_PROT_TYPE_UDP);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_L4PORTS);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV4_IPSEC_AH:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_IPSEC_SPI);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6_IPSEC_AH:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_IPSEC_SPI);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV4_IPSEC_ESP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_IPSEC_SPI);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6_IPSEC_ESP:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP_IPSEC_SPI);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV4:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV4);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP);
|
||||
break;
|
||||
|
||||
case MLX5E_TT_IPV6:
|
||||
MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
|
||||
MLX5_L3_PROT_TYPE_IPV6);
|
||||
MLX5_SET(rx_hash_field_select, hfso, selected_fields,
|
||||
MLX5_HASH_IP);
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(true,
|
||||
"mlx5e_build_indir_tir_ctx: bad traffic type!\n");
|
||||
}
|
||||
mlx5e_build_indir_tir_ctx_hash(priv, tirc, tt);
|
||||
}
|
||||
|
||||
static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
|
||||
@ -3331,7 +3331,7 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = {
|
||||
static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
if (!MLX5_CAP_GEN(mdev, eth_net_offloads) ||
|
||||
!MLX5_CAP_GEN(mdev, nic_flow_table) ||
|
||||
!MLX5_CAP_ETH(mdev, csum_cap) ||
|
||||
@ -3343,7 +3343,7 @@ static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
|
||||
< 3) {
|
||||
mlx5_core_warn(mdev,
|
||||
"Not creating net device, some required device capabilities are missing\n");
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
|
||||
mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
|
||||
|
@ -663,6 +663,7 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
|
||||
__be32 *saddr,
|
||||
int *out_ttl)
|
||||
{
|
||||
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
|
||||
struct rtable *rt;
|
||||
struct neighbour *n = NULL;
|
||||
int ttl;
|
||||
@ -677,12 +678,11 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
|
||||
if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev)) {
|
||||
pr_warn("%s: can't offload, devices not on same HW e-switch\n", __func__);
|
||||
ip_rt_put(rt);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
/* if the egress device isn't on the same HW e-switch, we use the uplink */
|
||||
if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev))
|
||||
*out_dev = mlx5_eswitch_get_uplink_netdev(esw);
|
||||
else
|
||||
*out_dev = rt->dst.dev;
|
||||
|
||||
ttl = ip4_dst_hoplimit(&rt->dst);
|
||||
n = dst_neigh_lookup(&rt->dst, &fl4->daddr);
|
||||
@ -693,7 +693,6 @@ static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
|
||||
*out_n = n;
|
||||
*saddr = fl4->saddr;
|
||||
*out_ttl = ttl;
|
||||
*out_dev = rt->dst.dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u32 vport,
|
||||
|
||||
if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) ||
|
||||
!MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist))
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n",
|
||||
vport, vlan, qos, set_flags);
|
||||
@ -353,7 +353,7 @@ static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw, int nvports)
|
||||
root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get FDB flow namespace\n");
|
||||
return -ENOMEM;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_group_in = mlx5_vzalloc(inlen);
|
||||
@ -962,7 +962,7 @@ static int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
|
||||
root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_EGRESS);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get E-Switch egress flow namespace\n");
|
||||
return -EIO;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_group_in = mlx5_vzalloc(inlen);
|
||||
@ -1079,7 +1079,7 @@ static int esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
|
||||
root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get E-Switch ingress flow namespace\n");
|
||||
return -EIO;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_group_in = mlx5_vzalloc(inlen);
|
||||
@ -1630,7 +1630,7 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
|
||||
if (!MLX5_CAP_GEN(esw->dev, eswitch_flow_table) ||
|
||||
!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
|
||||
esw_warn(esw->dev, "E-Switch FDB is not supported, aborting ...\n");
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
|
||||
|
@ -166,7 +166,7 @@ static int esw_add_vlan_action_check(struct mlx5_esw_flow_attr *attr,
|
||||
return 0;
|
||||
|
||||
out_notsupp:
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
|
||||
@ -424,6 +424,7 @@ static int esw_create_offloads_fdb_table(struct mlx5_eswitch *esw, int nvports)
|
||||
root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get FDB flow namespace\n");
|
||||
err = -EOPNOTSUPP;
|
||||
goto ns_err;
|
||||
}
|
||||
|
||||
@ -535,7 +536,7 @@ static int esw_create_offloads_table(struct mlx5_eswitch *esw)
|
||||
ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
|
||||
if (!ns) {
|
||||
esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
|
||||
return -ENOMEM;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0, 0);
|
||||
@ -655,7 +656,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw)
|
||||
esw_warn(esw->dev, "Failed setting eswitch to offloads, err %d\n", err);
|
||||
err1 = mlx5_eswitch_enable_sriov(esw, num_vfs, SRIOV_LEGACY);
|
||||
if (err1)
|
||||
esw_warn(esw->dev, "Failed setting eswitch back to legacy, err %d\n", err);
|
||||
esw_warn(esw->dev, "Failed setting eswitch back to legacy, err %d\n", err1);
|
||||
}
|
||||
if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
|
||||
if (mlx5_eswitch_inline_mode_get(esw,
|
||||
@ -674,9 +675,14 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int nvports)
|
||||
int vport;
|
||||
int err;
|
||||
|
||||
/* disable PF RoCE so missed packets don't go through RoCE steering */
|
||||
mlx5_dev_list_lock();
|
||||
mlx5_remove_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
|
||||
mlx5_dev_list_unlock();
|
||||
|
||||
err = esw_create_offloads_fdb_table(esw, nvports);
|
||||
if (err)
|
||||
return err;
|
||||
goto create_fdb_err;
|
||||
|
||||
err = esw_create_offloads_table(esw);
|
||||
if (err)
|
||||
@ -696,11 +702,6 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int nvports)
|
||||
goto err_reps;
|
||||
}
|
||||
|
||||
/* disable PF RoCE so missed packets don't go through RoCE steering */
|
||||
mlx5_dev_list_lock();
|
||||
mlx5_remove_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
|
||||
mlx5_dev_list_unlock();
|
||||
|
||||
return 0;
|
||||
|
||||
err_reps:
|
||||
@ -717,6 +718,13 @@ create_fg_err:
|
||||
|
||||
create_ft_err:
|
||||
esw_destroy_offloads_fdb_table(esw);
|
||||
|
||||
create_fdb_err:
|
||||
/* enable back PF RoCE */
|
||||
mlx5_dev_list_lock();
|
||||
mlx5_add_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
|
||||
mlx5_dev_list_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -724,11 +732,6 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw)
|
||||
{
|
||||
int err, err1, num_vfs = esw->dev->priv.sriov.num_vfs;
|
||||
|
||||
/* enable back PF RoCE */
|
||||
mlx5_dev_list_lock();
|
||||
mlx5_add_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
|
||||
mlx5_dev_list_unlock();
|
||||
|
||||
mlx5_eswitch_disable_sriov(esw);
|
||||
err = mlx5_eswitch_enable_sriov(esw, num_vfs, SRIOV_LEGACY);
|
||||
if (err) {
|
||||
@ -738,6 +741,11 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw)
|
||||
esw_warn(esw->dev, "Failed setting eswitch back to offloads, err %d\n", err);
|
||||
}
|
||||
|
||||
/* enable back PF RoCE */
|
||||
mlx5_dev_list_lock();
|
||||
mlx5_add_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
|
||||
mlx5_dev_list_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -322,7 +322,7 @@ int mlx5_cmd_update_fte(struct mlx5_core_dev *dev,
|
||||
flow_table_properties_nic_receive.
|
||||
flow_modify_en);
|
||||
if (!atomic_mod_cap)
|
||||
return -ENOTSUPP;
|
||||
return -EOPNOTSUPP;
|
||||
opmod = 1;
|
||||
|
||||
return mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, group_id, fte);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user