Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'scmi-smccc-fixes-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes

Arm SCMI and SMCCC fixes for v6.5

Set of fixes addressing issues:
1. Possible use of uninitialised results structure in the SMCCC SOC_ID
driver if the driver fails to complete the initialisation
2. Missed signed error return value handling from simple_write_to_buffer()
used in scmi_dbg_raw_mode_common_write()
3. The OF node reference obtained is not dropped if node is incompatible
with "arm,scmi-shmem" in the mailbox as well as SMC transport channel
setup
4. The possibility of a late response to an in-flight pending transaction
that could end up triggering the interrupt handler after the SCMI core
has cleaned up the transport channel as part of core driver remove

* tag 'scmi-smccc-fixes-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
firmware: arm_scmi: Fix chan_free cleanup on SMC
firmware: arm_scmi: Drop OF node reference in the transport channel setup
firmware: arm_scmi: Fix signed error return values handling
firmware: smccc: Fix use of uninitialised results structure

Link: https://lore.kernel.org/r/20230721114052.3371923-1-sudeep.holla@arm.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+23 -12
+3 -1
drivers/firmware/arm_scmi/mailbox.c
··· 166 166 return -ENOMEM; 167 167 168 168 shmem = of_parse_phandle(cdev->of_node, "shmem", idx); 169 - if (!of_device_is_compatible(shmem, "arm,scmi-shmem")) 169 + if (!of_device_is_compatible(shmem, "arm,scmi-shmem")) { 170 + of_node_put(shmem); 170 171 return -ENXIO; 172 + } 171 173 172 174 ret = of_address_to_resource(shmem, 0, &res); 173 175 of_node_put(shmem);
+4 -1
drivers/firmware/arm_scmi/raw_mode.c
··· 818 818 * before sending it with a single RAW xfer. 819 819 */ 820 820 if (rd->tx_size < rd->tx_req_size) { 821 - size_t cnt; 821 + ssize_t cnt; 822 822 823 823 cnt = simple_write_to_buffer(rd->tx.buf, rd->tx.len, ppos, 824 824 buf, count); 825 + if (cnt < 0) 826 + return cnt; 827 + 825 828 rd->tx_size += cnt; 826 829 if (cnt < count) 827 830 return cnt;
+14 -7
drivers/firmware/arm_scmi/smc.c
··· 40 40 /** 41 41 * struct scmi_smc - Structure representing a SCMI smc transport 42 42 * 43 + * @irq: An optional IRQ for completion 43 44 * @cinfo: SCMI channel info 44 45 * @shmem: Transmit/Receive shared memory area 45 46 * @shmem_lock: Lock to protect access to Tx/Rx shared memory area. ··· 53 52 */ 54 53 55 54 struct scmi_smc { 55 + int irq; 56 56 struct scmi_chan_info *cinfo; 57 57 struct scmi_shared_mem __iomem *shmem; 58 58 /* Protect access to shmem area */ ··· 129 127 struct resource res; 130 128 struct device_node *np; 131 129 u32 func_id; 132 - int ret, irq; 130 + int ret; 133 131 134 132 if (!tx) 135 133 return -ENODEV; ··· 139 137 return -ENOMEM; 140 138 141 139 np = of_parse_phandle(cdev->of_node, "shmem", 0); 142 - if (!of_device_is_compatible(np, "arm,scmi-shmem")) 140 + if (!of_device_is_compatible(np, "arm,scmi-shmem")) { 141 + of_node_put(np); 143 142 return -ENXIO; 143 + } 144 144 145 145 ret = of_address_to_resource(np, 0, &res); 146 146 of_node_put(np); ··· 171 167 * completion of a message is signaled by an interrupt rather than by 172 168 * the return of the SMC call. 173 169 */ 174 - irq = of_irq_get_byname(cdev->of_node, "a2p"); 175 - if (irq > 0) { 176 - ret = devm_request_irq(dev, irq, smc_msg_done_isr, 177 - IRQF_NO_SUSPEND, 178 - dev_name(dev), scmi_info); 170 + scmi_info->irq = of_irq_get_byname(cdev->of_node, "a2p"); 171 + if (scmi_info->irq > 0) { 172 + ret = request_irq(scmi_info->irq, smc_msg_done_isr, 173 + IRQF_NO_SUSPEND, dev_name(dev), scmi_info); 179 174 if (ret) { 180 175 dev_err(dev, "failed to setup SCMI smc irq\n"); 181 176 return ret; ··· 195 192 { 196 193 struct scmi_chan_info *cinfo = p; 197 194 struct scmi_smc *scmi_info = cinfo->transport_info; 195 + 196 + /* Ignore any possible further reception on the IRQ path */ 197 + if (scmi_info->irq > 0) 198 + free_irq(scmi_info->irq, scmi_info); 198 199 199 200 cinfo->transport_info = NULL; 200 201 scmi_info->cinfo = NULL;
+2 -3
drivers/firmware/smccc/soc_id.c
··· 34 34 35 35 static int __init smccc_soc_init(void) 36 36 { 37 - struct arm_smccc_res res; 38 37 int soc_id_rev, soc_id_version; 39 38 static char soc_id_str[20], soc_id_rev_str[12]; 40 39 static char soc_id_jep106_id_str[12]; ··· 48 49 } 49 50 50 51 if (soc_id_version < 0) { 51 - pr_err("ARCH_SOC_ID(0) returned error: %lx\n", res.a0); 52 + pr_err("Invalid SoC Version: %x\n", soc_id_version); 52 53 return -EINVAL; 53 54 } 54 55 55 56 soc_id_rev = arm_smccc_get_soc_id_revision(); 56 57 if (soc_id_rev < 0) { 57 - pr_err("ARCH_SOC_ID(1) returned error: %lx\n", res.a0); 58 + pr_err("Invalid SoC Revision: %x\n", soc_id_rev); 58 59 return -EINVAL; 59 60 } 60 61