Merge drm/drm-fixes into drm-misc-fixes

Updating drm-misc-fixes to the state of v7.2.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
This commit is contained in:
Thomas Zimmermann
2026-08-31 14:43:36 +02:00
192 changed files with 2159 additions and 982 deletions

View File

@@ -212,6 +212,10 @@ Christophe Ricard <christophe.ricard@gmail.com>
Christopher Obbard <christopher.obbard@linaro.org> <chris.obbard@collabora.com>
Christoph Hellwig <hch@lst.de>
Christoph Manszewski <c.manszewski@gmail.com> <christoph.manszewski@intel.com>
Christoph Paasch <cpaasch@openai.com> <christoph.paasch@gmail.com>
Christoph Paasch <cpaasch@openai.com> <christoph.paasch@student.uclouvain.be>
Christoph Paasch <cpaasch@openai.com> <christoph.paasch@uclouvain.be>
Christoph Paasch <cpaasch@openai.com> <cpaasch@apple.com>
Chuck Lever <cel@kernel.org> <chuck.lever@oracle.com>
Chuck Lever <cel@kernel.org> <cel@netapp.com>
Chuck Lever <cel@kernel.org> <cel@citi.umich.edu>

View File

@@ -7568,6 +7568,10 @@ Kernel parameters
See Documentation/admin-guide/mm/transhuge.rst for more
details.
tlbi= [X86-64]
Format: {ipi}
ipi: switch to IPI-based TLB flushing
topology= [S390,EARLY]
Format: {off | on}
Specify if the kernel should make use of the cpu

View File

@@ -7,8 +7,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Global Clock & Reset Controller on MSM8937, MSM8940, MSM8953 and SDM439
maintainers:
- Adam Skladowski <a_skl39@protonmail.com>
- Sireesh Kodali <sireeshkodali@protonmail.com>
- Barnabas Czeman <barnabas.czeman@mainlining.org>
description: |

View File

@@ -8,7 +8,6 @@ title: Qualcomm Global Clock & Reset Controller on IPQ9574
maintainers:
- Bjorn Andersson <andersson@kernel.org>
- Anusha Rao <quic_anusha@quicinc.com>
description: |
Qualcomm global clock control module provides the clocks, resets and power

View File

@@ -8,7 +8,6 @@ title: Qualcomm Networking Sub System Clock & Reset Controller on IPQ9574 and IP
maintainers:
- Bjorn Andersson <andersson@kernel.org>
- Anusha Rao <quic_anusha@quicinc.com>
description: |
Qualcomm networking sub system clock control module provides the clocks,

View File

@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung Exynos Auto v9 SoC clock controller
maintainers:
- Chanho Park <chanho61.park@samsung.com>
- Alim Akhtar <alim.akhtar@samsung.com>
- Chanwoo Choi <cw00.choi@samsung.com>
- Krzysztof Kozlowski <krzk@kernel.org>
- Sylwester Nawrocki <s.nawrocki@samsung.com>

View File

@@ -47,6 +47,7 @@ description: |
For PM8150, smps1 - smps10, ldo1 - ldo18
For PM8150L, smps1 - smps8, ldo1 - ldo11, bob, flash, rgb
For PM8350, smps1 - smps12, ldo1 - ldo10
For PM8350B, ldo1
For PM8350C, smps1 - smps10, ldo1 - ldo13, bob
For PM8450, smps1 - smps6, ldo1 - ldo4
For PM8550, smps1 - smps6, ldo1 - ldo17, bob1 - bob2
@@ -82,6 +83,7 @@ properties:
- qcom,pm8150-rpmh-regulators
- qcom,pm8150l-rpmh-regulators
- qcom,pm8350-rpmh-regulators
- qcom,pm8350b-rpmh-regulators
- qcom,pm8350c-rpmh-regulators
- qcom,pm8450-rpmh-regulators
- qcom,pm8550-rpmh-regulators
@@ -337,6 +339,15 @@ allOf:
patternProperties:
"^vdd-s([1-9]|1[0-2])-supply$": true
- if:
properties:
compatible:
enum:
- qcom,pm8350b-rpmh-regulators
then:
properties:
vdd-l1-supply: true
- if:
properties:
compatible:

View File

@@ -53,6 +53,11 @@ properties:
- sophgo,sg2042-spi
- thead,th1520-spi
- const: snps,dw-apb-ssi
- description: Vendor controllers compatible with v1.01a
items:
- enum:
- axiado,ax3005-spi
- const: snps,dwc-ssi-1.01a
- description: Vendor controllers which use snps,dwc-ssi-2.00a as fallback
items:
- enum:

View File

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

View File

