Skip to content

Commit 7ab36b5

Browse files
Bartosz Golaszewskiandersson
authored andcommitted
firmware: qcom: scm: request the waitqueue irq *after* initializing SCM
There's a subtle race in the SCM driver: we assign the __scm pointer before requesting the waitqueue interrupt. Assigning __scm marks the SCM API as ready to accept calls. It's possible that a user makes a call right after we set __scm and the firmware raises an interrupt before the driver's ready to service it. Move the __scm assignment after we request the interrupt. This has the added benefit of allowing us to drop the goto label. Reviewed-by: Konrad Dybcio <[email protected]> Signed-off-by: Bartosz Golaszewski <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
1 parent 87be3e7 commit 7ab36b5

File tree

1 file changed

+14
-22
lines changed

1 file changed

+14
-22
lines changed

drivers/firmware/qcom/qcom_scm.c

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,29 +2276,27 @@ static int qcom_scm_probe(struct platform_device *pdev)
22762276
return dev_err_probe(scm->dev, PTR_ERR(scm->mempool),
22772277
"Failed to create the SCM memory pool\n");
22782278

2279+
irq = platform_get_irq_optional(pdev, 0);
2280+
if (irq < 0) {
2281+
if (irq != -ENXIO)
2282+
return irq;
2283+
} else {
2284+
ret = devm_request_threaded_irq(scm->dev, irq, NULL, qcom_scm_irq_handler,
2285+
IRQF_ONESHOT, "qcom-scm", scm);
2286+
if (ret < 0)
2287+
return dev_err_probe(scm->dev, ret,
2288+
"Failed to request qcom-scm irq\n");
2289+
}
2290+
22792291
/*
22802292
* Paired with smp_load_acquire() in qcom_scm_is_available().
22812293
*
22822294
* This marks the SCM API as ready to accept user calls and can only
2283-
* be called after the TrustZone memory pool is initialized.
2295+
* be called after the TrustZone memory pool is initialized and the
2296+
* waitqueue interrupt requested.
22842297
*/
22852298
smp_store_release(&__scm, scm);
22862299

2287-
irq = platform_get_irq_optional(pdev, 0);
2288-
if (irq < 0) {
2289-
if (irq != -ENXIO) {
2290-
ret = irq;
2291-
goto err;
2292-
}
2293-
} else {
2294-
ret = devm_request_threaded_irq(__scm->dev, irq, NULL, qcom_scm_irq_handler,
2295-
IRQF_ONESHOT, "qcom-scm", __scm);
2296-
if (ret < 0) {
2297-
dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n");
2298-
goto err;
2299-
}
2300-
}
2301-
23022300
__get_convention();
23032301

23042302
/*
@@ -2328,12 +2326,6 @@ static int qcom_scm_probe(struct platform_device *pdev)
23282326
WARN(ret < 0, "failed to initialize qseecom: %d\n", ret);
23292327

23302328
return 0;
2331-
2332-
err:
2333-
/* Paired with smp_load_acquire() in qcom_scm_is_available(). */
2334-
smp_store_release(&__scm, NULL);
2335-
2336-
return ret;
23372329
}
23382330

23392331
static void qcom_scm_shutdown(struct platform_device *pdev)

0 commit comments

Comments
 (0)