Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf before 7.0-rc2

Cross-merge BPF and other fixes after downstream PR.

No conflicts.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Alexei Starovoitov 2026-03-01 09:03:45 -08:00
commit 309d8808ee
404 changed files with 4526 additions and 2137 deletions

View File

@ -210,7 +210,12 @@ Daniel Borkmann <daniel@iogearbox.net> <daniel.borkmann@tik.ee.ethz.ch>
Daniel Borkmann <daniel@iogearbox.net> <dborkmann@redhat.com>
Daniel Borkmann <daniel@iogearbox.net> <dborkman@redhat.com>
Daniel Borkmann <daniel@iogearbox.net> <dxchgb@gmail.com>
Daniel Lezcano <daniel.lezcano@kernel.org> <daniel.lezcano@linaro.org>
Daniel Lezcano <daniel.lezcano@kernel.org> <daniel.lezcano@free.fr>
Daniel Lezcano <daniel.lezcano@kernel.org> <daniel.lezcano@linexp.org>
Daniel Lezcano <daniel.lezcano@kernel.org> <dlezcano@fr.ibm.com>
Daniel Thompson <danielt@kernel.org> <daniel.thompson@linaro.org>
Daniele Alessandrelli <daniele.alessandrelli@gmail.com> <daniele.alessandrelli@intel.com>
Danilo Krummrich <dakr@kernel.org> <dakr@redhat.com>
David Brownell <david-b@pacbell.net>
David Collins <quic_collinsd@quicinc.com> <collinsd@codeaurora.org>
@ -876,6 +881,7 @@ Vivien Didelot <vivien.didelot@gmail.com> <vivien.didelot@savoirfairelinux.com>
Vlad Dogaru <ddvlad@gmail.com> <vlad.dogaru@intel.com>
Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@parallels.com>
Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@virtuozzo.com>
Vlastimil Babka <vbabka@kernel.org> <vbabka@suse.cz>
WangYuli <wangyuli@aosc.io> <wangyl5933@chinaunicom.cn>
WangYuli <wangyuli@aosc.io> <wangyuli@deepin.org>
Weiwen Hu <huweiwen@linux.alibaba.com> <sehuww@mail.scut.edu.cn>
@ -890,7 +896,8 @@ Yanteng Si <si.yanteng@linux.dev> <siyanteng@loongson.cn>
Ying Huang <huang.ying.caritas@gmail.com> <ying.huang@intel.com>
Yixun Lan <dlan@kernel.org> <dlan@gentoo.org>
Yixun Lan <dlan@kernel.org> <yixun.lan@amlogic.com>
Yosry Ahmed <yosry.ahmed@linux.dev> <yosryahmed@google.com>
Yosry Ahmed <yosry@kernel.org> <yosryahmed@google.com>
Yosry Ahmed <yosry@kernel.org> <yosry.ahmed@linux.dev>
Yu-Chun Lin <eleanor.lin@realtek.com> <eleanor15x@gmail.com>
Yusuke Goda <goda.yusuke@renesas.com>
Zack Rusin <zack.rusin@broadcom.com> <zackr@vmware.com>

View File

@ -594,6 +594,9 @@ Values:
their sockets will only be able to connect within their own
namespace.
The first write to ``child_ns_mode`` locks its value. Subsequent writes of the
same value succeed, but writing a different value returns ``-EBUSY``.
Changing ``child_ns_mode`` only affects namespaces created after the change;
it does not modify the current namespace or any existing children.

View File

@ -287,7 +287,7 @@ examples:
regulator-max-microvolt = <1700000>;
};
mt6359_vrfck_1_ldo_reg: ldo_vrfck_1 {
regulator-name = "vrfck";
regulator-name = "vrfck_1";
regulator-min-microvolt = <1240000>;
regulator-max-microvolt = <1600000>;
};
@ -309,7 +309,7 @@ examples:
regulator-max-microvolt = <3300000>;
};
mt6359_vemc_1_ldo_reg: ldo_vemc_1 {
regulator-name = "vemc";
regulator-name = "vemc_1";
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <3300000>;
};

View File

@ -22,21 +22,6 @@ allOf:
properties:
reg:
minItems: 2
- if:
properties:
compatible:
contains:
enum:
- baikal,bt1-sys-ssi
then:
properties:
mux-controls:
maxItems: 1
required:
- mux-controls
else:
required:
- interrupts
- if:
properties:
compatible:
@ -75,10 +60,6 @@ properties:
const: intel,mountevans-imc-ssi
- description: AMD Pensando Elba SoC SPI Controller
const: amd,pensando-elba-spi
- description: Baikal-T1 SPI Controller
const: baikal,bt1-ssi
- description: Baikal-T1 System Boot SPI Controller
const: baikal,bt1-sys-ssi
- description: Canaan Kendryte K210 SoS SPI Controller
const: canaan,k210-spi
- description: Renesas RZ/N1 SPI Controller
@ -170,6 +151,7 @@ required:
- "#address-cells"
- "#size-cells"
- clocks
- interrupts
examples:
- |
@ -190,15 +172,4 @@ examples:
rx-sample-delay-ns = <7>;
};
};
- |
spi@1f040100 {
compatible = "baikal,bt1-sys-ssi";
reg = <0x1f040100 0x900>,
<0x1c000000 0x1000000>;
#address-cells = <1>;
#size-cells = <0>;
mux-controls = <&boot_mux>;
clocks = <&ccu_sys>;
clock-names = "ssi_clk";
};
...

View File

@ -1292,7 +1292,6 @@ F: include/trace/events/amdxdna.h
F: include/uapi/drm/amdxdna_accel.h
AMD XGBE DRIVER
M: "Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>
M: Raju Rangoju <Raju.Rangoju@amd.com>
L: netdev@vger.kernel.org
S: Maintained
@ -6219,14 +6218,13 @@ S: Supported
F: drivers/scsi/snic/
CISCO VIC ETHERNET NIC DRIVER
M: Christian Benvenuti <benve@cisco.com>
M: Satish Kharat <satishkh@cisco.com>
S: Maintained
F: drivers/net/ethernet/cisco/enic/
CISCO VIC LOW LATENCY NIC DRIVER
M: Christian Benvenuti <benve@cisco.com>
M: Nelson Escobar <neescoba@cisco.com>
M: Satish Kharat <satishkh@cisco.com>
S: Supported
F: drivers/infiniband/hw/usnic/
@ -6280,7 +6278,7 @@ S: Maintained
F: include/linux/clk.h
CLOCKSOURCE, CLOCKEVENT DRIVERS
M: Daniel Lezcano <daniel.lezcano@linaro.org>
M: Daniel Lezcano <daniel.lezcano@kernel.org>
M: Thomas Gleixner <tglx@kernel.org>
L: linux-kernel@vger.kernel.org
S: Supported
@ -6669,7 +6667,7 @@ F: rust/kernel/cpu.rs
CPU IDLE TIME MANAGEMENT FRAMEWORK
M: "Rafael J. Wysocki" <rafael@kernel.org>
M: Daniel Lezcano <daniel.lezcano@linaro.org>
M: Daniel Lezcano <daniel.lezcano@kernel.org>
R: Christian Loehle <christian.loehle@arm.com>
L: linux-pm@vger.kernel.org
S: Maintained
@ -6699,7 +6697,7 @@ F: arch/x86/kernel/msr.c
CPUIDLE DRIVER - ARM BIG LITTLE
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
M: Daniel Lezcano <daniel.lezcano@linaro.org>
M: Daniel Lezcano <daniel.lezcano@kernel.org>
L: linux-pm@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@ -6707,7 +6705,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
F: drivers/cpuidle/cpuidle-big_little.c
CPUIDLE DRIVER - ARM EXYNOS
M: Daniel Lezcano <daniel.lezcano@linaro.org>
M: Daniel Lezcano <daniel.lezcano@kernel.org>
M: Kukjin Kim <kgene@kernel.org>
R: Krzysztof Kozlowski <krzk@kernel.org>
L: linux-pm@vger.kernel.org
@ -14412,9 +14410,9 @@ LANTIQ PEF2256 DRIVER
M: Herve Codina <herve.codina@bootlin.com>
S: Maintained
F: Documentation/devicetree/bindings/net/lantiq,pef2256.yaml
F: drivers/net/wan/framer/pef2256/
F: drivers/net/wan/framer/
F: drivers/pinctrl/pinctrl-pef2256.c
F: include/linux/framer/pef2256.h
F: include/linux/framer/
LASI 53c700 driver for PARISC
M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
@ -16656,7 +16654,7 @@ M: Andrew Morton <akpm@linux-foundation.org>
M: David Hildenbrand <david@kernel.org>
R: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
R: Liam R. Howlett <Liam.Howlett@oracle.com>
R: Vlastimil Babka <vbabka@suse.cz>
R: Vlastimil Babka <vbabka@kernel.org>
R: Mike Rapoport <rppt@kernel.org>
R: Suren Baghdasaryan <surenb@google.com>
R: Michal Hocko <mhocko@suse.com>
@ -16786,7 +16784,7 @@ M: Andrew Morton <akpm@linux-foundation.org>
M: David Hildenbrand <david@kernel.org>
R: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
R: Liam R. Howlett <Liam.Howlett@oracle.com>
R: Vlastimil Babka <vbabka@suse.cz>
R: Vlastimil Babka <vbabka@kernel.org>
R: Mike Rapoport <rppt@kernel.org>
R: Suren Baghdasaryan <surenb@google.com>
R: Michal Hocko <mhocko@suse.com>
@ -16841,7 +16839,7 @@ F: mm/oom_kill.c
MEMORY MANAGEMENT - PAGE ALLOCATOR
M: Andrew Morton <akpm@linux-foundation.org>
M: Vlastimil Babka <vbabka@suse.cz>
M: Vlastimil Babka <vbabka@kernel.org>
R: Suren Baghdasaryan <surenb@google.com>
R: Michal Hocko <mhocko@suse.com>
R: Brendan Jackman <jackmanb@google.com>
@ -16887,7 +16885,7 @@ M: David Hildenbrand <david@kernel.org>
M: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
R: Rik van Riel <riel@surriel.com>
R: Liam R. Howlett <Liam.Howlett@oracle.com>
R: Vlastimil Babka <vbabka@suse.cz>
R: Vlastimil Babka <vbabka@kernel.org>
R: Harry Yoo <harry.yoo@oracle.com>
R: Jann Horn <jannh@google.com>
L: linux-mm@kvack.org
@ -16986,7 +16984,7 @@ MEMORY MAPPING
M: Andrew Morton <akpm@linux-foundation.org>
M: Liam R. Howlett <Liam.Howlett@oracle.com>
M: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
R: Vlastimil Babka <vbabka@suse.cz>
R: Vlastimil Babka <vbabka@kernel.org>
R: Jann Horn <jannh@google.com>
R: Pedro Falcato <pfalcato@suse.de>
L: linux-mm@kvack.org
@ -17016,7 +17014,7 @@ M: Andrew Morton <akpm@linux-foundation.org>
M: Suren Baghdasaryan <surenb@google.com>
M: Liam R. Howlett <Liam.Howlett@oracle.com>
M: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
R: Vlastimil Babka <vbabka@suse.cz>
R: Vlastimil Babka <vbabka@kernel.org>
R: Shakeel Butt <shakeel.butt@linux.dev>
L: linux-mm@kvack.org
S: Maintained
@ -17032,7 +17030,7 @@ M: Andrew Morton <akpm@linux-foundation.org>
M: Liam R. Howlett <Liam.Howlett@oracle.com>
M: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
M: David Hildenbrand <david@kernel.org>
R: Vlastimil Babka <vbabka@suse.cz>
R: Vlastimil Babka <vbabka@kernel.org>
R: Jann Horn <jannh@google.com>
L: linux-mm@kvack.org
S: Maintained
@ -20509,7 +20507,7 @@ F: Documentation/devicetree/bindings/pci/hisilicon,kirin-pcie.yaml
F: drivers/pci/controller/dwc/pcie-kirin.c
PCIE DRIVER FOR HISILICON STB
M: Shawn Guo <shawn.guo@linaro.org>
M: Shawn Guo <shawnguo@kernel.org>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
@ -21695,7 +21693,7 @@ S: Maintained
F: drivers/net/ethernet/qualcomm/emac/
QUALCOMM ETHQOS ETHERNET DRIVER
M: Vinod Koul <vkoul@kernel.org>
M: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
L: netdev@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
@ -23174,7 +23172,7 @@ K: \b(?i:rust)\b
RUST [ALLOC]
M: Danilo Krummrich <dakr@kernel.org>
R: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
R: Vlastimil Babka <vbabka@suse.cz>
R: Vlastimil Babka <vbabka@kernel.org>
R: Liam R. Howlett <Liam.Howlett@oracle.com>
R: Uladzislau Rezki <urezki@gmail.com>
L: rust-for-linux@vger.kernel.org
@ -24350,7 +24348,7 @@ F: Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml
F: drivers/nvmem/layouts/sl28vpd.c
SLAB ALLOCATOR
M: Vlastimil Babka <vbabka@suse.cz>
M: Vlastimil Babka <vbabka@kernel.org>
M: Andrew Morton <akpm@linux-foundation.org>
R: Christoph Lameter <cl@gentwo.org>
R: David Rientjes <rientjes@google.com>
@ -26217,7 +26215,7 @@ F: drivers/media/radio/radio-raremono.c
THERMAL
M: Rafael J. Wysocki <rafael@kernel.org>
M: Daniel Lezcano <daniel.lezcano@linaro.org>
M: Daniel Lezcano <daniel.lezcano@kernel.org>
R: Zhang Rui <rui.zhang@intel.com>
R: Lukasz Luba <lukasz.luba@arm.com>
L: linux-pm@vger.kernel.org
@ -26247,7 +26245,7 @@ F: drivers/thermal/amlogic_thermal.c
THERMAL/CPU_COOLING
M: Amit Daniel Kachhap <amit.kachhap@gmail.com>
M: Daniel Lezcano <daniel.lezcano@linaro.org>
M: Daniel Lezcano <daniel.lezcano@kernel.org>
M: Viresh Kumar <viresh.kumar@linaro.org>
R: Lukasz Luba <lukasz.luba@arm.com>
L: linux-pm@vger.kernel.org
@ -29186,7 +29184,7 @@ K: zstd
ZSWAP COMPRESSED SWAP CACHING
M: Johannes Weiner <hannes@cmpxchg.org>
M: Yosry Ahmed <yosry.ahmed@linux.dev>
M: Yosry Ahmed <yosry@kernel.org>
M: Nhat Pham <nphamcs@gmail.com>
R: Chengming Zhou <chengming.zhou@linux.dev>
L: linux-mm@kvack.org

View File

