diff options
author | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 2018-11-04 14:18:46 -0500 |
---|---|---|
committer | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 2019-02-13 02:48:33 -0500 |
commit | 719b7d81f2048477f89f7303e2b4ddec8197e6e3 (patch) | |
tree | da5983336e23c58d3dba2a85326983baf54a07ce | |
parent | 2f257402ee981720d65080b1e3ce19f693f5c9c3 (diff) |
tpm: introduce tpm_chip_start() and tpm_chip_stop()
Encapsulate power gating and locality functionality to tpm_chip_start()
and tpm_chip_stop() in order to clean up the branching mess in
tpm_transmit().
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
Reviewed-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Tested-by: Alexander Steffen <Alexander.Steffen@infineon.com>
-rw-r--r-- | drivers/char/tpm/tpm-chip.c | 111 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 84 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 2 |
3 files changed, 116 insertions, 81 deletions
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 157505b0f755..ed673c7216a0 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c | |||
@@ -37,6 +37,117 @@ struct class *tpm_class; | |||
37 | struct class *tpmrm_class; | 37 | struct class *tpmrm_class; |
38 | dev_t tpm_devt; | 38 | dev_t tpm_devt; |
39 | 39 | ||
40 | static int tpm_request_locality(struct tpm_chip *chip, unsigned int flags) | ||
41 | { | ||
42 | int rc; | ||
43 | |||
44 | if (flags & TPM_TRANSMIT_NESTED) | ||
45 | return 0; | ||
46 | |||
47 | if (!chip->ops->request_locality) | ||
48 | return 0; | ||
49 | |||
50 | rc = chip->ops->request_locality(chip, 0); | ||
51 | if (rc < 0) | ||
52 | return rc; | ||
53 | |||
54 | chip->locality = rc; | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static void tpm_relinquish_locality(struct tpm_chip *chip, unsigned int flags) | ||
59 | { | ||
60 | int rc; | ||
61 | |||
62 | if (flags & TPM_TRANSMIT_NESTED) | ||
63 | return; | ||
64 | |||
65 | if (!chip->ops->relinquish_locality) | ||
66 | return; | ||
67 | |||
68 | rc = chip->ops->relinquish_locality(chip, chip->locality); | ||
69 | if (rc) | ||
70 | dev_err(&chip->dev, "%s: : error %d\n", __func__, rc); | ||
71 | |||
72 | chip->locality = -1; | ||
73 | } | ||
74 | |||
75 | static int tpm_cmd_ready(struct tpm_chip *chip, unsigned int flags) | ||
76 | { | ||
77 | if (flags & TPM_TRANSMIT_NESTED) | ||
78 | return 0; | ||
79 | |||
80 | if (!chip->ops->cmd_ready) | ||
81 | return 0; | ||
82 | |||
83 | return chip->ops->cmd_ready(chip); | ||
84 | } | ||
85 | |||
86 | static int tpm_go_idle(struct tpm_chip *chip, unsigned int flags) | ||
87 | { | ||
88 | if (flags & TPM_TRANSMIT_NESTED) | ||
89 | return 0; | ||
90 | |||
91 | if (!chip->ops->go_idle) | ||
92 | return 0; | ||
93 | |||
94 | return chip->ops->go_idle(chip); | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * tpm_chip_start() - power on the TPM | ||
99 | * @chip: a TPM chip to use | ||
100 | * @flags: TPM transmit flags | ||
101 | * | ||
102 | * Return: | ||
103 | * * The response length - OK | ||
104 | * * -errno - A system error | ||
105 | */ | ||
106 | int tpm_chip_start(struct tpm_chip *chip, unsigned int flags) | ||
107 | { | ||
108 | int ret; | ||
109 | |||
110 | if (chip->ops->clk_enable) | ||
111 | chip->ops->clk_enable(chip, true); | ||
112 | |||
113 | if (chip->locality == -1) { | ||
114 | ret = tpm_request_locality(chip, flags); | ||
115 | if (ret) { | ||
116 | chip->ops->clk_enable(chip, false); | ||
117 | return ret; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | ret = tpm_cmd_ready(chip, flags); | ||
122 | if (ret) { | ||
123 | tpm_relinquish_locality(chip, flags); | ||
124 | if (chip->ops->clk_enable) | ||
125 | chip->ops->clk_enable(chip, false); | ||
126 | return ret; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(tpm_chip_start); | ||
132 | |||
133 | /** | ||
134 | * tpm_chip_stop() - power off the TPM | ||
135 | * @chip: a TPM chip to use | ||
136 | * @flags: TPM transmit flags | ||
137 | * | ||
138 | * Return: | ||
139 | * * The response length - OK | ||
140 | * * -errno - A system error | ||
141 | */ | ||
142 | void tpm_chip_stop(struct tpm_chip *chip, unsigned int flags) | ||
143 | { | ||
144 | tpm_go_idle(chip, flags); | ||
145 | tpm_relinquish_locality(chip, flags); | ||
146 | if (chip->ops->clk_enable) | ||
147 | chip->ops->clk_enable(chip, false); | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(tpm_chip_stop); | ||
150 | |||
40 | /** | 151 | /** |
41 | * tpm_try_get_ops() - Get a ref to the tpm_chip | 152 | * tpm_try_get_ops() - Get a ref to the tpm_chip |
42 | * @chip: Chip to ref | 153 | * @chip: Chip to ref |
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 54a15f59e175..038a4767d9d6 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -62,64 +62,6 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) | |||
62 | } | 62 | } |
63 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); | 63 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); |
64 | 64 | ||
65 | static int tpm_request_locality(struct tpm_chip *chip, unsigned int flags) | ||
66 | { | ||
67 | int rc; | ||
68 | |||
69 | if (flags & TPM_TRANSMIT_NESTED) | ||
70 | return 0; | ||
71 | |||
72 | if (!chip->ops->request_locality) | ||
73 | return 0; | ||
74 | |||
75 | rc = chip->ops->request_locality(chip, 0); | ||
76 | if (rc < 0) | ||
77 | return rc; | ||
78 | |||
79 | chip->locality = rc; | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static void tpm_relinquish_locality(struct tpm_chip *chip, unsigned int flags) | ||
85 | { | ||
86 | int rc; | ||
87 | |||
88 | if (flags & TPM_TRANSMIT_NESTED) | ||
89 | return; | ||
90 | |||
91 | if (!chip->ops->relinquish_locality) | ||
92 | return; | ||
93 | |||
94 | rc = chip->ops->relinquish_locality(chip, chip->locality); | ||
95 | if (rc) | ||
96 | dev_err(&chip->dev, "%s: : error %d\n", __func__, rc); | ||
97 | |||
98 | chip->locality = -1; | ||
99 | } | ||
100 | |||
101 | static int tpm_cmd_ready(struct tpm_chip *chip, unsigned int flags) | ||
102 | { | ||
103 | if (flags & TPM_TRANSMIT_NESTED) | ||
104 | return 0; | ||
105 | |||
106 | if (!chip->ops->cmd_ready) | ||
107 | return 0; | ||
108 | |||
109 | return chip->ops->cmd_ready(chip); | ||
110 | } | ||
111 | |||
112 | static int tpm_go_idle(struct tpm_chip *chip, unsigned int flags) | ||
113 | { | ||
114 | if (flags & TPM_TRANSMIT_NESTED) | ||
115 | return 0; | ||
116 | |||
117 | if (!chip->ops->go_idle) | ||
118 | return 0; | ||
119 | |||
120 | return chip->ops->go_idle(chip); | ||
121 | } | ||
122 | |||
123 | static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz, | 65 | static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz, |
124 | unsigned int flags) | 66 | unsigned int flags) |
125 | { | 67 | { |
@@ -221,7 +163,6 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz, | |||
221 | /* space for header and handles */ | 163 | /* space for header and handles */ |
222 | u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)]; | 164 | u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)]; |
223 | unsigned int delay_msec = TPM2_DURATION_SHORT; | 165 | unsigned int delay_msec = TPM2_DURATION_SHORT; |
224 | bool has_locality = false; | ||
225 | u32 rc = 0; | 166 | u32 rc = 0; |
226 | ssize_t ret; | 167 | ssize_t ret; |
227 | const size_t save_size = min(sizeof(save), bufsiz); | 168 | const size_t save_size = min(sizeof(save), bufsiz); |
@@ -236,32 +177,13 @@ ssize_t tpm_transmit(struct tpm_chip *chip, u8 *buf, size_t bufsiz, | |||
236 | memcpy(save, buf, save_size); | 177 | memcpy(save, buf, save_size); |
237 | 178 | ||
238 | for (;;) { | 179 | for (;;) { |
239 | if (chip->ops->clk_enable != NULL) | 180 | ret = tpm_chip_start(chip, flags); |
240 | chip->ops->clk_enable(chip, true); | ||
241 | |||
242 | if (chip->locality == -1) { | ||
243 | ret = tpm_request_locality(chip, flags); | ||
244 | if (ret) | ||
245 | goto out_locality; | ||
246 | has_locality = true; | ||
247 | } | ||
248 | |||
249 | ret = tpm_cmd_ready(chip, flags); | ||
250 | if (ret) | 181 | if (ret) |
251 | goto out_locality; | 182 | return ret; |
252 | 183 | ||
253 | ret = tpm_try_transmit(chip, buf, bufsiz, flags); | 184 | ret = tpm_try_transmit(chip, buf, bufsiz, flags); |
254 | 185 | ||
255 | /* This may fail but do not override ret. */ | 186 | tpm_chip_stop(chip, flags); |
256 | tpm_go_idle(chip, flags); | ||
257 | |||
258 | out_locality: | ||
259 | if (has_locality) | ||
260 | tpm_relinquish_locality(chip, flags); | ||
261 | |||
262 | if (chip->ops->clk_enable != NULL) | ||
263 | chip->ops->clk_enable(chip, false); | ||
264 | |||
265 | if (ret < 0) | 187 | if (ret < 0) |
266 | break; | 188 | break; |
267 | rc = be32_to_cpu(header->return_code); | 189 | rc = be32_to_cpu(header->return_code); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 18ef432a3fde..2d6d934f1c8b 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -523,6 +523,8 @@ static inline void tpm_msleep(unsigned int delay_msec) | |||
523 | delay_msec * 1000); | 523 | delay_msec * 1000); |
524 | }; | 524 | }; |
525 | 525 | ||
526 | int tpm_chip_start(struct tpm_chip *chip, unsigned int flags); | ||
527 | void tpm_chip_stop(struct tpm_chip *chip, unsigned int flags); | ||
526 | struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); | 528 | struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); |
527 | __must_check int tpm_try_get_ops(struct tpm_chip *chip); | 529 | __must_check int tpm_try_get_ops(struct tpm_chip *chip); |
528 | void tpm_put_ops(struct tpm_chip *chip); | 530 | void tpm_put_ops(struct tpm_chip *chip); |