1/***********************license start*************** 2 * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 18 * * Neither the name of Cavium Inc. nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 23 * This Software, including technical data, may be subject to U.S. export control 24 * laws, including the U.S. Export Administration Act and its associated 25 * regulations, and may be subject to export or import regulations in other 26 * countries. 27 28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38 ***********************license end**************************************/ 39 40 41 42 43 44 45 46/** 47 * @file 48 * 49 * IPD Support. 50 * 51 * <hr>$Revision: 58943 $<hr> 52 */ 53#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 54#include <linux/module.h> 55#include <asm/octeon/cvmx.h> 56#include <asm/octeon/cvmx-config.h> 57#include <asm/octeon/cvmx-bootmem.h> 58#include <asm/octeon/cvmx-pip-defs.h> 59#include <asm/octeon/cvmx-dbg-defs.h> 60#include <asm/octeon/cvmx-sso-defs.h> 61 62#include <asm/octeon/cvmx-fpa.h> 63#include <asm/octeon/cvmx-wqe.h> 64#include <asm/octeon/cvmx-ipd.h> 65#include <asm/octeon/cvmx-clock.h> 66#include <asm/octeon/cvmx-helper-errata.h> 67#include <asm/octeon/cvmx-helper-cfg.h> 68#else 69#if !defined(__FreeBSD__) || !defined(_KERNEL) 70#include "executive-config.h" 71#endif 72#include "cvmx.h" 73#include "cvmx-sysinfo.h" 74#include "cvmx-bootmem.h" 75#include "cvmx-version.h" 76#include "cvmx-helper-check-defines.h" 77#if !defined(__FreeBSD__) || !defined(_KERNEL) 78#include "cvmx-error.h" 79#include "cvmx-config.h" 80#endif 81 82#include "cvmx-fpa.h" 83#include "cvmx-wqe.h" 84#include "cvmx-ipd.h" 85#include "cvmx-helper-errata.h" 86#include "cvmx-helper-cfg.h" 87#endif 88 89#ifdef CVMX_ENABLE_PKO_FUNCTIONS 90static void __cvmx_ipd_free_ptr_v1(void) 91{ 92 /* Only CN38XXp{1,2} cannot read pointer out of the IPD */ 93 if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) { 94 int no_wptr = 0; 95 cvmx_ipd_ptr_count_t ipd_ptr_count; 96 ipd_ptr_count.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT); 97 98 /* Handle Work Queue Entry in cn56xx and cn52xx */ 99 if (octeon_has_feature(OCTEON_FEATURE_NO_WPTR)) { 100 cvmx_ipd_ctl_status_t ipd_ctl_status; 101 ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); 102 if (ipd_ctl_status.s.no_wptr) 103 no_wptr = 1; 104 } 105 106 /* Free the prefetched WQE */ 107 if (ipd_ptr_count.s.wqev_cnt) { 108 cvmx_ipd_wqe_ptr_valid_t ipd_wqe_ptr_valid; 109 ipd_wqe_ptr_valid.u64 = cvmx_read_csr(CVMX_IPD_WQE_PTR_VALID); 110 if (no_wptr) 111 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_wqe_ptr_valid.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 112 else 113 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_wqe_ptr_valid.s.ptr<<7), CVMX_FPA_WQE_POOL, 0); 114 } 115 116 /* Free all WQE in the fifo */ 117 if (ipd_ptr_count.s.wqe_pcnt) { 118 int i; 119 cvmx_ipd_pwp_ptr_fifo_ctl_t ipd_pwp_ptr_fifo_ctl; 120 ipd_pwp_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); 121 for (i = 0; i < ipd_ptr_count.s.wqe_pcnt; i++) { 122 ipd_pwp_ptr_fifo_ctl.s.cena = 0; 123 ipd_pwp_ptr_fifo_ctl.s.raddr = ipd_pwp_ptr_fifo_ctl.s.max_cnts + (ipd_pwp_ptr_fifo_ctl.s.wraddr+i) % ipd_pwp_ptr_fifo_ctl.s.max_cnts; 124 cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, ipd_pwp_ptr_fifo_ctl.u64); 125 ipd_pwp_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); 126 if (no_wptr) 127 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_pwp_ptr_fifo_ctl.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 128 else 129 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_pwp_ptr_fifo_ctl.s.ptr<<7), CVMX_FPA_WQE_POOL, 0); 130 } 131 ipd_pwp_ptr_fifo_ctl.s.cena = 1; 132 cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, ipd_pwp_ptr_fifo_ctl.u64); 133 } 134 135 /* Free the prefetched packet */ 136 if (ipd_ptr_count.s.pktv_cnt) { 137 cvmx_ipd_pkt_ptr_valid_t ipd_pkt_ptr_valid; 138 ipd_pkt_ptr_valid.u64 = cvmx_read_csr(CVMX_IPD_PKT_PTR_VALID); 139 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_pkt_ptr_valid.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 140 } 141 142 /* Free the per port prefetched packets */ 143 if (1) { 144 int i; 145 cvmx_ipd_prc_port_ptr_fifo_ctl_t ipd_prc_port_ptr_fifo_ctl; 146 ipd_prc_port_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL); 147 148 for (i = 0; i < ipd_prc_port_ptr_fifo_ctl.s.max_pkt; i++) { 149 ipd_prc_port_ptr_fifo_ctl.s.cena = 0; 150 ipd_prc_port_ptr_fifo_ctl.s.raddr = i % ipd_prc_port_ptr_fifo_ctl.s.max_pkt; 151 cvmx_write_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL, ipd_prc_port_ptr_fifo_ctl.u64); 152 ipd_prc_port_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL); 153 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_prc_port_ptr_fifo_ctl.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 154 } 155 ipd_prc_port_ptr_fifo_ctl.s.cena = 1; 156 cvmx_write_csr(CVMX_IPD_PRC_PORT_PTR_FIFO_CTL, ipd_prc_port_ptr_fifo_ctl.u64); 157 } 158 159 /* Free all packets in the holding fifo */ 160 if (ipd_ptr_count.s.pfif_cnt) { 161 int i; 162 cvmx_ipd_prc_hold_ptr_fifo_ctl_t ipd_prc_hold_ptr_fifo_ctl; 163 164 ipd_prc_hold_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL); 165 166 for (i = 0; i < ipd_ptr_count.s.pfif_cnt; i++) { 167 ipd_prc_hold_ptr_fifo_ctl.s.cena = 0; 168 ipd_prc_hold_ptr_fifo_ctl.s.raddr = (ipd_prc_hold_ptr_fifo_ctl.s.praddr + i) % ipd_prc_hold_ptr_fifo_ctl.s.max_pkt; 169 cvmx_write_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL, ipd_prc_hold_ptr_fifo_ctl.u64); 170 ipd_prc_hold_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL); 171 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_prc_hold_ptr_fifo_ctl.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 172 } 173 ipd_prc_hold_ptr_fifo_ctl.s.cena = 1; 174 cvmx_write_csr(CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL, ipd_prc_hold_ptr_fifo_ctl.u64); 175 } 176 177 /* Free all packets in the fifo */ 178 if (ipd_ptr_count.s.pkt_pcnt) { 179 int i; 180 cvmx_ipd_pwp_ptr_fifo_ctl_t ipd_pwp_ptr_fifo_ctl; 181 ipd_pwp_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); 182 183 for (i = 0; i < ipd_ptr_count.s.pkt_pcnt; i++) { 184 ipd_pwp_ptr_fifo_ctl.s.cena = 0; 185 ipd_pwp_ptr_fifo_ctl.s.raddr = (ipd_pwp_ptr_fifo_ctl.s.praddr+i) % ipd_pwp_ptr_fifo_ctl.s.max_cnts; 186 cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, ipd_pwp_ptr_fifo_ctl.u64); 187 ipd_pwp_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PWP_PTR_FIFO_CTL); 188 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_pwp_ptr_fifo_ctl.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 189 } 190 ipd_pwp_ptr_fifo_ctl.s.cena = 1; 191 cvmx_write_csr(CVMX_IPD_PWP_PTR_FIFO_CTL, ipd_pwp_ptr_fifo_ctl.u64); 192 } 193 } 194} 195 196static void __cvmx_ipd_free_ptr_v2(void) 197{ 198 int no_wptr = 0; 199 int i; 200 cvmx_ipd_port_ptr_fifo_ctl_t ipd_port_ptr_fifo_ctl; 201 cvmx_ipd_ptr_count_t ipd_ptr_count; 202 ipd_ptr_count.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT); 203 204 /* Handle Work Queue Entry in cn68xx */ 205 if (octeon_has_feature(OCTEON_FEATURE_NO_WPTR)) { 206 cvmx_ipd_ctl_status_t ipd_ctl_status; 207 ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); 208 if (ipd_ctl_status.s.no_wptr) 209 no_wptr = 1; 210 } 211 212 /* Free the prefetched WQE */ 213 if (ipd_ptr_count.s.wqev_cnt) { 214 cvmx_ipd_next_wqe_ptr_t ipd_next_wqe_ptr; 215 ipd_next_wqe_ptr.u64 = cvmx_read_csr(CVMX_IPD_NEXT_WQE_PTR); 216 if (no_wptr) 217 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_next_wqe_ptr.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 218 else 219 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_next_wqe_ptr.s.ptr<<7), CVMX_FPA_WQE_POOL, 0); 220 } 221 222 223 /* Free all WQE in the fifo */ 224 if (ipd_ptr_count.s.wqe_pcnt) { 225 cvmx_ipd_free_ptr_fifo_ctl_t ipd_free_ptr_fifo_ctl; 226 cvmx_ipd_free_ptr_value_t ipd_free_ptr_value; 227 ipd_free_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_FREE_PTR_FIFO_CTL); 228 for (i = 0; i < ipd_ptr_count.s.wqe_pcnt; i++) { 229 ipd_free_ptr_fifo_ctl.s.cena = 0; 230 ipd_free_ptr_fifo_ctl.s.raddr = ipd_free_ptr_fifo_ctl.s.max_cnts + (ipd_free_ptr_fifo_ctl.s.wraddr+i) % ipd_free_ptr_fifo_ctl.s.max_cnts; 231 cvmx_write_csr(CVMX_IPD_FREE_PTR_FIFO_CTL, ipd_free_ptr_fifo_ctl.u64); 232 ipd_free_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_FREE_PTR_FIFO_CTL); 233 ipd_free_ptr_value.u64 = cvmx_read_csr(CVMX_IPD_FREE_PTR_VALUE); 234 if (no_wptr) 235 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_free_ptr_value.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 236 else 237 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_free_ptr_value.s.ptr<<7), CVMX_FPA_WQE_POOL, 0); 238 } 239 ipd_free_ptr_fifo_ctl.s.cena = 1; 240 cvmx_write_csr(CVMX_IPD_FREE_PTR_FIFO_CTL, ipd_free_ptr_fifo_ctl.u64); 241 } 242 243 /* Free the prefetched packet */ 244 if (ipd_ptr_count.s.pktv_cnt) { 245 cvmx_ipd_next_pkt_ptr_t ipd_next_pkt_ptr; 246 ipd_next_pkt_ptr.u64 = cvmx_read_csr(CVMX_IPD_NEXT_PKT_PTR); 247 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_next_pkt_ptr.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 248 } 249 250 /* Free the per port prefetched packets */ 251 ipd_port_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PORT_PTR_FIFO_CTL); 252 253 for (i = 0; i < ipd_port_ptr_fifo_ctl.s.max_pkt; i++) { 254 ipd_port_ptr_fifo_ctl.s.cena = 0; 255 ipd_port_ptr_fifo_ctl.s.raddr = i % ipd_port_ptr_fifo_ctl.s.max_pkt; 256 cvmx_write_csr(CVMX_IPD_PORT_PTR_FIFO_CTL, ipd_port_ptr_fifo_ctl.u64); 257 ipd_port_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_PORT_PTR_FIFO_CTL); 258 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_port_ptr_fifo_ctl.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 259 } 260 ipd_port_ptr_fifo_ctl.s.cena = 1; 261 cvmx_write_csr(CVMX_IPD_PORT_PTR_FIFO_CTL, ipd_port_ptr_fifo_ctl.u64); 262 263 /* Free all packets in the holding fifo */ 264 if (ipd_ptr_count.s.pfif_cnt) { 265 cvmx_ipd_hold_ptr_fifo_ctl_t ipd_hold_ptr_fifo_ctl; 266 267 ipd_hold_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_HOLD_PTR_FIFO_CTL); 268 269 for (i = 0; i < ipd_ptr_count.s.pfif_cnt; i++) { 270 ipd_hold_ptr_fifo_ctl.s.cena = 0; 271 ipd_hold_ptr_fifo_ctl.s.raddr = (ipd_hold_ptr_fifo_ctl.s.praddr + i) % ipd_hold_ptr_fifo_ctl.s.max_pkt; 272 cvmx_write_csr(CVMX_IPD_HOLD_PTR_FIFO_CTL, ipd_hold_ptr_fifo_ctl.u64); 273 ipd_hold_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_HOLD_PTR_FIFO_CTL); 274 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_hold_ptr_fifo_ctl.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 275 } 276 ipd_hold_ptr_fifo_ctl.s.cena = 1; 277 cvmx_write_csr(CVMX_IPD_HOLD_PTR_FIFO_CTL, ipd_hold_ptr_fifo_ctl.u64); 278 } 279 280 /* Free all packets in the fifo */ 281 if (ipd_ptr_count.s.pkt_pcnt) { 282 cvmx_ipd_free_ptr_fifo_ctl_t ipd_free_ptr_fifo_ctl; 283 cvmx_ipd_free_ptr_value_t ipd_free_ptr_value; 284 ipd_free_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_FREE_PTR_FIFO_CTL); 285 286 for (i = 0; i < ipd_ptr_count.s.pkt_pcnt; i++) { 287 ipd_free_ptr_fifo_ctl.s.cena = 0; 288 ipd_free_ptr_fifo_ctl.s.raddr = (ipd_free_ptr_fifo_ctl.s.praddr+i) % ipd_free_ptr_fifo_ctl.s.max_cnts; 289 cvmx_write_csr(CVMX_IPD_FREE_PTR_FIFO_CTL, ipd_free_ptr_fifo_ctl.u64); 290 ipd_free_ptr_fifo_ctl.u64 = cvmx_read_csr(CVMX_IPD_FREE_PTR_FIFO_CTL); 291 ipd_free_ptr_value.u64 = cvmx_read_csr(CVMX_IPD_FREE_PTR_VALUE); 292 cvmx_fpa_free(cvmx_phys_to_ptr((uint64_t)ipd_free_ptr_value.s.ptr<<7), CVMX_FPA_PACKET_POOL, 0); 293 } 294 ipd_free_ptr_fifo_ctl.s.cena = 1; 295 cvmx_write_csr(CVMX_IPD_FREE_PTR_FIFO_CTL, ipd_free_ptr_fifo_ctl.u64); 296 } 297} 298 299/** 300 * @INTERNAL 301 * This function is called by cvmx_helper_shutdown() to extract 302 * all FPA buffers out of the IPD and PIP. After this function 303 * completes, all FPA buffers that were prefetched by IPD and PIP 304 * wil be in the apropriate FPA pool. This functions does not reset 305 * PIP or IPD as FPA pool zero must be empty before the reset can 306 * be performed. WARNING: It is very important that IPD and PIP be 307 * reset soon after a call to this function. 308 */ 309void __cvmx_ipd_free_ptr(void) 310{ 311 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 312 __cvmx_ipd_free_ptr_v2(); 313 else 314 __cvmx_ipd_free_ptr_v1(); 315} 316 317#endif 318 319