diff options
Diffstat (limited to 'drivers/staging/wilc1000/host_interface.c')
-rw-r--r-- | drivers/staging/wilc1000/host_interface.c | 2788 |
1 files changed, 740 insertions, 2048 deletions
diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 01db8999335e..70c854d939ce 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -13,80 +13,11 @@ #define REAL_JOIN_REQ 0 -struct host_if_wpa_attr { - u8 *key; - const u8 *mac_addr; - u8 *seq; - u8 seq_len; - u8 index; - u8 key_len; - u8 mode; -}; - -struct host_if_wep_attr { - u8 *key; - u8 key_len; - u8 index; - u8 mode; - enum authtype auth_type; -}; - -union host_if_key_attr { - struct host_if_wep_attr wep; - struct host_if_wpa_attr wpa; - struct host_if_pmkid_attr pmkid; -}; - -struct key_attr { - enum KEY_TYPE type; - u8 action; - union host_if_key_attr attr; -}; - -struct scan_attr { - u8 src; - u8 type; - u8 *ch_freq_list; - u8 ch_list_len; - u8 *ies; - size_t ies_len; - wilc_scan_result result; - void *arg; - struct hidden_network hidden_network; -}; - -struct connect_attr { - u8 *bssid; - u8 *ssid; - size_t ssid_len; - u8 *ies; - size_t ies_len; - u8 security; - wilc_connect_result result; - void *arg; - enum authtype auth_type; - u8 ch; - void *params; -}; - struct rcvd_async_info { u8 *buffer; u32 len; }; -struct channel_attr { - u8 set_ch; -}; - -struct beacon_attr { - u32 interval; - u32 dtim_period; - u32 head_len; - u8 *head; - u32 tail_len; - u8 *tail; -}; - struct set_multicast { bool enabled; u32 cnt; @@ -94,58 +25,58 @@ struct set_multicast { }; struct del_all_sta { - u8 del_all_sta[MAX_NUM_STA][ETH_ALEN]; u8 assoc_sta; + u8 mac[WILC_MAX_NUM_STA][ETH_ALEN]; }; -struct del_sta { - u8 mac_addr[ETH_ALEN]; +struct wilc_op_mode { + __le32 mode; }; -struct power_mgmt_param { - bool enabled; - u32 timeout; -}; +struct wilc_reg_frame { + bool reg; + u8 reg_id; + __le32 frame_type; +} __packed; -struct set_ip_addr { - u8 *ip_addr; - u8 idx; -}; +struct wilc_drv_handler { + __le32 handler; + u8 mode; +} __packed; -struct sta_inactive_t { - u32 inactive_time; - u8 mac[6]; -}; +struct wilc_wep_key { + u8 index; + u8 key_len; + u8 key[0]; +} __packed; -struct tx_power { - u8 tx_pwr; -}; +struct wilc_sta_wpa_ptk { + u8 mac_addr[ETH_ALEN]; + u8 key_len; + u8 key[0]; +} __packed; + +struct wilc_ap_wpa_ptk { + u8 mac_addr[ETH_ALEN]; + u8 index; + u8 key_len; + u8 key[0]; +} __packed; + +struct wilc_gtk_key { + u8 mac_addr[ETH_ALEN]; + u8 rsc[8]; + u8 index; + u8 key_len; + u8 key[0]; +} __packed; union message_body { - struct scan_attr scan_info; - struct connect_attr con_info; struct rcvd_net_info net_info; struct rcvd_async_info async_info; - struct key_attr key_info; - struct cfg_param_attr cfg_info; - struct channel_attr channel_info; - struct beacon_attr beacon_info; - struct add_sta_param add_sta_info; - struct del_sta del_sta_info; - struct add_sta_param edit_sta_info; - struct power_mgmt_param pwr_mgmt_info; - struct sta_inactive_t mac_info; - struct set_ip_addr ip_info; - struct drv_handler drv; struct set_multicast multicast_info; - struct op_mode mode; - struct get_mac_addr get_mac_info; - struct ba_session_info session_info; struct remain_ch remain_on_ch; - struct reg_frame reg_frame; char *data; - struct del_all_sta del_all_sta_info; - struct tx_power tx_power; }; struct host_if_msg { @@ -242,422 +173,12 @@ static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx) { int index = idx - 1; - if (index < 0 || index >= NUM_CONCURRENT_IFC) + if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC) return NULL; return wilc->vif[index]; } -static void handle_set_channel(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct channel_attr *hif_set_ch = &msg->body.channel_info; - int ret; - struct wid wid; - - wid.id = WID_CURRENT_CHANNEL; - wid.type = WID_CHAR; - wid.val = (char *)&hif_set_ch->set_ch; - wid.size = sizeof(char); - - ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - - if (ret) - netdev_err(vif->ndev, "Failed to set channel\n"); - kfree(msg); -} - -static void handle_set_wfi_drv_handler(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct drv_handler *hif_drv_handler = &msg->body.drv; - int ret; - struct wid wid; - u8 *currbyte, *buffer; - struct host_if_drv *hif_drv; - - if (!vif->hif_drv || !hif_drv_handler) - goto free_msg; - - hif_drv = vif->hif_drv; - - buffer = kzalloc(DRV_HANDLER_SIZE, GFP_KERNEL); - if (!buffer) - goto free_msg; - - currbyte = buffer; - *currbyte = hif_drv->driver_handler_id & DRV_HANDLER_MASK; - currbyte++; - *currbyte = (u32)0 & DRV_HANDLER_MASK; - currbyte++; - *currbyte = (u32)0 & DRV_HANDLER_MASK; - currbyte++; - *currbyte = (u32)0 & DRV_HANDLER_MASK; - currbyte++; - *currbyte = (hif_drv_handler->name | (hif_drv_handler->mode << 1)); - - wid.id = WID_SET_DRV_HANDLER; - wid.type = WID_STR; - wid.val = (s8 *)buffer; - wid.size = DRV_HANDLER_SIZE; - - ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - hif_drv->driver_handler_id); - if (ret) - netdev_err(vif->ndev, "Failed to set driver handler\n"); - - kfree(buffer); - -free_msg: - if (msg->is_sync) - complete(&msg->work_comp); - - kfree(msg); -} - -static void handle_set_operation_mode(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct op_mode *hif_op_mode = &msg->body.mode; - int ret; - struct wid wid; - - wid.id = WID_SET_OPERATION_MODE; - wid.type = WID_INT; - wid.val = (s8 *)&hif_op_mode->mode; - wid.size = sizeof(u32); - - ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - - if (ret) - netdev_err(vif->ndev, "Failed to set operation mode\n"); - - kfree(msg); -} - -static void handle_get_mac_address(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct get_mac_addr *get_mac_addr = &msg->body.get_mac_info; - int ret; - struct wid wid; - - wid.id = WID_MAC_ADDR; - wid.type = WID_STR; - wid.val = get_mac_addr->mac_addr; - wid.size = ETH_ALEN; - - ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - - if (ret) - netdev_err(vif->ndev, "Failed to get mac address\n"); - complete(&msg->work_comp); - /* free 'msg' data later, in caller */ -} - -static void handle_cfg_param(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct cfg_param_attr *param = &msg->body.cfg_info; - int ret; - struct wid wid_list[32]; - struct host_if_drv *hif_drv = vif->hif_drv; - int i = 0; - - mutex_lock(&hif_drv->cfg_values_lock); - - if (param->flag & BSS_TYPE) { - u8 bss_type = param->bss_type; - - if (bss_type < 6) { - wid_list[i].id = WID_BSS_TYPE; - wid_list[i].val = (s8 *)¶m->bss_type; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.bss_type = bss_type; - } else { - netdev_err(vif->ndev, "check value 6 over\n"); - goto unlock; - } - i++; - } - if (param->flag & AUTH_TYPE) { - u8 auth_type = param->auth_type; - - if (auth_type == 1 || auth_type == 2 || auth_type == 5) { - wid_list[i].id = WID_AUTH_TYPE; - wid_list[i].val = (s8 *)¶m->auth_type; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.auth_type = auth_type; - } else { - netdev_err(vif->ndev, "Impossible value\n"); - goto unlock; - } - i++; - } - if (param->flag & AUTHEN_TIMEOUT) { - if (param->auth_timeout > 0) { - wid_list[i].id = WID_AUTH_TIMEOUT; - wid_list[i].val = (s8 *)¶m->auth_timeout; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.auth_timeout = param->auth_timeout; - } else { - netdev_err(vif->ndev, "Range(1 ~ 65535) over\n"); - goto unlock; - } - i++; - } - if (param->flag & POWER_MANAGEMENT) { - u8 pm_mode = param->power_mgmt_mode; - - if (pm_mode < 5) { - wid_list[i].id = WID_POWER_MANAGEMENT; - wid_list[i].val = (s8 *)¶m->power_mgmt_mode; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.power_mgmt_mode = pm_mode; - } else { - netdev_err(vif->ndev, "Invalid power mode\n"); - goto unlock; - } - i++; - } - if (param->flag & RETRY_SHORT) { - u16 retry_limit = param->short_retry_limit; - - if (retry_limit > 0 && retry_limit < 256) { - wid_list[i].id = WID_SHORT_RETRY_LIMIT; - wid_list[i].val = (s8 *)¶m->short_retry_limit; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.short_retry_limit = retry_limit; - } else { - netdev_err(vif->ndev, "Range(1~256) over\n"); - goto unlock; - } - i++; - } - if (param->flag & RETRY_LONG) { - u16 limit = param->long_retry_limit; - - if (limit > 0 && limit < 256) { - wid_list[i].id = WID_LONG_RETRY_LIMIT; - wid_list[i].val = (s8 *)¶m->long_retry_limit; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.long_retry_limit = limit; - } else { - netdev_err(vif->ndev, "Range(1~256) over\n"); - goto unlock; - } - i++; - } - if (param->flag & FRAG_THRESHOLD) { - u16 frag_th = param->frag_threshold; - - if (frag_th > 255 && frag_th < 7937) { - wid_list[i].id = WID_FRAG_THRESHOLD; - wid_list[i].val = (s8 *)¶m->frag_threshold; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.frag_threshold = frag_th; - } else { - netdev_err(vif->ndev, "Threshold Range fail\n"); - goto unlock; - } - i++; - } - if (param->flag & RTS_THRESHOLD) { - u16 rts_th = param->rts_threshold; - - if (rts_th > 255) { - wid_list[i].id = WID_RTS_THRESHOLD; - wid_list[i].val = (s8 *)¶m->rts_threshold; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.rts_threshold = rts_th; - } else { - netdev_err(vif->ndev, "Threshold Range fail\n"); - goto unlock; - } - i++; - } - if (param->flag & PREAMBLE) { - u16 preamble_type = param->preamble_type; - - if (param->preamble_type < 3) { - wid_list[i].id = WID_PREAMBLE; - wid_list[i].val = (s8 *)¶m->preamble_type; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.preamble_type = preamble_type; - } else { - netdev_err(vif->ndev, "Preamble Range(0~2) over\n"); - goto unlock; - } - i++; - } - if (param->flag & SHORT_SLOT_ALLOWED) { - u8 slot_allowed = param->short_slot_allowed; - - if (slot_allowed < 2) { - wid_list[i].id = WID_SHORT_SLOT_ALLOWED; - wid_list[i].val = (s8 *)¶m->short_slot_allowed; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.short_slot_allowed = slot_allowed; - } else { - netdev_err(vif->ndev, "Short slot(2) over\n"); - goto unlock; - } - i++; - } - if (param->flag & TXOP_PROT_DISABLE) { - u8 prot_disabled = param->txop_prot_disabled; - - if (param->txop_prot_disabled < 2) { - wid_list[i].id = WID_11N_TXOP_PROT_DISABLE; - wid_list[i].val = (s8 *)¶m->txop_prot_disabled; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.txop_prot_disabled = prot_disabled; - } else { - netdev_err(vif->ndev, "TXOP prot disable\n"); - goto unlock; - } - i++; - } - if (param->flag & BEACON_INTERVAL) { - u16 beacon_interval = param->beacon_interval; - - if (beacon_interval > 0) { - wid_list[i].id = WID_BEACON_INTERVAL; - wid_list[i].val = (s8 *)¶m->beacon_interval; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.beacon_interval = beacon_interval; - } else { - netdev_err(vif->ndev, "Beacon interval(1~65535)fail\n"); - goto unlock; - } - i++; - } - if (param->flag & DTIM_PERIOD) { - if (param->dtim_period > 0 && param->dtim_period < 256) { - wid_list[i].id = WID_DTIM_PERIOD; - wid_list[i].val = (s8 *)¶m->dtim_period; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.dtim_period = param->dtim_period; - } else { - netdev_err(vif->ndev, "DTIM range(1~255) fail\n"); - goto unlock; - } - i++; - } - if (param->flag & SITE_SURVEY) { - enum site_survey enabled = param->site_survey_enabled; - - if (enabled < 3) { - wid_list[i].id = WID_SITE_SURVEY; - wid_list[i].val = (s8 *)¶m->site_survey_enabled; - wid_list[i].type = WID_CHAR; - wid_list[i].size = sizeof(char); - hif_drv->cfg_values.site_survey_enabled = enabled; - } else { - netdev_err(vif->ndev, "Site survey disable\n"); - goto unlock; - } - i++; - } - if (param->flag & SITE_SURVEY_SCAN_TIME) { - u16 scan_time = param->site_survey_scan_time; - - if (scan_time > 0) { - wid_list[i].id = WID_SITE_SURVEY_SCAN_TIME; - wid_list[i].val = (s8 *)¶m->site_survey_scan_time; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.site_survey_scan_time = scan_time; - } else { - netdev_err(vif->ndev, "Site scan time(1~65535) over\n"); - goto unlock; - } - i++; - } - if (param->flag & ACTIVE_SCANTIME) { - u16 active_scan_time = param->active_scan_time; - - if (active_scan_time > 0) { - wid_list[i].id = WID_ACTIVE_SCAN_TIME; - wid_list[i].val = (s8 *)¶m->active_scan_time; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.active_scan_time = active_scan_time; - } else { - netdev_err(vif->ndev, "Active time(1~65535) over\n"); - goto unlock; - } - i++; - } - if (param->flag & PASSIVE_SCANTIME) { - u16 time = param->passive_scan_time; - - if (time > 0) { - wid_list[i].id = WID_PASSIVE_SCAN_TIME; - wid_list[i].val = (s8 *)¶m->passive_scan_time; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.passive_scan_time = time; - } else { - netdev_err(vif->ndev, "Passive time(1~65535) over\n"); - goto unlock; - } - i++; - } - if (param->flag & CURRENT_TX_RATE) { - enum current_tx_rate curr_tx_rate = param->curr_tx_rate; - - if (curr_tx_rate == AUTORATE || curr_tx_rate == MBPS_1 || - curr_tx_rate == MBPS_2 || curr_tx_rate == MBPS_5_5 || - curr_tx_rate == MBPS_11 || curr_tx_rate == MBPS_6 || - curr_tx_rate == MBPS_9 || curr_tx_rate == MBPS_12 || - curr_tx_rate == MBPS_18 || curr_tx_rate == MBPS_24 || - curr_tx_rate == MBPS_36 || curr_tx_rate == MBPS_48 || - curr_tx_rate == MBPS_54) { - wid_list[i].id = WID_CURRENT_TX_RATE; - wid_list[i].val = (s8 *)&curr_tx_rate; - wid_list[i].type = WID_SHORT; - wid_list[i].size = sizeof(u16); - hif_drv->cfg_values.curr_tx_rate = (u8)curr_tx_rate; - } else { - netdev_err(vif->ndev, "out of TX rate\n"); - goto unlock; - } - i++; - } - - ret = wilc_send_config_pkt(vif, SET_CFG, wid_list, - i, wilc_get_vif_idx(vif)); - - if (ret) - netdev_err(vif->ndev, "Error in setting CFG params\n"); - -unlock: - mutex_unlock(&hif_drv->cfg_values_lock); - kfree(msg); -} - static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt) { int result = 0; @@ -673,7 +194,7 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt) wid.val = (s8 *)&abort_running_scan; wid.size = sizeof(char); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -696,11 +217,11 @@ static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt) return result; } -static void handle_scan(struct work_struct *work) +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) { - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct scan_attr *scan_info = &msg->body.scan_info; int result = 0; struct wid wid_list[5]; u32 index = 0; @@ -709,10 +230,6 @@ static void handle_scan(struct work_struct *work) u8 valuesize = 0; u8 *hdn_ntwk_wid_val = NULL; struct host_if_drv *hif_drv = vif->hif_drv; - struct hidden_network *hidden_net = &scan_info->hidden_network; - - hif_drv->usr_scan_req.scan_result = scan_info->result; - hif_drv->usr_scan_req.arg = scan_info->arg; if (hif_drv->hif_state >= HOST_IF_SCANNING && hif_drv->hif_state < HOST_IF_CONNECTED) { @@ -729,156 +246,95 @@ static void handle_scan(struct work_struct *work) hif_drv->usr_scan_req.ch_cnt = 0; - wid_list[index].id = WID_SSID_PROBE_REQ; - wid_list[index].type = WID_STR; + 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) { - buffer = wid_list[index].val; + 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) { + buffer = wid_list[index].val; - *buffer++ = hidden_net->n_ssids; + *buffer++ = hidden_net->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 < 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; + } - wid_list[index].size = (s32)(valuesize + 1); - index++; + wid_list[index].size = (s32)(valuesize + 1); + index++; + } } wid_list[index].id = WID_INFO_ELEMENT_PROBE; wid_list[index].type = WID_BIN_DATA; - wid_list[index].val = scan_info->ies; - wid_list[index].size = scan_info->ies_len; + wid_list[index].val = (s8 *)ies; + wid_list[index].size = ies_len; index++; wid_list[index].id = WID_SCAN_TYPE; wid_list[index].type = WID_CHAR; wid_list[index].size = sizeof(char); - wid_list[index].val = (s8 *)&scan_info->type; + wid_list[index].val = (s8 *)&scan_type; index++; wid_list[index].id = WID_SCAN_CHANNEL_LIST; wid_list[index].type = WID_BIN_DATA; - if (scan_info->ch_freq_list && - scan_info->ch_list_len > 0) { - int i; - - for (i = 0; i < scan_info->ch_list_len; i++) { - if (scan_info->ch_freq_list[i] > 0) - scan_info->ch_freq_list[i] -= 1; + if (ch_freq_list && ch_list_len > 0) { + for (i = 0; i < ch_list_len; i++) { + if (ch_freq_list[i] > 0) + ch_freq_list[i] -= 1; } } - wid_list[index].val = scan_info->ch_freq_list; - wid_list[index].size = scan_info->ch_list_len; + wid_list[index].val = ch_freq_list; + wid_list[index].size = ch_list_len; index++; wid_list[index].id = WID_START_SCAN_REQ; wid_list[index].type = WID_CHAR; wid_list[index].size = sizeof(char); - wid_list[index].val = (s8 *)&scan_info->src; + wid_list[index].val = (s8 *)&scan_source; index++; - result = wilc_send_config_pkt(vif, SET_CFG, wid_list, + result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, index, wilc_get_vif_idx(vif)); - - if (result) - netdev_err(vif->ndev, "Failed to send scan parameters\n"); - -error: if (result) { - del_timer(&hif_drv->scan_timer); - handle_scan_done(vif, SCAN_EVENT_ABORTED); + netdev_err(vif->ndev, "Failed to send scan parameters\n"); + goto error; } - kfree(scan_info->ch_freq_list); - scan_info->ch_freq_list = NULL; - - kfree(scan_info->ies); - scan_info->ies = NULL; - kfree(scan_info->hidden_network.net_info); - scan_info->hidden_network.net_info = NULL; + hif_drv->usr_scan_req.scan_result = scan_result; + 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)); - kfree(hdn_ntwk_wid_val); +error: + if (hidden_net) { + kfree(hidden_net->net_info); + kfree(hdn_ntwk_wid_val); + } - kfree(msg); + return result; } -static void handle_connect(struct work_struct *work) +static int wilc_send_connect_wid(struct wilc_vif *vif) { - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct connect_attr *conn_attr = &msg->body.con_info; int result = 0; struct wid wid_list[8]; u32 wid_cnt = 0, dummyval = 0; u8 *cur_byte = NULL; - struct join_bss_param *bss_param; struct host_if_drv *hif_drv = vif->hif_drv; - - if (msg->vif->hif_drv->usr_scan_req.scan_result) { - result = wilc_enqueue_work(msg); - if (result) - goto error; - - usleep_range(2 * 1000, 2 * 1000); - return; - } - - bss_param = conn_attr->params; - if (!bss_param) { - netdev_err(vif->ndev, "Required BSSID not found\n"); - result = -ENOENT; - goto error; - } - - if (conn_attr->bssid) { - hif_drv->usr_conn_req.bssid = kmemdup(conn_attr->bssid, 6, - GFP_KERNEL); - if (!hif_drv->usr_conn_req.bssid) { - result = -ENOMEM; - goto error; - } - } - - hif_drv->usr_conn_req.ssid_len = conn_attr->ssid_len; - if (conn_attr->ssid) { - hif_drv->usr_conn_req.ssid = kmalloc(conn_attr->ssid_len + 1, - GFP_KERNEL); - if (!hif_drv->usr_conn_req.ssid) { - result = -ENOMEM; - goto error; - } - memcpy(hif_drv->usr_conn_req.ssid, - conn_attr->ssid, - conn_attr->ssid_len); - hif_drv->usr_conn_req.ssid[conn_attr->ssid_len] = '\0'; - } - - hif_drv->usr_conn_req.ies_len = conn_attr->ies_len; - if (conn_attr->ies) { - hif_drv->usr_conn_req.ies = kmemdup(conn_attr->ies, - conn_attr->ies_len, - GFP_KERNEL); - if (!hif_drv->usr_conn_req.ies) { - result = -ENOMEM; - goto error; - } - } - - hif_drv->usr_conn_req.security = conn_attr->security; - hif_drv->usr_conn_req.auth_type = conn_attr->auth_type; - hif_drv->usr_conn_req.conn_result = conn_attr->result; - hif_drv->usr_conn_req.arg = conn_attr->arg; + 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; @@ -900,20 +356,20 @@ static void handle_connect(struct work_struct *work) wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE; wid_list[wid_cnt].type = WID_BIN_DATA; - wid_list[wid_cnt].val = hif_drv->usr_conn_req.ies; - wid_list[wid_cnt].size = hif_drv->usr_conn_req.ies_len; + wid_list[wid_cnt].val = conn_attr->ies; + wid_list[wid_cnt].size = conn_attr->ies_len; wid_cnt++; wid_list[wid_cnt].id = WID_11I_MODE; wid_list[wid_cnt].type = WID_CHAR; wid_list[wid_cnt].size = sizeof(char); - wid_list[wid_cnt].val = (s8 *)&hif_drv->usr_conn_req.security; + wid_list[wid_cnt].val = (s8 *)&conn_attr->security; wid_cnt++; wid_list[wid_cnt].id = WID_AUTH_TYPE; wid_list[wid_cnt].type = WID_CHAR; wid_list[wid_cnt].size = sizeof(char); - wid_list[wid_cnt].val = (s8 *)&hif_drv->usr_conn_req.auth_type; + wid_list[wid_cnt].val = (s8 *)&conn_attr->auth_type; wid_cnt++; wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED; @@ -933,7 +389,7 @@ static void handle_connect(struct work_struct *work) cur_byte[conn_attr->ssid_len] = '\0'; } cur_byte += MAX_SSID_LEN; - *(cur_byte++) = INFRASTRUCTURE; + *(cur_byte++) = WILC_FW_BSS_TYPE_INFRA; if (conn_attr->ch >= 1 && conn_attr->ch <= 14) { *(cur_byte++) = conn_attr->ch; @@ -941,8 +397,8 @@ static void handle_connect(struct work_struct *work) netdev_err(vif->ndev, "Channel out of range\n"); *(cur_byte++) = 0xFF; } - *(cur_byte++) = (bss_param->cap_info) & 0xFF; - *(cur_byte++) = ((bss_param->cap_info) >> 8) & 0xFF; + put_unaligned_le16(bss_param->cap_info, cur_byte); + cur_byte += 2; if (conn_attr->bssid) memcpy(cur_byte, conn_attr->bssid, 6); @@ -952,8 +408,8 @@ static void handle_connect(struct work_struct *work) memcpy(cur_byte, conn_attr->bssid, 6); cur_byte += 6; - *(cur_byte++) = (bss_param->beacon_period) & 0xFF; - *(cur_byte++) = ((bss_param->beacon_period) >> 8) & 0xFF; + 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); @@ -963,7 +419,7 @@ static void handle_connect(struct work_struct *work) *(cur_byte++) = bss_param->uapsd_cap; *(cur_byte++) = bss_param->ht_capable; - hif_drv->usr_conn_req.ht_capable = 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; @@ -984,10 +440,8 @@ static void handle_connect(struct work_struct *work) *(cur_byte++) = bss_param->noa_enabled; if (bss_param->noa_enabled) { - *(cur_byte++) = (bss_param->tsf) & 0xFF; - *(cur_byte++) = ((bss_param->tsf) >> 8) & 0xFF; - *(cur_byte++) = ((bss_param->tsf) >> 16) & 0xFF; - *(cur_byte++) = ((bss_param->tsf) >> 24) & 0xFF; + put_unaligned_le32(bss_param->tsf, cur_byte); + cur_byte += 4; *(cur_byte++) = bss_param->opp_enabled; *(cur_byte++) = bss_param->idx; @@ -1013,49 +467,21 @@ static void handle_connect(struct work_struct *work) cur_byte = wid_list[wid_cnt].val; wid_cnt++; - result = wilc_send_config_pkt(vif, SET_CFG, wid_list, + result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, wid_cnt, wilc_get_vif_idx(vif)); if (result) { netdev_err(vif->ndev, "failed to send config packet\n"); - result = -EFAULT; + kfree(cur_byte); goto error; } else { hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP; } -error: - if (result) { - struct connect_info conn_info; - - del_timer(&hif_drv->connect_timer); - - memset(&conn_info, 0, sizeof(struct connect_info)); - - if (conn_attr->result) { - if (conn_attr->bssid) - memcpy(conn_info.bssid, conn_attr->bssid, 6); - - if (conn_attr->ies) { - conn_info.req_ies_len = conn_attr->ies_len; - conn_info.req_ies = kmalloc(conn_attr->ies_len, - GFP_KERNEL); - memcpy(conn_info.req_ies, - conn_attr->ies, - conn_attr->ies_len); - } - - conn_attr->result(CONN_DISCONN_EVENT_CONN_RESP, - &conn_info, MAC_STATUS_DISCONNECTED, - NULL, conn_attr->arg); - hif_drv->hif_state = HOST_IF_IDLE; - kfree(conn_info.req_ies); - conn_info.req_ies = NULL; + kfree(cur_byte); + return 0; - } else { - netdev_err(vif->ndev, "Connect callback is NULL\n"); - } - } +error: kfree(conn_attr->bssid); conn_attr->bssid = NULL; @@ -1066,8 +492,7 @@ error: kfree(conn_attr->ies); conn_attr->ies = NULL; - kfree(cur_byte); - kfree(msg); + return result; } static void handle_connect_timeout(struct work_struct *work) @@ -1106,7 +531,7 @@ static void handle_connect_timeout(struct work_struct *work) hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP, &info, - MAC_STATUS_DISCONNECTED, + WILC_MAC_STATUS_DISCONNECTED, NULL, hif_drv->usr_conn_req.arg); @@ -1121,7 +546,7 @@ static void handle_connect_timeout(struct work_struct *work) wid.val = (s8 *)&dummy_reason_code; wid.size = sizeof(char); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) netdev_err(vif->ndev, "Failed to send disconnect\n"); @@ -1305,6 +730,101 @@ static void *host_int_parse_join_bss_param(struct network_info *info) 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; +} + +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; + + wid_len = get_unaligned_le16(&msg_buffer[6]); + wid_val = &msg_buffer[8]; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->rssi = wid_val[0]; + + msa = &wid_val[1]; + mgt = (struct ieee80211_mgmt *)&wid_val[1]; + rx_len = wid_len - 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; + } + + ether_addr_copy(info->bssid, get_bssid(mgt)); + + ies = mgt->u.beacon.variable; + ies_len = rx_len - offset; + if (ies_len <= 0) { + kfree(info); + return -EIO; + } + + info->ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!info->ies) { + kfree(info); + return -ENOMEM; + } + + info->ies_len = ies_len; + + 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; + } + + ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len); + if (ch_elm && ch_elm[1] > 0) + info->ch = ch_elm[2]; + + tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len); + if (tim_elm && tim_elm[1] >= 2) + info->dtim_period = tim_elm[3]; + + *ret_network_info = info; + + return 0; +} + static void handle_rcvd_ntwrk_info(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); @@ -1387,7 +907,7 @@ static void host_int_get_assoc_res_info(struct wilc_vif *vif, wid.val = assoc_resp_info; wid.size = max_assoc_resp_info_len; - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { *rcvd_assoc_resp_info_len = 0; @@ -1410,6 +930,28 @@ static inline void host_int_free_user_conn_req(struct host_if_drv *hif_drv) 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) +{ + u8 *ies; + u16 ies_len; + struct assoc_resp *res = (struct assoc_resp *)buffer; + + ret_conn_info->status = le16_to_cpu(res->status_code); + if (ret_conn_info->status == WLAN_STATUS_SUCCESS) { + ies = &buffer[sizeof(*res)]; + ies_len = buffer_len - sizeof(*res); + + ret_conn_info->resp_ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!ret_conn_info->resp_ies) + return -ENOMEM; + + ret_conn_info->resp_ies_len = ies_len; + } + + return 0; +} + static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, u8 mac_status) { @@ -1418,13 +960,13 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, memset(&conn_info, 0, sizeof(struct connect_info)); - if (mac_status == MAC_STATUS_CONNECTED) { + if (mac_status == WILC_MAC_STATUS_CONNECTED) { u32 assoc_resp_info_len; - memset(hif_drv->assoc_resp, 0, MAX_ASSOC_RESP_FRAME_SIZE); + memset(hif_drv->assoc_resp, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE); host_int_get_assoc_res_info(vif, hif_drv->assoc_resp, - MAX_ASSOC_RESP_FRAME_SIZE, + WILC_MAX_ASSOC_RESP_FRAME_SIZE, &assoc_resp_info_len); if (assoc_resp_info_len != 0) { @@ -1443,7 +985,7 @@ 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 == MAC_STATUS_CONNECTED && + 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); @@ -1463,7 +1005,7 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, &conn_info, mac_status, NULL, hif_drv->usr_conn_req.arg); - if (mac_status == MAC_STATUS_CONNECTED && + if (mac_status == WILC_MAC_STATUS_CONNECTED && conn_info.status == WLAN_STATUS_SUCCESS) { wilc_set_power_mgmt(vif, 0, 0); @@ -1555,10 +1097,10 @@ static void handle_rcvd_gnrl_async_info(struct work_struct *work) 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 == MAC_STATUS_DISCONNECTED) && + } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) && (hif_drv->hif_state == HOST_IF_CONNECTED)) { host_int_handle_disconnect(vif); - } else if ((mac_status == MAC_STATUS_DISCONNECTED) && + } else if ((mac_status == WILC_MAC_STATUS_DISCONNECTED) && (hif_drv->usr_scan_req.scan_result)) { del_timer(&hif_drv->scan_timer); if (hif_drv->usr_scan_req.scan_result) @@ -1574,268 +1116,8 @@ free_msg: kfree(msg); } -static int wilc_pmksa_key_copy(struct wilc_vif *vif, struct key_attr *hif_key) -{ - int i; - int ret; - struct wid wid; - u8 *key_buf; - - key_buf = kmalloc((hif_key->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1, - GFP_KERNEL); - if (!key_buf) - return -ENOMEM; - - key_buf[0] = hif_key->attr.pmkid.numpmkid; - - for (i = 0; i < hif_key->attr.pmkid.numpmkid; i++) { - memcpy(key_buf + ((PMKSA_KEY_LEN * i) + 1), - hif_key->attr.pmkid.pmkidlist[i].bssid, ETH_ALEN); - memcpy(key_buf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1), - hif_key->attr.pmkid.pmkidlist[i].pmkid, PMKID_LEN); - } - - wid.id = WID_PMKID_INFO; - wid.type = WID_STR; - wid.val = (s8 *)key_buf; - wid.size = (hif_key->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1; - - ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - - kfree(key_buf); - - return ret; -} - -static void handle_key(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct key_attr *hif_key = &msg->body.key_info; - int result = 0; - struct wid wid; - struct wid wid_list[5]; - u8 *key_buf; - struct host_if_drv *hif_drv = vif->hif_drv; - - switch (hif_key->type) { - case WEP: - - if (hif_key->action & ADDKEY_AP) { - wid_list[0].id = WID_11I_MODE; - wid_list[0].type = WID_CHAR; - wid_list[0].size = sizeof(char); - wid_list[0].val = (s8 *)&hif_key->attr.wep.mode; - - wid_list[1].id = WID_AUTH_TYPE; - wid_list[1].type = WID_CHAR; - wid_list[1].size = sizeof(char); - wid_list[1].val = (s8 *)&hif_key->attr.wep.auth_type; - - key_buf = kmalloc(hif_key->attr.wep.key_len + 2, - GFP_KERNEL); - if (!key_buf) { - result = -ENOMEM; - goto out_wep; - } - - key_buf[0] = hif_key->attr.wep.index; - key_buf[1] = hif_key->attr.wep.key_len; - - memcpy(&key_buf[2], hif_key->attr.wep.key, - hif_key->attr.wep.key_len); - - wid_list[2].id = WID_WEP_KEY_VALUE; - wid_list[2].type = WID_STR; - wid_list[2].size = hif_key->attr.wep.key_len + 2; - wid_list[2].val = (s8 *)key_buf; - - result = wilc_send_config_pkt(vif, SET_CFG, - wid_list, 3, - wilc_get_vif_idx(vif)); - kfree(key_buf); - } else if (hif_key->action & ADDKEY) { - key_buf = kmalloc(hif_key->attr.wep.key_len + 2, - GFP_KERNEL); - if (!key_buf) { - result = -ENOMEM; - goto out_wep; - } - key_buf[0] = hif_key->attr.wep.index; - memcpy(key_buf + 1, &hif_key->attr.wep.key_len, 1); - memcpy(key_buf + 2, hif_key->attr.wep.key, - hif_key->attr.wep.key_len); - - wid.id = WID_ADD_WEP_KEY; - wid.type = WID_STR; - wid.val = (s8 *)key_buf; - wid.size = hif_key->attr.wep.key_len + 2; - - result = wilc_send_config_pkt(vif, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); - kfree(key_buf); - } else if (hif_key->action & REMOVEKEY) { - wid.id = WID_REMOVE_WEP_KEY; - wid.type = WID_STR; - - wid.val = (s8 *)&hif_key->attr.wep.index; - wid.size = 1; - - result = wilc_send_config_pkt(vif, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); - } else if (hif_key->action & DEFAULTKEY) { - wid.id = WID_KEY_ID; - wid.type = WID_CHAR; - wid.val = (s8 *)&hif_key->attr.wep.index; - wid.size = sizeof(char); - - result = wilc_send_config_pkt(vif, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); - } -out_wep: - complete(&msg->work_comp); - break; - - case WPA_RX_GTK: - if (hif_key->action & ADDKEY_AP) { - key_buf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL); - if (!key_buf) { - result = -ENOMEM; - goto out_wpa_rx_gtk; - } - - if (hif_key->attr.wpa.seq) - memcpy(key_buf + 6, hif_key->attr.wpa.seq, 8); - - memcpy(key_buf + 14, &hif_key->attr.wpa.index, 1); - memcpy(key_buf + 15, &hif_key->attr.wpa.key_len, 1); - memcpy(key_buf + 16, hif_key->attr.wpa.key, - hif_key->attr.wpa.key_len); - - wid_list[0].id = WID_11I_MODE; - wid_list[0].type = WID_CHAR; - wid_list[0].size = sizeof(char); - wid_list[0].val = (s8 *)&hif_key->attr.wpa.mode; - - wid_list[1].id = WID_ADD_RX_GTK; - wid_list[1].type = WID_STR; - wid_list[1].val = (s8 *)key_buf; - wid_list[1].size = RX_MIC_KEY_MSG_LEN; - - result = wilc_send_config_pkt(vif, SET_CFG, - wid_list, 2, - wilc_get_vif_idx(vif)); - - kfree(key_buf); - } else if (hif_key->action & ADDKEY) { - key_buf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL); - if (!key_buf) { - result = -ENOMEM; - goto out_wpa_rx_gtk; - } - - if (hif_drv->hif_state == HOST_IF_CONNECTED) - memcpy(key_buf, hif_drv->assoc_bssid, ETH_ALEN); - else - netdev_err(vif->ndev, "Couldn't handle\n"); - - memcpy(key_buf + 6, hif_key->attr.wpa.seq, 8); - memcpy(key_buf + 14, &hif_key->attr.wpa.index, 1); - memcpy(key_buf + 15, &hif_key->attr.wpa.key_len, 1); - memcpy(key_buf + 16, hif_key->attr.wpa.key, - hif_key->attr.wpa.key_len); - - wid.id = WID_ADD_RX_GTK; - wid.type = WID_STR; - wid.val = (s8 *)key_buf; - wid.size = RX_MIC_KEY_MSG_LEN; - - result = wilc_send_config_pkt(vif, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); - - kfree(key_buf); - } -out_wpa_rx_gtk: - complete(&msg->work_comp); - break; - - case WPA_PTK: - if (hif_key->action & ADDKEY_AP) { - key_buf = kmalloc(PTK_KEY_MSG_LEN + 1, GFP_KERNEL); - if (!key_buf) { - result = -ENOMEM; - goto out_wpa_ptk; - } - - memcpy(key_buf, hif_key->attr.wpa.mac_addr, 6); - memcpy(key_buf + 6, &hif_key->attr.wpa.index, 1); - memcpy(key_buf + 7, &hif_key->attr.wpa.key_len, 1); - memcpy(key_buf + 8, hif_key->attr.wpa.key, - hif_key->attr.wpa.key_len); - - wid_list[0].id = WID_11I_MODE; - wid_list[0].type = WID_CHAR; - wid_list[0].size = sizeof(char); - wid_list[0].val = (s8 *)&hif_key->attr.wpa.mode; - - wid_list[1].id = WID_ADD_PTK; - wid_list[1].type = WID_STR; - wid_list[1].val = (s8 *)key_buf; - wid_list[1].size = PTK_KEY_MSG_LEN + 1; - - result = wilc_send_config_pkt(vif, SET_CFG, - wid_list, 2, - wilc_get_vif_idx(vif)); - kfree(key_buf); - } else if (hif_key->action & ADDKEY) { - key_buf = kmalloc(PTK_KEY_MSG_LEN, GFP_KERNEL); - if (!key_buf) { - result = -ENOMEM; - goto out_wpa_ptk; - } - - memcpy(key_buf, hif_key->attr.wpa.mac_addr, 6); - memcpy(key_buf + 6, &hif_key->attr.wpa.key_len, 1); - memcpy(key_buf + 7, hif_key->attr.wpa.key, - hif_key->attr.wpa.key_len); - - wid.id = WID_ADD_PTK; - wid.type = WID_STR; - wid.val = (s8 *)key_buf; - wid.size = PTK_KEY_MSG_LEN; - - result = wilc_send_config_pkt(vif, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); - kfree(key_buf); - } - -out_wpa_ptk: - complete(&msg->work_comp); - break; - - case PMKSA: - result = wilc_pmksa_key_copy(vif, hif_key); - /*free 'msg', this case it not a sync call*/ - kfree(msg); - break; - } - - if (result) - netdev_err(vif->ndev, "Failed to send key config packet\n"); - - /* free 'msg' data in caller sync call */ -} - -static void handle_disconnect(struct work_struct *work) +int wilc_disconnect(struct wilc_vif *vif) { - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; struct wid wid; struct host_if_drv *hif_drv = vif->hif_drv; struct disconnect_info disconn_info; @@ -1852,12 +1134,11 @@ static void handle_disconnect(struct work_struct *work) vif->obtaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - if (result) { netdev_err(vif->ndev, "Failed to send dissconect\n"); - goto out; + return result; } memset(&disconn_info, 0, sizeof(struct disconnect_info)); @@ -1898,10 +1179,7 @@ static void handle_disconnect(struct work_struct *work) kfree(conn_req->ies); conn_req->ies = NULL; -out: - - complete(&msg->work_comp); - /* free 'msg' in caller after receiving completion */ + return 0; } void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) @@ -1910,37 +1188,13 @@ void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) return; if (vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || vif->hif_drv->hif_state == HOST_IF_CONNECTING) - wilc_disconnect(vif, 1); -} - -static void handle_get_rssi(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 wid wid; - - wid.id = WID_RSSI; - wid.type = WID_CHAR; - wid.val = msg->body.data; - wid.size = sizeof(char); - - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (result) - netdev_err(vif->ndev, "Failed to get RSSI value\n"); - - complete(&msg->work_comp); - /* free 'msg' data in caller */ + wilc_disconnect(vif); } -static void handle_get_statistics(struct work_struct *work) +int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) { - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; struct wid wid_list[5]; u32 wid_cnt = 0, result; - struct rf_info *stats = (struct rf_info *)msg->body.data; wid_list[wid_cnt].id = WID_LINKSPEED; wid_list[wid_cnt].type = WID_CHAR; @@ -1972,12 +1226,14 @@ static void handle_get_statistics(struct work_struct *work) wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt; wid_cnt++; - result = wilc_send_config_pkt(vif, GET_CFG, wid_list, + result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list, wid_cnt, wilc_get_vif_idx(vif)); - if (result) + if (result) { netdev_err(vif->ndev, "Failed to send scan parameters\n"); + return result; + } if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH && stats->link_speed != DEFAULT_LINK_SPEED) @@ -1985,293 +1241,47 @@ static void handle_get_statistics(struct work_struct *work) else if (stats->link_speed != DEFAULT_LINK_SPEED) wilc_enable_tcp_ack_filter(vif, false); - /* free 'msg' for async command, for sync caller will free it */ - if (msg->is_sync) - complete(&msg->work_comp); - else - kfree(msg); -} - -static void handle_get_inactive_time(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct sta_inactive_t *hif_sta_inactive = &msg->body.mac_info; - int result; - struct wid wid; - - wid.id = WID_SET_STA_MAC_INACTIVE_TIME; - wid.type = WID_STR; - wid.size = ETH_ALEN; - wid.val = kmalloc(wid.size, GFP_KERNEL); - if (!wid.val) - goto out; - - ether_addr_copy(wid.val, hif_sta_inactive->mac); - - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - kfree(wid.val); - - if (result) { - netdev_err(vif->ndev, "Failed to set inactive mac\n"); - goto out; - } - - wid.id = WID_GET_INACTIVE_TIME; - wid.type = WID_INT; - wid.val = (s8 *)&hif_sta_inactive->inactive_time; - wid.size = sizeof(u32); - - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - - if (result) - netdev_err(vif->ndev, "Failed to get inactive time\n"); - -out: - /* free 'msg' data in caller */ - complete(&msg->work_comp); -} - -static void handle_add_beacon(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct beacon_attr *param = &msg->body.beacon_info; - int result; - struct wid wid; - u8 *cur_byte; - - wid.id = WID_ADD_BEACON; - wid.type = WID_BIN; - wid.size = param->head_len + param->tail_len + 16; - wid.val = kmalloc(wid.size, GFP_KERNEL); - if (!wid.val) - goto error; - - cur_byte = wid.val; - *cur_byte++ = (param->interval & 0xFF); - *cur_byte++ = ((param->interval >> 8) & 0xFF); - *cur_byte++ = ((param->interval >> 16) & 0xFF); - *cur_byte++ = ((param->interval >> 24) & 0xFF); - - *cur_byte++ = (param->dtim_period & 0xFF); - *cur_byte++ = ((param->dtim_period >> 8) & 0xFF); - *cur_byte++ = ((param->dtim_period >> 16) & 0xFF); - *cur_byte++ = ((param->dtim_period >> 24) & 0xFF); - - *cur_byte++ = (param->head_len & 0xFF); - *cur_byte++ = ((param->head_len >> 8) & 0xFF); - *cur_byte++ = ((param->head_len >> 16) & 0xFF); - *cur_byte++ = ((param->head_len >> 24) & 0xFF); - - memcpy(cur_byte, param->head, param->head_len); - cur_byte += param->head_len; - - *cur_byte++ = (param->tail_len & 0xFF); - *cur_byte++ = ((param->tail_len >> 8) & 0xFF); - *cur_byte++ = ((param->tail_len >> 16) & 0xFF); - *cur_byte++ = ((param->tail_len >> 24) & 0xFF); - - if (param->tail) - memcpy(cur_byte, param->tail, param->tail_len); - cur_byte += param->tail_len; - - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (result) - netdev_err(vif->ndev, "Failed to send add beacon\n"); - -error: - kfree(wid.val); - kfree(param->head); - kfree(param->tail); - kfree(msg); -} - -static void handle_del_beacon(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 wid wid; - u8 del_beacon = 0; - - wid.id = WID_DEL_BEACON; - wid.type = WID_CHAR; - wid.size = sizeof(char); - wid.val = &del_beacon; - - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (result) - netdev_err(vif->ndev, "Failed to send delete beacon\n"); - kfree(msg); -} - -static u32 wilc_hif_pack_sta_param(u8 *buff, struct add_sta_param *param) -{ - u8 *cur_byte; - - cur_byte = buff; - - memcpy(cur_byte, param->bssid, ETH_ALEN); - cur_byte += ETH_ALEN; - - *cur_byte++ = param->aid & 0xFF; - *cur_byte++ = (param->aid >> 8) & 0xFF; - - *cur_byte++ = param->rates_len; - if (param->rates_len > 0) - memcpy(cur_byte, param->rates, param->rates_len); - cur_byte += param->rates_len; - - *cur_byte++ = param->ht_supported; - memcpy(cur_byte, ¶m->ht_capa, sizeof(struct ieee80211_ht_cap)); - cur_byte += sizeof(struct ieee80211_ht_cap); - - *cur_byte++ = param->flags_mask & 0xFF; - *cur_byte++ = (param->flags_mask >> 8) & 0xFF; - - *cur_byte++ = param->flags_set & 0xFF; - *cur_byte++ = (param->flags_set >> 8) & 0xFF; - - return cur_byte - buff; + return result; } -static void handle_add_station(struct work_struct *work) +static void handle_get_statistics(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); struct wilc_vif *vif = msg->vif; - struct add_sta_param *param = &msg->body.add_sta_info; - int result; - struct wid wid; - u8 *cur_byte; - - wid.id = WID_ADD_STA; - wid.type = WID_BIN; - wid.size = WILC_ADD_STA_LENGTH + param->rates_len; - - wid.val = kmalloc(wid.size, GFP_KERNEL); - if (!wid.val) - goto error; - - cur_byte = wid.val; - cur_byte += wilc_hif_pack_sta_param(cur_byte, param); + struct rf_info *stats = (struct rf_info *)msg->body.data; - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (result != 0) - netdev_err(vif->ndev, "Failed to send add station\n"); + wilc_get_statistics(vif, stats); -error: - kfree(param->rates); - kfree(wid.val); kfree(msg); } -static void handle_del_all_sta(struct work_struct *work) +static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac, + struct station_parameters *params) { - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct del_all_sta *param = &msg->body.del_all_sta_info; - int result; - struct wid wid; - u8 *curr_byte; - u8 i; - u8 zero_buff[6] = {0}; + ether_addr_copy(cur_byte, mac); + cur_byte += ETH_ALEN; - wid.id = WID_DEL_ALL_STA; - wid.type = WID_STR; - wid.size = (param->assoc_sta * ETH_ALEN) + 1; - - wid.val = kmalloc((param->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL); - if (!wid.val) - goto error; + put_unaligned_le16(params->aid, cur_byte); + cur_byte += 2; - curr_byte = wid.val; + *cur_byte++ = params->supported_rates_len; + if (params->supported_rates_len > 0) + memcpy(cur_byte, params->supported_rates, + params->supported_rates_len); + cur_byte += params->supported_rates_len; - *(curr_byte++) = param->assoc_sta; - - for (i = 0; i < MAX_NUM_STA; i++) { - if (memcmp(param->del_all_sta[i], zero_buff, ETH_ALEN)) - memcpy(curr_byte, param->del_all_sta[i], ETH_ALEN); - else - continue; - - curr_byte += ETH_ALEN; + if (params->ht_capa) { + *cur_byte++ = true; + memcpy(cur_byte, ¶ms->ht_capa, + sizeof(struct ieee80211_ht_cap)); + } else { + *cur_byte++ = false; } + cur_byte += sizeof(struct ieee80211_ht_cap); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (result) - netdev_err(vif->ndev, "Failed to send delete all station\n"); - -error: - kfree(wid.val); - - /* free 'msg' data in caller */ - complete(&msg->work_comp); -} - -static void handle_del_station(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct del_sta *param = &msg->body.del_sta_info; - int result; - struct wid wid; - - wid.id = WID_REMOVE_STA; - wid.type = WID_BIN; - wid.size = ETH_ALEN; - - wid.val = kmalloc(wid.size, GFP_KERNEL); - if (!wid.val) - goto error; - - ether_addr_copy(wid.val, param->mac_addr); - - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (result) - netdev_err(vif->ndev, "Failed to del station\n"); - -error: - kfree(wid.val); - kfree(msg); -} - -static void handle_edit_station(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct add_sta_param *param = &msg->body.edit_sta_info; - int result; - struct wid wid; - u8 *cur_byte; - - wid.id = WID_EDIT_STA; - wid.type = WID_BIN; - wid.size = WILC_ADD_STA_LENGTH + param->rates_len; - - wid.val = kmalloc(wid.size, GFP_KERNEL); - if (!wid.val) - goto error; - - cur_byte = wid.val; - cur_byte += wilc_hif_pack_sta_param(cur_byte, param); - - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (result) - netdev_err(vif->ndev, "Failed to send edit station\n"); - -error: - kfree(param->rates); - kfree(wid.val); - kfree(msg); + put_unaligned_le16(params->sta_flags_mask, cur_byte); + cur_byte += 2; + put_unaligned_le16(params->sta_flags_set, cur_byte); } static int handle_remain_on_chan(struct wilc_vif *vif, @@ -2320,7 +1330,7 @@ static int handle_remain_on_chan(struct wilc_vif *vif, wid.val[0] = remain_on_chan_flag; wid.val[1] = (s8)hif_remain_ch->ch; - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(wid.val); if (result != 0) @@ -2340,39 +1350,6 @@ error: return result; } -static void handle_register_frame(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct reg_frame *hif_reg_frame = &msg->body.reg_frame; - int result; - struct wid wid; - u8 *cur_byte; - - wid.id = WID_REGISTER_FRAME; - wid.type = WID_STR; - wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL); - if (!wid.val) - goto out; - - cur_byte = wid.val; - - *cur_byte++ = hif_reg_frame->reg; - *cur_byte++ = hif_reg_frame->reg_id; - memcpy(cur_byte, &hif_reg_frame->frame_type, sizeof(u16)); - - wid.size = sizeof(u16) + 2; - - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - kfree(wid.val); - if (result) - netdev_err(vif->ndev, "Failed to frame register\n"); - -out: - kfree(msg); -} - static void handle_listen_state_expired(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); @@ -2397,7 +1374,7 @@ static void handle_listen_state_expired(struct work_struct *work) wid.val[0] = remain_on_chan_flag; wid.val[1] = FALSE_FRMWR_CHANNEL; - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(wid.val); if (result != 0) { @@ -2440,32 +1417,6 @@ static void listen_timer_cb(struct timer_list *t) } } -static void handle_power_management(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - struct power_mgmt_param *pm_param = &msg->body.pwr_mgmt_info; - int result; - struct wid wid; - s8 power_mode; - - wid.id = WID_POWER_MANAGEMENT; - - if (pm_param->enabled) - power_mode = MIN_FAST_PS; - else - power_mode = NO_POWERSAVE; - - wid.val = &power_mode; - wid.size = sizeof(char); - - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (result) - netdev_err(vif->ndev, "Failed to send power management\n"); - kfree(msg); -} - static void handle_set_mcast_filter(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); @@ -2497,7 +1448,7 @@ static void handle_set_mcast_filter(struct work_struct *work) memcpy(cur_byte, hif_set_mc->mc_list, ((hif_set_mc->cnt) * ETH_ALEN)); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) netdev_err(vif->ndev, "Failed to send setup multicast\n"); @@ -2508,48 +1459,6 @@ error: kfree(msg); } -static void handle_set_tx_pwr(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - u8 tx_pwr = msg->body.tx_power.tx_pwr; - int ret; - struct wid wid; - - wid.id = WID_TX_POWER; - wid.type = WID_CHAR; - wid.val = &tx_pwr; - wid.size = sizeof(char); - - ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (ret) - netdev_err(vif->ndev, "Failed to set TX PWR\n"); - kfree(msg); -} - -/* Note: 'msg' will be free after using data */ -static void handle_get_tx_pwr(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - struct wilc_vif *vif = msg->vif; - u8 *tx_pwr = &msg->body.tx_power.tx_pwr; - int ret; - struct wid wid; - - wid.id = WID_TX_POWER; - wid.type = WID_CHAR; - wid.val = (s8 *)tx_pwr; - wid.size = sizeof(char); - - ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (ret) - netdev_err(vif->ndev, "Failed to get TX PWR\n"); - - complete(&msg->work_comp); -} - static void handle_scan_timer(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); @@ -2558,14 +1467,6 @@ static void handle_scan_timer(struct work_struct *work) kfree(msg); } -static void handle_remain_on_chan_work(struct work_struct *work) -{ - struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - - handle_remain_on_chan(msg->vif, &msg->body.remain_on_ch); - kfree(msg); -} - static void handle_scan_complete(struct work_struct *work) { struct host_if_msg *msg = container_of(work, struct host_if_msg, work); @@ -2579,7 +1480,8 @@ 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->body.remain_on_ch); + handle_remain_on_chan(msg->vif, + &msg->vif->hif_drv->remain_on_ch); kfree(msg); } @@ -2618,145 +1520,107 @@ static void timer_connect_cb(struct timer_list *t) int wilc_remove_wep_key(struct wilc_vif *vif, u8 index) { + struct wid wid; int result; - struct host_if_msg *msg; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!hif_drv) { - result = -EFAULT; - netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); - return result; - } - msg = wilc_alloc_work(vif, handle_key, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->body.key_info.type = WEP; - msg->body.key_info.action = REMOVEKEY; - msg->body.key_info.attr.wep.index = index; + wid.id = WID_REMOVE_WEP_KEY; + wid.type = WID_STR; + wid.size = sizeof(char); + wid.val = &index; - result = wilc_enqueue_work(msg); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (result) - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - else - wait_for_completion(&msg->work_comp); - - kfree(msg); + netdev_err(vif->ndev, + "Failed to send remove wep key config packet\n"); return result; } int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index) { + struct wid wid; int result; - struct host_if_msg *msg; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!hif_drv) { - result = -EFAULT; - netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__); - return result; - } - - msg = wilc_alloc_work(vif, handle_key, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->body.key_info.type = WEP; - msg->body.key_info.action = DEFAULTKEY; - msg->body.key_info.attr.wep.index = index; - result = wilc_enqueue_work(msg); + wid.id = WID_KEY_ID; + wid.type = WID_CHAR; + wid.size = sizeof(char); + wid.val = &index; + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (result) - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - else - wait_for_completion(&msg->work_comp); + netdev_err(vif->ndev, + "Failed to send wep default key config packet\n"); - kfree(msg); return result; } int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, u8 index) { + struct wid wid; int result; - struct host_if_msg *msg; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!hif_drv) { - netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); - return -EFAULT; - } + struct wilc_wep_key *wep_key; - msg = wilc_alloc_work(vif, handle_key, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); + wid.id = WID_ADD_WEP_KEY; + wid.type = WID_STR; + wid.size = sizeof(*wep_key) + len; + wep_key = kzalloc(wid.size, GFP_KERNEL); + if (!wep_key) + return -ENOMEM; - msg->body.key_info.type = WEP; - msg->body.key_info.action = ADDKEY; - msg->body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL); - if (!msg->body.key_info.attr.wep.key) { - result = -ENOMEM; - goto free_msg; - } + wid.val = (u8 *)wep_key; - msg->body.key_info.attr.wep.key_len = len; - msg->body.key_info.attr.wep.index = index; + wep_key->index = index; + wep_key->key_len = len; + memcpy(wep_key->key, key, len); - result = wilc_enqueue_work(msg); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (result) - goto free_key; - - wait_for_completion(&msg->work_comp); - -free_key: - kfree(msg->body.key_info.attr.wep.key); + netdev_err(vif->ndev, + "Failed to add wep key config packet\n"); -free_msg: - kfree(msg); + kfree(wep_key); return result; } int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, u8 index, u8 mode, enum authtype auth_type) { + struct wid wid_list[3]; int result; - struct host_if_msg *msg; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!hif_drv) { - netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__); - return -EFAULT; - } - - msg = wilc_alloc_work(vif, handle_key, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->body.key_info.type = WEP; - msg->body.key_info.action = ADDKEY_AP; - msg->body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL); - if (!msg->body.key_info.attr.wep.key) { - result = -ENOMEM; - goto free_msg; - } + struct wilc_wep_key *wep_key; + + wid_list[0].id = WID_11I_MODE; + wid_list[0].type = WID_CHAR; + wid_list[0].size = sizeof(char); + wid_list[0].val = &mode; + + wid_list[1].id = WID_AUTH_TYPE; + wid_list[1].type = WID_CHAR; + wid_list[1].size = sizeof(char); + wid_list[1].val = (s8 *)&auth_type; + + wid_list[2].id = WID_WEP_KEY_VALUE; + wid_list[2].type = WID_STR; + wid_list[2].size = sizeof(*wep_key) + len; + wep_key = kzalloc(wid_list[2].size, GFP_KERNEL); + if (!wep_key) + return -ENOMEM; - msg->body.key_info.attr.wep.key_len = len; - msg->body.key_info.attr.wep.index = index; - msg->body.key_info.attr.wep.mode = mode; - msg->body.key_info.attr.wep.auth_type = auth_type; + wid_list[2].val = (u8 *)wep_key; - result = wilc_enqueue_work(msg); + wep_key->index = index; + wep_key->key_len = len; + memcpy(wep_key->key, key, len); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, + ARRAY_SIZE(wid_list), + wilc_get_vif_idx(vif)); if (result) - goto free_key; - - wait_for_completion(&msg->work_comp); - -free_key: - kfree(msg->body.key_info.attr.wep.key); + netdev_err(vif->ndev, + "Failed to add wep ap key config packet\n"); -free_msg: - kfree(msg); + kfree(wep_key); return result; } @@ -2764,65 +1628,72 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode, u8 index) { - int result; - struct host_if_msg *msg; - struct host_if_drv *hif_drv = vif->hif_drv; - u8 key_len = ptk_key_len; - - if (!hif_drv) { - netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); - return -EFAULT; - } + int result = 0; + u8 t_key_len = ptk_key_len + RX_MIC_KEY_LEN + TX_MIC_KEY_LEN; - if (rx_mic) - key_len += RX_MIC_KEY_LEN; + if (mode == WILC_AP_MODE) { + struct wid wid_list[2]; + struct wilc_ap_wpa_ptk *key_buf; - if (tx_mic) - key_len += TX_MIC_KEY_LEN; + wid_list[0].id = WID_11I_MODE; + wid_list[0].type = WID_CHAR; + wid_list[0].size = sizeof(char); + wid_list[0].val = (s8 *)&cipher_mode; - msg = wilc_alloc_work(vif, handle_key, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); + key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL); + if (!key_buf) + return -ENOMEM; - msg->body.key_info.type = WPA_PTK; - if (mode == AP_MODE) { - msg->body.key_info.action = ADDKEY_AP; - msg->body.key_info.attr.wpa.index = index; - } - if (mode == STATION_MODE) - msg->body.key_info.action = ADDKEY; + ether_addr_copy(key_buf->mac_addr, mac_addr); + key_buf->index = index; + key_buf->key_len = t_key_len; + memcpy(&key_buf->key[0], ptk, ptk_key_len); + + if (rx_mic) + memcpy(&key_buf->key[ptk_key_len], rx_mic, + RX_MIC_KEY_LEN); + + if (tx_mic) + memcpy(&key_buf->key[ptk_key_len + RX_MIC_KEY_LEN], + tx_mic, TX_MIC_KEY_LEN); + + wid_list[1].id = WID_ADD_PTK; + wid_list[1].type = WID_STR; + wid_list[1].size = sizeof(*key_buf) + t_key_len; + wid_list[1].val = (u8 *)key_buf; + result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, + ARRAY_SIZE(wid_list), + wilc_get_vif_idx(vif)); + kfree(key_buf); + } else if (mode == WILC_STATION_MODE) { + struct wid wid; + struct wilc_sta_wpa_ptk *key_buf; - msg->body.key_info.attr.wpa.key = kmemdup(ptk, ptk_key_len, GFP_KERNEL); - if (!msg->body.key_info.attr.wpa.key) { - result = -ENOMEM; - goto free_msg; - } + key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL); + if (!key_buf) + return -ENOMEM; - if (rx_mic) - memcpy(msg->body.key_info.attr.wpa.key + 16, rx_mic, - RX_MIC_KEY_LEN); + ether_addr_copy(key_buf->mac_addr, mac_addr); + key_buf->key_len = t_key_len; + memcpy(&key_buf->key[0], ptk, ptk_key_len); - if (tx_mic) - memcpy(msg->body.key_info.attr.wpa.key + 24, tx_mic, - TX_MIC_KEY_LEN); + if (rx_mic) + memcpy(&key_buf->key[ptk_key_len], rx_mic, + RX_MIC_KEY_LEN); - msg->body.key_info.attr.wpa.key_len = key_len; - msg->body.key_info.attr.wpa.mac_addr = mac_addr; - msg->body.key_info.attr.wpa.mode = cipher_mode; + if (tx_mic) + memcpy(&key_buf->key[ptk_key_len + RX_MIC_KEY_LEN], + tx_mic, TX_MIC_KEY_LEN); - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - goto free_key; + wid.id = WID_ADD_PTK; + wid.type = WID_STR; + wid.size = sizeof(*key_buf) + t_key_len; + wid.val = (s8 *)key_buf; + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + kfree(key_buf); } - wait_for_completion(&msg->work_comp); - -free_key: - kfree(msg->body.key_info.attr.wpa.key); - -free_msg: - kfree(msg); return result; } @@ -2831,108 +1702,76 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode) { - int result; - struct host_if_msg *msg; - struct host_if_drv *hif_drv = vif->hif_drv; - u8 key_len = gtk_key_len; - - if (!hif_drv) { - netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); - return -EFAULT; - } - - msg = wilc_alloc_work(vif, handle_key, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - if (rx_mic) - key_len += RX_MIC_KEY_LEN; - - if (tx_mic) - key_len += TX_MIC_KEY_LEN; - - if (key_rsc) { - msg->body.key_info.attr.wpa.seq = kmemdup(key_rsc, - key_rsc_len, - GFP_KERNEL); - if (!msg->body.key_info.attr.wpa.seq) { - result = -ENOMEM; - goto free_msg; - } - } + int result = 0; + struct wilc_gtk_key *gtk_key; + int t_key_len = gtk_key_len + RX_MIC_KEY_LEN + TX_MIC_KEY_LEN; - msg->body.key_info.type = WPA_RX_GTK; + gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL); + if (!gtk_key) + return -ENOMEM; - if (mode == AP_MODE) { - msg->body.key_info.action = ADDKEY_AP; - msg->body.key_info.attr.wpa.mode = cipher_mode; - } - if (mode == STATION_MODE) - msg->body.key_info.action = ADDKEY; + /* fill bssid value only in station mode */ + if (mode == WILC_STATION_MODE && + vif->hif_drv->hif_state == HOST_IF_CONNECTED) + memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN); - msg->body.key_info.attr.wpa.key = kmemdup(rx_gtk, key_len, GFP_KERNEL); - if (!msg->body.key_info.attr.wpa.key) { - result = -ENOMEM; - goto free_seq; - } + if (key_rsc) + memcpy(gtk_key->rsc, key_rsc, 8); + gtk_key->index = index; + gtk_key->key_len = t_key_len; + memcpy(>k_key->key[0], rx_gtk, gtk_key_len); if (rx_mic) - memcpy(msg->body.key_info.attr.wpa.key + 16, rx_mic, - RX_MIC_KEY_LEN); + memcpy(>k_key->key[gtk_key_len], rx_mic, RX_MIC_KEY_LEN); if (tx_mic) - memcpy(msg->body.key_info.attr.wpa.key + 24, tx_mic, - TX_MIC_KEY_LEN); + memcpy(>k_key->key[gtk_key_len + RX_MIC_KEY_LEN], + tx_mic, TX_MIC_KEY_LEN); - msg->body.key_info.attr.wpa.index = index; - msg->body.key_info.attr.wpa.key_len = key_len; - msg->body.key_info.attr.wpa.seq_len = key_rsc_len; + if (mode == WILC_AP_MODE) { + struct wid wid_list[2]; - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - goto free_key; - } + wid_list[0].id = WID_11I_MODE; + wid_list[0].type = WID_CHAR; + wid_list[0].size = sizeof(char); + wid_list[0].val = (s8 *)&cipher_mode; - wait_for_completion(&msg->work_comp); + wid_list[1].id = WID_ADD_RX_GTK; + wid_list[1].type = WID_STR; + wid_list[1].size = sizeof(*gtk_key) + t_key_len; + wid_list[1].val = (u8 *)gtk_key; -free_key: - kfree(msg->body.key_info.attr.wpa.key); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, + ARRAY_SIZE(wid_list), + wilc_get_vif_idx(vif)); + kfree(gtk_key); + } else if (mode == WILC_STATION_MODE) { + struct wid wid; -free_seq: - kfree(msg->body.key_info.attr.wpa.seq); + wid.id = WID_ADD_RX_GTK; + wid.type = WID_STR; + wid.size = sizeof(*gtk_key) + t_key_len; + wid.val = (u8 *)gtk_key; + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + kfree(gtk_key); + } -free_msg: - kfree(msg); return result; } -int wilc_set_pmkid_info(struct wilc_vif *vif, - struct host_if_pmkid_attr *pmkid) +int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid) { + struct wid wid; int result; - struct host_if_msg *msg; - int i; - - msg = wilc_alloc_work(vif, handle_key, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); - msg->body.key_info.type = PMKSA; - msg->body.key_info.action = ADDKEY; - - for (i = 0; i < pmkid->numpmkid; i++) { - memcpy(msg->body.key_info.attr.pmkid.pmkidlist[i].bssid, - &pmkid->pmkidlist[i].bssid, ETH_ALEN); - memcpy(msg->body.key_info.attr.pmkid.pmkidlist[i].pmkid, - &pmkid->pmkidlist[i].pmkid, PMKID_LEN); - } + wid.id = WID_PMKID_INFO; + wid.type = WID_STR; + wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1; + wid.val = (u8 *)pmkid; - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - } + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); return result; } @@ -2940,21 +1779,17 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) { int result; - struct host_if_msg *msg; - - msg = wilc_alloc_work(vif, handle_get_mac_address, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); + struct wid wid; - msg->body.get_mac_info.mac_addr = mac_addr; + wid.id = WID_MAC_ADDR; + wid.type = WID_STR; + wid.size = ETH_ALEN; + wid.val = mac_addr; - result = wilc_enqueue_work(msg); + result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (result) - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - else - wait_for_completion(&msg->work_comp); - - kfree(msg); + netdev_err(vif->ndev, "Failed to get mac address\n"); return result; } @@ -2966,8 +1801,8 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, u8 channel, void *join_params) { int result; - struct host_if_msg *msg; struct host_if_drv *hif_drv = vif->hif_drv; + struct user_conn_req *con_info = &hif_drv->usr_conn_req; if (!hif_drv || !connect_result) { netdev_err(vif->ndev, @@ -2981,50 +1816,45 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, return -EFAULT; } - msg = wilc_alloc_work(vif, handle_connect, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); + if (hif_drv->usr_scan_req.scan_result) { + netdev_err(vif->ndev, "%s: Scan in progress\n", __func__); + return -EBUSY; + } - msg->body.con_info.security = security; - msg->body.con_info.auth_type = auth_type; - msg->body.con_info.ch = channel; - msg->body.con_info.result = connect_result; - msg->body.con_info.arg = user_arg; - msg->body.con_info.params = join_params; + 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) { - msg->body.con_info.bssid = kmemdup(bssid, 6, GFP_KERNEL); - if (!msg->body.con_info.bssid) { - result = -ENOMEM; - goto free_msg; - } + con_info->bssid = kmemdup(bssid, 6, GFP_KERNEL); + if (!con_info->bssid) + return -ENOMEM; } if (ssid) { - msg->body.con_info.ssid_len = ssid_len; - msg->body.con_info.ssid = kmemdup(ssid, ssid_len, GFP_KERNEL); - if (!msg->body.con_info.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 (ies) { - msg->body.con_info.ies_len = ies_len; - msg->body.con_info.ies = kmemdup(ies, ies_len, GFP_KERNEL); - if (!msg->body.con_info.ies) { + con_info->ies_len = ies_len; + con_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!con_info->ies) { result = -ENOMEM; goto free_ssid; } } - if (hif_drv->hif_state < HOST_IF_CONNECTING) - hif_drv->hif_state = HOST_IF_CONNECTING; - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + result = wilc_send_connect_wid(vif); + if (result) goto free_ies; - } hif_drv->connect_timer_vif = vif; mod_timer(&hif_drv->connect_timer, @@ -3033,181 +1863,141 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, return 0; free_ies: - kfree(msg->body.con_info.ies); + kfree(con_info->ies); free_ssid: - kfree(msg->body.con_info.ssid); + kfree(con_info->ssid); free_bssid: - kfree(msg->body.con_info.bssid); - -free_msg: - kfree(msg); - return result; -} - -int wilc_disconnect(struct wilc_vif *vif, u16 reason_code) -{ - int result; - struct host_if_msg *msg; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!hif_drv) { - netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); - return -EFAULT; - } - - msg = wilc_alloc_work(vif, handle_disconnect, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - result = wilc_enqueue_work(msg); - if (result) - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - else - wait_for_completion(&msg->work_comp); + kfree(con_info->bssid); - kfree(msg); return result; } int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel) { + struct wid wid; int result; - struct host_if_msg *msg; - msg = wilc_alloc_work(vif, handle_set_channel, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->body.channel_info.set_ch = channel; + wid.id = WID_CURRENT_CHANNEL; + wid.type = WID_CHAR; + wid.size = sizeof(char); + wid.val = &channel; - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - } + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) + netdev_err(vif->ndev, "Failed to set channel\n"); return result; } int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, - u8 ifc_id, bool is_sync) + u8 ifc_id) { + struct wid wid; + struct host_if_drv *hif_drv = vif->hif_drv; int result; - struct host_if_msg *msg; - - msg = wilc_alloc_work(vif, handle_set_wfi_drv_handler, is_sync); - if (IS_ERR(msg)) - return PTR_ERR(msg); + struct wilc_drv_handler drv; - msg->body.drv.handler = index; - msg->body.drv.mode = mode; - msg->body.drv.name = ifc_id; + wid.id = WID_SET_DRV_HANDLER; + wid.type = WID_STR; + wid.size = sizeof(drv); + wid.val = (u8 *)&drv; - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - return result; - } + drv.handler = cpu_to_le32(index); + drv.mode = (ifc_id | (mode << 1)); - if (is_sync) - wait_for_completion(&msg->work_comp); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + hif_drv->driver_handler_id); + if (result) + netdev_err(vif->ndev, "Failed to set driver handler\n"); return result; } int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode) { + struct wid wid; + struct wilc_op_mode op_mode; int result; - struct host_if_msg *msg; - msg = wilc_alloc_work(vif, handle_set_operation_mode, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); + wid.id = WID_SET_OPERATION_MODE; + wid.type = WID_INT; + wid.size = sizeof(op_mode); + wid.val = (u8 *)&op_mode; - msg->body.mode.mode = mode; - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - } + op_mode.mode = cpu_to_le32(mode); + + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) + netdev_err(vif->ndev, "Failed to set operation mode\n"); return result; } -s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, - u32 *out_val) +s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val) { + struct wid wid; s32 result; - struct host_if_msg *msg; - struct host_if_drv *hif_drv = vif->hif_drv; - if (!hif_drv) { - netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); - return -EFAULT; - } - - msg = wilc_alloc_work(vif, handle_get_inactive_time, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); + wid.id = WID_SET_STA_MAC_INACTIVE_TIME; + wid.type = WID_STR; + wid.size = ETH_ALEN; + wid.val = kzalloc(wid.size, GFP_KERNEL); + if (!wid.val) + return -ENOMEM; - memcpy(msg->body.mac_info.mac, mac, ETH_ALEN); + ether_addr_copy(wid.val, mac); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + kfree(wid.val); + if (result) { + netdev_err(vif->ndev, "Failed to set inactive mac\n"); + return result; + } - result = wilc_enqueue_work(msg); + wid.id = WID_GET_INACTIVE_TIME; + wid.type = WID_INT; + wid.val = (s8 *)out_val; + wid.size = sizeof(u32); + result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (result) - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - else - wait_for_completion(&msg->work_comp); - - *out_val = msg->body.mac_info.inactive_time; - kfree(msg); + netdev_err(vif->ndev, "Failed to get inactive time\n"); return result; } int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) { + struct wid wid; int result; - struct host_if_msg *msg; if (!rssi_level) { netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__); return -EFAULT; } - msg = wilc_alloc_work(vif, handle_get_rssi, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->body.data = kzalloc(sizeof(s8), GFP_KERNEL); - if (!msg->body.data) { - kfree(msg); - return -ENOMEM; - } - - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - } else { - wait_for_completion(&msg->work_comp); - *rssi_level = *msg->body.data; - } - - kfree(msg->body.data); - kfree(msg); + wid.id = WID_RSSI; + wid.type = WID_CHAR; + wid.size = sizeof(char); + wid.val = rssi_level; + result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) + netdev_err(vif->ndev, "Failed to get RSSI value\n"); return result; } -int -wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats, bool is_sync) +int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats) { int result; struct host_if_msg *msg; - msg = wilc_alloc_work(vif, handle_get_statistics, is_sync); + msg = wilc_alloc_work(vif, handle_get_statistics, false); if (IS_ERR(msg)) return PTR_ERR(msg); @@ -3220,104 +2010,46 @@ wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats, bool is_sync) return result; } - if (is_sync) { - wait_for_completion(&msg->work_comp); - kfree(msg); - } - return result; } -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) +int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param) { + struct wid wid_list[4]; + int i = 0; int result; - struct host_if_msg *msg; - struct scan_attr *scan_info; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!hif_drv || !scan_result) { - netdev_err(vif->ndev, "hif_drv or scan_result = NULL\n"); - return -EFAULT; - } - - msg = wilc_alloc_work(vif, handle_scan, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); - scan_info = &msg->body.scan_info; - - if (hidden_network) { - scan_info->hidden_network.net_info = hidden_network->net_info; - scan_info->hidden_network.n_ssids = hidden_network->n_ssids; - } - - scan_info->src = scan_source; - scan_info->type = scan_type; - scan_info->result = scan_result; - scan_info->arg = user_arg; - - scan_info->ch_list_len = ch_list_len; - scan_info->ch_freq_list = kmemdup(ch_freq_list, - ch_list_len, - GFP_KERNEL); - if (!scan_info->ch_freq_list) { - result = -ENOMEM; - goto free_msg; + if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) { + wid_list[i].id = WID_SHORT_RETRY_LIMIT; + wid_list[i].val = (s8 *)¶m->short_retry_limit; + wid_list[i].type = WID_SHORT; + wid_list[i].size = sizeof(u16); + i++; } - - scan_info->ies_len = ies_len; - scan_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); - if (!scan_info->ies) { - result = -ENOMEM; - goto free_freq_list; + if (param->flag & WILC_CFG_PARAM_RETRY_LONG) { + wid_list[i].id = WID_LONG_RETRY_LIMIT; + wid_list[i].val = (s8 *)¶m->long_retry_limit; + wid_list[i].type = WID_SHORT; + wid_list[i].size = sizeof(u16); + i++; } - - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - goto free_ies; + if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) { + wid_list[i].id = WID_FRAG_THRESHOLD; + wid_list[i].val = (s8 *)¶m->frag_threshold; + wid_list[i].type = WID_SHORT; + wid_list[i].size = sizeof(u16); + i++; } - - hif_drv->scan_timer_vif = vif; - mod_timer(&hif_drv->scan_timer, - jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT)); - - return 0; - -free_ies: - kfree(scan_info->ies); - -free_freq_list: - kfree(scan_info->ch_freq_list); - -free_msg: - kfree(msg); - return result; -} - -int wilc_hif_set_cfg(struct wilc_vif *vif, - struct cfg_param_attr *cfg_param) -{ - struct host_if_msg *msg; - struct host_if_drv *hif_drv = vif->hif_drv; - int result; - - if (!hif_drv) { - netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); - return -EFAULT; + if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) { + wid_list[i].id = WID_RTS_THRESHOLD; + wid_list[i].val = (s8 *)¶m->rts_threshold; + wid_list[i].type = WID_SHORT; + wid_list[i].size = sizeof(u16); + i++; } - msg = wilc_alloc_work(vif, handle_cfg_param, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->body.cfg_info = *cfg_param; - result = wilc_enqueue_work(msg); - if (result) - kfree(msg); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, + i, wilc_get_vif_idx(vif)); return result; } @@ -3332,7 +2064,7 @@ static void get_periodic_rssi(struct timer_list *t) } if (vif->hif_drv->hif_state == HOST_IF_CONNECTED) - wilc_get_statistics(vif, &vif->periodic_stat, false); + wilc_get_stats_async(vif, &vif->periodic_stat); mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000)); } @@ -3368,20 +2100,10 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0); timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0); - mutex_init(&hif_drv->cfg_values_lock); - mutex_lock(&hif_drv->cfg_values_lock); - hif_drv->hif_state = HOST_IF_IDLE; - hif_drv->cfg_values.site_survey_enabled = SITE_SURVEY_OFF; - hif_drv->cfg_values.scan_source = DEFAULT_SCAN; - hif_drv->cfg_values.active_scan_time = ACTIVE_SCAN_TIME; - hif_drv->cfg_values.passive_scan_time = PASSIVE_SCAN_TIME; - hif_drv->cfg_values.curr_tx_rate = AUTORATE; hif_drv->p2p_timeout = 0; - mutex_unlock(&hif_drv->cfg_values_lock); - wilc->clients_count++; return 0; @@ -3406,7 +2128,7 @@ int wilc_deinit(struct wilc_vif *vif) del_timer_sync(&vif->periodic_rssi); del_timer_sync(&hif_drv->remain_on_ch_timer); - wilc_set_wfi_drv_handler(vif, 0, 0, 0, true); + wilc_set_wfi_drv_handler(vif, 0, 0, 0); if (hif_drv->usr_scan_req.scan_result) { hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL, @@ -3564,25 +2286,19 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, wilc_remain_on_chan_ready ready, void *user_arg) { + struct remain_ch roc; int result; - struct host_if_msg *msg; - - msg = wilc_alloc_work(vif, handle_remain_on_chan_work, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); - msg->body.remain_on_ch.ch = chan; - msg->body.remain_on_ch.expired = expired; - msg->body.remain_on_ch.ready = ready; - msg->body.remain_on_ch.arg = user_arg; - msg->body.remain_on_ch.duration = duration; - msg->body.remain_on_ch.id = session_id; - - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - } + roc.ch = chan; + roc.expired = expired; + roc.ready = ready; + roc.arg = user_arg; + roc.duration = duration; + roc.id = session_id; + result = handle_remain_on_chan(vif, &roc); + if (result) + netdev_err(vif->ndev, "%s: failed to set remain on channel\n", + __func__); return result; } @@ -3617,77 +2333,75 @@ int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id) void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) { + struct wid wid; int result; - struct host_if_msg *msg; + struct wilc_reg_frame reg_frame; - msg = wilc_alloc_work(vif, handle_register_frame, false); - if (IS_ERR(msg)) - return; + wid.id = WID_REGISTER_FRAME; + wid.type = WID_STR; + wid.size = sizeof(reg_frame); + wid.val = (u8 *)®_frame; + + memset(®_frame, 0x0, sizeof(reg_frame)); + reg_frame.reg = reg; switch (frame_type) { - case ACTION: - msg->body.reg_frame.reg_id = ACTION_FRM_IDX; + case IEEE80211_STYPE_ACTION: + reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX; break; - case PROBE_REQ: - msg->body.reg_frame.reg_id = PROBE_REQ_IDX; + case IEEE80211_STYPE_PROBE_REQ: + reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX; break; default: break; } - msg->body.reg_frame.frame_type = frame_type; - msg->body.reg_frame.reg = reg; - - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - } + reg_frame.frame_type = cpu_to_le16(frame_type); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) + netdev_err(vif->ndev, "Failed to frame register\n"); } int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *head, u32 tail_len, u8 *tail) + struct cfg80211_beacon_data *params) { + struct wid wid; int result; - struct host_if_msg *msg; - struct beacon_attr *beacon_info; + u8 *cur_byte; - msg = wilc_alloc_work(vif, handle_add_beacon, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); + wid.id = WID_ADD_BEACON; + wid.type = WID_BIN; + wid.size = params->head_len + params->tail_len + 16; + wid.val = kzalloc(wid.size, GFP_KERNEL); + if (!wid.val) + return -ENOMEM; - beacon_info = &msg->body.beacon_info; - beacon_info->interval = interval; - beacon_info->dtim_period = dtim_period; - beacon_info->head_len = head_len; - beacon_info->head = kmemdup(head, head_len, GFP_KERNEL); - if (!beacon_info->head) { - result = -ENOMEM; - goto error; - } - beacon_info->tail_len = tail_len; + cur_byte = wid.val; + put_unaligned_le32(interval, cur_byte); + cur_byte += 4; + put_unaligned_le32(dtim_period, cur_byte); + cur_byte += 4; + put_unaligned_le32(params->head_len, cur_byte); + cur_byte += 4; - if (tail_len > 0) { - beacon_info->tail = kmemdup(tail, tail_len, GFP_KERNEL); - if (!beacon_info->tail) { - result = -ENOMEM; - goto error; - } - } else { - beacon_info->tail = NULL; - } + if (params->head_len > 0) + memcpy(cur_byte, params->head, params->head_len); + cur_byte += params->head_len; - result = wilc_enqueue_work(msg); + put_unaligned_le32(params->tail_len, cur_byte); + cur_byte += 4; + + if (params->tail_len > 0) + memcpy(cur_byte, params->tail, params->tail_len); + + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (result) - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + netdev_err(vif->ndev, "Failed to send add beacon\n"); -error: - if (result) { - kfree(beacon_info->head); - kfree(beacon_info->tail); - kfree(msg); - } + kfree(wid.val); return result; } @@ -3695,170 +2409,158 @@ error: int wilc_del_beacon(struct wilc_vif *vif) { int result; - struct host_if_msg *msg; + struct wid wid; + u8 del_beacon = 0; - msg = wilc_alloc_work(vif, handle_del_beacon, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); + wid.id = WID_DEL_BEACON; + wid.type = WID_CHAR; + wid.size = sizeof(char); + wid.val = &del_beacon; - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - } + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) + netdev_err(vif->ndev, "Failed to send delete beacon\n"); return result; } -int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param) +int wilc_add_station(struct wilc_vif *vif, const u8 *mac, + struct station_parameters *params) { + struct wid wid; int result; - struct host_if_msg *msg; - struct add_sta_param *add_sta_info; + u8 *cur_byte; - msg = wilc_alloc_work(vif, handle_add_station, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); + wid.id = WID_ADD_STA; + wid.type = WID_BIN; + wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len; + wid.val = kmalloc(wid.size, GFP_KERNEL); + if (!wid.val) + return -ENOMEM; - add_sta_info = &msg->body.add_sta_info; - memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param)); - if (add_sta_info->rates_len > 0) { - add_sta_info->rates = kmemdup(sta_param->rates, - add_sta_info->rates_len, - GFP_KERNEL); - if (!add_sta_info->rates) { - kfree(msg); - return -ENOMEM; - } - } + cur_byte = wid.val; + wilc_hif_pack_sta_param(cur_byte, mac, params); + + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result != 0) + netdev_err(vif->ndev, "Failed to send add station\n"); + + kfree(wid.val); - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(add_sta_info->rates); - kfree(msg); - } return result; } int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr) { + struct wid wid; int result; - struct host_if_msg *msg; - struct del_sta *del_sta_info; - msg = wilc_alloc_work(vif, handle_del_station, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - del_sta_info = &msg->body.del_sta_info; + wid.id = WID_REMOVE_STA; + wid.type = WID_BIN; + wid.size = ETH_ALEN; + wid.val = kzalloc(wid.size, GFP_KERNEL); + if (!wid.val) + return -ENOMEM; if (!mac_addr) - eth_broadcast_addr(del_sta_info->mac_addr); + eth_broadcast_addr(wid.val); else - memcpy(del_sta_info->mac_addr, mac_addr, ETH_ALEN); + ether_addr_copy(wid.val, mac_addr); + + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) + netdev_err(vif->ndev, "Failed to del station\n"); + + kfree(wid.val); - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - } return result; } int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) { + struct wid wid; int result; - struct host_if_msg *msg; - struct del_all_sta *del_all_sta_info; - u8 zero_addr[ETH_ALEN] = {0}; int i; u8 assoc_sta = 0; + struct del_all_sta del_sta; - msg = wilc_alloc_work(vif, handle_del_all_sta, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - del_all_sta_info = &msg->body.del_all_sta_info; - - for (i = 0; i < MAX_NUM_STA; i++) { - if (memcmp(mac_addr[i], zero_addr, ETH_ALEN)) { - memcpy(del_all_sta_info->del_all_sta[i], mac_addr[i], - ETH_ALEN); + memset(&del_sta, 0x0, sizeof(del_sta)); + for (i = 0; i < WILC_MAX_NUM_STA; i++) { + if (!is_zero_ether_addr(mac_addr[i])) { assoc_sta++; + ether_addr_copy(del_sta.mac[i], mac_addr[i]); } } - if (!assoc_sta) { - kfree(msg); + + if (!assoc_sta) return 0; - } - del_all_sta_info->assoc_sta = assoc_sta; - result = wilc_enqueue_work(msg); + del_sta.assoc_sta = assoc_sta; - if (result) - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - else - wait_for_completion(&msg->work_comp); + wid.id = WID_DEL_ALL_STA; + wid.type = WID_STR; + wid.size = (assoc_sta * ETH_ALEN) + 1; + wid.val = (u8 *)&del_sta; - kfree(msg); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) + netdev_err(vif->ndev, "Failed to send delete all station\n"); return result; } -int wilc_edit_station(struct wilc_vif *vif, - struct add_sta_param *sta_param) +int wilc_edit_station(struct wilc_vif *vif, const u8 *mac, + struct station_parameters *params) { + struct wid wid; int result; - struct host_if_msg *msg; - struct add_sta_param *add_sta_info; + u8 *cur_byte; - msg = wilc_alloc_work(vif, handle_edit_station, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); + wid.id = WID_EDIT_STA; + wid.type = WID_BIN; + wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len; + wid.val = kmalloc(wid.size, GFP_KERNEL); + if (!wid.val) + return -ENOMEM; - add_sta_info = &msg->body.add_sta_info; - memcpy(add_sta_info, sta_param, sizeof(*add_sta_info)); - if (add_sta_info->rates_len > 0) { - add_sta_info->rates = kmemdup(sta_param->rates, - add_sta_info->rates_len, - GFP_KERNEL); - if (!add_sta_info->rates) { - kfree(msg); - return -ENOMEM; - } - } + cur_byte = wid.val; + wilc_hif_pack_sta_param(cur_byte, mac, params); - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(add_sta_info->rates); - kfree(msg); - } + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) + netdev_err(vif->ndev, "Failed to send edit station\n"); + kfree(wid.val); return result; } int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) { + struct wid wid; int result; - struct host_if_msg *msg; + s8 power_mode; if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled) return 0; - msg = wilc_alloc_work(vif, handle_power_management, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); + if (enabled) + power_mode = WILC_FW_MIN_FAST_PS; + else + power_mode = WILC_FW_NO_POWERSAVE; - msg->body.pwr_mgmt_info.enabled = enabled; - msg->body.pwr_mgmt_info.timeout = timeout; + wid.id = WID_POWER_MANAGEMENT; + wid.val = &power_mode; + wid.size = sizeof(char); + result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) + netdev_err(vif->ndev, "Failed to send power management\n"); - result = wilc_enqueue_work(msg); - if (result) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - } return result; } @@ -3887,19 +2589,15 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count, int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power) { int ret; - struct host_if_msg *msg; - - msg = wilc_alloc_work(vif, handle_set_tx_pwr, false); - if (IS_ERR(msg)) - return PTR_ERR(msg); + struct wid wid; - msg->body.tx_power.tx_pwr = tx_power; + wid.id = WID_TX_POWER; + wid.type = WID_CHAR; + wid.val = &tx_power; + wid.size = sizeof(char); - ret = wilc_enqueue_work(msg); - if (ret) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - kfree(msg); - } + ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); return ret; } @@ -3907,21 +2605,15 @@ int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power) int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power) { int ret; - struct host_if_msg *msg; + struct wid wid; - msg = wilc_alloc_work(vif, handle_get_tx_pwr, true); - if (IS_ERR(msg)) - return PTR_ERR(msg); + wid.id = WID_TX_POWER; + wid.type = WID_CHAR; + wid.val = tx_power; + wid.size = sizeof(char); - ret = wilc_enqueue_work(msg); - if (ret) { - netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); - } else { - wait_for_completion(&msg->work_comp); - *tx_power = msg->body.tx_power.tx_pwr; - } + ret = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); - /* free 'msg' after copying data */ - kfree(msg); return ret; } |