Merge tag 'ASB-2024-12-05_4.19-stable' of https://android.googlesource.com/kernel/common into android13-4.19-kona

https://source.android.com/docs/security/bulletin/2024-12-01

* tag 'ASB-2024-12-05_4.19-stable' of https://android.googlesource.com/kernel/common: (401 commits)
  Linux 4.19.324
  9p: fix slab cache name creation for real
  net: usb: qmi_wwan: add Fibocom FG132 0x0112 composition
  fs: Fix uninitialized value issue in from_kuid and from_kgid
  powerpc/powernv: Free name on error in opal_event_init()
  sound: Make CONFIG_SND depend on INDIRECT_IOMEM instead of UML
  bpf: use kvzmalloc to allocate BPF verifier environment
  HID: multitouch: Add quirk for HONOR MagicBook Art 14 touchpad
  9p: Avoid creating multiple slab caches with the same name
  ALSA: usb-audio: Add endianness annotations
  vsock/virtio: Initialization of the dangling pointer occurring in vsk->trans
  hv_sock: Initializing vsk->trans to NULL to prevent a dangling pointer
  ALSA: usb-audio: Add quirks for Dell WD19 dock
  ALSA: usb-audio: Support jack detection on Dell dock
  ALSA: usb-audio: Add custom mixer status quirks for RME CC devices
  ALSA: pcm: Return 0 when size < start_threshold in capture
  ocfs2: remove entry once instead of null-ptr-dereference in ocfs2_xa_remove()
  irqchip/gic-v3: Force propagation of the active state with a read-back
  USB: serial: option: add Quectel RG650V
  USB: serial: option: add Fibocom FG132 0x0112 composition
  ...

 Conflicts:
	drivers/usb/dwc3/core.c
	drivers/usb/dwc3/core.h
	net/qrtr/qrtr.c

Change-Id: I328847813eb875d25c4aa35dcc7ba58ad09b53ae
This commit is contained in:
Michael Bestas
2024-12-16 01:21:42 +02:00
364 changed files with 3311 additions and 1871 deletions

1
.gitignore vendored
View File

@@ -114,7 +114,6 @@ GTAGS
# id-utils files # id-utils files
ID ID
*.orig
*~ *~
\#*# \#*#

View File

@@ -518,7 +518,7 @@ at module load time (for a module) with::
[dbg_probe=1] [dbg_probe=1]
The addresses are normal I2C addresses. The adapter is the string The addresses are normal I2C addresses. The adapter is the string
name of the adapter, as shown in /sys/class/i2c-adapter/i2c-<n>/name. name of the adapter, as shown in /sys/bus/i2c/devices/i2c-<n>/name.
It is *NOT* i2c-<n> itself. Also, the comparison is done ignoring It is *NOT* i2c-<n> itself. Also, the comparison is done ignoring
spaces, so if the name is "This is an I2C chip" you can say spaces, so if the name is "This is an I2C chip" you can say
adapter_name=ThisisanI2cchip. This is because it's hard to pass in adapter_name=ThisisanI2cchip. This is because it's hard to pass in

View File

@@ -66,6 +66,7 @@ stable kernels.
| ARM | Cortex-A78 | #3324344 | ARM64_ERRATUM_3194386 | | ARM | Cortex-A78 | #3324344 | ARM64_ERRATUM_3194386 |
| ARM | Cortex-A78C | #3324346,3324347| ARM64_ERRATUM_3194386 | | ARM | Cortex-A78C | #3324346,3324347| ARM64_ERRATUM_3194386 |
| ARM | Cortex-A710 | #3324338 | ARM64_ERRATUM_3194386 | | ARM | Cortex-A710 | #3324338 | ARM64_ERRATUM_3194386 |
| ARM | Cortex-A715 | #3456084 | ARM64_ERRATUM_3194386 |
| ARM | Cortex-A720 | #3456091 | ARM64_ERRATUM_3194386 | | ARM | Cortex-A720 | #3456091 | ARM64_ERRATUM_3194386 |
| ARM | Cortex-A725 | #3456106 | ARM64_ERRATUM_3194386 | | ARM | Cortex-A725 | #3456106 | ARM64_ERRATUM_3194386 |
| ARM | Cortex-X1 | #3324344 | ARM64_ERRATUM_3194386 | | ARM | Cortex-X1 | #3324344 | ARM64_ERRATUM_3194386 |
@@ -78,6 +79,7 @@ stable kernels.
| ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 | | ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 |
| ARM | Neoverse-N1 | #3324349 | ARM64_ERRATUM_3194386 | | ARM | Neoverse-N1 | #3324349 | ARM64_ERRATUM_3194386 |
| ARM | Neoverse-N2 | #3324339 | ARM64_ERRATUM_3194386 | | ARM | Neoverse-N2 | #3324339 | ARM64_ERRATUM_3194386 |
| ARM | Neoverse-N3 | #3456111 | ARM64_ERRATUM_3194386 |
| ARM | Neoverse-V1 | #3324341 | ARM64_ERRATUM_3194386 | | ARM | Neoverse-V1 | #3324341 | ARM64_ERRATUM_3194386 |
| ARM | Neoverse-V2 | #3324336 | ARM64_ERRATUM_3194386 | | ARM | Neoverse-V2 | #3324336 | ARM64_ERRATUM_3194386 |
| ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3194386 | | ARM | Neoverse-V3 | #3312417 | ARM64_ERRATUM_3194386 |

View File

@@ -235,6 +235,7 @@ certainly invest a bit more effort into libata core layer).
CLOCK CLOCK
devm_clk_get() devm_clk_get()
devm_clk_get_optional()
devm_clk_put() devm_clk_put()
devm_clk_hw_register() devm_clk_hw_register()
devm_of_clk_add_hw_provider() devm_of_clk_add_hw_provider()

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
VERSION = 4 VERSION = 4
PATCHLEVEL = 19 PATCHLEVEL = 19
SUBLEVEL = 322 SUBLEVEL = 324
EXTRAVERSION = EXTRAVERSION =
NAME = "People's Front" NAME = "People's Front"

View File

@@ -300,8 +300,8 @@
&i2c2 { &i2c2 {
status = "okay"; status = "okay";
rt5616: rt5616@1b { rt5616: audio-codec@1b {
compatible = "rt5616"; compatible = "realtek,rt5616";
reg = <0x1b>; reg = <0x1b>;
clocks = <&cru SCLK_I2S_OUT>; clocks = <&cru SCLK_I2S_OUT>;
clock-names = "mclk"; clock-names = "mclk";

View File

@@ -316,12 +316,13 @@
}; };
}; };
acodec: acodec-ana@20030000 { acodec: audio-codec@20030000 {
compatible = "rk3036-codec"; compatible = "rockchip,rk3036-codec";
reg = <0x20030000 0x4000>; reg = <0x20030000 0x4000>;
rockchip,grf = <&grf>;
clock-names = "acodec_pclk"; clock-names = "acodec_pclk";
clocks = <&cru PCLK_ACODEC>; clocks = <&cru PCLK_ACODEC>;
rockchip,grf = <&grf>;
#sound-dai-cells = <0>;
status = "disabled"; status = "disabled";
}; };
@@ -331,7 +332,6 @@
interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_HDMI>; clocks = <&cru PCLK_HDMI>;
clock-names = "pclk"; clock-names = "pclk";
rockchip,grf = <&grf>;
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&hdmi_ctl>; pinctrl-0 = <&hdmi_ctl>;
status = "disabled"; status = "disabled";

View File

