mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
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.ccb9959ab5f("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.ca342c99cb7("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.c093305d801("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.cb38cae85d1("net: airoha: Fix use-after-free in metadata dst teardown")ec6c391bcc("net: airoha: Introduce airoha_gdm_dev struct") drivers/net/ethernet/microchip/lan743x_main.c8173d22b21("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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -25,6 +25,7 @@ properties:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,ipq5018-snand
|
||||
- qcom,ipq5210-snand
|
||||
- qcom,ipq5332-snand
|
||||
- qcom,ipq5424-snand
|
||||
- const: qcom,ipq9574-snand
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
2
Makefile
2
Makefile
@@ -2,7 +2,7 @@
|
||||
VERSION = 7
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc6
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
@@ -146,7 +146,7 @@ flash@30000000 {
|
||||
partitions {
|
||||
compatible = "redboot-fis";
|
||||
/* Eraseblock at 0xfe0000 */
|
||||
fis-index-block = <0x1fc>;
|
||||
fis-index-block = <0x7f>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ flash@30000000 {
|
||||
partitions {
|
||||
compatible = "redboot-fis";
|
||||
/* Eraseblock at 0xfe0000 */
|
||||
fis-index-block = <0x1fc>;
|
||||
fis-index-block = <0x7f>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user