@ -264,19 +264,33 @@ __iowrite64_copy(void __iomem *to, const void *from, size_t count)
typedef int (*ioremap_prot_hook_t)(phys_addr_t phys_addr, size_t size,
pgprot_t *prot);
int arm64_ioremap_prot_hook_register(const ioremap_prot_hook_t hook);
void __iomem *__ioremap_prot(phys_addr_t phys, size_t size, pgprot_t prot);
static inline void __iomem *ioremap_prot(phys_addr_t phys, size_t size,
pgprot_t user_prot)
{
pgprot_t prot;
ptdesc_t user_prot_val = pgprot_val(user_prot);
if (WARN_ON_ONCE(!(user_prot_val & PTE_USER)))
return NULL;
prot = __pgprot_modify(PAGE_KERNEL, PTE_ATTRINDX_MASK,
user_prot_val & PTE_ATTRINDX_MASK);
return __ioremap_prot(phys, size, prot);
}
#define ioremap_prot ioremap_prot
#define _PAGE_IOREMAP PROT_DEVICE_nGnRE
#define ioremap(addr, size) \
__ioremap_prot((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
#define ioremap_wc(addr, size) \
ioremap_prot((addr), (size), __pgprot(PROT_NORMAL_NC))
__ioremap_prot((addr), (size), __pgprot(PROT_NORMAL_NC))
#define ioremap_np(addr, size) \
ioremap_prot((addr), (size), __pgprot(PROT_DEVICE_nGnRnE))
__ioremap_prot((addr), (size), __pgprot(PROT_DEVICE_nGnRnE))
#define ioremap_encrypted(addr, size) \
ioremap_prot((addr), (size), PAGE_KERNEL)
__ioremap_prot((addr), (size), PAGE_KERNEL)
/*
* io{read,write}{16,32,64}be() macros
@ -297,7 +311,7 @@ static inline void __iomem *ioremap_cache(phys_addr_t addr, size_t size)
if (pfn_is_map_memory(__phys_to_pfn(addr)))
return (void __iomem *)__phys_to_virt(addr);
return ioremap_prot(addr, size, __pgprot(PROT_NORMAL));
return __ioremap_prot(addr, size, __pgprot(PROT_NORMAL));
}
/*

View File

@ -164,9 +164,6 @@ static inline bool __pure lpa2_is_enabled(void)
#define _PAGE_GCS (_PAGE_DEFAULT | PTE_NG | PTE_UXN | PTE_WRITE | PTE_USER)
#define _PAGE_GCS_RO (_PAGE_DEFAULT | PTE_NG | PTE_UXN | PTE_USER)
#define PAGE_GCS __pgprot(_PAGE_GCS)
#define PAGE_GCS_RO __pgprot(_PAGE_GCS_RO)
#define PIE_E0 ( \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS), PIE_GCS) | \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS_RO), PIE_R) | \

View File

@ -31,19 +31,11 @@
*/
#define __TLBI_0(op, arg) asm (ARM64_ASM_PREAMBLE \
"tlbi " #op "\n" \
ALTERNATIVE("nop\n nop", \
"dsb ish\n tlbi " #op, \
ARM64_WORKAROUND_REPEAT_TLBI, \
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
: : )
#define __TLBI_1(op, arg) asm (ARM64_ASM_PREAMBLE \
"tlbi " #op ", %0\n" \
ALTERNATIVE("nop\n nop", \
"dsb ish\n tlbi " #op ", %0", \
ARM64_WORKAROUND_REPEAT_TLBI, \
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
: : "r" (arg))
"tlbi " #op ", %x0\n" \
: : "rZ" (arg))
#define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
@ -181,6 +173,34 @@ static inline unsigned long get_trans_granule(void)
(__pages >> (5 * (scale) + 1)) - 1; \
})
#define __repeat_tlbi_sync(op, arg...) \
do { \
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI)) \
break; \
__tlbi(op, ##arg); \
dsb(ish); \
} while (0)
/*
* Complete broadcast TLB maintenance issued by the host which invalidates
* stage 1 information in the host's own translation regime.
*/
static inline void __tlbi_sync_s1ish(void)
{
dsb(ish);
__repeat_tlbi_sync(vale1is, 0);
}
/*
* Complete broadcast TLB maintenance issued by hyp code which invalidates
* stage 1 translation information in any translation regime.
*/
static inline void __tlbi_sync_s1ish_hyp(void)
{
dsb(ish);
__repeat_tlbi_sync(vale2is, 0);
}
/*
* TLB Invalidation
* ================
@ -279,7 +299,7 @@ static inline void flush_tlb_all(void)
{
dsb(ishst);
__tlbi(vmalle1is);
dsb(ish);
__tlbi_sync_s1ish();
isb();
}
@ -291,7 +311,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
asid = __TLBI_VADDR(0, ASID(mm));
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
dsb(ish);
__tlbi_sync_s1ish();
mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
}
@ -345,20 +365,11 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long uaddr)
{
flush_tlb_page_nosync(vma, uaddr);
dsb(ish);
__tlbi_sync_s1ish();
}
static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
{
/*
* TLB flush deferral is not required on systems which are affected by
* ARM64_WORKAROUND_REPEAT_TLBI, as __tlbi()/__tlbi_user() implementation
* will have two consecutive TLBI instructions with a dsb(ish) in between
* defeating the purpose (i.e save overall 'dsb ish' cost).
*/
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI))
return false;
return true;
}
@ -374,7 +385,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
*/
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
{
dsb(ish);
__tlbi_sync_s1ish();
}
/*
@ -509,7 +520,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
{
__flush_tlb_range_nosync(vma->vm_mm, start, end, stride,
last_level, tlb_level);
dsb(ish);
__tlbi_sync_s1ish();
}
static inline void local_flush_tlb_contpte(struct vm_area_struct *vma,
@ -557,7 +568,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
dsb(ishst);
__flush_tlb_range_op(vaale1is, start, pages, stride, 0,
TLBI_TTL_UNKNOWN, false, lpa2_is_enabled());
dsb(ish);
__tlbi_sync_s1ish();
isb();
}
@ -571,7 +582,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
dsb(ishst);
__tlbi(vaae1is, addr);
dsb(ish);
__tlbi_sync_s1ish();
isb();
}

View File

@ -377,7 +377,7 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
prot = __acpi_get_writethrough_mem_attribute();
}
}
return ioremap_prot(phys, size, prot);
return __ioremap_prot(phys, size, prot);
}
/*

View File

@ -37,7 +37,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end)
* We pick the reserved-ASID to minimise the impact.
*/
__tlbi(aside1is, __TLBI_VADDR(0, 0));
dsb(ish);
__tlbi_sync_s1ish();
}
ret = caches_clean_inval_user_pou(start, start + chunk);

View File

@ -400,16 +400,25 @@ static inline
int counters_read_on_cpu(int cpu, smp_call_func_t func, u64 *val)
{
/*
* Abort call on counterless CPU or when interrupts are
* disabled - can lead to deadlock in smp sync call.
* Abort call on counterless CPU.
*/
if (!cpu_has_amu_feat(cpu))
return -EOPNOTSUPP;
if (WARN_ON_ONCE(irqs_disabled()))
return -EPERM;
smp_call_function_single(cpu, func, val, 1);
if (irqs_disabled()) {
/*
* When IRQs are disabled (tick path: sched_tick ->
* topology_scale_freq_tick or cppc_scale_freq_tick), only local
* CPU counter reads are allowed. Remote CPU counter read would
* require smp_call_function_single() which is unsafe with IRQs
* disabled.
*/
if (WARN_ON_ONCE(cpu != smp_processor_id()))
return -EPERM;
func(val);
} else {
smp_call_function_single(cpu, func, val, 1);
}
return 0;
}

View File

@ -271,7 +271,7 @@ static void fixmap_clear_slot(struct hyp_fixmap_slot *slot)
*/
dsb(ishst);
__tlbi_level(vale2is, __TLBI_VADDR(addr, 0), level);
dsb(ish);
__tlbi_sync_s1ish_hyp();
isb();
}

View File

@ -169,7 +169,7 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
*/
dsb(ish);
__tlbi(vmalle1is);
dsb(ish);
__tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@ -226,7 +226,7 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
dsb(ish);
__tlbi(vmalle1is);
dsb(ish);
__tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@ -240,7 +240,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
enter_vmid_context(mmu, &cxt, false);
__tlbi(vmalls12e1is);
dsb(ish);
__tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@ -266,5 +266,5 @@ void __kvm_flush_vm_context(void)
/* Same remark as in enter_vmid_context() */
dsb(ish);
__tlbi(alle1is);
dsb(ish);
__tlbi_sync_s1ish_hyp();
}

View File

@ -501,7 +501,7 @@ static int hyp_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
*unmapped += granule;
}
dsb(ish);
__tlbi_sync_s1ish_hyp();
isb();
mm_ops->put_page(ctx->ptep);

View File

@ -115,7 +115,7 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
*/
dsb(ish);
__tlbi(vmalle1is);
dsb(ish);
__tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@ -176,7 +176,7 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
dsb(ish);
__tlbi(vmalle1is);
dsb(ish);
__tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@ -192,7 +192,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
enter_vmid_context(mmu, &cxt);
__tlbi(vmalls12e1is);
dsb(ish);
__tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@ -217,7 +217,7 @@ void __kvm_flush_vm_context(void)
{
dsb(ishst);
__tlbi(alle1is);
dsb(ish);
__tlbi_sync_s1ish_hyp();
}
/*
@ -358,7 +358,7 @@ int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding)
default:
ret = -EINVAL;
}
dsb(ish);
__tlbi_sync_s1ish_hyp();
isb();
if (mmu)

View File

@ -32,7 +32,11 @@ static inline unsigned long xloops_to_cycles(unsigned long xloops)
* Note that userspace cannot change the offset behind our back either,
* as the vcpu mutex is held as long as KVM_RUN is in progress.
*/
#define __delay_cycles() __arch_counter_get_cntvct_stable()
static cycles_t notrace __delay_cycles(void)
{
guard(preempt_notrace)();
return __arch_counter_get_cntvct_stable();
}
void __delay(unsigned long cycles)
{

View File

@ -14,8 +14,8 @@ int arm64_ioremap_prot_hook_register(ioremap_prot_hook_t hook)
return 0;
}
void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
pgprot_t pgprot)
void __iomem *__ioremap_prot(phys_addr_t phys_addr, size_t size,
pgprot_t pgprot)
{
unsigned long last_addr = phys_addr + size - 1;
@ -39,7 +39,7 @@ void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
return generic_ioremap_prot(phys_addr, size, pgprot);
}
EXPORT_SYMBOL(ioremap_prot);
EXPORT_SYMBOL(__ioremap_prot);
/*
* Must be called after early_fixmap_init

View File

@ -34,6 +34,8 @@ static pgprot_t protection_map[16] __ro_after_init = {
[VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_SHARED_EXEC
};
static ptdesc_t gcs_page_prot __ro_after_init = _PAGE_GCS_RO;
/*
* You really shouldn't be using read() or write() on /dev/mem. This might go
* away in the future.
@ -73,9 +75,11 @@ static int __init adjust_protection_map(void)
protection_map[VM_EXEC | VM_SHARED] = PAGE_EXECONLY;
}
if (lpa2_is_enabled())
if (lpa2_is_enabled()) {
for (int i = 0; i < ARRAY_SIZE(protection_map); i++)
pgprot_val(protection_map[i]) &= ~PTE_SHARED;
gcs_page_prot &= ~PTE_SHARED;
}
return 0;
}
@ -87,7 +91,11 @@ pgprot_t vm_get_page_prot(vm_flags_t vm_flags)
/* Short circuit GCS to avoid bloating the table. */
if (system_supports_gcs() && (vm_flags & VM_SHADOW_STACK)) {
prot = _PAGE_GCS_RO;
/* Honour mprotect(PROT_NONE) on shadow stack mappings */
if (vm_flags & VM_ACCESS_FLAGS)
prot = gcs_page_prot;
else
prot = pgprot_val(protection_map[VM_NONE]);
} else {
prot = pgprot_val(protection_map[vm_flags &
(VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]);

View File

@ -2119,7 +2119,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
extable_offset = round_up(prog_size + PLT_TARGET_SIZE, extable_align);
image_size = extable_offset + extable_size;
ro_header = bpf_jit_binary_pack_alloc(image_size, &ro_image_ptr,
sizeof(u32), &header, &image_ptr,
sizeof(u64), &header, &image_ptr,
jit_fill_hole);
if (!ro_header) {
prog = orig_prog;

View File

@ -19,9 +19,9 @@ struct s390_idle_data {
unsigned long mt_cycles_enter[8];
};
DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
extern struct device_attribute dev_attr_idle_count;
extern struct device_attribute dev_attr_idle_time_us;
void psw_idle(struct s390_idle_data *data, unsigned long psw_mask);
#endif /* _S390_IDLE_H */

View File

@ -2,6 +2,12 @@
#ifndef _S390_VTIME_H
#define _S390_VTIME_H
#include <asm/lowcore.h>
#include <asm/cpu_mf.h>
#include <asm/idle.h>
DECLARE_PER_CPU(u64, mt_cycles[8]);
static inline void update_timer_sys(void)
{
struct lowcore *lc = get_lowcore();
@ -20,4 +26,32 @@ static inline void update_timer_mcck(void)
lc->last_update_timer = lc->mcck_enter_timer;
}
static inline void update_timer_idle(void)
{
struct s390_idle_data *idle = this_cpu_ptr(&s390_idle);
struct lowcore *lc = get_lowcore();
u64 cycles_new[8];
int i, mtid;
mtid = smp_cpu_mtid;
if (mtid) {
stcctm(MT_DIAG, mtid, cycles_new);
for (i = 0; i < mtid; i++)
__this_cpu_add(mt_cycles[i], cycles_new[i] - idle->mt_cycles_enter[i]);
}
/*
* This is a bit subtle: Forward last_update_clock so it excludes idle
* time. For correct steal time calculation in do_account_vtime() add
* passed wall time before idle_enter to steal_timer:
* During the passed wall time before idle_enter CPU time may have
* been accounted to system, hardirq, softirq, etc. lowcore fields.
* The accounted CPU times will be subtracted again from steal_timer
* when accumulated steal time is calculated in do_account_vtime().
*/
lc->steal_timer += idle->clock_idle_enter - lc->last_update_clock;
lc->last_update_clock = lc->int_clock;
lc->system_timer += lc->last_update_timer - idle->timer_idle_enter;
lc->last_update_timer = lc->sys_enter_timer;
}
#endif /* _S390_VTIME_H */

View File

@ -56,8 +56,6 @@ long sys_s390_pci_mmio_write(unsigned long, const void __user *, size_t);
long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t);
long sys_s390_sthyi(unsigned long function_code, void __user *buffer, u64 __user *return_code, unsigned long flags);
DECLARE_PER_CPU(u64, mt_cycles[8]);
unsigned long stack_alloc(void);
void stack_free(unsigned long stack);

View File

@ -15,37 +15,22 @@
#include <trace/events/power.h>
#include <asm/cpu_mf.h>
#include <asm/cputime.h>
#include <asm/idle.h>
#include <asm/nmi.h>
#include <asm/smp.h>
#include "entry.h"
static DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
void account_idle_time_irq(void)
{
struct s390_idle_data *idle = this_cpu_ptr(&s390_idle);
struct lowcore *lc = get_lowcore();
unsigned long idle_time;
u64 cycles_new[8];
int i;
if (smp_cpu_mtid) {
stcctm(MT_DIAG, smp_cpu_mtid, cycles_new);
for (i = 0; i < smp_cpu_mtid; i++)
this_cpu_add(mt_cycles[i], cycles_new[i] - idle->mt_cycles_enter[i]);
}
idle_time = lc->int_clock - idle->clock_idle_enter;
lc->steal_timer += idle->clock_idle_enter - lc->last_update_clock;
lc->last_update_clock = lc->int_clock;
lc->system_timer += lc->last_update_timer - idle->timer_idle_enter;
lc->last_update_timer = lc->sys_enter_timer;
idle_time = get_lowcore()->int_clock - idle->clock_idle_enter;
/* Account time spent with enabled wait psw loaded as idle time. */
WRITE_ONCE(idle->idle_time, READ_ONCE(idle->idle_time) + idle_time);
WRITE_ONCE(idle->idle_count, READ_ONCE(idle->idle_count) + 1);
__atomic64_add(idle_time, &idle->idle_time);
__atomic64_add_const(1, &idle->idle_count);
account_idle_time(cputime_to_nsecs(idle_time));
}

View File

@ -2377,7 +2377,7 @@ void __init setup_ipl(void)
atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
}
void s390_reset_system(void)
void __no_stack_protector s390_reset_system(void)
{
/* Disable prefixing */
set_prefix(0);

View File

@ -146,6 +146,12 @@ void noinstr do_io_irq(struct pt_regs *regs)
struct pt_regs *old_regs = set_irq_regs(regs);
bool from_idle;
from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT);
if (from_idle) {
update_timer_idle();
regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT);
}
irq_enter_rcu();
if (user_mode(regs)) {
@ -154,7 +160,6 @@ void noinstr do_io_irq(struct pt_regs *regs)
current->thread.last_break = regs->last_break;
}
from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT);
if (from_idle)
account_idle_time_irq();
@ -171,9 +176,6 @@ void noinstr do_io_irq(struct pt_regs *regs)
set_irq_regs(old_regs);
irqentry_exit(regs, state);
if (from_idle)
regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT);
}
void noinstr do_ext_irq(struct pt_regs *regs)
@ -182,6 +184,12 @@ void noinstr do_ext_irq(struct pt_regs *regs)
struct pt_regs *old_regs = set_irq_regs(regs);
bool from_idle;
from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT);
if (from_idle) {
update_timer_idle();
regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT);
}
irq_enter_rcu();
if (user_mode(regs)) {
@ -194,7 +202,6 @@ void noinstr do_ext_irq(struct pt_regs *regs)
regs->int_parm = get_lowcore()->ext_params;
regs->int_parm_long = get_lowcore()->ext_params2;
from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT);
if (from_idle)
account_idle_time_irq();
@ -203,9 +210,6 @@ void noinstr do_ext_irq(struct pt_regs *regs)
irq_exit_rcu();
set_irq_regs(old_regs);
irqentry_exit(regs, state);
if (from_idle)
regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT);
}
static void show_msi_interrupt(struct seq_file *p, int irq)

