device.c 12.4 KB
Newer Older
gauthier's avatar
gauthier committed
1
2
/*! \file device.c
* \brief Networking Device Driver for OpenAirInterface
nikaeinn's avatar
nikaeinn committed
3
* \author  navid nikaein,  Lionel Gauthier, raymond knopp
gauthier's avatar
gauthier committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
* \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
22
#include <linux/version.h>
gauthier's avatar
gauthier committed
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#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

//---------------------------------------------------------------------------
45
46
47
int ue_ip_find_inst(struct net_device *dev_pP)
{
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
48
49
  int i;

50
  for (i=0; i<UE_IP_NB_INSTANCES_MAX; i++)
51
    if (ue_ip_dev[i] == dev_pP) {
gauthier's avatar
gauthier committed
52
      return(i);
53
    }
54

gauthier's avatar
gauthier committed
55
56
57
58
59
60
  return(-1);
}

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

#ifndef OAI_NW_DRIVER_USE_NETLINK
61
62
void *ue_ip_interrupt(void)
{
gauthier's avatar
gauthier committed
63
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
64
  uint8_t cxi;
gauthier's avatar
gauthier committed
65

gauthier's avatar
gauthier committed
66
  //  ue_ip_priv_t *priv_p=netdev_priv(dev_id);
gauthier's avatar
gauthier committed
67
  //  unsigned int flags;
gauthier's avatar
gauthier committed
68
  //  priv_p->lock = SPIN_LOCK_UNLOCKED;
gauthier's avatar
gauthier committed
69
70
71
72

#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT - begin\n");
#endif
gauthier's avatar
gauthier committed
73
  //  spin_lock_irqsave(&priv_p->lock,flags);
gauthier's avatar
gauthier committed
74
75
76
77
78
79
  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
80
  //  spin_unlock_irqrestore(&priv_p->lock,flags);
gauthier's avatar
gauthier committed
81
82
83
84
85
86
87
#ifdef OAI_DRV_DEBUG_INTERRUPT
  printk("INTERRUPT: end\n");
#endif
  //  return 0;
}
#endif //NETLINK
//---------------------------------------------------------------------------
88
89
void ue_ip_timer(unsigned long dataP)
{
gauthier's avatar
gauthier committed
90
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
91
92
93
94
95
96
97
  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
98
  return;
99
100
  //  add_timer(&gpriv->timer);
  //  spin_unlock(&gpriv->lock);
gauthier's avatar
gauthier committed
101
102
103
104
}

//---------------------------------------------------------------------------
// Called by ifconfig when the device is activated by ifconfig
105
106
int ue_ip_open(struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
107
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
108
  ue_ip_priv_t *priv_p=netdev_priv(dev_pP);
gauthier's avatar
gauthier committed
109
110
111

  // Address has already been set at init
#ifndef OAI_NW_DRIVER_USE_NETLINK
112
113
114
115

  if (pdcp_2_ue_ip_irq==-EBUSY) {
    printk("[UE_IP_DRV][%s] : irq failure\n", __FUNCTION__);
    return -EBUSY;
gauthier's avatar
gauthier committed
116
  }
117

gauthier's avatar
gauthier committed
118
119
#endif //OAI_NW_DRIVER_USE_NETLINK

120
  if(!netif_queue_stopped(dev_pP)) {
121
    netif_start_queue(dev_pP);
122
  } else {
123
    netif_wake_queue(dev_pP);
124
  }
gauthier's avatar
gauthier committed
125

gauthier's avatar
gauthier committed
126
127
128
129
130
  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
131

gauthier's avatar
gauthier committed
132
  printk("[UE_IP_DRV][%s] name = %s\n", __FUNCTION__, dev_pP->name);
gauthier's avatar
gauthier committed
133
134
135
136
137
  return 0;
}

//---------------------------------------------------------------------------
// Called by ifconfig when the device is desactivated
138
139
int ue_ip_stop(struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
140
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
141
  ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
gauthier's avatar
gauthier committed
142
143

  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
gauthier's avatar
gauthier committed
144
145
  del_timer(&(priv_p->timer));
  netif_stop_queue(dev_pP);
gauthier's avatar
gauthier committed
146
147
148
149
150
151
  //    MOD_DEC_USE_COUNT;
  printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
  return 0;
}

//---------------------------------------------------------------------------
152
153
void ue_ip_teardown(struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
154
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
155
  ue_ip_priv_t    *priv_p;
gauthier's avatar
gauthier committed
156
157
158
  int              inst;

  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
159

gauthier's avatar
gauthier committed
160
  if (dev_pP) {
161
162
    priv_p = netdev_priv(dev_pP);
    inst = ue_ip_find_inst(dev_pP);
gauthier's avatar
gauthier committed
163

164
165
166
167
    if ((inst<0) || (inst>=UE_IP_NB_INSTANCES_MAX)) {
      printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__);
      return;
    }
gauthier's avatar
gauthier committed
168

169
170

    printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
gauthier's avatar
gauthier committed
171
  } // check dev_pP
gauthier's avatar
gauthier committed
172
  else {
173
    printk("[UE_IP_DRV][%s] Device is null\n", __FUNCTION__);
gauthier's avatar
gauthier committed
174
175
176
  }
}
//---------------------------------------------------------------------------
177
178
int ue_ip_set_config(struct net_device *dev_pP, struct ifmap *map_pP)
{
gauthier's avatar
gauthier committed
179
180
  //---------------------------------------------------------------------------
  printk("[UE_IP_DRV][%s] Begin\n", __FUNCTION__);
181

182
  if (dev_pP->flags & IFF_UP) {
183
    return -EBUSY;
184
  }
185

gauthier's avatar
gauthier committed
186
  if (map_pP->base_addr != dev_pP->base_addr) {
187
188
    printk(KERN_WARNING "[UE_IP_DRV][%s] Can't change I/O address\n", __FUNCTION__);
    return -EOPNOTSUPP;
gauthier's avatar
gauthier committed
189
  }
190

191
  if (map_pP->irq != dev_pP->irq) {
192
    dev_pP->irq = map_pP->irq;
193
  }
194

gauthier's avatar
gauthier committed
195
196
197
198
199
200
  printk("[UE_IP_DRV][%s] End\n", __FUNCTION__);
  return 0;
}

//---------------------------------------------------------------------------
//
201
202
int ue_ip_hard_start_xmit(struct sk_buff *skb_pP, struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
203
204
205
  //---------------------------------------------------------------------------
  int inst;

gauthier's avatar
gauthier committed
206
  if (dev_pP) {
207
    inst = ue_ip_find_inst(dev_pP);
gauthier's avatar
gauthier committed
208
  } else {
209
210
    printk("[UE_IP_DRV][%s] ERROR, device is null\n", __FUNCTION__);
    return -1;
gauthier's avatar
gauthier committed
211
212
213
  }

  if ((inst>=0) && (inst<UE_IP_NB_INSTANCES_MAX)) {
214
215
216
#ifdef OAI_DRV_OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] inst %d,  begin\n", __FUNCTION__,inst);
#endif
gauthier's avatar
gauthier committed
217

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
    if (!skb_pP) {
      printk("[UE_IP_DRV][%s] input parameter skb is NULL\n", __FUNCTION__);
      return -1;
    }

    // End debug information
    netif_stop_queue(dev_pP);
    dev_pP->trans_start = jiffies;
#ifdef OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] step 1\n", __FUNCTION__);
#endif
    ue_ip_common_ip2wireless(skb_pP,inst);
#ifdef OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] step 2\n", __FUNCTION__);
#endif
    dev_kfree_skb(skb_pP);
#ifdef OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] step 3\n", __FUNCTION__);
#endif
    netif_wake_queue(dev_pP);
#ifdef OAI_DRV_DEBUG_DEVICE
    printk("[UE_IP_DRV][%s] end\n", __FUNCTION__);
#endif
gauthier's avatar
gauthier committed
241
  } else {
242
243
    printk("[UE_IP_DRV][%s] ERROR, couldn't find instance\n", __FUNCTION__);
    return(-1);
gauthier's avatar
gauthier committed
244
  }
245

gauthier's avatar
gauthier committed
246
247
248
249
  return 0;
}

//---------------------------------------------------------------------------
250
251
252
struct net_device_stats *ue_ip_get_stats(struct net_device *dev_pP)
{
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
253
254
  ue_ip_priv_t *priv_p = netdev_priv(dev_pP);
  return &priv_p->stats;
gauthier's avatar
gauthier committed
255
256
}
//---------------------------------------------------------------------------
257
258
259
int ue_ip_set_mac_address(struct net_device *dev_pP, void *mac_pP)
{
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
260
  //struct sockaddr *addr = mac_pP;
gauthier's avatar
gauthier committed
261
  printk("[UE_IP_DRV][%s] CHANGE MAC ADDRESS UNSUPPORTED\n", __FUNCTION__);
gauthier's avatar
gauthier committed
262
  //memcpy(dev_pP->dev_addr, addr->sa_data, dev_pP->addr_len);
gauthier's avatar
gauthier committed
263
264
265
  return 0;
}
//---------------------------------------------------------------------------
266
267
int ue_ip_change_mtu(struct net_device *dev_pP, int mtuP)
{
gauthier's avatar
gauthier committed
268
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
269
  printk("[UE_IP_DRV][%s] CHANGE MTU %d bytes\n", __FUNCTION__, mtuP);
270

271
  if ((mtuP<50) || (mtuP>1500)) {
272
    return -EINVAL;
273
  }
274

gauthier's avatar
gauthier committed
275
  dev_pP->mtu = mtuP;
gauthier's avatar
gauthier committed
276
277
278
  return 0;
}
//---------------------------------------------------------------------------
279
280
void ue_ip_change_rx_flags(struct net_device *dev_pP, int flagsP)
{
gauthier's avatar
gauthier committed
281
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
282
283
284
  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
285
286
287
}

//---------------------------------------------------------------------------
288
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
}

static const struct net_device_ops ue_ip_netdev_ops = {
303
304
305
306
307
308
309
310
311
312
313
  .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,
gauthier's avatar
gauthier committed
314
};
315
/*.ndo_set_multicast_list = NULL,*/
gauthier's avatar
gauthier committed
316
317
318

