device.c 13.9 KB
Newer Older
gauthier's avatar
gauthier committed
1
/*******************************************************************************
gauthier's avatar
Licence  
gauthier committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Eurecom OpenAirInterface 2
Copyright(c) 1999 - 2014 Eurecom

This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.

This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

The full GNU General Public License is included in this distribution in
the file called "COPYING".

Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums       : http://forums.eurecom.fsr/openairinterface
Address      : EURECOM,
               Campus SophiaTech,
               450 Route des Chappes,
               CS 50193
               06904 Biot Sophia Antipolis cedex,
               FRANCE
gauthier's avatar
gauthier committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
*******************************************************************************/

/*! \file device.c
* \brief Networking Device Driver for OpenAirInterface
* \author  navid.nikaein, yan.moret(no longer valid), michelle.wetterwald(no longer valid), raymond.knopp, Lionel Gauthier
* \company Eurecom
* \email: raymond.knopp@eurecom.fr, navid.nikaein@eurecom.fr, lionel.gauthier@eurecom.fr

*/
/*******************************************************************************/

#ifndef OAI_NW_DRIVER_USE_NETLINK
#ifdef RTAI
#include "rtai_posix.h"
#define RTAI_IRQ 30 //try to get this irq with RTAI
#endif // RTAI
#endif // OAI_NW_DRIVER_USE_NETLINK

#include "constant.h"
#include "local.h"
#include "proto_extern.h"

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/moduleparam.h>
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/delay.h>
#include <asm/unistd.h>
#include <linux/netdevice.h>



struct net_device *ue_ip_dev[UE_IP_NB_INSTANCES_MAX];

#ifdef OAI_NW_DRIVER_USE_NETLINK
extern void ue_ip_netlink_release(void);
extern int ue_ip_netlink_init(void);
#endif

//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
76
int ue_ip_find_inst(struct net_device *dev_pP) {
gauthier's avatar
gauthier committed
77 78 79 80
//---------------------------------------------------------------------------
  int i;

  for (i=0;i<UE_IP_NB_INSTANCES_MAX;i++)
gauthier's avatar
gauthier committed
81
    if (ue_ip_dev[i] == dev_pP)
gauthier's avatar
gauthier committed
82 83 84 85 86 87 88 89 90
      return(i);
  return(-1);
}

//---------------------------------------------------------------------------

#ifndef OAI_NW_DRIVER_USE_NETLINK
void *ue_ip_interrupt(void){
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
91
  uint8_t cxi;
gauthier's avatar
gauthier committed
92

gauthier's avatar
gauthier committed
93
  //  ue_ip_priv_t *priv_p=netdev_priv(dev_id);
gauthier's avatar
gauthier committed
94
  //  unsigned int flags;
gauthier's avatar
gauthier committed
95
  //  priv_p->lock = SPIN_LOCK_UNLOCKED;
gauthier's avatar
gauthier committed
96 97 98 99

#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT - begin\n");
#endif
gauthier's avatar
gauthier committed
100
  //  spin_lock_irqsave(&priv_p->lock,flags);
gauthier's avatar
gauthier committed
101 102 103 104 105 106
  cxi=0;
  //    mesh_GC_receive();
  //    mesh_DC_receive(naspriv->cx+cxi);
#ifndef OAI_NW_DRIVER_USE_NETLINK
  ue_ip_common_wireless2ip();
#endif
gauthier's avatar
gauthier committed
107
  //  spin_unlock_irqrestore(&priv_p->lock,flags);
gauthier's avatar
gauthier committed
108 109 110 111 112 113 114
#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT: end\n");
#endif
  //  return 0;
}
#endif //NETLINK
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
115
void ue_ip_timer(unsigned long dataP){
gauthier's avatar
gauthier committed
116
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
117 118 119 120 121 122 123
  ue_ip_priv_t *priv_p=(ue_ip_priv_t *)dataP;
  spin_lock(&priv_p->lock);
  (priv_p->timer).function=ue_ip_timer;
  (priv_p->timer).expires=jiffies+UE_IP_TIMER_TICK;
  (priv_p->timer).data=dataP;
  add_timer(&priv_p->timer);
  spin_unlock(&priv_p->lock);
gauthier's avatar
gauthier committed
124 125 126 127 128 129 130
  return;
//  add_timer(&gpriv->timer);
//  spin_unlock(&gpriv->lock);
}

