device.c 13.8 KB
Newer Older
gauthier's avatar
gauthier committed
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn 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
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that 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 OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
nikaeinn's avatar
nikaeinn committed
27

gauthier's avatar
gauthier committed
28 29 30 31
*******************************************************************************/

/*! \file device.c
* \brief Networking Device Driver for OpenAirInterface
nikaeinn's avatar
nikaeinn committed
32
* \author  navid nikaein,  Lionel Gauthier, raymond knopp
gauthier's avatar
gauthier committed
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
* \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
73
int ue_ip_find_inst(struct net_device *dev_pP) {
gauthier's avatar
gauthier committed
74 75 76 77
//---------------------------------------------------------------------------
  int i;

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

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

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

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

#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT - begin\n");
#endif
gauthier's avatar
gauthier committed
97
  //  spin_lock_irqsave(&priv_p->lock,flags);
gauthier's avatar
gauthier committed
98 99 100 101 102 103
  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
104
  //  spin_unlock_irqrestore(&priv_p->lock,flags);
gauthier's avatar
gauthier committed
105 106 107 108 109 110 111
#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT: end\n");
#endif
  //  return 0;
}
#endif //NETLINK
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
112
void ue_ip_timer(unsigned long dataP){
gauthier's avatar
gauthier committed
113
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
114 115 116 117 118 119 120
  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
121 122 123 124 125 126 127
  return;
//  add_timer(&gpriv->timer);
//  spin_unlock(&gpriv->lock);
}

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

  // 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
140 141
  if(!netif_queue_stopped(dev_pP))
      netif_start_queue(dev_pP);
gauthier's avatar
gauthier committed
142
  else
gauthier's avatar
gauthier committed
143
      netif_wake_queue(dev_pP);
gauthier's avatar
gauthier committed
144

gauthier's avatar
gauthier committed
145 146 147 148 149
  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
150

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

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

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

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

  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
176 177 178
  if (dev_pP) {
      priv_p = netdev_priv(dev_pP);
      inst = ue_ip_find_inst(dev_pP);
gauthier's avatar
gauthier committed
179 180 181 182 183 184 185
      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
186
  } // check dev_pP
gauthier's avatar
gauthier committed
187 188 189 190 191
  else {
      printk("[UE_IP_DRV][%s] Device is null\n", __FUNCTION__);
  }
}
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
192
int ue_ip_set_config(struct net_device *dev_pP, struct ifmap *map_pP){
gauthier's avatar
gauthier committed
193 194
  //---------------------------------------------------------------------------
  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
195
  if (dev_pP->flags & IFF_UP)
gauthier's avatar
gauthier committed
196
      return -EBUSY;
gauthier's avatar
gauthier committed
197
  if (map_pP->base_addr != dev_pP->base_addr) {
gauthier's avatar
gauthier committed
198 199 200
      printk(KERN_WARNING "[UE_IP_DRV][%s] Can't change I/O address\n", __FUNCTION__);
      return -EOPNOTSUPP;
  }
gauthier's avatar
gauthier committed
201 202
  if (map_pP->irq != dev_pP->irq)
      dev_pP->irq = map_pP->irq;
gauthier's avatar
gauthier committed
203 204 205 206 207 208
  printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
  return 0;
}

//---------------------------------------------------------------------------
//
gauthier's avatar
gauthier committed
209
int ue_ip_hard_start_xmit(struct sk_buff *skb_pP, struct net_device *dev_pP){
gauthier's avatar
gauthier committed
210 211 212
  //---------------------------------------------------------------------------
  int inst;

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

  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
225
      if (!skb_pP){
gauthier's avatar
gauthier committed
226 227 228 229
          printk("[UE_IP_DRV][%s] input parameter skb is NULL\n", __FUNCTION__);
          return -1;
      }
      // End debug information
gauthier's avatar
gauthier committed
230 231
      netif_stop_queue(dev_pP);
      dev_pP->trans_start = jiffies;
gauthier's avatar
gauthier committed
232 233 234
      #ifdef OAI_DRV_DEBUG_DEVICE
      printk("[UE_IP_DRV][%s] step 1\n", __FUNCTION__);
      #endif
gauthier's avatar
gauthier committed
235
      ue_ip_common_ip2wireless(skb_pP,inst);
gauthier's avatar
gauthier committed
236 237 238
      #ifdef OAI_DRV_DEBUG_DEVICE
      printk("[UE_IP_DRV][%s] step 2\n", __FUNCTION__);
      #endif
gauthier's avatar
gauthier committed
239
      dev_kfree_skb(skb_pP);
gauthier's avatar
gauthier committed
240 241 242
      #ifdef OAI_DRV_DEBUG_DEVICE
      printk("[UE_IP_DRV][%s] step 3\n", __FUNCTION__);
      #endif
gauthier's avatar
gauthier committed
243
      netif_wake_queue(dev_pP);
gauthier's avatar
gauthier committed
244 245 246 247 248 249 250 251 252 253 254
      #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
255
struct net_device_stats *ue_ip_get_stats(struct net_device *dev_pP){
gauthier's avatar
gauthier committed
256
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
257 258
  ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
  return &priv_p->stats;
gauthier's avatar
gauthier committed
259 260
}
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
261
int ue_ip_set_mac_address(struct net_device *dev_pP, void *mac_pP) {
gauthier's avatar
gauthier committed
262
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
263
  //struct sockaddr *addr = mac_pP;
gauthier's avatar
gauthier committed
264
  printk("[UE_IP_DRV][%s] CHANGE MAC ADDRESS UNSUPPORTED\n", __FUNCTION__);
gauthier's avatar
gauthier committed
265
  //memcpy(dev_pP->dev_addr, addr->sa_data, dev_pP->addr_len);
gauthier's avatar
gauthier committed
266 267 268
  return 0;
}
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
269
int ue_ip_change_mtu(struct net_device *dev_pP, int mtuP){
gauthier's avatar
gauthier committed
270
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
271 272
  printk("[UE_IP_DRV][%s] CHANGE MTU %d bytes\n", __FUNCTION__, mtuP);
  if ((mtuP<50) || (mtuP>1500))
gauthier's avatar
gauthier committed
273
      return -EINVAL;
gauthier's avatar
gauthier committed
274
  dev_pP->mtu = mtuP;
gauthier's avatar
gauthier committed
275 276 277
  return 0;
}
//---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
278
void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP){
gauthier's avatar
gauthier committed
279
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
280 281 282
  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
283 284 285
}

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

  printk("[UE_IP_DRV][%s] begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
292 293 294 295 296
  //  (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
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
}

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
316
void ue_ip_init(struct net_device *dev_pP){
gauthier's avatar
gauthier committed
317
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
318 319 320 321 322
  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
323
        #ifdef KERNEL_VERSION_GREATER_THAN_2629
gauthier's avatar
gauthier committed
324
        dev_pP->netdev_ops = &ue_ip_netdev_ops;
gauthier's avatar
gauthier committed
325 326 327
        #else
        #error "KERNEL VERSION MUST BE NEWER THAN 2.6.29"
        #endif
gauthier's avatar
gauthier committed
328 329 330 331 332
        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
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
    } 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
351
    ue_ip_dev[inst]  = alloc_netdev(sizeof(ue_ip_priv_t),devicename, ue_ip_init);
gauthier's avatar
gauthier committed
352 353 354 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
    //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