Skip to content

Commit 888d867

Browse files
Tomas WinklerJarkko Sakkinen
authored andcommitted
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: 877c57d ("tpm_crb: request and relinquish locality 0") Signed-off-by: Tomas Winkler <[email protected]> Reviewed-by: Jarkko Sakkinen <[email protected]> Tested-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Jarkko Sakkinen <[email protected]>
1 parent 5893ed1 commit 888d867

File tree

4 files changed

+120
-48
lines changed

4 files changed

+120
-48
lines changed

drivers/char/tpm/tpm-interface.c

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,36 @@ static int tpm_validate_command(struct tpm_chip *chip,
369369
return -EINVAL;
370370
}
371371

372+
static 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+
388+
static 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+
372402
/**
373403
* tmp_transmit - Internal kernel interface to transmit TPM commands.
374404
*
@@ -422,23 +452,22 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
422452
if (!(flags & TPM_TRANSMIT_UNLOCKED))
423453
mutex_lock(&chip->tpm_mutex);
424454

425-
if (chip->dev.parent)
426-
pm_runtime_get_sync(chip->dev.parent);
427455

428456
if (chip->ops->clk_enable != NULL)
429457
chip->ops->clk_enable(chip, true);
430458

431459
/* Store the decision as chip->locality will be changed. */
432460
need_locality = chip->locality == -1;
433461

434-
if (!(flags & TPM_TRANSMIT_RAW) &&
435-
need_locality && chip->ops->request_locality) {
436-
rc = chip->ops->request_locality(chip, 0);
462+
if (!(flags & TPM_TRANSMIT_RAW) && need_locality) {
463+
rc = tpm_request_locality(chip);
437464
if (rc < 0)
438465
goto out_no_locality;
439-
chip->locality = rc;
440466
}
441467

468+
if (chip->dev.parent)
469+
pm_runtime_get_sync(chip->dev.parent);
470+
442471
rc = tpm2_prepare_space(chip, space, ordinal, buf);
443472
if (rc)
444473
goto out;
@@ -499,17 +528,16 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
499528
rc = tpm2_commit_space(chip, space, ordinal, buf, &len);
500529

501530
out:
502-
if (need_locality && chip->ops->relinquish_locality) {
503-
chip->ops->relinquish_locality(chip, chip->locality);
504-
chip->locality = -1;
505-
}
531+
if (chip->dev.parent)
532+
pm_runtime_put_sync(chip->dev.parent);
533+
534+
if (need_locality)
535+
tpm_relinquish_locality(chip);
536+
506537
out_no_locality:
507538
if (chip->ops->clk_enable != NULL)
508539
chip->ops->clk_enable(chip, false);
509540

510-
if (chip->dev.parent)
511-
pm_runtime_put_sync(chip->dev.parent);
512-
513541
if (!(flags & TPM_TRANSMIT_UNLOCKED))
514542
mutex_unlock(&chip->tpm_mutex);
515543
return rc ? rc : len;

drivers/char/tpm/tpm_crb.c

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,25 @@ struct tpm2_crb_smc {
112112
u32 smc_func_id;
113113
};
114114

115+
static 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+
115134
/**
116135
* crb_go_idle - request tpm crb device to go the idle state
117136
*
@@ -128,38 +147,25 @@ struct tpm2_crb_smc {
128147
*
129148
* Return: 0 always
130149
*/
131-
static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
150+
static int crb_go_idle(struct device *dev, struct crb_priv *priv)
132151
{
133152
if ((priv->sm == ACPI_TPM2_START_METHOD) ||
134153
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
135154
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC))
136155
return 0;
137156

138157
iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
139-
/* we don't really care when this settles */
140158

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+
}
141166
return 0;
142167
}
143168