@@ -186,12 +186,12 @@ soc {
/* Required to get >32-bit DMA via DARTs */
dma-ranges = <0 0 0 0 0xffffffff 0xffffc000>;
i2c0: i2c@235010000 {
i2c0: i2c@2a1010000 {
compatible = "apple,t8122-i2c", "apple,t8103-i2c";
reg = <0x2 0x35010000 0x0 0x4000>;
reg = <0x2 0xa1010000 0x0 0x4000>;
clocks = <&clkref>;
interrupt-parent = <&aic>;
interrupts = <AIC_IRQ 761 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <AIC_IRQ 780 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-0 = <&i2c0_pins>;
pinctrl-names = "default";
#address-cells = <0x1>;
@@ -200,12 +200,12 @@ i2c0: i2c@235010000 {
status = "disabled";
};
i2c1: i2c@235014000 {
i2c1: i2c@2a1014000 {
compatible = "apple,t8122-i2c", "apple,t8103-i2c";
reg = <0x2 0x35014000 0x0 0x4000>;
reg = <0x2 0xa1014000 0x0 0x4000>;
clocks = <&clkref>;
interrupt-parent = <&aic>;
interrupts = <AIC_IRQ 762 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <AIC_IRQ 781 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-0 = <&i2c1_pins>;
pinctrl-names = "default";
#address-cells = <0x1>;
@@ -214,12 +214,12 @@ i2c1: i2c@235014000 {
status = "disabled";
};
i2c2: i2c@235018000 {
i2c2: i2c@2a1018000 {
compatible = "apple,t8122-i2c", "apple,t8103-i2c";
reg = <0x2 0x35018000 0x0 0x4000>;
reg = <0x2 0xa1018000 0x0 0x4000>;
clocks = <&clkref>;
interrupt-parent = <&aic>;
interrupts = <AIC_IRQ 763 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <AIC_IRQ 782 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-0 = <&i2c2_pins>;
pinctrl-names = "default";
#address-cells = <0x1>;
@@ -228,12 +228,12 @@ i2c2: i2c@235018000 {
status = "disabled";
};
i2c3: i2c@23501c000 {
i2c3: i2c@2a101c000 {
compatible = "apple,t8122-i2c", "apple,t8103-i2c";
reg = <0x2 0x3501c000 0x0 0x4000>;
reg = <0x2 0xa101c000 0x0 0x4000>;
clocks = <&clkref>;
interrupt-parent = <&aic>;
interrupts = <AIC_IRQ 764 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <AIC_IRQ 783 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-0 = <&i2c3_pins>;
pinctrl-names = "default";
#address-cells = <0x1>;
@@ -242,12 +242,12 @@ i2c3: i2c@23501c000 {
status = "disabled";
};
i2c4: i2c@235020000 {
i2c4: i2c@2a1020000 {
compatible = "apple,t8122-i2c", "apple,t8103-i2c";
reg = <0x2 0x35020000 0x0 0x4000>;
reg = <0x2 0xa1020000 0x0 0x4000>;
clocks = <&clkref>;
interrupt-parent = <&aic>;
interrupts = <AIC_IRQ 765 IRQ_TYPE_LEVEL_HIGH>;
interrupts = <AIC_IRQ 784 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-0 = <&i2c4_pins>;
pinctrl-names = "default";
#address-cells = <0x1>;

View File

@@ -3176,6 +3176,8 @@ timer {
<GIC_PPI 11
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 15
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
interrupt-parent = <&gic>;
always-on;

View File

@@ -549,6 +549,10 @@ config CACHE_COPYBACK
endchoice
endif # HAVE_CACHE_CB
config NR_CPUS
int
default "1"
# Coldfire cores that do not have a data cache configured can do coherent DMA.
config COLDFIRE_COHERENT_DMA
bool

View File

@@ -26,6 +26,8 @@
| SPR_SR_DCE | SPR_SR_SM)
#define USER_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
| SPR_SR_DCE | SPR_SR_IEE | SPR_SR_TEE)
/* SR bits user space may change via sigreturn, the rest stay kernel owned */
#define SPR_SR_USER_MASK (SPR_SR_F | SPR_SR_CY | SPR_SR_OV)
/*
* User space process size. This is hardcoded into a few places,

View File

@@ -74,6 +74,7 @@ static long save_fp_state(struct sigcontext __user *sc)
static int restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
{
unsigned long old_sr = regs->sr;
int err = 0;
/* Always make any pending restarted system calls return -EINTR */
@@ -89,8 +90,8 @@ static int restore_sigcontext(struct pt_regs *regs,
err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long));
err |= restore_fp_state(sc);
/* make sure the SM-bit is cleared so user-mode cannot fool us */
regs->sr &= ~SPR_SR_SM;
/* keep the privileged SR bits kernel owned, restore only user flags */
regs->sr = (old_sr & ~SPR_SR_USER_MASK) | (regs->sr & SPR_SR_USER_MASK);
regs->orig_gpr11 = -1; /* Avoid syscall restart checks */

View File

@@ -12,6 +12,7 @@
#include <linux/stop_machine.h>
#include <asm/cacheflush.h>
#include <asm/text-patching.h>
#include <asm/insn.h>
#ifdef CONFIG_DYNAMIC_FTRACE
void ftrace_arch_code_modify_prepare(void)
@@ -63,7 +64,9 @@ static int __ftrace_modify_call(unsigned long source, unsigned long target, bool
if (copy_from_kernel_nofault(replaced, (void *)source, 2 * MCOUNT_INSN_SIZE))
return -EFAULT;
if (replaced[0] != call[0]) {
/* Bypass the check if the auipc insn is a kprobe breakpoint */
if (replaced[0] != call[0] &&
!(riscv_insn_is_ebreak(replaced[0]) || riscv_insn_is_c_ebreak(replaced[0]))) {
pr_err("%p: expected (%08x) but got (%08x)\n",
(void *)source, call[0], replaced[0]);
return -EINVAL;

View File

@@ -411,4 +411,10 @@ static int __init check_unaligned_access_all_cpus(void)
return 0;
}
late_initcall(check_unaligned_access_all_cpus);
/*
* Run after clocksource_done_booting() so measure_cycles() uses a stable
* clocksource, but before rootfs_initcall() enables usermode helpers. Those
* helpers can reach hwprobe and populate the vDSO cache, so async hwprobe
* probes must be registered first.
*/
fs_initcall_sync(check_unaligned_access_all_cpus);

View File

@@ -83,8 +83,13 @@ strnlen_zbb:
sub t3, t3, t2
slli t2, t2, 3
/* Aligned boundary. */
/*
* Aligned boundary. Use the address of the last valid byte
* (s + count - 1) to avoid loading a word past the count
* boundary in the loop below. count == 0 is handled above.
*/
add t4, a0, a1
addi t4, t4, -1
andi t4, t4, -SZREG
/* Get the first word. */
@@ -120,6 +125,9 @@ strnlen_zbb:
bgtu t3, a0, 2f
/* All remaining bytes are in the first word, no loop needed. */
bgeu t0, t4, 2f
/* Prepare for the word comparison loop. */
addi t2, t0, SZREG
li t3, -1

View File

@@ -2664,3 +2664,13 @@ void __init arch_cpu_finalize_init(void)
*/
mem_encrypt_init();
}
/* Control TLB flushing methods */
static int __init tlbi_setup(char *str)
{
if (!strcmp(str, "ipi"))
setup_clear_cpu_cap(X86_FEATURE_INVLPGB);
return 1;
}
__setup("tlbi=", tlbi_setup);

View File

@@ -32,6 +32,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/net.h>
#include <linux/string.h>
#include <net/sock.h>
static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
@@ -309,7 +310,12 @@ static struct proto_ops algif_skcipher_ops_nokey = {
static void *skcipher_bind(const char *name)
{
return crypto_alloc_skcipher(name, 0, AF_ALG_CRYPTOAPI_MASK);
u32 mask = AF_ALG_CRYPTOAPI_MASK;
if (strcmp(name, "cbc(paes)") == 0)
mask = 0;
return crypto_alloc_skcipher(name, 0, mask);
}
static void skcipher_release(void *private)

View File

@@ -747,7 +747,7 @@ static int crypto_rfc4309_create(struct crypto_template *tmpl,
inst->alg.ivsize = 8;
inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
inst->alg.maxauthsize = 16;
inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);

View File

@@ -123,6 +123,8 @@ static void regcache_hw_exit(struct regmap *map)
int regcache_init(struct regmap *map, const struct regmap_config *config)
{
bool sort_defaults = false;
unsigned int reg_prev = 0;
int count = 0;
int ret;
int i;
@@ -149,10 +151,16 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
return -EINVAL;
}
for (i = 0; i < config->num_reg_defaults; i++)
for (i = 0; i < config->num_reg_defaults; i++) {
if (config->reg_defaults[i].reg % map->reg_stride)
return -EINVAL;
if (reg_prev > config->reg_defaults[i].reg)
sort_defaults = true;
reg_prev = config->reg_defaults[i].reg;
}
for (i = 0; i < ARRAY_SIZE(cache_types); i++)
if (cache_types[i]->type == map->cache_type)
break;
@@ -186,6 +194,13 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
sizeof(*map->reg_defaults), GFP_KERNEL);
if (!tmp_buf)
return -ENOMEM;
/* regcache_lookup_reg() bsearch()es this array */
if (sort_defaults) {
dev_warn(map->dev,
"Driver needs fixing: Unsorted reg_defaults, sorting the copy\n");
regcache_sort_defaults(tmp_buf, map->num_reg_defaults);
}
map->reg_defaults = tmp_buf;
} else if (map->num_reg_defaults_raw) {
count = regcache_count_cacheable_registers(map);
@@ -727,14 +742,6 @@ unsigned int regcache_get_val(struct regmap *map, const void *base,
return -1;
}
static int regcache_default_cmp(const void *a, const void *b)
{
const struct reg_default *_a = a;
const struct reg_default *_b = b;
return _a->reg - _b->reg;
}
int regcache_lookup_reg(struct regmap *map, unsigned int reg)
{
struct reg_default key;
@@ -744,7 +751,7 @@ int regcache_lookup_reg(struct regmap *map, unsigned int reg)
key.def = 0;
r = bsearch(&key, map->reg_defaults, map->num_reg_defaults,
sizeof(struct reg_default), regcache_default_cmp);
sizeof(struct reg_default), regcache_defaults_cmp);
if (r)
return r - map->reg_defaults;

View File

@@ -56,10 +56,10 @@ static int regmap_sdw_mbq_poll_busy(struct sdw_slave *slave, unsigned int reg,
reg = SDW_SDCA_CTL(SDW_SDCA_CTL_FUNC(reg), 0,
SDCA_CTL_ENTITY_0_FUNCTION_STATUS, 0);
if (ctx->readable_reg(dev, reg)) {
if (!ctx->readable_reg || ctx->readable_reg(dev, reg)) {
ret = read_poll_timeout(sdw_read_no_pm, val,
val < 0 || !(val & SDCA_CTL_ENTITY_0_FUNCTION_BUSY),
ctx->cfg.timeout_us, ctx->cfg.retry_us,
ctx->cfg.retry_us, ctx->cfg.timeout_us,
false, slave, reg);
if (val < 0)
return val;

View File

@@ -3306,6 +3306,26 @@ static int nla_put_drbd_cfg_context(struct sk_buff *skb,
return -EMSGSIZE;
}
/*
* net_conf_to_skb() serializes the shared secret verbatim. Any path that can
* answer a request from an unprivileged process must pass exclude_sensitive,
* so the secret is blanked in a private copy before it reaches the skb.
*/
static int net_conf_to_skb_sanitized(struct sk_buff *skb, struct net_conf *nc,
bool exclude_sensitive)
{
struct net_conf nc_clean;
if (!exclude_sensitive)
return net_conf_to_skb(skb, nc);
nc_clean = *nc;
memset(nc_clean.shared_secret, 0, sizeof(nc_clean.shared_secret));
nc_clean.shared_secret_len = 0;
return net_conf_to_skb(skb, &nc_clean);
}
/*
* The generic netlink dump callbacks are called outside the genl_lock(), so
* they cannot use the simple attribute parsing code which uses global
@@ -3621,7 +3641,8 @@ int drbd_nl_get_connections_dumpit(struct sk_buff *skb, struct netlink_callback
goto out;
net_conf = rcu_dereference(connection->net_conf);
if (net_conf) {
err = net_conf_to_skb(skb, net_conf);
err = net_conf_to_skb_sanitized(skb, net_conf,
!capable(CAP_SYS_ADMIN));
if (err)
goto out;
}
@@ -3842,18 +3863,8 @@ static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
struct net_conf *nc;
nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
if (nc) {
if (exclude_sensitive) {
struct net_conf nc_clean = *nc;
memset(nc_clean.shared_secret, 0,
sizeof(nc_clean.shared_secret));
nc_clean.shared_secret_len = 0;
err = net_conf_to_skb(skb, &nc_clean);
} else {
err = net_conf_to_skb(skb, nc);
}
}
if (nc)
err = net_conf_to_skb_sanitized(skb, nc, exclude_sensitive);
}
rcu_read_unlock();
if (err)
@@ -4058,7 +4069,7 @@ static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
struct net_conf *nc;
nc = rcu_dereference(connection->net_conf);
if (nc && net_conf_to_skb(skb, nc) != 0)
if (nc && net_conf_to_skb_sanitized(skb, nc, true) != 0)
goto cancel;
}
goto done;

View File

@@ -15,66 +15,48 @@
#define PHY_MUX_PHY_SRC 0
#define PHY_MUX_REF_SRC 2
#define XO_RATE 19200000UL
static inline struct clk_regmap_phy_mux *to_clk_regmap_phy_mux(struct clk_regmap *clkr)
{
return container_of(clkr, struct clk_regmap_phy_mux, clkr);
}
static unsigned long phy_mux_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
static int phy_mux_is_enabled(struct clk_hw *hw)
{
struct clk_regmap *clkr = to_clk_regmap(hw);
struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr);
u32 val;
unsigned int val;
regmap_read(clkr->regmap, phy_mux->reg, &val);
val = FIELD_GET(PHY_MUX_MASK, val);
switch (FIELD_GET(PHY_MUX_MASK, val)) {
case PHY_MUX_PHY_SRC:
return ULONG_MAX;
case PHY_MUX_REF_SRC:
return XO_RATE;
default:
return 0;
}
WARN_ON(val != PHY_MUX_PHY_SRC && val != PHY_MUX_REF_SRC);
return val == PHY_MUX_PHY_SRC;
}
static int phy_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
if (req->rate == XO_RATE || req->rate == ULONG_MAX)
return 0;
return -EINVAL;
}
static int phy_mux_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
static int phy_mux_enable(struct clk_hw *hw)
{
struct clk_regmap *clkr = to_clk_regmap(hw);
struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr);
u32 val;
switch (rate) {
case XO_RATE:
val = PHY_MUX_REF_SRC;
break;
case ULONG_MAX:
val = PHY_MUX_PHY_SRC;
break;
default:
return -EINVAL;
}
return regmap_update_bits(clkr->regmap, phy_mux->reg,
PHY_MUX_MASK,
FIELD_PREP(PHY_MUX_MASK, PHY_MUX_PHY_SRC));
}
static void phy_mux_disable(struct clk_hw *hw)
{
struct clk_regmap *clkr = to_clk_regmap(hw);
struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr);
regmap_update_bits(clkr->regmap, phy_mux->reg,
PHY_MUX_MASK,
FIELD_PREP(PHY_MUX_MASK, val));
return 0;
FIELD_PREP(PHY_MUX_MASK, PHY_MUX_REF_SRC));
}
const struct clk_ops clk_regmap_phy_mux_ops = {
.recalc_rate = phy_mux_recalc_rate,
.determine_rate = phy_mux_determine_rate,
.set_rate = phy_mux_set_rate,
.enable = phy_mux_enable,
.disable = phy_mux_disable,
.is_enabled = phy_mux_is_enabled,
};
EXPORT_SYMBOL_GPL(clk_regmap_phy_mux_ops);

View File

@@ -756,7 +756,7 @@ static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
.parent_data = disp_cc_parent_data_11,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_11),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_shared_ops,
.ops = &clk_rcg2_shared_no_init_park_ops,
},
};

View File

@@ -895,7 +895,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
MUX(I2S2_2CH_MCLKOUT, "i2s2_2ch_mclkout", i2s2_2ch_mclkout_p, CLK_SET_RATE_PARENT,
RK3588_CLKSEL_CON(30), 2, 1, MFLAGS),
GATE_GRF(I2S2_2CH_MCLKOUT_TO_IO, "i2s2_2ch_mclkout_to_io", "i2s2_2ch_mclkout",
0, RK3588_SYSGRF_SOC_CON6, 2, GFLAGS, grf_type_sys),
CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 2, GFLAGS, grf_type_sys),
COMPOSITE(CLK_I2S3_2CH_SRC, "clk_i2s3_2ch_src", gpll_aupll_p, 0,
RK3588_CLKSEL_CON(30), 8, 1, MFLAGS, 3, 5, DFLAGS,
@@ -912,7 +912,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
MUX(I2S3_2CH_MCLKOUT, "i2s3_2ch_mclkout", i2s3_2ch_mclkout_p, CLK_SET_RATE_PARENT,
RK3588_CLKSEL_CON(32), 2, 1, MFLAGS),
GATE_GRF(I2S3_2CH_MCLKOUT_TO_IO, "i2s3_2ch_mclkout_to_io", "i2s3_2ch_mclkout",
0, RK3588_SYSGRF_SOC_CON6, 7, GFLAGS, grf_type_sys),
CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 7, GFLAGS, grf_type_sys),
GATE(PCLK_ACDCDIG, "pclk_acdcdig", "pclk_audio_root", 0,
RK3588_CLKGATE_CON(7), 11, GFLAGS),
GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_audio_root", 0,
@@ -942,7 +942,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
MUX(I2S0_8CH_MCLKOUT, "i2s0_8ch_mclkout", i2s0_8ch_mclkout_p, CLK_SET_RATE_PARENT,
RK3588_CLKSEL_CON(28), 2, 2, MFLAGS),
GATE_GRF(I2S0_8CH_MCLKOUT_TO_IO, "i2s0_8ch_mclkout_to_io", "i2s0_8ch_mclkout",
0, RK3588_SYSGRF_SOC_CON6, 0, GFLAGS, grf_type_sys),
CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 0, GFLAGS, grf_type_sys),
GATE(HCLK_PDM1, "hclk_pdm1", "hclk_audio_root", 0,
RK3588_CLKGATE_CON(9), 6, GFLAGS),
@@ -2229,7 +2229,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
MUX(I2S1_8CH_MCLKOUT, "i2s1_8ch_mclkout", i2s1_8ch_mclkout_p, CLK_SET_RATE_PARENT,
RK3588_PMU_CLKSEL_CON(9), 2, 2, MFLAGS),
GATE_GRF(I2S1_8CH_MCLKOUT_TO_IO, "i2s1_8ch_mclkout_to_io", "i2s1_8ch_mclkout",
0, RK3588_SYSGRF_SOC_CON6, 1, GFLAGS, grf_type_sys),
CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 1, GFLAGS, grf_type_sys),
GATE(PCLK_PMU1, "pclk_pmu1", "pclk_pmu0_root", CLK_IS_CRITICAL,
RK3588_PMU_CLKGATE_CON(1), 0, GFLAGS),
GATE(CLK_DDR_FAIL_SAFE, "clk_ddr_fail_safe", "clk_pmu0", CLK_IGNORE_UNUSED,

View File

@@ -777,7 +777,7 @@ static const struct clk_parent_data sdh2_parents[] = {
CCU_MUX_DIV_GATE_FC_DEFINE(sdh2_clk, sdh2_parents, APMU_SDH2_CLK_RES_CTRL, 8, 3,
BIT(11), 5, 3, BIT(4), 0);
CCU_GATE_DEFINE(usb2_bus_clk, CCU_PARENT_HW(axi_clk), APMU_USB_CLK_RES_CTRL, BIT(0), 0);
CCU_GATE_DEFINE(usb2_bus_clk, CCU_PARENT_HW(axi_clk), APMU_USB_CLK_RES_CTRL, BIT(1), 0);
CCU_GATE_DEFINE(usb3_porta_bus_clk, CCU_PARENT_HW(axi_clk), APMU_USB_CLK_RES_CTRL, BIT(4), 0);
CCU_GATE_DEFINE(usb3_portb_bus_clk, CCU_PARENT_HW(axi_clk), APMU_USB_CLK_RES_CTRL, BIT(8), 0);
CCU_GATE_DEFINE(usb3_portc_bus_clk, CCU_PARENT_HW(axi_clk), APMU_USB_CLK_RES_CTRL, BIT(12), 0);
@@ -1026,7 +1026,7 @@ CCU_MUX_DIV_GATE_DEFINE(isim_vclk_out3, isim_vclk_parents, APMU_SNR_ISIM_VCLK_CT
/* APMU clocks end */
/* DCIU clocks start */
CCU_GATE_DEFINE(hdma_clk, CCU_PARENT_HW(axi_clk), DCIU_DMASYS_CLK_EN, BIT(0), 0);
CCU_GATE_DEFINE(hdma_clk, CCU_PARENT_HW(axi_clk), DCIU_DMASYS_CLK_EN, BIT(0), CLK_IS_CRITICAL);
CCU_GATE_DEFINE(dma350_clk, CCU_PARENT_HW(axi_clk), DCIU_DMASYS_SDMA_CLK_EN, BIT(0), 0);
CCU_GATE_DEFINE(c2_tcm_pipe_clk, CCU_PARENT_HW(axi_clk), DCIU_C2_TCM_PIPE_CLK, BIT(0), 0);
CCU_GATE_DEFINE(c3_tcm_pipe_clk, CCU_PARENT_HW(axi_clk), DCIU_C3_TCM_PIPE_CLK, BIT(0), 0);

View File

@@ -1090,6 +1090,27 @@ static int __init arch_timer_common_init(void)
return arch_timer_arch_init();
}
static bool __init has_broken_el2_vtimer(void)
{
/*
* SoCs described here have been found to be broken, though no
* explanation has been volunteered by the vendor. Let the user know
* we're papering over the vendor's lack of communication.
*/
static const char * const broken_el2_vtimer[] __initconst = {
"brcm,bcm2712",
NULL
};
if (of_machine_compatible_match(broken_el2_vtimer)) {
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
pr_warn_once(HW_ERR "Known broken EL2 virtual timer, ignoring it\n");
return true;
}
return false;
}
/**
* arch_timer_select_ppi() - Select suitable PPI for the current system.
*
@@ -1115,7 +1136,8 @@ static int __init arch_timer_common_init(void)
static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void)
{
if (is_kernel_in_hyp_mode()) {
if (arch_timer_ppi[ARCH_TIMER_HYP_VIRT_PPI])
if (arch_timer_ppi[ARCH_TIMER_HYP_VIRT_PPI] &&
!has_broken_el2_vtimer())
return ARCH_TIMER_HYP_VIRT_PPI;
pr_warn_once(FW_BUG "VHE-capable CPU without EL2 virtual timer interrupt\n");

View File

@@ -58,7 +58,7 @@ static int devm_qce_register_algs(struct qce_device *qce)
ret = ops->register_algs(qce);
if (ret) {
for (j = i - 1; j >= 0; j--)
ops->unregister_algs(qce);
qce_ops[j]->unregister_algs(qce);
return ret;
}
}

View File

@@ -677,7 +677,7 @@ static int starfive_aes_aead_do_one_req(struct crypto_engine *engine, void *areq
if (cryp->total_in)
sg_zero_buffer(rctx->in_sg, sg_nents(rctx->in_sg),
sg_dma_len(rctx->in_sg) - cryp->total_in,
rctx->in_sg->length - cryp->total_in,
cryp->total_in);
ctx->rctx = rctx;

View File

@@ -45,7 +45,6 @@ struct tegra_aes_reqctx {
struct tegra_aead_ctx {
struct tegra_se *se;
unsigned int authsize;
u32 alg;
u32 key_id;
u32 keylen;
@@ -1290,7 +1289,7 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
if (rctx->encrypt)
rctx->cryptlen = req->cryptlen;
else
rctx->cryptlen = req->cryptlen - ctx->authsize;
rctx->cryptlen = req->cryptlen - rctx->authsize;
memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE);
rctx->iv[3] = (1 << 24);
@@ -1394,8 +1393,6 @@ static int tegra_aead_cra_init(struct crypto_aead *tfm)
static int tegra_ccm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
{
struct tegra_aead_ctx *ctx = crypto_aead_ctx(tfm);
switch (authsize) {
case 4:
case 6:
@@ -1404,28 +1401,15 @@ static int tegra_ccm_setauthsize(struct crypto_aead *tfm, unsigned int authsize
case 12:
case 14:
case 16:
break;
return 0;
default:
return -EINVAL;
}
ctx->authsize = authsize;
return 0;
}
static int tegra_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
{
struct tegra_aead_ctx *ctx = crypto_aead_ctx(tfm);
int ret;
ret = crypto_gcm_check_authsize(authsize);
if (ret)
return ret;
ctx->authsize = authsize;
return 0;
return crypto_gcm_check_authsize(authsize);
}
static void tegra_aead_cra_exit(struct crypto_aead *tfm)

View File

@@ -335,7 +335,6 @@ static int dibs_lo_dev_probe(void)
return 0;
err_reg:
kfree(dibs->dmb_clientid_arr);
/* pairs with dibs_dev_alloc() */
put_device(&dibs->dev);
kfree(ldev);

View File

@@ -128,6 +128,7 @@ static void dibs_dev_release(struct device *dev)
dibs = container_of(dev, struct dibs_dev, dev);
kfree(dibs->dmb_clientid_arr);
kfree(dibs);
}
@@ -194,12 +195,13 @@ int dibs_dev_add(struct dibs_dev *dibs)
ret = device_add(&dibs->dev);
if (ret)
goto free_client_arr;
return ret;
ret = sysfs_create_group(&dibs->dev.kobj, &dibs_dev_attr_group);
if (ret) {
dev_err(&dibs->dev, "sysfs_create_group failed for dibs_dev\n");
goto err_device_del;
device_del(&dibs->dev);
return ret;
}
mutex_lock(&dibs_dev_list.mutex);
mutex_lock(&clients_lock);
@@ -214,13 +216,6 @@ int dibs_dev_add(struct dibs_dev *dibs)
mutex_unlock(&dibs_dev_list.mutex);
return 0;
err_device_del:
device_del(&dibs->dev);
free_client_arr:
kfree(dibs->dmb_clientid_arr);
return ret;
}
EXPORT_SYMBOL_GPL(dibs_dev_add);
@@ -247,7 +242,6 @@ void dibs_dev_del(struct dibs_dev *dibs)
mutex_unlock(&dibs_dev_list.mutex);
device_del(&dibs->dev);
kfree(dibs->dmb_clientid_arr);
}
EXPORT_SYMBOL_GPL(dibs_dev_del);

View File

@@ -540,11 +540,13 @@ static void ar_context_link_page(struct ar_context *ctx, unsigned int index)
static void ar_context_release(struct ar_context *ctx)
{
struct device *dev = ctx->ohci->card.device;
struct device *dev;
if (!ctx->buffer)
return;
dev = ctx->ohci->card.device;
for (int i = 0; i < AR_BUFFERS; ++i) {
dma_addr_t dma_addr = ctx->dma_addrs[i];
if (dma_addr)

View File

@@ -73,7 +73,7 @@ struct ioh_gpio_reg_data {
* @gpio_use_sel: Save GPIO_USE_SEL1~4 register for PM
* @ch: Indicate GPIO channel
* @irq_base: Save base of IRQ number for interrupt
* @spinlock: Used for register access protection
* @spinlock: Shared register access lock
*/
struct ioh_gpio {
void __iomem *base;
@@ -84,7 +84,12 @@ struct ioh_gpio {
u32 gpio_use_sel;
int ch;
int irq_base;
spinlock_t spinlock;
raw_spinlock_t *spinlock;
};
struct ioh_gpio_device {
raw_spinlock_t spinlock;
struct ioh_gpio chip[8];
};
static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12};
@@ -95,7 +100,7 @@ static int ioh_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
struct ioh_gpio *chip = gpiochip_get_data(gpio);
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
raw_spin_lock_irqsave(chip->spinlock, flags);
reg_val = ioread32(&chip->reg->regs[chip->ch].po);
if (val)
reg_val |= BIT(nr);
@@ -103,7 +108,7 @@ static int ioh_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
reg_val &= ~BIT(nr);
iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
spin_unlock_irqrestore(&chip->spinlock, flags);
raw_spin_unlock_irqrestore(chip->spinlock, flags);
return 0;
}
@@ -123,7 +128,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
u32 reg_val;
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
raw_spin_lock_irqsave(chip->spinlock, flags);
pm = ioread32(&chip->reg->regs[chip->ch].pm);
pm &= BIT(num_ports[chip->ch]) - 1;
pm |= BIT(nr);
@@ -136,7 +141,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
reg_val &= ~BIT(nr);
iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
spin_unlock_irqrestore(&chip->spinlock, flags);
raw_spin_unlock_irqrestore(chip->spinlock, flags);
return 0;
}
@@ -147,12 +152,12 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
u32 pm;
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
raw_spin_lock_irqsave(chip->spinlock, flags);
pm = ioread32(&chip->reg->regs[chip->ch].pm);
pm &= BIT(num_ports[chip->ch]) - 1;
pm &= ~BIT(nr);
iowrite32(pm, &chip->reg->regs[chip->ch].pm);
spin_unlock_irqrestore(&chip->spinlock, flags);
raw_spin_unlock_irqrestore(chip->spinlock, flags);
return 0;
}
@@ -256,7 +261,7 @@ static int ioh_irq_type(struct irq_data *d, unsigned int type)
dev_dbg(chip->dev, "%s:irq=%d type=%d ch=%d pos=%d type=%d\n",
__func__, irq, type, ch, im_pos, type);
spin_lock_irqsave(&chip->spinlock, flags);
raw_spin_lock_irqsave(chip->spinlock, flags);
switch (type) {
case IRQ_TYPE_EDGE_RISING:
@@ -296,7 +301,7 @@ static int ioh_irq_type(struct irq_data *d, unsigned int type)
ien = ioread32(&chip->reg->regs[chip->ch].ien);
iowrite32(ien | BIT(ch), &chip->reg->regs[chip->ch].ien);
end:
spin_unlock_irqrestore(&chip->spinlock, flags);
raw_spin_unlock_irqrestore(chip->spinlock, flags);
return 0;
}
@@ -326,11 +331,11 @@ static void ioh_irq_disable(struct irq_data *d)
unsigned long flags;
u32 ien;
spin_lock_irqsave(&chip->spinlock, flags);
raw_spin_lock_irqsave(chip->spinlock, flags);
ien = ioread32(&chip->reg->regs[chip->ch].ien);
ien &= ~BIT(d->irq - chip->irq_base);
iowrite32(ien, &chip->reg->regs[chip->ch].ien);
spin_unlock_irqrestore(&chip->spinlock, flags);
raw_spin_unlock_irqrestore(chip->spinlock, flags);
}
static void ioh_irq_enable(struct irq_data *d)
@@ -340,11 +345,11 @@ static void ioh_irq_enable(struct irq_data *d)
unsigned long flags;
u32 ien;
spin_lock_irqsave(&chip->spinlock, flags);
raw_spin_lock_irqsave(chip->spinlock, flags);
ien = ioread32(&chip->reg->regs[chip->ch].ien);
ien |= BIT(d->irq - chip->irq_base);
iowrite32(ien, &chip->reg->regs[chip->ch].ien);
spin_unlock_irqrestore(&chip->spinlock, flags);
raw_spin_unlock_irqrestore(chip->spinlock, flags);
}
static irqreturn_t ioh_gpio_handler(int irq, void *dev_id)
@@ -407,8 +412,8 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
int ret;
int i, j;
struct ioh_gpio *chip;
struct ioh_gpio_device *priv;
void __iomem *base;
void *chip_save;
int irq_base;
ret = pcim_enable_device(pdev);
@@ -429,18 +434,18 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
return -ENOMEM;
}
chip_save = devm_kcalloc(dev, 8, sizeof(*chip), GFP_KERNEL);
if (chip_save == NULL) {
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
}
chip = chip_save;
raw_spin_lock_init(&priv->spinlock);
chip = priv->chip;
for (i = 0; i < 8; i++, chip++) {
chip->dev = dev;
chip->base = base;
chip->reg = chip->base;
chip->ch = i;
spin_lock_init(&chip->spinlock);
chip->spinlock = &priv->spinlock;
ioh_gpio_setup(chip, num_ports[i]);
ret = devm_gpiochip_add_data(dev, &chip->gpio, chip);
if (ret) {
@@ -449,7 +454,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
}
}
chip = chip_save;
chip = priv->chip;
for (j = 0; j < 8; j++, chip++) {
irq_base = devm_irq_alloc_descs(dev, -1, IOH_IRQ_BASE,
num_ports[j], NUMA_NO_NODE);
@@ -466,7 +471,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
return ret;
}
chip = chip_save;
chip = priv->chip;
ret = devm_request_irq(dev, pdev->irq, ioh_gpio_handler,
IRQF_SHARED, KBUILD_MODNAME, chip);
if (ret != 0) {
@@ -474,33 +479,33 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
return ret;
}
pci_set_drvdata(pdev, chip);
pci_set_drvdata(pdev, priv);
return 0;
}
static int ioh_gpio_suspend(struct device *dev)
{
struct ioh_gpio *chip = dev_get_drvdata(dev);
struct ioh_gpio_device *priv = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
ioh_gpio_save_reg_conf(chip);
spin_unlock_irqrestore(&chip->spinlock, flags);
raw_spin_lock_irqsave(&priv->spinlock, flags);
ioh_gpio_save_reg_conf(priv->chip);
raw_spin_unlock_irqrestore(&priv->spinlock, flags);
return 0;
}
static int ioh_gpio_resume(struct device *dev)
{
struct ioh_gpio *chip = dev_get_drvdata(dev);
struct ioh_gpio_device *priv = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
iowrite32(0x01, &chip->reg->srst);
iowrite32(0x00, &chip->reg->srst);
ioh_gpio_restore_reg_conf(chip);
spin_unlock_irqrestore(&chip->spinlock, flags);
raw_spin_lock_irqsave(&priv->spinlock, flags);
iowrite32(0x01, &priv->chip->reg->srst);
iowrite32(0x00, &priv->chip->reg->srst);
ioh_gpio_restore_reg_conf(priv->chip);
raw_spin_unlock_irqrestore(&priv->spinlock, flags);
return 0;
}

View File

@@ -300,7 +300,7 @@ static int gpio_la_poll_probe(struct platform_device *pdev)
debugfs_create_ulong("delay_ns_acquisition", 0400, priv->debug_dir, &priv->acq_delay);
debugfs_create_file_unsafe("buf_size", 0600, priv->debug_dir, priv, &fops_buf_size);
debugfs_create_file_unsafe("capture", 0200, priv->debug_dir, priv, &fops_capture);
debugfs_create_file_unsafe("trigger", 0200, priv->debug_dir, priv, &fops_trigger);
debugfs_create_file("trigger", 0200, priv->debug_dir, priv, &fops_trigger);
return 0;
}

View File

@@ -5420,7 +5420,8 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *gc)
flags = READ_ONCE(desc->flags);
is_irq = test_bit(GPIOD_FLAG_USED_AS_IRQ, &flags);
if (is_irq || test_bit(GPIOD_FLAG_REQUESTED, &flags)) {
gpiod_get_direction(desc);
if (gc->get_direction)
gpiod_get_direction(desc);
is_out = test_bit(GPIOD_FLAG_IS_OUT, &flags);
value = gpio_chip_get_value(gc, desc);
active_low = test_bit(GPIOD_FLAG_ACTIVE_LOW, &flags);

View File

@@ -248,6 +248,10 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
if (size < sizeof(struct drm_amdgpu_cs_chunk_fence))
goto free_partial_kdata;
/* Only a single user fence is allowed to simplify handling. */
if (p->uf_bo)
goto free_partial_kdata;
ret = amdgpu_cs_p1_user_fence(p, p->chunks[i].kdata,
&uf_offset);
if (ret)

View File

@@ -1370,6 +1370,31 @@ static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
#endif
}
/*
* Some dGPUs expose their display endpoint below an internal PCIe switch.
* Use the switch upstream port to query the host-facing link.
*/
static struct pci_dev *amdgpu_device_get_aspm_pdev(struct amdgpu_device *adev)
{
struct pci_dev *swds, *swus;
swds = pci_upstream_bridge(adev->pdev);
if (!swds ||
(swds->vendor != PCI_VENDOR_ID_ATI &&
swds->vendor != PCI_VENDOR_ID_AMD) ||
pci_pcie_type(swds) != PCI_EXP_TYPE_DOWNSTREAM)
return adev->pdev;
swus = pci_upstream_bridge(swds);
if (!swus ||
(swus->vendor != PCI_VENDOR_ID_ATI &&
swus->vendor != PCI_VENDOR_ID_AMD) ||
pci_pcie_type(swus) != PCI_EXP_TYPE_UPSTREAM)
return adev->pdev;
return swus;
}
/**
* amdgpu_device_should_use_aspm - check if the device should program ASPM
*
@@ -1382,6 +1407,9 @@ static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
*/
bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev)
{
struct pci_dev *aspm_pdev, *parent;
bool enabled;
switch (amdgpu_aspm) {
case -1:
break;
@@ -1396,7 +1424,27 @@ bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev)
return false;
if (amdgpu_device_aspm_support_quirk(adev))
return false;
return pcie_aspm_enabled(adev->pdev);
/*
* pcie_aspm_enabled() checks the link between its argument and
* the immediate upstream bridge. Use SWUS for dGPUs with an
* internal switch so that this is the host-facing link.
*/
aspm_pdev = amdgpu_device_get_aspm_pdev(adev);
parent = pci_upstream_bridge(aspm_pdev);
if (!parent) {
dev_dbg(adev->dev, "ASPM: no upstream PCIe link for %s\n",
pci_name(aspm_pdev));
return false;
}
enabled = pcie_aspm_enabled(aspm_pdev);
/* Report the exact link used for the automatic ASPM decision. */
dev_dbg(adev->dev, "ASPM: link %s <-> %s is %s\n",
pci_name(parent), pci_name(aspm_pdev),
enabled ? "enabled" : "disabled");
return enabled;
}
/* if we get transitioned to only one device, take VGA back */

View File

@@ -311,6 +311,19 @@ static int amdgpu_discovery_get_tmr_info(struct amdgpu_device *adev,
goto out;
}
} else {
if (adev->discovery.offset) {
u32 signature;
/* If VRAM holds a valid discovery signature at the default
* discovery offset, use it as-is.
*/
amdgpu_device_vram_access(adev, adev->discovery.offset,
&signature, sizeof(signature),
false);
if (le32_to_cpu(signature) == BINARY_SIGNATURE)
goto out;
}
tmr_size = RREG32(mmDRIVER_SCRATCH_2);
if (tmr_size) {
/* It's preferred to transition to PSP mailbox reg interface

View File

@@ -397,6 +397,25 @@ const struct drm_gem_object_funcs amdgpu_gem_object_funcs = {
.vm_ops = &amdgpu_gem_vm_ops,
};
static bool amdgpu_gem_are_domains_valid(u32 domains)
{
u32 normal = AMDGPU_GEM_DOMAIN_CPU |
AMDGPU_GEM_DOMAIN_GTT |
AMDGPU_GEM_DOMAIN_VRAM;
/* Treat all non CPU/GTT/VRAM domains as special domains. */
u32 special = AMDGPU_GEM_DOMAIN_MASK & ~normal;
u32 normal_mask = domains & normal;
u32 special_mask = domains & special;
if (!special_mask)
return true;
if (normal_mask)
return false;
return !(special_mask & (special_mask - 1));
}
/*
* GEM ioctls.
*/
@@ -421,6 +440,8 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
/* reject invalid gem domains */
if (args->in.domains & ~AMDGPU_GEM_DOMAIN_MASK)
return -EINVAL;
if (!amdgpu_gem_are_domains_valid(args->in.domains))
return -EINVAL;
if (!amdgpu_is_tmz(adev) && (flags & AMDGPU_GEM_CREATE_ENCRYPTED)) {
DRM_NOTE_ONCE("Cannot allocate secure buffer since TMZ is disabled\n");

View File

@@ -646,17 +646,15 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
unsigned int height = msg[7];
unsigned int dpb_size = msg[9];
unsigned int pitch = msg[28];
unsigned int level = msg[57];
unsigned int width_in_mb = width / 16;
unsigned int height_in_mb = ALIGN(height / 16, 2);
unsigned int fs_in_mb = width_in_mb * height_in_mb;
unsigned int image_size, tmp, min_dpb_size, num_dpb_buffer;
unsigned int min_ctx_size = ~0;
/* Reject invalid dimensions to prevent division by zero */
if (width < 16 || height < 16) {
/* Reject invalid dimensions */
if (width < 16 || height < 16 || width > 4096 || height > 4096) {
dev_WARN_ONCE(adev->dev, 1,
"Invalid UVD decoding dimensions (%dx%d)!\n",
width, height);
@@ -669,35 +667,9 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
switch (stream_type) {
case 0: /* H264 */
switch (level) {
case 30:
num_dpb_buffer = 8100 / fs_in_mb;
break;
case 31:
num_dpb_buffer = 18000 / fs_in_mb;
break;
case 32:
num_dpb_buffer = 20480 / fs_in_mb;
break;
case 41:
num_dpb_buffer = 32768 / fs_in_mb;
break;
case 42:
num_dpb_buffer = 34816 / fs_in_mb;
break;
case 50:
num_dpb_buffer = 110400 / fs_in_mb;
break;
case 51:
num_dpb_buffer = 184320 / fs_in_mb;
break;
default:
num_dpb_buffer = 184320 / fs_in_mb;
break;
}
num_dpb_buffer++;
num_dpb_buffer = ((msg[61] >> 16) & 0xff) + 1;
if (num_dpb_buffer > 17)
num_dpb_buffer = 17;
return -EINVAL;
/* reference picture buffer */
min_dpb_size = image_size * num_dpb_buffer;
@@ -747,35 +719,9 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
break;
case 7: /* H264 Perf */
switch (level) {
case 30:
num_dpb_buffer = 8100 / fs_in_mb;
break;
case 31:
num_dpb_buffer = 18000 / fs_in_mb;
break;
case 32:
num_dpb_buffer = 20480 / fs_in_mb;
break;
case 41:
num_dpb_buffer = 32768 / fs_in_mb;
break;
case 42:
num_dpb_buffer = 34816 / fs_in_mb;
break;
case 50:
num_dpb_buffer = 110400 / fs_in_mb;
break;
case 51:
num_dpb_buffer = 184320 / fs_in_mb;
break;
default:
num_dpb_buffer = 184320 / fs_in_mb;
break;
}
num_dpb_buffer++;
num_dpb_buffer = ((msg[61] >> 16) & 0xff) + 1;
if (num_dpb_buffer > 17)
num_dpb_buffer = 17;
return -EINVAL;
/* reference picture buffer */
min_dpb_size = image_size * num_dpb_buffer;
@@ -803,6 +749,9 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
image_size = ALIGN(image_size, 256);
num_dpb_buffer = (le32_to_cpu(msg[59]) & 0xff) + 2;
if (num_dpb_buffer > 17)
return -EINVAL;
min_dpb_size = image_size * num_dpb_buffer;
min_ctx_size = ((width + 255) / 16) * ((height + 255) / 16)
* 16 * num_dpb_buffer + 52 * 1024;
@@ -813,7 +762,7 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
return -EINVAL;
}
if (width > pitch) {
if (width > pitch || pitch > 4096) {
DRM_ERROR("Invalid UVD decoding target pitch!\n");
return -EINVAL;
}
@@ -825,7 +774,7 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
}
buf_sizes[0x1] = dpb_size;
buf_sizes[0x2] = image_size;
buf_sizes[0x2] = (pitch * height) * 3 / 2;
buf_sizes[0x4] = min_ctx_size;
/* store image width to adjust nb memory pstate */
adev->uvd.decode_image_width = width;
@@ -972,15 +921,16 @@ static int amdgpu_uvd_cs_pass2(struct amdgpu_uvd_cs_ctx *ctx)
ctx->buf_sizes[cmd]);
return -EINVAL;
}
} else if (cmd == 0x204 || cmd == 0x206) {
unsigned int min_size = ctx->buf_sizes[cmd == 0x204 ? 5 : 4];
} else if (cmd == 0x206) {
if ((end - start) < ctx->buf_sizes[4]) {
if ((end - start) < min_size) {
DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
(unsigned int)(end - start),
ctx->buf_sizes[4]);
min_size);
return -EINVAL;
}
} else if ((cmd != 0x100) && (cmd != 0x204)) {
} else if ((cmd != 0x100)) {
DRM_ERROR("invalid UVD command %X!\n", cmd);
return -EINVAL;
}
@@ -1110,11 +1060,12 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser,
{
struct amdgpu_uvd_cs_ctx ctx = {};
unsigned int buf_sizes[] = {
[0x00000000] = 2048,
[0x00000000] = 3556,
[0x00000001] = 0xFFFFFFFF,
[0x00000002] = 0xFFFFFFFF,
[0x00000003] = 2048,
[0x00000004] = 0xFFFFFFFF,
[0x00000005] = 992,
};
int r;

View File

@@ -800,6 +800,7 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
mutex_unlock(&id_mgr->lock);
gds_switch_needed &= !!ring->funcs->emit_gds_switch;
spm_update_needed &= !!adev->gfx.rlc.funcs->update_spm_vmid;
vm_flush_needed &= !!ring->funcs->emit_vm_flush &&
job->vm_pd_addr != AMDGPU_BO_INVALID_OFFSET;
pasid_mapping_needed &= adev->gmc.gmc_funcs->emit_pasid_mapping &&
@@ -811,7 +812,7 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
&job->base.s_fence->scheduled == isolation->spearhead;
if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync &&
!cleaner_shader_needed)
!cleaner_shader_needed && !spm_update_needed)
return;
amdgpu_ring_ib_begin(ring);