//---------------------------------------------------------------------------
// Called by ifconfig when the device is activated by ifconfig
gauthier's avatar
gauthier committed
131
int ue_ip_open(struct net_device *dev_pP){
gauthier's avatar
gauthier committed
132
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
133
  ue_ip_priv_t *priv_p=netdev_priv(dev_pP);
gauthier's avatar
gauthier committed
134 135 136 137 138 139 140 141 142

  // Address has already been set at init
#ifndef OAI_NW_DRIVER_USE_NETLINK
  if (pdcp_2_ue_ip_irq==-EBUSY){
      printk("[UE_IP_DRV][%s] : irq failure\n", __FUNCTION__);
      return -EBUSY;
  }
#endif //OAI_NW_DRIVER_USE_NETLINK

gauthier's avatar
gauthier committed
143 144
  if(!netif_queue_stopped(dev_pP))
      netif_start_queue(dev_pP);
gauthier's avatar
gauthier committed
145
  else
gauthier's avatar
gauthier committed
146
      netif_wake_queue(dev_pP);
gauthier's avatar
gauthier committed
147

gauthier's avatar
gauthier committed
148 149 150 151 152
  init_timer(&priv_p->timer);
  (priv_p->timer).expires   = jiffies+UE_IP_TIMER_TICK;
  (priv_p->timer).data      = (unsigned long)priv_p;
  (priv_p->timer).function  = ue_ip_timer;
  //add_timer(&priv_p->timer);
gauthier's avatar
gauthier committed
153

gauthier's avatar
gauthier committed
154
  printk("[UE_IP_DRV][%s] name = %s\n", __FUNCTION__, dev_pP->name);
gauthier's avatar
gauthier committed
155 156 157 158 159
  return 0;
}

//---------------------------------------------------------------------------
// Called by ifconfig when the device is desactivated
gauthier's avatar
gauthier committed
160
int ue_ip_stop(struct net_device *dev_pP){
gauthier's avatar
gauthier committed
161
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
162
  ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
gauthier's avatar
gauthier committed
163 164

  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
165 166
  del_timer(&(priv_p->timer));
  netif_stop_queue(dev_pP);
gauthier's avatar
gauthier committed
167 168 169 170 171 172
  //    MOD_DEC_USE_COUNT;
  printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
  return 0;
}

//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
173
void ue_ip_teardown(struct net_device *dev_pP){
gauthier's avatar
gauthier committed
174
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
175
  ue_ip_priv_t    *priv_p;
gauthier's avatar
gauthier committed
176 177 178
  int              inst;

  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
179 180 181
  if (dev_pP) {
      priv_p = netdev_priv(dev_pP);
      inst = ue_ip_find_inst(dev_pP);
gauthier's avatar
gauthier committed
182 183 184 185 186 187 188
      if ((inst<0) || (inst>=UE_IP_NB_INSTANCES_MAX)) {
          printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__);
          return;
      }


      printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
gauthier's avatar
gauthier committed
189
  } // check dev_pP
gauthier's avatar
gauthier committed
190 191 192 193 194
  else {
      printk("[UE_IP_DRV][%s] Device is null\n", __FUNCTION__);
  }
}
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
195
int ue_ip_set_config(struct net_device *dev_pP, struct ifmap *map_pP){
gauthier's avatar
gauthier committed
196 197
  //---------------------------------------------------------------------------
  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
198
  if (dev_pP->flags & IFF_UP)
gauthier's avatar
gauthier committed
199
      return -EBUSY;
gauthier's avatar
gauthier committed
200
  if (map_pP->base_addr != dev_pP->base_addr) {
gauthier's avatar
gauthier committed
201 202 203
      printk(KERN_WARNING "[UE_IP_DRV][%s] Can't change I/O address\n", __FUNCTION__);
      return -EOPNOTSUPP;
  }
gauthier's avatar
gauthier committed
204 205
  if (map_pP->irq != dev_pP->irq)
      dev_pP->irq = map_pP->irq;
gauthier's avatar
gauthier committed
206 207 208 209 210 211
  printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
  return 0;
}

