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

firmware: arm_scmi: Use asynchronous CLOCK_RATE_SET when possible

CLOCK_PROTOCOL_ATTRIBUTES provides attributes to indicate the maximum
number of pending asynchronous clock rate changes supported by the
platform. If it's non-zero, then we should be able to use asynchronous
clock rate set for any clocks until the maximum limit is reached.

Tracking the current count of pending asynchronous clock set rate
requests, we can decide if the incoming/new request for clock set rate
can be handled asynchronously or not until the maximum limit is
reached.

Cc: linux-clk@vger.kernel.org
Reviewed-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

+16 -3
+16 -3
drivers/firmware/arm_scmi/clock.c
··· 56 56 struct scmi_clock_set_rate { 57 57 __le32 flags; 58 58 #define CLOCK_SET_ASYNC BIT(0) 59 - #define CLOCK_SET_DELAYED BIT(1) 59 + #define CLOCK_SET_IGNORE_RESP BIT(1) 60 60 #define CLOCK_SET_ROUND_UP BIT(2) 61 61 #define CLOCK_SET_ROUND_AUTO BIT(3) 62 62 __le32 id; ··· 67 67 struct clock_info { 68 68 int num_clocks; 69 69 int max_async_req; 70 + atomic_t cur_async_req; 70 71 struct scmi_clock_info *clk; 71 72 }; 72 73 ··· 222 221 u64 rate) 223 222 { 224 223 int ret; 224 + u32 flags = 0; 225 225 struct scmi_xfer *t; 226 226 struct scmi_clock_set_rate *cfg; 227 + struct clock_info *ci = handle->clk_priv; 227 228 228 229 ret = scmi_xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK, 229 230 sizeof(*cfg), 0, &t); 230 231 if (ret) 231 232 return ret; 232 233 234 + if (ci->max_async_req && 235 + atomic_inc_return(&ci->cur_async_req) < ci->max_async_req) 236 + flags |= CLOCK_SET_ASYNC; 237 + 233 238 cfg = t->tx.buf; 234 - cfg->flags = cpu_to_le32(0); 239 + cfg->flags = cpu_to_le32(flags); 235 240 cfg->id = cpu_to_le32(clk_id); 236 241 cfg->value_low = cpu_to_le32(rate & 0xffffffff); 237 242 cfg->value_high = cpu_to_le32(rate >> 32); 238 243 239 - ret = scmi_do_xfer(handle, t); 244 + if (flags & CLOCK_SET_ASYNC) 245 + ret = scmi_do_xfer_with_response(handle, t); 246 + else 247 + ret = scmi_do_xfer(handle, t); 248 + 249 + if (ci->max_async_req) 250 + atomic_dec(&ci->cur_async_req); 240 251 241 252 scmi_xfer_put(handle, t); 242 253 return ret;