diff options
author | Kiran Divekar <dkiran@marvell.com> | 2010-06-14 12:31:26 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-06-23 15:13:11 -0400 |
commit | e86dc1ca4676445d9f0dfe35104efe0eb8a2f566 (patch) | |
tree | bd39d0d4403899fb438a2e983e1b97c1ccd9b1ad /drivers/net/wireless/libertas/main.c | |
parent | f90754c15f47063671aea55268a9dd6a37b51492 (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.c | 221 |
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 | ||
99 | static int lbs_add_rtap(struct lbs_private *priv); | ||
100 | static void lbs_remove_rtap(struct lbs_private *priv); | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Get function for sysfs attribute rtap | ||
105 | */ | ||
106 | static 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 | */ | ||
116 | static 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 | */ | ||
163 | static 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 | ||
823 | static int lbs_init_adapter(struct lbs_private *priv) | 742 | static 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) | |||
1077 | EXPORT_SYMBOL_GPL(lbs_remove_card); | 958 | EXPORT_SYMBOL_GPL(lbs_remove_card); |
1078 | 959 | ||
1079 | 960 | ||
1080 | static int lbs_rtap_supported(struct lbs_private *priv) | 961 | int 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 | |||
1246 | static 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 | |||
1256 | static 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 | |||
1263 | static 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 | |||
1270 | static 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; | ||
1278 | out: | ||
1279 | lbs_deb_leave(LBS_DEB_MAIN); | ||
1280 | } | ||
1281 | |||
1282 | static 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 | |||
1288 | static 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 | |||
1318 | out: | ||
1319 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
1320 | return ret; | ||
1321 | } | ||
1322 | |||
1323 | module_init(lbs_init_module); | 1110 | module_init(lbs_init_module); |
1324 | module_exit(lbs_exit_module); | 1111 | module_exit(lbs_exit_module); |
1325 | 1112 | ||