View File

@ -48,8 +48,7 @@ static inline void set_vtimer(u64 expires)
static inline int virt_timer_forward(u64 elapsed)
{
BUG_ON(!irqs_disabled());
lockdep_assert_irqs_disabled();
if (list_empty(&virt_timer_list))
return 0;
elapsed = atomic64_add_return(elapsed, &virt_timer_elapsed);
@ -137,23 +136,16 @@ static int do_account_vtime(struct task_struct *tsk)
lc->system_timer += timer;
/* Update MT utilization calculation */
if (smp_cpu_mtid &&
time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies)))
if (smp_cpu_mtid && time_after64(jiffies_64, __this_cpu_read(mt_scaling_jiffies)))
update_mt_scaling();
/* Calculate cputime delta */
user = update_tsk_timer(&tsk->thread.user_timer,
READ_ONCE(lc->user_timer));
guest = update_tsk_timer(&tsk->thread.guest_timer,
READ_ONCE(lc->guest_timer));
system = update_tsk_timer(&tsk->thread.system_timer,
READ_ONCE(lc->system_timer));
hardirq = update_tsk_timer(&tsk->thread.hardirq_timer,
READ_ONCE(lc->hardirq_timer));
softirq = update_tsk_timer(&tsk->thread.softirq_timer,
READ_ONCE(lc->softirq_timer));
lc->steal_timer +=
clock - user - guest - system - hardirq - softirq;
user = update_tsk_timer(&tsk->thread.user_timer, lc->user_timer);
guest = update_tsk_timer(&tsk->thread.guest_timer, lc->guest_timer);
system = update_tsk_timer(&tsk->thread.system_timer, lc->system_timer);
hardirq = update_tsk_timer(&tsk->thread.hardirq_timer, lc->hardirq_timer);
softirq = update_tsk_timer(&tsk->thread.softirq_timer, lc->softirq_timer);
lc->steal_timer += clock - user - guest - system - hardirq - softirq;
/* Push account value */
if (user) {
@ -225,10 +217,6 @@ static u64 vtime_delta(void)
return timer - lc->last_update_timer;
}
/*
* Update process times based on virtual cpu times stored by entry.S
* to the lowcore fields user_timer, system_timer & steal_clock.
*/
void vtime_account_kernel(struct task_struct *tsk)
{
struct lowcore *lc = get_lowcore();
@ -238,27 +226,17 @@ void vtime_account_kernel(struct task_struct *tsk)
lc->guest_timer += delta;
else
lc->system_timer += delta;
virt_timer_forward(delta);
}
EXPORT_SYMBOL_GPL(vtime_account_kernel);
void vtime_account_softirq(struct task_struct *tsk)
{
u64 delta = vtime_delta();
get_lowcore()->softirq_timer += delta;
virt_timer_forward(delta);
get_lowcore()->softirq_timer += vtime_delta();
}
void vtime_account_hardirq(struct task_struct *tsk)
{
u64 delta = vtime_delta();
get_lowcore()->hardirq_timer += delta;
virt_timer_forward(delta);
get_lowcore()->hardirq_timer += vtime_delta();
}
/*

View File

@ -62,7 +62,7 @@ int __pfault_init(void)
"0: nopr %%r7\n"
EX_TABLE(0b, 0b)
: [rc] "+d" (rc)
: [refbk] "a" (&pfault_init_refbk), "m" (pfault_init_refbk)
: [refbk] "a" (virt_to_phys(&pfault_init_refbk)), "m" (pfault_init_refbk)
: "cc");
return rc;
}
@ -84,7 +84,7 @@ void __pfault_fini(void)
"0: nopr %%r7\n"
EX_TABLE(0b, 0b)
:
: [refbk] "a" (&pfault_fini_refbk), "m" (pfault_fini_refbk)
: [refbk] "a" (virt_to_phys(&pfault_fini_refbk)), "m" (pfault_fini_refbk)
: "cc");
}

View File

@ -312,6 +312,8 @@ static dma_addr_t dma_4u_map_phys(struct device *dev, phys_addr_t phys,
if (direction != DMA_TO_DEVICE)
iopte_protection |= IOPTE_WRITE;
phys &= IO_PAGE_MASK;
for (i = 0; i < npages; i++, base++, phys += IO_PAGE_SIZE)
iopte_val(*base) = iopte_protection | phys;

View File

@ -410,6 +410,8 @@ static dma_addr_t dma_4v_map_phys(struct device *dev, phys_addr_t phys,
iommu_batch_start(dev, prot, entry);
phys &= IO_PAGE_MASK;
for (i = 0; i < npages; i++, phys += IO_PAGE_SIZE) {
long err = iommu_batch_add(phys, mask);
if (unlikely(err < 0L))

View File

@ -69,11 +69,11 @@ struct io_thread_req {
};
static struct io_thread_req * (*irq_req_buffer)[];
static struct io_thread_req **irq_req_buffer;
static struct io_thread_req *irq_remainder;
static int irq_remainder_size;
static struct io_thread_req * (*io_req_buffer)[];
static struct io_thread_req **io_req_buffer;
static struct io_thread_req *io_remainder;
static int io_remainder_size;
@ -398,7 +398,7 @@ static int thread_fd = -1;
static int bulk_req_safe_read(
int fd,
struct io_thread_req * (*request_buffer)[],
struct io_thread_req **request_buffer,
struct io_thread_req **remainder,
int *remainder_size,
int max_recs
@ -465,7 +465,7 @@ static irqreturn_t ubd_intr(int irq, void *dev)
&irq_remainder, &irq_remainder_size,
UBD_REQ_BUFFER_SIZE)) >= 0) {
for (i = 0; i < len / sizeof(struct io_thread_req *); i++)
ubd_end_request((*irq_req_buffer)[i]);
ubd_end_request(irq_req_buffer[i]);
}
if (len < 0 && len != -EAGAIN)
@ -1512,7 +1512,7 @@ void *io_thread(void *arg)
}
for (count = 0; count < n/sizeof(struct io_thread_req *); count++) {
struct io_thread_req *req = (*io_req_buffer)[count];
struct io_thread_req *req = io_req_buffer[count];
int i;
io_count++;

View File

@ -23,9 +23,9 @@
#include "amdxdna_pci_drv.h"
#include "amdxdna_pm.h"
static bool force_cmdlist;
static bool force_cmdlist = true;
module_param(force_cmdlist, bool, 0600);
MODULE_PARM_DESC(force_cmdlist, "Force use command list (Default false)");
MODULE_PARM_DESC(force_cmdlist, "Force use command list (Default true)");
#define HWCTX_MAX_TIMEOUT 60000 /* milliseconds */
@ -53,6 +53,7 @@ static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwct
{
drm_sched_stop(&hwctx->priv->sched, bad_job);
aie2_destroy_context(xdna->dev_handle, hwctx);
drm_sched_start(&hwctx->priv->sched, 0);
}
static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx)
@ -80,7 +81,6 @@ static int aie2_hwctx_restart(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hw
}
out:
drm_sched_start(&hwctx->priv->sched, 0);
XDNA_DBG(xdna, "%s restarted, ret %d", hwctx->name, ret);
return ret;
}
@ -297,19 +297,23 @@ aie2_sched_job_run(struct drm_sched_job *sched_job)
struct dma_fence *fence;
int ret;
if (!hwctx->priv->mbox_chann)
ret = amdxdna_pm_resume_get(hwctx->client->xdna);
if (ret)
return NULL;
if (!mmget_not_zero(job->mm))
if (!hwctx->priv->mbox_chann) {
amdxdna_pm_suspend_put(hwctx->client->xdna);
return NULL;
}
if (!mmget_not_zero(job->mm)) {
amdxdna_pm_suspend_put(hwctx->client->xdna);
return ERR_PTR(-ESRCH);
}
kref_get(&job->refcnt);
fence = dma_fence_get(job->fence);
ret = amdxdna_pm_resume_get(hwctx->client->xdna);
if (ret)
goto out;
if (job->drv_cmd) {
switch (job->drv_cmd->opcode) {
case SYNC_DEBUG_BO:
@ -497,7 +501,7 @@ static void aie2_release_resource(struct amdxdna_hwctx *hwctx)
if (AIE2_FEATURE_ON(xdna->dev_handle, AIE2_TEMPORAL_ONLY)) {
ret = aie2_destroy_context(xdna->dev_handle, hwctx);
if (ret)
if (ret && ret != -ENODEV)
XDNA_ERR(xdna, "Destroy temporal only context failed, ret %d", ret);
} else {
ret = xrs_release_resource(xdna->xrs_hdl, (uintptr_t)hwctx);
@ -629,7 +633,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
goto free_entity;
}
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto free_col_list;
@ -760,7 +764,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size
if (!hwctx->cus)
return -ENOMEM;
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto free_cus;
@ -1070,6 +1074,8 @@ void aie2_hmm_invalidate(struct amdxdna_gem_obj *abo,
ret = dma_resv_wait_timeout(gobj->resv, DMA_RESV_USAGE_BOOKKEEP,
true, MAX_SCHEDULE_TIMEOUT);
if (!ret || ret == -ERESTARTSYS)
if (!ret)
XDNA_ERR(xdna, "Failed to wait for bo, ret %ld", ret);
else if (ret == -ERESTARTSYS)
XDNA_DBG(xdna, "Wait for bo interrupted by signal");
}

View File

@ -216,8 +216,10 @@ static int aie2_destroy_context_req(struct amdxdna_dev_hdl *ndev, u32 id)
req.context_id = id;
ret = aie2_send_mgmt_msg_wait(ndev, &msg);
if (ret)
if (ret && ret != -ENODEV)
XDNA_WARN(xdna, "Destroy context failed, ret %d", ret);
else if (ret == -ENODEV)
XDNA_DBG(xdna, "Destroy context: device already stopped");
return ret;
}
@ -318,6 +320,9 @@ int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwc
struct amdxdna_dev *xdna = ndev->xdna;
int ret;
if (!hwctx->priv->mbox_chann)
return 0;
xdna_mailbox_stop_channel(hwctx->priv->mbox_chann);
ret = aie2_destroy_context_req(ndev, hwctx->fw_ctx_id);
xdna_mailbox_destroy_channel(hwctx->priv->mbox_chann);
@ -694,11 +699,11 @@ aie2_cmdlist_fill_npu_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *siz
u32 cmd_len;
void *cmd;
memset(npu_slot, 0, sizeof(*npu_slot));
cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
if (*size < sizeof(*npu_slot) + cmd_len)
return -EINVAL;
memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
if (npu_slot->cu_idx == INVALID_CU_IDX)
return -EINVAL;
@ -719,7 +724,6 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
u32 cmd_len;
u32 arg_sz;
memset(npu_slot, 0, sizeof(*npu_slot));
sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
arg_sz = cmd_len - sizeof(*sn);
if (cmd_len < sizeof(*sn) || arg_sz > MAX_NPU_ARGS_SIZE)
@ -728,6 +732,7 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
if (*size < sizeof(*npu_slot) + arg_sz)
return -EINVAL;
memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
if (npu_slot->cu_idx == INVALID_CU_IDX)
return -EINVAL;
@ -751,7 +756,6 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t
u32 cmd_len;
u32 arg_sz;
memset(npu_slot, 0, sizeof(*npu_slot));
pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
arg_sz = cmd_len - sizeof(*pd);
if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
@ -760,6 +764,7 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t
if (*size < sizeof(*npu_slot) + arg_sz)
return -EINVAL;
memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->cu_idx = amdxdna_cmd_get_cu_idx(cmd_bo);
if (npu_slot->cu_idx == INVALID_CU_IDX)
return -EINVAL;
@ -787,7 +792,6 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
u32 cmd_len;
u32 arg_sz;
memset(npu_slot, 0, sizeof(*npu_slot));
pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
arg_sz = cmd_len - sizeof(*pd);
if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
@ -796,6 +800,7 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si
if (*size < sizeof(*npu_slot) + arg_sz)
return -EINVAL;
memset(npu_slot, 0, sizeof(*npu_slot));
npu_slot->type = EXEC_NPU_TYPE_ELF;
npu_slot->inst_buf_addr = pd->inst_buf;
npu_slot->save_buf_addr = pd->save_buf;

View File

@ -32,6 +32,11 @@ static int aie2_max_col = XRS_MAX_COL;
module_param(aie2_max_col, uint, 0600);
MODULE_PARM_DESC(aie2_max_col, "Maximum column could be used");
static char *npu_fw[] = {
"npu_7.sbin",
"npu.sbin"
};
/*
* The management mailbox channel is allocated by firmware.
* The related register and ring buffer information is on SRAM BAR.
@ -323,6 +328,7 @@ static void aie2_hw_stop(struct amdxdna_dev *xdna)
return;
}
aie2_runtime_cfg(ndev, AIE2_RT_CFG_CLK_GATING, NULL);
aie2_mgmt_fw_fini(ndev);
xdna_mailbox_stop_channel(ndev->mgmt_chann);
xdna_mailbox_destroy_channel(ndev->mgmt_chann);
@ -406,18 +412,18 @@ static int aie2_hw_start(struct amdxdna_dev *xdna)
goto stop_psp;
}
ret = aie2_pm_init(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
goto destroy_mgmt_chann;
}
ret = aie2_mgmt_fw_init(ndev);
if (ret) {
XDNA_ERR(xdna, "initial mgmt firmware failed, ret %d", ret);
goto destroy_mgmt_chann;
}
ret = aie2_pm_init(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to init pm, ret %d", ret);
goto destroy_mgmt_chann;
}
ret = aie2_mgmt_fw_query(ndev);
if (ret) {
XDNA_ERR(xdna, "failed to query fw, ret %d", ret);
@ -451,7 +457,6 @@ static int aie2_hw_suspend(struct amdxdna_dev *xdna)
{
struct amdxdna_client *client;
guard(mutex)(&xdna->dev_lock);
list_for_each_entry(client, &xdna->client_list, node)
aie2_hwctx_suspend(client);
@ -489,6 +494,7 @@ static int aie2_init(struct amdxdna_dev *xdna)
struct psp_config psp_conf;
const struct firmware *fw;
unsigned long bars = 0;
char *fw_full_path;
int i, nvec, ret;
if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
@ -503,7 +509,19 @@ static int aie2_init(struct amdxdna_dev *xdna)
ndev->priv = xdna->dev_info->dev_priv;
ndev->xdna = xdna;
ret = request_firmware(&fw, ndev->priv->fw_path, &pdev->dev);
for (i = 0; i < ARRAY_SIZE(npu_fw); i++) {
fw_full_path = kasprintf(GFP_KERNEL, "%s%s", ndev->priv->fw_path, npu_fw[i]);
if (!fw_full_path)
return -ENOMEM;
ret = firmware_request_nowarn(&fw, fw_full_path, &pdev->dev);
kfree(fw_full_path);
if (!ret) {
XDNA_INFO(xdna, "Load firmware %s%s", ndev->priv->fw_path, npu_fw[i]);
break;
}
}
if (ret) {
XDNA_ERR(xdna, "failed to request_firmware %s, ret %d",
ndev->priv->fw_path, ret);
@ -951,7 +969,7 @@ static int aie2_get_info(struct amdxdna_client *client, struct amdxdna_drm_get_i
if (!drm_dev_enter(&xdna->ddev, &idx))
return -ENODEV;
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto dev_exit;
@ -1044,7 +1062,7 @@ static int aie2_get_array(struct amdxdna_client *client,
if (!drm_dev_enter(&xdna->ddev, &idx))
return -ENODEV;
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto dev_exit;
@ -1134,7 +1152,7 @@ static int aie2_set_state(struct amdxdna_client *client,
if (!drm_dev_enter(&xdna->ddev, &idx))
return -ENODEV;
ret = amdxdna_pm_resume_get(xdna);
ret = amdxdna_pm_resume_get_locked(xdna);
if (ret)
goto dev_exit;

View File

@ -31,7 +31,7 @@ int aie2_pm_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
{
int ret;
ret = amdxdna_pm_resume_get(ndev->xdna);
ret = amdxdna_pm_resume_get_locked(ndev->xdna);
if (ret)
return ret;

View File

@ -104,7 +104,10 @@ void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size)
if (size) {
count = FIELD_GET(AMDXDNA_CMD_COUNT, cmd->header);
if (unlikely(count <= num_masks)) {
if (unlikely(count <= num_masks ||
count * sizeof(u32) +
offsetof(struct amdxdna_cmd, data[0]) >
abo->mem.size)) {
*size = 0;
return NULL;
}
@ -266,9 +269,9 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
struct amdxdna_drm_config_hwctx *args = data;
struct amdxdna_dev *xdna = to_xdna_dev(dev);
struct amdxdna_hwctx *hwctx;
int ret, idx;
u32 buf_size;
void *buf;
int ret;
u64 val;
if (XDNA_MBZ_DBG(xdna, &args->pad, sizeof(args->pad)))
@ -310,20 +313,17 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
return -EINVAL;
}
mutex_lock(&xdna->dev_lock);
idx = srcu_read_lock(&client->hwctx_srcu);
guard(mutex)(&xdna->dev_lock);
hwctx = xa_load(&client->hwctx_xa, args->handle);
if (!hwctx) {
XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
ret = -EINVAL;
goto unlock_srcu;
goto free_buf;
}
ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
unlock_srcu:
srcu_read_unlock(&client->hwctx_srcu, idx);
mutex_unlock(&xdna->dev_lock);
free_buf:
kfree(buf);
return ret;
}
@ -334,7 +334,7 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
struct amdxdna_hwctx *hwctx;
struct amdxdna_gem_obj *abo;
struct drm_gem_object *gobj;
int ret, idx;
int ret;
if (!xdna->dev_info->ops->hwctx_sync_debug_bo)
return -EOPNOTSUPP;
@ -345,17 +345,15 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl)
abo = to_xdna_obj(gobj);
guard(mutex)(&xdna->dev_lock);
idx = srcu_read_lock(&client->hwctx_srcu);
hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
if (!hwctx) {
ret = -EINVAL;
goto unlock_srcu;
goto put_obj;
}
ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
unlock_srcu:
srcu_read_unlock(&client->hwctx_srcu, idx);
put_obj:
drm_gem_object_put(gobj);
return ret;
}

View File

@ -21,8 +21,6 @@
#include "amdxdna_pci_drv.h"
#include "amdxdna_ubuf.h"
#define XDNA_MAX_CMD_BO_SIZE SZ_32K
MODULE_IMPORT_NS("DMA_BUF");
static int
@ -745,12 +743,6 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
{
struct amdxdna_dev *xdna = to_xdna_dev(dev);
struct amdxdna_gem_obj *abo;
int ret;
if (args->size > XDNA_MAX_CMD_BO_SIZE) {
XDNA_ERR(xdna, "Command bo size 0x%llx too large", args->size);
return ERR_PTR(-EINVAL);
}
if (args->size < sizeof(struct amdxdna_cmd)) {
XDNA_DBG(xdna, "Command BO size 0x%llx too small", args->size);
@ -764,17 +756,7 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev,
abo->type = AMDXDNA_BO_CMD;
abo->client = filp->driver_priv;
ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
if (ret) {
XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
goto release_obj;
}
return abo;
release_obj:
drm_gem_object_put(to_gobj(abo));
return ERR_PTR(ret);
}
int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
@ -871,6 +853,7 @@ struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
struct amdxdna_dev *xdna = client->xdna;
struct amdxdna_gem_obj *abo;
struct drm_gem_object *gobj;
int ret;
gobj = drm_gem_object_lookup(client->filp, bo_hdl);
if (!gobj) {
@ -879,9 +862,26 @@ struct amdxdna_gem_obj *amdxdna_gem_get_obj(struct amdxdna_client *client,
}
abo = to_xdna_obj(gobj);
if (bo_type == AMDXDNA_BO_INVALID || abo->type == bo_type)
if (bo_type != AMDXDNA_BO_INVALID && abo->type != bo_type)
goto put_obj;
if (bo_type != AMDXDNA_BO_CMD || abo->mem.kva)
return abo;
if (abo->mem.size > SZ_32K) {
XDNA_ERR(xdna, "Cmd bo is too big %ld", abo->mem.size);
goto put_obj;
}
ret = amdxdna_gem_obj_vmap(abo, &abo->mem.kva);
if (ret) {
XDNA_ERR(xdna, "Vmap cmd bo failed, ret %d", ret);
goto put_obj;
}
return abo;
put_obj:
drm_gem_object_put(gobj);
return NULL;
}

View File

@ -23,6 +23,9 @@ MODULE_FIRMWARE("amdnpu/1502_00/npu.sbin");
MODULE_FIRMWARE("amdnpu/17f0_10/npu.sbin");
MODULE_FIRMWARE("amdnpu/17f0_11/npu.sbin");
MODULE_FIRMWARE("amdnpu/17f0_20/npu.sbin");
MODULE_FIRMWARE("amdnpu/1502_00/npu_7.sbin");
MODULE_FIRMWARE("amdnpu/17f0_10/npu_7.sbin");
MODULE_FIRMWARE("amdnpu/17f0_11/npu_7.sbin");
/*
* 0.0: Initial version

View File

@ -16,6 +16,7 @@ int amdxdna_pm_suspend(struct device *dev)
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
int ret = -EOPNOTSUPP;
guard(mutex)(&xdna->dev_lock);
if (xdna->dev_info->ops->suspend)
ret = xdna->dev_info->ops->suspend(xdna);
@ -28,6 +29,7 @@ int amdxdna_pm_resume(struct device *dev)
struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
int ret = -EOPNOTSUPP;
guard(mutex)(&xdna->dev_lock);
if (xdna->dev_info->ops->resume)
ret = xdna->dev_info->ops->resume(xdna);

View File

@ -15,4 +15,15 @@ void amdxdna_pm_suspend_put(struct amdxdna_dev *xdna);
void amdxdna_pm_init(struct amdxdna_dev *xdna);
void amdxdna_pm_fini(struct amdxdna_dev *xdna);
static inline int amdxdna_pm_resume_get_locked(struct amdxdna_dev *xdna)
{
int ret;
mutex_unlock(&xdna->dev_lock);
ret = amdxdna_pm_resume_get(xdna);
mutex_lock(&xdna->dev_lock);
return ret;
}
#endif /* _AMDXDNA_PM_H_ */

View File

@ -7,6 +7,7 @@
#include <drm/drm_device.h>
#include <drm/drm_print.h>
#include <linux/dma-buf.h>
#include <linux/overflow.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
@ -176,7 +177,10 @@ struct dma_buf *amdxdna_get_ubuf(struct drm_device *dev,
goto free_ent;
}
exp_info.size += va_ent[i].len;
if (check_add_overflow(exp_info.size, va_ent[i].len, &exp_info.size)) {
ret = -EINVAL;
goto free_ent;
}
}
ubuf->nr_pages = exp_info.size >> PAGE_SHIFT;

