aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2016-01-07 19:36:26 -0500
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2016-02-09 21:11:51 -0500
commit1bd047be37d95bf65a219f4931215f71878ac060 (patch)
tree2e34afde34909507da6125d8589ce263226f2526 /drivers/char
parent1e3ed59d6200eb31b554dbdcfdde62d1e3d91f0c (diff)
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>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/tpm/tpm_crb.c151
1 files changed, 102 insertions, 49 deletions
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 0237006dc4d8..916332c9d906 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -77,6 +77,8 @@ enum crb_flags {
77 77
78struct crb_priv { 78struct crb_priv {
79 unsigned int flags; 79 unsigned int flags;
80 struct resource res;
81 void __iomem *iobase;
80 struct crb_control_area __iomem *cca; 82 struct crb_control_area __iomem *cca;
81 u8 __iomem *cmd; 83 u8 __iomem *cmd;
82 u8 __iomem *rsp; 84 u8 __iomem *rsp;
@@ -196,22 +198,115 @@ static const struct tpm_class_ops tpm_crb = {
196 .req_complete_val = CRB_STS_COMPLETE, 198 .req_complete_val = CRB_STS_COMPLETE,
197}; 199};
198 200
199static int crb_acpi_add(struct acpi_device *device) 201static int crb_init(struct acpi_device *device, struct crb_priv *priv)
200{ 202{
201 struct tpm_chip *chip; 203 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
225static 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
236static 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
255static 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
296static int crb_acpi_add(struct acpi_device *device)
297{
202 struct acpi_table_tpm2 *buf; 298 struct acpi_table_tpm2 *buf;
203 struct crb_priv *priv; 299 struct crb_priv *priv;
204 struct device *dev = &device->dev; 300 struct device *dev = &device->dev;
205 acpi_status status; 301 acpi_status status;
206 u32 sm; 302 u32 sm;
207 u64 pa;
208 int rc; 303 int rc;
209 304
210 status = acpi_get_table(ACPI_SIG_TPM2, 1, 305 status = acpi_get_table(ACPI_SIG_TPM2, 1,
211 (struct acpi_table_header **) &buf); 306 (struct acpi_table_header **) &buf);
212 if (ACPI_FAILURE(status) || buf->header.length < sizeof(*buf)) { 307 if (ACPI_FAILURE(status) || buf->header.length < sizeof(*buf)) {
213 dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n"); 308 dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n");
214 return -ENODEV; 309 return -EINVAL;
215 } 310 }
216 311
217 /* Should the FIFO driver handle this? */ 312 /* Should the FIFO driver handle this? */
@@ -219,18 +314,9 @@ static int crb_acpi_add(struct acpi_device *device)
219 if (sm == ACPI_TPM2_MEMORY_MAPPED) 314 if (sm == ACPI_TPM2_MEMORY_MAPPED)
220 return -ENODEV; 315 return -ENODEV;
221 316
222 chip = tpmm_chip_alloc(dev, &tpm_crb); 317 priv = devm_kzalloc(dev, sizeof(struct crb_priv), GFP_KERNEL);
223 if (IS_ERR(chip)) 318 if (!priv)
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");
232 return -ENOMEM; 319 return -ENOMEM;
233 }
234 320
235 /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs 321 /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs
236 * report only ACPI start but in practice seems to require both 322 * report only ACPI start but in practice seems to require both
@@ -244,44 +330,11 @@ static int crb_acpi_add(struct acpi_device *device)
244 sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) 330 sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)
245 priv->flags |= CRB_FL_ACPI_START; 331 priv->flags |= CRB_FL_ACPI_START;
246 332
247 priv->cca = (struct crb_control_area __iomem *) 333 rc = crb_map_io(device, priv, buf);
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);
275 if (rc) 334 if (rc)
276 return rc; 335 return rc;
277 336
278 chip->acpi_dev_handle = device->handle; 337 return crb_init(device, priv);
279
280 rc = tpm2_do_selftest(chip);
281 if (rc)
282 return rc;
283
284 return tpm_chip_register(chip);
285} 338}
286 339
287static int crb_acpi_remove(struct acpi_device *device) 340static int crb_acpi_remove(struct acpi_device *device)