Skip to content

Commit 0af6e0a

Browse files
author
Jarkko Sakkinen
committed
tpm_crb: fix mapping of the buffers
On my Lenovo x250 the following situation occurs: [18697.813871] tpm_crb MSFT0101:00: can't request region for resource [mem 0xacdff080-0xacdfffff] The mapping of the control area overlaps the mapping of the command buffer. The control area is mapped over page, which is not right. It should mapped over sizeof(struct crb_control_area). Fixing this issue unmasks another issue. Command and response buffers can overlap and they do interleave on this machine. According to the PTP specification the overlapping means that they are mapped to the same buffer. The commit has been also on a Haswell NUC where things worked before applying this fix so that the both code paths for response buffer initialization are tested. Cc: stable@vger.kernel.org Fixes: 1bd047b ("tpm_crb: Use devm_ioremap_resource") Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
1 parent 0c61500 commit 0af6e0a

File tree

1 file changed

+28
-11
lines changed

1 file changed

+28
-11
lines changed

drivers/char/tpm/tpm_crb.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,10 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
259259
struct list_head resources;
260260
struct resource io_res;
261261
struct device *dev = &device->dev;
262-
u64 pa;
262+
u64 cmd_pa;
263+
u32 cmd_size;
264+
u64 rsp_pa;
265+
u32 rsp_size;
263266
int ret;
264267

265268
INIT_LIST_HEAD(&resources);
@@ -280,22 +283,36 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
280283
return PTR_ERR(priv->iobase);
281284

282285
priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address,
283-
0x1000);
286+
sizeof(struct crb_control_area));
284287
if (IS_ERR(priv->cca))
285288
return PTR_ERR(priv->cca);
286289

287-
pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) |
288-
(u64) ioread32(&priv->cca->cmd_pa_low);
289-
priv->cmd = crb_map_res(dev, priv, &io_res, pa,
290-
ioread32(&priv->cca->cmd_size));
290+
cmd_pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) |
291+
(u64) ioread32(&priv->cca->cmd_pa_low);
292+
cmd_size = ioread32(&priv->cca->cmd_size);
293+
priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size);
291294
if (IS_ERR(priv->cmd))
292295
return PTR_ERR(priv->cmd);
293296

294-
memcpy_fromio(&pa, &priv->cca->rsp_pa, 8);
295-
pa = le64_to_cpu(pa);
296-
priv->rsp = crb_map_res(dev, priv, &io_res, pa,
297-
ioread32(&priv->cca->rsp_size));
298-
return PTR_ERR_OR_ZERO(priv->rsp);
297+
memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8);
298+
rsp_pa = le64_to_cpu(rsp_pa);
299+
rsp_size = ioread32(&priv->cca->rsp_size);
300+
301+
if (cmd_pa != rsp_pa) {
302+
priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
303+
return PTR_ERR_OR_ZERO(priv->rsp);
304+
}
305+
306+
/* According to the PTP specification, overlapping command and response
307+
* buffer sizes must be identical.
308+
*/
309+
if (cmd_size != rsp_size) {
310+
dev_err(dev, FW_BUG "overlapping command and response buffer sizes are not identical");
311+
return -EINVAL;
312+
}
313+
314+
priv->rsp = priv->cmd;
315+
return 0;
299316
}
300317

301318
static int crb_acpi_add(struct acpi_device *device)

0 commit comments

Comments
 (0)