View File

@@ -500,7 +500,6 @@ static u32 nbif_v6_3_1_get_rom_offset(struct amdgpu_device *adev)
static void nbif_v6_3_1_program_ltr(struct amdgpu_device *adev)
{
uint32_t def, data;
u16 devctl2;
def = RREG32_SOC15(NBIO, 0, regRCC_EP_DEV0_0_EP_PCIE_TX_LTR_CNTL);
data = 0x35EB;
@@ -514,15 +513,8 @@ static void nbif_v6_3_1_program_ltr(struct amdgpu_device *adev)
if (def != data)
WREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_BIF_STRAP2, data);
pcie_capability_read_word(adev->pdev, PCI_EXP_DEVCTL2, &devctl2);
if (adev->pdev->ltr_path == (devctl2 & PCI_EXP_DEVCTL2_LTR_EN))
return;
if (adev->pdev->ltr_path)
pcie_capability_set_word(adev->pdev, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_LTR_EN);
else
pcie_capability_clear_word(adev->pdev, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_LTR_EN);
pcie_capability_set_word(adev->pdev, PCI_EXP_DEVCTL2,
PCI_EXP_DEVCTL2_LTR_EN);
}
#endif
@@ -530,7 +522,7 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev)
{
#ifdef CONFIG_PCIEASPM
uint32_t def, data;
u16 devctl2, ltr;
u16 ltr;
def = data = RREG32_SOC15(PCIE, 0, regPCIE_LC_CNTL);
data &= ~PCIE_LC_CNTL__LC_L1_INACTIVITY_MASK;
@@ -560,11 +552,8 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev)
if (def != data)
WREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_BIF_STRAP5, data);
pcie_capability_read_word(adev->pdev, PCI_EXP_DEVCTL2, &devctl2);
data = def = devctl2;
data &= ~PCI_EXP_DEVCTL2_LTR_EN;
if (def != data)
pcie_capability_set_word(adev->pdev, PCI_EXP_DEVCTL2, (u16)data);
pcie_capability_clear_word(adev->pdev, PCI_EXP_DEVCTL2,
PCI_EXP_DEVCTL2_LTR_EN);
ltr = pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_LTR);
@@ -572,15 +561,13 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev)
pci_write_config_dword(adev->pdev, ltr + PCI_LTR_MAX_SNOOP_LAT, 0x10011001);
}
#if 0
/* regPSWUSP0_PCIE_LC_CNTL2 should be replace by PCIE_LC_CNTL2 or someone else ? */
def = data = RREG32_SOC15(NBIO, 0, regPSWUSP0_PCIE_LC_CNTL2);
data |= PSWUSP0_PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L1_MASK |
PSWUSP0_PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L23_MASK;
data &= ~PSWUSP0_PCIE_LC_CNTL2__LC_RCV_L0_TO_RCV_L0S_DIS_MASK;
def = data = RREG32_SOC15(PCIE, 0, regPCIE_LC_CNTL2);
data |= PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L1_MASK |
PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L23_MASK;
data &= ~PCIE_LC_CNTL2__LC_RCV_L0_TO_RCV_L0S_DIS_MASK;
if (def != data)
WREG32_SOC15(NBIO, 0, regPSWUSP0_PCIE_LC_CNTL2, data);
#endif
WREG32_SOC15(PCIE, 0, regPCIE_LC_CNTL2, data);
def = data = RREG32_SOC15(PCIE, 0, regPCIE_LC_CNTL4);
data |= PCIE_LC_CNTL4__LC_L1_POWERDOWN_MASK;
if (def != data)
@@ -591,7 +578,12 @@ static void nbif_v6_3_1_program_aspm(struct amdgpu_device *adev)
if (def != data)
WREG32_SOC15(PCIE, 0, regPCIE_LC_RXRECOVER_RXSTANDBY_CNTL, data);
nbif_v6_3_1_program_ltr(adev);
/*
* Do not enable endpoint LTR unless the Root Complex and every
* upstream switch support it.
*/
if (adev->pdev->ltr_path)
nbif_v6_3_1_program_ltr(adev);
def = data = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_BIF_STRAP3);
data |= 0x5DE0 << RCC_STRAP0_RCC_BIF_STRAP3__STRAP_VLINK_ASPM_IDLE_TIMER__SHIFT;

