summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2018-03-05 06:34:49 -0500
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2018-03-23 04:18:05 -0400
commit888d867df4417deffc33927e6fc2c6925736fe92 (patch)
treed587a1e61431f020c9368499a9d3b3daa23f94da
parent5893ed18a26d1f56b97c0290b0cbbc2d49d6de28 (diff)
tpm: cmd_ready command can be issued only after granting locality
The correct sequence is to first request locality and only after that perform cmd_ready handshake, otherwise the hardware will drop the subsequent message as from the device point of view the cmd_ready handshake wasn't performed. Symmetrically locality has to be relinquished only after going idle handshake has completed, this requires that go_idle has to poll for the completion and as well locality relinquish has to poll for completion so it is not overridden in back to back commands flow. Two wrapper functions are added (request_locality relinquish_locality) to simplify the error handling. The issue is only visible on devices that support multiple localities. Fixes: 877c57d0d0ca ("tpm_crb: request and relinquish locality 0") Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkine@linux.intel.com> Tested-by: Jarkko Sakkinen <jarkko.sakkine@linux.intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkine@linux.intel.com>
-rw-r--r--drivers/char/tpm/tpm-interface.c54
-rw-r--r--drivers/char/tpm/tpm_crb.c108
-rw-r--r--drivers/char/tpm/tpm_tis_core.c4
-rw-r--r--include/linux/tpm.h2
4 files changed, 120 insertions, 48 deletions
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 9e80a953d693..d27a7fb7b830 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -369,6 +369,36 @@ err_len:
369 return -EINVAL; 369 return -EINVAL;
370} 370}
371 371
372static int tpm_request_locality(struct tpm_chip *chip)
373{
374 int rc;
375
376 if (!chip->ops->request_locality)
377 return 0;
378
379 rc = chip->ops->request_locality(chip, 0);
380 if (rc < 0)
381 return rc;
382
383 chip->locality = rc;
384
385 return 0;
386}
387
388static void tpm_relinquish_locality(struct tpm_chip *chip)
389{
390 int rc;
391
392 if (!chip->ops->relinquish_locality)
393 return;
394
395 rc = chip->ops->relinquish_locality(chip, chip->locality);
396 if (rc)
397 dev_err(&chip->dev, "%s: : error %d\n", __func__, rc);
398
399 chip->locality = -1;
400}
401
372/** 402/**
373 * tmp_transmit - Internal kernel interface to transmit TPM commands. 403 * tmp_transmit - Internal kernel interface to transmit TPM commands.
374 * 404 *
@@ -422,8 +452,6 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
422 if (!(flags & TPM_TRANSMIT_UNLOCKED)) 452 if (!(flags & TPM_TRANSMIT_UNLOCKED))
423 mutex_lock(&chip->tpm_mutex); 453 mutex_lock(&chip->tpm_mutex);
424 454
425 if (chip->dev.parent)
426 pm_runtime_get_sync(chip->dev.parent);
427 455
428 if (chip->ops->clk_enable != NULL) 456 if (chip->ops->clk_enable != NULL)
429 chip->ops->clk_enable(chip, true); 457 chip->ops->clk_enable(chip, true);
@@ -431,14 +459,15 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
431 /* Store the decision as chip->locality will be changed. */ 459 /* Store the decision as chip->locality will be changed. */
432 need_locality = chip->locality == -1; 460 need_locality = chip->locality == -1;
433 461
434 if (!(flags & TPM_TRANSMIT_RAW) && 462 if (!(flags & TPM_TRANSMIT_RAW) && need_locality) {
435 need_locality && chip->ops->request_locality) { 463 rc = tpm_request_locality(chip);
436 rc = chip->ops->request_locality(chip, 0);
437 if (rc < 0) 464 if (rc < 0)
438 goto out_no_locality; 465 goto out_no_locality;
439 chip->locality = rc;
440 } 466 }
441 467
468 if (chip->dev.parent)
469 pm_runtime_get_sync(chip->dev.parent);
470
442 rc = tpm2_prepare_space(chip, space, ordinal, buf); 471 rc = tpm2_prepare_space(chip, space, ordinal, buf);
443 if (rc) 472 if (rc)
444 goto out; 473 goto out;
@@ -499,17 +528,16 @@ out_recv:
499 rc = tpm2_commit_space(chip, space, ordinal, buf, &len); 528 rc = tpm2_commit_space(chip, space, ordinal, buf, &len);
500 529
501out: 530out:
502 if (need_locality && chip->ops->relinquish_locality) { 531 if (chip->dev.parent)
503 chip->ops->relinquish_locality(chip, chip->locality); 532 pm_runtime_put_sync(chip->dev.parent);
504 chip->locality = -1; 533
505 } 534 if (need_locality)
535 tpm_relinquish_locality(chip);
536
506out_no_locality: 537out_no_locality:
507 if (chip->ops->clk_enable != NULL) 538 if (chip->ops->clk_enable != NULL)
508 chip->ops->clk_enable(chip, false); 539 chip->ops->clk_enable(chip, false);
509 540
510 if (chip->dev.parent)
511 pm_runtime_put_sync(chip->dev.parent);
512
513 if (!(flags & TPM_TRANSMIT_UNLOCKED)) 541 if (!(flags & TPM_TRANSMIT_UNLOCKED))
514 mutex_unlock(&chip->tpm_mutex); 542 mutex_unlock(&chip->tpm_mutex);
515 return rc ? rc : len; 543 return rc ? rc : len;
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 7b3c2a8aa9de..497edd9848cd 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -112,6 +112,25 @@ struct tpm2_crb_smc {
112 u32 smc_func_id; 112 u32 smc_func_id;
113}; 113};
114 114
115static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
116 unsigned long timeout)
117{
118 ktime_t start;
119 ktime_t stop;
120
121 start = ktime_get();
122 stop = ktime_add(start, ms_to_ktime(timeout));
123
124 do {
125 if ((ioread32(reg) & mask) == value)
126 return true;
127
128 usleep_range(50, 100);
129 } while (ktime_before(ktime_get(), stop));
130
131 return ((ioread32(reg) & mask) == value);
132}
133
115/** 134/**
116 * crb_go_idle - request tpm crb device to go the idle state 135 * crb_go_idle - request tpm crb device to go the idle state
117 * 136 *
@@ -128,7 +147,7 @@ struct tpm2_crb_smc {
128 * 147 *
129 * Return: 0 always 148 * Return: 0 always
130 */ 149 */
131static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) 150static int crb_go_idle(struct device *dev, struct crb_priv *priv)
132{ 151{
133 if ((priv->sm == ACPI_TPM2_START_METHOD) || 152 if ((priv->sm == ACPI_TPM2_START_METHOD) ||
134 (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || 153 (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
@@ -136,30 +155,17 @@ static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
136 return 0; 155 return 0;
137 156
138 iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); 157 iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
139 /* we don't really care when this settles */
140 158
159 if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
160 CRB_CTRL_REQ_GO_IDLE/* mask */,
161 0, /* value */
162 TPM2_TIMEOUT_C)) {
163 dev_warn(dev, "goIdle timed out\n");
164 return -ETIME;
165 }
141 return 0; 166 return 0;
142} 167}
143 168
144static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
145 unsigned long timeout)
146{
147 ktime_t start;
148 ktime_t stop;
149
150 start = ktime_get();
151 stop = ktime_add(start, ms_to_ktime(timeout));
152
153 do {
154 if ((ioread32(reg) & mask) == value)
155 return true;
156
157 usleep_range(50, 100);
158 } while (ktime_before(ktime_get(), stop));
159
160 return false;
161}
162
163/** 169/**
164 * crb_cmd_ready - request tpm crb device to enter ready state 170 * crb_cmd_ready - request tpm crb device to enter ready state
165 * 171 *
@@ -175,8 +181,7 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
175 * 181 *
176 * Return: 0 on success -ETIME on timeout; 182 * Return: 0 on success -ETIME on timeout;
177 */ 183 */
178static int __maybe_unused crb_cmd_ready(struct device *dev, 184static int crb_cmd_ready(struct device *dev, struct crb_priv *priv)
179 struct crb_priv *priv)
180{ 185{
181 if ((priv->sm == ACPI_TPM2_START_METHOD) || 186 if ((priv->sm == ACPI_TPM2_START_METHOD) ||
182 (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || 187 (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
@@ -195,11 +200,11 @@ static int __maybe_unused crb_cmd_ready(struct device *dev,
195 return 0; 200 return 0;
196} 201}
197 202
198static int crb_request_locality(struct tpm_chip *chip, int loc) 203static int __crb_request_locality(struct device *dev,
204 struct crb_priv *priv, int loc)
199{ 205{
200 struct crb_priv *priv = dev_get_drvdata(&chip->dev);
201 u32 value = CRB_LOC_STATE_LOC_ASSIGNED | 206 u32 value = CRB_LOC_STATE_LOC_ASSIGNED |
202 CRB_LOC_STATE_TPM_REG_VALID_STS; 207 CRB_LOC_STATE_TPM_REG_VALID_STS;
203 208
204 if (!priv->regs_h) 209 if (!priv->regs_h)
205 return 0; 210 return 0;
@@ -207,21 +212,45 @@ static int crb_request_locality(struct tpm_chip *chip, int loc)
207 iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl); 212 iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl);
208 if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value, 213 if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value,
209 TPM2_TIMEOUT_C)) { 214 TPM2_TIMEOUT_C)) {
210 dev_warn(&chip->dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); 215 dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
211 return -ETIME; 216 return -ETIME;
212 } 217 }
213 218
214 return 0; 219 return 0;
215} 220}
216 221
217static void crb_relinquish_locality(struct tpm_chip *chip, int loc) 222static int crb_request_locality(struct tpm_chip *chip, int loc)
218{ 223{
219 struct crb_priv *priv = dev_get_drvdata(&chip->dev); 224 struct crb_priv *priv = dev_get_drvdata(&chip->dev);
220 225
226 return __crb_request_locality(&chip->dev, priv, loc);
227}
228
229static int __crb_relinquish_locality(struct device *dev,
230 struct crb_priv *priv, int loc)
231{
232 u32 mask = CRB_LOC_STATE_LOC_ASSIGNED |
233 CRB_LOC_STATE_TPM_REG_VALID_STS;
234 u32 value = CRB_LOC_STATE_TPM_REG_VALID_STS;
235
221 if (!priv->regs_h) 236 if (!priv->regs_h)
222 return; 237 return 0;
223 238
224 iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl); 239 iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
240 if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value,
241 TPM2_TIMEOUT_C)) {
242 dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
243 return -ETIME;
244 }
245
246 return 0;
247}
248
249static int crb_relinquish_locality(struct tpm_chip *chip, int loc)
250{
251 struct crb_priv *priv = dev_get_drvdata(&chip->dev);
252
253 return __crb_relinquish_locality(&chip->dev, priv, loc);
225} 254}
226 255
227static u8 crb_status(struct tpm_chip *chip) 256static u8 crb_status(struct tpm_chip *chip)
@@ -475,6 +504,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
475 dev_warn(dev, FW_BUG "Bad ACPI memory layout"); 504 dev_warn(dev, FW_BUG "Bad ACPI memory layout");
476 } 505 }
477 506
507 ret = __crb_request_locality(dev, priv, 0);
508 if (ret)
509 return ret;
510
478 priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address, 511 priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address,
479 sizeof(struct crb_regs_tail)); 512 sizeof(struct crb_regs_tail));
480 if (IS_ERR(priv->regs_t)) 513 if (IS_ERR(priv->regs_t))
@@ -531,6 +564,8 @@ out:
531 564
532 crb_go_idle(dev, priv); 565 crb_go_idle(dev, priv);
533 566
567 __crb_relinquish_locality(dev, priv, 0);
568
534 return ret; 569 return ret;
535} 570}
536 571
@@ -588,10 +623,14 @@ static int crb_acpi_add(struct acpi_device *device)
588 chip->acpi_dev_handle = device->handle; 623 chip->acpi_dev_handle = device->handle;
589 chip->flags = TPM_CHIP_FLAG_TPM2; 624 chip->flags = TPM_CHIP_FLAG_TPM2;
590 625
591 rc = crb_cmd_ready(dev, priv); 626 rc = __crb_request_locality(dev, priv, 0);
592 if (rc) 627 if (rc)
593 return rc; 628 return rc;
594 629
630 rc = crb_cmd_ready(dev, priv);
631 if (rc)
632 goto out;
633
595 pm_runtime_get_noresume(dev); 634 pm_runtime_get_noresume(dev);
596 pm_runtime_set_active(dev); 635 pm_runtime_set_active(dev);
597 pm_runtime_enable(dev); 636 pm_runtime_enable(dev);
@@ -601,12 +640,15 @@ static int crb_acpi_add(struct acpi_device *device)
601 crb_go_idle(dev, priv); 640 crb_go_idle(dev, priv);
602 pm_runtime_put_noidle(dev); 641 pm_runtime_put_noidle(dev);
603 pm_runtime_disable(dev); 642 pm_runtime_disable(dev);
604 return rc; 643 goto out;
605 } 644 }
606 645
607 pm_runtime_put(dev); 646 pm_runtime_put_sync(dev);
608 647
609 return 0; 648out:
649 __crb_relinquish_locality(dev, priv, 0);
650
651 return rc;
610} 652}
611 653
612static int crb_acpi_remove(struct acpi_device *device) 654static int crb_acpi_remove(struct acpi_device *device)
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index da074e3db19b..5a1f47b43947 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -143,11 +143,13 @@ static bool check_locality(struct tpm_chip *chip, int l)
143 return false; 143 return false;
144} 144}
145 145
146static void release_locality(struct tpm_chip *chip, int l) 146static int release_locality(struct tpm_chip *chip, int l)
147{ 147{
148 struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); 148 struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
149 149
150 tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); 150 tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
151
152 return 0;
151} 153}
152 154
153static int request_locality(struct tpm_chip *chip, int l) 155static int request_locality(struct tpm_chip *chip, int l)
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index bcdd3790e94d..06639fb6ab85 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -44,7 +44,7 @@ struct tpm_class_ops {
44 bool (*update_timeouts)(struct tpm_chip *chip, 44 bool (*update_timeouts)(struct tpm_chip *chip,
45 unsigned long *timeout_cap); 45 unsigned long *timeout_cap);
46 int (*request_locality)(struct tpm_chip *chip, int loc); 46 int (*request_locality)(struct tpm_chip *chip, int loc);
47 void (*relinquish_locality)(struct tpm_chip *chip, int loc); 47 int (*relinquish_locality)(struct tpm_chip *chip, int loc);
48 void (*clk_enable)(struct tpm_chip *chip, bool value); 48 void (*clk_enable)(struct tpm_chip *chip, bool value);
49}; 49};
50 50