aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorLuis Carlos Cobo <luisca@cozybit.com>2007-08-02 13:16:55 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:50:13 -0400
commit965f8bbc6c92233600b176f4c80299f6766df9bd (patch)
tree85043fb97112a148d69171b744568fa78de2e05d /drivers/net
parent9483f03150cbfa1f706355b7f9d218d6086c6fce (diff)
[PATCH] libertas: monitor mode support for OLPC firmware
Driver support for the monitor mode support that will be available in the next OLPC 'bleeding edge' Marvell firmware release (most likely, 5.110.16.p2). To activate monitor mode, echo mode > /sys/class/net/{ethX,mshX}/device/libertas_rtap where mode is the hex mask that specifies which frames to sniff (in short, 0x1 for data, 0x2 for all management but beacons, 0x4 for beacons). Any non zero mode will activate the monitor mode, inhibiting transmission in ethX and mshX interfaces and routing all the incoming traffic to a new rtapX interface that will output the packets in 802.11+radiotap headers format. Signed-off-by: Luis Carlos Cobo <luisca@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/libertas/cmd.c25
-rw-r--r--drivers/net/wireless/libertas/dev.h7
-rw-r--r--drivers/net/wireless/libertas/host.h2
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h6
-rw-r--r--drivers/net/wireless/libertas/if_usb.c2
-rw-r--r--drivers/net/wireless/libertas/main.c153
-rw-r--r--drivers/net/wireless/libertas/rx.c49
-rw-r--r--drivers/net/wireless/libertas/tx.c8
-rw-r--r--drivers/net/wireless/libertas/wext.h5
9 files changed, 217 insertions, 40 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 517489a06063..cd3bddb243b1 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -565,6 +565,26 @@ static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
565 return 0; 565 return 0;
566} 566}
567 567
568static int wlan_cmd_802_11_monitor_mode(wlan_private * priv,
569 struct cmd_ds_command *cmd,
570 u16 cmd_action, void *pdata_buf)
571{
572 struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
573
574 cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
575 cmd->size =
576 cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
577 S_DS_GEN);
578
579 monitor->action = cpu_to_le16(cmd_action);
580 if (cmd_action == CMD_ACT_SET) {
581 monitor->mode =
582 cpu_to_le16((u16) (*(u32 *) pdata_buf));
583 }
584
585 return 0;
586}
587
568static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv, 588static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv,
569 struct cmd_ds_command *cmd, 589 struct cmd_ds_command *cmd,
570 u16 cmd_action) 590 u16 cmd_action)
@@ -1239,6 +1259,11 @@ int libertas_prepare_and_send_command(wlan_private * priv,
1239 ret = wlan_cmd_mac_multicast_adr(priv, cmdptr, cmd_action); 1259 ret = wlan_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
1240 break; 1260 break;
1241 1261
1262 case CMD_802_11_MONITOR_MODE:
1263 ret = wlan_cmd_802_11_monitor_mode(priv, cmdptr,
1264 cmd_action, pdata_buf);
1265 break;
1266
1242 case CMD_802_11_AD_HOC_JOIN: 1267 case CMD_802_11_AD_HOC_JOIN:
1243 ret = libertas_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf); 1268 ret = libertas_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
1244 break; 1269 break;
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 397c5fca0ff5..5697fec0cb1d 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -112,7 +112,9 @@ struct _wlan_private {
112 struct net_device *dev; 112 struct net_device *dev;
113 113
114 struct net_device_stats stats; 114 struct net_device_stats stats;
115 struct net_device *mesh_dev ; /* Virtual device */ 115 struct net_device *mesh_dev; /* Virtual device */
116 struct net_device *rtap_net_dev;
117 struct ieee80211_device *ieee;
116 118
117 struct iw_statistics wstats; 119 struct iw_statistics wstats;
118 struct wlan_mesh_stats mstats; 120 struct wlan_mesh_stats mstats;
@@ -362,8 +364,7 @@ struct _wlan_adapter {
362 364
363 struct cmd_ds_802_11_get_log logmsg; 365 struct cmd_ds_802_11_get_log logmsg;
364 366
365 u32 linkmode; 367 u32 monitormode;
366 u32 radiomode;
367 u8 fw_ready; 368 u8 fw_ready;
368 369
369 u8 last_scanned_channel; 370 u8 last_scanned_channel;
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index c6b44c831594..4ccdbf9c473a 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -110,6 +110,8 @@
110 110
111#define CMD_FWT_ACCESS 0x0095 111#define CMD_FWT_ACCESS 0x0095
112 112
113#define CMD_802_11_MONITOR_MODE 0x0098
114
113#define CMD_MESH_ACCESS 0x009b 115#define CMD_MESH_ACCESS 0x009b
114 116
115/* For the IEEE Power Save */ 117/* For the IEEE Power Save */
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index 44cf39c8d1b8..52884eaf2edd 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -405,6 +405,11 @@ struct cmd_ds_802_11_rf_antenna {
405 405
406}; 406};
407 407
408struct cmd_ds_802_11_monitor_mode {
409 u16 action;
410 u16 mode;
411};
412
408struct cmd_ds_802_11_ps_mode { 413struct cmd_ds_802_11_ps_mode {
409 __le16 action; 414 __le16 action;
410 __le16 nullpktinterval; 415 __le16 nullpktinterval;
@@ -623,6 +628,7 @@ struct cmd_ds_command {
623 struct cmd_ds_802_11_snmp_mib smib; 628 struct cmd_ds_802_11_snmp_mib smib;
624 struct cmd_ds_802_11_rf_tx_power txp; 629 struct cmd_ds_802_11_rf_tx_power txp;
625 struct cmd_ds_802_11_rf_antenna rant; 630 struct cmd_ds_802_11_rf_antenna rant;
631 struct cmd_ds_802_11_monitor_mode monitor;
626 struct cmd_ds_802_11_data_rate drate; 632 struct cmd_ds_802_11_data_rate drate;
627 struct cmd_ds_802_11_rate_adapt_rateset rateset; 633 struct cmd_ds_802_11_rate_adapt_rateset rateset;
628 struct cmd_ds_mac_multicast_adr madr; 634 struct cmd_ds_mac_multicast_adr madr;
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 670e1d23c043..d28802fb244b 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -208,6 +208,8 @@ static int if_usb_probe(struct usb_interface *intf,
208 if (!(priv = libertas_add_card(cardp, &udev->dev))) 208 if (!(priv = libertas_add_card(cardp, &udev->dev)))
209 goto dealloc; 209 goto dealloc;
210 210
211 udev->dev.driver_data = priv;
212
211 if (libertas_add_mesh(priv, &udev->dev)) 213 if (libertas_add_mesh(priv, &udev->dev))
212 goto err_add_mesh; 214 goto err_add_mesh;
213 215
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index a3a17caae439..9a46339ce47e 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -21,6 +21,7 @@
21#include "wext.h" 21#include "wext.h"
22#include "debugfs.h" 22#include "debugfs.h"
23#include "assoc.h" 23#include "assoc.h"
24#include "join.h"
24 25
25#define DRIVER_RELEASE_VERSION "322.p1" 26#define DRIVER_RELEASE_VERSION "322.p1"
26const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION 27const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
@@ -246,6 +247,66 @@ static ssize_t libertas_anycast_set(struct device * dev,
246 return strlen(buf); 247 return strlen(buf);
247} 248}
248 249
250int libertas_add_rtap(wlan_private *priv);
251void libertas_remove_rtap(wlan_private *priv);
252
253/**
254 * Get function for sysfs attribute rtap
255 */
256static ssize_t libertas_rtap_get(struct device * dev,
257 struct device_attribute *attr, char * buf)
258{
259 wlan_private *priv = (wlan_private *) dev->driver_data;
260 wlan_adapter *adapter = priv->adapter;
261 return snprintf(buf, 5, "0x%X\n", adapter->monitormode);
262}
263
264/**
265 * Set function for sysfs attribute rtap
266 */
267static ssize_t libertas_rtap_set(struct device * dev,
268 struct device_attribute *attr, const char * buf, size_t count)
269{
270 int monitor_mode;
271 wlan_private *priv = (wlan_private *) dev->driver_data;
272 wlan_adapter *adapter = priv->adapter;
273
274 sscanf(buf, "%x", &monitor_mode);
275 if (monitor_mode != WLAN_MONITOR_OFF) {
276 if(adapter->monitormode == monitor_mode)
277 return strlen(buf);
278 if (adapter->monitormode == WLAN_MONITOR_OFF) {
279 if (adapter->mode == IW_MODE_INFRA)
280 libertas_send_deauthentication(priv);
281 else if (adapter->mode == IW_MODE_ADHOC)
282 libertas_stop_adhoc_network(priv);
283 libertas_add_rtap(priv);
284 }
285 adapter->monitormode = monitor_mode;
286 }
287
288 else {
289 if(adapter->monitormode == WLAN_MONITOR_OFF)
290 return strlen(buf);
291 adapter->monitormode = WLAN_MONITOR_OFF;
292 libertas_remove_rtap(priv);
293 netif_wake_queue(priv->dev);
294 netif_wake_queue(priv->mesh_dev);
295 }
296
297 libertas_prepare_and_send_command(priv,
298 CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
299 CMD_OPTION_WAITFORRSP, 0, &adapter->monitormode);
300 return strlen(buf);
301}
302
303/**
304 * libertas_rtap attribute to be exported per mshX interface
305 * through sysfs (/sys/class/net/mshX/libertas-rtap)
306 */
307static DEVICE_ATTR(libertas_rtap, 0644, libertas_rtap_get,
308 libertas_rtap_set );
309
249/** 310/**
250 * anycast_mask attribute to be exported per mshX interface 311 * anycast_mask attribute to be exported per mshX interface
251 * through sysfs (/sys/class/net/mshX/anycast_mask) 312 * through sysfs (/sys/class/net/mshX/anycast_mask)
@@ -480,6 +541,10 @@ static int libertas_mesh_pre_start_xmit(struct sk_buff *skb,
480 int ret; 541 int ret;
481 542
482 lbs_deb_enter(LBS_DEB_MESH); 543 lbs_deb_enter(LBS_DEB_MESH);
544 if(priv->adapter->monitormode != WLAN_MONITOR_OFF) {
545 netif_stop_queue(dev);
546 return -EOPNOTSUPP;
547 }
483 548
484 SET_MESH_FRAME(skb); 549 SET_MESH_FRAME(skb);
485 550
@@ -494,10 +559,16 @@ static int libertas_mesh_pre_start_xmit(struct sk_buff *skb,
494 */ 559 */
495static int libertas_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) 560static int libertas_pre_start_xmit(struct sk_buff *skb, struct net_device *dev)
496{ 561{
562 wlan_private *priv = dev->priv;
497 int ret; 563 int ret;
498 564
499 lbs_deb_enter(LBS_DEB_NET); 565 lbs_deb_enter(LBS_DEB_NET);
500 566
567 if(priv->adapter->monitormode != WLAN_MONITOR_OFF) {
568 netif_stop_queue(dev);
569 return -EOPNOTSUPP;
570 }
571
501 UNSET_MESH_FRAME(skb); 572 UNSET_MESH_FRAME(skb);
502 573
503 ret = libertas_hard_start_xmit(skb, dev); 574 ret = libertas_hard_start_xmit(skb, dev);
@@ -517,7 +588,7 @@ static void libertas_tx_timeout(struct net_device *dev)
517 dev->trans_start = jiffies; 588 dev->trans_start = jiffies;
518 589
519 if (priv->adapter->currenttxskb) { 590 if (priv->adapter->currenttxskb) {
520 if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) { 591 if (priv->adapter->monitormode != WLAN_MONITOR_OFF) {
521 /* If we are here, we have not received feedback from 592 /* If we are here, we have not received feedback from
522 the previous packet. Assume TX_FAIL and move on. */ 593 the previous packet. Assume TX_FAIL and move on. */
523 priv->adapter->eventcause = 0x01000000; 594 priv->adapter->eventcause = 0x01000000;
@@ -1169,6 +1240,9 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
1169 spin_lock_init(&priv->adapter->driver_lock); 1240 spin_lock_init(&priv->adapter->driver_lock);
1170 init_waitqueue_head(&priv->adapter->cmd_pending); 1241 init_waitqueue_head(&priv->adapter->cmd_pending);
1171 priv->adapter->nr_cmd_pending = 0; 1242 priv->adapter->nr_cmd_pending = 0;
1243 priv->rtap_net_dev = NULL;
1244 if (device_create_file(dmdev, &dev_attr_libertas_rtap))
1245 goto err_kzalloc;
1172 goto done; 1246 goto done;
1173 1247
1174err_kzalloc: 1248err_kzalloc:
@@ -1333,6 +1407,7 @@ int libertas_remove_card(wlan_private *priv)
1333 1407
1334 lbs_deb_enter(LBS_DEB_NET); 1408 lbs_deb_enter(LBS_DEB_NET);
1335 1409
1410 libertas_remove_rtap(priv);
1336 if (!priv) 1411 if (!priv)
1337 goto out; 1412 goto out;
1338 1413
@@ -1342,6 +1417,7 @@ int libertas_remove_card(wlan_private *priv)
1342 goto out; 1417 goto out;
1343 1418
1344 dev = priv->dev; 1419 dev = priv->dev;
1420 device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap);
1345 1421
1346 netif_stop_queue(priv->dev); 1422 netif_stop_queue(priv->dev);
1347 netif_carrier_off(priv->dev); 1423 netif_carrier_off(priv->dev);
@@ -1537,6 +1613,81 @@ static void libertas_exit_module(void)
1537 lbs_deb_leave(LBS_DEB_MAIN); 1613 lbs_deb_leave(LBS_DEB_MAIN);
1538} 1614}
1539 1615
1616/*
1617 * rtap interface support fuctions
1618 */
1619
1620static int libertas_rtap_open(struct net_device *dev)
1621{
1622 netif_carrier_off(dev);
1623 netif_stop_queue(dev);
1624 return 0;
1625}
1626
1627static int libertas_rtap_stop(struct net_device *dev)
1628{
1629 return 0;
1630}
1631
1632static int libertas_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
1633{
1634 netif_stop_queue(dev);
1635 return -EOPNOTSUPP;
1636}
1637
1638static struct net_device_stats *libertas_rtap_get_stats(struct net_device *dev)
1639{
1640 wlan_private *priv = dev->priv;
1641 return &priv->ieee->stats;
1642}
1643
1644
1645void libertas_remove_rtap(wlan_private *priv)
1646{
1647 if (priv->rtap_net_dev == NULL)
1648 return;
1649 unregister_netdev(priv->rtap_net_dev);
1650 free_ieee80211(priv->rtap_net_dev);
1651 priv->rtap_net_dev = NULL;
1652}
1653
1654int libertas_add_rtap(wlan_private *priv)
1655{
1656 int rc = 0;
1657
1658 if (priv->rtap_net_dev)
1659 return -EPERM;
1660
1661 priv->rtap_net_dev = alloc_ieee80211(0);
1662 if (priv->rtap_net_dev == NULL)
1663 return -ENOMEM;
1664
1665
1666 priv->ieee = netdev_priv(priv->rtap_net_dev);
1667
1668 strcpy(priv->rtap_net_dev->name, "rtap%d");
1669
1670 priv->rtap_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
1671 priv->rtap_net_dev->open = libertas_rtap_open;
1672 priv->rtap_net_dev->stop = libertas_rtap_stop;
1673 priv->rtap_net_dev->get_stats = libertas_rtap_get_stats;
1674 priv->rtap_net_dev->hard_start_xmit = libertas_rtap_hard_start_xmit;
1675 priv->rtap_net_dev->set_multicast_list = libertas_set_multicast_list;
1676 priv->rtap_net_dev->priv = priv;
1677
1678 priv->ieee->iw_mode = IW_MODE_MONITOR;
1679
1680 rc = register_netdev(priv->rtap_net_dev);
1681 if (rc) {
1682 free_ieee80211(priv->rtap_net_dev);
1683 priv->rtap_net_dev = NULL;
1684 return rc;
1685 }
1686
1687 return 0;
1688}
1689
1690
1540module_init(libertas_init_module); 1691module_init(libertas_init_module);
1541module_exit(libertas_exit_module); 1692module_exit(libertas_exit_module);
1542 1693
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 83a7765fd23c..09def943b910 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -138,12 +138,15 @@ void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb)
138{ 138{
139 lbs_deb_rx("skb->data %p\n", skb->data); 139 lbs_deb_rx("skb->data %p\n", skb->data);
140 140
141 if (priv->mesh_dev && IS_MESH_FRAME(skb)) 141 if (priv->adapter->monitormode != WLAN_MONITOR_OFF) {
142 skb->protocol = eth_type_trans(skb, priv->mesh_dev); 142 skb->protocol = eth_type_trans(skb, priv->rtap_net_dev);
143 else 143 } else {
144 skb->protocol = eth_type_trans(skb, priv->dev); 144 if (priv->mesh_dev && IS_MESH_FRAME(skb))
145 skb->protocol = eth_type_trans(skb, priv->mesh_dev);
146 else
147 skb->protocol = eth_type_trans(skb, priv->dev);
148 }
145 skb->ip_summed = CHECKSUM_UNNECESSARY; 149 skb->ip_summed = CHECKSUM_UNNECESSARY;
146
147 netif_rx(skb); 150 netif_rx(skb);
148} 151}
149 152
@@ -170,7 +173,7 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
170 173
171 lbs_deb_enter(LBS_DEB_RX); 174 lbs_deb_enter(LBS_DEB_RX);
172 175
173 if (priv->adapter->linkmode == WLAN_LINKMODE_802_11) 176 if (priv->adapter->monitormode != WLAN_MONITOR_OFF)
174 return process_rxed_802_11_packet(priv, skb); 177 return process_rxed_802_11_packet(priv, skb);
175 178
176 p_rx_pkt = (struct rxpackethdr *) skb->data; 179 p_rx_pkt = (struct rxpackethdr *) skb->data;
@@ -290,21 +293,22 @@ static u8 convert_mv_rate_to_radiotap(u8 rate)
290 return 11; 293 return 11;
291 case 3: /* 11 Mbps */ 294 case 3: /* 11 Mbps */
292 return 22; 295 return 22;
293 case 4: /* 6 Mbps */ 296 /* case 4: reserved */
297 case 5: /* 6 Mbps */
294 return 12; 298 return 12;
295 case 5: /* 9 Mbps */ 299 case 6: /* 9 Mbps */
296 return 18; 300 return 18;
297 case 6: /* 12 Mbps */ 301 case 7: /* 12 Mbps */
298 return 24; 302 return 24;
299 case 7: /* 18 Mbps */ 303 case 8: /* 18 Mbps */
300 return 36; 304 return 36;
301 case 8: /* 24 Mbps */ 305 case 9: /* 24 Mbps */
302 return 48; 306 return 48;
303 case 9: /* 36 Mbps */ 307 case 10: /* 36 Mbps */
304 return 72; 308 return 72;
305 case 10: /* 48 Mbps */ 309 case 11: /* 48 Mbps */
306 return 96; 310 return 96;
307 case 11: /* 54 Mbps */ 311 case 12: /* 54 Mbps */
308 return 108; 312 return 108;
309 } 313 }
310 lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate); 314 lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate);
@@ -355,14 +359,13 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
355 skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); 359 skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
356 360
357 /* create the exported radio header */ 361 /* create the exported radio header */
358 switch (priv->adapter->radiomode) { 362 if(priv->adapter->monitormode == WLAN_MONITOR_OFF) {
359 case WLAN_RADIOMODE_NONE:
360 /* no radio header */ 363 /* no radio header */
361 /* chop the rxpd */ 364 /* chop the rxpd */
362 skb_pull(skb, sizeof(struct rxpd)); 365 skb_pull(skb, sizeof(struct rxpd));
363 break; 366 }
364 367
365 case WLAN_RADIOMODE_RADIOTAP: 368 else {
366 /* radiotap header */ 369 /* radiotap header */
367 radiotap_hdr.hdr.it_version = 0; 370 radiotap_hdr.hdr.it_version = 0;
368 /* XXX must check this value for pad */ 371 /* XXX must check this value for pad */
@@ -400,16 +403,6 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
400 rx_radiotap_hdr)); 403 rx_radiotap_hdr));
401 memcpy(pradiotap_hdr, &radiotap_hdr, 404 memcpy(pradiotap_hdr, &radiotap_hdr,
402 sizeof(struct rx_radiotap_hdr)); 405 sizeof(struct rx_radiotap_hdr));
403 break;
404
405 default:
406 /* unknown header */
407 lbs_pr_alert("Unknown radiomode %i\n",
408 priv->adapter->radiomode);
409 /* don't export any header */
410 /* chop the rxpd */
411 skb_pull(skb, sizeof(struct rxpd));
412 break;
413 } 406 }
414 407
415 /* Take the data rate from the rxpd structure 408 /* Take the data rate from the rxpd structure
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index bb6e17506a41..fbec06c10dd7 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -86,7 +86,7 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
86 plocaltxpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); 86 plocaltxpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
87 87
88 p802x_hdr = skb->data; 88 p802x_hdr = skb->data;
89 if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) { 89 if (priv->adapter->monitormode != WLAN_MONITOR_OFF) {
90 90
91 /* locate radiotap header */ 91 /* locate radiotap header */
92 pradiotap_hdr = (struct tx_radiotap_hdr *)skb->data; 92 pradiotap_hdr = (struct tx_radiotap_hdr *)skb->data;
@@ -106,7 +106,7 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
106 106
107 } 107 }
108 /* copy destination address from 802.3 or 802.11 header */ 108 /* copy destination address from 802.3 or 802.11 header */
109 if (priv->adapter->linkmode == WLAN_LINKMODE_802_11) 109 if (priv->adapter->monitormode != WLAN_MONITOR_OFF)
110 memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN); 110 memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
111 else 111 else
112 memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN); 112 memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);
@@ -144,7 +144,7 @@ done:
144 priv->stats.tx_errors++; 144 priv->stats.tx_errors++;
145 } 145 }
146 146
147 if (!ret && priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) { 147 if (!ret && priv->adapter->monitormode != WLAN_MONITOR_OFF) {
148 /* Keep the skb to echo it back once Tx feedback is 148 /* Keep the skb to echo it back once Tx feedback is
149 received from FW */ 149 received from FW */
150 skb_orphan(skb); 150 skb_orphan(skb);
@@ -252,7 +252,7 @@ void libertas_send_tx_feedback(wlan_private * priv)
252 int txfail; 252 int txfail;
253 int try_count; 253 int try_count;
254 254
255 if (adapter->radiomode != WLAN_RADIOMODE_RADIOTAP || 255 if (adapter->monitormode == WLAN_MONITOR_OFF ||
256 adapter->currenttxskb == NULL) 256 adapter->currenttxskb == NULL)
257 return; 257 return;
258 258
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
index 5b0bbc99a21e..6aa444c7de8d 100644
--- a/drivers/net/wireless/libertas/wext.h
+++ b/drivers/net/wireless/libertas/wext.h
@@ -15,10 +15,7 @@ struct wlan_ioctl_regrdwr {
15 u32 value; 15 u32 value;
16}; 16};
17 17
18#define WLAN_LINKMODE_802_3 0 18#define WLAN_MONITOR_OFF 0
19#define WLAN_LINKMODE_802_11 2
20#define WLAN_RADIOMODE_NONE 0
21#define WLAN_RADIOMODE_RADIOTAP 2
22 19
23extern struct iw_handler_def libertas_handler_def; 20extern struct iw_handler_def libertas_handler_def;
24extern struct iw_handler_def mesh_handler_def; 21extern struct iw_handler_def mesh_handler_def;