aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/wilc1000/host_interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/wilc1000/host_interface.c')
-rw-r--r--drivers/staging/wilc1000/host_interface.c277
1 files changed, 53 insertions, 224 deletions
diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
index 42d8accb1f60..01db8999335e 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -90,6 +90,7 @@ struct beacon_attr {
struct set_multicast {
bool enabled;
u32 cnt;
+ u8 *mc_list;
};
struct del_all_sta {
@@ -186,23 +187,7 @@ struct join_bss_param {
};
static struct host_if_drv *terminated_handle;
-bool wilc_optaining_ip;
-static u8 p2p_listen_state;
-static struct workqueue_struct *hif_workqueue;
-static struct completion hif_driver_comp;
static struct mutex hif_deinit_lock;
-static struct timer_list periodic_rssi;
-static struct wilc_vif *periodic_rssi_vif;
-
-u8 wilc_multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
-
-static u8 rcv_assoc_resp[MAX_ASSOC_RESP_FRAME_SIZE];
-
-static u8 set_ip[2][4];
-static u8 get_ip[2][4];
-static u32 clients_count;
-
-static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx);
/* 'msg' should be free by the caller for syc */
static struct host_if_msg*
@@ -229,7 +214,11 @@ wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
static int wilc_enqueue_work(struct host_if_msg *msg)
{
INIT_WORK(&msg->work, msg->fn);
- if (!hif_workqueue || !queue_work(hif_workqueue, &msg->work))
+
+ if (!msg->vif || !msg->vif->wilc || !msg->vif->wilc->hif_workqueue)
+ return -EINVAL;
+
+ if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
return -EINVAL;
return 0;
@@ -320,10 +309,12 @@ static void handle_set_wfi_drv_handler(struct work_struct *work)
if (ret)
netdev_err(vif->ndev, "Failed to set driver handler\n");
- complete(&hif_driver_comp);
kfree(buffer);
free_msg:
+ if (msg->is_sync)
+ complete(&msg->work_comp);
+
kfree(msg);
}
@@ -343,73 +334,12 @@ static void handle_set_operation_mode(struct work_struct *work)
ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
wilc_get_vif_idx(vif));
- if (hif_op_mode->mode == IDLE_MODE)
- complete(&hif_driver_comp);
-
if (ret)
netdev_err(vif->ndev, "Failed to set operation mode\n");
kfree(msg);
}
-static void handle_set_ip_address(struct work_struct *work)
-{
- struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
- struct wilc_vif *vif = msg->vif;
- u8 *ip_addr = msg->body.ip_info.ip_addr;
- u8 idx = msg->body.ip_info.idx;
- int ret;
- struct wid wid;
- char firmware_ip_addr[4] = {0};
-
- if (ip_addr[0] < 192)
- ip_addr[0] = 0;
-
- memcpy(set_ip[idx], ip_addr, IP_ALEN);
-
- wid.id = WID_IP_ADDRESS;
- wid.type = WID_STR;
- wid.val = ip_addr;
- wid.size = IP_ALEN;
-
- ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
-
- host_int_get_ipaddress(vif, firmware_ip_addr, idx);
-
- if (ret)
- netdev_err(vif->ndev, "Failed to set IP address\n");
- kfree(msg);
-}
-
-static void handle_get_ip_address(struct work_struct *work)
-{
- struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
- struct wilc_vif *vif = msg->vif;
- u8 idx = msg->body.ip_info.idx;
- int ret;
- struct wid wid;
-
- wid.id = WID_IP_ADDRESS;
- wid.type = WID_STR;
- wid.val = kmalloc(IP_ALEN, GFP_KERNEL);
- wid.size = IP_ALEN;
-
- ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1,
- wilc_get_vif_idx(vif));
-
- memcpy(get_ip[idx], wid.val, IP_ALEN);
-
- kfree(wid.val);
-
- if (memcmp(get_ip[idx], set_ip[idx], IP_ALEN) != 0)
- wilc_setup_ipaddress(vif, set_ip[idx], idx);
-
- if (ret)
- netdev_err(vif->ndev, "Failed to get IP address\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);
@@ -791,7 +721,7 @@ static void handle_scan(struct work_struct *work)
goto error;
}
- if (wilc_optaining_ip || wilc_connecting) {
+ if (vif->obtaining_ip || vif->connecting) {
netdev_err(vif->ndev, "Don't do obss scan\n");
result = -EBUSY;
goto error;
@@ -883,7 +813,6 @@ error:
kfree(msg);
}
-u8 wilc_connected_ssid[6] = {0};
static void handle_connect(struct work_struct *work)
{
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -905,11 +834,6 @@ static void handle_connect(struct work_struct *work)
return;
}
- if (memcmp(conn_attr->bssid, wilc_connected_ssid, ETH_ALEN) == 0) {
- netdev_err(vif->ndev, "Discard connect request\n");
- goto error;
- }
-
bss_param = conn_attr->params;
if (!bss_param) {
netdev_err(vif->ndev, "Required BSSID not found\n");
@@ -1089,10 +1013,6 @@ static void handle_connect(struct work_struct *work)
cur_byte = wid_list[wid_cnt].val;
wid_cnt++;
- if (conn_attr->bssid)
- memcpy(wilc_connected_ssid,
- conn_attr->bssid, ETH_ALEN);
-
result = wilc_send_config_pkt(vif, SET_CFG, wid_list,
wid_cnt,
wilc_get_vif_idx(vif));
@@ -1215,8 +1135,6 @@ static void handle_connect_timeout(struct work_struct *work)
kfree(hif_drv->usr_conn_req.ies);
hif_drv->usr_conn_req.ies = NULL;
- eth_zero_addr(wilc_connected_ssid);
-
out:
kfree(msg);
}
@@ -1456,10 +1374,10 @@ done:
kfree(msg);
}
-static s32 host_int_get_assoc_res_info(struct wilc_vif *vif,
- u8 *assoc_resp_info,
- u32 max_assoc_resp_info_len,
- u32 *rcvd_assoc_resp_info_len)
+static void host_int_get_assoc_res_info(struct wilc_vif *vif,
+ u8 *assoc_resp_info,
+ u32 max_assoc_resp_info_len,
+ u32 *rcvd_assoc_resp_info_len)
{
int result;
struct wid wid;
@@ -1474,11 +1392,10 @@ static s32 host_int_get_assoc_res_info(struct wilc_vif *vif,
if (result) {
*rcvd_assoc_resp_info_len = 0;
netdev_err(vif->ndev, "Failed to send association response\n");
- return -EINVAL;
+ return;
}
*rcvd_assoc_resp_info_len = wid.size;
- return result;
}
static inline void host_int_free_user_conn_req(struct host_if_drv *hif_drv)
@@ -1504,16 +1421,16 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
if (mac_status == MAC_STATUS_CONNECTED) {
u32 assoc_resp_info_len;
- memset(rcv_assoc_resp, 0, MAX_ASSOC_RESP_FRAME_SIZE);
+ memset(hif_drv->assoc_resp, 0, MAX_ASSOC_RESP_FRAME_SIZE);
- host_int_get_assoc_res_info(vif, rcv_assoc_resp,
+ host_int_get_assoc_res_info(vif, hif_drv->assoc_resp,
MAX_ASSOC_RESP_FRAME_SIZE,
&assoc_resp_info_len);
if (assoc_resp_info_len != 0) {
s32 err = 0;
- err = wilc_parse_assoc_resp_info(rcv_assoc_resp,
+ err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
assoc_resp_info_len,
&conn_info);
if (err)
@@ -1523,16 +1440,6 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
}
}
- if (mac_status == MAC_STATUS_CONNECTED &&
- conn_info.status != WLAN_STATUS_SUCCESS) {
- netdev_err(vif->ndev,
- "Received MAC status is MAC_STATUS_CONNECTED, Assoc Resp is not SUCCESS\n");
- eth_zero_addr(wilc_connected_ssid);
- } else if (mac_status == MAC_STATUS_DISCONNECTED) {
- netdev_err(vif->ndev, "Received MAC status is MAC_STATUS_DISCONNECTED\n");
- eth_zero_addr(wilc_connected_ssid);
- }
-
if (hif_drv->usr_conn_req.bssid) {
memcpy(conn_info.bssid, hif_drv->usr_conn_req.bssid, 6);
@@ -1562,8 +1469,8 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
hif_drv->hif_state = HOST_IF_CONNECTED;
- wilc_optaining_ip = true;
- mod_timer(&wilc_during_ip_timer,
+ vif->obtaining_ip = true;
+ mod_timer(&vif->during_ip_timer,
jiffies + msecs_to_jiffies(10000));
} else {
hif_drv->hif_state = HOST_IF_IDLE;
@@ -1595,7 +1502,7 @@ static inline void host_int_handle_disconnect(struct wilc_vif *vif)
disconn_info.ie_len = 0;
if (conn_result) {
- wilc_optaining_ip = false;
+ vif->obtaining_ip = false;
wilc_set_power_mgmt(vif, 0, 0);
conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, 0,
@@ -1942,11 +1849,9 @@ static void handle_disconnect(struct work_struct *work)
wid.val = (s8 *)&dummy_reason_code;
wid.size = sizeof(char);
- wilc_optaining_ip = false;
+ vif->obtaining_ip = false;
wilc_set_power_mgmt(vif, 0, 0);
- eth_zero_addr(wilc_connected_ssid);
-
result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
wilc_get_vif_idx(vif));
@@ -2076,9 +1981,9 @@ static void handle_get_statistics(struct work_struct *work)
if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
stats->link_speed != DEFAULT_LINK_SPEED)
- wilc_enable_tcp_ack_filter(true);
+ wilc_enable_tcp_ack_filter(vif, true);
else if (stats->link_speed != DEFAULT_LINK_SPEED)
- wilc_enable_tcp_ack_filter(false);
+ wilc_enable_tcp_ack_filter(vif, false);
/* free 'msg' for async command, for sync caller will free it */
if (msg->is_sync)
@@ -2397,7 +2302,7 @@ static int handle_remain_on_chan(struct wilc_vif *vif,
goto error;
}
- if (wilc_optaining_ip || wilc_connecting) {
+ if (vif->obtaining_ip || vif->connecting) {
result = -EBUSY;
goto error;
}
@@ -2422,7 +2327,6 @@ static int handle_remain_on_chan(struct wilc_vif *vif,
netdev_err(vif->ndev, "Failed to set remain on channel\n");
error:
- p2p_listen_state = 1;
hif_drv->remain_on_ch_timer_vif = vif;
mod_timer(&hif_drv->remain_on_ch_timer,
jiffies + msecs_to_jiffies(hif_remain_ch->duration));
@@ -2478,8 +2382,9 @@ static void handle_listen_state_expired(struct work_struct *work)
struct wid wid;
int result;
struct host_if_drv *hif_drv = vif->hif_drv;
+ struct wilc_priv *priv = wdev_priv(vif->ndev->ieee80211_ptr);
- if (p2p_listen_state) {
+ if (priv->p2p_listen_state) {
remain_on_chan_flag = false;
wid.id = WID_REMAIN_ON_CHAN;
wid.type = WID_STR;
@@ -2504,7 +2409,6 @@ static void handle_listen_state_expired(struct work_struct *work)
hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
hif_remain_ch->id);
}
- p2p_listen_state = 0;
} else {
netdev_dbg(vif->ndev, "Not in listen state\n");
}
@@ -2589,8 +2493,8 @@ static void handle_set_mcast_filter(struct work_struct *work)
*cur_byte++ = ((hif_set_mc->cnt >> 16) & 0xFF);
*cur_byte++ = ((hif_set_mc->cnt >> 24) & 0xFF);
- if (hif_set_mc->cnt > 0)
- memcpy(cur_byte, wilc_multicast_mac_addr_list,
+ if (hif_set_mc->cnt > 0 && hif_set_mc->mc_list)
+ memcpy(cur_byte, hif_set_mc->mc_list,
((hif_set_mc->cnt) * ETH_ALEN));
result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1,
@@ -2599,6 +2503,7 @@ static void handle_set_mcast_filter(struct work_struct *work)
netdev_err(vif->ndev, "Failed to send setup multicast\n");
error:
+ kfree(hif_set_mc->mc_list);
kfree(wid.val);
kfree(msg);
}
@@ -2661,14 +2566,6 @@ static void handle_remain_on_chan_work(struct work_struct *work)
kfree(msg);
}
-static void handle_hif_exit_work(struct work_struct *work)
-{
- struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
-
- /* free 'msg' data in caller */
- complete(&msg->work_comp);
-}
-
static void handle_scan_complete(struct work_struct *work)
{
struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
@@ -3195,12 +3092,12 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
}
int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
- u8 ifc_id)
+ u8 ifc_id, bool is_sync)
{
int result;
struct host_if_msg *msg;
- msg = wilc_alloc_work(vif, handle_set_wfi_drv_handler, false);
+ msg = wilc_alloc_work(vif, handle_set_wfi_drv_handler, is_sync);
if (IS_ERR(msg))
return PTR_ERR(msg);
@@ -3212,8 +3109,12 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode,
if (result) {
netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
kfree(msg);
+ return result;
}
+ if (is_sync)
+ wait_for_completion(&msg->work_comp);
+
return result;
}
@@ -3421,9 +3322,9 @@ int wilc_hif_set_cfg(struct wilc_vif *vif,
return result;
}
-static void get_periodic_rssi(struct timer_list *unused)
+static void get_periodic_rssi(struct timer_list *t)
{
- struct wilc_vif *vif = periodic_rssi_vif;
+ struct wilc_vif *vif = from_timer(vif, t, periodic_rssi);
if (!vif->hif_drv) {
netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
@@ -3431,9 +3332,9 @@ static void get_periodic_rssi(struct timer_list *unused)
}
if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
- wilc_get_statistics(vif, &vif->wilc->dummy_statistics, false);
+ wilc_get_statistics(vif, &vif->periodic_stat, false);
- mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
+ mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
}
int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
@@ -3455,25 +3356,13 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
break;
}
- wilc_optaining_ip = false;
+ vif->obtaining_ip = false;
- if (clients_count == 0) {
- init_completion(&hif_driver_comp);
+ if (wilc->clients_count == 0)
mutex_init(&hif_deinit_lock);
- }
- if (clients_count == 0) {
- hif_workqueue = create_singlethread_workqueue("WILC_wq");
- if (!hif_workqueue) {
- netdev_err(vif->ndev, "Failed to create workqueue\n");
- kfree(hif_drv);
- return -ENOMEM;
- }
-
- periodic_rssi_vif = vif;
- timer_setup(&periodic_rssi, get_periodic_rssi, 0);
- mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000));
- }
+ timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
+ mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
@@ -3493,7 +3382,7 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
mutex_unlock(&hif_drv->cfg_values_lock);
- clients_count++;
+ wilc->clients_count++;
return 0;
}
@@ -3514,11 +3403,10 @@ int wilc_deinit(struct wilc_vif *vif)
del_timer_sync(&hif_drv->scan_timer);
del_timer_sync(&hif_drv->connect_timer);
- del_timer_sync(&periodic_rssi);
+ del_timer_sync(&vif->periodic_rssi);
del_timer_sync(&hif_drv->remain_on_ch_timer);
- wilc_set_wfi_drv_handler(vif, 0, 0, 0);
- wait_for_completion(&hif_driver_comp);
+ wilc_set_wfi_drv_handler(vif, 0, 0, 0, true);
if (hif_drv->usr_scan_req.scan_result) {
hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
@@ -3529,25 +3417,9 @@ int wilc_deinit(struct wilc_vif *vif)
hif_drv->hif_state = HOST_IF_IDLE;
- if (clients_count == 1) {
- struct host_if_msg *msg;
-
- msg = wilc_alloc_work(vif, handle_hif_exit_work, true);
- if (!IS_ERR(msg)) {
- result = wilc_enqueue_work(msg);
- if (result)
- netdev_err(vif->ndev, "deinit : Error(%d)\n",
- result);
- else
- wait_for_completion(&msg->work_comp);
- kfree(msg);
- }
- destroy_workqueue(hif_workqueue);
- }
-
kfree(hif_drv);
- clients_count--;
+ vif->wilc->clients_count--;
terminated_handle = NULL;
mutex_unlock(&hif_deinit_lock);
return result;
@@ -3743,14 +3615,14 @@ int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id)
return result;
}
-int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
+void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
{
int result;
struct host_if_msg *msg;
msg = wilc_alloc_work(vif, handle_register_frame, false);
if (IS_ERR(msg))
- return PTR_ERR(msg);
+ return;
switch (frame_type) {
case ACTION:
@@ -3772,8 +3644,6 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
kfree(msg);
}
-
- return result;
}
int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
@@ -3992,8 +3862,8 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
return result;
}
-int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled,
- u32 count)
+int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count,
+ u8 *mc_list)
{
int result;
struct host_if_msg *msg;
@@ -4004,6 +3874,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled,
msg->body.multicast_info.enabled = enabled;
msg->body.multicast_info.cnt = count;
+ msg->body.multicast_info.mc_list = mc_list;
result = wilc_enqueue_work(msg);
if (result) {
@@ -4013,48 +3884,6 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled,
return result;
}
-int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
-{
- int result;
- struct host_if_msg *msg;
-
- msg = wilc_alloc_work(vif, handle_set_ip_address, false);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->body.ip_info.ip_addr = ip_addr;
- msg->body.ip_info.idx = idx;
-
- result = wilc_enqueue_work(msg);
- if (result) {
- netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
- kfree(msg);
- }
-
- return result;
-}
-
-static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx)
-{
- int result;
- struct host_if_msg *msg;
-
- msg = wilc_alloc_work(vif, handle_get_ip_address, false);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->body.ip_info.ip_addr = ip_addr;
- msg->body.ip_info.idx = idx;
-
- result = wilc_enqueue_work(msg);
- if (result) {
- netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
- kfree(msg);
- }
-
- return result;
-}
-
int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
{
int ret;