firmware: stratix10-svc and stratix10-rsu: fixes for v7.1

- Return -EOPNOTSUPP when ATF async is not supported
 - Fix SVC driver from loading entirely when asynchronous ops is not
   supported in older ATF.
 - Fix a NULL pointer dereference on a timeout in rsu_send_msg()
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEoHhMeiyk5VmwVMwNGZQEC4GjKPQFAmoYixgACgkQGZQEC4Gj
 KPRebw/+OGOjxFWdZtiRthbeOnYGrRYpvtSyjrwOil9UV6Z8H1Lznq6JHTqgEzig
 DTlIo2Gy1lBapJV9mUbMbTPfqRgaMqXOF9xd0dgnJV2j+x5LfON2PJMGm99jA0eG
 o6ngxkLXM49HMMksrcT1j66GYn+tsZ4zlZxX36VlQDGSW+CukKMt/dOK0zcY0Y5W
 NjT2wn5Oq8L7Fs7wUsTtdphihNSdtMqBdzHcllcqdfv7AzyH7odRBCGo7OwlR2pJ
 3ds3lbAz/r9QlKeY3TdC8SuvzGR+RI8/ZLbOB2aMM2KSlWYqH7GFft6maLDGb4Gr
 val/gN5J15Y8i0J9uQYVYI35t3bwOC+jzFhCm5TTq+7fFkjk6t5UE/ZQ360/T4lg
 wzOSRjDHz3gY03MmwXHYnB8NCmUEPi+CItlrIMnRbGZwSwm/D80fXjqdAUjiqEip
 ESCSsVTEgqpx4UEgEbC/e5jdeqA2XdTBwxSsXTlk+2d8YtPexD/8YNzVL7deQL4W
 /G7Eih296NYL1StN/k82c9lFDXp8w1JP/jvEk9s0VrGMRD6Q+S4Pd6HKmMxOsp4o
 qI9P4FJ/85TcvtWYDeW+oS1zgYGp1GV2G5H8c5IvLUxZJ0hMZThJoLpje7fAJBEJ
 /1YA4qh08wLBpOvuyMu8nlHWEbcmGzyOTrSHEeifCN6nQKl2Gj8=
 =7ZCU
 -----END PGP SIGNATURE-----

Merge tag 'svc_fixes_for_v7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux into char-misc-linus

Dinh writes:

firmware: stratix10-svc and stratix10-rsu: fixes for v7.1
- Return -EOPNOTSUPP when ATF async is not supported
- Fix SVC driver from loading entirely when asynchronous ops is not
  supported in older ATF.
- Fix a NULL pointer dereference on a timeout in rsu_send_msg()

* tag 'svc_fixes_for_v7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux:
  firmware: stratix10-rsu: Fix NULL deref on rsu_send_msg() timeout in probe
  firmware: stratix10-svc: Don't fail probe when async ops unsupported
  firmware: stratix10-svc: Return -EOPNOTSUPP when ATF async unsupported
This commit is contained in:
Greg Kroah-Hartman 2026-06-05 17:17:30 +02:00
commit b5277b3a6f
2 changed files with 37 additions and 29 deletions

View File

@ -723,15 +723,9 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
return -ENOMEM;
priv->client.dev = dev;
priv->client.receive_cb = NULL;
priv->client.priv = priv;
priv->status.current_image = 0;
priv->status.fail_image = 0;
priv->status.error_location = 0;
priv->status.error_details = 0;
priv->status.version = 0;
priv->status.state = 0;
priv->retry_counter = INVALID_RETRY_COUNTER;
priv->max_retry = INVALID_RETRY_COUNTER;
priv->dcmf_version.dcmf0 = INVALID_DCMF_VERSION;
priv->dcmf_version.dcmf1 = INVALID_DCMF_VERSION;
priv->dcmf_version.dcmf2 = INVALID_DCMF_VERSION;
@ -740,11 +734,11 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
priv->dcmf_status.dcmf1 = INVALID_DCMF_STATUS;
priv->dcmf_status.dcmf2 = INVALID_DCMF_STATUS;
priv->dcmf_status.dcmf3 = INVALID_DCMF_STATUS;
priv->max_retry = INVALID_RETRY_COUNTER;
priv->spt0_address = INVALID_SPT_ADDRESS;
priv->spt1_address = INVALID_SPT_ADDRESS;
/* spt0/1_address and status fields default to 0 from kzalloc */
mutex_init(&priv->lock);
init_completion(&priv->completion);
priv->chan = stratix10_svc_request_channel_byname(&priv->client,
SVC_CLIENT_RSU);
if (IS_ERR(priv->chan)) {
@ -756,11 +750,9 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
ret = stratix10_svc_add_async_client(priv->chan, false);
if (ret) {
dev_err(dev, "failed to add async client\n");
stratix10_svc_free_channel(priv->chan);
return ret;
goto free_channel;
}
init_completion(&priv->completion);
platform_set_drvdata(pdev, priv);
/* get the initial state from firmware */
@ -768,41 +760,44 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
rsu_async_status_callback);
if (ret) {
dev_err(dev, "Error, getting RSU status %i\n", ret);
stratix10_svc_remove_async_client(priv->chan);
stratix10_svc_free_channel(priv->chan);
return ret;
goto remove_async_client;
}
/* get DCMF version from firmware */
ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION,
0, rsu_dcmf_version_callback);
ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION, 0,
rsu_dcmf_version_callback);
if (ret) {
dev_err(dev, "Error, getting DCMF version %i\n", ret);
stratix10_svc_free_channel(priv->chan);
goto remove_async_client;
}
ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS,
0, rsu_dcmf_status_callback);
ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS, 0,
rsu_dcmf_status_callback);
if (ret) {
dev_err(dev, "Error, getting DCMF status %i\n", ret);
stratix10_svc_free_channel(priv->chan);
goto remove_async_client;
}
ret = rsu_send_msg(priv, COMMAND_RSU_MAX_RETRY, 0,
rsu_max_retry_callback);
if (ret) {
dev_err(dev, "Error, getting RSU max retry %i\n", ret);
stratix10_svc_free_channel(priv->chan);
goto remove_async_client;
}
ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_GET_SPT_TABLE, 0,
rsu_async_get_spt_table_callback);
if (ret) {
dev_err(dev, "Error, getting SPT table %i\n", ret);
stratix10_svc_free_channel(priv->chan);
goto remove_async_client;
}
return 0;
remove_async_client:
stratix10_svc_remove_async_client(priv->chan);
free_channel:
stratix10_svc_free_channel(priv->chan);
return ret;
}

