* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <typedefs.h>
-#include <linuxver.h>
+#include <linux/kernel.h>
+#include <linux/if_arp.h>
#include <osl.h>
#include <bcmutils.h>
#include <bcmendian.h>
#include <proto/ethernet.h>
-#include <linux/if_arp.h>
#include <asm/uaccess.h>
#include <dngl_stats.h>
#include <dhdioctl.h>
#include <wlioctl.h>
-#include <proto/ethernet.h>
-#include <dngl_stats.h>
-#include <dhd.h>
-
-#include <linux/kernel.h>
+#include <linux/kthread.h>
#include <linux/netdevice.h>
#include <linux/sched.h>
#include <linux/etherdevice.h>
u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
-#define WL_4329_FW_FILE "brcm/bcm4329-fullmac-4-218-248-5.bin"
-#define WL_4329_NVRAM_FILE "brcm/bcm4329-fullmac-4-218-248-5.txt"
+#define WL_4329_FW_FILE "brcm/bcm4329-fullmac-4.bin"
+#define WL_4329_NVRAM_FILE "brcm/bcm4329-fullmac-4.txt"
/*
** cfg80211_ops api/callback list
struct net_device *dev,
u8 key_idx);
static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, const u8 *mac_addr,
+ u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params);
static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, const u8 *mac_addr);
+ u8 key_idx, bool pairwise, const u8 *mac_addr);
static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, const u8 *mac_addr,
+ u8 key_idx, bool pairwise, const u8 *mac_addr,
void *cookie, void (*callback) (void *cookie,
struct
key_params *
static s32 wl_set_set_sharedkey(struct net_device *dev,
struct cfg80211_connect_params *sme);
static s32 wl_get_assoc_ies(struct wl_priv *wl);
+static void wl_ch_to_chanspec(int ch,
+ struct wl_join_params *join_params, size_t *join_params_size);
/*
** information element utilities
*/
static void wl_rst_ie(struct wl_priv *wl);
-static s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
+static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size);
static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size);
static u32 wl_get_ielen(struct wl_priv *wl);
static __used s32 wl_update_pmklist(struct net_device *dev,
struct wl_pmk_list *pmk_list, s32 err);
+static void wl_set_mpc(struct net_device *ndev, int mpc);
+
+/*
+* debufs support
+*/
+static int wl_debugfs_add_netdev_params(struct wl_priv *wl);
+static void wl_debugfs_remove_netdev(struct wl_priv *wl);
+
#define WL_PRIV_GET() \
({ \
struct wl_iface *ci; \
if (ssid && ssid->SSID_len)
params_size += sizeof(struct wlc_ssid);
- params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
+ params = kzalloc(params_size, GFP_KERNEL);
if (unlikely(!params))
return -ENOMEM;
memset(params, 0, params_size);
static s32 wl_do_iscan(struct wl_priv *wl)
{
struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
+ struct net_device *ndev = wl_to_ndev(wl);
struct wlc_ssid ssid;
+ s32 passive_scan;
s32 err = 0;
/* Broadcast scan by default */
iscan->state = WL_ISCAN_STATE_SCANING;
- if (wl->active_scan) {
- s32 passive_scan = 0;
- /* make it active scan */
- err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
- &passive_scan, sizeof(passive_scan));
- if (unlikely(err)) {
- WL_DBG(("error (%d)\n", err));
- return err;
- }
+ passive_scan = wl->active_scan ? 0 : 1;
+ err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
+ &passive_scan, sizeof(passive_scan));
+ if (unlikely(err)) {
+ WL_DBG(("error (%d)\n", err));
+ return err;
}
- wl->iscan_kickstart = TRUE;
+ wl_set_mpc(ndev, 0);
+ wl->iscan_kickstart = true;
wl_run_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
iscan->timer_on = 1;
struct wl_priv *wl = ndev_to_wl(ndev);
struct cfg80211_ssid *ssids;
struct wl_scan_req *sr = wl_to_sr(wl);
+ s32 passive_scan;
bool iscan_req;
bool spec_scan;
s32 err = 0;
return -EAGAIN;
}
- iscan_req = FALSE;
- spec_scan = FALSE;
+ iscan_req = false;
+ spec_scan = false;
if (request) { /* scan bss */
ssids = request->ssids;
if (wl->iscan_on && (!ssids || !ssids->ssid_len)) { /* for
* we do not iscan for
* specific scan request
*/
- iscan_req = TRUE;
+ iscan_req = true;
}
} else { /* scan in ibss */
/* we don't do iscan in ibss */
set_bit(WL_STATUS_SCANNING, &wl->status);
if (iscan_req) {
err = wl_do_iscan(wl);
- if (unlikely(err))
+ if (likely(!err))
return err;
else
goto scan_out;
ssids->ssid, ssids->ssid_len));
memset(&sr->ssid, 0, sizeof(sr->ssid));
sr->ssid.SSID_len =
- min(sizeof(sr->ssid.SSID), ssids->ssid_len);
+ min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
if (sr->ssid.SSID_len) {
memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
WL_DBG(("Specific scan ssid=\"%s\" len=%d\n",
sr->ssid.SSID, sr->ssid.SSID_len));
- spec_scan = TRUE;
+ spec_scan = true;
} else {
WL_DBG(("Broadcast scan\n"));
}
WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
- if (wl->active_scan) {
- s32 pssive_scan = 0;
- /* make it active scan */
- err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
- &pssive_scan, sizeof(pssive_scan));
- if (unlikely(err)) {
- WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n",
- err));
- goto scan_out;
- }
+ passive_scan = wl->active_scan ? 0 : 1;
+ err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+ &passive_scan, sizeof(passive_scan));
+ if (unlikely(err)) {
+ WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
+ goto scan_out;
}
+ wl_set_mpc(ndev, 0);
err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid,
sizeof(sr->ssid));
if (err) {
} else {
WL_ERR(("WLC_SCAN error (%d)\n", err));
}
+ wl_set_mpc(ndev, 1);
goto scan_out;
}
}
if (changed & WIPHY_PARAM_RETRY_LONG
&& (wl->conf->retry_long != wiphy->retry_long)) {
wl->conf->retry_long = wiphy->retry_long;
- err = wl_set_retry(ndev, wl->conf->retry_long, TRUE);
+ err = wl_set_retry(ndev, wl->conf->retry_long, true);
if (!err)
return err;
}
if (changed & WIPHY_PARAM_RETRY_SHORT
&& (wl->conf->retry_short != wiphy->retry_short)) {
wl->conf->retry_short = wiphy->retry_short;
- err = wl_set_retry(ndev, wl->conf->retry_short, FALSE);
+ err = wl_set_retry(ndev, wl->conf->retry_short, false);
if (!err) {
return err;
}
params->ssid, params->ssid_len);
}
if (bss) {
- wl->ibss_starter = FALSE;
+ wl->ibss_starter = false;
WL_DBG(("Found IBSS\n"));
} else {
- wl->ibss_starter = TRUE;
+ wl->ibss_starter = true;
}
chan = params->channel;
if (chan)
{
struct wl_priv *wl = wiphy_to_wl(wiphy);
struct ieee80211_channel *chan = sme->channel;
- struct wlc_ssid ssid;
+ struct wl_join_params join_params;
+ size_t join_params_size;
+
s32 err = 0;
CHECK_SYS_UP();
** Join with specific BSSID and cached SSID
** If SSID is zero join based on BSSID only
*/
- memset(&ssid, 0, sizeof(ssid));
- ssid.SSID_len = min(sizeof(ssid.SSID), sme->ssid_len);
- memcpy(ssid.SSID, sme->ssid, ssid.SSID_len);
- ssid.SSID_len = htod32(ssid.SSID_len);
- wl_update_prof(wl, NULL, &ssid, WL_PROF_SSID);
- if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
- WL_DBG(("ssid \"%s\", len (%d)\n", ssid.SSID, ssid.SSID_len));
- }
- err = wl_dev_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid));
+ memset(&join_params, 0, sizeof(join_params));
+ join_params_size = sizeof(join_params.ssid);
+
+ join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
+ memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
+ join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
+ wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
+ memcpy(&join_params.params.bssid, ðer_bcast, ETHER_ADDR_LEN);
+
+ wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
+ WL_DBG(("join_param_size %d\n", join_params_size));
+
+ if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
+ WL_DBG(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
+ join_params.ssid.SSID_len));
+ }
+ err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
if (unlikely(err)) {
WL_ERR(("error (%d)\n", err));
return err;
{
struct wl_priv *wl = wiphy_to_wl(wiphy);
scb_val_t scbval;
- bool act = FALSE;
+ bool act = false;
s32 err = 0;
WL_DBG(("Reason %d\n", reason_code));
key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
(ivptr[3] << 8) | ivptr[2];
key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
- key.iv_initialized = TRUE;
+ key.iv_initialized = true;
}
switch (params->cipher) {
static s32
wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, const u8 *mac_addr,
+ u8 key_idx, bool pairwise, const u8 *mac_addr,
struct key_params *params)
{
struct wl_wsec_key key;
static s32
wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, const u8 *mac_addr)
+ u8 key_idx, bool pairwise, const u8 *mac_addr)
{
struct wl_wsec_key key;
s32 err = 0;
static s32
wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
- u8 key_idx, const u8 *mac_addr, void *cookie,
+ u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
void (*callback) (void *cookie, struct key_params * params))
{
struct key_params params;
key.index = key_idx;
swap_key_to_BE(&key);
memset(¶ms, 0, sizeof(params));
- params.key_len = (u8) min(DOT11_MAX_KEY_SIZE, key.len);
+ params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
memcpy(params.key, key.data, params.key_len);
err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
{
struct wl_priv *wl = wiphy_to_wl(wiphy);
+ struct net_device *ndev = wl_to_ndev(wl);
s32 err = 0;
CHECK_SYS_UP();
set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
wl_term_iscan(wl);
if (wl->scan_request) {
- cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE means
+ cfg80211_scan_done(wl->scan_request, true); /* true means
abort */
+ wl_set_mpc(ndev, 1);
wl->scan_request = NULL;
}
clear_bit(WL_STATUS_SCANNING, &wl->status);
wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
s32 err)
{
- s8 eabuf[ETHER_ADDR_STR_LEN];
int i, j;
- memset(eabuf, 0, ETHER_ADDR_STR_LEN);
-
WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
- WL_DBG(("PMKID[%d]: %s =\n", i,
- bcm_ether_ntoa(&pmk_list->pmkids.pmkid[i].BSSID,
- eabuf)));
+ WL_DBG(("PMKID[%d]: %pM =\n", i,
+ &pmk_list->pmkids.pmkid[i].BSSID));
for (j = 0; j < WPA2_PMKID_LEN; j++) {
WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
}
struct cfg80211_pmksa *pmksa)
{
struct wl_priv *wl = wiphy_to_wl(wiphy);
- s8 eabuf[ETHER_ADDR_STR_LEN];
s32 err = 0;
int i;
CHECK_SYS_UP();
- memset(eabuf, 0, ETHER_ADDR_STR_LEN);
for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
ETHER_ADDR_LEN))
} else {
err = -EINVAL;
}
- WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %s =\n",
- bcm_ether_ntoa(&wl->pmk_list->pmkids.
- pmkid[wl->pmk_list->pmkids.npmkid].BSSID,
- eabuf)));
+ WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
+ &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID));
for (i = 0; i < WPA2_PMKID_LEN; i++) {
WL_DBG(("%02x\n",
wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].
struct cfg80211_pmksa *pmksa)
{
struct wl_priv *wl = wiphy_to_wl(wiphy);
- s8 eabuf[ETHER_ADDR_STR_LEN];
struct _pmkid_list pmkid;
s32 err = 0;
int i;
CHECK_SYS_UP();
- memset(eabuf, 0, ETHER_ADDR_STR_LEN);
memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
- WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %s =\n",
- bcm_ether_ntoa(&pmkid.pmkid[0].BSSID, eabuf)));
+ WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
+ &pmkid.pmkid[0].BSSID));
for (i = 0; i < WPA2_PMKID_LEN; i++) {
WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
}
struct ieee80211_supported_band *band;
struct wl_cfg80211_bss_info *notif_bss_info;
struct wl_scan_req *sr = wl_to_sr(wl);
+ struct beacon_proberesp *beacon_proberesp;
+ s32 mgmt_type;
u32 signal;
u32 freq;
s32 err = 0;
return -ENOMEM;
}
mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
- notif_bss_info->channel = CHSPEC_CHANNEL(bi->chanspec);
+ notif_bss_info->channel =
+ bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec);
+
if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
band = wiphy->bands[IEEE80211_BAND_2GHZ];
else
band = wiphy->bands[IEEE80211_BAND_5GHZ];
notif_bss_info->rssi = bi->RSSI;
memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
+ mgmt_type = wl->active_scan ?
+ IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_PROBE_RESP);
- }
- mgmt->u.probe_resp.timestamp = 0;
- mgmt->u.probe_resp.beacon_int = cpu_to_le16(bi->beacon_period);
- mgmt->u.probe_resp.capab_info = cpu_to_le16(bi->capability);
+ mgmt_type);
+ }
+ beacon_proberesp = wl->active_scan ?
+ (struct beacon_proberesp *)&mgmt->u.probe_resp :
+ (struct beacon_proberesp *)&mgmt->u.beacon;
+ beacon_proberesp->timestamp = 0;
+ beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
+ beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
wl_rst_ie(wl);
- wl_add_ie(wl, WLAN_EID_SSID, bi->SSID_len, bi->SSID);
- wl_add_ie(wl, WLAN_EID_SUPP_RATES, bi->rateset.count,
- bi->rateset.rates);
+ /*
+ * wl_add_ie is not necessary because it can only add duplicated
+ * SSID, rate information to frame_buf
+ */
+ /*
+ * wl_add_ie(wl, WLAN_EID_SSID, bi->SSID_len, bi->SSID);
+ * wl_add_ie(wl, WLAN_EID_SUPP_RATES, bi->rateset.count,
+ * bi->rateset.rates);
+ */
wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
- wl_cp_ie(wl, mgmt->u.probe_resp.variable, WL_BSS_INFO_MAX -
+ wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
offsetof(struct wl_cfg80211_bss_info, frame_buf));
notif_bss_info->frame_len =
offsetof(struct ieee80211_mgmt,
- u.probe_resp.variable) + wl_get_ielen(wl);
+ u.beacon.variable) + wl_get_ielen(wl);
freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
channel = ieee80211_get_channel(wiphy, freq);
- WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x\n",
+ WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
bi->SSID,
notif_bss_info->rssi, notif_bss_info->channel,
- mgmt->u.probe_resp.capab_info));
+ mgmt->u.beacon.capab_info, &bi->BSSID));
signal = notif_bss_info->rssi * 100;
if (unlikely(!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
u32 event = ntoh32(e->event_type);
u16 flags = ntoh16(e->flags);
- if (event == WLC_E_JOIN || event == WLC_E_ASSOC_IND
- || event == WLC_E_REASSOC_IND) {
- return TRUE;
- } else if (event == WLC_E_LINK) {
+ if (event == WLC_E_LINK) {
if (flags & WLC_EVENT_MSG_LINK) {
if (wl_is_ibssmode(wl)) {
if (wl_is_ibssstarter(wl)) {
}
} else {
-
+ return true;
}
}
}
- return FALSE;
+ return false;
}
static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
u16 flags = ntoh16(e->flags);
if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
- return TRUE;
+ return true;
} else if (event == WLC_E_LINK) {
if (!(flags & WLC_EVENT_MSG_LINK))
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
if (event == WLC_E_SET_SSID || event == WLC_E_LINK) {
if (status == WLC_E_STATUS_NO_NETWORKS)
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
static s32
GFP_KERNEL);
WL_DBG(("joined in IBSS network\n"));
} else {
- wl_bss_connect_done(wl, ndev, e, data, TRUE);
+ wl_bss_connect_done(wl, ndev, e, data, true);
WL_DBG(("joined in BSS network \"%s\"\n",
((struct wlc_ssid *)
wl_read_prof(wl, WL_PROF_SSID))->SSID));
}
- act = TRUE;
+ act = true;
wl_update_prof(wl, e, &act, WL_PROF_ACT);
} else if (wl_is_linkdown(wl, e)) {
cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
wl_link_down(wl);
wl_init_prof(wl->profile);
} else if (wl_is_nonetwork(wl, e)) {
- wl_bss_connect_done(wl, ndev, e, data, FALSE);
+ wl_bss_connect_done(wl, ndev, e, data, false);
}
return err;
s32 err = 0;
wl_bss_roaming_done(wl, ndev, e, data);
- act = TRUE;
+ act = true;
wl_update_prof(wl, e, &act, WL_PROF_ACT);
return err;
return err;
}
+static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
+ size_t *join_params_size)
+{
+ chanspec_t chanspec = 0;
+
+ if (ch != 0) {
+ join_params->params.chanspec_num = 1;
+ join_params->params.chanspec_list[0] = ch;
+
+ if (join_params->params.chanspec_list[0])
+ chanspec |= WL_CHANSPEC_BAND_2G;
+ else
+ chanspec |= WL_CHANSPEC_BAND_5G;
+
+ chanspec |= WL_CHANSPEC_BW_20;
+ chanspec |= WL_CHANSPEC_CTL_SB_NONE;
+
+ *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
+ join_params->params.chanspec_num * sizeof(chanspec_t);
+
+ join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
+ join_params->params.chanspec_list[0] |= chanspec;
+ join_params->params.chanspec_list[0] =
+ htodchanspec(join_params->params.chanspec_list[0]);
+
+ join_params->params.chanspec_num =
+ htod32(join_params->params.chanspec_num);
+
+ WL_DBG(("join_params->params.chanspec_list[0]= %#X, channel %d, chanspec %#X\n",
+ join_params->params.chanspec_list[0], ch, chanspec));
+ }
+}
+
static s32 wl_update_bss_info(struct wl_priv *wl)
{
struct cfg80211_bss *bss;
struct wl_bss_info *bi;
struct wlc_ssid *ssid;
+ struct bcm_tlv *tim;
+ u16 beacon_interval;
+ u8 dtim_period;
+ size_t ie_len;
+ u8 *ie;
s32 err = 0;
if (wl_is_ibssmode(wl))
err = wl_inform_single_bss(wl, bi);
if (unlikely(err))
goto update_bss_info_out;
+
+ ie = ((u8 *)bi) + bi->ie_offset;
+ ie_len = bi->ie_length;
+ beacon_interval = cpu_to_le16(bi->beacon_period);
} else {
- WL_DBG(("Found the AP in the list - "
- "BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
- bss->bssid[0], bss->bssid[1], bss->bssid[2],
- bss->bssid[3], bss->bssid[4], bss->bssid[5]));
+ WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
+ ie = bss->information_elements;
+ ie_len = bss->len_information_elements;
+ beacon_interval = bss->beacon_interval;
cfg80211_put_bss(bss);
}
+ tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
+ if (tim) {
+ dtim_period = tim->data[1];
+ } else {
+ /*
+ * active scan was done so we could not get dtim
+ * information out of probe response.
+ * so we speficially query dtim information to dongle.
+ */
+ err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_DTIMPRD,
+ &dtim_period, sizeof(dtim_period));
+ if (unlikely(err)) {
+ WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
+ goto update_bss_info_out;
+ }
+ }
+
+ wl_update_prof(wl, NULL, &beacon_interval, WL_PROF_BEACONINT);
+ wl_update_prof(wl, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
+
update_bss_info_out:
rtnl_unlock();
return err;
scan_done_out:
if (wl->scan_request) {
- cfg80211_scan_done(wl->scan_request, FALSE);
+ cfg80211_scan_done(wl->scan_request, false);
+ wl_set_mpc(ndev, 1);
wl->scan_request = NULL;
}
rtnl_unlock();
static s32 wl_init_priv_mem(struct wl_priv *wl)
{
- wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
+ wl->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
if (unlikely(!wl->scan_results)) {
WL_ERR(("Scan results alloc failed\n"));
goto init_priv_mem_out;
}
- wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
+ wl->conf = kzalloc(sizeof(*wl->conf), GFP_KERNEL);
if (unlikely(!wl->conf)) {
WL_ERR(("wl_conf alloc failed\n"));
goto init_priv_mem_out;
}
- wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL);
+ wl->profile = kzalloc(sizeof(*wl->profile), GFP_KERNEL);
if (unlikely(!wl->profile)) {
WL_ERR(("wl_profile alloc failed\n"));
goto init_priv_mem_out;
}
- wl->bss_info = (void *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+ wl->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
if (unlikely(!wl->bss_info)) {
WL_ERR(("Bss information alloc failed\n"));
goto init_priv_mem_out;
}
- wl->scan_req_int =
- (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
+ wl->scan_req_int = kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
if (unlikely(!wl->scan_req_int)) {
WL_ERR(("Scan req alloc failed\n"));
goto init_priv_mem_out;
}
- wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
+ wl->ioctl_buf = kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
if (unlikely(!wl->ioctl_buf)) {
WL_ERR(("Ioctl buf alloc failed\n"));
goto init_priv_mem_out;
}
- wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
+ wl->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
if (unlikely(!wl->extra_buf)) {
WL_ERR(("Extra buf alloc failed\n"));
goto init_priv_mem_out;
}
- wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
+ wl->iscan = kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
if (unlikely(!wl->iscan)) {
WL_ERR(("Iscan buf alloc failed\n"));
goto init_priv_mem_out;
}
- wl->fw = (void *)kzalloc(sizeof(*wl->fw), GFP_KERNEL);
+ wl->fw = kzalloc(sizeof(*wl->fw), GFP_KERNEL);
if (unlikely(!wl->fw)) {
WL_ERR(("fw object alloc failed\n"));
goto init_priv_mem_out;
}
- wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
+ wl->pmk_list = kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
if (unlikely(!wl->pmk_list)) {
WL_ERR(("pmk list alloc failed\n"));
goto init_priv_mem_out;
static s32 wl_create_event_handler(struct wl_priv *wl)
{
sema_init(&wl->event_sync, 0);
- init_completion(&wl->event_exit);
- wl->event_pid = kernel_thread(wl_event_handler, wl, 0);
- if (unlikely(wl->event_pid < 0)) {
+ wl->event_tsk = kthread_run(wl_event_handler, wl, "wl_event_handler");
+ if (IS_ERR(wl->event_tsk)) {
+ wl->event_tsk = NULL;
WL_ERR(("failed to create event thread\n"));
return -ENOMEM;
}
- WL_DBG(("pid %d\n", wl->event_pid));
return 0;
}
static void wl_destroy_event_handler(struct wl_priv *wl)
{
- if (wl->event_pid >= 0) {
- KILL_PROC(wl->event_pid, SIGTERM);
- wait_for_completion(&wl->event_exit);
+ if (wl->event_tsk) {
+ send_sig(SIGTERM, wl->event_tsk, 1);
+ kthread_stop(wl->event_tsk);
+ wl->event_tsk = NULL;
}
}
{
struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
- if (wl->iscan_on && iscan->pid >= 0) {
+ if (wl->iscan_on && iscan->tsk) {
iscan->state = WL_ISCAN_STATE_IDLE;
- KILL_PROC(iscan->pid, SIGTERM);
- wait_for_completion(&iscan->exited);
- iscan->pid = -1;
+ send_sig(SIGTERM, iscan->tsk, 1);
+ kthread_stop(iscan->tsk);
+ iscan->tsk = NULL;
}
}
static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
{
struct wl_priv *wl = iscan_to_wl(iscan);
+ struct net_device *ndev = wl_to_ndev(wl);
if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
WL_ERR(("Scan complete while device not scanning\n"));
}
if (likely(wl->scan_request)) {
cfg80211_scan_done(wl->scan_request, aborted);
+ wl_set_mpc(ndev, 1);
wl->scan_request = NULL;
}
- wl->iscan_kickstart = FALSE;
+ wl->iscan_kickstart = false;
}
static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
iscan->state = WL_ISCAN_STATE_IDLE;
rtnl_lock();
wl_inform_bss(wl);
- wl_notify_iscan_complete(iscan, FALSE);
+ wl_notify_iscan_complete(iscan, false);
rtnl_unlock();
return err;
iscan->state = WL_ISCAN_STATE_IDLE;
rtnl_lock();
- wl_notify_iscan_complete(iscan, TRUE);
+ wl_notify_iscan_complete(iscan, true);
rtnl_unlock();
return err;
int err = 0;
sched_setscheduler(current, SCHED_FIFO, ¶m);
+ allow_signal(SIGTERM);
status = WL_SCAN_RESULTS_PARTIAL;
while (likely(!down_interruptible(&iscan->sync))) {
+ if (kthread_should_stop())
+ break;
if (iscan->timer_on) {
del_timer_sync(&iscan->timer);
iscan->timer_on = 0;
del_timer_sync(&iscan->timer);
iscan->timer_on = 0;
}
- complete_and_exit(&iscan->exited, 0);
+ WL_DBG(("%s was terminated\n", __func__));
return 0;
}
struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
int err = 0;
- if (wl->iscan_on && iscan->pid < 0) {
+ if (wl->iscan_on && !iscan->tsk) {
iscan->state = WL_ISCAN_STATE_IDLE;
sema_init(&iscan->sync, 0);
- init_completion(&iscan->exited);
- iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0);
- if (unlikely(iscan->pid < 0)) {
+ iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
+ if (IS_ERR(iscan->tsk)) {
WL_ERR(("Could not create iscan thread\n"));
+ iscan->tsk = NULL;
return -ENOMEM;
}
}
iscan->timer.data = (unsigned long) iscan;
iscan->timer.function = wl_iscan_timer;
sema_init(&iscan->sync, 0);
- init_completion(&iscan->exited);
- iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0);
- if (unlikely(iscan->pid < 0)) {
+ iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
+ if (IS_ERR(iscan->tsk)) {
WL_ERR(("Could not create iscan thread\n"));
+ iscan->tsk = NULL;
return -ENOMEM;
}
iscan->data = wl;
wl->scan_request = NULL;
wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
-#ifndef WL_ISCAN_DISABLED
- wl->iscan_on = TRUE; /* iscan on & off switch.
+ wl->iscan_on = true; /* iscan on & off switch.
we enable iscan per default */
-#else
- wl->iscan_on = FALSE;
-#endif /* WL_ISCAN_DISABLED */
-#ifndef WL_ROAM_DISABLED
- wl->roam_on = TRUE; /* roam on & off switch.
+ wl->roam_on = false; /* roam on & off switch.
we enable roam per default */
-#else
- wl->roam_on = FALSE;
-#endif /* WL_ROAM_DISABLED */
- wl->iscan_kickstart = FALSE;
- wl->active_scan = TRUE; /* we do active scan for
+ wl->iscan_kickstart = false;
+ wl->active_scan = true; /* we do active scan for
specific scan per default */
- wl->dongle_up = FALSE; /* dongle is not up yet */
+ wl->dongle_up = false; /* dongle is not up yet */
wl_init_eq(wl);
err = wl_init_priv_mem(wl);
if (unlikely(err))
static void wl_deinit_priv(struct wl_priv *wl)
{
wl_destroy_event_handler(wl);
- wl->dongle_up = FALSE; /* dongle down */
+ wl->dongle_up = false; /* dongle down */
wl_flush_eq(wl);
wl_link_down(wl);
wl_term_iscan(wl);
ci = (struct wl_iface *)wl_to_ci(wl);
ci->wl = wl;
ndev->ieee80211_ptr = wdev;
+ SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
wdev->netdev = ndev;
err = wl_init_priv(wl);
if (unlikely(err)) {
struct wl_event_q *e;
sched_setscheduler(current, SCHED_FIFO, ¶m);
+ allow_signal(SIGTERM);
while (likely(!down_interruptible(&wl->event_sync))) {
+ if (kthread_should_stop())
+ break;
e = wl_deq_event(wl);
if (unlikely(!e)) {
WL_ERR(("eqeue empty..\n"));
}
wl_put_event(e);
}
- complete_and_exit(&wl->event_exit, 0);
+ WL_DBG(("%s was terminated\n", __func__));
+ return 0;
}
void
static s32 wl_pattern_atoh(s8 *src, s8 *dst)
{
-#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
int i;
if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
WL_ERR(("Mask invalid format. Needs to start with 0x\n"));
char num[3];
strncpy(num, src, 2);
num[2] = '\0';
- dst[i] = (u8) strtoul(num, NULL, 16);
+ dst[i] = (u8) simple_strtoul(num, NULL, 16);
src += 2;
}
return i;
if (need_lock)
rtnl_unlock();
- wl->dongle_up = TRUE;
+ wl->dongle_up = true;
return err;
{
s32 err = 0;
- err = wl_config_dongle(wl, FALSE);
+ wl_debugfs_add_netdev_params(wl);
+
+ err = wl_config_dongle(wl, false);
if (unlikely(err))
return err;
set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
wl_term_iscan(wl);
if (wl->scan_request) {
- cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE
+ cfg80211_scan_done(wl->scan_request, true); /* true
means abort */
+ /* wl_set_mpc(wl_to_ndev(wl), 1); */ /* BUG
+ * this operation cannot help
+ * but here because sdio
+ * is already down through
+ * rmmod process.
+ * Need to figure out how to
+ * address this issue
+ */
wl->scan_request = NULL;
}
clear_bit(WL_STATUS_READY, &wl->status);
clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
clear_bit(WL_STATUS_CONNECTED, &wl->status);
+ wl_debugfs_remove_netdev(wl);
+
return err;
}
memcpy(&wl->profile->sec, data, sizeof(wl->profile->sec));
break;
case WL_PROF_ACT:
- wl->profile->active = *(bool *) data;
+ wl->profile->active = *(bool *)data;
+ break;
+ case WL_PROF_BEACONINT:
+ wl->profile->beacon_interval = *(u16 *)data;
+ break;
+ case WL_PROF_DTIMPERIOD:
+ wl->profile->dtim_period = *(u8 *)data;
break;
default:
WL_ERR(("unsupported item (%d)\n", item));
ie->offset = 0;
}
-static s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
+static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
{
struct wl_ie *ie = wl_to_ie(wl);
s32 err = 0;
static void wl_link_up(struct wl_priv *wl)
{
- wl->link_up = TRUE;
+ wl->link_up = true;
}
static void wl_link_down(struct wl_priv *wl)
{
struct wl_connect_info *conn_info = wl_to_conn(wl);
- wl->link_up = FALSE;
+ wl->link_up = false;
kfree(conn_info->req_ie);
conn_info->req_ie = NULL;
conn_info->req_ie_len = 0;
strcpy(wl->fw->nvram_name, WL_4329_NVRAM_FILE);
return wl->fw->nvram_name;
}
+
+static void wl_set_mpc(struct net_device *ndev, int mpc)
+{
+ s32 err = 0;
+
+ err = wl_dev_intvar_set(ndev, "mpc", mpc);
+ if (unlikely(err)) {
+ WL_ERR(("fail to set mpc\n"));
+ return;
+ }
+ WL_DBG(("MPC : %d\n", mpc));
+}
+
+static int wl_debugfs_add_netdev_params(struct wl_priv *wl)
+{
+ char buf[10+IFNAMSIZ];
+ struct dentry *fd;
+ s32 err = 0;
+
+ sprintf(buf, "netdev:%s", wl_to_ndev(wl)->name);
+ wl->debugfsdir = debugfs_create_dir(buf, wl_to_wiphy(wl)->debugfsdir);
+
+ fd = debugfs_create_u16("beacon_int", S_IRUGO, wl->debugfsdir,
+ (u16 *)&wl->profile->beacon_interval);
+ if (!fd) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ fd = debugfs_create_u8("dtim_period", S_IRUGO, wl->debugfsdir,
+ (u8 *)&wl->profile->dtim_period);
+ if (!fd) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+err_out:
+ return err;
+}
+
+static void wl_debugfs_remove_netdev(struct wl_priv *wl)
+{
+ debugfs_remove_recursive(wl->debugfsdir);
+ wl->debugfsdir = NULL;
+}