View File

@ -72,7 +72,7 @@ static const struct aie2_fw_feature_tbl npu1_fw_feature_table[] = {
};
static const struct amdxdna_dev_priv npu1_dev_priv = {
.fw_path = "amdnpu/1502_00/npu.sbin",
.fw_path = "amdnpu/1502_00/",
.rt_config = npu1_default_rt_cfg,
.dpm_clk_tbl = npu1_dpm_clk_table,
.fw_feature_tbl = npu1_fw_feature_table,

View File

@ -98,7 +98,7 @@ const struct aie2_fw_feature_tbl npu4_fw_feature_table[] = {
};
static const struct amdxdna_dev_priv npu4_dev_priv = {
.fw_path = "amdnpu/17f0_10/npu.sbin",
.fw_path = "amdnpu/17f0_10/",
.rt_config = npu4_default_rt_cfg,
.dpm_clk_tbl = npu4_dpm_clk_table,
.fw_feature_tbl = npu4_fw_feature_table,

View File

@ -63,7 +63,7 @@
#define NPU5_SRAM_BAR_BASE MMNPU_APERTURE1_BASE
static const struct amdxdna_dev_priv npu5_dev_priv = {
.fw_path = "amdnpu/17f0_11/npu.sbin",
.fw_path = "amdnpu/17f0_11/",
.rt_config = npu4_default_rt_cfg,
.dpm_clk_tbl = npu4_dpm_clk_table,
.fw_feature_tbl = npu4_fw_feature_table,

View File

@ -63,7 +63,7 @@
#define NPU6_SRAM_BAR_BASE MMNPU_APERTURE1_BASE
static const struct amdxdna_dev_priv npu6_dev_priv = {
.fw_path = "amdnpu/17f0_10/npu.sbin",
.fw_path = "amdnpu/17f0_10/",
.rt_config = npu4_default_rt_cfg,
.dpm_clk_tbl = npu4_dpm_clk_table,
.fw_feature_tbl = npu4_fw_feature_table,

View File

@ -154,7 +154,7 @@ static void cmd_state_init(struct cmd_state *st)
static u64 cmd_to_addr(u32 *cmd)
{
return ((u64)((cmd[0] & 0xff0000) << 16)) | cmd[1];
return (((u64)cmd[0] & 0xff0000) << 16) | cmd[1];
}
static u64 dma_length(struct ethosu_validated_cmdstream_info *info,

View File

@ -389,6 +389,19 @@ static const struct dmi_system_id acpi_osi_dmi_table[] __initconst = {
},
},
/*
* The screen backlight turns off during udev device creation
* when returning true for _OSI("Windows 2009")
*/
{
.callback = dmi_disable_osi_win7,
.ident = "Acer Aspire One D255",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "AOD255"),
},
},
/*
* The wireless hotkey does not work on those machines when
* returning true for _OSI("Windows 2012")

View File

@ -386,6 +386,14 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "80E1"),
},
},
{
.callback = init_nvs_save_s3,
.ident = "Lenovo G70-35",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "80Q5"),
},
},
/*
* ThinkPad X1 Tablet(2016) cannot do suspend-to-idle using
* the Low Power S0 Idle firmware interface (see

View File

@ -6269,10 +6269,6 @@ static void ata_port_detach(struct ata_port *ap)
}
}
/* Make sure the deferred qc work finished. */
cancel_work_sync(&ap->deferred_qc_work);
WARN_ON(ap->deferred_qc);
/* Tell EH to disable all devices */
ap->pflags |= ATA_PFLAG_UNLOADING;
ata_port_schedule_eh(ap);
@ -6283,9 +6279,11 @@ static void ata_port_detach(struct ata_port *ap)
/* wait till EH commits suicide */
ata_port_wait_eh(ap);
/* it better be dead now */
/* It better be dead now and not have any remaining deferred qc. */
WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED));
WARN_ON(ap->deferred_qc);
cancel_work_sync(&ap->deferred_qc_work);
cancel_delayed_work_sync(&ap->hotplug_task);
cancel_delayed_work_sync(&ap->scsi_rescan_task);

View File

