mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Arm SCMI/FF-A fixes for v7.2
Fix two runtime issues in the SCMI framework. Use full 64-bit division when rounding range-based clock rates, avoiding divisor truncation and a possible divide-by-zero on 32-bit systems. Rate-limit notification queue-full warnings emitted from interrupt context to prevent printk floods and prolonged system stalls during notification bursts. Also correct a grammar error in the ARM_SCMI_POWER_CONTROL Kconfig help text. Fix the FF-A driver RX/TX buffer sizing logic to respect the maximum buffer size advertised by firmware, while retaining compatibility with older implementations that may reject PAGE_SIZE-rounded buffers. Also fix a NULL pointer dereference in ffa_partition_info_get() by rejecting NULL UUID strings before passing them to uuid_parse(). -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEunHlEgbzHrJD3ZPhAEG6vDF+4pgFAmpUwQAACgkQAEG6vDF+ 4pgbkA//Vi8kcHJvXynbr4doRmZwGn2tpK5+Rn921xJ8zWDIB3GgCkkLqGEm0KFm vg9KCi3dgXg3w2uM1DN+exPQlmxHmfHJtODiQyRUx7xwuWLUCEt/JqD8FUi1KIUL 0uwtizWj/QTKvioHnZqNOLPbwLn+PGn6E4LE3d7YYvaISnB9gtp68Fkxn+88W1ry guSHNErlaPdyLGLmhh2vCfKz+uWIh2X6ie1IxpLLri1QvlUHupAtOlyhvncWeeaO abBDURuniqP5ol9jLcKrkybshXNo/Nq/VYFgESp72VqkUu5Mccm7/3q9qm3UqOkl t9JKFyj/ytHgt+A6H5A3ju02Yujw7JrTP/Ql6rwBfanbuC4tT1hb28VHMEd0ocs1 uDql+bwIDdmGsoM8W9TxKl3PHGjIK7a8vamaOaKFlXCT3jHAdVoP1a8liC8HmiAq 9u3U86bWbE19U3HlqxDCPS4EO5oug8VJG/YXdUkR3jYOtEbwFk4IIeI/Fx/F8rUc rowSak9u63kg26rfeg5DX3gh+O/9z7cSnefHyYrXi3r+AR0jg396In6eKXG9AJRQ 2g1WjJdj+1UjQrU9rIPURqmMeasZa3o6c4mKpCoUVNbu1sz+elZM2RqhzpFX5V0N EJcGDnnqEK0Ply2YQ1UxIvnLRkRt62ZCp5/9tbGoYD/avOPtULc= =J0zR -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmpX8usACgkQmmx57+YA GNlwNQ/8Cel80xEVfhAQ9VXAuSTh+8JmGVoPH+COJpvVm38KcDy3d7FB/B5USpIk X3s7fjx9CCc67d2nv4n95JJ19Sj+Ml/sWJnfOsaFeZGSQrow04r6Pko1h4kBxFCG d/oWhq/EWKCxy1mdIkf6EjePQJAHOq0/NxPZuRGz2RQH6K42/otaP+RKGN0eXQqK hpmD9RPEiVBl7rpe0oF/AiUikRsDdbAvjiVG2wHaDVpNoq53u5WcaeHx2RxRtuV+ 2hsmVJ/kSrh4INotcMfE/fNolwW/FRdXsh4VHqo2rt6toF04puUVOMNiaVYtua71 AAoXvQG1x9VNfo8fUYwllHawDFtV66oyUSO6Jr1cUWXiN09PV9Qd18fWI0ncFa5b oGD8l54XsiCvKZzB4XbKPzrSPc3egbUD6o9nPb8G4XlEORPVaqa5U2l9mEuNgjc1 cdjuJU6zHu0plDSvZX3dQ9nLboP4k8jO08tgUaeKPX65Ol2lmOjR0u3/CakkaNQe fgEE6b0tYDNthplgN/rXJrG8D3JrysTQv1XaB1GCPIdBi/WnTkwKbwGJweygxvIL lmdq0apLM2cLzf7tEtXrBvoavHy7j7Os580hc9LllJHoz6jyK5I2vv48bxCkgDms xcky6OCfnD71jN0sLYIeCuhI8CR+5UvmeoW9V9TioFB7qKo1I68= =BUNp -----END PGP SIGNATURE----- Merge tag 'scmi-ffa-fixes-7.2' of https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes Arm SCMI/FF-A fixes for v7.2 Fix two runtime issues in the SCMI framework. Use full 64-bit division when rounding range-based clock rates, avoiding divisor truncation and a possible divide-by-zero on 32-bit systems. Rate-limit notification queue-full warnings emitted from interrupt context to prevent printk floods and prolonged system stalls during notification bursts. Also correct a grammar error in the ARM_SCMI_POWER_CONTROL Kconfig help text. Fix the FF-A driver RX/TX buffer sizing logic to respect the maximum buffer size advertised by firmware, while retaining compatibility with older implementations that may reject PAGE_SIZE-rounded buffers. Also fix a NULL pointer dereference in ffa_partition_info_get() by rejecting NULL UUID strings before passing them to uuid_parse(). * tag 'scmi-ffa-fixes-7.2' of https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context firmware: arm_scmi: Use 64-bit division for clock rate rounding firmware: arm_scmi: Grammar s/may needed/may be needed/ firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() firmware: arm_ffa: Respect firmware advertised RX/TX buffer size limits Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
add11ea55f
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
|
|
@ -59,7 +60,9 @@
|
|||
(FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r)))
|
||||
|
||||
#define RXTX_MAP_MIN_BUFSZ_MASK GENMASK(1, 0)
|
||||
#define RXTX_MAP_MIN_BUFSZ(x) ((x) & RXTX_MAP_MIN_BUFSZ_MASK)
|
||||
#define RXTX_MAP_MAX_BUFSZ_MASK GENMASK(31, 16)
|
||||
#define RXTX_MAP_MIN_BUFSZ(x) (FIELD_GET(RXTX_MAP_MIN_BUFSZ_MASK, (x)))
|
||||
#define RXTX_MAP_MAX_BUFSZ(x) (FIELD_GET(RXTX_MAP_MAX_BUFSZ_MASK, (x)))
|
||||
|
||||
#define FFA_MAX_NOTIFICATIONS 64
|
||||
|
||||
|
|
@ -1139,7 +1142,7 @@ static int ffa_partition_info_get(const char *uuid_str,
|
|||
uuid_t uuid;
|
||||
struct ffa_partition_info *pbuf;
|
||||
|
||||
if (uuid_parse(uuid_str, &uuid)) {
|
||||
if (!uuid_str || uuid_parse(uuid_str, &uuid)) {
|
||||
pr_err("invalid uuid (%s)\n", uuid_str);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
@ -2101,7 +2104,7 @@ static int ffa_probe(struct platform_device *pdev)
|
|||
{
|
||||
int ret;
|
||||
u32 buf_sz;
|
||||
size_t rxtx_bufsz = SZ_4K;
|
||||
size_t rxtx_min_bufsz = SZ_4K, rxtx_max_bufsz = 0, rxtx_bufsz;
|
||||
|
||||
if (IS_BUILTIN(CONFIG_ARM_FFA_TRANSPORT) &&
|
||||
is_protected_kvm_enabled() && !is_pkvm_initialized())
|
||||
|
|
@ -2132,15 +2135,18 @@ static int ffa_probe(struct platform_device *pdev)
|
|||
ret = ffa_features(FFA_FN_NATIVE(RXTX_MAP), 0, &buf_sz, NULL);
|
||||
if (!ret) {
|
||||
if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 1)
|
||||
rxtx_bufsz = SZ_64K;
|
||||
rxtx_min_bufsz = SZ_64K;
|
||||
else if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 2)
|
||||
rxtx_bufsz = SZ_16K;
|
||||
rxtx_min_bufsz = SZ_16K;
|
||||
else
|
||||
rxtx_bufsz = SZ_4K;
|
||||
rxtx_min_bufsz = SZ_4K;
|
||||
|
||||
rxtx_max_bufsz = RXTX_MAP_MAX_BUFSZ(buf_sz) * SZ_4K;
|
||||
if (rxtx_max_bufsz != 0 && rxtx_max_bufsz < rxtx_min_bufsz)
|
||||
rxtx_max_bufsz = rxtx_min_bufsz;
|
||||
}
|
||||
|
||||
rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz);
|
||||
drv_info->rxtx_bufsz = rxtx_bufsz;
|
||||
rxtx_bufsz = min_not_zero(PAGE_ALIGN(rxtx_min_bufsz), rxtx_max_bufsz);
|
||||
drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
|
||||
if (!drv_info->rx_buffer) {
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -2156,10 +2162,17 @@ static int ffa_probe(struct platform_device *pdev)
|
|||
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
|
||||
virt_to_phys(drv_info->rx_buffer),
|
||||
rxtx_bufsz / FFA_PAGE_SIZE);
|
||||
if (ret == -EINVAL && !rxtx_max_bufsz && rxtx_min_bufsz < rxtx_bufsz) {
|
||||
rxtx_bufsz = rxtx_min_bufsz;
|
||||
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
|
||||
virt_to_phys(drv_info->rx_buffer),
|
||||
rxtx_bufsz / FFA_PAGE_SIZE);
|
||||
}
|
||||
if (ret) {
|
||||
pr_err("failed to register FFA RxTx buffers\n");
|
||||
goto free_pages;
|
||||
}
|
||||
drv_info->rxtx_bufsz = rxtx_bufsz;
|
||||
|
||||
mutex_init(&drv_info->rx_lock);
|
||||
mutex_init(&drv_info->tx_lock);
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ config ARM_SCMI_POWER_CONTROL
|
|||
firmware.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called scmi_power_control. Note this may needed early in boot to catch
|
||||
early shutdown/reboot SCMI requests.
|
||||
called scmi_power_control. Note this may be needed early in boot to
|
||||
catch early shutdown/reboot SCMI requests.
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -718,7 +718,7 @@ static int scmi_clock_rate_set(const struct scmi_protocol_handle *ph,
|
|||
static int scmi_clock_determine_rate(const struct scmi_protocol_handle *ph,
|
||||
u32 clk_id, unsigned long *rate)
|
||||
{
|
||||
u64 fmin, fmax, ftmp;
|
||||
u64 fmin, fmax, ftmp, step;
|
||||
struct scmi_clock_info *clk;
|
||||
struct scmi_clock_desc *clkd;
|
||||
struct clock_info *ci = ph->get_priv(ph);
|
||||
|
|
@ -749,11 +749,14 @@ static int scmi_clock_determine_rate(const struct scmi_protocol_handle *ph,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ftmp = *rate - fmin;
|
||||
ftmp += clkd->r.rates[RATE_STEP] - 1; /* to round up */
|
||||
ftmp = div64_ul(ftmp, clkd->r.rates[RATE_STEP]);
|
||||
step = clkd->r.rates[RATE_STEP];
|
||||
if (!step)
|
||||
return -EINVAL;
|
||||
|
||||
*rate = ftmp * clkd->r.rates[RATE_STEP] + fmin;
|
||||
ftmp = *rate - fmin;
|
||||
ftmp = DIV64_U64_ROUND_UP(ftmp, step);
|
||||
|
||||
*rate = ftmp * step + fmin;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -600,9 +600,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id,
|
|||
return -EINVAL;
|
||||
}
|
||||
if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) {
|
||||
dev_warn(handle->dev,
|
||||
"queue full, dropping proto_id:%d evt_id:%d ts:%lld\n",
|
||||
proto_id, evt_id, ktime_to_ns(ts));
|
||||
dev_warn_ratelimited(handle->dev,
|
||||
"queue full, dropping proto_id:%d evt_id:%d ts:%lld\n",
|
||||
proto_id, evt_id, ktime_to_ns(ts));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user