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_deflate.h" 48 49/** 50 * zip_cmd_queue_consumed - Calculates the space consumed in the command queue. 51 * 52 * @zip_dev: Pointer to zip device structure 53 * @queue: Queue number 54 * 55 * Return: Bytes consumed in the command queue buffer. 56 */ 57static inline u32 zip_cmd_queue_consumed(struct zip_device *zip_dev, int queue) 58{ 59 return ((zip_dev->iq[queue].sw_head - zip_dev->iq[queue].sw_tail) * 60 sizeof(u64 *)); 61} 62 63/** 64 * zip_load_instr - Submits the instruction into the ZIP command queue 65 * @instr: Pointer to the instruction to be submitted 66 * @zip_dev: Pointer to ZIP device structure to which the instruction is to 67 * be submitted 68 * 69 * This function copies the ZIP instruction to the command queue and rings the 70 * doorbell to notify the engine of the instruction submission. The command 71 * queue is maintained in a circular fashion. When there is space for exactly 72 * one instruction in the queue, next chunk pointer of the queue is made to 73 * point to the head of the queue, thus maintaining a circular queue. 74 * 75 * Return: Queue number to which the instruction was submitted 76 */ 77u32 zip_load_instr(union zip_inst_s *instr, 78 struct zip_device *zip_dev) 79{ 80 union zip_quex_doorbell dbell; 81 u32 queue = 0; 82 u32 consumed = 0; 83 u64 *ncb_ptr = NULL; 84 union zip_nptr_s ncp; 85 86 /* 87 * Distribute the instructions between the enabled queues based on 88 * the CPU id. 89 */ 90 if (raw_smp_processor_id() % 2 == 0) 91 queue = 0; 92 else 93 queue = 1; 94 95 zip_dbg("CPU Core: %d Queue number:%d", raw_smp_processor_id(), queue); 96 97 /* Take cmd buffer lock */ 98 spin_lock(&zip_dev->iq[queue].lock); 99 100 /* 101 * Command Queue implementation 102 * 1. If there is place for new instructions, push the cmd at sw_head. 103 * 2. If there is place for exactly one instruction, push the new cmd 104 * at the sw_head. Make sw_head point to the sw_tail to make it 105 * circular. Write sw_head's physical address to the "Next-Chunk 106 * Buffer Ptr" to make it cmd_hw_tail. 107 * 3. Ring the door bell. 108 */ 109 zip_dbg("sw_head : %lx", zip_dev->iq[queue].sw_head); 110 zip_dbg("sw_tail : %lx", zip_dev->iq[queue].sw_tail); 111 112 consumed = zip_cmd_queue_consumed(zip_dev, queue); 113 /* Check if there is space to push just one cmd */ 114 if ((consumed + 128) == (ZIP_CMD_QBUF_SIZE - 8)) { 115 zip_dbg("Cmd queue space available for single command"); 116 /* Space for one cmd, pust it and make it circular queue */ 117 memcpy((u8 *)zip_dev->iq[queue].sw_head, (u8 *)instr, 118 sizeof(union zip_inst_s)); 119 zip_dev->iq[queue].sw_head += 16; /* 16 64_bit words = 128B */ 120 121 /* Now, point the "Next-Chunk Buffer Ptr" to sw_head */ 122 ncb_ptr = zip_dev->iq[queue].sw_head; 123 124 zip_dbg("ncb addr :0x%lx sw_head addr :0x%lx", 125 ncb_ptr, zip_dev->iq[queue].sw_head - 16); 126 127 /* Using Circular command queue */ 128 zip_dev->iq[queue].sw_head = zip_dev->iq[queue].sw_tail; 129 /* Mark this buffer for free */ 130 zip_dev->iq[queue].free_flag = 1; 131 132 /* Write new chunk buffer address at "Next-Chunk Buffer Ptr" */ 133 ncp.u_reg64 = 0ull; 134 ncp.s.addr = __pa(zip_dev->iq[queue].sw_head); 135 *ncb_ptr = ncp.u_reg64; 136 zip_dbg("*ncb_ptr :0x%lx sw_head[phys] :0x%lx", 137 *ncb_ptr, __pa(zip_dev->iq[queue].sw_head)); 138 139 zip_dev->iq[queue].pend_cnt++; 140 141 } else { 142 zip_dbg("Enough space is available for commands"); 143 /* Push this cmd to cmd queue buffer */ 144 memcpy((u8 *)zip_dev->iq[queue].sw_head, (u8 *)instr, 145 sizeof(union zip_inst_s)); 146 zip_dev->iq[queue].sw_head += 16; /* 16 64_bit words = 128B */ 147 148 zip_dev->iq[queue].pend_cnt++; 149 } 150 zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx", 151 zip_dev->iq[queue].sw_head, zip_dev->iq[queue].sw_tail, 152 zip_dev->iq[queue].hw_tail); 153 154 zip_dbg(" Pushed the new cmd : pend_cnt : %d", 155 zip_dev->iq[queue].pend_cnt); 156 157 /* Ring the doorbell */ 158 dbell.u_reg64 = 0ull; 159 dbell.s.dbell_cnt = 1; 160 zip_reg_write(dbell.u_reg64, 161 (zip_dev->reg_base + ZIP_QUEX_DOORBELL(queue))); 162 163 /* Unlock cmd buffer lock */ 164 spin_unlock(&zip_dev->iq[queue].lock); 165 166 return queue; 167} 168 169/** 170 * zip_update_cmd_bufs - Updates the queue statistics after posting the 171 * instruction 172 * @zip_dev: Pointer to zip device structure 173 * @queue: Queue number 174 */ 175void zip_update_cmd_bufs(struct zip_device *zip_dev, u32 queue) 176{ 177 /* Take cmd buffer lock */ 178 spin_lock(&zip_dev->iq[queue].lock); 179 180 /* Check if the previous buffer can be freed */ 181 if (zip_dev->iq[queue].free_flag == 1) { 182 zip_dbg("Free flag. Free cmd buffer, adjust sw head and tail"); 183 /* Reset the free flag */ 184 zip_dev->iq[queue].free_flag = 0; 185 186 /* Point the hw_tail to start of the new chunk buffer */ 187 zip_dev->iq[queue].hw_tail = zip_dev->iq[queue].sw_head; 188 } else { 189 zip_dbg("Free flag not set. increment hw tail"); 190 zip_dev->iq[queue].hw_tail += 16; /* 16 64_bit words = 128B */ 191 } 192 193 zip_dev->iq[queue].done_cnt++; 194 zip_dev->iq[queue].pend_cnt--; 195 196 zip_dbg("sw_head :0x%lx sw_tail :0x%lx hw_tail :0x%lx", 197 zip_dev->iq[queue].sw_head, zip_dev->iq[queue].sw_tail, 198 zip_dev->iq[queue].hw_tail); 199 zip_dbg(" Got CC : pend_cnt : %d\n", zip_dev->iq[queue].pend_cnt); 200 201 spin_unlock(&zip_dev->iq[queue].lock); 202} 203