device.c 13.9 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
* \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>
thomasl's avatar
thomasl committed
51
#include <linux/version.h>
gauthier's avatar
gauthier committed
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
#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
74
int ue_ip_find_inst(struct net_device *dev_pP) {
gauthier's avatar
gauthier committed
75 76 77 78
//---------------------------------------------------------------------------
  int i;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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
317
void ue_ip_init(struct net_device *dev_pP){
gauthier's avatar
gauthier committed
318
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
319 320 321 322 323 324 325 326 327 328 329
  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);
        dev_pP->netdev_ops = &ue_ip_netdev_ops;
        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
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    } 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);
thomasl's avatar
thomasl committed
348
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
gauthier's avatar
gauthier committed
349
    ue_ip_dev[inst]  = alloc_netdev(sizeof(ue_ip_priv_t),devicename, ue_ip_init);
thomasl's avatar
thomasl committed
350 351 352
#else
    ue_ip_dev[inst]  = alloc_netdev(sizeof(ue_ip_priv_t),devicename, NET_NAME_PREDICTABLE,ue_ip_init);
#endif
gauthier's avatar
gauthier committed
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 402
    //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