Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Cross-merge networking fixes after downstream PR (net-7.1-rc7).

Silent conflicts:

net/wireless/nl80211.c
  cb9959ab5f ("wifi: cfg80211: enforce HE/EHT cap/oper consistency")
  a384ae9699 ("wifi: cfg80211: move AP HT/VHT/... operation to beacon info")
https://lore.kernel.org/aiGJDaHV4UlCexIQ@sirena.org.uk

Conflicts:

drivers/net/wireless/intel/iwlwifi/mld/ap.c
  a342c99cb7 ("wifi: iwlwifi: mld: honor BSS_CHANGED_BEACON_ENABLED")
  9bf1b409af ("wifi: iwlwifi: mld: send tx power constraints before link activation")
https://lore.kernel.org/ah2bfedhV45ZxMO8@sirena.org.uk

drivers/net/wireless/intel/iwlwifi/pcie/drv.c
  093305d801 ("wifi: iwlwifi: pcie: simplify the resume flow if fast resume is not used")
  e2323929a6 ("wifi: iwlwifi: pcie: add debug print for resume flow if powered off")
https://lore.kernel.org/ah2bfedhV45ZxMO8@sirena.org.uk

Adjacent changes:

drivers/net/ethernet/airoha/airoha_eth.c
  b38cae85d1 ("net: airoha: Fix use-after-free in metadata dst teardown")
  ec6c391bcc ("net: airoha: Introduce airoha_gdm_dev struct")

drivers/net/ethernet/microchip/lan743x_main.c
  8173d22b21 ("net: lan743x: permit VLAN-tagged packets up to configured MTU")
  e3c6508a46 ("net: lan743x: avoid netdev-based logging before netdev registration")

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2026-06-04 15:26:27 -07:00
312 changed files with 3345 additions and 1765 deletions

View File

@@ -786,24 +786,6 @@ Kernel parameters
cio_ignore= [S390]
See Documentation/arch/s390/common_io.rst for details.
clearcpuid=X[,X...] [X86]
Disable CPUID feature X for the kernel. See
arch/x86/include/asm/cpufeatures.h for the valid bit
numbers X. Note the Linux-specific bits are not necessarily
stable over kernel options, but the vendor-specific
ones should be.
X can also be a string as appearing in the flags: line
in /proc/cpuinfo which does not have the above
instability issue. However, not all features have names
in /proc/cpuinfo.
Note that using this option will taint your kernel.
Also note that user programs calling CPUID directly
or using the feature without checking anything
will still see it. This just prevents it from
being used by the kernel or shown in /proc/cpuinfo.
Also note the kernel might malfunction if you disable
some critical bits.
clk_ignore_unused
[CLK]
Prevents the clock framework from automatically gating

View File

@@ -187,6 +187,10 @@ to disable features using the feature number as defined in
Protection can be disabled using clearcpuid=514. The number 514 is calculated
from #define X86_FEATURE_UMIP (16*32 + 2).
DO NOT USE this cmdline option in production - it is meant to be used only as
a quick'n'dirty debugging aid to rule out a feature-enabling code is the
culprit. If you use it, it'll taint the kernel.
In addition, there exists a variety of custom command-line parameters that
disable specific features. The list of parameters includes, but is not limited
to, nofsgsbase, nosgx, noxsave, etc. 5-level paging can also be disabled using

View File

@@ -30,6 +30,16 @@ properties:
maxItems: 1
clocks:
minItems: 1
maxItems: 2
clock-names:
minItems: 1
items:
- const: core
- const: iface
power-domains:
maxItems: 1
operating-points-v2: true
@@ -44,6 +54,25 @@ required:
additionalProperties: false
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,eliza-inline-crypto-engine
- qcom,milos-inline-crypto-engine
then:
required:
- power-domains
- clock-names
properties:
clocks:
minItems: 2
clock-names:
minItems: 2
examples:
- |
#include <dt-bindings/clock/qcom,sm8550-gcc.h>
@@ -52,7 +81,11 @@ examples:
compatible = "qcom,sm8550-inline-crypto-engine",
"qcom,inline-crypto-engine";
reg = <0x01d88000 0x8000>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>,
<&gcc GCC_UFS_PHY_AHB_CLK>;
clock-names = "core",
"iface";
power-domains = <&gcc UFS_PHY_GDSC>;
operating-points-v2 = <&ice_opp_table>;

View File

@@ -84,7 +84,8 @@ properties:
This reference is provided for background information only.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- minItems: 4
items:
- description: Phandle to HSP(High-Speed Peripheral) device
- description: Offset of phy control register for internal
or external clock selection

View File

@@ -25,6 +25,7 @@ properties:
- items:
- enum:
- qcom,ipq5018-snand
- qcom,ipq5210-snand
- qcom,ipq5332-snand
- qcom,ipq5424-snand
- const: qcom,ipq9574-snand

View File

@@ -41,12 +41,13 @@ properties:
- const: usb_en
resets:
maxItems: 2
maxItems: 3
reset-names:
items:
- const: vaux
- const: usb_rst
- const: usb_phy
eswin,hsp-sp-csr:
description:
@@ -85,8 +86,8 @@ examples:
interrupt-parent = <&plic>;
interrupts = <85>;
interrupt-names = "peripheral";
resets = <&reset 84>, <&hspcrg 2>;
reset-names = "vaux", "usb_rst";
resets = <&reset 84>, <&hspcrg 2>, <&hspcrg 4>;
reset-names = "vaux", "usb_rst", "usb_phy";
dr_mode = "peripheral";
maximum-speed = "high-speed";
phy_type = "utmi";

View File

@@ -81,9 +81,7 @@ properties:
const: usb2-phy
usb-phy:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: Phandle for the PHY device.
deprecated: true
maxItems: 1
ctrl-module:
$ref: /schemas/types.yaml#/definitions/phandle
@@ -96,6 +94,9 @@ required:
- interrupts
- interrupt-names
allOf:
- $ref: usb-hcd.yaml#
unevaluatedProperties: false
examples:

View File

@@ -6543,7 +6543,7 @@ F: include/linux/blk-cgroup.h
CONTROL GROUP - CPUSET
M: Waiman Long <longman@redhat.com>
R: Chen Ridong <chenridong@huaweicloud.com>
R: Ridong Chen <ridong.chen@linux.dev>
L: cgroups@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git

View File

@@ -2,7 +2,7 @@
VERSION = 7
PATCHLEVEL = 1
SUBLEVEL = 0
EXTRAVERSION = -rc5
EXTRAVERSION = -rc6
NAME = Baby Opossum Posse
# *DOCUMENTATION*

View File

@@ -146,7 +146,7 @@ flash@30000000 {
partitions {
compatible = "redboot-fis";
/* Eraseblock at 0xfe0000 */
fis-index-block = <0x1fc>;
fis-index-block = <0x7f>;
};
};

View File

@@ -134,7 +134,7 @@ flash@30000000 {
partitions {
compatible = "redboot-fis";
/* Eraseblock at 0xfe0000 */
fis-index-block = <0x1fc>;
fis-index-block = <0x7f>;
};
};

View File

@@ -990,9 +990,9 @@ gmac: ethernet@f802c000 {
<62 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 3 */
<63 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 4 */
<64 IRQ_TYPE_LEVEL_HIGH 3>; /* Queue 5 */
clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>, <&pmc PMC_TYPE_GCK 67>;
clock-names = "hclk", "pclk", "tx_clk", "tsu_clk";
assigned-clocks = <&pmc PMC_TYPE_GCK 67>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>;
clock-names = "hclk", "pclk", "tsu_clk";
assigned-clocks = <&pmc PMC_TYPE_GCK 24>;
assigned-clock-rates = <266666666>;
status = "disabled";
};

View File

@@ -78,6 +78,7 @@ static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
}
socfpga_scu_base_addr = of_iomap(np, 0);
of_node_put(np);
if (!socfpga_scu_base_addr)
return;
scu_enable(socfpga_scu_base_addr);

View File