@@ -70,6 +70,7 @@ static void __init realview_smp_prepare_cpus(unsigned int max_cpus)
return; return;
} }
map = syscon_node_to_regmap(np); map = syscon_node_to_regmap(np);
of_node_put(np);
if (IS_ERR(map)) { if (IS_ERR(map)) {
pr_err("PLATSMP: No syscon regmap\n"); pr_err("PLATSMP: No syscon regmap\n");
return; return;

View File

@@ -591,6 +591,7 @@ config ARM64_ERRATUM_3194386
* ARM Cortex-A78C erratum 3324346 * ARM Cortex-A78C erratum 3324346
* ARM Cortex-A78C erratum 3324347 * ARM Cortex-A78C erratum 3324347
* ARM Cortex-A710 erratam 3324338 * ARM Cortex-A710 erratam 3324338
* ARM Cortex-A715 errartum 3456084
* ARM Cortex-A720 erratum 3456091 * ARM Cortex-A720 erratum 3456091
* ARM Cortex-A725 erratum 3456106 * ARM Cortex-A725 erratum 3456106
* ARM Cortex-X1 erratum 3324344 * ARM Cortex-X1 erratum 3324344
@@ -601,6 +602,7 @@ config ARM64_ERRATUM_3194386
* ARM Cortex-X925 erratum 3324334 * ARM Cortex-X925 erratum 3324334
* ARM Neoverse-N1 erratum 3324349 * ARM Neoverse-N1 erratum 3324349
* ARM Neoverse N2 erratum 3324339 * ARM Neoverse N2 erratum 3324339
* ARM Neoverse-N3 erratum 3456111
* ARM Neoverse-V1 erratum 3324341 * ARM Neoverse-V1 erratum 3324341
* ARM Neoverse V2 erratum 3324336 * ARM Neoverse V2 erratum 3324336
* ARM Neoverse-V3 erratum 3312417 * ARM Neoverse-V3 erratum 3312417

View File

@@ -147,6 +147,22 @@
status = "okay"; status = "okay";
}; };
&gpio3 {
/*
* The Qseven BIOS_DISABLE signal on the RK3399-Q7 keeps the on-module
* eMMC and SPI flash powered-down initially (in fact it keeps the
* reset signal asserted). BIOS_DISABLE_OVERRIDE pin allows to override
* that signal so that eMMC and SPI can be used regardless of the state
* of the signal.
*/
bios-disable-override-hog {
gpios = <RK_PD5 GPIO_ACTIVE_LOW>;
gpio-hog;
line-name = "bios_disable_override";
output-high;
};
};
&gmac { &gmac {
assigned-clocks = <&cru SCLK_RMII_SRC>; assigned-clocks = <&cru SCLK_RMII_SRC>;
assigned-clock-parents = <&clkin_gmac>; assigned-clock-parents = <&clkin_gmac>;
@@ -433,9 +449,14 @@
&pinctrl { &pinctrl {
pinctrl-names = "default"; pinctrl-names = "default";
pinctrl-0 = <&q7_thermal_pin>; pinctrl-0 = <&q7_thermal_pin &bios_disable_override_hog_pin>;
gpios { gpios {
bios_disable_override_hog_pin: bios-disable-override-hog-pin {
rockchip,pins =
<3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>;
};
q7_thermal_pin: q7-thermal-pin { q7_thermal_pin: q7-thermal-pin {
rockchip,pins = rockchip,pins =
<0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;

View File

@@ -123,7 +123,7 @@
status = "okay"; status = "okay";
rt5651: rt5651@1a { rt5651: rt5651@1a {
compatible = "rockchip,rt5651"; compatible = "realtek,rt5651";
reg = <0x1a>; reg = <0x1a>;
clocks = <&cru SCLK_I2S_8CH_OUT>; clocks = <&cru SCLK_I2S_8CH_OUT>;
clock-names = "mclk"; clock-names = "mclk";

View File

@@ -89,6 +89,7 @@
#define ARM_CPU_PART_CORTEX_A78 0xD41 #define ARM_CPU_PART_CORTEX_A78 0xD41
#define ARM_CPU_PART_CORTEX_X1 0xD44 #define ARM_CPU_PART_CORTEX_X1 0xD44
#define ARM_CPU_PART_CORTEX_A710 0xD47 #define ARM_CPU_PART_CORTEX_A710 0xD47
#define ARM_CPU_PART_CORTEX_A715 0xD4D
#define ARM_CPU_PART_CORTEX_X2 0xD48 #define ARM_CPU_PART_CORTEX_X2 0xD48
#define ARM_CPU_PART_NEOVERSE_N2 0xD49 #define ARM_CPU_PART_NEOVERSE_N2 0xD49
#define ARM_CPU_PART_CORTEX_A78C 0xD4B #define ARM_CPU_PART_CORTEX_A78C 0xD4B
@@ -108,6 +109,7 @@
#define ARM_CPU_PART_NEOVERSE_V3 0xD84 #define ARM_CPU_PART_NEOVERSE_V3 0xD84
#define ARM_CPU_PART_CORTEX_X925 0xD85 #define ARM_CPU_PART_CORTEX_X925 0xD85
#define ARM_CPU_PART_CORTEX_A725 0xD87 #define ARM_CPU_PART_CORTEX_A725 0xD87
#define ARM_CPU_PART_NEOVERSE_N3 0xD8E
#define APM_CPU_PART_POTENZA 0x000 #define APM_CPU_PART_POTENZA 0x000
@@ -142,6 +144,7 @@
#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78) #define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78)
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
#define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715)
#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2) #define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C) #define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
@@ -161,6 +164,7 @@
#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3) #define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925) #define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725) #define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725)
#define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX) #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)

View File

@@ -13,21 +13,19 @@
#include <asm/insn.h> #include <asm/insn.h>
#include <asm/probes.h> #include <asm/probes.h>
#define MAX_UINSN_BYTES AARCH64_INSN_SIZE #define UPROBE_SWBP_INSN cpu_to_le32(BRK64_OPCODE_UPROBES)
#define UPROBE_SWBP_INSN BRK64_OPCODE_UPROBES
#define UPROBE_SWBP_INSN_SIZE AARCH64_INSN_SIZE #define UPROBE_SWBP_INSN_SIZE AARCH64_INSN_SIZE
#define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES #define UPROBE_XOL_SLOT_BYTES AARCH64_INSN_SIZE
typedef u32 uprobe_opcode_t; typedef __le32 uprobe_opcode_t;
struct arch_uprobe_task { struct arch_uprobe_task {
}; };
struct arch_uprobe { struct arch_uprobe {
union { union {
u8 insn[MAX_UINSN_BYTES]; __le32 insn;
u8 ixol[MAX_UINSN_BYTES]; __le32 ixol;
}; };
struct arch_probe_insn api; struct arch_probe_insn api;
bool simulate; bool simulate;

View File

@@ -763,6 +763,7 @@ static const struct midr_range erratum_spec_ssbs_list[] = {
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A715),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), MIDR_ALL_VERSIONS(MIDR_CORTEX_A720),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A725), MIDR_ALL_VERSIONS(MIDR_CORTEX_A725),
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
@@ -773,6 +774,7 @@ static const struct midr_range erratum_spec_ssbs_list[] = {
MIDR_ALL_VERSIONS(MIDR_CORTEX_X925), MIDR_ALL_VERSIONS(MIDR_CORTEX_X925),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N3),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),

View File

@@ -104,10 +104,6 @@ arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *api)
aarch64_insn_is_blr(insn) || aarch64_insn_is_blr(insn) ||
aarch64_insn_is_ret(insn)) { aarch64_insn_is_ret(insn)) {
api->handler = simulate_br_blr_ret; api->handler = simulate_br_blr_ret;
} else if (aarch64_insn_is_ldr_lit(insn)) {
api->handler = simulate_ldr_literal;
} else if (aarch64_insn_is_ldrsw_lit(insn)) {
api->handler = simulate_ldrsw_literal;
} else { } else {
/* /*
* Instruction cannot be stepped out-of-line and we don't * Instruction cannot be stepped out-of-line and we don't
@@ -145,6 +141,17 @@ arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi)
probe_opcode_t insn = le32_to_cpu(*addr); probe_opcode_t insn = le32_to_cpu(*addr);
probe_opcode_t *scan_end = NULL; probe_opcode_t *scan_end = NULL;
unsigned long size = 0, offset = 0; unsigned long size = 0, offset = 0;
struct arch_probe_insn *api = &asi->api;
if (aarch64_insn_is_ldr_lit(insn)) {
api->handler = simulate_ldr_literal;
decoded = INSN_GOOD_NO_SLOT;
} else if (aarch64_insn_is_ldrsw_lit(insn)) {
api->handler = simulate_ldrsw_literal;
decoded = INSN_GOOD_NO_SLOT;
} else {
decoded = arm_probe_decode_insn(insn, &asi->api);
}
/* /*
* If there's a symbol defined in front of and near enough to * If there's a symbol defined in front of and near enough to
@@ -162,7 +169,6 @@ arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi)
else else
scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE; scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE;
} }
decoded = arm_probe_decode_insn(insn, &asi->api);
if (decoded != INSN_REJECTED && scan_end) if (decoded != INSN_REJECTED && scan_end)
if (is_probed_address_atomic(addr - 1, scan_end)) if (is_probed_address_atomic(addr - 1, scan_end))

View File

@@ -178,17 +178,15 @@ simulate_tbz_tbnz(u32 opcode, long addr, struct pt_regs *regs)
void __kprobes void __kprobes
simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs) simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs)
{ {
u64 *load_addr; unsigned long load_addr;
int xn = opcode & 0x1f; int xn = opcode & 0x1f;
int disp;
disp = ldr_displacement(opcode); load_addr = addr + ldr_displacement(opcode);
load_addr = (u64 *) (addr + disp);
if (opcode & (1 << 30)) /* x0-x30 */ if (opcode & (1 << 30)) /* x0-x30 */
set_x_reg(regs, xn, *load_addr); set_x_reg(regs, xn, READ_ONCE(*(u64 *)load_addr));
else /* w0-w30 */ else /* w0-w30 */
set_w_reg(regs, xn, *load_addr); set_w_reg(regs, xn, READ_ONCE(*(u32 *)load_addr));
instruction_pointer_set(regs, instruction_pointer(regs) + 4); instruction_pointer_set(regs, instruction_pointer(regs) + 4);
} }
@@ -196,14 +194,12 @@ simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs)
void __kprobes void __kprobes
simulate_ldrsw_literal(u32 opcode, long addr, struct pt_regs *regs) simulate_ldrsw_literal(u32 opcode, long addr, struct pt_regs *regs)
{ {
s32 *load_addr; unsigned long load_addr;
int xn = opcode & 0x1f; int xn = opcode & 0x1f;
int disp;
disp = ldr_displacement(opcode); load_addr = addr + ldr_displacement(opcode);
load_addr = (s32 *) (addr + disp);
set_x_reg(regs, xn, *load_addr); set_x_reg(regs, xn, READ_ONCE(*(s32 *)load_addr));
instruction_pointer_set(regs, instruction_pointer(regs) + 4); instruction_pointer_set(regs, instruction_pointer(regs) + 4);
} }

View File

@@ -45,7 +45,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE)) else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE))
return -EINVAL; return -EINVAL;
insn = *(probe_opcode_t *)(&auprobe->insn[0]); insn = le32_to_cpu(auprobe->insn);
switch (arm_probe_decode_insn(insn, &auprobe->api)) { switch (arm_probe_decode_insn(insn, &auprobe->api)) {
case INSN_REJECTED: case INSN_REJECTED:
@@ -111,7 +111,7 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
if (!auprobe->simulate) if (!auprobe->simulate)
return false; return false;
insn = *(probe_opcode_t *)(&auprobe->insn[0]); insn = le32_to_cpu(auprobe->insn);
addr = instruction_pointer(regs); addr = instruction_pointer(regs);
if (auprobe->api.handler) if (auprobe->api.handler)

View File

@@ -289,11 +289,6 @@ asmlinkage void __init mmu_init(void)
{ {
unsigned int kstart, ksize; unsigned int kstart, ksize;
if (!memblock.reserved.cnt) {
pr_emerg("Error memory count\n");
machine_restart(NULL);
}
if ((u32) memblock.memory.regions[0].size < 0x400000) { if ((u32) memblock.memory.regions[0].size < 0x400000) {
pr_emerg("Memory must be greater than 4MB\n"); pr_emerg("Memory must be greater than 4MB\n");
machine_restart(NULL); machine_restart(NULL);

View File

@@ -1089,8 +1089,7 @@ ENTRY_CFI(intr_save) /* for os_hpmc */
STREG %r16, PT_ISR(%r29) STREG %r16, PT_ISR(%r29)
STREG %r17, PT_IOR(%r29) STREG %r17, PT_IOR(%r29)
#if 0 && defined(CONFIG_64BIT) #if defined(CONFIG_64BIT)
/* Revisit when we have 64-bit code above 4Gb */
b,n intr_save2 b,n intr_save2
skip_save_ior: skip_save_ior:
@@ -1098,8 +1097,7 @@ skip_save_ior:
* need to adjust iasq/iaoq here in the same way we adjusted isr/ior * need to adjust iasq/iaoq here in the same way we adjusted isr/ior
* above. * above.
*/ */
extrd,u,* %r8,PSW_W_BIT,1,%r1 bb,COND(>=),n %r8,PSW_W_BIT,intr_save2
cmpib,COND(=),n 1,%r1,intr_save2
LDREG PT_IASQ0(%r29), %r16 LDREG PT_IASQ0(%r29), %r16
LDREG PT_IAOQ0(%r29), %r17 LDREG PT_IAOQ0(%r29), %r17
/* adjust iasq/iaoq */ /* adjust iasq/iaoq */

View File

@@ -217,10 +217,10 @@ linux_gateway_entry:
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
ldil L%sys_call_table, %r1 ldil L%sys_call_table, %r1
or,= %r2,%r2,%r2 or,ev %r2,%r2,%r2
addil L%(sys_call_table64-sys_call_table), %r1 ldil L%sys_call_table64, %r1
ldo R%sys_call_table(%r1), %r19 ldo R%sys_call_table(%r1), %r19
or,= %r2,%r2,%r2 or,ev %r2,%r2,%r2
ldo R%sys_call_table64(%r1), %r19 ldo R%sys_call_table64(%r1), %r19
#else #else
load32 sys_call_table, %r19 load32 sys_call_table, %r19
@@ -355,10 +355,10 @@ tracesys_next:
extrd,u %r19,63,1,%r2 /* W hidden in bottom bit */ extrd,u %r19,63,1,%r2 /* W hidden in bottom bit */
ldil L%sys_call_table, %r1 ldil L%sys_call_table, %r1
or,= %r2,%r2,%r2 or,ev %r2,%r2,%r2
addil L%(sys_call_table64-sys_call_table), %r1 ldil L%sys_call_table64, %r1
ldo R%sys_call_table(%r1), %r19 ldo R%sys_call_table(%r1), %r19
or,= %r2,%r2,%r2 or,ev %r2,%r2,%r2
ldo R%sys_call_table64(%r1), %r19 ldo R%sys_call_table64(%r1), %r19
#else #else
load32 sys_call_table, %r19 load32 sys_call_table, %r19
@@ -930,6 +930,8 @@ ENTRY(sys_call_table)
END(sys_call_table) END(sys_call_table)
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
#undef __SYSCALL_WITH_COMPAT
#define __SYSCALL_WITH_COMPAT(nr, native, compat) __SYSCALL(nr, native)
.align 8 .align 8
ENTRY(sys_call_table64) ENTRY(sys_call_table64)
#define SYSCALL_TABLE_64BIT #define SYSCALL_TABLE_64BIT

View File

@@ -289,6 +289,7 @@ int __init opal_event_init(void)
name, NULL); name, NULL);
if (rc) { if (rc) {
pr_warn("Error %d requesting OPAL irq %d\n", rc, (int)r->start); pr_warn("Error %d requesting OPAL irq %d\n", rc, (int)r->start);
kfree(name);
continue; continue;
} }
} }

View File

@@ -84,6 +84,11 @@ config GENERIC_CSUM
config GENERIC_HWEIGHT config GENERIC_HWEIGHT
def_bool y def_bool y
config ILLEGAL_POINTER_VALUE
hex
default 0 if 32BIT
default 0xdead000000000000 if 64BIT
config PGTABLE_LEVELS config PGTABLE_LEVELS
int int
default 3 if 64BIT default 3 if 64BIT

View File

@@ -53,8 +53,10 @@ static inline int test_facility(unsigned long nr)
unsigned long facilities_als[] = { FACILITIES_ALS }; unsigned long facilities_als[] = { FACILITIES_ALS };
if (__builtin_constant_p(nr) && nr < sizeof(facilities_als) * 8) { if (__builtin_constant_p(nr) && nr < sizeof(facilities_als) * 8) {
if (__test_facility(nr, &facilities_als)) if (__test_facility(nr, &facilities_als)) {
return 1; if (!__is_defined(__DECOMPRESSOR))
return 1;
}
} }
return __test_facility(nr, &S390_lowcore.stfle_fac_list); return __test_facility(nr, &S390_lowcore.stfle_fac_list);
} }

View File

@@ -1360,7 +1360,7 @@ static int aux_output_begin(struct perf_output_handle *handle,
unsigned long head, base, offset; unsigned long head, base, offset;
struct hws_trailer_entry *te; struct hws_trailer_entry *te;
if (WARN_ON_ONCE(handle->head & ~PAGE_MASK)) if (handle->head & ~PAGE_MASK)
return -EINVAL; return -EINVAL;
aux->head = handle->head >> PAGE_SHIFT; aux->head = handle->head >> PAGE_SHIFT;
@@ -1528,7 +1528,7 @@ static void hw_collect_aux(struct cpu_hw_sf *cpuhw)
unsigned long num_sdb; unsigned long num_sdb;
aux = perf_get_aux(handle); aux = perf_get_aux(handle);
if (WARN_ON_ONCE(!aux)) if (!aux)
return; return;
/* Inform user space new data arrived */ /* Inform user space new data arrived */
@@ -1547,7 +1547,7 @@ static void hw_collect_aux(struct cpu_hw_sf *cpuhw)
debug_sprintf_event(sfdbg, 1, "AUX buffer used up\n"); debug_sprintf_event(sfdbg, 1, "AUX buffer used up\n");
break; break;
} }
if (WARN_ON_ONCE(!aux)) if (!aux)
return; return;
/* Update head and alert_mark to new position */ /* Update head and alert_mark to new position */
@@ -1746,12 +1746,8 @@ static void cpumsf_pmu_start(struct perf_event *event, int flags)
{ {
struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf); struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf);
if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) if (!(event->hw.state & PERF_HES_STOPPED))
return; return;
if (flags & PERF_EF_RELOAD)
WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
perf_pmu_disable(event->pmu); perf_pmu_disable(event->pmu);
event->hw.state = 0; event->hw.state = 0;
cpuhw->lsctl.cs = 1; cpuhw->lsctl.cs = 1;

View File

@@ -78,7 +78,7 @@ static int __diag_page_ref_service(struct kvm_vcpu *vcpu)
vcpu->stat.diagnose_258++; vcpu->stat.diagnose_258++;
if (vcpu->run->s.regs.gprs[rx] & 7) if (vcpu->run->s.regs.gprs[rx] & 7)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
rc = read_guest(vcpu, vcpu->run->s.regs.gprs[rx], rx, &parm, sizeof(parm)); rc = read_guest_real(vcpu, vcpu->run->s.regs.gprs[rx], &parm, sizeof(parm));
if (rc) if (rc)
return kvm_s390_inject_prog_cond(vcpu, rc); return kvm_s390_inject_prog_cond(vcpu, rc);
if (parm.parm_version != 2 || parm.parm_len < 5 || parm.code != 0x258) if (parm.parm_version != 2 || parm.parm_len < 5 || parm.code != 0x258)

View File