//---------------------------------------------------------------------------
//
gauthier's avatar
gauthier committed
212
int ue_ip_hard_start_xmit(struct sk_buff *skb_pP, struct net_device *dev_pP){
gauthier's avatar
gauthier committed
213 214 215
  //---------------------------------------------------------------------------
  int inst;

gauthier's avatar
gauthier committed
216 217
  if (dev_pP) {
      inst = ue_ip_find_inst(dev_pP);
gauthier's avatar
gauthier committed
218
  } else {
gauthier's avatar
gauthier committed
219 220
      printk("[UE_IP_DRV][%s] ERROR, device is null\n", __FUNCTION__);
      return -1;
gauthier's avatar
gauthier committed
221 222 223 224 225 226 227
  }

  if ((inst>=0) && (inst<UE_IP_NB_INSTANCES_MAX)) {
      #ifdef OAI_DRV_OAI_DRV_DEBUG_DEVICE
      printk("[UE_IP_DRV][%s] inst %d,  begin\n", __FUNCTION__,inst);
      #endif

gauthier's avatar
gauthier committed
228
      if (!skb_pP){
gauthier's avatar
gauthier committed
229 230 231 232
          printk("[UE_IP_DRV][%s] input parameter skb is NULL\n", __FUNCTION__);
          return -1;
      }
      // End debug information
gauthier's avatar
gauthier committed
233 234
      netif_stop_queue(dev_pP);
      dev_pP->trans_start = jiffies;
gauthier's avatar
gauthier committed
235 236 237
      #ifdef OAI_DRV_DEBUG_DEVICE
      printk("[UE_IP_DRV][%s] step 1\n", __FUNCTION__);
      #endif
gauthier's avatar
gauthier committed
238
      ue_ip_common_ip2wireless(skb_pP,inst);
gauthier's avatar
gauthier committed
239 240 241
      #ifdef OAI_DRV_DEBUG_DEVICE
      printk("[UE_IP_DRV][%s] step 2\n", __FUNCTION__);
      #endif
gauthier's avatar
gauthier committed
242
      dev_kfree_skb(skb_pP);
gauthier's avatar
gauthier committed
243 244 245
      #ifdef OAI_DRV_DEBUG_DEVICE
      printk("[UE_IP_DRV][%s] step 3\n", __FUNCTION__);
      #endif
gauthier's avatar
gauthier committed
246
      netif_wake_queue(dev_pP);
gauthier's avatar
gauthier committed
247 248 249 250 251 252 253 254 255 256 257
      #ifdef OAI_DRV_DEBUG_DEVICE
      printk("[UE_IP_DRV][%s] end\n", __FUNCTION__);
      #endif
  } else {
      printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__);
      return(-1);
  }
  return 0;
}

//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
258
struct net_device_stats *ue_ip_get_stats(struct net_device *dev_pP){
gauthier's avatar
gauthier committed
259
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
260 261
  ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
  return &priv_p->stats;
gauthier's avatar
gauthier committed
262 263
}
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
264
int ue_ip_set_mac_address(struct net_device *dev_pP, void *mac_pP) {
gauthier's avatar
gauthier committed
265
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
266
  //struct sockaddr *addr = mac_pP;
gauthier's avatar
gauthier committed
267
  printk("[UE_IP_DRV][%s] CHANGE MAC ADDRESS UNSUPPORTED\n", __FUNCTION__);
gauthier's avatar
gauthier committed
268
  //memcpy(dev_pP->dev_addr, addr->sa_data, dev_pP->addr_len);
gauthier's avatar
gauthier committed
269 270 271
  return 0;
}
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
272
int ue_ip_change_mtu(struct net_device *dev_pP, int mtuP){
gauthier's avatar
gauthier committed
273
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
274 275
  printk("[UE_IP_DRV][%s] CHANGE MTU %d bytes\n", __FUNCTION__, mtuP);
  if ((mtuP<50) || (mtuP>1500))
gauthier's avatar
gauthier committed
276
      return -EINVAL;
gauthier's avatar
gauthier committed
277
  dev_pP->mtu = mtuP;
gauthier's avatar
gauthier committed
278 279 280
  return 0;
}
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
281
void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP){
gauthier's avatar
gauthier committed
282
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
283 284 285
  ue_ip_priv_t *priv_p =  netdev_priv(dev_pP);
  printk("[UE_IP_DRV][%s] CHANGE RX FLAGS %08X\n", __FUNCTION__, flagsP);
  priv_p->rx_flags ^= flagsP;
gauthier's avatar
gauthier committed
286 287 288
}

