mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 14:52:05 +00:00
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
This commit is contained in:
commit
8715d941b2
@ -6,3 +6,5 @@ wl1251_sdio-objs += sdio.o
|
||||
obj-$(CONFIG_WL1251) += wl1251.o
|
||||
obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o
|
||||
obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
@ -464,8 +464,6 @@ static int wl1251_boot_upload_nvs(struct wl1251 *wl)
|
||||
val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
|
||||
| (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
|
||||
|
||||
val = cpu_to_le32(val);
|
||||
|
||||
wl1251_debug(DEBUG_BOOT,
|
||||
"nvs write table 0x%x: 0x%x",
|
||||
nvs_start, val);
|
||||
|
@ -36,16 +36,15 @@
|
||||
|
||||
static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
|
||||
{
|
||||
u32 response;
|
||||
wl->if_ops->read(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32));
|
||||
|
||||
wl->if_ops->read(wl, addr, &response, sizeof(u32));
|
||||
|
||||
return response;
|
||||
return le32_to_cpu(wl->buffer_32);
|
||||
}
|
||||
|
||||
static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
|
||||
{
|
||||
wl->if_ops->write(wl, addr, &val, sizeof(u32));
|
||||
wl->buffer_32 = cpu_to_le32(val);
|
||||
wl->if_ops->write(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32));
|
||||
}
|
||||
|
||||
static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr)
|
||||
|
@ -380,7 +380,7 @@ struct wl1251 {
|
||||
struct wl1251_stats stats;
|
||||
struct wl1251_debugfs debugfs;
|
||||
|
||||
u32 buffer_32;
|
||||
__le32 buffer_32;
|
||||
u32 buffer_cmd;
|
||||
u8 buffer_busyword[WL1251_BUSY_WORD_LEN];
|
||||
struct wl1251_rx_descriptor *rx_descriptor;
|
||||
|
@ -11,3 +11,5 @@ obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o
|
||||
|
||||
# small builtin driver bit
|
||||
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
@ -34,12 +34,14 @@
|
||||
#include "reg.h"
|
||||
#include "ps.h"
|
||||
|
||||
int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
u8 wake_up_event, u8 listen_interval)
|
||||
{
|
||||
struct acx_wake_up_condition *wake_up;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx wake up conditions");
|
||||
wl1271_debug(DEBUG_ACX, "acx wake up conditions (wake_up_event %d listen_interval %d)",
|
||||
wake_up_event, listen_interval);
|
||||
|
||||
wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
|
||||
if (!wake_up) {
|
||||
@ -48,8 +50,8 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
}
|
||||
|
||||
wake_up->role_id = wlvif->role_id;
|
||||
wake_up->wake_up_event = wl->conf.conn.wake_up_event;
|
||||
wake_up->listen_interval = wl->conf.conn.listen_interval;
|
||||
wake_up->wake_up_event = wake_up_event;
|
||||
wake_up->listen_interval = listen_interval;
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
|
||||
wake_up, sizeof(*wake_up));
|
||||
@ -1459,9 +1461,10 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
|
||||
int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
u64 *mactime)
|
||||
{
|
||||
struct wl1271_acx_fw_tsf_information *tsf_info;
|
||||
struct wl12xx_acx_fw_tsf_information *tsf_info;
|
||||
int ret;
|
||||
|
||||
tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL);
|
||||
@ -1470,6 +1473,8 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
|
||||
goto out;
|
||||
}
|
||||
|
||||
tsf_info->role_id = wlvif->role_id;
|
||||
|
||||
ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO,
|
||||
tsf_info, sizeof(*tsf_info));
|
||||
if (ret < 0) {
|
||||
|
@ -995,15 +995,17 @@ struct wl1271_acx_ba_receiver_setup {
|
||||
u8 padding[2];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_fw_tsf_information {
|
||||
struct wl12xx_acx_fw_tsf_information {
|
||||
struct acx_header header;
|
||||
|
||||
u8 role_id;
|
||||
u8 padding1[3];
|
||||
__le32 current_tsf_high;
|
||||
__le32 current_tsf_low;
|
||||
__le32 last_bttt_high;
|
||||
__le32 last_tbtt_low;
|
||||
u8 last_dtim_count;
|
||||
u8 padding[3];
|
||||
u8 padding2[3];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_acx_ps_rx_streaming {
|
||||
@ -1151,79 +1153,81 @@ struct wl12xx_acx_config_hangover {
|
||||
} __packed;
|
||||
|
||||
enum {
|
||||
ACX_WAKE_UP_CONDITIONS = 0x0002,
|
||||
ACX_MEM_CFG = 0x0003,
|
||||
ACX_SLOT = 0x0004,
|
||||
ACX_AC_CFG = 0x0007,
|
||||
ACX_MEM_MAP = 0x0008,
|
||||
ACX_AID = 0x000A,
|
||||
ACX_MEDIUM_USAGE = 0x000F,
|
||||
ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */
|
||||
ACX_STATISTICS = 0x0013, /* Debug API */
|
||||
ACX_PWR_CONSUMPTION_STATISTICS = 0x0014,
|
||||
ACX_FEATURE_CFG = 0x0015,
|
||||
ACX_TID_CFG = 0x001A,
|
||||
ACX_PS_RX_STREAMING = 0x001B,
|
||||
ACX_BEACON_FILTER_OPT = 0x001F,
|
||||
ACX_NOISE_HIST = 0x0021,
|
||||
ACX_HDK_VERSION = 0x0022, /* ??? */
|
||||
ACX_PD_THRESHOLD = 0x0023,
|
||||
ACX_TX_CONFIG_OPT = 0x0024,
|
||||
ACX_CCA_THRESHOLD = 0x0025,
|
||||
ACX_EVENT_MBOX_MASK = 0x0026,
|
||||
ACX_CONN_MONIT_PARAMS = 0x002D,
|
||||
ACX_BCN_DTIM_OPTIONS = 0x0031,
|
||||
ACX_SG_ENABLE = 0x0032,
|
||||
ACX_SG_CFG = 0x0033,
|
||||
ACX_FM_COEX_CFG = 0x0034,
|
||||
ACX_BEACON_FILTER_TABLE = 0x0038,
|
||||
ACX_ARP_IP_FILTER = 0x0039,
|
||||
ACX_ROAMING_STATISTICS_TBL = 0x003B,
|
||||
ACX_RATE_POLICY = 0x003D,
|
||||
ACX_CTS_PROTECTION = 0x003E,
|
||||
ACX_SLEEP_AUTH = 0x003F,
|
||||
ACX_PREAMBLE_TYPE = 0x0040,
|
||||
ACX_ERROR_CNT = 0x0041,
|
||||
ACX_IBSS_FILTER = 0x0044,
|
||||
ACX_SERVICE_PERIOD_TIMEOUT = 0x0045,
|
||||
ACX_TSF_INFO = 0x0046,
|
||||
ACX_CONFIG_PS_WMM = 0x0049,
|
||||
ACX_ENABLE_RX_DATA_FILTER = 0x004A,
|
||||
ACX_SET_RX_DATA_FILTER = 0x004B,
|
||||
ACX_GET_DATA_FILTER_STATISTICS = 0x004C,
|
||||
ACX_RX_CONFIG_OPT = 0x004E,
|
||||
ACX_FRAG_CFG = 0x004F,
|
||||
ACX_BET_ENABLE = 0x0050,
|
||||
ACX_RSSI_SNR_TRIGGER = 0x0051,
|
||||
ACX_RSSI_SNR_WEIGHTS = 0x0052,
|
||||
ACX_KEEP_ALIVE_MODE = 0x0053,
|
||||
ACX_SET_KEEP_ALIVE_CONFIG = 0x0054,
|
||||
ACX_BA_SESSION_INIT_POLICY = 0x0055,
|
||||
ACX_BA_SESSION_RX_SETUP = 0x0056,
|
||||
ACX_PEER_HT_CAP = 0x0057,
|
||||
ACX_HT_BSS_OPERATION = 0x0058,
|
||||
ACX_COEX_ACTIVITY = 0x0059,
|
||||
ACX_BURST_MODE = 0x005C,
|
||||
ACX_SET_RATE_MGMT_PARAMS = 0x005D,
|
||||
ACX_SET_RATE_ADAPT_PARAMS = 0x0060,
|
||||
ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
|
||||
ACX_GEN_FW_CMD = 0x0070,
|
||||
ACX_HOST_IF_CFG_BITMAP = 0x0071,
|
||||
ACX_MAX_TX_FAILURE = 0x0072,
|
||||
ACX_UPDATE_INCONNECTION_STA_LIST = 0x0073,
|
||||
DOT11_RX_MSDU_LIFE_TIME = 0x1004,
|
||||
DOT11_CUR_TX_PWR = 0x100D,
|
||||
DOT11_RX_DOT11_MODE = 0x1012,
|
||||
DOT11_RTS_THRESHOLD = 0x1013,
|
||||
DOT11_GROUP_ADDRESS_TBL = 0x1014,
|
||||
ACX_PM_CONFIG = 0x1016,
|
||||
ACX_CONFIG_PS = 0x1017,
|
||||
ACX_CONFIG_HANGOVER = 0x1018,
|
||||
ACX_WAKE_UP_CONDITIONS = 0x0000,
|
||||
ACX_MEM_CFG = 0x0001,
|
||||
ACX_SLOT = 0x0002,
|
||||
ACX_AC_CFG = 0x0003,
|
||||
ACX_MEM_MAP = 0x0004,
|
||||
ACX_AID = 0x0005,
|
||||
ACX_MEDIUM_USAGE = 0x0006,
|
||||
ACX_STATISTICS = 0x0007,
|
||||
ACX_PWR_CONSUMPTION_STATISTICS = 0x0008,
|
||||
ACX_TID_CFG = 0x0009,
|
||||
ACX_PS_RX_STREAMING = 0x000A,
|
||||
ACX_BEACON_FILTER_OPT = 0x000B,
|
||||
ACX_NOISE_HIST = 0x000C,
|
||||
ACX_HDK_VERSION = 0x000D,
|
||||
ACX_PD_THRESHOLD = 0x000E,
|
||||
ACX_TX_CONFIG_OPT = 0x000F,
|
||||
ACX_CCA_THRESHOLD = 0x0010,
|
||||
ACX_EVENT_MBOX_MASK = 0x0011,
|
||||
ACX_CONN_MONIT_PARAMS = 0x0012,
|
||||
ACX_DISABLE_BROADCASTS = 0x0013,
|
||||
ACX_BCN_DTIM_OPTIONS = 0x0014,
|
||||
ACX_SG_ENABLE = 0x0015,
|
||||
ACX_SG_CFG = 0x0016,
|
||||
ACX_FM_COEX_CFG = 0x0017,
|
||||
ACX_BEACON_FILTER_TABLE = 0x0018,
|
||||
ACX_ARP_IP_FILTER = 0x0019,
|
||||
ACX_ROAMING_STATISTICS_TBL = 0x001A,
|
||||
ACX_RATE_POLICY = 0x001B,
|
||||
ACX_CTS_PROTECTION = 0x001C,
|
||||
ACX_SLEEP_AUTH = 0x001D,
|
||||
ACX_PREAMBLE_TYPE = 0x001E,
|
||||
ACX_ERROR_CNT = 0x001F,
|
||||
ACX_IBSS_FILTER = 0x0020,
|
||||
ACX_SERVICE_PERIOD_TIMEOUT = 0x0021,
|
||||
ACX_TSF_INFO = 0x0022,
|
||||
ACX_CONFIG_PS_WMM = 0x0023,
|
||||
ACX_ENABLE_RX_DATA_FILTER = 0x0024,
|
||||
ACX_SET_RX_DATA_FILTER = 0x0025,
|
||||
ACX_GET_DATA_FILTER_STATISTICS = 0x0026,
|
||||
ACX_RX_CONFIG_OPT = 0x0027,
|
||||
ACX_FRAG_CFG = 0x0028,
|
||||
ACX_BET_ENABLE = 0x0029,
|
||||
ACX_RSSI_SNR_TRIGGER = 0x002A,
|
||||
ACX_RSSI_SNR_WEIGHTS = 0x002B,
|
||||
ACX_KEEP_ALIVE_MODE = 0x002C,
|
||||
ACX_SET_KEEP_ALIVE_CONFIG = 0x002D,
|
||||
ACX_BA_SESSION_INIT_POLICY = 0x002E,
|
||||
ACX_BA_SESSION_RX_SETUP = 0x002F,
|
||||
ACX_PEER_HT_CAP = 0x0030,
|
||||
ACX_HT_BSS_OPERATION = 0x0031,
|
||||
ACX_COEX_ACTIVITY = 0x0032,
|
||||
ACX_BURST_MODE = 0x0033,
|
||||
ACX_SET_RATE_MGMT_PARAMS = 0x0034,
|
||||
ACX_GET_RATE_MGMT_PARAMS = 0x0035,
|
||||
ACX_SET_RATE_ADAPT_PARAMS = 0x0036,
|
||||
ACX_SET_DCO_ITRIM_PARAMS = 0x0037,
|
||||
ACX_GEN_FW_CMD = 0x0038,
|
||||
ACX_HOST_IF_CFG_BITMAP = 0x0039,
|
||||
ACX_MAX_TX_FAILURE = 0x003A,
|
||||
ACX_UPDATE_INCONNECTION_STA_LIST = 0x003B,
|
||||
DOT11_RX_MSDU_LIFE_TIME = 0x003C,
|
||||
DOT11_CUR_TX_PWR = 0x003D,
|
||||
DOT11_RTS_THRESHOLD = 0x003E,
|
||||
DOT11_GROUP_ADDRESS_TBL = 0x003F,
|
||||
ACX_PM_CONFIG = 0x0040,
|
||||
ACX_CONFIG_PS = 0x0041,
|
||||
ACX_CONFIG_HANGOVER = 0x0042,
|
||||
ACX_FEATURE_CFG = 0x0043,
|
||||
ACX_PROTECTION_CFG = 0x0044,
|
||||
};
|
||||
|
||||
|
||||
int wl1271_acx_wake_up_conditions(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif);
|
||||
struct wl12xx_vif *wlvif,
|
||||
u8 wake_up_event, u8 listen_interval);
|
||||
int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth);
|
||||
int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
int power);
|
||||
@ -1296,7 +1300,8 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif);
|
||||
int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
|
||||
u16 ssn, bool enable, u8 peer_hlid);
|
||||
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
|
||||
int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
u64 *mactime);
|
||||
int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
bool enable);
|
||||
int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||
|
@ -33,65 +33,6 @@
|
||||
#include "event.h"
|
||||
#include "rx.h"
|
||||
|
||||
static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
|
||||
[PART_DOWN] = {
|
||||
.mem = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x000177c0
|
||||
},
|
||||
.reg = {
|
||||
.start = REGISTERS_BASE,
|
||||
.size = 0x00008800
|
||||
},
|
||||
.mem2 = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x00000000
|
||||
},
|
||||
.mem3 = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x00000000
|
||||
},
|
||||
},
|
||||
|
||||
[PART_WORK] = {
|
||||
.mem = {
|
||||
.start = 0x00040000,
|
||||
.size = 0x00014fc0
|
||||
},
|
||||
.reg = {
|
||||
.start = REGISTERS_BASE,
|
||||
.size = 0x0000a000
|
||||
},
|
||||
.mem2 = {
|
||||
.start = 0x003004f8,
|
||||
.size = 0x00000004
|
||||
},
|
||||
.mem3 = {
|
||||
.start = 0x00040404,
|
||||
.size = 0x00000000
|
||||
},
|
||||
},
|
||||
|
||||
[PART_DRPW] = {
|
||||
.mem = {
|
||||
.start = 0x00040000,
|
||||
.size = 0x00014fc0
|
||||
},
|
||||
.reg = {
|
||||
.start = DRPW_BASE,
|
||||
.size = 0x00006000
|
||||
},
|
||||
.mem2 = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x00000000
|
||||
},
|
||||
.mem3 = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x00000000
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
|
||||
{
|
||||
u32 cpu_ctrl;
|
||||
@ -181,13 +122,13 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(&partition, &part_table[PART_DOWN], sizeof(partition));
|
||||
memcpy(&partition, &wl12xx_part_table[PART_DOWN], sizeof(partition));
|
||||
partition.mem.start = dest;
|
||||
wl1271_set_partition(wl, &partition);
|
||||
|
||||
/* 10.1 set partition limit and chunk num */
|
||||
chunk_num = 0;
|
||||
partition_limit = part_table[PART_DOWN].mem.size;
|
||||
partition_limit = wl12xx_part_table[PART_DOWN].mem.size;
|
||||
|
||||
while (chunk_num < fw_data_len / CHUNK_SIZE) {
|
||||
/* 10.2 update partition, if needed */
|
||||
@ -195,7 +136,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
|
||||
if (addr > partition_limit) {
|
||||
addr = dest + chunk_num * CHUNK_SIZE;
|
||||
partition_limit = chunk_num * CHUNK_SIZE +
|
||||
part_table[PART_DOWN].mem.size;
|
||||
wl12xx_part_table[PART_DOWN].mem.size;
|
||||
partition.mem.start = addr;
|
||||
wl1271_set_partition(wl, &partition);
|
||||
}
|
||||
@ -317,12 +258,12 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
}
|
||||
|
||||
/* update current MAC address to NVS */
|
||||
nvs_ptr[11] = wl->mac_addr[0];
|
||||
nvs_ptr[10] = wl->mac_addr[1];
|
||||
nvs_ptr[6] = wl->mac_addr[2];
|
||||
nvs_ptr[5] = wl->mac_addr[3];
|
||||
nvs_ptr[4] = wl->mac_addr[4];
|
||||
nvs_ptr[3] = wl->mac_addr[5];
|
||||
nvs_ptr[11] = wl->addresses[0].addr[0];
|
||||
nvs_ptr[10] = wl->addresses[0].addr[1];
|
||||
nvs_ptr[6] = wl->addresses[0].addr[2];
|
||||
nvs_ptr[5] = wl->addresses[0].addr[3];
|
||||
nvs_ptr[4] = wl->addresses[0].addr[4];
|
||||
nvs_ptr[3] = wl->addresses[0].addr[5];
|
||||
|
||||
/*
|
||||
* Layout before the actual NVS tables:
|
||||
@ -383,7 +324,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
nvs_len -= nvs_ptr - (u8 *)wl->nvs;
|
||||
|
||||
/* Now we must set the partition correctly */
|
||||
wl1271_set_partition(wl, &part_table[PART_WORK]);
|
||||
wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
|
||||
|
||||
/* Copy the NVS tables to a new block to ensure alignment */
|
||||
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
|
||||
@ -492,7 +433,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
|
||||
wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
|
||||
|
||||
/* set the working partition to its "running" mode offset */
|
||||
wl1271_set_partition(wl, &part_table[PART_WORK]);
|
||||
wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
|
||||
|
||||
wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
|
||||
wl->cmd_box_addr, wl->event_box_addr);
|
||||
@ -507,8 +448,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
|
||||
/* unmask required mbox events */
|
||||
wl->event_mask = BSS_LOSE_EVENT_ID |
|
||||
SCAN_COMPLETE_EVENT_ID |
|
||||
PS_REPORT_EVENT_ID |
|
||||
DISCONNECT_EVENT_COMPLETE_ID |
|
||||
ROLE_STOP_COMPLETE_EVENT_ID |
|
||||
RSSI_SNR_TRIGGER_0_EVENT_ID |
|
||||
PSPOLL_DELIVERY_FAILURE_EVENT_ID |
|
||||
SOFT_GEMINI_SENSE_EVENT_ID |
|
||||
@ -547,19 +487,6 @@ static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wl1271_boot_hw_version(struct wl1271 *wl)
|
||||
{
|
||||
u32 fuse;
|
||||
|
||||
if (wl->chip.id == CHIP_ID_1283_PG20)
|
||||
fuse = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
|
||||
else
|
||||
fuse = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
|
||||
fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET;
|
||||
|
||||
wl->hw_pg_ver = (s8)fuse;
|
||||
}
|
||||
|
||||
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
|
||||
{
|
||||
u16 spare_reg;
|
||||
@ -698,7 +625,7 @@ static int wl127x_boot_clk(struct wl1271 *wl)
|
||||
u32 pause;
|
||||
u32 clk;
|
||||
|
||||
if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
|
||||
if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
|
||||
wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
|
||||
|
||||
if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
|
||||
@ -753,8 +680,6 @@ int wl1271_load_firmware(struct wl1271 *wl)
|
||||
u32 tmp, clk;
|
||||
int selected_clock = -1;
|
||||
|
||||
wl1271_boot_hw_version(wl);
|
||||
|
||||
if (wl->chip.id == CHIP_ID_1283_PG20) {
|
||||
ret = wl128x_boot_clk(wl, &selected_clock);
|
||||
if (ret < 0)
|
||||
@ -769,7 +694,7 @@ int wl1271_load_firmware(struct wl1271 *wl)
|
||||
wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
|
||||
udelay(500);
|
||||
|
||||
wl1271_set_partition(wl, &part_table[PART_DRPW]);
|
||||
wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]);
|
||||
|
||||
/* Read-modify-write DRPW_SCRATCH_START register (see next state)
|
||||
to be used by DRPw FW. The RTRIM value will be added by the FW
|
||||
@ -788,7 +713,7 @@ int wl1271_load_firmware(struct wl1271 *wl)
|
||||
|
||||
wl1271_write32(wl, DRPW_SCRATCH_START, clk);
|
||||
|
||||
wl1271_set_partition(wl, &part_table[PART_WORK]);
|
||||
wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
|
||||
|
||||
/* Disable interrupts */
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
|
||||
|
@ -55,16 +55,6 @@ struct wl1271_static_data {
|
||||
#define OCP_REG_CLK_POLARITY 0x0cb2
|
||||
#define OCP_REG_CLK_PULL 0x0cb4
|
||||
|
||||
#define WL127X_REG_FUSE_DATA_2_1 0x050a
|
||||
#define WL128X_REG_FUSE_DATA_2_1 0x2152
|
||||
#define PG_VER_MASK 0x3c
|
||||
#define PG_VER_OFFSET 2
|
||||
|
||||
#define PG_MAJOR_VER_MASK 0x3
|
||||
#define PG_MAJOR_VER_OFFSET 0x0
|
||||
#define PG_MINOR_VER_MASK 0xc
|
||||
#define PG_MINOR_VER_OFFSET 0x2
|
||||
|
||||
#define CMD_MBOX_ADDRESS 0x407B4
|
||||
|
||||
#define POLARITY_LOW BIT(1)
|
||||
|
@ -566,7 +566,7 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl,
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
|
||||
ret = wl1271_cmd_wait_for_event(wl, ROLE_STOP_COMPLETE_EVENT_ID);
|
||||
if (ret < 0) {
|
||||
wl1271_error("cmd role stop dev event completion error");
|
||||
goto out_free;
|
||||
@ -715,6 +715,8 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int);
|
||||
cmd->ap.dtim_interval = bss_conf->dtim_period;
|
||||
cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
|
||||
/* FIXME: Change when adding DFS */
|
||||
cmd->ap.reset_tsf = 1; /* By default reset AP TSF */
|
||||
cmd->channel = wlvif->channel;
|
||||
|
||||
if (!bss_conf->hidden_ssid) {
|
||||
@ -994,7 +996,7 @@ out:
|
||||
}
|
||||
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
u8 ps_mode)
|
||||
u8 ps_mode, u16 auto_ps_timeout)
|
||||
{
|
||||
struct wl1271_cmd_ps_params *ps_params = NULL;
|
||||
int ret = 0;
|
||||
@ -1009,6 +1011,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
|
||||
ps_params->role_id = wlvif->role_id;
|
||||
ps_params->ps_mode = ps_mode;
|
||||
ps_params->auto_ps_timeout = auto_ps_timeout;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
|
||||
sizeof(*ps_params), 0);
|
||||
@ -1022,13 +1025,15 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
|
||||
void *buf, size_t buf_len, int index, u32 rates)
|
||||
int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id,
|
||||
u16 template_id, void *buf, size_t buf_len,
|
||||
int index, u32 rates)
|
||||
{
|
||||
struct wl1271_cmd_template_set *cmd;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id);
|
||||
wl1271_debug(DEBUG_CMD, "cmd template_set %d (role %d)",
|
||||
template_id, role_id);
|
||||
|
||||
WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE);
|
||||
buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE);
|
||||
@ -1039,6 +1044,8 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* during initialization wlvif is NULL */
|
||||
cmd->role_id = role_id;
|
||||
cmd->len = cpu_to_le16(buf_len);
|
||||
cmd->template_type = template_id;
|
||||
cmd->enabled_rates = cpu_to_le32(rates);
|
||||
@ -1082,7 +1089,8 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
ptr = skb->data;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0,
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id,
|
||||
CMD_TEMPL_NULL_DATA, ptr, size, 0,
|
||||
wlvif->basic_rate);
|
||||
|
||||
out:
|
||||
@ -1105,7 +1113,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl,
|
||||
if (!skb)
|
||||
goto out;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV,
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_KLV,
|
||||
skb->data, skb->len,
|
||||
CMD_TEMPL_KLV_IDX_NULL_DATA,
|
||||
wlvif->basic_rate);
|
||||
@ -1130,7 +1138,8 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
if (!skb)
|
||||
goto out;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data,
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id,
|
||||
CMD_TEMPL_PS_POLL, skb->data,
|
||||
skb->len, 0, wlvif->basic_rate_set);
|
||||
|
||||
out:
|
||||
@ -1138,9 +1147,10 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
u8 role_id, u8 band,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const u8 *ie, size_t ie_len, u8 band)
|
||||
const u8 *ie, size_t ie_len)
|
||||
{
|
||||
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
struct sk_buff *skb;
|
||||
@ -1158,10 +1168,12 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
|
||||
rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
|
||||
ret = wl1271_cmd_template_set(wl, role_id,
|
||||
CMD_TEMPL_CFG_PROBE_REQ_2_4,
|
||||
skb->data, skb->len, 0, rate);
|
||||
else
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
ret = wl1271_cmd_template_set(wl, role_id,
|
||||
CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
skb->data, skb->len, 0, rate);
|
||||
|
||||
out:
|
||||
@ -1186,10 +1198,12 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
|
||||
|
||||
rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]);
|
||||
if (wlvif->band == IEEE80211_BAND_2GHZ)
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id,
|
||||
CMD_TEMPL_CFG_PROBE_REQ_2_4,
|
||||
skb->data, skb->len, 0, rate);
|
||||
else
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id,
|
||||
CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
skb->data, skb->len, 0, rate);
|
||||
|
||||
if (ret < 0)
|
||||
@ -1199,32 +1213,34 @@ out:
|
||||
return skb;
|
||||
}
|
||||
|
||||
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
__be32 ip_addr)
|
||||
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
{
|
||||
int ret;
|
||||
int ret, extra;
|
||||
u16 fc;
|
||||
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
struct wl12xx_arp_rsp_template tmpl;
|
||||
struct sk_buff *skb;
|
||||
struct wl12xx_arp_rsp_template *tmpl;
|
||||
struct ieee80211_hdr_3addr *hdr;
|
||||
struct arphdr *arp_hdr;
|
||||
|
||||
memset(&tmpl, 0, sizeof(tmpl));
|
||||
skb = dev_alloc_skb(sizeof(*hdr) + sizeof(__le16) + sizeof(*tmpl) +
|
||||
WL1271_EXTRA_SPACE_MAX);
|
||||
if (!skb) {
|
||||
wl1271_error("failed to allocate buffer for arp rsp template");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* mac80211 header */
|
||||
hdr = &tmpl.hdr;
|
||||
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
|
||||
IEEE80211_STYPE_DATA |
|
||||
IEEE80211_FCTL_TODS);
|
||||
memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN);
|
||||
memcpy(hdr->addr2, vif->addr, ETH_ALEN);
|
||||
memset(hdr->addr3, 0xff, ETH_ALEN);
|
||||
skb_reserve(skb, sizeof(*hdr) + WL1271_EXTRA_SPACE_MAX);
|
||||
|
||||
tmpl = (struct wl12xx_arp_rsp_template *)skb_put(skb, sizeof(*tmpl));
|
||||
memset(tmpl, 0, sizeof(tmpl));
|
||||
|
||||
/* llc layer */
|
||||
memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header));
|
||||
tmpl.llc_type = cpu_to_be16(ETH_P_ARP);
|
||||
memcpy(tmpl->llc_hdr, rfc1042_header, sizeof(rfc1042_header));
|
||||
tmpl->llc_type = cpu_to_be16(ETH_P_ARP);
|
||||
|
||||
/* arp header */
|
||||
arp_hdr = &tmpl.arp_hdr;
|
||||
arp_hdr = &tmpl->arp_hdr;
|
||||
arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER);
|
||||
arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP);
|
||||
arp_hdr->ar_hln = ETH_ALEN;
|
||||
@ -1232,13 +1248,59 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY);
|
||||
|
||||
/* arp payload */
|
||||
memcpy(tmpl.sender_hw, vif->addr, ETH_ALEN);
|
||||
tmpl.sender_ip = ip_addr;
|
||||
memcpy(tmpl->sender_hw, vif->addr, ETH_ALEN);
|
||||
tmpl->sender_ip = wlvif->ip_addr;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP,
|
||||
&tmpl, sizeof(tmpl), 0,
|
||||
/* encryption space */
|
||||
switch (wlvif->encryption_type) {
|
||||
case KEY_TKIP:
|
||||
extra = WL1271_EXTRA_SPACE_TKIP;
|
||||
break;
|
||||
case KEY_AES:
|
||||
extra = WL1271_EXTRA_SPACE_AES;
|
||||
break;
|
||||
case KEY_NONE:
|
||||
case KEY_WEP:
|
||||
case KEY_GEM:
|
||||
extra = 0;
|
||||
break;
|
||||
default:
|
||||
wl1271_warning("Unknown encryption type: %d",
|
||||
wlvif->encryption_type);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (extra) {
|
||||
u8 *space = skb_push(skb, extra);
|
||||
memset(space, 0, extra);
|
||||
}
|
||||
|
||||
/* QoS header - BE */
|
||||
if (wlvif->sta.qos)
|
||||
memset(skb_push(skb, sizeof(__le16)), 0, sizeof(__le16));
|
||||
|
||||
/* mac80211 header */
|
||||
hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, sizeof(*hdr));
|
||||
memset(hdr, 0, sizeof(hdr));
|
||||
fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS;
|
||||
if (wlvif->sta.qos)
|
||||
fc |= IEEE80211_STYPE_QOS_DATA;
|
||||
else
|
||||
fc |= IEEE80211_STYPE_DATA;
|
||||
if (wlvif->encryption_type != KEY_NONE)
|
||||
fc |= IEEE80211_FCTL_PROTECTED;
|
||||
|
||||
hdr->frame_control = cpu_to_le16(fc);
|
||||
memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN);
|
||||
memcpy(hdr->addr2, vif->addr, ETH_ALEN);
|
||||
memset(hdr->addr3, 0xff, ETH_ALEN);
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_ARP_RSP,
|
||||
skb->data, skb->len, 0,
|
||||
wlvif->basic_rate);
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1260,7 +1322,8 @@ int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif)
|
||||
/* FIXME: not sure what priority to use here */
|
||||
template.qos_ctrl = cpu_to_le16(0);
|
||||
|
||||
return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
|
||||
return wl1271_cmd_template_set(wl, wlvif->role_id,
|
||||
CMD_TEMPL_QOS_NULL_DATA, &template,
|
||||
sizeof(template), 0,
|
||||
wlvif->basic_rate);
|
||||
}
|
||||
@ -1744,6 +1807,7 @@ out:
|
||||
}
|
||||
|
||||
int wl12xx_cmd_channel_switch(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct wl12xx_cmd_channel_switch *cmd;
|
||||
@ -1757,10 +1821,13 @@ int wl12xx_cmd_channel_switch(struct wl1271 *wl,
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->role_id = wlvif->role_id;
|
||||
cmd->channel = ch_switch->channel->hw_value;
|
||||
cmd->switch_time = ch_switch->count;
|
||||
cmd->tx_suspend = ch_switch->block_tx;
|
||||
cmd->flush = 0; /* this value is ignored by the FW */
|
||||
cmd->stop_tx = ch_switch->block_tx;
|
||||
|
||||
/* FIXME: control from mac80211 in the future */
|
||||
cmd->post_switch_tx_disable = 0; /* Enable TX on the target channel */
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
|
@ -51,22 +51,23 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
|
||||
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
|
||||
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
u8 ps_mode);
|
||||
u8 ps_mode, u16 auto_ps_timeout);
|
||||
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
|
||||
size_t len);
|
||||
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
|
||||
void *buf, size_t buf_len, int index, u32 rates);
|
||||
int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id,
|
||||
u16 template_id, void *buf, size_t buf_len,
|
||||
int index, u32 rates);
|
||||
int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||
int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
u16 aid);
|
||||
int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
u8 role_id, u8 band,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const u8 *ie, size_t ie_len, u8 band);
|
||||
const u8 *ie, size_t ie_len);
|
||||
struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct sk_buff *skb);
|
||||
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
__be32 ip_addr);
|
||||
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||
int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif);
|
||||
int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif);
|
||||
@ -89,6 +90,7 @@ int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
|
||||
int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
|
||||
int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
|
||||
int wl12xx_cmd_channel_switch(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl);
|
||||
int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
@ -96,62 +98,65 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid);
|
||||
|
||||
enum wl1271_commands {
|
||||
CMD_INTERROGATE = 1, /*use this to read information elements*/
|
||||
CMD_CONFIGURE = 2, /*use this to write information elements*/
|
||||
CMD_ENABLE_RX = 3,
|
||||
CMD_ENABLE_TX = 4,
|
||||
CMD_DISABLE_RX = 5,
|
||||
CMD_DISABLE_TX = 6,
|
||||
CMD_SCAN = 8,
|
||||
CMD_STOP_SCAN = 9,
|
||||
CMD_SET_KEYS = 12,
|
||||
CMD_READ_MEMORY = 13,
|
||||
CMD_WRITE_MEMORY = 14,
|
||||
CMD_SET_TEMPLATE = 19,
|
||||
CMD_TEST = 23,
|
||||
CMD_NOISE_HIST = 28,
|
||||
CMD_QUIET_ELEMENT_SET_STATE = 29,
|
||||
CMD_SET_BCN_MODE = 33,
|
||||
CMD_MEASUREMENT = 34,
|
||||
CMD_STOP_MEASUREMENT = 35,
|
||||
CMD_SET_PS_MODE = 37,
|
||||
CMD_CHANNEL_SWITCH = 38,
|
||||
CMD_STOP_CHANNEL_SWICTH = 39,
|
||||
CMD_AP_DISCOVERY = 40,
|
||||
CMD_STOP_AP_DISCOVERY = 41,
|
||||
CMD_HEALTH_CHECK = 45,
|
||||
CMD_DEBUG = 46,
|
||||
CMD_TRIGGER_SCAN_TO = 47,
|
||||
CMD_CONNECTION_SCAN_CFG = 48,
|
||||
CMD_CONNECTION_SCAN_SSID_CFG = 49,
|
||||
CMD_START_PERIODIC_SCAN = 50,
|
||||
CMD_STOP_PERIODIC_SCAN = 51,
|
||||
CMD_SET_PEER_STATE = 52,
|
||||
CMD_REMAIN_ON_CHANNEL = 53,
|
||||
CMD_CANCEL_REMAIN_ON_CHANNEL = 54,
|
||||
CMD_INTERROGATE = 1, /* use this to read information elements */
|
||||
CMD_CONFIGURE = 2, /* use this to write information elements */
|
||||
CMD_ENABLE_RX = 3,
|
||||
CMD_ENABLE_TX = 4,
|
||||
CMD_DISABLE_RX = 5,
|
||||
CMD_DISABLE_TX = 6,
|
||||
CMD_SCAN = 7,
|
||||
CMD_STOP_SCAN = 8,
|
||||
CMD_SET_KEYS = 9,
|
||||
CMD_READ_MEMORY = 10,
|
||||
CMD_WRITE_MEMORY = 11,
|
||||
CMD_SET_TEMPLATE = 12,
|
||||
CMD_TEST = 13,
|
||||
CMD_NOISE_HIST = 14,
|
||||
CMD_QUIET_ELEMENT_SET_STATE = 15,
|
||||
CMD_SET_BCN_MODE = 16,
|
||||
|
||||
CMD_CONFIG_FWLOGGER = 55,
|
||||
CMD_START_FWLOGGER = 56,
|
||||
CMD_STOP_FWLOGGER = 57,
|
||||
CMD_MEASUREMENT = 17,
|
||||
CMD_STOP_MEASUREMENT = 18,
|
||||
CMD_SET_PS_MODE = 19,
|
||||
CMD_CHANNEL_SWITCH = 20,
|
||||
CMD_STOP_CHANNEL_SWICTH = 21,
|
||||
CMD_AP_DISCOVERY = 22,
|
||||
CMD_STOP_AP_DISCOVERY = 23,
|
||||
CMD_HEALTH_CHECK = 24,
|
||||
CMD_DEBUG = 25,
|
||||
CMD_TRIGGER_SCAN_TO = 26,
|
||||
CMD_CONNECTION_SCAN_CFG = 27,
|
||||
CMD_CONNECTION_SCAN_SSID_CFG = 28,
|
||||
CMD_START_PERIODIC_SCAN = 29,
|
||||
CMD_STOP_PERIODIC_SCAN = 30,
|
||||
CMD_SET_PEER_STATE = 31,
|
||||
CMD_REMAIN_ON_CHANNEL = 32,
|
||||
CMD_CANCEL_REMAIN_ON_CHANNEL = 33,
|
||||
CMD_CONFIG_FWLOGGER = 34,
|
||||
CMD_START_FWLOGGER = 35,
|
||||
CMD_STOP_FWLOGGER = 36,
|
||||
|
||||
/* AP commands */
|
||||
CMD_ADD_PEER = 62,
|
||||
CMD_REMOVE_PEER = 63,
|
||||
/* Access point commands */
|
||||
CMD_ADD_PEER = 37,
|
||||
CMD_REMOVE_PEER = 38,
|
||||
|
||||
/* Role API */
|
||||
CMD_ROLE_ENABLE = 70,
|
||||
CMD_ROLE_DISABLE = 71,
|
||||
CMD_ROLE_START = 72,
|
||||
CMD_ROLE_STOP = 73,
|
||||
CMD_ROLE_ENABLE = 39,
|
||||
CMD_ROLE_DISABLE = 40,
|
||||
CMD_ROLE_START = 41,
|
||||
CMD_ROLE_STOP = 42,
|
||||
|
||||
/* DFS */
|
||||
CMD_START_RADAR_DETECTION = 43,
|
||||
CMD_STOP_RADAR_DETECTION = 44,
|
||||
|
||||
/* WIFI Direct */
|
||||
CMD_WFD_START_DISCOVERY = 80,
|
||||
CMD_WFD_STOP_DISCOVERY = 81,
|
||||
CMD_WFD_ATTRIBUTE_CONFIG = 82,
|
||||
CMD_WFD_START_DISCOVERY = 45,
|
||||
CMD_WFD_STOP_DISCOVERY = 46,
|
||||
CMD_WFD_ATTRIBUTE_CONFIG = 47,
|
||||
CMD_NOP = 48,
|
||||
CMD_LAST_COMMAND,
|
||||
|
||||
CMD_NOP = 100,
|
||||
|
||||
NUM_COMMANDS,
|
||||
MAX_COMMAND_ID = 0xFFFF,
|
||||
};
|
||||
|
||||
@ -191,7 +196,7 @@ enum cmd_templ {
|
||||
/* unit ms */
|
||||
#define WL1271_COMMAND_TIMEOUT 2000
|
||||
#define WL1271_CMD_TEMPL_DFLT_SIZE 252
|
||||
#define WL1271_CMD_TEMPL_MAX_SIZE 548
|
||||
#define WL1271_CMD_TEMPL_MAX_SIZE 512
|
||||
#define WL1271_EVENT_TIMEOUT 750
|
||||
|
||||
struct wl1271_cmd_header {
|
||||
@ -339,7 +344,9 @@ struct wl12xx_cmd_role_start {
|
||||
u8 ssid_len;
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
|
||||
u8 padding_1[5];
|
||||
u8 reset_tsf;
|
||||
|
||||
u8 padding_1[4];
|
||||
} __packed ap;
|
||||
};
|
||||
} __packed;
|
||||
@ -364,14 +371,18 @@ struct cmd_enabledisable_path {
|
||||
struct wl1271_cmd_template_set {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
__le16 len;
|
||||
u8 role_id;
|
||||
u8 template_type;
|
||||
__le16 len;
|
||||
u8 index; /* relevant only for KLV_TEMPLATE type */
|
||||
u8 padding[3];
|
||||
|
||||
__le32 enabled_rates;
|
||||
u8 short_retry_limit;
|
||||
u8 long_retry_limit;
|
||||
u8 aflags;
|
||||
u8 reserved;
|
||||
|
||||
u8 template_data[WL1271_CMD_TEMPL_MAX_SIZE];
|
||||
} __packed;
|
||||
|
||||
@ -388,6 +399,7 @@ struct wl1271_tim {
|
||||
} __packed;
|
||||
|
||||
enum wl1271_cmd_ps_mode {
|
||||
STATION_AUTO_PS_MODE, /* Dynamic Power Save */
|
||||
STATION_ACTIVE_MODE,
|
||||
STATION_POWER_SAVE_MODE
|
||||
};
|
||||
@ -397,7 +409,7 @@ struct wl1271_cmd_ps_params {
|
||||
|
||||
u8 role_id;
|
||||
u8 ps_mode; /* STATION_* */
|
||||
u8 padding[2];
|
||||
u16 auto_ps_timeout;
|
||||
} __packed;
|
||||
|
||||
/* HW encryption keys */
|
||||
@ -695,14 +707,18 @@ struct wl12xx_cmd_stop_fwlog {
|
||||
struct wl12xx_cmd_channel_switch {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
u8 role_id;
|
||||
|
||||
/* The new serving channel */
|
||||
u8 channel;
|
||||
/* Relative time of the serving channel switch in TBTT units */
|
||||
u8 switch_time;
|
||||
/* 1: Suspend TX till switch time; 0: Do not suspend TX */
|
||||
u8 tx_suspend;
|
||||
/* 1: Flush TX at switch time; 0: Do not flush */
|
||||
u8 flush;
|
||||
/* Stop the role TX, should expect it after radar detection */
|
||||
u8 stop_tx;
|
||||
/* The target channel tx status 1-stopped 0-open*/
|
||||
u8 post_switch_tx_disable;
|
||||
|
||||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
struct wl12xx_cmd_stop_channel_switch {
|
||||
|
@ -66,7 +66,8 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
CONF_HW_RXTX_RATE_MCS7 = 0,
|
||||
CONF_HW_RXTX_RATE_MCS7_SGI = 0,
|
||||
CONF_HW_RXTX_RATE_MCS7,
|
||||
CONF_HW_RXTX_RATE_MCS6,
|
||||
CONF_HW_RXTX_RATE_MCS5,
|
||||
CONF_HW_RXTX_RATE_MCS4,
|
||||
@ -91,6 +92,10 @@ enum {
|
||||
CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff
|
||||
};
|
||||
|
||||
/* Rates between and including these are MCS rates */
|
||||
#define CONF_HW_RXTX_RATE_MCS_MIN CONF_HW_RXTX_RATE_MCS7_SGI
|
||||
#define CONF_HW_RXTX_RATE_MCS_MAX CONF_HW_RXTX_RATE_MCS0
|
||||
|
||||
enum {
|
||||
CONF_SG_DISABLE = 0,
|
||||
CONF_SG_PROTECTIVE,
|
||||
@ -312,6 +317,10 @@ enum {
|
||||
CONF_AP_BT_ACL_VAL_BT_SERVE_TIME,
|
||||
CONF_AP_BT_ACL_VAL_WL_SERVE_TIME,
|
||||
|
||||
/* CTS Diluting params */
|
||||
CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH,
|
||||
CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER,
|
||||
|
||||
CONF_SG_TEMP_PARAM_1,
|
||||
CONF_SG_TEMP_PARAM_2,
|
||||
CONF_SG_TEMP_PARAM_3,
|
||||
@ -809,6 +818,19 @@ struct conf_conn_settings {
|
||||
*/
|
||||
u8 listen_interval;
|
||||
|
||||
/*
|
||||
* Firmware wakeup conditions during suspend
|
||||
* Range: CONF_WAKE_UP_EVENT_*
|
||||
*/
|
||||
u8 suspend_wake_up_event;
|
||||
|
||||
/*
|
||||
* Listen interval during suspend.
|
||||
* Currently will be in DTIMs (1-10)
|
||||
*
|
||||
*/
|
||||
u8 suspend_listen_interval;
|
||||
|
||||
/*
|
||||
* Enable or disable the beacon filtering.
|
||||
*
|
||||
@ -867,13 +889,6 @@ struct conf_conn_settings {
|
||||
*/
|
||||
u8 ps_poll_threshold;
|
||||
|
||||
/*
|
||||
* PS Poll failure recovery ACTIVE period length
|
||||
*
|
||||
* Range: u32 (ms)
|
||||
*/
|
||||
u32 ps_poll_recovery_period;
|
||||
|
||||
/*
|
||||
* Configuration of signal average weights.
|
||||
*/
|
||||
@ -921,6 +936,18 @@ struct conf_conn_settings {
|
||||
*/
|
||||
u8 psm_entry_nullfunc_retries;
|
||||
|
||||
/*
|
||||
* Specifies the dynamic PS timeout in ms that will be used
|
||||
* by the FW when in AUTO_PS mode
|
||||
*/
|
||||
u16 dynamic_ps_timeout;
|
||||
|
||||
/*
|
||||
* Specifies whether dynamic PS should be disabled and PSM forced.
|
||||
* This is required for certain WiFi certification tests.
|
||||
*/
|
||||
u8 forced_ps;
|
||||
|
||||
/*
|
||||
*
|
||||
* Specifies the interval of the connection keep-alive null-func
|
||||
@ -1055,6 +1082,14 @@ struct conf_scan_settings {
|
||||
*/
|
||||
u16 num_probe_reqs;
|
||||
|
||||
/*
|
||||
* Scan trigger (split scan) timeout. The FW will split the scan
|
||||
* operation into slices of the given time and allow the FW to schedule
|
||||
* other tasks in between.
|
||||
*
|
||||
* Range: u32 Microsecs
|
||||
*/
|
||||
u32 split_scan_timeout;
|
||||
};
|
||||
|
||||
struct conf_sched_scan_settings {
|
||||
|
@ -51,6 +51,7 @@ enum {
|
||||
DEBUG_FILTERS = BIT(15),
|
||||
DEBUG_ADHOC = BIT(16),
|
||||
DEBUG_AP = BIT(17),
|
||||
DEBUG_PROBE = BIT(18),
|
||||
DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP),
|
||||
DEBUG_ALL = ~0,
|
||||
};
|
||||
|
@ -113,7 +113,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (wl->state == WL1271_STATE_ON &&
|
||||
if (wl->state == WL1271_STATE_ON && !wl->plt &&
|
||||
time_after(jiffies, wl->stats.fw_stats_update +
|
||||
msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
|
||||
wl1271_acx_statistics(wl, wl->stats.fw_stats);
|
||||
@ -312,6 +312,181 @@ static const struct file_operations start_recovery_ops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t dynamic_ps_timeout_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
|
||||
return wl1271_format_buffer(user_buf, count,
|
||||
ppos, "%d\n",
|
||||
wl->conf.conn.dynamic_ps_timeout);
|
||||
}
|
||||
|
||||
static ssize_t dynamic_ps_timeout_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
struct wl12xx_vif *wlvif;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
ret = kstrtoul_from_user(user_buf, count, 10, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value in dynamic_ps");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (value < 1 || value > 65535) {
|
||||
wl1271_warning("dyanmic_ps_timeout is not in valid range");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
wl->conf.conn.dynamic_ps_timeout = value;
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* In case we're already in PSM, trigger it again to set new timeout
|
||||
* immediately without waiting for re-association
|
||||
*/
|
||||
|
||||
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||
if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags))
|
||||
wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE);
|
||||
}
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations dynamic_ps_timeout_ops = {
|
||||
.read = dynamic_ps_timeout_read,
|
||||
.write = dynamic_ps_timeout_write,
|
||||
.open = wl1271_open_file_generic,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t forced_ps_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
|
||||
return wl1271_format_buffer(user_buf, count,
|
||||
ppos, "%d\n",
|
||||
wl->conf.conn.forced_ps);
|
||||
}
|
||||
|
||||
static ssize_t forced_ps_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
struct wl12xx_vif *wlvif;
|
||||
unsigned long value;
|
||||
int ret, ps_mode;
|
||||
|
||||
ret = kstrtoul_from_user(user_buf, count, 10, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value in forced_ps");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (value != 1 && value != 0) {
|
||||
wl1271_warning("forced_ps should be either 0 or 1");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->conf.conn.forced_ps == value)
|
||||
goto out;
|
||||
|
||||
wl->conf.conn.forced_ps = value;
|
||||
|
||||
if (wl->state == WL1271_STATE_OFF)
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* In case we're already in PSM, trigger it again to switch mode
|
||||
* immediately without waiting for re-association
|
||||
*/
|
||||
|
||||
ps_mode = value ? STATION_POWER_SAVE_MODE : STATION_AUTO_PS_MODE;
|
||||
|
||||
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||
if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags))
|
||||
wl1271_ps_set_mode(wl, wlvif, ps_mode);
|
||||
}
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations forced_ps_ops = {
|
||||
.read = forced_ps_read,
|
||||
.write = forced_ps_write,
|
||||
.open = wl1271_open_file_generic,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t split_scan_timeout_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
|
||||
return wl1271_format_buffer(user_buf, count,
|
||||
ppos, "%d\n",
|
||||
wl->conf.scan.split_scan_timeout / 1000);
|
||||
}
|
||||
|
||||
static ssize_t split_scan_timeout_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
ret = kstrtoul_from_user(user_buf, count, 10, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value in split_scan_timeout");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (value == 0)
|
||||
wl1271_info("split scan will be disabled");
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
wl->conf.scan.split_scan_timeout = value * 1000;
|
||||
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations split_scan_timeout_ops = {
|
||||
.read = split_scan_timeout_read,
|
||||
.write = split_scan_timeout_write,
|
||||
.open = wl1271_open_file_generic,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t driver_state_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -446,6 +621,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
|
||||
VIF_STATE_PRINT_INT(sta.basic_rate_idx);
|
||||
VIF_STATE_PRINT_INT(sta.ap_rate_idx);
|
||||
VIF_STATE_PRINT_INT(sta.p2p_rate_idx);
|
||||
VIF_STATE_PRINT_INT(sta.qos);
|
||||
} else {
|
||||
VIF_STATE_PRINT_INT(ap.global_hlid);
|
||||
VIF_STATE_PRINT_INT(ap.bcast_hlid);
|
||||
@ -471,7 +647,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
|
||||
VIF_STATE_PRINT_INT(default_key);
|
||||
VIF_STATE_PRINT_INT(aid);
|
||||
VIF_STATE_PRINT_INT(session_counter);
|
||||
VIF_STATE_PRINT_INT(ps_poll_failures);
|
||||
VIF_STATE_PRINT_INT(psm_entry_retry);
|
||||
VIF_STATE_PRINT_INT(power_level);
|
||||
VIF_STATE_PRINT_INT(rssi_thold);
|
||||
@ -562,6 +737,64 @@ static const struct file_operations dtim_interval_ops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static ssize_t suspend_dtim_interval_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
u8 value;
|
||||
|
||||
if (wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_DTIM ||
|
||||
wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM)
|
||||
value = wl->conf.conn.suspend_listen_interval;
|
||||
else
|
||||
value = 0;
|
||||
|
||||
return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value);
|
||||
}
|
||||
|
||||
static ssize_t suspend_dtim_interval_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct wl1271 *wl = file->private_data;
|
||||
unsigned long value;
|
||||
int ret;
|
||||
|
||||
ret = kstrtoul_from_user(user_buf, count, 10, &value);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("illegal value for suspend_dtim_interval");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (value < 1 || value > 10) {
|
||||
wl1271_warning("suspend_dtim value is not in valid range");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
wl->conf.conn.suspend_listen_interval = value;
|
||||
/* for some reason there are different event types for 1 and >1 */
|
||||
if (value == 1)
|
||||
wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_DTIM;
|
||||
else
|
||||
wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM;
|
||||
|
||||
mutex_unlock(&wl->mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations suspend_dtim_interval_ops = {
|
||||
.read = suspend_dtim_interval_read,
|
||||
.write = suspend_dtim_interval_write,
|
||||
.open = wl1271_open_file_generic,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t beacon_interval_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -886,8 +1119,12 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
|
||||
DEBUGFS_ADD(driver_state, rootdir);
|
||||
DEBUGFS_ADD(vifs_state, rootdir);
|
||||
DEBUGFS_ADD(dtim_interval, rootdir);
|
||||
DEBUGFS_ADD(suspend_dtim_interval, rootdir);
|
||||
DEBUGFS_ADD(beacon_interval, rootdir);
|
||||
DEBUGFS_ADD(beacon_filtering, rootdir);
|
||||
DEBUGFS_ADD(dynamic_ps_timeout, rootdir);
|
||||
DEBUGFS_ADD(forced_ps, rootdir);
|
||||
DEBUGFS_ADD(split_scan_timeout, rootdir);
|
||||
|
||||
streaming = debugfs_create_dir("rx_streaming", rootdir);
|
||||
if (!streaming || IS_ERR(streaming))
|
||||
|
@ -30,133 +30,6 @@
|
||||
#include "scan.h"
|
||||
#include "wl12xx_80211.h"
|
||||
|
||||
void wl1271_pspoll_work(struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
struct wl12xx_vif *wlvif;
|
||||
struct delayed_work *dwork;
|
||||
struct wl1271 *wl;
|
||||
int ret;
|
||||
|
||||
dwork = container_of(work, struct delayed_work, work);
|
||||
wlvif = container_of(dwork, struct wl12xx_vif, pspoll_work);
|
||||
vif = container_of((void *)wlvif, struct ieee80211_vif, drv_priv);
|
||||
wl = wlvif->wl;
|
||||
|
||||
wl1271_debug(DEBUG_EVENT, "pspoll work");
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
goto out;
|
||||
|
||||
if (!test_and_clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags))
|
||||
goto out;
|
||||
|
||||
if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* if we end up here, then we were in powersave when the pspoll
|
||||
* delivery failure occurred, and no-one changed state since, so
|
||||
* we should go back to powersave.
|
||||
*/
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE,
|
||||
wlvif->basic_rate, true);
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
};
|
||||
|
||||
static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif)
|
||||
{
|
||||
int delay = wl->conf.conn.ps_poll_recovery_period;
|
||||
int ret;
|
||||
|
||||
wlvif->ps_poll_failures++;
|
||||
if (wlvif->ps_poll_failures == 1)
|
||||
wl1271_info("AP with dysfunctional ps-poll, "
|
||||
"trying to work around it.");
|
||||
|
||||
/* force active mode receive data from the AP */
|
||||
if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
|
||||
ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE,
|
||||
wlvif->basic_rate, true);
|
||||
if (ret < 0)
|
||||
return;
|
||||
set_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags);
|
||||
ieee80211_queue_delayed_work(wl->hw, &wlvif->pspoll_work,
|
||||
msecs_to_jiffies(delay));
|
||||
}
|
||||
|
||||
/*
|
||||
* If already in active mode, lets we should be getting data from
|
||||
* the AP right away. If we enter PSM too fast after this, and data
|
||||
* remains on the AP, we will get another event like this, and we'll
|
||||
* go into active once more.
|
||||
*/
|
||||
}
|
||||
|
||||
static int wl1271_event_ps_report(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct event_mailbox *mbox,
|
||||
bool *beacon_loss)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 total_retries = wl->conf.conn.psm_entry_retries;
|
||||
|
||||
wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);
|
||||
|
||||
switch (mbox->ps_status) {
|
||||
case EVENT_ENTER_POWER_SAVE_FAIL:
|
||||
wl1271_debug(DEBUG_PSM, "PSM entry failed");
|
||||
|
||||
if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) {
|
||||
/* remain in active mode */
|
||||
wlvif->psm_entry_retry = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wlvif->psm_entry_retry < total_retries) {
|
||||
wlvif->psm_entry_retry++;
|
||||
ret = wl1271_ps_set_mode(wl, wlvif,
|
||||
STATION_POWER_SAVE_MODE,
|
||||
wlvif->basic_rate, true);
|
||||
} else {
|
||||
wl1271_info("No ack to nullfunc from AP.");
|
||||
wlvif->psm_entry_retry = 0;
|
||||
*beacon_loss = true;
|
||||
}
|
||||
break;
|
||||
case EVENT_ENTER_POWER_SAVE_SUCCESS:
|
||||
wlvif->psm_entry_retry = 0;
|
||||
|
||||
/*
|
||||
* BET has only a minor effect in 5GHz and masks
|
||||
* channel switch IEs, so we only enable BET on 2.4GHz
|
||||
*/
|
||||
if (wlvif->band == IEEE80211_BAND_2GHZ)
|
||||
/* enable beacon early termination */
|
||||
ret = wl1271_acx_bet_enable(wl, wlvif, true);
|
||||
|
||||
if (wlvif->ps_compl) {
|
||||
complete(wlvif->ps_compl);
|
||||
wlvif->ps_compl = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wl1271_event_rssi_trigger(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct event_mailbox *mbox)
|
||||
@ -205,21 +78,13 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
|
||||
u8 enable)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
struct wl12xx_vif *wlvif;
|
||||
|
||||
if (enable) {
|
||||
/* disable dynamic PS when requested by the firmware */
|
||||
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||
vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
ieee80211_disable_dyn_ps(vif);
|
||||
}
|
||||
set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
|
||||
} else {
|
||||
clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
|
||||
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||
vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
ieee80211_enable_dyn_ps(vif);
|
||||
wl1271_recalc_rx_streaming(wl, wlvif);
|
||||
}
|
||||
}
|
||||
@ -237,7 +102,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
||||
{
|
||||
struct ieee80211_vif *vif;
|
||||
struct wl12xx_vif *wlvif;
|
||||
int ret;
|
||||
u32 vector;
|
||||
bool beacon_loss = false;
|
||||
bool disconnect_sta = false;
|
||||
@ -293,21 +157,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
||||
beacon_loss = true;
|
||||
}
|
||||
|
||||
if (vector & PS_REPORT_EVENT_ID) {
|
||||
wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
|
||||
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||
ret = wl1271_event_ps_report(wl, wlvif,
|
||||
mbox, &beacon_loss);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID)
|
||||
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||
wl1271_event_pspoll_delivery_fail(wl, wlvif);
|
||||
}
|
||||
|
||||
if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
|
||||
/* TODO: check actual multi-role support */
|
||||
wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT");
|
||||
@ -344,7 +193,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
||||
|
||||
/* TODO: configure only the relevant vif */
|
||||
wl12xx_for_each_wlvif_sta(wl, wlvif) {
|
||||
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
bool success;
|
||||
|
||||
if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS,
|
||||
@ -352,6 +200,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
|
||||
continue;
|
||||
|
||||
success = mbox->channel_switch_status ? false : true;
|
||||
vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
|
||||
ieee80211_chswitch_done(vif, success);
|
||||
}
|
||||
}
|
||||
|
@ -51,10 +51,10 @@ enum {
|
||||
SCAN_COMPLETE_EVENT_ID = BIT(10),
|
||||
WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11),
|
||||
AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12),
|
||||
PS_REPORT_EVENT_ID = BIT(13),
|
||||
RESERVED1 = BIT(13),
|
||||
PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14),
|
||||
DISCONNECT_EVENT_COMPLETE_ID = BIT(15),
|
||||
/* BIT(16) is reserved */
|
||||
ROLE_STOP_COMPLETE_EVENT_ID = BIT(15),
|
||||
RADAR_DETECTED_EVENT_ID = BIT(16),
|
||||
CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
|
||||
BSS_LOSE_EVENT_ID = BIT(18),
|
||||
REGAINED_BSS_EVENT_ID = BIT(19),
|
||||
@ -94,9 +94,9 @@ struct event_mailbox {
|
||||
u8 soft_gemini_sense_info;
|
||||
u8 soft_gemini_protective_info;
|
||||
s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
|
||||
u8 channel_switch_status;
|
||||
u8 change_auto_mode_timeout;
|
||||
u8 scheduled_scan_status;
|
||||
u8 ps_status;
|
||||
u8 reserved4;
|
||||
/* tuned channel (roc) */
|
||||
u8 roc_channel;
|
||||
|
||||
@ -119,17 +119,21 @@ struct event_mailbox {
|
||||
u8 rx_ba_allowed;
|
||||
u8 reserved_6[2];
|
||||
|
||||
/* Channel switch results */
|
||||
|
||||
u8 channel_switch_role_id;
|
||||
u8 channel_switch_status;
|
||||
u8 reserved_7[2];
|
||||
|
||||
u8 ps_poll_delivery_failure_role_ids;
|
||||
u8 stopped_role_ids;
|
||||
u8 started_role_ids;
|
||||
u8 change_auto_mode_timeout;
|
||||
|
||||
u8 reserved_7[12];
|
||||
u8 reserved_8[9];
|
||||
} __packed;
|
||||
|
||||
int wl1271_event_unmask(struct wl1271 *wl);
|
||||
void wl1271_event_mbox_config(struct wl1271 *wl);
|
||||
int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
|
||||
void wl1271_pspoll_work(struct work_struct *work);
|
||||
|
||||
#endif
|
||||
|
@ -37,54 +37,64 @@
|
||||
int wl1271_init_templates_config(struct wl1271 *wl)
|
||||
{
|
||||
int ret, i;
|
||||
size_t max_size;
|
||||
|
||||
/* send empty templates for fw memory reservation */
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
|
||||
WL1271_CMD_TEMPL_DFLT_SIZE,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
|
||||
WL1271_CMD_TEMPL_MAX_SIZE,
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0,
|
||||
WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_NULL_DATA, NULL,
|
||||
sizeof(struct wl12xx_null_data_template),
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_PS_POLL, NULL,
|
||||
sizeof(struct wl12xx_ps_poll_template),
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_QOS_NULL_DATA, NULL,
|
||||
sizeof
|
||||
(struct ieee80211_qos_hdr),
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_PROBE_RESPONSE, NULL,
|
||||
WL1271_CMD_TEMPL_DFLT_SIZE,
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_BEACON, NULL,
|
||||
WL1271_CMD_TEMPL_DFLT_SIZE,
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL,
|
||||
sizeof
|
||||
(struct wl12xx_arp_rsp_template),
|
||||
max_size = sizeof(struct wl12xx_arp_rsp_template) +
|
||||
WL1271_EXTRA_SPACE_MAX;
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_ARP_RSP, NULL,
|
||||
max_size,
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -93,19 +103,22 @@ int wl1271_init_templates_config(struct wl1271 *wl)
|
||||
* Put very large empty placeholders for all templates. These
|
||||
* reserve memory for later.
|
||||
*/
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
|
||||
WL1271_CMD_TEMPL_MAX_SIZE,
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_AP_BEACON, NULL,
|
||||
WL1271_CMD_TEMPL_MAX_SIZE,
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_DEAUTH_AP, NULL,
|
||||
sizeof
|
||||
(struct wl12xx_disconn_template),
|
||||
0, WL1271_RATE_AUTOMATIC);
|
||||
@ -113,7 +126,8 @@ int wl1271_init_templates_config(struct wl1271 *wl)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
|
||||
ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID,
|
||||
CMD_TEMPL_KLV, NULL,
|
||||
sizeof(struct ieee80211_qos_hdr),
|
||||
i, WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
@ -140,7 +154,8 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl,
|
||||
IEEE80211_STYPE_DEAUTH);
|
||||
|
||||
rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id,
|
||||
CMD_TEMPL_DEAUTH_AP,
|
||||
tmpl, sizeof(*tmpl), 0, rate);
|
||||
|
||||
out:
|
||||
@ -172,7 +187,8 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl,
|
||||
memcpy(nullfunc->addr3, vif->addr, ETH_ALEN);
|
||||
|
||||
rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id,
|
||||
CMD_TEMPL_NULL_DATA, nullfunc,
|
||||
sizeof(*nullfunc), 0, rate);
|
||||
|
||||
out:
|
||||
@ -204,7 +220,8 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl,
|
||||
memcpy(qosnull->addr3, vif->addr, ETH_ALEN);
|
||||
|
||||
rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set);
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
|
||||
ret = wl1271_cmd_template_set(wl, wlvif->role_id,
|
||||
CMD_TEMPL_QOS_NULL_DATA, qosnull,
|
||||
sizeof(*qosnull), 0, rate);
|
||||
|
||||
out:
|
||||
|
@ -45,6 +45,65 @@
|
||||
#define OCP_STATUS_REQ_FAILED 0x20000
|
||||
#define OCP_STATUS_RESP_ERROR 0x30000
|
||||
|
||||
struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN] = {
|
||||
[PART_DOWN] = {
|
||||
.mem = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x000177c0
|
||||
},
|
||||
.reg = {
|
||||
.start = REGISTERS_BASE,
|
||||
.size = 0x00008800
|
||||
},
|
||||
.mem2 = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x00000000
|
||||
},
|
||||
.mem3 = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x00000000
|
||||
},
|
||||
},
|
||||
|
||||
[PART_WORK] = {
|
||||
.mem = {
|
||||
.start = 0x00040000,
|
||||
.size = 0x00014fc0
|
||||
},
|
||||
.reg = {
|
||||
.start = REGISTERS_BASE,
|
||||
.size = 0x0000a000
|
||||
},
|
||||
.mem2 = {
|
||||
.start = 0x003004f8,
|
||||
.size = 0x00000004
|
||||
},
|
||||
.mem3 = {
|
||||
.start = 0x00040404,
|
||||
.size = 0x00000000
|
||||
},
|
||||
},
|
||||
|
||||
[PART_DRPW] = {
|
||||
.mem = {
|
||||
.start = 0x00040000,
|
||||
.size = 0x00014fc0
|
||||
},
|
||||
.reg = {
|
||||
.start = DRPW_BASE,
|
||||
.size = 0x00006000
|
||||
},
|
||||
.mem2 = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x00000000
|
||||
},
|
||||
.mem3 = {
|
||||
.start = 0x00000000,
|
||||
.size = 0x00000000
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool wl1271_set_block_size(struct wl1271 *wl)
|
||||
{
|
||||
if (wl->if_ops->set_block_size) {
|
||||
|
@ -43,6 +43,8 @@
|
||||
|
||||
#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
|
||||
|
||||
extern struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN];
|
||||
|
||||
struct wl1271;
|
||||
|
||||
void wl1271_disable_interrupts(struct wl1271 *wl);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,7 +56,7 @@ void wl1271_elp_work(struct work_struct *work)
|
||||
if (wlvif->bss_type == BSS_TYPE_AP_BSS)
|
||||
goto out;
|
||||
|
||||
if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
|
||||
if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) &&
|
||||
test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
|
||||
goto out;
|
||||
}
|
||||
@ -84,7 +84,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
|
||||
if (wlvif->bss_type == BSS_TYPE_AP_BSS)
|
||||
return;
|
||||
|
||||
if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) &&
|
||||
if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) &&
|
||||
test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
|
||||
return;
|
||||
}
|
||||
@ -160,28 +160,39 @@ out:
|
||||
}
|
||||
|
||||
int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
enum wl1271_cmd_ps_mode mode, u32 rates, bool send)
|
||||
enum wl1271_cmd_ps_mode mode)
|
||||
{
|
||||
int ret;
|
||||
u16 timeout = wl->conf.conn.dynamic_ps_timeout;
|
||||
|
||||
switch (mode) {
|
||||
case STATION_AUTO_PS_MODE:
|
||||
case STATION_POWER_SAVE_MODE:
|
||||
wl1271_debug(DEBUG_PSM, "entering psm");
|
||||
wl1271_debug(DEBUG_PSM, "entering psm (mode=%d,timeout=%u)",
|
||||
mode, timeout);
|
||||
|
||||
ret = wl1271_acx_wake_up_conditions(wl, wlvif);
|
||||
ret = wl1271_acx_wake_up_conditions(wl, wlvif,
|
||||
wl->conf.conn.wake_up_event,
|
||||
wl->conf.conn.listen_interval);
|
||||
if (ret < 0) {
|
||||
wl1271_error("couldn't set wake up conditions");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_POWER_SAVE_MODE);
|
||||
ret = wl1271_cmd_ps_mode(wl, wlvif, mode, timeout);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
set_bit(WLVIF_FLAG_PSM, &wlvif->flags);
|
||||
set_bit(WLVIF_FLAG_IN_PS, &wlvif->flags);
|
||||
|
||||
/* enable beacon early termination. Not relevant for 5GHz */
|
||||
if (wlvif->band == IEEE80211_BAND_2GHZ) {
|
||||
ret = wl1271_acx_bet_enable(wl, wlvif, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case STATION_ACTIVE_MODE:
|
||||
default:
|
||||
wl1271_debug(DEBUG_PSM, "leaving psm");
|
||||
|
||||
/* disable beacon early termination */
|
||||
@ -191,12 +202,15 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE);
|
||||
ret = wl1271_cmd_ps_mode(wl, wlvif, mode, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
clear_bit(WLVIF_FLAG_PSM, &wlvif->flags);
|
||||
clear_bit(WLVIF_FLAG_IN_PS, &wlvif->flags);
|
||||
break;
|
||||
default:
|
||||
wl1271_warning("trying to set ps to unsupported mode %d", mode);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "acx.h"
|
||||
|
||||
int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
enum wl1271_cmd_ps_mode mode, u32 rates, bool send);
|
||||
enum wl1271_cmd_ps_mode mode);
|
||||
void wl1271_ps_elp_sleep(struct wl1271 *wl);
|
||||
int wl1271_ps_elp_wakeup(struct wl1271 *wl);
|
||||
void wl1271_elp_work(struct work_struct *work);
|
||||
|
@ -525,4 +525,31 @@ b12-b0 - Supported Rate indicator bits as defined below.
|
||||
*/
|
||||
#define INTR_TRIG_TX_PROC1 BIT(18)
|
||||
|
||||
#define WL127X_REG_FUSE_DATA_2_1 0x050a
|
||||
#define WL128X_REG_FUSE_DATA_2_1 0x2152
|
||||
#define PG_VER_MASK 0x3c
|
||||
#define PG_VER_OFFSET 2
|
||||
|
||||
#define WL127X_PG_MAJOR_VER_MASK 0x3
|
||||
#define WL127X_PG_MAJOR_VER_OFFSET 0x0
|
||||
#define WL127X_PG_MINOR_VER_MASK 0xc
|
||||
#define WL127X_PG_MINOR_VER_OFFSET 0x2
|
||||
|
||||
#define WL128X_PG_MAJOR_VER_MASK 0xc
|
||||
#define WL128X_PG_MAJOR_VER_OFFSET 0x2
|
||||
#define WL128X_PG_MINOR_VER_MASK 0x3
|
||||
#define WL128X_PG_MINOR_VER_OFFSET 0x0
|
||||
|
||||
#define WL127X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL127X_PG_MAJOR_VER_MASK) >> \
|
||||
WL127X_PG_MAJOR_VER_OFFSET)
|
||||
#define WL127X_PG_GET_MINOR(pg_ver) ((pg_ver & WL127X_PG_MINOR_VER_MASK) >> \
|
||||
WL127X_PG_MINOR_VER_OFFSET)
|
||||
#define WL128X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL128X_PG_MAJOR_VER_MASK) >> \
|
||||
WL128X_PG_MAJOR_VER_OFFSET)
|
||||
#define WL128X_PG_GET_MINOR(pg_ver) ((pg_ver & WL128X_PG_MINOR_VER_MASK) >> \
|
||||
WL128X_PG_MINOR_VER_OFFSET)
|
||||
|
||||
#define WL12XX_REG_FUSE_BD_ADDR_1 0x00310eb4
|
||||
#define WL12XX_REG_FUSE_BD_ADDR_2 0x00310eb8
|
||||
|
||||
#endif
|
||||
|
@ -113,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
|
||||
* In PLT mode we seem to get frames and mac80211 warns about them,
|
||||
* workaround this by not retrieving them at all.
|
||||
*/
|
||||
if (unlikely(wl->state == WL1271_STATE_PLT))
|
||||
if (unlikely(wl->plt))
|
||||
return -EINVAL;
|
||||
|
||||
/* the data read starts with the descriptor */
|
||||
|
@ -38,7 +38,6 @@ void wl1271_scan_complete_work(struct work_struct *work)
|
||||
struct ieee80211_vif *vif;
|
||||
struct wl12xx_vif *wlvif;
|
||||
int ret;
|
||||
bool is_sta, is_ibss;
|
||||
|
||||
dwork = container_of(work, struct delayed_work, work);
|
||||
wl = container_of(dwork, struct wl1271, scan_complete_work);
|
||||
@ -70,15 +69,6 @@ void wl1271_scan_complete_work(struct work_struct *work)
|
||||
wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq);
|
||||
}
|
||||
|
||||
/* return to ROC if needed */
|
||||
is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS);
|
||||
is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS);
|
||||
if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) ||
|
||||
(is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) &&
|
||||
!test_bit(wlvif->dev_role_id, wl->roc_map)) {
|
||||
/* restore remain on channel */
|
||||
wl12xx_start_dev(wl, wlvif);
|
||||
}
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
if (wl->scan.failed) {
|
||||
@ -182,14 +172,23 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (wl->conf.scan.split_scan_timeout)
|
||||
scan_options |= WL1271_SCAN_OPT_SPLIT_SCAN;
|
||||
|
||||
if (passive)
|
||||
scan_options |= WL1271_SCAN_OPT_PASSIVE;
|
||||
|
||||
if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID)) {
|
||||
if (wlvif->bss_type == BSS_TYPE_AP_BSS ||
|
||||
test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
|
||||
cmd->params.role_id = wlvif->role_id;
|
||||
else
|
||||
cmd->params.role_id = wlvif->dev_role_id;
|
||||
|
||||
if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
cmd->params.role_id = wlvif->role_id;
|
||||
|
||||
cmd->params.scan_options = cpu_to_le16(scan_options);
|
||||
|
||||
cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
|
||||
@ -202,7 +201,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
|
||||
|
||||
cmd->params.tx_rate = cpu_to_le32(basic_rate);
|
||||
cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
|
||||
cmd->params.tid_trigger = 0;
|
||||
cmd->params.tid_trigger = CONF_TX_AC_ANY_TID;
|
||||
cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
|
||||
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
@ -217,16 +216,17 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif,
|
||||
|
||||
memcpy(cmd->addr, vif->addr, ETH_ALEN);
|
||||
|
||||
ret = wl1271_cmd_build_probe_req(wl, wlvif, wl->scan.ssid,
|
||||
wl->scan.ssid_len, wl->scan.req->ie,
|
||||
wl->scan.req->ie_len, band);
|
||||
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
|
||||
cmd->params.role_id, band,
|
||||
wl->scan.ssid, wl->scan.ssid_len,
|
||||
wl->scan.req->ie,
|
||||
wl->scan.req->ie_len);
|
||||
if (ret < 0) {
|
||||
wl1271_error("PROBE request template failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* disable the timeout */
|
||||
trigger->timeout = 0;
|
||||
trigger->timeout = cpu_to_le32(wl->conf.scan.split_scan_timeout);
|
||||
ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
|
||||
sizeof(*trigger), 0);
|
||||
if (ret < 0) {
|
||||
@ -658,11 +658,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
|
||||
}
|
||||
|
||||
if (!force_passive && cfg->active[0]) {
|
||||
ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
|
||||
u8 band = IEEE80211_BAND_2GHZ;
|
||||
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
|
||||
wlvif->dev_role_id, band,
|
||||
req->ssids[0].ssid,
|
||||
req->ssids[0].ssid_len,
|
||||
ies->ie[IEEE80211_BAND_2GHZ],
|
||||
ies->len[IEEE80211_BAND_2GHZ],
|
||||
IEEE80211_BAND_2GHZ);
|
||||
ies->ie[band],
|
||||
ies->len[band]);
|
||||
if (ret < 0) {
|
||||
wl1271_error("2.4GHz PROBE request template failed");
|
||||
goto out;
|
||||
@ -670,11 +672,13 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
|
||||
}
|
||||
|
||||
if (!force_passive && cfg->active[1]) {
|
||||
ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid,
|
||||
u8 band = IEEE80211_BAND_5GHZ;
|
||||
ret = wl12xx_cmd_build_probe_req(wl, wlvif,
|
||||
wlvif->dev_role_id, band,
|
||||
req->ssids[0].ssid,
|
||||
req->ssids[0].ssid_len,
|
||||
ies->ie[IEEE80211_BAND_5GHZ],
|
||||
ies->len[IEEE80211_BAND_5GHZ],
|
||||
IEEE80211_BAND_5GHZ);
|
||||
ies->ie[band],
|
||||
ies->len[band]);
|
||||
if (ret < 0) {
|
||||
wl1271_error("5GHz PROBE request template failed");
|
||||
goto out;
|
||||
|
@ -48,7 +48,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl);
|
||||
#define WL1271_SCAN_CURRENT_TX_PWR 0
|
||||
#define WL1271_SCAN_OPT_ACTIVE 0
|
||||
#define WL1271_SCAN_OPT_PASSIVE 1
|
||||
#define WL1271_SCAN_OPT_TRIGGERED_SCAN 2
|
||||
#define WL1271_SCAN_OPT_SPLIT_SCAN 2
|
||||
#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
|
||||
/* scan even if we fail to enter psm */
|
||||
#define WL1271_SCAN_OPT_FORCE 8
|
||||
|
@ -74,6 +74,8 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
|
||||
struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
|
||||
struct sdio_func *func = dev_to_sdio_func(glue->dev);
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
|
||||
((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
|
||||
dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n",
|
||||
@ -88,6 +90,8 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
|
||||
addr, len);
|
||||
}
|
||||
|
||||
sdio_release_host(func);
|
||||
|
||||
if (ret)
|
||||
dev_err(child->parent, "sdio read failed (%d)\n", ret);
|
||||
}
|
||||
@ -99,6 +103,8 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
|
||||
struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
|
||||
struct sdio_func *func = dev_to_sdio_func(glue->dev);
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
|
||||
sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
|
||||
dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n",
|
||||
@ -113,6 +119,8 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
|
||||
ret = sdio_memcpy_toio(func, addr, buf, len);
|
||||
}
|
||||
|
||||
sdio_release_host(func);
|
||||
|
||||
if (ret)
|
||||
dev_err(child->parent, "sdio write failed (%d)\n", ret);
|
||||
}
|
||||
@ -136,6 +144,7 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
|
||||
|
||||
sdio_claim_host(func);
|
||||
sdio_enable_func(func);
|
||||
sdio_release_host(func);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@ -146,6 +155,7 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
|
||||
int ret;
|
||||
struct sdio_func *func = dev_to_sdio_func(glue->dev);
|
||||
|
||||
sdio_claim_host(func);
|
||||
sdio_disable_func(func);
|
||||
sdio_release_host(func);
|
||||
|
||||
@ -314,9 +324,6 @@ static int wl1271_suspend(struct device *dev)
|
||||
dev_err(dev, "error while trying to keep power\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* release host */
|
||||
sdio_release_host(func);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
@ -324,15 +331,7 @@ out:
|
||||
|
||||
static int wl1271_resume(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
|
||||
struct wl1271 *wl = platform_get_drvdata(glue->core);
|
||||
|
||||
dev_dbg(dev, "wl1271 resume\n");
|
||||
if (wl->wow_enabled) {
|
||||
/* claim back host */
|
||||
sdio_claim_host(func);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -371,5 +370,9 @@ module_exit(wl1271_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
|
||||
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
||||
MODULE_FIRMWARE(WL127X_FW_NAME);
|
||||
MODULE_FIRMWARE(WL128X_FW_NAME);
|
||||
MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
|
||||
MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
|
||||
MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
|
||||
MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
|
||||
MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
|
||||
MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
|
||||
|
@ -433,6 +433,10 @@ module_exit(wl1271_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
|
||||
MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
|
||||
MODULE_FIRMWARE(WL127X_FW_NAME);
|
||||
MODULE_FIRMWARE(WL128X_FW_NAME);
|
||||
MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
|
||||
MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
|
||||
MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
|
||||
MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
|
||||
MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
|
||||
MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
|
||||
MODULE_ALIAS("spi:wl1271");
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "acx.h"
|
||||
#include "reg.h"
|
||||
#include "ps.h"
|
||||
#include "io.h"
|
||||
|
||||
#define WL1271_TM_MAX_DATA_LENGTH 1024
|
||||
|
||||
@ -41,6 +42,7 @@ enum wl1271_tm_commands {
|
||||
WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */
|
||||
WL1271_TM_CMD_SET_PLT_MODE,
|
||||
WL1271_TM_CMD_RECOVER,
|
||||
WL1271_TM_CMD_GET_MAC,
|
||||
|
||||
__WL1271_TM_CMD_AFTER_LAST
|
||||
};
|
||||
@ -264,6 +266,52 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[])
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (!wl->plt) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (wl->fuse_oui_addr == 0 && wl->fuse_nic_addr == 0) {
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mac_addr[0] = (u8)(wl->fuse_oui_addr >> 16);
|
||||
mac_addr[1] = (u8)(wl->fuse_oui_addr >> 8);
|
||||
mac_addr[2] = (u8) wl->fuse_oui_addr;
|
||||
mac_addr[3] = (u8)(wl->fuse_nic_addr >> 16);
|
||||
mac_addr[4] = (u8)(wl->fuse_nic_addr >> 8);
|
||||
mac_addr[5] = (u8) wl->fuse_nic_addr;
|
||||
|
||||
skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, ETH_ALEN);
|
||||
if (!skb) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
NLA_PUT(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr);
|
||||
ret = cfg80211_testmode_reply(skb);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
return ret;
|
||||
|
||||
nla_put_failure:
|
||||
kfree_skb(skb);
|
||||
ret = -EMSGSIZE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
@ -288,6 +336,8 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
return wl1271_tm_cmd_set_plt_mode(wl, tb);
|
||||
case WL1271_TM_CMD_RECOVER:
|
||||
return wl1271_tm_cmd_recover(wl, tb);
|
||||
case WL1271_TM_CMD_GET_MAC:
|
||||
return wl12xx_tm_cmd_get_mac(wl, tb);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -77,35 +77,6 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id)
|
||||
}
|
||||
}
|
||||
|
||||
static int wl1271_tx_update_filters(struct wl1271 *wl,
|
||||
struct wl12xx_vif *wlvif,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr;
|
||||
int ret;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
/*
|
||||
* stop bssid-based filtering before transmitting authentication
|
||||
* requests. this way the hw will never drop authentication
|
||||
* responses coming from BSSIDs it isn't familiar with (e.g. on
|
||||
* roaming)
|
||||
*/
|
||||
if (!ieee80211_is_auth(hdr->frame_control))
|
||||
return 0;
|
||||
|
||||
if (wlvif->dev_hlid != WL12XX_INVALID_LINK_ID)
|
||||
goto out;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "starting device role for roaming");
|
||||
ret = wl12xx_start_dev(wl, wlvif);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@ -187,8 +158,6 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
if (wlvif->bss_type == BSS_TYPE_AP_BSS)
|
||||
return wl12xx_tx_get_hlid_ap(wl, wlvif, skb);
|
||||
|
||||
wl1271_tx_update_filters(wl, wlvif, skb);
|
||||
|
||||
if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) ||
|
||||
test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) &&
|
||||
!ieee80211_is_auth(hdr->frame_control) &&
|
||||
@ -286,16 +255,20 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
int aligned_len, ac, rate_idx;
|
||||
s64 hosttime;
|
||||
u16 tx_attr = 0;
|
||||
__le16 frame_control;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u8 *frame_start;
|
||||
bool is_dummy;
|
||||
|
||||
desc = (struct wl1271_tx_hw_descr *) skb->data;
|
||||
frame_start = (u8 *)(desc + 1);
|
||||
hdr = (struct ieee80211_hdr *)(frame_start + extra);
|
||||
frame_control = hdr->frame_control;
|
||||
|
||||
/* relocate space for security header */
|
||||
if (extra) {
|
||||
void *framestart = skb->data + sizeof(*desc);
|
||||
u16 fc = *(u16 *)(framestart + extra);
|
||||
int hdrlen = ieee80211_hdrlen(cpu_to_le16(fc));
|
||||
memmove(framestart, framestart + extra, hdrlen);
|
||||
int hdrlen = ieee80211_hdrlen(frame_control);
|
||||
memmove(frame_start, hdr, hdrlen);
|
||||
}
|
||||
|
||||
/* configure packet life time */
|
||||
@ -384,6 +357,11 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
desc->wl127x_mem.total_mem_blocks);
|
||||
}
|
||||
|
||||
/* for WEP shared auth - no fw encryption is needed */
|
||||
if (ieee80211_is_auth(frame_control) &&
|
||||
ieee80211_has_protected(frame_control))
|
||||
tx_attr |= TX_HW_ATTR_HOST_ENCRYPT;
|
||||
|
||||
desc->tx_attr = cpu_to_le16(tx_attr);
|
||||
}
|
||||
|
||||
@ -408,7 +386,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
||||
|
||||
if (info->control.hw_key &&
|
||||
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP)
|
||||
extra = WL1271_TKIP_IV_SPACE;
|
||||
extra = WL1271_EXTRA_SPACE_TKIP;
|
||||
|
||||
if (info->control.hw_key) {
|
||||
bool is_wep;
|
||||
@ -795,6 +773,18 @@ out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static u8 wl1271_tx_get_rate_flags(u8 rate_class_index)
|
||||
{
|
||||
u8 flags = 0;
|
||||
|
||||
if (rate_class_index >= CONF_HW_RXTX_RATE_MCS_MIN &&
|
||||
rate_class_index <= CONF_HW_RXTX_RATE_MCS_MAX)
|
||||
flags |= IEEE80211_TX_RC_MCS;
|
||||
if (rate_class_index == CONF_HW_RXTX_RATE_MCS7_SGI)
|
||||
flags |= IEEE80211_TX_RC_SHORT_GI;
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void wl1271_tx_complete_packet(struct wl1271 *wl,
|
||||
struct wl1271_tx_hw_res_descr *result)
|
||||
{
|
||||
@ -804,6 +794,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
|
||||
struct sk_buff *skb;
|
||||
int id = result->id;
|
||||
int rate = -1;
|
||||
u8 rate_flags = 0;
|
||||
u8 retries = 0;
|
||||
|
||||
/* check for id legality */
|
||||
@ -830,6 +821,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
rate = wl1271_rate_to_idx(result->rate_class_index,
|
||||
wlvif->band);
|
||||
rate_flags = wl1271_tx_get_rate_flags(result->rate_class_index);
|
||||
retries = result->ack_failures;
|
||||
} else if (result->status == TX_RETRY_EXCEEDED) {
|
||||
wl->stats.excessive_retries++;
|
||||
@ -838,7 +830,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
|
||||
|
||||
info->status.rates[0].idx = rate;
|
||||
info->status.rates[0].count = retries;
|
||||
info->status.rates[0].flags = 0;
|
||||
info->status.rates[0].flags = rate_flags;
|
||||
info->status.ack_signal = -1;
|
||||
|
||||
wl->stats.retry_count += result->ack_failures;
|
||||
@ -869,8 +861,9 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
|
||||
if (info->control.hw_key &&
|
||||
info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
|
||||
int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen);
|
||||
skb_pull(skb, WL1271_TKIP_IV_SPACE);
|
||||
memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data,
|
||||
hdrlen);
|
||||
skb_pull(skb, WL1271_EXTRA_SPACE_TKIP);
|
||||
}
|
||||
|
||||
wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x"
|
||||
@ -1012,9 +1005,9 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
|
||||
info->control.hw_key->cipher ==
|
||||
WLAN_CIPHER_SUITE_TKIP) {
|
||||
int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
memmove(skb->data + WL1271_TKIP_IV_SPACE,
|
||||
memmove(skb->data + WL1271_EXTRA_SPACE_TKIP,
|
||||
skb->data, hdrlen);
|
||||
skb_pull(skb, WL1271_TKIP_IV_SPACE);
|
||||
skb_pull(skb, WL1271_EXTRA_SPACE_TKIP);
|
||||
}
|
||||
|
||||
info->status.rates[0].idx = -1;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11))
|
||||
#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12)
|
||||
#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13)
|
||||
#define TX_HW_ATTR_HOST_ENCRYPT BIT(14)
|
||||
|
||||
#define TX_HW_ATTR_OFST_SAVE_RETRIES 0
|
||||
#define TX_HW_ATTR_OFST_HEADER_PAD 1
|
||||
@ -51,7 +52,9 @@
|
||||
#define TX_HW_RESULT_QUEUE_LEN_MASK 0xf
|
||||
|
||||
#define WL1271_TX_ALIGN_TO 4
|
||||
#define WL1271_TKIP_IV_SPACE 4
|
||||
#define WL1271_EXTRA_SPACE_TKIP 4
|
||||
#define WL1271_EXTRA_SPACE_AES 8
|
||||
#define WL1271_EXTRA_SPACE_MAX 8
|
||||
|
||||
/* Used for management frames and dummy packets */
|
||||
#define WL1271_TID_MGMT 7
|
||||
|
@ -35,8 +35,14 @@
|
||||
#include "conf.h"
|
||||
#include "ini.h"
|
||||
|
||||
#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
|
||||
#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
|
||||
#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin"
|
||||
#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin"
|
||||
|
||||
#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin"
|
||||
#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
|
||||
|
||||
#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin"
|
||||
#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
|
||||
|
||||
/*
|
||||
* wl127x and wl128x are using the same NVS file name. However, the
|
||||
@ -90,7 +96,13 @@
|
||||
enum wl1271_state {
|
||||
WL1271_STATE_OFF,
|
||||
WL1271_STATE_ON,
|
||||
WL1271_STATE_PLT,
|
||||
};
|
||||
|
||||
enum wl12xx_fw_type {
|
||||
WL12XX_FW_TYPE_NONE,
|
||||
WL12XX_FW_TYPE_NORMAL,
|
||||
WL12XX_FW_TYPE_MULTI,
|
||||
WL12XX_FW_TYPE_PLT,
|
||||
};
|
||||
|
||||
enum wl1271_partition_type {
|
||||
@ -247,6 +259,7 @@ enum wl12xx_flags {
|
||||
WL1271_FLAG_PENDING_WORK,
|
||||
WL1271_FLAG_SOFT_GEMINI,
|
||||
WL1271_FLAG_RECOVERY_IN_PROGRESS,
|
||||
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum wl12xx_vif_flags {
|
||||
@ -254,8 +267,7 @@ enum wl12xx_vif_flags {
|
||||
WLVIF_FLAG_STA_ASSOCIATED,
|
||||
WLVIF_FLAG_IBSS_JOINED,
|
||||
WLVIF_FLAG_AP_STARTED,
|
||||
WLVIF_FLAG_PSM,
|
||||
WLVIF_FLAG_PSM_REQUESTED,
|
||||
WLVIF_FLAG_IN_PS,
|
||||
WLVIF_FLAG_STA_STATE_SENT,
|
||||
WLVIF_FLAG_RX_STREAMING_STARTED,
|
||||
WLVIF_FLAG_PSPOLL_FAILURE,
|
||||
@ -295,6 +307,9 @@ struct wl1271 {
|
||||
spinlock_t wl_lock;
|
||||
|
||||
enum wl1271_state state;
|
||||
enum wl12xx_fw_type fw_type;
|
||||
bool plt;
|
||||
u8 last_vif_count;
|
||||
struct mutex mutex;
|
||||
|
||||
unsigned long flags;
|
||||
@ -313,7 +328,12 @@ struct wl1271 {
|
||||
|
||||
s8 hw_pg_ver;
|
||||
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
/* address read from the fuse ROM */
|
||||
u32 fuse_oui_addr;
|
||||
u32 fuse_nic_addr;
|
||||
|
||||
/* we have up to 2 MAC addresses */
|
||||
struct mac_address addresses[2];
|
||||
int channel;
|
||||
u8 system_hlid;
|
||||
|
||||
@ -425,8 +445,6 @@ struct wl1271 {
|
||||
struct wl12xx_fw_status *fw_status;
|
||||
struct wl1271_tx_hw_res_if *tx_res_if;
|
||||
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
/* Current chipset configuration */
|
||||
struct conf_drv_settings conf;
|
||||
|
||||
@ -503,6 +521,8 @@ struct wl12xx_vif {
|
||||
u8 basic_rate_idx;
|
||||
u8 ap_rate_idx;
|
||||
u8 p2p_rate_idx;
|
||||
|
||||
bool qos;
|
||||
} sta;
|
||||
struct {
|
||||
u8 global_hlid;
|
||||
@ -560,12 +580,6 @@ struct wl12xx_vif {
|
||||
/* Session counter for the chipset */
|
||||
int session_counter;
|
||||
|
||||
struct completion *ps_compl;
|
||||
struct delayed_work pspoll_work;
|
||||
|
||||
/* counter for ps-poll delivery failures */
|
||||
int ps_poll_failures;
|
||||
|
||||
/* retry counter for PSM entries */
|
||||
u8 psm_entry_retry;
|
||||
|
||||
@ -575,6 +589,10 @@ struct wl12xx_vif {
|
||||
int rssi_thold;
|
||||
int last_rssi_event;
|
||||
|
||||
/* save the current encryption type for auto-arp config */
|
||||
u8 encryption_type;
|
||||
__be32 ip_addr;
|
||||
|
||||
/* RX BA constraint value */
|
||||
bool ba_support;
|
||||
bool ba_allowed;
|
||||
|
@ -117,7 +117,7 @@ struct wl12xx_ps_poll_template {
|
||||
} __packed;
|
||||
|
||||
struct wl12xx_arp_rsp_template {
|
||||
struct ieee80211_hdr_3addr hdr;
|
||||
/* not including ieee80211 header */
|
||||
|
||||
u8 llc_hdr[sizeof(rfc1042_header)];
|
||||
__be16 llc_type;
|
||||
|
Loading…
Reference in New Issue
Block a user