1 /***********************license start************************************
2 * Copyright (c) 2003-2017 Cavium, Inc.
5 * License: one of 'Cavium License' or 'GNU General Public License Version 2'
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.
12 * Cavium License: Redistribution and use in source and binary forms, with
13 * or without modification, are permitted provided that the following
16 * * Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
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
44 ***********************license end**************************************/
47 #include "zip_crypto.h"
49 #define DRV_NAME "ThunderX-ZIP"
51 static struct zip_device
*zip_dev
[MAX_ZIP_DEVICES
];
53 static const struct pci_device_id zip_id_table
[] = {
54 { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM
, PCI_DEVICE_ID_THUNDERX_ZIP
) },
58 void zip_reg_write(u64 val
, u64 __iomem
*addr
)
63 u64
zip_reg_read(u64 __iomem
*addr
)
69 * Allocates new ZIP device structure
70 * Returns zip_device pointer or NULL if cannot allocate memory for zip_device
72 static struct zip_device
*zip_alloc_device(struct pci_dev
*pdev
)
74 struct zip_device
*zip
= NULL
;
77 for (idx
= 0; idx
< MAX_ZIP_DEVICES
; idx
++) {
82 /* To ensure that the index is within the limit */
83 if (idx
< MAX_ZIP_DEVICES
)
84 zip
= devm_kzalloc(&pdev
->dev
, sizeof(*zip
), GFP_KERNEL
);
95 * zip_get_device - Get ZIP device based on node id of cpu
97 * @node: Node id of the current cpu
98 * Return: Pointer to Zip device structure
100 struct zip_device
*zip_get_device(int node
)
102 if ((node
< MAX_ZIP_DEVICES
) && (node
>= 0))
103 return zip_dev
[node
];
105 zip_err("ZIP device not found for node id %d\n", node
);
110 * zip_get_node_id - Get the node id of the current cpu
112 * Return: Node id of the current cpu
114 int zip_get_node_id(void)
116 return cpu_to_node(raw_smp_processor_id());
119 /* Initializes the ZIP h/w sub-system */
120 static int zip_init_hw(struct zip_device
*zip
)
122 union zip_cmd_ctl cmd_ctl
;
123 union zip_constants constants
;
124 union zip_que_ena que_ena
;
125 union zip_quex_map que_map
;
126 union zip_que_pri que_pri
;
128 union zip_quex_sbuf_addr que_sbuf_addr
;
129 union zip_quex_sbuf_ctl que_sbuf_ctl
;
133 /* Enable the ZIP Engine(Core) Clock */
134 cmd_ctl
.u_reg64
= zip_reg_read(zip
->reg_base
+ ZIP_CMD_CTL
);
135 cmd_ctl
.s
.forceclk
= 1;
136 zip_reg_write(cmd_ctl
.u_reg64
& 0xFF, (zip
->reg_base
+ ZIP_CMD_CTL
));
138 zip_msg("ZIP_CMD_CTL : 0x%016llx",
139 zip_reg_read(zip
->reg_base
+ ZIP_CMD_CTL
));
141 constants
.u_reg64
= zip_reg_read(zip
->reg_base
+ ZIP_CONSTANTS
);
142 zip
->depth
= constants
.s
.depth
;
143 zip
->onfsize
= constants
.s
.onfsize
;
144 zip
->ctxsize
= constants
.s
.ctxsize
;
146 zip_msg("depth: 0x%016llx , onfsize : 0x%016llx , ctxsize : 0x%016llx",
147 zip
->depth
, zip
->onfsize
, zip
->ctxsize
);
150 * Program ZIP_QUE(0..7)_SBUF_ADDR and ZIP_QUE(0..7)_SBUF_CTL to
151 * have the correct buffer pointer and size configured for each
154 for (q
= 0; q
< ZIP_NUM_QUEUES
; q
++) {
155 que_sbuf_ctl
.u_reg64
= 0ull;
156 que_sbuf_ctl
.s
.size
= (ZIP_CMD_QBUF_SIZE
/ sizeof(u64
));
157 que_sbuf_ctl
.s
.inst_be
= 0;
158 que_sbuf_ctl
.s
.stream_id
= 0;
159 zip_reg_write(que_sbuf_ctl
.u_reg64
,
160 (zip
->reg_base
+ ZIP_QUEX_SBUF_CTL(q
)));
162 zip_msg("QUEX_SBUF_CTL[%d]: 0x%016llx", q
,
163 zip_reg_read(zip
->reg_base
+ ZIP_QUEX_SBUF_CTL(q
)));
166 for (q
= 0; q
< ZIP_NUM_QUEUES
; q
++) {
167 memset(&zip
->iq
[q
], 0x0, sizeof(struct zip_iq
));
169 spin_lock_init(&zip
->iq
[q
].lock
);
171 if (zip_cmd_qbuf_alloc(zip
, q
)) {
174 zip_cmd_qbuf_free(zip
, q
);
179 /* Initialize tail ptr to head */
180 zip
->iq
[q
].sw_tail
= zip
->iq
[q
].sw_head
;
181 zip
->iq
[q
].hw_tail
= zip
->iq
[q
].sw_head
;
183 /* Write the physical addr to register */
184 que_sbuf_addr
.u_reg64
= 0ull;
185 que_sbuf_addr
.s
.ptr
= (__pa(zip
->iq
[q
].sw_head
) >>
188 zip_msg("QUE[%d]_PTR(PHYS): 0x%016llx", q
,
189 (u64
)que_sbuf_addr
.s
.ptr
);
191 zip_reg_write(que_sbuf_addr
.u_reg64
,
192 (zip
->reg_base
+ ZIP_QUEX_SBUF_ADDR(q
)));
194 zip_msg("QUEX_SBUF_ADDR[%d]: 0x%016llx", q
,
195 zip_reg_read(zip
->reg_base
+ ZIP_QUEX_SBUF_ADDR(q
)));
197 zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx",
198 zip
->iq
[q
].sw_head
, zip
->iq
[q
].sw_tail
,
200 zip_dbg("sw_head phy addr : 0x%lx", que_sbuf_addr
.s
.ptr
);
204 * Queue-to-ZIP core mapping
205 * If a queue is not mapped to a particular core, it is equivalent to
206 * the ZIP core being disabled.
208 que_ena
.u_reg64
= 0x0ull
;
209 /* Enabling queues based on ZIP_NUM_QUEUES */
210 for (q
= 0; q
< ZIP_NUM_QUEUES
; q
++)
211 que_ena
.s
.ena
|= (0x1 << q
);
212 zip_reg_write(que_ena
.u_reg64
, (zip
->reg_base
+ ZIP_QUE_ENA
));
214 zip_msg("QUE_ENA : 0x%016llx",
215 zip_reg_read(zip
->reg_base
+ ZIP_QUE_ENA
));
217 for (q
= 0; q
< ZIP_NUM_QUEUES
; q
++) {
218 que_map
.u_reg64
= 0ull;
219 /* Mapping each queue to two ZIP cores */
221 zip_reg_write(que_map
.u_reg64
,
222 (zip
->reg_base
+ ZIP_QUEX_MAP(q
)));
224 zip_msg("QUE_MAP(%d) : 0x%016llx", q
,
225 zip_reg_read(zip
->reg_base
+ ZIP_QUEX_MAP(q
)));
228 que_pri
.u_reg64
= 0ull;
229 for (q
= 0; q
< ZIP_NUM_QUEUES
; q
++)
230 que_pri
.s
.pri
|= (0x1 << q
); /* Higher Priority RR */
231 zip_reg_write(que_pri
.u_reg64
, (zip
->reg_base
+ ZIP_QUE_PRI
));
233 zip_msg("QUE_PRI %016llx", zip_reg_read(zip
->reg_base
+ ZIP_QUE_PRI
));
238 static int zip_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
240 struct device
*dev
= &pdev
->dev
;
241 struct zip_device
*zip
= NULL
;
244 zip
= zip_alloc_device(pdev
);
248 dev_info(dev
, "Found ZIP device %d %x:%x on Node %d\n", zip
->index
,
249 pdev
->vendor
, pdev
->device
, dev_to_node(dev
));
251 pci_set_drvdata(pdev
, zip
);
254 err
= pci_enable_device(pdev
);
256 dev_err(dev
, "Failed to enable PCI device");
257 goto err_free_device
;
260 err
= pci_request_regions(pdev
, DRV_NAME
);
262 dev_err(dev
, "PCI request regions failed 0x%x", err
);
263 goto err_disable_device
;
266 err
= dma_set_mask_and_coherent(&pdev
->dev
, DMA_BIT_MASK(48));
268 dev_err(dev
, "Unable to get usable 48-bit DMA configuration\n");
269 goto err_release_regions
;
272 /* MAP configuration registers */
273 zip
->reg_base
= pci_ioremap_bar(pdev
, PCI_CFG_ZIP_PF_BAR0
);
274 if (!zip
->reg_base
) {
275 dev_err(dev
, "ZIP: Cannot map BAR0 CSR memory space, aborting");
277 goto err_release_regions
;
280 /* Initialize ZIP Hardware */
281 err
= zip_init_hw(zip
);
283 goto err_release_regions
;
289 iounmap(zip
->reg_base
);
290 pci_release_regions(pdev
);
293 pci_disable_device(pdev
);
296 pci_set_drvdata(pdev
, NULL
);
298 /* Remove zip_dev from zip_device list, free the zip_device memory */
299 zip_dev
[zip
->index
] = NULL
;
300 devm_kfree(dev
, zip
);
305 static void zip_remove(struct pci_dev
*pdev
)
307 struct zip_device
*zip
= pci_get_drvdata(pdev
);
308 union zip_cmd_ctl cmd_ctl
;
315 cmd_ctl
.u_reg64
= 0x0ull
;
316 cmd_ctl
.s
.reset
= 1; /* Forces ZIP cores to do reset */
317 zip_reg_write(cmd_ctl
.u_reg64
, (zip
->reg_base
+ ZIP_CMD_CTL
));
318 iounmap(zip
->reg_base
);
321 pci_release_regions(pdev
);
322 pci_disable_device(pdev
);
325 * Free Command Queue buffers. This free should be called for all
326 * the enabled Queues.
328 for (q
= 0; q
< ZIP_NUM_QUEUES
; q
++)
329 zip_cmd_qbuf_free(zip
, q
);
331 pci_set_drvdata(pdev
, NULL
);
332 /* remove zip device from zip device list */
333 zip_dev
[zip
->index
] = NULL
;
336 /* PCI Sub-System Interface */
337 static struct pci_driver zip_driver
= {
339 .id_table
= zip_id_table
,
341 .remove
= zip_remove
,
344 /* Kernel Crypto Subsystem Interface */
346 static struct crypto_alg zip_comp_deflate
= {
347 .cra_name
= "deflate",
348 .cra_driver_name
= "deflate-cavium",
349 .cra_flags
= CRYPTO_ALG_TYPE_COMPRESS
,
350 .cra_ctxsize
= sizeof(struct zip_kernel_ctx
),
352 .cra_module
= THIS_MODULE
,
353 .cra_init
= zip_alloc_comp_ctx_deflate
,
354 .cra_exit
= zip_free_comp_ctx
,
355 .cra_u
= { .compress
= {
356 .coa_compress
= zip_comp_compress
,
357 .coa_decompress
= zip_comp_decompress
361 static struct crypto_alg zip_comp_lzs
= {
363 .cra_driver_name
= "lzs-cavium",
364 .cra_flags
= CRYPTO_ALG_TYPE_COMPRESS
,
365 .cra_ctxsize
= sizeof(struct zip_kernel_ctx
),
367 .cra_module
= THIS_MODULE
,
368 .cra_init
= zip_alloc_comp_ctx_lzs
,
369 .cra_exit
= zip_free_comp_ctx
,
370 .cra_u
= { .compress
= {
371 .coa_compress
= zip_comp_compress
,
372 .coa_decompress
= zip_comp_decompress
376 static struct scomp_alg zip_scomp_deflate
= {
377 .alloc_ctx
= zip_alloc_scomp_ctx_deflate
,
378 .free_ctx
= zip_free_scomp_ctx
,
379 .compress
= zip_scomp_compress
,
380 .decompress
= zip_scomp_decompress
,
382 .cra_name
= "deflate",
383 .cra_driver_name
= "deflate-scomp-cavium",
384 .cra_module
= THIS_MODULE
,
389 static struct scomp_alg zip_scomp_lzs
= {
390 .alloc_ctx
= zip_alloc_scomp_ctx_lzs
,
391 .free_ctx
= zip_free_scomp_ctx
,
392 .compress
= zip_scomp_compress
,
393 .decompress
= zip_scomp_decompress
,
396 .cra_driver_name
= "lzs-scomp-cavium",
397 .cra_module
= THIS_MODULE
,
402 static int zip_register_compression_device(void)
406 ret
= crypto_register_alg(&zip_comp_deflate
);
408 zip_err("Deflate algorithm registration failed\n");
412 ret
= crypto_register_alg(&zip_comp_lzs
);
414 zip_err("LZS algorithm registration failed\n");
415 goto err_unregister_alg_deflate
;
418 ret
= crypto_register_scomp(&zip_scomp_deflate
);
420 zip_err("Deflate scomp algorithm registration failed\n");
421 goto err_unregister_alg_lzs
;
424 ret
= crypto_register_scomp(&zip_scomp_lzs
);
426 zip_err("LZS scomp algorithm registration failed\n");
427 goto err_unregister_scomp_deflate
;
432 err_unregister_scomp_deflate
:
433 crypto_unregister_scomp(&zip_scomp_deflate
);
434 err_unregister_alg_lzs
:
435 crypto_unregister_alg(&zip_comp_lzs
);
436 err_unregister_alg_deflate
:
437 crypto_unregister_alg(&zip_comp_deflate
);
442 static void zip_unregister_compression_device(void)
444 crypto_unregister_alg(&zip_comp_deflate
);
445 crypto_unregister_alg(&zip_comp_lzs
);
446 crypto_unregister_scomp(&zip_scomp_deflate
);
447 crypto_unregister_scomp(&zip_scomp_lzs
);
453 #ifdef CONFIG_DEBUG_FS
454 #include <linux/debugfs.h>
456 /* Displays ZIP device statistics */
457 static int zip_stats_show(struct seq_file
*s
, void *unused
)
460 u64 avg_chunk
= 0ull, avg_cr
= 0ull;
464 struct zip_device
*zip
;
465 struct zip_stats
*st
;
467 for (index
= 0; index
< MAX_ZIP_DEVICES
; index
++) {
470 if (zip_dev
[index
]) {
471 zip
= zip_dev
[index
];
474 /* Get all the pending requests */
475 for (q
= 0; q
< ZIP_NUM_QUEUES
; q
++) {
476 val
= zip_reg_read((zip
->reg_base
+
477 ZIP_DBG_QUEX_STA(q
)));
478 pending
+= val
>> 32 & 0xffffff;
481 val
= atomic64_read(&st
->comp_req_complete
);
482 avg_chunk
= (val
) ? atomic64_read(&st
->comp_in_bytes
) / val
: 0;
484 val
= atomic64_read(&st
->comp_out_bytes
);
485 avg_cr
= (val
) ? atomic64_read(&st
->comp_in_bytes
) / val
: 0;
486 seq_printf(s
, " ZIP Device %d Stats\n"
487 "-----------------------------------\n"
488 "Comp Req Submitted : \t%lld\n"
489 "Comp Req Completed : \t%lld\n"
490 "Compress In Bytes : \t%lld\n"
491 "Compressed Out Bytes : \t%lld\n"
492 "Average Chunk size : \t%llu\n"
493 "Average Compression ratio : \t%llu\n"
494 "Decomp Req Submitted : \t%lld\n"
495 "Decomp Req Completed : \t%lld\n"
496 "Decompress In Bytes : \t%lld\n"
497 "Decompressed Out Bytes : \t%lld\n"
498 "Decompress Bad requests : \t%lld\n"
499 "Pending Req : \t%lld\n"
500 "---------------------------------\n",
502 (u64
)atomic64_read(&st
->comp_req_submit
),
503 (u64
)atomic64_read(&st
->comp_req_complete
),
504 (u64
)atomic64_read(&st
->comp_in_bytes
),
505 (u64
)atomic64_read(&st
->comp_out_bytes
),
508 (u64
)atomic64_read(&st
->decomp_req_submit
),
509 (u64
)atomic64_read(&st
->decomp_req_complete
),
510 (u64
)atomic64_read(&st
->decomp_in_bytes
),
511 (u64
)atomic64_read(&st
->decomp_out_bytes
),
512 (u64
)atomic64_read(&st
->decomp_bad_reqs
),
519 /* Clears stats data */
520 static int zip_clear_show(struct seq_file
*s
, void *unused
)
524 for (index
= 0; index
< MAX_ZIP_DEVICES
; index
++) {
525 if (zip_dev
[index
]) {
526 memset(&zip_dev
[index
]->stats
, 0,
527 sizeof(struct zip_stats
));
528 seq_printf(s
, "Cleared stats for zip %d\n", index
);
535 static struct zip_registers zipregs
[64] = {
536 {"ZIP_CMD_CTL ", 0x0000ull
},
537 {"ZIP_THROTTLE ", 0x0010ull
},
538 {"ZIP_CONSTANTS ", 0x00A0ull
},
539 {"ZIP_QUE0_MAP ", 0x1400ull
},
540 {"ZIP_QUE1_MAP ", 0x1408ull
},
541 {"ZIP_QUE_ENA ", 0x0500ull
},
542 {"ZIP_QUE_PRI ", 0x0508ull
},
543 {"ZIP_QUE0_DONE ", 0x2000ull
},
544 {"ZIP_QUE1_DONE ", 0x2008ull
},
545 {"ZIP_QUE0_DOORBELL ", 0x4000ull
},
546 {"ZIP_QUE1_DOORBELL ", 0x4008ull
},
547 {"ZIP_QUE0_SBUF_ADDR ", 0x1000ull
},
548 {"ZIP_QUE1_SBUF_ADDR ", 0x1008ull
},
549 {"ZIP_QUE0_SBUF_CTL ", 0x1200ull
},
550 {"ZIP_QUE1_SBUF_CTL ", 0x1208ull
},
554 /* Prints registers' contents */
555 static int zip_regs_show(struct seq_file
*s
, void *unused
)
558 int i
= 0, index
= 0;
560 for (index
= 0; index
< MAX_ZIP_DEVICES
; index
++) {
561 if (zip_dev
[index
]) {
562 seq_printf(s
, "--------------------------------\n"
563 " ZIP Device %d Registers\n"
564 "--------------------------------\n",
569 while (zipregs
[i
].reg_name
) {
570 val
= zip_reg_read((zip_dev
[index
]->reg_base
+
571 zipregs
[i
].reg_offset
));
572 seq_printf(s
, "%s: 0x%016llx\n",
573 zipregs
[i
].reg_name
, val
);
581 DEFINE_SHOW_ATTRIBUTE(zip_stats
);
582 DEFINE_SHOW_ATTRIBUTE(zip_clear
);
583 DEFINE_SHOW_ATTRIBUTE(zip_regs
);
585 /* Root directory for thunderx_zip debugfs entry */
586 static struct dentry
*zip_debugfs_root
;
588 static void __init
zip_debugfs_init(void)
590 if (!debugfs_initialized())
593 zip_debugfs_root
= debugfs_create_dir("thunderx_zip", NULL
);
595 /* Creating files for entries inside thunderx_zip directory */
596 debugfs_create_file("zip_stats", 0444, zip_debugfs_root
, NULL
,
599 debugfs_create_file("zip_clear", 0444, zip_debugfs_root
, NULL
,
602 debugfs_create_file("zip_regs", 0444, zip_debugfs_root
, NULL
,
607 static void __exit
zip_debugfs_exit(void)
609 debugfs_remove_recursive(zip_debugfs_root
);
613 static void __init
zip_debugfs_init(void) { }
614 static void __exit
zip_debugfs_exit(void) { }
618 static int __init
zip_init_module(void)
622 zip_msg("%s\n", DRV_NAME
);
624 ret
= pci_register_driver(&zip_driver
);
626 zip_err("ZIP: pci_register_driver() failed\n");
630 /* Register with the Kernel Crypto Interface */
631 ret
= zip_register_compression_device();
633 zip_err("ZIP: Kernel Crypto Registration failed\n");
634 goto err_pci_unregister
;
637 /* comp-decomp statistics are handled with debugfs interface */
643 pci_unregister_driver(&zip_driver
);
647 static void __exit
zip_cleanup_module(void)
651 /* Unregister from the kernel crypto interface */
652 zip_unregister_compression_device();
654 /* Unregister this driver for pci zip devices */
655 pci_unregister_driver(&zip_driver
);
658 module_init(zip_init_module
);
659 module_exit(zip_cleanup_module
);
661 MODULE_AUTHOR("Cavium Inc");
662 MODULE_DESCRIPTION("Cavium Inc ThunderX ZIP Driver");
663 MODULE_LICENSE("GPL v2");
664 MODULE_DEVICE_TABLE(pci
, zip_id_table
);