diff options
author | Jason Gunthorpe <jgunthorpe@obsidianresearch.com> | 2013-11-26 15:30:45 -0500 |
---|---|---|
committer | Peter Huewe <peterhuewe@gmx.de> | 2014-01-06 08:37:25 -0500 |
commit | e3302e0d6dcc02f369ecdc01c8392a28f14c0cba (patch) | |
tree | e0e0b6aa43cd6c9a59c77a6492c4db503a1078e5 /drivers/char | |
parent | 5f82e9f00417b92a108ccf0f0f5ebd53205d81ed (diff) |
tpm: Make tpm-dev allocate a per-file structure
This consolidates everything that is only used within tpm-dev.c
into tpm-dev.c and out of the publicly visible struct tpm_chip.
The per-file allocation lays the ground work for someday fixing the
strange forced O_EXCL behaviour of the current code.
Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Reviewed-by: Ashley Lai <adlai@linux.vnet.ibm.com>
Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/tpm-dev.c | 100 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 7 |
2 files changed, 57 insertions, 50 deletions
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c index 4f0cf2b6fc67..d9b774e02a1f 100644 --- a/drivers/char/tpm/tpm-dev.c +++ b/drivers/char/tpm/tpm-dev.c | |||
@@ -22,21 +22,34 @@ | |||
22 | #include <linux/uaccess.h> | 22 | #include <linux/uaccess.h> |
23 | #include "tpm.h" | 23 | #include "tpm.h" |
24 | 24 | ||
25 | struct file_priv { | ||
26 | struct tpm_chip *chip; | ||
27 | |||
28 | /* Data passed to and from the tpm via the read/write calls */ | ||
29 | atomic_t data_pending; | ||
30 | struct mutex buffer_mutex; | ||
31 | |||
32 | struct timer_list user_read_timer; /* user needs to claim result */ | ||
33 | struct work_struct work; | ||
34 | |||
35 | u8 data_buffer[TPM_BUFSIZE]; | ||
36 | }; | ||
37 | |||
25 | static void user_reader_timeout(unsigned long ptr) | 38 | static void user_reader_timeout(unsigned long ptr) |
26 | { | 39 | { |
27 | struct tpm_chip *chip = (struct tpm_chip *) ptr; | 40 | struct file_priv *priv = (struct file_priv *)ptr; |
28 | 41 | ||
29 | schedule_work(&chip->work); | 42 | schedule_work(&priv->work); |
30 | } | 43 | } |
31 | 44 | ||
32 | static void timeout_work(struct work_struct *work) | 45 | static void timeout_work(struct work_struct *work) |
33 | { | 46 | { |
34 | struct tpm_chip *chip = container_of(work, struct tpm_chip, work); | 47 | struct file_priv *priv = container_of(work, struct file_priv, work); |
35 | 48 | ||
36 | mutex_lock(&chip->buffer_mutex); | 49 | mutex_lock(&priv->buffer_mutex); |
37 | atomic_set(&chip->data_pending, 0); | 50 | atomic_set(&priv->data_pending, 0); |
38 | memset(chip->data_buffer, 0, TPM_BUFSIZE); | 51 | memset(priv->data_buffer, 0, sizeof(priv->data_buffer)); |
39 | mutex_unlock(&chip->buffer_mutex); | 52 | mutex_unlock(&priv->buffer_mutex); |
40 | } | 53 | } |
41 | 54 | ||
42 | static int tpm_open(struct inode *inode, struct file *file) | 55 | static int tpm_open(struct inode *inode, struct file *file) |
@@ -44,6 +57,7 @@ static int tpm_open(struct inode *inode, struct file *file) | |||
44 | struct miscdevice *misc = file->private_data; | 57 | struct miscdevice *misc = file->private_data; |
45 | struct tpm_chip *chip = container_of(misc, struct tpm_chip, | 58 | struct tpm_chip *chip = container_of(misc, struct tpm_chip, |
46 | vendor.miscdev); | 59 | vendor.miscdev); |
60 | struct file_priv *priv; | ||
47 | 61 | ||
48 | /* It's assured that the chip will be opened just once, | 62 | /* It's assured that the chip will be opened just once, |
49 | * by the check of is_open variable, which is protected | 63 | * by the check of is_open variable, which is protected |
@@ -53,15 +67,20 @@ static int tpm_open(struct inode *inode, struct file *file) | |||
53 | return -EBUSY; | 67 | return -EBUSY; |
54 | } | 68 | } |
55 | 69 | ||
56 | chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL); | 70 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
57 | if (chip->data_buffer == NULL) { | 71 | if (priv == NULL) { |
58 | clear_bit(0, &chip->is_open); | 72 | clear_bit(0, &chip->is_open); |
59 | return -ENOMEM; | 73 | return -ENOMEM; |
60 | } | 74 | } |
61 | 75 | ||
62 | atomic_set(&chip->data_pending, 0); | 76 | priv->chip = chip; |
77 | atomic_set(&priv->data_pending, 0); | ||
78 | mutex_init(&priv->buffer_mutex); | ||
79 | setup_timer(&priv->user_read_timer, user_reader_timeout, | ||
80 | (unsigned long)priv); | ||
81 | INIT_WORK(&priv->work, timeout_work); | ||
63 | 82 | ||
64 | file->private_data = chip; | 83 | file->private_data = priv; |
65 | get_device(chip->dev); | 84 | get_device(chip->dev); |
66 | return 0; | 85 | return 0; |
67 | } | 86 | } |
@@ -69,28 +88,28 @@ static int tpm_open(struct inode *inode, struct file *file) | |||
69 | static ssize_t tpm_read(struct file *file, char __user *buf, | 88 | static ssize_t tpm_read(struct file *file, char __user *buf, |
70 | size_t size, loff_t *off) | 89 | size_t size, loff_t *off) |
71 | { | 90 | { |
72 | struct tpm_chip *chip = file->private_data; | 91 | struct file_priv *priv = file->private_data; |
73 | ssize_t ret_size; | 92 | ssize_t ret_size; |
74 | int rc; | 93 | int rc; |
75 | 94 | ||
76 | del_singleshot_timer_sync(&chip->user_read_timer); | 95 | del_singleshot_timer_sync(&priv->user_read_timer); |
77 | flush_work(&chip->work); | 96 | flush_work(&priv->work); |
78 | ret_size = atomic_read(&chip->data_pending); | 97 | ret_size = atomic_read(&priv->data_pending); |
79 | if (ret_size > 0) { /* relay data */ | 98 | if (ret_size > 0) { /* relay data */ |
80 | ssize_t orig_ret_size = ret_size; | 99 | ssize_t orig_ret_size = ret_size; |
81 | if (size < ret_size) | 100 | if (size < ret_size) |
82 | ret_size = size; | 101 | ret_size = size; |
83 | 102 | ||
84 | mutex_lock(&chip->buffer_mutex); | 103 | mutex_lock(&priv->buffer_mutex); |
85 | rc = copy_to_user(buf, chip->data_buffer, ret_size); | 104 | rc = copy_to_user(buf, priv->data_buffer, ret_size); |
86 | memset(chip->data_buffer, 0, orig_ret_size); | 105 | memset(priv->data_buffer, 0, orig_ret_size); |
87 | if (rc) | 106 | if (rc) |
88 | ret_size = -EFAULT; | 107 | ret_size = -EFAULT; |
89 | 108 | ||
90 | mutex_unlock(&chip->buffer_mutex); | 109 | mutex_unlock(&priv->buffer_mutex); |
91 | } | 110 | } |
92 | 111 | ||
93 | atomic_set(&chip->data_pending, 0); | 112 | atomic_set(&priv->data_pending, 0); |
94 | 113 | ||
95 | return ret_size; | 114 | return ret_size; |
96 | } | 115 | } |
@@ -98,7 +117,7 @@ static ssize_t tpm_read(struct file *file, char __user *buf, | |||
98 | static ssize_t tpm_write(struct file *file, const char __user *buf, | 117 | static ssize_t tpm_write(struct file *file, const char __user *buf, |
99 | size_t size, loff_t *off) | 118 | size_t size, loff_t *off) |
100 | { | 119 | { |
101 | struct tpm_chip *chip = file->private_data; | 120 | struct file_priv *priv = file->private_data; |
102 | size_t in_size = size; | 121 | size_t in_size = size; |
103 | ssize_t out_size; | 122 | ssize_t out_size; |
104 | 123 | ||
@@ -106,32 +125,33 @@ static ssize_t tpm_write(struct file *file, const char __user *buf, | |||
106 | either via tpm_read or a user_read_timer timeout. | 125 | either via tpm_read or a user_read_timer timeout. |
107 | This also prevents splitted buffered writes from blocking here. | 126 | This also prevents splitted buffered writes from blocking here. |
108 | */ | 127 | */ |
109 | if (atomic_read(&chip->data_pending) != 0) | 128 | if (atomic_read(&priv->data_pending) != 0) |
110 | return -EBUSY; | 129 | return -EBUSY; |
111 | 130 | ||
112 | if (in_size > TPM_BUFSIZE) | 131 | if (in_size > TPM_BUFSIZE) |
113 | return -E2BIG; | 132 | return -E2BIG; |
114 | 133 | ||
115 | mutex_lock(&chip->buffer_mutex); | 134 | mutex_lock(&priv->buffer_mutex); |
116 | 135 | ||
117 | if (copy_from_user | 136 | if (copy_from_user |
118 | (chip->data_buffer, (void __user *) buf, in_size)) { | 137 | (priv->data_buffer, (void __user *) buf, in_size)) { |
119 | mutex_unlock(&chip->buffer_mutex); | 138 | mutex_unlock(&priv->buffer_mutex); |
120 | return -EFAULT; | 139 | return -EFAULT; |
121 | } | 140 | } |
122 | 141 | ||
123 | /* atomic tpm command send and result receive */ | 142 | /* atomic tpm command send and result receive */ |
124 | out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); | 143 | out_size = tpm_transmit(priv->chip, priv->data_buffer, |
144 | sizeof(priv->data_buffer)); | ||
125 | if (out_size < 0) { | 145 | if (out_size < 0) { |
126 | mutex_unlock(&chip->buffer_mutex); | 146 | mutex_unlock(&priv->buffer_mutex); |
127 | return out_size; | 147 | return out_size; |
128 | } | 148 | } |
129 | 149 | ||
130 | atomic_set(&chip->data_pending, out_size); | 150 | atomic_set(&priv->data_pending, out_size); |
131 | mutex_unlock(&chip->buffer_mutex); | 151 | mutex_unlock(&priv->buffer_mutex); |
132 | 152 | ||
133 | /* Set a timeout by which the reader must come claim the result */ | 153 | /* Set a timeout by which the reader must come claim the result */ |
134 | mod_timer(&chip->user_read_timer, jiffies + (60 * HZ)); | 154 | mod_timer(&priv->user_read_timer, jiffies + (60 * HZ)); |
135 | 155 | ||
136 | return in_size; | 156 | return in_size; |
137 | } | 157 | } |
@@ -141,15 +161,15 @@ static ssize_t tpm_write(struct file *file, const char __user *buf, | |||
141 | */ | 161 | */ |
142 | static int tpm_release(struct inode *inode, struct file *file) | 162 | static int tpm_release(struct inode *inode, struct file *file) |
143 | { | 163 | { |
144 | struct tpm_chip *chip = file->private_data; | 164 | struct file_priv *priv = file->private_data; |
145 | 165 | ||
146 | del_singleshot_timer_sync(&chip->user_read_timer); | 166 | del_singleshot_timer_sync(&priv->user_read_timer); |
147 | flush_work(&chip->work); | 167 | flush_work(&priv->work); |
148 | file->private_data = NULL; | 168 | file->private_data = NULL; |
149 | atomic_set(&chip->data_pending, 0); | 169 | atomic_set(&priv->data_pending, 0); |
150 | kzfree(chip->data_buffer); | 170 | clear_bit(0, &priv->chip->is_open); |
151 | clear_bit(0, &chip->is_open); | 171 | put_device(priv->chip->dev); |
152 | put_device(chip->dev); | 172 | kfree(priv); |
153 | return 0; | 173 | return 0; |
154 | } | 174 | } |
155 | 175 | ||
@@ -166,12 +186,6 @@ int tpm_dev_add_device(struct tpm_chip *chip) | |||
166 | { | 186 | { |
167 | int rc; | 187 | int rc; |
168 | 188 | ||
169 | mutex_init(&chip->buffer_mutex); | ||
170 | INIT_WORK(&chip->work, timeout_work); | ||
171 | |||
172 | setup_timer(&chip->user_read_timer, user_reader_timeout, | ||
173 | (unsigned long)chip); | ||
174 | |||
175 | chip->vendor.miscdev.fops = &tpm_fops; | 189 | chip->vendor.miscdev.fops = &tpm_fops; |
176 | if (chip->dev_num == 0) | 190 | if (chip->dev_num == 0) |
177 | chip->vendor.miscdev.minor = TPM_MINOR; | 191 | chip->vendor.miscdev.minor = TPM_MINOR; |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 7b0a46e214c5..e4d0888d2eab 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -103,13 +103,6 @@ struct tpm_chip { | |||
103 | unsigned long is_open; /* only one allowed */ | 103 | unsigned long is_open; /* only one allowed */ |
104 | int time_expired; | 104 | int time_expired; |
105 | 105 | ||
106 | /* Data passed to and from the tpm via the read/write calls */ | ||
107 | u8 *data_buffer; | ||
108 | atomic_t data_pending; | ||
109 | struct mutex buffer_mutex; | ||
110 | |||
111 | struct timer_list user_read_timer; /* user needs to claim result */ | ||
112 | struct work_struct work; | ||
113 | struct mutex tpm_mutex; /* tpm is processing */ | 106 | struct mutex tpm_mutex; /* tpm is processing */ |
114 | 107 | ||
115 | struct tpm_vendor_specific vendor; | 108 | struct tpm_vendor_specific vendor; |