Skip to content

Commit

Permalink
mwifiex: use cfg80211 dynamic scan table and cfg80211_get_bss API
Browse files Browse the repository at this point in the history
Instead of maintaining static scan table in driver, scan list is sent
to cfg80211 stack (after parsing each scan command response).
In assoc handler (for infra and ibss network) requested BSS information
is retrieved using cfg80211_get_bss() API.

With the changes above some redundant code are removed.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Amitkumar Karwar authored and linvjw committed Aug 12, 2011
1 parent 9af73cf commit 7c6fa2a
Show file tree
Hide file tree
Showing 8 changed files with 471 additions and 1,634 deletions.
207 changes: 43 additions & 164 deletions drivers/net/wireless/mwifiex/cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -792,139 +792,6 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
return 0;
}

/*
* This function informs the CFG802.11 subsystem of a new BSS connection.
*
* The following information are sent to the CFG802.11 subsystem
* to register the new BSS connection. If we do not register the new BSS,
* a kernel panic will result.
* - MAC address
* - Capabilities
* - Beacon period
* - RSSI value
* - Channel
* - Supported rates IE
* - Extended capabilities IE
* - DS parameter set IE
* - HT Capability IE
* - Vendor Specific IE (221)
* - WPA IE
* - RSN IE
*/
static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
struct mwifiex_802_11_ssid *ssid)
{
struct mwifiex_bssdescriptor *scan_table;
int i, j;
struct ieee80211_channel *chan;
u8 *ie, *ie_buf;
u32 ie_len;
u8 *beacon;
int beacon_size;
u8 element_id, element_len;

#define MAX_IE_BUF 2048
ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL);
if (!ie_buf) {
dev_err(priv->adapter->dev, "%s: failed to alloc ie_buf\n",
__func__);
return -ENOMEM;
}

scan_table = priv->adapter->scan_table;
for (i = 0; i < priv->adapter->num_in_scan_table; i++) {
if (ssid) {
/* Inform specific BSS only */
if (memcmp(ssid->ssid, scan_table[i].ssid.ssid,
ssid->ssid_len))
continue;
}
memset(ie_buf, 0, MAX_IE_BUF);
ie_buf[0] = WLAN_EID_SSID;
ie_buf[1] = scan_table[i].ssid.ssid_len;
memcpy(&ie_buf[sizeof(struct ieee_types_header)],
scan_table[i].ssid.ssid, ie_buf[1]);

ie = ie_buf + ie_buf[1] + sizeof(struct ieee_types_header);
ie_len = ie_buf[1] + sizeof(struct ieee_types_header);

ie[0] = WLAN_EID_SUPP_RATES;

for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) {
if (!scan_table[i].supported_rates[j])
break;
else
ie[j + sizeof(struct ieee_types_header)] =
scan_table[i].supported_rates[j];
}

ie[1] = j;
ie_len += ie[1] + sizeof(struct ieee_types_header);

beacon = scan_table[i].beacon_buf;
beacon_size = scan_table[i].beacon_buf_size;

/* Skip time stamp, beacon interval and capability */

if (beacon) {
beacon += sizeof(scan_table[i].beacon_period)
+ sizeof(scan_table[i].time_stamp) +
+sizeof(scan_table[i].cap_info_bitmap);

beacon_size -= sizeof(scan_table[i].beacon_period)
+ sizeof(scan_table[i].time_stamp)
+ sizeof(scan_table[i].cap_info_bitmap);
}

while (beacon_size >= sizeof(struct ieee_types_header)) {
ie = ie_buf + ie_len;
element_id = *beacon;
element_len = *(beacon + 1);
if (beacon_size < (int) element_len +
sizeof(struct ieee_types_header)) {
dev_err(priv->adapter->dev, "%s: in processing"
" IE, bytes left < IE length\n",
__func__);
break;
}
switch (element_id) {
case WLAN_EID_EXT_CAPABILITY:
case WLAN_EID_DS_PARAMS:
case WLAN_EID_HT_CAPABILITY:
case WLAN_EID_VENDOR_SPECIFIC:
case WLAN_EID_RSN:
case WLAN_EID_BSS_AC_ACCESS_DELAY:
ie[0] = element_id;
ie[1] = element_len;
memcpy(&ie[sizeof(struct ieee_types_header)],
(u8 *) beacon
+ sizeof(struct ieee_types_header),
element_len);
ie_len += ie[1] +
sizeof(struct ieee_types_header);
break;
default:
break;
}
beacon += element_len +
sizeof(struct ieee_types_header);
beacon_size -= element_len +
sizeof(struct ieee_types_header);
}
chan = ieee80211_get_channel(priv->wdev->wiphy,
scan_table[i].freq);
cfg80211_inform_bss(priv->wdev->wiphy, chan,
scan_table[i].mac_address,
0, scan_table[i].cap_info_bitmap,
scan_table[i].beacon_period,
ie_buf, ie_len,
scan_table[i].rssi, GFP_KERNEL);
}