@@ -843,7 +843,11 @@ ice: crypto@1d88000 {
"qcom,inline-crypto-engine";
reg = <0x0 0x01d88000 0x0 0x18000>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>,
<&gcc GCC_UFS_PHY_AHB_CLK>;
clock-names = "core",
"iface";
power-domains = <&gcc GCC_UFS_PHY_GDSC>;
};
tcsr_mutex: hwlock@1f40000 {

View File

@@ -2314,11 +2314,9 @@ usb_mp_qmpphy0: phy@fa3000 {
clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>,
<&tcsr TCSR_USB3_0_CLKREF_EN>,
<&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_MP_PHY_PIPE_0_CLK>;
clock-names = "aux",
"clkref",
"ref",
"com_aux",
"pipe";
@@ -2343,11 +2341,9 @@ usb_mp_qmpphy1: phy@fa5000 {
clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>,
<&tcsr TCSR_USB3_1_CLKREF_EN>,
<&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_MP_PHY_PIPE_1_CLK>;
clock-names = "aux",
"clkref",
"ref",
"com_aux",
"pipe";
@@ -2482,15 +2478,13 @@ usb_1_qmpphy: phy@fde000 {
reg = <0x0 0x00fde000 0x0 0x8000>;
clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>,
<&rpmhcc RPMH_CXO_CLK>,
<&tcsr TCSR_USB4_1_CLKREF_EN>,
<&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_SEC_PHY_PIPE_CLK>,
<&tcsr TCSR_USB4_1_CLKREF_EN>;
<&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
clock-names = "aux",
"ref",
"com_aux",
"usb3_pipe",
"clkref";
"usb3_pipe";
power-domains = <&gcc GCC_USB_1_PHY_GDSC>;
@@ -3750,15 +3744,13 @@ usb_2_qmpphy: phy@88e1000 {
reg = <0x0 0x088e1000 0x0 0x8000>;
clocks = <&gcc GCC_USB3_TERT_PHY_AUX_CLK>,
<&rpmhcc RPMH_CXO_CLK>,
<&tcsr TCSR_USB4_2_CLKREF_EN>,
<&gcc GCC_USB3_TERT_PHY_COM_AUX_CLK>,
<&gcc GCC_USB3_TERT_PHY_PIPE_CLK>,
<&tcsr TCSR_USB4_2_CLKREF_EN>;
<&gcc GCC_USB3_TERT_PHY_PIPE_CLK>;
clock-names = "aux",
"ref",
"com_aux",
"usb3_pipe",
"clkref";
"usb3_pipe";
power-domains = <&gcc GCC_USB_2_PHY_GDSC>;

View File

@@ -1275,7 +1275,11 @@ ice: crypto@1d88000 {
"qcom,inline-crypto-engine";
reg = <0x0 0x01d88000 0x0 0x18000>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>,
<&gcc GCC_UFS_PHY_AHB_CLK>;
clock-names = "core",
"iface";
power-domains = <&gcc UFS_PHY_GDSC>;
};
tcsr_mutex: hwlock@1f40000 {

View File

@@ -982,12 +982,6 @@ &i2c8 {
status = "okay";
};
&i2c20 {
clock-frequency = <400000>;
status = "okay";
};
&lpass_tlmm {
spkr_01_sd_n_active: spkr-01-sd-n-active-state {
pins = "gpio12";
@@ -1308,6 +1302,7 @@ right_tweeter: speaker@0,1 {
&tlmm {
gpio-reserved-ranges = <44 4>, /* SPI11 (TPM) */
<76 4>, /* SPI19 (TZ Protected) */
<80 2>, /* I2C20 (Battery SMBus) */
<238 1>; /* UFS Reset */
cam_rgb_default: cam-rgb-default-state {

View File

@@ -260,6 +260,7 @@ CONFIG_PCI_ENDPOINT=y
CONFIG_PCI_ENDPOINT_CONFIGFS=y
CONFIG_PCI_EPF_TEST=m
CONFIG_PCI_PWRCTRL_GENERIC=m
CONFIG_POWER_SEQUENCING_PCIE_M2=m
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER=y

View File

@@ -10,6 +10,14 @@
#include <linux/mc146818rtc.h>
#include <linux/platform_device.h>
#include <asm/bootinfo.h>
#include <asm/dec/interrupts.h>
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/kn01.h>
#include <asm/dec/kn02.h>
#include <asm/dec/system.h>
static struct resource dec_rtc_resources[] = {
{
.name = "rtc",
@@ -30,11 +38,110 @@ static struct platform_device dec_rtc_device = {
.num_resources = ARRAY_SIZE(dec_rtc_resources),
};
static struct resource dec_dz_resources[] = {
{ .name = "dz", .flags = IORESOURCE_MEM, },
{ .name = "dz", .flags = IORESOURCE_IRQ, },
};
static struct platform_device dec_dz_device = {
.name = "dz",
.id = PLATFORM_DEVID_NONE,
.resource = dec_dz_resources,
.num_resources = ARRAY_SIZE(dec_dz_resources),
};
static struct platform_device *dec_dz_devices[] __initdata = {
&dec_dz_device,
};
static struct resource dec_zs_resources[][2] = {
{
{ .name = "scc0", .flags = IORESOURCE_MEM, },
{ .name = "scc0", .flags = IORESOURCE_IRQ, },
},
{
{ .name = "scc1", .flags = IORESOURCE_MEM, },
{ .name = "scc1", .flags = IORESOURCE_IRQ, },
},
};
static struct platform_device dec_zs_device[] = {
{
.name = "zs",
.id = 0,
.resource = dec_zs_resources[0],
.num_resources = ARRAY_SIZE(dec_zs_resources[0]),
},
{
.name = "zs",
.id = 1,
.resource = dec_zs_resources[1],
.num_resources = ARRAY_SIZE(dec_zs_resources[1]),
},
};
static int __init dec_add_devices(void)
{
struct platform_device *dec_zs_devices[ARRAY_SIZE(dec_zs_device)];
int ret1, ret2, ret3;
int num_dz, num_zs;
int irq, i;
dec_rtc_resources[0].start = RTC_PORT(0);
dec_rtc_resources[0].end = RTC_PORT(0) + dec_kn_slot_size - 1;
return platform_device_register(&dec_rtc_device);
i = 0;
irq = dec_interrupt[DEC_IRQ_DZ11];
if (IS_ENABLED(CONFIG_32BIT) && irq >= 0) {
resource_size_t base;
switch (mips_machtype) {
case MACH_DS23100:
case MACH_DS5100:
base = dec_kn_slot_base + KN01_DZ11;
break;
default:
base = dec_kn_slot_base + KN02_DZ11;
break;
}
dec_dz_device.resource[0].start = base;
dec_dz_device.resource[0].end = base + dec_kn_slot_size - 1;
dec_dz_device.resource[1].start = irq;
dec_dz_device.resource[1].end = irq;
i++;
}
num_dz = i;
i = 0;
irq = dec_interrupt[DEC_IRQ_SCC0];
if (irq >= 0) {
resource_size_t base = dec_kn_slot_base + IOASIC_SCC0;
dec_zs_device[i].resource[0].start = base;
dec_zs_device[i].resource[0].end = base + dec_kn_slot_size - 1;
dec_zs_device[i].resource[1].start = irq;
dec_zs_device[i].resource[1].end = irq;
dec_zs_devices[i] = &dec_zs_device[i];
i++;
}
irq = dec_interrupt[DEC_IRQ_SCC1];
if (irq >= 0) {
resource_size_t base = dec_kn_slot_base + IOASIC_SCC1;
dec_zs_device[i].resource[0].start = base;
dec_zs_device[i].resource[0].end = base + dec_kn_slot_size - 1;
dec_zs_device[i].resource[1].start = irq;
dec_zs_device[i].resource[1].end = irq;
dec_zs_devices[i] = &dec_zs_device[i];
i++;
}
num_zs = i;
ret1 = platform_device_register(&dec_rtc_device);
ret2 = IS_ENABLED(CONFIG_32BIT) ?
platform_add_devices(dec_dz_devices, num_dz) : 0;
ret3 = platform_add_devices(dec_zs_devices, num_zs);
return ret1 ? ret1 : ret2 ? ret2 : ret3;
}
device_initcall(dec_add_devices);

View File

@@ -56,6 +56,10 @@ CONFIG_EXPOLINE_AUTO=y
CONFIG_CHSC_SCH=y
CONFIG_VFIO_CCW=m
CONFIG_VFIO_AP=m
CONFIG_VFIO_DEVICE_CDEV=y
CONFIG_IOMMUFD_DRIVER=y
CONFIG_IOMMUFD_DRIVER_CORE=y
CONFIG_IOMMUFD=y
CONFIG_CMM=m
CONFIG_APPLDATA_BASE=y
CONFIG_S390_HYPFS_FS=y

View File

@@ -54,6 +54,10 @@ CONFIG_EXPOLINE_AUTO=y
CONFIG_CHSC_SCH=y
CONFIG_VFIO_CCW=m
CONFIG_VFIO_AP=m
CONFIG_VFIO_DEVICE_CDEV=y
CONFIG_IOMMUFD_DRIVER=y
CONFIG_IOMMUFD_DRIVER_CORE=y
CONFIG_IOMMUFD=y
CONFIG_CMM=m
CONFIG_APPLDATA_BASE=y
CONFIG_S390_HYPFS_FS=y

View File

@@ -12,12 +12,11 @@
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
#ifdef CONFIG_DEBUG_BUGVERBOSE
#define __BUG_ENTRY_VERBOSE(format, file, line) \
" .long " format " - . # bug_entry::format\n" \
#define __BUG_ENTRY_VERBOSE(file, line) \
" .long " file " - . # bug_entry::file\n" \
" .short " line " # bug_entry::line\n"
#else
#define __BUG_ENTRY_VERBOSE(format, file, line)
#define __BUG_ENTRY_VERBOSE(file, line)
#endif
#ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
@@ -28,9 +27,10 @@
#define __BUG_ENTRY(format, file, line, flags, size) \
" .section __bug_table,\"aw\"\n" \
"1: .long 0b - . # bug_entry::bug_addr\n" \
__BUG_ENTRY_VERBOSE(format, file, line) \
" .short "flags" # bug_entry::flags\n" \
"1: .long 0b - . # bug_entry::bug_addr\n"\
" .long " format " - . # bug_entry::format\n" \
__BUG_ENTRY_VERBOSE(file, line) \
" .short "flags" # bug_entry::flags\n" \
" .org 1b+"size"\n" \
" .previous"

View File

@@ -7,4 +7,6 @@
#define __ALIGN .balign CONFIG_FUNCTION_ALIGNMENT, 0x07
#define __ALIGN_STR __stringify(__ALIGN)
#define _THIS_IP_ ({ unsigned long __ip; asm volatile("larl %0, ." : "=d" (__ip)); __ip; })
#endif

View File

@@ -55,7 +55,7 @@ noinstr void x86_entry_from_kvm(unsigned int event_type, unsigned int vector)
* The FRED NMI context is significantly different and will not work
* right (specifically FRED fixed the NMI recursion issue).
*/
idt_entry_from_kvm(vector);
idt_do_nmi_irqoff();
}
EXPORT_SYMBOL_FOR_KVM(x86_entry_from_kvm);
#endif

View File

@@ -109,11 +109,13 @@ EXPORT_SYMBOL(__ref_stack_chk_guard);
RET
.endm
#ifndef CONFIG_X86_64
.pushsection .text, "ax"
SYM_FUNC_START(idt_do_interrupt_irqoff)
IDT_DO_EVENT_IRQOFF CALL_NOSPEC _ASM_ARG1
SYM_FUNC_END(idt_do_interrupt_irqoff)
.popsection
#endif
.pushsection .noinstr.text, "ax"
SYM_FUNC_START(idt_do_nmi_irqoff)

View File

@@ -733,6 +733,7 @@ bool xen_set_default_idle(void);
#endif
void __noreturn stop_this_cpu(void *dummy);
extern bool x86_hypervisor_present;
void microcode_check(struct cpuinfo_x86 *prev_info);
void store_cpu_caps(struct cpuinfo_x86 *info);

View File

@@ -322,7 +322,7 @@ static u32 get_patch_level(void)
{
u32 rev, dummy __always_unused;
if (IS_ENABLED(CONFIG_MICROCODE_DBG) && hypervisor_present) {
if (IS_ENABLED(CONFIG_MICROCODE_DBG) && x86_hypervisor_present) {
int cpu = smp_processor_id();
if (!microcode_rev[cpu]) {
@@ -714,7 +714,7 @@ static bool __apply_microcode_amd(struct microcode_amd *mc, u32 *cur_rev,
invlpg(p_addr_end);
}
if (IS_ENABLED(CONFIG_MICROCODE_DBG) && hypervisor_present)
if (IS_ENABLED(CONFIG_MICROCODE_DBG) && x86_hypervisor_present)
microcode_rev[smp_processor_id()] = mc->hdr.patch_id;
/* verify patch application was successful */

View File

@@ -57,7 +57,7 @@ bool force_minrev = IS_ENABLED(CONFIG_MICROCODE_LATE_FORCE_MINREV);
u32 base_rev;
u32 microcode_rev[NR_CPUS] = {};
bool hypervisor_present;
bool __ro_after_init x86_hypervisor_present;
/*
* Synchronization.
@@ -118,14 +118,9 @@ bool __init microcode_loader_disabled(void)
/*
* Disable when:
*
* 1) The CPU does not support CPUID.
*/
if (!cpuid_feature()) {
dis_ucode_ldr = true;
return dis_ucode_ldr;
}
/*
* 1) The CPU does not support CPUID, detected below in
* load_ucode_bsp().
*
* 2) Bit 31 in CPUID[1]:ECX is clear
* The bit is reserved for hypervisor use. This is still not
* completely accurate as XEN PV guests don't see that CPUID bit
@@ -135,9 +130,7 @@ bool __init microcode_loader_disabled(void)
* 3) Certain AMD patch levels are not allowed to be
* overwritten.
*/
hypervisor_present = native_cpuid_ecx(1) & BIT(31);
if ((hypervisor_present && !IS_ENABLED(CONFIG_MICROCODE_DBG)) ||
if ((x86_hypervisor_present && !IS_ENABLED(CONFIG_MICROCODE_DBG)) ||
amd_check_current_patch_level())
dis_ucode_ldr = true;
@@ -179,6 +172,11 @@ void __init load_ucode_bsp(void)
early_parse_cmdline();
if (!cpuid_feature())
dis_ucode_ldr = true;
else
x86_hypervisor_present = native_cpuid_ecx(1) & BIT(31);
if (microcode_loader_disabled())
return;

View File

@@ -138,6 +138,9 @@ u32 intel_get_platform_id(void)
{
unsigned int val[2];
if (x86_hypervisor_present)
return 0;
/*
* This can be called early. Use CPUID directly instead of
* relying on cpuinfo_x86 which may not be fully initialized.

View File

@@ -48,7 +48,6 @@ extern struct early_load_data early_data;
extern struct ucode_cpu_info ucode_cpu_info[];
extern u32 microcode_rev[NR_CPUS];
extern u32 base_rev;
extern bool hypervisor_present;
struct cpio_data find_microcode_in_initrd(const char *path);

View File

@@ -27,14 +27,19 @@
static inline bool check_xstate_in_sigframe(struct fxregs_state __user *fxbuf,
struct _fpx_sw_bytes *fx_sw)
{
int min_xstate_size = sizeof(struct fxregs_state) +
sizeof(struct xstate_header);
void __user *fpstate = fxbuf;
unsigned int magic2;
if (__copy_from_user(fx_sw, &fxbuf->sw_reserved[0], sizeof(*fx_sw)))
return false;
/* Check for the first magic field */
if (fx_sw->magic1 != FP_XSTATE_MAGIC1)
/* Check for the first magic field and other error scenarios. */
if (fx_sw->magic1 != FP_XSTATE_MAGIC1 ||
fx_sw->xstate_size < min_xstate_size ||
fx_sw->xstate_size > x86_task_fpu(current)->fpstate->user_size ||
fx_sw->xstate_size > fx_sw->extended_size)
goto setfx;
/*
@@ -43,7 +48,7 @@ static inline bool check_xstate_in_sigframe(struct fxregs_state __user *fxbuf,
* fpstate layout with out copying the extended state information
* in the memory layout.
*/
if (__get_user(magic2, (__u32 __user *)(fpstate + x86_task_fpu(current)->fpstate->user_size)))
if (__get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size)))
return false;
if (likely(magic2 == FP_XSTATE_MAGIC2))

View File

@@ -375,6 +375,13 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
goto fail;
}
/*
* Generated trampoline may contain rIP-relative addressing which
* displacement needs to be fixed.
*/
text_poke_apply_relocation(trampoline, trampoline, size,
(void *)start_offset, size);
/*
* The address of the ftrace_ops that is used for this trampoline
* is stored at the end of the trampoline. This will be used to

View File

@@ -268,18 +268,10 @@ void __init idt_setup_early_pf(void)
}
#endif
#if IS_ENABLED(CONFIG_KVM_INTEL)
noinstr void idt_entry_from_kvm(unsigned int vector)
#if IS_ENABLED(CONFIG_KVM_INTEL) && !defined(CONFIG_X86_64)
void idt_entry_from_kvm(unsigned int vector)
{
if (vector == NMI_VECTOR)
return idt_do_nmi_irqoff();
/*
* Only the NMI path requires noinstr.
*/
instrumentation_begin();
idt_do_interrupt_irqoff(gate_offset(idt_table + vector));
instrumentation_end();
}
#endif

View File

@@ -511,6 +511,11 @@ static int aie2_init(struct amdxdna_dev *xdna)
return -EINVAL;
}
if (!xdna->group) {
XDNA_ERR(xdna, "Running without IOMMU not supported");
return -EINVAL;
}
ndev = drmm_kzalloc(&xdna->ddev, sizeof(*ndev), GFP_KERNEL);
if (!ndev)
return -ENOMEM;

View File

@@ -450,7 +450,7 @@ priority_bands_fops_write(struct file *file, const char __user *user_buf, size_t
u32 band;
int ret;
if (size >= sizeof(buf))
if (*pos != 0 || size >= sizeof(buf))
return -EINVAL;
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, pos, user_buf, size);

View File

@@ -79,11 +79,6 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
rkt_obj->size = args->size;
rkt_obj->offset = 0;
ret = drm_gem_handle_create(file, gem_obj, &args->handle);
drm_gem_object_put(gem_obj);
if (ret)
goto err;
sgt = drm_gem_shmem_get_pages_sgt(shmem_obj);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
@@ -95,6 +90,8 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
rkt_obj->size, PAGE_SIZE,
0, 0);
mutex_unlock(&rocket_priv->mm_lock);
if (ret)
goto err;
ret = iommu_map_sgtable(rocket_priv->domain->domain,
rkt_obj->mm.start,
@@ -112,8 +109,18 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
args->dma_address = rkt_obj->mm.start;
ret = drm_gem_handle_create(file, gem_obj, &args->handle);
if (ret)
goto err_unmap;
drm_gem_object_put(gem_obj);
return 0;
err_unmap:
iommu_unmap(rocket_priv->domain->domain,
rkt_obj->mm.start, rkt_obj->size);
err_remove_node:
mutex_lock(&rocket_priv->mm_lock);
drm_mm_remove_node(&rkt_obj->mm);

View File

@@ -157,6 +157,14 @@ pub(crate) fn set_info_target_node(&mut self, target_node: NodeRef) {
self.get_or_init_info().target_node = Some(target_node);
}
pub(crate) fn take_oneway_node(&mut self) -> Option<DArc<Node>> {
if let Some(info) = self.allocation_info.as_mut() {
info.oneway_node.take()
} else {
None
}
}
/// Reserve enough space to push at least `num_fds` fds.
pub(crate) fn info_add_fd_reserve(&mut self, num_fds: usize) -> Result {
self.get_or_init_info()

View File

@@ -1402,7 +1402,12 @@ fn deferred_release(self: Arc<Self>) {
// Clear delivered_deaths list.
//
// Scope ensures that MutexGuard is dropped while executing the body.
while let Some(delivered_death) = { self.inner.lock().delivered_deaths.pop_front() } {
while let Some(delivered_death) = {
// Explicitly bind to avoid tail expression lifetime extension of the lockguard
// Can be removed when the kernel moves to edition 2024
let maybe_death = self.inner.lock().delivered_deaths.pop_front();
maybe_death
} {
drop(delivered_death);
}

View File

@@ -270,7 +270,8 @@ fn drop_outstanding_txn(&self) {
/// Not used for replies.
pub(crate) fn submit(self: DLArc<Self>, info: &mut TransactionInfo) -> BinderResult {
// Defined before `process_inner` so that the destructor runs after releasing the lock.
let mut _t_outdated;
let _t_outdated;
let _oneway_node;
let oneway = self.flags & TF_ONE_WAY != 0;
let process = self.to.clone();
@@ -287,6 +288,14 @@ pub(crate) fn submit(self: DLArc<Self>, info: &mut TransactionInfo) -> BinderRes
if let Some(t_outdated) =
target_node.take_outdated_transaction(&self, &mut process_inner)
{
let mut alloc_guard = t_outdated.allocation.lock();
if let Some(alloc) = (*alloc_guard).as_mut() {
// Take the oneway node to prevent `Allocation::drop` from calling
// `pending_oneway_finished()`, which would be incorrect as this
// transaction is not being submitted.
_oneway_node = alloc.take_oneway_node();
}
drop(alloc_guard);
// Save the transaction to be dropped after locks are released.
_t_outdated = t_outdated;
}

View File

@@ -327,7 +327,7 @@ config PANEL_CHANGE_MESSAGE
say 'N' and keep the default message with the version.
config PANEL_BOOT_MESSAGE
depends on PANEL_CHANGE_MESSAGE="y"
depends on PANEL_CHANGE_MESSAGE
string "New initialization message"
default ""
help

View File

@@ -173,7 +173,7 @@ static int linedisp_display(struct linedisp *linedisp, const char *msg,
count = strlen(msg);
/* if the string ends with a newline, trim it */
if (msg[count - 1] == '\n')
if (count && msg[count - 1] == '\n')
count--;
if (!count) {

View File

@@ -86,10 +86,7 @@ static const struct linedisp_ops max6959_linedisp_ops = {
static int max6959_enable(struct max6959_priv *priv, bool enable)
{
u8 mask = REG_CONFIGURATION_S_BIT;
u8 value = enable ? mask : 0;
return regmap_update_bits(priv->regmap, REG_CONFIGURATION, mask, value);
return regmap_assign_bits(priv->regmap, REG_CONFIGURATION, REG_CONFIGURATION_S_BIT, enable);
}
static void max6959_power_off(void *priv)

View File

@@ -3257,6 +3257,9 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
*change = false;
if (regmap_volatile(map, reg) && map->reg_update_bits) {
if (map->cache_only)
return -EBUSY;
reg = regmap_reg_addr(map, reg);
ret = map->reg_update_bits(map->bus_context, reg, mask, val);
if (ret == 0 && change)

View File

@@ -274,6 +274,7 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
/* Step 2a : make sure trigger sources are unique */
err |= comedi_check_trigger_is_unique(cmd->convert_src);
err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
err |= comedi_check_trigger_is_unique(cmd->stop_src);
/* Step 2b : and mutually compatible */
@@ -324,10 +325,10 @@ static int waveform_ai_cmdtest(struct comedi_device *dev,
arg = min(arg,
rounddown(UINT_MAX, (unsigned int)NSEC_PER_USEC));
arg = NSEC_PER_USEC * DIV_ROUND_CLOSEST(arg, NSEC_PER_USEC);
if (cmd->scan_begin_arg == TRIG_TIMER) {
if (cmd->scan_begin_src == TRIG_TIMER) {
/* limit convert_arg to keep scan_begin_arg in range */
limit = UINT_MAX / cmd->scan_end_arg;
limit = rounddown(limit, (unsigned int)NSEC_PER_SEC);
limit = rounddown(limit, (unsigned int)NSEC_PER_USEC);
arg = min(arg, limit);
}
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);

View File

@@ -124,7 +124,8 @@ struct counter_device *counter_alloc(size_t sizeof_priv)
err_dev_set_name:
counter_chrdev_remove(counter);
put_device(dev);
return NULL;
err_chrdev_add:
ida_free(&counter_ida, dev->id);

View File

@@ -792,9 +792,13 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags)
if (!dmabuf || !dmabuf->file)
return -EINVAL;
fd = FD_ADD(flags, dmabuf->file);
fd = get_unused_fd_flags(flags);
if (fd < 0)
return fd;
DMA_BUF_TRACE(trace_dma_buf_fd, dmabuf, fd);
fd_install(fd, dmabuf->file);
return fd;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_fd, "DMA_BUF");

View File

@@ -31,6 +31,9 @@ static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
if (response) {
xfer->rxcnt = cmdlen;
xfer->rxd = cmd;
} else {
xfer->rxcnt = 0;
xfer->rxd = NULL;
}
}

View File

@@ -7,11 +7,12 @@
#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/bits.h>
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/container_of.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/find.h>
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
#include <linux/io.h>
#include <linux/iopoll.h>
@@ -104,12 +105,15 @@ struct acpm_queue {
*
* @cmd: pointer to where the data shall be saved.
* @n_cmd: number of 32-bit commands.
* @response: true if the client expects the RX data.
* @rxcnt: expected length of the response in 32-bit words.
* @completed: flag indicating if the firmware response has been fully
* processed.
*/
struct acpm_rx_data {
u32 *cmd;
size_t n_cmd;
bool response;
size_t rxcnt;
bool completed;
};
#define ACPM_SEQNUM_MAX 64
@@ -199,31 +203,33 @@ static void acpm_get_saved_rx(struct acpm_chan *achan,
const struct acpm_rx_data *rx_data = &achan->rx_data[tx_seqnum - 1];
u32 rx_seqnum;
if (!rx_data->response)
if (!rx_data->rxcnt)
return;
rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
if (rx_seqnum == tx_seqnum) {
if (rx_seqnum == tx_seqnum)
memcpy(xfer->rxd, rx_data->cmd, xfer->rxcnt * sizeof(*xfer->rxd));
clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
}
}
/**
* acpm_get_rx() - get response from RX queue.
* @achan: ACPM channel info.
* @xfer: reference to the transfer to get response for.
* @native_match: pointer to a boolean set to true if the thread natively
* processed its own sequence number during this call.
*
* Return: 0 on success, -errno otherwise.
*/
static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer,
bool *native_match)
{
u32 rx_front, rx_seqnum, tx_seqnum, seqnum;
const void __iomem *base, *addr;
struct acpm_rx_data *rx_data;
u32 i, val, mlen;
bool rx_set = false;
*native_match = false;
guard(mutex)(&achan->rx_lock);
@@ -232,10 +238,8 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
if (i == rx_front) {
acpm_get_saved_rx(achan, xfer, tx_seqnum);
if (i == rx_front)
return 0;
}
base = achan->rx.base;
mlen = achan->mlen;
@@ -256,11 +260,16 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
seqnum = rx_seqnum - 1;
rx_data = &achan->rx_data[seqnum];
if (rx_data->response) {
if (rx_data->rxcnt) {
if (rx_seqnum == tx_seqnum) {
__ioread32_copy(xfer->rxd, addr, xfer->rxcnt);
rx_set = true;
clear_bit(seqnum, achan->bitmap_seqnum);
/*
* Signal completion to the polling thread.
* Pairs with smp_load_acquire() in polling
* loop.
*/
smp_store_release(&rx_data->completed, true);
*native_match = true;
} else {
/*
* The RX data corresponds to another request.
@@ -268,10 +277,23 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
* clear yet the bitmap. It will be cleared
* after the response is copied to the request.
*/
__ioread32_copy(rx_data->cmd, addr, xfer->rxcnt);
__ioread32_copy(rx_data->cmd, addr,
rx_data->rxcnt);
/*
* Signal completion to the polling thread.
* Pairs with smp_load_acquire() in polling
* loop.
*/
smp_store_release(&rx_data->completed, true);
}
} else {
clear_bit(seqnum, achan->bitmap_seqnum);
/*
* Signal completion to the polling thread.
* Pairs with smp_load_acquire() in polling loop.
*/
smp_store_release(&rx_data->completed, true);
if (rx_seqnum == tx_seqnum)
*native_match = true;
}
i = (i + 1) % achan->qlen;
@@ -280,13 +302,6 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
/* We saved all responses, mark RX empty. */
writel(rx_front, achan->rx.rear);
/*
* If the response was not in this iteration of the queue, check if the
* RX data was previously saved.
*/
if (!rx_set)
acpm_get_saved_rx(achan, xfer, tx_seqnum);
return 0;
}
@@ -301,6 +316,7 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
const struct acpm_xfer *xfer)
{
struct device *dev = achan->acpm->dev;
bool native_match;
ktime_t timeout;
u32 seqnum;
int ret;
@@ -309,12 +325,25 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US);
do {
ret = acpm_get_rx(achan, xfer);
ret = acpm_get_rx(achan, xfer, &native_match);
if (ret)
return ret;
if (!test_bit(seqnum - 1, achan->bitmap_seqnum))
/*
* Safely check if our specific transaction has been processed.
* smp_load_acquire prevents the CPU from speculatively
* executing subsequent instructions before the transaction is
* synchronized.
*/
if (smp_load_acquire(&achan->rx_data[seqnum - 1].completed)) {
/* Retrieve payload if another thread cached it for us */
if (!native_match)
acpm_get_saved_rx(achan, xfer, seqnum);
/* Relinquish ownership of the sequence slot */
clear_bit_unlock(seqnum - 1, achan->bitmap_seqnum);
return 0;
}
/* Determined experimentally. */
udelay(20);
@@ -362,29 +391,48 @@ static int acpm_wait_for_queue_slots(struct acpm_chan *achan, u32 next_tx_front)
* TX queue.
* @achan: ACPM channel info.
* @xfer: reference to the transfer being prepared.
*
* Return: 0 on success, -errno otherwise.
*/
static void acpm_prepare_xfer(struct acpm_chan *achan,
const struct acpm_xfer *xfer)
static int acpm_prepare_xfer(struct acpm_chan *achan,
const struct acpm_xfer *xfer)
{
struct acpm_rx_data *rx_data;
u32 *txd = (u32 *)xfer->txd;
unsigned long size = ACPM_SEQNUM_MAX - 1;
unsigned long bit = achan->seqnum;
/* Prevent chan->seqnum from being re-used */
do {
if (++achan->seqnum == ACPM_SEQNUM_MAX)
achan->seqnum = 1;
} while (test_bit(achan->seqnum - 1, achan->bitmap_seqnum));
bit = find_next_zero_bit(achan->bitmap_seqnum, size, bit);
if (bit >= size) {
bit = find_first_zero_bit(achan->bitmap_seqnum, size);
if (bit >= size) {
dev_err_ratelimited(achan->acpm->dev,
"ACPM sequence number pool exhausted\n");
return -EBUSY;
}
}
/*
* Execute the atomic set to formally claim the bit and establish
* LKMM Acquire semantics against the RX thread's clear_bit_unlock().
* A loop is unnecessary because allocations are strictly serialized
* by tx_lock.
*/
if (WARN_ON_ONCE(test_and_set_bit_lock(bit, achan->bitmap_seqnum)))
return -EIO;
/* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
achan->seqnum = bit + 1;
txd[0] |= FIELD_PREP(ACPM_PROTOCOL_SEQNUM, achan->seqnum);
/* Clear data for upcoming responses */
rx_data = &achan->rx_data[achan->seqnum - 1];
rx_data = &achan->rx_data[bit];
rx_data->completed = false;
memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd);
if (xfer->rxd)
rx_data->response = true;
/* zero means no response expected */
rx_data->rxcnt = xfer->rxcnt;
/* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
set_bit(achan->seqnum - 1, achan->bitmap_seqnum);
return 0;
}
/**
@@ -444,7 +492,9 @@ int acpm_do_xfer(struct acpm_handle *handle, const struct acpm_xfer *xfer)
if (ret)
return ret;
acpm_prepare_xfer(achan, xfer);
ret = acpm_prepare_xfer(achan, xfer);
if (ret)
return ret;
/* Write TX command. */
__iowrite32_copy(achan->tx.base + achan->mlen * tx_front,
@@ -526,10 +576,11 @@ static int acpm_achan_alloc_cmds(struct acpm_chan *achan)
/**
* acpm_free_mbox_chans() - free mailbox channels.
* @acpm: pointer to driver data.
* @data: pointer to driver data.
*/
static void acpm_free_mbox_chans(struct acpm_info *acpm)
static void acpm_free_mbox_chans(void *data)
{
struct acpm_info *acpm = data;
int i;
for (i = 0; i < acpm->num_chans; i++)
@@ -557,6 +608,10 @@ static int acpm_channels_init(struct acpm_info *acpm)
if (!acpm->chans)
return -ENOMEM;
ret = devm_add_action_or_reset(dev, acpm_free_mbox_chans, acpm);
if (ret)
return dev_err_probe(dev, ret, "Failed to add mbox free action.\n");
chans_shmem = acpm->sram_base + readl(&shmem->chans);
for (i = 0; i < acpm->num_chans; i++) {
@@ -578,10 +633,8 @@ static int acpm_channels_init(struct acpm_info *acpm)
cl->dev = dev;
achan->chan = mbox_request_channel(cl, 0);
if (IS_ERR(achan->chan)) {
acpm_free_mbox_chans(acpm);
if (IS_ERR(achan->chan))
return PTR_ERR(achan->chan);
}
}
return 0;

View File

@@ -1093,9 +1093,16 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
* If that number is larger than the size of the array, the ioctl must
* be retried.
*/
if (args->num_entries > INT_MAX / sizeof(*vm_entries)) {
r = -EINVAL;
goto out_exec;
}
vm_entries = kvcalloc(args->num_entries, sizeof(*vm_entries), GFP_KERNEL);
if (!vm_entries)
return -ENOMEM;
if (!vm_entries) {
r = -ENOMEM;
goto out_exec;
}
amdgpu_vm_bo_va_for_each_valid_mapping(bo_va, mapping) {
if (num_mappings < args->num_entries) {

View File

@@ -51,8 +51,6 @@
#include "amdgpu_amdkfd.h"
#include "amdgpu_hmm.h"
#define MAX_WALK_BYTE (2UL << 30)
/**
* amdgpu_hmm_invalidate_gfx - callback to notify about mm change
*
@@ -78,6 +76,7 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
mmu_interval_set_seq(mni, cur_seq);
amdgpu_vm_bo_invalidate(bo, false);
r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP,
false, MAX_SCHEDULE_TIMEOUT);
mutex_unlock(&adev->notifier_lock);
@@ -170,11 +169,13 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
void *owner,
struct amdgpu_hmm_range *range)
{
unsigned long end;
const u64 max_bytes = SZ_2G;
struct hmm_range *hmm_range = &range->hmm_range;
unsigned long timeout;
unsigned long *pfns;
int r = 0;
struct hmm_range *hmm_range = &range->hmm_range;
unsigned long end;
int r;
pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
if (unlikely(!pfns)) {
@@ -191,8 +192,9 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
end = start + npages * PAGE_SIZE;
hmm_range->dev_private_owner = owner;
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
do {
hmm_range->end = min(hmm_range->start + MAX_WALK_BYTE, end);
hmm_range->end = min(hmm_range->start + max_bytes, end);
pr_debug("hmm range: start = 0x%lx, end = 0x%lx",
hmm_range->start, hmm_range->end);
@@ -200,7 +202,6 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
retry:
hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
r = hmm_range_fault(hmm_range);
if (unlikely(r)) {
if (r == -EBUSY && !time_after(jiffies, timeout))
@@ -210,7 +211,7 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
if (hmm_range->end == end)
break;
hmm_range->hmm_pfns += MAX_WALK_BYTE >> PAGE_SHIFT;
hmm_range->hmm_pfns += max_bytes >> PAGE_SHIFT;
hmm_range->start = hmm_range->end;
} while (hmm_range->end < end);

View File

@@ -2280,7 +2280,8 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev)
list_for_each_entry(obj, &con->head, node) {
if (amdgpu_ras_is_supported(adev, obj->head.block) &&
(obj->attr_inuse == 1)) {
sprintf(fs_info.debugfs_name, "%s_err_inject",
snprintf(fs_info.debugfs_name, sizeof(fs_info.debugfs_name),
"%s_err_inject",
get_ras_block_str(&obj->head));
fs_info.head = obj->head;
amdgpu_ras_debugfs_create(adev, &fs_info, dir);

View File

@@ -215,33 +215,15 @@ void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell)
xa_unlock_irqrestore(xa, flags);
}
static int amdgpu_userq_buffer_va_list_add(struct amdgpu_usermode_queue *queue,
struct amdgpu_bo_va_mapping *va_map, u64 addr)
{
struct amdgpu_userq_va_cursor *va_cursor;
struct userq_va_list;
va_cursor = kzalloc_obj(*va_cursor);
if (!va_cursor)
return -ENOMEM;
INIT_LIST_HEAD(&va_cursor->list);
va_cursor->gpu_addr = addr;
va_map->bo_va->userq_va_mapped = true;
list_add(&va_cursor->list, &queue->userq_va_list);
return 0;
}
int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
struct amdgpu_usermode_queue *queue,
u64 addr, u64 expected_size)
u64 addr, u64 expected_size,
u64 *va_out)
{
struct amdgpu_bo_va_mapping *va_map;
struct amdgpu_vm *vm = queue->vm;
u64 user_addr;
u64 size;
int r = 0;
/* Caller must hold vm->root.bo reservation */
dma_resv_assert_held(queue->vm->root.bo->tbo.base.resv);
@@ -250,20 +232,18 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
size = expected_size >> AMDGPU_GPU_PAGE_SHIFT;
va_map = amdgpu_vm_bo_lookup_mapping(vm, user_addr);
if (!va_map) {
r = -EINVAL;
goto out_err;
}
if (!va_map)
return -EINVAL;
/* Only validate the userq whether resident in the VM mapping range */
if (user_addr >= va_map->start &&
va_map->last - user_addr + 1 >= size) {
amdgpu_userq_buffer_va_list_add(queue, va_map, user_addr);
va_map->bo_va->userq_va_mapped = true;
*va_out = user_addr;
return 0;
}
r = -EINVAL;
out_err:
return r;
return -EINVAL;
}
static bool amdgpu_userq_buffer_va_mapped(struct amdgpu_vm *vm, u64 addr)
@@ -284,14 +264,16 @@ static bool amdgpu_userq_buffer_va_mapped(struct amdgpu_vm *vm, u64 addr)
static bool amdgpu_userq_buffer_vas_mapped(struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_va_cursor *va_cursor, *tmp;
int r = 0;
int i, r = 0;
list_for_each_entry_safe(va_cursor, tmp, &queue->userq_va_list, list) {
r += amdgpu_userq_buffer_va_mapped(queue->vm, va_cursor->gpu_addr);
for (i = 0; i < ARRAY_SIZE(queue->userq_vas.va_array); i++) {
if (!queue->userq_vas.va_array[i])
continue;
r += amdgpu_userq_buffer_va_mapped(queue->vm,
queue->userq_vas.va_array[i]);
dev_dbg(queue->userq_mgr->adev->dev,
"validate the userq mapping:%p va:%llx r:%d\n",
queue, va_cursor->gpu_addr, r);
queue, queue->userq_vas.va_array[i], r);
}
if (r != 0)
@@ -300,24 +282,7 @@ static bool amdgpu_userq_buffer_vas_mapped(struct amdgpu_usermode_queue *queue)
return false;
}
static void amdgpu_userq_buffer_vas_list_cleanup(struct amdgpu_device *adev,
struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_va_cursor *va_cursor, *tmp;
struct amdgpu_bo_va_mapping *mapping;
/* Caller must hold vm->root.bo reservation */
dma_resv_assert_held(queue->vm->root.bo->tbo.base.resv);
list_for_each_entry_safe(va_cursor, tmp, &queue->userq_va_list, list) {
mapping = amdgpu_vm_bo_lookup_mapping(queue->vm, va_cursor->gpu_addr);
if (mapping)
dev_dbg(adev->dev, "delete the userq:%p va:%llx\n",
queue, va_cursor->gpu_addr);
list_del(&va_cursor->list);
kfree(va_cursor);
}
}
static int amdgpu_userq_preempt_helper(struct amdgpu_usermode_queue *queue)
{
@@ -417,18 +382,14 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
struct amdgpu_device *adev = uq_mgr->adev;
const struct amdgpu_userq_funcs *uq_funcs = adev->userq_funcs[queue->queue_type];
/* Wait for mode-1 reset to complete */
down_read(&adev->reset_domain->sem);
uq_funcs->mqd_destroy(queue);
/* Use interrupt-safe locking since IRQ handlers may access these XArrays */
xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index);
amdgpu_userq_fence_driver_free(queue);
queue->fence_drv = NULL;
queue->userq_mgr = NULL;
list_del(&queue->userq_va_list);
up_read(&adev->reset_domain->sem);
}
@@ -467,81 +428,15 @@ amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
dma_fence_put(ev_fence);
}
int amdgpu_userq_create_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj,
int size)
{
struct amdgpu_device *adev = uq_mgr->adev;
struct amdgpu_bo_param bp;
int r;
memset(&bp, 0, sizeof(bp));
bp.byte_align = PAGE_SIZE;
bp.domain = AMDGPU_GEM_DOMAIN_GTT;
bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
bp.type = ttm_bo_type_kernel;
bp.size = size;
bp.resv = NULL;
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
r = amdgpu_bo_create(adev, &bp, &userq_obj->obj);
if (r) {
drm_file_err(uq_mgr->file, "Failed to allocate BO for userqueue (%d)", r);
return r;
}
r = amdgpu_bo_reserve(userq_obj->obj, true);
if (r) {
drm_file_err(uq_mgr->file, "Failed to reserve BO to map (%d)", r);
goto free_obj;
}
r = amdgpu_bo_pin(userq_obj->obj, AMDGPU_GEM_DOMAIN_GTT);
if (r)
goto unresv;
r = amdgpu_ttm_alloc_gart(&(userq_obj->obj)->tbo);
if (r) {
drm_file_err(uq_mgr->file, "Failed to alloc GART for userqueue object (%d)", r);
goto unpin_bo;
}
r = amdgpu_bo_kmap(userq_obj->obj, &userq_obj->cpu_ptr);
if (r) {
drm_file_err(uq_mgr->file, "Failed to map BO for userqueue (%d)", r);
goto unpin_bo;
}
userq_obj->gpu_addr = amdgpu_bo_gpu_offset(userq_obj->obj);
amdgpu_bo_unreserve(userq_obj->obj);
memset(userq_obj->cpu_ptr, 0, size);
return 0;
unpin_bo:
amdgpu_bo_unpin(userq_obj->obj);
unresv:
amdgpu_bo_unreserve(userq_obj->obj);
free_obj:
amdgpu_bo_unref(&userq_obj->obj);
return r;
}
void amdgpu_userq_destroy_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj)
{
amdgpu_bo_kunmap(userq_obj->obj);
amdgpu_bo_unpin(userq_obj->obj);
amdgpu_bo_unref(&userq_obj->obj);
}
uint64_t
static int
amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_db_info *db_info,
struct drm_file *filp)
struct drm_file *filp,
u64 *index)
{
uint64_t index;
u64 doorbell_index;
struct drm_gem_object *gobj;
struct amdgpu_userq_obj *db_obj = db_info->db_obj;
int r, db_size;
@@ -588,12 +483,13 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
goto unpin_bo;
}
index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj,
db_info->doorbell_offset, db_size);
doorbell_index = amdgpu_doorbell_index_on_bar(uq_mgr->adev, db_obj->obj,
db_info->doorbell_offset, db_size);
drm_dbg_driver(adev_to_drm(uq_mgr->adev),
"[Usermode queues] doorbell index=%lld\n", index);
"[Usermode queues] doorbell index=%lld\n", doorbell_index);
amdgpu_bo_unreserve(db_obj->obj);
return index;
*index = doorbell_index;
return 0;
unpin_bo:
amdgpu_bo_unpin(db_obj->obj);
@@ -608,9 +504,7 @@ static int
amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
{
struct amdgpu_device *adev = uq_mgr->adev;
struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
struct amdgpu_vm *vm = &fpriv->vm;
const struct amdgpu_userq_funcs *uq_funcs = adev->userq_funcs[queue->queue_type];
int r = 0;
cancel_delayed_work_sync(&uq_mgr->resume_work);
@@ -618,14 +512,6 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
/* Cancel any pending hang detection work and cleanup */
cancel_delayed_work_sync(&queue->hang_detect_work);
r = amdgpu_bo_reserve(vm->root.bo, false);
if (r) {
drm_file_err(uq_mgr->file, "Failed to reserve root bo during userqueue destroy\n");
return r;
}
amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
amdgpu_bo_unreserve(vm->root.bo);
mutex_lock(&uq_mgr->userq_mutex);
amdgpu_userq_wait_for_last_fence(queue);
@@ -637,6 +523,10 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
amdgpu_userq_cleanup(queue);
mutex_unlock(&uq_mgr->userq_mutex);
cancel_delayed_work_sync(&queue->hang_detect_work);
uq_funcs->mqd_destroy(queue);
queue->userq_mgr = NULL;
amdgpu_bo_reserve(queue->db_obj.obj, true);
amdgpu_bo_unpin(queue->db_obj.obj);
amdgpu_bo_unreserve(queue->db_obj.obj);
@@ -739,7 +629,6 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
}
kref_init(&queue->refcount);
INIT_LIST_HEAD(&queue->userq_va_list);
queue->doorbell_handle = args->in.doorbell_handle;
queue->queue_type = args->in.ip_type;
queue->vm = &fpriv->vm;
@@ -748,26 +637,29 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
INIT_DELAYED_WORK(&queue->hang_detect_work,
amdgpu_userq_hang_detect_work);
mutex_init(&queue->fence_drv_lock);
xa_init_flags(&queue->fence_drv_xa, XA_FLAGS_ALLOC);
r = amdgpu_userq_fence_driver_alloc(adev, &queue->fence_drv);
if (r)
goto free_queue;
xa_init_flags(&queue->fence_drv_xa, XA_FLAGS_ALLOC);
mutex_init(&queue->fence_drv_lock);
/* Make sure the queue can actually run with those virtual addresses. */
r = amdgpu_bo_reserve(fpriv->vm.root.bo, false);
if (r)
goto free_fence_drv;
if (amdgpu_userq_input_va_validate(adev, queue, args->in.queue_va,
args->in.queue_size) ||
args->in.queue_size,
&queue->userq_vas.va.queue_rb) ||
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va,
AMDGPU_GPU_PAGE_SIZE) ||
AMDGPU_GPU_PAGE_SIZE,
&queue->userq_vas.va.rptr) ||
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va,
AMDGPU_GPU_PAGE_SIZE)) {
AMDGPU_GPU_PAGE_SIZE,
&queue->userq_vas.va.wptr)) {
r = -EINVAL;
amdgpu_bo_unreserve(fpriv->vm.root.bo);
goto clean_mapping;
goto free_fence_drv;
}
amdgpu_bo_unreserve(fpriv->vm.root.bo);
@@ -776,18 +668,17 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
db_info.doorbell_handle = queue->doorbell_handle;
db_info.db_obj = &queue->db_obj;
db_info.doorbell_offset = args->in.doorbell_offset;
index = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp);
if (index == (uint64_t)-EINVAL) {
r = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp, &index);
if (r) {
drm_file_err(uq_mgr->file, "Failed to get doorbell for queue\n");
r = -EINVAL;
goto clean_mapping;
goto free_fence_drv;
}
queue->doorbell_index = index;
r = uq_funcs->mqd_create(queue, &args->in);
if (r) {
drm_file_err(uq_mgr->file, "Failed to create Queue\n");
goto clean_mapping;
goto clean_doorbell_bo;
}
/* Update VM owner at userq submit-time for page-fault attribution. */
@@ -808,7 +699,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
if (r) {
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
mutex_unlock(&uq_mgr->userq_mutex);
goto clean_doorbell;
goto erase_doorbell;
}
}
@@ -831,15 +722,15 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
args->out.queue_id = qid;
return 0;
clean_doorbell:
erase_doorbell:
xa_erase_irq(&adev->userq_doorbell_xa, index);
clean_mqd:
uq_funcs->mqd_destroy(queue);
clean_mapping:
amdgpu_bo_reserve(fpriv->vm.root.bo, true);
amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
amdgpu_bo_unreserve(fpriv->vm.root.bo);
mutex_destroy(&queue->fence_drv_lock);
clean_doorbell_bo:
amdgpu_bo_reserve(queue->db_obj.obj, true);
amdgpu_bo_unpin(queue->db_obj.obj);
amdgpu_bo_unreserve(queue->db_obj.obj);
amdgpu_bo_unref(&queue->db_obj.obj);
free_fence_drv:
amdgpu_userq_fence_driver_free(queue);
free_queue:

View File

@@ -48,11 +48,6 @@ struct amdgpu_userq_obj {
struct amdgpu_bo *obj;
};
struct amdgpu_userq_va_cursor {
u64 gpu_addr;
struct list_head list;
};
struct amdgpu_usermode_queue {
int queue_type;
enum amdgpu_userq_state state;
@@ -93,7 +88,17 @@ struct amdgpu_usermode_queue {
struct delayed_work hang_detect_work;
struct kref refcount;
struct list_head userq_va_list;
union {
struct {
u64 queue_rb;
u64 wptr;
u64 rptr;
u64 eop;
u64 shadow;
u64 csa;
} va;
u64 va_array[6];
} userq_vas;
};
struct amdgpu_userq_funcs {
@@ -151,22 +156,11 @@ void amdgpu_userq_mgr_cancel_reset_work(struct amdgpu_device *adev);
void amdgpu_userq_mgr_cancel_resume(struct amdgpu_userq_mgr *userq_mgr);
void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
int amdgpu_userq_create_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj,
int size);
void amdgpu_userq_destroy_object(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_userq_obj *userq_obj);
void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr);
void amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *userq_mgr,
struct amdgpu_eviction_fence_mgr *evf_mgr);
uint64_t amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_db_info *db_info,
struct drm_file *filp);
u32 amdgpu_userq_get_supported_ip_mask(struct amdgpu_device *adev);
bool amdgpu_userq_enabled(struct drm_device *dev);
@@ -185,7 +179,8 @@ void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell);
int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
struct amdgpu_usermode_queue *queue,
u64 addr, u64 expected_size);
u64 addr, u64 expected_size, u64 *va_out);
void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping,
uint64_t saddr);

View File

@@ -1631,6 +1631,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
{
struct amdgpu_bo_va *bo_va;
struct dma_resv *resv;
struct amdgpu_bo *bo;
bool clear, unlock;
int r;
@@ -1650,11 +1651,13 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev,
while (!list_empty(&vm->invalidated)) {
bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va,
base.vm_status);
resv = bo_va->base.bo->tbo.base.resv;
bo = bo_va->base.bo;
resv = bo->tbo.base.resv;
spin_unlock(&vm->status_lock);
/* Try to reserve the BO to avoid clearing its ptes */
if (!adev->debug_vm && dma_resv_trylock(resv)) {
if (!adev->debug_vm && !amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) &&
dma_resv_trylock(resv)) {
clear = false;
unlock = true;
/* The caller is already holding the reservation lock */

View File

@@ -81,7 +81,7 @@ mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
ret = amdgpu_ttm_alloc_gart(&wptr_obj->obj->tbo);
if (ret) {
DRM_ERROR("Failed to bind bo to GART. ret %d\n", ret);
goto fail_map;
goto fail_alloc_gart;
}
queue->wptr_obj.gpu_addr = amdgpu_bo_gpu_offset(wptr_obj->obj);
@@ -89,6 +89,8 @@ mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
drm_exec_fini(&exec);
return 0;
fail_alloc_gart:
amdgpu_bo_unpin(wptr_obj->obj);
fail_map:
amdgpu_bo_unref(&wptr_obj->obj);
fail_lock:
@@ -190,12 +192,16 @@ static int mes_userq_create_ctx_space(struct amdgpu_userq_mgr *uq_mgr,
* for the same.
*/
size = AMDGPU_USERQ_PROC_CTX_SZ + AMDGPU_USERQ_GANG_CTX_SZ;
r = amdgpu_userq_create_object(uq_mgr, ctx, size);
r = amdgpu_bo_create_kernel(uq_mgr->adev, size, 0,
AMDGPU_GEM_DOMAIN_GTT,
&ctx->obj, &ctx->gpu_addr,
&ctx->cpu_ptr);
if (r) {
DRM_ERROR("Failed to allocate ctx space bo for userqueue, err:%d\n", r);
return r;
}
memset(ctx->cpu_ptr, 0, size);
return 0;
}
@@ -268,13 +274,19 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
return -ENOMEM;
}
r = amdgpu_userq_create_object(uq_mgr, &queue->mqd,
AMDGPU_MQD_SIZE_ALIGN(mqd_hw_default->mqd_size));
r = amdgpu_bo_create_kernel(adev,
AMDGPU_MQD_SIZE_ALIGN(mqd_hw_default->mqd_size),
0, AMDGPU_GEM_DOMAIN_GTT,
&queue->mqd.obj, &queue->mqd.gpu_addr,
&queue->mqd.cpu_ptr);
if (r) {
DRM_ERROR("Failed to create MQD object for userqueue\n");
goto free_props;
}
memset(queue->mqd.cpu_ptr, 0,
AMDGPU_MQD_SIZE_ALIGN(mqd_hw_default->mqd_size));
/* Initialize the MQD BO with user given values */
userq_props->wptr_gpu_addr = mqd_user->wptr_va;
userq_props->rptr_gpu_addr = mqd_user->rptr_va;
@@ -306,8 +318,9 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
kfree(compute_mqd);
goto free_mqd;
}
r = amdgpu_userq_input_va_validate(adev, queue, compute_mqd->eop_va,
2048);
r = amdgpu_userq_input_va_validate(adev, queue,
compute_mqd->eop_va, 2048,
&queue->userq_vas.va.eop);
amdgpu_bo_unreserve(queue->vm->root.bo);
if (r) {
kfree(compute_mqd);
@@ -356,7 +369,8 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
goto free_mqd;
}
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->shadow_va,
shadow_info.shadow_size);
shadow_info.shadow_size,
&queue->userq_vas.va.shadow);
if (r) {
amdgpu_bo_unreserve(queue->vm->root.bo);
kfree(mqd_gfx_v11);
@@ -364,7 +378,8 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
}
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->csa_va,
shadow_info.csa_size);
shadow_info.csa_size,
&queue->userq_vas.va.csa);
amdgpu_bo_unreserve(queue->vm->root.bo);
if (r) {
kfree(mqd_gfx_v11);
@@ -394,7 +409,8 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
goto free_mqd;
}
r = amdgpu_userq_input_va_validate(adev, queue, mqd_sdma_v11->csa_va,
32);
32,
&queue->userq_vas.va.csa);
amdgpu_bo_unreserve(queue->vm->root.bo);
if (r) {
kfree(mqd_sdma_v11);
@@ -430,10 +446,12 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
return 0;
free_ctx:
amdgpu_userq_destroy_object(uq_mgr, &queue->fw_obj);
amdgpu_bo_free_kernel(&queue->fw_obj.obj, &queue->fw_obj.gpu_addr,
&queue->fw_obj.cpu_ptr);
free_mqd:
amdgpu_userq_destroy_object(uq_mgr, &queue->mqd);
amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
&queue->mqd.cpu_ptr);
free_props:
kfree(userq_props);
@@ -443,11 +461,12 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
static void mes_userq_mqd_destroy(struct amdgpu_usermode_queue *queue)
{
struct amdgpu_userq_mgr *uq_mgr = queue->userq_mgr;
amdgpu_userq_destroy_object(uq_mgr, &queue->fw_obj);
amdgpu_bo_free_kernel(&queue->fw_obj.obj, &queue->fw_obj.gpu_addr,
&queue->fw_obj.cpu_ptr);
kfree(queue->userq_prop);
amdgpu_userq_destroy_object(uq_mgr, &queue->mqd);
amdgpu_bo_free_kernel(&queue->mqd.obj, &queue->mqd.gpu_addr,
&queue->mqd.cpu_ptr);
}
static int mes_userq_preempt(struct amdgpu_usermode_queue *queue)