//---------------------------------------------------------------------------
// Initialisation of the network device
319
320
void ue_ip_init(struct net_device *dev_pP)
{
gauthier's avatar
gauthier committed
321
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
322
  ue_ip_priv_t *priv_p = NULL;
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

  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;
  } else {
    printk("[UE_IP_DRV][%s] ERROR, Device is NULL!!\n", __FUNCTION__);
    return;
  }
gauthier's avatar
gauthier committed
338
339
}
//---------------------------------------------------------------------------
340
341
342
int init_module (void)
{
  //---------------------------------------------------------------------------
gauthier's avatar
gauthier committed
343
344
345
346
347
348
349
  int err,inst;
  char devicename[100];


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

350
  for (inst=0; inst<UE_IP_NB_INSTANCES_MAX; inst++) {
gauthier's avatar
gauthier committed
351
352
    printk("[UE_IP_DRV][%s] begin init instance %d\n", __FUNCTION__,inst);
    sprintf(devicename,"oip%d",inst);
thomasl's avatar
thomasl committed
353
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
gauthier's avatar
gauthier committed
354
    ue_ip_dev[inst]  = alloc_netdev(sizeof(ue_ip_priv_t),devicename, ue_ip_init);
thomasl's avatar
thomasl committed
355
356
357
#else
    ue_ip_dev[inst]  = alloc_netdev(sizeof(ue_ip_priv_t),devicename, NET_NAME_PREDICTABLE,ue_ip_init);
#endif
358

gauthier's avatar
gauthier committed
359
360
    //netif_stop_queue(ue_ip_dev[inst]);
    if (ue_ip_dev[inst] == NULL) {
361
      printk("[UE_IP_DRV][%s][INST %02d] alloc_netdev FAILED\n", __FUNCTION__,inst);
gauthier's avatar
gauthier committed
362
    } else {
363
364
365
366
367
368
369
370
      // 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);
      }
gauthier's avatar
gauthier committed
371
372
373
374
    }
  }

  printk("[UE_IP_DRV][%s] NETLINK INIT\n", __FUNCTION__);