View File

@@ -875,6 +875,23 @@ static void vce_v3_0_ring_emit_ib(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, ib->length_dw);
}
static void vce_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
u64 seq, unsigned flags)
{
WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
amdgpu_ring_write(ring, VCE_CMD_FENCE);
amdgpu_ring_write(ring, addr);
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, seq);
amdgpu_ring_write(ring, VCE_CMD_TRAP);
}
static void vce_v3_0_ring_insert_end(struct amdgpu_ring *ring)
{
amdgpu_ring_write(ring, VCE_CMD_END);
}
static void vce_v3_0_emit_vm_flush(struct amdgpu_ring *ring,
unsigned int vmid, uint64_t pd_addr)
{
@@ -884,7 +901,6 @@ static void vce_v3_0_emit_vm_flush(struct amdgpu_ring *ring,
amdgpu_ring_write(ring, VCE_CMD_FLUSH_TLB);
amdgpu_ring_write(ring, vmid);
amdgpu_ring_write(ring, VCE_CMD_END);
}
static void vce_v3_0_emit_pipeline_sync(struct amdgpu_ring *ring)
@@ -953,17 +969,19 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = {
.set_wptr = vce_v3_0_ring_set_wptr,
.patch_cs_in_place = amdgpu_vce_ring_parse_cs_vm,
.emit_frame_size =
6 + /* vce_v3_0_emit_vm_flush */
5 + /* vce_v3_0_emit_vm_flush */
4 + /* vce_v3_0_emit_pipeline_sync */
6 + 6, /* amdgpu_vce_ring_emit_fence x2 vm fence */
5 + 5 + /* vce_v3_0_ring_emit_fence x2 vm fence */
1, /* vce_v3_0_ring_insert_end */
.emit_ib_size = 5, /* vce_v3_0_ring_emit_ib */
.emit_ib = vce_v3_0_ring_emit_ib,
.emit_vm_flush = vce_v3_0_emit_vm_flush,
.emit_pipeline_sync = vce_v3_0_emit_pipeline_sync,
.emit_fence = amdgpu_vce_ring_emit_fence,
.emit_fence = vce_v3_0_ring_emit_fence,
.test_ring = amdgpu_vce_ring_test_ring,
.test_ib = amdgpu_vce_ring_test_ib,
.insert_nop = amdgpu_ring_insert_nop,
.insert_end = vce_v3_0_ring_insert_end,
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_vce_ring_begin_use,
.end_use = amdgpu_vce_ring_end_use,

View File

@@ -257,7 +257,7 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id);
if (enable) {
if (enable && acrtc_state->stream) {
struct dc *dc = adev->dm.dc;
struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
struct psr_settings *psr = &acrtc_state->stream->link->psr_settings;

View File

@@ -58,7 +58,8 @@ enum dc_color_space_type {
COLOR_SPACE_RGB_LIMITED_TYPE,
COLOR_SPACE_YCBCR601_TYPE,
COLOR_SPACE_YCBCR709_TYPE,
COLOR_SPACE_YCBCR2020_TYPE,
COLOR_SPACE_YCBCR2020_LIMITED_TYPE,
COLOR_SPACE_YCBCR2020_FULL_TYPE,
COLOR_SPACE_YCBCR601_LIMITED_TYPE,
COLOR_SPACE_YCBCR709_LIMITED_TYPE,
COLOR_SPACE_YCBCR709_BLACK_TYPE,
@@ -110,9 +111,15 @@ static const struct out_csc_color_matrix_type output_csc_matrix[] = {
{ 0xE00, 0xF349, 0xFEB7, 0x1000,
0x6CE, 0x16E3, 0x24F, 0x200,
0xFCCB, 0xF535, 0xE00, 0x1000} },
{ COLOR_SPACE_YCBCR2020_TYPE,
/* Corrected. Not included in the TODO above. */
{ COLOR_SPACE_YCBCR2020_LIMITED_TYPE,
{ 0x0E04, 0xF31D, 0xFEDF, 0x1004,
0x0733, 0x1294, 0x01A0, 0x0201,
0xFC16, 0xF5E6, 0x0E04, 0x1004} },
/* Corrected. Not included in the TODO above. */
{ COLOR_SPACE_YCBCR2020_FULL_TYPE,
{ 0x1000, 0xF149, 0xFEB7, 0x1004,
0x0868, 0x15B2, 0x01E6, 0x201,
0x0868, 0x15B2, 0x01E6, 0,
0xFB88, 0xF478, 0x1000, 0x1004} },
{ COLOR_SPACE_YCBCR709_BLACK_TYPE,
{ 0x0000, 0x0000, 0x0000, 0x1000,
@@ -179,14 +186,14 @@ static bool is_ycbcr709_type(
return ret;
}
static bool is_ycbcr2020_type(
enum dc_color_space color_space)
static bool is_ycbcr2020_limited_type(enum dc_color_space color_space)
{
bool ret = false;
return color_space == COLOR_SPACE_2020_YCBCR_LIMITED;
}
if (color_space == COLOR_SPACE_2020_YCBCR_LIMITED || color_space == COLOR_SPACE_2020_YCBCR_FULL)
ret = true;
return ret;
static bool is_ycbcr2020_full_type(enum dc_color_space color_space)
{
return color_space == COLOR_SPACE_2020_YCBCR_FULL;
}
static bool is_ycbcr709_limited_type(
@@ -215,8 +222,10 @@ static enum dc_color_space_type get_color_space_type(enum dc_color_space color_s
type = COLOR_SPACE_YCBCR601_LIMITED_TYPE;
else if (is_ycbcr709_limited_type(color_space))
type = COLOR_SPACE_YCBCR709_LIMITED_TYPE;
else if (is_ycbcr2020_type(color_space))
type = COLOR_SPACE_YCBCR2020_TYPE;
else if (is_ycbcr2020_limited_type(color_space))
type = COLOR_SPACE_YCBCR2020_LIMITED_TYPE;
else if (is_ycbcr2020_full_type(color_space))
type = COLOR_SPACE_YCBCR2020_FULL_TYPE;
else if (color_space == COLOR_SPACE_YCBCR709)
type = COLOR_SPACE_YCBCR709_BLACK_TYPE;
else if (color_space == COLOR_SPACE_YCBCR709_BLACK)

View File

@@ -115,10 +115,11 @@ static const struct out_csc_color_matrix global_color_matrix[] = {
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
{ COLOR_SPACE_2020_RGB_LIMITEDRANGE,
{ 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} },
{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868,
0x15B2, 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
/* COLOR_SPACE_2020_YCBCR_* values corrected. Not included in the TODO above. */
{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x0E04, 0xF31D, 0xFEDF, 0x1004, 0x0733,
0x1294, 0x01A0, 0x201, 0xFC16, 0xF5E6, 0x0E04, 0x1004} },
{ COLOR_SPACE_2020_YCBCR_FULL, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2,
0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} }
0x01E6, 0, 0xFB88, 0xF478, 0x1000, 0x1004} }
};
static bool setup_scaling_configuration(

View File

@@ -93,10 +93,11 @@ static const struct out_csc_color_matrix global_color_matrix[] = {
{ 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
{ COLOR_SPACE_2020_RGB_LIMITEDRANGE,
{ 0x1B67, 0, 0, 0x201, 0, 0x1B67, 0, 0x201, 0, 0, 0x1B67, 0x201} },
{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868,
0x15B2, 0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
/* COLOR_SPACE_2020_YCBCR_* values corrected. Not included in the TODO above. */
{ COLOR_SPACE_2020_YCBCR_LIMITED, { 0x0E04, 0xF31D, 0xFEDF, 0x1004, 0x0733,
0x1294, 0x01A0, 0x201, 0xFC16, 0xF5E6, 0x0E04, 0x1004} },
{ COLOR_SPACE_2020_YCBCR_FULL, { 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2,
0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} }
0x01E6, 0, 0xFB88, 0xF478, 0x1000, 0x1004} }
};
enum csc_color_mode {

View File

@@ -71,6 +71,7 @@ void radeon_driver_unload_kms(struct drm_device *dev)
if (radeon_is_px(dev)) {
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
pm_runtime_dont_use_autosuspend(dev->dev);
}
radeon_acpi_fini(rdev);

View File

@@ -164,31 +164,14 @@ static int __xe_pin_fb_vma_dpt(struct drm_gem_object *obj,
dpt_size = ALIGN(intel_rotation_info_size(&view->rotated) * 8,
XE_PAGE_SIZE);
if (IS_DGFX(xe))
dpt = xe_bo_create_pin_map_at_novm(xe, tile0,
dpt_size, ~0ull,
ttm_bo_type_kernel,
XE_BO_FLAG_VRAM0 |
XE_BO_FLAG_GGTT |
XE_BO_FLAG_PAGETABLE,
pin_params->alignment, false);
else
dpt = xe_bo_create_pin_map_at_novm(xe, tile0,
dpt_size, ~0ull,
ttm_bo_type_kernel,
XE_BO_FLAG_STOLEN |
XE_BO_FLAG_GGTT |
XE_BO_FLAG_PAGETABLE,
pin_params->alignment, false);
if (IS_ERR(dpt))
dpt = xe_bo_create_pin_map_at_novm(xe, tile0,
dpt_size, ~0ull,
ttm_bo_type_kernel,
XE_BO_FLAG_SYSTEM |
XE_BO_FLAG_GGTT |
XE_BO_FLAG_PAGETABLE |
XE_BO_FLAG_FORCE_WC,
pin_params->alignment, false);
dpt = xe_bo_create_pin_map_at_novm(xe, tile0,
dpt_size, ~0ull,
ttm_bo_type_kernel,
XE_BO_FLAG_VRAM_IF_DGFX(tile0) |
XE_BO_FLAG_GGTT |
XE_BO_FLAG_PAGETABLE |
XE_BO_FLAG_FORCE_WC,
pin_params->alignment, false);
if (IS_ERR(dpt))
return PTR_ERR(dpt);

View File

@@ -6,6 +6,7 @@
#ifndef _XE_BO_H_
#define _XE_BO_H_
#include <drm/drm_prime.h>
#include <drm/ttm/ttm_tt.h>
#include "xe_bo_types.h"
@@ -548,6 +549,19 @@ void xe_bo_dev_fini(struct xe_bo_dev *bo_device);
struct sg_table *xe_bo_sg(struct xe_bo *bo);
/**
* xe_bo_sg_is_contiguous() - Check if a BO's DMA address space is contiguous.
* @bo: the BO to check (must have a valid sg table, i.e. !xe_bo_is_vram())
* @len: required contiguous length in bytes
*
* Returns true if the first @len bytes of the BO are mapped to a contiguous
* DMA address range.
*/
static inline bool xe_bo_sg_is_contiguous(struct xe_bo *bo, size_t len)
{
return drm_prime_get_contiguous_size(xe_bo_sg(bo)) >= len;
}
/*
* xe_sg_segment_size() - Provides upper limit for sg segment size.
* @dev: device pointer

View File

@@ -1102,7 +1102,11 @@ int xe_device_probe(struct xe_device *xe)
if (err)
goto err_unregister_display;
return devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe);
err = devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe);
if (err)
goto err_unregister_display;
return 0;
err_unregister_display:
xe_display_unregister(xe);

View File

@@ -63,10 +63,14 @@ ads_to_map(struct xe_guc_ads *ads)
/*
* The Additional Data Struct (ADS) has pointers for different buffers used by
* the GuC. One single gem object contains the ADS struct itself (guc_ads) and
* all the extra buffers indirectly linked via the ADS struct's entries.
* the GuC. One gem object (ads->bo) contains the ADS struct itself (guc_ads)
* and most of the extra buffers linked via the ADS struct's entries. The UM
* fault queues (PAGE_FAULT, PAGE_FAULT_RESPONSE, ACCESS_COUNTER rings) are
* kept in a separate BO (ads->um_queue_bo) so that the full memset of ads->bo
* performed on every GT reset does not discard fault descriptors already
* written into the rings by the GPU.
*
* Layout of the ADS blob allocated for the GuC:
* Layout of the ADS blob (ads->bo):
*
* +---------------------------------------+ <== base
* | guc_ads |
@@ -98,10 +102,6 @@ ads_to_map(struct xe_guc_ads *ads)
* +---------------------------------------+
* | padding |
* +---------------------------------------+ <== 4K aligned
* | UM queues |
* +---------------------------------------+
* | padding |
* +---------------------------------------+ <== 4K aligned
* | private data |
* +---------------------------------------+
* | padding |
@@ -155,16 +155,6 @@ static size_t guc_ads_capture_size(struct xe_guc_ads *ads)
return PAGE_ALIGN(ads->capture_size);
}
static size_t guc_ads_um_queues_size(struct xe_guc_ads *ads)
{
struct xe_device *xe = ads_to_xe(ads);
if (!xe->info.has_usm)
return 0;
return GUC_UM_QUEUE_SIZE * GUC_UM_HW_QUEUE_MAX;
}
static size_t guc_ads_private_data_size(struct xe_guc_ads *ads)
{
return PAGE_ALIGN(ads_to_guc(ads)->fw.private_data_size);
@@ -205,22 +195,12 @@ static size_t guc_ads_capture_offset(struct xe_guc_ads *ads)
return PAGE_ALIGN(offset);
}
static size_t guc_ads_um_queues_offset(struct xe_guc_ads *ads)
{
u32 offset;
offset = guc_ads_capture_offset(ads) +
guc_ads_capture_size(ads);
return PAGE_ALIGN(offset);
}
static size_t guc_ads_private_data_offset(struct xe_guc_ads *ads)
{
size_t offset;
offset = guc_ads_um_queues_offset(ads) +
guc_ads_um_queues_size(ads);
offset = guc_ads_capture_offset(ads) +
guc_ads_capture_size(ads);
return PAGE_ALIGN(offset);
}
@@ -409,6 +389,49 @@ int xe_guc_ads_init(struct xe_guc_ads *ads)
ads->bo = bo;
if (xe->info.has_usm) {
/*
* Allocate a separate BO for the HW fault ring (UM queues).
*
* Round the size up to the next power of two so that on iGPU
* (system memory, no IOMMU) the TTM pool issues a single
* alloc_pages(order=N) call, maximising the chance of getting
* a physically contiguous block. GuC requires contiguous DPA.
*/
size_t um_size = IS_DGFX(xe) ?
GUC_UM_QUEUE_SIZE * GUC_UM_HW_QUEUE_MAX :
roundup_pow_of_two(GUC_UM_QUEUE_SIZE *
GUC_UM_HW_QUEUE_MAX);
u32 um_flags = XE_BO_FLAG_VRAM_IF_DGFX(tile) |
XE_BO_FLAG_GGTT |
XE_BO_FLAG_GGTT_INVALIDATE |
XE_BO_FLAG_PINNED_NORESTORE |
XE_BO_FLAG_NEEDS_UC;
bo = xe_managed_bo_create_pin_map(xe, tile, um_size, um_flags);
if (IS_ERR(bo))
return PTR_ERR(bo);
/*
* On pre-Xe3p platforms, GAM (not GuC) accesses the UM queue
* ring via base_dpa, which must be a contiguous DMA address
* range. Verify that the allocated pages are contiguous in
* DMA address space.
*/
if (!xe_bo_is_vram(bo) &&
!xe_guc_using_main_gamctrl_queues(ads_to_guc(ads)) &&
unlikely(!xe_bo_sg_is_contiguous(bo,
GUC_UM_QUEUE_SIZE *
GUC_UM_HW_QUEUE_MAX))) {
drm_err(&xe->drm,
"UM fault queue memory is not contiguous in DMA address space; GAM requires contiguous DPA\n");
return -ENOMEM;
}
ads->um_queue_bo = bo;
}
return 0;
}
ALLOW_ERROR_INJECTION(xe_guc_ads_init, ERRNO); /* See xe_pci_probe() */
@@ -820,7 +843,7 @@ static void guc_mmio_reg_state_init(struct xe_guc_ads *ads)
static void guc_um_init_params(struct xe_guc_ads *ads)
{
u32 um_queue_offset = guc_ads_um_queues_offset(ads);
struct xe_bo *um_bo = ads->um_queue_bo;
struct xe_guc *guc = ads_to_guc(ads);
struct xe_device *xe = ads_to_xe(ads);
u64 base_dpa;
@@ -830,8 +853,14 @@ static void guc_um_init_params(struct xe_guc_ads *ads)
with_dpa = !xe_guc_using_main_gamctrl_queues(guc);
base_ggtt = xe_bo_ggtt_addr(ads->bo) + um_queue_offset;
base_dpa = xe_bo_main_addr(ads->bo, PAGE_SIZE) + um_queue_offset;
if (um_bo) {
/* All USM platforms: UM queues in dedicated um_queue_bo */
base_ggtt = xe_bo_ggtt_addr(um_bo);
base_dpa = xe_bo_main_addr(um_bo, PAGE_SIZE);
} else {
/* Platform does not support USM: no UM queues, nothing to do */
return;
}
for (i = 0; i < GUC_UM_HW_QUEUE_MAX; ++i) {
/*

View File

@@ -16,6 +16,11 @@ struct xe_bo;
struct xe_guc_ads {
/** @bo: Xe BO for GuC ads blob */
struct xe_bo *bo;
/**
* @um_queue_bo: Dedicated BO for the HW fault ring (UM queues).
* NULL if the platform does not support USM.
*/
struct xe_bo *um_queue_bo;
/** @golden_lrc_size: golden LRC size */
size_t golden_lrc_size;
/** @regset_size: size of register set passed to GuC for save/restore */

View File

@@ -911,6 +911,7 @@ static bool pc_needs_min_freq_change(struct xe_guc_pc *pc)
static int pc_adjust_freq_bounds(struct xe_guc_pc *pc)
{
int ret;
u32 min_freq;
lockdep_assert_held(&pc->freq_lock);
@@ -933,8 +934,14 @@ static int pc_adjust_freq_bounds(struct xe_guc_pc *pc)
* Same thing happens for Server platforms where min is listed as
* RPMax
*/
if (pc_get_min_freq(pc) > pc->rp0_freq)
min_freq = pc_get_min_freq(pc);
if (min_freq > pc->rp0_freq) {
ret = pc_set_min_freq(pc, pc->rp0_freq);
if (ret)
goto out;
min_freq = pc->rp0_freq;
}
/*
* Setting GT RP min frequency to 1.2GHz by default for
@@ -947,8 +954,8 @@ static int pc_adjust_freq_bounds(struct xe_guc_pc *pc)
* we aren't expecting high power output across board
*
*/
if (pc_needs_min_freq_change(pc))
ret = pc_set_min_freq(pc, max(BMG_MIN_FREQ, pc_get_min_freq(pc)));
if (pc_needs_min_freq_change(pc) && min_freq < BMG_MIN_FREQ)
ret = pc_set_min_freq(pc, BMG_MIN_FREQ);
out:
return ret;

View File

@@ -1096,7 +1096,7 @@ static void xe_lrc_finish(struct xe_lrc *lrc)
* on until it is scheduled, we also read the ENGINE_ID MMIO in the WA BB and
* store it in the PPHSWP.
*/
#define CONTEXT_ACTIVE 1ULL
#define CONTEXT_ACTIVE XE_LRC_CTX_TIMESTAMP_ACTIVE
static ssize_t setup_utilization_wa(struct xe_lrc *lrc,
struct xe_hw_engine *hwe,
u32 *batch,
@@ -1849,6 +1849,13 @@ void xe_lrc_write_ring(struct xe_lrc *lrc, const void *data, size_t size)
__xe_lrc_write_ring(lrc, ring, &noop, sizeof(noop));
}
/*
* The ring and the LRC context image are both WC, so the ring tail
* update which publishes these writes can become visible to the device
* first. Ensure the ring contents are visible before returning.
*/
xe_device_wmb(xe);
}
u64 xe_lrc_descriptor(struct xe_lrc *lrc)
@@ -2720,21 +2727,27 @@ static u64 xe_lrc_update_multi_queue_timestamp(struct xe_lrc *lrc, u64 *old_ts)
static u64 xe_lrc_context_timestamp(struct xe_lrc *lrc)
{
u64 reg_ts, new_ts = lrc->ctx_timestamp;
u64 stored;
/* CTX_TIMESTAMP mmio read is invalid on VF, so return the LRC value */
if (IS_SRIOV_VF(lrc_to_xe(lrc)))
return xe_lrc_ctx_timestamp(lrc);
if (context_active(lrc) &&
!get_ctx_timestamp(lrc, xe_lrc_engine_id(lrc), &reg_ts))
/* Safely read CTX_TIMESTAMP: Avoid TOCTOU on LRC-stored CONTEXT_ACTIVE sentinel */
stored = xe_lrc_ctx_timestamp(lrc);
if (stored != CONTEXT_ACTIVE)
return stored;
/* Context is active: read the live timestamp from the engine's MMIO register */
if (!get_ctx_timestamp(lrc, xe_lrc_engine_id(lrc), &reg_ts))
new_ts = reg_ts;
/*
* If context swicthed out while we were here, just return the latest
* LRC CTX TIMESTAMP value.
/* If the context switched out prefer using the value
* from context-save over the stale MMIO read.
*/
if (!context_active(lrc))
return xe_lrc_ctx_timestamp(lrc);
stored = xe_lrc_ctx_timestamp(lrc);
if (stored != CONTEXT_ACTIVE)
return stored;
return new_ts;
}

View File

@@ -9,6 +9,13 @@
#include "xe_lrc_types.h"
/*
* Sentinel value stored in lrc->ctx_timestamp while a context is starting.
* The hardware hasn't yet written the real CTX_TIMESTAMP, so this is not a
* valid elapsed-time sample and must not be used as one.
*/
#define XE_LRC_CTX_TIMESTAMP_ACTIVE 1ULL
struct drm_printer;
struct xe_bb;
struct xe_device;

View File

@@ -1594,6 +1594,10 @@ static long xe_oa_config_locked(struct xe_oa_stream *stream, u64 arg)
config = xchg(&stream->oa_config, config);
drm_dbg(&stream->oa->xe->drm, "changed to oa config uuid=%s\n",
stream->oa_config->uuid);
} else {
while (param.num_syncs--)
xe_sync_entry_cleanup(&param.syncs[param.num_syncs]);
kfree(param.syncs);
}
err_config_put:
@@ -2713,9 +2717,7 @@ static int xe_oa_init_gt(struct xe_gt *gt)
__xe_oa_init_oa_units(gt);
drmm_mutex_init(&gt_to_xe(gt)->drm, &gt->oa.gt_lock);
return 0;
return drmm_mutex_init(&gt_to_xe(gt)->drm, &gt->oa.gt_lock);
}
static void xe_oa_print_gt_oa_units(struct xe_gt *gt)
@@ -2855,7 +2857,10 @@ int xe_oa_init(struct xe_device *xe)
oa->xe = xe;
oa->oa_formats = oa_formats;
drmm_mutex_init(&oa->xe->drm, &oa->metrics_lock);
ret = drmm_mutex_init(&oa->xe->drm, &oa->metrics_lock);
if (ret)
goto exit;
idr_init_base(&oa->metrics_idr, 1);
ret = xe_oa_init_oa_units(oa);

View File

@@ -8,6 +8,8 @@
#include <drm/drm_managed.h>
#include <uapi/drm/xe_drm.h>
#include <linux/device.h>
#include "xe_bo.h"
#include "xe_bo_types.h"
#include "xe_device_types.h"
@@ -164,16 +166,9 @@ static void mark_termination_in_progress(struct xe_pxp *pxp)
pxp->status = XE_PXP_TERMINATION_IN_PROGRESS;
}
static void pxp_terminate(struct xe_pxp *pxp)
static bool pxp_prep_for_termination(struct xe_pxp *pxp)
{
int ret = 0;
struct xe_device *xe = pxp->xe;
if (!wait_for_completion_timeout(&pxp->activation,
msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS)))
drm_err(&xe->drm, "failed to wait for PXP start before termination\n");
mutex_lock(&pxp->mutex);
lockdep_assert_held(&pxp->mutex);
if (pxp->status == XE_PXP_ACTIVE)
pxp->key_instance++;
@@ -182,10 +177,8 @@ static void pxp_terminate(struct xe_pxp *pxp)
* we'll mark the status as needing termination on resume, so no need to
* emit a termination now.
*/
if (pxp->status == XE_PXP_SUSPENDED) {
mutex_unlock(&pxp->mutex);
return;
}
if (pxp->status == XE_PXP_SUSPENDED)
return false;
/*
* If we have a termination already in progress, we need to wait for
@@ -195,15 +188,44 @@ static void pxp_terminate(struct xe_pxp *pxp)
*/
if (pxp->status == XE_PXP_TERMINATION_IN_PROGRESS) {
pxp->status = XE_PXP_NEEDS_ADDITIONAL_TERMINATION;
mutex_unlock(&pxp->mutex);
return;
return false;
}
mark_termination_in_progress(pxp);
mutex_unlock(&pxp->mutex);
return true;
}
pxp_invalidate_queues(pxp);
static void pxp_terminate(struct xe_pxp *pxp, bool hw_only)
{
struct xe_device *xe = pxp->xe;
int ret = 0;
if (!wait_for_completion_timeout(&pxp->activation,
msecs_to_jiffies(PXP_ACTIVATION_TIMEOUT_MS)))
drm_err(&xe->drm, "failed to wait for PXP start before termination\n");
if (!hw_only) {
bool prep_ok;
mutex_lock(&pxp->mutex);
prep_ok = pxp_prep_for_termination(pxp);
mutex_unlock(&pxp->mutex);
if (!prep_ok)
return;
pxp_invalidate_queues(pxp);
} else {
/*
* The caller of the HW-only termination should have already
* called pxp_prep_for_termination and marked the termination as
* in progress.
*/
xe_assert(xe, !completion_done(&pxp->termination));
}
ret = pxp_terminate_hw(pxp);
if (ret) {
@@ -249,33 +271,46 @@ static void pxp_terminate_complete(struct xe_pxp *pxp)
mutex_unlock(&pxp->mutex);
}
static void pxp_irq_work(struct work_struct *work)
static void pxp_events_work(struct work_struct *work)
{
struct xe_pxp *pxp = container_of(work, typeof(*pxp), irq.work);
struct xe_pxp *pxp = container_of(work, typeof(*pxp), events.work);
struct xe_device *xe = pxp->xe;
bool hw_only = false;
u32 events = 0;
spin_lock_irq(&xe->irq.lock);
events = pxp->irq.events;
pxp->irq.events = 0;
spin_unlock_irq(&xe->irq.lock);
events = atomic_xchg(&pxp->events.pending, 0);
if (!events)
return;
/*
* If we're processing a termination irq while suspending then don't
* bother, we're going to re-init everything on resume anyway.
* If the termination request comes from an irq while we're suspending,
* then we can defer it to the resume path instead of waking the device
* up.
* In the case of the termination on resume the pm reference is taken
* in xe_pxp_pm_resume() and released here.
* Note that we do not expect both events to be set at the same time,
* but if it does happen due to a spurious interrupt we want to behave
* as if the only request we got was the one from the resume path; this
* is because the termination prep has already been done in
* xe_pxp_pm_resume() and it is impossible for any PXP operations to
* occur between the prep and the termination completion, so there is no
* need for a new SW prep.
*/
if ((events & PXP_TERMINATION_REQUEST) && !xe_pm_runtime_get_if_active(xe))
if (events & PXP_TERMINATION_REQUEST_ON_RESUME) {
events &= ~PXP_TERMINATION_REQUEST_IRQ;
hw_only = true;
}
if ((events & PXP_TERMINATION_REQUEST_IRQ) && !xe_pm_runtime_get_if_active(xe))
return;
if (events & PXP_TERMINATION_REQUEST) {
events &= ~PXP_TERMINATION_COMPLETE;
pxp_terminate(pxp);
events &= ~PXP_TERMINATION_COMPLETE_IRQ;
pxp_terminate(pxp, hw_only);
}
if (events & PXP_TERMINATION_COMPLETE)
if (events & PXP_TERMINATION_COMPLETE_IRQ)
pxp_terminate_complete(pxp);
if (events & PXP_TERMINATION_REQUEST)
@@ -296,20 +331,18 @@ void xe_pxp_irq_handler(struct xe_device *xe, u16 iir)
return;
}
lockdep_assert_held(&xe->irq.lock);
if (unlikely(!iir))
return;
if (iir & (KCR_PXP_STATE_TERMINATED_INTERRUPT |
KCR_APP_TERMINATED_PER_FW_REQ_INTERRUPT))
pxp->irq.events |= PXP_TERMINATION_REQUEST;
atomic_or(PXP_TERMINATION_REQUEST_IRQ, &pxp->events.pending);
if (iir & KCR_PXP_STATE_RESET_COMPLETE_INTERRUPT)
pxp->irq.events |= PXP_TERMINATION_COMPLETE;
atomic_or(PXP_TERMINATION_COMPLETE_IRQ, &pxp->events.pending);
if (pxp->irq.events)
queue_work(pxp->irq.wq, &pxp->irq.work);
if (atomic_read(&pxp->events.pending))
queue_work(pxp->events.wq, &pxp->events.work);
}
static int kcr_pxp_set_status(const struct xe_pxp *pxp, bool enable)
@@ -340,7 +373,7 @@ static void pxp_fini(void *arg)
{
struct xe_pxp *pxp = arg;
destroy_workqueue(pxp->irq.wq);
destroy_workqueue(pxp->events.wq);
xe_pxp_destroy_execution_resources(pxp);
/* no need to explicitly disable KCR since we're going to do an FLR */
@@ -402,7 +435,7 @@ int xe_pxp_init(struct xe_device *xe)
INIT_LIST_HEAD(&pxp->queues.list);
spin_lock_init(&pxp->queues.lock);
INIT_WORK(&pxp->irq.work, pxp_irq_work);
INIT_WORK(&pxp->events.work, pxp_events_work);
pxp->xe = xe;
pxp->gt = gt;
@@ -421,8 +454,8 @@ int xe_pxp_init(struct xe_device *xe)
mutex_init(&pxp->mutex);
pxp->irq.wq = alloc_ordered_workqueue("pxp-wq", 0);
if (!pxp->irq.wq) {
pxp->events.wq = alloc_ordered_workqueue("pxp-wq", 0);
if (!pxp->events.wq) {
err = -ENOMEM;
goto out_free;
}
@@ -442,7 +475,7 @@ int xe_pxp_init(struct xe_device *xe)
out_kcr_disable:
kcr_pxp_disable(pxp);
out_wq:
destroy_workqueue(pxp->irq.wq);
destroy_workqueue(pxp->events.wq);
out_free:
drmm_kfree(&xe->drm, pxp);
out:
@@ -889,6 +922,7 @@ int xe_pxp_pm_suspend(struct xe_pxp *pxp)
fallthrough;
case XE_PXP_ACTIVE:
pxp->key_instance++;
pxp->needs_termination_on_resume = true;
needs_queue_inval = true;
break;
}
@@ -924,6 +958,7 @@ int xe_pxp_pm_suspend(struct xe_pxp *pxp)
*/
void xe_pxp_pm_resume(struct xe_pxp *pxp)
{
bool has_pm = false;
int err;
if (!xe_pxp_is_enabled(pxp))
@@ -931,14 +966,57 @@ void xe_pxp_pm_resume(struct xe_pxp *pxp)
err = kcr_pxp_enable(pxp);
/*
* We want to avoid the device runtime suspending before we're done with
* the termination queued below, so we need a runtime PM reference; we
* can't call the rpm functions from within the PXP lock, so we take the
* ref here. Note that we don't want the rpm resume code to actually run
* here as that would call back into this function, but as long as we
* don't enable DPM_FLAG_SMART_SUSPEND (which we currently do not) we're
* guaranteed to not be runtime suspended at this point, so we can
* safely use the get_noresume variant.
*/
if (pxp->needs_termination_on_resume) {
has_pm = true;
xe_assert(pxp->xe, !dev_pm_smart_suspend(pxp->xe->drm.dev));
xe_pm_runtime_get_noresume(pxp->xe);
}
mutex_lock(&pxp->mutex);
xe_assert(pxp->xe, pxp->status == XE_PXP_SUSPENDED);
if (err)
if (err) {
pxp->status = XE_PXP_ERROR;
else
} else {
pxp->status = XE_PXP_NEEDS_TERMINATION;
if (pxp->needs_termination_on_resume) {
pxp->needs_termination_on_resume = false;
/*
* We can't call pxp_terminate_hw directly from here
* because we're not allowed to do allocations within
* the rpm resume call, so we defer the termination to
* the worker that we use for the termination irqs.
* However, we do not want any PXP ops to go through
* between the suspend completing and the worker
* starting, so we need to do the termination prep
* immediately, which will mark the termination as in
* progress and stall PXP ops.
*/
if (pxp_prep_for_termination(pxp)) {
has_pm = false; /* move PM ref ownership to worker */
atomic_or(PXP_TERMINATION_REQUEST_ON_RESUME, &pxp->events.pending);
queue_work(pxp->events.wq, &pxp->events.work);
}
}
}
mutex_unlock(&pxp->mutex);
if (has_pm)
xe_pm_runtime_put(pxp->xe);
}

View File

@@ -85,17 +85,20 @@ struct xe_pxp {
/** @gsc_res: kernel-owned objects for PXP submissions to the GSCCS */
struct xe_pxp_gsc_client_resources gsc_res;
/** @irq: wrapper for the worker and queue used for PXP irq support */
/** @events: wrapper for the worker and queue used for PXP event handling */
struct {
/** @irq.work: worker that manages irq events. */
/** @events.work: worker that manages termination events. */
struct work_struct work;
/** @irq.wq: workqueue on which to queue the irq work. */
/** @events.wq: workqueue on which to queue the work. */
struct workqueue_struct *wq;
/** @irq.events: pending events, protected with xe->irq.lock. */
u32 events;
#define PXP_TERMINATION_REQUEST BIT(0)
#define PXP_TERMINATION_COMPLETE BIT(1)
} irq;
/** @events.pending: pending events */
atomic_t pending;
#define PXP_TERMINATION_REQUEST_IRQ BIT(0)
#define PXP_TERMINATION_REQUEST_ON_RESUME BIT(1)
#define PXP_TERMINATION_REQUEST (PXP_TERMINATION_REQUEST_IRQ | \
PXP_TERMINATION_REQUEST_ON_RESUME)
#define PXP_TERMINATION_COMPLETE_IRQ BIT(2)
} events;
/** @mutex: protects the pxp status and the queue list */
struct mutex mutex;
@@ -130,6 +133,14 @@ struct xe_pxp {
* suspend cycles.
*/
u32 last_suspend_key_instance;
/**
* @needs_termination_on_resume: indicates if PXP termination is needed
* on resume. This is set if PXP was active when we suspend and it is
* cleared when we queue the termination on resume. Since the suspend
* and resume calls cannot execute at the same time, this variable does
* not need to be protected by the PXP lock.
*/
bool needs_termination_on_resume;
};
#endif /* _XE_PXP_TYPES_H_ */

View File

@@ -8,14 +8,12 @@
* Copyright (C) 2007 MontaVista Software Inc.
* Copyright (C) 2009 Provigent Ltd.
*/
#include <linux/acpi.h>
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -132,80 +130,6 @@ static int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev)
return 0;
}
#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB)
/*
* Check whether an ACPI GpioInt resource's referenced GPIO controller
* has finished probing. Resources with no named controller (resource
* source string) are skipped, since they can't be resolved to a
* struct device.
*/
static int check_gpioint_resource(struct acpi_resource *ares, void *data)
{
struct acpi_resource_gpio *agpio;
struct acpi_device *gpio_adev;
struct device *gpio_dev;
acpi_handle handle;
acpi_status status;
if (!acpi_gpio_get_irq_resource(ares, &agpio))
return 1; /* not a GpioInt resource, skip */
if (!agpio->resource_source.string_length)
return 1; /* no named controller, skip */
status = acpi_get_handle(NULL, agpio->resource_source.string_ptr, &handle);
if (ACPI_FAILURE(status))
return 1;
gpio_adev = acpi_fetch_acpi_dev(handle);
if (!gpio_adev)
return 1;
struct gpio_device *gdev __free(gpio_device_put) =
gpio_device_find_by_fwnode(acpi_fwnode_handle(gpio_adev));
if (!gdev)
return -EPROBE_DEFER; /* controller not registered yet: abort walk */
gpio_dev = gpio_device_to_device(gdev)->parent;
guard(device)(gpio_dev);
if (!device_is_bound(gpio_dev))
return -EPROBE_DEFER; /* controller not bound yet: abort walk */
return 1; /* bound, skip adding to resource list, continue walk */
}
static int check_child_gpioint(struct acpi_device *adev, void *data)
{
LIST_HEAD(res_list);
int ret;
ret = acpi_dev_get_resources(adev, &res_list, check_gpioint_resource, NULL);
if (ret < 0)
return ret;
acpi_dev_free_resource_list(&res_list);
return 0;
}
static int i2c_dw_check_gpio_dependencies(struct device *dev)
{
struct acpi_device *adev;
adev = ACPI_COMPANION(dev);
if (!adev)
return 0;
return acpi_dev_for_each_child(adev, check_child_gpioint, NULL);
}
#else
static int i2c_dw_check_gpio_dependencies(struct device *dev)
{
return 0;
}
#endif /* CONFIG_ACPI && CONFIG_GPIOLIB */
static int dw_i2c_plat_probe(struct platform_device *pdev)
{
u32 flags = (uintptr_t)device_get_match_data(&pdev->dev);
@@ -214,10 +138,6 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
struct dw_i2c_dev *dev;
int irq, ret;
ret = i2c_dw_check_gpio_dependencies(device);
if (ret)
return ret;
irq = platform_get_irq_optional(pdev, 0);
if (irq == -ENXIO)
flags |= ACCESS_POLLING;

View File

@@ -725,21 +725,13 @@ static int sur40_probe(struct usb_interface *interface,
goto err_free_input;
}
/* register the polled input device */
error = input_register_device(input);
if (error) {
dev_err(&interface->dev,
"Unable to register polled input device.");
goto err_free_buffer;
}
/* register the video master device */
snprintf(sur40->v4l2.name, sizeof(sur40->v4l2.name), "%s", DRIVER_LONG);
error = v4l2_device_register(sur40->dev, &sur40->v4l2);
if (error) {
dev_err(&interface->dev,
"Unable to register video master device.");
goto err_unreg_v4l2;
goto err_free_buffer;
}
/* initialize the lock and subdevice */
@@ -795,6 +787,14 @@ static int sur40_probe(struct usb_interface *interface,
if (error) {
dev_err(&interface->dev,
"Unable to register video subdevice.");
goto err_free_ctrl;
}
/* register the polled input device */
error = input_register_device(input);
if (error) {
dev_err(&interface->dev,
"Unable to register polled input device.");
goto err_unreg_video;
}
@@ -806,6 +806,8 @@ static int sur40_probe(struct usb_interface *interface,
err_unreg_video:
video_unregister_device(&sur40->vdev);
err_free_ctrl:
v4l2_ctrl_handler_free(&sur40->hdl);
err_unreg_v4l2:
v4l2_device_unregister(&sur40->v4l2);
err_free_buffer:
@@ -823,11 +825,12 @@ static void sur40_disconnect(struct usb_interface *interface)
{
struct sur40_state *sur40 = usb_get_intfdata(interface);
input_unregister_device(sur40->input);
v4l2_ctrl_handler_free(&sur40->hdl);
video_unregister_device(&sur40->vdev);
v4l2_device_unregister(&sur40->v4l2);
input_unregister_device(sur40->input);
kfree(sur40->bulk_in_buffer);
kfree(sur40);

View File

@@ -2610,6 +2610,8 @@ static void atmci_remove(struct platform_device *pdev)
free_irq(platform_get_irq(pdev, 0), host);
cancel_work_sync(&host->bh_work);
clk_disable_unprepare(host->mck);
pm_runtime_disable(dev);

View File

@@ -641,8 +641,8 @@ static void ls2k0500_mmc_reorder_cmd_data(struct loongson2_mmc_host *host,
return;
for_each_sg(cmd->data->sg, sg, cmd->data->sg_len, i) {
data = sg_virt(&sg[i]);
for (j = 0; j < (sg_dma_len(&sg[i]) / 4); j++)
data = sg_virt(sg);
for (j = 0; j < (sg_dma_len(sg) / 4); j++)
if (cmd->opcode == SD_SWITCH)
data[j] = bitrev8x4(data[j]);
else
@@ -758,8 +758,8 @@ static void ls2k2000_mmc_reorder_cmd_data(struct loongson2_mmc_host *host,
return;
for_each_sg(cmd->data->sg, sg, cmd->data->sg_len, i) {
data = sg_virt(&sg[i]);
for (j = 0; j < (sg_dma_len(&sg[i]) / 4); j++)
data = sg_virt(sg);
for (j = 0; j < (sg_dma_len(sg) / 4); j++)
data[j] = bitrev8x4(data[j]);
}
}

View File

@@ -1357,7 +1357,7 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
if (req->data == NULL) {
OMAP_HSMMC_WRITE(host->base, BLK, 0);
if (req->cmd->flags & MMC_RSP_BUSY) {
timeout = req->cmd->busy_timeout * NSEC_PER_MSEC;
timeout = (u64)req->cmd->busy_timeout * NSEC_PER_MSEC;
/*
* Set an arbitrary 100ms data timeout for commands with

View File

@@ -4187,6 +4187,14 @@ void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver,
}
EXPORT_SYMBOL_GPL(__sdhci_read_caps);
static void sdhci_unmap_bounce_buffer(void *data)
{
struct sdhci_host *host = data;
dma_unmap_single(mmc_dev(host->mmc), host->bounce_addr,
host->bounce_buffer_size, DMA_BIDIRECTIONAL);
}
static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)
{
struct mmc_host *mmc = host->mmc;
@@ -4247,6 +4255,14 @@ static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)
}
host->bounce_buffer_size = bounce_size;
ret = devm_add_action_or_reset(mmc_dev(mmc),
sdhci_unmap_bounce_buffer, host);
if (ret) {
devm_kfree(mmc_dev(mmc), host->bounce_buffer);
host->bounce_buffer = NULL;
host->bounce_buffer_size = 0;
return;
}
out:
/* Lie about this since we're bouncing */

View File

@@ -659,7 +659,7 @@ struct sdhci_host {
unsigned int tuning_count; /* Timer count for re-tuning */
unsigned int tuning_mode; /* Re-tuning mode supported by host */
unsigned int tuning_err; /* Error code for re-tuning */
int tuning_err; /* Error code for re-tuning */
#define SDHCI_TUNING_MODE_1 0
#define SDHCI_TUNING_MODE_2 1
#define SDHCI_TUNING_MODE_3 2

View File

@@ -11789,10 +11789,21 @@ static void bnxt_irq_affinity_notify(struct irq_affinity_notify *notify,
{
struct bnxt_irq *irq;
u16 tag;
int err;
irq = container_of(notify, struct bnxt_irq, affinity_notify);
#ifdef CONFIG_RFS_ACCEL
if (irq->bp->dev->rx_cpu_rmap && irq->ring_nr < irq->bp->rx_nr_rings) {
int err;
err = cpu_rmap_update(irq->bp->dev->rx_cpu_rmap, irq->ring_nr,
mask);
if (err)
netdev_warn(irq->bp->dev,
"aRFS rmap update failed: %d\n", err);
}
#endif
if (!irq->bp->tph_mode)
return;
@@ -11802,20 +11813,11 @@ static void bnxt_irq_affinity_notify(struct irq_affinity_notify *notify,
return;
if (pcie_tph_get_cpu_st(irq->bp->pdev, TPH_MEM_TYPE_VM,
cpumask_first(irq->cpu_mask), &tag))
cpumask_first(mask), &tag))
return;
if (pcie_tph_set_st_entry(irq->bp->pdev, irq->msix_nr, tag))
return;
netdev_lock(irq->bp->dev);
if (netif_running(irq->bp->dev)) {
err = netdev_rx_queue_restart(irq->bp->dev, irq->ring_nr);
if (err)
netdev_err(irq->bp->dev,
"RX queue restart failed: err=%d\n", err);
}
netdev_unlock(irq->bp->dev);
WRITE_ONCE(irq->new_tag, tag);
bnxt_queue_sp_work(irq->bp, BNXT_TPH_UPDATE_SP_EVENT);
}
static void bnxt_irq_affinity_release(struct kref *ref)
@@ -11866,10 +11868,6 @@ static void bnxt_free_irq(struct bnxt *bp)
struct bnxt_irq *irq;
int i;
#ifdef CONFIG_RFS_ACCEL
free_irq_cpu_rmap(bp->dev->rx_cpu_rmap);
bp->dev->rx_cpu_rmap = NULL;
#endif
if (!bp->irq_tbl || !bp->bnapi)
return;
@@ -11878,27 +11876,35 @@ static void bnxt_free_irq(struct bnxt *bp)
irq = &bp->irq_tbl[map_idx];
if (irq->requested) {
bnxt_release_irq_notifier(irq);
if (irq->have_cpumask) {
irq_update_affinity_hint(irq->vector, NULL);
free_cpumask_var(irq->cpu_mask);
irq->have_cpumask = 0;
}
bnxt_release_irq_notifier(irq);
free_irq(irq->vector, bp->bnapi[i]);
}
irq->requested = 0;
irq->tag = 0;
irq->new_tag = 0;
}
/* Disable TPH support */
pcie_disable_tph(bp->pdev);
bp->tph_mode = 0;
#ifdef CONFIG_RFS_ACCEL
free_irq_cpu_rmap(bp->dev->rx_cpu_rmap);
bp->dev->rx_cpu_rmap = NULL;
#endif
}
static int bnxt_request_irq(struct bnxt *bp)
{
const int numa_node = dev_to_node(&bp->pdev->dev);
struct cpu_rmap *rmap = NULL;
int i, j, rc = 0;
unsigned long flags = 0;
@@ -11921,6 +11927,8 @@ static int bnxt_request_irq(struct bnxt *bp)
for (i = 0, j = 0; i < bp->cp_nr_rings; i++) {
int map_idx = bnxt_cp_num_to_irq_num(bp, i);
struct bnxt_irq *irq = &bp->irq_tbl[map_idx];
unsigned int cpu_num;
u16 tag;
if (IS_ENABLED(CONFIG_RFS_ACCEL) &&
rmap && bp->bnapi[i]->rx_ring) {
@@ -11939,32 +11947,31 @@ static int bnxt_request_irq(struct bnxt *bp)
netif_napi_set_irq_locked(&bp->bnapi[i]->napi, irq->vector);
irq->requested = 1;
if (zalloc_cpumask_var(&irq->cpu_mask, GFP_KERNEL)) {
int numa_node = dev_to_node(&bp->pdev->dev);
u16 tag;
if (!zalloc_cpumask_var(&irq->cpu_mask, GFP_KERNEL))
continue;
irq->have_cpumask = 1;
irq->msix_nr = map_idx;
irq->ring_nr = i;
cpumask_set_cpu(cpumask_local_spread(i, numa_node),
irq->cpu_mask);
rc = irq_update_affinity_hint(irq->vector, irq->cpu_mask);
if (rc) {
netdev_warn(bp->dev,
"Update affinity hint failed, IRQ = %d\n",
irq->vector);
break;
}
irq->have_cpumask = 1;
irq->msix_nr = map_idx;
irq->ring_nr = i;
cpu_num = cpumask_local_spread(i, numa_node);
cpumask_set_cpu(cpu_num, irq->cpu_mask);
bnxt_register_irq_notifier(bp, irq);
/* Init ST table entry if we can get the mapping */
if (!pcie_tph_get_cpu_st(bp->pdev, TPH_MEM_TYPE_VM,
cpu_num, &tag)) {
pcie_tph_set_st_entry(bp->pdev, irq->msix_nr, tag);
irq->tag = tag;
irq->new_tag = tag;
}
/* Init ST table entry */
if (pcie_tph_get_cpu_st(irq->bp->pdev, TPH_MEM_TYPE_VM,
cpumask_first(irq->cpu_mask),
&tag))
continue;
bnxt_register_irq_notifier(bp, irq);
pcie_tph_set_st_entry(irq->bp->pdev, irq->msix_nr, tag);
rc = irq_update_affinity_hint(irq->vector, irq->cpu_mask);
if (rc) {
netdev_warn(bp->dev,
"Update affinity hint failed, IRQ = %d\n",
irq->vector);
break;
}
}
return rc;
@@ -14468,6 +14475,43 @@ static void bnxt_rtnl_unlock_sp(struct bnxt *bp)
rtnl_unlock();
}
static void bnxt_tph_update(struct bnxt *bp)
{
struct net_device *dev = bp->dev;
int i;
bnxt_lock_sp(bp);
if (!test_bit(BNXT_STATE_OPEN, &bp->state))
goto unlock;
for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_irq *irq;
int map_idx, err;
u16 tag;
map_idx = bnxt_cp_num_to_irq_num(bp, i);
irq = &bp->irq_tbl[map_idx];
tag = READ_ONCE(irq->new_tag);
if (irq->tag == tag)
continue;
if (pcie_tph_set_st_entry(bp->pdev, irq->msix_nr, tag))
continue;
err = netdev_rx_queue_restart(dev, irq->ring_nr);
if (err) {
netdev_err(dev, "RX queue restart failed: err=%d\n",
err);
continue;
}
irq->tag = tag;
}
unlock:
bnxt_unlock_sp(bp);
}
/* Only called from bnxt_sp_task() */
static void bnxt_reset(struct bnxt *bp, bool silent)
{
@@ -14892,6 +14936,9 @@ static void bnxt_sp_task(struct work_struct *work)
bnxt_devlink_health_fw_report(bp);
}
if (test_and_clear_bit(BNXT_TPH_UPDATE_SP_EVENT, &bp->sp_event))
bnxt_tph_update(bp);
smp_mb__before_atomic();
clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
}

View File

@@ -1268,6 +1268,8 @@ struct bnxt_irq {
struct bnxt *bp;
int msix_nr;
int ring_nr;
u16 tag;
u16 new_tag;
struct irq_affinity_notify affinity_notify;
};
@@ -2642,6 +2644,7 @@ struct bnxt {
#define BNXT_RING_COAL_NOW_SP_EVENT 17
#define BNXT_FW_RESET_NOTIFY_SP_EVENT 18
#define BNXT_FW_EXCEPTION_SP_EVENT 19
#define BNXT_TPH_UPDATE_SP_EVENT 20
#define BNXT_LINK_CFG_CHANGE_SP_EVENT 21
#define BNXT_THERMAL_THRESHOLD_SP_EVENT 22
#define BNXT_FW_ECHO_REQUEST_SP_EVENT 23

View File

@@ -26,6 +26,11 @@ int gve_clock_nic_ts_read(struct gve_priv *priv)
return 0;
}
static int gve_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{
return -EOPNOTSUPP;
}
static int gve_ptp_gettimex64(struct ptp_clock_info *info,
struct timespec64 *ts,
struct ptp_system_timestamp *sts)
@@ -60,6 +65,7 @@ static long gve_ptp_do_aux_work(struct ptp_clock_info *info)
static const struct ptp_clock_info gve_ptp_caps = {
.owner = THIS_MODULE,
.name = "gve clock",
.adjfine = gve_ptp_adjfine,
.gettimex64 = gve_ptp_gettimex64,
.settime64 = gve_ptp_settime64,
.do_aux_work = gve_ptp_do_aux_work,

View File

@@ -886,6 +886,11 @@ static int gve_rx_dqo(struct napi_struct *napi, struct gve_rx_ring *rx,
rx->rx_hsplit_unsplit_pkt += unsplit;
rx->rx_hsplit_bytes += hdr_len;
u64_stats_update_end(&rx->statss);
if (!buf_len) {
gve_free_buffer(rx, buf_state);
return 0;
}
} else if (!rx->ctx.skb_head && rx->dqo.page_pool &&
netmem_is_net_iov(buf_state->page_info.netmem)) {
/* when header split is disabled, the header went to the packet

View File

@@ -1310,6 +1310,8 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_rx_flow *flow,
k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL);
/* Port ID is contained in the lower 8-bits of the 16-bit Source Tag */
port_id &= 0xFF;
dev_dbg(dev, "%s rx port_id:%d\n", __func__, port_id);
port = am65_common_get_port(common, port_id);
ndev = port->ndev;

View File

@@ -180,8 +180,10 @@ static void ngbe_irq_enable(struct wx *wx, bool queues)
/* mask interrupt */
if (queues)
wx_intr_enable(wx, NGBE_INTR_ALL);
else
else if (wx->pdev->msix_enabled)
wx_intr_enable(wx, NGBE_INTR_MISC(wx));
else
wx_intr_enable(wx, BIT(0));
}
/**

View File

@@ -146,6 +146,8 @@ static int ipvlan_init(struct net_device *dev)
dev->lltx = true;
netif_inherit_tso_max(dev, phy_dev);
dev->hard_header_len = phy_dev->hard_header_len;
dev->needed_headroom = phy_dev->needed_headroom;
dev->needed_tailroom = phy_dev->needed_tailroom;
netdev_lockdep_set_classes(dev);
@@ -773,6 +775,8 @@ static int ipvlan_device_event(struct notifier_block *unused,
case NETDEV_FEAT_CHANGE:
list_for_each_entry(ipvlan, &port->ipvlans, pnode) {
netif_inherit_tso_max(ipvlan->dev, dev);
ipvlan->dev->needed_headroom = dev->needed_headroom;
ipvlan->dev->needed_tailroom = dev->needed_tailroom;
netdev_update_features(ipvlan->dev);
}
break;

View File

@@ -950,6 +950,8 @@ static int macvlan_init(struct net_device *dev)
dev->lltx = true;
netif_inherit_tso_max(dev, lowerdev);
dev->hard_header_len = lowerdev->hard_header_len;
dev->needed_headroom = lowerdev->needed_headroom;
dev->needed_tailroom = lowerdev->needed_tailroom;
macvlan_set_lockdep_class(dev);
vlan->pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
@@ -1824,6 +1826,8 @@ static int macvlan_device_event(struct notifier_block *unused,
case NETDEV_FEAT_CHANGE:
list_for_each_entry(vlan, &port->vlans, list) {
netif_inherit_tso_max(vlan->dev, dev);
vlan->dev->needed_headroom = dev->needed_headroom;
vlan->dev->needed_tailroom = dev->needed_tailroom;
netdev_update_features(vlan->dev);
}
break;

View File

@@ -127,8 +127,8 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
{
struct ntb_netdev_queue *q = qp_data;
struct ntb_netdev *dev = q->ntdev;
struct sk_buff *skb, *new_skb;
struct net_device *ndev;
struct sk_buff *skb;
int rc;
ndev = dev->ndev;
@@ -144,6 +144,12 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
goto enqueue_again;
}
new_skb = netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN);
if (!new_skb) {
ndev->stats.rx_dropped++;
goto enqueue_again;
}
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, ndev);
skb->ip_summed = CHECKSUM_NONE;
@@ -157,12 +163,7 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
ndev->stats.rx_bytes += len;
}
skb = netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN);
if (!skb) {
ndev->stats.rx_errors++;
ndev->stats.rx_frame_errors++;
return;
}
skb = new_skb;
enqueue_again:
rc = ntb_transport_rx_enqueue(qp, skb, skb->data, ndev->mtu + ETH_HLEN);

View File

@@ -18,20 +18,12 @@
#include "crypto_aead.h"
#include "crypto.h"
static void ovpn_ks_destroy_rcu(struct rcu_head *head)
{
struct ovpn_crypto_key_slot *ks;
ks = container_of(head, struct ovpn_crypto_key_slot, rcu);
ovpn_aead_crypto_key_slot_destroy(ks);
}
void ovpn_crypto_key_slot_release(struct kref *kref)
{
struct ovpn_crypto_key_slot *ks;
ks = container_of(kref, struct ovpn_crypto_key_slot, refcount);
call_rcu(&ks->rcu, ovpn_ks_destroy_rcu);
queue_rcu_work(ovpn_wq, &ks->free_work);
}
/* can only be invoked when all peer references have been dropped (i.e. RCU
@@ -58,15 +50,19 @@ void ovpn_crypto_state_release(struct ovpn_crypto_state *cs)
bool ovpn_crypto_kill_key(struct ovpn_crypto_state *cs, u8 key_id)
{
struct ovpn_crypto_key_slot *ks = NULL;
struct ovpn_crypto_key_slot *tmp;
int slot = 0;
spin_lock_bh(&cs->lock);
if (rcu_access_pointer(cs->slots[0])->key_id == key_id) {
ks = rcu_replace_pointer(cs->slots[0], NULL,
lockdep_is_held(&cs->lock));
} else if (rcu_access_pointer(cs->slots[1])->key_id == key_id) {
ks = rcu_replace_pointer(cs->slots[1], NULL,
lockdep_is_held(&cs->lock));
tmp = rcu_access_pointer(cs->slots[slot]);
if (!tmp || tmp->key_id != key_id) {
slot = 1;
tmp = rcu_access_pointer(cs->slots[slot]);
}
if (tmp && tmp->key_id == key_id)
ks = rcu_replace_pointer(cs->slots[slot], NULL,
lockdep_is_held(&cs->lock));
spin_unlock_bh(&cs->lock);
if (ks)

View File

@@ -10,6 +10,8 @@
#ifndef _NET_OVPN_OVPNCRYPTO_H_
#define _NET_OVPN_OVPNCRYPTO_H_
#include <linux/workqueue.h>
#include "pktid.h"
#include "proto.h"
@@ -45,8 +47,8 @@ struct ovpn_crypto_key_slot {
struct ovpn_pktid_recv pid_recv ____cacheline_aligned_in_smp;
struct ovpn_pktid_xmit pid_xmit ____cacheline_aligned_in_smp;
struct rcu_work free_work;
struct kref refcount;
struct rcu_head rcu;
};
struct ovpn_crypto_state {

View File

@@ -9,6 +9,7 @@
#include <crypto/aead.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/udp.h>
@@ -380,13 +381,19 @@ static struct crypto_aead *ovpn_aead_init(const char *title,
return ERR_PTR(ret);
}
void ovpn_aead_crypto_key_slot_destroy(struct ovpn_crypto_key_slot *ks)
static void ovpn_aead_crypto_key_slot_free(struct ovpn_crypto_key_slot *ks)
{
if (!ks)
return;
crypto_free_aead(ks->encrypt);
crypto_free_aead(ks->decrypt);
}
static void ovpn_aead_crypto_key_slot_free_work(struct work_struct *work)
{
struct ovpn_crypto_key_slot *ks;
ks = container_of(to_rcu_work(work), struct ovpn_crypto_key_slot,
free_work);
ovpn_aead_crypto_key_slot_free(ks);
kfree(ks);
}
@@ -420,6 +427,7 @@ ovpn_aead_crypto_key_slot_new(const struct ovpn_key_config *kc)
ks->encrypt = NULL;
ks->decrypt = NULL;
INIT_RCU_WORK(&ks->free_work, ovpn_aead_crypto_key_slot_free_work);
kref_init(&ks->refcount);
ks->key_id = kc->key_id;
@@ -453,7 +461,8 @@ ovpn_aead_crypto_key_slot_new(const struct ovpn_key_config *kc)
return ks;
destroy_ks:
ovpn_aead_crypto_key_slot_destroy(ks);
ovpn_aead_crypto_key_slot_free(ks);
kfree(ks);
return ERR_PTR(ret);
}

View File

@@ -22,7 +22,6 @@ int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
struct ovpn_crypto_key_slot *
ovpn_aead_crypto_key_slot_new(const struct ovpn_key_config *kc);
void ovpn_aead_crypto_key_slot_destroy(struct ovpn_crypto_key_slot *ks);
enum ovpn_cipher_alg ovpn_aead_crypto_alg(struct ovpn_crypto_key_slot *ks);

View File

@@ -204,10 +204,10 @@ void ovpn_decrypt_post(void *data, int ret)
ovpn_dev_dstats_rx_dropped(peer->ovpn->dev);
kfree_skb(skb);
drop_nocount:
if (likely(peer))
ovpn_peer_put(peer);
if (likely(ks))
ovpn_crypto_key_slot_put(ks);
if (likely(peer))
ovpn_peer_put(peer);
}
/* RX path entry point: decrypt packet and forward it to the device */
@@ -302,11 +302,11 @@ void ovpn_encrypt_post(void *data, int ret)
err:
if (unlikely(skb))
ovpn_dev_dstats_tx_dropped(peer->ovpn->dev);
if (likely(peer))
ovpn_peer_put(peer);
kfree_skb(skb);
if (likely(ks))
ovpn_crypto_key_slot_put(ks);
kfree_skb(skb);
if (likely(peer))
ovpn_peer_put(peer);
}
static bool ovpn_encrypt_one(struct ovpn_peer *peer, struct sk_buff *skb)

View File

@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/workqueue.h>
#include <net/gro_cells.h>
#include <net/ip.h>
#include <net/rtnetlink.h>
@@ -26,6 +27,9 @@
#include "tcp.h"
#include "udp.h"
/* module-owned workqueue on which all ovpn-specific work is queued */
struct workqueue_struct *ovpn_wq;
static void ovpn_priv_free(struct net_device *net)
{
struct ovpn_priv *ovpn = netdev_priv(net);
@@ -264,10 +268,16 @@ static int __init ovpn_init(void)
ovpn_tcp_init();
ovpn_wq = alloc_workqueue("ovpn", WQ_PERCPU, 0);
if (!ovpn_wq) {
pr_err("ovpn: cannot allocate workqueue\n");
return -ENOMEM;
}
err = rtnl_link_register(&ovpn_link_ops);
if (err) {
pr_err("ovpn: can't register rtnl link ops: %d\n", err);
return err;
goto destroy_wq;
}
err = ovpn_nl_register();
@@ -280,6 +290,9 @@ static int __init ovpn_init(void)
unreg_rtnl:
rtnl_link_unregister(&ovpn_link_ops);
destroy_wq:
destroy_workqueue(ovpn_wq);
ovpn_wq = NULL;
return err;
}
@@ -288,7 +301,11 @@ static __exit void ovpn_cleanup(void)
ovpn_nl_unregister();
rtnl_link_unregister(&ovpn_link_ops);
flush_workqueue(ovpn_wq);
rcu_barrier();
destroy_workqueue(ovpn_wq);
ovpn_wq = NULL;
}
module_init(ovpn_init);

View File

@@ -15,6 +15,10 @@
#include <uapi/linux/if_link.h>
#include <uapi/linux/ovpn.h>
struct workqueue_struct;
extern struct workqueue_struct *ovpn_wq;
/**
* struct ovpn_peer_collection - container of peers for MultiPeer mode
* @by_id: table of peers index by ID

View File

@@ -62,7 +62,7 @@ void ovpn_peer_keepalive_set(struct ovpn_peer *peer, u32 interval, u32 timeout)
/* now that interval and timeout have been changed, kick
* off the worker so that the next delay can be recomputed
*/
mod_delayed_work(system_percpu_wq, &peer->ovpn->keepalive_work, 0);
mod_delayed_work(ovpn_wq, &peer->ovpn->keepalive_work, 0);
}
/**
@@ -1371,7 +1371,7 @@ static time64_t ovpn_peer_keepalive_work_single(struct ovpn_peer *peer,
peer->id);
if (WARN_ON(!ovpn_peer_hold(peer)))
return 0;
if (!schedule_work(&peer->keepalive_work))
if (!queue_work(ovpn_wq, &peer->keepalive_work))
ovpn_peer_put(peer);
}
@@ -1463,8 +1463,8 @@ void ovpn_peer_keepalive_work(struct work_struct *work)
netdev_dbg(ovpn->dev,
"scheduling keepalive work: now=%llu next_run=%llu delta=%llu\n",
next_run, now, next_run - now);
schedule_delayed_work(&ovpn->keepalive_work,
(next_run - now) * HZ);
queue_delayed_work(ovpn_wq, &ovpn->keepalive_work,
(next_run - now) * HZ);
}
unlock_ovpn(ovpn, &release_list);
}

View File

@@ -151,7 +151,7 @@ static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)
/* take reference for deferred peer deletion. should never fail */
if (WARN_ON(!ovpn_peer_hold(peer)))
goto err_nopeer;
if (!schedule_work(&peer->tcp.defer_del_work))
if (!queue_work(ovpn_wq, &peer->tcp.defer_del_work))
ovpn_peer_put(peer);
ovpn_dev_dstats_rx_dropped(peer->ovpn->dev);
err_nopeer:
@@ -284,13 +284,12 @@ static void ovpn_tcp_send_sock(struct ovpn_peer *peer, struct sock *sk)
* stream therefore we abort the connection
*/
ovpn_peer_hold(peer);
if (!schedule_work(&peer->tcp.defer_del_work))
if (!queue_work(ovpn_wq, &peer->tcp.defer_del_work))
ovpn_peer_put(peer);
/* we bail out immediately and keep tx_in_progress set
* to true. This way we prevent more TX attempts
* which would lead to more invocations of
* schedule_work()
* which would lead to more invocations of queue_work()
*/
return;
}
@@ -487,7 +486,7 @@ static void ovpn_tcp_write_space(struct sock *sk)
rcu_read_lock();
sock = rcu_dereference_sk_user_data(sk);
if (likely(sock && sock->peer)) {
schedule_work(&sock->tcp_tx_work);
queue_work(ovpn_wq, &sock->tcp_tx_work);
sock->peer->tcp.sk_cb.sk_write_space(sk);
}
rcu_read_unlock();

View File

@@ -1370,7 +1370,7 @@ static int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
if (devnum == MDIO_MMD_VEND2)
ret = rtlgen_write_vend2(phydev, regnum, val);
else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV)
ret = rtlgen_write_vend2(phydev, regnum, RTL_MDIO_AN_EEE_ADV);
ret = rtlgen_write_vend2(phydev, RTL_MDIO_AN_EEE_ADV, val);
else
ret = -EOPNOTSUPP;

View File

@@ -1091,12 +1091,13 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
}
}
skb_probe_transport_header(skb);
/* Move network header to the right position for VLAN tagged packets */
if (eth_type_vlan(skb->protocol) &&
vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
skb_set_network_header(skb, depth);
skb_probe_transport_header(skb);
dev_queue_xmit(skb);
rcu_read_unlock();

View File

@@ -865,18 +865,24 @@ static struct sk_buff *veth_xdp_rcv_skb(struct veth_rq *rq,
skb_reset_mac_header(skb);
/* check if bpf_xdp_adjust_tail was used */
off = xdp->data_end - orig_data_end;
if (off != 0)
__skb_put(skb, off); /* positive on grow, negative on shrink */
/* XDP frag metadata (e.g. nr_frags) are updated in eBPF helpers
* (e.g. bpf_xdp_adjust_tail), we need to update data_len here.
* (e.g. bpf_xdp_adjust_tail). Remove the old fragment contribution
* from skb->len before updating data_len, then add the new one back.
*/
if (xdp_buff_has_frags(xdp))
skb->len -= skb->data_len;
if (xdp_buff_has_frags(xdp)) {
skb->data_len = skb_shinfo(skb)->xdp_frags_size;
else
skb->len += skb->data_len;
} else {
skb->data_len = 0;
}
/* Synchronize the skb tail with XDP's updated linear area. */
off = xdp->data_end - orig_data_end;
if (off != 0) {
skb_set_tail_pointer(skb, xdp->data_end - xdp->data);
skb->len += off; /* positive on grow, negative on shrink */
}
skb->protocol = eth_type_trans(skb, rq->dev);
@@ -961,7 +967,7 @@ static int veth_poll(struct napi_struct *napi, int budget)
struct veth_rq *rq =
container_of(napi, struct veth_rq, xdp_napi);
struct veth_priv *priv = netdev_priv(rq->dev);
int queue_idx = rq->xdp_rxq.queue_index;
int queue_idx = rq - priv->rq;
struct netdev_queue *peer_txq;
struct veth_stats stats = {};
struct net_device *peer_dev;

View File

@@ -4500,7 +4500,7 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
if (change_igmp && vxlan_addr_multicast(&dst->remote_ip))
err = vxlan_multicast_leave(vxlan);
if (conf.age_interval != vxlan->cfg.age_interval)
if (netif_running(dev) && conf.age_interval != vxlan->cfg.age_interval)
mod_timer(&vxlan->age_timer, jiffies);
netdev_adjacent_change_commit(dst->remote_dev, lowerdev, dev);

View File

@@ -1189,10 +1189,7 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
mt76_for_each_q_rx(dev, i) {
struct mt76_queue *q = &dev->q_rx[i];
if (!mt76_queue_is_wed_rro(q)) {
napi_disable(&dev->napi[i]);
netif_napi_del(&dev->napi[i]);
}
netif_napi_del(&dev->napi[i]);
mt76_dma_rx_cleanup(dev, q);
page_pool_destroy(q->page_pool);

View File

@@ -802,7 +802,7 @@ mt7921_regd_set_6ghz_power_type(struct ieee80211_vif *vif, bool is_add)
out:
if (vif->bss_conf.chanreq.oper.chan->band == NL80211_BAND_6GHZ)
mt7921_mcu_regd_update(dev, dev->mt76.alpha2, dev->country_ie_env);
__mt7921_mcu_regd_update(dev, dev->mt76.alpha2, dev->country_ie_env);
}
int mt7921_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,

View File

@@ -71,36 +71,44 @@ mt7921_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev)
}
}
int mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap country_ie_env)
/* Internal version that assumes mutex is already held by caller */
int __mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap country_ie_env)
{
struct mt76_dev *mdev = &dev->mt76;
struct ieee80211_hw *hw = mdev->hw;
struct wiphy *wiphy = hw->wiphy;
int ret = 0;
dev->regd_in_progress = true;
mt792x_mutex_acquire(dev);
if (!dev->regd_change)
goto err;
return 0;
ret = mt7921_mcu_set_clc(dev, alpha2, country_ie_env);
if (ret < 0)
goto err;
return ret;
mt7921_regd_channel_update(wiphy, dev);
ret = mt76_connac_mcu_set_channel_domain(hw->priv);
if (ret < 0)
goto err;
return ret;
ret = mt7921_set_tx_sar_pwr(hw, NULL);
if (ret < 0)
goto err;
err:
return ret;
}
int mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap country_ie_env)
{
int ret = 0;
dev->regd_in_progress = true;
mt792x_mutex_acquire(dev);
ret = __mt7921_mcu_regd_update(dev, alpha2, country_ie_env);
mt792x_mutex_release(dev);
dev->regd_change = false;
dev->regd_in_progress = false;
wake_up(&dev->wait);

View File

@@ -10,6 +10,8 @@ struct regulatory_request;
int mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap country_ie_env);
int __mt7921_mcu_regd_update(struct mt792x_dev *dev, u8 *alpha2,
enum environment_cap country_ie_env);
void mt7921_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request);
bool mt7921_regd_clc_supported(struct mt792x_dev *dev);

