diff options
| author | Mark Brown <broonie@kernel.org> | 2025-11-26 22:56:01 +0000 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2025-11-26 22:56:01 +0000 |
| commit | 5d0cad409099798462d8a46756be537730bd8a22 (patch) | |
| tree | 76b1d8dd3439e966e69a266144330ce8cfa9a124 /drivers | |
| parent | 994a0b2eb605144871a85fac29a2c4bdbac07131 (diff) | |
| parent | 3a03de362975398b39d4c6df7325ccb982026a8f (diff) | |
ASoC: stm32: sai: fix device and OF node leaks on
Merge series from Johan Hovold <johan@kernel.org>:
This series fixes device and OF node reference leaks during probe and
a clock prepare imbalance on probe failures.
Included is a related cleanup of an error path.
Diffstat (limited to 'drivers')
106 files changed, 712 insertions, 370 deletions
diff --git a/drivers/acpi/apei/einj-core.c b/drivers/acpi/apei/einj-core.c index 3c87953dbd19..305c240a303f 100644 --- a/drivers/acpi/apei/einj-core.c +++ b/drivers/acpi/apei/einj-core.c @@ -182,6 +182,7 @@ bool einj_initialized __ro_after_init; static void __iomem *einj_param; static u32 v5param_size; +static u32 v66param_size; static bool is_v2; static void einj_exec_ctx_init(struct apei_exec_context *ctx) @@ -283,6 +284,24 @@ static void check_vendor_extension(u64 paddr, acpi_os_unmap_iomem(p, sizeof(v)); } +static u32 einjv2_init(struct einjv2_extension_struct *e) +{ + if (e->revision != 1) { + pr_info("Unknown v2 extension revision %u\n", e->revision); + return 0; + } + if (e->length < sizeof(*e) || e->length > PAGE_SIZE) { + pr_info(FW_BUG "Bad1 v2 extension length %u\n", e->length); + return 0; + } + if ((e->length - sizeof(*e)) % sizeof(e->component_arr[0])) { + pr_info(FW_BUG "Bad2 v2 extension length %u\n", e->length); + return 0; + } + + return (e->length - sizeof(*e)) / sizeof(e->component_arr[0]); +} + static void __iomem *einj_get_parameter_address(void) { int i; @@ -310,28 +329,21 @@ static void __iomem *einj_get_parameter_address(void) v5param_size = sizeof(v5param); p = acpi_os_map_iomem(pa_v5, sizeof(*p)); if (p) { - int offset, len; - memcpy_fromio(&v5param, p, v5param_size); acpi5 = 1; check_vendor_extension(pa_v5, &v5param); - if (is_v2 && available_error_type & ACPI65_EINJV2_SUPP) { - len = v5param.einjv2_struct.length; - offset = offsetof(struct einjv2_extension_struct, component_arr); - max_nr_components = (len - offset) / - sizeof(v5param.einjv2_struct.component_arr[0]); - /* - * The first call to acpi_os_map_iomem above does not include the - * component array, instead it is used to read and calculate maximum - * number of components supported by the system. Below, the mapping - * is expanded to include the component array. - */ + if (available_error_type & ACPI65_EINJV2_SUPP) { + struct einjv2_extension_struct *e; + + e = &v5param.einjv2_struct; + max_nr_components = einjv2_init(e); + + /* remap including einjv2_extension_struct */ acpi_os_unmap_iomem(p, v5param_size); - offset = offsetof(struct set_error_type_with_address, einjv2_struct); - v5param_size = offset + struct_size(&v5param.einjv2_struct, - component_arr, max_nr_components); - p = acpi_os_map_iomem(pa_v5, v5param_size); + v66param_size = v5param_size - sizeof(*e) + e->length; + p = acpi_os_map_iomem(pa_v5, v66param_size); } + return p; } } @@ -527,6 +539,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3, u64 param4) { struct apei_exec_context ctx; + u32 param_size = is_v2 ? v66param_size : v5param_size; u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT; int i, rc; @@ -539,11 +552,11 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, if (acpi5) { struct set_error_type_with_address *v5param; - v5param = kmalloc(v5param_size, GFP_KERNEL); + v5param = kmalloc(param_size, GFP_KERNEL); if (!v5param) return -ENOMEM; - memcpy_fromio(v5param, einj_param, v5param_size); + memcpy_fromio(v5param, einj_param, param_size); v5param->type = type; if (type & ACPI5_VENDOR_BIT) { switch (vendor_flags) { @@ -601,7 +614,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, break; } } - memcpy_toio(einj_param, v5param, v5param_size); + memcpy_toio(einj_param, v5param, param_size); kfree(v5param); } else { rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE); @@ -1132,9 +1145,14 @@ static void einj_remove(struct faux_device *fdev) struct apei_exec_context ctx; if (einj_param) { - acpi_size size = (acpi5) ? - v5param_size : - sizeof(struct einj_parameter); + acpi_size size; + + if (v66param_size) + size = v66param_size; + else if (acpi5) + size = v5param_size; + else + size = sizeof(struct einj_parameter); acpi_os_unmap_iomem(einj_param, size); if (vendor_errors.size) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2a210719c4ce..f48fb63d7e85 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3006,6 +3006,16 @@ int ata_dev_configure(struct ata_device *dev) } dev->n_sectors = ata_id_n_sectors(id); + if (ata_id_is_locked(id)) { + /* + * If Security locked, set capacity to zero to prevent + * any I/O, e.g. partition scanning, as any I/O to a + * locked drive will result in user visible errors. + */ + ata_dev_info(dev, + "Security locked, setting capacity to zero\n"); + dev->n_sectors = 0; + } /* get current R/W Multiple count setting */ if ((dev->id[47] >> 8) == 0x80 && (dev->id[59] & 0x100)) { diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index b43a3196e2be..434774e71fe6 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -992,6 +992,13 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) return; } + if (ata_id_is_locked(dev->id)) { + /* Security locked */ + /* LOGICAL UNIT ACCESS NOT AUTHORIZED */ + ata_scsi_set_sense(dev, cmd, DATA_PROTECT, 0x74, 0x71); + return; + } + if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) { ata_dev_dbg(dev, "Missing result TF: reporting aborted command\n"); @@ -4894,8 +4901,10 @@ void ata_scsi_dev_rescan(struct work_struct *work) spin_unlock_irqrestore(ap->lock, flags); if (do_resume) { ret = scsi_resume_device(sdev); - if (ret == -EWOULDBLOCK) + if (ret == -EWOULDBLOCK) { + scsi_device_put(sdev); goto unlock_scan; + } dev->flags &= ~ATA_DFLAG_RESUMING; } ret = scsi_rescan_device(sdev); diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index e83503bdc1fd..1de1cd72b616 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -888,12 +888,15 @@ static void device_resume_early(struct device *dev, pm_message_t state, bool asy TRACE_DEVICE(dev); TRACE_RESUME(0); - if (dev->power.syscore || dev->power.direct_complete) + if (dev->power.direct_complete) goto Out; if (!dev->power.is_late_suspended) goto Out; + if (dev->power.syscore) + goto Skip; + if (!dpm_wait_for_superior(dev, async)) goto Out; @@ -926,11 +929,11 @@ Run: Skip: dev->power.is_late_suspended = false; + pm_runtime_enable(dev); Out: TRACE_RESUME(error); - pm_runtime_enable(dev); complete_all(&dev->power.completion); if (error) { |
