1
0
Files
2016-11-30 09:03:17 +08:00

6161 lines
169 KiB
C
Executable File

/*
** $Id: //BBN_Linux/Branch/Branch_for_Rel_CMCC_7526_20161014/tclinux_phoenix/modules/private/tc3162l2hp2h/sar_tc3162l2.c#1 $
*/
/************************************************************************
*
* Copyright (C) 2006 Trendchip Technologies, Corp.
* All Rights Reserved.
*
* Trendchip Confidential; Need to Know only.
* Protected as an unpublished work.
*
* The computer program listings, specifications and documentation
* herein are the property of Trendchip Technologies, Co. and shall
* not be reproduced, copied, disclosed, or used in whole or in part
* for any reason without the prior express written permission of
* Trendchip Technologeis, Co.
*
*************************************************************************/
/*
** $Log: sar_tc3162l2.c,v $
** Revision 1.21 2011/08/12 08:22:09 xmdai_nj
** #11299
**
** Revision 1.20 2011/08/12 07:02:43 xmdai_nj
** #11297:Upstream throughput can not reach to 100% when ADSL is set to Annex M mode.
**
** Revision 1.19 2011/08/05 03:14:01 xyzhu_nj
** #11006: ct com merge to main trunk.(phase 3)
** 1. Add TCSUPPORT_COMPILE tag for ct com compile option;
** 2. Delete files in filesystem that CT_COM not used;
** 3. Merge the lastes bugfix from ct com branch to main trunk.(TLB7.1.2.20-51 -- 57);
** 4. update mic.
**
** Revision 1.18 2011/07/24 12:00:14 xyzhu_nj
** #11006: Merge China telecom branch to Main trunk.
**
** Revision 1.17 2011/07/07 07:46:13 shnwind
** RT63260 & RT63260 auto_bench support
**
** Revision 1.16 2011/07/07 01:18:54 xmdai_nj
** #10616:AnnexM throughput
**
** Revision 1.15 2011/06/30 09:07:25 serenahuang_hc
** remove compile option WITHVOIP
**
** Revision 1.14 2011/06/23 04:41:28 serenahuang_hc
** 1.remove to put packets to HH priority when the destPort is match.
** 2.Put rtp packets to HH priority when qos_flag not be selected as WRR or PQ
**
** Revision 1.13 2011/06/13 05:59:55 frankliao_hc
** add rt65168 support
**
** Revision 1.12 2011/06/03 08:46:26 xhshi
** #9797 l2m throughput issue
**
** Revision 1.11 2011/04/12 14:48:54 shnwind
** remove debug message
**
** Revision 1.10 2011/02/21 07:30:37 shnwind
** fix bug : treg_tstbr will set wrong in tc3182
**
** Revision 1.9 2011/01/21 14:41:35 shnwind
** fix Bug 8620
**
** Revision 1.8 2011/01/20 13:33:42 shnwind
** fix Bug 8599
**
** Revision 1.7 2010/12/31 10:33:34 xyzhu_nj
** #8261: sp / wrr qos enhancement.
**
** Revision 1.6 2010/12/27 04:59:13 here
** [Bug fix]Compiler error with TC3182 profile with "Support 802.1p Remark function"
**
** Revision 1.5 2010/12/24 11:30:08 here
** [Ehancement]Support 802.1p Remark function
**
** Revision 1.4 2010/12/24 10:34:36 serenahuang_hc
** remove tc3162/voip proc make
**
** Revision 1.3 2010/12/02 06:24:34 shnwind
** fix some warning
**
** Revision 1.2 2010/11/30 10:57:43 rclv_nj
** bug5954
**
** Revision 1.1.1.1 2010/09/30 21:14:55 josephxu
** modules/public, private
**
** Revision 1.17 2010/09/29 11:06:28 serenahuang_hc
** modify isPriorityPkt() for check arp packet & tcp data packet.
**
** Revision 1.16 2010/09/10 04:31:30 xyzhu_nj
** #6856: Add support old qos mechanism.
**
** Revision 1.15 2010/09/03 16:39:12 here
** [Ehance] TC3182 GMAC Driver is support TC-Console & WAN2LAN function.
**
** Revision 1.14 2010/09/03 13:47:23 xyyou
** add new version control
**
** Revision 1.13 2010/08/23 06:28:11 serenahuang_hc
** modifid files for RTP QoS
**
** Revision 1.12 2010/07/22 11:47:34 xhshi
** #6353
** 1.Add some pvc links,and then delete some,occasionally we find that delete
** the wrong pvc link.for example:we want to delete the pvc with '0.35',but actually delete
** the pvc with '0.36'.
** 2.If we add the same pvc more times,after that,we cannot add other
** pvc whether the pvc is correct or not.
** 3."atmcmd pvc --delete 0.0" can be used as valid command.
**
** Revision 1.11 2010/07/22 05:19:10 jlliu_nj
** Bug#6345:Support Version control mechanism in mldsnooping module,mac driver,sar driver:add line break in version
**
** Revision 1.10 2010/07/22 02:48:55 jlliu_nj
** Bug#6345:Support Version control mechanism in mldsnooping module,mac driver,sar driver
**
** Revision 1.9 2010/07/14 15:55:36 frankliao_hc
** BUGFIX:
** remove hareware vlan untag setting in initMOPA function
**
** Revision 1.8 2010/07/06 13:39:32 xhshi
** #6183
** 1.Do f5 loopback diagnostic which use atmcmd like this:"atmcmd oam --start 0.35 f5 --type segment --repetition 2 --timeout 40000"
** 2.CPE hang,and after a while reboot.
**
** Revision 1.7 2010/06/23 04:30:56 xmdai_nj
** bug#5814,pppoa cannot dail and get ip.
**
** Revision 1.6 2010/06/17 04:36:55 serenahuang_hc
** If packet dest port match rtp_port put it into the highest priority queue.
**
** Revision 1.5 2010/06/09 08:26:33 shnwind
** tc3182 asic support
**
** Revision 1.4 2010/06/07 04:29:06 xyzhu_nj
** [#5858]: support 802.1p remark.
**
** Revision 1.3 2010/05/21 05:15:01 xyzhu_nj
** [#5762]: Support CAR QoS in Linux.
**
** Revision 1.2 2010/04/14 02:36:28 xhshi
** #5431 support driver interface
**
** Revision 1.1.1.1 2010/04/09 09:35:29 feiyan
** New TC Linux Make Flow Trunk
**
** Revision 1.18 2010/03/22 14:14:52 yzwang_nj
** [Bug#5128] Implement TR068 LED
**
** Revision 1.17 2010/02/22 03:17:39 rodney
** RED
**
** Revision 1.16 2010/02/05 10:16:33 ian
** Remove keyword "Huawei" for adslcmd and atmcmd
**
** Revision 1.15 2010/02/03 02:42:40 here
** [Ehancement]Remove the check mechanism for wifi driver that is released by trendchip crop.
**
** Revision 1.14 2010/02/02 12:13:13 here
** [Ehancement]1.RT3092 Chip is support polling mode when the adsl at init state.
** 2. Support the check mechanism for wifi driver that is released by trendchip crop.
**
** Revision 1.13 2010/01/15 17:25:56 pork
** wan2lan porting
**
** Revision 1.12 2010/01/15 09:38:45 here
** [BugFix]Fixed TC3162U Platform the sar interface's rx descriptor is mismatch at SMB Routing throughput(WiFi interface is up)
**
** Revision 1.11 2010/01/10 16:06:48 here
** [Ehancement]TC3162U MAC EEE is operated at 100M-FD, SAR interface is accroding the SAR_CLK to calculate atm rate.
**
** Revision 1.9 2010/01/10 13:45:21 here
** [BugFix] Help shnwind to commit sar modules
**
** Revision 1.3 2009/12/30 12:33:21 yzwang_nj
** [Bug#4409] Add TR064 Parameters
**
** Revision 1.2 2009/12/30 03:01:05 xhshi
** [#4366]
** Implement ATM F5 Loopback Diagnostic function in linux platform
**
** Revision 1.1.1.1 2009/12/17 01:48:05 josephxu
** 20091217, from Hinchu ,with VoIP
**
** Revision 1.2 2006/07/06 06:05:59 lino
** update to version 1.2
**
** Revision 1.1 2006/07/06 05:04:47 lino
** add kernel module support
**
** Revision 1.4 2006/02/14 11:16:14 lino
** workaround to prevent the HW SAR issue abnormal IRQ status
**
** Revision 1.3 2006/02/07 07:24:21 lino
** add tx/rx/cc descriptor dump, process abnormal irq status and let atm reset work
**
** Revision 1.2 2006/01/17 07:14:23 lino
** set pvc qos priority CBR > rt-VBR > nrt-VBR > UBR
**
** Revision 1.1.1.1 2005/11/02 05:45:19 lino
** no message
**
** Revision 1.10 2005/09/29 12:10:01 bread.hsu
** reduce code size and beautify code structure of tc3162l2 sar driver
**
** Revision 1.9 2005/09/28 13:45:42 jasonlin
** Fix the compilation error after adding rtVBR and nrtVBR
**
** Revision 1.8 2005/09/27 08:03:06 bread.hsu
** adding IMEM support for Tc3162L2
**
** Revision 1.7 2005/09/22 13:22:02 jasonlin
** Add nrtVBR selection on CI command and TC new web page
**
** Revision 1.6 2005/09/21 04:46:22 bread.hsu
** fix the L2 sar and mac driver counter and register message display error
**
** Revision 1.5 2005/09/14 11:10:51 bread.hsu
** TC3162L2 SAR and MAC driver synchronize with TC3162
**
** Revision 1.4 2005/08/09 03:06:34 bread.hsu
** L2 SAR any-byte alignment test function error fixed
**
** Revision 1.3 2005/06/22 14:28:21 jasonlin
** fix the merge error of tc3162l2sar.c
**
** Revision 1.2 2005/06/22 14:23:41 jasonlin
** Sync with main trunk version 2.2.28
**
** Revision 1.1 2005/06/14 10:02:05 jasonlin
** Merge TC3162L2 source code into new main trunk
**
** Revision 1.14 2004/12/20 05:15:09 lino
** prevent multiple call atmAal5VcClose to cause cannot open new vc anymore
**
** Revision 1.13 2004/11/18 11:05:19 lino
** fixed CBR's PCR lower than line rate, UBR traffic will be blocked
**
** Revision 1.12 2004/11/15 03:41:20 lino
** add UBR QoS enhance, let UBR has lower priority than CBR and VBR
**
** Revision 1.11 2004/11/05 10:27:12 svtseng
** Delete the QOS parameter seting must plus 2 in last modification
**
** Revision 1.10 2004/11/05 06:18:26 svtseng
** 1. Fix the QOS setting in VBR
** 2. The caculated value should be raise two levels
** 3. Change timebase counter.
** 4. Add 1 to the atmRateCalCulate's timebase parameter
**
** Revision 1.9 2004/10/28 10:30:11 svtseng
** Fix the QOS traffic type (UBR) compete with others
**
** Revision 1.8 2004/10/21 13:31:49 svtseng
** Fix the bug in VAR qos setting, the pci_init can not be equal to scr_init,
** or the rate would be wrong
**
** Revision 1.7 2004/10/21 05:36:19 lino
** change oam cell format and add oam debug messages
**
** Revision 1.6 2004/10/13 05:22:02 svtseng
** Fix the QOS parameter caculation by system CLK
**
** Revision 1.5 2004/10/12 06:41:16 lino
** add more sar discard counters
**
** Revision 1.4 2004/09/14 03:58:32 lino
** fixed will not hunt vcpool oam loopback cell
**
** Revision 1.3 2004/08/27 12:18:51 lino
** add qos calculation and clean code
**
** Revision 1.2 2004/08/09 11:36:18 lino
** add vpi/vci=0/16 cells to packet
**
** Revision 1.1 2004/07/02 08:06:01 lino
** tc3160 and tc3162 code merge
**
*/
#include <linux/kernel.h>
#include <linux/atmdev.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/tc3162/tc3162.h>
#include <asm/tc3162/TCIfSetQuery_os.h>
#include <asm/tc3162/ledcetrl.h>
#include "../../version/tcversion.h"
#ifdef DMA_API
#include <linux/dma-mapping.h>
#endif
#include "../tcphy/tcswitch.h"
#include "../tcphy/tcconsole.h"
#include "tsarm.h"
#ifdef SAR_VERIFY
#include "tsarm_verify.h"
#endif
#ifdef L2_AUTOPVC
#include "autoPVC.h"
#include "aal5.h"
extern uint32 g_manageFlag;
#endif
//add by brian
#ifdef CWMP
uint32 g_f5loopback_rxtime = 0;
uint32 g_f5loopback_txtime = 0;
uint32 maxtimeindex = 0xFFFFFFFF;
static uint32 cwmpSavedInF5Pkts = 0;
static uint32 cwmpSavedOutF5Pkts = 0;
uint8 internal_error = 0;
uint32 cwmpflag = 0;
//static uint32 cwmpSavedInF4Pkts = 0;
#endif
#if defined(TCSUPPORT_CT_SWQOS)
static uint8 atmTxQosQueueSize = ATM_TX_VC_DESCR_P3_NUMMAX;
#endif
/************************************************************************
* E X T E R N A L R E F E R E N C E S
*************************************************************************
*/
#ifdef SAR_VERIFY
extern uint16 test_flag;
#endif
#ifdef WAN2LAN
extern int masko_on_off; //use this flag control if open wan2lan function
#endif
#ifdef TR068_LED
extern int internet_led_on;
extern int internet_trying_led_on;
#endif
#if defined(TCSUPPORT_CT_SWQOS)
extern int (*sw_pktqosEnqueue) (struct sk_buff * bp);
extern void (*sw_PKTQOS_SET_STOP) (void);
extern void (*sw_PKTQOS_CLEAR_STOP) (void);
#endif
/************************************************************************
* V E R S I O N C O N T R O L
*************************************************************************
*/
/************************************************************************
* C O N S T A N T S
*************************************************************************
*/
#if defined(TCSUPPORT_CT)
#define DYNAMIC_ALLOC_SKB 1
#endif
#define DYNAMIC_ALLOC_DMA_BUF 1
#if 0 /*move tsarm.h*/
#define RX_BUF_LEN (2048 - 16 - 64 - (sizeof(struct skb_shared_info)))
#endif
//#define QOS_UBR_ENHANCE 1
#if defined(TCSUPPORT_CT)
#ifndef TCSUPPORT_QOS
#define QOS_REMARKING 0//1 /*Rodney_20090724*/
#endif
#if defined(TCSUPPORT_C1_CUC)
#define TCSUPPORT_HW_QOS
#endif
#else
#ifndef TCSUPPORT_QOS
#define QOS_REMARKING 1 /*Rodney_20090724*/
#endif
#define TCSUPPORT_HW_QOS
#endif
#ifdef QOS_REMARKING /*Rodney_20090724*/
#define QOS_REMARKING_MASK 0x00000007
#define QOS_REMARKING_FLAG 0x00000001
//#define QOS_DMAWRR_USERDEFINE 0x01
#endif
#if defined(TCSUPPORT_CT)
#define QOS_DMAWRR_USERDEFINE 0x01
#endif
#if !defined(TCSUPPORT_CT)
#if defined (QOS_REMARKING) || defined(TCSUPPORT_HW_QOS)
#define QOS_DMAWRR_USERDEFINE 0x1
#endif
#endif
#ifdef CONFIG_NET_SCHED /*Rodney_20091115*/
//#define QOS_DROP_DUMP 1
#define QOS_QDISC_NOR 1 /*normal*/
#define QOS_QDISC_RED 2
#define QOS_QDISC_WRED 4
#endif
#define SAVED_IRQ_MAX_ENTRY 16
#define DEF_PRIORITY_PKT_CHK_LEN 100
#ifdef ALIGN32
#define ALIGN32BYTESBASE 32
#endif
#ifdef WAN2LAN
#define SKBUF_COPYTOLAN (1<<26) //xyzhu_nj_091105:borrow this bit to show if the packet is used for wan2lan
#endif
/************************************************************************
* D A T A T Y P E S
*************************************************************************
*/
#ifdef CMD_API
typedef struct
{
uint32 crc_errs;
uint32 oversized_sdus;
uint32 short_pkt_errs;
uint32 len_errs;
} PVCSTATS;
PVCSTATS pvc_stats[ATM_VC_MAX];
#endif
/************************************************************************
* M A C R O S
*************************************************************************
*/
#define dbg_pline_1(x) printk("%s", x)
#define dbg_plineb_1(x, y) printk("%s%02x", x, (uint8) y)
#define dbg_plinew_1(x, y) printk("%s%04x", x, (uint16) y)
#define dbg_plinel_1(x, y) printk("%s%08lx", x, (uint32) y)
#define puts(s) printk("%s", s)
#define printf printk
//#define delay1ms(x) mdelay(x)
/************************************************************************
* F U N C T I O N D E C L A R A T I O N S
*************************************************************************
*/
void atmTxDescrInit(void);
void atmRxDescrInit(void);
#if defined(TCSUPPORT_CT)
#ifdef DYNAMIC_ALLOC_SKB
int atmRxSkbAlloc(uint8 vc);
void atmRxSkbFree(uint8 vc);
#endif
#endif
void atmRxIrqQueueSet( uint32 irqBase, uint32 irqLength );
void atmTxDescrFree(uint8 vc, uint8 free_any);
irqreturn_t atmIsr(int irq , void *dev);
uint8 atmCcHandler(uint8 *cellp);
uint8 atmOamHandler(atmRxCcDescr_t *atmRxCcDescrp, uint8 vc);
uint8 atmOamDataReq(uint8 *data_p, uint8 pti, uint8 vc);
uint8 atmVcNumberGet(uint8 vpi, uint16 vci);
struct sk_buff *atmAal5DataInd(struct sk_buff *skb, uint8 vc, uint32 len);
void atmReset(void);
uint8 atmDataReq(struct sk_buff *skb, uint8 vc, uint8 priority);
void sarDrvDescripReset(int freeRxSkb);
int atmOamOpen(void);
void atmIrqStSaved(uint32 irqst, uint8 vc);
extern int getXdslSpeed(void);
extern uint8 getXdslModeType(void);
int getATMState(char *stateATM);
static int setAtmQosRed(qosProfile_t *qos_p, uint32 vc);
static int update_qosred(uint32 vc);
/************************************************************************
* P U B L I C D A T A
*************************************************************************
*/
atmCtrl_t atmCtrl;
atmCtrl_t *atm_p = &atmCtrl;
//#ifdef QOS_REMARKING /*Rodney_20090724*/
#if defined(QOS_REMARKING) || defined(TCSUPPORT_HW_QOS)
static int qos_wrr_info[5] = {0};
static int max_prio = 0;
static uint8 qos_wrr_user = 0x00;
#endif
#ifdef TCSUPPORT_QOS
#define QOS_FILTER_MARK 0xf0
#define QOS_HH_PRIORITY 0x10
#define QOS_H_PRIORITY 0x20
#define QOS_M_PRIORITY 0x30
#define QOS_L_PRIORITY 0x40
#define NULLQOS -1
#define QOS_SW_PQ 0 //will use hw at the same time
#define QOS_SW_WRR 1
#define QOS_SW_CAR 2
#define QOS_HW_WRR 3
#define QOS_HW_PQ 4
static int qos_flag = NULLQOS;
#endif
#ifdef CONFIG_NET_SCHED /*Rodney_20091115*/
static int qos_qdisc_mode = 1;
#ifdef QOS_DROP_DUMP
#define MAX_LOG_PKT 10000
static unsigned short int qos_drop_flag[MAX_LOG_PKT] = {0};
#endif /*QOS_DROP_DUMP*/
#endif /*CONFIG_NET_SCHED*/
static uint32 atmRxBufferSize=0;
static int pcr_modify_flag = 0;//The mark of pcr's value modified by client,1:modified,0:no
static int g_qos_pcr = 0;// if the pcr value is modified by client, then the pcr value will be saved in the g_qos_pcr
/************************************************************************
* E X T E R N A L D A T A
*************************************************************************
*/
static uint8 sarDebugFlag = 0;
static uint8 sarSoftReset = 0;
static uint8 isAdslUp = 0;
#ifdef CONFIG_MIPS_TC3262
static spinlock_t sarLock;
#endif
/************************************************************************
* P R I V A T E D A T A
*************************************************************************
*/
//atmTxDescr_t *atmTxVcFreeDescrp[ATM_VC_MAX];
//atmTxDescr_t *atmTxVcBusyDescrp[ATM_VC_MAX];
atmRxDescr_t *atmRxVcDescrp[ATM_VC_MAX];
uint32 volatile atmTxVcTotalCnt;
uint16 volatile atmTxVcCnt[ATM_VC_MAX];
uint8 atmTxCcCnt;
atmTxDescr_t *atmTxVcFreeDescrp[ATM_TX_PRIORITY_MAX][ATM_VC_MAX];
atmTxDescr_t *atmTxVcBusyDescrp[ATM_TX_PRIORITY_MAX][ATM_VC_MAX];
uint16 volatile atmTxPriVcCnt[ATM_TX_PRIORITY_MAX][ATM_VC_MAX];
atmTxCcDescr_t *atmTxCcFreeDescrp;
atmRxCcDescr_t *atmRxCcBusyDescrp;
#ifdef DYNAMIC_ALLOC_DMA_BUF
struct atmTxDescrPoolAddr_s{
atmTxDescr_t * pTxDescr[ATM_TX_PRIORITY_MAX];
atmTxCcDescr_t * pTxOamDescr;
} atmTxDescrPoolAddr[ATM_VC_MAX];
uint8 *atmTxDescrPool = NULL;
int atmTxDescrPoolSize = 0;
atmTxCcDescrPool_t *atmTxCcDescrPool = NULL;
atmRxCcDescrPool_t *atmRxCcDescrPool = NULL;
atmRxCcCell_t *ccBuf = NULL;
atmRxOamDescrPool_t *oamBuf = NULL;
atmRxDescrPool_t *atmRxDescrPool = NULL;
uint32 *atmRxIrq = NULL;
#if DMA_API
uint8* atmTxDescrPool_phys_p = NULL;
atmTxCcDescrPool_t* atmTxCcDescrPool_phys_p = NULL;
atmRxCcDescrPool_t* atmRxCcDescrPool_phys_p = NULL;
atmRxCcCell_t* ccBuf_phys_p = NULL;
atmRxOamDescrPool_t* oamBuf_phys_p = NULL;
atmRxDescrPool_t* atmRxDescrPool_phys_p = NULL;
uint32* atmRxIrq_phys_p = NULL;
atmCell_t *atmCellCirBuf = NULL;
atmCell_t* atmCellCirBuf_phys_p=NULL;
#endif
#else
atmTxCcDescrPool_t atmTxCcDescrPool;
atmRxCcDescrPool_t atmRxCcDescrPool;
atmRxCcCell_t ccBuf[ATM_RX_CC_DESCR_NUMMAX];
atmRxOamDescrPool_t oamBuf[ATM_VC_MAX];
atmTxDescrPool_t atmTxDescrPool[ATM_VC_MAX];
atmRxDescrPool_t atmRxDescrPool[ATM_VC_MAX];
uint32 atmRxIrq[IRQ_MAX_ENTRY];
#endif
atmTxCcDescr_t *atmTxOamFreeDescrp[ATM_VC_MAX];
atmRxCcDescr_t *atmRxOamBusyDescrp[ATM_VC_MAX];
typedef struct saved_atm_irq_st_s {
uint32 irqst;
uint8 vc;
} saved_atm_irq_st_t;
saved_atm_irq_st_t savedAtmIrqSt[SAVED_IRQ_MAX_ENTRY];
uint32 savedAtmIrqIndex = 0;
atmConfig_t atmCfgTable = { 0 };
atmConfig_t atmCfgBackup = { 0 };
qosProfile_t qosRecord[ATM_VC_MAX];
int atmTxQueSize[4] = { ATM_TX_VC_DESCR_P0_NUMMAX,
ATM_TX_VC_DESCR_P1_NUMMAX,
ATM_TX_VC_DESCR_P2_NUMMAX,
ATM_TX_VC_DESCR_P3_NUMMAX};
module_param_array(atmTxQueSize, int, NULL, 0);
/* priority packet check parameters */
int priPktChkLen = DEF_PRIORITY_PKT_CHK_LEN;
#ifdef CONFIG_QOS
#ifdef TCSUPPORT_SBTHROUGHPUT_ENHANCE
extern int tc_qos_switch;
#endif
#endif
#if defined(TCSUPPORT_CT)
#ifdef DYNAMIC_ALLOC_SKB
/*Fix dynamic alloc bug*/
int g_NoNeedFreeSKB = 0;
#endif
#endif
module_param(priPktChkLen, int, 0);
#ifdef PURE_BRIDGE
int priPktChk = 0;
#else
int priPktChk = 1;
#endif
module_param(priPktChk, int, 0);
uint8 oamAisCell[52] = {
/* ATM Header, without HEC */
0x00, 0x00, 0x00, 0x00,
/* 48 octets payload */
0x10, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x03, 0xB9
};
uint8 oamRdiCell[52] = {
/* ATM Header, without HEC */
0x00, 0x00, 0x00, 0x00,
/* 48 octets payload */
0x11, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x00, 0xAF
};
uint8 oamLoopBackReqCell[52] = {
/* ATM Header, without HEC */
0x00, 0x00, 0x00, 0x00,
/* 48 octets payload */
0x18, 0x01, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x03, 0x93
};
uint8 oamContinuityCheckReqCell[52] = {
/* ATM Header, without HEC */
0x00, 0x00, 0x00, 0x00,
/* 48 octets payload */
0x14, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x03, 0x87
};
uint8 oamF5AisCell[48] = {
/* 48 octets payload */
0x10, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x03, 0xB9
};
uint8 oamF5RdiCell[48] = {
/* 48 octets payload */
0x11, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x00, 0xAF
};
uint8 oamF5LoopBackReqCell[48] = {
/* 48 octets payload */
0x18, 0x01, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x03, 0x93
};
uint8 oamF5ContinuityCheckReqCell[48] = {
/* 48 octets payload */
0x14, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A,
0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x03, 0x87
};
typedef struct QosParm_s{
uint16 cellRate;
uint16 init;
uint8 dec;
} QosParm_t;
#define MAX_ATMQOS_CNT 17 /* 1+8*2 = 17; 1:dslupRate;8 PVCs, 2:pcr and scr */
QosParm_t ATMQosParam[MAX_ATMQOS_CNT] = {0};
#if defined(TCSUPPORT_CT_SWQOS)
uint32 treg_irqm = 0x402; //TX_SW_DIS_M, TX_M_DONE_M, been masked
#else
uint32 treg_irqm = 0x403; //TX_SW_DIS_M, TX_M_DONE_M, and TX_U_DONE_M been masked
#endif
#ifdef TC3262_FPGA
int32 treg_tstbr = 9; //for FPGA
#else
uint32 treg_tstbr = 3600; //for ASIC
#endif
uint32 treg_tslr = 65537; //0x00010001 default value
uint8 irqrereadflag = 0;
uint32 irqrereadmax = 0;
uint32 irqrereadtime = 0;
/************************************************************************
* L I N U X S P E C I F I C S E C T I O N
*************************************************************************
*/
static int tc3162_atm_open(struct atm_vcc *vcc);
static void tc3162_atm_close(struct atm_vcc *vcc);
static int tc3162_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg);
static int tc3162_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
static int tc3162_atm_change_qos (struct atm_vcc *vcc, struct atm_qos *qos,int flags);
static struct atm_dev *tc3162_atm_dev;
static struct atmdev_ops tc3162_atm_ops = {
.open = tc3162_atm_open,
.close = tc3162_atm_close,
.ioctl = tc3162_atm_ioctl,
.send = tc3162_atm_send,
.change_qos = tc3162_atm_change_qos,
.owner = THIS_MODULE
};
/************************************************************************
* F U N C T I O N D E F I N I T I O N S
*************************************************************************
*/
static uint8 RFC1483_B_LLC_HDR[] = {
0xaa, 0xaa, 0x03, 0x00, 0x80, 0xc2, 0x00, 0x07, 0x00, 0x00
};
static uint8 RFC1483_R_LLC_HDR[] = {
0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00
};
static uint8 RFC1483_B_LLC_FCS_HDR[] = {
0xaa, 0xaa, 0x03, 0x00, 0x80, 0xc2, 0x00, 0x01, 0x00, 0x00
};
static uint8 RFC1483_B_VC_HDR[] = {
0x00, 0x00
};
static uint8 PPPOA_LLC_HDR[] = {
0xfe, 0xfe, 0x03, 0xcf, 0x00, 0x21
};
static uint8 PPPOA_VC_HDR[] = {
0x00, 0x21
};
/*_____________________________________________________________________________
** function name: align32Byte
** descriptions:
** If you allocate memory with non-cache area and it is close neighbor cache area, If this not
**
** parameters:
** addr: Specify the address that you want to 32 bytes alignment.
**
** global:
** None
**
** return:
** 32 bytes alignment address.
**
** call:
** None
**
** revision:
** 1. Here 2008/09/08
**____________________________________________________________________________
*/
uint32
align32Byte(uint32 addr)
{
#ifdef ALIGN32
return (addr+31)&0xFFFFFFE0;
#else
return addr;
#endif
}/*end align32Byte*/
/*20100921_serena_modify: add inupu arg "len" to check tcp packet*/
static uint8 isPriorityPkt(uint8 *cp, uint8 *priority, unsigned int len)
{
uint16 etherType;
uint8 ipVerLen;
uint8 ipProtocol;
uint8 tcpFlags;
uint16 pppProtocol;
uint8 ipv6_protocol, ipv6_type;
#ifdef TCSUPPORT_CWMP_FAST_GET
uint16 tcpSrcPort = 0;
uint16 dnsPort = 0;
#endif
/* RFC1483 LLC Bridge mode */
if (memcmp(cp, RFC1483_B_LLC_HDR, 7) == 0) {
cp += sizeof(RFC1483_B_LLC_HDR);
goto eth_header;
/* RFC1483 LLC Routing mode */
} else if (memcmp(cp, RFC1483_R_LLC_HDR, sizeof(RFC1483_R_LLC_HDR)) == 0) {
cp += sizeof(RFC1483_R_LLC_HDR);
goto ipv4_header;
/* PPPoA LLC Routing mode */
} else if (memcmp(cp, PPPOA_LLC_HDR, sizeof(PPPOA_LLC_HDR)) == 0) {
cp += sizeof(PPPOA_LLC_HDR);
goto ipv4_header;
/* PPPoA VCMUX Routing mode */
} else if (memcmp(cp, PPPOA_VC_HDR, sizeof(PPPOA_VC_HDR)) == 0) {
cp += sizeof(PPPOA_VC_HDR);
goto ipv4_header;
/* RFC1483 VCMUX Bridge mode */
} else if (memcmp(cp, RFC1483_B_VC_HDR, sizeof(RFC1483_B_VC_HDR)) == 0) {
cp += sizeof(RFC1483_B_VC_HDR);
goto eth_header;
/* try RFC1483 VCMUX Routing mode */
} else {
goto ipv4_header;
}
return 0;
eth_header:
/* skip DA and SA mac address */
cp += 12;
/* get ether type */
etherType = *(uint16 *) cp;
/* skip ether type */
cp += 2;
/*parse if vlan exists*/
if (etherType == 0x8100) {
/*skip 802.1q tag field*/
cp += 2;
/*re-parse ether type*/
etherType = *(uint16 *) cp;
/* skip ether type */
cp += 2;
}
/*check whether PPP packets*/
if (etherType == 0x8864) {
/* skip pppoe head */
cp += 6; /* 6: PPPoE header 2: PPP protocol */
/* get ppp protocol */
pppProtocol = *(uint16 *) cp;
/* check if LCP protocol */
if (pppProtocol == 0xc021) {
*priority = 2;
return 1;
/* check if IP protocol */
} else if (pppProtocol != 0x0021) {
return 0;
}
/* skip ppp protocol */
cp += 2; /* 6: PPPoE header 2: PPP protocol */
} else if (etherType == 0x8863) {
*priority = 2;
return 1;
/*20100921_serena_modify: check whether arp packet*/
} else if (etherType == 0x0806) {
*priority = 0;
return 1;
}
else if (etherType == 0x86dd) {
cp += 6;
ipv6_protocol = *(uint8*)cp;
if (ipv6_protocol == 0x3a) {
cp += 34;
ipv6_type = *(uint8*)cp;
if (ipv6_type == 0x87) {
//printk("check ipv6 icmp packet.jiffies is %u\n", jiffies);
*priority = 0;
return 1;
}
}
}
else {
/* check if ip packet */
if (etherType != 0x0800)
return 0;
}
ipv4_header:
/* check if it is a ipv4 packet */
ipVerLen = *cp;
if ((ipVerLen & 0xf0) != 0x40)
return 0;
/* get ip protocol */
ipProtocol = *(cp + 9);
/* check if ICMP/IGMP protocol */
if ((ipProtocol == 1) || (ipProtocol == 2)) {
*priority = 2;
return 1;
}
#ifdef TCSUPPORT_CWMP_FAST_GET
/* dns packet enqueue first queue */
if (ipProtocol == 17) {
dnsPort = *((uint16*)(cp + 13 + 9));
if (dnsPort == 0x35) {
//printk("\r\nisPriorityPkt():It is dns query packet\n");
*priority = 0;
return 1;
}
}
#endif
/* check if TCP protocol */
if (ipProtocol != 6)
return 0;
#ifdef TCSUPPORT_CWMP_FAST_GET
/* tcp */
tcpSrcPort = *((uint16*)(cp + 11 + 9));
//printk("\r\nisPriorityPkt():before-----------debug, tcpSrcPort = %x\n", tcpSrcPort);
if (tcpSrcPort == 0x1d7b) {
//printk("\r\nisPriorityPkt():it is tr069 connection request port packet\n");
*priority = 0;
return 1;
}
#endif
/* align to TCP header */
cp += (ipVerLen & 0x0f) << 2;
/* get TCP flags */
tcpFlags = *(cp + 13);
/* check if TCP syn/ack/psh ack/fin ack */ /*20100921_serena_modify*/
if ((((tcpFlags & 0x10) == 0x10) || (tcpFlags == 0x02)) && (len < priPktChkLen)) {
*priority = 2;
return 1;
}
return 0;
}
void
delay1ms(
int ms
)
{
volatile uint32 timer_now, timer_last;
volatile uint32 tick_acc;
uint32 one_tick_unit = 1 * SYS_HCLK * 1000 / 2;
volatile uint32 tick_wait = ms * one_tick_unit;
volatile uint32 timer1_ldv = VPint(CR_TIMER1_LDV);
tick_acc = 0;
timer_last = VPint(CR_TIMER1_VLR);
do {
timer_now = VPint(CR_TIMER1_VLR);
if (timer_last >= timer_now)
tick_acc += timer_last - timer_now;
else
tick_acc += timer1_ldv - timer_now + timer_last;
timer_last = timer_now;
} while (tick_acc < tick_wait);
}
#ifdef DYNAMIC_ALLOC_DMA_BUF
static void atmTxDescrAlloc(void) {
uint8 vc, priority, i, * ptr;
uint32 ptr_data, ptr_oam, mem_size=0, cnt_pri, cnt_vc, cnt_pri_total=0;
/* the actual total size of each priorities will dynamically change, we should caculate every time enter this function*/
for (priority = 0; priority < ATM_TX_PRIORITY_MAX; priority++)
cnt_pri_total += atmTxQueSize[priority];
mem_size = ATM_VC_MAX * ( (cnt_pri_total * sizeof(atmTxDescr_t))
+ (ATM_TX_CC_DESCR_NUMMAX * sizeof(atmTxCcDescr_t)) );
#ifndef DMA_API
ptr = (uint8 *) kmalloc(mem_size, GFP_KERNEL);
if (ptr == NULL){
printk("ATM Tx Descriptor Memory Allocation Fail!\n");
return;
}
/* record tx descr pool and size */
atmTxDescrPool = ptr;
atmTxDescrPoolSize = mem_size;
/*clean this block of mem*/
memset(ptr, 0x00, mem_size);
#else
atmTxDescrPool=(uint8 *)dma_alloc_coherent(NULL, mem_size, (dma_addr_t *) &atmTxDescrPool_phys_p, GFP_KERNEL);
if (atmTxDescrPool == NULL) {
printk("unable to dma_alloc_coherent atmTxDescrPool structure.\n");
return;
}
ptr=atmTxDescrPool;
atmTxDescrPoolSize=mem_size;
#endif
/* arrange memory for Tx descriptor */
for (vc = 0; vc < ATM_VC_MAX; vc++){
/* cnt_vc == the maximum num of bytes each vc will have */
cnt_vc = vc * ( sizeof(atmTxDescr_t)*cnt_pri_total +
sizeof(atmTxCcDescr_t)*ATM_TX_CC_DESCR_NUMMAX );
for (priority = 0; priority < ATM_TX_PRIORITY_MAX; priority++){
for (i = 0, cnt_pri = 0 ; i < priority; i++){
cnt_pri += atmTxQueSize[i];
}
ptr_data = (uint32)(ptr + cnt_vc + cnt_pri * sizeof(atmTxDescr_t));
/* store the starting address of these data descriptors */
atmTxDescrPoolAddr[vc].pTxDescr[priority] = (atmTxDescr_t *)CACHE_TO_NONCACHE(ptr_data);
}
ptr_oam = (uint32)(ptr + cnt_vc + cnt_pri_total * sizeof(atmTxDescr_t));
/* store the starting address of these oam descriptors */
atmTxDescrPoolAddr[vc].pTxOamDescr = (atmTxCcDescr_t *)CACHE_TO_NONCACHE(ptr_oam);
}
}
#endif
void atmQosParmInit(void){
if(SAR_CLK < 10){ /*It's mean FAGA Clock rate, HCLK=25Mhz, SAR_CLK=6.125Mhz*/
treg_tstbr=9;
}
else{
//Do not use isTC3162L2P2 definition. It will be true in 3182 or 3262 chip. shnwind 20100221.
if(isTC3162L3P3 || isTC3162L4P4 || isTC3162L5P5){/*HCLK=133Mhz, SAR_CLK=33.25Mhz*/
treg_tstbr=8139;
}
else if(isTC3162U){ /*SAR_CLK=41.5Mhz*/
treg_tstbr=5864;
}
else if(isTC3182 || isRT65168){
treg_tstbr=3600;
}
else if(isRT63260){
treg_tstbr=5652;
}
else if(isRT63365 || isRT63368){
treg_tstbr=(SAR_CLK*1000000/7076)-1;
}
}
//printk("tstbr %d\n",treg_tstbr);
/*The default value is 3600*/
}
/*______________________________________________________________________________
** atmInit
**
** descriptions: the intialization function of ATM SAR module
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
void
atmInit(
void
)
{
uint8 i;
uint32 priority; /*Rodney_20090724*/
#ifdef DMA_API
uint32 mem_size=0;
#endif
#ifdef DYNAMIC_ALLOC_DMA_BUF
if( sarSoftReset == 0) {
#ifndef DMA_API
atmTxCcDescrPool = kmalloc(sizeof(atmTxCcDescrPool_t), GFP_KERNEL);
if (atmTxCcDescrPool == NULL) {
printk("unable to kmalloc atmTxCcDescrPool structure.\n");
return;
}
atmRxCcDescrPool = kmalloc(sizeof(atmRxCcDescrPool_t), GFP_KERNEL);
if (atmRxCcDescrPool == NULL) {
printk("unable to kmalloc atmRxCcDescrPool structure.\n");
return;
}
ccBuf = kmalloc(sizeof(atmRxCcCell_t)*ATM_RX_CC_DESCR_NUMMAX, GFP_KERNEL);
if (ccBuf == NULL) {
printk("unable to kmalloc ccBuf structure.\n");
return;
}
oamBuf = kmalloc(sizeof(atmRxOamDescrPool_t)*ATM_VC_MAX, GFP_KERNEL);
if (oamBuf == NULL) {
printk("unable to kmalloc oamBuf structure.\n");
return;
}
atmRxDescrPool = kmalloc(sizeof(atmRxDescrPool_t)*ATM_VC_MAX, GFP_KERNEL);
if (atmRxDescrPool == NULL) {
printk("unable to kmalloc atmRxDescrPool structure.\n");
return;
}
atmRxIrq = kmalloc(sizeof(uint32)*IRQ_MAX_ENTRY, GFP_KERNEL);
if (atmRxIrq == NULL) {
printk("unable to kmalloc atmRxIrq structure.\n");
return;
}
memset( (uint8*)atmTxCcDescrPool, 0 ,sizeof(atmTxCcDescrPool_t));
memset( (uint8*)atmRxCcDescrPool, 0, sizeof(atmRxCcDescrPool_t));
memset( (uint8*)ccBuf, 0, sizeof(atmRxCcCell_t)*ATM_RX_CC_DESCR_NUMMAX);
memset( (uint8*)oamBuf, 0, sizeof(atmRxOamDescrPool_t)*ATM_VC_MAX);
memset( (uint8*)atmRxDescrPool, 0 ,sizeof(atmRxDescrPool_t)*ATM_VC_MAX);
memset( (uint8*)atmRxIrq, 0 ,sizeof(uint32)*IRQ_MAX_ENTRY);
#else /*DMA_API*/
mem_size=sizeof(atmTxCcDescrPool_t);
atmTxCcDescrPool=(atmTxCcDescrPool_t *)dma_alloc_coherent(NULL, mem_size, (dma_addr_t *) &atmTxCcDescrPool_phys_p, GFP_KERNEL);
if (atmTxCcDescrPool == NULL) {
printk("unable to dma_alloc_coherent atmTxCcDescrPool structure.\n");
return;
}
mem_size=sizeof(atmRxCcDescrPool_t);
atmRxCcDescrPool = (atmRxCcDescrPool_t *)dma_alloc_coherent(NULL, mem_size, (dma_addr_t *) &atmRxCcDescrPool_phys_p, GFP_KERNEL);
if (atmRxCcDescrPool == NULL) {
printk("unable to dma_alloc_coherent atmRxCcDescrPool structure.\n");
return;
}
mem_size=sizeof(atmRxCcCell_t)*ATM_RX_CC_DESCR_NUMMAX;
ccBuf = (atmRxCcCell_t *)dma_alloc_coherent(NULL, mem_size, (dma_addr_t *) &ccBuf_phys_p, GFP_KERNEL);
if (ccBuf == NULL) {
printk("unable to dma_alloc_coherent ccBuf structure.\n");
return;
}
mem_size=sizeof(atmRxOamDescrPool_t)*ATM_VC_MAX;
oamBuf = (atmRxOamDescrPool_t *)dma_alloc_coherent(NULL, mem_size, (dma_addr_t *) &oamBuf_phys_p, GFP_KERNEL);
if (oamBuf == NULL) {
printk("unable to dma_alloc_coherent oamBuf structure.\n");
return;
}
mem_size=sizeof(atmRxDescrPool_t)*ATM_VC_MAX;
atmRxDescrPool = (atmRxDescrPool_t *) dma_alloc_coherent(NULL, mem_size, (dma_addr_t *) &atmRxDescrPool_phys_p, GFP_KERNEL);
if (atmRxDescrPool == NULL) {
printk("unable to dma_alloc_coherent atmRxDescrPool.\n");
return;
}
mem_size=sizeof(uint32)*IRQ_MAX_ENTRY;
atmRxIrq = (uint32 *) dma_alloc_coherent(NULL, mem_size, (dma_addr_t *) &atmRxIrq_phys_p, GFP_KERNEL);
if (atmRxIrq == NULL) {
printk("unable to dma_alloc_coherent atmRxIrq structure.\n");
return;
}
#endif
atmTxDescrAlloc();
}
#endif
//disable Tx/Rx first to prevent error
TSARM_GFR = 0x0;
//reset SAR Module
delay1ms(1); //delay1ms(50);
TSARM_RAI = RAI_RESET_ENB(1);
delay1ms(1);//delay1ms(5);
TSARM_RAI = RAI_RESET_ENB(0);
/* free mbuf descriptor allocation */
if( sarSoftReset != 0)
sarDrvDescripReset(0);
atmQosParmInit();
TSARM_TSTBR = treg_tstbr;
TSARM_TXSLRC = treg_tslr;
/* Clear ATM SAR registers */
//there are 10 VCs inside 3162L2
for (i = 0; i < 10; i++)
{
// VC configuration
TSARM_VCCR(i) = 0;
// Transmit Buffer Descriptor
TSARM_TXDCBDA(i) = 0;
TSARM_VC_TX_BD_PRIORITY01(i) = 0;
TSARM_VC_TX_BD_PRIORITY23(i) = 0;
// OAM Transmit Buffer Descriptor
TSARM_TXMCBDA(i)=0;
// Receive Buffer Descriptor
TSARM_RXDCBDA(i)=0;
TSARM_VC_RX_DATA(i) = 0;
// OAM Receive Buffer Descriptor
TSARM_RXMCBDA(i) = 0;
// Traffic Scheduler - PCR
TSARM_PCR(i) = 0;
// Traffic Scheduler - SCR
TSARM_SCR(i) = 0;
// Traffic Scheduler - MBSTP
TSARM_MBSTP(i) = 0;
TSARM_IRQM(i) = 0;
TSARM_VC_MPOA_CTRL(i) = 0;
}
//mpoa registers
TSARM_MPOA_GCR = 0x0;
//MPOA header insertion field values
TSARM_MPOA_HFIV11 = 0xaaaa03;
TSARM_MPOA_HFIV12 = 0xfefe03;
TSARM_MPOA_HFIV13 = 0x0;
TSARM_MPOA_HFIV21 = 0x0080c2;
TSARM_MPOA_HFIV22 = 0x000000;
TSARM_MPOA_HFIV23 = 0x0;
TSARM_MPOA_HFIV31 = 0x0001;
TSARM_MPOA_HFIV32 = 0x0007;
TSARM_MPOA_HFIV33 = 0xfefe;
TSARM_MPOA_HFIV41 = 0x0000;
TSARM_MPOA_HFIV42 = 0x0800;
TSARM_MPOA_HFIV43 = 0x03cf;
TSARM_CCCR = 0x0;
TSARM_IRQMCC = 0x0;
// CC channel current Tx/Rx descriptor
TSARM_CC_TX_BD_BASE = 0;
TSARM_CC_TX_BD_MNG_BASE = 0;
TSARM_CC_RX_BD_BASE = 0;
TSARM_CC_RX_BD_MNG_BASE = 0;
/* every 4 packets to issue interrupt and timeout is about 31us */
TSARM_IRQ_QUE_THRE = 0x4;
TSARM_IRQ_TIMEOUT_CTRL = 0x400;
/* Set up tx/rx descriptors */
atmTxDescrInit();
atmRxDescrInit();
/* Reset ATM rx IRQ queue */
atmRxIrqQueueSet((uint32) atmRxIrq, IRQ_MAX_ENTRY);
TSARM_VCCR(10) = VCCFGR_VPI(255) | VCCFGR_VCI(15) |
VCCFGR_PORT(VCCFGR_ATM_PHY0) | VCCFGR_VALID;
atmOamOpen();
if( sarSoftReset == 0) {
atm_p = &atmCtrl;
/* clear atm counters */
memset((char *)&(atm_p->MIB_II), 0, sizeof(atmMIB_II_t));
memset( (uint8*)&atmCfgTable, 0, sizeof(atmConfig_t));
}
/* Hook Isr */
isAdslUp = 1;
TSARM_GFR = GFR_TXENB | GFR_RXENB | GFR_GIRQEN | GFR_BIGENDIAN | GFR_RX_INACT_VC_M;
// #ifdef QOS_REMARKING /*Rodney_20090724*/
#if defined (QOS_REMARKING) || defined (TCSUPPORT_HW_QOS)
if(qos_wrr_user == QOS_DMAWRR_USERDEFINE){
if(*qos_wrr_info == 0) /*strict priority*/
TSARM_GFR &= ~(GFR_DMT_WRR_EN);
else{ /*WRR*/
priority = TSARM_DMAWRRCR;
priority = (priority & 0xf0f0f0f0);
priority |= (((uint32)(qos_wrr_info[1] & 0x0f) << 0) | ((uint32)(qos_wrr_info[2] & 0x0f) << 8) | ((uint32)(qos_wrr_info[3] & 0x0f) << 16) | ((uint32)(qos_wrr_info[4] & 0x0f) << 24));
TSARM_DMAWRRCR = priority;
TSARM_GFR |= GFR_DMT_WRR_EN;
}
}
#endif
if(isRT63365 || isRT63368){
irqrereadflag = 1;
}
#ifdef SAR_VERIFY
/*Encable inactive VC IRQ Event*/
TSARM_GFR |= GFR_ACTIVE_MIS;
#endif
}
/*______________________________________________________________________________
** atmTxDescrInit
**
** descriptions: Initialize atm Tx descriptors
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
void
atmTxDescrInit(
void
)
{
uint8 vc;
uint8 descrId;
atmTxDescr_t *atmTxDescrp;
atmTxCcDescr_t *atmTxOamDescrp;
atmTxCcDescrPool_t *atmTxCcDescrVcPoolp;
atmTxCcDescr_t *atmTxCcDescrp;
uint32 P0_offset, P1_offset, P2_offset, P3_offset, Oam_offset, Cc_offset;
uint8 priority;
atmTxVcTotalCnt = 0;
// init data and management buffer descriptor
for(vc=0; vc < ATM_VC_MAX; vc++){
//calcute each priority offset from base address
P0_offset = 0x00000000;
P1_offset = (uint32)atmTxDescrPoolAddr[vc].pTxDescr[1] - (uint32)atmTxDescrPoolAddr[vc].pTxDescr[0];
P2_offset = (uint32)atmTxDescrPoolAddr[vc].pTxDescr[2] - (uint32)atmTxDescrPoolAddr[vc].pTxDescr[0];
P3_offset = (uint32)atmTxDescrPoolAddr[vc].pTxDescr[3] - (uint32)atmTxDescrPoolAddr[vc].pTxDescr[0];
Oam_offset = (uint32)atmTxDescrPoolAddr[vc].pTxOamDescr - (uint32)atmTxDescrPoolAddr[vc].pTxDescr[0];
//fill in Register
TSARM_TXDCBDA(vc) = K1_TO_PHYSICAL(atmTxDescrPoolAddr[vc].pTxDescr[0]);
TSARM_VC_TX_BD_PRIORITY01(vc) = K1_TO_PHYSICAL(((P1_offset << 16) + P0_offset));
TSARM_VC_TX_BD_PRIORITY23(vc) = K1_TO_PHYSICAL(((P3_offset << 16) + P2_offset));
TSARM_TXMCBDA(vc) = K1_TO_PHYSICAL(Oam_offset);
//initialize each priority
for(priority = 0; priority < ATM_TX_PRIORITY_MAX; priority ++){
// Free and Busy Descriptor
atmTxVcFreeDescrp[priority][vc] = atmTxDescrPoolAddr[vc].pTxDescr[priority];
atmTxVcBusyDescrp[priority][vc] = atmTxDescrPoolAddr[vc].pTxDescr[priority];
atmTxPriVcCnt[priority][vc] = 0;
//init each descriptor
for ( descrId = 0; descrId < atmTxQueSize[priority]; descrId++ )
{
atmTxDescrp = atmTxDescrPoolAddr[vc].pTxDescr[priority]+ descrId;
if ( descrId == atmTxQueSize[priority] - 1 ) {
//BD_GAP, others = 0; EOR = 1
atmTxDescrp->tdes0 = TSARM_TX_DESCR_BD_GAP(TSARM_TX_DATA_BD_GAP)
| TSARM_TX_DESCR_EOR;
}else{
//BD_GAP, others = 0
atmTxDescrp->tdes0 = TSARM_TX_DESCR_BD_GAP(TSARM_TX_DATA_BD_GAP);
}
// TDES1 =0 ; Buffer length =0;
atmTxDescrp->tdes1 = 0x0;
// TDES2 = 0x0; buffer address = null
atmTxDescrp->tdes2 = 0x0;
atmTxDescrp->tdes3 = 0x0;
atmTxDescrp->skb = NULL;
}
}
atmTxOamFreeDescrp[vc] = atmTxDescrPoolAddr[vc].pTxOamDescr;
atmTxVcCnt[vc] = 0;
// management
for ( descrId = 0; descrId < ATM_TX_CC_DESCR_NUMMAX; descrId++ )
{
atmTxOamDescrp = atmTxDescrPoolAddr[vc].pTxOamDescr + descrId;
if ( descrId == ATM_TX_CC_DESCR_NUMMAX - 1 ) {
//BD_GAP, EOR = 1, others=0;
atmTxOamDescrp->tdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_TX_CC_BD_GAP)
| TSARM_TX_DESCR_EOR;
}else{
//BD_GAP, others = 0
atmTxOamDescrp->tdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_TX_CC_BD_GAP);
}
// TDES1 =0 ; Buffer length =0;
atmTxOamDescrp->tdes1 = 0x0;
// TDES2 = 0x0; buffer address = null
atmTxOamDescrp->tdes2 = 0x0;
atmTxOamDescrp->tdes3 = 0x0;
}
}
// init Cc
#ifdef DYNAMIC_ALLOC_DMA_BUF
atmTxCcDescrVcPoolp = (atmTxCcDescrPool_t *)CACHE_TO_NONCACHE(atmTxCcDescrPool);
#else
atmTxCcDescrVcPoolp = (atmTxCcDescrPool_t *)CACHE_TO_NONCACHE(&atmTxCcDescrPool);
#endif
TSARM_CC_TX_BD_BASE = K1_TO_PHYSICAL(atmTxCcDescrVcPoolp);
// calculate the offset value
Cc_offset = ((uint32)atmTxCcDescrVcPoolp->txCcDescrPool - (uint32)atmTxCcDescrVcPoolp);
TSARM_CC_TX_BD_MNG_BASE = K1_TO_PHYSICAL(Cc_offset);
atmTxCcFreeDescrp = atmTxCcDescrVcPoolp->txCcDescrPool;
for ( descrId = 0; descrId < ATM_TX_CC_DESCR_NUMMAX; descrId++ )
{
atmTxCcDescrp = atmTxCcDescrVcPoolp->txCcDescrPool+ descrId;
if ( descrId == ATM_TX_CC_DESCR_NUMMAX - 1 ) {
//BD_GAP, EOR = 1, others=0;
atmTxCcDescrp->tdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_TX_CC_BD_GAP)
| TSARM_TX_DESCR_EOR;
}else{
//BD_GAP, others=0;
atmTxCcDescrp->tdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_TX_CC_BD_GAP);
}
// TDES1 =0 ; Buffer length =0;
atmTxCcDescrp->tdes1 = 0x0;
// TDES2 = 0x0; buffer address = null
atmTxCcDescrp->tdes2 = 0x0;
atmTxCcDescrp->tdes3 = 0x0;
}
}
/*______________________________________________________________________________
** atmRxDescrInit
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
void
atmRxDescrInit(
void
)
{
uint8 vc;
uint8 descrId;
struct sk_buff *skb;
atmRxDescrPool_t *atmRxDescrVcPoolp;
atmRxDescr_t *atmRxDataDescrp;
atmRxCcDescr_t *atmRxMngDescrp;
atmRxCcDescrPool_t *atmRxCcDescrPoolp;
atmRxCcDescr_t *atmRxCcDescrp;
uint32 Data_offset, Oam_offset, Cc_offset;
// init vc data and management descriptor
for(vc = 0; vc < ATM_VC_MAX; vc++){
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
//calculate the offset value
Data_offset = (uint32)atmRxDescrVcPoolp->rxDescrPool - (uint32)atmRxDescrVcPoolp;
Oam_offset = (uint32)atmRxDescrVcPoolp->rxOamDescrPool - (uint32)atmRxDescrVcPoolp;
//fill in Register
TSARM_RXDCBDA(vc)=K1_TO_PHYSICAL(atmRxDescrVcPoolp);
TSARM_VC_RX_DATA(vc) = K1_TO_PHYSICAL(Data_offset);
TSARM_RXMCBDA(vc)=K1_TO_PHYSICAL(Oam_offset);
atmRxVcDescrp[vc] = atmRxDescrVcPoolp->rxDescrPool;
atmRxOamBusyDescrp[vc] = atmRxDescrVcPoolp->rxOamDescrPool;
// data
for ( descrId = 0; descrId < ATM_RX_VC_DESCR_NUMMAX; descrId++ )
{
atmRxDataDescrp = atmRxDescrVcPoolp->rxDescrPool + descrId;
if (sarSoftReset != 0)
skb = atmRxDataDescrp->skb;
else{
#if defined(TCSUPPORT_CT)
#ifdef DYNAMIC_ALLOC_SKB
skb = NULL;
#else
skb = skbmgr_dev_alloc_skb2k();
dma_cache_inv((unsigned long)skb->data, RX_BUF_LEN);
#endif
#else
skb = skbmgr_dev_alloc_skb2k();
dma_cache_inv((unsigned long)skb->data, RX_BUF_LEN);
#endif
}
if ( descrId == ATM_RX_VC_DESCR_NUMMAX - 1 ) {
// BD_GAP, Rx Descriptor own by DMA; EOR=1
atmRxDataDescrp->rdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_RX_DATA_BD_GAP)
| TSARM_RX_DESCR_EOR | TSARM_RX_DESCR_VALID;
}else{
// BD_GAP, Rx Descriptor own by DMA
atmRxDataDescrp->rdes0 = TSARM_TX_DESCR_BD_GAP(TSARM_RX_DATA_BD_GAP)
| TSARM_RX_DESCR_VALID;
}
// RDES1 = 1776; Set Rx Buffer size = 1776, reference zynos configure
atmRxDataDescrp->rdes1 = atmRxBufferSize<<16;
#ifdef SAR_VERIFY
rxBufAddrOffset(skb);
#endif
// RDES2 = point the Rx Buffer to mbuf
#if defined(TCSUPPORT_CT)
#ifdef DYNAMIC_ALLOC_SKB
if(skb == NULL)
atmRxDataDescrp->rdes2 = 0x0;
else
atmRxDataDescrp->rdes2 = K1_TO_PHYSICAL(skb->data);
#else
atmRxDataDescrp->rdes2 = K1_TO_PHYSICAL(skb->data);
#endif
#else
atmRxDataDescrp->rdes2 = K1_TO_PHYSICAL(skb->data);
#endif
atmRxDataDescrp->rdes3 = 0x0;
atmRxDataDescrp->skb = skb;
}
// management
for ( descrId = 0; descrId < ATM_RX_CC_DESCR_NUMMAX; descrId++ )
{
atmRxMngDescrp = atmRxDescrVcPoolp->rxOamDescrPool+ descrId;
if ( descrId == ATM_RX_CC_DESCR_NUMMAX - 1 ) {
// BD_GAP, Rx Descriptor own by DMA; EOR=1
atmRxMngDescrp->rdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_RX_CC_BD_GAP)
| TSARM_RX_DESCR_EOR | TSARM_RX_DESCR_VALID;
}else{
// BD_GAP, Rx Descriptor own by DMA
atmRxMngDescrp->rdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_RX_CC_BD_GAP)
| TSARM_RX_DESCR_VALID;
}
// RDES1 = 48; Set Rx Buffer size = 48, reference zynos configure
atmRxMngDescrp->rdes1 = 48 << 16;
// RDES2 = point the Rx Buffer to mbuf
atmRxMngDescrp->rdes2 = K1_TO_PHYSICAL(CACHE_TO_NONCACHE(&(oamBuf[vc].rxOamDescrPool[descrId])));
atmRxMngDescrp->rdes3 = 0x0;
}
}
// init Cc
#ifdef DYNAMIC_ALLOC_DMA_BUF
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(atmRxCcDescrPool);
#else
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(&atmRxCcDescrPool);
#endif
//calcute Cc offset value
Cc_offset = (uint32)atmRxCcDescrPoolp->rxCcDescrPool - (uint32)atmRxCcDescrPoolp;
//fill in register
TSARM_CC_RX_BD_BASE = K1_TO_PHYSICAL(atmRxCcDescrPoolp);
TSARM_CC_RX_BD_MNG_BASE = K1_TO_PHYSICAL(Cc_offset);
atmRxCcBusyDescrp = atmRxCcDescrPoolp->rxCcDescrPool;
for ( descrId = 0; descrId < ATM_RX_CC_DESCR_NUMMAX; descrId++ ) {
atmRxCcDescrp = atmRxCcDescrPoolp->rxCcDescrPool + descrId;
if ( descrId == ATM_RX_CC_DESCR_NUMMAX - 1 ) {
// BD_GAP, Rx Descriptor own by DMA; EOR=1
atmRxCcDescrp->rdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_RX_CC_BD_GAP)
| TSARM_RX_DESCR_EOR | TSARM_RX_DESCR_VALID;
}else{
// BD_GAP, Rx Descriptor own by DMA
atmRxCcDescrp->rdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_RX_CC_BD_GAP)
| TSARM_RX_DESCR_VALID;
}
atmRxCcDescrp->rdes1 = (96 << 16);
atmRxCcDescrp->rdes2 = K1_TO_PHYSICAL(CACHE_TO_NONCACHE((ccBuf + descrId)));
atmRxCcDescrp->rdes3 = 0x0;
}
}
#if defined(TCSUPPORT_CT)
#ifdef DYNAMIC_ALLOC_SKB
int atmRxSkbAlloc(uint8 vc)
{
uint8 descrId;
struct sk_buff *skb;
atmRxDescrPool_t *atmRxDescrVcPoolp;
atmRxDescr_t *atmRxDataDescrp;
uint32 Data_offset;
// init vc data and management descriptor
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
// data
for ( descrId = 0; descrId < ATM_RX_VC_DESCR_NUMMAX; descrId++ )
{
atmRxDataDescrp = atmRxDescrVcPoolp->rxDescrPool + descrId;
if(atmRxDataDescrp->skb == NULL){
//skb = skbmgr_dev_alloc_skb2k();
skb = skbmgr_dev_alloc_skb2k_tc_critical();
if(skb == NULL){
printk("atmRxSkbAlloc skb==NULL");
return -1;
}
dma_cache_inv((unsigned long)skb->data, RX_BUF_LEN);
}
else{
skb = atmRxDataDescrp->skb;
}
#if 0
if (sarSoftReset != 0)
skb = atmRxDataDescrp->skb;
else{
//skb = skbmgr_dev_alloc_skb2k();
skb = skbmgr_dev_alloc_skb2k_tc_critical();
if(skb == NULL){
printk("atmRxSkbAlloc skb==NULL");
return -1;
}
dma_cache_inv((unsigned long)skb->data, RX_BUF_LEN);
}
#endif
if ( descrId == ATM_RX_VC_DESCR_NUMMAX - 1 ) {
// BD_GAP, Rx Descriptor own by DMA; EOR=1
atmRxDataDescrp->rdes0 =TSARM_TX_DESCR_BD_GAP(TSARM_RX_DATA_BD_GAP)
| TSARM_RX_DESCR_EOR | TSARM_RX_DESCR_VALID;
}else{
// BD_GAP, Rx Descriptor own by DMA
atmRxDataDescrp->rdes0 = TSARM_TX_DESCR_BD_GAP(TSARM_RX_DATA_BD_GAP)
| TSARM_RX_DESCR_VALID;
}
// RDES1 = 1776; Set Rx Buffer size = 1776, reference zynos configure
atmRxDataDescrp->rdes1 = atmRxBufferSize<<16;
// RDES2 = point the Rx Buffer to mbuf
atmRxDataDescrp->rdes2 = K1_TO_PHYSICAL(skb->data);
atmRxDataDescrp->rdes3 = 0x0;
atmRxDataDescrp->skb = skb;
}
return 0;
}
void atmRxSkbFree(uint8 vc)
{
uint8 descrId;
atmRxDescrPool_t *atmRxDescrVcPoolp;
atmRxDescr_t *atmRxDataDescrp;
struct sk_buff *skb;
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
for ( descrId = 0; descrId < ATM_RX_VC_DESCR_NUMMAX; descrId++ ) {
atmRxDataDescrp = atmRxDescrVcPoolp->rxDescrPool+ descrId;
skb = atmRxDataDescrp->skb;
if( skb != NULL ){
dev_kfree_skb_any(skb);
atmRxDataDescrp->skb = NULL;
}
atmRxDataDescrp->rdes2 = 0x0;
}
}
#endif
#endif
/*______________________________________________________________________________
** atmAal5RealDataReq
**
** descriptions: API for sending an AAL5 frame
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
uint8
atmAal5RealDataReq(
struct sk_buff *skb,
uint8 vc
)
{
uint32 atmTxVcDescrNummax=0;
uint8 priority = 3;
uint8 new_priority;
int i;
atmTxVcDescrNummax = atmTxQueSize[0] + atmTxQueSize[1] + atmTxQueSize[2] +
atmTxQueSize[3];
if ( atmTxVcCnt[vc] >= ATM_TX_BUF_RELEASE_THRESHOLD ) {
atmTxDescrFree(vc, 0);
}
#ifdef TCSUPPORT_QOS
switch (qos_flag) {
#if !defined(TCSUPPORT_CT)
case QOS_SW_PQ:
/* PQ mode */
if (priority > 1 && (skb->mark & QOS_FILTER_MARK) == QOS_HH_PRIORITY) {
priority = 1;
}
else if (priority > 2 && (skb->mark & QOS_FILTER_MARK) == QOS_H_PRIORITY) {
priority = 2;
}
break;
#endif
#if defined(TCSUPPORT_HW_QOS)
case QOS_HW_WRR:
/* HW WRR mode */
if ((skb->mark & QOS_FILTER_MARK) == QOS_HH_PRIORITY) {
//printk("lalala to first queue.\n");
priority = 0;
}
else if ((skb->mark & QOS_FILTER_MARK) == QOS_H_PRIORITY) {
priority = 1;
}
else if ((skb->mark & QOS_FILTER_MARK) == QOS_M_PRIORITY) {
priority = 2;
}
else {
priority = 3;
}
break;
#endif
#if !defined(TCSUPPORT_CT)
case QOS_HW_PQ:
/* HW PQ mode */
if (priority > 0 && (skb->mark & QOS_FILTER_MARK) == QOS_HH_PRIORITY) {
priority = 0;
}
else if (priority > 1 && (skb->mark & QOS_FILTER_MARK) == QOS_H_PRIORITY) {
priority = 1;
}
else if (priority > 2 && (skb->mark & QOS_FILTER_MARK) == QOS_M_PRIORITY) {
priority = 2;
}
break;
case NULLQOS:/*It's for putting rtp packets to HH priority when qos_flag not be selected as WRR or PQ*/
if ((skb->mark & QOS_FILTER_MARK) == QOS_HH_PRIORITY) {
priority = 0;
}
break;
#endif
default:
break;
}
#endif
#ifdef QOS_REMARKING /*Rodney_20090724*/
if((skb->mark & QOS_REMARKING_FLAG)){
priority = (uint8)((skb->mark & QOS_REMARKING_MASK) >> 1);
}
else{
if (priPktChk && (skb->len < priPktChkLen)) {
/*20100921_serena_modify: add inupu arg "len" to check tcp packet*/
if (isPriorityPkt(skb->data, &new_priority, skb->len)) {
#if !defined(TCSUPPORT_CT)
#ifdef TCSUPPORT_QOS
if (qos_flag == QOS_HW_WRR) {
/* hw wrr mode, to handle special packet */
priority = max_prio;
}
else {
if (new_priority < priority) {
priority = new_priority;
}
}
#else
priority = new_priority;
#endif
#endif
}
}
}
#else
if (priPktChk && (skb->len < priPktChkLen)) {
/*20100921_serena_modify: add inupu arg "len" to check tcp packet*/
if (isPriorityPkt(skb->data, &new_priority, skb->len)) {
#if !defined(TCSUPPORT_CT)
#ifdef TCSUPPORT_QOS
if (qos_flag == QOS_HW_WRR) {
/* hw wrr mode, to handle special packet */
priority = max_prio;
}
else {
if (new_priority < priority) {
priority = new_priority;
}
}
#else
priority = new_priority;
#endif
#endif
}
}
#endif
#ifdef PURE_BRIDGE
priority = 0;
#endif
#ifdef SAR_VERIFY
priority=isWrrPriorityPkt(skb, priority);
#endif
#if defined(TCSUPPORT_CT)
#ifdef TCSUPPORT_QOS
if (qos_flag == 0) {
/* PQ mode */
if (priority == 3 && (skb->mark & QOS_FILTER_MARK) == QOS_HH_PRIORITY) {
priority = 2;
}
}
#endif
#endif
if ( atmTxPriVcCnt[priority][vc] >= atmTxQueSize[priority]) {
atmTxDescrFree(vc, 0);
}
if ( atmTxVcCnt[vc] >= atmTxVcDescrNummax ) {
atm_p->MIB_II.outDiscards++;
if (ATM_SKB(skb)->vcc->pop) {
ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb);
} else {
dev_kfree_skb_any(skb);
}
for (i = 0; i < ATM_VC_MAX; i++)
atmTxDescrFree(i, 0);
return 1;
}
atmDataReq(skb, vc, priority);
return 0;
}
void atmTxPolling(uint8 priority, uint8 vc){
switch(priority){
case 0:
TSARM_TXDBCSR_P01 |= 1 << vc;
break;
case 1:
TSARM_TXDBCSR_P01 |= 1 << (vc+16);
break;
case 2:
TSARM_TXDBCSR_P23 |= 1 << vc;
break;
case 3:
TSARM_TXDBCSR_P23 |= 1 << (vc+16);
break;
default:
break;
}
return;
}
uint8 atmDataReq(struct sk_buff *skb, uint8 vc, uint8 priority){
volatile atmTxDescr_t *atmTxDescrp;
#ifdef QOS_DROP_DUMP /*Rodney_20091115*/
static int drop_cnt = 0;
#endif
#ifdef SAR_VERIFY
dumpDataCell(skb, priority);
#endif
atmTxDescrp = atmTxVcFreeDescrp[priority][vc];
if ( !(atmTxDescrp->tdes0 & TSARM_TX_DESCR_VALID) && (atmTxDescrp->skb == NULL)) {
#if defined(TCSUPPORT_CT_SWQOS)
if(atmTxVcCnt[vc] >=(atmTxQosQueueSize - 2)){
if(sw_PKTQOS_SET_STOP != NULL)
sw_PKTQOS_SET_STOP();
}
#endif
dma_cache_wback_inv((unsigned long)(skb->data), skb->len);
#ifdef SAR_VERIFY
setSarVerifyDataDescrip(atmTxDescrp);
#endif
atm_p->MIB_II.outPkts++;
atm_p->MIB_II.outBytes += skb->len;//yzwang_20091125
atmTxDescrp->tdes1 = skb->len << 16;
atmTxDescrp->tdes2 = K1_TO_PHYSICAL(skb->data);
atmTxDescrp->skb = skb;
atmTxDescrp->tdes0 |= TSARM_TX_DESCR_VALID;
if(atmTxDescrp->tdes0 & TSARM_TX_DESCR_EOR){
atmTxVcFreeDescrp[priority][vc] = atmTxDescrPoolAddr[vc].pTxDescr[priority];
}else
atmTxVcFreeDescrp[priority][vc]++;
atmTxPriVcCnt[priority][vc]++;
atmTxVcCnt[vc]++;
atmTxVcTotalCnt++;
atmTxPolling(priority, vc);
ledTurnOn(LED_DSL_ACT_STATUS);
#ifdef TR068_LED
/*for interner traffic led*/
if(internet_led_on) {//IP connected and IP traffic is passing
ledTurnOn(LED_INTERNET_STATUS);
ledTurnOn(LED_INTERNET_ACT_STATUS);
}
else {
if(!internet_trying_led_on) {
ledTurnOff(LED_INTERNET_STATUS);
ledTurnOff(LED_INTERNET_TRYING_STATUS);
}
}
#endif
#ifdef QOS_DROP_DUMP /*Rodney_20091115*/
if(drop_cnt >= MAX_LOG_PKT)
drop_cnt = 0;
qos_drop_flag[drop_cnt++] = 0;
#endif
} else {
#ifdef QOS_DROP_DUMP /*Rodney_20091115*/
if(drop_cnt >= MAX_LOG_PKT)
drop_cnt = 0;
qos_drop_flag[drop_cnt++] = 1;
#endif
atm_p->MIB_II.outDiscards++;
#ifdef SAR_VERIFY
if(ATM_SKB(skb)->vcc ==NULL){
dev_kfree_skb_any(skb);
return 0;
}
#endif
if (ATM_SKB(skb)->vcc->pop) {
ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb);
} else {
dev_kfree_skb_any(skb);
}
}
return 0;
}
#define CONFIG_VLAN_ATM
#ifdef CONFIG_VLAN_ATM
#define QOS_8021p_MARK 0x0F00 /* 8~11 bits used for 802.1p */
#define QOS_8021P_0_MARK 0x08 /* default mark is zero */
#define QOS_8021P_TRANSPARENT 0x09
#define RFC1483_B_LLC (0)
#define RFC1483_R_LLC 1
#define RFC1483_B_VC 2
#define PPPoA_LLC 3
#define PPPoA_VC 4
#define RFC1483_R_VC 5
#define VLAN_HLEN 4
#define VLAN_ETH_ALEN 6
#define SET_ATM_VLAN 0x1111
#define DEL_ATM_PVC 0x2222
typedef struct tsarm_ioctl{
unsigned short int active;
unsigned int vid;
unsigned char vpi;
unsigned char vci;
}tsarm_ioctl_t;
tsarm_ioctl_t vlan_vcc[ATM_VC_MAX] = {0};
uint8 getIndexVlanVcc( uint8 vpi, uint8 vci )
{
uint8 vc;
for ( vc = 0; vc < ATM_VC_MAX; vc++ ) {
if ( vlan_vcc[vc].vpi == vpi && vlan_vcc[vc].vci == vci ) {
return vc;
}
}
return ATM_DUMMY_VC;
}
int getEncapMode(uint8 *data)
{
/*RFC1483 LLC Brided Mode*/
if ( memcmp(data, RFC1483_B_LLC_HDR, 7 ) == 0 ) {
return RFC1483_B_LLC;
}
/*RFC1483 LLC Routing Mode*/
else if ( memcmp(data, RFC1483_R_LLC_HDR, sizeof(RFC1483_R_LLC_HDR)) == 0 ){
return RFC1483_R_LLC;
}
/*PPPoA LLC Routing Mode*/
else if ( memcmp(data, PPPOA_LLC_HDR, sizeof(PPPOA_LLC_HDR)) == 0 ){
return PPPoA_LLC;
}
/*PPPoA VCMux Routing Mode*/
else if ( memcmp(data, PPPOA_VC_HDR, sizeof(PPPOA_VC_HDR)) == 0 ){
return PPPoA_VC;
}
/*RFC1483 VCMux Bridged Mode*/
else if ( memcmp(data, RFC1483_B_VC_HDR, sizeof(RFC1483_B_VC_HDR)) == 0 ) {
return RFC1483_B_VC;
}
else {
return RFC1483_R_VC;
}
}
int atmEncapLen[] = {
sizeof(RFC1483_B_LLC_HDR),
sizeof(RFC1483_R_LLC_HDR),
sizeof(PPPOA_LLC_HDR),
sizeof(PPPOA_VC_HDR),
sizeof(RFC1483_B_VC_HDR)
};
#if 0
static void dump_skb(struct sk_buff *skb)
{
char tmp[80];
char *p = skb->data;
char *t = tmp;
int i, n = 0;
printk("ERR skb=%08lx data=%08lx len=%d\n", (uint32) skb, (uint32) skb->data, skb->len);
for (i = 0; i < skb->len + 4; i++) {
t += sprintf(t, "%02x ", *p++ & 0xff);
if ((i & 0x0f) == 0x0f) {
printk("%04x: %s\n", n, tmp);
n += 16;
t = tmp;
}
}
if (i & 0x0f)
printk("%04x: %s\n", n, tmp);
}
#endif
#if defined(TCSUPPORT_CT)
static inline struct sk_buff * insert_vtag(struct sk_buff *skb, uint8 vc)
#else
static struct sk_buff * insert_vtag(struct sk_buff *skb, uint8 vc)
#endif
{
uint8 encap_mode = 0, encap_len = 0;
char * vlan_p = NULL, *ether_type_ptr = NULL;
unsigned char ucprio = 0;
unsigned char uc802prio = 0;
int copy_len = 0;
if ( skb->mark & QOS_8021p_MARK ) {
/*vlan tagging*/
encap_mode = getEncapMode((uint8*)skb->data);
/*Note Ethernet Header*/
if ( (encap_mode == RFC1483_B_VC)
|| (encap_mode == PPPoA_LLC)
|| (encap_mode == PPPoA_VC) ) {
/*Nono ethernet header to do nothings*/
return skb;
}
encap_len = atmEncapLen[encap_mode];
ether_type_ptr = skb->data + encap_len + 12;
ucprio = (skb->mark & QOS_8021p_MARK) >> 8;
if ( (ucprio < QOS_8021P_0_MARK) && (ucprio >= 0) ) { //0~7 remark
uc802prio = ucprio;
}
else if ( QOS_8021P_0_MARK == ucprio ) { //zero mark
uc802prio = 0;
}
else if ( QOS_8021P_TRANSPARENT == ucprio ) {//pass through
/*do nothing*/
return skb;
}
#if defined(TCSUPPORT_C1_CUC)
/*
** if the packet is vlan packet, just change the 802.1p value
** or add vlan tag header
*/
vlan_p = skb->data + encap_len + 12;
if (*(unsigned short *)vlan_p == 0x8100) {
vlan_p += 2;
*(unsigned short*)vlan_p &= 0x8fff;
*(unsigned short*)vlan_p |= ((uc802prio & 0x7) << 13);
return skb;
}
#endif
if ( skb_headroom(skb) < VLAN_HLEN ) {
struct sk_buff *sk_tmp = skb;
skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
if ( ATM_SKB(sk_tmp)->vcc->pop ) {
ATM_SKB(sk_tmp)->vcc->pop(ATM_SKB(sk_tmp)->vcc, sk_tmp);
}
else {
dev_kfree_skb_any(sk_tmp);
}
if ( !skb ) {
printk(KERN_ERR, "Vlan:failed to realloc headroom\n");
return NULL;
}
}
else {
skb = skb_unshare(skb, GFP_ATOMIC);
if ( !skb ) {
// printk(KERN_ERR, "Vlan: failed to unshare skbuff\n");
return NULL;
}
}
/*offset 4 bytes*/
#if 0
skb_push(skb, VLAN_HLEN*2);
copy_len = encap_len + 2*VLAN_ETH_ALEN;
#else
skb_push(skb, VLAN_HLEN);
copy_len = encap_len + 2*VLAN_ETH_ALEN;
#endif
/*move the mac address to the beginning of new header*/
memmove(skb->data, skb->data+VLAN_HLEN, copy_len);
#if 0
printk("mac is %02x:%02x:%02x:%02x:%02x:%02x\n",*(skb->data+encap_len),\
*(skb->data+encap_len+1),*(skb->data+encap_len+2),*(skb->data+encap_len+3),\
*(skb->data+encap_len+4),*(skb->data+encap_len+5));
#endif
vlan_p = skb->data + encap_len + 12;
*(unsigned short *)vlan_p = 0x8100;
vlan_p += 2;
*(unsigned short *)vlan_p = 0;
#if 0
vlan_p += 2;
*(unsigned short *)vlan_p = 0x8100;
vlan_p += 2;
*(unsigned short *)vlan_p = 0;
#endif
/*3 bits priority*/
*(unsigned short*)vlan_p |= ((uc802prio & 0x7) << 13);
/*12 bits vlan id*/
*(unsigned short *)vlan_p |= (vlan_vcc[vc].vid & 0x0fff);
//skb->mac.raw -= VLAN_HLEN;
//skb->nh.raw -= VLAN_HLEN;
skb->network_header -= VLAN_HLEN;
skb->mac_header -= VLAN_HLEN;
}
//dump_skb(skb);
return skb;
}
int resetVlanVcc(uint8 vpi, uint8 vci)
{
uint8 vc = getIndexVlanVcc( vpi, vci );
if ( (vc != ATM_DUMMY_VC) && (vc < ATM_VC_MAX) ) {
memset( &vlan_vcc[vc], 0, sizeof(tsarm_ioctl_t) );
}
else {
return -1;
}
return 0;
}
int setATMVlan( tsarm_ioctl_t *sar_ioctl )
{
uint8 vc;
/* reset this entry first */
resetVlanVcc( sar_ioctl->vpi, sar_ioctl->vci );
for( vc = 0; vc < ATM_VC_MAX; vc++ ) {
if(vlan_vcc[vc].vpi == 0 && vlan_vcc[vc].vci == 0 ){
vlan_vcc[vc].vpi = sar_ioctl->vpi;
vlan_vcc[vc].vci = sar_ioctl->vci;
vlan_vcc[vc].active = sar_ioctl->active;
vlan_vcc[vc].vid = sar_ioctl->vid;
return 0;
}
}
return -1;
}
#endif
/*______________________________________________________________________________
** atmAal5DataReq
**
** descriptions: API for sending an AAL5 frame
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
uint8
atmAal5DataReq(
struct sk_buff *skb,
uint8 vpi,
uint16 vci
)
{
uint8 vc;
vc = atmVcNumberGet(vpi, vci);
if ( vc == ATM_DUMMY_VC ) {
if (ATM_SKB(skb)->vcc->pop) {
ATM_SKB(skb)->vcc->pop (ATM_SKB(skb)->vcc, skb);
} else {
dev_kfree_skb_any(skb);
}
return 1;
}
return atmAal5RealDataReq(skb, vc);
}
/*______________________________________________________________________________
** atmCcDataReq
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
uint8
atmCcDataReq(
uint8 *data_p
)
{
atmTxCcDescr_t *atmTxCcDescrp;
atmTxCcDescrPool_t *atmTxCcDescrVcPoolp;
atmTxCcDescrp = atmTxCcFreeDescrp;
if ( !(atmTxCcDescrp->tdes0 & TSARM_TX_DESCR_VALID) ) {
#ifdef L2_AUTOPVC
setTxRaw(atmTxCcDescrp);
#endif
atmTxCcDescrp->tdes1 = 50 << 16;
atmTxCcDescrp->tdes2 = K1_TO_PHYSICAL(data_p);
atmTxCcDescrp->tdes0 |= TSARM_TX_DESCR_VALID;
if(atmTxCcDescrp->tdes0 & TSARM_TX_DESCR_EOR){
#ifdef DYNAMIC_ALLOC_DMA_BUF
atmTxCcDescrVcPoolp = (atmTxCcDescrPool_t *)CACHE_TO_NONCACHE(atmTxCcDescrPool);
#else
atmTxCcDescrVcPoolp = (atmTxCcDescrPool_t *)CACHE_TO_NONCACHE(&atmTxCcDescrPool);
#endif
atmTxCcFreeDescrp = atmTxCcDescrVcPoolp->txCcDescrPool;
}else{
atmTxCcFreeDescrp++;
}
atmTxCcCnt++;
TSARM_TXMBCSR |= 1 << 16;
}
else {
return 1;
}
return 0;
}
/*______________________________________________________________________________
** atmOamDataReq
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
uint8
atmOamDataReq(
uint8 *data_p,
uint8 pti,
uint8 vc
)
{
atmTxCcDescr_t *atmTxCcDescrp;
#ifdef SAR_VERIFY
dumpMCellAddr(data_p, OAM_CELL);
#endif
atmTxCcDescrp = atmTxOamFreeDescrp[vc];
if ( !(atmTxCcDescrp->tdes0 & TSARM_TX_DESCR_VALID) ) {
atmTxCcDescrp->tdes1 = (pti << 28) | (48 << 16);
atmTxCcDescrp->tdes2 = K1_TO_PHYSICAL(data_p);
atmTxCcDescrp->tdes0 |= TSARM_TX_DESCR_VALID;
if(atmTxCcDescrp->tdes0 & TSARM_TX_DESCR_EOR){
atmTxOamFreeDescrp[vc] = atmTxDescrPoolAddr[vc].pTxOamDescr;
}else{
atmTxOamFreeDescrp[vc]++;
}
atmTxCcCnt++;
TSARM_TXMBCSR |= 1 << vc;
}
else {
return 1;
}
return 0;
}
/*______________________________________________________________________________
** atmOamF4F5DataReq
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
uint32
atmOamF4F5DataReq(
uint8 vpi,
uint16 vci,
uint8 f5,
uint8 endToEnd,
uint8 funcType
)
{
atmOamCell_t *oamCellp;
atmOamCellPayload_t *oamCellPayloadp;
uint8 vc;
uint8 pti;
#ifdef DMA_API
uint32 mem_size=0;
#endif
#ifdef DYNAMIC_ALLOC_DMA_BUF
#ifndef DMA_API
static atmCell_t *atmCellCirBuf = NULL;
#endif
static int atmCellCirBufIndex = 0;
atmCell_t *atmCellBuf;
if (atmCellCirBuf == NULL) {
#ifndef DMA_API
if ((atmCellCirBuf = kmalloc(sizeof(atmCell_t)*ATM_VC_MAX, GFP_KERNEL)) == NULL) {
printk("unable to kmalloc atmCellCirBuf structure.\n");
return 1;
}
#else
mem_size=sizeof(atmCell_t)*ATM_VC_MAX;
atmCellCirBuf=(atmCell_t *)dma_alloc_coherent(NULL, mem_size, (dma_addr_t *) &atmCellCirBuf_phys_p, GFP_KERNEL);
if (atmCellCirBuf == NULL) {
printk("unable to dma_alloc_coherent atmCellCirBuf structure.\n");
return 1;
}
#endif
}
atmCellBuf = (atmCell_t *)(atmCellCirBuf + atmCellCirBufIndex);
memset((uint8*)atmCellBuf, 0, sizeof(atmCell_t));
atmCellCirBufIndex++;
if (atmCellCirBufIndex == ATM_VC_MAX)
atmCellCirBufIndex = 0;
#endif
if ( f5 ) { /* F5: by PTI */
/* Move to non-cacheable region */
switch ( funcType ) {
case 0: /* AIS */
#ifdef DYNAMIC_ALLOC_DMA_BUF
oamCellPayloadp = (atmOamCellPayload_t *)(oamF5AisCell);
#else
oamCellPayloadp = (atmOamCellPayload_t *)(CACHE_TO_NONCACHE(oamF5AisCell));
#endif
break;
case 1: /* RDI */
#ifdef DYNAMIC_ALLOC_DMA_BUF
oamCellPayloadp = (atmOamCellPayload_t *)(oamF5RdiCell);
#else
oamCellPayloadp = (atmOamCellPayload_t *)(CACHE_TO_NONCACHE(oamF5RdiCell));
#endif
break;
case 2: /* Loopback */
#ifdef DYNAMIC_ALLOC_DMA_BUF
oamCellPayloadp = (atmOamCellPayload_t *)(oamF5LoopBackReqCell);
#else
oamCellPayloadp = (atmOamCellPayload_t *)(CACHE_TO_NONCACHE(oamF5LoopBackReqCell));
#endif
break;
case 3: /* Continuity check */
#ifdef DYNAMIC_ALLOC_DMA_BUF
oamCellPayloadp = (atmOamCellPayload_t *)(oamF5ContinuityCheckReqCell);
#else
oamCellPayloadp = (atmOamCellPayload_t *)(CACHE_TO_NONCACHE(oamF5ContinuityCheckReqCell));
#endif
break;
default:
return 1;
}
vc = atmVcNumberGet(vpi, vci);
if ( vc == ATM_DUMMY_VC ) {
/* This is not a opened VC */
return 1;
}
if ( endToEnd ) {
pti = 5;
}
else {
pti = 4;
}
#ifdef DYNAMIC_ALLOC_DMA_BUF
memcpy(atmCellBuf->word, (uint8 *)oamCellPayloadp, 48);
if(!atmOamDataReq((uint8 *)atmCellBuf->word, pti, vc)){
#else
if(!atmOamDataReq((uint8 *)oamCellPayloadp, pti, vc)){
#endif
atm_p->MIB_II.outF5Pkts++;
atm_p->MIB_II.outPkts++;
//add by brian
#ifdef CWMP
if(cwmpflag)
{
cwmpSavedOutF5Pkts++;
}
#endif
}
}
else { /* F4: by VCI */
/* Move to non-cacheable region */
switch ( funcType ) {
case 0: /* AIS */
#ifdef DYNAMIC_ALLOC_DMA_BUF
oamCellp = (atmOamCell_t *)(oamAisCell);
#else
oamCellp = (atmOamCell_t *)(CACHE_TO_NONCACHE(oamAisCell));
#endif
break;
case 1: /* RDI */
#ifdef DYNAMIC_ALLOC_DMA_BUF
oamCellp = (atmOamCell_t *)(oamRdiCell);
#else
oamCellp = (atmOamCell_t *)(CACHE_TO_NONCACHE(oamRdiCell));
#endif
break;
case 2: /* Loopback */
#ifdef DYNAMIC_ALLOC_DMA_BUF
oamCellp = (atmOamCell_t *)(oamLoopBackReqCell);
#else
oamCellp = (atmOamCell_t *)(CACHE_TO_NONCACHE(oamLoopBackReqCell));
#endif
break;
case 3: /* Continuity check */
#ifdef DYNAMIC_ALLOC_DMA_BUF
oamCellp = (atmOamCell_t *)(oamContinuityCheckReqCell);
#else
oamCellp = (atmOamCell_t *)(CACHE_TO_NONCACHE(oamContinuityCheckReqCell));
#endif
break;
default:
return 1;
}
oamCellp->vpi = vpi;
if ( endToEnd ) {
oamCellp->vci = 4;
}
else {
oamCellp->vci = 3;
}
#ifdef DYNAMIC_ALLOC_DMA_BUF
memcpy(atmCellBuf->word, (uint8 *)oamCellp, 52);
if(!atmCcDataReq((uint8 *)atmCellBuf->word)){
#else
if(!atmCcDataReq((uint8 *)oamCellp)){
#endif
atm_p->MIB_II.outF4Pkts++;
atm_p->MIB_II.outPkts++;
}
}
return 0;
}
void
atmRxIrqQueueSet(
uint32 irqBase,
uint32 irqLength
)
{
TSARM_IRQBA = K0_TO_PHYSICAL(irqBase);
TSARM_IRQLEN = irqLength;
}
void initMPOA(uint32 vc, qosProfile_t *qos_p)
{
//re-init reg
TSARM_MPOA_GCR &= ~(1<<(vc+16) | (1<<vc));
TSARM_VC_MPOA_CTRL(vc) = 0x0;
//MPOA global control register
if(qos_p->mode == MODE_ROUTER){ //router mode
if(qos_p->encapType == ENCAP_RFC2364)
TSARM_MPOA_GCR |= 1 << (vc+16) | 1 << vc;
else
TSARM_MPOA_GCR |= 0 << (vc+16) | 1 << vc;
}else if(qos_p->mode == MODE_BRIDGE){ //bridge mode
TSARM_MPOA_GCR |= 0 << (vc+16) | 0 << vc;
}
//VC 0 ~ 9 control register
if(qos_p->muxType == MUX_VC){
switch(qos_p->encapType){
case ENCAP_RFC1483:
if(qos_p->mode == MODE_ROUTER){ //router mode
// TSARM_VC_MPOA_CTRL(vc) |= 0x0;
TSARM_VC_MPOA_CTRL(vc) |= 0x0200; // Jason_20060710 workaround the HW MPOA problem
}else if(qos_p->mode == MODE_BRIDGE){ //bridge mode
TSARM_VC_MPOA_CTRL(vc) |= 0x0340; //(00001, 0100, 0000){Field4Value1}
}
break;
case ENCAP_RFC2364: //PPPoA
// TSARM_VC_MPOA_CTRL(vc) |= 0x0;
TSARM_VC_MPOA_CTRL(vc) |= 0x0200; // Jason_20060710 workaround the HW MPOA problem
break;
case ENCAP_MER:
TSARM_VC_MPOA_CTRL(vc) |= 0x0340; //(00001, 0100, 0000){Field4Value1}
break;
case ENCAP_POE:
TSARM_VC_MPOA_CTRL(vc) |= 0x0340; //(00001, 0100, 0000){Field4Value1}
default:
break;
}
}else if(qos_p->muxType == MUX_LLC){ //MUX_LLC
switch(qos_p->encapType){
case ENCAP_RFC1483:
if(qos_p->mode == MODE_ROUTER){ //router mode
//(00001, 1000, 1001){Field4Value2, Field2Value2, Field1Value1}
TSARM_VC_MPOA_CTRL(vc) |= 0x0389;
}else if(qos_p->mode == MODE_BRIDGE){ //bridge mode
//(00001, 0110, 0101){Field4Value1, Field3Value2, Field2Value1, Field1Value1}
TSARM_VC_MPOA_CTRL(vc) |= 0x0365;
}
break;
case ENCAP_RFC2364: //PPPoA
//(0001, 1111, 0000){Field4Valu3, Field3Value3}
TSARM_VC_MPOA_CTRL(vc) |= 0x03f0;
break;
case ENCAP_MER:
//(00001, 0110, 0101){Field4Value1, Field3Value2, Field2Value1, Field1Value1}
TSARM_VC_MPOA_CTRL(vc) |= 0x0365;
break;
case ENCAP_POE:
//(00001, 0110, 0101){Field4Value1, Field3Value2, Field2Value1, Field1Value1}
TSARM_VC_MPOA_CTRL(vc) |= 0x0365;
default:
break;
}
}
/*
* to avoid function dependency problem, move hareware vlan untag setting
* to doTsarmHwVlanUntagSwitch function
*
* frankliao removed 20100713
*/
// #ifdef SAR_VERIFY
// enHwVlanUntag(vc);
// #endif
}
uint32
tc3162l2AtmMbsCalCulate(
uint16 pcr,
uint16 scr,
uint16 mbs
)
{
uint32 cal_mbs;
cal_mbs = (uint32)(mbs*(1-(scr * (1 /(float)pcr))));
if(cal_mbs == 0)
cal_mbs = 1;
return cal_mbs;
}
void
tc3162l2AtmRateCalCulate(
uint16 tb,
uint16 cellRate,
uint8 *dec_p,
uint16 *init_p
)
{
uint16 dec, init;
uint32 calCellRate;
uint32 diffSquare = 0xffffffff;
uint32 closesetSquare = 0xff;
float calRateParam=0;
float calRateParam_f=0;
int i = 0, j = 0;
#if 0
/*add by zyzhang, 20080123
Question: cpe crash when cell rate is small
Root cause: if the cell rate is too small, timebase(default: 59) is not appropriate;
Through emluting, timebase(default: 59) is not appropriate to high cell rate too.
Thess cases will cause cpu 100%, and mpoa state machine and conn-mgr state machine can't work properly*/
#if defined(TC3262_FPGA) //for FPGA
; //reserved for FPGA test
#else
if(cellRate <= 0x29 && cellRate > 0x1f)
tb = 256;
else if(cellRate <= 0x53 && cellRate > 0x29)
tb = 199;
else if(cellRate <= 0x87 && cellRate > 0x53)
tb = 98;
else if(cellRate < 0x5000 && cellRate > 0x87)
; //do nothing, don't change timebase, the default timebase is 59. please refer to treg_tstbr
else if(cellRate>=0x5000) //cell rate >= 0x5000(may be imposible now). if cell rate is too big, this algorithem is out of action
tb = 2;
else{ //cell rate <= 0x1f(may be imposible actually), this algorithem is out of action
*dec_p = 1;
*init_p = 0xff5;
return;
}
#endif
#endif
/* find ATM Qos parameter in table */
for(i = 0; i < MAX_ATMQOS_CNT; i++){
if((ATMQosParam[i].dec == 0)&&(ATMQosParam[i].init == 0))
continue;
else
{
if(ATMQosParam[i].cellRate == cellRate){
*dec_p = ATMQosParam[i].dec;
*init_p = ATMQosParam[i].init;
return;
}
}
}
//calRateParam=(float)SAR_CLK*1000000;
calRateParam_f=(float)SAR_CLK*1000000*(1/(float)(tb+1));
for ( dec = 1; dec <= 0x07f; dec++ ) { /* PCR_dec or SCR_dec are both 7 bits long */
diffSquare = 0xffffffff;
calRateParam=calRateParam_f*(float)dec;
for ( init = dec; init <= 0x0fff; init++ ) { /* PCR_init or SCR_init are both 12 bits long */
//calCellRate= calRateParam * dec * (1/(float)(tb+1)) * (1/(float)init);
calCellRate= calRateParam*(1/(float)init);
diffSquare = calCellRate - cellRate;
if ( diffSquare < closesetSquare ) {
closesetSquare = diffSquare;
*dec_p = dec;
*init_p = init;
if ( diffSquare == 0 ) {
/* Perfectly match */
goto Store; /*store the parameter to table and you can find next time when cellRate is the same*/
//return;
}
}
}
}
Store:
for(j = 0; j < MAX_ATMQOS_CNT; j++){
if((ATMQosParam[j].dec == 0)&&(ATMQosParam[j].init == 0)){
ATMQosParam[j].cellRate = cellRate;
ATMQosParam[j].dec = *dec_p;
ATMQosParam[j].init = *init_p;
break;
}
}
if(j == MAX_ATMQOS_CNT){ /*The table is full and modify from the last one*/
ATMQosParam[j-1].cellRate = cellRate;
ATMQosParam[j-1].dec = *dec_p;
ATMQosParam[j-1].init = *init_p;
}
return;
}
/*______________________________________________________________________________
** setAtmQosRed
**
** descriptions:Used to set Atm Qos register
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:atmAal5VcOpen,update_qosred
** call:
**____________________________________________________________________________*/
static int
setAtmQosRed(
qosProfile_t *qos_p,
uint32 vc
)
{
uint32 dslUpRate;
uint8 pcr_dec;
uint8 scr_dec;
uint8 lr_dec;
uint16 pcr_init;
uint16 scr_init;
uint16 lr_init;
uint32 cal_mbs;
switch (qos_p->type)
{
case CBR : qos_p->type = TSARM_QOS_CBR; break;
case UBR : qos_p->type = TSARM_QOS_UBR; break;
case VBR : qos_p->type = TSARM_QOS_rtVBR; break;
case nrtVBR : qos_p->type = TSARM_QOS_nrtVBR; break;
default : qos_p->type = TSARM_QOS_UBR; break;
}
dslUpRate = getXdslSpeed(); /* Kbps */
if (dslUpRate <= 0)
{
dslUpRate = 1024;
}
dslUpRate = (dslUpRate * 1000) / (53 * 8); /* cell rate */
if(dslUpRate % 53 !=0){
dslUpRate=dslUpRate+1;
}
if (pcr_modify_flag)
{
qos_p->pcr = g_qos_pcr;
}
if ((qos_p->pcr == 0) || (qos_p->pcr > dslUpRate))
qos_p->pcr = dslUpRate;
if ((qos_p->scr == 0) || (qos_p->scr > qos_p->pcr))
qos_p->scr = qos_p->pcr;
if (qos_p->mbs == 0)
qos_p->mbs = 1;
//init line rate
tc3162l2AtmRateCalCulate((uint16)treg_tstbr, (uint16)dslUpRate, &lr_dec, &lr_init);
TSARM_TXSLRC = (lr_dec << 16) | lr_init;
/* ----- Set up vpi, vci, and QoS parameters of the vc ----- */
//calculate rate.......
if (( qos_p->type == TSARM_QOS_CBR) || (qos_p->type == TSARM_QOS_UBR) ) {
tc3162l2AtmRateCalCulate((uint16)treg_tstbr, qos_p->pcr, &scr_dec, &scr_init);
if(getXdslModeType() == ME_CMD_ADSL_ANNEXM){
qos_p->mbs = 2;
}
else{
qos_p->mbs = 1; // if CBR, mbs must be 1
}
TSARM_SCR(vc) = (scr_dec << 16) | scr_init;
TSARM_PCR(vc) = (scr_dec << 16) | scr_init;
if(qos_p->type == TSARM_QOS_CBR)
TSARM_MBSTP(vc) = (1 << 28) |(0 << 26) |(qos_p->mbs << 2) | qos_p->type;
else
TSARM_MBSTP(vc) = (1 << 28) |(3 << 26) |(qos_p->mbs << 2) | qos_p->type;
} else {
tc3162l2AtmRateCalCulate((uint16)treg_tstbr, qos_p->pcr, &pcr_dec, &pcr_init);
tc3162l2AtmRateCalCulate((uint16)treg_tstbr, qos_p->scr, &scr_dec, &scr_init);
TSARM_PCR(vc) = (pcr_dec << 16) | pcr_init;
TSARM_SCR(vc) = (scr_dec << 16) | scr_init;
cal_mbs = tc3162l2AtmMbsCalCulate(qos_p->pcr, qos_p->scr, qos_p->mbs);
if(qos_p->type == TSARM_QOS_rtVBR)
TSARM_MBSTP(vc) = (1 << 28) |(1 << 26) | (cal_mbs << 2) | qos_p->type; //for new L2 SAR
else
TSARM_MBSTP(vc) = (1 << 28) |(2 << 26) | (cal_mbs << 2) | (2 << 0);
}
if (sarDebugFlag){
dbg_plinel_1("\r\n vc:", vc);
dbg_plinel_1(" PCR:", TSARM_PCR(vc));
dbg_plinel_1(" SCR:", TSARM_SCR(vc));
dbg_plinel_1(" MBSTP:", TSARM_MBSTP(vc));
dbg_plinel_1("\r\n TSARM_MPOA_GCR:", TSARM_MPOA_GCR);
dbg_plinel_1(" TSARM_VC_MPOA_CTRL:", TSARM_VC_MPOA_CTRL(vc));
dbg_pline_1("\r\n");
}
return 0;
}
#if defined(TCSUPPORT_CT)
extern atomic_t g_used_skb_num;
#endif
/*______________________________________________________________________________
** atmAal5VcOpen
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
int
atmAal5VcOpen(
uint8 vpi,
uint16 vci,
qosProfile_t *qos_p,
struct atm_vcc *vcc
)
{
uint32 i, vc = ATM_VC_MAX;
//uint8 pcr_dec;
//uint8 scr_dec;
//uint8 lr_dec;
//uint16 pcr_init;
//uint16 scr_init;
//uint16 lr_init;
uint32 temp;
//uint32 dslUpRate;
//uint32 cal_mbs;
if (sarDebugFlag) {
dbg_plineb_1("\r\n open vpi=", vpi);
dbg_plinew_1(" vci=", vci);
dbg_plinew_1(" type=", qos_p->type);
dbg_plinew_1(" pcr=", qos_p->pcr);
dbg_plinew_1(" scr=", qos_p->scr);
dbg_plinew_1(" mbs=", qos_p->mbs);
}
/* ----- Check the number of total opened vc ----- */
if ( atmCfgTable.vcNumber >= ATM_VC_MAX ) {
return 1;
}
for ( i = 0; i < ATM_VC_MAX; i++ ) {
if ( atmCfgTable.openFlag[i] == 0 ) {
atmCfgTable.openFlag[i] = 1;
vc = i;
atmCfgTable.vpi[vc] = vpi;
atmCfgTable.vci[vc] = vci;
memcpy( (uint8*)&qosRecord[vc],(uint8*)qos_p, sizeof(qosProfile_t));
atmCfgTable.vcc[vc] = vcc;
atmCfgTable.vcNumber++;
break;
}
}
if (vc == ATM_VC_MAX)
return 1;
#if defined(TCSUPPORT_CT)
#ifdef DYNAMIC_ALLOC_SKB
if(g_NoNeedFreeSKB != 1){
if(atmRxSkbAlloc(vc) == -1){
printk("atmRxSkbAlloc FAILED\n");
printk("skb_buff_alloc_num is %d\n", atomic_read(&g_used_skb_num));
dump_stack();
return 1;
}
}
#endif
#endif
#if 1
setAtmQosRed(qos_p,vc);
#else
switch (qos_p->type)
{
case CBR : qos_p->type = TSARM_QOS_CBR; break;
case UBR : qos_p->type = TSARM_QOS_UBR; break;
case VBR : qos_p->type = TSARM_QOS_rtVBR; break;
case nrtVBR : qos_p->type = TSARM_QOS_nrtVBR; break;
default : qos_p->type = TSARM_QOS_UBR; break;
}
dslUpRate = getXdslSpeed(); /* Kbps */
if (dslUpRate <= 0)
{
dslUpRate = 1024;
}
dslUpRate = (dslUpRate * 1000) / (53 * 8); /* cell rate */
if(dslUpRate % 53 !=0){
dslUpRate=dslUpRate+1;
}
if ((qos_p->pcr == 0) || (qos_p->pcr > dslUpRate))
qos_p->pcr = dslUpRate;
if ((qos_p->scr == 0) || (qos_p->scr > qos_p->pcr))
qos_p->scr = qos_p->pcr;
if (qos_p->mbs == 0)
qos_p->mbs = 1;
//init line rate
tc3162l2AtmRateCalCulate((uint16)treg_tstbr, (uint16)dslUpRate, &lr_dec, &lr_init);
TSARM_TXSLRC = (lr_dec << 16) | lr_init;
/* ----- Set up vpi, vci, and QoS parameters of the vc ----- */
//calculate rate.......
if (( qos_p->type == TSARM_QOS_CBR) || (qos_p->type == TSARM_QOS_UBR) ) {
tc3162l2AtmRateCalCulate((uint16)treg_tstbr, qos_p->pcr, &scr_dec, &scr_init);
qos_p->mbs = 1; // if CBR, mbs must be 1
TSARM_SCR(vc) = (scr_dec << 16) | scr_init;
TSARM_PCR(vc) = (scr_dec << 16) | scr_init;
if(qos_p->type == TSARM_QOS_CBR)
TSARM_MBSTP(vc) = (1 << 28) |(0 << 26) |(qos_p->mbs << 2) | qos_p->type;
else
TSARM_MBSTP(vc) = (1 << 28) |(3 << 26) |(qos_p->mbs << 2) | qos_p->type;
} else {
tc3162l2AtmRateCalCulate((uint16)treg_tstbr, qos_p->pcr, &pcr_dec, &pcr_init);
tc3162l2AtmRateCalCulate((uint16)treg_tstbr, qos_p->scr, &scr_dec, &scr_init);
TSARM_PCR(vc) = (pcr_dec << 16) | pcr_init;
TSARM_SCR(vc) = (scr_dec << 16) | scr_init;
cal_mbs = tc3162l2AtmMbsCalCulate(qos_p->pcr, qos_p->scr, qos_p->mbs);
if(qos_p->type == TSARM_QOS_rtVBR)
TSARM_MBSTP(vc) = (1 << 28) |(1 << 26) | (cal_mbs << 2) | qos_p->type; //for new L2 SAR
else
TSARM_MBSTP(vc) = (1 << 28) |(2 << 26) | (cal_mbs << 2) | (2 << 0);
}
if (sarDebugFlag){
dbg_plinel_1("\r\n vc:", vc);
dbg_plinel_1(" PCR:", TSARM_PCR(vc));
dbg_plinel_1(" SCR:", TSARM_SCR(vc));
dbg_plinel_1(" MBSTP:", TSARM_MBSTP(vc));
dbg_plinel_1("\r\n TSARM_MPOA_GCR:", TSARM_MPOA_GCR);
dbg_plinel_1(" TSARM_VC_MPOA_CTRL:", TSARM_VC_MPOA_CTRL(vc));
dbg_pline_1("\r\n");
}
#endif
TSARM_IRQM(vc) = treg_irqm;
// read to clear Receive Counter
temp = TSARM_TDCNT(vc);
temp = TSARM_RDCNT(vc);
// set up VC Configuration as valid =1, raw =0(AAL5 mode), port =0, VPI, VCI
TSARM_VCCR(vc) =
VCCFGR_VPI(vpi) | VCCFGR_VCI(vci) |
VCCFGR_PORT(VCCFGR_ATM_PHY0) | VCCFGR_VALID;
// to prevent 1/2^(28) error chance
VPint(0xbfb60128) = 0x1;
// workaround for abnormal irq report
TSARM_VCCR(10) = VCCFGR_VPI(vpi) | VCCFGR_VCI(vci) |
VCCFGR_PORT(VCCFGR_ATM_PHY0) | VCCFGR_VALID;
/* data cell */
TSARM_RXDBCSR |= 1 << vc;
/* management cell */
TSARM_RXMBCSR |= 1 << vc;
return 0;
}
/*______________________________________________________________________________
** atmAal5VcClose
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
uint8
atmAal5VcClose(
uint8 vpi,
uint16 vci
)
{
uint8 vc, i;
int priority=0;
vc = atmVcNumberGet(vpi, vci);
if ( vc == ATM_DUMMY_VC )
return 1;
if (sarDebugFlag) {
dbg_plineb_1("\r\n close vpi=", vpi);
dbg_plinew_1(" vci=", vci);
}
// VC configuration
TSARM_VCCR(vc) = 0;
// Transmit Buffer Descriptor
//TSARM_TXDCBDA(vc) = 0;
// OAM Transmit Buffer Descriptor
//TSARM_TXMCBDA(vc)=0;
// Receive Buffer Descriptor
//TSARM_RXDCBDA(vc)=0;
// OAM Receive Buffer Descriptor
//TSARM_RXMCBDA(vc) = 0;
// Traffic Scheduler - PCR
TSARM_PCR(vc) = 0;
// Traffic Scheduler - SCR
TSARM_SCR(vc) = 0;
// Traffic Scheduler - MBSTP
TSARM_MBSTP(vc) = 0;
atmCfgTable.openFlag[vc] = 0;
atmCfgTable.vpi[vc] = atmCfgTable.vci[vc] = 0;
atmCfgTable.vcc[vc] = NULL;
atmCfgTable.vcNumber--;
#ifdef CONFIG_VLAN_ATM
resetVlanVcc(vpi, vci);
#endif
#if defined(TCSUPPORT_CT)
#ifdef DYNAMIC_ALLOC_SKB
if(g_NoNeedFreeSKB != 1){
atmRxSkbFree(vc);
}
#endif
#endif
local_irq_disable();
atmTxDescrFree(vc, 1);
/*Reset the hardware tx descriptor index*/
TSARM_VC_TX_BD_PRIORITY01(vc) = TSARM_VC_TX_BD_PRIORITY01(vc) ;
TSARM_VC_TX_BD_PRIORITY23(vc) = TSARM_VC_TX_BD_PRIORITY23(vc);
for(priority = 0; priority < ATM_TX_PRIORITY_MAX; priority ++){
atmTxVcFreeDescrp[priority][vc] = atmTxDescrPoolAddr[vc].pTxDescr[priority];
atmTxVcBusyDescrp[priority][vc] = atmTxDescrPoolAddr[vc].pTxDescr[priority];
}
local_irq_enable();
// workaround for abnormal irq report
for ( i = 0; i < ATM_VC_MAX; i++ ) {
if ( atmCfgTable.openFlag[i] == 1 ) {
TSARM_VCCR(10) =
VCCFGR_VPI(atmCfgTable.vpi[i]) | VCCFGR_VCI(atmCfgTable.vci[i]) |
VCCFGR_PORT(VCCFGR_ATM_PHY0) | VCCFGR_VALID;
break;
}
}
if (i == ATM_VC_MAX)
TSARM_VCCR(10) = VCCFGR_VPI(255) | VCCFGR_VCI(15) |
VCCFGR_PORT(VCCFGR_ATM_PHY0) | VCCFGR_VALID;
return 0;
}
/*______________________________________________________________________________
** atmOamOpen
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
int
atmOamOpen(
void
)
{
TSARM_CCCR = VCCFGR_VPI(0) | VCCFGR_VCI(0) |
VCCFGR_PORT(VCCFGR_ATM_PHY0) | VCCFGR_VALID;
TSARM_IRQMCC = 0x202;
TSARM_RXMBCSR |= 1 << 16;
return 0;
}
void atmTxPriDescrFree(uint8 vc, uint8 priority, uint8 free_any){
volatile atmTxDescr_t *atmTxBusyDescrp;
uint16 i;
uint16 len = atmTxPriVcCnt[priority][vc];
for (i = 0; i < len; i++) {
atmTxBusyDescrp = atmTxVcBusyDescrp[priority][vc];
if ((!(atmTxBusyDescrp->tdes0 & TSARM_TX_DESCR_VALID)) || free_any) {
if ( atmTxBusyDescrp->skb ) {
/* Free descr */
#ifdef SAR_VERIFY
if (free_any || test_flag) {
#else
if (free_any) {
#endif
dev_kfree_skb_any(atmTxBusyDescrp->skb);
} else {
if (ATM_SKB(atmTxBusyDescrp->skb)->vcc->pop) {
ATM_SKB(atmTxBusyDescrp->skb)->vcc->pop (ATM_SKB(atmTxBusyDescrp->skb)->vcc, atmTxBusyDescrp->skb);
} else {
dev_kfree_skb_any(atmTxBusyDescrp->skb);
}
}
atmTxBusyDescrp->tdes1 = 0x0;
if(free_any)
atmTxBusyDescrp->tdes0 &= ~TSARM_TX_DESCR_VALID;
atmTxBusyDescrp->skb = NULL;
if(atmTxBusyDescrp->tdes0 & TSARM_TX_DESCR_EOR){
atmTxVcBusyDescrp[priority][vc] = atmTxDescrPoolAddr[vc].pTxDescr[priority];
}else{
atmTxVcBusyDescrp[priority][vc]++;
}
atmTxPriVcCnt[priority][vc]--;
atmTxVcCnt[vc]--;
atmTxVcTotalCnt--;
}
} else {
break;
}
}
}
/*______________________________________________________________________________
** atmTxDescrFree
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
void
atmTxDescrFree(
uint8 vc, uint8 free_any
)
{
uint8 priority;
for(priority = 0; priority < ATM_TX_PRIORITY_MAX; priority++){
atmTxPriDescrFree(vc, priority, free_any);
}
}
/*______________________________________________________________________________
** atmIsr
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
#ifdef SAR_POLLING
static struct task_struct *polling_task = 0;
int isrPollingFlag = 0;
extern int tcSarIsrPollingMode;
#endif
irqreturn_t
atmIsr(
int irq , void *dev
)
{
register uint32 atmRxIrqReport;
uint32 atmRxIrqHeadOffset;
uint8 vc;
register atmRxDescr_t *atmRxDescrp;
atmRxCcDescr_t *atmRxCcDescrp;
struct sk_buff *skb;
atmRxDescrPool_t *atmRxDescrVcPoolp;
atmRxCcDescrPool_t *atmRxCcDescrPoolp;
uint32 len=0;
uint32 atmIrqEventCheckTime = 0;
ledTurnOn(LED_DSL_ACT_STATUS);
atmIrqEventCheckTime = 0;
ISREVENTREREAD:
//loop while there are irq entries on irq queue
while ((TSARM_IRQH & 0x00fff000) >> 12) {
//get the irq offset value
atmRxIrqHeadOffset = TSARM_IRQH & 0x00000fff;
//get the irq entry content
atmRxIrqReport = *(volatile uint32 *) PHYSICAL_TO_K1(TSARM_IRQBA + (atmRxIrqHeadOffset << 2));
vc = LIRQ_GET_VC_NO(atmRxIrqReport);
/* mask the vc field out */
atmRxIrqReport = atmRxIrqReport & 0xfe0fffff;
if(irqrereadflag){
if(atmRxIrqReport == 0)
{
atmIrqEventCheckTime++;
if(irqrereadmax < atmIrqEventCheckTime)
{
irqrereadmax = atmIrqEventCheckTime;
}
if(atmIrqEventCheckTime >= 1000)
{
dbg_pline_1("\n\natmIrqEventCheckTime >= 1000, error case! need software reset atm sar\n\n");
goto ISRPROCESSCONTINUE;
}
goto ISREVENTREREAD;
}
else
{
if(atmIrqEventCheckTime)
{
irqrereadtime++;
}
}
}
ISRPROCESSCONTINUE:
#ifdef SAR_VERIFY
dumpIRQEvent(vc, atmRxIrqReport);
#endif
/* If the irq queue is full, we must to reset the sar modules.
* This bit will be also inclued another event,so if the we
* must to handle this event at first,system won't to ignore the
* irq queue full event.
*/
if (atmRxIrqReport & LIRQ_IRQ_Q_FULL) {
atmReset();
atm_p->MIB_II.irqFull++;
return IRQ_HANDLED;
}
//the successful receive user data done event will be handled first, the others handled below.
/*When descriptor ring is full, sar will receive (LIRQ_RX_U_DONE | LIRQ_RX_U_BD_OV) interrupt.
shnwind 20101005*/
else if (atmRxIrqReport == LIRQ_RX_U_DONE || (atmRxIrqReport == (LIRQ_RX_U_DONE |LIRQ_RX_U_BD_OV))) {
atmRxDescrp = atmRxVcDescrp[vc];
skb = atmRxDescrp->skb;
if (!(atmRxDescrp->rdes0 & TSARM_RX_DESCR_VALID)) {
len = (uint32) (atmRxDescrp->rdes1 & 0xffff);
#ifdef SAR_VERIFY
skb=atmDataLpbkHandler(atmRxDescrp, skb, vc);
#else
if (len && (len <= atmRxBufferSize)) {
skb = atmAal5DataInd(skb, vc, len);
}
#endif
} else {
atm_p->MIB_II.inDiscards++;
atm_p->MIB_II.inBufErr++;
}
atmRxDescrp->rdes1 = atmRxBufferSize << 16; /* Buffer size */
atmRxDescrp->rdes2 = K1_TO_PHYSICAL(skb->data);
atmRxDescrp->skb = skb;
atmRxDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxDescrp->rdes0 & TSARM_RX_DESCR_EOR){
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
atmRxVcDescrp[vc] = atmRxDescrVcPoolp->rxDescrPool;
}else{
atmRxVcDescrp[vc]++;
}
// } else if (atmRxIrqReport & LIRQ_TX_U_DONE) {
#if defined(CONFIG_NET_SCHED) || defined(TCSUPPORT_CT_SWQOS) /*Rodney_20091115*/
} else if (atmRxIrqReport & LIRQ_TX_U_DONE) {
#if defined(TCSUPPORT_CT_SWQOS)
if (sw_PKTQOS_CLEAR_STOP)
sw_PKTQOS_CLEAR_STOP();
#else
if((qos_qdisc_mode == QOS_QDISC_RED) || (qos_qdisc_mode == QOS_QDISC_WRED)){
if(atmCfgTable.vcc[vc]->_dev != NULL)
netif_wake_queue(atmCfgTable.vcc[vc]->_dev);
}
atmTxDescrFree(vc,0);
#endif
#endif
} else if (atmRxIrqReport & LIRQ_RX_U_BD_OV) {
if( vc < 10 ) {
#if 0 /*When overflow happen, sar will not receive any packet.
We should not drop here. shnwind 20101005*/
atmRxDescrp = atmRxVcDescrp[vc];
if (!(atmRxDescrp->rdes0 & TSARM_RX_DESCR_VALID)) {
atm_p->MIB_II.inDiscards++;
atm_p->MIB_II.inBufErr++;
skb = atmRxDescrp->skb;
atmRxDescrp->rdes1 = 1776 << 16; /* Buffer size */
atmRxDescrp->rdes2 = K1_TO_PHYSICAL(skb->data);
atmRxDescrp->skb = skb;
atmRxDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxDescrp->rdes0 & TSARM_RX_DESCR_EOR){
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
atmRxVcDescrp[vc] = atmRxDescrVcPoolp->rxDescrPool;
}else{
atmRxVcDescrp[vc]++;
}
}
#endif
TSARM_RXDBCSR |= 1 << vc;
atm_p->MIB_II.inDiscards++;
atm_p->MIB_II.inBufDescrOverflow++;
} else {
atmIrqStSaved(atmRxIrqReport, vc);
atm_p->MIB_II.inCcUBDOV++;
atmReset();
return IRQ_HANDLED;
}
} else if ((atmRxIrqReport & LIRQ_RX_CRC32E) ||
(atmRxIrqReport & LIRQ_RX_U_BOV) ||
(atmRxIrqReport & LIRQ_RX_MAXLENE) ||
(atmRxIrqReport & LIRQ_RX_LENE)) {
// The VC should be leass than 10, but we can get the VC=10.
// workaround the abnormal situation. // Jason_20060105
if( vc < 10 ) {
atmRxDescrp = atmRxVcDescrp[vc];
atm_p->MIB_II.inDiscards++;
if (atmRxIrqReport & LIRQ_RX_CRC32E){
atm_p->MIB_II.inCrcErr++;
#ifdef CMD_API
pvc_stats[vc].crc_errs++;
#endif
}
else if (atmRxIrqReport & LIRQ_RX_U_BOV)
atm_p->MIB_II.inBufOverflow++;
else if (atmRxIrqReport & LIRQ_RX_MAXLENE){
atm_p->MIB_II.inBufMaxLenErr++;
#ifdef CMD_API
pvc_stats[vc].oversized_sdus++;
#endif
}
else if (atmRxIrqReport & LIRQ_RX_LENE){
atm_p->MIB_II.inBufLenErr++;
#ifdef CMD_API
pvc_stats[vc].len_errs++;
#endif
}
skb = atmRxDescrp->skb;
atmRxDescrp->rdes1 = atmRxBufferSize << 16; /* Buffer size */
atmRxDescrp->rdes2 = K1_TO_PHYSICAL(skb->data);
atmRxDescrp->skb = skb;
atmRxDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxDescrp->rdes0 & TSARM_RX_DESCR_EOR){
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
atmRxVcDescrp[vc] = atmRxDescrVcPoolp->rxDescrPool;
}else{
atmRxVcDescrp[vc]++;
}
} else {
atmIrqStSaved(atmRxIrqReport, vc);
atm_p->MIB_II.inCcUDoneErr++;
atmReset();
return IRQ_HANDLED;
}
#if 0 /*Move to handle the irq queue full envet to top.*/
} else if (atmRxIrqReport & LIRQ_IRQ_Q_FULL) {
atmReset();
return IRQ_HANDLED;
#endif
} else if (atmRxIrqReport & LIRQ_RX_M_BD_OV) {
if (vc == 0x0a) { /* CC ...for L2-> vc = 0x0a means oam or cc cell.*/
atmRxCcDescrp = atmRxCcBusyDescrp;
atmRxCcDescrp->rdes1 = (96 << 16);
atmRxCcDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_EOR){
#ifdef DYNAMIC_ALLOC_DMA_BUF
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(atmRxCcDescrPool);
#else
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(&atmRxCcDescrPool);
#endif
atmRxCcBusyDescrp = atmRxCcDescrPoolp->rxCcDescrPool;
}else{
atmRxCcBusyDescrp++;
}
TSARM_RXMBCSR |= 1 << 16;
atm_p->MIB_II.inCcBufDescrOverflow++;
} else { /* OAM ...for L2-> vc = 0x0a means oam or cc cell. */
atmRxCcDescrp = atmRxOamBusyDescrp[vc];
atmRxCcDescrp->rdes1 = (48 << 16);
atmRxCcDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_EOR){
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
atmRxOamBusyDescrp[vc] = atmRxDescrVcPoolp->rxOamDescrPool;
}else{
atmRxOamBusyDescrp[vc]++;
}
TSARM_RXMBCSR |= 1 << vc;
atm_p->MIB_II.inMngBufDescrOverflow++;
}
} else if (atmRxIrqReport & LIRQ_RX_CRC10E) {
if (vc == 0x0a) { /* CC ...for L2-> vc = 0x0a means oam or cc cell.*/
atmRxCcDescrp = atmRxCcBusyDescrp;
#ifdef L2_AUTOPVC
if (g_manageFlag & VC_HUNT_FLAG_MANG_START){
RawCcCellRecv((uint8 *)CACHE_TO_NONCACHE(PHYSICAL_TO_K1(atmRxCcDescrp->rdes2)));
}
#endif
atmRxCcDescrp->rdes1 = (96 << 16);
atmRxCcDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_EOR){
#ifdef DYNAMIC_ALLOC_DMA_BUF
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(atmRxCcDescrPool);
#else
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(&atmRxCcDescrPool);
#endif
atmRxCcBusyDescrp = atmRxCcDescrPoolp->rxCcDescrPool;
}else{
atmRxCcBusyDescrp++;
}
} else { /* OAM ...for L2-> vc = 0x0a means oam or cc cell. */
atmRxCcDescrp = atmRxOamBusyDescrp[vc];
atmRxCcDescrp->rdes1 = (48 << 16);
atmRxCcDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_EOR){
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
atmRxOamBusyDescrp[vc] = atmRxDescrVcPoolp->rxOamDescrPool;
}else{
atmRxOamBusyDescrp[vc]++;
}
}
atm_p->MIB_II.inCrc10Err++;
} else if (atmRxIrqReport & LIRQ_RX_M_DONE) {
if (vc == 0x0a) { /* CC ...for L2-> vc = 0x0a means oam or cc cell. */
atmRxCcDescrp = atmRxCcBusyDescrp;
if ( !(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_VALID) ) {
#ifndef SAR_VERIFY
atmCcHandler((uint8 *)PHYSICAL_TO_K1(atmRxCcDescrp->rdes2));
#else
atmCcLpbkHandler((uint8 *)PHYSICAL_TO_K1(atmRxCcDescrp->rdes2));
#endif
}
atmRxCcDescrp->rdes1 = (96 << 16);
atmRxCcDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_EOR){
#ifdef DYNAMIC_ALLOC_DMA_BUF
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(atmRxCcDescrPool);
#else
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(&atmRxCcDescrPool);
#endif
atmRxCcBusyDescrp = atmRxCcDescrPoolp->rxCcDescrPool;
}else{
atmRxCcBusyDescrp++;
}
} else { /* OAM ...for L2-> vc = 0x0a means oam or cc cell. */
atmRxCcDescrp = atmRxOamBusyDescrp[vc];
if ( !(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_VALID) ) {
#ifndef SAR_VERIFY
atmOamHandler(atmRxCcDescrp, vc);
#else
atmOamLpbkHandler(atmRxCcDescrp, vc);
#endif
}
atmRxCcDescrp->rdes1 = (48 << 16);
atmRxCcDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_EOR){
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
atmRxOamBusyDescrp[vc] = atmRxDescrVcPoolp->rxOamDescrPool;
}else{
atmRxOamBusyDescrp[vc]++;
}
}
} else if (atmRxIrqReport == LIRQ_RX_INACT_VC) {
/* inactive cell, just need to remove irq */
if (sarDebugFlag)
dbg_plinel_1("\r\n atmRxIrqReport=", atmRxIrqReport);
}
else if(atmRxIrqReport & LIRQ_RX_M_BOV){
if (vc == 0x0a) { /* CC ...for L2-> vc = 0x0a means oam or cc cell.*/
atmRxCcDescrp = atmRxCcBusyDescrp;
atmRxCcDescrp->rdes1 = (96 << 16);
atmRxCcDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_EOR){
#ifdef DYNAMIC_ALLOC_DMA_BUF
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(atmRxCcDescrPool);
#else
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(&atmRxCcDescrPool);
#endif
atmRxCcBusyDescrp = atmRxCcDescrPoolp->rxCcDescrPool;
}else{
atmRxCcBusyDescrp++;
}
atm_p->MIB_II.inCcBufOverflow++;
} else { /* OAM ...for L2-> vc = 0x0a means oam or cc cell. */
atmRxCcDescrp = atmRxOamBusyDescrp[vc];
atmRxCcDescrp->rdes1 = (48 << 16);
atmRxCcDescrp->rdes0 |= TSARM_RX_DESCR_VALID;
if(atmRxCcDescrp->rdes0 & TSARM_RX_DESCR_EOR){
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
atmRxOamBusyDescrp[vc] = atmRxDescrVcPoolp->rxOamDescrPool;
}else{
atmRxOamBusyDescrp[vc]++;
}
atm_p->MIB_II.inMngBufOverflow++;
}
}
#ifdef SAR_VERIFY
else if(atmRxIrqReport & LIRQ_TX_M_DONE){
}
else if(atmRxIrqReport & LIRQ_TX_U_DONE){
}
else if(atmRxIrqReport & LIRQ_TX_SW_DIS){
}
#endif
else {
atmIrqStSaved(atmRxIrqReport, vc);
dbg_plinel_1("\r\n Invalid atmRxIrqReport=", atmRxIrqReport);
dbg_plineb_1(" vc=", vc);
if (sarDebugFlag)
dbg_plinel_1("\r\n atmRxIrqReport=", atmRxIrqReport);
atmReset();
return IRQ_HANDLED;
}
if(irqrereadflag)
{
//clean SDRAM value for check isr event valid
*(volatile uint32 *) PHYSICAL_TO_K1(TSARM_IRQBA + (atmRxIrqHeadOffset << 2)) = 0;
}
TSARM_IRQC = 1;
}
return IRQ_HANDLED;
}
#ifdef SAR_POLLING
#include <linux/kthread.h>
wait_queue_head_t isrPollingQueue;
irqreturn_t
fakeAtmIsr(
int irq , void *dev
)
{
atmIsr( 0, 0);
if(tcSarIsrPollingMode){
//mask sar interrupt
TSARM_GFR &= ~(GFR_GIRQEN);
isrPollingFlag = 1;
//printk("enter sar polling mode\n");
wake_up_interruptible( &isrPollingQueue);
}
return IRQ_HANDLED;
}
static int isrPollingThread(void* dummy){
while(1){
wait_event_interruptible( isrPollingQueue, isrPollingFlag != 0);
isrPollingFlag = 0;
while(1){
atmIsr( 0, 0);
if(!tcSarIsrPollingMode){
printk("leave sar polling mode\n");
break;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ/100);
}
//enable sar interrupt
TSARM_GFR |= GFR_GIRQEN;
}
return 0;
}
#endif
/*______________________________________________________________________________
** atmRegDump
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
int
atmRegDump(
char *buf,
uint8 vc
)
{
uint16 index=0;
index += sprintf( buf+index, "\n\r***** ATM SAR Module: Common Register Dump *****");
index += sprintf( buf+index, "\n\rReset&Identify reg = 0x%08lx, General CFG reg = 0x%08lx",
TSARM_RAI, TSARM_GFR);
index += sprintf( buf+index, "\n\rTraffic Sched. TB reg= 0x%08lx, RX Max Length reg = 0x%08lx",
TSARM_TSTBR, TSARM_RMPLR);
index += sprintf( buf+index, "\n\rP23 Data c /s reg = 0x%08lx, TX Traffic Sched. LR reg= 0x%08lx",
TSARM_TXDBCSR_P23, TSARM_TXSLRC);
index += sprintf( buf+index, "\n\rP01 Data c /s reg = 0x%08lx, TX OAM ctrl/stat reg = 0x%08lx",
TSARM_TXDBCSR_P01, TSARM_TXMBCSR);
index += sprintf( buf+index, "\n\rRX Data ctrl/stat reg= 0x%08lx, RX OAM ctrl/stat reg = 0x%08lx",
TSARM_RXDBCSR, TSARM_RXMBCSR);
index += sprintf( buf+index, "\n\rLast IRQ Status reg = 0x%08lx, IRQ Queue Base reg = 0x%08lx",
TSARM_LIRQ, TSARM_IRQBA);
index += sprintf( buf+index, "\n\rIRQ Queue Entry len = 0x%08lx, IRQ Head ind. reg = 0x%08lx",
TSARM_IRQLEN, TSARM_IRQH);
index += sprintf( buf+index, "\n\r");
index += sprintf( buf+index, "\n\r***** ATM SAR Module: VC(%02d) Register Dump *****\n\r", vc);
index += sprintf( buf+index, "\n\rVC IRQ Mask register = 0x%08lx, VC Configuration reg = 0x%08lx",
TSARM_IRQM(vc), TSARM_VCCR(vc));
index += sprintf( buf+index, "\n\rTX Data Current descr= 0x%08lx, TX OAM Current descr = 0x%08lx",
TSARM_TXDCBDA(vc), TSARM_TXMCBDA(vc));
index += sprintf( buf+index, "\n\rRX Data Current descr= 0x%08lx, RX OAM Current descr = 0x%08lx",
TSARM_RXDCBDA(vc), TSARM_RXMCBDA(vc));
index += sprintf( buf+index, "\n\rTX Traffic PCR = 0x%08lx, TX Traffic SCR = 0x%08lx",
TSARM_PCR(vc), TSARM_SCR(vc));
index += sprintf( buf+index, "\n\rTX Traffic MBS/Type = 0x%08lx",
TSARM_MBSTP(vc));
index += sprintf( buf+index, "\n\rTX Total Data Count = 0x%08lx, RX Total Data Count = 0x%08lx",
TSARM_TDCNT(vc), TSARM_RDCNT(vc));
index += sprintf( buf+index, "\n\rVC IRQ CC Mask reg = 0x%08lx, VC CC Config reg = 0x%08lx",
TSARM_IRQMCC, TSARM_CCCR);
index += sprintf( buf+index, "\n\rTX CC Current descr = 0x%08lx, RX CC Current descr = 0x%08lx",
TSARM_CC_TX_BD_BASE, TSARM_CC_RX_BD_BASE);
index += sprintf( buf+index, "\n\rTX CC Total Count = 0x%08lx, RX CC Total Count = 0x%08lx",
TSARM_TDCNTCC, TSARM_RDCNTCC);
index += sprintf( buf+index, "\n\rRX Mis-insert Cnt. = 0x%08lx, TX AAL5 Count = 0x%08x",
TSARM_MISCNT, atmTxVcCnt[vc]);
index += sprintf( buf+index, "\n\r");
return index;
}
/*______________________________________________________________________________
** atmCounterDisplay
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
void
atmCounterDisplay(
void
)
{
int index = 0;
//shnwind modify because 800 bytes is not enough. 20100608
//char stateATM[800];
char *stateATM;
stateATM = (char *)kzalloc(2048, GFP_KERNEL);
index = getATMState( stateATM );
printf("%s", stateATM);
kfree(stateATM);
}
int
getATMState(char *stateATM)
{
uint16 index=0;
index += sprintf( stateATM+index, "\n[ SAR Counters ]\n");
index += sprintf( stateATM+index, "inPkts = 0x%08lx, inDiscards = 0x%08lx\n",
atm_p->MIB_II.inPkts, atm_p->MIB_II.inDiscards);
index += sprintf( stateATM+index, "inF4Pkts = 0x%08lx, inF5Pkts = 0x%08lx\n",
atm_p->MIB_II.inF4Pkts, atm_p->MIB_II.inF5Pkts);
index += sprintf( stateATM+index, "inDMATaskEnd = 0x%08lx, inBufErr = 0x%08lx\n",
atm_p->MIB_II.inDMATaskEnd, atm_p->MIB_II.inBufErr);
index += sprintf( stateATM+index, "inCrcErr = 0x%08lx\n", atm_p->MIB_II.inCrcErr);
index += sprintf( stateATM+index, "inBufOverflow = 0x%08lx, inBufMaxLenErr = 0x%08lx\n",
atm_p->MIB_II.inBufOverflow, atm_p->MIB_II.inBufMaxLenErr);
index += sprintf( stateATM+index, "inBufLenErr = 0x%08lx, inBufDescrOV = 0x%08lx\n",
atm_p->MIB_II.inBufLenErr, atm_p->MIB_II.inBufDescrOverflow);
index += sprintf( stateATM+index, "outPkts = 0x%08lx, outDiscards = 0x%08lx\n",
atm_p->MIB_II.outPkts, atm_p->MIB_II.outDiscards);
index += sprintf( stateATM+index, "outF4Pkts = 0x%08lx, outF5Pkts = 0x%08lx\n",
atm_p->MIB_II.outF4Pkts, atm_p->MIB_II.outF5Pkts);
index += sprintf( stateATM+index, "softRstCnt = 0x%08lx\n", atm_p->MIB_II.softRstCnt);
index += sprintf( stateATM+index, "inCrc10Err = 0x%08lx\n", atm_p->MIB_II.inCrc10Err);
index += sprintf( stateATM+index, "inMngBufOV = 0x%08lx, inCcBufOV = 0x%08lx\n",
atm_p->MIB_II.inMngBufOverflow, atm_p->MIB_II.inCcBufOverflow);
index += sprintf( stateATM+index, "inMngBufDescrOV= 0x%08lx, inCcBufDescrOV = 0x%08lx\n",
atm_p->MIB_II.inMngBufDescrOverflow, atm_p->MIB_II.inCcBufDescrOverflow);
index += sprintf( stateATM+index, "inMpoaErr = 0x%08lx, inVlanHit = 0x%08lx\n",
atm_p->MIB_II.inMpoaErr, atm_p->MIB_II.inVlanHit);
index += sprintf( stateATM+index, "inCcUDoneErr = 0x%08lx, inCcUBDOV = 0x%08lx\n",
atm_p->MIB_II.inCcUDoneErr, atm_p->MIB_II.inCcUBDOV);
index += sprintf( stateATM+index, "inBytes = 0x%08lx, outBytes = 0x%08lx\n",
atm_p->MIB_II.inBytes, atm_p->MIB_II.outBytes);//yzwang_20091125
index += sprintf( stateATM+index, "irqFull = 0x%08lx\n",
atm_p->MIB_II.irqFull);
if(irqrereadflag){
index += sprintf( stateATM+index, "irqrereadmax = %u, irqrereadtime = %u\n",irqrereadmax, irqrereadtime);
}
return index;
}
/*______________________________________________________________________________
** atmCounterClear
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
void
atmCounterClear(
void
)
{
memset((char *)&(atm_p->MIB_II), 0, sizeof(atmMIB_II_t));
}
/*______________________________________________________________________________
** atmPktsClear
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
void
atmPktsClear(
void
)
{ atm_p->MIB_II.inPkts = 0;
atm_p->MIB_II.outPkts = 0;
}
int
getATMQueState(char *stateATM)
{
uint16 index=0;
uint8 vc;
int i;
index += sprintf( stateATM+index, "ATM SAR Queue Information:\n\n");
for (vc = 0; vc < ATM_VC_MAX; vc++) {
index += sprintf( stateATM+index,
"VC%d %d/%d: open=%d txVcCnt=%d P0=%d/%d, P1=%d/%d, P2=%d/%d, P3=%d/%d\n",
vc, atmCfgTable.vpi[vc], atmCfgTable.vci[vc], atmCfgTable.openFlag[vc],
atmTxVcCnt[vc],
atmTxPriVcCnt[0][vc], atmTxQueSize[0],
atmTxPriVcCnt[1][vc], atmTxQueSize[1],
atmTxPriVcCnt[2][vc], atmTxQueSize[2],
atmTxPriVcCnt[3][vc], atmTxQueSize[3]);
}
index += sprintf( stateATM+index, "\nSaved IRQ st: index=%lx\n", savedAtmIrqIndex);
for (i = 0; i < SAVED_IRQ_MAX_ENTRY; i++) {
if ((i & 0x3) == 0)
index += sprintf( stateATM+index, "\n");
index += sprintf( stateATM+index, "%08lx:%02x ",
savedAtmIrqSt[i].irqst, savedAtmIrqSt[i].vc);
}
index += sprintf( stateATM+index, "\n");
return index;
}
int
getATMVcTxDescrDump(char *stateATM, uint8 vc)
{
uint16 index=0;
int i;
atmTxDescr_t *atmTxDescrp;
atmTxCcDescr_t *atmTxOamDescrp;
uint8 priority;
index += sprintf( stateATM+index, "VC=%d\n", vc);
for(priority = 0; priority < ATM_TX_PRIORITY_MAX; priority++){
index += sprintf( stateATM+index, " --- Tx Priority %d ---\n", priority);
index += sprintf( stateATM+index, " atmTxVcBusyDescrp = %08lx\n", (uint32) atmTxVcBusyDescrp[priority][vc]);
index += sprintf( stateATM+index, " atmTxVcFreeDescrp = %08lx\n", (uint32) atmTxVcFreeDescrp[priority][vc]);
atmTxDescrp = atmTxDescrPoolAddr[vc].pTxDescr[priority];
for (i=0; i < atmTxQueSize[priority]; i++, atmTxDescrp++){
index += sprintf( stateATM+index, " --- i=%d ", i);
index += sprintf( stateATM+index, " atmTxDescrp = %08lx --- \n", (uint32)atmTxDescrp);
index += sprintf( stateATM+index, " ->tdes0 = %08lx\n", (uint32) atmTxDescrp->tdes0);
index += sprintf( stateATM+index, " ->tdes1 = %08lx\n", (uint32) atmTxDescrp->tdes1);
index += sprintf( stateATM+index, " ->tdes2 = %08lx\n", (uint32) atmTxDescrp->tdes2);
index += sprintf( stateATM+index, " ->tdes3 = %08lx\n", (uint32) atmTxDescrp->tdes3);
index += sprintf( stateATM+index, " ->skb = %08lx\n", (uint32) atmTxDescrp->skb);
}
}
// management
index += sprintf( stateATM+index, " --- Tx Oam descriptor dump ---\n");
index += sprintf( stateATM+index, " atmTxOamFreeDescrp = %08lx\n", (uint32) atmTxOamFreeDescrp[vc]);
atmTxOamDescrp = atmTxDescrPoolAddr[vc].pTxOamDescr;
for (i=0; i<ATM_TX_CC_DESCR_NUMMAX; i++, atmTxOamDescrp++){
index += sprintf( stateATM+index, " --- i=%d atmTxOamDescrp = %08lx --- \n", i, (uint32)atmTxOamDescrp);
index += sprintf( stateATM+index, " ->tdes0 = %08lx\n", (uint32) atmTxOamDescrp->tdes0);
index += sprintf( stateATM+index, " ->tdes1 = %08lx\n", (uint32) atmTxOamDescrp->tdes1);
index += sprintf( stateATM+index, " ->tdes2 = %08lx\n", (uint32) atmTxOamDescrp->tdes2);
index += sprintf( stateATM+index, " ->tdes3 = %08lx\n", (uint32) atmTxOamDescrp->tdes3);
}
return index;
}
int
getATMVcRxDescrDump(char *stateATM, uint8 vc)
{
uint16 index=0;
int i;
atmRxDescrPool_t *atmRxDescrVcPoolp;
atmRxDescr_t *atmRxDataDescrp;
atmRxCcDescr_t *atmRxMngDescrp;
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
index += sprintf( stateATM+index, " atmRxDescrPool = %08lx\n", (uint32)atmRxDescrPool);
index += sprintf( stateATM+index, " atmRxDataDescrVcPoolp = %08lx\n", (uint32)atmRxDescrVcPoolp);
// data
index += sprintf( stateATM+index, " --- Rx Data Descriptor dump ---");
atmRxDataDescrp = atmRxDescrVcPoolp->rxDescrPool;
for (i=0; i<ATM_RX_VC_DESCR_NUMMAX; i++, atmRxDataDescrp++){
index += sprintf( stateATM+index, " --- i=%d atmRxDataDescrp = %08lx ---\n", i, (uint32)atmRxDataDescrp);
index += sprintf( stateATM+index, " ->rdes0 = %08lx\n", (uint32) atmRxDataDescrp->rdes0);
index += sprintf( stateATM+index, " ->rdes1 = %08lx\n", (uint32) atmRxDataDescrp->rdes1);
index += sprintf( stateATM+index, " ->rdes2 = %08lx\n", (uint32) atmRxDataDescrp->rdes2);
index += sprintf( stateATM+index, " ->rdes3 = %08lx\n", (uint32) atmRxDataDescrp->rdes3);
index += sprintf( stateATM+index, " ->skb = %08lx\n", (uint32) atmRxDataDescrp->skb);
}
// management
index += sprintf( stateATM+index, " --- Rx Mng Descriptor dump ---\n");
atmRxMngDescrp = atmRxDescrVcPoolp->rxOamDescrPool;
for (i=0; i<ATM_RX_CC_DESCR_NUMMAX; i++, atmRxMngDescrp++){
index += sprintf( stateATM+index, " --- i=%d atmRxMngDescrp = %08lx ---\n", i, (uint32)atmRxMngDescrp);
index += sprintf( stateATM+index, " ->rdes0 = %08lx\n", atmRxMngDescrp->rdes0);
index += sprintf( stateATM+index, " ->rdes1 = %08lx\n", atmRxMngDescrp->rdes1);
index += sprintf( stateATM+index, " ->rdes2 = %08lx\n", atmRxMngDescrp->rdes2);
index += sprintf( stateATM+index, " ->rdes3 = %08lx\n", atmRxMngDescrp->rdes3);
}
return index;
}
void atmIrqStSaved(uint32 irqst, uint8 vc)
{
savedAtmIrqSt[savedAtmIrqIndex].irqst = irqst;
savedAtmIrqSt[savedAtmIrqIndex].vc = vc;
savedAtmIrqIndex++;
if (savedAtmIrqIndex >= SAVED_IRQ_MAX_ENTRY)
savedAtmIrqIndex = 0;
}
int
atmDebugOn(
void
)
{
sarDebugFlag = 1;
printf("debug = on\n");
return 0;
}
int
atmDebugOff(
void
)
{
sarDebugFlag = 0;
printf("debug = off\n");
return 0;
}
#ifdef CMD_API
volatile uint8 recved;
#endif
/*______________________________________________________________________________
** atmCcHandler
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
uint8
atmCcHandler(
uint8 *cellp
)
{
atmOamCell_t *oamCellp;
uint8 ret = 0;
uint8 isF4 = 0;
uint32 i;
oamCellp = (atmOamCell_t *)(CACHE_TO_NONCACHE(cellp));
if (sarDebugFlag) {
dbg_plinew_1("\n\r gfc=", oamCellp->gfc);
dbg_plinew_1("\n\r vpi=", oamCellp->vpi);
dbg_plinew_1("\n\r vci=", oamCellp->vci);
dbg_plinew_1("\n\r pti=", oamCellp->pti);
dbg_plinew_1("\n\r clp=", oamCellp->clp);
dbg_plinew_1("\n\r cellType=", oamCellp->oamCellType);
dbg_plinew_1("\n\r funcType=", oamCellp->oamFuncType);
dbg_pline_1("\n\r payload=");
for (i = 0; i < 45; i++) {
if ((i & 0x7) == 0)
dbg_pline_1("\n\r");
dbg_plineb_1(" ", oamCellp->payload[i]);
}
}
if ( oamCellp->oamCellType != OAM_FAULT_MANAGEMENT ) {
ret = 1;
}
if ((oamCellp->vci == 3) || (oamCellp->vci == 4)) {
isF4 = 1;
#ifdef CMD_API
recved = 1;
#endif
atm_p->MIB_II.inF4Pkts++;
}
switch ( oamCellp->oamFuncType ) {
case OAM_LOOPBACK:
/* Loopback Indication field:
** 1 - source point, 0 - loopback point
*/
if ( oamCellp->payload[0] == 0x00 ) {
ret = 1;
}
else {
oamCellp->payload[0] = 0x00;
}
break;
case OAM_AIS:
oamCellp->oamFuncType = OAM_RDI;
break;
default:
ret = 1;
break;
}
if ( !ret ) {
if(!atmCcDataReq((uint8 *)oamCellp)){
if(isF4){
atm_p->MIB_II.outF4Pkts++;
}
atm_p->MIB_II.outPkts++;
}
}
return ret;
}
/*______________________________________________________________________________
** atmOamHandler
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
uint8
atmOamHandler(
atmRxCcDescr_t *atmRxCcDescrp,
uint8 vc
)
{
atmOamCellPayload_t *oamCellPayloadp;
uint8 pti;
uint8 ret = 0;
uint8 isF4 = 0;
uint32 i;
oamCellPayloadp = (atmOamCellPayload_t *)(CACHE_TO_NONCACHE(PHYSICAL_TO_K1(atmRxCcDescrp->rdes2)));
pti = (atmRxCcDescrp->rdes1 & 0x70000000) >> 28;
if (sarDebugFlag) {
dbg_plinew_1("\n\r vpi=", atmCfgTable.vpi[vc]);
dbg_plinew_1("\n\r vci=", atmCfgTable.vci[vc]);
dbg_plinew_1("\n\r pti=", pti);
dbg_plinew_1("\n\r cellType=", oamCellPayloadp->oamCellType);
dbg_plinew_1("\n\r funcType=", oamCellPayloadp->oamFuncType);
dbg_pline_1("\n\r payload=");
for (i = 0; i < 45; i++) {
if ((i & 0x7) == 0)
dbg_pline_1("\n\r");
dbg_plineb_1(" ", oamCellPayloadp->payload[i]);
}
}
if ( oamCellPayloadp->oamCellType != OAM_FAULT_MANAGEMENT ) {
ret = 1;
}
if ((pti == 4) || (pti == 5)) {
isF4 = 0;
#ifdef CMD_API
recved = 1;
#endif
atm_p->MIB_II.inF5Pkts++;
//add by brian
#ifdef CWMP
if(cwmpflag)
{
g_f5loopback_rxtime = jiffies;
cwmpSavedInF5Pkts++;
}
#endif
}
switch ( oamCellPayloadp->oamFuncType ) {
case OAM_LOOPBACK:
/* Loopback Indication field:
** 1 - source point, 0 - loopback point
*/
#ifdef L2_AUTOPVC
if (g_manageFlag & VC_HUNT_FLAG_MANG_START){
vcPoolProbeVcPktRx(atmCfgTable.vpi[vc], atmCfgTable.vci[vc]);
}
#endif
if ( oamCellPayloadp->payload[0] == 0x00 ) {
ret = 1;
}
else {
oamCellPayloadp->payload[0] = 0x00;
}
break;
case OAM_AIS:
oamCellPayloadp->oamFuncType = OAM_RDI;
break;
default:
ret = 1;
break;
}
if ( !ret ) {
if(!atmOamDataReq((uint8 *)oamCellPayloadp, pti, vc)) {
if(!isF4){
atm_p->MIB_II.outF5Pkts++;
}
atm_p->MIB_II.outPkts++;
}
}
return ret;
}
/*______________________________________________________________________________
** atmVcNumberGet
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
uint8
atmVcNumberGet(
uint8 vpi,
uint16 vci
)
{
uint8 vc;
for ( vc = 0; vc < ATM_VC_MAX; vc++ ) {
if ( atmCfgTable.openFlag[vc] &&
(atmCfgTable.vpi[vc] == vpi) &&
(atmCfgTable.vci[vc] == vci) ) {
return vc;
}
}
return ATM_DUMMY_VC;
}
/*______________________________________________________________________________
** atmAal5DataInd
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
struct sk_buff *
atmAal5DataInd(
struct sk_buff *skb,
uint8 vc,
uint32 len
)
{
struct sk_buff *freeSkb = NULL;
struct atm_vcc *vcc;
atm_p->MIB_II.inPkts++;
atm_p->MIB_II.inBytes += len;//yzwang_20091125
freeSkb = skbmgr_dev_alloc_skb2k();
if ( freeSkb ) {
dma_cache_inv((unsigned long)freeSkb->data, RX_BUF_LEN);
vcc = atmCfgTable.vcc[vc];
if (unlikely(vcc == NULL)) {
dev_kfree_skb_any(skb);
atm_p->MIB_II.inDiscards++;
return freeSkb;
}
ATM_SKB(skb)->vcc = vcc;
//skb->stamp = vcc->timestamp = xtime;
//skb->stamp = xtime;
#ifdef L2_AUTOPVC
if (g_manageFlag & VC_HUNT_FLAG_MANG_START){
if (vcPoolProbeVcPktRx(atmCfgTable.vpi[vc], atmCfgTable.vci[vc])) {
dev_kfree_skb_any(skb);
return freeSkb;
}
}
#endif
skb_put(skb, len);
if (atm_charge(vcc, skb->truesize) == 0) {
dev_kfree_skb_any(skb);
atm_p->MIB_II.inDiscards++;
return freeSkb;
}
#ifdef WAN2LAN
/*****************xyzhu_nj_091104: wan2lan start*************/
if(masko_on_off){
struct sk_buff *skb2 = NULL;
//Check the skb headroom is enough or not. shnwind 20100121.
if(skb_headroom(skb) < TX_STAG_LEN){
skb2 = skb_copy_expand(skb, TX_STAG_LEN, skb_tailroom(skb) , GFP_ATOMIC);;
}else{
skb2 = skb_copy(skb,GFP_ATOMIC);
}
if(skb2 == NULL){
printk("wan2lan failure in sar rx direction for skb2 allocate failure.\n");
}
else{
if ( memcmp(skb2->data, RFC1483_B_LLC_HDR, 7) == 0 ){
skb_pull(skb2, sizeof(RFC1483_B_LLC_HDR));
}
else if ( memcmp(skb2->data, RFC1483_B_VC_HDR, sizeof(RFC1483_B_VC_HDR)) == 0 ){
skb_pull(skb2, sizeof(RFC1483_B_VC_HDR));
}
skb2->mark |= SKBUF_COPYTOLAN;
macSend(WAN2LAN_CH_ID,skb2);
}
}
/*****************xyzhu_nj_091104: wan2lan end****************/
#endif
/*pass it up to kernel networking layer and update stats*/
vcc->push(vcc, skb);
atomic_inc(&vcc->stats->rx);
}
else {
atm_p->MIB_II.inDiscards++;
freeSkb = skb;
}
return freeSkb;
}
/*______________________________________________________________________________
** atm
**
** descriptions:
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:
** call:
**____________________________________________________________________________*/
void
atmReset(
void
)
{
uint32 i;
unsigned long flags;
if (sarDebugFlag) {
dbg_pline_1("\r\n atmReset");
}
#if defined(TCSUPPORT_CT)
#ifdef DYNAMIC_ALLOC_SKB
g_NoNeedFreeSKB = 0;
#endif
#endif
#ifndef CONFIG_MIPS_TC3262
local_irq_save(flags);
#else
spin_lock_irqsave(&sarLock, flags);
#endif
// disable rx
TSARM_GFR = 0x0;
delay1ms(1);
atm_p->MIB_II.softRstCnt++;
while ((TSARM_IRQH & 0x00fff000) >> 12)
TSARM_IRQC = 1;
sarSoftReset = 1;
memcpy( (uint8*)&atmCfgBackup, (uint8*)&atmCfgTable ,sizeof(atmConfig_t)); /* backup control table */
for( i = 0; i < atmCfgBackup.vcNumber; i++ ){ /* open vc according to backup table*/
atmAal5VcClose( atmCfgTable.vpi[i], atmCfgTable.vci[i]);
}
sarDrvDescripReset(0);
memset( (uint8*)&atmCfgTable, 0, sizeof(atmConfig_t));
#ifdef DYNAMIC_ALLOC_DMA_BUF
memset( (uint8*)atmTxCcDescrPool, 0 ,sizeof(atmTxCcDescrPool_t));
memset( (uint8*)atmRxCcDescrPool, 0, sizeof(atmRxCcDescrPool_t));
memset( (uint8*)ccBuf, 0, sizeof(atmRxCcCell_t)*ATM_RX_CC_DESCR_NUMMAX);
memset( (uint8*)oamBuf, 0, sizeof(atmRxOamDescrPool_t)*ATM_VC_MAX);
memset( atmTxDescrPool, 0, atmTxDescrPoolSize);
//memset( (uint8*)atmRxDescrPool, 0 ,sizeof(atmRxDescrPool_t)*ATM_VC_MAX);
#else
memset( (uint8*)&atmTxCcDescrPool, 0 ,sizeof(atmTxCcDescrPool_t));
memset( (uint8*)&atmRxCcDescrPool, 0, sizeof(atmRxCcDescrPool_t));
memset( (uint8*)&ccBuf, 0, sizeof(atmRxCcCell_t)*ATM_RX_CC_DESCR_NUMMAX);
memset( (uint8*)&oamBuf, 0, sizeof(atmRxOamDescrPool_t)*ATM_VC_MAX);
memset( (uint8*)&atmTxDescrPool, 0 ,sizeof(atmTxDescrPool_t)*ATM_VC_MAX);
//memset( (uint8*)&atmRxDescrPool, 0 ,sizeof(atmRxDescrPool_t)*ATM_VC_MAX);
#endif
atmInit(); /* reset sar & init descriptor */
for( i = 0; i < atmCfgBackup.vcNumber; i++ ){ /* open vc according to backup table*/
atmAal5VcOpen( atmCfgBackup.vpi[i], atmCfgBackup.vci[i], &qosRecord[i], atmCfgBackup.vcc[i]);
}
#if defined(TCSUPPORT_CT)
#ifdef DYNAMIC_ALLOC_SKB
g_NoNeedFreeSKB = 0;
#endif
#endif
#ifndef CONFIG_MIPS_TC3262
local_irq_restore(flags);
#else
spin_unlock_irqrestore(&sarLock, flags);
#endif
}
void
sarDrvDescripReset(
int freeRxSkb
)
{
uint8 vc;
uint8 descrId;
atmTxDescr_t *atmTxDescrp;
atmRxDescrPool_t *atmRxDescrVcPoolp;
atmRxDescr_t *atmRxDescrp;
struct sk_buff *skb;
uint32 rxData_offset;
uint8 priority;
if (freeRxSkb) {
for ( vc = 0; vc < ATM_VC_MAX; vc++ ) {
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
rxData_offset = (uint32)atmRxDescrVcPoolp->rxDescrPool - (uint32)atmRxDescrVcPoolp;
TSARM_RXDCBDA(vc)=K1_TO_PHYSICAL(atmRxDescrVcPoolp);
TSARM_VC_RX_DATA(vc) = K1_TO_PHYSICAL(rxData_offset);
atmRxVcDescrp[vc] = atmRxDescrVcPoolp->rxDescrPool;
for ( descrId = 0; descrId < ATM_RX_VC_DESCR_NUMMAX; descrId++ ) {
atmRxDescrp = atmRxDescrVcPoolp->rxDescrPool+ descrId;
skb = atmRxDescrp->skb;
if( skb != NULL ){
dev_kfree_skb_any(skb);
atmRxDescrp->skb = NULL;
}
}
}
}
for ( vc = 0; vc < ATM_VC_MAX; vc++ ) {
// Clear tx packet count and initialize free pointer per vc
//Set up VC(n)'s current tx descr pointer
for (priority = 0; priority < ATM_TX_PRIORITY_MAX; priority++){
for (descrId = 0; descrId < atmTxQueSize[priority]; descrId++ ) {
atmTxDescrp = atmTxDescrPoolAddr[vc].pTxDescr[priority] + descrId;
skb = atmTxDescrp->skb;
if( skb != NULL ){
dev_kfree_skb_any(skb);
atmTxDescrp->skb = NULL;
}
}
}
}
}
/************************************************************************
* A T M D E V I C E O P S D E F I N I T I O N S
*************************************************************************
*/
static int tc3162_atm_open(struct atm_vcc *vcc)
{
qosProfile_t qos;
set_bit(ATM_VF_ADDR, &vcc->flags); /* claim address */
vcc->itf = vcc->dev->number; /* interface number */
qos.pcr = 0;
qos.scr = 0;
qos.mbs = 0;
qos.type = UBR;
switch (vcc->qos.txtp.traffic_class) {
case ATM_CBR:
qos.type = CBR;
qos.pcr = vcc->qos.txtp.pcr;
break;
case ATM_UBR:
qos.type = UBR;
qos.pcr = vcc->qos.txtp.pcr;
break;
case ATM_VBR:
qos.type = VBR;
qos.pcr = vcc->qos.txtp.pcr;
qos.scr = vcc->qos.txtp.scr;
qos.mbs = vcc->qos.txtp.mbs;
break;
case ATM_nrtVBR:
qos.type = nrtVBR;
qos.pcr = vcc->qos.txtp.pcr;
qos.scr = vcc->qos.txtp.scr;
qos.mbs = vcc->qos.txtp.mbs;
break;
default:
/* default is UBR */
break;
}
if(qos.pcr)//the pcr value has been modified by client
{
pcr_modify_flag = 1;
g_qos_pcr = qos.pcr;//save the pcr's value
}
// printk("tc3162_atm_open vpi=%d vci=%d\n", vcc->vpi, vcc->vci);
// printk("tc3162_atm_open qos type=%d pcr=%d scr=%d mbs=%d\n", qos.type, qos.pcr, qos.scr, qos.mbs);
if (atmAal5VcOpen(vcc->vpi, vcc->vci, &qos, vcc))
return -EBUSY;
vcc->sk.sk_sndbuf = 0x7fffffff;
vcc->sk.sk_rcvbuf = 0x7fffffff;
set_bit(ATM_VF_READY, &vcc->flags);
//printk("tc3162_atm_open vpi=%d vci=%d done\n", vpi, vci);
return 0;
}
static void tc3162_atm_close(struct atm_vcc *vcc)
{
//printk("tc3162_atm_close vpi=%d vci=%d\n", vcc->vpi, vcc->vci);
clear_bit(ATM_VF_ADDR, &vcc->flags);
atmAal5VcClose(vcc->vpi, vcc->vci);
clear_bit(ATM_VF_READY, &vcc->flags);
#if defined(TCSUPPORT_PPPOA_ENHANCE)
atomic_set(&sk_atm(vcc)->sk_wmem_alloc, 1);
#endif
//printk("tc3162_atm_close done\n");
}
static int tc3162_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg)
{
#if 0
printk("tc3162_atm_ioctl\n");
return 0;
#else
#ifdef CONFIG_VLAN_ATM
tsarm_ioctl_t sar_ioctl;
switch(cmd) {
case SET_ATM_VLAN:
if ( copy_from_user(&sar_ioctl, (tsarm_ioctl_t*)arg, sizeof(tsarm_ioctl_t)) ) {
return -EFAULT;
}
if ( setATMVlan(&sar_ioctl) == -1 ) {
return -EFAULT;
}
break;
case DEL_ATM_PVC:
default:
break;
}
return 0;
#endif
#endif
}
#if !defined(TCSUPPORT_CT)
#define CONFIG_8021P_REMARK 1
#ifdef CONFIG_8021P_REMARK
static inline struct sk_buff* vlanPriRemark(struct sk_buff *skb)
{
uint8 encap_mode = 0, encap_len = 0;
char * vlan_p = NULL, *ether_type_ptr = NULL;
unsigned char ucprio = 0;
unsigned char uc802prio = 0;
uint16 vid=0;
int copy_len = 0;
if ( skb->mark & QOS_8021p_MARK ) {
/*vlan tagging*/
encap_mode = getEncapMode((uint8*)skb->data);
/*Note Ethernet Header*/
if ( (encap_mode == RFC1483_B_VC)
|| (encap_mode == PPPoA_LLC)
|| (encap_mode == PPPoA_VC) ) {
/*Nono ethernet header to do nothings*/
return skb;
}
encap_len = atmEncapLen[encap_mode];
ether_type_ptr = skb->data + encap_len + 12;
ucprio = (skb->mark & QOS_8021p_MARK) >> 8;
if ( (ucprio < QOS_8021P_0_MARK) && (ucprio >= 0) ) { //0~7 remark
uc802prio = ucprio;
}
else if ( QOS_8021P_0_MARK == ucprio ) { //zero mark
uc802prio = 0;
}
else{//pass through
/*do nothing*/
return skb;
}
if(*(unsigned short *)ether_type_ptr == 0x8100){
vid=(*(unsigned short *)(ether_type_ptr+2) & 0xfff);
}
else{
/*Insert a vlan tag with vid =0*/
vid=0;
if ( skb_headroom(skb) < VLAN_HLEN ) {
struct sk_buff *sk_tmp = skb;
skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
if ( ATM_SKB(sk_tmp)->vcc->pop ) {
ATM_SKB(sk_tmp)->vcc->pop(ATM_SKB(sk_tmp)->vcc, sk_tmp);
}
else {
dev_kfree_skb_any(sk_tmp);
}
if ( !skb ) {
printk(KERN_ERR, "Vlan:failed to realloc headroom\n");
return NULL;
}
}
else {
skb = skb_unshare(skb, GFP_ATOMIC);
if ( !skb ) {
// printk(KERN_ERR, "Vlan: failed to unshare skbuff\n");
return NULL;
}
}
/*offset 4 bytes*/
skb_push(skb, VLAN_HLEN);
copy_len = encap_len + 2*VLAN_ETH_ALEN;
/*move the mac address to the beginning of new header*/
memmove(skb->data, skb->data+VLAN_HLEN, copy_len);
}
vlan_p = skb->data + encap_len + 12;
*(unsigned short *)vlan_p = 0x8100;
vlan_p += 2;
*(unsigned short *)vlan_p = 0;
/*3 bits priority and vid vlaue*/
*(unsigned short*)vlan_p |= (((uc802prio & 0x7) << 13)|vid) ;
skb->network_header -= VLAN_HLEN;
skb->mac_header -= VLAN_HLEN;
}
return skb;
}
#endif /*CONFIG_8021P_REMARK*/
#endif
static int tc3162_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
{
int ret;
uint32 flags;
#ifdef CONFIG_VLAN_ATM
int vlan_vc;
vlan_vc = getIndexVlanVcc( vcc->vpi, vcc->vci );
if ( vlan_vc != ATM_DUMMY_VC ) {
if ( vlan_vcc[vlan_vc].active == 1 ) {
//printk("insert vlan tag here.\n");
skb = insert_vtag( skb, vlan_vc );
if ( skb == NULL ) {
printk("just return for skb is NULL.\n");
return 1;
}
}
}
#if !defined(TCSUPPORT_CT)
#ifdef CONFIG_8021P_REMARK
else{
skb=vlanPriRemark(skb);
if(skb==NULL){
printk("802.1p remark failure\r\n");
return 1;
}
}
#endif
#endif
#endif
#ifdef WAN2LAN
/*****************xyzhu_nj_091104: wan2lan start*************/
if(masko_on_off){
struct sk_buff *skb2 = NULL;
if(skb_headroom(skb) < TX_STAG_LEN){
skb2 = skb_copy_expand(skb, TX_STAG_LEN, skb_tailroom(skb), GFP_ATOMIC);
}else{
skb2 = skb_copy(skb,GFP_ATOMIC);
}
if(skb2 == NULL){
printk("wan2lan failure in sar tx direction for skb2 allocate failure.\n");
}
else{
if ( memcmp(skb2->data, RFC1483_B_LLC_HDR, 7) == 0 ){
skb_pull(skb2, sizeof(RFC1483_B_LLC_HDR));
}
else if ( memcmp(skb2->data, RFC1483_B_VC_HDR, sizeof(RFC1483_B_VC_HDR)) == 0 ){
skb_pull(skb2, sizeof(RFC1483_B_VC_HDR));
}
skb2->mark |= SKBUF_COPYTOLAN;
//Bug 8620. shnwind 20100121
macSend(WAN2LAN_CH_ID,skb2);
}
}
/*****************xyzhu_nj_091104: wan2lan end****************/
#endif
#ifdef CONFIG_NET_SCHED /*Rodney_20091115*/
if((qos_qdisc_mode == QOS_QDISC_RED) || (qos_qdisc_mode == QOS_QDISC_WRED)){
if(vcc->_dev != NULL)
netif_stop_queue(vcc->_dev);
}
#endif
#ifndef CONFIG_MIPS_TC3262
local_irq_save(flags);
#else
spin_lock_irqsave(&sarLock, flags);
#endif
ATM_SKB(skb)->vcc = vcc;
ret = atmAal5DataReq(skb, vcc->vpi, vcc->vci);
if (!ret)
atomic_inc(&vcc->stats->tx);
#ifndef CONFIG_MIPS_TC3262
local_irq_restore(flags);
#else
spin_unlock_irqrestore(&sarLock, flags);
#endif
return ret;
}
static int tc3162_atm_change_qos (struct atm_vcc *vcc, struct atm_qos *qos,int flags)
{
printk("tc3162_atm_change_qos\n");
return 0;
}
/************************************************************************
* A T M D E V I C E P R O C D E F I N I T I O N S
*************************************************************************
*/
int proc_vc[ATM_VC_MAX];
char proc_vc_name[ATM_VC_MAX][32];
static int tsarm_stats_read_proc(char *buf, char **start, off_t off, int count,
int *eof, void *data)
{
int len = getATMState(buf);
if (len <= off+count)
*eof = 1;
*start = buf + off;
len -= off;
if (len>count)
len = count;
if (len<0)
len = 0;
return len;
}
static int tsarm_stats_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char val_string[32];
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
memset((char *)&(atm_p->MIB_II), 0, sizeof(atmMIB_II_t));
return count;
}
static int tsarm_questats_read_proc(char *buf, char **start, off_t off, int count,
int *eof, void *data)
{
int len = getATMQueState(buf);
if (len <= off+count)
*eof = 1;
*start = buf + off;
len -= off;
if (len>count)
len = count;
if (len<0)
len = 0;
return len;
}
static int tsarm_proc_reg(char *buf, char **start, off_t off, int count,
int *eof, void *data)
{
int len;
int *vc;
vc = (int *) data;
len = atmRegDump(buf, *vc);
if (len <= off+count)
*eof = 1;
*start = buf + off;
len -= off;
if (len>count)
len = count;
if (len<0)
len = 0;
return len;
}
static uint32 savedInF5Pkts = 0;
static uint32 savedInF4Pkts = 0;
#ifdef CMD_API
static uint32 oam_success_cnt, oam_fail_cnt;
static uint32 res_time_sum = 0, res_time_min = 0xFFFFFFFF, res_time_max = 0;
static uint32 rep_num, f5;
#endif
static int oam_ping_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
int result;
#ifdef CMD_API
if(f5){
oam_success_cnt = atm_p->MIB_II.inF5Pkts - savedInF5Pkts;
oam_fail_cnt = rep_num - atm_p->MIB_II.inF5Pkts + savedInF5Pkts;
}
else{
oam_success_cnt = atm_p->MIB_II.inF4Pkts - savedInF4Pkts;
oam_fail_cnt = rep_num - atm_p->MIB_II.inF4Pkts + savedInF4Pkts;
}
savedInF5Pkts = atm_p->MIB_II.inF5Pkts;
savedInF4Pkts = atm_p->MIB_II.inF4Pkts;
if(oam_success_cnt)
do_div(res_time_sum, oam_success_cnt);
else
res_time_sum = 0;
len = sprintf(page, "OAM- Test Results\r\nSuccessCount:%ld FailureCount:%ld AverageResponseTime:%lu MinimumResponseTime:%lu MaximumResponseTime:%lu\r\n", oam_success_cnt, oam_fail_cnt, res_time_sum, res_time_min, res_time_max);
res_time_sum = 0;
res_time_min = 0xFFFFFFFF;
res_time_max = 0;
rep_num = 0;
#else
result = (savedInF5Pkts != atm_p->MIB_II.inF5Pkts) || (savedInF4Pkts != atm_p->MIB_II.inF4Pkts);
if (result) {
savedInF5Pkts = atm_p->MIB_II.inF5Pkts;
savedInF4Pkts = atm_p->MIB_II.inF4Pkts;
}
len = sprintf(page, "%d\n", result);
#endif
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int oam_ping_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char val_string[32];
uint32 vpi;
uint32 vci;
#ifndef CMD_API
uint32 f5;
#endif
uint32 endToEnd;
uint32 funcType;
#ifdef CMD_API
uint32 ms, timeout;
uint32 i;
volatile uint32 timer_now, timer_last;
volatile uint32 tick_acc;
uint32 one_tick_unit = 1 * SYS_HCLK * 1000 / 2;
volatile uint32 timer1_ldv = VPint(CR_TIMER1_LDV);
volatile uint32 tick_wait;
#endif
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
#ifdef CMD_API
if (sscanf(val_string, "%lu %lu %lu %lu %lu %lu", &vpi, &vci, &f5, &endToEnd, &funcType, &timeout) != 6) {
printk("usage: <vpi> <vci> <0(f4) 1(f5)> <0(segment) 1(end-to-end)> <type:0(AIS) 1(RDI) 2(Loopback)> <timeout>\n");
return count;
}
rep_num++;
tick_acc = 0;
recved = 0;
timer_last = VPint(CR_TIMER1_VLR);
#else
if (sscanf(val_string, "%lu %lu %lu %lu %lu", &vpi, &vci, &f5, &endToEnd, &funcType) != 5) {
printk("usage: <vpi> <vci> <f5> <end-to-end> <type:0(AIS) 1(RDI) 2(Loopback)>\n");
return count;
}
savedInF5Pkts = atm_p->MIB_II.inF5Pkts;
savedInF4Pkts = atm_p->MIB_II.inF4Pkts;
#endif
atmOamF4F5DataReq((uint8 )vpi, (uint16 )vci, f5, endToEnd, funcType);
#ifdef CMD_API
tick_wait=timeout*one_tick_unit;
while (!recved){
// msleep(10);
timer_now = VPint(CR_TIMER1_VLR);
if (timer_last >= timer_now)
tick_acc += timer_last - timer_now;
else
tick_acc += timer1_ldv - timer_now + timer_last;
timer_last = timer_now;
ms = tick_acc;
// do_div(ms, one_tick_unit);
if((ms >= tick_wait)||recved)
break;
}
ms = tick_acc;
do_div(ms, one_tick_unit);
res_time_sum += ms;
if(res_time_min > ms)
res_time_min = ms;
if(res_time_max < ms)
res_time_max = ms;
#endif
return count;
}
//add by brian for atm f5 loopback diagnostic
#ifdef CWMP
static int loopback_diagnostic_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int index = 0;
char *loopbackbuf = NULL;
uint32 diagnostictime;
char result[][32] = {"Complete","Error_internal","InProgress","Error_other"};
enum result_index
{
Complete = 0,
Internal,
InProgress,
Other
};
loopbackbuf = page;
if(internal_error)
{
index += sprintf(loopbackbuf+index, "DiagnosticState=%s\n", result[Internal]);
index += sprintf(loopbackbuf+index, "DiagnosticTime=0\n");
internal_error = 0;
}
else
{
if((cwmpSavedInF5Pkts != 0) && (cwmpSavedOutF5Pkts <= cwmpSavedInF5Pkts))//diagnostic ok
{
if(g_f5loopback_rxtime > g_f5loopback_txtime)
diagnostictime = (g_f5loopback_rxtime - g_f5loopback_txtime)*1000 / HZ;
else
diagnostictime = (maxtimeindex + g_f5loopback_rxtime - g_f5loopback_txtime)*1000 / HZ;
index += sprintf(loopbackbuf+index, "DiagnosticState=%s\n", result[Complete]);
index += sprintf(loopbackbuf+index, "DiagnosticTime=%lu\n", diagnostictime);
}
else
{
index += sprintf(loopbackbuf+index, "DiagnosticState=%s\n", result[InProgress]);
index += sprintf(loopbackbuf+index, "DiagnosticTime=0\n");
}
}
index -= off;
*start = page + off;
if (index > count)
index = count;
else
*eof = 1;
if (index < 0)
index = 0;
return index;
}
static int loopback_diagnostic_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data)
{
uint32 f5;
uint32 endToEnd;
uint32 funcType;
uint32 flag;
uint32 vpi = 0;
uint32 vci = 0;
char val_string[32];
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
if (sscanf(val_string, "%lu %lu %lu %lu %lu %lu", &vpi, &vci, &f5, &endToEnd, &funcType,&flag) != 6) {
printk("usage: <wanindex> <f5> <end-to-end> <type:0(AIS) 1(RDI) 2(Loopback)> <flag>\n");
return count;
}
printk("\r\nthe value is %lu,%lu,%lu,%lu,%lu,%lu",vpi,vci,f5,endToEnd,funcType,flag);
//the glag used for cwmp diagnostic
cwmpflag = flag;
//compute the time
g_f5loopback_rxtime = 0;
g_f5loopback_txtime = jiffies;
//reset the pkt number
cwmpSavedInF5Pkts = 0;
cwmpSavedOutF5Pkts = 0;
//do loopback diagnostic
if(atmOamF4F5DataReq((uint8 )vpi, (uint16 )vci, f5, endToEnd, funcType))
{
//internal error,so wu just set the variable
internal_error = 1;
}
return count;
}
static int loopback_diagnostic_reset_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
return 0;
}
static int loopback_diagnostic_reset_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data)
{
int resetflag = 0;
char val_string[32];
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
if (sscanf(val_string, "%d", &resetflag) != 1) {
printk("usage: <flag>\n");
return count;
}
if(resetflag)
{
cwmpSavedInF5Pkts = 0;
cwmpSavedOutF5Pkts = 0;
g_f5loopback_rxtime = 0;
g_f5loopback_txtime = 0;
cwmpflag = 0;//reset the cwmpflag,so no need to compute the in or out pkt number
internal_error = 0;
resetflag = 0;
}
return count;
}
#endif
static int tsarm_debug_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "%d\n", sarDebugFlag);
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int tsarm_debug_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char val_string[8];
unsigned long val;
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
val = simple_strtoul(val_string, NULL, 10);
if (val != 0)
sarDebugFlag = 1;
else
sarDebugFlag = 0;
return count;
}
static uint32 vcTxDescrDump = 0;
static uint32 vcRxDescrDump = 0;
#define CHK_BUF() pos = begin + index; if (pos < off) { index = 0; begin = pos; }; if (pos > off + count) goto done;
static int tsarm_txdescrdump_read_proc(char *buf, char **start, off_t off, int count,
int *eof, void *data)
{
int index=0;
off_t pos = 0;
off_t begin = 0;
int i;
atmTxDescr_t *atmTxDescrp;
atmTxCcDescr_t *atmTxOamDescrp;
uint8 priority;
int vc;
char *stateATM = buf;
vc = vcTxDescrDump;
index += sprintf( stateATM+index, "VC=%d\n", vc);
CHK_BUF();
for(priority = 0; priority < ATM_TX_PRIORITY_MAX; priority++){
index += sprintf( stateATM+index, " --- Tx Priority %d ---\n", priority);
CHK_BUF();
index += sprintf( stateATM+index, " atmTxVcBusyDescrp = %08lx\n", (uint32) atmTxVcBusyDescrp[priority][vc]);
CHK_BUF();
index += sprintf( stateATM+index, " atmTxVcFreeDescrp = %08lx\n", (uint32) atmTxVcFreeDescrp[priority][vc]);
CHK_BUF();
atmTxDescrp = atmTxDescrPoolAddr[vc].pTxDescr[priority];
for (i=0; i < atmTxQueSize[priority]; i++, atmTxDescrp++){
index += sprintf( stateATM+index, " --- i=%d ", i);
CHK_BUF();
index += sprintf( stateATM+index, " atmTxDescrp = %08lx --- \n", (uint32)atmTxDescrp);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes0 = %08lx\n", (uint32) atmTxDescrp->tdes0);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes1 = %08lx\n", (uint32) atmTxDescrp->tdes1);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes2 = %08lx\n", (uint32) atmTxDescrp->tdes2);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes3 = %08lx\n", (uint32) atmTxDescrp->tdes3);
CHK_BUF();
index += sprintf( stateATM+index, " ->skb = %08lx\n", (uint32) atmTxDescrp->skb);
CHK_BUF();
}
}
// management
index += sprintf( stateATM+index, " --- Tx Oam descriptor dump ---\n");
CHK_BUF();
index += sprintf( stateATM+index, " atmTxOamFreeDescrp = %08lx\n", (uint32) atmTxOamFreeDescrp[vc]);
CHK_BUF();
atmTxOamDescrp = atmTxDescrPoolAddr[vc].pTxOamDescr;
for (i=0; i<ATM_TX_CC_DESCR_NUMMAX; i++, atmTxOamDescrp++){
index += sprintf( stateATM+index, " --- i=%d atmTxOamDescrp = %08lx --- \n", i, (uint32)atmTxOamDescrp);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes0 = %08lx\n", (uint32) atmTxOamDescrp->tdes0);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes1 = %08lx\n", (uint32) atmTxOamDescrp->tdes1);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes2 = %08lx\n", (uint32) atmTxOamDescrp->tdes2);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes3 = %08lx\n", (uint32) atmTxOamDescrp->tdes3);
CHK_BUF();
}
*eof = 1;
done:
*start = buf + (off - begin);
index -= (off - begin);
if (index<0)
index = 0;
if (index>count)
index = count;
return index;
}
static int tsarm_txdescrdump_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char val_string[32];
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
vcTxDescrDump = simple_strtoul(val_string, NULL, 10);
return count;
}
static int tsarm_rxdescrdump_read_proc(char *buf, char **start, off_t off, int count,
int *eof, void *data)
{
int index=0;
off_t pos = 0;
off_t begin = 0;
int i;
atmRxDescrPool_t *atmRxDescrVcPoolp;
atmRxDescr_t *atmRxDataDescrp;
atmRxCcDescr_t *atmRxMngDescrp;
uint32 vc;
char *stateATM = buf;
vc = vcTxDescrDump;
atmRxDescrVcPoolp = (atmRxDescrPool_t *)CACHE_TO_NONCACHE(atmRxDescrPool + vc);
index += sprintf( stateATM+index, " atmRxDescrPool = %08lx\n", (uint32)atmRxDescrPool);
CHK_BUF();
index += sprintf( stateATM+index, " atmRxDataDescrVcPoolp = %08lx\n", (uint32)atmRxDescrVcPoolp);
CHK_BUF();
// data
index += sprintf( stateATM+index, " --- Rx Data Descriptor dump ---\n");
CHK_BUF();
atmRxDataDescrp = atmRxDescrVcPoolp->rxDescrPool;
for (i=0; i<ATM_RX_VC_DESCR_NUMMAX; i++, atmRxDataDescrp++){
index += sprintf( stateATM+index, " --- i=%d atmRxDataDescrp = %08lx ---\n", i, (uint32)atmRxDataDescrp);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes0 = %08lx\n", (uint32) atmRxDataDescrp->rdes0);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes1 = %08lx\n", (uint32) atmRxDataDescrp->rdes1);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes2 = %08lx\n", (uint32) atmRxDataDescrp->rdes2);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes3 = %08lx\n", (uint32) atmRxDataDescrp->rdes3);
CHK_BUF();
index += sprintf( stateATM+index, " ->skb = %08lx\n", (uint32) atmRxDataDescrp->skb);
CHK_BUF();
}
// management
index += sprintf( stateATM+index, " --- Rx Mng Descriptor dump ---\n");
CHK_BUF();
atmRxMngDescrp = (atmRxCcDescr_t *) atmRxDescrVcPoolp->rxOamDescrPool;
for (i=0; i<ATM_RX_CC_DESCR_NUMMAX; i++, atmRxMngDescrp++){
index += sprintf( stateATM+index, " --- i=%d atmRxMngDescrp = %08lx ---\n", i, (uint32) atmRxMngDescrp);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes0 = %08lx\n", atmRxMngDescrp->rdes0);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes1 = %08lx\n", atmRxMngDescrp->rdes1);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes2 = %08lx\n", atmRxMngDescrp->rdes2);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes3 = %08lx\n", atmRxMngDescrp->rdes3);
CHK_BUF();
}
*eof = 1;
done:
*start = buf + (off - begin);
index -= (off - begin);
if (index<0)
index = 0;
if (index>count)
index = count;
return index;
}
static int tsarm_rxdescrdump_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char val_string[32];
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
vcRxDescrDump = simple_strtoul(val_string, NULL, 10);
return count;
}
static int tsarm_ccdescrdump_read_proc(char *buf, char **start, off_t off, int count,
int *eof, void *data)
{
int index=0;
off_t pos = 0;
off_t begin = 0;
int i;
atmRxCcDescrPool_t *atmRxCcDescrPoolp;
atmRxCcDescr_t *atmRxCcDescrp;
atmTxCcDescrPool_t *atmTxCcDescrVcPoolp;
atmTxCcDescr_t *atmTxCcDescrp;
char *stateATM = buf;
#ifdef DYNAMIC_ALLOC_DMA_BUF
atmTxCcDescrVcPoolp = (atmTxCcDescrPool_t *)CACHE_TO_NONCACHE(atmTxCcDescrPool);
#else
atmTxCcDescrVcPoolp = (atmTxCcDescrPool_t *)CACHE_TO_NONCACHE(&atmTxCcDescrPool);
#endif
#ifdef DYNAMIC_ALLOC_DMA_BUF
index += sprintf( stateATM+index, " atmTxCcFreeDescrp = %08lx\n", (uint32)atmTxCcFreeDescrp);
#else
index += sprintf( stateATM+index, " atmTxCcFreeDescrp = %08lx\n", (uint32)&atmTxCcFreeDescrp);
#endif
CHK_BUF();
#ifdef DYNAMIC_ALLOC_DMA_BUF
index += sprintf( stateATM+index, " atmTxCcDescrPool = %08lx\n", (uint32)atmTxCcDescrPool);
#else
index += sprintf( stateATM+index, " atmTxCcDescrPool = %08lx\n", (uint32)&atmTxCcDescrPool);
#endif
CHK_BUF();
index += sprintf( stateATM+index, " atmTxCcDescrVcPool = %08lx\n", (uint32)atmTxCcDescrVcPoolp);
CHK_BUF();
index += sprintf( stateATM+index, " --- Tx Cc descriptor dump ---\n");
CHK_BUF();
atmTxCcDescrp = atmTxCcDescrVcPoolp->txCcDescrPool;
for (i=0; i<ATM_TX_CC_DESCR_NUMMAX; i++, atmTxCcDescrp++){
index += sprintf( stateATM+index, " -- i=%d atmTxCcDescrp = %08lx ---\n", i, (uint32)atmTxCcDescrp);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes0 = %08lx\n", atmTxCcDescrp->tdes0);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes1 = %08lx\n", atmTxCcDescrp->tdes1);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes2 = %08lx\n", atmTxCcDescrp->tdes2);
CHK_BUF();
index += sprintf( stateATM+index, " ->tdes3 = %08lx\n", atmTxCcDescrp->tdes3);
CHK_BUF();
}
#ifdef DYNAMIC_ALLOC_DMA_BUF
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(atmRxCcDescrPool);
#else
atmRxCcDescrPoolp = (atmRxCcDescrPool_t *)CACHE_TO_NONCACHE(&atmRxCcDescrPool);
#endif
#ifdef DYNAMIC_ALLOC_DMA_BUF
index += sprintf( stateATM+index, " atmRxCcDescrPool = %08lx\n", (uint32)atmRxCcDescrPool);
#else
index += sprintf( stateATM+index, " atmRxCcDescrPool = %08lx\n", (uint32)&atmRxCcDescrPool);
#endif
CHK_BUF();
index += sprintf( stateATM+index, " atmRxCcDescrVcPoolp = %08lx\n", (uint32)atmRxCcDescrPoolp);
CHK_BUF();
index += sprintf( stateATM+index, " --- Rx Cc Descriptor dump ---\n");
CHK_BUF();
atmRxCcDescrp = atmRxCcDescrPoolp->rxCcDescrPool;
for (i=0; i<ATM_RX_CC_DESCR_NUMMAX; i++, atmRxCcDescrp++){
index += sprintf( stateATM+index, " --- i=%d atmRxCcDescrp = %08lx ---\n", i, (uint32)atmRxCcDescrp);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes0 = %08lx\n", atmRxCcDescrp->rdes0);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes1 = %08lx\n", atmRxCcDescrp->rdes1);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes2 = %08lx\n", atmRxCcDescrp->rdes2);
CHK_BUF();
index += sprintf( stateATM+index, " ->rdes3 = %08lx\n", atmRxCcDescrp->rdes3);
CHK_BUF();
}
*eof = 1;
done:
*start = buf + (off - begin);
index -= (off - begin);
if (index<0)
index = 0;
if (index>count)
index = count;
return index;
}
static int tsarm_reset_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "\n");
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int tsarm_reset_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char val_string[8];
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
atmReset();
return count;
}
static int tsarm_pktsclear_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "\n");
len -= off;
*start = page + off;
if (len > count)
len = count;
else
*eof = 1;
if (len < 0)
len = 0;
return len;
}
static int tsarm_pktsclear_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
char val_string[8];
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
atmReset();
atmPktsClear();
return count;
}
//#ifdef QOS_REMARKING /*Rodney_20090724*/
#if defined (QOS_REMARKING) || defined (TCSUPPORT_HW_QOS)
static int tsarm_qoswrr_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data){
int len = sprintf(page, "%d %d %d %d %d\r\n",*qos_wrr_info, *(qos_wrr_info + 1), *(qos_wrr_info + 2), *(qos_wrr_info + 3), *(qos_wrr_info + 4));
return len;
}
static int tsarm_qoswrr_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
int len;
char get_buf[32];
uint32 priority;
int max_wrr_val = 0, i;
/* do a range checking, don't overflow buffers in kernel modules */
if(count > 32)
len = 32;
else
len = count;
/* use the copy_from_user function to copy buffer data to our get_buf */
if(copy_from_user(get_buf, buffer, len))
return -EFAULT;
/* zero terminate get_buf */
get_buf[len]='\0';
if(sscanf(get_buf, "%d %d %d %d %d", qos_wrr_info, (qos_wrr_info+1), (qos_wrr_info+2), (qos_wrr_info+3), (qos_wrr_info+4)) != 5)
return count;
/* find max qos wrr weight */
for (i = 0; i < 4; i++) {
if (max_wrr_val < qos_wrr_info[i + 1]) {
max_wrr_val = qos_wrr_info[i + 1];
max_prio = i;
}
}
qos_wrr_user = QOS_DMAWRR_USERDEFINE;
if(*qos_wrr_info == 0) /*strict priority*/
TSARM_GFR &= ~(GFR_DMT_WRR_EN);
else{ /*WRR*/
priority = TSARM_DMAWRRCR;
priority = (priority & 0xf0f0f0f0);
priority |= (((uint32)(qos_wrr_info[1] & 0x0f) << 0) | ((uint32)(qos_wrr_info[2] & 0x0f) << 8) | ((uint32)(qos_wrr_info[3] & 0x0f) << 16) | ((uint32)(qos_wrr_info[4] & 0x0f) << 24));
TSARM_DMAWRRCR = priority;
TSARM_GFR |= GFR_DMT_WRR_EN;
}
return len;
}
#endif
#ifdef TCSUPPORT_QOS
static int tsarm_tcqos_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data){
if (qos_flag == QOS_SW_PQ) {
printk("qos discipline is PQ.\n");
}
else if (qos_flag == QOS_SW_WRR) {
printk("qos discipline is WRR.\n");
}
else if (qos_flag == QOS_SW_CAR) {
printk("qos discipline is CAR.\n");
}
else if (qos_flag == QOS_HW_WRR) {
printk("qos discipline is HW WRR.\n");
}
else if (qos_flag == QOS_HW_PQ) {
printk("qos discipline is HW PQ.\n");
}
else {
printk("qos is disabled.\n");
}
return 0;
}
static int tsarm_tcqos_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
char qos_disc[10];
int len;
if (count > 10) {
len = 10;
}
else {
len = count;
}
memset(qos_disc, 0, sizeof(qos_disc));
if(copy_from_user(qos_disc, buffer, len - 1))
return -EFAULT;
qos_disc[len] = '\0';
if (!strcmp(qos_disc, "PQ")) {
qos_flag = QOS_SW_PQ;
}
else if (!strcmp(qos_disc, "WRR")) {
qos_flag = QOS_SW_WRR;
}
else if (!strcmp(qos_disc, "CAR")) {
qos_flag = QOS_SW_CAR;
}
else if (!strcmp(qos_disc, "HWWRR")) {
qos_flag = QOS_HW_WRR;
}
else if (!strcmp(qos_disc, "HWPQ")) {
qos_flag = QOS_HW_PQ;
}
else {
qos_flag = NULLQOS;
}
return len;
}
#endif
#ifdef CMD_API
static int tsarm_pvc_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data){
int i, len=0;
for ( i = 0; i < ATM_VC_MAX; i++ ){
if ( atmCfgTable.openFlag[i] == 0 ) {
len = sprintf(page, "%d\r\n", i);
return len;
}
}
return len;
}
static int tsarm_pvc_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
char val_string[32];
uint32 vpi, vci;
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
if(sscanf(val_string, "%lu %lu", &vpi, &vci) != 2){
printk("Input format: vpi vci\r\n");
return -1;
}
#if 0
else{
int i;
if(vpi == 0 && vci == 0){
for(i = 0; i < ATM_VC_MAX; i++){
printk("aal5 vcc statistics for 0.%d.%d\r\n",
atmCfgTable.vpi[i], atmCfgTable.vci[i]);
printk("crc errors\t\t%d\r\n", pvc_stats[i].crc_errs);
printk("oversized sdus\t\t%d\r\n", pvc_stats[i].oversized_sdus);
printk("short packet errors\t%d\r\n", pvc_stats[i].short_pkt_errs);
printk("length errors\t\t%d\r\n\r\n", pvc_stats[i].len_errs);
}
}
else{
for(i = 0; i < ATM_VC_MAX; i++){
if(atmCfgTable.vpi[i] == vpi && atmCfgTable.vci[i] == vci){
printk("aal5 vcc statistics for 0.%d.%d\r\n",
atmCfgTable.vpi[i], atmCfgTable.vci[i]);
printk("crc errors\t\t%d\r\n", pvc_stats[i].crc_errs);
printk("oversized sdus\t\t%d\r\n", pvc_stats[i].oversized_sdus);
printk("short packet errors\t%d\r\n", pvc_stats[i].short_pkt_errs);
printk("length errors\t\t%d\r\n\r\n", pvc_stats[i].len_errs);
}
}
}
}
#endif
return count;
}
int pvc_num, pid_del, pid_add, pid_map[8][3];
static int tsarm_pvc_del_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data){
int len = sprintf(page, "%d %d\r\n", pvc_num, pid_del);
return len;
}
static int tsarm_pvc_del_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
char val_string[32];
uint32 vpi, vci, pid;
int i, mode;
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
mode = sscanf(val_string, "%lu %lu %d", &vpi, &vci, &pid);
switch(pid){
case 0://Delete
for(i = 0; i < 8; i++){
if(pid_map[i][0] == vpi && pid_map[i][1] == vci){
pvc_num = i;
pid_del = pid_map[i][2];
pid_map[i][0] = 0;
pid_map[i][1] = 0;
pid_map[i][2] = 0;
break;
}
}
if(i == 8){
pvc_num = -1;
pid_del = -1;
}
return count;
case -1://Look-up
for(i = 0; i < 8; i++){
if(pid_map[i][0] == vpi && pid_map[i][1] == vci){
pvc_num = i;
pid_del = pid_map[i][2];
break;
}
}
if(i == 8){
pvc_num = -1;
pid_del = -1;
}
return count;
//break;
default://Add
//if vpi.vci exist,use the intial pvcnum and pid_del and return without do anything
for(i = 0; i < 8; i++){
if(pid_map[i][0] == vpi && pid_map[i][1] == vci){
pvc_num = i;
pid_del = pid_map[i][2];
return count;
//break;
}
}
for(i = 0; i < 8; i++){
if(pid_map[i][0] == 0 && pid_map[i][1] == 0){
pvc_num = i;
pid_map[i][0] = vpi;
pid_map[i][1] = vci;
pid_map[i][2] = pid;
pid_del = pid;
break;
}
}
if(i == 8){
pvc_num = -1;
pid_del = -1;
}
return count;
//break;
}
}
static int tsarm_pvc_pid_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data){
int len = sprintf(page, "%d\r\n", pid_add);
return len;
}
static int tsarm_pvc_pid_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
char val_string[100], *pid;
int i = 0,j = 0,index = 0;
char*ptr = NULL;
char*ptrbegin = NULL;
int number[8] = {0,0,0,0,0,0,0,0};
char tmp[10] = {0};
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
#if 0
val_string[count] = '\0';
pid = strrchr(val_string, ' ');
if(!pid)
sscanf(val_string, "%lu", &pid_add);
else
sscanf(pid+1, "%lu", &pid_add);
#endif
val_string[count] = '\0';
strcat(val_string," ");
ptrbegin = val_string;
pid_add = -1;//if not find new value ,return -1
//get the all pid information
while(ptr = strchr(ptrbegin,' '))
{
memset(tmp,0 ,sizeof(tmp));
strncpy(tmp,ptrbegin,ptr - ptrbegin);
sscanf(tmp,"%lu",&number[index]);
ptrbegin = ptr + 1;
if(++index >= 8)
break;
}
#if 0
for(i = 0; i < index; i++)
printk("\r\nnumber[%d] is %d",i,number[i]);
#endif
//fetch the most new pid
for(i = 0; i < index; i++)
{
for(j = 0; j < 8; j++)
{
if(number[i] == pid_map[j][2])
break;
}
//because the number is new,so add it to variable 'pid_add'
if(j == 8)
{
pid_add = number[i];
break;
}
}
return count;
}
uint32 vpiinfo, vciinfo;
static int tsarm_pvc_info_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data){
int i,index = 0;
char *atminfo = page;
if(vpiinfo == 0 && vciinfo == 0)
{
for(i = 0; i < ATM_VC_MAX; i++)
{
index += sprintf( atminfo+index, "aal5 vcc statistics for 0.%u.%u\r\n",atmCfgTable.vpi[i], atmCfgTable.vci[i]);
index += sprintf( atminfo+index, "crc errors\t\t%lu\r\n", pvc_stats[i].crc_errs);
index += sprintf( atminfo+index, "oversized sdus\t\t%lu\r\n", pvc_stats[i].oversized_sdus);
index += sprintf( atminfo+index, "short packet errors\t%lu\r\n", pvc_stats[i].short_pkt_errs);
index += sprintf( atminfo+index, "length errors\t\t%lu\r\n\r\n", pvc_stats[i].len_errs);
}
}
else
{
for(i = 0; i < ATM_VC_MAX; i++)
{
if(atmCfgTable.vpi[i] == vpiinfo && atmCfgTable.vci[i] == vciinfo)
{
index += sprintf( atminfo+index, "aal5 vcc statistics for 0.%u.%u\r\n",atmCfgTable.vpi[i], atmCfgTable.vci[i]);
index += sprintf( atminfo+index, "crc errors\t\t%lu\r\n", pvc_stats[i].crc_errs);
index += sprintf( atminfo+index, "oversized sdus\t\t%lu\r\n", pvc_stats[i].oversized_sdus);
index += sprintf( atminfo+index, "short packet errors\t%lu\r\n", pvc_stats[i].short_pkt_errs);
index += sprintf( atminfo+index, "length errors\t\t%lu\r\n\r\n", pvc_stats[i].len_errs);
}
}
}
index -= off;
*start = page + off;
if (index > count)
index = count;
else
*eof = 1;
if (index < 0)
index = 0;
return index;
}
static int tsarm_pvc_info_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
char val_string[32];
vpiinfo = 0;
vciinfo = 0;
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
if(sscanf(val_string, "%lu %lu", &vpiinfo, &vciinfo) != 2){
printk("Input format: vpi vci\r\n");
return -1;
}
return count;
}
#endif
#ifdef CONFIG_NET_SCHED /*Rodney_20091115*/
static int tsarm_qosred_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data){
int index=0;
off_t begin = 0;
index += sprintf(page+index, "qos_qdisc_mode=%d\n", qos_qdisc_mode);
#ifdef QOS_DROP_DUMP
int cnt;
for(cnt=0 ; cnt<MAX_LOG_PKT ; cnt++)
printk("cnt=%4d flag=%d\n",cnt, qos_drop_flag[cnt]);
#endif
*eof = 1;
*start = page + (off - begin);
index -= (off - begin);
if (index<0)
index = 0;
if (index>count)
index = count;
return index;
}
static int tsarm_qosred_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
int len, proc_data[5] = {0}, vc;
char get_buf[32];
uint32 reg_tmp;
/* do a range checking, don't overflow buffers in kernel modules */
if(count > 32)
len = 32;
else
len = count;
/* use the copy_from_user function to copy buffer data to our get_buf */
if(copy_from_user(get_buf, buffer, len))
return -EFAULT;
/* zero terminate get_buf */
get_buf[len]='\0';
if(sscanf(get_buf, "%d %d %d %d %d", proc_data, (proc_data+1), (proc_data+2), (proc_data+3), (proc_data+4)) != 5)
return count;
qos_qdisc_mode = proc_data[0];
for ( vc = 0; vc < ATM_VC_MAX; vc++ ){
if(atmCfgTable.openFlag[vc] == 1){
if((qos_qdisc_mode == QOS_QDISC_RED) || (qos_qdisc_mode == QOS_QDISC_WRED)){
reg_tmp = TSARM_IRQM(vc);
reg_tmp = reg_tmp & 0xfffffffe;
TSARM_IRQM(vc) = reg_tmp;
}else{
reg_tmp = TSARM_IRQM(vc);
reg_tmp = reg_tmp | 0x00000001;
TSARM_IRQM(vc) = reg_tmp;
}
}
}
return len;
}
#endif
static int tsarm_qosred_update_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data){
return 0;
}
/*______________________________________________________________________________
** update_qosred
**
** descriptions:used to udate atm qos when adsl is up
** execution sequence:
** commands process:
** parameters:
** local:
** global:
** return:
** called by:tsarm_qosred_update_write_proc
** call:
**____________________________________________________________________________*/
static int update_qosred(uint32 vc)
{
qosProfile_t *qos_p;
if ( atmCfgTable.openFlag[vc] == 0) {
//printk("vc = %d is not active\n",vc);
return 0;
}
qos_p=&qosRecord[vc];
setAtmQosRed(qos_p,vc);
return 0;
}
static int tsarm_qosred_update_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
int len;
int vc;
char get_buf[32];
/* do a range checking, don't overflow buffers in kernel modules */
if(count > sizeof(get_buf)-1)
len = sizeof(get_buf);
else
len = count;
/* use the copy_from_user function to copy buffer data to our get_buf */
if(copy_from_user(get_buf, buffer, len))
return -EFAULT;
/* zero terminate get_buf */
get_buf[len]='\0';
if(sscanf(get_buf, "%d", &vc)!= 1)
return count;
if(vc>=0 && vc<ATM_VC_MAX)
update_qosred(vc);
return count;
}
#ifdef CONFIG_QOS
#ifdef TCSUPPORT_SBTHROUGHPUT_ENHANCE
static int qos_switch_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data){
int len = sprintf(page, "%d\r\n", tc_qos_switch);
return len;
}
static int qos_switch_write_proc(struct file *file, const char *buffer,
unsigned long count, void *data){
char val_string[10];
if (count > sizeof(val_string) - 1)
return -EINVAL;
if (copy_from_user(val_string, buffer, count))
return -EFAULT;
val_string[count] = '\0';
sscanf(val_string, "%d", &tc_qos_switch);
return count;
}
#endif
#endif
#ifdef CONFIG_MIPS_TC3262
static void
tc3262sar_irq_dispatch(void)
{
do_IRQ(SAR_INT);
}
#endif
static int __init tc3162_atm_init(void)
{
struct proc_dir_entry *tsarm_proc;
int vc;
int err=0;
printk("TSARM: TC3162 ATM SAR driver 1.5 init\n");
printk("\r\n%s\n", MODULE_VERSION_TC3162SAR);
if ((tc3162_atm_dev = atm_dev_register("TSARM", &tc3162_atm_ops, -1, NULL)) == NULL) {
printk("atm dev register fail.\n");
err = -ENODEV;
goto failed;
}
tc3162_atm_dev->ci_range.vpi_bits = ATM_CI_MAX; /* atm VPI supports 8 bits */
tc3162_atm_dev->ci_range.vci_bits = ATM_CI_MAX; /* atm VCI supports 16 bits */
#ifdef CONFIG_MIPS_TC3262
/*Workaround to disabe back to back function, otherwise due to irq=0 event*/
VPint(0xBFB000B8)=0x1;
if(cpu_has_vint){
set_vi_handler(SAR_INT, tc3262sar_irq_dispatch);
}
#endif
#ifdef SAR_POLLING
if (request_irq(SAR_INT, fakeAtmIsr, 0, "TSARM", tc3162_atm_dev) != 0) {
#else
if (request_irq(SAR_INT, atmIsr, 0, "TSARM", tc3162_atm_dev) != 0) {
#endif
printk("can not allocate IRQ.\n");
err = -EIO;
goto failed;
}
atmRxBufferSize = ((uint32)(RX_BUF_LEN/48))*48;
/* init tsarm hardware module */
atmInit();
/* atm related stats */
tsarm_proc = create_proc_entry("tc3162/tsarm_stats", 0, NULL);
tsarm_proc->read_proc = tsarm_stats_read_proc;
tsarm_proc->write_proc = tsarm_stats_write_proc;
create_proc_read_entry("tc3162/tsarm_questats", 0, NULL, tsarm_questats_read_proc, NULL);
for (vc = 0; vc < ATM_VC_MAX; vc++) {
proc_vc[vc] = vc;
sprintf(proc_vc_name[vc], "tc3162/tsarm_vc%d", vc);
create_proc_read_entry(proc_vc_name[vc], 0, NULL, tsarm_proc_reg, &proc_vc[vc]);
}
/* atm oam loopback */
tsarm_proc = create_proc_entry("tc3162/oam_ping", 0, NULL);
tsarm_proc->read_proc = oam_ping_read_proc;
tsarm_proc->write_proc = oam_ping_write_proc;
/* atm debug */
tsarm_proc = create_proc_entry("tc3162/tsarm_debug", 0, NULL);
tsarm_proc->read_proc = tsarm_debug_read_proc;
tsarm_proc->write_proc = tsarm_debug_write_proc;
/* atm tx descr dump */
tsarm_proc = create_proc_entry("tc3162/tsarm_txdescr", 0, NULL);
tsarm_proc->read_proc = tsarm_txdescrdump_read_proc;
tsarm_proc->write_proc = tsarm_txdescrdump_write_proc;
/* atm rx descr dump */
tsarm_proc = create_proc_entry("tc3162/tsarm_rxdescr", 0, NULL);
tsarm_proc->read_proc = tsarm_rxdescrdump_read_proc;
tsarm_proc->write_proc = tsarm_rxdescrdump_write_proc;
/* atm cc descr dump */
create_proc_read_entry("tc3162/tsarm_ccdescr", 0, NULL, tsarm_ccdescrdump_read_proc, NULL);
/* atm reset */
tsarm_proc = create_proc_entry("tc3162/tsarm_reset", 0, NULL);
tsarm_proc->read_proc = tsarm_reset_read_proc;
tsarm_proc->write_proc = tsarm_reset_write_proc;
/*pork 20090310 added atm packets clear*/
tsarm_proc = create_proc_entry("tc3162/tsarm_pktsclear", 0, NULL);
tsarm_proc->read_proc = tsarm_pktsclear_read_proc;
tsarm_proc->write_proc = tsarm_pktsclear_write_proc;
//#ifdef QOS_REMARKING /*Rodney_20090724*/
#if defined(QOS_REMARKING) || defined(TCSUPPORT_HW_QOS)
tsarm_proc = create_proc_entry("tc3162/tsarm_qoswrr", 0, NULL);
tsarm_proc->read_proc = tsarm_qoswrr_read_proc;
tsarm_proc->write_proc = tsarm_qoswrr_write_proc;
#endif
#ifdef TCSUPPORT_QOS
tsarm_proc = create_proc_entry("tc3162/tcqos_disc", 0, NULL);
tsarm_proc->read_proc = tsarm_tcqos_read_proc;
tsarm_proc->write_proc = tsarm_tcqos_write_proc;
#endif
//add by brian for atm f5 loopback diagnostic
#ifdef CWMP
tsarm_proc = create_proc_entry("tc3162/atm_f5_loopback_diagnostic", 0, NULL);
tsarm_proc->read_proc = loopback_diagnostic_read_proc;
tsarm_proc->write_proc = loopback_diagnostic_write_proc;
tsarm_proc = create_proc_entry("tc3162/atm_f5_loopback_diagnostic_reset", 0, NULL);
tsarm_proc->read_proc = loopback_diagnostic_reset_read_proc;
tsarm_proc->write_proc = loopback_diagnostic_reset_write_proc;
#endif
#ifdef CMD_API
tsarm_proc = create_proc_entry("tc3162/tsarm_pvc", 0, NULL);
tsarm_proc->read_proc = tsarm_pvc_read_proc;
tsarm_proc->write_proc = tsarm_pvc_write_proc;
tsarm_proc = create_proc_entry("tc3162/tsarm_pvc_del", 0, NULL);
tsarm_proc->read_proc = tsarm_pvc_del_read_proc;
tsarm_proc->write_proc = tsarm_pvc_del_write_proc;
tsarm_proc = create_proc_entry("tc3162/tsarm_pvc_pid", 0, NULL);
tsarm_proc->read_proc = tsarm_pvc_pid_read_proc;
tsarm_proc->write_proc = tsarm_pvc_pid_write_proc;
tsarm_proc = create_proc_entry("tc3162/tsarm_pvc_info", 0, NULL);
tsarm_proc->read_proc = tsarm_pvc_info_read_proc;
tsarm_proc->write_proc = tsarm_pvc_info_write_proc;
#endif
#ifdef CONFIG_NET_SCHED /*Rodney_20091115*/
tsarm_proc = create_proc_entry("tc3162/tsarm_qosred", 0, NULL);
tsarm_proc->read_proc = tsarm_qosred_read_proc;
tsarm_proc->write_proc = tsarm_qosred_write_proc;
#endif
#ifdef CONFIG_QOS
#ifdef TCSUPPORT_SBTHROUGHPUT_ENHANCE
tsarm_proc = create_proc_entry("tc3162/qos_switch", 0, NULL);
tsarm_proc->read_proc = qos_switch_read_proc;
tsarm_proc->write_proc = qos_switch_write_proc;
#endif
#endif
tsarm_proc = create_proc_entry("tc3162/tsarm_qosred_update", 0, NULL);
tsarm_proc->read_proc = tsarm_qosred_update_read_proc;
tsarm_proc->write_proc = tsarm_qosred_update_write_proc;
/*pork 20090310 added atm packets clear over*/
#ifdef SAR_VERIFY
/*Register ci-cmd*/
sarVerifyInit();
#endif
#ifdef CONFIG_MIPS_TC3262
spin_lock_init(&sarLock);
#endif
#ifdef L2_AUTOPVC
autopvcInit();
#endif
#ifdef SAR_POLLING
init_waitqueue_head( &isrPollingQueue);
polling_task = kthread_run(isrPollingThread, NULL, "sarPollingIsrThread");
#endif
printk("TSARM: TC3162 ATM SAR driver 1.5 done\n");
return 0;
failed:
if (tc3162_atm_dev)
atm_dev_deregister(tc3162_atm_dev);
tc3162_atm_dev = NULL;
return err;
}
static void __exit tc3162_atm_exit(void)
{
int vc;
printk("tc3162_atm_exit\n");
free_irq(SAR_INT, tc3162_atm_dev);
// disable rx
TSARM_GFR = 0x0;
while ((TSARM_IRQH & 0x00fff000) >> 12)
TSARM_IRQC = 1;
sarDrvDescripReset(1);
atm_dev_deregister(tc3162_atm_dev);
tc3162_atm_dev = NULL;
remove_proc_entry("tc3162/tsarm_stats", NULL);
remove_proc_entry("tc3162/tsarm_questats", NULL);
for (vc = 0; vc < ATM_VC_MAX; vc++) {
sprintf(proc_vc_name[vc], "tc3162/tsarm_vc%d", vc);
remove_proc_entry(proc_vc_name[vc], NULL);
}
remove_proc_entry("tc3162/oam_ping", NULL);
remove_proc_entry("tc3162/tsarm_debug", NULL);
remove_proc_entry("tc3162/tsarm_txdescr", NULL);
remove_proc_entry("tc3162/tsarm_rxdescr", NULL);
remove_proc_entry("tc3162/tsarm_ccdescr", NULL);
remove_proc_entry("tc3162/tsarm_reset", NULL);
#ifdef QOS_REMARKING /*Rodney_20090724*/
remove_proc_entry("tc3162/tsarm_qoswrr", NULL);
#endif
//add by brian for atm f5 loopback diagnostic
#ifdef CWMP
remove_proc_entry("tc3162/atm_f5_loopback_diagnostic", NULL);
remove_proc_entry("tc3162/atm_f5_loopback_diagnostic_reset", NULL);
#endif
#ifdef CMD_API
remove_proc_entry("tc3162/tsarm_pvc", NULL);
remove_proc_entry("tc3162/tsarm_pvc_del", NULL);
remove_proc_entry("tc3162/tsarm_pvc_pid", NULL);
remove_proc_entry("tc3162/tsarm_pvc_info", NULL);
#endif
#ifdef CONFIG_NET_SCHED /*Rodney_20091115*/
remove_proc_entry("tc3162/tsarm_qosred", NULL);
#endif
#ifdef CONFIG_QOS
#ifdef TCSUPPORT_SBTHROUGHPUT_ENHANCE
remove_proc_entry("tc3162/qos_switch", NULL);
#endif
#endif
remove_proc_entry("tc3162/tsarm_qosred_update", NULL);
#ifdef DYNAMIC_ALLOC_DMA_BUF
#ifndef DMA_API
if (atmTxCcDescrPool) {
kfree(atmTxCcDescrPool);
atmTxCcDescrPool = NULL;
}
if (atmRxCcDescrPool) {
kfree(atmRxCcDescrPool);
atmRxCcDescrPool = NULL;
}
if (ccBuf) {
kfree(ccBuf);
ccBuf = NULL;
}
if (oamBuf) {
kfree(oamBuf);
oamBuf = NULL;
}
if (atmTxDescrPool) {
kfree(atmTxDescrPool);
atmTxDescrPool = NULL;
}
if (atmRxDescrPool) {
kfree(atmRxDescrPool);
atmRxDescrPool = NULL;
}
if (atmRxIrq) {
kfree(atmRxIrq);
atmRxIrq = NULL;
}
#else
dma_free_coherent(NULL, sizeof(atmTxCcDescrPool_t), atmTxCcDescrPool, (dma_addr_t) atmTxCcDescrPool_phys_p);
dma_free_coherent(NULL, sizeof(atmRxCcDescrPool_t), atmRxCcDescrPool, (dma_addr_t) atmRxCcDescrPool_phys_p);
dma_free_coherent(NULL, sizeof(atmRxCcCell_t)*ATM_RX_CC_DESCR_NUMMAX, ccBuf, (dma_addr_t) ccBuf_phys_p);
dma_free_coherent(NULL, sizeof(atmRxOamDescrPool_t)*ATM_VC_MAX, oamBuf, (dma_addr_t) oamBuf_phys_p);
dma_free_coherent(NULL, atmTxDescrPoolSize, atmTxDescrPool, (dma_addr_t) atmTxDescrPool_phys_p);
dma_free_coherent(NULL, sizeof(atmRxDescrPool_t)*ATM_VC_MAX, atmRxDescrPool, (dma_addr_t) atmRxDescrPool_phys_p);
dma_free_coherent(NULL, sizeof(uint32)*IRQ_MAX_ENTRY, atmRxIrq, (dma_addr_t) atmRxIrq_phys_p);
#ifndef SAR_VERIFY
dma_free_coherent(NULL, sizeof(atmCell_t)*ATM_VC_MAX, atmCellCirBuf, (dma_addr_t) atmCellCirBuf_phys_p);
#else
dma_free_coherent(NULL, sizeof(atmCell_t)*MCELL_BUF_RING_SIZE, atmCellCirBuf, (dma_addr_t) atmCellCirBuf_phys_p);
#endif
#endif
#ifdef SAR_VERIFY
sarVerifyExit();
#endif
#endif
#ifdef L2_AUTOPVC
autopvcExit();
#endif
#ifdef SAR_POLLING
if( polling_task){
kthread_stop(polling_task);
}
#endif
}
module_init (tc3162_atm_init);
module_exit (tc3162_atm_exit);