Commit ae971859 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arm-fixes-6.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull arm SoC fixes from Arnd Bergmann:
 "There are a couple of devicetree fixes for samsung, riscv/sophgo, and
  for TPM device nodes on a couple of platforms.

  Both the Arm FF-A and the SCMI firmware drivers get a number of code
  fixes, addressing minor implementation bugs and compatibility with
  firmware implementations. Most of these bugs relate to the usage of
  xarray and rwlock structures and are fixed by Cristian Marussi"

* tag 'arm-fixes-6.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc:
  riscv: dts: sophgo: separate sg2042 mtime and mtimecmp to fit aclint format
  arm64: dts: Fix TPM schema violations
  ARM: dts: Fix TPM schema violations
  ARM: dts: exynos4212-tab3: add samsung,invert-vclk flag to fimd
  arm64: dts: exynos: gs101: comply with the new cmu_misc clock names
  firmware: arm_ffa: Handle partitions setup failures
  firmware: arm_ffa: Use xa_insert() and check for result
  firmware: arm_ffa: Simplify ffa_partitions_cleanup()
  firmware: arm_ffa: Check xa_load() return value
  firmware: arm_ffa: Add missing rwlock_init() for the driver partition
  firmware: arm_ffa: Add missing rwlock_init() in ffa_setup_partitions()
  firmware: arm_scmi: Fix the clock protocol supported version
  firmware: arm_scmi: Fix the clock protocol version for v3.2
  firmware: arm_scmi: Use xa_insert() when saving raw queues
  firmware: arm_scmi: Use xa_insert() to store opps
  firmware: arm_scmi: Replace asm-generic/bug.h with linux/bug.h
  firmware: arm_scmi: Check mailbox/SMT channel for consistency