//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
289
void ue_ip_tx_timeout(struct net_device *dev_pP){
gauthier's avatar
gauthier committed
290 291
  //---------------------------------------------------------------------------
  // Transmitter timeout, serious problems.
gauthier's avatar
gauthier committed
292
  ue_ip_priv_t *priv_p =  netdev_priv(dev_pP);
gauthier's avatar
gauthier committed
293 294

  printk("[UE_IP_DRV][%s] begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
295 296 297 298 299
  //  (ue_ip_priv_t *)(dev_pP->priv_p)->stats.tx_errors++;
  (priv_p->stats).tx_errors++;
  dev_pP->trans_start = jiffies;
  netif_wake_queue(dev_pP);
  printk("[UE_IP_DRV][%s] transmit timed out %s\n", __FUNCTION__,dev_pP->name);
gauthier's avatar
gauthier committed
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
}

static const struct net_device_ops ue_ip_netdev_ops = {
    .ndo_open               = ue_ip_open,
    .ndo_stop               = ue_ip_stop,
    .ndo_start_xmit         = ue_ip_hard_start_xmit,
    .ndo_validate_addr      = NULL,
    .ndo_get_stats          = ue_ip_get_stats,
    .ndo_set_mac_address    = ue_ip_set_mac_address,
    .ndo_set_config         = ue_ip_set_config,
    .ndo_do_ioctl           = NULL,
    .ndo_change_mtu         = ue_ip_change_mtu,
    .ndo_tx_timeout         = ue_ip_tx_timeout,
    .ndo_change_rx_flags    = ue_ip_change_rx_flags,
};
    /*.ndo_set_multicast_list = NULL,*/

//---------------------------------------------------------------------------
// Initialisation of the network device
gauthier's avatar
gauthier committed
319
void ue_ip_init(struct net_device *dev_pP){
gauthier's avatar
gauthier committed
320
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
321 322 323 324 325
  ue_ip_priv_t *priv_p = NULL;
    if (dev_pP) {
        priv_p = netdev_priv(dev_pP);
        memset(priv_p, 0, sizeof(ue_ip_priv_t));
        spin_lock_init(&priv_p->lock);
gauthier's avatar
gauthier committed
326
        #ifdef KERNEL_VERSION_GREATER_THAN_2629
gauthier's avatar
gauthier committed
327
        dev_pP->netdev_ops = &ue_ip_netdev_ops;
gauthier's avatar
gauthier committed
328 329 330
        #else
        #error "KERNEL VERSION MUST BE NEWER THAN 2.6.29"
        #endif
gauthier's avatar
gauthier committed
331 332 333 334 335
        dev_pP->hard_header_len = 0;
        dev_pP->addr_len = UE_IP_ADDR_LEN;
        dev_pP->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP;
        dev_pP->tx_queue_len = UE_IP_TX_QUEUE_LEN;
        dev_pP->mtu = UE_IP_MTU;
gauthier's avatar
gauthier committed
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
    } else {
        printk("[UE_IP_DRV][%s] ERROR, Device is NULL!!\n", __FUNCTION__);
        return;
    }
}
//---------------------------------------------------------------------------
int init_module (void) {
//---------------------------------------------------------------------------
  int err,inst;
  char devicename[100];


  // Initialize parameters shared with RRC
  printk("[UE_IP_DRV][%s] Starting OAI IP driver", __FUNCTION__);

  for (inst=0;inst<UE_IP_NB_INSTANCES_MAX;inst++) {
    printk("[UE_IP_DRV][%s] begin init instance %d\n", __FUNCTION__,inst);
    sprintf(devicename,"oip%d",inst);
gauthier's avatar
gauthier committed
354
    ue_ip_dev[inst]  = alloc_netdev(sizeof(ue_ip_priv_t),devicename, ue_ip_init);
gauthier's avatar
gauthier committed
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
    //netif_stop_queue(ue_ip_dev[inst]);
    if (ue_ip_dev[inst] == NULL) {
         printk("[UE_IP_DRV][%s][INST %02d] alloc_netdev FAILED\n", __FUNCTION__,inst);
    } else {
        // linux/net/core/dev.c line 4767
        err= register_netdev(ue_ip_dev[inst]);
        if (err){
          printk("[UE_IP_DRV][%s] (inst %d): error %i registering device %s\n", __FUNCTION__, inst,err, ue_ip_dev[inst]->name);
        }else{
          printk("[UE_IP_DRV][%s] registering device %s, ifindex = %d\n\n", __FUNCTION__,ue_ip_dev[inst]->name, ue_ip_dev[inst]->ifindex);
        }
    }
  }

  printk("[UE_IP_DRV][%s] NETLINK INIT\n", __FUNCTION__);
  if ((err=ue_ip_netlink_init()) == -1)
    printk("[UE_IP_DRV][%s] NETLINK failed\n", __FUNCTION__);

  return err;

}

//---------------------------------------------------------------------------
void cleanup_module(void){
//---------------------------------------------------------------------------
    int inst;

    printk("[UE_IP_DRV][CLEANUP]nasmesh_cleanup_module: begin\n");

    for (inst=0;inst<UE_IP_NB_INSTANCES_MAX;inst++) {
#ifdef OAI_DRV_DEBUG_DEVICE
        printk("nasmesh_cleanup_module: unregister and free net device instance %d\n",inst);
#endif
        if (ue_ip_dev[inst]) {
            unregister_netdev(ue_ip_dev[inst]);
            ue_ip_teardown(ue_ip_dev[inst]);
            free_netdev(ue_ip_dev[inst]);
        }
    }
    ue_ip_netlink_release();
    printk("nasmesh_cleanup_module: end\n");
}

#define DRV_NAME        "ue_ip"
#define DRV_VERSION     "1.0"DRV_NAME
#define DRV_DESCRIPTION "OPENAIR UE IP Device Driver"
#define DRV_COPYRIGHT   "-Copyright(c) GNU GPL Eurecom 2013"
#define DRV_AUTHOR      "Lionel GAUTHIER: <firstname.name@eurecom.fr>"DRV_COPYRIGHT