diff options
author | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-11-01 18:52:35 +0000 |
---|---|---|
committer | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-11-01 18:52:35 +0000 |
commit | d30299b51ebb3b15a67e66dc95f7b75c40a114c1 (patch) | |
tree | 37744ee3f20d4027e40ab1052295409e66d1a664 /package/ifxmips-atm/src/core.c | |
parent | 5a58232dfa18a1f8fbb4becc9f2df586f9039cce (diff) |
[ifxmips] adds dsl support, thank you infineon/lantiq
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18259 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/ifxmips-atm/src/core.c')
-rw-r--r-- | package/ifxmips-atm/src/core.c | 800 |
1 files changed, 0 insertions, 800 deletions
diff --git a/package/ifxmips-atm/src/core.c b/package/ifxmips-atm/src/core.c deleted file mode 100644 index 95b05f3db..000000000 --- a/package/ifxmips-atm/src/core.c +++ /dev/null @@ -1,800 +0,0 @@ -#include <asm/mach-ifxmips/cgu.h> -#include <linux/module.h> -#include <linux/atmdev.h> -#include <linux/irq.h> - -#include "common.h" -#include "proc.h" - -// our main struct -struct ppe_dev ppe_dev; - -static int port_max_connection[2] = {7, 7}; /* Maximum number of connections for ports (0-14) */ -static int port_cell_rate_up[2] = {3200, 3200}; /* Maximum TX cell rate for ports */ -static int qsb_tau = 1; -static int qsb_srvm = 0x0f; -static int qsb_tstep = 4; -static int write_descriptor_delay = 0x20; -static int aal5_fill_pattern = 0x007E; -static int aal5r_max_packet_size = 0x0700; -static int aal5r_min_packet_size = 0x0000; -static int aal5s_max_packet_size = 0x0700; -static int aal5s_min_packet_size = 0x0000; -static int aal5r_drop_error_packet = 1; -static int dma_rx_descriptor_length = 48; -static int dma_tx_descriptor_length = 64; -static int dma_rx_clp1_descriptor_threshold = 38; - -//module_param(port_max_connection, "2-2i"); -//module_param(port_cell_rate_up, "2-2i"); -module_param(qsb_tau, int, 0); -module_param(qsb_srvm, int, 0); -module_param(qsb_tstep, int, 0); -module_param(write_descriptor_delay, int, 0); -module_param(aal5_fill_pattern, int, 0); -module_param(aal5r_max_packet_size, int, 0); -module_param(aal5r_min_packet_size, int, 0); -module_param(aal5s_max_packet_size, int, 0); -module_param(aal5s_min_packet_size, int, 0); -module_param(aal5r_drop_error_packet, int, 0); -module_param(dma_rx_descriptor_length, int, 0); -module_param(dma_tx_descriptor_length, int, 0); -module_param(dma_rx_clp1_descriptor_threshold, int, 0); - -MODULE_PARM_DESC(port_cell_rate_up, "ATM port upstream rate in cells/s"); -MODULE_PARM_DESC(port_max_connection, "Maximum atm connection for port (0-1)"); -MODULE_PARM_DESC(qsb_tau, "Cell delay variation. Value must be > 0"); -MODULE_PARM_DESC(qsb_srvm, "Maximum burst size"); -MODULE_PARM_DESC(qsb_tstep, "n*32 cycles per sbs cycles n=1,2,4"); -MODULE_PARM_DESC(write_descriptor_delay, "PPE core clock cycles between descriptor write and effectiveness in external RAM"); -MODULE_PARM_DESC(a5_fill_pattern, "Filling pattern (PAD) for AAL5 frames"); -MODULE_PARM_DESC(aal5r_max_packet_size, "Max packet size in byte for downstream AAL5 frames"); -MODULE_PARM_DESC(aal5r_min_packet_size, "Min packet size in byte for downstream AAL5 frames"); -MODULE_PARM_DESC(aal5s_max_packet_size, "Max packet size in byte for upstream AAL5 frames"); -MODULE_PARM_DESC(aal5s_min_packet_size, "Min packet size in byte for upstream AAL5 frames"); -MODULE_PARM_DESC(aal5r_drop_error_packet, "Non-zero value to drop error packet for downstream"); -MODULE_PARM_DESC(dma_rx_descriptor_length, "Number of descriptor assigned to DMA RX channel (>16)"); -MODULE_PARM_DESC(dma_tx_descriptor_length, "Number of descriptor assigned to DMA TX channel (>16)"); -MODULE_PARM_DESC(dma_rx_clp1_descriptor_threshold, "Descriptor threshold for cells with cell loss priority 1"); - -void init_rx_tables(void) -{ - int i, j; - struct wrx_queue_config wrx_queue_config = {0}; - struct wrx_dma_channel_config wrx_dma_channel_config = {0}; - struct htu_entry htu_entry = {0}; - struct htu_result htu_result = {0}; - - struct htu_mask htu_mask = { set: 0x03, - pid_mask: 0x00, - vpi_mask: 0x00, - vci_mask: 0x00, - pti_mask: 0x00, - clear: 0x00}; - - /* - * General Registers - */ - *CFG_WRX_HTUTS = ppe_dev.max_connections + OAM_HTU_ENTRY_NUMBER; - *CFG_WRX_QNUM = ppe_dev.max_connections + OAM_RX_QUEUE_NUMBER + QSB_QUEUE_NUMBER_BASE; - *CFG_WRX_DCHNUM = ppe_dev.dma.rx_total_channel_used; - *WRX_DMACH_ON = (1 << ppe_dev.dma.rx_total_channel_used) - 1; - *WRX_HUNT_BITTH = DEFAULT_RX_HUNT_BITTH; - - /* - * WRX Queue Configuration Table - */ - wrx_queue_config.uumask = 0; - wrx_queue_config.cpimask = 0; - wrx_queue_config.uuexp = 0; - wrx_queue_config.cpiexp = 0; - wrx_queue_config.mfs = ppe_dev.aal5.rx_max_packet_size; // rx_buffer_size - wrx_queue_config.oversize = ppe_dev.aal5.rx_max_packet_size; - wrx_queue_config.undersize = ppe_dev.aal5.rx_min_packet_size; - wrx_queue_config.errdp = ppe_dev.aal5.rx_drop_error_packet; - for ( i = 0; i < QSB_QUEUE_NUMBER_BASE; i++ ) - *WRX_QUEUE_CONFIG(i) = wrx_queue_config; - for ( j = 0; j < ppe_dev.max_connections; j++ ) - { -#if !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS - /* If RX QoS is disabled, the DMA channel must be fixed. */ - wrx_queue_config.dmach = ppe_dev.connection[i].rx_dma_channel; -#endif // !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS - *WRX_QUEUE_CONFIG(i++) = wrx_queue_config; - } - /* OAM RX Queue */ - for ( j = 0; j < OAM_RX_DMA_CHANNEL_NUMBER; j++ ) - { -#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS - wrx_queue_config.dmach = RX_DMA_CH_OAM; -#else - wrx_queue_config.dmach = ppe_dev.oam_rx_dma_channel + j; -#endif // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS - *WRX_QUEUE_CONFIG(i++) = wrx_queue_config; - } - - wrx_dma_channel_config.deslen = ppe_dev.dma.rx_descriptor_number; - wrx_dma_channel_config.chrl = 0; - wrx_dma_channel_config.clp1th = ppe_dev.dma.rx_clp1_desc_threshold; - wrx_dma_channel_config.mode = WRX_DMA_CHANNEL_COUNTER_MODE; - wrx_dma_channel_config.rlcfg = WRX_DMA_BUF_LEN_PER_DESCRIPTOR; - for ( i = 0; i < ppe_dev.dma.rx_total_channel_used; i++ ) - { - wrx_dma_channel_config.desba = (((u32)ppe_dev.dma.rx_descriptor_base >> 2) & 0x0FFFFFFF) + ppe_dev.dma.rx_descriptor_number * i * (sizeof(struct rx_descriptor) >> 2); - *WRX_DMA_CHANNEL_CONFIG(i) = wrx_dma_channel_config; - } - - /* - * HTU Tables - */ - for ( i = 0; i < ppe_dev.max_connections; i++ ) - { - htu_result.qid = (unsigned int)i; - - *HTU_ENTRY(i + OAM_HTU_ENTRY_NUMBER) = htu_entry; - *HTU_MASK(i + OAM_HTU_ENTRY_NUMBER) = htu_mask; - *HTU_RESULT(i + OAM_HTU_ENTRY_NUMBER) = htu_result; - } - /* OAM HTU Entry */ - htu_entry.vci = 0x03; - htu_mask.pid_mask = 0x03; - htu_mask.vpi_mask = 0xFF; - htu_mask.vci_mask = 0x0000; - htu_mask.pti_mask = 0x07; - htu_result.cellid = ppe_dev.oam_rx_queue; - htu_result.type = 1; - htu_result.ven = 1; - htu_result.qid = ppe_dev.oam_rx_queue; - *HTU_RESULT(OAM_F4_SEG_HTU_ENTRY) = htu_result; - *HTU_MASK(OAM_F4_SEG_HTU_ENTRY) = htu_mask; - *HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY) = htu_entry; - htu_entry.vci = 0x04; - htu_result.cellid = ppe_dev.oam_rx_queue; - htu_result.type = 1; - htu_result.ven = 1; - htu_result.qid = ppe_dev.oam_rx_queue; - *HTU_RESULT(OAM_F4_TOT_HTU_ENTRY) = htu_result; - *HTU_MASK(OAM_F4_TOT_HTU_ENTRY) = htu_mask; - *HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY) = htu_entry; - htu_entry.vci = 0x00; - htu_entry.pti = 0x04; - htu_mask.vci_mask = 0xFFFF; - htu_mask.pti_mask = 0x01; - htu_result.cellid = ppe_dev.oam_rx_queue; - htu_result.type = 1; - htu_result.ven = 1; - htu_result.qid = ppe_dev.oam_rx_queue; - *HTU_RESULT(OAM_F5_HTU_ENTRY) = htu_result; - *HTU_MASK(OAM_F5_HTU_ENTRY) = htu_mask; - *HTU_ENTRY(OAM_F5_HTU_ENTRY) = htu_entry; -} - -void init_tx_tables(void) -{ - int i, j; - struct wtx_queue_config wtx_queue_config = {0}; - struct wtx_dma_channel_config wtx_dma_channel_config = {0}; - - struct wtx_port_config wtx_port_config = { res1: 0, - qid: 0, - qsben: 1}; - - /* - * General Registers - */ - *CFG_WTX_DCHNUM = ppe_dev.dma.tx_total_channel_used + QSB_QUEUE_NUMBER_BASE; - *WTX_DMACH_ON = ((1 << (ppe_dev.dma.tx_total_channel_used + QSB_QUEUE_NUMBER_BASE)) - 1) ^ ((1 << QSB_QUEUE_NUMBER_BASE) - 1); - *CFG_WRDES_DELAY = ppe_dev.dma.write_descriptor_delay; - - /* - * WTX Port Configuration Table - */ -#if !defined(DISABLE_QSB) || !DISABLE_QSB - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - *WTX_PORT_CONFIG(i) = wtx_port_config; -#else - wtx_port_config.qsben = 0; - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - { - wtx_port_config.qid = ppe_dev.port[i].connection_base; - *WTX_PORT_CONFIG(i) = wtx_port_config; - -printk("port %d: qid = %d, qsb disabled\n", i, wtx_port_config.qid); - } -#endif - - /* - * WTX Queue Configuration Table - */ - wtx_queue_config.res1 = 0; - wtx_queue_config.res2 = 0; -// wtx_queue_config.type = 0x03; - wtx_queue_config.type = 0x0; -#if !defined(DISABLE_QSB) || !DISABLE_QSB - wtx_queue_config.qsben = 1; -#else - wtx_queue_config.qsben = 0; -#endif - wtx_queue_config.sbid = 0; - for ( i = 0; i < QSB_QUEUE_NUMBER_BASE; i++ ) - *WTX_QUEUE_CONFIG(i) = wtx_queue_config; - for ( j = 0; j < ppe_dev.max_connections; j++ ) - { - wtx_queue_config.sbid = ppe_dev.connection[i].port & 0x01; /* assign QSB to TX queue */ - *WTX_QUEUE_CONFIG(i) = wtx_queue_config; - i++; - } - /* OAM TX Queue */ -// wtx_queue_config.type = 0x01; - wtx_queue_config.type = 0x00; - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - { - wtx_queue_config.sbid = i & 0x01; - for ( j = 0; j < OAM_TX_QUEUE_NUMBER_PER_PORT; j++ ) - *WTX_QUEUE_CONFIG(ppe_dev.port[i].oam_tx_queue + j) = wtx_queue_config; - } - - wtx_dma_channel_config.mode = WRX_DMA_CHANNEL_COUNTER_MODE; - wtx_dma_channel_config.deslen = 0; - wtx_dma_channel_config.desba = 0; - for ( i = 0; i < QSB_QUEUE_NUMBER_BASE; i++ ) - *WTX_DMA_CHANNEL_CONFIG(i) = wtx_dma_channel_config; - /* normal connection and OAM channel */ - wtx_dma_channel_config.deslen = ppe_dev.dma.tx_descriptor_number; - for ( j = 0; j < ppe_dev.dma.tx_total_channel_used; j++ ) - { - wtx_dma_channel_config.desba = (((u32)ppe_dev.dma.tx_descriptor_base >> 2) & 0x0FFFFFFF) + ppe_dev.dma.tx_descriptor_number * j * (sizeof(struct tx_descriptor) >> 2); - *WTX_DMA_CHANNEL_CONFIG(i++) = wtx_dma_channel_config; - } -} - -static inline void qsb_global_set(void) -{ - int i, j; - u32 qsb_clk = cgu_get_fpi_bus_clock(2); - u32 tmp1, tmp2, tmp3; - union qsb_queue_parameter_table qsb_queue_parameter_table = {{0}}; - union qsb_queue_vbr_parameter_table qsb_queue_vbr_parameter_table = {{0}}; - int qsb_qid; - - *QSB_ICDV = QSB_ICDV_TAU_SET(ppe_dev.qsb.tau); - *QSB_SBL = QSB_SBL_SBL_SET(ppe_dev.qsb.sbl); - *QSB_CFG = QSB_CFG_TSTEPC_SET(ppe_dev.qsb.tstepc >> 1); - - /* - * set SCT and SPT per port - */ - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - if ( ppe_dev.port[i].max_connections != 0 && ppe_dev.port[i].tx_max_cell_rate != 0 ) - { - tmp1 = ((qsb_clk * ppe_dev.qsb.tstepc) >> 1) / ppe_dev.port[i].tx_max_cell_rate; - tmp2 = tmp1 >> 6; /* integer value of Tsb */ - tmp3 = (tmp1 & ((1 << 6) - 1)) + 1; /* fractional part of Tsb */ - /* carry over to integer part (?) */ - if ( tmp3 == (1 << 6) ) - { - tmp3 = 0; - tmp2++; - } - if ( tmp2 == 0 ) - tmp2 = tmp3 = 1; - /* 1. set mask */ - /* 2. write value to data transfer register */ - /* 3. start the tranfer */ - /* SCT (FracRate) */ - *QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SCT_MASK); - *QSB_RTD = QSB_RTD_TTV_SET(tmp3); - *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SCT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01); - /* SPT (SBV + PN + IntRage) */ - *QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SPT_MASK); - *QSB_RTD = QSB_RTD_TTV_SET(QSB_SPT_SBV_VALID | QSB_SPT_PN_SET(i & 0x01) | QSB_SPT_INTRATE_SET(tmp2)); - *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01); - } - - /* - * set OAM TX queue - */ - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - if ( ppe_dev.port[i].max_connections != 0 ) - { - tmp1 = ((qsb_clk * ppe_dev.qsb.tstepc) >> 1) / ppe_dev.port[i].tx_max_cell_rate; - tmp2 = tmp1 >> 6; /* integer value of Tsb */ - tmp3 = (tmp1 & ((1 << 6) - 1)) + 1; /* fractional part of Tsb */ - /* carry over to integer part (?) */ - if ( tmp3 == (1 << 6) ) - { - tmp3 = 0; - tmp2++; - } - if ( tmp2 == 0 ) - tmp2 = tmp3 = 1; - /* 1. set mask */ - /* 2. write value to data transfer register */ - /* 3. start the tranfer */ - /* SCT (FracRate) */ - *QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SCT_MASK); - *QSB_RTD = QSB_RTD_TTV_SET(tmp3); - *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SCT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01); - - /* SPT (SBV + PN + IntRage) */ - *QSB_RTM = QSB_RTM_DM_SET(QSB_SET_SPT_MASK); - *QSB_RTD = QSB_RTD_TTV_SET(QSB_SPT_SBV_VALID | QSB_SPT_PN_SET(i & 0x01) | QSB_SPT_INTRATE_SET(tmp2)); - *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_SPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(i & 0x01); - } - - /* - * * set OAM TX queue - * */ - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - if ( ppe_dev.port[i].max_connections != 0 ) - for ( j = 0; j < OAM_TX_QUEUE_NUMBER_PER_PORT; j++ ) - { - qsb_qid = ppe_dev.port[i].oam_tx_queue + j; - - /* disable PCR limiter */ - qsb_queue_parameter_table.bit.tp = 0; - /* set WFQ as real time queue */ - qsb_queue_parameter_table.bit.wfqf = 0; - /* disable leaky bucket shaper */ - qsb_queue_vbr_parameter_table.bit.taus = 0; - qsb_queue_vbr_parameter_table.bit.ts = 0; - - /* Queue Parameter Table (QPT) */ - *QSB_RTM = QSB_RTM_DM_SET(QSB_QPT_SET_MASK); - *QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_parameter_table.dword); - *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_QPT) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(qsb_qid); - /* Queue VBR Paramter Table (QVPT) */ - *QSB_RTM = QSB_RTM_DM_SET(QSB_QVPT_SET_MASK); - *QSB_RTD = QSB_RTD_TTV_SET(qsb_queue_vbr_parameter_table.dword); - *QSB_RAMAC = QSB_RAMAC_RW_SET(QSB_RAMAC_RW_WRITE) | QSB_RAMAC_TSEL_SET(QSB_RAMAC_TSEL_VBR) | QSB_RAMAC_LH_SET(QSB_RAMAC_LH_LOW) | QSB_RAMAC_TESEL_SET(qsb_qid); - } -} - -static inline void clear_ppe_dev(void) -{ - int i; - - for (i = 0; i < ppe_dev.dma.tx_total_channel_used; i++ ) - { - int conn = i + QSB_QUEUE_NUMBER_BASE; - int desc_base; - struct sk_buff *skb; - - while(ppe_dev.dma.tx_desc_release_pos[conn] != ppe_dev.dma.tx_desc_alloc_pos[conn]) - { - desc_base = ppe_dev.dma.tx_descriptor_number * (conn - QSB_QUEUE_NUMBER_BASE) + ppe_dev.dma.tx_desc_release_pos[conn]; - if(!ppe_dev.dma.tx_descriptor_base[desc_base].own) - { - skb = ppe_dev.dma.tx_skb_pointers[desc_base]; - atm_free_tx_skb_vcc(skb); - - // pretend PP32 hold owner bit, so that won't be released more than once, so allocation process don't check this bit - ppe_dev.dma.tx_descriptor_base[desc_base].own = 1; - } - if (++ppe_dev.dma.tx_desc_release_pos[conn] == ppe_dev.dma.tx_descriptor_number) - ppe_dev.dma.tx_desc_release_pos[conn] = 0; - } - } - - for (i = ppe_dev.dma.rx_total_channel_used * ppe_dev.dma.rx_descriptor_number - 1; i >= 0; i--) - dev_kfree_skb_any(*(struct sk_buff **)(((ppe_dev.dma.rx_descriptor_base[i].dataptr << 2) | KSEG0) - 4)); - - kfree(ppe_dev.dma.tx_skb_pointers); - kfree(ppe_dev.dma.tx_descriptor_addr); - kfree(ppe_dev.dma.rx_descriptor_addr); -} - -static inline int init_ppe_dev(void) -{ - int i, j; - int rx_desc, tx_desc; - int conn; - int oam_tx_queue; -#if !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS - int rx_dma_channel_base; - int rx_dma_channel_assigned; -#endif // !defined(ENABLE_RX_QOS) || !ENABLE_RX_QOS - - struct rx_descriptor rx_descriptor = { own: 1, - c: 0, - sop: 1, - eop: 1, - res1: 0, - byteoff:0, - res2: 0, - id: 0, - err: 0, - datalen:0, - res3: 0, - dataptr:0}; - - struct tx_descriptor tx_descriptor = { own: 1, // pretend it's hold by PP32 - c: 0, - sop: 1, - eop: 1, - byteoff:0, - res1: 0, - iscell: 0, - clp: 0, - datalen:0, - res2: 0, - dataptr:0}; - - memset(&ppe_dev, 0, sizeof(ppe_dev)); - - /* - * Setup AAL5 members, buffer size must be larger than max packet size plus overhead. - */ - ppe_dev.aal5.padding_byte = (u8)aal5_fill_pattern; - ppe_dev.aal5.rx_max_packet_size = (u32)aal5r_max_packet_size; - ppe_dev.aal5.rx_min_packet_size = (u32)aal5r_min_packet_size; - ppe_dev.aal5.rx_buffer_size = ((u32)(aal5r_max_packet_size > CELL_SIZE ? aal5r_max_packet_size + MAX_RX_FRAME_EXTRA_BYTES : CELL_SIZE + MAX_RX_FRAME_EXTRA_BYTES) + DMA_ALIGNMENT - 1) & ~(DMA_ALIGNMENT - 1); - ppe_dev.aal5.tx_max_packet_size = (u32)aal5s_max_packet_size; - ppe_dev.aal5.tx_min_packet_size = (u32)aal5s_min_packet_size; - ppe_dev.aal5.tx_buffer_size = ((u32)(aal5s_max_packet_size > CELL_SIZE ? aal5s_max_packet_size + MAX_TX_FRAME_EXTRA_BYTES : CELL_SIZE + MAX_TX_FRAME_EXTRA_BYTES) + DMA_ALIGNMENT - 1) & ~(DMA_ALIGNMENT - 1); - ppe_dev.aal5.rx_drop_error_packet = aal5r_drop_error_packet ? 1 : 0; - - /* - * Setup QSB members, please refer to Amazon spec 15.4 to get the value calculation formula. - */ - ppe_dev.qsb.tau = (u32)qsb_tau; - ppe_dev.qsb.tstepc = (u32)qsb_tstep; - ppe_dev.qsb.sbl = (u32)qsb_srvm; - - /* - * Setup port, connection, other members. - */ - conn = 0; - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - { - /* first connection ID of port */ - ppe_dev.port[i].connection_base = conn + QSB_QUEUE_NUMBER_BASE; - /* max number of connections of port */ - ppe_dev.port[i].max_connections = (u32)port_max_connection[i]; - /* max cell rate the port has */ - ppe_dev.port[i].tx_max_cell_rate = (u32)port_cell_rate_up[i]; - - /* link connection ID to port ID */ - for ( j = port_max_connection[i] - 1; j >= 0; j-- ) - ppe_dev.connection[conn++ + QSB_QUEUE_NUMBER_BASE].port = i; - } - /* total connection numbers of all ports */ - ppe_dev.max_connections = conn; - /* OAM RX queue ID, which is the first available connection ID after */ - /* connections assigned to ports. */ - ppe_dev.oam_rx_queue = conn + QSB_QUEUE_NUMBER_BASE; - -#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS - oam_tx_queue = conn; - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - if ( port_max_connection[i] != 0 ) - { - ppe_dev.port[i].oam_tx_queue = oam_tx_queue + QSB_QUEUE_NUMBER_BASE; - - for ( j = 0; j < OAM_TX_QUEUE_NUMBER_PER_PORT; j++ ) - /* Since connection ID is one to one mapped to RX/TX queue ID, the connection */ - /* structure must be reserved for OAM RX/TX queues, and member "port" is set */ - /* according to port to which OAM TX queue is connected. */ - ppe_dev.connection[oam_tx_queue++ + QSB_QUEUE_NUMBER_BASE].port = i; - } - /* DMA RX channel assigned to OAM RX queue */ - ppe_dev.oam_rx_dma_channel = RX_DMA_CH_OAM; - /* DMA RX channel will be assigned dynamically when VCC is open. */ -#else // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS - rx_dma_channel_base = 0; - oam_tx_queue = conn; - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - if ( port_max_connection[i] != 0 ) - { - /* Calculate the number of DMA RX channels could be assigned to port. */ - rx_dma_channel_assigned = i == ATM_PORT_NUMBER - 1 - ? (MAX_RX_DMA_CHANNEL_NUMBER - OAM_RX_DMA_CHANNEL_NUMBER) - rx_dma_channel_base - : (ppe_dev.port[i].max_connections * (MAX_RX_DMA_CHANNEL_NUMBER - OAM_RX_DMA_CHANNEL_NUMBER) + ppe_dev.max_connections / 2) / ppe_dev.max_connections; - /* Amend the number, which could be zero. */ - if ( rx_dma_channel_assigned == 0 ) - rx_dma_channel_assigned = 1; - /* Calculate the first DMA RX channel ID could be assigned to port. */ - if ( rx_dma_channel_base + rx_dma_channel_assigned > MAX_RX_DMA_CHANNEL_NUMBER - OAM_RX_DMA_CHANNEL_NUMBER ) - rx_dma_channel_base = MAX_RX_DMA_CHANNEL_NUMBER - OAM_RX_DMA_CHANNEL_NUMBER - rx_dma_channel_assigned; - - /* first DMA RX channel ID */ - ppe_dev.port[i].rx_dma_channel_base = rx_dma_channel_base; - /* number of DMA RX channels assigned to this port */ - ppe_dev.port[i].rx_dma_channel_assigned = rx_dma_channel_assigned; - /* OAM TX queue ID, which must be assigned after connections assigned to ports */ - ppe_dev.port[i].oam_tx_queue = oam_tx_queue + QSB_QUEUE_NUMBER_BASE; - - rx_dma_channel_base += rx_dma_channel_assigned; - - for ( j = 0; j < OAM_TX_QUEUE_NUMBER_PER_PORT; j++ ) - /* Since connection ID is one to one mapped to RX/TX queue ID, the connection */ - /* structure must be reserved for OAM RX/TX queues, and member "port" is set */ - /* according to port to which OAM TX queue is connected. */ - ppe_dev.connection[oam_tx_queue++ + QSB_QUEUE_NUMBER_BASE].port = i; - } - /* DMA RX channel assigned to OAM RX queue */ - ppe_dev.oam_rx_dma_channel = rx_dma_channel_base; - - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - for ( j = 0; j < port_max_connection[i]; j++ ) - /* Assign DMA RX channel to RX queues. One channel could be assigned to more than one queue. */ - ppe_dev.connection[ppe_dev.port[i].connection_base + j].rx_dma_channel = ppe_dev.port[i].rx_dma_channel_base + j % ppe_dev.port[i].rx_dma_channel_assigned; -#endif // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS - - /* initialize semaphore used by open and close */ - sema_init(&ppe_dev.sem, 1); - /* descriptor number of RX DMA channel */ - ppe_dev.dma.rx_descriptor_number = dma_rx_descriptor_length; - /* descriptor number of TX DMA channel */ - ppe_dev.dma.tx_descriptor_number = dma_tx_descriptor_length; - /* If used descriptors are more than this value, cell with CLP1 is dropped. */ - ppe_dev.dma.rx_clp1_desc_threshold = dma_rx_clp1_descriptor_threshold; - - /* delay on descriptor write path */ - ppe_dev.dma.write_descriptor_delay = write_descriptor_delay; - - /* total DMA RX channel used */ -#if defined(ENABLE_RX_QOS) && ENABLE_RX_QOS - ppe_dev.dma.rx_total_channel_used = RX_DMA_CH_TOTAL; -#else - ppe_dev.dma.rx_total_channel_used = rx_dma_channel_base + OAM_RX_DMA_CHANNEL_NUMBER; -#endif // defined(ENABLE_RX_QOS) && ENABLE_RX_QOS - /* total DMA TX channel used (exclude channel reserved by QSB) */ - ppe_dev.dma.tx_total_channel_used = oam_tx_queue; - - /* allocate memory for RX descriptors */ - ppe_dev.dma.rx_descriptor_addr = kmalloc(ppe_dev.dma.rx_total_channel_used * ppe_dev.dma.rx_descriptor_number * sizeof(struct rx_descriptor) + 4, GFP_KERNEL | GFP_DMA); - if ( !ppe_dev.dma.rx_descriptor_addr ) - goto RX_DESCRIPTOR_BASE_ALLOCATE_FAIL; - /* do alignment (DWORD) */ - ppe_dev.dma.rx_descriptor_base = (struct rx_descriptor *)(((u32)ppe_dev.dma.rx_descriptor_addr + 0x03) & ~0x03); - ppe_dev.dma.rx_descriptor_base = (struct rx_descriptor *)((u32)ppe_dev.dma.rx_descriptor_base | KSEG1); // no cache - - /* allocate memory for TX descriptors */ - ppe_dev.dma.tx_descriptor_addr = kmalloc(ppe_dev.dma.tx_total_channel_used * ppe_dev.dma.tx_descriptor_number * sizeof(struct tx_descriptor) + 4, GFP_KERNEL | GFP_DMA); - if ( !ppe_dev.dma.tx_descriptor_addr ) - goto TX_DESCRIPTOR_BASE_ALLOCATE_FAIL; - /* do alignment (DWORD) */ - ppe_dev.dma.tx_descriptor_base = (struct tx_descriptor *)(((u32)ppe_dev.dma.tx_descriptor_addr + 0x03) & ~0x03); - ppe_dev.dma.tx_descriptor_base = (struct tx_descriptor *)((u32)ppe_dev.dma.tx_descriptor_base | KSEG1); // no cache - /* allocate pointers to TX sk_buff */ - ppe_dev.dma.tx_skb_pointers = kmalloc(ppe_dev.dma.tx_total_channel_used * ppe_dev.dma.tx_descriptor_number * sizeof(struct sk_buff *), GFP_KERNEL); - if ( !ppe_dev.dma.tx_skb_pointers ) - goto TX_SKB_POINTER_ALLOCATE_FAIL; - memset(ppe_dev.dma.tx_skb_pointers, 0, ppe_dev.dma.tx_total_channel_used * ppe_dev.dma.tx_descriptor_number * sizeof(struct sk_buff *)); - - /* Allocate RX sk_buff and fill up RX descriptors. */ - rx_descriptor.datalen = ppe_dev.aal5.rx_buffer_size; - for ( rx_desc = ppe_dev.dma.rx_total_channel_used * ppe_dev.dma.rx_descriptor_number - 1; rx_desc >= 0; rx_desc-- ) - { - struct sk_buff *skb; - skb = alloc_skb_rx(); - if ( skb == NULL ) - panic("sk buffer is used up\n"); - rx_descriptor.dataptr = (u32)skb->data >> 2; - ppe_dev.dma.rx_descriptor_base[rx_desc] = rx_descriptor; - - } - - /* Fill up TX descriptors. */ - tx_descriptor.datalen = ppe_dev.aal5.tx_buffer_size; - for ( tx_desc = ppe_dev.dma.tx_total_channel_used * ppe_dev.dma.tx_descriptor_number - 1; tx_desc >= 0; tx_desc-- ) - ppe_dev.dma.tx_descriptor_base[tx_desc] = tx_descriptor; - - return 0; - -TX_SKB_POINTER_ALLOCATE_FAIL: - kfree(ppe_dev.dma.tx_descriptor_addr); -TX_DESCRIPTOR_BASE_ALLOCATE_FAIL: - kfree(ppe_dev.dma.rx_descriptor_addr); -RX_DESCRIPTOR_BASE_ALLOCATE_FAIL: - return -ENOMEM; -} - - -static inline void clear_share_buffer(void) -{ - volatile u32 *p = SB_RAM0_ADDR(0); - unsigned int i; - - /* write all zeros only */ - for ( i = 0; i < SB_RAM0_DWLEN + SB_RAM1_DWLEN + SB_RAM2_DWLEN + SB_RAM3_DWLEN; i++ ) - *p++ = 0; -} - - -static inline void check_parameters(void) -{ - int i; - int enabled_port_number; - int unassigned_queue_number; - int assigned_queue_number; - - enabled_port_number = 0; - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - if ( port_max_connection[i] < 1 ) - port_max_connection[i] = 0; - else - enabled_port_number++; - /* If the max connection number of a port is not 0, the port is enabled */ - /* and at lease two connection ID must be reserved for this port. One of */ - /* them is used as OAM TX path. */ - unassigned_queue_number = MAX_QUEUE_NUMBER - QSB_QUEUE_NUMBER_BASE; - for ( i = 0; i < ATM_PORT_NUMBER; i++ ) - if ( port_max_connection[i] > 0 ) - { - enabled_port_number--; - assigned_queue_number = unassigned_queue_number - enabled_port_number * (1 + OAM_TX_QUEUE_NUMBER_PER_PORT) - OAM_TX_QUEUE_NUMBER_PER_PORT; - if ( assigned_queue_number > MAX_QUEUE_NUMBER_PER_PORT - OAM_TX_QUEUE_NUMBER_PER_PORT ) - assigned_queue_number = MAX_QUEUE_NUMBER_PER_PORT - OAM_TX_QUEUE_NUMBER_PER_PORT; - if ( port_max_connection[i] > assigned_queue_number ) - { - port_max_connection[i] = assigned_queue_number; - unassigned_queue_number -= assigned_queue_number; - } - else - unassigned_queue_number -= port_max_connection[i]; - } - - /* Please refer to Amazon spec 15.4 for setting these values. */ - if ( qsb_tau < 1 ) - qsb_tau = 1; - if ( qsb_tstep < 1 ) - qsb_tstep = 1; - else if ( qsb_tstep > 4 ) - qsb_tstep = 4; - else if ( qsb_tstep == 3 ) - qsb_tstep = 2; - - /* There is a delay between PPE write descriptor and descriptor is */ - /* really stored in memory. Host also has this delay when writing */ - /* descriptor. So PPE will use this value to determine if the write */ - /* operation makes effect. */ - if ( write_descriptor_delay < 0 ) - write_descriptor_delay = 0; - - if ( aal5_fill_pattern < 0 ) - aal5_fill_pattern = 0; - else - aal5_fill_pattern &= 0xFF; - - /* Because of the limitation of length field in descriptors, the packet */ - /* size could not be larger than 64K minus overhead size. */ - if ( aal5r_max_packet_size < 0 ) - aal5r_max_packet_size = 0; - else if ( aal5r_max_packet_size >= 65536 - MAX_RX_FRAME_EXTRA_BYTES ) - aal5r_max_packet_size = 65536 - MAX_RX_FRAME_EXTRA_BYTES; - if ( aal5r_min_packet_size < 0 ) - aal5r_min_packet_size = 0; - else if ( aal5r_min_packet_size > aal5r_max_packet_size ) - aal5r_min_packet_size = aal5r_max_packet_size; - if ( aal5s_max_packet_size < 0 ) - aal5s_max_packet_size = 0; - else if ( aal5s_max_packet_size >= 65536 - MAX_TX_FRAME_EXTRA_BYTES ) - aal5s_max_packet_size = 65536 - MAX_TX_FRAME_EXTRA_BYTES; - if ( aal5s_min_packet_size < 0 ) - aal5s_min_packet_size = 0; - else if ( aal5s_min_packet_size > aal5s_max_packet_size ) - aal5s_min_packet_size = aal5s_max_packet_size; - - if ( dma_rx_descriptor_length < 2 ) - dma_rx_descriptor_length = 2; - if ( dma_tx_descriptor_length < 2 ) - dma_tx_descriptor_length = 2; - if ( dma_rx_clp1_descriptor_threshold < 0 ) - dma_rx_clp1_descriptor_threshold = 0; - else if ( dma_rx_clp1_descriptor_threshold > dma_rx_descriptor_length ) - dma_rx_clp1_descriptor_threshold = dma_rx_descriptor_length; -} - -static struct atmdev_ops ppe_atm_ops = { - owner: THIS_MODULE, - open: ppe_open, - close: ppe_close, - ioctl: ppe_ioctl, - send: ppe_send, - send_oam: ppe_send_oam, - change_qos: ppe_change_qos, -}; - -int __init danube_ppe_init(void) -{ - int ret; - int port_num; - - check_parameters(); - - ret = init_ppe_dev(); - if ( ret ) - goto INIT_PPE_DEV_FAIL; - - clear_share_buffer(); - init_rx_tables(); - init_tx_tables(); -printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__); - - for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ ) - if ( ppe_dev.port[port_num].max_connections != 0 ) - { - printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__); - ppe_dev.port[port_num].dev = atm_dev_register("danube_atm", &ppe_atm_ops, -1, 0UL); - if ( !ppe_dev.port[port_num].dev ) - { - printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__); - ret = -EIO; - goto ATM_DEV_REGISTER_FAIL; - } - else - { - printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__); - ppe_dev.port[port_num].dev->ci_range.vpi_bits = 8; - ppe_dev.port[port_num].dev->ci_range.vci_bits = 16; - ppe_dev.port[port_num].dev->link_rate = ppe_dev.port[port_num].tx_max_cell_rate; - ppe_dev.port[port_num].dev->dev_data = (void*)port_num; - } - } - /* register interrupt handler */ - ret = request_irq(IFXMIPS_PPE_MBOX_INT, mailbox_irq_handler, IRQF_DISABLED, "ppe_mailbox_isr", NULL); - if ( ret ) - { - if ( ret == -EBUSY ) - printk("ppe: IRQ may be occupied by ETH2 driver, please reconfig to disable it.\n"); - goto REQUEST_IRQ_IFXMIPS_PPE_MBOX_INT_FAIL; - } - disable_irq(IFXMIPS_PPE_MBOX_INT); - - #if defined(CONFIG_PCI) && defined(USE_FIX_FOR_PCI_PPE) && USE_FIX_FOR_PCI_PPE - ret = request_irq(PPE_MAILBOX_IGU0_INT, pci_fix_irq_handler, SA_INTERRUPT, "ppe_pci_fix_isr", NULL); - if ( ret ) - printk("failed in registering mailbox 0 interrupt (pci fix)\n"); - #endif // defined(CONFIG_PCI) && defined(USE_FIX_FOR_PCI_PPE) && USE_FIX_FOR_PCI_PPE - - ret = pp32_start(); - if ( ret ) - goto PP32_START_FAIL; - - qsb_global_set(); - HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 1; - HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 1; - HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 1; - - /* create proc file */ - proc_file_create(); - - printk("ppe: ATM init succeeded (firmware version 1.1.0.2.1.13\n"); - return 0; - -PP32_START_FAIL: - - free_irq(IFXMIPS_PPE_MBOX_INT, NULL); -REQUEST_IRQ_IFXMIPS_PPE_MBOX_INT_FAIL: -ATM_DEV_REGISTER_FAIL: - clear_ppe_dev(); -INIT_PPE_DEV_FAIL: - printk("ppe: ATM init failed\n"); - return ret; -} - -void __exit danube_ppe_exit(void) -{ - int port_num; - register int l; - proc_file_delete(); - HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 0; - HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 0; - HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 0; - /* idle for a while to finish running HTU search */ - for (l = 0; l < IDLE_CYCLE_NUMBER; l++ ); - pp32_stop(); - free_irq(IFXMIPS_PPE_MBOX_INT, NULL); - for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ ) - if ( ppe_dev.port[port_num].max_connections != 0 ) - atm_dev_deregister(ppe_dev.port[port_num].dev); - clear_ppe_dev(); -} - -module_init(danube_ppe_init); -module_exit(danube_ppe_exit); - -MODULE_LICENSE("GPL"); - |