diff options
Diffstat (limited to 'drivers/staging/wilc1000')
-rw-r--r-- | drivers/staging/wilc1000/Makefile | 2 | ||||
-rw-r--r-- | drivers/staging/wilc1000/host_interface.c | 1164 | ||||
-rw-r--r-- | drivers/staging/wilc1000/host_interface.h | 165 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_mon.c (renamed from drivers/staging/wilc1000/linux_mon.c) | 77 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_netdev.c (renamed from drivers/staging/wilc1000/linux_wlan.c) | 430 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_sdio.c | 187 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_spi.c | 4 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 644 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_wfi_cfgoperations.h | 7 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_wfi_netdevice.h | 14 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_wlan.c | 52 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_wlan.h | 38 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_wlan_cfg.c | 39 | ||||
-rw-r--r-- | drivers/staging/wilc1000/wilc_wlan_if.h | 40 |
14 files changed, 975 insertions, 1888 deletions
diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile index 72a4daa05fdb..2ad3feed9725 100644 --- a/drivers/staging/wilc1000/Makefile +++ b/drivers/staging/wilc1000/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_WILC1000) += wilc1000.o ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \ -DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\" -wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \ +wilc1000-objs := wilc_wfi_cfgoperations.o wilc_netdev.o wilc_mon.o \ host_interface.o wilc_wlan_cfg.o wilc_wlan.o obj-$(CONFIG_WILC1000_SDIO) += wilc1000-sdio.o diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3d0badc34825..4dd9a20f6a0b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -6,25 +6,23 @@ #include "wilc_wfi_netdevice.h" -#define HOST_IF_SCAN_TIMEOUT 4000 -#define HOST_IF_CONNECT_TIMEOUT 9500 +#define WILC_HIF_SCAN_TIMEOUT_MS 4000 +#define WILC_HIF_CONNECT_TIMEOUT_MS 9500 -#define FALSE_FRMWR_CHANNEL 100 +#define WILC_FALSE_FRMWR_CHANNEL 100 +#define WILC_MAX_RATES_SUPPORTED 12 -#define REAL_JOIN_REQ 0 - -struct rcvd_async_info { - u8 *buffer; - u32 len; +struct wilc_rcvd_mac_info { + u8 status; }; -struct set_multicast { - bool enabled; +struct wilc_set_multicast { + u32 enabled; u32 cnt; u8 *mc_list; }; -struct del_all_sta { +struct wilc_del_all_sta { u8 assoc_sta; u8 mac[WILC_MAX_NUM_STA][ETH_ALEN]; }; @@ -71,16 +69,16 @@ struct wilc_gtk_key { u8 key[0]; } __packed; -union message_body { - struct rcvd_net_info net_info; - struct rcvd_async_info async_info; - struct set_multicast multicast_info; - struct remain_ch remain_on_ch; +union wilc_message_body { + struct wilc_rcvd_net_info net_info; + struct wilc_rcvd_mac_info mac_info; + struct wilc_set_multicast mc_info; + struct wilc_remain_ch remain_on_ch; char *data; }; struct host_if_msg { - union message_body body; + union wilc_message_body body; struct wilc_vif *vif; struct work_struct work; void (*fn)(struct work_struct *ws); @@ -88,37 +86,50 @@ struct host_if_msg { bool is_sync; }; -struct join_bss_param { - enum bss_types bss_type; +struct wilc_noa_opp_enable { + u8 ct_window; + u8 cnt; + __le32 duration; + __le32 interval; + __le32 start_time; +} __packed; + +struct wilc_noa_opp_disable { + u8 cnt; + __le32 duration; + __le32 interval; + __le32 start_time; +} __packed; + +struct wilc_join_bss_param { + char ssid[IEEE80211_MAX_SSID_LEN]; + u8 ssid_terminator; + u8 bss_type; + u8 ch; + __le16 cap_info; + u8 sa[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + __le16 beacon_period; u8 dtim_period; - u16 beacon_period; - u16 cap_info; - u8 bssid[6]; - char ssid[MAX_SSID_LEN]; - u8 ssid_len; - u8 supp_rates[MAX_RATES_SUPPORTED + 1]; - u8 ht_capable; + u8 supp_rates[WILC_MAX_RATES_SUPPORTED + 1]; u8 wmm_cap; u8 uapsd_cap; - bool rsn_found; + u8 ht_capable; + u8 rsn_found; u8 rsn_grp_policy; u8 mode_802_11i; - u8 rsn_pcip_policy[3]; - u8 rsn_auth_policy[3]; + u8 p_suites[3]; + u8 akm_suites[3]; u8 rsn_cap[2]; - u32 tsf; u8 noa_enabled; - u8 opp_enabled; - u8 ct_window; - u8 cnt; + __le32 tsf_lo; u8 idx; - u8 duration[4]; - u8 interval[4]; - u8 start_time[4]; -}; - -static struct host_if_drv *terminated_handle; -static struct mutex hif_deinit_lock; + u8 opp_enabled; + union { + struct wilc_noa_opp_disable opp_dis; + struct wilc_noa_opp_enable opp_en; + }; +} __packed; /* 'msg' should be free by the caller for syc */ static struct host_if_msg* @@ -185,7 +196,7 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt) u8 abort_running_scan; struct wid wid; struct host_if_drv *hif_drv = vif->hif_drv; - struct user_scan_req *scan_req; + struct wilc_user_scan_req *scan_req; if (evt == SCAN_EVENT_ABORTED) { abort_running_scan = 1; @@ -210,7 +221,7 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt) scan_req = &hif_drv->usr_scan_req; if (scan_req->scan_result) { - scan_req->scan_result(evt, NULL, scan_req->arg, NULL); + scan_req->scan_result(evt, NULL, scan_req->arg); scan_req->scan_result = NULL; } @@ -218,9 +229,10 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt) } int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result scan_result, void *user_arg, - struct hidden_network *hidden_net) + u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, + void (*scan_result_fn)(enum scan_event, + struct wilc_rcvd_net_info *, void *), + void *user_arg, struct wilc_probe_ssid *search) { int result = 0; struct wid wid_list[5]; @@ -228,7 +240,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u32 i; u8 *buffer; u8 valuesize = 0; - u8 *hdn_ntwk_wid_val = NULL; + u8 *search_ssid_vals = NULL; struct host_if_drv *hif_drv = vif->hif_drv; if (hif_drv->hif_state >= HOST_IF_SCANNING && @@ -246,26 +258,24 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, hif_drv->usr_scan_req.ch_cnt = 0; - if (hidden_net) { - wid_list[index].id = WID_SSID_PROBE_REQ; - wid_list[index].type = WID_STR; - - for (i = 0; i < hidden_net->n_ssids; i++) - valuesize += ((hidden_net->net_info[i].ssid_len) + 1); - hdn_ntwk_wid_val = kmalloc(valuesize + 1, GFP_KERNEL); - wid_list[index].val = hdn_ntwk_wid_val; - if (wid_list[index].val) { + if (search) { + for (i = 0; i < search->n_ssids; i++) + valuesize += ((search->ssid_info[i].ssid_len) + 1); + search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL); + if (search_ssid_vals) { + wid_list[index].id = WID_SSID_PROBE_REQ; + wid_list[index].type = WID_STR; + wid_list[index].val = search_ssid_vals; buffer = wid_list[index].val; - *buffer++ = hidden_net->n_ssids; + *buffer++ = search->n_ssids; - for (i = 0; i < hidden_net->n_ssids; i++) { - *buffer++ = hidden_net->net_info[i].ssid_len; - memcpy(buffer, hidden_net->net_info[i].ssid, - hidden_net->net_info[i].ssid_len); - buffer += hidden_net->net_info[i].ssid_len; + for (i = 0; i < search->n_ssids; i++) { + *buffer++ = search->ssid_info[i].ssid_len; + memcpy(buffer, search->ssid_info[i].ssid, + search->ssid_info[i].ssid_len); + buffer += search->ssid_info[i].ssid_len; } - wid_list[index].size = (s32)(valuesize + 1); index++; } @@ -311,16 +321,16 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, goto error; } - hif_drv->usr_scan_req.scan_result = scan_result; + hif_drv->usr_scan_req.scan_result = scan_result_fn; hif_drv->usr_scan_req.arg = user_arg; hif_drv->scan_timer_vif = vif; mod_timer(&hif_drv->scan_timer, - jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT)); + jiffies + msecs_to_jiffies(WILC_HIF_SCAN_TIMEOUT_MS)); error: - if (hidden_net) { - kfree(hidden_net->net_info); - kfree(hdn_ntwk_wid_val); + if (search) { + kfree(search->ssid_info); + kfree(search_ssid_vals); } return result; @@ -329,35 +339,16 @@ error: static int wilc_send_connect_wid(struct wilc_vif *vif) { int result = 0; - struct wid wid_list[8]; - u32 wid_cnt = 0, dummyval = 0; - u8 *cur_byte = NULL; + struct wid wid_list[4]; + u32 wid_cnt = 0; struct host_if_drv *hif_drv = vif->hif_drv; - struct user_conn_req *conn_attr = &hif_drv->usr_conn_req; - struct join_bss_param *bss_param = hif_drv->usr_conn_req.param; - - wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT; - wid_list[wid_cnt].type = WID_INT; - wid_list[wid_cnt].size = sizeof(u32); - wid_list[wid_cnt].val = (s8 *)(&(dummyval)); - wid_cnt++; - - wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT; - wid_list[wid_cnt].type = WID_INT; - wid_list[wid_cnt].size = sizeof(u32); - wid_list[wid_cnt].val = (s8 *)(&(dummyval)); - wid_cnt++; - - wid_list[wid_cnt].id = WID_FAILED_COUNT; - wid_list[wid_cnt].type = WID_INT; - wid_list[wid_cnt].size = sizeof(u32); - wid_list[wid_cnt].val = (s8 *)(&(dummyval)); - wid_cnt++; + struct wilc_conn_info *conn_attr = &hif_drv->conn_info; + struct wilc_join_bss_param *bss_param = conn_attr->param; wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE; wid_list[wid_cnt].type = WID_BIN_DATA; - wid_list[wid_cnt].val = conn_attr->ies; - wid_list[wid_cnt].size = conn_attr->ies_len; + wid_list[wid_cnt].val = conn_attr->req_ies; + wid_list[wid_cnt].size = conn_attr->req_ies_len; wid_cnt++; wid_list[wid_cnt].id = WID_11I_MODE; @@ -374,97 +365,8 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED; wid_list[wid_cnt].type = WID_STR; - wid_list[wid_cnt].size = 112; - wid_list[wid_cnt].val = kmalloc(wid_list[wid_cnt].size, GFP_KERNEL); - - if (!wid_list[wid_cnt].val) { - result = -EFAULT; - goto error; - } - - cur_byte = wid_list[wid_cnt].val; - - if (conn_attr->ssid) { - memcpy(cur_byte, conn_attr->ssid, conn_attr->ssid_len); - cur_byte[conn_attr->ssid_len] = '\0'; - } - cur_byte += MAX_SSID_LEN; - *(cur_byte++) = WILC_FW_BSS_TYPE_INFRA; - - if (conn_attr->ch >= 1 && conn_attr->ch <= 14) { - *(cur_byte++) = conn_attr->ch; - } else { - netdev_err(vif->ndev, "Channel out of range\n"); - *(cur_byte++) = 0xFF; - } - put_unaligned_le16(bss_param->cap_info, cur_byte); - cur_byte += 2; - - if (conn_attr->bssid) - memcpy(cur_byte, conn_attr->bssid, 6); - cur_byte += 6; - - if (conn_attr->bssid) - memcpy(cur_byte, conn_attr->bssid, 6); - cur_byte += 6; - - put_unaligned_le16(bss_param->beacon_period, cur_byte); - cur_byte += 2; - *(cur_byte++) = bss_param->dtim_period; - - memcpy(cur_byte, bss_param->supp_rates, MAX_RATES_SUPPORTED + 1); - cur_byte += (MAX_RATES_SUPPORTED + 1); - - *(cur_byte++) = bss_param->wmm_cap; - *(cur_byte++) = bss_param->uapsd_cap; - - *(cur_byte++) = bss_param->ht_capable; - conn_attr->ht_capable = bss_param->ht_capable; - - *(cur_byte++) = bss_param->rsn_found; - *(cur_byte++) = bss_param->rsn_grp_policy; - *(cur_byte++) = bss_param->mode_802_11i; - - memcpy(cur_byte, bss_param->rsn_pcip_policy, - sizeof(bss_param->rsn_pcip_policy)); - cur_byte += sizeof(bss_param->rsn_pcip_policy); - - memcpy(cur_byte, bss_param->rsn_auth_policy, - sizeof(bss_param->rsn_auth_policy)); - cur_byte += sizeof(bss_param->rsn_auth_policy); - - memcpy(cur_byte, bss_param->rsn_cap, sizeof(bss_param->rsn_cap)); - cur_byte += sizeof(bss_param->rsn_cap); - - *(cur_byte++) = REAL_JOIN_REQ; - *(cur_byte++) = bss_param->noa_enabled; - - if (bss_param->noa_enabled) { - put_unaligned_le32(bss_param->tsf, cur_byte); - cur_byte += 4; - - *(cur_byte++) = bss_param->opp_enabled; - *(cur_byte++) = bss_param->idx; - - if (bss_param->opp_enabled) - *(cur_byte++) = bss_param->ct_window; - - *(cur_byte++) = bss_param->cnt; - - memcpy(cur_byte, bss_param->duration, - sizeof(bss_param->duration)); - cur_byte += sizeof(bss_param->duration); - - memcpy(cur_byte, bss_param->interval, - sizeof(bss_param->interval)); - cur_byte += sizeof(bss_param->interval); - - memcpy(cur_byte, bss_param->start_time, - sizeof(bss_param->start_time)); - cur_byte += sizeof(bss_param->start_time); - } - - cur_byte = wid_list[wid_cnt].val; + wid_list[wid_cnt].size = sizeof(*bss_param); + wid_list[wid_cnt].val = (u8 *)bss_param; wid_cnt++; result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, @@ -472,25 +374,17 @@ static int wilc_send_connect_wid(struct wilc_vif *vif) wilc_get_vif_idx(vif)); if (result) { netdev_err(vif->ndev, "failed to send config packet\n"); - kfree(cur_byte); goto error; } else { hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP; } - kfree(cur_byte); return 0; error: - kfree(conn_attr->bssid); - conn_attr->bssid = NULL; - - kfree(conn_attr->ssid); - conn_attr->ssid = NULL; - - kfree(conn_attr->ies); - conn_attr->ies = NULL; + kfree(conn_attr->req_ies); + conn_attr->req_ies = NULL; return result; } @@ -500,7 +394,6 @@ static void handle_connect_timeout(struct work_struct *work) struct host_if_msg *msg = container_of(work, struct host_if_msg, work); struct wilc_vif *vif = msg->vif; int result; - struct connect_info info; struct wid wid; u16 dummy_reason_code = 0; struct host_if_drv *hif_drv = vif->hif_drv; @@ -512,31 +405,11 @@ static void handle_connect_timeout(struct work_struct *work) hif_drv->hif_state = HOST_IF_IDLE; - memset(&info, 0, sizeof(struct connect_info)); + if (hif_drv->conn_info.conn_result) { + hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_CONN_RESP, + WILC_MAC_STATUS_DISCONNECTED, + hif_drv->conn_info.arg); - if (hif_drv->usr_conn_req.conn_result) { - if (hif_drv->usr_conn_req.bssid) { - memcpy(info.bssid, - hif_drv->usr_conn_req.bssid, 6); - } - - if (hif_drv->usr_conn_req.ies) { - info.req_ies_len = hif_drv->usr_conn_req.ies_len; - info.req_ies = kmemdup(hif_drv->usr_conn_req.ies, - hif_drv->usr_conn_req.ies_len, - GFP_KERNEL); - if (!info.req_ies) - goto out; - } - - hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP, - &info, - WILC_MAC_STATUS_DISCONNECTED, - NULL, - hif_drv->usr_conn_req.arg); - - kfree(info.req_ies); - info.req_ies = NULL; } else { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } @@ -551,346 +424,174 @@ static void handle_connect_timeout(struct work_struct *work) if (result) netdev_err(vif->ndev, "Failed to send disconnect\n"); - hif_drv->usr_conn_req.ssid_len = 0; - kfree(hif_drv->usr_conn_req.ssid); - hif_drv->usr_conn_req.ssid = NULL; - kfree(hif_drv->usr_conn_req.bssid); - hif_drv->usr_conn_req.bssid = NULL; - hif_drv->usr_conn_req.ies_len = 0; - kfree(hif_drv->usr_conn_req.ies); - hif_drv->usr_conn_req.ies = NULL; + hif_drv->conn_info.req_ies_len = 0; + kfree(hif_drv->conn_info.req_ies); + hif_drv->conn_info.req_ies = NULL; out: kfree(msg); } -static void host_int_fill_join_bss_param(struct join_bss_param *param, u8 *ies, - u16 *out_index, u8 *pcipher_tc, - u8 *auth_total_cnt, u32 tsf_lo, - u8 *rates_no) +void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, + struct cfg80211_crypto_settings *crypto) { - u8 ext_rates_no; - u16 offset; - u8 pcipher_cnt; - u8 auth_cnt; - u8 i, j; - u16 index = *out_index; - - if (ies[index] == WLAN_EID_SUPP_RATES) { - *rates_no = ies[index + 1]; - param->supp_rates[0] = *rates_no; - index += 2; - - for (i = 0; i < *rates_no; i++) - param->supp_rates[i + 1] = ies[index + i]; - - index += *rates_no; - } else if (ies[index] == WLAN_EID_EXT_SUPP_RATES) { - ext_rates_no = ies[index + 1]; - if (ext_rates_no > (MAX_RATES_SUPPORTED - *rates_no)) - param->supp_rates[0] = MAX_RATES_SUPPORTED; - else - param->supp_rates[0] += ext_rates_no; - index += 2; - for (i = 0; i < (param->supp_rates[0] - *rates_no); i++) - param->supp_rates[*rates_no + i + 1] = ies[index + i]; - - index += ext_rates_no; - } else if (ies[index] == WLAN_EID_HT_CAPABILITY) { - param->ht_capable = true; - index += ies[index + 1] + 2; - } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) && - (ies[index + 2] == 0x00) && (ies[index + 3] == 0x50) && - (ies[index + 4] == 0xF2) && (ies[index + 5] == 0x02) && - ((ies[index + 6] == 0x00) || (ies[index + 6] == 0x01)) && - (ies[index + 7] == 0x01)) { - param->wmm_cap = true; - - if (ies[index + 8] & BIT(7)) - param->uapsd_cap = true; - index += ies[index + 1] + 2; - } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) && - (ies[index + 2] == 0x50) && (ies[index + 3] == 0x6f) && - (ies[index + 4] == 0x9a) && - (ies[index + 5] == 0x09) && (ies[index + 6] == 0x0c)) { - u16 p2p_cnt; - - param->tsf = tsf_lo; - param->noa_enabled = 1; - param->idx = ies[index + 9]; - - if (ies[index + 10] & BIT(7)) { - param->opp_enabled = 1; - param->ct_window = ies[index + 10]; - } else { - param->opp_enabled = 0; - } - - param->cnt = ies[index + 11]; - p2p_cnt = index + 12; - - memcpy(param->duration, ies + p2p_cnt, 4); - p2p_cnt += 4; - - memcpy(param->interval, ies + p2p_cnt, 4); - p2p_cnt += 4; - - memcpy(param->start_time, ies + p2p_cnt, 4); - - index += ies[index + 1] + 2; - } else if ((ies[index] == WLAN_EID_RSN) || - ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) && - (ies[index + 2] == 0x00) && - (ies[index + 3] == 0x50) && (ies[index + 4] == 0xF2) && - (ies[index + 5] == 0x01))) { - u16 rsn_idx = index; - - if (ies[rsn_idx] == WLAN_EID_RSN) { - param->mode_802_11i = 2; - } else { - if (param->mode_802_11i == 0) - param->mode_802_11i = 1; - rsn_idx += 4; - } - - rsn_idx += 7; - param->rsn_grp_policy = ies[rsn_idx]; - rsn_idx++; - offset = ies[rsn_idx] * 4; - pcipher_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx]; - rsn_idx += 2; - - i = *pcipher_tc; - j = 0; - for (; i < (pcipher_cnt + *pcipher_tc) && i < 3; i++, j++) { - u8 *policy = ¶m->rsn_pcip_policy[i]; - - *policy = ies[rsn_idx + ((j + 1) * 4) - 1]; - } - - *pcipher_tc += pcipher_cnt; - rsn_idx += offset; - - offset = ies[rsn_idx] * 4; - - auth_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx]; - rsn_idx += 2; - i = *auth_total_cnt; - j = 0; - for (; i < (*auth_total_cnt + auth_cnt); i++, j++) { - u8 *policy = ¶m->rsn_auth_policy[i]; - - *policy = ies[rsn_idx + ((j + 1) * 4) - 1]; - } - - *auth_total_cnt += auth_cnt; - rsn_idx += offset; - - if (ies[index] == WLAN_EID_RSN) { - param->rsn_cap[0] = ies[rsn_idx]; - param->rsn_cap[1] = ies[rsn_idx + 1]; - rsn_idx += 2; - } - param->rsn_found = true; - index += ies[index + 1] + 2; - } else { - index += ies[index + 1] + 2; - } - - *out_index = index; -} - -static void *host_int_parse_join_bss_param(struct network_info *info) -{ - struct join_bss_param *param; - u16 index = 0; - u8 rates_no = 0; - u8 pcipher_total_cnt = 0; - u8 auth_total_cnt = 0; + struct wilc_join_bss_param *param; + struct ieee80211_p2p_noa_attr noa_attr; + u8 rates_len = 0; + const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie; + const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie; + int ret; + const struct cfg80211_bss_ies *ies = rcu_dereference(bss->ies); param = kzalloc(sizeof(*param), GFP_KERNEL); if (!param) return NULL; - param->dtim_period = info->dtim_period; - param->beacon_period = info->beacon_period; - param->cap_info = info->cap_info; - memcpy(param->bssid, info->bssid, 6); - memcpy((u8 *)param->ssid, info->ssid, info->ssid_len + 1); - param->ssid_len = info->ssid_len; - memset(param->rsn_pcip_policy, 0xFF, 3); - memset(param->rsn_auth_policy, 0xFF, 3); - - while (index < info->ies_len) - host_int_fill_join_bss_param(param, info->ies, &index, - &pcipher_total_cnt, - &auth_total_cnt, info->tsf_lo, - &rates_no); - - return (void *)param; -} - -static inline u8 *get_bssid(struct ieee80211_mgmt *mgmt) -{ - if (ieee80211_has_fromds(mgmt->frame_control)) - return mgmt->sa; - else if (ieee80211_has_tods(mgmt->frame_control)) - return mgmt->da; - else - return mgmt->bssid; -} + param->beacon_period = cpu_to_le16(bss->beacon_interval); + param->cap_info = cpu_to_le16(bss->capability); + param->bss_type = WILC_FW_BSS_TYPE_INFRA; + param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq); + ether_addr_copy(param->bssid, bss->bssid); -static s32 wilc_parse_network_info(u8 *msg_buffer, - struct network_info **ret_network_info) -{ - struct network_info *info; - struct ieee80211_mgmt *mgt; - u8 *wid_val, *msa, *ies; - u16 wid_len, rx_len, ies_len; - u8 msg_type; - size_t offset; - const u8 *ch_elm, *tim_elm, *ssid_elm; - - msg_type = msg_buffer[0]; - if ('N' != msg_type) - return -EFAULT; + ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); + if (ssid_elm) { + if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN) + memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]); + } - wid_len = get_unaligned_le16(&msg_buffer[6]); - wid_val = &msg_buffer[8]; + tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len); + if (tim_elm && tim_elm[1] >= 2) + param->dtim_period = tim_elm[3]; - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; + memset(param->p_suites, 0xFF, 3); + memset(param->akm_suites, 0xFF, 3); - info->rssi = wid_val[0]; + rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len); + if (rates_ie) { + rates_len = rates_ie[1]; + param->supp_rates[0] = rates_len; + memcpy(¶m->supp_rates[1], rates_ie + 2, rates_len); + } - msa = &wid_val[1]; - mgt = (struct ieee80211_mgmt *)&wid_val[1]; - rx_len = wid_len - 1; + supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, ies->data, + ies->len); + if (supp_rates_ie) { + if (supp_rates_ie[1] > (WILC_MAX_RATES_SUPPORTED - rates_len)) + param->supp_rates[0] = WILC_MAX_RATES_SUPPORTED; + else + param->supp_rates[0] += supp_rates_ie[1]; - if (ieee80211_is_probe_resp(mgt->frame_control)) { - info->cap_info = le16_to_cpu(mgt->u.probe_resp.capab_info); - info->beacon_period = le16_to_cpu(mgt->u.probe_resp.beacon_int); - info->tsf = le64_to_cpu(mgt->u.probe_resp.timestamp); - info->tsf_lo = (u32)info->tsf; - offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - } else if (ieee80211_is_beacon(mgt->frame_control)) { - info->cap_info = le16_to_cpu(mgt->u.beacon.capab_info); - info->beacon_period = le16_to_cpu(mgt->u.beacon.beacon_int); - info->tsf = le64_to_cpu(mgt->u.beacon.timestamp); - info->tsf_lo = (u32)info->tsf; - offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); - } else { - /* only process probe response and beacon frame */ - kfree(info); - return -EIO; + memcpy(¶m->supp_rates[rates_len + 1], supp_rates_ie + 2, + (param->supp_rates[0] - rates_len)); } - ether_addr_copy(info->bssid, get_bssid(mgt)); + ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len); + if (ht_ie) + param->ht_capable = true; - ies = mgt->u.beacon.variable; - ies_len = rx_len - offset; - if (ies_len <= 0) { - kfree(info); - return -EIO; + ret = cfg80211_get_p2p_attr(ies->data, ies->len, + IEEE80211_P2P_ATTR_ABSENCE_NOTICE, + (u8 *)&noa_attr, sizeof(noa_attr)); + if (ret > 0) { + param->tsf_lo = cpu_to_le32(ies->tsf); + param->noa_enabled = 1; + param->idx = noa_attr.index; + if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) { + param->opp_enabled = 1; + param->opp_en.ct_window = noa_attr.oppps_ctwindow; + param->opp_en.cnt = noa_attr.desc[0].count; + param->opp_en.duration = noa_attr.desc[0].duration; + param->opp_en.interval = noa_attr.desc[0].interval; + param->opp_en.start_time = noa_attr.desc[0].start_time; + } else { + param->opp_enabled = 0; + param->opp_dis.cnt = noa_attr.desc[0].count; + param->opp_dis.duration = noa_attr.desc[0].duration; + param->opp_dis.interval = noa_attr.desc[0].interval; + param->opp_dis.start_time = noa_attr.desc[0].start_time; + } + } + wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WMM, + ies->data, ies->len); + if (wmm_ie) { + struct ieee80211_wmm_param_ie *ie; + + ie = (struct ieee80211_wmm_param_ie *)wmm_ie; + if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) && + ie->version == 1) { + param->wmm_cap = true; + if (ie->qos_info & BIT(7)) + param->uapsd_cap = true; + } } - info->ies = kmemdup(ies, ies_len, GFP_KERNEL); - if (!info->ies) { - kfree(info); - return -ENOMEM; + wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPA, + ies->data, ies->len); + if (wpa_ie) { + param->mode_802_11i = 1; + param->rsn_found = true; } - info->ies_len = ies_len; + rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len); + if (rsn_ie) { + int offset = 8; - ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies, ies_len); - if (ssid_elm) { - info->ssid_len = ssid_elm[1]; - if (info->ssid_len <= IEEE80211_MAX_SSID_LEN) - memcpy(info->ssid, ssid_elm + 2, info->ssid_len); - else - info->ssid_len = 0; + param->mode_802_11i = 2; + param->rsn_found = true; + //extract RSN capabilities + offset += (rsn_ie[offset] * 4) + 2; + offset += (rsn_ie[offset] * 4) + 2; + memcpy(param->rsn_cap, &rsn_ie[offset], 2); } - ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len); - if (ch_elm && ch_elm[1] > 0) - info->ch = ch_elm[2]; + if (param->rsn_found) { + int i; - tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len); - if (tim_elm && tim_elm[1] >= 2) - info->dtim_period = tim_elm[3]; + param->rsn_grp_policy = crypto->cipher_group & 0xFF; + for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++) + param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF; - *ret_network_info = info; + for (i = 0; i < crypto->n_akm_suites && i < 3; i++) + param->akm_suites[i] = crypto->akm_suites[i] & 0xFF; + } - return 0; + return (void *)param; } static void handle_rcvd_ntwrk_info(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct rcvd_net_info *rcvd_info = &msg->body.net_info; - u32 i; - bool found; - struct network_info *info = NULL; - void *params; - struct host_if_drv *hif_drv = vif->hif_drv; - struct user_scan_req *scan_req = &hif_drv->usr_scan_req; - - found = true; + struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info; + struct wilc_user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req; + const u8 *ch_elm; + u8 *ies; + int ies_len; + size_t offset; - if (!scan_req->scan_result) + if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control)) + offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); + else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control)) + offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); + else goto done; - wilc_parse_network_info(rcvd_info->buffer, &info); - if (!info || !scan_req->scan_result) { - netdev_err(vif->ndev, "%s: info or scan result NULL\n", - __func__); + ies = rcvd_info->mgmt->u.beacon.variable; + ies_len = rcvd_info->frame_len - offset; + if (ies_len <= 0) goto done; - } - - for (i = 0; i < scan_req->ch_cnt; i++) { - if (memcmp(scan_req->net_info[i].bssid, info->bssid, 6) == 0) { - if (info->rssi <= scan_req->net_info[i].rssi) { - goto done; - } else { - scan_req->net_info[i].rssi = info->rssi; - found = false; - break; - } - } - } - - if (found) { - if (scan_req->ch_cnt < MAX_NUM_SCANNED_NETWORKS) { - scan_req->net_info[scan_req->ch_cnt].rssi = info->rssi; - - memcpy(scan_req->net_info[scan_req->ch_cnt].bssid, - info->bssid, 6); - - scan_req->ch_cnt++; - info->new_network = true; - params = host_int_parse_join_bss_param(info); + ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len); + if (ch_elm && ch_elm[1] > 0) + rcvd_info->ch = ch_elm[2]; - scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info, - scan_req->arg, params); - } - } else { - info->new_network = false; - scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, info, - scan_req->arg, NULL); - } + if (scan_req->scan_result) + scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, rcvd_info, + scan_req->arg); done: - kfree(rcvd_info->buffer); - rcvd_info->buffer = NULL; - - if (info) { - kfree(info->ies); - kfree(info); - } - + kfree(rcvd_info->mgmt); kfree(msg); } @@ -918,20 +619,8 @@ static void host_int_get_assoc_res_info(struct wilc_vif *vif, *rcvd_assoc_resp_info_len = wid.size; } -static inline void host_int_free_user_conn_req(struct host_if_drv *hif_drv) -{ - hif_drv->usr_conn_req.ssid_len = 0; - kfree(hif_drv->usr_conn_req.ssid); - hif_drv->usr_conn_req.ssid = NULL; - kfree(hif_drv->usr_conn_req.bssid); - hif_drv->usr_conn_req.bssid = NULL; - hif_drv->usr_conn_req.ies_len = 0; - kfree(hif_drv->usr_conn_req.ies); - hif_drv->usr_conn_req.ies = NULL; -} - static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, - struct connect_info *ret_conn_info) + struct wilc_conn_info *ret_conn_info) { u8 *ies; u16 ies_len; @@ -955,10 +644,8 @@ static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, u8 mac_status) { - struct connect_info conn_info; struct host_if_drv *hif_drv = vif->hif_drv; - - memset(&conn_info, 0, sizeof(struct connect_info)); + struct wilc_conn_info *conn_info = &hif_drv->conn_info; if (mac_status == WILC_MAC_STATUS_CONNECTED) { u32 assoc_resp_info_len; @@ -974,7 +661,7 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp, assoc_resp_info_len, - &conn_info); + conn_info); if (err) netdev_err(vif->ndev, "wilc_parse_assoc_resp_info() returned error %d\n", @@ -982,31 +669,13 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, } } - if (hif_drv->usr_conn_req.bssid) { - memcpy(conn_info.bssid, hif_drv->usr_conn_req.bssid, 6); - - if (mac_status == WILC_MAC_STATUS_CONNECTED && - conn_info.status == WLAN_STATUS_SUCCESS) { - memcpy(hif_drv->assoc_bssid, - hif_drv->usr_conn_req.bssid, ETH_ALEN); - } - } - - if (hif_drv->usr_conn_req.ies) { - conn_info.req_ies = kmemdup(hif_drv->usr_conn_req.ies, - hif_drv->usr_conn_req.ies_len, - GFP_KERNEL); - if (conn_info.req_ies) - conn_info.req_ies_len = hif_drv->usr_conn_req.ies_len; - } - del_timer(&hif_drv->connect_timer); - hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP, - &conn_info, mac_status, NULL, - hif_drv->usr_conn_req.arg); + conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status, + hif_drv->conn_info.arg); if (mac_status == WILC_MAC_STATUS_CONNECTED && - conn_info.status == WLAN_STATUS_SUCCESS) { + conn_info->status == WLAN_STATUS_SUCCESS) { + ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid); wilc_set_power_mgmt(vif, 0, 0); hif_drv->hif_state = HOST_IF_CONNECTED; @@ -1018,44 +687,39 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, hif_drv->hif_state = HOST_IF_IDLE; } - kfree(conn_info.resp_ies); - conn_info.resp_ies = NULL; + kfree(conn_info->resp_ies); + conn_info->resp_ies = NULL; + conn_info->resp_ies_len = 0; - kfree(conn_info.req_ies); - conn_info.req_ies = NULL; - host_int_free_user_conn_req(hif_drv); + kfree(conn_info->req_ies); + conn_info->req_ies = NULL; + conn_info->req_ies_len = 0; } static inline void host_int_handle_disconnect(struct wilc_vif *vif) { - struct disconnect_info disconn_info; struct host_if_drv *hif_drv = vif->hif_drv; - wilc_connect_result conn_result = hif_drv->usr_conn_req.conn_result; - - memset(&disconn_info, 0, sizeof(struct disconnect_info)); if (hif_drv->usr_scan_req.scan_result) { del_timer(&hif_drv->scan_timer); handle_scan_done(vif, SCAN_EVENT_ABORTED); } - disconn_info.reason = 0; - disconn_info.ie = NULL; - disconn_info.ie_len = 0; - - if (conn_result) { + if (hif_drv->conn_info.conn_result) { vif->obtaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); - conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, 0, - &disconn_info, hif_drv->usr_conn_req.arg); + hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, + 0, hif_drv->conn_info.arg); } else { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } eth_zero_addr(hif_drv->assoc_bssid); - host_int_free_user_conn_req(hif_drv); + hif_drv->conn_info.req_ies_len = 0; + kfree(hif_drv->conn_info.req_ies); + hif_drv->conn_info.req_ies = NULL; hif_drv->hif_state = HOST_IF_IDLE; } @@ -1063,55 +727,30 @@ static void handle_rcvd_gnrl_async_info(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); struct wilc_vif *vif = msg->vif; - struct rcvd_async_info *rcvd_info = &msg->body.async_info; - u8 msg_type; - u8 mac_status; + struct wilc_rcvd_mac_info *mac_info = &msg->body.mac_info; struct host_if_drv *hif_drv = vif->hif_drv; - if (!rcvd_info->buffer) { - netdev_err(vif->ndev, "%s: buffer is NULL\n", __func__); - goto free_msg; - } - if (!hif_drv) { netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__); - goto free_rcvd_info; + goto free_msg; } - if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || - hif_drv->hif_state == HOST_IF_CONNECTED || - hif_drv->usr_scan_req.scan_result) { - if (!hif_drv->usr_conn_req.conn_result) { - netdev_err(vif->ndev, "%s: conn_result is NULL\n", - __func__); - goto free_rcvd_info; - } - - msg_type = rcvd_info->buffer[0]; - - if ('I' != msg_type) { - netdev_err(vif->ndev, "Received Message incorrect.\n"); - goto free_rcvd_info; - } + if (!hif_drv->conn_info.conn_result) { + netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); + goto free_msg; + } - mac_status = rcvd_info->buffer[7]; - if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { - host_int_parse_assoc_resp_info(vif, mac_status); - } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) && - (hif_drv->hif_state == HOST_IF_CONNECTED)) { + if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { + host_int_parse_assoc_resp_info(vif, mac_info->status); + } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) { + if (hif_drv->hif_state == HOST_IF_CONNECTED) { host_int_handle_disconnect(vif); - } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) && - (hif_drv->usr_scan_req.scan_result)) { + } else if (hif_drv->usr_scan_req.scan_result) { del_timer(&hif_drv->scan_timer); - if (hif_drv->usr_scan_req.scan_result) - handle_scan_done(vif, SCAN_EVENT_ABORTED); + handle_scan_done(vif, SCAN_EVENT_ABORTED); } } -free_rcvd_info: - kfree(rcvd_info->buffer); - rcvd_info->buffer = NULL; - free_msg: kfree(msg); } @@ -1120,9 +759,8 @@ int wilc_disconnect(struct wilc_vif *vif) { struct wid wid; struct host_if_drv *hif_drv = vif->hif_drv; - struct disconnect_info disconn_info; - struct user_scan_req *scan_req; - struct user_conn_req *conn_req; + struct wilc_user_scan_req *scan_req; + struct wilc_conn_info *conn_info; int result; u16 dummy_reason_code = 0; @@ -1141,27 +779,21 @@ int wilc_disconnect(struct wilc_vif *vif) return result; } - memset(&disconn_info, 0, sizeof(struct disconnect_info)); - - disconn_info.reason = 0; - disconn_info.ie = NULL; - disconn_info.ie_len = 0; scan_req = &hif_drv->usr_scan_req; - conn_req = &hif_drv->usr_conn_req; + conn_info = &hif_drv->conn_info; if (scan_req->scan_result) { del_timer(&hif_drv->scan_timer); - scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg, - NULL); + scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg); scan_req->scan_result = NULL; } - if (conn_req->conn_result) { + if (conn_info->conn_result) { if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) del_timer(&hif_drv->connect_timer); - conn_req->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, - 0, &disconn_info, conn_req->arg); + conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0, + conn_info->arg); } else { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } @@ -1170,14 +802,9 @@ int wilc_disconnect(struct wilc_vif *vif) eth_zero_addr(hif_drv->assoc_bssid); - conn_req->ssid_len = 0; - kfree(conn_req->ssid); - conn_req->ssid = NULL; - kfree(conn_req->bssid); - conn_req->bssid = NULL; - conn_req->ies_len = 0; - kfree(conn_req->ies); - conn_req->ies = NULL; + conn_info->req_ies_len = 0; + kfree(conn_info->req_ies); + conn_info->req_ies = NULL; return 0; } @@ -1285,47 +912,29 @@ static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac, } static int handle_remain_on_chan(struct wilc_vif *vif, - struct remain_ch *hif_remain_ch) + struct wilc_remain_ch *hif_remain_ch) { int result; u8 remain_on_chan_flag; struct wid wid; struct host_if_drv *hif_drv = vif->hif_drv; - if (!hif_drv->remain_on_ch_pending) { - hif_drv->remain_on_ch.arg = hif_remain_ch->arg; - hif_drv->remain_on_ch.expired = hif_remain_ch->expired; - hif_drv->remain_on_ch.ready = hif_remain_ch->ready; - hif_drv->remain_on_ch.ch = hif_remain_ch->ch; - hif_drv->remain_on_ch.id = hif_remain_ch->id; - } else { - hif_remain_ch->ch = hif_drv->remain_on_ch.ch; - } + if (hif_drv->usr_scan_req.scan_result) + return -EBUSY; - if (hif_drv->usr_scan_req.scan_result) { - hif_drv->remain_on_ch_pending = 1; - result = -EBUSY; - goto error; - } - if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { - result = -EBUSY; - goto error; - } + if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) + return -EBUSY; - if (vif->obtaining_ip || vif->connecting) { - result = -EBUSY; - goto error; - } + if (vif->obtaining_ip || vif->connecting) + return -EBUSY; remain_on_chan_flag = true; wid.id = WID_REMAIN_ON_CHAN; wid.type = WID_STR; wid.size = 2; wid.val = kmalloc(wid.size, GFP_KERNEL); - if (!wid.val) { - result = -ENOMEM; - goto error; - } + if (!wid.val) + return -ENOMEM; wid.val[0] = remain_on_chan_flag; wid.val[1] = (s8)hif_remain_ch->ch; @@ -1333,28 +942,23 @@ static int handle_remain_on_chan(struct wilc_vif *vif, result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(wid.val); - if (result != 0) - netdev_err(vif->ndev, "Failed to set remain on channel\n"); + if (result) + return -EBUSY; -error: + hif_drv->remain_on_ch.arg = hif_remain_ch->arg; + hif_drv->remain_on_ch.expired = hif_remain_ch->expired; + hif_drv->remain_on_ch.ch = hif_remain_ch->ch; + hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie; hif_drv->remain_on_ch_timer_vif = vif; - mod_timer(&hif_drv->remain_on_ch_timer, - jiffies + msecs_to_jiffies(hif_remain_ch->duration)); - - if (hif_drv->remain_on_ch.ready) - hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg); - - if (hif_drv->remain_on_ch_pending) - hif_drv->remain_on_ch_pending = 0; - return result; + return 0; } static void handle_listen_state_expired(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); struct wilc_vif *vif = msg->vif; - struct remain_ch *hif_remain_ch = &msg->body.remain_on_ch; + struct wilc_remain_ch *hif_remain_ch = &msg->body.remain_on_ch; u8 remain_on_chan_flag; struct wid wid; int result; @@ -1372,7 +976,7 @@ static void handle_listen_state_expired(struct work_struct *work) goto free_msg; wid.val[0] = remain_on_chan_flag; - wid.val[1] = FALSE_FRMWR_CHANNEL; + wid.val[1] = WILC_FALSE_FRMWR_CHANNEL; result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -1384,7 +988,7 @@ static void handle_listen_state_expired(struct work_struct *work) if (hif_drv->remain_on_ch.expired) { hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg, - hif_remain_ch->id); + hif_remain_ch->cookie); } } else { netdev_dbg(vif->ndev, "Not in listen state\n"); @@ -1408,7 +1012,7 @@ static void listen_timer_cb(struct timer_list *t) if (IS_ERR(msg)) return; - msg->body.remain_on_ch.id = vif->hif_drv->remain_on_ch.id; + msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie; result = wilc_enqueue_work(msg); if (result) { @@ -1421,32 +1025,27 @@ static void handle_set_mcast_filter(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); struct wilc_vif *vif = msg->vif; - struct set_multicast *hif_set_mc = &msg->body.multicast_info; + struct wilc_set_multicast *set_mc = &msg->body.mc_info; int result; struct wid wid; u8 *cur_byte; wid.id = WID_SETUP_MULTICAST_FILTER; wid.type = WID_BIN; - wid.size = sizeof(struct set_multicast) + (hif_set_mc->cnt * ETH_ALEN); + wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN); wid.val = kmalloc(wid.size, GFP_KERNEL); if (!wid.val) goto error; cur_byte = wid.val; - *cur_byte++ = (hif_set_mc->enabled & 0xFF); - *cur_byte++ = 0; - *cur_byte++ = 0; - *cur_byte++ = 0; + put_unaligned_le32(set_mc->enabled, cur_byte); + cur_byte += 4; - *cur_byte++ = (hif_set_mc->cnt & 0xFF); - *cur_byte++ = ((hif_set_mc->cnt >> 8) & 0xFF); - *cur_byte++ = ((hif_set_mc->cnt >> 16) & 0xFF); - *cur_byte++ = ((hif_set_mc->cnt >> 24) & 0xFF); + put_unaligned_le32(set_mc->cnt, cur_byte); + cur_byte += 4; - if (hif_set_mc->cnt > 0 && hif_set_mc->mc_list) - memcpy(cur_byte, hif_set_mc->mc_list, - ((hif_set_mc->cnt) * ETH_ALEN)); + if (set_mc->cnt > 0 && set_mc->mc_list) + memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN); result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -1454,7 +1053,7 @@ static void handle_set_mcast_filter(struct work_struct *work) netdev_err(vif->ndev, "Failed to send setup multicast\n"); error: - kfree(hif_set_mc->mc_list); + kfree(set_mc->mc_list); kfree(wid.val); kfree(msg); } @@ -1479,9 +1078,6 @@ static void handle_scan_complete(struct work_struct *work) handle_scan_done(msg->vif, SCAN_EVENT_DONE); - if (msg->vif->hif_drv->remain_on_ch_pending) - handle_remain_on_chan(msg->vif, - &msg->vif->hif_drv->remain_on_ch); kfree(msg); } @@ -1629,7 +1225,7 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, u8 mode, u8 cipher_mode, u8 index) { int result = 0; - u8 t_key_len = ptk_key_len + RX_MIC_KEY_LEN + TX_MIC_KEY_LEN; + u8 t_key_len = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN; if (mode == WILC_AP_MODE) { struct wid wid_list[2]; @@ -1651,11 +1247,11 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, if (rx_mic) memcpy(&key_buf->key[ptk_key_len], rx_mic, - RX_MIC_KEY_LEN); + WILC_RX_MIC_KEY_LEN); if (tx_mic) - memcpy(&key_buf->key[ptk_key_len + RX_MIC_KEY_LEN], - tx_mic, TX_MIC_KEY_LEN); + memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN], + tx_mic, WILC_TX_MIC_KEY_LEN); wid_list[1].id = WID_ADD_PTK; wid_list[1].type = WID_STR; @@ -1679,11 +1275,11 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, if (rx_mic) memcpy(&key_buf->key[ptk_key_len], rx_mic, - RX_MIC_KEY_LEN); + WILC_RX_MIC_KEY_LEN); if (tx_mic) - memcpy(&key_buf->key[ptk_key_len + RX_MIC_KEY_LEN], - tx_mic, TX_MIC_KEY_LEN); + memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN], + tx_mic, WILC_TX_MIC_KEY_LEN); wid.id = WID_ADD_PTK; wid.type = WID_STR; @@ -1704,7 +1300,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, { int result = 0; struct wilc_gtk_key *gtk_key; - int t_key_len = gtk_key_len + RX_MIC_KEY_LEN + TX_MIC_KEY_LEN; + int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN; gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL); if (!gtk_key) @@ -1722,11 +1318,11 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, memcpy(>k_key->key[0], rx_gtk, gtk_key_len); if (rx_mic) - memcpy(>k_key->key[gtk_key_len], rx_mic, RX_MIC_KEY_LEN); + memcpy(>k_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN); if (tx_mic) - memcpy(>k_key->key[gtk_key_len + RX_MIC_KEY_LEN], - tx_mic, TX_MIC_KEY_LEN); + memcpy(>k_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN], + tx_mic, WILC_TX_MIC_KEY_LEN); if (mode == WILC_AP_MODE) { struct wid wid_list[2]; @@ -1793,61 +1389,22 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result connect_result, void *user_arg, - u8 security, enum authtype auth_type, - u8 channel, void *join_params) +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies, + size_t ies_len) { int result; struct host_if_drv *hif_drv = vif->hif_drv; - struct user_conn_req *con_info = &hif_drv->usr_conn_req; + struct wilc_conn_info *conn_info = &hif_drv->conn_info; - if (!hif_drv || !connect_result) { - netdev_err(vif->ndev, - "%s: hif driver or connect result is NULL", - __func__); - return -EFAULT; - } - - if (!join_params) { - netdev_err(vif->ndev, "%s: joinparams is NULL\n", __func__); - return -EFAULT; - } - - if (hif_drv->usr_scan_req.scan_result) { - netdev_err(vif->ndev, "%s: Scan in progress\n", __func__); - return -EBUSY; - } - - con_info->security = security; - con_info->auth_type = auth_type; - con_info->ch = channel; - con_info->conn_result = connect_result; - con_info->arg = user_arg; - con_info->param = join_params; - - if (bssid) { - con_info->bssid = kmemdup(bssid, 6, GFP_KERNEL); - if (!con_info->bssid) - return -ENOMEM; - } - - if (ssid) { - con_info->ssid_len = ssid_len; - con_info->ssid = kmemdup(ssid, ssid_len, GFP_KERNEL); - if (!con_info->ssid) { - result = -ENOMEM; - goto free_bssid; - } - } + if (bssid) + ether_addr_copy(conn_info->bssid, bssid); if (ies) { - con_info->ies_len = ies_len; - con_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); - if (!con_info->ies) { + conn_info->req_ies_len = ies_len; + conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!conn_info->req_ies) { result = -ENOMEM; - goto free_ssid; + return result; } } @@ -1857,18 +1414,12 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, hif_drv->connect_timer_vif = vif; mod_timer(&hif_drv->connect_timer, - jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT)); + jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS)); return 0; free_ies: - kfree(con_info->ies); - -free_ssid: - kfree(con_info->ssid); - -free_bssid: - kfree(con_info->bssid); + kfree(conn_info->req_ies); return result; } @@ -1899,6 +1450,9 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, int result; struct wilc_drv_handler drv; + if (!hif_drv) + return -EFAULT; + wid.id = WID_SET_DRV_HANDLER; wid.type = WID_STR; wid.size = sizeof(drv); @@ -1991,7 +1545,7 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) return result; } -int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats) +static int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats) { int result; struct host_if_msg *msg; @@ -2090,7 +1644,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) vif->obtaining_ip = false; if (wilc->clients_count == 0) - mutex_init(&hif_deinit_lock); + mutex_init(&wilc->deinit_lock); timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0); mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000)); @@ -2118,9 +1672,7 @@ int wilc_deinit(struct wilc_vif *vif) return -EFAULT; } - mutex_lock(&hif_deinit_lock); - - terminated_handle = hif_drv; + mutex_lock(&vif->wilc->deinit_lock); del_timer_sync(&hif_drv->scan_timer); del_timer_sync(&hif_drv->connect_timer); @@ -2131,18 +1683,16 @@ int wilc_deinit(struct wilc_vif *vif) if (hif_drv->usr_scan_req.scan_result) { hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL, - hif_drv->usr_scan_req.arg, - NULL); + hif_drv->usr_scan_req.arg); hif_drv->usr_scan_req.scan_result = NULL; } hif_drv->hif_state = HOST_IF_IDLE; kfree(hif_drv); - + vif->hif_drv = NULL; vif->wilc->clients_count--; - terminated_handle = NULL; - mutex_unlock(&hif_deinit_lock); + mutex_unlock(&vif->wilc->deinit_lock); return result; } @@ -2154,16 +1704,13 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length) struct host_if_drv *hif_drv; struct wilc_vif *vif; - id = buffer[length - 4]; - id |= (buffer[length - 3] << 8); - id |= (buffer[length - 2] << 16); - id |= (buffer[length - 1] << 24); + id = get_unaligned_le32(&buffer[length - 4]); vif = wilc_get_vif_from_idx(wilc, id); if (!vif) return; hif_drv = vif->hif_drv; - if (!hif_drv || hif_drv == terminated_handle) { + if (!hif_drv) { netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv); return; } @@ -2172,9 +1719,12 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length) if (IS_ERR(msg)) return; - msg->body.net_info.len = length; - msg->body.net_info.buffer = kmemdup(buffer, length, GFP_KERNEL); - if (!msg->body.net_info.buffer) { + msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1; + msg->body.net_info.rssi = buffer[8]; + msg->body.net_info.mgmt = kmemdup(&buffer[9], + msg->body.net_info.frame_len, + GFP_KERNEL); + if (!msg->body.net_info.mgmt) { kfree(msg); return; } @@ -2182,7 +1732,7 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length) result = wilc_enqueue_work(msg); if (result) { netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg->body.net_info.buffer); + kfree(msg->body.net_info.mgmt); kfree(msg); } } @@ -2195,53 +1745,42 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length) struct host_if_drv *hif_drv; struct wilc_vif *vif; - mutex_lock(&hif_deinit_lock); + mutex_lock(&wilc->deinit_lock); - id = buffer[length - 4]; - id |= (buffer[length - 3] << 8); - id |= (buffer[length - 2] << 16); - id |= (buffer[length - 1] << 24); + id = get_unaligned_le32(&buffer[length - 4]); vif = wilc_get_vif_from_idx(wilc, id); if (!vif) { - mutex_unlock(&hif_deinit_lock); + mutex_unlock(&wilc->deinit_lock); return; } hif_drv = vif->hif_drv; - if (!hif_drv || hif_drv == terminated_handle) { - mutex_unlock(&hif_deinit_lock); + if (!hif_drv) { + mutex_unlock(&wilc->deinit_lock); return; } - if (!hif_drv->usr_conn_req.conn_result) { + if (!hif_drv->conn_info.conn_result) { netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); - mutex_unlock(&hif_deinit_lock); + mutex_unlock(&wilc->deinit_lock); return; } msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false); if (IS_ERR(msg)) { - mutex_unlock(&hif_deinit_lock); - return; - } - - msg->body.async_info.len = length; - msg->body.async_info.buffer = kmemdup(buffer, length, GFP_KERNEL); - if (!msg->body.async_info.buffer) { - kfree(msg); - mutex_unlock(&hif_deinit_lock); + mutex_unlock(&wilc->deinit_lock); return; } + msg->body.mac_info.status = buffer[7]; result = wilc_enqueue_work(msg); if (result) { netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg->body.async_info.buffer); kfree(msg); } - mutex_unlock(&hif_deinit_lock); + mutex_unlock(&wilc->deinit_lock); } void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length) @@ -2251,16 +1790,13 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length) struct host_if_drv *hif_drv; struct wilc_vif *vif; - id = buffer[length - 4]; - id |= buffer[length - 3] << 8; - id |= buffer[length - 2] << 16; - id |= buffer[length - 1] << 24; + id = get_unaligned_le32(&buffer[length - 4]); vif = wilc_get_vif_from_idx(wilc, id); if (!vif) return; hif_drv = vif->hif_drv; - if (!hif_drv || hif_drv == terminated_handle) + if (!hif_drv) return; if (hif_drv->usr_scan_req.scan_result) { @@ -2279,21 +1815,19 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length) } } -int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, +int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, u32 duration, u16 chan, - wilc_remain_on_chan_expired expired, - wilc_remain_on_chan_ready ready, + void (*expired)(void *, u64), void *user_arg) { - struct remain_ch roc; + struct wilc_remain_ch roc; int result; roc.ch = chan; roc.expired = expired; - roc.ready = ready; roc.arg = user_arg; roc.duration = duration; - roc.id = session_id; + roc.cookie = cookie; result = handle_remain_on_chan(vif, &roc); if (result) netdev_err(vif->ndev, "%s: failed to set remain on channel\n", @@ -2302,7 +1836,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, return result; } -int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id) +int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie) { int result; struct host_if_msg *msg; @@ -2319,7 +1853,7 @@ int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id) if (IS_ERR(msg)) return PTR_ERR(msg); - msg->body.remain_on_ch.id = session_id; + msg->body.remain_on_ch.cookie = cookie; result = wilc_enqueue_work(msg); if (result) { @@ -2484,7 +2018,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) int result; int i; u8 assoc_sta = 0; - struct del_all_sta del_sta; + struct wilc_del_all_sta del_sta; memset(&del_sta, 0x0, sizeof(del_sta)); for (i = 0; i < WILC_MAX_NUM_STA; i++) { @@ -2563,7 +2097,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) return result; } -int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count, +int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count, u8 *mc_list) { int result; @@ -2573,9 +2107,9 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count, if (IS_ERR(msg)) return PTR_ERR(msg); - msg->body.multicast_info.enabled = enabled; - msg->body.multicast_info.cnt = count; - msg->body.multicast_info.mc_list = mc_list; + msg->body.mc_info.enabled = enabled; + msg->body.mc_info.cnt = count; + msg->body.mc_info.mc_list = mc_list; result = wilc_enqueue_work(msg); if (result) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 9b396a79b144..678e62312215 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -18,19 +18,16 @@ enum { }; #define WILC_MAX_NUM_STA 9 -#define MAX_NUM_SCANNED_NETWORKS 100 -#define MAX_NUM_SCANNED_NETWORKS_SHADOW 130 +#define WILC_MAX_NUM_SCANNED_CH 14 #define WILC_MAX_NUM_PROBED_SSID 10 -#define TX_MIC_KEY_LEN 8 -#define RX_MIC_KEY_LEN 8 +#define WILC_TX_MIC_KEY_LEN 8 +#define WILC_RX_MIC_KEY_LEN 8 #define WILC_MAX_NUM_PMKIDS 16 #define WILC_ADD_STA_LENGTH 40 #define WILC_NUM_CONCURRENT_IFC 2 -#define NUM_RSSI 5 - enum { WILC_SET_CFG = 0, WILC_GET_CFG @@ -38,48 +35,6 @@ enum { #define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256 -struct rssi_history_buffer { - bool full; - u8 index; - s8 samples[NUM_RSSI]; -}; - -struct network_info { - s8 rssi; - u16 cap_info; - u8 ssid[MAX_SSID_LEN]; - u8 ssid_len; - u8 bssid[6]; - u16 beacon_period; - u8 dtim_period; - u8 ch; - unsigned long time_scan_cached; - unsigned long time_scan; - bool new_network; - u8 found; - u32 tsf_lo; - u8 *ies; - u16 ies_len; - void *join_params; - struct rssi_history_buffer rssi_history; - u64 tsf; -}; - -struct connect_info { - u8 bssid[6]; - u8 *req_ies; - size_t req_ies_len; - u8 *resp_ies; - u16 resp_ies_len; - u16 status; -}; - -struct disconnect_info { - u16 reason; - u8 *ie; - size_t ie_len; -}; - struct assoc_resp { __le16 capab_info; __le16 status_code; @@ -129,11 +84,6 @@ enum cfg_param { WILC_CFG_PARAM_RTS_THRESHOLD = BIT(3) }; -struct found_net_info { - u8 bssid[6]; - s8 rssi; -}; - enum scan_event { SCAN_EVENT_NETWORK_FOUND = 0, SCAN_EVENT_DONE = 1, @@ -147,72 +97,71 @@ enum conn_event { CONN_DISCONN_EVENT_FORCE_32BIT = 0xFFFFFFFF }; -typedef void (*wilc_scan_result)(enum scan_event, struct network_info *, - void *, void *); - -typedef void (*wilc_connect_result)(enum conn_event, - struct connect_info *, - u8, - struct disconnect_info *, - void *); +enum { + WILC_HIF_SDIO = 0, + WILC_HIF_SPI = BIT(0) +}; -typedef void (*wilc_remain_on_chan_expired)(void *, u32); -typedef void (*wilc_remain_on_chan_ready)(void *); +enum { + WILC_MAC_STATUS_INIT = -1, + WILC_MAC_STATUS_DISCONNECTED = 0, + WILC_MAC_STATUS_CONNECTED = 1 +}; -struct rcvd_net_info { - u8 *buffer; - u32 len; +struct wilc_rcvd_net_info { + s8 rssi; + u8 ch; + u16 frame_len; + struct ieee80211_mgmt *mgmt; }; -struct hidden_net_info { - u8 *ssid; +struct wilc_probe_ssid_info { u8 ssid_len; + u8 *ssid; }; -struct hidden_network { - struct hidden_net_info *net_info; +struct wilc_probe_ssid { + struct wilc_probe_ssid_info *ssid_info; u8 n_ssids; + u32 size; }; -struct user_scan_req { - wilc_scan_result scan_result; +struct wilc_user_scan_req { + void (*scan_result)(enum scan_event evt, + struct wilc_rcvd_net_info *info, void *priv); void *arg; u32 ch_cnt; - struct found_net_info net_info[MAX_NUM_SCANNED_NETWORKS]; }; -struct user_conn_req { - u8 *bssid; - u8 *ssid; +struct wilc_conn_info { + u8 bssid[ETH_ALEN]; u8 security; enum authtype auth_type; - size_t ssid_len; - u8 *ies; - size_t ies_len; - wilc_connect_result conn_result; - bool ht_capable; u8 ch; + u8 *req_ies; + size_t req_ies_len; + u8 *resp_ies; + u16 resp_ies_len; + u16 status; + void (*conn_result)(enum conn_event evt, u8 status, void *priv_data); void *arg; void *param; }; -struct remain_ch { +struct wilc_remain_ch { u16 ch; u32 duration; - wilc_remain_on_chan_expired expired; - wilc_remain_on_chan_ready ready; + void (*expired)(void *priv, u64 cookie); void *arg; - u32 id; + u32 cookie; }; struct wilc; struct host_if_drv { - struct user_scan_req usr_scan_req; - struct user_conn_req usr_conn_req; - struct remain_ch remain_on_ch; - u8 remain_on_ch_pending; + struct wilc_user_scan_req usr_scan_req; + struct wilc_conn_info conn_info; + struct wilc_remain_ch remain_on_ch; u64 p2p_timeout; - u8 p2p_connect; enum host_if_state hif_state; @@ -232,17 +181,6 @@ struct host_if_drv { u8 assoc_resp[WILC_MAX_ASSOC_RESP_FRAME_SIZE]; }; -struct add_sta_param { - u8 bssid[ETH_ALEN]; - u16 aid; - u8 rates_len; - const u8 *rates; - bool ht_supported; - struct ieee80211_ht_cap ht_capa; - u16 flags_mask; - u16 flags_set; -}; - struct wilc_vif; int wilc_remove_wep_key(struct wilc_vif *vif, u8 index); int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index); @@ -261,18 +199,16 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 cipher_mode); int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid); int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); -int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result connect_result, void *user_arg, - u8 security, enum authtype auth_type, - u8 channel, void *join_params); +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies, + size_t ies_len); int wilc_disconnect(struct wilc_vif *vif); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result scan_result, void *user_arg, - struct hidden_network *hidden_network); + u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, + void (*scan_result_fn)(enum scan_event, + struct wilc_rcvd_net_info *, void *), + void *user_arg, struct wilc_probe_ssid *search); int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *cfg_param); int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); @@ -287,14 +223,13 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); int wilc_edit_station(struct wilc_vif *vif, const u8 *mac, struct station_parameters *params); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); -int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count, +int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count, u8 *mc_list); -int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, +int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, u32 duration, u16 chan, - wilc_remain_on_chan_expired expired, - wilc_remain_on_chan_ready ready, + void (*expired)(void *, u64), void *user_arg); -int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); +int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie); void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, u8 ifc_id); @@ -307,4 +242,6 @@ int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length); void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length); void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length); +void *wilc_parse_join_bss_param(struct cfg80211_bss *bss, + struct cfg80211_crypto_settings *crypto); #endif diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/wilc_mon.c index a63446818eac..9fe19a3e1dd4 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/wilc_mon.c @@ -18,28 +18,20 @@ struct wilc_wfi_radiotap_cb_hdr { u16 tx_flags; } __packed; -static struct net_device *wilc_wfi_mon; /* global monitor netdev */ - -static u8 srcadd[6]; -static u8 bssid[6]; - -#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ -#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/ - #define TX_RADIOTAP_PRESENT ((1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_TX_FLAGS)) -void wilc_wfi_monitor_rx(u8 *buff, u32 size) +void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size) { u32 header, pkt_offset; struct sk_buff *skb = NULL; struct wilc_wfi_radiotap_hdr *hdr; struct wilc_wfi_radiotap_cb_hdr *cb_hdr; - if (!wilc_wfi_mon) + if (!mon_dev) return; - if (!netif_running(wilc_wfi_mon)) + if (!netif_running(mon_dev)) return; /* Get WILC header */ @@ -94,7 +86,7 @@ void wilc_wfi_monitor_rx(u8 *buff, u32 size) hdr->rate = 5; } - skb->dev = wilc_wfi_mon; + skb->dev = mon_dev; skb_reset_mac_header(skb); skb->ip_summed = CHECKSUM_UNNECESSARY; skb->pkt_type = PACKET_OTHERHOST; @@ -155,13 +147,13 @@ static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb, struct wilc_wfi_mon_priv *mon_priv; struct sk_buff *skb2; struct wilc_wfi_radiotap_cb_hdr *cb_hdr; + u8 srcadd[ETH_ALEN]; + u8 bssid[ETH_ALEN]; - if (!wilc_wfi_mon) - return -EFAULT; - - mon_priv = netdev_priv(wilc_wfi_mon); + mon_priv = netdev_priv(dev); if (!mon_priv) return -EFAULT; + rtap_len = ieee80211_get_radiotap_len(skb->data); if (skb->len < rtap_len) return -1; @@ -187,7 +179,7 @@ static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb, cb_hdr->rate = 5; cb_hdr->tx_flags = 0x0004; - skb2->dev = wilc_wfi_mon; + skb2->dev = dev; skb_reset_mac_header(skb2); skb2->ip_summed = CHECKSUM_UNNECESSARY; skb2->pkt_type = PACKET_OTHERHOST; @@ -200,8 +192,8 @@ static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb, } skb->dev = mon_priv->real_ndev; - memcpy(srcadd, &skb->data[10], 6); - memcpy(bssid, &skb->data[16], 6); + ether_addr_copy(srcadd, &skb->data[10]); + ether_addr_copy(bssid, &skb->data[16]); /* * Identify if data or mgmt packet, if source address and bssid * fields are equal send it to mgmt frames handler @@ -223,51 +215,44 @@ static const struct net_device_ops wilc_wfi_netdev_ops = { }; -struct net_device *wilc_wfi_init_mon_interface(const char *name, +struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, + const char *name, struct net_device *real_dev) { struct wilc_wfi_mon_priv *priv; /*If monitor interface is already initialized, return it*/ - if (wilc_wfi_mon) - return wilc_wfi_mon; + if (wl->monitor_dev) + return wl->monitor_dev; - wilc_wfi_mon = alloc_etherdev(sizeof(struct wilc_wfi_mon_priv)); - if (!wilc_wfi_mon) + wl->monitor_dev = alloc_etherdev(sizeof(struct wilc_wfi_mon_priv)); + if (!wl->monitor_dev) return NULL; - wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP; - strncpy(wilc_wfi_mon->name, name, IFNAMSIZ); - wilc_wfi_mon->name[IFNAMSIZ - 1] = 0; - wilc_wfi_mon->netdev_ops = &wilc_wfi_netdev_ops; - if (register_netdevice(wilc_wfi_mon)) { + wl->monitor_dev->type = ARPHRD_IEEE80211_RADIOTAP; + strncpy(wl->monitor_dev->name, name, IFNAMSIZ); + wl->monitor_dev->name[IFNAMSIZ - 1] = 0; + wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops; + + if (register_netdevice(wl->monitor_dev)) { netdev_err(real_dev, "register_netdevice failed\n"); return NULL; } - priv = netdev_priv(wilc_wfi_mon); + priv = netdev_priv(wl->monitor_dev); if (!priv) return NULL; priv->real_ndev = real_dev; - return wilc_wfi_mon; + return wl->monitor_dev; } -void wilc_wfi_deinit_mon_interface(void) +void wilc_wfi_deinit_mon_interface(struct wilc *wl) { - bool rollback_lock = false; - - if (wilc_wfi_mon) { - if (rtnl_is_locked()) { - rtnl_unlock(); - rollback_lock = true; - } - unregister_netdev(wilc_wfi_mon); + if (!wl->monitor_dev) + return; - if (rollback_lock) { - rtnl_lock(); - rollback_lock = false; - } - wilc_wfi_mon = NULL; - } + unregister_netdev(wl->monitor_dev); + free_netdev(wl->monitor_dev); + wl->monitor_dev = NULL; } diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/wilc_netdev.c index 721689048648..1787154ee088 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/wilc_netdev.c @@ -12,86 +12,7 @@ #include "wilc_wfi_cfgoperations.h" -static int dev_state_ev_handler(struct notifier_block *this, - unsigned long event, void *ptr) -{ - struct in_ifaddr *dev_iface = ptr; - struct wilc_priv *priv; - struct host_if_drv *hif_drv; - struct net_device *dev; - u8 *ip_addr_buf; - struct wilc_vif *vif; - u8 null_ip[4] = {0}; - char wlan_dev_name[5] = "wlan0"; - - if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) - return NOTIFY_DONE; - - if (memcmp(dev_iface->ifa_label, "wlan0", 5) && - memcmp(dev_iface->ifa_label, "p2p0", 4)) - return NOTIFY_DONE; - - dev = (struct net_device *)dev_iface->ifa_dev->dev; - if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) - return NOTIFY_DONE; - - priv = wiphy_priv(dev->ieee80211_ptr->wiphy); - if (!priv) - return NOTIFY_DONE; - - hif_drv = (struct host_if_drv *)priv->hif_drv; - vif = netdev_priv(dev); - if (!vif || !hif_drv) - return NOTIFY_DONE; - - switch (event) { - case NETDEV_UP: - if (vif->iftype == WILC_STATION_MODE || - vif->iftype == WILC_CLIENT_MODE) { - hif_drv->ifc_up = 1; - vif->obtaining_ip = false; - del_timer(&vif->during_ip_timer); - } - - if (vif->wilc->enable_ps) - wilc_set_power_mgmt(vif, 1, 0); - - netdev_dbg(dev, "[%s] Up IP\n", dev_iface->ifa_label); - - ip_addr_buf = (char *)&dev_iface->ifa_address; - netdev_dbg(dev, "IP add=%d:%d:%d:%d\n", - ip_addr_buf[0], ip_addr_buf[1], - ip_addr_buf[2], ip_addr_buf[3]); - - break; - - case NETDEV_DOWN: - if (vif->iftype == WILC_STATION_MODE || - vif->iftype == WILC_CLIENT_MODE) { - hif_drv->ifc_up = 0; - vif->obtaining_ip = false; - } - - if (memcmp(dev_iface->ifa_label, wlan_dev_name, 5) == 0) - wilc_set_power_mgmt(vif, 0, 0); - - wilc_resolve_disconnect_aberration(vif); - - netdev_dbg(dev, "[%s] Down IP\n", dev_iface->ifa_label); - - ip_addr_buf = null_ip; - netdev_dbg(dev, "IP add=%d:%d:%d:%d\n", - ip_addr_buf[0], ip_addr_buf[1], - ip_addr_buf[2], ip_addr_buf[3]); - - break; - - default: - break; - } - - return NOTIFY_DONE; -} +#define WILC_MULTICAST_TABLE_SIZE 8 static irqreturn_t isr_uh_routine(int irq, void *user_data) { @@ -198,7 +119,11 @@ void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode) { struct wilc_vif *vif = netdev_priv(wilc_netdev); - memcpy(vif->bssid, bssid, 6); + if (bssid) + ether_addr_copy(vif->bssid, bssid); + else + eth_zero_addr(vif->bssid); + vif->mode = mode; } @@ -214,7 +139,7 @@ int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc) return ret_val; } -static int linux_wlan_txq_task(void *vp) +static int wilc_txq_task(void *vp) { int ret; u32 txq_count; @@ -236,9 +161,11 @@ static int linux_wlan_txq_task(void *vp) do { ret = wilc_wlan_handle_txq(dev, &txq_count); if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) { - if (netif_queue_stopped(wl->vif[0]->ndev)) + if (wl->vif[0]->mac_opened && + netif_queue_stopped(wl->vif[0]->ndev)) netif_wake_queue(wl->vif[0]->ndev); - if (netif_queue_stopped(wl->vif[1]->ndev)) + if (wl->vif[1]->mac_opened && + netif_queue_stopped(wl->vif[1]->ndev)) netif_wake_queue(wl->vif[1]->ndev); } } while (ret == -ENOBUFS && !wl->close); @@ -275,7 +202,7 @@ fail: return ret; } -static int linux_wlan_start_firmware(struct net_device *dev) +static int wilc_start_firmware(struct net_device *dev) { struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; @@ -316,204 +243,169 @@ static int wilc1000_firmware_download(struct net_device *dev) return 0; } -static int linux_wlan_init_test_config(struct net_device *dev, - struct wilc_vif *vif) +static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif) { - unsigned char c_val[64]; - struct wilc *wilc = vif->wilc; struct wilc_priv *priv; struct host_if_drv *hif_drv; + u8 b; + u16 hw; + u32 w; netdev_dbg(dev, "Start configuring Firmware\n"); priv = wiphy_priv(dev->ieee80211_ptr->wiphy); hif_drv = (struct host_if_drv *)priv->hif_drv; netdev_dbg(dev, "Host = %p\n", hif_drv); - wilc_get_chipid(wilc, false); - - *(int *)c_val = 1; - - if (!wilc_wlan_cfg_set(vif, 1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0)) - goto fail; - - c_val[0] = 0; - if (!wilc_wlan_cfg_set(vif, 0, WID_PC_TEST_MODE, c_val, 1, 0, 0)) - goto fail; - c_val[0] = WILC_FW_BSS_TYPE_INFRA; - if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, c_val, 1, 0, 0)) - goto fail; - - c_val[0] = WILC_FW_TX_RATE_AUTO; - if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0)) - goto fail; - - c_val[0] = WILC_FW_OPER_MODE_G_MIXED_11B_2; - if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, c_val, 1, 0, - 0)) - goto fail; - - c_val[0] = 1; - if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0)) - goto fail; - - c_val[0] = WILC_FW_PREAMBLE_SHORT; - if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, c_val, 1, 0, 0)) + w = vif->iftype; + cpu_to_le32s(&w); + if (!wilc_wlan_cfg_set(vif, 1, WID_SET_OPERATION_MODE, (u8 *)&w, 4, + 0, 0)) goto fail; - c_val[0] = WILC_FW_11N_PROT_AUTO; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, c_val, 1, 0, 0)) + b = WILC_FW_BSS_TYPE_INFRA; + if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, &b, 1, 0, 0)) goto fail; - c_val[0] = WILC_FW_ACTIVE_SCAN; - if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, c_val, 1, 0, 0)) + b = WILC_FW_TX_RATE_AUTO; + if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, &b, 1, 0, 0)) goto fail; - c_val[0] = WILC_FW_SITE_SURVEY_OFF; - if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, c_val, 1, 0, 0)) + b = WILC_FW_OPER_MODE_G_MIXED_11B_2; + if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, &b, 1, 0, 0)) goto fail; - *((int *)c_val) = 0xffff; - if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, c_val, 2, 0, 0)) + b = WILC_FW_PREAMBLE_SHORT; + if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, &b, 1, 0, 0)) goto fail; - *((int *)c_val) = 2346; - if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0)) + b = WILC_FW_11N_PROT_AUTO; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, &b, 1, 0, 0)) goto fail; - c_val[0] = 0; - if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, c_val, 1, 0, 0)) + b = WILC_FW_ACTIVE_SCAN; + if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, &b, 1, 0, 0)) goto fail; - c_val[0] = 1; - if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, c_val, 1, 0, 0)) + b = WILC_FW_SITE_SURVEY_OFF; + if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, &b, 1, 0, 0)) goto fail; - c_val[0] = WILC_FW_NO_POWERSAVE; - if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0)) + hw = 0xffff; + cpu_to_le16s(&hw); + if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, (u8 *)&hw, 2, 0, 0)) goto fail; - c_val[0] = WILC_FW_SEC_NO; - if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, c_val, 1, 0, 0)) + hw = 2346; + cpu_to_le16s(&hw); + if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, (u8 *)&hw, 2, 0, 0)) goto fail; - c_val[0] = WILC_FW_AUTH_OPEN_SYSTEM; - if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, c_val, 1, 0, 0)) + b = 0; + if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, &b, 1, 0, 0)) goto fail; - strcpy(c_val, "123456790abcdef1234567890"); - if (!wilc_wlan_cfg_set(vif, 0, WID_WEP_KEY_VALUE, c_val, - (strlen(c_val) + 1), 0, 0)) + b = 1; + if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, &b, 1, 0, 0)) goto fail; - strcpy(c_val, "12345678"); - if (!wilc_wlan_cfg_set(vif, 0, WID_11I_PSK, c_val, (strlen(c_val)), 0, - 0)) + b = WILC_FW_NO_POWERSAVE; + if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, &b, 1, 0, 0)) goto fail; - strcpy(c_val, "password"); - if (!wilc_wlan_cfg_set(vif, 0, WID_1X_KEY, c_val, (strlen(c_val) + 1), - 0, 0)) + b = WILC_FW_SEC_NO; + if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, &b, 1, 0, 0)) goto fail; - c_val[0] = 192; - c_val[1] = 168; - c_val[2] = 1; - c_val[3] = 112; - if (!wilc_wlan_cfg_set(vif, 0, WID_1X_SERV_ADDR, c_val, 4, 0, 0)) + b = WILC_FW_AUTH_OPEN_SYSTEM; + if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, &b, 1, 0, 0)) goto fail; - c_val[0] = 3; - if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0)) + b = 3; + if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, &b, 1, 0, 0)) goto fail; - c_val[0] = 3; - if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, c_val, 1, 0, 0)) + b = 3; + if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, &b, 1, 0, 0)) goto fail; - c_val[0] = WILC_FW_ACK_POLICY_NORMAL; - if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, c_val, 1, 0, 0)) + b = WILC_FW_ACK_POLICY_NORMAL; + if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, &b, 1, 0, 0)) goto fail; - c_val[0] = 0; - if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1, + b = 0; + if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, &b, 1, 0, 0)) goto fail; - c_val[0] = 48; - if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0, - 0)) + b = 48; + if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, &b, 1, 0, 0)) goto fail; - c_val[0] = 28; - if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0, - 0)) + b = 28; + if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, &b, 1, 0, 0)) goto fail; - *((int *)c_val) = 100; - if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, c_val, 2, 0, 0)) + hw = 100; + cpu_to_le16s(&hw); + if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, (u8 *)&hw, 2, 0, 0)) goto fail; - c_val[0] = WILC_FW_REKEY_POLICY_DISABLE; - if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, c_val, 1, 0, 0)) + b = WILC_FW_REKEY_POLICY_DISABLE; + if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, &b, 1, 0, 0)) goto fail; - *((int *)c_val) = 84600; - if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, c_val, 4, 0, 0)) + w = 84600; + cpu_to_le32s(&w); + if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, (u8 *)&w, 4, 0, 0)) goto fail; - *((int *)c_val) = 500; - if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, c_val, 4, 0, + w = 500; + cpu_to_le32s(&w); + if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, (u8 *)&w, 4, 0, 0)) goto fail; - c_val[0] = 1; - if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0, + b = 1; + if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, &b, 1, 0, 0)) goto fail; - c_val[0] = WILC_FW_ERP_PROT_SELF_CTS; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0)) + b = WILC_FW_ERP_PROT_SELF_CTS; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, &b, 1, 0, 0)) goto fail; - c_val[0] = 1; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, c_val, 1, 0, 0)) + b = 1; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, &b, 1, 0, 0)) goto fail; - c_val[0] = WILC_FW_11N_OP_MODE_HT_MIXED; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, c_val, 1, 0, - 0)) + b = WILC_FW_11N_OP_MODE_HT_MIXED; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, &b, 1, 0, 0)) goto fail; - c_val[0] = 1; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0, - 0)) + b = 1; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, &b, 1, 0, 0)) goto fail; - c_val[0] = WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, + b = WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, &b, 1, 0, 0)) goto fail; - c_val[0] = WILC_FW_HT_PROT_RTS_CTS_NONHT; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0)) + b = WILC_FW_HT_PROT_RTS_CTS_NONHT; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, &b, 1, 0, 0)) goto fail; - c_val[0] = 0; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0, + b = 0; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, &b, 1, 0, 0)) goto fail; - c_val[0] = WILC_FW_SMPS_MODE_MIMO; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_SMPS_MODE, c_val, 1, 0, 0)) - goto fail; - - c_val[0] = 7; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0, - 0)) + b = 7; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, &b, 1, 0, 0)) goto fail; - c_val[0] = 1; - if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, + b = 1; + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, &b, 1, 1, 1)) goto fail; @@ -609,7 +501,7 @@ static int wlan_initialize_threads(struct net_device *dev) struct wilc_vif *vif = netdev_priv(dev); struct wilc *wilc = vif->wilc; - wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev, + wilc->txq_thread = kthread_run(wilc_txq_task, (void *)dev, "K_TXQ_TASK"); if (IS_ERR(wilc->txq_thread)) { netdev_err(dev, "couldn't create TXQ thread\n"); @@ -667,7 +559,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) goto fail_irq_enable; } - ret = linux_wlan_start_firmware(dev); + ret = wilc_start_firmware(dev); if (ret < 0) { ret = -EIO; goto fail_irq_enable; @@ -683,7 +575,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) firmware_ver[size] = '\0'; netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver); } - ret = linux_wlan_init_test_config(dev, vif); + ret = wilc_init_fw_config(dev, vif); if (ret < 0) { netdev_err(dev, "Failed to configure firmware\n"); @@ -807,12 +699,12 @@ static void wilc_set_multicast_list(struct net_device *dev) if (dev->flags & IFF_ALLMULTI || dev->mc.count > WILC_MULTICAST_TABLE_SIZE) { - wilc_setup_multicast_filter(vif, false, 0, NULL); + wilc_setup_multicast_filter(vif, 0, 0, NULL); return; } if (dev->mc.count == 0) { - wilc_setup_multicast_filter(vif, true, 0, NULL); + wilc_setup_multicast_filter(vif, 1, 0, NULL); return; } @@ -829,11 +721,11 @@ static void wilc_set_multicast_list(struct net_device *dev) cur_mc += ETH_ALEN; } - if (wilc_setup_multicast_filter(vif, true, dev->mc.count, mc_list)) + if (wilc_setup_multicast_filter(vif, 1, dev->mc.count, mc_list)) kfree(mc_list); } -static void linux_wlan_tx_complete(void *priv, int status) +static void wilc_tx_complete(void *priv, int status) { struct tx_complete_data *pv_data = priv; @@ -847,9 +739,6 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) struct wilc *wilc = vif->wilc; struct tx_complete_data *tx_data = NULL; int queue_count; - char *udp_buf; - struct iphdr *ih; - struct ethhdr *eth_h; if (skb->dev != ndev) { netdev_err(ndev, "Packet not destined to this device\n"); @@ -867,28 +756,18 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) tx_data->size = skb->len; tx_data->skb = skb; - eth_h = (struct ethhdr *)(skb->data); - if (eth_h->h_proto == cpu_to_be16(0x8e88)) - netdev_dbg(ndev, "EAPOL transmitted\n"); - - ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); - - udp_buf = (char *)ih + sizeof(struct iphdr); - if ((udp_buf[1] == 68 && udp_buf[3] == 67) || - (udp_buf[1] == 67 && udp_buf[3] == 68)) - netdev_dbg(ndev, "DHCP Message transmitted, type:%x %x %x\n", - udp_buf[248], udp_buf[249], udp_buf[250]); - vif->netstats.tx_packets++; vif->netstats.tx_bytes += tx_data->size; tx_data->bssid = wilc->vif[vif->idx]->bssid; queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data, tx_data->buff, tx_data->size, - linux_wlan_tx_complete); + wilc_tx_complete); if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) { - netif_stop_queue(wilc->vif[0]->ndev); - netif_stop_queue(wilc->vif[1]->ndev); + if (wilc->vif[0]->mac_opened) + netif_stop_queue(wilc->vif[0]->ndev); + if (wilc->vif[1]->mac_opened) + netif_stop_queue(wilc->vif[1]->ndev); } return 0; @@ -916,7 +795,6 @@ static int wilc_mac_close(struct net_device *ndev) netdev_dbg(ndev, "Deinitializing wilc1000\n"); wl->close = 1; wilc_wlan_deinitialize(ndev); - wilc_wfi_deinit_mon_interface(); } vif->mac_opened = 0; @@ -924,7 +802,8 @@ static int wilc_mac_close(struct net_device *ndev) return 0; } -void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset) +void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, + u32 pkt_offset) { unsigned int frame_len = 0; int stats; @@ -972,7 +851,7 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size) for (i = 0; i < wilc->vif_num; i++) { vif = netdev_priv(wilc->vif[i]->ndev); if (vif->monitor_flag) { - wilc_wfi_monitor_rx(buff, size); + wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size); return; } } @@ -983,6 +862,76 @@ void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size) wilc_wfi_p2p_rx(wilc->vif[1]->ndev, buff, size); } +static const struct net_device_ops wilc_netdev_ops = { + .ndo_init = mac_init_fn, + .ndo_open = wilc_mac_open, + .ndo_stop = wilc_mac_close, + .ndo_start_xmit = wilc_mac_xmit, + .ndo_get_stats = mac_stats, + .ndo_set_rx_mode = wilc_set_multicast_list, +}; + +static int dev_state_ev_handler(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct in_ifaddr *dev_iface = ptr; + struct wilc_priv *priv; + struct host_if_drv *hif_drv; + struct net_device *dev; + struct wilc_vif *vif; + + if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) + return NOTIFY_DONE; + + dev = (struct net_device *)dev_iface->ifa_dev->dev; + if (dev->netdev_ops != &wilc_netdev_ops) + return NOTIFY_DONE; + + if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) + return NOTIFY_DONE; + + priv = wiphy_priv(dev->ieee80211_ptr->wiphy); + if (!priv) + return NOTIFY_DONE; + + hif_drv = (struct host_if_drv *)priv->hif_drv; + vif = netdev_priv(dev); + if (!vif || !hif_drv) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_UP: + if (vif->iftype == WILC_STATION_MODE || + vif->iftype == WILC_CLIENT_MODE) { + hif_drv->ifc_up = 1; + vif->obtaining_ip = false; + del_timer(&vif->during_ip_timer); + } + + if (vif->wilc->enable_ps) + wilc_set_power_mgmt(vif, 1, 0); + + break; + + case NETDEV_DOWN: + if (vif->iftype == WILC_STATION_MODE || + vif->iftype == WILC_CLIENT_MODE) { + hif_drv->ifc_up = 0; + vif->obtaining_ip = false; + wilc_set_power_mgmt(vif, 0, 0); + } + + wilc_resolve_disconnect_aberration(vif); + + break; + + default: + break; + } + + return NOTIFY_DONE; +} + static struct notifier_block g_dev_notifier = { .notifier_call = dev_state_ev_handler }; @@ -1002,19 +951,15 @@ void wilc_netdev_cleanup(struct wilc *wilc) wilc->firmware = NULL; } - if (wilc->vif[0]->ndev || wilc->vif[1]->ndev) { - for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) - if (wilc->vif[i]->ndev) - if (wilc->vif[i]->mac_opened) - wilc_mac_close(wilc->vif[i]->ndev); - - for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) { + for (i = 0; i < WILC_NUM_CONCURRENT_IFC; i++) { + if (wilc->vif[i] && wilc->vif[i]->ndev) { unregister_netdev(wilc->vif[i]->ndev); wilc_free_wiphy(wilc->vif[i]->ndev); free_netdev(wilc->vif[i]->ndev); } } + wilc_wfi_deinit_mon_interface(wilc); flush_workqueue(wilc->hif_workqueue); destroy_workqueue(wilc->hif_workqueue); wilc_wlan_cfg_deinit(wilc); @@ -1023,15 +968,6 @@ void wilc_netdev_cleanup(struct wilc *wilc) } EXPORT_SYMBOL_GPL(wilc_netdev_cleanup); -static const struct net_device_ops wilc_netdev_ops = { - .ndo_init = mac_init_fn, - .ndo_open = wilc_mac_open, - .ndo_stop = wilc_mac_close, - .ndo_start_xmit = wilc_mac_xmit, - .ndo_get_stats = mac_stats, - .ndo_set_rx_mode = wilc_set_multicast_list, -}; - int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, const struct wilc_hif_func *ops) { @@ -1086,8 +1022,8 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, vif->wilc = *wilc; vif->ndev = ndev; wl->vif[i] = vif; - wl->vif_num = i; - vif->idx = wl->vif_num; + wl->vif_num = i + 1; + vif->idx = i; ndev->netdev_ops = &wilc_netdev_ops; diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index e2f739fef21c..b789c57d7e80 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -51,10 +51,6 @@ struct sdio_cmd53 { static const struct wilc_hif_func wilc_hif_sdio; -static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data); -static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data); -static int sdio_init(struct wilc *wilc, bool resume); - static void wilc_sdio_interrupt(struct sdio_func *func) { sdio_release_host(func); @@ -121,8 +117,8 @@ static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd) return ret; } -static int linux_sdio_probe(struct sdio_func *func, - const struct sdio_device_id *id) +static int wilc_sdio_probe(struct sdio_func *func, + const struct sdio_device_id *id) { struct wilc *wilc; int ret; @@ -160,7 +156,7 @@ static int linux_sdio_probe(struct sdio_func *func, return 0; } -static void linux_sdio_remove(struct sdio_func *func) +static void wilc_sdio_remove(struct sdio_func *func) { struct wilc *wilc = sdio_get_drvdata(func); @@ -170,7 +166,7 @@ static void linux_sdio_remove(struct sdio_func *func) wilc_netdev_cleanup(wilc); } -static int sdio_reset(struct wilc *wilc) +static int wilc_sdio_reset(struct wilc *wilc) { struct sdio_cmd52 cmd; int ret; @@ -205,7 +201,7 @@ static int wilc_sdio_suspend(struct device *dev) chip_allow_sleep(wilc); } - ret = sdio_reset(wilc); + ret = wilc_sdio_reset(wilc); if (ret) { dev_err(&func->dev, "Fail reset sdio\n"); return ret; @@ -215,50 +211,6 @@ static int wilc_sdio_suspend(struct device *dev) return 0; } -static int wilc_sdio_resume(struct device *dev) -{ - struct sdio_func *func = dev_to_sdio_func(dev); - struct wilc *wilc = sdio_get_drvdata(func); - - dev_info(dev, "sdio resume\n"); - sdio_release_host(func); - chip_wakeup(wilc); - sdio_init(wilc, true); - - if (wilc->suspend_event) - host_wakeup_notify(wilc); - - chip_allow_sleep(wilc); - - return 0; -} - -static const struct of_device_id wilc_of_match[] = { - { .compatible = "microchip,wilc1000-sdio", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, wilc_of_match); - -static const struct dev_pm_ops wilc_sdio_pm_ops = { - .suspend = wilc_sdio_suspend, - .resume = wilc_sdio_resume, -}; - -static struct sdio_driver wilc_sdio_driver = { - .name = SDIO_MODALIAS, - .id_table = wilc_sdio_ids, - .probe = linux_sdio_probe, - .remove = linux_sdio_remove, - .drv = { - .pm = &wilc_sdio_pm_ops, - .of_match_table = wilc_of_match, - } -}; -module_driver(wilc_sdio_driver, - sdio_register_driver, - sdio_unregister_driver); -MODULE_LICENSE("GPL"); - static int wilc_sdio_enable_interrupt(struct wilc *dev) { struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev); @@ -293,7 +245,7 @@ static void wilc_sdio_disable_interrupt(struct wilc *dev) * ********************************************/ -static int sdio_set_func0_csa_address(struct wilc *wilc, u32 adr) +static int wilc_sdio_set_func0_csa_address(struct wilc *wilc, u32 adr) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct sdio_cmd52 cmd; @@ -334,7 +286,7 @@ fail: return 0; } -static int sdio_set_func0_block_size(struct wilc *wilc, u32 block_size) +static int wilc_sdio_set_func0_block_size(struct wilc *wilc, u32 block_size) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct sdio_cmd52 cmd; @@ -370,7 +322,7 @@ fail: * ********************************************/ -static int sdio_set_func1_block_size(struct wilc *wilc, u32 block_size) +static int wilc_sdio_set_func1_block_size(struct wilc *wilc, u32 block_size) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct sdio_cmd52 cmd; @@ -404,7 +356,7 @@ fail: * Sdio interfaces * ********************************************/ -static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data) +static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; @@ -432,7 +384,7 @@ static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data) /** * set the AHB address **/ - if (!sdio_set_func0_csa_address(wilc, addr)) + if (!wilc_sdio_set_func0_csa_address(wilc, addr)) goto fail; cmd.read_write = 1; @@ -458,7 +410,7 @@ fail: return 0; } -static int sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) +static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; @@ -507,7 +459,7 @@ static int sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) cmd.buffer = buf; cmd.block_size = block_size; if (addr > 0) { - if (!sdio_set_func0_csa_address(wilc, addr)) + if (!wilc_sdio_set_func0_csa_address(wilc, addr)) goto fail; } ret = wilc_sdio_cmd53(wilc, &cmd); @@ -530,7 +482,7 @@ static int sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) cmd.block_size = block_size; if (addr > 0) { - if (!sdio_set_func0_csa_address(wilc, addr)) + if (!wilc_sdio_set_func0_csa_address(wilc, addr)) goto fail; } ret = wilc_sdio_cmd53(wilc, &cmd); @@ -548,7 +500,7 @@ fail: return 0; } -static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data) +static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; @@ -571,7 +523,7 @@ static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data) } else { struct sdio_cmd53 cmd; - if (!sdio_set_func0_csa_address(wilc, addr)) + if (!wilc_sdio_set_func0_csa_address(wilc, addr)) goto fail; cmd.read_write = 0; @@ -600,7 +552,7 @@ fail: return 0; } -static int sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) +static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; @@ -649,7 +601,7 @@ static int sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) cmd.buffer = buf; cmd.block_size = block_size; if (addr > 0) { - if (!sdio_set_func0_csa_address(wilc, addr)) + if (!wilc_sdio_set_func0_csa_address(wilc, addr)) goto fail; } ret = wilc_sdio_cmd53(wilc, &cmd); @@ -672,7 +624,7 @@ static int sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) cmd.block_size = block_size; if (addr > 0) { - if (!sdio_set_func0_csa_address(wilc, addr)) + if (!wilc_sdio_set_func0_csa_address(wilc, addr)) goto fail; } ret = wilc_sdio_cmd53(wilc, &cmd); @@ -696,12 +648,12 @@ fail: * ********************************************/ -static int sdio_deinit(struct wilc *wilc) +static int wilc_sdio_deinit(struct wilc *wilc) { return 1; } -static int sdio_init(struct wilc *wilc, bool resume) +static int wilc_sdio_init(struct wilc *wilc, bool resume) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; @@ -729,7 +681,7 @@ static int sdio_init(struct wilc *wilc, bool resume) /** * function 0 block size **/ - if (!sdio_set_func0_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) { + if (!wilc_sdio_set_func0_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) { dev_err(&func->dev, "Fail cmd 52, set func 0 block size...\n"); goto fail; } @@ -778,7 +730,7 @@ static int sdio_init(struct wilc *wilc, bool resume) /** * func 1 is ready, set func 1 block size **/ - if (!sdio_set_func1_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) { + if (!wilc_sdio_set_func1_block_size(wilc, WILC_SDIO_BLOCK_SIZE)) { dev_err(&func->dev, "Fail set func 1 block size...\n"); goto fail; } @@ -801,7 +753,7 @@ static int sdio_init(struct wilc *wilc, bool resume) * make sure can read back chip id correctly **/ if (!resume) { - if (!sdio_read_reg(wilc, 0x1000, &chipid)) { + if (!wilc_sdio_read_reg(wilc, 0x1000, &chipid)) { dev_err(&func->dev, "Fail cmd read chip id...\n"); goto fail; } @@ -821,7 +773,7 @@ fail: return 0; } -static int sdio_read_size(struct wilc *wilc, u32 *size) +static int wilc_sdio_read_size(struct wilc *wilc, u32 *size) { u32 tmp; struct sdio_cmd52 cmd; @@ -846,14 +798,14 @@ static int sdio_read_size(struct wilc *wilc, u32 *size) return 1; } -static int sdio_read_int(struct wilc *wilc, u32 *int_status) +static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; u32 tmp; struct sdio_cmd52 cmd; - sdio_read_size(wilc, &tmp); + wilc_sdio_read_size(wilc, &tmp); /** * Read IRQ flags @@ -905,7 +857,7 @@ static int sdio_read_int(struct wilc *wilc, u32 *int_status) return 1; } -static int sdio_clear_int_ext(struct wilc *wilc, u32 val) +static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; @@ -1030,7 +982,7 @@ fail: return 0; } -static int sdio_sync_ext(struct wilc *wilc, int nint) +static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); struct wilc_sdio *sdio_priv = wilc->bus_data; @@ -1051,13 +1003,13 @@ static int sdio_sync_ext(struct wilc *wilc, int nint) /** * Disable power sequencer **/ - if (!sdio_read_reg(wilc, WILC_MISC, ®)) { + if (!wilc_sdio_read_reg(wilc, WILC_MISC, ®)) { dev_err(&func->dev, "Failed read misc reg...\n"); return 0; } reg &= ~BIT(8); - if (!sdio_write_reg(wilc, WILC_MISC, reg)) { + if (!wilc_sdio_write_reg(wilc, WILC_MISC, reg)) { dev_err(&func->dev, "Failed write misc reg...\n"); return 0; } @@ -1069,14 +1021,14 @@ static int sdio_sync_ext(struct wilc *wilc, int nint) /** * interrupt pin mux select **/ - ret = sdio_read_reg(wilc, WILC_PIN_MUX_0, ®); + ret = wilc_sdio_read_reg(wilc, WILC_PIN_MUX_0, ®); if (!ret) { dev_err(&func->dev, "Failed read reg (%08x)...\n", WILC_PIN_MUX_0); return 0; } reg |= BIT(8); - ret = sdio_write_reg(wilc, WILC_PIN_MUX_0, reg); + ret = wilc_sdio_write_reg(wilc, WILC_PIN_MUX_0, reg); if (!ret) { dev_err(&func->dev, "Failed write reg (%08x)...\n", WILC_PIN_MUX_0); @@ -1086,7 +1038,7 @@ static int sdio_sync_ext(struct wilc *wilc, int nint) /** * interrupt enable **/ - ret = sdio_read_reg(wilc, WILC_INTR_ENABLE, ®); + ret = wilc_sdio_read_reg(wilc, WILC_INTR_ENABLE, ®); if (!ret) { dev_err(&func->dev, "Failed read reg (%08x)...\n", WILC_INTR_ENABLE); @@ -1095,14 +1047,14 @@ static int sdio_sync_ext(struct wilc *wilc, int nint) for (i = 0; (i < 5) && (nint > 0); i++, nint--) reg |= BIT((27 + i)); - ret = sdio_write_reg(wilc, WILC_INTR_ENABLE, reg); + ret = wilc_sdio_write_reg(wilc, WILC_INTR_ENABLE, reg); if (!ret) { dev_err(&func->dev, "Failed write reg (%08x)...\n", WILC_INTR_ENABLE); return 0; } if (nint) { - ret = sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®); + ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®); if (!ret) { dev_err(&func->dev, "Failed read reg (%08x)...\n", @@ -1113,7 +1065,7 @@ static int sdio_sync_ext(struct wilc *wilc, int nint) for (i = 0; (i < 3) && (nint > 0); i++, nint--) reg |= BIT(i); - ret = sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®); + ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®); if (!ret) { dev_err(&func->dev, "Failed write reg (%08x)...\n", @@ -1127,19 +1079,62 @@ static int sdio_sync_ext(struct wilc *wilc, int nint) /* Global sdio HIF function table */ static const struct wilc_hif_func wilc_hif_sdio = { - .hif_init = sdio_init, - .hif_deinit = sdio_deinit, - .hif_read_reg = sdio_read_reg, - .hif_write_reg = sdio_write_reg, - .hif_block_rx = sdio_read, - .hif_block_tx = sdio_write, - .hif_read_int = sdio_read_int, - .hif_clear_int_ext = sdio_clear_int_ext, - .hif_read_size = sdio_read_size, - .hif_block_tx_ext = sdio_write, - .hif_block_rx_ext = sdio_read, - .hif_sync_ext = sdio_sync_ext, + .hif_init = wilc_sdio_init, + .hif_deinit = wilc_sdio_deinit, + .hif_read_reg = wilc_sdio_read_reg, + .hif_write_reg = wilc_sdio_write_reg, + .hif_block_rx = wilc_sdio_read, + .hif_block_tx = wilc_sdio_write, + .hif_read_int = wilc_sdio_read_int, + .hif_clear_int_ext = wilc_sdio_clear_int_ext, + .hif_read_size = wilc_sdio_read_size, + .hif_block_tx_ext = wilc_sdio_write, + .hif_block_rx_ext = wilc_sdio_read, + .hif_sync_ext = wilc_sdio_sync_ext, .enable_interrupt = wilc_sdio_enable_interrupt, .disable_interrupt = wilc_sdio_disable_interrupt, }; +static int wilc_sdio_resume(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct wilc *wilc = sdio_get_drvdata(func); + + dev_info(dev, "sdio resume\n"); + sdio_release_host(func); + chip_wakeup(wilc); + wilc_sdio_init(wilc, true); + + if (wilc->suspend_event) + host_wakeup_notify(wilc); + + chip_allow_sleep(wilc); + + return 0; +} + +static const struct of_device_id wilc_of_match[] = { + { .compatible = "microchip,wilc1000-sdio", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, wilc_of_match); + +static const struct dev_pm_ops wilc_sdio_pm_ops = { + .suspend = wilc_sdio_suspend, + .resume = wilc_sdio_resume, +}; + +static struct sdio_driver wilc_sdio_driver = { + .name = SDIO_MODALIAS, + .id_table = wilc_sdio_ids, + .probe = wilc_sdio_probe, + .remove = wilc_sdio_remove, + .drv = { + .pm = &wilc_sdio_pm_ops, + .of_match_table = wilc_of_match, + } +}; +module_driver(wilc_sdio_driver, + sdio_register_driver, + sdio_unregister_driver); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 153e120eff00..4a1be9e60d74 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -814,7 +814,7 @@ static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) * ********************************************/ -static int _wilc_spi_deinit(struct wilc *wilc) +static int wilc_spi_deinit(struct wilc *wilc) { /* * TODO: @@ -1122,7 +1122,7 @@ static int wilc_spi_sync_ext(struct wilc *wilc, int nint) /* Global spi HIF function table */ static const struct wilc_hif_func wilc_hif_spi = { .hif_init = wilc_spi_init, - .hif_deinit = _wilc_spi_deinit, + .hif_deinit = wilc_spi_deinit, .hif_read_reg = wilc_spi_read_reg, .hif_write_reg = wilc_spi_write_reg, .hif_block_rx = wilc_spi_read, diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index ac47dda510e0..5e7a4676324e 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -27,10 +27,7 @@ #define GAS_INITIAL_REQ 0x0a #define GAS_INITIAL_RSP 0x0b -#define INVALID_CHANNEL 0 - -#define nl80211_SCAN_RESULT_EXPIRE (3 * HZ) -#define SCAN_RESULT_EXPIRE (40 * HZ) +#define WILC_INVALID_CHANNEL 0 static const struct ieee80211_txrx_stypes wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = { @@ -65,124 +62,15 @@ static const struct wiphy_wowlan_support wowlan_support = { .flags = WIPHY_WOWLAN_ANY }; -struct p2p_mgmt_data { +struct wilc_p2p_mgmt_data { int size; u8 *buff; }; -static u8 wlan_channel = INVALID_CHANNEL; -static u8 curr_channel; -static u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09}; -static u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03}; - -#define AGING_TIME (9 * 1000) -#define DURING_IP_TIME_OUT 15000 - -static void clear_shadow_scan(struct wilc_priv *priv) -{ - int i; - - for (i = 0; i < priv->scanned_cnt; i++) { - kfree(priv->scanned_shadow[i].ies); - priv->scanned_shadow[i].ies = NULL; - - kfree(priv->scanned_shadow[i].join_params); - priv->scanned_shadow[i].join_params = NULL; - } - priv->scanned_cnt = 0; -} - -static u32 get_rssi_avg(struct network_info *network_info) -{ - u8 i; - int rssi_v = 0; - u8 num_rssi = (network_info->rssi_history.full) ? - NUM_RSSI : (network_info->rssi_history.index); - - for (i = 0; i < num_rssi; i++) - rssi_v += network_info->rssi_history.samples[i]; - - rssi_v /= num_rssi; - return rssi_v; -} - -static void refresh_scan(struct wilc_priv *priv, bool direct_scan) -{ - struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy; - int i; - - for (i = 0; i < priv->scanned_cnt; i++) { - struct network_info *network_info; - s32 freq; - struct ieee80211_channel *channel; - int rssi; - struct cfg80211_bss *bss; - - network_info = &priv->scanned_shadow[i]; - - if (!memcmp("DIRECT-", network_info->ssid, 7) && !direct_scan) - continue; - - freq = ieee80211_channel_to_frequency((s32)network_info->ch, - NL80211_BAND_2GHZ); - channel = ieee80211_get_channel(wiphy, freq); - rssi = get_rssi_avg(network_info); - bss = cfg80211_inform_bss(wiphy, - channel, - CFG80211_BSS_FTYPE_UNKNOWN, - network_info->bssid, - network_info->tsf, - network_info->cap_info, - network_info->beacon_period, - (const u8 *)network_info->ies, - (size_t)network_info->ies_len, - (s32)rssi * 100, - GFP_KERNEL); - cfg80211_put_bss(wiphy, bss); - } -} - -static void reset_shadow_found(struct wilc_priv *priv) -{ - int i; - - for (i = 0; i < priv->scanned_cnt; i++) - priv->scanned_shadow[i].found = 0; -} - -static void update_scan_time(struct wilc_priv *priv) -{ - int i; - - for (i = 0; i < priv->scanned_cnt; i++) - priv->scanned_shadow[i].time_scan = jiffies; -} - -static void remove_network_from_shadow(struct timer_list *t) -{ - struct wilc_priv *priv = from_timer(priv, t, aging_timer); - unsigned long now = jiffies; - int i, j; - - for (i = 0; i < priv->scanned_cnt; i++) { - if (!time_after(now, priv->scanned_shadow[i].time_scan + - (unsigned long)(SCAN_RESULT_EXPIRE))) - continue; - kfree(priv->scanned_shadow[i].ies); - priv->scanned_shadow[i].ies = NULL; - - kfree(priv->scanned_shadow[i].join_params); +static const u8 p2p_oui[] = {0x50, 0x6f, 0x9A, 0x09}; +static const u8 p2p_vendor_spec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03}; - for (j = i; (j < priv->scanned_cnt - 1); j++) - priv->scanned_shadow[j] = priv->scanned_shadow[j + 1]; - - priv->scanned_cnt--; - } - - if (priv->scanned_cnt != 0) - mod_timer(&priv->aging_timer, - jiffies + msecs_to_jiffies(AGING_TIME)); -} +#define WILC_IP_TIMEOUT_MS 15000 static void clear_during_ip(struct timer_list *t) { @@ -191,151 +79,36 @@ static void clear_during_ip(struct timer_list *t) vif->obtaining_ip = false; } -static int is_network_in_shadow(struct network_info *nw_info, - struct wilc_priv *priv) -{ - int state = -1; - int i; - - if (priv->scanned_cnt == 0) { - mod_timer(&priv->aging_timer, - jiffies + msecs_to_jiffies(AGING_TIME)); - state = -1; - } else { - for (i = 0; i < priv->scanned_cnt; i++) { - if (memcmp(priv->scanned_shadow[i].bssid, - nw_info->bssid, 6) == 0) { - state = i; - break; - } - } - } - return state; -} - -static void add_network_to_shadow(struct network_info *nw_info, - struct wilc_priv *priv, void *join_params) -{ - int ap_found = is_network_in_shadow(nw_info, priv); - u32 ap_index = 0; - u8 rssi_index = 0; - struct network_info *shadow_nw_info; - - if (priv->scanned_cnt >= MAX_NUM_SCANNED_NETWORKS_SHADOW) - return; - - if (ap_found == -1) { - ap_index = priv->scanned_cnt; - priv->scanned_cnt++; - } else { - ap_index = ap_found; - } - shadow_nw_info = &priv->scanned_shadow[ap_index]; - rssi_index = shadow_nw_info->rssi_history.index; - shadow_nw_info->rssi_history.samples[rssi_index++] = nw_info->rssi; - if (rssi_index == NUM_RSSI) { - rssi_index = 0; - shadow_nw_info->rssi_history.full = true; - } - shadow_nw_info->rssi_history.index = rssi_index; - shadow_nw_info->rssi = nw_info->rssi; - shadow_nw_info->cap_info = nw_info->cap_info; - shadow_nw_info->ssid_len = nw_info->ssid_len; - memcpy(shadow_nw_info->ssid, nw_info->ssid, nw_info->ssid_len); - memcpy(shadow_nw_info->bssid, nw_info->bssid, ETH_ALEN); - shadow_nw_info->beacon_period = nw_info->beacon_period; - shadow_nw_info->dtim_period = nw_info->dtim_period; - shadow_nw_info->ch = nw_info->ch; - shadow_nw_info->tsf = nw_info->tsf; - if (ap_found != -1) - kfree(shadow_nw_info->ies); - shadow_nw_info->ies = kmemdup(nw_info->ies, nw_info->ies_len, - GFP_KERNEL); - if (shadow_nw_info->ies) - shadow_nw_info->ies_len = nw_info->ies_len; - else - shadow_nw_info->ies_len = 0; - shadow_nw_info->time_scan = jiffies; - shadow_nw_info->time_scan_cached = jiffies; - shadow_nw_info->found = 1; - if (ap_found != -1) - kfree(shadow_nw_info->join_params); - shadow_nw_info->join_params = join_params; -} - static void cfg_scan_result(enum scan_event scan_event, - struct network_info *network_info, - void *user_void, void *join_params) + struct wilc_rcvd_net_info *info, void *user_void) { - struct wilc_priv *priv; - struct wiphy *wiphy; - s32 freq; - struct ieee80211_channel *channel; - struct cfg80211_bss *bss = NULL; + struct wilc_priv *priv = user_void; - priv = user_void; if (!priv->cfg_scanning) return; if (scan_event == SCAN_EVENT_NETWORK_FOUND) { - wiphy = priv->dev->ieee80211_ptr->wiphy; - - if (!wiphy || !network_info) - return; + s32 freq; + struct ieee80211_channel *channel; + struct cfg80211_bss *bss; + struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy; - if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && - (((s32)network_info->rssi * 100) < 0 || - ((s32)network_info->rssi * 100) > 100)) + if (!wiphy || !info) return; - freq = ieee80211_channel_to_frequency((s32)network_info->ch, + freq = ieee80211_channel_to_frequency((s32)info->ch, NL80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, freq); - if (!channel) return; - if (network_info->new_network) { - if (priv->rcvd_ch_cnt >= MAX_NUM_SCANNED_NETWORKS) - return; - - priv->rcvd_ch_cnt++; - - add_network_to_shadow(network_info, priv, join_params); - - if (memcmp("DIRECT-", network_info->ssid, 7)) - return; - - bss = cfg80211_inform_bss(wiphy, - channel, - CFG80211_BSS_FTYPE_UNKNOWN, - network_info->bssid, - network_info->tsf, - network_info->cap_info, - network_info->beacon_period, - (const u8 *)network_info->ies, - (size_t)network_info->ies_len, - (s32)network_info->rssi * 100, - GFP_KERNEL); + bss = cfg80211_inform_bss_frame(wiphy, channel, info->mgmt, + info->frame_len, + (s32)info->rssi * 100, + GFP_KERNEL); + if (!bss) cfg80211_put_bss(wiphy, bss); - } else { - u32 i; - - for (i = 0; i < priv->rcvd_ch_cnt; i++) { - if (memcmp(priv->scanned_shadow[i].bssid, - network_info->bssid, 6) == 0) - break; - } - - if (i >= priv->rcvd_ch_cnt) - return; - - priv->scanned_shadow[i].rssi = network_info->rssi; - priv->scanned_shadow[i].time_scan = jiffies; - } } else if (scan_event == SCAN_EVENT_DONE) { - refresh_scan(priv, false); - mutex_lock(&priv->scan_req_lock); if (priv->scan_req) { @@ -344,7 +117,6 @@ static void cfg_scan_result(enum scan_event scan_event, }; cfg80211_scan_done(priv->scan_req, &info); - priv->rcvd_ch_cnt = 0; priv->cfg_scanning = false; priv->scan_req = NULL; } @@ -357,9 +129,6 @@ static void cfg_scan_result(enum scan_event scan_event, .aborted = false, }; - update_scan_time(priv); - refresh_scan(priv, false); - cfg80211_scan_done(priv->scan_req, &info); priv->cfg_scanning = false; priv->scan_req = NULL; @@ -368,21 +137,7 @@ static void cfg_scan_result(enum scan_event scan_event, } } -static inline bool wilc_cfg_scan_time_expired(struct wilc_priv *priv, int i) -{ - unsigned long now = jiffies; - - if (time_after(now, priv->scanned_shadow[i].time_scan_cached + - (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) - return true; - else - return false; -} - -static void cfg_connect_result(enum conn_event conn_disconn_evt, - struct connect_info *conn_info, - u8 mac_status, - struct disconnect_info *disconn_info, +static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status, void *priv_data) { struct wilc_priv *priv = priv_data; @@ -390,49 +145,28 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, struct wilc_vif *vif = netdev_priv(dev); struct wilc *wl = vif->wilc; struct host_if_drv *wfi_drv = priv->hif_drv; - u8 null_bssid[ETH_ALEN] = {0}; + struct wilc_conn_info *conn_info = &wfi_drv->conn_info; vif->connecting = false; if (conn_disconn_evt == CONN_DISCONN_EVENT_CONN_RESP) { - u16 connect_status; - - connect_status = conn_info->status; + u16 connect_status = conn_info->status; if (mac_status == WILC_MAC_STATUS_DISCONNECTED && - conn_info->status == WLAN_STATUS_SUCCESS) { + connect_status == WLAN_STATUS_SUCCESS) { connect_status = WLAN_STATUS_UNSPECIFIED_FAILURE; - wilc_wlan_set_bssid(priv->dev, null_bssid, - WILC_STATION_MODE); + wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE); - if (!wfi_drv->p2p_connect) - wlan_channel = INVALID_CHANNEL; + if (vif->iftype != WILC_CLIENT_MODE) + wl->sta_ch = WILC_INVALID_CHANNEL; netdev_err(dev, "Unspecified failure\n"); } - if (connect_status == WLAN_STATUS_SUCCESS) { - bool scan_refresh = false; - u32 i; - + if (connect_status == WLAN_STATUS_SUCCESS) memcpy(priv->associated_bss, conn_info->bssid, ETH_ALEN); - for (i = 0; i < priv->scanned_cnt; i++) { - if (memcmp(priv->scanned_shadow[i].bssid, - conn_info->bssid, - ETH_ALEN) == 0) { - if (wilc_cfg_scan_time_expired(priv, i)) - scan_refresh = true; - - break; - } - } - - if (scan_refresh) - refresh_scan(priv, true); - } - cfg80211_connect_result(dev, conn_info->bssid, conn_info->req_ies, conn_info->req_ies_len, @@ -440,23 +174,24 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, conn_info->resp_ies_len, connect_status, GFP_KERNEL); } else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) { + u16 reason = 0; + vif->obtaining_ip = false; priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; eth_zero_addr(priv->associated_bss); - wilc_wlan_set_bssid(priv->dev, null_bssid, WILC_STATION_MODE); + wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE); + + if (vif->iftype != WILC_CLIENT_MODE) + wl->sta_ch = WILC_INVALID_CHANNEL; - if (!wfi_drv->p2p_connect) - wlan_channel = INVALID_CHANNEL; if (wfi_drv->ifc_up && dev == wl->vif[1]->ndev) - disconn_info->reason = 3; + reason = 3; else if (!wfi_drv->ifc_up && dev == wl->vif[1]->ndev) - disconn_info->reason = 1; + reason = 1; - cfg80211_disconnected(dev, disconn_info->reason, - disconn_info->ie, disconn_info->ie_len, - false, GFP_KERNEL); + cfg80211_disconnected(dev, reason, NULL, 0, false, GFP_KERNEL); } } @@ -470,7 +205,7 @@ static int set_channel(struct wiphy *wiphy, channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq); - curr_channel = channelnum; + vif->wilc->op_ch = channelnum; result = wilc_set_mac_chnl_num(vif, channelnum); if (result != 0) @@ -481,22 +216,23 @@ static int set_channel(struct wiphy *wiphy, static inline int wilc_wfi_cfg_alloc_fill_ssid(struct cfg80211_scan_request *request, - struct hidden_network *ntwk) + struct wilc_probe_ssid *search) { int i; int slot_id = 0; - ntwk->net_info = kcalloc(request->n_ssids, sizeof(*ntwk->net_info), - GFP_KERNEL); - if (!ntwk->net_info) + search->ssid_info = kcalloc(request->n_ssids, + sizeof(*search->ssid_info), GFP_KERNEL); + if (!search->ssid_info) goto out; - ntwk->n_ssids = request->n_ssids; + search->n_ssids = request->n_ssids; for (i = 0; i < request->n_ssids; i++) { if (request->ssids[i].ssid_len > 0) { - struct hidden_net_info *info = &ntwk->net_info[slot_id]; + struct wilc_probe_ssid_info *info; + info = &search->ssid_info[slot_id]; info->ssid = kmemdup(request->ssids[i].ssid, request->ssids[i].ssid_len, GFP_KERNEL); @@ -506,7 +242,7 @@ wilc_wfi_cfg_alloc_fill_ssid(struct cfg80211_scan_request *request, info->ssid_len = request->ssids[i].ssid_len; slot_id++; } else { - ntwk->n_ssids -= 1; + search->n_ssids -= 1; } } return 0; @@ -514,9 +250,9 @@ wilc_wfi_cfg_alloc_fill_ssid(struct cfg80211_scan_request *request, out_free: for (i = 0; i < slot_id; i++) - kfree(ntwk->net_info[i].ssid); + kfree(search->ssid_info[i].ssid); - kfree(ntwk->net_info); + kfree(search->ssid_info); out: return -ENOMEM; @@ -528,46 +264,41 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) struct wilc_vif *vif = netdev_priv(priv->dev); u32 i; int ret = 0; - u8 scan_ch_list[MAX_NUM_SCANNED_NETWORKS]; - struct hidden_network hidden_ntwk; - - priv->scan_req = request; + u8 scan_ch_list[WILC_MAX_NUM_SCANNED_CH]; + struct wilc_probe_ssid probe_ssid; - priv->rcvd_ch_cnt = 0; - - reset_shadow_found(priv); + if (request->n_channels > WILC_MAX_NUM_SCANNED_CH) { + netdev_err(priv->dev, "Requested scanned channels over\n"); + return -EINVAL; + } + priv->scan_req = request; priv->cfg_scanning = true; - if (request->n_channels <= MAX_NUM_SCANNED_NETWORKS) { - for (i = 0; i < request->n_channels; i++) { - u16 freq = request->channels[i]->center_freq; + for (i = 0; i < request->n_channels; i++) { + u16 freq = request->channels[i]->center_freq; - scan_ch_list[i] = ieee80211_frequency_to_channel(freq); - } - - if (request->n_ssids >= 1) { - if (wilc_wfi_cfg_alloc_fill_ssid(request, - &hidden_ntwk)) { - ret = -ENOMEM; - goto out; - } + scan_ch_list[i] = ieee80211_frequency_to_channel(freq); + } - ret = wilc_scan(vif, WILC_FW_USER_SCAN, - WILC_FW_ACTIVE_SCAN, scan_ch_list, - request->n_channels, - (const u8 *)request->ie, - request->ie_len, cfg_scan_result, - (void *)priv, &hidden_ntwk); - } else { - ret = wilc_scan(vif, WILC_FW_USER_SCAN, - WILC_FW_ACTIVE_SCAN, scan_ch_list, - request->n_channels, - (const u8 *)request->ie, - request->ie_len, cfg_scan_result, - (void *)priv, NULL); + if (request->n_ssids >= 1) { + if (wilc_wfi_cfg_alloc_fill_ssid(request, &probe_ssid)) { + ret = -ENOMEM; + goto out; } + + ret = wilc_scan(vif, WILC_FW_USER_SCAN, + WILC_FW_ACTIVE_SCAN, scan_ch_list, + request->n_channels, + (const u8 *)request->ie, + request->ie_len, cfg_scan_result, + (void *)priv, &probe_ssid); } else { - netdev_err(priv->dev, "Requested scanned channels over\n"); + ret = wilc_scan(vif, WILC_FW_USER_SCAN, + WILC_FW_ACTIVE_SCAN, scan_ch_list, + request->n_channels, + (const u8 *)request->ie, + request->ie_len, cfg_scan_result, + (void *)priv, NULL); } out: @@ -585,54 +316,17 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(priv->dev); struct host_if_drv *wfi_drv = priv->hif_drv; - struct network_info *nw_info; int ret; u32 i; - u32 sel_bssi_idx = UINT_MAX; u8 security = WILC_FW_SEC_NO; enum authtype auth_type = WILC_FW_AUTH_ANY; u32 cipher_group; + struct cfg80211_bss *bss; + void *join_params; + u8 ch; vif->connecting = true; - if (!(strncmp(sme->ssid, "DIRECT-", 7))) - wfi_drv->p2p_connect = 1; - else - wfi_drv->p2p_connect = 0; - - for (i = 0; i < priv->scanned_cnt; i++) { - if (sme->ssid_len == priv->scanned_shadow[i].ssid_len && - memcmp(priv->scanned_shadow[i].ssid, - sme->ssid, - sme->ssid_len) == 0) { - if (!sme->bssid) { - if (sel_bssi_idx == UINT_MAX || - priv->scanned_shadow[i].rssi > - priv->scanned_shadow[sel_bssi_idx].rssi) - sel_bssi_idx = i; - } else { - if (memcmp(priv->scanned_shadow[i].bssid, - sme->bssid, - ETH_ALEN) == 0) { - sel_bssi_idx = i; - break; - } - } - } - } - - if (sel_bssi_idx < priv->scanned_cnt) { - nw_info = &priv->scanned_shadow[sel_bssi_idx]; - } else { - ret = -ENOENT; - goto out_error; - } - - if (ether_addr_equal_unaligned(vif->bssid, nw_info->bssid)) { - ret = -EALREADY; - goto out_error; - } - memset(priv->wep_key, 0, sizeof(priv->wep_key)); memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len)); @@ -706,31 +400,65 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, auth_type = WILC_FW_AUTH_IEEE8021; } - curr_channel = nw_info->ch; + if (wfi_drv->usr_scan_req.scan_result) { + netdev_err(vif->ndev, "%s: Scan in progress\n", __func__); + ret = -EBUSY; + goto out_error; + } - if (!wfi_drv->p2p_connect) - wlan_channel = nw_info->ch; + bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid, + sme->ssid_len, IEEE80211_BSS_TYPE_ANY, + IEEE80211_PRIVACY(sme->privacy)); + if (!bss) { + ret = -EINVAL; + goto out_error; + } - wilc_wlan_set_bssid(dev, nw_info->bssid, WILC_STATION_MODE); + if (ether_addr_equal_unaligned(vif->bssid, bss->bssid)) { + ret = -EALREADY; + goto out_put_bss; + } - ret = wilc_set_join_req(vif, nw_info->bssid, sme->ssid, - sme->ssid_len, sme->ie, sme->ie_len, - cfg_connect_result, (void *)priv, - security, auth_type, - nw_info->ch, - nw_info->join_params); - if (ret) { - u8 null_bssid[ETH_ALEN] = {0}; + join_params = wilc_parse_join_bss_param(bss, &sme->crypto); + if (!join_params) { + netdev_err(dev, "%s: failed to construct join param\n", + __func__); + ret = -EINVAL; + goto out_put_bss; + } + + ch = ieee80211_frequency_to_channel(bss->channel->center_freq); + vif->wilc->op_ch = ch; + if (vif->iftype != WILC_CLIENT_MODE) + vif->wilc->sta_ch = ch; + + wilc_wlan_set_bssid(dev, bss->bssid, WILC_STATION_MODE); + wfi_drv->conn_info.security = security; + wfi_drv->conn_info.auth_type = auth_type; + wfi_drv->conn_info.ch = ch; + wfi_drv->conn_info.conn_result = cfg_connect_result; + wfi_drv->conn_info.arg = priv; + wfi_drv->conn_info.param = join_params; + + ret = wilc_set_join_req(vif, bss->bssid, sme->ie, sme->ie_len); + if (ret) { netdev_err(dev, "wilc_set_join_req(): Error\n"); ret = -ENOENT; - if (!wfi_drv->p2p_connect) - wlan_channel = INVALID_CHANNEL; - wilc_wlan_set_bssid(dev, null_bssid, WILC_STATION_MODE); - goto out_error; - } + if (vif->iftype != WILC_CLIENT_MODE) + vif->wilc->sta_ch = WILC_INVALID_CHANNEL; + wilc_wlan_set_bssid(dev, NULL, WILC_STATION_MODE); + wfi_drv->conn_info.conn_result = NULL; + kfree(join_params); + goto out_put_bss; + } + kfree(join_params); + cfg80211_put_bss(wiphy, bss); return 0; +out_put_bss: + cfg80211_put_bss(wiphy, bss); + out_error: vif->connecting = false; return ret; @@ -742,9 +470,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(priv->dev); struct wilc *wilc = vif->wilc; - struct host_if_drv *wfi_drv; int ret; - u8 null_bssid[ETH_ALEN] = {0}; vif->connecting = false; @@ -757,15 +483,14 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, return 0; } - wfi_drv = (struct host_if_drv *)priv->hif_drv; - if (!wfi_drv->p2p_connect) - wlan_channel = INVALID_CHANNEL; - wilc_wlan_set_bssid(priv->dev, null_bssid, WILC_STATION_MODE); + if (vif->iftype != WILC_CLIENT_MODE) + wilc->sta_ch = WILC_INVALID_CHANNEL; + wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE); priv->p2p.local_random = 0x01; priv->p2p.recv_random = 0x00; priv->p2p.is_wilc_ie = false; - wfi_drv->p2p_timeout = 0; + priv->hif_drv->p2p_timeout = 0; ret = wilc_disconnect(vif); if (ret != 0) { @@ -1210,7 +935,7 @@ static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) } static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u8 ch_list_attr_idx, - u8 op_ch_attr_idx) + u8 op_ch_attr_idx, u8 sta_ch) { int i = 0; int j = 0; @@ -1221,7 +946,7 @@ static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u8 ch_list_attr_idx, for (i = ch_list_attr_idx + 3; i < limit; i++) { if (buf[i] == 0x51) { for (j = i + 2; j < ((i + 2) + buf[i + 1]); j++) - buf[j] = wlan_channel; + buf[j] = sta_ch; break; } } @@ -1229,11 +954,11 @@ static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u8 ch_list_attr_idx, if (op_ch_attr_idx) { buf[op_ch_attr_idx + 6] = 0x51; - buf[op_ch_attr_idx + 7] = wlan_channel; + buf[op_ch_attr_idx + 7] = sta_ch; } } -static void wilc_wfi_cfg_parse_rx_action(u8 *buf, u32 len) +static void wilc_wfi_cfg_parse_rx_action(u8 *buf, u32 len, u8 sta_ch) { u32 index = 0; u8 op_channel_attr_index = 0; @@ -1249,13 +974,13 @@ static void wilc_wfi_cfg_parse_rx_action(u8 *buf, u32 len) op_channel_attr_index = index; index += buf[index + 1] + 3; } - if (wlan_channel != INVALID_CHANNEL) + if (sta_ch != WILC_INVALID_CHANNEL) wilc_wfi_cfg_parse_ch_attr(buf, channel_list_attr_index, - op_channel_attr_index); + op_channel_attr_index, sta_ch); } static void wilc_wfi_cfg_parse_tx_action(u8 *buf, u32 len, bool oper_ch, - u8 iftype) + u8 iftype, u8 sta_ch) { u32 index = 0; u8 op_channel_attr_index = 0; @@ -1274,9 +999,9 @@ static void wilc_wfi_cfg_parse_tx_action(u8 *buf, u32 len, bool oper_ch, op_channel_attr_index = index; index += buf[index + 1] + 3; } - if (wlan_channel != INVALID_CHANNEL && oper_ch) + if (sta_ch != WILC_INVALID_CHANNEL && oper_ch) wilc_wfi_cfg_parse_ch_attr(buf, channel_list_attr_index, - op_channel_attr_index); + op_channel_attr_index, sta_ch); } static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff, @@ -1311,7 +1036,8 @@ static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff, if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buff[i + 2], 4))) { wilc_wfi_cfg_parse_rx_action(&buff[i + 6], - size - (i + 6)); + size - (i + 6), + vif->wilc->sta_ch); break; } } @@ -1322,6 +1048,8 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) { struct wilc_priv *priv = wiphy_priv(dev->ieee80211_ptr->wiphy); struct host_if_drv *wfi_drv = priv->hif_drv; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wl = vif->wilc; u32 header, pkt_offset; s32 freq; __le16 fc; @@ -1342,7 +1070,7 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) return; } - freq = ieee80211_channel_to_frequency(curr_channel, NL80211_BAND_2GHZ); + freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ); fc = ((struct ieee80211_hdr *)buff)->frame_control; if (!ieee80211_is_action(fc)) { @@ -1387,33 +1115,18 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) static void wilc_wfi_mgmt_tx_complete(void *priv, int status) { - struct p2p_mgmt_data *pv_data = priv; + struct wilc_p2p_mgmt_data *pv_data = priv; kfree(pv_data->buff); kfree(pv_data); } -static void wilc_wfi_remain_on_channel_ready(void *priv_data) -{ - struct wilc_priv *priv; - - priv = priv_data; - - priv->p2p_listen_state = true; - - cfg80211_ready_on_channel(priv->wdev, - priv->remain_on_ch_params.listen_cookie, - priv->remain_on_ch_params.listen_ch, - priv->remain_on_ch_params.listen_duration, - GFP_KERNEL); -} - -static void wilc_wfi_remain_on_channel_expired(void *data, u32 session_id) +static void wilc_wfi_remain_on_channel_expired(void *data, u64 cookie) { struct wilc_priv *priv = data; struct wilc_wfi_p2p_listen_params *params = &priv->remain_on_ch_params; - if (session_id != params->listen_session_id) + if (cookie != params->listen_cookie) return; priv->p2p_listen_state = false; @@ -1430,24 +1143,36 @@ static int remain_on_channel(struct wiphy *wiphy, int ret = 0; struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(priv->dev); + u64 id; if (wdev->iftype == NL80211_IFTYPE_AP) { netdev_dbg(vif->ndev, "Required while in AP mode\n"); return ret; } - curr_channel = chan->hw_value; + id = ++priv->inc_roc_cookie; + if (id == 0) + id = ++priv->inc_roc_cookie; + + ret = wilc_remain_on_channel(vif, id, duration, chan->hw_value, + wilc_wfi_remain_on_channel_expired, + (void *)priv); + if (ret) + return ret; + + vif->wilc->op_ch = chan->hw_value; priv->remain_on_ch_params.listen_ch = chan; - priv->remain_on_ch_params.listen_cookie = *cookie; + priv->remain_on_ch_params.listen_cookie = id; + *cookie = id; + priv->p2p_listen_state = true; priv->remain_on_ch_params.listen_duration = duration; - priv->remain_on_ch_params.listen_session_id++; - return wilc_remain_on_channel(vif, - priv->remain_on_ch_params.listen_session_id, - duration, chan->hw_value, - wilc_wfi_remain_on_channel_expired, - wilc_wfi_remain_on_channel_ready, (void *)priv); + cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL); + mod_timer(&vif->hif_drv->remain_on_ch_timer, + jiffies + msecs_to_jiffies(duration)); + + return ret; } static int cancel_remain_on_channel(struct wiphy *wiphy, @@ -1457,12 +1182,14 @@ static int cancel_remain_on_channel(struct wiphy *wiphy, struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(priv->dev); - return wilc_listen_state_expired(vif, - priv->remain_on_ch_params.listen_session_id); + if (cookie != priv->remain_on_ch_params.listen_cookie) + return -ENOENT; + + return wilc_listen_state_expired(vif, cookie); } static void wilc_wfi_cfg_tx_vendor_spec(struct wilc_priv *priv, - struct p2p_mgmt_data *mgmt_tx, + struct wilc_p2p_mgmt_data *mgmt_tx, struct cfg80211_mgmt_tx_params *params, u8 iftype, u32 buf_len) { @@ -1470,6 +1197,7 @@ static void wilc_wfi_cfg_tx_vendor_spec(struct wilc_priv *priv, size_t len = params->len; u32 i; u8 subtype = buf[P2P_PUB_ACTION_SUBTYPE]; + struct wilc_vif *vif = netdev_priv(priv->dev); if (subtype == GO_NEG_REQ || subtype == GO_NEG_RSP) { if (priv->p2p.local_random == 1 && @@ -1494,7 +1222,8 @@ static void wilc_wfi_cfg_tx_vendor_spec(struct wilc_priv *priv, oper_ch = true; wilc_wfi_cfg_parse_tx_action(tx_buff, len - (i + 6), - oper_ch, iftype); + oper_ch, iftype, + vif->wilc->sta_ch); break; } @@ -1520,14 +1249,14 @@ static int mgmt_tx(struct wiphy *wiphy, const u8 *buf = params->buf; size_t len = params->len; const struct ieee80211_mgmt *mgmt; - struct p2p_mgmt_data *mgmt_tx; + struct wilc_p2p_mgmt_data *mgmt_tx; struct wilc_priv *priv = wiphy_priv(wiphy); struct host_if_drv *wfi_drv = priv->hif_drv; struct wilc_vif *vif = netdev_priv(wdev->netdev); u32 buf_len = len + sizeof(p2p_vendor_spec) + sizeof(priv->p2p.local_random); int ret = 0; - *cookie = (unsigned long)buf; + *cookie = prandom_u32(); priv->tx_cookie = *cookie; mgmt = (const struct ieee80211_mgmt *)buf; @@ -1552,7 +1281,7 @@ static int mgmt_tx(struct wiphy *wiphy, if (ieee80211_is_probe_resp(mgmt->frame_control)) { wilc_set_mac_chnl_num(vif, chan->hw_value); - curr_channel = chan->hw_value; + vif->wilc->op_ch = chan->hw_value; goto out_txq_add_pkt; } @@ -1563,7 +1292,7 @@ static int mgmt_tx(struct wiphy *wiphy, if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC || buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) { wilc_set_mac_chnl_num(vif, chan->hw_value); - curr_channel = chan->hw_value; + vif->wilc->op_ch = chan->hw_value; } switch (buf[ACTION_SUBTYPE_ID]) { case GAS_INITIAL_REQ: @@ -1755,7 +1484,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, case NL80211_IFTYPE_P2P_GO: vif->obtaining_ip = true; mod_timer(&vif->during_ip_timer, - jiffies + msecs_to_jiffies(DURING_IP_TIME_OUT)); + jiffies + msecs_to_jiffies(WILC_IP_TIMEOUT_MS)); wilc_set_operation_mode(vif, WILC_AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev->iftype = type; @@ -1805,9 +1534,8 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev) int ret; struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(priv->dev); - u8 null_bssid[ETH_ALEN] = {0}; - wilc_wlan_set_bssid(dev, null_bssid, WILC_AP_MODE); + wilc_wlan_set_bssid(dev, NULL, WILC_AP_MODE); ret = wilc_del_beacon(vif); @@ -1884,7 +1612,8 @@ static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy, struct net_device *new_ifc; if (type == NL80211_IFTYPE_MONITOR) { - new_ifc = wilc_wfi_init_mon_interface(name, vif->ndev); + new_ifc = wilc_wfi_init_mon_interface(vif->wilc, name, + vif->ndev); if (new_ifc) { vif = netdev_priv(priv->wdev->netdev); vif->monitor_flag = 1; @@ -2102,7 +1831,6 @@ int wilc_init_host_int(struct net_device *net) struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr); struct wilc_vif *vif = netdev_priv(priv->dev); - timer_setup(&priv->aging_timer, remove_network_from_shadow, 0); timer_setup(&vif->during_ip_timer, clear_during_ip, 0); priv->p2p_listen_state = false; @@ -2126,8 +1854,6 @@ void wilc_deinit_host_int(struct net_device *net) mutex_destroy(&priv->scan_req_lock); ret = wilc_deinit(vif); - del_timer_sync(&priv->aging_timer); - clear_shadow_scan(priv); del_timer_sync(&vif->during_ip_timer); if (ret) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h index 4812c8e2c79b..31dfa1f141f1 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h @@ -13,9 +13,10 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, void wilc_free_wiphy(struct net_device *net); void wilc_deinit_host_int(struct net_device *net); int wilc_init_host_int(struct net_device *net); -void wilc_wfi_monitor_rx(u8 *buff, u32 size); -void wilc_wfi_deinit_mon_interface(void); -struct net_device *wilc_wfi_init_mon_interface(const char *name, +void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size); +void wilc_wfi_deinit_mon_interface(struct wilc *wl); +struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl, + const char *name, struct net_device *real_dev); void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, u16 frame_type, bool reg); diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index c6685c0c238b..df00762487c0 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -65,7 +65,6 @@ struct wilc_wfi_p2p_listen_params { struct ieee80211_channel *listen_ch; u32 listen_duration; u64 listen_cookie; - u32 listen_session_id; }; struct wilc_p2p_var { @@ -137,7 +136,6 @@ struct wilc_priv { u64 tx_cookie; bool cfg_scanning; - u32 rcvd_ch_cnt; u8 associated_bss[ETH_ALEN]; struct sta_info assoc_stainfo; @@ -155,8 +153,6 @@ struct wilc_priv { /* mutexes */ struct mutex scan_req_lock; bool p2p_listen_state; - struct timer_list aging_timer; - struct network_info scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW]; int scanned_cnt; struct wilc_p2p_var p2p; @@ -164,6 +160,7 @@ struct wilc_priv { struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)]; struct ieee80211_supported_band band; u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)]; + u64 inc_roc_cookie; }; struct frame_reg { @@ -251,7 +248,7 @@ struct wilc { struct mutex cfg_cmd_lock; struct wilc_cfg_frame cfg_frame; u32 cfg_frame_offset; - int cfg_seq_no; + u8 cfg_seq_no; u8 *rx_buffer; u32 rx_buffer_offset; @@ -273,13 +270,18 @@ struct wilc { enum chip_ps_states chip_ps_state; struct wilc_cfg cfg; void *bus_data; + struct net_device *monitor_dev; + /* deinit lock */ + struct mutex deinit_lock; + u8 sta_ch; + u8 op_ch; }; struct wilc_wfi_mon_priv { struct net_device *real_ndev; }; -void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset); +void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset); void wilc_mac_indicate(struct wilc *wilc); void wilc_netdev_cleanup(struct wilc *wilc); int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 489e5a5038f8..c2389695fe20 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -274,7 +274,8 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer, } int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, - u32 buffer_size, wilc_tx_complete_func_t func) + u32 buffer_size, + void (*tx_complete_fn)(void *, int)) { struct txq_entry_t *tqe; struct wilc_vif *vif = netdev_priv(dev); @@ -292,7 +293,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->type = WILC_NET_PKT; tqe->buffer = buffer; tqe->buffer_size = buffer_size; - tqe->tx_complete_func = func; + tqe->tx_complete_func = tx_complete_fn; tqe->priv = priv; tqe->ack_idx = NOT_TCP_ACK; @@ -303,7 +304,8 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, } int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, - u32 buffer_size, wilc_tx_complete_func_t func) + u32 buffer_size, + void (*tx_complete_fn)(void *, int)) { struct txq_entry_t *tqe; struct wilc_vif *vif = netdev_priv(dev); @@ -321,7 +323,7 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->type = WILC_MGMT_PKT; tqe->buffer = buffer; tqe->buffer_size = buffer_size; - tqe->tx_complete_func = func; + tqe->tx_complete_func = tx_complete_fn; tqe->priv = priv; tqe->ack_idx = NOT_TCP_ACK; wilc_wlan_txq_add_to_tail(dev, tqe); @@ -521,7 +523,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (vmm_sz & 0x3) vmm_sz = (vmm_sz + 4) & ~0x3; - if ((sum + vmm_sz) > LINUX_TX_SIZE) + if ((sum + vmm_sz) > WILC_TX_BUFF_SIZE) break; vmm_table[i] = vmm_sz / 4; @@ -715,9 +717,8 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size) } else { if (!is_cfg_packet) { if (pkt_len > 0) { - wilc_frmw_to_linux(wilc, buff_ptr, - pkt_len, - pkt_offset); + wilc_frmw_to_host(wilc, buff_ptr, + pkt_len, pkt_offset); } } else { struct wilc_cfg_rsp rsp; @@ -809,7 +810,7 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) if (size <= 0) return; - if (LINUX_RX_SIZE - offset < size) + if (WILC_RX_BUFF_SIZE - offset < size) offset = 0; buffer = &wilc->rx_buffer[offset]; @@ -1092,24 +1093,19 @@ static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type, { struct wilc *wilc = vif->wilc; struct wilc_cfg_frame *cfg = &wilc->cfg_frame; - int total_len = wilc->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE; - int seq_no = wilc->cfg_seq_no % 256; - int driver_handler = (u32)drv_handler; + int t_len = wilc->cfg_frame_offset + sizeof(struct wilc_cfg_cmd_hdr); if (type == WILC_CFG_SET) - cfg->wid_header[0] = 'W'; + cfg->hdr.cmd_type = 'W'; else - cfg->wid_header[0] = 'Q'; - cfg->wid_header[1] = seq_no; - cfg->wid_header[2] = (u8)total_len; - cfg->wid_header[3] = (u8)(total_len >> 8); - cfg->wid_header[4] = (u8)driver_handler; - cfg->wid_header[5] = (u8)(driver_handler >> 8); - cfg->wid_header[6] = (u8)(driver_handler >> 16); - cfg->wid_header[7] = (u8)(driver_handler >> 24); - wilc->cfg_seq_no = seq_no; - - if (!wilc_wlan_txq_add_cfg_pkt(vif, &cfg->wid_header[0], total_len)) + cfg->hdr.cmd_type = 'Q'; + + cfg->hdr.seq_no = wilc->cfg_seq_no % 256; + cfg->hdr.total_len = cpu_to_le16(t_len); + cfg->hdr.driver_handler = cpu_to_le32(drv_handler); + wilc->cfg_seq_no = cfg->hdr.seq_no; + + if (!wilc_wlan_txq_add_cfg_pkt(vif, (u8 *)&cfg->hdr, t_len)) return -1; return 0; @@ -1144,7 +1140,7 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, ret_size = 0; if (!wait_for_completion_timeout(&wilc->cfg_event, - msecs_to_jiffies(CFG_PKTS_TIMEOUT))) { + WILC_CFG_PKTS_TIMEOUT)) { netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__); ret_size = 0; } @@ -1182,7 +1178,7 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, ret_size = 0; if (!wait_for_completion_timeout(&wilc->cfg_event, - msecs_to_jiffies(CFG_PKTS_TIMEOUT))) { + WILC_CFG_PKTS_TIMEOUT)) { netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__); ret_size = 0; } @@ -1317,7 +1313,7 @@ int wilc_wlan_init(struct net_device *dev) } if (!wilc->tx_buffer) - wilc->tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL); + wilc->tx_buffer = kmalloc(WILC_TX_BUFF_SIZE, GFP_KERNEL); if (!wilc->tx_buffer) { ret = -ENOBUFS; @@ -1325,7 +1321,7 @@ int wilc_wlan_init(struct net_device *dev) } if (!wilc->rx_buffer) - wilc->rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL); + wilc->rx_buffer = kmalloc(WILC_RX_BUFF_SIZE, GFP_KERNEL); if (!wilc->rx_buffer) { ret = -ENOBUFS; diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 27667131de1a..1a27f62589a2 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -14,7 +14,6 @@ * Mac eth header length * ********************************************/ -#define DRIVER_HANDLER_SIZE 4 #define MAX_MAC_HDR_LEN 26 /* QOS_MAC_HDR_LEN */ #define SUB_MSDU_HEADER_LENGTH 14 #define SNAP_HDR_LEN 8 @@ -132,8 +131,8 @@ #define WILC_PLL_TO_SPI 2 #define ABORT_INT BIT(31) -#define LINUX_RX_SIZE (96 * 1024) -#define LINUX_TX_SIZE (64 * 1024) +#define WILC_RX_BUFF_SIZE (96 * 1024) +#define WILC_TX_BUFF_SIZE (64 * 1024) #define MODALIAS "WILC_SPI" #define GPIO_NUM 0x44 @@ -197,7 +196,7 @@ #define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM) #define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM) /*time for expiring the completion of cfg packets*/ -#define CFG_PKTS_TIMEOUT 2000 +#define WILC_CFG_PKTS_TIMEOUT msecs_to_jiffies(2000) #define IS_MANAGMEMENT 0x100 #define IS_MANAGMEMENT_CALLBACK 0x080 @@ -249,16 +248,30 @@ struct wilc_hif_func { void (*disable_interrupt)(struct wilc *nic); }; -#define MAX_CFG_FRAME_SIZE 1468 +#define WILC_MAX_CFG_FRAME_SIZE 1468 + +struct tx_complete_data { + int size; + void *buff; + u8 *bssid; + struct sk_buff *skb; +}; + +struct wilc_cfg_cmd_hdr { + u8 cmd_type; + u8 seq_no; + __le16 total_len; + __le32 driver_handler; +}; struct wilc_cfg_frame { - u8 wid_header[8]; - u8 frame[MAX_CFG_FRAME_SIZE]; + struct wilc_cfg_cmd_hdr hdr; + u8 frame[WILC_MAX_CFG_FRAME_SIZE]; }; struct wilc_cfg_rsp { - int type; - u32 seq_no; + u8 type; + u8 seq_no; }; struct wilc; @@ -269,7 +282,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, int wilc_wlan_start(struct wilc *wilc); int wilc_wlan_stop(struct wilc *wilc); int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, - u32 buffer_size, wilc_tx_complete_func_t func); + u32 buffer_size, + void (*tx_complete_fn)(void *, int)); int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count); void wilc_handle_isr(struct wilc *wilc); void wilc_wlan_cleanup(struct net_device *dev); @@ -280,7 +294,7 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer, u32 buffer_size); int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, - u32 buffer_size, wilc_tx_complete_func_t func); + u32 buffer_size, void (*func)(void *, int)); void wilc_chip_sleep_manually(struct wilc *wilc); void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value); @@ -294,4 +308,6 @@ void chip_allow_sleep(struct wilc *wilc); void chip_wakeup(struct wilc *wilc); int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count, u32 drv); +int wilc_wlan_init(struct net_device *dev); +u32 wilc_get_chipid(struct wilc *wilc, bool update); #endif diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index 8390766358da..9dc5de4eb08d 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -54,7 +54,7 @@ static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8) { u8 *buf; - if ((offset + 4) >= MAX_CFG_FRAME_SIZE) + if ((offset + 4) >= WILC_MAX_CFG_FRAME_SIZE) return 0; buf = &frame[offset]; @@ -71,7 +71,7 @@ static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16) { u8 *buf; - if ((offset + 5) >= MAX_CFG_FRAME_SIZE) + if ((offset + 5) >= WILC_MAX_CFG_FRAME_SIZE) return 0; buf = &frame[offset]; @@ -90,7 +90,7 @@ static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32) { u8 *buf; - if ((offset + 7) >= MAX_CFG_FRAME_SIZE) + if ((offset + 7) >= WILC_MAX_CFG_FRAME_SIZE) return 0; buf = &frame[offset]; @@ -112,7 +112,7 @@ static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str, { u8 *buf; - if ((offset + size + 4) >= MAX_CFG_FRAME_SIZE) + if ((offset + size + 4) >= WILC_MAX_CFG_FRAME_SIZE) return 0; buf = &frame[offset]; @@ -134,7 +134,7 @@ static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) u32 i; u8 checksum = 0; - if ((offset + size + 5) >= MAX_CFG_FRAME_SIZE) + if ((offset + size + 5) >= WILC_MAX_CFG_FRAME_SIZE) return 0; buf = &frame[offset]; @@ -168,7 +168,7 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) while (size > 0) { i = 0; - wid = info[0] | (info[1] << 8); + wid = get_unaligned_le16(info); switch (GET_WID_TYPE(wid)) { case WID_CHAR: @@ -187,12 +187,13 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) case WID_SHORT: do { - if (wl->cfg.hw[i].id == WID_NIL) + struct wilc_cfg_hword *hw = &wl->cfg.hw[i]; + + if (hw->id == WID_NIL) break; - if (wl->cfg.hw[i].id == wid) { - wl->cfg.hw[i].val = (info[4] | - (info[5] << 8)); + if (hw->id == wid) { + hw->val = get_unaligned_le16(&info[4]); break; } i++; @@ -202,14 +203,13 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size) case WID_INT: do { - if (wl->cfg.w[i].id == WID_NIL) + struct wilc_cfg_word *w = &wl->cfg.w[i]; + + if (w->id == WID_NIL) break; - if (wl->cfg.w[i].id == wid) { - wl->cfg.w[i].val = (info[4] | - (info[5] << 8) | - (info[6] << 16) | - (info[7] << 24)); + if (w->id == wid) { + w->val = get_unaligned_le32(&info[4]); break; } i++; @@ -244,7 +244,7 @@ static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info) { u32 wid, len; - wid = info[0] | (info[1] << 8); + wid = get_unaligned_le16(info); len = info[2]; @@ -309,7 +309,7 @@ int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id) { u8 *buf; - if ((offset + 2) >= MAX_CFG_FRAME_SIZE) + if ((offset + 2) >= WILC_MAX_CFG_FRAME_SIZE) return 0; buf = &frame[offset]; @@ -371,8 +371,7 @@ int wilc_wlan_cfg_get_wid_value(struct wilc *wl, u16 wid, u8 *buffer, break; if (id == wid) { - u32 size = (wl->cfg.s[i].str[0] | - (wl->cfg.s[i].str[1] << 8)); + u16 size = get_unaligned_le16(wl->cfg.s[i].str); if (buffer_size >= size) { memcpy(buffer, &wl->cfg.s[i].str[2], diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index e2310d860291..b15de36e32e0 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -11,44 +11,9 @@ /******************************************** * - * Host Interface Defines - * - ********************************************/ - -enum { - WILC_HIF_SDIO = 0, - WILC_HIF_SPI = BIT(0) -}; - -/******************************************** - * - * Wlan Interface Defines - * - ********************************************/ - -enum { - WILC_MAC_STATUS_INIT = -1, - WILC_MAC_STATUS_DISCONNECTED = 0, - WILC_MAC_STATUS_CONNECTED = 1 -}; - -struct tx_complete_data { - int size; - void *buff; - u8 *bssid; - struct sk_buff *skb; -}; - -typedef void (*wilc_tx_complete_func_t)(void *, int); - -/******************************************** - * * Wlan Configuration ID * ********************************************/ -#define WILC_MULTICAST_TABLE_SIZE 8 -#define MAX_SSID_LEN 33 -#define MAX_RATES_SUPPORTED 12 enum bss_types { WILC_FW_BSS_TYPE_INFRA = 0, @@ -689,7 +654,6 @@ enum { WID_TX_POWER_LEVEL_11N = 0x00B1, /* Custom Character WID list */ - WID_PC_TEST_MODE = 0x00C8, /* SCAN Complete notification WID*/ WID_SCAN_COMPLETE = 0x00C9, @@ -836,8 +800,4 @@ enum { WID_MAX = 0xFFFF }; -struct wilc; -int wilc_wlan_init(struct net_device *dev); -u32 wilc_get_chipid(struct wilc *wilc, bool update); - #endif |