struct wilc_vif *vif;
struct work_struct work;
void (*fn)(struct work_struct *ws);
+ struct completion work_comp;
+ bool is_sync;
};
struct join_bss_param {
static struct workqueue_struct *hif_workqueue;
static struct completion hif_thread_comp;
static struct completion hif_driver_comp;
-static struct completion hif_wait_response;
static struct mutex hif_deinit_lock;
static struct timer_list periodic_rssi;
static struct wilc_vif *periodic_rssi_vif;
static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx);
static s32 handle_scan_done(struct wilc_vif *vif, enum scan_event evt);
+/* 'msg' should be free by the caller for syc */
static struct host_if_msg*
-wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *))
+wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
+ bool is_sync)
{
struct host_if_msg *msg;
return ERR_PTR(-ENOMEM);
msg->fn = work_fun;
msg->vif = vif;
+ msg->is_sync = is_sync;
+ if (is_sync)
+ init_completion(&msg->work_comp);
return msg;
}
if (ret)
netdev_err(vif->ndev, "Failed to get mac address\n");
- complete(&hif_wait_response);
- kfree(msg);
+ complete(&msg->work_comp);
+ /* free 'msg' data later, in caller */
complete(&hif_thread_comp);
}
wilc_get_vif_idx(vif));
}
out_wep:
- complete(&hif_drv->comp_test_key_block);
+ complete(&msg->work_comp);
break;
case WPA_RX_GTK:
kfree(key_buf);
}
out_wpa_rx_gtk:
- complete(&hif_drv->comp_test_key_block);
+ complete(&msg->work_comp);
kfree(hif_key->attr.wpa.key);
kfree(hif_key->attr.wpa.seq);
break;
}
out_wpa_ptk:
- complete(&hif_drv->comp_test_key_block);
+ complete(&msg->work_comp);
kfree(hif_key->attr.wpa.key);
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");
- kfree(msg);
+ /* free 'msg' data in caller sync call */
complete(&hif_thread_comp);
}
out:
- complete(&hif_drv->comp_test_disconn_block);
- kfree(msg);
+ complete(&msg->work_comp);
+ /* free 'msg' in caller after receiving completion */
complete(&hif_thread_comp);
}
if (result)
netdev_err(vif->ndev, "Failed to get RSSI value\n");
- complete(&vif->hif_drv->comp_get_rssi);
- kfree(msg);
+ complete(&msg->work_comp);
+ /* free 'msg' data in caller */
complete(&hif_thread_comp);
}
else if (stats->link_speed != DEFAULT_LINK_SPEED)
wilc_enable_tcp_ack_filter(false);
- if (stats != &vif->wilc->dummy_statistics)
- complete(&hif_wait_response);
- kfree(msg);
+ /* free 'msg' for async command, for sync caller will free it */
+ if (msg->is_sync)
+ complete(&msg->work_comp);
+ else
+ kfree(msg);
+
complete(&hif_thread_comp);
}
struct sta_inactive_t *hif_sta_inactive = &msg->body.mac_info;
s32 result = 0;
struct wid wid;
- struct host_if_drv *hif_drv = vif->hif_drv;
wid.id = (u16)WID_SET_STA_MAC_INACTIVE_TIME;
wid.type = WID_STR;
netdev_err(vif->ndev, "Failed to get inactive time\n");
out:
- complete(&hif_drv->comp_inactive_time);
-
- kfree(msg);
+ /* free 'msg' data in caller */
+ complete(&msg->work_comp);
complete(&hif_thread_comp);
}
error:
kfree(wid.val);
- complete(&hif_wait_response);
- kfree(msg);
+ /* free 'msg' data in caller */
+ complete(&msg->work_comp);
complete(&hif_thread_comp);
}
del_timer(&vif->hif_drv->remain_on_ch_timer);
- msg = wilc_alloc_work(vif, handle_listen_state_expired);
+ msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
if (IS_ERR(msg))
return;
if (ret)
netdev_err(vif->ndev, "Failed to get TX PWR\n");
- complete(&hif_wait_response);
+ complete(&msg->work_comp);
complete(&hif_thread_comp);
}
{
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
- kfree(msg);
- complete(&hif_thread_comp);
+ /* free 'msg' data in caller */
+ complete(&msg->work_comp);
}
static void handle_scan_complete(struct work_struct *work)
struct host_if_msg *msg;
int result;
- msg = wilc_alloc_work(vif, handle_scan_timer);
+ msg = wilc_alloc_work(vif, handle_scan_timer, false);
if (IS_ERR(msg))
return;
struct host_if_msg *msg;
int result;
- msg = wilc_alloc_work(vif, handle_connect_timeout);
+ msg = wilc_alloc_work(vif, handle_connect_timeout, false);
if (IS_ERR(msg))
return;
return result;
}
- msg = wilc_alloc_work(vif, handle_key);
+ msg = wilc_alloc_work(vif, handle_key, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
msg->body.key_info.attr.wep.index = index;
result = wilc_enqueue_cmd(msg);
- if (result) {
+ if (result)
netdev_err(vif->ndev, "Request to remove WEP key\n");
- kfree(msg);
- } else {
- wait_for_completion(&hif_drv->comp_test_key_block);
- }
+ else
+ wait_for_completion(&msg->work_comp);
+ kfree(msg);
return result;
}
return result;
}
- msg = wilc_alloc_work(vif, handle_key);
+ msg = wilc_alloc_work(vif, handle_key, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
msg->body.key_info.attr.wep.index = index;
result = wilc_enqueue_cmd(msg);
- if (result) {
+ if (result)
netdev_err(vif->ndev, "Default key index\n");
- kfree(msg);
- } else {
- wait_for_completion(&hif_drv->comp_test_key_block);
- }
+ else
+ wait_for_completion(&msg->work_comp);
+ kfree(msg);
return result;
}
return -EFAULT;
}
- msg = wilc_alloc_work(vif, handle_key);
+ msg = wilc_alloc_work(vif, handle_key, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
if (result)
goto free_key;
- wait_for_completion(&hif_drv->comp_test_key_block);
+ wait_for_completion(&msg->work_comp);
+ kfree(msg);
return 0;
free_key:
return -EFAULT;
}
- msg = wilc_alloc_work(vif, handle_key);
+ msg = wilc_alloc_work(vif, handle_key, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
if (result)
goto free_key;
- wait_for_completion(&hif_drv->comp_test_key_block);
+ wait_for_completion(&msg->work_comp);
+ kfree(msg);
return 0;
free_key:
if (tx_mic)
key_len += TX_MIC_KEY_LEN;
- msg = wilc_alloc_work(vif, handle_key);
+ msg = wilc_alloc_work(vif, handle_key, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
goto free_key;
}
- wait_for_completion(&hif_drv->comp_test_key_block);
+ wait_for_completion(&msg->work_comp);
+ kfree(msg);
return 0;
free_key:
return -EFAULT;
}
- msg = wilc_alloc_work(vif, handle_key);
+ msg = wilc_alloc_work(vif, handle_key, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
goto free_key;
}
- wait_for_completion(&hif_drv->comp_test_key_block);
+ wait_for_completion(&msg->work_comp);
+ kfree(msg);
return 0;
free_key:
struct host_if_msg *msg;
int i;
- msg = wilc_alloc_work(vif, handle_key);
+ msg = wilc_alloc_work(vif, handle_key, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_get_mac_address);
+ msg = wilc_alloc_work(vif, handle_get_mac_address, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
msg->body.get_mac_info.mac_addr = mac_addr;
result = wilc_enqueue_cmd(msg);
- if (result) {
+ if (result)
netdev_err(vif->ndev, "Failed to send get mac address\n");
- kfree(msg);
- return -EFAULT;
- }
+ else
+ wait_for_completion(&msg->work_comp);
+
+ kfree(msg);
- wait_for_completion(&hif_wait_response);
return result;
}
return -EFAULT;
}
- msg = wilc_alloc_work(vif, handle_connect);
+ msg = wilc_alloc_work(vif, handle_connect, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
return -EFAULT;
}
- msg = wilc_alloc_work(vif, handle_disconnect);
+ msg = wilc_alloc_work(vif, handle_disconnect, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
result = wilc_enqueue_cmd(msg);
- if (result) {
+ if (result)
netdev_err(vif->ndev, "Failed to send message: disconnect\n");
- kfree(msg);
- } else {
- wait_for_completion(&hif_drv->comp_test_disconn_block);
- }
+ else
+ wait_for_completion(&msg->work_comp);
+ kfree(msg);
return result;
}
int result;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_set_channel);
+ msg = wilc_alloc_work(vif, handle_set_channel, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_set_wfi_drv_handler);
+ msg = wilc_alloc_work(vif, handle_set_wfi_drv_handler, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_set_operation_mode);
+ msg = wilc_alloc_work(vif, handle_set_operation_mode, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
return -EFAULT;
}
- msg = wilc_alloc_work(vif, handle_get_inactive_time);
+ msg = wilc_alloc_work(vif, handle_get_inactive_time, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
memcpy(msg->body.mac_info.mac, mac, ETH_ALEN);
result = wilc_enqueue_cmd(msg);
- if (result) {
+ if (result)
netdev_err(vif->ndev, "Failed to send get host ch param\n");
- kfree(msg);
- } else {
- wait_for_completion(&hif_drv->comp_inactive_time);
- }
+ else
+ wait_for_completion(&msg->work_comp);
*out_val = inactive_time;
+ kfree(msg);
return result;
}
{
int result = 0;
struct host_if_msg *msg;
- struct host_if_drv *hif_drv = vif->hif_drv;
- msg = wilc_alloc_work(vif, handle_get_rssi);
+ if (!rssi_level) {
+ netdev_err(vif->ndev, "RSS pointer value is null\n");
+ return -EFAULT;
+ }
+
+ msg = wilc_alloc_work(vif, handle_get_rssi, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
result = wilc_enqueue_cmd(msg);
if (result) {
netdev_err(vif->ndev, "Failed to send get host ch param\n");
- kfree(msg);
- return result;
- }
-
- wait_for_completion(&hif_drv->comp_get_rssi);
-
- if (!rssi_level) {
- netdev_err(vif->ndev, "RSS pointer value is null\n");
- return -EFAULT;
+ } else {
+ wait_for_completion(&msg->work_comp);
+ *rssi_level = rssi;
}
- *rssi_level = rssi;
+ kfree(msg);
return result;
}
-int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
+int
+wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats, bool is_sync)
{
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_get_statistics);
+ msg = wilc_alloc_work(vif, handle_get_statistics, is_sync);
if (IS_ERR(msg))
return PTR_ERR(msg);
return result;
}
- if (stats != &vif->wilc->dummy_statistics)
- wait_for_completion(&hif_wait_response);
+ if (is_sync) {
+ wait_for_completion(&msg->work_comp);
+ kfree(msg);
+ }
+
return result;
}
return -EFAULT;
}
- msg = wilc_alloc_work(vif, handle_scan);
+ msg = wilc_alloc_work(vif, handle_scan, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
return -EFAULT;
}
- msg = wilc_alloc_work(vif, handle_cfg_param);
+ msg = wilc_alloc_work(vif, handle_cfg_param, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
}
if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
- wilc_get_statistics(vif, &vif->wilc->dummy_statistics);
+ wilc_get_statistics(vif, &vif->wilc->dummy_statistics, false);
mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
}
vif = netdev_priv(dev);
wilc = vif->wilc;
- init_completion(&hif_wait_response);
-
hif_drv = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
if (!hif_drv)
return -ENOMEM;
mutex_init(&hif_deinit_lock);
}
- init_completion(&hif_drv->comp_test_key_block);
- init_completion(&hif_drv->comp_test_disconn_block);
- init_completion(&hif_drv->comp_get_rssi);
- init_completion(&hif_drv->comp_inactive_time);
-
if (clients_count == 0) {
hif_workqueue = create_singlethread_workqueue("WILC_wq");
if (!hif_workqueue) {
if (clients_count == 1) {
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_hif_exit_work);
+ msg = wilc_alloc_work(vif, handle_hif_exit_work, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
if (result)
netdev_err(vif->ndev, "deinit : Error(%d)\n", result);
else
- wait_for_completion(&hif_thread_comp);
-
+ wait_for_completion(&msg->work_comp);
+ kfree(msg);
destroy_workqueue(hif_workqueue);
}
return;
}
- msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info);
+ msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
if (IS_ERR(msg))
return;
return;
}
- msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info);
+ msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
if (IS_ERR(msg)) {
mutex_unlock(&hif_deinit_lock);
return;
if (hif_drv->usr_scan_req.scan_result) {
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_scan_complete);
+ msg = wilc_alloc_work(vif, handle_scan_complete, false);
if (IS_ERR(msg))
return;
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_remain_on_chan_work);
+ msg = wilc_alloc_work(vif, handle_remain_on_chan_work, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
del_timer(&hif_drv->remain_on_ch_timer);
- msg = wilc_alloc_work(vif, handle_listen_state_expired);
+ msg = wilc_alloc_work(vif, handle_listen_state_expired, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_register_frame);
+ msg = wilc_alloc_work(vif, handle_register_frame, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
struct host_if_msg *msg;
struct beacon_attr *beacon_info;
- msg = wilc_alloc_work(vif, handle_add_beacon);
+ msg = wilc_alloc_work(vif, handle_add_beacon, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_del_beacon);
+ msg = wilc_alloc_work(vif, handle_del_beacon, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
struct host_if_msg *msg;
struct add_sta_param *add_sta_info;
- msg = wilc_alloc_work(vif, handle_add_station);
+ msg = wilc_alloc_work(vif, handle_add_station, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
struct host_if_msg *msg;
struct del_sta *del_sta_info;
- msg = wilc_alloc_work(vif, handle_del_station);
+ msg = wilc_alloc_work(vif, handle_del_station, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int i;
u8 assoc_sta = 0;
- msg = wilc_alloc_work(vif, handle_del_all_sta);
+ msg = wilc_alloc_work(vif, handle_del_all_sta, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
del_all_sta_info->assoc_sta = assoc_sta;
result = wilc_enqueue_cmd(msg);
- if (result) {
+ if (result)
netdev_err(vif->ndev, "wilc_mq_send fail\n");
- kfree(msg);
- } else {
- wait_for_completion(&hif_wait_response);
- }
+ else
+ wait_for_completion(&msg->work_comp);
+
+ kfree(msg);
return result;
}
struct host_if_msg *msg;
struct add_sta_param *add_sta_info;
- msg = wilc_alloc_work(vif, handle_edit_station);
+ msg = wilc_alloc_work(vif, handle_edit_station, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled)
return 0;
- msg = wilc_alloc_work(vif, handle_power_management);
+ msg = wilc_alloc_work(vif, handle_power_management, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_set_mcast_filter);
+ msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_set_ip_address);
+ msg = wilc_alloc_work(vif, handle_set_ip_address, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int result = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_get_ip_address);
+ msg = wilc_alloc_work(vif, handle_get_ip_address, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int ret = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_set_tx_pwr);
+ msg = wilc_alloc_work(vif, handle_set_tx_pwr, false);
if (IS_ERR(msg))
return PTR_ERR(msg);
int ret = 0;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_get_tx_pwr);
+ msg = wilc_alloc_work(vif, handle_get_tx_pwr, true);
if (IS_ERR(msg))
return PTR_ERR(msg);
ret = wilc_enqueue_cmd(msg);
if (ret) {
netdev_err(vif->ndev, "Failed to get TX PWR\n");
- kfree(msg);
- return ret;
+ } else {
+ wait_for_completion(&msg->work_comp);
+ *tx_power = msg->body.tx_power.tx_pwr;
}
- wait_for_completion(&hif_wait_response);
-
- *tx_power = msg->body.tx_power.tx_pwr;
/* free 'msg' after copying data */
kfree(msg);
return ret;