aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAshwin <ashwin.bhat@broadcom.com>2014-07-22 18:04:46 -0700
committerZiyan <jaraidaniel@gmail.com>2016-05-01 23:35:36 +0200
commit24e1bc9e171cd62dae4cdfa4208500d84fd9d45f (patch)
tree48ef46337a093b26d463bc0d3d369c30116de25a /drivers
parentd3d16f6279a1ec3ce8783ecb25d1cac75eb2a921 (diff)
downloadkernel_samsung_tuna-24e1bc9e171cd62dae4cdfa4208500d84fd9d45f.zip
kernel_samsung_tuna-24e1bc9e171cd62dae4cdfa4208500d84fd9d45f.tar.gz
kernel_samsung_tuna-24e1bc9e171cd62dae4cdfa4208500d84fd9d45f.tar.bz2
net: wireless: bcmdhd: Add support for hidden ssid PNO scan
Changes to support hidden ssid config to be sent to FW. Earlier all ssids were hard coded as hidden, now only those indicated as such by supplicant will be. Change-Id: I927030fe12f162c52c93277b2ebfb4bf55daef4a Signed-off-by: Ashwin <ashwin.bhat@broadcom.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c3
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c2
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_pno.c194
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_pno.h5
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlioctl.h6
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c2
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c63
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.h2
8 files changed, 170 insertions, 107 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
index c3e19b2..93f5e4d 100644
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -2084,7 +2084,7 @@ wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list,
* SSIDs list parsing from cscan tlv list
*/
int
-wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left)
+wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_ext_t* ssid, int max, int *bytes_left)
{
char* str;
int idx = 0;
@@ -2132,6 +2132,7 @@ wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes
*bytes_left -= ssid[idx].SSID_len;
str += ssid[idx].SSID_len;
+ ssid[idx].hidden = TRUE;
DHD_TRACE(("%s :size=%d left=%d\n",
(char*)ssid[idx].SSID, ssid[idx].SSID_len, *bytes_left));
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 7d53f40..71caa5e 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -5527,7 +5527,7 @@ dhd_dev_pno_stop_for_ssid(struct net_device *dev)
/* Linux wrapper to call common dhd_pno_set_for_ssid */
int
-dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid,
+dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_ext_t* ssids_local, int nssid,
uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c
index 5e6f14d..dd81ccf 100644
--- a/drivers/net/wireless/bcmdhd/dhd_pno.c
+++ b/drivers/net/wireless/bcmdhd/dhd_pno.c
@@ -81,6 +81,8 @@
#define ENTRY_OVERHEAD strlen("bssid=\nssid=\nfreq=\nlevel=\nage=\ndist=\ndistSd=\n====")
#define TIME_MIN_DIFF 5
+static wlc_ssid_ext_t * dhd_pno_get_legacy_pno_ssid(dhd_pub_t *dhd,
+ dhd_pno_status_info_t *pno_state);
static inline bool
is_dfs(uint16 channel)
{
@@ -172,7 +174,7 @@ _dhd_pno_enable(dhd_pub_t *dhd, int enable)
/* Enable/Disable PNO */
err = dhd_iovar(dhd, 0, "pfn", (char *)&enable, sizeof(enable), 1);
if (err < 0) {
- DHD_ERROR(("%s : failed to execute pfn_set\n", __FUNCTION__));
+ DHD_ERROR(("%s : failed to execute pfn_set - %d\n", __FUNCTION__, err));
goto exit;
}
_pno_state->pno_status = (enable)?
@@ -316,7 +318,7 @@ _dhd_pno_set(dhd_pub_t *dhd, const dhd_pno_params_t *pno_params, dhd_pno_mode_t
}
err = dhd_iovar(dhd, 0, "pfn_set", (char *)&pfn_param, sizeof(pfn_param), 1);
if (err < 0) {
- DHD_ERROR(("%s : failed to execute pfn_set\n", __FUNCTION__));
+ DHD_ERROR(("%s : failed to execute pfn_set %d\n", __FUNCTION__, err));
goto exit;
}
/* need to return mscan if this is for batch scan instead of err */
@@ -325,7 +327,7 @@ exit:
return err;
}
static int
-_dhd_pno_add_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssids_list, int nssid)
+_dhd_pno_add_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssids_list, int nssid)
{
int err = BCME_OK;
int i = 0;
@@ -338,8 +340,8 @@ _dhd_pno_add_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssids_list, int nssid)
{
int j;
for (j = 0; j < nssid; j++) {
- DHD_PNO(("%d: scan for %s size = %d\n", j,
- ssids_list[j].SSID, ssids_list[j].SSID_len));
+ DHD_PNO(("%d: scan for %s size = %d hidden = %d\n", j,
+ ssids_list[j].SSID, ssids_list[j].SSID_len, ssids_list[j].hidden));
}
}
/* Check for broadcast ssid */
@@ -357,7 +359,10 @@ _dhd_pno_add_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssids_list, int nssid)
pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
pfn_element.wsec = htod32(0);
pfn_element.infra = htod32(1);
- pfn_element.flags = htod32(ENABLE << WL_PFN_HIDDEN_BIT);
+ if (ssids_list[i].hidden)
+ pfn_element.flags = htod32(ENABLE << WL_PFN_HIDDEN_BIT);
+ else
+ pfn_element.flags = 0;
memcpy((char *)pfn_element.ssid.SSID, ssids_list[i].SSID,
ssids_list[i].SSID_len);
pfn_element.ssid.SSID_len = ssids_list[i].SSID_len;
@@ -670,6 +675,7 @@ _dhd_pno_reinitialize_prof(dhd_pub_t *dhd, dhd_pno_params_t *params, dhd_pno_mod
kfree(iter);
}
}
+ params->params_legacy.nssid = 0;
params->params_legacy.scan_fr = 0;
params->params_legacy.pno_freq_expo_max = 0;
params->params_legacy.pno_repeat = 0;
@@ -735,7 +741,7 @@ _dhd_pno_add_bssid(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, int nbssid)
if (nbssid) {
NULL_CHECK(p_pfn_bssid, "bssid list is NULL", err);
}
- err = dhd_iovar(dhd, 0, "pfn_add_bssid", (char *)&p_pfn_bssid,
+ err = dhd_iovar(dhd, 0, "pfn_add_bssid", (char *)p_pfn_bssid,
sizeof(wl_pfn_bssid_t) * nbssid, 1);
if (err < 0) {
DHD_ERROR(("%s : failed to execute pfn_cfg\n", __FUNCTION__));
@@ -831,11 +837,73 @@ dhd_pno_enable(dhd_pub_t *dhd, int enable)
return (_dhd_pno_enable(dhd, enable));
}
+static wlc_ssid_ext_t * dhd_pno_get_legacy_pno_ssid(dhd_pub_t *dhd,
+ dhd_pno_status_info_t *pno_state)
+{
+ int err = BCME_OK;
+ int i;
+ struct dhd_pno_ssid *iter, *next;
+ dhd_pno_params_t *_params1 = &pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
+ wlc_ssid_ext_t *p_ssid_list;
+
+ p_ssid_list = kzalloc(sizeof(wlc_ssid_ext_t) *
+ _params1->params_legacy.nssid, GFP_KERNEL);
+ if (p_ssid_list == NULL) {
+ DHD_ERROR(("%s : failed to allocate wlc_ssid_ext_t array (count: %d)",
+ __FUNCTION__, _params1->params_legacy.nssid));
+ err = BCME_ERROR;
+ pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ goto exit;
+ }
+ i = 0;
+ /* convert dhd_pno_ssid to wlc_ssid_ext_t */
+ list_for_each_entry_safe(iter, next, &_params1->params_legacy.ssid_list, list) {
+ p_ssid_list[i].SSID_len = iter->SSID_len;
+ p_ssid_list[i].hidden = iter->hidden;
+ memcpy(p_ssid_list[i].SSID, iter->SSID, p_ssid_list[i].SSID_len);
+ i++;
+ }
+exit:
+ return p_ssid_list;
+
+}
+
+static int
+dhd_pno_add_to_ssid_list(dhd_pno_params_t *params, wlc_ssid_ext_t *ssid_list,
+ int nssid)
+{
+ int ret = 0;
+ int i;
+ struct dhd_pno_ssid *_pno_ssid;
+
+ for (i = 0; i < nssid; i++) {
+ if (ssid_list[i].SSID_len > DOT11_MAX_SSID_LEN) {
+ DHD_ERROR(("%s : Invalid SSID length %d\n",
+ __FUNCTION__, ssid_list[i].SSID_len));
+ ret = BCME_ERROR;
+ goto exit;
+ }
+ _pno_ssid = kzalloc(sizeof(struct dhd_pno_ssid), GFP_KERNEL);
+ if (_pno_ssid == NULL) {
+ DHD_ERROR(("%s : failed to allocate struct dhd_pno_ssid\n",
+ __FUNCTION__));
+ ret = BCME_ERROR;
+ goto exit;
+ }
+ _pno_ssid->SSID_len = ssid_list[i].SSID_len;
+ _pno_ssid->hidden = ssid_list[i].hidden;
+ memcpy(_pno_ssid->SSID, ssid_list[i].SSID, _pno_ssid->SSID_len);
+ list_add_tail(&_pno_ssid->list, &params->params_legacy.ssid_list);
+ }
+
+exit:
+ return ret;
+}
+
int
-dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
+dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssid_list, int nssid,
uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan)
{
- struct dhd_pno_ssid *_pno_ssid;
dhd_pno_params_t *_params;
dhd_pno_params_t *_params2;
dhd_pno_status_info_t *_pno_state;
@@ -850,7 +918,7 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
if (!dhd_support_sta_mode(dhd)) {
err = BCME_BADOPTION;
- goto exit;
+ goto exit_no_clear;
}
DHD_PNO(("%s enter : scan_fr :%d, pno_repeat :%d,"
"pno_freq_expo_max: %d, nchan :%d\n", __FUNCTION__,
@@ -864,7 +932,7 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
if (err < 0) {
DHD_ERROR(("%s : failed to stop legacy PNO (err %d)\n",
__FUNCTION__, err));
- goto exit;
+ goto exit_no_clear;
}
}
_pno_state->pno_mode |= DHD_PNO_LEGACY_MODE;
@@ -872,7 +940,7 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
if (err < 0) {
DHD_ERROR(("%s : failed to reinitialize profile (err %d)\n",
__FUNCTION__, err));
- goto exit;
+ goto exit_no_clear;
}
memset(_chan_list, 0, sizeof(_chan_list));
tot_nchan = nchan;
@@ -889,7 +957,7 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
err = _dhd_pno_enable(dhd, PNO_OFF);
if (err < 0) {
DHD_ERROR(("%s : failed to disable PNO\n", __FUNCTION__));
- goto exit;
+ goto exit_no_clear;
}
/* restore the previous mode */
_pno_state->pno_mode = mode;
@@ -905,7 +973,7 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
DHD_ERROR(("%s : failed to merge channel list"
" between legacy and batch\n",
__FUNCTION__));
- goto exit;
+ goto exit_no_clear;
}
} else {
DHD_PNO(("superset channel will use"
@@ -922,7 +990,7 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
DHD_ERROR(("%s : failed to merge channel list"
" between legacy and hotlist\n",
__FUNCTION__));
- goto exit;
+ goto exit_no_clear;
}
}
}
@@ -941,17 +1009,9 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
DHD_ERROR(("failed to add ssid list(err %d), %d in firmware\n", err, nssid));
goto exit;
}
- for (i = 0; i < nssid; i++) {
- _pno_ssid = kzalloc(sizeof(struct dhd_pno_ssid), GFP_KERNEL);
- if (_pno_ssid == NULL) {
- DHD_ERROR(("%s : failed to allocate struct dhd_pno_ssid\n",
- __FUNCTION__));
- goto exit;
- }
- _pno_ssid->SSID_len = ssid_list[i].SSID_len;
- memcpy(_pno_ssid->SSID, ssid_list[i].SSID, _pno_ssid->SSID_len);
- list_add_tail(&_pno_ssid->list, &_params->params_legacy.ssid_list);
-
+ if (dhd_pno_add_to_ssid_list(_params, ssid_list, nssid) < 0) {
+ err = BCME_ERROR;
+ goto exit;
}
if (tot_nchan > 0) {
if ((err = _dhd_pno_cfg(dhd, _chan_list, tot_nchan)) < 0) {
@@ -965,6 +1025,9 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
DHD_ERROR(("%s : failed to enable PNO\n", __FUNCTION__));
}
exit:
+ if (err < 0)
+ _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
+exit_no_clear:
/* clear mode in case of error */
if (err < 0)
_pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
@@ -977,11 +1040,10 @@ dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params)
uint16 _chan_list[WL_NUMCHANNELS];
int rem_nchan = 0, tot_nchan = 0;
int mode = 0, mscan = 0;
- int i = 0;
dhd_pno_params_t *_params;
dhd_pno_params_t *_params2;
dhd_pno_status_info_t *_pno_state;
- wlc_ssid_t *p_ssid_list = NULL;
+ wlc_ssid_ext_t *p_ssid_list = NULL;
NULL_CHECK(dhd, "dhd is NULL", err);
NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
NULL_CHECK(batch_params, "batch_params is NULL", err);
@@ -1051,7 +1113,6 @@ dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params)
tot_nchan = _params->params_batch.nchan;
}
if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
- struct dhd_pno_ssid *iter, *next;
DHD_PNO(("PNO SSID is on progress in firmware\n"));
/* store current pno_mode before disabling pno */
mode = _pno_state->pno_mode;
@@ -1078,22 +1139,12 @@ dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params)
} else {
DHD_PNO(("superset channel will use all channels in firmware\n"));
}
- p_ssid_list = kzalloc(sizeof(wlc_ssid_t) *
- _params2->params_legacy.nssid, GFP_KERNEL);
- if (p_ssid_list == NULL) {
- DHD_ERROR(("%s : failed to allocate wlc_ssid_t array (count: %d)",
- __FUNCTION__, _params2->params_legacy.nssid));
- err = BCME_ERROR;
- _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ p_ssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
+ if (!p_ssid_list) {
+ err = BCME_NOMEM;
+ DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
goto exit;
}
- i = 0;
- /* convert dhd_pno_ssid to dhd_pno_ssid */
- list_for_each_entry_safe(iter, next, &_params2->params_legacy.ssid_list, list) {
- p_ssid_list[i].SSID_len = iter->SSID_len;
- memcpy(p_ssid_list->SSID, iter->SSID, p_ssid_list[i].SSID_len);
- i++;
- }
if ((err = _dhd_pno_add_ssid(dhd, p_ssid_list,
_params2->params_legacy.nssid)) < 0) {
DHD_ERROR(("failed to add ssid list (err %d) in firmware\n", err));
@@ -1127,8 +1178,7 @@ exit:
/* return #max scan firmware can do */
err = mscan;
}
- if (p_ssid_list)
- kfree(p_ssid_list);
+ kfree(p_ssid_list);
return err;
}
@@ -1300,6 +1350,11 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
pbestnet_entry->rtt0 = plnetinfo->rtt0;
pbestnet_entry->rtt1 = plnetinfo->rtt1;
pbestnet_entry->timestamp = plnetinfo->timestamp;
+ if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) {
+ DHD_ERROR(("%s: Invalid SSID length %d: trimming it to max\n",
+ __FUNCTION__, plnetinfo->pfnsubnet.SSID_len));
+ plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN;
+ }
pbestnet_entry->SSID_len = plnetinfo->pfnsubnet.SSID_len;
memcpy(pbestnet_entry->SSID, plnetinfo->pfnsubnet.SSID,
pbestnet_entry->SSID_len);
@@ -1444,7 +1499,7 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd)
dhd_pno_status_info_t *_pno_state;
dhd_pno_params_t *_params;
wl_pfn_bssid_t *p_pfn_bssid;
- wlc_ssid_t *p_ssid_list = NULL;
+ wlc_ssid_ext_t *p_ssid_list = NULL;
NULL_CHECK(dhd, "dhd is NULL", err);
NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
_pno_state = PNO_GET_PNOSTATE(dhd);
@@ -1471,25 +1526,14 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd)
/* restart Legacy PNO if the Legacy PNO is on */
if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
struct dhd_pno_legacy_params *_params_legacy;
- struct dhd_pno_ssid *iter, *next;
_params_legacy =
&(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
- p_ssid_list = kzalloc(sizeof(wlc_ssid_t) *
- _params_legacy->nssid, GFP_KERNEL);
- if (p_ssid_list == NULL) {
- DHD_ERROR(("%s : failed to allocate wlc_ssid_t array (count: %d)",
- __FUNCTION__, _params_legacy->nssid));
- err = BCME_ERROR;
- _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ p_ssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
+ if (!p_ssid_list) {
+ err = BCME_NOMEM;
+ DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
goto exit;
}
- i = 0;
- /* convert dhd_pno_ssid to dhd_pno_ssid */
- list_for_each_entry_safe(iter, next, &_params_legacy->ssid_list, list) {
- p_ssid_list[i].SSID_len = iter->SSID_len;
- memcpy(p_ssid_list[i].SSID, iter->SSID, p_ssid_list[i].SSID_len);
- i++;
- }
err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid,
_params_legacy->scan_fr, _params_legacy->pno_repeat,
_params_legacy->pno_freq_expo_max, _params_legacy->chan_list,
@@ -1540,8 +1584,7 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd)
exit:
_params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
_dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE);
- if (p_ssid_list)
- kfree(p_ssid_list);
+ kfree(p_ssid_list);
return err;
}
@@ -1701,7 +1744,7 @@ dhd_pno_stop_for_hotlist(dhd_pub_t *dhd)
uint32 mode = 0;
dhd_pno_status_info_t *_pno_state;
dhd_pno_params_t *_params;
- wlc_ssid_t *p_ssid_list;
+ wlc_ssid_ext_t *p_ssid_list;
NULL_CHECK(dhd, "dhd is NULL", err);
NULL_CHECK(dhd->pno_state, "pno_state is NULL", err);
_pno_state = PNO_GET_PNOSTATE(dhd);
@@ -1736,24 +1779,14 @@ dhd_pno_stop_for_hotlist(dhd_pub_t *dhd)
if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
/* restart Legacy PNO Scan */
struct dhd_pno_legacy_params *_params_legacy;
- struct dhd_pno_ssid *iter, *next;
_params_legacy =
&(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy);
- p_ssid_list =
- kzalloc(sizeof(wlc_ssid_t) * _params_legacy->nssid, GFP_KERNEL);
- if (p_ssid_list == NULL) {
- DHD_ERROR(("%s : failed to allocate wlc_ssid_t array (count: %d)",
- __FUNCTION__, _params_legacy->nssid));
- err = BCME_ERROR;
- _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE;
+ p_ssid_list = dhd_pno_get_legacy_pno_ssid(dhd, _pno_state);
+ if (!p_ssid_list) {
+ err = BCME_NOMEM;
+ DHD_ERROR(("failed to get Legacy PNO SSID list\n"));
goto exit;
}
- /* convert dhd_pno_ssid to dhd_pno_ssid */
- list_for_each_entry_safe(iter, next, &_params_legacy->ssid_list, list) {
- p_ssid_list->SSID_len = iter->SSID_len;
- memcpy(p_ssid_list->SSID, iter->SSID, p_ssid_list->SSID_len);
- p_ssid_list++;
- }
err = dhd_pno_set_for_ssid(dhd, p_ssid_list, _params_legacy->nssid,
_params_legacy->scan_fr, _params_legacy->pno_repeat,
_params_legacy->pno_freq_expo_max, _params_legacy->chan_list,
@@ -1873,6 +1906,11 @@ int dhd_pno_deinit(dhd_pub_t *dhd)
DHD_PNO(("%s enter\n", __FUNCTION__));
_pno_state = PNO_GET_PNOSTATE(dhd);
NULL_CHECK(_pno_state, "pno_state is NULL", err);
+ /* may need to free legacy ssid_list */
+ if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) {
+ _params = &_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS];
+ _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE);
+ }
if (_pno_state->pno_mode & DHD_PNO_BATCH_MODE) {
_params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS];
/* clear resource if the BATCH MODE is on */
diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.h b/drivers/net/wireless/bcmdhd/dhd_pno.h
index 0cf1bf4..49a8fd2 100644
--- a/drivers/net/wireless/bcmdhd/dhd_pno.h
+++ b/drivers/net/wireless/bcmdhd/dhd_pno.h
@@ -104,6 +104,7 @@ typedef enum dhd_pno_mode {
DHD_PNO_HOTLIST_MODE = (1 << (2))
} dhd_pno_mode_t;
struct dhd_pno_ssid {
+ bool hidden;
uint32 SSID_len;
uchar SSID[DOT11_MAX_SSID_LEN];
struct list_head list;
@@ -209,7 +210,7 @@ extern int
dhd_dev_pno_stop_for_ssid(struct net_device *dev);
extern int
-dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid,
+dhd_dev_pno_set_for_ssid(struct net_device *dev, wlc_ssid_ext_t* ssids_local, int nssid,
uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan);
extern int
@@ -229,7 +230,7 @@ dhd_dev_pno_set_for_hotlist(struct net_device *dev, wl_pfn_bssid_t *p_pfn_bssid,
/* dhd pno fuctions */
extern int dhd_pno_stop_for_ssid(dhd_pub_t *dhd);
extern int dhd_pno_enable(dhd_pub_t *dhd, int enable);
-extern int dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_t* ssid_list, int nssid,
+extern int dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssid_list, int nssid,
uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan);
extern int dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params);
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
index 2d0f90e..4901a49 100644
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
@@ -313,6 +313,12 @@ typedef struct wlc_ssid {
uchar SSID[DOT11_MAX_SSID_LEN];
} wlc_ssid_t;
+typedef struct wlc_ssid_ext {
+ bool hidden;
+ uint32 SSID_len;
+ uchar SSID[DOT11_MAX_SSID_LEN];
+} wlc_ssid_ext_t;
+
#ifndef LINUX_POSTMOGRIFY_REMOVAL
#define MAX_PREFERRED_AP_NUM 5
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 4b1f149..742d873 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -401,7 +401,7 @@ exit:
#ifndef WL_SCHED_SCAN
static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
{
- wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
+ wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
int res = -1;
int nssid = 0;
cmd_tlv_t *cmd_tlv_temp;
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index adf7c33..11e5972 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -6424,6 +6424,23 @@ fail:
#define PNO_TIME 30
#define PNO_REPEAT 4
#define PNO_FREQ_EXPO_MAX 2
+static bool
+is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
+{
+ int i;
+
+ if (!ssid || !ssid_list)
+ return FALSE;
+
+ for (i = 0; i < count; i++) {
+ if (ssid->ssid_len == ssid_list[i].ssid_len) {
+ if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
static int
wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
struct net_device *dev,
@@ -6432,10 +6449,11 @@ wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
ushort pno_time = PNO_TIME;
int pno_repeat = PNO_REPEAT;
int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
- wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
+ wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
struct wl_priv *wl = wiphy_priv(wiphy);
struct cfg80211_ssid *ssid = NULL;
- int ssid_count = 0;
+ struct cfg80211_ssid *hidden_ssid_list = NULL;
+ int ssid_cnt = 0;
int i;
int ret = 0;
@@ -6454,30 +6472,29 @@ wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
memset(&ssids_local, 0, sizeof(ssids_local));
- if (request->n_match_sets > 0) {
- for (i = 0; i < request->n_match_sets; i++) {
- ssid = &request->match_sets[i].ssid;
- memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len);
- ssids_local[i].SSID_len = ssid->ssid_len;
- WL_PNO((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
- ssid_count++;
- }
- }
-
- if (request->n_ssids > 0) {
- for (i = 0; i < request->n_ssids; i++) {
- /* Active scan req for ssids */
- WL_PNO((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
-
- /* match_set ssids is a supert set of n_ssid list, so we need
- * not add these set seperately
- */
+ if (request->n_ssids > 0)
+ hidden_ssid_list = request->ssids;
+
+ for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
+ ssid = &request->match_sets[i].ssid;
+ /* No need to include null ssid */
+ if (ssid->ssid_len) {
+ memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid, ssid->ssid_len);
+ ssids_local[ssid_cnt].SSID_len = ssid->ssid_len;
+ if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
+ ssids_local[ssid_cnt].hidden = TRUE;
+ WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
+ } else {
+ ssids_local[ssid_cnt].hidden = FALSE;
+ WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
+ }
+ ssid_cnt++;
}
}
- if (ssid_count) {
- if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, request->n_match_sets,
- pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
+ if (ssid_cnt) {
+ if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt, pno_time,
+ pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
WL_ERR(("PNO setup failed!! ret=%d \n", ret));
return -EINVAL;
}
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h
index ca87b3c..e00b224 100644
--- a/drivers/net/wireless/bcmdhd/wldev_common.h
+++ b/drivers/net/wireless/bcmdhd/wldev_common.h
@@ -95,7 +95,7 @@ extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val);
extern int net_os_set_dtim_skip(struct net_device *dev, int val);
extern int net_os_set_suspend_disable(struct net_device *dev, int val);
extern int net_os_set_suspend(struct net_device *dev, int val, int force);
-extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid,
+extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_ext_t* ssid,
int max, int *bytes_left);
/* Get the link speed from dongle, speed is in kpbs */