Changeset 9324


Ignore:
Timestamp:
2007-10-15T08:22:34+02:00 (10 years ago)
Author:
juhosg
Message:

[adm5120] switch driver cleanup, 1st phase

Location:
trunk/target/linux/adm5120/files
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/adm5120/files/drivers/net/adm5120sw.c

    r8309 r9324  
    1313 * 
    1414 */ 
    15 #include <linux/autoconf.h> 
     15#include <linux/kernel.h> 
    1616#include <linux/module.h> 
    17 #include <linux/kernel.h> 
     17#include <linux/errno.h> 
     18#include <linux/interrupt.h> 
     19#include <linux/ioport.h> 
     20#include <linux/spinlock.h> 
     21 
    1822#include <linux/netdevice.h> 
    1923#include <linux/etherdevice.h> 
    2024#include <linux/skbuff.h> 
    21 #include <linux/errno.h> 
    22 #include <linux/interrupt.h> 
    23 #include <linux/ioport.h> 
     25 
     26#include <linux/io.h> 
     27#include <linux/irq.h> 
     28 
    2429#include <asm/mipsregs.h> 
    25 #include <asm/irq.h> 
    26 #include <asm/io.h> 
     30 
     31#include <adm5120_info.h> 
     32#include <adm5120_defs.h> 
     33#include <adm5120_irq.h> 
     34#include <adm5120_switch.h> 
     35 
    2736#include "adm5120sw.h" 
    2837 
    29 #include <asm/mach-adm5120/adm5120_info.h> 
    30 #include <asm/mach-adm5120/adm5120_irq.h> 
     38#define DRV_NAME        "adm5120-switch" 
     39#define DRV_DESC        "ADM5120 built-in ethernet switch driver" 
     40#define DRV_VERSION     "0.1.0" 
    3141 
    3242MODULE_AUTHOR("Jeroen Vreeken (pe1rxq@amsat.org)"); 
     
    3444MODULE_LICENSE("GPL"); 
    3545 
     46/* ------------------------------------------------------------------------ */ 
     47 
     48#if 1 /*def ADM5120_SWITCH_DEBUG*/ 
     49#define SW_DBG(f, a...)         printk(KERN_DEBUG "%s: " f, DRV_NAME , ## a) 
     50#else 
     51#define SW_DBG(f, a...)         do {} while (0) 
     52#endif 
     53#define SW_ERR(f, a...)         printk(KERN_ERR "%s: " f, DRV_NAME , ## a) 
     54#define SW_INFO(f, a...)        printk(KERN_INFO "%s: " f, DRV_NAME , ## a) 
     55 
     56#define SWITCH_NUM_PORTS        6 
     57#define ETH_CSUM_LEN            4 
     58 
     59#define RX_MAX_PKTLEN   1550 
     60#define RX_RING_SIZE    64 
     61 
     62#define TX_RING_SIZE    32 
     63#define TX_QUEUE_LEN    28      /* Limit ring entries actually used. */ 
     64#define TX_TIMEOUT      HZ*400 
     65 
     66#define SKB_ALLOC_LEN           (RX_MAX_PKTLEN + 32) 
     67#define SKB_RESERVE_LEN         (NET_IP_ALIGN + NET_SKB_PAD) 
     68 
     69#define SWITCH_INTS_HIGH (SWITCH_INT_SHD | SWITCH_INT_RHD | SWITCH_INT_HDF) 
     70#define SWITCH_INTS_LOW (SWITCH_INT_SLD | SWITCH_INT_RLD | SWITCH_INT_LDF) 
     71#define SWITCH_INTS_ERR (SWITCH_INT_RDE | SWITCH_INT_SDE | SWITCH_INT_CPUH) 
     72#define SWITCH_INTS_Q (SWITCH_INT_P0QF | SWITCH_INT_P1QF | SWITCH_INT_P2QF | \ 
     73                        SWITCH_INT_P3QF | SWITCH_INT_P4QF | SWITCH_INT_P5QF | \ 
     74                        SWITCH_INT_CPQF | SWITCH_INT_GQF) 
     75 
     76#define SWITCH_INTS_ALL (SWITCH_INTS_HIGH | SWITCH_INTS_LOW | \ 
     77                        SWITCH_INTS_ERR | SWITCH_INTS_Q | \ 
     78                        SWITCH_INT_MD | SWITCH_INT_PSC) 
     79 
     80#define SWITCH_INTS_USED (SWITCH_INTS_LOW | SWITCH_INT_PSC) 
     81#define SWITCH_INTS_POLL (SWITCH_INT_RLD | SWITCH_INT_LDF) 
     82 
     83/* ------------------------------------------------------------------------ */ 
     84 
     85struct dma_desc { 
     86        __u32                   buf1; 
     87#define DESC_OWN                (1UL << 31)     /* Owned by the switch */ 
     88#define DESC_EOR                (1UL << 28)     /* End of Ring */ 
     89#define DESC_ADDR_MASK          0x1FFFFFF 
     90#define DESC_ADDR(x)    ((__u32)(x) & DESC_ADDR_MASK) 
     91        __u32                   buf2; 
     92#define DESC_BUF2_EN            (1UL << 31)     /* Buffer 2 enable */ 
     93        __u32                   buflen; 
     94        __u32                   misc; 
     95/* definitions for tx/rx descriptors */ 
     96#define DESC_PKTLEN_SHIFT       16 
     97#define DESC_PKTLEN_MASK        0x7FF 
     98/* tx descriptor specific part */ 
     99#define DESC_CSUM               (1UL << 31)     /* Append checksum */ 
     100#define DESC_DSTPORT_SHIFT      8 
     101#define DESC_DSTPORT_MASK       0x3F 
     102#define DESC_VLAN_MASK          0x3F 
     103/* rx descriptor specific part */ 
     104#define DESC_SRCPORT_SHIFT      12 
     105#define DESC_SRCPORT_MASK       0x7 
     106#define DESC_DA_MASK            0x3 
     107#define DESC_DA_SHIFT           4 
     108#define DESC_IPCSUM_FAIL        (1UL << 3)      /* IP checksum fail */ 
     109#define DESC_VLAN_TAG           (1UL << 2)      /* VLAN tag present */ 
     110#define DESC_TYPE_MASK          0x3             /* mask for Packet type */ 
     111#define DESC_TYPE_IP            0x0             /* IP packet */ 
     112#define DESC_TYPE_PPPoE         0x1             /* PPPoE packet */ 
     113} __attribute__ ((aligned(16))); 
     114 
     115static inline u32 desc_get_srcport(struct dma_desc *desc) 
     116{ 
     117        return (desc->misc >> DESC_SRCPORT_SHIFT) & DESC_SRCPORT_MASK; 
     118} 
     119 
     120static inline u32 desc_get_pktlen(struct dma_desc *desc) 
     121{ 
     122        return (desc->misc >> DESC_PKTLEN_SHIFT) & DESC_PKTLEN_MASK; 
     123} 
     124 
     125static inline int desc_ipcsum_fail(struct dma_desc *desc) 
     126{ 
     127        return ((desc->misc & DESC_IPCSUM_FAIL) != 0); 
     128} 
     129 
     130/* ------------------------------------------------------------------------ */ 
     131 
    36132/* default settings - unlimited TX and RX on all ports, default shaper mode */ 
    37 static unsigned char bw_matrix[SW_DEVS] = { 
     133static unsigned char bw_matrix[SWITCH_NUM_PORTS] = { 
    38134        0, 0, 0, 0, 0, 0 
    39135}; 
     
    41137static int adm5120_nrdevs; 
    42138 
    43 static struct net_device *adm5120_devs[SW_DEVS]; 
     139static struct net_device *adm5120_devs[SWITCH_NUM_PORTS]; 
    44140/* Lookup table port -> device */ 
    45 static struct net_device *adm5120_port[SW_DEVS]; 
    46  
    47 static struct adm5120_dma 
    48     adm5120_dma_txh_v[ADM5120_DMA_TXH] __attribute__((aligned(16))), 
    49     adm5120_dma_txl_v[ADM5120_DMA_TXL] __attribute__((aligned(16))), 
    50     adm5120_dma_rxh_v[ADM5120_DMA_RXH] __attribute__((aligned(16))), 
    51     adm5120_dma_rxl_v[ADM5120_DMA_RXL] __attribute__((aligned(16))), 
    52     *adm5120_dma_txh, 
    53     *adm5120_dma_txl, 
    54     *adm5120_dma_rxh, 
    55     *adm5120_dma_rxl; 
    56 static struct sk_buff 
    57     *adm5120_skb_rxh[ADM5120_DMA_RXH], 
    58     *adm5120_skb_rxl[ADM5120_DMA_RXL], 
    59     *adm5120_skb_txh[ADM5120_DMA_TXH], 
    60     *adm5120_skb_txl[ADM5120_DMA_TXL]; 
    61 static int adm5120_rxli = 0; 
    62 static int adm5120_txli = 0; 
    63 /*static int adm5120_txhi = 0;*/ 
    64 static int adm5120_if_open = 0; 
    65  
    66 static inline void adm5120_set_reg(unsigned int reg, unsigned long val) 
    67 { 
    68         *(volatile unsigned long*)(SW_BASE+reg) = val; 
    69 } 
    70  
    71 static inline unsigned long adm5120_get_reg(unsigned int reg) 
    72 { 
    73         return *(volatile unsigned long*)(SW_BASE+reg); 
    74 } 
    75  
    76 static inline void adm5120_rx_dma_update(struct adm5120_dma *dma, 
     141static struct net_device *adm5120_port[SWITCH_NUM_PORTS]; 
     142 
     143static struct dma_desc txh_descs_v[TX_RING_SIZE] __attribute__((aligned(16))); 
     144static struct dma_desc txl_descs_v[TX_RING_SIZE] __attribute__((aligned(16))); 
     145static struct dma_desc rxh_descs_v[RX_RING_SIZE] __attribute__((aligned(16))); 
     146static struct dma_desc rxl_descs_v[RX_RING_SIZE] __attribute__((aligned(16))); 
     147static struct dma_desc *txh_descs; 
     148static struct dma_desc *txl_descs; 
     149static struct dma_desc *rxh_descs; 
     150static struct dma_desc *rxl_descs; 
     151 
     152static struct sk_buff *rxl_skbuff[RX_RING_SIZE]; 
     153static struct sk_buff *rxh_skbuff[RX_RING_SIZE]; 
     154static struct sk_buff *txl_skbuff[TX_RING_SIZE]; 
     155static struct sk_buff *txh_skbuff[TX_RING_SIZE]; 
     156 
     157static unsigned int cur_rxl, dirty_rxl; /* producer/consumer ring indices */ 
     158static unsigned int cur_txl, dirty_txl; 
     159 
     160static unsigned int sw_used; 
     161 
     162static spinlock_t sw_lock = SPIN_LOCK_UNLOCKED; 
     163 
     164static struct net_device sw_dev; 
     165 
     166/* ------------------------------------------------------------------------ */ 
     167 
     168static inline u32 sw_read_reg(u32 reg) 
     169{ 
     170        return __raw_readl((void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE)+reg); 
     171} 
     172 
     173static inline void sw_write_reg(u32 reg, u32 val) 
     174{ 
     175        __raw_writel(val, (void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE)+reg); 
     176} 
     177 
     178static inline void sw_int_disable(u32 mask) 
     179{ 
     180        u32     t; 
     181 
     182        t = sw_read_reg(SWITCH_REG_INT_MASK); 
     183        t |= mask; 
     184        sw_write_reg(SWITCH_REG_INT_MASK, t); 
     185} 
     186 
     187static inline void sw_int_enable(u32 mask) 
     188{ 
     189        u32     t; 
     190 
     191        t = sw_read_reg(SWITCH_REG_INT_MASK); 
     192        t &= ~mask; 
     193        sw_write_reg(SWITCH_REG_INT_MASK, t); 
     194} 
     195 
     196static inline void sw_int_ack(u32 mask) 
     197{ 
     198        sw_write_reg(SWITCH_REG_INT_STATUS, mask); 
     199} 
     200 
     201/* ------------------------------------------------------------------------ */ 
     202 
     203static void sw_dump_desc(char *label, struct dma_desc *desc, int tx) 
     204{ 
     205        u32 t; 
     206 
     207        SW_DBG("%s %s desc/%p\n", label, tx ? "tx" : "rx", desc); 
     208 
     209        t = desc->buf1; 
     210        SW_DBG("    buf1 %08X addr=%08X; len=%08X %s%s\n", t, 
     211                t & DESC_ADDR_MASK, 
     212                desc->buflen, 
     213                (t & DESC_OWN) ? "SWITCH" : "CPU", 
     214                (t & DESC_EOR) ? " RE" : ""); 
     215 
     216        t = desc->buf2; 
     217        SW_DBG("    buf2 %08X addr=%08X%s\n", desc->buf2, 
     218                t & DESC_ADDR_MASK, 
     219                (t & DESC_BUF2_EN) ? " EN" : "" ); 
     220 
     221        t = desc->misc; 
     222        if (tx) 
     223                SW_DBG("    misc %08X%s pktlen=%04X ports=%02X vlan=%02X\n", t, 
     224                        (t & DESC_CSUM) ? " CSUM" : "", 
     225                        (t >> DESC_PKTLEN_SHIFT) & DESC_PKTLEN_MASK, 
     226                        (t >> DESC_DSTPORT_SHIFT) & DESC_DSTPORT_MASK, 
     227                        t & DESC_VLAN_MASK); 
     228        else 
     229                SW_DBG("    misc %08X pktlen=%04X port=%d DA=%d%s%s type=%d\n", 
     230                        t, 
     231                        (t >> DESC_PKTLEN_SHIFT) & DESC_PKTLEN_MASK, 
     232                        (t >> DESC_SRCPORT_SHIFT) & DESC_SRCPORT_MASK, 
     233                        (t >> DESC_DA_SHIFT) & DESC_DA_MASK, 
     234                        (t & DESC_IPCSUM_FAIL) ? " IPCF" : "", 
     235                        (t & DESC_VLAN_TAG) ? " VLAN" : "", 
     236                        (t & DESC_TYPE_MASK)); 
     237} 
     238 
     239static void sw_dump_intr_mask(char *label, u32 mask) 
     240{ 
     241        SW_DBG("%s %08X%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", 
     242                label, mask, 
     243                (mask & SWITCH_INT_SHD) ? " SHD" : "", 
     244                (mask & SWITCH_INT_SLD) ? " SLD" : "", 
     245                (mask & SWITCH_INT_RHD) ? " RHD" : "", 
     246                (mask & SWITCH_INT_RLD) ? " RLD" : "", 
     247                (mask & SWITCH_INT_HDF) ? " HDF" : "", 
     248                (mask & SWITCH_INT_LDF) ? " LDF" : "", 
     249                (mask & SWITCH_INT_P0QF) ? " P0QF" : "", 
     250                (mask & SWITCH_INT_P1QF) ? " P1QF" : "", 
     251                (mask & SWITCH_INT_P2QF) ? " P2QF" : "", 
     252                (mask & SWITCH_INT_P3QF) ? " P3QF" : "", 
     253                (mask & SWITCH_INT_P4QF) ? " P4QF" : "", 
     254                (mask & SWITCH_INT_CPQF) ? " CPQF" : "", 
     255                (mask & SWITCH_INT_GQF) ? " GQF" : "", 
     256                (mask & SWITCH_INT_MD) ? " MD" : "", 
     257                (mask & SWITCH_INT_BCS) ? " BCS" : "", 
     258                (mask & SWITCH_INT_PSC) ? " PSC" : "", 
     259                (mask & SWITCH_INT_ID) ? " ID" : "", 
     260                (mask & SWITCH_INT_W0TE) ? " W0TE" : "", 
     261                (mask & SWITCH_INT_W1TE) ? " W1TE" : "", 
     262                (mask & SWITCH_INT_RDE) ? " RDE" : "", 
     263                (mask & SWITCH_INT_SDE) ? " SDE" : "", 
     264                (mask & SWITCH_INT_CPUH) ? " CPUH" : ""); 
     265} 
     266 
     267/* ------------------------------------------------------------------------ */ 
     268 
     269static inline void adm5120_rx_dma_update(struct dma_desc *desc, 
    77270        struct sk_buff *skb, int end) 
    78271{ 
    79         dma->status = 0; 
    80         dma->cntl = 0; 
    81         dma->len = ADM5120_DMA_RXSIZE; 
    82         dma->data = ADM5120_DMA_ADDR(skb->data) | 
    83                 ADM5120_DMA_OWN | (end ? ADM5120_DMA_RINGEND : 0); 
    84 } 
    85  
    86 static int adm5120_rx(struct net_device *dev,int *budget) 
     272        desc->misc = 0; 
     273        desc->buf2 = 0; 
     274        desc->buflen = RX_MAX_PKTLEN; 
     275        desc->buf1 = DESC_ADDR(skb->data) | 
     276                DESC_OWN | (end ? DESC_EOR : 0); 
     277} 
     278 
     279static int adm5120_switch_rx(struct net_device *dev, int *budget) 
    87280{ 
    88281        struct sk_buff *skb, *skbn; 
    89282        struct adm5120_sw *priv; 
    90283        struct net_device *cdev; 
    91         struct adm5120_dma *dma; 
    92         int port, len, quota; 
     284        struct dma_desc *desc; 
     285        int len, quota; 
    93286 
    94287        quota = min(dev->quota, *budget); 
    95         dma = &adm5120_dma_rxl[adm5120_rxli]; 
    96         while (!(dma->data & ADM5120_DMA_OWN) && quota) { 
    97                 port = (dma->status & ADM5120_DMA_PORTID); 
    98                 port >>= ADM5120_DMA_PORTSHIFT; 
     288        SW_DBG("%s polling, quota=%d\n", dev->name, quota); 
     289 
     290        sw_int_ack(SWITCH_INTS_POLL); 
     291 
     292        desc = &rxl_descs[cur_rxl]; 
     293        while (!(desc->buf1 & DESC_OWN) && quota) { 
     294                u32 port = desc_get_srcport(desc); 
    99295                cdev = adm5120_port[port]; 
    100296                if (cdev != dev) {      /* The current packet belongs to a different device */ 
     
    110306 
    111307                } 
    112                 skb = adm5120_skb_rxl[adm5120_rxli]; 
    113                 len = (dma->status & ADM5120_DMA_LEN); 
    114                 len >>= ADM5120_DMA_LENSHIFT; 
    115                 len -= ETH_FCS; 
     308                skb = rxl_skbuff[cur_rxl]; 
     309                len = desc_get_pktlen(desc); 
     310                len -= ETH_CSUM_LEN; 
    116311 
    117312                priv = netdev_priv(dev); 
    118                 if (len <= 0 || len > ADM5120_DMA_RXSIZE || 
    119                         dma->status & ADM5120_DMA_FCSERR) { 
    120                         priv->stats.rx_errors++; 
     313                if (len <= 0 || len > RX_MAX_PKTLEN || 
     314                        desc_ipcsum_fail(desc)) { 
     315                        dev->stats.rx_errors++; 
    121316                        skbn = NULL; 
    122317                } else { 
    123                         skbn = dev_alloc_skb(ADM5120_DMA_RXSIZE+16); 
     318                        skbn = dev_alloc_skb(SKB_ALLOC_LEN); 
    124319                        if (skbn) { 
    125320                                skb_put(skb, len); 
     
    128323                                skb->ip_summed = CHECKSUM_UNNECESSARY; 
    129324                                dev->last_rx = jiffies; 
    130                                 priv->stats.rx_packets++; 
    131                                 priv->stats.rx_bytes += len; 
    132                                 skb_reserve(skbn, NET_IP_ALIGN); 
    133                                 adm5120_skb_rxl[adm5120_rxli] = skbn; 
     325                                dev->stats.rx_packets++; 
     326                                dev->stats.rx_bytes += len; 
     327                                skb_reserve(skbn, SKB_RESERVE_LEN); 
     328                                rxl_skbuff[cur_rxl] = skbn; 
    134329                        } else { 
    135                                 printk(KERN_INFO "%s recycling!\n", dev->name); 
     330                                SW_INFO("%s recycling!\n", dev->name); 
    136331                        } 
    137332                } 
    138333rx_skip: 
    139                 adm5120_rx_dma_update(&adm5120_dma_rxl[adm5120_rxli], 
    140                         adm5120_skb_rxl[adm5120_rxli], 
    141                         (ADM5120_DMA_RXL-1==adm5120_rxli)); 
    142                 if (ADM5120_DMA_RXL == ++adm5120_rxli) 
    143                         adm5120_rxli = 0; 
    144                 dma = &adm5120_dma_rxl[adm5120_rxli]; 
     334                adm5120_rx_dma_update(&rxl_descs[cur_rxl], 
     335                        rxl_skbuff[cur_rxl], 
     336                        (RX_RING_SIZE-1==cur_rxl)); 
     337                if (RX_RING_SIZE == ++cur_rxl) 
     338                        cur_rxl = 0; 
     339                desc = &rxl_descs[cur_rxl]; 
    145340                if (skbn){ 
    146341                        netif_receive_skb(skb); 
     
    150345                } 
    151346        } /* while */ 
     347 
     348        if (quota) { 
     349                netif_rx_complete(dev); 
     350                sw_int_enable(SWITCH_INTS_POLL); 
     351                return 0; 
     352        } 
     353 
    152354        /* If there are still packets to process, return 1 */ 
    153         if (quota){ 
    154                 /* No more packets to process, so disable the polling and reenable the interrupts */ 
    155                 netif_rx_complete(dev); 
    156                 adm5120_set_reg(ADM5120_INT_MASK, 
    157                         adm5120_get_reg(ADM5120_INT_MASK) & 
    158                         ~(ADM5120_INT_RXL|ADM5120_INT_LFULL)); 
    159                 return 0; 
    160  
    161  
    162         } 
    163355        return 1; 
    164356} 
    165357 
    166 static irqreturn_t adm5120_sw_irq(int irq, void *dev_id) 
    167 { 
    168         unsigned long intreg, intmask; 
    169         int port; 
    170         struct net_device *dev; 
    171  
    172         intmask = adm5120_get_reg(ADM5120_INT_MASK);   /* Remember interrupt mask */ 
    173         adm5120_set_reg(ADM5120_INT_MASK, ADM5120_INTMASKALL); /* Disable interrupts */ 
    174  
    175         intreg = adm5120_get_reg(ADM5120_INT_ST); /* Read interrupt status */ 
    176         adm5120_set_reg(ADM5120_INT_ST, intreg);  /* Clear interrupt status */ 
    177  
    178         /* In NAPI operation the interrupts are disabled and the polling mechanism 
    179          * is activated. The interrupts are finally enabled again in the polling routine. 
    180          */ 
    181         if (intreg & (ADM5120_INT_RXL|ADM5120_INT_LFULL)) { 
    182                 /* check rx buffer for port number */ 
    183                 port = adm5120_dma_rxl[adm5120_rxli].status & ADM5120_DMA_PORTID; 
    184                 port >>= ADM5120_DMA_PORTSHIFT; 
    185                 dev = adm5120_port[port]; 
    186                 if ((dev==NULL) || !netif_running(dev)) { 
    187                 /* discard (update with old skb) */ 
    188                         adm5120_rx_dma_update(&adm5120_dma_rxl[adm5120_rxli], 
    189                                 adm5120_skb_rxl[adm5120_rxli], 
    190                                 (ADM5120_DMA_RXL-1==adm5120_rxli)); 
    191                         if (ADM5120_DMA_RXL == ++adm5120_rxli) 
    192                                 adm5120_rxli = 0; 
     358static void adm5120_switch_tx(void) 
     359{ 
     360        unsigned int entry; 
     361 
     362        /* find and cleanup dirty tx descriptors */ 
     363        entry = dirty_txl % TX_RING_SIZE; 
     364        while (dirty_txl != cur_txl) { 
     365                struct dma_desc *desc = &txl_descs[entry]; 
     366                struct sk_buff *skb = txl_skbuff[entry]; 
     367 
     368                if (desc->buf1 & DESC_OWN) 
     369                        break; 
     370 
     371                sw_dump_desc("tx done", desc, 1); 
     372                if (netif_running(skb->dev)) { 
     373                        skb->dev->stats.tx_bytes += skb->len; 
     374                        skb->dev->stats.tx_packets++; 
    193375                } 
    194                 else { 
    195                         netif_rx_schedule(dev); 
    196                         intmask |= (ADM5120_INT_RXL|ADM5120_INT_LFULL); /* Disable RX interrupts */ 
     376 
     377                dev_kfree_skb_irq(skb); 
     378                txl_skbuff[entry] = NULL; 
     379                entry = (++dirty_txl) % TX_RING_SIZE; 
     380        } 
     381 
     382        if ((cur_txl - dirty_txl) < TX_QUEUE_LEN - 4) { 
     383                /* wake up queue of all devices */ 
     384                int i; 
     385                for (i = 0; i < SWITCH_NUM_PORTS; i++) { 
     386                        if (!adm5120_devs[i]) 
     387                                continue; 
     388                        netif_wake_queue(adm5120_devs[i]); 
    197389                } 
    198390        } 
    199 #ifdef CONFIG_DEBUG 
    200         if (intreg & ~(intmask)) 
    201                 printk(KERN_INFO "adm5120sw: IRQ 0x%08X unexpected!\n", (unsigned int)(intreg & ~(intmask))); 
    202 #endif 
    203  
    204         adm5120_set_reg(ADM5120_INT_MASK, intmask); 
     391} 
     392 
     393static irqreturn_t adm5120_poll_irq(int irq, void *dev_id) 
     394{ 
     395        struct net_device *dev = dev_id; 
     396        u32 status; 
     397 
     398        status = sw_read_reg(SWITCH_REG_INT_STATUS); 
     399        status &= ~(sw_read_reg(SWITCH_REG_INT_MASK)); 
     400 
     401        status &= SWITCH_INTS_POLL; 
     402        if (!status) 
     403                return IRQ_NONE; 
     404 
     405        sw_int_disable(SWITCH_INTS_POLL); 
     406        netif_rx_schedule(dev); 
     407 
     408        SW_DBG("%s handling IRQ%d\n", dev->name, irq); 
     409        return IRQ_HANDLED; 
     410} 
     411 
     412static irqreturn_t adm5120_switch_irq(int irq, void *dev_id) 
     413{ 
     414        irqreturn_t ret; 
     415        u32 status; 
     416 
     417        status = sw_read_reg(SWITCH_REG_INT_STATUS); 
     418        status &= ~(sw_read_reg(SWITCH_REG_INT_MASK)); 
     419 
     420        sw_dump_intr_mask("sw irq", status); 
     421 
     422        status &= SWITCH_INTS_ALL & ~SWITCH_INTS_POLL; 
     423        if (!status) 
     424                return IRQ_NONE; 
     425 
     426        sw_int_ack(status); 
     427 
     428        if (status & SWITCH_INT_SLD) { 
     429                spin_lock(&sw_lock); 
     430                adm5120_switch_tx(); 
     431                spin_unlock(&sw_lock); 
     432        } 
    205433 
    206434        return IRQ_HANDLED; 
     
    213441 
    214442        val = matrix[0] + (matrix[1]<<8) + (matrix[2]<<16) + (matrix[3]<<24); 
    215         adm5120_set_reg(ADM5120_VLAN_GI, val); 
     443        sw_write_reg(SWITCH_REG_VLAN_G1, val); 
    216444        val = matrix[4] + (matrix[5]<<8); 
    217         adm5120_set_reg(ADM5120_VLAN_GII, val); 
     445        sw_write_reg(SWITCH_REG_VLAN_G2, val); 
     446 
    218447        /* Now set/update the port vs. device lookup table */ 
    219         for (port=0; port<SW_DEVS; port++) { 
    220                 for (vlan_port=0; vlan_port<SW_DEVS && !(matrix[vlan_port] & (0x00000001 << port)); vlan_port++); 
    221                 if (vlan_port <SW_DEVS) 
     448        for (port=0; port<SWITCH_NUM_PORTS; port++) { 
     449                for (vlan_port=0; vlan_port<SWITCH_NUM_PORTS && !(matrix[vlan_port] & (0x00000001 << port)); vlan_port++); 
     450                if (vlan_port <SWITCH_NUM_PORTS) 
    222451                        adm5120_port[port] = adm5120_devs[vlan_port]; 
    223452                else 
     
    232461        /* Port 0 to 3 are set using the bandwidth control 0 register */ 
    233462        val = matrix[0] + (matrix[1]<<8) + (matrix[2]<<16) + (matrix[3]<<24); 
    234         adm5120_set_reg(ADM5120_BW_CTL0, val); 
     463        sw_write_reg(SWITCH_REG_BW_CNTL0, val); 
    235464 
    236465        /* Port 4 and 5 are set using the bandwidth control 1 register */ 
    237466        val = matrix[4]; 
    238467        if (matrix[5] == 1) 
    239                 adm5120_set_reg(ADM5120_BW_CTL1, val | 0x80000000); 
     468                sw_write_reg(SWITCH_REG_BW_CNTL1, val | 0x80000000); 
    240469        else 
    241                 adm5120_set_reg(ADM5120_BW_CTL1, val & ~0x8000000); 
    242  
    243         printk(KERN_DEBUG "D: ctl0 0x%lx, ctl1 0x%lx\n", 
    244                 adm5120_get_reg(ADM5120_BW_CTL0), 
    245                 adm5120_get_reg(ADM5120_BW_CTL1)); 
    246 } 
    247  
    248 static int adm5120_sw_open(struct net_device *dev) 
    249 { 
    250         unsigned long val; 
     470                sw_write_reg(SWITCH_REG_BW_CNTL1, val & ~0x8000000); 
     471 
     472        SW_DBG("D: ctl0 0x%ux, ctl1 0x%ux\n", sw_read_reg(SWITCH_REG_BW_CNTL0), 
     473                sw_read_reg(SWITCH_REG_BW_CNTL1)); 
     474} 
     475 
     476static int adm5120_switch_open(struct net_device *dev) 
     477{ 
     478        u32 t; 
    251479        int i; 
    252480 
    253481        netif_start_queue(dev); 
    254         if (!adm5120_if_open++) { 
     482        if (!sw_used++) 
    255483                /* enable interrupts on first open */ 
    256                 adm5120_set_reg(ADM5120_INT_MASK, 
    257                         adm5120_get_reg(ADM5120_INT_MASK) & 
    258                         ~(ADM5120_INT_RXL|ADM5120_INT_LFULL)); 
    259         } 
     484                sw_int_enable(SWITCH_INTS_USED); 
     485 
    260486        /* enable (additional) port */ 
    261         val = adm5120_get_reg(ADM5120_PORT_CONF0); 
    262         for (i=0; i<SW_DEVS; i++) { 
     487        t = sw_read_reg(SWITCH_REG_PORT_CONF0); 
     488        for (i = 0; i < SWITCH_NUM_PORTS; i++) { 
    263489                if (dev == adm5120_devs[i]) 
    264                         val &= ~adm5120_eth_vlans[i]; 
    265         } 
    266         adm5120_set_reg(ADM5120_PORT_CONF0, val); 
     490                        t &= ~adm5120_eth_vlans[i]; 
     491        } 
     492        sw_write_reg(SWITCH_REG_PORT_CONF0, t); 
     493 
    267494        return 0; 
    268495} 
    269496 
    270 static int adm5120_sw_stop(struct net_device *dev) 
    271 { 
    272         unsigned long val; 
     497static int adm5120_switch_stop(struct net_device *dev) 
     498{ 
     499        u32 t; 
    273500        int i; 
    274501 
    275         if (!--adm5120_if_open) { 
    276                 adm5120_set_reg(ADM5120_INT_MASK, ADM5120_INTMASKALL); 
    277         } 
     502        if (!--sw_used) 
     503                sw_int_disable(SWITCH_INTS_USED); 
     504 
    278505        /* disable port if not assigned to other devices */ 
    279         val = adm5120_get_reg(ADM5120_PORT_CONF0) | ADM5120_PORTDISALL; 
    280         for (i=0; i<SW_DEVS; i++) { 
     506        t = sw_read_reg(SWITCH_REG_PORT_CONF0); 
     507        t |= SWITCH_PORTS_NOCPU; 
     508        for (i = 0; i < SWITCH_NUM_PORTS; i++) { 
    281509                if ((dev != adm5120_devs[i]) && netif_running(adm5120_devs[i])) 
    282                         val &= ~adm5120_eth_vlans[i]; 
    283         } 
    284         adm5120_set_reg(ADM5120_PORT_CONF0, val); 
     510                        t &= ~adm5120_eth_vlans[i]; 
     511        } 
     512        sw_write_reg(SWITCH_REG_PORT_CONF0, t); 
     513 
    285514        netif_stop_queue(dev); 
    286515        return 0; 
    287516} 
    288517 
    289 static int adm5120_sw_tx(struct sk_buff *skb, struct net_device *dev) 
    290 { 
    291         struct adm5120_dma *dma; 
    292         struct sk_buff **skbl = adm5120_skb_txl; 
     518static int adm5120_sw_start_xmit(struct sk_buff *skb, struct net_device *dev) 
     519{ 
     520        struct dma_desc *desc; 
    293521        struct adm5120_sw *priv = netdev_priv(dev); 
     522        unsigned int entry; 
    294523        unsigned long data; 
    295524 
    296         dev->trans_start = jiffies; 
    297         dma = &adm5120_dma_txl[adm5120_txli]; 
    298         if (dma->data & ADM5120_DMA_OWN) { 
     525        /* calculate the next TX descriptor entry. */ 
     526        entry = cur_txl % TX_RING_SIZE; 
     527 
     528        desc = &txl_descs[entry]; 
     529        if (desc->buf1 & DESC_OWN) { 
    299530                /* We want to write a packet but the TX queue is still 
    300531                 * occupied by the DMA. We are faster than the DMA... */ 
    301532                dev_kfree_skb(skb); 
    302                 priv->stats.tx_dropped++; 
     533                dev->stats.tx_dropped++; 
    303534                return 0; 
    304535        } 
    305         data = ADM5120_DMA_ADDR(skb->data) | ADM5120_DMA_OWN; 
    306         if (adm5120_txli == ADM5120_DMA_TXL-1) 
    307                 data |= ADM5120_DMA_RINGEND; 
    308         dma->status = 
    309             ((skb->len<ETH_ZLEN?ETH_ZLEN:skb->len) << ADM5120_DMA_LENSHIFT) | 
     536 
     537        txl_skbuff[entry] = skb; 
     538        data = (desc->buf1 & DESC_EOR); 
     539        data |= DESC_ADDR(skb->data); 
     540 
     541        desc->misc = 
     542            ((skb->len<ETH_ZLEN?ETH_ZLEN:skb->len) << DESC_PKTLEN_SHIFT) | 
    310543            (0x1 << priv->port); 
    311544 
    312         dma->len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; 
    313         priv->stats.tx_packets++; 
    314         priv->stats.tx_bytes += skb->len; 
    315  
    316         /* free old skbs here instead of tx completion interrupt: 
    317          * will hold some more memory allocated but reduces interrupts */ 
    318         if (skbl[adm5120_txli]){ 
    319                 dev_kfree_skb(skbl[adm5120_txli]); 
    320         } 
    321         skbl[adm5120_txli] = skb; 
    322  
    323         dma->data = data; /* Here we enable the buffer for the TX DMA machine */ 
    324         adm5120_set_reg(ADM5120_SEND_TRIG, ADM5120_SEND_TRIG_L); 
    325         if (++adm5120_txli == ADM5120_DMA_TXL) 
    326                 adm5120_txli = 0; 
     545        desc->buflen = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; 
     546 
     547        /* lock switch irq */ 
     548        spin_lock_irq(&sw_lock); 
     549 
     550        desc->buf1 = data | DESC_OWN; 
     551        sw_write_reg(SWITCH_REG_SEND_TRIG, SEND_TRIG_STL); 
     552 
     553        cur_txl++; 
     554        if (cur_txl == dirty_txl + TX_QUEUE_LEN) { 
     555                /* FIXME: stop queue for all devices */ 
     556                netif_stop_queue(dev); 
     557        } 
     558 
     559        dev->trans_start = jiffies; 
     560 
     561        spin_unlock_irq(&sw_lock); 
     562 
    327563        return 0; 
    328564} 
     
    330566static void adm5120_tx_timeout(struct net_device *dev) 
    331567{ 
    332         printk(KERN_INFO "%s: TX timeout\n",dev->name); 
    333 } 
    334  
    335 static struct net_device_stats *adm5120_sw_stats(struct net_device *dev) 
     568        SW_INFO("TX timeout on %s\n",dev->name); 
     569} 
     570 
     571static void adm5120_set_multicast_list(struct net_device *dev) 
    336572{ 
    337573        struct adm5120_sw *priv = netdev_priv(dev); 
    338         int portmask; 
    339         unsigned long adm5120_cpup_conf_reg; 
    340  
    341         portmask = adm5120_eth_vlans[priv->port] & 0x3f; 
    342  
    343         adm5120_cpup_conf_reg = adm5120_get_reg(ADM5120_CPUP_CONF); 
    344  
     574        u32 ports; 
     575        u32 t; 
     576 
     577        ports = adm5120_eth_vlans[priv->port] & SWITCH_PORTS_NOCPU; 
     578 
     579        t = sw_read_reg(SWITCH_REG_CPUP_CONF); 
    345580        if (dev->flags & IFF_PROMISC) 
    346                 adm5120_cpup_conf_reg &= ~((portmask << ADM5120_DISUNSHIFT) & ADM5120_DISUNALL); 
     581                /* enable unknown packets */ 
     582                t &= ~(ports << CPUP_CONF_DUNP_SHIFT); 
    347583        else 
    348                 adm5120_cpup_conf_reg |= (portmask << ADM5120_DISUNSHIFT); 
    349  
    350         if (dev->flags & IFF_PROMISC || dev->flags & IFF_ALLMULTI || dev->mc_count) 
    351                 adm5120_cpup_conf_reg &= ~((portmask << ADM5120_DISMCSHIFT) & ADM5120_DISMCALL); 
     584                /* disable unknown packets */ 
     585                t |= (ports << CPUP_CONF_DUNP_SHIFT); 
     586 
     587        if (dev->flags & IFF_PROMISC || dev->flags & IFF_ALLMULTI || 
     588                                        dev->mc_count) 
     589                /* enable multicast packets */ 
     590                t &= ~(ports << CPUP_CONF_DMCP_SHIFT); 
    352591        else 
    353                 adm5120_cpup_conf_reg |= (portmask << ADM5120_DISMCSHIFT); 
    354  
    355                 /* If there is any port configured to be in promiscuous mode, then the */ 
    356                 /* Bridge Test Mode has to be activated. This will result in           */ 
    357                 /* transporting also packets learned in another VLAN to be forwarded   */ 
    358                 /* to the CPU.                                                         */ 
    359                 /* The difficult scenario is when we want to build a bridge on the CPU.*/ 
    360                 /* Assume we have port0 and the CPU port in VLAN0 and port1 and the    */ 
    361                 /* CPU port in VLAN1. Now we build a bridge on the CPU between         */ 
    362                 /* VLAN0 and VLAN1. Both ports of the VLANs are set in promisc mode.   */ 
    363                 /* Now assume a packet with ethernet source address 99 enters port 0   */ 
    364                 /* It will be forwarded to the CPU because it is unknown. Then the     */ 
    365                 /* bridge in the CPU will send it to VLAN1 and it goes out at port 1.  */ 
    366                 /* When now a packet with ethernet destination address 99 comes in at  */ 
    367                 /* port 1 in VLAN1, then the switch has learned that this address is   */ 
    368                 /* located at port 0 in VLAN0. Therefore the switch will drop          */ 
    369                 /* this packet. In order to avoid this and to send the packet still    */ 
    370                 /* to the CPU, the Bridge Test Mode has to be activated.               */ 
    371  
    372                 /* Check if there is any vlan in promisc mode. */ 
    373         if (~adm5120_cpup_conf_reg & ADM5120_DISUNALL) 
    374                 adm5120_cpup_conf_reg |= ADM5120_BTM;  /* Set the BTM     */ 
     592                /* disable multicast packets */ 
     593                t |= (ports << CPUP_CONF_DMCP_SHIFT); 
     594 
     595        /* If there is any port configured to be in promiscuous mode, then the */ 
     596        /* Bridge Test Mode has to be activated. This will result in           */ 
     597        /* transporting also packets learned in another VLAN to be forwarded   */ 
     598        /* to the CPU.                                                         */ 
     599        /* The difficult scenario is when we want to build a bridge on the CPU.*/ 
     600        /* Assume we have port0 and the CPU port in VLAN0 and port1 and the    */ 
     601        /* CPU port in VLAN1. Now we build a bridge on the CPU between         */ 
     602        /* VLAN0 and VLAN1. Both ports of the VLANs are set in promisc mode.   */ 
     603        /* Now assume a packet with ethernet source address 99 enters port 0   */ 
     604        /* It will be forwarded to the CPU because it is unknown. Then the     */ 
     605        /* bridge in the CPU will send it to VLAN1 and it goes out at port 1.  */ 
     606        /* When now a packet with ethernet destination address 99 comes in at  */ 
     607        /* port 1 in VLAN1, then the switch has learned that this address is   */ 
     608        /* located at port 0 in VLAN0. Therefore the switch will drop          */ 
     609        /* this packet. In order to avoid this and to send the packet still    */ 
     610        /* to the CPU, the Bridge Test Mode has to be activated.               */ 
     611 
     612        /* Check if there is any vlan in promisc mode. */ 
     613        if (t & (SWITCH_PORTS_NOCPU << CPUP_CONF_DUNP_SHIFT)) 
     614                t &= ~CPUP_CONF_BTM; /* Disable Bridge Testing Mode */ 
    375615        else 
    376                 adm5120_cpup_conf_reg &= ~ADM5120_BTM; /* Disable the BTM */ 
    377  
    378         adm5120_set_reg(ADM5120_CPUP_CONF,adm5120_cpup_conf_reg); 
    379  
    380         return &((struct adm5120_sw *)netdev_priv(dev))->stats; 
    381 } 
    382  
    383 static void adm5120_set_multicast_list(struct net_device *dev) 
    384 { 
    385         struct adm5120_sw *priv = netdev_priv(dev); 
    386         int portmask; 
    387  
    388         portmask = adm5120_eth_vlans[priv->port] & 0x3f; 
    389  
    390         if (dev->flags & IFF_PROMISC) 
    391                 adm5120_set_reg(ADM5120_CPUP_CONF, 
    392                     adm5120_get_reg(ADM5120_CPUP_CONF) & 
    393                     ~((portmask << ADM5120_DISUNSHIFT) & ADM5120_DISUNALL)); 
    394         else 
    395                 adm5120_set_reg(ADM5120_CPUP_CONF, 
    396                     adm5120_get_reg(ADM5120_CPUP_CONF) | 
    397                     (portmask << ADM5120_DISUNSHIFT)); 
    398  
    399         if (dev->flags & IFF_PROMISC || dev->flags & IFF_ALLMULTI || 
    400             dev->mc_count) 
    401                 adm5120_set_reg(ADM5120_CPUP_CONF, 
    402                     adm5120_get_reg(ADM5120_CPUP_CONF) & 
    403                     ~((portmask << ADM5120_DISMCSHIFT) & ADM5120_DISMCALL)); 
    404         else 
    405                 adm5120_set_reg(ADM5120_CPUP_CONF, 
    406                     adm5120_get_reg(ADM5120_CPUP_CONF) | 
    407                     (portmask << ADM5120_DISMCSHIFT)); 
     616                t |= CPUP_CONF_BTM;  /* Enable Bridge Testing Mode */ 
     617 
     618        sw_write_reg(SWITCH_REG_CPUP_CONF, t); 
     619 
    408620} 
    409621 
     
    412624        struct adm5120_sw *priv = netdev_priv(dev); 
    413625        unsigned char *mac = dev->dev_addr; 
    414  
    415         adm5120_set_reg(ADM5120_MAC_WT1, 
    416             mac[2] | (mac[3]<<8) | (mac[4]<<16) | (mac[5]<<24)); 
    417         adm5120_set_reg(ADM5120_MAC_WT0, (priv->port<<3) | 
    418             (mac[0]<<16) | (mac[1]<<24) | ADM5120_MAC_WRITE | ADM5120_VLAN_EN); 
    419  
    420         while (!(adm5120_get_reg(ADM5120_MAC_WT0) & ADM5120_MAC_WRITE_DONE)); 
     626        u32 t; 
     627 
     628        t = mac[2] | (mac[3] << MAC_WT1_MAC3_SHIFT) | 
     629                (mac[4] << MAC_WT1_MAC4_SHIFT) | (mac[5] << MAC_WT1_MAC4_SHIFT); 
     630        sw_write_reg(SWITCH_REG_MAC_WT1, t); 
     631 
     632        t = (mac[0] << MAC_WT0_MAC0_SHIFT) | (mac[1] << MAC_WT0_MAC1_SHIFT) | 
     633                MAC_WT0_MAWC | MAC_WT0_WVE | (priv->port<<3); 
     634 
     635        sw_write_reg(SWITCH_REG_MAC_WT0, t); 
     636 
     637        while (!(sw_read_reg(SWITCH_REG_MAC_WT0) & MAC_WT0_MWD)); 
    421638} 
    422639 
     
    437654 
    438655        switch(cmd) { 
    439                 case SIOCGADMINFO: 
    440                         info.magic = 0x5120; 
    441                         info.ports = adm5120_nrdevs; 
    442                         info.vlan = priv->port; 
    443                         err = copy_to_user(rq->ifr_data, &info, sizeof(info)); 
    444                         if (err) 
    445                                 return -EFAULT; 
    446                         break; 
    447                 case SIOCSMATRIX: 
    448                         if (!capable(CAP_NET_ADMIN)) 
    449                                 return -EPERM; 
    450                         err = copy_from_user(adm5120_eth_vlans, rq->ifr_data, 
    451                             sizeof(adm5120_eth_vlans)); 
    452                         if (err) 
    453                                 return -EFAULT; 
    454                         adm5120_set_vlan(adm5120_eth_vlans); 
    455                         break; 
    456                 case SIOCGMATRIX: 
    457                         err = copy_to_user(rq->ifr_data, adm5120_eth_vlans, 
    458                             sizeof(adm5120_eth_vlans)); 
    459                         if (err) 
    460                                 return -EFAULT; 
    461                         break; 
    462                 case SIOCGETBW: 
    463                         err = copy_to_user(rq->ifr_data, bw_matrix, sizeof(bw_matrix)); 
    464                         if (err) 
    465                                 return -EFAULT; 
    466                         break; 
    467                 case SIOCSETBW: 
    468                         if (!capable(CAP_NET_ADMIN)) 
    469                                 return -EPERM; 
    470                         err = copy_from_user(bw_matrix, rq->ifr_data, sizeof(bw_matrix)); 
    471                         if (err) 
    472                                 return -EFAULT; 
    473                         adm5120_set_bw(bw_matrix); 
    474                         break; 
    475                 default: 
    476                         return -EOPNOTSUPP; 
     656        case SIOCGADMINFO: 
     657                info.magic = 0x5120; 
     658                info.ports = adm5120_nrdevs; 
     659                info.vlan = priv->port; 
     660                err = copy_to_user(rq->ifr_data, &info, sizeof(info)); 
     661                if (err) 
     662                        return -EFAULT; 
     663                break; 
     664        case SIOCSMATRIX: 
     665                if (!capable(CAP_NET_ADMIN)) 
     666                        return -EPERM; 
     667                err = copy_from_user(adm5120_eth_vlans, rq->ifr_data, 
     668                                        sizeof(adm5120_eth_vlans)); 
     669                if (err) 
     670                        return -EFAULT; 
     671                adm5120_set_vlan(adm5120_eth_vlans); 
     672                break; 
     673        case SIOCGMATRIX: 
     674                err = copy_to_user(rq->ifr_data, adm5120_eth_vlans, 
     675                                        sizeof(adm5120_eth_vlans)); 
     676                if (err) 
     677                        return -EFAULT; 
     678                break; 
     679        case SIOCGETBW: 
     680                err = copy_to_user(rq->ifr_data, bw_matrix, sizeof(bw_matrix)); 
     681                if (err) 
     682                        return -EFAULT; 
     683                break; 
     684        case SIOCSETBW: 
     685                if (!capable(CAP_NET_ADMIN)) 
     686                        return -EPERM; 
     687                err = copy_from_user(bw_matrix, rq->ifr_data, sizeof(bw_matrix)); 
     688                if (err) 
     689                        return -EFAULT; 
     690                adm5120_set_bw(bw_matrix); 
     691                break; 
     692        default: 
     693                return -EOPNOTSUPP; 
    477694        } 
    478695        return 0; 
    479696} 
    480697 
    481 static void adm5120_dma_tx_init(struct adm5120_dma *dma, struct sk_buff **skbl, 
    482     int num) 
    483 { 
    484         memset(dma, 0, sizeof(struct adm5120_dma)*num); 
    485         dma[num-1].data |= ADM5120_DMA_RINGEND; 
     698static void adm5120_dma_tx_init(struct dma_desc *desc, struct sk_buff **skbl, 
     699                int num) 
     700{ 
     701        memset(desc, 0, num * sizeof(*desc)); 
     702        desc[num-1].buf1 |= DESC_EOR; 
    486703        memset(skbl, 0, sizeof(struct skb*)*num); 
    487704} 
    488705 
    489 static void adm5120_dma_rx_init(struct adm5120_dma *dma, struct sk_buff **skbl, 
    490     int num) 
     706static void adm5120_dma_rx_init(struct dma_desc *desc, struct sk_buff **skbl, 
     707                int num) 
    491708{ 
    492709        int i; 
    493710 
    494         memset(dma, 0, sizeof(struct adm5120_dma)*num); 
     711        memset(desc, 0, num * sizeof(*desc)); 
    495712        for (i=0; i<num; i++) { 
    496                 skbl[i] = dev_alloc_skb(ADM5120_DMA_RXSIZE+16); 
     713                skbl[i] = dev_alloc_skb(SKB_ALLOC_LEN); 
    497714                if (!skbl[i]) { 
    498715                        i=num; 
    499716                        break; 
    500717                } 
    501                 skb_reserve(skbl[i], NET_IP_ALIGN); 
    502                 adm5120_rx_dma_update(&dma[i], skbl[i], (num-1==i)); 
     718                skb_reserve(skbl[i], SKB_RESERVE_LEN); 
     719                adm5120_rx_dma_update(&desc[i], skbl[i], (num-1==i)); 
    503720        } 
    504721} 
     
    506723static int __init adm5120_sw_init(void) 
    507724{ 
     725        struct net_device *dev; 
     726        u32 t; 
    508727        int i, err; 
    509         struct net_device *dev; 
    510  
    511         err = request_irq(ADM5120_IRQ_SWITCH, adm5120_sw_irq, 0, "ethernet switch", NULL); 
     728 
     729        err = request_irq(ADM5120_IRQ_SWITCH, adm5120_switch_irq, 
     730                (IRQF_SHARED | IRQF_DISABLED), "switch", &sw_dev); 
    512731        if (err) 
    513732                goto out; 
     
    515734        adm5120_nrdevs = adm5120_eth_num_ports; 
    516735 
    517         adm5120_set_reg(ADM5120_CPUP_CONF, 
    518             ADM5120_DISCCPUPORT | ADM5120_CRC_PADDING | 
    519             ADM5120_DISUNALL | ADM5120_DISMCALL); 
    520         adm5120_set_reg(ADM5120_PORT_CONF0, ADM5120_ENMC | ADM5120_ENBP | ADM5120_PORTDISALL); 
    521  
    522         adm5120_set_reg(ADM5120_PHY_CNTL2, adm5120_get_reg(ADM5120_PHY_CNTL2) | 
    523             ADM5120_AUTONEG | ADM5120_NORMAL | ADM5120_AUTOMDIX); 
    524         adm5120_set_reg(ADM5120_PHY_CNTL3, adm5120_get_reg(ADM5120_PHY_CNTL3) | 
    525             ADM5120_PHY_NTH); 
     736        t = CPUP_CONF_DCPUP | CPUP_CONF_CRCP | 
     737                SWITCH_PORTS_NOCPU << CPUP_CONF_DUNP_SHIFT | 
     738                SWITCH_PORTS_NOCPU << CPUP_CONF_DMCP_SHIFT ; 
     739        sw_write_reg(SWITCH_REG_CPUP_CONF, t); 
     740 
     741        t = (SWITCH_PORTS_NOCPU << PORT_CONF0_EMCP_SHIFT) | 
     742                (SWITCH_PORTS_NOCPU << PORT_CONF0_BP_SHIFT) | 
     743                (SWITCH_PORTS_NOCPU); 
     744        sw_write_reg(SWITCH_REG_PORT_CONF0, t); 
     745 
     746        /* setup ports to Autoneg/100M/Full duplex/Auto MDIX */ 
     747        t =  SWITCH_PORTS_PHY | 
     748                (SWITCH_PORTS_PHY << PHY_CNTL2_SC_SHIFT) | 
     749                (SWITCH_PORTS_PHY << PHY_CNTL2_DC_SHIFT) | 
     750                (SWITCH_PORTS_PHY << PHY_CNTL2_PHYR_SHIFT) | 
     751                (SWITCH_PORTS_PHY << PHY_CNTL2_AMDIX_SHIFT) | 
     752                PHY_CNTL2_RMAE; 
     753        SW_WRITE_REG(PHY_CNTL2, t); 
     754 
     755        t = sw_read_reg(SWITCH_REG_PHY_CNTL3); 
     756        t |= PHY_CNTL3_RNT; 
     757        sw_write_reg(SWITCH_REG_PHY_CNTL3, t); 
    526758 
    527759        /* Force all the packets from all ports are low priority */ 
    528         adm5120_set_reg(ADM5120_PRI_CNTL, 0); 
    529  
    530         adm5120_set_reg(ADM5120_INT_MASK, ADM5120_INTMASKALL); 
    531         adm5120_set_reg(ADM5120_INT_ST, ADM5120_INTMASKALL); 
    532  
    533         adm5120_dma_txh = (void *)KSEG1ADDR((u32)adm5120_dma_txh_v); 
    534         adm5120_dma_txl = (void *)KSEG1ADDR((u32)adm5120_dma_txl_v); 
    535         adm5120_dma_rxh = (void *)KSEG1ADDR((u32)adm5120_dma_rxh_v); 
    536         adm5120_dma_rxl = (void *)KSEG1ADDR((u32)adm5120_dma_rxl_v); 
    537  
    538         adm5120_dma_tx_init(adm5120_dma_txh, adm5120_skb_txh, ADM5120_DMA_TXH); 
    539         adm5120_dma_tx_init(adm5120_dma_txl, adm5120_skb_txl, ADM5120_DMA_TXL); 
    540         adm5120_dma_rx_init(adm5120_dma_rxh, adm5120_skb_rxh, ADM5120_DMA_RXH); 
    541         adm5120_dma_rx_init(adm5120_dma_rxl, adm5120_skb_rxl, ADM5120_DMA_RXL); 
    542         adm5120_set_reg(ADM5120_SEND_HBADDR, KSEG1ADDR(adm5120_dma_txh)); 
    543         adm5120_set_reg(ADM5120_SEND_LBADDR, KSEG1ADDR(adm5120_dma_txl)); 
    544         adm5120_set_reg(ADM5120_RECEIVE_HBADDR, KSEG1ADDR(adm5120_dma_rxh)); 
    545         adm5120_set_reg(ADM5120_RECEIVE_LBADDR, KSEG1ADDR(adm5120_dma_rxl)); 
    546  
    547         for (i = 0; i < SW_DEVS; i++) { 
     760        sw_write_reg(SWITCH_REG_PRI_CNTL, 0); 
     761 
     762        sw_int_disable(SWITCH_INTS_ALL); 
     763        sw_int_ack(SWITCH_INTS_ALL); 
     764 
     765        cur_txl = dirty_txl = 0; 
     766        cur_rxl = dirty_rxl = 0; 
     767 
     768        txh_descs = (void *)KSEG1ADDR((u32)txh_descs_v); 
     769        txl_descs = (void *)KSEG1ADDR((u32)txl_descs_v); 
     770        rxh_descs = (void *)KSEG1ADDR((u32)rxh_descs_v); 
     771        rxl_descs = (void *)KSEG1ADDR((u32)rxl_descs_v); 
     772 
     773        adm5120_dma_tx_init(txh_descs, txh_skbuff, TX_RING_SIZE); 
     774        adm5120_dma_tx_init(txl_descs, txl_skbuff, TX_RING_SIZE); 
     775        adm5120_dma_rx_init(rxh_descs, rxh_skbuff, RX_RING_SIZE); 
     776        adm5120_dma_rx_init(rxl_descs, rxl_skbuff, RX_RING_SIZE); 
     777        sw_write_reg(SWITCH_REG_SHDA, KSEG1ADDR(txh_descs)); 
     778        sw_write_reg(SWITCH_REG_SLDA, KSEG1ADDR(txl_descs)); 
     779        sw_write_reg(SWITCH_REG_RHDA, KSEG1ADDR(rxh_descs)); 
     780        sw_write_reg(SWITCH_REG_RLDA, KSEG1ADDR(rxl_descs)); 
     781 
     782        for (i = 0; i < SWITCH_NUM_PORTS; i++) { 
    548783                adm5120_devs[i] = alloc_etherdev(sizeof(struct adm5120_sw)); 
    549784                if (!adm5120_devs[i]) { 
     
    553788 
    554789                dev = adm5120_devs[i]; 
     790                err = request_irq(ADM5120_IRQ_SWITCH, adm5120_poll_irq, 
     791                        (IRQF_SHARED | IRQF_DISABLED), dev->name, dev); 
     792                if (err) { 
     793                        SW_ERR("unable to get irq for %s\n", dev->name); 
     794                        goto out_int; 
     795                } 
     796 
    555797                SET_MODULE_OWNER(dev); 
    556798                memset(netdev_priv(dev), 0, sizeof(struct adm5120_sw)); 
    557799                ((struct adm5120_sw*)netdev_priv(dev))->port = i; 
    558                 dev->base_addr = SW_BASE; 
     800                dev->base_addr = ADM5120_SWITCH_BASE; 
    559801                dev->irq = ADM5120_IRQ_SWITCH; 
    560                 dev->open = adm5120_sw_open; 
    561                 dev->hard_start_xmit = adm5120_sw_tx; 
    562                 dev->stop = adm5120_sw_stop; 
    563                 dev->get_stats = adm5120_sw_stats; 
     802                dev->open = adm5120_switch_open; 
     803                dev->hard_start_xmit = adm5120_sw_start_xmit; 
     804                dev->stop = adm5120_switch_stop; 
    564805                dev->set_multicast_list = adm5120_set_multicast_list; 
    565806                dev->do_ioctl = adm5120_do_ioctl; 
    566807                dev->tx_timeout = adm5120_tx_timeout; 
    567                 dev->watchdog_timeo = ETH_TX_TIMEOUT; 
     808                dev->watchdog_timeo = TX_TIMEOUT; 
    568809                dev->set_mac_address = adm5120_sw_set_mac_address; 
    569                 dev->poll = adm5120_rx; 
     810                dev->poll = adm5120_switch_rx; 
    570811                dev->weight = 64; 
    571812 
     
    574815 
    575816                if ((err = register_netdev(dev))) { 
     817                        free_irq(ADM5120_IRQ_SWITCH, dev); 
    576818                        free_netdev(dev); 
    577819                        goto out_int; 
    578820                } 
    579                 printk(KERN_INFO "%s: ADM5120 switch port%d\n", dev->name, i); 
     821                SW_INFO("%s created for switch port%d\n", dev->name, i); 
    580822        } 
    581823        /* setup vlan/port mapping after devs are filled up */ 
    582824        adm5120_set_vlan(adm5120_eth_vlans); 
    583825 
    584         adm5120_set_reg(ADM5120_CPUP_CONF, 
    585             ADM5120_CRC_PADDING | ADM5120_DISUNALL | ADM5120_DISMCALL); 
     826        /* enable CPU port */ 
     827        t = sw_read_reg(SWITCH_REG_CPUP_CONF); 
     828        t &= ~CPUP_CONF_DCPUP; 
     829        sw_write_reg(SWITCH_REG_CPUP_CONF, t); 
    586830 
    587831        return 0; 
     
    595839        free_irq(ADM5120_IRQ_SWITCH, NULL); 
    596840out: 
    597         printk(KERN_ERR "ADM5120 Ethernet switch init failed\n"); 
     841        SW_ERR("init failed\n"); 
    598842        return err; 
    599843} 
     
    603847        int i; 
    604848 
    605         for (i = 0; i < SW_DEVS; i++) { 
    606                 unregister_netdev(adm5120_devs[i]); 
    607                 free_netdev(adm5120_devs[i]); 
    608         } 
    609  
    610         free_irq(ADM5120_IRQ_SWITCH, NULL); 
    611  
    612         for (i = 0; i < ADM5120_DMA_RXH; i++) { 
    613                 if (!adm5120_skb_rxh[i]) 
     849        for (i = 0; i < SWITCH_NUM_PORTS; i++) { 
     850                struct net_device *dev = adm5120_devs[i]; 
     851                unregister_netdev(dev); 
     852                free_irq(ADM5120_IRQ_SWITCH, dev); 
     853                free_netdev(dev); 
     854        } 
     855 
     856        free_irq(ADM5120_IRQ_SWITCH, &sw_dev); 
     857 
     858        for (i = 0; i < RX_RING_SIZE; i++) { 
     859                if (!rxh_skbuff[i]) 
    614860                        break; 
    615                 kfree_skb(adm5120_skb_rxh[i]); 
    616         } 
    617         for (i = 0; i < ADM5120_DMA_RXL; i++) { 
    618                 if (!adm5120_skb_rxl[i]) 
     861                kfree_skb(rxh_skbuff[i]); 
     862        } 
     863 
     864        for (i = 0; i < RX_RING_SIZE; i++) { 
     865                if (!rxl_skbuff[i]) 
    619866                        break; 
    620                 kfree_skb(adm5120_skb_rxl[i]); 
     867                kfree_skb(rxl_skbuff[i]); 
    621868        } 
    622869} 
  • trunk/target/linux/adm5120/files/drivers/net/adm5120sw.h

    r8083 r9324  
    1111#define _INCLUDE_ADM5120SW_H_ 
    1212 
    13 #define SW_BASE KSEG1ADDR(0x12000000) 
    14 #define SW_DEVS 6 
    15  
    16 #define ETH_TX_TIMEOUT          HZ*400 
    17 #define ETH_FCS 4; 
    18  
    19 #define ADM5120_CODE            0x00            /* CPU description */ 
    20 #define ADM5120_CODE_PQFP       0x20000000      /* package type */ 
    21 #define ADM5120_SW_CONF         0x20            /* Switch configuration register */ 
    22 #define ADM5120_SW_CONF_BPM     0x00300000      /* Mask for backpressure mode */ 
    23 #define ADM5120_CPUP_CONF       0x24            /* CPU port config */ 
    24 #define ADM5120_DISCCPUPORT     0x00000001      /* disable cpu port */ 
    25 #define ADM5120_CRC_PADDING     0x00000002      /* software crc */ 
    26 #define ADM5120_BTM             0x00000004      /* bridge test mode */ 
    27 #define ADM5120_DISUNSHIFT      9 
    28 #define ADM5120_DISUNALL        0x00007e00      /* disable unknown from all */ 
    29 #define ADM5120_DISMCSHIFT      16 
    30 #define ADM5120_DISMCALL        0x003f0000      /* disable multicast from all */ 
    31 #define ADM5120_PORT_CONF0      0x28 
    32 #define ADM5120_ENMC            0x00003f00      /* Enable MC routing (ex cpu) */ 
    33 #define ADM5120_ENBP            0x003f0000      /* Enable Back Pressure */ 
    34 #define ADM5120_PORTDISALL      0x0000003F 
    35 #define ADM5120_VLAN_GI         0x40            /* VLAN settings */ 
    36 #define ADM5120_VLAN_GII        0x44 
    37 #define ADM5120_SEND_TRIG       0x48 
    38 #define ADM5120_SEND_TRIG_L     0x00000001 
    39 #define ADM5120_SEND_TRIG_H     0x00000002 
    40 #define ADM5120_MAC_WT0         0x58 
    41 #define ADM5120_MAC_WRITE       0x00000001 
    42 #define ADM5120_MAC_WRITE_DONE  0x00000002 
    43 #define ADM5120_VLAN_EN         0x00000040 
    44 #define ADM5120_MAC_WT1         0x5c 
    45 #define ADM5120_BW_CTL0         0x60            /* Bandwidth control 0 */ 
    46 #define ADM5120_BW_CTL1         0x64            /* Bandwidth control 1 */ 
    47 #define ADM5120_PHY_CNTL2       0x7c 
    48 #define ADM5120_AUTONEG         0x0000001f      /* Auto negotiate */ 
    49 #define ADM5120_NORMAL          0x01f00000      /* PHY normal mode */ 
    50 #define ADM5120_AUTOMDIX        0x3e000000      /* Auto MDIX */ 
    51 #define ADM5120_PHY_CNTL3       0x80 
    52 #define ADM5120_PHY_NTH         0x00000400 
    53 #define ADM5120_PRI_CNTL        0x84 
    54 #define ADM5120_INT_ST          0xb0 
    55 #define ADM5120_INT_RXH         0x0000004 
    56 #define ADM5120_INT_RXL         0x0000008 
    57 #define ADM5120_INT_HFULL       0x0000010 
    58 #define ADM5120_INT_LFULL       0x0000020 
    59 #define ADM5120_INT_TXH         0x0000001 
    60 #define ADM5120_INT_TXL         0x0000002 
    61 #define ADM5120_INT_MASK        0xb4 
    62 #define ADM5120_INTMASKALL      0x1FDEFFF       /* All interrupts */ 
    63 #define ADM5120_INTHANDLE       (ADM5120_INT_RXH | ADM5120_INT_RXL | \ 
    64                                  ADM5120_INT_HFULL | ADM5120_INT_LFULL | \ 
    65                                  ADM5120_INT_TXH | ADM5120_INT_TXL) 
    66 #define ADM5120_SEND_HBADDR     0xd0 
    67 #define ADM5120_SEND_LBADDR     0xd4 
    68 #define ADM5120_RECEIVE_HBADDR  0xd8 
    69 #define ADM5120_RECEIVE_LBADDR  0xdc 
    70  
    71 struct adm5120_dma { 
    72         u32 data; 
    73         u32 cntl; 
    74         u32 len; 
    75         u32 status; 
    76 } __attribute__ ((packed)); 
    77  
    78 #define ADM5120_DMA_MASK        0x01ffffff 
    79 #define ADM5120_DMA_OWN         0x80000000      /* buffer owner */ 
    80 #define ADM5120_DMA_RINGEND     0x10000000      /* Last in DMA ring */ 
    81  
    82 #define ADM5120_DMA_ADDR(ptr)   ((u32)(ptr) & ADM5120_DMA_MASK) 
    83 #define ADM5120_DMA_PORTID      0x00007000 
    84 #define ADM5120_DMA_PORTSHIFT   12 
    85 #define ADM5120_DMA_LEN         0x07ff0000 
    86 #define ADM5120_DMA_LENSHIFT    16 
    87 #define ADM5120_DMA_FCSERR      0x00000008 
    88  
    89 #define ADM5120_DMA_TXH         2 
    90 #define ADM5120_DMA_TXL         64 
    91 #define ADM5120_DMA_RXH         2 
    92 #define ADM5120_DMA_RXL         64 
    93  
    94 #define ADM5120_DMA_RXSIZE      1550 
    95 #define ADM5120_DMA_EXTRA       20 
    96  
    9713struct adm5120_sw { 
    98         int                     port; 
    99         struct net_device_stats stats; 
     14        int     port; 
    10015}; 
    10116 
  • trunk/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_switch.h

    r9118 r9324  
    142142#define CPUP_CONF_CRCP          BIT(1)  /* CRC padding from CPU */ 
    143143#define CPUP_CONF_BTM           BIT(2)  /* Bridge Testing Mode */ 
     144#define CPUP_CONF_DUNP_SHIFT    9       /* Disable Unknown Packets for portX */ 
     145#define CPUP_CONF_DMCP_SHIFT    16      /* Disable Mcast Packets form portX */ 
     146#define CPUP_CONF_DBCP_SHIFT    24      /* Disable Bcast Packets form portX */ 
    144147 
    145148/* PORT_CONF0 register bits */ 
     
    156159#define SEND_TRIG_STL           BIT(0)  /* Send Trigger Low */ 
    157160#define SEND_TRIG_STH           BIT(1)  /* Send Trigger High */ 
     161 
     162/* MAC_WT0 register bits */ 
     163#define MAC_WT0_MAWC            BIT(0)  /* MAC address write command */ 
     164#define MAC_WT0_MWD_SHIFT       1 
     165#define MAC_WT0_MWD             BIT(1)  /* MAC write done */ 
     166#define MAC_WT0_WFB             BIT(2)  /* Write Filter Bit */ 
     167#define MAC_WT0_WVN_SHIFT       3 
     168#define MAC_WT0_WVE             BIT(6)  /* Write VLAN enable */ 
     169#define MAC_WT0_WPMN_SHIFT      7 
     170#define MAC_WT0_WAF_SHIFT       13      /* Write Age Field shift */ 
     171#define MAC_WT0_WAF_EMPTY       0 
     172#define MAC_WT0_WAF_STATIC      7 
     173#define MAC_WT0_MAC0_SHIFT      16 
     174#define MAC_WT0_MAC1_SHIFT      24 
     175 
     176/* MAC_WT1 register bits */ 
     177#define MAC_WT1_MAC2_SHIFT      0 
     178#define MAC_WT1_MAC3_SHIFT      8 
     179#define MAC_WT1_MAC4_SHIFT      16 
     180#define MAC_WT1_MAC5_SHIFT      24 
    158181 
    159182/* BW_CNTL0/BW_CNTL1 register bits */ 
     
    198221/* PHY_CNTL2_RMAE is bad in datasheet */ 
    199222#define PHY_CNTL2_RMAE          BIT(31) /* Recommended MCC Average enable */ 
     223 
     224/* PHY_CNTL3 register bits */ 
     225#define PHY_CNTL3_RNT           BIT(10) /* Recommend Normal Threshold */ 
    200226 
    201227/* PORT_TH register bits */ 
Note: See TracChangeset for help on using the changeset viewer.