static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) { struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev); ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__, reason_code); if (!ath6kl_cfg80211_ready(ar)) return -EIO; if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { ath6kl_err("busy, destroy in progress\n"); return -EBUSY; } if (down_interruptible(&ar->sem)) { ath6kl_err("busy, couldn't get access\n"); return -ERESTARTSYS; } ar->reconnect_flag = 0; ath6kl_disconnect(ar); memset(ar->ssid, 0, sizeof(ar->ssid)); ar->ssid_len = 0; if (!test_bit(SKIP_SCAN, &ar->flag)) memset(ar->req_bssid, 0, sizeof(ar->req_bssid)); up(&ar->sem); ar->sme_state = SME_DISCONNECTED; return 0; }
void disconnect_timer_handler(unsigned long ptr) { struct net_device *dev = (struct net_device *)ptr; struct ath6kl_vif *vif = netdev_priv(dev); ath6kl_init_profile_info(vif); ath6kl_disconnect(vif); }
static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev); if (!ath6kl_cfg80211_ready(ar)) return -EIO; ath6kl_disconnect(ar); memset(ar->ssid, 0, sizeof(ar->ssid)); ar->ssid_len = 0; return 0; }
static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { struct ath6kl *ar = ath6kl_priv(dev); int status; ar->sme_state = SME_CONNECTING; if (!ath6kl_cfg80211_ready(ar)) return -EIO; if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { ath6kl_err("destroy in progress\n"); return -EBUSY; } if (test_bit(SKIP_SCAN, &ar->flag) && ((sme->channel && sme->channel->center_freq == 0) || (sme->bssid && is_zero_ether_addr(sme->bssid)))) { ath6kl_err("SkipScan: channel or bssid invalid\n"); return -EINVAL; } if (down_interruptible(&ar->sem)) { ath6kl_err("busy, couldn't get access\n"); return -ERESTARTSYS; } if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { ath6kl_err("busy, destroy in progress\n"); up(&ar->sem); return -EBUSY; } if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) { /* * sleep until the command queue drains */ wait_event_interruptible_timeout(ar->event_wq, ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0, WMI_TIMEOUT); if (signal_pending(current)) { ath6kl_err("cmd queue drain timeout\n"); up(&ar->sem); return -EINTR; } } if (test_bit(CONNECTED, &ar->flag) && ar->ssid_len == sme->ssid_len && !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) { ar->reconnect_flag = true; status = ath6kl_wmi_reconnect_cmd(ar->wmi, ar->req_bssid, ar->ch_hint); up(&ar->sem); if (status) { ath6kl_err("wmi_reconnect_cmd failed\n"); return -EIO; } return 0; } else if (ar->ssid_len == sme->ssid_len && !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) { ath6kl_disconnect(ar); } memset(ar->ssid, 0, sizeof(ar->ssid)); ar->ssid_len = sme->ssid_len; memcpy(ar->ssid, sme->ssid, sme->ssid_len); if (sme->channel) ar->ch_hint = sme->channel->center_freq; memset(ar->req_bssid, 0, sizeof(ar->req_bssid)); if (sme->bssid && !is_broadcast_ether_addr(sme->bssid)) memcpy(ar->req_bssid, sme->bssid, sizeof(ar->req_bssid)); ath6kl_set_wpa_version(ar, sme->crypto.wpa_versions); status = ath6kl_set_auth_type(ar, sme->auth_type); if (status) { up(&ar->sem); return status; } if (sme->crypto.n_ciphers_pairwise) ath6kl_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true); else ath6kl_set_cipher(ar, 0, true); ath6kl_set_cipher(ar, sme->crypto.cipher_group, false); if (sme->crypto.n_akm_suites) ath6kl_set_key_mgmt(ar, sme->crypto.akm_suites[0]); if ((sme->key_len) && (ar->auth_mode == NONE_AUTH) && (ar->prwise_crypto == WEP_CRYPT)) { struct ath6kl_key *key = NULL; if (sme->key_idx < WMI_MIN_KEY_INDEX || sme->key_idx > WMI_MAX_KEY_INDEX) { ath6kl_err("key index %d out of bounds\n", sme->key_idx); up(&ar->sem); return -ENOENT; } key = &ar->keys[sme->key_idx]; key->key_len = sme->key_len; memcpy(key->key, sme->key, key->key_len); key->cipher = ar->prwise_crypto; ar->def_txkey_index = sme->key_idx; ath6kl_wmi_addkey_cmd(ar->wmi, sme->key_idx, ar->prwise_crypto, GROUP_USAGE | TX_USAGE, key->key_len, NULL, key->key, KEY_OP_INIT_VAL, NULL, NO_SYNC_WMIFLAG); } if (!ar->usr_bss_filter) { clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag); if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) { ath6kl_err("couldn't set bss filtering\n"); up(&ar->sem); return -EIO; } } ar->nw_type = ar->next_mode; ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: connect called with authmode %d dot11 auth %d" " PW crypto %d PW crypto len %d GRP crypto %d" " GRP crypto len %d channel hint %u\n", __func__, ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto, ar->prwise_crypto_len, ar->grp_crypto, ar->grp_crypto_len, ar->ch_hint); ar->reconnect_flag = 0; status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type, ar->dot11_auth_mode, ar->auth_mode, ar->prwise_crypto, ar->prwise_crypto_len, ar->grp_crypto, ar->grp_crypto_len, ar->ssid_len, ar->ssid, ar->req_bssid, ar->ch_hint, ar->connect_ctrl_flags); up(&ar->sem); if (status == -EINVAL) { memset(ar->ssid, 0, sizeof(ar->ssid)); ar->ssid_len = 0; ath6kl_err("invalid request\n"); return -ENOENT; } else if (status) { ath6kl_err("ath6kl_wmi_connect_cmd failed\n"); return -EIO; } if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) && ((ar->auth_mode == WPA_PSK_AUTH) || (ar->auth_mode == WPA2_PSK_AUTH))) { mod_timer(&ar->disconnect_timer, jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL)); } ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD; set_bit(CONNECT_PEND, &ar->flag); return 0; }