@ -640,12 +640,28 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
set_host_byte(scmd, DID_OK);
ata_qc_for_each_raw(ap, qc, i) {
if (qc->flags & ATA_QCFLAG_ACTIVE &&
qc->scsicmd == scmd)
if (qc->scsicmd != scmd)
continue;
if ((qc->flags & ATA_QCFLAG_ACTIVE) ||
qc == ap->deferred_qc)
break;
}
if (i < ATA_MAX_QUEUE) {
if (qc == ap->deferred_qc) {
/*
* This is a deferred command that timed out while
* waiting for the command queue to drain. Since the qc
* is not active yet (deferred_qc is still set, so the
* deferred qc work has not issued the command yet),
* simply signal the timeout by finishing the SCSI
* command and clear the deferred qc to prevent the
* deferred qc work from issuing this qc.
*/
WARN_ON_ONCE(qc->flags & ATA_QCFLAG_ACTIVE);
ap->deferred_qc = NULL;
set_host_byte(scmd, DID_TIME_OUT);
scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
} else if (i < ATA_MAX_QUEUE) {
/* the scmd has an associated qc */
if (!(qc->flags & ATA_QCFLAG_EH)) {
/* which hasn't failed yet, timeout */

View File

@ -797,7 +797,18 @@ struct fwnode_handle *
fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
struct fwnode_handle *child)
{
return fwnode_call_ptr_op(fwnode, get_next_child_node, child);
struct fwnode_handle *next;
if (IS_ERR_OR_NULL(fwnode))
return NULL;
/* Try to find a child in primary fwnode */
next = fwnode_call_ptr_op(fwnode, get_next_child_node, child);
if (next)
return next;
/* When no more children in primary, continue with secondary */
return fwnode_call_ptr_op(fwnode->secondary, get_next_child_node, child);
}
EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
@ -841,19 +852,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
struct fwnode_handle *device_get_next_child_node(const struct device *dev,
struct fwnode_handle *child)
{
const struct fwnode_handle *fwnode = dev_fwnode(dev);
struct fwnode_handle *next;
if (IS_ERR_OR_NULL(fwnode))
return NULL;
/* Try to find a child in primary fwnode */
next = fwnode_get_next_child_node(fwnode, child);
if (next)
return next;
/* When no more children in primary, continue with secondary */
return fwnode_get_next_child_node(fwnode->secondary, child);
return fwnode_get_next_child_node(dev_fwnode(dev), child);
}
EXPORT_SYMBOL_GPL(device_get_next_child_node);

View File

@ -483,38 +483,20 @@ void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i)
int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *i)
{
struct lru_cache *al = device->act_log;
/* for bios crossing activity log extent boundaries,
* we may need to activate two extents in one go */
unsigned first = i->sector >> (AL_EXTENT_SHIFT-9);
unsigned last = i->size == 0 ? first : (i->sector + (i->size >> 9) - 1) >> (AL_EXTENT_SHIFT-9);
unsigned nr_al_extents;
unsigned available_update_slots;
unsigned enr;
D_ASSERT(device, first <= last);
nr_al_extents = 1 + last - first; /* worst case: all touched extends are cold. */
available_update_slots = min(al->nr_elements - al->used,
al->max_pending_changes - al->pending_changes);
/* We want all necessary updates for a given request within the same transaction
* We could first check how many updates are *actually* needed,
* and use that instead of the worst-case nr_al_extents */
if (available_update_slots < nr_al_extents) {
/* Too many activity log extents are currently "hot".
*
* If we have accumulated pending changes already,
* we made progress.
*
* If we cannot get even a single pending change through,
* stop the fast path until we made some progress,
* or requests to "cold" extents could be starved. */
if (!al->pending_changes)
__set_bit(__LC_STARVING, &device->act_log->flags);
return -ENOBUFS;
if (i->partially_in_al_next_enr) {
D_ASSERT(device, first < i->partially_in_al_next_enr);
D_ASSERT(device, last >= i->partially_in_al_next_enr);
first = i->partially_in_al_next_enr;
}
D_ASSERT(device, first <= last);
/* Is resync active in this area? */
for (enr = first; enr <= last; enr++) {
struct lc_element *tmp;
@ -529,14 +511,21 @@ int drbd_al_begin_io_nonblock(struct drbd_device *device, struct drbd_interval *
}
}
/* Checkout the refcounts.
* Given that we checked for available elements and update slots above,
* this has to be successful. */
/* Try to checkout the refcounts. */
for (enr = first; enr <= last; enr++) {
struct lc_element *al_ext;
al_ext = lc_get_cumulative(device->act_log, enr);
if (!al_ext)
drbd_info(device, "LOGIC BUG for enr=%u\n", enr);
if (!al_ext) {
/* Did not work. We may have exhausted the possible
* changes per transaction. Or raced with someone
* "locking" it against changes.
* Remember where to continue from.
*/
if (enr > first)
i->partially_in_al_next_enr = enr;
return -ENOBUFS;
}
}
return 0;
}
@ -556,7 +545,11 @@ void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i)
for (enr = first; enr <= last; enr++) {
extent = lc_find(device->act_log, enr);
if (!extent) {
/* Yes, this masks a bug elsewhere. However, during normal
* operation this is harmless, so no need to crash the kernel
* by the BUG_ON(refcount == 0) in lc_put().
*/
if (!extent || extent->refcnt == 0) {
drbd_err(device, "al_complete_io() called on inactive extent %u\n", enr);
continue;
}

View File

@ -8,12 +8,15 @@
struct drbd_interval {
struct rb_node rb;
sector_t sector; /* start sector of the interval */
unsigned int size; /* size in bytes */
sector_t end; /* highest interval end in subtree */
unsigned int size; /* size in bytes */
unsigned int local:1 /* local or remote request? */;
unsigned int waiting:1; /* someone is waiting for completion */
unsigned int completed:1; /* this has been completed already;
* ignore for conflict detection */
/* to resume a partially successful drbd_al_begin_io_nonblock(); */
unsigned int partially_in_al_next_enr;
};
static inline void drbd_clear_interval(struct drbd_interval *i)

View File

@ -32,6 +32,7 @@
#include <linux/memcontrol.h>
#include <linux/mm_inline.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/random.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
@ -732,9 +733,9 @@ int drbd_send_sync_param(struct drbd_peer_device *peer_device)
}
if (apv >= 88)
strcpy(p->verify_alg, nc->verify_alg);
strscpy(p->verify_alg, nc->verify_alg);
if (apv >= 89)
strcpy(p->csums_alg, nc->csums_alg);
strscpy(p->csums_alg, nc->csums_alg);
rcu_read_unlock();
return drbd_send_command(peer_device, sock, cmd, size, NULL, 0);
@ -745,6 +746,7 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
struct drbd_socket *sock;
struct p_protocol *p;
struct net_conf *nc;
size_t integrity_alg_len;
int size, cf;
sock = &connection->data;
@ -762,8 +764,10 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
}
size = sizeof(*p);
if (connection->agreed_pro_version >= 87)
size += strlen(nc->integrity_alg) + 1;
if (connection->agreed_pro_version >= 87) {
integrity_alg_len = strlen(nc->integrity_alg) + 1;
size += integrity_alg_len;
}
p->protocol = cpu_to_be32(nc->wire_protocol);
p->after_sb_0p = cpu_to_be32(nc->after_sb_0p);
@ -778,7 +782,7 @@ int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_packet cm
p->conn_flags = cpu_to_be32(cf);
if (connection->agreed_pro_version >= 87)
strcpy(p->integrity_alg, nc->integrity_alg);
strscpy(p->integrity_alg, nc->integrity_alg, integrity_alg_len);
rcu_read_unlock();
return __conn_send_command(connection, sock, cmd, size, NULL, 0);

View File