@@ -794,46 +794,102 @@ static int low_address_protection_enabled(struct kvm_vcpu *vcpu,
return 1; return 1;
} }
static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, /**
unsigned long *pages, unsigned long nr_pages, * guest_range_to_gpas() - Calculate guest physical addresses of page fragments
const union asce asce, enum gacc_mode mode) * covering a logical range
* @vcpu: virtual cpu
* @ga: guest address, start of range
* @ar: access register
* @gpas: output argument, may be NULL
* @len: length of range in bytes
* @asce: address-space-control element to use for translation
* @mode: access mode
*
* Translate a logical range to a series of guest absolute addresses,
* such that the concatenation of page fragments starting at each gpa make up
* the whole range.
* The translation is performed as if done by the cpu for the given @asce, @ar,
* @mode and state of the @vcpu.
* If the translation causes an exception, its program interruption code is
* returned and the &struct kvm_s390_pgm_info pgm member of @vcpu is modified
* such that a subsequent call to kvm_s390_inject_prog_vcpu() will inject
* a correct exception into the guest.
* The resulting gpas are stored into @gpas, unless it is NULL.
*
* Note: All fragments except the first one start at the beginning of a page.
* When deriving the boundaries of a fragment from a gpa, all but the last
* fragment end at the end of the page.
*
* Return:
* * 0 - success
* * <0 - translation could not be performed, for example if guest
* memory could not be accessed
* * >0 - an access exception occurred. In this case the returned value
* is the program interruption code and the contents of pgm may
* be used to inject an exception into the guest.
*/
static int guest_range_to_gpas(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
unsigned long *gpas, unsigned long len,
const union asce asce, enum gacc_mode mode)
{ {
psw_t *psw = &vcpu->arch.sie_block->gpsw; psw_t *psw = &vcpu->arch.sie_block->gpsw;
unsigned int offset = offset_in_page(ga);
unsigned int fragment_len;
int lap_enabled, rc = 0; int lap_enabled, rc = 0;
enum prot_type prot; enum prot_type prot;
unsigned long gpa;
lap_enabled = low_address_protection_enabled(vcpu, asce); lap_enabled = low_address_protection_enabled(vcpu, asce);
while (nr_pages) { while (min(PAGE_SIZE - offset, len) > 0) {
fragment_len = min(PAGE_SIZE - offset, len);
ga = kvm_s390_logical_to_effective(vcpu, ga); ga = kvm_s390_logical_to_effective(vcpu, ga);
if (mode == GACC_STORE && lap_enabled && is_low_address(ga)) if (mode == GACC_STORE && lap_enabled && is_low_address(ga))
return trans_exc(vcpu, PGM_PROTECTION, ga, ar, mode, return trans_exc(vcpu, PGM_PROTECTION, ga, ar, mode,
PROT_TYPE_LA); PROT_TYPE_LA);
ga &= PAGE_MASK;
if (psw_bits(*psw).dat) { if (psw_bits(*psw).dat) {
rc = guest_translate(vcpu, ga, pages, asce, mode, &prot); rc = guest_translate(vcpu, ga, &gpa, asce, mode, &prot);
if (rc < 0) if (rc < 0)
return rc; return rc;
} else { } else {
*pages = kvm_s390_real_to_abs(vcpu, ga); gpa = kvm_s390_real_to_abs(vcpu, ga);
if (kvm_is_error_gpa(vcpu->kvm, *pages)) if (kvm_is_error_gpa(vcpu->kvm, gpa))
rc = PGM_ADDRESSING; rc = PGM_ADDRESSING;
} }
if (rc) if (rc)
return trans_exc(vcpu, rc, ga, ar, mode, prot); return trans_exc(vcpu, rc, ga, ar, mode, prot);
ga += PAGE_SIZE; if (gpas)
pages++; *gpas++ = gpa;
nr_pages--; offset = 0;
ga += fragment_len;
len -= fragment_len;
} }
return 0; return 0;
} }
static int access_guest_page(struct kvm *kvm, enum gacc_mode mode, gpa_t gpa,
void *data, unsigned int len)
{
const unsigned int offset = offset_in_page(gpa);
const gfn_t gfn = gpa_to_gfn(gpa);
int rc;
if (!gfn_to_memslot(kvm, gfn))
return PGM_ADDRESSING;
if (mode == GACC_STORE)
rc = kvm_write_guest_page(kvm, gfn, data, offset, len);
else
rc = kvm_read_guest_page(kvm, gfn, data, offset, len);
return rc;
}
int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,
unsigned long len, enum gacc_mode mode) unsigned long len, enum gacc_mode mode)
{ {
psw_t *psw = &vcpu->arch.sie_block->gpsw; psw_t *psw = &vcpu->arch.sie_block->gpsw;
unsigned long _len, nr_pages, gpa, idx; unsigned long nr_pages, idx;
unsigned long pages_array[2]; unsigned long gpa_array[2];
unsigned long *pages; unsigned int fragment_len;
unsigned long *gpas;
int need_ipte_lock; int need_ipte_lock;
union asce asce; union asce asce;
int rc; int rc;
@@ -845,50 +901,45 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,
if (rc) if (rc)
return rc; return rc;
nr_pages = (((ga & ~PAGE_MASK) + len - 1) >> PAGE_SHIFT) + 1; nr_pages = (((ga & ~PAGE_MASK) + len - 1) >> PAGE_SHIFT) + 1;
pages = pages_array; gpas = gpa_array;
if (nr_pages > ARRAY_SIZE(pages_array)) if (nr_pages > ARRAY_SIZE(gpa_array))
pages = vmalloc(array_size(nr_pages, sizeof(unsigned long))); gpas = vmalloc(array_size(nr_pages, sizeof(unsigned long)));
if (!pages) if (!gpas)
return -ENOMEM; return -ENOMEM;
need_ipte_lock = psw_bits(*psw).dat && !asce.r; need_ipte_lock = psw_bits(*psw).dat && !asce.r;
if (need_ipte_lock) if (need_ipte_lock)
ipte_lock(vcpu); ipte_lock(vcpu);
rc = guest_page_range(vcpu, ga, ar, pages, nr_pages, asce, mode); rc = guest_range_to_gpas(vcpu, ga, ar, gpas, len, asce, mode);
for (idx = 0; idx < nr_pages && !rc; idx++) { for (idx = 0; idx < nr_pages && !rc; idx++) {
gpa = *(pages + idx) + (ga & ~PAGE_MASK); fragment_len = min(PAGE_SIZE - offset_in_page(gpas[idx]), len);
_len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len); rc = access_guest_page(vcpu->kvm, mode, gpas[idx], data, fragment_len);
if (mode == GACC_STORE) len -= fragment_len;
rc = kvm_write_guest(vcpu->kvm, gpa, data, _len); data += fragment_len;
else
rc = kvm_read_guest(vcpu->kvm, gpa, data, _len);
len -= _len;
ga += _len;
data += _len;
} }
if (need_ipte_lock) if (need_ipte_lock)
ipte_unlock(vcpu); ipte_unlock(vcpu);
if (nr_pages > ARRAY_SIZE(pages_array)) if (nr_pages > ARRAY_SIZE(gpa_array))
vfree(pages); vfree(gpas);
return rc; return rc;
} }
int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
void *data, unsigned long len, enum gacc_mode mode) void *data, unsigned long len, enum gacc_mode mode)
{ {
unsigned long _len, gpa; unsigned int fragment_len;
unsigned long gpa;
int rc = 0; int rc = 0;
while (len && !rc) { while (len && !rc) {
gpa = kvm_s390_real_to_abs(vcpu, gra); gpa = kvm_s390_real_to_abs(vcpu, gra);
_len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len); fragment_len = min(PAGE_SIZE - offset_in_page(gpa), len);
if (mode) rc = access_guest_page(vcpu->kvm, mode, gpa, data, fragment_len);
rc = write_guest_abs(vcpu, gpa, data, _len); len -= fragment_len;
else gra += fragment_len;
rc = read_guest_abs(vcpu, gpa, data, _len); data += fragment_len;
len -= _len;
gra += _len;
data += _len;
} }
if (rc > 0)
vcpu->arch.pgm.code = rc;
return rc; return rc;
} }
@@ -904,8 +955,6 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
unsigned long *gpa, enum gacc_mode mode) unsigned long *gpa, enum gacc_mode mode)
{ {
psw_t *psw = &vcpu->arch.sie_block->gpsw;
enum prot_type prot;
union asce asce; union asce asce;
int rc; int rc;
@@ -913,23 +962,7 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
rc = get_vcpu_asce(vcpu, &asce, gva, ar, mode); rc = get_vcpu_asce(vcpu, &asce, gva, ar, mode);
if (rc) if (rc)
return rc; return rc;
if (is_low_address(gva) && low_address_protection_enabled(vcpu, asce)) { return guest_range_to_gpas(vcpu, gva, ar, gpa, 1, asce, mode);
if (mode == GACC_STORE)
return trans_exc(vcpu, PGM_PROTECTION, gva, 0,
mode, PROT_TYPE_LA);
}
if (psw_bits(*psw).dat && !asce.r) { /* Use DAT? */
rc = guest_translate(vcpu, gva, gpa, asce, mode, &prot);
if (rc > 0)
return trans_exc(vcpu, rc, gva, 0, mode, prot);
} else {
*gpa = kvm_s390_real_to_abs(vcpu, gva);
if (kvm_is_error_gpa(vcpu->kvm, *gpa))
return trans_exc(vcpu, rc, gva, PGM_ADDRESSING, mode, 0);
}
return rc;
} }
/** /**
@@ -938,17 +971,14 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar, int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
unsigned long length, enum gacc_mode mode) unsigned long length, enum gacc_mode mode)
{ {
unsigned long gpa; union asce asce;
unsigned long currlen;
int rc = 0; int rc = 0;
rc = get_vcpu_asce(vcpu, &asce, gva, ar, mode);
if (rc)
return rc;
ipte_lock(vcpu); ipte_lock(vcpu);
while (length > 0 && !rc) { rc = guest_range_to_gpas(vcpu, gva, ar, NULL, length, asce, mode);
currlen = min(length, PAGE_SIZE - (gva % PAGE_SIZE));
rc = guest_translate_address(vcpu, gva, ar, &gpa, mode);
gva += currlen;
length -= currlen;
}
ipte_unlock(vcpu); ipte_unlock(vcpu);
return rc; return rc;

View File

@@ -344,11 +344,12 @@ int read_guest_abs(struct kvm_vcpu *vcpu, unsigned long gpa, void *data,
* @len: number of bytes to copy * @len: number of bytes to copy
* *
* Copy @len bytes from @data (kernel space) to @gra (guest real address). * Copy @len bytes from @data (kernel space) to @gra (guest real address).
* It is up to the caller to ensure that the entire guest memory range is
* valid memory before calling this function.
* Guest low address and key protection are not checked. * Guest low address and key protection are not checked.
* *
* Returns zero on success or -EFAULT on error. * Returns zero on success, -EFAULT when copying from @data failed, or
* PGM_ADRESSING in case @gra is outside a memslot. In this case, pgm check info
* is also stored to allow injecting into the guest (if applicable) using
* kvm_s390_inject_prog_cond().
* *
* If an error occurs data may have been copied partially to guest memory. * If an error occurs data may have been copied partially to guest memory.
*/ */
@@ -367,11 +368,12 @@ int write_guest_real(struct kvm_vcpu *vcpu, unsigned long gra, void *data,
* @len: number of bytes to copy * @len: number of bytes to copy
* *
* Copy @len bytes from @gra (guest real address) to @data (kernel space). * Copy @len bytes from @gra (guest real address) to @data (kernel space).
* It is up to the caller to ensure that the entire guest memory range is
* valid memory before calling this function.
* Guest key protection is not checked. * Guest key protection is not checked.
* *
* Returns zero on success or -EFAULT on error. * Returns zero on success, -EFAULT when copying to @data failed, or
* PGM_ADRESSING in case @gra is outside a memslot. In this case, pgm check info
* is also stored to allow injecting into the guest (if applicable) using
* kvm_s390_inject_prog_cond().
* *
* If an error occurs data may have been copied partially to kernel space. * If an error occurs data may have been copied partially to kernel space.
*/ */

View File

@@ -98,11 +98,12 @@ static long cmm_alloc_pages(long nr, long *counter,
(*counter)++; (*counter)++;
spin_unlock(&cmm_lock); spin_unlock(&cmm_lock);
nr--; nr--;
cond_resched();
} }
return nr; return nr;
} }
static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) static long __cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
{ {
struct cmm_page_array *pa; struct cmm_page_array *pa;
unsigned long addr; unsigned long addr;
@@ -126,6 +127,21 @@ static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
return nr; return nr;
} }
static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
{
long inc = 0;
while (nr) {
inc = min(256L, nr);
nr -= inc;
inc = __cmm_free_pages(inc, counter, list);
if (inc)
break;
cond_resched();
}
return nr + inc;
}
static int cmm_oom_notify(struct notifier_block *self, static int cmm_oom_notify(struct notifier_block *self,
unsigned long dummy, void *parm) unsigned long dummy, void *parm)
{ {

View File

@@ -216,7 +216,7 @@
#define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* "" Disable Speculative Store Bypass. */ #define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* "" Disable Speculative Store Bypass. */
#define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* "" AMD SSBD implementation via LS_CFG MSR */ #define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* "" AMD SSBD implementation via LS_CFG MSR */
#define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */ #define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */
#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ #define X86_FEATURE_IBPB ( 7*32+26) /* "ibpb" Indirect Branch Prediction Barrier without a guaranteed RSB flush */
#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ #define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */
#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */ #define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ #define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */
@@ -306,6 +306,7 @@
#define X86_FEATURE_VIRT_SSBD (13*32+25) /* Virtualized Speculative Store Bypass Disable */ #define X86_FEATURE_VIRT_SSBD (13*32+25) /* Virtualized Speculative Store Bypass Disable */
#define X86_FEATURE_AMD_SSB_NO (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */ #define X86_FEATURE_AMD_SSB_NO (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */
#define X86_FEATURE_BTC_NO (13*32+29) /* "" Not vulnerable to Branch Type Confusion */ #define X86_FEATURE_BTC_NO (13*32+29) /* "" Not vulnerable to Branch Type Confusion */
#define X86_FEATURE_AMD_IBPB_RET (13*32+30) /* "" IBPB clears return address predictor */
/* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */ /* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */
#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ #define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */

View File

@@ -484,7 +484,19 @@ static int lapic_timer_shutdown(struct clock_event_device *evt)
v = apic_read(APIC_LVTT); v = apic_read(APIC_LVTT);
v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR); v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
apic_write(APIC_LVTT, v); apic_write(APIC_LVTT, v);
apic_write(APIC_TMICT, 0);
/*
* Setting APIC_LVT_MASKED (above) should be enough to tell
* the hardware that this timer will never fire. But AMD
* erratum 411 and some Intel CPU behavior circa 2024 say
* otherwise. Time for belt and suspenders programming: mask
* the timer _and_ zero the counter registers:
*/
if (v & APIC_LVT_TIMER_TSCDEADLINE)
wrmsrl(MSR_IA32_TSC_DEADLINE, 0);
else
apic_write(APIC_TMICT, 0);
return 0; return 0;
} }

View File