View File

@@ -2300,6 +2300,11 @@ static int criu_restore_devices(struct kfd_process *p,
ret = -EINVAL;
goto exit;
}
if (pdd->drm_file) {
ret = -EINVAL;
goto exit;
}
pdd->user_gpu_id = device_buckets[i].user_gpu_id;
drm_file = fget(device_buckets[i].drm_fd);
@@ -2310,11 +2315,6 @@ static int criu_restore_devices(struct kfd_process *p,
goto exit;
}
if (pdd->drm_file) {
ret = -EINVAL;
goto exit;
}
/* create the vm using render nodes for kfd pdd */
if (kfd_process_device_init_vm(pdd, drm_file)) {
pr_err("could not init vm for given pdd\n");

View File

@@ -3308,12 +3308,14 @@ static void copy_context_work_handler(struct work_struct *work)
static uint32_t *get_queue_ids(uint32_t num_queues, uint32_t *usr_queue_id_array)
{
size_t array_size = num_queues * sizeof(uint32_t);
if (!usr_queue_id_array)
return NULL;
return memdup_user(usr_queue_id_array, array_size);
if (num_queues > KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)
return ERR_PTR(-EINVAL);
return memdup_user(usr_queue_id_array,
array_size(num_queues, sizeof(uint32_t)));
}
int resume_queues(struct kfd_process *p,

View File

@@ -3732,6 +3732,9 @@ svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm,
svms = &p->svms;
if (!process_info)
return -EINVAL;
mutex_lock(&process_info->lock);
svm_range_list_lock_and_flush_work(svms, mm);

View File

@@ -105,15 +105,26 @@ static void dccg21_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppcl
* dccg2_init() unconditionally overwrites MICROSECOND_TIME_BASE_DIV to
* 0x00120264, destroying the marker before it can be read.
*
* Guard the call: if the S0i3 marker is present, skip dccg2_init() so the
* Guard the call: if the S0i3 marker is present, skip init so the
* WA can function correctly. bios_golden_init() will handle init in that case.
*
* DCN21 uses 48MHz refclk, not 100MHz, so we must explicitly set the correct
* values (48MHz is taken from rn_clk_mgr_construct()).
*/
static void dccg21_init(struct dccg *dccg)
{
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
if (dccg2_is_s0i3_golden_init_wa_done(dccg))
return;
dccg2_init(dccg);
/* 48MHz refclk from rn_clk_mgr_construct() */
REG_WRITE(MICROSECOND_TIME_BASE_DIV, 0x00120230);
REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x0010bb80);
REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x0e01003c);
if (REG(REFCLK_CNTL))
REG_WRITE(REFCLK_CNTL, 0);
}
static const struct dccg_funcs dccg21_funcs = {

View File

@@ -3076,6 +3076,10 @@ static bool si_dpm_vblank_too_short(void *handle)
/* we never hit the non-gddr5 limit so disable it */
u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0;
/* Disregard vblank time when there are no displays connected */
if (!adev->pm.pm_display_cfg.num_display)
return false;
/* Consider zero vblank time too short and disable MCLK switching.
* Note that the vblank time is set to maximum when no displays are attached,
* so we'll still enable MCLK switching in that case.

View File

@@ -70,8 +70,11 @@ static int drm_mode_align_dumb(struct drm_mode_create_dumb *args,
if (!pitch)
return -EINVAL;
if (hw_pitch_align)
if (hw_pitch_align) {
pitch = roundup(pitch, hw_pitch_align);
if (pitch < hw_pitch_align)
return -EINVAL;
}
if (!hw_size_align)
hw_size_align = PAGE_SIZE;
@@ -80,7 +83,7 @@ static int drm_mode_align_dumb(struct drm_mode_create_dumb *args,
if (check_mul_overflow(args->height, pitch, &size))
return -EINVAL;
size = ALIGN(size, hw_size_align);
size = roundup(size, hw_size_align);
if (!size)
return -EINVAL;
@@ -199,6 +202,13 @@ int drm_mode_create_dumb(struct drm_device *dev,
if (!args->width || !args->height || !args->bpp)
return -EINVAL;
/* Reject unreasonable inputs early. Dumb buffers are for software
* rendering; nothing legitimate needs more than 8192x8192 at 32bpp.
* This prevents overflows in downstream alignment helpers.
*/
if (args->width >= 8192 || args->height >= 8192 || args->bpp > 32)
return -EINVAL;
/* overflow checks for 32bit size calculations */
if (args->bpp > U32_MAX - 8)
return -EINVAL;

View File

@@ -1065,6 +1065,7 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
goto out_unlock;
}
idr_replace(&file_priv->object_idr, NULL, args->handle);
spin_unlock(&file_priv->table_lock);
if (obj->dma_buf) {
@@ -1073,6 +1074,7 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data,
if (ret < 0) {
spin_lock(&file_priv->table_lock);
idr_remove(&file_priv->object_idr, handle);
idr_replace(&file_priv->object_idr, obj, args->handle);
spin_unlock(&file_priv->table_lock);
goto out_unlock;
}

View File

@@ -391,8 +391,11 @@ static int hyperv_get_supported_resolution(struct hv_device *hdev)
return -ETIMEDOUT;
}
if (msg->resolution_resp.resolution_count == 0) {
drm_err(dev, "No supported resolutions\n");
if (msg->resolution_resp.resolution_count == 0 ||
msg->resolution_resp.resolution_count >
SYNTHVID_MAX_RESOLUTION_COUNT) {
drm_err(dev, "Invalid resolution count: %d\n",
msg->resolution_resp.resolution_count);
return -ENODEV;
}
@@ -417,30 +420,92 @@ static int hyperv_get_supported_resolution(struct hv_device *hdev)
return 0;
}
static void hyperv_receive_sub(struct hv_device *hdev)
static void hyperv_receive_sub(struct hv_device *hdev, u32 bytes_recvd)
{
struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
struct synthvid_msg *msg;
size_t hdr_size;
size_t need;
if (!hv)
return;
msg = (struct synthvid_msg *)hv->recv_buf;
/* Complete the wait event */
if (msg->vid_hdr.type == SYNTHVID_VERSION_RESPONSE ||
msg->vid_hdr.type == SYNTHVID_RESOLUTION_RESPONSE ||
msg->vid_hdr.type == SYNTHVID_VRAM_LOCATION_ACK) {
memcpy(hv->init_buf, msg, VMBUS_MAX_PACKET_SIZE);
complete(&hv->wait);
hdr_size = sizeof(struct pipe_msg_hdr) +
sizeof(struct synthvid_msg_hdr);
if (bytes_recvd < hdr_size) {
drm_err_ratelimited(&hv->dev,
"synthvid packet too small for header: %u\n",
bytes_recvd);
return;
}
if (msg->vid_hdr.type == SYNTHVID_FEATURE_CHANGE) {
msg = (struct synthvid_msg *)hv->recv_buf;
need = hdr_size;
switch (msg->vid_hdr.type) {
case SYNTHVID_VERSION_RESPONSE:
need += sizeof(struct synthvid_version_resp);
break;
case SYNTHVID_RESOLUTION_RESPONSE:
/*
* The resolution response is variable length: the host
* fills resolution_count entries, not the full
* SYNTHVID_MAX_RESOLUTION_COUNT array. Require the fixed
* prefix first so resolution_count can be read, then
* demand exactly the count-sized array.
*/
need += offsetof(struct synthvid_supported_resolution_resp,
supported_resolution);
if (bytes_recvd < need)
break;
if (msg->resolution_resp.resolution_count >
SYNTHVID_MAX_RESOLUTION_COUNT) {
drm_err_ratelimited(&hv->dev,
"synthvid resolution count too large: %u\n",
msg->resolution_resp.resolution_count);
return;
}
need += msg->resolution_resp.resolution_count *
sizeof(struct hvd_screen_info);
break;
case SYNTHVID_VRAM_LOCATION_ACK:
need += sizeof(struct synthvid_vram_location_ack);
break;
case SYNTHVID_FEATURE_CHANGE:
/*
* Not a completion-driving message: validate its own payload
* and consume it here rather than falling through to the
* memcpy/complete shared by the wait-event responses.
*/
if (bytes_recvd < need +
sizeof(struct synthvid_feature_change)) {
drm_err_ratelimited(&hv->dev,
"synthvid feature change packet too small: %u\n",
bytes_recvd);
return;
}
hv->dirt_needed = msg->feature_chg.is_dirt_needed;
if (hv->dirt_needed)
hyperv_hide_hw_ptr(hv->hdev);
return;
default:
return;
}
/*
* Shared completion path for the wait-event responses
* (VERSION_RESPONSE, RESOLUTION_RESPONSE, VRAM_LOCATION_ACK):
* require the type-specific payload before handing the buffer to
* the waiter.
*/
if (bytes_recvd < need) {
drm_err_ratelimited(&hv->dev,
"synthvid packet too small for type %u: %u < %zu\n",
msg->vid_hdr.type, bytes_recvd, need);
return;
}
memcpy(hv->init_buf, msg, bytes_recvd);
complete(&hv->wait);
}
static void hyperv_receive(void *ctx)
@@ -461,9 +526,21 @@ static void hyperv_receive(void *ctx)
ret = vmbus_recvpacket(hdev->channel, recv_buf,
VMBUS_MAX_PACKET_SIZE,
&bytes_recvd, &req_id);
if (bytes_recvd > 0 &&
recv_buf->pipe_hdr.type == PIPE_MSG_DATA)
hyperv_receive_sub(hdev);
if (ret) {
/*
* A nonzero return (e.g. -ENOBUFS for an oversized
* packet) is itself a malformed message: bytes_recvd
* then reports the required length rather than a copied
* payload, so it must not be forwarded to the
* sub-handler. Channel recovery is not attempted.
*/
drm_err_ratelimited(&hv->dev,
"vmbus_recvpacket failed: %d (need %u)\n",
ret, bytes_recvd);
} else if (bytes_recvd > 0 &&
recv_buf->pipe_hdr.type == PIPE_MSG_DATA) {
hyperv_receive_sub(hdev, bytes_recvd);
}
} while (bytes_recvd > 0 && ret == 0);
}
@@ -508,9 +585,13 @@ int hyperv_connect_vsp(struct hv_device *hdev)
ret = hyperv_get_supported_resolution(hdev);
if (ret)
drm_err(dev, "Failed to get supported resolution from host, use default\n");
} else {
}
if (!hv->screen_width_max) {
hv->screen_width_max = SYNTHVID_WIDTH_WIN8;
hv->screen_height_max = SYNTHVID_HEIGHT_WIN8;
hv->preferred_width = SYNTHVID_WIDTH_WIN8;
hv->preferred_height = SYNTHVID_HEIGHT_WIN8;
}
hv->mmio_megabytes = hdev->channel->offermsg.offer.mmio_megabytes;