144-
static 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-
163169
/**
164170
* crb_cmd_ready - request tpm crb device to enter ready state
165171
*
@@ -175,8 +181,7 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
175181
*
176182
* Return: 0 on success -ETIME on timeout;
177183
*/
178-
static int __maybe_unused crb_cmd_ready(struct device *dev,
179-
struct crb_priv *priv)
184+
static int crb_cmd_ready(struct device *dev, struct crb_priv *priv)
180185
{
181186
if ((priv->sm == ACPI_TPM2_START_METHOD) ||
182187
(priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) ||
@@ -195,33 +200,57 @@ static int __maybe_unused crb_cmd_ready(struct device *dev,
195200
return 0;
196201
}
197202

198-
static int crb_request_locality(struct tpm_chip *chip, int loc)
203+
static int __crb_request_locality(struct device *dev,
204+
struct crb_priv *priv, int loc)
199205
{
200-
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
201206
u32 value = CRB_LOC_STATE_LOC_ASSIGNED |
202-
CRB_LOC_STATE_TPM_REG_VALID_STS;
207+
CRB_LOC_STATE_TPM_REG_VALID_STS;
203208

204209
if (!priv->regs_h)
205210
return 0;
206211

207212
iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl);
208213
if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value,
209214
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");
211216
return -ETIME;
212217
}
213218

214219
return 0;
215220
}
216221

217-
static void crb_relinquish_locality(struct tpm_chip *chip, int loc)
222+
static int crb_request_locality(struct tpm_chip *chip, int loc)
218223
{
219224
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
220225

226+
return __crb_request_locality(&chip->dev, priv, loc);
227+
}
228+
229+
static 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+
221236
if (!priv->regs_h)
222-
return;
237+
return 0;
223238

224239
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+
249+
static 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);
225254
}
226255

227256
static u8 crb_status(struct tpm_chip *chip)
@@ -475,6 +504,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
475504
dev_warn(dev, FW_BUG "Bad ACPI memory layout");
476505
}
477506

507+
ret = __crb_request_locality(dev, priv, 0);
508+
if (ret)
509+
return ret;
510+
478511
priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address,
479512
sizeof(struct crb_regs_tail));
480513
if (IS_ERR(priv->regs_t))
@@ -531,6 +564,8 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
531564

532565
crb_go_idle(dev, priv);
533566

567+
__crb_relinquish_locality(dev, priv, 0);
568+
534569
return ret;
535570
}
536571

@@ -588,10 +623,14 @@ static int crb_acpi_add(struct acpi_device *device)
588623
chip->acpi_dev_handle = device->handle;
589624
chip->flags = TPM_CHIP_FLAG_TPM2;
590625

591-
rc = crb_cmd_ready(dev, priv);
626+
rc = __crb_request_locality(dev, priv, 0);
592627
if (rc)
593628
return rc;
594629

630+
rc = crb_cmd_ready(dev, priv);
631+
if (rc)
632+
goto out;
633+
595634
pm_runtime_get_noresume(dev);
596635
pm_runtime_set_active(dev);
597636
pm_runtime_enable(dev);
@@ -601,12 +640,15 @@ static int crb_acpi_add(struct acpi_device *device)
601640
crb_go_idle(dev, priv);
602641
pm_runtime_put_noidle(dev);
603642
pm_runtime_disable(dev);
604-
return rc;
643+
goto out;
605644
}
606645

607-
pm_runtime_put(dev);
646+
pm_runtime_put_sync(dev);
608647

609-
return 0;
648+
out:
649+
__crb_relinquish_locality(dev, priv, 0);
650+
651+
return rc;
610652
}
611653

612654
static int crb_acpi_remove(struct acpi_device *device)

drivers/char/tpm/tpm_tis_core.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,13 @@ static bool check_locality(struct tpm_chip *chip, int l)
143143
return false;
144144
}
145145

146-
static void release_locality(struct tpm_chip *chip, int l)
146+
static int release_locality(struct tpm_chip *chip, int l)
147147
{
148148
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
149149

150150
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
151+
152+
return 0;
151153
}
152154

153155
static int request_locality(struct tpm_chip *chip, int l)

include/linux/tpm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ struct tpm_class_ops {
4444
bool (*update_timeouts)(struct tpm_chip *chip,
4545
unsigned long *timeout_cap);
4646
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);
4848
void (*clk_enable)(struct tpm_chip *chip, bool value);
4949
};
5050

0 commit comments

Comments
 (0)