wilc1000: move wilc driver out of staging
WILC1000 is an IEEE 802.11 b/g/n IoT link controller module. The WILC1000 connects to Microchip AVR/SMART MCUs, SMART MPUs, and other processors with minimal resource requirements with a simple SPI/SDIO-to-Wi-Fi interface. WILC1000 driver has been part of staging for few years. With contributions from the community, it has improved significantly. Full driver review has helped in achieving the current state. The details for those reviews are captured in 1 & 2. [1]. https://lore.kernel.org/linux-wireless/1537957525-11467-1-git-send-email-ajay.kathat@microchip.com/ [2]. https://lore.kernel.org/linux-wireless/1562896697-8002-1-git-send-email-ajay.kathat@microchip.com/ Signed-off-by: Ajay Singh <ajay.kathat@microchip.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
15
drivers/net/wireless/microchip/Kconfig
Normal file
15
drivers/net/wireless/microchip/Kconfig
Normal file
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
config WLAN_VENDOR_MICROCHIP
|
||||
bool "Microchip devices"
|
||||
default y
|
||||
help
|
||||
If you have a wireless card belonging to this class, say Y.
|
||||
|
||||
Note that the answer to this question doesn't directly affect the
|
||||
kernel: saying N will just cause the configurator to skip all the
|
||||
questions about these cards. If you say Y, you will be asked for
|
||||
your specific card in the following questions.
|
||||
|
||||
if WLAN_VENDOR_MICROCHIP
|
||||
source "drivers/net/wireless/microchip/wilc1000/Kconfig"
|
||||
endif # WLAN_VENDOR_MICROCHIP
|
2
drivers/net/wireless/microchip/Makefile
Normal file
2
drivers/net/wireless/microchip/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_WILC1000) += wilc1000/
|
47
drivers/net/wireless/microchip/wilc1000/Kconfig
Normal file
47
drivers/net/wireless/microchip/wilc1000/Kconfig
Normal file
@@ -0,0 +1,47 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
config WILC1000
|
||||
tristate
|
||||
help
|
||||
Add support for the Atmel WILC1000 802.11 b/g/n SoC.
|
||||
This provides Wi-FI over an SDIO or SPI interface, and
|
||||
is usually found in IoT devices.
|
||||
|
||||
This module only support IEEE 802.11n WiFi.
|
||||
|
||||
config WILC1000_SDIO
|
||||
tristate "Atmel WILC1000 SDIO (WiFi only)"
|
||||
depends on CFG80211 && INET && MMC
|
||||
select WILC1000
|
||||
help
|
||||
This module adds support for the SDIO interface of adapters using
|
||||
WILC1000 chipset. The Atmel WILC1000 SDIO is a full speed interface.
|
||||
It meets SDIO card specification version 2.0. The interface supports
|
||||
the 1-bit/4-bit SD transfer mode at the clock range of 0-50 MHz.
|
||||
The host can use this interface to read and write from any register
|
||||
within the chip as well as configure the WILC1000 for data DMA.
|
||||
To use this interface, pin9 (SDIO_SPI_CFG) must be grounded. Select
|
||||
this if your platform is using the SDIO bus.
|
||||
|
||||
config WILC1000_SPI
|
||||
tristate "Atmel WILC1000 SPI (WiFi only)"
|
||||
depends on CFG80211 && INET && SPI
|
||||
select WILC1000
|
||||
select CRC7
|
||||
help
|
||||
This module adds support for the SPI interface of adapters using
|
||||
WILC1000 chipset. The Atmel WILC1000 has a Serial Peripheral
|
||||
Interface (SPI) that operates as a SPI slave. This SPI interface can
|
||||
be used for control and for serial I/O of 802.11 data. The SPI is a
|
||||
full-duplex slave synchronous serial interface that is available
|
||||
immediately following reset when pin 9 (SDIO_SPI_CFG) is tied to
|
||||
VDDIO. Select this if your platform is using the SPI bus.
|
||||
|
||||
config WILC1000_HW_OOB_INTR
|
||||
bool "WILC1000 out of band interrupt"
|
||||
depends on WILC1000_SDIO
|
||||
help
|
||||
This option enables out-of-band interrupt support for the WILC1000
|
||||
chipset. This OOB interrupt is intended to provide a faster interrupt
|
||||
mechanism for SDIO host controllers that don't support SDIO interrupt.
|
||||
Select this option If the SDIO host controller in your platform
|
||||
doesn't support SDIO time devision interrupt.
|
14
drivers/net/wireless/microchip/wilc1000/Makefile
Normal file
14
drivers/net/wireless/microchip/wilc1000/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
# 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\"
|
||||
|
||||
wilc1000-objs := cfg80211.o netdev.o mon.o \
|
||||
hif.o wlan_cfg.o wlan.o
|
||||
|
||||
obj-$(CONFIG_WILC1000_SDIO) += wilc1000-sdio.o
|
||||
wilc1000-sdio-objs += sdio.o
|
||||
|
||||
obj-$(CONFIG_WILC1000_SPI) += wilc1000-spi.o
|
||||
wilc1000-spi-objs += spi.o
|
1847
drivers/net/wireless/microchip/wilc1000/cfg80211.c
Normal file
1847
drivers/net/wireless/microchip/wilc1000/cfg80211.c
Normal file
File diff suppressed because it is too large
Load Diff
30
drivers/net/wireless/microchip/wilc1000/cfg80211.h
Normal file
30
drivers/net/wireless/microchip/wilc1000/cfg80211.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef WILC_CFG80211_H
|
||||
#define WILC_CFG80211_H
|
||||
#include "netdev.h"
|
||||
|
||||
struct wiphy *wilc_cfg_alloc(void);
|
||||
int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
|
||||
const struct wilc_hif_func *ops);
|
||||
struct wilc *wilc_create_wiphy(struct device *dev);
|
||||
void wilc_deinit_host_int(struct net_device *net);
|
||||
int wilc_init_host_int(struct net_device *net);
|
||||
void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size);
|
||||
struct wilc_vif *wilc_netdev_interface(struct wilc *wl, const char *name,
|
||||
enum nl80211_iftype type);
|
||||
void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked);
|
||||
struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
|
||||
const char *name,
|
||||
struct net_device *real_dev);
|
||||
void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
struct mgmt_frame_regs *upd);
|
||||
struct wilc_vif *wilc_get_interface(struct wilc *wl);
|
||||
struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl);
|
||||
void wlan_deinit_locks(struct wilc *wilc);
|
||||
#endif
|
119
drivers/net/wireless/microchip/wilc1000/fw.h
Normal file
119
drivers/net/wireless/microchip/wilc1000/fw.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef WILC_FW_H
|
||||
#define WILC_FW_H
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
|
||||
#define WILC_MAX_NUM_STA 9
|
||||
#define WILC_MAX_RATES_SUPPORTED 12
|
||||
#define WILC_MAX_NUM_PMKIDS 16
|
||||
#define WILC_MAX_NUM_SCANNED_CH 14
|
||||
|
||||
struct wilc_assoc_resp {
|
||||
__le16 capab_info;
|
||||
__le16 status_code;
|
||||
__le16 aid;
|
||||
} __packed;
|
||||
|
||||
struct wilc_pmkid {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 pmkid[WLAN_PMKID_LEN];
|
||||
} __packed;
|
||||
|
||||
struct wilc_pmkid_attr {
|
||||
u8 numpmkid;
|
||||
struct wilc_pmkid pmkidlist[WILC_MAX_NUM_PMKIDS];
|
||||
} __packed;
|
||||
|
||||
struct wilc_reg_frame {
|
||||
u8 reg;
|
||||
u8 reg_id;
|
||||
__le16 frame_type;
|
||||
} __packed;
|
||||
|
||||
struct wilc_drv_handler {
|
||||
__le32 handler;
|
||||
u8 mode;
|
||||
} __packed;
|
||||
|
||||
struct wilc_wep_key {
|
||||
u8 index;
|
||||
u8 key_len;
|
||||
u8 key[0];
|
||||
} __packed;
|
||||
|
||||
struct wilc_sta_wpa_ptk {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 key_len;
|
||||
u8 key[0];
|
||||
} __packed;
|
||||
|
||||
struct wilc_ap_wpa_ptk {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 index;
|
||||
u8 key_len;
|
||||
u8 key[0];
|
||||
} __packed;
|
||||
|
||||
struct wilc_gtk_key {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 rsc[8];
|
||||
u8 index;
|
||||
u8 key_len;
|
||||
u8 key[0];
|
||||
} __packed;
|
||||
|
||||
struct wilc_op_mode {
|
||||
__le32 mode;
|
||||
} __packed;
|
||||
|
||||
struct wilc_noa_opp_enable {
|
||||
u8 ct_window;
|
||||
u8 cnt;
|
||||
__le32 duration;
|
||||
__le32 interval;
|
||||
__le32 start_time;
|
||||
} __packed;
|
||||
|
||||
struct wilc_noa_opp_disable {
|
||||
u8 cnt;
|
||||
__le32 duration;
|
||||
__le32 interval;
|
||||
__le32 start_time;
|
||||
} __packed;
|
||||
|
||||
struct wilc_join_bss_param {
|
||||
char ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 ssid_terminator;
|
||||
u8 bss_type;
|
||||
u8 ch;
|
||||
__le16 cap_info;
|
||||
u8 sa[ETH_ALEN];
|
||||
u8 bssid[ETH_ALEN];
|
||||
__le16 beacon_period;
|
||||
u8 dtim_period;
|
||||
u8 supp_rates[WILC_MAX_RATES_SUPPORTED + 1];
|
||||
u8 wmm_cap;
|
||||
u8 uapsd_cap;
|
||||
u8 ht_capable;
|
||||
u8 rsn_found;
|
||||
u8 rsn_grp_policy;
|
||||
u8 mode_802_11i;
|
||||
u8 p_suites[3];
|
||||
u8 akm_suites[3];
|
||||
u8 rsn_cap[2];
|
||||
u8 noa_enabled;
|
||||
__le32 tsf_lo;
|
||||
u8 idx;
|
||||
u8 opp_enabled;
|
||||
union {
|
||||
struct wilc_noa_opp_disable opp_dis;
|
||||
struct wilc_noa_opp_enable opp_en;
|
||||
};
|
||||
} __packed;
|
||||
#endif
|
1961
drivers/net/wireless/microchip/wilc1000/hif.c
Normal file
1961
drivers/net/wireless/microchip/wilc1000/hif.c
Normal file
File diff suppressed because it is too large
Load Diff
214
drivers/net/wireless/microchip/wilc1000/hif.h
Normal file
214
drivers/net/wireless/microchip/wilc1000/hif.h
Normal file
@@ -0,0 +1,214 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef WILC_HIF_H
|
||||
#define WILC_HIF_H
|
||||
#include <linux/ieee80211.h>
|
||||
#include "wlan_if.h"
|
||||
|
||||
enum {
|
||||
WILC_IDLE_MODE = 0x0,
|
||||
WILC_AP_MODE = 0x1,
|
||||
WILC_STATION_MODE = 0x2,
|
||||
WILC_GO_MODE = 0x3,
|
||||
WILC_CLIENT_MODE = 0x4
|
||||
};
|
||||
|
||||
#define WILC_MAX_NUM_PROBED_SSID 10
|
||||
|
||||
#define WILC_TX_MIC_KEY_LEN 8
|
||||
#define WILC_RX_MIC_KEY_LEN 8
|
||||
|
||||
#define WILC_ADD_STA_LENGTH 40
|
||||
#define WILC_NUM_CONCURRENT_IFC 2
|
||||
|
||||
enum {
|
||||
WILC_SET_CFG = 0,
|
||||
WILC_GET_CFG
|
||||
};
|
||||
|
||||
#define WILC_MAX_ASSOC_RESP_FRAME_SIZE 256
|
||||
|
||||
struct rf_info {
|
||||
u8 link_speed;
|
||||
s8 rssi;
|
||||
u32 tx_cnt;
|
||||
u32 rx_cnt;
|
||||
u32 tx_fail_cnt;
|
||||
};
|
||||
|
||||
enum host_if_state {
|
||||
HOST_IF_IDLE = 0,
|
||||
HOST_IF_SCANNING = 1,
|
||||
HOST_IF_CONNECTING = 2,
|
||||
HOST_IF_WAITING_CONN_RESP = 3,
|
||||
HOST_IF_CONNECTED = 4,
|
||||
HOST_IF_P2P_LISTEN = 5,
|
||||
HOST_IF_FORCE_32BIT = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
struct cfg_param_attr {
|
||||
u32 flag;
|
||||
u16 short_retry_limit;
|
||||
u16 long_retry_limit;
|
||||
u16 frag_threshold;
|
||||
u16 rts_threshold;
|
||||
};
|
||||
|
||||
enum cfg_param {
|
||||
WILC_CFG_PARAM_RETRY_SHORT = BIT(0),
|
||||
WILC_CFG_PARAM_RETRY_LONG = BIT(1),
|
||||
WILC_CFG_PARAM_FRAG_THRESHOLD = BIT(2),
|
||||
WILC_CFG_PARAM_RTS_THRESHOLD = BIT(3)
|
||||
};
|
||||
|
||||
enum scan_event {
|
||||
SCAN_EVENT_NETWORK_FOUND = 0,
|
||||
SCAN_EVENT_DONE = 1,
|
||||
SCAN_EVENT_ABORTED = 2,
|
||||
SCAN_EVENT_FORCE_32BIT = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
enum conn_event {
|
||||
CONN_DISCONN_EVENT_CONN_RESP = 0,
|
||||
CONN_DISCONN_EVENT_DISCONN_NOTIF = 1,
|
||||
CONN_DISCONN_EVENT_FORCE_32BIT = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_HIF_SDIO = 0,
|
||||
WILC_HIF_SPI = BIT(0)
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_MAC_STATUS_INIT = -1,
|
||||
WILC_MAC_STATUS_DISCONNECTED = 0,
|
||||
WILC_MAC_STATUS_CONNECTED = 1
|
||||
};
|
||||
|
||||
struct wilc_rcvd_net_info {
|
||||
s8 rssi;
|
||||
u8 ch;
|
||||
u16 frame_len;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
};
|
||||
|
||||
struct wilc_user_scan_req {
|
||||
void (*scan_result)(enum scan_event evt,
|
||||
struct wilc_rcvd_net_info *info, void *priv);
|
||||
void *arg;
|
||||
u32 ch_cnt;
|
||||
};
|
||||
|
||||
struct wilc_conn_info {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 security;
|
||||
enum authtype auth_type;
|
||||
u8 ch;
|
||||
u8 *req_ies;
|
||||
size_t req_ies_len;
|
||||
u8 *resp_ies;
|
||||
u16 resp_ies_len;
|
||||
u16 status;
|
||||
void (*conn_result)(enum conn_event evt, u8 status, void *priv_data);
|
||||
void *arg;
|
||||
void *param;
|
||||
};
|
||||
|
||||
struct wilc_remain_ch {
|
||||
u16 ch;
|
||||
u32 duration;
|
||||
void (*expired)(void *priv, u64 cookie);
|
||||
void *arg;
|
||||
u32 cookie;
|
||||
};
|
||||
|
||||
struct wilc;
|
||||
struct host_if_drv {
|
||||
struct wilc_user_scan_req usr_scan_req;
|
||||
struct wilc_conn_info conn_info;
|
||||
struct wilc_remain_ch remain_on_ch;
|
||||
u64 p2p_timeout;
|
||||
|
||||
enum host_if_state hif_state;
|
||||
|
||||
u8 assoc_bssid[ETH_ALEN];
|
||||
|
||||
struct timer_list scan_timer;
|
||||
struct wilc_vif *scan_timer_vif;
|
||||
|
||||
struct timer_list connect_timer;
|
||||
struct wilc_vif *connect_timer_vif;
|
||||
|
||||
struct timer_list remain_on_ch_timer;
|
||||
struct wilc_vif *remain_on_ch_timer_vif;
|
||||
|
||||
bool ifc_up;
|
||||
u8 assoc_resp[WILC_MAX_ASSOC_RESP_FRAME_SIZE];
|
||||
};
|
||||
|
||||
struct wilc_vif;
|
||||
int wilc_remove_wep_key(struct wilc_vif *vif, u8 index);
|
||||
int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index);
|
||||
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);
|
||||
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);
|
||||
s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac,
|
||||
u32 *out_val);
|
||||
int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
|
||||
u8 index, u32 key_rsc_len, const u8 *key_rsc,
|
||||
const u8 *rx_mic, const u8 *tx_mic, u8 mode,
|
||||
u8 cipher_mode);
|
||||
int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid);
|
||||
int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr);
|
||||
int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
|
||||
size_t ies_len);
|
||||
int wilc_disconnect(struct wilc_vif *vif);
|
||||
int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel);
|
||||
int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level);
|
||||
int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
|
||||
u8 *ch_freq_list, u8 ch_list_len,
|
||||
void (*scan_result_fn)(enum scan_event,
|
||||
struct wilc_rcvd_net_info *, void *),
|
||||
void *user_arg, struct cfg80211_scan_request *request);
|
||||
int wilc_hif_set_cfg(struct wilc_vif *vif,
|
||||
struct cfg_param_attr *cfg_param);
|
||||
int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler);
|
||||
int wilc_deinit(struct wilc_vif *vif);
|
||||
int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
|
||||
struct cfg80211_beacon_data *params);
|
||||
int wilc_del_beacon(struct wilc_vif *vif);
|
||||
int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
|
||||
struct station_parameters *params);
|
||||
int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]);
|
||||
int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr);
|
||||
int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
|
||||
struct station_parameters *params);
|
||||
int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout);
|
||||
int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
|
||||
u8 *mc_list);
|
||||
int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
|
||||
u32 duration, u16 chan,
|
||||
void (*expired)(void *, u64),
|
||||
void *user_arg);
|
||||
int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie);
|
||||
void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg);
|
||||
int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode,
|
||||
u8 ifc_id);
|
||||
int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats);
|
||||
int wilc_get_vif_idx(struct wilc_vif *vif);
|
||||
int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power);
|
||||
int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power);
|
||||
void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length);
|
||||
void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length);
|
||||
void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length);
|
||||
void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
|
||||
struct cfg80211_crypto_settings *crypto);
|
||||
#endif
|
260
drivers/net/wireless/microchip/wilc1000/mon.c
Normal file
260
drivers/net/wireless/microchip/wilc1000/mon.c
Normal file
@@ -0,0 +1,260 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "cfg80211.h"
|
||||
|
||||
struct wilc_wfi_radiotap_hdr {
|
||||
struct ieee80211_radiotap_header hdr;
|
||||
u8 rate;
|
||||
} __packed;
|
||||
|
||||
struct wilc_wfi_radiotap_cb_hdr {
|
||||
struct ieee80211_radiotap_header hdr;
|
||||
u8 rate;
|
||||
u8 dump;
|
||||
u16 tx_flags;
|
||||
} __packed;
|
||||
|
||||
#define TX_RADIOTAP_PRESENT ((1 << IEEE80211_RADIOTAP_RATE) | \
|
||||
(1 << IEEE80211_RADIOTAP_TX_FLAGS))
|
||||
|
||||
void wilc_wfi_monitor_rx(struct net_device *mon_dev, u8 *buff, u32 size)
|
||||
{
|
||||
u32 header, pkt_offset;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct wilc_wfi_radiotap_hdr *hdr;
|
||||
struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
|
||||
|
||||
if (!mon_dev)
|
||||
return;
|
||||
|
||||
if (!netif_running(mon_dev))
|
||||
return;
|
||||
|
||||
/* Get WILC header */
|
||||
header = get_unaligned_le32(buff - HOST_HDR_OFFSET);
|
||||
/*
|
||||
* The packet offset field contain info about what type of management
|
||||
* the frame we are dealing with and ack status
|
||||
*/
|
||||
pkt_offset = FIELD_GET(WILC_PKT_HDR_OFFSET_FIELD, header);
|
||||
|
||||
if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {
|
||||
/* hostapd callback mgmt frame */
|
||||
|
||||
skb = dev_alloc_skb(size + sizeof(*cb_hdr));
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
skb_put_data(skb, buff, size);
|
||||
|
||||
cb_hdr = skb_push(skb, sizeof(*cb_hdr));
|
||||
memset(cb_hdr, 0, sizeof(*cb_hdr));
|
||||
|
||||
cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
|
||||
|
||||
cb_hdr->hdr.it_len = cpu_to_le16(sizeof(*cb_hdr));
|
||||
|
||||
cb_hdr->hdr.it_present = cpu_to_le32(TX_RADIOTAP_PRESENT);
|
||||
|
||||
cb_hdr->rate = 5;
|
||||
|
||||
if (pkt_offset & IS_MGMT_STATUS_SUCCES) {
|
||||
/* success */
|
||||
cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_RTS;
|
||||
} else {
|
||||
cb_hdr->tx_flags = IEEE80211_RADIOTAP_F_TX_FAIL;
|
||||
}
|
||||
|
||||
} else {
|
||||
skb = dev_alloc_skb(size + sizeof(*hdr));
|
||||
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
skb_put_data(skb, buff, size);
|
||||
hdr = skb_push(skb, sizeof(*hdr));
|
||||
memset(hdr, 0, sizeof(struct wilc_wfi_radiotap_hdr));
|
||||
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;
|
||||
}
|
||||
|
||||
skb->dev = mon_dev;
|
||||
skb_reset_mac_header(skb);
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb->pkt_type = PACKET_OTHERHOST;
|
||||
skb->protocol = htons(ETH_P_802_2);
|
||||
memset(skb->cb, 0, sizeof(skb->cb));
|
||||
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
struct tx_complete_mon_data {
|
||||
int size;
|
||||
void *buff;
|
||||
};
|
||||
|
||||
static void mgmt_tx_complete(void *priv, int status)
|
||||
{
|
||||
struct tx_complete_mon_data *pv_data = priv;
|
||||
/*
|
||||
* in case of fully hosting mode, the freeing will be done
|
||||
* in response to the cfg packet
|
||||
*/
|
||||
kfree(pv_data->buff);
|
||||
|
||||
kfree(pv_data);
|
||||
}
|
||||
|
||||
static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
|
||||
{
|
||||
struct tx_complete_mon_data *mgmt_tx = NULL;
|
||||
|
||||
if (!dev)
|
||||
return -EFAULT;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC);
|
||||
if (!mgmt_tx)
|
||||
return -ENOMEM;
|
||||
|
||||
mgmt_tx->buff = kmemdup(buf, len, GFP_ATOMIC);
|
||||
if (!mgmt_tx->buff) {
|
||||
kfree(mgmt_tx);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mgmt_tx->size = len;
|
||||
|
||||
wilc_wlan_txq_add_mgmt_pkt(dev, mgmt_tx, mgmt_tx->buff, mgmt_tx->size,
|
||||
mgmt_tx_complete);
|
||||
|
||||
netif_wake_queue(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static netdev_tx_t wilc_wfi_mon_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
u32 rtap_len, ret = 0;
|
||||
struct wilc_wfi_mon_priv *mon_priv;
|
||||
struct sk_buff *skb2;
|
||||
struct wilc_wfi_radiotap_cb_hdr *cb_hdr;
|
||||
u8 srcadd[ETH_ALEN];
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
||||
mon_priv = netdev_priv(dev);
|
||||
if (!mon_priv)
|
||||
return -EFAULT;
|
||||
|
||||
rtap_len = ieee80211_get_radiotap_len(skb->data);
|
||||
if (skb->len < rtap_len)
|
||||
return -1;
|
||||
|
||||
skb_pull(skb, rtap_len);
|
||||
|
||||
if (skb->data[0] == 0xc0 && is_broadcast_ether_addr(&skb->data[4])) {
|
||||
skb2 = dev_alloc_skb(skb->len + sizeof(*cb_hdr));
|
||||
if (!skb2)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_put_data(skb2, skb->data, skb->len);
|
||||
|
||||
cb_hdr = skb_push(skb2, sizeof(*cb_hdr));
|
||||
memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr));
|
||||
|
||||
cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */
|
||||
|
||||
cb_hdr->hdr.it_len = cpu_to_le16(sizeof(*cb_hdr));
|
||||
|
||||
cb_hdr->hdr.it_present = cpu_to_le32(TX_RADIOTAP_PRESENT);
|
||||
|
||||
cb_hdr->rate = 5;
|
||||
cb_hdr->tx_flags = 0x0004;
|
||||
|
||||
skb2->dev = dev;
|
||||
skb_reset_mac_header(skb2);
|
||||
skb2->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb2->pkt_type = PACKET_OTHERHOST;
|
||||
skb2->protocol = htons(ETH_P_802_2);
|
||||
memset(skb2->cb, 0, sizeof(skb2->cb));
|
||||
|
||||
netif_rx(skb2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
skb->dev = mon_priv->real_ndev;
|
||||
|
||||
ether_addr_copy(srcadd, &skb->data[10]);
|
||||
ether_addr_copy(bssid, &skb->data[16]);
|
||||
/*
|
||||
* Identify if data or mgmt packet, if source address and bssid
|
||||
* fields are equal send it to mgmt frames handler
|
||||
*/
|
||||
if (!(memcmp(srcadd, bssid, 6))) {
|
||||
ret = mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len);
|
||||
if (ret)
|
||||
netdev_err(dev, "fail to mgmt tx\n");
|
||||
dev_kfree_skb(skb);
|
||||
} else {
|
||||
ret = wilc_mac_xmit(skb, mon_priv->real_ndev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct net_device_ops wilc_wfi_netdev_ops = {
|
||||
.ndo_start_xmit = wilc_wfi_mon_xmit,
|
||||
|
||||
};
|
||||
|
||||
struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
|
||||
const char *name,
|
||||
struct net_device *real_dev)
|
||||
{
|
||||
struct wilc_wfi_mon_priv *priv;
|
||||
|
||||
/* If monitor interface is already initialized, return it */
|
||||
if (wl->monitor_dev)
|
||||
return wl->monitor_dev;
|
||||
|
||||
wl->monitor_dev = alloc_etherdev(sizeof(struct wilc_wfi_mon_priv));
|
||||
if (!wl->monitor_dev)
|
||||
return NULL;
|
||||
|
||||
wl->monitor_dev->type = ARPHRD_IEEE80211_RADIOTAP;
|
||||
strncpy(wl->monitor_dev->name, name, IFNAMSIZ);
|
||||
wl->monitor_dev->name[IFNAMSIZ - 1] = 0;
|
||||
wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops;
|
||||
wl->monitor_dev->needs_free_netdev = true;
|
||||
|
||||
if (register_netdevice(wl->monitor_dev)) {
|
||||
netdev_err(real_dev, "register_netdevice failed\n");
|
||||
return NULL;
|
||||
}
|
||||
priv = netdev_priv(wl->monitor_dev);
|
||||
if (!priv)
|
||||
return NULL;
|
||||
|
||||
priv->real_ndev = real_dev;
|
||||
|
||||
return wl->monitor_dev;
|
||||
}
|
||||
|
||||
void wilc_wfi_deinit_mon_interface(struct wilc *wl, bool rtnl_locked)
|
||||
{
|
||||
if (!wl->monitor_dev)
|
||||
return;
|
||||
|
||||
if (rtnl_locked)
|
||||
unregister_netdevice(wl->monitor_dev);
|
||||
else
|
||||
unregister_netdev(wl->monitor_dev);
|
||||
wl->monitor_dev = NULL;
|
||||
}
|
931
drivers/net/wireless/microchip/wilc1000/netdev.c
Normal file
931
drivers/net/wireless/microchip/wilc1000/netdev.c
Normal file
@@ -0,0 +1,931 @@
|
||||
// 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/kthread.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/inetdevice.h>
|
||||
|
||||
#include "cfg80211.h"
|
||||
#include "wlan_cfg.h"
|
||||
|
||||
#define WILC_MULTICAST_TABLE_SIZE 8
|
||||
|
||||
static irqreturn_t isr_uh_routine(int irq, void *user_data)
|
||||
{
|
||||
struct net_device *dev = user_data;
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
|
||||
if (wilc->close) {
|
||||
netdev_err(dev, "Can't handle UH interrupt\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
static irqreturn_t isr_bh_routine(int irq, void *userdata)
|
||||
{
|
||||
struct net_device *dev = userdata;
|
||||
struct wilc_vif *vif = netdev_priv(userdata);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
|
||||
if (wilc->close) {
|
||||
netdev_err(dev, "Can't handle BH interrupt\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
wilc_handle_isr(wilc);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int init_irq(struct net_device *dev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wl = vif->wilc;
|
||||
int ret;
|
||||
|
||||
ret = request_threaded_irq(wl->dev_irq_num, isr_uh_routine,
|
||||
isr_bh_routine,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"WILC_IRQ", dev);
|
||||
if (ret) {
|
||||
netdev_err(dev, "Failed to request IRQ [%d]\n", ret);
|
||||
return ret;
|
||||
}
|
||||
netdev_dbg(dev, "IRQ request succeeded IRQ-NUM= %d\n", wl->dev_irq_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void deinit_irq(struct net_device *dev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
|
||||
/* Deinitialize IRQ */
|
||||
if (wilc->dev_irq_num)
|
||||
free_irq(wilc->dev_irq_num, wilc);
|
||||
}
|
||||
|
||||
void wilc_mac_indicate(struct wilc *wilc)
|
||||
{
|
||||
s8 status;
|
||||
|
||||
wilc_wlan_cfg_get_val(wilc, WID_STATUS, &status, 1);
|
||||
if (wilc->mac_status == WILC_MAC_STATUS_INIT) {
|
||||
wilc->mac_status = status;
|
||||
complete(&wilc->sync_event);
|
||||
} else {
|
||||
wilc->mac_status = status;
|
||||
}
|
||||
}
|
||||
|
||||
static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header)
|
||||
{
|
||||
struct net_device *ndev = NULL;
|
||||
struct wilc_vif *vif;
|
||||
struct ieee80211_hdr *h = (struct ieee80211_hdr *)mac_header;
|
||||
|
||||
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
|
||||
if (vif->mode == WILC_STATION_MODE)
|
||||
if (ether_addr_equal_unaligned(h->addr2, vif->bssid)) {
|
||||
ndev = vif->ndev;
|
||||
goto out;
|
||||
}
|
||||
if (vif->mode == WILC_AP_MODE)
|
||||
if (ether_addr_equal_unaligned(h->addr1, vif->bssid)) {
|
||||
ndev = vif->ndev;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
return ndev;
|
||||
}
|
||||
|
||||
void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(wilc_netdev);
|
||||
|
||||
if (bssid)
|
||||
ether_addr_copy(vif->bssid, bssid);
|
||||
else
|
||||
eth_zero_addr(vif->bssid);
|
||||
|
||||
vif->mode = mode;
|
||||
}
|
||||
|
||||
int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc)
|
||||
{
|
||||
int srcu_idx;
|
||||
u8 ret_val = 0;
|
||||
struct wilc_vif *vif;
|
||||
|
||||
srcu_idx = srcu_read_lock(&wilc->srcu);
|
||||
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
|
||||
if (!is_zero_ether_addr(vif->bssid))
|
||||
ret_val++;
|
||||
}
|
||||
srcu_read_unlock(&wilc->srcu, srcu_idx);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int wilc_txq_task(void *vp)
|
||||
{
|
||||
int ret;
|
||||
u32 txq_count;
|
||||
struct wilc *wl = vp;
|
||||
|
||||
complete(&wl->txq_thread_started);
|
||||
while (1) {
|
||||
wait_for_completion(&wl->txq_event);
|
||||
|
||||
if (wl->close) {
|
||||
complete(&wl->txq_thread_started);
|
||||
|
||||
while (!kthread_should_stop())
|
||||
schedule();
|
||||
break;
|
||||
}
|
||||
do {
|
||||
ret = wilc_wlan_handle_txq(wl, &txq_count);
|
||||
if (txq_count < FLOW_CONTROL_LOWER_THRESHOLD) {
|
||||
int srcu_idx;
|
||||
struct wilc_vif *ifc;
|
||||
|
||||
srcu_idx = srcu_read_lock(&wl->srcu);
|
||||
list_for_each_entry_rcu(ifc, &wl->vif_list,
|
||||
list) {
|
||||
if (ifc->mac_opened && ifc->ndev)
|
||||
netif_wake_queue(ifc->ndev);
|
||||
}
|
||||
srcu_read_unlock(&wl->srcu, srcu_idx);
|
||||
}
|
||||
} while (ret == WILC_VMM_ENTRY_FULL_RETRY && !wl->close);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_wlan_get_firmware(struct net_device *dev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
int chip_id;
|
||||
const struct firmware *wilc_firmware;
|
||||
char *firmware;
|
||||
|
||||
chip_id = wilc_get_chipid(wilc, false);
|
||||
|
||||
if (chip_id < 0x1003a0)
|
||||
firmware = FIRMWARE_1002;
|
||||
else
|
||||
firmware = FIRMWARE_1003;
|
||||
|
||||
netdev_info(dev, "loading firmware %s\n", firmware);
|
||||
|
||||
if (request_firmware(&wilc_firmware, firmware, wilc->dev) != 0) {
|
||||
netdev_err(dev, "%s - firmware not available\n", firmware);
|
||||
return -EINVAL;
|
||||
}
|
||||
wilc->firmware = wilc_firmware;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_start_firmware(struct net_device *dev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
int ret = 0;
|
||||
|
||||
ret = wilc_wlan_start(wilc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!wait_for_completion_timeout(&wilc->sync_event,
|
||||
msecs_to_jiffies(5000)))
|
||||
return -ETIME;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc1000_firmware_download(struct net_device *dev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
int ret = 0;
|
||||
|
||||
if (!wilc->firmware) {
|
||||
netdev_err(dev, "Firmware buffer is NULL\n");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data,
|
||||
wilc->firmware->size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
release_firmware(wilc->firmware);
|
||||
wilc->firmware = NULL;
|
||||
|
||||
netdev_dbg(dev, "Download Succeeded\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_init_fw_config(struct net_device *dev, struct wilc_vif *vif)
|
||||
{
|
||||
struct wilc_priv *priv = &vif->priv;
|
||||
struct host_if_drv *hif_drv;
|
||||
u8 b;
|
||||
u16 hw;
|
||||
u32 w;
|
||||
|
||||
netdev_dbg(dev, "Start configuring Firmware\n");
|
||||
hif_drv = (struct host_if_drv *)priv->hif_drv;
|
||||
netdev_dbg(dev, "Host = %p\n", hif_drv);
|
||||
|
||||
w = vif->iftype;
|
||||
cpu_to_le32s(&w);
|
||||
if (!wilc_wlan_cfg_set(vif, 1, WID_SET_OPERATION_MODE, (u8 *)&w, 4,
|
||||
0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_BSS_TYPE_INFRA;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_TX_RATE_AUTO;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_OPER_MODE_G_MIXED_11B_2;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_PREAMBLE_SHORT;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_11N_PROT_AUTO;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_ACTIVE_SCAN;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_SITE_SURVEY_OFF;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
hw = 0xffff;
|
||||
cpu_to_le16s(&hw);
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, (u8 *)&hw, 2, 0, 0))
|
||||
goto fail;
|
||||
|
||||
hw = 2346;
|
||||
cpu_to_le16s(&hw);
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, (u8 *)&hw, 2, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 0;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 1;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_NO_POWERSAVE;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_SEC_NO;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_AUTH_OPEN_SYSTEM;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 3;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 3;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_ACK_POLICY_NORMAL;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 0;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, &b, 1,
|
||||
0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 48;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 28;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
hw = 100;
|
||||
cpu_to_le16s(&hw);
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, (u8 *)&hw, 2, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_REKEY_POLICY_DISABLE;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
w = 84600;
|
||||
cpu_to_le32s(&w);
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, (u8 *)&w, 4, 0, 0))
|
||||
goto fail;
|
||||
|
||||
w = 500;
|
||||
cpu_to_le32s(&w);
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, (u8 *)&w, 4, 0,
|
||||
0))
|
||||
goto fail;
|
||||
|
||||
b = 1;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, &b, 1, 0,
|
||||
0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_ERP_PROT_SELF_CTS;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 1;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_11N_OP_MODE_HT_MIXED;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 1;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, &b, 1,
|
||||
0, 0))
|
||||
goto fail;
|
||||
|
||||
b = WILC_FW_HT_PROT_RTS_CTS_NONHT;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 0;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, &b, 1, 0,
|
||||
0))
|
||||
goto fail;
|
||||
|
||||
b = 7;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, &b, 1, 0, 0))
|
||||
goto fail;
|
||||
|
||||
b = 1;
|
||||
if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, &b, 1,
|
||||
1, 1))
|
||||
goto fail;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void wlan_deinitialize_threads(struct net_device *dev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wl = vif->wilc;
|
||||
|
||||
wl->close = 1;
|
||||
|
||||
complete(&wl->txq_event);
|
||||
|
||||
if (wl->txq_thread) {
|
||||
kthread_stop(wl->txq_thread);
|
||||
wl->txq_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void wilc_wlan_deinitialize(struct net_device *dev)
|
||||
{
|
||||
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) {
|
||||
netdev_info(dev, "Deinitializing wilc1000...\n");
|
||||
|
||||
if (!wl->dev_irq_num &&
|
||||
wl->hif_func->disable_interrupt) {
|
||||
mutex_lock(&wl->hif_cs);
|
||||
wl->hif_func->disable_interrupt(wl);
|
||||
mutex_unlock(&wl->hif_cs);
|
||||
}
|
||||
complete(&wl->txq_event);
|
||||
|
||||
wlan_deinitialize_threads(dev);
|
||||
deinit_irq(dev);
|
||||
|
||||
wilc_wlan_stop(wl, vif);
|
||||
wilc_wlan_cleanup(dev);
|
||||
|
||||
wl->initialized = false;
|
||||
|
||||
netdev_dbg(dev, "wilc1000 deinitialization Done\n");
|
||||
} else {
|
||||
netdev_dbg(dev, "wilc1000 is not initialized\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int wlan_initialize_threads(struct net_device *dev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
|
||||
wilc->txq_thread = kthread_run(wilc_txq_task, (void *)wilc,
|
||||
"K_TXQ_TASK");
|
||||
if (IS_ERR(wilc->txq_thread)) {
|
||||
netdev_err(dev, "couldn't create TXQ thread\n");
|
||||
wilc->close = 0;
|
||||
return PTR_ERR(wilc->txq_thread);
|
||||
}
|
||||
wait_for_completion(&wilc->txq_thread_started);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif)
|
||||
{
|
||||
int ret = 0;
|
||||
struct wilc *wl = vif->wilc;
|
||||
|
||||
if (!wl->initialized) {
|
||||
wl->mac_status = WILC_MAC_STATUS_INIT;
|
||||
wl->close = 0;
|
||||
|
||||
ret = wilc_wlan_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wlan_initialize_threads(dev);
|
||||
if (ret)
|
||||
goto fail_wilc_wlan;
|
||||
|
||||
if (wl->dev_irq_num && init_irq(dev)) {
|
||||
ret = -EIO;
|
||||
goto fail_threads;
|
||||
}
|
||||
|
||||
if (!wl->dev_irq_num &&
|
||||
wl->hif_func->enable_interrupt &&
|
||||
wl->hif_func->enable_interrupt(wl)) {
|
||||
ret = -EIO;
|
||||
goto fail_irq_init;
|
||||
}
|
||||
|
||||
ret = wilc_wlan_get_firmware(dev);
|
||||
if (ret)
|
||||
goto fail_irq_enable;
|
||||
|
||||
ret = wilc1000_firmware_download(dev);
|
||||
if (ret)
|
||||
goto fail_irq_enable;
|
||||
|
||||
ret = wilc_start_firmware(dev);
|
||||
if (ret)
|
||||
goto fail_irq_enable;
|
||||
|
||||
if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) {
|
||||
int size;
|
||||
char firmware_ver[20];
|
||||
|
||||
size = wilc_wlan_cfg_get_val(wl, WID_FIRMWARE_VERSION,
|
||||
firmware_ver,
|
||||
sizeof(firmware_ver));
|
||||
firmware_ver[size] = '\0';
|
||||
netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver);
|
||||
}
|
||||
|
||||
ret = wilc_init_fw_config(dev, vif);
|
||||
if (ret) {
|
||||
netdev_err(dev, "Failed to configure firmware\n");
|
||||
goto fail_fw_start;
|
||||
}
|
||||
wl->initialized = true;
|
||||
return 0;
|
||||
|
||||
fail_fw_start:
|
||||
wilc_wlan_stop(wl, vif);
|
||||
|
||||
fail_irq_enable:
|
||||
if (!wl->dev_irq_num &&
|
||||
wl->hif_func->disable_interrupt)
|
||||
wl->hif_func->disable_interrupt(wl);
|
||||
fail_irq_init:
|
||||
if (wl->dev_irq_num)
|
||||
deinit_irq(dev);
|
||||
fail_threads:
|
||||
wlan_deinitialize_threads(dev);
|
||||
fail_wilc_wlan:
|
||||
wilc_wlan_cleanup(dev);
|
||||
netdev_err(dev, "WLAN initialization FAILED\n");
|
||||
} else {
|
||||
netdev_dbg(dev, "wilc1000 already initialized\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mac_init_fn(struct net_device *ndev)
|
||||
{
|
||||
netif_start_queue(ndev);
|
||||
netif_stop_queue(ndev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_mac_open(struct net_device *ndev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(ndev);
|
||||
struct wilc *wl = vif->wilc;
|
||||
unsigned char mac_add[ETH_ALEN] = {0};
|
||||
int ret = 0;
|
||||
struct mgmt_frame_regs mgmt_regs = {};
|
||||
|
||||
if (!wl || !wl->dev) {
|
||||
netdev_err(ndev, "device not ready\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev);
|
||||
|
||||
ret = wilc_init_host_int(ndev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wilc_wlan_initialize(ndev, vif);
|
||||
if (ret) {
|
||||
wilc_deinit_host_int(ndev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype,
|
||||
vif->idx);
|
||||
wilc_get_mac_address(vif, mac_add);
|
||||
netdev_dbg(ndev, "Mac address: %pM\n", mac_add);
|
||||
ether_addr_copy(ndev->dev_addr, mac_add);
|
||||
|
||||
if (!is_valid_ether_addr(ndev->dev_addr)) {
|
||||
netdev_err(ndev, "Wrong MAC address\n");
|
||||
wilc_deinit_host_int(ndev);
|
||||
wilc_wlan_deinitialize(ndev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mgmt_regs.interface_stypes = vif->mgmt_reg_stypes;
|
||||
/* so we detect a change */
|
||||
vif->mgmt_reg_stypes = 0;
|
||||
wilc_update_mgmt_frame_registrations(vif->ndev->ieee80211_ptr->wiphy,
|
||||
vif->ndev->ieee80211_ptr,
|
||||
&mgmt_regs);
|
||||
netif_wake_queue(ndev);
|
||||
wl->open_ifcs++;
|
||||
vif->mac_opened = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct net_device_stats *mac_stats(struct net_device *dev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
|
||||
return &vif->netstats;
|
||||
}
|
||||
|
||||
static void wilc_set_multicast_list(struct net_device *dev)
|
||||
{
|
||||
struct netdev_hw_addr *ha;
|
||||
struct wilc_vif *vif = netdev_priv(dev);
|
||||
int i;
|
||||
u8 *mc_list;
|
||||
u8 *cur_mc;
|
||||
|
||||
if (dev->flags & IFF_PROMISC)
|
||||
return;
|
||||
|
||||
if (dev->flags & IFF_ALLMULTI ||
|
||||
dev->mc.count > WILC_MULTICAST_TABLE_SIZE) {
|
||||
wilc_setup_multicast_filter(vif, 0, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->mc.count == 0) {
|
||||
wilc_setup_multicast_filter(vif, 1, 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
mc_list = kmalloc_array(dev->mc.count, ETH_ALEN, GFP_ATOMIC);
|
||||
if (!mc_list)
|
||||
return;
|
||||
|
||||
cur_mc = mc_list;
|
||||
i = 0;
|
||||
netdev_for_each_mc_addr(ha, dev) {
|
||||
memcpy(cur_mc, ha->addr, ETH_ALEN);
|
||||
netdev_dbg(dev, "Entry[%d]: %pM\n", i, cur_mc);
|
||||
i++;
|
||||
cur_mc += ETH_ALEN;
|
||||
}
|
||||
|
||||
if (wilc_setup_multicast_filter(vif, 1, dev->mc.count, mc_list))
|
||||
kfree(mc_list);
|
||||
}
|
||||
|
||||
static void wilc_tx_complete(void *priv, int status)
|
||||
{
|
||||
struct tx_complete_data *pv_data = priv;
|
||||
|
||||
dev_kfree_skb(pv_data->skb);
|
||||
kfree(pv_data);
|
||||
}
|
||||
|
||||
netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(ndev);
|
||||
struct wilc *wilc = vif->wilc;
|
||||
struct tx_complete_data *tx_data = NULL;
|
||||
int queue_count;
|
||||
|
||||
if (skb->dev != ndev) {
|
||||
netdev_err(ndev, "Packet not destined to this device\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC);
|
||||
if (!tx_data) {
|
||||
dev_kfree_skb(skb);
|
||||
netif_wake_queue(ndev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tx_data->buff = skb->data;
|
||||
tx_data->size = skb->len;
|
||||
tx_data->skb = skb;
|
||||
|
||||
vif->netstats.tx_packets++;
|
||||
vif->netstats.tx_bytes += tx_data->size;
|
||||
queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
|
||||
tx_data->buff, tx_data->size,
|
||||
wilc_tx_complete);
|
||||
|
||||
if (queue_count > FLOW_CONTROL_UPPER_THRESHOLD) {
|
||||
int srcu_idx;
|
||||
struct wilc_vif *vif;
|
||||
|
||||
srcu_idx = srcu_read_lock(&wilc->srcu);
|
||||
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
|
||||
if (vif->mac_opened)
|
||||
netif_stop_queue(vif->ndev);
|
||||
}
|
||||
srcu_read_unlock(&wilc->srcu, srcu_idx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_mac_close(struct net_device *ndev)
|
||||
{
|
||||
struct wilc_vif *vif = netdev_priv(ndev);
|
||||
struct wilc *wl = vif->wilc;
|
||||
|
||||
netdev_dbg(ndev, "Mac close\n");
|
||||
|
||||
if (wl->open_ifcs > 0)
|
||||
wl->open_ifcs--;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (vif->ndev) {
|
||||
netif_stop_queue(vif->ndev);
|
||||
|
||||
wilc_deinit_host_int(vif->ndev);
|
||||
}
|
||||
|
||||
if (wl->open_ifcs == 0) {
|
||||
netdev_dbg(ndev, "Deinitializing wilc1000\n");
|
||||
wl->close = 1;
|
||||
wilc_wlan_deinitialize(ndev);
|
||||
}
|
||||
|
||||
vif->mac_opened = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size,
|
||||
u32 pkt_offset)
|
||||
{
|
||||
unsigned int frame_len = 0;
|
||||
int stats;
|
||||
unsigned char *buff_to_send = NULL;
|
||||
struct sk_buff *skb;
|
||||
struct net_device *wilc_netdev;
|
||||
struct wilc_vif *vif;
|
||||
|
||||
if (!wilc)
|
||||
return;
|
||||
|
||||
wilc_netdev = get_if_handler(wilc, buff);
|
||||
if (!wilc_netdev)
|
||||
return;
|
||||
|
||||
buff += pkt_offset;
|
||||
vif = netdev_priv(wilc_netdev);
|
||||
|
||||
if (size > 0) {
|
||||
frame_len = size;
|
||||
buff_to_send = buff;
|
||||
|
||||
skb = dev_alloc_skb(frame_len);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
skb->dev = wilc_netdev;
|
||||
|
||||
skb_put_data(skb, buff_to_send, frame_len);
|
||||
|
||||
skb->protocol = eth_type_trans(skb, wilc_netdev);
|
||||
vif->netstats.rx_packets++;
|
||||
vif->netstats.rx_bytes += frame_len;
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
stats = netif_rx(skb);
|
||||
netdev_dbg(wilc_netdev, "netif_rx ret value is: %d\n", stats);
|
||||
}
|
||||
}
|
||||
|
||||
void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size)
|
||||
{
|
||||
int srcu_idx;
|
||||
struct wilc_vif *vif;
|
||||
|
||||
srcu_idx = srcu_read_lock(&wilc->srcu);
|
||||
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
|
||||
u16 type = le16_to_cpup((__le16 *)buff);
|
||||
u32 type_bit = BIT(type >> 4);
|
||||
|
||||
if (vif->priv.p2p_listen_state &&
|
||||
vif->mgmt_reg_stypes & type_bit)
|
||||
wilc_wfi_p2p_rx(vif, buff, size);
|
||||
|
||||
if (vif->monitor_flag)
|
||||
wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size);
|
||||
}
|
||||
srcu_read_unlock(&wilc->srcu, srcu_idx);
|
||||
}
|
||||
|
||||
static const struct net_device_ops wilc_netdev_ops = {
|
||||
.ndo_init = mac_init_fn,
|
||||
.ndo_open = wilc_mac_open,
|
||||
.ndo_stop = wilc_mac_close,
|
||||
.ndo_start_xmit = wilc_mac_xmit,
|
||||
.ndo_get_stats = mac_stats,
|
||||
.ndo_set_rx_mode = wilc_set_multicast_list,
|
||||
};
|
||||
|
||||
void wilc_netdev_cleanup(struct wilc *wilc)
|
||||
{
|
||||
struct wilc_vif *vif;
|
||||
int srcu_idx, ifc_cnt = 0;
|
||||
|
||||
if (!wilc)
|
||||
return;
|
||||
|
||||
if (wilc->firmware) {
|
||||
release_firmware(wilc->firmware);
|
||||
wilc->firmware = NULL;
|
||||
}
|
||||
|
||||
srcu_idx = srcu_read_lock(&wilc->srcu);
|
||||
list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
|
||||
if (vif->ndev)
|
||||
unregister_netdev(vif->ndev);
|
||||
}
|
||||
srcu_read_unlock(&wilc->srcu, srcu_idx);
|
||||
|
||||
wilc_wfi_deinit_mon_interface(wilc, false);
|
||||
flush_workqueue(wilc->hif_workqueue);
|
||||
destroy_workqueue(wilc->hif_workqueue);
|
||||
|
||||
while (ifc_cnt < WILC_NUM_CONCURRENT_IFC) {
|
||||
mutex_lock(&wilc->vif_mutex);
|
||||
if (wilc->vif_num <= 0) {
|
||||
mutex_unlock(&wilc->vif_mutex);
|
||||
break;
|
||||
}
|
||||
vif = wilc_get_wl_to_vif(wilc);
|
||||
if (!IS_ERR(vif))
|
||||
list_del_rcu(&vif->list);
|
||||
|
||||
wilc->vif_num--;
|
||||
mutex_unlock(&wilc->vif_mutex);
|
||||
synchronize_srcu(&wilc->srcu);
|
||||
ifc_cnt++;
|
||||
}
|
||||
|
||||
wilc_wlan_cfg_deinit(wilc);
|
||||
wlan_deinit_locks(wilc);
|
||||
kfree(wilc->bus_data);
|
||||
wiphy_unregister(wilc->wiphy);
|
||||
wiphy_free(wilc->wiphy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wilc_netdev_cleanup);
|
||||
|
||||
static u8 wilc_get_available_idx(struct wilc *wl)
|
||||
{
|
||||
int idx = 0;
|
||||
struct wilc_vif *vif;
|
||||
int srcu_idx;
|
||||
|
||||
srcu_idx = srcu_read_lock(&wl->srcu);
|
||||
list_for_each_entry_rcu(vif, &wl->vif_list, list) {
|
||||
if (vif->idx == 0)
|
||||
idx = 1;
|
||||
else
|
||||
idx = 0;
|
||||
}
|
||||
srcu_read_unlock(&wl->srcu, srcu_idx);
|
||||
return idx;
|
||||
}
|
||||
|
||||
struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
|
||||
int vif_type, enum nl80211_iftype type,
|
||||
bool rtnl_locked)
|
||||
{
|
||||
struct net_device *ndev;
|
||||
struct wilc_vif *vif;
|
||||
int ret;
|
||||
|
||||
ndev = alloc_etherdev(sizeof(*vif));
|
||||
if (!ndev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
vif = netdev_priv(ndev);
|
||||
ndev->ieee80211_ptr = &vif->priv.wdev;
|
||||
strcpy(ndev->name, name);
|
||||
vif->wilc = wl;
|
||||
vif->ndev = ndev;
|
||||
ndev->ml_priv = vif;
|
||||
|
||||
ndev->netdev_ops = &wilc_netdev_ops;
|
||||
|
||||
SET_NETDEV_DEV(ndev, wiphy_dev(wl->wiphy));
|
||||
|
||||
vif->priv.wdev.wiphy = wl->wiphy;
|
||||
vif->priv.wdev.netdev = ndev;
|
||||
vif->priv.wdev.iftype = type;
|
||||
vif->priv.dev = ndev;
|
||||
|
||||
if (rtnl_locked)
|
||||
ret = register_netdevice(ndev);
|
||||
else
|
||||
ret = register_netdev(ndev);
|
||||
|
||||
if (ret) {
|
||||
free_netdev(ndev);
|
||||
return ERR_PTR(-EFAULT);
|
||||
}
|
||||
|
||||
ndev->needs_free_netdev = true;
|
||||
vif->iftype = vif_type;
|
||||
vif->idx = wilc_get_available_idx(wl);
|
||||
vif->mac_opened = 0;
|
||||
mutex_lock(&wl->vif_mutex);
|
||||
list_add_tail_rcu(&vif->list, &wl->vif_list);
|
||||
wl->vif_num += 1;
|
||||
mutex_unlock(&wl->vif_mutex);
|
||||
synchronize_srcu(&wl->srcu);
|
||||
|
||||
return vif;
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
287
drivers/net/wireless/microchip/wilc1000/netdev.h
Normal file
287
drivers/net/wireless/microchip/wilc1000/netdev.h
Normal file
@@ -0,0 +1,287 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef WILC_NETDEV_H
|
||||
#define WILC_NETDEV_H
|
||||
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
#include "hif.h"
|
||||
#include "wlan.h"
|
||||
#include "wlan_cfg.h"
|
||||
|
||||
#define FLOW_CONTROL_LOWER_THRESHOLD 128
|
||||
#define FLOW_CONTROL_UPPER_THRESHOLD 256
|
||||
|
||||
#define PMKID_FOUND 1
|
||||
#define NUM_STA_ASSOCIATED 8
|
||||
|
||||
#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
|
||||
#define DEFAULT_LINK_SPEED 72
|
||||
|
||||
struct wilc_wfi_stats {
|
||||
unsigned long rx_packets;
|
||||
unsigned long tx_packets;
|
||||
unsigned long rx_bytes;
|
||||
unsigned long tx_bytes;
|
||||
u64 rx_time;
|
||||
u64 tx_time;
|
||||
|
||||
};
|
||||
|
||||
struct wilc_wfi_key {
|
||||
u8 *key;
|
||||
u8 *seq;
|
||||
int key_len;
|
||||
int seq_len;
|
||||
u32 cipher;
|
||||
};
|
||||
|
||||
struct wilc_wfi_wep_key {
|
||||
u8 *key;
|
||||
u8 key_len;
|
||||
u8 key_idx;
|
||||
};
|
||||
|
||||
struct sta_info {
|
||||
u8 sta_associated_bss[WILC_MAX_NUM_STA][ETH_ALEN];
|
||||
};
|
||||
|
||||
/* Parameters needed for host interface for remaining on channel */
|
||||
struct wilc_wfi_p2p_listen_params {
|
||||
struct ieee80211_channel *listen_ch;
|
||||
u32 listen_duration;
|
||||
u64 listen_cookie;
|
||||
};
|
||||
|
||||
static const u32 wilc_cipher_suites[] = {
|
||||
WLAN_CIPHER_SUITE_WEP40,
|
||||
WLAN_CIPHER_SUITE_WEP104,
|
||||
WLAN_CIPHER_SUITE_TKIP,
|
||||
WLAN_CIPHER_SUITE_CCMP,
|
||||
WLAN_CIPHER_SUITE_AES_CMAC
|
||||
};
|
||||
|
||||
#define CHAN2G(_channel, _freq, _flags) { \
|
||||
.band = NL80211_BAND_2GHZ, \
|
||||
.center_freq = (_freq), \
|
||||
.hw_value = (_channel), \
|
||||
.flags = (_flags), \
|
||||
.max_antenna_gain = 0, \
|
||||
.max_power = 30, \
|
||||
}
|
||||
|
||||
static const struct ieee80211_channel wilc_2ghz_channels[] = {
|
||||
CHAN2G(1, 2412, 0),
|
||||
CHAN2G(2, 2417, 0),
|
||||
CHAN2G(3, 2422, 0),
|
||||
CHAN2G(4, 2427, 0),
|
||||
CHAN2G(5, 2432, 0),
|
||||
CHAN2G(6, 2437, 0),
|
||||
CHAN2G(7, 2442, 0),
|
||||
CHAN2G(8, 2447, 0),
|
||||
CHAN2G(9, 2452, 0),
|
||||
CHAN2G(10, 2457, 0),
|
||||
CHAN2G(11, 2462, 0),
|
||||
CHAN2G(12, 2467, 0),
|
||||
CHAN2G(13, 2472, 0),
|
||||
CHAN2G(14, 2484, 0)
|
||||
};
|
||||
|
||||
#define RATETAB_ENT(_rate, _hw_value, _flags) { \
|
||||
.bitrate = (_rate), \
|
||||
.hw_value = (_hw_value), \
|
||||
.flags = (_flags), \
|
||||
}
|
||||
|
||||
static struct ieee80211_rate wilc_bitrates[] = {
|
||||
RATETAB_ENT(10, 0, 0),
|
||||
RATETAB_ENT(20, 1, 0),
|
||||
RATETAB_ENT(55, 2, 0),
|
||||
RATETAB_ENT(110, 3, 0),
|
||||
RATETAB_ENT(60, 9, 0),
|
||||
RATETAB_ENT(90, 6, 0),
|
||||
RATETAB_ENT(120, 7, 0),
|
||||
RATETAB_ENT(180, 8, 0),
|
||||
RATETAB_ENT(240, 9, 0),
|
||||
RATETAB_ENT(360, 10, 0),
|
||||
RATETAB_ENT(480, 11, 0),
|
||||
RATETAB_ENT(540, 12, 0)
|
||||
};
|
||||
|
||||
struct wilc_priv {
|
||||
struct wireless_dev wdev;
|
||||
struct cfg80211_scan_request *scan_req;
|
||||
|
||||
struct wilc_wfi_p2p_listen_params remain_on_ch_params;
|
||||
u64 tx_cookie;
|
||||
|
||||
bool cfg_scanning;
|
||||
|
||||
u8 associated_bss[ETH_ALEN];
|
||||
struct sta_info assoc_stainfo;
|
||||
struct sk_buff *skb;
|
||||
struct net_device *dev;
|
||||
struct host_if_drv *hif_drv;
|
||||
struct wilc_pmkid_attr pmkid_list;
|
||||
u8 wep_key[4][WLAN_KEY_LEN_WEP104];
|
||||
u8 wep_key_len[4];
|
||||
|
||||
/* The real interface that the monitor is on */
|
||||
struct net_device *real_ndev;
|
||||
struct wilc_wfi_key *wilc_gtk[WILC_MAX_NUM_STA];
|
||||
struct wilc_wfi_key *wilc_ptk[WILC_MAX_NUM_STA];
|
||||
u8 wilc_groupkey;
|
||||
|
||||
/* mutexes */
|
||||
struct mutex scan_req_lock;
|
||||
bool p2p_listen_state;
|
||||
int scanned_cnt;
|
||||
|
||||
u64 inc_roc_cookie;
|
||||
};
|
||||
|
||||
#define MAX_TCP_SESSION 25
|
||||
#define MAX_PENDING_ACKS 256
|
||||
|
||||
struct ack_session_info {
|
||||
u32 seq_num;
|
||||
u32 bigger_ack_num;
|
||||
u16 src_port;
|
||||
u16 dst_port;
|
||||
u16 status;
|
||||
};
|
||||
|
||||
struct pending_acks {
|
||||
u32 ack_num;
|
||||
u32 session_index;
|
||||
struct txq_entry_t *txqe;
|
||||
};
|
||||
|
||||
struct tcp_ack_filter {
|
||||
struct ack_session_info ack_session_info[2 * MAX_TCP_SESSION];
|
||||
struct pending_acks pending_acks[MAX_PENDING_ACKS];
|
||||
u32 pending_base;
|
||||
u32 tcp_session;
|
||||
u32 pending_acks_idx;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
struct wilc_vif {
|
||||
u8 idx;
|
||||
u8 iftype;
|
||||
int monitor_flag;
|
||||
int mac_opened;
|
||||
u32 mgmt_reg_stypes;
|
||||
struct net_device_stats netstats;
|
||||
struct wilc *wilc;
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct host_if_drv *hif_drv;
|
||||
struct net_device *ndev;
|
||||
u8 mode;
|
||||
struct timer_list during_ip_timer;
|
||||
struct timer_list periodic_rssi;
|
||||
struct rf_info periodic_stat;
|
||||
struct tcp_ack_filter ack_filter;
|
||||
bool connecting;
|
||||
struct wilc_priv priv;
|
||||
struct list_head list;
|
||||
struct cfg80211_bss *bss;
|
||||
};
|
||||
|
||||
struct wilc {
|
||||
struct wiphy *wiphy;
|
||||
const struct wilc_hif_func *hif_func;
|
||||
int io_type;
|
||||
s8 mac_status;
|
||||
struct clk *rtc_clk;
|
||||
bool initialized;
|
||||
int dev_irq_num;
|
||||
int close;
|
||||
u8 vif_num;
|
||||
struct list_head vif_list;
|
||||
|
||||
/* protect vif list */
|
||||
struct mutex vif_mutex;
|
||||
struct srcu_struct srcu;
|
||||
u8 open_ifcs;
|
||||
|
||||
/* protect head of transmit queue */
|
||||
struct mutex txq_add_to_head_cs;
|
||||
|
||||
/* protect txq_entry_t transmit queue */
|
||||
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;
|
||||
struct completion sync_event;
|
||||
struct completion txq_event;
|
||||
struct completion txq_thread_started;
|
||||
|
||||
struct task_struct *txq_thread;
|
||||
|
||||
int quit;
|
||||
|
||||
/* lock to protect issue of wid command to firmware */
|
||||
struct mutex cfg_cmd_lock;
|
||||
struct wilc_cfg_frame cfg_frame;
|
||||
u32 cfg_frame_offset;
|
||||
u8 cfg_seq_no;
|
||||
|
||||
u8 *rx_buffer;
|
||||
u32 rx_buffer_offset;
|
||||
u8 *tx_buffer;
|
||||
|
||||
struct txq_entry_t txq_head;
|
||||
int txq_entries;
|
||||
|
||||
struct rxq_entry_t rxq_head;
|
||||
|
||||
const struct firmware *firmware;
|
||||
|
||||
struct device *dev;
|
||||
bool suspend_event;
|
||||
|
||||
int clients_count;
|
||||
struct workqueue_struct *hif_workqueue;
|
||||
enum chip_ps_states chip_ps_state;
|
||||
struct wilc_cfg cfg;
|
||||
void *bus_data;
|
||||
struct net_device *monitor_dev;
|
||||
|
||||
/* deinit lock */
|
||||
struct mutex deinit_lock;
|
||||
u8 sta_ch;
|
||||
u8 op_ch;
|
||||
struct ieee80211_channel channels[ARRAY_SIZE(wilc_2ghz_channels)];
|
||||
struct ieee80211_rate bitrates[ARRAY_SIZE(wilc_bitrates)];
|
||||
struct ieee80211_supported_band band;
|
||||
u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)];
|
||||
};
|
||||
|
||||
struct wilc_wfi_mon_priv {
|
||||
struct net_device *real_ndev;
|
||||
};
|
||||
|
||||
void wilc_frmw_to_host(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset);
|
||||
void wilc_mac_indicate(struct wilc *wilc);
|
||||
void wilc_netdev_cleanup(struct wilc *wilc);
|
||||
void wilc_wfi_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size);
|
||||
void wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode);
|
||||
struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
|
||||
int vif_type, enum nl80211_iftype type,
|
||||
bool rtnl_locked);
|
||||
#endif
|
1023
drivers/net/wireless/microchip/wilc1000/sdio.c
Normal file
1023
drivers/net/wireless/microchip/wilc1000/sdio.c
Normal file
File diff suppressed because it is too large
Load Diff
945
drivers/net/wireless/microchip/wilc1000/spi.c
Normal file
945
drivers/net/wireless/microchip/wilc1000/spi.c
Normal file
@@ -0,0 +1,945 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/crc7.h>
|
||||
|
||||
#include "netdev.h"
|
||||
#include "cfg80211.h"
|
||||
|
||||
struct wilc_spi {
|
||||
int crc_off;
|
||||
};
|
||||
|
||||
static const struct wilc_hif_func wilc_hif_spi;
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Spi protocol Function
|
||||
*
|
||||
********************************************/
|
||||
|
||||
#define CMD_DMA_WRITE 0xc1
|
||||
#define CMD_DMA_READ 0xc2
|
||||
#define CMD_INTERNAL_WRITE 0xc3
|
||||
#define CMD_INTERNAL_READ 0xc4
|
||||
#define CMD_TERMINATE 0xc5
|
||||
#define CMD_REPEAT 0xc6
|
||||
#define CMD_DMA_EXT_WRITE 0xc7
|
||||
#define CMD_DMA_EXT_READ 0xc8
|
||||
#define CMD_SINGLE_WRITE 0xc9
|
||||
#define CMD_SINGLE_READ 0xca
|
||||
#define CMD_RESET 0xcf
|
||||
|
||||
#define DATA_PKT_SZ_256 256
|
||||
#define DATA_PKT_SZ_512 512
|
||||
#define DATA_PKT_SZ_1K 1024
|
||||
#define DATA_PKT_SZ_4K (4 * 1024)
|
||||
#define DATA_PKT_SZ_8K (8 * 1024)
|
||||
#define DATA_PKT_SZ DATA_PKT_SZ_8K
|
||||
|
||||
#define USE_SPI_DMA 0
|
||||
|
||||
#define WILC_SPI_COMMAND_STAT_SUCCESS 0
|
||||
#define WILC_GET_RESP_HDR_START(h) (((h) >> 4) & 0xf)
|
||||
|
||||
struct wilc_spi_cmd {
|
||||
u8 cmd_type;
|
||||
union {
|
||||
struct {
|
||||
u8 addr[3];
|
||||
u8 crc[];
|
||||
} __packed simple_cmd;
|
||||
struct {
|
||||
u8 addr[3];
|
||||
u8 size[2];
|
||||
u8 crc[];
|
||||
} __packed dma_cmd;
|
||||
struct {
|
||||
u8 addr[3];
|
||||
u8 size[3];
|
||||
u8 crc[];
|
||||
} __packed dma_cmd_ext;
|
||||
struct {
|
||||
u8 addr[2];
|
||||
__be32 data;
|
||||
u8 crc[];
|
||||
} __packed internal_w_cmd;
|
||||
struct {
|
||||
u8 addr[3];
|
||||
__be32 data;
|
||||
u8 crc[];
|
||||
} __packed w_cmd;
|
||||
} u;
|
||||
} __packed;
|
||||
|
||||
struct wilc_spi_read_rsp_data {
|
||||
u8 rsp_cmd_type;
|
||||
u8 status;
|
||||
u8 resp_header;
|
||||
u8 resp_data[4];
|
||||
u8 crc[];
|
||||
} __packed;
|
||||
|
||||
struct wilc_spi_rsp_data {
|
||||
u8 rsp_cmd_type;
|
||||
u8 status;
|
||||
} __packed;
|
||||
|
||||
static int wilc_bus_probe(struct spi_device *spi)
|
||||
{
|
||||
int ret;
|
||||
struct wilc *wilc;
|
||||
struct wilc_spi *spi_priv;
|
||||
|
||||
spi_priv = kzalloc(sizeof(*spi_priv), GFP_KERNEL);
|
||||
if (!spi_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = wilc_cfg80211_init(&wilc, &spi->dev, WILC_HIF_SPI, &wilc_hif_spi);
|
||||
if (ret) {
|
||||
kfree(spi_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, wilc);
|
||||
wilc->dev = &spi->dev;
|
||||
wilc->bus_data = spi_priv;
|
||||
wilc->dev_irq_num = spi->irq;
|
||||
|
||||
wilc->rtc_clk = devm_clk_get(&spi->dev, "rtc_clk");
|
||||
if (PTR_ERR_OR_ZERO(wilc->rtc_clk) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
else if (!IS_ERR(wilc->rtc_clk))
|
||||
clk_prepare_enable(wilc->rtc_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_bus_remove(struct spi_device *spi)
|
||||
{
|
||||
struct wilc *wilc = spi_get_drvdata(spi);
|
||||
|
||||
if (!IS_ERR(wilc->rtc_clk))
|
||||
clk_disable_unprepare(wilc->rtc_clk);
|
||||
|
||||
wilc_netdev_cleanup(wilc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id wilc_of_match[] = {
|
||||
{ .compatible = "microchip,wilc1000", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, wilc_of_match);
|
||||
|
||||
static struct spi_driver wilc_spi_driver = {
|
||||
.driver = {
|
||||
.name = MODALIAS,
|
||||
.of_match_table = wilc_of_match,
|
||||
},
|
||||
.probe = wilc_bus_probe,
|
||||
.remove = wilc_bus_remove,
|
||||
};
|
||||
module_spi_driver(wilc_spi_driver);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
int ret;
|
||||
struct spi_message msg;
|
||||
|
||||
if (len > 0 && b) {
|
||||
struct spi_transfer tr = {
|
||||
.tx_buf = b,
|
||||
.len = len,
|
||||
.delay = {
|
||||
.value = 0,
|
||||
.unit = SPI_DELAY_UNIT_USECS
|
||||
},
|
||||
};
|
||||
char *r_buffer = kzalloc(len, GFP_KERNEL);
|
||||
|
||||
if (!r_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
tr.rx_buf = r_buffer;
|
||||
dev_dbg(&spi->dev, "Request writing %d bytes\n", len);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
spi_message_init(&msg);
|
||||
msg.spi = spi;
|
||||
msg.is_dma_mapped = USE_SPI_DMA;
|
||||
spi_message_add_tail(&tr, &msg);
|
||||
|
||||
ret = spi_sync(spi, &msg);
|
||||
if (ret < 0)
|
||||
dev_err(&spi->dev, "SPI transaction failed\n");
|
||||
|
||||
kfree(r_buffer);
|
||||
} else {
|
||||
dev_err(&spi->dev,
|
||||
"can't write data with the following length: %d\n",
|
||||
len);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wilc_spi_rx(struct wilc *wilc, u8 *rb, u32 rlen)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
int ret;
|
||||
|
||||
if (rlen > 0) {
|
||||
struct spi_message msg;
|
||||
struct spi_transfer tr = {
|
||||
.rx_buf = rb,
|
||||
.len = rlen,
|
||||
.delay = {
|
||||
.value = 0,
|
||||
.unit = SPI_DELAY_UNIT_USECS
|
||||
},
|
||||
|
||||
};
|
||||
char *t_buffer = kzalloc(rlen, GFP_KERNEL);
|
||||
|
||||
if (!t_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
tr.tx_buf = t_buffer;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
spi_message_init(&msg);
|
||||
msg.spi = spi;
|
||||
msg.is_dma_mapped = USE_SPI_DMA;
|
||||
spi_message_add_tail(&tr, &msg);
|
||||
|
||||
ret = spi_sync(spi, &msg);
|
||||
if (ret < 0)
|
||||
dev_err(&spi->dev, "SPI transaction failed\n");
|
||||
kfree(t_buffer);
|
||||
} else {
|
||||
dev_err(&spi->dev,
|
||||
"can't read data with the following length: %u\n",
|
||||
rlen);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wilc_spi_tx_rx(struct wilc *wilc, u8 *wb, u8 *rb, u32 rlen)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
int ret;
|
||||
|
||||
if (rlen > 0) {
|
||||
struct spi_message msg;
|
||||
struct spi_transfer tr = {
|
||||
.rx_buf = rb,
|
||||
.tx_buf = wb,
|
||||
.len = rlen,
|
||||
.bits_per_word = 8,
|
||||
.delay = {
|
||||
.value = 0,
|
||||
.unit = SPI_DELAY_UNIT_USECS
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
spi_message_init(&msg);
|
||||
msg.spi = spi;
|
||||
msg.is_dma_mapped = USE_SPI_DMA;
|
||||
|
||||
spi_message_add_tail(&tr, &msg);
|
||||
ret = spi_sync(spi, &msg);
|
||||
if (ret < 0)
|
||||
dev_err(&spi->dev, "SPI transaction failed\n");
|
||||
} else {
|
||||
dev_err(&spi->dev,
|
||||
"can't read data with the following length: %u\n",
|
||||
rlen);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
struct wilc_spi *spi_priv = wilc->bus_data;
|
||||
int ix, nbytes;
|
||||
int result = 0;
|
||||
u8 cmd, order, crc[2] = {0};
|
||||
|
||||
/*
|
||||
* Data
|
||||
*/
|
||||
ix = 0;
|
||||
do {
|
||||
if (sz <= DATA_PKT_SZ) {
|
||||
nbytes = sz;
|
||||
order = 0x3;
|
||||
} else {
|
||||
nbytes = DATA_PKT_SZ;
|
||||
if (ix == 0)
|
||||
order = 0x1;
|
||||
else
|
||||
order = 0x02;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write command
|
||||
*/
|
||||
cmd = 0xf0;
|
||||
cmd |= order;
|
||||
|
||||
if (wilc_spi_tx(wilc, &cmd, 1)) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed data block cmd write, bus error...\n");
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data
|
||||
*/
|
||||
if (wilc_spi_tx(wilc, &b[ix], nbytes)) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed data block write, bus error...\n");
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write Crc
|
||||
*/
|
||||
if (!spi_priv->crc_off) {
|
||||
if (wilc_spi_tx(wilc, crc, 2)) {
|
||||
dev_err(&spi->dev, "Failed data block crc write, bus error...\n");
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* No need to wait for response
|
||||
*/
|
||||
ix += nbytes;
|
||||
sz -= nbytes;
|
||||
} while (sz);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Spi Internal Read/Write Function
|
||||
*
|
||||
********************************************/
|
||||
static u8 wilc_get_crc7(u8 *buffer, u32 len)
|
||||
{
|
||||
return crc7_be(0xfe, buffer, len);
|
||||
}
|
||||
|
||||
static int wilc_spi_single_read(struct wilc *wilc, u8 cmd, u32 adr, void *b,
|
||||
u8 clockless)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
struct wilc_spi *spi_priv = wilc->bus_data;
|
||||
u8 wb[32], rb[32];
|
||||
int cmd_len, resp_len;
|
||||
u8 crc[2];
|
||||
struct wilc_spi_cmd *c;
|
||||
struct wilc_spi_read_rsp_data *r;
|
||||
|
||||
memset(wb, 0x0, sizeof(wb));
|
||||
memset(rb, 0x0, sizeof(rb));
|
||||
c = (struct wilc_spi_cmd *)wb;
|
||||
c->cmd_type = cmd;
|
||||
if (cmd == CMD_SINGLE_READ) {
|
||||
c->u.simple_cmd.addr[0] = adr >> 16;
|
||||
c->u.simple_cmd.addr[1] = adr >> 8;
|
||||
c->u.simple_cmd.addr[2] = adr;
|
||||
} else if (cmd == CMD_INTERNAL_READ) {
|
||||
c->u.simple_cmd.addr[0] = adr >> 8;
|
||||
if (clockless == 1)
|
||||
c->u.simple_cmd.addr[0] |= BIT(7);
|
||||
c->u.simple_cmd.addr[1] = adr;
|
||||
c->u.simple_cmd.addr[2] = 0x0;
|
||||
} else {
|
||||
dev_err(&spi->dev, "cmd [%x] not supported\n", cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cmd_len = offsetof(struct wilc_spi_cmd, u.simple_cmd.crc);
|
||||
resp_len = sizeof(*r);
|
||||
if (!spi_priv->crc_off) {
|
||||
c->u.simple_cmd.crc[0] = wilc_get_crc7(wb, cmd_len);
|
||||
cmd_len += 1;
|
||||
resp_len += 2;
|
||||
}
|
||||
|
||||
if (cmd_len + resp_len > ARRAY_SIZE(wb)) {
|
||||
dev_err(&spi->dev,
|
||||
"spi buffer size too small (%d) (%d) (%zu)\n",
|
||||
cmd_len, resp_len, ARRAY_SIZE(wb));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (wilc_spi_tx_rx(wilc, wb, rb, cmd_len + resp_len)) {
|
||||
dev_err(&spi->dev, "Failed cmd write, bus error...\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = (struct wilc_spi_read_rsp_data *)&rb[cmd_len];
|
||||
if (r->rsp_cmd_type != cmd) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed cmd response, cmd (%02x), resp (%02x)\n",
|
||||
cmd, r->rsp_cmd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->status != WILC_SPI_COMMAND_STAT_SUCCESS) {
|
||||
dev_err(&spi->dev, "Failed cmd state response state (%02x)\n",
|
||||
r->status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (WILC_GET_RESP_HDR_START(r->resp_header) != 0xf) {
|
||||
dev_err(&spi->dev, "Error, data read response (%02x)\n",
|
||||
r->resp_header);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (b)
|
||||
memcpy(b, r->resp_data, 4);
|
||||
|
||||
if (!spi_priv->crc_off)
|
||||
memcpy(crc, r->crc, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_spi_write_cmd(struct wilc *wilc, u8 cmd, u32 adr, u32 data,
|
||||
u8 clockless)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
struct wilc_spi *spi_priv = wilc->bus_data;
|
||||
u8 wb[32], rb[32];
|
||||
int cmd_len, resp_len;
|
||||
struct wilc_spi_cmd *c;
|
||||
struct wilc_spi_rsp_data *r;
|
||||
|
||||
memset(wb, 0x0, sizeof(wb));
|
||||
memset(rb, 0x0, sizeof(rb));
|
||||
c = (struct wilc_spi_cmd *)wb;
|
||||
c->cmd_type = cmd;
|
||||
if (cmd == CMD_INTERNAL_WRITE) {
|
||||
c->u.internal_w_cmd.addr[0] = adr >> 8;
|
||||
if (clockless == 1)
|
||||
c->u.internal_w_cmd.addr[0] |= BIT(7);
|
||||
|
||||
c->u.internal_w_cmd.addr[1] = adr;
|
||||
c->u.internal_w_cmd.data = cpu_to_be32(data);
|
||||
cmd_len = offsetof(struct wilc_spi_cmd, u.internal_w_cmd.crc);
|
||||
if (!spi_priv->crc_off)
|
||||
c->u.internal_w_cmd.crc[0] = wilc_get_crc7(wb, cmd_len);
|
||||
} else if (cmd == CMD_SINGLE_WRITE) {
|
||||
c->u.w_cmd.addr[0] = adr >> 16;
|
||||
c->u.w_cmd.addr[1] = adr >> 8;
|
||||
c->u.w_cmd.addr[2] = adr;
|
||||
c->u.w_cmd.data = cpu_to_be32(data);
|
||||
cmd_len = offsetof(struct wilc_spi_cmd, u.w_cmd.crc);
|
||||
if (!spi_priv->crc_off)
|
||||
c->u.w_cmd.crc[0] = wilc_get_crc7(wb, cmd_len);
|
||||
} else {
|
||||
dev_err(&spi->dev, "write cmd [%x] not supported\n", cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!spi_priv->crc_off)
|
||||
cmd_len += 1;
|
||||
|
||||
resp_len = sizeof(*r);
|
||||
|
||||
if (cmd_len + resp_len > ARRAY_SIZE(wb)) {
|
||||
dev_err(&spi->dev,
|
||||
"spi buffer size too small (%d) (%d) (%zu)\n",
|
||||
cmd_len, resp_len, ARRAY_SIZE(wb));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (wilc_spi_tx_rx(wilc, wb, rb, cmd_len + resp_len)) {
|
||||
dev_err(&spi->dev, "Failed cmd write, bus error...\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = (struct wilc_spi_rsp_data *)&rb[cmd_len];
|
||||
if (r->rsp_cmd_type != cmd) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed cmd response, cmd (%02x), resp (%02x)\n",
|
||||
cmd, r->rsp_cmd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->status != WILC_SPI_COMMAND_STAT_SUCCESS) {
|
||||
dev_err(&spi->dev, "Failed cmd state response state (%02x)\n",
|
||||
r->status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_spi_dma_rw(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
struct wilc_spi *spi_priv = wilc->bus_data;
|
||||
u8 wb[32], rb[32];
|
||||
int cmd_len, resp_len;
|
||||
int retry, ix = 0;
|
||||
u8 crc[2];
|
||||
struct wilc_spi_cmd *c;
|
||||
struct wilc_spi_rsp_data *r;
|
||||
|
||||
memset(wb, 0x0, sizeof(wb));
|
||||
memset(rb, 0x0, sizeof(rb));
|
||||
c = (struct wilc_spi_cmd *)wb;
|
||||
c->cmd_type = cmd;
|
||||
if (cmd == CMD_DMA_WRITE || cmd == CMD_DMA_READ) {
|
||||
c->u.dma_cmd.addr[0] = adr >> 16;
|
||||
c->u.dma_cmd.addr[1] = adr >> 8;
|
||||
c->u.dma_cmd.addr[2] = adr;
|
||||
c->u.dma_cmd.size[0] = sz >> 8;
|
||||
c->u.dma_cmd.size[1] = sz;
|
||||
cmd_len = offsetof(struct wilc_spi_cmd, u.dma_cmd.crc);
|
||||
if (!spi_priv->crc_off)
|
||||
c->u.dma_cmd.crc[0] = wilc_get_crc7(wb, cmd_len);
|
||||
} else if (cmd == CMD_DMA_EXT_WRITE || cmd == CMD_DMA_EXT_READ) {
|
||||
c->u.dma_cmd_ext.addr[0] = adr >> 16;
|
||||
c->u.dma_cmd_ext.addr[1] = adr >> 8;
|
||||
c->u.dma_cmd_ext.addr[2] = adr;
|
||||
c->u.dma_cmd_ext.size[0] = sz >> 16;
|
||||
c->u.dma_cmd_ext.size[1] = sz >> 8;
|
||||
c->u.dma_cmd_ext.size[2] = sz;
|
||||
cmd_len = offsetof(struct wilc_spi_cmd, u.dma_cmd_ext.crc);
|
||||
if (!spi_priv->crc_off)
|
||||
c->u.dma_cmd_ext.crc[0] = wilc_get_crc7(wb, cmd_len);
|
||||
} else {
|
||||
dev_err(&spi->dev, "dma read write cmd [%x] not supported\n",
|
||||
cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!spi_priv->crc_off)
|
||||
cmd_len += 1;
|
||||
|
||||
resp_len = sizeof(*r);
|
||||
|
||||
if (cmd_len + resp_len > ARRAY_SIZE(wb)) {
|
||||
dev_err(&spi->dev, "spi buffer size too small (%d)(%d) (%zu)\n",
|
||||
cmd_len, resp_len, ARRAY_SIZE(wb));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (wilc_spi_tx_rx(wilc, wb, rb, cmd_len + resp_len)) {
|
||||
dev_err(&spi->dev, "Failed cmd write, bus error...\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = (struct wilc_spi_rsp_data *)&rb[cmd_len];
|
||||
if (r->rsp_cmd_type != cmd) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed cmd response, cmd (%02x), resp (%02x)\n",
|
||||
cmd, r->rsp_cmd_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->status != WILC_SPI_COMMAND_STAT_SUCCESS) {
|
||||
dev_err(&spi->dev, "Failed cmd state response state (%02x)\n",
|
||||
r->status);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cmd == CMD_DMA_WRITE || cmd == CMD_DMA_EXT_WRITE)
|
||||
return 0;
|
||||
|
||||
while (sz > 0) {
|
||||
int nbytes;
|
||||
u8 rsp;
|
||||
|
||||
if (sz <= DATA_PKT_SZ)
|
||||
nbytes = sz;
|
||||
else
|
||||
nbytes = DATA_PKT_SZ;
|
||||
|
||||
/*
|
||||
* Data Response header
|
||||
*/
|
||||
retry = 100;
|
||||
do {
|
||||
if (wilc_spi_rx(wilc, &rsp, 1)) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed resp read, bus err\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (WILC_GET_RESP_HDR_START(rsp) == 0xf)
|
||||
break;
|
||||
} while (retry--);
|
||||
|
||||
/*
|
||||
* Read bytes
|
||||
*/
|
||||
if (wilc_spi_rx(wilc, &b[ix], nbytes)) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed block read, bus err\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read Crc
|
||||
*/
|
||||
if (!spi_priv->crc_off && wilc_spi_rx(wilc, crc, 2)) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed block crc read, bus err\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ix += nbytes;
|
||||
sz -= nbytes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
int result;
|
||||
u8 cmd = CMD_SINGLE_READ;
|
||||
u8 clockless = 0;
|
||||
|
||||
if (addr < WILC_SPI_CLOCKLESS_ADDR_LIMIT) {
|
||||
/* Clockless register */
|
||||
cmd = CMD_INTERNAL_READ;
|
||||
clockless = 1;
|
||||
}
|
||||
|
||||
result = wilc_spi_single_read(wilc, cmd, addr, data, clockless);
|
||||
if (result) {
|
||||
dev_err(&spi->dev, "Failed cmd, read reg (%08x)...\n", addr);
|
||||
return result;
|
||||
}
|
||||
|
||||
le32_to_cpus(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
int result;
|
||||
|
||||
if (size <= 4)
|
||||
return -EINVAL;
|
||||
|
||||
result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_READ, addr, buf, size);
|
||||
if (result) {
|
||||
dev_err(&spi->dev, "Failed cmd, read block (%08x)...\n", addr);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
int result;
|
||||
|
||||
result = wilc_spi_write_cmd(wilc, CMD_INTERNAL_WRITE, adr, dat, 0);
|
||||
if (result) {
|
||||
dev_err(&spi->dev, "Failed internal write cmd...\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
int result;
|
||||
|
||||
result = wilc_spi_single_read(wilc, CMD_INTERNAL_READ, adr, data, 0);
|
||||
if (result) {
|
||||
dev_err(&spi->dev, "Failed internal read cmd...\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
le32_to_cpus(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Spi interfaces
|
||||
*
|
||||
********************************************/
|
||||
|
||||
static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
int result;
|
||||
u8 cmd = CMD_SINGLE_WRITE;
|
||||
u8 clockless = 0;
|
||||
|
||||
if (addr < WILC_SPI_CLOCKLESS_ADDR_LIMIT) {
|
||||
/* Clockless register */
|
||||
cmd = CMD_INTERNAL_WRITE;
|
||||
clockless = 1;
|
||||
}
|
||||
|
||||
result = wilc_spi_write_cmd(wilc, cmd, addr, data, clockless);
|
||||
if (result) {
|
||||
dev_err(&spi->dev, "Failed cmd, write reg (%08x)...\n", addr);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
int result;
|
||||
|
||||
/*
|
||||
* has to be greated than 4
|
||||
*/
|
||||
if (size <= 4)
|
||||
return -EINVAL;
|
||||
|
||||
result = wilc_spi_dma_rw(wilc, CMD_DMA_EXT_WRITE, addr, NULL, size);
|
||||
if (result) {
|
||||
dev_err(&spi->dev,
|
||||
"Failed cmd, write block (%08x)...\n", addr);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Data
|
||||
*/
|
||||
result = spi_data_write(wilc, buf, size);
|
||||
if (result) {
|
||||
dev_err(&spi->dev, "Failed block data write...\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Bus interfaces
|
||||
*
|
||||
********************************************/
|
||||
|
||||
static int wilc_spi_deinit(struct wilc *wilc)
|
||||
{
|
||||
/*
|
||||
* TODO:
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_spi_init(struct wilc *wilc, bool resume)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
struct wilc_spi *spi_priv = wilc->bus_data;
|
||||
u32 reg;
|
||||
u32 chipid;
|
||||
static int isinit;
|
||||
int ret;
|
||||
|
||||
if (isinit) {
|
||||
ret = wilc_spi_read_reg(wilc, WILC_CHIPID, &chipid);
|
||||
if (ret)
|
||||
dev_err(&spi->dev, "Fail cmd read chip id...\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* configure protocol
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO: We can remove the CRC trials if there is a definite
|
||||
* way to reset
|
||||
*/
|
||||
/* the SPI to it's initial value. */
|
||||
ret = spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®);
|
||||
if (ret) {
|
||||
/*
|
||||
* Read failed. Try with CRC off. This might happen when module
|
||||
* is removed but chip isn't reset
|
||||
*/
|
||||
spi_priv->crc_off = 1;
|
||||
dev_err(&spi->dev,
|
||||
"Failed read with CRC on, retrying with CRC off\n");
|
||||
ret = spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®);
|
||||
if (ret) {
|
||||
/*
|
||||
* Read failed with both CRC on and off,
|
||||
* something went bad
|
||||
*/
|
||||
dev_err(&spi->dev, "Failed internal read protocol\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (spi_priv->crc_off == 0) {
|
||||
reg &= ~0xc; /* disable crc checking */
|
||||
reg &= ~0x70;
|
||||
reg |= (0x5 << 4);
|
||||
ret = spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev,
|
||||
"[wilc spi %d]: Failed internal write reg\n",
|
||||
__LINE__);
|
||||
return ret;
|
||||
}
|
||||
spi_priv->crc_off = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure can read back chip id correctly
|
||||
*/
|
||||
ret = wilc_spi_read_reg(wilc, WILC_CHIPID, &chipid);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Fail cmd read chip id...\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
isinit = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wilc_spi_read_size(struct wilc *wilc, u32 *size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = spi_internal_read(wilc,
|
||||
WILC_SPI_INT_STATUS - WILC_SPI_REG_BASE, size);
|
||||
*size = FIELD_GET(IRQ_DMA_WD_CNT_MASK, *size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status)
|
||||
{
|
||||
return spi_internal_read(wilc, WILC_SPI_INT_STATUS - WILC_SPI_REG_BASE,
|
||||
int_status);
|
||||
}
|
||||
|
||||
static int wilc_spi_clear_int_ext(struct wilc *wilc, u32 val)
|
||||
{
|
||||
return spi_internal_write(wilc, WILC_SPI_INT_CLEAR - WILC_SPI_REG_BASE,
|
||||
val);
|
||||
}
|
||||
|
||||
static int wilc_spi_sync_ext(struct wilc *wilc, int nint)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(wilc->dev);
|
||||
u32 reg;
|
||||
int ret, i;
|
||||
|
||||
if (nint > MAX_NUM_INT) {
|
||||
dev_err(&spi->dev, "Too many interrupts (%d)...\n", nint);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* interrupt pin mux select
|
||||
*/
|
||||
ret = wilc_spi_read_reg(wilc, WILC_PIN_MUX_0, ®);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed read reg (%08x)...\n",
|
||||
WILC_PIN_MUX_0);
|
||||
return ret;
|
||||
}
|
||||
reg |= BIT(8);
|
||||
ret = wilc_spi_write_reg(wilc, WILC_PIN_MUX_0, reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed write reg (%08x)...\n",
|
||||
WILC_PIN_MUX_0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* interrupt enable
|
||||
*/
|
||||
ret = wilc_spi_read_reg(wilc, WILC_INTR_ENABLE, ®);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed read reg (%08x)...\n",
|
||||
WILC_INTR_ENABLE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; (i < 5) && (nint > 0); i++, nint--)
|
||||
reg |= (BIT((27 + i)));
|
||||
|
||||
ret = wilc_spi_write_reg(wilc, WILC_INTR_ENABLE, reg);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed write reg (%08x)...\n",
|
||||
WILC_INTR_ENABLE);
|
||||
return ret;
|
||||
}
|
||||
if (nint) {
|
||||
ret = wilc_spi_read_reg(wilc, WILC_INTR2_ENABLE, ®);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed read reg (%08x)...\n",
|
||||
WILC_INTR2_ENABLE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; (i < 3) && (nint > 0); i++, nint--)
|
||||
reg |= BIT(i);
|
||||
|
||||
ret = wilc_spi_read_reg(wilc, WILC_INTR2_ENABLE, ®);
|
||||
if (ret) {
|
||||
dev_err(&spi->dev, "Failed write reg (%08x)...\n",
|
||||
WILC_INTR2_ENABLE);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Global spi HIF function table */
|
||||
static const struct wilc_hif_func wilc_hif_spi = {
|
||||
.hif_init = wilc_spi_init,
|
||||
.hif_deinit = wilc_spi_deinit,
|
||||
.hif_read_reg = wilc_spi_read_reg,
|
||||
.hif_write_reg = wilc_spi_write_reg,
|
||||
.hif_block_rx = wilc_spi_read,
|
||||
.hif_block_tx = wilc_spi_write,
|
||||
.hif_read_int = wilc_spi_read_int,
|
||||
.hif_clear_int_ext = wilc_spi_clear_int_ext,
|
||||
.hif_read_size = wilc_spi_read_size,
|
||||
.hif_block_tx_ext = wilc_spi_write,
|
||||
.hif_block_rx_ext = wilc_spi_read,
|
||||
.hif_sync_ext = wilc_spi_sync_ext,
|
||||
};
|
1238
drivers/net/wireless/microchip/wilc1000/wlan.c
Normal file
1238
drivers/net/wireless/microchip/wilc1000/wlan.c
Normal file
File diff suppressed because it is too large
Load Diff
397
drivers/net/wireless/microchip/wilc1000/wlan.h
Normal file
397
drivers/net/wireless/microchip/wilc1000/wlan.h
Normal file
@@ -0,0 +1,397 @@
|
||||
/* 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>
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Mac eth header length
|
||||
*
|
||||
********************************************/
|
||||
#define MAX_MAC_HDR_LEN 26 /* QOS_MAC_HDR_LEN */
|
||||
#define SUB_MSDU_HEADER_LENGTH 14
|
||||
#define SNAP_HDR_LEN 8
|
||||
#define ETHERNET_HDR_LEN 14
|
||||
#define WORD_ALIGNMENT_PAD 0
|
||||
|
||||
#define ETH_ETHERNET_HDR_OFFSET (MAX_MAC_HDR_LEN + \
|
||||
SUB_MSDU_HEADER_LENGTH + \
|
||||
SNAP_HDR_LEN - \
|
||||
ETHERNET_HDR_LEN + \
|
||||
WORD_ALIGNMENT_PAD)
|
||||
|
||||
#define HOST_HDR_OFFSET 4
|
||||
#define ETHERNET_HDR_LEN 14
|
||||
#define IP_HDR_LEN 20
|
||||
#define IP_HDR_OFFSET ETHERNET_HDR_LEN
|
||||
#define UDP_HDR_OFFSET (IP_HDR_LEN + IP_HDR_OFFSET)
|
||||
#define UDP_HDR_LEN 8
|
||||
#define UDP_DATA_OFFSET (UDP_HDR_OFFSET + UDP_HDR_LEN)
|
||||
#define ETH_CONFIG_PKT_HDR_LEN UDP_DATA_OFFSET
|
||||
|
||||
#define ETH_CONFIG_PKT_HDR_OFFSET (ETH_ETHERNET_HDR_OFFSET + \
|
||||
ETH_CONFIG_PKT_HDR_LEN)
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Register Defines
|
||||
*
|
||||
********************************************/
|
||||
#define WILC_PERIPH_REG_BASE 0x1000
|
||||
#define WILC_CHANGING_VIR_IF 0x108c
|
||||
#define WILC_CHIPID WILC_PERIPH_REG_BASE
|
||||
#define WILC_GLB_RESET_0 (WILC_PERIPH_REG_BASE + 0x400)
|
||||
#define WILC_PIN_MUX_0 (WILC_PERIPH_REG_BASE + 0x408)
|
||||
#define WILC_HOST_TX_CTRL (WILC_PERIPH_REG_BASE + 0x6c)
|
||||
#define WILC_HOST_RX_CTRL_0 (WILC_PERIPH_REG_BASE + 0x70)
|
||||
#define WILC_HOST_RX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x74)
|
||||
#define WILC_HOST_VMM_CTL (WILC_PERIPH_REG_BASE + 0x78)
|
||||
#define WILC_HOST_RX_CTRL (WILC_PERIPH_REG_BASE + 0x80)
|
||||
#define WILC_HOST_RX_EXTRA_SIZE (WILC_PERIPH_REG_BASE + 0x84)
|
||||
#define WILC_HOST_TX_CTRL_1 (WILC_PERIPH_REG_BASE + 0x88)
|
||||
#define WILC_MISC (WILC_PERIPH_REG_BASE + 0x428)
|
||||
#define WILC_INTR_REG_BASE (WILC_PERIPH_REG_BASE + 0xa00)
|
||||
#define WILC_INTR_ENABLE WILC_INTR_REG_BASE
|
||||
#define WILC_INTR2_ENABLE (WILC_INTR_REG_BASE + 4)
|
||||
|
||||
#define WILC_INTR_POLARITY (WILC_INTR_REG_BASE + 0x10)
|
||||
#define WILC_INTR_TYPE (WILC_INTR_REG_BASE + 0x20)
|
||||
#define WILC_INTR_CLEAR (WILC_INTR_REG_BASE + 0x30)
|
||||
#define WILC_INTR_STATUS (WILC_INTR_REG_BASE + 0x40)
|
||||
|
||||
#define WILC_RF_REVISION_ID 0x13f4
|
||||
|
||||
#define WILC_VMM_TBL_SIZE 64
|
||||
#define WILC_VMM_TX_TBL_BASE 0x150400
|
||||
#define WILC_VMM_RX_TBL_BASE 0x150500
|
||||
|
||||
#define WILC_VMM_BASE 0x150000
|
||||
#define WILC_VMM_CORE_CTL WILC_VMM_BASE
|
||||
#define WILC_VMM_TBL_CTL (WILC_VMM_BASE + 0x4)
|
||||
#define WILC_VMM_TBL_ENTRY (WILC_VMM_BASE + 0x8)
|
||||
#define WILC_VMM_TBL0_SIZE (WILC_VMM_BASE + 0xc)
|
||||
#define WILC_VMM_TO_HOST_SIZE (WILC_VMM_BASE + 0x10)
|
||||
#define WILC_VMM_CORE_CFG (WILC_VMM_BASE + 0x14)
|
||||
#define WILC_VMM_TBL_ACTIVE (WILC_VMM_BASE + 040)
|
||||
#define WILC_VMM_TBL_STATUS (WILC_VMM_BASE + 0x44)
|
||||
|
||||
#define WILC_SPI_REG_BASE 0xe800
|
||||
#define WILC_SPI_CTL WILC_SPI_REG_BASE
|
||||
#define WILC_SPI_MASTER_DMA_ADDR (WILC_SPI_REG_BASE + 0x4)
|
||||
#define WILC_SPI_MASTER_DMA_COUNT (WILC_SPI_REG_BASE + 0x8)
|
||||
#define WILC_SPI_SLAVE_DMA_ADDR (WILC_SPI_REG_BASE + 0xc)
|
||||
#define WILC_SPI_SLAVE_DMA_COUNT (WILC_SPI_REG_BASE + 0x10)
|
||||
#define WILC_SPI_TX_MODE (WILC_SPI_REG_BASE + 0x20)
|
||||
#define WILC_SPI_PROTOCOL_CONFIG (WILC_SPI_REG_BASE + 0x24)
|
||||
#define WILC_SPI_INTR_CTL (WILC_SPI_REG_BASE + 0x2c)
|
||||
#define WILC_SPI_INT_STATUS (WILC_SPI_REG_BASE + 0x40)
|
||||
#define WILC_SPI_INT_CLEAR (WILC_SPI_REG_BASE + 0x44)
|
||||
|
||||
#define WILC_SPI_WAKEUP_REG 0x1
|
||||
#define WILC_SPI_WAKEUP_BIT BIT(1)
|
||||
|
||||
#define WILC_SPI_PROTOCOL_OFFSET (WILC_SPI_PROTOCOL_CONFIG - \
|
||||
WILC_SPI_REG_BASE)
|
||||
|
||||
#define WILC_SPI_CLOCKLESS_ADDR_LIMIT 0x30
|
||||
|
||||
/* Functions IO enables bits */
|
||||
#define WILC_SDIO_CCCR_IO_EN_FUNC1 BIT(1)
|
||||
|
||||
/* Function/Interrupt enables bits */
|
||||
#define WILC_SDIO_CCCR_IEN_MASTER BIT(0)
|
||||
#define WILC_SDIO_CCCR_IEN_FUNC1 BIT(1)
|
||||
|
||||
/* Abort CCCR register bits */
|
||||
#define WILC_SDIO_CCCR_ABORT_RESET BIT(3)
|
||||
|
||||
/* Vendor specific CCCR registers */
|
||||
#define WILC_SDIO_WAKEUP_REG 0xf0
|
||||
#define WILC_SDIO_WAKEUP_BIT BIT(0)
|
||||
|
||||
#define WILC_SDIO_CLK_STATUS_REG 0xf1
|
||||
#define WILC_SDIO_CLK_STATUS_BIT BIT(0)
|
||||
|
||||
#define WILC_SDIO_INTERRUPT_DATA_SZ_REG 0xf2 /* Read size (2 bytes) */
|
||||
|
||||
#define WILC_SDIO_VMM_TBL_CTRL_REG 0xf6
|
||||
#define WILC_SDIO_IRQ_FLAG_REG 0xf7
|
||||
#define WILC_SDIO_IRQ_CLEAR_FLAG_REG 0xf8
|
||||
|
||||
#define WILC_SDIO_HOST_TO_FW_REG 0xfa
|
||||
#define WILC_SDIO_HOST_TO_FW_BIT BIT(0)
|
||||
|
||||
#define WILC_SDIO_FW_TO_HOST_REG 0xfc
|
||||
#define WILC_SDIO_FW_TO_HOST_BIT BIT(0)
|
||||
|
||||
/* Function 1 specific FBR register */
|
||||
#define WILC_SDIO_FBR_CSA_REG 0x10C /* CSA pointer (3 bytes) */
|
||||
#define WILC_SDIO_FBR_DATA_REG 0x10F
|
||||
|
||||
#define WILC_SDIO_F1_DATA_REG 0x0
|
||||
#define WILC_SDIO_EXT_IRQ_FLAG_REG 0x4
|
||||
|
||||
#define WILC_AHB_DATA_MEM_BASE 0x30000
|
||||
#define WILC_AHB_SHARE_MEM_BASE 0xd0000
|
||||
|
||||
#define WILC_VMM_TBL_RX_SHADOW_BASE WILC_AHB_SHARE_MEM_BASE
|
||||
#define WILC_VMM_TBL_RX_SHADOW_SIZE 256
|
||||
|
||||
#define WILC_FW_HOST_COMM 0x13c0
|
||||
#define WILC_GP_REG_0 0x149c
|
||||
#define WILC_GP_REG_1 0x14a0
|
||||
|
||||
#define WILC_HAVE_SDIO_IRQ_GPIO BIT(0)
|
||||
#define WILC_HAVE_USE_PMU BIT(1)
|
||||
#define WILC_HAVE_SLEEP_CLK_SRC_RTC BIT(2)
|
||||
#define WILC_HAVE_SLEEP_CLK_SRC_XO BIT(3)
|
||||
#define WILC_HAVE_EXT_PA_INV_TX_RX BIT(4)
|
||||
#define WILC_HAVE_LEGACY_RF_SETTINGS BIT(5)
|
||||
#define WILC_HAVE_XTAL_24 BIT(6)
|
||||
#define WILC_HAVE_DISABLE_WILC_UART BIT(7)
|
||||
#define WILC_HAVE_USE_IRQ_AS_HOST_WAKE BIT(8)
|
||||
|
||||
#define WILC_CORTUS_INTERRUPT_BASE 0x10A8
|
||||
#define WILC_CORTUS_INTERRUPT_1 (WILC_CORTUS_INTERRUPT_BASE + 0x4)
|
||||
#define WILC_CORTUS_INTERRUPT_2 (WILC_CORTUS_INTERRUPT_BASE + 0x8)
|
||||
|
||||
/* tx control register 1 to 4 for RX */
|
||||
#define WILC_REG_4_TO_1_RX 0x1e1c
|
||||
|
||||
/* tx control register 1 to 4 for TX Bank_0 */
|
||||
#define WILC_REG_4_TO_1_TX_BANK0 0x1e9c
|
||||
|
||||
#define WILC_CORTUS_RESET_MUX_SEL 0x1118
|
||||
#define WILC_CORTUS_BOOT_REGISTER 0xc0000
|
||||
|
||||
#define WILC_CORTUS_BOOT_FROM_IRAM 0x71
|
||||
|
||||
#define WILC_1000_BASE_ID 0x100000
|
||||
|
||||
#define WILC_1000_BASE_ID_2A 0x1002A0
|
||||
#define WILC_1000_BASE_ID_2A_REV1 (WILC_1000_BASE_ID_2A + 1)
|
||||
|
||||
#define WILC_1000_BASE_ID_2B 0x1002B0
|
||||
#define WILC_1000_BASE_ID_2B_REV1 (WILC_1000_BASE_ID_2B + 1)
|
||||
#define WILC_1000_BASE_ID_2B_REV2 (WILC_1000_BASE_ID_2B + 2)
|
||||
|
||||
#define WILC_CHIP_REV_FIELD GENMASK(11, 0)
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Wlan Defines
|
||||
*
|
||||
********************************************/
|
||||
#define WILC_CFG_PKT 1
|
||||
#define WILC_NET_PKT 0
|
||||
#define WILC_MGMT_PKT 2
|
||||
|
||||
#define WILC_CFG_SET 1
|
||||
#define WILC_CFG_QUERY 0
|
||||
|
||||
#define WILC_CFG_RSP 1
|
||||
#define WILC_CFG_RSP_STATUS 2
|
||||
#define WILC_CFG_RSP_SCAN 3
|
||||
|
||||
#define WILC_ABORT_REQ_BIT BIT(31)
|
||||
|
||||
#define WILC_RX_BUFF_SIZE (96 * 1024)
|
||||
#define WILC_TX_BUFF_SIZE (64 * 1024)
|
||||
|
||||
#define MODALIAS "WILC_SPI"
|
||||
|
||||
#define WILC_PKT_HDR_CONFIG_FIELD BIT(31)
|
||||
#define WILC_PKT_HDR_OFFSET_FIELD GENMASK(30, 22)
|
||||
#define WILC_PKT_HDR_TOTAL_LEN_FIELD GENMASK(21, 11)
|
||||
#define WILC_PKT_HDR_LEN_FIELD GENMASK(10, 0)
|
||||
|
||||
#define WILC_INTERRUPT_DATA_SIZE GENMASK(14, 0)
|
||||
|
||||
#define WILC_VMM_BUFFER_SIZE GENMASK(9, 0)
|
||||
|
||||
#define WILC_VMM_HDR_TYPE BIT(31)
|
||||
#define WILC_VMM_HDR_MGMT_FIELD BIT(30)
|
||||
#define WILC_VMM_HDR_PKT_SIZE GENMASK(29, 15)
|
||||
#define WILC_VMM_HDR_BUFF_SIZE GENMASK(14, 0)
|
||||
|
||||
#define WILC_VMM_ENTRY_COUNT GENMASK(8, 3)
|
||||
#define WILC_VMM_ENTRY_AVAILABLE BIT(2)
|
||||
/*******************************************/
|
||||
/* E0 and later Interrupt flags. */
|
||||
/*******************************************/
|
||||
/*******************************************/
|
||||
/* E0 and later Interrupt flags. */
|
||||
/* IRQ Status word */
|
||||
/* 15:0 = DMA count in words. */
|
||||
/* 16: INT0 flag */
|
||||
/* 17: INT1 flag */
|
||||
/* 18: INT2 flag */
|
||||
/* 19: INT3 flag */
|
||||
/* 20: INT4 flag */
|
||||
/* 21: INT5 flag */
|
||||
/*******************************************/
|
||||
#define IRG_FLAGS_OFFSET 16
|
||||
#define IRQ_DMA_WD_CNT_MASK GENMASK(IRG_FLAGS_OFFSET - 1, 0)
|
||||
#define INT_0 BIT(IRG_FLAGS_OFFSET)
|
||||
#define INT_1 BIT(IRG_FLAGS_OFFSET + 1)
|
||||
#define INT_2 BIT(IRG_FLAGS_OFFSET + 2)
|
||||
#define INT_3 BIT(IRG_FLAGS_OFFSET + 3)
|
||||
#define INT_4 BIT(IRG_FLAGS_OFFSET + 4)
|
||||
#define INT_5 BIT(IRG_FLAGS_OFFSET + 5)
|
||||
#define MAX_NUM_INT 5
|
||||
#define IRG_FLAGS_MASK GENMASK(IRG_FLAGS_OFFSET + MAX_NUM_INT, \
|
||||
IRG_FLAGS_OFFSET)
|
||||
|
||||
/*******************************************/
|
||||
/* E0 and later Interrupt flags. */
|
||||
/* IRQ Clear word */
|
||||
/* 0: Clear INT0 */
|
||||
/* 1: Clear INT1 */
|
||||
/* 2: Clear INT2 */
|
||||
/* 3: Clear INT3 */
|
||||
/* 4: Clear INT4 */
|
||||
/* 5: Clear INT5 */
|
||||
/* 6: Select VMM table 1 */
|
||||
/* 7: Select VMM table 2 */
|
||||
/* 8: Enable VMM */
|
||||
/*******************************************/
|
||||
#define CLR_INT0 BIT(0)
|
||||
#define CLR_INT1 BIT(1)
|
||||
#define CLR_INT2 BIT(2)
|
||||
#define CLR_INT3 BIT(3)
|
||||
#define CLR_INT4 BIT(4)
|
||||
#define CLR_INT5 BIT(5)
|
||||
#define SEL_VMM_TBL0 BIT(6)
|
||||
#define SEL_VMM_TBL1 BIT(7)
|
||||
#define EN_VMM BIT(8)
|
||||
|
||||
#define DATA_INT_EXT INT_0
|
||||
#define ALL_INT_EXT DATA_INT_EXT
|
||||
#define NUM_INT_EXT 1
|
||||
#define UNHANDLED_IRQ_MASK GENMASK(MAX_NUM_INT - 1, NUM_INT_EXT)
|
||||
|
||||
#define DATA_INT_CLR CLR_INT0
|
||||
|
||||
#define ENABLE_RX_VMM (SEL_VMM_TBL1 | EN_VMM)
|
||||
#define ENABLE_TX_VMM (SEL_VMM_TBL0 | EN_VMM)
|
||||
/* time for expiring the completion of cfg packets */
|
||||
#define WILC_CFG_PKTS_TIMEOUT msecs_to_jiffies(2000)
|
||||
|
||||
#define IS_MANAGMEMENT 0x100
|
||||
#define IS_MANAGMEMENT_CALLBACK 0x080
|
||||
#define IS_MGMT_STATUS_SUCCES 0x040
|
||||
|
||||
#define WILC_WID_TYPE GENMASK(15, 12)
|
||||
#define WILC_VMM_ENTRY_FULL_RETRY 1
|
||||
/********************************************
|
||||
*
|
||||
* Tx/Rx Queue Structure
|
||||
*
|
||||
********************************************/
|
||||
|
||||
struct txq_entry_t {
|
||||
struct list_head list;
|
||||
int type;
|
||||
int ack_idx;
|
||||
u8 *buffer;
|
||||
int buffer_size;
|
||||
void *priv;
|
||||
int status;
|
||||
struct wilc_vif *vif;
|
||||
void (*tx_complete_func)(void *priv, int status);
|
||||
};
|
||||
|
||||
struct rxq_entry_t {
|
||||
struct list_head list;
|
||||
u8 *buffer;
|
||||
int buffer_size;
|
||||
};
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Host IF Structure
|
||||
*
|
||||
********************************************/
|
||||
struct wilc;
|
||||
struct wilc_hif_func {
|
||||
int (*hif_init)(struct wilc *wilc, bool resume);
|
||||
int (*hif_deinit)(struct wilc *wilc);
|
||||
int (*hif_read_reg)(struct wilc *wilc, u32 addr, u32 *data);
|
||||
int (*hif_write_reg)(struct wilc *wilc, u32 addr, u32 data);
|
||||
int (*hif_block_rx)(struct wilc *wilc, u32 addr, u8 *buf, u32 size);
|
||||
int (*hif_block_tx)(struct wilc *wilc, u32 addr, u8 *buf, u32 size);
|
||||
int (*hif_read_int)(struct wilc *wilc, u32 *int_status);
|
||||
int (*hif_clear_int_ext)(struct wilc *wilc, u32 val);
|
||||
int (*hif_read_size)(struct wilc *wilc, u32 *size);
|
||||
int (*hif_block_tx_ext)(struct wilc *wilc, u32 addr, u8 *buf, u32 size);
|
||||
int (*hif_block_rx_ext)(struct wilc *wilc, u32 addr, u8 *buf, u32 size);
|
||||
int (*hif_sync_ext)(struct wilc *wilc, int nint);
|
||||
int (*enable_interrupt)(struct wilc *nic);
|
||||
void (*disable_interrupt)(struct wilc *nic);
|
||||
};
|
||||
|
||||
#define WILC_MAX_CFG_FRAME_SIZE 1468
|
||||
|
||||
struct tx_complete_data {
|
||||
int size;
|
||||
void *buff;
|
||||
struct sk_buff *skb;
|
||||
};
|
||||
|
||||
struct wilc_cfg_cmd_hdr {
|
||||
u8 cmd_type;
|
||||
u8 seq_no;
|
||||
__le16 total_len;
|
||||
__le32 driver_handler;
|
||||
};
|
||||
|
||||
struct wilc_cfg_frame {
|
||||
struct wilc_cfg_cmd_hdr hdr;
|
||||
u8 frame[WILC_MAX_CFG_FRAME_SIZE];
|
||||
};
|
||||
|
||||
struct wilc_cfg_rsp {
|
||||
u8 type;
|
||||
u8 seq_no;
|
||||
};
|
||||
|
||||
struct wilc;
|
||||
struct wilc_vif;
|
||||
|
||||
int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer,
|
||||
u32 buffer_size);
|
||||
int wilc_wlan_start(struct wilc *wilc);
|
||||
int wilc_wlan_stop(struct wilc *wilc, struct wilc_vif *vif);
|
||||
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
|
||||
u32 buffer_size,
|
||||
void (*tx_complete_fn)(void *, int));
|
||||
int wilc_wlan_handle_txq(struct wilc *wl, u32 *txq_count);
|
||||
void wilc_handle_isr(struct wilc *wilc);
|
||||
void wilc_wlan_cleanup(struct net_device *dev);
|
||||
int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u16 wid, u8 *buffer,
|
||||
u32 buffer_size, int commit, u32 drv_handler);
|
||||
int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u16 wid, int commit,
|
||||
u32 drv_handler);
|
||||
int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer,
|
||||
u32 buffer_size, void (*func)(void *, int));
|
||||
void wilc_enable_tcp_ack_filter(struct wilc_vif *vif, bool value);
|
||||
int wilc_wlan_get_num_conn_ifcs(struct wilc *wilc);
|
||||
netdev_tx_t wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
|
||||
void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size);
|
||||
void host_wakeup_notify(struct wilc *wilc);
|
||||
void host_sleep_notify(struct wilc *wilc);
|
||||
void chip_allow_sleep(struct wilc *wilc);
|
||||
void chip_wakeup(struct wilc *wilc);
|
||||
int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids,
|
||||
u32 count);
|
||||
int wilc_wlan_init(struct net_device *dev);
|
||||
u32 wilc_get_chipid(struct wilc *wilc, bool update);
|
||||
#endif
|
413
drivers/net/wireless/microchip/wilc1000/wlan_cfg.c
Normal file
413
drivers/net/wireless/microchip/wilc1000/wlan_cfg.c
Normal file
@@ -0,0 +1,413 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include "wlan_if.h"
|
||||
#include "wlan.h"
|
||||
#include "wlan_cfg.h"
|
||||
#include "netdev.h"
|
||||
|
||||
enum cfg_cmd_type {
|
||||
CFG_BYTE_CMD = 0,
|
||||
CFG_HWORD_CMD = 1,
|
||||
CFG_WORD_CMD = 2,
|
||||
CFG_STR_CMD = 3,
|
||||
CFG_BIN_CMD = 4
|
||||
};
|
||||
|
||||
static const struct wilc_cfg_byte g_cfg_byte[] = {
|
||||
{WID_STATUS, 0},
|
||||
{WID_RSSI, 0},
|
||||
{WID_LINKSPEED, 0},
|
||||
{WID_NIL, 0}
|
||||
};
|
||||
|
||||
static const struct wilc_cfg_hword g_cfg_hword[] = {
|
||||
{WID_NIL, 0}
|
||||
};
|
||||
|
||||
static const struct wilc_cfg_word g_cfg_word[] = {
|
||||
{WID_FAILED_COUNT, 0},
|
||||
{WID_RECEIVED_FRAGMENT_COUNT, 0},
|
||||
{WID_SUCCESS_FRAME_COUNT, 0},
|
||||
{WID_GET_INACTIVE_TIME, 0},
|
||||
{WID_NIL, 0}
|
||||
|
||||
};
|
||||
|
||||
static const struct wilc_cfg_str g_cfg_str[] = {
|
||||
{WID_FIRMWARE_VERSION, NULL},
|
||||
{WID_MAC_ADDR, NULL},
|
||||
{WID_ASSOC_RES_INFO, NULL},
|
||||
{WID_NIL, NULL}
|
||||
};
|
||||
|
||||
#define WILC_RESP_MSG_TYPE_CONFIG_REPLY 'R'
|
||||
#define WILC_RESP_MSG_TYPE_STATUS_INFO 'I'
|
||||
#define WILC_RESP_MSG_TYPE_NETWORK_INFO 'N'
|
||||
#define WILC_RESP_MSG_TYPE_SCAN_COMPLETE 'S'
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Configuration Functions
|
||||
*
|
||||
********************************************/
|
||||
|
||||
static int wilc_wlan_cfg_set_byte(u8 *frame, u32 offset, u16 id, u8 val8)
|
||||
{
|
||||
if ((offset + 4) >= WILC_MAX_CFG_FRAME_SIZE)
|
||||
return 0;
|
||||
|
||||
put_unaligned_le16(id, &frame[offset]);
|
||||
put_unaligned_le16(1, &frame[offset + 2]);
|
||||
frame[offset + 4] = val8;
|
||||
return 5;
|
||||
}
|
||||
|
||||
static int wilc_wlan_cfg_set_hword(u8 *frame, u32 offset, u16 id, u16 val16)
|
||||
{
|
||||
if ((offset + 5) >= WILC_MAX_CFG_FRAME_SIZE)
|
||||
return 0;
|
||||
|
||||
put_unaligned_le16(id, &frame[offset]);
|
||||
put_unaligned_le16(2, &frame[offset + 2]);
|
||||
put_unaligned_le16(val16, &frame[offset + 4]);
|
||||
|
||||
return 6;
|
||||
}
|
||||
|
||||
static int wilc_wlan_cfg_set_word(u8 *frame, u32 offset, u16 id, u32 val32)
|
||||
{
|
||||
if ((offset + 7) >= WILC_MAX_CFG_FRAME_SIZE)
|
||||
return 0;
|
||||
|
||||
put_unaligned_le16(id, &frame[offset]);
|
||||
put_unaligned_le16(4, &frame[offset + 2]);
|
||||
put_unaligned_le32(val32, &frame[offset + 4]);
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
static int wilc_wlan_cfg_set_str(u8 *frame, u32 offset, u16 id, u8 *str,
|
||||
u32 size)
|
||||
{
|
||||
if ((offset + size + 4) >= WILC_MAX_CFG_FRAME_SIZE)
|
||||
return 0;
|
||||
|
||||
put_unaligned_le16(id, &frame[offset]);
|
||||
put_unaligned_le16(size, &frame[offset + 2]);
|
||||
if (str && size != 0)
|
||||
memcpy(&frame[offset + 4], str, size);
|
||||
|
||||
return (size + 4);
|
||||
}
|
||||
|
||||
static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size)
|
||||
{
|
||||
u32 i;
|
||||
u8 checksum = 0;
|
||||
|
||||
if ((offset + size + 5) >= WILC_MAX_CFG_FRAME_SIZE)
|
||||
return 0;
|
||||
|
||||
put_unaligned_le16(id, &frame[offset]);
|
||||
put_unaligned_le16(size, &frame[offset + 2]);
|
||||
|
||||
if ((b) && size != 0) {
|
||||
memcpy(&frame[offset + 4], b, size);
|
||||
for (i = 0; i < size; i++)
|
||||
checksum += frame[offset + i + 4];
|
||||
}
|
||||
|
||||
frame[offset + size + 4] = checksum;
|
||||
|
||||
return (size + 5);
|
||||
}
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Configuration Response Functions
|
||||
*
|
||||
********************************************/
|
||||
|
||||
static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size)
|
||||
{
|
||||
u16 wid;
|
||||
u32 len = 0, i = 0;
|
||||
struct wilc_cfg *cfg = &wl->cfg;
|
||||
|
||||
while (size > 0) {
|
||||
i = 0;
|
||||
wid = get_unaligned_le16(info);
|
||||
|
||||
switch (FIELD_GET(WILC_WID_TYPE, wid)) {
|
||||
case WID_CHAR:
|
||||
while (cfg->b[i].id != WID_NIL && cfg->b[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->b[i].id == wid)
|
||||
cfg->b[i].val = info[4];
|
||||
|
||||
len = 3;
|
||||
break;
|
||||
|
||||
case WID_SHORT:
|
||||
while (cfg->hw[i].id != WID_NIL && cfg->hw[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->hw[i].id == wid)
|
||||
cfg->hw[i].val = get_unaligned_le16(&info[4]);
|
||||
|
||||
len = 4;
|
||||
break;
|
||||
|
||||
case WID_INT:
|
||||
while (cfg->w[i].id != WID_NIL && cfg->w[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->w[i].id == wid)
|
||||
cfg->w[i].val = get_unaligned_le32(&info[4]);
|
||||
|
||||
len = 6;
|
||||
break;
|
||||
|
||||
case WID_STR:
|
||||
while (cfg->s[i].id != WID_NIL && cfg->s[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->s[i].id == wid)
|
||||
memcpy(cfg->s[i].str, &info[2], info[2] + 2);
|
||||
|
||||
len = 2 + info[2];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
size -= (2 + len);
|
||||
info += (2 + len);
|
||||
}
|
||||
}
|
||||
|
||||
static void wilc_wlan_parse_info_frame(struct wilc *wl, u8 *info)
|
||||
{
|
||||
u32 wid, len;
|
||||
|
||||
wid = get_unaligned_le16(info);
|
||||
|
||||
len = info[2];
|
||||
|
||||
if (len == 1 && wid == WID_STATUS) {
|
||||
int i = 0;
|
||||
|
||||
while (wl->cfg.b[i].id != WID_NIL &&
|
||||
wl->cfg.b[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (wl->cfg.b[i].id == wid)
|
||||
wl->cfg.b[i].val = info[3];
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Configuration Exported Functions
|
||||
*
|
||||
********************************************/
|
||||
|
||||
int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size)
|
||||
{
|
||||
u8 type = FIELD_GET(WILC_WID_TYPE, id);
|
||||
int ret = 0;
|
||||
|
||||
switch (type) {
|
||||
case CFG_BYTE_CMD:
|
||||
if (size >= 1)
|
||||
ret = wilc_wlan_cfg_set_byte(frame, offset, id, *buf);
|
||||
break;
|
||||
|
||||
case CFG_HWORD_CMD:
|
||||
if (size >= 2)
|
||||
ret = wilc_wlan_cfg_set_hword(frame, offset, id,
|
||||
*((u16 *)buf));
|
||||
break;
|
||||
|
||||
case CFG_WORD_CMD:
|
||||
if (size >= 4)
|
||||
ret = wilc_wlan_cfg_set_word(frame, offset, id,
|
||||
*((u32 *)buf));
|
||||
break;
|
||||
|
||||
case CFG_STR_CMD:
|
||||
ret = wilc_wlan_cfg_set_str(frame, offset, id, buf, size);
|
||||
break;
|
||||
|
||||
case CFG_BIN_CMD:
|
||||
ret = wilc_wlan_cfg_set_bin(frame, offset, id, buf, size);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id)
|
||||
{
|
||||
if ((offset + 2) >= WILC_MAX_CFG_FRAME_SIZE)
|
||||
return 0;
|
||||
|
||||
put_unaligned_le16(id, &frame[offset]);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer,
|
||||
u32 buffer_size)
|
||||
{
|
||||
u8 type = FIELD_GET(WILC_WID_TYPE, wid);
|
||||
int i, ret = 0;
|
||||
struct wilc_cfg *cfg = &wl->cfg;
|
||||
|
||||
i = 0;
|
||||
if (type == CFG_BYTE_CMD) {
|
||||
while (cfg->b[i].id != WID_NIL && cfg->b[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->b[i].id == wid) {
|
||||
memcpy(buffer, &cfg->b[i].val, 1);
|
||||
ret = 1;
|
||||
}
|
||||
} else if (type == CFG_HWORD_CMD) {
|
||||
while (cfg->hw[i].id != WID_NIL && cfg->hw[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->hw[i].id == wid) {
|
||||
memcpy(buffer, &cfg->hw[i].val, 2);
|
||||
ret = 2;
|
||||
}
|
||||
} else if (type == CFG_WORD_CMD) {
|
||||
while (cfg->w[i].id != WID_NIL && cfg->w[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->w[i].id == wid) {
|
||||
memcpy(buffer, &cfg->w[i].val, 4);
|
||||
ret = 4;
|
||||
}
|
||||
} else if (type == CFG_STR_CMD) {
|
||||
while (cfg->s[i].id != WID_NIL && cfg->s[i].id != wid)
|
||||
i++;
|
||||
|
||||
if (cfg->s[i].id == wid) {
|
||||
u16 size = get_unaligned_le16(cfg->s[i].str);
|
||||
|
||||
if (buffer_size >= size) {
|
||||
memcpy(buffer, &cfg->s[i].str[2], size);
|
||||
ret = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
|
||||
struct wilc_cfg_rsp *rsp)
|
||||
{
|
||||
u8 msg_type;
|
||||
u8 msg_id;
|
||||
|
||||
msg_type = frame[0];
|
||||
msg_id = frame[1]; /* seq no */
|
||||
frame += 4;
|
||||
size -= 4;
|
||||
rsp->type = 0;
|
||||
|
||||
switch (msg_type) {
|
||||
case WILC_RESP_MSG_TYPE_CONFIG_REPLY:
|
||||
wilc_wlan_parse_response_frame(wilc, frame, size);
|
||||
rsp->type = WILC_CFG_RSP;
|
||||
rsp->seq_no = msg_id;
|
||||
break;
|
||||
|
||||
case WILC_RESP_MSG_TYPE_STATUS_INFO:
|
||||
wilc_wlan_parse_info_frame(wilc, frame);
|
||||
rsp->type = WILC_CFG_RSP_STATUS;
|
||||
rsp->seq_no = msg_id;
|
||||
/* call host interface info parse as well */
|
||||
wilc_gnrl_async_info_received(wilc, frame - 4, size + 4);
|
||||
break;
|
||||
|
||||
case WILC_RESP_MSG_TYPE_NETWORK_INFO:
|
||||
wilc_network_info_received(wilc, frame - 4, size + 4);
|
||||
break;
|
||||
|
||||
case WILC_RESP_MSG_TYPE_SCAN_COMPLETE:
|
||||
wilc_scan_complete_received(wilc, frame - 4, size + 4);
|
||||
break;
|
||||
|
||||
default:
|
||||
rsp->seq_no = msg_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int wilc_wlan_cfg_init(struct wilc *wl)
|
||||
{
|
||||
struct wilc_cfg_str_vals *str_vals;
|
||||
int i = 0;
|
||||
|
||||
wl->cfg.b = kmemdup(g_cfg_byte, sizeof(g_cfg_byte), GFP_KERNEL);
|
||||
if (!wl->cfg.b)
|
||||
return -ENOMEM;
|
||||
|
||||
wl->cfg.hw = kmemdup(g_cfg_hword, sizeof(g_cfg_hword), GFP_KERNEL);
|
||||
if (!wl->cfg.hw)
|
||||
goto out_b;
|
||||
|
||||
wl->cfg.w = kmemdup(g_cfg_word, sizeof(g_cfg_word), GFP_KERNEL);
|
||||
if (!wl->cfg.w)
|
||||
goto out_hw;
|
||||
|
||||
wl->cfg.s = kmemdup(g_cfg_str, sizeof(g_cfg_str), GFP_KERNEL);
|
||||
if (!wl->cfg.s)
|
||||
goto out_w;
|
||||
|
||||
str_vals = kzalloc(sizeof(*str_vals), GFP_KERNEL);
|
||||
if (!str_vals)
|
||||
goto out_s;
|
||||
|
||||
wl->cfg.str_vals = str_vals;
|
||||
/* store the string cfg parameters */
|
||||
wl->cfg.s[i].id = WID_FIRMWARE_VERSION;
|
||||
wl->cfg.s[i].str = str_vals->firmware_version;
|
||||
i++;
|
||||
wl->cfg.s[i].id = WID_MAC_ADDR;
|
||||
wl->cfg.s[i].str = str_vals->mac_address;
|
||||
i++;
|
||||
wl->cfg.s[i].id = WID_ASSOC_RES_INFO;
|
||||
wl->cfg.s[i].str = str_vals->assoc_rsp;
|
||||
i++;
|
||||
wl->cfg.s[i].id = WID_NIL;
|
||||
wl->cfg.s[i].str = NULL;
|
||||
return 0;
|
||||
|
||||
out_s:
|
||||
kfree(wl->cfg.s);
|
||||
out_w:
|
||||
kfree(wl->cfg.w);
|
||||
out_hw:
|
||||
kfree(wl->cfg.hw);
|
||||
out_b:
|
||||
kfree(wl->cfg.b);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void wilc_wlan_cfg_deinit(struct wilc *wl)
|
||||
{
|
||||
kfree(wl->cfg.b);
|
||||
kfree(wl->cfg.hw);
|
||||
kfree(wl->cfg.w);
|
||||
kfree(wl->cfg.s);
|
||||
kfree(wl->cfg.str_vals);
|
||||
}
|
54
drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
Normal file
54
drivers/net/wireless/microchip/wilc1000/wlan_cfg.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef WILC_WLAN_CFG_H
|
||||
#define WILC_WLAN_CFG_H
|
||||
|
||||
struct wilc_cfg_byte {
|
||||
u16 id;
|
||||
u8 val;
|
||||
};
|
||||
|
||||
struct wilc_cfg_hword {
|
||||
u16 id;
|
||||
u16 val;
|
||||
};
|
||||
|
||||
struct wilc_cfg_word {
|
||||
u16 id;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
struct wilc_cfg_str {
|
||||
u16 id;
|
||||
u8 *str;
|
||||
};
|
||||
|
||||
struct wilc_cfg_str_vals {
|
||||
u8 mac_address[7];
|
||||
u8 firmware_version[129];
|
||||
u8 assoc_rsp[256];
|
||||
};
|
||||
|
||||
struct wilc_cfg {
|
||||
struct wilc_cfg_byte *b;
|
||||
struct wilc_cfg_hword *hw;
|
||||
struct wilc_cfg_word *w;
|
||||
struct wilc_cfg_str *s;
|
||||
struct wilc_cfg_str_vals *str_vals;
|
||||
};
|
||||
|
||||
struct wilc;
|
||||
int wilc_wlan_cfg_set_wid(u8 *frame, u32 offset, u16 id, u8 *buf, int size);
|
||||
int wilc_wlan_cfg_get_wid(u8 *frame, u32 offset, u16 id);
|
||||
int wilc_wlan_cfg_get_val(struct wilc *wl, u16 wid, u8 *buffer,
|
||||
u32 buffer_size);
|
||||
void wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size,
|
||||
struct wilc_cfg_rsp *rsp);
|
||||
int wilc_wlan_cfg_init(struct wilc *wl);
|
||||
void wilc_wlan_cfg_deinit(struct wilc *wl);
|
||||
|
||||
#endif
|
803
drivers/net/wireless/microchip/wilc1000/wlan_if.h
Normal file
803
drivers/net/wireless/microchip/wilc1000/wlan_if.h
Normal file
@@ -0,0 +1,803 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef WILC_WLAN_IF_H
|
||||
#define WILC_WLAN_IF_H
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include "fw.h"
|
||||
|
||||
/********************************************
|
||||
*
|
||||
* Wlan Configuration ID
|
||||
*
|
||||
********************************************/
|
||||
|
||||
enum bss_types {
|
||||
WILC_FW_BSS_TYPE_INFRA = 0,
|
||||
WILC_FW_BSS_TYPE_INDEPENDENT,
|
||||
WILC_FW_BSS_TYPE_AP,
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_OPER_MODE_B_ONLY = 0, /* 1, 2 M, otherwise 5, 11 M */
|
||||
WILC_FW_OPER_MODE_G_ONLY, /* 6,12,24 otherwise 9,18,36,48,54 */
|
||||
WILC_FW_OPER_MODE_G_MIXED_11B_1, /* 1,2,5.5,11 otherwise all on */
|
||||
WILC_FW_OPER_MODE_G_MIXED_11B_2, /* 1,2,5,11,6,12,24 otherwise all on */
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_PREAMBLE_SHORT = 0, /* Short Preamble */
|
||||
WILC_FW_PREAMBLE_LONG = 1, /* Long Preamble */
|
||||
WILC_FW_PREAMBLE_AUTO = 2, /* Auto Preamble Selection */
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_PASSIVE_SCAN = 0,
|
||||
WILC_FW_ACTIVE_SCAN = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_NO_POWERSAVE = 0,
|
||||
WILC_FW_MIN_FAST_PS = 1,
|
||||
WILC_FW_MAX_FAST_PS = 2,
|
||||
WILC_FW_MIN_PSPOLL_PS = 3,
|
||||
WILC_FW_MAX_PSPOLL_PS = 4
|
||||
};
|
||||
|
||||
enum chip_ps_states {
|
||||
WILC_CHIP_WAKEDUP = 0,
|
||||
WILC_CHIP_SLEEPING_AUTO = 1,
|
||||
WILC_CHIP_SLEEPING_MANUAL = 2
|
||||
};
|
||||
|
||||
enum bus_acquire {
|
||||
WILC_BUS_ACQUIRE_ONLY = 0,
|
||||
WILC_BUS_ACQUIRE_AND_WAKEUP = 1,
|
||||
};
|
||||
|
||||
enum bus_release {
|
||||
WILC_BUS_RELEASE_ONLY = 0,
|
||||
WILC_BUS_RELEASE_ALLOW_SLEEP = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_NO_ENCRYPT = 0,
|
||||
WILC_FW_ENCRYPT_ENABLED = BIT(0),
|
||||
WILC_FW_WEP = BIT(1),
|
||||
WILC_FW_WEP_EXTENDED = BIT(2),
|
||||
WILC_FW_WPA = BIT(3),
|
||||
WILC_FW_WPA2 = BIT(4),
|
||||
WILC_FW_AES = BIT(5),
|
||||
WILC_FW_TKIP = BIT(6)
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_SEC_NO = WILC_FW_NO_ENCRYPT,
|
||||
WILC_FW_SEC_WEP = WILC_FW_WEP | WILC_FW_ENCRYPT_ENABLED,
|
||||
WILC_FW_SEC_WEP_EXTENDED = WILC_FW_WEP_EXTENDED | WILC_FW_SEC_WEP,
|
||||
WILC_FW_SEC_WPA = WILC_FW_WPA | WILC_FW_ENCRYPT_ENABLED,
|
||||
WILC_FW_SEC_WPA_AES = WILC_FW_AES | WILC_FW_SEC_WPA,
|
||||
WILC_FW_SEC_WPA_TKIP = WILC_FW_TKIP | WILC_FW_SEC_WPA,
|
||||
WILC_FW_SEC_WPA2 = WILC_FW_WPA2 | WILC_FW_ENCRYPT_ENABLED,
|
||||
WILC_FW_SEC_WPA2_AES = WILC_FW_AES | WILC_FW_SEC_WPA2,
|
||||
WILC_FW_SEC_WPA2_TKIP = WILC_FW_TKIP | WILC_FW_SEC_WPA2
|
||||
};
|
||||
|
||||
enum authtype {
|
||||
WILC_FW_AUTH_OPEN_SYSTEM = 1,
|
||||
WILC_FW_AUTH_SHARED_KEY = 2,
|
||||
WILC_FW_AUTH_ANY = 3,
|
||||
WILC_FW_AUTH_IEEE8021 = 5
|
||||
};
|
||||
|
||||
enum site_survey {
|
||||
WILC_FW_SITE_SURVEY_1CH = 0,
|
||||
WILC_FW_SITE_SURVEY_ALL_CH = 1,
|
||||
WILC_FW_SITE_SURVEY_OFF = 2
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_ACK_POLICY_NORMAL = 0,
|
||||
WILC_FW_ACK_NO_POLICY,
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_REKEY_POLICY_DISABLE = 1,
|
||||
WILC_FW_REKEY_POLICY_TIME_BASE,
|
||||
WILC_FW_REKEY_POLICY_PKT_BASE,
|
||||
WILC_FW_REKEY_POLICY_TIME_PKT_BASE
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_FILTER_NO = 0x00,
|
||||
WILC_FW_FILTER_AP_ONLY = 0x01,
|
||||
WILC_FW_FILTER_STA_ONLY = 0x02
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_11N_PROT_AUTO = 0, /* Auto */
|
||||
WILC_FW_11N_NO_PROT, /* Do not use any protection */
|
||||
WILC_FW_11N_PROT_ERP, /* Protect all ERP frame exchanges */
|
||||
WILC_FW_11N_PROT_HT, /* Protect all HT frame exchanges */
|
||||
WILC_FW_11N_PROT_GF /* Protect all GF frame exchanges */
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_ERP_PROT_SELF_CTS,
|
||||
WILC_FW_ERP_PROT_RTS_CTS,
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_11N_OP_MODE_HT_MIXED = 1,
|
||||
WILC_FW_11N_OP_MODE_HT_ONLY_20MHZ,
|
||||
WILC_FW_11N_OP_MODE_HT_ONLY_20_40MHZ,
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_OBBS_NONHT_NO_DETECT = 0,
|
||||
WILC_FW_OBBS_NONHT_DETECT_ONLY = 1,
|
||||
WILC_FW_OBBS_NONHT_DETECT_PROTECT = 2,
|
||||
WILC_FW_OBBS_NONHT_DETECT_PROTECT_REPORT = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_HT_PROT_RTS_CTS_NONHT = 0, /* RTS-CTS at non-HT rate */
|
||||
WILC_FW_HT_PROT_FIRST_FRAME_NONHT, /* First frame at non-HT rate */
|
||||
WILC_FW_HT_PROT_LSIG_TXOP, /* LSIG TXOP Protection */
|
||||
WILC_FW_HT_PROT_FIRST_FRAME_MIXED, /* First frame at Mixed format */
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_SMPS_MODE_STATIC = 1,
|
||||
WILC_FW_SMPS_MODE_DYNAMIC = 2,
|
||||
WILC_FW_SMPS_MODE_MIMO = 3, /* power save disable */
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_TX_RATE_AUTO = 0,
|
||||
WILC_FW_TX_RATE_MBPS_1 = 1,
|
||||
WILC_FW_TX_RATE_MBPS_2 = 2,
|
||||
WILC_FW_TX_RATE_MBPS_5_5 = 5,
|
||||
WILC_FW_TX_RATE_MBPS_11 = 11,
|
||||
WILC_FW_TX_RATE_MBPS_6 = 6,
|
||||
WILC_FW_TX_RATE_MBPS_9 = 9,
|
||||
WILC_FW_TX_RATE_MBPS_12 = 12,
|
||||
WILC_FW_TX_RATE_MBPS_18 = 18,
|
||||
WILC_FW_TX_RATE_MBPS_24 = 24,
|
||||
WILC_FW_TX_RATE_MBPS_36 = 36,
|
||||
WILC_FW_TX_RATE_MBPS_48 = 48,
|
||||
WILC_FW_TX_RATE_MBPS_54 = 54
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_DEFAULT_SCAN = 0,
|
||||
WILC_FW_USER_SCAN = BIT(0),
|
||||
WILC_FW_OBSS_PERIODIC_SCAN = BIT(1),
|
||||
WILC_FW_OBSS_ONETIME_SCAN = BIT(2)
|
||||
};
|
||||
|
||||
enum {
|
||||
WILC_FW_ACTION_FRM_IDX = 0,
|
||||
WILC_FW_PROBE_REQ_IDX = 1
|
||||
};
|
||||
|
||||
enum wid_type {
|
||||
WID_CHAR = 0,
|
||||
WID_SHORT = 1,
|
||||
WID_INT = 2,
|
||||
WID_STR = 3,
|
||||
WID_BIN_DATA = 4,
|
||||
WID_BIN = 5,
|
||||
};
|
||||
|
||||
struct wid {
|
||||
u16 id;
|
||||
enum wid_type type;
|
||||
s32 size;
|
||||
s8 *val;
|
||||
};
|
||||
|
||||
enum {
|
||||
WID_NIL = 0xffff,
|
||||
|
||||
/*
|
||||
* BSS Type
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Infrastructure Independent Access Point
|
||||
* Values to set : 0 1 2
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_BSS_TYPE = 0x0000,
|
||||
|
||||
/*
|
||||
* Transmit Rate
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : 1 2 5.5 11 6 9 12 18 24 36 48 54
|
||||
* Values to set : 1 2 5 11 6 9 12 18 24 36 48 54
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_CURRENT_TX_RATE = 0x0001,
|
||||
|
||||
/*
|
||||
* Channel
|
||||
* -----------------------------------------------------------
|
||||
* Configuration(g) : 1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
||||
* Values to set : 1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_CURRENT_CHANNEL = 0x0002,
|
||||
|
||||
/*
|
||||
* Preamble
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : short long Auto
|
||||
* Values to set : 0 1 2
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_PREAMBLE = 0x0003,
|
||||
|
||||
/*
|
||||
* 11g operating mode (ignored if 11g not present)
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : HighPerf Compat(RSet #1) Compat(RSet #2)
|
||||
* Values to set : 1 2 3
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11G_OPERATING_MODE = 0x0004,
|
||||
|
||||
/*
|
||||
* Mac status (response only)
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : disconnect connect
|
||||
* Values to get : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_STATUS = 0x0005,
|
||||
|
||||
/*
|
||||
* Scan type
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Passive Scanning Active Scanning
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_SCAN_TYPE = 0x0007,
|
||||
|
||||
/*
|
||||
* Key Id (WEP default key Id)
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Any value between 0 to 3
|
||||
* Values to set : Same value. Default is 0
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_KEY_ID = 0x0009,
|
||||
|
||||
/*
|
||||
* QoS Enable
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : QoS Disable WMM Enable
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_QOS_ENABLE = 0x000A,
|
||||
|
||||
/*
|
||||
* Power Management
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : NO_POWERSAVE MIN_POWERSAVE MAX_POWERSAVE
|
||||
* Values to set : 0 1 2
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_POWER_MANAGEMENT = 0x000B,
|
||||
|
||||
/*
|
||||
* WEP/802 11I Configuration
|
||||
* -----------------------------------------------------------
|
||||
* Configuration:Disable WP40 WP104 WPA-AES WPA-TKIP RSN-AES RSN-TKIP
|
||||
* Values (0x) : 00 03 07 29 49 31 51
|
||||
* Configuration:WPA-AES+TKIP RSN-AES+TKIP
|
||||
* Values (0x) : 69 71
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11I_MODE = 0x000C,
|
||||
|
||||
/*
|
||||
* WEP Configuration: Used in BSS STA mode only when WEP is enabled
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Open System Shared Key Any Type | 802.1x Auth
|
||||
* Values (0x) : 01 02 03 | BIT2
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_AUTH_TYPE = 0x000D,
|
||||
|
||||
/*
|
||||
* Site Survey Type
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Values to set
|
||||
* Survey 1 Channel : 0
|
||||
* survey all Channels : 1
|
||||
* Disable Site Survey : 2
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_SITE_SURVEY = 0x000E,
|
||||
|
||||
/*
|
||||
* Listen Interval
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Any value between 1 to 255
|
||||
* Values to set : Same value. Default is 3
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_LISTEN_INTERVAL = 0x000F,
|
||||
|
||||
/*
|
||||
* DTIM Period
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Any value between 1 to 255
|
||||
* Values to set : Same value. Default is 3
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_DTIM_PERIOD = 0x0010,
|
||||
|
||||
/*
|
||||
* ACK Policy
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Normal Ack No Ack
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_ACK_POLICY = 0x0011,
|
||||
|
||||
/*
|
||||
* Reset MAC (Set only)
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Don't Reset Reset No Request
|
||||
* Values to set : 0 1 2
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_RESET = 0x0012,
|
||||
|
||||
/*
|
||||
* Broadcast SSID Option: Setting this will adhere to "" SSID element
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Enable Disable
|
||||
* Values to set : 1 0
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_BCAST_SSID = 0x0015,
|
||||
|
||||
/*
|
||||
* Disconnect (Station)
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Association ID
|
||||
* Values to set : Association ID
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_DISCONNECT = 0x0016,
|
||||
|
||||
/*
|
||||
* 11a Tx Power Level
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Sets TX Power (Higher the value greater the power)
|
||||
* Values to set : Any value between 0 and 63 (inclusive Default 48)
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_TX_POWER_LEVEL_11A = 0x0018,
|
||||
|
||||
/*
|
||||
* Group Key Update Policy Selection
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disabled timeBased packetBased timePacketBased
|
||||
* Values to set : 1 2 3 4
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_REKEY_POLICY = 0x0019,
|
||||
|
||||
/*
|
||||
* Allow Short Slot
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disallow Short Slot Allow Short Slot
|
||||
* (Enable Only Long Slot) (Enable Short Slot if applicable)
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_SHORT_SLOT_ALLOWED = 0x001A,
|
||||
|
||||
WID_PHY_ACTIVE_REG = 0x001B,
|
||||
|
||||
/*
|
||||
* 11b Tx Power Level
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Sets TX Power (Higher the value greater the power)
|
||||
* Values to set : Any value between 0 and 63 (inclusive Default 48)
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_TX_POWER_LEVEL_11B = 0x001D,
|
||||
|
||||
/*
|
||||
* Scan Request
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Request default scan
|
||||
* Values to set : 0
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_START_SCAN_REQ = 0x001E,
|
||||
|
||||
/*
|
||||
* Rssi (get only)
|
||||
* -----------------------------------------------------------
|
||||
* Configuration :
|
||||
* Values to get : Rssi value
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_RSSI = 0x001F,
|
||||
|
||||
/*
|
||||
* Join Request
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Request to join
|
||||
* Values to set : index of scan result
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_JOIN_REQ = 0x0020,
|
||||
|
||||
WID_LINKSPEED = 0x0026,
|
||||
|
||||
/*
|
||||
* Enable User Control of TX Power
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disable Enable
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_USER_CONTROL_ON_TX_POWER = 0x0027,
|
||||
|
||||
WID_MEMORY_ACCESS_8BIT = 0x0029,
|
||||
|
||||
/*
|
||||
* Enable Auto RX Sensitivity feature
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disable Enable
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_AUTO_RX_SENSITIVITY = 0x0032,
|
||||
|
||||
/*
|
||||
* Receive Buffer Based Ack
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disable Enable
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_DATAFLOW_CONTROL = 0x0033,
|
||||
|
||||
/*
|
||||
* Scan Filter
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Class No filter AP only Station Only
|
||||
* Values to set : 0 1 2
|
||||
* Configuration : Priority High Rssi Low Rssi Detect
|
||||
* Values to set : 0 0x4 0x0
|
||||
* Configuration : Channel filter off filter on
|
||||
* Values to set : 0 0x10
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_SCAN_FILTER = 0x0036,
|
||||
|
||||
/*
|
||||
* Link Loss Threshold (measure in the beacon period)
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Any value between 10 and 254(Set to 255 disable)
|
||||
* Values to set : Same value. Default is 10
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_LINK_LOSS_THRESHOLD = 0x0037,
|
||||
|
||||
WID_ABORT_RUNNING_SCAN = 0x003E,
|
||||
|
||||
/* NMAC Character WID list */
|
||||
WID_WPS_START = 0x0043,
|
||||
|
||||
/*
|
||||
* Protection mode for MAC
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Auto No protection ERP HT GF
|
||||
* Values to set : 0 1 2 3 4
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_PROT_MECH = 0x0080,
|
||||
|
||||
/*
|
||||
* ERP Protection type for MAC
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Self-CTS RTS-CTS
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_ERP_PROT_TYPE = 0x0081,
|
||||
|
||||
/*
|
||||
* HT Option Enable
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : HT Enable HT Disable
|
||||
* Values to set : 1 0
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_ENABLE = 0x0082,
|
||||
|
||||
/*
|
||||
* 11n Operating mode (Note that 11g operating mode will also be
|
||||
* used in addition to this, if this is set to HT Mixed mode)
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : HT Mixed HT Only-20MHz HT Only-20/40MHz
|
||||
* Values to set : 1 2 3
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_OPERATING_MODE = 0x0083,
|
||||
|
||||
/*
|
||||
* 11n OBSS non-HT STA Detection flag
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Do not detect
|
||||
* Values to set : 0
|
||||
* Configuration : Detect, do not protect or report
|
||||
* Values to set : 1
|
||||
* Configuration : Detect, protect and do not report
|
||||
* Values to set : 2
|
||||
* Configuration : Detect, protect and report to other BSS
|
||||
* Values to set : 3
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_OBSS_NONHT_DETECTION = 0x0084,
|
||||
|
||||
/*
|
||||
* 11n HT Protection Type
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : RTS-CTS First Frame Exchange at non-HT-rate
|
||||
* Values to set : 0 1
|
||||
* Configuration : LSIG TXOP First Frame Exchange in Mixed Fmt
|
||||
* Values to set : 2 3
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_HT_PROT_TYPE = 0x0085,
|
||||
|
||||
/*
|
||||
* 11n RIFS Protection Enable Flag
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disable Enable
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_RIFS_PROT_ENABLE = 0x0086,
|
||||
|
||||
/*
|
||||
* SMPS Mode
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Static Dynamic MIMO (Power Save Disabled)
|
||||
* Values to set : 1 2 3
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_SMPS_MODE = 0x0087,
|
||||
|
||||
/*
|
||||
* Current transmit MCS
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : MCS Index for data rate
|
||||
* Values to set : 0 to 7
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_CURRENT_TX_MCS = 0x0088,
|
||||
|
||||
WID_11N_PRINT_STATS = 0x0089,
|
||||
|
||||
/*
|
||||
* 11n Short GI Enable Flag
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disable Enable
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_SHORT_GI_ENABLE = 0x008D,
|
||||
|
||||
/*
|
||||
* 11n RIFS Enable Flag
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disable Enable
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_RIFS_MODE = 0x0094,
|
||||
|
||||
/*
|
||||
* TX Abort Feature
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disable Self CTS Enable Self CTS
|
||||
* Values to set : 0 1
|
||||
* Configuration : Disable TX Abort Enable TX Abort
|
||||
* Values to set : 2 3
|
||||
* Configuration : Enable HW TX Abort Enable SW TX Abort
|
||||
* Values to set : 4 5
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_TX_ABORT_CONFIG = 0x00A1,
|
||||
|
||||
WID_REG_TSSI_11B_VALUE = 0x00A6,
|
||||
WID_REG_TSSI_11G_VALUE = 0x00A7,
|
||||
WID_REG_TSSI_11N_VALUE = 0x00A8,
|
||||
WID_TX_CALIBRATION = 0x00A9,
|
||||
WID_DSCR_TSSI_11B_VALUE = 0x00AA,
|
||||
WID_DSCR_TSSI_11G_VALUE = 0x00AB,
|
||||
WID_DSCR_TSSI_11N_VALUE = 0x00AC,
|
||||
|
||||
/*
|
||||
* Immediate Block-Ack Support
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disable Enable
|
||||
* Values to set : 0 1
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_IMMEDIATE_BA_ENABLED = 0x00AF,
|
||||
|
||||
/*
|
||||
* TXOP Disable Flag
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Disable Enable
|
||||
* Values to set : 1 0
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_11N_TXOP_PROT_DISABLE = 0x00B0,
|
||||
|
||||
WID_TX_POWER_LEVEL_11N = 0x00B1,
|
||||
|
||||
/* Custom Character WID list */
|
||||
/* SCAN Complete notification WID*/
|
||||
WID_SCAN_COMPLETE = 0x00C9,
|
||||
|
||||
WID_DEL_BEACON = 0x00CA,
|
||||
|
||||
WID_LOG_TERMINAL_SWITCH = 0x00CD,
|
||||
WID_TX_POWER = 0x00CE,
|
||||
/* EMAC Short WID list */
|
||||
/* RTS Threshold */
|
||||
/*
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Any value between 256 to 2347
|
||||
* Values to set : Same value. Default is 2347
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_RTS_THRESHOLD = 0x1000,
|
||||
|
||||
/*
|
||||
* Fragmentation Threshold
|
||||
* -----------------------------------------------------------
|
||||
* Configuration : Any value between 256 to 2346
|
||||
* Values to set : Same value. Default is 2346
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
WID_FRAG_THRESHOLD = 0x1001,
|
||||
|
||||
WID_SHORT_RETRY_LIMIT = 0x1002,
|
||||
WID_LONG_RETRY_LIMIT = 0x1003,
|
||||
WID_BEACON_INTERVAL = 0x1006,
|
||||
WID_MEMORY_ACCESS_16BIT = 0x1008,
|
||||
WID_PASSIVE_SCAN_TIME = 0x100D,
|
||||
WID_JOIN_START_TIMEOUT = 0x100F,
|
||||
WID_ASOC_TIMEOUT = 0x1011,
|
||||
WID_11I_PROTOCOL_TIMEOUT = 0x1012,
|
||||
WID_EAPOL_RESPONSE_TIMEOUT = 0x1013,
|
||||
|
||||
/* NMAC Short WID list */
|
||||
WID_11N_SIG_QUAL_VAL = 0x1085,
|
||||
WID_CCA_THRESHOLD = 0x1087,
|
||||
|
||||
/* Custom Short WID list */
|
||||
|
||||
/* EMAC Integer WID list */
|
||||
WID_FAILED_COUNT = 0x2000,
|
||||
WID_RETRY_COUNT = 0x2001,
|
||||
WID_MULTIPLE_RETRY_COUNT = 0x2002,
|
||||
WID_FRAME_DUPLICATE_COUNT = 0x2003,
|
||||
WID_ACK_FAILURE_COUNT = 0x2004,
|
||||
WID_RECEIVED_FRAGMENT_COUNT = 0x2005,
|
||||
WID_MCAST_RECEIVED_FRAME_COUNT = 0x2006,
|
||||
WID_FCS_ERROR_COUNT = 0x2007,
|
||||
WID_SUCCESS_FRAME_COUNT = 0x2008,
|
||||
WID_HUT_TX_COUNT = 0x200A,
|
||||
WID_TX_FRAGMENT_COUNT = 0x200B,
|
||||
WID_TX_MULTICAST_FRAME_COUNT = 0x200C,
|
||||
WID_RTS_SUCCESS_COUNT = 0x200D,
|
||||
WID_RTS_FAILURE_COUNT = 0x200E,
|
||||
WID_WEP_UNDECRYPTABLE_COUNT = 0x200F,
|
||||
WID_REKEY_PERIOD = 0x2010,
|
||||
WID_REKEY_PACKET_COUNT = 0x2011,
|
||||
WID_1X_SERV_ADDR = 0x2012,
|
||||
WID_STACK_IP_ADDR = 0x2013,
|
||||
WID_STACK_NETMASK_ADDR = 0x2014,
|
||||
WID_HW_RX_COUNT = 0x2015,
|
||||
WID_MEMORY_ADDRESS = 0x201E,
|
||||
WID_MEMORY_ACCESS_32BIT = 0x201F,
|
||||
|
||||
/* NMAC Integer WID list */
|
||||
/* Custom Integer WID list */
|
||||
WID_GET_INACTIVE_TIME = 0x2084,
|
||||
/* EMAC String WID list */
|
||||
WID_SSID = 0x3000,
|
||||
WID_FIRMWARE_VERSION = 0x3001,
|
||||
WID_OPERATIONAL_RATE_SET = 0x3002,
|
||||
WID_BSSID = 0x3003,
|
||||
WID_WEP_KEY_VALUE = 0x3004,
|
||||
WID_11I_PSK = 0x3008,
|
||||
WID_11E_P_ACTION_REQ = 0x3009,
|
||||
WID_1X_KEY = 0x300A,
|
||||
WID_HARDWARE_VERSION = 0x300B,
|
||||
WID_MAC_ADDR = 0x300C,
|
||||
WID_HUT_DEST_ADDR = 0x300D,
|
||||
WID_PHY_VERSION = 0x300F,
|
||||
WID_SUPP_USERNAME = 0x3010,
|
||||
WID_SUPP_PASSWORD = 0x3011,
|
||||
WID_SITE_SURVEY_RESULTS = 0x3012,
|
||||
WID_RX_POWER_LEVEL = 0x3013,
|
||||
WID_SET_STA_MAC_INACTIVE_TIME = 0x3017,
|
||||
WID_ADD_WEP_KEY = 0x3019,
|
||||
WID_REMOVE_WEP_KEY = 0x301A,
|
||||
WID_ADD_PTK = 0x301B,
|
||||
WID_ADD_RX_GTK = 0x301C,
|
||||
WID_ADD_TX_GTK = 0x301D,
|
||||
WID_REMOVE_KEY = 0x301E,
|
||||
WID_ASSOC_REQ_INFO = 0x301F,
|
||||
WID_ASSOC_RES_INFO = 0x3020,
|
||||
WID_MANUFACTURER = 0x3026, /* Added for CAPI tool */
|
||||
WID_MODEL_NAME = 0x3027, /* Added for CAPI tool */
|
||||
WID_MODEL_NUM = 0x3028, /* Added for CAPI tool */
|
||||
WID_DEVICE_NAME = 0x3029, /* Added for CAPI tool */
|
||||
|
||||
/* NMAC String WID list */
|
||||
WID_SET_OPERATION_MODE = 0x3079,
|
||||
WID_11N_P_ACTION_REQ = 0x3080,
|
||||
WID_HUT_TEST_ID = 0x3081,
|
||||
WID_PMKID_INFO = 0x3082,
|
||||
WID_FIRMWARE_INFO = 0x3083,
|
||||
WID_REGISTER_FRAME = 0x3084,
|
||||
WID_DEL_ALL_STA = 0x3085,
|
||||
WID_REMAIN_ON_CHAN = 0x3996,
|
||||
WID_SSID_PROBE_REQ = 0x3997,
|
||||
WID_JOIN_REQ_EXTENDED = 0x3998,
|
||||
|
||||
WID_IP_ADDRESS = 0x3999,
|
||||
|
||||
/* Custom String WID list */
|
||||
|
||||
/* EMAC Binary WID list */
|
||||
WID_UAPSD_CONFIG = 0x4001,
|
||||
WID_UAPSD_STATUS = 0x4002,
|
||||
WID_WMM_AP_AC_PARAMS = 0x4003,
|
||||
WID_WMM_STA_AC_PARAMS = 0x4004,
|
||||
WID_NETWORK_INFO = 0x4005,
|
||||
WID_STA_JOIN_INFO = 0x4006,
|
||||
WID_CONNECTED_STA_LIST = 0x4007,
|
||||
|
||||
/* NMAC Binary WID list */
|
||||
WID_11N_AUTORATE_TABLE = 0x4080,
|
||||
|
||||
WID_SCAN_CHANNEL_LIST = 0x4084,
|
||||
|
||||
WID_INFO_ELEMENT_PROBE = 0x4085,
|
||||
WID_INFO_ELEMENT_ASSOCIATE = 0x4086,
|
||||
WID_ADD_STA = 0X4087,
|
||||
WID_REMOVE_STA = 0X4088,
|
||||
WID_EDIT_STA = 0X4089,
|
||||
WID_ADD_BEACON = 0x408a,
|
||||
|
||||
WID_SETUP_MULTICAST_FILTER = 0x408b,
|
||||
|
||||
/* Miscellaneous WIDs */
|
||||
WID_ALL = 0x7FFE,
|
||||
WID_MAX = 0xFFFF
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user