View File

@@ -3976,7 +3976,7 @@ xelpd_program_plane_pre_csc_lut(struct intel_dsb *dsb,
intel_de_write_dsb(display, dsb,
PLANE_PRE_CSC_GAMC_DATA_ENH(pipe, plane, 0),
(1 << 24));
} while (i++ > 130);
} while (i++ < 130);
} else {
for (i = 0; i < lut_size; i++) {
u32 v = (i * ((1 << 24) - 1)) / (lut_size - 1);

View File

@@ -497,6 +497,7 @@ struct intel_display {
u8 vblank_enabled;
int vblank_enable_count;
bool vblank_status_last_notified;
struct work_struct vblank_notify_work;

View File

@@ -1773,8 +1773,12 @@ static void intel_display_vblank_notify_work(struct work_struct *work)
struct intel_display *display =
container_of(work, typeof(*display), irq.vblank_notify_work);
int vblank_enable_count = READ_ONCE(display->irq.vblank_enable_count);
bool vblank_status = !!vblank_enable_count;
intel_psr_notify_vblank_enable_disable(display, vblank_enable_count);
if (display->irq.vblank_status_last_notified != vblank_status) {
intel_psr_notify_vblank_enable_disable(display, vblank_status);
display->irq.vblank_status_last_notified = vblank_status;
}
}
int bdw_enable_vblank(struct drm_crtc *_crtc)
@@ -1787,10 +1791,10 @@ int bdw_enable_vblank(struct drm_crtc *_crtc)
if (gen11_dsi_configure_te(crtc, true))
return 0;
spin_lock_irqsave(&display->irq.lock, irqflags);
if (crtc->vblank_psr_notify && display->irq.vblank_enable_count++ == 0)
schedule_work(&display->irq.vblank_notify_work);
spin_lock_irqsave(&display->irq.lock, irqflags);
bdw_enable_pipe_irq(display, pipe, GEN8_PIPE_VBLANK);
spin_unlock_irqrestore(&display->irq.lock, irqflags);

View File

@@ -1790,6 +1790,8 @@ struct intel_psr {
u8 active_non_psr_pipes;
const char *no_psr_reason;
struct ref_tracker *vblank_wakeref;
};
struct intel_dp {

View File

@@ -12,6 +12,7 @@
#include "intel_dp.h"
#include "intel_dp_aux.h"
#include "intel_dp_aux_regs.h"
#include "intel_parent.h"
#include "intel_pps.h"
#include "intel_quirks.h"
#include "intel_tc.h"
@@ -60,18 +61,29 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp)
struct intel_display *display = to_intel_display(intel_dp);
i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
const unsigned int timeout_ms = 10;
bool done = true;
u32 status;
bool done;
int ret;
if (intel_parent_irq_enabled(display)) {
#define C (((status = intel_de_read_notrace(display, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
done = wait_event_timeout(display->gmbus.wait_queue, C,
msecs_to_jiffies_timeout(timeout_ms));
done = wait_event_timeout(display->gmbus.wait_queue, C,
msecs_to_jiffies_timeout(timeout_ms));
#undef C
} else {
ret = intel_de_wait_ms(display, ch_ctl,
DP_AUX_CH_CTL_SEND_BUSY, 0,
timeout_ms, &status);
if (ret == -ETIMEDOUT)
done = false;
}
if (!done)
drm_err(display->drm,
"%s: did not complete or timeout within %ums (status 0x%08x)\n",
intel_dp->aux.name, timeout_ms, status);
#undef C
return status;
}

View File

@@ -4156,27 +4156,22 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
mutex_lock(&intel_dp->psr.lock);
if (intel_dp->psr.panel_replay_enabled) {
mutex_unlock(&intel_dp->psr.lock);
break;
if (CAN_PANEL_REPLAY(intel_dp)) {
if (enable)
intel_dp->psr.vblank_wakeref =
intel_display_power_get(display,
POWER_DOMAIN_DC_OFF);
else
intel_display_power_put(display, POWER_DOMAIN_DC_OFF,
intel_dp->psr.vblank_wakeref);
}
if (intel_dp->psr.enabled && intel_dp->psr.pkg_c_latency_used)
if (intel_dp->psr.enabled && !intel_dp->psr.panel_replay_enabled &&
intel_dp->psr.pkg_c_latency_used)
intel_psr_apply_underrun_on_idle_wa_locked(intel_dp);
mutex_unlock(&intel_dp->psr.lock);
return;
}
/*
* NOTE: intel_display_power_set_target_dc_state is used
* only by PSR * code for DC3CO handling. DC3CO target
* state is currently disabled in * PSR code. If DC3CO
* is taken into use we need take that into account here
* as well.
*/
intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
DC_STATE_EN_UPTO_DC6);
}
static void

