soc: fixes for 7.1

The ff-a firmware driver gets 11 individual bugfixes for a number
 of issues with robustness to buggy firmware or client implementations.
 Another firmware fix address suspend to RAM via PSCI firmware.
 
 The final code change is for the old Arm Integrator reference
 platform that recently started exposing an old NULL pointer
 dereference bug.
 
 The MAINTAINERS file gets two updates, notably James Tai and Yu-Chun
 Lin are stepping up as co-maintainers for the Realtek platform.
 
 The remaining patches are all for devicetree files. Two of these
 are for riscv  boards, the rest are all for enesas Arm platforms,
 addressing build time checking issues as well as minor configuration
 problems.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmoOI3UACgkQmmx57+YA
 GNmfZRAAgTy6C1902MT6aysKlN1rZLAPN2izKjAUXTaH0tXzTs4N1Q9UqUSQrOtM
 INjWwfHuDw0oJOJozkN8jdmTW9s+4ebo1KM6vUoW21yLGprxiVmm/uG62Ycyt2cb
 tKA/SzoK1sg7ZnV2agmBNyXvEtQyx4mbfNCfv1l1DH+f4q26PZMR8s6kzfK8Kb4O
 e8oIRF/q773Ht7dRqT+NKb+qPMfG0IeLrcnRWY5qoHF/RIUDShO6W8uZEYisiXnY
 Z9e/eNbTyG/zIsqhr8qgwbdW9GXHkj0ztvwbwzC8PeXqsETl4LhXZkUaO/jvA2MH
 VihikFOFYhYZcna/6OQqPEyTKrCxGfuK4be9bYPrD3weEou3YR6+aHV8rpUPEsNq
 3C8iSYDflWwhsj571qy8sMwkYkvIcrIIdDZltKU20Q6p5pv6EeyUwN3RlUJDsXr/
 j6wnHm6DFF8WL0V8/Vv1lB/PjySkzOIFfjihq6VVPeo2EYhJjLmdxg/Z9MNbCY59
 E8Fl9xBqg6YJyZ+Why6v4vkFvNKJX1T35AhgHR58X5DsrGz3v9fvC//m9EENrKCz
 GbNFXC7i93+6/MnQh7SYFUEYaVcAM+3Z8N91qYVJxvgJ4BVURnelJKe5WVwZjjY4
 Ws981yptKHgHWaRHZbCCd9VXQKtnb+jU1Zjjx1uTVEOZtecM3Dw=
 =MpIJ
 -----END PGP SIGNATURE-----

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

Pull SoC fixes from Arnd Bergmann:

 - The ff-a firmware driver gets 11 individual bugfixes for a number of
   issues with robustness to buggy firmware or client implementations.
   Another firmware fix address suspend to RAM via PSCI firmware.

 - The final code change is for the old Arm Integrator reference
   platform that recently started exposing an old NULL pointer
   dereference bug.

 - The MAINTAINERS file gets two updates, notably James Tai and Yu-Chun
   Lin are stepping up as co-maintainers for the Realtek platform.

 - The remaining patches are all for devicetree files. Two of these are
   for riscv boards, the rest are all for enesas Arm platforms,
   addressing build time checking issues as well as minor configuration
   problems.