kfree(ie_buf);
return 0;
}

/*
* This function connects with a BSS.
*
Expand All @@ -937,20 +804,19 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
* For Infra mode, the function returns failure if the specified SSID
* is not found in scan table. However, for Ad-Hoc mode, it can create
* the IBSS if it does not exist. On successful completion in either case,
* the function notifies the CFG802.11 subsystem of the new BSS connection,
* otherwise the kernel will panic.
* the function notifies the CFG802.11 subsystem of the new BSS connection.
*/
static int
mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
u8 *bssid, int mode, struct ieee80211_channel *channel,
struct cfg80211_connect_params *sme, bool privacy)
{
struct mwifiex_802_11_ssid req_ssid;
struct mwifiex_ssid_bssid ssid_bssid;
int ret, auth_type = 0;
struct cfg80211_bss *bss = NULL;
u8 is_scanning_required = 0;

memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));
memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));

req_ssid.ssid_len = ssid_len;
if (ssid_len > IEEE80211_MAX_SSID_LEN) {
Expand Down Expand Up @@ -1028,30 +894,48 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
return -EFAULT;
}

/*
* Scan entries are valid for some time (15 sec). So we can save one
* active scan time if we just try cfg80211_get_bss first. If it fails
* then request scan and cfg80211_get_bss() again for final output.
*/
while (1) {
if (is_scanning_required) {
/* Do specific SSID scanning */
if (mwifiex_request_scan(priv, &req_ssid)) {
dev_err(priv->adapter->dev, "scan error\n");
return -EFAULT;
}
}

memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid));

if (mode != NL80211_IFTYPE_ADHOC) {
if (mwifiex_find_best_bss(priv, &ssid_bssid))
return -EFAULT;
/* Inform the BSS information to kernel, otherwise
* kernel will give a panic after successful assoc */
if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid))
return -EFAULT;
/* Find the BSS we want using available scan results */
if (mode == NL80211_IFTYPE_ADHOC)
bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
bssid, ssid, ssid_len,
WLAN_CAPABILITY_IBSS,
WLAN_CAPABILITY_IBSS);
else
bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
bssid, ssid, ssid_len,
WLAN_CAPABILITY_ESS,
WLAN_CAPABILITY_ESS);

if (!bss) {
if (is_scanning_required) {
dev_warn(priv->adapter->dev, "assoc: requested "
"bss not found in scan results\n");
break;
}
is_scanning_required = 1;
} else {
dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n",
(char *) req_ssid.ssid, bss->bssid);
memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
break;
}
}

dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n",
(char *) req_ssid.ssid, ssid_bssid.bssid);

memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6);

/* Connect to BSS by ESSID */
memset(&ssid_bssid.bssid, 0, ETH_ALEN);

if (!netif_queue_stopped(priv->netdev))
netif_stop_queue(priv->netdev);

if (mwifiex_bss_start(priv, &ssid_bssid))
if (mwifiex_bss_start(priv, bss, &req_ssid))
return -EFAULT;

if (mode == NL80211_IFTYPE_ADHOC) {
Expand Down Expand Up @@ -1416,13 +1300,8 @@ mwifiex_cfg80211_results(struct work_struct *work)
MWIFIEX_SCAN_TYPE_ACTIVE;
scan_req->chan_list[i].scan_time = 0;
}
if (mwifiex_set_user_scan_ioctl(priv, scan_req)) {
if (mwifiex_set_user_scan_ioctl(priv, scan_req))
ret = -EFAULT;
goto done;
}
if (mwifiex_inform_bss_from_scan_result(priv, NULL))
ret = -EFAULT;
done:
priv->scan_result_status = ret;
dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n",
__func__);
Expand Down
15 changes: 8 additions & 7 deletions drivers/net/wireless/mwifiex/fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,14 @@ struct host_cmd_ds_txpwr_cfg {
__le32 mode;
} __packed;

struct mwifiex_bcn_param {
u8 bssid[ETH_ALEN];
u8 rssi;
__le32 timestamp[2];
__le16 beacon_period;
__le16 cap_info_bitmap;
} __packed;

#define MWIFIEX_USER_SCAN_CHAN_MAX 50

#define MWIFIEX_MAX_SSID_LIST_LENGTH 10
Expand Down Expand Up @@ -861,13 +869,6 @@ struct mwifiex_user_scan_ssid {
} __packed;

struct mwifiex_user_scan_cfg {
/*
* Flag set to keep the previous scan table intact
*
* If set, the scan results will accumulate, replacing any previous
* matched entries for a BSS with the new scan data
*/
u8 keep_previous_scan;
/*
* BSS mode to be sent in the firmware command
*/
Expand Down
21 changes: 0 additions & 21 deletions drivers/net/wireless/mwifiex/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,6 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
{
int ret;
u32 buf_size;
struct mwifiex_bssdescriptor *temp_scan_table;

/* Allocate buffer to store the BSSID list */
buf_size = sizeof(struct mwifiex_bssdescriptor) * MWIFIEX_MAX_AP;
temp_scan_table = kzalloc(buf_size, GFP_KERNEL);
if (!temp_scan_table) {
dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n",
__func__);
return -ENOMEM;
}

adapter->scan_table = temp_scan_table;

/* Allocate command buffer */
ret = mwifiex_alloc_cmd_buffer(adapter);
Expand Down Expand Up @@ -222,14 +209,8 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;

adapter->num_in_scan_table = 0;
memset(adapter->scan_table, 0,
(sizeof(struct mwifiex_bssdescriptor) * MWIFIEX_MAX_AP));
adapter->scan_probes = 1;

memset(adapter->bcn_buf, 0, sizeof(adapter->bcn_buf));
adapter->bcn_buf_end = adapter->bcn_buf;

adapter->multiple_dtim = 1;

adapter->local_listen_interval = 0; /* default value in firmware
Expand Down Expand Up @@ -326,8 +307,6 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)
del_timer(&adapter->cmd_timer);

dev_dbg(adapter->dev, "info: free scan table\n");
kfree(adapter->scan_table);
adapter->scan_table = NULL;

adapter->if_ops.cleanup_if(adapter);

Expand Down
32 changes: 0 additions & 32 deletions drivers/net/wireless/mwifiex/join.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,32 +223,6 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv,
return 0;
}

/*
* This function updates the scan entry TSF timestamps to reflect
* a new association.
*/
static void
mwifiex_update_tsf_timestamps(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *new_bss_desc)
{
struct mwifiex_adapter *adapter = priv->adapter;
u32 table_idx;
long long new_tsf_base;
signed long long tsf_delta;

memcpy(&new_tsf_base, new_bss_desc->time_stamp, sizeof(new_tsf_base));

tsf_delta = new_tsf_base - new_bss_desc->network_tsf;

dev_dbg(adapter->dev, "info: TSF: update TSF timestamps, "
"0x%016llx -> 0x%016llx\n",
new_bss_desc->network_tsf, new_tsf_base);

for (table_idx = 0; table_idx < adapter->num_in_scan_table;
table_idx++)
adapter->scan_table[table_idx].network_tsf += tsf_delta;
}

/*
* This function appends a WAPI IE.
*
Expand Down Expand Up @@ -639,12 +613,6 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,

priv->curr_bss_params.band = (u8) bss_desc->bss_band;

/*
* Adjust the timestamps in the scan table to be relative to the newly
* associated AP's TSF
*/
mwifiex_update_tsf_timestamps(priv, bss_desc);

if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)
priv->curr_bss_params.wmm_enabled = true;
else
Expand Down

0 comments on commit 7c6fa2a

Please sign in to comment.