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

ACPI / CPPC: use MRTT/MPAR to decide if/when a req can be sent

The ACPI spec defines Minimum Request Turnaround Time(MRTT) and
Maximum Periodic Access Rate(MPAR) to prevent the OSPM from sending
too many requests than the platform can handle. For further details
on these parameters please refer to section 14.1.3 of ACPI 6.0 spec.

This patch includes MRTT/MPAR in deciding if or when a CPPC request
can be sent to the platform to make sure CPPC implementation is
compliant to the spec.

Signed-off-by: Prashanth Prakash <pprakash@codeaurora.org>
Acked-by: Ashwin Chaugule <ashwin.chaugule@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Prakash, Prashanth and committed by
Rafael J. Wysocki
f387e5b9 beee23ae

+55 -1
+55 -1
drivers/acpi/cppc_acpi.c
··· 66 66 static int pcc_subspace_idx = -1; 67 67 static bool pcc_channel_acquired; 68 68 static ktime_t deadline; 69 + static unsigned int pcc_mpar, pcc_mrtt; 69 70 70 71 /* pcc mapped address + header size + offset within PCC subspace */ 71 72 #define GET_PCC_VADDR(offs) (pcc_comm_addr + 0x8 + (offs)) ··· 86 85 87 86 /* Retry in case the remote processor was too slow to catch up. */ 88 87 while (!ktime_after(ktime_get(), next_deadline)) { 88 + /* 89 + * Per spec, prior to boot the PCC space wil be initialized by 90 + * platform and should have set the command completion bit when 91 + * PCC can be used by OSPM 92 + */ 89 93 if (readw_relaxed(&generic_comm_base->status) & PCC_CMD_COMPLETE) { 90 94 ret = 0; 91 95 break; ··· 110 104 int ret = -EIO; 111 105 struct acpi_pcct_shared_memory *generic_comm_base = 112 106 (struct acpi_pcct_shared_memory *) pcc_comm_addr; 107 + static ktime_t last_cmd_cmpl_time, last_mpar_reset; 108 + static int mpar_count; 109 + unsigned int time_delta; 113 110 114 111 /* 115 112 * For CMD_WRITE we know for a fact the caller should have checked ··· 122 113 ret = check_pcc_chan(); 123 114 if (ret) 124 115 return ret; 116 + } 117 + 118 + /* 119 + * Handle the Minimum Request Turnaround Time(MRTT) 120 + * "The minimum amount of time that OSPM must wait after the completion 121 + * of a command before issuing the next command, in microseconds" 122 + */ 123 + if (pcc_mrtt) { 124 + time_delta = ktime_us_delta(ktime_get(), last_cmd_cmpl_time); 125 + if (pcc_mrtt > time_delta) 126 + udelay(pcc_mrtt - time_delta); 127 + } 128 + 129 + /* 130 + * Handle the non-zero Maximum Periodic Access Rate(MPAR) 131 + * "The maximum number of periodic requests that the subspace channel can 132 + * support, reported in commands per minute. 0 indicates no limitation." 133 + * 134 + * This parameter should be ideally zero or large enough so that it can 135 + * handle maximum number of requests that all the cores in the system can 136 + * collectively generate. If it is not, we will follow the spec and just 137 + * not send the request to the platform after hitting the MPAR limit in 138 + * any 60s window 139 + */ 140 + if (pcc_mpar) { 141 + if (mpar_count == 0) { 142 + time_delta = ktime_ms_delta(ktime_get(), last_mpar_reset); 143 + if (time_delta < 60 * MSEC_PER_SEC) { 144 + pr_debug("PCC cmd not sent due to MPAR limit"); 145 + return -EIO; 146 + } 147 + last_mpar_reset = ktime_get(); 148 + mpar_count = pcc_mpar; 149 + } 150 + mpar_count--; 125 151 } 126 152 127 153 /* Write to the shared comm region. */ ··· 179 135 * because the actual write()s are done before coming here 180 136 * and the next READ or WRITE will check if the channel 181 137 * is busy/free at the entry of this call. 138 + * 139 + * If Minimum Request Turnaround Time is non-zero, we need 140 + * to record the completion time of both READ and WRITE 141 + * command for proper handling of MRTT, so we need to check 142 + * for pcc_mrtt in addition to CMD_READ 182 143 */ 183 - if (cmd == CMD_READ) 144 + if (cmd == CMD_READ || pcc_mrtt) { 184 145 ret = check_pcc_chan(); 146 + if (pcc_mrtt) 147 + last_cmd_cmpl_time = ktime_get(); 148 + } 185 149 186 150 mbox_client_txdone(pcc_channel, ret); 187 151 return ret; ··· 427 375 */ 428 376 usecs_lat = NUM_RETRIES * cppc_ss->latency; 429 377 deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC); 378 + pcc_mrtt = cppc_ss->min_turnaround_time; 379 + pcc_mpar = cppc_ss->max_access_rate; 430 380 431 381 pcc_comm_addr = acpi_os_ioremap(comm_base_addr, len); 432 382 if (!pcc_comm_addr) {