aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/cppc_acpi.c
diff options
context:
space:
mode:
authorPrakash, Prashanth <pprakash@codeaurora.org>2016-08-16 16:39:44 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-08-30 19:02:34 -0400
commit139aee73f0c23b95a7e919b8f7e51ccf2d221181 (patch)
tree54af1fac0f5f558e9bf51e67f9b828144f4c11e0 /drivers/acpi/cppc_acpi.c
parent8482ef8c6e684a1bba703c330e0bafe2d1d29ef7 (diff)
ACPI / CPPC: check for error bit in PCC status field
PCC status field exposes an error bit(2) to indicate any errors during the execution of last comamnd. This patch checks the error bit before notifying success/failure to the cpufreq driver. Signed-off-by: Prashanth Prakash <pprakash@codeaurora.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi/cppc_acpi.c')
-rw-r--r--drivers/acpi/cppc_acpi.c66
1 files changed, 31 insertions, 35 deletions
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 80c123fbfdcf..ed58883d35ee 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -54,6 +54,7 @@ struct cppc_pcc_data {
54 unsigned int pcc_mpar, pcc_mrtt, pcc_nominal; 54 unsigned int pcc_mpar, pcc_mrtt, pcc_nominal;
55 55
56 bool pending_pcc_write_cmd; /* Any pending/batched PCC write cmds? */ 56 bool pending_pcc_write_cmd; /* Any pending/batched PCC write cmds? */
57 bool platform_owns_pcc; /* Ownership of PCC subspace */
57 unsigned int pcc_write_cnt; /* Running count of PCC write commands */ 58 unsigned int pcc_write_cnt; /* Running count of PCC write commands */
58 59
59 /* 60 /*
@@ -79,6 +80,7 @@ struct cppc_pcc_data {
79/* Structure to represent the single PCC channel */ 80/* Structure to represent the single PCC channel */
80static struct cppc_pcc_data pcc_data = { 81static struct cppc_pcc_data pcc_data = {
81 .pcc_subspace_idx = -1, 82 .pcc_subspace_idx = -1,
83 .platform_owns_pcc = true,
82}; 84};
83 85
84/* 86/*
@@ -181,12 +183,15 @@ static struct kobj_type cppc_ktype = {
181 .default_attrs = cppc_attrs, 183 .default_attrs = cppc_attrs,
182}; 184};
183 185
184static int check_pcc_chan(void) 186static int check_pcc_chan(bool chk_err_bit)
185{ 187{
186 int ret = -EIO; 188 int ret = -EIO, status = 0;
187 struct acpi_pcct_shared_memory __iomem *generic_comm_base = pcc_data.pcc_comm_addr; 189 struct acpi_pcct_shared_memory __iomem *generic_comm_base = pcc_data.pcc_comm_addr;
188 ktime_t next_deadline = ktime_add(ktime_get(), pcc_data.deadline); 190 ktime_t next_deadline = ktime_add(ktime_get(), pcc_data.deadline);
189 191
192 if (!pcc_data.platform_owns_pcc)
193 return 0;
194
190 /* Retry in case the remote processor was too slow to catch up. */ 195 /* Retry in case the remote processor was too slow to catch up. */
191 while (!ktime_after(ktime_get(), next_deadline)) { 196 while (!ktime_after(ktime_get(), next_deadline)) {
192 /* 197 /*
@@ -194,8 +199,11 @@ static int check_pcc_chan(void)
194 * platform and should have set the command completion bit when 199 * platform and should have set the command completion bit when
195 * PCC can be used by OSPM 200 * PCC can be used by OSPM
196 */ 201 */
197 if (readw_relaxed(&generic_comm_base->status) & PCC_CMD_COMPLETE) { 202 status = readw_relaxed(&generic_comm_base->status);
203 if (status & PCC_CMD_COMPLETE_MASK) {
198 ret = 0; 204 ret = 0;
205 if (chk_err_bit && (status & PCC_ERROR_MASK))
206 ret = -EIO;
199 break; 207 break;
200 } 208 }
201 /* 209 /*
@@ -205,6 +213,11 @@ static int check_pcc_chan(void)
205 udelay(3); 213 udelay(3);
206 } 214 }
207 215
216 if (likely(!ret))
217 pcc_data.platform_owns_pcc = false;
218 else
219 pr_err("PCC check channel failed. Status=%x\n", status);
220
208 return ret; 221 return ret;
209} 222}
210 223
@@ -234,7 +247,7 @@ static int send_pcc_cmd(u16 cmd)
234 if (pcc_data.pending_pcc_write_cmd) 247 if (pcc_data.pending_pcc_write_cmd)
235 send_pcc_cmd(CMD_WRITE); 248 send_pcc_cmd(CMD_WRITE);
236 249
237 ret = check_pcc_chan(); 250 ret = check_pcc_chan(false);
238 if (ret) 251 if (ret)
239 goto end; 252 goto end;
240 } else /* CMD_WRITE */ 253 } else /* CMD_WRITE */
@@ -282,6 +295,8 @@ static int send_pcc_cmd(u16 cmd)
282 /* Flip CMD COMPLETE bit */ 295 /* Flip CMD COMPLETE bit */
283 writew_relaxed(0, &generic_comm_base->status); 296 writew_relaxed(0, &generic_comm_base->status);
284 297
298 pcc_data.platform_owns_pcc = true;
299
285 /* Ring doorbell */ 300 /* Ring doorbell */
286 ret = mbox_send_message(pcc_data.pcc_channel, &cmd); 301 ret = mbox_send_message(pcc_data.pcc_channel, &cmd);
287 if (ret < 0) { 302 if (ret < 0) {
@@ -290,23 +305,11 @@ static int send_pcc_cmd(u16 cmd)
290 goto end; 305 goto end;
291 } 306 }
292 307
293 /* 308 /* wait for completion and check for PCC errro bit */
294 * For READs we need to ensure the cmd completed to ensure 309 ret = check_pcc_chan(true);
295 * the ensuing read()s can proceed. For WRITEs we dont care 310
296 * because the actual write()s are done before coming here 311 if (pcc_data.pcc_mrtt)
297 * and the next READ or WRITE will check if the channel 312 last_cmd_cmpl_time = ktime_get();
298 * is busy/free at the entry of this call.
299 *
300 * If Minimum Request Turnaround Time is non-zero, we need
301 * to record the completion time of both READ and WRITE
302 * command for proper handling of MRTT, so we need to check
303 * for pcc_mrtt in addition to CMD_READ
304 */
305 if (cmd == CMD_READ || pcc_data.pcc_mrtt) {
306 ret = check_pcc_chan();
307 if (pcc_data.pcc_mrtt)
308 last_cmd_cmpl_time = ktime_get();
309 }
310 313
311 mbox_client_txdone(pcc_data.pcc_channel, ret); 314 mbox_client_txdone(pcc_data.pcc_channel, ret);
312 315
@@ -1059,25 +1062,18 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
1059 */ 1062 */
1060 if (CPC_IN_PCC(desired_reg)) { 1063 if (CPC_IN_PCC(desired_reg)) {
1061 down_read(&pcc_data.pcc_lock); /* BEGIN Phase-I */ 1064 down_read(&pcc_data.pcc_lock); /* BEGIN Phase-I */
1062 /* 1065 if (pcc_data.platform_owns_pcc) {
1063 * If there are pending write commands i.e pending_pcc_write_cmd 1066 ret = check_pcc_chan(false);
1064 * is TRUE, then we know OSPM owns the channel as another CPU
1065 * has already checked for command completion bit and updated
1066 * the corresponding CPC registers
1067 */
1068 if (!pcc_data.pending_pcc_write_cmd) {
1069 ret = check_pcc_chan();
1070 if (ret) { 1067 if (ret) {
1071 up_read(&pcc_data.pcc_lock); 1068 up_read(&pcc_data.pcc_lock);
1072 return ret; 1069 return ret;
1073 } 1070 }
1074 /*
1075 * Update the pending_write to make sure a PCC CMD_READ
1076 * will not arrive and steal the channel during the
1077 * transition to write lock
1078 */
1079 pcc_data.pending_pcc_write_cmd = TRUE;
1080 } 1071 }
1072 /*
1073 * Update the pending_write to make sure a PCC CMD_READ will not
1074 * arrive and steal the channel during the switch to write lock
1075 */
1076 pcc_data.pending_pcc_write_cmd = true;
1081 cpc_desc->write_cmd_id = pcc_data.pcc_write_cnt; 1077 cpc_desc->write_cmd_id = pcc_data.pcc_write_cnt;
1082 cpc_desc->write_cmd_status = 0; 1078 cpc_desc->write_cmd_status = 0;
1083 } 1079 }