@@ -243,6 +243,7 @@ static void __init ms_hyperv_init_platform(void)
ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) { ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
x86_platform.calibrate_tsc = hv_get_tsc_khz; x86_platform.calibrate_tsc = hv_get_tsc_khz;
x86_platform.calibrate_cpu = hv_get_tsc_khz; x86_platform.calibrate_cpu = hv_get_tsc_khz;
setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
} }
if (ms_hyperv.hints & HV_X64_ENLIGHTENED_VMCS_RECOMMENDED) { if (ms_hyperv.hints & HV_X64_ENLIGHTENED_VMCS_RECOMMENDED) {

View File

@@ -862,7 +862,7 @@ char * __init xen_memory_setup(void)
* to relocating (and even reusing) pages with kernel text or data. * to relocating (and even reusing) pages with kernel text or data.
*/ */
if (xen_is_e820_reserved(__pa_symbol(_text), if (xen_is_e820_reserved(__pa_symbol(_text),
__pa_symbol(__bss_stop) - __pa_symbol(_text))) { __pa_symbol(_end) - __pa_symbol(_text))) {
xen_raw_console_write("Xen hypervisor allocated kernel memory conflicts with E820 map\n"); xen_raw_console_write("Xen hypervisor allocated kernel memory conflicts with E820 map\n");
BUG(); BUG();
} }

View File

@@ -2226,8 +2226,12 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
struct bfq_queue *in_service_bfqq, *new_bfqq; struct bfq_queue *in_service_bfqq, *new_bfqq;
/* if a merge has already been setup, then proceed with that first */ /* if a merge has already been setup, then proceed with that first */
if (bfqq->new_bfqq) new_bfqq = bfqq->new_bfqq;
return bfqq->new_bfqq; if (new_bfqq) {
while (new_bfqq->new_bfqq)
new_bfqq = new_bfqq->new_bfqq;
return new_bfqq;
}
/* /*
* Prevent bfqq from being merged if it has been created too * Prevent bfqq from being merged if it has been created too
@@ -5033,7 +5037,7 @@ bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq)
{ {
bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue");
if (bfqq_process_refs(bfqq) == 1) { if (bfqq_process_refs(bfqq) == 1 && !bfqq->new_bfqq) {
bfqq->pid = current->pid; bfqq->pid = current->pid;
bfq_clear_bfqq_coop(bfqq); bfq_clear_bfqq_coop(bfqq);
bfq_clear_bfqq_split_coop(bfqq); bfq_clear_bfqq_split_coop(bfqq);
@@ -5218,7 +5222,8 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
* addition, if the queue has also just been split, we have to * addition, if the queue has also just been split, we have to
* resume its state. * resume its state.
*/ */
if (likely(bfqq != &bfqd->oom_bfqq) && bfqq_process_refs(bfqq) == 1) { if (likely(bfqq != &bfqd->oom_bfqq) && !bfqq->new_bfqq &&
bfqq_process_refs(bfqq) == 1) {
bfqq->bic = bic; bfqq->bic = bic;
if (split) { if (split) {
/* /*

View File

@@ -45,8 +45,7 @@ static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
memcpy(alignbuffer, key, keylen); memcpy(alignbuffer, key, keylen);
ret = crypto_aead_alg(tfm)->setkey(tfm, alignbuffer, keylen); ret = crypto_aead_alg(tfm)->setkey(tfm, alignbuffer, keylen);
memset(alignbuffer, 0, keylen); kzfree(buffer);
kfree(buffer);
return ret; return ret;
} }

View File

@@ -38,8 +38,7 @@ static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,
alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
memcpy(alignbuffer, key, keylen); memcpy(alignbuffer, key, keylen);
ret = cia->cia_setkey(tfm, alignbuffer, keylen); ret = cia->cia_setkey(tfm, alignbuffer, keylen);
memset(alignbuffer, 0, keylen); kzfree(buffer);
kfree(buffer);
return ret; return ret;
} }

View File

@@ -170,6 +170,8 @@ acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object)
elements = elements =
ACPI_ALLOCATE_ZEROED(DB_DEFAULT_PKG_ELEMENTS * ACPI_ALLOCATE_ZEROED(DB_DEFAULT_PKG_ELEMENTS *
sizeof(union acpi_object)); sizeof(union acpi_object));
if (!elements)
return (AE_NO_MEMORY);
this = string; this = string;
for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) { for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) {

View File

@@ -437,6 +437,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
if (info->connection_node) { if (info->connection_node) {
second_desc = info->connection_node->object; second_desc = info->connection_node->object;
if (second_desc == NULL) {
break;
}
if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) { if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) {
status = status =
acpi_ds_get_buffer_arguments(second_desc); acpi_ds_get_buffer_arguments(second_desc);

View File

@@ -25,6 +25,8 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state);
static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
*parser_state); *parser_state);
static void acpi_ps_free_field_list(union acpi_parse_object *start);
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ps_get_next_package_length * FUNCTION: acpi_ps_get_next_package_length
@@ -683,6 +685,39 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
return_PTR(field); return_PTR(field);
} }
/*******************************************************************************
*
* FUNCTION: acpi_ps_free_field_list
*
* PARAMETERS: start - First Op in field list
*
* RETURN: None.
*
* DESCRIPTION: Free all Op objects inside a field list.
*
******************************************************************************/
static void acpi_ps_free_field_list(union acpi_parse_object *start)
{
union acpi_parse_object *cur = start;
union acpi_parse_object *next;
union acpi_parse_object *arg;
while (cur) {
next = cur->common.next;
/* AML_INT_CONNECTION_OP can have a single argument */
arg = acpi_ps_get_arg(cur, 0);
if (arg) {
acpi_ps_free_op(arg);
}
acpi_ps_free_op(cur);
cur = next;
}
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ps_get_next_arg * FUNCTION: acpi_ps_get_next_arg
@@ -751,6 +786,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
while (parser_state->aml < parser_state->pkg_end) { while (parser_state->aml < parser_state->pkg_end) {
field = acpi_ps_get_next_field(parser_state); field = acpi_ps_get_next_field(parser_state);
if (!field) { if (!field) {
if (arg) {
acpi_ps_free_field_list(arg);
}
return_ACPI_STATUS(AE_NO_MEMORY); return_ACPI_STATUS(AE_NO_MEMORY);
} }
@@ -820,6 +859,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
acpi_ps_get_next_namepath(walk_state, parser_state, acpi_ps_get_next_namepath(walk_state, parser_state,
arg, arg,
ACPI_NOT_METHOD_CALL); ACPI_NOT_METHOD_CALL);
if (ACPI_FAILURE(status)) {
acpi_ps_free_op(arg);
return_ACPI_STATUS(status);
}
} else { } else {
/* Single complex argument, nothing returned */ /* Single complex argument, nothing returned */
@@ -854,6 +897,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
acpi_ps_get_next_namepath(walk_state, parser_state, acpi_ps_get_next_namepath(walk_state, parser_state,
arg, arg,
ACPI_POSSIBLE_METHOD_CALL); ACPI_POSSIBLE_METHOD_CALL);
if (ACPI_FAILURE(status)) {
acpi_ps_free_op(arg);
return_ACPI_STATUS(status);
}
if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) { if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) {

View File

@@ -713,27 +713,34 @@ static LIST_HEAD(acpi_battery_list);
static LIST_HEAD(battery_hook_list); static LIST_HEAD(battery_hook_list);
static DEFINE_MUTEX(hook_mutex); static DEFINE_MUTEX(hook_mutex);
static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock) static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook)
{ {
struct acpi_battery *battery; struct acpi_battery *battery;
/* /*
* In order to remove a hook, we first need to * In order to remove a hook, we first need to
* de-register all the batteries that are registered. * de-register all the batteries that are registered.
*/ */
if (lock)
mutex_lock(&hook_mutex);
list_for_each_entry(battery, &acpi_battery_list, list) { list_for_each_entry(battery, &acpi_battery_list, list) {
hook->remove_battery(battery->bat); hook->remove_battery(battery->bat);
} }
list_del(&hook->list); list_del_init(&hook->list);
if (lock)
mutex_unlock(&hook_mutex);
pr_info("extension unregistered: %s\n", hook->name); pr_info("extension unregistered: %s\n", hook->name);
} }
void battery_hook_unregister(struct acpi_battery_hook *hook) void battery_hook_unregister(struct acpi_battery_hook *hook)
{ {
__battery_hook_unregister(hook, 1); mutex_lock(&hook_mutex);
/*
* Ignore already unregistered battery hooks. This might happen
* if a battery hook was previously unloaded due to an error when
* adding a new battery.
*/
if (!list_empty(&hook->list))
battery_hook_unregister_unlocked(hook);
mutex_unlock(&hook_mutex);
} }
EXPORT_SYMBOL_GPL(battery_hook_unregister); EXPORT_SYMBOL_GPL(battery_hook_unregister);
@@ -742,7 +749,6 @@ void battery_hook_register(struct acpi_battery_hook *hook)
struct acpi_battery *battery; struct acpi_battery *battery;
mutex_lock(&hook_mutex); mutex_lock(&hook_mutex);
INIT_LIST_HEAD(&hook->list);
list_add(&hook->list, &battery_hook_list); list_add(&hook->list, &battery_hook_list);
/* /*
* Now that the driver is registered, we need * Now that the driver is registered, we need
@@ -759,7 +765,7 @@ void battery_hook_register(struct acpi_battery_hook *hook)
* hooks. * hooks.
*/ */
pr_err("extension failed to load: %s", hook->name); pr_err("extension failed to load: %s", hook->name);
__battery_hook_unregister(hook, 0); battery_hook_unregister_unlocked(hook);
goto end; goto end;
} }
} }
@@ -796,7 +802,7 @@ static void battery_hook_add_battery(struct acpi_battery *battery)
*/ */
pr_err("error in extension, unloading: %s", pr_err("error in extension, unloading: %s",
hook_node->name); hook_node->name);
__battery_hook_unregister(hook_node, 0); battery_hook_unregister_unlocked(hook_node);
} }
} }
mutex_unlock(&hook_mutex); mutex_unlock(&hook_mutex);
@@ -829,7 +835,7 @@ static void __exit battery_hook_exit(void)
* need to remove the hooks. * need to remove the hooks.
*/ */
list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) { list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) {
__battery_hook_unregister(hook, 1); battery_hook_unregister(hook);
} }
mutex_destroy(&hook_mutex); mutex_destroy(&hook_mutex);
} }

View File

@@ -124,6 +124,17 @@ static const struct dmi_system_id lid_blacklst[] = {
}, },
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN, .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
}, },
{
/*
* Samsung galaxybook2 ,initial _LID device notification returns
* lid closed.
*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "750XED"),
},
.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
},
{} {}
}; };

View File

@@ -539,8 +539,9 @@ int acpi_device_setup_files(struct acpi_device *dev)
* If device has _STR, 'description' file is created * If device has _STR, 'description' file is created
*/ */
if (acpi_has_method(dev->handle, "_STR")) { if (acpi_has_method(dev->handle, "_STR")) {
status = acpi_evaluate_object(dev->handle, "_STR", status = acpi_evaluate_object_typed(dev->handle, "_STR",
NULL, &buffer); NULL, &buffer,
ACPI_TYPE_BUFFER);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
buffer.pointer = NULL; buffer.pointer = NULL;
dev->pnp.str_obj = buffer.pointer; dev->pnp.str_obj = buffer.pointer;

View File

@@ -807,6 +807,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
unsigned long tmp; unsigned long tmp;
int ret = 0; int ret = 0;
if (t->rdata)
memset(t->rdata, 0, t->rlen);
/* start transaction */ /* start transaction */
spin_lock_irqsave(&ec->lock, tmp); spin_lock_irqsave(&ec->lock, tmp);
/* Enable GPE for command processing (IBF=0/OBF=1) */ /* Enable GPE for command processing (IBF=0/OBF=1) */
@@ -843,8 +846,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata)) if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
return -EINVAL; return -EINVAL;
if (t->rdata)
memset(t->rdata, 0, t->rlen);
mutex_lock(&ec->mutex); mutex_lock(&ec->mutex);
if (ec->global_lock) { if (ec->global_lock) {
@@ -871,7 +872,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec)
.wdata = NULL, .rdata = &d, .wdata = NULL, .rdata = &d,
.wlen = 0, .rlen = 1}; .wlen = 0, .rlen = 1};
return acpi_ec_transaction(ec, &t); return acpi_ec_transaction_unlocked(ec, &t);
} }
static int acpi_ec_burst_disable(struct acpi_ec *ec) static int acpi_ec_burst_disable(struct acpi_ec *ec)
@@ -881,7 +882,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
.wlen = 0, .rlen = 0}; .wlen = 0, .rlen = 0};
return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
acpi_ec_transaction(ec, &t) : 0; acpi_ec_transaction_unlocked(ec, &t) : 0;
} }
static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
@@ -897,6 +898,19 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
return result; return result;
} }
static int acpi_ec_read_unlocked(struct acpi_ec *ec, u8 address, u8 *data)
{
int result;
u8 d;
struct transaction t = {.command = ACPI_EC_COMMAND_READ,
.wdata = &address, .rdata = &d,
.wlen = 1, .rlen = 1};
result = acpi_ec_transaction_unlocked(ec, &t);
*data = d;
return result;
}
static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
{ {
u8 wdata[2] = { address, data }; u8 wdata[2] = { address, data };
@@ -907,6 +921,16 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
return acpi_ec_transaction(ec, &t); return acpi_ec_transaction(ec, &t);
} }
static int acpi_ec_write_unlocked(struct acpi_ec *ec, u8 address, u8 data)
{
u8 wdata[2] = { address, data };
struct transaction t = {.command = ACPI_EC_COMMAND_WRITE,
.wdata = wdata, .rdata = NULL,
.wlen = 2, .rlen = 0};
return acpi_ec_transaction_unlocked(ec, &t);
}
int ec_read(u8 addr, u8 *val) int ec_read(u8 addr, u8 *val)
{ {
int err; int err;
@@ -1320,6 +1344,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
struct acpi_ec *ec = handler_context; struct acpi_ec *ec = handler_context;
int result = 0, i, bytes = bits / 8; int result = 0, i, bytes = bits / 8;
u8 *value = (u8 *)value64; u8 *value = (u8 *)value64;
u32 glk;
if ((address > 0xFF) || !value || !handler_context) if ((address > 0xFF) || !value || !handler_context)
return AE_BAD_PARAMETER; return AE_BAD_PARAMETER;
@@ -1327,13 +1352,25 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
if (function != ACPI_READ && function != ACPI_WRITE) if (function != ACPI_READ && function != ACPI_WRITE)
return AE_BAD_PARAMETER; return AE_BAD_PARAMETER;
mutex_lock(&ec->mutex);
if (ec->global_lock) {
acpi_status status;
status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
if (ACPI_FAILURE(status)) {
result = -ENODEV;
goto unlock;
}
}
if (ec->busy_polling || bits > 8) if (ec->busy_polling || bits > 8)
acpi_ec_burst_enable(ec); acpi_ec_burst_enable(ec);
for (i = 0; i < bytes; ++i, ++address, ++value) { for (i = 0; i < bytes; ++i, ++address, ++value) {
result = (function == ACPI_READ) ? result = (function == ACPI_READ) ?
acpi_ec_read(ec, address, value) : acpi_ec_read_unlocked(ec, address, value) :
acpi_ec_write(ec, address, *value); acpi_ec_write_unlocked(ec, address, *value);
if (result < 0) if (result < 0)
break; break;
} }
@@ -1341,6 +1378,12 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
if (ec->busy_polling || bits > 8) if (ec->busy_polling || bits > 8)
acpi_ec_burst_disable(ec); acpi_ec_burst_disable(ec);
if (ec->global_lock)
acpi_release_global_lock(glk);
unlock:
mutex_unlock(&ec->mutex);
switch (result) { switch (result) {
case -EINVAL: case -EINVAL:
return AE_BAD_PARAMETER; return AE_BAD_PARAMETER;

View File

@@ -376,10 +376,8 @@ static int tps68470_pmic_opregion_probe(struct platform_device *pdev)
struct tps68470_pmic_opregion *opregion; struct tps68470_pmic_opregion *opregion;
acpi_status status; acpi_status status;
if (!dev || !tps68470_regmap) { if (!tps68470_regmap)
dev_warn(dev, "dev or regmap is NULL\n"); return dev_err_probe(dev, -EINVAL, "regmap is missing\n");
return -EINVAL;
}
if (!handle) { if (!handle) {
dev_warn(dev, "acpi handle is NULL\n"); dev_warn(dev, "acpi handle is NULL\n");

View File

@@ -144,7 +144,7 @@ static const struct pci_device_id sil_pci_tbl[] = {
static const struct sil_drivelist { static const struct sil_drivelist {
const char *product; const char *product;
unsigned int quirk; unsigned int quirk;
} sil_blacklist [] = { } sil_quirks[] = {
{ "ST320012AS", SIL_QUIRK_MOD15WRITE }, { "ST320012AS", SIL_QUIRK_MOD15WRITE },
{ "ST330013AS", SIL_QUIRK_MOD15WRITE }, { "ST330013AS", SIL_QUIRK_MOD15WRITE },
{ "ST340017AS", SIL_QUIRK_MOD15WRITE }, { "ST340017AS", SIL_QUIRK_MOD15WRITE },
@@ -617,8 +617,8 @@ static void sil_thaw(struct ata_port *ap)
* list, and apply the fixups to only the specific * list, and apply the fixups to only the specific
* devices/hosts/firmwares that need it. * devices/hosts/firmwares that need it.
* *
* 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted * 20040111 - Seagate drives affected by the Mod15Write bug are quirked
* The Maxtor quirk is in the blacklist, but I'm keeping the original * The Maxtor quirk is in sil_quirks, but I'm keeping the original
* pessimistic fix for the following reasons... * pessimistic fix for the following reasons...
* - There seems to be less info on it, only one device gleaned off the * - There seems to be less info on it, only one device gleaned off the
* Windows driver, maybe only one is affected. More info would be greatly * Windows driver, maybe only one is affected. More info would be greatly
@@ -637,9 +637,9 @@ static void sil_dev_config(struct ata_device *dev)
ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
for (n = 0; sil_blacklist[n].product; n++) for (n = 0; sil_quirks[n].product; n++)
if (!strcmp(sil_blacklist[n].product, model_num)) { if (!strcmp(sil_quirks[n].product, model_num)) {
quirks = sil_blacklist[n].quirk; quirks = sil_quirks[n].quirk;
break; break;
} }

View File

@@ -103,7 +103,8 @@ static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,
{ {
struct bus_attribute *bus_attr = to_bus_attr(attr); struct bus_attribute *bus_attr = to_bus_attr(attr);
struct subsys_private *subsys_priv = to_subsys_private(kobj); struct subsys_private *subsys_priv = to_subsys_private(kobj);
ssize_t ret = 0; /* return -EIO for reading a bus attribute without show() */
ssize_t ret = -EIO;
if (bus_attr->show) if (bus_attr->show)
ret = bus_attr->show(subsys_priv->bus, buf); ret = bus_attr->show(subsys_priv->bus, buf);
@@ -115,7 +116,8 @@ static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr,
{ {
struct bus_attribute *bus_attr = to_bus_attr(attr); struct bus_attribute *bus_attr = to_bus_attr(attr);
struct subsys_private *subsys_priv = to_subsys_private(kobj); struct subsys_private *subsys_priv = to_subsys_private(kobj);
ssize_t ret = 0; /* return -EIO for writing a bus attribute without store() */
ssize_t ret = -EIO;
if (bus_attr->store) if (bus_attr->store)
ret = bus_attr->store(subsys_priv->bus, buf, count); ret = bus_attr->store(subsys_priv->bus, buf, count);

View File

@@ -24,7 +24,6 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/rcupdate.h>
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
@@ -1586,7 +1585,6 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
struct kobj_uevent_env *env) struct kobj_uevent_env *env)
{ {
struct device *dev = kobj_to_dev(kobj); struct device *dev = kobj_to_dev(kobj);
struct device_driver *driver;
int retval = 0; int retval = 0;
/* add device node properties if present */ /* add device node properties if present */
@@ -1615,12 +1613,8 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
if (dev->type && dev->type->name) if (dev->type && dev->type->name)
add_uevent_var(env, "DEVTYPE=%s", dev->type->name); add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
/* Synchronize with module_remove_driver() */ if (dev->driver)
rcu_read_lock(); add_uevent_var(env, "DRIVER=%s", dev->driver->name);
driver = READ_ONCE(dev->driver);
if (driver)
add_uevent_var(env, "DRIVER=%s", driver->name);
rcu_read_unlock();
/* Add common DT information about the device */ /* Add common DT information about the device */
of_device_uevent(dev, env); of_device_uevent(dev, env);
@@ -1690,8 +1684,11 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
if (!env) if (!env)
return -ENOMEM; return -ENOMEM;
/* Synchronize with really_probe() */
device_lock(dev);
/* let the kset specific function add its keys */ /* let the kset specific function add its keys */
retval = kset->uevent_ops->uevent(kset, &dev->kobj, env); retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
device_unlock(dev);
if (retval) if (retval)
goto out; goto out;

View File

@@ -570,6 +570,26 @@ static void fw_abort_batch_reqs(struct firmware *fw)
mutex_unlock(&fw_lock); mutex_unlock(&fw_lock);
} }
/*
* Reject firmware file names with ".." path components.
* There are drivers that construct firmware file names from device-supplied
* strings, and we don't want some device to be able to tell us "I would like to
* be sent my firmware from ../../../etc/shadow, please".
*
* Search for ".." surrounded by either '/' or start/end of string.
*
* This intentionally only looks at the firmware name, not at the firmware base
* directory or at symlink contents.
*/
static bool name_contains_dotdot(const char *name)
{
size_t name_len = strlen(name);
return strcmp(name, "..") == 0 || strncmp(name, "../", 3) == 0 ||
strstr(name, "/../") != NULL ||
(name_len >= 3 && strcmp(name+name_len-3, "/..") == 0);
}
/* called from request_firmware() and request_firmware_work_func() */ /* called from request_firmware() and request_firmware_work_func() */
static int static int
_request_firmware(const struct firmware **firmware_p, const char *name, _request_firmware(const struct firmware **firmware_p, const char *name,
@@ -587,6 +607,14 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
goto out; goto out;
} }
if (name_contains_dotdot(name)) {
dev_warn(device,
"Firmware load for '%s' refused, path contains '..' component\n",
name);
ret = -EINVAL;
goto out;
}
ret = _request_firmware_prepare(&fw, name, device, buf, size, ret = _request_firmware_prepare(&fw, name, device, buf, size,
opt_flags); opt_flags);
if (ret <= 0) /* error or already assigned */ if (ret <= 0) /* error or already assigned */
@@ -627,6 +655,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
* @name will be used as $FIRMWARE in the uevent environment and * @name will be used as $FIRMWARE in the uevent environment and
* should be distinctive enough not to be confused with any other * should be distinctive enough not to be confused with any other
* firmware image for this or any other device. * firmware image for this or any other device.
* It must not contain any ".." path components - "foo/bar..bin" is
* allowed, but "foo/../bar.bin" is not.
* *
* Caller must hold the reference count of @device. * Caller must hold the reference count of @device.
* *

View File

@@ -7,7 +7,6 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/rcupdate.h>
#include "base.h" #include "base.h"
static char *make_driver_name(struct device_driver *drv) static char *make_driver_name(struct device_driver *drv)
@@ -78,9 +77,6 @@ void module_remove_driver(struct device_driver *drv)
if (!drv) if (!drv)
return; return;
/* Synchronize with dev_uevent() */
synchronize_rcu();
sysfs_remove_link(&drv->p->kobj, "module"); sysfs_remove_link(&drv->p->kobj, "module");
if (drv->owner) if (drv->owner)

View File

@@ -362,6 +362,7 @@ ata_rw_frameinit(struct frame *f)
} }
ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit; ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit;
dev_hold(t->ifp->nd);
skb->dev = t->ifp->nd; skb->dev = t->ifp->nd;
} }
@@ -402,6 +403,8 @@ aoecmd_ata_rw(struct aoedev *d)
__skb_queue_head_init(&queue); __skb_queue_head_init(&queue);
__skb_queue_tail(&queue, skb); __skb_queue_tail(&queue, skb);
aoenet_xmit(&queue); aoenet_xmit(&queue);
} else {
dev_put(f->t->ifp->nd);
} }
return 1; return 1;
} }
@@ -484,10 +487,13 @@ resend(struct aoedev *d, struct frame *f)
memcpy(h->dst, t->addr, sizeof h->dst); memcpy(h->dst, t->addr, sizeof h->dst);
memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src);
dev_hold(t->ifp->nd);
skb->dev = t->ifp->nd; skb->dev = t->ifp->nd;
skb = skb_clone(skb, GFP_ATOMIC); skb = skb_clone(skb, GFP_ATOMIC);
if (skb == NULL) if (skb == NULL) {
dev_put(t->ifp->nd);
return; return;
}
f->sent = ktime_get(); f->sent = ktime_get();
__skb_queue_head_init(&queue); __skb_queue_head_init(&queue);
__skb_queue_tail(&queue, skb); __skb_queue_tail(&queue, skb);
@@ -618,6 +624,8 @@ probe(struct aoetgt *t)
__skb_queue_head_init(&queue); __skb_queue_head_init(&queue);
__skb_queue_tail(&queue, skb); __skb_queue_tail(&queue, skb);
aoenet_xmit(&queue); aoenet_xmit(&queue);
} else {
dev_put(f->t->ifp->nd);
} }
} }
@@ -1407,6 +1415,7 @@ aoecmd_ata_id(struct aoedev *d)
ah->cmdstat = ATA_CMD_ID_ATA; ah->cmdstat = ATA_CMD_ID_ATA;
ah->lba3 = 0xa0; ah->lba3 = 0xa0;
dev_hold(t->ifp->nd);
skb->dev = t->ifp->nd; skb->dev = t->ifp->nd;
d->rttavg = RTTAVG_INIT; d->rttavg = RTTAVG_INIT;
@@ -1416,6 +1425,8 @@ aoecmd_ata_id(struct aoedev *d)
skb = skb_clone(skb, GFP_ATOMIC); skb = skb_clone(skb, GFP_ATOMIC);
if (skb) if (skb)
f->sent = ktime_get(); f->sent = ktime_get();
else
dev_put(t->ifp->nd);
return skb; return skb;
} }