@ -3801,14 +3801,14 @@ static int receive_SyncParam(struct drbd_connection *connection, struct packet_i
*new_net_conf = *old_net_conf;
if (verify_tfm) {
strcpy(new_net_conf->verify_alg, p->verify_alg);
strscpy(new_net_conf->verify_alg, p->verify_alg);
new_net_conf->verify_alg_len = strlen(p->verify_alg) + 1;
crypto_free_shash(peer_device->connection->verify_tfm);
peer_device->connection->verify_tfm = verify_tfm;
drbd_info(device, "using verify-alg: \"%s\"\n", p->verify_alg);
}
if (csums_tfm) {
strcpy(new_net_conf->csums_alg, p->csums_alg);
strscpy(new_net_conf->csums_alg, p->csums_alg);
new_net_conf->csums_alg_len = strlen(p->csums_alg) + 1;
crypto_free_shash(peer_device->connection->csums_tfm);
peer_device->connection->csums_tfm = csums_tfm;

View File

@ -621,7 +621,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
break;
case READ_COMPLETED_WITH_ERROR:
drbd_set_out_of_sync(peer_device, req->i.sector, req->i.size);
drbd_set_out_of_sync(first_peer_device(device),
req->i.sector, req->i.size);
drbd_report_io_error(device, req);
__drbd_chk_io_error(device, DRBD_READ_ERROR);
fallthrough;

View File

@ -542,6 +542,21 @@ static void zloop_rw(struct zloop_cmd *cmd)
zloop_put_cmd(cmd);
}
/*
* Sync the entire FS containing the zone files instead of walking all files.
*/
static int zloop_flush(struct zloop_device *zlo)
{
struct super_block *sb = file_inode(zlo->data_dir)->i_sb;
int ret;
down_read(&sb->s_umount);
ret = sync_filesystem(sb);
up_read(&sb->s_umount);
return ret;
}
static void zloop_handle_cmd(struct zloop_cmd *cmd)
{
struct request *rq = blk_mq_rq_from_pdu(cmd);
@ -562,11 +577,7 @@ static void zloop_handle_cmd(struct zloop_cmd *cmd)
zloop_rw(cmd);
return;
case REQ_OP_FLUSH:
/*
* Sync the entire FS containing the zone files instead of
* walking all files
*/
cmd->ret = sync_filesystem(file_inode(zlo->data_dir)->i_sb);
cmd->ret = zloop_flush(zlo);
break;
case REQ_OP_ZONE_RESET:
cmd->ret = zloop_reset_zone(zlo, rq_zone_no(rq));
@ -981,7 +992,8 @@ static int zloop_ctl_add(struct zloop_options *opts)
struct queue_limits lim = {
.max_hw_sectors = SZ_1M >> SECTOR_SHIFT,
.chunk_sectors = opts->zone_size,
.features = BLK_FEAT_ZONED,
.features = BLK_FEAT_ZONED | BLK_FEAT_WRITE_CACHE,
};
unsigned int nr_zones, i, j;
struct zloop_device *zlo;
@ -1162,7 +1174,12 @@ static int zloop_ctl_remove(struct zloop_options *opts)
int ret;
if (!(opts->mask & ZLOOP_OPT_ID)) {
pr_err("No ID specified\n");
pr_err("No ID specified for remove\n");
return -EINVAL;
}
if (opts->mask & ~ZLOOP_OPT_ID) {
pr_err("Invalid option specified for remove\n");
return -EINVAL;
}

View File

@ -2046,19 +2046,23 @@ static int qca_setup(struct hci_uart *hu)
}
out:
if (ret && retries < MAX_INIT_RETRIES) {
bt_dev_warn(hdev, "Retry BT power ON:%d", retries);
if (ret) {
qca_power_shutdown(hu);
if (hu->serdev) {
serdev_device_close(hu->serdev);
ret = serdev_device_open(hu->serdev);
if (ret) {
bt_dev_err(hdev, "failed to open port");
return ret;
if (retries < MAX_INIT_RETRIES) {
bt_dev_warn(hdev, "Retry BT power ON:%d", retries);
if (hu->serdev) {
serdev_device_close(hu->serdev);
ret = serdev_device_open(hu->serdev);
if (ret) {
bt_dev_err(hdev, "failed to open port");
return ret;
}
}
retries++;
goto retry;
}
retries++;
goto retry;
return ret;
}
/* Setup bdaddr */

View File

@ -202,11 +202,16 @@ static int ipmi_ipmb_slave_cb(struct i2c_client *client,
break;
case I2C_SLAVE_READ_REQUESTED:
*val = 0xff;
ipmi_ipmb_check_msg_done(iidev);
break;
case I2C_SLAVE_STOP:
ipmi_ipmb_check_msg_done(iidev);
break;
case I2C_SLAVE_READ_PROCESSED:
*val = 0xff;
break;
}

View File

@ -602,6 +602,22 @@ static int __ipmi_bmc_register(struct ipmi_smi *intf,
static int __scan_channels(struct ipmi_smi *intf,
struct ipmi_device_id *id, bool rescan);
static void ipmi_lock_xmit_msgs(struct ipmi_smi *intf, int run_to_completion,
unsigned long *flags)
{
if (run_to_completion)
return;
spin_lock_irqsave(&intf->xmit_msgs_lock, *flags);
}
static void ipmi_unlock_xmit_msgs(struct ipmi_smi *intf, int run_to_completion,
unsigned long *flags)
{
if (run_to_completion)
return;
spin_unlock_irqrestore(&intf->xmit_msgs_lock, *flags);
}
static void free_ipmi_user(struct kref *ref)
{
struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
@ -1869,21 +1885,32 @@ static struct ipmi_smi_msg *smi_add_send_msg(struct ipmi_smi *intf,
return smi_msg;
}
static void smi_send(struct ipmi_smi *intf,
static int smi_send(struct ipmi_smi *intf,
const struct ipmi_smi_handlers *handlers,
struct ipmi_smi_msg *smi_msg, int priority)
{
int run_to_completion = READ_ONCE(intf->run_to_completion);
unsigned long flags = 0;
int rv = 0;
if (!run_to_completion)
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
smi_msg = smi_add_send_msg(intf, smi_msg, priority);
if (!run_to_completion)
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
if (smi_msg)
handlers->sender(intf->send_info, smi_msg);
if (smi_msg) {
rv = handlers->sender(intf->send_info, smi_msg);
if (rv) {
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
intf->curr_msg = NULL;
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
/*
* Something may have been added to the transmit
* queue, so schedule a check for that.
*/
queue_work(system_wq, &intf->smi_work);
}
}
return rv;
}
static bool is_maintenance_mode_cmd(struct kernel_ipmi_msg *msg)
@ -2296,6 +2323,7 @@ static int i_ipmi_request(struct ipmi_user *user,
struct ipmi_recv_msg *recv_msg;
int run_to_completion = READ_ONCE(intf->run_to_completion);
int rv = 0;
bool in_seq_table = false;
if (supplied_recv) {
recv_msg = supplied_recv;
@ -2349,33 +2377,50 @@ static int i_ipmi_request(struct ipmi_user *user,
rv = i_ipmi_req_ipmb(intf, addr, msgid, msg, smi_msg, recv_msg,
source_address, source_lun,
retries, retry_time_ms);
in_seq_table = true;
} else if (is_ipmb_direct_addr(addr)) {
rv = i_ipmi_req_ipmb_direct(intf, addr, msgid, msg, smi_msg,
recv_msg, source_lun);
} else if (is_lan_addr(addr)) {
rv = i_ipmi_req_lan(intf, addr, msgid, msg, smi_msg, recv_msg,
source_lun, retries, retry_time_ms);
in_seq_table = true;
} else {
/* Unknown address type. */
/* Unknown address type. */
ipmi_inc_stat(intf, sent_invalid_commands);
rv = -EINVAL;
}
if (rv) {
if (!rv) {
dev_dbg(intf->si_dev, "Send: %*ph\n",
smi_msg->data_size, smi_msg->data);
rv = smi_send(intf, intf->handlers, smi_msg, priority);
if (rv != IPMI_CC_NO_ERROR)
/* smi_send() returns an IPMI err, return a Linux one. */
rv = -EIO;
if (rv && in_seq_table) {
/*
* If it's in the sequence table, it will be
* retried later, so ignore errors.
*/
rv = 0;
/* But we need to fix the timeout. */
intf_start_seq_timer(intf, smi_msg->msgid);
ipmi_free_smi_msg(smi_msg);
smi_msg = NULL;
}
}
out_err:
if (!run_to_completion)
mutex_unlock(&intf->users_mutex);
if (rv) {
if (!supplied_smi)
ipmi_free_smi_msg(smi_msg);
if (!supplied_recv)
ipmi_free_recv_msg(recv_msg);
} else {
dev_dbg(intf->si_dev, "Send: %*ph\n",
smi_msg->data_size, smi_msg->data);
smi_send(intf, intf->handlers, smi_msg, priority);
}
if (!run_to_completion)
mutex_unlock(&intf->users_mutex);
return rv;
}
@ -3949,12 +3994,12 @@ static int handle_ipmb_get_msg_cmd(struct ipmi_smi *intf,
dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
msg->data_size, msg->data);
smi_send(intf, intf->handlers, msg, 0);
/*
* We used the message, so return the value that
* causes it to not be freed or queued.
*/
rv = -1;
if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
/*
* We used the message, so return the value that
* causes it to not be freed or queued.
*/
rv = -1;
} else if (!IS_ERR(recv_msg)) {
/* Extract the source address from the data. */
ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr;
@ -4028,12 +4073,12 @@ static int handle_ipmb_direct_rcv_cmd(struct ipmi_smi *intf,
msg->data[4] = IPMI_INVALID_CMD_COMPLETION_CODE;
msg->data_size = 5;
smi_send(intf, intf->handlers, msg, 0);
/*
* We used the message, so return the value that
* causes it to not be freed or queued.
*/
rv = -1;
if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
/*
* We used the message, so return the value that
* causes it to not be freed or queued.
*/
rv = -1;
} else if (!IS_ERR(recv_msg)) {
/* Extract the source address from the data. */
daddr = (struct ipmi_ipmb_direct_addr *)&recv_msg->addr;
@ -4173,7 +4218,7 @@ static int handle_lan_get_msg_cmd(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{
struct cmd_rcvr *rcvr;
int rv = 0;
int rv = 0; /* Free by default */
unsigned char netfn;
unsigned char cmd;
unsigned char chan;
@ -4226,12 +4271,12 @@ static int handle_lan_get_msg_cmd(struct ipmi_smi *intf,
dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
msg->data_size, msg->data);
smi_send(intf, intf->handlers, msg, 0);
/*
* We used the message, so return the value that
* causes it to not be freed or queued.
*/
rv = -1;
if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
/*
* We used the message, so return the value that
* causes it to not be freed or queued.
*/
rv = -1;
} else if (!IS_ERR(recv_msg)) {
/* Extract the source address from the data. */
lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr;
@ -4824,8 +4869,7 @@ static void smi_work(struct work_struct *t)
* message delivery.
*/
restart:
if (!run_to_completion)
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
if (intf->curr_msg == NULL && !intf->in_shutdown) {
struct list_head *entry = NULL;
@ -4841,8 +4885,7 @@ static void smi_work(struct work_struct *t)
intf->curr_msg = newmsg;
}
}
if (!run_to_completion)
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
if (newmsg) {
cc = intf->handlers->sender(intf->send_info, newmsg);
@ -4850,8 +4893,11 @@ static void smi_work(struct work_struct *t)
if (newmsg->recv_msg)
deliver_err_response(intf,
newmsg->recv_msg, cc);
else
ipmi_free_smi_msg(newmsg);
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
intf->curr_msg = NULL;
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
ipmi_free_smi_msg(newmsg);
newmsg = NULL;
goto restart;
}
}
@ -4919,16 +4965,14 @@ void ipmi_smi_msg_received(struct ipmi_smi *intf,
spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock,
flags);
if (!run_to_completion)
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
/*
* We can get an asynchronous event or receive message in addition
* to commands we send.
*/
if (msg == intf->curr_msg)
intf->curr_msg = NULL;
if (!run_to_completion)
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
if (run_to_completion)
smi_work(&intf->smi_work);
@ -5041,7 +5085,12 @@ static void check_msg_timeout(struct ipmi_smi *intf, struct seq_table *ent,
ipmi_inc_stat(intf,
retransmitted_ipmb_commands);
smi_send(intf, intf->handlers, smi_msg, 0);
/* If this fails we'll retry later or timeout. */
if (smi_send(intf, intf->handlers, smi_msg, 0) != IPMI_CC_NO_ERROR) {
/* But fix the timeout. */
intf_start_seq_timer(intf, smi_msg->msgid);
ipmi_free_smi_msg(smi_msg);
}
} else
ipmi_free_smi_msg(smi_msg);

View File

@ -809,6 +809,12 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
*/
return_hosed_msg(smi_info, IPMI_BUS_ERR);
}
if (smi_info->waiting_msg != NULL) {
/* Also handle if there was a message waiting. */
smi_info->curr_msg = smi_info->waiting_msg;
smi_info->waiting_msg = NULL;
return_hosed_msg(smi_info, IPMI_BUS_ERR);
}
smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_HOSED);
goto out;
}
@ -918,9 +924,14 @@ static int sender(void *send_info, struct ipmi_smi_msg *msg)
{
struct smi_info *smi_info = send_info;
unsigned long flags;
int rv = IPMI_CC_NO_ERROR;
debug_timestamp(smi_info, "Enqueue");
/*
* Check here for run to completion mode. A check under lock is
* later.
*/
if (smi_info->si_state == SI_HOSED)
return IPMI_BUS_ERR;
@ -934,18 +945,15 @@ static int sender(void *send_info, struct ipmi_smi_msg *msg)
}
spin_lock_irqsave(&smi_info->si_lock, flags);
/*
* The following two lines don't need to be under the lock for
* the lock's sake, but they do need SMP memory barriers to
* avoid getting things out of order. We are already claiming
* the lock, anyway, so just do it under the lock to avoid the
* ordering problem.
*/
BUG_ON(smi_info->waiting_msg);
smi_info->waiting_msg = msg;
check_start_timer_thread(smi_info);
if (smi_info->si_state == SI_HOSED) {
rv = IPMI_BUS_ERR;
} else {
BUG_ON(smi_info->waiting_msg);
smi_info->waiting_msg = msg;
check_start_timer_thread(smi_info);
}
spin_unlock_irqrestore(&smi_info->si_lock, flags);
return IPMI_CC_NO_ERROR;
return rv;
}
static void set_run_to_completion(void *send_info, bool i_run_to_completion)
@ -1113,7 +1121,9 @@ static void smi_timeout(struct timer_list *t)
* SI_USEC_PER_JIFFY);
smi_result = smi_event_handler(smi_info, time_diff);
if ((smi_info->io.irq) && (!smi_info->interrupt_disabled)) {
if (smi_info->si_state == SI_HOSED) {
timeout = jiffies + SI_TIMEOUT_HOSED;
} else if ((smi_info->io.irq) && (!smi_info->interrupt_disabled)) {
/* Running with interrupts, only do long timeouts. */
timeout = jiffies + SI_TIMEOUT_JIFFIES;
smi_inc_stat(smi_info, long_timeouts);
@ -2226,7 +2236,8 @@ static void wait_msg_processed(struct smi_info *smi_info)
unsigned long jiffies_now;
long time_diff;
while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
while (smi_info->si_state != SI_HOSED &&
(smi_info->curr_msg || (smi_info->si_state != SI_NORMAL))) {
jiffies_now = jiffies;
time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
* SI_USEC_PER_JIFFY);

View File

@ -168,7 +168,7 @@ static void ipmi_ls2k_remove(struct platform_device *pdev)
ipmi_si_remove_by_dev(&pdev->dev);
}
struct platform_driver ipmi_ls2k_platform_driver = {
static struct platform_driver ipmi_ls2k_platform_driver = {
.driver = {
.name = "ls2k-ipmi-si",
},

View File

@ -96,8 +96,7 @@ static ATOMIC_NOTIFIER_HEAD(random_ready_notifier);
/* Control how we warn userspace. */
static struct ratelimit_state urandom_warning =
RATELIMIT_STATE_INIT_FLAGS("urandom_warning", HZ, 3, RATELIMIT_MSG_ON_RELEASE);
static int ratelimit_disable __read_mostly =
IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM);
static int ratelimit_disable __read_mostly = 0;
module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
@ -168,12 +167,6 @@ int __cold execute_with_initialized_rng(struct notifier_block *nb)
return ret;
}
#define warn_unseeded_randomness() \
if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \
printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \
__func__, (void *)_RET_IP_, crng_init)
/*********************************************************************
*
* Fast key erasure RNG, the "crng".
@ -434,7 +427,6 @@ static void _get_random_bytes(void *buf, size_t len)
*/
void get_random_bytes(void *buf, size_t len)
{
warn_unseeded_randomness();
_get_random_bytes(buf, len);
}
EXPORT_SYMBOL(get_random_bytes);
@ -523,8 +515,6 @@ type get_random_ ##type(void) \
struct batch_ ##type *batch; \
unsigned long next_gen; \
\
warn_unseeded_randomness(); \
\
if (!crng_ready()) { \
_get_random_bytes(&ret, sizeof(ret)); \
return ret; \

View File

@ -346,7 +346,29 @@ static struct platform_driver imx8qxp_clk_driver = {
},
.probe = imx8qxp_clk_probe,
};
module_platform_driver(imx8qxp_clk_driver);
static int __init imx8qxp_clk_init(void)
{
int ret;
ret = platform_driver_register(&imx8qxp_clk_driver);
if (ret)
return ret;
ret = imx_clk_scu_module_init();
if (ret)
platform_driver_unregister(&imx8qxp_clk_driver);
return ret;
}
module_init(imx8qxp_clk_init);
static void __exit imx8qxp_clk_exit(void)
{
imx_clk_scu_module_exit();
platform_driver_unregister(&imx8qxp_clk_driver);
}
module_exit(imx8qxp_clk_exit);
MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>");
MODULE_DESCRIPTION("NXP i.MX8QXP clock driver");

View File

@ -191,6 +191,16 @@ static bool imx_scu_clk_is_valid(u32 rsrc_id)
return p != NULL;
}
int __init imx_clk_scu_module_init(void)
{
return platform_driver_register(&imx_clk_scu_driver);
}
void __exit imx_clk_scu_module_exit(void)
{
return platform_driver_unregister(&imx_clk_scu_driver);
}
int imx_clk_scu_init(struct device_node *np,
const struct imx_clk_scu_rsrc_table *data)
{
@ -215,7 +225,7 @@ int imx_clk_scu_init(struct device_node *np,
rsrc_table = data;
}
return platform_driver_register(&imx_clk_scu_driver);
return 0;
}
/*

View File

@ -25,6 +25,8 @@ extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8dxl;
extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp;
extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm;
int __init imx_clk_scu_module_init(void);
void __exit imx_clk_scu_module_exit(void);
int imx_clk_scu_init(struct device_node *np,
const struct imx_clk_scu_rsrc_table *data);
struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,

View File

@ -1476,13 +1476,13 @@ static void __intel_pstate_update_max_freq(struct cpufreq_policy *policy,
refresh_frequency_limits(policy);
}
static bool intel_pstate_update_max_freq(struct cpudata *cpudata)
static bool intel_pstate_update_max_freq(int cpu)
{
struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu);
if (!policy)
return false;
__intel_pstate_update_max_freq(policy, cpudata);
__intel_pstate_update_max_freq(policy, all_cpu_data[cpu]);
return true;
}
@ -1501,7 +1501,7 @@ static void intel_pstate_update_limits_for_all(void)
int cpu;
for_each_possible_cpu(cpu)
intel_pstate_update_max_freq(all_cpu_data[cpu]);
intel_pstate_update_max_freq(cpu);
mutex_lock(&hybrid_capacity_lock);
@ -1647,8 +1647,8 @@ static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b,
static void update_cpu_qos_request(int cpu, enum freq_qos_req_type type)
{
struct cpudata *cpudata = all_cpu_data[cpu];
unsigned int freq = cpudata->pstate.turbo_freq;
struct freq_qos_request *req;
unsigned int freq;
struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu);
if (!policy)
@ -1661,6 +1661,8 @@ static void update_cpu_qos_request(int cpu, enum freq_qos_req_type type)
if (hwp_active)
intel_pstate_get_hwp_cap(cpudata);
freq = cpudata->pstate.turbo_freq;
if (type == FREQ_QOS_MIN) {
freq = DIV_ROUND_UP(freq * global.min_perf_pct, 100);
} else {
@ -1908,7 +1910,7 @@ static void intel_pstate_notify_work(struct work_struct *work)
struct cpudata *cpudata =
container_of(to_delayed_work(work), struct cpudata, hwp_notify_work);
if (intel_pstate_update_max_freq(cpudata)) {
if (intel_pstate_update_max_freq(cpudata->cpu)) {
/*
* The driver will not be unregistered while this function is
* running, so update the capacity without acquiring the driver

View File

@ -152,6 +152,24 @@ int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c);
int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
struct access_coordinate *c);
static inline struct device *port_to_host(struct cxl_port *port)
{
struct cxl_port *parent = is_cxl_root(port) ? NULL :
to_cxl_port(port->dev.parent);
/*
* The host of CXL root port and the first level of ports is
* the platform firmware device, the host of all other ports
* is their parent port.
*/
if (!parent)
return port->uport_dev;
else if (is_cxl_root(parent))
return parent->uport_dev;
else
return &parent->dev;
}
static inline struct device *dport_to_host(struct cxl_dport *dport)
{
struct cxl_port *port = dport->port;

View File

@ -904,7 +904,7 @@ static void cxl_decoder_reset(struct cxl_decoder *cxld)
if ((cxld->flags & CXL_DECODER_F_ENABLE) == 0)
return;
if (test_bit(CXL_DECODER_F_LOCK, &cxld->flags))
if (cxld->flags & CXL_DECODER_F_LOCK)
return;
if (port->commit_end == id)

View File

@ -311,6 +311,7 @@ static bool cxl_mem_raw_command_allowed(u16 opcode)
* cxl_payload_from_user_allowed() - Check contents of in_payload.
* @opcode: The mailbox command opcode.
* @payload_in: Pointer to the input payload passed in from user space.
* @in_size: Size of @payload_in in bytes.
*
* Return:
* * true - payload_in passes check for @opcode.
@ -325,12 +326,15 @@ static bool cxl_mem_raw_command_allowed(u16 opcode)
*
* The specific checks are determined by the opcode.
*/
static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in)
static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in,
size_t in_size)
{
switch (opcode) {
case CXL_MBOX_OP_SET_PARTITION_INFO: {
struct cxl_mbox_set_partition_info *pi = payload_in;
if (in_size < sizeof(*pi))
return false;
if (pi->flags & CXL_SET_PARTITION_IMMEDIATE_FLAG)
return false;
break;
@ -338,6 +342,8 @@ static bool cxl_payload_from_user_allowed(u16 opcode, void *payload_in)
case CXL_MBOX_OP_CLEAR_LOG: {
const uuid_t *uuid = (uuid_t *)payload_in;
if (in_size < sizeof(uuid_t))
return false;
/*
* Restrict the Clear log action to only apply to
* Vendor debug logs.
@ -365,7 +371,8 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox_cmd,
if (IS_ERR(mbox_cmd->payload_in))
return PTR_ERR(mbox_cmd->payload_in);
if (!cxl_payload_from_user_allowed(opcode, mbox_cmd->payload_in)) {
if (!cxl_payload_from_user_allowed(opcode, mbox_cmd->payload_in,
in_size)) {
dev_dbg(cxl_mbox->host, "%s: input payload not allowed\n",
cxl_mem_opcode_to_name(opcode));
kvfree(mbox_cmd->payload_in);

View File

@ -1089,10 +1089,8 @@ static int cxlmd_add(struct cxl_memdev *cxlmd, struct cxl_dev_state *cxlds)
DEFINE_FREE(put_cxlmd, struct cxl_memdev *,
if (!IS_ERR_OR_NULL(_T)) put_device(&_T->dev))
static struct cxl_memdev *cxl_memdev_autoremove(struct cxl_memdev *cxlmd)
static bool cxl_memdev_attach_failed(struct cxl_memdev *cxlmd)
{
int rc;
/*
* If @attach is provided fail if the driver is not attached upon
* return. Note that failure here could be the result of a race to
@ -1100,7 +1098,14 @@ static struct cxl_memdev *cxl_memdev_autoremove(struct cxl_memdev *cxlmd)
* succeeded and then cxl_mem unbound before the lock is acquired.
*/
guard(device)(&cxlmd->dev);
if (cxlmd->attach && !cxlmd->dev.driver) {
return (cxlmd->attach && !cxlmd->dev.driver);
}
static struct cxl_memdev *cxl_memdev_autoremove(struct cxl_memdev *cxlmd)
{
int rc;
if (cxl_memdev_attach_failed(cxlmd)) {
cxl_memdev_unregister(cxlmd);
return ERR_PTR(-ENXIO);
}

View File

@ -115,15 +115,17 @@ static void unregister_nvb(void *_cxl_nvb)
device_unregister(&cxl_nvb->dev);
}
/**
* devm_cxl_add_nvdimm_bridge() - add the root of a LIBNVDIMM topology
* @host: platform firmware root device
* @port: CXL port at the root of a CXL topology
*
* Return: bridge device that can host cxl_nvdimm objects
*/
struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
struct cxl_port *port)
static bool cxl_nvdimm_bridge_failed_attach(struct cxl_nvdimm_bridge *cxl_nvb)
{
struct device *dev = &cxl_nvb->dev;
guard(device)(dev);
/* If the device has no driver, then it failed to attach. */
return dev->driver == NULL;
}
struct cxl_nvdimm_bridge *__devm_cxl_add_nvdimm_bridge(struct device *host,
struct cxl_port *port)
{
struct cxl_nvdimm_bridge *cxl_nvb;
struct device *dev;
@ -145,6 +147,11 @@ struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
if (rc)
goto err;
if (cxl_nvdimm_bridge_failed_attach(cxl_nvb)) {
unregister_nvb(cxl_nvb);
return ERR_PTR(-ENODEV);
}
rc = devm_add_action_or_reset(host, unregister_nvb, cxl_nvb);
if (rc)
return ERR_PTR(rc);
@ -155,7 +162,7 @@ struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
put_device(dev);
return ERR_PTR(rc);
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_nvdimm_bridge, "CXL");
EXPORT_SYMBOL_FOR_MODULES(__devm_cxl_add_nvdimm_bridge, "cxl_pmem");
static void cxl_nvdimm_release(struct device *dev)
{
@ -255,6 +262,21 @@ int devm_cxl_add_nvdimm(struct device *host, struct cxl_port *port,
if (!cxl_nvb)
return -ENODEV;
/*
* Take the uport_dev lock to guard against race of nvdimm_bus object.
* cxl_acpi_probe() registers the nvdimm_bus and is done under the
* root port uport_dev lock.
*
* Take the cxl_nvb device lock to ensure that cxl_nvb driver is in a
* consistent state. And the driver registers nvdimm_bus.
*/
guard(device)(cxl_nvb->port->uport_dev);
guard(device)(&cxl_nvb->dev);
if (!cxl_nvb->nvdimm_bus) {
rc = -ENODEV;
goto err_alloc;
}
cxl_nvd = cxl_nvdimm_alloc(cxl_nvb, cxlmd);
if (IS_ERR(cxl_nvd)) {
rc = PTR_ERR(cxl_nvd);

View File

@ -615,22 +615,8 @@ struct cxl_port *parent_port_of(struct cxl_port *port)
static void unregister_port(void *_port)
{
struct cxl_port *port = _port;
struct cxl_port *parent = parent_port_of(port);
struct device *lock_dev;
/*
* CXL root port's and the first level of ports are unregistered
* under the platform firmware device lock, all other ports are
* unregistered while holding their parent port lock.
*/
if (!parent)
lock_dev = port->uport_dev;
else if (is_cxl_root(parent))
lock_dev = parent->uport_dev;
else
lock_dev = &parent->dev;
device_lock_assert(lock_dev);
device_lock_assert(port_to_host(port));
port->dead = true;
device_unregister(&port->dev);
}
@ -1427,20 +1413,11 @@ static struct device *grandparent(struct device *dev)
return NULL;
}
static struct device *endpoint_host(struct cxl_port *endpoint)
{
struct cxl_port *port = to_cxl_port(endpoint->dev.parent);
if (is_cxl_root(port))
return port->uport_dev;
return &port->dev;
}
static void delete_endpoint(void *data)
{
struct cxl_memdev *cxlmd = data;
struct cxl_port *endpoint = cxlmd->endpoint;
struct device *host = endpoint_host(endpoint);
struct device *host = port_to_host(endpoint);
scoped_guard(device, host) {
if (host->driver && !endpoint->dead) {
@ -1456,7 +1433,7 @@ static void delete_endpoint(void *data)
int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint)
{
struct device *host = endpoint_host(endpoint);
struct device *host = port_to_host(endpoint);
struct device *dev = &cxlmd->dev;
get_device(host);
@ -1790,7 +1767,16 @@ static struct cxl_dport *find_or_add_dport(struct cxl_port *port,
{
struct cxl_dport *dport;
device_lock_assert(&port->dev);
/*
* The port is already visible in CXL hierarchy, but it may still
* be in the process of binding to the CXL port driver at this point.
*
* port creation and driver binding are protected by the port's host
* lock, so acquire the host lock here to ensure the port has completed
* driver binding before proceeding with dport addition.
*/
guard(device)(port_to_host(port));
guard(device)(&port->dev);
dport = cxl_find_dport_by_dev(port, dport_dev);
if (!dport) {
dport = probe_dport(port, dport_dev);
@ -1857,13 +1843,11 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
* RP port enumerated by cxl_acpi without dport will
* have the dport added here.
*/
scoped_guard(device, &port->dev) {
dport = find_or_add_dport(port, dport_dev);
if (IS_ERR(dport)) {
if (PTR_ERR(dport) == -EAGAIN)
goto retry;
return PTR_ERR(dport);
}
dport = find_or_add_dport(port, dport_dev);
if (IS_ERR(dport)) {
if (PTR_ERR(dport) == -EAGAIN)
goto retry;
return PTR_ERR(dport);
}
rc = cxl_add_ep(dport, &cxlmd->dev);

View File

@ -1100,12 +1100,12 @@ static int cxl_rr_assign_decoder(struct cxl_port *port, struct cxl_region *cxlr,
static void cxl_region_setup_flags(struct cxl_region *cxlr,
struct cxl_decoder *cxld)
{
if (test_bit(CXL_DECODER_F_LOCK, &cxld->flags)) {
if (cxld->flags & CXL_DECODER_F_LOCK) {
set_bit(CXL_REGION_F_LOCK, &cxlr->flags);
clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
}
if (test_bit(CXL_DECODER_F_NORMALIZED_ADDRESSING, &cxld->flags))
if (cxld->flags & CXL_DECODER_F_NORMALIZED_ADDRESSING)
set_bit(CXL_REGION_F_NORMALIZED_ADDRESSING, &cxlr->flags);
}

View File

@ -574,11 +574,16 @@ struct cxl_nvdimm_bridge {
#define CXL_DEV_ID_LEN 19
enum {
CXL_NVD_F_INVALIDATED = 0,
};
struct cxl_nvdimm {
struct device dev;
struct cxl_memdev *cxlmd;
u8 dev_id[CXL_DEV_ID_LEN]; /* for nvdimm, string of 'serial' */
u64 dirty_shutdowns;
unsigned long flags;
};
struct cxl_pmem_region_mapping {
@ -920,6 +925,8 @@ void cxl_driver_unregister(struct cxl_driver *cxl_drv);
struct cxl_nvdimm_bridge *to_cxl_nvdimm_bridge(struct device *dev);
struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
struct cxl_port *port);
struct cxl_nvdimm_bridge *__devm_cxl_add_nvdimm_bridge(struct device *host,
struct cxl_port *port);
struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev);
bool is_cxl_nvdimm(struct device *dev);
int devm_cxl_add_nvdimm(struct device *host, struct cxl_port *port,

View File

@ -13,6 +13,20 @@
static __read_mostly DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX);
/**
* devm_cxl_add_nvdimm_bridge() - add the root of a LIBNVDIMM topology
* @host: platform firmware root device
* @port: CXL port at the root of a CXL topology
*
* Return: bridge device that can host cxl_nvdimm objects
*/
struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
struct cxl_port *port)
{
return __devm_cxl_add_nvdimm_bridge(host, port);
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_nvdimm_bridge, "CXL");
static void clear_exclusive(void *mds)
{
clear_exclusive_cxl_commands(mds, exclusive_cmds);
@ -129,6 +143,9 @@ static int cxl_nvdimm_probe(struct device *dev)
struct nvdimm *nvdimm;
int rc;
if (test_bit(CXL_NVD_F_INVALIDATED, &cxl_nvd->flags))
return -EBUSY;
set_exclusive_cxl_commands(mds, exclusive_cmds);
rc = devm_add_action_or_reset(dev, clear_exclusive, mds);
if (rc)
@ -309,8 +326,10 @@ static int detach_nvdimm(struct device *dev, void *data)
scoped_guard(device, dev) {
if (dev->driver) {
cxl_nvd = to_cxl_nvdimm(dev);
if (cxl_nvd->cxlmd && cxl_nvd->cxlmd->cxl_nvb == data)
if (cxl_nvd->cxlmd && cxl_nvd->cxlmd->cxl_nvb == data) {
release = true;
set_bit(CXL_NVD_F_INVALIDATED, &cxl_nvd->flags);
}
}
}
if (release)
@ -353,6 +372,7 @@ static struct cxl_driver cxl_nvdimm_bridge_driver = {
.probe = cxl_nvdimm_bridge_probe,
.id = CXL_DEVICE_NVDIMM_BRIDGE,
.drv = {
.probe_type = PROBE_FORCE_SYNCHRONOUS,
.suppress_bind_attrs = true,
},
};

View File

@ -981,11 +981,7 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
}
/* Add devres action to release DPLL related resources */
rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev);
if (rc)
goto error;
return 0;
return devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev);
error:
zl3073x_dev_dpll_fini(zldev);
@ -1026,6 +1022,7 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
"Unknown or non-match chip ID: 0x%0x\n",
id);
}
zldev->chip_id = id;
/* Read revision, firmware version and custom config version */
rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision);

View File

@ -35,6 +35,7 @@ struct zl3073x_dpll;
* @dev: pointer to device
* @regmap: regmap to access device registers
* @multiop_lock: to serialize multiple register operations
* @chip_id: chip ID read from hardware
* @ref: array of input references' invariants
* @out: array of outs' invariants
* @synth: array of synths' invariants
@ -48,6 +49,7 @@ struct zl3073x_dev {
struct device *dev;
struct regmap *regmap;
struct mutex multiop_lock;
u16 chip_id;
/* Invariants */
struct zl3073x_ref ref[ZL3073X_NUM_REFS];
@ -144,6 +146,32 @@ int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev,
int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel);
/**
* zl3073x_dev_is_ref_phase_comp_32bit - check ref phase comp register size
* @zldev: pointer to zl3073x device
*
* Some chip IDs have a 32-bit wide ref_phase_offset_comp register instead
* of the default 48-bit.
*
* Return: true if the register is 32-bit, false if 48-bit
*/
static inline bool
zl3073x_dev_is_ref_phase_comp_32bit(struct zl3073x_dev *zldev)
{
switch (zldev->chip_id) {
case 0x0E30:
case 0x0E93:
case 0x0E94:
case 0x0E95:
case 0x0E96:
case 0x0E97:
case 0x1F60:
return true;
default:
return false;
}
}
static inline bool
zl3073x_is_n_pin(u8 id)
{

View File

@ -475,8 +475,11 @@ zl3073x_dpll_input_pin_phase_adjust_get(const struct dpll_pin *dpll_pin,
ref_id = zl3073x_input_pin_ref_get(pin->id);
ref = zl3073x_ref_state_get(zldev, ref_id);
/* Perform sign extension for 48bit signed value */
phase_comp = sign_extend64(ref->phase_comp, 47);
/* Perform sign extension based on register width */
if (zl3073x_dev_is_ref_phase_comp_32bit(zldev))
phase_comp = sign_extend64(ref->phase_comp, 31);
else
phase_comp = sign_extend64(ref->phase_comp, 47);
/* Reverse two's complement negation applied during set and convert
* to 32bit signed int

View File

@ -121,8 +121,16 @@ int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index)
return rc;
/* Read phase compensation register */
rc = zl3073x_read_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP,
&ref->phase_comp);
if (zl3073x_dev_is_ref_phase_comp_32bit(zldev)) {
u32 val;
rc = zl3073x_read_u32(zldev, ZL_REG_REF_PHASE_OFFSET_COMP_32,
&val);
ref->phase_comp = val;
} else {
rc = zl3073x_read_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP,
&ref->phase_comp);
}
if (rc)
return rc;
@ -179,9 +187,16 @@ int zl3073x_ref_state_set(struct zl3073x_dev *zldev, u8 index,
if (!rc && dref->sync_ctrl != ref->sync_ctrl)
rc = zl3073x_write_u8(zldev, ZL_REG_REF_SYNC_CTRL,
ref->sync_ctrl);
if (!rc && dref->phase_comp != ref->phase_comp)
rc = zl3073x_write_u48(zldev, ZL_REG_REF_PHASE_OFFSET_COMP,
ref->phase_comp);
if (!rc && dref->phase_comp != ref->phase_comp) {
if (zl3073x_dev_is_ref_phase_comp_32bit(zldev))
rc = zl3073x_write_u32(zldev,
ZL_REG_REF_PHASE_OFFSET_COMP_32,
ref->phase_comp);
else
rc = zl3073x_write_u48(zldev,
ZL_REG_REF_PHASE_OFFSET_COMP,
ref->phase_comp);
}
if (rc)
return rc;

View File

@ -194,6 +194,7 @@
#define ZL_REF_CONFIG_DIFF_EN BIT(2)
#define ZL_REG_REF_PHASE_OFFSET_COMP ZL_REG(10, 0x28, 6)
#define ZL_REG_REF_PHASE_OFFSET_COMP_32 ZL_REG(10, 0x28, 4)
#define ZL_REG_REF_SYNC_CTRL ZL_REG(10, 0x2e, 1)
#define ZL_REF_SYNC_CTRL_MODE GENMASK(2, 0)

View File

@ -848,7 +848,7 @@ static int ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci,
{
struct device *dev = ohci->card.device;
unsigned int i;
struct page *pages[AR_BUFFERS + AR_WRAPAROUND_PAGES];
struct page *pages[AR_BUFFERS + AR_WRAPAROUND_PAGES] = { NULL };
dma_addr_t dma_addrs[AR_BUFFERS];
void *vaddr;
struct descriptor *d;

View File

@ -748,14 +748,14 @@ static bool gpio_shared_entry_is_really_shared(struct gpio_shared_entry *entry)
static void gpio_shared_free_exclusive(void)
{
struct gpio_shared_entry *entry, *epos;
struct gpio_shared_ref *ref, *rpos;
list_for_each_entry_safe(entry, epos, &gpio_shared_list, list) {
if (gpio_shared_entry_is_really_shared(entry))
continue;
gpio_shared_drop_ref(list_first_entry(&entry->refs,
struct gpio_shared_ref,
list));
list_for_each_entry_safe(ref, rpos, &entry->refs, list)
gpio_shared_drop_ref(ref);
gpio_shared_drop_entry(entry);
}
}

View File

@ -3267,8 +3267,12 @@ static int gpiochip_get(struct gpio_chip *gc, unsigned int offset)
/* Make sure this is called after checking for gc->get(). */
ret = gc->get(gc, offset);
if (ret > 1)
ret = -EBADE;
if (ret > 1) {
gpiochip_warn(gc,
"invalid return value from gc->get(): %d, consider fixing the driver\n",
ret);
ret = !!ret;
}
return ret;
}

View File

@ -641,6 +641,7 @@ static void aca_error_fini(struct aca_error *aerr)
aca_bank_error_remove(aerr, bank_error);
out_unlock:
mutex_unlock(&aerr->lock);
mutex_destroy(&aerr->lock);
}

View File

@ -7059,6 +7059,15 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
dev_info(adev->dev, "PCI error: slot reset callback!!\n");
memset(&reset_context, 0, sizeof(reset_context));
INIT_LIST_HEAD(&device_list);
hive = amdgpu_get_xgmi_hive(adev);
if (hive) {
mutex_lock(&hive->hive_lock);
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
list_add_tail(&tmp_adev->reset_list, &device_list);
} else {
list_add_tail(&adev->reset_list, &device_list);
}
if (adev->pcie_reset_ctx.swus)
link_dev = adev->pcie_reset_ctx.swus;
@ -7099,19 +7108,13 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
reset_context.reset_req_dev = adev;
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags);
INIT_LIST_HEAD(&device_list);
hive = amdgpu_get_xgmi_hive(adev);
if (hive) {
mutex_lock(&hive->hive_lock);
reset_context.hive = hive;
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) {
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
tmp_adev->pcie_reset_ctx.in_link_reset = true;
list_add_tail(&tmp_adev->reset_list, &device_list);
}
} else {
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
list_add_tail(&adev->reset_list, &device_list);
}
r = amdgpu_device_asic_reset(adev, &device_list, &reset_context);

View File

@ -332,13 +332,13 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
if (!context || !context->initialized) {
dev_err(adev->dev, "TA is not initialized\n");
ret = -EINVAL;
goto err_free_shared_buf;
goto free_shared_buf;
}
if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) {
dev_err(adev->dev, "Unsupported function to invoke TA\n");
ret = -EOPNOTSUPP;
goto err_free_shared_buf;
goto free_shared_buf;
}
context->session_id = ta_id;
@ -346,7 +346,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
mutex_lock(&psp->ras_context.mutex);
ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len);
if (ret)
goto err_free_shared_buf;
goto unlock;
ret = psp_fn_ta_invoke(psp, cmd_id);
if (ret || context->resp_status) {
@ -354,15 +354,17 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
ret, context->resp_status);
if (!ret) {
ret = -EINVAL;
goto err_free_shared_buf;
goto unlock;
}
}
if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len))
ret = -EFAULT;
err_free_shared_buf:
unlock:
mutex_unlock(&psp->ras_context.mutex);
free_shared_buf:
kfree(shared_buf);
return ret;

View File

@ -35,6 +35,8 @@
static const struct dma_fence_ops amdgpu_userq_fence_ops;
static struct kmem_cache *amdgpu_userq_fence_slab;
#define AMDGPU_USERQ_MAX_HANDLES (1U << 16)
int amdgpu_userq_fence_slab_init(void)
{
amdgpu_userq_fence_slab = kmem_cache_create("amdgpu_userq_fence",
@ -478,6 +480,11 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
if (!amdgpu_userq_enabled(dev))
return -ENOTSUPP;
if (args->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES ||
args->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES ||
args->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES)
return -EINVAL;
num_syncobj_handles = args->num_syncobj_handles;
syncobj_handles = memdup_user(u64_to_user_ptr(args->syncobj_handles),
size_mul(sizeof(u32), num_syncobj_handles));
@ -664,6 +671,11 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
if (!amdgpu_userq_enabled(dev))
return -ENOTSUPP;
if (wait_info->num_syncobj_handles > AMDGPU_USERQ_MAX_HANDLES ||
wait_info->num_bo_write_handles > AMDGPU_USERQ_MAX_HANDLES ||
wait_info->num_bo_read_handles > AMDGPU_USERQ_MAX_HANDLES)
return -EINVAL;
num_read_bo_handles = wait_info->num_bo_read_handles;
bo_handles_read = memdup_user(u64_to_user_ptr(wait_info->bo_read_handles),
size_mul(sizeof(u32), num_read_bo_handles));
@ -833,7 +845,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
dma_resv_for_each_fence(&resv_cursor, gobj_read[i]->resv,
DMA_RESV_USAGE_READ, fence) {
if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
goto free_fences;
}
@ -850,7 +862,7 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
dma_resv_for_each_fence(&resv_cursor, gobj_write[i]->resv,
DMA_RESV_USAGE_WRITE, fence) {
if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
goto free_fences;
}
@ -874,8 +886,9 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
goto free_fences;
dma_fence_unwrap_for_each(f, &iter, fence) {
if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
dma_fence_put(fence);
goto free_fences;
}
@ -898,8 +911,9 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
if (r)
goto free_fences;
if (WARN_ON_ONCE(num_fences >= wait_info->num_fences)) {
if (num_fences >= wait_info->num_fences) {
r = -EINVAL;
dma_fence_put(fence);
goto free_fences;
}

View File

@ -720,11 +720,6 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes)
mes_set_hw_res_pkt.enable_reg_active_poll = 1;
mes_set_hw_res_pkt.enable_level_process_quantum_check = 1;
mes_set_hw_res_pkt.oversubscription_timer = 50;
if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x7f)
mes_set_hw_res_pkt.enable_lr_compute_wa = 1;
else
dev_info_once(mes->adev->dev,
"MES FW version must be >= 0x7f to enable LR compute workaround.\n");
if (amdgpu_mes_log_enable) {
mes_set_hw_res_pkt.enable_mes_event_int_logging = 1;

View File

@ -779,11 +779,6 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes, int pipe)
mes_set_hw_res_pkt.use_different_vmid_compute = 1;
mes_set_hw_res_pkt.enable_reg_active_poll = 1;
mes_set_hw_res_pkt.enable_level_process_quantum_check = 1;
if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x82)
mes_set_hw_res_pkt.enable_lr_compute_wa = 1;
else
dev_info_once(adev->dev,
"MES FW version must be >= 0x82 to enable LR compute workaround.\n");
/*
* Keep oversubscribe timer for sdma . When we have unmapped doorbell

View File

@ -174,6 +174,10 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
fw_shared->sq.is_enabled = 1;
fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_SMU_DPM_INTERFACE_FLAG);
fw_shared->smu_dpm_interface.smu_interface_type = (adev->flags & AMD_IS_APU) ?
AMDGPU_VCN_SMU_DPM_INTERFACE_APU : AMDGPU_VCN_SMU_DPM_INTERFACE_DGPU;
if (amdgpu_vcnfw_log)
amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);

View File

@ -170,11 +170,11 @@ struct dc_stream_state *dc_create_stream_for_sink(
if (sink == NULL)
goto fail;
stream = kzalloc_obj(struct dc_stream_state);
stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC);
if (stream == NULL)
goto fail;
stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_KERNEL);
stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_ATOMIC);
if (stream->update_scratch == NULL)
goto fail;

View File

@ -1881,6 +1881,14 @@ static int samsung_dsim_register_te_irq(struct samsung_dsim *dsi, struct device
return 0;
}
static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi)
{
if (dsi->te_gpio) {
free_irq(gpiod_to_irq(dsi->te_gpio), dsi);
gpiod_put(dsi->te_gpio);
}
}
static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
@ -1961,7 +1969,7 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO)) {
ret = samsung_dsim_register_te_irq(dsi, &device->dev);
if (ret)
return ret;
goto err_remove_bridge;
}
// The next bridge can be used by host_ops->attach
@ -1982,15 +1990,12 @@ static int samsung_dsim_host_attach(struct mipi_dsi_host *host,
err_release_next_bridge:
drm_bridge_put(dsi->bridge.next_bridge);
dsi->bridge.next_bridge = NULL;
return ret;
}
static void samsung_dsim_unregister_te_irq(struct samsung_dsim *dsi)
{
if (dsi->te_gpio) {
free_irq(gpiod_to_irq(dsi->te_gpio), dsi);
gpiod_put(dsi->te_gpio);
}
if (!(device->mode_flags & MIPI_DSI_MODE_VIDEO))
samsung_dsim_unregister_te_irq(dsi);
err_remove_bridge:
drm_bridge_remove(&dsi->bridge);
return ret;
}
static int samsung_dsim_host_detach(struct mipi_dsi_host *host,

View File

@ -2049,7 +2049,9 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
bridge->ycbcr_420_allowed = true;
devm_drm_bridge_add(dev, bridge);
ret = devm_drm_bridge_add(dev, bridge);
if (ret)
return ERR_PTR(ret);
dp->aux.dev = dev;
dp->aux.drm_dev = encoder->dev;

View File

@ -1415,6 +1415,7 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
{
struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent);
struct device_node *np = pdata->dev->of_node;
const struct i2c_client *client = to_i2c_client(pdata->dev);
int ret;
pdata->next_bridge = devm_drm_of_get_bridge(&adev->dev, np, 1, 0);
@ -1433,8 +1434,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP;
if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) {
pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT |
DRM_BRIDGE_OP_HPD;
pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT;
if (client->irq)
pdata->bridge.ops |= DRM_BRIDGE_OP_HPD;
/*
* If comms were already enabled they would have been enabled
* with the wrong value of HPD_DISABLE. Update it now. Comms

View File

@ -930,7 +930,8 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
mutex_unlock(&client->modeset_mutex);
out:
kfree(crtcs);
modes_destroy(dev, modes, connector_count);
if (modes)
modes_destroy(dev, modes, connector_count);
kfree(modes);
kfree(offsets);
kfree(enabled);

View File

@ -1338,14 +1338,14 @@ bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
/**
* drm_gpusvm_range_pages_valid_unlocked() - GPU SVM range pages valid unlocked
* drm_gpusvm_pages_valid_unlocked() - GPU SVM pages valid unlocked
* @gpusvm: Pointer to the GPU SVM structure
* @range: Pointer to the GPU SVM range structure
* @svm_pages: Pointer to the GPU SVM pages structure
*
* This function determines if a GPU SVM range pages are valid. Expected be
* called without holding gpusvm->notifier_lock.
* This function determines if a GPU SVM pages are valid. Expected be called
* without holding gpusvm->notifier_lock.
*
* Return: True if GPU SVM range has valid pages, False otherwise
* Return: True if GPU SVM pages are valid, False otherwise
*/
static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_pages *svm_pages)

View File

@ -562,12 +562,7 @@ void intel_alpm_disable(struct intel_dp *intel_dp)
mutex_lock(&intel_dp->alpm.lock);
intel_de_rmw(display, ALPM_CTL(display, cpu_transcoder),
ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE |
ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
intel_de_rmw(display,
PORT_ALPM_CTL(cpu_transcoder),
PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE, 0);
drm_dbg_kms(display->drm, "Disabling ALPM\n");
mutex_unlock(&intel_dp->alpm.lock);

View File

@ -256,7 +256,9 @@ static int imx_pd_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, imxpd);
devm_drm_bridge_add(dev, &imxpd->bridge);
ret = devm_drm_bridge_add(dev, &imxpd->bridge);
if (ret)
return ret;
return component_add(dev, &imx_pd_ops);
}

View File

@ -92,7 +92,6 @@ static int logicvc_drm_config_parse(struct logicvc_drm *logicvc)
struct device *dev = drm_dev->dev;
struct device_node *of_node = dev->of_node;
struct logicvc_drm_config *config = &logicvc->config;
struct device_node *layers_node;
int ret;
logicvc_of_property_parse_bool(of_node, LOGICVC_OF_PROPERTY_DITHERING,
@ -128,7 +127,8 @@ static int logicvc_drm_config_parse(struct logicvc_drm *logicvc)
if (ret)
return ret;
layers_node = of_get_child_by_name(of_node, "layers");
struct device_node *layers_node __free(device_node) =
of_get_child_by_name(of_node, "layers");
if (!layers_node) {
drm_err(drm_dev, "Missing non-optional layers node\n");
return -EINVAL;

View File

@ -737,8 +737,8 @@ r535_gsp_acpi_caps(acpi_handle handle, CAPS_METHOD_DATA *caps)
if (!obj)
goto done;
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
WARN_ON(obj->buffer.length != 4))
if (obj->type != ACPI_TYPE_BUFFER ||
obj->buffer.length != 4)
goto done;
caps->status = 0;
@ -773,8 +773,8 @@ r535_gsp_acpi_jt(acpi_handle handle, JT_METHOD_DATA *jt)
if (!obj)
goto done;
if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) ||
WARN_ON(obj->buffer.length != 4))
if (obj->type != ACPI_TYPE_BUFFER ||
obj->buffer.length != 4)
goto done;
jt->status = 0;
@ -861,8 +861,8 @@ r535_gsp_acpi_dod(acpi_handle handle, DOD_METHOD_DATA *dod)
_DOD = output.pointer;
if (WARN_ON(_DOD->type != ACPI_TYPE_PACKAGE) ||
WARN_ON(_DOD->package.count > ARRAY_SIZE(dod->acpiIdList)))
if (_DOD->type != ACPI_TYPE_PACKAGE ||
_DOD->package.count > ARRAY_SIZE(dod->acpiIdList))
return;
for (int i = 0; i < _DOD->package.count; i++) {

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