* tag 'soc-fixes-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (30 commits)
  firmware: psci: Set pm_set_resume/suspend_via_firmware() for SYSTEM_SUSPEND
  ARM: realtek: MAINTAINERS: Include pin controller drivers
  MAINTAINERS: Add maintainers for ARM/REALTEK ARCHITECTURE
  ARM: integrator: Fix early initialization
  firmware: arm_ffa: Fix sched-recv callback partition lookup
  firmware: arm_ffa: Snapshot notifier callbacks under lock
  firmware: arm_ffa: Align RxTx buffer size before mapping
  firmware: arm_ffa: Validate framework notification message layout
  firmware: arm_ffa: Keep framework RX release under lock
  firmware: arm_ffa: Bound PARTITION_INFO_GET_REGS copies
  firmware: arm_ffa: Unregister bus notifier on teardown for FF-A v1.0
  firmware: arm_ffa: Fix per-vcpu self notifications handling in workqueue
  firmware: arm_ffa: Avoid collapsing NPI work from different CPUs
  firmware: arm_ffa: Skip free_pages on RX buffer alloc failure
  firmware: arm_ffa: Check for NULL FF-A ID table while driver registration
  riscv: dts: microchip: fix icicle i2c pinctrl configuration
  riscv: dts: starfive: jh7110: Drop CAMSS node
  arm64: dts: renesas: r9a09g056: Add #mux-state-cells to usb20phyrst
  arm64: dts: renesas: r9a09g057: Add #mux-state-cells to usb2{0,1}phyrst
  ARM: dts: renesas: rskrza1: Drop superfluous cells
  ...
This commit is contained in:
Linus Torvalds 2026-05-21 08:43:26 -07:00
commit dd3802fc4f
23 changed files with 184 additions and 132 deletions

View File

@ -3367,7 +3367,9 @@ F: drivers/irqchip/irq-rda-intc.c
F: drivers/tty/serial/rda-uart.c
ARM/REALTEK ARCHITECTURE
M: Andreas Färber <afaerber@suse.de>
M: James Tai <james.tai@realtek.com>
M: Yu-Chun Lin <eleanor.lin@realtek.com>
R: Andreas Färber <afaerber@suse.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-realtek-soc@lists.infradead.org (moderated for non-subscribers)
S: Maintained
@ -3375,6 +3377,7 @@ F: Documentation/devicetree/bindings/arm/realtek.yaml
F: arch/arm/boot/dts/realtek/
F: arch/arm/mach-realtek/
F: arch/arm64/boot/dts/realtek/
F: drivers/pinctrl/realtek/
ARM/RISC-V/RENESAS ARCHITECTURE
M: Geert Uytterhoeven <geert+renesas@glider.be>

View File

