diff options
Diffstat (limited to 'drivers/staging/wilc1000')
21 files changed, 1741 insertions, 2048 deletions
diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile index ee7e26b886a5..f7b07c0b5ce2 100644 --- a/drivers/staging/wilc1000/Makefile +++ b/drivers/staging/wilc1000/Makefile @@ -1,5 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_WILC1000) += wilc1000.o ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \ -DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\" @@ -12,7 +11,9 @@ wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \ wilc_wlan.o obj-$(CONFIG_WILC1000_SDIO) += wilc1000-sdio.o +wilc1000-sdio-objs += $(wilc1000-objs) wilc1000-sdio-objs += wilc_sdio.o obj-$(CONFIG_WILC1000_SPI) += wilc1000-spi.o +wilc1000-spi-objs += $(wilc1000-objs) wilc1000-spi-objs += wilc_spi.o diff --git a/drivers/staging/wilc1000/TODO b/drivers/staging/wilc1000/TODO index d123324bd5c9..862e9eac9d60 100644 --- a/drivers/staging/wilc1000/TODO +++ b/drivers/staging/wilc1000/TODO @@ -1,14 +1,3 @@ TODO: -- rework comments and function headers(also coding style) -- Move handling for each individual members of 'union message_body' out - into a separate 'struct work_struct' and completely remove the multiplexer - that is currently part of host_if_work(), allowing movement of the - implementation of each message handler into the callsite of the function - that currently queues the 'host_if_msg'. -- make spi and sdio components coexist in one build - support soft-ap and p2p mode - support resume/suspend function -- convert all uses of the old GPIO API from <linux/gpio.h> to the - GPIO descriptor API in <linux/gpio/consumer.h> and look up GPIO - lines from device tree, ACPI or board files, board files should - use <linux/gpio/machine.h> diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 44816024f79c..e5420676afb3 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -1,17 +1,16 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + +#include <linux/ieee80211.h> + #include "coreconfigurator.h" #define TAG_PARAM_OFFSET (MAC_HDR_LEN + TIME_STAMP_LEN + \ BEACON_INTERVAL_LEN + CAP_INFO_LEN) -enum basic_frame_type { - FRAME_TYPE_CONTROL = 0x04, - FRAME_TYPE_DATA = 0x08, - FRAME_TYPE_MANAGEMENT = 0x00, - FRAME_TYPE_RESERVED = 0x0C, - FRAME_TYPE_FORCE_32BIT = 0xFFFFFFFF -}; - enum sub_frame_type { ASSOC_REQ = 0x00, ASSOC_RSP = 0x10, @@ -51,49 +50,6 @@ enum sub_frame_type { FRAME_SUBTYPE_FORCE_32BIT = 0xFFFFFFFF }; -enum info_element_id { - ISSID = 0, /* Service Set Identifier */ - ISUPRATES = 1, /* Supported Rates */ - IFHPARMS = 2, /* FH parameter set */ - IDSPARMS = 3, /* DS parameter set */ - ICFPARMS = 4, /* CF parameter set */ - ITIM = 5, /* Traffic Information Map */ - IIBPARMS = 6, /* IBSS parameter set */ - ICOUNTRY = 7, /* Country element */ - IEDCAPARAMS = 12, /* EDCA parameter set */ - ITSPEC = 13, /* Traffic Specification */ - ITCLAS = 14, /* Traffic Classification */ - ISCHED = 15, /* Schedule */ - ICTEXT = 16, /* Challenge Text */ - IPOWERCONSTRAINT = 32, /* Power Constraint */ - IPOWERCAPABILITY = 33, /* Power Capability */ - ITPCREQUEST = 34, /* TPC Request */ - ITPCREPORT = 35, /* TPC Report */ - ISUPCHANNEL = 36, /* Supported channel list */ - ICHSWANNOUNC = 37, /* Channel Switch Announcement */ - IMEASUREMENTREQUEST = 38, /* Measurement request */ - IMEASUREMENTREPORT = 39, /* Measurement report */ - IQUIET = 40, /* Quiet element Info */ - IIBSSDFS = 41, /* IBSS DFS */ - IERPINFO = 42, /* ERP Information */ - ITSDELAY = 43, /* TS Delay */ - ITCLASPROCESS = 44, /* TCLAS Processing */ - IHTCAP = 45, /* HT Capabilities */ - IQOSCAP = 46, /* QoS Capability */ - IRSNELEMENT = 48, /* RSN Information Element */ - IEXSUPRATES = 50, /* Extended Supported Rates */ - IEXCHSWANNOUNC = 60, /* Extended Ch Switch Announcement*/ - IHTOPERATION = 61, /* HT Information */ - ISECCHOFF = 62, /* Secondary Channel Offeset */ - I2040COEX = 72, /* 20/40 Coexistence IE */ - I2040INTOLCHREPORT = 73, /* 20/40 Intolerant channel report*/ - IOBSSSCAN = 74, /* OBSS Scan parameters */ - IEXTCAP = 127, /* Extended capability */ - IWMM = 221, /* WMM parameters */ - IWPAELEMENT = 221, /* WPA Information Element */ - INFOELEM_ID_FORCE_32BIT = 0xFFFFFFFF -}; - static inline u16 get_beacon_period(u8 *data) { u16 bcn_per; @@ -172,9 +128,7 @@ static inline void get_BSSID(u8 *data, u8 *bssid) static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len) { - u8 len = 0; - u8 i = 0; - u8 j = 0; + u8 i, j, len; len = data[TAG_PARAM_OFFSET + 1]; j = TAG_PARAM_OFFSET + 2; @@ -222,7 +176,7 @@ static u8 *get_tim_elm(u8 *msa, u16 rx_len, u16 tag_param_offset) index = tag_param_offset; while (index < (rx_len - FCS_LEN)) { - if (msa[index] == ITIM) + if (msa[index] == WLAN_EID_TIM) return &msa[index]; index += (IE_HDR_LEN + msa[index + 1]); } @@ -236,7 +190,7 @@ static u8 get_current_channel_802_11n(u8 *msa, u16 rx_len) index = TAG_PARAM_OFFSET; while (index < (rx_len - FCS_LEN)) { - if (msa[index] == IDSPARMS) + if (msa[index] == WLAN_EID_DS_PARAMS) return msa[index + 2]; index += msa[index + 1] + IE_HDR_LEN; } @@ -247,18 +201,11 @@ static u8 get_current_channel_802_11n(u8 *msa, u16 rx_len) s32 wilc_parse_network_info(u8 *msg_buffer, struct network_info **ret_network_info) { - struct network_info *network_info = NULL; - u8 msg_type = 0; - u16 wid_len = 0; - u8 *wid_val = NULL; - u8 *msa = NULL; - u16 rx_len = 0; - u8 *tim_elm = NULL; - u8 *ies = NULL; - u16 ies_len = 0; - u8 index = 0; - u32 tsf_lo; - u32 tsf_hi; + struct network_info *network_info; + u8 *wid_val, *msa, *tim_elm, *ies; + u32 tsf_lo, tsf_hi; + u16 wid_len, rx_len, ies_len; + u8 msg_type, index; msg_type = msg_buffer[0]; @@ -320,11 +267,11 @@ s32 wilc_parse_network_info(u8 *msg_buffer, s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, struct connect_info *ret_conn_info) { - u8 *ies = NULL; - u16 ies_len = 0; + u8 *ies; + u16 ies_len; ret_conn_info->status = get_asoc_status(buffer); - if (ret_conn_info->status == SUCCESSFUL_STATUSCODE) { + if (ret_conn_info->status == WLAN_STATUS_SUCCESS) { ies = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; ies_len = buffer_len - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 55b5531856f8..b62acb447383 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -1,4 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + #ifndef CORECONFIGURATOR_H #define CORECONFIGURATOR_H @@ -24,26 +29,6 @@ #define MAKE_WORD16(lsb, msb) ((((u16)(msb) << 8) & 0xFF00) | (lsb)) #define MAKE_WORD32(lsw, msw) ((((u32)(msw) << 16) & 0xFFFF0000) | (lsw)) -enum connect_status { - SUCCESSFUL_STATUSCODE = 0, - UNSPEC_FAIL = 1, - UNSUP_CAP = 10, - REASOC_NO_ASOC = 11, - FAIL_OTHER = 12, - UNSUPT_ALG = 13, - AUTH_SEQ_FAIL = 14, - CHLNG_FAIL = 15, - AUTH_TIMEOUT = 16, - AP_FULL = 17, - UNSUP_RATE = 18, - SHORT_PREAMBLE_UNSUP = 19, - PBCC_UNSUP = 20, - CHANNEL_AGIL_UNSUP = 21, - SHORT_SLOT_UNSUP = 25, - OFDM_DSSS_UNSUP = 26, - CONNECT_STS_FORCE_16_BIT = 0xFFFF -}; - struct rssi_history_buffer { bool full; u8 index; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0aaae33f97b9..42d8accb1f60 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1,49 +1,16 @@ // SPDX-License-Identifier: GPL-2.0 -#include "wilc_wfi_netdevice.h" +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ -#define HOST_IF_MSG_SCAN 0 -#define HOST_IF_MSG_CONNECT 1 -#define HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO 2 -#define HOST_IF_MSG_KEY 3 -#define HOST_IF_MSG_RCVD_NTWRK_INFO 4 -#define HOST_IF_MSG_RCVD_SCAN_COMPLETE 5 -#define HOST_IF_MSG_CFG_PARAMS 6 -#define HOST_IF_MSG_SET_CHANNEL 7 -#define HOST_IF_MSG_DISCONNECT 8 -#define HOST_IF_MSG_GET_RSSI 9 -#define HOST_IF_MSG_ADD_BEACON 11 -#define HOST_IF_MSG_DEL_BEACON 12 -#define HOST_IF_MSG_ADD_STATION 13 -#define HOST_IF_MSG_DEL_STATION 14 -#define HOST_IF_MSG_EDIT_STATION 15 -#define HOST_IF_MSG_SCAN_TIMER_FIRED 16 -#define HOST_IF_MSG_CONNECT_TIMER_FIRED 17 -#define HOST_IF_MSG_POWER_MGMT 18 -#define HOST_IF_MSG_GET_INACTIVETIME 19 -#define HOST_IF_MSG_REMAIN_ON_CHAN 20 -#define HOST_IF_MSG_REGISTER_FRAME 21 -#define HOST_IF_MSG_LISTEN_TIMER_FIRED 22 -#define HOST_IF_MSG_SET_WFIDRV_HANDLER 24 -#define HOST_IF_MSG_GET_MAC_ADDRESS 26 -#define HOST_IF_MSG_SET_OPERATION_MODE 27 -#define HOST_IF_MSG_SET_IPADDRESS 28 -#define HOST_IF_MSG_GET_IPADDRESS 29 -#define HOST_IF_MSG_GET_STATISTICS 31 -#define HOST_IF_MSG_SET_MULTICAST_FILTER 32 -#define HOST_IF_MSG_DEL_BA_SESSION 34 -#define HOST_IF_MSG_DEL_ALL_STA 36 -#define HOST_IF_MSG_SET_TX_POWER 38 -#define HOST_IF_MSG_GET_TX_POWER 39 -#define HOST_IF_MSG_EXIT 100 +#include "wilc_wfi_netdevice.h" #define HOST_IF_SCAN_TIMEOUT 4000 #define HOST_IF_CONNECT_TIMEOUT 9500 #define FALSE_FRMWR_CHANNEL 100 -#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54 -#define DEFAULT_LINK_SPEED 72 - #define REAL_JOIN_REQ 0 struct host_if_wpa_attr { @@ -61,7 +28,7 @@ struct host_if_wep_attr { u8 key_len; u8 index; u8 mode; - enum AUTHTYPE auth_type; + enum authtype auth_type; }; union host_if_key_attr { @@ -97,7 +64,7 @@ struct connect_attr { u8 security; wilc_connect_result result; void *arg; - enum AUTHTYPE auth_type; + enum authtype auth_type; u8 ch; void *params; }; @@ -145,6 +112,7 @@ struct set_ip_addr { }; struct sta_inactive_t { + u32 inactive_time; u8 mac[6]; }; @@ -180,10 +148,12 @@ union message_body { }; struct host_if_msg { - u16 id; union message_body body; 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 { @@ -219,9 +189,7 @@ 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_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; @@ -230,37 +198,44 @@ u8 wilc_multicast_mac_addr_list[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN]; static u8 rcv_assoc_resp[MAX_ASSOC_RESP_FRAME_SIZE]; -static s8 rssi; static u8 set_ip[2][4]; static u8 get_ip[2][4]; -static u32 inactive_time; static u32 clients_count; -static void *host_int_parse_join_bss_param(struct network_info *info); 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); -static void host_if_work(struct work_struct *work); - -/*! - * @author syounan - * @date 1 Sep 2010 - * @note copied from FLO glue implementatuion - * @version 1.0 - */ -static int wilc_enqueue_cmd(struct host_if_msg *msg) + +/* '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 *), + bool is_sync) { - struct host_if_msg *new_msg; + struct host_if_msg *msg; - new_msg = kmemdup(msg, sizeof(*new_msg), GFP_ATOMIC); - if (!new_msg) - return -ENOMEM; + if (!work_fun) + return ERR_PTR(-EINVAL); + + msg = kzalloc(sizeof(*msg), GFP_ATOMIC); + if (!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; +} + +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)) + return -EINVAL; - INIT_WORK(&new_msg->work, host_if_work); - queue_work(hif_workqueue, &new_msg->work); return 0; } -/* The u8IfIdx starts from 0 to NUM_CONCURRENT_IFC -1, but 0 index used as +/* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as * special purpose in wilc device, so we add 1 to the index to starts from 1. * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC. */ @@ -272,7 +247,7 @@ int wilc_get_vif_idx(struct wilc_vif *vif) /* We need to minus 1 from idx which is from wilc device to get real index * of wilc->vif[], because we add 1 when pass to wilc device in the function * wilc_get_vif_idx. - * As a result, the index should be between 0 and NUM_CONCURRENT_IFC -1. + * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1). */ static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx) { @@ -284,13 +259,15 @@ static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx) return wilc->vif[index]; } -static void handle_set_channel(struct wilc_vif *vif, - struct channel_attr *hif_set_ch) +static void handle_set_channel(struct work_struct *work) { - int ret = 0; + 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 = (u16)WID_CURRENT_CHANNEL; + wid.id = WID_CURRENT_CHANNEL; wid.type = WID_CHAR; wid.val = (char *)&hif_set_ch->set_ch; wid.size = sizeof(char); @@ -300,27 +277,27 @@ static void handle_set_channel(struct wilc_vif *vif, if (ret) netdev_err(vif->ndev, "Failed to set channel\n"); + kfree(msg); } -static int handle_set_wfi_drv_handler(struct wilc_vif *vif, - struct drv_handler *hif_drv_handler) +static void handle_set_wfi_drv_handler(struct work_struct *work) { - int ret = 0; + 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 = NULL; - - if (!vif->hif_drv) - return -EINVAL; + struct host_if_drv *hif_drv; - if (!hif_drv_handler) - return -EINVAL; + if (!vif->hif_drv || !hif_drv_handler) + goto free_msg; hif_drv = vif->hif_drv; buffer = kzalloc(DRV_HANDLER_SIZE, GFP_KERNEL); if (!buffer) - return -ENOMEM; + goto free_msg; currbyte = buffer; *currbyte = hif_drv->driver_handler_id & DRV_HANDLER_MASK; @@ -333,31 +310,32 @@ static int handle_set_wfi_drv_handler(struct wilc_vif *vif, currbyte++; *currbyte = (hif_drv_handler->name | (hif_drv_handler->mode << 1)); - wid.id = (u16)WID_SET_DRV_HANDLER; + 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) { + if (ret) netdev_err(vif->ndev, "Failed to set driver handler\n"); - complete(&hif_driver_comp); - kfree(buffer); - return ret; - } + complete(&hif_driver_comp); kfree(buffer); - return 0; + +free_msg: + kfree(msg); } -static void handle_set_operation_mode(struct wilc_vif *vif, - struct op_mode *hif_op_mode) +static void handle_set_operation_mode(struct work_struct *work) { - int ret = 0; + 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 = (u16)WID_SET_OPERATION_MODE; + wid.id = WID_SET_OPERATION_MODE; wid.type = WID_INT; wid.val = (s8 *)&hif_op_mode->mode; wid.size = sizeof(u32); @@ -369,12 +347,18 @@ static void handle_set_operation_mode(struct wilc_vif *vif, complete(&hif_driver_comp); if (ret) - netdev_err(vif->ndev, "Failed to set driver handler\n"); + netdev_err(vif->ndev, "Failed to set operation mode\n"); + + kfree(msg); } -static void handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) +static void handle_set_ip_address(struct work_struct *work) { - int ret = 0; + 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}; @@ -383,7 +367,7 @@ static void handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) memcpy(set_ip[idx], ip_addr, IP_ALEN); - wid.id = (u16)WID_IP_ADDRESS; + wid.id = WID_IP_ADDRESS; wid.type = WID_STR; wid.val = ip_addr; wid.size = IP_ALEN; @@ -395,14 +379,18 @@ static void handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) if (ret) netdev_err(vif->ndev, "Failed to set IP address\n"); + kfree(msg); } -static void handle_get_ip_address(struct wilc_vif *vif, u8 idx) +static void handle_get_ip_address(struct work_struct *work) { - int ret = 0; + 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 = (u16)WID_IP_ADDRESS; + wid.id = WID_IP_ADDRESS; wid.type = WID_STR; wid.val = kmalloc(IP_ALEN, GFP_KERNEL); wid.size = IP_ALEN; @@ -419,15 +407,18 @@ static void handle_get_ip_address(struct wilc_vif *vif, u8 idx) if (ret) netdev_err(vif->ndev, "Failed to get IP address\n"); + kfree(msg); } -static void handle_get_mac_address(struct wilc_vif *vif, - struct get_mac_addr *get_mac_addr) +static void handle_get_mac_address(struct work_struct *work) { - int ret = 0; + 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 = (u16)WID_MAC_ADDR; + wid.id = WID_MAC_ADDR; wid.type = WID_STR; wid.val = get_mac_addr->mac_addr; wid.size = ETH_ALEN; @@ -437,12 +428,16 @@ static void handle_get_mac_address(struct wilc_vif *vif, if (ret) netdev_err(vif->ndev, "Failed to get mac address\n"); - complete(&hif_wait_response); + complete(&msg->work_comp); + /* free 'msg' data later, in caller */ } -static void handle_cfg_param(struct wilc_vif *vif, struct cfg_param_attr *param) +static void handle_cfg_param(struct work_struct *work) { - int ret = 0; + 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; @@ -641,7 +636,7 @@ static void handle_cfg_param(struct wilc_vif *vif, struct cfg_param_attr *param) i++; } if (param->flag & SITE_SURVEY) { - enum SITESURVEY enabled = param->site_survey_enabled; + enum site_survey enabled = param->site_survey_enabled; if (enabled < 3) { wid_list[i].id = WID_SITE_SURVEY; @@ -701,7 +696,7 @@ static void handle_cfg_param(struct wilc_vif *vif, struct cfg_param_attr *param) i++; } if (param->flag & CURRENT_TX_RATE) { - enum CURRENT_TXRATE curr_tx_rate = param->curr_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 || @@ -730,11 +725,53 @@ static void handle_cfg_param(struct wilc_vif *vif, struct cfg_param_attr *param) 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; + u8 abort_running_scan; + struct wid wid; + struct host_if_drv *hif_drv = vif->hif_drv; + struct user_scan_req *scan_req; + + if (evt == SCAN_EVENT_ABORTED) { + abort_running_scan = 1; + wid.id = WID_ABORT_RUNNING_SCAN; + wid.type = WID_CHAR; + wid.val = (s8 *)&abort_running_scan; + 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 set abort running\n"); + result = -EFAULT; + } + } + + if (!hif_drv) { + netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__); + return result; + } + + scan_req = &hif_drv->usr_scan_req; + if (scan_req->scan_result) { + scan_req->scan_result(evt, NULL, scan_req->arg, NULL); + scan_req->scan_result = NULL; + } + + return result; } -static s32 handle_scan(struct wilc_vif *vif, struct scan_attr *scan_info) +static void handle_scan(struct work_struct *work) { - s32 result = 0; + 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; u32 i; @@ -760,9 +797,9 @@ static s32 handle_scan(struct wilc_vif *vif, struct scan_attr *scan_info) goto error; } - hif_drv->usr_scan_req.rcvd_ch_cnt = 0; + hif_drv->usr_scan_req.ch_cnt = 0; - wid_list[index].id = (u16)WID_SSID_PROBE_REQ; + wid_list[index].id = WID_SSID_PROBE_REQ; wid_list[index].type = WID_STR; for (i = 0; i < hidden_net->n_ssids; i++) @@ -804,7 +841,7 @@ static s32 handle_scan(struct wilc_vif *vif, struct scan_attr *scan_info) scan_info->ch_list_len > 0) { int i; - for (i = 0; i < scan_info->ch_list_len; 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; } @@ -843,62 +880,34 @@ error: kfree(hdn_ntwk_wid_val); - return result; -} - -static s32 handle_scan_done(struct wilc_vif *vif, enum scan_event evt) -{ - s32 result = 0; - u8 abort_running_scan; - struct wid wid; - struct host_if_drv *hif_drv = vif->hif_drv; - struct user_scan_req *scan_req; - - if (evt == SCAN_EVENT_ABORTED) { - abort_running_scan = 1; - wid.id = (u16)WID_ABORT_RUNNING_SCAN; - wid.type = WID_CHAR; - wid.val = (s8 *)&abort_running_scan; - 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 set abort running\n"); - result = -EFAULT; - } - } - - if (!hif_drv) { - netdev_err(vif->ndev, "Driver handler is NULL\n"); - return result; - } - - scan_req = &hif_drv->usr_scan_req; - if (scan_req->scan_result) { - scan_req->scan_result(evt, NULL, scan_req->arg, NULL); - scan_req->scan_result = NULL; - } - - return result; + kfree(msg); } u8 wilc_connected_ssid[6] = {0}; -static s32 handle_connect(struct wilc_vif *vif, - struct connect_attr *conn_attr) +static void handle_connect(struct work_struct *work) { - s32 result = 0; + 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; + } + if (memcmp(conn_attr->bssid, wilc_connected_ssid, ETH_ALEN) == 0) { - result = 0; netdev_err(vif->ndev, "Discard connect request\n"); - return result; + goto error; } bss_param = conn_attr->params; @@ -971,19 +980,19 @@ static s32 handle_connect(struct wilc_vif *vif, wid_list[wid_cnt].size = hif_drv->usr_conn_req.ies_len; wid_cnt++; - wid_list[wid_cnt].id = (u16)WID_11I_MODE; + 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_cnt++; - wid_list[wid_cnt].id = (u16)WID_AUTH_TYPE; + 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_cnt++; - wid_list[wid_cnt].id = (u16)WID_JOIN_REQ_EXTENDED; + wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED; wid_list[wid_cnt].type = WID_STR; wid_list[wid_cnt].size = 112; wid_list[wid_cnt].val = kmalloc(wid_list[wid_cnt].size, GFP_KERNEL); @@ -1138,20 +1147,22 @@ error: conn_attr->ies = NULL; kfree(cur_byte); - return result; + kfree(msg); } -static s32 handle_connect_timeout(struct wilc_vif *vif) +static void handle_connect_timeout(struct work_struct *work) { - s32 result = 0; + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); + struct wilc_vif *vif = msg->vif; + int result; struct connect_info info; struct wid wid; u16 dummy_reason_code = 0; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { - netdev_err(vif->ndev, "Driver handler is NULL\n"); - return result; + netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__); + goto out; } hif_drv->hif_state = HOST_IF_IDLE; @@ -1170,7 +1181,7 @@ static s32 handle_connect_timeout(struct wilc_vif *vif) hif_drv->usr_conn_req.ies_len, GFP_KERNEL); if (!info.req_ies) - return -ENOMEM; + goto out; } hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_CONN_RESP, @@ -1182,10 +1193,10 @@ static s32 handle_connect_timeout(struct wilc_vif *vif) kfree(info.req_ies); info.req_ies = NULL; } else { - netdev_err(vif->ndev, "Connect callback is NULL\n"); + netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } - wid.id = (u16)WID_DISCONNECT; + wid.id = WID_DISCONNECT; wid.type = WID_CHAR; wid.val = (s8 *)&dummy_reason_code; wid.size = sizeof(char); @@ -1206,17 +1217,185 @@ static s32 handle_connect_timeout(struct wilc_vif *vif) eth_zero_addr(wilc_connected_ssid); - return result; +out: + kfree(msg); } -static s32 handle_rcvd_ntwrk_info(struct wilc_vif *vif, - struct rcvd_net_info *rcvd_info) +static void host_int_fill_join_bss_param(struct join_bss_param *param, u8 *ies, + u16 *out_index, u8 *pcipher_tc, + u8 *auth_total_cnt, u32 tsf_lo, + u8 *rates_no) { + u8 ext_rates_no; + u16 offset; + u8 pcipher_cnt; + u8 auth_cnt; + u8 i, j; + u16 index = *out_index; + + if (ies[index] == WLAN_EID_SUPP_RATES) { + *rates_no = ies[index + 1]; + param->supp_rates[0] = *rates_no; + index += 2; + + for (i = 0; i < *rates_no; i++) + param->supp_rates[i + 1] = ies[index + i]; + + index += *rates_no; + } else if (ies[index] == WLAN_EID_EXT_SUPP_RATES) { + ext_rates_no = ies[index + 1]; + if (ext_rates_no > (MAX_RATES_SUPPORTED - *rates_no)) + param->supp_rates[0] = MAX_RATES_SUPPORTED; + else + param->supp_rates[0] += ext_rates_no; + index += 2; + for (i = 0; i < (param->supp_rates[0] - *rates_no); i++) + param->supp_rates[*rates_no + i + 1] = ies[index + i]; + + index += ext_rates_no; + } else if (ies[index] == WLAN_EID_HT_CAPABILITY) { + param->ht_capable = true; + index += ies[index + 1] + 2; + } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) && + (ies[index + 2] == 0x00) && (ies[index + 3] == 0x50) && + (ies[index + 4] == 0xF2) && (ies[index + 5] == 0x02) && + ((ies[index + 6] == 0x00) || (ies[index + 6] == 0x01)) && + (ies[index + 7] == 0x01)) { + param->wmm_cap = true; + + if (ies[index + 8] & BIT(7)) + param->uapsd_cap = true; + index += ies[index + 1] + 2; + } else if ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) && + (ies[index + 2] == 0x50) && (ies[index + 3] == 0x6f) && + (ies[index + 4] == 0x9a) && + (ies[index + 5] == 0x09) && (ies[index + 6] == 0x0c)) { + u16 p2p_cnt; + + param->tsf = tsf_lo; + param->noa_enabled = 1; + param->idx = ies[index + 9]; + + if (ies[index + 10] & BIT(7)) { + param->opp_enabled = 1; + param->ct_window = ies[index + 10]; + } else { + param->opp_enabled = 0; + } + + param->cnt = ies[index + 11]; + p2p_cnt = index + 12; + + memcpy(param->duration, ies + p2p_cnt, 4); + p2p_cnt += 4; + + memcpy(param->interval, ies + p2p_cnt, 4); + p2p_cnt += 4; + + memcpy(param->start_time, ies + p2p_cnt, 4); + + index += ies[index + 1] + 2; + } else if ((ies[index] == WLAN_EID_RSN) || + ((ies[index] == WLAN_EID_VENDOR_SPECIFIC) && + (ies[index + 2] == 0x00) && + (ies[index + 3] == 0x50) && (ies[index + 4] == 0xF2) && + (ies[index + 5] == 0x01))) { + u16 rsn_idx = index; + + if (ies[rsn_idx] == WLAN_EID_RSN) { + param->mode_802_11i = 2; + } else { + if (param->mode_802_11i == 0) + param->mode_802_11i = 1; + rsn_idx += 4; + } + + rsn_idx += 7; + param->rsn_grp_policy = ies[rsn_idx]; + rsn_idx++; + offset = ies[rsn_idx] * 4; + pcipher_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx]; + rsn_idx += 2; + + i = *pcipher_tc; + j = 0; + for (; i < (pcipher_cnt + *pcipher_tc) && i < 3; i++, j++) { + u8 *policy = ¶m->rsn_pcip_policy[i]; + + *policy = ies[rsn_idx + ((j + 1) * 4) - 1]; + } + + *pcipher_tc += pcipher_cnt; + rsn_idx += offset; + + offset = ies[rsn_idx] * 4; + + auth_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx]; + rsn_idx += 2; + i = *auth_total_cnt; + j = 0; + for (; i < (*auth_total_cnt + auth_cnt); i++, j++) { + u8 *policy = ¶m->rsn_auth_policy[i]; + + *policy = ies[rsn_idx + ((j + 1) * 4) - 1]; + } + + *auth_total_cnt += auth_cnt; + rsn_idx += offset; + + if (ies[index] == WLAN_EID_RSN) { + param->rsn_cap[0] = ies[rsn_idx]; + param->rsn_cap[1] = ies[rsn_idx + 1]; + rsn_idx += 2; + } + param->rsn_found = true; + index += ies[index + 1] + 2; + } else { + index += ies[index + 1] + 2; + } + + *out_index = index; +} + +static void *host_int_parse_join_bss_param(struct network_info *info) +{ + struct join_bss_param *param; + u16 index = 0; + u8 rates_no = 0; + u8 pcipher_total_cnt = 0; + u8 auth_total_cnt = 0; + + param = kzalloc(sizeof(*param), GFP_KERNEL); + if (!param) + return NULL; + + param->dtim_period = info->dtim_period; + param->beacon_period = info->beacon_period; + param->cap_info = info->cap_info; + memcpy(param->bssid, info->bssid, 6); + memcpy((u8 *)param->ssid, info->ssid, info->ssid_len + 1); + param->ssid_len = info->ssid_len; + memset(param->rsn_pcip_policy, 0xFF, 3); + memset(param->rsn_auth_policy, 0xFF, 3); + + while (index < info->ies_len) + host_int_fill_join_bss_param(param, info->ies, &index, + &pcipher_total_cnt, + &auth_total_cnt, info->tsf_lo, + &rates_no); + + return (void *)param; +} + +static void handle_rcvd_ntwrk_info(struct work_struct *work) +{ + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); + struct wilc_vif *vif = msg->vif; + struct rcvd_net_info *rcvd_info = &msg->body.net_info; u32 i; bool found; - s32 result = 0; struct network_info *info = NULL; - void *params = NULL; + void *params; struct host_if_drv *hif_drv = vif->hif_drv; struct user_scan_req *scan_req = &hif_drv->usr_scan_req; @@ -1227,12 +1406,12 @@ static s32 handle_rcvd_ntwrk_info(struct wilc_vif *vif, wilc_parse_network_info(rcvd_info->buffer, &info); if (!info || !scan_req->scan_result) { - netdev_err(vif->ndev, "driver is null\n"); - result = -EINVAL; + netdev_err(vif->ndev, "%s: info or scan result NULL\n", + __func__); goto done; } - for (i = 0; i < scan_req->rcvd_ch_cnt; i++) { + for (i = 0; i < scan_req->ch_cnt; i++) { if (memcmp(scan_req->net_info[i].bssid, info->bssid, 6) == 0) { if (info->rssi <= scan_req->net_info[i].rssi) { goto done; @@ -1245,13 +1424,13 @@ static s32 handle_rcvd_ntwrk_info(struct wilc_vif *vif, } if (found) { - if (scan_req->rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) { - scan_req->net_info[scan_req->rcvd_ch_cnt].rssi = info->rssi; + if (scan_req->ch_cnt < MAX_NUM_SCANNED_NETWORKS) { + scan_req->net_info[scan_req->ch_cnt].rssi = info->rssi; - memcpy(scan_req->net_info[scan_req->rcvd_ch_cnt].bssid, + memcpy(scan_req->net_info[scan_req->ch_cnt].bssid, info->bssid, 6); - scan_req->rcvd_ch_cnt++; + scan_req->ch_cnt++; info->new_network = true; params = host_int_parse_join_bss_param(info); @@ -1274,13 +1453,33 @@ done: kfree(info); } - return result; + 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); + u32 *rcvd_assoc_resp_info_len) +{ + int result; + struct wid wid; + + wid.id = WID_ASSOC_RES_INFO; + wid.type = WID_STR; + wid.val = assoc_resp_info; + wid.size = max_assoc_resp_info_len; + + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (result) { + *rcvd_assoc_resp_info_len = 0; + netdev_err(vif->ndev, "Failed to send association response\n"); + return -EINVAL; + } + + *rcvd_assoc_resp_info_len = wid.size; + return result; +} static inline void host_int_free_user_conn_req(struct host_if_drv *hif_drv) { @@ -1325,9 +1524,9 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, } if (mac_status == MAC_STATUS_CONNECTED && - conn_info.status != SUCCESSFUL_STATUSCODE) { + conn_info.status != WLAN_STATUS_SUCCESS) { netdev_err(vif->ndev, - "Received MAC status is MAC_STATUS_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE\n"); + "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"); @@ -1338,7 +1537,7 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, memcpy(conn_info.bssid, hif_drv->usr_conn_req.bssid, 6); if (mac_status == MAC_STATUS_CONNECTED && - conn_info.status == SUCCESSFUL_STATUSCODE) { + conn_info.status == WLAN_STATUS_SUCCESS) { memcpy(hif_drv->assoc_bssid, hif_drv->usr_conn_req.bssid, ETH_ALEN); } @@ -1358,7 +1557,7 @@ static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif, hif_drv->usr_conn_req.arg); if (mac_status == MAC_STATUS_CONNECTED && - conn_info.status == SUCCESSFUL_STATUSCODE) { + conn_info.status == WLAN_STATUS_SUCCESS) { wilc_set_power_mgmt(vif, 0, 0); hif_drv->hif_state = HOST_IF_CONNECTED; @@ -1402,7 +1601,7 @@ static inline void host_int_handle_disconnect(struct wilc_vif *vif) conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, 0, &disconn_info, hif_drv->usr_conn_req.arg); } else { - netdev_err(vif->ndev, "Connect result NULL\n"); + netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } eth_zero_addr(hif_drv->assoc_bssid); @@ -1411,43 +1610,39 @@ static inline void host_int_handle_disconnect(struct wilc_vif *vif) hif_drv->hif_state = HOST_IF_IDLE; } -static s32 handle_rcvd_gnrl_async_info(struct wilc_vif *vif, - struct rcvd_async_info *rcvd_info) +static void handle_rcvd_gnrl_async_info(struct work_struct *work) { - s32 result = 0; - u8 msg_type = 0; + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); + struct wilc_vif *vif = msg->vif; + struct rcvd_async_info *rcvd_info = &msg->body.async_info; + u8 msg_type; u8 mac_status; struct host_if_drv *hif_drv = vif->hif_drv; if (!rcvd_info->buffer) { - netdev_err(vif->ndev, "Received buffer is NULL\n"); - return -EINVAL; + netdev_err(vif->ndev, "%s: buffer is NULL\n", __func__); + goto free_msg; } if (!hif_drv) { - netdev_err(vif->ndev, "Driver handler is NULL\n"); - kfree(rcvd_info->buffer); - rcvd_info->buffer = NULL; - return -ENODEV; + netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__); + goto free_rcvd_info; } if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP || hif_drv->hif_state == HOST_IF_CONNECTED || hif_drv->usr_scan_req.scan_result) { if (!hif_drv->usr_conn_req.conn_result) { - netdev_err(vif->ndev, "driver is null\n"); - kfree(rcvd_info->buffer); - rcvd_info->buffer = NULL; - return -EINVAL; + netdev_err(vif->ndev, "%s: conn_result is NULL\n", + __func__); + goto free_rcvd_info; } msg_type = rcvd_info->buffer[0]; if ('I' != msg_type) { netdev_err(vif->ndev, "Received Message incorrect.\n"); - kfree(rcvd_info->buffer); - rcvd_info->buffer = NULL; - return -EFAULT; + goto free_rcvd_info; } mac_status = rcvd_info->buffer[7]; @@ -1464,10 +1659,12 @@ static s32 handle_rcvd_gnrl_async_info(struct wilc_vif *vif, } } +free_rcvd_info: kfree(rcvd_info->buffer); rcvd_info->buffer = NULL; - return result; +free_msg: + kfree(msg); } static int wilc_pmksa_key_copy(struct wilc_vif *vif, struct key_attr *hif_key) @@ -1491,7 +1688,7 @@ static int wilc_pmksa_key_copy(struct wilc_vif *vif, struct key_attr *hif_key) hif_key->attr.pmkid.pmkidlist[i].pmkid, PMKID_LEN); } - wid.id = (u16)WID_PMKID_INFO; + 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; @@ -1504,8 +1701,11 @@ static int wilc_pmksa_key_copy(struct wilc_vif *vif, struct key_attr *hif_key) return ret; } -static int handle_key(struct wilc_vif *vif, struct key_attr *hif_key) +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]; @@ -1516,7 +1716,7 @@ static int handle_key(struct wilc_vif *vif, struct key_attr *hif_key) case WEP: if (hif_key->action & ADDKEY_AP) { - wid_list[0].id = (u16)WID_11I_MODE; + 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; @@ -1539,9 +1739,7 @@ static int handle_key(struct wilc_vif *vif, struct key_attr *hif_key) memcpy(&key_buf[2], hif_key->attr.wep.key, hif_key->attr.wep.key_len); - kfree(hif_key->attr.wep.key); - - wid_list[2].id = (u16)WID_WEP_KEY_VALUE; + 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; @@ -1561,9 +1759,8 @@ static int handle_key(struct wilc_vif *vif, struct key_attr *hif_key) 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); - kfree(hif_key->attr.wep.key); - wid.id = (u16)WID_ADD_WEP_KEY; + wid.id = WID_ADD_WEP_KEY; wid.type = WID_STR; wid.val = (s8 *)key_buf; wid.size = hif_key->attr.wep.key_len + 2; @@ -1573,7 +1770,7 @@ static int handle_key(struct wilc_vif *vif, struct key_attr *hif_key) wilc_get_vif_idx(vif)); kfree(key_buf); } else if (hif_key->action & REMOVEKEY) { - wid.id = (u16)WID_REMOVE_WEP_KEY; + wid.id = WID_REMOVE_WEP_KEY; wid.type = WID_STR; wid.val = (s8 *)&hif_key->attr.wep.index; @@ -1583,7 +1780,7 @@ static int handle_key(struct wilc_vif *vif, struct key_attr *hif_key) &wid, 1, wilc_get_vif_idx(vif)); } else if (hif_key->action & DEFAULTKEY) { - wid.id = (u16)WID_KEY_ID; + wid.id = WID_KEY_ID; wid.type = WID_CHAR; wid.val = (s8 *)&hif_key->attr.wep.index; wid.size = sizeof(char); @@ -1593,7 +1790,7 @@ static int handle_key(struct wilc_vif *vif, struct key_attr *hif_key) wilc_get_vif_idx(vif)); } out_wep: - complete(&hif_drv->comp_test_key_block); + complete(&msg->work_comp); break; case WPA_RX_GTK: @@ -1612,12 +1809,12 @@ out_wep: memcpy(key_buf + 16, hif_key->attr.wpa.key, hif_key->attr.wpa.key_len); - wid_list[0].id = (u16)WID_11I_MODE; + 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 = (u16)WID_ADD_RX_GTK; + 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; @@ -1645,7 +1842,7 @@ out_wep: memcpy(key_buf + 16, hif_key->attr.wpa.key, hif_key->attr.wpa.key_len); - wid.id = (u16)WID_ADD_RX_GTK; + wid.id = WID_ADD_RX_GTK; wid.type = WID_STR; wid.val = (s8 *)key_buf; wid.size = RX_MIC_KEY_MSG_LEN; @@ -1657,9 +1854,7 @@ out_wep: kfree(key_buf); } out_wpa_rx_gtk: - complete(&hif_drv->comp_test_key_block); - kfree(hif_key->attr.wpa.key); - kfree(hif_key->attr.wpa.seq); + complete(&msg->work_comp); break; case WPA_PTK: @@ -1676,12 +1871,12 @@ out_wpa_rx_gtk: memcpy(key_buf + 8, hif_key->attr.wpa.key, hif_key->attr.wpa.key_len); - wid_list[0].id = (u16)WID_11I_MODE; + 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 = (u16)WID_ADD_PTK; + 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; @@ -1702,7 +1897,7 @@ out_wpa_rx_gtk: memcpy(key_buf + 7, hif_key->attr.wpa.key, hif_key->attr.wpa.key_len); - wid.id = (u16)WID_ADD_PTK; + wid.id = WID_ADD_PTK; wid.type = WID_STR; wid.val = (s8 *)key_buf; wid.size = PTK_KEY_MSG_LEN; @@ -1714,32 +1909,35 @@ out_wpa_rx_gtk: } out_wpa_ptk: - complete(&hif_drv->comp_test_key_block); - kfree(hif_key->attr.wpa.key); + 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"); - return result; + /* free 'msg' data in caller sync call */ } -static void handle_disconnect(struct wilc_vif *vif) +static void handle_disconnect(struct work_struct *work) { + 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; struct user_scan_req *scan_req; struct user_conn_req *conn_req; - s32 result = 0; + int result; u16 dummy_reason_code = 0; - wid.id = (u16)WID_DISCONNECT; + wid.id = WID_DISCONNECT; wid.type = WID_CHAR; wid.val = (s8 *)&dummy_reason_code; wid.size = sizeof(char); @@ -1779,7 +1977,7 @@ static void handle_disconnect(struct wilc_vif *vif) conn_req->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, 0, &disconn_info, conn_req->arg); } else { - netdev_err(vif->ndev, "conn_result = NULL\n"); + netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); } hif_drv->hif_state = HOST_IF_IDLE; @@ -1797,7 +1995,8 @@ static void handle_disconnect(struct wilc_vif *vif) out: - complete(&hif_drv->comp_test_disconn_block); + complete(&msg->work_comp); + /* free 'msg' in caller after receiving completion */ } void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) @@ -1809,31 +2008,34 @@ void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) wilc_disconnect(vif, 1); } -static void handle_get_rssi(struct wilc_vif *vif) +static void handle_get_rssi(struct work_struct *work) { - s32 result = 0; + 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 = (u16)WID_RSSI; + wid.id = WID_RSSI; wid.type = WID_CHAR; - wid.val = &rssi; + 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) { + if (result) netdev_err(vif->ndev, "Failed to get RSSI value\n"); - result = -EFAULT; - } - complete(&vif->hif_drv->comp_get_rssi); + complete(&msg->work_comp); + /* free 'msg' data in caller */ } -static s32 handle_get_statistics(struct wilc_vif *vif, - struct rf_info *stats) +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 wid wid_list[5]; - u32 wid_cnt = 0, result = 0; + 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; @@ -1878,24 +2080,27 @@ static s32 handle_get_statistics(struct wilc_vif *vif, else if (stats->link_speed != DEFAULT_LINK_SPEED) wilc_enable_tcp_ack_filter(false); - if (stats != &vif->wilc->dummy_statistics) - complete(&hif_wait_response); - return 0; + /* free 'msg' for async command, for sync caller will free it */ + if (msg->is_sync) + complete(&msg->work_comp); + else + kfree(msg); } -static s32 handle_get_inactive_time(struct wilc_vif *vif, - struct sta_inactive_t *hif_sta_inactive) +static void handle_get_inactive_time(struct work_struct *work) { - s32 result = 0; + 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; - struct host_if_drv *hif_drv = vif->hif_drv; - wid.id = (u16)WID_SET_STA_MAC_INACTIVE_TIME; + 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) - return -ENOMEM; + goto out; ether_addr_copy(wid.val, hif_sta_inactive->mac); @@ -1904,35 +2109,36 @@ static s32 handle_get_inactive_time(struct wilc_vif *vif, kfree(wid.val); if (result) { - netdev_err(vif->ndev, "Failed to SET inactive time\n"); - return -EFAULT; + netdev_err(vif->ndev, "Failed to set inactive mac\n"); + goto out; } - wid.id = (u16)WID_GET_INACTIVE_TIME; + wid.id = WID_GET_INACTIVE_TIME; wid.type = WID_INT; - wid.val = (s8 *)&inactive_time; + 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) { + if (result) netdev_err(vif->ndev, "Failed to get inactive time\n"); - return -EFAULT; - } - - complete(&hif_drv->comp_inactive_time); - return result; +out: + /* free 'msg' data in caller */ + complete(&msg->work_comp); } -static void handle_add_beacon(struct wilc_vif *vif, struct beacon_attr *param) +static void handle_add_beacon(struct work_struct *work) { - s32 result = 0; + 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 = (u16)WID_ADD_BEACON; + 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); @@ -1976,15 +2182,18 @@ error: kfree(wid.val); kfree(param->head); kfree(param->tail); + kfree(msg); } -static void handle_del_beacon(struct wilc_vif *vif) +static void handle_del_beacon(struct work_struct *work) { - s32 result = 0; + 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 = (u16)WID_DEL_BEACON; + wid.id = WID_DEL_BEACON; wid.type = WID_CHAR; wid.size = sizeof(char); wid.val = &del_beacon; @@ -1993,6 +2202,7 @@ static void handle_del_beacon(struct wilc_vif *vif) 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) @@ -2025,14 +2235,16 @@ static u32 wilc_hif_pack_sta_param(u8 *buff, struct add_sta_param *param) return cur_byte - buff; } -static void handle_add_station(struct wilc_vif *vif, - struct add_sta_param *param) +static void handle_add_station(struct work_struct *work) { - s32 result = 0; + 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 = (u16)WID_ADD_STA; + wid.id = WID_ADD_STA; wid.type = WID_BIN; wid.size = WILC_ADD_STA_LENGTH + param->rates_len; @@ -2051,18 +2263,21 @@ static void handle_add_station(struct wilc_vif *vif, error: kfree(param->rates); kfree(wid.val); + kfree(msg); } -static void handle_del_all_sta(struct wilc_vif *vif, - struct del_all_sta *param) +static void handle_del_all_sta(struct work_struct *work) { - s32 result = 0; + 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}; - wid.id = (u16)WID_DEL_ALL_STA; + wid.id = WID_DEL_ALL_STA; wid.type = WID_STR; wid.size = (param->assoc_sta * ETH_ALEN) + 1; @@ -2086,20 +2301,24 @@ static void handle_del_all_sta(struct wilc_vif *vif, 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 station\n"); + netdev_err(vif->ndev, "Failed to send delete all station\n"); error: kfree(wid.val); - complete(&hif_wait_response); + /* free 'msg' data in caller */ + complete(&msg->work_comp); } -static void handle_del_station(struct wilc_vif *vif, struct del_sta *param) +static void handle_del_station(struct work_struct *work) { - s32 result = 0; + 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 = (u16)WID_REMOVE_STA; + wid.id = WID_REMOVE_STA; wid.type = WID_BIN; wid.size = ETH_ALEN; @@ -2112,20 +2331,23 @@ static void handle_del_station(struct wilc_vif *vif, struct del_sta *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 add station\n"); + netdev_err(vif->ndev, "Failed to del station\n"); error: kfree(wid.val); + kfree(msg); } -static void handle_edit_station(struct wilc_vif *vif, - struct add_sta_param *param) +static void handle_edit_station(struct work_struct *work) { - s32 result = 0; + 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 = (u16)WID_EDIT_STA; + wid.id = WID_EDIT_STA; wid.type = WID_BIN; wid.size = WILC_ADD_STA_LENGTH + param->rates_len; @@ -2144,12 +2366,13 @@ static void handle_edit_station(struct wilc_vif *vif, error: kfree(param->rates); kfree(wid.val); + kfree(msg); } static int handle_remain_on_chan(struct wilc_vif *vif, struct remain_ch *hif_remain_ch) { - s32 result = 0; + int result; u8 remain_on_chan_flag; struct wid wid; struct host_if_drv *hif_drv = vif->hif_drv; @@ -2180,7 +2403,7 @@ static int handle_remain_on_chan(struct wilc_vif *vif, } remain_on_chan_flag = true; - wid.id = (u16)WID_REMAIN_ON_CHAN; + wid.id = WID_REMAIN_ON_CHAN; wid.type = WID_STR; wid.size = 2; wid.val = kmalloc(wid.size, GFP_KERNEL); @@ -2213,18 +2436,20 @@ error: return result; } -static int handle_register_frame(struct wilc_vif *vif, - struct reg_frame *hif_reg_frame) +static void handle_register_frame(struct work_struct *work) { - s32 result = 0; + 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 = (u16)WID_REGISTER_FRAME; + wid.id = WID_REGISTER_FRAME; wid.type = WID_STR; wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL); if (!wid.val) - return -ENOMEM; + goto out; cur_byte = wid.val; @@ -2237,31 +2462,32 @@ static int handle_register_frame(struct wilc_vif *vif, result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(wid.val); - if (result) { + if (result) netdev_err(vif->ndev, "Failed to frame register\n"); - result = -EINVAL; - } - return result; +out: + kfree(msg); } -static u32 handle_listen_state_expired(struct wilc_vif *vif, - struct remain_ch *hif_remain_ch) +static void handle_listen_state_expired(struct work_struct *work) { + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); + struct wilc_vif *vif = msg->vif; + struct remain_ch *hif_remain_ch = &msg->body.remain_on_ch; u8 remain_on_chan_flag; struct wid wid; - s32 result = 0; + int result; struct host_if_drv *hif_drv = vif->hif_drv; if (p2p_listen_state) { remain_on_chan_flag = false; - wid.id = (u16)WID_REMAIN_ON_CHAN; + wid.id = WID_REMAIN_ON_CHAN; wid.type = WID_STR; wid.size = 2; wid.val = kmalloc(wid.size, GFP_KERNEL); if (!wid.val) - return -ENOMEM; + goto free_msg; wid.val[0] = remain_on_chan_flag; wid.val[1] = FALSE_FRMWR_CHANNEL; @@ -2271,7 +2497,7 @@ static u32 handle_listen_state_expired(struct wilc_vif *vif, kfree(wid.val); if (result != 0) { netdev_err(vif->ndev, "Failed to set remain channel\n"); - return result; + goto free_msg; } if (hif_drv->remain_on_ch.expired) { @@ -2281,10 +2507,10 @@ static u32 handle_listen_state_expired(struct wilc_vif *vif, p2p_listen_state = 0; } else { netdev_dbg(vif->ndev, "Not in listen state\n"); - result = -EFAULT; } - return result; +free_msg: + kfree(msg); } static void listen_timer_cb(struct timer_list *t) @@ -2292,29 +2518,34 @@ static void listen_timer_cb(struct timer_list *t) struct host_if_drv *hif_drv = from_timer(hif_drv, t, remain_on_ch_timer); struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif; - s32 result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; del_timer(&vif->hif_drv->remain_on_ch_timer); - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED; - msg.vif = vif; - msg.body.remain_on_ch.id = vif->hif_drv->remain_on_ch.id; + msg = wilc_alloc_work(vif, handle_listen_state_expired, false); + if (IS_ERR(msg)) + return; + + msg->body.remain_on_ch.id = vif->hif_drv->remain_on_ch.id; - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + result = wilc_enqueue_work(msg); + if (result) { + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); + } } -static void handle_power_management(struct wilc_vif *vif, - struct power_mgmt_param *pm_param) +static void handle_power_management(struct work_struct *work) { - s32 result = 0; + 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 = (u16)WID_POWER_MANAGEMENT; + wid.id = WID_POWER_MANAGEMENT; if (pm_param->enabled) power_mode = MIN_FAST_PS; @@ -2328,16 +2559,19 @@ static void handle_power_management(struct wilc_vif *vif, 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 wilc_vif *vif, - struct set_multicast *hif_set_mc) +static void handle_set_mcast_filter(struct work_struct *work) { - s32 result = 0; + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); + struct wilc_vif *vif = msg->vif; + struct set_multicast *hif_set_mc = &msg->body.multicast_info; + int result; struct wid wid; u8 *cur_byte; - wid.id = (u16)WID_SETUP_MULTICAST_FILTER; + wid.id = WID_SETUP_MULTICAST_FILTER; wid.type = WID_BIN; wid.size = sizeof(struct set_multicast) + (hif_set_mc->cnt * ETH_ALEN); wid.val = kmalloc(wid.size, GFP_KERNEL); @@ -2366,14 +2600,18 @@ static void handle_set_mcast_filter(struct wilc_vif *vif, error: kfree(wid.val); + kfree(msg); } -static void handle_set_tx_pwr(struct wilc_vif *vif, u8 tx_pwr) +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 = (u16)WID_TX_POWER; + wid.id = WID_TX_POWER; wid.type = WID_CHAR; wid.val = &tx_pwr; wid.size = sizeof(char); @@ -2382,14 +2620,19 @@ static void handle_set_tx_pwr(struct wilc_vif *vif, u8 tx_pwr) wilc_get_vif_idx(vif)); if (ret) netdev_err(vif->ndev, "Failed to set TX PWR\n"); + kfree(msg); } -static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr) +/* Note: 'msg' will be free after using data */ +static void handle_get_tx_pwr(struct work_struct *work) { - int ret = 0; + 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 = (u16)WID_TX_POWER; + wid.id = WID_TX_POWER; wid.type = WID_CHAR; wid.val = (s8 *)tx_pwr; wid.size = sizeof(char); @@ -2399,190 +2642,64 @@ static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr) if (ret) netdev_err(vif->ndev, "Failed to get TX PWR\n"); - complete(&hif_wait_response); + complete(&msg->work_comp); } -static void host_if_work(struct work_struct *work) +static void handle_scan_timer(struct work_struct *work) { - struct host_if_msg *msg; - struct wilc *wilc; - int ret = 0; + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - msg = container_of(work, struct host_if_msg, work); - wilc = msg->vif->wilc; - - if (msg->id == HOST_IF_MSG_CONNECT && - msg->vif->hif_drv->usr_scan_req.scan_result) { - wilc_enqueue_cmd(msg); - usleep_range(2 * 1000, 2 * 1000); - goto free_msg; - } - switch (msg->id) { - case HOST_IF_MSG_SCAN: - handle_scan(msg->vif, &msg->body.scan_info); - break; - - case HOST_IF_MSG_CONNECT: - handle_connect(msg->vif, &msg->body.con_info); - break; - - case HOST_IF_MSG_RCVD_NTWRK_INFO: - handle_rcvd_ntwrk_info(msg->vif, &msg->body.net_info); - break; - - case HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO: - handle_rcvd_gnrl_async_info(msg->vif, - &msg->body.async_info); - break; - - case HOST_IF_MSG_KEY: - handle_key(msg->vif, &msg->body.key_info); - break; - - case HOST_IF_MSG_CFG_PARAMS: - handle_cfg_param(msg->vif, &msg->body.cfg_info); - break; - - case HOST_IF_MSG_SET_CHANNEL: - handle_set_channel(msg->vif, &msg->body.channel_info); - break; - - case HOST_IF_MSG_DISCONNECT: - handle_disconnect(msg->vif); - break; - - case HOST_IF_MSG_RCVD_SCAN_COMPLETE: - del_timer(&msg->vif->hif_drv->scan_timer); - - if (!wilc_wlan_get_num_conn_ifcs(wilc)) - wilc_chip_sleep_manually(wilc); - - 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); - - break; - - case HOST_IF_MSG_GET_RSSI: - handle_get_rssi(msg->vif); - break; - - case HOST_IF_MSG_GET_STATISTICS: - handle_get_statistics(msg->vif, - (struct rf_info *)msg->body.data); - break; - - case HOST_IF_MSG_ADD_BEACON: - handle_add_beacon(msg->vif, &msg->body.beacon_info); - break; - - case HOST_IF_MSG_DEL_BEACON: - handle_del_beacon(msg->vif); - break; - - case HOST_IF_MSG_ADD_STATION: - handle_add_station(msg->vif, &msg->body.add_sta_info); - break; - - case HOST_IF_MSG_DEL_STATION: - handle_del_station(msg->vif, &msg->body.del_sta_info); - break; - - case HOST_IF_MSG_EDIT_STATION: - handle_edit_station(msg->vif, &msg->body.edit_sta_info); - break; - - case HOST_IF_MSG_GET_INACTIVETIME: - handle_get_inactive_time(msg->vif, &msg->body.mac_info); - break; + handle_scan_done(msg->vif, SCAN_EVENT_ABORTED); + kfree(msg); +} - case HOST_IF_MSG_SCAN_TIMER_FIRED: - handle_scan_done(msg->vif, SCAN_EVENT_ABORTED); - break; +static void handle_remain_on_chan_work(struct work_struct *work) +{ + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - case HOST_IF_MSG_CONNECT_TIMER_FIRED: - handle_connect_timeout(msg->vif); - break; + handle_remain_on_chan(msg->vif, &msg->body.remain_on_ch); + kfree(msg); +} - case HOST_IF_MSG_POWER_MGMT: - handle_power_management(msg->vif, - &msg->body.pwr_mgmt_info); - break; +static void handle_hif_exit_work(struct work_struct *work) +{ + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); - case HOST_IF_MSG_SET_WFIDRV_HANDLER: - ret = handle_set_wfi_drv_handler(msg->vif, &msg->body.drv); - break; + /* free 'msg' data in caller */ + complete(&msg->work_comp); +} - case HOST_IF_MSG_SET_OPERATION_MODE: - handle_set_operation_mode(msg->vif, &msg->body.mode); - break; +static void handle_scan_complete(struct work_struct *work) +{ + struct host_if_msg *msg = container_of(work, struct host_if_msg, work); + struct wilc *wilc = msg->vif->wilc; - case HOST_IF_MSG_SET_IPADDRESS: - handle_set_ip_address(msg->vif, - msg->body.ip_info.ip_addr, - msg->body.ip_info.idx); - break; + del_timer(&msg->vif->hif_drv->scan_timer); - case HOST_IF_MSG_GET_IPADDRESS: - handle_get_ip_address(msg->vif, msg->body.ip_info.idx); - break; + if (!wilc_wlan_get_num_conn_ifcs(wilc)) + wilc_chip_sleep_manually(wilc); - case HOST_IF_MSG_GET_MAC_ADDRESS: - handle_get_mac_address(msg->vif, - &msg->body.get_mac_info); - break; + handle_scan_done(msg->vif, SCAN_EVENT_DONE); - case HOST_IF_MSG_REMAIN_ON_CHAN: + if (msg->vif->hif_drv->remain_on_ch_pending) handle_remain_on_chan(msg->vif, &msg->body.remain_on_ch); - break; - - case HOST_IF_MSG_REGISTER_FRAME: - handle_register_frame(msg->vif, &msg->body.reg_frame); - break; - - case HOST_IF_MSG_LISTEN_TIMER_FIRED: - handle_listen_state_expired(msg->vif, &msg->body.remain_on_ch); - break; - - case HOST_IF_MSG_SET_MULTICAST_FILTER: - handle_set_mcast_filter(msg->vif, &msg->body.multicast_info); - break; - - case HOST_IF_MSG_DEL_ALL_STA: - handle_del_all_sta(msg->vif, &msg->body.del_all_sta_info); - break; - - case HOST_IF_MSG_SET_TX_POWER: - handle_set_tx_pwr(msg->vif, msg->body.tx_power.tx_pwr); - break; - - case HOST_IF_MSG_GET_TX_POWER: - handle_get_tx_pwr(msg->vif, &msg->body.tx_power.tx_pwr); - break; - default: - netdev_err(msg->vif->ndev, "[Host Interface] undefined\n"); - break; - } -free_msg: - if (ret) - netdev_err(msg->vif->ndev, "Host cmd %d failed\n", msg->id); kfree(msg); - complete(&hif_thread_comp); } static void timer_scan_cb(struct timer_list *t) { struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer); struct wilc_vif *vif = hif_drv->scan_timer_vif; - struct host_if_msg msg; + struct host_if_msg *msg; + int result; - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.vif = vif; - msg.id = HOST_IF_MSG_SCAN_TIMER_FIRED; + msg = wilc_alloc_work(vif, handle_scan_timer, false); + if (IS_ERR(msg)) + return; - wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); + if (result) + kfree(msg); } static void timer_connect_cb(struct timer_list *t) @@ -2590,70 +2707,75 @@ static void timer_connect_cb(struct timer_list *t) struct host_if_drv *hif_drv = from_timer(hif_drv, t, connect_timer); struct wilc_vif *vif = hif_drv->connect_timer_vif; - struct host_if_msg msg; + struct host_if_msg *msg; + int result; - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.vif = vif; - msg.id = HOST_IF_MSG_CONNECT_TIMER_FIRED; + msg = wilc_alloc_work(vif, handle_connect_timeout, false); + if (IS_ERR(msg)) + return; - wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); + if (result) + kfree(msg); } int wilc_remove_wep_key(struct wilc_vif *vif, u8 index) { - int result = 0; - struct host_if_msg msg; + 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, "Failed to send setup multicast\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return result; } - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_key, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_KEY; - msg.body.key_info.type = WEP; - msg.body.key_info.action = REMOVEKEY; - msg.vif = vif; - msg.body.key_info.attr.wep.index = index; + msg->body.key_info.type = WEP; + msg->body.key_info.action = REMOVEKEY; + msg->body.key_info.attr.wep.index = index; - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) - netdev_err(vif->ndev, "Request to remove WEP key\n"); + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); else - wait_for_completion(&hif_drv->comp_test_key_block); + wait_for_completion(&msg->work_comp); + kfree(msg); return result; } int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index) { - int result = 0; - struct host_if_msg msg; + 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, "driver is null\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__); return result; } - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_key, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_KEY; - msg.body.key_info.type = WEP; - msg.body.key_info.action = DEFAULTKEY; - msg.vif = vif; - msg.body.key_info.attr.wep.index = index; + msg->body.key_info.type = WEP; + msg->body.key_info.action = DEFAULTKEY; + msg->body.key_info.attr.wep.index = index; - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) - netdev_err(vif->ndev, "Default key index\n"); + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); else - wait_for_completion(&hif_drv->comp_test_key_block); + wait_for_completion(&msg->work_comp); + kfree(msg); return result; } @@ -2661,74 +2783,84 @@ int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, u8 index) { int result; - struct host_if_msg msg; + struct host_if_msg *msg; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { - netdev_err(vif->ndev, "driver is null\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return -EFAULT; } - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_key, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_KEY; - msg.body.key_info.type = WEP; - msg.body.key_info.action = ADDKEY; - msg.vif = vif; - msg.body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL); - if (!msg.body.key_info.attr.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; + } - msg.body.key_info.attr.wep.key_len = len; - msg.body.key_info.attr.wep.index = index; + msg->body.key_info.attr.wep.key_len = len; + msg->body.key_info.attr.wep.index = index; - result = wilc_enqueue_cmd(&msg); - if (result) { - netdev_err(vif->ndev, "STA - WEP Key\n"); - kfree(msg.body.key_info.attr.wep.key); - return result; - } + result = wilc_enqueue_work(msg); + if (result) + goto free_key; - wait_for_completion(&hif_drv->comp_test_key_block); - return 0; + wait_for_completion(&msg->work_comp); + +free_key: + kfree(msg->body.key_info.attr.wep.key); + +free_msg: + kfree(msg); + 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) + u8 index, u8 mode, enum authtype auth_type) { int result; - struct host_if_msg msg; + struct host_if_msg *msg; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { - netdev_err(vif->ndev, "driver is null\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__); return -EFAULT; } - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_key, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_KEY; - msg.body.key_info.type = WEP; - msg.body.key_info.action = ADDKEY_AP; - msg.vif = vif; - msg.body.key_info.attr.wep.key = kmemdup(key, len, GFP_KERNEL); - if (!msg.body.key_info.attr.wep.key) - return -ENOMEM; + 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; + } - 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; + 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; - result = wilc_enqueue_cmd(&msg); - if (result) { - netdev_err(vif->ndev, "AP - WEP Key\n"); - kfree(msg.body.key_info.attr.wep.key); - return result; - } + result = wilc_enqueue_work(msg); + if (result) + goto free_key; - wait_for_completion(&hif_drv->comp_test_key_block); - return 0; + wait_for_completion(&msg->work_comp); + +free_key: + kfree(msg->body.key_info.attr.wep.key); + +free_msg: + kfree(msg); + return result; } int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, @@ -2736,12 +2868,12 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, u8 mode, u8 cipher_mode, u8 index) { int result; - struct host_if_msg msg; + 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, "driver is null\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return -EFAULT; } @@ -2751,43 +2883,50 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, if (tx_mic) key_len += TX_MIC_KEY_LEN; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_key, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_KEY; - msg.body.key_info.type = WPA_PTK; + 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; + 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; + msg->body.key_info.action = ADDKEY; - msg.body.key_info.attr.wpa.key = kmemdup(ptk, ptk_key_len, GFP_KERNEL); - if (!msg.body.key_info.attr.wpa.key) - return -ENOMEM; + 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; + } if (rx_mic) - memcpy(msg.body.key_info.attr.wpa.key + 16, rx_mic, + memcpy(msg->body.key_info.attr.wpa.key + 16, rx_mic, RX_MIC_KEY_LEN); if (tx_mic) - memcpy(msg.body.key_info.attr.wpa.key + 24, tx_mic, + memcpy(msg->body.key_info.attr.wpa.key + 24, tx_mic, TX_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; - msg.vif = vif; + 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; - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "PTK Key\n"); - kfree(msg.body.key_info.attr.wpa.key); - return result; + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + goto free_key; } - wait_for_completion(&hif_drv->comp_test_key_block); - return 0; + wait_for_completion(&msg->work_comp); + +free_key: + kfree(msg->body.key_info.attr.wpa.key); + +free_msg: + kfree(msg); + return result; } int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, @@ -2796,15 +2935,18 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 cipher_mode) { int result; - struct host_if_msg msg; + 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, "driver is null\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return -EFAULT; } - memset(&msg, 0, sizeof(struct host_if_msg)); + + 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; @@ -2813,258 +2955,263 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, 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) - return -ENOMEM; + 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; + } } - msg.id = HOST_IF_MSG_KEY; - msg.body.key_info.type = WPA_RX_GTK; - msg.vif = vif; + msg->body.key_info.type = WPA_RX_GTK; if (mode == AP_MODE) { - msg.body.key_info.action = ADDKEY_AP; - msg.body.key_info.attr.wpa.mode = cipher_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; + msg->body.key_info.action = ADDKEY; - msg.body.key_info.attr.wpa.key = kmemdup(rx_gtk, - key_len, - GFP_KERNEL); - if (!msg.body.key_info.attr.wpa.key) { - kfree(msg.body.key_info.attr.wpa.seq); - return -ENOMEM; + 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 (rx_mic) - memcpy(msg.body.key_info.attr.wpa.key + 16, rx_mic, + memcpy(msg->body.key_info.attr.wpa.key + 16, rx_mic, RX_MIC_KEY_LEN); if (tx_mic) - memcpy(msg.body.key_info.attr.wpa.key + 24, tx_mic, + memcpy(msg->body.key_info.attr.wpa.key + 24, 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; + 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; - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "RX GTK\n"); - kfree(msg.body.key_info.attr.wpa.seq); - kfree(msg.body.key_info.attr.wpa.key); - return result; + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + goto free_key; } - wait_for_completion(&hif_drv->comp_test_key_block); - return 0; + wait_for_completion(&msg->work_comp); + +free_key: + kfree(msg->body.key_info.attr.wpa.key); + +free_seq: + kfree(msg->body.key_info.attr.wpa.seq); + +free_msg: + kfree(msg); + return result; } int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid) { - int result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; int i; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_key, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_KEY; - msg.body.key_info.type = PMKSA; - msg.body.key_info.action = ADDKEY; - msg.vif = vif; + 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, + 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, + memcpy(msg->body.key_info.attr.pmkid.pmkidlist[i].pmkid, &pmkid->pmkidlist[i].pmkid, PMKID_LEN); } - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "PMKID Info\n"); + result = wilc_enqueue_work(msg); + if (result) { + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); + } return result; } int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) { - int result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_get_mac_address, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_GET_MAC_ADDRESS; - msg.body.get_mac_info.mac_addr = mac_addr; - msg.vif = vif; + msg->body.get_mac_info.mac_addr = mac_addr; - result = wilc_enqueue_cmd(&msg); - if (result) { - netdev_err(vif->ndev, "Failed to send get mac address\n"); - return -EFAULT; - } + 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(msg); - wait_for_completion(&hif_wait_response); return result; } int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 security, enum AUTHTYPE auth_type, + u8 security, enum authtype auth_type, u8 channel, void *join_params) { - int result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv || !connect_result) { - netdev_err(vif->ndev, "Driver is null\n"); + netdev_err(vif->ndev, + "%s: hif driver or connect result is NULL", + __func__); return -EFAULT; } if (!join_params) { - netdev_err(vif->ndev, "Unable to Join - JoinParams is NULL\n"); + netdev_err(vif->ndev, "%s: joinparams is NULL\n", __func__); return -EFAULT; } - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_connect, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_CONNECT; - - 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; - msg.vif = vif; + 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; if (bssid) { - msg.body.con_info.bssid = kmemdup(bssid, 6, GFP_KERNEL); - if (!msg.body.con_info.bssid) - return -ENOMEM; + msg->body.con_info.bssid = kmemdup(bssid, 6, GFP_KERNEL); + if (!msg->body.con_info.bssid) { + result = -ENOMEM; + goto free_msg; + } } 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) - return -ENOMEM; + 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) { + 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) - return -ENOMEM; + 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) { + result = -ENOMEM; + goto free_ssid; + } } if (hif_drv->hif_state < HOST_IF_CONNECTING) hif_drv->hif_state = HOST_IF_CONNECTING; - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "send message: Set join request\n"); - return -EFAULT; + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + goto free_ies; } hif_drv->connect_timer_vif = vif; mod_timer(&hif_drv->connect_timer, jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT)); + return 0; + +free_ies: + kfree(msg->body.con_info.ies); + +free_ssid: + kfree(msg->body.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 = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { - netdev_err(vif->ndev, "Driver is null\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return -EFAULT; } - memset(&msg, 0, sizeof(struct host_if_msg)); - - msg.id = HOST_IF_MSG_DISCONNECT; - msg.vif = vif; + msg = wilc_alloc_work(vif, handle_disconnect, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) - netdev_err(vif->ndev, "Failed to send message: disconnect\n"); + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); else - wait_for_completion(&hif_drv->comp_test_disconn_block); - - return result; -} - -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) -{ - s32 result = 0; - struct wid wid; - - wid.id = (u16)WID_ASSOC_RES_INFO; - wid.type = WID_STR; - wid.val = assoc_resp_info; - wid.size = max_assoc_resp_info_len; + wait_for_completion(&msg->work_comp); - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); - if (result) { - *rcvd_assoc_resp_info_len = 0; - netdev_err(vif->ndev, "Failed to send association response\n"); - return -EINVAL; - } - - *rcvd_assoc_resp_info_len = wid.size; + kfree(msg); return result; } int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel) { int result; - struct host_if_msg msg; + struct host_if_msg *msg; + + msg = wilc_alloc_work(vif, handle_set_channel, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_SET_CHANNEL; - msg.body.channel_info.set_ch = channel; - msg.vif = vif; + msg->body.channel_info.set_ch = channel; - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "wilc mq send fail\n"); - return -EINVAL; + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); } - return 0; + return result; } int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, u8 ifc_id) { - int result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; + + msg = wilc_alloc_work(vif, handle_set_wfi_drv_handler, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_SET_WFIDRV_HANDLER; - msg.body.drv.handler = index; - msg.body.drv.mode = mode; - msg.body.drv.name = ifc_id; - msg.vif = vif; + msg->body.drv.handler = index; + msg->body.drv.mode = mode; + msg->body.drv.name = ifc_id; - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "wilc mq send fail\n"); - result = -EINVAL; + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); } return result; @@ -3072,18 +3219,18 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode) { - int result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_SET_OPERATION_MODE; - msg.body.mode.mode = mode; - msg.vif = vif; + msg = wilc_alloc_work(vif, handle_set_operation_mode, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - result = wilc_enqueue_cmd(&msg); + msg->body.mode.mode = mode; + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "wilc mq send fail\n"); - result = -EINVAL; + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); } return result; @@ -3092,78 +3239,91 @@ int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode) s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val) { - s32 result = 0; - struct host_if_msg msg; + s32 result; + struct host_if_msg *msg; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { - netdev_err(vif->ndev, "driver is null\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return -EFAULT; } - memset(&msg, 0, sizeof(struct host_if_msg)); - memcpy(msg.body.mac_info.mac, mac, ETH_ALEN); + msg = wilc_alloc_work(vif, handle_get_inactive_time, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_GET_INACTIVETIME; - msg.vif = vif; + memcpy(msg->body.mac_info.mac, mac, ETH_ALEN); - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) - netdev_err(vif->ndev, "Failed to send get host ch param\n"); + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); else - wait_for_completion(&hif_drv->comp_inactive_time); + wait_for_completion(&msg->work_comp); - *out_val = inactive_time; + *out_val = msg->body.mac_info.inactive_time; + kfree(msg); return result; } int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) { - int result = 0; - struct host_if_msg msg; - struct host_if_drv *hif_drv = vif->hif_drv; - - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_GET_RSSI; - msg.vif = vif; + int result; + struct host_if_msg *msg; - result = wilc_enqueue_cmd(&msg); - if (result) { - netdev_err(vif->ndev, "Failed to send get host ch param\n"); + if (!rssi_level) { + netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__); return -EFAULT; } - wait_for_completion(&hif_drv->comp_get_rssi); + msg = wilc_alloc_work(vif, handle_get_rssi, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - if (!rssi_level) { - netdev_err(vif->ndev, "RSS pointer value is null\n"); - return -EFAULT; + msg->body.data = kzalloc(sizeof(s8), GFP_KERNEL); + if (!msg->body.data) { + kfree(msg); + return -ENOMEM; } - *rssi_level = rssi; + 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); 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; + int result; + struct host_if_msg *msg; - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_GET_STATISTICS; - msg.body.data = (char *)stats; - msg.vif = vif; + msg = wilc_alloc_work(vif, handle_get_statistics, is_sync); + if (IS_ERR(msg)) + return PTR_ERR(msg); - result = wilc_enqueue_cmd(&msg); + msg->body.data = (char *)stats; + + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "Failed to send get host channel\n"); - return -EFAULT; + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); + return result; + } + + if (is_sync) { + wait_for_completion(&msg->work_comp); + kfree(msg); } - if (stats != &vif->wilc->dummy_statistics) - wait_for_completion(&hif_wait_response); return result; } @@ -3172,9 +3332,9 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, size_t ies_len, wilc_scan_result scan_result, void *user_arg, struct hidden_network *hidden_network) { - int result = 0; - struct host_if_msg msg; - struct scan_attr *scan_info = &msg.body.scan_info; + 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) { @@ -3182,16 +3342,17 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, return -EFAULT; } - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_scan, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_SCAN; + 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; } - msg.vif = vif; scan_info->src = scan_source; scan_info->type = scan_type; scan_info->result = scan_result; @@ -3201,44 +3362,63 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, scan_info->ch_freq_list = kmemdup(ch_freq_list, ch_list_len, GFP_KERNEL); - if (!scan_info->ch_freq_list) - return -ENOMEM; + if (!scan_info->ch_freq_list) { + result = -ENOMEM; + goto free_msg; + } scan_info->ies_len = ies_len; scan_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); - if (!scan_info->ies) - return -ENOMEM; + if (!scan_info->ies) { + result = -ENOMEM; + goto free_freq_list; + } - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "Error in sending message queue\n"); - return -EINVAL; + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + goto free_ies; } 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_msg *msg; struct host_if_drv *hif_drv = vif->hif_drv; + int result; if (!hif_drv) { - netdev_err(vif->ndev, "hif_drv NULL\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return -EFAULT; } - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_CFG_PARAMS; - msg.body.cfg_info = *cfg_param; - msg.vif = vif; + 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); - return wilc_enqueue_cmd(&msg); + return result; } static void get_periodic_rssi(struct timer_list *unused) @@ -3246,12 +3426,12 @@ static void get_periodic_rssi(struct timer_list *unused) struct wilc_vif *vif = periodic_rssi_vif; if (!vif->hif_drv) { - netdev_err(vif->ndev, "Driver handler is NULL\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return; } 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)); } @@ -3259,15 +3439,10 @@ static void get_periodic_rssi(struct timer_list *unused) int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) { struct host_if_drv *hif_drv; - struct wilc_vif *vif; - struct wilc *wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; int i; - 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; @@ -3283,16 +3458,10 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) wilc_optaining_ip = false; if (clients_count == 0) { - init_completion(&hif_thread_comp); init_completion(&hif_driver_comp); 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) { @@ -3332,11 +3501,10 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) int wilc_deinit(struct wilc_vif *vif) { int result = 0; - struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; - if (!hif_drv) { - netdev_err(vif->ndev, "hif_drv = NULL\n"); + if (!hif_drv) { + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return -EFAULT; } @@ -3361,18 +3529,19 @@ int wilc_deinit(struct wilc_vif *vif) hif_drv->hif_state = HOST_IF_IDLE; - memset(&msg, 0, sizeof(struct host_if_msg)); - if (clients_count == 1) { - msg.id = HOST_IF_MSG_EXIT; - msg.vif = vif; - - result = wilc_enqueue_cmd(&msg); - if (result != 0) - netdev_err(vif->ndev, "deinit : Error(%d)\n", result); - else - wait_for_completion(&hif_thread_comp); - + 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); } @@ -3386,10 +3555,10 @@ int wilc_deinit(struct wilc_vif *vif) void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length) { - s32 result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; int id; - struct host_if_drv *hif_drv = NULL; + struct host_if_drv *hif_drv; struct wilc_vif *vif; id = buffer[length - 4]; @@ -3401,34 +3570,36 @@ void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length) return; hif_drv = vif->hif_drv; - if (!hif_drv || hif_drv == terminated_handle) { + if (!hif_drv || hif_drv == terminated_handle) { netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv); return; } - memset(&msg, 0, sizeof(struct host_if_msg)); - - msg.id = HOST_IF_MSG_RCVD_NTWRK_INFO; - msg.vif = vif; + msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false); + if (IS_ERR(msg)) + return; - msg.body.net_info.len = length; - msg.body.net_info.buffer = kmemdup(buffer, length, GFP_KERNEL); - if (!msg.body.net_info.buffer) + msg->body.net_info.len = length; + msg->body.net_info.buffer = kmemdup(buffer, length, GFP_KERNEL); + if (!msg->body.net_info.buffer) { + kfree(msg); return; + } - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "message parameters (%d)\n", result); - kfree(msg.body.net_info.buffer); + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg->body.net_info.buffer); + kfree(msg); } } void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length) { - s32 result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; int id; - struct host_if_drv *hif_drv = NULL; + struct host_if_drv *hif_drv; struct wilc_vif *vif; mutex_lock(&hif_deinit_lock); @@ -3451,27 +3622,30 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length) } if (!hif_drv->usr_conn_req.conn_result) { - netdev_err(vif->ndev, "there is no current Connect Request\n"); + netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__); mutex_unlock(&hif_deinit_lock); return; } - memset(&msg, 0, sizeof(struct host_if_msg)); - - msg.id = HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO; - msg.vif = vif; + msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false); + if (IS_ERR(msg)) { + mutex_unlock(&hif_deinit_lock); + return; + } - msg.body.async_info.len = length; - msg.body.async_info.buffer = kmemdup(buffer, length, GFP_KERNEL); - if (!msg.body.async_info.buffer) { + msg->body.async_info.len = length; + msg->body.async_info.buffer = kmemdup(buffer, length, GFP_KERNEL); + if (!msg->body.async_info.buffer) { + kfree(msg); mutex_unlock(&hif_deinit_lock); return; } - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "synchronous info (%d)\n", result); - kfree(msg.body.async_info.buffer); + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg->body.async_info.buffer); + kfree(msg); } mutex_unlock(&hif_deinit_lock); @@ -3479,10 +3653,9 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length) void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length) { - s32 result = 0; - struct host_if_msg msg; + int result; int id; - struct host_if_drv *hif_drv = NULL; + struct host_if_drv *hif_drv; struct wilc_vif *vif; id = buffer[length - 4]; @@ -3498,14 +3671,18 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length) return; if (hif_drv->usr_scan_req.scan_result) { - memset(&msg, 0, sizeof(struct host_if_msg)); + struct host_if_msg *msg; - msg.id = HOST_IF_MSG_RCVD_SCAN_COMPLETE; - msg.vif = vif; + msg = wilc_alloc_work(vif, handle_scan_complete, false); + if (IS_ERR(msg)) + return; - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "complete param (%d)\n", result); + result = wilc_enqueue_work(msg); + if (result) { + netdev_err(vif->ndev, "%s: enqueue work failed\n", + __func__); + kfree(msg); + } } } @@ -3515,79 +3692,86 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, wilc_remain_on_chan_ready ready, void *user_arg) { - int result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_remain_on_chan_work, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_REMAIN_ON_CHAN; - 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; - msg.vif = vif; + 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_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc mq send fail\n"); + result = wilc_enqueue_work(msg); + if (result) { + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); + } return result; } int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id) { - int result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { - netdev_err(vif->ndev, "driver is null\n"); + netdev_err(vif->ndev, "%s: hif driver is NULL", __func__); return -EFAULT; } del_timer(&hif_drv->remain_on_ch_timer); - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED; - msg.vif = vif; - msg.body.remain_on_ch.id = session_id; + msg = wilc_alloc_work(vif, handle_listen_state_expired, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc mq send fail\n"); + 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); + } return result; } int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) { - int result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_register_frame, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_REGISTER_FRAME; switch (frame_type) { case ACTION: - msg.body.reg_frame.reg_id = ACTION_FRM_IDX; + msg->body.reg_frame.reg_id = ACTION_FRM_IDX; break; case PROBE_REQ: - msg.body.reg_frame.reg_id = PROBE_REQ_IDX; + msg->body.reg_frame.reg_id = PROBE_REQ_IDX; break; default: break; } - msg.body.reg_frame.frame_type = frame_type; - msg.body.reg_frame.reg = reg; - msg.vif = vif; + msg->body.reg_frame.frame_type = frame_type; + msg->body.reg_frame.reg = reg; - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc mq send fail\n"); + result = wilc_enqueue_work(msg); + if (result) { + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); + } return result; } @@ -3595,14 +3779,15 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 head_len, u8 *head, u32 tail_len, u8 *tail) { - int result = 0; - struct host_if_msg msg; - struct beacon_attr *beacon_info = &msg.body.beacon_info; + int result; + struct host_if_msg *msg; + struct beacon_attr *beacon_info; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_add_beacon, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_ADD_BEACON; - msg.vif = vif; + beacon_info = &msg->body.beacon_info; beacon_info->interval = interval; beacon_info->dtim_period = dtim_period; beacon_info->head_len = head_len; @@ -3623,15 +3808,15 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, beacon_info->tail = NULL; } - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) - netdev_err(vif->ndev, "wilc mq send fail\n"); + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); error: if (result) { kfree(beacon_info->head); - kfree(beacon_info->tail); + kfree(msg); } return result; @@ -3639,82 +3824,92 @@ error: int wilc_del_beacon(struct wilc_vif *vif) { - int result = 0; - struct host_if_msg msg; + int result; + struct host_if_msg *msg; - msg.id = HOST_IF_MSG_DEL_BEACON; - msg.vif = vif; + msg = wilc_alloc_work(vif, handle_del_beacon, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + result = wilc_enqueue_work(msg); + if (result) { + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); + } return result; } int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param) { - int result = 0; - struct host_if_msg msg; - struct add_sta_param *add_sta_info = &msg.body.add_sta_info; - - memset(&msg, 0, sizeof(struct host_if_msg)); + int result; + struct host_if_msg *msg; + struct add_sta_param *add_sta_info; - msg.id = HOST_IF_MSG_ADD_STATION; - msg.vif = vif; + msg = wilc_alloc_work(vif, handle_add_station, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); + 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) + if (!add_sta_info->rates) { + kfree(msg); return -ENOMEM; + } } - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + 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) { - int result = 0; - struct host_if_msg msg; - struct del_sta *del_sta_info = &msg.body.del_sta_info; + int result; + struct host_if_msg *msg; + struct del_sta *del_sta_info; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_del_station, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_DEL_STATION; - msg.vif = vif; + del_sta_info = &msg->body.del_sta_info; if (!mac_addr) eth_broadcast_addr(del_sta_info->mac_addr); else memcpy(del_sta_info->mac_addr, mac_addr, ETH_ALEN); - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + 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]) { - int result = 0; - struct host_if_msg msg; - struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info; + 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; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_del_all_sta, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_DEL_ALL_STA; - msg.vif = vif; + 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)) { @@ -3723,16 +3918,20 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) assoc_sta++; } } - if (!assoc_sta) - return result; + if (!assoc_sta) { + kfree(msg); + return 0; + } del_all_sta_info->assoc_sta = assoc_sta; - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); else - wait_for_completion(&hif_wait_response); + wait_for_completion(&msg->work_comp); + + kfree(msg); return result; } @@ -3740,28 +3939,31 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) int wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *sta_param) { - int result = 0; - struct host_if_msg msg; - struct add_sta_param *add_sta_info = &msg.body.add_sta_info; - - memset(&msg, 0, sizeof(struct host_if_msg)); + int result; + struct host_if_msg *msg; + struct add_sta_param *add_sta_info; - msg.id = HOST_IF_MSG_EDIT_STATION; - msg.vif = vif; + msg = wilc_alloc_work(vif, handle_edit_station, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param)); + 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) + if (!add_sta_info->rates) { + kfree(msg); return -ENOMEM; + } } - result = wilc_enqueue_cmd(&msg); + result = wilc_enqueue_work(msg); if (result) { - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); kfree(add_sta_info->rates); + kfree(msg); } return result; @@ -3769,287 +3971,128 @@ int wilc_edit_station(struct wilc_vif *vif, int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) { - int result = 0; - struct host_if_msg msg; - struct power_mgmt_param *pwr_mgmt_info = &msg.body.pwr_mgmt_info; + int result; + struct host_if_msg *msg; if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled) return 0; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_power_management, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_POWER_MGMT; - msg.vif = vif; + msg->body.pwr_mgmt_info.enabled = enabled; + msg->body.pwr_mgmt_info.timeout = timeout; - pwr_mgmt_info->enabled = enabled; - pwr_mgmt_info->timeout = timeout; - - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + result = wilc_enqueue_work(msg); + if (result) { + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); + } return result; } int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count) { - int result = 0; - struct host_if_msg msg; - struct set_multicast *multicast_filter_param = &msg.body.multicast_info; - - memset(&msg, 0, sizeof(struct host_if_msg)); - - msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER; - msg.vif = vif; - - multicast_filter_param->enabled = enabled; - multicast_filter_param->cnt = count; - - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc_mq_send fail\n"); - return result; -} - -static void host_int_fill_join_bss_param(struct join_bss_param *param, u8 *ies, - u16 *out_index, u8 *pcipher_tc, - u8 *auth_total_cnt, u32 tsf_lo, - u8 *rates_no) -{ - u8 ext_rates_no; - u16 offset; - u8 pcipher_cnt; - u8 auth_cnt; - u8 i, j; - u16 index = *out_index; - - if (ies[index] == SUPP_RATES_IE) { - *rates_no = ies[index + 1]; - param->supp_rates[0] = *rates_no; - index += 2; - - for (i = 0; i < *rates_no; i++) - param->supp_rates[i + 1] = ies[index + i]; - - index += *rates_no; - } else if (ies[index] == EXT_SUPP_RATES_IE) { - ext_rates_no = ies[index + 1]; - if (ext_rates_no > (MAX_RATES_SUPPORTED - *rates_no)) - param->supp_rates[0] = MAX_RATES_SUPPORTED; - else - param->supp_rates[0] += ext_rates_no; - index += 2; - for (i = 0; i < (param->supp_rates[0] - *rates_no); i++) - param->supp_rates[*rates_no + i + 1] = ies[index + i]; - - index += ext_rates_no; - } else if (ies[index] == HT_CAPABILITY_IE) { - param->ht_capable = true; - index += ies[index + 1] + 2; - } else if ((ies[index] == WMM_IE) && - (ies[index + 2] == 0x00) && (ies[index + 3] == 0x50) && - (ies[index + 4] == 0xF2) && (ies[index + 5] == 0x02) && - ((ies[index + 6] == 0x00) || (ies[index + 6] == 0x01)) && - (ies[index + 7] == 0x01)) { - param->wmm_cap = true; - - if (ies[index + 8] & BIT(7)) - param->uapsd_cap = true; - index += ies[index + 1] + 2; - } else if ((ies[index] == P2P_IE) && - (ies[index + 2] == 0x50) && (ies[index + 3] == 0x6f) && - (ies[index + 4] == 0x9a) && - (ies[index + 5] == 0x09) && (ies[index + 6] == 0x0c)) { - u16 p2p_cnt; - - param->tsf = tsf_lo; - param->noa_enabled = 1; - param->idx = ies[index + 9]; - - if (ies[index + 10] & BIT(7)) { - param->opp_enabled = 1; - param->ct_window = ies[index + 10]; - } else { - param->opp_enabled = 0; - } - - param->cnt = ies[index + 11]; - p2p_cnt = index + 12; - - memcpy(param->duration, ies + p2p_cnt, 4); - p2p_cnt += 4; - - memcpy(param->interval, ies + p2p_cnt, 4); - p2p_cnt += 4; - - memcpy(param->start_time, ies + p2p_cnt, 4); - - index += ies[index + 1] + 2; - } else if ((ies[index] == RSN_IE) || - ((ies[index] == WPA_IE) && (ies[index + 2] == 0x00) && - (ies[index + 3] == 0x50) && (ies[index + 4] == 0xF2) && - (ies[index + 5] == 0x01))) { - u16 rsn_idx = index; - - if (ies[rsn_idx] == RSN_IE) { - param->mode_802_11i = 2; - } else { - if (param->mode_802_11i == 0) - param->mode_802_11i = 1; - rsn_idx += 4; - } - - rsn_idx += 7; - param->rsn_grp_policy = ies[rsn_idx]; - rsn_idx++; - offset = ies[rsn_idx] * 4; - pcipher_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx]; - rsn_idx += 2; - - i = *pcipher_tc; - j = 0; - for (; i < (pcipher_cnt + *pcipher_tc) && i < 3; i++, j++) { - u8 *policy = ¶m->rsn_pcip_policy[i]; - - *policy = ies[rsn_idx + ((j + 1) * 4) - 1]; - } - - *pcipher_tc += pcipher_cnt; - rsn_idx += offset; + int result; + struct host_if_msg *msg; - offset = ies[rsn_idx] * 4; + msg = wilc_alloc_work(vif, handle_set_mcast_filter, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - auth_cnt = (ies[rsn_idx] > 3) ? 3 : ies[rsn_idx]; - rsn_idx += 2; - i = *auth_total_cnt; - j = 0; - for (; i < (*auth_total_cnt + auth_cnt); i++, j++) { - u8 *policy = ¶m->rsn_auth_policy[i]; + msg->body.multicast_info.enabled = enabled; + msg->body.multicast_info.cnt = count; - *policy = ies[rsn_idx + ((j + 1) * 4) - 1]; - } - - *auth_total_cnt += auth_cnt; - rsn_idx += offset; - - if (ies[index] == RSN_IE) { - param->rsn_cap[0] = ies[rsn_idx]; - param->rsn_cap[1] = ies[rsn_idx + 1]; - rsn_idx += 2; - } - param->rsn_found = true; - index += ies[index + 1] + 2; - } else { - index += ies[index + 1] + 2; + result = wilc_enqueue_work(msg); + if (result) { + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); } - - *out_index = index; -} - -static void *host_int_parse_join_bss_param(struct network_info *info) -{ - struct join_bss_param *param = NULL; - u16 index = 0; - u8 rates_no = 0; - u8 pcipher_total_cnt = 0; - u8 auth_total_cnt = 0; - - param = kzalloc(sizeof(*param), GFP_KERNEL); - if (!param) - return NULL; - - param->dtim_period = info->dtim_period; - param->beacon_period = info->beacon_period; - param->cap_info = info->cap_info; - memcpy(param->bssid, info->bssid, 6); - memcpy((u8 *)param->ssid, info->ssid, info->ssid_len + 1); - param->ssid_len = info->ssid_len; - memset(param->rsn_pcip_policy, 0xFF, 3); - memset(param->rsn_auth_policy, 0xFF, 3); - - while (index < info->ies_len) - host_int_fill_join_bss_param(param, info->ies, &index, - &pcipher_total_cnt, - &auth_total_cnt, info->tsf_lo, - &rates_no); - - return (void *)param; + return result; } int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { - int result = 0; - struct host_if_msg msg; - - memset(&msg, 0, sizeof(struct host_if_msg)); + int result; + struct host_if_msg *msg; - msg.id = HOST_IF_MSG_SET_IPADDRESS; + 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.vif = vif; - msg.body.ip_info.idx = idx; + msg->body.ip_info.ip_addr = ip_addr; + msg->body.ip_info.idx = idx; - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + 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 = 0; - struct host_if_msg msg; - - memset(&msg, 0, sizeof(struct host_if_msg)); + int result; + struct host_if_msg *msg; - msg.id = HOST_IF_MSG_GET_IPADDRESS; + 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.vif = vif; - msg.body.ip_info.idx = idx; + msg->body.ip_info.ip_addr = ip_addr; + msg->body.ip_info.idx = idx; - result = wilc_enqueue_cmd(&msg); - if (result) - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + 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 = 0; - struct host_if_msg msg; + int ret; + struct host_if_msg *msg; - memset(&msg, 0, sizeof(struct host_if_msg)); + msg = wilc_alloc_work(vif, handle_set_tx_pwr, false); + if (IS_ERR(msg)) + return PTR_ERR(msg); - msg.id = HOST_IF_MSG_SET_TX_POWER; - msg.body.tx_power.tx_pwr = tx_power; - msg.vif = vif; + msg->body.tx_power.tx_pwr = tx_power; - ret = wilc_enqueue_cmd(&msg); - if (ret) - netdev_err(vif->ndev, "wilc_mq_send fail\n"); + ret = wilc_enqueue_work(msg); + if (ret) { + netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__); + kfree(msg); + } return ret; } int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power) { - int ret = 0; - struct host_if_msg msg; - - memset(&msg, 0, sizeof(struct host_if_msg)); - - msg.id = HOST_IF_MSG_GET_TX_POWER; - msg.vif = vif; + int ret; + struct host_if_msg *msg; - ret = wilc_enqueue_cmd(&msg); - if (ret) - netdev_err(vif->ndev, "Failed to get TX PWR\n"); + msg = wilc_alloc_work(vif, handle_get_tx_pwr, true); + if (IS_ERR(msg)) + return PTR_ERR(msg); - wait_for_completion(&hif_wait_response); - *tx_power = msg.body.tx_power.tx_pwr; + 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; + } + /* free 'msg' after copying data */ + kfree(msg); return ret; } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 068b587a9df4..84866a62a4d4 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -1,4 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries + * All rights reserved. + */ + #ifndef HOST_INT_H #define HOST_INT_H #include <linux/ieee80211.h> @@ -81,7 +86,7 @@ struct host_if_pmkid_attr { struct host_if_pmkid pmkidlist[WILC_MAX_NUM_PMKIDS]; }; -enum CURRENT_TXRATE { +enum current_tx_rate { AUTORATE = 0, MBPS_1 = 1, MBPS_2 = 2, @@ -113,12 +118,12 @@ struct cfg_param_attr { u8 txop_prot_disabled; u16 beacon_interval; u16 dtim_period; - enum SITESURVEY site_survey_enabled; + enum site_survey site_survey_enabled; u16 site_survey_scan_time; u8 scan_source; u16 active_scan_time; u16 passive_scan_time; - enum CURRENT_TXRATE curr_tx_rate; + enum current_tx_rate curr_tx_rate; }; @@ -199,7 +204,7 @@ struct hidden_network { struct user_scan_req { wilc_scan_result scan_result; void *arg; - u32 rcvd_ch_cnt; + u32 ch_cnt; struct found_net_info net_info[MAX_NUM_SCANNED_NETWORKS]; }; @@ -207,7 +212,7 @@ struct user_conn_req { u8 *bssid; u8 *ssid; u8 security; - enum AUTHTYPE auth_type; + enum authtype auth_type; size_t ssid_len; u8 *ies; size_t ies_len; @@ -252,12 +257,6 @@ struct reg_frame { u8 reg_id; }; -enum p2p_listen_state { - P2P_IDLE, - P2P_LISTEN, - P2P_GRP_FORMATION -}; - struct wilc; struct host_if_drv { struct user_scan_req usr_scan_req; @@ -273,10 +272,6 @@ struct host_if_drv { struct cfg_param_attr cfg_values; /*lock to protect concurrent setting of cfg params*/ struct mutex cfg_values_lock; - struct completion comp_test_key_block; - struct completion comp_test_disconn_block; - struct completion comp_get_rssi; - struct completion comp_inactive_time; struct timer_list scan_timer; struct wilc_vif *scan_timer_vif; @@ -287,7 +282,7 @@ struct host_if_drv { struct timer_list remain_on_ch_timer; struct wilc_vif *remain_on_ch_timer_vif; - bool IFC_UP; + bool ifc_up; int driver_handler_id; }; @@ -308,7 +303,7 @@ int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index); int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, u8 index); int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, - u8 index, u8 mode, enum AUTHTYPE auth_type); + u8 index, u8 mode, enum authtype auth_type); 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); @@ -324,7 +319,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 security, enum AUTHTYPE auth_type, + u8 security, enum authtype auth_type, u8 channel, void *join_params); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); @@ -359,7 +354,8 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mode, u8 ifc_id); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); -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); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power); diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 1c7e6e15809c..1afdb9e86bc1 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -1,4 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + #include "wilc_wfi_cfgoperations.h" struct wilc_wfi_radiotap_hdr { @@ -20,7 +25,6 @@ static u8 bssid[6]; #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ #define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive*/ -#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff) #define TX_RADIOTAP_PRESENT ((1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_TX_FLAGS)) @@ -40,6 +44,7 @@ void wilc_wfi_monitor_rx(u8 *buff, u32 size) /* Get WILC header */ memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); + le32_to_cpus(&header); /* * The packet offset field contain info about what type of management * the frame we are dealing with and ack status @@ -64,7 +69,7 @@ void wilc_wfi_monitor_rx(u8 *buff, u32 size) cb_hdr->hdr.it_present = cpu_to_le32(TX_RADIOTAP_PRESENT); - cb_hdr->rate = 5; /* txrate->bitrate / 5; */ + cb_hdr->rate = 5; if (pkt_offset & IS_MGMT_STATUS_SUCCES) { /* success */ @@ -85,8 +90,8 @@ void wilc_wfi_monitor_rx(u8 *buff, u32 size) hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); hdr->hdr.it_present = cpu_to_le32 - (1 << IEEE80211_RADIOTAP_RATE); /* | */ - hdr->rate = 5; /* txrate->bitrate / 5; */ + (1 << IEEE80211_RADIOTAP_RATE); + hdr->rate = 5; } skb->dev = wilc_wfi_mon; @@ -148,7 +153,6 @@ static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb, { u32 rtap_len, ret = 0; struct wilc_wfi_mon_priv *mon_priv; - struct sk_buff *skb2; struct wilc_wfi_radiotap_cb_hdr *cb_hdr; @@ -180,7 +184,7 @@ static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb, cb_hdr->hdr.it_present = cpu_to_le32(TX_RADIOTAP_PRESENT); - cb_hdr->rate = 5; /* txrate->bitrate / 5; */ + cb_hdr->rate = 5; cb_hdr->tx_flags = 0x0004; skb2->dev = wilc_wfi_mon; @@ -196,11 +200,12 @@ static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb, } skb->dev = mon_priv->real_ndev; - /* Identify if Ethernet or MAC header (data or mgmt) */ memcpy(srcadd, &skb->data[10], 6); memcpy(bssid, &skb->data[16], 6); - /* if source address and bssid fields are equal>>Mac header */ - /*send it to mgmt frames handler */ + /* + * Identify if data or mgmt packet, if source address and bssid + * fields are equal send it to mgmt frames handler + */ if (!(memcmp(srcadd, bssid, 6))) { ret = mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len); if (ret) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 02e6b1338440..01cf4bd2e192 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1,6 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + #include <linux/irq.h> -#include <linux/gpio.h> #include <linux/kthread.h> #include <linux/firmware.h> #include <linux/netdevice.h> @@ -45,7 +49,7 @@ static int dev_state_ev_handler(struct notifier_block *this, switch (event) { case NETDEV_UP: if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) { - hif_drv->IFC_UP = 1; + hif_drv->ifc_up = 1; wilc_optaining_ip = false; del_timer(&wilc_during_ip_timer); } @@ -65,7 +69,7 @@ static int dev_state_ev_handler(struct notifier_block *this, case NETDEV_DOWN: if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) { - hif_drv->IFC_UP = 0; + hif_drv->ifc_up = 0; wilc_optaining_ip = false; } @@ -94,12 +98,9 @@ static int dev_state_ev_handler(struct notifier_block *this, static irqreturn_t isr_uh_routine(int irq, void *user_data) { - struct wilc_vif *vif; - struct wilc *wilc; struct net_device *dev = user_data; - - vif = netdev_priv(dev); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; if (wilc->close) { netdev_err(dev, "Can't handle UH interrupt\n"); @@ -110,12 +111,9 @@ static irqreturn_t isr_uh_routine(int irq, void *user_data) static irqreturn_t isr_bh_routine(int irq, void *userdata) { - struct wilc_vif *vif; - struct wilc *wilc; struct net_device *dev = userdata; - - vif = netdev_priv(userdata); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(userdata); + struct wilc *wilc = vif->wilc; if (wilc->close) { netdev_err(dev, "Can't handle BH interrupt\n"); @@ -130,50 +128,38 @@ static irqreturn_t isr_bh_routine(int irq, void *userdata) static int init_irq(struct net_device *dev) { int ret = 0; - struct wilc_vif *vif; - struct wilc *wl; - - vif = netdev_priv(dev); - wl = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wl = vif->wilc; - if ((gpio_request(wl->gpio, "WILC_INTR") == 0) && - (gpio_direction_input(wl->gpio) == 0)) { - wl->dev_irq_num = gpio_to_irq(wl->gpio); - } else { - ret = -1; + ret = gpiod_direction_input(wl->gpio_irq); + if (ret) { netdev_err(dev, "could not obtain gpio for WILC_INTR\n"); + return ret; } - if (ret != -1 && request_threaded_irq(wl->dev_irq_num, - isr_uh_routine, - isr_bh_routine, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "WILC_IRQ", dev) < 0) { - netdev_err(dev, "Failed to request IRQ GPIO: %d\n", wl->gpio); - gpio_free(wl->gpio); - ret = -1; - } else { - netdev_dbg(dev, - "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n", - wl->dev_irq_num, wl->gpio); - } + wl->dev_irq_num = gpiod_to_irq(wl->gpio_irq); + + ret = request_threaded_irq(wl->dev_irq_num, isr_uh_routine, + isr_bh_routine, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "WILC_IRQ", dev); + if (ret < 0) + netdev_err(dev, "Failed to request IRQ\n"); + else + netdev_dbg(dev, "IRQ request succeeded IRQ-NUM= %d\n", + wl->dev_irq_num); return ret; } static void deinit_irq(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; /* Deinitialize IRQ */ - if (wilc->dev_irq_num) { + if (wilc->dev_irq_num) free_irq(wilc->dev_irq_num, wilc); - gpio_free(wilc->gpio); - } } void wilc_mac_indicate(struct wilc *wilc) @@ -238,12 +224,9 @@ static int linux_wlan_txq_task(void *vp) { int ret; u32 txq_count; - struct wilc_vif *vif; - struct wilc *wl; struct net_device *dev = vp; - - vif = netdev_priv(dev); - wl = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wl = vif->wilc; complete(&wl->txq_thread_started); while (1) { @@ -271,15 +254,12 @@ static int linux_wlan_txq_task(void *vp) static int wilc_wlan_get_firmware(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; int chip_id, ret = 0; const struct firmware *wilc_firmware; char *firmware; - vif = netdev_priv(dev); - wilc = vif->wilc; - chip_id = wilc_get_chipid(wilc, false); if (chip_id < 0x1003a0) @@ -306,13 +286,10 @@ fail: static int linux_wlan_start_firmware(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; int ret = 0; - vif = netdev_priv(dev); - wilc = vif->wilc; - ret = wilc_wlan_start(wilc); if (ret < 0) return ret; @@ -326,13 +303,10 @@ static int linux_wlan_start_firmware(struct net_device *dev) static int wilc1000_firmware_download(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; int ret = 0; - vif = netdev_priv(dev); - wilc = vif->wilc; - if (!wilc->firmware) { netdev_err(dev, "Firmware buffer is NULL\n"); return -ENOBUFS; @@ -378,7 +352,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, c_val, 1, 0, 0)) goto fail; - c_val[0] = RATE_AUTO; + c_val[0] = AUTORATE; if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0)) goto fail; @@ -560,11 +534,8 @@ fail: static int wlan_deinit_locks(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; mutex_destroy(&wilc->hif_cs); mutex_destroy(&wilc->rxq_cs); @@ -575,11 +546,8 @@ static int wlan_deinit_locks(struct net_device *dev) static void wlan_deinitialize_threads(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wl; - - vif = netdev_priv(dev); - wl = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wl = vif->wilc; wl->close = 1; @@ -593,18 +561,15 @@ static void wlan_deinitialize_threads(struct net_device *dev) static void wilc_wlan_deinitialize(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wl; - - vif = netdev_priv(dev); - wl = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wl = vif->wilc; if (!wl) { netdev_err(dev, "wl is NULL\n"); return; } - if (wl->initialized) { + if (wl->initialized) { netdev_info(dev, "Deinitializing wilc1000...\n"); if (!wl->dev_irq_num && @@ -632,11 +597,8 @@ static void wilc_wlan_deinitialize(struct net_device *dev) static int wlan_init_locks(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wl; - - vif = netdev_priv(dev); - wl = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wl = vif->wilc; mutex_init(&wl->hif_cs); mutex_init(&wl->rxq_cs); @@ -655,11 +617,8 @@ static int wlan_init_locks(struct net_device *dev) static int wlan_initialize_threads(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev, "K_TXQ_TASK"); @@ -690,7 +649,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) goto fail_locks; } - if (wl->gpio >= 0 && init_irq(dev)) { + if (wl->gpio_irq && init_irq(dev)) { ret = -EIO; goto fail_locks; } @@ -779,15 +738,11 @@ static int mac_init_fn(struct net_device *ndev) static int wilc_mac_open(struct net_device *ndev) { - struct wilc_vif *vif; - + struct wilc_vif *vif = netdev_priv(ndev); + struct wilc *wl = vif->wilc; unsigned char mac_add[ETH_ALEN] = {0}; int ret = 0; int i = 0; - struct wilc *wl; - - vif = netdev_priv(ndev); - wl = vif->wilc; if (!wl || !wl->dev) { netdev_err(ndev, "device not ready\n"); @@ -851,11 +806,9 @@ static struct net_device_stats *mac_stats(struct net_device *dev) static void wilc_set_multicast_list(struct net_device *dev) { struct netdev_hw_addr *ha; - struct wilc_vif *vif; + struct wilc_vif *vif = netdev_priv(dev); int i = 0; - vif = netdev_priv(dev); - if (dev->flags & IFF_PROMISC) return; @@ -895,16 +848,13 @@ static void linux_wlan_tx_complete(void *priv, int status) netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) { - struct wilc_vif *vif; + struct wilc_vif *vif = netdev_priv(ndev); + struct wilc *wilc = vif->wilc; struct tx_complete_data *tx_data = NULL; int queue_count; char *udp_buf; struct iphdr *ih; struct ethhdr *eth_h; - struct wilc *wilc; - - vif = netdev_priv(ndev); - wilc = vif->wilc; if (skb->dev != ndev) { netdev_err(ndev, "Packet not destined to this device\n"); @@ -952,12 +902,10 @@ netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) static int wilc_mac_close(struct net_device *ndev) { struct wilc_priv *priv; - struct wilc_vif *vif; + struct wilc_vif *vif = netdev_priv(ndev); struct host_if_drv *hif_drv; struct wilc *wl; - vif = netdev_priv(ndev); - if (!vif || !vif->ndev || !vif->ndev->ieee80211_ptr || !vif->ndev->ieee80211_ptr->wiphy) return 0; @@ -1090,8 +1038,8 @@ void wilc_netdev_cleanup(struct wilc *wilc) } kfree(wilc); + wilc_debugfs_remove(); } -EXPORT_SYMBOL_GPL(wilc_netdev_cleanup); static const struct net_device_ops wilc_netdev_ops = { .ndo_init = mac_init_fn, @@ -1103,7 +1051,7 @@ static const struct net_device_ops wilc_netdev_ops = { }; int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, - int gpio, const struct wilc_hif_func *ops) + const struct wilc_hif_func *ops) { int i, ret; struct wilc_vif *vif; @@ -1114,10 +1062,12 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, if (!wl) return -ENOMEM; + wilc_debugfs_init(); *wilc = wl; wl->io_type = io_type; - wl->gpio = gpio; wl->hif_func = ops; + INIT_LIST_HEAD(&wl->txq_head.list); + INIT_LIST_HEAD(&wl->rxq_head.list); register_inetaddr_notifier(&g_dev_notifier); @@ -1174,6 +1124,3 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, return 0; } -EXPORT_SYMBOL_GPL(wilc_netdev_init); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt b/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt new file mode 100644 index 000000000000..4f7d1c2be4d0 --- /dev/null +++ b/drivers/staging/wilc1000/microchip,wilc1000,sdio.txt @@ -0,0 +1,32 @@ +* Microchip WILC wireless SDIO device + +The wilc1000 chips can be connected via SDIO. The node is used to specifiy +child node to the SDIO controller that connects the device to the system. + +Required properties: +- compatible : Should be "microchip,wilc1000-spi" +- irq-gpios : Connect to a host IRQ +- reg : Slot ID used in the controller + +Optional: +- bus-width : Number of data lines wired up the slot. Default 1 bit. + + +Examples: +mmc1: mmc@fc000000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3>; + non-removable; + vmmc-supply = <&vcc_mmc1_reg>; + vqmmc-supply = <&vcc_3v3_reg>; + status = "okay"; + + wilc_sdio@0 { + compatible = "microchip,wilc1000-sdio"; + irq-gpios = <&pioC 27 0>; + status = "okay"; + reg = <0>; + bus-width = <4>; + } + }; +} diff --git a/drivers/staging/wilc1000/microchip,wilc1000,spi.txt b/drivers/staging/wilc1000/microchip,wilc1000,spi.txt new file mode 100644 index 000000000000..87db87b2d901 --- /dev/null +++ b/drivers/staging/wilc1000/microchip,wilc1000,spi.txt @@ -0,0 +1,26 @@ +* Microchip WILC wireless SPI device + +The wilc1000 chips can be connected via SPI. This document describes +the binding for the SPI connected module. + +Required properties: +- compatible : Should be "microchip,wilc1000-spi" +- spi-max-frequency : Maximum SPI clocking speed of device in Hz +- reg : Chip select address of device +- irq-gpios : Connect to a host IRQ + + +Examples: + +spi1: spi@fc018000 { + cs-gpios = <&pioB 21 0>; + status = "okay"; + + wilc_spi@0 { + compatible = "microchip,wilc1000-spi"; + spi-max-frequency = <48000000>; + reg = <0>; + irq-gpios = <&pioC 27 0>; + status = "okay"; + }; +}; diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 287c11b58160..edc72876458d 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -1,13 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* - * NewportMedia WiFi chipset driver test tools - wilc-debug - * Copyright (c) 2012 NewportMedia Inc. - * Author: SSW <sswd@wilcsemic.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. */ #if defined(WILC_DEBUGFS) @@ -18,9 +12,6 @@ static struct dentry *wilc_dir; -/* - * ---------------------------------------------------------------------------- - */ #define DEBUG BIT(0) #define INFO BIT(1) #define WRN BIT(2) @@ -28,11 +19,6 @@ static struct dentry *wilc_dir; #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) static atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR); -EXPORT_SYMBOL_GPL(WILC_DEBUG_LEVEL); - -/* - * ---------------------------------------------------------------------------- - */ static ssize_t wilc_debug_level_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) @@ -77,10 +63,6 @@ static ssize_t wilc_debug_level_write(struct file *filp, return count; } -/* - * ---------------------------------------------------------------------------- - */ - #define FOPS(_open, _read, _write, _poll) { \ .owner = THIS_MODULE, \ .open = (_open), \ @@ -105,7 +87,7 @@ static struct wilc_debugfs_info_t debugfs_info[] = { }, }; -static int __init wilc_debugfs_init(void) +int wilc_debugfs_init(void) { int i; struct wilc_debugfs_info_t *info; @@ -121,12 +103,10 @@ static int __init wilc_debugfs_init(void) } return 0; } -module_init(wilc_debugfs_init); -static void __exit wilc_debugfs_remove(void) +void wilc_debugfs_remove(void) { debugfs_remove_recursive(wilc_dir); } -module_exit(wilc_debugfs_remove); #endif diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 4ab43f97646a..b2080d8b801f 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -1,12 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) Atmel Corporation. All rights reserved. - * - * Module Name: wilc_sdio.c + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. */ #include <linux/mmc/sdio_func.h> -#include <linux/of_gpio.h> +#include <linux/mmc/host.h> #include "wilc_wfi_netdevice.h" @@ -108,24 +107,28 @@ static int linux_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { struct wilc *wilc; - int gpio, ret; + int ret; + struct gpio_desc *gpio = NULL; - gpio = -1; if (IS_ENABLED(CONFIG_WILC1000_HW_OOB_INTR)) { - gpio = of_get_gpio(func->dev.of_node, 0); - if (gpio < 0) - gpio = GPIO_NUM; + gpio = gpiod_get(&func->dev, "irq", GPIOD_IN); + if (IS_ERR(gpio)) { + /* get the GPIO descriptor from hardcode GPIO number */ + gpio = gpio_to_desc(GPIO_NUM); + if (!gpio) + dev_err(&func->dev, "failed to get irq gpio\n"); + } } dev_dbg(&func->dev, "Initializing netdev\n"); - ret = wilc_netdev_init(&wilc, &func->dev, HIF_SDIO, gpio, - &wilc_hif_sdio); + ret = wilc_netdev_init(&wilc, &func->dev, HIF_SDIO, &wilc_hif_sdio); if (ret) { dev_err(&func->dev, "Couldn't initialize netdev\n"); return ret; } sdio_set_drvdata(func, wilc); wilc->dev = &func->dev; + wilc->gpio_irq = gpio; dev_info(&func->dev, "Driver Initializing success\n"); return 0; @@ -133,7 +136,12 @@ static int linux_sdio_probe(struct sdio_func *func, static void linux_sdio_remove(struct sdio_func *func) { - wilc_netdev_cleanup(sdio_get_drvdata(func)); + struct wilc *wilc = sdio_get_drvdata(func); + + /* free the GPIO in module remove */ + if (wilc->gpio_irq) + gpiod_put(wilc->gpio_irq); + wilc_netdev_cleanup(wilc); } static int sdio_reset(struct wilc *wilc) @@ -199,21 +207,28 @@ static int wilc_sdio_resume(struct device *dev) return 0; } +static const struct of_device_id wilc_of_match[] = { + { .compatible = "microchip,wilc1000-sdio", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, wilc_of_match); + static const struct dev_pm_ops wilc_sdio_pm_ops = { .suspend = wilc_sdio_suspend, .resume = wilc_sdio_resume, }; -static struct sdio_driver wilc1000_sdio_driver = { +static struct sdio_driver wilc_sdio_driver = { .name = SDIO_MODALIAS, .id_table = wilc_sdio_ids, .probe = linux_sdio_probe, .remove = linux_sdio_remove, .drv = { .pm = &wilc_sdio_pm_ops, + .of_match_table = wilc_of_match, } }; -module_driver(wilc1000_sdio_driver, +module_driver(wilc_sdio_driver, sdio_register_driver, sdio_unregister_driver); MODULE_LICENSE("GPL"); @@ -368,7 +383,7 @@ static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data) struct sdio_func *func = dev_to_sdio_func(wilc->dev); int ret; - data = cpu_to_le32(data); + cpu_to_le32s(&data); if (addr >= 0xf0 && addr <= 0xff) { struct sdio_cmd52 cmd; @@ -547,7 +562,7 @@ static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data) } } - *data = cpu_to_le32(*data); + le32_to_cpus(data); return 1; @@ -793,9 +808,6 @@ static int sdio_read_size(struct wilc *wilc, u32 *size) wilc_sdio_cmd52(wilc, &cmd); tmp = cmd.data; - /* cmd.read_write = 0; */ - /* cmd.function = 0; */ - /* cmd.raw = 0; */ cmd.address = 0xf3; cmd.data = 0; wilc_sdio_cmd52(wilc, &cmd); @@ -1080,12 +1092,7 @@ static int sdio_sync_ext(struct wilc *wilc, int nint) return 1; } -/******************************************** - * - * Global sdio HIF function table - * - ********************************************/ - +/* Global sdio HIF function table */ static const struct wilc_hif_func wilc_hif_sdio = { .hif_init = sdio_init, .hif_deinit = sdio_deinit, diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 647526387784..5517477d875a 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -1,12 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) Atmel Corporation. All rights reserved. - * - * Module Name: wilc_spi.c + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. */ #include <linux/spi/spi.h> -#include <linux/of_gpio.h> #include "wilc_wfi_netdevice.h" @@ -106,44 +104,55 @@ static u8 crc7(u8 crc, const u8 *buffer, u32 len) static int wilc_bus_probe(struct spi_device *spi) { - int ret, gpio; + int ret; struct wilc *wilc; + struct gpio_desc *gpio; + + gpio = gpiod_get(&spi->dev, "irq", GPIOD_IN); + if (IS_ERR(gpio)) { + /* get the GPIO descriptor from hardcode GPIO number */ + gpio = gpio_to_desc(GPIO_NUM); + if (!gpio) + dev_err(&spi->dev, "failed to get the irq gpio\n"); + } - gpio = of_get_gpio(spi->dev.of_node, 0); - if (gpio < 0) - gpio = GPIO_NUM; - - ret = wilc_netdev_init(&wilc, NULL, HIF_SPI, GPIO_NUM, &wilc_hif_spi); + ret = wilc_netdev_init(&wilc, NULL, HIF_SPI, &wilc_hif_spi); if (ret) return ret; spi_set_drvdata(spi, wilc); wilc->dev = &spi->dev; + wilc->gpio_irq = gpio; return 0; } static int wilc_bus_remove(struct spi_device *spi) { - wilc_netdev_cleanup(spi_get_drvdata(spi)); + struct wilc *wilc = spi_get_drvdata(spi); + + /* free the GPIO in module remove */ + if (wilc->gpio_irq) + gpiod_put(wilc->gpio_irq); + wilc_netdev_cleanup(wilc); return 0; } -static const struct of_device_id wilc1000_of_match[] = { - { .compatible = "atmel,wilc_spi", }, - {} +static const struct of_device_id wilc_of_match[] = { + { .compatible = "microchip,wilc1000-spi", }, + { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, wilc1000_of_match); +MODULE_DEVICE_TABLE(of, wilc_of_match); -static struct spi_driver wilc1000_spi_driver = { +static struct spi_driver wilc_spi_driver = { .driver = { .name = MODALIAS, - .of_match_table = wilc1000_of_match, + .of_match_table = wilc_of_match, }, .probe = wilc_bus_probe, .remove = wilc_bus_remove, }; -module_spi_driver(wilc1000_spi_driver); +module_spi_driver(wilc_spi_driver); MODULE_LICENSE("GPL"); static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len) @@ -668,7 +677,7 @@ static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat) struct spi_device *spi = to_spi_device(wilc->dev); int result; - dat = cpu_to_le32(dat); + cpu_to_le32s(&dat); result = spi_cmd_complete(wilc, CMD_INTERNAL_WRITE, adr, (u8 *)&dat, 4, 0); if (result != N_OK) @@ -689,7 +698,7 @@ static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) return 0; } - *data = cpu_to_le32(*data); + le32_to_cpus(data); return 1; } @@ -707,7 +716,7 @@ static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data) u8 cmd = CMD_SINGLE_WRITE; u8 clockless = 0; - data = cpu_to_le32(data); + cpu_to_le32s(&data); if (addr < 0x30) { /* Clockless register */ cmd = CMD_INTERNAL_WRITE; @@ -757,7 +766,6 @@ static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) u8 clockless = 0; if (addr < 0x30) { - /* dev_err(&spi->dev, "***** read addr %d\n\n", addr); */ /* Clockless register */ cmd = CMD_INTERNAL_READ; clockless = 1; @@ -769,7 +777,7 @@ static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) return 0; } - *data = cpu_to_le32(*data); + le32_to_cpus(data); return 1; } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index e248702ee519..7cd033004651 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1,4 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + #include "wilc_wfi_cfgoperations.h" #define NO_ENCRYPT 0 @@ -77,11 +82,6 @@ static const struct wiphy_wowlan_support wowlan_support = { .flags = WIPHY_WOWLAN_ANY }; -#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54 -#define DEFAULT_LINK_SPEED 72 - -#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff) - static struct network_info last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW]; static u32 last_scanned_cnt; struct timer_list wilc_during_ip_timer; @@ -468,28 +468,22 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, struct disconnect_info *disconn_info, void *priv_data) { - struct wilc_priv *priv; - struct net_device *dev; - struct host_if_drv *wfi_drv; + struct wilc_priv *priv = priv_data; + struct net_device *dev = priv->dev; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wl = vif->wilc; + struct host_if_drv *wfi_drv = priv->hif_drv; u8 null_bssid[ETH_ALEN] = {0}; - struct wilc *wl; - struct wilc_vif *vif; wilc_connecting = 0; - priv = priv_data; - dev = priv->dev; - vif = netdev_priv(dev); - wl = vif->wilc; - wfi_drv = (struct host_if_drv *)priv->hif_drv; - if (conn_disconn_evt == CONN_DISCONN_EVENT_CONN_RESP) { u16 connect_status; connect_status = conn_info->status; if (mac_status == MAC_STATUS_DISCONNECTED && - conn_info->status == SUCCESSFUL_STATUSCODE) { + conn_info->status == WLAN_STATUS_SUCCESS) { connect_status = WLAN_STATUS_UNSPECIFIED_FAILURE; wilc_wlan_set_bssid(priv->dev, null_bssid, STATION_MODE); @@ -529,7 +523,7 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, conn_info->resp_ies, conn_info->resp_ies_len, connect_status, GFP_KERNEL); - } else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) { + } else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) { wilc_optaining_ip = false; p2p_local_random = 0x01; p2p_recv_random = 0x00; @@ -540,9 +534,9 @@ static void cfg_connect_result(enum conn_event conn_disconn_evt, if (!wfi_drv->p2p_connect) wlan_channel = INVALID_CHANNEL; - if (wfi_drv->IFC_UP && dev == wl->vif[1]->ndev) + if (wfi_drv->ifc_up && dev == wl->vif[1]->ndev) disconn_info->reason = 3; - else if (!wfi_drv->IFC_UP && dev == wl->vif[1]->ndev) + else if (!wfi_drv->ifc_up && dev == wl->vif[1]->ndev) disconn_info->reason = 1; cfg80211_disconnected(dev, disconn_info->reason, @@ -555,12 +549,9 @@ static int set_channel(struct wiphy *wiphy, struct cfg80211_chan_def *chandef) { u32 channelnum = 0; - struct wilc_priv *priv; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); int result = 0; - struct wilc_vif *vif; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq); @@ -618,15 +609,12 @@ out: static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { - struct wilc_priv *priv; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); u32 i; - s32 ret = 0; + int ret = 0; u8 scan_ch_list[MAX_NUM_SCANNED_NETWORKS]; struct hidden_network hidden_ntwk; - struct wilc_vif *vif; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); priv->scan_req = request; @@ -674,21 +662,18 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) static int connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { - s32 ret = 0; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + struct host_if_drv *wfi_drv = priv->hif_drv; + struct network_info *nw_info; + int ret; u32 i; u32 sel_bssi_idx = UINT_MAX; u8 security = NO_ENCRYPT; - enum AUTHTYPE auth_type = ANY; + enum authtype auth_type = ANY; u32 cipher_group; - struct wilc_priv *priv; - struct host_if_drv *wfi_drv; - struct network_info *nw_info = NULL; - struct wilc_vif *vif; wilc_connecting = 1; - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); - wfi_drv = (struct host_if_drv *)priv->hif_drv; if (!(strncmp(sme->ssid, "DIRECT-", 7))) wfi_drv->p2p_connect = 1; @@ -761,7 +746,8 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, security = ENCRYPT_ENABLED | WPA | AES; } else { ret = -ENOTSUPP; - netdev_err(dev, "Not supported cipher\n"); + netdev_err(dev, "%s: Unsupported cipher\n", + __func__); wilc_connecting = 0; return ret; } @@ -823,17 +809,14 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) { - s32 ret = 0; - struct wilc_priv *priv; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + struct wilc *wilc = vif->wilc; struct host_if_drv *wfi_drv; - struct wilc_vif *vif; - struct wilc *wilc; + int ret; u8 null_bssid[ETH_ALEN] = {0}; wilc_connecting = 0; - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); - wilc = vif->wilc; if (!wilc) return -EIO; @@ -919,16 +902,13 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { - s32 ret = 0, keylen = params->key_len; - struct wilc_priv *priv; + int ret = 0, keylen = params->key_len; + struct wilc_priv *priv = wiphy_priv(wiphy); const u8 *rx_mic = NULL; const u8 *tx_mic = NULL; u8 mode = NO_ENCRYPT; u8 op_mode; - struct wilc_vif *vif; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(netdev); + struct wilc_vif *vif = netdev_priv(netdev); switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: @@ -1021,7 +1001,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, break; default: - netdev_err(netdev, "Not supported cipher\n"); + netdev_err(netdev, "%s: Unsupported cipher\n", __func__); ret = -ENOTSUPP; } @@ -1033,13 +1013,9 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev, bool pairwise, const u8 *mac_addr) { - struct wilc_priv *priv; - struct wilc *wl; - struct wilc_vif *vif; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(netdev); - wl = vif->wilc; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(netdev); + struct wilc *wl = vif->wilc; if (netdev == wl->vif[0]->ndev) { if (priv->wilc_gtk[key_index]) { @@ -1076,11 +1052,9 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params *)) { - struct wilc_priv *priv; + struct wilc_priv *priv = wiphy_priv(wiphy); struct key_params key_params; - priv = wiphy_priv(wiphy); - if (!pairwise) { key_params.key = priv->wilc_gtk[key_index]->key; key_params.cipher = priv->wilc_gtk[key_index]->cipher; @@ -1103,11 +1077,8 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool unicast, bool multicast) { - struct wilc_priv *priv; - struct wilc_vif *vif; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); wilc_set_wep_default_keyid(vif, key_index); @@ -1117,15 +1088,12 @@ static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, static int get_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac, struct station_info *sinfo) { - struct wilc_priv *priv; - struct wilc_vif *vif; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(dev); u32 i = 0; u32 associatedsta = ~0; u32 inactive_time = 0; - priv = wiphy_priv(wiphy); - vif = netdev_priv(dev); - if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) { for (i = 0; i < NUM_STA_ASSOCIATED; i++) { if (!(memcmp(mac, @@ -1141,20 +1109,20 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev, return -ENOENT; } - sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME); wilc_get_inactive_time(vif, mac, &inactive_time); sinfo->inactive_time = 1000 * inactive_time; } else if (vif->iftype == STATION_MODE) { struct rf_info stats; - wilc_get_statistics(vif, &stats); + wilc_get_statistics(vif, &stats, true); - sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) | - BIT(NL80211_STA_INFO_RX_PACKETS) | - BIT(NL80211_STA_INFO_TX_PACKETS) | - BIT(NL80211_STA_INFO_TX_FAILED) | - BIT(NL80211_STA_INFO_TX_BITRATE); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL) | + BIT_ULL(NL80211_STA_INFO_RX_PACKETS) | + BIT_ULL(NL80211_STA_INFO_TX_PACKETS) | + BIT_ULL(NL80211_STA_INFO_TX_FAILED) | + BIT_ULL(NL80211_STA_INFO_TX_BITRATE); sinfo->signal = stats.rssi; sinfo->rx_packets = stats.rx_cnt; @@ -1179,13 +1147,10 @@ static int change_bss(struct wiphy *wiphy, struct net_device *dev, static int set_wiphy_params(struct wiphy *wiphy, u32 changed) { - s32 ret = 0; + int ret; struct cfg_param_attr cfg_param_val; - struct wilc_priv *priv; - struct wilc_vif *vif; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); cfg_param_val.flag = 0; @@ -1217,13 +1182,11 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed) static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev, struct cfg80211_pmksa *pmksa) { + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); u32 i; - s32 ret = 0; + int ret = 0; u8 flag = 0; - struct wilc_vif *vif; - struct wilc_priv *priv = wiphy_priv(wiphy); - - vif = netdev_priv(priv->dev); for (i = 0; i < priv->pmkid_list.numpmkid; i++) { if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid, @@ -1254,8 +1217,7 @@ static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev, struct cfg80211_pmksa *pmksa) { u32 i; - s32 ret = 0; - + int ret = 0; struct wilc_priv *priv = wiphy_priv(wiphy); for (i = 0; i < priv->pmkid_list.numpmkid; i++) { @@ -1320,7 +1282,6 @@ static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u8 ch_list_attr_idx, static void wilc_wfi_cfg_parse_rx_action(u8 *buf, u32 len) { u32 index = 0; - u8 op_channel_attr_index = 0; u8 channel_list_attr_index = 0; @@ -1343,7 +1304,6 @@ static void wilc_wfi_cfg_parse_tx_action(u8 *buf, u32 len, bool oper_ch, u8 iftype) { u32 index = 0; - u8 op_channel_attr_index = 0; u8 channel_list_attr_index = 0; @@ -1405,16 +1365,14 @@ static void wilc_wfi_cfg_parse_rx_vendor_spec(struct wilc_priv *priv, u8 *buff, void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) { - struct wilc_priv *priv; + struct wilc_priv *priv = wiphy_priv(dev->ieee80211_ptr->wiphy); + struct host_if_drv *wfi_drv = priv->hif_drv; u32 header, pkt_offset; - struct host_if_drv *wfi_drv; s32 freq; - - priv = wiphy_priv(dev->ieee80211_ptr->wiphy); - wfi_drv = (struct host_if_drv *)priv->hif_drv; + __le16 fc; memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); - + le32_to_cpus(&header); pkt_offset = GET_PKT_OFFSET(header); if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { @@ -1431,7 +1389,8 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) freq = ieee80211_channel_to_frequency(curr_channel, NL80211_BAND_2GHZ); - if (!ieee80211_is_action(buff[FRAME_TYPE_ID])) { + fc = ((struct ieee80211_hdr *)buff)->frame_control; + if (!ieee80211_is_action(fc)) { cfg80211_rx_mgmt(priv->wdev, freq, 0, buff, size, 0); return; } @@ -1462,8 +1421,8 @@ void wilc_wfi_p2p_rx(struct net_device *dev, u8 *buff, u32 size) default: netdev_dbg(dev, - "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", - buff[ACTION_SUBTYPE_ID]); + "%s: Not handled action frame type:%x\n", + __func__, buff[ACTION_SUBTYPE_ID]); break; } } @@ -1513,12 +1472,9 @@ static int remain_on_channel(struct wiphy *wiphy, struct ieee80211_channel *chan, unsigned int duration, u64 *cookie) { - s32 ret = 0; - struct wilc_priv *priv; - struct wilc_vif *vif; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); + int ret = 0; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); if (wdev->iftype == NL80211_IFTYPE_AP) { netdev_dbg(vif->ndev, "Required while in AP mode\n"); @@ -1543,11 +1499,8 @@ static int cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) { - struct wilc_priv *priv; - struct wilc_vif *vif; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); return wilc_listen_state_expired(vif, priv->remain_on_ch_params.listen_session_id); @@ -1613,16 +1566,12 @@ static int mgmt_tx(struct wiphy *wiphy, size_t len = params->len; const struct ieee80211_mgmt *mgmt; struct p2p_mgmt_data *mgmt_tx; - struct wilc_priv *priv; - struct host_if_drv *wfi_drv; - struct wilc_vif *vif; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct host_if_drv *wfi_drv = priv->hif_drv; + struct wilc_vif *vif = netdev_priv(wdev->netdev); u32 buf_len = len + sizeof(p2p_vendor_spec) + sizeof(p2p_local_random); int ret = 0; - vif = netdev_priv(wdev->netdev); - priv = wiphy_priv(wiphy); - wfi_drv = (struct host_if_drv *)priv->hif_drv; - *cookie = (unsigned long)buf; priv->tx_cookie = *cookie; mgmt = (const struct ieee80211_mgmt *)buf; @@ -1679,8 +1628,8 @@ static int mgmt_tx(struct wiphy *wiphy, default: netdev_dbg(vif->ndev, - "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", - buf[ACTION_SUBTYPE_ID]); + "%s: Not handled action frame type:%x\n", + __func__, buf[ACTION_SUBTYPE_ID]); break; } } @@ -1702,11 +1651,9 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) { - struct wilc_priv *priv; - struct host_if_drv *wfi_drv; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct host_if_drv *wfi_drv = priv->hif_drv; - priv = wiphy_priv(wiphy); - wfi_drv = (struct host_if_drv *)priv->hif_drv; wfi_drv->p2p_timeout = jiffies; if (!priv->p2p_listen_state) { @@ -1726,13 +1673,9 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy, void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, u16 frame_type, bool reg) { - struct wilc_priv *priv; - struct wilc_vif *vif; - struct wilc *wl; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->wdev->netdev); - wl = vif->wilc; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->wdev->netdev); + struct wilc *wl = vif->wilc; if (!frame_type) return; @@ -1766,16 +1709,13 @@ static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev, static int dump_station(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *mac, struct station_info *sinfo) { - struct wilc_priv *priv; - struct wilc_vif *vif; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); if (idx != 0) return -ENOENT; - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); - - sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); wilc_get_rssi(vif, &sinfo->signal); @@ -1786,14 +1726,9 @@ static int dump_station(struct wiphy *wiphy, struct net_device *dev, static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout) { - struct wilc_priv *priv; - struct wilc_vif *vif; - - if (!wiphy) - return -ENOENT; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); if (!priv->hif_drv) return -EIO; @@ -1807,13 +1742,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, enum nl80211_iftype type, struct vif_params *params) { - struct wilc_priv *priv; - struct wilc_vif *vif; - struct wilc *wl; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wl = vif->wilc; - vif = netdev_priv(dev); - priv = wiphy_priv(wiphy); - wl = vif->wilc; p2p_local_random = 0x01; p2p_recv_random = 0x00; wilc_ie = false; @@ -1886,13 +1818,10 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, static int start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings) { + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wl = vif->wilc; struct cfg80211_beacon_data *beacon = &settings->beacon; - s32 ret = 0; - struct wilc *wl; - struct wilc_vif *vif; - - vif = netdev_priv(dev); - wl = vif->wilc; + int ret; ret = set_channel(wiphy, &settings->chandef); @@ -1911,11 +1840,8 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, static int change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *beacon) { - struct wilc_priv *priv; - struct wilc_vif *vif; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); return wilc_add_beacon(vif, 0, 0, beacon->head_len, (u8 *)beacon->head, beacon->tail_len, @@ -1924,17 +1850,11 @@ static int change_beacon(struct wiphy *wiphy, struct net_device *dev, static int stop_ap(struct wiphy *wiphy, struct net_device *dev) { - s32 ret = 0; - struct wilc_priv *priv; - struct wilc_vif *vif; + int ret; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); u8 null_bssid[ETH_ALEN] = {0}; - if (!wiphy) - return -EFAULT; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->dev); - wilc_wlan_set_bssid(dev, null_bssid, AP_MODE); ret = wilc_del_beacon(vif); @@ -1948,16 +1868,10 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev) static int add_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac, struct station_parameters *params) { - s32 ret = 0; - struct wilc_priv *priv; + int ret = 0; + struct wilc_priv *priv = wiphy_priv(wiphy); struct add_sta_param sta_params = { {0} }; - struct wilc_vif *vif; - - if (!wiphy) - return -EFAULT; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(dev); + struct wilc_vif *vif = netdev_priv(dev); if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) { memcpy(sta_params.bssid, mac, ETH_ALEN); @@ -1989,17 +1903,11 @@ static int del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) { const u8 *mac = params->mac; - s32 ret = 0; - struct wilc_priv *priv; - struct wilc_vif *vif; + int ret = 0; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(dev); struct sta_info *info; - if (!wiphy) - return -EFAULT; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(dev); - if (!(vif->iftype == AP_MODE || vif->iftype == GO_MODE)) return ret; @@ -2017,14 +1925,9 @@ static int del_station(struct wiphy *wiphy, struct net_device *dev, static int change_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac, struct station_parameters *params) { - s32 ret = 0; + int ret = 0; struct add_sta_param sta_params = { {0} }; - struct wilc_vif *vif; - - if (!wiphy) - return -EFAULT; - - vif = netdev_priv(dev); + struct wilc_vif *vif = netdev_priv(dev); if (vif->iftype == AP_MODE || vif->iftype == GO_MODE) { memcpy(sta_params.bssid, mac, ETH_ALEN); @@ -2055,12 +1958,9 @@ static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy, enum nl80211_iftype type, struct vif_params *params) { - struct wilc_vif *vif; - struct wilc_priv *priv; - struct net_device *new_ifc = NULL; - - priv = wiphy_priv(wiphy); - vif = netdev_priv(priv->wdev->netdev); + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->wdev->netdev); + struct net_device *new_ifc; if (type == NL80211_IFTYPE_MONITOR) { new_ifc = wilc_wfi_init_mon_interface(name, vif->ndev); @@ -2132,9 +2032,7 @@ static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, int ret; struct wilc_priv *priv = wiphy_priv(wiphy); struct wilc_vif *vif = netdev_priv(priv->dev); - struct wilc *wl; - - wl = vif->wilc; + struct wilc *wl = vif->wilc; /* If firmware is not started, return. */ if (!wl->initialized) @@ -2196,11 +2094,11 @@ static struct wireless_dev *wilc_wfi_cfg_alloc(void) wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); if (!wdev) - goto _fail_; + goto out; wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv)); if (!wdev->wiphy) - goto _fail_mem_; + goto free_mem; wilc_band_2ghz.ht_cap.ht_supported = 1; wilc_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); @@ -2212,9 +2110,9 @@ static struct wireless_dev *wilc_wfi_cfg_alloc(void) return wdev; -_fail_mem_: +free_mem: kfree(wdev); -_fail_: +out: return NULL; } @@ -2223,7 +2121,7 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, { struct wilc_priv *priv; struct wireless_dev *wdev; - s32 ret = 0; + int ret; wdev = wilc_wfi_cfg_alloc(); if (!wdev) { @@ -2265,19 +2163,15 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, int wilc_init_host_int(struct net_device *net) { - int ret = 0; - - struct wilc_priv *priv; + int ret; + struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr); - priv = wdev_priv(net->ieee80211_ptr); if (op_ifcs == 0) { timer_setup(&aging_timer, remove_network_from_shadow, 0); timer_setup(&wilc_during_ip_timer, clear_during_ip, 0); } op_ifcs++; - priv->auto_rate_adjusted = false; - priv->p2p_listen_state = false; mutex_init(&priv->scan_req_lock); @@ -2290,14 +2184,9 @@ int wilc_init_host_int(struct net_device *net) int wilc_deinit_host_int(struct net_device *net) { - int ret = 0; - struct wilc_vif *vif; - struct wilc_priv *priv; - - priv = wdev_priv(net->ieee80211_ptr); - vif = netdev_priv(priv->dev); - - priv->auto_rate_adjusted = false; + int ret; + struct wilc_priv *priv = wdev_priv(net->ieee80211_ptr); + struct wilc_vif *vif = netdev_priv(priv->dev); priv->p2p_listen_state = false; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h index a69103b44958..be412b65926c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h @@ -1,4 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + #ifndef NM_WFI_CFGOPERATIONS #define NM_WFI_CFGOPERATIONS #include "wilc_wfi_netdevice.h" diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index f2b07e8aedd7..b7eee772f3fe 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -1,4 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + #ifndef WILC_WFI_NETDEVICE #define WILC_WFI_NETDEVICE @@ -7,6 +12,7 @@ #include <net/cfg80211.h> #include <net/ieee80211_radiotap.h> #include <linux/if_arp.h> +#include <linux/gpio/consumer.h> #include "host_interface.h" #include "wilc_wlan.h" @@ -21,6 +27,11 @@ #define NUM_REG_FRAME 2 +#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54 +#define DEFAULT_LINK_SPEED 72 + +#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff) + struct wilc_wfi_stats { unsigned long rx_packets; unsigned long tx_packets; @@ -31,11 +42,6 @@ struct wilc_wfi_stats { }; -/* - * This structure is private to each device. It is used to pass - * packets in and out, so there is place for a packet - */ - struct wilc_wfi_key { u8 *key; u8 *seq; @@ -74,14 +80,10 @@ struct wilc_priv { u8 associated_bss[ETH_ALEN]; struct sta_info assoc_stainfo; - struct net_device_stats stats; - u8 monitor_flag; - int status; struct sk_buff *skb; struct net_device *dev; struct host_if_drv *hif_drv; struct host_if_pmkid_attr pmkid_list; - struct wilc_wfi_stats netstats; u8 wep_key[4][WLAN_KEY_LEN_WEP104]; u8 wep_key_len[4]; /* The real interface that the monitor is on */ @@ -91,9 +93,6 @@ struct wilc_priv { u8 wilc_groupkey; /* mutexes */ struct mutex scan_req_lock; - /* */ - bool auto_rate_adjusted; - bool p2p_listen_state; }; @@ -123,7 +122,7 @@ struct wilc { const struct wilc_hif_func *hif_func; int io_type; int mac_status; - int gpio; + struct gpio_desc *gpio_irq; bool initialized; int dev_irq_num; int close; @@ -136,6 +135,7 @@ struct wilc { spinlock_t txq_spinlock; /*protect rxq_entry_t receiver queue*/ struct mutex rxq_cs; + /* lock to protect hif access */ struct mutex hif_cs; struct completion cfg_event; @@ -155,19 +155,10 @@ struct wilc { u32 rx_buffer_offset; u8 *tx_buffer; - unsigned long txq_spinlock_flags; - - struct txq_entry_t *txq_head; - struct txq_entry_t *txq_tail; + struct txq_entry_t txq_head; int txq_entries; - int txq_exit; - - struct rxq_entry_t *rxq_head; - struct rxq_entry_t *rxq_tail; - int rxq_entries; - int rxq_exit; - unsigned char eth_src_address[NUM_CONCURRENT_IFC][6]; + struct rxq_entry_t rxq_head; const struct firmware *firmware; @@ -185,7 +176,7 @@ void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset); void wilc_mac_indicate(struct wilc *wilc); void wilc_netdev_cleanup(struct wilc *wilc); int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, - int gpio, const struct wilc_hif_func *ops); + const struct wilc_hif_func *ops); void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size); int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index d4ebbf67e50b..6787b6e9f124 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1,9 +1,21 @@ // SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + +#include <linux/if_ether.h> +#include <linux/ip.h> #include "wilc_wfi_netdevice.h" #include "wilc_wlan_cfg.h" static enum chip_ps_states chip_ps_state = CHIP_WAKEDUP; +static inline bool is_wilc1000(u32 id) +{ + return ((id & 0xfffff000) == 0x100000 ? true : false); +} + static inline void acquire_bus(struct wilc *wilc, enum bus_acquire acquire) { mutex_lock(&wilc->hif_cs); @@ -20,42 +32,25 @@ static inline void release_bus(struct wilc *wilc, enum bus_release release) static void wilc_wlan_txq_remove(struct wilc *wilc, struct txq_entry_t *tqe) { - if (tqe == wilc->txq_head) { - wilc->txq_head = tqe->next; - if (wilc->txq_head) - wilc->txq_head->prev = NULL; - } else if (tqe == wilc->txq_tail) { - wilc->txq_tail = (tqe->prev); - if (wilc->txq_tail) - wilc->txq_tail->next = NULL; - } else { - tqe->prev->next = tqe->next; - tqe->next->prev = tqe->prev; - } + list_del(&tqe->list); wilc->txq_entries -= 1; } static struct txq_entry_t * wilc_wlan_txq_remove_from_head(struct net_device *dev) { - struct txq_entry_t *tqe; + struct txq_entry_t *tqe = NULL; unsigned long flags; - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; spin_lock_irqsave(&wilc->txq_spinlock, flags); - if (wilc->txq_head) { - tqe = wilc->txq_head; - wilc->txq_head = tqe->next; - if (wilc->txq_head) - wilc->txq_head->prev = NULL; + if (!list_empty(&wilc->txq_head.list)) { + tqe = list_first_entry(&wilc->txq_head.list, struct txq_entry_t, + list); + list_del(&tqe->list); wilc->txq_entries -= 1; - } else { - tqe = NULL; } spin_unlock_irqrestore(&wilc->txq_spinlock, flags); return tqe; @@ -65,25 +60,12 @@ static void wilc_wlan_txq_add_to_tail(struct net_device *dev, struct txq_entry_t *tqe) { unsigned long flags; - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; spin_lock_irqsave(&wilc->txq_spinlock, flags); - if (!wilc->txq_head) { - tqe->next = NULL; - tqe->prev = NULL; - wilc->txq_head = tqe; - wilc->txq_tail = tqe; - } else { - tqe->next = NULL; - tqe->prev = wilc->txq_tail; - wilc->txq_tail->next = tqe; - wilc->txq_tail = tqe; - } + list_add_tail(&tqe->list, &wilc->txq_head.list); wilc->txq_entries += 1; spin_unlock_irqrestore(&wilc->txq_spinlock, flags); @@ -101,17 +83,7 @@ static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif, spin_lock_irqsave(&wilc->txq_spinlock, flags); - if (!wilc->txq_head) { - tqe->next = NULL; - tqe->prev = NULL; - wilc->txq_head = tqe; - wilc->txq_tail = tqe; - } else { - tqe->next = wilc->txq_head; - tqe->prev = NULL; - wilc->txq_head->prev = tqe; - wilc->txq_head = tqe; - } + list_add(&tqe->list, &wilc->txq_head.list); wilc->txq_entries += 1; spin_unlock_irqrestore(&wilc->txq_spinlock, flags); @@ -184,50 +156,32 @@ static inline int add_tcp_pending_ack(u32 ack, u32 session_index, static inline void tcp_process(struct net_device *dev, struct txq_entry_t *tqe) { - u8 *eth_hdr_ptr; - u8 *buffer = tqe->buffer; - unsigned short h_proto; + void *buffer = tqe->buffer; + const struct ethhdr *eth_hdr_ptr = buffer; int i; unsigned long flags; - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; spin_lock_irqsave(&wilc->txq_spinlock, flags); - eth_hdr_ptr = &buffer[0]; - h_proto = ntohs(*((unsigned short *)ð_hdr_ptr[12])); - if (h_proto == ETH_P_IP) { - u8 *ip_hdr_ptr; - u8 protocol; + if (eth_hdr_ptr->h_proto == htons(ETH_P_IP)) { + const struct iphdr *ip_hdr_ptr = buffer + ETH_HLEN; - ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN]; - protocol = ip_hdr_ptr[9]; - - if (protocol == 0x06) { - u8 *tcp_hdr_ptr; + if (ip_hdr_ptr->protocol == IPPROTO_TCP) { + const struct tcphdr *tcp_hdr_ptr; u32 IHL, total_length, data_offset; - tcp_hdr_ptr = &ip_hdr_ptr[IP_HDR_LEN]; - IHL = (ip_hdr_ptr[0] & 0xf) << 2; - total_length = ((u32)ip_hdr_ptr[2] << 8) + - (u32)ip_hdr_ptr[3]; - data_offset = ((u32)tcp_hdr_ptr[12] & 0xf0) >> 2; + IHL = ip_hdr_ptr->ihl << 2; + tcp_hdr_ptr = buffer + ETH_HLEN + IHL; + total_length = ntohs(ip_hdr_ptr->tot_len); + + data_offset = tcp_hdr_ptr->doff << 2; if (total_length == (IHL + data_offset)) { u32 seq_no, ack_no; - seq_no = ((u32)tcp_hdr_ptr[4] << 24) + - ((u32)tcp_hdr_ptr[5] << 16) + - ((u32)tcp_hdr_ptr[6] << 8) + - (u32)tcp_hdr_ptr[7]; - - ack_no = ((u32)tcp_hdr_ptr[8] << 24) + - ((u32)tcp_hdr_ptr[9] << 16) + - ((u32)tcp_hdr_ptr[10] << 8) + - (u32)tcp_hdr_ptr[11]; - + seq_no = ntohl(tcp_hdr_ptr->seq); + ack_no = ntohl(tcp_hdr_ptr->ack_seq); for (i = 0; i < tcp_session; i++) { u32 j = ack_session_info[i].seq_num; @@ -249,15 +203,13 @@ static inline void tcp_process(struct net_device *dev, struct txq_entry_t *tqe) static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) { - struct wilc_vif *vif; - struct wilc *wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; u32 i = 0; u32 dropped = 0; + unsigned long flags; - vif = netdev_priv(dev); - wilc = vif->wilc; - - spin_lock_irqsave(&wilc->txq_spinlock, wilc->txq_spinlock_flags); + spin_lock_irqsave(&wilc->txq_spinlock, flags); for (i = pending_base; i < (pending_base + pending_acks); i++) { u32 session_index; u32 bigger_ack_num; @@ -295,7 +247,7 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) else pending_base = 0; - spin_unlock_irqrestore(&wilc->txq_spinlock, wilc->txq_spinlock_flags); + spin_unlock_irqrestore(&wilc->txq_spinlock, flags); while (dropped > 0) { wait_for_completion_timeout(&wilc->txq_event, @@ -402,12 +354,14 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, static struct txq_entry_t *wilc_wlan_txq_get_first(struct wilc *wilc) { - struct txq_entry_t *tqe; + struct txq_entry_t *tqe = NULL; unsigned long flags; spin_lock_irqsave(&wilc->txq_spinlock, flags); - tqe = wilc->txq_head; + if (!list_empty(&wilc->txq_head.list)) + tqe = list_first_entry(&wilc->txq_head.list, struct txq_entry_t, + list); spin_unlock_irqrestore(&wilc->txq_spinlock, flags); @@ -421,45 +375,37 @@ static struct txq_entry_t *wilc_wlan_txq_get_next(struct wilc *wilc, spin_lock_irqsave(&wilc->txq_spinlock, flags); - tqe = tqe->next; + if (!list_is_last(&tqe->list, &wilc->txq_head.list)) + tqe = list_next_entry(tqe, list); + else + tqe = NULL; spin_unlock_irqrestore(&wilc->txq_spinlock, flags); return tqe; } -static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe) +static void wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe) { if (wilc->quit) - return 0; + return; mutex_lock(&wilc->rxq_cs); - if (!wilc->rxq_head) { - rqe->next = NULL; - wilc->rxq_head = rqe; - wilc->rxq_tail = rqe; - } else { - wilc->rxq_tail->next = rqe; - rqe->next = NULL; - wilc->rxq_tail = rqe; - } - wilc->rxq_entries += 1; + list_add_tail(&rqe->list, &wilc->rxq_head.list); mutex_unlock(&wilc->rxq_cs); - return wilc->rxq_entries; } static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) { - if (wilc->rxq_head) { - struct rxq_entry_t *rqe; - - mutex_lock(&wilc->rxq_cs); - rqe = wilc->rxq_head; - wilc->rxq_head = wilc->rxq_head->next; - wilc->rxq_entries -= 1; - mutex_unlock(&wilc->rxq_cs); - return rqe; + struct rxq_entry_t *rqe = NULL; + + mutex_lock(&wilc->rxq_cs); + if (!list_empty(&wilc->rxq_head.list)) { + rqe = list_first_entry(&wilc->rxq_head.list, struct rxq_entry_t, + list); + list_del(&rqe->list); } - return NULL; + mutex_unlock(&wilc->rxq_cs); + return rqe; } void chip_allow_sleep(struct wilc *wilc) @@ -471,7 +417,6 @@ void chip_allow_sleep(struct wilc *wilc) wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0)); wilc->hif_func->hif_write_reg(wilc, 0xfa, 0); } -EXPORT_SYMBOL_GPL(chip_allow_sleep); void chip_wakeup(struct wilc *wilc) { @@ -488,7 +433,7 @@ void chip_wakeup(struct wilc *wilc) wilc_get_chipid(wilc, true); } while (wilc_get_chipid(wilc, true) == 0); } while (wilc_get_chipid(wilc, true) == 0); - } else if ((wilc->io_type & 0x1) == HIF_SDIO) { + } else if ((wilc->io_type & 0x1) == HIF_SDIO) { wilc->hif_func->hif_write_reg(wilc, 0xfa, 1); udelay(200); wilc->hif_func->hif_read_reg(wilc, 0xf0, ®); @@ -526,7 +471,6 @@ void chip_wakeup(struct wilc *wilc) } chip_ps_state = CHIP_WAKEDUP; } -EXPORT_SYMBOL_GPL(chip_wakeup); void wilc_chip_sleep_manually(struct wilc *wilc) { @@ -540,7 +484,6 @@ void wilc_chip_sleep_manually(struct wilc *wilc) chip_ps_state = CHIP_SLEEPING_MANUAL; release_bus(wilc, RELEASE_ONLY); } -EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually); void host_wakeup_notify(struct wilc *wilc) { @@ -548,7 +491,6 @@ void host_wakeup_notify(struct wilc *wilc) wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1); release_bus(wilc, RELEASE_ONLY); } -EXPORT_SYMBOL_GPL(host_wakeup_notify); void host_sleep_notify(struct wilc *wilc) { @@ -556,14 +498,12 @@ void host_sleep_notify(struct wilc *wilc) wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1); release_bus(wilc, RELEASE_ONLY); } -EXPORT_SYMBOL_GPL(host_sleep_notify); int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) { int i, entries = 0; u32 sum; u32 reg; - u8 *txb; u32 offset = 0; int vmm_sz = 0; struct txq_entry_t *tqe; @@ -571,15 +511,10 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) int counter; int timeout; u32 vmm_table[WILC_VMM_TBL_SIZE]; - struct wilc_vif *vif; - struct wilc *wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; const struct wilc_hif_func *func; - - vif = netdev_priv(dev); - wilc = vif->wilc; - - txb = wilc->tx_buffer; - wilc->txq_exit = 0; + u8 *txb = wilc->tx_buffer; if (wilc->quit) goto out; @@ -611,7 +546,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) vmm_table[i] = vmm_sz / 4; if (tqe->type == WILC_CFG_PKT) vmm_table[i] |= BIT(10); - vmm_table[i] = cpu_to_le32(vmm_table[i]); + cpu_to_le32s(&vmm_table[i]); i++; sum += vmm_sz; @@ -714,7 +649,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (vmm_table[i] == 0) break; - vmm_table[i] = cpu_to_le32(vmm_table[i]); + le32_to_cpus(&vmm_table[i]); vmm_sz = (vmm_table[i] & 0x3ff); vmm_sz *= 4; header = (tqe->type << 31) | @@ -725,7 +660,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) else header &= ~BIT(30); - header = cpu_to_le32(header); + cpu_to_le32s(&header); memcpy(&txb[offset], &header, 4); if (tqe->type == WILC_CFG_PKT) { buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET; @@ -765,7 +700,6 @@ out_release_bus: out: mutex_unlock(&wilc->txq_add_to_head_cs); - wilc->txq_exit = 1; *txq_count = wilc->txq_entries; return ret; } @@ -781,7 +715,7 @@ static void wilc_wlan_handle_rx_buff(struct wilc *wilc, u8 *buffer, int size) do { buff_ptr = buffer + offset; memcpy(&header, buff_ptr, 4); - header = cpu_to_le32(header); + le32_to_cpus(&header); is_cfg_packet = (header >> 31) & 0x1; pkt_offset = (header >> 22) & 0x1ff; @@ -832,8 +766,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) u8 *buffer; struct rxq_entry_t *rqe; - wilc->rxq_exit = 0; - do { if (wilc->quit) { complete(&wilc->cfg_event); @@ -849,8 +781,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) kfree(rqe); } while (1); - - wilc->rxq_exit = 1; } static void wilc_unknown_isr_ext(struct wilc *wilc) @@ -869,7 +799,7 @@ static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats) else mdelay(WILC_PLL_TO_SPI); - while (!(ISWILC1000(wilc_get_chipid(wilc, true)) && --trials)) + while (!(is_wilc1000(wilc_get_chipid(wilc, true)) && --trials)) mdelay(1); } @@ -895,31 +825,28 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) retries++; } - if (size > 0) { - if (LINUX_RX_SIZE - offset < size) - offset = 0; + if (size <= 0) + return; - if (wilc->rx_buffer) - buffer = &wilc->rx_buffer[offset]; - else - goto _end_; - - wilc->hif_func->hif_clear_int_ext(wilc, - DATA_INT_CLR | ENABLE_RX_VMM); - ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size); - -_end_: - if (ret) { - offset += size; - wilc->rx_buffer_offset = offset; - rqe = kmalloc(sizeof(*rqe), GFP_KERNEL); - if (rqe) { - rqe->buffer = buffer; - rqe->buffer_size = size; - wilc_wlan_rxq_add(wilc, rqe); - } - } - } + if (LINUX_RX_SIZE - offset < size) + offset = 0; + + buffer = &wilc->rx_buffer[offset]; + + wilc->hif_func->hif_clear_int_ext(wilc, DATA_INT_CLR | ENABLE_RX_VMM); + ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size); + if (!ret) + return; + + offset += size; + wilc->rx_buffer_offset = offset; + rqe = kmalloc(sizeof(*rqe), GFP_KERNEL); + if (!rqe) + return; + + rqe->buffer = buffer; + rqe->buffer_size = size; + wilc_wlan_rxq_add(wilc, rqe); wilc_wlan_handle_rxq(wilc); } @@ -944,7 +871,6 @@ void wilc_handle_isr(struct wilc *wilc) release_bus(wilc, RELEASE_ALLOW_SLEEP); } -EXPORT_SYMBOL_GPL(wilc_handle_isr); int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size) @@ -964,8 +890,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, do { memcpy(&addr, &buffer[offset], 4); memcpy(&size, &buffer[offset + 4], 4); - addr = cpu_to_le32(addr); - size = cpu_to_le32(size); + le32_to_cpus(&addr); + le32_to_cpus(&size); acquire_bus(wilc, ACQUIRE_ONLY); offset += 8; while (((int)size) && (offset < buffer_size)) { @@ -1139,11 +1065,8 @@ void wilc_wlan_cleanup(struct net_device *dev) struct rxq_entry_t *rqe; u32 reg = 0; int ret; - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; wilc->quit = 1; do { @@ -1232,10 +1155,7 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, if (!commit) return ret_size; - netdev_dbg(vif->ndev, - "[WILC]PACKET Commit with sequence number %d\n", - wilc->cfg_seq_no); - netdev_dbg(vif->ndev, "Processing cfg_set()\n"); + netdev_dbg(vif->ndev, "%s: seqno[%d]\n", __func__, wilc->cfg_seq_no); wilc->cfg_frame_in_use = 1; if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler)) @@ -1243,7 +1163,7 @@ int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer, if (!wait_for_completion_timeout(&wilc->cfg_event, msecs_to_jiffies(CFG_PKTS_TIMEOUT))) { - netdev_dbg(vif->ndev, "Set Timed Out\n"); + netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__); ret_size = 0; } @@ -1282,7 +1202,7 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit, if (!wait_for_completion_timeout(&wilc->cfg_event, msecs_to_jiffies(CFG_PKTS_TIMEOUT))) { - netdev_dbg(vif->ndev, "Get Timed Out\n"); + netdev_dbg(vif->ndev, "%s: Timed Out\n", __func__); ret_size = 0; } wilc->cfg_frame_in_use = 0; @@ -1339,11 +1259,8 @@ static u32 init_chip(struct net_device *dev) { u32 chipid; u32 reg, ret = 0; - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; + struct wilc_vif *vif = netdev_priv(dev); + struct wilc *wilc = vif->wilc; acquire_bus(wilc, ACQUIRE_ONLY); @@ -1382,7 +1299,7 @@ u32 wilc_get_chipid(struct wilc *wilc, bool update) if (chipid == 0 || update) { wilc->hif_func->hif_read_reg(wilc, 0x1000, &tempchipid); wilc->hif_func->hif_read_reg(wilc, 0x13f4, &rfrevid); - if (!ISWILC1000(tempchipid)) { + if (!is_wilc1000(tempchipid)) { chipid = 0; return chipid; } diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index a5b9c68e1b9c..7467188dbf2f 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -1,11 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ + #ifndef WILC_WLAN_H #define WILC_WLAN_H #include <linux/types.h> -#define ISWILC1000(id) ((id & 0xfffff000) == 0x100000 ? 1 : 0) - /******************************************** * * Mac eth header length @@ -207,8 +210,7 @@ ********************************************/ struct txq_entry_t { - struct txq_entry_t *next; - struct txq_entry_t *prev; + struct list_head list; int type; int tcp_pending_ack_idx; u8 *buffer; @@ -219,7 +221,7 @@ struct txq_entry_t { }; struct rxq_entry_t { - struct rxq_entry_t *next; + struct list_head list; u8 *buffer; int buffer_size; }; @@ -247,18 +249,9 @@ struct wilc_hif_func { void (*disable_interrupt)(struct wilc *nic); }; -/******************************************** - * - * Configuration Structure - * - ********************************************/ - #define MAX_CFG_FRAME_SIZE 1468 struct wilc_cfg_frame { - u8 ether_header[14]; - u8 ip_header[20]; - u8 udp_header[8]; u8 wid_header[8]; u8 frame[MAX_CFG_FRAME_SIZE]; }; diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index c0b9b700f4d7..421576386ab4 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -1,23 +1,14 @@ // SPDX-License-Identifier: GPL-2.0 -/* ////////////////////////////////////////////////////////////////////////// */ -/* */ -/* Copyright (c) Atmel Corporation. All rights reserved. */ -/* */ -/* Module Name: wilc_wlan_cfg.c */ -/* */ -/* */ -/* ///////////////////////////////////////////////////////////////////////// */ +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ #include "wilc_wlan_if.h" #include "wilc_wlan.h" #include "wilc_wlan_cfg.h" #include "coreconfigurator.h" -/******************************************** - * - * Global Data - * - ********************************************/ enum cfg_cmd_type { CFG_BYTE_CMD = 0, CFG_HWORD_CMD = 1, @@ -273,16 +264,17 @@ static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) * ********************************************/ +#define GET_WID_TYPE(wid) (((wid) >> 12) & 0x7) static void wilc_wlan_parse_response_frame(u8 *info, int size) { - u32 wid, len = 0, i = 0; + u16 wid; + u32 len = 0, i = 0; while (size > 0) { i = 0; wid = info[0] | (info[1] << 8); - wid = cpu_to_le32(wid); - switch ((wid >> 12) & 0x7) { + switch (GET_WID_TYPE(wid)) { case WID_CHAR: do { if (g_cfg_byte[i].id == WID_NIL) @@ -303,9 +295,8 @@ static void wilc_wlan_parse_response_frame(u8 *info, int size) break; if (g_cfg_hword[i].id == wid) { - g_cfg_hword[i].val = - cpu_to_le16(info[4] | - (info[5] << 8)); + g_cfg_hword[i].val = (info[4] | + (info[5] << 8)); break; } i++; @@ -319,11 +310,10 @@ static void wilc_wlan_parse_response_frame(u8 *info, int size) break; if (g_cfg_word[i].id == wid) { - g_cfg_word[i].val = - cpu_to_le32(info[4] | - (info[5] << 8) | - (info[6] << 16) | - (info[7] << 24)); + g_cfg_word[i].val = (info[4] | + (info[5] << 8) | + (info[6] << 16) | + (info[7] << 24)); break; } i++; diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.h b/drivers/staging/wilc1000/wilc_wlan_cfg.h index 08092a551840..0c649d1f6f11 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.h +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.h @@ -1,12 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* */ -/* Copyright (c) Atmel Corporation. All rights reserved. */ -/* */ -/* Module Name: wilc_wlan_cfg.h */ -/* */ -/* */ -/* ///////////////////////////////////////////////////////////////////////// */ +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ #ifndef WILC_WLAN_CFG_H #define WILC_WLAN_CFG_H @@ -22,12 +18,12 @@ struct wilc_cfg_hword { }; struct wilc_cfg_word { - u32 id; + u16 id; u32 val; }; struct wilc_cfg_str { - u32 id; + u16 id; u8 *str; }; diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index e4a7bf5df65b..00d13b153f80 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -1,12 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* ///////////////////////////////////////////////////////////////////////// */ -/* */ -/* Copyright (c) Atmel Corporation. All rights reserved. */ -/* */ -/* Module Name: wilc_wlan_if.h */ -/* */ -/* */ -/* ///////////////////////////////////////////////////////////////////////// */ +/* + * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. + * All rights reserved. + */ #ifndef WILC_WLAN_IF_H #define WILC_WLAN_IF_H @@ -71,16 +67,6 @@ typedef void (*wilc_tx_complete_func_t)(void *, int); #define MAX_SSID_LEN 33 #define MAX_RATES_SUPPORTED 12 -enum { - SUPP_RATES_IE = 1, - EXT_SUPP_RATES_IE = 50, - HT_CAPABILITY_IE = 45, - RSN_IE = 48, - WPA_IE = 221, - WMM_IE = 221, - P2P_IE = 221, -}; - enum bss_types { INFRASTRUCTURE = 0, INDEPENDENT, @@ -88,22 +74,6 @@ enum bss_types { }; enum { - RATE_AUTO = 0, - RATE_1MB = 1, - RATE_2MB = 2, - RATE_5MB = 5, - RATE_6MB = 6, - RATE_9MB = 9, - RATE_11MB = 11, - RATE_12MB = 12, - RATE_18MB = 18, - RATE_24MB = 24, - RATE_26MB = 36, - RATE_48MB = 48, - RATE_54MB = 54 -}; - -enum { B_ONLY_MODE = 0, /* 1, 2 M, otherwise 5, 11 M */ G_ONLY_MODE, /* 6,12,24 otherwise 9,18,36,48,54 */ G_MIXED_11B_1_MODE, /* 1,2,5.5,11 otherwise all on */ @@ -157,14 +127,14 @@ enum { WPA2_AES_TKIP = 0x71, /* Aes or Tkip */ }; -enum AUTHTYPE { +enum authtype { OPEN_SYSTEM = 1, SHARED_KEY = 2, ANY = 3, IEEE8021 = 5 }; -enum SITESURVEY { +enum site_survey { SITE_SURVEY_1CH = 0, SITE_SURVEY_ALL_CH = 1, SITE_SURVEY_OFF = 2 @@ -176,12 +146,6 @@ enum { }; enum { - DONT_RESET = 0, - DO_RESET = 1, - NO_REQUEST = 2, -}; - -enum { REKEY_DISABLE = 1, REKEY_TIME_BASE, REKEY_PKT_BASE, @@ -195,17 +159,6 @@ enum { }; enum { - PRI_HIGH_RSSI = 0x00, - PRI_LOW_RSSI = 0x04, - PRI_DETECT = 0x08 -}; - -enum { - CH_FILTER_OFF = 0x00, - CH_FILTER_ON = 0x10 -}; - -enum { AUTO_PROT = 0, /* Auto */ NO_PROT, /* Do not use any protection */ ERP_PROT, /* Protect all ERP frame exchanges */ @@ -244,15 +197,6 @@ enum { MIMO_MODE = 3, /* power save disable */ }; -enum { - DISABLE_SELF_CTS, - ENABLE_SELF_CTS, - DISABLE_TX_ABORT, - ENABLE_TX_ABORT, - HW_TRIGGER_ABORT, - SW_TRIGGER_ABORT, -}; - enum wid_type { WID_CHAR = 0, WID_SHORT = 1, @@ -887,4 +831,6 @@ struct wilc; int wilc_wlan_init(struct net_device *dev); u32 wilc_get_chipid(struct wilc *wilc, bool update); +int wilc_debugfs_init(void); +void wilc_debugfs_remove(void); #endif |