mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-11 18:25:33 -04:00
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:
4
.mailmap
4
.mailmap
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
2
Makefile
2
Makefile
@@ -2,7 +2,7 @@
|
||||
VERSION = 7
|
||||
PATCHLEVEL = 2
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc7
|
||||
EXTRAVERSION =
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(®s->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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
/*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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), ®_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), ®_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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(¶m.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(>_to_xe(gt)->drm, >->oa.gt_lock);
|
||||
|
||||
return 0;
|
||||
return drmm_mutex_init(>_to_xe(gt)->drm, >->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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user