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