1 | /***********************license start************************************ |
2 | * Copyright (c) 2003-2017 Cavium, Inc. |
3 | * All rights reserved. |
4 | * |
5 | * License: one of 'Cavium License' or 'GNU General Public License Version 2' |
6 | * |
7 | * This file is provided under the terms of the Cavium License (see below) |
8 | * or under the terms of GNU General Public License, Version 2, as |
9 | * published by the Free Software Foundation. When using or redistributing |
10 | * this file, you may do so under either license. |
11 | * |
12 | * Cavium License: Redistribution and use in source and binary forms, with |
13 | * or without modification, are permitted provided that the following |
14 | * conditions are met: |
15 | * |
16 | * * Redistributions of source code must retain the above copyright |
17 | * notice, this list of conditions and the following disclaimer. |
18 | * |
19 | * * Redistributions in binary form must reproduce the above |
20 | * copyright notice, this list of conditions and the following |
21 | * disclaimer in the documentation and/or other materials provided |
22 | * with the distribution. |
23 | * |
24 | * * Neither the name of Cavium Inc. nor the names of its contributors may be |
25 | * used to endorse or promote products derived from this software without |
26 | * specific prior written permission. |
27 | * |
28 | * This Software, including technical data, may be subject to U.S. export |
29 | * control laws, including the U.S. Export Administration Act and its |
30 | * associated regulations, and may be subject to export or import |
31 | * regulations in other countries. |
32 | * |
33 | * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" |
34 | * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS |
35 | * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH |
36 | * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY |
37 | * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT |
38 | * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) |
39 | * WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A |
40 | * PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET |
41 | * ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE |
42 | * ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES |
43 | * WITH YOU. |
44 | ***********************license end**************************************/ |
45 | |
46 | #include "common.h" |
47 | #include "zip_crypto.h" |
48 | |
49 | #define DRV_NAME "ThunderX-ZIP" |
50 | |
51 | static struct zip_device *zip_dev[MAX_ZIP_DEVICES]; |
52 | |
53 | static const struct pci_device_id zip_id_table[] = { |
54 | { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDERX_ZIP) }, |
55 | { 0, } |
56 | }; |
57 | |
58 | static void zip_debugfs_init(void); |
59 | static void zip_debugfs_exit(void); |
60 | static int zip_register_compression_device(void); |
61 | static void zip_unregister_compression_device(void); |
62 | |
63 | void zip_reg_write(u64 val, u64 __iomem *addr) |
64 | { |
65 | writeq(val, addr); |
66 | } |
67 | |
68 | u64 zip_reg_read(u64 __iomem *addr) |
69 | { |
70 | return readq(addr); |
71 | } |
72 | |
73 | /* |
74 | * Allocates new ZIP device structure |
75 | * Returns zip_device pointer or NULL if cannot allocate memory for zip_device |
76 | */ |
77 | static struct zip_device *zip_alloc_device(struct pci_dev *pdev) |
78 | { |
79 | struct zip_device *zip = NULL; |
80 | int idx; |
81 | |
82 | for (idx = 0; idx < MAX_ZIP_DEVICES; idx++) { |
83 | if (!zip_dev[idx]) |
84 | break; |
85 | } |
86 | |
87 | /* To ensure that the index is within the limit */ |
88 | if (idx < MAX_ZIP_DEVICES) |
89 | zip = devm_kzalloc(dev: &pdev->dev, size: sizeof(*zip), GFP_KERNEL); |
90 | |
91 | if (!zip) |
92 | return NULL; |
93 | |
94 | zip_dev[idx] = zip; |
95 | zip->index = idx; |
96 | return zip; |
97 | } |
98 | |
99 | /** |
100 | * zip_get_device - Get ZIP device based on node id of cpu |
101 | * |
102 | * @node: Node id of the current cpu |
103 | * Return: Pointer to Zip device structure |
104 | */ |
105 | struct zip_device *zip_get_device(int node) |
106 | { |
107 | if ((node < MAX_ZIP_DEVICES) && (node >= 0)) |
108 | return zip_dev[node]; |
109 | |
110 | zip_err("ZIP device not found for node id %d\n" , node); |
111 | return NULL; |
112 | } |
113 | |
114 | /** |
115 | * zip_get_node_id - Get the node id of the current cpu |
116 | * |
117 | * Return: Node id of the current cpu |
118 | */ |
119 | int zip_get_node_id(void) |
120 | { |
121 | return cpu_to_node(raw_smp_processor_id()); |
122 | } |
123 | |
124 | /* Initializes the ZIP h/w sub-system */ |
125 | static int zip_init_hw(struct zip_device *zip) |
126 | { |
127 | union zip_cmd_ctl cmd_ctl; |
128 | union zip_constants constants; |
129 | union zip_que_ena que_ena; |
130 | union zip_quex_map que_map; |
131 | union zip_que_pri que_pri; |
132 | |
133 | union zip_quex_sbuf_addr que_sbuf_addr; |
134 | union zip_quex_sbuf_ctl que_sbuf_ctl; |
135 | |
136 | int q = 0; |
137 | |
138 | /* Enable the ZIP Engine(Core) Clock */ |
139 | cmd_ctl.u_reg64 = zip_reg_read(addr: zip->reg_base + ZIP_CMD_CTL); |
140 | cmd_ctl.s.forceclk = 1; |
141 | zip_reg_write(val: cmd_ctl.u_reg64 & 0xFF, addr: (zip->reg_base + ZIP_CMD_CTL)); |
142 | |
143 | zip_msg("ZIP_CMD_CTL : 0x%016llx" , |
144 | zip_reg_read(zip->reg_base + ZIP_CMD_CTL)); |
145 | |
146 | constants.u_reg64 = zip_reg_read(addr: zip->reg_base + ZIP_CONSTANTS); |
147 | zip->depth = constants.s.depth; |
148 | zip->onfsize = constants.s.onfsize; |
149 | zip->ctxsize = constants.s.ctxsize; |
150 | |
151 | zip_msg("depth: 0x%016llx , onfsize : 0x%016llx , ctxsize : 0x%016llx" , |
152 | zip->depth, zip->onfsize, zip->ctxsize); |
153 | |
154 | /* |
155 | * Program ZIP_QUE(0..7)_SBUF_ADDR and ZIP_QUE(0..7)_SBUF_CTL to |
156 | * have the correct buffer pointer and size configured for each |
157 | * instruction queue. |
158 | */ |
159 | for (q = 0; q < ZIP_NUM_QUEUES; q++) { |
160 | que_sbuf_ctl.u_reg64 = 0ull; |
161 | que_sbuf_ctl.s.size = (ZIP_CMD_QBUF_SIZE / sizeof(u64)); |
162 | que_sbuf_ctl.s.inst_be = 0; |
163 | que_sbuf_ctl.s.stream_id = 0; |
164 | zip_reg_write(val: que_sbuf_ctl.u_reg64, |
165 | addr: (zip->reg_base + ZIP_QUEX_SBUF_CTL(param1: q))); |
166 | |
167 | zip_msg("QUEX_SBUF_CTL[%d]: 0x%016llx" , q, |
168 | zip_reg_read(zip->reg_base + ZIP_QUEX_SBUF_CTL(q))); |
169 | } |
170 | |
171 | for (q = 0; q < ZIP_NUM_QUEUES; q++) { |
172 | memset(&zip->iq[q], 0x0, sizeof(struct zip_iq)); |
173 | |
174 | spin_lock_init(&zip->iq[q].lock); |
175 | |
176 | if (zip_cmd_qbuf_alloc(zip, q)) { |
177 | while (q != 0) { |
178 | q--; |
179 | zip_cmd_qbuf_free(zip, q); |
180 | } |
181 | return -ENOMEM; |
182 | } |
183 | |
184 | /* Initialize tail ptr to head */ |
185 | zip->iq[q].sw_tail = zip->iq[q].sw_head; |
186 | zip->iq[q].hw_tail = zip->iq[q].sw_head; |
187 | |
188 | /* Write the physical addr to register */ |
189 | que_sbuf_addr.u_reg64 = 0ull; |
190 | que_sbuf_addr.s.ptr = (__pa(zip->iq[q].sw_head) >> |
191 | ZIP_128B_ALIGN); |
192 | |
193 | zip_msg("QUE[%d]_PTR(PHYS): 0x%016llx" , q, |
194 | (u64)que_sbuf_addr.s.ptr); |
195 | |
196 | zip_reg_write(val: que_sbuf_addr.u_reg64, |
197 | addr: (zip->reg_base + ZIP_QUEX_SBUF_ADDR(param1: q))); |
198 | |
199 | zip_msg("QUEX_SBUF_ADDR[%d]: 0x%016llx" , q, |
200 | zip_reg_read(zip->reg_base + ZIP_QUEX_SBUF_ADDR(q))); |
201 | |
202 | zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx" , |
203 | zip->iq[q].sw_head, zip->iq[q].sw_tail, |
204 | zip->iq[q].hw_tail); |
205 | zip_dbg("sw_head phy addr : 0x%lx" , que_sbuf_addr.s.ptr); |
206 | } |
207 | |
208 | /* |
209 | * Queue-to-ZIP core mapping |
210 | * If a queue is not mapped to a particular core, it is equivalent to |
211 | * the ZIP core being disabled. |
212 | */ |
213 | que_ena.u_reg64 = 0x0ull; |
214 | /* Enabling queues based on ZIP_NUM_QUEUES */ |
215 | for (q = 0; q < ZIP_NUM_QUEUES; q++) |
216 | que_ena.s.ena |= (0x1 << q); |
217 | zip_reg_write(val: que_ena.u_reg64, addr: (zip->reg_base + ZIP_QUE_ENA)); |
218 | |
219 | zip_msg("QUE_ENA : 0x%016llx" , |
220 | zip_reg_read(zip->reg_base + ZIP_QUE_ENA)); |
221 | |
222 | for (q = 0; q < ZIP_NUM_QUEUES; q++) { |
223 | que_map.u_reg64 = 0ull; |
224 | /* Mapping each queue to two ZIP cores */ |
225 | que_map.s.zce = 0x3; |
226 | zip_reg_write(val: que_map.u_reg64, |
227 | addr: (zip->reg_base + ZIP_QUEX_MAP(param1: q))); |
228 | |
229 | zip_msg("QUE_MAP(%d) : 0x%016llx" , q, |
230 | zip_reg_read(zip->reg_base + ZIP_QUEX_MAP(q))); |
231 | } |
232 | |
233 | que_pri.u_reg64 = 0ull; |
234 | for (q = 0; q < ZIP_NUM_QUEUES; q++) |
235 | que_pri.s.pri |= (0x1 << q); /* Higher Priority RR */ |
236 | zip_reg_write(val: que_pri.u_reg64, addr: (zip->reg_base + ZIP_QUE_PRI)); |
237 | |
238 | zip_msg("QUE_PRI %016llx" , zip_reg_read(zip->reg_base + ZIP_QUE_PRI)); |
239 | |
240 | return 0; |
241 | } |
242 | |
243 | static void zip_reset(struct zip_device *zip) |
244 | { |
245 | union zip_cmd_ctl cmd_ctl; |
246 | |
247 | cmd_ctl.u_reg64 = 0x0ull; |
248 | cmd_ctl.s.reset = 1; /* Forces ZIP cores to do reset */ |
249 | zip_reg_write(val: cmd_ctl.u_reg64, addr: (zip->reg_base + ZIP_CMD_CTL)); |
250 | } |
251 | |
252 | static int zip_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
253 | { |
254 | struct device *dev = &pdev->dev; |
255 | struct zip_device *zip = NULL; |
256 | int err; |
257 | |
258 | zip = zip_alloc_device(pdev); |
259 | if (!zip) |
260 | return -ENOMEM; |
261 | |
262 | dev_info(dev, "Found ZIP device %d %x:%x on Node %d\n" , zip->index, |
263 | pdev->vendor, pdev->device, dev_to_node(dev)); |
264 | |
265 | pci_set_drvdata(pdev, data: zip); |
266 | zip->pdev = pdev; |
267 | |
268 | err = pci_enable_device(dev: pdev); |
269 | if (err) { |
270 | dev_err(dev, "Failed to enable PCI device" ); |
271 | goto err_free_device; |
272 | } |
273 | |
274 | err = pci_request_regions(pdev, DRV_NAME); |
275 | if (err) { |
276 | dev_err(dev, "PCI request regions failed 0x%x" , err); |
277 | goto err_disable_device; |
278 | } |
279 | |
280 | err = dma_set_mask_and_coherent(dev: &pdev->dev, DMA_BIT_MASK(48)); |
281 | if (err) { |
282 | dev_err(dev, "Unable to get usable 48-bit DMA configuration\n" ); |
283 | goto err_release_regions; |
284 | } |
285 | |
286 | /* MAP configuration registers */ |
287 | zip->reg_base = pci_ioremap_bar(pdev, PCI_CFG_ZIP_PF_BAR0); |
288 | if (!zip->reg_base) { |
289 | dev_err(dev, "ZIP: Cannot map BAR0 CSR memory space, aborting" ); |
290 | err = -ENOMEM; |
291 | goto err_release_regions; |
292 | } |
293 | |
294 | /* Initialize ZIP Hardware */ |
295 | err = zip_init_hw(zip); |
296 | if (err) |
297 | goto err_release_regions; |
298 | |
299 | /* Register with the Kernel Crypto Interface */ |
300 | err = zip_register_compression_device(); |
301 | if (err < 0) { |
302 | zip_err("ZIP: Kernel Crypto Registration failed\n" ); |
303 | goto err_register; |
304 | } |
305 | |
306 | /* comp-decomp statistics are handled with debugfs interface */ |
307 | zip_debugfs_init(); |
308 | |
309 | return 0; |
310 | |
311 | err_register: |
312 | zip_reset(zip); |
313 | |
314 | err_release_regions: |
315 | if (zip->reg_base) |
316 | iounmap(addr: zip->reg_base); |
317 | pci_release_regions(pdev); |
318 | |
319 | err_disable_device: |
320 | pci_disable_device(dev: pdev); |
321 | |
322 | err_free_device: |
323 | pci_set_drvdata(pdev, NULL); |
324 | |
325 | /* Remove zip_dev from zip_device list, free the zip_device memory */ |
326 | zip_dev[zip->index] = NULL; |
327 | devm_kfree(dev, p: zip); |
328 | |
329 | return err; |
330 | } |
331 | |
332 | static void zip_remove(struct pci_dev *pdev) |
333 | { |
334 | struct zip_device *zip = pci_get_drvdata(pdev); |
335 | int q = 0; |
336 | |
337 | if (!zip) |
338 | return; |
339 | |
340 | zip_debugfs_exit(); |
341 | |
342 | zip_unregister_compression_device(); |
343 | |
344 | if (zip->reg_base) { |
345 | zip_reset(zip); |
346 | iounmap(addr: zip->reg_base); |
347 | } |
348 | |
349 | pci_release_regions(pdev); |
350 | pci_disable_device(dev: pdev); |
351 | |
352 | /* |
353 | * Free Command Queue buffers. This free should be called for all |
354 | * the enabled Queues. |
355 | */ |
356 | for (q = 0; q < ZIP_NUM_QUEUES; q++) |
357 | zip_cmd_qbuf_free(zip, q); |
358 | |
359 | pci_set_drvdata(pdev, NULL); |
360 | /* remove zip device from zip device list */ |
361 | zip_dev[zip->index] = NULL; |
362 | } |
363 | |
364 | /* PCI Sub-System Interface */ |
365 | static struct pci_driver zip_driver = { |
366 | .name = DRV_NAME, |
367 | .id_table = zip_id_table, |
368 | .probe = zip_probe, |
369 | .remove = zip_remove, |
370 | }; |
371 | |
372 | /* Kernel Crypto Subsystem Interface */ |
373 | |
374 | static struct crypto_alg zip_comp_deflate = { |
375 | .cra_name = "deflate" , |
376 | .cra_driver_name = "deflate-cavium" , |
377 | .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, |
378 | .cra_ctxsize = sizeof(struct zip_kernel_ctx), |
379 | .cra_priority = 300, |
380 | .cra_module = THIS_MODULE, |
381 | .cra_init = zip_alloc_comp_ctx_deflate, |
382 | .cra_exit = zip_free_comp_ctx, |
383 | .cra_u = { .compress = { |
384 | .coa_compress = zip_comp_compress, |
385 | .coa_decompress = zip_comp_decompress |
386 | } } |
387 | }; |
388 | |
389 | static struct crypto_alg zip_comp_lzs = { |
390 | .cra_name = "lzs" , |
391 | .cra_driver_name = "lzs-cavium" , |
392 | .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, |
393 | .cra_ctxsize = sizeof(struct zip_kernel_ctx), |
394 | .cra_priority = 300, |
395 | .cra_module = THIS_MODULE, |
396 | .cra_init = zip_alloc_comp_ctx_lzs, |
397 | .cra_exit = zip_free_comp_ctx, |
398 | .cra_u = { .compress = { |
399 | .coa_compress = zip_comp_compress, |
400 | .coa_decompress = zip_comp_decompress |
401 | } } |
402 | }; |
403 | |
404 | static struct scomp_alg zip_scomp_deflate = { |
405 | .alloc_ctx = zip_alloc_scomp_ctx_deflate, |
406 | .free_ctx = zip_free_scomp_ctx, |
407 | .compress = zip_scomp_compress, |
408 | .decompress = zip_scomp_decompress, |
409 | .base = { |
410 | .cra_name = "deflate" , |
411 | .cra_driver_name = "deflate-scomp-cavium" , |
412 | .cra_module = THIS_MODULE, |
413 | .cra_priority = 300, |
414 | } |
415 | }; |
416 | |
417 | static struct scomp_alg zip_scomp_lzs = { |
418 | .alloc_ctx = zip_alloc_scomp_ctx_lzs, |
419 | .free_ctx = zip_free_scomp_ctx, |
420 | .compress = zip_scomp_compress, |
421 | .decompress = zip_scomp_decompress, |
422 | .base = { |
423 | .cra_name = "lzs" , |
424 | .cra_driver_name = "lzs-scomp-cavium" , |
425 | .cra_module = THIS_MODULE, |
426 | .cra_priority = 300, |
427 | } |
428 | }; |
429 | |
430 | static int zip_register_compression_device(void) |
431 | { |
432 | int ret; |
433 | |
434 | ret = crypto_register_alg(alg: &zip_comp_deflate); |
435 | if (ret < 0) { |
436 | zip_err("Deflate algorithm registration failed\n" ); |
437 | return ret; |
438 | } |
439 | |
440 | ret = crypto_register_alg(alg: &zip_comp_lzs); |
441 | if (ret < 0) { |
442 | zip_err("LZS algorithm registration failed\n" ); |
443 | goto err_unregister_alg_deflate; |
444 | } |
445 | |
446 | ret = crypto_register_scomp(alg: &zip_scomp_deflate); |
447 | if (ret < 0) { |
448 | zip_err("Deflate scomp algorithm registration failed\n" ); |
449 | goto err_unregister_alg_lzs; |
450 | } |
451 | |
452 | ret = crypto_register_scomp(alg: &zip_scomp_lzs); |
453 | if (ret < 0) { |
454 | zip_err("LZS scomp algorithm registration failed\n" ); |
455 | goto err_unregister_scomp_deflate; |
456 | } |
457 | |
458 | return ret; |
459 | |
460 | err_unregister_scomp_deflate: |
461 | crypto_unregister_scomp(alg: &zip_scomp_deflate); |
462 | err_unregister_alg_lzs: |
463 | crypto_unregister_alg(alg: &zip_comp_lzs); |
464 | err_unregister_alg_deflate: |
465 | crypto_unregister_alg(alg: &zip_comp_deflate); |
466 | |
467 | return ret; |
468 | } |
469 | |
470 | static void zip_unregister_compression_device(void) |
471 | { |
472 | crypto_unregister_alg(alg: &zip_comp_deflate); |
473 | crypto_unregister_alg(alg: &zip_comp_lzs); |
474 | crypto_unregister_scomp(alg: &zip_scomp_deflate); |
475 | crypto_unregister_scomp(alg: &zip_scomp_lzs); |
476 | } |
477 | |
478 | /* |
479 | * debugfs functions |
480 | */ |
481 | #ifdef CONFIG_DEBUG_FS |
482 | #include <linux/debugfs.h> |
483 | |
484 | /* Displays ZIP device statistics */ |
485 | static int zip_stats_show(struct seq_file *s, void *unused) |
486 | { |
487 | u64 val = 0ull; |
488 | u64 avg_chunk = 0ull, avg_cr = 0ull; |
489 | u32 q = 0; |
490 | |
491 | int index = 0; |
492 | struct zip_device *zip; |
493 | struct zip_stats *st; |
494 | |
495 | for (index = 0; index < MAX_ZIP_DEVICES; index++) { |
496 | u64 pending = 0; |
497 | |
498 | if (zip_dev[index]) { |
499 | zip = zip_dev[index]; |
500 | st = &zip->stats; |
501 | |
502 | /* Get all the pending requests */ |
503 | for (q = 0; q < ZIP_NUM_QUEUES; q++) { |
504 | val = zip_reg_read(addr: (zip->reg_base + |
505 | ZIP_DBG_QUEX_STA(param1: q))); |
506 | pending += val >> 32 & 0xffffff; |
507 | } |
508 | |
509 | val = atomic64_read(v: &st->comp_req_complete); |
510 | avg_chunk = (val) ? atomic64_read(v: &st->comp_in_bytes) / val : 0; |
511 | |
512 | val = atomic64_read(v: &st->comp_out_bytes); |
513 | avg_cr = (val) ? atomic64_read(v: &st->comp_in_bytes) / val : 0; |
514 | seq_printf(m: s, fmt: " ZIP Device %d Stats\n" |
515 | "-----------------------------------\n" |
516 | "Comp Req Submitted : \t%lld\n" |
517 | "Comp Req Completed : \t%lld\n" |
518 | "Compress In Bytes : \t%lld\n" |
519 | "Compressed Out Bytes : \t%lld\n" |
520 | "Average Chunk size : \t%llu\n" |
521 | "Average Compression ratio : \t%llu\n" |
522 | "Decomp Req Submitted : \t%lld\n" |
523 | "Decomp Req Completed : \t%lld\n" |
524 | "Decompress In Bytes : \t%lld\n" |
525 | "Decompressed Out Bytes : \t%lld\n" |
526 | "Decompress Bad requests : \t%lld\n" |
527 | "Pending Req : \t%lld\n" |
528 | "---------------------------------\n" , |
529 | index, |
530 | (u64)atomic64_read(v: &st->comp_req_submit), |
531 | (u64)atomic64_read(v: &st->comp_req_complete), |
532 | (u64)atomic64_read(v: &st->comp_in_bytes), |
533 | (u64)atomic64_read(v: &st->comp_out_bytes), |
534 | avg_chunk, |
535 | avg_cr, |
536 | (u64)atomic64_read(v: &st->decomp_req_submit), |
537 | (u64)atomic64_read(v: &st->decomp_req_complete), |
538 | (u64)atomic64_read(v: &st->decomp_in_bytes), |
539 | (u64)atomic64_read(v: &st->decomp_out_bytes), |
540 | (u64)atomic64_read(v: &st->decomp_bad_reqs), |
541 | pending); |
542 | } |
543 | } |
544 | return 0; |
545 | } |
546 | |
547 | /* Clears stats data */ |
548 | static int zip_clear_show(struct seq_file *s, void *unused) |
549 | { |
550 | int index = 0; |
551 | |
552 | for (index = 0; index < MAX_ZIP_DEVICES; index++) { |
553 | if (zip_dev[index]) { |
554 | memset(&zip_dev[index]->stats, 0, |
555 | sizeof(struct zip_stats)); |
556 | seq_printf(m: s, fmt: "Cleared stats for zip %d\n" , index); |
557 | } |
558 | } |
559 | |
560 | return 0; |
561 | } |
562 | |
563 | static struct zip_registers zipregs[64] = { |
564 | {"ZIP_CMD_CTL " , 0x0000ull}, |
565 | {"ZIP_THROTTLE " , 0x0010ull}, |
566 | {"ZIP_CONSTANTS " , 0x00A0ull}, |
567 | {"ZIP_QUE0_MAP " , 0x1400ull}, |
568 | {"ZIP_QUE1_MAP " , 0x1408ull}, |
569 | {"ZIP_QUE_ENA " , 0x0500ull}, |
570 | {"ZIP_QUE_PRI " , 0x0508ull}, |
571 | {"ZIP_QUE0_DONE " , 0x2000ull}, |
572 | {"ZIP_QUE1_DONE " , 0x2008ull}, |
573 | {"ZIP_QUE0_DOORBELL " , 0x4000ull}, |
574 | {"ZIP_QUE1_DOORBELL " , 0x4008ull}, |
575 | {"ZIP_QUE0_SBUF_ADDR " , 0x1000ull}, |
576 | {"ZIP_QUE1_SBUF_ADDR " , 0x1008ull}, |
577 | {"ZIP_QUE0_SBUF_CTL " , 0x1200ull}, |
578 | {"ZIP_QUE1_SBUF_CTL " , 0x1208ull}, |
579 | { NULL, 0} |
580 | }; |
581 | |
582 | /* Prints registers' contents */ |
583 | static int zip_regs_show(struct seq_file *s, void *unused) |
584 | { |
585 | u64 val = 0; |
586 | int i = 0, index = 0; |
587 | |
588 | for (index = 0; index < MAX_ZIP_DEVICES; index++) { |
589 | if (zip_dev[index]) { |
590 | seq_printf(m: s, fmt: "--------------------------------\n" |
591 | " ZIP Device %d Registers\n" |
592 | "--------------------------------\n" , |
593 | index); |
594 | |
595 | i = 0; |
596 | |
597 | while (zipregs[i].reg_name) { |
598 | val = zip_reg_read(addr: (zip_dev[index]->reg_base + |
599 | zipregs[i].reg_offset)); |
600 | seq_printf(m: s, fmt: "%s: 0x%016llx\n" , |
601 | zipregs[i].reg_name, val); |
602 | i++; |
603 | } |
604 | } |
605 | } |
606 | return 0; |
607 | } |
608 | |
609 | DEFINE_SHOW_ATTRIBUTE(zip_stats); |
610 | DEFINE_SHOW_ATTRIBUTE(zip_clear); |
611 | DEFINE_SHOW_ATTRIBUTE(zip_regs); |
612 | |
613 | /* Root directory for thunderx_zip debugfs entry */ |
614 | static struct dentry *zip_debugfs_root; |
615 | |
616 | static void zip_debugfs_init(void) |
617 | { |
618 | if (!debugfs_initialized()) |
619 | return; |
620 | |
621 | zip_debugfs_root = debugfs_create_dir(name: "thunderx_zip" , NULL); |
622 | |
623 | /* Creating files for entries inside thunderx_zip directory */ |
624 | debugfs_create_file(name: "zip_stats" , mode: 0444, parent: zip_debugfs_root, NULL, |
625 | fops: &zip_stats_fops); |
626 | |
627 | debugfs_create_file(name: "zip_clear" , mode: 0444, parent: zip_debugfs_root, NULL, |
628 | fops: &zip_clear_fops); |
629 | |
630 | debugfs_create_file(name: "zip_regs" , mode: 0444, parent: zip_debugfs_root, NULL, |
631 | fops: &zip_regs_fops); |
632 | |
633 | } |
634 | |
635 | static void zip_debugfs_exit(void) |
636 | { |
637 | debugfs_remove_recursive(dentry: zip_debugfs_root); |
638 | } |
639 | |
640 | #else |
641 | static void __init zip_debugfs_init(void) { } |
642 | static void __exit zip_debugfs_exit(void) { } |
643 | #endif |
644 | /* debugfs - end */ |
645 | |
646 | module_pci_driver(zip_driver); |
647 | |
648 | MODULE_AUTHOR("Cavium Inc" ); |
649 | MODULE_DESCRIPTION("Cavium Inc ThunderX ZIP Driver" ); |
650 | MODULE_LICENSE("GPL v2" ); |
651 | MODULE_DEVICE_TABLE(pci, zip_id_table); |
652 | |