View File

@@ -419,8 +419,6 @@ void i915_ttm_free_cached_io_rsgt(struct drm_i915_gem_object *obj)
int i915_ttm_purge(struct drm_i915_gem_object *obj)
{
struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
struct i915_ttm_tt *i915_tt =
container_of(bo->ttm, typeof(*i915_tt), ttm);
struct ttm_operation_ctx ctx = {
.interruptible = true,
.no_wait_gpu = false,
@@ -435,16 +433,22 @@ int i915_ttm_purge(struct drm_i915_gem_object *obj)
if (ret)
return ret;
if (bo->ttm && i915_tt->filp) {
/*
* The below fput(which eventually calls shmem_truncate) might
* be delayed by worker, so when directly called to purge the
* pages(like by the shrinker) we should try to be more
* aggressive and release the pages immediately.
*/
shmem_truncate_range(file_inode(i915_tt->filp),
0, (loff_t)-1);
fput(fetch_and_zero(&i915_tt->filp));
if (bo->ttm) {
struct i915_ttm_tt *i915_tt =
container_of(bo->ttm, typeof(*i915_tt), ttm);
if (i915_tt->filp) {
/*
* The below fput(which eventually calls shmem_truncate)
* might be delayed by worker, so when directly called
* to purge the pages(like by the shrinker) we should
* try to be more aggressive and release the pages
* immediately.
*/
shmem_truncate_range(file_inode(i915_tt->filp),
0, (loff_t)-1);
fput(fetch_and_zero(&i915_tt->filp));
}
}
obj->write_domain = 0;

View File

@@ -767,6 +767,11 @@ static unsigned int guc_mmio_regset_write(struct xe_guc_ads *ads,
}
}
if (XE_GT_WA(hwe->gt, 16023105232))
guc_mmio_regset_write_one(ads, regset_map,
RING_IDLEDLY(hwe->mmio_base),
count++);
return count;
}

View File

@@ -117,7 +117,7 @@
/* timeout for pm runtime autosuspend */
#define DAVINCI_I2C_PM_TIMEOUT 1000 /* ms */
#define DAVINCI_I2C_DEFAULT_BUS_FREQ 100
#define DAVINCI_I2C_DEFAULT_BUS_FREQ 100000
struct davinci_i2c_dev {
struct device *dev;

View File

@@ -222,6 +222,8 @@ static int virtio_i2c_probe(struct virtio_device *vdev)
*/
ACPI_COMPANION_SET(&vi->adap.dev, ACPI_COMPANION(vdev->dev.parent));
virtio_device_ready(vdev);
ret = i2c_add_adapter(&vi->adap);
if (ret)
virtio_i2c_del_vqs(vdev);

View File

@@ -876,14 +876,14 @@ static int ad4695_offload_buffer_postenable(struct iio_dev *indio_dev)
if (ret)
goto err_unoptimize_message;
ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
&config);
ret = ad4695_enter_advanced_sequencer_mode(st, num_slots);
if (ret)
goto err_disable_busy_output;
ret = ad4695_enter_advanced_sequencer_mode(st, num_slots);
ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
&config);
if (ret)
goto err_offload_trigger_disable;
goto err_exit_conversion_mode;
mutex_lock(&st->cnv_pwm_lock);
pwm_get_state(st->cnv_pwm, &state);
@@ -895,23 +895,16 @@ static int ad4695_offload_buffer_postenable(struct iio_dev *indio_dev)
ret = pwm_apply_might_sleep(st->cnv_pwm, &state);
mutex_unlock(&st->cnv_pwm_lock);
if (ret)
goto err_offload_exit_conversion_mode;
goto err_offload_trigger_disable;
return 0;
err_offload_exit_conversion_mode:
/*
* We have to unwind in a different order to avoid triggering offload.
* ad4695_exit_conversion_mode() triggers a conversion, so it has to be
* done after spi_offload_trigger_disable().
*/
spi_offload_trigger_disable(st->offload, st->offload_trigger);
ad4695_exit_conversion_mode(st);
goto err_disable_busy_output;
err_offload_trigger_disable:
spi_offload_trigger_disable(st->offload, st->offload_trigger);
err_exit_conversion_mode:
ad4695_exit_conversion_mode(st);
err_disable_busy_output:
regmap_clear_bits(st->regmap, AD4695_REG_GP_MODE,
AD4695_REG_GP_MODE_BUSY_GP_EN);

