openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

bcm-knet.c (289076B)


      1 /*
      2  * Copyright 2017 Broadcom
      3  * 
      4  * This program is free software; you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License, version 2, as
      6  * published by the Free Software Foundation (the "GPL").
      7  * 
      8  * This program is distributed in the hope that it will be useful, but
      9  * WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     11  * General Public License version 2 (GPLv2) for more details.
     12  * 
     13  * You should have received a copy of the GNU General Public License
     14  * version 2 (GPLv2) along with this source code.
     15  */
     16 /*
     17  * $Id: bcm-knet.c,v 1.90 Broadcom SDK $
     18  * $Copyright: (c) 2005 Broadcom Corp.
     19  * All Rights Reserved.$
     20  */
     21 
     22 /*
     23  * This module implements a Linux network driver for Broadcom
     24  * XGS switch devices. The driver simultaneously serves a
     25  * number of vitual Linux network devices and a Tx/Rx API
     26  * implemented in user space.
     27  *
     28  * Packets received from the switch device are sent to either
     29  * a virtual Linux network device or the user mode Rx API
     30  * based on a set of packet filters.susp
     31  *
     32  * Packets from the virtual Linux network devices and the user
     33  * mode Tx API are multiplexed with priority given to the Tx API.
     34  *
     35  * A message-based IOCTL interface is used for managing packet
     36  * filters and virtual Linux network interfaces.
     37  *
     38  * A virtual network interface can be configured to work in RCPU
     39  * mode, which means that packets from the switch device will
     40  * be encasulated with a RCPU header and a block of meta data
     41  * that basically contains the core DCB information. Likewise,
     42  * packets received from the Linux network stack are assumed to
     43  * be RCPU encapsulated when going out on an interface in RCPU
     44  * mode.
     45  *
     46  * The module implements basic Rx DMA rate control. The rate is
     47  * specified in packets per second, and different Rx DMA channels
     48  * can be configured to use different maximum packet rates.
     49  * The packet rate can be configure as a module parameter, and
     50  * it can also be changed dynamically through the proc file
     51  * system (syntax is described in function header comment).
     52  *
     53  * To support multiple instance, each instance has its event queue.
     54  *
     55  * To support pci hot-plug in this module, the resource update
     56  * should be handled when the PCI device is re-plugged.
     57  * NOTE: the KNET detach should be invoked befere removing the
     58  * device.
     59  *
     60  * For a list of supported module parameters, please see below.
     61  */
     62 
     63 #include <gmodule.h> /* Must be included first */
     64 #include <linux-bde.h>
     65 #include <kcom.h>
     66 #include <bcm-knet.h>
     67 
     68 #include <linux/netdevice.h>
     69 #include <linux/etherdevice.h>
     70 #include <linux/ethtool.h>
     71 #include <linux/random.h>
     72 #include <linux/seq_file.h>
     73 #include <linux/if_vlan.h>
     74 
     75 
     76 MODULE_AUTHOR("Broadcom Corporation");
     77 MODULE_DESCRIPTION("Network Device Driver for Broadcom BCM TxRx API");
     78 MODULE_LICENSE("GPL");
     79 
     80 static int debug;
     81 LKM_MOD_PARAM(debug, "i", int, 0);
     82 MODULE_PARM_DESC(debug,
     83 "Debug level (default 0)");
     84 
     85 static char *mac_addr = NULL;
     86 LKM_MOD_PARAM(mac_addr, "s", charp, 0);
     87 MODULE_PARM_DESC(mac_addr,
     88 "Ethernet MAC address (default 02:10:18:xx:xx:xx)");
     89 
     90 static int rx_buffer_size = 9216;
     91 LKM_MOD_PARAM(rx_buffer_size, "i", int, 0);
     92 MODULE_PARM_DESC(rx_buffer_size,
     93 "Size of RX packet buffers (default 9216)");
     94 
     95 static int default_mtu = 1500;
     96 LKM_MOD_PARAM(default_mtu, "i", int, 0);
     97 MODULE_PARM_DESC(default_mtu,
     98 "Default MTU for KNET network interfaces (default 1500)");
     99 
    100 static int rx_sync_retry = 1000;
    101 LKM_MOD_PARAM(rx_sync_retry, "i", int, 0);
    102 MODULE_PARM_DESC(rx_sync_retry,
    103 "Retries if chain is incomplete on interrupt (default 10)");
    104 
    105 static char *base_dev_name = NULL;
    106 LKM_MOD_PARAM(base_dev_name, "s", charp, 0);
    107 MODULE_PARM_DESC(base_dev_name,
    108 "Base device name (default bcm0, bcm1, etc.)");
    109 
    110 static int rcpu_mode = 0;
    111 LKM_MOD_PARAM(rcpu_mode, "i", int, 0);
    112 MODULE_PARM_DESC(rcpu_mode,
    113 "Enable RCPU encapsulation (default 0)");
    114 
    115 static char *rcpu_dmac = NULL;
    116 LKM_MOD_PARAM(rcpu_dmac, "s", charp, 0);
    117 MODULE_PARM_DESC(rcpu_dmac,
    118 "RCPU destination MAC address (by default use L2 destination MAC address)");
    119 
    120 static char *rcpu_smac = NULL;
    121 LKM_MOD_PARAM(rcpu_smac, "s", charp, 0);
    122 MODULE_PARM_DESC(rcpu_smac,
    123 "RCPU source MAC address (by default use L2 source MAC address)");
    124 
    125 static int rcpu_ethertype = 0xde08;
    126 LKM_MOD_PARAM(rcpu_ethertype, "i", int, 0);
    127 MODULE_PARM_DESC(rcpu_ethertype,
    128 "RCPU EtherType (default DE08h)");
    129 
    130 static int rcpu_signature = 0;
    131 LKM_MOD_PARAM(rcpu_signature, "i", int, 0);
    132 MODULE_PARM_DESC(rcpu_signature,
    133 "RCPU Signature (default is PCI device ID)");
    134 
    135 static int rcpu_vlan = 1;
    136 LKM_MOD_PARAM(rcpu_vlan, "i", int, 0);
    137 MODULE_PARM_DESC(rcpu_vlan,
    138 "RCPU VLAN ID (default 1)");
    139 
    140 static int use_rx_skb = 0;
    141 LKM_MOD_PARAM(use_rx_skb, "i", int, 0);
    142 MODULE_PARM_DESC(use_rx_skb,
    143 "Use socket buffers for receive operation (default 0)");
    144 
    145 static int num_rx_prio = 1;
    146 LKM_MOD_PARAM(num_rx_prio, "i", int, 0);
    147 MODULE_PARM_DESC(num_rx_prio,
    148 "Number of filter priorities per Rx DMA channel");
    149 
    150 static int rx_rate[8] = { 100000, 100000, 100000, 100000, 100000, 100000, 100000, 0 };
    151 LKM_MOD_PARAM_ARRAY(rx_rate, "1-4i", int, NULL, 0);
    152 MODULE_PARM_DESC(rx_rate,
    153 "Rx rate in packets per second (default 100000)");
    154 
    155 static int rx_burst[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    156 LKM_MOD_PARAM_ARRAY(rx_burst, "1-4i", int, NULL, 0);
    157 MODULE_PARM_DESC(rx_burst,
    158 "Rx rate burst maximum in packets (default rx_rate/10)");
    159 
    160 static int check_rcpu_signature = 0;
    161 LKM_MOD_PARAM(check_rcpu_signature, "i", int, 0);
    162 MODULE_PARM_DESC(check_rcpu_signature,
    163 "Check RCPU Signature for Tx packets from RCPU interfaces");
    164 
    165 static int basedev_suspend = 0;
    166 LKM_MOD_PARAM(basedev_suspend, "i", int, 0);
    167 MODULE_PARM_DESC(basedev_suspend,
    168 "Pause traffic till base device is up (enabled by default in NAPI mode)");
    169 
    170 /* Debug levels */
    171 #define DBG_LVL_VERB    0x1
    172 #define DBG_LVL_DCB     0x2
    173 #define DBG_LVL_PKT     0x4
    174 #define DBG_LVL_SKB     0x8
    175 #define DBG_LVL_CMD     0x10
    176 #define DBG_LVL_EVT     0x20
    177 #define DBG_LVL_IRQ     0x40
    178 #define DBG_LVL_NAPI    0x80
    179 #define DBG_LVL_PDMP    0x100
    180 #define DBG_LVL_FLTR    0x200
    181 #define DBG_LVL_KCOM    0x400
    182 #define DBG_LVL_RCPU    0x800
    183 #define DBG_LVL_WARN    0x1000
    184 #define DBG_LVL_NDEV    0x2000
    185 #define DBG_LVL_INST    0x4000
    186 /* Level to output Dune internal headers Parsing */
    187 #define DBG_LVL_DUNE    0x8000
    188 #define DBG_LVL_DCB_TX  0x10000
    189 #define DBG_LVL_DCB_RX  0x20000
    190 #define DBG_LVL_PDMP_TX 0x40000
    191 #define DBG_LVL_PDMP_RX 0x80000
    192 
    193 #define DBG_VERB(_s)    do { if (debug & DBG_LVL_VERB) gprintk _s; } while (0)
    194 #define DBG_PKT(_s)     do { if (debug & DBG_LVL_PKT)  gprintk _s; } while (0)
    195 #define DBG_SKB(_s)     do { if (debug & DBG_LVL_SKB)  gprintk _s; } while (0)
    196 #define DBG_CMD(_s)     do { if (debug & DBG_LVL_CMD)  gprintk _s; } while (0)
    197 #define DBG_EVT(_s)     do { if (debug & DBG_LVL_EVT)  gprintk _s; } while (0)
    198 #define DBG_IRQ(_s)     do { if (debug & DBG_LVL_IRQ)  gprintk _s; } while (0)
    199 #define DBG_NAPI(_s)    do { if (debug & DBG_LVL_NAPI) gprintk _s; } while (0)
    200 #define DBG_PDMP(_s)    do { if (debug & DBG_LVL_PDMP) gprintk _s; } while (0)
    201 #define DBG_FLTR(_s)    do { if (debug & DBG_LVL_FLTR) gprintk _s; } while (0)
    202 #define DBG_KCOM(_s)    do { if (debug & DBG_LVL_KCOM) gprintk _s; } while (0)
    203 #define DBG_RCPU(_s)    do { if (debug & DBG_LVL_RCPU) gprintk _s; } while (0)
    204 #define DBG_WARN(_s)    do { if (debug & DBG_LVL_WARN) gprintk _s; } while (0)
    205 #define DBG_NDEV(_s)    do { if (debug & DBG_LVL_NDEV) gprintk _s; } while (0)
    206 #define DBG_INST(_s)    do { if (debug & DBG_LVL_INST) gprintk _s; } while (0)
    207 #define DBG_DUNE(_s)    do { if (debug & DBG_LVL_DUNE) gprintk _s; } while (0)
    208 #define DBG_DCB_TX(_s)  do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_TX)) \
    209                                  gprintk _s; } while (0)
    210 #define DBG_DCB_RX(_s)  do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_RX)) \
    211                                  gprintk _s; } while (0)
    212 #define DBG_DCB(_s)     do { if (debug & (DBG_LVL_DCB|DBG_LVL_DCB_TX| \
    213                                           DBG_LVL_DCB_RX)) \
    214                                  gprintk _s; } while (0)
    215 
    216 
    217 /* This flag is used to indicate if debugging packet function is open or closed */
    218 static int dbg_pkt_enable = 0;
    219 
    220 /* Module Information */
    221 #define MODULE_MAJOR 122
    222 #define MODULE_NAME "linux-bcm-knet"
    223 
    224 #ifndef NAPI_SUPPORT
    225 #define NAPI_SUPPORT 1
    226 #endif
    227 
    228 #if NAPI_SUPPORT
    229 
    230 static int use_napi = 0;
    231 LKM_MOD_PARAM(use_napi, "i", int, 0);
    232 MODULE_PARM_DESC(use_napi,
    233 "Use NAPI interface (default 0)");
    234 
    235 static int napi_weight = 64;
    236 LKM_MOD_PARAM(napi_weight, "i", int, 0);
    237 MODULE_PARM_DESC(napi_weight,
    238 "Weight of NAPI interfaces (default 64)");
    239 
    240 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
    241 #define bkn_napi_enable(_dev, _napi) netif_poll_enable(_dev)
    242 #define bkn_napi_disable(_dev, _napi) netif_poll_disable(_dev)
    243 #define bkn_napi_schedule(_dev, _napi) netif_rx_schedule(_dev)
    244 #define bkn_napi_schedule_prep(_dev, _napi) netif_rx_schedule_prep(_dev)
    245 #define __bkn_napi_schedule(_dev, _napi) __netif_rx_schedule(_dev)
    246 #define bkn_napi_complete(_dev, _napi) netif_rx_complete(_dev)
    247 #else
    248 #define bkn_napi_enable(_dev, _napi) napi_enable(_napi)
    249 #define bkn_napi_disable(_dev, _napi) napi_disable(_napi)
    250 #define bkn_napi_schedule(_dev, _napi) napi_schedule(_napi)
    251 #define bkn_napi_schedule_prep(_dev, _napi) napi_schedule_prep(_napi)
    252 #define __bkn_napi_schedule(_dev, _napi) __napi_schedule(_napi)
    253 #define bkn_napi_complete(_dev, _napi) napi_complete(_napi)
    254 #endif
    255 
    256 #else
    257 
    258 static int use_napi = 0;
    259 static int napi_weight = 0;
    260 
    261 #define bkn_napi_enable(_dev, _napi)
    262 #define bkn_napi_disable(_dev, _napi)
    263 #define bkn_napi_schedule(_dev, _napi)
    264 #define bkn_napi_schedule_prep(_dev, _napi) (0)
    265 #define __bkn_napi_schedule(_dev, _napi)
    266 #define bkn_napi_complete(_dev, _napi)
    267 
    268 #endif
    269 
    270 /*
    271  * If proxy support is compiled in the module will attempt to use
    272  * the user/kernel message service provided by the linux-uk-proxy
    273  * kernel module, otherwise device IOCTL will be used.
    274  */
    275 #ifndef PROXY_SUPPORT
    276 #define PROXY_SUPPORT 0
    277 #endif
    278 
    279 #if PROXY_SUPPORT
    280 
    281 #include <linux-uk-proxy.h>
    282 
    283 static int use_proxy = 1;
    284 LKM_MOD_PARAM(use_proxy, "i", int, 0);
    285 MODULE_PARM_DESC(use_proxy,
    286 "Use Linux User/Kernel proxy (default 1)");
    287 
    288 #define PROXY_SERVICE_CREATE(_s,_q,_f)  linux_uk_proxy_service_create(_s,_q,_f)
    289 #define PROXY_SERVICE_DESTROY(_s)       linux_uk_proxy_service_destroy(_s);
    290 #define PROXY_SEND(_s,_m,_l)            linux_uk_proxy_send(_s,_m,_l)
    291 #define PROXY_RECV(_s,_m,_l)            linux_uk_proxy_recv(_s,_m,_l)
    292 
    293 #else
    294 
    295 static int use_proxy = 0;
    296 
    297 #define PROXY_SERVICE_CREATE(_s,_q,_f)
    298 #define PROXY_SERVICE_DESTROY(_s)
    299 #define PROXY_SEND(_s,_m,_l)
    300 #define PROXY_RECV(_s,_m,_l) (-1)
    301 
    302 #endif
    303 
    304 /* Compatibility */
    305 
    306 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0))
    307 #define NETDEV_UPDATE_TRANS_START_TIME(dev) dev->trans_start = jiffies
    308 #else
    309 #define NETDEV_UPDATE_TRANS_START_TIME(dev) netif_trans_update(dev)
    310 #endif
    311 
    312 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
    313 #define skb_copy_to_linear_data(_skb, _pkt, _len) \
    314     eth_copy_and_sum(_skb, _pkt, _len, 0)
    315 struct napi_struct { int not_used; };
    316 #define netif_napi_add(_dev, _napi, _poll, _weight) do { \
    317         (_dev)->poll = _poll; \
    318         (_dev)->weight = _weight; \
    319 } while(0)
    320 #endif
    321 
    322 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
    323 #define SKB_PADTO(_skb,_len) (((_skb = skb_padto(_skb,_len)) == NULL) ? -1 : 0)
    324 #else
    325 #define SKB_PADTO(_skb,_len) skb_padto(_skb,_len)
    326 #endif
    327 
    328 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12))
    329 #define skb_header_cloned(_skb) \
    330     skb_cloned(_skb)
    331 #endif
    332 
    333 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27)
    334 static inline void *netdev_priv(struct net_device *dev)
    335 {
    336         return dev->priv;
    337 }
    338 #endif /* KERNEL_VERSION(2,4,27) */
    339 
    340 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
    341 /* Special check for MontaVista 2.4.20 MIPS */
    342 #if !(defined(MAX_USER_RT_PRIO) && defined(CONFIG_MIPS))
    343 static inline void free_netdev(struct net_device *dev)
    344 {
    345         kfree(dev);
    346 }
    347 #endif
    348 static inline void netif_poll_disable(struct net_device *dev)
    349 {
    350         while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) {
    351                 /* No hurry. */
    352                 current->state = TASK_INTERRUPTIBLE;
    353                 schedule_timeout(1);
    354         }
    355 }
    356 static inline void netif_poll_enable(struct net_device *dev)
    357 {
    358         clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
    359 }
    360 #endif /* KERNEL_VERSION(2,4,23) */
    361 
    362 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21)
    363 static struct sk_buff *skb_pad(struct sk_buff *skb, int pad)
    364 {
    365         struct sk_buff *nskb;
    366 
    367         /* If the skbuff is non linear tailroom is always zero.. */
    368         if(skb_tailroom(skb) >= pad)
    369         {
    370                 memset(skb->data+skb->len, 0, pad);
    371                 return skb;
    372         }
    373 
    374         nskb = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb) + pad, GFP_ATOMIC);
    375         kfree_skb(skb);
    376         if(nskb)
    377                 memset(nskb->data+nskb->len, 0, pad);
    378         return nskb;
    379 }
    380 static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len)
    381 {
    382         unsigned int size = skb->len;
    383         if(likely(size >= len))
    384                 return skb;
    385         return skb_pad(skb, len-size);
    386 }
    387 #endif /* KERNEL_VERSION(2,4,21) */
    388 
    389 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
    390 #define bkn_vlan_hwaccel_put_tag(_skb, _proto, _tci) \
    391     __vlan_hwaccel_put_tag(_skb, _tci)
    392 #else
    393 #define bkn_vlan_hwaccel_put_tag(_skb, _proto, _tci) \
    394     __vlan_hwaccel_put_tag(_skb, htons(_proto), _tci)
    395 #endif
    396 
    397 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
    398 #define bkn_dma_mapping_error(d, a) \
    399     dma_mapping_error(a)
    400 #define bkn_pci_dma_mapping_error(d, a) \
    401     pci_dma_mapping_error(a)
    402 #else
    403 #define bkn_dma_mapping_error(d, a) \
    404     dma_mapping_error(d, a)
    405 #define bkn_pci_dma_mapping_error(d, a) \
    406     pci_dma_mapping_error(d, a)
    407 #endif
    408 
    409 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
    410 enum {
    411     SKBTX_HW_TSTAMP = 1 << 0,
    412     SKBTX_SW_TSTAMP = 1 << 1,
    413     SKBTX_IN_PROGRESS = 1 << 2,
    414 };
    415 struct skb_shared_hwtstamps {
    416     ktime_t hwtstamp;
    417     ktime_t syststamp;
    418 };
    419 struct bkn_skb_shared_info {
    420     uint8_t tx_flags;
    421     struct skb_shared_hwtstamps hwtstamps;
    422 };
    423 #define bkn_skb_shinfo(_skb) ((struct bkn_skb_shared_info *)(unsigned char *)_skb->end)
    424 #define bkn_skb_tx_flags(_skb) bkn_skb_shinfo(_skb)->tx_flags
    425 static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb)
    426 {
    427     return &bkn_skb_shinfo(skb)->hwtstamps;
    428 }
    429 void skb_tstamp_tx(struct sk_buff *orig_skb, struct skb_shared_hwtstamps *hwtstamps)
    430 {
    431 }
    432 static inline void bkn_skb_tx_timestamp(struct sk_buff *skb)
    433 {
    434 }
    435 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
    436 static inline ktime_t ns_to_ktime(u64 ns)
    437 {
    438     static const ktime_t ktime;
    439     return ktime;
    440 }
    441 #endif
    442 #elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
    443 #include <linux/net_tstamp.h>
    444 enum {
    445     SKBTX_HW_TSTAMP = 1 << 0,
    446     SKBTX_SW_TSTAMP = 1 << 1,
    447     SKBTX_IN_PROGRESS = 1 << 2,
    448 };
    449 #define bkn_skb_tx_flags(_skb) skb_shinfo(_skb)->tx_flags.flags
    450 static inline void bkn_skb_tx_timestamp(struct sk_buff *skb)
    451 {
    452 }
    453 #else
    454 #include <linux/net_tstamp.h>
    455 #define bkn_skb_tx_flags(_skb) skb_shinfo(_skb)->tx_flags
    456 static inline void bkn_skb_tx_timestamp(struct sk_buff *skb)
    457 {
    458     return skb_tx_timestamp(skb);
    459 }
    460 #endif
    461 
    462 #ifdef LINUX_BDE_DMA_DEVICE_SUPPORT
    463 #define DMA_DEV                         device
    464 #define DMA_FROMDEV                     DMA_FROM_DEVICE
    465 #define DMA_TODEV                       DMA_TO_DEVICE
    466 #define DMA_MAP_SINGLE(d,p,s,r)         dma_map_single(d,p,s,r)
    467 #define DMA_UNMAP_SINGLE(d,a,s,r)       dma_unmap_single(d,a,s,r)
    468 #define DMA_ALLOC_COHERENT(d,s,h)       dma_alloc_coherent(d,s,h,GFP_ATOMIC|GFP_DMA32)
    469 #define DMA_FREE_COHERENT(d,s,a,h)      dma_free_coherent(d,s,a,h)
    470 #define DMA_MAPPING_ERROR(d,a)          bkn_dma_mapping_error(d,a)
    471 #else
    472 #define DMA_DEV pci_dev
    473 #define DMA_FROMDEV                     PCI_DMA_FROMDEVICE
    474 #define DMA_TODEV                       PCI_DMA_TODEVICE
    475 #define DMA_MAP_SINGLE(d,p,s,r)         pci_map_single(d,p,s,r)
    476 #define DMA_UNMAP_SINGLE(d,a,s,r)       pci_unmap_single(d,a,s,r)
    477 #define DMA_ALLOC_COHERENT(d,s,h)       pci_alloc_consistent(d,s,h)
    478 #define DMA_FREE_COHERENT(d,s,a,h)      pci_free_consistent(d,s,a,h)
    479 #define DMA_MAPPING_ERROR(d,a)          bkn_pci_dma_mapping_error(d,a)
    480 #endif
    481 
    482 /* RCPU operations */
    483 #define RCPU_OPCODE_RX          0x10
    484 #define RCPU_OPCODE_TX          0x20
    485 
    486 /* RCPU flags */
    487 #define RCPU_F_MODHDR           0x4
    488 
    489 /* RCPU encapsulation */
    490 #define RCPU_HDR_SIZE           32
    491 #define RCPU_TX_META_SIZE       32
    492 #define RCPU_TX_ENCAP_SIZE      (RCPU_HDR_SIZE + RCPU_TX_META_SIZE)
    493 #define RCPU_RX_META_SIZE       64
    494 #define RCPU_RX_ENCAP_SIZE      (RCPU_HDR_SIZE + RCPU_RX_META_SIZE)
    495 
    496 #define PKT_TX_HDR_SIZE         16
    497 
    498 static volatile int module_initialized;
    499 
    500 static ibde_t *kernel_bde = NULL;
    501 
    502 /* Descriptor info */
    503 typedef struct bkn_desc_info_s {
    504     uint32_t *dcb_mem;
    505     uint64_t dcb_dma;
    506     struct sk_buff *skb;
    507     uint64_t skb_dma;
    508     uint32_t dma_size;
    509 } bkn_desc_info_t;
    510 
    511 /* DCB chain info */
    512 typedef struct bkn_dcb_chain_s {
    513     struct list_head list;
    514     int dcb_cnt;
    515     int dcb_cur;
    516     uint32_t *dcb_mem;
    517     uint64_t dcb_dma;
    518 } bkn_dcb_chain_t;
    519 
    520 #define MAX_TX_DCBS 64
    521 #define MAX_RX_DCBS 64
    522 
    523 #define NUM_DMA_CHAN 8
    524 #define NUM_RX_CHAN 7
    525 #define NUM_CMICX_RX_CHAN 7
    526 #define NUM_CMICM_RX_CHAN 3
    527 
    528 #define FCS_SZ 4
    529 #define TAG_SZ 4
    530 
    531 /* Device control info */
    532 typedef struct bkn_switch_info_s {
    533     struct list_head list;
    534     struct list_head ndev_list; /* Associated virtual Ethernet interfaces */
    535     struct net_device **ndevs;  /* Indexed array of ndev_list */
    536     int ndev_max;               /* Size of indexed array */
    537     struct list_head rxpf_list; /* Associated Rx packet filters */
    538     volatile void *base_addr;   /* Base address for PCI register access */
    539     struct DMA_DEV *dma_dev;    /* Required for DMA memory control */
    540     struct pci_dev *pdev;       /* Required for DMA memory control */
    541     struct net_device *dev;     /* Base network device */
    542     struct napi_struct napi;    /* New NAPI */
    543     struct timer_list timer;    /* Retry/resource timer */
    544     int timer_queued;           /* Flag indicating queued timer function */
    545     uint32_t timer_runs;        /* Timer function runs (debug only) */
    546     struct timer_list rxtick;   /* Rx rate control timer */
    547     uint32_t rxticks_per_sec;   /* Rx rate control update frequency */
    548     uint32_t rxtick_jiffies;    /* Time between updates (in jiffies) */
    549     uint32_t rxticks;           /* Rx rate control debug counter */
    550     uint32_t interrupts;        /* Total number of interrupts */
    551     spinlock_t lock;            /* Main lock for device */
    552     int dev_no;                 /* Device number (from BDE) */
    553     int cpu_no;                 /* Cpu number. 1 for iHost(AXI),0 for others */
    554     int dcb_type;               /* DCB type */
    555     int dcb_wsize;              /* DCB size (in 32-bit words) */
    556     int pkt_hdr_size;           /* Packet header size */
    557     uint32_t ftmh_lb_key_ext_size;      /* FTMH LB-Key Extension existence/size */
    558     uint32_t ftmh_stacking_ext_size;    /* FTMH Stacking extension existence/size */
    559     uint32_t pph_base_size;         /* Size of PPH base */
    560     uint32_t pph_lif_ext_size[8];   /* Size of PPH Lif extension header */
    561     uint8_t  udh_enable;            /* Indicates UDH existence */
    562     uint32_t udh_length_type[4];    /* Size of UDH header per type */
    563     int rx_chans;               /* Number of Rx channels */
    564     uint32_t dma_hi;            /* DMA higher address */
    565     uint32_t cmic_type;         /* CMIC type (CMICe or CMICm) */
    566     uint32_t irq_mask;          /* Active IRQs for DMA control */
    567     uint32_t napi_poll_mode;    /* NAPI is in polling mode */
    568     uint32_t napi_not_done;     /* NAPI poll did not process all packets */
    569     uint32_t napi_poll_again;   /* Used if DCB chain is restarted */
    570     uint32_t tx_yield;          /* Tx schedule for Continuous DMA and Non-NAPI mode */
    571     void *dcb_mem;              /* Logical pointer to DCB memory */
    572     uint64_t dcb_dma;           /* Physical bus address for DCB memory */
    573     int dcb_mem_size;           /* Total size of allocated DCB memory */
    574     uint32_t dma_events;        /* DMA events pending for BCM API */
    575     uint32_t rcpu_sig;          /* RCPU signature */
    576     uint64_t halt_addr[NUM_DMA_CHAN]; /* DMA halt address */
    577     uint32_t cdma_channels;     /* Active channels for Continuous DMA mode */
    578     uint32_t poll_channels;     /* Channels for polling */
    579     uint32_t inst_id;           /* Instance id of this device */
    580     int evt_idx;                /* Event queue index for this device*/
    581     int basedev_suspended;      /* Base device suspended */
    582     int tx_hwts;                /* HW timestamp for Tx */
    583     int rx_hwts;                /* HW timestamp for Rx */
    584     struct sk_buff_head tx_ptp_queue;   /* Tx PTP skb queue */
    585     struct work_struct tx_ptp_work;     /* Tx PTP work */
    586     struct {
    587         bkn_desc_info_t desc[MAX_TX_DCBS+1];
    588         int free;               /* Number of free Tx DCBs */
    589         int cur;                /* Index of current Tx DCB */
    590         int dirty;              /* Index of next Tx DCB to complete */
    591         int api_active;         /* BCM Tx API is in progress */
    592         int suspends;           /* Calls to netif_stop_queue (debug only) */
    593         struct list_head api_dcb_list; /* Tx DCB chains from BCM Tx API */
    594         bkn_dcb_chain_t *api_dcb_chain; /* Current Tx DCB chain */
    595         bkn_dcb_chain_t *api_dcb_chain_end; /* Tx DCB chain end */
    596         uint32_t pkts;              /* Tx packet counter */
    597         uint32_t pkts_d_no_skb;     /* Tx drop - skb allocation failed */
    598         uint32_t pkts_d_rcpu_encap; /* Tx drop - bad RCPU encapsulation */
    599         uint32_t pkts_d_rcpu_sig;   /* Tx drop - bad RCPU signature */
    600         uint32_t pkts_d_rcpu_meta;  /* Tx drop - bad RCPU meta data */
    601         uint32_t pkts_d_pad_fail;   /* Tx drop - pad to minimum size failed */
    602         uint32_t pkts_d_dma_resrc;  /* Tx drop - no DMA resources */
    603         uint32_t pkts_d_callback;   /* Tx drop - consumed by call-back */
    604         uint32_t pkts_d_no_link;    /* Tx drop - software link down */
    605         uint32_t pkts_d_over_limit; /* Tx drop - length is out of range */
    606     } tx;
    607     struct {
    608         bkn_desc_info_t desc[MAX_RX_DCBS+1];
    609         int free;               /* Number of free Rx DCBs */
    610         int cur;                /* Index of current Rx DCB */
    611         int dirty;              /* Index of next Rx DCB to complete */
    612         int running;            /* Rx DMA is active */
    613         int api_active;         /* BCM Rx API is active */
    614         int chain_complete;     /* All DCBs in chain processed */
    615         int sync_err;           /* Chain done with incomplete DCBs (debug) */
    616         int sync_retry;         /* Total retry times for sync error (debug) */
    617         int sync_maxloop;       /* Max loop times once in recovering sync (debug) */
    618         int use_rx_skb;         /* Use SKBs for DMA */
    619         uint32_t rate_max;      /* Rx rate in packets/sec */
    620         uint32_t burst_max;     /* Rx burst size in number of packets */
    621         uint32_t tokens;        /* Tokens for Rx rate control */
    622         uint32_t rate;          /* Current packet rate */
    623         unsigned long tok_jif;  /* Jiffies at last token update */
    624         unsigned long rate_jif; /* Jiffies at last rate update */
    625         struct list_head api_dcb_list; /* Rx DCB chains from BCM Rx API */
    626         bkn_dcb_chain_t *api_dcb_chain; /* Current Rx DCB chain */
    627         bkn_dcb_chain_t *api_dcb_chain_end; /* Rx DCB chain end */
    628         uint32_t pkts;              /* Rx packet counter */
    629         uint32_t pkts_ref;          /* Rx packet count for rate calculation */
    630         uint32_t pkts_f_api;        /* Rx packets filtered to API */
    631         uint32_t pkts_f_netif;      /* Rx packets filtered to net interface */
    632         uint32_t pkts_m_api;        /* Rx packets mirrored to API */
    633         uint32_t pkts_m_netif;      /* Rx packets mirrored to net interface */
    634         uint32_t pkts_d_no_skb;     /* Rx drop - skb allocation failed */
    635         uint32_t pkts_d_no_match;   /* Rx drop - no matching filters */
    636         uint32_t pkts_d_unkn_netif; /* Rx drop - unknown net interface ID */
    637         uint32_t pkts_d_unkn_dest;  /* Rx drop - unknown destination type */
    638         uint32_t pkts_d_callback;   /* Rx drop - consumed by call-back */
    639         uint32_t pkts_d_no_link;    /* Rx drop - software link down */
    640         uint32_t pkts_d_no_api_buf; /* Rx drop - no API buffers */
    641     } rx[NUM_RX_CHAN];
    642 } bkn_switch_info_t;
    643 
    644 /* PTCH_2 */
    645 #define BKN_DNX_PTCH_2_SIZE         2
    646 /* ITMH */
    647 #define BKN_DNX_ITMH_SIZE           5
    648 /* Modlue Header */
    649 #define BKN_DNX_MODULE_HEADER_SIZE   20
    650 /* FTMH */
    651 #define BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_MSB        17
    652 #define BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_NOF_BITS   16
    653 #define BKN_DNX_FTMH_PP_DSP_MSB                        33
    654 #define BKN_DNX_FTMH_PP_DSP_NOF_BITS                   8
    655 #define BKN_DNX_FTMH_ACTION_TYPE_MSB                   43
    656 #define BKN_DNX_FTMH_ACTION_TYPE_NOF_BITS              2
    657 #define BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_MSB            73
    658 #define BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_NOF_BITS       1
    659 #define BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_MSB            74
    660 #define BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_NOF_BITS       1
    661 #define BKN_DNX_FTMH_TM_DST_EXT_PRESENT_MSB            75
    662 #define BKN_DNX_FTMH_TM_DST_EXT_PRESENT_NOF_BITS       1
    663 #define BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_MSB         76
    664 #define BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_NOF_BITS    1
    665 #define BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_MSB              77
    666 #define BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_NOF_BITS         1
    667 #define BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_MSB             78
    668 #define BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_NOF_BITS        1
    669 /* Fix Length for FTMH and Extension headers */
    670 #define BKN_DNX_FTMH_BASE_SIZE                         10
    671 #define BKN_DNX_FTMH_BIER_BFR_EXT_SIZE                 2
    672 #define BKN_DNX_FTMH_TM_DST_EXT_SIZE                   3
    673 #define BKN_DNX_FTMH_FLOW_ID_EXT_SIZE                  3
    674 #define BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE             6
    675 /* TSH */
    676 #define BKN_DNX_TSH_SIZE                               4
    677 /* PPH */
    678 #define BKN_DNX_PPH_BASE_TYPE_9                        9
    679 #define BKN_DNX_PPH_BASE_TYPE_10                       10
    680 #define BKN_DNX_PPH_BASE_TYPE_12                       12
    681 #define BKN_DNX_PPH_9_FORWARD_DOMAIN_MSB               5
    682 #define BKN_DNX_PPH_9_FORWARD_DOMAIN_NOF_BITS          16
    683 #define BKN_DNX_PPH_9_LEARN_EXT_PRESENT_MSB            53
    684 #define BKN_DNX_PPH_9_LEARN_EXT_PRESENT_NOF_BITS       1
    685 #define BKN_DNX_PPH_9_FHEI_SIZE_MSB                    54
    686 #define BKN_DNX_PPH_9_FHEI_SIZE_NOF_BITS               2
    687 #define BKN_DNX_PPH_9_LIF_EXT_TYPE_MSB                 56
    688 #define BKN_DNX_PPH_9_LIF_EXT_TYPE_NOF_BITS            3
    689 #define BKN_DNX_PPH_10_FORWARD_DOMAIN_MSB              9
    690 #define BKN_DNX_PPH_10_FORWARD_DOMAIN_NOF_BITS         16
    691 #define BKN_DNX_PPH_10_LEARN_EXT_PRESENT_MSB           61
    692 #define BKN_DNX_PPH_10_LEARN_EXT_PRESENT_NOF_BITS      1
    693 #define BKN_DNX_PPH_10_FHEI_SIZE_MSB                   62
    694 #define BKN_DNX_PPH_10_FHEI_SIZE_NOF_BITS              2
    695 #define BKN_DNX_PPH_10_LIF_EXT_TYPE_MSB                64
    696 #define BKN_DNX_PPH_10_LIF_EXT_TYPE_NOF_BITS           3
    697 #define BKN_DNX_PPH_12_FORWARD_DOMAIN_MSB              21
    698 #define BKN_DNX_PPH_12_FORWARD_DOMAIN_NOF_BITS         18
    699 #define BKN_DNX_PPH_12_LEARN_EXT_PRESENT_MSB           77
    700 #define BKN_DNX_PPH_12_LEARN_EXT_PRESENT_NOF_BITS      1
    701 #define BKN_DNX_PPH_12_FHEI_SIZE_MSB                   78
    702 #define BKN_DNX_PPH_12_FHEI_SIZE_NOF_BITS              2
    703 #define BKN_DNX_PPH_12_LIF_EXT_TYPE_MSB                80
    704 #define BKN_DNX_PPH_12_LIF_EXT_TYPE_NOF_BITS           3
    705 /* PPH.FHEI_TYPE */
    706 #define BKN_DNX_PPH_FHEI_TYPE_SZ0                      1
    707 #define BKN_DNX_PPH_FHEI_TYPE_SZ1                      2
    708 #define BKN_DNX_PPH_FHEI_TYPE_SZ2                      3
    709 /* FHEI */
    710 #define BKN_DNX_PPH_FHEI_SZ0_SIZE                      3
    711 #define BKN_DNX_PPH_FHEI_SZ1_SIZE                      5
    712 #define BKN_DNX_PPH_FHEI_SZ2_SIZE                      8
    713 #define BKN_DNX_PPH_FHEI_TRAP_5B_QUALIFIER_MSB         0
    714 #define BKN_DNX_PPH_FHEI_TRAP_5B_QUALIFIER_NOF_BITS    27
    715 #define BKN_DNX_PPH_FHEI_TRAP_5B_CODE_MSB              27
    716 #define BKN_DNX_PPH_FHEI_TRAP_5B_CODE_NOF_BITS         9
    717 #define BKN_DNX_PPH_FHEI_TRAP_5B_TYPE_MSB              36
    718 #define BKN_DNX_PPH_FHEI_TRAP_5B_TYPE_NOF_BITS         4
    719 /* PPH Extension */
    720 #define BKN_DNX_PPH_LEARN_EXT_SIZE                     19
    721 /* UDH */
    722 #define BKN_DNX_UDH_DATA_TYPE_0_MSB                    0
    723 #define BKN_DNX_UDH_DATA_TYPE_0_NOF_BITS               2
    724 #define BKN_DNX_UDH_DATA_TYPE_1_MSB                    2
    725 #define BKN_DNX_UDH_DATA_TYPE_1_NOF_BITS               2
    726 #define BKN_DNX_UDH_DATA_TYPE_2_MSB                    4
    727 #define BKN_DNX_UDH_DATA_TYPE_2_NOF_BITS               2
    728 #define BKN_DNX_UDH_DATA_TYPE_3_MSB                    6
    729 #define BKN_DNX_UDH_DATA_TYPE_3_NOF_BITS               2
    730 #define BKN_DNX_UDH_BASE_SIZE                          1
    731 
    732 #define BKN_DPP_HDR_MAX_SIZE 40
    733 /* PTCH_2 */
    734 #define BKN_DPP_PTCH_2_SIZE         2
    735 /* ITMH */
    736 #define BKN_DPP_ITMH_SIZE           4
    737 /* FTMH */
    738 #define BKN_DPP_FTMH_LB_EXT_EN              0x1
    739 #define BKN_DPP_FTMH_STACKING_EXT_EN        0x2
    740 #define BKN_DPP_FTMH_SIZE_BYTE               9
    741 #define BKN_DPP_FTMH_LB_EXT_SIZE_BYTE        1
    742 #define BKN_DPP_FTMH_STACKING_SIZE_BYTE      2
    743 #define BKN_DPP_FTMH_DEST_EXT_SIZE_BYTE      2
    744 #define BKN_DPP_FTMH_LB_EXT_SIZE_BYTE        1
    745 #define BKN_DPP_FTMH_PKT_SIZE_MSB            0
    746 #define BKN_DPP_FTMH_PKT_SIZE_NOF_BITS       14
    747 #define BKN_DPP_FTMH_TC_MSB                  14
    748 #define BKN_DPP_FTMH_TC_NOF_BITS             3
    749 #define BKN_DPP_FTMH_SRC_SYS_PORT_MSB        17
    750 #define BKN_DPP_FTMH_SRC_SYS_PORT_NOF_BITS   16
    751 #define BKN_DPP_FTMH_EXT_DSP_EXIST_MSB       68
    752 #define BKN_DPP_FTMH_EXT_DSP_EXIST_NOF_BITS  1
    753 #define BKN_DPP_FTMH_EXT_MSB                 45
    754 #define BKN_DPP_FTMH_EXT_NOF_BITS            2
    755 #define BKN_DPP_FTMH_FIRST_EXT_MSB           72
    756 #define BKN_DPP_FTMH_ACTION_TYPE_MSB         43
    757 #define BKN_DPP_FTMH_ACTION_TYPE_NOF_BITS    2
    758 #define BKN_DPP_FTMH_PPH_TYPE_MSB            45
    759 #define BKN_DPP_FTMH_PPH_TYPE_NOF_BITS       2
    760 
    761 /* PPH */
    762 #define BKN_DPP_PPH_SIZE_BYTE                           7
    763 #define BKN_DPP_PPH_EEI_EXTENSION_PRESENT_MSB           0
    764 #define BKN_DPP_PPH_EEI_EXTENSION_PRESENT_NOF_BITS      1
    765 #define BKN_DPP_PPH_LEARN_EXENSION_PRESENT_MSB          1
    766 #define BKN_DPP_PPH_LEARN_EXENSION_PRESENT_NOF_BITS     1
    767 #define BKN_DPP_PPH_FHEI_SIZE_MSB                       2
    768 #define BKN_DPP_PPH_FHEI_SIZE_NOF_BITS                  2
    769 #define BKN_DPP_PPH_FORWARD_CODE_MSB                    4
    770 #define BKN_DPP_PPH_FORWARD_CODE_NOF_BITS               4
    771 #define BKN_DPP_PPH_VSI_MSB                             22
    772 #define BKN_DPP_PPH_VSI_NOF_BITS                        16
    773 /* FHEI TRAP/SNOOP 3B */
    774 #define BKN_DPP_PPH_FHEI_3B_SIZE_BYTE                   3
    775 #define BKN_DPP_PPH_FHEI_5B_SIZE_BYTE                   5
    776 #define BKN_DPP_PPH_FHEI_8B_SIZE_BYTE                   8
    777 #define BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB      0
    778 #define BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS 16
    779 #define BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB                16
    780 #define BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS           8
    781 /* PPH extension */
    782 #define BKN_DPP_PPH_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE     3
    783 #define BKN_DPP_PPH_LEARN_EXTENSION_SIZE_BYTE           5
    784 
    785 /* ftmh action type. */
    786 typedef enum bkn_dpp_ftmh_action_type_e {
    787     BKN_DPP_FTMH_ACTION_TYPE_FORWARD = 0, /* TM action is forward */
    788     BKN_DPP_FTMH_ACTION_TYPE_SNOOP = 1,   /* TM action is snoop */
    789     BKN_DPP_FTMH_ACTION_TYPE_INBOUND_MIRROR = 2, /* TM action is inbound mirror. */
    790     BKN_DPP_FTMH_ACTION_TYPE_OUTBOUND_MIRROR = 3 /* TM action is outbound mirror. */
    791 }bkn_dpp_ftmh_action_type_t;
    792 
    793 /* ftmh dest extension. */
    794 typedef struct bkn_dpp_ftmh_dest_extension_s {
    795     uint8 valid; /* Set if the extension is present */
    796     uint32_t dst_sys_port; /* Destination System Port */
    797 } bkn_dpp_ftmh_dest_extension_t;
    798 
    799 /* dnx packet */
    800 typedef struct bkn_dune_system_header_info_s {
    801     uint32_t ntwrk_header_ptr;
    802     struct {
    803         uint32_t packet_size;                 /* Packet size in bytes */
    804         uint32_t action_type;                 /* Indicates if the copy is one of the Forward Snoop or Mirror packet copies */
    805         uint32_t pph_type;
    806         uint32_t prio;                        /* Traffic class */
    807         uint32_t src_sys_port;                /* Source System port*/
    808     } ftmh;
    809     struct {
    810         uint32_t vsi;
    811         uint32_t trap_qualifier;              /* RAW Data */
    812         uint32_t trap_id;                     /* RAW Data */
    813     } internal;
    814     uint32_t system_header_size;
    815     uint32_t ftmh_spa;                        /* FTMH: Source-System-Port-Aggregate*/
    816     uint32_t pph_forward_domain;              /* PPH:  Forward-Domain*/
    817     uint32_t fhei_qualifier;                  /* FHEI: Qualifier */
    818     uint32_t fhei_code;                       /* FHEI: Code */
    819     uint32_t fhei_type;                       /* FHEI: Type */
    820 } bkn_dune_system_header_info_t;
    821 
    822 #define PREV_IDX(_cur, _max) (((_cur) == 0) ? (_max) - 1 : (_cur) - 1)
    823 
    824 #if defined(CMIC_SOFT_BYTE_SWAP)
    825 
    826 #define CMIC_SWAP32(_x)   ((((_x) & 0xff000000) >> 24) \
    827                          | (((_x) & 0x00ff0000) >>  8) \
    828                          | (((_x) & 0x0000ff00) <<  8) \
    829                          | (((_x) & 0x000000ff) << 24))
    830 
    831 #define DEV_READ32(_d, _a, _p) \
    832     do { \
    833         uint32_t _data; \
    834         _data = (((volatile uint32_t *)(_d)->base_addr)[(_a)/4]); \
    835         *(_p) = CMIC_SWAP32(_data); \
    836     } while(0)
    837 
    838 #define DEV_WRITE32(_d, _a, _v) \
    839     do { \
    840         uint32_t _data = CMIC_SWAP32(_v); \
    841         ((volatile uint32_t *)(_d)->base_addr)[(_a)/4] = (_data); \
    842     } while(0)
    843 
    844 #else
    845 
    846 #define DEV_READ32(_d, _a, _p) \
    847     do { \
    848         *(_p) = (((volatile uint32_t *)(_d)->base_addr)[(_a)/4]); \
    849     } while(0)
    850 
    851 #define DEV_WRITE32(_d, _a, _v) \
    852     do { \
    853         ((volatile uint32_t *)(_d)->base_addr)[(_a)/4] = (_v); \
    854     } while(0)
    855 
    856 #endif  /* defined(CMIC_SOFT_BYTE_SWAP) */
    857 
    858 #define MEMORY_BARRIER smp_mb()
    859 
    860 /* Default random MAC address has Broadcom OUI with local admin bit set */
    861 static u8 bkn_dev_mac[6] = { 0x02, 0x10, 0x18, 0x00, 0x00, 0x00 };
    862 
    863 static u8 bkn_rcpu_dmac[6];
    864 static u8 bkn_rcpu_smac[6];
    865 
    866 /* Driver Proc Entry root */
    867 static struct proc_dir_entry *bkn_proc_root = NULL;
    868 
    869 typedef struct bkn_priv_s {
    870     struct list_head list;
    871     struct net_device_stats stats;
    872     struct net_device *dev;
    873     bkn_switch_info_t *sinfo;
    874     int id;
    875     int type;
    876     int port;
    877     uint8_t itmh[4];
    878     int qnum;
    879     uint32_t vlan;
    880     uint32_t flags;
    881     uint32_t cb_user_data;
    882     uint8_t system_headers[27];
    883     uint32_t system_headers_size;
    884 } bkn_priv_t;
    885 
    886 typedef struct bkn_filter_s {
    887     struct list_head list;
    888     int dev_no;
    889     unsigned long hits;
    890     kcom_filter_t kf;
    891 } bkn_filter_t;
    892 
    893 
    894 /*
    895  * Multiple instance support in KNET
    896  */
    897 static int _bkn_multi_inst = 0;
    898 typedef struct {
    899     wait_queue_head_t evt_wq;
    900     int evt_wq_put;
    901     int evt_wq_get;
    902     uint32_t inst_id;
    903 } bkn_evt_resource_t;
    904 
    905 static bkn_evt_resource_t _bkn_evt[LINUX_BDE_MAX_DEVICES];
    906 
    907 static int bkn_knet_dev_init(int d);
    908 static int bkn_knet_dev_reinit(int d);
    909 
    910 /* IOCTL debug counters */
    911 static int ioctl_cmd;
    912 static int ioctl_evt;
    913 
    914 /* Switch devices */
    915 LIST_HEAD(_sinfo_list);
    916 
    917 /* Reallocation chunk size for netif array */
    918 #define NDEVS_CHUNK     64
    919 
    920 /* User call-backs */
    921 static knet_skb_cb_f knet_rx_cb = NULL;
    922 static knet_skb_cb_f knet_tx_cb = NULL;
    923 static knet_filter_cb_f knet_filter_cb = NULL;
    924 static knet_hw_tstamp_enable_cb_f knet_hw_tstamp_enable_cb = NULL;
    925 static knet_hw_tstamp_enable_cb_f knet_hw_tstamp_disable_cb = NULL;
    926 static knet_hw_tstamp_tx_time_get_cb_f knet_hw_tstamp_tx_time_get_cb = NULL;
    927 static knet_hw_tstamp_tx_meta_get_cb_f knet_hw_tstamp_tx_meta_get_cb = NULL;
    928 static knet_hw_tstamp_ptp_clock_index_cb_f knet_hw_tstamp_ptp_clock_index_cb = NULL;
    929 static knet_hw_tstamp_rx_time_upscale_cb_f knet_hw_tstamp_rx_time_upscale_cb = NULL;
    930 
    931 /*
    932  * Thread management
    933  */
    934 
    935 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10))
    936 /*
    937  * Old style using kernel_thread()
    938  */
    939 typedef struct {
    940     const char * name;
    941     volatile int pid;
    942     volatile int run;
    943     struct completion completion;
    944     int state;
    945 } bkn_thread_ctrl_t;
    946 
    947 static int
    948 bkn_thread_start(bkn_thread_ctrl_t *tc, const char *name,
    949                  int (*threadfn)(void *))
    950 {
    951     if (name == NULL) {
    952         return -1;
    953     }
    954     tc->name = name;
    955     tc->pid = kernel_thread(threadfn, tc, 0);
    956     if (tc->pid < 0) {
    957         tc->pid = 0;
    958         return -1;
    959     }
    960     tc->run = 1;
    961     init_completion(&tc->completion);
    962     return 0;
    963 }
    964 
    965 static int
    966 bkn_thread_stop(bkn_thread_ctrl_t *tc)
    967 {
    968     if (tc->pid == 0) {
    969         return 0;
    970     }
    971     tc->run = 0;
    972     kill_proc(tc->pid, SIGTERM, 1);
    973     wait_for_completion(&tc->completion);
    974     return 0;
    975 }
    976 
    977 static int
    978 bkn_thread_should_stop(bkn_thread_ctrl_t *tc)
    979 {
    980     if (tc->run) {
    981         return 0;
    982     }
    983     tc->pid = 0;
    984     return 1;
    985 }
    986 
    987 static void
    988 bkn_thread_boot(bkn_thread_ctrl_t *tc)
    989 {
    990     siginitsetinv(&current->blocked, sigmask(SIGTERM) | sigmask(SIGKILL));
    991 }
    992 
    993 static void
    994 bkn_thread_exit(bkn_thread_ctrl_t *tc)
    995 {
    996     complete_and_exit(&tc->completion, 0);
    997 }
    998 
    999 static void
   1000 bkn_sleep(int clicks)
   1001 {
   1002     wait_queue_head_t wq;
   1003 
   1004     init_waitqueue_head(&wq);
   1005     sleep_on_timeout(&wq, clicks);
   1006 }
   1007 #else
   1008 /*
   1009  * New style using kthread API
   1010  */
   1011 #include <linux/kthread.h>
   1012 typedef struct {
   1013     const char * name;
   1014     struct task_struct *task;
   1015     int state;
   1016 } bkn_thread_ctrl_t;
   1017 
   1018 static int
   1019 bkn_thread_start(bkn_thread_ctrl_t *tc, const char *name,
   1020                  int (*threadfn)(void *))
   1021 {
   1022     if (name == NULL) {
   1023         return -1;
   1024     }
   1025     tc->name = name;
   1026     tc->task = kthread_run(threadfn, tc, name);
   1027     if (IS_ERR(tc->task)) {
   1028         tc->task = NULL;
   1029         return -1;
   1030     }
   1031     return 0;
   1032 }
   1033 
   1034 static int
   1035 bkn_thread_stop(bkn_thread_ctrl_t *tc)
   1036 {
   1037     if (tc->task == NULL) {
   1038         return 0;
   1039     }
   1040     send_sig(SIGTERM, tc->task, 0);
   1041     return kthread_stop(tc->task);
   1042 }
   1043 
   1044 static int
   1045 bkn_thread_should_stop(bkn_thread_ctrl_t *tc)
   1046 {
   1047     return kthread_should_stop();
   1048 }
   1049 
   1050 static void
   1051 bkn_thread_boot(bkn_thread_ctrl_t *tc)
   1052 {
   1053     allow_signal(SIGTERM);
   1054     allow_signal(SIGKILL);
   1055 }
   1056 
   1057 static void
   1058 bkn_thread_exit(bkn_thread_ctrl_t *tc)
   1059 {
   1060 }
   1061 
   1062 static void
   1063 bkn_sleep(int clicks)
   1064 {
   1065     wait_queue_head_t wq;
   1066 
   1067     init_waitqueue_head(&wq);
   1068     wait_event_timeout(wq, 0, clicks);
   1069 }
   1070 #endif
   1071 
   1072 static bkn_thread_ctrl_t bkn_cmd_ctrl;
   1073 static bkn_thread_ctrl_t bkn_evt_ctrl;
   1074 
   1075 /*
   1076  * On XGS devices bit 15 fo the Transferred Bytes field in
   1077  * the DCBs is used to indicate that kernel processing is
   1078  * complete. Using this bit reduces the theoretically maximum
   1079  * supported packet size from 64K to 32K, but this is still
   1080  * adequate for 16K jumbo packets.
   1081  */
   1082 #define SOC_DCB_KNET_DONE       0x8000
   1083 #define SOC_DCB_KNET_COUNT_MASK 0x7fff
   1084 #define SOC_DCB_META_OFFSET     2
   1085 
   1086 /* Default channel configuration */
   1087 #define XGS_DMA_TX_CHAN         0
   1088 #define XGS_DMA_RX_CHAN         1
   1089 
   1090 /* CMIC registers */
   1091 #define CMIC_DMA_CTRLr          0x00000100
   1092 #define CMIC_DMA_STATr          0x00000104
   1093 #define CMIC_DMA_DESC0r         0x00000110
   1094 #define CMIC_IRQ_STATr          0x00000144
   1095 #define CMIC_IRQ_MASKr          0x00000148
   1096 #define CMIC_DEV_REV_IDr        0x00000178
   1097 
   1098 /* CMIC interrupts reserved for kernel handler */
   1099 #define CMIC_TXRX_IRQ_MASK      0x7f80
   1100 
   1101 /* CMICm registers */
   1102 #define CMICM_CMC_BASE          0x00031000
   1103 #define CMICM_DMA_CTRLr         (CMICM_CMC_BASE + 0x00000140)
   1104 #define CMICM_DMA_STATr         (CMICM_CMC_BASE + 0x00000150)
   1105 #define CMICM_DMA_STAT_CLRr     (CMICM_CMC_BASE + 0x000001a4)
   1106 #define CMICM_DMA_DESC0r        (CMICM_CMC_BASE + 0x00000158)
   1107 #define CMICM_DMA_HALT_ADDRr    (CMICM_CMC_BASE + 0x00000120)
   1108 #define CMICM_IRQ_STATr         (CMICM_CMC_BASE + 0x00000400)
   1109 #define CMICM_IRQ_PCI_MASKr     (CMICM_CMC_BASE + 0x00000414)
   1110 #define CMICM_IRQ_UC0_MASKr     (CMICM_CMC_BASE + 0x00000428)
   1111 #define CMICM_DEV_REV_IDr       0x00010224
   1112 
   1113 /* CMICm interrupts reserved for kernel handler */
   1114 #define CMICM_TXRX_IRQ_MASK     0xff00
   1115 
   1116 /* CMICd increased interrupts reserved for kernel handler */
   1117 #define CMICD_CTRLD_IRQ_MASK    0x78000000
   1118 
   1119 /* CMICx registers */
   1120 #define CMICX_CMC_BASE          0x00000000
   1121 #define CMICX_DMA_CTRLr         (CMICX_CMC_BASE + 0x00002100)
   1122 #define CMICX_DMA_STATr         (CMICX_CMC_BASE + 0x00002114)
   1123 #define CMICX_DMA_DESC_HIr      (CMICX_CMC_BASE + 0x00002108)
   1124 #define CMICX_DMA_DESC_LOr      (CMICX_CMC_BASE + 0x00002104)
   1125 #define CMICX_DMA_HALT_HIr      (CMICX_CMC_BASE + 0x00002110)
   1126 #define CMICX_DMA_HALT_LOr      (CMICX_CMC_BASE + 0x0000210c)
   1127 #define CMICX_IRQ_STATr         (CMICX_CMC_BASE + 0x0000106c)
   1128 #define CMICX_IRQ_STAT_CLRr     (CMICX_CMC_BASE + 0x00001074)
   1129 #define CMICX_IRQ_ENABr         0x18013100
   1130 #define IHOST_GIC_GIC400_GICD_ISENABLERN_5r 0x10781114
   1131 #define IHOST_GIC_GIC400_GICD_ICENABLERN_5r 0x10781194
   1132 
   1133 /* CMICx interrupts reserved for kernel handler */
   1134 #define CMICX_TXRX_IRQ_MASK     0xffffffff
   1135 
   1136 #define DEV_IS_CMICX(_sinfo)    ((_sinfo)->cmic_type == 'x')
   1137 #define DEV_IS_CMICM(_sinfo)    ((_sinfo)->cmic_type == 'm')
   1138 #define CDMA_CH(_d, _ch)        ((_d)->cdma_channels & (1 << (_ch)))
   1139 
   1140 /*
   1141  * DMA_STAT: control bits
   1142  *
   1143  *  xxx_SET and xxx_CLR can be WRITTEN to CMIC_DMA_STAT
   1144  *  xxx_TST can be masked against values read from CMIC_DMA_STAT.
   1145  *  Argument required: 0 <= ch <= 3
   1146  */
   1147 #define DS_DMA_ACTIVE(ch)               (0x00040000 << (ch))
   1148 #define DS_DMA_EN_SET(ch)               (0x80|(ch))
   1149 #define DS_DMA_EN_CLR(ch)               (0x00|(ch))
   1150 #define DS_DMA_EN_TST(ch)               (0x00000001 << (ch))
   1151 
   1152 #define DS_CHAIN_DONE_SET(ch)           (0x80|(4+(ch)))
   1153 #define DS_CHAIN_DONE_CLR(ch)           (0x00|(4+(ch)))
   1154 #define DS_CHAIN_DONE_TST(ch)           (0x00000010 << (ch))
   1155 
   1156 #define DS_DESC_DONE_SET(ch)            (0x80|(8+(ch)))
   1157 #define DS_DESC_DONE_CLR(ch)            (0x00|(8+(ch)))
   1158 #define DS_DESC_DONE_TST(ch)            (0x00000100 << (ch))
   1159 
   1160 #define DC_ABORT_DMA(ch)                (0x04 << (8 * (ch)))
   1161 
   1162 #define DS_CMC_DESCRD_CMPLT_CLR(ch)     (0x00000001 << (ch))
   1163 #define DS_CMC_CTRLD_INT_CLR(ch)        (0x00000100 << (ch))
   1164 #define DS_CMC_DMA_ACTIVE(ch)           (0x00000100 << (ch))
   1165 
   1166 #define CMICX_DS_CMC_DESC_DONE(ch)      (0x00000001 << ((ch) * 4))
   1167 #define CMICX_DS_CMC_CHAIN_DONE(ch)     (0x00000002 << ((ch) * 4))
   1168 #define CMICX_DS_CMC_CTRLD_INT(ch)      (0x00000008 << ((ch) * 4))
   1169 #define CMICX_DS_CMC_DMA_CHAIN_DONE     (0x00000001)
   1170 #define CMICX_DS_CMC_DMA_ACTIVE         (0x00000002)
   1171 
   1172 #define DMA_TO_BUS_HI(dma)              ((dma) | sinfo->dma_hi)
   1173 #define BUS_TO_DMA_HI(bus)              ((bus) & ~sinfo->dma_hi)
   1174 
   1175 /*
   1176  * DMA_CTRL: control bits
   1177  */
   1178 #define DC_CMC_DIRECTION                (0x00000001)
   1179 #define DC_CMC_ENABLE                   (0x00000002)
   1180 #define DC_CMC_ABORT                    (0x00000004)
   1181 #define DC_CMC_CTRLD_INT                (0x00000100)
   1182 #define DC_CMC_CONTINUOUS               (0x00000200)
   1183 
   1184 #define CMICX_DC_CMC_DIRECTION          (0x00000001)
   1185 #define CMICX_DC_CMC_ENABLE             (0x00000002)
   1186 #define CMICX_DC_CMC_ABORT              (0x00000004)
   1187 #define CMICX_DC_CMC_CTRLD_INT          (0x00000080)
   1188 #define CMICX_DC_CMC_CONTINUOUS         (0x00000100)
   1189 
   1190 /*
   1191  * Per-channel operations.
   1192  * These are the basis for the TX/RX functions
   1193  */
   1194 
   1195 static inline void
   1196 xgs_dma_chain_clear(bkn_switch_info_t *sinfo, int chan)
   1197 {
   1198     DBG_IRQ(("Clear chain on device %d chan %d\n",
   1199              sinfo->dev_no, chan));
   1200     DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DMA_EN_CLR(chan));
   1201     DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_CHAIN_DONE_CLR(chan));
   1202 
   1203     MEMORY_BARRIER;
   1204 }
   1205 
   1206 static inline void
   1207 xgs_dma_desc_clear(bkn_switch_info_t *sinfo, int chan)
   1208 {
   1209     uint32_t val;
   1210 
   1211     DBG_IRQ(("Clear desc on device %d chan %d\n",
   1212              sinfo->dev_no, chan));
   1213     DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DESC_DONE_CLR(chan));
   1214 
   1215     MEMORY_BARRIER;
   1216 
   1217     /* Flush write buffer */
   1218     DEV_READ32(sinfo, CMIC_DMA_STATr, &val);
   1219 
   1220     MEMORY_BARRIER;
   1221 }
   1222 
   1223 static int
   1224 xgs_dma_chan_clear(bkn_switch_info_t *sinfo, int chan)
   1225 {
   1226     xgs_dma_chain_clear(sinfo, chan);
   1227     xgs_dma_desc_clear(sinfo, chan);
   1228 
   1229     return 0;
   1230 }
   1231 
   1232 static int
   1233 xgs_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir)
   1234 {
   1235     uint32_t cdc;
   1236 
   1237     DEV_READ32(sinfo, CMIC_DMA_CTRLr, &cdc);
   1238 
   1239     cdc &= ~(0x9 << (8 * chan));
   1240     if (dir) {
   1241         cdc |= 0x1 << (8 * chan);
   1242     } else {
   1243         cdc |= 0x8 << (8 * chan);
   1244     }
   1245 
   1246     DEV_WRITE32(sinfo, CMIC_DMA_CTRLr, cdc);
   1247 
   1248     return 0;
   1249 }
   1250 
   1251 static int
   1252 xgs_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb)
   1253 {
   1254     /* Write the DCB address to the DESC address for this channel */
   1255     DEV_WRITE32(sinfo, CMIC_DMA_DESC0r + 4 * chan, dcb);
   1256 
   1257     MEMORY_BARRIER;
   1258 
   1259     /* Kick it off */
   1260     DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DMA_EN_SET(chan));
   1261 
   1262     MEMORY_BARRIER;
   1263 
   1264     return 0;
   1265 }
   1266 
   1267 static int
   1268 xgs_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls)
   1269 {
   1270     uint32_t ctrl, dma_stat;
   1271     int p;
   1272 
   1273     /* Clear enable */
   1274     DEV_WRITE32(sinfo, CMIC_DMA_STATr, DS_DMA_EN_CLR(chan));
   1275 
   1276     MEMORY_BARRIER;
   1277 
   1278     /* Abort the channel */
   1279     DEV_READ32(sinfo, CMIC_DMA_CTRLr, &ctrl);
   1280     DEV_WRITE32(sinfo, CMIC_DMA_CTRLr, ctrl | DC_ABORT_DMA(chan));
   1281 
   1282     MEMORY_BARRIER;
   1283 
   1284     /* Poll for abort completion */
   1285     for (p = 0; p < polls; p++) {
   1286         DEV_READ32(sinfo, CMIC_DMA_STATr, &dma_stat);
   1287         if (!(dma_stat & DS_DMA_ACTIVE(chan))) {
   1288             /* Restore previous control value */
   1289             DEV_WRITE32(sinfo, CMIC_DMA_CTRLr, ctrl);
   1290 
   1291             MEMORY_BARRIER;
   1292 
   1293             /* Clear up channel */
   1294             xgs_dma_chan_clear(sinfo, chan);
   1295 
   1296             return polls;
   1297         }
   1298     }
   1299     DBG_WARN(("DMA channel %d abort failed\n", chan));
   1300 
   1301     return -1;
   1302 }
   1303 
   1304 static inline void
   1305 xgs_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask)
   1306 {
   1307     if (sinfo->napi_poll_mode) {
   1308         mask = 0;
   1309     }
   1310     lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV, CMIC_IRQ_MASKr,
   1311                        mask, CMIC_TXRX_IRQ_MASK);
   1312 }
   1313 
   1314 static inline void
   1315 xgs_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw)
   1316 {
   1317     uint32_t mask;
   1318 
   1319     if (chan == XGS_DMA_TX_CHAN) {
   1320         mask = 0x100;
   1321     } else {
   1322         mask = 0x180 << (2 * chan);
   1323     }
   1324 
   1325     sinfo->irq_mask |= mask;
   1326 
   1327     if (update_hw) {
   1328         xgs_irq_mask_set(sinfo, sinfo->irq_mask);
   1329     }
   1330 }
   1331 
   1332 static inline void
   1333 xgs_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw)
   1334 {
   1335     uint32_t mask;
   1336 
   1337     if (chan == XGS_DMA_TX_CHAN) {
   1338         mask = 0x100;
   1339     } else {
   1340         mask = 0x180 << (2 * chan);
   1341     }
   1342 
   1343     sinfo->irq_mask &= ~mask;
   1344 
   1345     if (update_hw) {
   1346         xgs_irq_mask_set(sinfo, sinfo->irq_mask);
   1347     }
   1348 }
   1349 
   1350 static inline void
   1351 xgsm_dma_chain_clear(bkn_switch_info_t *sinfo, int chan)
   1352 {
   1353     uint32_t cdc;
   1354 
   1355     /* Disabing DMA clears chain done */
   1356     DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &cdc);
   1357     cdc &= ~(DC_CMC_ENABLE | DC_CMC_ABORT);
   1358     DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, cdc);
   1359 
   1360     MEMORY_BARRIER;
   1361 }
   1362 
   1363 static inline void
   1364 xgsm_dma_desc_clear(bkn_switch_info_t *sinfo, int chan)
   1365 {
   1366     uint32_t val;
   1367 
   1368     val = DS_CMC_DESCRD_CMPLT_CLR(chan);
   1369     if (CDMA_CH(sinfo, chan)) {
   1370         val |= DS_CMC_CTRLD_INT_CLR(chan);
   1371     }
   1372     DEV_WRITE32(sinfo, CMICM_DMA_STAT_CLRr, val);
   1373 
   1374     MEMORY_BARRIER;
   1375 
   1376     /* Flush write buffer */
   1377     DEV_READ32(sinfo, CMICM_DMA_STAT_CLRr, &val);
   1378 
   1379     MEMORY_BARRIER;
   1380 }
   1381 
   1382 static int
   1383 xgsm_dma_chan_clear(bkn_switch_info_t *sinfo, int chan)
   1384 {
   1385     xgsm_dma_chain_clear(sinfo, chan);
   1386     xgsm_dma_desc_clear(sinfo, chan);
   1387 
   1388     return 0;
   1389 }
   1390 
   1391 static inline void
   1392 xgsm_cdma_halt_set(bkn_switch_info_t *sinfo, int chan)
   1393 {
   1394     DEV_WRITE32(sinfo, CMICM_DMA_HALT_ADDRr + 4 * chan,
   1395                 sinfo->halt_addr[chan]);
   1396 
   1397     MEMORY_BARRIER;
   1398 }
   1399 
   1400 static int 
   1401 xgsm_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir)
   1402 {
   1403     uint32_t cdc;
   1404 
   1405     DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &cdc);
   1406     cdc &= ~DC_CMC_DIRECTION;
   1407     if (dir) {
   1408         cdc |= DC_CMC_DIRECTION;
   1409     }
   1410     if (CDMA_CH(sinfo, chan)) {
   1411         cdc |= DC_CMC_CONTINUOUS | DC_CMC_CTRLD_INT;
   1412         xgsm_cdma_halt_set(sinfo, chan);
   1413     }
   1414     DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, cdc);
   1415 
   1416     return 0;
   1417 }
   1418 
   1419 static int
   1420 xgsm_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb)
   1421 {
   1422     uint32_t cdc;
   1423 
   1424     /* Write the DCB address to the DESC address for this channel */
   1425     DEV_WRITE32(sinfo, CMICM_DMA_DESC0r + 4 * chan, dcb);
   1426 
   1427     MEMORY_BARRIER;
   1428 
   1429     /* Kick it off */
   1430     DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &cdc);
   1431     cdc |= DC_CMC_ENABLE;
   1432     DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, cdc);
   1433 
   1434     MEMORY_BARRIER;
   1435 
   1436     return 0;
   1437 }
   1438 
   1439 static int
   1440 xgsm_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls)
   1441 {
   1442     uint32_t ctrl, dma_stat;
   1443     int p;
   1444 
   1445     /* Skip abort sequence if channel is not active */
   1446     DEV_READ32(sinfo, CMICM_DMA_STATr, &dma_stat);
   1447     if (!(dma_stat & DS_CMC_DMA_ACTIVE(chan))) {
   1448         return 0;
   1449     }
   1450 
   1451     /* Abort the channel */
   1452     DEV_READ32(sinfo, CMICM_DMA_CTRLr + 4 * chan, &ctrl);
   1453     ctrl |= (DC_CMC_ENABLE | DC_CMC_ABORT);
   1454     DEV_WRITE32(sinfo, CMICM_DMA_CTRLr + 4 * chan, ctrl);
   1455 
   1456     MEMORY_BARRIER;
   1457 
   1458     /* Poll for abort completion */
   1459     for (p = 0; p < polls; p++) {
   1460         DEV_READ32(sinfo, CMICM_DMA_STATr, &dma_stat);
   1461         if (!(dma_stat & DS_CMC_DMA_ACTIVE(chan))) {
   1462             /* Clear up channel */
   1463             xgsm_dma_chan_clear(sinfo, chan);
   1464             return polls;
   1465         }
   1466     }
   1467     DBG_WARN(("DMA channel %d abort failed\n", chan));
   1468 
   1469     return -1;
   1470 }
   1471 
   1472 static inline void
   1473 xgsm_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask)
   1474 {
   1475     uint32_t irq_mask_reg = CMICM_IRQ_PCI_MASKr;
   1476     uint32_t ctrld_mask = 0;
   1477 
   1478     if (sinfo->napi_poll_mode) {
   1479         mask = 0;
   1480     }
   1481     if (sinfo->cpu_no == 1) {
   1482         irq_mask_reg = CMICM_IRQ_UC0_MASKr;
   1483     }
   1484 
   1485     /* Get the Controlled Interrupts mask for Continuous DMA mode */
   1486     ctrld_mask |= (sinfo->cdma_channels << 27) & CMICD_CTRLD_IRQ_MASK;
   1487 
   1488     lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV, irq_mask_reg,
   1489                        mask, CMICM_TXRX_IRQ_MASK | ctrld_mask);
   1490 }
   1491 
   1492 static inline void
   1493 xgsm_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw)
   1494 {
   1495     uint32_t mask;
   1496 
   1497     if (CDMA_CH(sinfo, chan)) {
   1498         mask = 0x08000000 << chan;
   1499     } else {
   1500         if (chan == XGS_DMA_TX_CHAN) {
   1501             mask = 0x8000;
   1502         } else {
   1503             mask = 0xc000 >> (2 * chan);
   1504         }
   1505     }
   1506 
   1507     sinfo->irq_mask |= mask;
   1508 
   1509     if (update_hw) {
   1510         xgsm_irq_mask_set(sinfo, sinfo->irq_mask);
   1511     }
   1512 }
   1513 
   1514 static inline void
   1515 xgsm_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw)
   1516 {
   1517     uint32_t mask;
   1518 
   1519     if (CDMA_CH(sinfo, chan)) {
   1520         mask = 0x08000000 << chan;
   1521     } else {
   1522         if (chan == XGS_DMA_TX_CHAN) {
   1523             mask = 0x8000;
   1524         } else {
   1525             mask = 0xc000 >> (2 * chan);
   1526         }
   1527     }
   1528 
   1529     sinfo->irq_mask &= ~mask;
   1530 
   1531     if (update_hw) {
   1532         xgsm_irq_mask_set(sinfo, sinfo->irq_mask);
   1533     }
   1534 }
   1535 
   1536 static inline void
   1537 xgsx_dma_chain_clear(bkn_switch_info_t *sinfo, int chan)
   1538 {
   1539     uint32_t ctrl, stat;
   1540 
   1541     /* Disabing DMA clears chain done */
   1542     DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl);
   1543     ctrl &= ~(CMICX_DC_CMC_ENABLE | CMICX_DC_CMC_ABORT);
   1544     DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl);
   1545 
   1546     stat = CMICX_DS_CMC_CHAIN_DONE(chan);
   1547     DEV_WRITE32(sinfo, CMICX_IRQ_STAT_CLRr, stat);
   1548 
   1549     MEMORY_BARRIER;
   1550 
   1551     /* Flush write buffer */
   1552     DEV_READ32(sinfo, CMICX_IRQ_STAT_CLRr, &stat);
   1553 
   1554     MEMORY_BARRIER;
   1555 }
   1556 
   1557 static inline void
   1558 xgsx_dma_desc_clear(bkn_switch_info_t *sinfo, int chan)
   1559 {
   1560     uint32_t stat;
   1561 
   1562     if (CDMA_CH(sinfo, chan)) {
   1563         stat = CMICX_DS_CMC_CTRLD_INT(chan);
   1564     } else {
   1565         stat = CMICX_DS_CMC_DESC_DONE(chan);
   1566     }
   1567     DEV_WRITE32(sinfo, CMICX_IRQ_STAT_CLRr, stat);
   1568 
   1569     MEMORY_BARRIER;
   1570 
   1571     /* Flush write buffer */
   1572     DEV_READ32(sinfo, CMICX_IRQ_STAT_CLRr, &stat);
   1573 
   1574     MEMORY_BARRIER;
   1575 }
   1576 
   1577 static int
   1578 xgsx_dma_chan_clear(bkn_switch_info_t *sinfo, int chan)
   1579 {
   1580     xgsx_dma_chain_clear(sinfo, chan);
   1581     xgsx_dma_desc_clear(sinfo, chan);
   1582 
   1583     return 0;
   1584 }
   1585 
   1586 static inline void
   1587 xgsx_cdma_halt_set(bkn_switch_info_t *sinfo, int chan)
   1588 {
   1589     DEV_WRITE32(sinfo, CMICX_DMA_HALT_LOr + 0x80 * chan,
   1590                 sinfo->halt_addr[chan]);
   1591     DEV_WRITE32(sinfo, CMICX_DMA_HALT_HIr + 0x80 * chan,
   1592                 DMA_TO_BUS_HI(sinfo->halt_addr[chan] >> 32));
   1593 
   1594     MEMORY_BARRIER;
   1595 }
   1596 
   1597 static int
   1598 xgsx_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir)
   1599 {
   1600     uint32_t ctrl;
   1601 
   1602     DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl);
   1603     ctrl &= ~CMICX_DC_CMC_DIRECTION;
   1604     if (dir) {
   1605         ctrl |= CMICX_DC_CMC_DIRECTION;
   1606     }
   1607     if (CDMA_CH(sinfo, chan)) {
   1608         ctrl |= CMICX_DC_CMC_CONTINUOUS | CMICX_DC_CMC_CTRLD_INT;
   1609         xgsx_cdma_halt_set(sinfo, chan);
   1610     }
   1611     DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl);
   1612 
   1613     MEMORY_BARRIER;
   1614 
   1615     return 0;
   1616 }
   1617 
   1618 static int
   1619 xgsx_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb)
   1620 {
   1621     uint32_t ctrl;
   1622 
   1623     /* Write the DCB address to the DESC address for this channel */
   1624     DEV_WRITE32(sinfo, CMICX_DMA_DESC_LOr + 0x80 * chan, dcb);
   1625     DEV_WRITE32(sinfo, CMICX_DMA_DESC_HIr + 0x80 * chan, DMA_TO_BUS_HI(dcb >> 32));
   1626 
   1627     MEMORY_BARRIER;
   1628 
   1629     /* Kick it off */
   1630     DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl);
   1631     ctrl |= CMICX_DC_CMC_ENABLE;
   1632     DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl);
   1633 
   1634     MEMORY_BARRIER;
   1635 
   1636     return 0;
   1637 }
   1638 
   1639 static int
   1640 xgsx_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls)
   1641 {
   1642     uint32_t ctrl, stat;
   1643     int p;
   1644 
   1645     /* Skip abort sequence if channel is not active */
   1646     DEV_READ32(sinfo, CMICX_DMA_STATr + 0x80 * chan, &stat);
   1647     if (!(stat & CMICX_DS_CMC_DMA_ACTIVE)) {
   1648         return 0;
   1649     }
   1650 
   1651     /* Abort the channel */
   1652     DEV_READ32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, &ctrl);
   1653     ctrl |= CMICX_DC_CMC_ENABLE | CMICX_DC_CMC_ABORT;
   1654     DEV_WRITE32(sinfo, CMICX_DMA_CTRLr + 0x80 * chan, ctrl);
   1655 
   1656     MEMORY_BARRIER;
   1657 
   1658     /* Poll for abort completion */
   1659     for (p = 0; p < polls; p++) {
   1660         DEV_READ32(sinfo, CMICX_DMA_STATr + 0x80 * chan, &stat);
   1661         if (!(stat & CMICX_DS_CMC_DMA_ACTIVE)) {
   1662             /* Clear up channel */
   1663             xgsx_dma_chan_clear(sinfo, chan);
   1664             return polls;
   1665         }
   1666     }
   1667 
   1668     DBG_WARN(("DMA channel %d abort failed\n", chan));
   1669 
   1670     return -1;
   1671 }
   1672 
   1673 static inline void
   1674 xgsx_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask)
   1675 {
   1676     uint32_t irq_mask_reg = CMICX_IRQ_ENABr;
   1677     uint32_t irq_mask, irq_fmask, disable_mask;
   1678 
   1679     if (sinfo->napi_poll_mode) {
   1680         mask = 0;
   1681     }
   1682 
   1683     if (sinfo->cpu_no == 1) {
   1684         lkbde_irq_mask_get(sinfo->dev_no, &irq_mask, &irq_fmask);
   1685         disable_mask = ~mask & (irq_mask & irq_fmask);
   1686         if (disable_mask) {
   1687             lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV | LKBDE_IPROC_REG,
   1688                        IHOST_GIC_GIC400_GICD_ICENABLERN_5r, disable_mask, CMICX_TXRX_IRQ_MASK);
   1689         }
   1690         irq_mask_reg = IHOST_GIC_GIC400_GICD_ISENABLERN_5r;
   1691     }
   1692 
   1693     lkbde_irq_mask_set(sinfo->dev_no | LKBDE_ISR2_DEV | LKBDE_IPROC_REG,
   1694                        irq_mask_reg, mask, CMICX_TXRX_IRQ_MASK);
   1695 }
   1696 
   1697 static inline void
   1698 xgsx_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw)
   1699 {
   1700     uint32_t mask;
   1701 
   1702     if (CDMA_CH(sinfo, chan)) {
   1703         mask = CMICX_DS_CMC_CTRLD_INT(chan);
   1704     } else {
   1705         if (chan == XGS_DMA_TX_CHAN) {
   1706             mask = CMICX_DS_CMC_CHAIN_DONE(chan);
   1707         } else {
   1708             mask = CMICX_DS_CMC_DESC_DONE(chan) |
   1709                    CMICX_DS_CMC_CHAIN_DONE(chan);
   1710         }
   1711     }
   1712 
   1713     sinfo->irq_mask |= mask;
   1714 
   1715     if (update_hw) {
   1716         xgsx_irq_mask_set(sinfo, sinfo->irq_mask);
   1717     }
   1718 }
   1719 
   1720 static inline void
   1721 xgsx_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw)
   1722 {
   1723     uint32_t mask;
   1724 
   1725     if (CDMA_CH(sinfo, chan)) {
   1726         mask = CMICX_DS_CMC_CTRLD_INT(chan);
   1727     } else {
   1728         if (chan == XGS_DMA_TX_CHAN) {
   1729             mask = CMICX_DS_CMC_CHAIN_DONE(chan);
   1730         } else {
   1731             mask = CMICX_DS_CMC_DESC_DONE(chan) |
   1732                    CMICX_DS_CMC_CHAIN_DONE(chan);
   1733         }
   1734     }
   1735 
   1736     sinfo->irq_mask &= ~mask;
   1737 
   1738     if (update_hw) {
   1739         xgsx_irq_mask_set(sinfo, sinfo->irq_mask);
   1740     }
   1741 }
   1742 
   1743 static inline void
   1744 dev_dma_chain_clear(bkn_switch_info_t *sinfo, int chan)
   1745 {
   1746     if (DEV_IS_CMICX(sinfo)) {
   1747         xgsx_dma_chain_clear(sinfo, chan);
   1748     } else if (DEV_IS_CMICM(sinfo)) {
   1749         xgsm_dma_chain_clear(sinfo, chan);
   1750     } else {
   1751         xgs_dma_chain_clear(sinfo, chan);
   1752     }
   1753 }
   1754 
   1755 static inline void
   1756 dev_dma_desc_clear(bkn_switch_info_t *sinfo, int chan)
   1757 {
   1758     if (DEV_IS_CMICX(sinfo)) {
   1759         xgsx_dma_desc_clear(sinfo, chan);
   1760     } else if (DEV_IS_CMICM(sinfo)) {
   1761         xgsm_dma_desc_clear(sinfo, chan);
   1762     } else {
   1763         xgs_dma_desc_clear(sinfo, chan);
   1764     }
   1765 }
   1766 
   1767 static int
   1768 dev_dma_chan_clear(bkn_switch_info_t *sinfo, int chan)
   1769 {
   1770     if (DEV_IS_CMICX(sinfo)) {
   1771         return xgsx_dma_chan_clear(sinfo, chan);
   1772     } else if (DEV_IS_CMICM(sinfo)) {
   1773         return xgsm_dma_chan_clear(sinfo, chan);
   1774     } else {
   1775         return xgs_dma_chan_clear(sinfo, chan);
   1776     }
   1777 }
   1778 
   1779 static void
   1780 dev_cdma_halt_set(bkn_switch_info_t *sinfo, int chan)
   1781 {
   1782     if (DEV_IS_CMICX(sinfo)) {
   1783         xgsx_cdma_halt_set(sinfo, chan);
   1784     } else if (DEV_IS_CMICM(sinfo)) {
   1785         xgsm_cdma_halt_set(sinfo, chan);
   1786     }
   1787 }
   1788 
   1789 static int
   1790 dev_dma_chan_init(bkn_switch_info_t *sinfo, int chan, int dir)
   1791 {
   1792     if (DEV_IS_CMICX(sinfo)) {
   1793         return xgsx_dma_chan_init(sinfo, chan, dir);
   1794     } else if (DEV_IS_CMICM(sinfo)) {
   1795         return xgsm_dma_chan_init(sinfo, chan, dir);
   1796     } else {
   1797         return xgs_dma_chan_init(sinfo, chan, dir);
   1798     }
   1799 }
   1800 
   1801 static int
   1802 dev_dma_chan_start(bkn_switch_info_t *sinfo, int chan, uint64_t dcb)
   1803 {
   1804     if (DEV_IS_CMICX(sinfo)) {
   1805         return xgsx_dma_chan_start(sinfo, chan, dcb);
   1806     } else if (DEV_IS_CMICM(sinfo)) {
   1807         return xgsm_dma_chan_start(sinfo, chan, dcb);
   1808     } else {
   1809         return xgs_dma_chan_start(sinfo, chan, dcb);
   1810     }
   1811 }
   1812 
   1813 static int
   1814 dev_dma_chan_abort(bkn_switch_info_t *sinfo, int chan, int polls)
   1815 {
   1816     if (DEV_IS_CMICX(sinfo)) {
   1817         return xgsx_dma_chan_abort(sinfo, chan, polls);
   1818     } else if (DEV_IS_CMICM(sinfo)) {
   1819         return xgsm_dma_chan_abort(sinfo, chan, polls);
   1820     } else {
   1821         return xgs_dma_chan_abort(sinfo, chan, polls);
   1822     }
   1823 }
   1824 
   1825 static inline void
   1826 dev_irq_mask_set(bkn_switch_info_t *sinfo, uint32_t mask)
   1827 {
   1828     if (DEV_IS_CMICX(sinfo)) {
   1829         xgsx_irq_mask_set(sinfo, mask);
   1830     } else if (DEV_IS_CMICM(sinfo)) {
   1831         xgsm_irq_mask_set(sinfo, mask);
   1832     } else {
   1833         xgs_irq_mask_set(sinfo, mask);
   1834     }
   1835 }
   1836 
   1837 static inline void
   1838 dev_irq_mask_enable(bkn_switch_info_t *sinfo, int chan, int update_hw)
   1839 {
   1840     if (DEV_IS_CMICX(sinfo)) {
   1841         xgsx_irq_mask_enable(sinfo, chan, update_hw);
   1842     } else if (DEV_IS_CMICM(sinfo)) {
   1843         xgsm_irq_mask_enable(sinfo, chan, update_hw);
   1844     } else {
   1845         xgs_irq_mask_enable(sinfo, chan, update_hw);
   1846     }
   1847 }
   1848 
   1849 static void
   1850 dev_irq_mask_disable(bkn_switch_info_t *sinfo, int chan, int update_hw)
   1851 {
   1852     if (DEV_IS_CMICX(sinfo)) {
   1853         xgsx_irq_mask_disable(sinfo, chan, update_hw);
   1854     } else if (DEV_IS_CMICM(sinfo)) {
   1855         xgsm_irq_mask_disable(sinfo, chan, update_hw);
   1856     } else {
   1857         xgs_irq_mask_disable(sinfo, chan, update_hw);
   1858     }
   1859 }
   1860 
   1861 static int
   1862 bkn_alloc_dcbs(bkn_switch_info_t *sinfo)
   1863 {
   1864     int dcb_size;
   1865     int tx_ring_size, rx_ring_size;
   1866     dma_addr_t dcb_dma = 0;
   1867 
   1868     dcb_size = sinfo->dcb_wsize * sizeof(uint32_t);
   1869     tx_ring_size = dcb_size * (MAX_TX_DCBS + 1);
   1870     rx_ring_size = dcb_size * (MAX_RX_DCBS + 1);
   1871     sinfo->dcb_mem_size = tx_ring_size + rx_ring_size * sinfo->rx_chans;
   1872 
   1873     sinfo->dcb_mem = DMA_ALLOC_COHERENT(sinfo->dma_dev,
   1874                                         sinfo->dcb_mem_size,
   1875                                         &dcb_dma);
   1876     if (sinfo->dcb_mem == NULL) {
   1877         gprintk("DCB memory allocation (%d bytes) failed.\n",
   1878                 sinfo->dcb_mem_size);
   1879         return -ENOMEM;
   1880     }
   1881     sinfo->dcb_dma = (uint64_t)dcb_dma;
   1882 
   1883     return 0;
   1884 }
   1885 
   1886 static void
   1887 bkn_free_dcbs(bkn_switch_info_t *sinfo)
   1888 {
   1889     if (sinfo->dcb_mem != NULL) {
   1890         DMA_FREE_COHERENT(sinfo->dma_dev, sinfo->dcb_mem_size,
   1891                           sinfo->dcb_mem, (dma_addr_t)sinfo->dcb_dma);
   1892         sinfo->dcb_mem = NULL;
   1893     }
   1894 }
   1895 
   1896 static void
   1897 bkn_clean_tx_dcbs(bkn_switch_info_t *sinfo)
   1898 {
   1899     bkn_desc_info_t *desc;
   1900 
   1901     DBG_DCB_TX(("Cleaning Tx DCBs (%d %d).\n",
   1902                 sinfo->tx.cur, sinfo->tx.dirty));
   1903     while (sinfo->tx.free < MAX_TX_DCBS) {
   1904         desc = &sinfo->tx.desc[sinfo->tx.dirty];
   1905         if (desc->skb != NULL) {
   1906             DBG_SKB(("Cleaning Tx SKB from DCB %d.\n",
   1907                      sinfo->tx.dirty));
   1908             DMA_UNMAP_SINGLE(sinfo->dma_dev,
   1909                              desc->skb_dma, desc->dma_size,
   1910                              DMA_TODEV);
   1911             desc->skb_dma = 0;
   1912             dev_kfree_skb_any(desc->skb);
   1913             desc->skb = NULL;
   1914         }
   1915         if (++sinfo->tx.dirty >= MAX_TX_DCBS) {
   1916             sinfo->tx.dirty = 0;
   1917         }
   1918         sinfo->tx.free++;
   1919     }
   1920     sinfo->tx.api_active = 0;
   1921     DBG_DCB_TX(("Cleaned Tx DCBs (%d %d).\n",
   1922                 sinfo->tx.cur, sinfo->tx.dirty));
   1923 }
   1924 
   1925 static void
   1926 bkn_clean_rx_dcbs(bkn_switch_info_t *sinfo, int chan)
   1927 {
   1928     bkn_desc_info_t *desc;
   1929 
   1930     DBG_DCB_RX(("Cleaning Rx%d DCBs (%d %d).\n",
   1931                 chan, sinfo->rx[chan].cur, sinfo->rx[chan].dirty));
   1932     while (sinfo->rx[chan].free) {
   1933         desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty];
   1934         if (desc->skb != NULL) {
   1935             DBG_SKB(("Cleaning Rx%d SKB from DCB %d.\n",
   1936                      chan, sinfo->rx[chan].dirty));
   1937             DMA_UNMAP_SINGLE(sinfo->dma_dev,
   1938                              desc->skb_dma, desc->dma_size,
   1939                              DMA_FROMDEV);
   1940             desc->skb_dma = 0;
   1941             dev_kfree_skb_any(desc->skb);
   1942             desc->skb = NULL;
   1943         }
   1944         if (++sinfo->rx[chan].dirty >= MAX_RX_DCBS) {
   1945             sinfo->rx[chan].dirty = 0;
   1946         }
   1947         sinfo->rx[chan].free--;
   1948     }
   1949     sinfo->rx[chan].running = 0;
   1950     sinfo->rx[chan].api_active = 0;
   1951     DBG_DCB_RX(("Cleaned Rx%d DCBs (%d %d).\n",
   1952                 chan, sinfo->rx[chan].cur, sinfo->rx[chan].dirty));
   1953 }
   1954 
   1955 static void
   1956 bkn_clean_dcbs(bkn_switch_info_t *sinfo)
   1957 {
   1958     int chan;
   1959 
   1960     bkn_clean_tx_dcbs(sinfo);
   1961 
   1962     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   1963         bkn_clean_rx_dcbs(sinfo, chan);
   1964     }
   1965 }
   1966 
   1967 static void
   1968 bkn_init_dcbs(bkn_switch_info_t *sinfo)
   1969 {
   1970     int dcb_size;
   1971     uint32_t *dcb_mem;
   1972     uint64_t dcb_dma;
   1973     bkn_desc_info_t *desc;
   1974     int idx;
   1975     int chan;
   1976 
   1977     memset(sinfo->dcb_mem, 0, sinfo->dcb_mem_size);
   1978 
   1979     dcb_size = sinfo->dcb_wsize * sizeof(uint32_t);
   1980     dcb_mem = sinfo->dcb_mem;
   1981     dcb_dma = sinfo->dcb_dma;
   1982 
   1983     for (idx = 0; idx < (MAX_TX_DCBS + 1); idx++) {
   1984         if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) {
   1985             if (sinfo->cmic_type == 'x') {
   1986                 dcb_mem[2] |= 1 << 24 | 1 << 16;
   1987             } else {
   1988                 dcb_mem[1] |= 1 << 24 | 1 << 16;
   1989             }
   1990             if (idx == MAX_TX_DCBS) {
   1991                 if (sinfo->cmic_type == 'x') {
   1992                     dcb_mem[0] = sinfo->tx.desc[0].dcb_dma;
   1993                     dcb_mem[1] = DMA_TO_BUS_HI(sinfo->tx.desc[0].dcb_dma >> 32);
   1994                     dcb_mem[2] |= 1 << 18;
   1995                 } else {
   1996                     dcb_mem[0] = sinfo->tx.desc[0].dcb_dma;
   1997                     dcb_mem[1] |= 1 << 18;
   1998                 }
   1999             }
   2000         }
   2001         desc = &sinfo->tx.desc[idx];
   2002         desc->dcb_mem = dcb_mem;
   2003         desc->dcb_dma = dcb_dma;
   2004         dcb_mem += sinfo->dcb_wsize;
   2005         dcb_dma += dcb_size;
   2006     }
   2007     sinfo->halt_addr[XGS_DMA_TX_CHAN] = sinfo->tx.desc[0].dcb_dma;
   2008     sinfo->tx.free = MAX_TX_DCBS;
   2009     sinfo->tx.cur = 0;
   2010     sinfo->tx.dirty = 0;
   2011 
   2012     DBG_DCB_TX(("Tx DCBs @ 0x%08x.\n",
   2013                 (uint32_t)sinfo->tx.desc[0].dcb_dma));
   2014 
   2015     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   2016         for (idx = 0; idx < (MAX_RX_DCBS + 1); idx++) {
   2017             if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   2018                 if (sinfo->cmic_type == 'x') {
   2019                     dcb_mem[2] |= 1 << 24 | 1 << 16;
   2020                 } else {
   2021                     dcb_mem[1] |= 1 << 24 | 1 << 16;
   2022                 }
   2023                 if (idx == MAX_RX_DCBS) {
   2024                     if (sinfo->cmic_type == 'x') {
   2025                         dcb_mem[0] = sinfo->rx[chan].desc[0].dcb_dma;
   2026                         dcb_mem[1] = DMA_TO_BUS_HI(sinfo->rx[chan].desc[0].dcb_dma >> 32);
   2027                         dcb_mem[2] |= 1 << 18;
   2028                     } else {
   2029                         dcb_mem[0] = sinfo->rx[chan].desc[0].dcb_dma;
   2030                         dcb_mem[1] |= 1 << 18;
   2031                     }
   2032                 }
   2033             }
   2034             desc = &sinfo->rx[chan].desc[idx];
   2035             desc->dcb_mem = dcb_mem;
   2036             desc->dcb_dma = dcb_dma;
   2037             dcb_mem += sinfo->dcb_wsize;
   2038             dcb_dma += dcb_size;
   2039         }
   2040         sinfo->halt_addr[XGS_DMA_RX_CHAN + chan] = sinfo->rx[chan].desc[MAX_RX_DCBS].dcb_dma;
   2041         sinfo->rx[chan].free = 0;
   2042         sinfo->rx[chan].cur = 0;
   2043         sinfo->rx[chan].dirty = 0;
   2044 
   2045         DBG_DCB_RX(("Rx%d DCBs @ 0x%08x.\n",
   2046                     chan, (uint32_t)sinfo->rx[chan].desc[0].dcb_dma));
   2047     }
   2048 }
   2049 
   2050 static void
   2051 bkn_dump_dcb(char *prefix, uint32_t *dcb, int wsize, int txrx)
   2052 {
   2053     if (XGS_DMA_TX_CHAN == txrx) {
   2054         if (wsize > 4) {
   2055             DBG_DCB_TX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x ... 0x%08x\n",
   2056                         prefix, dcb[0], dcb[1], dcb[2], dcb[3], dcb[4], dcb[5],
   2057                         dcb[wsize - 1]));
   2058         } else {
   2059             DBG_DCB_TX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x\n",
   2060                         prefix, dcb[0], dcb[1], dcb[2], dcb[3]));
   2061         }
   2062     } else {
   2063         if (wsize > 4) {
   2064             DBG_DCB_RX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x ... 0x%08x\n",
   2065                         prefix, dcb[0], dcb[1], dcb[2], dcb[3], dcb[4], dcb[5],
   2066                         dcb[wsize - 1]));
   2067         } else {
   2068             DBG_DCB_RX(("%s: 0x%08x 0x%08x 0x%08x 0x%08x\n",
   2069                         prefix, dcb[0], dcb[1], dcb[2], dcb[3]));
   2070         }
   2071     }
   2072 }
   2073 
   2074 static void
   2075 bkn_dump_pkt(uint8_t *data, int size, int txrx)
   2076 {
   2077     int idx;
   2078     char str[128];
   2079 
   2080     if (!(debug & DBG_LVL_PDMP) &&
   2081         !(txrx == XGS_DMA_TX_CHAN && debug & DBG_LVL_PDMP_TX) &&
   2082         !(txrx == XGS_DMA_RX_CHAN && debug & DBG_LVL_PDMP_RX)) {
   2083         return;
   2084     }
   2085 
   2086     for (idx = 0; idx < size; idx++) {
   2087         if ((idx & 0xf) == 0) {
   2088             sprintf(str, "%04x: ", idx);
   2089         }
   2090         if ((idx & 0xf) == 8) {
   2091             sprintf(&str[strlen(str)], "- ");
   2092         }
   2093         sprintf(&str[strlen(str)], "%02x ", data[idx]);
   2094         if ((idx & 0xf) == 0xf) {
   2095             sprintf(&str[strlen(str)], "\n");
   2096             gprintk(str);
   2097         }
   2098     }
   2099     if ((idx & 0xf) != 0) {
   2100         sprintf(&str[strlen(str)], "\n");
   2101         gprintk(str);
   2102     }
   2103 }
   2104 
   2105 static bkn_switch_info_t *
   2106 bkn_sinfo_from_unit(int unit)
   2107 {
   2108     struct list_head *list;
   2109     bkn_switch_info_t *sinfo;
   2110 
   2111     list_for_each(list, &_sinfo_list) {
   2112         sinfo = (bkn_switch_info_t *)list;
   2113         if (sinfo->dev_no == unit || unit == -1) {
   2114             return sinfo;
   2115         }
   2116     }
   2117     return NULL;
   2118 }
   2119 
   2120 static void
   2121 bkn_cdma_goto(bkn_switch_info_t *sinfo, int chan, uint64_t dcb)
   2122 {
   2123     if (sinfo->basedev_suspended) {
   2124         return;
   2125     }
   2126 
   2127     /* Set the new halt location */
   2128     sinfo->halt_addr[chan] = dcb;
   2129     dev_cdma_halt_set(sinfo, chan);
   2130 }
   2131 
   2132 static void
   2133 bkn_api_rx_restart(bkn_switch_info_t *sinfo, int chan)
   2134 {
   2135     bkn_dcb_chain_t *dcb_chain;
   2136     int start_dma;
   2137 
   2138     if (sinfo->basedev_suspended) {
   2139         return;
   2140     }
   2141 
   2142     /* If resume from basedev suspended, there could be a suspended chain */
   2143     if (sinfo->rx[chan].api_dcb_chain) {
   2144         return;
   2145     }
   2146 
   2147     /* Assume that driver lock is held */
   2148     if (!list_empty(&sinfo->rx[chan].api_dcb_list)) {
   2149         dcb_chain = list_entry(sinfo->rx[chan].api_dcb_list.next,
   2150                                bkn_dcb_chain_t, list);
   2151         start_dma = 0;
   2152         if (sinfo->rx[chan].use_rx_skb == 0) {
   2153             sinfo->rx[chan].chain_complete = 0;
   2154             start_dma = 1;
   2155             if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) &&
   2156                 sinfo->rx[chan].api_active) {
   2157                 /* HW is running already, so we just move to the next chain */
   2158                 start_dma = 0;
   2159             }
   2160         }
   2161         sinfo->rx[chan].api_dcb_chain = dcb_chain;
   2162         sinfo->rx[chan].api_active = 1;
   2163         if (start_dma) {
   2164             DBG_DCB_RX(("Start API Rx DMA, first DCB @ 0x%08x (%d DCBs).\n",
   2165                         (uint32_t)dcb_chain->dcb_dma, dcb_chain->dcb_cnt));
   2166             dev_dma_chan_clear(sinfo, XGS_DMA_RX_CHAN + chan);
   2167             dev_irq_mask_enable(sinfo, XGS_DMA_RX_CHAN + chan, 1);
   2168             dev_dma_chan_start(sinfo, XGS_DMA_RX_CHAN + chan, dcb_chain->dcb_dma);
   2169         }
   2170 
   2171         list_del(&dcb_chain->list);
   2172     }
   2173 }
   2174 
   2175 static void
   2176 bkn_api_rx_chain_done(bkn_switch_info_t *sinfo, int chan)
   2177 {
   2178     DBG_DCB_RX(("API Rx DMA chain done\n"));
   2179 
   2180     if (!CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   2181         sinfo->rx[chan].api_active = 0;
   2182     }
   2183     if (sinfo->rx[chan].api_dcb_chain) {
   2184         kfree(sinfo->rx[chan].api_dcb_chain);
   2185         sinfo->rx[chan].api_dcb_chain = NULL;
   2186     }
   2187     bkn_api_rx_restart(sinfo, chan);
   2188 }
   2189 
   2190 static int
   2191 bkn_api_rx_copy_from_skb(bkn_switch_info_t *sinfo,
   2192                          int chan, bkn_desc_info_t *desc)
   2193 {
   2194     bkn_dcb_chain_t *dcb_chain;
   2195     uint32_t *dcb;
   2196     uint32_t dcb_stat;
   2197     uint8_t *pkt;
   2198     uint64_t pkt_dma;
   2199     int pktlen;
   2200     int i;
   2201     bkn_evt_resource_t *evt;
   2202 
   2203     dcb_stat = desc->dcb_mem[sinfo->dcb_wsize-1];
   2204     pktlen = dcb_stat & SOC_DCB_KNET_COUNT_MASK;
   2205 
   2206     dcb_chain = sinfo->rx[chan].api_dcb_chain;
   2207     if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && dcb_chain == NULL) {
   2208         /* Last chain done, try to get a new one */
   2209         bkn_api_rx_chain_done(sinfo, chan);
   2210         dcb_chain = sinfo->rx[chan].api_dcb_chain;
   2211     }
   2212     if (dcb_chain == NULL) {
   2213         DBG_WARN(("No Rx API buffers\n"));
   2214         sinfo->rx[chan].pkts_d_no_api_buf++;
   2215         return -1;
   2216     }
   2217     dcb = &dcb_chain->dcb_mem[dcb_chain->dcb_cur * sinfo->dcb_wsize];
   2218     if ((sinfo->cmic_type == 'x' && (dcb[2] & 0xffff) < pktlen) ||
   2219         (sinfo->cmic_type != 'x' && (dcb[1] & 0xffff) < pktlen)) {
   2220         DBG_WARN(("Rx API buffer too small\n"));
   2221         return -1;
   2222     }
   2223     if (sinfo->cmic_type == 'x') {
   2224         pkt_dma = BUS_TO_DMA_HI(dcb[1]);
   2225         pkt_dma = pkt_dma << 32 | dcb[0];
   2226     } else {
   2227         pkt_dma = dcb[0];
   2228     }
   2229     pkt = (uint8_t *)kernel_bde->p2l(sinfo->dev_no, (sal_paddr_t)pkt_dma);
   2230     if (pkt == NULL) {
   2231         DBG_WARN(("Invalid Rx API buffer\n"));
   2232         return -1;
   2233     }
   2234 
   2235     /* Copy packet data */
   2236     memcpy(pkt, desc->skb->data, pktlen);
   2237 
   2238     /* Copy packet metadata and mark as done */
   2239     if (sinfo->cmic_type != 'x') {
   2240         for (i = SOC_DCB_META_OFFSET; i < sinfo->dcb_wsize; i++) {
   2241             dcb[i] = desc->dcb_mem[i];
   2242         }
   2243     }
   2244     dcb[sinfo->dcb_wsize-1] = dcb_stat | SOC_DCB_KNET_DONE;
   2245     MEMORY_BARRIER;
   2246 
   2247     dcb_chain->dcb_cur++;
   2248 
   2249     if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   2250         dcb = &dcb_chain->dcb_mem[dcb_chain->dcb_cur * sinfo->dcb_wsize];
   2251         if ((sinfo->cmic_type == 'x' && dcb[2] & (1 << 18)) ||
   2252             (sinfo->cmic_type != 'x' && dcb[1] & (1 << 18))) {
   2253             /* Get the next chain if reload done */
   2254             dcb[sinfo->dcb_wsize-1] |= 1 << 31 | SOC_DCB_KNET_DONE;
   2255             MEMORY_BARRIER;
   2256             bkn_api_rx_chain_done(sinfo, chan);
   2257             dcb_chain = sinfo->rx[chan].api_dcb_chain;
   2258             if (dcb_chain == NULL) {
   2259                 sinfo->rx[chan].api_dcb_chain_end = NULL;
   2260             }
   2261         }
   2262     } else {
   2263         if ((sinfo->cmic_type == 'x' && (dcb[2] & (1 << 16)) == 0) ||
   2264             (sinfo->cmic_type != 'x' && (dcb[1] & (1 << 16)) == 0)) {
   2265             bkn_api_rx_chain_done(sinfo, chan);
   2266         }
   2267     }
   2268 
   2269     sinfo->dma_events |= KCOM_DMA_INFO_F_RX_DONE;
   2270 
   2271     evt = &_bkn_evt[sinfo->evt_idx];
   2272     evt->evt_wq_put++;
   2273     wake_up_interruptible(&evt->evt_wq);
   2274 
   2275     return 0;
   2276 }
   2277 
   2278 static void
   2279 bkn_rx_refill(bkn_switch_info_t *sinfo, int chan)
   2280 {
   2281     struct sk_buff *skb;
   2282     bkn_desc_info_t *desc;
   2283     uint32_t *dcb;
   2284     uint32_t resv_size = sinfo->cmic_type == 'x' ? RCPU_HDR_SIZE : RCPU_RX_ENCAP_SIZE;
   2285     uint32_t meta_size = sinfo->cmic_type == 'x' ? RCPU_RX_META_SIZE : 0;
   2286     int prev;
   2287 
   2288     if (sinfo->rx[chan].use_rx_skb == 0) {
   2289         /* Rx buffers are provided by BCM Rx API */
   2290         return;
   2291     }
   2292 
   2293     if (!CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) &&
   2294         sinfo->rx[chan].tokens < MAX_RX_DCBS) {
   2295         /* Pause DMA for now */
   2296         return;
   2297     }
   2298 
   2299     while (sinfo->rx[chan].free < MAX_RX_DCBS) {
   2300         desc = &sinfo->rx[chan].desc[sinfo->rx[chan].cur];
   2301         if (desc->skb == NULL) {
   2302             skb = dev_alloc_skb(rx_buffer_size + RCPU_RX_ENCAP_SIZE);
   2303             if (skb == NULL) {
   2304                 break;
   2305             }
   2306             skb_reserve(skb, resv_size);
   2307             desc->skb = skb;
   2308         } else {
   2309             DBG_DCB_RX(("Refill Rx%d SKB in DCB %d recycled.\n",
   2310                         chan, sinfo->rx[chan].cur));
   2311         }
   2312         skb = desc->skb;
   2313         desc->dma_size = rx_buffer_size + meta_size;
   2314 #ifdef KNET_NO_AXI_DMA_INVAL
   2315         /*
   2316          * FIXME: Need to retain this code until iProc customers have been
   2317          * migrated to updated u-boot. Old u-boot versions are unable to load
   2318          * the kernel into non-ACP memory.
   2319          */
   2320         /*
   2321          * Cache invalidate may corrupt DMA memory on some iProc-based devices
   2322          * if the kernel is mapped to ACP memory.
   2323          */
   2324         if (sinfo->pdev == NULL) {
   2325             desc->dma_size = 0;
   2326         }
   2327 #endif
   2328         desc->skb_dma = DMA_MAP_SINGLE(sinfo->dma_dev,
   2329                                        skb->data, desc->dma_size,
   2330                                        DMA_FROMDEV);
   2331         if (DMA_MAPPING_ERROR(sinfo->dma_dev, desc->skb_dma)) {
   2332             dev_kfree_skb_any(skb);
   2333             desc->skb = NULL;
   2334             break;
   2335         }
   2336         DBG_DCB_RX(("Refill Rx%d DCB %d (0x%08x).\n",
   2337                     chan, sinfo->rx[chan].cur, (uint32_t)desc->skb_dma));
   2338         dcb = desc->dcb_mem;
   2339         dcb[0] = desc->skb_dma;
   2340         if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   2341             if (sinfo->cmic_type == 'x') {
   2342                 dcb[2] |= 1 << 24 | 1 << 16;
   2343             } else {
   2344                 dcb[1] |= 1 << 24 | 1 << 16;
   2345             }
   2346         } else {
   2347             prev = PREV_IDX(sinfo->rx[chan].cur, MAX_RX_DCBS);
   2348             if (prev < (MAX_RX_DCBS - 1)) {
   2349                 if (sinfo->cmic_type == 'x') {
   2350                     sinfo->rx[chan].desc[prev].dcb_mem[2] |= 1 << 16;
   2351                 } else {
   2352                     sinfo->rx[chan].desc[prev].dcb_mem[1] |= 1 << 16;
   2353                 }
   2354             }
   2355         }
   2356         if (sinfo->cmic_type == 'x') {
   2357             dcb[1] = DMA_TO_BUS_HI(desc->skb_dma >> 32);
   2358             dcb[2] |= rx_buffer_size + meta_size;
   2359         } else {
   2360             dcb[1] |= rx_buffer_size;
   2361         }
   2362 
   2363         if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) &&
   2364             sinfo->rx[chan].tokens > MAX_RX_DCBS) {
   2365             /* DMA run to the new halt location */
   2366             bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma);
   2367         }
   2368 
   2369         if (++sinfo->rx[chan].cur >= MAX_RX_DCBS) {
   2370             sinfo->rx[chan].cur = 0;
   2371         }
   2372         sinfo->rx[chan].free++;
   2373         sinfo->rx[chan].tokens--;
   2374     }
   2375 }
   2376 
   2377 static int
   2378 bkn_rx_restart(bkn_switch_info_t *sinfo, int chan)
   2379 {
   2380     bkn_desc_info_t *desc;
   2381 
   2382     if (sinfo->basedev_suspended) {
   2383         return 0;
   2384     }
   2385 
   2386     if (sinfo->rx[chan].running) {
   2387         return 0;
   2388     }
   2389 
   2390     if (sinfo->rx[chan].free < MAX_RX_DCBS) {
   2391         return 1;
   2392     }
   2393 
   2394     desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty];
   2395     sinfo->rx[chan].chain_complete = 0;
   2396     DBG_DCB_RX(("Restart Rx%d DMA, DCB @ 0x%08x (%d).\n",
   2397                 chan, (uint32_t)desc->dcb_dma, sinfo->rx[chan].dirty));
   2398     dev_dma_chan_clear(sinfo, XGS_DMA_RX_CHAN + chan);
   2399     dev_irq_mask_enable(sinfo, XGS_DMA_RX_CHAN + chan, 1);
   2400     dev_dma_chan_start(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma);
   2401     sinfo->rx[chan].running = 1;
   2402 
   2403     /* Request one extra poll if chain was restarted during poll */
   2404     if (sinfo->napi_poll_mode) {
   2405         sinfo->napi_poll_again = 1;
   2406     }
   2407 
   2408     return 0;
   2409 }
   2410 
   2411 static int
   2412 bkn_tx_dma_start(bkn_switch_info_t *sinfo)
   2413 {
   2414     bkn_desc_info_t *desc;
   2415 
   2416     desc = &sinfo->tx.desc[sinfo->tx.cur];
   2417     if (sinfo->tx.free == MAX_TX_DCBS) {
   2418         if (!sinfo->tx.api_active) {
   2419             DBG_DCB_TX(("Start Tx DMA, DCB @ 0x%08x (%d).\n",
   2420                         (uint32_t)desc->dcb_dma, sinfo->tx.cur));
   2421             dev_dma_chan_clear(sinfo, XGS_DMA_TX_CHAN);
   2422             dev_irq_mask_enable(sinfo, XGS_DMA_TX_CHAN, 1);
   2423             dev_dma_chan_start(sinfo, XGS_DMA_TX_CHAN, desc->dcb_dma);
   2424         }
   2425     }
   2426 
   2427     return 0;
   2428 }
   2429 
   2430 static int
   2431 bkn_dma_init(bkn_switch_info_t *sinfo)
   2432 {
   2433     int chan;
   2434 
   2435     dev_dma_chan_init(sinfo, XGS_DMA_TX_CHAN, 1);
   2436     if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) {
   2437         bkn_tx_dma_start(sinfo);
   2438     }
   2439 
   2440     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   2441         dev_dma_chan_init(sinfo, XGS_DMA_RX_CHAN + chan, 0);
   2442         bkn_rx_refill(sinfo, chan);
   2443         bkn_rx_restart(sinfo, chan);
   2444     }
   2445 
   2446     return 0;
   2447 }
   2448 
   2449 static int
   2450 bkn_dma_abort_tx(bkn_switch_info_t *sinfo)
   2451 {
   2452     bkn_dcb_chain_t *dcb_chain;
   2453 
   2454     DBG_VERB(("Aborting Tx DMA.\n"));
   2455 
   2456     dev_irq_mask_disable(sinfo, XGS_DMA_TX_CHAN, 1);
   2457 
   2458     dev_dma_chan_abort(sinfo, XGS_DMA_TX_CHAN, 10000);
   2459 
   2460     if (sinfo->tx.api_dcb_chain) {
   2461         DBG_DCB_TX(("Freeing active Tx DCB chain.\n"));
   2462         kfree(sinfo->tx.api_dcb_chain);
   2463         sinfo->tx.api_dcb_chain = NULL;
   2464     }
   2465     while (!list_empty(&sinfo->tx.api_dcb_list)) {
   2466         dcb_chain = list_entry(sinfo->tx.api_dcb_list.next,
   2467                                bkn_dcb_chain_t, list);
   2468         list_del(&dcb_chain->list);
   2469         DBG_DCB_TX(("Freeing Tx DCB chain.\n"));
   2470         kfree(dcb_chain);
   2471     }
   2472     sinfo->tx.api_dcb_chain_end = NULL;
   2473 
   2474     return 0;
   2475 }
   2476 
   2477 static int
   2478 bkn_dma_abort_rx(bkn_switch_info_t *sinfo, int chan)
   2479 {
   2480     bkn_dcb_chain_t *dcb_chain;
   2481 
   2482     DBG_VERB(("Aborting Rx%d DMA.\n", chan));
   2483 
   2484     dev_irq_mask_disable(sinfo, XGS_DMA_RX_CHAN + chan, 1);
   2485 
   2486     dev_dma_chan_abort(sinfo, XGS_DMA_RX_CHAN + chan, 10000);
   2487 
   2488     if (sinfo->rx[chan].api_dcb_chain) {
   2489         DBG_DCB_RX(("Freeing active Rx%d DCB chain.\n", chan));
   2490         kfree(sinfo->rx[chan].api_dcb_chain);
   2491         sinfo->rx[chan].api_dcb_chain = NULL;
   2492     }
   2493     while (!list_empty(&sinfo->rx[chan].api_dcb_list)) {
   2494         dcb_chain = list_entry(sinfo->rx[chan].api_dcb_list.next,
   2495                                bkn_dcb_chain_t, list);
   2496         list_del(&dcb_chain->list);
   2497         DBG_DCB_RX(("Freeing Rx%d DCB chain.\n", chan));
   2498         kfree(dcb_chain);
   2499     }
   2500     sinfo->rx[chan].api_dcb_chain_end = NULL;
   2501 
   2502     return 0;
   2503 }
   2504 
   2505 static int
   2506 bkn_dma_abort(bkn_switch_info_t *sinfo)
   2507 {
   2508     int chan;
   2509 
   2510     bkn_dma_abort_tx(sinfo);
   2511 
   2512     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   2513         bkn_dma_abort_rx(sinfo, chan);
   2514     }
   2515 
   2516     return 0;
   2517 }
   2518 
   2519 static int
   2520 device_is_dpp(bkn_switch_info_t *sinfo)
   2521 {
   2522     int is_dpp = 0;
   2523 
   2524     is_dpp = (sinfo->dcb_type == 28) ? 1 : 0;
   2525     return is_dpp;
   2526 }
   2527 
   2528 static int
   2529 device_is_dnx(bkn_switch_info_t *sinfo)
   2530 {
   2531     int is_dnx = 0;
   2532 
   2533     /* No EP_TO_CPU header for DNX(JR2) */
   2534     is_dnx = ((sinfo->cmic_type == 'x') && (sinfo->pkt_hdr_size ==0)) ? 1 : 0;
   2535     return is_dnx;
   2536 }
   2537 
   2538 /* is DPP or is DNX*/
   2539 static int
   2540 device_is_sand(bkn_switch_info_t *sinfo)
   2541 {
   2542     int is_sand = 0;
   2543 
   2544     if (device_is_dpp(sinfo) || device_is_dnx(sinfo)) {
   2545         is_sand = 1;
   2546     }
   2547     return is_sand;
   2548 }
   2549 
   2550 static bkn_filter_t *
   2551 bkn_match_rx_pkt(bkn_switch_info_t *sinfo, uint8_t *pkt, int pktlen,
   2552                  void *meta, int chan, bkn_filter_t *cbf)
   2553 {
   2554     struct list_head *list;
   2555     bkn_filter_t *filter;
   2556     kcom_filter_t scratch, *kf;
   2557     uint8_t *oob = (uint8_t *)meta;
   2558     int size, wsize;
   2559     int idx, match;
   2560 
   2561     list_for_each(list, &sinfo->rxpf_list) {
   2562         filter = (bkn_filter_t *)list;
   2563         kf = &filter->kf;
   2564         memcpy(&scratch.data.b[0],
   2565                &oob[kf->oob_data_offset], kf->oob_data_size);
   2566         memcpy(&scratch.data.b[kf->oob_data_size],
   2567                &pkt[kf->pkt_data_offset], kf->pkt_data_size);
   2568         size = kf->oob_data_size + kf->pkt_data_size;
   2569         wsize = BYTES2WORDS(size);
   2570         DBG_VERB(("Filter: size = %d (%d), data = 0x%08x, mask = 0x%08x\n",
   2571                   size, wsize, kf->data.w[0], kf->mask.w[0]));
   2572 
   2573         if (device_is_dnx(sinfo)) {
   2574             DBG_DUNE(("Filter: size = %d (wsize %d)\n", size, wsize));
   2575             for (idx = 0; idx < wsize; idx++)
   2576             {
   2577                 DBG_DUNE(("OOB[%d]: 0x%08x [0x%08x]\n", idx, kf->data.w[idx], kf->mask.w[idx]));
   2578             }
   2579             DBG_DUNE(("Meta Data [+ Selected Raw packet data]\n"));
   2580             for (idx = 0; idx < wsize; idx++)
   2581             {
   2582                 DBG_DUNE(("Scratch[%d]: 0x%08x\n", idx, scratch.data.w[idx]));
   2583             }
   2584         }
   2585 
   2586         match = 1;
   2587         if (match) {
   2588             if (device_is_sand(sinfo))
   2589             {
   2590                 /** priority 0 means no priority check */
   2591                 if (kf->priority && (kf->priority < (num_rx_prio * sinfo->rx_chans))) {
   2592                     if (kf->priority < (num_rx_prio * chan) ||
   2593                         kf->priority >= (num_rx_prio * (chan + 1))) {
   2594                         match = 0;
   2595                     }
   2596                 }
   2597             }
   2598             else {
   2599                 if (kf->priority < (num_rx_prio * sinfo->rx_chans)) {
   2600                     if (kf->priority < (num_rx_prio * chan) ||
   2601                         kf->priority >= (num_rx_prio * (chan + 1))) {
   2602                         match = 0;
   2603                     }
   2604                 }
   2605             }
   2606         }
   2607         if (match) {
   2608             for (idx = 0; idx < wsize; idx++) {
   2609                 scratch.data.w[idx] &= kf->mask.w[idx];
   2610                 if (scratch.data.w[idx] != kf->data.w[idx]) {
   2611                     match = 0;
   2612                     break;
   2613                 }
   2614             }
   2615         }
   2616         if (match) {
   2617             if (kf->dest_type == KCOM_DEST_T_CB) {
   2618                 /* Check for custom filters */
   2619                 if (knet_filter_cb != NULL && cbf != NULL) {
   2620                     memset(cbf, 0, sizeof(*cbf));
   2621                     memcpy(&cbf->kf, kf, sizeof(cbf->kf));
   2622                     if (knet_filter_cb(pkt, pktlen, sinfo->dev_no,
   2623                                        meta, chan, &cbf->kf)) {
   2624                         filter->hits++;
   2625                         return cbf;
   2626                     }
   2627                 } else {
   2628                     DBG_FLTR(("Match, but not filter callback\n"));
   2629                 }
   2630             } else {
   2631                 filter->hits++;
   2632                 return filter;
   2633             }
   2634         }
   2635     }
   2636 
   2637     return NULL;
   2638 }
   2639 
   2640 static bkn_priv_t *
   2641 bkn_netif_lookup(bkn_switch_info_t *sinfo, int id)
   2642 {
   2643     struct list_head *list;
   2644     bkn_priv_t *priv;
   2645     int found;
   2646 
   2647     /* Fast path */
   2648     if (id < sinfo->ndev_max) {
   2649         if (sinfo->ndevs[id] != NULL) {
   2650             DBG_NDEV(("Look up netif ID %d successful\n", id));
   2651             return netdev_priv(sinfo->ndevs[id]);
   2652         }
   2653     }
   2654 
   2655     /* Slow path - should normally not get here */
   2656     found = 0;
   2657     priv = NULL;
   2658     list_for_each(list, &sinfo->ndev_list) {
   2659         priv = (bkn_priv_t *)list;
   2660         if (priv->id == id) {
   2661             found = 1;
   2662             break;
   2663         }
   2664     }
   2665     if (found && priv != NULL) {
   2666         return priv;
   2667     }
   2668     return NULL;
   2669 }
   2670 
   2671 static int
   2672 bkn_hw_tstamp_rx_set(bkn_switch_info_t *sinfo, struct sk_buff *skb, uint32 *meta)
   2673 {
   2674     struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
   2675     uint32_t *md = meta;
   2676     uint64_t ts = 0;
   2677 
   2678     switch (sinfo->dcb_type) {
   2679     case 26:
   2680     case 32:
   2681     case 33:
   2682         ts = md[14];
   2683         ts = ts << 32 | md[12];
   2684         break;
   2685     case 36:
   2686         ts = md[10];
   2687         break;
   2688     case 38:
   2689         ts = md[4] & 0xffff;
   2690         ts = ts << 32 | md[5];
   2691         break;
   2692     default:
   2693         return -1;
   2694     }
   2695 
   2696     if (knet_hw_tstamp_rx_time_upscale_cb) {
   2697         if (knet_hw_tstamp_rx_time_upscale_cb(sinfo->dev_no, &ts) < 0) {
   2698           return -1;
   2699         }
   2700     }
   2701 
   2702     memset(shhwtstamps, 0, sizeof(*shhwtstamps));
   2703     shhwtstamps->hwtstamp = ns_to_ktime(be64_to_cpu(ts));
   2704 
   2705     return 0;
   2706 }
   2707 
   2708 static int
   2709 bkn_add_rcpu_encap(bkn_switch_info_t *sinfo, struct sk_buff *skb, void *meta)
   2710 {
   2711     int pktlen = skb->len;
   2712     uint32_t *dmeta, *smeta, wsize, psize;
   2713     int idx;
   2714 
   2715     /* Add and clear RCPU encapsulation */
   2716     if (sinfo->cmic_type == 'x') {
   2717         psize = RCPU_HDR_SIZE + sinfo->pkt_hdr_size;
   2718         skb_push(skb, psize);
   2719         memset(skb->data, 0, RCPU_HDR_SIZE);
   2720     } else {
   2721         psize = RCPU_RX_ENCAP_SIZE;
   2722         skb_push(skb, psize);
   2723         memset(skb->data, 0, RCPU_RX_ENCAP_SIZE);
   2724     }
   2725 
   2726     /* RCPU Header */
   2727     memcpy(skb->data, &skb->data[psize], 12);
   2728     if (rcpu_dmac != NULL) {
   2729         memcpy(skb->data, bkn_rcpu_dmac, 6);
   2730     }
   2731     if (rcpu_smac != NULL) {
   2732         memcpy(&skb->data[6], bkn_rcpu_smac, 6);
   2733     }
   2734     skb->data[12] = 0x81;
   2735     skb->data[14] = rcpu_vlan >> 8;
   2736     skb->data[15] = rcpu_vlan & 0xff;
   2737     skb->data[16] = rcpu_ethertype >> 8;
   2738     skb->data[17] = rcpu_ethertype & 0xff;
   2739     skb->data[18] = sinfo->rcpu_sig >> 8;
   2740     skb->data[19] = sinfo->rcpu_sig & 0xff;
   2741     skb->data[20] = RCPU_OPCODE_RX;
   2742     skb->data[21] = RCPU_F_MODHDR;
   2743     skb->data[24] = pktlen >> 8;
   2744     skb->data[25] = pktlen & 0xff;
   2745 
   2746     /* Meta data */
   2747     dmeta = (uint32_t *)&skb->data[RCPU_HDR_SIZE];
   2748     smeta = sinfo->cmic_type == 'x' ? (uint32_t *)meta : (uint32_t *)meta + 2;
   2749     wsize = sinfo->cmic_type == 'x' ? sinfo->pkt_hdr_size / 4 : sinfo->dcb_wsize - 3;
   2750     for (idx = 0; idx < wsize; idx++) {
   2751         dmeta[idx] = htonl(smeta[idx]);
   2752     }
   2753 
   2754     return 0;
   2755 }
   2756 
   2757 static void
   2758 bkn_eth_type_update(struct sk_buff *skb, int ethertype)
   2759 {
   2760 #if defined(PM_ETH_TYPE) && defined(PM_FC_TYPE)
   2761     /* Optionally override standard protocol */
   2762     skb->protocol = PM_ETH_TYPE;
   2763     if (ethertype == ETH_P_FCOE) {
   2764         skb->protocol = PM_FC_TYPE;
   2765     }
   2766 #endif
   2767 }
   2768 
   2769 #define BKN_DNX_BIT(x) (1<<(x))
   2770 #define BKN_DNX_RBIT(x) (~(1<<(x)))
   2771 #ifdef __LITTLE_ENDIAN
   2772 #define BKN_DNX_BYTE_SWAP(x) (x)
   2773 #else
   2774 #define BKN_DNX_BYTE_SWAP(x) ((((x) << 24)) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) >> 24)))
   2775 #endif
   2776 
   2777 static int
   2778 packet_is_untagged(uint16_t tpid)
   2779 {
   2780     int is_untagged = 0;
   2781 
   2782     /* Fixme SDK-111398 */
   2783     /* 0x8100 is used in 802.1Q */
   2784     /* 0x8848 is used in 802.11ad, the dtag tpid can be set to anything besides 0x8848, 0x9100 is a typical value, but couldn't cover all scenarios. */
   2785     is_untagged = ((tpid != 0x8100) && (tpid != 0x8848) && (tpid != 0x9100));
   2786     return is_untagged;
   2787 }
   2788 
   2789 static void
   2790 bkn_bitstream_set_field(uint32_t *input_buffer, uint32_t start_bit, uint32_t  nof_bits, uint32_t field)
   2791 {
   2792     uint32_t place;
   2793     uint32_t field_bit_i;
   2794     uint32_t bit_indicator;
   2795 
   2796     if( nof_bits > 32)
   2797     {
   2798         return;
   2799     }
   2800 
   2801     for( place=start_bit, field_bit_i = 0; field_bit_i< nof_bits; ++place, ++field_bit_i)
   2802     {
   2803         bit_indicator = field & BKN_DNX_BIT(nof_bits-field_bit_i-1);
   2804         if(bit_indicator)
   2805         {
   2806             input_buffer[place>>5] |= (0x80000000 >> (place & 0x0000001F));
   2807         }
   2808         else
   2809         {
   2810             input_buffer[place>>5] &= ~(0x80000000 >> (place & 0x0000001F));
   2811         }
   2812     }
   2813     return;
   2814 }
   2815 
   2816 static void
   2817 bkn_bitstream_get_field(uint8_t  *input_buffer, uint32_t start_bit, uint32_t  nof_bits, uint32_t *output_value)
   2818 {
   2819     uint32_t idx;
   2820     uint32_t buf_sizes=0;
   2821     uint32_t tmp_output_value[2]={0};
   2822     uint32_t first_byte_ndx;
   2823     uint32_t last_byte_ndx;
   2824     uint32_t place;
   2825     uint32_t field_bit_i;
   2826     uint8_t *tmp_output_value_u8_ptr = (uint8_t*)&tmp_output_value;
   2827     uint32_t bit_indicator;
   2828 
   2829     if (nof_bits > 32)
   2830     {
   2831          return;
   2832     }
   2833 
   2834     first_byte_ndx = start_bit / 8;
   2835     last_byte_ndx = ((start_bit + nof_bits - 1) / 8);
   2836     *output_value=0;
   2837 
   2838     /* get 32 bit value, MSB */
   2839     for (idx = first_byte_ndx; idx <= last_byte_ndx; ++idx)
   2840     {
   2841         tmp_output_value_u8_ptr[last_byte_ndx - idx] = input_buffer[idx];
   2842         buf_sizes += 8;
   2843     }
   2844     tmp_output_value[0] = BKN_DNX_BYTE_SWAP(tmp_output_value[0]);
   2845     if (last_byte_ndx > 4)
   2846     {
   2847        tmp_output_value[1] = BKN_DNX_BYTE_SWAP(tmp_output_value[1]);
   2848     }
   2849 
   2850     place = buf_sizes - (start_bit % 8 + nof_bits);
   2851     for (field_bit_i = 0; field_bit_i< nof_bits; ++place, ++field_bit_i)
   2852     {
   2853         uint32_t result;
   2854         result = tmp_output_value[place>>5] & BKN_DNX_BIT(place & 0x0000001F);
   2855         if (result)
   2856         {
   2857            bit_indicator = 1;
   2858         } else {
   2859            bit_indicator = 0;
   2860         }
   2861         *output_value |=  bit_indicator << field_bit_i;
   2862     }
   2863     return;
   2864 }
   2865 
   2866 static void
   2867 bkn_dpp_packet_parse_ftmh(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_dune_system_header_info_t *packet_info)
   2868 {
   2869     uint32_t header_ptr = 0;
   2870     uint32_t dsp_ext_exist=0;
   2871     uint32_t fld_val;
   2872 
   2873     header_ptr = packet_info->ntwrk_header_ptr;
   2874 
   2875     /* Packet-size */
   2876     bkn_bitstream_get_field(
   2877             &hdr_buff[header_ptr],
   2878             BKN_DPP_FTMH_PKT_SIZE_MSB,
   2879             BKN_DPP_FTMH_PKT_SIZE_NOF_BITS,
   2880             &fld_val);
   2881     packet_info->ftmh.packet_size = fld_val;
   2882     /* Traffic-class */
   2883     bkn_bitstream_get_field(
   2884             &hdr_buff[header_ptr],
   2885             BKN_DPP_FTMH_TC_MSB,
   2886             BKN_DPP_FTMH_TC_NOF_BITS,
   2887             &fld_val);
   2888     packet_info->ftmh.prio = fld_val;
   2889     /* Source-system-port-aggregate */
   2890     bkn_bitstream_get_field(
   2891             &hdr_buff[header_ptr],
   2892             BKN_DPP_FTMH_SRC_SYS_PORT_MSB,
   2893             BKN_DPP_FTMH_SRC_SYS_PORT_NOF_BITS,
   2894             &fld_val);
   2895     packet_info->ftmh.src_sys_port = fld_val;
   2896     /* TM-action-type */
   2897     bkn_bitstream_get_field(
   2898             &hdr_buff[header_ptr],
   2899             BKN_DPP_FTMH_ACTION_TYPE_MSB,
   2900             BKN_DPP_FTMH_ACTION_TYPE_NOF_BITS,
   2901             &fld_val);
   2902     packet_info->ftmh.action_type = fld_val;
   2903     /* PPH-type */
   2904     bkn_bitstream_get_field(
   2905             &hdr_buff[header_ptr],
   2906             BKN_DPP_FTMH_PPH_TYPE_MSB,
   2907             BKN_DPP_FTMH_PPH_TYPE_NOF_BITS,
   2908             &fld_val);
   2909     packet_info->ftmh.pph_type = fld_val;
   2910 
   2911     packet_info->ntwrk_header_ptr += BKN_DPP_FTMH_SIZE_BYTE;
   2912     DBG_DUNE(("FTMH(%d) Packet-size %d Action-type %d PPH-type %d Source-system-port 0x%x Traffic-class %d\n",
   2913               packet_info->ntwrk_header_ptr, packet_info->ftmh.packet_size, packet_info->ftmh.action_type,
   2914               packet_info->ftmh.pph_type, packet_info->ftmh.src_sys_port, packet_info->ftmh.prio));
   2915 
   2916     /* LB-Key ext */
   2917     if ((sinfo->pkt_hdr_size & BKN_DPP_FTMH_LB_EXT_EN) == BKN_DPP_FTMH_LB_EXT_EN)
   2918     {
   2919         packet_info->ntwrk_header_ptr += BKN_DPP_FTMH_LB_EXT_SIZE_BYTE;
   2920         DBG_DUNE(("FTMH(%d) FTMH LB-Key Extension is present\n", packet_info->ntwrk_header_ptr));
   2921     }
   2922     /* DSP ext*/
   2923     fld_val = 0;
   2924     bkn_bitstream_get_field(
   2925         &hdr_buff[header_ptr],
   2926         BKN_DPP_FTMH_EXT_DSP_EXIST_MSB,
   2927         BKN_DPP_FTMH_EXT_DSP_EXIST_NOF_BITS,
   2928         &dsp_ext_exist);
   2929     if (dsp_ext_exist)
   2930     {
   2931         packet_info->ntwrk_header_ptr += BKN_DPP_FTMH_DEST_EXT_SIZE_BYTE;
   2932         DBG_DUNE(("FTMH(%d) DSP-extension-present 1\n", packet_info->ntwrk_header_ptr));
   2933     }
   2934 
   2935     /* stacking ext */
   2936     if ((sinfo->pkt_hdr_size & BKN_DPP_FTMH_STACKING_EXT_EN) == BKN_DPP_FTMH_STACKING_EXT_EN)
   2937     {
   2938         packet_info->ntwrk_header_ptr += BKN_DPP_FTMH_STACKING_SIZE_BYTE;
   2939         DBG_DUNE(("FTMH(%d) FTMH Stacking Extension is present\n", packet_info->ntwrk_header_ptr));
   2940     }
   2941     return;
   2942 }
   2943 
   2944 static void
   2945 bkn_dpp_packet_parse_internal(bkn_switch_info_t *sinfo, uint8_t hdr_buff[], bkn_dune_system_header_info_t *packet_info)
   2946 {
   2947     uint32_t header_ptr = 0;
   2948     uint32_t fld_val;
   2949     uint32_t eei_extension_present = 0;
   2950     uint32_t learn_extension_present = 0;
   2951     uint32_t fhei_size = 0;
   2952     uint32_t forward_code;
   2953     uint8_t  is_trapped = 0;
   2954 
   2955     header_ptr = packet_info->ntwrk_header_ptr;
   2956 
   2957     bkn_bitstream_get_field(
   2958             &hdr_buff[header_ptr],
   2959             BKN_DPP_PPH_EEI_EXTENSION_PRESENT_MSB,
   2960             BKN_DPP_PPH_EEI_EXTENSION_PRESENT_NOF_BITS,
   2961             &eei_extension_present);
   2962     bkn_bitstream_get_field(
   2963             &hdr_buff[header_ptr],
   2964             BKN_DPP_PPH_LEARN_EXENSION_PRESENT_MSB,
   2965             BKN_DPP_PPH_LEARN_EXENSION_PRESENT_NOF_BITS,
   2966             &learn_extension_present);
   2967     bkn_bitstream_get_field(
   2968             &hdr_buff[header_ptr],
   2969             BKN_DPP_PPH_FHEI_SIZE_MSB,
   2970             BKN_DPP_PPH_FHEI_SIZE_NOF_BITS,
   2971             &fhei_size);
   2972     bkn_bitstream_get_field(
   2973             &hdr_buff[header_ptr],
   2974             BKN_DPP_PPH_FORWARD_CODE_MSB,
   2975             BKN_DPP_PPH_FORWARD_CODE_NOF_BITS,
   2976             &forward_code);
   2977     /* 7: CPU-Trap  */
   2978     is_trapped = (uint8_t)(forward_code == 7);
   2979 
   2980     bkn_bitstream_get_field(
   2981              &hdr_buff[header_ptr],
   2982              BKN_DPP_PPH_VSI_MSB,
   2983              BKN_DPP_PPH_VSI_NOF_BITS,
   2984              &fld_val);
   2985     packet_info->internal.vsi = fld_val;
   2986 
   2987     /* size of PPH base is 7 */
   2988     packet_info->ntwrk_header_ptr += BKN_DPP_PPH_SIZE_BYTE;
   2989     header_ptr = packet_info->ntwrk_header_ptr;
   2990 
   2991     DBG_DUNE(("PPH(%d) Forward-Code %d EEI-Extension %d Learn-Extension %d VSI %d FHEI-size %d\n", packet_info->ntwrk_header_ptr,
   2992         forward_code, eei_extension_present, learn_extension_present, packet_info->internal.vsi, fhei_size));
   2993 
   2994     /* PPH extension */
   2995     if (is_trapped && (fhei_size == 1))
   2996     {
   2997         /* CPU trap code qualifier */
   2998         bkn_bitstream_get_field(
   2999                 &hdr_buff[header_ptr],
   3000                 BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_MSB,
   3001                 BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_QUALIFIER_NOF_BITS,
   3002                 &fld_val);
   3003         packet_info->internal.trap_qualifier = fld_val;
   3004        /* CPU trap code */
   3005         bkn_bitstream_get_field(
   3006           &hdr_buff[header_ptr],
   3007           BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_MSB,
   3008           BKN_DPP_PPH_FHEI_TRAP_SNOOP_3B_CPU_TRAP_CODE_NOF_BITS,
   3009           &fld_val);
   3010         packet_info->internal.trap_id = fld_val;
   3011     }
   3012     switch(fhei_size) {
   3013         case 1:
   3014             packet_info->ntwrk_header_ptr += BKN_DPP_PPH_FHEI_3B_SIZE_BYTE;
   3015             break;
   3016         case 2:
   3017             packet_info->ntwrk_header_ptr += BKN_DPP_PPH_FHEI_5B_SIZE_BYTE;
   3018             break;
   3019         case 3:
   3020             packet_info->ntwrk_header_ptr += BKN_DPP_PPH_FHEI_8B_SIZE_BYTE;
   3021             break;
   3022         default:
   3023             break;
   3024     }
   3025     if (eei_extension_present) {
   3026         packet_info->ntwrk_header_ptr += BKN_DPP_PPH_EXPLICIT_EDITING_INFOMATION_EXTENSION_SIZE_BYTE;
   3027     }
   3028     if (learn_extension_present) {
   3029         packet_info->ntwrk_header_ptr += BKN_DPP_PPH_LEARN_EXTENSION_SIZE_BYTE;
   3030     }
   3031 
   3032     DBG_DUNE(("FHEI(%d) trap_qualifier 0x%x trap_id 0x%x\n", packet_info->ntwrk_header_ptr, packet_info->internal.trap_qualifier, packet_info->internal.trap_id));
   3033     return;
   3034 }
   3035 
   3036 static int
   3037 bkn_dpp_packet_header_parse(bkn_switch_info_t *sinfo, uint8 *buff, uint32_t buff_len, bkn_dune_system_header_info_t *packet_info)
   3038 {
   3039     uint8_t  hdr_buff[BKN_DPP_HDR_MAX_SIZE];
   3040     uint32_t hdr_size;
   3041     uint8_t  has_internal = 0;
   3042 
   3043     if ((buff == NULL) || (packet_info == NULL)) {
   3044         return -1;
   3045     }
   3046     hdr_size = buff_len < BKN_DPP_HDR_MAX_SIZE ? buff_len: BKN_DPP_HDR_MAX_SIZE;
   3047     memcpy(hdr_buff, buff, hdr_size);
   3048 
   3049     /* FTMH */
   3050     bkn_dpp_packet_parse_ftmh(sinfo, hdr_buff, packet_info);
   3051     if (packet_info->ftmh.packet_size != (buff_len + 2)) {
   3052         DBG_DUNE(("FTMH packet size verfication failed, %d-%d\n", packet_info->ftmh.packet_size, buff_len));
   3053         memset(packet_info, 0, sizeof(bkn_dune_system_header_info_t));
   3054         return -1;
   3055     }
   3056     switch (packet_info->ftmh.pph_type) {
   3057     case 0:
   3058         has_internal = 0;
   3059         break;
   3060     case 1:
   3061         has_internal = 1;
   3062         break;
   3063     case 2: /* PPH OAM-TS only */
   3064     case 3: /* PPH Base + OAM-TS */
   3065         /* OTSH immediately follows the FTMH when present */
   3066         packet_info->ntwrk_header_ptr +=  6;
   3067         DBG_DUNE(("FTMH + OAM-TS(%d)\n", packet_info->ntwrk_header_ptr));
   3068         has_internal = 1;
   3069         break;
   3070     default:
   3071         break;
   3072     }
   3073 
   3074     if (has_internal) {
   3075       bkn_dpp_packet_parse_internal(sinfo, &hdr_buff[0], packet_info);
   3076     }
   3077 
   3078     /* FIXME: */
   3079     /* ignore packets with a double set of FTMH,internals */
   3080     /* ignore the user header size */
   3081     return 0;
   3082 }
   3083 
   3084 static int
   3085 bkn_dnx_packet_header_parse(bkn_switch_info_t *sinfo, uint8 *buf, uint32_t buf_len, bkn_dune_system_header_info_t *packet_info)
   3086 {
   3087     uint32_t fld_val;
   3088     uint32_t hdr_size = 0;
   3089     uint32_t pkt_offset_ingress_untrapped =0;
   3090     uint8_t  tm_dst_ext_present = 0;
   3091     uint8_t  app_specific_ext_size = 0;
   3092     uint8_t  flow_id_ext_size = 0;
   3093     uint8_t  bier_bfr_ext_size = 0;
   3094     uint8_t  is_pph_en = 0;
   3095     uint8_t  is_tsh_en = 0;
   3096 
   3097     if ((buf == NULL) || (packet_info == NULL)) {
   3098         return -1;
   3099     }
   3100 
   3101     /* FTMH: Source-System-Port-Aggregate */
   3102     bkn_bitstream_get_field(
   3103             &buf[hdr_size],
   3104             BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_MSB,
   3105             BKN_DNX_FTMH_SRC_SYS_PORT_AGGREGATE_NOF_BITS,
   3106             &fld_val);
   3107     packet_info->ftmh_spa = fld_val;
   3108     /* FTMH: PPH-Type TSH */
   3109     bkn_bitstream_get_field(
   3110             &buf[hdr_size],
   3111             BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_MSB,
   3112             BKN_DNX_FTMH_PPH_TYPE_IS_TSH_EN_NOF_BITS,
   3113             &fld_val);
   3114     is_tsh_en = fld_val;
   3115     /* FTMH: PPH-Type PPH base */
   3116     bkn_bitstream_get_field(
   3117             &buf[hdr_size],
   3118             BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_MSB,
   3119             BKN_DNX_FTMH_PPH_TYPE_IS_PPH_EN_NOF_BITS,
   3120             &fld_val);
   3121     is_pph_en = fld_val;
   3122     /* FTMH: TM-Destination-Extension-Present */
   3123     bkn_bitstream_get_field(
   3124             &buf[hdr_size],
   3125             BKN_DNX_FTMH_TM_DST_EXT_PRESENT_MSB,
   3126             BKN_DNX_FTMH_TM_DST_EXT_PRESENT_NOF_BITS,
   3127             &fld_val);
   3128     tm_dst_ext_present = fld_val;
   3129     /* FTMH: Application-Specific-Extension-Size */
   3130     bkn_bitstream_get_field(
   3131             &buf[hdr_size],
   3132             BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_MSB,
   3133             BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE_NOF_BITS,
   3134             &fld_val);
   3135     app_specific_ext_size = fld_val;
   3136     /* FTMH: Flow-ID-Extension-Size */
   3137     bkn_bitstream_get_field(
   3138             &buf[hdr_size],
   3139             BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_MSB,
   3140             BKN_DNX_FTMH_FLOW_ID_EXT_SIZE_NOF_BITS,
   3141             &fld_val);
   3142     flow_id_ext_size = fld_val;
   3143     /* FTMH: BIER-BFR-Extension-Size */
   3144     bkn_bitstream_get_field(
   3145             &buf[hdr_size],
   3146             BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_MSB,
   3147             BKN_DNX_FTMH_BIER_BFR_EXT_SIZE_NOF_BITS,
   3148             &fld_val);
   3149     bier_bfr_ext_size = fld_val;
   3150 
   3151     hdr_size = BKN_DNX_FTMH_BASE_SIZE;
   3152     pkt_offset_ingress_untrapped = BKN_DNX_FTMH_BASE_SIZE;
   3153 
   3154     DBG_DUNE(("FTMH(%d) source-system-port 0x%x is_tsh_en %d is_pph_en %d\n",
   3155               hdr_size, packet_info->ftmh_spa, is_tsh_en, is_pph_en));
   3156 
   3157     /* FTMH LB-Key Extension */
   3158     if (sinfo->ftmh_lb_key_ext_size > 0)
   3159     {
   3160         hdr_size += sinfo->ftmh_lb_key_ext_size;
   3161         DBG_DUNE(("FTMH LB-Key Extension(%d) is present\n", sinfo->ftmh_lb_key_ext_size));
   3162     }
   3163     /* FTMH Stacking Extension */
   3164     if (sinfo->ftmh_stacking_ext_size > 0)
   3165     {
   3166         hdr_size += sinfo->ftmh_stacking_ext_size;
   3167         DBG_DUNE(("FTMH Stacking Extension(%d) is present\n", sinfo->ftmh_stacking_ext_size));
   3168     }
   3169     /* FTMH BIER BFR Extension */
   3170     if (bier_bfr_ext_size > 0)
   3171     {
   3172         hdr_size += BKN_DNX_FTMH_BIER_BFR_EXT_SIZE;
   3173         DBG_DUNE(("FTMH BIER BFR Extension(2) is present\n"));
   3174     }
   3175     /* FTMH TM Destination Extension */
   3176     if (tm_dst_ext_present > 0)
   3177     {
   3178         hdr_size += BKN_DNX_FTMH_TM_DST_EXT_SIZE;
   3179         DBG_DUNE(("FTMH TM Destination Extension(3) is present\n"));
   3180     }
   3181     /* FTMH Application Specific Extension */
   3182     if (app_specific_ext_size > 0)
   3183     {
   3184         hdr_size += BKN_DNX_FTMH_APP_SPECIFIC_EXT_SIZE;
   3185         DBG_DUNE(("FTMH Application Specific Extension(6) is present\n"));
   3186     }
   3187     /* FTMH Flow-ID Extension */
   3188     if (flow_id_ext_size > 0)
   3189     {
   3190         hdr_size += BKN_DNX_FTMH_FLOW_ID_EXT_SIZE;
   3191         DBG_DUNE(("FTMH Flow-ID Extension(3) is present\n"));
   3192     }
   3193 
   3194     /* Given the packet is trapped to CPU */
   3195 
   3196     /* Time-Stamp Header */
   3197     if (is_tsh_en == TRUE)
   3198     {
   3199         hdr_size += BKN_DNX_TSH_SIZE;
   3200         DBG_DUNE(("Time-Stamp Header(4) is present\n"));
   3201     }
   3202 
   3203     /* Packet Processing Header */
   3204     if (is_pph_en)
   3205     {
   3206         uint8_t  learn_ext_present;
   3207         uint8_t  fhei_size;
   3208         uint8_t  lif_ext_type;
   3209 
   3210         switch (sinfo->pph_base_size)
   3211         {
   3212             case BKN_DNX_PPH_BASE_TYPE_9:
   3213                 /* FTMH: Forward-Domain */
   3214                 bkn_bitstream_get_field(
   3215                         &buf[hdr_size],
   3216                         BKN_DNX_PPH_9_FORWARD_DOMAIN_MSB,
   3217                         BKN_DNX_PPH_9_FORWARD_DOMAIN_NOF_BITS,
   3218                         &fld_val);
   3219                 packet_info->pph_forward_domain = fld_val;
   3220                 /* FTMH: Learn-Extension-Present */
   3221                 bkn_bitstream_get_field(
   3222                         &buf[hdr_size],
   3223                         BKN_DNX_PPH_9_LEARN_EXT_PRESENT_MSB,
   3224                         BKN_DNX_PPH_9_LEARN_EXT_PRESENT_NOF_BITS,
   3225                         &fld_val);
   3226                 learn_ext_present = fld_val;
   3227                 /* FTMH: FHEI-Size */
   3228                 bkn_bitstream_get_field(
   3229                         &buf[hdr_size],
   3230                         BKN_DNX_PPH_9_FHEI_SIZE_MSB,
   3231                         BKN_DNX_PPH_9_FHEI_SIZE_NOF_BITS,
   3232                         &fld_val);
   3233                 fhei_size = fld_val;
   3234                 /* FTMH: LIF-Extension-Type */
   3235                 bkn_bitstream_get_field(
   3236                         &buf[hdr_size],
   3237                         BKN_DNX_PPH_9_LIF_EXT_TYPE_MSB,
   3238                         BKN_DNX_PPH_9_LIF_EXT_TYPE_NOF_BITS,
   3239                         &fld_val);
   3240                 lif_ext_type = fld_val;
   3241 
   3242                 hdr_size += BKN_DNX_PPH_BASE_TYPE_9;
   3243                 DBG_DUNE(("PPH(10) FWD_DOMAIN %d, LEARN_EXT %d, FHEI_SIZE %d, LIF_EXT %d \n",
   3244                             packet_info->pph_forward_domain, learn_ext_present, fhei_size, lif_ext_type));
   3245                 break;
   3246             case BKN_DNX_PPH_BASE_TYPE_10:
   3247                 /* FTMH: Forward-Domain */
   3248                 bkn_bitstream_get_field(
   3249                         &buf[hdr_size],
   3250                         BKN_DNX_PPH_10_FORWARD_DOMAIN_MSB,
   3251                         BKN_DNX_PPH_10_FORWARD_DOMAIN_NOF_BITS,
   3252                         &fld_val);
   3253                 packet_info->pph_forward_domain = fld_val;
   3254                 /* FTMH: Learn-Extension-Present */
   3255                 bkn_bitstream_get_field(
   3256                         &buf[hdr_size],
   3257                         BKN_DNX_PPH_10_LEARN_EXT_PRESENT_MSB,
   3258                         BKN_DNX_PPH_10_LEARN_EXT_PRESENT_NOF_BITS,
   3259                         &fld_val);
   3260                 learn_ext_present = fld_val;
   3261                 /* FTMH: FHEI-Size */
   3262                 bkn_bitstream_get_field(
   3263                         &buf[hdr_size],
   3264                         BKN_DNX_PPH_10_FHEI_SIZE_MSB,
   3265                         BKN_DNX_PPH_10_FHEI_SIZE_NOF_BITS,
   3266                         &fld_val);
   3267                 fhei_size = fld_val;
   3268                 /* FTMH: LIF-Extension-Type */
   3269                 bkn_bitstream_get_field(
   3270                         &buf[hdr_size],
   3271                         BKN_DNX_PPH_10_LIF_EXT_TYPE_MSB,
   3272                         BKN_DNX_PPH_10_LIF_EXT_TYPE_NOF_BITS,
   3273                         &fld_val);
   3274                 lif_ext_type = fld_val;
   3275 
   3276                 hdr_size += BKN_DNX_PPH_BASE_TYPE_10;
   3277                 DBG_DUNE(("PPH(10) FWD_DOMAIN %d, LEARN_EXT %d, FHEI_SIZE %d, LIF_EXT %d \n",
   3278                             packet_info->pph_forward_domain, learn_ext_present, fhei_size, lif_ext_type));
   3279                 break;
   3280             case BKN_DNX_PPH_BASE_TYPE_12:
   3281                 /* FTMH: Forward-Domain */
   3282                 bkn_bitstream_get_field(
   3283                         &buf[hdr_size],
   3284                         BKN_DNX_PPH_12_FORWARD_DOMAIN_MSB,
   3285                         BKN_DNX_PPH_12_FORWARD_DOMAIN_NOF_BITS,
   3286                         &fld_val);
   3287                 packet_info->pph_forward_domain = fld_val;
   3288                 /* FTMH: Learn-Extension-Present */
   3289                 bkn_bitstream_get_field(
   3290                         &buf[hdr_size],
   3291                         BKN_DNX_PPH_12_LEARN_EXT_PRESENT_MSB,
   3292                         BKN_DNX_PPH_12_LEARN_EXT_PRESENT_NOF_BITS,
   3293                         &fld_val);
   3294                 learn_ext_present = fld_val;
   3295                 /* FTMH: FHEI-Size */
   3296                 bkn_bitstream_get_field(
   3297                         &buf[hdr_size],
   3298                         BKN_DNX_PPH_12_FHEI_SIZE_MSB,
   3299                         BKN_DNX_PPH_12_FHEI_SIZE_NOF_BITS,
   3300                         &fld_val);
   3301                 fhei_size = fld_val;
   3302                 /* FTMH: LIF-Extension-Type */
   3303                 bkn_bitstream_get_field(
   3304                         &buf[hdr_size],
   3305                         BKN_DNX_PPH_12_LIF_EXT_TYPE_MSB,
   3306                         BKN_DNX_PPH_12_LIF_EXT_TYPE_NOF_BITS,
   3307                         &fld_val);
   3308                 lif_ext_type = fld_val;
   3309 
   3310                 hdr_size += BKN_DNX_PPH_BASE_TYPE_12;
   3311                 DBG_DUNE(("PPH(12) FWD_DOMAIN %d, LEARN_EXT %d, FHEI_SIZE %d, LIF_EXT %d \n",
   3312                             packet_info->pph_forward_domain, learn_ext_present, fhei_size, lif_ext_type));
   3313                 break;
   3314             default:
   3315                 fhei_size = 0;
   3316                 lif_ext_type = 0;
   3317                 learn_ext_present = 0;
   3318                 break;
   3319         }
   3320         if (fhei_size)
   3321         {
   3322             switch (fhei_size)
   3323             {
   3324                 case BKN_DNX_PPH_FHEI_TYPE_SZ0:
   3325                     hdr_size += BKN_DNX_PPH_FHEI_SZ0_SIZE;
   3326                     DBG_DUNE(("FHEI(3) is present\n"));
   3327                     break;
   3328                 case BKN_DNX_PPH_FHEI_TYPE_SZ1:
   3329                     /* FHEI: Code */
   3330                     bkn_bitstream_get_field(
   3331                             &buf[hdr_size],
   3332                             BKN_DNX_PPH_FHEI_TRAP_5B_TYPE_MSB,
   3333                             BKN_DNX_PPH_FHEI_TRAP_5B_TYPE_NOF_BITS,
   3334                             &fld_val);
   3335                     packet_info->fhei_type = fld_val;
   3336                     /* FHEI-Size == 5B, FHEI-Type == Trap/Sniff */
   3337                     if (packet_info->fhei_type == 0x5)
   3338                     {
   3339                         /* FHEI: Qualifier */
   3340                         bkn_bitstream_get_field(
   3341                                 &buf[hdr_size],
   3342                                 BKN_DNX_PPH_FHEI_TRAP_5B_QUALIFIER_MSB,
   3343                                 BKN_DNX_PPH_FHEI_TRAP_5B_QUALIFIER_NOF_BITS,
   3344                                 &fld_val);
   3345                         packet_info->fhei_qualifier = fld_val;
   3346                         /* FHEI: Code */
   3347                         bkn_bitstream_get_field(
   3348                                 &buf[hdr_size],
   3349                                 BKN_DNX_PPH_FHEI_TRAP_5B_CODE_MSB,
   3350                                 BKN_DNX_PPH_FHEI_TRAP_5B_CODE_NOF_BITS,
   3351                                 &fld_val);
   3352                         packet_info->fhei_code = fld_val;
   3353                     }
   3354                     hdr_size += BKN_DNX_PPH_FHEI_SZ1_SIZE;
   3355                     DBG_DUNE(("FHEI(5) is present code 0x%x qualifier 0x%x\n", packet_info->fhei_code, packet_info->fhei_qualifier));
   3356                     break;
   3357                 case BKN_DNX_PPH_FHEI_TYPE_SZ2:
   3358                     hdr_size += BKN_DNX_PPH_FHEI_SZ1_SIZE;
   3359                     DBG_DUNE(("FHEI(8) is present\n"));
   3360                     break;
   3361             }
   3362         }
   3363 
   3364         /* PPH LIF Extension */
   3365         if (lif_ext_type)
   3366         {
   3367             hdr_size += sinfo->pph_lif_ext_size[lif_ext_type];
   3368             DBG_DUNE(("PPH LIF Extension(%d) is present\n", sinfo->pph_lif_ext_size[lif_ext_type]));
   3369         }
   3370 
   3371         /* PPH Learn Extension */
   3372         if (learn_ext_present)
   3373         {
   3374             hdr_size += BKN_DNX_PPH_LEARN_EXT_SIZE;
   3375             DBG_DUNE(("PPH Learn Extension(19) is present\n"));
   3376         }
   3377     }
   3378 
   3379     /* UDH Header */
   3380     if (sinfo->udh_enable)
   3381     {
   3382         uint8 data_type_0;
   3383         uint8 data_type_1;
   3384         uint8 data_type_2;
   3385         uint8 data_type_3;
   3386 
   3387         DBG_DUNE(("UDH base(1) is present\n"));
   3388 
   3389         /* UDH: UDH-Data-Type[0] */
   3390         bkn_bitstream_get_field(
   3391                 &buf[hdr_size],
   3392                 BKN_DNX_UDH_DATA_TYPE_0_MSB,
   3393                 BKN_DNX_UDH_DATA_TYPE_0_NOF_BITS,
   3394                 &fld_val);
   3395         data_type_0 = fld_val;
   3396         hdr_size += sinfo->udh_length_type[data_type_0];
   3397         /* UDH: UDH-Data-Type[1] */
   3398         bkn_bitstream_get_field(
   3399                 &buf[hdr_size],
   3400                 BKN_DNX_UDH_DATA_TYPE_1_MSB,
   3401                 BKN_DNX_UDH_DATA_TYPE_1_NOF_BITS,
   3402                 &fld_val);
   3403         data_type_1 = fld_val;
   3404         hdr_size += sinfo->udh_length_type[data_type_1];
   3405         /* UDH: UDH-Data-Type[2] */
   3406         bkn_bitstream_get_field(
   3407                 &buf[hdr_size],
   3408                 BKN_DNX_UDH_DATA_TYPE_2_MSB,
   3409                 BKN_DNX_UDH_DATA_TYPE_2_NOF_BITS,
   3410                 &fld_val);
   3411         data_type_2 = fld_val;
   3412         hdr_size += sinfo->udh_length_type[data_type_2];
   3413         /* UDH: UDH-Data-Type[3] */
   3414         bkn_bitstream_get_field(
   3415                 &buf[hdr_size],
   3416                 BKN_DNX_UDH_DATA_TYPE_3_MSB,
   3417                 BKN_DNX_UDH_DATA_TYPE_3_NOF_BITS,
   3418                 &fld_val);
   3419         data_type_3 = fld_val;
   3420         hdr_size += sinfo->udh_length_type[data_type_3];
   3421         hdr_size += BKN_DNX_UDH_BASE_SIZE;
   3422     }
   3423 
   3424     /*
   3425      * Check if fhei_type if of type trap
   3426      * There is a RISK that raw packet data is parsed and fhei_type is 0x5 by chance
   3427      */
   3428     if (packet_info->fhei_type == 0x5)
   3429     {
   3430         /* Done for ingress trapped packets */
   3431         packet_info->system_header_size = hdr_size;
   3432         DBG_DUNE(("Total Size of Headers is %d\n", packet_info->system_header_size));
   3433         return 0;
   3434     }
   3435     else
   3436     {
   3437         /* New generated header will be FTMH(80b), TSH(32b), PPH(96b), FHEI(40b) */
   3438 
   3439         /* Revert packet_info except info from FTHM base header */
   3440         packet_info->fhei_qualifier = 0;
   3441         packet_info->fhei_code = 0;
   3442         packet_info->fhei_type = 0;
   3443         hdr_size = pkt_offset_ingress_untrapped;
   3444 
   3445         /* Time-Stamp Header */
   3446         hdr_size += BKN_DNX_TSH_SIZE;
   3447         DBG_DUNE(("Time-Stamp Header(4) is present\n"));
   3448 
   3449         /** Packet Processing Header */
   3450         bkn_bitstream_get_field(
   3451                 &buf[hdr_size],
   3452                 BKN_DNX_PPH_12_FORWARD_DOMAIN_MSB,
   3453                 BKN_DNX_PPH_12_FORWARD_DOMAIN_NOF_BITS,
   3454                 &fld_val);
   3455         packet_info->pph_forward_domain = fld_val;
   3456         hdr_size += BKN_DNX_PPH_BASE_TYPE_12;
   3457         DBG_DUNE(("PPH(12) is present\n"));
   3458 
   3459         /*
   3460          * FHEI(Trap,40)
   3461          * 5B-FHEI format for sys_hdr_generation_profile:J2-OAM
   3462          *  8b' 0
   3463          *  19b'oam_id
   3464          *  9b' cpu_trap_code: INGRESS_TRAP_ID is always 0 here
   3465          *  4b' type(0x5): J2-Configuration FHEI Type for CPU trap
   3466          */
   3467         hdr_size += BKN_DNX_PPH_FHEI_SZ1_SIZE;
   3468         DBG_DUNE(("FHEI(5) is present\n"));
   3469     }
   3470     packet_info->system_header_size = hdr_size;
   3471     DBG_DUNE(("Total Size of Headers is %d\n", packet_info->system_header_size));
   3472     return 0;
   3473 }
   3474 
   3475 
   3476 static int
   3477 bkn_do_api_rx(bkn_switch_info_t *sinfo, int chan, int budget)
   3478 {
   3479     bkn_priv_t *priv;
   3480     bkn_dcb_chain_t *dcb_chain;
   3481     struct sk_buff *skb;
   3482     bkn_filter_t cbf;
   3483     bkn_filter_t *filter;
   3484     uint32_t err_woff;
   3485     uint32_t *dcb, *meta;
   3486     uint8_t *pkt;
   3487     uint64_t pkt_dma;
   3488     int drop_api;
   3489     int ethertype;
   3490     int pktlen;
   3491     int idx;
   3492     int dcbs_done = 0;
   3493     bkn_dune_system_header_info_t packet_info = {0};
   3494     uint32_t dnx_meta_data[3] = {0};
   3495 
   3496     dcb_chain = sinfo->rx[chan].api_dcb_chain;
   3497     if (dcb_chain == NULL) {
   3498         /* No active chains */
   3499         return 0;
   3500     }
   3501 
   3502     while (dcb_chain->dcb_cur < dcb_chain->dcb_cnt) {
   3503         dcb = &dcb_chain->dcb_mem[dcb_chain->dcb_cur * sinfo->dcb_wsize];
   3504         DBG_VERB(("DCB %2d: 0x%08x\n",
   3505                   dcb_chain->dcb_cur, dcb[sinfo->dcb_wsize-1]));
   3506         if ((dcb[sinfo->dcb_wsize-1] & (1 << 31)) == 0) {
   3507             break;
   3508         }
   3509         if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   3510             /* Handle for Continuous DMA mode */
   3511             if (dcbs_done >= budget) {
   3512                 break;
   3513             }
   3514             if ((sinfo->cmic_type == 'x' && dcb[2] & (1 << 18)) ||
   3515                 (sinfo->cmic_type != 'x' && dcb[1] & (1 << 18))) {
   3516                 dcb[sinfo->dcb_wsize-1] |= SOC_DCB_KNET_DONE;
   3517                 bkn_api_rx_chain_done(sinfo, chan);
   3518                 dcb_chain = sinfo->rx[chan].api_dcb_chain;
   3519                 if (dcb_chain == NULL) {
   3520                     break;
   3521                 }
   3522                 continue;
   3523             }
   3524         }
   3525         if ((sinfo->cmic_type == 'x' && (dcb[2] & (1 << 16)) == 0) ||
   3526             (sinfo->cmic_type != 'x' && (dcb[1] & (1 << 16)) == 0)) {
   3527             sinfo->rx[chan].chain_complete = 1;
   3528         }
   3529         sinfo->rx[chan].pkts++;
   3530         if (sinfo->cmic_type == 'x') {
   3531             pkt_dma = BUS_TO_DMA_HI(dcb[1]);
   3532             pkt_dma = pkt_dma << 32 | dcb[0];
   3533         } else {
   3534             pkt_dma = dcb[0];
   3535         }
   3536         pkt = (uint8_t *)kernel_bde->p2l(sinfo->dev_no, (sal_paddr_t)pkt_dma);
   3537         if (sinfo->cmic_type == 'x') {
   3538             if (device_is_dnx(sinfo)){
   3539                 meta = &dnx_meta_data[0];
   3540                 /* get error bit from last DCB words */
   3541                 err_woff = 2;
   3542                 meta[err_woff] = dcb[sinfo->dcb_wsize-1];
   3543             } else {
   3544                 meta = (uint32_t *)pkt;
   3545                 err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1;
   3546                 meta[err_woff] = dcb[sinfo->dcb_wsize-1];
   3547             }
   3548         } else {
   3549             meta = dcb;
   3550             err_woff = sinfo->dcb_wsize - 1;
   3551         }
   3552         pktlen = dcb[sinfo->dcb_wsize-1] & SOC_DCB_KNET_COUNT_MASK;
   3553         bkn_dump_pkt(pkt, pktlen, XGS_DMA_RX_CHAN);
   3554 
   3555         if (device_is_dpp(sinfo)) {
   3556             uint16_t tpid = 0;
   3557             uint16_t vid = 0;
   3558             int res = -1;
   3559 
   3560             memset(&packet_info, 0, sizeof(bkn_dune_system_header_info_t));
   3561             res = bkn_dpp_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info);
   3562             if (res == 0) {
   3563                 if (packet_info.ftmh.action_type == 0x2) {
   3564                     bkn_bitstream_set_field((uint32_t *)dcb, 192, 32, 0x8);
   3565                 } else if (packet_info.ftmh.action_type == 0x1) {
   3566                     bkn_bitstream_set_field((uint32_t *)dcb, 231, 25, 0x20);
   3567                 }
   3568                 bkn_bitstream_set_field((uint32_t *)dcb, 112, 16, packet_info.ftmh.src_sys_port);
   3569                 bkn_bitstream_set_field((uint32_t *)dcb, 296, 12, packet_info.internal.vsi);
   3570                 bkn_bitstream_set_field((uint32_t *)dcb, 64, 32, (packet_info.internal.trap_id << 16 | packet_info.internal.trap_qualifier));
   3571                 pkt += packet_info.ntwrk_header_ptr;
   3572                 pktlen -= packet_info.ntwrk_header_ptr;
   3573                 bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN);
   3574                 /* check if vlan tag exists */
   3575                 tpid = (uint16_t)((pkt[12] << 8) | pkt[13]);
   3576                 vid = (uint16_t)(packet_info.internal.vsi & 0xfff);
   3577                 if (packet_is_untagged(tpid)) {
   3578                     if ((pktlen + 4) < rx_buffer_size) {
   3579                         DBG_DUNE(("add vlan tag (%d) to untagged packets\n", vid));
   3580                         for (idx = (pktlen-1); idx >= 12; idx--) {
   3581                             pkt[idx+4] = pkt[idx];
   3582                         }
   3583                         pkt[12] = 0x81;
   3584                         pkt[13] = 0x00;
   3585                         pkt[14] = (vid >> 8);
   3586                         pkt[15] = (vid & 0xff);
   3587                         /* reset packet length in DCB */
   3588                         pktlen += 4;
   3589                         dcb[sinfo->dcb_wsize-1] &= ~SOC_DCB_KNET_COUNT_MASK;
   3590                         dcb[sinfo->dcb_wsize-1] |= ((pktlen + packet_info.ntwrk_header_ptr) & SOC_DCB_KNET_COUNT_MASK);
   3591                         bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN);
   3592                     }
   3593                 }
   3594             }
   3595         }
   3596         else if (device_is_dnx(sinfo)) {
   3597             int res = -1;
   3598             res = bkn_dnx_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info);
   3599             if (res == 0) {
   3600                 bkn_bitstream_set_field(meta, 0, 16, packet_info.fhei_code);
   3601                 bkn_bitstream_set_field(meta, 16, 16, packet_info.fhei_qualifier);
   3602                 bkn_bitstream_set_field(meta, 32, 16, packet_info.ftmh_spa);
   3603                 bkn_bitstream_set_field(meta, 48, 16, (packet_info.pph_forward_domain & 0xffff));
   3604 
   3605                 pkt += packet_info.system_header_size;
   3606                 pktlen -= packet_info.system_header_size;
   3607                 bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN);
   3608             }
   3609         }
   3610 
   3611         if (device_is_dpp(sinfo)) {
   3612             filter = bkn_match_rx_pkt(sinfo, pkt, pktlen, dcb, chan, &cbf);
   3613         } else if (device_is_dnx(sinfo)) {
   3614             filter = bkn_match_rx_pkt(sinfo, pkt, pktlen, meta, chan, &cbf);
   3615         } else {
   3616             filter = bkn_match_rx_pkt(sinfo, pkt + sinfo->pkt_hdr_size,
   3617                                       pktlen - sinfo->pkt_hdr_size, meta, chan, &cbf);
   3618         }
   3619         if ((dcb[sinfo->dcb_wsize-1] & 0xf0000) != 0x30000) {
   3620             /* Fragment or error */
   3621             if (filter && filter->kf.mask.w[err_woff] == 0) {
   3622                 /* Drop unless DCB status is part of filter */
   3623                 filter = NULL;
   3624             }
   3625         }
   3626         drop_api = 1;
   3627         if (filter) {
   3628             DBG_FLTR(("Match filter ID %d\n", filter->kf.id));
   3629             switch (filter->kf.dest_type) {
   3630             case KCOM_DEST_T_API:
   3631                 DBG_FLTR(("Send to Rx API\n"));
   3632                 sinfo->rx[chan].pkts_f_api++;
   3633                 drop_api = 0;
   3634                 break;
   3635             case KCOM_DEST_T_NETIF:
   3636                 priv = bkn_netif_lookup(sinfo, filter->kf.dest_id);
   3637                 if (priv) {
   3638                     /* Check that software link is up */
   3639                     if (!netif_carrier_ok(priv->dev)) {
   3640                         sinfo->rx[chan].pkts_d_no_link++;
   3641                         break;
   3642                     }
   3643 
   3644                     if (sinfo->cmic_type == 'x') {
   3645                         pkt += sinfo->pkt_hdr_size;
   3646                         pktlen -= sinfo->pkt_hdr_size;
   3647                     }
   3648 
   3649                     /* Add 2 bytes for IP header alignment (see below) */
   3650                     skb = dev_alloc_skb(pktlen + RCPU_RX_ENCAP_SIZE + 2);
   3651                     if (skb == NULL) {
   3652                         sinfo->rx[chan].pkts_d_no_skb++;
   3653                         break;
   3654                     }
   3655                     skb_reserve(skb, RCPU_RX_ENCAP_SIZE);
   3656 
   3657                     DBG_FLTR(("Send to netif %d (%s)\n",
   3658                               priv->id, priv->dev->name));
   3659                     sinfo->rx[chan].pkts_f_netif++;
   3660                     skb->dev = priv->dev;
   3661                     skb_reserve(skb, 2);    /* 16 byte align the IP fields. */
   3662 
   3663                     /* Save for RCPU before stripping tag */
   3664                     ethertype = (pkt[16] << 8) | pkt[17];
   3665                     if ((priv->flags & KCOM_NETIF_F_KEEP_RX_TAG) == 0) {
   3666                         if (filter->kf.flags & KCOM_FILTER_F_STRIP_TAG) {
   3667                             /* Strip the VLAN tag */
   3668                             uint16_t vlan_proto = (uint16_t)((pkt[12] << 8) | pkt[13]);
   3669                             if (vlan_proto == 0x8100 || vlan_proto == 0x88a8) {
   3670                                 DBG_FLTR(("Strip VLAN tag\n"));
   3671                                 for (idx = 11; idx >= 0; idx--) {
   3672                                     pkt[idx+4] = pkt[idx];
   3673                                 }
   3674                                 pktlen -= 4;
   3675                                 pkt += 4;
   3676                             }
   3677                         } else {
   3678                             /*
   3679                              * Mark packet as VLAN-tagged, otherwise newer
   3680                              * kernels will strip the tag.
   3681                              */
   3682                             uint16_t tci = (pkt[14] << 8) | pkt[15];
   3683                             if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) {
   3684                                 bkn_vlan_hwaccel_put_tag(skb, ETH_P_8021Q, tci);
   3685                             } else {
   3686                                 bkn_vlan_hwaccel_put_tag(skb,
   3687                                 ((skb->data[12] << 8) | skb->data[13]), tci);
   3688                             }
   3689                         }
   3690                     }
   3691 
   3692                     skb_copy_to_linear_data(skb, pkt, pktlen);
   3693                     if (device_is_sand(sinfo)) {
   3694                         /* CRC has been stripped */
   3695                         skb_put(skb, pktlen);
   3696                     } else {
   3697                         skb_put(skb, pktlen - 4); /* Strip CRC */
   3698                     }
   3699                     priv->stats.rx_packets++;
   3700                     priv->stats.rx_bytes += skb->len;
   3701 
   3702                     /* Optional SKB updates */
   3703                     if (knet_rx_cb != NULL) {
   3704                         KNET_SKB_CB(skb)->netif_user_data = priv->cb_user_data;
   3705                         KNET_SKB_CB(skb)->filter_user_data = filter->kf.cb_user_data;
   3706                         KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF;
   3707                         skb = knet_rx_cb(skb, sinfo->dev_no, meta);
   3708                         if (skb == NULL) {
   3709                             /* Consumed by call-back */
   3710                             sinfo->rx[chan].pkts_d_callback++;
   3711                             break;
   3712                         }
   3713                     }
   3714 
   3715                     /* Do Rx timestamping */
   3716                     if (sinfo->rx_hwts) {
   3717                         bkn_hw_tstamp_rx_set(sinfo, skb, meta);
   3718                     }
   3719 
   3720                     if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) {
   3721                         bkn_add_rcpu_encap(sinfo, skb, meta);
   3722                         DBG_PDMP(("After add RCPU ENCAP\n"));
   3723                         bkn_dump_pkt(skb->data, pktlen + RCPU_RX_ENCAP_SIZE, XGS_DMA_RX_CHAN);
   3724                     }
   3725                     skb->protocol = eth_type_trans(skb, skb->dev);
   3726                     if (filter->kf.dest_proto) {
   3727                         skb->protocol = filter->kf.dest_proto;
   3728                     }
   3729                     if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) {
   3730                         bkn_eth_type_update(skb, ethertype);
   3731                     }
   3732                     DBG_DUNE(("skb protocol 0x%04x\n",skb->protocol));
   3733 
   3734                     /* Unlock while calling up network stack */
   3735                     spin_unlock(&sinfo->lock);
   3736                     if (use_napi) {
   3737                         netif_receive_skb(skb);
   3738                     } else {
   3739                         netif_rx(skb);
   3740                     }
   3741                     spin_lock(&sinfo->lock);
   3742 
   3743                     if (filter->kf.mirror_type == KCOM_DEST_T_API ||
   3744                         dbg_pkt_enable) {
   3745                         DBG_FLTR(("Mirror to Rx API\n"));
   3746                         sinfo->rx[chan].pkts_m_api++;
   3747                         drop_api = 0;
   3748                     }
   3749                 } else {
   3750                     DBG_FLTR(("Unknown netif %d\n",
   3751                               filter->kf.dest_id));
   3752                     sinfo->rx[chan].pkts_d_unkn_netif++;
   3753                 }
   3754                 break;
   3755             default:
   3756                 /* Drop packet */
   3757                 DBG_FLTR(("Unknown dest type %d\n",
   3758                           filter->kf.dest_type));
   3759                 sinfo->rx[chan].pkts_d_unkn_dest++;
   3760                 break;
   3761             }
   3762         } else {
   3763             DBG_PKT(("Rx packet dropped.\n"));
   3764             sinfo->rx[chan].pkts_d_no_match++;
   3765         }
   3766         if (drop_api) {
   3767             /* If count is zero, the DCB will just be recycled */
   3768             dcb[sinfo->dcb_wsize-1] &= ~SOC_DCB_KNET_COUNT_MASK;
   3769         }
   3770         dcb[sinfo->dcb_wsize-1] |= SOC_DCB_KNET_DONE;
   3771         dcb_chain->dcb_cur++;
   3772         dcbs_done++;
   3773     }
   3774 
   3775     return dcbs_done;
   3776 }
   3777 
   3778 static int
   3779 bkn_do_skb_rx(bkn_switch_info_t *sinfo, int chan, int budget)
   3780 {
   3781     bkn_priv_t *priv;
   3782     bkn_desc_info_t *desc;
   3783     struct sk_buff *skb;
   3784     bkn_filter_t cbf;
   3785     bkn_filter_t *filter;
   3786     uint32_t err_woff;
   3787     uint32_t *dcb, *meta;
   3788     int ethertype;
   3789     int pktlen;
   3790     int idx;
   3791     int dcbs_done = 0;
   3792     bkn_dune_system_header_info_t packet_info = {0};
   3793     uint32_t dnx_meta_data[3] = {0};
   3794 
   3795     if (!sinfo->rx[chan].running) {
   3796         /* Rx not ready */
   3797         return 0;
   3798     }
   3799 
   3800     while (dcbs_done < budget) {
   3801         char str[32];
   3802         sprintf(str, "Rx DCB (%d)", sinfo->rx[chan].dirty);
   3803         desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty];
   3804         dcb = desc->dcb_mem;
   3805         bkn_dump_dcb(str, dcb, sinfo->dcb_wsize, XGS_DMA_RX_CHAN);
   3806         if ((dcb[sinfo->dcb_wsize-1] & (1 << 31)) == 0) {
   3807             break;
   3808         }
   3809         if ((sinfo->cmic_type == 'x' && (dcb[2] & (1 << 16)) == 0) ||
   3810             (sinfo->cmic_type != 'x' && (dcb[1] & (1 << 16)) == 0)) {
   3811             sinfo->rx[chan].chain_complete = 1;
   3812             /* Request one extra poll to check for chain done interrupt */
   3813             if (sinfo->napi_poll_mode) {
   3814                 sinfo->napi_poll_again = 1;
   3815             }
   3816         }
   3817         sinfo->rx[chan].pkts++;
   3818         skb = desc->skb;
   3819         if (sinfo->cmic_type == 'x') {
   3820             if (device_is_dnx(sinfo)){
   3821                 meta = &dnx_meta_data[0];
   3822                 /* get error bit from last DCB words */
   3823                 err_woff = 2;
   3824                 meta[err_woff] = dcb[sinfo->dcb_wsize-1];
   3825             } else {
   3826                 meta = (uint32_t *)skb->data;
   3827                 err_woff = sinfo->pkt_hdr_size / sizeof(uint32_t) - 1;
   3828                 meta[err_woff] = dcb[sinfo->dcb_wsize-1];
   3829             }
   3830         } else {
   3831             meta = dcb;
   3832             err_woff = sinfo->dcb_wsize - 1;
   3833         }
   3834         pktlen = dcb[sinfo->dcb_wsize-1] & 0xffff;
   3835         priv = netdev_priv(sinfo->dev);
   3836         DBG_DCB_RX(("Rx%d SKB DMA done (%d).\n", chan, sinfo->rx[chan].dirty));
   3837         DMA_UNMAP_SINGLE(sinfo->dma_dev,
   3838                          desc->skb_dma, desc->dma_size,
   3839                          DMA_FROMDEV);
   3840         desc->skb_dma = 0;
   3841         bkn_dump_pkt(skb->data, pktlen, XGS_DMA_RX_CHAN);
   3842 
   3843         if (device_is_dpp(sinfo)) {
   3844             uint16_t tpid = 0;
   3845             uint16_t vid = 0;
   3846             uint8_t *pkt = skb->data;
   3847             int res = 0;
   3848 
   3849             memset(&packet_info, 0, sizeof(bkn_dune_system_header_info_t));
   3850             res = bkn_dpp_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info);
   3851             if (res == 0) {
   3852                 if (packet_info.ftmh.action_type == 0x2) {
   3853                     bkn_bitstream_set_field((uint32_t *)dcb, 192, 32, 0x8);
   3854                 } else if (packet_info.ftmh.action_type == 0x1) {
   3855                     bkn_bitstream_set_field((uint32_t *)dcb, 231, 25, 0x20);
   3856                 }
   3857                 bkn_bitstream_set_field((uint32_t *)dcb, 112, 16, packet_info.ftmh.src_sys_port);
   3858                 bkn_bitstream_set_field((uint32_t *)dcb, 296, 12, packet_info.internal.vsi);
   3859                 bkn_bitstream_set_field((uint32_t *)dcb, 64, 32, (packet_info.internal.trap_id << 16 | packet_info.internal.trap_qualifier));
   3860                 pkt = skb->data + packet_info.ntwrk_header_ptr;
   3861                 /* check if vlan tag exists */
   3862                 tpid = (uint16_t)((pkt[12] << 8) | pkt[13]);
   3863                 vid = (uint16_t)(packet_info.internal.vsi & 0xfff);
   3864                 if (packet_is_untagged(tpid)) {
   3865                     if ((pktlen + 4) < rx_buffer_size) {
   3866                          DBG_DUNE(("add vlan tag to untagged packets\n"));
   3867                          for (idx = (pktlen-packet_info.ntwrk_header_ptr-1); idx >= 12; idx--) {
   3868                              pkt[idx+4] = pkt[idx];
   3869                          }
   3870                          pkt[12] = 0x81;
   3871                          pkt[13] = 0x00;
   3872                          pkt[14] = (vid >> 8);
   3873                          pkt[15] = (vid & 0xff);
   3874                          pktlen += 4;
   3875                          /* reset packet length in DCB */
   3876                          dcb[sinfo->dcb_wsize-1] &= ~SOC_DCB_KNET_COUNT_MASK;
   3877                          dcb[sinfo->dcb_wsize-1] |= (pktlen & SOC_DCB_KNET_COUNT_MASK);
   3878                          bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN);
   3879                     }
   3880                 }
   3881             }
   3882         }
   3883         else if (device_is_dnx(sinfo)) {
   3884             uint8_t *pkt = skb->data;
   3885             int res = -1;
   3886 
   3887             res = bkn_dnx_packet_header_parse(sinfo, pkt, (uint32_t)pktlen, &packet_info);
   3888             if (res == 0) {
   3889                 bkn_bitstream_set_field(meta, 0, 16, packet_info.fhei_code);
   3890                 bkn_bitstream_set_field(meta, 16, 16, packet_info.fhei_qualifier);
   3891                 bkn_bitstream_set_field(meta, 32, 16, packet_info.ftmh_spa);
   3892                 bkn_bitstream_set_field(meta, 48, 16, (packet_info.pph_forward_domain & 0xffff));
   3893 
   3894                 pkt += packet_info.system_header_size;
   3895                 pktlen -= packet_info.ntwrk_header_ptr;
   3896                 bkn_dump_pkt(pkt, 32, XGS_DMA_RX_CHAN);
   3897             }
   3898         }
   3899 
   3900         if (device_is_dpp(sinfo)) {
   3901             filter = bkn_match_rx_pkt(sinfo, skb->data + packet_info.ntwrk_header_ptr,
   3902                                      pktlen, dcb, chan, &cbf);
   3903         } else if (device_is_dnx(sinfo)) {
   3904             filter = bkn_match_rx_pkt(sinfo, skb->data + packet_info.system_header_size,
   3905                                       pktlen, meta, chan, &cbf);
   3906         } else {
   3907            filter = bkn_match_rx_pkt(sinfo, skb->data + sinfo->pkt_hdr_size,
   3908                                      pktlen - sinfo->pkt_hdr_size, meta, chan, &cbf);
   3909         }
   3910         if ((dcb[sinfo->dcb_wsize-1] & 0xf0000) != 0x30000) {
   3911             /* Fragment or error */
   3912             priv->stats.rx_errors++;
   3913             if (filter && filter->kf.mask.w[err_woff] == 0) {
   3914                 /* Drop unless DCB status is part of filter */
   3915                 filter = NULL;
   3916             }
   3917         }
   3918         DBG_PKT(("Rx packet (%d bytes).\n", pktlen));
   3919         if (filter) {
   3920             DBG_FLTR(("Match filter ID %d\n", filter->kf.id));
   3921             switch (filter->kf.dest_type) {
   3922             case KCOM_DEST_T_API:
   3923                 DBG_FLTR(("Send to Rx API\n"));
   3924                 sinfo->rx[chan].pkts_f_api++;
   3925                 bkn_api_rx_copy_from_skb(sinfo, chan, desc);
   3926                 break;
   3927             case KCOM_DEST_T_NETIF:
   3928                 priv = bkn_netif_lookup(sinfo, filter->kf.dest_id);
   3929                 if (priv) {
   3930                     /* Check that software link is up */
   3931                     if (!netif_carrier_ok(priv->dev)) {
   3932                         sinfo->rx[chan].pkts_d_no_link++;
   3933                         break;
   3934                     }
   3935                     DBG_FLTR(("Send to netif %d (%s)\n",
   3936                               priv->id, priv->dev->name));
   3937                     sinfo->rx[chan].pkts_f_netif++;
   3938 
   3939                     if (((filter->kf.mirror_type == KCOM_DEST_T_API) &&
   3940                          (!device_is_sand(sinfo))) || dbg_pkt_enable) {
   3941                         sinfo->rx[chan].pkts_m_api++;
   3942                         bkn_api_rx_copy_from_skb(sinfo, chan, desc);
   3943                     }
   3944 
   3945                     if (device_is_dpp(sinfo)) {
   3946                         if (filter->kf.mirror_type == KCOM_DEST_T_API) {
   3947                             sinfo->rx[chan].pkts_m_api++;
   3948                             bkn_api_rx_copy_from_skb(sinfo, chan, desc);
   3949                         }
   3950                         /* Strip Dune headers */
   3951                         skb->data += packet_info.ntwrk_header_ptr;
   3952                         pktlen -= packet_info.ntwrk_header_ptr;
   3953                         bkn_dump_pkt(skb->data, 32, XGS_DMA_RX_CHAN);
   3954                         /* CRC has been stripped on Dune*/
   3955                         skb_put(skb, pktlen);
   3956                     } else if (device_is_dnx(sinfo)) {
   3957                         if (filter->kf.mirror_type == KCOM_DEST_T_API) {
   3958                             sinfo->rx[chan].pkts_m_api++;
   3959                             bkn_api_rx_copy_from_skb(sinfo, chan, desc);
   3960                         }
   3961                         /* Strip Dune headers */
   3962                         skb->data += packet_info.system_header_size;
   3963                         pktlen -= packet_info.system_header_size;
   3964                         bkn_dump_pkt(skb->data, 32, XGS_DMA_RX_CHAN);
   3965                         /* CRC has been stripped on Dune*/
   3966                         skb_put(skb, pktlen);
   3967                     } else {
   3968                         skb_put(skb, pktlen - 4); /* Strip CRC */
   3969                     }
   3970 
   3971                     if (sinfo->cmic_type == 'x' && !device_is_dnx(sinfo)) {
   3972                         skb_pull(skb, sinfo->pkt_hdr_size);
   3973                     }
   3974 
   3975                     /* Save for RCPU before stripping tag */
   3976                     ethertype = (skb->data[16] << 8) | skb->data[17];
   3977                     if ((priv->flags & KCOM_NETIF_F_KEEP_RX_TAG) == 0) {
   3978                         if (filter->kf.flags & KCOM_FILTER_F_STRIP_TAG) {
   3979                             /* Strip VLAN tag */
   3980                             uint16_t vlan_proto = (uint16_t)((skb->data[12] << 8) | skb->data[13]);
   3981                             if (vlan_proto == 0x8100 || vlan_proto == 0x88a8) {
   3982                                 DBG_FLTR(("Strip VLAN tag\n"));
   3983                                 ((u32*)skb->data)[3] = ((u32*)skb->data)[2];
   3984                                 ((u32*)skb->data)[2] = ((u32*)skb->data)[1];
   3985                                 ((u32*)skb->data)[1] = ((u32*)skb->data)[0];
   3986                                 skb_pull(skb, 4);
   3987                                 if (sinfo->cmic_type == 'x' && !device_is_dnx(sinfo)) {
   3988                                     for (idx = sinfo->pkt_hdr_size / sizeof(uint32_t); idx; idx--) {
   3989                                         meta[idx] = meta[idx - 1];
   3990                                     }
   3991                                     meta++;
   3992                                 }
   3993                             }
   3994                         } else {
   3995                             /*
   3996                              * Mark packet as VLAN-tagged, otherwise newer
   3997                              * kernels will strip the tag.
   3998                              */
   3999                             uint16_t tci = (skb->data[14] << 8) | skb->data[15];
   4000                             if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) {
   4001                                 bkn_vlan_hwaccel_put_tag(skb, ETH_P_8021Q, tci);
   4002                             } else {
   4003                                 bkn_vlan_hwaccel_put_tag(skb,
   4004                                 ((skb->data[12] << 8) | skb->data[13]), tci);
   4005                             }
   4006                         }
   4007                     }
   4008                     priv->stats.rx_packets++;
   4009                     priv->stats.rx_bytes += skb->len;
   4010                     skb->dev = priv->dev;
   4011 
   4012                     /* Optional SKB updates */
   4013                     if (knet_rx_cb != NULL) {
   4014                         KNET_SKB_CB(skb)->netif_user_data = priv->cb_user_data;
   4015                         KNET_SKB_CB(skb)->filter_user_data = filter->kf.cb_user_data;
   4016                         KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF;
   4017                         skb = knet_rx_cb(skb, sinfo->dev_no, meta);
   4018                         if (skb == NULL) {
   4019                             /* Consumed by call-back */
   4020                             sinfo->rx[chan].pkts_d_callback++;
   4021                             priv->stats.rx_dropped++;
   4022                             desc->skb = NULL;
   4023                             break;
   4024                         }
   4025                     }
   4026 
   4027                     /* Do Rx timestamping */
   4028                     if (sinfo->rx_hwts) {
   4029                         bkn_hw_tstamp_rx_set(sinfo, skb, meta);
   4030                     }
   4031 
   4032                     if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) {
   4033                         bkn_add_rcpu_encap(sinfo, skb, meta);
   4034                         DBG_PDMP(("After add RCPU ENCAP\n"));
   4035                         bkn_dump_pkt(skb->data, pktlen + RCPU_RX_ENCAP_SIZE, XGS_DMA_RX_CHAN);
   4036                     }
   4037                     skb->protocol = eth_type_trans(skb, skb->dev);
   4038                     if (filter->kf.dest_proto) {
   4039                         skb->protocol = filter->kf.dest_proto;
   4040                     }
   4041                     if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) {
   4042                         bkn_eth_type_update(skb, ethertype);
   4043                     }
   4044                     DBG_DUNE(("skb protocol 0x%04x\n",skb->protocol));
   4045 
   4046                     if (filter->kf.mirror_type == KCOM_DEST_T_NETIF) {
   4047                         bkn_priv_t *mpriv;
   4048                         struct sk_buff *mskb;
   4049                         mpriv = bkn_netif_lookup(sinfo, filter->kf.mirror_id);
   4050                         if (mpriv && netif_carrier_ok(mpriv->dev)) {
   4051                             mskb = skb_clone(skb, GFP_ATOMIC);
   4052                             if (mskb == NULL) {
   4053                                 sinfo->rx[chan].pkts_d_no_skb++;
   4054                             } else {
   4055                                 sinfo->rx[chan].pkts_m_netif++;
   4056                                 mpriv->stats.rx_packets++;
   4057                                 mpriv->stats.rx_bytes += mskb->len;
   4058                                 skb->dev = mpriv->dev;
   4059                                 if (filter->kf.mirror_proto) {
   4060                                     skb->protocol = filter->kf.mirror_proto;
   4061                                 }
   4062                                 /* Unlock while calling up network stack */
   4063                                 spin_unlock(&sinfo->lock);
   4064                                 if (use_napi) {
   4065                                     netif_receive_skb(mskb);
   4066                                 } else {
   4067                                     netif_rx(mskb);
   4068                                 }
   4069                                 spin_lock(&sinfo->lock);
   4070                             }
   4071                         }
   4072                     }
   4073 
   4074                     /* Unlock while calling up network stack */
   4075                     spin_unlock(&sinfo->lock);
   4076                     if (use_napi) {
   4077                         netif_receive_skb(skb);
   4078                     } else {
   4079                         netif_rx(skb);
   4080                     }
   4081                     spin_lock(&sinfo->lock);
   4082 
   4083                     /* Ensure that we reallocate SKB for this DCB */
   4084                     desc->skb = NULL;
   4085                 } else {
   4086                     DBG_FLTR(("Unknown netif %d\n",
   4087                               filter->kf.dest_id));
   4088                     sinfo->rx[chan].pkts_d_unkn_netif++;
   4089                 }
   4090                 break;
   4091             default:
   4092                 /* Drop packet */
   4093                 DBG_FLTR(("Unknown dest type %d\n",
   4094                           filter->kf.dest_type));
   4095                 sinfo->rx[chan].pkts_d_unkn_dest++;
   4096                 break;
   4097             }
   4098         } else {
   4099             DBG_PKT(("Rx packet dropped.\n"));
   4100             sinfo->rx[chan].pkts_d_no_match++;
   4101             priv->stats.rx_dropped++;
   4102         }
   4103         dcb[sinfo->dcb_wsize-1] &= ~(1 << 31);
   4104         if (++sinfo->rx[chan].dirty >= MAX_RX_DCBS) {
   4105             sinfo->rx[chan].dirty = 0;
   4106         }
   4107         sinfo->rx[chan].free--;
   4108         dcbs_done++;
   4109         if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   4110             /* Right now refill for Continuous DMA mode */
   4111             bkn_rx_refill(sinfo, chan);
   4112         }
   4113     }
   4114 
   4115     return dcbs_done;
   4116 }
   4117 
   4118 static int
   4119 bkn_do_rx(bkn_switch_info_t *sinfo, int chan, int budget)
   4120 {
   4121     if (sinfo->rx[chan].use_rx_skb == 0) {
   4122         /* Rx buffers are provided by BCM Rx API */
   4123         return bkn_do_api_rx(sinfo, chan, budget);
   4124     } else {
   4125         /* Rx buffers are provided by Linux kernel */
   4126         return bkn_do_skb_rx(sinfo, chan, budget);
   4127     }
   4128 }
   4129 
   4130 static void
   4131 bkn_rx_desc_done(bkn_switch_info_t *sinfo, int chan)
   4132 {
   4133     bkn_evt_resource_t *evt;
   4134     evt = &_bkn_evt[sinfo->evt_idx];
   4135     DBG_IRQ(("Rx%d desc done\n", chan));
   4136 
   4137     if (sinfo->rx[chan].use_rx_skb == 0) {
   4138         sinfo->dma_events |= KCOM_DMA_INFO_F_RX_DONE;
   4139         evt->evt_wq_put++;
   4140         wake_up_interruptible(&evt->evt_wq);
   4141     }
   4142 }
   4143 
   4144 static void
   4145 bkn_rx_chain_done(bkn_switch_info_t *sinfo, int chan)
   4146 {
   4147     DBG_IRQ(("Rx%d chain done\n", chan));
   4148 
   4149     if (sinfo->rx[chan].chain_complete == 0) {
   4150         /*
   4151          * In certain environments the DCB memory is updated after
   4152          * the corresponding interrupt has been received.
   4153          * The following code will ensure that this situation is
   4154          * handled properly.
   4155          */
   4156         int maxloop = 0;
   4157         while (sinfo->rx[chan].chain_complete == 0) {
   4158             sinfo->rx[chan].sync_retry++;
   4159             if (maxloop == 0) {
   4160                 sinfo->rx[chan].sync_err++;
   4161             }
   4162             if (maxloop > sinfo->rx[chan].sync_maxloop) {
   4163                 sinfo->rx[chan].sync_maxloop = maxloop;
   4164             }
   4165             if (bkn_do_rx(sinfo, chan, MAX_RX_DCBS) > 0) {
   4166                 bkn_rx_desc_done(sinfo, chan);
   4167             }
   4168             if (++maxloop > rx_sync_retry) {
   4169                 gprintk("Fatal error: Incomplete chain\n");
   4170                 sinfo->rx[chan].chain_complete = 1;
   4171                 break;
   4172             }
   4173         }
   4174     }
   4175 
   4176     sinfo->rx[chan].running = 0;
   4177 
   4178     if (sinfo->rx[chan].use_rx_skb == 0) {
   4179         bkn_api_rx_chain_done(sinfo, chan);
   4180     } else {
   4181         bkn_rx_refill(sinfo, chan);
   4182 
   4183         if (bkn_rx_restart(sinfo, chan) != 0) {
   4184             /* Presumably out of resources */
   4185             sinfo->timer.expires = jiffies + 1;
   4186             if (!sinfo->timer_queued) {
   4187                 sinfo->timer_queued = 1;
   4188                 add_timer(&sinfo->timer);
   4189             }
   4190         }
   4191     }
   4192 }
   4193 
   4194 static void
   4195 bkn_suspend_tx(bkn_switch_info_t *sinfo)
   4196 {
   4197     struct list_head *list;
   4198     bkn_priv_t *priv = netdev_priv(sinfo->dev);
   4199 
   4200     /* Stop main device */
   4201     netif_stop_queue(priv->dev);
   4202     sinfo->tx.suspends++;
   4203     /* Stop associated virtual devices */
   4204     list_for_each(list, &sinfo->ndev_list) {
   4205         priv = (bkn_priv_t *)list;
   4206         netif_stop_queue(priv->dev);
   4207     }
   4208 }
   4209 
   4210 static void
   4211 bkn_resume_tx(bkn_switch_info_t *sinfo)
   4212 {
   4213     struct list_head *list;
   4214     bkn_priv_t *priv = netdev_priv(sinfo->dev);
   4215 
   4216     /* Check main device */
   4217     if (netif_queue_stopped(priv->dev) && sinfo->tx.free > 1) {
   4218         netif_wake_queue(priv->dev);
   4219     }
   4220     /* Check associated virtual devices */
   4221     list_for_each(list, &sinfo->ndev_list) {
   4222         priv = (bkn_priv_t *)list;
   4223         if (netif_queue_stopped(priv->dev) && sinfo->tx.free > 1) {
   4224             netif_wake_queue(priv->dev);
   4225         }
   4226     }
   4227 }
   4228 
   4229 static int
   4230 bkn_hw_tstamp_tx_set(bkn_switch_info_t *sinfo, struct sk_buff *skb)
   4231 {
   4232     struct skb_shared_hwtstamps shhwtstamps;
   4233     uint64_t ts = 0;
   4234     uint32_t hdrlen = sinfo->cmic_type == 'x' ? PKT_TX_HDR_SIZE : 0;
   4235     int port;
   4236 
   4237     if (!knet_hw_tstamp_tx_time_get_cb) {
   4238         return -1;
   4239     }
   4240 
   4241     port = KNET_SKB_CB(skb)->port;
   4242     if (knet_hw_tstamp_tx_time_get_cb(sinfo->dev_no, port, skb->data + hdrlen, &ts) < 0) {
   4243         return -1;
   4244     }
   4245 
   4246     memset(&shhwtstamps, 0, sizeof(shhwtstamps));
   4247     shhwtstamps.hwtstamp = ns_to_ktime(be64_to_cpu(ts));
   4248     skb_tstamp_tx(skb, &shhwtstamps);
   4249 
   4250     return 0;
   4251 }
   4252 
   4253 static void
   4254 bkn_hw_tstamp_tx_work(struct work_struct *work)
   4255 {
   4256     bkn_switch_info_t *sinfo = container_of(work, bkn_switch_info_t, tx_ptp_work);
   4257     struct sk_buff *skb;
   4258 
   4259     while (skb_queue_len(&sinfo->tx_ptp_queue)) {
   4260         skb = skb_dequeue(&sinfo->tx_ptp_queue);
   4261         if (bkn_hw_tstamp_tx_set(sinfo, skb) < 0) {
   4262             gprintk("Timestamp has not been taken for the current skb.\n");
   4263         }
   4264         dev_kfree_skb_any(skb);
   4265     }
   4266 }
   4267 
   4268 static int
   4269 bkn_do_tx(bkn_switch_info_t *sinfo)
   4270 {
   4271     bkn_desc_info_t *desc;
   4272     int dcbs_done = 0;
   4273 
   4274     if (!CDMA_CH(sinfo, XGS_DMA_TX_CHAN) && sinfo->tx.api_active) {
   4275         return dcbs_done;
   4276     }
   4277 
   4278     while (dcbs_done < MAX_TX_DCBS) {
   4279         char str[32];
   4280         if (sinfo->tx.free == MAX_TX_DCBS) {
   4281             break;
   4282         }
   4283         sprintf(str, "Tx DCB (%d)", sinfo->tx.dirty);
   4284         desc = &sinfo->tx.desc[sinfo->tx.dirty];
   4285         bkn_dump_dcb(str, desc->dcb_mem, sinfo->dcb_wsize, XGS_DMA_TX_CHAN);
   4286         if ((desc->dcb_mem[sinfo->dcb_wsize-1] & (1 << 31)) == 0) {
   4287             break;
   4288         }
   4289         if (desc->skb) {
   4290             DBG_DCB_TX(("Tx SKB DMA done (%d).\n", sinfo->tx.dirty));
   4291             DMA_UNMAP_SINGLE(sinfo->dma_dev,
   4292                              desc->skb_dma, desc->dma_size,
   4293                              DMA_TODEV);
   4294             if (bkn_skb_tx_flags(desc->skb) & SKBTX_IN_PROGRESS) {
   4295                 skb_queue_tail(&sinfo->tx_ptp_queue, desc->skb);
   4296                 schedule_work(&sinfo->tx_ptp_work);
   4297             } else {
   4298                 dev_kfree_skb_any(desc->skb);
   4299             }
   4300             desc->skb = NULL;
   4301             desc->skb_dma = 0;
   4302         }
   4303         desc->dcb_mem[sinfo->dcb_wsize-1] &= ~(1 << 31);
   4304         if (++sinfo->tx.dirty >= MAX_TX_DCBS) {
   4305             sinfo->tx.dirty = 0;
   4306         }
   4307         if (++sinfo->tx.free > MAX_TX_DCBS) {
   4308             gprintk("Too many free Tx DCBs(%d).\n", sinfo->tx.free);
   4309         }
   4310         dcbs_done++;
   4311     }
   4312 
   4313     return dcbs_done;
   4314 }
   4315 
   4316 static void
   4317 bkn_tx_cdma_chain_switch(bkn_switch_info_t *sinfo)
   4318 {
   4319     bkn_dcb_chain_t *dcb_chain = sinfo->tx.api_dcb_chain;
   4320     uint32_t *dcb_mem;
   4321     uint64_t dcb_dma;
   4322     int woffset;
   4323 
   4324     /* Switch between SKB Tx and API Tx for Continuous DMA mode */
   4325     if (!sinfo->tx.api_active) {
   4326         /*
   4327          * Set the current SKB DCB as reload DCB and the last DCB of
   4328          * the pending API chain as the new halt location.
   4329          */
   4330         sinfo->tx.api_active = 1;
   4331         dcb_mem = sinfo->tx.desc[sinfo->tx.cur].dcb_mem;
   4332         memset(dcb_mem, 0, sinfo->dcb_wsize * sizeof(uint32_t));
   4333         dcb_mem[0] = dcb_chain->dcb_dma;
   4334         if (sinfo->cmic_type == 'x') {
   4335             dcb_mem[1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32);
   4336             dcb_mem[2] |= 1 << 24 | 1 << 18 | 1 << 16;
   4337         } else {
   4338             dcb_mem[1] |= 1 << 24 | 1 << 18 | 1 << 16;
   4339         }
   4340         if (++sinfo->tx.cur >= MAX_TX_DCBS) {
   4341             sinfo->tx.cur = 0;
   4342         }
   4343         sinfo->tx.free--;
   4344         woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize;
   4345         dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t);
   4346         /* DMA run to the new halt location */
   4347         bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, dcb_dma);
   4348     } else {
   4349         /* Only need to set the current SKB DCB as the new halt location */
   4350         sinfo->tx.api_active = 0;
   4351         woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize;
   4352         dcb_mem = &dcb_chain->dcb_mem[woffset];
   4353         dcb_mem[0] = sinfo->tx.desc[sinfo->tx.dirty].dcb_dma;
   4354         if (sinfo->cmic_type == 'x') {
   4355             dcb_mem[1] = DMA_TO_BUS_HI(sinfo->tx.desc[sinfo->tx.dirty].dcb_dma >> 32);
   4356         }
   4357         dcb_dma = sinfo->tx.desc[sinfo->tx.cur].dcb_dma;
   4358         /* DMA run to the new halt location */
   4359         bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, dcb_dma);
   4360     }
   4361 }
   4362 
   4363 static void
   4364 bkn_skb_tx(bkn_switch_info_t *sinfo)
   4365 {
   4366     if (sinfo->tx.api_active) {
   4367         /* Switch from API Tx to SKB Tx */
   4368         bkn_tx_cdma_chain_switch(sinfo);
   4369     }
   4370 }
   4371 
   4372 static void
   4373 bkn_api_tx(bkn_switch_info_t *sinfo)
   4374 {
   4375     bkn_dcb_chain_t *dcb_chain;
   4376     uint64_t pkt_dma;
   4377     unsigned char *pktdata;
   4378     int pktlen;
   4379     int i;
   4380 
   4381     /* Assume that driver lock is held */
   4382     if (list_empty(&sinfo->tx.api_dcb_list)) {
   4383         sinfo->tx.api_active = 0;
   4384     } else {
   4385         sinfo->tx.pkts++;
   4386         dcb_chain = list_entry(sinfo->tx.api_dcb_list.next,
   4387                                bkn_dcb_chain_t, list);
   4388         DBG_DCB_TX(("Start API Tx DMA, first DCB @ 0x%08x (%d DCBs).\n",
   4389                     (uint32_t)dcb_chain->dcb_dma, dcb_chain->dcb_cnt));
   4390         for (i = 0; i < dcb_chain->dcb_cnt && debug & DBG_LVL_PDMP; i++) {
   4391             if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN) && i == dcb_chain->dcb_cnt - 1) {
   4392                 break;
   4393             }
   4394             if (sinfo->cmic_type == 'x') {
   4395                 pkt_dma = BUS_TO_DMA_HI(dcb_chain->dcb_mem[sinfo->dcb_wsize * i + 1]);
   4396                 pkt_dma = pkt_dma << 32 | dcb_chain->dcb_mem[sinfo->dcb_wsize * i];
   4397             } else {
   4398                 pkt_dma = dcb_chain->dcb_mem[sinfo->dcb_wsize * i];
   4399             }
   4400             pktdata = kernel_bde->p2l(sinfo->dev_no, pkt_dma);
   4401             if (sinfo->cmic_type == 'x') {
   4402                 pktlen = dcb_chain->dcb_mem[sinfo->dcb_wsize * i + 2] & 0xffff;
   4403             } else {
   4404                 pktlen = dcb_chain->dcb_mem[sinfo->dcb_wsize * i + 1] & 0xffff;
   4405             }
   4406             bkn_dump_pkt(pktdata, pktlen, XGS_DMA_TX_CHAN);
   4407         }
   4408 
   4409         if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) {
   4410             sinfo->tx.api_dcb_chain = dcb_chain;
   4411             if (!sinfo->tx.api_active) {
   4412                 /* Switch from SKB Tx to API Tx */
   4413                 bkn_tx_cdma_chain_switch(sinfo);
   4414             }
   4415             list_del(&dcb_chain->list);
   4416         } else {
   4417             sinfo->tx.api_active = 1;
   4418             dev_dma_chan_clear(sinfo, XGS_DMA_TX_CHAN);
   4419             dev_irq_mask_enable(sinfo, XGS_DMA_TX_CHAN, 1);
   4420             dev_dma_chan_start(sinfo, XGS_DMA_TX_CHAN, dcb_chain->dcb_dma);
   4421             list_del(&dcb_chain->list);
   4422             kfree(dcb_chain);
   4423         }
   4424     }
   4425 }
   4426 
   4427 static void
   4428 bkn_tx_cdma_chain_done(bkn_switch_info_t *sinfo, int done)
   4429 {
   4430     int woffset;
   4431     int dcbs_done = 0;
   4432     bkn_evt_resource_t *evt;
   4433 
   4434     DBG_IRQ(("Tx CDMA chain done \n"));
   4435 
   4436     evt = &_bkn_evt[sinfo->evt_idx];
   4437 
   4438     if (sinfo->tx.api_active) {
   4439         /* Drain API Tx chains */
   4440         while (sinfo->tx.api_dcb_chain != sinfo->tx.api_dcb_chain_end) {
   4441             woffset = sinfo->tx.api_dcb_chain->dcb_cnt * sinfo->dcb_wsize - 1;
   4442             if (!(sinfo->tx.api_dcb_chain->dcb_mem[woffset] & (1 << 31))) {
   4443                 return;
   4444             }
   4445             sinfo->tx.api_dcb_chain->dcb_mem[woffset - sinfo->dcb_wsize] |= SOC_DCB_KNET_DONE;
   4446             sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE;
   4447             evt->evt_wq_put++;
   4448             wake_up_interruptible(&evt->evt_wq);
   4449             kfree(sinfo->tx.api_dcb_chain);
   4450             sinfo->tx.api_dcb_chain = NULL;
   4451             bkn_api_tx(sinfo);
   4452             if ((++dcbs_done + done) >= MAX_TX_DCBS) {
   4453                 if (sinfo->napi_poll_mode) {
   4454                     /* Request one extra poll to reschedule Tx */
   4455                     sinfo->napi_poll_again = 1;
   4456                 } else {
   4457                     /* Request to yield for Continuous DMA mode */
   4458                     sinfo->tx_yield = 1;
   4459                 }
   4460                 return;
   4461             }
   4462         }
   4463         woffset = (sinfo->tx.api_dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize - 1;
   4464         if (!(sinfo->tx.api_dcb_chain->dcb_mem[woffset] & (1 << 31))) {
   4465             return;
   4466         }
   4467         sinfo->tx.api_dcb_chain->dcb_mem[woffset] |= SOC_DCB_KNET_DONE;
   4468         /* Try and park at SKB Tx if API Tx done */
   4469         bkn_skb_tx(sinfo);
   4470         sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE;
   4471         evt->evt_wq_put++;
   4472         wake_up_interruptible(&evt->evt_wq);
   4473         kfree(sinfo->tx.api_dcb_chain);
   4474         sinfo->tx.api_dcb_chain = NULL;
   4475         sinfo->tx.api_dcb_chain_end = NULL;
   4476         if (!sinfo->napi_poll_mode) {
   4477             /* Not need to yield for Continuous DMA mode */
   4478             sinfo->tx_yield = 0;
   4479         }
   4480     } else {
   4481         if (sinfo->tx.free == MAX_TX_DCBS) {
   4482             /* Try API Tx if SKB Tx done */
   4483             bkn_api_tx(sinfo);
   4484             if (sinfo->tx.api_active) {
   4485                 return;
   4486             }
   4487         }
   4488     }
   4489 
   4490     /* Resume if netif Tx resources available and API Tx not active */
   4491     bkn_resume_tx(sinfo);
   4492 }
   4493 
   4494 static void
   4495 bkn_tx_chain_done(bkn_switch_info_t *sinfo, int done)
   4496 {
   4497     bkn_desc_info_t *desc;
   4498     int idx, pending;
   4499     bkn_evt_resource_t *evt;
   4500 
   4501     if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) {
   4502         return bkn_tx_cdma_chain_done(sinfo, done);
   4503     }
   4504 
   4505     DBG_IRQ(("Tx chain done (%d/%d)\n", sinfo->tx.cur, sinfo->tx.dirty));
   4506 
   4507     dev_irq_mask_disable(sinfo, XGS_DMA_TX_CHAN, 0);
   4508 
   4509     evt = &_bkn_evt[sinfo->evt_idx];
   4510 
   4511     if (sinfo->tx.api_active) {
   4512         sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE;
   4513         evt->evt_wq_put++;
   4514         wake_up_interruptible(&evt->evt_wq);
   4515         /* Check if BCM API has more to send */
   4516         bkn_api_tx(sinfo);
   4517         if (sinfo->tx.api_active) {
   4518             return;
   4519         }
   4520     }
   4521 
   4522     if (sinfo->tx.free == MAX_TX_DCBS) {
   4523         /* If netif Tx is idle then allow BCM API to send */
   4524         bkn_api_tx(sinfo);
   4525         if (sinfo->tx.api_active) {
   4526             return;
   4527         }
   4528     } else {
   4529         /* If two or more DCBs are pending, chain them */
   4530         pending = MAX_TX_DCBS - sinfo->tx.free;
   4531         idx = sinfo->tx.dirty;
   4532         while (--pending && idx < (MAX_TX_DCBS - 1)) {
   4533             if (sinfo->cmic_type == 'x') {
   4534                 sinfo->tx.desc[idx++].dcb_mem[2] |= 1 << 16;
   4535             } else {
   4536                 sinfo->tx.desc[idx++].dcb_mem[1] |= 1 << 16;
   4537             }
   4538             DBG_DCB_TX(("Chain Tx DCB %d (%d)\n", idx, pending));
   4539         }
   4540         /* Restart DMA from where we stopped */
   4541         desc = &sinfo->tx.desc[sinfo->tx.dirty];
   4542         DBG_DCB_TX(("Restart Tx DMA, DCB @ 0x%08x (%d).\n",
   4543                     (uint32_t)desc->dcb_dma, sinfo->tx.dirty));
   4544         dev_dma_chan_clear(sinfo, XGS_DMA_TX_CHAN);
   4545         dev_irq_mask_enable(sinfo, XGS_DMA_TX_CHAN, 0);
   4546         dev_dma_chan_start(sinfo, XGS_DMA_TX_CHAN, desc->dcb_dma);
   4547     }
   4548 
   4549     /* Resume if netif Tx resources available and API Tx not active */
   4550     bkn_resume_tx(sinfo);
   4551 }
   4552 
   4553 static void
   4554 bkn_schedule_napi_poll(bkn_switch_info_t *sinfo)
   4555 {
   4556     /* Schedule NAPI poll */
   4557     DBG_NAPI(("Schedule NAPI poll on %s.\n", sinfo->dev->name));
   4558     /* Disable interrupts until poll job is complete */
   4559     sinfo->napi_poll_mode = 1;
   4560     /* Unlock while calling up network stack */
   4561     spin_unlock(&sinfo->lock);
   4562     if (bkn_napi_schedule_prep(sinfo->dev, &sinfo->napi)) {
   4563         __bkn_napi_schedule(sinfo->dev, &sinfo->napi);
   4564         DBG_NAPI(("Schedule prep OK on %s.\n", sinfo->dev->name));
   4565     } else {
   4566         /* Most likely the base device is has not been opened */
   4567         gprintk("Warning: Unable to schedule NAPI - base device not up?\n");
   4568     }
   4569     spin_lock(&sinfo->lock);
   4570 }
   4571 
   4572 static void
   4573 bkn_napi_poll_complete(bkn_switch_info_t *sinfo)
   4574 {
   4575     /* Unlock while calling up network stack */
   4576     spin_unlock(&sinfo->lock);
   4577     bkn_napi_complete(sinfo->dev, &sinfo->napi);
   4578     spin_lock(&sinfo->lock);
   4579     /* Re-enable interrupts */
   4580     sinfo->napi_poll_mode = 0;
   4581     dev_irq_mask_set(sinfo, sinfo->irq_mask);
   4582 }
   4583 
   4584 static int
   4585 xgs_do_dma(bkn_switch_info_t *sinfo, int budget)
   4586 {
   4587     int rx_dcbs_done = 0, tx_dcbs_done = 0;
   4588     int chan_done, budget_chans = 0;
   4589     uint32_t dma_stat;
   4590     int chan;
   4591 
   4592     DEV_READ32(sinfo, CMIC_DMA_STATr, &dma_stat);
   4593 
   4594     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4595         if (dma_stat & DS_DESC_DONE_TST(XGS_DMA_RX_CHAN + chan)) {
   4596             xgs_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan);
   4597             sinfo->poll_channels |= 1 << chan;
   4598         }
   4599     }
   4600     if (!sinfo->poll_channels) {
   4601         sinfo->poll_channels = (uint32_t)(1 << sinfo->rx_chans) - 1;
   4602         budget_chans = budget / sinfo->rx_chans;
   4603     } else {
   4604         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4605             if (1 << chan & sinfo->poll_channels) {
   4606                 budget_chans++;
   4607             }
   4608         }
   4609         budget_chans = budget / budget_chans;
   4610     }
   4611 
   4612     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4613         if (1 << chan & sinfo->poll_channels) {
   4614             chan_done = bkn_do_rx(sinfo, chan, budget_chans);
   4615             rx_dcbs_done += chan_done;
   4616             if (chan_done < budget_chans) {
   4617                 sinfo->poll_channels &= ~(1 << chan);
   4618             }
   4619             bkn_rx_desc_done(sinfo, chan);
   4620         }
   4621 
   4622         if (dma_stat & DS_CHAIN_DONE_TST(XGS_DMA_RX_CHAN + chan)) {
   4623             xgs_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan);
   4624             bkn_rx_chain_done(sinfo, chan);
   4625         }
   4626     }
   4627 
   4628     if (dma_stat & DS_CHAIN_DONE_TST(XGS_DMA_TX_CHAN)) {
   4629         xgs_dma_chain_clear(sinfo, XGS_DMA_TX_CHAN);
   4630         tx_dcbs_done = bkn_do_tx(sinfo);
   4631         bkn_tx_chain_done(sinfo, tx_dcbs_done);
   4632     }
   4633 
   4634     return sinfo->poll_channels ? budget : rx_dcbs_done;
   4635 }
   4636 
   4637 static int
   4638 xgsm_do_dma(bkn_switch_info_t *sinfo, int budget)
   4639 {
   4640     int rx_dcbs_done = 0, tx_dcbs_done = 0;
   4641     int chan_done, budget_chans = 0;
   4642     uint32_t dma_stat, irq_stat = 0;
   4643     int chan;
   4644 
   4645     /* Get Controlled interrupt states for Continuous DMA mode */
   4646     if (sinfo->cdma_channels) {
   4647         DEV_READ32(sinfo, CMICM_IRQ_STATr, &irq_stat);
   4648     }
   4649 
   4650     DEV_READ32(sinfo, CMICM_DMA_STATr, &dma_stat);
   4651 
   4652     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4653         if (dma_stat & (0x10 << (XGS_DMA_RX_CHAN + chan)) ||
   4654             irq_stat & (0x08000000 << (XGS_DMA_RX_CHAN + chan))) {
   4655             xgsm_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan);
   4656             sinfo->poll_channels |= 1 << chan;
   4657         }
   4658     }
   4659     if (!sinfo->poll_channels) {
   4660         sinfo->poll_channels = (uint32_t)(1 << sinfo->rx_chans) - 1;
   4661         budget_chans = budget / sinfo->rx_chans;
   4662     } else {
   4663         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4664             if (1 << chan & sinfo->poll_channels) {
   4665                 budget_chans++;
   4666             }
   4667         }
   4668         budget_chans = budget / budget_chans;
   4669     }
   4670 
   4671     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4672         if (1 << chan & sinfo->poll_channels) {
   4673             chan_done = bkn_do_rx(sinfo, chan, budget_chans);
   4674             rx_dcbs_done += chan_done;
   4675             if (chan_done < budget_chans) {
   4676                 sinfo->poll_channels &= ~(1 << chan);
   4677             }
   4678             bkn_rx_desc_done(sinfo, chan);
   4679         }
   4680 
   4681         if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   4682             continue;
   4683         }
   4684 
   4685         if (dma_stat & (0x1 << (XGS_DMA_RX_CHAN + chan))) {
   4686             xgsm_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan);
   4687             bkn_rx_chain_done(sinfo, chan);
   4688         }
   4689     }
   4690 
   4691     if (dma_stat & (0x1 << XGS_DMA_TX_CHAN) ||
   4692         irq_stat & (0x08000000 << XGS_DMA_TX_CHAN)) {
   4693         if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) {
   4694             xgsm_dma_desc_clear(sinfo, XGS_DMA_TX_CHAN);
   4695         } else {
   4696             xgsm_dma_chain_clear(sinfo, XGS_DMA_TX_CHAN);
   4697         }
   4698         tx_dcbs_done = bkn_do_tx(sinfo);
   4699         bkn_tx_chain_done(sinfo, tx_dcbs_done);
   4700     }
   4701 
   4702     return sinfo->poll_channels ? budget : rx_dcbs_done;
   4703 }
   4704 
   4705 static int
   4706 xgsx_do_dma(bkn_switch_info_t *sinfo, int budget)
   4707 {
   4708     int rx_dcbs_done = 0, tx_dcbs_done = 0;
   4709     int chan_done, budget_chans = 0;
   4710     uint32_t irq_stat, tx_dma_stat, rx_dma_stat[NUM_CMICX_RX_CHAN];
   4711     int chan;
   4712 
   4713     DEV_READ32(sinfo, CMICX_IRQ_STATr, &irq_stat);
   4714     DEV_READ32(sinfo, CMICX_DMA_STATr + 0x80 * XGS_DMA_TX_CHAN, &tx_dma_stat);
   4715     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4716         DEV_READ32(sinfo,
   4717                    CMICX_DMA_STATr + 0x80 * (XGS_DMA_RX_CHAN + chan),
   4718                    &rx_dma_stat[chan]);
   4719     }
   4720 
   4721     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4722         if ((irq_stat & CMICX_DS_CMC_CTRLD_INT(XGS_DMA_RX_CHAN + chan)) ||
   4723             (irq_stat & CMICX_DS_CMC_DESC_DONE(XGS_DMA_RX_CHAN + chan))) {
   4724             xgsx_dma_desc_clear(sinfo, XGS_DMA_RX_CHAN + chan);
   4725             sinfo->poll_channels |= 1 << chan;
   4726         }
   4727     }
   4728     if (!sinfo->poll_channels) {
   4729         sinfo->poll_channels = (uint32_t)(1 << sinfo->rx_chans) - 1;
   4730         budget_chans = budget / sinfo->rx_chans;
   4731     } else {
   4732         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4733             if (1 << chan & sinfo->poll_channels) {
   4734                 budget_chans++;
   4735             }
   4736         }
   4737         budget_chans = budget / budget_chans;
   4738     }
   4739 
   4740     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4741         if (1 << chan & sinfo->poll_channels) {
   4742             chan_done = bkn_do_rx(sinfo, chan, budget_chans);
   4743             rx_dcbs_done += chan_done;
   4744             if (chan_done < budget_chans) {
   4745                 sinfo->poll_channels &= ~(1 << chan);
   4746             }
   4747             bkn_rx_desc_done(sinfo, chan);
   4748         }
   4749 
   4750         if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   4751             continue;
   4752         }
   4753 
   4754         if (rx_dma_stat[chan] & CMICX_DS_CMC_DMA_CHAIN_DONE) {
   4755             xgsx_dma_chain_clear(sinfo, XGS_DMA_RX_CHAN + chan);
   4756             bkn_rx_chain_done(sinfo, chan);
   4757         }
   4758     }
   4759 
   4760     if ((irq_stat & CMICX_DS_CMC_CTRLD_INT(XGS_DMA_TX_CHAN)) ||
   4761         (tx_dma_stat & CMICX_DS_CMC_DMA_CHAIN_DONE)) {
   4762         if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) {
   4763             xgsx_dma_desc_clear(sinfo, XGS_DMA_TX_CHAN);
   4764         } else {
   4765             xgsx_dma_chain_clear(sinfo, XGS_DMA_TX_CHAN);
   4766         }
   4767         tx_dcbs_done = bkn_do_tx(sinfo);
   4768         bkn_tx_chain_done(sinfo, tx_dcbs_done);
   4769     }
   4770 
   4771     return sinfo->poll_channels ? budget : rx_dcbs_done;
   4772 }
   4773 
   4774 static int
   4775 dev_do_dma(bkn_switch_info_t *sinfo, int budget)
   4776 {
   4777     if (DEV_IS_CMICX(sinfo)) {
   4778         return xgsx_do_dma(sinfo, budget);
   4779     } else if (DEV_IS_CMICM(sinfo)) {
   4780         return xgsm_do_dma(sinfo, budget);
   4781     } else {
   4782         return xgs_do_dma(sinfo, budget);
   4783     }
   4784 }
   4785 
   4786 static void
   4787 xgs_isr(bkn_switch_info_t *sinfo)
   4788 {
   4789     uint32_t irq_stat;
   4790     int rx_dcbs_done;
   4791 
   4792     DEV_READ32(sinfo, CMIC_IRQ_STATr, &irq_stat);
   4793     if ((irq_stat & sinfo->irq_mask) == 0) {
   4794         /* Not ours */
   4795         return;
   4796     }
   4797     sinfo->interrupts++;
   4798 
   4799     DBG_IRQ(("Got interrupt on device %d (0x%08x)\n",
   4800              sinfo->dev_no, irq_stat));
   4801 
   4802     if (use_napi) {
   4803         bkn_schedule_napi_poll(sinfo);
   4804     } else {
   4805         xgs_irq_mask_set(sinfo, 0);
   4806         do {
   4807             rx_dcbs_done = xgs_do_dma(sinfo, MAX_RX_DCBS);
   4808         } while (rx_dcbs_done);
   4809     }
   4810 
   4811     xgs_irq_mask_set(sinfo, sinfo->irq_mask);
   4812 }
   4813 
   4814 static void
   4815 xgsm_isr(bkn_switch_info_t *sinfo)
   4816 {
   4817     uint32_t irq_stat;
   4818     int rx_dcbs_done;
   4819 
   4820     DEV_READ32(sinfo, CMICM_IRQ_STATr, &irq_stat);
   4821     if ((irq_stat & sinfo->irq_mask) == 0) {
   4822         /* Not ours */
   4823         return;
   4824     }
   4825     sinfo->interrupts++;
   4826 
   4827     DBG_IRQ(("Got interrupt on device %d (0x%08x)\n",
   4828              sinfo->dev_no, irq_stat));
   4829 
   4830     if (use_napi) {
   4831         bkn_schedule_napi_poll(sinfo);
   4832     } else {
   4833         xgsm_irq_mask_set(sinfo, 0);
   4834         do {
   4835             rx_dcbs_done = xgsm_do_dma(sinfo, MAX_RX_DCBS);
   4836             if (sinfo->cdma_channels) {
   4837                 if (rx_dcbs_done >= MAX_RX_DCBS || sinfo->tx_yield) {
   4838                     /* Continuous DMA mode requires to yield timely */
   4839                     break;
   4840                 }
   4841             }
   4842         } while (rx_dcbs_done);
   4843     }
   4844 
   4845     xgsm_irq_mask_set(sinfo, sinfo->irq_mask);
   4846 }
   4847 
   4848 static void
   4849 xgsx_isr(bkn_switch_info_t *sinfo)
   4850 {
   4851     uint32_t irq_stat;
   4852     int rx_dcbs_done;
   4853 
   4854     DEV_READ32(sinfo, CMICX_IRQ_STATr, &irq_stat);
   4855     if ((irq_stat & sinfo->irq_mask) == 0) {
   4856         /* Not ours */
   4857         return;
   4858     }
   4859     sinfo->interrupts++;
   4860 
   4861     DBG_IRQ(("Got interrupt on device %d (0x%08x)\n",
   4862              sinfo->dev_no, irq_stat));
   4863 
   4864     if (use_napi) {
   4865         bkn_schedule_napi_poll(sinfo);
   4866     } else {
   4867         xgsx_irq_mask_set(sinfo, 0);
   4868         do {
   4869             rx_dcbs_done = xgsx_do_dma(sinfo, MAX_RX_DCBS);
   4870             if (sinfo->cdma_channels) {
   4871                 if (rx_dcbs_done >= MAX_RX_DCBS || sinfo->tx_yield) {
   4872                     /* Continuous DMA mode requires to yield timely */
   4873                     break;
   4874                 }
   4875             }
   4876         } while (rx_dcbs_done);
   4877     }
   4878 
   4879     xgsx_irq_mask_set(sinfo, sinfo->irq_mask);
   4880 }
   4881 
   4882 static void
   4883 bkn_isr(void *isr_data)
   4884 {
   4885     bkn_switch_info_t *sinfo = isr_data;
   4886 
   4887     /* Safe exit on SMP systems */
   4888     if (!module_initialized) {
   4889         return;
   4890     }
   4891 
   4892     /* Ensure that we do not touch registers during device reset */
   4893     if (sinfo->irq_mask == 0) {
   4894         /* Not ours */
   4895         return;
   4896     }
   4897 
   4898     spin_lock(&sinfo->lock);
   4899 
   4900     if (sinfo->napi_poll_mode) {
   4901         /* Not ours */
   4902         spin_unlock(&sinfo->lock);
   4903         return;
   4904     }
   4905 
   4906     if (DEV_IS_CMICX(sinfo)) {
   4907         xgsx_isr(sinfo);
   4908     } else if (DEV_IS_CMICM(sinfo)) {
   4909         xgsm_isr(sinfo);
   4910     } else {
   4911         xgs_isr(sinfo);
   4912     }
   4913 
   4914     spin_unlock(&sinfo->lock);
   4915 }
   4916 
   4917 #ifdef CONFIG_NET_POLL_CONTROLLER
   4918 static void
   4919 bkn_poll_controller(struct net_device *dev)
   4920 {
   4921     bkn_priv_t *priv = netdev_priv(dev);
   4922 
   4923     disable_irq(dev->irq);
   4924     bkn_isr(priv->sinfo);
   4925     enable_irq(dev->irq);
   4926 }
   4927 #endif
   4928 
   4929 static void
   4930 bkn_resume_rx(bkn_switch_info_t *sinfo)
   4931 {
   4932     bkn_desc_info_t *desc;
   4933     bkn_dcb_chain_t *dcb_chain;
   4934     uint64_t cur_halt, last_dcb, dcb_dma;
   4935     int woffset, chan, cdma_running;
   4936 
   4937     /* Resume Rx DMA on all channels */
   4938     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   4939         if (sinfo->rx[chan].use_rx_skb) {
   4940             cdma_running = 0;
   4941             bkn_api_rx_restart(sinfo, chan);
   4942             if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   4943                 cur_halt = sinfo->halt_addr[XGS_DMA_RX_CHAN + chan];
   4944                 last_dcb = sinfo->rx[chan].desc[MAX_RX_DCBS].dcb_dma;
   4945                 if (cur_halt != last_dcb) {
   4946                     desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty + 1];
   4947                     bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma);
   4948                     cdma_running = 1;
   4949                 }
   4950             }
   4951             if (!cdma_running) {
   4952                 bkn_rx_restart(sinfo, chan);
   4953             }
   4954         } else {
   4955             cdma_running = 0;
   4956             if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   4957                 if (sinfo->rx[chan].api_active) {
   4958                     dcb_chain = sinfo->rx[chan].api_dcb_chain_end;
   4959                     woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize;
   4960                     dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t);
   4961                     bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, dcb_dma);
   4962                     cdma_running = 1;
   4963                 }
   4964             }
   4965             if (!cdma_running) {
   4966                 bkn_api_rx_restart(sinfo, chan);
   4967             }
   4968         }
   4969     }
   4970 }
   4971 
   4972 static int
   4973 bkn_open(struct net_device *dev)
   4974 {
   4975     bkn_priv_t *priv = netdev_priv(dev);
   4976     bkn_switch_info_t *sinfo = priv->sinfo;
   4977     unsigned long flags;
   4978 
   4979     /* Check if base device */
   4980     if (priv->id <= 0) {
   4981         /* NAPI used only on base device */
   4982         if (use_napi) {
   4983             bkn_napi_enable(dev, &sinfo->napi);
   4984         }
   4985 
   4986         /* Start DMA when base device is started */
   4987         if (sinfo->basedev_suspended) {
   4988             spin_lock_irqsave(&sinfo->lock, flags);
   4989             dev_do_dma(sinfo, MAX_RX_DCBS);
   4990             sinfo->basedev_suspended = 0;
   4991             bkn_api_tx(sinfo);
   4992             if (!sinfo->tx.api_active) {
   4993                 bkn_resume_tx(sinfo);
   4994             }
   4995             bkn_resume_rx(sinfo);
   4996             spin_unlock_irqrestore(&sinfo->lock, flags);
   4997         }
   4998     }
   4999 
   5000     if (!sinfo->basedev_suspended) {
   5001         netif_start_queue(dev);
   5002     }
   5003 
   5004     return 0;
   5005 }
   5006 
   5007 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
   5008 static int
   5009 bkn_set_mac_address(struct net_device *dev, void *addr)
   5010 {
   5011     if (!is_valid_ether_addr(((struct sockaddr *)addr)->sa_data)) {
   5012         return -EINVAL;
   5013     }
   5014     memcpy(dev->dev_addr, ((struct sockaddr *)addr)->sa_data, dev->addr_len);
   5015     return 0;
   5016 }
   5017 #endif
   5018 
   5019 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
   5020 static int
   5021 bkn_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
   5022 {
   5023     bkn_priv_t *priv = netdev_priv(dev);
   5024     bkn_switch_info_t *sinfo = priv->sinfo;
   5025     struct hwtstamp_config config;
   5026 
   5027     if (cmd == SIOCSHWTSTAMP) {
   5028         if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) {
   5029             return -EFAULT;
   5030         }
   5031 
   5032         if (!knet_hw_tstamp_enable_cb || !knet_hw_tstamp_disable_cb ||
   5033             priv->type != KCOM_NETIF_T_PORT) {
   5034             return -ERANGE;
   5035         }
   5036 
   5037         switch (config.tx_type) {
   5038         case HWTSTAMP_TX_OFF:
   5039             knet_hw_tstamp_disable_cb(sinfo->dev_no, priv->port);
   5040             sinfo->tx_hwts = 0;
   5041             break;
   5042         case HWTSTAMP_TX_ON:
   5043             knet_hw_tstamp_enable_cb(sinfo->dev_no, priv->port);
   5044             sinfo->tx_hwts = 1;
   5045             break;
   5046         default:
   5047             return -ERANGE;
   5048         }
   5049 
   5050         switch (config.rx_filter) {
   5051         case HWTSTAMP_FILTER_NONE:
   5052             if (sinfo->rx_hwts) {
   5053                 knet_hw_tstamp_disable_cb(sinfo->dev_no, priv->port);
   5054                 sinfo->rx_hwts = 0;
   5055             }
   5056             break;
   5057         default:
   5058             if (!sinfo->rx_hwts) {
   5059                 knet_hw_tstamp_enable_cb(sinfo->dev_no, priv->port);
   5060                 sinfo->rx_hwts = 1;
   5061             }
   5062             config.rx_filter = HWTSTAMP_FILTER_ALL;
   5063             break;
   5064         }
   5065 
   5066         return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0;
   5067     }
   5068 
   5069 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
   5070     if (cmd == SIOCGHWTSTAMP) {
   5071         config.flags = 0;
   5072         config.tx_type = sinfo->tx_hwts ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
   5073         config.rx_filter = sinfo->rx_hwts ? HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE;
   5074 
   5075         return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0;
   5076     }
   5077 #endif
   5078 
   5079     return -EINVAL;
   5080 }
   5081 #endif
   5082 
   5083 static int
   5084 bkn_change_mtu(struct net_device *dev, int new_mtu)
   5085 {
   5086     int max_size = new_mtu + ETH_HLEN + VLAN_HLEN + 4;
   5087 
   5088     if (new_mtu < 68 || max_size > rx_buffer_size) {
   5089         return -EINVAL;
   5090     }
   5091     dev->mtu = new_mtu;
   5092     return 0;
   5093 }
   5094 
   5095 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
   5096 static int
   5097 bkn_poll(struct net_device *dev, int *budget)
   5098 {
   5099     bkn_priv_t *priv = netdev_priv(dev);
   5100     bkn_switch_info_t *sinfo = priv->sinfo;
   5101     int cur_budget = *budget;
   5102     int poll_again = 0;
   5103     int rx_dcbs_done;
   5104     unsigned long flags;
   5105 
   5106     spin_lock_irqsave(&sinfo->lock, flags);
   5107 
   5108     DBG_NAPI(("NAPI poll on %s.\n", dev->name));
   5109 
   5110     sinfo->napi_poll_again = 0;
   5111 
   5112     if (cur_budget > dev->quota) {
   5113         cur_budget = dev->quota;
   5114     }
   5115 
   5116     rx_dcbs_done = dev_do_dma(sinfo, cur_budget);
   5117 
   5118     *budget -= rx_dcbs_done;
   5119     cur_budget -= rx_dcbs_done;
   5120     dev->quota -= rx_dcbs_done;
   5121 
   5122     if (sinfo->napi_poll_again || cur_budget <= 0) {
   5123         poll_again = 1;
   5124         sinfo->napi_not_done++;
   5125     } else {
   5126         bkn_napi_poll_complete(sinfo);
   5127     }
   5128 
   5129     spin_unlock_irqrestore(&sinfo->lock, flags);
   5130 
   5131     return poll_again;
   5132 }
   5133 #else
   5134 static int
   5135 bkn_poll(struct napi_struct *napi, int budget)
   5136 {
   5137     bkn_switch_info_t *sinfo = container_of(napi, bkn_switch_info_t, napi);
   5138     int rx_dcbs_done;
   5139     unsigned long flags;
   5140 
   5141     spin_lock_irqsave(&sinfo->lock, flags);
   5142 
   5143     DBG_NAPI(("NAPI poll on %s.\n", sinfo->dev->name));
   5144 
   5145     sinfo->napi_poll_again = 0;
   5146 
   5147     rx_dcbs_done = dev_do_dma(sinfo, budget);
   5148 
   5149     if (sinfo->napi_poll_again || rx_dcbs_done >= budget) {
   5150         /* Force poll again */
   5151         rx_dcbs_done = budget;
   5152         sinfo->napi_not_done++;
   5153     } else {
   5154         bkn_napi_poll_complete(sinfo);
   5155     }
   5156 
   5157     spin_unlock_irqrestore(&sinfo->lock, flags);
   5158 
   5159     return rx_dcbs_done;
   5160 }
   5161 #endif
   5162 
   5163 static int
   5164 bkn_stop(struct net_device *dev)
   5165 {
   5166     bkn_priv_t *priv = netdev_priv(dev);
   5167     bkn_switch_info_t *sinfo = priv->sinfo;
   5168     unsigned long flags;
   5169 
   5170     netif_stop_queue(dev);
   5171 
   5172     /* Check if base device */
   5173     if (priv->id <= 0) {
   5174         /* NAPI used only on base device */
   5175         if (use_napi) {
   5176             bkn_napi_disable(dev, &sinfo->napi);
   5177         }
   5178         /* Suspend all devices if base device is stopped */
   5179         if (basedev_suspend) {
   5180             spin_lock_irqsave(&sinfo->lock, flags);
   5181             bkn_suspend_tx(sinfo);
   5182             sinfo->basedev_suspended = 1;
   5183             spin_unlock_irqrestore(&sinfo->lock, flags);
   5184         }
   5185     }
   5186 
   5187     return 0;
   5188 }
   5189 
   5190 /*
   5191  * Network Device Statistics.
   5192  * Cleared at init time.
   5193  */
   5194 static struct net_device_stats *
   5195 bkn_get_stats(struct net_device *dev)
   5196 {
   5197     bkn_priv_t *priv = netdev_priv(dev);
   5198 
   5199     return &priv->stats;
   5200 }
   5201 
   5202 /* Fake multicast ability */
   5203 static void
   5204 bkn_set_multicast_list(struct net_device *dev)
   5205 {
   5206 }
   5207 
   5208 static int
   5209 bkn_hw_tstamp_tx_config(bkn_switch_info_t *sinfo, struct sk_buff *skb, uint32_t *meta)
   5210 {
   5211     uint32_t *md = NULL;
   5212 
   5213     if (!knet_hw_tstamp_tx_meta_get_cb) {
   5214         return -1;
   5215     }
   5216 
   5217     KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF;
   5218     knet_hw_tstamp_tx_meta_get_cb(sinfo->dev_no, skb, &md);
   5219     if (!md) {
   5220         return -1;
   5221     }
   5222 
   5223     switch (sinfo->dcb_type) {
   5224     case 26:
   5225     case 32:
   5226     case 33:
   5227         meta[2] |= md[0];
   5228         meta[3] |= md[1];
   5229         meta[4] |= md[2];
   5230         meta[5] |= md[3];
   5231         break;
   5232     case 36:
   5233     case 38:
   5234         meta[0] |= md[0];
   5235         meta[1] |= md[1];
   5236         meta[2] |= md[2];
   5237         meta[3] |= md[3];
   5238         break;
   5239     default:
   5240         return -1;
   5241     }
   5242 
   5243     return 0;
   5244 }
   5245 
   5246 static int
   5247 bkn_tx(struct sk_buff *skb, struct net_device *dev)
   5248 {
   5249     bkn_priv_t *priv = netdev_priv(dev);
   5250     bkn_switch_info_t *sinfo = priv->sinfo;
   5251     struct sk_buff *new_skb = NULL;
   5252     unsigned char *pktdata;
   5253     int pktlen, hdrlen, taglen, rcpulen, metalen;
   5254     int sop, idx;
   5255     uint16_t tpid;
   5256     uint32_t *metadata;
   5257     unsigned long flags;
   5258 
   5259     DBG_VERB(("Netif Tx: Len=%d\n", skb->len));
   5260 
   5261     if (priv->id <= 0) {
   5262         /* Do not transmit on base device */
   5263         priv->stats.tx_dropped++;
   5264         dev_kfree_skb_any(skb);
   5265         return 0;
   5266     }
   5267 
   5268     if (!netif_carrier_ok(dev)) {
   5269         DBG_WARN(("Tx drop: Invalid RCPU encapsulation\n"));
   5270         priv->stats.tx_dropped++;
   5271         sinfo->tx.pkts_d_no_link++;
   5272         dev_kfree_skb_any(skb);
   5273         return 0;
   5274     }
   5275 
   5276     spin_lock_irqsave(&sinfo->lock, flags);
   5277 
   5278     if (sinfo->tx.free > 1) {
   5279         bkn_desc_info_t *desc = &sinfo->tx.desc[sinfo->tx.cur];
   5280         uint32_t *dcb, *meta;
   5281 
   5282         pktdata = skb->data;
   5283         pktlen = skb->len;
   5284         hdrlen = (sinfo->cmic_type == 'x' ) ? ((device_is_dnx(sinfo)) ? priv->system_headers_size: PKT_TX_HDR_SIZE) : 0;
   5285         rcpulen = 0;
   5286         sop = 0;
   5287 
   5288         if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) {
   5289             rcpulen = RCPU_HDR_SIZE;
   5290             if (skb->len < (rcpulen + 14)) {
   5291                 DBG_WARN(("Tx drop: Invalid RCPU encapsulation\n"));
   5292                 priv->stats.tx_dropped++;
   5293                 sinfo->tx.pkts_d_rcpu_encap++;
   5294                 dev_kfree_skb_any(skb);
   5295                 spin_unlock_irqrestore(&sinfo->lock, flags);
   5296                 return 0;
   5297             }
   5298             if (check_rcpu_signature &&
   5299                 ((skb->data[18] << 8) | skb->data[19]) != sinfo->rcpu_sig) {
   5300                 DBG_WARN(("Tx drop: Invalid RCPU signature\n"));
   5301                 priv->stats.tx_dropped++;
   5302                 sinfo->tx.pkts_d_rcpu_sig++;
   5303                 dev_kfree_skb_any(skb);
   5304                 spin_unlock_irqrestore(&sinfo->lock, flags);
   5305                 return 0;
   5306             }
   5307             if (skb->data[21] & RCPU_F_MODHDR) {
   5308                 sop = skb->data[RCPU_HDR_SIZE];
   5309                 switch (sop) {
   5310                 case 0xff:
   5311                 case 0x81:
   5312                 case 0xfb:
   5313                 case 0xfc:
   5314                     break;
   5315                 default:
   5316                     DBG_WARN(("Tx drop: Invalid RCPU meta data\n"));
   5317                     priv->stats.tx_dropped++;
   5318                     sinfo->tx.pkts_d_rcpu_meta++;
   5319                     dev_kfree_skb_any(skb);
   5320                     spin_unlock_irqrestore(&sinfo->lock, flags);
   5321                     return 0;
   5322                 }
   5323                 if (sinfo->cmic_type != 'x') {
   5324                     rcpulen += RCPU_TX_META_SIZE;
   5325                 }
   5326             }
   5327             /* Skip over RCPU encapsulation */
   5328             pktdata = &skb->data[rcpulen];
   5329             pktlen -= rcpulen;
   5330 
   5331             /* CPU packets require tag */
   5332             if (sop == 0) {
   5333                 hdrlen = 0;
   5334                 tpid = (pktdata[12] << 8) | pktdata[13];
   5335                 if (tpid != 0x8100) {
   5336                     if (skb_header_cloned(skb)) {
   5337                         /* Current SKB cannot be modified */
   5338                         DBG_SKB(("Realloc Tx SKB\n"));
   5339                         new_skb = dev_alloc_skb(pktlen + TAG_SZ + FCS_SZ);
   5340                         if (new_skb == NULL) {
   5341                             DBG_WARN(("Tx drop: No SKB memory\n"));
   5342                             priv->stats.tx_dropped++;
   5343                             sinfo->tx.pkts_d_no_skb++;
   5344                             dev_kfree_skb_any(skb);
   5345                             spin_unlock_irqrestore(&sinfo->lock, flags);
   5346                             return 0;
   5347                         }
   5348                         memcpy(new_skb->data, pktdata, 12);
   5349                         memcpy(&new_skb->data[16], &pktdata[12], pktlen - 12);
   5350                         skb_put(new_skb, pktlen + TAG_SZ);
   5351                         dev_kfree_skb_any(skb);
   5352                         skb = new_skb;
   5353                         pktdata = skb->data;
   5354                         rcpulen = 0;
   5355                     } else {
   5356                         /* Add tag to RCPU header space */
   5357                         DBG_SKB(("Expand into unused RCPU header\n"));
   5358                         rcpulen -= TAG_SZ;
   5359                         pktdata = &skb->data[rcpulen];
   5360                         for (idx = 0; idx < 12; idx++) {
   5361                             pktdata[idx] = pktdata[idx + TAG_SZ];
   5362                         }
   5363                     }
   5364                     pktdata[12] = 0x81;
   5365                     pktdata[13] = 0x00;
   5366                     pktdata[14] = (priv->vlan >> 8) & 0xf;
   5367                     pktdata[15] = priv->vlan & 0xff;
   5368                     pktlen += TAG_SZ;
   5369                 }
   5370             }
   5371         } else {
   5372             if (sinfo->cmic_type == 'x' && priv->port >= 0) {
   5373                 if (skb_header_cloned(skb) || skb_headroom(skb) < hdrlen + 4) {
   5374                     /* Current SKB cannot be modified */
   5375                     DBG_SKB(("Realloc Tx SKB\n"));
   5376                     new_skb = dev_alloc_skb(pktlen + hdrlen + 4 + FCS_SZ);
   5377                     if (new_skb == NULL) {
   5378                         DBG_WARN(("Tx drop: No SKB memory\n"));
   5379                         priv->stats.tx_dropped++;
   5380                         sinfo->tx.pkts_d_no_skb++;
   5381                         dev_kfree_skb_any(skb);
   5382                         spin_unlock_irqrestore(&sinfo->lock, flags);
   5383                         return 0;
   5384                     }
   5385                     if (!device_is_dnx(sinfo))
   5386                     {
   5387                         skb_reserve(new_skb, 4);
   5388                     }
   5389                     memcpy(new_skb->data + hdrlen, skb->data, pktlen);
   5390                     skb_put(new_skb, pktlen + hdrlen);
   5391                     dev_kfree_skb_any(skb);
   5392                     skb = new_skb;
   5393                 } else {
   5394                     DBG_SKB(("Expand Tx SKB\n"));
   5395                     skb_push(skb, hdrlen);
   5396                 }
   5397                 memset(skb->data, 0, hdrlen);
   5398                 pktdata = skb->data;
   5399                 pktlen += hdrlen;
   5400             } else {
   5401                 hdrlen = 0;
   5402             }
   5403 
   5404             if (priv->port < 0 || (priv->flags & KCOM_NETIF_F_ADD_TAG)) {
   5405                 DBG_DUNE(("ADD VLAN TAG\n"));
   5406                 /* Need to add VLAN tag if packet is untagged */
   5407                 tpid = (skb->data[hdrlen + 12] << 8) | skb->data[hdrlen + 13];
   5408                 if (tpid != 0x8100) {
   5409                     if (skb_header_cloned(skb) || skb_headroom(skb) < 4) {
   5410                         /* Current SKB cannot be modified */
   5411                         DBG_SKB(("Realloc Tx SKB\n"));
   5412                         new_skb = dev_alloc_skb(pktlen + TAG_SZ + FCS_SZ);
   5413                         if (new_skb == NULL) {
   5414                             DBG_WARN(("Tx drop: No SKB memory\n"));
   5415                             priv->stats.tx_dropped++;
   5416                             sinfo->tx.pkts_d_no_skb++;
   5417                             dev_kfree_skb_any(skb);
   5418                             spin_unlock_irqrestore(&sinfo->lock, flags);
   5419                             return 0;
   5420                         }
   5421                         memcpy(new_skb->data, skb->data, hdrlen + 12);
   5422                         memcpy(&new_skb->data[hdrlen + 16], &skb->data[hdrlen + 12],
   5423                                pktlen - hdrlen - 12);
   5424                         skb_put(new_skb, pktlen + TAG_SZ);
   5425                         dev_kfree_skb_any(skb);
   5426                         skb = new_skb;
   5427                     } else {
   5428                         /* Add tag to existing buffer */
   5429                         DBG_SKB(("Expand Tx SKB\n"));
   5430                         skb_push(skb, TAG_SZ);
   5431                         for (idx = 0; idx < hdrlen + 12; idx++) {
   5432                             skb->data[idx] = skb->data[idx + TAG_SZ];
   5433                         }
   5434                     }
   5435                     pktdata = skb->data;
   5436                     pktdata[hdrlen + 12] = 0x81;
   5437                     pktdata[hdrlen + 13] = 0x00;
   5438                     pktdata[hdrlen + 14] = (priv->vlan >> 8) & 0xf;
   5439                     pktdata[hdrlen + 15] = priv->vlan & 0xff;
   5440                     pktlen += TAG_SZ;
   5441                 }
   5442             }
   5443         }
   5444 
   5445         /* Pad packet if needed */
   5446         taglen = 0;
   5447         tpid = (pktdata[hdrlen + 12] << 8) | pktdata[hdrlen + 13];
   5448         if (tpid == 0x8100) {
   5449             taglen = 4;
   5450         }
   5451         if (pktlen < (60 + taglen + hdrlen)) {
   5452             pktlen = (60 + taglen + hdrlen);
   5453             if (SKB_PADTO(skb, pktlen) != 0) {
   5454                 DBG_WARN(("Tx drop: skb_padto failed\n"));
   5455                 priv->stats.tx_dropped++;
   5456                 sinfo->tx.pkts_d_pad_fail++;
   5457                 dev_kfree_skb_any(skb);
   5458                 spin_unlock_irqrestore(&sinfo->lock, flags);
   5459                 return 0;
   5460             }
   5461             /* skb_padto may update the skb->data pointer */
   5462             pktdata = &skb->data[rcpulen];
   5463         }
   5464 
   5465         if ((pktlen + FCS_SZ) > SOC_DCB_KNET_COUNT_MASK) {
   5466             DBG_WARN(("Tx drop: size of pkt (%d) is out of range(%d)\n",
   5467                      (pktlen + FCS_SZ), SOC_DCB_KNET_COUNT_MASK));
   5468             sinfo->tx.pkts_d_over_limit++;
   5469             priv->stats.tx_dropped++;
   5470             dev_kfree_skb_any(skb);
   5471             spin_unlock_irqrestore(&sinfo->lock, flags);
   5472             return 0;
   5473         }
   5474 
   5475         dcb = desc->dcb_mem;
   5476         meta = (sinfo->cmic_type == 'x') ? (uint32_t *)pktdata : dcb;
   5477         memset(dcb, 0, sinfo->dcb_wsize * sizeof(uint32_t));
   5478         if (priv->flags & KCOM_NETIF_F_RCPU_ENCAP) {
   5479             /* If module header SOP is non-zero, use RCPU meta data */
   5480             if (sop != 0) {
   5481                 if (sinfo->cmic_type == 'x') {
   5482                     dcb[2] |= 1 << 19;
   5483                 } else {
   5484                     metalen = (sinfo->dcb_wsize - 3) * sizeof(uint32_t);
   5485                     if (metalen > RCPU_TX_META_SIZE) {
   5486                         metalen = RCPU_TX_META_SIZE;
   5487                     }
   5488                     metadata = (uint32_t *)&skb->data[RCPU_HDR_SIZE];
   5489                     for (idx = 0; idx < BYTES2WORDS(metalen); idx++) {
   5490                         dcb[idx + 2] = ntohl(metadata[idx]);
   5491                     }
   5492                     dcb[1] |= 1 << 19;
   5493                 }
   5494             }
   5495         } else if (priv->port >= 0) {
   5496             /* Send to physical port */
   5497             if (sinfo->cmic_type == 'x') {
   5498                 dcb[2] |= 1 << 19;
   5499             } else {
   5500                 dcb[1] |= 1 << 19;
   5501             }
   5502             switch (sinfo->dcb_type) {
   5503             case 23:
   5504             case 26:
   5505             case 30:
   5506             case 31:
   5507             case 34:
   5508             case 37:
   5509                 dcb[2] = 0x81000000;
   5510                 dcb[3] = priv->port;
   5511                 dcb[3] |= (priv->qnum & 0xc00) << 20;
   5512                 dcb[4] = 0x00040000;
   5513                 dcb[4] |= (priv->qnum & 0x3ff) << 8;
   5514                 break;
   5515             case 24:
   5516                 dcb[2] = 0xff000000;
   5517                 dcb[3] = 0x00000100;
   5518                 dcb[4] = priv->port;
   5519                 dcb[4] |= (priv->qnum & 0xfff) << 14;
   5520                 break;
   5521             case 28:
   5522                 {
   5523                     if (priv->type == KCOM_NETIF_T_PORT) {
   5524                         /* add PTCH ITMH header */
   5525                         if (skb_header_cloned(skb) || skb_headroom(skb) < 4) {
   5526                            /* Current SKB cannot be modified */
   5527                            DBG_SKB(("Realloc Tx SKB for DNX ITMH header\n"));
   5528                            new_skb = dev_alloc_skb(pktlen + 4 + 2 + FCS_SZ);
   5529                            if (new_skb == NULL) {
   5530                                DBG_WARN(("Tx drop: No SKB memory for DNX ITMH header\n"));
   5531                                priv->stats.tx_dropped++;
   5532                                sinfo->tx.pkts_d_no_skb++;
   5533                                dev_kfree_skb_any(skb);
   5534                                spin_unlock_irqrestore(&sinfo->lock, flags);
   5535                                return 0;
   5536                            }
   5537                            memcpy(&new_skb->data[6], skb->data, pktlen);
   5538                            skb_put(new_skb, pktlen + 6);
   5539                            dev_kfree_skb_any(skb);
   5540                            skb = new_skb;
   5541                         } else {
   5542                            /* Add tag to existing buffer */
   5543                            DBG_SKB(("Expand Tx SKB for DNX ITMH header\n"));
   5544                            skb_push(skb, 6);
   5545                         }
   5546                         pktdata = skb->data;
   5547                         pktdata[0] = 0x50;
   5548                         pktdata[1] = 0x00;
   5549                         memcpy(&pktdata[2], priv->itmh, 4);
   5550                         pktlen += 6;
   5551                     }
   5552                     else if (priv->type == KCOM_NETIF_T_VLAN) {
   5553                         /* add PTCH header */
   5554                         if (skb_header_cloned(skb) || skb_headroom(skb) < 4) {
   5555                             /* Current SKB cannot be modified */
   5556                             DBG_SKB(("Realloc Tx SKB for DNX header\n"));
   5557                             new_skb = dev_alloc_skb(pktlen + 2 + FCS_SZ);
   5558                             if (new_skb == NULL) {
   5559                                 DBG_WARN(("Tx drop: No SKB memory for DNX header\n"));
   5560                                 priv->stats.tx_dropped++;
   5561                                 sinfo->tx.pkts_d_no_skb++;
   5562                                 dev_kfree_skb_any(skb);
   5563                                 spin_unlock_irqrestore(&sinfo->lock, flags);
   5564                                 return 0;
   5565                             }
   5566                             memcpy(&new_skb->data[2], skb->data, pktlen);
   5567                             skb_put(new_skb, pktlen + 2);
   5568                             dev_kfree_skb_any(skb);
   5569                             skb = new_skb;
   5570                         } else {
   5571                             /* Add tag to existing buffer */
   5572                             DBG_SKB(("Expand Tx SKB for DNX header\n"));
   5573                             skb_push(skb, 2);
   5574                         }
   5575                         pktdata = skb->data;
   5576                         pktdata[0] = 0xd0;
   5577                         pktdata[1] = priv->port;
   5578                         pktlen += 2;
   5579                     }
   5580                     dcb[1] = pktlen;
   5581                     break;
   5582                 }
   5583             case 29:
   5584                 dcb[2] = 0x81000000;
   5585                 dcb[3] = priv->port;
   5586                 dcb[4] = 0x00100000;
   5587                 dcb[4] |= (priv->qnum & 0xfff) << 8;
   5588                 break;
   5589             case 32:
   5590                 dcb[2] = 0x81000000;
   5591                 dcb[3] = priv->port;
   5592                 dcb[4] = 0x00004000;
   5593                 dcb[4] |= (priv->qnum & 0x3f) << 8;
   5594                 break;
   5595             case 33:
   5596                 dcb[2] = 0x81000000;
   5597                 dcb[3] = (priv->port) << 2;
   5598                 dcb[4] = 0x00100000;
   5599                 dcb[4] |= (priv->qnum & 0xfff) << 8;
   5600                 break;
   5601             case 35:
   5602                 dcb[2] = 0x81000000;
   5603                 dcb[3] = (priv->port) << 4;
   5604                 dcb[4] = 0x00400000;
   5605                 dcb[4] |= (priv->qnum & 0x3fff) << 8;
   5606                 break;
   5607             case 36:
   5608                 if (sinfo->cmic_type == 'x') {
   5609                     meta[0] = htonl(0x81000000);
   5610                     meta[1] = htonl(priv->port);
   5611                     meta[2] = htonl(0x00008000 | (priv->qnum & 0x3f) << 9);
   5612                 } else {
   5613                     dcb[2] = 0x81000000;
   5614                     dcb[3] = priv->port;
   5615                     dcb[4] = 0x00008000;
   5616                     dcb[4] |= (priv->qnum & 0x3f) << 9;
   5617                 }
   5618                 break;
   5619             case 38:
   5620                 if (sinfo->cmic_type == 'x') {
   5621                     meta[0] = htonl(0x81000000);
   5622                     meta[1] = htonl(priv->port);
   5623                     meta[2] = htonl(0x00004000 | (priv->qnum & 0x3f) << 8);
   5624                 } else {
   5625                     dcb[2] = 0x81000000;
   5626                     dcb[3] = priv->port;
   5627                     dcb[4] = 0x00004000;
   5628                     dcb[4] |= (priv->qnum & 0x3f) << 8;
   5629                 }
   5630                 break;
   5631             case 39:
   5632                 if (device_is_dnx(sinfo)) {
   5633                     /*
   5634                      * if KCOM_NETIF_T_PORT, add MH+PTCH+ITMH header
   5635                      * if KCOM_NETIF_T_VLAN, add MH+PTCH+header
   5636                      */
   5637                     pktdata = skb->data;
   5638                     memcpy(&pktdata[0], priv->system_headers, priv->system_headers_size);
   5639                 }
   5640                 break;
   5641             default:
   5642                 dcb[2] = 0xff000000;
   5643                 dcb[3] = 0x00000100;
   5644                 dcb[4] = priv->port;
   5645                 break;
   5646             }
   5647         }
   5648 
   5649         /* Optional SKB updates */
   5650         if (knet_tx_cb != NULL) {
   5651             KNET_SKB_CB(skb)->netif_user_data = priv->cb_user_data;
   5652             KNET_SKB_CB(skb)->dcb_type = sinfo->dcb_type & 0xFFFF;
   5653             skb = knet_tx_cb(skb, sinfo->dev_no, meta);
   5654             if (skb == NULL) {
   5655                 /* Consumed by call-back */
   5656                 DBG_WARN(("Tx drop: Consumed by call-back\n"));
   5657                 priv->stats.tx_dropped++;
   5658                 sinfo->tx.pkts_d_callback++;
   5659                 spin_unlock_irqrestore(&sinfo->lock, flags);
   5660                 return 0;
   5661             }
   5662             /* Restore (possibly) altered packet variables
   5663              * bit0 -bit15 of dcb[1] is used to save requested byte count
   5664              */
   5665             if ((skb->len + FCS_SZ) <= SOC_DCB_KNET_COUNT_MASK) {
   5666                 pktlen = skb->len;
   5667                 if (pktlen < (60 + taglen + hdrlen)) {
   5668                     pktlen = (60 + taglen + hdrlen);
   5669                     if (SKB_PADTO(skb, pktlen) != 0) {
   5670                         DBG_WARN(("Tx drop: skb_padto failed\n"));
   5671                         priv->stats.tx_dropped++;
   5672                         sinfo->tx.pkts_d_pad_fail++;
   5673                         dev_kfree_skb_any(skb);
   5674                         spin_unlock_irqrestore(&sinfo->lock, flags);
   5675                         return 0;
   5676                     }
   5677                     DBG_SKB(("Packet padded to %d bytes after tx callback\n", pktlen));
   5678                 }
   5679                 pktdata = skb->data;
   5680                 if (sinfo->cmic_type == 'x') {
   5681                     meta = (uint32_t *)pktdata;
   5682                 }
   5683             } else {
   5684                 DBG_WARN(("Tx drop: size of pkt (%d) is out of range(%d)\n",
   5685                          (pktlen + FCS_SZ), SOC_DCB_KNET_COUNT_MASK));
   5686                 sinfo->tx.pkts_d_over_limit++;
   5687                 priv->stats.tx_dropped++;
   5688                 sinfo->tx.pkts_d_callback++;
   5689                 dev_kfree_skb_any(skb);
   5690                 spin_unlock_irqrestore(&sinfo->lock, flags);
   5691                 return 0;
   5692             }
   5693         }
   5694 
   5695         /* Do Tx timestamping */
   5696         if (priv->port >= 0) {
   5697             if (bkn_skb_tx_flags(skb) & SKBTX_HW_TSTAMP && sinfo->tx_hwts) {
   5698                 KNET_SKB_CB(skb)->port = priv->port;
   5699                 bkn_hw_tstamp_tx_config(sinfo, skb, meta);
   5700                 bkn_skb_tx_flags(skb) |= SKBTX_IN_PROGRESS;
   5701             }
   5702             bkn_skb_tx_timestamp(skb);
   5703         }
   5704 
   5705         /* Prepare for DMA */
   5706         desc->skb = skb;
   5707         /* Add FCS bytes */
   5708         pktlen = pktlen + FCS_SZ;
   5709         desc->dma_size = pktlen;
   5710         desc->skb_dma = DMA_MAP_SINGLE(sinfo->dma_dev,
   5711                                        pktdata, desc->dma_size,
   5712                                        DMA_TODEV);
   5713         if (DMA_MAPPING_ERROR(sinfo->dma_dev, desc->skb_dma)) {
   5714             priv->stats.tx_dropped++;
   5715             dev_kfree_skb_any(skb);
   5716             spin_unlock_irqrestore(&sinfo->lock, flags);
   5717             return 0;
   5718         }
   5719         dcb[0] = desc->skb_dma;
   5720         if (sinfo->cmic_type == 'x') {
   5721             dcb[1] = DMA_TO_BUS_HI(desc->skb_dma >> 32);
   5722             dcb[2] &= ~SOC_DCB_KNET_COUNT_MASK;
   5723             dcb[2] |= pktlen;
   5724         } else {
   5725             dcb[1] &= ~SOC_DCB_KNET_COUNT_MASK;
   5726             dcb[1] |= pktlen;
   5727         }
   5728 
   5729         bkn_dump_dcb("Tx RCPU", dcb, sinfo->dcb_wsize, XGS_DMA_TX_CHAN);
   5730         DBG_DCB_TX(("Add Tx DCB @ 0x%08x (%d) [%d free] (%d bytes).\n",
   5731                     (uint32_t)desc->dcb_dma, sinfo->tx.cur,
   5732                     sinfo->tx.free, pktlen));
   5733         bkn_dump_pkt(pktdata, pktlen, XGS_DMA_TX_CHAN);
   5734 
   5735         if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) {
   5736             if (sinfo->cmic_type == 'x') {
   5737                 dcb[2] |= 1 << 24 | 1 << 16;
   5738             } else {
   5739                 dcb[1] |= 1 << 24 | 1 << 16;
   5740             }
   5741         } else {
   5742             bkn_tx_dma_start(sinfo);
   5743         }
   5744         if (++sinfo->tx.cur >= MAX_TX_DCBS) {
   5745             sinfo->tx.cur = 0;
   5746         }
   5747         sinfo->tx.free--;
   5748 
   5749         if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN) && !sinfo->tx.api_active) {
   5750             /* DMA run to the new halt location */
   5751             bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN,
   5752                           sinfo->tx.desc[sinfo->tx.cur].dcb_dma);
   5753         }
   5754 
   5755         priv->stats.tx_packets++;
   5756         priv->stats.tx_bytes += pktlen;
   5757         sinfo->tx.pkts++;
   5758     } else {
   5759         DBG_WARN(("Tx drop: No DMA resources\n"));
   5760         priv->stats.tx_dropped++;
   5761         sinfo->tx.pkts_d_dma_resrc++;
   5762         dev_kfree_skb_any(skb);
   5763     }
   5764 
   5765     /* Check our Tx resources */
   5766     if (sinfo->tx.free <= 1) {
   5767         bkn_suspend_tx(sinfo);
   5768     }
   5769 
   5770     NETDEV_UPDATE_TRANS_START_TIME(dev);
   5771 
   5772     spin_unlock_irqrestore(&sinfo->lock, flags);
   5773 
   5774     return 0;
   5775 }
   5776 
   5777 static void
   5778 bkn_timer_func(bkn_switch_info_t *sinfo)
   5779 {
   5780     unsigned long flags;
   5781     int chan;
   5782     int restart_timer;
   5783 
   5784     spin_lock_irqsave(&sinfo->lock, flags);
   5785 
   5786     sinfo->timer_runs++;
   5787 
   5788     restart_timer = 0;
   5789     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   5790         /* Restart channel if not running */
   5791         if (sinfo->rx[chan].running == 0) {
   5792             bkn_rx_refill(sinfo, chan);
   5793             if (bkn_rx_restart(sinfo, chan) != 0) {
   5794                 restart_timer = 1;
   5795             }
   5796         }
   5797     }
   5798 
   5799     if (restart_timer) {
   5800         /* Presumably still out of memory */
   5801         sinfo->timer.expires = jiffies + 1;
   5802         add_timer(&sinfo->timer);
   5803     } else {
   5804         sinfo->timer_queued = 0;
   5805     }
   5806 
   5807     spin_unlock_irqrestore(&sinfo->lock, flags);
   5808 }
   5809 
   5810 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
   5811 static void
   5812 bkn_timer(unsigned long context)
   5813 {
   5814     bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context;
   5815     return bkn_timer_func(sinfo);
   5816 }
   5817 #else
   5818 static void
   5819 bkn_timer(struct timer_list *t)
   5820 {
   5821     bkn_switch_info_t *sinfo = from_timer(sinfo, t, timer);
   5822     return bkn_timer_func(sinfo);
   5823 }
   5824 #endif
   5825 
   5826 static void
   5827 bkn_rx_add_tokens(bkn_switch_info_t *sinfo, int chan)
   5828 {
   5829     unsigned long cur_jif, ticks;
   5830     uint32_t tokens_per_tick;
   5831     bkn_desc_info_t *desc;
   5832 
   5833     tokens_per_tick = sinfo->rx[chan].rate_max / HZ;
   5834     cur_jif = jiffies;
   5835     ticks = cur_jif - sinfo->rx[chan].tok_jif;
   5836     sinfo->rx[chan].tokens += ticks * tokens_per_tick;
   5837     sinfo->rx[chan].tok_jif = cur_jif;
   5838     if (sinfo->rx[chan].tokens > sinfo->rx[chan].burst_max) {
   5839         sinfo->rx[chan].tokens = sinfo->rx[chan].burst_max;
   5840     }
   5841 
   5842     /* Restart channel if Rx is suppressed */
   5843     if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   5844         bkn_rx_refill(sinfo, chan);
   5845         desc = &sinfo->rx[chan].desc[sinfo->rx[chan].dirty];
   5846         if (desc->dcb_dma == sinfo->halt_addr[XGS_DMA_RX_CHAN + chan]) {
   5847             desc = &sinfo->rx[chan].desc[MAX_RX_DCBS];
   5848             bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, desc->dcb_dma);
   5849         }
   5850     } else {
   5851         if (sinfo->rx[chan].running == 0) {
   5852             bkn_rx_refill(sinfo, chan);
   5853             bkn_rx_restart(sinfo, chan);
   5854         }
   5855     }
   5856 }
   5857 
   5858 static void
   5859 bkn_rxtick_func(bkn_switch_info_t *sinfo)
   5860 {
   5861     unsigned long flags;
   5862     unsigned long cur_jif, ticks;
   5863     uint32_t pkt_diff;
   5864     int chan;
   5865 
   5866     spin_lock_irqsave(&sinfo->lock, flags);
   5867 
   5868     sinfo->rxtick.expires = jiffies + sinfo->rxtick_jiffies;
   5869 
   5870     /* For debug purposes we maintain a rough actual packet rate */
   5871     if (++sinfo->rxticks >= sinfo->rxticks_per_sec) {
   5872         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   5873             pkt_diff = sinfo->rx[chan].pkts - sinfo->rx[chan].pkts_ref;
   5874             cur_jif = jiffies;
   5875             ticks = cur_jif - sinfo->rx[chan].rate_jif;
   5876             sinfo->rx[chan].rate = (pkt_diff * HZ) / ticks;
   5877             sinfo->rx[chan].rate_jif = cur_jif;
   5878             sinfo->rx[chan].pkts_ref = sinfo->rx[chan].pkts;
   5879         }
   5880         sinfo->rxticks = 0;
   5881     }
   5882 
   5883     /* Update tokens for Rx rate control */
   5884     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   5885         if (sinfo->rx[chan].tokens < sinfo->rx[chan].burst_max) {
   5886             bkn_rx_add_tokens(sinfo, chan);
   5887         }
   5888     }
   5889 
   5890     spin_unlock_irqrestore(&sinfo->lock, flags);
   5891 
   5892     add_timer(&sinfo->rxtick);
   5893 }
   5894 
   5895 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
   5896 static void
   5897 bkn_rxtick(unsigned long context)
   5898 {
   5899     bkn_switch_info_t *sinfo = (bkn_switch_info_t *)context;
   5900     return bkn_rxtick_func(sinfo);
   5901 }
   5902 #else
   5903 static void
   5904 bkn_rxtick(struct timer_list *t)
   5905 {
   5906     bkn_switch_info_t *sinfo = from_timer(sinfo, t, rxtick);
   5907     return bkn_rxtick_func(sinfo);
   5908 }
   5909 #endif
   5910 
   5911 static void
   5912 bkn_rx_rate_config(bkn_switch_info_t *sinfo)
   5913 {
   5914     unsigned long flags;
   5915     int chan;
   5916     uint32_t rxticks_per_sec, rps;
   5917     uint32_t jiffies_per_rxtick;
   5918     uint32_t tokens_per_rxtick;
   5919 
   5920     spin_lock_irqsave(&sinfo->lock, flags);
   5921 
   5922     /* Calculate the minimum update frequency across all channels */
   5923     rxticks_per_sec = 1;
   5924     for (chan = 0; chan < NUM_RX_CHAN; chan++) {
   5925         if (sinfo->rx[chan].burst_max == 0) {
   5926             sinfo->rx[chan].burst_max = sinfo->rx[chan].rate_max / 10;
   5927         }
   5928         rps = sinfo->rx[chan].rate_max / sinfo->rx[chan].burst_max;
   5929         if (rxticks_per_sec < rps) {
   5930             rxticks_per_sec = rps;
   5931         }
   5932     }
   5933 
   5934     /* Convert update frequency to system ticks */
   5935     jiffies_per_rxtick = HZ / rxticks_per_sec;
   5936     if (jiffies_per_rxtick == 0) {
   5937         jiffies_per_rxtick = 1;
   5938     }
   5939     rxticks_per_sec = HZ / jiffies_per_rxtick;
   5940 
   5941     for (chan = 0; chan < NUM_RX_CHAN; chan++) {
   5942         /* Ensure that burst size satifies overall rate */
   5943         tokens_per_rxtick = sinfo->rx[chan].rate_max / rxticks_per_sec;
   5944         if (sinfo->rx[chan].burst_max < tokens_per_rxtick) {
   5945             sinfo->rx[chan].burst_max = tokens_per_rxtick;
   5946         }
   5947         /* Ensure that rate has a sane value */
   5948         if (sinfo->rx[chan].rate_max != 0) {
   5949             if (sinfo->rx[chan].rate_max < rxticks_per_sec) {
   5950                 sinfo->rx[chan].rate_max = rxticks_per_sec;
   5951             }
   5952         }
   5953         sinfo->rx[chan].tokens = sinfo->rx[chan].burst_max;
   5954     }
   5955 
   5956     /* Update timer controls */
   5957     sinfo->rxticks_per_sec = rxticks_per_sec;
   5958     sinfo->rxtick_jiffies = jiffies_per_rxtick;
   5959 
   5960     spin_unlock_irqrestore(&sinfo->lock, flags);
   5961 }
   5962 
   5963 static void
   5964 bkn_destroy_sinfo(bkn_switch_info_t *sinfo)
   5965 {
   5966     list_del(&sinfo->list);
   5967     bkn_free_dcbs(sinfo);
   5968     kfree(sinfo);
   5969 }
   5970 
   5971 static bkn_switch_info_t *
   5972 bkn_create_sinfo(int dev_no)
   5973 {
   5974     bkn_switch_info_t *sinfo;
   5975     int chan;
   5976 
   5977     if ((sinfo = kmalloc(sizeof(*sinfo), GFP_KERNEL)) == NULL) {
   5978         return NULL;
   5979     }
   5980     memset(sinfo, 0, sizeof(*sinfo));
   5981     INIT_LIST_HEAD(&sinfo->ndev_list);
   5982     INIT_LIST_HEAD(&sinfo->rxpf_list);
   5983     sinfo->base_addr = lkbde_get_dev_virt(dev_no);
   5984     sinfo->dma_dev = lkbde_get_dma_dev(dev_no);
   5985     sinfo->pdev = lkbde_get_hw_dev(dev_no);
   5986     sinfo->dev_no = dev_no;
   5987     sinfo->evt_idx = -1;
   5988 
   5989     spin_lock_init(&sinfo->lock);
   5990     skb_queue_head_init(&sinfo->tx_ptp_queue);
   5991     INIT_WORK(&sinfo->tx_ptp_work, bkn_hw_tstamp_tx_work);
   5992 
   5993 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
   5994     init_timer(&sinfo->timer);
   5995     sinfo->timer.data = (unsigned long)sinfo;
   5996     sinfo->timer.function = bkn_timer;
   5997 #else
   5998     timer_setup(&sinfo->timer, bkn_timer, 0);
   5999 #endif
   6000     sinfo->timer.expires = jiffies + 1;
   6001 
   6002     INIT_LIST_HEAD(&sinfo->tx.api_dcb_list);
   6003 
   6004     for (chan = 0; chan < NUM_RX_CHAN; chan++) {
   6005         INIT_LIST_HEAD(&sinfo->rx[chan].api_dcb_list);
   6006         sinfo->rx[chan].use_rx_skb = use_rx_skb;
   6007     }
   6008 
   6009     /*
   6010      * Check for dual DMA mode where Rx DMA channel 0 uses DMA buffers
   6011      * provided by the BCM API, and the remaining Rx DMA channel(s)
   6012      * use socket buffers (SKB) provided by the Linux kernel.
   6013      */
   6014     if (use_rx_skb == 2) {
   6015         sinfo->rx[0].use_rx_skb = 0;
   6016     }
   6017 
   6018 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0))
   6019     init_timer(&sinfo->rxtick);
   6020     sinfo->rxtick.data = (unsigned long)sinfo;
   6021     sinfo->rxtick.function = bkn_rxtick;
   6022 #else
   6023     timer_setup(&sinfo->rxtick, bkn_rxtick, 0);
   6024 #endif
   6025     sinfo->rxtick.expires = jiffies + 1;
   6026 
   6027     for (chan = 0; chan < NUM_RX_CHAN; chan++) {
   6028         sinfo->rx[chan].rate_max = rx_rate[chan];
   6029         sinfo->rx[chan].burst_max = rx_burst[chan];
   6030     }
   6031     bkn_rx_rate_config(sinfo);
   6032 
   6033     add_timer(&sinfo->rxtick);
   6034 
   6035     list_add_tail(&sinfo->list, &_sinfo_list);
   6036 
   6037     return sinfo;
   6038 }
   6039 
   6040 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
   6041 static const struct net_device_ops bkn_netdev_ops = {
   6042     .ndo_open            = bkn_open,
   6043     .ndo_stop            = bkn_stop,
   6044     .ndo_start_xmit      = bkn_tx,
   6045     .ndo_get_stats       = bkn_get_stats,
   6046     .ndo_validate_addr   = eth_validate_addr,
   6047     .ndo_set_rx_mode     = bkn_set_multicast_list,
   6048     .ndo_set_mac_address = bkn_set_mac_address,
   6049     .ndo_do_ioctl        = bkn_ioctl,
   6050     .ndo_tx_timeout      = NULL,
   6051     .ndo_change_mtu      = bkn_change_mtu,
   6052 #ifdef CONFIG_NET_POLL_CONTROLLER
   6053     .ndo_poll_controller = bkn_poll_controller,
   6054 #endif
   6055 };
   6056 #endif
   6057 
   6058 static void
   6059 bkn_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
   6060 {
   6061     strlcpy(drvinfo->driver, "bcm-knet", sizeof(drvinfo->driver));
   6062     snprintf(drvinfo->version, sizeof(drvinfo->version), "%d", KCOM_VERSION);
   6063     strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
   6064     strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info));
   6065 }
   6066 
   6067 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
   6068 static int
   6069 bkn_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
   6070 {
   6071     bkn_priv_t *priv = netdev_priv(dev);
   6072     bkn_switch_info_t *sinfo = priv->sinfo;
   6073 
   6074     switch (sinfo->dcb_type) {
   6075     case 26:
   6076     case 32:
   6077     case 33:
   6078     case 36:
   6079     case 38:
   6080         info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
   6081                                 SOF_TIMESTAMPING_TX_SOFTWARE |
   6082                                 SOF_TIMESTAMPING_RX_HARDWARE |
   6083                                 SOF_TIMESTAMPING_RX_SOFTWARE |
   6084                                 SOF_TIMESTAMPING_SOFTWARE |
   6085                                 SOF_TIMESTAMPING_RAW_HARDWARE;
   6086         info->tx_types = 1 << HWTSTAMP_TX_OFF | 1 << HWTSTAMP_TX_ON;
   6087         info->rx_filters = 1 << HWTSTAMP_FILTER_NONE | 1 << HWTSTAMP_FILTER_ALL;
   6088         if (knet_hw_tstamp_ptp_clock_index_cb) {
   6089             info->phc_index = knet_hw_tstamp_ptp_clock_index_cb(sinfo->dev_no);
   6090         } else {
   6091             info->phc_index = -1;
   6092         }
   6093         break;
   6094     default:
   6095         info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
   6096                                 SOF_TIMESTAMPING_RX_SOFTWARE |
   6097                                 SOF_TIMESTAMPING_SOFTWARE;
   6098         info->phc_index = -1;
   6099         break;
   6100     }
   6101 
   6102     return 0;
   6103 }
   6104 #endif
   6105 
   6106 static const struct ethtool_ops bkn_ethtool_ops = {
   6107     .get_drvinfo        = bkn_get_drvinfo,
   6108 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
   6109     .get_ts_info        = bkn_get_ts_info,
   6110 #endif
   6111 };
   6112 
   6113 static struct net_device *
   6114 bkn_init_ndev(u8 *mac, char *name)
   6115 {
   6116     struct net_device *dev;
   6117 
   6118     /* Create Ethernet device */
   6119     dev = alloc_etherdev(sizeof(bkn_priv_t));
   6120 
   6121     if (dev == NULL) {
   6122         DBG_WARN(("Error allocating Ethernet device.\n"));
   6123         return NULL;
   6124     }
   6125 #ifdef SET_MODULE_OWNER
   6126     SET_MODULE_OWNER(dev);
   6127 #endif
   6128 
   6129     /* Set the device MAC address */
   6130     memcpy(dev->dev_addr, mac, 6);
   6131 
   6132     /* Device information -- not available right now */
   6133     dev->irq = 0;
   6134     dev->base_addr = 0;
   6135 
   6136     /* Default MTU should not exceed MTU of switch front-panel ports */
   6137     dev->mtu = default_mtu;
   6138     if (dev->mtu == 0) {
   6139         dev->mtu = rx_buffer_size;
   6140     }
   6141 
   6142     /* Device vectors */
   6143 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
   6144     dev->netdev_ops = &bkn_netdev_ops;
   6145 #else
   6146     dev->open = bkn_open;
   6147     dev->hard_start_xmit = bkn_tx;
   6148     dev->stop = bkn_stop;
   6149     dev->set_multicast_list = bkn_set_multicast_list;
   6150     dev->do_ioctl = NULL;
   6151     dev->get_stats = bkn_get_stats;
   6152     dev->change_mtu = bkn_change_mtu;
   6153 #ifdef CONFIG_NET_POLL_CONTROLLER
   6154     dev->poll_controller = bkn_poll_controller;
   6155 #endif
   6156 #endif
   6157     dev->ethtool_ops = &bkn_ethtool_ops;
   6158     if (name && *name) {
   6159         strncpy(dev->name, name, IFNAMSIZ-1);
   6160     }
   6161 
   6162     /* Register the kernel Ethernet device */
   6163     if (register_netdev(dev)) {
   6164         DBG_WARN(("Error registering Ethernet device.\n"));
   6165         free_netdev(dev);
   6166         return NULL;
   6167     }
   6168     DBG_VERB(("Created Ethernet device %s.\n", dev->name));
   6169 
   6170     return dev;
   6171 }
   6172 
   6173 /*
   6174  * Device Link Control Proc Read Entry
   6175  */
   6176 static int
   6177 bkn_proc_link_show(struct seq_file *m, void *v)
   6178 {
   6179     struct list_head *slist, *dlist;
   6180     struct net_device *dev;
   6181     bkn_priv_t *priv;
   6182     bkn_switch_info_t *sinfo;
   6183     unsigned long flags;
   6184 
   6185     seq_printf(m, "Software link status:\n");
   6186     list_for_each(slist, &_sinfo_list) {
   6187         sinfo = (bkn_switch_info_t *)slist;
   6188         spin_lock_irqsave(&sinfo->lock, flags);
   6189         list_for_each(dlist, &sinfo->ndev_list) {
   6190             priv = (bkn_priv_t *)dlist;
   6191             dev = priv->dev;
   6192             if (dev) {
   6193                 seq_printf(m, "  %-14s %s\n", dev->name,
   6194                            netif_carrier_ok(dev) ? "up" : "down");
   6195             }
   6196         }
   6197         spin_unlock_irqrestore(&sinfo->lock, flags);
   6198     }
   6199     return 0;
   6200 }
   6201 
   6202 static int
   6203 bkn_proc_link_open(struct inode * inode, struct file * file)
   6204 {
   6205     return single_open(file, bkn_proc_link_show, NULL);
   6206 }
   6207 
   6208 /*
   6209  * Device Link Control Proc Write Entry
   6210  *
   6211  *   Syntax:
   6212  *   <netif>=up|down
   6213  *
   6214  *   Where <netif> is a virtual network interface name.
   6215  *
   6216  *   Examples:
   6217  *   eth4=up
   6218  *   eth4=down
   6219  */
   6220 static ssize_t
   6221 bkn_proc_link_write(struct file *file, const char *buf,
   6222                     size_t count, loff_t *loff)
   6223 {
   6224     struct list_head *slist, *dlist;
   6225     struct net_device *dev;
   6226     bkn_priv_t *priv;
   6227     bkn_switch_info_t *sinfo;
   6228     unsigned long flags;
   6229     char link_str[40];
   6230     char *ptr;
   6231     char *newline;
   6232 
   6233     if (count > sizeof(link_str)) {
   6234         count = sizeof(link_str) - 1;
   6235         link_str[count] = '\0';
   6236     }
   6237     if (copy_from_user(link_str, buf, count)) {
   6238         return -EFAULT;
   6239     }
   6240     link_str[count] = 0;
   6241     newline = strchr(link_str, '\n');
   6242     if (newline) {
   6243         /* Chop off the trailing newline */
   6244         *newline = '\0';
   6245     }
   6246 
   6247     if ((ptr = strchr(link_str, '=')) == NULL &&
   6248         (ptr = strchr(link_str, ':')) == NULL) {
   6249         gprintk("Error: link syntax not recognized: '%s'\n", link_str);
   6250         return count;
   6251     }
   6252     *ptr++ = 0;
   6253 
   6254     dev = NULL;
   6255     list_for_each(slist, &_sinfo_list) {
   6256         sinfo = (bkn_switch_info_t *)slist;
   6257         spin_lock_irqsave(&sinfo->lock, flags);
   6258         list_for_each(dlist, &sinfo->ndev_list) {
   6259             priv = (bkn_priv_t *)dlist;
   6260             if (priv->dev) {
   6261                 if (strcmp(priv->dev->name, link_str) == 0) {
   6262                     dev = priv->dev;
   6263                     break;
   6264                 }
   6265             }
   6266         }
   6267         if (dev) {
   6268             if (strcmp(ptr, "up") == 0) {
   6269                 netif_carrier_on(dev);
   6270             } else if (strcmp(ptr, "down") == 0) {
   6271                 netif_carrier_off(dev);
   6272             } else {
   6273                 gprintk("Warning: unknown link state setting: '%s'\n", ptr);
   6274             }
   6275             spin_unlock_irqrestore(&sinfo->lock, flags);
   6276             return count;
   6277         }
   6278         spin_unlock_irqrestore(&sinfo->lock, flags);
   6279     }
   6280 
   6281     gprintk("Warning: unknown network interface: '%s'\n", link_str);
   6282 
   6283     return count;
   6284 }
   6285 
   6286 struct file_operations bkn_proc_link_file_ops = {
   6287     owner:      THIS_MODULE,
   6288     open:       bkn_proc_link_open,
   6289     read:       seq_read,
   6290     llseek:     seq_lseek,
   6291     write:      bkn_proc_link_write,
   6292     release:    single_release,
   6293 };
   6294 
   6295 /*
   6296  * Device Rate Control Proc Read Entry
   6297  */
   6298 static int
   6299 bkn_proc_rate_show(struct seq_file *m, void *v)
   6300 {
   6301     int unit = 0;
   6302     struct list_head *list;
   6303     bkn_switch_info_t *sinfo;
   6304     int chan;
   6305 
   6306     list_for_each(list, &_sinfo_list) {
   6307         sinfo = (bkn_switch_info_t *)list;
   6308 
   6309         seq_printf(m, "Rate control (unit %d):\n", unit);
   6310         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   6311             seq_printf(m, "  Rx%d max rate  %8u\n",
   6312                             chan, sinfo->rx[chan].rate_max);
   6313             seq_printf(m, "  Rx%d max burst %8u\n",
   6314                             chan, sinfo->rx[chan].burst_max);
   6315             seq_printf(m, "  Rx%d rate      %8u\n",
   6316                             chan, sinfo->rx[chan].rate);
   6317             seq_printf(m, "  Rx%d tokens    %8u\n",
   6318                             chan, sinfo->rx[chan].tokens);
   6319         }
   6320 
   6321         unit++;
   6322     }
   6323     return 0;
   6324 }
   6325 
   6326 static int
   6327 bkn_proc_rate_open(struct inode * inode, struct file * file)
   6328 {
   6329     return single_open(file, bkn_proc_rate_show, NULL);
   6330 }
   6331 
   6332 /*
   6333  * Device Rate Control Proc Write Entry
   6334  *
   6335  *   Syntax:
   6336  *   [<unit>:]rx_rate=<rate0>[,<rate1>[,<rate2]]
   6337  *
   6338  *   Where <rate0> is packets/sec for the first Rx DMA channel,
   6339  *   <rate1> is packets/sec for the second Rx DMA channel, etc.
   6340  *
   6341  *   Examples:
   6342  *   rx_rate=5000
   6343  *   0:rx_rate=10000,10000
   6344  *   1:rx_rate=10000,5000
   6345  */
   6346 static ssize_t
   6347 bkn_proc_rate_write(struct file *file, const char *buf,
   6348                     size_t count, loff_t *loff)
   6349 {
   6350     bkn_switch_info_t *sinfo;
   6351     char rate_str[80];
   6352     char *ptr;
   6353     int unit, chan;
   6354 
   6355     if (count > sizeof(rate_str)) {
   6356         count = sizeof(rate_str) - 1;
   6357         rate_str[count] = '\0';
   6358     }
   6359     if (copy_from_user(rate_str, buf, count)) {
   6360         return -EFAULT;
   6361     }
   6362 
   6363     unit = simple_strtol(rate_str, NULL, 10);
   6364     sinfo = bkn_sinfo_from_unit(unit);
   6365     if (sinfo == NULL) {
   6366         gprintk("Warning: unknown unit: %d\n", unit);
   6367         return count;
   6368     }
   6369 
   6370     if ((ptr = strstr(rate_str, "rx_rate=")) != NULL) {
   6371         ptr += 7;
   6372         chan = 0;
   6373         do {
   6374             ptr++;
   6375             sinfo->rx[chan].rate_max = simple_strtol(ptr, NULL, 10);
   6376         } while ((ptr = strchr(ptr, ',')) != NULL && ++chan < sinfo->rx_chans);
   6377         bkn_rx_rate_config(sinfo);
   6378     } else if ((ptr = strstr(rate_str, "rx_burst=")) != NULL) {
   6379         ptr += 8;
   6380         chan = 0;
   6381         do {
   6382             ptr++;
   6383             sinfo->rx[chan].burst_max = simple_strtol(ptr, NULL, 10);
   6384         } while ((ptr = strchr(ptr, ',')) != NULL && ++chan < sinfo->rx_chans);
   6385         bkn_rx_rate_config(sinfo);
   6386     } else {
   6387         gprintk("Warning: unknown configuration setting\n");
   6388     }
   6389 
   6390     return count;
   6391 }
   6392 
   6393 struct file_operations bkn_proc_rate_file_ops = {
   6394     owner:      THIS_MODULE,
   6395     open:       bkn_proc_rate_open,
   6396     read:       seq_read,
   6397     llseek:     seq_lseek,
   6398     write:      bkn_proc_rate_write,
   6399     release:    single_release,
   6400 };
   6401 
   6402 /*
   6403  * Driver DMA Proc Entry
   6404  *
   6405  * This output can be rather large (> PAGE_SIZE) so we use the
   6406  * seq_file interface to do the output. Special header records
   6407  * are indicated by a negative DCB index.
   6408  */
   6409 typedef struct {
   6410     int dev_no;         /* Current unit */
   6411     int rx_dma;         /* 0: Tx DMA, 1: Rx DMA*/
   6412     int ch_no;          /* DMA channel no. (Rx only) */
   6413     int idx;            /* DCB index */
   6414 } bkn_seq_dma_iter_t;
   6415 
   6416 /* From current record, move forward 'pos' records */
   6417 static int
   6418 bkn_seq_dma_next_pos(bkn_seq_dma_iter_t *iter, loff_t pos)
   6419 {
   6420     bkn_switch_info_t *sinfo;
   6421 
   6422     sinfo = bkn_sinfo_from_unit(iter->dev_no);
   6423     while (pos) {
   6424         if (iter->rx_dma) {
   6425             if (++iter->idx >= MAX_RX_DCBS + 1) {
   6426                 iter->idx = -1;
   6427                 if (++iter->ch_no >= sinfo->rx_chans) {
   6428                     iter->rx_dma = 0;
   6429                     iter->ch_no = 0;
   6430                     iter->dev_no++;
   6431                     if ((sinfo = bkn_sinfo_from_unit(iter->dev_no)) == NULL) {
   6432                         return -1;
   6433                     }
   6434                 }
   6435             }
   6436         } else {
   6437             if (++iter->idx >= MAX_TX_DCBS + 1) {
   6438                 iter->idx = -1;
   6439                 iter->rx_dma = 1;
   6440             }
   6441         }
   6442         pos--;
   6443     }
   6444     return 0;
   6445 }
   6446 
   6447 /* Initialize private data and move to requested start record */
   6448 static void *
   6449 bkn_seq_dma_start(struct seq_file *s, loff_t *pos)
   6450 {
   6451     bkn_seq_dma_iter_t *iter;
   6452 
   6453     iter = kmalloc(sizeof(bkn_seq_dma_iter_t), GFP_KERNEL);
   6454     if (!iter) {
   6455         return NULL;
   6456     }
   6457     memset(iter, 0, sizeof(*iter));
   6458     iter->idx = -2;
   6459     if (bkn_seq_dma_next_pos(iter, *pos) < 0) {
   6460         kfree(iter);
   6461         return NULL;
   6462     }
   6463     return iter;
   6464 }
   6465 
   6466 /* Move to next record */
   6467 static void *
   6468 bkn_seq_dma_next(struct seq_file *s, void *v, loff_t *pos)
   6469 {
   6470     bkn_seq_dma_iter_t *iter = (bkn_seq_dma_iter_t *)v;
   6471     void *rv = iter;
   6472 
   6473     if (bkn_seq_dma_next_pos(iter, 1) < 0) {
   6474         return NULL;
   6475     }
   6476     (*pos)++;
   6477     return rv;
   6478 }
   6479 
   6480 /* Release private data */
   6481 static void
   6482 bkn_seq_dma_stop(struct seq_file *s, void *v)
   6483 {
   6484     if (v) {
   6485         kfree(v);
   6486     }
   6487 }
   6488 
   6489 /* Print current record */
   6490 static int
   6491 bkn_seq_dma_show(struct seq_file *s, void *v)
   6492 {
   6493     bkn_seq_dma_iter_t *iter = (bkn_seq_dma_iter_t *)v;
   6494     bkn_switch_info_t *sinfo;
   6495     uint32_t *dcb = NULL;
   6496     bkn_dcb_chain_t *dcb_chain = NULL;
   6497     struct list_head *curr, *next;
   6498     unsigned long flags;
   6499     int chan, cnt;
   6500 
   6501     sinfo = bkn_sinfo_from_unit(iter->dev_no);
   6502     if (sinfo == NULL) {
   6503         /* Should not happen */
   6504         return 0;
   6505     }
   6506 
   6507     if (iter->rx_dma == 0) {
   6508         if (iter->idx == -2) {
   6509             seq_printf(s, "Pending events: 0x%x\n", sinfo->dma_events);
   6510         } else if (iter->idx == -1) {
   6511             spin_lock_irqsave(&sinfo->lock, flags);
   6512             curr = &sinfo->tx.api_dcb_list;
   6513             dcb_chain = sinfo->tx.api_dcb_chain;
   6514             while (dcb_chain) {
   6515                 seq_printf(s, "  [0x%08lx]--->\n", (unsigned long)dcb_chain->dcb_dma);
   6516                 for (cnt = 0; cnt < dcb_chain->dcb_cnt; cnt++) {
   6517                     dcb = &dcb_chain->dcb_mem[sinfo->dcb_wsize * cnt];
   6518                     if (sinfo->cmic_type == 'x') {
   6519                         seq_printf(s, "  DCB %2d: 0x%08x 0x%08x 0x%08x 0x%08x\n", cnt,
   6520                                    dcb[0], dcb[1], dcb[2], dcb[sinfo->dcb_wsize-1]);
   6521                     } else {
   6522                         seq_printf(s, "  DCB %2d: 0x%08x 0x%08x ... 0x%08x\n", cnt,
   6523                                    dcb[0], dcb[1], dcb[sinfo->dcb_wsize-1]);
   6524                     }
   6525                 }
   6526                 next = curr->next;
   6527                 if (next != &sinfo->tx.api_dcb_list) {
   6528                     dcb_chain = list_entry(next, bkn_dcb_chain_t, list);
   6529                     curr = next;
   6530                 } else {
   6531                     dcb_chain = NULL;
   6532                 }
   6533             }
   6534             dcb = NULL;
   6535             spin_unlock_irqrestore(&sinfo->lock, flags);
   6536             seq_printf(s,
   6537                        "Tx DCB info (unit %d):\n"
   6538                        "  api:   %d\n"
   6539                        "  dirty: %d\n"
   6540                        "  cur:   %d\n"
   6541                        "  free:  %d\n"
   6542                        "  pause: %s\n",
   6543                        iter->dev_no,
   6544                        sinfo->tx.api_active,
   6545                        sinfo->tx.dirty,
   6546                        sinfo->tx.cur,
   6547                        sinfo->tx.free,
   6548                        netif_queue_stopped(sinfo->dev) ? "yes" : "no");
   6549             if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) {
   6550                 bkn_desc_info_t *desc = &sinfo->tx.desc[0];
   6551                 uint64_t halt = sinfo->halt_addr[XGS_DMA_TX_CHAN];
   6552                 seq_printf(s,
   6553                            "  halt:  %d\n",
   6554                            (int)((uint32_t)(halt - desc->dcb_dma) / (sinfo->dcb_wsize * sizeof(uint32_t))));
   6555             }
   6556         } else {
   6557             dcb = sinfo->tx.desc[iter->idx].dcb_mem;
   6558             if (iter->idx == 0) {
   6559                 seq_printf(s, "  [0x%08lx]--->\n", (unsigned long)sinfo->tx.desc[0].dcb_dma);
   6560             }
   6561         }
   6562     } else {
   6563         if (iter->idx == -1) {
   6564             chan = iter->ch_no;
   6565             seq_printf(s,
   6566                        "Rx%d DCB info (unit %d):\n"
   6567                        "  api:   %d\n"
   6568                        "  dirty: %d\n"
   6569                        "  cur:   %d\n"
   6570                        "  free:  %d\n"
   6571                        "  run:   %d\n",
   6572                        chan, iter->dev_no,
   6573                        sinfo->rx[chan].api_active,
   6574                        sinfo->rx[chan].dirty,
   6575                        sinfo->rx[chan].cur,
   6576                        sinfo->rx[chan].free,
   6577                        sinfo->rx[chan].running);
   6578             if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan) && sinfo->rx[chan].use_rx_skb) {
   6579                 bkn_desc_info_t *desc = &sinfo->rx[chan].desc[0];
   6580                 uint64_t halt = sinfo->halt_addr[XGS_DMA_RX_CHAN + chan];
   6581                 seq_printf(s,
   6582                            "  halt:  %d\n",
   6583                            (int)((uint32_t)(halt - desc->dcb_dma) / (sinfo->dcb_wsize * sizeof(uint32_t))));
   6584             }
   6585         } else if (sinfo->rx[iter->ch_no].use_rx_skb) {
   6586             dcb = sinfo->rx[iter->ch_no].desc[iter->idx].dcb_mem;
   6587             if (iter->idx == 0) {
   6588                 seq_printf(s, "  [0x%08lx]--->\n", (unsigned long)sinfo->rx[iter->ch_no].desc[0].dcb_dma);
   6589             }
   6590         } else if (!sinfo->rx[iter->ch_no].use_rx_skb && iter->idx == 0) {
   6591             spin_lock_irqsave(&sinfo->lock, flags);
   6592             curr = &sinfo->rx[iter->ch_no].api_dcb_list;
   6593             dcb_chain = sinfo->rx[iter->ch_no].api_dcb_chain;
   6594             while (dcb_chain) {
   6595                 seq_printf(s, "  [0x%08lx]--->\n", (unsigned long)dcb_chain->dcb_dma);
   6596                 for (cnt = 0; cnt < dcb_chain->dcb_cnt; cnt++) {
   6597                     dcb = &dcb_chain->dcb_mem[sinfo->dcb_wsize * cnt];
   6598                     if (sinfo->cmic_type == 'x') {
   6599                         seq_printf(s, "  DCB %2d: 0x%08x 0x%08x 0x%08x 0x%08x\n", cnt,
   6600                                    dcb[0], dcb[1], dcb[2], dcb[sinfo->dcb_wsize-1]);
   6601                     } else {
   6602                         seq_printf(s, "  DCB %2d: 0x%08x 0x%08x ... 0x%08x\n", cnt,
   6603                                    dcb[0], dcb[1], dcb[sinfo->dcb_wsize-1]);
   6604                     }
   6605                 }
   6606                 next = curr->next;
   6607                 if (next != &sinfo->rx[iter->ch_no].api_dcb_list) {
   6608                     dcb_chain = list_entry(next, bkn_dcb_chain_t, list);
   6609                     curr = next;
   6610                 } else {
   6611                     dcb_chain = NULL;
   6612                 }
   6613             }
   6614             dcb = NULL;
   6615             spin_unlock_irqrestore(&sinfo->lock, flags);
   6616         }
   6617     }
   6618     if (dcb) {
   6619         if (sinfo->cmic_type == 'x') {
   6620             seq_printf(s, "  DCB %2d: 0x%08x 0x%08x 0x%08x 0x%08x\n", iter->idx,
   6621                        dcb[0], dcb[1], dcb[2], dcb[sinfo->dcb_wsize-1]);
   6622         } else {
   6623             seq_printf(s, "  DCB %2d: 0x%08x 0x%08x ... 0x%08x\n", iter->idx,
   6624                        dcb[0], dcb[1], dcb[sinfo->dcb_wsize-1]);
   6625         }
   6626     }
   6627     return 0;
   6628 }
   6629 
   6630 static struct seq_operations bkn_seq_dma_ops = {
   6631     .start = bkn_seq_dma_start,
   6632     .next  = bkn_seq_dma_next,
   6633     .stop  = bkn_seq_dma_stop,
   6634     .show  = bkn_seq_dma_show
   6635 };
   6636 
   6637 static int
   6638 bkn_seq_dma_open(struct inode *inode, struct file *file)
   6639 {
   6640     return seq_open(file, &bkn_seq_dma_ops);
   6641 };
   6642 
   6643 static struct file_operations bkn_seq_dma_file_ops = {
   6644     .owner   = THIS_MODULE,
   6645     .open    = bkn_seq_dma_open,
   6646     .read    = seq_read,
   6647     .llseek  = seq_lseek,
   6648     .release = seq_release
   6649 };
   6650 
   6651 /*
   6652  * Device Debug Control Proc Write Entry
   6653  *
   6654  *   Syntax:
   6655  *   [<unit>:]debug=<mask>
   6656  *
   6657  *   Where <mask> corresponds to the debug module parameter.
   6658  *
   6659  *   Examples:
   6660  *   debug=0xffff
   6661  *   0:debug-0x2000
   6662  */
   6663 static ssize_t
   6664 bkn_proc_debug_write(struct file *file, const char *buf,
   6665                      size_t count, loff_t *loff)
   6666 {
   6667     bkn_switch_info_t *sinfo;
   6668     char debug_str[40];
   6669     char *ptr;
   6670     int unit;
   6671 
   6672     if (count > sizeof(debug_str)) {
   6673         count = sizeof(debug_str) - 1;
   6674         debug_str[count] = '\0';
   6675     }
   6676     if (copy_from_user(debug_str, buf, count)) {
   6677         return -EFAULT;
   6678     }
   6679 
   6680     unit = simple_strtol(debug_str, NULL, 10);
   6681     sinfo = bkn_sinfo_from_unit(unit);
   6682     if (sinfo == NULL) {
   6683         gprintk("Warning: unknown unit: %d\n", unit);
   6684         return count;
   6685     }
   6686 
   6687     if ((ptr = strstr(debug_str, "debug=")) != NULL) {
   6688         ptr += 6;
   6689         debug = simple_strtol(ptr, NULL, 0);
   6690     } else {
   6691         gprintk("Warning: unknown configuration setting\n");
   6692     }
   6693 
   6694     return count;
   6695 }
   6696 
   6697 /*
   6698  * Driver Debug Proc Entry
   6699  */
   6700 static int
   6701 bkn_proc_debug_show(struct seq_file *m, void *v)
   6702 {
   6703     int unit = 0;
   6704     struct list_head *list;
   6705     bkn_switch_info_t *sinfo;
   6706 
   6707     seq_printf(m, "Configuration:\n");
   6708     seq_printf(m, "  debug:          0x%x\n", debug);
   6709     seq_printf(m, "  mac_addr:       %02x:%02x:%02x:%02x:%02x:%02x\n",
   6710                     bkn_dev_mac[0], bkn_dev_mac[1], bkn_dev_mac[2],
   6711                     bkn_dev_mac[3], bkn_dev_mac[4], bkn_dev_mac[5]);
   6712     seq_printf(m, "  rx_buffer_size: %d (0x%x)\n",
   6713                     rx_buffer_size, rx_buffer_size);
   6714     seq_printf(m, "  rcpu_mode:      %d\n", rcpu_mode);
   6715     seq_printf(m, "  rcpu_dmac:      %02x:%02x:%02x:%02x:%02x:%02x\n",
   6716                     bkn_rcpu_dmac[0], bkn_rcpu_dmac[1], bkn_rcpu_dmac[2],
   6717                     bkn_rcpu_dmac[3], bkn_rcpu_dmac[4], bkn_rcpu_dmac[5]);
   6718     seq_printf(m, "  rcpu_smac:      %02x:%02x:%02x:%02x:%02x:%02x\n",
   6719                     bkn_rcpu_smac[0], bkn_rcpu_smac[1], bkn_rcpu_smac[2],
   6720                     bkn_rcpu_smac[3], bkn_rcpu_smac[4], bkn_rcpu_smac[5]);
   6721     seq_printf(m, "  rcpu_ethertype: 0x%x\n", rcpu_ethertype);
   6722     seq_printf(m, "  rcpu_signature: 0x%x\n", rcpu_signature);
   6723     seq_printf(m, "  rcpu_vlan:      %d\n", rcpu_vlan);
   6724     seq_printf(m, "  use_rx_skb:     %d\n", use_rx_skb);
   6725     seq_printf(m, "  num_rx_prio:    %d\n", num_rx_prio);
   6726     seq_printf(m, "  check_rcpu_sig: %d\n", check_rcpu_signature);
   6727     seq_printf(m, "  default_mtu:    %d\n", default_mtu);
   6728     seq_printf(m, "  rx_sync_retry:  %d\n", rx_sync_retry);
   6729     seq_printf(m, "  use_napi:       %d\n", use_napi);
   6730     seq_printf(m, "  napi_weight:    %d\n", napi_weight);
   6731     seq_printf(m, "  basedev_susp:   %d\n", basedev_suspend);
   6732     seq_printf(m, "Thread states:\n");
   6733     seq_printf(m, "  Command thread: %d\n", bkn_cmd_ctrl.state);
   6734     seq_printf(m, "  Event thread:   %d\n", bkn_evt_ctrl.state);
   6735     seq_printf(m, "Active IOCTLs:\n");
   6736     seq_printf(m, "  Command:        %d\n", ioctl_cmd);
   6737     seq_printf(m, "  Event:          %d\n", ioctl_evt);
   6738 
   6739     list_for_each(list, &_sinfo_list) {
   6740         sinfo = (bkn_switch_info_t *)list;
   6741 
   6742         seq_printf(m, "Device %d:\n", unit);
   6743         seq_printf(m, "  base_addr:      0x%p\n", sinfo->base_addr);
   6744         seq_printf(m, "  dev_no:         %d\n", sinfo->dev_no);
   6745         seq_printf(m, "  cmic_type:      %c\n", sinfo->cmic_type);
   6746         seq_printf(m, "  dcb_type:       %d\n", sinfo->dcb_type);
   6747         seq_printf(m, "  dcb_wsize:      %d\n", sinfo->dcb_wsize);
   6748         seq_printf(m, "  pkt_hdr_size:   %d\n", sinfo->pkt_hdr_size);
   6749         seq_printf(m, "  rx_chans:       %d\n", sinfo->rx_chans);
   6750         seq_printf(m, "  cdma_chans:     0x%x\n", sinfo->cdma_channels);
   6751         seq_printf(m, "  irq_mask:       0x%x\n", sinfo->irq_mask);
   6752         seq_printf(m, "  dma_events:     0x%x\n", sinfo->dma_events);
   6753         seq_printf(m, "  dcb_dma:        0x%p\n", (void *)(sal_paddr_t)sinfo->dcb_dma);
   6754         seq_printf(m, "  dcb_mem_size:   0x%x\n", sinfo->dcb_mem_size);
   6755         seq_printf(m, "  rcpu_sig:       0x%x\n", sinfo->rcpu_sig);
   6756         seq_printf(m, "  napi_poll_mode: %d\n", sinfo->napi_poll_mode);
   6757         seq_printf(m, "  inst_id:        0x%x\n", sinfo->inst_id);
   6758         seq_printf(m, "  evt_queue:      %d\n", sinfo->evt_idx);
   6759 
   6760         unit++;
   6761     }
   6762 
   6763     return 0;
   6764 }
   6765 
   6766 static int bkn_proc_debug_open(struct inode * inode, struct file * file)
   6767 {
   6768     return single_open(file, bkn_proc_debug_show, NULL);
   6769 }
   6770 
   6771 struct file_operations bkn_proc_debug_file_ops = {
   6772     owner:      THIS_MODULE,
   6773     open:       bkn_proc_debug_open,
   6774     read:       seq_read,
   6775     llseek:     seq_lseek,
   6776     write:      bkn_proc_debug_write,
   6777     release:    single_release,
   6778 };
   6779 
   6780 /*
   6781  * Device Statistics Proc Entry
   6782  */
   6783 static int
   6784 bkn_proc_stats_show(struct seq_file *m, void *v)
   6785 {
   6786     int unit = 0;
   6787     struct list_head *list, *flist;
   6788     bkn_switch_info_t *sinfo;
   6789     bkn_filter_t *filter;
   6790     int chan;
   6791 
   6792 
   6793     list_for_each(list, &_sinfo_list) {
   6794         sinfo = (bkn_switch_info_t *)list;
   6795 
   6796         seq_printf(m, "Device stats (unit %d):\n", unit);
   6797         seq_printf(m, "  Interrupts  %10u\n", sinfo->interrupts);
   6798         seq_printf(m, "  Tx packets  %10u\n", sinfo->tx.pkts);
   6799         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   6800             seq_printf(m, "  Rx%d packets %10u\n", chan, sinfo->rx[chan].pkts);
   6801         }
   6802         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   6803             if (sinfo->interrupts == 0) {
   6804                 /* Avoid divide-by-zero */
   6805                 seq_printf(m, "  Rx%d pkts/intr        -\n", chan);
   6806             } else {
   6807                 seq_printf(m, "  Rx%d pkts/intr %8u\n",
   6808                            chan, sinfo->rx[chan].pkts / sinfo->interrupts);
   6809             }
   6810         }
   6811         seq_printf(m, "  Timer runs  %10u\n", sinfo->timer_runs);
   6812         seq_printf(m, "  NAPI reruns %10u\n", sinfo->napi_not_done);
   6813 
   6814         list_for_each(flist, &sinfo->rxpf_list) {
   6815             filter = (bkn_filter_t *)flist;
   6816 
   6817             seq_printf(m, "  Filter %d stats:\n", filter->kf.id);
   6818             seq_printf(m, "    Hits      %10lu\n", filter->hits);
   6819         }
   6820 
   6821         unit++;
   6822     }
   6823     return 0;
   6824 }
   6825 
   6826 static int bkn_proc_stats_open(struct inode * inode, struct file * file)
   6827 {
   6828     return single_open(file, bkn_proc_stats_show, NULL);
   6829 }
   6830 
   6831 /*
   6832  * Device Statistics Proc Write Entry
   6833  *
   6834  *   Syntax:
   6835  *   [<unit>:]clear[=all]
   6836  *
   6837  *   Where <mask> corresponds to the debug module parameter.
   6838  *
   6839  *   Examples:
   6840  *   clear
   6841  *   0:clear=all
   6842  */
   6843 static ssize_t
   6844 bkn_proc_stats_write(struct file *file, const char *buf,
   6845                      size_t count, loff_t *loff)
   6846 {
   6847     bkn_switch_info_t *sinfo;
   6848     struct list_head *flist;
   6849     bkn_filter_t *filter;
   6850     char debug_str[40];
   6851     char *ptr;
   6852     int unit;
   6853     int clear_mask;
   6854     int chan;
   6855 
   6856     if (count > sizeof(debug_str)) {
   6857         count = sizeof(debug_str) - 1;
   6858         debug_str[count] = '\0';
   6859     }
   6860     if (copy_from_user(debug_str, buf, count)) {
   6861         return -EFAULT;
   6862     }
   6863 
   6864     unit = simple_strtol(debug_str, NULL, 10);
   6865     sinfo = bkn_sinfo_from_unit(unit);
   6866     if (sinfo == NULL) {
   6867         gprintk("Warning: unknown unit: %d\n", unit);
   6868         return count;
   6869     }
   6870 
   6871     clear_mask = 0;
   6872     if ((ptr = strstr(debug_str, "clear=")) != NULL) {
   6873         ptr += 6;
   6874         if (strncmp(ptr, "all", 3) == 0) {
   6875             clear_mask = ~0;
   6876         }
   6877     } else if ((ptr = strstr(debug_str, "clear")) != NULL) {
   6878         clear_mask = ~0;
   6879     } else {
   6880         gprintk("Warning: unknown configuration setting\n");
   6881     }
   6882 
   6883     if (clear_mask) {
   6884         sinfo->tx.pkts = 0;
   6885         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   6886             sinfo->rx[chan].pkts = 0;
   6887         }
   6888         sinfo->interrupts = 0;
   6889         sinfo->timer_runs = 0;
   6890         sinfo->napi_not_done = 0;
   6891         list_for_each(flist, &sinfo->rxpf_list) {
   6892             filter = (bkn_filter_t *)flist;
   6893             filter->hits = 0;
   6894         }
   6895     }
   6896 
   6897     return count;
   6898 }
   6899 
   6900 struct file_operations bkn_proc_stats_file_ops = {
   6901     owner:      THIS_MODULE,
   6902     open:       bkn_proc_stats_open,
   6903     read:       seq_read,
   6904     llseek:     seq_lseek,
   6905     write:      bkn_proc_stats_write,
   6906     release:    single_release,
   6907 };
   6908 
   6909 /*
   6910  * Device Debug Statistics Proc Entry
   6911  */
   6912 static int
   6913 bkn_proc_dstats_show(struct seq_file *m, void *v)
   6914 {
   6915     int unit = 0;
   6916     struct list_head *list;
   6917     bkn_switch_info_t *sinfo;
   6918     int chan;
   6919 
   6920     list_for_each(list, &_sinfo_list) {
   6921         sinfo = (bkn_switch_info_t *)list;
   6922 
   6923         seq_printf(m, "Device debug stats (unit %d):\n", unit);
   6924         seq_printf(m, "  Tx drop no skb      %10u\n",
   6925                         sinfo->tx.pkts_d_no_skb);
   6926         seq_printf(m, "  Tx drop rcpu encap  %10u\n",
   6927                         sinfo->tx.pkts_d_rcpu_encap);
   6928         seq_printf(m, "  Tx drop rcpu sig    %10u\n",
   6929                         sinfo->tx.pkts_d_rcpu_sig);
   6930         seq_printf(m, "  Tx drop rcpu meta   %10u\n",
   6931                         sinfo->tx.pkts_d_rcpu_meta);
   6932         seq_printf(m, "  Tx drop pad failed  %10u\n",
   6933                         sinfo->tx.pkts_d_pad_fail);
   6934         seq_printf(m, "  Tx drop no resource %10u\n",
   6935                         sinfo->tx.pkts_d_dma_resrc);
   6936         seq_printf(m, "  Tx drop callback    %10u\n",
   6937                         sinfo->tx.pkts_d_callback);
   6938         seq_printf(m, "  Tx drop no link     %10u\n",
   6939                         sinfo->tx.pkts_d_no_link);
   6940         seq_printf(m, "  Tx drop oversized   %10u\n",
   6941                         sinfo->tx.pkts_d_over_limit);
   6942         seq_printf(m, "  Tx suspends         %10u\n",
   6943                         sinfo->tx.suspends);
   6944         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   6945             seq_printf(m, "  Rx%d filter to api   %10u\n",
   6946                             chan, sinfo->rx[chan].pkts_f_api);
   6947             seq_printf(m, "  Rx%d filter to netif %10u\n",
   6948                             chan, sinfo->rx[chan].pkts_f_netif);
   6949             seq_printf(m, "  Rx%d mirror to api   %10u\n",
   6950                             chan, sinfo->rx[chan].pkts_m_api);
   6951             seq_printf(m, "  Rx%d mirror to netif %10u\n",
   6952                             chan, sinfo->rx[chan].pkts_m_netif);
   6953             seq_printf(m, "  Rx%d drop no skb     %10u\n",
   6954                             chan, sinfo->rx[chan].pkts_d_no_skb);
   6955             seq_printf(m, "  Rx%d drop no match   %10u\n",
   6956                             chan, sinfo->rx[chan].pkts_d_no_match);
   6957             seq_printf(m, "  Rx%d drop unkn netif %10u\n",
   6958                             chan, sinfo->rx[chan].pkts_d_unkn_netif);
   6959             seq_printf(m, "  Rx%d drop unkn dest  %10u\n",
   6960                             chan, sinfo->rx[chan].pkts_d_unkn_dest);
   6961             seq_printf(m, "  Rx%d drop callback   %10u\n",
   6962                             chan, sinfo->rx[chan].pkts_d_callback);
   6963             seq_printf(m, "  Rx%d drop no link    %10u\n",
   6964                             chan, sinfo->rx[chan].pkts_d_no_link);
   6965             seq_printf(m, "  Rx%d sync error      %10u\n",
   6966                             chan, sinfo->rx[chan].sync_err);
   6967             seq_printf(m, "  Rx%d sync retry      %10u\n",
   6968                             chan, sinfo->rx[chan].sync_retry);
   6969             seq_printf(m, "  Rx%d sync maxloop    %10u\n",
   6970                             chan, sinfo->rx[chan].sync_maxloop);
   6971             seq_printf(m, "  Rx%d drop no buffer  %10u\n",
   6972                             chan, sinfo->rx[chan].pkts_d_no_api_buf);
   6973         }
   6974         unit++;
   6975     }
   6976     return 0;
   6977 }
   6978 
   6979 static int bkn_proc_dstats_open(struct inode * inode, struct file * file)
   6980 {
   6981     return single_open(file, bkn_proc_dstats_show, NULL);
   6982 }
   6983 
   6984 /*
   6985  * Device Debug Statistics Proc Write Entry
   6986  *
   6987  *   Syntax:
   6988  *   [<unit>:]clear[=all|tx|rx[<chan>]]
   6989  *
   6990  *   Where <mask> corresponds to the debug module parameter.
   6991  *
   6992  *   Examples:
   6993  *   clear
   6994  *   0:clear=rx1
   6995  */
   6996 static ssize_t
   6997 bkn_proc_dstats_write(struct file *file, const char *buf,
   6998                       size_t count, loff_t *loff)
   6999 {
   7000     bkn_switch_info_t *sinfo;
   7001     char debug_str[40];
   7002     char *ptr;
   7003     int unit;
   7004     int clear_mask;
   7005     int chan;
   7006 
   7007     if (count > sizeof(debug_str)) {
   7008         count = sizeof(debug_str) - 1;
   7009         debug_str[count] = '\0';
   7010     }
   7011     if (copy_from_user(debug_str, buf, count)) {
   7012         return -EFAULT;
   7013     }
   7014 
   7015     unit = simple_strtol(debug_str, NULL, 10);
   7016     sinfo = bkn_sinfo_from_unit(unit);
   7017     if (sinfo == NULL) {
   7018         gprintk("Warning: unknown unit: %d\n", unit);
   7019         return count;
   7020     }
   7021 
   7022     clear_mask = 0;
   7023     if ((ptr = strstr(debug_str, "clear=")) != NULL) {
   7024         ptr += 6;
   7025         if (strncmp(ptr, "all", 3) == 0) {
   7026             clear_mask = ~0;
   7027         } else if (strncmp(ptr, "dev", 3) == 0) {
   7028             clear_mask = 0x20;
   7029         } else if (strncmp(ptr, "tx", 2) == 0) {
   7030             clear_mask = 0x10;
   7031         } else if (strncmp(ptr, "rx0", 3) == 0) {
   7032             clear_mask = (1 << 0);
   7033         } else if (strncmp(ptr, "rx1", 3) == 0) {
   7034             clear_mask = (1 << 1);
   7035         } else if (strncmp(ptr, "rx", 2) == 0) {
   7036             clear_mask = 0xf;
   7037         }
   7038     } else if ((ptr = strstr(debug_str, "clear")) != NULL) {
   7039         clear_mask = ~0;
   7040     } else {
   7041         gprintk("Warning: unknown configuration setting\n");
   7042     }
   7043 
   7044     /* Tx counters */
   7045     if (clear_mask & 0x10) {
   7046         sinfo->tx.pkts_d_no_skb = 0;
   7047         sinfo->tx.pkts_d_rcpu_encap = 0;
   7048         sinfo->tx.pkts_d_rcpu_sig = 0;
   7049         sinfo->tx.pkts_d_rcpu_meta = 0;
   7050         sinfo->tx.pkts_d_pad_fail = 0;
   7051         sinfo->tx.pkts_d_over_limit = 0;
   7052         sinfo->tx.pkts_d_dma_resrc = 0;
   7053         sinfo->tx.suspends = 0;
   7054     }
   7055     /* Rx counters */
   7056     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   7057         if (clear_mask & (1 << chan)) {
   7058             sinfo->rx[chan].pkts_f_api = 0;
   7059             sinfo->rx[chan].pkts_f_netif = 0;
   7060             sinfo->rx[chan].pkts_m_api = 0;
   7061             sinfo->rx[chan].pkts_m_netif = 0;
   7062             sinfo->rx[chan].pkts_d_no_skb = 0;
   7063             sinfo->rx[chan].pkts_d_no_match = 0;
   7064             sinfo->rx[chan].pkts_d_unkn_netif = 0;
   7065             sinfo->rx[chan].pkts_d_unkn_dest = 0;
   7066             sinfo->rx[chan].pkts_d_no_api_buf = 0;
   7067             sinfo->rx[chan].sync_err = 0;
   7068             sinfo->rx[chan].sync_retry = 0;
   7069             sinfo->rx[chan].sync_maxloop = 0;
   7070         }
   7071     }
   7072 
   7073     return count;
   7074 }
   7075 
   7076 struct file_operations bkn_proc_dstats_file_ops = {
   7077     owner:      THIS_MODULE,
   7078     open:       bkn_proc_dstats_open,
   7079     read:       seq_read,
   7080     llseek:     seq_lseek,
   7081     write:      bkn_proc_dstats_write,
   7082     release:    single_release,
   7083 };
   7084 
   7085 static int
   7086 bkn_proc_init(void)
   7087 {
   7088     struct proc_dir_entry *entry;
   7089 
   7090     PROC_CREATE(entry, "link", 0666, bkn_proc_root, &bkn_proc_link_file_ops);
   7091     if (entry == NULL) {
   7092         return -1;
   7093     }
   7094     PROC_CREATE(entry, "rate", 0666, bkn_proc_root, &bkn_proc_rate_file_ops);
   7095     if (entry == NULL) {
   7096         return -1;
   7097     }
   7098     PROC_CREATE(entry, "dma", 0, bkn_proc_root, &bkn_seq_dma_file_ops);
   7099     if (entry == NULL) {
   7100         return -1;
   7101     }
   7102     PROC_CREATE(entry, "debug", 0666, bkn_proc_root, &bkn_proc_debug_file_ops);
   7103     if (entry == NULL) {
   7104         return -1;
   7105     }
   7106     PROC_CREATE(entry, "stats", 0666, bkn_proc_root, &bkn_proc_stats_file_ops);
   7107     if (entry == NULL) {
   7108         return -1;
   7109     }
   7110     PROC_CREATE(entry, "dstats", 0666, bkn_proc_root, &bkn_proc_dstats_file_ops);
   7111     if (entry == NULL) {
   7112         return -1;
   7113     }
   7114 
   7115     return 0;
   7116 }
   7117 
   7118 static int
   7119 bkn_proc_cleanup(void)
   7120 {
   7121     remove_proc_entry("link", bkn_proc_root);
   7122     remove_proc_entry("rate", bkn_proc_root);
   7123     remove_proc_entry("dma", bkn_proc_root);
   7124     remove_proc_entry("debug", bkn_proc_root);
   7125     remove_proc_entry("stats", bkn_proc_root);
   7126     remove_proc_entry("dstats", bkn_proc_root);
   7127     return 0;
   7128 }
   7129 
   7130 /*
   7131  * Generic module functions
   7132  */
   7133 
   7134 static int
   7135 _pprint(void)
   7136 {
   7137     pprintf("Broadcom BCM KNET Linux Network Driver\n");
   7138 
   7139     return 0;
   7140 }
   7141 
   7142 static int
   7143 bkn_knet_dma_info(kcom_msg_dma_info_t *kmsg, int len)
   7144 {
   7145     bkn_switch_info_t *sinfo;
   7146     bkn_dcb_chain_t *dcb_chain, *dcb_chain_end;
   7147     unsigned long flags;
   7148     int chan;
   7149     uint64_t dcb_dma;
   7150     int woffset;
   7151 
   7152     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7153 
   7154     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7155     if (sinfo == NULL) {
   7156         kmsg->hdr.status = KCOM_E_PARAM;
   7157         return sizeof(kcom_msg_hdr_t);
   7158     }
   7159 
   7160     dcb_chain = kmalloc(sizeof(*dcb_chain), GFP_KERNEL);
   7161     if (dcb_chain == NULL) {
   7162         gprintk("Fatal error: No memory for dcb_chain\n");
   7163         kmsg->hdr.status = KCOM_E_RESOURCE;
   7164         return sizeof(kcom_msg_hdr_t);
   7165     }
   7166     memset(dcb_chain, 0, sizeof(*dcb_chain));
   7167     dcb_chain->dcb_cnt = kmsg->dma_info.cnt;
   7168     dcb_chain->dcb_dma = kmsg->dma_info.data.dcb_start;
   7169     dcb_chain->dcb_mem = kernel_bde->p2l(sinfo->dev_no,
   7170                                          (sal_paddr_t)dcb_chain->dcb_dma);
   7171 
   7172     if (kmsg->dma_info.type == KCOM_DMA_INFO_T_TX_DCB) {
   7173         spin_lock_irqsave(&sinfo->lock, flags);
   7174 
   7175         /* Hold back packets from kernel */
   7176         bkn_suspend_tx(sinfo);
   7177 
   7178         list_add_tail(&dcb_chain->list, &sinfo->tx.api_dcb_list);
   7179 
   7180         /* Handle for Continuous DMA mode */
   7181         if (CDMA_CH(sinfo, XGS_DMA_TX_CHAN)) {
   7182             woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize + 1;
   7183             if (sinfo->cmic_type == 'x') {
   7184                 woffset += 1;
   7185             }
   7186             if ((dcb_chain->dcb_mem[woffset] & ((1 << 18) | (1 << 16))) != 0x50000) {
   7187                 gprintk("Not suitable API DCB chain for Continuous DMA mode\n");
   7188                 list_del(&dcb_chain->list);
   7189                 kfree(dcb_chain);
   7190                 kmsg->hdr.status = KCOM_E_PARAM;
   7191                 spin_unlock_irqrestore(&sinfo->lock, flags);
   7192                 return sizeof(kcom_msg_hdr_t);
   7193             }
   7194             dcb_chain_end = sinfo->tx.api_dcb_chain_end;
   7195             if (dcb_chain_end != NULL) {
   7196                 /* Stitch this chain */
   7197                 woffset = (dcb_chain_end->dcb_cnt - 1) * sinfo->dcb_wsize;
   7198                 dcb_chain_end->dcb_mem[woffset] = dcb_chain->dcb_dma;
   7199                 if (sinfo->cmic_type == 'x') {
   7200                     dcb_chain_end->dcb_mem[woffset + 1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32);
   7201                 }
   7202                 MEMORY_BARRIER;
   7203             }
   7204             sinfo->tx.api_dcb_chain_end = dcb_chain;
   7205             if (sinfo->tx.api_active) {
   7206                 /* Set new halt location */
   7207                 woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize;
   7208                 dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t);
   7209                 /* DMA run to the new halt location */
   7210                 bkn_cdma_goto(sinfo, XGS_DMA_TX_CHAN, dcb_dma);
   7211             }
   7212         }
   7213 
   7214         if (sinfo->tx.free == MAX_TX_DCBS &&
   7215             !sinfo->tx.api_active &&
   7216             !sinfo->basedev_suspended) {
   7217             bkn_api_tx(sinfo);
   7218         }
   7219 
   7220         spin_unlock_irqrestore(&sinfo->lock, flags);
   7221     } else if (kmsg->dma_info.type == KCOM_DMA_INFO_T_RX_DCB) {
   7222         spin_lock_irqsave(&sinfo->lock, flags);
   7223 
   7224         chan = kmsg->dma_info.chan - 1;
   7225         if ((chan < 0) || (chan > sinfo->rx_chans)) {
   7226             gprintk("Invalid RX DMA channel specified: %d\n",
   7227                     kmsg->dma_info.chan);
   7228             kmsg->hdr.status = KCOM_E_PARAM;
   7229             spin_unlock_irqrestore(&sinfo->lock, flags);
   7230             return sizeof(kcom_msg_hdr_t);
   7231         }
   7232 
   7233         list_add_tail(&dcb_chain->list, &sinfo->rx[chan].api_dcb_list);
   7234 
   7235         /* Handle for Continuous DMA mode */
   7236         if (CDMA_CH(sinfo, XGS_DMA_RX_CHAN + chan)) {
   7237             woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize + 1;
   7238             if (sinfo->cmic_type == 'x') {
   7239                 woffset += 1;
   7240             }
   7241             if ((dcb_chain->dcb_mem[woffset] & ((1 << 18) | (1 << 16))) != 0x50000) {
   7242                 gprintk("Not suitable API DCB chain for Continuous DMA mode\n");
   7243                 list_del(&dcb_chain->list);
   7244                 kfree(dcb_chain);
   7245                 kmsg->hdr.status = KCOM_E_PARAM;
   7246                 spin_unlock_irqrestore(&sinfo->lock, flags);
   7247                 return sizeof(kcom_msg_hdr_t);
   7248             }
   7249             dcb_chain_end = sinfo->rx[chan].api_dcb_chain_end;
   7250             if (dcb_chain_end != NULL) {
   7251                 /* Stitch this chain */
   7252                 woffset = (dcb_chain_end->dcb_cnt - 1) * sinfo->dcb_wsize;
   7253                 dcb_chain_end->dcb_mem[woffset] = dcb_chain->dcb_dma;
   7254                 if (sinfo->cmic_type == 'x') {
   7255                     dcb_chain_end->dcb_mem[woffset + 1] = DMA_TO_BUS_HI(dcb_chain->dcb_dma >> 32);
   7256                 }
   7257                 MEMORY_BARRIER;
   7258             }
   7259             sinfo->rx[chan].api_dcb_chain_end = dcb_chain;
   7260             if (!sinfo->rx[chan].use_rx_skb) {
   7261                 /* Set new halt location */
   7262                 woffset = (dcb_chain->dcb_cnt - 1) * sinfo->dcb_wsize;
   7263                 dcb_dma = dcb_chain->dcb_dma + woffset * sizeof(uint32_t);
   7264                 /* DMA run to the new halt location */
   7265                 bkn_cdma_goto(sinfo, XGS_DMA_RX_CHAN + chan, dcb_dma);
   7266             }
   7267         }
   7268 
   7269         if (sinfo->rx[chan].api_active == 0) {
   7270             bkn_api_rx_restart(sinfo, chan);
   7271         }
   7272 
   7273         spin_unlock_irqrestore(&sinfo->lock, flags);
   7274     } else {
   7275         DBG_DCB(("Unknown DCB_INFO type (%d).\n", kmsg->dma_info.type));
   7276         kfree(dcb_chain);
   7277         kmsg->hdr.status = KCOM_E_PARAM;
   7278     }
   7279 
   7280     return sizeof(kcom_msg_hdr_t);
   7281 }
   7282 
   7283 static int
   7284 bkn_create_inst(uint32 inst_id)
   7285 {
   7286     bkn_switch_info_t *sinfo;
   7287     bkn_evt_resource_t *evt;
   7288     unsigned long flags;
   7289     int i, evt_idx = -1;
   7290 
   7291     /* multiple instance mode */
   7292     for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) {
   7293         evt = &_bkn_evt[i];
   7294         if (evt->inst_id == inst_id) {
   7295             evt_idx = i;
   7296             DBG_INST(("%s evt_idx %d inst_id 0x%x\n",__FUNCTION__, i, inst_id));
   7297             break;
   7298         }
   7299         if ((_bkn_multi_inst == 0) || (evt->inst_id == 0)) {
   7300             _bkn_multi_inst ++;
   7301             evt_idx = i;
   7302             init_waitqueue_head(&evt->evt_wq);
   7303             evt->inst_id = inst_id;
   7304             DBG_INST(("%s evt_idx %d inst_id 0x%x\n",__FUNCTION__, i, inst_id));
   7305             break;
   7306         }
   7307     }
   7308 
   7309     if (evt_idx == -1) {
   7310         DBG_WARN(("Run out the event queue resource !\n"));
   7311         return -1;
   7312     }
   7313     for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) {
   7314         if (inst_id & (1 << i)) {
   7315             sinfo = bkn_sinfo_from_unit(i);
   7316             spin_lock_irqsave(&sinfo->lock, flags);
   7317             sinfo->evt_idx = evt_idx;
   7318             spin_unlock_irqrestore(&sinfo->lock, flags);
   7319             DBG_INST(("%s d(%d) evt_idx %d \n",__FUNCTION__, i, evt_idx));
   7320         }
   7321     }
   7322     return 0;
   7323 }
   7324 
   7325 /*
   7326  * Device reprobe driven by application to check if new device is probed or
   7327  * existed device is changed after inserting KNET module.
   7328  */
   7329 static int
   7330 bkn_knet_dev_reprobe(void)
   7331 {
   7332     bkn_switch_info_t *sinfo;
   7333     int i;
   7334 
   7335     for (i = 0; i < kernel_bde->num_devices(BDE_ALL_DEVICES); i++) {
   7336         sinfo = bkn_sinfo_from_unit(i);
   7337         if (sinfo == NULL) {
   7338             /* New device found after re-probe. */
   7339             if (bkn_knet_dev_init(i) < 0) {
   7340                 return -1;
   7341             }
   7342         } else {
   7343             /* Existed device reinit after re-probe. */
   7344             if (bkn_knet_dev_reinit(i) < 0) {
   7345                 return -1;
   7346             }
   7347         }
   7348     }
   7349     return 0;
   7350 }
   7351 
   7352 /* Assign the inst_id and evt_idx */
   7353 static int
   7354 bkn_knet_dev_inst_set(kcom_msg_reprobe_t *kmsg)
   7355 {
   7356     bkn_switch_info_t *sinfo;
   7357     int d = kmsg->hdr.unit;
   7358     uint32 inst = 0;
   7359     unsigned long flags;
   7360     struct list_head *list;
   7361 
   7362     sinfo = bkn_sinfo_from_unit(d);
   7363     lkbde_dev_instid_get(d, &inst);
   7364 
   7365     spin_lock_irqsave(&sinfo->lock, flags);
   7366     if (sinfo->inst_id != inst) {
   7367         /* Instance database changed, reinit the inst_id */
   7368         sinfo->inst_id = 0;
   7369         sinfo->evt_idx = -1;
   7370     }
   7371     spin_unlock_irqrestore(&sinfo->lock, flags);
   7372 
   7373     if (inst) {
   7374         if (sinfo->inst_id == 0) {
   7375             if (bkn_create_inst(inst) != 0) {
   7376                 return -1;
   7377             }
   7378         }
   7379         spin_lock_irqsave(&sinfo->lock, flags);
   7380         sinfo->inst_id = inst;
   7381         spin_unlock_irqrestore(&sinfo->lock, flags);
   7382     } else {
   7383         /* legacy mode */
   7384         list_for_each(list, &_sinfo_list) {
   7385             sinfo = (bkn_switch_info_t *)list;
   7386             spin_lock_irqsave(&sinfo->lock, flags);
   7387             sinfo->evt_idx = 0;
   7388             sinfo->inst_id = 0;
   7389             spin_unlock_irqrestore(&sinfo->lock, flags);
   7390         }
   7391     }
   7392     return 0;
   7393 }
   7394 
   7395 static int
   7396 bkn_knet_version(kcom_msg_version_t *kmsg, int len)
   7397 {
   7398     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7399     kmsg->version = KCOM_VERSION;
   7400     kmsg->netif_max = KCOM_NETIF_MAX;
   7401     kmsg->filter_max = KCOM_FILTER_MAX;
   7402 
   7403     return sizeof(kcom_msg_version_t);
   7404 }
   7405 
   7406 static int
   7407 bkn_knet_hw_reset(kcom_msg_hw_reset_t *kmsg, int len)
   7408 {
   7409     bkn_switch_info_t *sinfo;
   7410     unsigned long flags;
   7411     int chan;
   7412 
   7413     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7414 
   7415     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7416     if (sinfo == NULL) {
   7417         kmsg->hdr.status = KCOM_E_PARAM;
   7418         return sizeof(kcom_msg_hdr_t);
   7419     }
   7420 
   7421     spin_lock_irqsave(&sinfo->lock, flags);
   7422 
   7423     if (kmsg->channels == 0) {
   7424         /* Clean all if no channels specified */
   7425         bkn_dma_abort(sinfo);
   7426         bkn_clean_dcbs(sinfo);
   7427         skb_queue_purge(&sinfo->tx_ptp_queue);
   7428     } else {
   7429         if (kmsg->channels & (1 << XGS_DMA_TX_CHAN)) {
   7430             bkn_dma_abort_tx(sinfo);
   7431             bkn_clean_tx_dcbs(sinfo);
   7432             skb_queue_purge(&sinfo->tx_ptp_queue);
   7433         }
   7434         for (chan = 0; chan < sinfo->rx_chans; chan++) {
   7435             if (kmsg->channels & (1 << (XGS_DMA_RX_CHAN + chan))) {
   7436                 bkn_dma_abort_rx(sinfo, chan);
   7437                 bkn_clean_rx_dcbs(sinfo, chan);
   7438             }
   7439         }
   7440     }
   7441 
   7442     spin_unlock_irqrestore(&sinfo->lock, flags);
   7443 
   7444     return sizeof(kcom_msg_hdr_t);
   7445 }
   7446 
   7447 static int
   7448 bkn_knet_hw_init(kcom_msg_hw_init_t *kmsg, int len)
   7449 {
   7450     bkn_switch_info_t *sinfo;
   7451     uint32_t dev_type;
   7452     unsigned long flags;
   7453 
   7454     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7455 
   7456     DBG_DCB(("DCB size %d, type %d\n", kmsg->dcb_size, kmsg->dcb_type));
   7457 
   7458     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7459     if (sinfo == NULL) {
   7460         kmsg->hdr.status = KCOM_E_PARAM;
   7461         return sizeof(kcom_msg_hdr_t);
   7462     }
   7463 
   7464     spin_lock_irqsave(&sinfo->lock, flags);
   7465 
   7466     sinfo->cmic_type = kmsg->cmic_type;
   7467     sinfo->dcb_type = kmsg->dcb_type;
   7468     sinfo->dcb_wsize = BYTES2WORDS(kmsg->dcb_size);
   7469     sinfo->pkt_hdr_size = kmsg->pkt_hdr_size;
   7470     sinfo->dma_hi = kmsg->dma_hi;
   7471     sinfo->rx_chans = sinfo->cmic_type == 'x' ? NUM_CMICX_RX_CHAN : NUM_CMICM_RX_CHAN;
   7472     if (sinfo->rx_chans > NUM_RX_CHAN) {
   7473         sinfo->rx_chans = NUM_RX_CHAN;
   7474     }
   7475 
   7476     DBG_DUNE(("CMIC:%c DCB:%d WSIZE:%d DMA HI: 0x%08x HDR size: %d\n",
   7477         sinfo->cmic_type, sinfo->dcb_type, sinfo->dcb_wsize,
   7478         sinfo->dma_hi, sinfo->pkt_hdr_size));
   7479 
   7480     /* Config Continuous DMA mode */
   7481     sinfo->cdma_channels = kmsg->cdma_channels & ~(~0 << (sinfo->rx_chans + 1));
   7482 
   7483     /* Ensure 32-bit PCI DMA is mapped properly on 64-bit platforms */
   7484     dev_type = kernel_bde->get_dev_type(sinfo->dev_no);
   7485     if (dev_type & BDE_PCI_DEV_TYPE && sinfo->cmic_type != 'x') {
   7486         if (pci_set_dma_mask(sinfo->pdev, 0xffffffff)) {
   7487             spin_unlock_irqrestore(&sinfo->lock, flags);
   7488             gprintk("No suitable DMA available for SKBs\n");
   7489             kmsg->hdr.status = KCOM_E_RESOURCE;
   7490             return sizeof(kcom_msg_hdr_t);
   7491         }
   7492     }
   7493 
   7494     /* First time called we need to allocate DCBs */
   7495     if (sinfo->dcb_mem == NULL) {
   7496         if (bkn_alloc_dcbs(sinfo) < 0) {
   7497             spin_unlock_irqrestore(&sinfo->lock, flags);
   7498             kmsg->hdr.status = KCOM_E_RESOURCE;
   7499             return sizeof(kcom_msg_hdr_t);
   7500         }
   7501     }
   7502 
   7503     /* Ensure that we restart properly */
   7504     bkn_dma_abort(sinfo);
   7505     bkn_clean_dcbs(sinfo);
   7506 
   7507     if (basedev_suspend) {
   7508         if (!netif_running(sinfo->dev)) {
   7509             sinfo->basedev_suspended = 1;
   7510         }
   7511     }
   7512 
   7513     /* Ensure all interrupts are disabled, e.g. if warmbooting */
   7514     dev_irq_mask_set(sinfo, 0);
   7515 
   7516     /* Register interrupt handler */
   7517     kernel_bde->interrupt_connect(sinfo->dev_no | LKBDE_ISR2_DEV,
   7518                                   bkn_isr, sinfo);
   7519 
   7520     /* Init DCBs */
   7521     bkn_init_dcbs(sinfo);
   7522 
   7523     bkn_dma_init(sinfo);
   7524 
   7525     spin_unlock_irqrestore(&sinfo->lock, flags);
   7526 
   7527     return sizeof(kcom_msg_hdr_t);
   7528 }
   7529 
   7530 static int
   7531 bkn_knet_detach(kcom_msg_detach_t *kmsg, int len)
   7532 {
   7533     bkn_switch_info_t *sinfo;
   7534     unsigned long flags;
   7535     bkn_evt_resource_t *evt;
   7536 
   7537     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7538     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7539     if (sinfo == NULL) {
   7540         kmsg->hdr.status = KCOM_E_PARAM;
   7541         return sizeof(kcom_msg_hdr_t);
   7542     }
   7543 
   7544     spin_lock_irqsave(&sinfo->lock, flags);
   7545 
   7546     /* Create dummy event to unblock pending IOCTL */
   7547     sinfo->dma_events |= KCOM_DMA_INFO_F_TX_DONE;
   7548     evt = &_bkn_evt[sinfo->evt_idx];
   7549     evt->evt_wq_put++;
   7550     wake_up_interruptible(&evt->evt_wq);
   7551 
   7552     spin_unlock_irqrestore(&sinfo->lock, flags);
   7553 
   7554     /* Ensure that we return a valid unit number */
   7555     kmsg->hdr.unit = sinfo->dev_no;
   7556 
   7557     return sizeof(kcom_msg_detach_t);
   7558 }
   7559 
   7560 static int
   7561 bkn_knet_reprobe(kcom_msg_reprobe_t *kmsg, int len)
   7562 {
   7563     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7564 
   7565     /* Support pci hot plug and multiple instance */
   7566     if ((bkn_knet_dev_reprobe() < 0) ||
   7567         (bkn_knet_dev_inst_set(kmsg) < 0)) {
   7568         kmsg->hdr.status = KCOM_E_RESOURCE;
   7569         return sizeof(kcom_msg_reprobe_t);
   7570     }
   7571 
   7572     return sizeof(kcom_msg_reprobe_t);
   7573 }
   7574 
   7575 static int
   7576 bkn_knet_netif_create(kcom_msg_netif_create_t *kmsg, int len)
   7577 {
   7578     bkn_switch_info_t *sinfo;
   7579     struct net_device *dev;
   7580     struct list_head *list;
   7581     bkn_priv_t *priv, *lpriv;
   7582     unsigned long flags;
   7583     int found, id;
   7584     uint8 *ma;
   7585 
   7586     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7587 
   7588     switch (kmsg->netif.type) {
   7589     case KCOM_NETIF_T_VLAN:
   7590     case KCOM_NETIF_T_PORT:
   7591     case KCOM_NETIF_T_META:
   7592         break;
   7593     default:
   7594         kmsg->hdr.status = KCOM_E_PARAM;
   7595         return sizeof(kcom_msg_hdr_t);
   7596     }
   7597     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7598     if (sinfo == NULL) {
   7599         kmsg->hdr.status = KCOM_E_PARAM;
   7600         return sizeof(kcom_msg_hdr_t);
   7601     }
   7602     ma = kmsg->netif.macaddr;
   7603     if ((ma[0] | ma[1] | ma[2] | ma[3] | ma[4] | ma[5]) == 0) {
   7604         bkn_dev_mac[5]++;
   7605         ma = bkn_dev_mac;
   7606     }
   7607     if ((dev = bkn_init_ndev(ma, kmsg->netif.name)) == NULL) {
   7608         kmsg->hdr.status = KCOM_E_RESOURCE;
   7609         return sizeof(kcom_msg_hdr_t);
   7610     }
   7611     priv = netdev_priv(dev);
   7612     priv->dev = dev;
   7613     priv->sinfo = sinfo;
   7614     priv->type = kmsg->netif.type;
   7615     priv->vlan = kmsg->netif.vlan;
   7616     if (priv->type == KCOM_NETIF_T_PORT) {
   7617         priv->port = kmsg->netif.port;
   7618         if (device_is_dpp(sinfo)) {
   7619             memcpy(priv->itmh, kmsg->netif.itmh, 4);
   7620         } else if (device_is_dnx(sinfo)) {
   7621             memcpy(priv->system_headers, kmsg->netif.system_headers, kmsg->netif.system_headers_size);
   7622             priv->system_headers_size = kmsg->netif.system_headers_size;
   7623         }
   7624         priv->qnum = kmsg->netif.qnum;
   7625     } else {
   7626         if (device_is_sand(sinfo)) {
   7627             if (device_is_dpp(sinfo)) {
   7628                 priv->port = kmsg->netif.port;
   7629                 priv->qnum = kmsg->netif.qnum;
   7630             }else if (device_is_dnx(sinfo)) {
   7631                 memcpy(priv->system_headers, kmsg->netif.system_headers, kmsg->netif.system_headers_size);
   7632                 priv->system_headers_size = kmsg->netif.system_headers_size;
   7633             }
   7634         }
   7635         else {
   7636             priv->port = -1;
   7637         }
   7638     }
   7639     priv->flags = kmsg->netif.flags;
   7640     priv->cb_user_data = kmsg->netif.cb_user_data;
   7641 
   7642     /* Force RCPU encapsulation if rcpu_mode */
   7643     if (rcpu_mode) {
   7644         priv->flags |= KCOM_NETIF_F_RCPU_ENCAP;
   7645         DBG_RCPU(("RCPU auto-enabled\n"));
   7646     }
   7647 
   7648     /* Prevent (incorrect) compiler warning */
   7649     lpriv = NULL;
   7650 
   7651     spin_lock_irqsave(&sinfo->lock, flags);
   7652 
   7653     /*
   7654      * We insert network interfaces sorted by ID.
   7655      * In case an interface is destroyed, we reuse the ID
   7656      * the next time an interface is created.
   7657      */
   7658     found = 0;
   7659     id = 1;
   7660     list_for_each(list, &sinfo->ndev_list) {
   7661         lpriv = (bkn_priv_t *)list;
   7662         if (id < lpriv->id) {
   7663             found = 1;
   7664             break;
   7665         }
   7666         id = lpriv->id + 1;
   7667     }
   7668     priv->id = id;
   7669     if (found) {
   7670         /* Replace previously removed interface */
   7671         list_add_tail(&priv->list, &lpriv->list);
   7672     } else {
   7673         /* No holes - add to end of list */
   7674         list_add_tail(&priv->list, &sinfo->ndev_list);
   7675     }
   7676 
   7677     if (id < sinfo->ndev_max) {
   7678         DBG_NDEV(("Add netif ID %d to table\n", id));
   7679         sinfo->ndevs[id] = dev;
   7680     } else {
   7681         int ndev_max = sinfo->ndev_max + NDEVS_CHUNK;
   7682         int size = ndev_max * sizeof(struct net_device *);
   7683         void *ndevs = kmalloc(size, GFP_ATOMIC);
   7684         if (ndevs != NULL) {
   7685             DBG_NDEV(("Reallocate netif table for ID %d\n", id));
   7686             memset(ndevs, 0, size);
   7687             if (sinfo->ndevs != NULL) {
   7688                 size = sinfo->ndev_max * sizeof(struct net_device *);
   7689                 memcpy(ndevs, sinfo->ndevs, size);
   7690                 kfree(sinfo->ndevs);
   7691             }
   7692             sinfo->ndevs = ndevs;
   7693             sinfo->ndev_max = ndev_max;
   7694             sinfo->ndevs[id] = dev;
   7695         }
   7696     }
   7697 
   7698     spin_unlock_irqrestore(&sinfo->lock, flags);
   7699 
   7700     DBG_VERB(("Assigned ID %d to Ethernet device %s\n",
   7701               priv->id, dev->name));
   7702 
   7703     kmsg->netif.id = priv->id;
   7704     memcpy(kmsg->netif.macaddr, dev->dev_addr, 6);
   7705     memcpy(kmsg->netif.name, dev->name, KCOM_NETIF_NAME_MAX - 1);
   7706 
   7707     if (device_is_dnx(sinfo)) {
   7708         int idx = 0;
   7709         for (idx = 0; idx < priv->system_headers_size; idx++) {
   7710             DBG_DUNE(("System Header[%d]: 0x%02x\n", idx, priv->system_headers[idx]));
   7711         }
   7712     }
   7713 
   7714     return sizeof(*kmsg);
   7715 }
   7716 
   7717 static int
   7718 bkn_knet_netif_destroy(kcom_msg_netif_destroy_t *kmsg, int len)
   7719 {
   7720     bkn_switch_info_t *sinfo;
   7721     struct net_device *dev;
   7722     bkn_priv_t *priv;
   7723     struct list_head *list;
   7724     unsigned long flags;
   7725     int found;
   7726 
   7727     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7728 
   7729     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7730     if (sinfo == NULL) {
   7731         kmsg->hdr.status = KCOM_E_PARAM;
   7732         return sizeof(kcom_msg_hdr_t);
   7733     }
   7734 
   7735     spin_lock_irqsave(&sinfo->lock, flags);
   7736 
   7737     found = 0;
   7738     list_for_each(list, &sinfo->ndev_list) {
   7739         priv = (bkn_priv_t *)list;
   7740         if (kmsg->hdr.id == priv->id) {
   7741             found = 1;
   7742             break;
   7743         }
   7744     }
   7745 
   7746     if (!found) {
   7747         spin_unlock_irqrestore(&sinfo->lock, flags);
   7748         kmsg->hdr.status = KCOM_E_NOT_FOUND;
   7749         return sizeof(kcom_msg_hdr_t);
   7750     }
   7751 
   7752     list_del(&priv->list);
   7753 
   7754     if (priv->id < sinfo->ndev_max) {
   7755         sinfo->ndevs[priv->id] = NULL;
   7756     }
   7757 
   7758     spin_unlock_irqrestore(&sinfo->lock, flags);
   7759 
   7760     dev = priv->dev;
   7761     DBG_VERB(("Removing virtual Ethernet device %s (%d).\n",
   7762               dev->name, priv->id));
   7763     unregister_netdev(dev);
   7764     free_netdev(dev);
   7765 
   7766     return sizeof(kcom_msg_hdr_t);
   7767 }
   7768 
   7769 static int
   7770 bkn_knet_netif_list(kcom_msg_netif_list_t *kmsg, int len)
   7771 {
   7772     bkn_switch_info_t *sinfo;
   7773     bkn_priv_t *priv;
   7774     struct list_head *list;
   7775     unsigned long flags;
   7776     int idx;
   7777 
   7778     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7779 
   7780     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7781     if (sinfo == NULL) {
   7782         kmsg->hdr.status = KCOM_E_PARAM;
   7783         return sizeof(kcom_msg_hdr_t);
   7784     }
   7785 
   7786     spin_lock_irqsave(&sinfo->lock, flags);
   7787 
   7788     idx = 0;
   7789     list_for_each(list, &sinfo->ndev_list) {
   7790         if (idx >= KCOM_NETIF_MAX) {
   7791             DBG_WARN(("Too many network interfaces to list (max %d).\n",
   7792                       KCOM_NETIF_MAX));
   7793             break;
   7794         }
   7795         priv = (bkn_priv_t *)list;
   7796         kmsg->id[idx] = priv->id;
   7797         idx++;
   7798     }
   7799     kmsg->ifcnt = idx;
   7800 
   7801     spin_unlock_irqrestore(&sinfo->lock, flags);
   7802 
   7803     return sizeof(*kmsg) - sizeof(kmsg->id) + (idx * sizeof(kmsg->id[0]));
   7804 }
   7805 
   7806 static int
   7807 bkn_knet_netif_get(kcom_msg_netif_get_t *kmsg, int len)
   7808 {
   7809     bkn_switch_info_t *sinfo;
   7810     bkn_priv_t *priv;
   7811     unsigned long flags;
   7812 
   7813     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7814 
   7815     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7816     if (sinfo == NULL) {
   7817         kmsg->hdr.status = KCOM_E_PARAM;
   7818         return sizeof(kcom_msg_hdr_t);
   7819     }
   7820 
   7821     spin_lock_irqsave(&sinfo->lock, flags);
   7822 
   7823     priv = bkn_netif_lookup(sinfo, kmsg->hdr.id);
   7824 
   7825     if (priv == NULL) {
   7826         spin_unlock_irqrestore(&sinfo->lock, flags);
   7827         kmsg->hdr.status = KCOM_E_NOT_FOUND;
   7828         return sizeof(kcom_msg_hdr_t);
   7829     }
   7830 
   7831     memcpy(kmsg->netif.macaddr, priv->dev->dev_addr, 6);
   7832     memcpy(kmsg->netif.name, priv->dev->name, KCOM_NETIF_NAME_MAX - 1);
   7833     kmsg->netif.vlan = priv->vlan;
   7834     kmsg->netif.type = priv->type;
   7835     kmsg->netif.id = priv->id;
   7836     kmsg->netif.flags = priv->flags;
   7837 
   7838     if (priv->port < 0) {
   7839         kmsg->netif.port = 0;
   7840     } else {
   7841         kmsg->netif.port = priv->port;
   7842     }
   7843     kmsg->netif.qnum = priv->qnum;
   7844 
   7845     spin_unlock_irqrestore(&sinfo->lock, flags);
   7846 
   7847     return sizeof(*kmsg);
   7848 }
   7849 
   7850 static int
   7851 bkn_knet_filter_create(kcom_msg_filter_create_t *kmsg, int len)
   7852 {
   7853     bkn_switch_info_t *sinfo;
   7854     struct list_head *list;
   7855     bkn_filter_t *filter, *lfilter;
   7856     unsigned long flags;
   7857     int found, id;
   7858 
   7859     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7860 
   7861     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7862     if (sinfo == NULL) {
   7863         kmsg->hdr.status = KCOM_E_PARAM;
   7864         return sizeof(kcom_msg_hdr_t);
   7865     }
   7866 
   7867     switch (kmsg->filter.type) {
   7868     case KCOM_FILTER_T_RX_PKT:
   7869         break;
   7870     default:
   7871         kmsg->hdr.status = KCOM_E_PARAM;
   7872         return sizeof(kcom_msg_hdr_t);
   7873     }
   7874 
   7875     spin_lock_irqsave(&sinfo->lock, flags);
   7876 
   7877     /*
   7878      * Find available ID
   7879      */
   7880     found = 1;
   7881     id = 0;
   7882     while (found && ++id < KCOM_FILTER_MAX) {
   7883         found = 0;
   7884         list_for_each(list, &sinfo->rxpf_list) {
   7885             lfilter = (bkn_filter_t *)list;
   7886             if (id == lfilter->kf.id) {
   7887                 found = 1;
   7888                 break;
   7889             }
   7890         }
   7891     }
   7892     if (found) {
   7893         /* Too many filters */
   7894         spin_unlock_irqrestore(&sinfo->lock, flags);
   7895         kmsg->hdr.status = KCOM_E_RESOURCE;
   7896         return sizeof(kcom_msg_hdr_t);
   7897     }
   7898 
   7899     filter = kmalloc(sizeof(*filter), GFP_ATOMIC);
   7900     if (filter == NULL) {
   7901         spin_unlock_irqrestore(&sinfo->lock, flags);
   7902         kmsg->hdr.status = KCOM_E_PARAM;
   7903         return sizeof(kcom_msg_hdr_t);
   7904     }
   7905     memset(filter, 0, sizeof(*filter));
   7906     memcpy(&filter->kf, &kmsg->filter, sizeof(filter->kf));
   7907 
   7908     if (device_is_dnx(sinfo)) {
   7909         /* Information to parser Dune system headers */
   7910         sinfo->ftmh_lb_key_ext_size = kmsg->filter.ftmh_lb_key_ext_size;
   7911         sinfo->ftmh_stacking_ext_size = kmsg->filter.ftmh_stacking_ext_size;
   7912         sinfo->pph_base_size = kmsg->filter.pph_base_size;
   7913         memcpy(sinfo->pph_lif_ext_size, kmsg->filter.pph_lif_ext_size, sizeof(sinfo->pph_lif_ext_size));
   7914         sinfo->udh_enable = kmsg->filter.udh_enable;
   7915         memcpy(sinfo->udh_length_type, kmsg->filter.udh_length_type, sizeof(sinfo->udh_length_type));
   7916     }
   7917 
   7918     filter->kf.id = id;
   7919 
   7920     /* Add according to priority */
   7921     found = 0;
   7922     list_for_each(list, &sinfo->rxpf_list) {
   7923         lfilter = (bkn_filter_t *)list;
   7924         if (filter->kf.priority < lfilter->kf.priority) {
   7925             list_add_tail(&filter->list, &lfilter->list);
   7926             found = 1;
   7927             break;
   7928         }
   7929     }
   7930     if (!found) {
   7931         list_add_tail(&filter->list, &sinfo->rxpf_list);
   7932     }
   7933 
   7934     kmsg->filter.id = filter->kf.id;
   7935 
   7936     spin_unlock_irqrestore(&sinfo->lock, flags);
   7937 
   7938     DBG_VERB(("Created filter ID %d (%s).\n",
   7939               filter->kf.id, filter->kf.desc));
   7940 
   7941     if (device_is_dnx(sinfo)) {
   7942         int idx, wsize;
   7943         wsize = BYTES2WORDS(filter->kf.oob_data_size + filter->kf.pkt_data_size);
   7944         DBG_DUNE(("Filter: oob_data_size = %d pkt_data_size=%d wsize %d\n", filter->kf.oob_data_size, filter->kf.pkt_data_size, wsize));
   7945         for (idx = 0; idx < wsize; idx++)
   7946         {
   7947             DBG_DUNE(("OOB[%d]: 0x%08x [0x%08x]\n", idx, filter->kf.data.w[idx], filter->kf.mask.w[idx]));
   7948         }
   7949         DBG_DUNE(("DNX system headers parameters:LB_KEY_EXT %d, STK_EXT %d, PPH_BASE %d, LIF_EXT %d %d %d, UDH_ENA %d, %d %d %d %d\n",
   7950                   sinfo->ftmh_lb_key_ext_size, sinfo->ftmh_stacking_ext_size, sinfo->pph_base_size,
   7951                   sinfo->pph_lif_ext_size[1],sinfo->pph_lif_ext_size[2], sinfo->pph_lif_ext_size[3],
   7952                   sinfo->udh_enable, sinfo->udh_length_type[0], sinfo->udh_length_type[1], sinfo->udh_length_type[2], sinfo->udh_length_type[3]));
   7953     }
   7954 
   7955     return len;
   7956 }
   7957 
   7958 static int
   7959 bkn_knet_filter_destroy(kcom_msg_filter_destroy_t *kmsg, int len)
   7960 {
   7961     bkn_switch_info_t *sinfo;
   7962     bkn_filter_t *filter;
   7963     struct list_head *list;
   7964     unsigned long flags;
   7965     int found;
   7966 
   7967     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   7968 
   7969     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   7970     if (sinfo == NULL) {
   7971         kmsg->hdr.status = KCOM_E_PARAM;
   7972         return sizeof(kcom_msg_hdr_t);
   7973     }
   7974 
   7975     spin_lock_irqsave(&sinfo->lock, flags);
   7976 
   7977     found = 0;
   7978     list_for_each(list, &sinfo->rxpf_list) {
   7979         filter = (bkn_filter_t *)list;
   7980         if (kmsg->hdr.id == filter->kf.id) {
   7981             found = 1;
   7982             break;
   7983         }
   7984     }
   7985 
   7986     if (!found) {
   7987         spin_unlock_irqrestore(&sinfo->lock, flags);
   7988         kmsg->hdr.status = KCOM_E_NOT_FOUND;
   7989         return sizeof(kcom_msg_hdr_t);
   7990     }
   7991 
   7992     list_del(&filter->list);
   7993 
   7994     spin_unlock_irqrestore(&sinfo->lock, flags);
   7995 
   7996     DBG_VERB(("Removing filter ID %d.\n", filter->kf.id));
   7997     kfree(filter);
   7998 
   7999     return sizeof(kcom_msg_hdr_t);
   8000 }
   8001 
   8002 static int
   8003 bkn_knet_filter_list(kcom_msg_filter_list_t *kmsg, int len)
   8004 {
   8005     bkn_switch_info_t *sinfo;
   8006     bkn_filter_t *filter;
   8007     struct list_head *list;
   8008     unsigned long flags;
   8009     int idx;
   8010 
   8011     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   8012 
   8013     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   8014     if (sinfo == NULL) {
   8015         kmsg->hdr.status = KCOM_E_PARAM;
   8016         return sizeof(kcom_msg_hdr_t);
   8017     }
   8018 
   8019     spin_lock_irqsave(&sinfo->lock, flags);
   8020 
   8021     idx = 0;
   8022     list_for_each(list, &sinfo->rxpf_list) {
   8023         if (idx >= KCOM_FILTER_MAX) {
   8024             DBG_WARN(("Too many filters to list (max %d).\n",
   8025                       KCOM_FILTER_MAX));
   8026             break;
   8027         }
   8028         filter = (bkn_filter_t *)list;
   8029         kmsg->id[idx] = filter->kf.id;
   8030         idx++;
   8031     }
   8032     kmsg->fcnt = idx;
   8033 
   8034     spin_unlock_irqrestore(&sinfo->lock, flags);
   8035 
   8036     return sizeof(*kmsg) - sizeof(kmsg->id) + (idx * sizeof(kmsg->id[0]));
   8037 }
   8038 
   8039 static int
   8040 bkn_knet_filter_get(kcom_msg_filter_get_t *kmsg, int len)
   8041 {
   8042     bkn_switch_info_t *sinfo;
   8043     bkn_filter_t *filter;
   8044     struct list_head *list;
   8045     unsigned long flags;
   8046     int found;
   8047 
   8048     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   8049 
   8050     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   8051     if (sinfo == NULL) {
   8052         kmsg->hdr.status = KCOM_E_PARAM;
   8053         return sizeof(kcom_msg_hdr_t);
   8054     }
   8055 
   8056     spin_lock_irqsave(&sinfo->lock, flags);
   8057 
   8058     found = 0;
   8059     list_for_each(list, &sinfo->rxpf_list) {
   8060         filter = (bkn_filter_t *)list;
   8061         if (kmsg->hdr.id == filter->kf.id) {
   8062             found = 1;
   8063             break;
   8064         }
   8065     }
   8066 
   8067     if (!found) {
   8068         spin_unlock_irqrestore(&sinfo->lock, flags);
   8069         kmsg->hdr.status = KCOM_E_NOT_FOUND;
   8070         return sizeof(kcom_msg_hdr_t);
   8071     }
   8072 
   8073     memcpy(&kmsg->filter, &filter->kf, sizeof(kmsg->filter));
   8074 
   8075     spin_unlock_irqrestore(&sinfo->lock, flags);
   8076 
   8077     return sizeof(*kmsg);
   8078 }
   8079 
   8080 static int
   8081 bkn_knet_dbg_pkt_set(kcom_msg_dbg_pkt_set_t *kmsg, int len)
   8082 {
   8083     dbg_pkt_enable = kmsg->enable;
   8084     return sizeof(kcom_msg_dbg_pkt_set_t);
   8085 }
   8086 
   8087 static int
   8088 bkn_knet_dbg_pkt_get(kcom_msg_dbg_pkt_get_t *kmsg, int len)
   8089 {
   8090     kmsg->value = dbg_pkt_enable;
   8091     return sizeof(kcom_msg_dbg_pkt_get_t);
   8092 }
   8093 
   8094 static int
   8095 bkn_knet_wb_cleanup(kcom_msg_wb_cleanup_t *kmsg, int len)
   8096 {
   8097     bkn_switch_info_t *sinfo;
   8098     bkn_dcb_chain_t *dcb_chain;
   8099     unsigned long flags;
   8100     int chan;
   8101 
   8102     kmsg->hdr.type = KCOM_MSG_TYPE_RSP;
   8103 
   8104     sinfo = bkn_sinfo_from_unit(kmsg->hdr.unit);
   8105     if (sinfo == NULL) {
   8106         kmsg->hdr.status = KCOM_E_PARAM;
   8107         return sizeof(kcom_msg_hdr_t);
   8108     }
   8109 
   8110     spin_lock_irqsave(&sinfo->lock, flags);
   8111 
   8112     for (chan = 0; chan < sinfo->rx_chans; chan++) {
   8113         if (sinfo->rx[chan].api_dcb_chain) {
   8114             DBG_DCB_RX(("Freeing active Rx%d DCB chain.\n", chan));
   8115             kfree(sinfo->rx[chan].api_dcb_chain);
   8116             sinfo->rx[chan].api_dcb_chain = NULL;
   8117         }
   8118         while (!list_empty(&sinfo->rx[chan].api_dcb_list)) {
   8119             dcb_chain = list_entry(sinfo->rx[chan].api_dcb_list.next,
   8120                                    bkn_dcb_chain_t, list);
   8121             list_del(&dcb_chain->list);
   8122             DBG_DCB_RX(("Freeing Rx%d DCB chain.\n", chan));
   8123             kfree(dcb_chain);
   8124         }
   8125         sinfo->rx[chan].api_dcb_chain_end = NULL;
   8126         sinfo->rx[chan].api_active = 0;
   8127     }
   8128 
   8129     spin_unlock_irqrestore(&sinfo->lock, flags);
   8130 
   8131     return sizeof(kcom_msg_hdr_t);
   8132 }
   8133 
   8134 static int
   8135 bkn_handle_cmd_req(kcom_msg_t *kmsg, int len)
   8136 {
   8137     /* Silently drop events and unrecognized message types */
   8138     if (kmsg->hdr.type != KCOM_MSG_TYPE_CMD) {
   8139         if (kmsg->hdr.opcode == KCOM_M_STRING) {
   8140             DBG_VERB(("Debug string: '%s'\n", kmsg->string.val));
   8141             return 0;
   8142         }
   8143         DBG_WARN(("Unsupported message (type=%d, opcode=%d)\n",
   8144                   kmsg->hdr.type, kmsg->hdr.opcode));
   8145         return 0;
   8146     }
   8147 
   8148     switch (kmsg->hdr.opcode) {
   8149     case KCOM_M_DMA_INFO:
   8150         DBG_CMD(("KCOM_M_DMA_INFO\n"));
   8151         /* Packet buffer */
   8152         len = bkn_knet_dma_info(&kmsg->dma_info, len);
   8153         break;
   8154     case KCOM_M_VERSION:
   8155         DBG_CMD(("KCOM_M_VERSION\n"));
   8156         /* Return procotol version */
   8157         len = bkn_knet_version(&kmsg->version, len);
   8158         break;
   8159     case KCOM_M_HW_RESET:
   8160         DBG_CMD(("KCOM_M_HW_RESET\n"));
   8161         /* Shut down DMA and release buffers */
   8162         len = bkn_knet_hw_reset(&kmsg->hw_reset, len);
   8163         break;
   8164     case KCOM_M_HW_INIT:
   8165         DBG_CMD(("KCOM_M_HW_INIT\n"));
   8166         /* Initialize DMA */
   8167         len = bkn_knet_hw_init(&kmsg->hw_init, len);
   8168         break;
   8169     case KCOM_M_DETACH:
   8170         DBG_CMD(("KCOM_M_DETACH\n"));
   8171         /* Detach kernel module */
   8172         len = bkn_knet_detach(&kmsg->detach, len);
   8173         break;
   8174     case KCOM_M_REPROBE:
   8175         DBG_CMD(("KCOM_M_REPROBE\n"));
   8176         /* Reprobe device */
   8177         len = bkn_knet_reprobe(&kmsg->reprobe, len);
   8178         break;
   8179     case KCOM_M_NETIF_CREATE:
   8180         DBG_CMD(("KCOM_M_NETIF_CREATE\n"));
   8181         /* Create network interface */
   8182         len = bkn_knet_netif_create(&kmsg->netif_create, len);
   8183         break;
   8184     case KCOM_M_NETIF_DESTROY:
   8185         DBG_CMD(("KCOM_M_NETIF_DESTROY\n"));
   8186         /* Destroy network interface */
   8187         len = bkn_knet_netif_destroy(&kmsg->netif_destroy, len);
   8188         break;
   8189     case KCOM_M_NETIF_LIST:
   8190         DBG_CMD(("KCOM_M_NETIF_LIST\n"));
   8191         /* Return list of IDs of installed network interfaces */
   8192         len = bkn_knet_netif_list(&kmsg->netif_list, len);
   8193         break;
   8194     case KCOM_M_NETIF_GET:
   8195         DBG_CMD(("KCOM_M_NETIF_GET\n"));
   8196         /* Return network interface info */
   8197         len = bkn_knet_netif_get(&kmsg->netif_get, len);
   8198         break;
   8199     case KCOM_M_FILTER_CREATE:
   8200         DBG_CMD(("KCOM_M_FILTER_CREATE\n"));
   8201         /* Create packet filter */
   8202         len = bkn_knet_filter_create(&kmsg->filter_create, len);
   8203         break;
   8204     case KCOM_M_FILTER_DESTROY:
   8205         DBG_CMD(("KCOM_M_FILTER_DESTROY\n"));
   8206         /* Destroy packet filter */
   8207         len = bkn_knet_filter_destroy(&kmsg->filter_destroy, len);
   8208         break;
   8209     case KCOM_M_FILTER_LIST:
   8210         DBG_CMD(("KCOM_M_FILTER_LIST\n"));
   8211         /* Return list of IDs of installed packet filters */
   8212         len = bkn_knet_filter_list(&kmsg->filter_list, len);
   8213         break;
   8214     case KCOM_M_FILTER_GET:
   8215         DBG_CMD(("KCOM_M_FILTER_GET\n"));
   8216         /* Return packet filter info */
   8217         len = bkn_knet_filter_get(&kmsg->filter_get, len);
   8218         break;
   8219     case KCOM_M_DBGPKT_SET:
   8220         DBG_CMD(("KCOM_M_DBGPKT_SET\n"));
   8221         /* Set debugging packet function */
   8222         len = bkn_knet_dbg_pkt_set(&kmsg->dbg_pkt_set, len);
   8223         break;
   8224     case KCOM_M_DBGPKT_GET:
   8225         DBG_CMD(("KCOM_M_DBGPKT_GET\n"));
   8226         /* Get debugging packet function info */
   8227         len = bkn_knet_dbg_pkt_get(&kmsg->dbg_pkt_get, len);
   8228         break;
   8229     case KCOM_M_WB_CLEANUP:
   8230         DBG_CMD(("KCOM_M_WB_CLEANUP\n"));
   8231         /* Clean up for warmbooting */
   8232         len = bkn_knet_wb_cleanup(&kmsg->wb_cleanup, len);
   8233         break;
   8234     default:
   8235         DBG_WARN(("Unsupported command (type=%d, opcode=%d)\n",
   8236                   kmsg->hdr.type, kmsg->hdr.opcode));
   8237         kmsg->hdr.opcode = 0;
   8238         len = sizeof(kcom_msg_hdr_t);
   8239         break;
   8240     }
   8241     return len;
   8242 }
   8243 
   8244 static int
   8245 bkn_cmd_thread(void *context)
   8246 {
   8247     bkn_thread_ctrl_t *tc = (bkn_thread_ctrl_t *)context;
   8248     kcom_msg_t kmsg;
   8249     unsigned int len, rlen;
   8250 
   8251     bkn_thread_boot(tc);
   8252 
   8253     DBG_VERB(("Command thread starting\n"));
   8254     tc->state = 1;
   8255     while (!bkn_thread_should_stop(tc)) {
   8256         len = sizeof(kmsg);
   8257         tc->state = 2;
   8258         if (PROXY_RECV(KCOM_CHAN_KNET, &kmsg, &len) >= 0) {
   8259             DBG_VERB(("Received %d bytes from KCOM_CHAN_CMD\n", len));
   8260             tc->state = 3;
   8261             rlen = bkn_handle_cmd_req(&kmsg, len);
   8262             tc->state = 4;
   8263             if (rlen > 0) {
   8264                 PROXY_SEND(KCOM_CHAN_KNET, &kmsg, rlen);
   8265             }
   8266         } else {
   8267             /* Thread interrupted */
   8268             bkn_sleep(1);
   8269         }
   8270     }
   8271     DBG_VERB(("Command thread done\n"));
   8272 
   8273     bkn_thread_exit(tc);
   8274     return 0;
   8275 }
   8276 
   8277 static int
   8278 bkn_get_next_dma_event(kcom_msg_dma_info_t *kmsg)
   8279 {
   8280     static int last_dev_no = 0;
   8281     bkn_switch_info_t *sinfo;
   8282     unsigned long flags;
   8283     int dev_no, dev_evt;
   8284     bkn_evt_resource_t *evt;
   8285 
   8286     dev_evt = kmsg->hdr.unit;
   8287     sinfo = bkn_sinfo_from_unit(dev_evt);
   8288     if (sinfo == NULL) {
   8289         /* The device is not probed or initialized yet.*/
   8290         return 0;
   8291     }
   8292     if (sinfo->evt_idx == -1) {
   8293         /* Event queue is not ready yet */
   8294         return 0;
   8295     }
   8296 
   8297     DBG_INST(("%s dev %d evt_idx %d\n",__FUNCTION__, dev_evt, sinfo->evt_idx));
   8298     dev_no = last_dev_no;
   8299     while (1) {
   8300         dev_no++;
   8301         sinfo = bkn_sinfo_from_unit(dev_no);
   8302         if (sinfo == NULL) {
   8303             dev_no = 0;
   8304             sinfo = bkn_sinfo_from_unit(dev_no);
   8305         }
   8306 
   8307         if (sinfo && (sinfo->inst_id != 0) &&
   8308            ((sinfo->inst_id & (1 << dev_evt)) == 0)) {
   8309             DBG_INST((" %s skip dev(%d)\n",__FUNCTION__,dev_evt));
   8310             continue;
   8311         }
   8312 
   8313         if (sinfo && sinfo->dma_events) {
   8314             DBG_EVT(("Next DMA events (0x%08x)\n", sinfo->dma_events));
   8315             kmsg->hdr.unit = sinfo->dev_no;
   8316 
   8317             spin_lock_irqsave(&sinfo->lock, flags);
   8318             kmsg->dma_info.flags = sinfo->dma_events;
   8319             sinfo->dma_events = 0;
   8320             spin_unlock_irqrestore(&sinfo->lock, flags);
   8321 
   8322             last_dev_no = dev_no;
   8323             break;
   8324         }
   8325 
   8326         if (dev_no == last_dev_no) {
   8327             evt = &_bkn_evt[sinfo->evt_idx];
   8328             DBG_INST(("wait queue index %d\n",sinfo->evt_idx));
   8329             wait_event_interruptible(evt->evt_wq,
   8330                                      evt->evt_wq_get != evt->evt_wq_put);
   8331             DBG_VERB(("Event thread wakeup\n"));
   8332 
   8333             /* Thread interrupted */
   8334             if (signal_pending(current)) {
   8335                return 0;
   8336             }
   8337 
   8338             evt->evt_wq_get = evt->evt_wq_put;
   8339         }
   8340     }
   8341     return sizeof(*kmsg);
   8342 }
   8343 
   8344 static int
   8345 bkn_evt_thread(void *context)
   8346 {
   8347     bkn_thread_ctrl_t *tc = (bkn_thread_ctrl_t *)context;
   8348     kcom_msg_dma_info_t kmsg;
   8349     int len;
   8350 
   8351     bkn_thread_boot(tc);
   8352 
   8353     memset(&kmsg, 0, sizeof(kmsg));
   8354     kmsg.hdr.type = KCOM_MSG_TYPE_EVT;
   8355     kmsg.hdr.opcode = KCOM_M_DMA_INFO;
   8356 
   8357     DBG_VERB(("Event thread starting\n"));
   8358     tc->state = 1;
   8359     while (!bkn_thread_should_stop(tc)) {
   8360         tc->state = 2;
   8361         len = bkn_get_next_dma_event(&kmsg);
   8362         tc->state = 3;
   8363         if (len) {
   8364             PROXY_SEND(KCOM_CHAN_KNET, &kmsg, len);
   8365         } else {
   8366             /* Thread interrupted */
   8367             bkn_sleep(1);
   8368         }
   8369     }
   8370     DBG_VERB(("Event thread done\n"));
   8371 
   8372     bkn_thread_exit(tc);
   8373     return 0;
   8374 }
   8375 
   8376 static int
   8377 _cleanup(void)
   8378 {
   8379     struct list_head *list;
   8380     struct net_device *dev;
   8381     bkn_filter_t *filter;
   8382     bkn_priv_t *priv;
   8383     bkn_switch_info_t *sinfo;
   8384     unsigned long flags;
   8385 
   8386     /* Inidicate that we are shutting down */
   8387     module_initialized = 0;
   8388 
   8389     /* Shut down event thread */
   8390     bkn_thread_stop(&bkn_evt_ctrl);
   8391 
   8392     /* Shut down command thread */
   8393     bkn_thread_stop(&bkn_cmd_ctrl);
   8394 
   8395     /* Remove KCOM channel */
   8396     PROXY_SERVICE_DESTROY(KCOM_CHAN_KNET);
   8397 
   8398     bkn_proc_cleanup();
   8399     remove_proc_entry("bcm/knet", NULL);
   8400     remove_proc_entry("bcm", NULL);
   8401 
   8402     list_for_each(list, &_sinfo_list) {
   8403         sinfo = (bkn_switch_info_t *)list;
   8404 
   8405         del_timer_sync(&sinfo->timer);
   8406         del_timer_sync(&sinfo->rxtick);
   8407 
   8408         spin_lock_irqsave(&sinfo->lock, flags);
   8409         bkn_dma_abort(sinfo);
   8410         dev_irq_mask_set(sinfo, 0);
   8411         spin_unlock_irqrestore(&sinfo->lock, flags);
   8412 
   8413         DBG_IRQ(("Unregister ISR.\n"));
   8414         kernel_bde->interrupt_disconnect(sinfo->dev_no | LKBDE_ISR2_DEV);
   8415 
   8416         if (use_napi) {
   8417             while (sinfo->napi_poll_mode) {
   8418                 bkn_sleep(1);
   8419             }
   8420         }
   8421 
   8422         spin_lock_irqsave(&sinfo->lock, flags);
   8423         bkn_clean_dcbs(sinfo);
   8424         skb_queue_purge(&sinfo->tx_ptp_queue);
   8425         spin_unlock_irqrestore(&sinfo->lock, flags);
   8426     }
   8427 
   8428     /* Destroy all switch devices */
   8429     while (!list_empty(&_sinfo_list)) {
   8430         sinfo = list_entry(_sinfo_list.next, bkn_switch_info_t, list);
   8431 
   8432         /* Destroy all associated Rx packet filters */
   8433         while (!list_empty(&sinfo->rxpf_list)) {
   8434             filter = list_entry(sinfo->rxpf_list.next, bkn_filter_t, list);
   8435             list_del(&filter->list);
   8436             DBG_VERB(("Removing filter ID %d.\n", filter->kf.id));
   8437             kfree(filter);
   8438         }
   8439 
   8440         /* Destroy all associated virtual net devices */
   8441         while (!list_empty(&sinfo->ndev_list)) {
   8442             priv = list_entry(sinfo->ndev_list.next, bkn_priv_t, list);
   8443             list_del(&priv->list);
   8444             dev = priv->dev;
   8445             DBG_VERB(("Removing virtual Ethernet device %s.\n", dev->name));
   8446             unregister_netdev(dev);
   8447             free_netdev(dev);
   8448         }
   8449         if (sinfo->ndevs != NULL) {
   8450             kfree(sinfo->ndevs);
   8451         }
   8452 
   8453         /* Destroy base net device */
   8454         if (sinfo->dev) {
   8455             DBG_VERB(("Removing Ethernet device %s.\n", sinfo->dev->name));
   8456             unregister_netdev(sinfo->dev);
   8457             free_netdev(sinfo->dev);
   8458         }
   8459 
   8460         DBG_VERB(("Removing switch device.\n"));
   8461         bkn_destroy_sinfo(sinfo);
   8462     }
   8463 
   8464     return 0;
   8465 }
   8466 
   8467 static int
   8468 bkn_knet_dev_reinit(int d)
   8469 {
   8470     bkn_switch_info_t *sinfo;
   8471     uint32 dev_state;
   8472     unsigned long flags;
   8473 
   8474     if (lkbde_dev_state_get(d, &dev_state) < 0) {
   8475         return -1;
   8476     }
   8477     DBG_VERB(("%s dev %d dev_state %d\n",__FUNCTION__, d, dev_state));
   8478     if (dev_state == BDE_DEV_STATE_CHANGED) {
   8479         sinfo = bkn_sinfo_from_unit(d);
   8480         spin_lock_irqsave(&sinfo->lock, flags);
   8481         sinfo->base_addr = lkbde_get_dev_virt(d);
   8482         sinfo->dma_dev = lkbde_get_dma_dev(d);
   8483         sinfo->pdev = lkbde_get_hw_dev(d);
   8484         spin_unlock_irqrestore(&sinfo->lock, flags);
   8485 
   8486         dev_state = 0;
   8487         lkbde_dev_state_set(d, dev_state);
   8488     }
   8489     return 0;
   8490 }
   8491 
   8492 static int
   8493 bkn_knet_dev_init(int d)
   8494 {
   8495     uint32_t dev_type;
   8496     struct net_device *dev;
   8497     bkn_switch_info_t *sinfo;
   8498     bkn_priv_t *priv;
   8499     char *bdev_name;
   8500     const ibde_dev_t *bde_dev;
   8501 
   8502     DBG_VERB(("%s dev %d\n",__FUNCTION__, d));
   8503     /* Base network device name */
   8504     bdev_name = "bcm%d";
   8505     if (base_dev_name) {
   8506         if (strlen(base_dev_name) < IFNAMSIZ) {
   8507             bdev_name = base_dev_name;
   8508         } else {
   8509             DBG_WARN(("Base device name too long\n"));
   8510         }
   8511     }
   8512 
   8513     dev_type = kernel_bde->get_dev_type(d);
   8514     DBG_VERB(("Found device type 0x%x\n", dev_type));
   8515     if ((dev_type & BDE_SWITCH_DEV_TYPE) == 0) {
   8516         DBG_WARN(("Not switch device - skipping\n"));
   8517         return 0;
   8518     }
   8519     switch (dev_type & BDE_DEV_BUS_TYPE_MASK) {
   8520     case BDE_PCI_DEV_TYPE:
   8521     case BDE_ICS_DEV_TYPE:
   8522     case BDE_AXI_DEV_TYPE:
   8523         break;
   8524     default:
   8525         DBG_WARN(("Not PCI/ICS/AXI device - skipping\n"));
   8526         return 0;
   8527     }
   8528 
   8529     if ((sinfo = bkn_create_sinfo(d)) == NULL) {
   8530         _cleanup();
   8531         return -ENOMEM;
   8532     }
   8533 
   8534     /* Initialize the cpu_no.*/
   8535     if (dev_type & BDE_AXI_DEV_TYPE) {
   8536         /* AXI device type implies the activated iProc iHost */
   8537         sinfo->cpu_no = 1;
   8538     }
   8539     /* Initialize default RCPU signature */
   8540     if ((bde_dev = kernel_bde->get_dev(d)) != NULL) {
   8541         sinfo->rcpu_sig = bde_dev->device & ~0xf;
   8542     }
   8543     /* Check for override */
   8544     if (rcpu_signature) {
   8545         sinfo->rcpu_sig = rcpu_signature;
   8546     }
   8547 
   8548     /* Create base virtual net device */
   8549     bkn_dev_mac[5]++;
   8550     if ((dev = bkn_init_ndev(bkn_dev_mac, bdev_name)) == NULL) {
   8551         _cleanup();
   8552         return -ENOMEM;
   8553     } else {
   8554         sinfo->dev = dev;
   8555         priv = netdev_priv(dev);
   8556         priv->dev = dev;
   8557         priv->sinfo = sinfo;
   8558         priv->vlan = 1;
   8559         priv->port = -1;
   8560         memset(priv->itmh, 0, sizeof(priv->itmh));
   8561         priv->id = -1;
   8562     }
   8563 
   8564     if (use_napi) {
   8565         netif_napi_add(dev, &sinfo->napi, bkn_poll, napi_weight);
   8566     }
   8567     return 0;
   8568 }
   8569 
   8570 static int
   8571 _init(void)
   8572 {
   8573     int idx;
   8574     int num_dev;
   8575     int rv;
   8576     bkn_evt_resource_t *evt;
   8577 
   8578     /* Connect to the kernel bde */
   8579     if ((linux_bde_create(NULL, &kernel_bde) < 0) || kernel_bde == NULL) {
   8580         return -ENODEV;
   8581     }
   8582 
   8583     /* Randomize Lower 3 bytes of the MAC address (TESTING ONLY) */
   8584     get_random_bytes(&bkn_dev_mac[3], 3);
   8585 
   8586     /* Check for user-supplied MAC address (recommended) */
   8587     if (mac_addr != NULL && strlen(mac_addr) == 17) {
   8588         for (idx = 0; idx < 6; idx++) {
   8589             bkn_dev_mac[idx] = simple_strtoul(&mac_addr[idx*3], NULL, 16);
   8590         }
   8591         /* Do not allow multicast address */
   8592         bkn_dev_mac[0] &= ~0x01;
   8593     }
   8594 
   8595     /* Optional RCPU MAC addresses */
   8596     if (rcpu_dmac != NULL && strlen(rcpu_dmac) == 17) {
   8597         for (idx = 0; idx < 6; idx++) {
   8598             bkn_rcpu_dmac[idx] = simple_strtoul(&rcpu_dmac[idx*3], NULL, 16);
   8599         }
   8600     }
   8601     if (rcpu_smac != NULL && strlen(rcpu_smac) == 17) {
   8602         for (idx = 0; idx < 6; idx++) {
   8603             bkn_rcpu_smac[idx] = simple_strtoul(&rcpu_smac[idx*3], NULL, 16);
   8604         }
   8605     }
   8606 
   8607     /* NAPI implies that base device must be up before we can pass traffic */
   8608     if (use_napi) {
   8609         basedev_suspend = 1;
   8610     }
   8611 
   8612     num_dev = kernel_bde->num_devices(BDE_ALL_DEVICES);
   8613     for (idx = 0; idx < num_dev; idx++) {
   8614         rv = bkn_knet_dev_init(idx);
   8615         if (rv) {
   8616             return rv;
   8617         }
   8618     }
   8619 
   8620     /* Initialize proc files */
   8621     proc_mkdir("bcm", NULL);
   8622     bkn_proc_root = proc_mkdir("bcm/knet", NULL);
   8623 
   8624     bkn_proc_init();
   8625 
   8626     /* Initialize event queue */
   8627     for (idx = 0; idx < LINUX_BDE_MAX_DEVICES; idx++) {
   8628         memset(&_bkn_evt[idx], 0, sizeof(bkn_evt_resource_t));
   8629     }
   8630     evt = &_bkn_evt[0];
   8631     init_waitqueue_head(&evt->evt_wq);
   8632 
   8633     if (use_proxy) {
   8634         PROXY_SERVICE_CREATE(KCOM_CHAN_KNET, 1, 0);
   8635 
   8636         DBG_VERB(("Starting command thread\n"));
   8637         bkn_thread_start(&bkn_cmd_ctrl, "bkncmd", bkn_cmd_thread);
   8638 
   8639         DBG_VERB(("Starting event thread\n"));
   8640         bkn_thread_start(&bkn_evt_ctrl, "bknevt", bkn_evt_thread);
   8641     }
   8642 
   8643     module_initialized = 1;
   8644 
   8645     return 0;
   8646 }
   8647 
   8648 static int
   8649 _ioctl(unsigned int cmd, unsigned long arg)
   8650 {
   8651     bkn_ioctl_t io;
   8652     kcom_msg_t kmsg;
   8653 
   8654     if (!module_initialized) {
   8655         return -EFAULT;
   8656     }
   8657 
   8658     if (copy_from_user(&io, (void*)arg, sizeof(io))) {
   8659         return -EFAULT;
   8660     }
   8661 
   8662     if (io.len > sizeof(kmsg)) {
   8663         return -EINVAL;
   8664     }
   8665 
   8666     io.rc = 0;
   8667 
   8668     switch(cmd) {
   8669     case 0:
   8670         if (io.len > 0) {
   8671             if (copy_from_user(&kmsg, (void *)(unsigned long)io.buf, io.len)) {
   8672                 return -EFAULT;
   8673             }
   8674             ioctl_cmd++;
   8675             io.len = bkn_handle_cmd_req(&kmsg, io.len);
   8676             ioctl_cmd--;
   8677         } else {
   8678             memset(&kmsg, 0, sizeof(kcom_msg_dma_info_t));
   8679             /*
   8680              * Retrive the kmsg.hdr.unit from user space. The dma event queue
   8681              * selection is based the instance derived from unit.
   8682              */
   8683             if (copy_from_user(&kmsg, (void *)(unsigned long)io.buf, sizeof(kmsg))) {
   8684                 return -EFAULT;
   8685             }
   8686             kmsg.hdr.type = KCOM_MSG_TYPE_EVT;
   8687             kmsg.hdr.opcode = KCOM_M_DMA_INFO;
   8688             ioctl_evt++;
   8689             io.len = bkn_get_next_dma_event((kcom_msg_dma_info_t *)&kmsg);
   8690             ioctl_evt--;
   8691         }
   8692         if (io.len > 0) {
   8693             if (copy_to_user((void *)(unsigned long)io.buf, &kmsg, io.len)) {
   8694                 return -EFAULT;
   8695             }
   8696         }
   8697         break;
   8698     default:
   8699         gprintk("Invalid IOCTL");
   8700         io.rc = -1;
   8701         break;
   8702     }
   8703 
   8704     if (copy_to_user((void*)arg, &io, sizeof(io))) {
   8705         return -EFAULT;
   8706     }
   8707 
   8708     return 0;
   8709 }
   8710 
   8711 static gmodule_t _gmodule = {
   8712     name: MODULE_NAME,
   8713     major: MODULE_MAJOR,
   8714     init: _init,
   8715     cleanup: _cleanup,
   8716     pprint: _pprint,
   8717     ioctl: _ioctl,
   8718     open: NULL,
   8719     close: NULL,
   8720 };
   8721 
   8722 gmodule_t *
   8723 gmodule_get(void)
   8724 {
   8725     EXPORT_NO_SYMBOLS;
   8726     return &_gmodule;
   8727 }
   8728 
   8729 /*
   8730  * Call-back interfaces for other Linux kernel drivers.
   8731  *
   8732  * The Rx call-back allows an external module to modify SKB contents
   8733  * before it is handed off to the Linux network stack.
   8734  *
   8735  * The Tx call-back allows an external module to modify SKB contents
   8736  * before it is injected inot the switch.
   8737  *
   8738  * The HW timestamp callbacks invoke an external module to enable, disable
   8739  * HW timestamp on a specific port which is indicated while the netif is
   8740  * created through KNET API. KNET can also get device-specific SOBMH and
   8741  * timestamp for a Tx PTP packet through these callbacks.
   8742  */
   8743 
   8744 int
   8745 bkn_rx_skb_cb_register(knet_skb_cb_f rx_cb)
   8746 {
   8747     if (knet_rx_cb != NULL) {
   8748         return -1;
   8749     }
   8750     knet_rx_cb = rx_cb;
   8751     return 0;
   8752 }
   8753 
   8754 int
   8755 bkn_rx_skb_cb_unregister(knet_skb_cb_f rx_cb)
   8756 {
   8757     if (rx_cb != NULL && knet_rx_cb != rx_cb) {
   8758         return -1;
   8759     }
   8760     knet_rx_cb = NULL;
   8761     return 0;
   8762 }
   8763 
   8764 int
   8765 bkn_tx_skb_cb_register(knet_skb_cb_f tx_cb)
   8766 {
   8767     if (knet_tx_cb != NULL) {
   8768         return -1;
   8769     }
   8770     knet_tx_cb = tx_cb;
   8771     return 0;
   8772 }
   8773 
   8774 int
   8775 bkn_tx_skb_cb_unregister(knet_skb_cb_f tx_cb)
   8776 {
   8777     if (tx_cb != NULL && knet_tx_cb != tx_cb) {
   8778         return -1;
   8779     }
   8780     knet_tx_cb = NULL;
   8781     return 0;
   8782 }
   8783 
   8784 int
   8785 bkn_filter_cb_register(knet_filter_cb_f filter_cb)
   8786 {
   8787     if (knet_filter_cb != NULL) {
   8788         return -1;
   8789     }
   8790     knet_filter_cb = filter_cb;
   8791     return 0;
   8792 }
   8793 
   8794 int
   8795 bkn_filter_cb_unregister(knet_filter_cb_f filter_cb)
   8796 {
   8797     if (filter_cb != NULL && knet_filter_cb != filter_cb) {
   8798         return -1;
   8799     }
   8800     knet_filter_cb = NULL;
   8801     return 0;
   8802 }
   8803 
   8804 int
   8805 bkn_hw_tstamp_enable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb)
   8806 {
   8807     if (knet_hw_tstamp_enable_cb != NULL) {
   8808         return -1;
   8809     }
   8810     knet_hw_tstamp_enable_cb = hw_tstamp_enable_cb;
   8811     return 0;
   8812 }
   8813 
   8814 int
   8815 bkn_hw_tstamp_enable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_enable_cb)
   8816 {
   8817     if (hw_tstamp_enable_cb == NULL ||
   8818         knet_hw_tstamp_enable_cb != hw_tstamp_enable_cb) {
   8819         return -1;
   8820     }
   8821     knet_hw_tstamp_enable_cb = NULL;
   8822     return 0;
   8823 }
   8824 
   8825 int
   8826 bkn_hw_tstamp_disable_cb_register(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb)
   8827 {
   8828     if (knet_hw_tstamp_disable_cb != NULL) {
   8829         return -1;
   8830     }
   8831     knet_hw_tstamp_disable_cb = hw_tstamp_disable_cb;
   8832     return 0;
   8833 }
   8834 
   8835 int
   8836 bkn_hw_tstamp_disable_cb_unregister(knet_hw_tstamp_enable_cb_f hw_tstamp_disable_cb)
   8837 {
   8838     if (hw_tstamp_disable_cb == NULL ||
   8839         knet_hw_tstamp_disable_cb != hw_tstamp_disable_cb) {
   8840         return -1;
   8841     }
   8842     knet_hw_tstamp_disable_cb = NULL;
   8843     return 0;
   8844 }
   8845 
   8846 int
   8847 bkn_hw_tstamp_tx_time_get_cb_register(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb)
   8848 {
   8849     if (knet_hw_tstamp_tx_time_get_cb != NULL) {
   8850         return -1;
   8851     }
   8852     knet_hw_tstamp_tx_time_get_cb = hw_tstamp_tx_time_get_cb;
   8853     return 0;
   8854 }
   8855 
   8856 int
   8857 bkn_hw_tstamp_tx_time_get_cb_unregister(knet_hw_tstamp_tx_time_get_cb_f hw_tstamp_tx_time_get_cb)
   8858 {
   8859     if (hw_tstamp_tx_time_get_cb == NULL ||
   8860         knet_hw_tstamp_tx_time_get_cb != hw_tstamp_tx_time_get_cb) {
   8861         return -1;
   8862     }
   8863     knet_hw_tstamp_tx_time_get_cb = NULL;
   8864     return 0;
   8865 }
   8866 
   8867 int
   8868 bkn_hw_tstamp_tx_meta_get_cb_register(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb)
   8869 {
   8870     if (knet_hw_tstamp_tx_meta_get_cb != NULL) {
   8871         return -1;
   8872     }
   8873     knet_hw_tstamp_tx_meta_get_cb = hw_tstamp_tx_meta_get_cb;
   8874     return 0;
   8875 }
   8876 
   8877 int
   8878 bkn_hw_tstamp_tx_meta_get_cb_unregister(knet_hw_tstamp_tx_meta_get_cb_f hw_tstamp_tx_meta_get_cb)
   8879 {
   8880     if (hw_tstamp_tx_meta_get_cb == NULL ||
   8881         knet_hw_tstamp_tx_meta_get_cb != hw_tstamp_tx_meta_get_cb) {
   8882         return -1;
   8883     }
   8884     knet_hw_tstamp_tx_meta_get_cb = NULL;
   8885     return 0;
   8886 }
   8887 
   8888 int
   8889 bkn_hw_tstamp_ptp_clock_index_cb_register(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb)
   8890 {
   8891     if (knet_hw_tstamp_ptp_clock_index_cb != NULL) {
   8892         return -1;
   8893     }
   8894     knet_hw_tstamp_ptp_clock_index_cb = hw_tstamp_ptp_clock_index_cb;
   8895     return 0;
   8896 }
   8897 
   8898 int
   8899 bkn_hw_tstamp_ptp_clock_index_cb_unregister(knet_hw_tstamp_ptp_clock_index_cb_f hw_tstamp_ptp_clock_index_cb)
   8900 {
   8901     if (hw_tstamp_ptp_clock_index_cb == NULL ||
   8902         knet_hw_tstamp_ptp_clock_index_cb != hw_tstamp_ptp_clock_index_cb) {
   8903         return -1;
   8904     }
   8905     knet_hw_tstamp_ptp_clock_index_cb = NULL;
   8906     return 0;
   8907 }
   8908 
   8909 int
   8910 bkn_hw_tstamp_rx_time_upscale_cb_register(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb)
   8911 {
   8912     if (knet_hw_tstamp_rx_time_upscale_cb != NULL) {
   8913         return -1;
   8914     }
   8915     knet_hw_tstamp_rx_time_upscale_cb = hw_tstamp_rx_time_upscale_cb;
   8916     return 0;
   8917 }
   8918 
   8919 int
   8920 bkn_hw_tstamp_rx_time_upscale_cb_unregister(knet_hw_tstamp_rx_time_upscale_cb_f hw_tstamp_rx_time_upscale_cb)
   8921 {
   8922     if (hw_tstamp_rx_time_upscale_cb == NULL ||
   8923         knet_hw_tstamp_rx_time_upscale_cb != hw_tstamp_rx_time_upscale_cb) {
   8924         return -1;
   8925     }
   8926     knet_hw_tstamp_rx_time_upscale_cb = NULL;
   8927     return 0;
   8928 }
   8929 
   8930 LKM_EXPORT_SYM(bkn_rx_skb_cb_register);
   8931 LKM_EXPORT_SYM(bkn_rx_skb_cb_unregister);
   8932 LKM_EXPORT_SYM(bkn_tx_skb_cb_register);
   8933 LKM_EXPORT_SYM(bkn_tx_skb_cb_unregister);
   8934 LKM_EXPORT_SYM(bkn_filter_cb_register);
   8935 LKM_EXPORT_SYM(bkn_filter_cb_unregister);
   8936 LKM_EXPORT_SYM(bkn_hw_tstamp_enable_cb_register);
   8937 LKM_EXPORT_SYM(bkn_hw_tstamp_enable_cb_unregister);
   8938 LKM_EXPORT_SYM(bkn_hw_tstamp_disable_cb_register);
   8939 LKM_EXPORT_SYM(bkn_hw_tstamp_disable_cb_unregister);
   8940 LKM_EXPORT_SYM(bkn_hw_tstamp_tx_time_get_cb_register);
   8941 LKM_EXPORT_SYM(bkn_hw_tstamp_tx_time_get_cb_unregister);
   8942 LKM_EXPORT_SYM(bkn_hw_tstamp_tx_meta_get_cb_register);
   8943 LKM_EXPORT_SYM(bkn_hw_tstamp_tx_meta_get_cb_unregister);
   8944 LKM_EXPORT_SYM(bkn_hw_tstamp_ptp_clock_index_cb_register);
   8945 LKM_EXPORT_SYM(bkn_hw_tstamp_ptp_clock_index_cb_unregister);
   8946 LKM_EXPORT_SYM(bkn_hw_tstamp_rx_time_upscale_cb_register);
   8947 LKM_EXPORT_SYM(bkn_hw_tstamp_rx_time_upscale_cb_unregister);