366 lines
12 KiB
C
366 lines
12 KiB
C
/*
|
|
<:copyright-BRCM:2009:DUAL/GPL:standard
|
|
|
|
Copyright (c) 2009 Broadcom Corporation
|
|
All Rights Reserved
|
|
|
|
Unless you and Broadcom execute a separate written software license
|
|
agreement governing use of this software, this software is licensed
|
|
to you under the terms of the GNU General Public License version 2
|
|
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
|
|
with the following added to such license:
|
|
|
|
As a special exception, the copyright holders of this software give
|
|
you permission to link this software with independent modules, and
|
|
to copy and distribute the resulting executable under terms of your
|
|
choice, provided that you also meet, for each linked independent
|
|
module, the terms and conditions of the license of that module.
|
|
An independent module is a module which is not derived from this
|
|
software. The special exception does not apply to any modifications
|
|
of the software.
|
|
|
|
Not withstanding the above, under no circumstances may you combine
|
|
this software in any way with any other Broadcom software provided
|
|
under a license other than the GPL, without Broadcom's express prior
|
|
written consent.
|
|
|
|
:>
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
*******************************************************************************
|
|
* File Name : gbpm.c
|
|
*******************************************************************************
|
|
*/
|
|
#if (defined(CONFIG_BCM_BPM) || defined(CONFIG_BCM_BPM_MODULE))
|
|
#include <linux/version.h>
|
|
#include <linux/init.h>
|
|
#include <linux/module.h>
|
|
#include <linux/workqueue.h>
|
|
#include <linux/gbpm.h>
|
|
#include <linux/bcm_colors.h>
|
|
#include <linux/ip.h>
|
|
#include <linux/in.h>
|
|
#include <linux/tcp.h>
|
|
#include <linux/udp.h>
|
|
#include <net/ip.h>
|
|
#include <linux/bcm_log_mod.h>
|
|
#include <linux/bcm_log.h>
|
|
|
|
/* Debug macros */
|
|
int gbpm_debug_g = 0;
|
|
|
|
#if defined(CC_GBPM_SUPPORT_DEBUG)
|
|
#define gbpm_print(fmt, arg...) \
|
|
if ( gbpm_debug_g ) \
|
|
printk( CLRc "GBPM %s :" fmt CLRnl, __FUNCTION__, ##arg )
|
|
#define gbpm_assertv(cond) \
|
|
if ( !cond ) { \
|
|
printk( CLRerr "GBPM ASSERT %s : " #cond CLRnl, __FUNCTION__ ); \
|
|
return; \
|
|
}
|
|
#define gbpm_assertr(cond, rtn) \
|
|
if ( !cond ) { \
|
|
printk( CLRerr "GBPM ASSERT %s : " #cond CLRnl, __FUNCTION__ ); \
|
|
return rtn; \
|
|
}
|
|
#define GBPM_DBG(debug_code) do { debug_code } while(0)
|
|
#else
|
|
#define gbpm_print(fmt, arg...) NULL_STMT
|
|
#define gbpm_assertv(cond) NULL_STMT
|
|
#define gbpm_assertr(cond, rtn) NULL_STMT
|
|
#define GBPM_DBG(debug_code) NULL_STMT
|
|
#endif
|
|
|
|
#define gbpm_error(fmt, arg...) \
|
|
printk( CLRerr "GBPM ERROR %s :" fmt CLRnl, __FUNCTION__, ##arg)
|
|
|
|
#undef GBPM_DECL
|
|
#define GBPM_DECL(x) #x, /* string declaration */
|
|
|
|
|
|
/* global Buffer Pool Manager (BPM) */
|
|
gbpm_status_hook_t gbpm_enet_status_hook_g = (gbpm_status_hook_t)NULL;
|
|
EXPORT_SYMBOL(gbpm_enet_status_hook_g);
|
|
|
|
|
|
#if (defined(CONFIG_BCM_FAP) || defined(CONFIG_BCM_FAP_MODULE))
|
|
gbpm_fap_set_status_hook_t gbpm_fap_set_status_hook_g = NULL;
|
|
gbpm_status_hook_t gbpm_fap_status_hook_g = (gbpm_status_hook_t)NULL;
|
|
|
|
gbpm_thresh_hook_t gbpm_fap_thresh_hook_g = (gbpm_thresh_hook_t)NULL;
|
|
gbpm_thresh_hook_t gbpm_fap_enet_thresh_hook_g = (gbpm_thresh_hook_t)NULL;
|
|
gbpm_thresh_hook_t gbpm_enet_thresh_hook_g = (gbpm_thresh_hook_t)NULL;
|
|
gbpm_upd_buf_lvl_hook_t gbpm_fap_upd_buf_lvl_hook_g = (gbpm_upd_buf_lvl_hook_t)NULL;
|
|
|
|
EXPORT_SYMBOL(gbpm_fap_set_status_hook_g);
|
|
EXPORT_SYMBOL(gbpm_fap_status_hook_g);
|
|
EXPORT_SYMBOL(gbpm_fap_thresh_hook_g);
|
|
EXPORT_SYMBOL(gbpm_fap_enet_thresh_hook_g);
|
|
EXPORT_SYMBOL(gbpm_enet_thresh_hook_g);
|
|
EXPORT_SYMBOL(gbpm_fap_upd_buf_lvl_hook_g);
|
|
#endif
|
|
|
|
#if defined(CONFIG_BCM96368)
|
|
gbpm_status_hook_t gbpm_fwd_status_hook_g = (gbpm_status_hook_t)NULL;
|
|
EXPORT_SYMBOL(gbpm_fwd_status_hook_g);
|
|
#endif
|
|
|
|
#if defined(CONFIG_BCM96816)
|
|
gbpm_thresh_hook_t gbpm_moca_thresh_hook_g = (gbpm_thresh_hook_t)NULL;
|
|
EXPORT_SYMBOL(gbpm_moca_thresh_hook_g);
|
|
#endif
|
|
|
|
#if defined(CONFIG_BCM_XTMCFG) || defined(CONFIG_BCM_XTMCFG_MODULE)
|
|
gbpm_status_hook_t gbpm_xtm_status_hook_g = (gbpm_status_hook_t)NULL;
|
|
gbpm_thresh_hook_t gbpm_xtm_thresh_hook_g = (gbpm_thresh_hook_t)NULL;
|
|
|
|
EXPORT_SYMBOL(gbpm_xtm_status_hook_g);
|
|
EXPORT_SYMBOL(gbpm_xtm_thresh_hook_g);
|
|
#endif
|
|
|
|
|
|
uint32_t gbpm_enable_g = 0; /* Enable GBPM feature */
|
|
|
|
/*
|
|
*------------------------------------------------------------------------------
|
|
* Default hooks.
|
|
* FIXME: Group these hooks into a structure and change gbpm_bind to use
|
|
* a structure.
|
|
*------------------------------------------------------------------------------
|
|
*/
|
|
static gbpm_dyn_buf_lvl_hook_t gbpm_dyn_buf_lvl_hook_g =
|
|
(gbpm_dyn_buf_lvl_hook_t ) NULL;
|
|
static gbpm_alloc_mult_hook_t gbpm_alloc_mult_hook_g = (gbpm_alloc_mult_hook_t) NULL;
|
|
static gbpm_free_mult_hook_t gbpm_free_mult_hook_g=(gbpm_free_mult_hook_t) NULL;
|
|
static gbpm_alloc_hook_t gbpm_alloc_hook_g = (gbpm_alloc_hook_t) NULL;
|
|
static gbpm_free_hook_t gbpm_free_hook_g = (gbpm_free_hook_t) NULL;
|
|
static gbpm_resv_rx_hook_t gbpm_resv_rx_hook_g = (gbpm_resv_rx_hook_t) NULL;
|
|
static gbpm_unresv_rx_hook_t gbpm_unresv_rx_hook_g=(gbpm_unresv_rx_hook_t) NULL;
|
|
static gbpm_get_total_bufs_hook_t gbpm_get_total_bufs_hook_g=(gbpm_get_total_bufs_hook_t) NULL;
|
|
static gbpm_get_avail_bufs_hook_t gbpm_get_avail_bufs_hook_g=(gbpm_get_avail_bufs_hook_t) NULL;
|
|
|
|
|
|
#if (defined(CONFIG_BCM_FAP) || defined(CONFIG_BCM_FAP_MODULE))
|
|
static void gbpm_do_work(struct work_struct *);
|
|
static DECLARE_WORK(gbpm_work, gbpm_do_work);
|
|
static struct workqueue_struct *gbpm_workqueue;
|
|
|
|
static gbpm_evt_hook_t gbpm_fap_evt_hook_g = (gbpm_evt_hook_t)NULL;
|
|
EXPORT_SYMBOL(gbpm_fap_evt_hook_g);
|
|
|
|
/* Do the BPM work */
|
|
static void gbpm_do_work(struct work_struct *work_unused)
|
|
{
|
|
/* process BPM pending events */
|
|
if ( likely(gbpm_fap_evt_hook_g != (gbpm_evt_hook_t)NULL) )
|
|
gbpm_fap_evt_hook_g();
|
|
}
|
|
|
|
/* Add the BPM work */
|
|
void gbpm_queue_work(void)
|
|
{
|
|
queue_work(gbpm_workqueue, &gbpm_work);
|
|
}
|
|
|
|
EXPORT_SYMBOL(gbpm_queue_work);
|
|
#endif
|
|
|
|
|
|
/* Stub functions */
|
|
int gbpm_dyn_buf_lvl_stub( void )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
int gbpm_alloc_mult_stub( uint32_t num, uint32_t *buf_p )
|
|
{
|
|
return GBPM_ERROR;
|
|
}
|
|
|
|
void gbpm_free_mult_stub( uint32_t num, uint32_t *buf_p )
|
|
{
|
|
return;
|
|
}
|
|
|
|
uint32_t *gbpm_alloc_stub( void )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
void gbpm_free_stub( uint32_t *buf_p )
|
|
{
|
|
return;
|
|
}
|
|
|
|
int gbpm_resv_rx_stub( gbpm_port_t port, uint32_t chnl,
|
|
uint32_t num_rx_buf, uint32_t bulk_alloc_cnt )
|
|
{
|
|
return GBPM_ERROR;
|
|
}
|
|
|
|
int gbpm_unresv_rx_stub( gbpm_port_t port, uint32_t chnl )
|
|
{
|
|
return GBPM_ERROR;
|
|
}
|
|
|
|
uint32_t gbpm_get_total_bufs_stub( void )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
uint32_t gbpm_get_avail_bufs_stub( void )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* BQoS BPM APIs invoked through hooks */
|
|
int gbpm_get_dyn_buf_level(void)
|
|
{
|
|
return gbpm_dyn_buf_lvl_hook_g();
|
|
}
|
|
|
|
int gbpm_alloc_mult_buf( uint32_t num, uint32_t *buf_p )
|
|
{
|
|
return gbpm_alloc_mult_hook_g( num, buf_p );
|
|
}
|
|
|
|
void gbpm_free_mult_buf( uint32_t num, uint32_t *buf_p )
|
|
{
|
|
gbpm_free_mult_hook_g( num, buf_p );
|
|
}
|
|
|
|
uint32_t *gbpm_alloc_buf( void )
|
|
{
|
|
return gbpm_alloc_hook_g();
|
|
}
|
|
|
|
void gbpm_free_buf( uint32_t *buf_p )
|
|
{
|
|
return gbpm_free_hook_g( buf_p );
|
|
}
|
|
|
|
int gbpm_resv_rx_buf( gbpm_port_t port, uint32_t chnl,
|
|
uint32_t num_rx_buf, uint32_t bulk_alloc_cnt )
|
|
{
|
|
return gbpm_resv_rx_hook_g(port, chnl, num_rx_buf, bulk_alloc_cnt);
|
|
}
|
|
|
|
int gbpm_unresv_rx_buf( gbpm_port_t port, uint32_t chnl )
|
|
{
|
|
return gbpm_unresv_rx_hook_g( port, chnl );
|
|
}
|
|
|
|
uint32_t gbpm_get_total_bufs( void )
|
|
{
|
|
return gbpm_get_total_bufs_hook_g();
|
|
}
|
|
|
|
uint32_t gbpm_get_avail_bufs( void )
|
|
{
|
|
return gbpm_get_avail_bufs_hook_g();
|
|
}
|
|
|
|
/*
|
|
*------------------------------------------------------------------------------
|
|
* Function : gbpm_bind
|
|
* Description : Override default hooks.
|
|
* gbpm_dyn_buf_lvl: Function pointer to get the buffer levle in BPM
|
|
* gbpm_alloc_mult: Function pointer to allocate multiple buffers
|
|
* gbpm_free_mult : Function pointer to free multiple buffers
|
|
* gbpm_alloc : Function pointer to allocate one buffer
|
|
* gbpm_free : Function pointer to free one buffer
|
|
* gbpm_resv_rx : Function pointer to reserve buffers for RX rings
|
|
* gbpm_uresv_rx : Function pointer to unreserve buffers for RX rings
|
|
* gbpm_get_total_bufs : get total number of bufs BPM manages
|
|
* gbpm_get_avail_bufs : get current number of free bufs in BPM pool
|
|
*------------------------------------------------------------------------------
|
|
*/
|
|
void gbpm_bind( gbpm_dyn_buf_lvl_hook_t gbpm_dyn_buf_lvl,
|
|
gbpm_alloc_mult_hook_t gbpm_alloc_mult,
|
|
gbpm_free_mult_hook_t gbpm_free_mult,
|
|
gbpm_alloc_hook_t gbpm_alloc,
|
|
gbpm_free_hook_t gbpm_free,
|
|
gbpm_resv_rx_hook_t gbpm_resv_rx,
|
|
gbpm_unresv_rx_hook_t gbpm_unresv_rx,
|
|
gbpm_get_total_bufs_hook_t gbpm_get_total_bufs,
|
|
gbpm_get_avail_bufs_hook_t gbpm_get_avail_bufs )
|
|
{
|
|
gbpm_print( "Bind dyn[<%08x>] "
|
|
"mult_alloc[<%08x>] mult_free[<%08x>]"
|
|
"alloc[<%08x>] free[<%08x>]"
|
|
"resv_rx[<%08x>] unresv_rx[<%08x>]"
|
|
(int)gbpm_dyn_buf_lvl,
|
|
(int)gbpm_alloc_mult, (int)gbpm_free_mult,
|
|
(int)gbpm_alloc, (int)gbpm_free,
|
|
(int)gbpm_resv_rx, (int)gbpm_unresv_rx );
|
|
|
|
gbpm_dyn_buf_lvl_hook_g = gbpm_dyn_buf_lvl;
|
|
gbpm_alloc_mult_hook_g = gbpm_alloc_mult;
|
|
gbpm_free_mult_hook_g = gbpm_free_mult;
|
|
gbpm_alloc_hook_g = gbpm_alloc;
|
|
gbpm_free_hook_g = gbpm_free;
|
|
gbpm_resv_rx_hook_g = gbpm_resv_rx;
|
|
gbpm_unresv_rx_hook_g = gbpm_unresv_rx;
|
|
gbpm_get_total_bufs_hook_g = gbpm_get_total_bufs;
|
|
gbpm_get_avail_bufs_hook_g = gbpm_get_avail_bufs;
|
|
}
|
|
|
|
|
|
/*
|
|
*------------------------------------------------------------------------------
|
|
* Function : gbpm_unbind
|
|
* Description : use default hooks.
|
|
*------------------------------------------------------------------------------
|
|
*/
|
|
void gbpm_unbind( void )
|
|
{
|
|
gbpm_bind( gbpm_dyn_buf_lvl_stub,
|
|
gbpm_alloc_mult_stub, gbpm_free_mult_stub,
|
|
gbpm_alloc_stub, gbpm_free_stub,
|
|
gbpm_resv_rx_stub, gbpm_unresv_rx_stub,
|
|
gbpm_get_total_bufs_stub, gbpm_get_avail_bufs_stub );
|
|
}
|
|
|
|
|
|
/*
|
|
*------------------------------------------------------------------------------
|
|
* Function : __init_gbpm
|
|
* Description : Static construction of global buffer pool manager subsystem.
|
|
*------------------------------------------------------------------------------
|
|
*/
|
|
static int __init __init_gbpm( void )
|
|
{
|
|
#if (defined(CONFIG_BCM_FAP) || defined(CONFIG_BCM_FAP_MODULE))
|
|
/* Set up BPM workqueue. */
|
|
gbpm_workqueue = create_singlethread_workqueue("bpm");
|
|
set_workqueue_thread_prio(gbpm_workqueue, SCHED_RR, CONFIG_BRCM_SOFTIRQ_BASE_RT_PRIO+1);
|
|
#endif
|
|
|
|
gbpm_unbind();
|
|
|
|
printk( GBPM_MODNAME GBPM_VER_STR " initialized\n" );
|
|
return 0;
|
|
}
|
|
|
|
subsys_initcall(__init_gbpm);
|
|
|
|
EXPORT_SYMBOL(gbpm_enable_g);
|
|
EXPORT_SYMBOL(gbpm_get_dyn_buf_level);
|
|
EXPORT_SYMBOL(gbpm_alloc_mult_buf);
|
|
EXPORT_SYMBOL(gbpm_free_mult_buf);
|
|
EXPORT_SYMBOL(gbpm_alloc_buf);
|
|
EXPORT_SYMBOL(gbpm_free_buf);
|
|
EXPORT_SYMBOL(gbpm_resv_rx_buf);
|
|
EXPORT_SYMBOL(gbpm_unresv_rx_buf);
|
|
EXPORT_SYMBOL(gbpm_get_total_bufs);
|
|
EXPORT_SYMBOL(gbpm_get_avail_bufs);
|
|
|
|
EXPORT_SYMBOL(gbpm_bind);
|
|
EXPORT_SYMBOL(gbpm_unbind);
|
|
#endif /* (defined(CONFIG_BCM_BPM) || defined(CONFIG_BCM_BPM_MODULE)) */
|
|
|