View File

@ -212,6 +212,7 @@ struct stratix10_async_chan {
/**
* struct stratix10_async_ctrl - Control structure for Stratix10
* asynchronous operations
* @supported: Flag indicating whether the system supports async operations
* @initialized: Flag indicating whether the control structure has
* been initialized
* @invoke_fn: Function pointer for invoking Stratix10 service calls
@ -228,6 +229,7 @@ struct stratix10_async_chan {
*/
struct stratix10_async_ctrl {
bool supported;
bool initialized;
void (*invoke_fn)(struct stratix10_async_ctrl *actrl,
const struct arm_smccc_1_2_regs *args,
@ -1103,6 +1105,7 @@ EXPORT_SYMBOL_GPL(stratix10_svc_request_channel_byname);
* Return: 0 on success, or a negative error code on failure:
* -EINVAL if the channel is NULL or the async controller is
* not initialized.
* -EOPNOTSUPP if async operations are not supported.
* -EALREADY if the async channel is already allocated.
* -ENOMEM if memory allocation fails.
* Other negative values if ID allocation fails.
@ -1121,6 +1124,9 @@ int stratix10_svc_add_async_client(struct stratix10_svc_chan *chan,
ctrl = chan->ctrl;
actrl = &ctrl->actrl;
if (!actrl->supported)
return -EOPNOTSUPP;
if (!actrl->initialized) {
dev_err(ctrl->dev, "Async controller not initialized\n");
return -EINVAL;
@ -1562,6 +1568,7 @@ static inline void stratix10_smc_1_2(struct stratix10_async_ctrl *actrl,
* initialized, -ENOMEM if memory allocation fails,
* -EADDRINUSE if the client ID is already reserved, or other
* negative error codes on failure.
* -EOPNOTSUPP if system doesn't support async operations.
*/
static int stratix10_svc_async_init(struct stratix10_svc_controller *controller)
{
@ -1585,10 +1592,12 @@ static int stratix10_svc_async_init(struct stratix10_svc_controller *controller)
!(res.a1 > ASYNC_ATF_MINIMUM_MAJOR_VERSION ||
(res.a1 == ASYNC_ATF_MINIMUM_MAJOR_VERSION &&
res.a2 >= ASYNC_ATF_MINIMUM_MINOR_VERSION))) {
dev_err(dev,
"Intel Service Layer Driver: ATF version is not compatible for async operation\n");
return -EINVAL;
dev_info(dev,
"Intel Service Layer Driver: ATF version is not compatible for async operation\n");
actrl->supported = false;
return -EOPNOTSUPP;
}
actrl->supported = true;
actrl->invoke_fn = stratix10_smc_1_2;
@ -1952,10 +1961,14 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
init_completion(&controller->complete_status);
ret = stratix10_svc_async_init(controller);
if (ret) {
if (ret == -EOPNOTSUPP) {
dev_info(dev, "Intel Service Layer Driver Initialized (sync-only mode)\n");
} else if (ret) {
dev_dbg(dev, "Intel Service Layer Driver: Error on stratix10_svc_async_init %d\n",
ret);
goto err_destroy_pool;
} else {
dev_info(dev, "Intel Service Layer Driver Initialized\n");
}
fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;