parents 48fa8ec6 1f4a994b
......@@ -45,8 +45,8 @@ spi1_gpio: spi1-gpio {
num-chipselects = <1>;
cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>;
tpmdev@0 {
compatible = "tcg,tpm_tis-spi";
tpm@0 {
compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
spi-max-frequency = <33000000>;
reg = <0>;
};
......
......@@ -80,8 +80,8 @@ spi_gpio: spi {
gpio-miso = <&gpio ASPEED_GPIO(R, 5) GPIO_ACTIVE_HIGH>;
num-chipselects = <1>;
tpmdev@0 {
compatible = "tcg,tpm_tis-spi";
tpm@0 {
compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
spi-max-frequency = <33000000>;
reg = <0>;
};
......
......@@ -456,7 +456,7 @@ &i2c1 {
status = "okay";
tpm: tpm@2e {
compatible = "tcg,tpm-tis-i2c";
compatible = "nuvoton,npct75x", "tcg,tpm-tis-i2c";
reg = <0x2e>;
};
};
......
......@@ -35,8 +35,8 @@ spi_gpio: spi {
gpio-mosi = <&gpio0 ASPEED_GPIO(X, 4) GPIO_ACTIVE_HIGH>;
gpio-miso = <&gpio0 ASPEED_GPIO(X, 5) GPIO_ACTIVE_HIGH>;
tpmdev@0 {
compatible = "tcg,tpm_tis-spi";
tpm@0 {
compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
spi-max-frequency = <33000000>;
reg = <0>;
};
......
......@@ -116,7 +116,7 @@ &ecspi1 {
tpm_tis: tpm@1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tpm>;
compatible = "tcg,tpm_tis-spi";
compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
reg = <1>;
spi-max-frequency = <20000000>;
interrupt-parent = <&gpio5>;
......
......@@ -130,7 +130,7 @@ &ecspi4 {
* TCG specification - Section 6.4.1 Clocking:
* TPM shall support a SPI clock frequency range of 10-24 MHz.
*/
st33htph: tpm-tis@0 {
st33htph: tpm@0 {
compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi";
reg = <0>;
spi-max-frequency = <24000000>;
......
......@@ -434,6 +434,7 @@ &exynos_usbphy {
};
&fimd {
samsung,invert-vclk;
status = "okay";
};
......
......@@ -217,7 +217,7 @@ &spi1 {
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
tpm_spi_tis@0 {
tpm@0 {
compatible = "tcg,tpm_tis-spi";
reg = <0>;
spi-max-frequency = <500000>;
......
......@@ -289,7 +289,7 @@ cmu_misc: clock-controller@10010000 {
#clock-cells = <1>;
clocks = <&cmu_top CLK_DOUT_CMU_MISC_BUS>,
<&cmu_top CLK_DOUT_CMU_MISC_SSS>;
clock-names = "dout_cmu_misc_bus", "dout_cmu_misc_sss";
clock-names = "bus", "sss";
};
watchdog_cl0: watchdog@10060000 {
......
......@@ -120,7 +120,7 @@ can0: can@0 {
};
tpm: tpm@1 {
compatible = "tcg,tpm_tis-spi";
compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
interrupt-parent = <&gpio2>;
pinctrl-names = "default";
......
......@@ -89,7 +89,7 @@ &ecspi2 {
status = "okay";
tpm@1 {
compatible = "tcg,tpm_tis-spi";
compatible = "atmel,attpm20p", "tcg,tpm_tis-spi";
reg = <0x1>;
spi-max-frequency = <36000000>;
};
......
......@@ -109,7 +109,7 @@ &ecspi2 {
status = "okay";
tpm@1 {
compatible = "tcg,tpm_tis-spi";
compatible = "atmel,attpm20p", "tcg,tpm_tis-spi";
reg = <0x1>;
spi-max-frequency = <36000000>;
};
......
......@@ -234,7 +234,7 @@ &ecspi2 {
status = "okay";
tpm: tpm@0 {
compatible = "infineon,slb9670";
compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
reg = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tpm>;
......
......@@ -103,7 +103,7 @@ &ecspi2 {
status = "okay";
tpm@1 {
compatible = "tcg,tpm_tis-spi";
compatible = "atmel,attpm20p", "tcg,tpm_tis-spi";
reg = <0x1>;
spi-max-frequency = <36000000>;
};
......
......@@ -115,7 +115,7 @@ &ecspi2 {
status = "okay";
tpm@1 {
compatible = "tcg,tpm_tis-spi";
compatible = "atmel,attpm20p", "tcg,tpm_tis-spi";
reg = <0x1>;
spi-max-frequency = <36000000>;
};
......
......@@ -196,7 +196,7 @@ &ecspi1 {
status = "okay";
tpm@0 {
compatible = "tcg,tpm_tis-spi";
compatible = "atmel,attpm20p", "tcg,tpm_tis-spi";
reg = <0x0>;
spi-max-frequency = <36000000>;
};
......
......@@ -65,7 +65,7 @@ &ecspi2 {
status = "okay";
tpm@0 {
compatible = "infineon,slb9670";
compatible = "infineon,slb9670", "tcg,tpm_tis-spi";
reg = <0>;
spi-max-frequency = <43000000>;
};
......
......@@ -888,7 +888,7 @@ &spi0 {
status = "okay";
cs-gpios = <&pio 86 GPIO_ACTIVE_LOW>;
cr50@0 {
tpm@0 {
compatible = "google,cr50";
reg = <0>;
spi-max-frequency = <1000000>;
......
......@@ -1402,7 +1402,7 @@ &spi5 {
pinctrl-names = "default";
pinctrl-0 = <&spi5_pins>;
cr50@0 {
tpm@0 {
compatible = "google,cr50";
reg = <0>;
interrupts-extended = <&pio 171 IRQ_TYPE_EDGE_RISING>;
......
......@@ -70,7 +70,7 @@ &cpu_alert1 {
&spi0 {
status = "okay";
cr50@0 {
tpm@0 {
compatible = "google,cr50";
reg = <0>;
interrupt-parent = <&gpio0>;
......
......@@ -706,7 +706,7 @@ &sound {
&spi2 {
status = "okay";
cr50@0 {
tpm@0 {
compatible = "google,cr50";
reg = <0>;
interrupt-parent = <&gpio1>;
......
......@@ -93,144 +93,160 @@ clint_mswi: interrupt-controller@7094000000 {
<&cpu63_intc 3>;
};
clint_mtimer0: timer@70ac000000 {
clint_mtimer0: timer@70ac004000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac000000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac004000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu0_intc 7>,
<&cpu1_intc 7>,
<&cpu2_intc 7>,
<&cpu3_intc 7>;
};
clint_mtimer1: timer@70ac010000 {
clint_mtimer1: timer@70ac014000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac010000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac014000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu4_intc 7>,
<&cpu5_intc 7>,
<&cpu6_intc 7>,
<&cpu7_intc 7>;
};
clint_mtimer2: timer@70ac020000 {
clint_mtimer2: timer@70ac024000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac020000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac024000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu8_intc 7>,
<&cpu9_intc 7>,
<&cpu10_intc 7>,
<&cpu11_intc 7>;
};
clint_mtimer3: timer@70ac030000 {
clint_mtimer3: timer@70ac034000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac030000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac034000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu12_intc 7>,
<&cpu13_intc 7>,
<&cpu14_intc 7>,
<&cpu15_intc 7>;
};
clint_mtimer4: timer@70ac040000 {
clint_mtimer4: timer@70ac044000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac040000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac044000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu16_intc 7>,
<&cpu17_intc 7>,
<&cpu18_intc 7>,
<&cpu19_intc 7>;
};
clint_mtimer5: timer@70ac050000 {
clint_mtimer5: timer@70ac054000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac050000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac054000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu20_intc 7>,
<&cpu21_intc 7>,
<&cpu22_intc 7>,
<&cpu23_intc 7>;
};
clint_mtimer6: timer@70ac060000 {
clint_mtimer6: timer@70ac064000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac060000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac064000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu24_intc 7>,
<&cpu25_intc 7>,
<&cpu26_intc 7>,
<&cpu27_intc 7>;
};
clint_mtimer7: timer@70ac070000 {
clint_mtimer7: timer@70ac074000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac070000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac074000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu28_intc 7>,
<&cpu29_intc 7>,
<&cpu30_intc 7>,
<&cpu31_intc 7>;
};
clint_mtimer8: timer@70ac080000 {
clint_mtimer8: timer@70ac084000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac080000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac084000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu32_intc 7>,
<&cpu33_intc 7>,
<&cpu34_intc 7>,
<&cpu35_intc 7>;
};
clint_mtimer9: timer@70ac090000 {
clint_mtimer9: timer@70ac094000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac090000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac094000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu36_intc 7>,
<&cpu37_intc 7>,
<&cpu38_intc 7>,
<&cpu39_intc 7>;
};
clint_mtimer10: timer@70ac0a0000 {
clint_mtimer10: timer@70ac0a4000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac0a0000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac0a4000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu40_intc 7>,
<&cpu41_intc 7>,
<&cpu42_intc 7>,
<&cpu43_intc 7>;
};
clint_mtimer11: timer@70ac0b0000 {
clint_mtimer11: timer@70ac0b4000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac0b0000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac0b4000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu44_intc 7>,
<&cpu45_intc 7>,
<&cpu46_intc 7>,
<&cpu47_intc 7>;
};
clint_mtimer12: timer@70ac0c0000 {
clint_mtimer12: timer@70ac0c4000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac0c0000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac0c4000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu48_intc 7>,
<&cpu49_intc 7>,
<&cpu50_intc 7>,
<&cpu51_intc 7>;
};
clint_mtimer13: timer@70ac0d0000 {
clint_mtimer13: timer@70ac0d4000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac0d0000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac0d4000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu52_intc 7>,
<&cpu53_intc 7>,
<&cpu54_intc 7>,
<&cpu55_intc 7>;
};
clint_mtimer14: timer@70ac0e0000 {
clint_mtimer14: timer@70ac0e4000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac0e0000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac0e4000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu56_intc 7>,
<&cpu57_intc 7>,
<&cpu58_intc 7>,
<&cpu59_intc 7>;
};
clint_mtimer15: timer@70ac0f0000 {
clint_mtimer15: timer@70ac0f4000 {
compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer";
reg = <0x00000070 0xac0f0000 0x00000000 0x00007ff8>;
reg = <0x00000070 0xac0f4000 0x00000000 0x0000c000>;
reg-names = "mtimecmp";
interrupts-extended = <&cpu60_intc 7>,
<&cpu61_intc 7>,
<&cpu62_intc 7>,
......
......@@ -107,12 +107,12 @@ struct ffa_drv_info {
struct work_struct notif_pcpu_work;
struct work_struct irq_work;
struct xarray partition_info;
unsigned int partition_count;
DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
struct mutex notify_lock; /* lock to protect notifier hashtable */
};
static struct ffa_drv_info *drv_info;
static void ffa_partitions_cleanup(void);
/*
* The driver must be able to support all the versions from the earliest
......@@ -733,6 +733,11 @@ static void __do_sched_recv_cb(u16 part_id, u16 vcpu, bool is_per_vcpu)
void *cb_data;
partition = xa_load(&drv_info->partition_info, part_id);
if (!partition) {
pr_err("%s: Invalid partition ID 0x%x\n", __func__, part_id);
return;
}
read_lock(&partition->rw_lock);
callback = partition->callback;
cb_data = partition->cb_data;
......@@ -915,6 +920,11 @@ static int ffa_sched_recv_cb_update(u16 part_id, ffa_sched_recv_cb callback,
return -EOPNOTSUPP;
partition = xa_load(&drv_info->partition_info, part_id);
if (!partition) {
pr_err("%s: Invalid partition ID 0x%x\n", __func__, part_id);
return -EINVAL;
}
write_lock(&partition->rw_lock);
cb_valid = !!partition->callback;
......@@ -1186,9 +1196,9 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
kfree(pbuf);
}
static void ffa_setup_partitions(void)
static int ffa_setup_partitions(void)
{
int count, idx;
int count, idx, ret;
uuid_t uuid;
struct ffa_device *ffa_dev;
struct ffa_dev_part_info *info;
......@@ -1197,7 +1207,7 @@ static void ffa_setup_partitions(void)
count = ffa_partition_probe(&uuid_null, &pbuf);
if (count <= 0) {
pr_info("%s: No partitions found, error %d\n", __func__, count);
return;
return -EINVAL;
}
xa_init(&drv_info->partition_info);
......@@ -1226,40 +1236,53 @@ static void ffa_setup_partitions(void)
ffa_device_unregister(ffa_dev);
continue;
}
xa_store(&drv_info->partition_info, tpbuf->id, info, GFP_KERNEL);
rwlock_init(&info->rw_lock);
ret = xa_insert(&drv_info->partition_info, tpbuf->id,
info, GFP_KERNEL);
if (ret) {
pr_err("%s: failed to save partition ID 0x%x - ret:%d\n",
__func__, tpbuf->id, ret);
ffa_device_unregister(ffa_dev);
kfree(info);
}
}
drv_info->partition_count = count;
kfree(pbuf);
/* Allocate for the host */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return;
xa_store(&drv_info->partition_info, drv_info->vm_id, info, GFP_KERNEL);
drv_info->partition_count++;
if (!info) {
pr_err("%s: failed to alloc Host partition ID 0x%x. Abort.\n",
__func__, drv_info->vm_id);
/* Already registered devices are freed on bus_exit */
ffa_partitions_cleanup();
return -ENOMEM;
}
rwlock_init(&info->rw_lock);
ret = xa_insert(&drv_info->partition_info, drv_info->vm_id,
info, GFP_KERNEL);
if (ret) {
pr_err("%s: failed to save Host partition ID 0x%x - ret:%d. Abort.\n",
__func__, drv_info->vm_id, ret);
kfree(info);
/* Already registered devices are freed on bus_exit */
ffa_partitions_cleanup();
}
return ret;
}
static void ffa_partitions_cleanup(void)
{
struct ffa_dev_part_info **info;
int idx, count = drv_info->partition_count;
if (!count)
return;
info = kcalloc(count, sizeof(*info), GFP_KERNEL);
if (!info)
return;
xa_extract(&drv_info->partition_info, (void **)info, 0, VM_ID_MASK,
count, XA_PRESENT);
struct ffa_dev_part_info *info;
unsigned long idx;
for (idx = 0; idx < count; idx++)
kfree(info[idx]);
kfree(info);
xa_for_each(&drv_info->partition_info, idx, info) {
xa_erase(&drv_info->partition_info, idx);
kfree(info);
}
drv_info->partition_count = 0;
xa_destroy(&drv_info->partition_info);
}
......@@ -1508,7 +1531,11 @@ static int __init ffa_init(void)
ffa_notifications_setup();
ffa_setup_partitions();
ret = ffa_setup_partitions();
if (ret) {
pr_err("failed to setup partitions\n");
goto cleanup_notifs;
}
ret = ffa_sched_recv_cb_update(drv_info->vm_id, ffa_self_notif_handle,
drv_info, true);
......@@ -1516,6 +1543,9 @@ static int __init ffa_init(void)
pr_info("Failed to register driver sched callback %d\n", ret);
return 0;
cleanup_notifs:
ffa_notifications_cleanup();
free_pages:
if (drv_info->tx_buffer)
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
......@@ -1535,7 +1565,6 @@ static void __exit ffa_exit(void)
ffa_rxtx_unmap(drv_info->vm_id);
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
xa_destroy(&drv_info->partition_info);
kfree(drv_info);
arm_ffa_bus_exit();
}
......
......@@ -13,7 +13,7 @@
#include "notify.h"
/* Updated only after ALL the mandatory features for that version are merged */
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20001
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20000
enum scmi_clock_protocol_cmd {
CLOCK_ATTRIBUTES = 0x3,
......@@ -954,8 +954,7 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
scmi_clock_describe_rates_get(ph, clkid, clk);
}
if (PROTOCOL_REV_MAJOR(version) >= 0x2 &&
PROTOCOL_REV_MINOR(version) >= 0x1) {
if (PROTOCOL_REV_MAJOR(version) >= 0x3) {
cinfo->clock_config_set = scmi_clock_config_set_v2;
cinfo->clock_config_get = scmi_clock_config_get_v2;
} else {
......
......@@ -314,6 +314,7 @@ void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem,
void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem);
bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
struct scmi_xfer *xfer);
bool shmem_channel_free(struct scmi_shared_mem __iomem *shmem);
/* declarations for message passing transports */
struct scmi_msg_payld;
......
......@@ -45,6 +45,20 @@ static void rx_callback(struct mbox_client *cl, void *m)
{
struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl);
/*
* An A2P IRQ is NOT valid when received while the platform still has
* the ownership of the channel, because the platform at first releases
* the SMT channel and then sends the completion interrupt.
*
* This addresses a possible race condition in which a spurious IRQ from
* a previous timed-out reply which arrived late could be wrongly
* associated with the next pending transaction.
*/
if (cl->knows_txdone && !shmem_channel_free(smbox->shmem)) {
dev_warn(smbox->cinfo->dev, "Ignoring spurious A2P IRQ !\n");
return;
}
scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem), NULL);
}
......
......@@ -350,8 +350,8 @@ process_response_opp(struct scmi_opp *opp, unsigned int loop_idx,
}
static inline void
process_response_opp_v4(struct perf_dom_info *dom, struct scmi_opp *opp,
unsigned int loop_idx,
process_response_opp_v4(struct device *dev, struct perf_dom_info *dom,
struct scmi_opp *opp, unsigned int loop_idx,
const struct scmi_msg_resp_perf_describe_levels_v4 *r)
{
opp->perf = le32_to_cpu(r->opp[loop_idx].perf_val);
......@@ -362,10 +362,23 @@ process_response_opp_v4(struct perf_dom_info *dom, struct scmi_opp *opp,
/* Note that PERF v4 reports always five 32-bit words */
opp->indicative_freq = le32_to_cpu(r->opp[loop_idx].indicative_freq);
if (dom->level_indexing_mode) {
int ret;
opp->level_index = le32_to_cpu(r->opp[loop_idx].level_index);
xa_store(&dom->opps_by_idx, opp->level_index, opp, GFP_KERNEL);
xa_store(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL);
ret = xa_insert(&dom->opps_by_idx, opp->level_index, opp,
GFP_KERNEL);
if (ret)
dev_warn(dev,
"Failed to add opps_by_idx at %d - ret:%d\n",
opp->level_index, ret);
ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL);
if (ret)
dev_warn(dev,
"Failed to add opps_by_lvl at %d - ret:%d\n",
opp->perf, ret);
hash_add(dom->opps_by_freq, &opp->hash, opp->indicative_freq);
}
}
......@@ -382,7 +395,7 @@ iter_perf_levels_process_response(const struct scmi_protocol_handle *ph,
if (PROTOCOL_REV_MAJOR(p->version) <= 0x3)
process_response_opp(opp, st->loop_idx, response);
else
process_response_opp_v4(p->perf_dom, opp, st->loop_idx,
process_response_opp_v4(ph->dev, p->perf_dom, opp, st->loop_idx,
response);
p->perf_dom->opp_count++;
......
......@@ -1111,7 +1111,6 @@ static int scmi_raw_mode_setup(struct scmi_raw_mode_info *raw,
int i;
for (i = 0; i < num_chans; i++) {
void *xret;
struct scmi_raw_queue *q;
q = scmi_raw_queue_init(raw);
......@@ -1120,13 +1119,12 @@ static int scmi_raw_mode_setup(struct scmi_raw_mode_info *raw,
goto err_xa;
}
xret = xa_store(&raw->chans_q, channels[i], q,
ret = xa_insert(&raw->chans_q, channels[i], q,
GFP_KERNEL);
if (xa_err(xret)) {
if (ret) {
dev_err(dev,
"Fail to allocate Raw queue 0x%02X\n",
channels[i]);
ret = xa_err(xret);
goto err_xa;
}
}
......@@ -1322,6 +1320,12 @@ void scmi_raw_message_report(void *r, struct scmi_xfer *xfer,
dev = raw->handle->dev;
q = scmi_raw_queue_select(raw, idx,
SCMI_XFER_IS_CHAN_SET(xfer) ? chan_id : 0);
if (!q) {
dev_warn(dev,
"RAW[%d] - NO queue for chan 0x%X. Dropping report.\n",
idx, chan_id);
return;
}
/*
* Grab the msg_q_lock upfront to avoid a possible race between
......
......@@ -10,7 +10,7 @@
#include <linux/processor.h>
#include <linux/types.h>
#include <asm-generic/bug.h>
#include <linux/bug.h>
#include "common.h"
......@@ -122,3 +122,9 @@ bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
(SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR |
SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
}
bool shmem_channel_free(struct scmi_shared_mem __iomem *shmem)
{
return (ioread32(&shmem->channel_status) &
SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment