aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
authorHolger Schurig <hs4233@mail.mn-solutions.de>2009-10-06 10:31:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:47 -0400
commitff9fc791940f9ff51387c35f9332efe5007154f1 (patch)
tree49aa914b7d4162312ca7a0d42fde15cfede079a4 /drivers/net/wireless/libertas
parent0465af8e03bdc6cd0b49dc5548671387a8674b69 (diff)
libertas: first stab at cfg80211 support
Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/Makefile1
-rw-r--r--drivers/net/wireless/libertas/cfg.c198
-rw-r--r--drivers/net/wireless/libertas/cfg.h16
-rw-r--r--drivers/net/wireless/libertas/defs.h2
-rw-r--r--drivers/net/wireless/libertas/dev.h1
-rw-r--r--drivers/net/wireless/libertas/main.c61
6 files changed, 262 insertions, 17 deletions
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index 2f63940fb7f6..e5584dd1c79a 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -1,5 +1,6 @@
1libertas-y += 11d.o 1libertas-y += 11d.o
2libertas-y += assoc.o 2libertas-y += assoc.o
3libertas-y += cfg.o
3libertas-y += cmd.o 4libertas-y += cmd.o
4libertas-y += cmdresp.o 5libertas-y += cmdresp.o
5libertas-y += debugfs.o 6libertas-y += debugfs.o
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
new file mode 100644
index 000000000000..4396dccd12ac
--- /dev/null
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -0,0 +1,198 @@
1/*
2 * Implement cfg80211 ("iw") support.
3 *
4 * Copyright (C) 2009 M&N Solutions GmbH, 61191 Rosbach, Germany
5 * Holger Schurig <hs4233@mail.mn-solutions.de>
6 *
7 */
8
9#include <net/cfg80211.h>
10
11#include "cfg.h"
12#include "cmd.h"
13
14
15#define CHAN2G(_channel, _freq, _flags) { \
16 .band = IEEE80211_BAND_2GHZ, \
17 .center_freq = (_freq), \
18 .hw_value = (_channel), \
19 .flags = (_flags), \
20 .max_antenna_gain = 0, \
21 .max_power = 30, \
22}
23
24static struct ieee80211_channel lbs_2ghz_channels[] = {
25 CHAN2G(1, 2412, 0),
26 CHAN2G(2, 2417, 0),
27 CHAN2G(3, 2422, 0),
28 CHAN2G(4, 2427, 0),
29 CHAN2G(5, 2432, 0),
30 CHAN2G(6, 2437, 0),
31 CHAN2G(7, 2442, 0),
32 CHAN2G(8, 2447, 0),
33 CHAN2G(9, 2452, 0),
34 CHAN2G(10, 2457, 0),
35 CHAN2G(11, 2462, 0),
36 CHAN2G(12, 2467, 0),
37 CHAN2G(13, 2472, 0),
38 CHAN2G(14, 2484, 0),
39};
40
41#define RATETAB_ENT(_rate, _rateid, _flags) { \
42 .bitrate = (_rate), \
43 .hw_value = (_rateid), \
44 .flags = (_flags), \
45}
46
47
48static struct ieee80211_rate lbs_rates[] = {
49 RATETAB_ENT(10, 0x1, 0),
50 RATETAB_ENT(20, 0x2, 0),
51 RATETAB_ENT(55, 0x4, 0),
52 RATETAB_ENT(110, 0x8, 0),
53 RATETAB_ENT(60, 0x10, 0),
54 RATETAB_ENT(90, 0x20, 0),
55 RATETAB_ENT(120, 0x40, 0),
56 RATETAB_ENT(180, 0x80, 0),
57 RATETAB_ENT(240, 0x100, 0),
58 RATETAB_ENT(360, 0x200, 0),
59 RATETAB_ENT(480, 0x400, 0),
60 RATETAB_ENT(540, 0x800, 0),
61};
62
63static struct ieee80211_supported_band lbs_band_2ghz = {
64 .channels = lbs_2ghz_channels,
65 .n_channels = ARRAY_SIZE(lbs_2ghz_channels),
66 .bitrates = lbs_rates,
67 .n_bitrates = ARRAY_SIZE(lbs_rates),
68};
69
70
71static const u32 cipher_suites[] = {
72 WLAN_CIPHER_SUITE_WEP40,
73 WLAN_CIPHER_SUITE_WEP104,
74 WLAN_CIPHER_SUITE_TKIP,
75 WLAN_CIPHER_SUITE_CCMP,
76};
77
78
79
80static int lbs_cfg_set_channel(struct wiphy *wiphy,
81 struct ieee80211_channel *chan,
82 enum nl80211_channel_type channel_type)
83{
84 struct lbs_private *priv = wiphy_priv(wiphy);
85 int ret = -ENOTSUPP;
86
87 lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type);
88
89 if (channel_type != NL80211_CHAN_NO_HT)
90 goto out;
91
92 ret = lbs_set_channel(priv, chan->hw_value);
93
94 out:
95 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
96 return ret;
97}
98
99
100
101
102static struct cfg80211_ops lbs_cfg80211_ops = {
103 .set_channel = lbs_cfg_set_channel,
104};
105
106
107/*
108 * At this time lbs_private *priv doesn't even exist, so we just allocate
109 * memory and don't initialize the wiphy further. This is postponed until we
110 * can talk to the firmware and happens at registration time in
111 * lbs_cfg_wiphy_register().
112 */
113struct wireless_dev *lbs_cfg_alloc(struct device *dev)
114{
115 int ret = 0;
116 struct wireless_dev *wdev;
117
118 lbs_deb_enter(LBS_DEB_CFG80211);
119
120 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
121 if (!wdev) {
122 dev_err(dev, "cannot allocate wireless device\n");
123 return ERR_PTR(-ENOMEM);
124 }
125
126 wdev->wiphy = wiphy_new(&lbs_cfg80211_ops, sizeof(struct lbs_private));
127 if (!wdev->wiphy) {
128 dev_err(dev, "cannot allocate wiphy\n");
129 ret = -ENOMEM;
130 goto err_wiphy_new;
131 }
132
133 lbs_deb_leave(LBS_DEB_CFG80211);
134 return wdev;
135
136 err_wiphy_new:
137 kfree(wdev);
138 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
139 return ERR_PTR(ret);
140}
141
142
143/*
144 * This function get's called after lbs_setup_firmware() determined the
145 * firmware capabities. So we can setup the wiphy according to our
146 * hardware/firmware.
147 */
148int lbs_cfg_register(struct lbs_private *priv)
149{
150 struct wireless_dev *wdev = priv->wdev;
151 int ret;
152
153 lbs_deb_enter(LBS_DEB_CFG80211);
154
155 wdev->wiphy->max_scan_ssids = 1;
156 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
157
158 /* TODO: BIT(NL80211_IFTYPE_ADHOC); */
159 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
160
161 /* TODO: honor priv->regioncode */
162 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
163
164 /*
165 * We could check priv->fwcapinfo && FW_CAPINFO_WPA, but I have
166 * never seen a firmware without WPA
167 */
168 wdev->wiphy->cipher_suites = cipher_suites;
169 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
170
171 ret = wiphy_register(wdev->wiphy);
172 if (ret < 0)
173 lbs_pr_err("cannot register wiphy device\n");
174
175 ret = register_netdev(priv->dev);
176 if (ret)
177 lbs_pr_err("cannot register network device\n");
178
179 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
180 return ret;
181}
182
183
184void lbs_cfg_free(struct lbs_private *priv)
185{
186 struct wireless_dev *wdev = priv->wdev;
187
188 lbs_deb_enter(LBS_DEB_CFG80211);
189
190 if (!wdev)
191 return;
192
193 if (wdev->wiphy) {
194 wiphy_unregister(wdev->wiphy);
195 wiphy_free(wdev->wiphy);
196 }
197 kfree(wdev);
198}
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
new file mode 100644
index 000000000000..e09a193a34d6
--- /dev/null
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -0,0 +1,16 @@
1#ifndef __LBS_CFG80211_H__
2#define __LBS_CFG80211_H__
3
4#include "dev.h"
5
6struct wireless_dev *lbs_cfg_alloc(struct device *dev);
7int lbs_cfg_register(struct lbs_private *priv);
8void lbs_cfg_free(struct lbs_private *priv);
9
10int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
11 u8 ssid_len);
12int lbs_scan_networks(struct lbs_private *priv, int full_scan);
13void lbs_cfg_scan_worker(struct work_struct *work);
14
15
16#endif
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 72f3479a4d70..1cf5d5985dac 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -42,6 +42,7 @@
42#define LBS_DEB_SDIO 0x00400000 42#define LBS_DEB_SDIO 0x00400000
43#define LBS_DEB_SYSFS 0x00800000 43#define LBS_DEB_SYSFS 0x00800000
44#define LBS_DEB_SPI 0x01000000 44#define LBS_DEB_SPI 0x01000000
45#define LBS_DEB_CFG80211 0x02000000
45 46
46extern unsigned int lbs_debug; 47extern unsigned int lbs_debug;
47 48
@@ -86,6 +87,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \
86#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) 87#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
87#define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) 88#define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
88#define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) 89#define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
90#define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args)
89 91
90#define lbs_pr_info(format, args...) \ 92#define lbs_pr_info(format, args...) \
91 printk(KERN_INFO DRV_NAME": " format, ## args) 93 printk(KERN_INFO DRV_NAME": " format, ## args)
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 0018df14fad9..8abb28af5afa 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -100,6 +100,7 @@ struct lbs_mesh_stats {
100 100
101/** Private structure for the MV device */ 101/** Private structure for the MV device */
102struct lbs_private { 102struct lbs_private {
103 struct wireless_dev *wdev;
103 int mesh_open; 104 int mesh_open;
104 int mesh_fw_ver; 105 int mesh_fw_ver;
105 int infra_open; 106 int infra_open;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 9b2a9174a017..e6da1dfa8131 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -14,11 +14,13 @@
14#include <linux/stddef.h> 14#include <linux/stddef.h>
15#include <linux/ieee80211.h> 15#include <linux/ieee80211.h>
16#include <net/iw_handler.h> 16#include <net/iw_handler.h>
17#include <net/cfg80211.h>
17 18
18#include "host.h" 19#include "host.h"
19#include "decl.h" 20#include "decl.h"
20#include "dev.h" 21#include "dev.h"
21#include "wext.h" 22#include "wext.h"
23#include "cfg.h"
22#include "debugfs.h" 24#include "debugfs.h"
23#include "scan.h" 25#include "scan.h"
24#include "assoc.h" 26#include "assoc.h"
@@ -1245,31 +1247,42 @@ static const struct net_device_ops lbs_netdev_ops = {
1245 */ 1247 */
1246struct lbs_private *lbs_add_card(void *card, struct device *dmdev) 1248struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1247{ 1249{
1248 struct net_device *dev = NULL; 1250 struct net_device *dev;
1251 struct wireless_dev *wdev;
1249 struct lbs_private *priv = NULL; 1252 struct lbs_private *priv = NULL;
1250 1253
1251 lbs_deb_enter(LBS_DEB_MAIN); 1254 lbs_deb_enter(LBS_DEB_MAIN);
1252 1255
1253 /* Allocate an Ethernet device and register it */ 1256 /* Allocate an Ethernet device and register it */
1254 dev = alloc_etherdev(sizeof(struct lbs_private)); 1257 wdev = lbs_cfg_alloc(dmdev);
1255 if (!dev) { 1258 if (IS_ERR(wdev)) {
1256 lbs_pr_err("init wlanX device failed\n"); 1259 lbs_pr_err("cfg80211 init failed\n");
1257 goto done; 1260 goto done;
1258 } 1261 }
1259 priv = netdev_priv(dev); 1262 /* TODO? */
1260 dev->ml_priv = priv; 1263 wdev->iftype = NL80211_IFTYPE_STATION;
1264 priv = wdev_priv(wdev);
1265 priv->wdev = wdev;
1261 1266
1262 if (lbs_init_adapter(priv)) { 1267 if (lbs_init_adapter(priv)) {
1263 lbs_pr_err("failed to initialize adapter structure.\n"); 1268 lbs_pr_err("failed to initialize adapter structure.\n");
1264 goto err_init_adapter; 1269 goto err_wdev;
1270 }
1271
1272 //TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
1273 dev = alloc_netdev(0, "wlan%d", ether_setup);
1274 if (!dev) {
1275 dev_err(dmdev, "no memory for network device instance\n");
1276 goto err_adapter;
1265 } 1277 }
1266 1278
1279 dev->netdev_ops = &lbs_netdev_ops;
1280 dev->ieee80211_ptr = wdev;
1281 dev->ml_priv = priv;
1282 SET_NETDEV_DEV(dev, dmdev);
1283 wdev->netdev = dev;
1267 priv->dev = dev; 1284 priv->dev = dev;
1268 priv->card = card;
1269 priv->mesh_open = 0;
1270 priv->infra_open = 0;
1271 1285
1272 /* Setup the OS Interface to our functions */
1273 dev->netdev_ops = &lbs_netdev_ops; 1286 dev->netdev_ops = &lbs_netdev_ops;
1274 dev->watchdog_timeo = 5 * HZ; 1287 dev->watchdog_timeo = 5 * HZ;
1275 dev->ethtool_ops = &lbs_ethtool_ops; 1288 dev->ethtool_ops = &lbs_ethtool_ops;
@@ -1278,7 +1291,14 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1278#endif 1291#endif
1279 dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 1292 dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
1280 1293
1281 SET_NETDEV_DEV(dev, dmdev); 1294
1295 // TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
1296
1297
1298 priv->card = card;
1299 priv->mesh_open = 0;
1300 priv->infra_open = 0;
1301
1282 1302
1283 priv->rtap_net_dev = NULL; 1303 priv->rtap_net_dev = NULL;
1284 strcpy(dev->name, "wlan%d"); 1304 strcpy(dev->name, "wlan%d");
@@ -1288,7 +1308,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1288 priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main"); 1308 priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main");
1289 if (IS_ERR(priv->main_thread)) { 1309 if (IS_ERR(priv->main_thread)) {
1290 lbs_deb_thread("Error creating main thread.\n"); 1310 lbs_deb_thread("Error creating main thread.\n");
1291 goto err_init_adapter; 1311 goto err_ndev;
1292 } 1312 }
1293 1313
1294 priv->work_thread = create_singlethread_workqueue("lbs_worker"); 1314 priv->work_thread = create_singlethread_workqueue("lbs_worker");
@@ -1305,9 +1325,15 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1305 1325
1306 goto done; 1326 goto done;
1307 1327
1308err_init_adapter: 1328 err_ndev:
1309 lbs_free_adapter(priv);
1310 free_netdev(dev); 1329 free_netdev(dev);
1330
1331 err_adapter:
1332 lbs_free_adapter(priv);
1333
1334 err_wdev:
1335 lbs_cfg_free(priv);
1336
1311 priv = NULL; 1337 priv = NULL;
1312 1338
1313done: 1339done:
@@ -1359,6 +1385,7 @@ void lbs_remove_card(struct lbs_private *priv)
1359 kthread_stop(priv->main_thread); 1385 kthread_stop(priv->main_thread);
1360 1386
1361 lbs_free_adapter(priv); 1387 lbs_free_adapter(priv);
1388 lbs_cfg_free(priv);
1362 1389
1363 priv->dev = NULL; 1390 priv->dev = NULL;
1364 free_netdev(dev); 1391 free_netdev(dev);
@@ -1383,8 +1410,8 @@ int lbs_start_card(struct lbs_private *priv)
1383 /* init 802.11d */ 1410 /* init 802.11d */
1384 lbs_init_11d(priv); 1411 lbs_init_11d(priv);
1385 1412
1386 if (register_netdev(dev)) { 1413 if (lbs_cfg_register(priv)) {
1387 lbs_pr_err("cannot register ethX device\n"); 1414 lbs_pr_err("cannot register device\n");
1388 goto done; 1415 goto done;
1389 } 1416 }
1390 1417