mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge branch 'wireless-next' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx
This commit is contained in:
@@ -6321,7 +6321,7 @@ WL1271 WIRELESS DRIVER
|
||||
M: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/wl12xx/wl1271*
|
||||
F: include/linux/wl12xx.h
|
||||
|
||||
@@ -213,7 +213,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
|
||||
{
|
||||
.name = "wl1271",
|
||||
.mmc = 3,
|
||||
.wires = 4,
|
||||
.caps = MMC_CAP_4_BIT_DATA,
|
||||
.gpio_wp = -EINVAL,
|
||||
.gpio_cd = -EINVAL,
|
||||
.nonremovable = true,
|
||||
|
||||
@@ -117,10 +117,7 @@ enum {
|
||||
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
|
||||
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
|
||||
|
||||
/*
|
||||
* Enable/disable 802.11a support for WL1273
|
||||
*/
|
||||
#undef WL1271_80211A_ENABLED
|
||||
#define WL1271_CIPHER_SUITE_GEM 0x00147201
|
||||
|
||||
#define WL1271_BUSY_WORD_CNT 1
|
||||
#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
|
||||
@@ -133,6 +130,8 @@ enum {
|
||||
|
||||
#define ACX_TX_DESCRIPTORS 32
|
||||
|
||||
#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
|
||||
|
||||
enum wl1271_state {
|
||||
WL1271_STATE_OFF,
|
||||
WL1271_STATE_ON,
|
||||
@@ -301,6 +300,7 @@ struct wl1271_rx_mem_pool_addr {
|
||||
struct wl1271_scan {
|
||||
struct cfg80211_scan_request *req;
|
||||
bool *scanned_ch;
|
||||
bool failed;
|
||||
u8 state;
|
||||
u8 ssid[IW_ESSID_MAX_SIZE+1];
|
||||
size_t ssid_len;
|
||||
@@ -350,6 +350,7 @@ struct wl1271 {
|
||||
#define WL1271_FLAG_IDLE (10)
|
||||
#define WL1271_FLAG_IDLE_REQUESTED (11)
|
||||
#define WL1271_FLAG_PSPOLL_FAILURE (12)
|
||||
#define WL1271_FLAG_STA_STATE_SENT (13)
|
||||
unsigned long flags;
|
||||
|
||||
struct wl1271_partition_set part;
|
||||
@@ -362,6 +363,7 @@ struct wl1271 {
|
||||
u8 *fw;
|
||||
size_t fw_len;
|
||||
struct wl1271_nvs_file *nvs;
|
||||
size_t nvs_len;
|
||||
|
||||
s8 hw_pg_ver;
|
||||
|
||||
@@ -408,9 +410,15 @@ struct wl1271 {
|
||||
/* Rx memory pool address */
|
||||
struct wl1271_rx_mem_pool_addr rx_mem_pool_addr;
|
||||
|
||||
/* Intermediate buffer, used for packet aggregation */
|
||||
u8 *aggr_buf;
|
||||
|
||||
/* The target interrupt mask */
|
||||
struct work_struct irq_work;
|
||||
|
||||
/* Hardware recovery work */
|
||||
struct work_struct recovery_work;
|
||||
|
||||
/* The mbox event mask */
|
||||
u32 event_mask;
|
||||
|
||||
@@ -419,6 +427,7 @@ struct wl1271 {
|
||||
|
||||
/* Are we currently scanning */
|
||||
struct wl1271_scan scan;
|
||||
struct delayed_work scan_complete_work;
|
||||
|
||||
/* Our association ID */
|
||||
u16 aid;
|
||||
@@ -475,6 +484,8 @@ struct wl1271 {
|
||||
|
||||
bool sg_enabled;
|
||||
|
||||
bool enable_11a;
|
||||
|
||||
struct list_head list;
|
||||
|
||||
/* Most recently reported noise in dBm */
|
||||
@@ -498,14 +509,4 @@ int wl1271_plt_stop(struct wl1271 *wl);
|
||||
#define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */
|
||||
#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
|
||||
|
||||
static inline bool wl1271_11a_enabled(void)
|
||||
{
|
||||
/* FIXME: this could be determined based on the NVS-INI file */
|
||||
#ifdef WL1271_80211A_ENABLED
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -86,40 +86,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len)
|
||||
{
|
||||
struct acx_revision *rev;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx fw rev");
|
||||
|
||||
rev = kzalloc(sizeof(*rev), GFP_KERNEL);
|
||||
if (!rev) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("ACX_FW_REV interrogate failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* be careful with the buffer sizes */
|
||||
strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
|
||||
|
||||
/*
|
||||
* if the firmware version string is exactly
|
||||
* sizeof(rev->fw_version) long or fw_len is less than
|
||||
* sizeof(rev->fw_version) it won't be null terminated
|
||||
*/
|
||||
buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
|
||||
|
||||
out:
|
||||
kfree(rev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_tx_power(struct wl1271 *wl, int power)
|
||||
{
|
||||
struct acx_current_tx_power *acx;
|
||||
|
||||
@@ -100,35 +100,6 @@ struct acx_error_counter {
|
||||
__le32 seq_num_miss;
|
||||
} __packed;
|
||||
|
||||
struct acx_revision {
|
||||
struct acx_header header;
|
||||
|
||||
/*
|
||||
* The WiLink firmware version, an ASCII string x.x.x.x,
|
||||
* that uniquely identifies the current firmware.
|
||||
* The left most digit is incremented each time a
|
||||
* significant change is made to the firmware, such as
|
||||
* code redesign or new platform support.
|
||||
* The second digit is incremented when major enhancements
|
||||
* are added or major fixes are made.
|
||||
* The third digit is incremented for each GA release.
|
||||
* The fourth digit is incremented for each build.
|
||||
* The first two digits identify a firmware release version,
|
||||
* in other words, a unique set of features.
|
||||
* The first three digits identify a GA release.
|
||||
*/
|
||||
char fw_version[20];
|
||||
|
||||
/*
|
||||
* This 4 byte field specifies the WiLink hardware version.
|
||||
* bits 0 - 15: Reserved.
|
||||
* bits 16 - 23: Version ID - The WiLink version ID
|
||||
* (1 = first spin, 2 = second spin, and so on).
|
||||
* bits 24 - 31: Chip ID - The WiLink chip ID.
|
||||
*/
|
||||
__le32 hw_version;
|
||||
} __packed;
|
||||
|
||||
enum wl1271_psm_mode {
|
||||
/* Active mode */
|
||||
WL1271_PSM_CAM = 0,
|
||||
@@ -1060,7 +1031,6 @@ enum {
|
||||
ACX_PEER_HT_CAP = 0x0057,
|
||||
ACX_HT_BSS_OPERATION = 0x0058,
|
||||
ACX_COEX_ACTIVITY = 0x0059,
|
||||
ACX_SET_SMART_REFLEX_DEBUG = 0x005A,
|
||||
ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
|
||||
DOT11_RX_MSDU_LIFE_TIME = 0x1004,
|
||||
DOT11_CUR_TX_PWR = 0x100D,
|
||||
@@ -1077,7 +1047,6 @@ enum {
|
||||
|
||||
int wl1271_acx_wake_up_conditions(struct wl1271 *wl);
|
||||
int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth);
|
||||
int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len);
|
||||
int wl1271_acx_tx_power(struct wl1271 *wl, int power);
|
||||
int wl1271_acx_feature_cfg(struct wl1271 *wl);
|
||||
int wl1271_acx_mem_map(struct wl1271 *wl,
|
||||
|
||||
@@ -225,6 +225,28 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
if (wl->nvs == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
|
||||
* configurations) can be removed when those NVS files stop floating
|
||||
* around.
|
||||
*/
|
||||
if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
|
||||
wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
|
||||
if (wl->nvs->general_params.dual_mode_select)
|
||||
wl->enable_11a = true;
|
||||
}
|
||||
|
||||
if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
|
||||
(wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
|
||||
wl->enable_11a)) {
|
||||
wl1271_error("nvs size is not as expected: %zu != %zu",
|
||||
wl->nvs_len, sizeof(struct wl1271_nvs_file));
|
||||
kfree(wl->nvs);
|
||||
wl->nvs = NULL;
|
||||
wl->nvs_len = 0;
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
/* only the first part of the NVS needs to be uploaded */
|
||||
nvs_len = sizeof(wl->nvs->nvs);
|
||||
nvs_ptr = (u8 *)wl->nvs->nvs;
|
||||
@@ -251,8 +273,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
burst_len = nvs_ptr[0];
|
||||
dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
|
||||
|
||||
/* FIXME: Due to our new wl1271_translate_reg_addr function,
|
||||
we need to add the REGISTER_BASE to the destination */
|
||||
/*
|
||||
* Due to our new wl1271_translate_reg_addr function,
|
||||
* we need to add the REGISTER_BASE to the destination
|
||||
*/
|
||||
dest_addr += REGISTERS_BASE;
|
||||
|
||||
/* We move our pointer to the data */
|
||||
@@ -280,8 +304,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4);
|
||||
nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
|
||||
|
||||
/* FIXME: The driver sets the partition here, but this is not needed,
|
||||
since it sets to the same one as currently in use */
|
||||
/* Now we must set the partition correctly */
|
||||
wl1271_set_partition(wl, &part_table[PART_WORK]);
|
||||
|
||||
@@ -291,9 +313,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
return -ENOMEM;
|
||||
|
||||
/* And finally we upload the NVS tables */
|
||||
/* FIXME: In wl1271, we upload everything at once.
|
||||
No endianness handling needed here?! The ref driver doesn't do
|
||||
anything about it at this point */
|
||||
wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
|
||||
|
||||
kfree(nvs_aligned);
|
||||
@@ -491,10 +510,7 @@ int wl1271_boot(struct wl1271 *wl)
|
||||
|
||||
wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
|
||||
|
||||
pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be
|
||||
* WU_COUNTER_PAUSE_VAL instead of
|
||||
* 0x3ff (magic number ). How does
|
||||
* this work?! */
|
||||
pause &= ~(WU_COUNTER_PAUSE_VAL);
|
||||
pause |= WU_COUNTER_PAUSE_VAL;
|
||||
wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
|
||||
|
||||
@@ -548,7 +564,6 @@ int wl1271_boot(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* FIXME: Need to check whether this is really what we want */
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_ALL_EVENTS_VECTOR);
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
||||
status = le16_to_cpu(cmd->status);
|
||||
if (status != CMD_STATUS_SUCCESS) {
|
||||
wl1271_error("command execute failure %d", status);
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
@@ -170,6 +171,39 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_ext_radio_parms_cmd *ext_radio_parms;
|
||||
struct conf_rf_settings *rf = &wl->conf.rf;
|
||||
int ret;
|
||||
|
||||
if (!wl->nvs)
|
||||
return -ENODEV;
|
||||
|
||||
ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL);
|
||||
if (!ext_radio_parms)
|
||||
return -ENOMEM;
|
||||
|
||||
ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM;
|
||||
|
||||
memcpy(ext_radio_parms->tx_per_channel_power_compensation_2,
|
||||
rf->tx_per_channel_power_compensation_2,
|
||||
CONF_TX_PWR_COMPENSATION_LEN_2);
|
||||
memcpy(ext_radio_parms->tx_per_channel_power_compensation_5,
|
||||
rf->tx_per_channel_power_compensation_5,
|
||||
CONF_TX_PWR_COMPENSATION_LEN_5);
|
||||
|
||||
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ",
|
||||
ext_radio_parms, sizeof(*ext_radio_parms));
|
||||
|
||||
ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0);
|
||||
if (ret < 0)
|
||||
wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed");
|
||||
|
||||
kfree(ext_radio_parms);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Poll the mailbox event field until any of the bits in the mask is set or a
|
||||
* timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
|
||||
@@ -182,8 +216,10 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
|
||||
timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
|
||||
|
||||
do {
|
||||
if (time_after(jiffies, timeout))
|
||||
if (time_after(jiffies, timeout)) {
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
msleep(1);
|
||||
|
||||
@@ -390,18 +426,11 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
|
||||
{
|
||||
struct wl1271_cmd_ps_params *ps_params = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/* FIXME: this should be in ps.c */
|
||||
ret = wl1271_acx_wake_up_conditions(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_error("couldn't set wake up conditions");
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd set ps mode");
|
||||
|
||||
ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
|
||||
@@ -412,9 +441,9 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
|
||||
|
||||
ps_params->ps_mode = ps_mode;
|
||||
ps_params->send_null_data = send;
|
||||
ps_params->retries = 5;
|
||||
ps_params->hang_over_period = 1;
|
||||
ps_params->null_data_rate = cpu_to_le32(wl->basic_rate_set);
|
||||
ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries;
|
||||
ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period;
|
||||
ps_params->null_data_rate = cpu_to_le32(rates);
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
|
||||
sizeof(*ps_params), 0);
|
||||
@@ -428,41 +457,6 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
|
||||
size_t len)
|
||||
{
|
||||
struct cmd_read_write_memory *cmd;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd read memory");
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
WARN_ON(len > MAX_READ_SIZE);
|
||||
len = min_t(size_t, len, MAX_READ_SIZE);
|
||||
|
||||
cmd->addr = cpu_to_le32(addr);
|
||||
cmd->size = cpu_to_le32(len);
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd),
|
||||
sizeof(*cmd));
|
||||
if (ret < 0) {
|
||||
wl1271_error("read memory command failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* the read command got in */
|
||||
memcpy(answer, cmd->value, len);
|
||||
|
||||
out:
|
||||
kfree(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
|
||||
void *buf, size_t buf_len, int index, u32 rates)
|
||||
{
|
||||
@@ -523,7 +517,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0,
|
||||
WL1271_RATE_AUTOMATIC);
|
||||
wl->basic_rate);
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
@@ -546,7 +540,7 @@ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl)
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV,
|
||||
skb->data, skb->len,
|
||||
CMD_TEMPL_KLV_IDX_NULL_DATA,
|
||||
WL1271_RATE_AUTOMATIC);
|
||||
wl->basic_rate);
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
@@ -623,7 +617,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
|
||||
|
||||
return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
|
||||
sizeof(template), 0,
|
||||
WL1271_RATE_AUTOMATIC);
|
||||
wl->basic_rate);
|
||||
}
|
||||
|
||||
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
|
||||
@@ -746,3 +740,31 @@ out_free:
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_set_sta_state(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_cmd_set_sta_state *cmd;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd set sta state");
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
|
||||
|
||||
ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_error("failed to send set STA state command");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
kfree(cmd);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -33,12 +33,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
||||
size_t res_len);
|
||||
int wl1271_cmd_general_parms(struct wl1271 *wl);
|
||||
int wl1271_cmd_radio_parms(struct wl1271 *wl);
|
||||
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
|
||||
int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type);
|
||||
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
|
||||
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, u8 ps_mode, bool send);
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send);
|
||||
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,
|
||||
@@ -55,6 +56,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
|
||||
u8 key_size, const u8 *key, const u8 *addr,
|
||||
u32 tx_seq_32, u16 tx_seq_16);
|
||||
int wl1271_cmd_disconnect(struct wl1271 *wl);
|
||||
int wl1271_cmd_set_sta_state(struct wl1271 *wl);
|
||||
|
||||
enum wl1271_commands {
|
||||
CMD_INTERROGATE = 1, /*use this to read information elements*/
|
||||
@@ -160,41 +162,6 @@ enum {
|
||||
MAX_COMMAND_STATUS = 0xff
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* CMD_READ_MEMORY
|
||||
*
|
||||
* The host issues this command to read the WiLink device memory/registers.
|
||||
*
|
||||
* Note: The Base Band address has special handling (16 bits registers and
|
||||
* addresses). For more information, see the hardware specification.
|
||||
*/
|
||||
/*
|
||||
* CMD_WRITE_MEMORY
|
||||
*
|
||||
* The host issues this command to write the WiLink device memory/registers.
|
||||
*
|
||||
* The Base Band address has special handling (16 bits registers and
|
||||
* addresses). For more information, see the hardware specification.
|
||||
*/
|
||||
#define MAX_READ_SIZE 256
|
||||
|
||||
struct cmd_read_write_memory {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
/* The address of the memory to read from or write to.*/
|
||||
__le32 addr;
|
||||
|
||||
/* The amount of data in bytes to read from or write to the WiLink
|
||||
* device.*/
|
||||
__le32 size;
|
||||
|
||||
/* The actual value read from or written to the Wilink. The source
|
||||
of this field is the Host in WRITE command or the Wilink in READ
|
||||
command. */
|
||||
u8 value[MAX_READ_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define CMDMBOX_HEADER_LEN 4
|
||||
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
|
||||
|
||||
@@ -313,7 +280,7 @@ enum wl1271_cmd_key_type {
|
||||
KEY_WEP = 1,
|
||||
KEY_TKIP = 2,
|
||||
KEY_AES = 3,
|
||||
KEY_GEM = 4
|
||||
KEY_GEM = 4,
|
||||
};
|
||||
|
||||
/* FIXME: Add description for key-types */
|
||||
@@ -358,13 +325,14 @@ enum wl1271_channel_tune_bands {
|
||||
WL1271_CHANNEL_TUNE_BAND_4_9
|
||||
};
|
||||
|
||||
#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0
|
||||
#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0
|
||||
|
||||
#define TEST_CMD_P2G_CAL 0x02
|
||||
#define TEST_CMD_CHANNEL_TUNE 0x0d
|
||||
#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
|
||||
#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
|
||||
#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
|
||||
#define TEST_CMD_P2G_CAL 0x02
|
||||
#define TEST_CMD_CHANNEL_TUNE 0x0d
|
||||
#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
|
||||
#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
|
||||
#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
|
||||
#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26
|
||||
|
||||
struct wl1271_general_parms_cmd {
|
||||
struct wl1271_cmd_header header;
|
||||
@@ -397,6 +365,16 @@ struct wl1271_radio_parms_cmd {
|
||||
u8 padding3[2];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_ext_radio_parms_cmd {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
struct wl1271_cmd_test_header test;
|
||||
|
||||
u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
|
||||
u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
|
||||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
struct wl1271_cmd_cal_channel_tune {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
@@ -469,4 +447,13 @@ struct wl1271_cmd_disconnect {
|
||||
u8 padding;
|
||||
} __packed;
|
||||
|
||||
#define WL1271_CMD_STA_STATE_CONNECTED 1
|
||||
|
||||
struct wl1271_cmd_set_sta_state {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
u8 state;
|
||||
u8 padding[3];
|
||||
} __packed;
|
||||
|
||||
#endif /* __WL1271_CMD_H__ */
|
||||
|
||||
@@ -595,7 +595,7 @@ struct conf_tx_ac_category {
|
||||
u16 tx_op_limit;
|
||||
};
|
||||
|
||||
#define CONF_TX_MAX_TID_COUNT 7
|
||||
#define CONF_TX_MAX_TID_COUNT 8
|
||||
|
||||
enum {
|
||||
CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/
|
||||
@@ -911,6 +911,22 @@ struct conf_conn_settings {
|
||||
*/
|
||||
u8 psm_entry_retries;
|
||||
|
||||
/*
|
||||
* Specifies the maximum number of times to try transmit the PSM entry
|
||||
* null-func frame for each PSM entry attempt
|
||||
*
|
||||
* Range 0 - 255
|
||||
*/
|
||||
u8 psm_entry_nullfunc_retries;
|
||||
|
||||
/*
|
||||
* Specifies the time to linger in active mode after successfully
|
||||
* transmitting the PSM entry null-func frame.
|
||||
*
|
||||
* Range 0 - 255 TU's
|
||||
*/
|
||||
u8 psm_entry_hangover_period;
|
||||
|
||||
/*
|
||||
*
|
||||
* Specifies the interval of the connection keep-alive null-func
|
||||
@@ -1016,6 +1032,64 @@ struct conf_roam_trigger_settings {
|
||||
u8 avg_weight_snr_data;
|
||||
};
|
||||
|
||||
struct conf_scan_settings {
|
||||
/*
|
||||
* The minimum time to wait on each channel for active scans
|
||||
*
|
||||
* Range: 0 - 65536 tu
|
||||
*/
|
||||
u16 min_dwell_time_active;
|
||||
|
||||
/*
|
||||
* The maximum time to wait on each channel for active scans
|
||||
*
|
||||
* Range: 0 - 65536 tu
|
||||
*/
|
||||
u16 max_dwell_time_active;
|
||||
|
||||
/*
|
||||
* The maximum time to wait on each channel for passive scans
|
||||
*
|
||||
* Range: 0 - 65536 tu
|
||||
*/
|
||||
u16 min_dwell_time_passive;
|
||||
|
||||
/*
|
||||
* The maximum time to wait on each channel for passive scans
|
||||
*
|
||||
* Range: 0 - 65536 tu
|
||||
*/
|
||||
u16 max_dwell_time_passive;
|
||||
|
||||
/*
|
||||
* Number of probe requests to transmit on each active scan channel
|
||||
*
|
||||
* Range: u8
|
||||
*/
|
||||
u16 num_probe_reqs;
|
||||
|
||||
};
|
||||
|
||||
/* these are number of channels on the band divided by two, rounded up */
|
||||
#define CONF_TX_PWR_COMPENSATION_LEN_2 7
|
||||
#define CONF_TX_PWR_COMPENSATION_LEN_5 18
|
||||
|
||||
struct conf_rf_settings {
|
||||
/*
|
||||
* Per channel power compensation for 2.4GHz
|
||||
*
|
||||
* Range: s8
|
||||
*/
|
||||
u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
|
||||
|
||||
/*
|
||||
* Per channel power compensation for 5GHz
|
||||
*
|
||||
* Range: s8
|
||||
*/
|
||||
u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
|
||||
};
|
||||
|
||||
struct conf_drv_settings {
|
||||
struct conf_sg_settings sg;
|
||||
struct conf_rx_settings rx;
|
||||
@@ -1024,6 +1098,8 @@ struct conf_drv_settings {
|
||||
struct conf_itrim_settings itrim;
|
||||
struct conf_pm_config_settings pm_config;
|
||||
struct conf_roam_trigger_settings roam_trigger;
|
||||
struct conf_scan_settings scan;
|
||||
struct conf_rf_settings rf;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,9 @@ void wl1271_pspoll_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
goto out;
|
||||
|
||||
if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags))
|
||||
goto out;
|
||||
|
||||
@@ -52,7 +55,7 @@ void wl1271_pspoll_work(struct work_struct *work)
|
||||
* delivery failure occurred, and no-one changed state since, so
|
||||
* we should go back to powersave.
|
||||
*/
|
||||
wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true);
|
||||
wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
@@ -70,7 +73,8 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl)
|
||||
|
||||
/* force active mode receive data from the AP */
|
||||
if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
|
||||
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true);
|
||||
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
|
||||
wl->basic_rate, true);
|
||||
if (ret < 0)
|
||||
return;
|
||||
set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
|
||||
@@ -91,6 +95,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
|
||||
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);
|
||||
|
||||
@@ -104,10 +109,10 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
|
||||
break;
|
||||
}
|
||||
|
||||
if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
|
||||
if (wl->psm_entry_retry < total_retries) {
|
||||
wl->psm_entry_retry++;
|
||||
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
|
||||
true);
|
||||
wl->basic_rate, true);
|
||||
} else {
|
||||
wl1271_info("No ack to nullfunc from AP.");
|
||||
wl->psm_entry_retry = 0;
|
||||
@@ -143,7 +148,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
|
||||
/* make sure the firmware goes to active mode - the frame to
|
||||
be sent next will indicate to the AP, that we are active. */
|
||||
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
|
||||
false);
|
||||
wl->basic_rate, false);
|
||||
break;
|
||||
case EVENT_EXIT_POWER_SAVE_SUCCESS:
|
||||
default:
|
||||
|
||||
@@ -53,6 +53,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl)
|
||||
int wl1271_init_templates_config(struct wl1271 *wl)
|
||||
{
|
||||
int ret, i;
|
||||
size_t size;
|
||||
|
||||
/* send empty templates for fw memory reservation */
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
|
||||
@@ -61,14 +62,12 @@ int wl1271_init_templates_config(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (wl1271_11a_enabled()) {
|
||||
size_t size = sizeof(struct wl12xx_probe_req_template);
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
NULL, size, 0,
|
||||
WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
size = sizeof(struct wl12xx_probe_req_template);
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
NULL, size, 0,
|
||||
WL1271_RATE_AUTOMATIC);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
|
||||
sizeof(struct wl12xx_null_data_template),
|
||||
@@ -223,6 +222,10 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_ext_radio_parms(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Template settings */
|
||||
ret = wl1271_init_templates_config(wl);
|
||||
if (ret < 0)
|
||||
@@ -291,8 +294,16 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Default TID configuration */
|
||||
/* Default TID/AC configuration */
|
||||
BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
|
||||
for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
|
||||
conf_ac = &wl->conf.tx.ac_conf[i];
|
||||
ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
|
||||
conf_ac->cw_max, conf_ac->aifsn,
|
||||
conf_ac->tx_op_limit);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
conf_tid = &wl->conf.tx.tid_conf[i];
|
||||
ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
|
||||
conf_tid->channel_type,
|
||||
@@ -305,16 +316,6 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
goto out_free_memmap;
|
||||
}
|
||||
|
||||
/* Default AC configuration */
|
||||
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
|
||||
conf_ac = &wl->conf.tx.ac_conf[i];
|
||||
ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
|
||||
conf_ac->cw_max, conf_ac->aifsn,
|
||||
conf_ac->tx_op_limit);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
}
|
||||
|
||||
/* Configure TX rate classes */
|
||||
ret = wl1271_acx_rate_policies(wl);
|
||||
if (ret < 0)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,9 @@ void wl1271_elp_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
goto out;
|
||||
|
||||
if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
|
||||
(!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
|
||||
!test_bit(WL1271_FLAG_IDLE, &wl->flags)))
|
||||
@@ -61,7 +64,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
|
||||
test_bit(WL1271_FLAG_IDLE, &wl->flags)) {
|
||||
cancel_delayed_work(&wl->elp_work);
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
|
||||
msecs_to_jiffies(ELP_ENTRY_DELAY));
|
||||
msecs_to_jiffies(ELP_ENTRY_DELAY));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +99,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
|
||||
&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
|
||||
if (ret == 0) {
|
||||
wl1271_error("ELP wakeup timeout!");
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
ret = -ETIMEDOUT;
|
||||
goto err;
|
||||
} else if (ret < 0) {
|
||||
@@ -121,7 +125,7 @@ out:
|
||||
}
|
||||
|
||||
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
|
||||
bool send)
|
||||
u32 rates, bool send)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -129,7 +133,14 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
|
||||
case STATION_POWER_SAVE_MODE:
|
||||
wl1271_debug(DEBUG_PSM, "entering psm");
|
||||
|
||||
ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send);
|
||||
ret = wl1271_acx_wake_up_conditions(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_error("couldn't set wake up conditions");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE,
|
||||
rates, send);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -152,7 +163,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send);
|
||||
ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE,
|
||||
rates, send);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "wl1271_acx.h"
|
||||
|
||||
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
|
||||
bool send);
|
||||
u32 rates, bool send);
|
||||
void wl1271_ps_elp_sleep(struct wl1271 *wl);
|
||||
int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
|
||||
void wl1271_elp_work(struct work_struct *work);
|
||||
|
||||
@@ -74,7 +74,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
|
||||
}
|
||||
}
|
||||
|
||||
static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
|
||||
static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
|
||||
{
|
||||
struct wl1271_rx_descriptor *desc;
|
||||
struct sk_buff *skb;
|
||||
@@ -87,16 +87,16 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
|
||||
* workaround this by not retrieving them at all.
|
||||
*/
|
||||
if (unlikely(wl->state == WL1271_STATE_PLT))
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
skb = __dev_alloc_skb(length, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
wl1271_error("Couldn't allocate RX frame");
|
||||
return;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
buf = skb_put(skb, length);
|
||||
wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
|
||||
memcpy(buf, data, length);
|
||||
|
||||
/* the data read starts with the descriptor */
|
||||
desc = (struct wl1271_rx_descriptor *) buf;
|
||||
@@ -116,6 +116,8 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
|
||||
skb_trim(skb, skb->len - desc->pad_len);
|
||||
|
||||
ieee80211_rx_ni(wl->hw, skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
|
||||
@@ -124,31 +126,60 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
|
||||
u32 buf_size;
|
||||
u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
|
||||
u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
|
||||
u32 rx_counter;
|
||||
u32 mem_block;
|
||||
u32 pkt_length;
|
||||
u32 pkt_offset;
|
||||
|
||||
while (drv_rx_counter != fw_rx_counter) {
|
||||
mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
|
||||
buf_size = wl1271_rx_get_buf_size(status, drv_rx_counter);
|
||||
buf_size = 0;
|
||||
rx_counter = drv_rx_counter;
|
||||
while (rx_counter != fw_rx_counter) {
|
||||
pkt_length = wl1271_rx_get_buf_size(status, rx_counter);
|
||||
if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
|
||||
break;
|
||||
buf_size += pkt_length;
|
||||
rx_counter++;
|
||||
rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
|
||||
}
|
||||
|
||||
if (buf_size == 0) {
|
||||
wl1271_warning("received empty data");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose the block we want to read
|
||||
* For aggregated packets, only the first memory block should
|
||||
* be retrieved. The FW takes care of the rest.
|
||||
*/
|
||||
mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
|
||||
wl->rx_mem_pool_addr.addr = (mem_block << 8) +
|
||||
le32_to_cpu(wl_mem_map->packet_memory_pool_start);
|
||||
wl->rx_mem_pool_addr.addr_extra =
|
||||
wl->rx_mem_pool_addr.addr + 4;
|
||||
|
||||
/* Choose the block we want to read */
|
||||
wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr,
|
||||
sizeof(wl->rx_mem_pool_addr), false);
|
||||
sizeof(wl->rx_mem_pool_addr), false);
|
||||
|
||||
wl1271_rx_handle_data(wl, buf_size);
|
||||
/* Read all available packets at once */
|
||||
wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
|
||||
buf_size, true);
|
||||
|
||||
wl->rx_counter++;
|
||||
drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
|
||||
/* Split data into separate packets */
|
||||
pkt_offset = 0;
|
||||
while (pkt_offset < buf_size) {
|
||||
pkt_length = wl1271_rx_get_buf_size(status,
|
||||
drv_rx_counter);
|
||||
if (wl1271_rx_handle_data(wl,
|
||||
wl->aggr_buf + pkt_offset,
|
||||
pkt_length) < 0)
|
||||
break;
|
||||
wl->rx_counter++;
|
||||
drv_rx_counter++;
|
||||
drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
|
||||
pkt_offset += pkt_length;
|
||||
}
|
||||
}
|
||||
|
||||
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
|
||||
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS,
|
||||
cpu_to_le32(wl->rx_counter));
|
||||
}
|
||||
|
||||
@@ -28,11 +28,43 @@
|
||||
#include "wl1271_scan.h"
|
||||
#include "wl1271_acx.h"
|
||||
|
||||
void wl1271_scan_complete_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dwork;
|
||||
struct wl1271 *wl;
|
||||
|
||||
dwork = container_of(work, struct delayed_work, work);
|
||||
wl = container_of(dwork, struct wl1271, scan_complete_work);
|
||||
|
||||
wl1271_debug(DEBUG_SCAN, "Scanning complete");
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (wl->scan.state == WL1271_SCAN_STATE_IDLE) {
|
||||
mutex_unlock(&wl->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
wl->scan.state = WL1271_SCAN_STATE_IDLE;
|
||||
kfree(wl->scan.scanned_ch);
|
||||
wl->scan.scanned_ch = NULL;
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
ieee80211_scan_completed(wl->hw, false);
|
||||
|
||||
if (wl->scan.failed) {
|
||||
wl1271_info("Scan completed due to error.");
|
||||
ieee80211_queue_work(wl->hw, &wl->recovery_work);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int wl1271_get_scan_channels(struct wl1271 *wl,
|
||||
struct cfg80211_scan_request *req,
|
||||
struct basic_scan_channel_params *channels,
|
||||
enum ieee80211_band band, bool passive)
|
||||
{
|
||||
struct conf_scan_settings *c = &wl->conf.scan;
|
||||
int i, j;
|
||||
u32 flags;
|
||||
|
||||
@@ -60,10 +92,17 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
|
||||
wl1271_debug(DEBUG_SCAN, "beacon_found %d",
|
||||
req->channels[i]->beacon_found);
|
||||
|
||||
channels[j].min_duration =
|
||||
cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
|
||||
channels[j].max_duration =
|
||||
cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
|
||||
if (!passive) {
|
||||
channels[j].min_duration =
|
||||
cpu_to_le32(c->min_dwell_time_active);
|
||||
channels[j].max_duration =
|
||||
cpu_to_le32(c->max_dwell_time_active);
|
||||
} else {
|
||||
channels[j].min_duration =
|
||||
cpu_to_le32(c->min_dwell_time_passive);
|
||||
channels[j].max_duration =
|
||||
cpu_to_le32(c->max_dwell_time_passive);
|
||||
}
|
||||
channels[j].early_termination = 0;
|
||||
channels[j].tx_power_att = req->channels[i]->max_power;
|
||||
channels[j].channel = req->channels[i]->hw_value;
|
||||
@@ -100,8 +139,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
|
||||
|
||||
/* We always use high priority scans */
|
||||
scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
|
||||
if(passive)
|
||||
|
||||
/* No SSIDs means that we have a forced passive scan */
|
||||
if (passive || wl->scan.req->n_ssids == 0)
|
||||
scan_options |= WL1271_SCAN_OPT_PASSIVE;
|
||||
|
||||
cmd->params.scan_options = cpu_to_le16(scan_options);
|
||||
|
||||
cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
|
||||
@@ -117,7 +159,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
|
||||
cmd->params.rx_filter_options =
|
||||
cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
|
||||
|
||||
cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS;
|
||||
cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
|
||||
cmd->params.tx_rate = cpu_to_le32(basic_rate);
|
||||
cmd->params.tid_trigger = 0;
|
||||
cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
|
||||
@@ -165,7 +207,7 @@ out:
|
||||
|
||||
void wl1271_scan_stm(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
switch (wl->scan.state) {
|
||||
case WL1271_SCAN_STATE_IDLE:
|
||||
@@ -185,7 +227,7 @@ void wl1271_scan_stm(struct wl1271 *wl)
|
||||
ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true,
|
||||
wl->conf.tx.basic_rate);
|
||||
if (ret == WL1271_NOTHING_TO_SCAN) {
|
||||
if (wl1271_11a_enabled())
|
||||
if (wl->enable_11a)
|
||||
wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
|
||||
else
|
||||
wl->scan.state = WL1271_SCAN_STATE_DONE;
|
||||
@@ -215,18 +257,22 @@ void wl1271_scan_stm(struct wl1271 *wl)
|
||||
break;
|
||||
|
||||
case WL1271_SCAN_STATE_DONE:
|
||||
ieee80211_scan_completed(wl->hw, false);
|
||||
|
||||
kfree(wl->scan.scanned_ch);
|
||||
wl->scan.scanned_ch = NULL;
|
||||
|
||||
wl->scan.state = WL1271_SCAN_STATE_IDLE;
|
||||
wl->scan.failed = false;
|
||||
cancel_delayed_work(&wl->scan_complete_work);
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
|
||||
msecs_to_jiffies(0));
|
||||
break;
|
||||
|
||||
default:
|
||||
wl1271_error("invalid scan state");
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
cancel_delayed_work(&wl->scan_complete_work);
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
|
||||
msecs_to_jiffies(0));
|
||||
}
|
||||
}
|
||||
|
||||
int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
|
||||
@@ -249,6 +295,11 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
|
||||
wl->scan.scanned_ch = kzalloc(req->n_channels *
|
||||
sizeof(*wl->scan.scanned_ch),
|
||||
GFP_KERNEL);
|
||||
/* we assume failure so that timeout scenarios are handled correctly */
|
||||
wl->scan.failed = true;
|
||||
ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
|
||||
msecs_to_jiffies(WL1271_SCAN_TIMEOUT));
|
||||
|
||||
wl1271_scan_stm(wl);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -32,6 +32,7 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl,
|
||||
const u8 *ssid, size_t ssid_len,
|
||||
const u8 *ie, size_t ie_len, u8 band);
|
||||
void wl1271_scan_stm(struct wl1271 *wl);
|
||||
void wl1271_scan_complete_work(struct work_struct *work);
|
||||
|
||||
#define WL1271_SCAN_MAX_CHANNELS 24
|
||||
#define WL1271_SCAN_DEFAULT_TAG 1
|
||||
@@ -39,11 +40,10 @@ void wl1271_scan_stm(struct wl1271 *wl);
|
||||
#define WL1271_SCAN_OPT_ACTIVE 0
|
||||
#define WL1271_SCAN_OPT_PASSIVE 1
|
||||
#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
|
||||
#define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */
|
||||
#define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */
|
||||
#define WL1271_SCAN_BAND_2_4_GHZ 0
|
||||
#define WL1271_SCAN_BAND_5_GHZ 1
|
||||
#define WL1271_SCAN_PROBE_REQS 3
|
||||
|
||||
#define WL1271_SCAN_TIMEOUT 10000 /* msec */
|
||||
|
||||
enum {
|
||||
WL1271_SCAN_STATE_IDLE,
|
||||
|
||||
@@ -274,9 +274,8 @@ static void __devexit wl1271_remove(struct sdio_func *func)
|
||||
{
|
||||
struct wl1271 *wl = sdio_get_drvdata(func);
|
||||
|
||||
free_irq(wl->irq, wl);
|
||||
|
||||
wl1271_unregister_hw(wl);
|
||||
free_irq(wl->irq, wl);
|
||||
wl1271_free_hw(wl);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,11 @@
|
||||
((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32))
|
||||
#define HW_ACCESS_WSPI_INIT_CMD_MASK 0
|
||||
|
||||
/* HW limitation: maximum possible chunk size is 4095 bytes */
|
||||
#define WSPI_MAX_CHUNK_SIZE 4092
|
||||
|
||||
#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
|
||||
|
||||
static inline struct spi_device *wl_to_spi(struct wl1271 *wl)
|
||||
{
|
||||
return wl->if_priv;
|
||||
@@ -202,90 +207,117 @@ static int wl1271_spi_read_busy(struct wl1271 *wl)
|
||||
static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
struct spi_transfer t[3];
|
||||
struct spi_transfer t[2];
|
||||
struct spi_message m;
|
||||
u32 *busy_buf;
|
||||
u32 *cmd;
|
||||
u32 chunk_len;
|
||||
|
||||
cmd = &wl->buffer_cmd;
|
||||
busy_buf = wl->buffer_busyword;
|
||||
while (len > 0) {
|
||||
chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
|
||||
|
||||
*cmd = 0;
|
||||
*cmd |= WSPI_CMD_READ;
|
||||
*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
|
||||
*cmd |= addr & WSPI_CMD_BYTE_ADDR;
|
||||
cmd = &wl->buffer_cmd;
|
||||
busy_buf = wl->buffer_busyword;
|
||||
|
||||
if (fixed)
|
||||
*cmd |= WSPI_CMD_FIXED;
|
||||
*cmd = 0;
|
||||
*cmd |= WSPI_CMD_READ;
|
||||
*cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
|
||||
WSPI_CMD_BYTE_LENGTH;
|
||||
*cmd |= addr & WSPI_CMD_BYTE_ADDR;
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(t, 0, sizeof(t));
|
||||
if (fixed)
|
||||
*cmd |= WSPI_CMD_FIXED;
|
||||
|
||||
t[0].tx_buf = cmd;
|
||||
t[0].len = 4;
|
||||
t[0].cs_change = true;
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
spi_message_init(&m);
|
||||
memset(t, 0, sizeof(t));
|
||||
|
||||
/* Busy and non busy words read */
|
||||
t[1].rx_buf = busy_buf;
|
||||
t[1].len = WL1271_BUSY_WORD_LEN;
|
||||
t[1].cs_change = true;
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
t[0].tx_buf = cmd;
|
||||
t[0].len = 4;
|
||||
t[0].cs_change = true;
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
|
||||
spi_sync(wl_to_spi(wl), &m);
|
||||
/* Busy and non busy words read */
|
||||
t[1].rx_buf = busy_buf;
|
||||
t[1].len = WL1271_BUSY_WORD_LEN;
|
||||
t[1].cs_change = true;
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
|
||||
if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
|
||||
wl1271_spi_read_busy(wl)) {
|
||||
memset(buf, 0, len);
|
||||
return;
|
||||
spi_sync(wl_to_spi(wl), &m);
|
||||
|
||||
if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
|
||||
wl1271_spi_read_busy(wl)) {
|
||||
memset(buf, 0, chunk_len);
|
||||
return;
|
||||
}
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(t, 0, sizeof(t));
|
||||
|
||||
t[0].rx_buf = buf;
|
||||
t[0].len = chunk_len;
|
||||
t[0].cs_change = true;
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
|
||||
spi_sync(wl_to_spi(wl), &m);
|
||||
|
||||
wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
|
||||
wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, chunk_len);
|
||||
|
||||
if (!fixed)
|
||||
addr += chunk_len;
|
||||
buf += chunk_len;
|
||||
len -= chunk_len;
|
||||
}
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(t, 0, sizeof(t));
|
||||
|
||||
t[0].rx_buf = buf;
|
||||
t[0].len = len;
|
||||
t[0].cs_change = true;
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
|
||||
spi_sync(wl_to_spi(wl), &m);
|
||||
|
||||
wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
|
||||
wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
|
||||
}
|
||||
|
||||
static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
struct spi_transfer t[2];
|
||||
struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
|
||||
struct spi_message m;
|
||||
u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
|
||||
u32 *cmd;
|
||||
u32 chunk_len;
|
||||
int i;
|
||||
|
||||
cmd = &wl->buffer_cmd;
|
||||
|
||||
*cmd = 0;
|
||||
*cmd |= WSPI_CMD_WRITE;
|
||||
*cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
|
||||
*cmd |= addr & WSPI_CMD_BYTE_ADDR;
|
||||
|
||||
if (fixed)
|
||||
*cmd |= WSPI_CMD_FIXED;
|
||||
WARN_ON(len > WL1271_AGGR_BUFFER_SIZE);
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(t, 0, sizeof(t));
|
||||
|
||||
t[0].tx_buf = cmd;
|
||||
t[0].len = sizeof(*cmd);
|
||||
spi_message_add_tail(&t[0], &m);
|
||||
cmd = &commands[0];
|
||||
i = 0;
|
||||
while (len > 0) {
|
||||
chunk_len = min((size_t)WSPI_MAX_CHUNK_SIZE, len);
|
||||
|
||||
t[1].tx_buf = buf;
|
||||
t[1].len = len;
|
||||
spi_message_add_tail(&t[1], &m);
|
||||
*cmd = 0;
|
||||
*cmd |= WSPI_CMD_WRITE;
|
||||
*cmd |= (chunk_len << WSPI_CMD_BYTE_LENGTH_OFFSET) &
|
||||
WSPI_CMD_BYTE_LENGTH;
|
||||
*cmd |= addr & WSPI_CMD_BYTE_ADDR;
|
||||
|
||||
if (fixed)
|
||||
*cmd |= WSPI_CMD_FIXED;
|
||||
|
||||
t[i].tx_buf = cmd;
|
||||
t[i].len = sizeof(*cmd);
|
||||
spi_message_add_tail(&t[i++], &m);
|
||||
|
||||
t[i].tx_buf = buf;
|
||||
t[i].len = chunk_len;
|
||||
spi_message_add_tail(&t[i++], &m);
|
||||
|
||||
wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
|
||||
wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, chunk_len);
|
||||
|
||||
if (!fixed)
|
||||
addr += chunk_len;
|
||||
buf += chunk_len;
|
||||
len -= chunk_len;
|
||||
cmd++;
|
||||
}
|
||||
|
||||
spi_sync(wl_to_spi(wl), &m);
|
||||
|
||||
wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
|
||||
wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
|
||||
}
|
||||
|
||||
static irqreturn_t wl1271_irq(int irq, void *cookie)
|
||||
@@ -416,9 +448,8 @@ static int __devexit wl1271_remove(struct spi_device *spi)
|
||||
{
|
||||
struct wl1271 *wl = dev_get_drvdata(&spi->dev);
|
||||
|
||||
free_irq(wl->irq, wl);
|
||||
|
||||
wl1271_unregister_hw(wl);
|
||||
free_irq(wl->irq, wl);
|
||||
wl1271_free_hw(wl);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -199,19 +199,6 @@ 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]);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
kfree(wl->nvs);
|
||||
@@ -224,6 +211,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
|
||||
}
|
||||
|
||||
memcpy(wl->nvs, buf, len);
|
||||
wl->nvs_len = len;
|
||||
|
||||
wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user