Merge branch 'pm-cpufreq'
[linux-2.6-block.git] / drivers / staging / wilc1000 / linux_mon.c
CommitLineData
c5c77ba1
JK
1/*!
2 * @file linux_mon.c
3 * @brief File Operations OS wrapper functionality
4 * @author mdaftedar
5 * @sa wilc_wfi_netdevice.h
6 * @date 01 MAR 2012
7 * @version 1.0
8 */
c5c77ba1
JK
9#include "wilc_wfi_cfgoperations.h"
10#include "linux_wlan_common.h"
11#include "wilc_wlan_if.h"
12#include "wilc_wlan.h"
9690df3f 13
c5c77ba1
JK
14#ifdef WILC_FULLY_HOSTING_AP
15#include "wilc_host_ap.h"
16#endif
17#ifdef WILC_AP_EXTERNAL_MLME
c5c77ba1
JK
18
19struct wilc_wfi_radiotap_hdr {
20 struct ieee80211_radiotap_header hdr;
21 u8 rate;
22 /* u32 channel; */
23} __attribute__((packed));
24
25struct wilc_wfi_radiotap_cb_hdr {
26 struct ieee80211_radiotap_header hdr;
27 u8 rate;
28 u8 dump;
29 u16 tx_flags;
30 /* u32 channel; */
31} __attribute__((packed));
32
33extern linux_wlan_t *g_linux_wlan;
34
35static struct net_device *wilc_wfi_mon; /* global monitor netdev */
36
9690df3f 37#if USE_WIRELESS
c5c77ba1
JK
38extern int mac_xmit(struct sk_buff *skb, struct net_device *dev);
39#endif
40
41
63d03e47
GKH
42u8 srcAdd[6];
43u8 bssid[6];
44u8 broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
c5c77ba1
JK
45/**
46 * @brief WILC_WFI_monitor_rx
47 * @details
48 * @param[in]
49 * @return int : Return 0 on Success
50 * @author mdaftedar
51 * @date 12 JUL 2012
52 * @version 1.0
53 */
54
55#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
56#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/
57#define IS_MANAGMEMENT 0x100
58#define IS_MANAGMEMENT_CALLBACK 0x080
59#define IS_MGMT_STATUS_SUCCES 0x040
60#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
61
62void WILC_WFI_monitor_rx(uint8_t *buff, uint32_t size)
63{
64 uint32_t header, pkt_offset;
65 struct sk_buff *skb = NULL;
66 struct wilc_wfi_radiotap_hdr *hdr;
67 struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
68
69 PRINT_INFO(HOSTAPD_DBG, "In monitor interface receive function\n");
70
71 /* struct WILC_WFI_priv *priv = netdev_priv(dev); */
72
73 /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
74
75 /* Bug 4601 */
76 if (wilc_wfi_mon == NULL)
77 return;
78
79 if (!netif_running(wilc_wfi_mon)) {
80 PRINT_INFO(HOSTAPD_DBG, "Monitor interface already RUNNING\n");
81 return;
82 }
83
84 /* Get WILC header */
85 memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
86
87 /* The packet offset field conain info about what type of managment frame */
88 /* we are dealing with and ack status */
89 pkt_offset = GET_PKT_OFFSET(header);
90
91 if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
92
93 /* hostapd callback mgmt frame */
94
95 skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr));
96 if (skb == NULL) {
97 PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb");
98 return;
99 }
100
101 memcpy(skb_put(skb, size), buff, size);
102
103 cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr));
104 memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
105
106 cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
107
108 cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
109
110 cb_hdr->hdr.it_present = cpu_to_le32(
111 (1 << IEEE80211_RADIOTAP_RATE) |
112 (1 << IEEE80211_RADIOTAP_TX_FLAGS));
113
114 cb_hdr->rate = 5; /* txrate->bitrate / 5; */
115
116 if (pkt_offset & IS_MGMT_STATUS_SUCCES) {
117 /* success */
118 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS;
119 } else {
120 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL;
121 }
122
123 } else {
124
125 skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr));
126
127 if (skb == NULL) {
128 PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb");
129 return;
130 }
131
132 /* skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); */
133 /* if (skb == NULL) */
134 /* return; */
135
136 memcpy(skb_put(skb, size), buff, size);
137 hdr = (struct wilc_wfi_radiotap_hdr *) skb_push(skb, sizeof(*hdr));
138 memset(hdr, 0, sizeof(struct wilc_wfi_radiotap_hdr));
139 hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
140 /* hdr->hdr.it_pad = 0; */
141 hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr));
142 PRINT_INFO(HOSTAPD_DBG, "Radiotap len %d\n", hdr->hdr.it_len);
143 hdr->hdr.it_present = cpu_to_le32
144 (1 << IEEE80211_RADIOTAP_RATE); /* | */
145 /* (1 << IEEE80211_RADIOTAP_CHANNEL)); */
146 PRINT_INFO(HOSTAPD_DBG, "Presentflags %d\n", hdr->hdr.it_present);
147 hdr->rate = 5; /* txrate->bitrate / 5; */
148
149 }
150
151/* if(INFO || if(skb->data[9] == 0x00 || skb->data[9] == 0xb0))
152 * {
153 * for(i=0;i<skb->len;i++)
154 * PRINT_INFO(HOSTAPD_DBG,"Mon RxData[%d] = %02x\n",i,skb->data[i]);
155 * }*/
156
157
158 skb->dev = wilc_wfi_mon;
159 skb_set_mac_header(skb, 0);
160 skb->ip_summed = CHECKSUM_UNNECESSARY;
161 skb->pkt_type = PACKET_OTHERHOST;
162 skb->protocol = htons(ETH_P_802_2);
163 memset(skb->cb, 0, sizeof(skb->cb));
164
165 netif_rx(skb);
166
167
168}
169
170struct tx_complete_mon_data {
171 int size;
172 void *buff;
173};
174
175static void mgmt_tx_complete(void *priv, int status)
176{
177
178 /* struct sk_buff *skb2; */
179 /* struct wilc_wfi_radiotap_cb_hdr *cb_hdr; */
180
181 struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv;
63d03e47 182 u8 *buf = pv_data->buff;
c5c77ba1
JK
183
184
185
186 if (status == 1) {
187 if (INFO || buf[0] == 0x10 || buf[0] == 0xb0)
188 PRINT_INFO(HOSTAPD_DBG, "Packet sent successfully - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff);
189 } else {
190 PRINT_INFO(HOSTAPD_DBG, "Couldn't send packet - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff);
191 }
192
193
194/* //(skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 )
195 * {
196 * skb2 = dev_alloc_skb(pv_data->size+sizeof(struct wilc_wfi_radiotap_cb_hdr));
197 *
198 * memcpy(skb_put(skb2,pv_data->size),pv_data->buff, pv_data->size);
199 *
200 * cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
201 * memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
202 *
203 * cb_hdr->hdr.it_version = 0;//PKTHDR_RADIOTAP_VERSION;
204 *
205 * cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
206 *
207 * cb_hdr->hdr.it_present = cpu_to_le32(
208 * (1 << IEEE80211_RADIOTAP_RATE) |
209 * (1 << IEEE80211_RADIOTAP_TX_FLAGS));
210 *
211 * cb_hdr->rate = 5;//txrate->bitrate / 5;
212 * cb_hdr->tx_flags = 0x0004;
213 *
214 * skb2->dev = wilc_wfi_mon;
215 * skb_set_mac_header(skb2, 0);
216 * skb2->ip_summed = CHECKSUM_UNNECESSARY;
217 * skb2->pkt_type = PACKET_OTHERHOST;
218 * skb2->protocol = htons(ETH_P_802_2);
219 * memset(skb2->cb, 0, sizeof(skb2->cb));
220 *
221 * netif_rx(skb2);
222 * }*/
223
224 /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */
225 #ifndef WILC_FULLY_HOSTING_AP
226 kfree(pv_data->buff);
227
228 kfree(pv_data);
229 #endif
230}
231static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
232{
c5c77ba1
JK
233 struct tx_complete_mon_data *mgmt_tx = NULL;
234
235 if (dev == NULL) {
236 PRINT_D(HOSTAPD_DBG, "ERROR: dev == NULL\n");
237 return WILC_FAIL;
238 }
c5c77ba1
JK
239
240 netif_stop_queue(dev);
25fe2274 241 mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC);
c5c77ba1
JK
242 if (mgmt_tx == NULL) {
243 PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
244 return WILC_FAIL;
245 }
246
247 #ifdef WILC_FULLY_HOSTING_AP
248 /* add space for the pointer to tx_complete_mon_data */
249 len += sizeof(struct tx_complete_mon_data *);
250 #endif
251
30ef5c8b 252 mgmt_tx->buff = kmalloc(len, GFP_ATOMIC);
c5c77ba1
JK
253 if (mgmt_tx->buff == NULL) {
254 PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
255 return WILC_FAIL;
256
257 }
258
259 mgmt_tx->size = len;
260
261 #ifndef WILC_FULLY_HOSTING_AP
262 memcpy(mgmt_tx->buff, buf, len);
263 #else
264 memcpy(mgmt_tx->buff, buf, len - sizeof(struct tx_complete_mon_data *));
265 memcpy((mgmt_tx->buff) + (len - sizeof(struct tx_complete_mon_data *)), &mgmt_tx, sizeof(struct tx_complete_mon_data *));
266
267 /* filter data frames to handle it's PS */
72ed4dc7 268 if (filter_monitor_data_frames((mgmt_tx->buff), len) == true) {
c5c77ba1
JK
269 return;
270 }
271
272 #endif /* WILC_FULLY_HOSTING_AP */
273
274 g_linux_wlan->oup.wlan_add_mgmt_to_tx_que(mgmt_tx, mgmt_tx->buff, mgmt_tx->size, mgmt_tx_complete);
275
276 netif_wake_queue(dev);
277 return 0;
278}
279
280/**
281 * @brief WILC_WFI_mon_xmit
282 * @details
283 * @param[in]
284 * @return int : Return 0 on Success
285 * @author mdaftedar
286 * @date 12 JUL 2012
287 * @version 1.0
288 */
289static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb,
290 struct net_device *dev)
291{
4e4467fd 292 u32 rtap_len, i, ret = 0;
c5c77ba1
JK
293 struct WILC_WFI_mon_priv *mon_priv;
294
295 struct sk_buff *skb2;
296 struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
297
298 /* Bug 4601 */
299 if (wilc_wfi_mon == NULL)
300 return WILC_FAIL;
301
302 /* if(skb->data[3] == 0x10 || skb->data[3] == 0xb0) */
303
304 mon_priv = netdev_priv(wilc_wfi_mon);
305
306 if (mon_priv == NULL) {
307 PRINT_ER("Monitor interface private structure is NULL\n");
308 return WILC_FAIL;
309 }
310
c5c77ba1
JK
311
312 rtap_len = ieee80211_get_radiotap_len(skb->data);
313 if (skb->len < rtap_len) {
314 PRINT_ER("Error in radiotap header\n");
315 return -1;
316 }
317 /* skip the radiotap header */
318 PRINT_INFO(HOSTAPD_DBG, "Radiotap len: %d\n", rtap_len);
319
320 if (INFO) {
321 for (i = 0; i < rtap_len; i++)
322 PRINT_INFO(HOSTAPD_DBG, "Radiotap_hdr[%d] %02x\n", i, skb->data[i]);
323 }
324 /* Skip the ratio tap header */
325 skb_pull(skb, rtap_len);
326
327 if (skb->data[0] == 0xc0)
328 PRINT_INFO(HOSTAPD_DBG, "%x:%x:%x:%x:%x%x\n", skb->data[4], skb->data[5], skb->data[6], skb->data[7], skb->data[8], skb->data[9]);
329
330 if (skb->data[0] == 0xc0 && (!(memcmp(broadcast, &skb->data[4], 6)))) {
331 skb2 = dev_alloc_skb(skb->len + sizeof(struct wilc_wfi_radiotap_cb_hdr));
332
333 memcpy(skb_put(skb2, skb->len), skb->data, skb->len);
334
335 cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr));
336 memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
337
338 cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
339
340 cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
341
342 cb_hdr->hdr.it_present = cpu_to_le32(
343 (1 << IEEE80211_RADIOTAP_RATE) |
344 (1 << IEEE80211_RADIOTAP_TX_FLAGS));
345
346 cb_hdr->rate = 5; /* txrate->bitrate / 5; */
347 cb_hdr->tx_flags = 0x0004;
348
349 skb2->dev = wilc_wfi_mon;
350 skb_set_mac_header(skb2, 0);
351 skb2->ip_summed = CHECKSUM_UNNECESSARY;
352 skb2->pkt_type = PACKET_OTHERHOST;
353 skb2->protocol = htons(ETH_P_802_2);
354 memset(skb2->cb, 0, sizeof(skb2->cb));
355
356 netif_rx(skb2);
357
358 return 0;
359 }
360 skb->dev = mon_priv->real_ndev;
361
362 PRINT_INFO(HOSTAPD_DBG, "Skipping the radiotap header\n");
363
364
365
366 /* actual deliver of data is device-specific, and not shown here */
367 PRINT_INFO(HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name);
368 PRINT_INFO(HOSTAPD_DBG, "MONITOR real dev name = %s\n", mon_priv->real_ndev->name);
369
9690df3f 370 #if USE_WIRELESS
c5c77ba1
JK
371 /* Identify if Ethernet or MAC header (data or mgmt) */
372 memcpy(srcAdd, &skb->data[10], 6);
373 memcpy(bssid, &skb->data[16], 6);
374 /* if source address and bssid fields are equal>>Mac header */
375 /*send it to mgmt frames handler */
376 if (!(memcmp(srcAdd, bssid, 6))) {
377 mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len);
378 dev_kfree_skb(skb);
379 } else
380 ret = mac_xmit(skb, mon_priv->real_ndev);
381 #endif
382
383 /* return NETDEV_TX_OK; */
384 return ret;
385}
386
387static const struct net_device_ops wilc_wfi_netdev_ops = {
388 .ndo_start_xmit = WILC_WFI_mon_xmit,
389
390};
391
392#ifdef WILC_FULLY_HOSTING_AP
393/*
394 * @brief WILC_mgm_HOSTAPD_ACK
395 * @details report the status of transmitted mgmt frames to HOSTAPD
396 * @param[in] priv : pointer to tx_complete_mon_data struct
397 * bStatus : status of transmission
398 * @author Abd Al-Rahman Diab
399 * @date 9 May 2013
400 * @version 1.0
401 */
72ed4dc7 402void WILC_mgm_HOSTAPD_ACK(void *priv, bool bStatus)
c5c77ba1
JK
403{
404 struct sk_buff *skb;
405 struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
406
407 struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv;
63d03e47 408 u8 *buf = pv_data->buff;
c5c77ba1
JK
409
410 /* len of the original frame without the added pointer at the tail */
d85f5326 411 u16 u16len = (pv_data->size) - sizeof(struct tx_complete_mon_data *);
c5c77ba1
JK
412
413
414 /*if(bStatus == 1){
415 * if(INFO || buf[0] == 0x10 || buf[0] == 0xb0)
416 * PRINT_D(HOSTAPD_DBG,"Packet sent successfully - Size = %d - Address = %p.\n",u16len,pv_data->buff);
417 * }else{
418 * PRINT_D(HOSTAPD_DBG,"Couldn't send packet - Size = %d - Address = %p.\n",u16len,pv_data->buff);
419 * }
420 */
421
422 /* (skb->data[9] == 0x00 || skb->data[9] == 0xb0 || skb->data[9] == 0x40 || skb->data[9] == 0xd0 ) */
423 {
424 skb = dev_alloc_skb(u16len + sizeof(struct wilc_wfi_radiotap_cb_hdr));
425
426 memcpy(skb_put(skb, u16len), pv_data->buff, u16len);
427
428 cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr));
429 memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
430
431 cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
432
433 cb_hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_cb_hdr));
434
435 cb_hdr->hdr.it_present = cpu_to_le32(
436 (1 << IEEE80211_RADIOTAP_RATE) |
437 (1 << IEEE80211_RADIOTAP_TX_FLAGS));
438
439 cb_hdr->rate = 5; /* txrate->bitrate / 5; */
440
441
5a66bf20 442 if (bStatus) {
c5c77ba1
JK
443 /* success */
444 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS;
445 } else {
446 cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL;
447 }
448
449 skb->dev = wilc_wfi_mon;
450 skb_set_mac_header(skb, 0);
451 skb->ip_summed = CHECKSUM_UNNECESSARY;
452 skb->pkt_type = PACKET_OTHERHOST;
453 skb->protocol = htons(ETH_P_802_2);
454 memset(skb->cb, 0, sizeof(skb->cb));
455
456 netif_rx(skb);
457 }
458
459 /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */
460 kfree(pv_data->buff);
461
462 kfree(pv_data);
463
464}
465#endif /* WILC_FULLY_HOSTING_AP */
466
467/**
468 * @brief WILC_WFI_mon_setup
469 * @details
470 * @param[in]
471 * @return int : Return 0 on Success
472 * @author mdaftedar
473 * @date 12 JUL 2012
474 * @version 1.0
475 */
476static void WILC_WFI_mon_setup(struct net_device *dev)
477{
478
479 dev->netdev_ops = &wilc_wfi_netdev_ops;
480 /* dev->destructor = free_netdev; */
481 PRINT_INFO(CORECONFIG_DBG, "In Ethernet setup function\n");
482 ether_setup(dev);
483 dev->tx_queue_len = 0;
484 dev->type = ARPHRD_IEEE80211_RADIOTAP;
8ca1b55a 485 eth_zero_addr(dev->dev_addr);
c5c77ba1
JK
486
487 #ifdef USE_WIRELESS
488 {
489 /* u8 * mac_add; */
490 unsigned char mac_add[] = {0x00, 0x50, 0xc2, 0x5e, 0x10, 0x8f};
491 /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
63d03e47 492 /* mac_add = (u8*)WILC_MALLOC(ETH_ALEN); */
c5c77ba1
JK
493 /* status = host_int_get_MacAddress(priv->hWILCWFIDrv,mac_add); */
494 /* mac_add[ETH_ALEN-1]+=1; */
495 memcpy(dev->dev_addr, mac_add, ETH_ALEN);
496 }
497 #else
498 dev->dev_addr[0] = 0x12;
499 #endif
500
501}
502
503/**
504 * @brief WILC_WFI_init_mon_interface
505 * @details
506 * @param[in]
507 * @return int : Return 0 on Success
508 * @author mdaftedar
509 * @date 12 JUL 2012
510 * @version 1.0
511 */
057d1e97 512struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_device *real_dev)
c5c77ba1
JK
513{
514
515
4e4467fd 516 u32 ret = WILC_SUCCESS;
c5c77ba1
JK
517 struct WILC_WFI_mon_priv *priv;
518
519 /*If monitor interface is already initialized, return it*/
520 if (wilc_wfi_mon) {
521 return wilc_wfi_mon;
522 }
c5c77ba1
JK
523
524 wilc_wfi_mon = alloc_etherdev(sizeof(struct WILC_WFI_mon_priv));
525 if (!wilc_wfi_mon) {
526 PRINT_ER("failed to allocate memory\n");
527 return NULL;
528
529 }
530
531 wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP;
532 strncpy(wilc_wfi_mon->name, name, IFNAMSIZ);
533 wilc_wfi_mon->name[IFNAMSIZ - 1] = 0;
534 wilc_wfi_mon->netdev_ops = &wilc_wfi_netdev_ops;
535
536 ret = register_netdevice(wilc_wfi_mon);
537 if (ret) {
538 PRINT_ER(" register_netdevice failed (%d)\n", ret);
539 return NULL;
540 }
541 priv = netdev_priv(wilc_wfi_mon);
542 if (priv == NULL) {
543 PRINT_ER("private structure is NULL\n");
544 return NULL;
545 }
546
547 priv->real_ndev = real_dev;
548
549 return wilc_wfi_mon;
550}
551
552/**
553 * @brief WILC_WFI_deinit_mon_interface
554 * @details
555 * @param[in]
556 * @return int : Return 0 on Success
557 * @author mdaftedar
558 * @date 12 JUL 2012
559 * @version 1.0
560 */
a96c47e1 561int WILC_WFI_deinit_mon_interface(void)
c5c77ba1
JK
562{
563 bool rollback_lock = false;
564
565 if (wilc_wfi_mon != NULL) {
566 PRINT_D(HOSTAPD_DBG, "In Deinit monitor interface\n");
567 PRINT_D(HOSTAPD_DBG, "RTNL is being locked\n");
568 if (rtnl_is_locked()) {
569 rtnl_unlock();
570 rollback_lock = true;
571 }
572 PRINT_D(HOSTAPD_DBG, "Unregister netdev\n");
573 unregister_netdev(wilc_wfi_mon);
574 /* free_netdev(wilc_wfi_mon); */
575
576 if (rollback_lock) {
577 rtnl_lock();
578 rollback_lock = false;
579 }
580 wilc_wfi_mon = NULL;
581 }
582 return WILC_SUCCESS;
583
584}
585#endif /* WILC_AP_EXTERNAL_MLME */