18c2ecf20Sopenharmony_ci/***********************license start************************************ 28c2ecf20Sopenharmony_ci * Copyright (c) 2003-2017 Cavium, Inc. 38c2ecf20Sopenharmony_ci * All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * License: one of 'Cavium License' or 'GNU General Public License Version 2' 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This file is provided under the terms of the Cavium License (see below) 88c2ecf20Sopenharmony_ci * or under the terms of GNU General Public License, Version 2, as 98c2ecf20Sopenharmony_ci * published by the Free Software Foundation. When using or redistributing 108c2ecf20Sopenharmony_ci * this file, you may do so under either license. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Cavium License: Redistribution and use in source and binary forms, with 138c2ecf20Sopenharmony_ci * or without modification, are permitted provided that the following 148c2ecf20Sopenharmony_ci * conditions are met: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * * Redistributions of source code must retain the above copyright 178c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * * Redistributions in binary form must reproduce the above 208c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 218c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials provided 228c2ecf20Sopenharmony_ci * with the distribution. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * * Neither the name of Cavium Inc. nor the names of its contributors may be 258c2ecf20Sopenharmony_ci * used to endorse or promote products derived from this software without 268c2ecf20Sopenharmony_ci * specific prior written permission. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * This Software, including technical data, may be subject to U.S. export 298c2ecf20Sopenharmony_ci * control laws, including the U.S. Export Administration Act and its 308c2ecf20Sopenharmony_ci * associated regulations, and may be subject to export or import 318c2ecf20Sopenharmony_ci * regulations in other countries. 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 348c2ecf20Sopenharmony_ci * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS 358c2ecf20Sopenharmony_ci * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 368c2ecf20Sopenharmony_ci * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 378c2ecf20Sopenharmony_ci * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 388c2ecf20Sopenharmony_ci * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) 398c2ecf20Sopenharmony_ci * WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A 408c2ecf20Sopenharmony_ci * PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET 418c2ecf20Sopenharmony_ci * ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE 428c2ecf20Sopenharmony_ci * ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES 438c2ecf20Sopenharmony_ci * WITH YOU. 448c2ecf20Sopenharmony_ci ***********************license end**************************************/ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include "common.h" 478c2ecf20Sopenharmony_ci#include "zip_deflate.h" 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/** 508c2ecf20Sopenharmony_ci * zip_cmd_queue_consumed - Calculates the space consumed in the command queue. 518c2ecf20Sopenharmony_ci * 528c2ecf20Sopenharmony_ci * @zip_dev: Pointer to zip device structure 538c2ecf20Sopenharmony_ci * @queue: Queue number 548c2ecf20Sopenharmony_ci * 558c2ecf20Sopenharmony_ci * Return: Bytes consumed in the command queue buffer. 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_cistatic inline u32 zip_cmd_queue_consumed(struct zip_device *zip_dev, int queue) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci return ((zip_dev->iq[queue].sw_head - zip_dev->iq[queue].sw_tail) * 608c2ecf20Sopenharmony_ci sizeof(u64 *)); 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/** 648c2ecf20Sopenharmony_ci * zip_load_instr - Submits the instruction into the ZIP command queue 658c2ecf20Sopenharmony_ci * @instr: Pointer to the instruction to be submitted 668c2ecf20Sopenharmony_ci * @zip_dev: Pointer to ZIP device structure to which the instruction is to 678c2ecf20Sopenharmony_ci * be submitted 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci * This function copies the ZIP instruction to the command queue and rings the 708c2ecf20Sopenharmony_ci * doorbell to notify the engine of the instruction submission. The command 718c2ecf20Sopenharmony_ci * queue is maintained in a circular fashion. When there is space for exactly 728c2ecf20Sopenharmony_ci * one instruction in the queue, next chunk pointer of the queue is made to 738c2ecf20Sopenharmony_ci * point to the head of the queue, thus maintaining a circular queue. 748c2ecf20Sopenharmony_ci * 758c2ecf20Sopenharmony_ci * Return: Queue number to which the instruction was submitted 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ciu32 zip_load_instr(union zip_inst_s *instr, 788c2ecf20Sopenharmony_ci struct zip_device *zip_dev) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci union zip_quex_doorbell dbell; 818c2ecf20Sopenharmony_ci u32 queue = 0; 828c2ecf20Sopenharmony_ci u32 consumed = 0; 838c2ecf20Sopenharmony_ci u64 *ncb_ptr = NULL; 848c2ecf20Sopenharmony_ci union zip_nptr_s ncp; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* 878c2ecf20Sopenharmony_ci * Distribute the instructions between the enabled queues based on 888c2ecf20Sopenharmony_ci * the CPU id. 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_ci if (raw_smp_processor_id() % 2 == 0) 918c2ecf20Sopenharmony_ci queue = 0; 928c2ecf20Sopenharmony_ci else 938c2ecf20Sopenharmony_ci queue = 1; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci zip_dbg("CPU Core: %d Queue number:%d", raw_smp_processor_id(), queue); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* Take cmd buffer lock */ 988c2ecf20Sopenharmony_ci spin_lock(&zip_dev->iq[queue].lock); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* 1018c2ecf20Sopenharmony_ci * Command Queue implementation 1028c2ecf20Sopenharmony_ci * 1. If there is place for new instructions, push the cmd at sw_head. 1038c2ecf20Sopenharmony_ci * 2. If there is place for exactly one instruction, push the new cmd 1048c2ecf20Sopenharmony_ci * at the sw_head. Make sw_head point to the sw_tail to make it 1058c2ecf20Sopenharmony_ci * circular. Write sw_head's physical address to the "Next-Chunk 1068c2ecf20Sopenharmony_ci * Buffer Ptr" to make it cmd_hw_tail. 1078c2ecf20Sopenharmony_ci * 3. Ring the door bell. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci zip_dbg("sw_head : %lx", zip_dev->iq[queue].sw_head); 1108c2ecf20Sopenharmony_ci zip_dbg("sw_tail : %lx", zip_dev->iq[queue].sw_tail); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci consumed = zip_cmd_queue_consumed(zip_dev, queue); 1138c2ecf20Sopenharmony_ci /* Check if there is space to push just one cmd */ 1148c2ecf20Sopenharmony_ci if ((consumed + 128) == (ZIP_CMD_QBUF_SIZE - 8)) { 1158c2ecf20Sopenharmony_ci zip_dbg("Cmd queue space available for single command"); 1168c2ecf20Sopenharmony_ci /* Space for one cmd, pust it and make it circular queue */ 1178c2ecf20Sopenharmony_ci memcpy((u8 *)zip_dev->iq[queue].sw_head, (u8 *)instr, 1188c2ecf20Sopenharmony_ci sizeof(union zip_inst_s)); 1198c2ecf20Sopenharmony_ci zip_dev->iq[queue].sw_head += 16; /* 16 64_bit words = 128B */ 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* Now, point the "Next-Chunk Buffer Ptr" to sw_head */ 1228c2ecf20Sopenharmony_ci ncb_ptr = zip_dev->iq[queue].sw_head; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci zip_dbg("ncb addr :0x%lx sw_head addr :0x%lx", 1258c2ecf20Sopenharmony_ci ncb_ptr, zip_dev->iq[queue].sw_head - 16); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* Using Circular command queue */ 1288c2ecf20Sopenharmony_ci zip_dev->iq[queue].sw_head = zip_dev->iq[queue].sw_tail; 1298c2ecf20Sopenharmony_ci /* Mark this buffer for free */ 1308c2ecf20Sopenharmony_ci zip_dev->iq[queue].free_flag = 1; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* Write new chunk buffer address at "Next-Chunk Buffer Ptr" */ 1338c2ecf20Sopenharmony_ci ncp.u_reg64 = 0ull; 1348c2ecf20Sopenharmony_ci ncp.s.addr = __pa(zip_dev->iq[queue].sw_head); 1358c2ecf20Sopenharmony_ci *ncb_ptr = ncp.u_reg64; 1368c2ecf20Sopenharmony_ci zip_dbg("*ncb_ptr :0x%lx sw_head[phys] :0x%lx", 1378c2ecf20Sopenharmony_ci *ncb_ptr, __pa(zip_dev->iq[queue].sw_head)); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci zip_dev->iq[queue].pend_cnt++; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci } else { 1428c2ecf20Sopenharmony_ci zip_dbg("Enough space is available for commands"); 1438c2ecf20Sopenharmony_ci /* Push this cmd to cmd queue buffer */ 1448c2ecf20Sopenharmony_ci memcpy((u8 *)zip_dev->iq[queue].sw_head, (u8 *)instr, 1458c2ecf20Sopenharmony_ci sizeof(union zip_inst_s)); 1468c2ecf20Sopenharmony_ci zip_dev->iq[queue].sw_head += 16; /* 16 64_bit words = 128B */ 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci zip_dev->iq[queue].pend_cnt++; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx", 1518c2ecf20Sopenharmony_ci zip_dev->iq[queue].sw_head, zip_dev->iq[queue].sw_tail, 1528c2ecf20Sopenharmony_ci zip_dev->iq[queue].hw_tail); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci zip_dbg(" Pushed the new cmd : pend_cnt : %d", 1558c2ecf20Sopenharmony_ci zip_dev->iq[queue].pend_cnt); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* Ring the doorbell */ 1588c2ecf20Sopenharmony_ci dbell.u_reg64 = 0ull; 1598c2ecf20Sopenharmony_ci dbell.s.dbell_cnt = 1; 1608c2ecf20Sopenharmony_ci zip_reg_write(dbell.u_reg64, 1618c2ecf20Sopenharmony_ci (zip_dev->reg_base + ZIP_QUEX_DOORBELL(queue))); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Unlock cmd buffer lock */ 1648c2ecf20Sopenharmony_ci spin_unlock(&zip_dev->iq[queue].lock); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci return queue; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci/** 1708c2ecf20Sopenharmony_ci * zip_update_cmd_bufs - Updates the queue statistics after posting the 1718c2ecf20Sopenharmony_ci * instruction 1728c2ecf20Sopenharmony_ci * @zip_dev: Pointer to zip device structure 1738c2ecf20Sopenharmony_ci * @queue: Queue number 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_civoid zip_update_cmd_bufs(struct zip_device *zip_dev, u32 queue) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci /* Take cmd buffer lock */ 1788c2ecf20Sopenharmony_ci spin_lock(&zip_dev->iq[queue].lock); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* Check if the previous buffer can be freed */ 1818c2ecf20Sopenharmony_ci if (zip_dev->iq[queue].free_flag == 1) { 1828c2ecf20Sopenharmony_ci zip_dbg("Free flag. Free cmd buffer, adjust sw head and tail"); 1838c2ecf20Sopenharmony_ci /* Reset the free flag */ 1848c2ecf20Sopenharmony_ci zip_dev->iq[queue].free_flag = 0; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci /* Point the hw_tail to start of the new chunk buffer */ 1878c2ecf20Sopenharmony_ci zip_dev->iq[queue].hw_tail = zip_dev->iq[queue].sw_head; 1888c2ecf20Sopenharmony_ci } else { 1898c2ecf20Sopenharmony_ci zip_dbg("Free flag not set. increment hw tail"); 1908c2ecf20Sopenharmony_ci zip_dev->iq[queue].hw_tail += 16; /* 16 64_bit words = 128B */ 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci zip_dev->iq[queue].done_cnt++; 1948c2ecf20Sopenharmony_ci zip_dev->iq[queue].pend_cnt--; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx", 1978c2ecf20Sopenharmony_ci zip_dev->iq[queue].sw_head, zip_dev->iq[queue].sw_tail, 1988c2ecf20Sopenharmony_ci zip_dev->iq[queue].hw_tail); 1998c2ecf20Sopenharmony_ci zip_dbg(" Got CC : pend_cnt : %d\n", zip_dev->iq[queue].pend_cnt); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci spin_unlock(&zip_dev->iq[queue].lock); 2028c2ecf20Sopenharmony_ci} 203