View File

@@ -33,7 +33,7 @@ scmi_pd_set_perf_state(struct generic_pm_domain *genpd, unsigned int state)
return 0;
if (!state)
return -EINVAL;
return 0;
ret = pd->perf_ops->level_set(pd->ph, pd->domain_id, state, false);
if (ret)

View File

@@ -47,7 +47,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
.pwr_sta2nd_offs = 0x0184,
.sram_pdn_bits = 0,
.sram_pdn_ack_bits = 0,
.caps = MTK_SCPD_DOMAIN_SUPPLY,
.caps = MTK_SCPD_DOMAIN_SUPPLY | MTK_SCPD_KEEP_DEFAULT_OFF,
},
[MT8183_POWER_DOMAIN_MFG] = {
.name = "mfg",
@@ -57,7 +57,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
.pwr_sta2nd_offs = 0x0184,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.caps = MTK_SCPD_DOMAIN_SUPPLY,
.caps = MTK_SCPD_DOMAIN_SUPPLY | MTK_SCPD_KEEP_DEFAULT_OFF,
},
[MT8183_POWER_DOMAIN_MFG_CORE0] = {
.name = "mfg_core0",
@@ -67,6 +67,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
.pwr_sta2nd_offs = 0x0184,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
},
[MT8183_POWER_DOMAIN_MFG_CORE1] = {
.name = "mfg_core1",
@@ -76,6 +77,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
.pwr_sta2nd_offs = 0x0184,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
},
[MT8183_POWER_DOMAIN_MFG_2D] = {
.name = "mfg_2d",
@@ -85,6 +87,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
.pwr_sta2nd_offs = 0x0184,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
.bp_cfg = {
BUS_PROT_WR(INFRA,
MT8183_TOP_AXI_PROT_EN_1_MFG,

View File

@@ -657,7 +657,7 @@ static int mtk_mfg_attach_dev(struct generic_pm_domain *pd, struct device *dev)
struct mtk_mfg *mfg = mtk_mfg_from_genpd(pd);
struct dev_pm_opp_data *so = mfg->stack_opps;
struct dev_pm_opp_data *go = mfg->gpu_opps;
struct dev_pm_opp_data *prev_o;
struct dev_pm_opp_data *prev_o = NULL;
struct dev_pm_opp_data *o;
int i, ret;

View File

@@ -486,16 +486,8 @@ static int scpsys_ctl_pwrseq_on(struct scpsys_domain *pd)
if (ret < 0)
return ret;
if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RTFF_CLK_DIS);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
/* Wait for RTFF HW to sync buck isolation state if this is PCIe PHY RTFF */
if (pd->data->rtff_type == SCPSYS_RTFF_TYPE_PCIE_PHY)
udelay(5);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
/*
@@ -1058,12 +1050,15 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
node = of_find_node_with_property(np, "mediatek,infracfg");
if (node) {
regmap[0] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg");
of_node_put(node);
num_regmaps++;
if (IS_ERR(regmap[0]))
return dev_err_probe(dev, PTR_ERR(regmap[0]),
if (IS_ERR(regmap[0])) {
ret = dev_err_probe(dev, PTR_ERR(regmap[0]),
"%pOF: failed to get infracfg regmap\n",
node);
of_node_put(node);
return ret;
}
of_node_put(node);
} else {
regmap[0] = NULL;
}
@@ -1072,17 +1067,22 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
node = of_find_node_with_property(np, "mediatek,smi");
if (node) {
smi_np = of_parse_phandle(node, "mediatek,smi", 0);
of_node_put(node);
if (!smi_np)
if (!smi_np) {
of_node_put(node);
return -ENODEV;
}
regmap[1] = device_node_to_regmap(smi_np);
num_regmaps++;
of_node_put(smi_np);
if (IS_ERR(regmap[1]))
return dev_err_probe(dev, PTR_ERR(regmap[1]),
if (IS_ERR(regmap[1])) {
ret = dev_err_probe(dev, PTR_ERR(regmap[1]),
"%pOF: failed to get SMI regmap\n",
node);
of_node_put(node);
return ret;
}
of_node_put(node);
} else {
regmap[1] = NULL;
}

View File

@@ -245,9 +245,13 @@ static struct rpmhpd *eliza_rpmhpds[] = {
[RPMHPD_GFX] = &gfx,
[RPMHPD_LCX] = &lcx,
[RPMHPD_LMX] = &lmx,
[RPMHPD_MMCX] = &mmcx,
[RPMHPD_MMCX_AO] = &mmcx_ao,
[RPMHPD_MSS] = &mss,
[RPMHPD_MX] = &mx,
[RPMHPD_MX_AO] = &mx_ao,
[RPMHPD_MXC] = &mxc,
[RPMHPD_MXC_AO] = &mxc_ao,
[RPMHPD_NSP] = &nsp,
};

View File

@@ -37,48 +37,18 @@ struct fp9931_data {
};
static const unsigned int VPOSNEG_table[] = {
7040000,
7040000,
7040000,
7040000,
7040000,
7040000,
7260000,
7490000,
7710000,
7930000,
8150000,
8380000,
8600000,
8820000,
9040000,
9270000,
9490000,
9710000,
9940000,
10160000,
10380000,
10600000,
10830000,
11050000,
11270000,
11490000,
11720000,
11940000,
12160000,
12380000,
12610000,
12830000,
13050000,
13280000,
13500000,
13720000,
13940000,
14170000,
14390000,
14610000,
14830000,
15060000,
7040000, 7040000, 7040000, 7040000, 7040000, /* 00h-04h */
7260000, 7490000, 7710000, 7930000, 8150000, 8380000, /* 05h-0Ah */
8600000, 8820000, 9040000, 9270000, 9490000, 9710000, /* 0Bh-10h */
9940000, 10160000, 10380000, 10600000, 10830000, 11050000, /* 11h-16h */
11270000, 11490000, 11720000, 11940000, 12160000, 12380000, /* 17h-1Ch */
12610000, 12830000, 13050000, 13280000, 13500000, 13720000, /* 1Dh-22h */
13940000, 14170000, 14390000, 14610000, 14830000, 15060000, /* 23h-28h */
/* 29h-3Fh: clamped to 15.06V per datasheet */
15060000, 15060000, 15060000, 15060000, 15060000, 15060000,
15060000, 15060000, 15060000, 15060000, 15060000, 15060000,
15060000, 15060000, 15060000, 15060000, 15060000, 15060000,
15060000, 15060000, 15060000, 15060000, 15060000,
};
static const struct hwmon_channel_info *fp9931_info[] = {

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