375

376
  if ((err=ue_ip_netlink_init()) == -1) {
gauthier's avatar
gauthier committed
377
    printk("[UE_IP_DRV][%s] NETLINK failed\n", __FUNCTION__);
378
  }
gauthier's avatar
gauthier committed
379
380
381
382
383
384

  return err;

}

//---------------------------------------------------------------------------
385
386
387
388
void cleanup_module(void)
{
  //---------------------------------------------------------------------------
  int inst;
gauthier's avatar
gauthier committed
389

390
  printk("[UE_IP_DRV][CLEANUP] begin\n");
gauthier's avatar
gauthier committed
391

392
  for (inst=0; inst<UE_IP_NB_INSTANCES_MAX; inst++) {
gauthier's avatar
gauthier committed
393
#ifdef OAI_DRV_DEBUG_DEVICE
394
    printk("[UE_IP_DRV][CLEANUP]  unregister and free net device instance %d\n",inst);
gauthier's avatar
gauthier committed
395
#endif
396
397
398
399
400

    if (ue_ip_dev[inst]) {
      unregister_netdev(ue_ip_dev[inst]);
      ue_ip_teardown(ue_ip_dev[inst]);
      free_netdev(ue_ip_dev[inst]);
gauthier's avatar
gauthier committed
401
    }
402
403
404
  }

  ue_ip_netlink_release();
405
  printk("[UE_IP_DRV][CLEANUP] end\n");
gauthier's avatar
gauthier committed
406
407
408
409
410
411
412
413
414
}

#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