View File

@@ -3499,10 +3499,12 @@ void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local)
void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local) void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
{ {
unsigned long flags; unsigned long flags;
if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0)
return;
spin_lock_irqsave(&device->ldev->md.uuid_lock, flags); spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0) {
spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
return;
}
if (val == 0) { if (val == 0) {
drbd_uuid_move_history(device); drbd_uuid_move_history(device);
device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP]; device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP];

View File

@@ -888,7 +888,7 @@ is_valid_state(struct drbd_device *device, union drbd_state ns)
ns.disk == D_OUTDATED) ns.disk == D_OUTDATED)
rv = SS_CONNECTED_OUTDATES; rv = SS_CONNECTED_OUTDATES;
else if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) && else if (nc && (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
(nc->verify_alg[0] == 0)) (nc->verify_alg[0] == 0))
rv = SS_NO_VERIFY_ALG; rv = SS_NO_VERIFY_ALG;

View File

@@ -743,7 +743,15 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
if (!urb) if (!urb)
return -ENOMEM; return -ENOMEM;
size = le16_to_cpu(data->intr_ep->wMaxPacketSize); if (le16_to_cpu(data->udev->descriptor.idVendor) == 0x0a12 &&
le16_to_cpu(data->udev->descriptor.idProduct) == 0x0001)
/* Fake CSR devices don't seem to support sort-transter */
size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
else
/* Use maximum HCI Event size so the USB stack handles
* ZPL/short-transfer automatically.
*/
size = HCI_MAX_EVENT_SIZE;
buf = kmalloc(size, mem_flags); buf = kmalloc(size, mem_flags);
if (!buf) { if (!buf) {

View File

@@ -2075,25 +2075,27 @@ static int virtcons_probe(struct virtio_device *vdev)
multiport = true; multiport = true;
} }
err = init_vqs(portdev);
if (err < 0) {
dev_err(&vdev->dev, "Error %d initializing vqs\n", err);
goto free_chrdev;
}
spin_lock_init(&portdev->ports_lock); spin_lock_init(&portdev->ports_lock);
INIT_LIST_HEAD(&portdev->ports); INIT_LIST_HEAD(&portdev->ports);
INIT_LIST_HEAD(&portdev->list); INIT_LIST_HEAD(&portdev->list);
virtio_device_ready(portdev->vdev);
INIT_WORK(&portdev->config_work, &config_work_handler); INIT_WORK(&portdev->config_work, &config_work_handler);
INIT_WORK(&portdev->control_work, &control_work_handler); INIT_WORK(&portdev->control_work, &control_work_handler);
if (multiport) { if (multiport) {
spin_lock_init(&portdev->c_ivq_lock); spin_lock_init(&portdev->c_ivq_lock);
spin_lock_init(&portdev->c_ovq_lock); spin_lock_init(&portdev->c_ovq_lock);
}
err = init_vqs(portdev);
if (err < 0) {
dev_err(&vdev->dev, "Error %d initializing vqs\n", err);
goto free_chrdev;
}
virtio_device_ready(portdev->vdev);
if (multiport) {
err = fill_queue(portdev->c_ivq, &portdev->c_ivq_lock); err = fill_queue(portdev->c_ivq, &portdev->c_ivq_lock);
if (err < 0) { if (err < 0) {
dev_err(&vdev->dev, dev_err(&vdev->dev,

View File

@@ -115,7 +115,7 @@ static void bcm53573_ilp_init(struct device_node *np)
goto err_free_ilp; goto err_free_ilp;
} }
ilp->regmap = syscon_node_to_regmap(of_get_parent(np)); ilp->regmap = syscon_node_to_regmap(np->parent);
if (IS_ERR(ilp->regmap)) { if (IS_ERR(ilp->regmap)) {
err = PTR_ERR(ilp->regmap); err = PTR_ERR(ilp->regmap);
goto err_free_ilp; goto err_free_ilp;

View File

@@ -9,31 +9,101 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/gfp.h> #include <linux/gfp.h>
struct devm_clk_state {
struct clk *clk;
void (*exit)(struct clk *clk);
};
static void devm_clk_release(struct device *dev, void *res) static void devm_clk_release(struct device *dev, void *res)
{ {
clk_put(*(struct clk **)res); struct devm_clk_state *state = res;
if (state->exit)
state->exit(state->clk);
clk_put(state->clk);
}
static struct clk *__devm_clk_get(struct device *dev, const char *id,
struct clk *(*get)(struct device *dev, const char *id),
int (*init)(struct clk *clk),
void (*exit)(struct clk *clk))
{
struct devm_clk_state *state;
struct clk *clk;
int ret;
state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
if (!state)
return ERR_PTR(-ENOMEM);
clk = get(dev, id);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
goto err_clk_get;
}
if (init) {
ret = init(clk);
if (ret)
goto err_clk_init;
}
state->clk = clk;
state->exit = exit;
devres_add(dev, state);
return clk;
err_clk_init:
clk_put(clk);
err_clk_get:
devres_free(state);
return ERR_PTR(ret);
} }
struct clk *devm_clk_get(struct device *dev, const char *id) struct clk *devm_clk_get(struct device *dev, const char *id)
{ {
struct clk **ptr, *clk; return __devm_clk_get(dev, id, clk_get, NULL, NULL);
ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
clk = clk_get(dev, id);
if (!IS_ERR(clk)) {
*ptr = clk;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return clk;
} }
EXPORT_SYMBOL(devm_clk_get); EXPORT_SYMBOL(devm_clk_get);
struct clk *devm_clk_get_prepared(struct device *dev, const char *id)
{
return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare);
}
EXPORT_SYMBOL_GPL(devm_clk_get_prepared);
struct clk *devm_clk_get_enabled(struct device *dev, const char *id)
{
return __devm_clk_get(dev, id, clk_get,
clk_prepare_enable, clk_disable_unprepare);
}
EXPORT_SYMBOL_GPL(devm_clk_get_enabled);
struct clk *devm_clk_get_optional(struct device *dev, const char *id)
{
return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
}
EXPORT_SYMBOL(devm_clk_get_optional);
struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id)
{
return __devm_clk_get(dev, id, clk_get_optional,
clk_prepare, clk_unprepare);
}
EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared);
struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
{
return __devm_clk_get(dev, id, clk_get_optional,
clk_prepare_enable, clk_disable_unprepare);
}
EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
struct clk_bulk_devres { struct clk_bulk_devres {
struct clk_bulk_data *clks; struct clk_bulk_data *clks;
int num_clks; int num_clks;
@@ -93,18 +163,19 @@ EXPORT_SYMBOL(devm_clk_put);
struct clk *devm_get_clk_from_child(struct device *dev, struct clk *devm_get_clk_from_child(struct device *dev,
struct device_node *np, const char *con_id) struct device_node *np, const char *con_id)
{ {
struct clk **ptr, *clk; struct devm_clk_state *state;
struct clk *clk;
ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
if (!ptr) if (!state)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
clk = of_clk_get_by_name(np, con_id); clk = of_clk_get_by_name(np, con_id);
if (!IS_ERR(clk)) { if (!IS_ERR(clk)) {
*ptr = clk; state->clk = clk;
devres_add(dev, ptr); devres_add(dev, state);
} else { } else {
devres_free(ptr); devres_free(state);
} }
return clk; return clk;

View File

@@ -415,7 +415,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
RK2928_CLKSEL_CON(29), 0, 3, DFLAGS), RK2928_CLKSEL_CON(29), 0, 3, DFLAGS),
DIV(0, "sclk_vop_pre", "sclk_vop_src", 0, DIV(0, "sclk_vop_pre", "sclk_vop_src", 0,
RK2928_CLKSEL_CON(27), 8, 8, DFLAGS), RK2928_CLKSEL_CON(27), 8, 8, DFLAGS),
MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, 0, MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
RK2928_CLKSEL_CON(27), 1, 1, MFLAGS), RK2928_CLKSEL_CON(27), 1, 1, MFLAGS),
FACTOR(0, "xin12m", "xin24m", 0, 1, 2), FACTOR(0, "xin12m", "xin24m", 0, 1, 2),

View File

@@ -444,12 +444,13 @@ void __init rockchip_clk_register_branches(
struct rockchip_clk_branch *list, struct rockchip_clk_branch *list,
unsigned int nr_clk) unsigned int nr_clk)
{ {
struct clk *clk = NULL; struct clk *clk;
unsigned int idx; unsigned int idx;
unsigned long flags; unsigned long flags;
for (idx = 0; idx < nr_clk; idx++, list++) { for (idx = 0; idx < nr_clk; idx++, list++) {
flags = list->flags; flags = list->flags;
clk = NULL;
/* catch simple muxes */ /* catch simple muxes */
switch (list->branch_type) { switch (list->branch_type) {

View File

@@ -257,6 +257,7 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev)
} }
clk = of_clk_get_from_provider(&clkspec); clk = of_clk_get_from_provider(&clkspec);
of_node_put(clkspec.np);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
pr_err("%s: failed to get atl clock %d from provider\n", pr_err("%s: failed to get atl clock %d from provider\n",
__func__, i); __func__, i);

View File

@@ -242,6 +242,7 @@ static int __init msm_dt_timer_init(struct device_node *np)
} }
if (of_property_read_u32(np, "clock-frequency", &freq)) { if (of_property_read_u32(np, "clock-frequency", &freq)) {
iounmap(cpu0_base);
pr_err("Unknown frequency\n"); pr_err("Unknown frequency\n");
return -EINVAL; return -EINVAL;
} }
@@ -252,7 +253,11 @@ static int __init msm_dt_timer_init(struct device_node *np)
freq /= 4; freq /= 4;
writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL); writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL);
return msm_timer_init(freq, 32, irq, !!percpu_offset); ret = msm_timer_init(freq, 32, irq, !!percpu_offset);
if (ret)
iounmap(cpu0_base);
return ret;
} }
TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init); TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init); TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);

