summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx')
-rw-r--r--drivers/net/wireless/wl12xx/Kconfig4
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_acx.h102
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_cmd.h22
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_event.h4
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c4
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_rx.h2
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_sdio.c40
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_tx.h6
-rw-r--r--drivers/net/wireless/wl12xx/wl1271.h33
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.h102
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.c41
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.h66
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.c10
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.h4
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_ini.h123
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c95
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_rx.h2
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_sdio.c2
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_testmode.c11
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.c36
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.h7
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx_80211.h26
22 files changed, 476 insertions, 266 deletions
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 337fc7bec5a..2f98058be45 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -41,7 +41,7 @@ config WL1251_SDIO
config WL1271
tristate "TI wl1271 support"
- depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS
+ depends on WL12XX && GENERIC_HARDIRQS
depends on INET
select FW_LOADER
select CRC7
@@ -65,7 +65,7 @@ config WL1271_SPI
config WL1271_SDIO
tristate "TI wl1271 SDIO support"
- depends on WL1271 && MMC && ARM
+ depends on WL1271 && MMC
---help---
This module adds support for the SDIO interface of adapters using
TI wl1271 chipset. Select this if your platform is using
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h
index 26160c45784..842df310d92 100644
--- a/drivers/net/wireless/wl12xx/wl1251_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.h
@@ -60,7 +60,7 @@ struct acx_error_counter {
/* the number of missed sequence numbers in the squentially */
/* values of frames seq numbers */
u32 seq_num_miss;
-} __attribute__ ((packed));
+} __packed;
struct acx_revision {
struct acx_header header;
@@ -89,7 +89,7 @@ struct acx_revision {
* bits 24 - 31: Chip ID - The WiLink chip ID.
*/
u32 hw_version;
-} __attribute__ ((packed));
+} __packed;
enum wl1251_psm_mode {
/* Active mode */
@@ -111,7 +111,7 @@ struct acx_sleep_auth {
/* 2 - ELP mode: Deep / Max sleep*/
u8 sleep_auth;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
enum {
HOSTIF_PCI_MASTER_HOST_INDIRECT,
@@ -159,7 +159,7 @@ struct acx_data_path_params {
* complete ring until an interrupt is generated.
*/
u32 tx_complete_timeout;
-} __attribute__ ((packed));
+} __packed;
struct acx_data_path_params_resp {
@@ -180,7 +180,7 @@ struct acx_data_path_params_resp {
u32 tx_control_addr;
u32 tx_complete_addr;
-} __attribute__ ((packed));
+} __packed;
#define TX_MSDU_LIFETIME_MIN 0
#define TX_MSDU_LIFETIME_MAX 3000
@@ -197,7 +197,7 @@ struct acx_rx_msdu_lifetime {
* firmware discards the MSDU.
*/
u32 lifetime;
-} __attribute__ ((packed));
+} __packed;
/*
* RX Config Options Table
@@ -285,7 +285,7 @@ struct acx_rx_config {
u32 config_options;
u32 filter_options;
-} __attribute__ ((packed));
+} __packed;
enum {
QOS_AC_BE = 0,
@@ -325,13 +325,13 @@ struct acx_tx_queue_qos_config {
/* Lowest memory blocks guaranteed for this queue */
u16 low_threshold;
-} __attribute__ ((packed));
+} __packed;
struct acx_packet_detection {
struct acx_header header;
u32 threshold;
-} __attribute__ ((packed));
+} __packed;
enum acx_slot_type {
@@ -349,7 +349,7 @@ struct acx_slot {
u8 wone_index; /* Reserved */
u8 slot_time;
u8 reserved[6];
-} __attribute__ ((packed));
+} __packed;
#define ADDRESS_GROUP_MAX (8)
@@ -362,7 +362,7 @@ struct acx_dot11_grp_addr_tbl {
u8 num_groups;
u8 pad[2];
u8 mac_table[ADDRESS_GROUP_MAX_LEN];
-} __attribute__ ((packed));
+} __packed;
#define RX_TIMEOUT_PS_POLL_MIN 0
@@ -388,7 +388,7 @@ struct acx_rx_timeout {
* from an UPSD enabled queue.
*/
u16 upsd_timeout;
-} __attribute__ ((packed));
+} __packed;
#define RTS_THRESHOLD_MIN 0
#define RTS_THRESHOLD_MAX 4096
@@ -399,7 +399,7 @@ struct acx_rts_threshold {
u16 threshold;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
struct acx_beacon_filter_option {
struct acx_header header;
@@ -415,7 +415,7 @@ struct acx_beacon_filter_option {
*/
u8 max_num_beacons;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
/*
* ACXBeaconFilterEntry (not 221)
@@ -461,7 +461,7 @@ struct acx_beacon_filter_ie_table {
u8 num_ie;
u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
u8 pad[3];
-} __attribute__ ((packed));
+} __packed;
#define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */
#define NO_BEACON_DEFAULT_TIMEOUT (500) /* in microseconds */
@@ -494,7 +494,7 @@ struct acx_bt_wlan_coex {
*/
u8 enable;
u8 pad[3];
-} __attribute__ ((packed));
+} __packed;
#define PTA_ANTENNA_TYPE_DEF (0)
#define PTA_BT_HP_MAXTIME_DEF (2000)
@@ -648,7 +648,7 @@ struct acx_bt_wlan_coex_param {
/* range: 0 - 20 default: 1 */
u8 bt_hp_respected_num;
-} __attribute__ ((packed));
+} __packed;
#define CCA_THRSH_ENABLE_ENERGY_D 0x140A
#define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF
@@ -660,7 +660,7 @@ struct acx_energy_detection {
u16 rx_cca_threshold;
u8 tx_energy_detection;
u8 pad;
-} __attribute__ ((packed));
+} __packed;
#define BCN_RX_TIMEOUT_DEF_VALUE 10000
#define BROADCAST_RX_TIMEOUT_DEF_VALUE 20000
@@ -679,14 +679,14 @@ struct acx_beacon_broadcast {
/* Consecutive PS Poll failures before updating the host */
u8 ps_poll_threshold;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
struct acx_event_mask {
struct acx_header header;
u32 event_mask;
u32 high_event_mask; /* Unused */
-} __attribute__ ((packed));
+} __packed;
#define CFG_RX_FCS BIT(2)
#define CFG_RX_ALL_GOOD BIT(3)
@@ -729,7 +729,7 @@ struct acx_fw_gen_frame_rates {
u8 tx_ctrl_frame_mod; /* CCK_* or PBCC_* */
u8 tx_mgt_frame_rate;
u8 tx_mgt_frame_mod;
-} __attribute__ ((packed));
+} __packed;
/* STA MAC */
struct acx_dot11_station_id {
@@ -737,28 +737,28 @@ struct acx_dot11_station_id {
u8 mac[ETH_ALEN];
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
struct acx_feature_config {
struct acx_header header;
u32 options;
u32 data_flow_options;
-} __attribute__ ((packed));
+} __packed;
struct acx_current_tx_power {
struct acx_header header;
u8 current_tx_power;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
struct acx_dot11_default_key {
struct acx_header header;
u8 id;
u8 pad[3];
-} __attribute__ ((packed));
+} __packed;
struct acx_tsf_info {
struct acx_header header;
@@ -769,7 +769,7 @@ struct acx_tsf_info {
u32 last_TBTT_lsb;
u8 last_dtim_count;
u8 pad[3];
-} __attribute__ ((packed));
+} __packed;
enum acx_wake_up_event {
WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/
@@ -785,7 +785,7 @@ struct acx_wake_up_condition {
u8 wake_up_event; /* Only one bit can be set */
u8 listen_interval;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
struct acx_aid {
struct acx_header header;
@@ -795,7 +795,7 @@ struct acx_aid {
*/
u16 aid;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
enum acx_preamble_type {
ACX_PREAMBLE_LONG = 0,
@@ -811,7 +811,7 @@ struct acx_preamble {
*/
u8 preamble;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
enum acx_ctsprotect_type {
CTSPROTECT_DISABLE = 0,
@@ -822,11 +822,11 @@ struct acx_ctsprotect {
struct acx_header header;
u8 ctsprotect;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
struct acx_tx_statistics {
u32 internal_desc_overflow;
-} __attribute__ ((packed));
+} __packed;
struct acx_rx_statistics {
u32 out_of_mem;
@@ -837,14 +837,14 @@ struct acx_rx_statistics {
u32 xfr_hint_trig;
u32 path_reset;
u32 reset_counter;
-} __attribute__ ((packed));
+} __packed;
struct acx_dma_statistics {
u32 rx_requested;
u32 rx_errors;
u32 tx_requested;
u32 tx_errors;
-} __attribute__ ((packed));
+} __packed;
struct acx_isr_statistics {
/* host command complete */
@@ -903,7 +903,7 @@ struct acx_isr_statistics {
/* (INT_STS_ND & INT_TRIG_LOW_RSSI) */
u32 low_rssi;
-} __attribute__ ((packed));
+} __packed;
struct acx_wep_statistics {
/* WEP address keys configured */
@@ -925,7 +925,7 @@ struct acx_wep_statistics {
/* WEP decrypt interrupts */
u32 interrupt;
-} __attribute__ ((packed));
+} __packed;
#define ACX_MISSED_BEACONS_SPREAD 10
@@ -985,12 +985,12 @@ struct acx_pwr_statistics {
/* the number of beacons in awake mode */
u32 rcvd_awake_beacons;
-} __attribute__ ((packed));
+} __packed;
struct acx_mic_statistics {
u32 rx_pkts;
u32 calc_failure;
-} __attribute__ ((packed));
+} __packed;
struct acx_aes_statistics {
u32 encrypt_fail;
@@ -999,7 +999,7 @@ struct acx_aes_statistics {
u32 decrypt_packets;
u32 encrypt_interrupt;
u32 decrypt_interrupt;
-} __attribute__ ((packed));
+} __packed;
struct acx_event_statistics {
u32 heart_beat;
@@ -1010,7 +1010,7 @@ struct acx_event_statistics {
u32 oom_late;
u32 phy_transmit_error;
u32 tx_stuck;
-} __attribute__ ((packed));
+} __packed;
struct acx_ps_statistics {
u32 pspoll_timeouts;
@@ -1020,7 +1020,7 @@ struct acx_ps_statistics {
u32 pspoll_max_apturn;
u32 pspoll_utilization;
u32 upsd_utilization;
-} __attribute__ ((packed));
+} __packed;
struct acx_rxpipe_statistics {
u32 rx_prep_beacon_drop;
@@ -1028,7 +1028,7 @@ struct acx_rxpipe_statistics {
u32 beacon_buffer_thres_host_int_trig_rx_data;
u32 missed_beacon_host_int_trig_rx_data;
u32 tx_xfr_host_int_trig_rx_data;
-} __attribute__ ((packed));
+} __packed;
struct acx_statistics {
struct acx_header header;
@@ -1044,7 +1044,7 @@ struct acx_statistics {
struct acx_event_statistics event;
struct acx_ps_statistics ps;
struct acx_rxpipe_statistics rxpipe;
-} __attribute__ ((packed));
+} __packed;
#define ACX_MAX_RATE_CLASSES 8
#define ACX_RATE_MASK_UNSPECIFIED 0
@@ -1063,7 +1063,7 @@ struct acx_rate_policy {
u32 rate_class_cnt;
struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES];
-} __attribute__ ((packed));
+} __packed;
struct wl1251_acx_memory {
__le16 num_stations; /* number of STAs to be supported. */
@@ -1082,7 +1082,7 @@ struct wl1251_acx_memory {
u8 tx_min_mem_block_num;
u8 num_ssid_profiles;
__le16 debug_buffer_size;
-} __attribute__ ((packed));
+} __packed;
#define ACX_RX_DESC_MIN 1
@@ -1094,7 +1094,7 @@ struct wl1251_acx_rx_queue_config {
u8 type;
u8 priority;
__le32 dma_address;
-} __attribute__ ((packed));
+} __packed;
#define ACX_TX_DESC_MIN 1
#define ACX_TX_DESC_MAX 127
@@ -1103,7 +1103,7 @@ struct wl1251_acx_tx_queue_config {
u8 num_descs;
u8 pad[2];
u8 attributes;
-} __attribute__ ((packed));
+} __packed;
#define MAX_TX_QUEUE_CONFIGS 5
#define MAX_TX_QUEUES 4
@@ -1113,7 +1113,7 @@ struct wl1251_acx_config_memory {
struct wl1251_acx_memory mem_config;
struct wl1251_acx_rx_queue_config rx_queue_config;
struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS];
-} __attribute__ ((packed));
+} __packed;
struct wl1251_acx_mem_map {
struct acx_header header;
@@ -1147,7 +1147,7 @@ struct wl1251_acx_mem_map {
/* Number of blocks FW allocated for RX packets */
u32 num_rx_mem_blocks;
-} __attribute__ ((packed));
+} __packed;
struct wl1251_acx_wr_tbtt_and_dtim {
@@ -1164,7 +1164,7 @@ struct wl1251_acx_wr_tbtt_and_dtim {
*/
u8 dtim;
u8 padding;
-} __attribute__ ((packed));
+} __packed;
struct wl1251_acx_ac_cfg {
struct acx_header header;
@@ -1194,7 +1194,7 @@ struct wl1251_acx_ac_cfg {
/* The TX Op Limit (in microseconds) for the access class. */
u16 txop_limit;
-} __attribute__ ((packed));
+} __packed;
enum wl1251_acx_channel_type {
@@ -1245,7 +1245,7 @@ struct wl1251_acx_tid_cfg {
/* not supported */
u32 apsdconf[2];
-} __attribute__ ((packed));
+} __packed;
/*************************************************************************
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h
index 4ad67cae94d..7e70dd5a21b 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h
@@ -106,7 +106,7 @@ struct wl1251_cmd_header {
u16 status;
/* payload */
u8 data[0];
-} __attribute__ ((packed));
+} __packed;
struct wl1251_command {
struct wl1251_cmd_header header;
@@ -201,7 +201,7 @@ struct wl1251_scan_parameters {
u8 ssid_len;
u8 ssid[32];
-} __attribute__ ((packed));
+} __packed;
struct wl1251_scan_ch_parameters {
u32 min_duration; /* in TU */
@@ -218,7 +218,7 @@ struct wl1251_scan_ch_parameters {
u8 tx_power_att;
u8 channel;
u8 pad[3];
-} __attribute__ ((packed));
+} __packed;
/* SCAN parameters */
#define SCAN_MAX_NUM_OF_CHANNELS 16
@@ -228,7 +228,7 @@ struct wl1251_cmd_scan {
struct wl1251_scan_parameters params;
struct wl1251_scan_ch_parameters channels[SCAN_MAX_NUM_OF_CHANNELS];
-} __attribute__ ((packed));
+} __packed;
enum {
BSS_TYPE_IBSS = 0,
@@ -276,14 +276,14 @@ struct cmd_join {
u8 tx_mgt_frame_rate; /* OBSOLETE */
u8 tx_mgt_frame_mod; /* OBSOLETE */
u8 reserved;
-} __attribute__ ((packed));
+} __packed;
struct cmd_enabledisable_path {
struct wl1251_cmd_header header;
u8 channel;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
#define WL1251_MAX_TEMPLATE_SIZE 300
@@ -292,7 +292,7 @@ struct wl1251_cmd_packet_template {
__le16 size;
u8 data[0];
-} __attribute__ ((packed));
+} __packed;
#define TIM_ELE_ID 5
#define PARTIAL_VBM_MAX 251
@@ -304,7 +304,7 @@ struct wl1251_tim {
u8 dtim_period;
u8 bitmap_ctrl;
u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */
-} __attribute__ ((packed));
+} __packed;
/* Virtual Bit Map update */
struct wl1251_cmd_vbm_update {
@@ -312,7 +312,7 @@ struct wl1251_cmd_vbm_update {
__le16 len;
u8 padding[2];
struct wl1251_tim tim;
-} __attribute__ ((packed));
+} __packed;
enum wl1251_cmd_ps_mode {
STATION_ACTIVE_MODE,
@@ -333,7 +333,7 @@ struct wl1251_cmd_ps_params {
u8 hang_over_period;
u16 null_data_rate;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
struct wl1251_cmd_trigger_scan_to {
struct wl1251_cmd_header header;
@@ -411,7 +411,7 @@ struct wl1251_cmd_set_keys {
u8 key[MAX_KEY_SIZE];
u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
-} __attribute__ ((packed));
+} __packed;
#endif /* __WL1251_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl12xx/wl1251_event.h
index be0ac54d624..f48a2b66bc5 100644
--- a/drivers/net/wireless/wl12xx/wl1251_event.h
+++ b/drivers/net/wireless/wl12xx/wl1251_event.h
@@ -82,7 +82,7 @@ struct event_debug_report {
u32 report_1;
u32 report_2;
u32 report_3;
-} __attribute__ ((packed));
+} __packed;
struct event_mailbox {
u32 events_vector;
@@ -112,7 +112,7 @@ struct event_mailbox {
struct event_debug_report report;
u8 average_snr_level;
u8 padding[19];
-} __attribute__ ((packed));
+} __packed;
int wl1251_event_unmask(struct wl1251 *wl);
void wl1251_event_mbox_config(struct wl1251 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 00b24282fc7..c8f268951e1 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -124,7 +124,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
}
wl->nvs_len = fw->size;
- wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
+ wl->nvs = kmemdup(fw->data, wl->nvs_len, GFP_KERNEL);
if (!wl->nvs) {
wl1251_error("could not allocate memory for the nvs file");
@@ -132,8 +132,6 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
goto out;
}
- memcpy(wl->nvs, fw->data, wl->nvs_len);
-
ret = 0;
out:
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h
index 563a3fde40f..da4e53406a0 100644
--- a/drivers/net/wireless/wl12xx/wl1251_rx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_rx.h
@@ -117,7 +117,7 @@ struct wl1251_rx_descriptor {
s8 rssi; /* in dB */
u8 rcpi; /* in dB */
u8 snr; /* in dB */
-} __attribute__ ((packed));
+} __packed;
void wl1251_rx(struct wl1251 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
index c561332e700..b901b613565 100644
--- a/drivers/net/wireless/wl12xx/wl1251_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -37,11 +37,17 @@
#define SDIO_DEVICE_ID_TI_WL1251 0x9066
#endif
+struct wl1251_sdio {
+ struct sdio_func *func;
+ u32 elp_val;
+};
+
static struct wl12xx_platform_data *wl12xx_board_data;
static struct sdio_func *wl_to_func(struct wl1251 *wl)
{
- return wl->if_priv;
+ struct wl1251_sdio *wl_sdio = wl->if_priv;
+ return wl_sdio->func;
}
static void wl1251_sdio_interrupt(struct sdio_func *func)
@@ -90,10 +96,17 @@ static void wl1251_sdio_write(struct wl1251 *wl, int addr,
static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
{
int ret = 0;
- struct sdio_func *func = wl_to_func(wl);
-
+ struct wl1251_sdio *wl_sdio = wl->if_priv;
+ struct sdio_func *func = wl_sdio->func;
+
+ /*
+ * The hardware only supports RAW (read after write) access for
+ * reading, regular sdio_readb won't work here (it interprets
+ * the unused bits of CMD52 as write data even if we send read
+ * request).
+ */
sdio_claim_host(func);
- *val = sdio_readb(func, addr, &ret);
+ *val = sdio_writeb_readb(func, wl_sdio->elp_val, addr, &ret);
sdio_release_host(func);
if (ret)
@@ -103,7 +116,8 @@ static void wl1251_sdio_read_elp(struct wl1251 *wl, int addr, u32 *val)
static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
{
int ret = 0;
- struct sdio_func *func = wl_to_func(wl);
+ struct wl1251_sdio *wl_sdio = wl->if_priv;
+ struct sdio_func *func = wl_sdio->func;
sdio_claim_host(func);
sdio_writeb(func, val, addr, &ret);
@@ -111,6 +125,8 @@ static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
if (ret)
wl1251_error("sdio_writeb failed (%d)", ret);
+ else
+ wl_sdio->elp_val = val;
}
static void wl1251_sdio_reset(struct wl1251 *wl)
@@ -197,6 +213,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
int ret;
struct wl1251 *wl;
struct ieee80211_hw *hw;
+ struct wl1251_sdio *wl_sdio;
hw = wl1251_alloc_hw();
if (IS_ERR(hw))
@@ -204,6 +221,12 @@ static int wl1251_sdio_probe(struct sdio_func *func,
wl = hw->priv;
+ wl_sdio = kzalloc(sizeof(*wl_sdio), GFP_KERNEL);
+ if (wl_sdio == NULL) {
+ ret = -ENOMEM;
+ goto out_free_hw;
+ }
+
sdio_claim_host(func);
ret = sdio_enable_func(func);
if (ret)
@@ -213,7 +236,8 @@ static int wl1251_sdio_probe(struct sdio_func *func,
sdio_release_host(func);
SET_IEEE80211_DEV(hw, &func->dev);
- wl->if_priv = func;
+ wl_sdio->func = func;
+ wl->if_priv = wl_sdio;
wl->if_ops = &wl1251_sdio_ops;
wl->set_power = wl1251_sdio_set_power;
@@ -259,6 +283,8 @@ disable:
sdio_disable_func(func);
release:
sdio_release_host(func);
+ kfree(wl_sdio);
+out_free_hw:
wl1251_free_hw(wl);
return ret;
}
@@ -266,9 +292,11 @@ release:
static void __devexit wl1251_sdio_remove(struct sdio_func *func)
{
struct wl1251 *wl = sdio_get_drvdata(func);
+ struct wl1251_sdio *wl_sdio = wl->if_priv;
if (wl->irq)
free_irq(wl->irq, wl);
+ kfree(wl_sdio);
wl1251_free_hw(wl);
sdio_claim_host(func);
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h
index 55856c6bb97..65c4be8c2e8 100644
--- a/drivers/net/wireless/wl12xx/wl1251_tx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_tx.h
@@ -109,7 +109,7 @@ struct tx_control {
unsigned xfer_pad:1;
unsigned reserved:7;
-} __attribute__ ((packed));
+} __packed;
struct tx_double_buffer_desc {
@@ -156,7 +156,7 @@ struct tx_double_buffer_desc {
u8 num_mem_blocks;
u8 reserved;
-} __attribute__ ((packed));
+} __packed;
enum {
TX_SUCCESS = 0,
@@ -208,7 +208,7 @@ struct tx_result {
/* See done_1 */
u8 done_2;
-} __attribute__ ((packed));
+} __packed;
static inline int wl1251_tx_get_queue(int queue)
{
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 6f1b6b5640c..ec09f0d40ca 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -33,6 +33,7 @@
#include <net/mac80211.h>
#include "wl1271_conf.h"
+#include "wl1271_ini.h"
#define DRIVER_NAME "wl1271"
#define DRIVER_PREFIX DRIVER_NAME ": "
@@ -116,33 +117,6 @@ enum {
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
-/* NVS data structure */
-#define WL1271_NVS_SECTION_SIZE 468
-
-#define WL1271_NVS_GENERAL_PARAMS_SIZE 57
-#define WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED \
- (WL1271_NVS_GENERAL_PARAMS_SIZE + 1)
-#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE 17
-#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED \
- (WL1271_NVS_STAT_RADIO_PARAMS_SIZE + 1)
-#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE 65
-#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED \
- (WL1271_NVS_DYN_RADIO_PARAMS_SIZE + 1)
-#define WL1271_NVS_FEM_COUNT 2
-#define WL1271_NVS_INI_SPARE_SIZE 124
-
-struct wl1271_nvs_file {
- /* NVS section */
- u8 nvs[WL1271_NVS_SECTION_SIZE];
-
- /* INI section */
- u8 general_params[WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED];
- u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED];
- u8 dyn_radio_params[WL1271_NVS_FEM_COUNT]
- [WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED];
- u8 ini_spare[WL1271_NVS_INI_SPARE_SIZE];
-} __attribute__ ((packed));
-
/*
* Enable/disable 802.11a support for WL1273
*/
@@ -317,7 +291,7 @@ struct wl1271_fw_status {
__le32 tx_released_blks[NUM_TX_QUEUES];
__le32 fw_localtime;
__le32 padding[2];
-} __attribute__ ((packed));
+} __packed;
struct wl1271_rx_mem_pool_addr {
u32 addr;
@@ -325,6 +299,7 @@ struct wl1271_rx_mem_pool_addr {
};
struct wl1271_scan {
+ struct cfg80211_scan_request *req;
u8 state;
u8 ssid[IW_ESSID_MAX_SIZE+1];
size_t ssid_len;
@@ -375,6 +350,7 @@ struct wl1271 {
#define WL1271_FLAG_IRQ_PENDING (9)
#define WL1271_FLAG_IRQ_RUNNING (10)
#define WL1271_FLAG_IDLE (11)
+#define WL1271_FLAG_IDLE_REQUESTED (12)
unsigned long flags;
struct wl1271_partition_set part;
@@ -421,6 +397,7 @@ struct wl1271 {
/* Pending TX frames */
struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
+ int tx_frames_cnt;
/* Security sequence number counters */
u8 tx_security_last_seq;
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 420e7e2fc02..4c87e601df2 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -75,7 +75,7 @@ struct acx_header {
/* payload length (not including headers */
__le16 len;
-} __attribute__ ((packed));
+} __packed;
struct acx_error_counter {
struct acx_header header;
@@ -98,7 +98,7 @@ struct acx_error_counter {
/* the number of missed sequence numbers in the squentially */
/* values of frames seq numbers */
__le32 seq_num_miss;
-} __attribute__ ((packed));
+} __packed;
struct acx_revision {
struct acx_header header;
@@ -127,7 +127,7 @@ struct acx_revision {
* bits 24 - 31: Chip ID - The WiLink chip ID.
*/
__le32 hw_version;
-} __attribute__ ((packed));
+} __packed;
enum wl1271_psm_mode {
/* Active mode */
@@ -149,7 +149,7 @@ struct acx_sleep_auth {
/* 2 - ELP mode: Deep / Max sleep*/
u8 sleep_auth;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
enum {
HOSTIF_PCI_MASTER_HOST_INDIRECT,
@@ -187,7 +187,7 @@ struct acx_rx_msdu_lifetime {
* firmware discards the MSDU.
*/
__le32 lifetime;
-} __attribute__ ((packed));
+} __packed;
/*
* RX Config Options Table
@@ -275,13 +275,13 @@ struct acx_rx_config {
__le32 config_options;
__le32 filter_options;
-} __attribute__ ((packed));
+} __packed;
struct acx_packet_detection {
struct acx_header header;
__le32 threshold;
-} __attribute__ ((packed));
+} __packed;
enum acx_slot_type {
@@ -299,7 +299,7 @@ struct acx_slot {
u8 wone_index; /* Reserved */
u8 slot_time;
u8 reserved[6];
-} __attribute__ ((packed));
+} __packed;
#define ACX_MC_ADDRESS_GROUP_MAX (8)
@@ -312,21 +312,21 @@ struct acx_dot11_grp_addr_tbl {
u8 num_groups;
u8 pad[2];
u8 mac_table[ADDRESS_GROUP_MAX_LEN];
-} __attribute__ ((packed));
+} __packed;
struct acx_rx_timeout {
struct acx_header header;
__le16 ps_poll_timeout;
__le16 upsd_timeout;
-} __attribute__ ((packed));
+} __packed;
struct acx_rts_threshold {
struct acx_header header;
__le16 threshold;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
struct acx_beacon_filter_option {
struct acx_header header;
@@ -342,7 +342,7 @@ struct acx_beacon_filter_option {
*/
u8 max_num_beacons;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
/*
* ACXBeaconFilterEntry (not 221)
@@ -383,21 +383,21 @@ struct acx_beacon_filter_ie_table {
u8 num_ie;
u8 pad[3];
u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
-} __attribute__ ((packed));
+} __packed;
struct acx_conn_monit_params {
struct acx_header header;
__le32 synch_fail_thold; /* number of beacons missed */
__le32 bss_lose_timeout; /* number of TU's from synch fail */
-} __attribute__ ((packed));
+} __packed;
struct acx_bt_wlan_coex {
struct acx_header header;
u8 enable;
u8 pad[3];
-} __attribute__ ((packed));
+} __packed;
struct acx_bt_wlan_coex_param {
struct acx_header header;
@@ -405,7 +405,7 @@ struct acx_bt_wlan_coex_param {
__le32 params[CONF_SG_PARAMS_MAX];
u8 param_idx;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
struct acx_dco_itrim_params {
struct acx_header header;
@@ -413,7 +413,7 @@ struct acx_dco_itrim_params {
u8 enable;
u8 padding[3];
__le32 timeout;
-} __attribute__ ((packed));
+} __packed;
struct acx_energy_detection {
struct acx_header header;
@@ -422,7 +422,7 @@ struct acx_energy_detection {
__le16 rx_cca_threshold;
u8 tx_energy_detection;
u8 pad;
-} __attribute__ ((packed));
+} __packed;
struct acx_beacon_broadcast {
struct acx_header header;
@@ -436,14 +436,14 @@ struct acx_beacon_broadcast {
/* Consecutive PS Poll failures before updating the host */
u8 ps_poll_threshold;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
struct acx_event_mask {
struct acx_header header;
__le32 event_mask;
__le32 high_event_mask; /* Unused */
-} __attribute__ ((packed));
+} __packed;
#define CFG_RX_FCS BIT(2)
#define CFG_RX_ALL_GOOD BIT(3)
@@ -488,14 +488,14 @@ struct acx_feature_config {
__le32 options;
__le32 data_flow_options;
-} __attribute__ ((packed));
+} __packed;
struct acx_current_tx_power {
struct acx_header header;
u8 current_tx_power;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
struct acx_wake_up_condition {
struct acx_header header;
@@ -503,7 +503,7 @@ struct acx_wake_up_condition {
u8 wake_up_event; /* Only one bit can be set */
u8 listen_interval;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
struct acx_aid {
struct acx_header header;
@@ -513,7 +513,7 @@ struct acx_aid {
*/
__le16 aid;
u8 pad[2];
-} __attribute__ ((packed));
+} __packed;
enum acx_preamble_type {
ACX_PREAMBLE_LONG = 0,
@@ -529,7 +529,7 @@ struct acx_preamble {
*/
u8 preamble;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
enum acx_ctsprotect_type {
CTSPROTECT_DISABLE = 0,
@@ -540,11 +540,11 @@ struct acx_ctsprotect {
struct acx_header header;
u8 ctsprotect;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
struct acx_tx_statistics {
__le32 internal_desc_overflow;
-} __attribute__ ((packed));
+} __packed;
struct acx_rx_statistics {
__le32 out_of_mem;
@@ -555,14 +555,14 @@ struct acx_rx_statistics {
__le32 xfr_hint_trig;
__le32 path_reset;
__le32 reset_counter;
-} __attribute__ ((packed));
+} __packed;
struct acx_dma_statistics {
__le32 rx_requested;
__le32 rx_errors;
__le32 tx_requested;
__le32 tx_errors;
-} __attribute__ ((packed));
+} __packed;
struct acx_isr_statistics {
/* host command complete */
@@ -621,7 +621,7 @@ struct acx_isr_statistics {
/* (INT_STS_ND & INT_TRIG_LOW_RSSI) */
__le32 low_rssi;
-} __attribute__ ((packed));
+} __packed;
struct acx_wep_statistics {
/* WEP address keys configured */
@@ -643,7 +643,7 @@ struct acx_wep_statistics {
/* WEP decrypt interrupts */
__le32 interrupt;
-} __attribute__ ((packed));
+} __packed;
#define ACX_MISSED_BEACONS_SPREAD 10
@@ -703,12 +703,12 @@ struct acx_pwr_statistics {
/* the number of beacons in awake mode */
__le32 rcvd_awake_beacons;
-} __attribute__ ((packed));
+} __packed;
struct acx_mic_statistics {
__le32 rx_pkts;
__le32 calc_failure;
-} __attribute__ ((packed));
+} __packed;
struct acx_aes_statistics {
__le32 encrypt_fail;
@@ -717,7 +717,7 @@ struct acx_aes_statistics {
__le32 decrypt_packets;
__le32 encrypt_interrupt;
__le32 decrypt_interrupt;
-} __attribute__ ((packed));
+} __packed;
struct acx_event_statistics {
__le32 heart_beat;
@@ -728,7 +728,7 @@ struct acx_event_statistics {
__le32 oom_late;
__le32 phy_transmit_error;
__le32 tx_stuck;
-} __attribute__ ((packed));
+} __packed;
struct acx_ps_statistics {
__le32 pspoll_timeouts;
@@ -738,7 +738,7 @@ struct acx_ps_statistics {
__le32 pspoll_max_apturn;
__le32 pspoll_utilization;
__le32 upsd_utilization;
-} __attribute__ ((packed));
+} __packed;
struct acx_rxpipe_statistics {
__le32 rx_prep_beacon_drop;
@@ -746,7 +746,7 @@ struct acx_rxpipe_statistics {
__le32 beacon_buffer_thres_host_int_trig_rx_data;
__le32 missed_beacon_host_int_trig_rx_data;
__le32 tx_xfr_host_int_trig_rx_data;
-} __attribute__ ((packed));
+} __packed;
struct acx_statistics {
struct acx_header header;
@@ -762,7 +762,7 @@ struct acx_statistics {
struct acx_event_statistics event;
struct acx_ps_statistics ps;
struct acx_rxpipe_statistics rxpipe;
-} __attribute__ ((packed));
+} __packed;
struct acx_rate_class {
__le32 enabled_rates;
@@ -780,7 +780,7 @@ struct acx_rate_policy {
__le32 rate_class_cnt;
struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES];
-} __attribute__ ((packed));
+} __packed;
struct acx_ac_cfg {
struct acx_header header;
@@ -790,7 +790,7 @@ struct acx_ac_cfg {
u8 aifsn;
u8 reserved;
__le16 tx_op_limit;
-} __attribute__ ((packed));
+} __packed;
struct acx_tid_config {
struct acx_header header;
@@ -801,19 +801,19 @@ struct acx_tid_config {
u8 ack_policy;
u8 padding[3];
__le32 apsd_conf[2];
-} __attribute__ ((packed));
+} __packed;
struct acx_frag_threshold {
struct acx_header header;
__le16 frag_threshold;
u8 padding[2];
-} __attribute__ ((packed));
+} __packed;
struct acx_tx_config_options {
struct acx_header header;
__le16 tx_compl_timeout; /* msec */
__le16 tx_compl_threshold; /* number of packets */
-} __attribute__ ((packed));
+} __packed;
#define ACX_RX_MEM_BLOCKS 70
#define ACX_TX_MIN_MEM_BLOCKS 40
@@ -828,7 +828,7 @@ struct wl1271_acx_config_memory {
u8 num_stations;
u8 num_ssid_profiles;
__le32 total_tx_descriptors;
-} __attribute__ ((packed));
+} __packed;
struct wl1271_acx_mem_map {
struct acx_header header;
@@ -872,7 +872,7 @@ struct wl1271_acx_mem_map {
u8 *rx_cbuf;
__le32 rx_ctrl;
__le32 tx_ctrl;
-} __attribute__ ((packed));
+} __packed;
struct wl1271_acx_rx_config_opt {
struct acx_header header;
@@ -882,7 +882,7 @@ struct wl1271_acx_rx_config_opt {
__le16 timeout;
u8 queue_type;
u8 reserved;
-} __attribute__ ((packed));
+} __packed;
struct wl1271_acx_bet_enable {
@@ -891,7 +891,7 @@ struct wl1271_acx_bet_enable {
u8 enable;
u8 max_consecutive;
u8 padding[2];
-} __attribute__ ((packed));
+} __packed;
#define ACX_IPV4_VERSION 4
#define ACX_IPV6_VERSION 6
@@ -905,7 +905,7 @@ struct wl1271_acx_arp_filter {
requests directed to this IP address will pass
through. For IPv4, the first four bytes are
used. */
-} __attribute__((packed));
+} __packed;
struct wl1271_acx_pm_config {
struct acx_header header;
@@ -913,14 +913,14 @@ struct wl1271_acx_pm_config {
__le32 host_clk_settling_time;
u8 host_fast_wakeup_support;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
struct wl1271_acx_keep_alive_mode {
struct acx_header header;
u8 enabled;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
enum {
ACX_KEEP_ALIVE_NO_TX = 0,
@@ -940,7 +940,7 @@ struct wl1271_acx_keep_alive_config {
u8 tpl_validation;
u8 trigger;
u8 padding;
-} __attribute__ ((packed));
+} __packed;
enum {
WL1271_ACX_TRIG_TYPE_LEVEL = 0,
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 19393e236e2..530678e45a1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -212,8 +212,8 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
- memcpy(gen_parms->params, wl->nvs->general_params,
- WL1271_NVS_GENERAL_PARAMS_SIZE);
+ memcpy(&gen_parms->general_params, &wl->nvs->general_params,
+ sizeof(struct wl1271_ini_general_params));
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
if (ret < 0)
@@ -238,13 +238,20 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
- memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params,
- WL1271_NVS_STAT_RADIO_PARAMS_SIZE);
- memcpy(radio_parms->dyn_radio_params,
- wl->nvs->dyn_radio_params[rparam->fem],
- WL1271_NVS_DYN_RADIO_PARAMS_SIZE);
-
- /* FIXME: current NVS is missing 5GHz parameters */
+ /* 2.4GHz parameters */
+ memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2,
+ sizeof(struct wl1271_ini_band_params_2));
+ memcpy(&radio_parms->dyn_params_2,
+ &wl->nvs->dyn_radio_params_2[rparam->fem].params,
+ sizeof(struct wl1271_ini_fem_params_2));
+
+ /* 5GHz parameters */
+ memcpy(&radio_parms->static_params_5,
+ &wl->nvs->stat_radio_params_5,
+ sizeof(struct wl1271_ini_band_params_5));
+ memcpy(&radio_parms->dyn_params_5,
+ &wl->nvs->dyn_radio_params_5[rparam->fem].params,
+ sizeof(struct wl1271_ini_fem_params_5));
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
radio_parms, sizeof(*radio_parms));
@@ -329,12 +336,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
join->channel = wl->channel;
join->ssid_len = wl->ssid_len;
memcpy(join->ssid, wl->ssid, wl->ssid_len);
- join->ctrl = WL1271_JOIN_CMD_CTRL_TX_FLUSH;
-
- /* increment the session counter */
- wl->session_counter++;
- if (wl->session_counter >= SESSION_COUNTER_MAX)
- wl->session_counter = 0;
join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
@@ -517,7 +518,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
ps_params->send_null_data = send;
ps_params->retries = 5;
ps_params->hang_over_period = 1;
- ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */
+ ps_params->null_data_rate = cpu_to_le32(wl->basic_rate_set);
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
sizeof(*ps_params), 0);
@@ -567,7 +568,7 @@ out:
}
int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len, u8 active_scan,
+ struct cfg80211_scan_request *req, u8 active_scan,
u8 high_prio, u8 band, u8 probe_requests)
{
@@ -648,7 +649,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
}
ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len,
- ie, ie_len, ieee_band);
+ req->ie, req->ie_len, ieee_band);
if (ret < 0) {
wl1271_error("PROBE request template failed");
goto out;
@@ -684,7 +685,9 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
memcpy(wl->scan.ssid, ssid, ssid_len);
} else
wl->scan.ssid_len = 0;
- }
+ wl->scan.req = req;
+ } else
+ wl->scan.req = NULL;
}
ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0);
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index f2820b42a94..f5745d829c9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -42,7 +42,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send);
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
size_t len);
int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len, u8 active_scan,
+ struct cfg80211_scan_request *req, u8 active_scan,
u8 high_prio, u8 band, u8 probe_requests);
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
void *buf, size_t buf_len, int index, u32 rates);
@@ -136,14 +136,14 @@ struct wl1271_cmd_header {
__le16 status;
/* payload */
u8 data[0];
-} __attribute__ ((packed));
+} __packed;
#define WL1271_CMD_MAX_PARAMS 572
struct wl1271_command {
struct wl1271_cmd_header header;
u8 parameters[WL1271_CMD_MAX_PARAMS];
-} __attribute__ ((packed));
+} __packed;
enum {
CMD_MAILBOX_IDLE = 0,
@@ -196,7 +196,7 @@ struct cmd_read_write_memory {
of this field is the Host in WRITE command or the Wilink in READ
command. */
u8 value[MAX_READ_SIZE];
-} __attribute__ ((packed));
+} __packed;
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
@@ -243,14 +243,14 @@ struct wl1271_cmd_join {
u8 ssid[IW_ESSID_MAX_SIZE];
u8 ctrl; /* JOIN_CMD_CTRL_* */
u8 reserved[3];
-} __attribute__ ((packed));
+} __packed;
struct cmd_enabledisable_path {
struct wl1271_cmd_header header;
u8 channel;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
#define WL1271_RATE_AUTOMATIC 0
@@ -266,7 +266,7 @@ struct wl1271_cmd_template_set {
u8 aflags;
u8 reserved;
u8 template_data[WL1271_CMD_TEMPL_MAX_SIZE];
-} __attribute__ ((packed));
+} __packed;
#define TIM_ELE_ID 5
#define PARTIAL_VBM_MAX 251
@@ -278,7 +278,7 @@ struct wl1271_tim {
u8 dtim_period;
u8 bitmap_ctrl;
u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */
-} __attribute__ ((packed));
+} __packed;
enum wl1271_cmd_ps_mode {
STATION_ACTIVE_MODE,
@@ -298,7 +298,7 @@ struct wl1271_cmd_ps_params {
*/
u8 hang_over_period;
__le32 null_data_rate;
-} __attribute__ ((packed));
+} __packed;
/* HW encryption keys */
#define NUM_ACCESS_CATEGORIES_COPY 4
@@ -348,7 +348,7 @@ struct wl1271_cmd_set_keys {
u8 key[MAX_KEY_SIZE];
__le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
__le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
-} __attribute__ ((packed));
+} __packed;
#define WL1271_SCAN_MAX_CHANNELS 24
@@ -385,7 +385,7 @@ struct basic_scan_params {
u8 use_ssid_list;
u8 scan_tag;
u8 padding2;
-} __attribute__ ((packed));
+} __packed;
struct basic_scan_channel_params {
/* Duration in TU to wait for frames on a channel for active scan */
@@ -400,25 +400,25 @@ struct basic_scan_channel_params {
u8 dfs_candidate;
u8 activity_detected;
u8 pad;
-} __attribute__ ((packed));
+} __packed;
struct wl1271_cmd_scan {
struct wl1271_cmd_header header;
struct basic_scan_params params;
struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS];
-} __attribute__ ((packed));
+} __packed;
struct wl1271_cmd_trigger_scan_to {
struct wl1271_cmd_header header;
__le32 timeout;
-} __attribute__ ((packed));
+} __packed;
struct wl1271_cmd_test_header {
u8 id;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
enum wl1271_channel_tune_bands {
WL1271_CHANNEL_TUNE_BAND_2_4,
@@ -439,25 +439,31 @@ struct wl1271_general_parms_cmd {
struct wl1271_cmd_test_header test;
- u8 params[WL1271_NVS_GENERAL_PARAMS_SIZE];
- s8 reserved[23];
-} __attribute__ ((packed));
+ struct wl1271_ini_general_params general_params;
-#define WL1271_STAT_RADIO_PARAMS_5_SIZE 29
-#define WL1271_DYN_RADIO_PARAMS_5_SIZE 104
+ u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM];
+ u8 sr_sen_n_p;
+ u8 sr_sen_n_p_gain;
+ u8 sr_sen_nrn;
+ u8 sr_sen_prn;
+ u8 padding[3];
+} __packed;
struct wl1271_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
- u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE];
- u8 stat_radio_params_5[WL1271_STAT_RADIO_PARAMS_5_SIZE];
+ /* Static radio parameters */
+ struct wl1271_ini_band_params_2 static_params_2;
+ struct wl1271_ini_band_params_5 static_params_5;
- u8 dyn_radio_params[WL1271_NVS_DYN_RADIO_PARAMS_SIZE];
- u8 reserved;
- u8 dyn_radio_params_5[WL1271_DYN_RADIO_PARAMS_5_SIZE];
-} __attribute__ ((packed));
+ /* Dynamic radio parameters */
+ struct wl1271_ini_fem_params_2 dyn_params_2;
+ u8 padding2;
+ struct wl1271_ini_fem_params_5 dyn_params_5;
+ u8 padding3[2];
+} __packed;
struct wl1271_cmd_cal_channel_tune {
struct wl1271_cmd_header header;
@@ -468,7 +474,7 @@ struct wl1271_cmd_cal_channel_tune {
u8 channel;
__le16 radio_status;
-} __attribute__ ((packed));
+} __packed;
struct wl1271_cmd_cal_update_ref_point {
struct wl1271_cmd_header header;
@@ -479,7 +485,7 @@ struct wl1271_cmd_cal_update_ref_point {
__le32 ref_detector;
u8 sub_band;
u8 padding[3];
-} __attribute__ ((packed));
+} __packed;
#define MAX_TLV_LENGTH 400
#define MAX_NVS_VERSION_LENGTH 12
@@ -501,7 +507,7 @@ struct wl1271_cmd_cal_p2g {
u8 sub_band_mask;
u8 padding2;
-} __attribute__ ((packed));
+} __packed;
/*
@@ -529,6 +535,6 @@ struct wl1271_cmd_disconnect {
u8 type;
u8 padding;
-} __attribute__ ((packed));
+} __packed;
#endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index cf37aa6eb13..ca52cdec7a8 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -43,11 +43,11 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
/* FIXME: ie missing! */
wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len,
- NULL, 0,
- wl->scan.active,
- wl->scan.high_prio,
- WL1271_SCAN_BAND_5_GHZ,
- wl->scan.probe_requests);
+ wl->scan.req,
+ wl->scan.active,
+ wl->scan.high_prio,
+ WL1271_SCAN_BAND_5_GHZ,
+ wl->scan.probe_requests);
} else {
mutex_unlock(&wl->mutex);
ieee80211_scan_completed(wl->hw, false);
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h
index 58371008f27..43d5aeae178 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.h
+++ b/drivers/net/wireless/wl12xx/wl1271_event.h
@@ -85,7 +85,7 @@ struct event_debug_report {
__le32 report_1;
__le32 report_2;
__le32 report_3;
-} __attribute__ ((packed));
+} __packed;
#define NUM_OF_RSSI_SNR_TRIGGERS 8
@@ -116,7 +116,7 @@ struct event_mailbox {
u8 ps_status;
u8 reserved_5[29];
-} __attribute__ ((packed));
+} __packed;
int wl1271_event_unmask(struct wl1271 *wl);
void wl1271_event_mbox_config(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_ini.h b/drivers/net/wireless/wl12xx/wl1271_ini.h
new file mode 100644
index 00000000000..2313047d401
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_ini.h
@@ -0,0 +1,123 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_INI_H__
+#define __WL1271_INI_H__
+
+#define WL1271_INI_MAX_SMART_REFLEX_PARAM 16
+
+struct wl1271_ini_general_params {
+ u8 ref_clock;
+ u8 settling_time;
+ u8 clk_valid_on_wakeup;
+ u8 dc2dc_mode;
+ u8 dual_mode_select;
+ u8 tx_bip_fem_auto_detect;
+ u8 tx_bip_fem_manufacturer;
+ u8 general_settings;
+ u8 sr_state;
+ u8 srf1[WL1271_INI_MAX_SMART_REFLEX_PARAM];
+ u8 srf2[WL1271_INI_MAX_SMART_REFLEX_PARAM];
+ u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM];
+} __packed;
+
+#define WL1271_INI_RSSI_PROCESS_COMPENS_SIZE 15
+
+struct wl1271_ini_band_params_2 {
+ u8 rx_trace_insertion_loss;
+ u8 tx_trace_loss;
+ u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE];
+} __packed;
+
+#define WL1271_INI_RATE_GROUP_COUNT 6
+#define WL1271_INI_CHANNEL_COUNT_2 14
+
+struct wl1271_ini_fem_params_2 {
+ __le16 tx_bip_ref_pd_voltage;
+ u8 tx_bip_ref_power;
+ u8 tx_bip_ref_offset;
+ u8 tx_per_rate_pwr_limits_normal[WL1271_INI_RATE_GROUP_COUNT];
+ u8 tx_per_rate_pwr_limits_degraded[WL1271_INI_RATE_GROUP_COUNT];
+ u8 tx_per_rate_pwr_limits_extreme[WL1271_INI_RATE_GROUP_COUNT];
+ u8 tx_per_chan_pwr_limits_11b[WL1271_INI_CHANNEL_COUNT_2];
+ u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_2];
+ u8 tx_pd_vs_rate_offsets[WL1271_INI_RATE_GROUP_COUNT];
+ u8 tx_ibias[WL1271_INI_RATE_GROUP_COUNT];
+ u8 rx_fem_insertion_loss;
+ u8 degraded_low_to_normal_thr;
+ u8 normal_to_degraded_high_thr;
+} __packed;
+
+#define WL1271_INI_CHANNEL_COUNT_5 35
+#define WL1271_INI_SUB_BAND_COUNT_5 7
+
+struct wl1271_ini_band_params_5 {
+ u8 rx_trace_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5];
+ u8 tx_trace_loss[WL1271_INI_SUB_BAND_COUNT_5];
+ u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE];
+} __packed;
+
+struct wl1271_ini_fem_params_5 {
+ __le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5];
+ u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5];
+ u8 tx_bip_ref_offset[WL1271_INI_SUB_BAND_COUNT_5];
+ u8 tx_per_rate_pwr_limits_normal[WL1271_INI_RATE_GROUP_COUNT];
+ u8 tx_per_rate_pwr_limits_degraded[WL1271_INI_RATE_GROUP_COUNT];
+ u8 tx_per_rate_pwr_limits_extreme[WL1271_INI_RATE_GROUP_COUNT];
+ u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_5];
+ u8 tx_pd_vs_rate_offsets[WL1271_INI_RATE_GROUP_COUNT];
+ u8 tx_ibias[WL1271_INI_RATE_GROUP_COUNT];
+ u8 rx_fem_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5];
+ u8 degraded_low_to_normal_thr;
+ u8 normal_to_degraded_high_thr;
+} __packed;
+
+
+/* NVS data structure */
+#define WL1271_INI_NVS_SECTION_SIZE 468
+#define WL1271_INI_FEM_MODULE_COUNT 2
+
+#define WL1271_INI_LEGACY_NVS_FILE_SIZE 800
+
+struct wl1271_nvs_file {
+ /* NVS section */
+ u8 nvs[WL1271_INI_NVS_SECTION_SIZE];
+
+ /* INI section */
+ struct wl1271_ini_general_params general_params;
+ u8 padding1;
+ struct wl1271_ini_band_params_2 stat_radio_params_2;
+ u8 padding2;
+ struct {
+ struct wl1271_ini_fem_params_2 params;
+ u8 padding;
+ } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT];
+ struct wl1271_ini_band_params_5 stat_radio_params_5;
+ u8 padding3;
+ struct {
+ struct wl1271_ini_fem_params_5 params;
+ u8 padding;
+ } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT];
+} __packed;
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index b7d9137851a..7a14da506d7 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -566,14 +566,21 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
return ret;
}
- if (fw->size != sizeof(struct wl1271_nvs_file)) {
+ /*
+ * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
+ * configurations) can be removed when those NVS files stop floating
+ * around.
+ */
+ if (fw->size != sizeof(struct wl1271_nvs_file) &&
+ (fw->size != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
+ wl1271_11a_enabled())) {
wl1271_error("nvs size is not as expected: %zu != %zu",
fw->size, sizeof(struct wl1271_nvs_file));
ret = -EILSEQ;
goto out;
}
- wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+ wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
if (!wl->nvs) {
wl1271_error("could not allocate memory for the nvs file");
@@ -581,7 +588,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
goto out;
}
- memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file));
+ memcpy(wl->nvs, fw->data, fw->size);
out:
release_firmware(fw);
@@ -1044,7 +1051,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);
/* let's notify MAC80211 about the remaining pending TX frames */
- wl1271_tx_flush(wl);
+ wl1271_tx_reset(wl);
wl1271_power_off(wl);
memset(wl->bssid, 0, ETH_ALEN);
@@ -1241,6 +1248,42 @@ static u32 wl1271_min_rate_get(struct wl1271 *wl)
return rate;
}
+static int wl1271_handle_idle(struct wl1271 *wl, bool idle)
+{
+ int ret;
+
+ if (idle) {
+ if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
+ ret = wl1271_unjoin(wl);
+ if (ret < 0)
+ goto out;
+ }
+ wl->rate_set = wl1271_min_rate_get(wl);
+ wl->sta_rate_set = 0;
+ ret = wl1271_acx_rate_policies(wl);
+ if (ret < 0)
+ goto out;
+ ret = wl1271_acx_keep_alive_config(
+ wl, CMD_TEMPL_KLV_IDX_NULL_DATA,
+ ACX_KEEP_ALIVE_TPL_INVALID);
+ if (ret < 0)
+ goto out;
+ set_bit(WL1271_FLAG_IDLE, &wl->flags);
+ } else {
+ /* increment the session counter */
+ wl->session_counter++;
+ if (wl->session_counter >= SESSION_COUNTER_MAX)
+ wl->session_counter = 0;
+ ret = wl1271_dummy_join(wl);
+ if (ret < 0)
+ goto out;
+ clear_bit(WL1271_FLAG_IDLE, &wl->flags);
+ }
+
+out:
+ return ret;
+}
+
static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct wl1271 *wl = hw->priv;
@@ -1255,6 +1298,15 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
conf->power_level,
conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use");
+ /*
+ * mac80211 will go to idle nearly immediately after transmitting some
+ * frames, such as the deauth. To make sure those frames reach the air,
+ * wait here until the TX queue is fully flushed.
+ */
+ if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
+ (conf->flags & IEEE80211_CONF_IDLE))
+ wl1271_tx_flush(wl);
+
mutex_lock(&wl->mutex);
if (unlikely(wl->state == WL1271_STATE_OFF))
@@ -1295,22 +1347,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
- if (conf->flags & IEEE80211_CONF_IDLE &&
- test_bit(WL1271_FLAG_JOINED, &wl->flags))
- wl1271_unjoin(wl);
- else if (!(conf->flags & IEEE80211_CONF_IDLE))
- wl1271_dummy_join(wl);
-
- if (conf->flags & IEEE80211_CONF_IDLE) {
- wl->rate_set = wl1271_min_rate_get(wl);
- wl->sta_rate_set = 0;
- wl1271_acx_rate_policies(wl);
- wl1271_acx_keep_alive_config(
- wl, CMD_TEMPL_KLV_IDX_NULL_DATA,
- ACX_KEEP_ALIVE_TPL_INVALID);
- set_bit(WL1271_FLAG_IDLE, &wl->flags);
- } else
- clear_bit(WL1271_FLAG_IDLE, &wl->flags);
+ ret = wl1271_handle_idle(wl, conf->flags & IEEE80211_CONF_IDLE);
+ if (ret < 0)
+ wl1271_warning("idle mode change failed %d", ret);
}
if (conf->flags & IEEE80211_CONF_PS &&
@@ -1595,13 +1634,11 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
goto out;
if (wl1271_11a_enabled())
- ret = wl1271_cmd_scan(hw->priv, ssid, len,
- req->ie, req->ie_len, 1, 0,
- WL1271_SCAN_BAND_DUAL, 3);
+ ret = wl1271_cmd_scan(hw->priv, ssid, len, req,
+ 1, 0, WL1271_SCAN_BAND_DUAL, 3);
else
- ret = wl1271_cmd_scan(hw->priv, ssid, len,
- req->ie, req->ie_len, 1, 0,
- WL1271_SCAN_BAND_2_4_GHZ, 3);
+ ret = wl1271_cmd_scan(hw->priv, ssid, len, req,
+ 1, 0, WL1271_SCAN_BAND_2_4_GHZ, 3);
wl1271_ps_elp_sleep(wl);
@@ -1991,7 +2028,7 @@ static struct ieee80211_channel wl1271_channels[] = {
};
/* mapping to indexes for wl1271_rates */
-const static u8 wl1271_rate_to_idx_2ghz[] = {
+static const u8 wl1271_rate_to_idx_2ghz[] = {
/* MCS rates are used only with 11n */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */
@@ -2103,7 +2140,7 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = {
};
/* mapping to indexes for wl1271_rates_5ghz */
-const static u8 wl1271_rate_to_idx_5ghz[] = {
+static const u8 wl1271_rate_to_idx_5ghz[] = {
/* MCS rates are used only with 11n */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */
CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */
@@ -2139,7 +2176,7 @@ static struct ieee80211_supported_band wl1271_band_5ghz = {
.n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
};
-const static u8 *wl1271_band_rate_to_idx[] = {
+static const u8 *wl1271_band_rate_to_idx[] = {
[IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz,
[IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz
};
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h
index b89be4758e7..13a232333b1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.h
@@ -113,7 +113,7 @@ struct wl1271_rx_descriptor {
u8 process_id;
u8 pad_len;
u8 reserved;
-} __attribute__ ((packed));
+} __packed;
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status);
u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate);
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index d3d6f302f70..7059b5cccf0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -28,7 +28,7 @@
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
-#include <plat/gpio.h>
+#include <linux/gpio.h>
#include "wl1271.h"
#include "wl12xx_80211.h"
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c
index 554deb4d024..6e0952f79e9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_testmode.c
+++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c
@@ -199,7 +199,14 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
len = nla_len(tb[WL1271_TM_ATTR_DATA]);
- if (len != sizeof(struct wl1271_nvs_file)) {
+ /*
+ * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
+ * configurations) can be removed when those NVS files stop floating
+ * around.
+ */
+ if (len != sizeof(struct wl1271_nvs_file) &&
+ (len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
+ wl1271_11a_enabled())) {
wl1271_error("nvs size is not as expected: %zu != %zu",
len, sizeof(struct wl1271_nvs_file));
return -EMSGSIZE;
@@ -209,7 +216,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
kfree(wl->nvs);
- wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+ wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
if (!wl->nvs) {
wl1271_error("could not allocate memory for the nvs file");
ret = -ENOMEM;
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 62db79508dd..c592cc2e9fe 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -36,6 +36,7 @@ static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb)
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
if (wl->tx_frames[i] == NULL) {
wl->tx_frames[i] = skb;
+ wl->tx_frames_cnt++;
return i;
}
@@ -73,8 +74,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
wl1271_debug(DEBUG_TX,
"tx_allocate: size: %d, blocks: %d, id: %d",
total_len, total_blocks, id);
- } else
+ } else {
wl->tx_frames[id] = NULL;
+ wl->tx_frames_cnt--;
+ }
return ret;
}
@@ -358,6 +361,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
/* return the packet to the stack */
ieee80211_tx_status(wl->hw, skb);
wl->tx_frames[result->id] = NULL;
+ wl->tx_frames_cnt--;
}
/* Called upon reception of a TX complete interrupt */
@@ -412,7 +416,7 @@ void wl1271_tx_complete(struct wl1271 *wl)
}
/* caller must hold wl->mutex */
-void wl1271_tx_flush(struct wl1271 *wl)
+void wl1271_tx_reset(struct wl1271 *wl)
{
int i;
struct sk_buff *skb;
@@ -421,7 +425,7 @@ void wl1271_tx_flush(struct wl1271 *wl)
/* control->flags = 0; FIXME */
while ((skb = skb_dequeue(&wl->tx_queue))) {
- wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb);
+ wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
ieee80211_tx_status(wl->hw, skb);
}
@@ -429,6 +433,32 @@ void wl1271_tx_flush(struct wl1271 *wl)
if (wl->tx_frames[i] != NULL) {
skb = wl->tx_frames[i];
wl->tx_frames[i] = NULL;
+ wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
ieee80211_tx_status(wl->hw, skb);
}
+ wl->tx_frames_cnt = 0;
+}
+
+#define WL1271_TX_FLUSH_TIMEOUT 500000
+
+/* caller must *NOT* hold wl->mutex */
+void wl1271_tx_flush(struct wl1271 *wl)
+{
+ unsigned long timeout;
+ timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT);
+
+ while (!time_after(jiffies, timeout)) {
+ mutex_lock(&wl->mutex);
+ wl1271_debug(DEBUG_TX, "flushing tx buffer: %d",
+ wl->tx_frames_cnt);
+ if ((wl->tx_frames_cnt == 0) &&
+ skb_queue_empty(&wl->tx_queue)) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
+ mutex_unlock(&wl->mutex);
+ msleep(1);
+ }
+
+ wl1271_warning("Unable to flush all TX buffers, timed out.");
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h
index 3b8b7ac253f..48bf92621c0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -80,7 +80,7 @@ struct wl1271_tx_hw_descr {
/* Identifier of the remote STA in IBSS, 1 in infra-BSS */
u8 aid;
u8 reserved;
-} __attribute__ ((packed));
+} __packed;
enum wl1271_tx_hw_res_status {
TX_SUCCESS = 0,
@@ -115,13 +115,13 @@ struct wl1271_tx_hw_res_descr {
u8 rate_class_index;
/* for 4-byte alignment. */
u8 spare;
-} __attribute__ ((packed));
+} __packed;
struct wl1271_tx_hw_res_if {
__le32 tx_result_fw_counter;
__le32 tx_result_host_counter;
struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN];
-} __attribute__ ((packed));
+} __packed;
static inline int wl1271_tx_get_queue(int queue)
{
@@ -158,6 +158,7 @@ static inline int wl1271_tx_ac_to_tid(int ac)
void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_complete(struct wl1271 *wl);
+void wl1271_tx_reset(struct wl1271 *wl);
void wl1271_tx_flush(struct wl1271 *wl);
u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate);
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h
index 055d7bc6f59..18462802721 100644
--- a/drivers/net/wireless/wl12xx/wl12xx_80211.h
+++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h
@@ -66,41 +66,41 @@ struct ieee80211_header {
u8 bssid[ETH_ALEN];
__le16 seq_ctl;
u8 payload[0];
-} __attribute__ ((packed));
+} __packed;
struct wl12xx_ie_header {
u8 id;
u8 len;
-} __attribute__ ((packed));
+} __packed;
/* IEs */
struct wl12xx_ie_ssid {
struct wl12xx_ie_header header;
char ssid[IW_ESSID_MAX_SIZE];
-} __attribute__ ((packed));
+} __packed;
struct wl12xx_ie_rates {
struct wl12xx_ie_header header;
u8 rates[MAX_SUPPORTED_RATES];
-} __attribute__ ((packed));
+} __packed;
struct wl12xx_ie_ds_params {
struct wl12xx_ie_header header;
u8 channel;
-} __attribute__ ((packed));
+} __packed;
struct country_triplet {
u8 channel;
u8 num_channels;
u8 max_tx_power;
-} __attribute__ ((packed));
+} __packed;
struct wl12xx_ie_country {
struct wl12xx_ie_header header;
u8 country_string[COUNTRY_STRING_LEN];
struct country_triplet triplets[MAX_COUNTRY_TRIPLETS];
-} __attribute__ ((packed));
+} __packed;
/* Templates */
@@ -115,30 +115,30 @@ struct wl12xx_beacon_template {
struct wl12xx_ie_rates ext_rates;
struct wl12xx_ie_ds_params ds_params;
struct wl12xx_ie_country country;
-} __attribute__ ((packed));
+} __packed;
struct wl12xx_null_data_template {
struct ieee80211_header header;
-} __attribute__ ((packed));
+} __packed;
struct wl12xx_ps_poll_template {
__le16 fc;
__le16 aid;
u8 bssid[ETH_ALEN];
u8 ta[ETH_ALEN];
-} __attribute__ ((packed));
+} __packed;
struct wl12xx_qos_null_data_template {
struct ieee80211_header header;
__le16 qos_ctl;
-} __attribute__ ((packed));
+} __packed;
struct wl12xx_probe_req_template {
struct ieee80211_header header;
struct wl12xx_ie_ssid ssid;
struct wl12xx_ie_rates rates;
struct wl12xx_ie_rates ext_rates;
-} __attribute__ ((packed));
+} __packed;
struct wl12xx_probe_resp_template {
@@ -151,6 +151,6 @@ struct wl12xx_probe_resp_template {
struct wl12xx_ie_rates ext_rates;
struct wl12xx_ie_ds_params ds_params;
struct wl12xx_ie_country country;
-} __attribute__ ((packed));
+} __packed;
#endif