libertas: cfg80211 support
PATCH 1/1 libertas: cfg80211 support
From: Holger Schurig <[email protected]>
We can get rid of the libertas wext, assoc and scan code.
The cfg80211 support is almost complete, the main missing feature being mesh support. There are also a few cfg80211_ops handlers missing (tx_power, bss_change for example).
Monitor and STA mode are supported and the latter have been tested on open, WEP, WPA and WPA2 links. At connection time, the cfg80211 bss list has to be populated with the BSS we're trying to join.
Also, passive and active (broadcast and directed) scanning have been tested (on a specific channel and on the whole band).
---
v1: scanning
v2: + WEP, WPA, WPA2
v3: + disconnect & MIC events, 11D region hint to cfg80211, auth_type TLV
v4: + IBSS
+ monitor mode
v5: + Search the cfg80211 bss list for the right BSSID when connecting.
+ Removed carrier off toggling when scanning.
+ Slightly changed the scanning state machine: The scan worker is
scheduled from the scan response handler, and we're checking for scan_channel to know if a scan is currently running.
+ Implemented RTS and fragmentation threshold.
+ Use the recently exported cfg80211_find_ie() routine.
In my opinion, the only missing feature (besides some small wext settings) is mesh, but I think this patch is ready for wireless-testing.
--- drivers/net/wireless/libertas/Makefile | 3 - drivers/net/wireless/libertas/assoc.c | 2243 ----------------------------- drivers/net/wireless/libertas/assoc.h | 155 -- drivers/net/wireless/libertas/cfg.c | 1939 +++++++++++++++++++++++++- drivers/net/wireless/libertas/cfg.h | 16 +- drivers/net/wireless/libertas/cmd.c | 22 +- drivers/net/wireless/libertas/cmdresp.c | 28 +- drivers/net/wireless/libertas/debugfs.c | 53 +- drivers/net/wireless/libertas/decl.h | 3 + drivers/net/wireless/libertas/dev.h | 59 +- drivers/net/wireless/libertas/ethtool.c | 5 - drivers/net/wireless/libertas/main.c | 221 +--- drivers/net/wireless/libertas/rx.c | 122 +-- drivers/net/wireless/libertas/scan.c | 1353 ------------------ drivers/net/wireless/libertas/scan.h | 63 - drivers/net/wireless/libertas/tx.c | 12 +- drivers/net/wireless/libertas/wext.c | 2348 ------------------------------- drivers/net/wireless/libertas/wext.h | 17 - 18 files changed, 1977 insertions(+), 6685 deletions(-) delete mode 100644 drivers/net/wireless/libertas/assoc.c delete mode 100644 drivers/net/wireless/libertas/assoc.h delete mode 100644 drivers/net/wireless/libertas/scan.c delete mode 100644 drivers/net/wireless/libertas/scan.h delete mode 100644 drivers/net/wireless/libertas/wext.c delete mode 100644 drivers/net/wireless/libertas/wext.h
drivers/net/wireless/libertas/Makefile +0 -3
@@ -1,4 +1,3 @@ -libertas-y += assoc.o libertas-y += cfg.o libertas-y += cmd.o libertas-y += cmdresp.o
@@ -6,9 +5,7 @@ libertas-y += debugfs.o libertas-y += ethtool.o libertas-y += main.o libertas-y += rx.o -libertas-y += scan.o libertas-y += tx.o -libertas-y += wext.o libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o usb8xxx-objs += if_usb.o
drivers/net/wireless/libertas/assoc.c deleted +0 -2243
2,243 lines not on this page · raw message
drivers/net/wireless/libertas/assoc.h deleted +0 -155
155 lines not on this page · raw message
drivers/net/wireless/libertas/cfg.c +1917 -22
589 lines not on this page · raw message
drivers/net/wireless/libertas/cmdresp.c +3 -25
Lines of this file are not shown. View the raw message.
drivers/net/wireless/libertas/debugfs.c +1 -52
53 lines not on this page · raw message
drivers/net/wireless/libertas/dev.h +9 -50
59 lines not on this page · raw message
drivers/net/wireless/libertas/ethtool.c +0 -5
Lines of this file are not shown. View the raw message.
drivers/net/wireless/libertas/main.c +4 -217
221 lines not on this page · raw message
drivers/net/wireless/libertas/rx.c +11 -111
122 lines not on this page · raw message
drivers/net/wireless/libertas/scan.c deleted +0 -1353
1,353 lines not on this page · raw message
drivers/net/wireless/libertas/scan.h deleted +0 -63
63 lines not on this page · raw message
drivers/net/wireless/libertas/wext.c deleted +0 -2348
2,348 lines not on this page · raw message
drivers/net/wireless/libertas/wext.h deleted +0 -17
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 5 lines
1.6.3.3 -- Intel Open Source Technology Centre http://oss.intel.com/
Part of the diff is not shown here. View the raw message.
Quoted 29 lines · Samuel Ortiz
From: Holger Schurig <[email protected]>
We can get rid of the libertas wext, assoc and scan code.
The cfg80211 support is almost complete, the main missing feature being mesh support. There are also a fewcfg80211_opshandlers missing (tx_power,bss_changefor example).
Monitor and STA mode are supported and the latter have been tested on open, WEP, WPA and WPA2 links. At connection time, the cfg80211 bss list has to be populated with the BSS we're trying to join.
Also, passive and active (broadcast and directed) scanning have been tested (on a specific channel and on the whole band).Signed-off-by Holger Schurig <[email protected]>Signed-off-by Samuel Ortiz <[email protected]>---
v1: scanning
v2: + WEP, WPA, WPA2
v3: + disconnect & MIC events, 11D region hint to cfg80211,auth_typeTLV
v4: + IBSS
+ monitor mode
v5: + Search the cfg80211 bss list for the right BSSID when connecting.
+ Removed carrier off toggling when scanning.
+ Slightly changed the scanning state machine: The scan worker is
scheduled from the scan response handler, and we're checking forscan_channelto know if a scan is currently running.
+ Implemented RTS and fragmentation threshold.
+ Use the recently exportedcfg80211_find_ie()routine.
Quoted 2 lines
In my opinion, the only missing feature (besides some small wext settings) is mesh, but I think this patch is ready for wireless-testing.
I'm happy to have libertas support cfg80211. But doesn't this remove the mesh support that the OLPC guys still use?
John
Signature · 2 lines
John W. Linville Someday the world will need a hero, and you [email protected] might be all we have. Be ready.
Quoted 2 lines
I'm happy to have libertas support cfg80211. But doesn't this remove the mesh support that the OLPC guys still use?
yes.
Or maybe not. I have another work-in-progress on top of my previous v4 patch that should implement mesh. I'll post that ASAP. Samuel can than rip things out of it :-) Because it's a patch on top of v4 (and not a new hs-v5 one), it's easy to see my changes.
------------------------------------------------------------------
* made "lbs_band_2ghz" non static, re-used that array in mesh code
* twiddled some debug output
* remove unused local variable "nr_sets" in lbs_ret_scan()
* lbs_ret_scan() bails out early if scanresp->nr_sets == 0
* added some "BUG_ON(!priv->scan_req)" sanity checks
* removed carrier up/down changes during scan
* lbs_cfg_scan() schedules the scan worker immediately and sets priv->scan_req before that
* added some more comments
* lbs_cfg_ret_disconnect() correctly sets state to LBS_DISCONNECTED
* removed reporting of bitrate, as this is not working
* fixed noise level reporting (broken lbs_get_survey() function)
* monitor will monitor more data
* untested mesh support via nl80211/cfg80211
* lbs_scan_deinit() will now send a scan-abort message to cfg80211 when priv->scan_req was active
* call lbs_scan_deinit() at "ifconfig wlan0 down" time. This also aborts the scan state inside cfg80211 and removes a BUG_ON- warning if a scan was active during "ifconfig wlan0 down" time.
* initialize return value in lbs_init_adapter() to avoid a warning
make C=1 clean, but not run throught scripts/checkpatch.pl
--- drivers/net/wireless/libertas/cfg.c | 108 +++++++++++++-------- drivers/net/wireless/libertas/cfg.h | 5 - drivers/net/wireless/libertas/cmd.c | 5 - drivers/net/wireless/libertas/dev.h | 3 drivers/net/wireless/libertas/main.c | 13 +- drivers/net/wireless/libertas/mesh.c | 174 ++++++++++++++++++++++++++++++----- drivers/net/wireless/libertas/mesh.h | 16 +-- 7 files changed, 236 insertions(+), 88 deletions(-)
drivers/net/wireless/libertas/cfg.c +67 -41
@@ -64,7 +64,7 @@ static struct ieee80211_rate lbs_rates[] RATETAB_ENT(540, 12, 0), }; -static struct ieee80211_supported_band lbs_band_2ghz = { +struct ieee80211_supported_band lbs_band_2ghz = { .channels = lbs_2ghz_channels, .n_channels =ARRAY_SIZE (lbs_2ghz_channels), .bitrates = lbs_rates,
@@ -203,7 +203,7 @@ static int lbs_add_channel_list_tlv(stru header->len =cpu_to_le16 (chanscanparamsize); tlv +=sizeof (struct mrvl_ie_header ); -/* lbs_deb_scan("scan: channels %d to %d\n", priv->scan_channel, +/* lbs_deb_scan("channels %d to %d\n", priv->scan_channel, last_channel); */ memset (tlv,0 , chanscanparamsize);
@@ -457,7 +457,6 @@ static int lbs_ret_scan(struct lbs_privastruct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;int bsssize;const u8 *pos; -u16 nr_sets;const u8 *tsfdesc;int tsfsize;int i;
@@ -465,8 +464,14 @@ static int lbs_ret_scan(struct lbs_privalbs_deb_enter (LBS_DEB_CFG80211 ); +/* Bail out early out if we didn't get BSS entries */ +if (scanresp->nr_sets ==0 ) { + ret =0 ; + goto done; + } bsssize =get_unaligned_le16 (&scanresp->bssdescriptsize); - nr_sets =le16_to_cpu (resp->size); + +BUG_ON (!priv->scan_req);/* * The general layout of the scan response is described in chapter
@@ -476,7 +481,7 @@ static int lbs_ret_scan(struct lbs_priva* * cmd_ds_802_11_scan_rsp * cmd_header -* pos_size +* bssdescriptsize * nr_sets * bssdesc 1 * bssid
@@ -569,11 +574,11 @@ static int lbs_ret_scan(struct lbs_privastruct ieee80211_channel *channel =ieee80211_get_channel (wiphy, freq); -lbs_deb_scan ("scan: %pM, capa %04x, chan %2d, %s, " -"%d dBm\n" , +lbs_deb_scan ("%pM, capa %04x, chan %2d, " +"%d dBm, %s\n" , bssid, capa, chan_no, -print_ssid (ssid_buf, ssid, ssid_len), -LBS_SCAN_RSSI_TO_MBM (rssi)/100 ); +LBS_SCAN_RSSI_TO_MBM (rssi)/100 , +print_ssid (ssid_buf, ssid, ssid_len));if (channel || !(channel->flags &IEEE80211_CHAN_DISABLED ))
@@ -614,24 +619,23 @@ static void lbs_scan_worker(struct work_struct cmd_ds_802_11_scan *scan_cmd;u8 *tlv;/* pointer into our current, growing TLV storage area */ int last_channel; -int running, carrier; +int running;lbs_deb_enter (LBS_DEB_SCAN ); +BUG_ON (!priv->scan_req); + scan_cmd =kzalloc (LBS_SCAN_MAX_CMD_SIZE ,GFP_KERNEL );if (scan_cmd ==NULL ) - goto out_no_scan_cmd; + goto done;/* prepare fixed part of scan command */ scan_cmd->bsstype =CMD_BSS_TYPE_ANY ;/* stop network while we're away from our main channel */ running = !netif_queue_stopped (priv->dev); - carrier =netif_carrier_ok (priv->dev);if (running)netif_stop_queue (priv->dev); -if (carrier) -netif_carrier_off (priv->dev);/* prepare fixed part of scan command */ tlv = scan_cmd->tlvbuffer;
@@ -669,6 +673,10 @@ static void lbs_scan_worker(struct work_le16_to_cpu (scan_cmd->hdr.size), lbs_ret_scan, 0); +/* __lbs_cmd() can possibly schedule, so make sure things are +* still sane */ +BUG_ON (!priv->scan_req); +if (priv->scan_channel >= priv->scan_req->n_channels) {/* Mark scan done */ cfg80211_scan_done (priv->scan_req, false);
@@ -676,14 +684,11 @@ static void lbs_scan_worker(struct work_ }/* Restart network */ -if (carrier) -netif_carrier_on (priv->dev);if (running && !priv->tx_pending_len)netif_wake_queue (priv->dev);kfree (scan_cmd); - - out_no_scan_cmd: + done:lbs_deb_leave (LBS_DEB_SCAN ); }
@@ -703,18 +708,16 @@ static int lbs_cfg_scan(struct wiphy *wi goto out; } -lbs_deb_scan ("scan: ssids %d, channels %d, ie_len %d\n" , +lbs_deb_scan ("ssids %d, channels %d, ie_len %d\n" , request->n_ssids, request->n_channels, request->ie_len); priv->scan_channel =0 ; -queue_delayed_work (priv->work_thread, &priv->scan_work, -msecs_to_jiffies (50 )); + priv->scan_req = request; +queue_delayed_work (priv->work_thread, &priv->scan_work,0 );if (priv->surpriseremoved) ret = -EIO ; - priv->scan_req = request; - out:lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret);return ret;
@@ -901,7 +904,7 @@ static int lbs_set_key_material(struct lstruct cmd_key_material cmd;int ret; -lbs_deb_enter (LBS_DEB_CFG80211 ); +lbs_deb_enter_args (LBS_DEB_CFG80211 ,"len %d" , key_len);/* * Example for WPA (TKIP):
@@ -910,8 +913,8 @@ static int lbs_set_key_material(struct l* size 34 00 * sequence xx xx * result 00 00 -* action 01 00 -* TLV type 00 01 key param +* action 01 00 CMD_ACT_SET +* TLV type 00 01 TLV_TYPE_KEY_MATERIAL * length 00 26 * key type 01 00 TKIP * key info 06 00 UNICAST | ENABLED
@@ -948,7 +951,7 @@ static int lbs_set_authtype(struct lbs_pstruct cmd_ds_802_11_authenticate cmd;int ret; -lbs_deb_enter_args (LBS_DEB_CFG80211 ,"%d" , sme->auth_type); +lbs_deb_enter_args (LBS_DEB_ASSOC ,"%d" , sme->auth_type);/* * cmd 11 00
@@ -972,7 +975,7 @@ static int lbs_set_authtype(struct lbs_p ret =lbs_cmd_with_response (priv,CMD_802_11_AUTHENTICATE , &cmd); done: -lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret); +lbs_deb_leave_args (LBS_DEB_ASSOC ,"ret %d" , ret);return ret; }
@@ -1002,7 +1005,7 @@ static int lbs_associate(struct lbs_privint ret;u8 *pos = &(cmd->iebuf[0 ]); -lbs_deb_enter (LBS_DEB_CFG80211 ); +lbs_deb_enter (LBS_DEB_ASSOC );if (!cmd) { ret = -ENOMEM ;
@@ -1121,7 +1124,7 @@ static int lbs_associate(struct lbs_priv done: -lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret); +lbs_deb_leave_args (LBS_DEB_ASSOC ,"ret %d" , ret);return ret; }
@@ -1162,7 +1165,7 @@ static int lbs_cfg_connect(struct wiphyif (!bss) { -lbs_pr_err ("assicate: bss %pM not in scan results\n" , +lbs_pr_err ("associate: BSS %pM not in scan results\n" , sme->bssid); ret = -ENOENT ; goto done;
@@ -1185,10 +1188,14 @@ static int lbs_cfg_connect(struct wiphy priv->wep_tx_key = sme->key_idx; priv->wep_key_len[sme->key_idx] = sme->key_len;memcpy (priv->wep_key[sme->key_idx], sme->key, sme->key_len); +/* Set WEP keys and WEP mode */ lbs_set_wep_keys (priv); + +/* Enable WEP mode in the MAC */ priv->mac_control |=CMD_ACT_MAC_WEP_ENABLE ;lbs_set_mac_control (priv); +/* No RSN mode for WEP */ lbs_enable_rsn (priv,0 );break ;
@@ -1204,6 +1211,8 @@ static int lbs_cfg_connect(struct wiphycase WLAN_CIPHER_SUITE_CCMP :/* Remove WEP keys and WEP mode */ lbs_remove_wep_keys (priv); + +/* Disable WEP mode in MAC */ priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE ;lbs_set_mac_control (priv);
@@ -1216,6 +1225,7 @@ static int lbs_cfg_connect(struct wiphyKEY_TYPE_ID_WEP ,/* doesn't matter */ KEY_INFO_WPA_MCAST , NULL, 0); +/* RSN mode for WPA/WPA2 */ lbs_enable_rsn (priv, sme->crypto.cipher_group !=0 );break ;
@@ -1246,7 +1256,7 @@ static int lbs_cfg_connect(struct wiphystatic int lbs_cfg_ret_disconnect (struct lbs_private *priv,unsigned long dummy,struct cmd_header *resp) { -lbs_deb_enter (LBS_DEB_CFG80211 ); +lbs_deb_enter (LBS_DEB_ASSOC ); cfg80211_disconnected(priv->dev, priv->disassoc_reason,
@@ -1254,9 +1264,10 @@ static int lbs_cfg_ret_disconnect(struct GFP_KERNEL);/* TODO: get rid of priv->connect_status */ - priv->connect_status =LBS_CONNECTED ; + priv->connect_status =LBS_DISCONNECTED ; +netif_carrier_off (priv->dev); -lbs_deb_leave (LBS_DEB_CFG80211 ); +lbs_deb_leave (LBS_DEB_ASSOC );return 0 ; }
@@ -1427,7 +1438,7 @@ static int lbs_enable_monitor_mode(struc* sequence xx xx * result 00 00 * action 01 00 ACT_SET -* enable 01 00 +* enable 01 00 bitmask (1=data, 2=ctrl, 4=beacon) */ memset (&cmd,0 ,sizeof (cmd)); cmd.hdr.size =cpu_to_le16 (sizeof (cmd));
@@ -1493,7 +1504,6 @@ static int lbs_cfg_get_station(struct wistruct lbs_private *priv =wiphy_priv (wiphy);s8 signal, noise;int ret; -size_t i;lbs_deb_enter (LBS_DEB_CFG80211 );
@@ -1513,14 +1523,20 @@ static int lbs_cfg_get_station(struct wi sinfo->filled |=STATION_INFO_SIGNAL ; } +#ifdef TODO +size_t i; + +/* "iw wlan link" says "failed to parse nested attributes!" */ +/* Convert priv->cur_rate from hw_value to NL80211 value */ for (i =0 ; i <ARRAY_SIZE (lbs_rates); i++) { -if (priv->cur_rate == lbs_rates[i].hw_value) { - sinfo->txrate.legacy = lbs_rates[i].bitrate; +if (priv->cur_rate == lbs_rates[i].bitrate) { + sinfo->txrate.legacy = lbs_rates[i].bitrate *10 ; sinfo->filled |=STATION_INFO_TX_BITRATE ;break ; } } +#endif return 0 ; }
@@ -1539,8 +1555,10 @@ static int lbs_get_survey(struct wiphy *s8 signal, noise;int ret; -if (idx !=0 ) +if (idx !=0 ) { ret = -ENOENT ; + goto out; + }lbs_deb_enter (LBS_DEB_CFG80211 );
@@ -1554,6 +1572,7 @@ static int lbs_get_survey(struct wiphy * }lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret); +out:return ret; }
@@ -1575,7 +1594,7 @@ static int lbs_change_intf(struct wiphyswitch (type) {case NL80211_IFTYPE_MONITOR : - ret =lbs_enable_monitor_mode (priv,1 ); + ret =lbs_enable_monitor_mode (priv,0x07 );break ;case NL80211_IFTYPE_STATION :if (priv->wdev->iftype ==NL80211_IFTYPE_MONITOR )
@@ -2076,8 +2095,15 @@ int lbs_cfg_register(struct lbs_privatevoid lbs_scan_deinit (struct lbs_private *priv) { -lbs_deb_enter (LBS_DEB_CFG80211 ); +lbs_deb_enter (LBS_DEB_SCAN ); +cancel_delayed_work_sync (&priv->scan_work); +if (priv->scan_req) { +cfg80211_scan_done (priv->scan_req, true); + priv->scan_req =NULL ; + } + +lbs_deb_leave (LBS_DEB_SCAN ); }
drivers/net/wireless/libertas/mesh.c +150 -24
272 lines not on this page · raw message
drivers/net/wireless/libertas/cfg.h +4 -1
@@ -1,9 +1,12 @@#ifndef __LBS_CFG80211_H__#define __LBS_CFG80211_H__ -struct device ; +#include <net/cfg80211.h> +struct lbs_private ; +extern struct ieee80211_supported_band lbs_band_2ghz; +struct wireless_dev *lbs_cfg_alloc (struct device *dev);int lbs_cfg_register (struct lbs_private *priv);void lbs_cfg_free (struct lbs_private *priv);
drivers/net/wireless/libertas/dev.h +2 -1
@@ -40,8 +40,9 @@ struct lbs_private {u8 disassoc_reason;/* Mesh */ -struct net_device *mesh_dev;/* Virtual device */ +struct net_device *mesh_dev;#ifdef CONFIG_LIBERTAS_MESH +struct wireless_dev *mesh_wdev;u32 mesh_connect_status;struct lbs_mesh_stats mstats;int mesh_open;
drivers/net/wireless/libertas/main.c +5 -8
@@ -129,6 +129,8 @@ static int lbs_eth_stop(struct net_deviclbs_deb_enter (LBS_DEB_NET ); +lbs_scan_deinit (priv); +spin_lock_irq (&priv->driver_lock);netif_stop_queue (dev);spin_unlock_irq (&priv->driver_lock);
@@ -730,7 +732,7 @@ int lbs_exit_auto_deep_sleep(struct lbs_static int lbs_init_adapter (struct lbs_private *priv) { -int ret; +int ret =0 ;lbs_deb_enter (LBS_DEB_MAIN );
@@ -899,17 +901,12 @@ void lbs_remove_card(struct lbs_privatelbs_remove_mesh (priv);lbs_scan_deinit (priv); - - dev = priv->dev; -cancel_work_sync (&priv->mcast_work);/* worker thread destruction blocks on the in-flight command which * should have been cleared already in lbs_stop_card(). */ -lbs_deb_main ("destroying worker thread\n" );destroy_workqueue (priv->work_thread); -lbs_deb_main ("done destroying worker thread\n" );if (priv->psmode ==LBS802_11POWERMODEMAX_PSP ) { priv->psmode =LBS802_11POWERMODECAM ;
@@ -1036,7 +1033,7 @@ void lbs_queue_event(struct lbs_private {unsigned long flags; -lbs_deb_enter (LBS_DEB_THREAD ); +lbs_deb_enter_args (LBS_DEB_CMD ,"event %d" , event);spin_lock_irqsave (&priv->driver_lock, flags);if (priv->psstate ==PS_STATE_SLEEP )
@@ -1047,7 +1044,7 @@ void lbs_queue_event(struct lbs_privatewake_up_interruptible (&priv->waitq);spin_unlock_irqrestore (&priv->driver_lock, flags); -lbs_deb_leave (LBS_DEB_THREAD ); +lbs_deb_leave (LBS_DEB_CMD ); }EXPORT_SYMBOL_GPL (lbs_queue_event);
drivers/net/wireless/libertas/mesh.h +7 -9
@@ -11,6 +11,11 @@ #ifdef CONFIG_LIBERTAS_MESH + +struct net_device; +struct lbs_private; + + /* Mesh statistics */ struct lbs_mesh_stats { u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
@@ -24,10 +29,8 @@ struct lbs_mesh_stats { }; -struct net_device ; -struct lbs_private ; - -int lbs_init_mesh (struct lbs_private *priv); +/* Initialization */ +void lbs_init_mesh (struct lbs_private *priv);int lbs_deinit_mesh (struct lbs_private *priv);int lbs_add_mesh (struct lbs_private *priv);
@@ -70,11 +73,6 @@ void lbs_persist_config_init(struct net_void lbs_persist_config_remove (struct net_device *net); -/* WEXT handler */ - -extern struct iw_handler_def mesh_handler_def; - -/* Ethtool statistics */ struct ethtool_stats ;
drivers/net/wireless/libertas/cmd.c +1 -4
@@ -81,8 +81,6 @@ static int lbs_is_cmd_allowed(struct lbs {int ret =1 ; -lbs_deb_enter (LBS_DEB_CMD ); -if (!priv->is_auto_deep_sleep_enabled) {if (priv->is_deep_sleep) {lbs_deb_cmd ("command not allowed in deep sleep\n" );
@@ -90,7 +88,6 @@ static int lbs_is_cmd_allowed(struct lbs } } -lbs_deb_leave (LBS_DEB_CMD );return ret; }
@@ -864,7 +861,7 @@ void lbs_set_mac_control(struct lbs_priv {struct cmd_ds_mac_control cmd; -lbs_deb_enter (LBS_DEB_CMD ); +lbs_deb_enter_args (LBS_DEB_CMD ,"0x%04x" , priv->mac_control); cmd.hdr.size =cpu_to_le16 (sizeof (cmd)); cmd.action =cpu_to_le16 (priv->mac_control);
Signature · 1 line
http://www.holgerschurig.de
Quoted 11 lines · Holger Schurig
Quoted 2 lines
I'm happy to have libertas support cfg80211. But doesn't this remove the mesh support that the OLPC guys still use?
yes.
Or maybe not. I have another work-in-progress on top of my previous v4 patch that should implement mesh. I'll post that ASAP. Samuel can than rip things out of it :-) Because it's a patch on top of v4 (and not a new hs-v5 one), it's easy to see my changes.
John, I'll try to integrate Holger's changes and come up with a new patch that would have mesh support.
Cheers,
Samuel.
Quoted 830 lines
------------------------------------------------------------------
* made "
lbs_band_2ghz" non static, re-used that array in mesh code
* twiddled some debug output
* remove unused local variable "nr_sets" inlbs_ret_scan()
*lbs_ret_scan()bails out early ifscanresp->nr_sets== 0
* added some "BUG_ON(!priv->scan_req)" sanity checks
* removed carrier up/down changes during scan
*lbs_cfg_scan()schedules the scan worker immediately and setspriv->scan_reqbefore that
* added some more comments
*lbs_cfg_ret_disconnect()correctly sets state toLBS_DISCONNECTED
* removed reporting of bitrate, as this is not working
* fixed noise level reporting (brokenlbs_get_survey()function)
* monitor will monitor more data
* untested mesh support via nl80211/cfg80211
*lbs_scan_deinit()will now send a scan-abort message to cfg80211 whenpriv->scan_reqwas active
* calllbs_scan_deinit()at "ifconfig wlan0 down" time. This also aborts the scan state inside cfg80211 and removes a BUG_ON- warning if a scan was active during "ifconfig wlan0 down" time.
* initialize return value inlbs_init_adapter()to avoid a warningSigned-off-by Holger Schurig <[email protected]>make C=1 clean, but not run throught
scripts/checkpatch.pl--- drivers/net/wireless/libertas/cfg.c | 108 +++++++++++++-------- drivers/net/wireless/libertas/cfg.h | 5 - drivers/net/wireless/libertas/cmd.c | 5 - drivers/net/wireless/libertas/dev.h | 3 drivers/net/wireless/libertas/main.c | 13 +- drivers/net/wireless/libertas/mesh.c | 174 ++++++++++++++++++++++++++++++----- drivers/net/wireless/libertas/mesh.h | 16 +-- 7 files changed, 236 insertions(+), 88 deletions(-)drivers/net/wireless/libertas/cfg.c +67
-41@@ -64,7 +64,7 @@ static struct ieee80211_rate lbs_rates[] RATETAB_ENT(540, 12, 0), }; -static struct ieee80211_supported_band lbs_band_2ghz = { +struct ieee80211_supported_band lbs_band_2ghz = { .channels = lbs_2ghz_channels, .n_channels =ARRAY_SIZE (lbs_2ghz_channels), .bitrates = lbs_rates,@@ -203,7 +203,7 @@ static int lbs_add_channel_list_tlv(stru header->len =cpu_to_le16 (chanscanparamsize); tlv +=sizeof (struct mrvl_ie_header ); -/* lbs_deb_scan("scan: channels %d to %d\n", priv->scan_channel, +/* lbs_deb_scan("channels %d to %d\n", priv->scan_channel, last_channel); */ memset (tlv,0 , chanscanparamsize);@@ -457,7 +457,6 @@ static int lbs_ret_scan(struct lbs_privastruct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;int bsssize;const u8 *pos; -u16 nr_sets;const u8 *tsfdesc;int tsfsize;int i;@@ -465,8 +464,14 @@ static int lbs_ret_scan(struct lbs_privalbs_deb_enter (LBS_DEB_CFG80211 ); +/* Bail out early out if we didn't get BSS entries */ +if (scanresp->nr_sets ==0 ) { + ret =0 ; + goto done; + } bsssize =get_unaligned_le16 (&scanresp->bssdescriptsize); - nr_sets =le16_to_cpu (resp->size); + +BUG_ON (!priv->scan_req);/* * The general layout of the scan response is described in chapter @@ -476,7 +481,7 @@ static int lbs_ret_scan(struct lbs_priva* * cmd_ds_802_11_scan_rsp * cmd_header -* pos_size +* bssdescriptsize * nr_sets * bssdesc 1 * bssid @@ -569,11 +574,11 @@ static int lbs_ret_scan(struct lbs_privastruct ieee80211_channel *channel =ieee80211_get_channel (wiphy, freq); -lbs_deb_scan ("scan: %pM, capa %04x, chan %2d, %s, " -"%d dBm\n" , +lbs_deb_scan ("%pM, capa %04x, chan %2d, " +"%d dBm, %s\n" , bssid, capa, chan_no, -print_ssid (ssid_buf, ssid, ssid_len), -LBS_SCAN_RSSI_TO_MBM (rssi)/100 ); +LBS_SCAN_RSSI_TO_MBM (rssi)/100 , +print_ssid (ssid_buf, ssid, ssid_len));if (channel || !(channel->flags &IEEE80211_CHAN_DISABLED ))@@ -614,24 +619,23 @@ static void lbs_scan_worker(struct work_struct cmd_ds_802_11_scan *scan_cmd;u8 *tlv;/* pointer into our current, growing TLV storage area */ int last_channel; -int running, carrier; +int running;lbs_deb_enter (LBS_DEB_SCAN ); +BUG_ON (!priv->scan_req); + scan_cmd =kzalloc (LBS_SCAN_MAX_CMD_SIZE ,GFP_KERNEL );if (scan_cmd ==NULL ) - goto out_no_scan_cmd; + goto done;/* prepare fixed part of scan command */ scan_cmd->bsstype =CMD_BSS_TYPE_ANY ;/* stop network while we're away from our main channel */ running = !netif_queue_stopped (priv->dev); - carrier =netif_carrier_ok (priv->dev);if (running)netif_stop_queue (priv->dev); -if (carrier) -netif_carrier_off (priv->dev);/* prepare fixed part of scan command */ tlv = scan_cmd->tlvbuffer;@@ -669,6 +673,10 @@ static void lbs_scan_worker(struct work_le16_to_cpu (scan_cmd->hdr.size), lbs_ret_scan, 0); +/* __lbs_cmd() can possibly schedule, so make sure things are +* still sane */ +BUG_ON (!priv->scan_req); +if (priv->scan_channel >= priv->scan_req->n_channels) {/* Mark scan done */ cfg80211_scan_done (priv->scan_req, false);@@ -676,14 +684,11 @@ static void lbs_scan_worker(struct work_ }/* Restart network */ -if (carrier) -netif_carrier_on (priv->dev);if (running && !priv->tx_pending_len)netif_wake_queue (priv->dev);kfree (scan_cmd); - - out_no_scan_cmd: + done:lbs_deb_leave (LBS_DEB_SCAN ); }@@ -703,18 +708,16 @@ static int lbs_cfg_scan(struct wiphy *wi goto out; } -lbs_deb_scan ("scan: ssids %d, channels %d, ie_len %d\n" , +lbs_deb_scan ("ssids %d, channels %d, ie_len %d\n" , request->n_ssids, request->n_channels, request->ie_len); priv->scan_channel =0 ; -queue_delayed_work (priv->work_thread, &priv->scan_work, -msecs_to_jiffies (50 )); + priv->scan_req = request; +queue_delayed_work (priv->work_thread, &priv->scan_work,0 );if (priv->surpriseremoved) ret = -EIO ; - priv->scan_req = request; - out:lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret);return ret;@@ -901,7 +904,7 @@ static int lbs_set_key_material(struct lstruct cmd_key_material cmd;int ret; -lbs_deb_enter (LBS_DEB_CFG80211 ); +lbs_deb_enter_args (LBS_DEB_CFG80211 ,"len %d" , key_len);/* * Example for WPA (TKIP): @@ -910,8 +913,8 @@ static int lbs_set_key_material(struct l* size 34 00 * sequence xx xx * result 00 00 -* action 01 00 -* TLV type 00 01 key param +* action 01 00 CMD_ACT_SET +* TLV type 00 01 TLV_TYPE_KEY_MATERIAL * length 00 26 * key type 01 00 TKIP * key info 06 00 UNICAST | ENABLED @@ -948,7 +951,7 @@ static int lbs_set_authtype(struct lbs_pstruct cmd_ds_802_11_authenticate cmd;int ret; -lbs_deb_enter_args (LBS_DEB_CFG80211 ,"%d" , sme->auth_type); +lbs_deb_enter_args (LBS_DEB_ASSOC ,"%d" , sme->auth_type);/* * cmd 11 00 @@ -972,7 +975,7 @@ static int lbs_set_authtype(struct lbs_p ret =lbs_cmd_with_response (priv,CMD_802_11_AUTHENTICATE , &cmd); done: -lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret); +lbs_deb_leave_args (LBS_DEB_ASSOC ,"ret %d" , ret);return ret; }@@ -1002,7 +1005,7 @@ static int lbs_associate(struct lbs_privint ret;u8 *pos = &(cmd->iebuf[0 ]); -lbs_deb_enter (LBS_DEB_CFG80211 ); +lbs_deb_enter (LBS_DEB_ASSOC );if (!cmd) { ret = -ENOMEM ;@@ -1121,7 +1124,7 @@ static int lbs_associate(struct lbs_priv done: -lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret); +lbs_deb_leave_args (LBS_DEB_ASSOC ,"ret %d" , ret);return ret; }@@ -1162,7 +1165,7 @@ static int lbs_cfg_connect(struct wiphyif (!bss) { -lbs_pr_err ("assicate: bss %pM not in scan results\n" , +lbs_pr_err ("associate: BSS %pM not in scan results\n" , sme->bssid); ret = -ENOENT ; goto done;@@ -1185,10 +1188,14 @@ static int lbs_cfg_connect(struct wiphy priv->wep_tx_key = sme->key_idx; priv->wep_key_len[sme->key_idx] = sme->key_len;memcpy (priv->wep_key[sme->key_idx], sme->key, sme->key_len); +/* Set WEP keys and WEP mode */ lbs_set_wep_keys (priv); + +/* Enable WEP mode in the MAC */ priv->mac_control |=CMD_ACT_MAC_WEP_ENABLE ;lbs_set_mac_control (priv); +/* No RSN mode for WEP */ lbs_enable_rsn (priv,0 );break ;@@ -1204,6 +1211,8 @@ static int lbs_cfg_connect(struct wiphycase WLAN_CIPHER_SUITE_CCMP :/* Remove WEP keys and WEP mode */ lbs_remove_wep_keys (priv); + +/* Disable WEP mode in MAC */ priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE ;lbs_set_mac_control (priv);@@ -1216,6 +1225,7 @@ static int lbs_cfg_connect(struct wiphyKEY_TYPE_ID_WEP ,/* doesn't matter */ KEY_INFO_WPA_MCAST , NULL, 0); +/* RSN mode for WPA/WPA2 */ lbs_enable_rsn (priv, sme->crypto.cipher_group !=0 );break ;@@ -1246,7 +1256,7 @@ static int lbs_cfg_connect(struct wiphystatic int lbs_cfg_ret_disconnect (struct lbs_private *priv,unsigned long dummy,struct cmd_header *resp) { -lbs_deb_enter (LBS_DEB_CFG80211 ); +lbs_deb_enter (LBS_DEB_ASSOC ); cfg80211_disconnected(priv->dev, priv->disassoc_reason,@@ -1254,9 +1264,10 @@ static int lbs_cfg_ret_disconnect(struct GFP_KERNEL);/* TODO: get rid of priv->connect_status */ - priv->connect_status =LBS_CONNECTED ; + priv->connect_status =LBS_DISCONNECTED ; +netif_carrier_off (priv->dev); -lbs_deb_leave (LBS_DEB_CFG80211 ); +lbs_deb_leave (LBS_DEB_ASSOC );return 0 ; }@@ -1427,7 +1438,7 @@ static int lbs_enable_monitor_mode(struc* sequence xx xx * result 00 00 * action 01 00 ACT_SET -* enable 01 00 +* enable 01 00 bitmask (1=data, 2=ctrl, 4=beacon) */ memset (&cmd,0 ,sizeof (cmd)); cmd.hdr.size =cpu_to_le16 (sizeof (cmd));@@ -1493,7 +1504,6 @@ static int lbs_cfg_get_station(struct wistruct lbs_private *priv =wiphy_priv (wiphy);s8 signal, noise;int ret; -size_t i;lbs_deb_enter (LBS_DEB_CFG80211 );@@ -1513,14 +1523,20 @@ static int lbs_cfg_get_station(struct wi sinfo->filled |=STATION_INFO_SIGNAL ; } +#ifdef TODO +size_t i; + +/* "iw wlan link" says "failed to parse nested attributes!" */ +/* Convert priv->cur_rate from hw_value to NL80211 value */ for (i =0 ; i <ARRAY_SIZE (lbs_rates); i++) { -if (priv->cur_rate == lbs_rates[i].hw_value) { - sinfo->txrate.legacy = lbs_rates[i].bitrate; +if (priv->cur_rate == lbs_rates[i].bitrate) { + sinfo->txrate.legacy = lbs_rates[i].bitrate *10 ; sinfo->filled |=STATION_INFO_TX_BITRATE ;break ; } } +#endif return 0 ; }@@ -1539,8 +1555,10 @@ static int lbs_get_survey(struct wiphy *s8 signal, noise;int ret; -if (idx !=0 ) +if (idx !=0 ) { ret = -ENOENT ; + goto out; + }lbs_deb_enter (LBS_DEB_CFG80211 );@@ -1554,6 +1572,7 @@ static int lbs_get_survey(struct wiphy * }lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret); +out:return ret; }@@ -1575,7 +1594,7 @@ static int lbs_change_intf(struct wiphyswitch (type) {case NL80211_IFTYPE_MONITOR : - ret =lbs_enable_monitor_mode (priv,1 ); + ret =lbs_enable_monitor_mode (priv,0x07 );break ;case NL80211_IFTYPE_STATION :if (priv->wdev->iftype ==NL80211_IFTYPE_MONITOR )@@ -2076,8 +2095,15 @@ int lbs_cfg_register(struct lbs_privatevoid lbs_scan_deinit (struct lbs_private *priv) { -lbs_deb_enter (LBS_DEB_CFG80211 ); +lbs_deb_enter (LBS_DEB_SCAN ); +cancel_delayed_work_sync (&priv->scan_work); +if (priv->scan_req) { +cfg80211_scan_done (priv->scan_req, true); + priv->scan_req =NULL ; + } + +lbs_deb_leave (LBS_DEB_SCAN ); }drivers/net/wireless/libertas/mesh.c +150
-24@@ -5,13 +5,130 @@#include <linux/if_arp.h> #include <linux/kthread.h> #include <linux/kfifo.h> +#include <net/cfg80211.h> #include "mesh.h" +#include "cfg.h" #include "decl.h" #include "cmd.h" /*************************************************************************** +* Mesh cfg80211 support +*/ + +static int lbs_join_mesh (struct wiphy *wiphy,struct net_device *dev, +struct cfg80211_ibss_params *params) +{ +struct lbs_private *priv =wiphy_priv (wiphy); +int ret =0 ; +DECLARE_SSID_BUF (ssid_buf); + +lbs_deb_enter (LBS_DEB_CFG80211 ); + +if (!params->channel) { + ret = -ENOTSUPP ; + goto out; + } + +/* If channel != current channel AND if we're connected, then this +* won't work */ + + ret =lbs_set_channel (priv, params->channel->hw_value); +if (ret) + goto out; + +//TODO +// CMD_ACT_MESH_CONFIG_START + out: +lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret); +return ret; +} + + +static int lbs_leave_mesh (struct wiphy *wiphy,struct net_device *dev) +{ +//struct lbs_private *priv = wiphy_priv(wiphy); +//struct cmd_ds_802_11_ad_hoc_stop cmd; +int ret =0 ; + +lbs_deb_enter (LBS_DEB_CFG80211 ); + +//TODO + +lbs_deb_leave_args (LBS_DEB_CFG80211 ,"ret %d" , ret); +return ret; +} + + +static struct cfg80211_ops lbs_cfg80211_mesh_ops = { + .join_ibss = lbs_join_mesh, + .leave_ibss = lbs_leave_mesh, +}; + + +static struct wireless_dev *lbs_cfg_alloc_mesh (struct lbs_private *priv) +{ +int ret =0 ; +struct wireless_dev *wdev; + +lbs_deb_enter (LBS_DEB_MESH ); + + wdev =kzalloc (sizeof (struct wireless_dev ),GFP_KERNEL ); +if (!wdev) { +lbs_pr_err ("cannot allocate mesh wireless device\n" ); +return ERR_PTR (-ENOMEM ); + } + + wdev->wiphy =wiphy_new (&lbs_cfg80211_mesh_ops,0 ); +if (!wdev->wiphy) { +lbs_pr_err ("cannot allocate mesh wiphy\n" ); + ret = -ENOMEM ; + goto err_wiphy_new; + } + wdev->iftype =NL80211_IFTYPE_ADHOC ;//TODO: is this right? + +lbs_deb_leave (LBS_DEB_MESH ); +return wdev; + + err_wiphy_new: +kfree (wdev); +lbs_deb_leave_args (LBS_DEB_MESH ,"ret %d" , ret); +return ERR_PTR (ret); +} + +static int lbs_mesh_register (struct lbs_private *priv) +{ +struct wireless_dev *wdev = priv->mesh_wdev; +int ret; + +lbs_deb_enter (LBS_DEB_MESH ); + + wdev->wiphy->max_scan_ssids =1 ; + wdev->wiphy->signal_type =CFG80211_SIGNAL_TYPE_MBM ; + + wdev->wiphy->interface_modes =BIT (NL80211_IFTYPE_ADHOC ); + + wdev->wiphy->bands[IEEE80211_BAND_2GHZ ] = &lbs_band_2ghz; + +/* +* We could check priv->fwcapinfo && FW_CAPINFO_WPA, but I have +* never seen a firmware without WPA +*/ +//wdev->wiphy->cipher_suites = cipher_suites; +//wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + + ret =wiphy_register (wdev->wiphy); +if (ret <0 ) +lbs_pr_err ("cannot register mesh wiphy device\n" ); + +lbs_deb_leave_args (LBS_DEB_MESH ,"ret %d" , ret); +return ret; +} + + + +/*************************************************************************** * Mesh sysfs support */ @@ -185,14 +302,14 @@ static struct attribute_group lbs_mesh_a* Initializing and starting, stopping mesh */ +/* * Check mesh FW version and appropriately send the mesh start * command */ -int lbs_init_mesh (struct lbs_private *priv) +void lbs_init_mesh (struct lbs_private *priv) {struct net_device *dev = priv->dev; -int ret =0 ;lbs_deb_enter (LBS_DEB_MESH );@@ -237,31 +354,41 @@ int lbs_init_mesh(struct lbs_private *pr priv->mesh_tlv =0 ; } +if (!priv->mesh_tlv) + goto out; -if (priv->mesh_tlv) { -sprintf (priv->mesh_ssid,"mesh" ); - priv->mesh_ssid_len =4 ; - -lbs_add_mesh (priv); - -if (device_create_file (&dev->dev, &dev_attr_lbs_mesh)) -lbs_pr_err ("cannot register lbs_mesh attribute\n" ); +lbs_deb_mesh ("using %s mesh commands\n" , + priv->mesh_tlv ==TLV_TYPE_OLD_MESH_ID + ?"old" :"new" ); +sprintf (priv->mesh_ssid,"mesh" ); + priv->mesh_ssid_len =4 ; + + priv->mesh_wdev =lbs_cfg_alloc_mesh (priv); +lbs_add_mesh (priv); +lbs_mesh_register (priv); - ret =1 ; - } +if (device_create_file (&dev->dev, &dev_attr_lbs_mesh)) +lbs_pr_err ("cannot register lbs_mesh attribute\n" ); -lbs_deb_leave_args (LBS_DEB_MESH ,"ret %d" , ret); -return ret; +out: +lbs_deb_leave (LBS_DEB_MESH ); }int lbs_deinit_mesh (struct lbs_private *priv) {struct net_device *dev = priv->dev; +struct wireless_dev *mesh_wdev = priv->mesh_wdev;int ret =0 ;lbs_deb_enter (LBS_DEB_MESH ); +if (mesh_wdev) { +if (mesh_wdev->wiphy) +wiphy_unregister (mesh_wdev->wiphy); +wiphy_free (mesh_wdev->wiphy); + } +if (priv->mesh_tlv) {device_remove_file (&dev->dev, &dev_attr_lbs_mesh); ret =1 ;@@ -283,6 +410,7 @@ static int lbs_mesh_stop(struct net_devistruct lbs_private *priv = dev->ml_priv;lbs_deb_enter (LBS_DEB_MESH ); +spin_lock_irq (&priv->driver_lock); priv->mesh_open =0 ;@@ -310,16 +438,14 @@ static int lbs_mesh_dev_open(struct net_struct lbs_private *priv = dev->ml_priv;int ret =0 ; -lbs_deb_enter (LBS_DEB_NET ); +lbs_deb_enter (LBS_DEB_MESH );spin_lock_irq (&priv->driver_lock); -#ifdef TODO -if (priv->monitormode) { +if (priv->wdev->iftype ==NL80211_IFTYPE_MONITOR ) { ret = -EBUSY ; goto out; } -#endif priv->mesh_open =1 ; priv->mesh_connect_status =LBS_CONNECTED ;@@ -329,7 +455,7 @@ static int lbs_mesh_dev_open(struct net_netif_wake_queue (dev);spin_unlock_irq (&priv->driver_lock); -lbs_deb_leave_args (LBS_DEB_NET ,"ret %d" , ret); +lbs_deb_leave_args (LBS_DEB_MESH ,"ret %d" , ret);return ret; }@@ -364,16 +490,15 @@ int lbs_add_mesh(struct lbs_private *pri mesh_dev->ml_priv = priv; priv->mesh_dev = mesh_dev; +//TODO mesh_dev->ieee80211_ptr = priv->mesh_wdev; mesh_dev->netdev_ops = &mesh_netdev_ops; mesh_dev->ethtool_ops = &lbs_ethtool_ops;memcpy (mesh_dev->dev_addr, priv->dev->dev_addr,ETH_ALEN );SET_NETDEV_DEV (priv->mesh_dev, priv->dev->dev.parent); -#ifdef WIRELESS_EXT - mesh_dev->wireless_handlers = &mesh_handler_def; -#endif mesh_dev->flags |=IFF_BROADCAST |IFF_MULTICAST ; +/* Register virtual mesh interface */ ret =register_netdev (mesh_dev);if (ret) {@@ -404,13 +529,13 @@ done:void lbs_remove_mesh (struct lbs_private *priv) { -struct net_device *mesh_dev; +struct net_device *mesh_dev = priv->mesh_dev; - mesh_dev = priv->mesh_dev;if (!mesh_dev)return ;lbs_deb_enter (LBS_DEB_MESH ); +netif_stop_queue (mesh_dev);netif_carrier_off (mesh_dev);sysfs_remove_group (&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);@@ -418,6 +543,7 @@ void lbs_remove_mesh(struct lbs_privateunregister_netdev (mesh_dev); priv->mesh_dev =NULL ;free_netdev (mesh_dev); +lbs_deb_leave (LBS_DEB_MESH ); }drivers/net/wireless/libertas/cfg.h +4
-1@@ -1,9 +1,12 @@#ifndef __LBS_CFG80211_H__#define __LBS_CFG80211_H__ -struct device ; +#include <net/cfg80211.h> +struct lbs_private ; +extern struct ieee80211_supported_band lbs_band_2ghz; +struct wireless_dev *lbs_cfg_alloc (struct device *dev);int lbs_cfg_register (struct lbs_private *priv);void lbs_cfg_free (struct lbs_private *priv);drivers/net/wireless/libertas/dev.h +2
-1@@ -40,8 +40,9 @@ struct lbs_private {u8 disassoc_reason;/* Mesh */ -struct net_device *mesh_dev;/* Virtual device */ +struct net_device *mesh_dev;#ifdef CONFIG_LIBERTAS_MESH +struct wireless_dev *mesh_wdev;u32 mesh_connect_status;struct lbs_mesh_stats mstats;int mesh_open;drivers/net/wireless/libertas/main.c +5
-8@@ -129,6 +129,8 @@ static int lbs_eth_stop(struct net_deviclbs_deb_enter (LBS_DEB_NET ); +lbs_scan_deinit (priv); +spin_lock_irq (&priv->driver_lock);netif_stop_queue (dev);spin_unlock_irq (&priv->driver_lock);@@ -730,7 +732,7 @@ int lbs_exit_auto_deep_sleep(struct lbs_static int lbs_init_adapter (struct lbs_private *priv) { -int ret; +int ret =0 ;lbs_deb_enter (LBS_DEB_MAIN );@@ -899,17 +901,12 @@ void lbs_remove_card(struct lbs_privatelbs_remove_mesh (priv);lbs_scan_deinit (priv); - - dev = priv->dev; -cancel_work_sync (&priv->mcast_work);/* worker thread destruction blocks on the in-flight command which * should have been cleared already in lbs_stop_card(). */ -lbs_deb_main ("destroying worker thread\n" );destroy_workqueue (priv->work_thread); -lbs_deb_main ("done destroying worker thread\n" );if (priv->psmode ==LBS802_11POWERMODEMAX_PSP ) { priv->psmode =LBS802_11POWERMODECAM ;@@ -1036,7 +1033,7 @@ void lbs_queue_event(struct lbs_private {unsigned long flags; -lbs_deb_enter (LBS_DEB_THREAD ); +lbs_deb_enter_args (LBS_DEB_CMD ,"event %d" , event);spin_lock_irqsave (&priv->driver_lock, flags);if (priv->psstate ==PS_STATE_SLEEP )@@ -1047,7 +1044,7 @@ void lbs_queue_event(struct lbs_privatewake_up_interruptible (&priv->waitq);spin_unlock_irqrestore (&priv->driver_lock, flags); -lbs_deb_leave (LBS_DEB_THREAD ); +lbs_deb_leave (LBS_DEB_CMD ); }EXPORT_SYMBOL_GPL (lbs_queue_event);drivers/net/wireless/libertas/mesh.h +7
-9@@ -11,6 +11,11 @@ #ifdef CONFIG_LIBERTAS_MESH + +struct net_device; +struct lbs_private; + + /* Mesh statistics */ struct lbs_mesh_stats { u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */@@ -24,10 +29,8 @@ struct lbs_mesh_stats { }; -struct net_device ; -struct lbs_private ; - -int lbs_init_mesh (struct lbs_private *priv); +/* Initialization */ +void lbs_init_mesh (struct lbs_private *priv);int lbs_deinit_mesh (struct lbs_private *priv);int lbs_add_mesh (struct lbs_private *priv);@@ -70,11 +73,6 @@ void lbs_persist_config_init(struct net_void lbs_persist_config_remove (struct net_device *net); -/* WEXT handler */ - -extern struct iw_handler_def mesh_handler_def; - -/* Ethtool statistics */ struct ethtool_stats ;drivers/net/wireless/libertas/cmd.c +1
-4@@ -81,8 +81,6 @@ static int lbs_is_cmd_allowed(struct lbs {int ret =1 ; -lbs_deb_enter (LBS_DEB_CMD ); -if (!priv->is_auto_deep_sleep_enabled) {if (priv->is_deep_sleep) {lbs_deb_cmd ("command not allowed in deep sleep\n" );@@ -90,7 +88,6 @@ static int lbs_is_cmd_allowed(struct lbs } } -lbs_deb_leave (LBS_DEB_CMD );return ret; }@@ -864,7 +861,7 @@ void lbs_set_mac_control(struct lbs_priv {struct cmd_ds_mac_control cmd; -lbs_deb_enter (LBS_DEB_CMD ); +lbs_deb_enter_args (LBS_DEB_CMD ,"0x%04x" , priv->mac_control); cmd.hdr.size =cpu_to_le16 (sizeof (cmd)); cmd.action =cpu_to_le16 (priv->mac_control);Signature · 2 lines
-- http://www.holgerschurig.de
Signature · 2 lines
Intel Open Source Technology Centre http://oss.intel.com/
Hmm, there are also still some bugs lurking in the code. Just
I had an application running that was pinging and showed the signal level. Then I moved out-of-reach of the AP. This happened:
libertas: PREP_CMD: command 0x001f failed: 1
libertas: PREP_CMD: command 0x001f failed: 1
libertas: PREP_CMD: command 0x001f failed: 1
libertas: PREP_CMD: command 0x001f failed: 1
libertas: PREP_CMD: command 0x001f failed: 1
libertas: PREP_CMD: command 0x001f failed: 1
libertas: PREP_CMD: command 0x001f failed: 1
libertas: PREP_CMD: command 0x001f failed: 1
libertas: PREP_CMD: command 0x001f failed: 1
libertas: PREP_CMD: command 0x001f failed: 1
libertas: command 0x001f timed out
libertas: requeueing command 0x001f due to timeout (#1)
libertas: command 0x001f timed out
libertas: requeueing command 0x001f due to timeout (#2)
libertas: command 0x001f timed out
libertas: requeueing command 0x001f due to timeout (#3)
------------[ cut here ]------------ WARNING: at net/sched/sch_generic.c:261 dev_watchdog+0x19c/0x290() NETDEV WATCHDOG: wlan0 (libertas_cs): transmit queue 0 timed out Modules linked in: libertas_cs libertas cfg80211 compat_firmware_class [last unloaded: cfg80211] Backtrace: [<c0029464>] (dump_backtrace+0x0/0x100) from [<c002957c>] (dump_stack+0x18/0x1c) r7:c0221e24 r6:c0170694 r5:c020aa78 r4:00000105 [<c0029564>] (dump_stack+0x0/0x1c) from [<c00353a8>] (warn_slowpath_common+0x4c/0x64) [<c003535c>] (warn_slowpath_common+0x0/0x64) from [<c003540c>] (warn_slowpath_fmt+0x30/0x38) r7:00000000 r6:00000001 r5:00000001 r4:c3b4f800 [<c00353dc>] (warn_slowpath_fmt+0x0/0x38) from [<c0170694>] (dev_watchdog+0x19c/0x290) r3:c3b4f800 r2:c020aa38 [<c01704f8>] (dev_watchdog+0x0/0x290) from [<c003ea28>] (run_timer_softirq+0x190/0x1f0) r8:c0221ebc r7:c01704f8 r6:00000100 r5:c023c0e0 r4:c0220000 [<c003e898>] (run_timer_softirq+0x0/0x1f0) from [<c0039d94>] (__do_softirq+0x8c/0x140) [<c0039d08>] (__do_softirq+0x0/0x140) from [<c003a0a4>] (irq_exit+0x40/0x88) [<c003a064>] (irq_exit+0x0/0x88) from [<c0025070>] (asm_do_IRQ+0x70/0x84) r4:0000001a [<c0025000>] (asm_do_IRQ+0x0/0x84) from [<c0025a84>] (__irq_svc+0x24/0xa0) Exception stack(0xc0221f58 to 0xc0221fa0)
1f40: 00000001 08eff847
1f60: 00000000 60000013 c0220000 c02388e4 c0018ca0 c0223dd4 a00178e0 69052d06 1f80: a0017878 c0221fac c0221fb0 c0221fa0 c00269e8 c00269f4 60000013 ffffffff
r6:04000000 r5:f2d00000 r4:ffffffff
[<c00269c8>] (default_idle+0x0/0x30) from [<c0026a64>] (cpu_idle+0x6c/0xa8) [<c00269f8>] (cpu_idle+0x0/0xa8) from [<c01b03c0>] (rest_init+0x58/0x6c)
r4:c0249774
[<c01b0368>] (rest_init+0x0/0x6c) from [<c00088f0>] (start_kernel+0x220/0x27c) [<c00086d0>] (start_kernel+0x0/0x27c) from [<a0008034>] (0xa0008034)
---[ end trace 54aeef8ca4684eee ]---
libertas: tx watch dog timeout
libertas: command 0x001f timed out
libertas: Excessive timeouts submitting command 0x001f
libertas: PREP_CMD: command 0x001f failed: -110
Quoted 5 lines · Holger Schurig
Hmm, there are also still some bugs lurking in the code. Just
I had an application running that was pinging and showed the signal level. Then I moved out-of-reach of the AP. This happened:
The command timeout code is just screwed all around. We've already seen that some commands just take longer than we're expecting them to. I think we should just get rid of the command retry stuff completely and return EBUSY when trying to submit additional commands if the firmware hasn't replied yet.
I don't think I've *ever* seen recovery from this situation unless the firmware finally sends the command reply back, which has happened in some cases with SD8686. IMHO the command retry stuff causes more problems than it's worth, given that it never actually fixes anything or recovers from the timeout.
If the firmware is hung, the only way to get the device back is to power-cycle it or possibly do a USB reset. Retrying a command just doesn't work.
Dan
Quoted 54 lines
libertas:
PREP_CMD: command0x001ffailed: 1
libertas:PREP_CMD: command0x001ffailed: 1
libertas:PREP_CMD: command0x001ffailed: 1
libertas:PREP_CMD: command0x001ffailed: 1
libertas:PREP_CMD: command0x001ffailed: 1
libertas:PREP_CMD: command0x001ffailed: 1
libertas:PREP_CMD: command0x001ffailed: 1
libertas:PREP_CMD: command0x001ffailed: 1
libertas:PREP_CMD: command0x001ffailed: 1
libertas:PREP_CMD: command0x001ffailed: 1
libertas: command0x001ftimed out
libertas: requeueing command0x001fdue to timeout (#1)
libertas: command0x001ftimed out
libertas: requeueing command0x001fdue to timeout (#2)
libertas: command0x001ftimed out
libertas: requeueing command0x001fdue to timeout (#3)------------[ cut here ]------------ WARNING: at net/sched/sch_generic.c:261 dev_watchdog+0x19c/0x290() NETDEV WATCHDOG: wlan0 (libertas_cs): transmit queue 0 timed out Modules linked in: libertas_cs libertas cfg80211 compat_firmware_class [last unloaded: cfg80211] Backtrace: [<c0029464>] (dump_backtrace+0x0/0x100) from [<c002957c>] (dump_stack+0x18/0x1c) r7:c0221e24 r6:c0170694 r5:c020aa78 r4:00000105 [<c0029564>] (dump_stack+0x0/0x1c) from [<c00353a8>] (warn_slowpath_common+0x4c/0x64) [<c003535c>] (warn_slowpath_common+0x0/0x64) from [<c003540c>] (warn_slowpath_fmt+0x30/0x38) r7:00000000 r6:00000001 r5:00000001 r4:c3b4f800 [<c00353dc>] (warn_slowpath_fmt+0x0/0x38) from [<c0170694>] (dev_watchdog+0x19c/0x290) r3:c3b4f800 r2:c020aa38 [<c01704f8>] (dev_watchdog+0x0/0x290) from [<c003ea28>] (run_timer_softirq+0x190/0x1f0) r8:c0221ebc r7:c01704f8 r6:00000100 r5:c023c0e0 r4:c0220000 [<c003e898>] (run_timer_softirq+0x0/0x1f0) from [<c0039d94>] (__do_softirq+0x8c/0x140) [<c0039d08>] (__do_softirq+0x0/0x140) from [<c003a0a4>] (irq_exit+0x40/0x88) [<c003a064>] (irq_exit+0x0/0x88) from [<c0025070>] (asm_do_IRQ+0x70/0x84) r4:0000001a [<c0025000>] (asm_do_IRQ+0x0/0x84) from [<c0025a84>] (__irq_svc+0x24/0xa0) Exception stack(0xc0221f58 to 0xc0221fa0)1f40: 00000001
08eff847
1f60: 00000000 60000013c0220000c02388e4c0018ca0c0223dd4a00178e069052d061f80:a0017878c0221facc0221fb0c0221fa0c00269e8c00269f460000013 ffffffff
r6:04000000 r5:f2d00000 r4:ffffffff
[<c00269c8>] (default_idle+0x0/0x30) from [<c0026a64>] (cpu_idle+0x6c/0xa8) [<c00269f8>] (cpu_idle+0x0/0xa8) from [<c01b03c0>] (rest_init+0x58/0x6c)
r4:c0249774
[<c01b0368>] (rest_init+0x0/0x6c) from [<c00088f0>] (start_kernel+0x220/0x27c) [<c00086d0>] (start_kernel+0x0/0x27c) from [<a0008034>] (0xa0008034)---[ end trace 54aeef8ca4684eee ]---libertas: tx watch dog timeout
libertas: command0x001ftimed out
libertas: Excessive timeouts submitting command0x001f
libertas:PREP_CMD: command0x001ffailed: -110
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 9 lines
Quoted 3 lines
I had an application running that was pinging and showed the signal level. Then I moved out-of-reach of the AP. This happened:
The command timeout code is just screwed all around. We've already seen that some commands just take longer than we're expecting them to. I think we should just get rid of the command retry stuff completely and return EBUSY when trying to submit additional commands if the firmware hasn't replied yet.
I think the same.
I think in my case --- which I haven't debugged completely yet --- user-space code was going wild. The firmware command 001f (get RSSI) failed. Which is to be expected, because the firmware noticed that there's no longer a connection to an AP.
However, user-space nl80211 code seems to have been buggy and issued the same command in a loop. This flooded the the command-execution logic in libertas, and it couldn't cope with it.
AFAIK the error I had had nothing to do with the cfg80211-code inside the libertas driver. Or maybe it is, I'll write a little program that floods libertas via cfg80211 with commands in a tight loop, let's see what happens. :-)
Getting rid of the command-retry and returning an error instead seems to be a sane thing.
Quoted 9 lines
I don't think I've *ever* seen recovery from this situation unless the firmware finally sends the command reply back, which has happened in some cases with SD8686. IMHO the command retry stuff causes more problems than it's worth, given that it never actually fixes anything or recovers from the timeout.
If the firmware is hung, the only way to get the device back is to power-cycle it or possibly do a USB reset. Retrying a command just doesn't work.
In my case, I could do a "pccardctl eject" / "pccardctl insert"
sequence :-) Not nice. Maybe we need a signal from
core-libertas to the libertas-drivers, so that they decide what to do.
Signature · 1 line
http://www.holgerschurig.de
Quoted 37 lines · Holger Schurig
Quoted 9 lines
Quoted 3 lines
I had an application running that was pinging and showed the signal level. Then I moved out-of-reach of the AP. This happened:
The command timeout code is just screwed all around. We've already seen that some commands just take longer than we're expecting them to. I think we should just get rid of the command retry stuff completely and return EBUSY when trying to submit additional commands if the firmware hasn't replied yet.
I think the same.
I think in my case --- which I haven't debugged completely yet --- user-space code was going wild. The firmware command 001f (get RSSI) failed. Which is to be expected, because the firmware noticed that there's no longer a connection to an AP.
However, user-space nl80211 code seems to have been buggy and issued the same command in a loop. This flooded the the command-execution logic in libertas, and it couldn't cope with it.
AFAIK the error I had had nothing to do with the cfg80211-code inside the libertas driver. Or maybe it is, I'll write a little program that floods libertas via cfg80211 with commands in a tight loop, let's see what happens. :-)
Getting rid of the command-retry and returning an error instead seems to be a sane thing.
Quoted 6 lines
I don't think I've *ever* seen recovery from this situation unless the firmware finally sends the command reply back, which has happened in some cases with SD8686. IMHO the command retry stuff causes more problems than it's worth, given that it never actually fixes anything or recovers from the timeout.
Quoted 8 lines
Quoted 3 lines
If the firmware is hung, the only way to get the device back is to power-cycle it or possibly do a USB reset. Retrying a command just doesn't work.
In my case, I could do a "pccardctl eject" / "pccardctl insert"
sequence :-) Not nice. Maybe we need a signal from
core-libertas to the libertas-drivers, so that they decide what to do.
There should be some reset logic in there for each bus type; it was only ever hooked up for USB because it's easy to do a USB reset. SDIO and SPI are somewhat harder because often it's board-specific thing. Not sure what to do there; we did try writing various SDIO registers that were supposed to reset the card but that never worked.
Dan
Quoted 4 lines
+ Slightly changed the scanning state machine: The scan worker is scheduled from the scan response handler, and we're checking for
scan_channelto know if a scan is currently running.
Can you tell my why you change the scanning state machine? What was broken with it, or why is it now better?
Also, previously priv->scan_req was the marker that a scan was going on. What did it "buy" to you to change this to priv->scan_channel?
Hi Holger,
Quoted 7 lines · Holger Schurig
Quoted 4 lines
+ Slightly changed the scanning state machine: The scan worker is scheduled from the scan response handler, and we're checking for
scan_channelto know if a scan is currently running.Can you tell my why you change the scanning state machine? What was broken with it, or why is it now better?
Well, I wasnt happy with the delayed scan work your patch was using. First you were delaying the initial work and I dont think it's useful. Then we were scheduling a new scan work from the scan worker itself. Although it was also delayed by 300 ms, you still dont have any guarantees that the previous scan is done when the next scan worker starts.
What I changed is triggerring the scan work whenever the last one is done, i.e. triggering it from lbs_ret_scan(). This way we have a fully synchronized scanning state machine.
Quoted 4 lines
Also, previously
priv->scan_reqwas the marker that a scan was going on. What did it "buy" to you to change this topriv->scan_channel?
I guess I could still use scan_req for that purpose.
My initial thought was that you could have 2 lbs_cfg_scan() running at the same time since you could potentially have a 2nd lbs_cfg_scan() call before scan_request is actually set. However I believe cfg80211 and nl80211 prevent that from happening anyway as they call the scan ops under the rtnl lock. So, as I said, I could probably keep using scan_request.
Cheers,
Samuel.
Signature · 2 lines
Intel Open Source Technology Centre http://oss.intel.com/
Quoted 2 lines
What I changed is triggerring the scan work whenever the last one is done, i.e. triggering it from
lbs_ret_scan().
Ah, that makes sense.
Quoted 3 lines
My initial thought was that you could have 2
lbs_cfg_scan()running at the same time since you could potentially have a 2ndlbs_cfg_scan()call beforescan_requestis actually set.
Hmm, even when cfg80211 would allow this, I wouldn't allow this in the driver. All the hoops with the delayed-scan-work is because the firmware can't send a I'm-on-powersafe-notification to the current AP while being on other channels. So I have to make sure to return from time to time to my AP, so that I won't loose packets for me and won't be disconnected.
If now two scan_req and therefore two scan workers run, the time we're away from our "home channel" increases, which also increase the deauthentication problem.
Oh, and btw: we can later add an optimization that if we aren't connected at all, we do all scans in one-go, without delays. We still need to send several scan-commands to the firmware, to reduce the possible that a huuuuuge scan response overflows some firmware buffer limit.
Thanks for your answers.
Best regards,
Holger
Signature · 1 line
http://www.holgerschurig.de
Hi Samuel !
You wrote this code:
Quoted 7 lines
drivers/net/wireless/libertas/cfg.c +7
-0+static int lbs_cfg_del_key (struct wiphy *wiphy,struct net_device *netdev, + u8 key_index, const u8 *mac_addr) +{ + struct lbs_private *priv = wiphy_priv(wiphy); + + lbs_deb_enter(LBS_DEB_CFG80211); +
drivers/net/wireless/libertas/cfg.c static const u32 cipher_suites[] = { · line 1394
Quoted 10 lines
drivers/net/wireless/libertas/cfg.c +10
-0+ if (key_index < 3 && priv->wep_key_len[key_index]) { + priv->wep_key_len[key_index] = 0; + lbs_set_wep_keys(priv); + } + + lbs_deb_assoc("del_key: key_idx %d, mac_addr %pM\n", + key_index, mac_addr); + + return 0; +}
while I had this a no-op. I had a long comment at this code, where I wrote:
/*
* I think can keep this a NO-OP, because:
* - we clear all keys whenever we do lbs_cfg_connect() anyway
* - neither "iw" nor "wpa_supplicant" won't call this during
* an ongoing connection
* - TODO: but I have to check if this is still true when
* I set the AP to periodic re-keying
* - we've not kzallec() something when we've added a key at
* lbs_cfg_connect() or lbs_cfg_add_key().
*
* This causes lbs_cfg_del_key() only called at disconnect time,
* where we'd just waste time deleting a key that is not going
* to be used anyway.
*/
Didn't you agree with that test? Did any of the WPA/WPA2/WEP connections broke for you? I didn't saw any problems, even when changing from WEP to WPA and back without reloading the driver.
However, I haven't tested libertas+cfg with the wext- compatibility thing, maybe it's needed then? But I doubt it, because of point one in my comment-list.
Signature · 1 line
http://www.holgerschurig.de
Hi Holger,
Quoted 15 lines · Holger Schurig
Hi Samuel !
You wrote this code:
Quoted 11 lines
drivers/net/wireless/libertas/cfg.c +11
-0+static int lbs_cfg_del_key (struct wiphy *wiphy,struct net_device *netdev, + u8 key_index, const u8 *mac_addr) +{ + struct lbs_private *priv = wiphy_priv(wiphy); + + lbs_deb_enter(LBS_DEB_CFG80211); + + if (key_index < 3 && priv->wep_key_len[key_index]) { + priv->wep_key_len[key_index] = 0; + lbs_set_wep_keys(priv); + }
Quoted 8 lines
drivers/net/wireless/libertas/cfg.c static const u32 cipher_suites[] = { · line 1394
Quoted 6 lines
drivers/net/wireless/libertas/cfg.c +6
-0+ + lbs_deb_assoc("del_key: key_idx %d, mac_addr %pM\n", + key_index, mac_addr); + + return 0; +}while I had this a no-op.
Sorry about this one. I was hitting WEP connection issues and I uncommented that as I thought it could be the problem. But it wasnt related and then I forgot to comment it again.
I definitely agree this could be left as a NO-OP.
Cheers,
Samuel.
Quoted 29 lines
I had a long comment at this code,
where I wrote:/*
* I think can keep this a NO-OP, because:
* - we clear all keys whenever we dolbs_cfg_connect()anyway
* - neither "iw" nor "wpa_supplicant" won't call this during
* an ongoing connection
* - TODO: but I have to check if this is still true when
* I set the AP to periodic re-keying
* - we've notkzallec()something when we've added a key at
*lbs_cfg_connect()orlbs_cfg_add_key().
*
* This causeslbs_cfg_del_key()only called at disconnect time,
* where we'd just waste time deleting a key that is not going
* to be used anyway.
*/Didn't you agree with that test? Did any of the WPA/WPA2/WEP connections broke for you? I didn't saw any problems, even when changing from WEP to WPA and back without reloading the driver.
However, I haven't tested libertas+cfg with the wext- compatibility thing, maybe it's needed then? But I doubt it, because of point one in my comment-list.
Signature · 1 line
http://www.holgerschurig.de
Signature · 2 lines
Intel Open Source Technology Centre http://oss.intel.com/
PATCH 1/1 libertas+cfg80211: better disconnect support
In reply to Samuel OrtizHi Samuel !
This patch was necessary for me to make
while true; iw wlan0 link; sleep 0.1; done
not hang in "iw" when moving out-of-reach of an AP.
--------------------------
An issue with "iw wlan0 link" hanging when moving out-of-reach of an AP was observed. The reason was that lbs_get_signal() returned "1" in case of an error from the firmware and that this value was given back to cfg80211.
However a cfg80211-operation method should return standard -Exxx error codes, not posive values. The positive value ended up in iw, where a line like "while (ret > 0) ..." was looping endless.
For error recovery, it also helped to report link loss much earlier to user-space. I actually have Cisco APs lying around, so I know that the one-second delay doesn't upset neither an Cisco 1231/1241 nor wpa_supplicant 0.7.1 (at least not in -Dnl80211 mode). This made wpa_supplicant scan one second earlier and re-connect therefore faster to another suitable AP.
--- drivers/net/wireless/libertas/cfg.c | 10 ++++++++-- drivers/net/wireless/libertas/cmdresp.c | 5 ----- 2 files changed, 8 insertions(+), 7 deletions(-)
drivers/net/wireless/libertas/cfg.c +1 -0
@@ -1478,6 +1478,7 @@ struct cmd_rssi {__le16 avg_nf; } __attribute__ ((packed)); + static int lbs_get_signal(struct lbs_private *priv, s8 *signal,
s8 *noise)
{
struct cmd_rssi cmd;
@@ -1492,6 +1493,7 @@ static int lbs_get_signal(struct lbs_pri
le16_to_cpu(cmd.nf));
*noise = CAL_NF(le16_to_cpu(cmd.nf));
}
+
return ret;
}
@@ -1516,7 +1518,9 @@ static int lbs_cfg_get_station(struct wi
/* Get current RSSI */
ret = lbs_get_signal(priv, &signal, &noise);
- if (ret == 0) {
+ if (ret)
+ ret = -EBUSY;
+ else {
sinfo->signal = signal;
sinfo->filled |= STATION_INFO_SIGNAL;
}
@@ -1564,7 +1568,9 @@ static int lbs_get_survey(struct wiphy *
ieee80211_channel_to_frequency(priv->channel));
ret = lbs_get_signal(priv, &signal, &noise);
- if (ret == 0) {
+ if (ret)
+ ret = -EBUSY;
+ else {
survey->filled = SURVEY_INFO_NOISE_DBM; survey->noise = noise;
}
drivers/net/wireless/libertas/cmdresp.c +0 -5
@@ -25,11 +25,6 @@ void lbs_mac_event_disconnected(struct llbs_deb_enter (LBS_DEB_ASSOC ); -/* -* Cisco AP sends EAP failure and de-auth in less than 0.5 ms. -* It causes problem in the Supplicant -*/ -msleep_interruptible (1000 );lbs_send_disconnect_notification (priv);/* report disconnect to upper layer */
Signature · 1 line
http://www.holgerschurig.de
Quoted 4 lines
+ bss = cfg80211_get_bss(wiphy,
sme->channel,sme->bssid, +sme->ssid,sme->ssid_len,
+WLAN_CAPABILITY_ESS,WLAN_CAPABILITY_ESS);drivers/net/wireless/libertas/cfg.c +1
-0+
drivers/net/wireless/libertas/cfg.c static const u32 cipher_suites[] = { · line 1180
Quoted 10 lines
drivers/net/wireless/libertas/cfg.c +10
-0+ if (!bss) { + if (sme->bssid || sme->ssid_len != IEEE80211_MAX_SSID_LEN) { + DECLARE_SSID_BUF(ssid); + lbs_pr_err("associate: BSS %s not in scan results\n", + print_ssid(ssid, sme->ssid, sme->ssid_len)); + ret = -ENOENT; + } + + goto done; + }
I have again some time for Libertas :-)
I'm still not getting this code at all, especially the code inside "if (!bss)". You set "ret = -ENOENT", but only under some circumstances. When they aren't met, we go to label done, but with "ret=0", e.g. we didn't connect, but still we won't return an error.
Also, you print the SSID, but name it "BSS". A BSS is kind-of-a-mac-address. So the text in the printk should be "associate: no SSID %s in scan results". Or you print the BSS from sme->
And then I don't get why there is a comparison sme->ssid_len != IEEE80211_MAX_SSID_LEN. print_ssid() handles this.
Wouldn't this snipped do the work:
lbs_deb_enter(LBS_DEB_CFG80211);
bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
sme->ssid, sme->ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
if (!bss) {
lbs_pr_err("no matching AP found in last scan\n");
ret = -ENOENT;
goto done;
}
lbs_deb_assoc("trying %pM", sme->bssid);Signature · 1 line
http://www.holgerschurig.de
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 9 lines · David MOUSSAUD
Hello,
I'm trying to apply the first patch of this thread to have the cfg80211 support to my driver but I do not succeed to select the goot git repository or the goot release tarball (linux kernel/compat wireless) to start.
Does someone could help me for that ?
Quoted 8 lines
Furthermore, I have an at91sam9260 atmel evk board with a wi2wi (which embeded a 8686 libertas chip) sdio evk. I need to have my board running as an Access Point.
Could someone tell me if, applying this patch, it will works ?For my understanding, I think it will because it is written that the driver with cfg80111 can now work in monitor mode, which is ok for hostapd to act as an AP.
This isn't going to work. The fullmac Libertas devices (8385, 8388, 8686, etc) do not have the firmware capability to operate in AP mode. cfg80211 is simply a better configuration interface than WEXT, it does not magically add AP mode capability.
Dan
Quoted 76 lines
Thanks for your help,
Best Regards,
D.MOUSSAUD.
On Mon, Feb 15, 2010 at 11:46 AM, Holger Schurig
<[email protected]> wrote:> + bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, > + sme->ssid, sme->ssid_len, > + WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); > + > + if (!bss) { > + if (sme->bssid || sme->ssid_len != IEEE80211_MAX_SSID_LEN) { > + DECLARE_SSID_BUF(ssid); > + lbs_pr_err("associate: BSS %s not in scan results\n", > + print_ssid(ssid, sme->ssid, sme->ssid_len)); > + ret = -ENOENT; > + } > + > + goto done; > + } I have again some time for Libertas :-) I'm still not getting this code at all, especially the code inside "if (!bss)". You set "ret = -ENOENT", but only under some circumstances. When they aren't met, we go to label done, but with "ret=0", e.g. we didn't connect, but still we won't return an error. Also, you print the SSID, but name it "BSS". A BSS is kind-of-a-mac-address. So the text in the printk should be "associate: no SSID %s in scan results". Or you print the BSS from sme-> And then I don't get why there is a comparison sme->ssid_len != IEEE80211_MAX_SSID_LEN. print_ssid() handles this. Wouldn't this snipped do the work: lbs_deb_enter(LBS_DEB_CFG80211); bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid, sme->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!bss) { lbs_pr_err("no matching AP found in last scan \n"); ret = -ENOENT; goto done; } lbs_deb_assoc("trying %pM", sme->bssid); -- http://www.holgerschurig.de -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Thanks for the explication.
Do you know an other sdio chipset that would do the job ?
BR,
David.
Quoted 105 lines · Dan Williams
Quoted 9 lines · David MOUSSAUD
Hello,
I'm trying to apply the first patch of this thread to have the cfg80211 support to my driver but I do not succeed to select the goot git repository or the goot release tarball (linux kernel/compat wireless) to start.
Does someone could help me for that ?
Quoted 8 lines
Furthermore, I have an at91sam9260 atmel evk board with a wi2wi (which embeded a 8686 libertas chip) sdio evk. I need to have my board running as an Access Point.
Could someone tell me if, applying this patch, it will works ?For my understanding, I think it will because it is written that the driver with cfg80111 can now work in monitor mode, which is ok for hostapd to act as an AP.
This isn't going to work. The fullmac Libertas devices (8385, 8388, 8686, etc) do not have the firmware capability to operate in AP mode. cfg80211 is simply a better configuration interface than WEXT, it does not magically add AP mode capability.
Dan
Quoted 76 lines
Thanks for your help,
Best Regards,
D.MOUSSAUD.
On Mon, Feb 15, 2010 at 11:46 AM, Holger Schurig <[email protected]> wrote:
> + bss = cfg80211_get_bss(wiphy,sme->channel,sme->bssid,
> + sme->ssid,sme->ssid_len, > + WLAN_CAPABILITY_ESS,WLAN_CAPABILITY_ESS);
> +
> + if (!bss) {
> + if (sme->bssid||sme->ssid_len!=IEEE80211_MAX_SSID_LEN) {
> +DECLARE_SSID_BUF(ssid);
> + lbs_pr_err("associate: BSS %s not in scan results\n",
> + print_ssid(ssid,sme->ssid,sme->ssid_len));
> + ret =-ENOENT;
> + }
> +
> + goto done;
> + }I have again some time for Libertas :-)
I'm still not getting this code at all, especially the code inside
"if (!bss)". You set "ret =-ENOENT", but only under some circumstances. When they aren't met, we go to label done, but with "ret=0", e.g. we didn't connect, but still we won't return an error.Also, you print the SSID, but name it "BSS". A BSS is kind-of-a-mac-address. So the text in the printk should be "associate: no SSID %s in scan results". Or you print the BSS from sme->
And then I don't get why there is a comparison
sme->ssid_len!=IEEE80211_MAX_SSID_LEN.print_ssid()handles this.Wouldn't this snipped do the work:
lbs_deb_enter(LBS_DEB_CFG80211);
bss = cfg80211_get_bss(wiphy,sme->channel,sme->bssid,sme->ssid,sme->ssid_len,WLAN_CAPABILITY_ESS,WLAN_CAPABILITY_ESS);if (!bss) {
lbs_pr_err("no matching AP found in last scan \n");
ret =-ENOENT;
goto done;
}
lbs_deb_assoc("trying %pM",sme->bssid);--
http://www.holgerschurig.de
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to [email protected] More majordomo info at
http://vger.kernel.org/majordomo-info.html
Johannes Berg
maintainerQuoted 2 lines · David MOUSSAUD
Thanks for the explication.
Do you know an other sdio chipset that would do the job ?
libertas_tf driver has AP iirc.
johannes
Quoted 5 lines · Johannes Berg
Quoted 2 lines · David MOUSSAUD
Thanks for the explication.
Do you know an other sdio chipset that would do the job ?
libertas_tfdriver has AP iirc.
Yes but it only supports one variant with USB (88w8388) and special firmware, there's no SDIO equivalent.
The only soft-MAC/mac80211 hardware/driver that I can think of that has an SDIO variant right now is the TI wl12xx stuff but I don't know anything about it or whether it can do enough to support AP via mac80211.
-Andrey
Quoted 11 lines · Andrey Yurovsky
Quoted 3 lines
Quoted 1 line
Do you know an other sdio chipset that would do the job ?
libertas_tfdriver has AP iirc.Yes but it only supports one variant with USB (88w8388) and special firmware, there's no SDIO equivalent.
The only soft-MAC/mac80211 hardware/driver that I can think of that has an SDIO variant right now is the TI wl12xx stuff but I don't know anything about it or whether it can do enough to support AP via mac80211.
wl1251 at least doesn't support AP mode. Maybe it's possible to hack something in the driver, but because firmware doesn't support it it would be incomplete anyway.
Signature · 1 line
Kalle Valo
Quoted 18 lines · Kalle Valo
Quoted 11 lines · Andrey Yurovsky
Quoted 3 lines
Quoted 1 line
Do you know an other sdio chipset that would do the job ?
libertas_tfdriver has AP iirc.Yes but it only supports one variant with USB (88w8388) and special firmware, there's no SDIO equivalent.
The only soft-MAC/mac80211 hardware/driver that I can think of that has an SDIO variant right now is the TI wl12xx stuff but I don't know anything about it or whether it can do enough to support AP via mac80211.
wl1251 at least doesn't support AP mode. Maybe it's possible to hack something in the driver, but because firmware doesn't support it it would be incomplete anyway.
Quoted 7 lines
--
Kalle Valo
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
B43 also has SDIO support, and AFAIK AP mode also works (though not sure if you can use AP mode on an SDIO card). The only problem is finding an SDIO card with a Broadcom chipset.
Signature · 1 line
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)
Hello,
I'm trying to apply this patch of this thread to have the cfg80211 support to my driver but I do not succeed to select the good git repository or the good release tarball (linux kernel/compat wireless) to start.
Does someone could help me for that ?
Furthermore, I have an at91sam9260 atmel evk board with a wi2wi (which embeded a 8686 libertas chip) sdio evk. I need to have my board running as an Access Point.
Could someone tell me if, applying this patch, it will works ?
For my understanding, I think it will because it is written that the driver with cfg80111 can now work in monitor mode, which is ok for hostapd to work.
Thanks for your help,
Best Regards,
D.MOUSSAUD.
Quoted 9,293 lines · Samuel Ortiz
From: Holger Schurig <[email protected]>
We can get rid of the libertas wext, assoc and scan code.
The cfg80211 support is almost complete, the main missing feature being mesh support. There are also a fewcfg80211_opshandlers missing (tx_power,bss_changefor example).
Monitor and STA mode are supported and the latter have been tested on open, WEP, WPA and WPA2 links. At connection time, the cfg80211 bss list has to be populated with the BSS we're trying to join.
Also, passive and active (broadcast and directed) scanning have been tested (on a specific channel and on the whole band).Signed-off-by Holger Schurig <[email protected]>Signed-off-by Samuel Ortiz <[email protected]>---
v1: scanning
v2: + WEP, WPA, WPA2
v3: + disconnect & MIC events, 11D region hint to cfg80211,auth_typeTLV
v4: + IBSS
+ monitor mode
v5: + Search the cfg80211 bss list for the right BSSID when connecting.
+ Removed carrier off toggling when scanning.
+ Slightly changed the scanning state machine: The scan worker is scheduled from the scan response handler, and we're checking forscan_channelto know if a scan is currently running.
+ Implemented RTS and fragmentation threshold.
+ Use the recently exportedcfg80211_find_ie()routine.In my opinion, the only missing feature (besides some small wext settings) is mesh, but I think this patch is ready for wireless-testing.
---drivers/net/wireless/libertas/Makefile | 3 - drivers/net/wireless/libertas/assoc.c | 2243 ----------------------------- drivers/net/wireless/libertas/assoc.h | 155 -- drivers/net/wireless/libertas/cfg.c | 1939 +++++++++++++++++++++++++- drivers/net/wireless/libertas/cfg.h | 16 +- drivers/net/wireless/libertas/cmd.c | 22 +-drivers/net/wireless/libertas/cmdresp.c | 28 +-
drivers/net/wireless/libertas/debugfs.c| 53 +-drivers/net/wireless/libertas/decl.h| 3 +drivers/net/wireless/libertas/dev.h| 59 +-drivers/net/wireless/libertas/ethtool.c| 5 -drivers/net/wireless/libertas/main.c| 221 +---drivers/net/wireless/libertas/rx.c| 122 +--drivers/net/wireless/libertas/scan.c| 1353 ------------------drivers/net/wireless/libertas/scan.h| 63 -drivers/net/wireless/libertas/tx.c| 12 +-drivers/net/wireless/libertas/wext.c| 2348 -------------------------------drivers/net/wireless/libertas/wext.h| 17 -18 files changed, 1977 insertions(+), 6685 deletions(-)delete mode 100644
drivers/net/wireless/libertas/assoc.cdelete mode 100644drivers/net/wireless/libertas/assoc.hdelete mode 100644drivers/net/wireless/libertas/scan.cdelete mode 100644drivers/net/wireless/libertas/scan.hdelete mode 100644drivers/net/wireless/libertas/wext.cdelete mode 100644drivers/net/wireless/libertas/wext.hdrivers/net/wireless/libertas/Makefile +0
-1@@ -1,4 +1,3 @@ -libertas-y += assoc.olibertas-y += cfg.o
libertas-y += cmd.o
libertas-y += cmdresp.odrivers/net/wireless/libertas/Makefile +0
-0@@ -6,9 +5,7 @@ libertas-y += debugfs.olibertas-y += ethtool.o
libertas-y += main.o
libertas-y += rx.o
-libertas-y += scan.o
libertas-y += tx.o
-libertas-y += wext.o
libertas-$(CONFIG_LIBERTAS_MESH) += mesh.ousb8xxx-objs += if_usb.o
drivers/net/wireless/libertas/assoc.c deleted +0
-2243@@ -1,2243 +0,0 @@ -/* Copyright (C) 2006, Red Hat, Inc. */ - -#include <linux/types.h> -#include <linux/etherdevice.h> -#include <linux/ieee80211.h> -#include <linux/if_arp.h> -#include <net/lib80211.h> - -#include "assoc.h" -#include "decl.h" -#include "host.h" -#include "scan.h" -#include "cmd.h" - -static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -/* The firmware needs the following bits masked out of the beacon-derived -* capability field when associating/joining to a BSS: -* 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) -*/ -#define CAPINFO_MASK (~(0xda00)) - -/** -* 802.11b/g supported bitrates (in 500Kb/s units) -*/ -u8 lbs_bg_rates[MAX_RATES ] = - { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, -0x00 ,0x00 }; - - -/** -* @brief This function finds common rates between rates and card rates. -* -* It will fill common rates in rates as output if found. -* -* NOTE: Setting the MSB of the basic rates need to be taken -* care, either before or after calling this function -* -* @param priv A pointer to struct lbs_private structure -* @param rates the buffer which keeps input and output -* @param rates_size the size of rates buffer; new size of buffer on return, -* which will be less than or equal to original rates_size -* -* @return 0 on success, or -1 on error -*/ -static int get_common_rates (struct lbs_private *priv, - u8 *rates, - u16 *rates_size) -{ - int i, j; - u8 intersection[MAX_RATES]; - u16 intersection_size; - u16 num_rates = 0; - - intersection_size = min_t(u16, *rates_size, ARRAY_SIZE(intersection)); - - /* Allow each rate from 'rates' that is supported by the hardware */ - for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && lbs_bg_rates[i]; i++) { - for (j = 0; j < intersection_size && rates[j]; j++) { - if (rates[j] == lbs_bg_rates[i]) - intersection[num_rates++] = rates[j]; - } - } - - lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size); - lbs_deb_hex(LBS_DEB_JOIN, "card rates ", lbs_bg_rates, - ARRAY_SIZE(lbs_bg_rates)); - lbs_deb_hex(LBS_DEB_JOIN, "common rates", intersection, num_rates); - lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); - - if (!priv->enablehwauto) { - for (i = 0; i < num_rates; i++) { - if (intersection[i] == priv->cur_rate) - goto done; - } - lbs_pr_alert("Previously set fixed data rate %#x isn't " - "compatible with the network.\n", priv->cur_rate); - return -1; - } - -done: - memset(rates, 0, *rates_size); - *rates_size = num_rates; - memcpy(rates, intersection, num_rates); - return 0; -} - - -/** -* @brief Sets the MSB on basic rates as the firmware requires -* -* Scan through an array and set the MSB for basic data rates. -* -* @param rates buffer of data rates -* @param len size of buffer -*/ -static void lbs_set_basic_rate_flags (u8 *rates,size_t len) -{ - int i; - - for (i = 0; i < len; i++) { - if (rates[i] == 0x02 || rates[i] == 0x04 || - rates[i] == 0x0b || rates[i] == 0x16) - rates[i] |= 0x80; - } -} - - -static u8 iw_auth_to_ieee_auth (u8 auth) -{ - if (auth == IW_AUTH_ALG_OPEN_SYSTEM) - return 0x00; - else if (auth == IW_AUTH_ALG_SHARED_KEY) - return 0x01; - else if (auth == IW_AUTH_ALG_LEAP) - return 0x80; - - lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth); - return 0; -} - -/** -* @brief This function prepares the authenticate command. AUTHENTICATE only -* sets the authentication suite for future associations, as the firmware -* handles authentication internally during the ASSOCIATE command. -* -* @param priv A pointer to struct lbs_private structure -* @param bssid The peer BSSID with which to authenticate -* @param auth The authentication mode to use (from wireless.h) -* -* @return 0 or -1 -*/ -static int lbs_set_authentication (struct lbs_private *priv,u8 bssid[6 ],u8 auth) -{ - struct cmd_ds_802_11_authenticate cmd; - int ret = -1; - - lbs_deb_enter(LBS_DEB_JOIN); - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - memcpy(cmd.bssid, bssid, ETH_ALEN); - - cmd.authtype = iw_auth_to_ieee_auth(auth); - - lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype); - - ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); - - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - - -int lbs_cmd_802_11_set_wep (struct lbs_private *priv,uint16_t cmd_action, - struct assoc_request *assoc) -{ - struct cmd_ds_802_11_set_wep cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - cmd.action = cpu_to_le16(cmd_action); - - if (cmd_action == CMD_ACT_ADD) { - int i; - - /* default tx key index */ - cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx & - CMD_WEP_KEY_INDEX_MASK); - - /* Copy key types and material to host command structure */ - for (i = 0; i < 4; i++) { - struct enc_key *pkey = &assoc->wep_keys[i]; - - switch (pkey->len) { - case KEY_LEN_WEP_40: - cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; - memmove(cmd.keymaterial[i], pkey->key, pkey->len); - lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i); - break; - case KEY_LEN_WEP_104: - cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; - memmove(cmd.keymaterial[i], pkey->key, pkey->len); - lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i); - break; - case 0: - break; - default: - lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n", - i, pkey->len); - ret = -1; - goto done; - break; - } - } - } else if (cmd_action == CMD_ACT_REMOVE) { - /* ACT_REMOVE clears _all_ WEP keys */ - - /* default tx key index */ - cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx & - CMD_WEP_KEY_INDEX_MASK); - lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx); - } - - ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); -done: - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -int lbs_cmd_802_11_enable_rsn (struct lbs_private *priv,uint16_t cmd_action, - uint16_t *enable) -{ - struct cmd_ds_802_11_enable_rsn cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(cmd_action); - - if (cmd_action == CMD_ACT_GET) - cmd.enable = 0; - else { - if (*enable) - cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); - else - cmd.enable = cpu_to_le16(CMD_DISABLE_RSN); - lbs_deb_cmd("ENABLE_RSN: %d\n", *enable); - } - - ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); - if (!ret && cmd_action == CMD_ACT_GET) - *enable = le16_to_cpu(cmd.enable); - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -static void set_one_wpa_key (struct MrvlIEtype_keyParamSet *keyparam, - struct enc_key *key) -{ - lbs_deb_enter(LBS_DEB_CMD); - - if (key->flags & KEY_INFO_WPA_ENABLED) - keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); - if (key->flags & KEY_INFO_WPA_UNICAST) - keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); - if (key->flags & KEY_INFO_WPA_MCAST) - keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); - - keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - keyparam->keytypeid = cpu_to_le16(key->type); - keyparam->keylen = cpu_to_le16(key->len); - memcpy(keyparam->key, key->key, key->len); - - /* Length field doesn't include the {type,length} header */ - keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); - lbs_deb_leave(LBS_DEB_CMD); -} - -int lbs_cmd_802_11_key_material (struct lbs_private *priv,uint16_t cmd_action, - struct assoc_request *assoc) -{ - struct cmd_ds_802_11_key_material cmd; - int ret = 0; - int index = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd.action = cpu_to_le16(cmd_action); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - if (cmd_action == CMD_ACT_GET) { - cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2); - } else { - memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); - - if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { - set_one_wpa_key(&cmd.keyParamSet[index], - &assoc->wpa_unicast_key); - index++; - } - - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { - set_one_wpa_key(&cmd.keyParamSet[index], - &assoc->wpa_mcast_key); - index++; - } - - /* The common header and as many keys as we included */ - cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), - keyParamSet[index])); - } - ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); - /* Copy the returned key to driver private data */ - if (!ret && cmd_action == CMD_ACT_GET) { - void *buf_ptr = cmd.keyParamSet; - void *resp_end = &(&cmd)[1]; - - while (buf_ptr < resp_end) { - struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; - struct enc_key *key; - uint16_t param_set_len = le16_to_cpu(keyparam->length); - uint16_t key_len = le16_to_cpu(keyparam->keylen); - uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); - uint16_t key_type = le16_to_cpu(keyparam->keytypeid); - void *end; - - end = (void *)keyparam + sizeof(keyparam->type) - + sizeof(keyparam->length) + param_set_len; - - /* Make sure we don't access past the end of the IEs */ - if (end > resp_end) - break; - - if (key_flags & KEY_INFO_WPA_UNICAST) - key = &priv->wpa_unicast_key; - else if (key_flags & KEY_INFO_WPA_MCAST) - key = &priv->wpa_mcast_key; - else - break; - - /* Copy returned key into driver */ - memset(key, 0, sizeof(struct enc_key)); - if (key_len > sizeof(key->key)) - break; - key->type = key_type; - key->flags = key_flags; - key->len = key_len; - memcpy(key->key, keyparam->key, key->len); - - buf_ptr = end + 1; - } - } - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -static __le16 lbs_rate_to_fw_bitmap (int rate,int lower_rates_ok) -{ -/* Bit Rate -* 15:13 Reserved -* 12 54 Mbps -* 11 48 Mbps -* 10 36 Mbps -* 9 24 Mbps -* 8 18 Mbps -* 7 12 Mbps -* 6 9 Mbps -* 5 6 Mbps -* 4 Reserved -* 3 11 Mbps -* 2 5.5 Mbps -* 1 2 Mbps -* 0 1 Mbps -**/ - - uint16_t ratemask; - int i = lbs_data_rate_to_fw_index(rate); - if (lower_rates_ok) - ratemask = (0x1fef >> (12 - i)); - else - ratemask = (1 << i); - return cpu_to_le16(ratemask); -} - -int lbs_cmd_802_11_rate_adapt_rateset (struct lbs_private *priv, - uint16_t cmd_action) -{ - struct cmd_ds_802_11_rate_adapt_rateset cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - if (!priv->cur_rate && !priv->enablehwauto) - return -EINVAL; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - cmd.action = cpu_to_le16(cmd_action); - cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); - cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); - ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); - if (!ret && cmd_action == CMD_ACT_GET) - priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** -* @brief Set the data rate -* -* @param priv A pointer to struct lbs_private structure -* @param rate The desired data rate, or 0 to clear a locked rate -* -* @return 0 on success, error on failure -*/ -int lbs_set_data_rate (struct lbs_private *priv,u8 rate) -{ - struct cmd_ds_802_11_data_rate cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - if (rate > 0) { - cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE); - cmd.rates[0] = lbs_data_rate_to_fw_index(rate); - if (cmd.rates[0] == 0) { - lbs_deb_cmd("DATA_RATE: invalid requested rate of" - " 0x%02X\n", rate); - ret = 0; - goto out; - } - lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]); - } else { - cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO); - lbs_deb_cmd("DATA_RATE: setting auto\n"); - } - - ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); - if (ret) - goto out; - - lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd)); - - /* FIXME: get actual rates FW can do if this command actually returns - * all data rates supported. - */ - priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]); - lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate); - -out: - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - - -int lbs_cmd_802_11_rssi (struct lbs_private *priv, - struct cmd_ds_command *cmd) -{ - - lbs_deb_enter(LBS_DEB_CMD); - cmd->command = cpu_to_le16(CMD_802_11_RSSI); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + - sizeof(struct cmd_header)); - cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); - - /* reset Beacon SNR/NF/RSSI values */ - priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; - priv->SNR[TYPE_BEACON][TYPE_AVG] = 0; - priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0; - priv->NF[TYPE_BEACON][TYPE_AVG] = 0; - priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0; - priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0; - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - -int lbs_ret_802_11_rssi (struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp; - - lbs_deb_enter(LBS_DEB_CMD); - - /* store the non average value */ - priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR); - priv->NF[TYPE_BEACON][TYPE_NOAVG] = - get_unaligned_le16(&rssirsp->noisefloor); - - priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR); - priv->NF[TYPE_BEACON][TYPE_AVG] = - get_unaligned_le16(&rssirsp->avgnoisefloor); - - priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = - CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], - priv->NF[TYPE_BEACON][TYPE_NOAVG]); - - priv->RSSI[TYPE_BEACON][TYPE_AVG] = - CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE, - priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE); - - lbs_deb_cmd("RSSI: beacon %d, avg %d\n", - priv->RSSI[TYPE_BEACON][TYPE_NOAVG], - priv->RSSI[TYPE_BEACON][TYPE_AVG]); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - - -int lbs_cmd_bcn_ctrl (struct lbs_private *priv, - struct cmd_ds_command *cmd, - u16 cmd_action) -{ - struct cmd_ds_802_11_beacon_control - *bcn_ctrl = &cmd->params.bcn_ctrl; - - lbs_deb_enter(LBS_DEB_CMD); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control) - + sizeof(struct cmd_header)); - cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL); - - bcn_ctrl->action = cpu_to_le16(cmd_action); - bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable); - bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - -int lbs_ret_802_11_bcn_ctrl (struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - struct cmd_ds_802_11_beacon_control *bcn_ctrl = - &resp->params.bcn_ctrl; - - lbs_deb_enter(LBS_DEB_CMD); - - if (bcn_ctrl->action == CMD_ACT_GET) { - priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable); - priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period); - } - - lbs_deb_enter(LBS_DEB_CMD); - return 0; -} - - - -static int lbs_assoc_post (struct lbs_private *priv, - struct cmd_ds_802_11_associate_response *resp) -{ - int ret = 0; - union iwreq_data wrqu; - struct bss_descriptor *bss; - u16 status_code; - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (!priv->in_progress_assoc_req) { - lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - /* - * Older FW versions map the IEEE 802.11 Status Code in the association - * response to the following values returned in resp->statuscode: - * - * IEEE Status Code Marvell Status Code - * 0 -> 0x0000 ASSOC_RESULT_SUCCESS - * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * others -> 0x0003 ASSOC_RESULT_REFUSED - * - * Other response codes: - * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) - * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for - * association response from the AP) - */ - - status_code = le16_to_cpu(resp->statuscode); - if (priv->fwrelease < 0x09000000) { - switch (status_code) { - case 0x00: - break; - case 0x01: - lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); - break; - case 0x02: - lbs_deb_assoc("ASSOC_RESP: internal timer " - "expired while waiting for the AP\n"); - break; - case 0x03: - lbs_deb_assoc("ASSOC_RESP: association " - "refused by AP\n"); - break; - case 0x04: - lbs_deb_assoc("ASSOC_RESP: authentication " - "refused by AP\n"); - break; - default: - lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " - " unknown\n", status_code); - break; - } - } else { - /* v9+ returns the AP's association response */ - lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code); - } - - if (status_code) { - lbs_mac_event_disconnected(priv); - ret = -1; - goto done; - } - - lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", - (void *) (resp + sizeof (resp->hdr)), - le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr)); - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - /* Update current SSID and BSSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN); - priv->curbssparams.ssid_len = bss->ssid_len; - memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; - priv->NF[TYPE_RXPD][TYPE_AVG] = 0; - - memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); - memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); - priv->nextSNRNF = 0; - priv->numSNRNF = 0; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** -* @brief This function prepares an association-class command. -* -* @param priv A pointer to struct lbs_private structure -* @param assoc_req The association request describing the BSS to associate -* or reassociate with -* @param command The actual command, either CMD_802_11_ASSOCIATE or -* CMD_802_11_REASSOCIATE -* -* @return 0 or -1 -*/ -static int lbs_associate (struct lbs_private *priv, - struct assoc_request *assoc_req, - u16 command) -{ - struct cmd_ds_802_11_associate cmd; - int ret = 0; - struct bss_descriptor *bss = &assoc_req->bss; - u8 *pos = &(cmd.iebuf[0]); - u16 tmpcap, tmplen, tmpauth; - struct mrvl_ie_ssid_param_set *ssid; - struct mrvl_ie_ds_param_set *ds; - struct mrvl_ie_cf_param_set *cf; - struct mrvl_ie_rates_param_set *rates; - struct mrvl_ie_rsn_param_set *rsn; - struct mrvl_ie_auth_type *auth; - - lbs_deb_enter(LBS_DEB_ASSOC); - - BUG_ON((command != CMD_802_11_ASSOCIATE) && - (command != CMD_802_11_REASSOCIATE)); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.command = cpu_to_le16(command); - - /* Fill in static fields */ - memcpy(cmd.bssid, bss->bssid, ETH_ALEN); - cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); - - /* Capability info */ - tmpcap = (bss->capability & CAPINFO_MASK); - if (bss->mode == IW_MODE_INFRA) - tmpcap |= WLAN_CAPABILITY_ESS; - cmd.capability = cpu_to_le16(tmpcap); - lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); - - /* SSID */ - ssid = (struct mrvl_ie_ssid_param_set *) pos; - ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); - tmplen = bss->ssid_len; - ssid->header.len = cpu_to_le16(tmplen); - memcpy(ssid->ssid, bss->ssid, tmplen); - pos += sizeof(ssid->header) + tmplen; - - ds = (struct mrvl_ie_ds_param_set *) pos; - ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); - ds->header.len = cpu_to_le16(1); - ds->channel = bss->phy.ds.channel; - pos += sizeof(ds->header) + 1; - - cf = (struct mrvl_ie_cf_param_set *) pos; - cf->header.type = cpu_to_le16(TLV_TYPE_CF); - tmplen = sizeof(*cf) - sizeof (cf->header); - cf->header.len = cpu_to_le16(tmplen); - /* IE payload should be zeroed, firmware fills it in for us */ - pos += sizeof(*cf); - - rates = (struct mrvl_ie_rates_param_set *) pos; - rates->header.type = cpu_to_le16(TLV_TYPE_RATES); - tmplen = min_t(u16, ARRAY_SIZE(bss->rates), MAX_RATES); - memcpy(&rates->rates, &bss->rates, tmplen); - if (get_common_rates(priv, rates->rates, &tmplen)) { - ret = -1; - goto done; - } - pos += sizeof(rates->header) + tmplen; - rates->header.len = cpu_to_le16(tmplen); - lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); - - /* Copy the infra. association rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(rates->rates, tmplen); - - /* Firmware v9+ indicate authentication suites as a TLV */ - if (priv->fwrelease >= 0x09000000) { - auth = (struct mrvl_ie_auth_type *) pos; - auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); - auth->header.len = cpu_to_le16(2); - tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode); - auth->auth = cpu_to_le16(tmpauth); - pos += sizeof(auth->header) + 2; - - lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", - bss->bssid, priv->secinfo.auth_mode); - } - - /* WPA/WPA2 IEs */ - if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { - rsn = (struct mrvl_ie_rsn_param_set *) pos; - /* WPA_IE or WPA2_IE */ - rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); - tmplen = (u16) assoc_req->wpa_ie[1]; - rsn->header.len = cpu_to_le16(tmplen); - memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); - lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn, - sizeof(rsn->header) + tmplen); - pos += sizeof(rsn->header) + tmplen; - } - - cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) + - (u16)(pos - (u8 *) &cmd.iebuf)); - - /* update curbssparams */ - priv->channel = bss->phy.ds.channel; - - ret = lbs_cmd_with_response(priv, command, &cmd); - if (ret == 0) { - ret = lbs_assoc_post(priv, - (struct cmd_ds_802_11_associate_response *) &cmd); - } - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** -* @brief Associate to a specific BSS discovered in a scan -* -* @param priv A pointer to struct lbs_private structure -* @param assoc_req The association request describing the BSS to associate with -* -* @return 0-success, otherwise fail -*/ -static int lbs_try_associate (struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - int ret; - u8 preamble = RADIO_PREAMBLE_LONG; - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* FW v9 and higher indicate authentication suites as a TLV in the - * association command, not as a separate authentication command. - */ - if (priv->fwrelease < 0x09000000) { - ret = lbs_set_authentication(priv, assoc_req->bss.bssid, - priv->secinfo.auth_mode); - if (ret) - goto out; - } - - /* Use short preamble only when both the BSS and firmware support it */ - if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - preamble = RADIO_PREAMBLE_SHORT; - - ret = lbs_set_radio(priv, preamble, 1); - if (ret) - goto out; - - ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE); - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static int lbs_adhoc_post (struct lbs_private *priv, - struct cmd_ds_802_11_ad_hoc_result *resp) -{ - int ret = 0; - u16 command = le16_to_cpu(resp->hdr.command); - u16 result = le16_to_cpu(resp->hdr.result); - union iwreq_data wrqu; - struct bss_descriptor *bss; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_JOIN); - - if (!priv->in_progress_assoc_req) { - lbs_deb_join("ADHOC_RESP: no in-progress association " - "request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - /* - * Join result code 0 --> SUCCESS - */ - if (result) { - lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); - if (priv->connect_status == LBS_CONNECTED) - lbs_mac_event_disconnected(priv); - ret = -1; - goto done; - } - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { - /* Update the created network descriptor with the new BSSID */ - memcpy(bss->bssid, resp->bssid, ETH_ALEN); - } - - /* Set the BSSID from the joined/started descriptor */ - memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - /* Set the new SSID to current SSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN); - priv->curbssparams.ssid_len = bss->ssid_len; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - - lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", - print_ssid(ssid, bss->ssid, bss->ssid_len), - priv->curbssparams.bssid, - priv->channel); - -done: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - -/** -* @brief Join an adhoc network found in a previous scan -* -* @param priv A pointer to struct lbs_private structure -* @param assoc_req The association request describing the BSS to join -* -* @return 0 on success, error on failure -*/ -static int lbs_adhoc_join (struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - struct cmd_ds_802_11_ad_hoc_join cmd; - struct bss_descriptor *bss = &assoc_req->bss; - u8 preamble = RADIO_PREAMBLE_LONG; - DECLARE_SSID_BUF(ssid); - u16 ratesize = 0; - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - lbs_deb_join("current SSID '%s', ssid length %u\n", - print_ssid(ssid, priv->curbssparams.ssid, - priv->curbssparams.ssid_len), - priv->curbssparams.ssid_len); - lbs_deb_join("requested ssid '%s', ssid length %u\n", - print_ssid(ssid, bss->ssid, bss->ssid_len), - bss->ssid_len); - - /* check if the requested SSID is already joined */ - if (priv->curbssparams.ssid_len && - !lbs_ssid_cmp(priv->curbssparams.ssid, - priv->curbssparams.ssid_len, - bss->ssid, bss->ssid_len) && - (priv->mode == IW_MODE_ADHOC) && - (priv->connect_status == LBS_CONNECTED)) { - union iwreq_data wrqu; - - lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as " - "current, not attempting to re-join"); - - /* Send the re-association event though, because the association - * request really was successful, even if just a null-op. - */ - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, - ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - goto out; - } - - /* Use short preamble only when both the BSS and firmware support it */ - if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { - lbs_deb_join("AdhocJoin: Short preamble\n"); - preamble = RADIO_PREAMBLE_SHORT; - } - - ret = lbs_set_radio(priv, preamble, 1); - if (ret) - goto out; - - lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); - lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); - - priv->adhoccreate = 0; - priv->channel = bss->channel; - - /* Build the join command */ - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - cmd.bss.type = CMD_BSS_TYPE_IBSS; - cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod); - - memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN); - memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len); - - memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set)); - - memcpy(&cmd.bss.ibss, &bss->ss.ibss, - sizeof(struct ieee_ie_ibss_param_set)); - - cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); - lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", - bss->capability, CAPINFO_MASK); - - /* information on BSSID descriptor passed to FW */ - lbs_deb_join("ADHOC_J_CMD: BSSID = %pM, SSID = '%s'\n", - cmd.bss.bssid, cmd.bss.ssid); - - /* Only v8 and below support setting these */ - if (priv->fwrelease < 0x09000000) { - /* failtimeout */ - cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); - /* probedelay */ - cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); - } - - /* Copy Data rates from the rates recorded in scan response */ - memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates)); - ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), ARRAY_SIZE (bss->rates)); - memcpy(cmd.bss.rates, bss->rates, ratesize); - if (get_common_rates(priv, cmd.bss.rates, &ratesize)) { - lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n"); - ret = -1; - goto out; - } - - /* Copy the ad-hoc creation rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(cmd.bss.rates, ratesize); - - cmd.bss.ibss.atimwindow = bss->atimwindow; - - if (assoc_req->secinfo.wep_enabled) { - u16 tmp = le16_to_cpu(cmd.bss.capability); - tmp |= WLAN_CAPABILITY_PRIVACY; - cmd.bss.capability = cpu_to_le16(tmp); - } - - if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { - __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM); - - /* wake up first */ - ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, - CMD_ACT_SET, 0, 0, - &local_ps_mode); - if (ret) { - ret = -1; - goto out; - } - } - - ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); - if (ret == 0) { - ret = lbs_adhoc_post(priv, - (struct cmd_ds_802_11_ad_hoc_result *)&cmd); - } - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** -* @brief Start an Adhoc Network -* -* @param priv A pointer to struct lbs_private structure -* @param assoc_req The association request describing the BSS to start -* -* @return 0 on success, error on failure -*/ -static int lbs_adhoc_start (struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - struct cmd_ds_802_11_ad_hoc_start cmd; - u8 preamble = RADIO_PREAMBLE_SHORT; - size_t ratesize = 0; - u16 tmpcap = 0; - int ret = 0; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_ASSOC); - - ret = lbs_set_radio(priv, preamble, 1); - if (ret) - goto out; - - /* Build the start command */ - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len); - - lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n", - print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len), - assoc_req->ssid_len); - - cmd.bsstype = CMD_BSS_TYPE_IBSS; - - if (priv->beacon_period == 0) - priv->beacon_period = MRVDRV_BEACON_INTERVAL; - cmd.beaconperiod = cpu_to_le16(priv->beacon_period); - - WARN_ON(!assoc_req->channel); - - /* set Physical parameter set */ - cmd.ds.header.id = WLAN_EID_DS_PARAMS; - cmd.ds.header.len = 1; - cmd.ds.channel = assoc_req->channel; - - /* set IBSS parameter set */ - cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS; - cmd.ibss.header.len = 2; - cmd.ibss.atimwindow = cpu_to_le16(0); - - /* set capability info */ - tmpcap = WLAN_CAPABILITY_IBSS; - if (assoc_req->secinfo.wep_enabled || - assoc_req->secinfo.WPAenabled || - assoc_req->secinfo.WPA2enabled) { - lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n"); - tmpcap |= WLAN_CAPABILITY_PRIVACY; - } else - lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n"); - - cmd.capability = cpu_to_le16(tmpcap); - - /* Only v8 and below support setting probe delay */ - if (priv->fwrelease < 0x09000000) - cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); - - ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates)); - memcpy(cmd.rates, lbs_bg_rates, ratesize); - - /* Copy the ad-hoc creating rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(cmd.rates, ratesize); - - lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n", - cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]); - - lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n", - assoc_req->channel, assoc_req->band); - - priv->adhoccreate = 1; - priv->mode = IW_MODE_ADHOC; - - ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd); - if (ret == 0) - ret = lbs_adhoc_post(priv, - (struct cmd_ds_802_11_ad_hoc_result *)&cmd); - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** -* @brief Stop and Ad-Hoc network and exit Ad-Hoc mode -* -* @param priv A pointer to struct lbs_private structure -* @return 0 on success, or an error -*/ -int lbs_adhoc_stop (struct lbs_private *priv) -{ - struct cmd_ds_802_11_ad_hoc_stop cmd; - int ret; - - lbs_deb_enter(LBS_DEB_JOIN); - - memset(&cmd, 0, sizeof (cmd)); - cmd.hdr.size = cpu_to_le16 (sizeof (cmd)); - - ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd); - - /* Clean up everything even if there was an error */ - lbs_mac_event_disconnected(priv); - - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static inline int match_bss_no_security (struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && - !secinfo->WPAenabled && !secinfo->WPA2enabled && - match_bss->wpa_ie[0] != WLAN_EID_GENERIC && - match_bss->rsn_ie[0] != WLAN_EID_RSN && - !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - else - return 0; -} - -static inline int match_bss_static_wep (struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (secinfo->wep_enabled && - !secinfo->WPAenabled && !secinfo->WPA2enabled && - (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - else - return 0; -} - -static inline int match_bss_wpa (struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && secinfo->WPAenabled && - (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ - ) - return 1; - else - return 0; -} - -static inline int match_bss_wpa2 (struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && secinfo->WPA2enabled && - (match_bss->rsn_ie[0] == WLAN_EID_RSN) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ - ) - return 1; - else - return 0; -} - -static inline int match_bss_dynamic_wep (struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && - !secinfo->WPAenabled && !secinfo->WPA2enabled && - (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) && - (match_bss->rsn_ie[0] != WLAN_EID_RSN) && - (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - else - return 0; -} - -/** -* @brief Check if a scanned network compatible with the driver settings -* -* WEP WPA WPA2 ad-hoc encrypt Network -* enabled enabled enabled AES mode privacy WPA WPA2 Compatible -* 0 0 0 0 NONE 0 0 0 yes No security -* 1 0 0 0 NONE 1 0 0 yes Static WEP -* 0 1 0 0 x 1x 1 x yes WPA -* 0 0 1 0 x 1x x 1 yes WPA2 -* 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES -* 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP -* -* -* @param priv A pointer to struct lbs_private -* @param index Index in scantable to check against current driver settings -* @param mode Network mode: Infrastructure or IBSS -* -* @return Index in scantable, or error code if negative -*/ -static int is_network_compatible (struct lbs_private *priv, - struct bss_descriptor *bss, uint8_t mode) -{ - int matched = 0; - - lbs_deb_enter(LBS_DEB_SCAN); - - if (bss->mode != mode) - goto done; - - matched = match_bss_no_security(&priv->secinfo, bss); - if (matched) - goto done; - matched = match_bss_static_wep(&priv->secinfo, bss); - if (matched) - goto done; - matched = match_bss_wpa(&priv->secinfo, bss); - if (matched) { - lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " - "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - goto done; - } - matched = match_bss_wpa2(&priv->secinfo, bss); - if (matched) { - lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " - "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - goto done; - } - matched = match_bss_dynamic_wep(&priv->secinfo, bss); - if (matched) { - lbs_deb_scan("is_network_compatible() dynamic WEP: " - "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", - bss->wpa_ie[0], bss->rsn_ie[0], - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - goto done; - } - - /* bss security settings don't match those configured on card */ - lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", - bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - -done: - lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); - return matched; -} - -/** -* @brief This function finds a specific compatible BSSID in the scan list -* -* Used in association code -* -* @param priv A pointer to struct lbs_private -* @param bssid BSSID to find in the scan list -* @param mode Network mode: Infrastructure or IBSS -* -* @return index in BSSID list, or error return code (< 0) -*/ -static struct bss_descriptor *lbs_find_bssid_in_list (struct lbs_private *priv, - uint8_t *bssid, uint8_t mode) -{ - struct bss_descriptor *iter_bss; - struct bss_descriptor *found_bss = NULL; - - lbs_deb_enter(LBS_DEB_SCAN); - - if (!bssid) - goto out; - - lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN); - - /* Look through the scan table for a compatible match. The loop will - * continue past a matched bssid that is not compatible in case there - * is an AP with multiple SSIDs assigned to the same BSSID - */ - mutex_lock(&priv->lock); - list_for_each_entry(iter_bss, &priv->network_list, list) { - if (compare_ether_addr(iter_bss->bssid, bssid)) - continue; /* bssid doesn't match */ - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - if (!is_network_compatible(priv, iter_bss, mode)) - break; - found_bss = iter_bss; - break; - default: - found_bss = iter_bss; - break; - } - } - mutex_unlock(&priv->lock); - -out: - lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); - return found_bss; -} - -/** -* @brief This function finds ssid in ssid list. -* -* Used in association code -* -* @param priv A pointer to struct lbs_private -* @param ssid SSID to find in the list -* @param bssid BSSID to qualify the SSID selection (if provided) -* @param mode Network mode: Infrastructure or IBSS -* -* @return index in BSSID list -*/ -static struct bss_descriptor *lbs_find_ssid_in_list (struct lbs_private *priv, - uint8_t *ssid, uint8_t ssid_len, - uint8_t *bssid, uint8_t mode, - int channel) -{ - u32 bestrssi = 0; - struct bss_descriptor *iter_bss = NULL; - struct bss_descriptor *found_bss = NULL; - struct bss_descriptor *tmp_oldest = NULL; - - lbs_deb_enter(LBS_DEB_SCAN); - - mutex_lock(&priv->lock); - - list_for_each_entry(iter_bss, &priv->network_list, list) { - if (!tmp_oldest || - (iter_bss->last_scanned < tmp_oldest->last_scanned)) - tmp_oldest = iter_bss; - - if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, - ssid, ssid_len) != 0) - continue; /* ssid doesn't match */ - if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) - continue; /* bssid doesn't match */ - if ((channel > 0) && (iter_bss->channel != channel)) - continue; /* channel doesn't match */ - - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - if (!is_network_compatible(priv, iter_bss, mode)) - break; - - if (bssid) { - /* Found requested BSSID */ - found_bss = iter_bss; - goto out; - } - - if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { - bestrssi = SCAN_RSSI(iter_bss->rssi); - found_bss = iter_bss; - } - break; - case IW_MODE_AUTO: - default: - if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { - bestrssi = SCAN_RSSI(iter_bss->rssi); - found_bss = iter_bss; - } - break; - } - } - -out: - mutex_unlock(&priv->lock); - lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); - return found_bss; -} - -static int assoc_helper_essid (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - struct bss_descriptor * bss; - int channel = -1; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* FIXME: take channel into account when picking SSIDs if a channel - * is set. - */ - - if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) - channel = assoc_req->channel; - - lbs_deb_assoc("SSID '%s' requested\n", - print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len)); - if (assoc_req->mode == IW_MODE_INFRA) { - lbs_send_specific_ssid_scan(priv, assoc_req->ssid, - assoc_req->ssid_len); - - bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, - assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); - if (bss != NULL) { - memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); - ret = lbs_try_associate(priv, assoc_req); - } else { - lbs_deb_assoc("SSID not found; cannot associate\n"); - } - } else if (assoc_req->mode == IW_MODE_ADHOC) { - /* Scan for the network, do not save previous results. Stale - * scan data will cause us to join a non-existant adhoc network - */ - lbs_send_specific_ssid_scan(priv, assoc_req->ssid, - assoc_req->ssid_len); - - /* Search for the requested SSID in the scan table */ - bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, - assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel); - if (bss != NULL) { - lbs_deb_assoc("SSID found, will join\n"); - memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); - lbs_adhoc_join(priv, assoc_req); - } else { - /* else send START command */ - lbs_deb_assoc("SSID not found, creating adhoc network\n"); - memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, - IEEE80211_MAX_SSID_LEN); - assoc_req->bss.ssid_len = assoc_req->ssid_len; - lbs_adhoc_start(priv, assoc_req); - } - } - - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_bssid (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - struct bss_descriptor * bss; - - lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %pM", assoc_req->bssid); - - /* Search for index position in list for requested MAC */ - bss = lbs_find_bssid_in_list(priv, assoc_req->bssid, - assoc_req->mode); - if (bss == NULL) { - lbs_deb_assoc("ASSOC: WAP: BSSID %pM not found, " - "cannot associate.\n", assoc_req->bssid); - goto out; - } - - memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); - if (assoc_req->mode == IW_MODE_INFRA) { - ret = lbs_try_associate(priv, assoc_req); - lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n", - ret); - } else if (assoc_req->mode == IW_MODE_ADHOC) { - lbs_adhoc_join(priv, assoc_req); - } - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_associate (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0, done = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* If we're given and 'any' BSSID, try associating based on SSID */ - - if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - if (compare_ether_addr(bssid_any, assoc_req->bssid) && - compare_ether_addr(bssid_off, assoc_req->bssid)) { - ret = assoc_helper_bssid(priv, assoc_req); - done = 1; - } - } - - if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - ret = assoc_helper_essid(priv, assoc_req); - } - - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_mode (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (assoc_req->mode == priv->mode) - goto done; - - if (assoc_req->mode == IW_MODE_INFRA) { - if (priv->psstate != PS_STATE_FULL_POWER) - lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); - priv->psmode = LBS802_11POWERMODECAM; - } - - priv->mode = assoc_req->mode; - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, - assoc_req->mode == IW_MODE_ADHOC ? 2 : 1); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static int assoc_helper_channel (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - ret = lbs_update_channel(priv); - if (ret) { - lbs_deb_assoc("ASSOC: channel: error getting channel.\n"); - goto done; - } - - if (assoc_req->channel == priv->channel) - goto done; - - if (priv->mesh_dev) { - /* Change mesh channel first; 21.p21 firmware won't let - you change channel otherwise (even though it'll return - an error to this */ - lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, - assoc_req->channel); - } - - lbs_deb_assoc("ASSOC: channel: %d -> %d\n", - priv->channel, assoc_req->channel); - - ret = lbs_set_channel(priv, assoc_req->channel); - if (ret < 0) - lbs_deb_assoc("ASSOC: channel: error setting channel.\n"); - - /* FIXME: shouldn't need to grab the channel _again_ after setting - * it since the firmware is supposed to return the new channel, but - * whatever... */ - ret = lbs_update_channel(priv); - if (ret) { - lbs_deb_assoc("ASSOC: channel: error getting channel.\n"); - goto done; - } - - if (assoc_req->channel != priv->channel) { - lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n", - assoc_req->channel); - goto restore_mesh; - } - - if (assoc_req->secinfo.wep_enabled && - (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len || - assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) { - /* Make sure WEP keys are re-sent to firmware */ - set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); - } - - /* Must restart/rejoin adhoc networks after channel change */ - set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); - - restore_mesh: - if (priv->mesh_dev) - lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, - priv->channel); - - done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_wep_keys (struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - int i; - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* Set or remove WEP keys */ - if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len || - assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len) - ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req); - else - ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req); - - if (ret) - goto out; - - /* enable/disable the MAC's WEP packet filter */ - if (assoc_req->secinfo.wep_enabled) - priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE; - else - priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE; - - lbs_set_mac_control(priv); - - mutex_lock(&priv->lock); - - /* Copy WEP keys into priv wep key fields */ - for (i = 0; i < 4; i++) { - memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i], - sizeof(struct enc_key)); - } - priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx; - - mutex_unlock(&priv->lock); - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static int assoc_helper_secinfo (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - uint16_t do_wpa; - uint16_t rsn = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - memcpy(&priv->secinfo, &assoc_req->secinfo, - sizeof(struct lbs_802_11_security)); - - lbs_set_mac_control(priv); - - /* If RSN is already enabled, don't try to enable it again, since - * ENABLE_RSN resets internal state machines and will clobber the - * 4-way WPA handshake. - */ - - /* Get RSN enabled/disabled */ - ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn); - if (ret) { - lbs_deb_assoc("Failed to get RSN status: %d\n", ret); - goto out; - } - - /* Don't re-enable RSN if it's already enabled */ - do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled; - if (do_wpa == rsn) - goto out; - - /* Set RSN enabled/disabled */ - ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa); - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_wpa_keys (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - unsigned int flags = assoc_req->flags; - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* Work around older firmware bug where WPA unicast and multicast - * keys must be set independently. Seen in SDIO parts with firmware - * version 5.0.11p0. - */ - - if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); - ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); - assoc_req->flags = flags; - } - - if (ret) - goto out; - - memcpy(&priv->wpa_unicast_key, &assoc_req->wpa_unicast_key, - sizeof(struct enc_key)); - - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { - clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); - - ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); - assoc_req->flags = flags; - - memcpy(&priv->wpa_mcast_key, &assoc_req->wpa_mcast_key, - sizeof(struct enc_key)); - } - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_wpa_ie (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { - memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len); - priv->wpa_ie_len = assoc_req->wpa_ie_len; - } else { - memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN); - priv->wpa_ie_len = 0; - } - - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int should_deauth_infrastructure (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - - if (priv->connect_status != LBS_CONNECTED) - return 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - lbs_deb_assoc("Deauthenticating due to new SSID\n"); - ret = 1; - goto out; - } - - if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { - if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) { - lbs_deb_assoc("Deauthenticating due to new security\n"); - ret = 1; - goto out; - } - } - - if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - lbs_deb_assoc("Deauthenticating due to new BSSID\n"); - ret = 1; - goto out; - } - - if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { - lbs_deb_assoc("Deauthenticating due to channel switch\n"); - ret = 1; - goto out; - } - - /* FIXME: deal with 'auto' mode somehow */ - if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { - if (assoc_req->mode != IW_MODE_INFRA) { - lbs_deb_assoc("Deauthenticating due to leaving " - "infra mode\n"); - ret = 1; - goto out; - } - } - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int should_stop_adhoc (struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - lbs_deb_enter(LBS_DEB_ASSOC); - - if (priv->connect_status != LBS_CONNECTED) - return 0; - - if (lbs_ssid_cmp(priv->curbssparams.ssid, - priv->curbssparams.ssid_len, - assoc_req->ssid, assoc_req->ssid_len) != 0) - return 1; - - /* FIXME: deal with 'auto' mode somehow */ - if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { - if (assoc_req->mode != IW_MODE_ADHOC) - return 1; - } - - if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { - if (assoc_req->channel != priv->channel) - return 1; - } - - lbs_deb_leave(LBS_DEB_ASSOC); - return 0; -} - - -/** -* @brief This function finds the best SSID in the Scan List -* -* Search the scan table for the best SSID that also matches the current -* adapter network preference (infrastructure or adhoc) -* -* @param priv A pointer to struct lbs_private -* -* @return index in BSSID list -*/ -static struct bss_descriptor *lbs_find_best_ssid_in_list ( - struct lbs_private *priv, uint8_t mode) -{ - uint8_t bestrssi = 0; - struct bss_descriptor *iter_bss; - struct bss_descriptor *best_bss = NULL; - - lbs_deb_enter(LBS_DEB_SCAN); - - mutex_lock(&priv->lock); - - list_for_each_entry(iter_bss, &priv->network_list, list) { - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - if (!is_network_compatible(priv, iter_bss, mode)) - break; - if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) - break; - bestrssi = SCAN_RSSI(iter_bss->rssi); - best_bss = iter_bss; - break; - case IW_MODE_AUTO: - default: - if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) - break; - bestrssi = SCAN_RSSI(iter_bss->rssi); - best_bss = iter_bss; - break; - } - } - - mutex_unlock(&priv->lock); - lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss); - return best_bss; -} - -/** -* @brief Find the best AP -* -* Used from association worker. -* -* @param priv A pointer to struct lbs_private structure -* @param pSSID A pointer to AP's ssid -* -* @return 0--success, otherwise--fail -*/ -static int lbs_find_best_network_ssid (struct lbs_private *priv, - uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode, - uint8_t *out_mode) -{ - int ret = -1; - struct bss_descriptor *found; - - lbs_deb_enter(LBS_DEB_SCAN); - - priv->scan_ssid_len = 0; - lbs_scan_networks(priv, 1); - if (priv->surpriseremoved) - goto out; - - found = lbs_find_best_ssid_in_list(priv, preferred_mode); - if (found && (found->ssid_len > 0)) { - memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN); - *out_ssid_len = found->ssid_len; - *out_mode = found->mode; - ret = 0; - } - -out: - lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); - return ret; -} - - -void lbs_association_worker (struct work_struct *work) -{ - struct lbs_private *priv = container_of(work, struct lbs_private, - assoc_work.work); - struct assoc_request * assoc_req = NULL; - int ret = 0; - int find_any_ssid = 0; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_ASSOC); - - mutex_lock(&priv->lock); - assoc_req = priv->pending_assoc_req; - priv->pending_assoc_req = NULL; - priv->in_progress_assoc_req = assoc_req; - mutex_unlock(&priv->lock); - - if (!assoc_req) - goto done; - - lbs_deb_assoc( - "Association Request:\n" - " flags: 0x%08lx\n" - " SSID: '%s'\n" - " chann: %d\n" - " band: %d\n" - " mode: %d\n" - " BSSID: %pM\n" - " secinfo: %s%s%s\n" - " auth_mode: %d\n", - assoc_req->flags, - print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len), - assoc_req->channel, assoc_req->band, assoc_req->mode, - assoc_req->bssid, - assoc_req->secinfo.WPAenabled ? " WPA" : "", - assoc_req->secinfo.WPA2enabled ? " WPA2" : "", - assoc_req->secinfo.wep_enabled ? " WEP" : "", - assoc_req->secinfo.auth_mode); - - /* If 'any' SSID was specified, find an SSID to associate with */ - if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) && - !assoc_req->ssid_len) - find_any_ssid = 1; - - /* But don't use 'any' SSID if there's a valid locked BSSID to use */ - if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - if (compare_ether_addr(assoc_req->bssid, bssid_any) && - compare_ether_addr(assoc_req->bssid, bssid_off)) - find_any_ssid = 0; - } - - if (find_any_ssid) { - u8 new_mode = assoc_req->mode; - - ret = lbs_find_best_network_ssid(priv, assoc_req->ssid, - &assoc_req->ssid_len, assoc_req->mode, &new_mode); - if (ret) { - lbs_deb_assoc("Could not find best network\n"); - ret = -ENETUNREACH; - goto out; - } - - /* Ensure we switch to the mode of the AP */ - if (assoc_req->mode == IW_MODE_AUTO) { - set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); - assoc_req->mode = new_mode; - } - } - - /* - * Check if the attributes being changing require deauthentication - * from the currently associated infrastructure access point. - */ - if (priv->mode == IW_MODE_INFRA) { - if (should_deauth_infrastructure(priv, assoc_req)) { - ret = lbs_cmd_80211_deauthenticate(priv, - priv->curbssparams.bssid, - WLAN_REASON_DEAUTH_LEAVING); - if (ret) { - lbs_deb_assoc("Deauthentication due to new " - "configuration request failed: %d\n", - ret); - } - } - } else if (priv->mode == IW_MODE_ADHOC) { - if (should_stop_adhoc(priv, assoc_req)) { - ret = lbs_adhoc_stop(priv); - if (ret) { - lbs_deb_assoc("Teardown of AdHoc network due to " - "new configuration request failed: %d\n", - ret); - } - - } - } - - /* Send the various configuration bits to the firmware */ - if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { - ret = assoc_helper_mode(priv, assoc_req); - if (ret) - goto out; - } - - if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { - ret = assoc_helper_channel(priv, assoc_req); - if (ret) - goto out; - } - - if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { - ret = assoc_helper_secinfo(priv, assoc_req); - if (ret) - goto out; - } - - if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) { - ret = assoc_helper_wpa_ie(priv, assoc_req); - if (ret) - goto out; - } - - /* - * v10 FW wants WPA keys to be set/cleared before WEP key operations, - * otherwise it will fail to correctly associate to WEP networks. - * Other firmware versions don't appear to care. - */ - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) || - test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - ret = assoc_helper_wpa_keys(priv, assoc_req); - if (ret) - goto out; - } - - if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) || - test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { - ret = assoc_helper_wep_keys(priv, assoc_req); - if (ret) - goto out; - } - - - /* SSID/BSSID should be the _last_ config option set, because they - * trigger the association attempt. - */ - if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) || - test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - int success = 1; - - ret = assoc_helper_associate(priv, assoc_req); - if (ret) { - lbs_deb_assoc("ASSOC: association unsuccessful: %d\n", - ret); - success = 0; - } - - if (priv->connect_status != LBS_CONNECTED) { - lbs_deb_assoc("ASSOC: association unsuccessful, " - "not connected\n"); - success = 0; - } - - if (success) { - lbs_deb_assoc("associated to %pM\n", - priv->curbssparams.bssid); - lbs_prepare_and_send_command(priv, - CMD_802_11_RSSI, - 0, CMD_OPTION_WAITFORRSP, 0, NULL); - } else { - ret = -1; - } - } - -out: - if (ret) { - lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n", - ret); - } - - mutex_lock(&priv->lock); - priv->in_progress_assoc_req = NULL; - mutex_unlock(&priv->lock); - kfree(assoc_req); - -done: - lbs_deb_leave(LBS_DEB_ASSOC); -} - - -/* -* Caller MUST hold any necessary locks -*/ -struct assoc_request *lbs_get_association_request (struct lbs_private *priv) -{ - struct assoc_request * assoc_req; - - lbs_deb_enter(LBS_DEB_ASSOC); - if (!priv->pending_assoc_req) { - priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request), - GFP_KERNEL); - if (!priv->pending_assoc_req) { - lbs_pr_info("Not enough memory to allocate association" - " request!\n"); - return NULL; - } - } - - /* Copy current configuration attributes to the association request, - * but don't overwrite any that are already set. - */ - assoc_req = priv->pending_assoc_req; - if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - memcpy(&assoc_req->ssid, &priv->curbssparams.ssid, - IEEE80211_MAX_SSID_LEN); - assoc_req->ssid_len = priv->curbssparams.ssid_len; - } - - if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) - assoc_req->channel = priv->channel; - - if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags)) - assoc_req->band = priv->curbssparams.band; - - if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) - assoc_req->mode = priv->mode; - - if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - memcpy(&assoc_req->bssid, priv->curbssparams.bssid, - ETH_ALEN); - } - - if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) { - int i; - for (i = 0; i < 4; i++) { - memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i], - sizeof(struct enc_key)); - } - } - - if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) - assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx; - - if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { - memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key, - sizeof(struct enc_key)); - } - - if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key, - sizeof(struct enc_key)); - } - - if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { - memcpy(&assoc_req->secinfo, &priv->secinfo, - sizeof(struct lbs_802_11_security)); - } - - if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) { - memcpy(&assoc_req->wpa_ie, &priv->wpa_ie, - MAX_WPA_IE_LEN); - assoc_req->wpa_ie_len = priv->wpa_ie_len; - } - - lbs_deb_leave(LBS_DEB_ASSOC); - return assoc_req; -} - - -/** -* @brief Deauthenticate from a specific BSS -* -* @param priv A pointer to struct lbs_private structure -* @param bssid The specific BSS to deauthenticate from -* @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating -* -* @return 0 on success, error on failure -*/ -int lbs_cmd_80211_deauthenticate (struct lbs_private *priv,u8 bssid[ETH_ALEN ], - u16 reason) -{ - struct cmd_ds_802_11_deauthenticate cmd; - int ret; - - lbs_deb_enter(LBS_DEB_JOIN); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - memcpy(cmd.macaddr, &bssid[0], ETH_ALEN); - cmd.reasoncode = cpu_to_le16(reason); - - ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd); - - /* Clean up everything even if there was an error; can't assume that - * we're still authenticated to the AP after trying to deauth. - */ - lbs_mac_event_disconnected(priv); - - lbs_deb_leave(LBS_DEB_JOIN); - return ret; -} -drivers/net/wireless/libertas/assoc.h deleted +0
-155@@ -1,155 +0,0 @@ -/* Copyright (C) 2006, Red Hat, Inc. */ - -#ifndef _LBS_ASSOC_H_ -#define _LBS_ASSOC_H_ - - -#include "defs.h" -#include "host.h" - - -struct lbs_private ; - -/* -* In theory, the IE is limited to the IE length, 255, -* but in practice 64 bytes are enough. -*/ -#define MAX_WPA_IE_LEN 64 - - - -struct lbs_802_11_security { - u8 WPAenabled; - u8 WPA2enabled; - u8 wep_enabled; - u8 auth_mode; - u32 key_mgmt; -}; - -/** Current Basic Service Set State Structure */ -struct current_bss_params { - /** bssid */ - u8 bssid[ETH_ALEN]; - /** ssid */ - u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; - u8 ssid_len; - - /** band */ - u8 band; - /** channel is directly in priv->channel */ - /** zero-terminated array of supported data rates */ - u8 rates[MAX_RATES + 1]; -}; - -/** -* @brief Structure used to store information for each beacon/probe response -*/ -struct bss_descriptor { - u8 bssid[ETH_ALEN]; - - u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; - u8 ssid_len; - - u16 capability; - u32 rssi; - u32 channel; - u16 beaconperiod; - __le16 atimwindow; - - /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ - u8 mode; - - /* zero-terminated array of supported data rates */ - u8 rates[MAX_RATES + 1]; - - unsigned long last_scanned; - - union ieee_phy_param_set phy; - union ieee_ss_param_set ss; - - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - - u8 mesh; - - struct list_head list; -}; - -/** Association request -* -* Encapsulates all the options that describe a specific assocation request -* or configuration of the wireless card's radio, mode, and security settings. -*/ -struct assoc_request { -#define ASSOC_FLAG_SSID 1 -#define ASSOC_FLAG_CHANNEL 2 -#define ASSOC_FLAG_BAND 3 -#define ASSOC_FLAG_MODE 4 -#define ASSOC_FLAG_BSSID 5 -#define ASSOC_FLAG_WEP_KEYS 6 -#define ASSOC_FLAG_WEP_TX_KEYIDX 7 -#define ASSOC_FLAG_WPA_MCAST_KEY 8 -#define ASSOC_FLAG_WPA_UCAST_KEY 9 -#define ASSOC_FLAG_SECINFO 10 -#define ASSOC_FLAG_WPA_IE 11 - unsigned long flags; - - u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; - u8 ssid_len; - u8 channel; - u8 band; - u8 mode; - u8 bssid[ETH_ALEN] __attribute__ ((aligned (2))); - - /** WEP keys */ - struct enc_key wep_keys[4]; - u16 wep_tx_keyidx; - - /** WPA keys */ - struct enc_key wpa_mcast_key; - struct enc_key wpa_unicast_key; - - struct lbs_802_11_security secinfo; - - /** WPA Information Elements*/ - u8 wpa_ie[MAX_WPA_IE_LEN]; - u8 wpa_ie_len; - - /* BSS to associate with for infrastructure of Ad-Hoc join */ - struct bss_descriptor bss; -}; - - -extern u8 lbs_bg_rates[MAX_RATES ]; - -void lbs_association_worker (struct work_struct *work); -struct assoc_request *lbs_get_association_request (struct lbs_private *priv); - -int lbs_adhoc_stop (struct lbs_private *priv); - -int lbs_cmd_80211_deauthenticate (struct lbs_private *priv, - u8 bssid[ETH_ALEN], u16 reason); - -int lbs_cmd_802_11_rssi (struct lbs_private *priv, - struct cmd_ds_command *cmd); -int lbs_ret_802_11_rssi (struct lbs_private *priv, - struct cmd_ds_command *resp); - -int lbs_cmd_bcn_ctrl (struct lbs_private *priv, - struct cmd_ds_command *cmd, - u16 cmd_action); -int lbs_ret_802_11_bcn_ctrl (struct lbs_private *priv, - struct cmd_ds_command *resp); - -int lbs_cmd_802_11_set_wep (struct lbs_private *priv,uint16_t cmd_action, - struct assoc_request *assoc); - -int lbs_cmd_802_11_enable_rsn (struct lbs_private *priv,uint16_t cmd_action, - uint16_t *enable); - -int lbs_cmd_802_11_key_material (struct lbs_private *priv,uint16_t cmd_action, - struct assoc_request *assoc); - -#endif /* _LBS_ASSOC_H */ drivers/net/wireless/libertas/cfg.c +632
-19@@ -6,8 +6,11 @@* */ +#include <linux/if_arp.h> #include <net/cfg80211.h> +#include <asm/unaligned.h> +#include "decl.h" #include "cfg.h" #include "cmd.h"@@ -38,26 +41,27 @@ static struct ieee80211_channel lbs_2ghz_channels[] = { CHAN2G(14, 2484, 0), }; -#define RATETAB_ENT (_rate, _rateid, _flags) { \ - .bitrate = (_rate), \ - .hw_value = (_rateid), \ - .flags = (_flags), \ +#define RATETAB_ENT (_rate, _hw_value, _flags) { \ + .bitrate = (_rate), \ + .hw_value = (_hw_value), \ + .flags = (_flags), \ } +/* Table 6 in section 3.2.1.1 */ static struct ieee80211_rate lbs_rates[] = { - RATETAB_ENT(10, 0x1, 0), - RATETAB_ENT(20, 0x2, 0), - RATETAB_ENT(55, 0x4, 0), - RATETAB_ENT(110, 0x8, 0), - RATETAB_ENT(60, 0x10, 0), - RATETAB_ENT(90, 0x20, 0), - RATETAB_ENT(120, 0x40, 0), - RATETAB_ENT(180, 0x80, 0), - RATETAB_ENT(240, 0x100, 0), - RATETAB_ENT(360, 0x200, 0), - RATETAB_ENT(480, 0x400, 0), - RATETAB_ENT(540, 0x800, 0), + RATETAB_ENT(10, 0, 0), + RATETAB_ENT(20, 1, 0), + RATETAB_ENT(55, 2, 0), + RATETAB_ENT(110, 3, 0), + RATETAB_ENT(60, 9, 0), + RATETAB_ENT(90, 6, 0), + RATETAB_ENT(120, 7, 0), + RATETAB_ENT(180, 8, 0), + RATETAB_ENT(240, 9, 0), + RATETAB_ENT(360, 10, 0), + RATETAB_ENT(480, 11, 0), + RATETAB_ENT(540, 12, 0), }; static struct ieee80211_supported_band lbs_band_2ghz = {@@ -75,32 +79,1880 @@ static const u32 cipher_suites[] = { WLAN_CIPHER_SUITE_CCMP, }; +/* Time to stay on the channel */ +#define LBS_DWELL_PASSIVE 100 +#define LBS_DWELL_ACTIVE 40 + +/*************************************************************************** +* Misc utility functions +* +* TLVs are Marvell specific. They are very similar to IEs, they have the +* same structure: type, length, data*. The only difference: for IEs, the +* type and length are u8, but for TLVs they're __le16. +*/ + +/* +* Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1 +* in the firmware spec +*/ +static u8 lbs_auth_to_authtype (enum nl80211_auth_type auth_type) +{ + int ret = -ENOTSUPP; + + switch (auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + case NL80211_AUTHTYPE_SHARED_KEY: + ret = auth_type; + break; + case NL80211_AUTHTYPE_AUTOMATIC: + ret = NL80211_AUTHTYPE_OPEN_SYSTEM; + break; + case NL80211_AUTHTYPE_NETWORK_EAP: + ret = 0x80; + break; + default: + /* silence compiler */ + break; + } + return ret; +} + + +/* Various firmware commands need the list of supported rates, but with +the hight-bit set for basic rates */ +static int lbs_add_rates (u8 *rates) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) { + u8 rate = lbs_rates[i].bitrate / 5; + if (rate == 0x02 || rate == 0x04 || + rate == 0x0b || rate == 0x16) + rate |= 0x80; + rates[i] = rate; + } + return ARRAY_SIZE(lbs_rates); +} + + +/*************************************************************************** +* TLV utility functions +* +* TLVs are Marvell specific. They are very similar to IEs, they have the +* same structure: type, length, data*. The only difference: for IEs, the +* type and length are u8, but for TLVs they're __le16. +*/ + + +/* +* Add ssid TLV +*/ +#define LBS_MAX_SSID_TLV_SIZE \ + (sizeof(struct mrvl_ie_header) \ + + IEEE80211_MAX_SSID_LEN) + +static int lbs_add_ssid_tlv (u8 *tlv,const u8 *ssid,int ssid_len) +{ + struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv; + + /* + * TLV-ID SSID 00 00 + * length 06 00 + * ssid 4d 4e 54 45 53 54 + */ + ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); + ssid_tlv->header.len = cpu_to_le16(ssid_len); + memcpy(ssid_tlv->ssid, ssid, ssid_len); + return sizeof(ssid_tlv->header) + ssid_len; +} + + +/* +* Add channel list TLV (section 8.4.2) +* +* Actual channel data comes from priv->wdev->wiphy->channels. +*/ +#define LBS_MAX_CHANNEL_LIST_TLV_SIZE \ + (sizeof(struct mrvl_ie_header) \ + + (LBS_SCAN_BEFORE_NAP * sizeof(struct chanscanparamset))) + +static int lbs_add_channel_list_tlv (struct lbs_private *priv,u8 *tlv, + int last_channel, int active_scan) +{ + int chanscanparamsize = sizeof(struct chanscanparamset) * + (last_channel - priv->scan_channel); + + struct mrvl_ie_header *header = (void *) tlv; + + /* + * TLV-ID CHANLIST 01 01 + * length 0e 00 + * channel 00 01 00 00 00 64 00 + * radio type 00 + * channel 01 + * scan type 00 + * min scan time 00 00 + * max scan time 64 00 + * channel 2 00 02 00 00 00 64 00 + * + */ + + header->type = cpu_to_le16(TLV_TYPE_CHANLIST); + header->len = cpu_to_le16(chanscanparamsize); + tlv += sizeof(struct mrvl_ie_header); + + /* lbs_deb_scan("scan: channels %d to %d\n", priv->scan_channel, + last_channel); */ + memset(tlv, 0, chanscanparamsize); + + while (priv->scan_channel < last_channel) { + struct chanscanparamset *param = (void *) tlv; + + param->radiotype = CMD_SCAN_RADIO_TYPE_BG; + param->channumber = + priv->scan_req->channels[priv->scan_channel]->hw_value; + if (active_scan) { + param->maxscantime = cpu_to_le16(LBS_DWELL_ACTIVE); + } else { + param->chanscanmode.passivescan = 1; + param->maxscantime = cpu_to_le16(LBS_DWELL_PASSIVE); + } + tlv += sizeof(struct chanscanparamset); + priv->scan_channel++; + } + return sizeof(struct mrvl_ie_header) + chanscanparamsize; +} + + +/* +* Add rates TLV +* +* The rates are in lbs_bg_rates[], but for the 802.11b +* rates the high bit is set. We add this TLV only because +* there's a firmware which otherwise doesn't report all +* APs in range. +*/ +#define LBS_MAX_RATES_TLV_SIZE \ + (sizeof(struct mrvl_ie_header) \ + + (ARRAY_SIZE(lbs_rates))) + +/* Adds a TLV with all rates the hardware supports */ +static int lbs_add_supported_rates_tlv (u8 *tlv) +{ + size_t i; + struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv; + + /* + * TLV-ID RATES 01 00 + * length 0e 00 + * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c + */ + rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); + tlv += sizeof(rate_tlv->header); + i = lbs_add_rates(tlv); + tlv += i; + rate_tlv->header.len = cpu_to_le16(i); + return sizeof(rate_tlv->header) + i; +} + + +/* +* Adds a TLV with all rates the hardware *and* BSS supports. +*/ +static int lbs_add_common_rates_tlv (u8 *tlv,struct cfg80211_bss *bss) +{ + struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv; + const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES); + int n; + + /* + * 01 00 TLV_TYPE_RATES + * 04 00 len + * 82 84 8b 96 rates + */ + rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); + tlv += sizeof(rate_tlv->header); + + if (!rates_eid) { + /* Fallback: add basic 802.11b rates */ + *tlv++ = 0x82; + *tlv++ = 0x84; + *tlv++ = 0x8b; + *tlv++ = 0x96; + n = 4; + } else { + int hw, ap; + u8 ap_max = rates_eid[1]; + n = 0; + for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) { + u8 hw_rate = lbs_rates[hw].bitrate / 5; + for (ap = 0; ap < ap_max; ap++) { + if (hw_rate == (rates_eid[ap+2] & 0x7f)) { + *tlv++ = rates_eid[ap+2]; + n++; + } + } + } + } + + rate_tlv->header.len = cpu_to_le16(n); + return sizeof(rate_tlv->header) + n; +} + + +/* +* Add auth type TLV. +* +* This is only needed for newer firmware (V9 and up). +*/ +#define LBS_MAX_AUTH_TYPE_TLV_SIZE \ + sizeof(struct mrvl_ie_auth_type) + +static int lbs_add_auth_type_tlv (u8 *tlv,enum nl80211_auth_type auth_type) +{ + struct mrvl_ie_auth_type *auth = (void *) tlv; + + /* + * 1f 01 TLV_TYPE_AUTH_TYPE + * 01 00 len + * 01 auth type + */ + auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); + auth->header.len = cpu_to_le16(sizeof(*auth)-sizeof(auth->header)); + auth->auth = cpu_to_le16(lbs_auth_to_authtype(auth_type)); + return sizeof(*auth); +} + + +/* +* Add channel (phy ds) TLV +*/ +#define LBS_MAX_CHANNEL_TLV_SIZE \ + sizeof(struct mrvl_ie_header) + +static int lbs_add_channel_tlv (u8 *tlv,u8 channel) +{ + struct mrvl_ie_ds_param_set *ds = (void *) tlv; + + /* + * 03 00 TLV_TYPE_PHY_DS + * 01 00 len + * 06 channel + */ + ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); + ds->header.len = cpu_to_le16(sizeof(*ds)-sizeof(ds->header)); + ds->channel = channel; + return sizeof(*ds); +} + + +/* +* Add (empty) CF param TLV of the form: +*/ +#define LBS_MAX_CF_PARAM_TLV_SIZE \ + sizeof(struct mrvl_ie_header) + +static int lbs_add_cf_param_tlv (u8 *tlv) +{ + struct mrvl_ie_cf_param_set *cf = (void *)tlv; + + /* + * 04 00 TLV_TYPE_CF + * 06 00 len + * 00 cfpcnt + * 00 cfpperiod + * 00 00 cfpmaxduration + * 00 00 cfpdurationremaining + */ + cf->header.type = cpu_to_le16(TLV_TYPE_CF); + cf->header.len = cpu_to_le16(sizeof(*cf)-sizeof(cf->header)); + return sizeof(*cf); +} + +/* +* Add WPA TLV +*/ +#define LBS_MAX_WPA_TLV_SIZE \ + (sizeof(struct mrvl_ie_header) \ + + 128 /* TODO: I guessed the size */) + +static int lbs_add_wpa_tlv (u8 *tlv,const u8 *ie,u8 ie_len) +{ + size_t tlv_len; + + /* + * We need just convert an IE to an TLV. IEs use u8 for the header, + * u8 type + * u8 len + * u8[] data + * but TLVs use __le16 instead: + * __le16 type + * __le16 len + * u8[] data + */ + *tlv++ = *ie++; + *tlv++ = 0; + tlv_len = *tlv++ = *ie++; + *tlv++ = 0; + while (tlv_len--) + *tlv++ = *ie++; + /* the TLV is two bytes larger than the IE */ + return ie_len + 2; +} + + + +/*************************************************************************** +* Set Channel +*/ + static int lbs_cfg_set_channel(struct wiphy *wiphy, - struct ieee80211_channel *chan, + struct ieee80211_channel *channel, enum nl80211_channel_type channel_type) { struct lbs_private *priv = wiphy_priv(wiphy); int ret = -ENOTSUPP; - lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type); + lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", + channel->center_freq, channel_type); if (channel_type != NL80211_CHAN_NO_HT) goto out; - ret = lbs_set_channel(priv, chan->hw_value); + ret = lbs_set_channel(priv, channel->hw_value); + + out: + lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); + return ret; +} + + + +/*************************************************************************** +* Scanning +*/ + +/* +* When scanning, the firmware doesn't send a nul packet with the power-safe +* bit to the AP. So we cannot stay away from our current channel too long, +* otherwise we loose data. So take a "nap" while scanning every other +* while. +*/ +#define LBS_SCAN_BEFORE_NAP 4 + + +/* +* When the firmware reports back a scan-result, it gives us an "u8 rssi", +* which isn't really an RSSI, as it becomes larger when moving away from +* the AP. Anyway, we need to convert that into mBm. +*/ +#define LBS_SCAN_RSSI_TO_MBM (rssi) \ + ((-(int)rssi + 3)*100) + +static int lbs_ret_scan (struct lbs_private *priv,unsigned long dummy, + struct cmd_header *resp) +{ + struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; + int bsssize; + const u8 *pos; + u16 nr_sets; + const u8 *tsfdesc; + int tsfsize; + int i; + int ret = -EILSEQ; + + lbs_deb_enter(LBS_DEB_CFG80211); + + bsssize = get_unaligned_le16(&scanresp->bssdescriptsize); + nr_sets = le16_to_cpu(resp->size); + + /* + * The general layout of the scan response is described in chapter + * 5.7.1. Basically we have a common part, then any number of BSS + * descriptor sections. Finally we have section with the same number + * of TSFs. + * + * cmd_ds_802_11_scan_rsp + * cmd_header + * pos_size + * nr_sets + * bssdesc 1 + * bssid + * rssi + * timestamp + * intvl + * capa + * IEs + * bssdesc 2 + * bssdesc n + * MrvlIEtypes_TsfFimestamp_t + * TSF for BSS 1 + * TSF for BSS 2 + * TSF for BSS n + */ + + pos = scanresp->bssdesc_and_tlvbuffer; + + tsfdesc = pos + bsssize; + tsfsize = 4 + 8 * scanresp->nr_sets; + + /* Validity check: we expect a Marvell-Local TLV */ + i = get_unaligned_le16(tsfdesc); + tsfdesc += 2; + if (i != TLV_TYPE_TSFTIMESTAMP) + goto done; + /* Validity check: the TLV holds TSF values with 8 bytes each, so + * the size in the TLV must match the nr_sets value */ + i = get_unaligned_le16(tsfdesc); + tsfdesc += 2; + if (i / 8 != scanresp->nr_sets) + goto done; + + for (i = 0; i < scanresp->nr_sets; i++) { + struct wiphy *wiphy; + int freq; + struct ieee80211_channel *channel; + const u8 *bssid, *ie, *chan_no_ie = NULL, *ssid = NULL; + int ie_len, rssi, chan_no; + u16 intvl, capa; + u8 ssid_len = 0; + DECLARE_SSID_BUF(ssid_buf); + + int len = get_unaligned_le16(pos); + pos += 2; + ie_len = len; + + /* BSSID */ + bssid = pos; + pos += ETH_ALEN; + ie_len -= ETH_ALEN; + /* RSSI */ + rssi = *pos++; + ie_len -= 1; + /* Packet time stamp */ + pos += 8; + ie_len -= 8; + /* Beacon interval */ + intvl = get_unaligned_le16(pos); + pos += 2; + ie_len -= 2; + /* Capabilities */ + capa = get_unaligned_le16(pos); + pos += 2; + ie_len -= 2; + + ie = pos; + ssid = cfg80211_find_ie(WLAN_EID_SSID, ie, ie_len); + if (!ssid) + goto done; + ssid_len = ssid[1]; + ssid += 2; + + chan_no_ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ie_len); + if (!chan_no_ie) + goto done; + chan_no = chan_no_ie[2]; + + pos += ie_len; + + wiphy = priv->wdev->wiphy; + freq = ieee80211_channel_to_frequency(chan_no); + channel = ieee80211_get_channel(wiphy, freq); + + lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, " + "%d dBm\n", + bssid, capa, chan_no, + print_ssid(ssid_buf, ssid, ssid_len), + LBS_SCAN_RSSI_TO_MBM(rssi)/100); + + if (channel && + !(channel->flags & IEEE80211_CHAN_DISABLED)) + cfg80211_inform_bss(wiphy, channel, + bssid, le64_to_cpu(*(__le64 *)tsfdesc), + capa, intvl, ie, ie_len, + LBS_SCAN_RSSI_TO_MBM(rssi), + GFP_KERNEL); + + tsfdesc += 8; + } + + ret = 0; + + done: + if (priv->scan_channel < priv->scan_req->n_channels) { + /* + * We are not done yet with the current scan request. + * Since the AP doesnt know we're scanning, we delay + * the scan work in order to minimize our data loss. + */ + queue_delayed_work(priv->work_thread, &priv->scan_work, + msecs_to_jiffies(300)); + } else { + /* Mark scan done */ + cfg80211_scan_done(priv->scan_req, false); + priv->scan_channel = 0; + priv->scan_req = NULL; + } + + lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); + return ret; +} + + +/* +* Our scan command contains a TLV, consting of a SSID TLV, a channel list +* TLV and a rates TLV. Determine the maximum size of them: +*/ +#define LBS_SCAN_MAX_CMD_SIZE \ + (sizeof(struct cmd_ds_802_11_scan) \ + + LBS_MAX_SSID_TLV_SIZE \ + + LBS_MAX_CHANNEL_LIST_TLV_SIZE \ + + LBS_MAX_RATES_TLV_SIZE) + +/* +* Assumes priv->scan_req is initialized and valid +* Assumes priv->scan_channel is initialized +*/ +static void lbs_scan_worker (struct work_struct *work) +{ + struct lbs_private *priv = + container_of(work, struct lbs_private, scan_work.work); + struct cmd_ds_802_11_scan *scan_cmd;Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
out:
lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); return ret;
}drivers/net/wireless/libertas/cfg.c +1227
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
static struct
cfg80211_opslbs_cfg80211_ops= { .set_channel =lbs_cfg_set_channel,
+ .scan =lbs_cfg_scan,
+ .set_wiphy_params =lbs_cfg_set_wiphy_params,
+ .connect =lbs_cfg_connect,
+ .disconnect =lbs_cfg_disconnect,
+ .add_key =lbs_cfg_add_key,
+ .del_key =lbs_cfg_del_key,
+ .set_default_key =lbs_cfg_set_default_key,
+ .get_station =lbs_cfg_get_station,
+ .dump_survey =lbs_get_survey,
+ .change_virtual_intf =lbs_change_intf,
+ .join_ibss =lbs_join_ibss,
+ .leave_ibss =lbs_leave_ibss,
};drivers/net/wireless/libertas/cfg.c +46
-3Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
out:
lbs_deb_leave(LBS_DEB_CMD);
return ret;drivers/net/wireless/libertas/cmd.c +9
-0Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
if ((
priv->psmode!=LBS802_11POWERMODECAM) && (priv->psstate==PS_STATE_FULL_POWER) && ((priv->connect_status==LBS_CONNECTED) ||drivers/net/wireless/libertas/cmd.c +1
-0Lines of this file are not shown. View the raw message.
drivers/net/wireless/libertas/cmdresp.c +3
-25Lines of this file are not shown. View the raw message.
drivers/net/wireless/libertas/debugfs.c +1
-52Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
struct
net_device*mesh_dev; /* Virtual device */drivers/net/wireless/libertas/dev.h +4
-47Lines of this file are not shown. View the raw message.
drivers/net/wireless/libertas/ethtool.c +0
-5Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
else
drivers/net/wireless/libertas/main.c +4
-138Lines of this file are not shown. View the raw message.
drivers/net/wireless/libertas/scan.c deleted +0
-1353Lines of this file are not shown. View the raw message.
drivers/net/wireless/libertas/scan.h deleted +0
-63Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
received from FW */
skb_orphan(skb);drivers/net/wireless/libertas/tx.c +0
-0@@ -160,6 +160,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)free:
dev_kfree_skb_any(skb);
}
+
unlock:
spin_unlock_irqrestore(&priv->driver_lock, flags);wake_up(&priv->waitq);drivers/net/wireless/libertas/tx.c +3
-2Lines of this file are not shown. View the raw message.
drivers/net/wireless/libertas/wext.c deleted +0
-2348Lines of this file are not shown. View the raw message.
drivers/net/wireless/libertas/wext.h deleted +0
-18Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
1.6.3.3
--
Intel Open Source Technology Centre
http://oss.intel.com/
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Part of the diff is not shown here. View the raw message.