mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
Merge tag 'v6.6.117' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into odroid-6.6.y
This is the 6.6.117 stable release
This commit is contained in:
@@ -1532,6 +1532,15 @@ PAGE_SIZE multiple when read back.
|
||||
collapsing an existing range of pages. This counter is not
|
||||
present when CONFIG_TRANSPARENT_HUGEPAGE is not set.
|
||||
|
||||
thp_swpout (npn)
|
||||
Number of transparent hugepages which are swapout in one piece
|
||||
without splitting.
|
||||
|
||||
thp_swpout_fallback (npn)
|
||||
Number of transparent hugepages which were split before swapout.
|
||||
Usually because failed to allocate some continuous swap space
|
||||
for the huge page.
|
||||
|
||||
memory.numa_stat
|
||||
A read-only nested-keyed file which exists on non-root cgroups.
|
||||
|
||||
|
||||
@@ -14730,6 +14730,7 @@ NETDEVSIM
|
||||
M: Jakub Kicinski <kuba@kernel.org>
|
||||
S: Maintained
|
||||
F: drivers/net/netdevsim/*
|
||||
F: tools/testing/selftests/drivers/net/netdevsim/*
|
||||
|
||||
NETEM NETWORK EMULATOR
|
||||
M: Stephen Hemminger <stephen@networkplumber.org>
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 116
|
||||
SUBLEVEL = 117
|
||||
EXTRAVERSION =
|
||||
NAME = Pinguïn Aangedreven
|
||||
|
||||
|
||||
@@ -133,6 +133,8 @@ static inline __attribute__ ((const)) int fls(unsigned int x)
|
||||
*/
|
||||
static inline __attribute__ ((const)) unsigned long __fls(unsigned long x)
|
||||
{
|
||||
if (__builtin_constant_p(x))
|
||||
return x ? BITS_PER_LONG - 1 - __builtin_clzl(x) : 0;
|
||||
/* FLS insn has exactly same semantics as the API */
|
||||
return __builtin_arc_fls(x);
|
||||
}
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
mdio {
|
||||
/delete-node/ switch@1e;
|
||||
|
||||
bcm54210e: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
bcm54210e: ethernet-phy@25 {
|
||||
reg = <25>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -502,6 +502,9 @@
|
||||
compatible = "asahi-kasei,ak8974";
|
||||
reg = <0xe>;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(N, 5) IRQ_TYPE_EDGE_RISING>;
|
||||
|
||||
avdd-supply = <&vdd_3v3_sys>;
|
||||
dvdd-supply = <&vdd_1v8_sys>;
|
||||
|
||||
@@ -515,7 +518,7 @@
|
||||
reg = <0x1a>;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(X, 1) IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupts = <TEGRA_GPIO(X, 3) IRQ_TYPE_EDGE_BOTH>;
|
||||
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
@@ -259,7 +259,7 @@
|
||||
pinctrl-0 = <&pinctrl_audmux>;
|
||||
status = "okay";
|
||||
|
||||
ssi2 {
|
||||
mux-ssi2 {
|
||||
fsl,audmux-port = <1>;
|
||||
fsl,port-config = <
|
||||
(IMX_AUDMUX_V2_PTCR_SYN |
|
||||
@@ -271,7 +271,7 @@
|
||||
>;
|
||||
};
|
||||
|
||||
aud3 {
|
||||
mux-aud3 {
|
||||
fsl,audmux-port = <2>;
|
||||
fsl,port-config = <
|
||||
IMX_AUDMUX_V2_PTCR_SYN
|
||||
|
||||
@@ -4,7 +4,7 @@ menu "Accelerated Cryptographic Algorithms for CPU (arm)"
|
||||
|
||||
config CRYPTO_CURVE25519_NEON
|
||||
tristate "Public key crypto: Curve25519 (NEON)"
|
||||
depends on KERNEL_MODE_NEON
|
||||
depends on KERNEL_MODE_NEON && !CPU_BIG_ENDIAN
|
||||
select CRYPTO_LIB_CURVE25519_GENERIC
|
||||
select CRYPTO_ARCH_HAVE_LIB_CURVE25519
|
||||
help
|
||||
|
||||
@@ -689,6 +689,10 @@ sr_dis_exit:
|
||||
bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
|
||||
str tmp2, [pmc, #AT91_PMC_PLL_UPDT]
|
||||
|
||||
/* save acr */
|
||||
ldr tmp2, [pmc, #AT91_PMC_PLL_ACR]
|
||||
str tmp2, .saved_acr
|
||||
|
||||
/* save div. */
|
||||
mov tmp1, #0
|
||||
ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL0]
|
||||
@@ -758,7 +762,7 @@ sr_dis_exit:
|
||||
str tmp1, [pmc, #AT91_PMC_PLL_UPDT]
|
||||
|
||||
/* step 2. */
|
||||
ldr tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA
|
||||
ldr tmp1, .saved_acr
|
||||
str tmp1, [pmc, #AT91_PMC_PLL_ACR]
|
||||
|
||||
/* step 3. */
|
||||
@@ -1134,6 +1138,8 @@ ENDPROC(at91_pm_suspend_in_sram)
|
||||
.word 0
|
||||
.saved_mckr:
|
||||
.word 0
|
||||
.saved_acr:
|
||||
.word 0
|
||||
.saved_pllar:
|
||||
.word 0
|
||||
.saved_sam9_lpr:
|
||||
|
||||
@@ -482,6 +482,8 @@
|
||||
};
|
||||
|
||||
&i2s1_8ch {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s1m0_sclktx &i2s1m0_lrcktx &i2s1m0_sdi0 &i2s1m0_sdo0>;
|
||||
rockchip,trcm-sync-tx-only;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -808,8 +808,8 @@
|
||||
pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
|
||||
"MIO60", "MIO61", "MIO62", "MIO63";
|
||||
bias-disable;
|
||||
drive-strength = <4>;
|
||||
slew-rate = <SLEW_RATE_SLOW>;
|
||||
drive-strength = <12>;
|
||||
slew-rate = <SLEW_RATE_FAST>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -134,13 +134,13 @@ static inline void hw_breakpoint_thread_switch(struct task_struct *next)
|
||||
/* Determine number of BRP registers available. */
|
||||
static inline int get_num_brps(void)
|
||||
{
|
||||
return csr_read64(LOONGARCH_CSR_FWPC) & CSR_FWPC_NUM;
|
||||
return csr_read32(LOONGARCH_CSR_FWPC) & CSR_FWPC_NUM;
|
||||
}
|
||||
|
||||
/* Determine number of WRP registers available. */
|
||||
static inline int get_num_wrps(void)
|
||||
{
|
||||
return csr_read64(LOONGARCH_CSR_MWPC) & CSR_MWPC_NUM;
|
||||
return csr_read32(LOONGARCH_CSR_MWPC) & CSR_MWPC_NUM;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
@@ -448,6 +448,9 @@ static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
|
||||
|
||||
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
||||
{
|
||||
if (pte_val(pte) & _PAGE_DIRTY)
|
||||
pte_val(pte) |= _PAGE_MODIFIED;
|
||||
|
||||
return __pte((pte_val(pte) & _PAGE_CHG_MASK) |
|
||||
(pgprot_val(newprot) & ~_PAGE_CHG_MASK));
|
||||
}
|
||||
@@ -570,9 +573,11 @@ static inline struct page *pmd_page(pmd_t pmd)
|
||||
|
||||
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
|
||||
{
|
||||
pmd_val(pmd) = (pmd_val(pmd) & _HPAGE_CHG_MASK) |
|
||||
(pgprot_val(newprot) & ~_HPAGE_CHG_MASK);
|
||||
return pmd;
|
||||
if (pmd_val(pmd) & _PAGE_DIRTY)
|
||||
pmd_val(pmd) |= _PAGE_MODIFIED;
|
||||
|
||||
return __pmd((pmd_val(pmd) & _HPAGE_CHG_MASK) |
|
||||
(pgprot_val(newprot) & ~_HPAGE_CHG_MASK));
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_mkinvalid(pmd_t pmd)
|
||||
|
||||
@@ -1097,8 +1097,8 @@ static void configure_exception_vector(void)
|
||||
tlbrentry = (unsigned long)exception_handlers + 80*VECSIZE;
|
||||
|
||||
csr_write64(eentry, LOONGARCH_CSR_EENTRY);
|
||||
csr_write64(eentry, LOONGARCH_CSR_MERRENTRY);
|
||||
csr_write64(tlbrentry, LOONGARCH_CSR_TLBRENTRY);
|
||||
csr_write64(__pa(eentry), LOONGARCH_CSR_MERRENTRY);
|
||||
csr_write64(__pa(tlbrentry), LOONGARCH_CSR_TLBRENTRY);
|
||||
}
|
||||
|
||||
void per_cpu_trap_init(int cpu)
|
||||
|
||||
@@ -5,8 +5,12 @@
|
||||
compatible = "lantiq,xway", "lantiq,danube";
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
compatible = "mips,mips24Kc";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -100,6 +104,8 @@
|
||||
0x1000000 0 0x00000000 0xae00000 0 0x200000>; /* io space */
|
||||
reg = <0x7000000 0x8000 /* config space */
|
||||
0xe105400 0x400>; /* pci bridge */
|
||||
|
||||
device_type = "pci";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
/include/ "danube.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Intel EASY50712";
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyLTQ0,115200 init=/etc/preinit";
|
||||
};
|
||||
@@ -94,7 +96,7 @@
|
||||
lantiq,tx-burst-length = <4>;
|
||||
};
|
||||
|
||||
stp0: stp@e100bb0 {
|
||||
stp0: gpio@e100bb0 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "lantiq,gpio-stp-xway";
|
||||
gpio-controller;
|
||||
|
||||
@@ -466,7 +466,7 @@ void __init ltq_soc_init(void)
|
||||
/* add our generic xway clocks */
|
||||
clkdev_add_pmu("10000000.fpi", NULL, 0, 0, PMU_FPI);
|
||||
clkdev_add_pmu("1e100a00.gptu", NULL, 1, 0, PMU_GPT);
|
||||
clkdev_add_pmu("1e100bb0.stp", NULL, 1, 0, PMU_STP);
|
||||
clkdev_add_pmu("1e100bb0.gpio", NULL, 1, 0, PMU_STP);
|
||||
clkdev_add_pmu("1e100c00.serial", NULL, 0, 0, PMU_ASC1);
|
||||
clkdev_add_pmu("1e104100.dma", NULL, 1, 0, PMU_DMA);
|
||||
clkdev_add_pmu("1e100800.spi", NULL, 1, 0, PMU_SPI);
|
||||
|
||||
@@ -334,7 +334,7 @@ static enum pci_ers_result eeh_report_error(struct eeh_dev *edev,
|
||||
rc = driver->err_handler->error_detected(pdev, pci_channel_io_frozen);
|
||||
|
||||
edev->in_error = true;
|
||||
pci_uevent_ers(pdev, PCI_ERS_RESULT_NONE);
|
||||
pci_uevent_ers(pdev, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu)
|
||||
|
||||
pr_notice("CPU%u: off\n", cpu);
|
||||
|
||||
clear_tasks_mm_cpumask(cpu);
|
||||
/* Verify from the firmware if the cpu is really stopped*/
|
||||
if (cpu_ops[cpu]->cpu_is_stopped)
|
||||
ret = cpu_ops[cpu]->cpu_is_stopped(cpu);
|
||||
|
||||
@@ -82,7 +82,6 @@ _save_context:
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
move a0, sp /* pt_regs */
|
||||
la ra, ret_from_exception
|
||||
|
||||
/*
|
||||
* MSB of cause differentiates between
|
||||
@@ -91,7 +90,8 @@ _save_context:
|
||||
bge s4, zero, 1f
|
||||
|
||||
/* Handle interrupts */
|
||||
tail do_irq
|
||||
call do_irq
|
||||
j ret_from_exception
|
||||
1:
|
||||
/* Handle other exceptions */
|
||||
slli t0, s4, RISCV_LGPTR
|
||||
@@ -99,11 +99,14 @@ _save_context:
|
||||
la t2, excp_vect_table_end
|
||||
add t0, t1, t0
|
||||
/* Check if exception code lies within bounds */
|
||||
bgeu t0, t2, 1f
|
||||
REG_L t0, 0(t0)
|
||||
jr t0
|
||||
1:
|
||||
tail do_trap_unknown
|
||||
bgeu t0, t2, 3f
|
||||
REG_L t1, 0(t0)
|
||||
2: jalr t1
|
||||
j ret_from_exception
|
||||
3:
|
||||
|
||||
la t1, do_trap_unknown
|
||||
j 2b
|
||||
SYM_CODE_END(handle_exception)
|
||||
ASM_NOKPROBE(handle_exception)
|
||||
|
||||
@@ -171,6 +174,7 @@ SYM_CODE_START_NOALIGN(ret_from_exception)
|
||||
#else
|
||||
sret
|
||||
#endif
|
||||
SYM_INNER_LABEL(ret_from_exception_end, SYM_L_GLOBAL)
|
||||
SYM_CODE_END(ret_from_exception)
|
||||
ASM_NOKPROBE(ret_from_exception)
|
||||
|
||||
|
||||
@@ -318,11 +318,14 @@ void __init setup_arch(char **cmdline_p)
|
||||
/* Parse the ACPI tables for possible boot-time configuration */
|
||||
acpi_boot_table_init();
|
||||
|
||||
if (acpi_disabled) {
|
||||
#if IS_ENABLED(CONFIG_BUILTIN_DTB)
|
||||
unflatten_and_copy_device_tree();
|
||||
unflatten_and_copy_device_tree();
|
||||
#else
|
||||
unflatten_device_tree();
|
||||
unflatten_device_tree();
|
||||
#endif
|
||||
}
|
||||
|
||||
misc_mem_init();
|
||||
|
||||
init_resources();
|
||||
|
||||
@@ -16,7 +16,24 @@
|
||||
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
|
||||
extern asmlinkage void ret_from_exception(void);
|
||||
/*
|
||||
* This disables KASAN checking when reading a value from another task's stack,
|
||||
* since the other task could be running on another CPU and could have poisoned
|
||||
* the stack in the meantime.
|
||||
*/
|
||||
#define READ_ONCE_TASK_STACK(task, x) \
|
||||
({ \
|
||||
unsigned long val; \
|
||||
unsigned long addr = x; \
|
||||
if ((task) == current) \
|
||||
val = READ_ONCE(addr); \
|
||||
else \
|
||||
val = READ_ONCE_NOCHECK(addr); \
|
||||
val; \
|
||||
})
|
||||
|
||||
extern asmlinkage void handle_exception(void);
|
||||
extern unsigned long ret_from_exception_end;
|
||||
|
||||
static inline int fp_is_valid(unsigned long fp, unsigned long sp)
|
||||
{
|
||||
@@ -68,10 +85,12 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
|
||||
fp = frame->ra;
|
||||
pc = regs->ra;
|
||||
} else {
|
||||
fp = frame->fp;
|
||||
pc = ftrace_graph_ret_addr(current, &graph_idx, frame->ra,
|
||||
fp = READ_ONCE_TASK_STACK(task, frame->fp);
|
||||
pc = READ_ONCE_TASK_STACK(task, frame->ra);
|
||||
pc = ftrace_graph_ret_addr(current, &graph_idx, pc,
|
||||
&frame->ra);
|
||||
if (pc == (unsigned long)ret_from_exception) {
|
||||
if (pc >= (unsigned long)handle_exception &&
|
||||
pc < (unsigned long)&ret_from_exception_end) {
|
||||
if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc)))
|
||||
break;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define pt_dump_seq_puts(m, fmt) \
|
||||
({ \
|
||||
if (m) \
|
||||
seq_printf(m, fmt); \
|
||||
seq_puts(m, fmt); \
|
||||
})
|
||||
|
||||
/*
|
||||
|
||||
@@ -855,10 +855,9 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
|
||||
stack_size += 16;
|
||||
|
||||
save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET);
|
||||
if (save_ret) {
|
||||
if (save_ret)
|
||||
stack_size += 16; /* Save both A5 (BPF R0) and A0 */
|
||||
retval_off = stack_size;
|
||||
}
|
||||
retval_off = stack_size;
|
||||
|
||||
stack_size += nregs * 8;
|
||||
args_off = stack_size;
|
||||
|
||||
@@ -128,7 +128,6 @@ config S390
|
||||
select ARCH_WANT_DEFAULT_BPF_JIT
|
||||
select ARCH_WANT_IPC_PARSE_VERSION
|
||||
select ARCH_WANT_KERNEL_PMD_MKWRITE
|
||||
select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP
|
||||
select BUILDTIME_TABLE_SORT
|
||||
select CLONE_BACKWARDS2
|
||||
select DMA_OPS if PCI
|
||||
|
||||
@@ -138,7 +138,6 @@ struct zpci_dev {
|
||||
u8 has_resources : 1;
|
||||
u8 is_physfn : 1;
|
||||
u8 util_str_avail : 1;
|
||||
u8 irqs_registered : 1;
|
||||
u8 reserved : 2;
|
||||
unsigned int devfn; /* DEVFN part of the RID*/
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ static pci_ers_result_t zpci_event_notify_error_detected(struct pci_dev *pdev,
|
||||
pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT;
|
||||
|
||||
ers_res = driver->err_handler->error_detected(pdev, pdev->error_state);
|
||||
pci_uevent_ers(pdev, ers_res);
|
||||
if (ers_result_indicates_abort(ers_res))
|
||||
pr_info("%s: Automatic recovery failed after initial reporting\n", pci_name(pdev));
|
||||
else if (ers_res == PCI_ERS_RESULT_NEED_RESET)
|
||||
@@ -173,7 +174,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
|
||||
* is unbound or probed and that userspace can't access its
|
||||
* configuration space while we perform recovery.
|
||||
*/
|
||||
pci_dev_lock(pdev);
|
||||
device_lock(&pdev->dev);
|
||||
if (pdev->error_state == pci_channel_io_perm_failure) {
|
||||
ers_res = PCI_ERS_RESULT_DISCONNECT;
|
||||
goto out_unlock;
|
||||
@@ -212,6 +213,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
|
||||
ers_res = zpci_event_do_reset(pdev, driver);
|
||||
|
||||
if (ers_res != PCI_ERS_RESULT_RECOVERED) {
|
||||
pci_uevent_ers(pdev, PCI_ERS_RESULT_DISCONNECT);
|
||||
pr_err("%s: Automatic recovery failed; operator intervention is required\n",
|
||||
pci_name(pdev));
|
||||
goto out_unlock;
|
||||
@@ -220,8 +222,9 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
|
||||
pr_info("%s: The device is ready to resume operations\n", pci_name(pdev));
|
||||
if (driver->err_handler->resume)
|
||||
driver->err_handler->resume(pdev);
|
||||
pci_uevent_ers(pdev, PCI_ERS_RESULT_RECOVERED);
|
||||
out_unlock:
|
||||
pci_dev_unlock(pdev);
|
||||
device_unlock(&pdev->dev);
|
||||
|
||||
return ers_res;
|
||||
}
|
||||
|
||||
@@ -107,9 +107,6 @@ static int zpci_set_irq(struct zpci_dev *zdev)
|
||||
else
|
||||
rc = zpci_set_airq(zdev);
|
||||
|
||||
if (!rc)
|
||||
zdev->irqs_registered = 1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -123,9 +120,6 @@ static int zpci_clear_irq(struct zpci_dev *zdev)
|
||||
else
|
||||
rc = zpci_clear_airq(zdev);
|
||||
|
||||
if (!rc)
|
||||
zdev->irqs_registered = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -427,8 +421,7 @@ bool arch_restore_msi_irqs(struct pci_dev *pdev)
|
||||
{
|
||||
struct zpci_dev *zdev = to_zpci(pdev);
|
||||
|
||||
if (!zdev->irqs_registered)
|
||||
zpci_set_irq(zdev);
|
||||
zpci_set_irq(zdev);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#define R_SPARC_7 43
|
||||
#define R_SPARC_5 44
|
||||
#define R_SPARC_6 45
|
||||
#define R_SPARC_UA64 54
|
||||
|
||||
/* Bits present in AT_HWCAP, primarily for Sparc32. */
|
||||
#define HWCAP_SPARC_FLUSH 0x00000001
|
||||
|
||||
@@ -250,19 +250,19 @@ void insl(unsigned long, void *, unsigned long);
|
||||
#define insw insw
|
||||
#define insl insl
|
||||
|
||||
static inline void readsb(void __iomem *port, void *buf, unsigned long count)
|
||||
static inline void readsb(const volatile void __iomem *port, void *buf, unsigned long count)
|
||||
{
|
||||
insb((unsigned long __force)port, buf, count);
|
||||
}
|
||||
#define readsb readsb
|
||||
|
||||
static inline void readsw(void __iomem *port, void *buf, unsigned long count)
|
||||
static inline void readsw(const volatile void __iomem *port, void *buf, unsigned long count)
|
||||
{
|
||||
insw((unsigned long __force)port, buf, count);
|
||||
}
|
||||
#define readsw readsw
|
||||
|
||||
static inline void readsl(void __iomem *port, void *buf, unsigned long count)
|
||||
static inline void readsl(const volatile void __iomem *port, void *buf, unsigned long count)
|
||||
{
|
||||
insl((unsigned long __force)port, buf, count);
|
||||
}
|
||||
|
||||
@@ -117,6 +117,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
|
||||
break;
|
||||
#ifdef CONFIG_SPARC64
|
||||
case R_SPARC_64:
|
||||
case R_SPARC_UA64:
|
||||
location[0] = v >> 56;
|
||||
location[1] = v >> 48;
|
||||
location[2] = v >> 40;
|
||||
|
||||
@@ -199,4 +199,7 @@ static int ssl_non_raw_setup(char *str)
|
||||
return 1;
|
||||
}
|
||||
__setup("ssl-non-raw", ssl_non_raw_setup);
|
||||
__channel_help(ssl_non_raw_setup, "set serial lines to non-raw mode");
|
||||
__uml_help(ssl_non_raw_setup,
|
||||
"ssl-non-raw\n"
|
||||
" Set serial lines to non-raw mode.\n\n"
|
||||
);
|
||||
|
||||
@@ -124,7 +124,12 @@ bool emulate_vsyscall(unsigned long error_code,
|
||||
if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
|
||||
return false;
|
||||
|
||||
if (!(error_code & X86_PF_INSTR)) {
|
||||
/*
|
||||
* Assume that faults at regs->ip are because of an
|
||||
* instruction fetch. Return early and avoid
|
||||
* emulation for faults during data accesses:
|
||||
*/
|
||||
if (address != regs->ip) {
|
||||
/* Failed vsyscall read */
|
||||
if (vsyscall_mode == EMULATE)
|
||||
return false;
|
||||
@@ -136,13 +141,19 @@ bool emulate_vsyscall(unsigned long error_code,
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* X86_PF_INSTR is only set when NX is supported. When
|
||||
* available, use it to double-check that the emulation code
|
||||
* is only being used for instruction fetches:
|
||||
*/
|
||||
if (cpu_feature_enabled(X86_FEATURE_NX))
|
||||
WARN_ON_ONCE(!(error_code & X86_PF_INSTR));
|
||||
|
||||
/*
|
||||
* No point in checking CS -- the only way to get here is a user mode
|
||||
* trap to a high address, which means that we're in 64-bit user code.
|
||||
*/
|
||||
|
||||
WARN_ON_ONCE(address != regs->ip);
|
||||
|
||||
if (vsyscall_mode == NONE) {
|
||||
warn_bad_vsyscall(KERN_INFO, regs,
|
||||
"vsyscall attempted with vsyscall=none");
|
||||
|
||||
@@ -210,10 +210,13 @@ static bool need_sha_check(u32 cur_rev)
|
||||
case 0xaa001: return cur_rev <= 0xaa00116; break;
|
||||
case 0xaa002: return cur_rev <= 0xaa00218; break;
|
||||
case 0xb0021: return cur_rev <= 0xb002146; break;
|
||||
case 0xb0081: return cur_rev <= 0xb008111; break;
|
||||
case 0xb1010: return cur_rev <= 0xb101046; break;
|
||||
case 0xb2040: return cur_rev <= 0xb204031; break;
|
||||
case 0xb4040: return cur_rev <= 0xb404031; break;
|
||||
case 0xb4041: return cur_rev <= 0xb404101; break;
|
||||
case 0xb6000: return cur_rev <= 0xb600031; break;
|
||||
case 0xb6080: return cur_rev <= 0xb608031; break;
|
||||
case 0xb7000: return cur_rev <= 0xb700031; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
@@ -757,6 +757,9 @@ void fpu__clear_user_states(struct fpu *fpu)
|
||||
!fpregs_state_valid(fpu, smp_processor_id()))
|
||||
os_xrstor_supervisor(fpu->fpstate);
|
||||
|
||||
/* Ensure XFD state is in sync before reloading XSTATE */
|
||||
xfd_update_state(fpu->fpstate);
|
||||
|
||||
/* Reset user states in registers. */
|
||||
restore_fpregs_from_init_fpstate(XFEATURE_MASK_USER_RESTORE);
|
||||
|
||||
|
||||
@@ -1066,16 +1066,6 @@ static void kvm_wait(u8 *ptr, u8 val)
|
||||
*/
|
||||
void __init kvm_spinlock_init(void)
|
||||
{
|
||||
/*
|
||||
* In case host doesn't support KVM_FEATURE_PV_UNHALT there is still an
|
||||
* advantage of keeping virt_spin_lock_key enabled: virt_spin_lock() is
|
||||
* preferred over native qspinlock when vCPU is preempted.
|
||||
*/
|
||||
if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) {
|
||||
pr_info("PV spinlocks disabled, no host support\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable PV spinlocks and use native qspinlock when dedicated pCPUs
|
||||
* are available.
|
||||
@@ -1095,6 +1085,16 @@ void __init kvm_spinlock_init(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* In case host doesn't support KVM_FEATURE_PV_UNHALT there is still an
|
||||
* advantage of keeping virt_spin_lock_key enabled: virt_spin_lock() is
|
||||
* preferred over native qspinlock when vCPU is preempted.
|
||||
*/
|
||||
if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) {
|
||||
pr_info("PV spinlocks disabled, no host support\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pr_info("PV spinlocks enabled\n");
|
||||
|
||||
__pv_init_lock_hash();
|
||||
|
||||
@@ -3183,7 +3183,11 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
|
||||
if (data & DEBUGCTL_RESERVED_BITS)
|
||||
return 1;
|
||||
|
||||
if (svm_get_lbr_vmcb(svm)->save.dbgctl == data)
|
||||
break;
|
||||
|
||||
svm_get_lbr_vmcb(svm)->save.dbgctl = data;
|
||||
vmcb_mark_dirty(svm->vmcb, VMCB_LBR);
|
||||
svm_update_lbrv(vcpu);
|
||||
break;
|
||||
case MSR_VM_HSAVE_PA:
|
||||
|
||||
@@ -1995,7 +1995,7 @@ emit_jmp:
|
||||
ctx->cleanup_addr = proglen;
|
||||
|
||||
if (bpf_prog_was_classic(bpf_prog) &&
|
||||
!capable(CAP_SYS_ADMIN)) {
|
||||
!ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN)) {
|
||||
u8 *ip = image + addrs[i - 1];
|
||||
|
||||
if (emit_spectre_bhb_barrier(&prog, ip, bpf_prog))
|
||||
|
||||
@@ -848,14 +848,8 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
||||
disk = ctx->bdev->bd_disk;
|
||||
q = disk->queue;
|
||||
|
||||
/*
|
||||
* blkcg_deactivate_policy() requires queue to be frozen, we can grab
|
||||
* q_usage_counter to prevent concurrent with blkcg_deactivate_policy().
|
||||
*/
|
||||
ret = blk_queue_enter(q, 0);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
/* Prevent concurrent with blkcg_deactivate_policy() */
|
||||
mutex_lock(&q->blkcg_mutex);
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
|
||||
if (!blkcg_policy_enabled(q, pol)) {
|
||||
@@ -885,16 +879,16 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
||||
/* Drop locks to do new blkg allocation with GFP_KERNEL. */
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
|
||||
new_blkg = blkg_alloc(pos, disk, GFP_KERNEL);
|
||||
new_blkg = blkg_alloc(pos, disk, GFP_NOIO);
|
||||
if (unlikely(!new_blkg)) {
|
||||
ret = -ENOMEM;
|
||||
goto fail_exit_queue;
|
||||
goto fail_exit;
|
||||
}
|
||||
|
||||
if (radix_tree_preload(GFP_KERNEL)) {
|
||||
blkg_free(new_blkg);
|
||||
ret = -ENOMEM;
|
||||
goto fail_exit_queue;
|
||||
goto fail_exit;
|
||||
}
|
||||
|
||||
spin_lock_irq(&q->queue_lock);
|
||||
@@ -922,7 +916,7 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
|
||||
goto success;
|
||||
}
|
||||
success:
|
||||
blk_queue_exit(q);
|
||||
mutex_unlock(&q->blkcg_mutex);
|
||||
ctx->blkg = blkg;
|
||||
return 0;
|
||||
|
||||
@@ -930,9 +924,8 @@ fail_preloaded:
|
||||
radix_tree_preload_end();
|
||||
fail_unlock:
|
||||
spin_unlock_irq(&q->queue_lock);
|
||||
fail_exit_queue:
|
||||
blk_queue_exit(q);
|
||||
fail:
|
||||
fail_exit:
|
||||
mutex_unlock(&q->blkcg_mutex);
|
||||
/*
|
||||
* If queue was bypassing, we should retry. Do so after a
|
||||
* short msleep(). It isn't strictly necessary but queue
|
||||
|
||||
@@ -2323,7 +2323,7 @@ static int get_user_memory(struct hl_device *hdev, u64 addr, u64 size,
|
||||
if (rc < 0)
|
||||
goto destroy_pages;
|
||||
npages = rc;
|
||||
rc = -EFAULT;
|
||||
rc = -ENOMEM;
|
||||
goto put_pages;
|
||||
}
|
||||
userptr->npages = npages;
|
||||
|
||||
@@ -4173,10 +4173,29 @@ static int gaudi_mmap(struct hl_device *hdev, struct vm_area_struct *vma,
|
||||
vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP |
|
||||
VM_DONTCOPY | VM_NORESERVE);
|
||||
|
||||
#ifdef _HAS_DMA_MMAP_COHERENT
|
||||
/*
|
||||
* If dma_alloc_coherent() returns a vmalloc address, set VM_MIXEDMAP
|
||||
* so vm_insert_page() can handle it safely. Without this, the kernel
|
||||
* may BUG_ON due to VM_PFNMAP.
|
||||
*/
|
||||
if (is_vmalloc_addr(cpu_addr))
|
||||
vm_flags_set(vma, VM_MIXEDMAP);
|
||||
|
||||
rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr,
|
||||
(dma_addr - HOST_PHYS_BASE), size);
|
||||
if (rc)
|
||||
dev_err(hdev->dev, "dma_mmap_coherent error %d", rc);
|
||||
#else
|
||||
|
||||
rc = remap_pfn_range(vma, vma->vm_start,
|
||||
virt_to_phys(cpu_addr) >> PAGE_SHIFT,
|
||||
size, vma->vm_page_prot);
|
||||
if (rc)
|
||||
dev_err(hdev->dev, "remap_pfn_range error %d", rc);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -2985,7 +2985,6 @@ static int gaudi2_early_init(struct hl_device *hdev)
|
||||
rc = hl_fw_read_preboot_status(hdev);
|
||||
if (rc) {
|
||||
if (hdev->reset_on_preboot_fail)
|
||||
/* we are already on failure flow, so don't check if hw_fini fails. */
|
||||
hdev->asic_funcs->hw_fini(hdev, true, false);
|
||||
goto pci_fini;
|
||||
}
|
||||
@@ -2997,6 +2996,13 @@ static int gaudi2_early_init(struct hl_device *hdev)
|
||||
dev_err(hdev->dev, "failed to reset HW in dirty state (%d)\n", rc);
|
||||
goto pci_fini;
|
||||
}
|
||||
|
||||
rc = hl_fw_read_preboot_status(hdev);
|
||||
if (rc) {
|
||||
if (hdev->reset_on_preboot_fail)
|
||||
hdev->asic_funcs->hw_fini(hdev, true, false);
|
||||
goto pci_fini;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -6339,6 +6345,13 @@ static int gaudi2_mmap(struct hl_device *hdev, struct vm_area_struct *vma,
|
||||
VM_DONTCOPY | VM_NORESERVE);
|
||||
|
||||
#ifdef _HAS_DMA_MMAP_COHERENT
|
||||
/*
|
||||
* If dma_alloc_coherent() returns a vmalloc address, set VM_MIXEDMAP
|
||||
* so vm_insert_page() can handle it safely. Without this, the kernel
|
||||
* may BUG_ON due to VM_PFNMAP.
|
||||
*/
|
||||
if (is_vmalloc_addr(cpu_addr))
|
||||
vm_flags_set(vma, VM_MIXEDMAP);
|
||||
|
||||
rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr, dma_addr, size);
|
||||
if (rc)
|
||||
|
||||
@@ -2409,7 +2409,7 @@ static int gaudi2_config_bmon(struct hl_device *hdev, struct hl_debug_params *pa
|
||||
WREG32(base_reg + mmBMON_ADDRH_E3_OFFSET, 0);
|
||||
WREG32(base_reg + mmBMON_REDUCTION_OFFSET, 0);
|
||||
WREG32(base_reg + mmBMON_STM_TRC_OFFSET, 0x7 | (0xA << 8));
|
||||
WREG32(base_reg + mmBMON_CR_OFFSET, 0x77 | 0xf << 24);
|
||||
WREG32(base_reg + mmBMON_CR_OFFSET, 0x41);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1952,8 +1952,10 @@ static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
|
||||
struct acpi_video_device *dev;
|
||||
|
||||
mutex_lock(&video->device_list_lock);
|
||||
list_for_each_entry(dev, &video->video_device_list, entry)
|
||||
list_for_each_entry(dev, &video->video_device_list, entry) {
|
||||
acpi_video_dev_remove_notify_handler(dev);
|
||||
cancel_delayed_work_sync(&dev->switch_brightness_work);
|
||||
}
|
||||
mutex_unlock(&video->device_list_lock);
|
||||
|
||||
acpi_video_bus_stop_devices(video);
|
||||
|
||||
@@ -462,7 +462,6 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
|
||||
struct acpi_walk_state *next_walk_state = NULL;
|
||||
union acpi_operand_object *obj_desc;
|
||||
struct acpi_evaluate_info *info;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state);
|
||||
|
||||
@@ -546,14 +545,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
|
||||
* Delete the operands on the previous walkstate operand stack
|
||||
* (they were copied to new objects)
|
||||
*/
|
||||
for (i = 0; i < obj_desc->method.param_count; i++) {
|
||||
acpi_ut_remove_reference(this_walk_state->operands[i]);
|
||||
this_walk_state->operands[i] = NULL;
|
||||
}
|
||||
|
||||
/* Clear the operand stack */
|
||||
|
||||
this_walk_state->num_operands = 0;
|
||||
acpi_ds_clear_operands(this_walk_state);
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
|
||||
"**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
|
||||
|
||||
@@ -603,8 +603,10 @@ static int acpi_button_add(struct acpi_device *device)
|
||||
|
||||
input_set_drvdata(input, device);
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
if (error) {
|
||||
input_free_device(input);
|
||||
goto err_remove_fs;
|
||||
}
|
||||
|
||||
switch (device->device_type) {
|
||||
case ACPI_BUS_TYPE_POWER_BUTTON:
|
||||
|
||||
@@ -445,7 +445,7 @@ bool acpi_cpc_valid(void)
|
||||
if (acpi_disabled)
|
||||
return false;
|
||||
|
||||
for_each_present_cpu(cpu) {
|
||||
for_each_online_cpu(cpu) {
|
||||
cpc_ptr = per_cpu(cpc_desc_ptr, cpu);
|
||||
if (!cpc_ptr)
|
||||
return false;
|
||||
@@ -461,7 +461,7 @@ bool cppc_allow_fast_switch(void)
|
||||
struct cpc_desc *cpc_ptr;
|
||||
int cpu;
|
||||
|
||||
for_each_present_cpu(cpu) {
|
||||
for_each_online_cpu(cpu) {
|
||||
cpc_ptr = per_cpu(cpc_desc_ptr, cpu);
|
||||
desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF];
|
||||
if (!CPC_IN_SYSTEM_MEMORY(desired_reg) &&
|
||||
@@ -1368,7 +1368,7 @@ bool cppc_perf_ctrs_in_pcc(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for_each_present_cpu(cpu) {
|
||||
for_each_online_cpu(cpu) {
|
||||
struct cpc_register_resource *ref_perf_reg;
|
||||
struct cpc_desc *cpc_desc;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/node.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/dax.h>
|
||||
#include <linux/memory-tiers.h>
|
||||
|
||||
static u8 hmat_revision;
|
||||
static int hmat_disable __initdata;
|
||||
@@ -57,14 +58,20 @@ struct target_cache {
|
||||
struct node_cache_attrs cache_attrs;
|
||||
};
|
||||
|
||||
enum {
|
||||
NODE_ACCESS_CLASS_GENPORT_SINK = ACCESS_COORDINATE_MAX,
|
||||
NODE_ACCESS_CLASS_MAX,
|
||||
};
|
||||
|
||||
struct memory_target {
|
||||
struct list_head node;
|
||||
unsigned int memory_pxm;
|
||||
unsigned int processor_pxm;
|
||||
struct resource memregions;
|
||||
struct node_hmem_attrs hmem_attrs[2];
|
||||
struct access_coordinate coord[NODE_ACCESS_CLASS_MAX];
|
||||
struct list_head caches;
|
||||
struct node_cache_attrs cache_attrs;
|
||||
u8 gen_port_device_handle[ACPI_SRAT_DEVICE_HANDLE_SIZE];
|
||||
bool registered;
|
||||
};
|
||||
|
||||
@@ -119,8 +126,7 @@ static __init void alloc_memory_initiator(unsigned int cpu_pxm)
|
||||
list_add_tail(&initiator->node, &initiators);
|
||||
}
|
||||
|
||||
static __init void alloc_memory_target(unsigned int mem_pxm,
|
||||
resource_size_t start, resource_size_t len)
|
||||
static __init struct memory_target *alloc_target(unsigned int mem_pxm)
|
||||
{
|
||||
struct memory_target *target;
|
||||
|
||||
@@ -128,7 +134,7 @@ static __init void alloc_memory_target(unsigned int mem_pxm,
|
||||
if (!target) {
|
||||
target = kzalloc(sizeof(*target), GFP_KERNEL);
|
||||
if (!target)
|
||||
return;
|
||||
return NULL;
|
||||
target->memory_pxm = mem_pxm;
|
||||
target->processor_pxm = PXM_INVAL;
|
||||
target->memregions = (struct resource) {
|
||||
@@ -141,6 +147,19 @@ static __init void alloc_memory_target(unsigned int mem_pxm,
|
||||
INIT_LIST_HEAD(&target->caches);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
static __init void alloc_memory_target(unsigned int mem_pxm,
|
||||
resource_size_t start,
|
||||
resource_size_t len)
|
||||
{
|
||||
struct memory_target *target;
|
||||
|
||||
target = alloc_target(mem_pxm);
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
/*
|
||||
* There are potentially multiple ranges per PXM, so record each
|
||||
* in the per-target memregions resource tree.
|
||||
@@ -151,6 +170,18 @@ static __init void alloc_memory_target(unsigned int mem_pxm,
|
||||
start, start + len, mem_pxm);
|
||||
}
|
||||
|
||||
static __init void alloc_genport_target(unsigned int mem_pxm, u8 *handle)
|
||||
{
|
||||
struct memory_target *target;
|
||||
|
||||
target = alloc_target(mem_pxm);
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
memcpy(target->gen_port_device_handle, handle,
|
||||
ACPI_SRAT_DEVICE_HANDLE_SIZE);
|
||||
}
|
||||
|
||||
static __init const char *hmat_data_type(u8 type)
|
||||
{
|
||||
switch (type) {
|
||||
@@ -227,24 +258,24 @@ static void hmat_update_target_access(struct memory_target *target,
|
||||
{
|
||||
switch (type) {
|
||||
case ACPI_HMAT_ACCESS_LATENCY:
|
||||
target->hmem_attrs[access].read_latency = value;
|
||||
target->hmem_attrs[access].write_latency = value;
|
||||
target->coord[access].read_latency = value;
|
||||
target->coord[access].write_latency = value;
|
||||
break;
|
||||
case ACPI_HMAT_READ_LATENCY:
|
||||
target->hmem_attrs[access].read_latency = value;
|
||||
target->coord[access].read_latency = value;
|
||||
break;
|
||||
case ACPI_HMAT_WRITE_LATENCY:
|
||||
target->hmem_attrs[access].write_latency = value;
|
||||
target->coord[access].write_latency = value;
|
||||
break;
|
||||
case ACPI_HMAT_ACCESS_BANDWIDTH:
|
||||
target->hmem_attrs[access].read_bandwidth = value;
|
||||
target->hmem_attrs[access].write_bandwidth = value;
|
||||
target->coord[access].read_bandwidth = value;
|
||||
target->coord[access].write_bandwidth = value;
|
||||
break;
|
||||
case ACPI_HMAT_READ_BANDWIDTH:
|
||||
target->hmem_attrs[access].read_bandwidth = value;
|
||||
target->coord[access].read_bandwidth = value;
|
||||
break;
|
||||
case ACPI_HMAT_WRITE_BANDWIDTH:
|
||||
target->hmem_attrs[access].write_bandwidth = value;
|
||||
target->coord[access].write_bandwidth = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -290,11 +321,28 @@ static __init void hmat_add_locality(struct acpi_hmat_locality *hmat_loc)
|
||||
}
|
||||
}
|
||||
|
||||
static __init void hmat_update_target(unsigned int tgt_pxm, unsigned int init_pxm,
|
||||
u8 mem_hier, u8 type, u32 value)
|
||||
{
|
||||
struct memory_target *target = find_mem_target(tgt_pxm);
|
||||
|
||||
if (mem_hier != ACPI_HMAT_MEMORY)
|
||||
return;
|
||||
|
||||
if (target && target->processor_pxm == init_pxm) {
|
||||
hmat_update_target_access(target, type, value,
|
||||
ACCESS_COORDINATE_LOCAL);
|
||||
/* If the node has a CPU, update access 1 */
|
||||
if (node_state(pxm_to_node(init_pxm), N_CPU))
|
||||
hmat_update_target_access(target, type, value,
|
||||
ACCESS_COORDINATE_CPU);
|
||||
}
|
||||
}
|
||||
|
||||
static __init int hmat_parse_locality(union acpi_subtable_headers *header,
|
||||
const unsigned long end)
|
||||
{
|
||||
struct acpi_hmat_locality *hmat_loc = (void *)header;
|
||||
struct memory_target *target;
|
||||
unsigned int init, targ, total_size, ipds, tpds;
|
||||
u32 *inits, *targs, value;
|
||||
u16 *entries;
|
||||
@@ -335,15 +383,8 @@ static __init int hmat_parse_locality(union acpi_subtable_headers *header,
|
||||
inits[init], targs[targ], value,
|
||||
hmat_data_type_suffix(type));
|
||||
|
||||
if (mem_hier == ACPI_HMAT_MEMORY) {
|
||||
target = find_mem_target(targs[targ]);
|
||||
if (target && target->processor_pxm == inits[init]) {
|
||||
hmat_update_target_access(target, type, value, 0);
|
||||
/* If the node has a CPU, update access 1 */
|
||||
if (node_state(pxm_to_node(inits[init]), N_CPU))
|
||||
hmat_update_target_access(target, type, value, 1);
|
||||
}
|
||||
}
|
||||
hmat_update_target(targs[targ], inits[init],
|
||||
mem_hier, type, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,6 +531,27 @@ static __init int srat_parse_mem_affinity(union acpi_subtable_headers *header,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __init int srat_parse_genport_affinity(union acpi_subtable_headers *header,
|
||||
const unsigned long end)
|
||||
{
|
||||
struct acpi_srat_generic_affinity *ga = (void *)header;
|
||||
|
||||
if (!ga)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(ga->flags & ACPI_SRAT_GENERIC_AFFINITY_ENABLED))
|
||||
return 0;
|
||||
|
||||
/* Skip PCI device_handle for now */
|
||||
if (ga->device_handle_type != 0)
|
||||
return 0;
|
||||
|
||||
alloc_genport_target(ga->proximity_domain,
|
||||
(u8 *)ga->device_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 hmat_initiator_perf(struct memory_target *target,
|
||||
struct memory_initiator *initiator,
|
||||
struct acpi_hmat_locality *hmat_loc)
|
||||
@@ -582,28 +644,31 @@ static int initiators_to_nodemask(unsigned long *p_nodes)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hmat_register_target_initiators(struct memory_target *target)
|
||||
static void hmat_update_target_attrs(struct memory_target *target,
|
||||
unsigned long *p_nodes, int access)
|
||||
{
|
||||
static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
|
||||
struct memory_initiator *initiator;
|
||||
unsigned int mem_nid, cpu_nid;
|
||||
unsigned int cpu_nid;
|
||||
struct memory_locality *loc = NULL;
|
||||
u32 best = 0;
|
||||
bool access0done = false;
|
||||
int i;
|
||||
|
||||
mem_nid = pxm_to_node(target->memory_pxm);
|
||||
/* Don't update for generic port if there's no device handle */
|
||||
if (access == NODE_ACCESS_CLASS_GENPORT_SINK &&
|
||||
!(*(u16 *)target->gen_port_device_handle))
|
||||
return;
|
||||
|
||||
bitmap_zero(p_nodes, MAX_NUMNODES);
|
||||
/*
|
||||
* If the Address Range Structure provides a local processor pxm, link
|
||||
* If the Address Range Structure provides a local processor pxm, set
|
||||
* only that one. Otherwise, find the best performance attributes and
|
||||
* register all initiators that match.
|
||||
* collect all initiators that match.
|
||||
*/
|
||||
if (target->processor_pxm != PXM_INVAL) {
|
||||
cpu_nid = pxm_to_node(target->processor_pxm);
|
||||
register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
|
||||
access0done = true;
|
||||
if (node_state(cpu_nid, N_CPU)) {
|
||||
register_memory_node_under_compute_node(mem_nid, cpu_nid, 1);
|
||||
if (access == ACCESS_COORDINATE_LOCAL ||
|
||||
node_state(cpu_nid, N_CPU)) {
|
||||
set_bit(target->processor_pxm, p_nodes);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -617,47 +682,10 @@ static void hmat_register_target_initiators(struct memory_target *target)
|
||||
* We'll also use the sorting to prime the candidate nodes with known
|
||||
* initiators.
|
||||
*/
|
||||
bitmap_zero(p_nodes, MAX_NUMNODES);
|
||||
list_sort(NULL, &initiators, initiator_cmp);
|
||||
if (initiators_to_nodemask(p_nodes) < 0)
|
||||
return;
|
||||
|
||||
if (!access0done) {
|
||||
for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
|
||||
loc = localities_types[i];
|
||||
if (!loc)
|
||||
continue;
|
||||
|
||||
best = 0;
|
||||
list_for_each_entry(initiator, &initiators, node) {
|
||||
u32 value;
|
||||
|
||||
if (!test_bit(initiator->processor_pxm, p_nodes))
|
||||
continue;
|
||||
|
||||
value = hmat_initiator_perf(target, initiator,
|
||||
loc->hmat_loc);
|
||||
if (hmat_update_best(loc->hmat_loc->data_type, value, &best))
|
||||
bitmap_clear(p_nodes, 0, initiator->processor_pxm);
|
||||
if (value != best)
|
||||
clear_bit(initiator->processor_pxm, p_nodes);
|
||||
}
|
||||
if (best)
|
||||
hmat_update_target_access(target, loc->hmat_loc->data_type,
|
||||
best, 0);
|
||||
}
|
||||
|
||||
for_each_set_bit(i, p_nodes, MAX_NUMNODES) {
|
||||
cpu_nid = pxm_to_node(i);
|
||||
register_memory_node_under_compute_node(mem_nid, cpu_nid, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Access 1 ignores Generic Initiators */
|
||||
bitmap_zero(p_nodes, MAX_NUMNODES);
|
||||
if (initiators_to_nodemask(p_nodes) < 0)
|
||||
return;
|
||||
|
||||
for (i = WRITE_LATENCY; i <= READ_BANDWIDTH; i++) {
|
||||
loc = localities_types[i];
|
||||
if (!loc)
|
||||
@@ -667,7 +695,8 @@ static void hmat_register_target_initiators(struct memory_target *target)
|
||||
list_for_each_entry(initiator, &initiators, node) {
|
||||
u32 value;
|
||||
|
||||
if (!initiator->has_cpu) {
|
||||
if (access == ACCESS_COORDINATE_CPU &&
|
||||
!initiator->has_cpu) {
|
||||
clear_bit(initiator->processor_pxm, p_nodes);
|
||||
continue;
|
||||
}
|
||||
@@ -681,14 +710,43 @@ static void hmat_register_target_initiators(struct memory_target *target)
|
||||
clear_bit(initiator->processor_pxm, p_nodes);
|
||||
}
|
||||
if (best)
|
||||
hmat_update_target_access(target, loc->hmat_loc->data_type, best, 1);
|
||||
hmat_update_target_access(target, loc->hmat_loc->data_type, best, access);
|
||||
}
|
||||
}
|
||||
|
||||
static void __hmat_register_target_initiators(struct memory_target *target,
|
||||
unsigned long *p_nodes,
|
||||
int access)
|
||||
{
|
||||
unsigned int mem_nid, cpu_nid;
|
||||
int i;
|
||||
|
||||
mem_nid = pxm_to_node(target->memory_pxm);
|
||||
hmat_update_target_attrs(target, p_nodes, access);
|
||||
for_each_set_bit(i, p_nodes, MAX_NUMNODES) {
|
||||
cpu_nid = pxm_to_node(i);
|
||||
register_memory_node_under_compute_node(mem_nid, cpu_nid, 1);
|
||||
register_memory_node_under_compute_node(mem_nid, cpu_nid, access);
|
||||
}
|
||||
}
|
||||
|
||||
static void hmat_update_generic_target(struct memory_target *target)
|
||||
{
|
||||
static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
|
||||
|
||||
hmat_update_target_attrs(target, p_nodes,
|
||||
NODE_ACCESS_CLASS_GENPORT_SINK);
|
||||
}
|
||||
|
||||
static void hmat_register_target_initiators(struct memory_target *target)
|
||||
{
|
||||
static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
|
||||
|
||||
__hmat_register_target_initiators(target, p_nodes,
|
||||
ACCESS_COORDINATE_LOCAL);
|
||||
__hmat_register_target_initiators(target, p_nodes,
|
||||
ACCESS_COORDINATE_CPU);
|
||||
}
|
||||
|
||||
static void hmat_register_target_cache(struct memory_target *target)
|
||||
{
|
||||
unsigned mem_nid = pxm_to_node(target->memory_pxm);
|
||||
@@ -701,7 +759,7 @@ static void hmat_register_target_cache(struct memory_target *target)
|
||||
static void hmat_register_target_perf(struct memory_target *target, int access)
|
||||
{
|
||||
unsigned mem_nid = pxm_to_node(target->memory_pxm);
|
||||
node_set_perf_attrs(mem_nid, &target->hmem_attrs[access], access);
|
||||
node_set_perf_attrs(mem_nid, &target->coord[access], access);
|
||||
}
|
||||
|
||||
static void hmat_register_target_devices(struct memory_target *target)
|
||||
@@ -722,10 +780,32 @@ static void hmat_register_target_devices(struct memory_target *target)
|
||||
}
|
||||
}
|
||||
|
||||
static void hmat_register_target(struct memory_target *target)
|
||||
static void hmat_hotplug_target(struct memory_target *target)
|
||||
{
|
||||
int nid = pxm_to_node(target->memory_pxm);
|
||||
|
||||
/*
|
||||
* Skip offline nodes. This can happen when memory marked EFI_MEMORY_SP,
|
||||
* "specific purpose", is applied to all the memory in a proximity
|
||||
* domain leading to * the node being marked offline / unplugged, or if
|
||||
* memory-only "hotplug" node is offline.
|
||||
*/
|
||||
if (nid == NUMA_NO_NODE || !node_online(nid))
|
||||
return;
|
||||
|
||||
guard(mutex)(&target_lock);
|
||||
if (target->registered)
|
||||
return;
|
||||
|
||||
hmat_register_target_initiators(target);
|
||||
hmat_register_target_cache(target);
|
||||
hmat_register_target_perf(target, ACCESS_COORDINATE_LOCAL);
|
||||
hmat_register_target_perf(target, ACCESS_COORDINATE_CPU);
|
||||
target->registered = true;
|
||||
}
|
||||
|
||||
static void hmat_register_target(struct memory_target *target)
|
||||
{
|
||||
/*
|
||||
* Devices may belong to either an offline or online
|
||||
* node, so unconditionally add them.
|
||||
@@ -733,24 +813,17 @@ static void hmat_register_target(struct memory_target *target)
|
||||
hmat_register_target_devices(target);
|
||||
|
||||
/*
|
||||
* Skip offline nodes. This can happen when memory
|
||||
* marked EFI_MEMORY_SP, "specific purpose", is applied
|
||||
* to all the memory in a proximity domain leading to
|
||||
* the node being marked offline / unplugged, or if
|
||||
* memory-only "hotplug" node is offline.
|
||||
* Register generic port perf numbers. The nid may not be
|
||||
* initialized and is still NUMA_NO_NODE.
|
||||
*/
|
||||
if (nid == NUMA_NO_NODE || !node_online(nid))
|
||||
return;
|
||||
|
||||
mutex_lock(&target_lock);
|
||||
if (!target->registered) {
|
||||
hmat_register_target_initiators(target);
|
||||
hmat_register_target_cache(target);
|
||||
hmat_register_target_perf(target, 0);
|
||||
hmat_register_target_perf(target, 1);
|
||||
if (*(u16 *)target->gen_port_device_handle) {
|
||||
hmat_update_generic_target(target);
|
||||
target->registered = true;
|
||||
}
|
||||
mutex_unlock(&target_lock);
|
||||
|
||||
hmat_hotplug_target(target);
|
||||
}
|
||||
|
||||
static void hmat_register_targets(void)
|
||||
@@ -776,10 +849,65 @@ static int hmat_callback(struct notifier_block *self,
|
||||
if (!target)
|
||||
return NOTIFY_OK;
|
||||
|
||||
hmat_register_target(target);
|
||||
hmat_hotplug_target(target);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int hmat_set_default_dram_perf(void)
|
||||
{
|
||||
int rc;
|
||||
int nid, pxm;
|
||||
struct memory_target *target;
|
||||
struct access_coordinate *attrs;
|
||||
|
||||
if (!default_dram_type)
|
||||
return -EIO;
|
||||
|
||||
for_each_node_mask(nid, default_dram_type->nodes) {
|
||||
pxm = node_to_pxm(nid);
|
||||
target = find_mem_target(pxm);
|
||||
if (!target)
|
||||
continue;
|
||||
attrs = &target->coord[1];
|
||||
rc = mt_set_default_dram_perf(nid, attrs, "ACPI HMAT");
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hmat_calculate_adistance(struct notifier_block *self,
|
||||
unsigned long nid, void *data)
|
||||
{
|
||||
static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
|
||||
struct memory_target *target;
|
||||
struct access_coordinate *perf;
|
||||
int *adist = data;
|
||||
int pxm;
|
||||
|
||||
pxm = node_to_pxm(nid);
|
||||
target = find_mem_target(pxm);
|
||||
if (!target)
|
||||
return NOTIFY_OK;
|
||||
|
||||
mutex_lock(&target_lock);
|
||||
hmat_update_target_attrs(target, p_nodes, ACCESS_COORDINATE_CPU);
|
||||
mutex_unlock(&target_lock);
|
||||
|
||||
perf = &target->coord[1];
|
||||
|
||||
if (mt_perf_to_adistance(perf, adist))
|
||||
return NOTIFY_OK;
|
||||
|
||||
return NOTIFY_STOP;
|
||||
}
|
||||
|
||||
static struct notifier_block hmat_adist_nb __meminitdata = {
|
||||
.notifier_call = hmat_calculate_adistance,
|
||||
.priority = 100,
|
||||
};
|
||||
|
||||
static __init void hmat_free_structures(void)
|
||||
{
|
||||
struct memory_target *target, *tnext;
|
||||
@@ -835,6 +963,13 @@ static __init int hmat_init(void)
|
||||
ACPI_SRAT_TYPE_MEMORY_AFFINITY,
|
||||
srat_parse_mem_affinity, 0) < 0)
|
||||
goto out_put;
|
||||
|
||||
if (acpi_table_parse_entries(ACPI_SIG_SRAT,
|
||||
sizeof(struct acpi_table_srat),
|
||||
ACPI_SRAT_TYPE_GENERIC_PORT_AFFINITY,
|
||||
srat_parse_genport_affinity, 0) < 0)
|
||||
goto out_put;
|
||||
|
||||
acpi_put_table(tbl);
|
||||
|
||||
status = acpi_get_table(ACPI_SIG_HMAT, 0, &tbl);
|
||||
@@ -862,8 +997,13 @@ static __init int hmat_init(void)
|
||||
hmat_register_targets();
|
||||
|
||||
/* Keep the table and structures if the notifier may use them */
|
||||
if (!hotplug_memory_notifier(hmat_callback, HMAT_CALLBACK_PRI))
|
||||
return 0;
|
||||
if (hotplug_memory_notifier(hmat_callback, HMAT_CALLBACK_PRI))
|
||||
goto out_put;
|
||||
|
||||
if (!hmat_set_default_dram_perf())
|
||||
register_mt_adistance_algorithm(&hmat_adist_nb);
|
||||
|
||||
return 0;
|
||||
out_put:
|
||||
hmat_free_structures();
|
||||
acpi_put_table(tbl);
|
||||
|
||||
@@ -140,7 +140,7 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
|
||||
struct acpi_srat_generic_affinity *p =
|
||||
(struct acpi_srat_generic_affinity *)header;
|
||||
|
||||
if (p->device_handle_type == 0) {
|
||||
if (p->device_handle_type == 1) {
|
||||
/*
|
||||
* For pci devices this may be the only place they
|
||||
* are assigned a proximity domain
|
||||
|
||||
@@ -150,15 +150,28 @@ acpi_parse_prmt(union acpi_subtable_headers *header, const unsigned long end)
|
||||
th = &tm->handlers[cur_handler];
|
||||
|
||||
guid_copy(&th->guid, (guid_t *)handler_info->handler_guid);
|
||||
|
||||
/*
|
||||
* Print an error message if handler_address is NULL, the parse of VA also
|
||||
* can be skipped.
|
||||
*/
|
||||
if (unlikely(!handler_info->handler_address)) {
|
||||
pr_info("Skipping handler with NULL address for GUID: %pUL",
|
||||
(guid_t *)handler_info->handler_guid);
|
||||
continue;
|
||||
}
|
||||
|
||||
th->handler_addr =
|
||||
(void *)efi_pa_va_lookup(&th->guid, handler_info->handler_address);
|
||||
/*
|
||||
* Print a warning message if handler_addr is zero which is not expected to
|
||||
* ever happen.
|
||||
* Print a warning message and skip the parse of VA if handler_addr is zero
|
||||
* which is not expected to ever happen.
|
||||
*/
|
||||
if (unlikely(!th->handler_addr))
|
||||
if (unlikely(!th->handler_addr)) {
|
||||
pr_warn("Failed to find VA of handler for GUID: %pUL, PA: 0x%llx",
|
||||
&th->guid, handler_info->handler_address);
|
||||
continue;
|
||||
}
|
||||
|
||||
th->static_data_buffer_addr =
|
||||
efi_pa_va_lookup(&th->guid, handler_info->static_data_buffer_address);
|
||||
|
||||
@@ -1286,6 +1286,28 @@ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* acpi_get_next_present_subnode - Return the next present child node handle
|
||||
* @fwnode: Firmware node to find the next child node for.
|
||||
* @child: Handle to one of the device's child nodes or a null handle.
|
||||
*
|
||||
* Like acpi_get_next_subnode(), but the device nodes returned by
|
||||
* acpi_get_next_present_subnode() are guaranteed to be present.
|
||||
*
|
||||
* Returns: The fwnode handle of the next present sub-node.
|
||||
*/
|
||||
static struct fwnode_handle *
|
||||
acpi_get_next_present_subnode(const struct fwnode_handle *fwnode,
|
||||
struct fwnode_handle *child)
|
||||
{
|
||||
do {
|
||||
child = acpi_get_next_subnode(fwnode, child);
|
||||
} while (is_acpi_device_node(child) &&
|
||||
!acpi_device_is_present(to_acpi_device_node(child)));
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_node_get_parent - Return parent fwnode of this fwnode
|
||||
* @fwnode: Firmware node whose parent to get
|
||||
@@ -1629,7 +1651,7 @@ static int acpi_fwnode_irq_get(const struct fwnode_handle *fwnode,
|
||||
.property_read_string_array = \
|
||||
acpi_fwnode_property_read_string_array, \
|
||||
.get_parent = acpi_node_get_parent, \
|
||||
.get_next_child_node = acpi_get_next_subnode, \
|
||||
.get_next_child_node = acpi_get_next_present_subnode, \
|
||||
.get_named_child_node = acpi_fwnode_get_named_child_node, \
|
||||
.get_name = acpi_fwnode_get_name, \
|
||||
.get_name_prefix = acpi_fwnode_get_name_prefix, \
|
||||
|
||||
@@ -784,6 +784,8 @@ static bool acpi_info_matches_ids(struct acpi_device_info *info,
|
||||
static const char * const acpi_ignore_dep_ids[] = {
|
||||
"PNP0D80", /* Windows-compatible System Power Management Controller */
|
||||
"INT33BD", /* Intel Baytrail Mailbox Device */
|
||||
"INTC10DE", /* Intel CVS LNL */
|
||||
"INTC10E0", /* Intel CVS ARL */
|
||||
"LATT2021", /* Lattice FW Update Client Driver */
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -74,14 +74,14 @@ static BIN_ATTR_RO(cpulist, CPULIST_FILE_MAX_BYTES);
|
||||
* @dev: Device for this memory access class
|
||||
* @list_node: List element in the node's access list
|
||||
* @access: The access class rank
|
||||
* @hmem_attrs: Heterogeneous memory performance attributes
|
||||
* @coord: Heterogeneous memory performance coordinates
|
||||
*/
|
||||
struct node_access_nodes {
|
||||
struct device dev;
|
||||
struct list_head list_node;
|
||||
unsigned int access;
|
||||
#ifdef CONFIG_HMEM_REPORTING
|
||||
struct node_hmem_attrs hmem_attrs;
|
||||
struct access_coordinate coord;
|
||||
#endif
|
||||
};
|
||||
#define to_access_nodes(dev) container_of(dev, struct node_access_nodes, dev)
|
||||
@@ -126,7 +126,7 @@ static void node_access_release(struct device *dev)
|
||||
}
|
||||
|
||||
static struct node_access_nodes *node_init_node_access(struct node *node,
|
||||
unsigned int access)
|
||||
enum access_coordinate_class access)
|
||||
{
|
||||
struct node_access_nodes *access_node;
|
||||
struct device *dev;
|
||||
@@ -167,7 +167,7 @@ static ssize_t property##_show(struct device *dev, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return sysfs_emit(buf, "%u\n", \
|
||||
to_access_nodes(dev)->hmem_attrs.property); \
|
||||
to_access_nodes(dev)->coord.property); \
|
||||
} \
|
||||
static DEVICE_ATTR_RO(property)
|
||||
|
||||
@@ -187,11 +187,11 @@ static struct attribute *access_attrs[] = {
|
||||
/**
|
||||
* node_set_perf_attrs - Set the performance values for given access class
|
||||
* @nid: Node identifier to be set
|
||||
* @hmem_attrs: Heterogeneous memory performance attributes
|
||||
* @coord: Heterogeneous memory performance coordinates
|
||||
* @access: The access class the for the given attributes
|
||||
*/
|
||||
void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs,
|
||||
unsigned int access)
|
||||
void node_set_perf_attrs(unsigned int nid, struct access_coordinate *coord,
|
||||
enum access_coordinate_class access)
|
||||
{
|
||||
struct node_access_nodes *c;
|
||||
struct node *node;
|
||||
@@ -205,7 +205,7 @@ void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs,
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
c->hmem_attrs = *hmem_attrs;
|
||||
c->coord = *coord;
|
||||
for (i = 0; access_attrs[i] != NULL; i++) {
|
||||
if (sysfs_add_file_to_group(&c->dev.kobj, access_attrs[i],
|
||||
"initiators")) {
|
||||
@@ -689,7 +689,7 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
|
||||
*/
|
||||
int register_memory_node_under_compute_node(unsigned int mem_nid,
|
||||
unsigned int cpu_nid,
|
||||
unsigned int access)
|
||||
enum access_coordinate_class access)
|
||||
{
|
||||
struct node *init_node, *targ_node;
|
||||
struct node_access_nodes *initiator, *target;
|
||||
|
||||
@@ -48,8 +48,7 @@ struct regmap *__regmap_init_slimbus(struct slim_device *slimbus,
|
||||
if (IS_ERR(bus))
|
||||
return ERR_CAST(bus);
|
||||
|
||||
return __regmap_init(&slimbus->dev, bus, &slimbus->dev, config,
|
||||
lock_key, lock_name);
|
||||
return __regmap_init(&slimbus->dev, bus, slimbus, config, lock_key, lock_name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__regmap_init_slimbus);
|
||||
|
||||
@@ -63,8 +62,7 @@ struct regmap *__devm_regmap_init_slimbus(struct slim_device *slimbus,
|
||||
if (IS_ERR(bus))
|
||||
return ERR_CAST(bus);
|
||||
|
||||
return __devm_regmap_init(&slimbus->dev, bus, &slimbus, config,
|
||||
lock_key, lock_name);
|
||||
return __devm_regmap_init(&slimbus->dev, bus, slimbus, config, lock_key, lock_name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__devm_regmap_init_slimbus);
|
||||
|
||||
|
||||
@@ -1257,6 +1257,12 @@ static void btmtksdio_cmd_timeout(struct hci_dev *hdev)
|
||||
|
||||
sdio_claim_host(bdev->func);
|
||||
|
||||
/* set drv_pmctrl if BT is closed before doing reset */
|
||||
if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) {
|
||||
sdio_enable_func(bdev->func);
|
||||
btmtksdio_drv_pmctrl(bdev);
|
||||
}
|
||||
|
||||
sdio_writel(bdev->func, C_INT_EN_CLR, MTK_REG_CHLPCR, NULL);
|
||||
skb_queue_purge(&bdev->txq);
|
||||
cancel_work_sync(&bdev->txrx_work);
|
||||
@@ -1272,6 +1278,12 @@ static void btmtksdio_cmd_timeout(struct hci_dev *hdev)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* set fw_pmctrl back if BT is closed after doing reset */
|
||||
if (!test_bit(BTMTKSDIO_FUNC_ENABLED, &bdev->tx_state)) {
|
||||
btmtksdio_fw_pmctrl(bdev);
|
||||
sdio_disable_func(bdev->func);
|
||||
}
|
||||
|
||||
clear_bit(BTMTKSDIO_PATCH_ENABLED, &bdev->tx_state);
|
||||
err:
|
||||
sdio_release_host(bdev->func);
|
||||
|
||||
@@ -604,8 +604,10 @@ static int rtlbt_parse_firmware_v2(struct hci_dev *hdev,
|
||||
len += entry->len;
|
||||
}
|
||||
|
||||
if (!len)
|
||||
if (!len) {
|
||||
kvfree(ptr);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
*_buf = ptr;
|
||||
return len;
|
||||
|
||||
@@ -65,6 +65,7 @@ static struct usb_driver btusb_driver;
|
||||
#define BTUSB_INTEL_BROKEN_INITIAL_NCMD BIT(25)
|
||||
#define BTUSB_INTEL_NO_WBS_SUPPORT BIT(26)
|
||||
#define BTUSB_ACTIONS_SEMI BIT(27)
|
||||
#define BTUSB_BARROT BIT(28)
|
||||
|
||||
static const struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
@@ -770,6 +771,10 @@ static const struct usb_device_id quirks_table[] = {
|
||||
{ USB_DEVICE(0x0cb5, 0xc547), .driver_info = BTUSB_REALTEK |
|
||||
BTUSB_WIDEBAND_SPEECH },
|
||||
|
||||
/* Barrot Technology Bluetooth devices */
|
||||
{ USB_DEVICE(0x33fa, 0x0010), .driver_info = BTUSB_BARROT },
|
||||
{ USB_DEVICE(0x33fa, 0x0012), .driver_info = BTUSB_BARROT },
|
||||
|
||||
/* Actions Semiconductor ATS2851 based devices */
|
||||
{ USB_DEVICE(0x10d7, 0xb012), .driver_info = BTUSB_ACTIONS_SEMI },
|
||||
|
||||
@@ -1167,6 +1172,18 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
|
||||
}
|
||||
|
||||
if (!hci_skb_expect(skb)) {
|
||||
/* Each chunk should correspond to at least 1 or more
|
||||
* events so if there are still bytes left that doesn't
|
||||
* constitute a new event this is likely a bug in the
|
||||
* controller.
|
||||
*/
|
||||
if (count && count < HCI_EVENT_HDR_SIZE) {
|
||||
bt_dev_warn(data->hdev,
|
||||
"Unexpected continuation: %d bytes",
|
||||
count);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/* Complete frame */
|
||||
btusb_recv_event(data, skb);
|
||||
skb = NULL;
|
||||
@@ -4696,6 +4713,11 @@ static void btusb_disconnect(struct usb_interface *intf)
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
|
||||
if (data->oob_wake_irq)
|
||||
device_init_wakeup(&data->udev->dev, false);
|
||||
if (data->reset_gpio)
|
||||
gpiod_put(data->reset_gpio);
|
||||
|
||||
if (intf == data->intf) {
|
||||
if (data->isoc)
|
||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||
@@ -4706,17 +4728,11 @@ static void btusb_disconnect(struct usb_interface *intf)
|
||||
usb_driver_release_interface(&btusb_driver, data->diag);
|
||||
usb_driver_release_interface(&btusb_driver, data->intf);
|
||||
} else if (intf == data->diag) {
|
||||
usb_driver_release_interface(&btusb_driver, data->intf);
|
||||
if (data->isoc)
|
||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||
usb_driver_release_interface(&btusb_driver, data->intf);
|
||||
}
|
||||
|
||||
if (data->oob_wake_irq)
|
||||
device_init_wakeup(&data->udev->dev, false);
|
||||
|
||||
if (data->reset_gpio)
|
||||
gpiod_put(data->reset_gpio);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
}
|
||||
|
||||
|
||||
@@ -582,6 +582,9 @@ static int bcsp_recv(struct hci_uart *hu, const void *data, int count)
|
||||
struct bcsp_struct *bcsp = hu->priv;
|
||||
const unsigned char *ptr;
|
||||
|
||||
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
return -EUNATCH;
|
||||
|
||||
BT_DBG("hu %p count %d rx_state %d rx_count %ld",
|
||||
hu, count, bcsp->rx_state, bcsp->rx_count);
|
||||
|
||||
|
||||
@@ -58,9 +58,8 @@ static LIST_HEAD(misc_list);
|
||||
static DEFINE_MUTEX(misc_mtx);
|
||||
|
||||
/*
|
||||
* Assigned numbers, used for dynamic minors
|
||||
* Assigned numbers.
|
||||
*/
|
||||
#define DYNAMIC_MINORS 128 /* like dynamic majors */
|
||||
static DEFINE_IDA(misc_minors_ida);
|
||||
|
||||
static int misc_minor_alloc(int minor)
|
||||
@@ -69,34 +68,17 @@ static int misc_minor_alloc(int minor)
|
||||
|
||||
if (minor == MISC_DYNAMIC_MINOR) {
|
||||
/* allocate free id */
|
||||
ret = ida_alloc_max(&misc_minors_ida, DYNAMIC_MINORS - 1, GFP_KERNEL);
|
||||
if (ret >= 0) {
|
||||
ret = DYNAMIC_MINORS - ret - 1;
|
||||
} else {
|
||||
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
|
||||
MINORMASK, GFP_KERNEL);
|
||||
}
|
||||
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
|
||||
MINORMASK, GFP_KERNEL);
|
||||
} else {
|
||||
/* specific minor, check if it is in dynamic or misc dynamic range */
|
||||
if (minor < DYNAMIC_MINORS) {
|
||||
minor = DYNAMIC_MINORS - minor - 1;
|
||||
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
|
||||
} else if (minor > MISC_DYNAMIC_MINOR) {
|
||||
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
|
||||
} else {
|
||||
/* case of non-dynamic minors, no need to allocate id */
|
||||
ret = 0;
|
||||
}
|
||||
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void misc_minor_free(int minor)
|
||||
{
|
||||
if (minor < DYNAMIC_MINORS)
|
||||
ida_free(&misc_minors_ida, DYNAMIC_MINORS - minor - 1);
|
||||
else if (minor > MISC_DYNAMIC_MINOR)
|
||||
ida_free(&misc_minors_ida, minor);
|
||||
ida_free(&misc_minors_ida, minor);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
@@ -150,7 +132,8 @@ static int misc_open(struct inode *inode, struct file *file)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!new_fops) {
|
||||
/* Only request module for fixed minor code */
|
||||
if (!new_fops && minor < MISC_DYNAMIC_MINOR) {
|
||||
mutex_unlock(&misc_mtx);
|
||||
request_module("char-major-%d-%d", MISC_MAJOR, minor);
|
||||
mutex_lock(&misc_mtx);
|
||||
@@ -162,10 +145,11 @@ static int misc_open(struct inode *inode, struct file *file)
|
||||
new_fops = fops_get(iter->fops);
|
||||
break;
|
||||
}
|
||||
if (!new_fops)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!new_fops)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Place the miscdevice in the file's
|
||||
* private_data so it can be used by the
|
||||
@@ -297,9 +281,11 @@ void misc_deregister(struct miscdevice *misc)
|
||||
return;
|
||||
|
||||
mutex_lock(&misc_mtx);
|
||||
list_del(&misc->list);
|
||||
list_del_init(&misc->list);
|
||||
device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor));
|
||||
misc_minor_free(misc->minor);
|
||||
if (misc->minor > MISC_DYNAMIC_MINOR)
|
||||
misc->minor = MISC_DYNAMIC_MINOR;
|
||||
mutex_unlock(&misc_mtx);
|
||||
}
|
||||
EXPORT_SYMBOL(misc_deregister);
|
||||
|
||||
@@ -580,6 +580,9 @@ clk_sama7g5_master_recalc_rate(struct clk_hw *hw,
|
||||
{
|
||||
struct clk_master *master = to_clk_master(hw);
|
||||
|
||||
if (master->div == MASTER_PRES_MAX)
|
||||
return DIV_ROUND_CLOSEST_ULL(parent_rate, 3);
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL(parent_rate, (1 << master->div));
|
||||
}
|
||||
|
||||
|
||||
@@ -90,8 +90,8 @@ static int sam9x60_frac_pll_set(struct sam9x60_pll_core *core)
|
||||
|
||||
spin_lock_irqsave(core->lock, flags);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, core->id);
|
||||
regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
|
||||
cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
|
||||
cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
|
||||
@@ -125,17 +125,17 @@ static int sam9x60_frac_pll_set(struct sam9x60_pll_core *core)
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
|
||||
AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
|
||||
AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
while (!sam9x60_pll_ready(regmap, core->id))
|
||||
cpu_relax();
|
||||
@@ -161,8 +161,8 @@ static void sam9x60_frac_pll_unprepare(struct clk_hw *hw)
|
||||
|
||||
spin_lock_irqsave(core->lock, flags);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, core->id);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0, AT91_PMC_PLL_CTRL0_ENPLL, 0);
|
||||
|
||||
@@ -170,9 +170,9 @@ static void sam9x60_frac_pll_unprepare(struct clk_hw *hw)
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_ACR,
|
||||
AT91_PMC_PLL_ACR_UTMIBG | AT91_PMC_PLL_ACR_UTMIVR, 0);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
spin_unlock_irqrestore(core->lock, flags);
|
||||
}
|
||||
@@ -257,8 +257,8 @@ static int sam9x60_frac_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
spin_lock_irqsave(core->lock, irqflags);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
core->id);
|
||||
regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
|
||||
cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
|
||||
cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
|
||||
@@ -270,18 +270,18 @@ static int sam9x60_frac_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
|
||||
(frac->mul << core->layout->mul_shift) |
|
||||
(frac->frac << core->layout->frac_shift));
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
|
||||
AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
|
||||
AT91_PMC_PLL_CTRL0_ENLOCK |
|
||||
AT91_PMC_PLL_CTRL0_ENPLL);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
while (!sam9x60_pll_ready(regmap, core->id))
|
||||
cpu_relax();
|
||||
@@ -333,7 +333,10 @@ static const struct clk_ops sam9x60_frac_pll_ops_chg = {
|
||||
.restore_context = sam9x60_frac_pll_restore_context,
|
||||
};
|
||||
|
||||
/* This function should be called with spinlock acquired. */
|
||||
/* This function should be called with spinlock acquired.
|
||||
* Warning: this function must be called only if the same PLL ID was set in
|
||||
* PLL_UPDT register previously.
|
||||
*/
|
||||
static void sam9x60_div_pll_set_div(struct sam9x60_pll_core *core, u32 div,
|
||||
bool enable)
|
||||
{
|
||||
@@ -345,9 +348,9 @@ static void sam9x60_div_pll_set_div(struct sam9x60_pll_core *core, u32 div,
|
||||
core->layout->div_mask | ena_msk,
|
||||
(div << core->layout->div_shift) | ena_val);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
while (!sam9x60_pll_ready(regmap, core->id))
|
||||
cpu_relax();
|
||||
@@ -361,8 +364,8 @@ static int sam9x60_div_pll_set(struct sam9x60_pll_core *core)
|
||||
unsigned int val, cdiv;
|
||||
|
||||
spin_lock_irqsave(core->lock, flags);
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, core->id);
|
||||
regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
|
||||
cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
|
||||
|
||||
@@ -393,15 +396,15 @@ static void sam9x60_div_pll_unprepare(struct clk_hw *hw)
|
||||
|
||||
spin_lock_irqsave(core->lock, flags);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_ID_MSK, core->id);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
|
||||
core->layout->endiv_mask, 0);
|
||||
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
AT91_PMC_PLL_UPDT_UPDATE | core->id);
|
||||
|
||||
spin_unlock_irqrestore(core->lock, flags);
|
||||
}
|
||||
@@ -507,8 +510,8 @@ static int sam9x60_div_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
|
||||
div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
|
||||
|
||||
spin_lock_irqsave(core->lock, irqflags);
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
core->id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
core->id);
|
||||
regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
|
||||
cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
|
||||
|
||||
@@ -563,8 +566,8 @@ static int sam9x60_div_pll_notifier_fn(struct notifier_block *notifier,
|
||||
div->div = div->safe_div;
|
||||
|
||||
spin_lock_irqsave(core.lock, irqflags);
|
||||
regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
core.id);
|
||||
regmap_write_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
|
||||
core.id);
|
||||
regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
|
||||
cdiv = (val & core.layout->div_mask) >> core.layout->div_shift;
|
||||
|
||||
|
||||
@@ -325,6 +325,13 @@ static const struct sun6i_rtc_match_data sun50i_r329_rtc_ccu_data = {
|
||||
.osc32k_fanout_nparents = ARRAY_SIZE(sun50i_r329_osc32k_fanout_parents),
|
||||
};
|
||||
|
||||
static const struct sun6i_rtc_match_data sun55i_a523_rtc_ccu_data = {
|
||||
.have_ext_osc32k = true,
|
||||
.have_iosc_calibration = true,
|
||||
.osc32k_fanout_parents = sun50i_r329_osc32k_fanout_parents,
|
||||
.osc32k_fanout_nparents = ARRAY_SIZE(sun50i_r329_osc32k_fanout_parents),
|
||||
};
|
||||
|
||||
static const struct of_device_id sun6i_rtc_ccu_match[] = {
|
||||
{
|
||||
.compatible = "allwinner,sun50i-h616-rtc",
|
||||
@@ -334,6 +341,10 @@ static const struct of_device_id sun6i_rtc_ccu_match[] = {
|
||||
.compatible = "allwinner,sun50i-r329-rtc",
|
||||
.data = &sun50i_r329_rtc_ccu_data,
|
||||
},
|
||||
{
|
||||
.compatible = "allwinner,sun55i-a523-rtc",
|
||||
.data = &sun55i_a523_rtc_ccu_data,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
@@ -258,6 +258,8 @@ static const char *enable_init_clks[] = {
|
||||
"dpll_ddr_m2_ck",
|
||||
"dpll_mpu_m2_ck",
|
||||
"l3_gclk",
|
||||
/* WKUP_DEBUGSS_CLKCTRL - disable fails, AM335x Errata Advisory 1.0.42 */
|
||||
"l3-aon-clkctrl:0000:0",
|
||||
/* AM3_L3_L3_MAIN_CLKCTRL, needed during suspend */
|
||||
"l3-clkctrl:00bc:0",
|
||||
"l4hs_gclk",
|
||||
|
||||
@@ -35,30 +35,30 @@ static unsigned long cycle_per_jiffy;
|
||||
|
||||
static inline void pit_timer_enable(void)
|
||||
{
|
||||
__raw_writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL);
|
||||
writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL);
|
||||
}
|
||||
|
||||
static inline void pit_timer_disable(void)
|
||||
{
|
||||
__raw_writel(0, clkevt_base + PITTCTRL);
|
||||
writel(0, clkevt_base + PITTCTRL);
|
||||
}
|
||||
|
||||
static inline void pit_irq_acknowledge(void)
|
||||
{
|
||||
__raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);
|
||||
writel(PITTFLG_TIF, clkevt_base + PITTFLG);
|
||||
}
|
||||
|
||||
static u64 notrace pit_read_sched_clock(void)
|
||||
{
|
||||
return ~__raw_readl(clksrc_base + PITCVAL);
|
||||
return ~readl(clksrc_base + PITCVAL);
|
||||
}
|
||||
|
||||
static int __init pit_clocksource_init(unsigned long rate)
|
||||
{
|
||||
/* set the max load value and start the clock source counter */
|
||||
__raw_writel(0, clksrc_base + PITTCTRL);
|
||||
__raw_writel(~0UL, clksrc_base + PITLDVAL);
|
||||
__raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL);
|
||||
writel(0, clksrc_base + PITTCTRL);
|
||||
writel(~0UL, clksrc_base + PITLDVAL);
|
||||
writel(PITTCTRL_TEN, clksrc_base + PITTCTRL);
|
||||
|
||||
sched_clock_register(pit_read_sched_clock, 32, rate);
|
||||
return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate,
|
||||
@@ -76,7 +76,7 @@ static int pit_set_next_event(unsigned long delta,
|
||||
* hardware requirement.
|
||||
*/
|
||||
pit_timer_disable();
|
||||
__raw_writel(delta - 1, clkevt_base + PITLDVAL);
|
||||
writel(delta - 1, clkevt_base + PITLDVAL);
|
||||
pit_timer_enable();
|
||||
|
||||
return 0;
|
||||
@@ -125,8 +125,8 @@ static struct clock_event_device clockevent_pit = {
|
||||
|
||||
static int __init pit_clockevent_init(unsigned long rate, int irq)
|
||||
{
|
||||
__raw_writel(0, clkevt_base + PITTCTRL);
|
||||
__raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);
|
||||
writel(0, clkevt_base + PITTCTRL);
|
||||
writel(PITTFLG_TIF, clkevt_base + PITTFLG);
|
||||
|
||||
BUG_ON(request_irq(irq, pit_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
|
||||
"VF pit timer", &clockevent_pit));
|
||||
@@ -183,7 +183,7 @@ static int __init pit_timer_init(struct device_node *np)
|
||||
cycle_per_jiffy = clk_rate / (HZ);
|
||||
|
||||
/* enable the pit module */
|
||||
__raw_writel(~PITMCR_MDIS, timer_base + PITMCR);
|
||||
writel(~PITMCR_MDIS, timer_base + PITMCR);
|
||||
|
||||
ret = pit_clocksource_init(clk_rate);
|
||||
if (ret)
|
||||
|
||||
@@ -953,6 +953,9 @@ static void __exit longhaul_exit(void)
|
||||
struct cpufreq_policy *policy = cpufreq_cpu_get(0);
|
||||
int i;
|
||||
|
||||
if (unlikely(!policy))
|
||||
return;
|
||||
|
||||
for (i = 0; i < numscales; i++) {
|
||||
if (mults[i] == maxmult) {
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
@@ -132,13 +132,14 @@ static struct cpufreq_driver tegra186_cpufreq_driver = {
|
||||
|
||||
static struct cpufreq_frequency_table *init_vhint_table(
|
||||
struct platform_device *pdev, struct tegra_bpmp *bpmp,
|
||||
struct tegra186_cpufreq_cluster *cluster, unsigned int cluster_id)
|
||||
struct tegra186_cpufreq_cluster *cluster, unsigned int cluster_id,
|
||||
int *num_rates)
|
||||
{
|
||||
struct cpufreq_frequency_table *table;
|
||||
struct mrq_cpu_vhint_request req;
|
||||
struct tegra_bpmp_message msg;
|
||||
struct cpu_vhint_data *data;
|
||||
int err, i, j, num_rates = 0;
|
||||
int err, i, j;
|
||||
dma_addr_t phys;
|
||||
void *virt;
|
||||
|
||||
@@ -168,6 +169,7 @@ static struct cpufreq_frequency_table *init_vhint_table(
|
||||
goto free;
|
||||
}
|
||||
|
||||
*num_rates = 0;
|
||||
for (i = data->vfloor; i <= data->vceil; i++) {
|
||||
u16 ndiv = data->ndiv[i];
|
||||
|
||||
@@ -178,10 +180,10 @@ static struct cpufreq_frequency_table *init_vhint_table(
|
||||
if (i > 0 && ndiv == data->ndiv[i - 1])
|
||||
continue;
|
||||
|
||||
num_rates++;
|
||||
(*num_rates)++;
|
||||
}
|
||||
|
||||
table = devm_kcalloc(&pdev->dev, num_rates + 1, sizeof(*table),
|
||||
table = devm_kcalloc(&pdev->dev, *num_rates + 1, sizeof(*table),
|
||||
GFP_KERNEL);
|
||||
if (!table) {
|
||||
table = ERR_PTR(-ENOMEM);
|
||||
@@ -223,7 +225,9 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra186_cpufreq_data *data;
|
||||
struct tegra_bpmp *bpmp;
|
||||
unsigned int i = 0, err;
|
||||
unsigned int i = 0, err, edvd_offset;
|
||||
int num_rates = 0;
|
||||
u32 edvd_val, cpu;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev,
|
||||
struct_size(data, clusters, TEGRA186_NUM_CLUSTERS),
|
||||
@@ -246,10 +250,21 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev)
|
||||
for (i = 0; i < TEGRA186_NUM_CLUSTERS; i++) {
|
||||
struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];
|
||||
|
||||
cluster->table = init_vhint_table(pdev, bpmp, cluster, i);
|
||||
cluster->table = init_vhint_table(pdev, bpmp, cluster, i, &num_rates);
|
||||
if (IS_ERR(cluster->table)) {
|
||||
err = PTR_ERR(cluster->table);
|
||||
goto put_bpmp;
|
||||
} else if (!num_rates) {
|
||||
err = -EINVAL;
|
||||
goto put_bpmp;
|
||||
}
|
||||
|
||||
for (cpu = 0; cpu < ARRAY_SIZE(tegra186_cpus); cpu++) {
|
||||
if (data->cpus[cpu].bpmp_cluster_id == i) {
|
||||
edvd_val = cluster->table[num_rates - 1].driver_data;
|
||||
edvd_offset = data->cpus[cpu].edvd_offset;
|
||||
writel(edvd_val, data->regs + edvd_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -634,8 +634,14 @@ static void __cpuidle_device_init(struct cpuidle_device *dev)
|
||||
static int __cpuidle_register_device(struct cpuidle_device *dev)
|
||||
{
|
||||
struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
|
||||
unsigned int cpu = dev->cpu;
|
||||
int i, ret;
|
||||
|
||||
if (per_cpu(cpuidle_devices, cpu)) {
|
||||
pr_info("CPU%d: cpuidle device already registered\n", cpu);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
if (!try_module_get(drv->owner))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -647,7 +653,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev)
|
||||
dev->states_usage[i].disable |= CPUIDLE_STATE_DISABLED_BY_USER;
|
||||
}
|
||||
|
||||
per_cpu(cpuidle_devices, dev->cpu) = dev;
|
||||
per_cpu(cpuidle_devices, cpu) = dev;
|
||||
list_add(&dev->device_list, &cpuidle_detected_devices);
|
||||
|
||||
ret = cpuidle_coupled_register_device(dev);
|
||||
|
||||
@@ -348,45 +348,50 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
|
||||
if (s->exit_latency_ns > latency_req)
|
||||
break;
|
||||
|
||||
if (s->target_residency_ns > predicted_ns) {
|
||||
/*
|
||||
* Use a physical idle state, not busy polling, unless
|
||||
* a timer is going to trigger soon enough.
|
||||
*/
|
||||
if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) &&
|
||||
s->target_residency_ns <= data->next_timer_ns) {
|
||||
predicted_ns = s->target_residency_ns;
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
if (predicted_ns < TICK_NSEC)
|
||||
break;
|
||||
|
||||
if (!tick_nohz_tick_stopped()) {
|
||||
/*
|
||||
* If the state selected so far is shallow,
|
||||
* waking up early won't hurt, so retain the
|
||||
* tick in that case and let the governor run
|
||||
* again in the next iteration of the loop.
|
||||
*/
|
||||
predicted_ns = drv->states[idx].target_residency_ns;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the state selected so far is shallow and this
|
||||
* state's target residency matches the time till the
|
||||
* closest timer event, select this one to avoid getting
|
||||
* stuck in the shallow one for too long.
|
||||
*/
|
||||
if (drv->states[idx].target_residency_ns < TICK_NSEC &&
|
||||
s->target_residency_ns <= delta_tick)
|
||||
idx = i;
|
||||
|
||||
return idx;
|
||||
if (s->target_residency_ns <= predicted_ns) {
|
||||
idx = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
idx = i;
|
||||
/*
|
||||
* Use a physical idle state, not busy polling, unless a timer
|
||||
* is going to trigger soon enough or the exit latency of the
|
||||
* idle state in question is greater than the predicted idle
|
||||
* duration.
|
||||
*/
|
||||
if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) &&
|
||||
s->target_residency_ns <= data->next_timer_ns &&
|
||||
s->exit_latency_ns <= predicted_ns) {
|
||||
predicted_ns = s->target_residency_ns;
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (predicted_ns < TICK_NSEC)
|
||||
break;
|
||||
|
||||
if (!tick_nohz_tick_stopped()) {
|
||||
/*
|
||||
* If the state selected so far is shallow, waking up
|
||||
* early won't hurt, so retain the tick in that case and
|
||||
* let the governor run again in the next iteration of
|
||||
* the idle loop.
|
||||
*/
|
||||
predicted_ns = drv->states[idx].target_residency_ns;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the state selected so far is shallow and this state's
|
||||
* target residency matches the time till the closest timer
|
||||
* event, select this one to avoid getting stuck in the shallow
|
||||
* one for too long.
|
||||
*/
|
||||
if (drv->states[idx].target_residency_ns < TICK_NSEC &&
|
||||
s->target_residency_ns <= delta_tick)
|
||||
idx = i;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
if (idx == -1)
|
||||
|
||||
@@ -264,7 +264,6 @@ static int sun8i_ce_cipher_prepare(struct crypto_engine *engine, void *async_req
|
||||
goto theend_sgs;
|
||||
}
|
||||
|
||||
chan->timeout = areq->cryptlen;
|
||||
rctx->nr_sgs = ns;
|
||||
rctx->nr_sgd = nd;
|
||||
return 0;
|
||||
|
||||
@@ -186,11 +186,10 @@ int sun8i_ce_run_task(struct sun8i_ce_dev *ce, int flow, const char *name)
|
||||
mutex_unlock(&ce->mlock);
|
||||
|
||||
wait_for_completion_interruptible_timeout(&ce->chanlist[flow].complete,
|
||||
msecs_to_jiffies(ce->chanlist[flow].timeout));
|
||||
msecs_to_jiffies(CE_DMA_TIMEOUT_MS));
|
||||
|
||||
if (ce->chanlist[flow].status == 0) {
|
||||
dev_err(ce->dev, "DMA timeout for %s (tm=%d) on flow %d\n", name,
|
||||
ce->chanlist[flow].timeout, flow);
|
||||
dev_err(ce->dev, "DMA timeout for %s on flow %d\n", name, flow);
|
||||
err = -EFAULT;
|
||||
}
|
||||
/* No need to lock for this read, the channel is locked so
|
||||
|
||||
@@ -457,8 +457,6 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq)
|
||||
else
|
||||
cet->t_dlen = cpu_to_le32(areq->nbytes / 4 + j);
|
||||
|
||||
chan->timeout = areq->nbytes;
|
||||
|
||||
err = sun8i_ce_run_task(ce, flow, crypto_ahash_alg_name(tfm));
|
||||
|
||||
dma_unmap_single(ce->dev, addr_pad, j * 4, DMA_TO_DEVICE);
|
||||
|
||||
@@ -137,7 +137,6 @@ int sun8i_ce_prng_generate(struct crypto_rng *tfm, const u8 *src,
|
||||
|
||||
cet->t_dst[0].addr = cpu_to_le32(dma_dst);
|
||||
cet->t_dst[0].len = cpu_to_le32(todo / 4);
|
||||
ce->chanlist[flow].timeout = 2000;
|
||||
|
||||
err = sun8i_ce_run_task(ce, 3, "PRNG");
|
||||
mutex_unlock(&ce->rnglock);
|
||||
|
||||
@@ -79,7 +79,6 @@ static int sun8i_ce_trng_read(struct hwrng *rng, void *data, size_t max, bool wa
|
||||
|
||||
cet->t_dst[0].addr = cpu_to_le32(dma_dst);
|
||||
cet->t_dst[0].len = cpu_to_le32(todo / 4);
|
||||
ce->chanlist[flow].timeout = todo;
|
||||
|
||||
err = sun8i_ce_run_task(ce, 3, "TRNG");
|
||||
mutex_unlock(&ce->rnglock);
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
#define MAX_SG 8
|
||||
|
||||
#define CE_MAX_CLOCKS 4
|
||||
#define CE_DMA_TIMEOUT_MS 3000
|
||||
|
||||
#define MAXFLOW 4
|
||||
|
||||
@@ -195,7 +196,6 @@ struct sun8i_ce_flow {
|
||||
struct completion complete;
|
||||
int status;
|
||||
dma_addr_t t_phy;
|
||||
int timeout;
|
||||
struct ce_task *tl;
|
||||
void *backup_iv;
|
||||
void *bounce_iv;
|
||||
|
||||
@@ -789,28 +789,24 @@ static int aspeed_acry_probe(struct platform_device *pdev)
|
||||
err_engine_rsa_start:
|
||||
crypto_engine_exit(acry_dev->crypt_engine_rsa);
|
||||
clk_exit:
|
||||
clk_disable_unprepare(acry_dev->clk);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int aspeed_acry_remove(struct platform_device *pdev)
|
||||
static void aspeed_acry_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct aspeed_acry_dev *acry_dev = platform_get_drvdata(pdev);
|
||||
|
||||
aspeed_acry_unregister(acry_dev);
|
||||
crypto_engine_exit(acry_dev->crypt_engine_rsa);
|
||||
tasklet_kill(&acry_dev->done_task);
|
||||
clk_disable_unprepare(acry_dev->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(of, aspeed_acry_of_matches);
|
||||
|
||||
static struct platform_driver aspeed_acry_driver = {
|
||||
.probe = aspeed_acry_probe,
|
||||
.remove = aspeed_acry_remove,
|
||||
.remove_new = aspeed_acry_remove,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.of_match_table = aspeed_acry_of_matches,
|
||||
|
||||
@@ -692,12 +692,12 @@ static int caam_ctrl_rng_init(struct device *dev)
|
||||
*/
|
||||
if (needs_entropy_delay_adjustment())
|
||||
ent_delay = 12000;
|
||||
if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
|
||||
if (!inst_handles) {
|
||||
dev_info(dev,
|
||||
"Entropy delay = %u\n",
|
||||
ent_delay);
|
||||
kick_trng(dev, ent_delay);
|
||||
ent_delay += 400;
|
||||
ent_delay = ent_delay * 2;
|
||||
}
|
||||
/*
|
||||
* if instantiate_rng(...) fails, the loop will rerun
|
||||
|
||||
@@ -3750,10 +3750,12 @@ static ssize_t qm_get_qos_value(struct hisi_qm *qm, const char *buf,
|
||||
pdev = container_of(dev, struct pci_dev, dev);
|
||||
if (pci_physfn(pdev) != qm->pdev) {
|
||||
pci_err(qm->pdev, "the pdev input does not match the pf!\n");
|
||||
put_device(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*fun_index = pdev->devfn;
|
||||
put_device(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1745,7 +1745,7 @@ static int qat_uclo_map_objs_from_mof(struct icp_qat_mof_handle *mobj_handle)
|
||||
if (sobj_hdr)
|
||||
sobj_chunk_num = sobj_hdr->num_chunks;
|
||||
|
||||
mobj_hdr = kzalloc((uobj_chunk_num + sobj_chunk_num) *
|
||||
mobj_hdr = kcalloc(size_add(uobj_chunk_num, sobj_chunk_num),
|
||||
sizeof(*mobj_hdr), GFP_KERNEL);
|
||||
if (!mobj_hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -595,6 +595,25 @@ dw_edma_device_prep_interleaved_dma(struct dma_chan *dchan,
|
||||
return dw_edma_device_transfer(&xfer);
|
||||
}
|
||||
|
||||
static void dw_hdma_set_callback_result(struct virt_dma_desc *vd,
|
||||
enum dmaengine_tx_result result)
|
||||
{
|
||||
u32 residue = 0;
|
||||
struct dw_edma_desc *desc;
|
||||
struct dmaengine_result *res;
|
||||
|
||||
if (!vd->tx.callback_result)
|
||||
return;
|
||||
|
||||
desc = vd2dw_edma_desc(vd);
|
||||
if (desc)
|
||||
residue = desc->alloc_sz - desc->xfer_sz;
|
||||
|
||||
res = &vd->tx_result;
|
||||
res->result = result;
|
||||
res->residue = residue;
|
||||
}
|
||||
|
||||
static void dw_edma_done_interrupt(struct dw_edma_chan *chan)
|
||||
{
|
||||
struct dw_edma_desc *desc;
|
||||
@@ -608,6 +627,8 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan)
|
||||
case EDMA_REQ_NONE:
|
||||
desc = vd2dw_edma_desc(vd);
|
||||
if (!desc->chunks_alloc) {
|
||||
dw_hdma_set_callback_result(vd,
|
||||
DMA_TRANS_NOERROR);
|
||||
list_del(&vd->node);
|
||||
vchan_cookie_complete(vd);
|
||||
}
|
||||
@@ -644,6 +665,7 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan)
|
||||
spin_lock_irqsave(&chan->vc.lock, flags);
|
||||
vd = vchan_next_desc(&chan->vc);
|
||||
if (vd) {
|
||||
dw_hdma_set_callback_result(vd, DMA_TRANS_ABORTED);
|
||||
list_del(&vd->node);
|
||||
vchan_cookie_complete(vd);
|
||||
}
|
||||
|
||||
@@ -1013,7 +1013,7 @@ static int mv_xor_channel_remove(struct mv_xor_chan *mv_chan)
|
||||
|
||||
dma_async_device_unregister(&mv_chan->dmadev);
|
||||
|
||||
dma_free_coherent(dev, MV_XOR_POOL_SIZE,
|
||||
dma_free_wc(dev, MV_XOR_POOL_SIZE,
|
||||
mv_chan->dma_desc_pool_virt, mv_chan->dma_desc_pool);
|
||||
dma_unmap_single(dev, mv_chan->dummy_src_addr,
|
||||
MV_XOR_MIN_BYTE_COUNT, DMA_FROM_DEVICE);
|
||||
@@ -1163,7 +1163,7 @@ mv_xor_channel_add(struct mv_xor_device *xordev,
|
||||
err_free_irq:
|
||||
free_irq(mv_chan->irq, mv_chan);
|
||||
err_free_dma:
|
||||
dma_free_coherent(&pdev->dev, MV_XOR_POOL_SIZE,
|
||||
dma_free_wc(&pdev->dev, MV_XOR_POOL_SIZE,
|
||||
mv_chan->dma_desc_pool_virt, mv_chan->dma_desc_pool);
|
||||
err_unmap_dst:
|
||||
dma_unmap_single(dma_dev->dev, mv_chan->dummy_dst_addr,
|
||||
|
||||
@@ -129,12 +129,25 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
|
||||
const struct shdma_ops *ops = sdev->ops;
|
||||
dev_dbg(schan->dev, "Bring up channel %d\n",
|
||||
schan->id);
|
||||
/*
|
||||
* TODO: .xfer_setup() might fail on some platforms.
|
||||
* Make it int then, on error remove chunks from the
|
||||
* queue again
|
||||
*/
|
||||
ops->setup_xfer(schan, schan->slave_id);
|
||||
|
||||
ret = ops->setup_xfer(schan, schan->slave_id);
|
||||
if (ret < 0) {
|
||||
dev_err(schan->dev, "setup_xfer failed: %d\n", ret);
|
||||
|
||||
/* Remove chunks from the queue and mark them as idle */
|
||||
list_for_each_entry_safe(chunk, c, &schan->ld_queue, node) {
|
||||
if (chunk->cookie == cookie) {
|
||||
chunk->mark = DESC_IDLE;
|
||||
list_move(&chunk->node, &schan->ld_free);
|
||||
}
|
||||
}
|
||||
|
||||
schan->pm_state = SHDMA_PM_ESTABLISHED;
|
||||
ret = pm_runtime_put(schan->dev);
|
||||
|
||||
spin_unlock_irq(&schan->chan_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (schan->pm_state == SHDMA_PM_PENDING)
|
||||
shdma_chan_xfer_ld_queue(schan);
|
||||
|
||||
@@ -300,21 +300,30 @@ static bool sh_dmae_channel_busy(struct shdma_chan *schan)
|
||||
return dmae_is_busy(sh_chan);
|
||||
}
|
||||
|
||||
static void sh_dmae_setup_xfer(struct shdma_chan *schan,
|
||||
int slave_id)
|
||||
static int sh_dmae_setup_xfer(struct shdma_chan *schan, int slave_id)
|
||||
{
|
||||
struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
|
||||
shdma_chan);
|
||||
|
||||
int ret = 0;
|
||||
if (slave_id >= 0) {
|
||||
const struct sh_dmae_slave_config *cfg =
|
||||
sh_chan->config;
|
||||
|
||||
dmae_set_dmars(sh_chan, cfg->mid_rid);
|
||||
dmae_set_chcr(sh_chan, cfg->chcr);
|
||||
ret = dmae_set_dmars(sh_chan, cfg->mid_rid);
|
||||
if (ret < 0)
|
||||
goto END;
|
||||
|
||||
ret = dmae_set_chcr(sh_chan, cfg->chcr);
|
||||
if (ret < 0)
|
||||
goto END;
|
||||
|
||||
} else {
|
||||
dmae_init(sh_chan);
|
||||
}
|
||||
|
||||
END:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1194,10 +1194,22 @@ altr_check_ocram_deps_init(struct altr_edac_device_dev *device)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Verify OCRAM has been initialized */
|
||||
/*
|
||||
* Verify that OCRAM has been initialized.
|
||||
* During a warm reset, OCRAM contents are retained, but the control
|
||||
* and status registers are reset to their default values. Therefore,
|
||||
* ECC must be explicitly re-enabled in the control register.
|
||||
* Error condition: if INITCOMPLETEA is clear and ECC_EN is already set.
|
||||
*/
|
||||
if (!ecc_test_bits(ALTR_A10_ECC_INITCOMPLETEA,
|
||||
(base + ALTR_A10_ECC_INITSTAT_OFST)))
|
||||
return -ENODEV;
|
||||
(base + ALTR_A10_ECC_INITSTAT_OFST))) {
|
||||
if (!ecc_test_bits(ALTR_A10_ECC_EN,
|
||||
(base + ALTR_A10_ECC_CTRL_OFST)))
|
||||
ecc_set_bits(ALTR_A10_ECC_EN,
|
||||
(base + ALTR_A10_ECC_CTRL_OFST));
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Enable IRQ on Single Bit Error */
|
||||
writel(ALTR_A10_ECC_SERRINTEN, (base + ALTR_A10_ECC_ERRINTENS_OFST));
|
||||
@@ -1367,7 +1379,7 @@ static const struct edac_device_prv_data a10_enetecc_data = {
|
||||
.ue_set_mask = ALTR_A10_ECC_TDERRA,
|
||||
.set_err_ofst = ALTR_A10_ECC_INTTEST_OFST,
|
||||
.ecc_irq_handler = altr_edac_a10_ecc_irq,
|
||||
.inject_fops = &altr_edac_a10_device_inject2_fops,
|
||||
.inject_fops = &altr_edac_a10_device_inject_fops,
|
||||
};
|
||||
|
||||
#endif /* CONFIG_EDAC_ALTERA_ETHERNET */
|
||||
@@ -1457,7 +1469,7 @@ static const struct edac_device_prv_data a10_usbecc_data = {
|
||||
.ue_set_mask = ALTR_A10_ECC_TDERRA,
|
||||
.set_err_ofst = ALTR_A10_ECC_INTTEST_OFST,
|
||||
.ecc_irq_handler = altr_edac_a10_ecc_irq,
|
||||
.inject_fops = &altr_edac_a10_device_inject2_fops,
|
||||
.inject_fops = &altr_edac_a10_device_inject_fops,
|
||||
};
|
||||
|
||||
#endif /* CONFIG_EDAC_ALTERA_USB */
|
||||
|
||||
@@ -162,6 +162,8 @@ static int adc_jack_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct adc_jack_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
if (data->wakeup_source)
|
||||
device_init_wakeup(&pdev->dev, false);
|
||||
free_irq(data->irq, data);
|
||||
cancel_work_sync(&data->handler.work);
|
||||
|
||||
|
||||
@@ -1205,29 +1205,69 @@ static void amdgpu_connector_dvi_force(struct drm_connector *connector)
|
||||
amdgpu_connector->use_digital = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_max_hdmi_pixel_clock - Return max supported HDMI (TMDS) pixel clock
|
||||
* @adev: pointer to amdgpu_device
|
||||
*
|
||||
* Return: maximum supported HDMI (TMDS) pixel clock in KHz.
|
||||
*/
|
||||
static int amdgpu_max_hdmi_pixel_clock(const struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->asic_type >= CHIP_POLARIS10)
|
||||
return 600000;
|
||||
else if (adev->asic_type >= CHIP_TONGA)
|
||||
return 300000;
|
||||
else
|
||||
return 297000;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_connector_dvi_mode_valid - Validate a mode on DVI/HDMI connectors
|
||||
* @connector: DRM connector to validate the mode on
|
||||
* @mode: display mode to validate
|
||||
*
|
||||
* Validate the given display mode on DVI and HDMI connectors, including
|
||||
* analog signals on DVI-I.
|
||||
*
|
||||
* Return: drm_mode_status indicating whether the mode is valid.
|
||||
*/
|
||||
static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
||||
const int max_hdmi_pixel_clock = amdgpu_max_hdmi_pixel_clock(adev);
|
||||
const int max_dvi_single_link_pixel_clock = 165000;
|
||||
int max_digital_pixel_clock_khz;
|
||||
|
||||
/* XXX check mode bandwidth */
|
||||
|
||||
if (amdgpu_connector->use_digital && (mode->clock > 165000)) {
|
||||
if ((amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) ||
|
||||
(amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
|
||||
(amdgpu_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B)) {
|
||||
return MODE_OK;
|
||||
} else if (connector->display_info.is_hdmi) {
|
||||
/* HDMI 1.3+ supports max clock of 340 Mhz */
|
||||
if (mode->clock > 340000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
else
|
||||
return MODE_OK;
|
||||
} else {
|
||||
return MODE_CLOCK_HIGH;
|
||||
if (amdgpu_connector->use_digital) {
|
||||
switch (amdgpu_connector->connector_object_id) {
|
||||
case CONNECTOR_OBJECT_ID_HDMI_TYPE_A:
|
||||
max_digital_pixel_clock_khz = max_hdmi_pixel_clock;
|
||||
break;
|
||||
case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I:
|
||||
case CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D:
|
||||
max_digital_pixel_clock_khz = max_dvi_single_link_pixel_clock;
|
||||
break;
|
||||
case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I:
|
||||
case CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D:
|
||||
case CONNECTOR_OBJECT_ID_HDMI_TYPE_B:
|
||||
max_digital_pixel_clock_khz = max_dvi_single_link_pixel_clock * 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* When the display EDID claims that it's an HDMI display,
|
||||
* we use the HDMI encoder mode of the display HW,
|
||||
* so we should verify against the max HDMI clock here.
|
||||
*/
|
||||
if (connector->display_info.is_hdmi)
|
||||
max_digital_pixel_clock_khz = max_hdmi_pixel_clock;
|
||||
|
||||
if (mode->clock > max_digital_pixel_clock_khz)
|
||||
return MODE_CLOCK_HIGH;
|
||||
}
|
||||
|
||||
/* check against the max pixel clock */
|
||||
|
||||
@@ -286,7 +286,7 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
|
||||
}
|
||||
}
|
||||
|
||||
if (!p->gang_size) {
|
||||
if (!p->gang_size || (amdgpu_sriov_vf(p->adev) && p->gang_size > 1)) {
|
||||
ret = -EINVAL;
|
||||
goto free_all_kdata;
|
||||
}
|
||||
@@ -690,7 +690,7 @@ static void amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev,
|
||||
*/
|
||||
const s64 us_upper_bound = 200000;
|
||||
|
||||
if (!adev->mm_stats.log2_max_MBps) {
|
||||
if ((!adev->mm_stats.log2_max_MBps) || !ttm_resource_manager_used(&adev->mman.vram_mgr.manager)) {
|
||||
*max_bytes = 0;
|
||||
*max_vis_bytes = 0;
|
||||
return;
|
||||
@@ -1732,30 +1732,21 @@ int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
union drm_amdgpu_wait_fences *wait = data;
|
||||
uint32_t fence_count = wait->in.fence_count;
|
||||
struct drm_amdgpu_fence *fences_user;
|
||||
struct drm_amdgpu_fence *fences;
|
||||
int r;
|
||||
|
||||
/* Get the fences from userspace */
|
||||
fences = kmalloc_array(fence_count, sizeof(struct drm_amdgpu_fence),
|
||||
GFP_KERNEL);
|
||||
if (fences == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
fences_user = u64_to_user_ptr(wait->in.fences);
|
||||
if (copy_from_user(fences, fences_user,
|
||||
sizeof(struct drm_amdgpu_fence) * fence_count)) {
|
||||
r = -EFAULT;
|
||||
goto err_free_fences;
|
||||
}
|
||||
fences = memdup_array_user(u64_to_user_ptr(wait->in.fences),
|
||||
wait->in.fence_count,
|
||||
sizeof(struct drm_amdgpu_fence));
|
||||
if (IS_ERR(fences))
|
||||
return PTR_ERR(fences);
|
||||
|
||||
if (wait->in.wait_all)
|
||||
r = amdgpu_cs_wait_all_fences(adev, filp, wait, fences);
|
||||
else
|
||||
r = amdgpu_cs_wait_any_fence(adev, filp, wait, fences);
|
||||
|
||||
err_free_fences:
|
||||
kfree(fences);
|
||||
|
||||
return r;
|
||||
|
||||
@@ -93,6 +93,7 @@ MODULE_FIRMWARE("amdgpu/picasso_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/raven2_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/arcturus_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
|
||||
MODULE_FIRMWARE("amdgpu/cyan_skillfish_gpu_info.bin");
|
||||
|
||||
#define AMDGPU_RESUME_MS 2000
|
||||
#define AMDGPU_MAX_RETRY_LIMIT 2
|
||||
@@ -1939,6 +1940,9 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev)
|
||||
case CHIP_NAVI12:
|
||||
chip_name = "navi12";
|
||||
break;
|
||||
case CHIP_CYAN_SKILLFISH:
|
||||
chip_name = "cyan_skillfish";
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_gpu_info.bin", chip_name);
|
||||
@@ -4109,6 +4113,10 @@ static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
|
||||
if ((adev->in_s3 || adev->in_s0ix) && (adev->flags & AMD_IS_APU))
|
||||
return 0;
|
||||
|
||||
/* No need to evict when going to S5 through S4 callbacks */
|
||||
if (system_state == SYSTEM_POWER_OFF)
|
||||
return 0;
|
||||
|
||||
ret = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM);
|
||||
if (ret)
|
||||
DRM_WARN("evicting device resources failed\n");
|
||||
|
||||
@@ -1819,13 +1819,16 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
|
||||
case IP_VERSION(11, 0, 5):
|
||||
case IP_VERSION(11, 0, 9):
|
||||
case IP_VERSION(11, 0, 7):
|
||||
case IP_VERSION(11, 0, 8):
|
||||
case IP_VERSION(11, 0, 11):
|
||||
case IP_VERSION(11, 0, 12):
|
||||
case IP_VERSION(11, 0, 13):
|
||||
case IP_VERSION(11, 5, 0):
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(11, 0, 8):
|
||||
if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)
|
||||
amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
|
||||
break;
|
||||
case IP_VERSION(12, 0, 0):
|
||||
case IP_VERSION(12, 0, 1):
|
||||
amdgpu_device_ip_block_add(adev, &smu_v12_0_ip_block);
|
||||
|
||||
@@ -1983,6 +1983,11 @@ static const struct pci_device_id pciidlist[] = {
|
||||
{0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN},
|
||||
|
||||
/* CYAN_SKILLFISH */
|
||||
{0x1002, 0x13DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
|
||||
{0x1002, 0x13F9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
|
||||
{0x1002, 0x13FA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
|
||||
{0x1002, 0x13FB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
|
||||
{0x1002, 0x13FC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
|
||||
{0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
|
||||
{0x1002, 0x143F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU},
|
||||
|
||||
|
||||
@@ -87,10 +87,12 @@ static void amdgpu_jpeg_idle_work_handler(struct work_struct *work)
|
||||
fences += amdgpu_fence_count_emitted(&adev->jpeg.inst[i].ring_dec[j]);
|
||||
}
|
||||
|
||||
if (!fences && !atomic_read(&adev->jpeg.total_submission_cnt))
|
||||
if (!fences && !atomic_read(&adev->jpeg.total_submission_cnt)) {
|
||||
mutex_lock(&adev->jpeg.jpeg_pg_lock);
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_JPEG,
|
||||
AMD_PG_STATE_GATE);
|
||||
else
|
||||
mutex_unlock(&adev->jpeg.jpeg_pg_lock);
|
||||
} else
|
||||
schedule_delayed_work(&adev->jpeg.idle_work, JPEG_IDLE_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
@@ -651,7 +651,8 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
ui64 = atomic64_read(&adev->num_vram_cpu_page_faults);
|
||||
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
|
||||
case AMDGPU_INFO_VRAM_USAGE:
|
||||
ui64 = ttm_resource_manager_usage(&adev->mman.vram_mgr.manager);
|
||||
ui64 = ttm_resource_manager_used(&adev->mman.vram_mgr.manager) ?
|
||||
ttm_resource_manager_usage(&adev->mman.vram_mgr.manager) : 0;
|
||||
return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
|
||||
case AMDGPU_INFO_VIS_VRAM_USAGE:
|
||||
ui64 = amdgpu_vram_mgr_vis_usage(&adev->mman.vram_mgr);
|
||||
@@ -697,8 +698,8 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
mem.vram.usable_heap_size = adev->gmc.real_vram_size -
|
||||
atomic64_read(&adev->vram_pin_size) -
|
||||
AMDGPU_VM_RESERVED_VRAM;
|
||||
mem.vram.heap_usage =
|
||||
ttm_resource_manager_usage(vram_man);
|
||||
mem.vram.heap_usage = ttm_resource_manager_used(&adev->mman.vram_mgr.manager) ?
|
||||
ttm_resource_manager_usage(vram_man) : 0;
|
||||
mem.vram.max_allocation = mem.vram.usable_heap_size * 3 / 4;
|
||||
|
||||
mem.cpu_accessible_vram.total_heap_size =
|
||||
|
||||
@@ -2015,8 +2015,11 @@ static int psp_securedisplay_initialize(struct psp_context *psp)
|
||||
if (!ret && !psp->securedisplay_context.context.resp_status) {
|
||||
psp->securedisplay_context.context.initialized = true;
|
||||
mutex_init(&psp->securedisplay_context.mutex);
|
||||
} else
|
||||
} else {
|
||||
/* don't try again */
|
||||
psp->securedisplay_context.context.bin_desc.size_bytes = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&psp->securedisplay_context.mutex);
|
||||
|
||||
|
||||
@@ -604,8 +604,8 @@ static int amdgpu_virt_write_vf2pf_data(struct amdgpu_device *adev)
|
||||
vf2pf_info->driver_cert = 0;
|
||||
vf2pf_info->os_info.all = 0;
|
||||
|
||||
vf2pf_info->fb_usage =
|
||||
ttm_resource_manager_usage(&adev->mman.vram_mgr.manager) >> 20;
|
||||
vf2pf_info->fb_usage = ttm_resource_manager_used(&adev->mman.vram_mgr.manager) ?
|
||||
ttm_resource_manager_usage(&adev->mman.vram_mgr.manager) >> 20 : 0;
|
||||
vf2pf_info->fb_vis_usage =
|
||||
amdgpu_vram_mgr_vis_usage(&adev->mman.vram_mgr) >> 20;
|
||||
vf2pf_info->fb_size = adev->gmc.real_vram_size >> 20;
|
||||
|
||||
@@ -1085,7 +1085,12 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
|
||||
svm_range_list_lock_and_flush_work(&p->svms, current->mm);
|
||||
mutex_lock(&p->svms.lock);
|
||||
mmap_write_unlock(current->mm);
|
||||
if (interval_tree_iter_first(&p->svms.objects,
|
||||
|
||||
/* Skip a special case that allocates VRAM without VA,
|
||||
* VA will be invalid of 0.
|
||||
*/
|
||||
if (!(!args->va_addr && (flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM)) &&
|
||||
interval_tree_iter_first(&p->svms.objects,
|
||||
args->va_addr >> PAGE_SHIFT,
|
||||
(args->va_addr + args->size - 1) >> PAGE_SHIFT)) {
|
||||
pr_err("Address: 0x%llx already allocated by SVM\n",
|
||||
@@ -2567,8 +2572,8 @@ static int criu_restore(struct file *filep,
|
||||
pr_debug("CRIU restore (num_devices:%u num_bos:%u num_objects:%u priv_data_size:%llu)\n",
|
||||
args->num_devices, args->num_bos, args->num_objects, args->priv_data_size);
|
||||
|
||||
if (!args->bos || !args->devices || !args->priv_data || !args->priv_data_size ||
|
||||
!args->num_devices || !args->num_bos)
|
||||
if ((args->num_bos > 0 && !args->bos) || !args->devices || !args->priv_data ||
|
||||
!args->priv_data_size || !args->num_devices)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&p->mutex);
|
||||
@@ -3252,8 +3257,10 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
|
||||
int retcode = -EINVAL;
|
||||
bool ptrace_attached = false;
|
||||
|
||||
if (nr >= AMDKFD_CORE_IOCTL_COUNT)
|
||||
if (nr >= AMDKFD_CORE_IOCTL_COUNT) {
|
||||
retcode = -ENOTTY;
|
||||
goto err_i1;
|
||||
}
|
||||
|
||||
if ((nr >= AMDKFD_COMMAND_START) && (nr < AMDKFD_COMMAND_END)) {
|
||||
u32 amdkfd_size;
|
||||
@@ -3266,8 +3273,10 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
|
||||
asize = amdkfd_size;
|
||||
|
||||
cmd = ioctl->cmd;
|
||||
} else
|
||||
} else {
|
||||
retcode = -ENOTTY;
|
||||
goto err_i1;
|
||||
}
|
||||
|
||||
dev_dbg(kfd_device, "ioctl cmd 0x%x (#0x%x), arg 0x%lx\n", cmd, nr, arg);
|
||||
|
||||
|
||||
@@ -1017,7 +1017,15 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
|
||||
}
|
||||
|
||||
for (i = 0; i < kfd->num_nodes; i++) {
|
||||
node = kfd->nodes[i];
|
||||
/* Race if another thread in b/w
|
||||
* kfd_cleanup_nodes and kfree(kfd),
|
||||
* when kfd->nodes[i] = NULL
|
||||
*/
|
||||
if (kfd->nodes[i])
|
||||
node = kfd->nodes[i];
|
||||
else
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&node->interrupt_lock, flags);
|
||||
|
||||
if (node->interrupts_active
|
||||
|
||||
@@ -111,7 +111,14 @@
|
||||
|
||||
#define KFD_KERNEL_QUEUE_SIZE 2048
|
||||
|
||||
#define KFD_UNMAP_LATENCY_MS (4000)
|
||||
/* KFD_UNMAP_LATENCY_MS is the timeout CP waiting for SDMA preemption. One XCC
|
||||
* can be associated to 2 SDMA engines. queue_preemption_timeout_ms is the time
|
||||
* driver waiting for CP returning the UNMAP_QUEUE fence. Thus the math is
|
||||
* queue_preemption_timeout_ms = sdma_preemption_time * 2 + cp workload
|
||||
* The format here makes CP workload 10% of total timeout
|
||||
*/
|
||||
#define KFD_UNMAP_LATENCY_MS \
|
||||
((queue_preemption_timeout_ms - queue_preemption_timeout_ms / 10) >> 1)
|
||||
|
||||
#define KFD_MAX_SDMA_QUEUES 128
|
||||
|
||||
|
||||
@@ -1709,6 +1709,29 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
|
||||
|
||||
next = min(vma->vm_end, end);
|
||||
npages = (next - addr) >> PAGE_SHIFT;
|
||||
/* HMM requires at least READ permissions. If provided with PROT_NONE,
|
||||
* unmap the memory. If it's not already mapped, this is a no-op
|
||||
* If PROT_WRITE is provided without READ, warn first then unmap
|
||||
*/
|
||||
if (!(vma->vm_flags & VM_READ)) {
|
||||
unsigned long e, s;
|
||||
|
||||
svm_range_lock(prange);
|
||||
if (vma->vm_flags & VM_WRITE)
|
||||
pr_debug("VM_WRITE without VM_READ is not supported");
|
||||
s = max(start, prange->start);
|
||||
e = min(end, prange->last);
|
||||
if (e >= s)
|
||||
r = svm_range_unmap_from_gpus(prange, s, e,
|
||||
KFD_SVM_UNMAP_TRIGGER_UNMAP_FROM_CPU);
|
||||
svm_range_unlock(prange);
|
||||
/* If unmap returns non-zero, we'll bail on the next for loop
|
||||
* iteration, so just leave r and continue
|
||||
*/
|
||||
addr = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
WRITE_ONCE(p->svms.faulting_task, current);
|
||||
r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
|
||||
readonly, owner, NULL,
|
||||
|
||||
@@ -2993,6 +2993,7 @@ static int dm_resume(void *handle)
|
||||
/* Do mst topology probing after resuming cached state*/
|
||||
drm_connector_list_iter_begin(ddev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter) {
|
||||
bool init = false;
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
|
||||
continue;
|
||||
@@ -3002,7 +3003,14 @@ static int dm_resume(void *handle)
|
||||
aconnector->mst_root)
|
||||
continue;
|
||||
|
||||
drm_dp_mst_topology_queue_probe(&aconnector->mst_mgr);
|
||||
scoped_guard(mutex, &aconnector->mst_mgr.lock) {
|
||||
init = !aconnector->mst_mgr.mst_primary;
|
||||
}
|
||||
if (init)
|
||||
dm_helpers_dp_mst_start_top_mgr(aconnector->dc_link->ctx,
|
||||
aconnector->dc_link, false);
|
||||
else
|
||||
drm_dp_mst_topology_queue_probe(&aconnector->mst_mgr);
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
@@ -9243,6 +9251,8 @@ static void get_freesync_config_for_crtc(
|
||||
} else {
|
||||
config.state = VRR_STATE_INACTIVE;
|
||||
}
|
||||
} else {
|
||||
config.state = VRR_STATE_UNSUPPORTED;
|
||||
}
|
||||
out:
|
||||
new_crtc_state->freesync_config = config;
|
||||
@@ -10838,7 +10848,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
|
||||
|
||||
dm_con_state = to_dm_connector_state(connector->state);
|
||||
|
||||
if (!adev->dm.freesync_module)
|
||||
if (!adev->dm.freesync_module || !dc_supports_vrr(sink->ctx->dce_version))
|
||||
goto update;
|
||||
|
||||
/* Some eDP panels only have the refresh rate range info in DisplayID */
|
||||
|
||||
@@ -561,6 +561,7 @@ static void vg_clk_mgr_helper_populate_bw_params(
|
||||
{
|
||||
int i, j;
|
||||
struct clk_bw_params *bw_params = clk_mgr->base.bw_params;
|
||||
uint32_t max_dispclk = 0, max_dppclk = 0;
|
||||
|
||||
j = -1;
|
||||
|
||||
@@ -581,6 +582,15 @@ static void vg_clk_mgr_helper_populate_bw_params(
|
||||
return;
|
||||
}
|
||||
|
||||
/* dispclk and dppclk can be max at any voltage, same number of levels for both */
|
||||
if (clock_table->NumDispClkLevelsEnabled <= VG_NUM_DISPCLK_DPM_LEVELS &&
|
||||
clock_table->NumDispClkLevelsEnabled <= VG_NUM_DPPCLK_DPM_LEVELS) {
|
||||
max_dispclk = find_max_clk_value(clock_table->DispClocks, clock_table->NumDispClkLevelsEnabled);
|
||||
max_dppclk = find_max_clk_value(clock_table->DppClocks, clock_table->NumDispClkLevelsEnabled);
|
||||
} else {
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
bw_params->clk_table.num_entries = j + 1;
|
||||
|
||||
for (i = 0; i < bw_params->clk_table.num_entries - 1; i++, j--) {
|
||||
@@ -588,11 +598,17 @@ static void vg_clk_mgr_helper_populate_bw_params(
|
||||
bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].memclk;
|
||||
bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].voltage;
|
||||
bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->DfPstateTable[j].voltage);
|
||||
|
||||
/* Now update clocks we do read */
|
||||
bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk;
|
||||
bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk;
|
||||
}
|
||||
bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[j].fclk;
|
||||
bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].memclk;
|
||||
bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].voltage;
|
||||
bw_params->clk_table.entries[i].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, VG_NUM_DCFCLK_DPM_LEVELS);
|
||||
bw_params->clk_table.entries[i].dispclk_mhz = find_max_clk_value(clock_table->DispClocks, VG_NUM_DISPCLK_DPM_LEVELS);
|
||||
bw_params->clk_table.entries[i].dppclk_mhz = find_max_clk_value(clock_table->DppClocks, VG_NUM_DPPCLK_DPM_LEVELS);
|
||||
|
||||
bw_params->vram_type = bios_info->memory_type;
|
||||
bw_params->num_channels = bios_info->ma_channel_number;
|
||||
|
||||
@@ -2068,6 +2068,18 @@ enum dc_status dc_commit_streams(struct dc *dc,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* If not already seamless, make transition seamless by inserting intermediate minimal transition
|
||||
*/
|
||||
if (dc->hwss.is_pipe_topology_transition_seamless &&
|
||||
!dc->hwss.is_pipe_topology_transition_seamless(dc, dc->current_state, context)) {
|
||||
res = commit_minimal_transition_state(dc, context);
|
||||
if (res != DC_OK) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
res = dc_commit_state_no_check(dc, context);
|
||||
|
||||
for (i = 0; i < stream_count; i++) {
|
||||
@@ -2940,6 +2952,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
|
||||
if (update->adaptive_sync_infopacket)
|
||||
stream->adaptive_sync_infopacket = *update->adaptive_sync_infopacket;
|
||||
|
||||
if (update->avi_infopacket)
|
||||
stream->avi_infopacket = *update->avi_infopacket;
|
||||
|
||||
if (update->dither_option)
|
||||
stream->dither_option = *update->dither_option;
|
||||
|
||||
@@ -3146,7 +3161,8 @@ static void commit_planes_do_stream_update(struct dc *dc,
|
||||
stream_update->vsp_infopacket ||
|
||||
stream_update->hfvsif_infopacket ||
|
||||
stream_update->adaptive_sync_infopacket ||
|
||||
stream_update->vtem_infopacket) {
|
||||
stream_update->vtem_infopacket ||
|
||||
stream_update->avi_infopacket) {
|
||||
resource_build_info_frame(pipe_ctx);
|
||||
dc->hwss.update_info_frame(pipe_ctx);
|
||||
|
||||
@@ -4229,6 +4245,7 @@ static bool full_update_required(struct dc *dc,
|
||||
stream_update->hfvsif_infopacket ||
|
||||
stream_update->vtem_infopacket ||
|
||||
stream_update->adaptive_sync_infopacket ||
|
||||
stream_update->avi_infopacket ||
|
||||
stream_update->dpms_off ||
|
||||
stream_update->allow_freesync ||
|
||||
stream_update->vrr_active_variable ||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user