Commit 7c6fa2a8 authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by John W. Linville

mwifiex: use cfg80211 dynamic scan table and cfg80211_get_bss API

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: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarYogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 9af73cf7
......@@ -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.
*
......@@ -937,8 +804,7 @@ 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,
......@@ -946,11 +812,11 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
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) {
......@@ -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) {
......@@ -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__);
......
......@@ -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
......@@ -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
*/
......
......@@ -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);
......@@ -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
......@@ -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);
......
......@@ -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.
*
......@@ -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
......
......@@ -229,21 +229,6 @@ struct ieee_types_header {
u8 len;
} __packed;
struct ieee_obss_scan_param {
u16 obss_scan_passive_dwell;
u16 obss_scan_active_dwell;
u16 bss_chan_width_trigger_scan_int;
u16 obss_scan_passive_total;
u16 obss_scan_active_total;
u16 bss_width_chan_trans_delay;
u16 obss_scan_active_threshold;
} __packed;
struct ieee_types_obss_scan_param {
struct ieee_types_header ieee_hdr;
struct ieee_obss_scan_param obss_scan;
} __packed;
#define MWIFIEX_SUPPORTED_RATES 14
#define MWIFIEX_SUPPORTED_RATES_EXT 32
......@@ -291,8 +276,6 @@ struct mwifiex_bssdescriptor {
u16 bss_co_2040_offset;
u8 *bcn_ext_cap;
u16 ext_cap_offset;
struct ieee_types_obss_scan_param *bcn_obss_scan;
u16 overlap_bss_offset;
struct ieee_types_vendor_specific *bcn_wpa_ie;
u16 wpa_offset;
struct ieee_types_generic *bcn_rsn_ie;
......@@ -301,8 +284,6 @@ struct mwifiex_bssdescriptor {
u16 wapi_offset;
u8 *beacon_buf;
u32 beacon_buf_size;
u32 beacon_buf_size_max;
};
struct mwifiex_current_bss_params {
......@@ -624,15 +605,11 @@ struct mwifiex_adapter {
u32 scan_processing;
u16 region_code;
struct mwifiex_802_11d_domain_reg domain_reg;
struct mwifiex_bssdescriptor *scan_table;
u32 num_in_scan_table;
u16 scan_probes;
u32 scan_mode;
u16 specific_scan_time;
u16 active_scan_time;
u16 passive_scan_time;
u8 bcn_buf[MAX_SCAN_BEACON_BUFFER];
u8 *bcn_buf_end;
u8 fw_bands;
u8 adhoc_start_band;
u8 config_bands;
......@@ -765,13 +742,6 @@ void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
struct cmd_ctrl_node *cmd_node);
int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
struct mwifiex_802_11_ssid *ssid, u8 *bssid,
u32 mode);
s32 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
u32 mode);
int mwifiex_find_best_network(struct mwifiex_private *priv,
struct mwifiex_ssid_bssid *req_ssid_bssid);
s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
struct mwifiex_802_11_ssid *ssid2);
int mwifiex_associate(struct mwifiex_private *priv,
......@@ -782,7 +752,6 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp);
void mwifiex_reset_connect_state(struct mwifiex_private *priv);
void mwifiex_2040_coex_event(struct mwifiex_private *priv);
u8 mwifiex_band_to_radio_type(u8 band);
int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
int mwifiex_adhoc_start(struct mwifiex_private *priv,
......@@ -922,8 +891,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
struct net_device *dev);
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
int mwifiex_bss_start(struct mwifiex_private *priv,
struct mwifiex_ssid_bssid *ssid_bssid);
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
struct mwifiex_802_11_ssid *req_ssid);
int mwifiex_set_hs_params(struct mwifiex_private *priv,
u16 action, int cmd_type,
struct mwifiex_ds_hs_cfg *hscfg);
......@@ -934,8 +903,6 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv,
struct mwifiex_ds_get_signal *signal);
int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate);
int mwifiex_find_best_bss(struct mwifiex_private *priv,
struct mwifiex_ssid_bssid *ssid_bssid);
int mwifiex_request_scan(struct mwifiex_private *priv,
struct mwifiex_802_11_ssid *req_ssid);
int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
......@@ -984,12 +951,20 @@ int mwifiex_main_process(struct mwifiex_adapter *);
int mwifiex_bss_set_channel(struct mwifiex_private *,
struct mwifiex_chan_freq_power *cfp);
int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *,
struct mwifiex_ssid_bssid *);
int mwifiex_set_radio_band_cfg(struct mwifiex_private *,
struct mwifiex_ds_band_cfg *);
int mwifiex_get_bss_info(struct mwifiex_private *,
struct mwifiex_bss_info *);
int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
u8 *bssid, s32 rssi, u8 *ie_buf,
size_t ie_len, u16 beacon_period,
u16 cap_info_bitmap,
struct mwifiex_bssdescriptor *bss_desc);
int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
struct mwifiex_bssdescriptor *bss_entry,
u8 *ie_buf, u32 ie_len);
int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
#ifdef CONFIG_DEBUG_FS
void mwifiex_debugfs_init(void);
......
This diff is collapsed.
......@@ -299,11 +299,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
case EVENT_BG_SCAN_REPORT:
dev_dbg(adapter->dev, "event: BGS_REPORT\n");
/* Clear the previous scan result */
memset(adapter->scan_table, 0x00,
sizeof(struct mwifiex_bssdescriptor) * MWIFIEX_MAX_AP);
adapter->num_in_scan_table = 0;
adapter->bcn_buf_end = adapter->bcn_buf;
ret = mwifiex_send_cmd_async(priv,
HostCmd_CMD_802_11_BG_SCAN_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
......
......@@ -141,91 +141,143 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
return ret;
}
/*
* This function fills bss descriptor structure using provided
* information.
*/
int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
u8 *bssid, s32 rssi, u8 *ie_buf,
size_t ie_len, u16 beacon_period,
u16 cap_info_bitmap,
struct mwifiex_bssdescriptor *bss_desc)
{
int ret;
memcpy(bss_desc->mac_address, bssid, ETH_ALEN);
bss_desc->rssi = rssi;
bss_desc->beacon_buf = ie_buf;
bss_desc->beacon_buf_size = ie_len;
bss_desc->beacon_period = beacon_period;
bss_desc->cap_info_bitmap = cap_info_bitmap;
if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");
bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
} else {
bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
}
if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
else
bss_desc->bss_mode = NL80211_IFTYPE_STATION;
ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc,
ie_buf, ie_len);
return ret;
}
/*
* In Ad-Hoc mode, the IBSS is created if not found in scan list.
* In both Ad-Hoc and infra mode, an deauthentication is performed
* first.
*/
int mwifiex_bss_start(struct mwifiex_private *priv,
struct mwifiex_ssid_bssid *ssid_bssid)
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
struct mwifiex_802_11_ssid *req_ssid)
{
int ret;
struct mwifiex_adapter *adapter = priv->adapter;
s32 i = -1;
struct mwifiex_bssdescriptor *bss_desc = NULL;
u8 *beacon_ie = NULL;
priv->scan_block = false;
if (!ssid_bssid)
return -1;
if (bss) {
/* Allocate and fill new bss descriptor */
bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
GFP_KERNEL);
if (!bss_desc) {
dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
return -ENOMEM;
}
beacon_ie = kzalloc(bss->len_beacon_ies, GFP_KERNEL);
if (!beacon_ie) {
dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
return -ENOMEM;
}
memcpy(beacon_ie, bss->information_elements,
bss->len_beacon_ies);
ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal,
beacon_ie, bss->len_beacon_ies,
bss->beacon_interval,
bss->capability, bss_desc);
if (ret)
goto done;
}
if (priv->bss_mode == NL80211_IFTYPE_STATION) {
/* Infra mode */
ret = mwifiex_deauthenticate(priv, NULL);
if (ret)
return ret;
goto done;
/* Search for the requested SSID in the scan table */
if (ssid_bssid->ssid.ssid_len)
i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid,
NULL, NL80211_IFTYPE_STATION);
else
i = mwifiex_find_bssid_in_list(priv,
(u8 *) &ssid_bssid->bssid,
NL80211_IFTYPE_STATION);
if (i < 0)
return -1;
ret = mwifiex_check_network_compatibility(priv, bss_desc);
if (ret)
goto done;
dev_dbg(adapter->dev, "info: SSID found in scan list ... "
"associating...\n");
dev_dbg(adapter->dev,
"info: SSID found in scan list ... associating...\n");
if (!netif_queue_stopped(priv->netdev))
netif_stop_queue(priv->netdev);
/* Clear any past association response stored for
* application retrieval */
priv->assoc_rsp_size = 0;
ret = mwifiex_associate(priv, &adapter->scan_table[i]);
if (ret)
return ret;
ret = mwifiex_associate(priv, bss_desc);
if (bss)
cfg80211_put_bss(bss);
} else {
/* Adhoc mode */
/* If the requested SSID matches current SSID, return */
if (ssid_bssid->ssid.ssid_len &&
if (bss_desc && bss_desc->ssid.ssid_len &&
(!mwifiex_ssid_cmp
(&priv->curr_bss_params.bss_descriptor.ssid,
&ssid_bssid->ssid)))
&bss_desc->ssid))) {
kfree(bss_desc);
kfree(beacon_ie);
return 0;
}
/* Exit Adhoc mode first */
dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
ret = mwifiex_deauthenticate(priv, NULL);
if (ret)
return ret;
goto done;
priv->adhoc_is_link_sensed = false;
/* Search for the requested network in the scan table */
if (ssid_bssid->ssid.ssid_len)
i = mwifiex_find_ssid_in_list(priv,
&ssid_bssid->ssid, NULL,
NL80211_IFTYPE_ADHOC);
else
i = mwifiex_find_bssid_in_list(priv,
(u8 *)&ssid_bssid->bssid,
NL80211_IFTYPE_ADHOC);
if (i >= 0) {
ret = mwifiex_check_network_compatibility(priv, bss_desc);
if (!netif_queue_stopped(priv->netdev))
netif_stop_queue(priv->netdev);
if (!ret) {
dev_dbg(adapter->dev, "info: network found in scan"
" list. Joining...\n");
ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]);
if (ret)
return ret;
ret = mwifiex_adhoc_join(priv, bss_desc);
if (bss)
cfg80211_put_bss(bss);
} else {
dev_dbg(adapter->dev, "info: Network not found in "
"the list, creating adhoc with ssid = %s\n",
ssid_bssid->ssid.ssid);
ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid);
if (ret)
return ret;
req_ssid->ssid);
ret = mwifiex_adhoc_start(priv, req_ssid);
}
}
done:
kfree(bss_desc);
kfree(beacon_ie);
return ret;
}
......@@ -573,50 +625,6 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,
action, 0, channel);
}
/*
* IOCTL request handler to find a particular BSS.
*
* The BSS can be searched with either a BSSID or a SSID. If none of
* these are provided, just the best BSS (best RSSI) is returned.
*/
int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv,
struct mwifiex_ssid_bssid *ssid_bssid)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_bssdescriptor *bss_desc;
u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
u8 mac[ETH_ALEN];
int i = 0;
if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) {
i = mwifiex_find_bssid_in_list(priv,
(u8 *) ssid_bssid->bssid,
priv->bss_mode);
if (i < 0) {
memcpy(mac, ssid_bssid->bssid, sizeof(mac));
dev_err(adapter->dev, "cannot find bssid %pM\n", mac);
return -1;
}
bss_desc = &adapter->scan_table[i];
memcpy(&ssid_bssid->ssid, &bss_desc->ssid,
sizeof(struct mwifiex_802_11_ssid));
} else if (ssid_bssid->ssid.ssid_len) {
i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL,
priv->bss_mode);
if (i < 0) {
dev_err(adapter->dev, "cannot find ssid %s\n",
ssid_bssid->ssid.ssid);
return -1;
}
bss_desc = &adapter->scan_table[i];
memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN);
} else {
return mwifiex_find_best_network(priv, ssid_bssid);
}
return 0;
}
/*
* IOCTL request handler to change Ad-Hoc channel.
*
......@@ -641,6 +649,8 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
struct mwifiex_bss_info bss_info;
struct mwifiex_ssid_bssid ssid_bssid;
u16 curr_chan = 0;
struct cfg80211_bss *bss = NULL;
struct ieee80211_channel *chan;
memset(&bss_info, 0, sizeof(bss_info));
......@@ -676,12 +686,20 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
ret = -1;
goto done;
}
/* Start/Join Adhoc network */
memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
memcpy(&ssid_bssid.ssid, &bss_info.ssid,
sizeof(struct mwifiex_802_11_ssid));
ret = mwifiex_bss_start(priv, &ssid_bssid);
chan = __ieee80211_get_channel(priv->wdev->wiphy,
ieee80211_channel_to_frequency(channel,
priv->curr_bss_params.band));
/* Find the BSS we want using available scan results */
bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid,
bss_info.ssid.ssid, bss_info.ssid.ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
if (!bss)
wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n",
bss_info.bssid);
ret = mwifiex_bss_start(priv, bss, &bss_info.ssid);
done:
return ret;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment