162306a36Sopenharmony_ci/***********************license start************************************ 262306a36Sopenharmony_ci * Copyright (c) 2003-2017 Cavium, Inc. 362306a36Sopenharmony_ci * All rights reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * License: one of 'Cavium License' or 'GNU General Public License Version 2' 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This file is provided under the terms of the Cavium License (see below) 862306a36Sopenharmony_ci * or under the terms of GNU General Public License, Version 2, as 962306a36Sopenharmony_ci * published by the Free Software Foundation. When using or redistributing 1062306a36Sopenharmony_ci * this file, you may do so under either license. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Cavium License: Redistribution and use in source and binary forms, with 1362306a36Sopenharmony_ci * or without modification, are permitted provided that the following 1462306a36Sopenharmony_ci * conditions are met: 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * * Redistributions of source code must retain the above copyright 1762306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * * Redistributions in binary form must reproduce the above 2062306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2162306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials provided 2262306a36Sopenharmony_ci * with the distribution. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * * Neither the name of Cavium Inc. nor the names of its contributors may be 2562306a36Sopenharmony_ci * used to endorse or promote products derived from this software without 2662306a36Sopenharmony_ci * specific prior written permission. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * This Software, including technical data, may be subject to U.S. export 2962306a36Sopenharmony_ci * control laws, including the U.S. Export Administration Act and its 3062306a36Sopenharmony_ci * associated regulations, and may be subject to export or import 3162306a36Sopenharmony_ci * regulations in other countries. 3262306a36Sopenharmony_ci * 3362306a36Sopenharmony_ci * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 3462306a36Sopenharmony_ci * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS 3562306a36Sopenharmony_ci * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 3662306a36Sopenharmony_ci * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 3762306a36Sopenharmony_ci * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 3862306a36Sopenharmony_ci * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) 3962306a36Sopenharmony_ci * WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A 4062306a36Sopenharmony_ci * PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET 4162306a36Sopenharmony_ci * ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE 4262306a36Sopenharmony_ci * ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES 4362306a36Sopenharmony_ci * WITH YOU. 4462306a36Sopenharmony_ci ***********************license end**************************************/ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#include "common.h" 4762306a36Sopenharmony_ci#include "zip_crypto.h" 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define DRV_NAME "ThunderX-ZIP" 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic struct zip_device *zip_dev[MAX_ZIP_DEVICES]; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic const struct pci_device_id zip_id_table[] = { 5462306a36Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDERX_ZIP) }, 5562306a36Sopenharmony_ci { 0, } 5662306a36Sopenharmony_ci}; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic void zip_debugfs_init(void); 5962306a36Sopenharmony_cistatic void zip_debugfs_exit(void); 6062306a36Sopenharmony_cistatic int zip_register_compression_device(void); 6162306a36Sopenharmony_cistatic void zip_unregister_compression_device(void); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_civoid zip_reg_write(u64 val, u64 __iomem *addr) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci writeq(val, addr); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ciu64 zip_reg_read(u64 __iomem *addr) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci return readq(addr); 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* 7462306a36Sopenharmony_ci * Allocates new ZIP device structure 7562306a36Sopenharmony_ci * Returns zip_device pointer or NULL if cannot allocate memory for zip_device 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_cistatic struct zip_device *zip_alloc_device(struct pci_dev *pdev) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct zip_device *zip = NULL; 8062306a36Sopenharmony_ci int idx; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci for (idx = 0; idx < MAX_ZIP_DEVICES; idx++) { 8362306a36Sopenharmony_ci if (!zip_dev[idx]) 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci /* To ensure that the index is within the limit */ 8862306a36Sopenharmony_ci if (idx < MAX_ZIP_DEVICES) 8962306a36Sopenharmony_ci zip = devm_kzalloc(&pdev->dev, sizeof(*zip), GFP_KERNEL); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (!zip) 9262306a36Sopenharmony_ci return NULL; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci zip_dev[idx] = zip; 9562306a36Sopenharmony_ci zip->index = idx; 9662306a36Sopenharmony_ci return zip; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/** 10062306a36Sopenharmony_ci * zip_get_device - Get ZIP device based on node id of cpu 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * @node: Node id of the current cpu 10362306a36Sopenharmony_ci * Return: Pointer to Zip device structure 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_cistruct zip_device *zip_get_device(int node) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci if ((node < MAX_ZIP_DEVICES) && (node >= 0)) 10862306a36Sopenharmony_ci return zip_dev[node]; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci zip_err("ZIP device not found for node id %d\n", node); 11162306a36Sopenharmony_ci return NULL; 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/** 11562306a36Sopenharmony_ci * zip_get_node_id - Get the node id of the current cpu 11662306a36Sopenharmony_ci * 11762306a36Sopenharmony_ci * Return: Node id of the current cpu 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_ciint zip_get_node_id(void) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci return cpu_to_node(raw_smp_processor_id()); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/* Initializes the ZIP h/w sub-system */ 12562306a36Sopenharmony_cistatic int zip_init_hw(struct zip_device *zip) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci union zip_cmd_ctl cmd_ctl; 12862306a36Sopenharmony_ci union zip_constants constants; 12962306a36Sopenharmony_ci union zip_que_ena que_ena; 13062306a36Sopenharmony_ci union zip_quex_map que_map; 13162306a36Sopenharmony_ci union zip_que_pri que_pri; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci union zip_quex_sbuf_addr que_sbuf_addr; 13462306a36Sopenharmony_ci union zip_quex_sbuf_ctl que_sbuf_ctl; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci int q = 0; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* Enable the ZIP Engine(Core) Clock */ 13962306a36Sopenharmony_ci cmd_ctl.u_reg64 = zip_reg_read(zip->reg_base + ZIP_CMD_CTL); 14062306a36Sopenharmony_ci cmd_ctl.s.forceclk = 1; 14162306a36Sopenharmony_ci zip_reg_write(cmd_ctl.u_reg64 & 0xFF, (zip->reg_base + ZIP_CMD_CTL)); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci zip_msg("ZIP_CMD_CTL : 0x%016llx", 14462306a36Sopenharmony_ci zip_reg_read(zip->reg_base + ZIP_CMD_CTL)); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci constants.u_reg64 = zip_reg_read(zip->reg_base + ZIP_CONSTANTS); 14762306a36Sopenharmony_ci zip->depth = constants.s.depth; 14862306a36Sopenharmony_ci zip->onfsize = constants.s.onfsize; 14962306a36Sopenharmony_ci zip->ctxsize = constants.s.ctxsize; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci zip_msg("depth: 0x%016llx , onfsize : 0x%016llx , ctxsize : 0x%016llx", 15262306a36Sopenharmony_ci zip->depth, zip->onfsize, zip->ctxsize); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci /* 15562306a36Sopenharmony_ci * Program ZIP_QUE(0..7)_SBUF_ADDR and ZIP_QUE(0..7)_SBUF_CTL to 15662306a36Sopenharmony_ci * have the correct buffer pointer and size configured for each 15762306a36Sopenharmony_ci * instruction queue. 15862306a36Sopenharmony_ci */ 15962306a36Sopenharmony_ci for (q = 0; q < ZIP_NUM_QUEUES; q++) { 16062306a36Sopenharmony_ci que_sbuf_ctl.u_reg64 = 0ull; 16162306a36Sopenharmony_ci que_sbuf_ctl.s.size = (ZIP_CMD_QBUF_SIZE / sizeof(u64)); 16262306a36Sopenharmony_ci que_sbuf_ctl.s.inst_be = 0; 16362306a36Sopenharmony_ci que_sbuf_ctl.s.stream_id = 0; 16462306a36Sopenharmony_ci zip_reg_write(que_sbuf_ctl.u_reg64, 16562306a36Sopenharmony_ci (zip->reg_base + ZIP_QUEX_SBUF_CTL(q))); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci zip_msg("QUEX_SBUF_CTL[%d]: 0x%016llx", q, 16862306a36Sopenharmony_ci zip_reg_read(zip->reg_base + ZIP_QUEX_SBUF_CTL(q))); 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci for (q = 0; q < ZIP_NUM_QUEUES; q++) { 17262306a36Sopenharmony_ci memset(&zip->iq[q], 0x0, sizeof(struct zip_iq)); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci spin_lock_init(&zip->iq[q].lock); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci if (zip_cmd_qbuf_alloc(zip, q)) { 17762306a36Sopenharmony_ci while (q != 0) { 17862306a36Sopenharmony_ci q--; 17962306a36Sopenharmony_ci zip_cmd_qbuf_free(zip, q); 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci return -ENOMEM; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci /* Initialize tail ptr to head */ 18562306a36Sopenharmony_ci zip->iq[q].sw_tail = zip->iq[q].sw_head; 18662306a36Sopenharmony_ci zip->iq[q].hw_tail = zip->iq[q].sw_head; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* Write the physical addr to register */ 18962306a36Sopenharmony_ci que_sbuf_addr.u_reg64 = 0ull; 19062306a36Sopenharmony_ci que_sbuf_addr.s.ptr = (__pa(zip->iq[q].sw_head) >> 19162306a36Sopenharmony_ci ZIP_128B_ALIGN); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci zip_msg("QUE[%d]_PTR(PHYS): 0x%016llx", q, 19462306a36Sopenharmony_ci (u64)que_sbuf_addr.s.ptr); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci zip_reg_write(que_sbuf_addr.u_reg64, 19762306a36Sopenharmony_ci (zip->reg_base + ZIP_QUEX_SBUF_ADDR(q))); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci zip_msg("QUEX_SBUF_ADDR[%d]: 0x%016llx", q, 20062306a36Sopenharmony_ci zip_reg_read(zip->reg_base + ZIP_QUEX_SBUF_ADDR(q))); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx", 20362306a36Sopenharmony_ci zip->iq[q].sw_head, zip->iq[q].sw_tail, 20462306a36Sopenharmony_ci zip->iq[q].hw_tail); 20562306a36Sopenharmony_ci zip_dbg("sw_head phy addr : 0x%lx", que_sbuf_addr.s.ptr); 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* 20962306a36Sopenharmony_ci * Queue-to-ZIP core mapping 21062306a36Sopenharmony_ci * If a queue is not mapped to a particular core, it is equivalent to 21162306a36Sopenharmony_ci * the ZIP core being disabled. 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_ci que_ena.u_reg64 = 0x0ull; 21462306a36Sopenharmony_ci /* Enabling queues based on ZIP_NUM_QUEUES */ 21562306a36Sopenharmony_ci for (q = 0; q < ZIP_NUM_QUEUES; q++) 21662306a36Sopenharmony_ci que_ena.s.ena |= (0x1 << q); 21762306a36Sopenharmony_ci zip_reg_write(que_ena.u_reg64, (zip->reg_base + ZIP_QUE_ENA)); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci zip_msg("QUE_ENA : 0x%016llx", 22062306a36Sopenharmony_ci zip_reg_read(zip->reg_base + ZIP_QUE_ENA)); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci for (q = 0; q < ZIP_NUM_QUEUES; q++) { 22362306a36Sopenharmony_ci que_map.u_reg64 = 0ull; 22462306a36Sopenharmony_ci /* Mapping each queue to two ZIP cores */ 22562306a36Sopenharmony_ci que_map.s.zce = 0x3; 22662306a36Sopenharmony_ci zip_reg_write(que_map.u_reg64, 22762306a36Sopenharmony_ci (zip->reg_base + ZIP_QUEX_MAP(q))); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci zip_msg("QUE_MAP(%d) : 0x%016llx", q, 23062306a36Sopenharmony_ci zip_reg_read(zip->reg_base + ZIP_QUEX_MAP(q))); 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci que_pri.u_reg64 = 0ull; 23462306a36Sopenharmony_ci for (q = 0; q < ZIP_NUM_QUEUES; q++) 23562306a36Sopenharmony_ci que_pri.s.pri |= (0x1 << q); /* Higher Priority RR */ 23662306a36Sopenharmony_ci zip_reg_write(que_pri.u_reg64, (zip->reg_base + ZIP_QUE_PRI)); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci zip_msg("QUE_PRI %016llx", zip_reg_read(zip->reg_base + ZIP_QUE_PRI)); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci return 0; 24162306a36Sopenharmony_ci} 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_cistatic void zip_reset(struct zip_device *zip) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci union zip_cmd_ctl cmd_ctl; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci cmd_ctl.u_reg64 = 0x0ull; 24862306a36Sopenharmony_ci cmd_ctl.s.reset = 1; /* Forces ZIP cores to do reset */ 24962306a36Sopenharmony_ci zip_reg_write(cmd_ctl.u_reg64, (zip->reg_base + ZIP_CMD_CTL)); 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistatic int zip_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci struct device *dev = &pdev->dev; 25562306a36Sopenharmony_ci struct zip_device *zip = NULL; 25662306a36Sopenharmony_ci int err; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci zip = zip_alloc_device(pdev); 25962306a36Sopenharmony_ci if (!zip) 26062306a36Sopenharmony_ci return -ENOMEM; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci dev_info(dev, "Found ZIP device %d %x:%x on Node %d\n", zip->index, 26362306a36Sopenharmony_ci pdev->vendor, pdev->device, dev_to_node(dev)); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci pci_set_drvdata(pdev, zip); 26662306a36Sopenharmony_ci zip->pdev = pdev; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci err = pci_enable_device(pdev); 26962306a36Sopenharmony_ci if (err) { 27062306a36Sopenharmony_ci dev_err(dev, "Failed to enable PCI device"); 27162306a36Sopenharmony_ci goto err_free_device; 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci err = pci_request_regions(pdev, DRV_NAME); 27562306a36Sopenharmony_ci if (err) { 27662306a36Sopenharmony_ci dev_err(dev, "PCI request regions failed 0x%x", err); 27762306a36Sopenharmony_ci goto err_disable_device; 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(48)); 28162306a36Sopenharmony_ci if (err) { 28262306a36Sopenharmony_ci dev_err(dev, "Unable to get usable 48-bit DMA configuration\n"); 28362306a36Sopenharmony_ci goto err_release_regions; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* MAP configuration registers */ 28762306a36Sopenharmony_ci zip->reg_base = pci_ioremap_bar(pdev, PCI_CFG_ZIP_PF_BAR0); 28862306a36Sopenharmony_ci if (!zip->reg_base) { 28962306a36Sopenharmony_ci dev_err(dev, "ZIP: Cannot map BAR0 CSR memory space, aborting"); 29062306a36Sopenharmony_ci err = -ENOMEM; 29162306a36Sopenharmony_ci goto err_release_regions; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* Initialize ZIP Hardware */ 29562306a36Sopenharmony_ci err = zip_init_hw(zip); 29662306a36Sopenharmony_ci if (err) 29762306a36Sopenharmony_ci goto err_release_regions; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* Register with the Kernel Crypto Interface */ 30062306a36Sopenharmony_ci err = zip_register_compression_device(); 30162306a36Sopenharmony_ci if (err < 0) { 30262306a36Sopenharmony_ci zip_err("ZIP: Kernel Crypto Registration failed\n"); 30362306a36Sopenharmony_ci goto err_register; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* comp-decomp statistics are handled with debugfs interface */ 30762306a36Sopenharmony_ci zip_debugfs_init(); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci return 0; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cierr_register: 31262306a36Sopenharmony_ci zip_reset(zip); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cierr_release_regions: 31562306a36Sopenharmony_ci if (zip->reg_base) 31662306a36Sopenharmony_ci iounmap(zip->reg_base); 31762306a36Sopenharmony_ci pci_release_regions(pdev); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cierr_disable_device: 32062306a36Sopenharmony_ci pci_disable_device(pdev); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cierr_free_device: 32362306a36Sopenharmony_ci pci_set_drvdata(pdev, NULL); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci /* Remove zip_dev from zip_device list, free the zip_device memory */ 32662306a36Sopenharmony_ci zip_dev[zip->index] = NULL; 32762306a36Sopenharmony_ci devm_kfree(dev, zip); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci return err; 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic void zip_remove(struct pci_dev *pdev) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci struct zip_device *zip = pci_get_drvdata(pdev); 33562306a36Sopenharmony_ci int q = 0; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci if (!zip) 33862306a36Sopenharmony_ci return; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci zip_debugfs_exit(); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci zip_unregister_compression_device(); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (zip->reg_base) { 34562306a36Sopenharmony_ci zip_reset(zip); 34662306a36Sopenharmony_ci iounmap(zip->reg_base); 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci pci_release_regions(pdev); 35062306a36Sopenharmony_ci pci_disable_device(pdev); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* 35362306a36Sopenharmony_ci * Free Command Queue buffers. This free should be called for all 35462306a36Sopenharmony_ci * the enabled Queues. 35562306a36Sopenharmony_ci */ 35662306a36Sopenharmony_ci for (q = 0; q < ZIP_NUM_QUEUES; q++) 35762306a36Sopenharmony_ci zip_cmd_qbuf_free(zip, q); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci pci_set_drvdata(pdev, NULL); 36062306a36Sopenharmony_ci /* remove zip device from zip device list */ 36162306a36Sopenharmony_ci zip_dev[zip->index] = NULL; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci/* PCI Sub-System Interface */ 36562306a36Sopenharmony_cistatic struct pci_driver zip_driver = { 36662306a36Sopenharmony_ci .name = DRV_NAME, 36762306a36Sopenharmony_ci .id_table = zip_id_table, 36862306a36Sopenharmony_ci .probe = zip_probe, 36962306a36Sopenharmony_ci .remove = zip_remove, 37062306a36Sopenharmony_ci}; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci/* Kernel Crypto Subsystem Interface */ 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic struct crypto_alg zip_comp_deflate = { 37562306a36Sopenharmony_ci .cra_name = "deflate", 37662306a36Sopenharmony_ci .cra_driver_name = "deflate-cavium", 37762306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, 37862306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct zip_kernel_ctx), 37962306a36Sopenharmony_ci .cra_priority = 300, 38062306a36Sopenharmony_ci .cra_module = THIS_MODULE, 38162306a36Sopenharmony_ci .cra_init = zip_alloc_comp_ctx_deflate, 38262306a36Sopenharmony_ci .cra_exit = zip_free_comp_ctx, 38362306a36Sopenharmony_ci .cra_u = { .compress = { 38462306a36Sopenharmony_ci .coa_compress = zip_comp_compress, 38562306a36Sopenharmony_ci .coa_decompress = zip_comp_decompress 38662306a36Sopenharmony_ci } } 38762306a36Sopenharmony_ci}; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_cistatic struct crypto_alg zip_comp_lzs = { 39062306a36Sopenharmony_ci .cra_name = "lzs", 39162306a36Sopenharmony_ci .cra_driver_name = "lzs-cavium", 39262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, 39362306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct zip_kernel_ctx), 39462306a36Sopenharmony_ci .cra_priority = 300, 39562306a36Sopenharmony_ci .cra_module = THIS_MODULE, 39662306a36Sopenharmony_ci .cra_init = zip_alloc_comp_ctx_lzs, 39762306a36Sopenharmony_ci .cra_exit = zip_free_comp_ctx, 39862306a36Sopenharmony_ci .cra_u = { .compress = { 39962306a36Sopenharmony_ci .coa_compress = zip_comp_compress, 40062306a36Sopenharmony_ci .coa_decompress = zip_comp_decompress 40162306a36Sopenharmony_ci } } 40262306a36Sopenharmony_ci}; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_cistatic struct scomp_alg zip_scomp_deflate = { 40562306a36Sopenharmony_ci .alloc_ctx = zip_alloc_scomp_ctx_deflate, 40662306a36Sopenharmony_ci .free_ctx = zip_free_scomp_ctx, 40762306a36Sopenharmony_ci .compress = zip_scomp_compress, 40862306a36Sopenharmony_ci .decompress = zip_scomp_decompress, 40962306a36Sopenharmony_ci .base = { 41062306a36Sopenharmony_ci .cra_name = "deflate", 41162306a36Sopenharmony_ci .cra_driver_name = "deflate-scomp-cavium", 41262306a36Sopenharmony_ci .cra_module = THIS_MODULE, 41362306a36Sopenharmony_ci .cra_priority = 300, 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci}; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic struct scomp_alg zip_scomp_lzs = { 41862306a36Sopenharmony_ci .alloc_ctx = zip_alloc_scomp_ctx_lzs, 41962306a36Sopenharmony_ci .free_ctx = zip_free_scomp_ctx, 42062306a36Sopenharmony_ci .compress = zip_scomp_compress, 42162306a36Sopenharmony_ci .decompress = zip_scomp_decompress, 42262306a36Sopenharmony_ci .base = { 42362306a36Sopenharmony_ci .cra_name = "lzs", 42462306a36Sopenharmony_ci .cra_driver_name = "lzs-scomp-cavium", 42562306a36Sopenharmony_ci .cra_module = THIS_MODULE, 42662306a36Sopenharmony_ci .cra_priority = 300, 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci}; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic int zip_register_compression_device(void) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci int ret; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci ret = crypto_register_alg(&zip_comp_deflate); 43562306a36Sopenharmony_ci if (ret < 0) { 43662306a36Sopenharmony_ci zip_err("Deflate algorithm registration failed\n"); 43762306a36Sopenharmony_ci return ret; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci ret = crypto_register_alg(&zip_comp_lzs); 44162306a36Sopenharmony_ci if (ret < 0) { 44262306a36Sopenharmony_ci zip_err("LZS algorithm registration failed\n"); 44362306a36Sopenharmony_ci goto err_unregister_alg_deflate; 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci ret = crypto_register_scomp(&zip_scomp_deflate); 44762306a36Sopenharmony_ci if (ret < 0) { 44862306a36Sopenharmony_ci zip_err("Deflate scomp algorithm registration failed\n"); 44962306a36Sopenharmony_ci goto err_unregister_alg_lzs; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci ret = crypto_register_scomp(&zip_scomp_lzs); 45362306a36Sopenharmony_ci if (ret < 0) { 45462306a36Sopenharmony_ci zip_err("LZS scomp algorithm registration failed\n"); 45562306a36Sopenharmony_ci goto err_unregister_scomp_deflate; 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci return ret; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cierr_unregister_scomp_deflate: 46162306a36Sopenharmony_ci crypto_unregister_scomp(&zip_scomp_deflate); 46262306a36Sopenharmony_cierr_unregister_alg_lzs: 46362306a36Sopenharmony_ci crypto_unregister_alg(&zip_comp_lzs); 46462306a36Sopenharmony_cierr_unregister_alg_deflate: 46562306a36Sopenharmony_ci crypto_unregister_alg(&zip_comp_deflate); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci return ret; 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic void zip_unregister_compression_device(void) 47162306a36Sopenharmony_ci{ 47262306a36Sopenharmony_ci crypto_unregister_alg(&zip_comp_deflate); 47362306a36Sopenharmony_ci crypto_unregister_alg(&zip_comp_lzs); 47462306a36Sopenharmony_ci crypto_unregister_scomp(&zip_scomp_deflate); 47562306a36Sopenharmony_ci crypto_unregister_scomp(&zip_scomp_lzs); 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci/* 47962306a36Sopenharmony_ci * debugfs functions 48062306a36Sopenharmony_ci */ 48162306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 48262306a36Sopenharmony_ci#include <linux/debugfs.h> 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci/* Displays ZIP device statistics */ 48562306a36Sopenharmony_cistatic int zip_stats_show(struct seq_file *s, void *unused) 48662306a36Sopenharmony_ci{ 48762306a36Sopenharmony_ci u64 val = 0ull; 48862306a36Sopenharmony_ci u64 avg_chunk = 0ull, avg_cr = 0ull; 48962306a36Sopenharmony_ci u32 q = 0; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci int index = 0; 49262306a36Sopenharmony_ci struct zip_device *zip; 49362306a36Sopenharmony_ci struct zip_stats *st; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci for (index = 0; index < MAX_ZIP_DEVICES; index++) { 49662306a36Sopenharmony_ci u64 pending = 0; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci if (zip_dev[index]) { 49962306a36Sopenharmony_ci zip = zip_dev[index]; 50062306a36Sopenharmony_ci st = &zip->stats; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* Get all the pending requests */ 50362306a36Sopenharmony_ci for (q = 0; q < ZIP_NUM_QUEUES; q++) { 50462306a36Sopenharmony_ci val = zip_reg_read((zip->reg_base + 50562306a36Sopenharmony_ci ZIP_DBG_QUEX_STA(q))); 50662306a36Sopenharmony_ci pending += val >> 32 & 0xffffff; 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci val = atomic64_read(&st->comp_req_complete); 51062306a36Sopenharmony_ci avg_chunk = (val) ? atomic64_read(&st->comp_in_bytes) / val : 0; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci val = atomic64_read(&st->comp_out_bytes); 51362306a36Sopenharmony_ci avg_cr = (val) ? atomic64_read(&st->comp_in_bytes) / val : 0; 51462306a36Sopenharmony_ci seq_printf(s, " ZIP Device %d Stats\n" 51562306a36Sopenharmony_ci "-----------------------------------\n" 51662306a36Sopenharmony_ci "Comp Req Submitted : \t%lld\n" 51762306a36Sopenharmony_ci "Comp Req Completed : \t%lld\n" 51862306a36Sopenharmony_ci "Compress In Bytes : \t%lld\n" 51962306a36Sopenharmony_ci "Compressed Out Bytes : \t%lld\n" 52062306a36Sopenharmony_ci "Average Chunk size : \t%llu\n" 52162306a36Sopenharmony_ci "Average Compression ratio : \t%llu\n" 52262306a36Sopenharmony_ci "Decomp Req Submitted : \t%lld\n" 52362306a36Sopenharmony_ci "Decomp Req Completed : \t%lld\n" 52462306a36Sopenharmony_ci "Decompress In Bytes : \t%lld\n" 52562306a36Sopenharmony_ci "Decompressed Out Bytes : \t%lld\n" 52662306a36Sopenharmony_ci "Decompress Bad requests : \t%lld\n" 52762306a36Sopenharmony_ci "Pending Req : \t%lld\n" 52862306a36Sopenharmony_ci "---------------------------------\n", 52962306a36Sopenharmony_ci index, 53062306a36Sopenharmony_ci (u64)atomic64_read(&st->comp_req_submit), 53162306a36Sopenharmony_ci (u64)atomic64_read(&st->comp_req_complete), 53262306a36Sopenharmony_ci (u64)atomic64_read(&st->comp_in_bytes), 53362306a36Sopenharmony_ci (u64)atomic64_read(&st->comp_out_bytes), 53462306a36Sopenharmony_ci avg_chunk, 53562306a36Sopenharmony_ci avg_cr, 53662306a36Sopenharmony_ci (u64)atomic64_read(&st->decomp_req_submit), 53762306a36Sopenharmony_ci (u64)atomic64_read(&st->decomp_req_complete), 53862306a36Sopenharmony_ci (u64)atomic64_read(&st->decomp_in_bytes), 53962306a36Sopenharmony_ci (u64)atomic64_read(&st->decomp_out_bytes), 54062306a36Sopenharmony_ci (u64)atomic64_read(&st->decomp_bad_reqs), 54162306a36Sopenharmony_ci pending); 54262306a36Sopenharmony_ci } 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci return 0; 54562306a36Sopenharmony_ci} 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci/* Clears stats data */ 54862306a36Sopenharmony_cistatic int zip_clear_show(struct seq_file *s, void *unused) 54962306a36Sopenharmony_ci{ 55062306a36Sopenharmony_ci int index = 0; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci for (index = 0; index < MAX_ZIP_DEVICES; index++) { 55362306a36Sopenharmony_ci if (zip_dev[index]) { 55462306a36Sopenharmony_ci memset(&zip_dev[index]->stats, 0, 55562306a36Sopenharmony_ci sizeof(struct zip_stats)); 55662306a36Sopenharmony_ci seq_printf(s, "Cleared stats for zip %d\n", index); 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci return 0; 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_cistatic struct zip_registers zipregs[64] = { 56462306a36Sopenharmony_ci {"ZIP_CMD_CTL ", 0x0000ull}, 56562306a36Sopenharmony_ci {"ZIP_THROTTLE ", 0x0010ull}, 56662306a36Sopenharmony_ci {"ZIP_CONSTANTS ", 0x00A0ull}, 56762306a36Sopenharmony_ci {"ZIP_QUE0_MAP ", 0x1400ull}, 56862306a36Sopenharmony_ci {"ZIP_QUE1_MAP ", 0x1408ull}, 56962306a36Sopenharmony_ci {"ZIP_QUE_ENA ", 0x0500ull}, 57062306a36Sopenharmony_ci {"ZIP_QUE_PRI ", 0x0508ull}, 57162306a36Sopenharmony_ci {"ZIP_QUE0_DONE ", 0x2000ull}, 57262306a36Sopenharmony_ci {"ZIP_QUE1_DONE ", 0x2008ull}, 57362306a36Sopenharmony_ci {"ZIP_QUE0_DOORBELL ", 0x4000ull}, 57462306a36Sopenharmony_ci {"ZIP_QUE1_DOORBELL ", 0x4008ull}, 57562306a36Sopenharmony_ci {"ZIP_QUE0_SBUF_ADDR ", 0x1000ull}, 57662306a36Sopenharmony_ci {"ZIP_QUE1_SBUF_ADDR ", 0x1008ull}, 57762306a36Sopenharmony_ci {"ZIP_QUE0_SBUF_CTL ", 0x1200ull}, 57862306a36Sopenharmony_ci {"ZIP_QUE1_SBUF_CTL ", 0x1208ull}, 57962306a36Sopenharmony_ci { NULL, 0} 58062306a36Sopenharmony_ci}; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci/* Prints registers' contents */ 58362306a36Sopenharmony_cistatic int zip_regs_show(struct seq_file *s, void *unused) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci u64 val = 0; 58662306a36Sopenharmony_ci int i = 0, index = 0; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci for (index = 0; index < MAX_ZIP_DEVICES; index++) { 58962306a36Sopenharmony_ci if (zip_dev[index]) { 59062306a36Sopenharmony_ci seq_printf(s, "--------------------------------\n" 59162306a36Sopenharmony_ci " ZIP Device %d Registers\n" 59262306a36Sopenharmony_ci "--------------------------------\n", 59362306a36Sopenharmony_ci index); 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci i = 0; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci while (zipregs[i].reg_name) { 59862306a36Sopenharmony_ci val = zip_reg_read((zip_dev[index]->reg_base + 59962306a36Sopenharmony_ci zipregs[i].reg_offset)); 60062306a36Sopenharmony_ci seq_printf(s, "%s: 0x%016llx\n", 60162306a36Sopenharmony_ci zipregs[i].reg_name, val); 60262306a36Sopenharmony_ci i++; 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci return 0; 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(zip_stats); 61062306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(zip_clear); 61162306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(zip_regs); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci/* Root directory for thunderx_zip debugfs entry */ 61462306a36Sopenharmony_cistatic struct dentry *zip_debugfs_root; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_cistatic void zip_debugfs_init(void) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci if (!debugfs_initialized()) 61962306a36Sopenharmony_ci return; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci zip_debugfs_root = debugfs_create_dir("thunderx_zip", NULL); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* Creating files for entries inside thunderx_zip directory */ 62462306a36Sopenharmony_ci debugfs_create_file("zip_stats", 0444, zip_debugfs_root, NULL, 62562306a36Sopenharmony_ci &zip_stats_fops); 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci debugfs_create_file("zip_clear", 0444, zip_debugfs_root, NULL, 62862306a36Sopenharmony_ci &zip_clear_fops); 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci debugfs_create_file("zip_regs", 0444, zip_debugfs_root, NULL, 63162306a36Sopenharmony_ci &zip_regs_fops); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci} 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_cistatic void zip_debugfs_exit(void) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci debugfs_remove_recursive(zip_debugfs_root); 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci#else 64162306a36Sopenharmony_cistatic void __init zip_debugfs_init(void) { } 64262306a36Sopenharmony_cistatic void __exit zip_debugfs_exit(void) { } 64362306a36Sopenharmony_ci#endif 64462306a36Sopenharmony_ci/* debugfs - end */ 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cimodule_pci_driver(zip_driver); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ciMODULE_AUTHOR("Cavium Inc"); 64962306a36Sopenharmony_ciMODULE_DESCRIPTION("Cavium Inc ThunderX ZIP Driver"); 65062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 65162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, zip_id_table); 652