/***********************license start***************
* Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* This Software, including technical data, may be subject to U.S. export control
* laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
* CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Helper functions for FPA setup.
*
* <hr>$Revision: 70030 $<hr>
*/
#include "cvmx.h"
#include "cvmx-bootmem.h"
#include "cvmx-fpa.h"
#include "cvmx-helper-fpa.h"
/**
* @INTERNAL
* Allocate memory for and initialize a single FPA pool.
*
* @param pool Pool to initialize
* @param buffer_size Size of buffers to allocate in bytes
* @param buffers Number of buffers to put in the pool. Zero is allowed
* @param name String name of the pool for debugging purposes
* @return Zero on success, non-zero on failure
*/
static int __cvmx_helper_initialize_fpa_pool(int pool, uint64_t buffer_size,
uint64_t buffers, const char *name)
{
uint64_t current_num;
void *memory;
uint64_t align = CVMX_CACHE_LINE_SIZE;
/* Align the allocation so that power of 2 size buffers are naturally aligned */
while (align < buffer_size)
align = align << 1;
if (buffers == 0)
return 0;
current_num = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(pool));
if (current_num)
{
cvmx_dprintf("Fpa pool %d(%s) already has %llu buffers. Skipping setup.\n",
pool, name, (unsigned long long)current_num);
return 0;
}
memory = cvmx_bootmem_alloc(buffer_size * buffers, align);
if (memory == NULL)
{
cvmx_dprintf("Out of memory initializing fpa pool %d(%s).\n", pool, name);
return -1;
}
cvmx_fpa_setup_pool(pool, name, memory, buffer_size, buffers);
return 0;
}
/**
* @INTERNAL
* Allocate memory and initialize the FPA pools using memory
* from cvmx-bootmem. Specifying zero for the number of
* buffers will cause that FPA pool to not be setup. This is
* useful if you aren't using some of the hardware and want
* to save memory. Use cvmx_helper_initialize_fpa instead of
* this function directly.
*
* @param pip_pool Should always be CVMX_FPA_PACKET_POOL
* @param pip_size Should always be CVMX_FPA_PACKET_POOL_SIZE
* @param pip_buffers
* Number of packet buffers.
* @param wqe_pool Should always be CVMX_FPA_WQE_POOL
* @param wqe_size Should always be CVMX_FPA_WQE_POOL_SIZE
* @param wqe_entries
* Number of work queue entries
* @param pko_pool Should always be CVMX_FPA_OUTPUT_BUFFER_POOL
* @param pko_size Should always be CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
* @param pko_buffers
* PKO Command buffers. You should at minimum have two per
* each PKO queue.
* @param tim_pool Should always be CVMX_FPA_TIMER_POOL
* @param tim_size Should always be CVMX_FPA_TIMER_POOL_SIZE
* @param tim_buffers
* TIM ring buffer command queues. At least two per timer bucket
* is recommended.
* @param dfa_pool Should always be CVMX_FPA_DFA_POOL
* @param dfa_size Should always be CVMX_FPA_DFA_POOL_SIZE
* @param dfa_buffers
* DFA command buffer. A relatively small (32 for example)
* number should work.
* @return Zero on success, non-zero if out of memory
*/
static int __cvmx_helper_initialize_fpa(int pip_pool, int pip_size, int pip_buffers,
int wqe_pool, int wqe_size, int wqe_entries,
int pko_pool, int pko_size, int pko_buffers,
int tim_pool, int tim_size, int tim_buffers,
int dfa_pool, int dfa_size, int dfa_buffers)
{
int status;
cvmx_fpa_enable();
if ((pip_buffers > 0) && (pip_buffers <= 64))
cvmx_dprintf("Warning: %d packet buffers may not be enough for hardware"
" prefetch. 65 or more is recommended.\n", pip_buffers);
if (pip_pool >= 0)
{
status = __cvmx_helper_initialize_fpa_pool(pip_pool, pip_size, pip_buffers,
"Packet Buffers");
if (status)
return status;
}
if (wqe_pool >= 0)
{
status = __cvmx_helper_initialize_fpa_pool(wqe_pool, wqe_size, wqe_entries,
"Work Queue Entries");
if (status)
return status;
}
if (pko_pool >= 0)
{
status = __cvmx_helper_initialize_fpa_pool(pko_pool, pko_size, pko_buffers,
"PKO Command Buffers");
if (status)
return status;
}
if (tim_pool >= 0)
{
status = __cvmx_helper_initialize_fpa_pool(tim_pool, tim_size, tim_buffers,
"TIM Command Buffers");
if (status)
return status;
}
if (dfa_pool >= 0)
{
status = __cvmx_helper_initialize_fpa_pool(dfa_pool, dfa_size, dfa_buffers,
"DFA Command Buffers");
if (status)
return status;
}
return 0;
}
/**
* Allocate memory and initialize the FPA pools using memory
* from cvmx-bootmem. Sizes of each element in the pools is
* controlled by the cvmx-config.h header file. Specifying
* zero for any parameter will cause that FPA pool to not be
* setup. This is useful if you aren't using some of the
* hardware and want to save memory.
*
* @param packet_buffers
* Number of packet buffers to allocate
* @param work_queue_entries
* Number of work queue entries
* @param pko_buffers
* PKO Command buffers. You should at minimum have two per
* each PKO queue.
* @param tim_buffers
* TIM ring buffer command queues. At least two per timer bucket
* is recommended.
* @param dfa_buffers
* DFA command buffer. A relatively small (32 for example)
* number should work.
* @return Zero on success, non-zero if out of memory
*/
int cvmx_helper_initialize_fpa(int packet_buffers, int work_queue_entries,
int pko_buffers, int tim_buffers, int dfa_buffers)
{
#ifndef CVMX_FPA_PACKET_POOL
#define CVMX_FPA_PACKET_POOL -1
#define CVMX_FPA_PACKET_POOL_SIZE 0
#endif
#ifndef CVMX_FPA_WQE_POOL
#define CVMX_FPA_WQE_POOL -1
#define CVMX_FPA_WQE_POOL_SIZE 0
#endif
#ifndef CVMX_FPA_OUTPUT_BUFFER_POOL
#define CVMX_FPA_OUTPUT_BUFFER_POOL -1
#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 0
#endif
#ifndef CVMX_FPA_TIMER_POOL
#define CVMX_FPA_TIMER_POOL -1
#define CVMX_FPA_TIMER_POOL_SIZE 0
#endif
#ifndef CVMX_FPA_DFA_POOL
#define CVMX_FPA_DFA_POOL -1
#define CVMX_FPA_DFA_POOL_SIZE 0
#endif
return __cvmx_helper_initialize_fpa(
CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, packet_buffers,
CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, work_queue_entries,
CVMX_FPA_OUTPUT_BUFFER_POOL, CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, pko_buffers,
CVMX_FPA_TIMER_POOL, CVMX_FPA_TIMER_POOL_SIZE, tim_buffers,
CVMX_FPA_DFA_POOL, CVMX_FPA_DFA_POOL_SIZE, dfa_buffers);
}