aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/main.c
diff options
context:
space:
mode:
authorKiran Divekar <dkiran@marvell.com>2010-06-14 12:31:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-23 15:13:11 -0400
commite86dc1ca4676445d9f0dfe35104efe0eb8a2f566 (patch)
treebd39d0d4403899fb438a2e983e1b97c1ccd9b1ad /drivers/net/wireless/libertas/main.c
parentf90754c15f47063671aea55268a9dd6a37b51492 (diff)
Libertas: cfg80211 support
Holger Schurig's patch (https://patchwork.kernel.org/patch/64286/) is rebased to latest wireless-testing tree. (Includes patches from me originally posted as "libertas: fix build error due to undefined symbol" and "libertas: unmangle capability value". -- JWL) Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Kiran Divekar <dkiran@marvell.com> Tested-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r--drivers/net/wireless/libertas/main.c221
1 files changed, 4 insertions, 217 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index abfecc4814b4..51b7e1923ab2 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -11,20 +11,14 @@
11#include <linux/if_arp.h> 11#include <linux/if_arp.h>
12#include <linux/kthread.h> 12#include <linux/kthread.h>
13#include <linux/kfifo.h> 13#include <linux/kfifo.h>
14#include <linux/stddef.h>
15#include <linux/ieee80211.h>
16#include <linux/slab.h> 14#include <linux/slab.h>
17#include <net/iw_handler.h>
18#include <net/cfg80211.h> 15#include <net/cfg80211.h>
19 16
20#include "host.h" 17#include "host.h"
21#include "decl.h" 18#include "decl.h"
22#include "dev.h" 19#include "dev.h"
23#include "wext.h"
24#include "cfg.h" 20#include "cfg.h"
25#include "debugfs.h" 21#include "debugfs.h"
26#include "scan.h"
27#include "assoc.h"
28#include "cmd.h" 22#include "cmd.h"
29 23
30#define DRIVER_RELEASE_VERSION "323.p0" 24#define DRIVER_RELEASE_VERSION "323.p0"
@@ -96,72 +90,6 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
96} 90}
97 91
98 92
99static int lbs_add_rtap(struct lbs_private *priv);
100static void lbs_remove_rtap(struct lbs_private *priv);
101
102
103/**
104 * Get function for sysfs attribute rtap
105 */
106static ssize_t lbs_rtap_get(struct device *dev,
107 struct device_attribute *attr, char * buf)
108{
109 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
110 return snprintf(buf, 5, "0x%X\n", priv->monitormode);
111}
112
113/**
114 * Set function for sysfs attribute rtap
115 */
116static ssize_t lbs_rtap_set(struct device *dev,
117 struct device_attribute *attr, const char * buf, size_t count)
118{
119 int monitor_mode;
120 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
121
122 sscanf(buf, "%x", &monitor_mode);
123 if (monitor_mode) {
124 if (priv->monitormode == monitor_mode)
125 return strlen(buf);
126 if (!priv->monitormode) {
127 if (priv->infra_open || lbs_mesh_open(priv))
128 return -EBUSY;
129 if (priv->mode == IW_MODE_INFRA)
130 lbs_cmd_80211_deauthenticate(priv,
131 priv->curbssparams.bssid,
132 WLAN_REASON_DEAUTH_LEAVING);
133 else if (priv->mode == IW_MODE_ADHOC)
134 lbs_adhoc_stop(priv);
135 lbs_add_rtap(priv);
136 }
137 priv->monitormode = monitor_mode;
138 } else {
139 if (!priv->monitormode)
140 return strlen(buf);
141 priv->monitormode = 0;
142 lbs_remove_rtap(priv);
143
144 if (priv->currenttxskb) {
145 dev_kfree_skb_any(priv->currenttxskb);
146 priv->currenttxskb = NULL;
147 }
148
149 /* Wake queues, command thread, etc. */
150 lbs_host_to_card_done(priv);
151 }
152
153 lbs_prepare_and_send_command(priv,
154 CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
155 CMD_OPTION_WAITFORRSP, 0, &priv->monitormode);
156 return strlen(buf);
157}
158
159/**
160 * lbs_rtap attribute to be exported per ethX interface
161 * through sysfs (/sys/class/net/ethX/lbs_rtap)
162 */
163static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
164
165/** 93/**
166 * @brief This function opens the ethX interface 94 * @brief This function opens the ethX interface
167 * 95 *
@@ -177,13 +105,6 @@ static int lbs_dev_open(struct net_device *dev)
177 105
178 spin_lock_irq(&priv->driver_lock); 106 spin_lock_irq(&priv->driver_lock);
179 107
180 if (priv->monitormode) {
181 ret = -EBUSY;
182 goto out;
183 }
184
185 priv->infra_open = 1;
186
187 if (priv->connect_status == LBS_CONNECTED) 108 if (priv->connect_status == LBS_CONNECTED)
188 netif_carrier_on(dev); 109 netif_carrier_on(dev);
189 else 110 else
@@ -191,7 +112,6 @@ static int lbs_dev_open(struct net_device *dev)
191 112
192 if (!priv->tx_pending_len) 113 if (!priv->tx_pending_len)
193 netif_wake_queue(dev); 114 netif_wake_queue(dev);
194 out:
195 115
196 spin_unlock_irq(&priv->driver_lock); 116 spin_unlock_irq(&priv->driver_lock);
197 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); 117 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
@@ -211,7 +131,6 @@ static int lbs_eth_stop(struct net_device *dev)
211 lbs_deb_enter(LBS_DEB_NET); 131 lbs_deb_enter(LBS_DEB_NET);
212 132
213 spin_lock_irq(&priv->driver_lock); 133 spin_lock_irq(&priv->driver_lock);
214 priv->infra_open = 0;
215 netif_stop_queue(dev); 134 netif_stop_queue(dev);
216 spin_unlock_irq(&priv->driver_lock); 135 spin_unlock_irq(&priv->driver_lock);
217 136
@@ -822,37 +741,16 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
822 741
823static int lbs_init_adapter(struct lbs_private *priv) 742static int lbs_init_adapter(struct lbs_private *priv)
824{ 743{
825 size_t bufsize; 744 int ret;
826 int i, ret = 0;
827 745
828 lbs_deb_enter(LBS_DEB_MAIN); 746 lbs_deb_enter(LBS_DEB_MAIN);
829 747
830 /* Allocate buffer to store the BSSID list */
831 bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
832 priv->networks = kzalloc(bufsize, GFP_KERNEL);
833 if (!priv->networks) {
834 lbs_pr_err("Out of memory allocating beacons\n");
835 ret = -1;
836 goto out;
837 }
838
839 /* Initialize scan result lists */
840 INIT_LIST_HEAD(&priv->network_free_list);
841 INIT_LIST_HEAD(&priv->network_list);
842 for (i = 0; i < MAX_NETWORK_COUNT; i++) {
843 list_add_tail(&priv->networks[i].list,
844 &priv->network_free_list);
845 }
846
847 memset(priv->current_addr, 0xff, ETH_ALEN); 748 memset(priv->current_addr, 0xff, ETH_ALEN);
848 749
849 priv->connect_status = LBS_DISCONNECTED; 750 priv->connect_status = LBS_DISCONNECTED;
850 priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
851 priv->mode = IW_MODE_INFRA;
852 priv->channel = DEFAULT_AD_HOC_CHANNEL; 751 priv->channel = DEFAULT_AD_HOC_CHANNEL;
853 priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; 752 priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
854 priv->radio_on = 1; 753 priv->radio_on = 1;
855 priv->enablehwauto = 1;
856 priv->psmode = LBS802_11POWERMODECAM; 754 priv->psmode = LBS802_11POWERMODECAM;
857 priv->psstate = PS_STATE_FULL_POWER; 755 priv->psstate = PS_STATE_FULL_POWER;
858 priv->is_deep_sleep = 0; 756 priv->is_deep_sleep = 0;
@@ -907,8 +805,6 @@ static void lbs_free_adapter(struct lbs_private *priv)
907 kfifo_free(&priv->event_fifo); 805 kfifo_free(&priv->event_fifo);
908 del_timer(&priv->command_timer); 806 del_timer(&priv->command_timer);
909 del_timer(&priv->auto_deepsleep_timer); 807 del_timer(&priv->auto_deepsleep_timer);
910 kfree(priv->networks);
911 priv->networks = NULL;
912 808
913 lbs_deb_leave(LBS_DEB_MAIN); 809 lbs_deb_leave(LBS_DEB_MAIN);
914} 810}
@@ -945,7 +841,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
945 lbs_pr_err("cfg80211 init failed\n"); 841 lbs_pr_err("cfg80211 init failed\n");
946 goto done; 842 goto done;
947 } 843 }
948 /* TODO? */ 844
949 wdev->iftype = NL80211_IFTYPE_STATION; 845 wdev->iftype = NL80211_IFTYPE_STATION;
950 priv = wdev_priv(wdev); 846 priv = wdev_priv(wdev);
951 priv->wdev = wdev; 847 priv->wdev = wdev;
@@ -955,7 +851,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
955 goto err_wdev; 851 goto err_wdev;
956 } 852 }
957 853
958 //TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
959 dev = alloc_netdev(0, "wlan%d", ether_setup); 854 dev = alloc_netdev(0, "wlan%d", ether_setup);
960 if (!dev) { 855 if (!dev) {
961 dev_err(dmdev, "no memory for network device instance\n"); 856 dev_err(dmdev, "no memory for network device instance\n");
@@ -971,20 +866,10 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
971 dev->netdev_ops = &lbs_netdev_ops; 866 dev->netdev_ops = &lbs_netdev_ops;
972 dev->watchdog_timeo = 5 * HZ; 867 dev->watchdog_timeo = 5 * HZ;
973 dev->ethtool_ops = &lbs_ethtool_ops; 868 dev->ethtool_ops = &lbs_ethtool_ops;
974#ifdef WIRELESS_EXT
975 dev->wireless_handlers = &lbs_handler_def;
976#endif
977 dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 869 dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
978 870
979
980 // TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
981
982
983 priv->card = card; 871 priv->card = card;
984 priv->infra_open = 0;
985
986 872
987 priv->rtap_net_dev = NULL;
988 strcpy(dev->name, "wlan%d"); 873 strcpy(dev->name, "wlan%d");
989 874
990 lbs_deb_thread("Starting main thread...\n"); 875 lbs_deb_thread("Starting main thread...\n");
@@ -996,8 +881,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
996 } 881 }
997 882
998 priv->work_thread = create_singlethread_workqueue("lbs_worker"); 883 priv->work_thread = create_singlethread_workqueue("lbs_worker");
999 INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
1000 INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
1001 INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); 884 INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
1002 885
1003 priv->wol_criteria = 0xffffffff; 886 priv->wol_criteria = 0xffffffff;
@@ -1031,12 +914,10 @@ void lbs_remove_card(struct lbs_private *priv)
1031 lbs_deb_enter(LBS_DEB_MAIN); 914 lbs_deb_enter(LBS_DEB_MAIN);
1032 915
1033 lbs_remove_mesh(priv); 916 lbs_remove_mesh(priv);
1034 lbs_remove_rtap(priv); 917 lbs_scan_deinit(priv);
1035 918
1036 dev = priv->dev; 919 dev = priv->dev;
1037 920
1038 cancel_delayed_work_sync(&priv->scan_work);
1039 cancel_delayed_work_sync(&priv->assoc_work);
1040 cancel_work_sync(&priv->mcast_work); 921 cancel_work_sync(&priv->mcast_work);
1041 922
1042 /* worker thread destruction blocks on the in-flight command which 923 /* worker thread destruction blocks on the in-flight command which
@@ -1077,7 +958,7 @@ void lbs_remove_card(struct lbs_private *priv)
1077EXPORT_SYMBOL_GPL(lbs_remove_card); 958EXPORT_SYMBOL_GPL(lbs_remove_card);
1078 959
1079 960
1080static int lbs_rtap_supported(struct lbs_private *priv) 961int lbs_rtap_supported(struct lbs_private *priv)
1081{ 962{
1082 if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) 963 if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
1083 return 1; 964 return 1;
@@ -1109,16 +990,6 @@ int lbs_start_card(struct lbs_private *priv)
1109 990
1110 lbs_init_mesh(priv); 991 lbs_init_mesh(priv);
1111 992
1112 /*
1113 * While rtap isn't related to mesh, only mesh-enabled
1114 * firmware implements the rtap functionality via
1115 * CMD_802_11_MONITOR_MODE.
1116 */
1117 if (lbs_rtap_supported(priv)) {
1118 if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
1119 lbs_pr_err("cannot register lbs_rtap attribute\n");
1120 }
1121
1122 lbs_debugfs_init_one(priv, dev); 993 lbs_debugfs_init_one(priv, dev);
1123 994
1124 lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); 995 lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
@@ -1150,9 +1021,6 @@ void lbs_stop_card(struct lbs_private *priv)
1150 lbs_debugfs_remove_one(priv); 1021 lbs_debugfs_remove_one(priv);
1151 lbs_deinit_mesh(priv); 1022 lbs_deinit_mesh(priv);
1152 1023
1153 if (lbs_rtap_supported(priv))
1154 device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
1155
1156 /* Delete the timeout of the currently processing command */ 1024 /* Delete the timeout of the currently processing command */
1157 del_timer_sync(&priv->command_timer); 1025 del_timer_sync(&priv->command_timer);
1158 del_timer_sync(&priv->auto_deepsleep_timer); 1026 del_timer_sync(&priv->auto_deepsleep_timer);
@@ -1239,87 +1107,6 @@ static void __exit lbs_exit_module(void)
1239 lbs_deb_leave(LBS_DEB_MAIN); 1107 lbs_deb_leave(LBS_DEB_MAIN);
1240} 1108}
1241 1109
1242/*
1243 * rtap interface support fuctions
1244 */
1245
1246static int lbs_rtap_open(struct net_device *dev)
1247{
1248 /* Yes, _stop_ the queue. Because we don't support injection */
1249 lbs_deb_enter(LBS_DEB_MAIN);
1250 netif_carrier_off(dev);
1251 netif_stop_queue(dev);
1252 lbs_deb_leave(LBS_DEB_LEAVE);
1253 return 0;
1254}
1255
1256static int lbs_rtap_stop(struct net_device *dev)
1257{
1258 lbs_deb_enter(LBS_DEB_MAIN);
1259 lbs_deb_leave(LBS_DEB_MAIN);
1260 return 0;
1261}
1262
1263static netdev_tx_t lbs_rtap_hard_start_xmit(struct sk_buff *skb,
1264 struct net_device *dev)
1265{
1266 netif_stop_queue(dev);
1267 return NETDEV_TX_BUSY;
1268}
1269
1270static void lbs_remove_rtap(struct lbs_private *priv)
1271{
1272 lbs_deb_enter(LBS_DEB_MAIN);
1273 if (priv->rtap_net_dev == NULL)
1274 goto out;
1275 unregister_netdev(priv->rtap_net_dev);
1276 free_netdev(priv->rtap_net_dev);
1277 priv->rtap_net_dev = NULL;
1278out:
1279 lbs_deb_leave(LBS_DEB_MAIN);
1280}
1281
1282static const struct net_device_ops rtap_netdev_ops = {
1283 .ndo_open = lbs_rtap_open,
1284 .ndo_stop = lbs_rtap_stop,
1285 .ndo_start_xmit = lbs_rtap_hard_start_xmit,
1286};
1287
1288static int lbs_add_rtap(struct lbs_private *priv)
1289{
1290 int ret = 0;
1291 struct net_device *rtap_dev;
1292
1293 lbs_deb_enter(LBS_DEB_MAIN);
1294 if (priv->rtap_net_dev) {
1295 ret = -EPERM;
1296 goto out;
1297 }
1298
1299 rtap_dev = alloc_netdev(0, "rtap%d", ether_setup);
1300 if (rtap_dev == NULL) {
1301 ret = -ENOMEM;
1302 goto out;
1303 }
1304
1305 memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN);
1306 rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP;
1307 rtap_dev->netdev_ops = &rtap_netdev_ops;
1308 rtap_dev->ml_priv = priv;
1309 SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
1310
1311 ret = register_netdev(rtap_dev);
1312 if (ret) {
1313 free_netdev(rtap_dev);
1314 goto out;
1315 }
1316 priv->rtap_net_dev = rtap_dev;
1317
1318out:
1319 lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
1320 return ret;
1321}
1322
1323module_init(lbs_init_module); 1110module_init(lbs_init_module);
1324module_exit(lbs_exit_module); 1111module_exit(lbs_exit_module);
1325 1112