Skip to content

Commit 1bd047b

Browse files
jgunthorpeJarkko Sakkinen
authored andcommitted
tpm_crb: Use devm_ioremap_resource
To support the force mode in tpm_tis we need to use resource locking in tpm_crb as well, via devm_ioremap_resource. The light restructuring better aligns crb and tis and makes it easier to see the that new changes make sense. The control area and its associated buffers do not always fall in the range of the iomem resource given by the ACPI object. This patch fixes the issue by mapping the buffers if this is the case. [jarkko.sakkinen@linux.intel.com: squashed update described in the last paragraph.] Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Acked-by: Peter Huewe <peterhuewe@gmx.de> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
1 parent 1e3ed59 commit 1bd047b

File tree

1 file changed

+102
-49
lines changed

1 file changed

+102
-49
lines changed

drivers/char/tpm/tpm_crb.c

Lines changed: 102 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ enum crb_flags {
7777

7878
struct crb_priv {
7979
unsigned int flags;
80+
struct resource res;
81+
void __iomem *iobase;
8082
struct crb_control_area __iomem *cca;
8183
u8 __iomem *cmd;
8284
u8 __iomem *rsp;
@@ -196,41 +198,125 @@ static const struct tpm_class_ops tpm_crb = {
196198
.req_complete_val = CRB_STS_COMPLETE,
197199
};
198200

199-
static int crb_acpi_add(struct acpi_device *device)
201+
static int crb_init(struct acpi_device *device, struct crb_priv *priv)
200202
{
201203
struct tpm_chip *chip;
204+
int rc;
205+
206+
chip = tpmm_chip_alloc(&device->dev, &tpm_crb);
207+
if (IS_ERR(chip))
208+
return PTR_ERR(chip);
209+
210+
chip->vendor.priv = priv;
211+
chip->acpi_dev_handle = device->handle;
212+
chip->flags = TPM_CHIP_FLAG_TPM2;
213+
214+
rc = tpm_get_timeouts(chip);
215+
if (rc)
216+
return rc;
217+
218+
rc = tpm2_do_selftest(chip);
219+
if (rc)
220+
return rc;
221+
222+
return tpm_chip_register(chip);
223+
}
224+
225+
static int crb_check_resource(struct acpi_resource *ares, void *data)
226+
{
227+
struct crb_priv *priv = data;
228+
struct resource res;
229+
230+
if (acpi_dev_resource_memory(ares, &res))
231+
priv->res = res;
232+
233+
return 1;
234+
}
235+
236+
static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv,
237+
u64 start, u32 size)
238+
{
239+
struct resource new_res = {
240+
.start = start,
241+
.end = start + size - 1,
242+
.flags = IORESOURCE_MEM,
243+
};
244+
245+
/* Detect a 64 bit address on a 32 bit system */
246+
if (start != new_res.start)
247+
return ERR_PTR(-EINVAL);
248+
249+
if (!resource_contains(&priv->res, &new_res))
250+
return devm_ioremap_resource(dev, &new_res);
251+
252+
return priv->iobase + (new_res.start - priv->res.start);
253+
}
254+
255+
static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
256+
struct acpi_table_tpm2 *buf)
257+
{
258+
struct list_head resources;
259+
struct device *dev = &device->dev;
260+
u64 pa;
261+
int ret;
262+
263+
INIT_LIST_HEAD(&resources);
264+
ret = acpi_dev_get_resources(device, &resources, crb_check_resource,
265+
priv);
266+
if (ret < 0)
267+
return ret;
268+
acpi_dev_free_resource_list(&resources);
269+
270+
if (resource_type(&priv->res) != IORESOURCE_MEM) {
271+
dev_err(dev,
272+
FW_BUG "TPM2 ACPI table does not define a memory resource\n");
273+
return -EINVAL;
274+
}
275+
276+
priv->iobase = devm_ioremap_resource(dev, &priv->res);
277+
if (IS_ERR(priv->iobase))
278+
return PTR_ERR(priv->iobase);
279+
280+
priv->cca = crb_map_res(dev, priv, buf->control_address, 0x1000);
281+
if (IS_ERR(priv->cca))
282+
return PTR_ERR(priv->cca);
283+
284+
pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) |
285+
(u64) ioread32(&priv->cca->cmd_pa_low);
286+
priv->cmd = crb_map_res(dev, priv, pa, ioread32(&priv->cca->cmd_size));
287+
if (IS_ERR(priv->cmd))
288+
return PTR_ERR(priv->cmd);
289+
290+
memcpy_fromio(&pa, &priv->cca->rsp_pa, 8);
291+
pa = le64_to_cpu(pa);
292+
priv->rsp = crb_map_res(dev, priv, pa, ioread32(&priv->cca->rsp_size));
293+
return PTR_ERR_OR_ZERO(priv->rsp);
294+
}
295+
296+
static int crb_acpi_add(struct acpi_device *device)
297+
{
202298
struct acpi_table_tpm2 *buf;
203299
struct crb_priv *priv;
204300
struct device *dev = &device->dev;
205301
acpi_status status;
206302
u32 sm;
207-
u64 pa;
208303
int rc;
209304

210305
status = acpi_get_table(ACPI_SIG_TPM2, 1,
211306
(struct acpi_table_header **) &buf);
212307
if (ACPI_FAILURE(status) || buf->header.length < sizeof(*buf)) {
213308
dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n");
214-
return -ENODEV;
309+
return -EINVAL;
215310
}
216311

217312
/* Should the FIFO driver handle this? */
218313
sm = buf->start_method;
219314
if (sm == ACPI_TPM2_MEMORY_MAPPED)
220315
return -ENODEV;
221316

222-
chip = tpmm_chip_alloc(dev, &tpm_crb);
223-
if (IS_ERR(chip))
224-
return PTR_ERR(chip);
225-
226-
chip->flags = TPM_CHIP_FLAG_TPM2;
227-
228-
priv = (struct crb_priv *) devm_kzalloc(dev, sizeof(struct crb_priv),
229-
GFP_KERNEL);
230-
if (!priv) {
231-
dev_err(dev, "failed to devm_kzalloc for private data\n");
317+
priv = devm_kzalloc(dev, sizeof(struct crb_priv), GFP_KERNEL);
318+
if (!priv)
232319
return -ENOMEM;
233-
}
234320

235321
/* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs
236322
* report only ACPI start but in practice seems to require both
@@ -244,44 +330,11 @@ static int crb_acpi_add(struct acpi_device *device)
244330
sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)
245331
priv->flags |= CRB_FL_ACPI_START;
246332

247-
priv->cca = (struct crb_control_area __iomem *)
248-
devm_ioremap_nocache(dev, buf->control_address, 0x1000);
249-
if (!priv->cca) {
250-
dev_err(dev, "ioremap of the control area failed\n");
251-
return -ENOMEM;
252-
}
253-
254-
pa = ((u64)ioread32(&priv->cca->cmd_pa_high) << 32) |
255-
(u64)ioread32(&priv->cca->cmd_pa_low);
256-
priv->cmd =
257-
devm_ioremap_nocache(dev, pa, ioread32(&priv->cca->cmd_size));
258-
if (!priv->cmd) {
259-
dev_err(dev, "ioremap of the command buffer failed\n");
260-
return -ENOMEM;
261-
}
262-
263-
memcpy_fromio(&pa, &priv->cca->rsp_pa, 8);
264-
pa = le64_to_cpu(pa);
265-
priv->rsp =
266-
devm_ioremap_nocache(dev, pa, ioread32(&priv->cca->rsp_size));
267-
if (!priv->rsp) {
268-
dev_err(dev, "ioremap of the response buffer failed\n");
269-
return -ENOMEM;
270-
}
271-
272-
chip->vendor.priv = priv;
273-
274-
rc = tpm_get_timeouts(chip);
333+
rc = crb_map_io(device, priv, buf);
275334
if (rc)
276335
return rc;
277336

278-
chip->acpi_dev_handle = device->handle;
279-
280-
rc = tpm2_do_selftest(chip);
281-
if (rc)
282-
return rc;
283-
284-
return tpm_chip_register(chip);
337+
return crb_init(device, priv);
285338
}
286339

287340
static int crb_acpi_remove(struct acpi_device *device)

0 commit comments

Comments
 (0)