@ -34,9 +34,6 @@ flash@18000000 {
clocks = <&mstp9_clks R7S72100_CLK_SPIBSC0>;
power-domains = <&cpg_clocks>;
#address-cells = <1>;
#size-cells = <1>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;

View File

@ -36,8 +36,6 @@ flash@18000000 {
power-domains = <&cpg_clocks>;
bank-width = <4>;
device-width = <1>;
#address-cells = <1>;
#size-cells = <1>;
partitions {
compatible = "fixed-partitions";

View File

@ -37,7 +37,7 @@ b_clk: b {
clock-div = <3>;
};
bsc: bus {
bsc: bus@0 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;

View File

@ -40,7 +40,7 @@ aliases {
spi2 = &hspi2;
};
lbsc: bus {
lbsc: bus@0 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;

View File

@ -704,7 +704,7 @@ R8A7779_CLK_MMC1 R8A7779_CLK_MMC0
};
};
lbsc: bus {
lbsc: bus@0 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;

View File

@ -86,7 +86,7 @@ extal_clk: extal {
bootph-all;
};
lbsc: bus {
lbsc: bus@0 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;

View File

@ -86,14 +86,6 @@ static u64 notrace intcp_read_sched_clock(void)
return val;
}
static void __init intcp_init_early(void)
{
cm_map = syscon_regmap_lookup_by_compatible("arm,core-module-integrator");
if (IS_ERR(cm_map))
return;
sched_clock_register(intcp_read_sched_clock, 32, 24000000);
}
static void __init intcp_init_irq_of(void)
{
cm_init();
@ -119,6 +111,10 @@ static void __init intcp_init_of(void)
{
struct device_node *cpcon;
cm_map = syscon_regmap_lookup_by_compatible("arm,core-module-integrator");
if (!IS_ERR(cm_map))
sched_clock_register(intcp_read_sched_clock, 32, 24000000);
cpcon = of_find_matching_node(NULL, intcp_syscon_match);
if (!cpcon)
return;
@ -138,7 +134,6 @@ static const char * intcp_dt_board_compat[] = {
DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
.reserve = integrator_reserve,
.map_io = intcp_map_io,
.init_early = intcp_init_early,
.init_irq = intcp_init_irq_of,
.init_machine = intcp_init_of,
.dt_compat = intcp_dt_board_compat,

View File

@ -27,7 +27,12 @@ &lvds1 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
lvds1_out: endpoint {
remote-endpoint = <&panel_in>;
};

View File

@ -699,7 +699,7 @@ scif0: serial@c0700000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc0700000 0 0x40>;
interrupts = <GIC_ESPI 10 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
status = "disabled";
};
@ -709,7 +709,7 @@ scif1: serial@c0704000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc0704000 0 0x40>;
interrupts = <GIC_ESPI 11 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
status = "disabled";
};
@ -719,7 +719,7 @@ scif3: serial@c0708000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc0708000 0 0x40>;
interrupts = <GIC_ESPI 12 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
status = "disabled";
};
@ -729,7 +729,7 @@ scif4: serial@c070c000 {
"renesas,rcar-gen5-scif", "renesas,scif";
reg = <0 0xc070c000 0 0x40>;
interrupts = <GIC_ESPI 13 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
status = "disabled";
};

View File

@ -1327,6 +1327,7 @@ usb20phyrst: usb20phy-reset@15830000 {
resets = <&cpg 0xaf>;
power-domains = <&cpg>;
#reset-cells = <0>;
#mux-state-cells = <1>;
status = "disabled";
};

View File

@ -1345,6 +1345,7 @@ usb20phyrst: usb20phy-reset@15830000 {
resets = <&cpg 0xaf>;
power-domains = <&cpg>;
#reset-cells = <0>;
#mux-state-cells = <1>;
status = "disabled";
};
@ -1355,6 +1356,7 @@ usb21phyrst: usb21phy-reset@15840000 {
resets = <&cpg 0xaf>;
power-domains = <&cpg>;
#reset-cells = <0>;
#mux-state-cells = <1>;
status = "disabled";
};

View File

@ -46,7 +46,12 @@ &csi2 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
csi2_in: endpoint {
clock-lanes = <0>;
data-lanes = <1 2>;

View File

@ -26,7 +26,12 @@ &du {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
du_out_rgb: endpoint {
remote-endpoint = <&adv7513_in>;
};

View File

@ -27,7 +27,12 @@ &lvds0 {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
reg = <1>;
lvds0_out: endpoint {
remote-endpoint = <&panel_in>;
};

View File

@ -101,16 +101,6 @@ &ccc_nw {
status = "okay";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_fabric>;
};
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_mssio>;
};
&mmuart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_fabric>;

View File

@ -14,6 +14,16 @@ / {
"microchip,mpfs";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_fabric>;
};
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_mssio>;
};
&syscontroller {
microchip,bitstream-flash = <&sys_ctrl_flash>;
};

View File

@ -11,3 +11,22 @@ / {
"microchip,mpfs-icicle-kit",
"microchip,mpfs";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_fabric>;
};
/*
* Due to silicon errata, routing via MSS IOs doesn't work on ES devices.
* Instead, i2c1, appearing on B1/C1, which are normally MSS IOs, is routed
* via the fabric and back to B1/C1 via "fabric-test" functionality.
* This is done silently by Libero, so the iomux0 setting for i2c1 has to
* be fabric IO, despite tooling etc saying that MSS IOs are used.
*
* See Section 3.3 of https://ww1.microchip.com/downloads/aemDocuments/documents/FPGA/ProductDocuments/Errata/polarfiresoc/microsemi_polarfire_soc_fpga_egineering_samples_errata_er0219_v1.pdf
*/
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_fabric>;
};

View File

@ -135,29 +135,6 @@ &tdm_ext {
clock-frequency = <49152000>;
};
&camss {
assigned-clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>,
<&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>;
assigned-clock-rates = <49500000>, <198000000>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
};
port@1 {
reg = <1>;
camss_from_csi2rx: endpoint {
remote-endpoint = <&csi2rx_to_camss>;
};
};
};
};
&csi2rx {
assigned-clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>;
assigned-clock-rates = <297000000>;
@ -175,9 +152,7 @@ port@0 {
port@1 {
reg = <1>;
csi2rx_to_camss: endpoint {
remote-endpoint = <&camss_from_csi2rx>;
};
/* remote CAMSS endpoint */
};
};
};

View File

@ -1199,34 +1199,6 @@ csi_phy: phy@19820000 {
#phy-cells = <0>;
};
camss: isp@19840000 {
compatible = "starfive,jh7110-camss";
reg = <0x0 0x19840000 0x0 0x10000>,
<0x0 0x19870000 0x0 0x30000>;
reg-names = "syscon", "isp";
clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>,
<&ispcrg JH7110_ISPCLK_ISPV2_TOP_WRAPPER_C>,
<&ispcrg JH7110_ISPCLK_DVP_INV>,
<&ispcrg JH7110_ISPCLK_VIN_P_AXI_WR>,
<&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>,
<&syscrg JH7110_SYSCLK_ISP_TOP_CORE>,
<&syscrg JH7110_SYSCLK_ISP_TOP_AXI>;
clock-names = "apb_func", "wrapper_clk_c", "dvp_inv",
"axiwr", "mipi_rx0_pxl", "ispcore_2x",
"isp_axi";
resets = <&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_P>,
<&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_C>,
<&ispcrg JH7110_ISPRST_VIN_P_AXI_RD>,
<&ispcrg JH7110_ISPRST_VIN_P_AXI_WR>,
<&syscrg JH7110_SYSRST_ISP_TOP>,
<&syscrg JH7110_SYSRST_ISP_TOP_AXI>;
reset-names = "wrapper_p", "wrapper_c", "axird",
"axiwr", "isp_top_n", "isp_top_axi";
power-domains = <&pwrc JH7110_PD_ISP>;
interrupts = <92>, <87>, <90>, <88>;
status = "disabled";
};
voutcrg: clock-controller@295c0000 {
compatible = "starfive,jh7110-voutcrg";
reg = <0x0 0x295c0000 0x0 0x10000>;

View File

@ -26,6 +26,8 @@ static int ffa_device_match(struct device *dev, const struct device_driver *drv)
id_table = to_ffa_driver(drv)->id_table;
ffa_dev = to_ffa_dev(dev);
if (!id_table)
return 0;
while (!uuid_is_null(&id_table->uuid)) {
/*
@ -123,7 +125,7 @@ int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
{
int ret;
if (!driver->probe)
if (!driver->probe || !driver->id_table)
return -EINVAL;
driver->driver.bus = &ffa_bus_type;

View File

@ -87,6 +87,7 @@ static inline int ffa_to_linux_errno(int errno)
struct ffa_pcpu_irq {
struct ffa_drv_info *info;
struct work_struct notif_pcpu_work;
};
struct ffa_drv_info {
@ -100,13 +101,13 @@ struct ffa_drv_info {
bool mem_ops_native;
bool msg_direct_req2_supp;
bool bitmap_created;
bool bus_notifier_registered;
bool notif_enabled;
unsigned int sched_recv_irq;
unsigned int notif_pend_irq;
unsigned int cpuhp_state;
struct ffa_pcpu_irq __percpu *irq_pcpu;
struct workqueue_struct *notif_pcpu_wq;
struct work_struct notif_pcpu_work;
struct work_struct sched_recv_irq_work;
struct xarray partition_info;
DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
@ -322,6 +323,12 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
#define PART_INFO_ID_MASK GENMASK(15, 0)
#define PART_INFO_EXEC_CXT_MASK GENMASK(31, 16)
#define PART_INFO_PROPS_MASK GENMASK(63, 32)
#define FFA_PART_INFO_GET_REGS_FIRST_REG 3
#define FFA_PART_INFO_GET_REGS_REGS_PER_DESC 3
#define FFA_PART_INFO_GET_REGS_MAX_DESC \
(((sizeof(ffa_value_t) / sizeof_field(ffa_value_t, a0)) - \
FFA_PART_INFO_GET_REGS_FIRST_REG) / \
FFA_PART_INFO_GET_REGS_REGS_PER_DESC)
#define PART_INFO_ID(x) ((u16)(FIELD_GET(PART_INFO_ID_MASK, (x))))
#define PART_INFO_EXEC_CXT(x) ((u16)(FIELD_GET(PART_INFO_EXEC_CXT_MASK, (x))))
#define PART_INFO_PROPERTIES(x) ((u32)(FIELD_GET(PART_INFO_PROPS_MASK, (x))))
@ -329,15 +336,13 @@ static int
__ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
struct ffa_partition_info *buffer, int num_parts)
{
u16 buf_sz, start_idx, cur_idx, count = 0, prev_idx = 0, tag = 0;
u16 buf_sz, start_idx = 0, cur_idx, count = 0, tag = 0;
struct ffa_partition_info *buf = buffer;
ffa_value_t partition_info;
do {
__le64 *regs;
int idx;
start_idx = prev_idx ? prev_idx + 1 : 0;
int idx, nr_desc, buf_idx;
invoke_ffa_fn((ffa_value_t){
.a0 = FFA_PARTITION_INFO_GET_REGS,
@ -353,15 +358,28 @@ __ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
count = PARTITION_COUNT(partition_info.a2);
if (!buffer || !num_parts) /* count only */
return count;
if (count > num_parts)
return -EINVAL;
cur_idx = CURRENT_INDEX(partition_info.a2);
if (cur_idx < start_idx || cur_idx >= count)
return -EINVAL;
nr_desc = cur_idx - start_idx + 1;
if (nr_desc > FFA_PART_INFO_GET_REGS_MAX_DESC)
return -EINVAL;
buf_idx = buf - buffer;
if (buf_idx + nr_desc > num_parts)
return -EINVAL;
tag = UUID_INFO_TAG(partition_info.a2);
buf_sz = PARTITION_INFO_SZ(partition_info.a2);
if (buf_sz > sizeof(*buffer))
buf_sz = sizeof(*buffer);
regs = (void *)&partition_info.a3;
for (idx = 0; idx < cur_idx - start_idx + 1; idx++, buf++) {
for (idx = 0; idx < nr_desc; idx++, buf++) {
union {
uuid_t uuid;
u64 regs[2];
@ -379,7 +397,7 @@ __ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
uuid_copy(&buf->uuid, &uuid_regs.uuid);
regs += 3;
}
prev_idx = cur_idx;
start_idx = cur_idx + 1;
} while (cur_idx < (count - 1));
@ -1189,7 +1207,7 @@ static int
ffa_sched_recv_cb_update(struct ffa_device *dev, ffa_sched_recv_cb callback,
void *cb_data, bool is_registration)
{
struct ffa_dev_part_info *partition = NULL, *tmp;
struct ffa_dev_part_info *partition = NULL;
struct list_head *phead;
bool cb_valid;
@ -1202,11 +1220,11 @@ ffa_sched_recv_cb_update(struct ffa_device *dev, ffa_sched_recv_cb callback,
return -EINVAL;
}
list_for_each_entry_safe(partition, tmp, phead, node)
list_for_each_entry(partition, phead, node)
if (partition->dev == dev)
break;
if (!partition) {
if (&partition->node == phead) {
pr_err("%s: No such partition ID 0x%x\n", __func__, dev->vm_id);
return -EINVAL;
}
@ -1445,20 +1463,25 @@ static int ffa_notify_send(struct ffa_device *dev, int notify_id,
static void handle_notif_callbacks(u64 bitmap, enum notify_type type)
{
ffa_notifier_cb cb;
void *cb_data;
int notify_id;
struct notifier_cb_info *cb_info = NULL;
for (notify_id = 0; notify_id <= FFA_MAX_NOTIFICATIONS && bitmap;
notify_id++, bitmap >>= 1) {
if (!(bitmap & 1))
continue;
read_lock(&drv_info->notify_lock);
cb_info = notifier_hnode_get_by_type(notify_id, type);
read_unlock(&drv_info->notify_lock);
scoped_guard(read_lock, &drv_info->notify_lock) {
struct notifier_cb_info *cb_info;
if (cb_info && cb_info->cb)
cb_info->cb(notify_id, cb_info->cb_data);
cb_info = notifier_hnode_get_by_type(notify_id, type);
cb = cb_info ? cb_info->cb : NULL;
cb_data = cb_info ? cb_info->cb_data : NULL;
}
if (cb)
cb(notify_id, cb_data);
}
}
@ -1466,39 +1489,56 @@ static void handle_fwk_notif_callbacks(u32 bitmap)
{
void *buf;
uuid_t uuid;
void *fwk_cb_data;
int notify_id = 0, target;
ffa_fwk_notifier_cb fwk_cb;
struct ffa_indirect_msg_hdr *msg;
struct notifier_cb_info *cb_info = NULL;
size_t min_offset = offsetof(struct ffa_indirect_msg_hdr, uuid);
/* Only one framework notification defined and supported for now */
if (!(bitmap & FRAMEWORK_NOTIFY_RX_BUFFER_FULL))
return;
mutex_lock(&drv_info->rx_lock);
scoped_guard(mutex, &drv_info->rx_lock) {
u32 offset, size;
msg = drv_info->rx_buffer;
buf = kmemdup((void *)msg + msg->offset, msg->size, GFP_KERNEL);
if (!buf) {
mutex_unlock(&drv_info->rx_lock);
return;
msg = drv_info->rx_buffer;
offset = msg->offset;
size = msg->size;
if (!size || (offset != min_offset && offset < sizeof(*msg)) ||
offset > drv_info->rxtx_bufsz ||
size > drv_info->rxtx_bufsz - offset) {
pr_err("invalid framework notification message\n");
ffa_rx_release();
return;
}
buf = kmemdup((void *)msg + offset, size, GFP_KERNEL);
if (!buf) {
ffa_rx_release();
return;
}
target = SENDER_ID(msg->send_recv_id);
if (offset >= sizeof(*msg))
uuid_copy(&uuid, &msg->uuid);
else
uuid_copy(&uuid, &uuid_null);
ffa_rx_release();
}
target = SENDER_ID(msg->send_recv_id);
if (msg->offset >= sizeof(*msg))
uuid_copy(&uuid, &msg->uuid);
else
uuid_copy(&uuid, &uuid_null);
scoped_guard(read_lock, &drv_info->notify_lock) {
struct notifier_cb_info *cb_info;
mutex_unlock(&drv_info->rx_lock);
cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, target,
&uuid);
fwk_cb = cb_info ? cb_info->fwk_cb : NULL;
fwk_cb_data = cb_info ? cb_info->cb_data : NULL;
}
ffa_rx_release();
read_lock(&drv_info->notify_lock);
cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, target, &uuid);
read_unlock(&drv_info->notify_lock);
if (cb_info && cb_info->fwk_cb)
cb_info->fwk_cb(notify_id, cb_info->cb_data, buf);
if (fwk_cb)
fwk_cb(notify_id, fwk_cb_data, buf);
kfree(buf);
}
@ -1539,10 +1579,11 @@ ffa_self_notif_handle(u16 vcpu, bool is_per_vcpu, void *cb_data)
static void notif_pcpu_irq_work_fn(struct work_struct *work)
{
struct ffa_drv_info *info = container_of(work, struct ffa_drv_info,
struct ffa_pcpu_irq *pcpu = container_of(work, struct ffa_pcpu_irq,
notif_pcpu_work);
struct ffa_drv_info *info = pcpu->info;
ffa_self_notif_handle(smp_processor_id(), true, info);
notif_get_and_handle(info);
}
static const struct ffa_info_ops ffa_drv_info_ops = {
@ -1629,6 +1670,15 @@ static struct notifier_block ffa_bus_nb = {
.notifier_call = ffa_bus_notifier,
};
static void ffa_bus_notifier_unregister(void)
{
if (!drv_info->bus_notifier_registered)
return;
bus_unregister_notifier(&ffa_bus_type, &ffa_bus_nb);
drv_info->bus_notifier_registered = false;
}
static int ffa_xa_add_partition_info(struct ffa_device *dev)
{
struct ffa_dev_part_info *info;
@ -1712,6 +1762,8 @@ static void ffa_partitions_cleanup(void)
struct list_head *phead;
unsigned long idx;
ffa_bus_notifier_unregister();
/* Clean up/free all registered devices */
ffa_devices_unregister();
@ -1739,11 +1791,14 @@ static int ffa_setup_partitions(void)
ret = bus_register_notifier(&ffa_bus_type, &ffa_bus_nb);
if (ret)
pr_err("Failed to register FF-A bus notifiers\n");
else
drv_info->bus_notifier_registered = true;
}
count = ffa_partition_probe(&uuid_null, &pbuf);
if (count <= 0) {
pr_info("%s: No partitions found, error %d\n", __func__, count);
ffa_bus_notifier_unregister();
return -EINVAL;
}
@ -1811,7 +1866,7 @@ static irqreturn_t notif_pend_irq_handler(int irq, void *irq_data)
struct ffa_drv_info *info = pcpu->info;
queue_work_on(smp_processor_id(), info->notif_pcpu_wq,
&info->notif_pcpu_work);
&pcpu->notif_pcpu_work);
return IRQ_HANDLED;
}
@ -1928,8 +1983,11 @@ static int ffa_init_pcpu_irq(void)
if (!irq_pcpu)
return -ENOMEM;
for_each_present_cpu(cpu)
for_each_present_cpu(cpu) {
per_cpu_ptr(irq_pcpu, cpu)->info = drv_info;
INIT_WORK(&per_cpu_ptr(irq_pcpu, cpu)->notif_pcpu_work,
notif_pcpu_irq_work_fn);
}
drv_info->irq_pcpu = irq_pcpu;
@ -1958,7 +2016,6 @@ static int ffa_init_pcpu_irq(void)
}
INIT_WORK(&drv_info->sched_recv_irq_work, ffa_sched_recv_irq_work_fn);
INIT_WORK(&drv_info->notif_pcpu_work, notif_pcpu_irq_work_fn);
drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
if (!drv_info->notif_pcpu_wq)
return -EINVAL;
@ -2063,11 +2120,12 @@ static int __init ffa_init(void)
rxtx_bufsz = SZ_4K;
}
rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz);
drv_info->rxtx_bufsz = rxtx_bufsz;
drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
if (!drv_info->rx_buffer) {
ret = -ENOMEM;
goto free_pages;
goto free_drv_info;
}
drv_info->tx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
@ -2078,7 +2136,7 @@ static int __init ffa_init(void)
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
virt_to_phys(drv_info->rx_buffer),
PAGE_ALIGN(rxtx_bufsz) / FFA_PAGE_SIZE);
rxtx_bufsz / FFA_PAGE_SIZE);
if (ret) {
pr_err("failed to register FFA RxTx buffers\n");
goto free_pages;

View File

@ -539,12 +539,22 @@ static int psci_system_suspend(unsigned long unused)
static int psci_system_suspend_enter(suspend_state_t state)
{
pm_set_resume_via_firmware();
return cpu_suspend(0, psci_system_suspend);
}
static int psci_system_suspend_begin(suspend_state_t state)
{
pm_set_suspend_via_firmware();
return 0;
}
static const struct platform_suspend_ops psci_suspend_ops = {
.valid = suspend_valid_only_mem,
.enter = psci_system_suspend_enter,
.begin = psci_system_suspend_begin,
};
static void __init psci_init_system_reset2(void)