View File

@@ -800,7 +800,7 @@ static int sdei_device_freeze(struct device *dev)
int err; int err;
/* unregister private events */ /* unregister private events */
cpuhp_remove_state(sdei_entry_point); cpuhp_remove_state(sdei_hp_state);
err = sdei_unregister_shared(); err = sdei_unregister_shared();
if (err) if (err)

View File

@@ -407,6 +407,8 @@ static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
gpio->dcache[GPIO_BANK(offset)] = reg; gpio->dcache[GPIO_BANK(offset)] = reg;
iowrite32(reg, addr); iowrite32(reg, addr);
/* Flush write */
ioread32(addr);
} }
static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset, static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
@@ -1174,7 +1176,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
if (!gpio_id) if (!gpio_id)
return -EINVAL; return -EINVAL;
gpio->clk = of_clk_get(pdev->dev.of_node, 0); gpio->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(gpio->clk)) { if (IS_ERR(gpio->clk)) {
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"Failed to get clock from devicetree, debouncing disabled\n"); "Failed to get clock from devicetree, debouncing disabled\n");

View File

@@ -294,7 +294,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)
* serve as EDMA event triggers. * serve as EDMA event triggers.
*/ */
static void gpio_irq_disable(struct irq_data *d) static void gpio_irq_mask(struct irq_data *d)
{ {
struct davinci_gpio_regs __iomem *g = irq2regs(d); struct davinci_gpio_regs __iomem *g = irq2regs(d);
u32 mask = (u32) irq_data_get_irq_handler_data(d); u32 mask = (u32) irq_data_get_irq_handler_data(d);
@@ -303,7 +303,7 @@ static void gpio_irq_disable(struct irq_data *d)
writel_relaxed(mask, &g->clr_rising); writel_relaxed(mask, &g->clr_rising);
} }
static void gpio_irq_enable(struct irq_data *d) static void gpio_irq_unmask(struct irq_data *d)
{ {
struct davinci_gpio_regs __iomem *g = irq2regs(d); struct davinci_gpio_regs __iomem *g = irq2regs(d);
u32 mask = (u32) irq_data_get_irq_handler_data(d); u32 mask = (u32) irq_data_get_irq_handler_data(d);
@@ -329,8 +329,8 @@ static int gpio_irq_type(struct irq_data *d, unsigned trigger)
static struct irq_chip gpio_irqchip = { static struct irq_chip gpio_irqchip = {
.name = "GPIO", .name = "GPIO",
.irq_enable = gpio_irq_enable, .irq_unmask = gpio_irq_unmask,
.irq_disable = gpio_irq_disable, .irq_mask = gpio_irq_mask,
.irq_set_type = gpio_irq_type, .irq_set_type = gpio_irq_type,
.flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE, .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE,
}; };

View File

@@ -3,6 +3,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/nospec.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/device.h> #include <linux/device.h>
@@ -144,7 +145,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip,
if (hwnum >= gdev->ngpio) if (hwnum >= gdev->ngpio)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
return &gdev->descs[hwnum]; return &gdev->descs[array_index_nospec(hwnum, gdev->ngpio)];
} }
/** /**

View File

@@ -90,6 +90,7 @@ static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
struct acpi_buffer *params) struct acpi_buffer *params)
{ {
acpi_status status; acpi_status status;
union acpi_object *obj;
union acpi_object atif_arg_elements[2]; union acpi_object atif_arg_elements[2];
struct acpi_object_list atif_arg; struct acpi_object_list atif_arg;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -112,16 +113,24 @@ static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
status = acpi_evaluate_object(atif->handle, NULL, &atif_arg, status = acpi_evaluate_object(atif->handle, NULL, &atif_arg,
&buffer); &buffer);
obj = (union acpi_object *)buffer.pointer;
/* Fail only if calling the method fails and ATIF is supported */ /* Fail if calling the method fails */
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { if (ACPI_FAILURE(status)) {
DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
acpi_format_exception(status)); acpi_format_exception(status));
kfree(buffer.pointer); kfree(obj);
return NULL; return NULL;
} }
return buffer.pointer; if (obj->type != ACPI_TYPE_BUFFER) {
DRM_DEBUG_DRIVER("bad object returned from ATIF: %d\n",
obj->type);
kfree(obj);
return NULL;
}
return obj;
} }
/** /**

View File

@@ -394,7 +394,7 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf,
if (!adev->smc_rreg) if (!adev->smc_rreg)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (size & 0x3 || *pos & 0x3) if (size > 4096 || size & 0x3 || *pos & 0x3)
return -EINVAL; return -EINVAL;
while (size) { while (size) {

View File

@@ -2095,23 +2095,29 @@ amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder)
fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
if (fake_edid_record->ucFakeEDIDLength) { if (fake_edid_record->ucFakeEDIDLength) {
struct edid *edid; struct edid *edid;
int edid_size = int edid_size;
max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
edid = kmalloc(edid_size, GFP_KERNEL);
if (edid) {
memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
fake_edid_record->ucFakeEDIDLength);
if (fake_edid_record->ucFakeEDIDLength == 128)
edid_size = fake_edid_record->ucFakeEDIDLength;
else
edid_size = fake_edid_record->ucFakeEDIDLength * 128;
edid = kmemdup(&fake_edid_record->ucFakeEDIDString[0],
edid_size, GFP_KERNEL);
if (edid) {
if (drm_edid_is_valid(edid)) { if (drm_edid_is_valid(edid)) {
adev->mode_info.bios_hardcoded_edid = edid; adev->mode_info.bios_hardcoded_edid = edid;
adev->mode_info.bios_hardcoded_edid_size = edid_size; adev->mode_info.bios_hardcoded_edid_size = edid_size;
} else } else {
kfree(edid); kfree(edid);
}
} }
record += struct_size(fake_edid_record,
ucFakeEDIDString,
edid_size);
} else {
/* empty fake edid record must be 3 bytes long */
record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
} }
record += fake_edid_record->ucFakeEDIDLength ?
fake_edid_record->ucFakeEDIDLength + 2 :
sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
break; break;
case LCD_PANEL_RESOLUTION_RECORD_TYPE: case LCD_PANEL_RESOLUTION_RECORD_TYPE:
panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;

View File

@@ -1569,6 +1569,8 @@ static bool are_stream_backends_same(
bool dc_is_stream_unchanged( bool dc_is_stream_unchanged(
struct dc_stream_state *old_stream, struct dc_stream_state *stream) struct dc_stream_state *old_stream, struct dc_stream_state *stream)
{ {
if (!old_stream || !stream)
return false;
if (!are_stream_backends_same(old_stream, stream)) if (!are_stream_backends_same(old_stream, stream))
return false; return false;

View File

@@ -482,6 +482,8 @@ bool cm_helper_translate_curve_to_degamma_hw_format(
i += increment) { i += increment) {
if (j == hw_points - 1) if (j == hw_points - 1)
break; break;
if (i >= TRANSFER_FUNC_POINTS)
return false;
rgb_resulted[j].red = output_tf->tf_pts.red[i]; rgb_resulted[j].red = output_tf->tf_pts.red[i];
rgb_resulted[j].green = output_tf->tf_pts.green[i]; rgb_resulted[j].green = output_tf->tf_pts.green[i];
rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; rgb_resulted[j].blue = output_tf->tf_pts.blue[i];

View File

@@ -4106,8 +4106,8 @@ typedef struct _ATOM_LCD_MODE_CONTROL_CAP
typedef struct _ATOM_FAKE_EDID_PATCH_RECORD typedef struct _ATOM_FAKE_EDID_PATCH_RECORD
{ {
UCHAR ucRecordType; UCHAR ucRecordType;
UCHAR ucFakeEDIDLength; // = 128 means EDID lenght is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128 UCHAR ucFakeEDIDLength; // = 128 means EDID length is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128
UCHAR ucFakeEDIDString[1]; // This actually has ucFakeEdidLength elements. UCHAR ucFakeEDIDString[]; // This actually has ucFakeEdidLength elements.
} ATOM_FAKE_EDID_PATCH_RECORD; } ATOM_FAKE_EDID_PATCH_RECORD;
typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD

View File

@@ -567,9 +567,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
struct drm_mode_crtc *crtc_req = data; struct drm_mode_crtc *crtc_req = data;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_plane *plane; struct drm_plane *plane;
struct drm_connector **connector_set, *connector; struct drm_connector **connector_set = NULL, *connector;
struct drm_framebuffer *fb; struct drm_framebuffer *fb = NULL;
struct drm_display_mode *mode; struct drm_display_mode *mode = NULL;
struct drm_mode_set set; struct drm_mode_set set;
uint32_t __user *set_connectors_ptr; uint32_t __user *set_connectors_ptr;
struct drm_modeset_acquire_ctx ctx; struct drm_modeset_acquire_ctx ctx;
@@ -601,10 +601,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
mutex_lock(&crtc->dev->mode_config.mutex); mutex_lock(&crtc->dev->mode_config.mutex);
drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
retry: retry:
connector_set = NULL;
fb = NULL;
mode = NULL;
ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx); ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx);
if (ret) if (ret)
goto out; goto out;
@@ -767,6 +763,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
} }
kfree(connector_set); kfree(connector_set);
drm_mode_destroy(dev, mode); drm_mode_destroy(dev, mode);
/* In case we need to retry... */
connector_set = NULL;
fb = NULL;
mode = NULL;
num_connectors = 0;
if (ret == -EDEADLK) { if (ret == -EDEADLK) {
ret = drm_modeset_backoff(&ctx); ret = drm_modeset_backoff(&ctx);
if (!ret) if (!ret)

View File

@@ -54,8 +54,9 @@ void __drm_puts_coredump(struct drm_printer *p, const char *str)
copy = iterator->remain; copy = iterator->remain;
/* Copy out the bit of the string that we need */ /* Copy out the bit of the string that we need */
memcpy(iterator->data, if (iterator->data)
str + (iterator->start - iterator->offset), copy); memcpy(iterator->data,
str + (iterator->start - iterator->offset), copy);
iterator->offset = iterator->start + copy; iterator->offset = iterator->start + copy;
iterator->remain -= copy; iterator->remain -= copy;
@@ -64,7 +65,8 @@ void __drm_puts_coredump(struct drm_printer *p, const char *str)
len = min_t(ssize_t, strlen(str), iterator->remain); len = min_t(ssize_t, strlen(str), iterator->remain);
memcpy(iterator->data + pos, str, len); if (iterator->data)
memcpy(iterator->data + pos, str, len);
iterator->offset += len; iterator->offset += len;
iterator->remain -= len; iterator->remain -= len;
@@ -94,8 +96,9 @@ void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
if ((iterator->offset >= iterator->start) && (len < iterator->remain)) { if ((iterator->offset >= iterator->start) && (len < iterator->remain)) {
ssize_t pos = iterator->offset - iterator->start; ssize_t pos = iterator->offset - iterator->start;
snprintf(((char *) iterator->data) + pos, if (iterator->data)
iterator->remain, "%pV", vaf); snprintf(((char *) iterator->data) + pos,
iterator->remain, "%pV", vaf);
iterator->offset += len; iterator->offset += len;
iterator->remain -= len; iterator->remain -= len;

View File

@@ -44,6 +44,7 @@ struct a5xx_gpu {
uint64_t preempt_iova[MSM_GPU_MAX_RINGS]; uint64_t preempt_iova[MSM_GPU_MAX_RINGS];
atomic_t preempt_state; atomic_t preempt_state;
spinlock_t preempt_start_lock;
struct timer_list preempt_timer; struct timer_list preempt_timer;
}; };

View File

@@ -107,12 +107,19 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)
if (gpu->nr_rings == 1) if (gpu->nr_rings == 1)
return; return;
/*
* Serialize preemption start to ensure that we always make
* decision on latest state. Otherwise we can get stuck in
* lower priority or empty ring.
*/
spin_lock_irqsave(&a5xx_gpu->preempt_start_lock, flags);
/* /*
* Try to start preemption by moving from NONE to START. If * Try to start preemption by moving from NONE to START. If
* unsuccessful, a preemption is already in flight * unsuccessful, a preemption is already in flight
*/ */
if (!try_preempt_state(a5xx_gpu, PREEMPT_NONE, PREEMPT_START)) if (!try_preempt_state(a5xx_gpu, PREEMPT_NONE, PREEMPT_START))
return; goto out;
/* Get the next ring to preempt to */ /* Get the next ring to preempt to */
ring = get_next_ring(gpu); ring = get_next_ring(gpu);
@@ -137,9 +144,11 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)
set_preempt_state(a5xx_gpu, PREEMPT_ABORT); set_preempt_state(a5xx_gpu, PREEMPT_ABORT);
update_wptr(gpu, a5xx_gpu->cur_ring); update_wptr(gpu, a5xx_gpu->cur_ring);
set_preempt_state(a5xx_gpu, PREEMPT_NONE); set_preempt_state(a5xx_gpu, PREEMPT_NONE);
return; goto out;
} }
spin_unlock_irqrestore(&a5xx_gpu->preempt_start_lock, flags);
/* Make sure the wptr doesn't update while we're in motion */ /* Make sure the wptr doesn't update while we're in motion */
spin_lock_irqsave(&ring->lock, flags); spin_lock_irqsave(&ring->lock, flags);
a5xx_gpu->preempt[ring->id]->wptr = get_wptr(ring); a5xx_gpu->preempt[ring->id]->wptr = get_wptr(ring);
@@ -163,6 +172,10 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)
/* And actually start the preemption */ /* And actually start the preemption */
gpu_write(gpu, REG_A5XX_CP_CONTEXT_SWITCH_CNTL, 1); gpu_write(gpu, REG_A5XX_CP_CONTEXT_SWITCH_CNTL, 1);
return;
out:
spin_unlock_irqrestore(&a5xx_gpu->preempt_start_lock, flags);
} }
void a5xx_preempt_irq(struct msm_gpu *gpu) void a5xx_preempt_irq(struct msm_gpu *gpu)
@@ -200,6 +213,12 @@ void a5xx_preempt_irq(struct msm_gpu *gpu)
update_wptr(gpu, a5xx_gpu->cur_ring); update_wptr(gpu, a5xx_gpu->cur_ring);
set_preempt_state(a5xx_gpu, PREEMPT_NONE); set_preempt_state(a5xx_gpu, PREEMPT_NONE);
/*
* Try to trigger preemption again in case there was a submit or
* retire during ring switch
*/
a5xx_preempt_trigger(gpu);
} }
void a5xx_preempt_hw_init(struct msm_gpu *gpu) void a5xx_preempt_hw_init(struct msm_gpu *gpu)
@@ -209,6 +228,8 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu)
int i; int i;
for (i = 0; i < gpu->nr_rings; i++) { for (i = 0; i < gpu->nr_rings; i++) {
a5xx_gpu->preempt[i]->data = 0;
a5xx_gpu->preempt[i]->info = 0;
a5xx_gpu->preempt[i]->wptr = 0; a5xx_gpu->preempt[i]->wptr = 0;
a5xx_gpu->preempt[i]->rptr = 0; a5xx_gpu->preempt[i]->rptr = 0;
a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova; a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova;
@@ -300,5 +321,6 @@ void a5xx_preempt_init(struct msm_gpu *gpu)
} }
} }
spin_lock_init(&a5xx_gpu->preempt_start_lock);
timer_setup(&a5xx_gpu->preempt_timer, a5xx_preempt_timer, 0); timer_setup(&a5xx_gpu->preempt_timer, a5xx_preempt_timer, 0);
} }

View File

@@ -366,7 +366,7 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p)
drm_printf(p, "%s:%d\t%d\t%s\n", drm_printf(p, "%s:%d\t%d\t%s\n",
pipe2name(pipe), j, inuse, pipe2name(pipe), j, inuse,
plane ? plane->name : NULL); plane ? plane->name : "(null)");
total += inuse; total += inuse;
} }

View File

@@ -671,7 +671,7 @@ static u32 dsi_get_pclk_rate(struct msm_dsi_host *msm_host, bool is_dual_dsi)
struct drm_display_mode *mode = msm_host->mode; struct drm_display_mode *mode = msm_host->mode;
u32 pclk_rate; u32 pclk_rate;
pclk_rate = mode->clock * 1000; pclk_rate = mode->clock * 1000u;
/* /*
* For dual DSI mode, the current DRM mode has the complete width of the * For dual DSI mode, the current DRM mode has the complete width of the

View File

@@ -3615,7 +3615,7 @@ typedef struct _ATOM_FAKE_EDID_PATCH_RECORD
{ {
UCHAR ucRecordType; UCHAR ucRecordType;
UCHAR ucFakeEDIDLength; UCHAR ucFakeEDIDLength;
UCHAR ucFakeEDIDString[1]; // This actually has ucFakeEdidLength elements. UCHAR ucFakeEDIDString[]; // This actually has ucFakeEdidLength elements.
} ATOM_FAKE_EDID_PATCH_RECORD; } ATOM_FAKE_EDID_PATCH_RECORD;
typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD

View File

@@ -396,7 +396,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i
struct evergreen_cs_track *track = p->track; struct evergreen_cs_track *track = p->track;
struct eg_surface surf; struct eg_surface surf;
unsigned pitch, slice, mslice; unsigned pitch, slice, mslice;
unsigned long offset; u64 offset;
int r; int r;
mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1; mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1;
@@ -434,14 +434,14 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i
return r; return r;
} }
offset = track->cb_color_bo_offset[id] << 8; offset = (u64)track->cb_color_bo_offset[id] << 8;
if (offset & (surf.base_align - 1)) { if (offset & (surf.base_align - 1)) {
dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n", dev_warn(p->dev, "%s:%d cb[%d] bo base %llu not aligned with %ld\n",
__func__, __LINE__, id, offset, surf.base_align); __func__, __LINE__, id, offset, surf.base_align);
return -EINVAL; return -EINVAL;
} }
offset += surf.layer_size * mslice; offset += (u64)surf.layer_size * mslice;
if (offset > radeon_bo_size(track->cb_color_bo[id])) { if (offset > radeon_bo_size(track->cb_color_bo[id])) {
/* old ddx are broken they allocate bo with w*h*bpp but /* old ddx are broken they allocate bo with w*h*bpp but
* program slice with ALIGN(h, 8), catch this and patch * program slice with ALIGN(h, 8), catch this and patch
@@ -449,14 +449,14 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i
*/ */
if (!surf.mode) { if (!surf.mode) {
uint32_t *ib = p->ib.ptr; uint32_t *ib = p->ib.ptr;
unsigned long tmp, nby, bsize, size, min = 0; u64 tmp, nby, bsize, size, min = 0;
/* find the height the ddx wants */ /* find the height the ddx wants */
if (surf.nby > 8) { if (surf.nby > 8) {
min = surf.nby - 8; min = surf.nby - 8;
} }
bsize = radeon_bo_size(track->cb_color_bo[id]); bsize = radeon_bo_size(track->cb_color_bo[id]);
tmp = track->cb_color_bo_offset[id] << 8; tmp = (u64)track->cb_color_bo_offset[id] << 8;
for (nby = surf.nby; nby > min; nby--) { for (nby = surf.nby; nby > min; nby--) {
size = nby * surf.nbx * surf.bpe * surf.nsamples; size = nby * surf.nbx * surf.bpe * surf.nsamples;
if ((tmp + size * mslice) <= bsize) { if ((tmp + size * mslice) <= bsize) {
@@ -468,7 +468,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i
slice = ((nby * surf.nbx) / 64) - 1; slice = ((nby * surf.nbx) / 64) - 1;
if (!evergreen_surface_check(p, &surf, "cb")) { if (!evergreen_surface_check(p, &surf, "cb")) {
/* check if this one works */ /* check if this one works */
tmp += surf.layer_size * mslice; tmp += (u64)surf.layer_size * mslice;
if (tmp <= bsize) { if (tmp <= bsize) {
ib[track->cb_color_slice_idx[id]] = slice; ib[track->cb_color_slice_idx[id]] = slice;
goto old_ddx_ok; goto old_ddx_ok;
@@ -477,9 +477,9 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i
} }
} }
dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, "
"offset %d, max layer %d, bo size %ld, slice %d)\n", "offset %llu, max layer %d, bo size %ld, slice %d)\n",
__func__, __LINE__, id, surf.layer_size, __func__, __LINE__, id, surf.layer_size,
track->cb_color_bo_offset[id] << 8, mslice, (u64)track->cb_color_bo_offset[id] << 8, mslice,
radeon_bo_size(track->cb_color_bo[id]), slice); radeon_bo_size(track->cb_color_bo[id]), slice);
dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n",
__func__, __LINE__, surf.nbx, surf.nby, __func__, __LINE__, surf.nbx, surf.nby,
@@ -563,7 +563,7 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
struct evergreen_cs_track *track = p->track; struct evergreen_cs_track *track = p->track;
struct eg_surface surf; struct eg_surface surf;
unsigned pitch, slice, mslice; unsigned pitch, slice, mslice;
unsigned long offset; u64 offset;
int r; int r;
mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
@@ -609,18 +609,18 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
return r; return r;
} }
offset = track->db_s_read_offset << 8; offset = (u64)track->db_s_read_offset << 8;
if (offset & (surf.base_align - 1)) { if (offset & (surf.base_align - 1)) {
dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", dev_warn(p->dev, "%s:%d stencil read bo base %llu not aligned with %ld\n",
__func__, __LINE__, offset, surf.base_align); __func__, __LINE__, offset, surf.base_align);
return -EINVAL; return -EINVAL;
} }
offset += surf.layer_size * mslice; offset += (u64)surf.layer_size * mslice;
if (offset > radeon_bo_size(track->db_s_read_bo)) { if (offset > radeon_bo_size(track->db_s_read_bo)) {
dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, " dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, "
"offset %ld, max layer %d, bo size %ld)\n", "offset %llu, max layer %d, bo size %ld)\n",
__func__, __LINE__, surf.layer_size, __func__, __LINE__, surf.layer_size,
(unsigned long)track->db_s_read_offset << 8, mslice, (u64)track->db_s_read_offset << 8, mslice,
radeon_bo_size(track->db_s_read_bo)); radeon_bo_size(track->db_s_read_bo));
dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
__func__, __LINE__, track->db_depth_size, __func__, __LINE__, track->db_depth_size,
@@ -628,18 +628,18 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
return -EINVAL; return -EINVAL;
} }
offset = track->db_s_write_offset << 8; offset = (u64)track->db_s_write_offset << 8;
if (offset & (surf.base_align - 1)) { if (offset & (surf.base_align - 1)) {
dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", dev_warn(p->dev, "%s:%d stencil write bo base %llu not aligned with %ld\n",
__func__, __LINE__, offset, surf.base_align); __func__, __LINE__, offset, surf.base_align);
return -EINVAL; return -EINVAL;
} }
offset += surf.layer_size * mslice; offset += (u64)surf.layer_size * mslice;
if (offset > radeon_bo_size(track->db_s_write_bo)) { if (offset > radeon_bo_size(track->db_s_write_bo)) {
dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, " dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, "
"offset %ld, max layer %d, bo size %ld)\n", "offset %llu, max layer %d, bo size %ld)\n",
__func__, __LINE__, surf.layer_size, __func__, __LINE__, surf.layer_size,
(unsigned long)track->db_s_write_offset << 8, mslice, (u64)track->db_s_write_offset << 8, mslice,
radeon_bo_size(track->db_s_write_bo)); radeon_bo_size(track->db_s_write_bo));
return -EINVAL; return -EINVAL;
} }
@@ -660,7 +660,7 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p)
struct evergreen_cs_track *track = p->track; struct evergreen_cs_track *track = p->track;
struct eg_surface surf; struct eg_surface surf;
unsigned pitch, slice, mslice; unsigned pitch, slice, mslice;
unsigned long offset; u64 offset;
int r; int r;
mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
@@ -707,34 +707,34 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p)
return r; return r;
} }
offset = track->db_z_read_offset << 8; offset = (u64)track->db_z_read_offset << 8;
if (offset & (surf.base_align - 1)) { if (offset & (surf.base_align - 1)) {
dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", dev_warn(p->dev, "%s:%d stencil read bo base %llu not aligned with %ld\n",
__func__, __LINE__, offset, surf.base_align); __func__, __LINE__, offset, surf.base_align);
return -EINVAL; return -EINVAL;
} }
offset += surf.layer_size * mslice; offset += (u64)surf.layer_size * mslice;
if (offset > radeon_bo_size(track->db_z_read_bo)) { if (offset > radeon_bo_size(track->db_z_read_bo)) {
dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, " dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, "
"offset %ld, max layer %d, bo size %ld)\n", "offset %llu, max layer %d, bo size %ld)\n",
__func__, __LINE__, surf.layer_size, __func__, __LINE__, surf.layer_size,
(unsigned long)track->db_z_read_offset << 8, mslice, (u64)track->db_z_read_offset << 8, mslice,
radeon_bo_size(track->db_z_read_bo)); radeon_bo_size(track->db_z_read_bo));
return -EINVAL; return -EINVAL;
} }
offset = track->db_z_write_offset << 8; offset = (u64)track->db_z_write_offset << 8;
if (offset & (surf.base_align - 1)) { if (offset & (surf.base_align - 1)) {
dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", dev_warn(p->dev, "%s:%d stencil write bo base %llu not aligned with %ld\n",
__func__, __LINE__, offset, surf.base_align); __func__, __LINE__, offset, surf.base_align);
return -EINVAL; return -EINVAL;
} }
offset += surf.layer_size * mslice; offset += (u64)surf.layer_size * mslice;
if (offset > radeon_bo_size(track->db_z_write_bo)) { if (offset > radeon_bo_size(track->db_z_write_bo)) {
dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, " dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, "
"offset %ld, max layer %d, bo size %ld)\n", "offset %llu, max layer %d, bo size %ld)\n",
__func__, __LINE__, surf.layer_size, __func__, __LINE__, surf.layer_size,
(unsigned long)track->db_z_write_offset << 8, mslice, (u64)track->db_z_write_offset << 8, mslice,
radeon_bo_size(track->db_z_write_bo)); radeon_bo_size(track->db_z_write_bo));
return -EINVAL; return -EINVAL;
} }

View File

@@ -999,45 +999,65 @@ static int r100_cp_init_microcode(struct radeon_device *rdev)
DRM_DEBUG_KMS("\n"); DRM_DEBUG_KMS("\n");
if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || switch (rdev->family) {
(rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || case CHIP_R100:
(rdev->family == CHIP_RS200)) { case CHIP_RV100:
case CHIP_RV200:
case CHIP_RS100:
case CHIP_RS200:
DRM_INFO("Loading R100 Microcode\n"); DRM_INFO("Loading R100 Microcode\n");
fw_name = FIRMWARE_R100; fw_name = FIRMWARE_R100;
} else if ((rdev->family == CHIP_R200) || break;
(rdev->family == CHIP_RV250) ||
(rdev->family == CHIP_RV280) || case CHIP_R200:
(rdev->family == CHIP_RS300)) { case CHIP_RV250:
case CHIP_RV280:
case CHIP_RS300:
DRM_INFO("Loading R200 Microcode\n"); DRM_INFO("Loading R200 Microcode\n");
fw_name = FIRMWARE_R200; fw_name = FIRMWARE_R200;
} else if ((rdev->family == CHIP_R300) || break;
(rdev->family == CHIP_R350) ||
(rdev->family == CHIP_RV350) || case CHIP_R300:
(rdev->family == CHIP_RV380) || case CHIP_R350:
(rdev->family == CHIP_RS400) || case CHIP_RV350:
(rdev->family == CHIP_RS480)) { case CHIP_RV380:
case CHIP_RS400:
case CHIP_RS480:
DRM_INFO("Loading R300 Microcode\n"); DRM_INFO("Loading R300 Microcode\n");
fw_name = FIRMWARE_R300; fw_name = FIRMWARE_R300;
} else if ((rdev->family == CHIP_R420) || break;
(rdev->family == CHIP_R423) ||
(rdev->family == CHIP_RV410)) { case CHIP_R420:
case CHIP_R423:
case CHIP_RV410:
DRM_INFO("Loading R400 Microcode\n"); DRM_INFO("Loading R400 Microcode\n");
fw_name = FIRMWARE_R420; fw_name = FIRMWARE_R420;
} else if ((rdev->family == CHIP_RS690) || break;
(rdev->family == CHIP_RS740)) {
case CHIP_RS690:
case CHIP_RS740:
DRM_INFO("Loading RS690/RS740 Microcode\n"); DRM_INFO("Loading RS690/RS740 Microcode\n");
fw_name = FIRMWARE_RS690; fw_name = FIRMWARE_RS690;
} else if (rdev->family == CHIP_RS600) { break;
case CHIP_RS600:
DRM_INFO("Loading RS600 Microcode\n"); DRM_INFO("Loading RS600 Microcode\n");
fw_name = FIRMWARE_RS600; fw_name = FIRMWARE_RS600;
} else if ((rdev->family == CHIP_RV515) || break;
(rdev->family == CHIP_R520) ||
(rdev->family == CHIP_RV530) || case CHIP_RV515:
(rdev->family == CHIP_R580) || case CHIP_R520:
(rdev->family == CHIP_RV560) || case CHIP_RV530:
(rdev->family == CHIP_RV570)) { case CHIP_R580:
case CHIP_RV560:
case CHIP_RV570:
DRM_INFO("Loading R500 Microcode\n"); DRM_INFO("Loading R500 Microcode\n");
fw_name = FIRMWARE_R520; fw_name = FIRMWARE_R520;
break;
default:
DRM_ERROR("Unsupported Radeon family %u\n", rdev->family);
return -EINVAL;
} }
err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);

View File

@@ -1727,23 +1727,29 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record; fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
if (fake_edid_record->ucFakeEDIDLength) { if (fake_edid_record->ucFakeEDIDLength) {
struct edid *edid; struct edid *edid;
int edid_size = int edid_size;
max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
edid = kmalloc(edid_size, GFP_KERNEL);
if (edid) {
memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
fake_edid_record->ucFakeEDIDLength);
if (fake_edid_record->ucFakeEDIDLength == 128)
edid_size = fake_edid_record->ucFakeEDIDLength;
else
edid_size = fake_edid_record->ucFakeEDIDLength * 128;
edid = kmemdup(&fake_edid_record->ucFakeEDIDString[0],
edid_size, GFP_KERNEL);
if (edid) {
if (drm_edid_is_valid(edid)) { if (drm_edid_is_valid(edid)) {
rdev->mode_info.bios_hardcoded_edid = edid; rdev->mode_info.bios_hardcoded_edid = edid;
rdev->mode_info.bios_hardcoded_edid_size = edid_size; rdev->mode_info.bios_hardcoded_edid_size = edid_size;
} else } else {
kfree(edid); kfree(edid);
}
} }
record += struct_size(fake_edid_record,
ucFakeEDIDString,
edid_size);
} else {
/* empty fake edid record must be 3 bytes long */
record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
} }
record += fake_edid_record->ucFakeEDIDLength ?
fake_edid_record->ucFakeEDIDLength + 2 :
sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
break; break;
case LCD_PANEL_RESOLUTION_RECORD_TYPE: case LCD_PANEL_RESOLUTION_RECORD_TYPE:
panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;

View File

@@ -308,8 +308,8 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
if (info->is_yuv) if (info->is_yuv)
is_yuv = true; is_yuv = true;
if (dst_w > 3840) { if (dst_w > 4096) {
DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n"); DRM_DEV_ERROR(vop->dev, "Maximum dst width (4096) exceeded\n");
return; return;
} }

View File

@@ -152,10 +152,12 @@ static int stm_drm_platform_probe(struct platform_device *pdev)
ret = drm_dev_register(ddev, 0); ret = drm_dev_register(ddev, 0);
if (ret) if (ret)
goto err_put; goto err_unload;
return 0; return 0;
err_unload:
drv_unload(ddev);
err_put: err_put:
drm_dev_put(ddev); drm_dev_put(ddev);

View File

@@ -1468,6 +1468,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
DRM_ERROR("Surface size cannot exceed %dx%d", DRM_ERROR("Surface size cannot exceed %dx%d",
dev_priv->texture_max_width, dev_priv->texture_max_width,
dev_priv->texture_max_height); dev_priv->texture_max_height);
ret = -EINVAL;
goto err_out; goto err_out;
} }

View File

@@ -1482,7 +1482,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
u32 len = hid_report_len(report) + 7; u32 len = hid_report_len(report) + 7;
return kmalloc(len, flags); return kzalloc(len, flags);
} }
EXPORT_SYMBOL_GPL(hid_alloc_report_buf); EXPORT_SYMBOL_GPL(hid_alloc_report_buf);

View File

@@ -919,6 +919,8 @@
#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES 0xc056 #define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES 0xc056
#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES 0xc057 #define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES 0xc057
#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES 0xc058 #define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES 0xc058
#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3325_SERIES 0x430c
#define USB_DEVICE_ID_PLANTRONICS_ENCOREPRO_500_SERIES 0x431e
#define USB_VENDOR_ID_PANASONIC 0x04da #define USB_VENDOR_ID_PANASONIC 0x04da
#define USB_DEVICE_ID_PANABOARD_UBT780 0x1044 #define USB_DEVICE_ID_PANABOARD_UBT780 0x1044

View File

@@ -1986,6 +1986,11 @@ static const struct hid_device_id mt_devices[] = {
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
0x347d, 0x7853) }, 0x347d, 0x7853) },
/* HONOR MagicBook Art 14 touchpad */
{ .driver_data = MT_CLS_VTL,
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
0x35cc, 0x0104) },
/* Ilitek dual touch panel */ /* Ilitek dual touch panel */
{ .driver_data = MT_CLS_NSMU, { .driver_data = MT_CLS_NSMU,
MT_USB_DEVICE(USB_VENDOR_ID_ILITEK, MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,

View File

@@ -41,8 +41,10 @@
(usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
#define PLT_QUIRK_DOUBLE_VOLUME_KEYS BIT(0) #define PLT_QUIRK_DOUBLE_VOLUME_KEYS BIT(0)
#define PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS BIT(1)
#define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */ #define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */
#define PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT 220 /* ms */
struct plt_drv_data { struct plt_drv_data {
unsigned long device_type; unsigned long device_type;
@@ -140,6 +142,21 @@ static int plantronics_event(struct hid_device *hdev, struct hid_field *field,
drv_data->last_volume_key_ts = cur_ts; drv_data->last_volume_key_ts = cur_ts;
} }
if (drv_data->quirks & PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS) {
unsigned long prev_ts, cur_ts;
/* Usages are filtered in plantronics_usages. */
if (!value) /* Handle key presses only. */
return 0;
prev_ts = drv_data->last_volume_key_ts;
cur_ts = jiffies;
if (jiffies_to_msecs(cur_ts - prev_ts) <= PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT)
return 1; /* Ignore the followed opposite volume key. */
drv_data->last_volume_key_ts = cur_ts;
}
return 0; return 0;
} }
@@ -213,6 +230,12 @@ static const struct hid_device_id plantronics_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES), USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES),
.driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS }, .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3325_SERIES),
.driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS },
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
USB_DEVICE_ID_PLANTRONICS_ENCOREPRO_500_SERIES),
.driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS },
{ HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },
{ } { }
}; };

View File

@@ -117,9 +117,10 @@ static inline int LIMIT_TO_MV(int limit, int range)
return limit * range / 256; return limit * range / 256;
} }
static inline int MV_TO_LIMIT(int mv, int range) static inline int MV_TO_LIMIT(unsigned long mv, int range)
{ {
return clamp_val(DIV_ROUND_CLOSEST(mv * 256, range), 0, 255); mv = clamp_val(mv, 0, ULONG_MAX / 256);
return DIV_ROUND_CLOSEST(clamp_val(mv * 256, 0, range * 255), range);
} }
static inline int ADC_TO_CURR(int adc, int gain) static inline int ADC_TO_CURR(int adc, int gain)

View File

@@ -57,6 +57,7 @@ static const struct platform_device_id ntc_thermistor_id[] = {
{ "ncp15xh103", TYPE_NCPXXXH103 }, { "ncp15xh103", TYPE_NCPXXXH103 },
{ }, { },
}; };
MODULE_DEVICE_TABLE(platform, ntc_thermistor_id);
/* /*
* A compensation table should be sorted by the values of .ohm * A compensation table should be sorted by the values of .ohm

View File

@@ -251,6 +251,7 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table)
{ {
tmc_free_table_pages(sg_table); tmc_free_table_pages(sg_table);
tmc_free_data_pages(sg_table); tmc_free_data_pages(sg_table);
kfree(sg_table);
} }
long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata) long tmc_sg_get_rwp_offset(struct tmc_drvdata *drvdata)
@@ -345,7 +346,6 @@ struct tmc_sg_table *tmc_alloc_sg_table(struct device *dev,
rc = tmc_alloc_table_pages(sg_table); rc = tmc_alloc_table_pages(sg_table);
if (rc) { if (rc) {
tmc_free_sg_table(sg_table); tmc_free_sg_table(sg_table);
kfree(sg_table);
return ERR_PTR(rc); return ERR_PTR(rc);
} }

View File

@@ -159,6 +159,13 @@ struct aspeed_i2c_bus {
static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus); static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
/* precondition: bus.lock has been acquired. */
static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
{
bus->master_state = ASPEED_I2C_MASTER_STOP;
writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
}
static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus) static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
{ {
unsigned long time_left, flags; unsigned long time_left, flags;
@@ -176,7 +183,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
command); command);
reinit_completion(&bus->cmd_complete); reinit_completion(&bus->cmd_complete);
writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG); aspeed_i2c_do_stop(bus);
spin_unlock_irqrestore(&bus->lock, flags); spin_unlock_irqrestore(&bus->lock, flags);
time_left = wait_for_completion_timeout( time_left = wait_for_completion_timeout(
@@ -350,13 +357,6 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
writel(command, bus->base + ASPEED_I2C_CMD_REG); writel(command, bus->base + ASPEED_I2C_CMD_REG);
} }
/* precondition: bus.lock has been acquired. */
static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
{
bus->master_state = ASPEED_I2C_MASTER_STOP;
writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
}
/* precondition: bus.lock has been acquired. */ /* precondition: bus.lock has been acquired. */
static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus) static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
{ {

View File

@@ -1674,8 +1674,15 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
i801_add_tco(priv); i801_add_tco(priv);
/*
* adapter.name is used by platform code to find the main I801 adapter
* to instantiante i2c_clients, do not change.
*/
snprintf(priv->adapter.name, sizeof(priv->adapter.name), snprintf(priv->adapter.name, sizeof(priv->adapter.name),
"SMBus I801 adapter at %04lx", priv->smba); "SMBus %s adapter at %04lx",
(priv->features & FEATURE_IDF) ? "I801 IDF" : "I801",
priv->smba);
err = i2c_add_adapter(&priv->adapter); err = i2c_add_adapter(&priv->adapter);
if (err) { if (err) {
platform_device_unregister(priv->tco_pdev); platform_device_unregister(priv->tco_pdev);

View File

@@ -107,8 +107,7 @@ static int sch_transaction(void)
if (retries > MAX_RETRIES) { if (retries > MAX_RETRIES) {
dev_err(&sch_adapter.dev, "SMBus Timeout!\n"); dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
result = -ETIMEDOUT; result = -ETIMEDOUT;
} } else if (temp & 0x04) {
if (temp & 0x04) {
result = -EIO; result = -EIO;
dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be " dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be "
"locked until next hard reset. (sorry!)\n"); "locked until next hard reset. (sorry!)\n");

View File

@@ -478,14 +478,17 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
goto out; goto out;
} }
xiic_fill_tx_fifo(i2c); if (xiic_tx_space(i2c)) {
xiic_fill_tx_fifo(i2c);
/* current message sent and there is space in the fifo */ } else {
if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >= 2) { /* current message fully written */
dev_dbg(i2c->adap.dev.parent, dev_dbg(i2c->adap.dev.parent,
"%s end of message sent, nmsgs: %d\n", "%s end of message sent, nmsgs: %d\n",
__func__, i2c->nmsgs); __func__, i2c->nmsgs);
if (i2c->nmsgs > 1) { /* Don't move onto the next message until the TX FIFO empties,
* to ensure that a NAK is not missed.
*/
if (i2c->nmsgs > 1 && (pend & XIIC_INTR_TX_EMPTY_MASK)) {
i2c->nmsgs--; i2c->nmsgs--;
i2c->tx_msg++; i2c->tx_msg++;
xfer_more = 1; xfer_more = 1;
@@ -496,11 +499,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
"%s Got TX IRQ but no more to do...\n", "%s Got TX IRQ but no more to do...\n",
__func__); __func__);
} }
} else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1)) }
/* current frame is sent and is last,
* make sure to disable tx half
*/
xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
} }
out: out:
dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr);

View File

@@ -896,6 +896,8 @@ config TI_ADS7950
config TI_ADS8688 config TI_ADS8688
tristate "Texas Instruments ADS8688" tristate "Texas Instruments ADS8688"
depends on SPI && OF depends on SPI && OF
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help help
If you say yes here you get support for Texas Instruments ADS8684 and If you say yes here you get support for Texas Instruments ADS8684 and
and ADS8688 ADC chips and ADS8688 ADC chips

View File

@@ -46,7 +46,7 @@ static ssize_t _hid_sensor_set_report_latency(struct device *dev,
latency = integer * 1000 + fract / 1000; latency = integer * 1000 + fract / 1000;
ret = hid_sensor_set_report_latency(attrb, latency); ret = hid_sensor_set_report_latency(attrb, latency);
if (ret < 0) if (ret < 0)
return len; return ret;
attrb->latency_ms = hid_sensor_get_report_latency(attrb); attrb->latency_ms = hid_sensor_get_report_latency(attrb);

View File

@@ -335,6 +335,7 @@ config STM32_DAC
config STM32_DAC_CORE config STM32_DAC_CORE
tristate tristate
select REGMAP_MMIO
config TI_DAC082S085 config TI_DAC082S085
tristate "Texas Instruments 8/10/12-bit 2/4-channel DAC driver" tristate "Texas Instruments 8/10/12-bit 2/4-channel DAC driver"

View File

@@ -145,6 +145,10 @@ static const struct opt3001_scale opt3001_scales[] = {
.val = 20966, .val = 20966,
.val2 = 400000, .val2 = 400000,
}, },
{
.val = 41932,
.val2 = 800000,
},
{ {
.val = 83865, .val = 83865,
.val2 = 600000, .val2 = 600000,

View File

@@ -673,22 +673,8 @@ static int ak8975_start_read_axis(struct ak8975_data *data,
if (ret < 0) if (ret < 0)
return ret; return ret;
/* This will be executed only for non-interrupt based waiting case */ /* Return with zero if the data is ready. */
if (ret & data->def->ctrl_masks[ST1_DRDY]) { return !data->def->ctrl_regs[ST1_DRDY];
ret = i2c_smbus_read_byte_data(client,
data->def->ctrl_regs[ST2]);
if (ret < 0) {
dev_err(&client->dev, "Error in reading ST2\n");
return ret;
}
if (ret & (data->def->ctrl_masks[ST2_DERR] |
data->def->ctrl_masks[ST2_HOFL])) {
dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
return -EINVAL;
}
}
return 0;
} }
/* Retrieve raw flux value for one of the x, y, or z axis. */ /* Retrieve raw flux value for one of the x, y, or z axis. */
@@ -715,6 +701,20 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
if (ret < 0) if (ret < 0)
goto exit; goto exit;
/* Read out ST2 for release lock on measurment data. */
ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST2]);
if (ret < 0) {
dev_err(&client->dev, "Error in reading ST2\n");
goto exit;
}
if (ret & (data->def->ctrl_masks[ST2_DERR] |
data->def->ctrl_masks[ST2_HOFL])) {
dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
ret = -EINVAL;
goto exit;
}
mutex_unlock(&data->lock); mutex_unlock(&data->lock);
pm_runtime_mark_last_busy(&data->client->dev); pm_runtime_mark_last_busy(&data->client->dev);

View File

@@ -1178,7 +1178,7 @@ static int __init iw_cm_init(void)
if (ret) if (ret)
return ret; return ret;
iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", 0); iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", WQ_MEM_RECLAIM);
if (!iwcm_wq) if (!iwcm_wq)
goto err_alloc; goto err_alloc;

View File

@@ -150,7 +150,7 @@ struct bnxt_qplib_swqe {
}; };
u32 q_key; u32 q_key;
u32 dst_qp; u32 dst_qp;
u16 avid; u32 avid;
} send; } send;
/* Send Raw Ethernet and QP1 */ /* Send Raw Ethernet and QP1 */

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