1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright IBM Corp. 2012, 2022 |
4 | * Author(s): Holger Dengler <hd@linux.vnet.ibm.com> |
5 | */ |
6 | |
7 | #include <linux/module.h> |
8 | #include <linux/slab.h> |
9 | #include <linux/init.h> |
10 | #include <linux/err.h> |
11 | #include <linux/atomic.h> |
12 | #include <linux/uaccess.h> |
13 | #include <linux/mod_devicetable.h> |
14 | |
15 | #include "ap_bus.h" |
16 | #include "zcrypt_api.h" |
17 | #include "zcrypt_msgtype6.h" |
18 | #include "zcrypt_msgtype50.h" |
19 | #include "zcrypt_error.h" |
20 | #include "zcrypt_cex4.h" |
21 | #include "zcrypt_ccamisc.h" |
22 | #include "zcrypt_ep11misc.h" |
23 | |
24 | #define CEX4A_MIN_MOD_SIZE 1 /* 8 bits */ |
25 | #define CEX4A_MAX_MOD_SIZE_2K 256 /* 2048 bits */ |
26 | #define CEX4A_MAX_MOD_SIZE_4K 512 /* 4096 bits */ |
27 | |
28 | #define CEX4C_MIN_MOD_SIZE 16 /* 256 bits */ |
29 | #define CEX4C_MAX_MOD_SIZE 512 /* 4096 bits */ |
30 | |
31 | /* Waiting time for requests to be processed. |
32 | * Currently there are some types of request which are not deterministic. |
33 | * But the maximum time limit managed by the stomper code is set to 60sec. |
34 | * Hence we have to wait at least that time period. |
35 | */ |
36 | #define CEX4_CLEANUP_TIME (900 * HZ) |
37 | |
38 | MODULE_AUTHOR("IBM Corporation" ); |
39 | MODULE_DESCRIPTION("CEX[45678] Cryptographic Card device driver, " \ |
40 | "Copyright IBM Corp. 2022" ); |
41 | MODULE_LICENSE("GPL" ); |
42 | |
43 | static struct ap_device_id zcrypt_cex4_card_ids[] = { |
44 | { .dev_type = AP_DEVICE_TYPE_CEX4, |
45 | .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, |
46 | { .dev_type = AP_DEVICE_TYPE_CEX5, |
47 | .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, |
48 | { .dev_type = AP_DEVICE_TYPE_CEX6, |
49 | .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, |
50 | { .dev_type = AP_DEVICE_TYPE_CEX7, |
51 | .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, |
52 | { .dev_type = AP_DEVICE_TYPE_CEX8, |
53 | .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, |
54 | { /* end of list */ }, |
55 | }; |
56 | |
57 | MODULE_DEVICE_TABLE(ap, zcrypt_cex4_card_ids); |
58 | |
59 | static struct ap_device_id zcrypt_cex4_queue_ids[] = { |
60 | { .dev_type = AP_DEVICE_TYPE_CEX4, |
61 | .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, |
62 | { .dev_type = AP_DEVICE_TYPE_CEX5, |
63 | .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, |
64 | { .dev_type = AP_DEVICE_TYPE_CEX6, |
65 | .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, |
66 | { .dev_type = AP_DEVICE_TYPE_CEX7, |
67 | .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, |
68 | { .dev_type = AP_DEVICE_TYPE_CEX8, |
69 | .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, |
70 | { /* end of list */ }, |
71 | }; |
72 | |
73 | MODULE_DEVICE_TABLE(ap, zcrypt_cex4_queue_ids); |
74 | |
75 | /* |
76 | * CCA card additional device attributes |
77 | */ |
78 | static ssize_t cca_serialnr_show(struct device *dev, |
79 | struct device_attribute *attr, |
80 | char *buf) |
81 | { |
82 | struct zcrypt_card *zc = dev_get_drvdata(dev); |
83 | struct cca_info ci; |
84 | struct ap_card *ac = to_ap_card(dev); |
85 | |
86 | memset(&ci, 0, sizeof(ci)); |
87 | |
88 | if (ap_domain_index >= 0) |
89 | cca_get_info(card: ac->id, dom: ap_domain_index, ci: &ci, verify: zc->online); |
90 | |
91 | return sysfs_emit(buf, fmt: "%s\n" , ci.serial); |
92 | } |
93 | |
94 | static struct device_attribute dev_attr_cca_serialnr = |
95 | __ATTR(serialnr, 0444, cca_serialnr_show, NULL); |
96 | |
97 | static struct attribute *cca_card_attrs[] = { |
98 | &dev_attr_cca_serialnr.attr, |
99 | NULL, |
100 | }; |
101 | |
102 | static const struct attribute_group cca_card_attr_grp = { |
103 | .attrs = cca_card_attrs, |
104 | }; |
105 | |
106 | /* |
107 | * CCA queue additional device attributes |
108 | */ |
109 | static ssize_t cca_mkvps_show(struct device *dev, |
110 | struct device_attribute *attr, |
111 | char *buf) |
112 | { |
113 | struct zcrypt_queue *zq = dev_get_drvdata(dev); |
114 | int n = 0; |
115 | struct cca_info ci; |
116 | static const char * const cao_state[] = { "invalid" , "valid" }; |
117 | static const char * const new_state[] = { "empty" , "partial" , "full" }; |
118 | |
119 | memset(&ci, 0, sizeof(ci)); |
120 | |
121 | cca_get_info(card: AP_QID_CARD(zq->queue->qid), |
122 | dom: AP_QID_QUEUE(zq->queue->qid), |
123 | ci: &ci, verify: zq->online); |
124 | |
125 | if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3') |
126 | n += sysfs_emit_at(buf, at: n, fmt: "AES NEW: %s 0x%016llx\n" , |
127 | new_state[ci.new_aes_mk_state - '1'], |
128 | ci.new_aes_mkvp); |
129 | else |
130 | n += sysfs_emit_at(buf, at: n, fmt: "AES NEW: - -\n" ); |
131 | |
132 | if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2') |
133 | n += sysfs_emit_at(buf, at: n, fmt: "AES CUR: %s 0x%016llx\n" , |
134 | cao_state[ci.cur_aes_mk_state - '1'], |
135 | ci.cur_aes_mkvp); |
136 | else |
137 | n += sysfs_emit_at(buf, at: n, fmt: "AES CUR: - -\n" ); |
138 | |
139 | if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2') |
140 | n += sysfs_emit_at(buf, at: n, fmt: "AES OLD: %s 0x%016llx\n" , |
141 | cao_state[ci.old_aes_mk_state - '1'], |
142 | ci.old_aes_mkvp); |
143 | else |
144 | n += sysfs_emit_at(buf, at: n, fmt: "AES OLD: - -\n" ); |
145 | |
146 | if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3') |
147 | n += sysfs_emit_at(buf, at: n, fmt: "APKA NEW: %s 0x%016llx\n" , |
148 | new_state[ci.new_apka_mk_state - '1'], |
149 | ci.new_apka_mkvp); |
150 | else |
151 | n += sysfs_emit_at(buf, at: n, fmt: "APKA NEW: - -\n" ); |
152 | |
153 | if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2') |
154 | n += sysfs_emit_at(buf, at: n, fmt: "APKA CUR: %s 0x%016llx\n" , |
155 | cao_state[ci.cur_apka_mk_state - '1'], |
156 | ci.cur_apka_mkvp); |
157 | else |
158 | n += sysfs_emit_at(buf, at: n, fmt: "APKA CUR: - -\n" ); |
159 | |
160 | if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2') |
161 | n += sysfs_emit_at(buf, at: n, fmt: "APKA OLD: %s 0x%016llx\n" , |
162 | cao_state[ci.old_apka_mk_state - '1'], |
163 | ci.old_apka_mkvp); |
164 | else |
165 | n += sysfs_emit_at(buf, at: n, fmt: "APKA OLD: - -\n" ); |
166 | |
167 | if (ci.new_asym_mk_state >= '1' && ci.new_asym_mk_state <= '3') |
168 | n += sysfs_emit_at(buf, at: n, fmt: "ASYM NEW: %s 0x%016llx%016llx\n" , |
169 | new_state[ci.new_asym_mk_state - '1'], |
170 | *((u64 *)(ci.new_asym_mkvp)), |
171 | *((u64 *)(ci.new_asym_mkvp + sizeof(u64)))); |
172 | else |
173 | n += sysfs_emit_at(buf, at: n, fmt: "ASYM NEW: - -\n" ); |
174 | |
175 | if (ci.cur_asym_mk_state >= '1' && ci.cur_asym_mk_state <= '2') |
176 | n += sysfs_emit_at(buf, at: n, fmt: "ASYM CUR: %s 0x%016llx%016llx\n" , |
177 | cao_state[ci.cur_asym_mk_state - '1'], |
178 | *((u64 *)(ci.cur_asym_mkvp)), |
179 | *((u64 *)(ci.cur_asym_mkvp + sizeof(u64)))); |
180 | else |
181 | n += sysfs_emit_at(buf, at: n, fmt: "ASYM CUR: - -\n" ); |
182 | |
183 | if (ci.old_asym_mk_state >= '1' && ci.old_asym_mk_state <= '2') |
184 | n += sysfs_emit_at(buf, at: n, fmt: "ASYM OLD: %s 0x%016llx%016llx\n" , |
185 | cao_state[ci.old_asym_mk_state - '1'], |
186 | *((u64 *)(ci.old_asym_mkvp)), |
187 | *((u64 *)(ci.old_asym_mkvp + sizeof(u64)))); |
188 | else |
189 | n += sysfs_emit_at(buf, at: n, fmt: "ASYM OLD: - -\n" ); |
190 | |
191 | return n; |
192 | } |
193 | |
194 | static struct device_attribute dev_attr_cca_mkvps = |
195 | __ATTR(mkvps, 0444, cca_mkvps_show, NULL); |
196 | |
197 | static struct attribute *cca_queue_attrs[] = { |
198 | &dev_attr_cca_mkvps.attr, |
199 | NULL, |
200 | }; |
201 | |
202 | static const struct attribute_group cca_queue_attr_grp = { |
203 | .attrs = cca_queue_attrs, |
204 | }; |
205 | |
206 | /* |
207 | * EP11 card additional device attributes |
208 | */ |
209 | static ssize_t ep11_api_ordinalnr_show(struct device *dev, |
210 | struct device_attribute *attr, |
211 | char *buf) |
212 | { |
213 | struct zcrypt_card *zc = dev_get_drvdata(dev); |
214 | struct ep11_card_info ci; |
215 | struct ap_card *ac = to_ap_card(dev); |
216 | |
217 | memset(&ci, 0, sizeof(ci)); |
218 | |
219 | ep11_get_card_info(card: ac->id, info: &ci, verify: zc->online); |
220 | |
221 | if (ci.API_ord_nr > 0) |
222 | return sysfs_emit(buf, fmt: "%u\n" , ci.API_ord_nr); |
223 | else |
224 | return sysfs_emit(buf, fmt: "\n" ); |
225 | } |
226 | |
227 | static struct device_attribute dev_attr_ep11_api_ordinalnr = |
228 | __ATTR(API_ordinalnr, 0444, ep11_api_ordinalnr_show, NULL); |
229 | |
230 | static ssize_t ep11_fw_version_show(struct device *dev, |
231 | struct device_attribute *attr, |
232 | char *buf) |
233 | { |
234 | struct zcrypt_card *zc = dev_get_drvdata(dev); |
235 | struct ep11_card_info ci; |
236 | struct ap_card *ac = to_ap_card(dev); |
237 | |
238 | memset(&ci, 0, sizeof(ci)); |
239 | |
240 | ep11_get_card_info(card: ac->id, info: &ci, verify: zc->online); |
241 | |
242 | if (ci.FW_version > 0) |
243 | return sysfs_emit(buf, fmt: "%d.%d\n" , |
244 | (int)(ci.FW_version >> 8), |
245 | (int)(ci.FW_version & 0xFF)); |
246 | else |
247 | return sysfs_emit(buf, fmt: "\n" ); |
248 | } |
249 | |
250 | static struct device_attribute dev_attr_ep11_fw_version = |
251 | __ATTR(FW_version, 0444, ep11_fw_version_show, NULL); |
252 | |
253 | static ssize_t ep11_serialnr_show(struct device *dev, |
254 | struct device_attribute *attr, |
255 | char *buf) |
256 | { |
257 | struct zcrypt_card *zc = dev_get_drvdata(dev); |
258 | struct ep11_card_info ci; |
259 | struct ap_card *ac = to_ap_card(dev); |
260 | |
261 | memset(&ci, 0, sizeof(ci)); |
262 | |
263 | ep11_get_card_info(card: ac->id, info: &ci, verify: zc->online); |
264 | |
265 | if (ci.serial[0]) |
266 | return sysfs_emit(buf, fmt: "%16.16s\n" , ci.serial); |
267 | else |
268 | return sysfs_emit(buf, fmt: "\n" ); |
269 | } |
270 | |
271 | static struct device_attribute dev_attr_ep11_serialnr = |
272 | __ATTR(serialnr, 0444, ep11_serialnr_show, NULL); |
273 | |
274 | static const struct { |
275 | int mode_bit; |
276 | const char *mode_txt; |
277 | } ep11_op_modes[] = { |
278 | { 0, "FIPS2009" }, |
279 | { 1, "BSI2009" }, |
280 | { 2, "FIPS2011" }, |
281 | { 3, "BSI2011" }, |
282 | { 4, "SIGG-IMPORT" }, |
283 | { 5, "SIGG" }, |
284 | { 6, "BSICC2017" }, |
285 | { 7, "FIPS2021" }, |
286 | { 8, "FIPS2024" }, |
287 | { 0, NULL } |
288 | }; |
289 | |
290 | static ssize_t ep11_card_op_modes_show(struct device *dev, |
291 | struct device_attribute *attr, |
292 | char *buf) |
293 | { |
294 | struct zcrypt_card *zc = dev_get_drvdata(dev); |
295 | int i, n = 0; |
296 | struct ep11_card_info ci; |
297 | struct ap_card *ac = to_ap_card(dev); |
298 | |
299 | memset(&ci, 0, sizeof(ci)); |
300 | |
301 | ep11_get_card_info(card: ac->id, info: &ci, verify: zc->online); |
302 | |
303 | for (i = 0; ep11_op_modes[i].mode_txt; i++) { |
304 | if (ci.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) { |
305 | if (n > 0) |
306 | buf[n++] = ' '; |
307 | n += sysfs_emit_at(buf, at: n, fmt: "%s" , |
308 | ep11_op_modes[i].mode_txt); |
309 | } |
310 | } |
311 | n += sysfs_emit_at(buf, at: n, fmt: "\n" ); |
312 | |
313 | return n; |
314 | } |
315 | |
316 | static struct device_attribute dev_attr_ep11_card_op_modes = |
317 | __ATTR(op_modes, 0444, ep11_card_op_modes_show, NULL); |
318 | |
319 | static struct attribute *ep11_card_attrs[] = { |
320 | &dev_attr_ep11_api_ordinalnr.attr, |
321 | &dev_attr_ep11_fw_version.attr, |
322 | &dev_attr_ep11_serialnr.attr, |
323 | &dev_attr_ep11_card_op_modes.attr, |
324 | NULL, |
325 | }; |
326 | |
327 | static const struct attribute_group ep11_card_attr_grp = { |
328 | .attrs = ep11_card_attrs, |
329 | }; |
330 | |
331 | /* |
332 | * EP11 queue additional device attributes |
333 | */ |
334 | |
335 | static ssize_t ep11_mkvps_show(struct device *dev, |
336 | struct device_attribute *attr, |
337 | char *buf) |
338 | { |
339 | struct zcrypt_queue *zq = dev_get_drvdata(dev); |
340 | int n = 0; |
341 | struct ep11_domain_info di; |
342 | static const char * const cwk_state[] = { "invalid" , "valid" }; |
343 | static const char * const nwk_state[] = { "empty" , "uncommitted" , |
344 | "committed" }; |
345 | |
346 | memset(&di, 0, sizeof(di)); |
347 | |
348 | if (zq->online) |
349 | ep11_get_domain_info(card: AP_QID_CARD(zq->queue->qid), |
350 | domain: AP_QID_QUEUE(zq->queue->qid), |
351 | info: &di); |
352 | |
353 | if (di.cur_wk_state == '0') { |
354 | n = sysfs_emit(buf, fmt: "WK CUR: %s -\n" , |
355 | cwk_state[di.cur_wk_state - '0']); |
356 | } else if (di.cur_wk_state == '1') { |
357 | n = sysfs_emit(buf, fmt: "WK CUR: %s 0x" , |
358 | cwk_state[di.cur_wk_state - '0']); |
359 | bin2hex(dst: buf + n, src: di.cur_wkvp, count: sizeof(di.cur_wkvp)); |
360 | n += 2 * sizeof(di.cur_wkvp); |
361 | n += sysfs_emit_at(buf, at: n, fmt: "\n" ); |
362 | } else { |
363 | n = sysfs_emit(buf, fmt: "WK CUR: - -\n" ); |
364 | } |
365 | |
366 | if (di.new_wk_state == '0') { |
367 | n += sysfs_emit_at(buf, at: n, fmt: "WK NEW: %s -\n" , |
368 | nwk_state[di.new_wk_state - '0']); |
369 | } else if (di.new_wk_state >= '1' && di.new_wk_state <= '2') { |
370 | n += sysfs_emit_at(buf, at: n, fmt: "WK NEW: %s 0x" , |
371 | nwk_state[di.new_wk_state - '0']); |
372 | bin2hex(dst: buf + n, src: di.new_wkvp, count: sizeof(di.new_wkvp)); |
373 | n += 2 * sizeof(di.new_wkvp); |
374 | n += sysfs_emit_at(buf, at: n, fmt: "\n" ); |
375 | } else { |
376 | n += sysfs_emit_at(buf, at: n, fmt: "WK NEW: - -\n" ); |
377 | } |
378 | |
379 | return n; |
380 | } |
381 | |
382 | static struct device_attribute dev_attr_ep11_mkvps = |
383 | __ATTR(mkvps, 0444, ep11_mkvps_show, NULL); |
384 | |
385 | static ssize_t ep11_queue_op_modes_show(struct device *dev, |
386 | struct device_attribute *attr, |
387 | char *buf) |
388 | { |
389 | struct zcrypt_queue *zq = dev_get_drvdata(dev); |
390 | int i, n = 0; |
391 | struct ep11_domain_info di; |
392 | |
393 | memset(&di, 0, sizeof(di)); |
394 | |
395 | if (zq->online) |
396 | ep11_get_domain_info(card: AP_QID_CARD(zq->queue->qid), |
397 | domain: AP_QID_QUEUE(zq->queue->qid), |
398 | info: &di); |
399 | |
400 | for (i = 0; ep11_op_modes[i].mode_txt; i++) { |
401 | if (di.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) { |
402 | if (n > 0) |
403 | buf[n++] = ' '; |
404 | n += sysfs_emit_at(buf, at: n, fmt: "%s" , |
405 | ep11_op_modes[i].mode_txt); |
406 | } |
407 | } |
408 | n += sysfs_emit_at(buf, at: n, fmt: "\n" ); |
409 | |
410 | return n; |
411 | } |
412 | |
413 | static struct device_attribute dev_attr_ep11_queue_op_modes = |
414 | __ATTR(op_modes, 0444, ep11_queue_op_modes_show, NULL); |
415 | |
416 | static struct attribute *ep11_queue_attrs[] = { |
417 | &dev_attr_ep11_mkvps.attr, |
418 | &dev_attr_ep11_queue_op_modes.attr, |
419 | NULL, |
420 | }; |
421 | |
422 | static const struct attribute_group ep11_queue_attr_grp = { |
423 | .attrs = ep11_queue_attrs, |
424 | }; |
425 | |
426 | /* |
427 | * Probe function for CEX[45678] card device. It always |
428 | * accepts the AP device since the bus_match already checked |
429 | * the hardware type. |
430 | * @ap_dev: pointer to the AP device. |
431 | */ |
432 | static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) |
433 | { |
434 | /* |
435 | * Normalized speed ratings per crypto adapter |
436 | * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY |
437 | */ |
438 | static const int CEX4A_SPEED_IDX[NUM_OPS] = { |
439 | 14, 19, 249, 42, 228, 1458, 0, 0}; |
440 | static const int CEX5A_SPEED_IDX[NUM_OPS] = { |
441 | 8, 9, 20, 18, 66, 458, 0, 0}; |
442 | static const int CEX6A_SPEED_IDX[NUM_OPS] = { |
443 | 6, 9, 20, 17, 65, 438, 0, 0}; |
444 | static const int CEX7A_SPEED_IDX[NUM_OPS] = { |
445 | 6, 8, 17, 15, 54, 362, 0, 0}; |
446 | static const int CEX8A_SPEED_IDX[NUM_OPS] = { |
447 | 6, 8, 17, 15, 54, 362, 0, 0}; |
448 | |
449 | static const int CEX4C_SPEED_IDX[NUM_OPS] = { |
450 | 59, 69, 308, 83, 278, 2204, 209, 40}; |
451 | static const int CEX5C_SPEED_IDX[] = { |
452 | 24, 31, 50, 37, 90, 479, 27, 10}; |
453 | static const int CEX6C_SPEED_IDX[NUM_OPS] = { |
454 | 16, 20, 32, 27, 77, 455, 24, 9}; |
455 | static const int CEX7C_SPEED_IDX[NUM_OPS] = { |
456 | 14, 16, 26, 23, 64, 376, 23, 8}; |
457 | static const int CEX8C_SPEED_IDX[NUM_OPS] = { |
458 | 14, 16, 26, 23, 64, 376, 23, 8}; |
459 | |
460 | static const int CEX4P_SPEED_IDX[NUM_OPS] = { |
461 | 0, 0, 0, 0, 0, 0, 0, 50}; |
462 | static const int CEX5P_SPEED_IDX[NUM_OPS] = { |
463 | 0, 0, 0, 0, 0, 0, 0, 10}; |
464 | static const int CEX6P_SPEED_IDX[NUM_OPS] = { |
465 | 0, 0, 0, 0, 0, 0, 0, 9}; |
466 | static const int CEX7P_SPEED_IDX[NUM_OPS] = { |
467 | 0, 0, 0, 0, 0, 0, 0, 8}; |
468 | static const int CEX8P_SPEED_IDX[NUM_OPS] = { |
469 | 0, 0, 0, 0, 0, 0, 0, 8}; |
470 | |
471 | struct ap_card *ac = to_ap_card(&ap_dev->device); |
472 | struct zcrypt_card *zc; |
473 | int rc = 0; |
474 | |
475 | zc = zcrypt_card_alloc(); |
476 | if (!zc) |
477 | return -ENOMEM; |
478 | zc->card = ac; |
479 | dev_set_drvdata(dev: &ap_dev->device, data: zc); |
480 | if (ap_test_bit(ptr: &ac->functions, AP_FUNC_ACCEL)) { |
481 | if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) { |
482 | zc->type_string = "CEX4A" ; |
483 | zc->user_space_type = ZCRYPT_CEX4; |
484 | zc->speed_rating = CEX4A_SPEED_IDX; |
485 | } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) { |
486 | zc->type_string = "CEX5A" ; |
487 | zc->user_space_type = ZCRYPT_CEX5; |
488 | zc->speed_rating = CEX5A_SPEED_IDX; |
489 | } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) { |
490 | zc->type_string = "CEX6A" ; |
491 | zc->user_space_type = ZCRYPT_CEX6; |
492 | zc->speed_rating = CEX6A_SPEED_IDX; |
493 | } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) { |
494 | zc->type_string = "CEX7A" ; |
495 | zc->speed_rating = CEX7A_SPEED_IDX; |
496 | /* wrong user space type, just for compatibility |
497 | * with the ZCRYPT_STATUS_MASK ioctl. |
498 | */ |
499 | zc->user_space_type = ZCRYPT_CEX6; |
500 | } else { |
501 | zc->type_string = "CEX8A" ; |
502 | zc->speed_rating = CEX8A_SPEED_IDX; |
503 | /* wrong user space type, just for compatibility |
504 | * with the ZCRYPT_STATUS_MASK ioctl. |
505 | */ |
506 | zc->user_space_type = ZCRYPT_CEX6; |
507 | } |
508 | zc->min_mod_size = CEX4A_MIN_MOD_SIZE; |
509 | if (ap_test_bit(ptr: &ac->functions, AP_FUNC_MEX4K) && |
510 | ap_test_bit(ptr: &ac->functions, AP_FUNC_CRT4K)) { |
511 | zc->max_mod_size = CEX4A_MAX_MOD_SIZE_4K; |
512 | zc->max_exp_bit_length = |
513 | CEX4A_MAX_MOD_SIZE_4K; |
514 | } else { |
515 | zc->max_mod_size = CEX4A_MAX_MOD_SIZE_2K; |
516 | zc->max_exp_bit_length = |
517 | CEX4A_MAX_MOD_SIZE_2K; |
518 | } |
519 | } else if (ap_test_bit(ptr: &ac->functions, AP_FUNC_COPRO)) { |
520 | if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) { |
521 | zc->type_string = "CEX4C" ; |
522 | zc->speed_rating = CEX4C_SPEED_IDX; |
523 | /* wrong user space type, must be CEX3C |
524 | * just keep it for cca compatibility |
525 | */ |
526 | zc->user_space_type = ZCRYPT_CEX3C; |
527 | } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) { |
528 | zc->type_string = "CEX5C" ; |
529 | zc->speed_rating = CEX5C_SPEED_IDX; |
530 | /* wrong user space type, must be CEX3C |
531 | * just keep it for cca compatibility |
532 | */ |
533 | zc->user_space_type = ZCRYPT_CEX3C; |
534 | } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) { |
535 | zc->type_string = "CEX6C" ; |
536 | zc->speed_rating = CEX6C_SPEED_IDX; |
537 | /* wrong user space type, must be CEX3C |
538 | * just keep it for cca compatibility |
539 | */ |
540 | zc->user_space_type = ZCRYPT_CEX3C; |
541 | } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) { |
542 | zc->type_string = "CEX7C" ; |
543 | zc->speed_rating = CEX7C_SPEED_IDX; |
544 | /* wrong user space type, must be CEX3C |
545 | * just keep it for cca compatibility |
546 | */ |
547 | zc->user_space_type = ZCRYPT_CEX3C; |
548 | } else { |
549 | zc->type_string = "CEX8C" ; |
550 | zc->speed_rating = CEX8C_SPEED_IDX; |
551 | /* wrong user space type, must be CEX3C |
552 | * just keep it for cca compatibility |
553 | */ |
554 | zc->user_space_type = ZCRYPT_CEX3C; |
555 | } |
556 | zc->min_mod_size = CEX4C_MIN_MOD_SIZE; |
557 | zc->max_mod_size = CEX4C_MAX_MOD_SIZE; |
558 | zc->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; |
559 | } else if (ap_test_bit(ptr: &ac->functions, AP_FUNC_EP11)) { |
560 | if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) { |
561 | zc->type_string = "CEX4P" ; |
562 | zc->user_space_type = ZCRYPT_CEX4; |
563 | zc->speed_rating = CEX4P_SPEED_IDX; |
564 | } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) { |
565 | zc->type_string = "CEX5P" ; |
566 | zc->user_space_type = ZCRYPT_CEX5; |
567 | zc->speed_rating = CEX5P_SPEED_IDX; |
568 | } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) { |
569 | zc->type_string = "CEX6P" ; |
570 | zc->user_space_type = ZCRYPT_CEX6; |
571 | zc->speed_rating = CEX6P_SPEED_IDX; |
572 | } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) { |
573 | zc->type_string = "CEX7P" ; |
574 | zc->speed_rating = CEX7P_SPEED_IDX; |
575 | /* wrong user space type, just for compatibility |
576 | * with the ZCRYPT_STATUS_MASK ioctl. |
577 | */ |
578 | zc->user_space_type = ZCRYPT_CEX6; |
579 | } else { |
580 | zc->type_string = "CEX8P" ; |
581 | zc->speed_rating = CEX8P_SPEED_IDX; |
582 | /* wrong user space type, just for compatibility |
583 | * with the ZCRYPT_STATUS_MASK ioctl. |
584 | */ |
585 | zc->user_space_type = ZCRYPT_CEX6; |
586 | } |
587 | zc->min_mod_size = CEX4C_MIN_MOD_SIZE; |
588 | zc->max_mod_size = CEX4C_MAX_MOD_SIZE; |
589 | zc->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; |
590 | } else { |
591 | zcrypt_card_free(zc); |
592 | return -ENODEV; |
593 | } |
594 | zc->online = 1; |
595 | |
596 | rc = zcrypt_card_register(zc); |
597 | if (rc) { |
598 | zcrypt_card_free(zc); |
599 | return rc; |
600 | } |
601 | |
602 | if (ap_test_bit(ptr: &ac->functions, AP_FUNC_COPRO)) { |
603 | rc = sysfs_create_group(kobj: &ap_dev->device.kobj, |
604 | grp: &cca_card_attr_grp); |
605 | if (rc) { |
606 | zcrypt_card_unregister(zc); |
607 | zcrypt_card_free(zc); |
608 | } |
609 | } else if (ap_test_bit(ptr: &ac->functions, AP_FUNC_EP11)) { |
610 | rc = sysfs_create_group(kobj: &ap_dev->device.kobj, |
611 | grp: &ep11_card_attr_grp); |
612 | if (rc) { |
613 | zcrypt_card_unregister(zc); |
614 | zcrypt_card_free(zc); |
615 | } |
616 | } |
617 | |
618 | return rc; |
619 | } |
620 | |
621 | /* |
622 | * This is called to remove the CEX[45678] card driver |
623 | * information if an AP card device is removed. |
624 | */ |
625 | static void zcrypt_cex4_card_remove(struct ap_device *ap_dev) |
626 | { |
627 | struct zcrypt_card *zc = dev_get_drvdata(dev: &ap_dev->device); |
628 | struct ap_card *ac = to_ap_card(&ap_dev->device); |
629 | |
630 | if (ap_test_bit(ptr: &ac->functions, AP_FUNC_COPRO)) |
631 | sysfs_remove_group(kobj: &ap_dev->device.kobj, grp: &cca_card_attr_grp); |
632 | else if (ap_test_bit(ptr: &ac->functions, AP_FUNC_EP11)) |
633 | sysfs_remove_group(kobj: &ap_dev->device.kobj, grp: &ep11_card_attr_grp); |
634 | |
635 | zcrypt_card_unregister(zc); |
636 | } |
637 | |
638 | static struct ap_driver zcrypt_cex4_card_driver = { |
639 | .probe = zcrypt_cex4_card_probe, |
640 | .remove = zcrypt_cex4_card_remove, |
641 | .ids = zcrypt_cex4_card_ids, |
642 | .flags = AP_DRIVER_FLAG_DEFAULT, |
643 | }; |
644 | |
645 | /* |
646 | * Probe function for CEX[45678] queue device. It always |
647 | * accepts the AP device since the bus_match already checked |
648 | * the hardware type. |
649 | * @ap_dev: pointer to the AP device. |
650 | */ |
651 | static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev) |
652 | { |
653 | struct ap_queue *aq = to_ap_queue(&ap_dev->device); |
654 | struct zcrypt_queue *zq; |
655 | int rc; |
656 | |
657 | if (ap_test_bit(ptr: &aq->card->functions, AP_FUNC_ACCEL)) { |
658 | zq = zcrypt_queue_alloc(aq->card->maxmsgsize); |
659 | if (!zq) |
660 | return -ENOMEM; |
661 | zq->ops = zcrypt_msgtype(MSGTYPE50_NAME, |
662 | MSGTYPE50_VARIANT_DEFAULT); |
663 | } else if (ap_test_bit(ptr: &aq->card->functions, AP_FUNC_COPRO)) { |
664 | zq = zcrypt_queue_alloc(aq->card->maxmsgsize); |
665 | if (!zq) |
666 | return -ENOMEM; |
667 | zq->ops = zcrypt_msgtype(MSGTYPE06_NAME, |
668 | MSGTYPE06_VARIANT_DEFAULT); |
669 | } else if (ap_test_bit(ptr: &aq->card->functions, AP_FUNC_EP11)) { |
670 | zq = zcrypt_queue_alloc(aq->card->maxmsgsize); |
671 | if (!zq) |
672 | return -ENOMEM; |
673 | zq->ops = zcrypt_msgtype(MSGTYPE06_NAME, |
674 | MSGTYPE06_VARIANT_EP11); |
675 | } else { |
676 | return -ENODEV; |
677 | } |
678 | |
679 | zq->queue = aq; |
680 | zq->online = 1; |
681 | atomic_set(v: &zq->load, i: 0); |
682 | ap_queue_init_state(aq); |
683 | ap_queue_init_reply(aq, ap_msg: &zq->reply); |
684 | aq->request_timeout = CEX4_CLEANUP_TIME; |
685 | dev_set_drvdata(dev: &ap_dev->device, data: zq); |
686 | rc = zcrypt_queue_register(zq); |
687 | if (rc) { |
688 | zcrypt_queue_free(zq); |
689 | return rc; |
690 | } |
691 | |
692 | if (ap_test_bit(ptr: &aq->card->functions, AP_FUNC_COPRO)) { |
693 | rc = sysfs_create_group(kobj: &ap_dev->device.kobj, |
694 | grp: &cca_queue_attr_grp); |
695 | if (rc) { |
696 | zcrypt_queue_unregister(zq); |
697 | zcrypt_queue_free(zq); |
698 | } |
699 | } else if (ap_test_bit(ptr: &aq->card->functions, AP_FUNC_EP11)) { |
700 | rc = sysfs_create_group(kobj: &ap_dev->device.kobj, |
701 | grp: &ep11_queue_attr_grp); |
702 | if (rc) { |
703 | zcrypt_queue_unregister(zq); |
704 | zcrypt_queue_free(zq); |
705 | } |
706 | } |
707 | |
708 | return rc; |
709 | } |
710 | |
711 | /* |
712 | * This is called to remove the CEX[45678] queue driver |
713 | * information if an AP queue device is removed. |
714 | */ |
715 | static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev) |
716 | { |
717 | struct zcrypt_queue *zq = dev_get_drvdata(dev: &ap_dev->device); |
718 | struct ap_queue *aq = to_ap_queue(&ap_dev->device); |
719 | |
720 | if (ap_test_bit(ptr: &aq->card->functions, AP_FUNC_COPRO)) |
721 | sysfs_remove_group(kobj: &ap_dev->device.kobj, grp: &cca_queue_attr_grp); |
722 | else if (ap_test_bit(ptr: &aq->card->functions, AP_FUNC_EP11)) |
723 | sysfs_remove_group(kobj: &ap_dev->device.kobj, grp: &ep11_queue_attr_grp); |
724 | |
725 | zcrypt_queue_unregister(zq); |
726 | } |
727 | |
728 | static struct ap_driver zcrypt_cex4_queue_driver = { |
729 | .probe = zcrypt_cex4_queue_probe, |
730 | .remove = zcrypt_cex4_queue_remove, |
731 | .ids = zcrypt_cex4_queue_ids, |
732 | .flags = AP_DRIVER_FLAG_DEFAULT, |
733 | }; |
734 | |
735 | int __init zcrypt_cex4_init(void) |
736 | { |
737 | int rc; |
738 | |
739 | rc = ap_driver_register(&zcrypt_cex4_card_driver, |
740 | THIS_MODULE, "cex4card" ); |
741 | if (rc) |
742 | return rc; |
743 | |
744 | rc = ap_driver_register(&zcrypt_cex4_queue_driver, |
745 | THIS_MODULE, "cex4queue" ); |
746 | if (rc) |
747 | ap_driver_unregister(&zcrypt_cex4_card_driver); |
748 | |
749 | return rc; |
750 | } |
751 | |
752 | void __exit zcrypt_cex4_exit(void) |
753 | { |
754 | ap_driver_unregister(&zcrypt_cex4_queue_driver); |
755 | ap_driver_unregister(&zcrypt_cex4_card_driver); |
756 | } |
757 | |
758 | module_init(zcrypt_cex4_init); |
759 | module_exit(zcrypt_cex4_exit); |
760 | |