aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/soc/qcom/rpmh.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 9fb25e627698..035091fd44b8 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -80,6 +80,7 @@ void rpmh_tx_done(const struct tcs_request *msg, int r)
80 struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request, 80 struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
81 msg); 81 msg);
82 struct completion *compl = rpm_msg->completion; 82 struct completion *compl = rpm_msg->completion;
83 bool free = rpm_msg->needs_free;
83 84
84 rpm_msg->err = r; 85 rpm_msg->err = r;
85 86
@@ -94,7 +95,7 @@ void rpmh_tx_done(const struct tcs_request *msg, int r)
94 complete(compl); 95 complete(compl);
95 96
96exit: 97exit:
97 if (rpm_msg->needs_free) 98 if (free)
98 kfree(rpm_msg); 99 kfree(rpm_msg);
99} 100}
100 101
@@ -347,11 +348,12 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
347{ 348{
348 struct batch_cache_req *req; 349 struct batch_cache_req *req;
349 struct rpmh_request *rpm_msgs; 350 struct rpmh_request *rpm_msgs;
350 DECLARE_COMPLETION_ONSTACK(compl); 351 struct completion *compls;
351 struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); 352 struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
352 unsigned long time_left; 353 unsigned long time_left;
353 int count = 0; 354 int count = 0;
354 int ret, i, j; 355 int ret, i;
356 void *ptr;
355 357
356 if (!cmd || !n) 358 if (!cmd || !n)
357 return -EINVAL; 359 return -EINVAL;
@@ -361,10 +363,15 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
361 if (!count) 363 if (!count)
362 return -EINVAL; 364 return -EINVAL;
363 365
364 req = kzalloc(sizeof(*req) + count * sizeof(req->rpm_msgs[0]), 366 ptr = kzalloc(sizeof(*req) +
367 count * (sizeof(req->rpm_msgs[0]) + sizeof(*compls)),
365 GFP_ATOMIC); 368 GFP_ATOMIC);
366 if (!req) 369 if (!ptr)
367 return -ENOMEM; 370 return -ENOMEM;
371
372 req = ptr;
373 compls = ptr + sizeof(*req) + count * sizeof(*rpm_msgs);
374
368 req->count = count; 375 req->count = count;
369 rpm_msgs = req->rpm_msgs; 376 rpm_msgs = req->rpm_msgs;
370 377
@@ -379,25 +386,26 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
379 } 386 }
380 387
381 for (i = 0; i < count; i++) { 388 for (i = 0; i < count; i++) {
382 rpm_msgs[i].completion = &compl; 389 struct completion *compl = &compls[i];
390
391 init_completion(compl);
392 rpm_msgs[i].completion = compl;
383 ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msgs[i].msg); 393 ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msgs[i].msg);
384 if (ret) { 394 if (ret) {
385 pr_err("Error(%d) sending RPMH message addr=%#x\n", 395 pr_err("Error(%d) sending RPMH message addr=%#x\n",
386 ret, rpm_msgs[i].msg.cmds[0].addr); 396 ret, rpm_msgs[i].msg.cmds[0].addr);
387 for (j = i; j < count; j++)
388 rpmh_tx_done(&rpm_msgs[j].msg, ret);
389 break; 397 break;
390 } 398 }
391 } 399 }
392 400
393 time_left = RPMH_TIMEOUT_MS; 401 time_left = RPMH_TIMEOUT_MS;
394 for (i = 0; i < count; i++) { 402 while (i--) {
395 time_left = wait_for_completion_timeout(&compl, time_left); 403 time_left = wait_for_completion_timeout(&compls[i], time_left);
396 if (!time_left) { 404 if (!time_left) {
397 /* 405 /*
398 * Better hope they never finish because they'll signal 406 * Better hope they never finish because they'll signal
399 * the completion on our stack and that's bad once 407 * the completion that we're going to free once
400 * we've returned from the function. 408 * we've returned from this function.
401 */ 409 */
402 WARN_ON(1); 410 WARN_ON(1);
403 ret = -ETIMEDOUT; 411 ret = -ETIMEDOUT;
@@ -406,7 +414,7 @@ int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
406 } 414 }
407 415
408exit: 416exit:
409 kfree(req); 417 kfree(ptr);
410 418
411 return ret; 419 return ret;
412} 420}