1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2004 IBM Corporation |
4 | * Authors: |
5 | * Leendert van Doorn <leendert@watson.ibm.com> |
6 | * Dave Safford <safford@watson.ibm.com> |
7 | * Reiner Sailer <sailer@watson.ibm.com> |
8 | * Kylene Hall <kjhall@us.ibm.com> |
9 | * |
10 | * Copyright (C) 2013 Obsidian Research Corp |
11 | * Jason Gunthorpe <jgunthorpe@obsidianresearch.com> |
12 | * |
13 | * Device file system interface to the TPM |
14 | */ |
15 | #include <linux/slab.h> |
16 | #include "tpm-dev.h" |
17 | |
18 | static int tpm_open(struct inode *inode, struct file *file) |
19 | { |
20 | struct tpm_chip *chip; |
21 | struct file_priv *priv; |
22 | |
23 | chip = container_of(inode->i_cdev, struct tpm_chip, cdev); |
24 | |
25 | /* It's assured that the chip will be opened just once, |
26 | * by the check of is_open variable, which is protected |
27 | * by driver_lock. */ |
28 | if (test_and_set_bit(nr: 0, addr: &chip->is_open)) { |
29 | dev_dbg(&chip->dev, "Another process owns this TPM\n" ); |
30 | return -EBUSY; |
31 | } |
32 | |
33 | priv = kzalloc(size: sizeof(*priv), GFP_KERNEL); |
34 | if (priv == NULL) |
35 | goto out; |
36 | |
37 | tpm_common_open(file, chip, priv, NULL); |
38 | |
39 | return 0; |
40 | |
41 | out: |
42 | clear_bit(nr: 0, addr: &chip->is_open); |
43 | return -ENOMEM; |
44 | } |
45 | |
46 | /* |
47 | * Called on file close |
48 | */ |
49 | static int tpm_release(struct inode *inode, struct file *file) |
50 | { |
51 | struct file_priv *priv = file->private_data; |
52 | |
53 | tpm_common_release(file, priv); |
54 | clear_bit(nr: 0, addr: &priv->chip->is_open); |
55 | kfree(objp: priv); |
56 | |
57 | return 0; |
58 | } |
59 | |
60 | const struct file_operations tpm_fops = { |
61 | .owner = THIS_MODULE, |
62 | .llseek = no_llseek, |
63 | .open = tpm_open, |
64 | .read = tpm_common_read, |
65 | .write = tpm_common_write, |
66 | .poll = tpm_common_poll, |
67 | .release = tpm_release, |
68 | }; |
69 | |