View File

@@ -817,9 +817,11 @@ static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
}
priv->tsc_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "amlogic,hhi-sysctrl");
if (IS_ERR(priv->tsc_regmap))
if (IS_ERR(priv->tsc_regmap)) {
kfree(buf);
return dev_err_probe(dev, PTR_ERR(priv->tsc_regmap),
"failed to get amlogic,hhi-sysctrl regmap\n");
}
trimming_bits = priv->param->temperature_trimming_bits;
trimming_mask = BIT(trimming_bits) - 1;

View File

@@ -497,6 +497,7 @@ static int mt6358_read_imp(struct mt6359_auxadc *adc_dev,
return ret;
/* Read the params before stopping */
val_v = 0;
regmap_read(regmap, reg_adc0 + (cinfo->imp_adc_num << 1), &val_v);
mt6358_stop_imp_conv(adc_dev);

View File

@@ -231,7 +231,7 @@ static int npcm_adc_probe(struct platform_device *pdev)
if (IS_ERR(info->reset))
return PTR_ERR(info->reset);
info->adc_clk = devm_clk_get(&pdev->dev, NULL);
info->adc_clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(info->adc_clk)) {
dev_warn(&pdev->dev, "ADC clock failed: can't read clk\n");
return PTR_ERR(info->adc_clk);
@@ -244,17 +244,13 @@ static int npcm_adc_probe(struct platform_device *pdev)
info->adc_sample_hz = clk_get_rate(info->adc_clk) / ((div + 1) * 2);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
ret = irq;
goto err_disable_clk;
}
if (irq < 0)
return irq;
ret = devm_request_irq(&pdev->dev, irq, npcm_adc_isr, 0,
"NPCM_ADC", indio_dev);
if (ret < 0) {
dev_err(dev, "failed requesting interrupt\n");
goto err_disable_clk;
}
if (ret < 0)
return ret;
reg_con = ioread32(info->regs + NPCM_ADCCON);
info->vref = devm_regulator_get_optional(&pdev->dev, "vref");
@@ -262,7 +258,7 @@ static int npcm_adc_probe(struct platform_device *pdev)
ret = regulator_enable(info->vref);
if (ret) {
dev_err(&pdev->dev, "Can't enable ADC reference voltage\n");
goto err_disable_clk;
return ret;
}
iowrite32(reg_con & ~NPCM_ADCCON_REFSEL,
@@ -272,10 +268,8 @@ static int npcm_adc_probe(struct platform_device *pdev)
* Any error which is not ENODEV indicates the regulator
* has been specified and so is a failure case.
*/
if (PTR_ERR(info->vref) != -ENODEV) {
ret = PTR_ERR(info->vref);
goto err_disable_clk;
}
if (PTR_ERR(info->vref) != -ENODEV)
return PTR_ERR(info->vref);
/* Use internal reference */
iowrite32(reg_con | NPCM_ADCCON_REFSEL,
@@ -314,8 +308,6 @@ static int npcm_adc_probe(struct platform_device *pdev)
iowrite32(reg_con & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
if (!IS_ERR(info->vref))
regulator_disable(info->vref);
err_disable_clk:
clk_disable_unprepare(info->adc_clk);
return ret;
}
@@ -332,7 +324,6 @@ static void npcm_adc_remove(struct platform_device *pdev)
iowrite32(regtemp & ~NPCM_ADCCON_ADC_EN, info->regs + NPCM_ADCCON);
if (!IS_ERR(info->vref))
regulator_disable(info->vref);
clk_disable_unprepare(info->adc_clk);
}
static struct platform_driver npcm_adc_driver = {

View File

@@ -198,6 +198,15 @@ static void nxp_sar_adc_irq_cfg(struct nxp_sar_adc *info, bool enable)
writel(0, NXP_SAR_ADC_IMR(info->regs));
}
static void nxp_sar_adc_wait_for(struct nxp_sar_adc *info, unsigned int cycles)
{
u64 rate;
rate = clk_get_rate(info->clk);
if (rate)
ndelay(div64_u64(NSEC_PER_SEC, rate * cycles));
}
static bool nxp_sar_adc_set_enabled(struct nxp_sar_adc *info, bool enable)
{
u32 mcr;
@@ -221,7 +230,7 @@ static bool nxp_sar_adc_set_enabled(struct nxp_sar_adc *info, bool enable)
* configuration of NCMR and the setting of NSTART.
*/
if (enable)
ndelay(div64_u64(NSEC_PER_SEC, clk_get_rate(info->clk) * 3));
nxp_sar_adc_wait_for(info, 3);
return pwdn;
}
@@ -469,7 +478,7 @@ static void nxp_sar_adc_stop_conversion(struct nxp_sar_adc *info)
* only when the capture finishes. The delay will be very
* short, usec-ish, which is acceptable in the atomic context.
*/
ndelay(div64_u64(NSEC_PER_SEC, clk_get_rate(info->clk)) * 80);
nxp_sar_adc_wait_for(info, 80);
}
static int nxp_sar_adc_start_conversion(struct nxp_sar_adc *info, bool raw)
@@ -560,6 +569,9 @@ static int nxp_sar_adc_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
if (val <= 0)
return -EINVAL;
/*
* Configures the sample period duration in terms of the SAR
* controller clock. The minimum acceptable value is 8.
@@ -568,7 +580,11 @@ static int nxp_sar_adc_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec
* sampling timing which gives us the number of cycles expected.
* The value is 8-bit wide, consequently the max value is 0xFF.
*/
inpsamp = clk_get_rate(info->clk) / val - NXP_SAR_ADC_CONV_TIME;
inpsamp = clk_get_rate(info->clk) / val;
if (inpsamp < NXP_SAR_ADC_CONV_TIME)
return -EINVAL;
inpsamp -= NXP_SAR_ADC_CONV_TIME;
nxp_sar_adc_conversion_timing_set(info, inpsamp);
return 0;
@@ -660,7 +676,7 @@ static void nxp_sar_adc_dma_cb(void *data)
static int nxp_sar_adc_start_cyclic_dma(struct iio_dev *indio_dev)
{
struct nxp_sar_adc *info = iio_priv(indio_dev);
struct dma_slave_config config;
struct dma_slave_config config = { };
struct dma_async_tx_descriptor *desc;
int ret;

View File

@@ -482,7 +482,7 @@ static int adc5_gen3_get_fw_channel_data(struct adc5_chip *adc,
sid = FIELD_GET(ADC5_GEN3_VIRTUAL_SID_MASK, chan);
chan = FIELD_GET(ADC5_GEN3_CHANNEL_MASK, chan);
if (chan > ADC5_MAX_CHANNEL)
if (chan >= ADC5_MAX_CHANNEL)
return dev_err_probe(dev, -EINVAL,
"%s invalid channel number %d\n",
name, chan);

View File

@@ -70,8 +70,10 @@ static int vprbrd_iio_read_raw(struct iio_dev *iio_dev,
VPRBRD_USB_TYPE_OUT, 0x0000, 0x0000, admsg,
sizeof(struct vprbrd_adc_msg), VPRBRD_USB_TIMEOUT_MS);
if (ret != sizeof(struct vprbrd_adc_msg)) {
dev_err(&iio_dev->dev, "usb send error on adc read\n");
mutex_unlock(&vb->lock);
error = -EREMOTEIO;
dev_err(&iio_dev->dev, "usb send error on adc read\n");
goto error;
}
ret = usb_control_msg(vb->usb_dev,

View File

@@ -817,6 +817,7 @@ static int xadc_postdisable(struct iio_dev *indio_dev)
{
struct xadc *xadc = iio_priv(indio_dev);
unsigned long scan_mask;
int seq_mode;
int ret;
int i;
@@ -824,6 +825,12 @@ static int xadc_postdisable(struct iio_dev *indio_dev)
for (i = 0; i < indio_dev->num_channels; i++)
scan_mask |= BIT(indio_dev->channels[i].scan_index);
/*
* Use the correct sequencer mode for the idle state: simultaneous
* mode for dual external mux configurations, continuous otherwise.
*/
seq_mode = xadc_get_seq_mode(xadc, scan_mask);
/* Enable all channels and calibration */
ret = xadc_write_adc_reg(xadc, XADC_REG_SEQ(0), scan_mask & 0xffff);
if (ret)
@@ -834,11 +841,11 @@ static int xadc_postdisable(struct iio_dev *indio_dev)
return ret;
ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_SEQ_MASK,
XADC_CONF1_SEQ_CONTINUOUS);
seq_mode);
if (ret)
return ret;
return xadc_power_adc_b(xadc, XADC_CONF1_SEQ_CONTINUOUS);
return xadc_power_adc_b(xadc, seq_mode);
}
static int xadc_preenable(struct iio_dev *indio_dev)

View File

@@ -85,7 +85,7 @@ static struct hw_consumer_buffer *iio_hw_consumer_get_buffer(
*/
struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev)
{
struct hw_consumer_buffer *buf;
struct hw_consumer_buffer *buf, *tmp;
struct iio_hw_consumer *hwc;
struct iio_channel *chan;
int ret;
@@ -116,7 +116,7 @@ struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev)
return hwc;
err_put_buffers:
list_for_each_entry(buf, &hwc->buffers, head)
list_for_each_entry_safe(buf, tmp, &hwc->buffers, head)
iio_buffer_put(&buf->buffer);
iio_channel_release_all(hwc->channels);
err_free_hwc:

View File

@@ -52,6 +52,8 @@ struct mhz19b_state {
struct completion buf_ready;
u8 buf_idx;
bool buf_overflow;
/*
* Serdev receive buffer.
* When data is received from the MH-Z19B,
@@ -106,6 +108,10 @@ static int mhz19b_serdev_cmd(struct iio_dev *indio_dev, int cmd, u16 arg)
cmd_buf[8] = mhz19b_get_checksum(cmd_buf);
/* Write buf to uart ctrl synchronously */
st->buf_idx = 0;
st->buf_overflow = false;
reinit_completion(&st->buf_ready);
ret = serdev_device_write(serdev, cmd_buf, MHZ19B_CMD_SIZE, 0);
if (ret < 0)
return ret;
@@ -121,6 +127,9 @@ static int mhz19b_serdev_cmd(struct iio_dev *indio_dev, int cmd, u16 arg)
if (!ret)
return -ETIMEDOUT;
if (st->buf_overflow)
return -EMSGSIZE;
if (st->buf[8] != mhz19b_get_checksum(st->buf)) {
dev_err(dev, "checksum err");
return -EINVAL;
@@ -240,6 +249,14 @@ static size_t mhz19b_receive_buf(struct serdev_device *serdev,
{
struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev);
struct mhz19b_state *st = iio_priv(indio_dev);
size_t remaining = MHZ19B_CMD_SIZE - st->buf_idx;
if (len > remaining) {
st->buf_idx = 0;
st->buf_overflow = true;
complete(&st->buf_ready);
return len;
}
memcpy(st->buf + st->buf_idx, data, len);
st->buf_idx += len;

View File

@@ -256,7 +256,7 @@ static int scd30_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const
guard(mutex)(&state->lock);
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
if (val)
if (val || !val2)
return -EINVAL;
val = 1000000000 / val2;

View File

@@ -590,6 +590,7 @@ static void ssp_remove(struct spi_device *spi)
ssp_clean_pending_list(data);
free_irq(data->spi->irq, data);
cancel_delayed_work_sync(&data->work_refresh);
timer_delete_sync(&data->wdt_timer);
cancel_work_sync(&data->work_wdt);

View File

@@ -105,6 +105,12 @@ static const char * const ad3530r_powerdown_modes[] = {
"32kohm_to_gnd",
};
static const char * const ad3531r_powerdown_modes[] = {
"500ohm_to_gnd",
"3.85kohm_to_gnd",
"16kohm_to_gnd",
};
static int ad3530r_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
@@ -133,6 +139,13 @@ static const struct iio_enum ad3530r_powerdown_mode_enum = {
.set = ad3530r_set_powerdown_mode,
};
static const struct iio_enum ad3531r_powerdown_mode_enum = {
.items = ad3531r_powerdown_modes,
.num_items = ARRAY_SIZE(ad3531r_powerdown_modes),
.get = ad3530r_get_powerdown_mode,
.set = ad3530r_set_powerdown_mode,
};
static ssize_t ad3530r_get_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
@@ -276,7 +289,20 @@ static const struct iio_chan_spec_ext_info ad3530r_ext_info[] = {
{ }
};
#define AD3530R_CHAN(_chan) \
static const struct iio_chan_spec_ext_info ad3531r_ext_info[] = {
{
.name = "powerdown",
.shared = IIO_SEPARATE,
.read = ad3530r_get_dac_powerdown,
.write = ad3530r_set_dac_powerdown,
},
IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad3531r_powerdown_mode_enum),
IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
&ad3531r_powerdown_mode_enum),
{ }
};
#define AD3530R_CHAN(_chan, _ext_info) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
@@ -284,25 +310,25 @@ static const struct iio_chan_spec_ext_info ad3530r_ext_info[] = {
.output = 1, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \
.ext_info = ad3530r_ext_info, \
.ext_info = _ext_info, \
}
static const struct iio_chan_spec ad3530r_channels[] = {
AD3530R_CHAN(0),
AD3530R_CHAN(1),
AD3530R_CHAN(2),
AD3530R_CHAN(3),
AD3530R_CHAN(4),
AD3530R_CHAN(5),
AD3530R_CHAN(6),
AD3530R_CHAN(7),
AD3530R_CHAN(0, ad3530r_ext_info),
AD3530R_CHAN(1, ad3530r_ext_info),
AD3530R_CHAN(2, ad3530r_ext_info),
AD3530R_CHAN(3, ad3530r_ext_info),
AD3530R_CHAN(4, ad3530r_ext_info),
AD3530R_CHAN(5, ad3530r_ext_info),
AD3530R_CHAN(6, ad3530r_ext_info),
AD3530R_CHAN(7, ad3530r_ext_info),
};
static const struct iio_chan_spec ad3531r_channels[] = {
AD3530R_CHAN(0),
AD3530R_CHAN(1),
AD3530R_CHAN(2),
AD3530R_CHAN(3),
AD3530R_CHAN(0, ad3531r_ext_info),
AD3530R_CHAN(1, ad3531r_ext_info),
AD3530R_CHAN(2, ad3531r_ext_info),
AD3530R_CHAN(3, ad3531r_ext_info),
};
static const struct ad3530r_chip_info ad3530_chip = {

View File

@@ -25,22 +25,37 @@ static const char * const ad5686_powerdown_modes[] = {
"three_state"
};
static inline unsigned int ad5686_pd_mask_shift(const struct iio_chan_spec *chan)
{
if (chan->channel == chan->address)
return chan->channel * 2;
/* one-hot encoding is used in dual/quad channel devices */
return __ffs(chan->address) * 2;
}
static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan)
{
unsigned int shift = ad5686_pd_mask_shift(chan);
struct ad5686_state *st = iio_priv(indio_dev);
return ((st->pwr_down_mode >> (chan->channel * 2)) & 0x3) - 1;
guard(mutex)(&st->lock);
return ((st->pwr_down_mode >> shift) & 0x3U) - 1;
}
static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
unsigned int mode)
{
unsigned int shift = ad5686_pd_mask_shift(chan);
struct ad5686_state *st = iio_priv(indio_dev);
st->pwr_down_mode &= ~(0x3 << (chan->channel * 2));
st->pwr_down_mode |= ((mode + 1) << (chan->channel * 2));
guard(mutex)(&st->lock);
st->pwr_down_mode &= ~(0x3U << shift);
st->pwr_down_mode |= (mode + 1) << shift;
return 0;
}
@@ -55,10 +70,12 @@ static const struct iio_enum ad5686_powerdown_mode_enum = {
static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan, char *buf)
{
unsigned int shift = ad5686_pd_mask_shift(chan);
struct ad5686_state *st = iio_priv(indio_dev);
return sysfs_emit(buf, "%d\n", !!(st->pwr_down_mask &
(0x3 << (chan->channel * 2))));
guard(mutex)(&st->lock);
return sysfs_emit(buf, "%d\n", !!(st->pwr_down_mask & (0x3U << shift)));
}
static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
@@ -77,10 +94,12 @@ static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
if (ret)
return ret;
guard(mutex)(&st->lock);
if (readin)
st->pwr_down_mask |= (0x3 << (chan->channel * 2));
st->pwr_down_mask |= 0x3U << ad5686_pd_mask_shift(chan);
else
st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
st->pwr_down_mask &= ~(0x3U << ad5686_pd_mask_shift(chan));
switch (st->chip_info->regmap_type) {
case AD5310_REGMAP:
@@ -154,7 +173,7 @@ static int ad5686_write_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (val > (1 << chan->scan_type.realbits) || val < 0)
if (val >= (1 << chan->scan_type.realbits) || val < 0)
return -EINVAL;
mutex_lock(&st->lock);
@@ -460,7 +479,7 @@ int ad5686_probe(struct device *dev,
{
struct ad5686_state *st;
struct iio_dev *indio_dev;
unsigned int val, ref_bit_msk;
unsigned int val, ref_bit_msk, shift;
bool has_external_vref;
u8 cmd;
int ret, i;
@@ -484,9 +503,18 @@ int ad5686_probe(struct device *dev,
has_external_vref = ret != -ENODEV;
st->vref_mv = has_external_vref ? ret / 1000 : st->chip_info->int_vref_mv;
/* Initialize masks to all ones provided the max shift (last channel) */
shift = ad5686_pd_mask_shift(&st->chip_info->channels[st->chip_info->num_channels - 1]);
st->pwr_down_mask = GENMASK(shift + 1, 0);
st->pwr_down_mode = GENMASK(shift + 1, 0);
/* Set all the power down mode for all channels to 1K pulldown */
for (i = 0; i < st->chip_info->num_channels; i++)
st->pwr_down_mode |= (0x01 << (i * 2));
for (i = 0; i < st->chip_info->num_channels; i++) {
shift = ad5686_pd_mask_shift(&st->chip_info->channels[i]);
st->pwr_down_mask &= ~(0x3U << shift); /* powered up state */
st->pwr_down_mode &= ~(0x3U << shift);
st->pwr_down_mode |= 0x01U << shift;
}
indio_dev->name = name;
indio_dev->info = &ad5686_info;
@@ -509,7 +537,7 @@ int ad5686_probe(struct device *dev,
break;
case AD5686_REGMAP:
cmd = AD5686_CMD_INTERNAL_REFER_SETUP;
ref_bit_msk = 0;
ref_bit_msk = AD5686_REF_BIT_MSK;
break;
case AD5693_REGMAP:
cmd = AD5686_CMD_CONTROL_REG;
@@ -520,9 +548,9 @@ int ad5686_probe(struct device *dev,
return -EINVAL;
}
val = (has_external_vref | ref_bit_msk);
val = has_external_vref ? ref_bit_msk : 0;
ret = st->write(st, cmd, 0, !!val);
ret = st->write(st, cmd, 0, val);
if (ret)
return ret;

View File

@@ -46,6 +46,7 @@
#define AD5310_REF_BIT_MSK BIT(8)
#define AD5683_REF_BIT_MSK BIT(12)
#define AD5686_REF_BIT_MSK BIT(0)
#define AD5693_REF_BIT_MSK BIT(12)
/**

View File

@@ -90,6 +90,7 @@ static int max5821_sync_powerdown_mode(struct max5821_data *data,
const struct iio_chan_spec *chan)
{
u8 outbuf[2];
int ret;
outbuf[0] = MAX5821_EXTENDED_COMMAND_MODE;
@@ -103,7 +104,13 @@ static int max5821_sync_powerdown_mode(struct max5821_data *data,
else
outbuf[1] |= MAX5821_EXTENDED_POWER_UP;
return i2c_master_send(data->client, outbuf, 2);
ret = i2c_master_send(data->client, outbuf, sizeof(outbuf));
if (ret < 0)
return ret;
if (ret != sizeof(outbuf))
return -EIO;
return 0;
}
static ssize_t max5821_write_dac_powerdown(struct iio_dev *indio_dev,

View File

@@ -287,6 +287,9 @@ static int adis16260_write_raw(struct iio_dev *indio_dev,
addr = adis16260_addresses[chan->scan_index][1];
return adis_write_reg_16(adis, addr, val);
case IIO_CHAN_INFO_SAMP_FREQ:
if (val <= 0)
return -EINVAL;
if (spi_get_device_id(adis->spi)->driver_data)
t = 256 / val;
else

View File

@@ -34,7 +34,7 @@ static int itg3200_read_all_channels(struct i2c_client *i2c, __be16 *buf)
.addr = i2c->addr,
.flags = i2c->flags | I2C_M_RD,
.len = ITG3200_SCAN_ELEMENTS * sizeof(s16),
.buf = (char *)&buf,
.buf = (char *)buf,
},
};

View File

@@ -836,7 +836,7 @@ static irqreturn_t adis16550_trigger_handler(int irq, void *p)
u16 dummy;
bool valid;
struct iio_poll_func *pf = p;
__be32 data[ADIS16550_MAX_SCAN_DATA] __aligned(8);
__be32 data[ADIS16550_MAX_SCAN_DATA] __aligned(8) = { };
struct iio_dev *indio_dev = pf->indio_dev;
struct adis16550 *st = iio_priv(indio_dev);
struct adis *adis = iio_device_get_drvdata(indio_dev);

View File

@@ -609,7 +609,7 @@ int st_lsm6dsx_read_tagged_fifo(struct st_lsm6dsx_hw *hw)
* must be passed a buffer that is aligned to 8 bytes so
* as to allow insertion of a naturally aligned timestamp.
*/
u8 iio_buff[ST_LSM6DSX_IIO_BUFF_SIZE] __aligned(8);
u8 iio_buff[ST_LSM6DSX_IIO_BUFF_SIZE] __aligned(8) = { };
u8 tag;
bool reset_ts = false;
int i, err, read_len;

View File

@@ -1909,6 +1909,7 @@ static int iio_buffer_enqueue_dmabuf(struct iio_dev_buffer_pair *ib,
dma_resv_add_fence(dmabuf->resv, &fence->base,
dma_to_ram ? DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ);
dma_fence_put(&fence->base);
dma_resv_unlock(dmabuf->resv);
cookie = dma_fence_begin_signalling();

View File

@@ -738,7 +738,11 @@ int iio_read_channel_processed_scale(struct iio_channel *chan, int *val,
if (ret < 0)
return ret;
return iio_multiply_value(val, scale, ret, pval, pval2);
ret = iio_multiply_value(val, scale, ret, pval, pval2);
if (ret < 0)
return ret;
return 0;
} else {
ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
if (ret < 0)

View File

@@ -89,15 +89,14 @@ static int cm3323_init(struct iio_dev *indio_dev)
/* enable sensor and set auto force mode */
ret &= ~(CM3323_CONF_SD_BIT | CM3323_CONF_AF_BIT);
data->reg_conf = ret;
ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, ret);
ret = i2c_smbus_write_word_data(data->client, CM3323_CMD_CONF, data->reg_conf);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_conf\n");
return ret;
}
data->reg_conf = ret;
return 0;
}

View File

@@ -245,13 +245,6 @@ static const struct iio_info veml6070_info = {
.write_raw = veml6070_write_raw,
};
static void veml6070_i2c_unreg(void *p)
{
struct veml6070_data *data = p;
i2c_unregister_device(data->client2);
}
static int veml6070_probe(struct i2c_client *client)
{
struct veml6070_data *data;
@@ -281,7 +274,8 @@ static int veml6070_probe(struct i2c_client *client)
if (ret < 0)
return ret;
data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB);
data->client2 = devm_i2c_new_dummy_device(&client->dev, client->adapter,
VEML6070_ADDR_DATA_LSB);
if (IS_ERR(data->client2))
return dev_err_probe(&client->dev, PTR_ERR(data->client2),
"i2c device for second chip address failed\n");
@@ -292,10 +286,6 @@ static int veml6070_probe(struct i2c_client *client)
if (ret < 0)
return ret;
ret = devm_add_action_or_reset(&client->dev, veml6070_i2c_unreg, data);
if (ret < 0)
return ret;
return devm_iio_device_register(&client->dev, indio_dev);
}

View File

@@ -506,6 +506,11 @@ static const struct st_sensors_platform_data default_magn_pdata = {
.drdy_int_pin = 2,
};
/* LIS2MDL only supports DRDY on INT1 */
static const struct st_sensors_platform_data alt_magn_pdata = {
.drdy_int_pin = 1,
};
static int st_magn_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *ch, int *val,
int *val2, long mask)
@@ -628,8 +633,12 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
mdata->current_fullscale = &mdata->sensor_settings->fs.fs_avl[0];
mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz;
if (!pdata)
pdata = (struct st_sensors_platform_data *)&default_magn_pdata;
if (!pdata) {
if (mdata->sensor_settings->drdy_irq.int2.mask)
pdata = (struct st_sensors_platform_data *)&default_magn_pdata;
else
pdata = (struct st_sensors_platform_data *)&alt_magn_pdata;
}
err = st_sensors_init_sensor(indio_dev, pdata);
if (err < 0)

View File

@@ -2616,7 +2616,7 @@ static irqreturn_t bmp580_trigger_handler(int irq, void *p)
__le32 comp_temp;
__le32 comp_press;
aligned_s64 timestamp;
} buffer;
} buffer = { };
int ret;
guard(mutex)(&data->lock);

View File

@@ -119,7 +119,7 @@ static bool tsys01_crc_valid(u16 *n_prom)
u8 sum = 0;
for (cnt = 0; cnt < TSYS01_PROM_WORDS_NB; cnt++)
sum += ((n_prom[0] >> 8) + (n_prom[0] & 0xFF));
sum += ((n_prom[cnt] >> 8) + (n_prom[cnt] & 0xFF));
return (sum == 0);
}

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