source: trunk/package/ifxmips-dsl-api/src/ifxmips_atm_core.c @ 18259

Last change on this file since 18259 was 18259, checked in by blogic, 7 years ago

[ifxmips] adds dsl support, thank you infineon/lantiq

File size: 81.8 KB
Line 
1/******************************************************************************
2**
3** FILE NAME    : ifxmips_atm_core.c
4** PROJECT      : UEIP
5** MODULES      : ATM
6**
7** DATE         : 7 Jul 2009
8** AUTHOR       : Xu Liang
9** DESCRIPTION  : ATM driver common source file (core functions)
10** COPYRIGHT    :       Copyright (c) 2006
11**                      Infineon Technologies AG
12**                      Am Campeon 1-12, 85579 Neubiberg, Germany
13**
14**    This program is free software; you can redistribute it and/or modify
15**    it under the terms of the GNU General Public License as published by
16**    the Free Software Foundation; either version 2 of the License, or
17**    (at your option) any later version.
18**
19** HISTORY
20** $Date        $Author         $Comment
21** 07 JUL 2009  Xu Liang        Init Version
22*******************************************************************************/
23
24
25
26/*
27 * ####################################
28 *              Version No.
29 * ####################################
30 */
31
32#define IFX_ATM_VER_MAJOR               1
33#define IFX_ATM_VER_MID                 0
34#define IFX_ATM_VER_MINOR               8
35
36
37
38/*
39 * ####################################
40 *              Head File
41 * ####################################
42 */
43
44/*
45 *  Common Head File
46 */
47#include <linux/kernel.h>
48#include <linux/module.h>
49#include <linux/version.h>
50#include <linux/types.h>
51#include <linux/errno.h>
52#include <linux/proc_fs.h>
53#include <linux/init.h>
54#include <linux/ioctl.h>
55#include <linux/atmdev.h>
56#include <linux/atm.h>
57
58/*
59 *  Chip Specific Head File
60 */
61#include <asm/ifx/ifx_types.h>
62#include <asm/ifx/ifx_regs.h>
63#include <asm/ifx/common_routines.h>
64#include "ifxmips_atm_core.h"
65
66
67
68/*
69 * ####################################
70 *        Kernel Version Adaption
71 * ####################################
72 */
73#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
74  #define MODULE_PARM_ARRAY(a, b)   module_param_array(a, int, NULL, 0)
75  #define MODULE_PARM(a, b)         module_param(a, int, 0)
76#else
77  #define MODULE_PARM_ARRAY(a, b)   MODULE_PARM(a, b)
78#endif
79
80
81
82/*!
83  \addtogroup IFXMIPS_ATM_MODULE_PARAMS
84 */
85/*@{*/
86/*
87 * ####################################
88 *   Parameters to Configure PPE
89 * ####################################
90 */
91/*!
92  \brief QSB cell delay variation due to concurrency
93 */
94static int qsb_tau   = 1;                       /*  QSB cell delay variation due to concurrency     */
95/*!
96  \brief QSB scheduler burst length
97 */
98static int qsb_srvm  = 0x0F;                    /*  QSB scheduler burst length                      */
99/*!
100  \brief QSB time step, all legal values are 1, 2, 4
101 */
102static int qsb_tstep = 4 ;                      /*  QSB time step, all legal values are 1, 2, 4     */
103
104/*!
105  \brief Write descriptor delay
106 */
107static int write_descriptor_delay  = 0x20;      /*  Write descriptor delay                          */
108
109/*!
110  \brief AAL5 padding byte ('~')
111 */
112static int aal5_fill_pattern       = 0x007E;    /*  AAL5 padding byte ('~')                         */
113/*!
114  \brief Max frame size for RX
115 */
116static int aal5r_max_packet_size   = 0x0700;    /*  Max frame size for RX                           */
117/*!
118  \brief Min frame size for RX
119 */
120static int aal5r_min_packet_size   = 0x0000;    /*  Min frame size for RX                           */
121/*!
122  \brief Max frame size for TX
123 */
124static int aal5s_max_packet_size   = 0x0700;    /*  Max frame size for TX                           */
125/*!
126  \brief Min frame size for TX
127 */
128static int aal5s_min_packet_size   = 0x0000;    /*  Min frame size for TX                           */
129/*!
130  \brief Drop error packet in RX path
131 */
132static int aal5r_drop_error_packet = 1;         /*  Drop error packet in RX path                    */
133
134/*!
135  \brief Number of descriptors per DMA RX channel
136 */
137static int dma_rx_descriptor_length = 128;      /*  Number of descriptors per DMA RX channel        */
138/*!
139  \brief Number of descriptors per DMA TX channel
140 */
141static int dma_tx_descriptor_length = 64;       /*  Number of descriptors per DMA TX channel        */
142/*!
143  \brief PPE core clock cycles between descriptor write and effectiveness in external RAM
144 */
145static int dma_rx_clp1_descriptor_threshold = 38;
146/*@}*/
147
148MODULE_PARM(qsb_tau, "i");
149MODULE_PARM_DESC(qsb_tau, "Cell delay variation. Value must be > 0");
150MODULE_PARM(qsb_srvm, "i");
151MODULE_PARM_DESC(qsb_srvm, "Maximum burst size");
152MODULE_PARM(qsb_tstep, "i");
153MODULE_PARM_DESC(qsb_tstep, "n*32 cycles per sbs cycles n=1,2,4");
154
155MODULE_PARM(write_descriptor_delay, "i");
156MODULE_PARM_DESC(write_descriptor_delay, "PPE core clock cycles between descriptor write and effectiveness in external RAM");
157
158MODULE_PARM(aal5_fill_pattern, "i");
159MODULE_PARM_DESC(aal5_fill_pattern, "Filling pattern (PAD) for AAL5 frames");
160MODULE_PARM(aal5r_max_packet_size, "i");
161MODULE_PARM_DESC(aal5r_max_packet_size, "Max packet size in byte for downstream AAL5 frames");
162MODULE_PARM(aal5r_min_packet_size, "i");
163MODULE_PARM_DESC(aal5r_min_packet_size, "Min packet size in byte for downstream AAL5 frames");
164MODULE_PARM(aal5s_max_packet_size, "i");
165MODULE_PARM_DESC(aal5s_max_packet_size, "Max packet size in byte for upstream AAL5 frames");
166MODULE_PARM(aal5s_min_packet_size, "i");
167MODULE_PARM_DESC(aal5s_min_packet_size, "Min packet size in byte for upstream AAL5 frames");
168MODULE_PARM(aal5r_drop_error_packet, "i");
169MODULE_PARM_DESC(aal5r_drop_error_packet, "Non-zero value to drop error packet for downstream");
170
171MODULE_PARM(dma_rx_descriptor_length, "i");
172MODULE_PARM_DESC(dma_rx_descriptor_length, "Number of descriptor assigned to DMA RX channel (>16)");
173MODULE_PARM(dma_tx_descriptor_length, "i");
174MODULE_PARM_DESC(dma_tx_descriptor_length, "Number of descriptor assigned to DMA TX channel (>16)");
175MODULE_PARM(dma_rx_clp1_descriptor_threshold, "i");
176MODULE_PARM_DESC(dma_rx_clp1_descriptor_threshold, "Descriptor threshold for cells with cell loss priority 1");
177
178
179
180/*
181 * ####################################
182 *              Definition
183 * ####################################
184 */
185
186#define DUMP_SKB_LEN                          ~0
187
188
189
190/*
191 * ####################################
192 *             Declaration
193 * ####################################
194 */
195
196/*
197 *  Network Operations
198 */
199static int ppe_ioctl(struct atm_dev *, unsigned int, void *);
200static int ppe_open(struct atm_vcc *);
201static void ppe_close(struct atm_vcc *);
202static int ppe_send(struct atm_vcc *, struct sk_buff *);
203static int ppe_send_oam(struct atm_vcc *, void *, int);
204static int ppe_change_qos(struct atm_vcc *, struct atm_qos *, int);
205
206/*
207 *  ADSL LED
208 */
209static INLINE int adsl_led_flash(void);
210
211/*
212 *  64-bit operation used by MIB calculation
213 */
214static INLINE void u64_add_u32(ppe_u64_t, unsigned int, ppe_u64_t *);
215
216/*
217 *  buffer manage functions
218 */
219static INLINE struct sk_buff* alloc_skb_rx(void);
220static INLINE struct sk_buff* alloc_skb_tx(unsigned int);
221struct sk_buff* atm_alloc_tx(struct atm_vcc *, unsigned int);
222static INLINE void atm_free_tx_skb_vcc(struct sk_buff *, struct atm_vcc *);
223static INLINE struct sk_buff *get_skb_rx_pointer(unsigned int);
224static INLINE int get_tx_desc(unsigned int);
225
226/*
227 *  mailbox handler and signal function
228 */
229static INLINE void mailbox_oam_rx_handler(void);
230static INLINE void mailbox_aal_rx_handler(void);
231#if defined(ENABLE_TASKLET) && ENABLE_TASKLET
232  static void do_ppe_tasklet(unsigned long);
233#endif
234static irqreturn_t mailbox_irq_handler(int, void *);
235static INLINE void mailbox_signal(unsigned int, int);
236
237/*
238 *  QSB & HTU setting functions
239 */
240static void set_qsb(struct atm_vcc *, struct atm_qos *, unsigned int);
241static void qsb_global_set(void);
242static INLINE void set_htu_entry(unsigned int, unsigned int, unsigned int, int, int);
243static INLINE void clear_htu_entry(unsigned int);
244static void validate_oam_htu_entry(void);
245static void invalidate_oam_htu_entry(void);
246
247/*
248 *  look up for connection ID
249 */
250static INLINE int find_vpi(unsigned int);
251static INLINE int find_vpivci(unsigned int, unsigned int);
252static INLINE int find_vcc(struct atm_vcc *);
253
254/*
255 *  Debug Functions
256 */
257#if defined(DEBUG_DUMP_SKB) && DEBUG_DUMP_SKB
258  static void dump_skb(struct sk_buff *, u32, char *, int, int, int);
259#else
260  #define dump_skb(skb, len, title, port, ch, is_tx)    do {} while (0)
261#endif
262
263/*
264 *  Proc File Functions
265 */
266static INLINE void proc_file_create(void);
267static INLINE void proc_file_delete(void);
268static int proc_read_version(char *, char **, off_t, int, int *, void *);
269static int proc_read_mib(char *, char **, off_t, int, int *, void *);
270static int proc_write_mib(struct file *, const char *, unsigned long, void *);
271#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
272  static int proc_read_dbg(char *, char **, off_t, int, int *, void *);
273  static int proc_write_dbg(struct file *, const char *, unsigned long, void *);
274#endif
275#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC
276  static int proc_read_htu(char *, char **, off_t, int, int *, void *);
277  static int proc_read_txq(char *, char **, off_t, int, int *, void *);
278#endif
279
280/*
281 *  Proc Help Functions
282 */
283static int stricmp(const char *, const char *);
284#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
285  static int strincmp(const char *, const char *, int);
286#endif
287static INLINE int ifx_atm_version(char *);
288//static INLINE int print_reset_domain(char *, int);
289//static INLINE int print_reset_handler(char *, int, ifx_rcu_handler_t *);
290
291/*
292 *  Init & clean-up functions
293 */
294#ifdef MODULE
295  static INLINE void reset_ppe(void);
296#endif
297static INLINE void check_parameters(void);
298static INLINE int init_priv_data(void);
299static INLINE void clear_priv_data(void);
300static INLINE void init_rx_tables(void);
301static INLINE void init_tx_tables(void);
302
303/*
304 *  Exteranl Function
305 */
306#if defined(CONFIG_IFX_OAM) || defined(CONFIG_IFX_OAM_MODULE)
307  extern void ifx_push_oam(unsigned char *);
308#else
309  static inline void ifx_push_oam(unsigned char *dummy) {}
310#endif
311#if defined(CONFIG_IFXMIPS_DSL_CPE_MEI) || defined(CONFIG_IFXMIPS_DSL_CPE_MEI_MODULE)
312  extern int ifx_mei_atm_led_blink(void);
313  extern int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr);
314#else
315  static inline int ifx_mei_atm_led_blink(void) { return IFX_SUCCESS; }
316  static inline int ifx_mei_atm_showtime_check(int *is_showtime, struct port_cell_info *port_cell, void **xdata_addr)
317  {
318    if ( is_showtime != NULL )
319        *is_showtime = 0;
320    return IFX_SUCCESS;
321  }
322#endif
323
324/*
325 *  External variable
326 */
327extern struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int);
328#if defined(CONFIG_IFXMIPS_DSL_CPE_MEI) || defined(CONFIG_IFXMIPS_DSL_CPE_MEI_MODULE)
329  extern int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *);
330  extern int (*ifx_mei_atm_showtime_exit)(void);
331#else
332  int (*ifx_mei_atm_showtime_enter)(struct port_cell_info *, void *) = NULL;
333  EXPORT_SYMBOL(ifx_mei_atm_showtime_enter);
334  int (*ifx_mei_atm_showtime_exit)(void) = NULL;
335  EXPORT_SYMBOL(ifx_mei_atm_showtime_exit);
336#endif
337
338
339
340/*
341 * ####################################
342 *            Local Variable
343 * ####################################
344 */
345
346static struct atm_priv_data g_atm_priv_data;
347
348static struct atmdev_ops g_ifx_atm_ops = {
349    .open       = ppe_open,
350    .close      = ppe_close,
351    .ioctl      = ppe_ioctl,
352    .send       = ppe_send,
353    .send_oam   = ppe_send_oam,
354    .change_qos = ppe_change_qos,
355    .owner      = THIS_MODULE,
356};
357
358#if defined(ENABLE_TASKLET) && ENABLE_TASKLET
359  DECLARE_TASKLET(g_dma_tasklet, do_ppe_tasklet, 0);
360#endif
361
362static int g_showtime = 0;
363static void *g_xdata_addr = NULL;
364
365unsigned int ifx_atm_dbg_enable = 0;
366
367static struct proc_dir_entry* g_atm_dir = NULL;
368
369
370
371/*
372 * ####################################
373 *            Local Function
374 * ####################################
375 */
376
377static int ppe_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg)
378{
379    int ret = 0;
380    atm_cell_ifEntry_t mib_cell;
381    atm_aal5_ifEntry_t mib_aal5;
382    atm_aal5_vcc_x_t mib_vcc;
383    unsigned int value;
384    int conn;
385
386    if ( _IOC_TYPE(cmd) != PPE_ATM_IOC_MAGIC
387        || _IOC_NR(cmd) >= PPE_ATM_IOC_MAXNR )
388        return -ENOTTY;
389
390    if ( _IOC_DIR(cmd) & _IOC_READ )
391        ret = !access_ok(VERIFY_WRITE, arg, _IOC_SIZE(cmd));
392    else if ( _IOC_DIR(cmd) & _IOC_WRITE )
393        ret = !access_ok(VERIFY_READ, arg, _IOC_SIZE(cmd));
394    if ( ret )
395        return -EFAULT;
396
397    switch ( cmd )
398    {
399    case PPE_ATM_MIB_CELL:  /*  cell level  MIB */
400        /*  These MIB should be read at ARC side, now put zero only.    */
401        mib_cell.ifHCInOctets_h = 0;
402        mib_cell.ifHCInOctets_l = 0;
403        mib_cell.ifHCOutOctets_h = 0;
404        mib_cell.ifHCOutOctets_l = 0;
405        mib_cell.ifInErrors = 0;
406        mib_cell.ifInUnknownProtos = WAN_MIB_TABLE->wrx_drophtu_cell;
407        mib_cell.ifOutErrors = 0;
408
409        ret = sizeof(mib_cell) - copy_to_user(arg, &mib_cell, sizeof(mib_cell));
410        break;
411
412    case PPE_ATM_MIB_AAL5:  /*  AAL5 MIB    */
413        value = WAN_MIB_TABLE->wrx_total_byte;
414        u64_add_u32(g_atm_priv_data.wrx_total_byte, value - g_atm_priv_data.prev_wrx_total_byte, &g_atm_priv_data.wrx_total_byte);
415        g_atm_priv_data.prev_wrx_total_byte = value;
416        mib_aal5.ifHCInOctets_h = g_atm_priv_data.wrx_total_byte.h;
417        mib_aal5.ifHCInOctets_l = g_atm_priv_data.wrx_total_byte.l;
418
419        value = WAN_MIB_TABLE->wtx_total_byte;
420        u64_add_u32(g_atm_priv_data.wtx_total_byte, value - g_atm_priv_data.prev_wtx_total_byte, &g_atm_priv_data.wtx_total_byte);
421        g_atm_priv_data.prev_wtx_total_byte = value;
422        mib_aal5.ifHCOutOctets_h = g_atm_priv_data.wtx_total_byte.h;
423        mib_aal5.ifHCOutOctets_l = g_atm_priv_data.wtx_total_byte.l;
424
425        mib_aal5.ifInUcastPkts  = g_atm_priv_data.wrx_pdu;
426        mib_aal5.ifOutUcastPkts = WAN_MIB_TABLE->wtx_total_pdu;
427        mib_aal5.ifInErrors     = WAN_MIB_TABLE->wrx_err_pdu;
428        mib_aal5.ifInDiscards   = WAN_MIB_TABLE->wrx_dropdes_pdu + g_atm_priv_data.wrx_drop_pdu;
429        mib_aal5.ifOutErros     = g_atm_priv_data.wtx_err_pdu;
430        mib_aal5.ifOutDiscards  = g_atm_priv_data.wtx_drop_pdu;
431
432        ret = sizeof(mib_aal5) - copy_to_user(arg, &mib_aal5, sizeof(mib_aal5));
433        break;
434
435    case PPE_ATM_MIB_VCC:   /*  VCC related MIB */
436        copy_from_user(&mib_vcc, arg, sizeof(mib_vcc));
437        conn = find_vpivci(mib_vcc.vpi, mib_vcc.vci);
438        if ( conn >= 0 )
439        {
440            mib_vcc.mib_vcc.aal5VccCrcErrors     = g_atm_priv_data.conn[conn].aal5_vcc_crc_err;
441            mib_vcc.mib_vcc.aal5VccOverSizedSDUs = g_atm_priv_data.conn[conn].aal5_vcc_oversize_sdu;
442            mib_vcc.mib_vcc.aal5VccSarTimeOuts   = 0;   /*  no timer support    */
443            ret = sizeof(mib_vcc) - copy_to_user(arg, &mib_vcc, sizeof(mib_vcc));
444        }
445        else
446            ret = -EINVAL;
447        break;
448
449    default:
450        ret = -ENOIOCTLCMD;
451    }
452
453    return ret;
454}
455
456static int ppe_open(struct atm_vcc *vcc)
457{
458    int ret;
459    short vpi = vcc->vpi;
460    int   vci = vcc->vci;
461    struct port *port = &g_atm_priv_data.port[(int)vcc->dev->dev_data];
462    int conn;
463    int f_enable_irq = 0;
464#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
465    int sys_flag;
466#endif
467
468    if ( vcc->qos.aal != ATM_AAL5 && vcc->qos.aal != ATM_AAL0 )
469        return -EPROTONOSUPPORT;
470
471    /*  check bandwidth */
472    if ( (vcc->qos.txtp.traffic_class == ATM_CBR && vcc->qos.txtp.max_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
473      || (vcc->qos.txtp.traffic_class == ATM_VBR_RT && vcc->qos.txtp.max_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
474      || (vcc->qos.txtp.traffic_class == ATM_VBR_NRT && vcc->qos.txtp.scr > (port->tx_max_cell_rate - port->tx_current_cell_rate))
475      || (vcc->qos.txtp.traffic_class == ATM_UBR_PLUS && vcc->qos.txtp.min_pcr > (port->tx_max_cell_rate - port->tx_current_cell_rate)) )
476    {
477        ret = -EINVAL;
478        goto PPE_OPEN_EXIT;
479    }
480
481    /*  check existing vpi,vci  */
482    conn = find_vpivci(vpi, vci);
483    if ( conn >= 0 ) {
484        ret = -EADDRINUSE;
485        goto PPE_OPEN_EXIT;
486    }
487
488    /*  check whether it need to enable irq */
489    if ( g_atm_priv_data.conn_table == 0 )
490        f_enable_irq = 1;
491
492    /*  allocate connection */
493    for ( conn = 0; conn < MAX_PVC_NUMBER; conn++ ) {
494        if ( test_and_set_bit(conn, &g_atm_priv_data.conn_table) == 0 ) {
495            g_atm_priv_data.conn[conn].vcc = vcc;
496            break;
497        }
498    }
499    if ( conn == MAX_PVC_NUMBER )
500    {
501        ret = -EINVAL;
502        goto PPE_OPEN_EXIT;
503    }
504
505    /*  reserve bandwidth   */
506    switch ( vcc->qos.txtp.traffic_class ) {
507    case ATM_CBR:
508    case ATM_VBR_RT:
509        port->tx_current_cell_rate += vcc->qos.txtp.max_pcr;
510        break;
511    case ATM_VBR_NRT:
512        port->tx_current_cell_rate += vcc->qos.txtp.scr;
513        break;
514    case ATM_UBR_PLUS:
515        port->tx_current_cell_rate += vcc->qos.txtp.min_pcr;
516        break;
517    }
518
519    /*  set qsb */
520    set_qsb(vcc, &vcc->qos, conn);
521
522    /*  update atm_vcc structure    */
523    vcc->itf = (int)vcc->dev->dev_data;
524    vcc->vpi = vpi;
525    vcc->vci = vci;
526    set_bit(ATM_VF_READY, &vcc->flags);
527
528    /*  enable irq  */
529    if (f_enable_irq ) {
530        ifx_atm_alloc_tx = atm_alloc_tx;
531
532        *MBOX_IGU1_ISRC = (1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM);
533        *MBOX_IGU1_IER  = (1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM);
534
535        enable_irq(PPE_MAILBOX_IGU1_INT);
536    }
537
538    /*  set port    */
539    WTX_QUEUE_CONFIG(conn)->sbid = (int)vcc->dev->dev_data;
540
541    /*  set htu entry   */
542    set_htu_entry(vpi, vci, conn, vcc->qos.aal == ATM_AAL5 ? 1 : 0, 0);
543
544#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
545    //  ReTX: occupy second QID
546    local_irq_save(sys_flag);
547    if ( g_retx_htu && vcc->qos.aal == ATM_AAL5 )
548    {
549        int retx_conn = (conn + 8) % 16;    //  ReTX queue
550
551        if ( retx_conn < MAX_PVC_NUMBER && test_and_set_bit(retx_conn, &g_atm_priv_data.conn_table) == 0 ) {
552            g_atm_priv_data.conn[retx_conn].vcc = vcc;
553            set_htu_entry(vpi, vci, retx_conn, vcc->qos.aal == ATM_AAL5 ? 1 : 0, 1);
554        }
555    }
556    local_irq_restore(sys_flag);
557#endif
558
559    ret = 0;
560
561PPE_OPEN_EXIT:
562    return ret;
563}
564
565static void ppe_close(struct atm_vcc *vcc)
566{
567    int conn;
568    struct port *port;
569    struct connection *connection;
570
571    if ( vcc == NULL )
572        return;
573
574    /*  get connection id   */
575    conn = find_vcc(vcc);
576    if ( conn < 0 ) {
577        err("can't find vcc");
578        goto PPE_CLOSE_EXIT;
579    }
580    connection = &g_atm_priv_data.conn[conn];
581    port = &g_atm_priv_data.port[connection->port];
582
583    /*  clear htu   */
584    clear_htu_entry(conn);
585
586    /*  release connection  */
587    clear_bit(conn, &g_atm_priv_data.conn_table);
588    connection->vcc = NULL;
589    connection->aal5_vcc_crc_err = 0;
590    connection->aal5_vcc_oversize_sdu = 0;
591
592    /*  disable irq */
593    if ( g_atm_priv_data.conn_table == 0 ) {
594        disable_irq(PPE_MAILBOX_IGU1_INT);
595        ifx_atm_alloc_tx = NULL;
596    }
597
598    /*  release bandwidth   */
599    switch ( vcc->qos.txtp.traffic_class )
600    {
601    case ATM_CBR:
602    case ATM_VBR_RT:
603        port->tx_current_cell_rate -= vcc->qos.txtp.max_pcr;
604        break;
605    case ATM_VBR_NRT:
606        port->tx_current_cell_rate -= vcc->qos.txtp.scr;
607        break;
608    case ATM_UBR_PLUS:
609        port->tx_current_cell_rate -= vcc->qos.txtp.min_pcr;
610        break;
611    }
612
613PPE_CLOSE_EXIT:
614    return;
615}
616
617static int ppe_send(struct atm_vcc *vcc, struct sk_buff *skb)
618{
619    int ret;
620    int conn;
621    int desc_base;
622    struct tx_descriptor reg_desc = {0};
623
624    if ( vcc == NULL || skb == NULL )
625        return -EINVAL;
626
627    skb_get(skb);
628    atm_free_tx_skb_vcc(skb, vcc);
629
630    conn = find_vcc(vcc);
631    if ( conn < 0 ) {
632        ret = -EINVAL;
633        goto FIND_VCC_FAIL;
634    }
635
636    if ( !g_showtime ) {
637        err("not in showtime");
638        ret = -EIO;
639        goto PPE_SEND_FAIL;
640    }
641
642    if ( vcc->qos.aal == ATM_AAL5 ) {
643        int byteoff;
644        int datalen;
645        struct tx_inband_header *header;
646
647        datalen = skb->len;
648        byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1);
649
650        if ( skb_headroom(skb) < byteoff + TX_INBAND_HEADER_LENGTH ) {
651            struct sk_buff *new_skb;
652
653            new_skb = alloc_skb_tx(datalen);
654            if ( new_skb == NULL ) {
655                err("ALLOC_SKB_TX_FAIL");
656                ret = -ENOMEM;
657                goto PPE_SEND_FAIL;
658            }
659            skb_put(new_skb, datalen);
660            memcpy(new_skb->data, skb->data, datalen);
661            dev_kfree_skb_any(skb);
662            skb = new_skb;
663            byteoff = (unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1);
664        }
665
666        skb_push(skb, byteoff + TX_INBAND_HEADER_LENGTH);
667
668        header = (struct tx_inband_header *)skb->data;
669
670        /*  setup inband trailer    */
671        header->uu   = 0;
672        header->cpi  = 0;
673        header->pad  = aal5_fill_pattern;
674        header->res1 = 0;
675
676        /*  setup cell header   */
677        header->clp  = (vcc->atm_options & ATM_ATMOPT_CLP) ? 1 : 0;
678        header->pti  = ATM_PTI_US0;
679        header->vci  = vcc->vci;
680        header->vpi  = vcc->vpi;
681        header->gfc  = 0;
682
683        /*  setup descriptor    */
684        reg_desc.dataptr = (unsigned int)skb->data >> 2;
685        reg_desc.datalen = datalen;
686        reg_desc.byteoff = byteoff;
687        reg_desc.iscell  = 0;
688    }
689    else {
690        /*  if data pointer is not aligned, allocate new sk_buff    */
691        if ( ((unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1)) != 0 ) {
692            struct sk_buff *new_skb;
693
694            err("skb->data not aligned");
695
696            new_skb = alloc_skb_tx(skb->len);
697            if ( new_skb == NULL ) {
698                err("ALLOC_SKB_TX_FAIL");
699                ret = -ENOMEM;
700                goto PPE_SEND_FAIL;
701            }
702            skb_put(new_skb, skb->len);
703            memcpy(new_skb->data, skb->data, skb->len);
704            dev_kfree_skb_any(skb);
705            skb = new_skb;
706        }
707
708        reg_desc.dataptr = (unsigned int)skb->data >> 2;
709        reg_desc.datalen = skb->len;
710        reg_desc.byteoff = 0;
711        reg_desc.iscell  = 1;
712    }
713
714    reg_desc.own = 1;
715    reg_desc.c = 1;
716    reg_desc.sop = reg_desc.eop = 1;
717
718    desc_base = get_tx_desc(conn);
719    if ( desc_base < 0 ) {
720        err("ALLOC_TX_CONNECTION_FAIL");
721        ret = -EIO;
722        goto PPE_SEND_FAIL;
723    }
724
725    if ( vcc->stats )
726        atomic_inc(&vcc->stats->tx);
727    if ( vcc->qos.aal == ATM_AAL5 )
728        g_atm_priv_data.wtx_pdu++;
729
730    /*  update descriptor send pointer  */
731    if ( g_atm_priv_data.conn[conn].tx_skb[desc_base] != NULL )
732        dev_kfree_skb_any(g_atm_priv_data.conn[conn].tx_skb[desc_base]);
733    g_atm_priv_data.conn[conn].tx_skb[desc_base] = skb;
734
735    /*  write discriptor to memory and write back cache */
736    g_atm_priv_data.conn[conn].tx_desc[desc_base] = reg_desc;
737    dma_cache_wback((unsigned long)skb->data, skb->len);
738
739    dump_skb(skb, DUMP_SKB_LEN, (char *)__func__, 0, conn, 1);
740
741    mailbox_signal(conn, 1);
742
743    adsl_led_flash();
744
745    return 0;
746
747FIND_VCC_FAIL:
748    err("FIND_VCC_FAIL");
749    g_atm_priv_data.wtx_err_pdu++;
750    dev_kfree_skb_any(skb);
751    return ret;
752
753PPE_SEND_FAIL:
754    if ( vcc->qos.aal == ATM_AAL5 )
755        g_atm_priv_data.wtx_drop_pdu++;
756    if ( vcc->stats )
757        atomic_inc(&vcc->stats->tx_err);
758    dev_kfree_skb_any(skb);
759    return ret;
760}
761
762static int ppe_send_oam(struct atm_vcc *vcc, void *cell, int flags)
763{
764    int conn;
765    struct uni_cell_header *uni_cell_header = (struct uni_cell_header *)cell;
766    int desc_base;
767    struct sk_buff *skb;
768    struct tx_descriptor reg_desc = {0};
769
770    if ( ((uni_cell_header->pti == ATM_PTI_SEGF5 || uni_cell_header->pti == ATM_PTI_E2EF5)
771        && find_vpivci(uni_cell_header->vpi, uni_cell_header->vci) < 0)
772        || ((uni_cell_header->vci == 0x03 || uni_cell_header->vci == 0x04)
773        && find_vpi(uni_cell_header->vpi) < 0) )
774        return -EINVAL;
775
776    if ( !g_showtime ) {
777        err("not in showtime");
778        return -EIO;
779    }
780
781    conn = find_vcc(vcc);
782    if ( conn < 0 ) {
783        err("FIND_VCC_FAIL");
784        return -EINVAL;
785    }
786
787    skb = alloc_skb_tx(CELL_SIZE);
788    if ( skb == NULL ) {
789        err("ALLOC_SKB_TX_FAIL");
790        return -ENOMEM;
791    }
792    memcpy(skb->data, cell, CELL_SIZE);
793
794    reg_desc.dataptr = (unsigned int)skb->data >> 2;
795    reg_desc.datalen = CELL_SIZE;
796    reg_desc.byteoff = 0;
797    reg_desc.iscell  = 1;
798
799    reg_desc.own = 1;
800    reg_desc.c = 1;
801    reg_desc.sop = reg_desc.eop = 1;
802
803    desc_base = get_tx_desc(conn);
804    if ( desc_base < 0 ) {
805        dev_kfree_skb_any(skb);
806        err("ALLOC_TX_CONNECTION_FAIL");
807        return -EIO;
808    }
809
810    if ( vcc->stats )
811        atomic_inc(&vcc->stats->tx);
812
813    /*  update descriptor send pointer  */
814    if ( g_atm_priv_data.conn[conn].tx_skb[desc_base] != NULL )
815        dev_kfree_skb_any(g_atm_priv_data.conn[conn].tx_skb[desc_base]);
816    g_atm_priv_data.conn[conn].tx_skb[desc_base] = skb;
817
818    /*  write discriptor to memory and write back cache */
819    g_atm_priv_data.conn[conn].tx_desc[desc_base] = reg_desc;
820    dma_cache_wback((unsigned long)skb->data, CELL_SIZE);
821
822    dump_skb(skb, DUMP_SKB_LEN, (char *)__func__, 0, conn, 1);
823
824    mailbox_signal(conn, 1);
825
826    adsl_led_flash();
827
828    return 0;
829}
830
831static int ppe_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)
832{
833    int conn;
834
835    if ( vcc == NULL || qos == NULL )
836        return -EINVAL;
837
838    conn = find_vcc(vcc);
839    if ( conn < 0 )
840        return -EINVAL;
841
842    set_qsb(vcc, qos, conn);
843
844    return 0;
845}
846
847static INLINE int adsl_led_flash(void)
848{
849    return ifx_mei_atm_led_blink();
850}
851
852/*
853 *  Description:
854 *    Add a 32-bit value to 64-bit value, and put result in a 64-bit variable.
855 *  Input:
856 *    opt1 --- ppe_u64_t, first operand, a 64-bit unsigned integer value
857 *    opt2 --- unsigned int, second operand, a 32-bit unsigned integer value
858 *    ret  --- ppe_u64_t, pointer to a variable to hold result
859 *  Output:
860 *    none
861 */
862static INLINE void u64_add_u32(ppe_u64_t opt1, unsigned int opt2, ppe_u64_t *ret)
863{
864    ret->l = opt1.l + opt2;
865    if ( ret->l < opt1.l || ret->l < opt2 )
866        ret->h++;
867}
868
869static INLINE struct sk_buff* alloc_skb_rx(void)
870{
871    struct sk_buff *skb;
872
873    skb = dev_alloc_skb(RX_DMA_CH_AAL_BUF_SIZE + DATA_BUFFER_ALIGNMENT);
874    if ( skb != NULL ) {
875        /*  must be burst length alignment  */
876        if ( ((unsigned int)skb->data & (DATA_BUFFER_ALIGNMENT - 1)) != 0 )
877            skb_reserve(skb, ~((unsigned int)skb->data + (DATA_BUFFER_ALIGNMENT - 1)) & (DATA_BUFFER_ALIGNMENT - 1));
878        /*  pub skb in reserved area "skb->data - 4"    */
879        *((struct sk_buff **)skb->data - 1) = skb;
880        /*  write back and invalidate cache */
881        dma_cache_wback_inv((unsigned long)skb->data - sizeof(skb), sizeof(skb));
882        /*  invalidate cache    */
883        dma_cache_inv((unsigned long)skb->data, (unsigned int)skb->end - (unsigned int)skb->data);
884    }
885
886    return skb;
887}
888
889static INLINE struct sk_buff* alloc_skb_tx(unsigned int size)
890{
891    struct sk_buff *skb;
892
893    /*  allocate memory including header and padding    */
894    size += TX_INBAND_HEADER_LENGTH + MAX_TX_PACKET_ALIGN_BYTES + MAX_TX_PACKET_PADDING_BYTES;
895    size &= ~(DATA_BUFFER_ALIGNMENT - 1);
896    skb = dev_alloc_skb(size + DATA_BUFFER_ALIGNMENT);
897    /*  must be burst length alignment  */
898    if ( skb != NULL )
899        skb_reserve(skb, (~((unsigned int)skb->data + (DATA_BUFFER_ALIGNMENT - 1)) & (DATA_BUFFER_ALIGNMENT - 1)) + TX_INBAND_HEADER_LENGTH);
900    return skb;
901}
902
903struct sk_buff* atm_alloc_tx(struct atm_vcc *vcc, unsigned int size)
904{
905    int conn;
906    struct sk_buff *skb;
907
908    /*  oversize packet */
909    if ( size > aal5s_max_packet_size ) {
910        err("atm_alloc_tx: oversize packet");
911        return NULL;
912    }
913    /*  send buffer overflow    */
914    if ( atomic_read(&sk_atm(vcc)->sk_wmem_alloc) && !atm_may_send(vcc, size) ) {
915        err("atm_alloc_tx: send buffer overflow");
916        return NULL;
917    }
918    conn = find_vcc(vcc);
919    if ( conn < 0 ) {
920        err("atm_alloc_tx: unknown VCC");
921        return NULL;
922    }
923
924    skb = dev_alloc_skb(size);
925    if ( skb == NULL ) {
926        err("atm_alloc_tx: sk buffer is used up");
927        return NULL;
928    }
929
930    atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
931
932    return skb;
933}
934
935static INLINE void atm_free_tx_skb_vcc(struct sk_buff *skb, struct atm_vcc *vcc)
936{
937    if ( vcc->pop != NULL )
938        vcc->pop(vcc, skb);
939    else
940        dev_kfree_skb_any(skb);
941}
942
943static INLINE struct sk_buff *get_skb_rx_pointer(unsigned int dataptr)
944{
945    unsigned int skb_dataptr;
946    struct sk_buff *skb;
947
948    skb_dataptr = ((dataptr - 1) << 2) | KSEG1;
949    skb = *(struct sk_buff **)skb_dataptr;
950
951    ASSERT((unsigned int)skb >= KSEG0, "invalid skb - skb = %#08x, dataptr = %#08x", (unsigned int)skb, dataptr);
952    ASSERT(((unsigned int)skb->data | KSEG1) == ((dataptr << 2) | KSEG1), "invalid skb - skb = %#08x, skb->data = %#08x, dataptr = %#08x", (unsigned int)skb, (unsigned int)skb->data, dataptr);
953
954    return skb;
955}
956
957static INLINE int get_tx_desc(unsigned int conn)
958{
959    int desc_base = -1;
960    struct connection *p_conn = &g_atm_priv_data.conn[conn];
961
962    if ( p_conn->tx_desc[p_conn->tx_desc_pos].own == 0 ) {
963        desc_base = p_conn->tx_desc_pos;
964        if ( ++(p_conn->tx_desc_pos) == dma_tx_descriptor_length )
965            p_conn->tx_desc_pos = 0;
966    }
967
968    return desc_base;
969}
970
971static INLINE void mailbox_oam_rx_handler(void)
972{
973    unsigned int vlddes = WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_OAM)->vlddes;
974    struct rx_descriptor reg_desc;
975    struct uni_cell_header *header;
976    int conn;
977    struct atm_vcc *vcc;
978    unsigned int i;
979
980    for ( i = 0; i < vlddes; i++ ) {
981        do {
982            reg_desc = g_atm_priv_data.oam_desc[g_atm_priv_data.oam_desc_pos];
983        } while ( reg_desc.own || !reg_desc.c );    //  keep test OWN and C bit until data is ready
984
985        header = (struct uni_cell_header *)&g_atm_priv_data.oam_buf[g_atm_priv_data.oam_desc_pos * RX_DMA_CH_OAM_BUF_SIZE];
986
987        if ( header->pti == ATM_PTI_SEGF5 || header->pti == ATM_PTI_E2EF5 )
988            conn = find_vpivci(header->vpi, header->vci);
989        else if ( header->vci == 0x03 || header->vci == 0x04 )
990            conn = find_vpi(header->vpi);
991        else
992            conn = -1;
993
994        if ( conn >= 0 && g_atm_priv_data.conn[conn].vcc != NULL ) {
995            vcc = g_atm_priv_data.conn[conn].vcc;
996
997            if ( vcc->push_oam != NULL )
998                vcc->push_oam(vcc, header);
999            else
1000                ifx_push_oam((unsigned char *)header);
1001
1002            adsl_led_flash();
1003        }
1004
1005        reg_desc.byteoff = 0;
1006        reg_desc.datalen = RX_DMA_CH_OAM_BUF_SIZE;
1007        reg_desc.own = 1;
1008        reg_desc.c   = 0;
1009
1010        g_atm_priv_data.oam_desc[g_atm_priv_data.oam_desc_pos] = reg_desc;
1011        if ( ++g_atm_priv_data.oam_desc_pos == RX_DMA_CH_OAM_DESC_LEN )
1012            g_atm_priv_data.oam_desc_pos = 0;
1013
1014        mailbox_signal(RX_DMA_CH_OAM, 0);
1015    }
1016}
1017
1018static INLINE void mailbox_aal_rx_handler(void)
1019{
1020    unsigned int vlddes = WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_AAL)->vlddes;
1021    struct rx_descriptor reg_desc;
1022    int conn;
1023    struct atm_vcc *vcc;
1024    struct sk_buff *skb, *new_skb;
1025    struct rx_inband_trailer *trailer;
1026    unsigned int i;
1027
1028    for ( i = 0; i < vlddes; i++ ) {
1029        do {
1030            reg_desc = g_atm_priv_data.aal_desc[g_atm_priv_data.aal_desc_pos];
1031        } while ( reg_desc.own || !reg_desc.c );    //  keep test OWN and C bit until data is ready
1032
1033        conn = reg_desc.id;
1034
1035        if ( g_atm_priv_data.conn[conn].vcc != NULL ) {
1036            vcc = g_atm_priv_data.conn[conn].vcc;
1037
1038            skb = get_skb_rx_pointer(reg_desc.dataptr);
1039
1040            if ( reg_desc.err ) {
1041                if ( vcc->qos.aal == ATM_AAL5 ) {
1042                    trailer = (struct rx_inband_trailer *)((unsigned int)skb->data + ((reg_desc.byteoff + reg_desc.datalen + MAX_RX_PACKET_PADDING_BYTES) & ~MAX_RX_PACKET_PADDING_BYTES));
1043                    if ( trailer->stw_crc )
1044                        g_atm_priv_data.conn[conn].aal5_vcc_crc_err++;
1045                    if ( trailer->stw_ovz )
1046                        g_atm_priv_data.conn[conn].aal5_vcc_oversize_sdu++;
1047                    g_atm_priv_data.wrx_drop_pdu++;
1048                }
1049                if ( vcc->stats ) {
1050                    atomic_inc(&vcc->stats->rx_drop);
1051                    atomic_inc(&vcc->stats->rx_err);
1052                }
1053            }
1054            else if ( atm_charge(vcc, skb->truesize) ) {
1055                new_skb = alloc_skb_rx();
1056                if ( new_skb != NULL ) {
1057                    skb_reserve(skb, reg_desc.byteoff);
1058                    skb_put(skb, reg_desc.datalen);
1059                    ATM_SKB(skb)->vcc = vcc;
1060
1061                    dump_skb(skb, DUMP_SKB_LEN, (char *)__func__, 0, conn, 0);
1062
1063                    vcc->push(vcc, skb);
1064
1065                    if ( vcc->qos.aal == ATM_AAL5 )
1066                        g_atm_priv_data.wrx_pdu++;
1067                    if ( vcc->stats )
1068                        atomic_inc(&vcc->stats->rx);
1069                    adsl_led_flash();
1070
1071                    reg_desc.dataptr = (unsigned int)new_skb->data >> 2;
1072                }
1073                else {
1074                    atm_return(vcc, skb->truesize);
1075                    if ( vcc->qos.aal == ATM_AAL5 )
1076                        g_atm_priv_data.wrx_drop_pdu++;
1077                    if ( vcc->stats )
1078                        atomic_inc(&vcc->stats->rx_drop);
1079                }
1080            }
1081            else {
1082                if ( vcc->qos.aal == ATM_AAL5 )
1083                    g_atm_priv_data.wrx_drop_pdu++;
1084                if ( vcc->stats )
1085                    atomic_inc(&vcc->stats->rx_drop);
1086            }
1087        }
1088        else {
1089            g_atm_priv_data.wrx_drop_pdu++;
1090        }
1091
1092        reg_desc.byteoff = 0;
1093        reg_desc.datalen = RX_DMA_CH_AAL_BUF_SIZE;
1094        reg_desc.own = 1;
1095        reg_desc.c   = 0;
1096
1097        g_atm_priv_data.aal_desc[g_atm_priv_data.aal_desc_pos] = reg_desc;
1098        if ( ++g_atm_priv_data.aal_desc_pos == dma_rx_descriptor_length )
1099            g_atm_priv_data.aal_desc_pos = 0;
1100
1101        mailbox_signal(RX_DMA_CH_AAL, 0);
1102    }
1103}
1104
1105#if defined(ENABLE_TASKLET) && ENABLE_TASKLET
1106static void do_ppe_tasklet(unsigned long arg)
1107{
1108    *MBOX_IGU1_ISRC = *MBOX_IGU1_ISR;
1109    mailbox_oam_rx_handler();
1110    mailbox_aal_rx_handler();
1111    if ( (*MBOX_IGU1_ISR & ((1 << RX_DMA_CH_AAL) | (1 << RX_DMA_CH_OAM))) != 0 )
1112        tasklet_schedule(&g_dma_tasklet);
1113    else
1114        enable_irq(PPE_MAILBOX_IGU1_INT);
1115}
1116#endif
1117
1118static irqreturn_t mailbox_irq_handler(int irq, void *dev_id)
1119{
1120    if ( !*MBOX_IGU1_ISR )
1121        return IRQ_HANDLED;
1122
1123#if defined(ENABLE_TASKLET) && ENABLE_TASKLET
1124    disable_irq(PPE_MAILBOX_IGU1_INT);
1125    tasklet_schedule(&g_dma_tasklet);
1126#else
1127    *MBOX_IGU1_ISRC = *MBOX_IGU1_ISR;
1128    mailbox_oam_rx_handler();
1129    mailbox_aal_rx_handler();
1130#endif
1131
1132    return IRQ_HANDLED;
1133}
1134
1135static INLINE void mailbox_signal(unsigned int queue, int is_tx)
1136{
1137    if ( is_tx ) {
1138        while ( MBOX_IGU3_ISR_ISR(queue + FIRST_QSB_QID + 16) );
1139        *MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(queue + FIRST_QSB_QID + 16);
1140    }
1141    else {
1142        while ( MBOX_IGU3_ISR_ISR(queue) );
1143        *MBOX_IGU3_ISRS = MBOX_IGU3_ISRS_SET(queue);
1144    }
1145}
1146
1147static void set_qsb(struct atm_vcc *vcc, struct atm_qos *qos, unsigned int queue)
1148{
1149    unsigned int qsb_clk = ifx_get_fpi_hz();
1150    unsigned int qsb_qid = queue + FIRST_QSB_QID;
1151    union qsb_queue_parameter_table qsb_queue_parameter_table = {{0}};
1152    union qsb_queue_vbr_parameter_table qsb_queue_vbr_parameter_table = {{0}};
1153    unsigned int tmp;
1154
1155#if defined(DEBUG_QOS) && DEBUG_QOS
1156    if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) {
1157        static char *str_traffic_class[9] = {
1158            "ATM_NONE",
1159            "ATM_UBR",
1160            "ATM_CBR",
1161            "ATM_VBR",
1162            "ATM_ABR",
1163            "ATM_ANYCLASS",
1164            "ATM_VBR_RT",
1165            "ATM_UBR_PLUS",
1166            "ATM_MAX_PCR"
1167        };
1168        printk(KERN_INFO  "QoS Parameters:\n");
1169        printk(KERN_INFO  "\tAAL          : %d\n", qos->aal);
1170        printk(KERN_INFO  "\tTX Traffic Class: %s\n", str_traffic_class[qos->txtp.traffic_class]);
1171        printk(KERN_INFO  "\tTX Max PCR      : %d\n", qos->txtp.max_pcr);
1172        printk(KERN_INFO  "\tTX Min PCR      : %d\n", qos->txtp.min_pcr);
1173        printk(KERN_INFO  "\tTX PCR          : %d\n", qos->txtp.pcr);
1174        printk(KERN_INFO  "\tTX Max CDV      : %d\n", qos->txtp.max_cdv);
1175        printk(KERN_INFO  "\tTX Max SDU      : %d\n", qos->txtp.max_sdu);
1176        printk(KERN_INFO  "\tTX SCR          : %d\n", qos->txtp.scr);
1177        printk(KERN_INFO  "\tTX MBS          : %d\n", qos->txtp.mbs);
1178        printk(KERN_INFO  "\tTX CDV          : %d\n", qos->txtp.cdv);
1179        printk(KERN_INFO  "\tRX Traffic Class: %s\n", str_traffic_class[qos->rxtp.traffic_class]);
1180        printk(KERN_INFO  "\tRX Max PCR      : %d\n", qos->rxtp.max_pcr);
1181        printk(KERN_INFO  "\tRX Min PCR      : %d\n", qos->rxtp.min_pcr);
1182        printk(KERN_INFO  "\tRX PCR          : %d\n", qos->rxtp.pcr);
1183        printk(KERN_INFO  "\tRX Max CDV      : %d\n", qos->rxtp.max_cdv);
1184        printk(KERN_INFO  "\tRX Max SDU      : %d\n", qos->rxtp.max_sdu);
1185        printk(KERN_INFO  "\tRX SCR          : %d\n", qos->rxtp.scr);
1186        printk(KERN_INFO  "\tRX MBS          : %d\n", qos->rxtp.mbs);
1187        printk(KERN_INFO  "\tRX CDV          : %d\n", qos->rxtp.cdv);
1188    }
1189#endif  //  defined(DEBUG_QOS) && DEBUG_QOS
1190
1191    /*
1192     *  Peak Cell Rate (PCR) Limiter
1193     */
1194    if ( qos->txtp.max_pcr == 0 )
1195        qsb_queue_parameter_table.bit.tp = 0;   /*  disable PCR limiter */
1196    else {
1197        /*  peak cell rate would be slightly lower than requested [maximum_rate / pcr = (qsb_clock / 8) * (time_step / 4) / pcr] */
1198        tmp = ((qsb_clk * qsb_tstep) >> 5) / qos->txtp.max_pcr + 1;
1199        /*  check if overflow takes place   */
1200        qsb_queue_parameter_table.bit.tp = tmp > QSB_TP_TS_MAX ? QSB_TP_TS_MAX : tmp;
1201    }
1202
1203    //  A funny issue. Create two PVCs, one UBR and one UBR with max_pcr.
1204    //  Send packets to these two PVCs at same time, it trigger strange behavior.
1205    //  In A1, RAM from 0x80000000 to 0x0x8007FFFF was corrupted with fixed pattern 0x00000000 0x40000000.
1206    //  In A4, PPE firmware keep emiting unknown cell and do not respond to driver.
1207    //  To work around, create UBR always with max_pcr.
1208    //  If user want to create UBR without max_pcr, we give a default one larger than line-rate.
1209    if ( qos->txtp.traffic_class == ATM_UBR && qsb_queue_parameter_table.bit.tp == 0 ) {
1210        int port = g_atm_priv_data.conn[queue].port;
1211        unsigned int max_pcr = g_atm_priv_data.port[port].tx_max_cell_rate + 1000;
1212
1213        tmp = ((qsb_clk * qsb_tstep) >> 5) / max_pcr + 1;
1214        if ( tmp > QSB_TP_TS_MAX )
1215            tmp = QSB_TP_TS_MAX;
1216        else if ( tmp < 1 )
1217            tmp = 1;
1218        qsb_queue_parameter_table.bit.tp = tmp;
1219    }
1220
1221    /*
1222     *  Weighted Fair Queueing Factor (WFQF)
1223     */
1224    switch ( qos->txtp.traffic_class ) {
1225    case ATM_CBR:
1226    case ATM_VBR_RT:
1227        /*  real time queue gets weighted fair queueing bypass  */
1228        qsb_queue_parameter_table.bit.wfqf = 0;
1229        break;
1230    case ATM_VBR_NRT:
1231    case ATM_UBR_PLUS:
1232        /*  WFQF calculation here is based on virtual cell rates, to reduce granularity for high rates  */
1233        /*  WFQF is maximum cell rate / garenteed cell rate                                             */
1234        /*  wfqf = qsb_minimum_cell_rate * QSB_WFQ_NONUBR_MAX / requested_minimum_peak_cell_rate        */
1235        if ( qos->txtp.min_pcr == 0 )
1236            qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_NONUBR_MAX;
1237        else
1238        {
1239            tmp = QSB_GCR_MIN * QSB_WFQ_NONUBR_MAX / qos->txtp.min_pcr;
1240            if ( tmp == 0 )
1241                qsb_queue_parameter_table.bit.wfqf = 1;
1242            else if ( tmp > QSB_WFQ_NONUBR_MAX )
1243                qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_NONUBR_MAX;
1244            else
1245                qsb_queue_parameter_table.bit.wfqf = tmp;
1246        }
1247        break;
1248    default:
1249    case ATM_UBR:
1250        qsb_queue_parameter_table.bit.wfqf = QSB_WFQ_UBR_BYPASS;
1251    }
1252
1253    /*
1254     *  Sustained Cell Rate (SCR) Leaky Bucket Shaper VBR.0/VBR.1
1255     */
1256    if ( qos->txtp.traffic_class == ATM_VBR_RT || qos->txtp.traffic_class == ATM_VBR_NRT ) {
1257        if ( qos->txtp.scr == 0 ) {
1258            /*  disable shaper  */
1259            qsb_queue_vbr_parameter_table.bit.taus = 0;
1260            qsb_queue_vbr_parameter_table.bit.ts = 0;
1261        }
1262        else {
1263            /*  Cell Loss Priority  (CLP)   */
1264            if ( (vcc->atm_options & ATM_ATMOPT_CLP) )
1265                /*  CLP1    */
1266                qsb_queue_parameter_table.bit.vbr = 1;
1267            else
1268                /*  CLP0    */
1269                qsb_queue_parameter_table.bit.vbr = 0;
1270            /*  Rate Shaper Parameter (TS) and Burst Tolerance Parameter for SCR (tauS) */
1271            tmp = ((qsb_clk * qsb_tstep) >> 5) / qos->txtp.scr + 1;
1272            qsb_queue_vbr_parameter_table.bit.ts = tmp > QSB_TP_TS_MAX ? QSB_TP_TS_MAX : tmp;
1273            tmp = (qos->txtp.mbs - 1) * (qsb_queue_vbr_parameter_table.bit.ts - qsb_queue_parameter_table.bit.tp) / 64;
1274            if ( tmp == 0 )
1275                qsb_queue_vbr_parameter_table.bit.taus = 1;
1276            else if ( tmp > QSB_TAUS_MAX )
1277                qsb_queue_vbr_parameter_table.bit.taus = QSB_TAUS_MAX;
1278            else
1279                qsb_queue_vbr_parameter_table.bit.taus = tmp;
1280        }
1281    }
1282    else {
1283        qsb_queue_vbr_parameter_table.bit.taus = 0;
1284        qsb_queue_vbr_parameter_table.bit.ts = 0;
1285    }
1286
1287    /*  Queue Parameter Table (QPT) */
1288    *QSB_RTM   = QSB_RTM_DM_SET(QSB_QPT_SET_MASK);
1289    *QSB_RTD   = QSB_RTD_TTV_SET(qsb_queue_parameter_table.dword);
1290    *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);
1291#if defined(DEBUG_QOS) && DEBUG_QOS
1292    if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) )
1293        printk("QPT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC);
1294#endif
1295    /*  Queue VBR Paramter Table (QVPT) */
1296    *QSB_RTM   = QSB_RTM_DM_SET(QSB_QVPT_SET_MASK);
1297    *QSB_RTD   = QSB_RTD_TTV_SET(qsb_queue_vbr_parameter_table.dword);
1298    *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);
1299#if defined(DEBUG_QOS) && DEBUG_QOS
1300    if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) )
1301        printk("QVPT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC);
1302#endif
1303
1304#if defined(DEBUG_QOS) && DEBUG_QOS
1305    if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) {
1306        printk("set_qsb\n");
1307        printk("  qsb_clk = %lu\n", (unsigned long)qsb_clk);
1308        printk("  qsb_queue_parameter_table.bit.tp       = %d\n", (int)qsb_queue_parameter_table.bit.tp);
1309        printk("  qsb_queue_parameter_table.bit.wfqf     = %d (0x%08X)\n", (int)qsb_queue_parameter_table.bit.wfqf, (int)qsb_queue_parameter_table.bit.wfqf);
1310        printk("  qsb_queue_parameter_table.bit.vbr      = %d\n", (int)qsb_queue_parameter_table.bit.vbr);
1311        printk("  qsb_queue_parameter_table.dword        = 0x%08X\n", (int)qsb_queue_parameter_table.dword);
1312        printk("  qsb_queue_vbr_parameter_table.bit.ts   = %d\n", (int)qsb_queue_vbr_parameter_table.bit.ts);
1313        printk("  qsb_queue_vbr_parameter_table.bit.taus = %d\n", (int)qsb_queue_vbr_parameter_table.bit.taus);
1314        printk("  qsb_queue_vbr_parameter_table.dword    = 0x%08X\n", (int)qsb_queue_vbr_parameter_table.dword);
1315    }
1316#endif
1317}
1318
1319static void qsb_global_set(void)
1320{
1321    unsigned int qsb_clk = ifx_get_fpi_hz();
1322    int i;
1323    unsigned int tmp1, tmp2, tmp3;
1324
1325    *QSB_ICDV = QSB_ICDV_TAU_SET(qsb_tau);
1326    *QSB_SBL  = QSB_SBL_SBL_SET(qsb_srvm);
1327    *QSB_CFG  = QSB_CFG_TSTEPC_SET(qsb_tstep >> 1);
1328#if defined(DEBUG_QOS) && DEBUG_QOS
1329    if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) ) {
1330        printk("qsb_clk = %u\n", qsb_clk);
1331        printk("QSB_ICDV (%08X) = %d (%d), QSB_SBL (%08X) = %d (%d), QSB_CFG (%08X) = %d (%d)\n", (unsigned int)QSB_ICDV, *QSB_ICDV, QSB_ICDV_TAU_SET(qsb_tau), (unsigned int)QSB_SBL, *QSB_SBL, QSB_SBL_SBL_SET(qsb_srvm), (unsigned int)QSB_CFG, *QSB_CFG, QSB_CFG_TSTEPC_SET(qsb_tstep >> 1));
1332    }
1333#endif
1334
1335    /*
1336     *  set SCT and SPT per port
1337     */
1338    for ( i = 0; i < ATM_PORT_NUMBER; i++ ) {
1339        if ( g_atm_priv_data.port[i].tx_max_cell_rate != 0 ) {
1340            tmp1 = ((qsb_clk * qsb_tstep) >> 1) / g_atm_priv_data.port[i].tx_max_cell_rate;
1341            tmp2 = tmp1 >> 6;                   /*  integer value of Tsb    */
1342            tmp3 = (tmp1 & ((1 << 6) - 1)) + 1; /*  fractional part of Tsb  */
1343            /*  carry over to integer part (?)  */
1344            if ( tmp3 == (1 << 6) )
1345            {
1346                tmp3 = 0;
1347                tmp2++;
1348            }
1349            if ( tmp2 == 0 )
1350                tmp2 = tmp3 = 1;
1351            /*  1. set mask                                 */
1352            /*  2. write value to data transfer register    */
1353            /*  3. start the tranfer                        */
1354            /*  SCT (FracRate)  */
1355            *QSB_RTM   = QSB_RTM_DM_SET(QSB_SET_SCT_MASK);
1356            *QSB_RTD   = QSB_RTD_TTV_SET(tmp3);
1357            *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);
1358#if defined(DEBUG_QOS) && DEBUG_QOS
1359            if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) )
1360                printk("SCT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC);
1361#endif
1362            /*  SPT (SBV + PN + IntRage)    */
1363            *QSB_RTM   = QSB_RTM_DM_SET(QSB_SET_SPT_MASK);
1364            *QSB_RTD   = QSB_RTD_TTV_SET(QSB_SPT_SBV_VALID | QSB_SPT_PN_SET(i & 0x01) | QSB_SPT_INTRATE_SET(tmp2));
1365            *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);
1366#if defined(DEBUG_QOS) && DEBUG_QOS
1367            if ( (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS) )
1368                printk("SPT: QSB_RTM (%08X) = 0x%08X, QSB_RTD (%08X) = 0x%08X, QSB_RAMAC (%08X) = 0x%08X\n", (unsigned int)QSB_RTM, *QSB_RTM, (unsigned int)QSB_RTD, *QSB_RTD, (unsigned int)QSB_RAMAC, *QSB_RAMAC);
1369#endif
1370        }
1371    }
1372}
1373
1374static INLINE void set_htu_entry(unsigned int vpi, unsigned int vci, unsigned int queue, int aal5, int is_retx)
1375{
1376    struct htu_entry htu_entry = {  res1:       0x00,
1377                                    clp:        is_retx ? 0x01 : 0x00,
1378                                    pid:        g_atm_priv_data.conn[queue].port & 0x01,
1379                                    vpi:        vpi,
1380                                    vci:        vci,
1381                                    pti:        0x00,
1382                                    vld:        0x01};
1383
1384    struct htu_mask htu_mask = {    set:        0x01,
1385#if !defined(ENABLE_ATM_RETX) || !ENABLE_ATM_RETX
1386                                    clp:        0x01,
1387                                    pid_mask:   0x02,
1388#else
1389                                    clp:        g_retx_htu ? 0x00 : 0x01,
1390                                    pid_mask:   RETX_MODE_CFG->retx_en ? 0x03 : 0x02,
1391#endif
1392                                    vpi_mask:   0x00,
1393#if !defined(ENABLE_ATM_RETX) || !ENABLE_ATM_RETX
1394                                    vci_mask:   0x0000,
1395#else
1396                                    vci_mask:   RETX_MODE_CFG->retx_en ? 0xFF00 : 0x0000,
1397#endif
1398                                    pti_mask:   0x03,   //  0xx, user data
1399                                    clear:      0x00};
1400
1401    struct htu_result htu_result = {res1:       0x00,
1402                                    cellid:     queue,
1403                                    res2:       0x00,
1404                                    type:       aal5 ? 0x00 : 0x01,
1405                                    ven:        0x01,
1406                                    res3:       0x00,
1407                                    qid:        queue};
1408
1409    *HTU_RESULT(queue + OAM_HTU_ENTRY_NUMBER) = htu_result;
1410    *HTU_MASK(queue + OAM_HTU_ENTRY_NUMBER)   = htu_mask;
1411    *HTU_ENTRY(queue + OAM_HTU_ENTRY_NUMBER)  = htu_entry;
1412}
1413
1414static INLINE void clear_htu_entry(unsigned int queue)
1415{
1416    HTU_ENTRY(queue + OAM_HTU_ENTRY_NUMBER)->vld = 0;
1417}
1418
1419static void validate_oam_htu_entry(void)
1420{
1421    HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 1;
1422    HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 1;
1423    HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 1;
1424#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
1425    HTU_ENTRY(OAM_ARQ_HTU_ENTRY)->vld = 1;
1426#endif
1427}
1428
1429static void invalidate_oam_htu_entry(void)
1430{
1431    HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)->vld = 0;
1432    HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)->vld = 0;
1433    HTU_ENTRY(OAM_F5_HTU_ENTRY)->vld = 0;
1434#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
1435    HTU_ENTRY(OAM_ARQ_HTU_ENTRY)->vld = 0;
1436#endif
1437}
1438
1439static INLINE int find_vpi(unsigned int vpi)
1440{
1441    int i;
1442    unsigned int bit;
1443
1444    for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) {
1445        if ( (g_atm_priv_data.conn_table & bit) != 0
1446            && g_atm_priv_data.conn[i].vcc != NULL
1447            && vpi == g_atm_priv_data.conn[i].vcc->vpi )
1448            return i;
1449    }
1450
1451    return -1;
1452}
1453
1454static INLINE int find_vpivci(unsigned int vpi, unsigned int vci)
1455{
1456    int i;
1457    unsigned int bit;
1458
1459    for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) {
1460        if ( (g_atm_priv_data.conn_table & bit) != 0
1461            && g_atm_priv_data.conn[i].vcc != NULL
1462            && vpi == g_atm_priv_data.conn[i].vcc->vpi
1463            && vci == g_atm_priv_data.conn[i].vcc->vci )
1464            return i;
1465    }
1466
1467    return -1;
1468}
1469
1470static INLINE int find_vcc(struct atm_vcc *vcc)
1471{
1472    int i;
1473    unsigned int bit;
1474
1475    for ( i = 0, bit = 1; i < MAX_PVC_NUMBER; i++, bit <<= 1 ) {
1476        if ( (g_atm_priv_data.conn_table & bit) != 0
1477            && g_atm_priv_data.conn[i].vcc == vcc )
1478            return i;
1479    }
1480
1481    return -1;
1482}
1483
1484#if defined(DEBUG_DUMP_SKB) && DEBUG_DUMP_SKB
1485static void dump_skb(struct sk_buff *skb, u32 len, char *title, int port, int ch, int is_tx)
1486{
1487    int i;
1488
1489    if ( !(ifx_atm_dbg_enable & (is_tx ? DBG_ENABLE_MASK_DUMP_SKB_TX : DBG_ENABLE_MASK_DUMP_SKB_RX)) )
1490        return;
1491
1492    if ( skb->len < len )
1493        len = skb->len;
1494
1495    if ( len > RX_DMA_CH_AAL_BUF_SIZE ) {
1496        printk("too big data length: skb = %08x, skb->data = %08x, skb->len = %d\n", (u32)skb, (u32)skb->data, skb->len);
1497        return;
1498    }
1499
1500    if ( ch >= 0 )
1501        printk("%s (port %d, ch %d)\n", title, port, ch);
1502    else
1503        printk("%s\n", title);
1504    printk("  skb->data = %08X, skb->tail = %08X, skb->len = %d\n", (u32)skb->data, (u32)skb->tail, (int)skb->len);
1505    for ( i = 1; i <= len; i++ ) {
1506        if ( i % 16 == 1 )
1507            printk("  %4d:", i - 1);
1508        printk(" %02X", (int)(*((char*)skb->data + i - 1) & 0xFF));
1509        if ( i % 16 == 0 )
1510            printk("\n");
1511    }
1512    if ( (i - 1) % 16 != 0 )
1513        printk("\n");
1514}
1515#endif
1516
1517static INLINE void proc_file_create(void)
1518{
1519#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
1520    struct proc_dir_entry *res;
1521#endif
1522
1523    g_atm_dir = proc_mkdir("driver/ifx_atm", NULL);
1524
1525    create_proc_read_entry("version",
1526                            0,
1527                            g_atm_dir,
1528                            proc_read_version,
1529                            NULL);
1530
1531    res = create_proc_entry("mib",
1532                            0,
1533                            g_atm_dir);
1534    if ( res != NULL ) {
1535        res->read_proc  = proc_read_mib;
1536        res->write_proc = proc_write_mib;
1537    }
1538
1539#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
1540    res = create_proc_entry("dbg",
1541                            0,
1542                            g_atm_dir);
1543    if ( res != NULL ) {
1544        res->read_proc  = proc_read_dbg;
1545        res->write_proc = proc_write_dbg;
1546    }
1547#endif
1548
1549#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC
1550    create_proc_read_entry("htu",
1551                            0,
1552                            g_atm_dir,
1553                            proc_read_htu,
1554                            NULL);
1555
1556    create_proc_read_entry("txq",
1557                            0,
1558                            g_atm_dir,
1559                            proc_read_txq,
1560                            NULL);
1561#endif
1562}
1563
1564static INLINE void proc_file_delete(void)
1565{
1566#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC
1567    remove_proc_entry("txq", g_atm_dir);
1568
1569    remove_proc_entry("htu", g_atm_dir);
1570#endif
1571
1572#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
1573    remove_proc_entry("dbg", g_atm_dir);
1574#endif
1575
1576    remove_proc_entry("version", g_atm_dir);
1577
1578    remove_proc_entry("driver/ifx_atm", NULL);
1579}
1580
1581static int proc_read_version(char *buf, char **start, off_t offset, int count, int *eof, void *data)
1582{
1583    int len = 0;
1584
1585    len += ifx_atm_version(buf + len);
1586
1587    if ( offset >= len ) {
1588        *start = buf;
1589        *eof = 1;
1590        return 0;
1591    }
1592    *start = buf + offset;
1593    if ( (len -= offset) > count )
1594        return count;
1595    *eof = 1;
1596    return len;
1597}
1598
1599static int proc_read_mib(char *page, char **start, off_t off, int count, int *eof, void *data)
1600{
1601    int len = 0;
1602
1603    len += sprintf(page + off + len,    "Firmware\n");
1604    len += sprintf(page + off + len,    "  wrx_drophtu_cell = %u\n", WAN_MIB_TABLE->wrx_drophtu_cell);
1605    len += sprintf(page + off + len,    "  wrx_dropdes_pdu  = %u\n", WAN_MIB_TABLE->wrx_dropdes_pdu);
1606    len += sprintf(page + off + len,    "  wrx_correct_pdu  = %u\n", WAN_MIB_TABLE->wrx_correct_pdu);
1607    len += sprintf(page + off + len,    "  wrx_err_pdu      = %u\n", WAN_MIB_TABLE->wrx_err_pdu);
1608    len += sprintf(page + off + len,    "  wrx_dropdes_cell = %u\n", WAN_MIB_TABLE->wrx_dropdes_cell);
1609    len += sprintf(page + off + len,    "  wrx_correct_cell = %u\n", WAN_MIB_TABLE->wrx_correct_cell);
1610    len += sprintf(page + off + len,    "  wrx_err_cell     = %u\n", WAN_MIB_TABLE->wrx_err_cell);
1611    len += sprintf(page + off + len,    "  wrx_total_byte   = %u\n", WAN_MIB_TABLE->wrx_total_byte);
1612    len += sprintf(page + off + len,    "  wtx_total_pdu    = %u\n", WAN_MIB_TABLE->wtx_total_pdu);
1613    len += sprintf(page + off + len,    "  wtx_total_cell   = %u\n", WAN_MIB_TABLE->wtx_total_cell);
1614    len += sprintf(page + off + len,    "  wtx_total_byte   = %u\n", WAN_MIB_TABLE->wtx_total_byte);
1615    len += sprintf(page + off + len,    "Driver\n");
1616    len += sprintf(page + off + len,    "  wrx_pdu      = %u\n", g_atm_priv_data.wrx_pdu);
1617    len += sprintf(page + off + len,    "  wrx_drop_pdu = %u\n", g_atm_priv_data.wrx_drop_pdu);
1618    len += sprintf(page + off + len,    "  wtx_pdu      = %u\n", g_atm_priv_data.wtx_pdu);
1619    len += sprintf(page + off + len,    "  wtx_err_pdu  = %u\n", g_atm_priv_data.wtx_err_pdu);
1620    len += sprintf(page + off + len,    "  wtx_drop_pdu = %u\n", g_atm_priv_data.wtx_drop_pdu);
1621
1622    *eof = 1;
1623
1624    return len;
1625}
1626
1627static int proc_write_mib(struct file *file, const char *buf, unsigned long count, void *data)
1628{
1629    char str[2048];
1630    char *p;
1631    int len, rlen;
1632
1633    len = count < sizeof(str) ? count : sizeof(str) - 1;
1634    rlen = len - copy_from_user(str, buf, len);
1635    while ( rlen && str[rlen - 1] <= ' ' )
1636        rlen--;
1637    str[rlen] = 0;
1638    for ( p = str; *p && *p <= ' '; p++, rlen-- );
1639    if ( !*p )
1640        return 0;
1641
1642    if ( stricmp(p, "clear") == 0 || stricmp(p, "clear all") == 0
1643        || stricmp(p, "clean") == 0 || stricmp(p, "clean all") == 0 ) {
1644        memset(WAN_MIB_TABLE, 0, sizeof(*WAN_MIB_TABLE));
1645        g_atm_priv_data.wrx_pdu      = 0;
1646        g_atm_priv_data.wrx_drop_pdu = 0;
1647        g_atm_priv_data.wtx_pdu      = 0;
1648        g_atm_priv_data.wtx_err_pdu  = 0;
1649        g_atm_priv_data.wtx_drop_pdu = 0;
1650    }
1651
1652    return count;
1653}
1654
1655#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
1656
1657static int proc_read_dbg(char *page, char **start, off_t off, int count, int *eof, void *data)
1658{
1659    int len = 0;
1660
1661    len += sprintf(page + off + len, "error print - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ERR)           ? "enabled" : "disabled");
1662    len += sprintf(page + off + len, "debug print - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DEBUG_PRINT)   ? "enabled" : "disabled");
1663    len += sprintf(page + off + len, "assert      - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_ASSERT)        ? "enabled" : "disabled");
1664    len += sprintf(page + off + len, "dump rx skb - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_SKB_RX)   ? "enabled" : "disabled");
1665    len += sprintf(page + off + len, "dump tx skb - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_SKB_TX)   ? "enabled" : "disabled");
1666    len += sprintf(page + off + len, "qos         - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_QOS)      ? "enabled" : "disabled");
1667    len += sprintf(page + off + len, "dump init   - %s\n", (ifx_atm_dbg_enable & DBG_ENABLE_MASK_DUMP_INIT)     ? "enabled" : "disabled");
1668
1669    *eof = 1;
1670
1671    return len;
1672}
1673
1674static int proc_write_dbg(struct file *file, const char *buf, unsigned long count, void *data)
1675{
1676    static const char *dbg_enable_mask_str[] = {
1677        " error print",
1678        " err",
1679        " debug print",
1680        " dbg",
1681        " assert",
1682        " assert",
1683        " dump rx skb",
1684        " rx",
1685        " dump tx skb",
1686        " tx",
1687        " dump qos",
1688        " qos",
1689        " dump init",
1690        " init",
1691        " all"
1692    };
1693    static const int dbg_enable_mask_str_len[] = {
1694        12, 4,
1695        12, 4,
1696        7,  7,
1697        12, 3,
1698        12, 3,
1699        9,  4,
1700        10, 5,
1701        4
1702    };
1703    u32 dbg_enable_mask[] = {
1704        DBG_ENABLE_MASK_ERR,
1705        DBG_ENABLE_MASK_DEBUG_PRINT,
1706        DBG_ENABLE_MASK_ASSERT,
1707        DBG_ENABLE_MASK_DUMP_SKB_RX,
1708        DBG_ENABLE_MASK_DUMP_SKB_TX,
1709        DBG_ENABLE_MASK_DUMP_QOS,
1710        DBG_ENABLE_MASK_DUMP_INIT,
1711        DBG_ENABLE_MASK_ALL
1712    };
1713
1714    char str[2048];
1715    char *p;
1716
1717    int len, rlen;
1718
1719    int f_enable = 0;
1720    int i;
1721
1722    len = count < sizeof(str) ? count : sizeof(str) - 1;
1723    rlen = len - copy_from_user(str, buf, len);
1724    while ( rlen && str[rlen - 1] <= ' ' )
1725        rlen--;
1726    str[rlen] = 0;
1727    for ( p = str; *p && *p <= ' '; p++, rlen-- );
1728    if ( !*p )
1729        return 0;
1730
1731    if ( strincmp(p, "enable", 6) == 0 ) {
1732        p += 6;
1733        f_enable = 1;
1734    }
1735    else if ( strincmp(p, "disable", 7) == 0 ) {
1736        p += 7;
1737        f_enable = -1;
1738    }
1739    else if ( strincmp(p, "help", 4) == 0 || *p == '?' ) {
1740        printk("echo <enable/disable> [err/dbg/assert/rx/tx/init/all] > /proc/eth/dbg\n");
1741    }
1742
1743    if ( f_enable ) {
1744        if ( *p == 0 ) {
1745            if ( f_enable > 0 )
1746                ifx_atm_dbg_enable |= DBG_ENABLE_MASK_ALL;
1747            else
1748                ifx_atm_dbg_enable &= ~DBG_ENABLE_MASK_ALL;
1749        }
1750        else {
1751            do {
1752                for ( i = 0; i < NUM_ENTITY(dbg_enable_mask_str); i++ )
1753                    if ( strincmp(p, dbg_enable_mask_str[i], dbg_enable_mask_str_len[i]) == 0 ) {
1754                        if ( f_enable > 0 )
1755                            ifx_atm_dbg_enable |= dbg_enable_mask[i >> 1];
1756                        else
1757                            ifx_atm_dbg_enable &= ~dbg_enable_mask[i >> 1];
1758                        p += dbg_enable_mask_str_len[i];
1759                        break;
1760                    }
1761            } while ( i < NUM_ENTITY(dbg_enable_mask_str) );
1762        }
1763    }
1764
1765    return count;
1766}
1767
1768#endif
1769
1770#if defined(ENABLE_FW_PROC) && ENABLE_FW_PROC
1771
1772static INLINE int print_htu(char *buf, int i)
1773{
1774    int len = 0;
1775
1776    if ( HTU_ENTRY(i)->vld ) {
1777        len += sprintf(buf + len, "%2d. valid\n", i);
1778        len += sprintf(buf + len, "    entry  0x%08x - pid %01x vpi %02x vci %04x pti %01x\n", *(u32*)HTU_ENTRY(i), HTU_ENTRY(i)->pid, HTU_ENTRY(i)->vpi, HTU_ENTRY(i)->vci, HTU_ENTRY(i)->pti);
1779        len += sprintf(buf + len, "    mask   0x%08x - pid %01x vpi %02x vci %04x pti %01x\n", *(u32*)HTU_MASK(i), HTU_MASK(i)->pid_mask, HTU_MASK(i)->vpi_mask, HTU_MASK(i)->vci_mask, HTU_MASK(i)->pti_mask);
1780        len += sprintf(buf + len, "    result 0x%08x - type: %s, qid: %d", *(u32*)HTU_RESULT(i), HTU_RESULT(i)->type ? "cell" : "AAL5", HTU_RESULT(i)->qid);
1781        if ( HTU_RESULT(i)->type )
1782            len += sprintf(buf + len, ", cell id: %d, verification: %s", HTU_RESULT(i)->cellid, HTU_RESULT(i)->ven ? "on" : "off");
1783        len += sprintf(buf + len, "\n");
1784    }
1785    else
1786        len += sprintf(buf + len, "%2d. invalid\n", i);
1787
1788    return len;
1789}
1790
1791static int proc_read_htu(char *page, char **start, off_t off, int count, int *eof, void *data)
1792{
1793    int len = 0;
1794    int len_max = off + count;
1795    char *pstr;
1796    char str[1024];
1797    int llen;
1798
1799    int htuts = *CFG_WRX_HTUTS;
1800    int i;
1801
1802    pstr = *start = page;
1803
1804    llen = sprintf(pstr, "HTU Table (Max %d):\n", htuts);
1805    pstr += llen;
1806    len += llen;
1807
1808    for ( i = 0; i < htuts; i++ ) {
1809        llen = print_htu(str, i);
1810        if ( len <= off && len + llen > off ) {
1811            memcpy(pstr, str + off - len, len + llen - off);
1812            pstr += len + llen - off;
1813        }
1814        else if ( len > off ) {
1815            memcpy(pstr, str, llen);
1816            pstr += llen;
1817        }
1818        len += llen;
1819        if ( len >= len_max )
1820            goto PROC_READ_HTU_OVERRUN_END;
1821    }
1822
1823    *eof = 1;
1824
1825    return len - off;
1826
1827PROC_READ_HTU_OVERRUN_END:
1828
1829    return len - llen - off;
1830}
1831
1832static INLINE int print_tx_queue(char *buf, int i)
1833{
1834    int len = 0;
1835
1836    if ( (*WTX_DMACH_ON & (1 << i)) ) {
1837        len += sprintf(buf + len, "%2d. valid\n", i);
1838        len += sprintf(buf + len, "    queue 0x%08x - sbid %u, qsb %s\n", *(u32*)WTX_QUEUE_CONFIG(i), (unsigned int)WTX_QUEUE_CONFIG(i)->sbid, WTX_QUEUE_CONFIG(i)->qsben ? "enable" : "disable");
1839        len += sprintf(buf + len, "    dma   0x%08x - base %08x, len %u, vlddes %u\n", *(u32*)WTX_DMA_CHANNEL_CONFIG(i), WTX_DMA_CHANNEL_CONFIG(i)->desba, WTX_DMA_CHANNEL_CONFIG(i)->deslen, WTX_DMA_CHANNEL_CONFIG(i)->vlddes);
1840    }
1841    else
1842        len += sprintf(buf + len, "%2d. invalid\n", i);
1843
1844    return len;
1845}
1846
1847static int proc_read_txq(char *page, char **start, off_t off, int count, int *eof, void *data)
1848{
1849    int len = 0;
1850    int len_max = off + count;
1851    char *pstr;
1852    char str[1024];
1853    int llen;
1854
1855    int i;
1856
1857    pstr = *start = page;
1858
1859    llen = sprintf(pstr, "TX Queue Config (Max %d):\n", *CFG_WTX_DCHNUM);
1860    pstr += llen;
1861    len += llen;
1862
1863    for ( i = 0; i < 16; i++ ) {
1864        llen = print_tx_queue(str, i);
1865        if ( len <= off && len + llen > off ) {
1866            memcpy(pstr, str + off - len, len + llen - off);
1867            pstr += len + llen - off;
1868        }
1869        else if ( len > off ) {
1870            memcpy(pstr, str, llen);
1871            pstr += llen;
1872        }
1873        len += llen;
1874        if ( len >= len_max )
1875            goto PROC_READ_HTU_OVERRUN_END;
1876    }
1877
1878    *eof = 1;
1879
1880    return len - off;
1881
1882PROC_READ_HTU_OVERRUN_END:
1883
1884    return len - llen - off;
1885}
1886
1887#endif
1888
1889static int stricmp(const char *p1, const char *p2)
1890{
1891    int c1, c2;
1892
1893    while ( *p1 && *p2 )
1894    {
1895        c1 = *p1 >= 'A' && *p1 <= 'Z' ? *p1 + 'a' - 'A' : *p1;
1896        c2 = *p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2;
1897        if ( (c1 -= c2) )
1898            return c1;
1899        p1++;
1900        p2++;
1901    }
1902
1903    return *p1 - *p2;
1904}
1905
1906#if defined(ENABLE_DBG_PROC) && ENABLE_DBG_PROC
1907static int strincmp(const char *p1, const char *p2, int n)
1908{
1909    int c1 = 0, c2;
1910
1911    while ( n && *p1 && *p2 )
1912    {
1913        c1 = *p1 >= 'A' && *p1 <= 'Z' ? *p1 + 'a' - 'A' : *p1;
1914        c2 = *p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2;
1915        if ( (c1 -= c2) )
1916            return c1;
1917        p1++;
1918        p2++;
1919        n--;
1920    }
1921
1922    return n ? *p1 - *p2 : c1;
1923}
1924#endif
1925
1926static INLINE int ifx_atm_version(char *buf)
1927{
1928    int len = 0;
1929    unsigned int major, minor;
1930
1931    ifx_atm_get_fw_ver(&major, &minor);
1932
1933    len += sprintf(buf + len, "Infineon Technologies ATM driver version %d.%d.%d\n", IFX_ATM_VER_MAJOR, IFX_ATM_VER_MID, IFX_ATM_VER_MINOR);
1934    len += sprintf(buf + len, "Infineon Technologies ATM (A1) firmware version %d.%d\n", major, minor);
1935
1936    return len;
1937}
1938
1939#ifdef MODULE
1940static INLINE void reset_ppe(void)
1941{
1942    //  TODO:
1943}
1944#endif
1945
1946static INLINE void check_parameters(void)
1947{
1948    /*  Please refer to Amazon spec 15.4 for setting these values.  */
1949    if ( qsb_tau < 1 )
1950        qsb_tau = 1;
1951    if ( qsb_tstep < 1 )
1952        qsb_tstep = 1;
1953    else if ( qsb_tstep > 4 )
1954        qsb_tstep = 4;
1955    else if ( qsb_tstep == 3 )
1956        qsb_tstep = 2;
1957
1958    /*  There is a delay between PPE write descriptor and descriptor is       */
1959    /*  really stored in memory. Host also has this delay when writing        */
1960    /*  descriptor. So PPE will use this value to determine if the write      */
1961    /*  operation makes effect.                                               */
1962    if ( write_descriptor_delay < 0 )
1963        write_descriptor_delay = 0;
1964
1965    if ( aal5_fill_pattern < 0 )
1966        aal5_fill_pattern = 0;
1967    else
1968        aal5_fill_pattern &= 0xFF;
1969
1970    /*  Because of the limitation of length field in descriptors, the packet  */
1971    /*  size could not be larger than 64K minus overhead size.                */
1972    if ( aal5r_max_packet_size < 0 )
1973        aal5r_max_packet_size = 0;
1974    else if ( aal5r_max_packet_size >= 65535 - MAX_RX_FRAME_EXTRA_BYTES )
1975        aal5r_max_packet_size = 65535 - MAX_RX_FRAME_EXTRA_BYTES;
1976    if ( aal5r_min_packet_size < 0 )
1977        aal5r_min_packet_size = 0;
1978    else if ( aal5r_min_packet_size > aal5r_max_packet_size )
1979        aal5r_min_packet_size = aal5r_max_packet_size;
1980    if ( aal5s_max_packet_size < 0 )
1981        aal5s_max_packet_size = 0;
1982    else if ( aal5s_max_packet_size >= 65535 - MAX_TX_FRAME_EXTRA_BYTES )
1983        aal5s_max_packet_size = 65535 - MAX_TX_FRAME_EXTRA_BYTES;
1984    if ( aal5s_min_packet_size < 0 )
1985        aal5s_min_packet_size = 0;
1986    else if ( aal5s_min_packet_size > aal5s_max_packet_size )
1987        aal5s_min_packet_size = aal5s_max_packet_size;
1988
1989    if ( dma_rx_descriptor_length < 2 )
1990        dma_rx_descriptor_length = 2;
1991    if ( dma_tx_descriptor_length < 2 )
1992        dma_tx_descriptor_length = 2;
1993    if ( dma_rx_clp1_descriptor_threshold < 0 )
1994        dma_rx_clp1_descriptor_threshold = 0;
1995    else if ( dma_rx_clp1_descriptor_threshold > dma_rx_descriptor_length )
1996        dma_rx_clp1_descriptor_threshold = dma_rx_descriptor_length;
1997
1998    if ( dma_tx_descriptor_length < 2 )
1999        dma_tx_descriptor_length = 2;
2000}
2001
2002static INLINE int init_priv_data(void)
2003{
2004    void *p;
2005    int i;
2006    struct rx_descriptor rx_desc = {0};
2007    struct sk_buff *skb;
2008    volatile struct tx_descriptor *p_tx_desc;
2009    struct sk_buff **ppskb;
2010
2011    //  clear atm private data structure
2012    memset(&g_atm_priv_data, 0, sizeof(g_atm_priv_data));
2013
2014    //  allocate memory for RX (AAL) descriptors
2015    p = kzalloc(dma_rx_descriptor_length * sizeof(struct rx_descriptor) + DESC_ALIGNMENT, GFP_KERNEL);
2016    if ( p == NULL )
2017        return IFX_ERROR;
2018    dma_cache_wback_inv((unsigned long)p, dma_rx_descriptor_length * sizeof(struct rx_descriptor) + DESC_ALIGNMENT);
2019    g_atm_priv_data.aal_desc_base = p;
2020    p = (void *)((((unsigned int)p + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1);
2021    g_atm_priv_data.aal_desc = (volatile struct rx_descriptor *)p;
2022
2023    //  allocate memory for RX (OAM) descriptors
2024    p = kzalloc(RX_DMA_CH_OAM_DESC_LEN * sizeof(struct rx_descriptor) + DESC_ALIGNMENT, GFP_KERNEL);
2025    if ( p == NULL )
2026        return IFX_ERROR;
2027    dma_cache_wback_inv((unsigned long)p, RX_DMA_CH_OAM_DESC_LEN * sizeof(struct rx_descriptor) + DESC_ALIGNMENT);
2028    g_atm_priv_data.oam_desc_base = p;
2029    p = (void *)((((unsigned int)p + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1);
2030    g_atm_priv_data.oam_desc = (volatile struct rx_descriptor *)p;
2031
2032    //  allocate memory for RX (OAM) buffer
2033    p = kzalloc(RX_DMA_CH_OAM_DESC_LEN * RX_DMA_CH_OAM_BUF_SIZE + DATA_BUFFER_ALIGNMENT, GFP_KERNEL);
2034    if ( p == NULL )
2035        return IFX_ERROR;
2036    dma_cache_wback_inv((unsigned long)p, RX_DMA_CH_OAM_DESC_LEN * RX_DMA_CH_OAM_BUF_SIZE + DATA_BUFFER_ALIGNMENT);
2037    g_atm_priv_data.oam_buf_base = p;
2038    p = (void *)(((unsigned int)p + DATA_BUFFER_ALIGNMENT - 1) & ~(DATA_BUFFER_ALIGNMENT - 1));
2039    g_atm_priv_data.oam_buf = p;
2040
2041    //  allocate memory for TX descriptors
2042    p = kzalloc(MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct tx_descriptor) + DESC_ALIGNMENT, GFP_KERNEL);
2043    if ( p == NULL )
2044        return IFX_ERROR;
2045    dma_cache_wback_inv((unsigned long)p, MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct tx_descriptor) + DESC_ALIGNMENT);
2046    g_atm_priv_data.tx_desc_base = p;
2047
2048    //  allocate memory for TX skb pointers
2049    p = kzalloc(MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct sk_buff *) + 4, GFP_KERNEL);
2050    if ( p == NULL )
2051        return IFX_ERROR;
2052    dma_cache_wback_inv((unsigned long)p, MAX_PVC_NUMBER * dma_tx_descriptor_length * sizeof(struct sk_buff *) + 4);
2053    g_atm_priv_data.tx_skb_base = p;
2054
2055    //  setup RX (AAL) descriptors
2056    rx_desc.own     = 1;
2057    rx_desc.c       = 0;
2058    rx_desc.sop     = 1;
2059    rx_desc.eop     = 1;
2060    rx_desc.byteoff = 0;
2061    rx_desc.id      = 0;
2062    rx_desc.err     = 0;
2063    rx_desc.datalen = RX_DMA_CH_AAL_BUF_SIZE;
2064    for ( i = 0; i < dma_rx_descriptor_length; i++ ) {
2065        skb = alloc_skb_rx();
2066        if ( skb == NULL )
2067            return IFX_ERROR;
2068        rx_desc.dataptr = ((unsigned int)skb->data >> 2) & 0x0FFFFFFF;
2069        g_atm_priv_data.aal_desc[i] = rx_desc;
2070    }
2071
2072    //  setup RX (OAM) descriptors
2073    p = (void *)((unsigned int)g_atm_priv_data.oam_buf | KSEG1);
2074    rx_desc.own     = 1;
2075    rx_desc.c       = 0;
2076    rx_desc.sop     = 1;
2077    rx_desc.eop     = 1;
2078    rx_desc.byteoff = 0;
2079    rx_desc.id      = 0;
2080    rx_desc.err     = 0;
2081    rx_desc.datalen = RX_DMA_CH_OAM_BUF_SIZE;
2082    for ( i = 0; i < RX_DMA_CH_OAM_DESC_LEN; i++ ) {
2083        rx_desc.dataptr = ((unsigned int)p >> 2) & 0x0FFFFFFF;
2084        g_atm_priv_data.oam_desc[i] = rx_desc;
2085        p = (void *)((unsigned int)p + RX_DMA_CH_OAM_BUF_SIZE);
2086    }
2087
2088    //  setup TX descriptors and skb pointers
2089    p_tx_desc = (volatile struct tx_descriptor *)((((unsigned int)g_atm_priv_data.tx_desc_base + DESC_ALIGNMENT - 1) & ~(DESC_ALIGNMENT - 1)) | KSEG1);
2090    ppskb = (struct sk_buff **)(((unsigned int)g_atm_priv_data.tx_skb_base + 3) & ~3);
2091    for ( i = 0; i < MAX_PVC_NUMBER; i++ ) {
2092        g_atm_priv_data.conn[i].tx_desc = &p_tx_desc[i * dma_tx_descriptor_length];
2093        g_atm_priv_data.conn[i].tx_skb  = &ppskb[i * dma_tx_descriptor_length];
2094    }
2095
2096    for ( i = 0; i < ATM_PORT_NUMBER; i++ )
2097        g_atm_priv_data.port[i].tx_max_cell_rate = DEFAULT_TX_LINK_RATE;
2098
2099    return IFX_SUCCESS;
2100}
2101
2102static INLINE void clear_priv_data(void)
2103{
2104    int i, j;
2105    struct sk_buff *skb;
2106
2107    for ( i = 0; i < MAX_PVC_NUMBER; i++ ) {
2108        if ( g_atm_priv_data.conn[i].tx_skb != NULL ) {
2109            for ( j = 0; j < dma_tx_descriptor_length; j++ )
2110                if ( g_atm_priv_data.conn[i].tx_skb[j] != NULL )
2111                    dev_kfree_skb_any(g_atm_priv_data.conn[i].tx_skb[j]);
2112        }
2113    }
2114
2115    if ( g_atm_priv_data.tx_skb_base != NULL )
2116        kfree(g_atm_priv_data.tx_skb_base);
2117
2118    if ( g_atm_priv_data.tx_desc_base != NULL )
2119        kfree(g_atm_priv_data.tx_desc_base);
2120
2121    if ( g_atm_priv_data.oam_buf_base != NULL )
2122        kfree(g_atm_priv_data.oam_buf_base);
2123
2124    if ( g_atm_priv_data.oam_desc_base != NULL )
2125        kfree(g_atm_priv_data.oam_desc_base);
2126
2127    if ( g_atm_priv_data.aal_desc_base != NULL ) {
2128        for ( i = 0; i < dma_rx_descriptor_length; i++ ) {
2129            if ( g_atm_priv_data.aal_desc[i].sop || g_atm_priv_data.aal_desc[i].eop ) { //  descriptor initialized
2130                skb = get_skb_rx_pointer(g_atm_priv_data.aal_desc[i].dataptr);
2131                dev_kfree_skb_any(skb);
2132            }
2133        }
2134        kfree(g_atm_priv_data.aal_desc_base);
2135    }
2136}
2137
2138static INLINE void init_rx_tables(void)
2139{
2140    int i;
2141    struct wrx_queue_config wrx_queue_config = {0};
2142    struct wrx_dma_channel_config wrx_dma_channel_config = {0};
2143    struct htu_entry htu_entry = {0};
2144    struct htu_result htu_result = {0};
2145    struct htu_mask htu_mask = {    set:        0x01,
2146                                    clp:        0x01,
2147                                    pid_mask:   0x00,
2148                                    vpi_mask:   0x00,
2149                                    vci_mask:   0x00,
2150                                    pti_mask:   0x00,
2151                                    clear:      0x00};
2152
2153    /*
2154     *  General Registers
2155     */
2156    *CFG_WRX_HTUTS  = MAX_PVC_NUMBER + OAM_HTU_ENTRY_NUMBER;
2157    *CFG_WRX_QNUM   = MAX_QUEUE_NUMBER;
2158    *CFG_WRX_DCHNUM = RX_DMA_CH_TOTAL;
2159    *WRX_DMACH_ON   = (1 << RX_DMA_CH_TOTAL) - 1;
2160    *WRX_HUNT_BITTH = DEFAULT_RX_HUNT_BITTH;
2161
2162    /*
2163     *  WRX Queue Configuration Table
2164     */
2165    wrx_queue_config.uumask    = 0;
2166    wrx_queue_config.cpimask   = 0;
2167    wrx_queue_config.uuexp     = 0;
2168    wrx_queue_config.cpiexp    = 0;
2169    wrx_queue_config.mfs       = aal5r_max_packet_size;
2170    wrx_queue_config.oversize  = aal5r_max_packet_size;
2171    wrx_queue_config.undersize = aal5r_min_packet_size;
2172    wrx_queue_config.errdp     = aal5r_drop_error_packet;
2173    wrx_queue_config.dmach     = RX_DMA_CH_AAL;
2174    for ( i = 0; i < MAX_QUEUE_NUMBER; i++ )
2175        *WRX_QUEUE_CONFIG(i) = wrx_queue_config;
2176    WRX_QUEUE_CONFIG(OAM_RX_QUEUE)->dmach = RX_DMA_CH_OAM;
2177
2178    /*
2179     *  WRX DMA Channel Configuration Table
2180     */
2181    wrx_dma_channel_config.chrl   = 0;
2182    wrx_dma_channel_config.clp1th = dma_rx_clp1_descriptor_threshold;
2183    wrx_dma_channel_config.mode   = 0;
2184    wrx_dma_channel_config.rlcfg  = 0;
2185
2186    wrx_dma_channel_config.deslen = RX_DMA_CH_OAM_DESC_LEN;
2187    wrx_dma_channel_config.desba  = ((unsigned int)g_atm_priv_data.oam_desc >> 2) & 0x0FFFFFFF;
2188    *WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_OAM) = wrx_dma_channel_config;
2189
2190    wrx_dma_channel_config.deslen = dma_rx_descriptor_length;
2191    wrx_dma_channel_config.desba  = ((unsigned int)g_atm_priv_data.aal_desc >> 2) & 0x0FFFFFFF;
2192    *WRX_DMA_CHANNEL_CONFIG(RX_DMA_CH_AAL) = wrx_dma_channel_config;
2193
2194    /*
2195     *  HTU Tables
2196     */
2197    for ( i = 0; i < MAX_PVC_NUMBER; i++ )
2198    {
2199        htu_result.qid = (unsigned int)i;
2200
2201        *HTU_ENTRY(i + OAM_HTU_ENTRY_NUMBER)  = htu_entry;
2202        *HTU_MASK(i + OAM_HTU_ENTRY_NUMBER)   = htu_mask;
2203        *HTU_RESULT(i + OAM_HTU_ENTRY_NUMBER) = htu_result;
2204    }
2205    /*  OAM HTU Entry   */
2206    htu_entry.vci     = 0x03;
2207    htu_mask.pid_mask = 0x03;
2208    htu_mask.vpi_mask = 0xFF;
2209    htu_mask.vci_mask = 0x0000;
2210    htu_mask.pti_mask = 0x07;
2211    htu_result.cellid = OAM_RX_QUEUE;
2212    htu_result.type   = 1;
2213    htu_result.ven    = 1;
2214    htu_result.qid    = OAM_RX_QUEUE;
2215    *HTU_RESULT(OAM_F4_SEG_HTU_ENTRY) = htu_result;
2216    *HTU_MASK(OAM_F4_SEG_HTU_ENTRY)   = htu_mask;
2217    *HTU_ENTRY(OAM_F4_SEG_HTU_ENTRY)  = htu_entry;
2218    htu_entry.vci     = 0x04;
2219    htu_result.cellid = OAM_RX_QUEUE;
2220    htu_result.type   = 1;
2221    htu_result.ven    = 1;
2222    htu_result.qid    = OAM_RX_QUEUE;
2223    *HTU_RESULT(OAM_F4_TOT_HTU_ENTRY) = htu_result;
2224    *HTU_MASK(OAM_F4_TOT_HTU_ENTRY)   = htu_mask;
2225    *HTU_ENTRY(OAM_F4_TOT_HTU_ENTRY)  = htu_entry;
2226    htu_entry.vci     = 0x00;
2227    htu_entry.pti     = 0x04;
2228    htu_mask.vci_mask = 0xFFFF;
2229    htu_mask.pti_mask = 0x01;
2230    htu_result.cellid = OAM_RX_QUEUE;
2231    htu_result.type   = 1;
2232    htu_result.ven    = 1;
2233    htu_result.qid    = OAM_RX_QUEUE;
2234    *HTU_RESULT(OAM_F5_HTU_ENTRY) = htu_result;
2235    *HTU_MASK(OAM_F5_HTU_ENTRY)   = htu_mask;
2236    *HTU_ENTRY(OAM_F5_HTU_ENTRY)  = htu_entry;
2237#if defined(ENABLE_ATM_RETX) && ENABLE_ATM_RETX
2238    htu_entry.pid     = 0x0;
2239    htu_entry.vpi     = 0x01;
2240    htu_entry.vci     = 0x0001;
2241    htu_entry.pti     = 0x00;
2242    htu_mask.pid_mask = 0x0;
2243    htu_mask.vpi_mask = 0x00;
2244    htu_mask.vci_mask = 0x0000;
2245    htu_mask.pti_mask = 0x3;
2246    htu_result.cellid = OAM_RX_QUEUE;
2247    htu_result.type   = 1;
2248    htu_result.ven    = 1;
2249    htu_result.qid    = OAM_RX_QUEUE;
2250    *HTU_RESULT(OAM_ARQ_HTU_ENTRY) = htu_result;
2251    *HTU_MASK(OAM_ARQ_HTU_ENTRY)   = htu_mask;
2252    *HTU_ENTRY(OAM_ARQ_HTU_ENTRY)  = htu_entry;
2253#endif
2254}
2255
2256static INLINE void init_tx_tables(void)
2257{
2258    int i;
2259    struct wtx_queue_config wtx_queue_config = {0};
2260    struct wtx_dma_channel_config wtx_dma_channel_config = {0};
2261    struct wtx_port_config wtx_port_config = {  res1:   0,
2262                                                qid:    0,
2263                                                qsben:  1};
2264
2265    /*
2266     *  General Registers
2267     */
2268    *CFG_WTX_DCHNUM     = MAX_TX_DMA_CHANNEL_NUMBER;
2269    *WTX_DMACH_ON       = ((1 << MAX_TX_DMA_CHANNEL_NUMBER) - 1) ^ ((1 << FIRST_QSB_QID) - 1);
2270    *CFG_WRDES_DELAY    = write_descriptor_delay;
2271
2272    /*
2273     *  WTX Port Configuration Table
2274     */
2275    for ( i = 0; i < ATM_PORT_NUMBER; i++ )
2276        *WTX_PORT_CONFIG(i) = wtx_port_config;
2277
2278    /*
2279     *  WTX Queue Configuration Table
2280     */
2281    wtx_queue_config.type  = 0x0;
2282    wtx_queue_config.qsben = 1;
2283    wtx_queue_config.sbid  = 0;
2284    for ( i = 0; i < MAX_TX_DMA_CHANNEL_NUMBER; i++ )
2285        *WTX_QUEUE_CONFIG(i) = wtx_queue_config;
2286
2287    /*
2288     *  WTX DMA Channel Configuration Table
2289     */
2290    wtx_dma_channel_config.mode   = 0;
2291    wtx_dma_channel_config.deslen = 0;
2292    wtx_dma_channel_config.desba  = 0;
2293    for ( i = 0; i < FIRST_QSB_QID; i++ )
2294        *WTX_DMA_CHANNEL_CONFIG(i) = wtx_dma_channel_config;
2295    /*  normal connection   */
2296    wtx_dma_channel_config.deslen = dma_tx_descriptor_length;
2297    for ( ; i < MAX_TX_DMA_CHANNEL_NUMBER ; i++ ) {
2298        wtx_dma_channel_config.desba = ((unsigned int)g_atm_priv_data.conn[i - FIRST_QSB_QID].tx_desc >> 2) & 0x0FFFFFFF;
2299        *WTX_DMA_CHANNEL_CONFIG(i) = wtx_dma_channel_config;
2300    }
2301}
2302
2303
2304
2305/*
2306 * ####################################
2307 *           Global Function
2308 * ####################################
2309 */
2310
2311static int atm_showtime_enter(struct port_cell_info *port_cell, void *xdata_addr)
2312{
2313    int i, j;
2314
2315    ASSERT(port_cell != NULL, "port_cell is NULL");
2316    ASSERT(xdata_addr != NULL, "xdata_addr is NULL");
2317
2318    for ( j = 0; j < ATM_PORT_NUMBER && j < port_cell->port_num; j++ )
2319        if ( port_cell->tx_link_rate[j] > 0 )
2320            break;
2321    for ( i = 0; i < ATM_PORT_NUMBER && i < port_cell->port_num; i++ )
2322        g_atm_priv_data.port[i].tx_max_cell_rate = port_cell->tx_link_rate[i] > 0 ? port_cell->tx_link_rate[i] : port_cell->tx_link_rate[j];
2323
2324    qsb_global_set();
2325
2326    for ( i = 0; i < MAX_PVC_NUMBER; i++ )
2327        if ( g_atm_priv_data.conn[i].vcc != NULL )
2328            set_qsb(g_atm_priv_data.conn[i].vcc, &g_atm_priv_data.conn[i].vcc->qos, i);
2329
2330    //  TODO: ReTX set xdata_addr
2331    g_xdata_addr = xdata_addr;
2332
2333    g_showtime = 1;
2334
2335#if defined(CONFIG_VR9)
2336    IFX_REG_W32(0x0F, UTP_CFG);
2337#endif
2338
2339    printk("enter showtime, cell rate: 0 - %d, 1 - %d, xdata addr: 0x%08x\n", g_atm_priv_data.port[0].tx_max_cell_rate, g_atm_priv_data.port[1].tx_max_cell_rate, (unsigned int)g_xdata_addr);
2340
2341    return IFX_SUCCESS;
2342}
2343
2344static int atm_showtime_exit(void)
2345{
2346#if defined(CONFIG_VR9)
2347    IFX_REG_W32(0x00, UTP_CFG);
2348#endif
2349
2350    g_showtime = 0;
2351
2352    //  TODO: ReTX clean state
2353    g_xdata_addr = NULL;
2354
2355    printk("leave showtime\n");
2356
2357    return IFX_SUCCESS;
2358}
2359
2360
2361
2362/*
2363 * ####################################
2364 *           Init/Cleanup API
2365 * ####################################
2366 */
2367
2368/*
2369 *  Description:
2370 *    Initialize global variables, PP32, comunication structures, register IRQ
2371 *    and register device.
2372 *  Input:
2373 *    none
2374 *  Output:
2375 *    0    --- successful
2376 *    else --- failure, usually it is negative value of error code
2377 */
2378static int __devinit ifx_atm_init(void)
2379{
2380    int ret;
2381    int port_num;
2382    struct port_cell_info port_cell = {0};
2383    int i, j;
2384    char ver_str[256];
2385
2386#ifdef MODULE
2387    reset_ppe();
2388#endif
2389
2390    check_parameters();
2391
2392    ret = init_priv_data();
2393    if ( ret != IFX_SUCCESS ) {
2394        err("INIT_PRIV_DATA_FAIL");
2395        goto INIT_PRIV_DATA_FAIL;
2396    }
2397
2398    ifx_atm_init_chip();
2399    init_rx_tables();
2400    init_tx_tables();
2401
2402    /*  create devices  */
2403    for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ ) {
2404        g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", &g_ifx_atm_ops, -1, NULL);
2405        if ( !g_atm_priv_data.port[port_num].dev ) {
2406            err("failed to register atm device %d!", port_num);
2407            ret = -EIO;
2408            goto ATM_DEV_REGISTER_FAIL;
2409        }
2410        else {
2411            g_atm_priv_data.port[port_num].dev->ci_range.vpi_bits = 8;
2412            g_atm_priv_data.port[port_num].dev->ci_range.vci_bits = 16;
2413            g_atm_priv_data.port[port_num].dev->link_rate = g_atm_priv_data.port[port_num].tx_max_cell_rate;
2414            g_atm_priv_data.port[port_num].dev->dev_data = (void*)port_num;
2415        }
2416    }
2417
2418    /*  register interrupt handler  */
2419    ret = request_irq(PPE_MAILBOX_IGU1_INT, mailbox_irq_handler, IRQF_DISABLED, "atm_mailbox_isr", &g_atm_priv_data);
2420    if ( ret ) {
2421        if ( ret == -EBUSY ) {
2422            err("IRQ may be occupied by other driver, please reconfig to disable it.");
2423        }
2424        else {
2425            err("request_irq fail");
2426        }
2427        goto REQUEST_IRQ_PPE_MAILBOX_IGU1_INT_FAIL;
2428    }
2429    disable_irq(PPE_MAILBOX_IGU1_INT);
2430
2431    ret = ifx_pp32_start(0);
2432    if ( ret ) {
2433        err("ifx_pp32_start fail!");
2434        goto PP32_START_FAIL;
2435    }
2436
2437    port_cell.port_num = ATM_PORT_NUMBER;
2438    ifx_mei_atm_showtime_check(&g_showtime, &port_cell, &g_xdata_addr);
2439    if ( g_showtime ) {
2440        for ( i = 0; i < ATM_PORT_NUMBER; i++ )
2441            if ( port_cell.tx_link_rate[i] != 0 )
2442                break;
2443        for ( j = 0; j < ATM_PORT_NUMBER; j++ )
2444            g_atm_priv_data.port[j].tx_max_cell_rate = port_cell.tx_link_rate[j] != 0 ? port_cell.tx_link_rate[j] : port_cell.tx_link_rate[i];
2445    }
2446
2447    qsb_global_set();
2448    validate_oam_htu_entry();
2449
2450    /*  create proc file    */
2451    proc_file_create();
2452
2453    ifx_mei_atm_showtime_enter = atm_showtime_enter;
2454    ifx_mei_atm_showtime_exit  = atm_showtime_exit;
2455
2456    ifx_atm_version(ver_str);
2457    printk(KERN_INFO "%s", ver_str);
2458
2459    printk("ifxmips_atm: ATM init succeed\n");
2460
2461    return IFX_SUCCESS;
2462
2463PP32_START_FAIL:
2464    free_irq(PPE_MAILBOX_IGU1_INT, &g_atm_priv_data);
2465REQUEST_IRQ_PPE_MAILBOX_IGU1_INT_FAIL:
2466ATM_DEV_REGISTER_FAIL:
2467    while ( port_num-- > 0 )
2468        atm_dev_deregister(g_atm_priv_data.port[port_num].dev);
2469INIT_PRIV_DATA_FAIL:
2470    clear_priv_data();
2471    printk("ifxmips_atm: ATM init failed\n");
2472    return ret;
2473}
2474
2475/*
2476 *  Description:
2477 *    Release memory, free IRQ, and deregister device.
2478 *  Input:
2479 *    none
2480 *  Output:
2481 *   none
2482 */
2483static void __exit ifx_atm_exit(void)
2484{
2485    int port_num;
2486
2487    ifx_mei_atm_showtime_enter = NULL;
2488    ifx_mei_atm_showtime_exit  = NULL;
2489
2490    proc_file_delete();
2491
2492    invalidate_oam_htu_entry();
2493
2494    ifx_pp32_stop(0);
2495
2496    free_irq(PPE_MAILBOX_IGU1_INT, &g_atm_priv_data);
2497
2498    for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ )
2499        atm_dev_deregister(g_atm_priv_data.port[port_num].dev);
2500
2501    ifx_atm_uninit_chip();
2502
2503    clear_priv_data();
2504}
2505
2506module_init(ifx_atm_init);
2507module_exit(ifx_atm_exit);
Note: See TracBrowser for help on using the repository browser.