Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx

This commit is contained in:
John W. Linville 2011-02-09 15:44:17 -05:00
commit 09db47b08a
14 changed files with 298 additions and 176 deletions

View File

@ -783,6 +783,10 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT); acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates,
acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates);
ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
if (ret < 0) { if (ret < 0) {
wl1271_warning("Setting of rate policies failed: %d", ret); wl1271_warning("Setting of rate policies failed: %d", ret);
@ -947,9 +951,9 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_mem_cfg(struct wl1271 *wl) int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
{ {
struct wl1271_acx_config_memory *mem_conf; struct wl1271_acx_ap_config_memory *mem_conf;
int ret; int ret;
wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
@ -961,10 +965,10 @@ int wl1271_acx_mem_cfg(struct wl1271 *wl)
} }
/* memory config */ /* memory config */
mem_conf->num_stations = DEFAULT_NUM_STATIONS; mem_conf->num_stations = wl->conf.mem.num_stations;
mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS; mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS; mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES; mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
@ -979,14 +983,46 @@ int wl1271_acx_mem_cfg(struct wl1271 *wl)
return ret; return ret;
} }
int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
{
struct wl1271_acx_sta_config_memory *mem_conf;
int ret;
wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
if (!mem_conf) {
ret = -ENOMEM;
goto out;
}
/* memory config */
mem_conf->num_stations = wl->conf.mem.num_stations;
mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory;
mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks;
mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks;
mem_conf->tx_min = wl->conf.mem.tx_min;
ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
sizeof(*mem_conf));
if (ret < 0) {
wl1271_warning("wl1271 mem config failed: %d", ret);
goto out;
}
out:
kfree(mem_conf);
return ret;
}
int wl1271_acx_init_mem_config(struct wl1271 *wl) int wl1271_acx_init_mem_config(struct wl1271 *wl)
{ {
int ret; int ret;
ret = wl1271_acx_mem_cfg(wl);
if (ret < 0)
return ret;
wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map), wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
GFP_KERNEL); GFP_KERNEL);
if (!wl->target_mem_map) { if (!wl->target_mem_map) {
@ -1476,3 +1512,33 @@ int wl1271_acx_max_tx_retry(struct wl1271 *wl)
kfree(acx); kfree(acx);
return ret; return ret;
} }
int wl1271_acx_config_ps(struct wl1271 *wl)
{
struct wl1271_acx_config_ps *config_ps;
int ret;
wl1271_debug(DEBUG_ACX, "acx config ps");
config_ps = kzalloc(sizeof(*config_ps), GFP_KERNEL);
if (!config_ps) {
ret = -ENOMEM;
goto out;
}
config_ps->exit_retries = wl->conf.conn.psm_exit_retries;
config_ps->enter_retries = wl->conf.conn.psm_entry_retries;
config_ps->null_data_rate = cpu_to_le32(wl->basic_rate);
ret = wl1271_cmd_configure(wl, ACX_CONFIG_PS, config_ps,
sizeof(*config_ps));
if (ret < 0) {
wl1271_warning("acx config ps failed: %d", ret);
goto out;
}
out:
kfree(config_ps);
return ret;
}

View File

@ -133,7 +133,6 @@ enum {
#define DEFAULT_UCAST_PRIORITY 0 #define DEFAULT_UCAST_PRIORITY 0
#define DEFAULT_RX_Q_PRIORITY 0 #define DEFAULT_RX_Q_PRIORITY 0
#define DEFAULT_NUM_STATIONS 1
#define DEFAULT_RXQ_PRIORITY 0 /* low 0 .. 15 high */ #define DEFAULT_RXQ_PRIORITY 0 /* low 0 .. 15 high */
#define DEFAULT_RXQ_TYPE 0x07 /* All frames, Data/Ctrl/Mgmt */ #define DEFAULT_RXQ_TYPE 0x07 /* All frames, Data/Ctrl/Mgmt */
#define TRACE_BUFFER_MAX_SIZE 256 #define TRACE_BUFFER_MAX_SIZE 256
@ -797,12 +796,9 @@ struct acx_tx_config_options {
__le16 tx_compl_threshold; /* number of packets */ __le16 tx_compl_threshold; /* number of packets */
} __packed; } __packed;
#define ACX_RX_MEM_BLOCKS 70
#define ACX_TX_MIN_MEM_BLOCKS 40
#define ACX_TX_DESCRIPTORS 32 #define ACX_TX_DESCRIPTORS 32
#define ACX_NUM_SSID_PROFILES 1
struct wl1271_acx_config_memory { struct wl1271_acx_ap_config_memory {
struct acx_header header; struct acx_header header;
u8 rx_mem_block_num; u8 rx_mem_block_num;
@ -812,6 +808,20 @@ struct wl1271_acx_config_memory {
__le32 total_tx_descriptors; __le32 total_tx_descriptors;
} __packed; } __packed;
struct wl1271_acx_sta_config_memory {
struct acx_header header;
u8 rx_mem_block_num;
u8 tx_min_mem_block_num;
u8 num_stations;
u8 num_ssid_profiles;
__le32 total_tx_descriptors;
u8 dyn_mem_enable;
u8 tx_free_req;
u8 rx_free_req;
u8 tx_min;
} __packed;
struct wl1271_acx_mem_map { struct wl1271_acx_mem_map {
struct acx_header header; struct acx_header header;
@ -1136,6 +1146,15 @@ struct wl1271_acx_max_tx_retry {
u8 padding_1[2]; u8 padding_1[2];
} __packed; } __packed;
struct wl1271_acx_config_ps {
struct acx_header header;
u8 exit_retries;
u8 enter_retries;
u8 padding[2];
__le32 null_data_rate;
} __packed;
enum { enum {
ACX_WAKE_UP_CONDITIONS = 0x0002, ACX_WAKE_UP_CONDITIONS = 0x0002,
ACX_MEM_CFG = 0x0003, ACX_MEM_CFG = 0x0003,
@ -1193,6 +1212,8 @@ enum {
ACX_HT_BSS_OPERATION = 0x0058, ACX_HT_BSS_OPERATION = 0x0058,
ACX_COEX_ACTIVITY = 0x0059, ACX_COEX_ACTIVITY = 0x0059,
ACX_SET_DCO_ITRIM_PARAMS = 0x0061, ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
ACX_GEN_FW_CMD = 0x0070,
ACX_HOST_IF_CFG_BITMAP = 0x0071,
ACX_MAX_TX_FAILURE = 0x0072, ACX_MAX_TX_FAILURE = 0x0072,
DOT11_RX_MSDU_LIFE_TIME = 0x1004, DOT11_RX_MSDU_LIFE_TIME = 0x1004,
DOT11_CUR_TX_PWR = 0x100D, DOT11_CUR_TX_PWR = 0x100D,
@ -1200,10 +1221,8 @@ enum {
DOT11_RTS_THRESHOLD = 0x1013, DOT11_RTS_THRESHOLD = 0x1013,
DOT11_GROUP_ADDRESS_TBL = 0x1014, DOT11_GROUP_ADDRESS_TBL = 0x1014,
ACX_PM_CONFIG = 0x1016, ACX_PM_CONFIG = 0x1016,
ACX_CONFIG_PS = 0x1017,
MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, ACX_CONFIG_HANGOVER = 0x1018,
MAX_IE = 0xFFFF
}; };
@ -1245,7 +1264,8 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
u32 apsd_conf0, u32 apsd_conf1); u32 apsd_conf0, u32 apsd_conf1);
int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold); int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold);
int wl1271_acx_tx_config_options(struct wl1271 *wl); int wl1271_acx_tx_config_options(struct wl1271 *wl);
int wl1271_acx_mem_cfg(struct wl1271 *wl); int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
int wl1271_acx_init_mem_config(struct wl1271 *wl); int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
int wl1271_acx_smart_reflex(struct wl1271 *wl); int wl1271_acx_smart_reflex(struct wl1271 *wl);
@ -1269,5 +1289,6 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
bool enable); bool enable);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
int wl1271_acx_max_tx_retry(struct wl1271 *wl); int wl1271_acx_max_tx_retry(struct wl1271 *wl);
int wl1271_acx_config_ps(struct wl1271 *wl);
#endif /* __WL1271_ACX_H__ */ #endif /* __WL1271_ACX_H__ */

View File

@ -286,6 +286,7 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
join->rx_filter_options = cpu_to_le32(wl->rx_filter); join->rx_filter_options = cpu_to_le32(wl->rx_filter);
join->bss_type = bss_type; join->bss_type = bss_type;
join->basic_rate_set = cpu_to_le32(wl->basic_rate_set); join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
join->supported_rate_set = cpu_to_le32(wl->rate_set);
if (wl->band == IEEE80211_BAND_5GHZ) if (wl->band == IEEE80211_BAND_5GHZ)
join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
@ -303,6 +304,9 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
wl->tx_security_last_seq = 0; wl->tx_security_last_seq = 0;
wl->tx_security_seq = 0; wl->tx_security_seq = 0;
wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
join->basic_rate_set, join->supported_rate_set);
ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
if (ret < 0) { if (ret < 0) {
wl1271_error("failed to initiate cmd join"); wl1271_error("failed to initiate cmd join");
@ -454,7 +458,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
return ret; return ret;
} }
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send) int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
{ {
struct wl1271_cmd_ps_params *ps_params = NULL; struct wl1271_cmd_ps_params *ps_params = NULL;
int ret = 0; int ret = 0;
@ -468,10 +472,6 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
} }
ps_params->ps_mode = ps_mode; ps_params->ps_mode = ps_mode;
ps_params->send_null_data = send;
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, ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
sizeof(*ps_params), 0); sizeof(*ps_params), 0);

View File

@ -39,7 +39,7 @@ 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_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_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send); int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
size_t len); size_t len);
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
@ -140,6 +140,7 @@ enum cmd_templ {
* For CTS-to-self (FastCTS) mechanism * For CTS-to-self (FastCTS) mechanism
* for BT/WLAN coexistence (SoftGemini). */ * for BT/WLAN coexistence (SoftGemini). */
CMD_TEMPL_ARP_RSP, CMD_TEMPL_ARP_RSP,
CMD_TEMPL_LINK_MEASUREMENT_REPORT,
/* AP-mode specific */ /* AP-mode specific */
CMD_TEMPL_AP_BEACON = 13, CMD_TEMPL_AP_BEACON = 13,
@ -216,6 +217,7 @@ struct wl1271_cmd_join {
* ACK or CTS frames). * ACK or CTS frames).
*/ */
__le32 basic_rate_set; __le32 basic_rate_set;
__le32 supported_rate_set;
u8 dtim_interval; u8 dtim_interval;
/* /*
* bits 0-2: This bitwise field specifies the type * bits 0-2: This bitwise field specifies the type
@ -278,15 +280,7 @@ struct wl1271_cmd_ps_params {
struct wl1271_cmd_header header; struct wl1271_cmd_header header;
u8 ps_mode; /* STATION_* */ u8 ps_mode; /* STATION_* */
u8 send_null_data; /* Do we have to send NULL data packet ? */ u8 padding[3];
u8 retries; /* Number of retires for the initial NULL data packet */
/*
* TUs during which the target stays awake after switching
* to power save mode.
*/
u8 hang_over_period;
__le32 null_data_rate;
} __packed; } __packed;
/* HW encryption keys */ /* HW encryption keys */

View File

@ -959,6 +959,14 @@ struct conf_conn_settings {
*/ */
u8 psm_entry_retries; u8 psm_entry_retries;
/*
* Specifies the maximum number of times to try PSM exit if it fails
* (if sending the appropriate null-func message fails.)
*
* Range 0 - 255
*/
u8 psm_exit_retries;
/* /*
* Specifies the maximum number of times to try transmit the PSM entry * Specifies the maximum number of times to try transmit the PSM entry
* null-func frame for each PSM entry attempt * null-func frame for each PSM entry attempt
@ -1143,6 +1151,46 @@ struct conf_ht_setting {
u16 inactivity_timeout; u16 inactivity_timeout;
}; };
struct conf_memory_settings {
/* Number of stations supported in IBSS mode */
u8 num_stations;
/* Number of ssid profiles used in IBSS mode */
u8 ssid_profiles;
/* Number of memory buffers allocated to rx pool */
u8 rx_block_num;
/* Minimum number of blocks allocated to tx pool */
u8 tx_min_block_num;
/* Disable/Enable dynamic memory */
u8 dynamic_memory;
/*
* Minimum required free tx memory blocks in order to assure optimum
* performence
*
* Range: 0-120
*/
u8 min_req_tx_blocks;
/*
* Minimum required free rx memory blocks in order to assure optimum
* performence
*
* Range: 0-120
*/
u8 min_req_rx_blocks;
/*
* Minimum number of mem blocks (free+used) guaranteed for TX
*
* Range: 0-120
*/
u8 tx_min;
};
struct conf_drv_settings { struct conf_drv_settings {
struct conf_sg_settings sg; struct conf_sg_settings sg;
struct conf_rx_settings rx; struct conf_rx_settings rx;
@ -1154,6 +1202,7 @@ struct conf_drv_settings {
struct conf_scan_settings scan; struct conf_scan_settings scan;
struct conf_rf_settings rf; struct conf_rf_settings rf;
struct conf_ht_setting ht; struct conf_ht_setting ht;
struct conf_memory_settings mem;
}; };
#endif #endif

View File

@ -135,20 +135,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
/* go to extremely low power mode */ /* go to extremely low power mode */
wl1271_ps_elp_sleep(wl); wl1271_ps_elp_sleep(wl);
break; break;
case EVENT_EXIT_POWER_SAVE_FAIL:
wl1271_debug(DEBUG_PSM, "PSM exit failed");
if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
wl->psm_entry_retry = 0;
break;
}
/* 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,
wl->basic_rate, false);
break;
case EVENT_EXIT_POWER_SAVE_SUCCESS:
default: default:
break; break;
} }

View File

@ -75,8 +75,6 @@ enum {
enum { enum {
EVENT_ENTER_POWER_SAVE_FAIL = 0, EVENT_ENTER_POWER_SAVE_FAIL = 0,
EVENT_ENTER_POWER_SAVE_SUCCESS, EVENT_ENTER_POWER_SAVE_SUCCESS,
EVENT_EXIT_POWER_SAVE_FAIL,
EVENT_EXIT_POWER_SAVE_SUCCESS,
}; };
struct event_debug_report { struct event_debug_report {

View File

@ -325,6 +325,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
return ret; return ret;
/* PS config */
ret = wl1271_acx_config_ps(wl);
if (ret < 0)
return ret;
ret = wl1271_sta_init_templates_config(wl); ret = wl1271_sta_init_templates_config(wl);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -367,6 +372,10 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = wl1271_acx_sta_mem_cfg(wl);
if (ret < 0)
return ret;
return 0; return 0;
} }
@ -433,6 +442,10 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = wl1271_acx_ap_mem_cfg(wl);
if (ret < 0)
return ret;
return 0; return 0;
} }

View File

@ -256,6 +256,7 @@ static struct conf_drv_settings default_conf = {
.bet_enable = CONF_BET_MODE_ENABLE, .bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 10, .bet_max_consecutive = 10,
.psm_entry_retries = 5, .psm_entry_retries = 5,
.psm_exit_retries = 255,
.psm_entry_nullfunc_retries = 3, .psm_entry_nullfunc_retries = 3,
.psm_entry_hangover_period = 1, .psm_entry_hangover_period = 1,
.keep_alive_interval = 55000, .keep_alive_interval = 55000,
@ -297,6 +298,16 @@ static struct conf_drv_settings default_conf = {
.tx_ba_win_size = 64, .tx_ba_win_size = 64,
.inactivity_timeout = 10000, .inactivity_timeout = 10000,
}, },
.mem = {
.num_stations = 1,
.ssid_profiles = 1,
.rx_block_num = 70,
.tx_min_block_num = 40,
.dynamic_memory = 0,
.min_req_tx_blocks = 104,
.min_req_rx_blocks = 22,
.tx_min = 27,
}
}; };
static void __wl1271_op_remove_interface(struct wl1271 *wl); static void __wl1271_op_remove_interface(struct wl1271 *wl);
@ -523,13 +534,19 @@ static int wl1271_plt_init(struct wl1271 *wl)
} }
static void wl1271_fw_status(struct wl1271 *wl, static void wl1271_fw_status(struct wl1271 *wl,
struct wl1271_fw_status *status) struct wl1271_fw_full_status *full_status)
{ {
struct wl1271_fw_common_status *status = &full_status->common;
struct timespec ts; struct timespec ts;
u32 total = 0; u32 total = 0;
int i; int i;
wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); if (wl->bss_type == BSS_TYPE_AP_BSS)
wl1271_raw_read(wl, FW_STATUS_ADDR, status,
sizeof(struct wl1271_fw_ap_status), false);
else
wl1271_raw_read(wl, FW_STATUS_ADDR, status,
sizeof(struct wl1271_fw_sta_status), false);
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)", "drv_rx_counter = %d, tx_results_counter = %d)",
@ -588,7 +605,7 @@ static void wl1271_irq_work(struct work_struct *work)
loopcount--; loopcount--;
wl1271_fw_status(wl, wl->fw_status); wl1271_fw_status(wl, wl->fw_status);
intr = le32_to_cpu(wl->fw_status->intr); intr = le32_to_cpu(wl->fw_status->common.intr);
if (!intr) { if (!intr) {
wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
spin_lock_irqsave(&wl->wl_lock, flags); spin_lock_irqsave(&wl->wl_lock, flags);
@ -610,7 +627,7 @@ static void wl1271_irq_work(struct work_struct *work)
wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
/* check for tx results */ /* check for tx results */
if (wl->fw_status->tx_results_counter != if (wl->fw_status->common.tx_results_counter !=
(wl->tx_results_count & 0xff)) (wl->tx_results_count & 0xff))
wl1271_tx_complete(wl); wl1271_tx_complete(wl);
@ -624,7 +641,7 @@ static void wl1271_irq_work(struct work_struct *work)
wl1271_tx_work_locked(wl); wl1271_tx_work_locked(wl);
} }
wl1271_rx(wl, wl->fw_status); wl1271_rx(wl, &wl->fw_status->common);
} }
if (intr & WL1271_ACX_INTR_EVENT_A) { if (intr & WL1271_ACX_INTR_EVENT_A) {
@ -961,39 +978,10 @@ int wl1271_plt_stop(struct wl1271 *wl)
static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{ {
struct wl1271 *wl = hw->priv; struct wl1271 *wl = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = txinfo->control.sta;
unsigned long flags; unsigned long flags;
int q; int q;
/*
* peek into the rates configured in the STA entry.
* The rates set after connection stage, The first block only BG sets:
* the compare is for bit 0-16 of sta_rate_set. The second block add
* HT rates in case of HT supported.
*/
spin_lock_irqsave(&wl->wl_lock, flags); spin_lock_irqsave(&wl->wl_lock, flags);
if (sta &&
(sta->supp_rates[conf->channel->band] !=
(wl->sta_rate_set & HW_BG_RATES_MASK)) &&
wl->bss_type != BSS_TYPE_AP_BSS) {
wl->sta_rate_set = sta->supp_rates[conf->channel->band];
set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
}
#ifdef CONFIG_WL12XX_HT
if (sta &&
sta->ht_cap.ht_supported &&
((wl->sta_rate_set >> HW_HT_RATES_OFFSET) !=
sta->ht_cap.mcs.rx_mask[0])) {
/* Clean MCS bits before setting them */
wl->sta_rate_set &= HW_BG_RATES_MASK;
wl->sta_rate_set |=
(sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
}
#endif
wl->tx_queue_count++; wl->tx_queue_count++;
spin_unlock_irqrestore(&wl->wl_lock, flags); spin_unlock_irqrestore(&wl->wl_lock, flags);
@ -1228,7 +1216,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
wl->time_offset = 0; wl->time_offset = 0;
wl->session_counter = 0; wl->session_counter = 0;
wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->rate_set = CONF_TX_RATE_MASK_BASIC;
wl->sta_rate_set = 0;
wl->flags = 0; wl->flags = 0;
wl->vif = NULL; wl->vif = NULL;
wl->filters = 0; wl->filters = 0;
@ -1415,7 +1402,6 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
goto out; goto out;
} }
wl->rate_set = wl1271_tx_min_rate_get(wl); wl->rate_set = wl1271_tx_min_rate_get(wl);
wl->sta_rate_set = 0;
ret = wl1271_acx_sta_rate_policies(wl); ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0) if (ret < 0)
goto out; goto out;
@ -2229,6 +2215,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
{ {
bool do_join = false, set_assoc = false; bool do_join = false, set_assoc = false;
bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
u32 sta_rate_set = 0;
int ret; int ret;
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
@ -2294,6 +2281,49 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
} }
} }
rcu_read_lock();
sta = ieee80211_find_sta(vif, bss_conf->bssid);
if (sta) {
/* save the supp_rates of the ap */
sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band];
if (sta->ht_cap.ht_supported)
sta_rate_set |=
(sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
/* handle new association with HT and HT information change */
if ((changed & BSS_CHANGED_HT) &&
(bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap,
true);
if (ret < 0) {
wl1271_warning("Set ht cap true failed %d",
ret);
rcu_read_unlock();
goto out;
}
ret = wl1271_acx_set_ht_information(wl,
bss_conf->ht_operation_mode);
if (ret < 0) {
wl1271_warning("Set ht information failed %d",
ret);
rcu_read_unlock();
goto out;
}
}
/* handle new association without HT and disassociation */
else if (changed & BSS_CHANGED_ASSOC) {
ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap,
false);
if (ret < 0) {
wl1271_warning("Set ht cap false failed %d",
ret);
rcu_read_unlock();
goto out;
}
}
}
rcu_read_unlock();
if ((changed & BSS_CHANGED_ASSOC)) { if ((changed & BSS_CHANGED_ASSOC)) {
if (bss_conf->assoc) { if (bss_conf->assoc) {
u32 rates; u32 rates;
@ -2311,6 +2341,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
rates); rates);
wl->basic_rate = wl1271_tx_min_rate_get(wl); wl->basic_rate = wl1271_tx_min_rate_get(wl);
if (sta_rate_set)
wl->rate_set = wl1271_tx_enabled_rates_get(wl,
sta_rate_set);
ret = wl1271_acx_sta_rate_policies(wl); ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0) if (ret < 0)
goto out; goto out;
@ -2389,43 +2422,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if (ret < 0) if (ret < 0)
goto out; goto out;
rcu_read_lock();
sta = ieee80211_find_sta(vif, bss_conf->bssid);
if (sta) {
/* handle new association with HT and HT information change */
if ((changed & BSS_CHANGED_HT) &&
(bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap,
true);
if (ret < 0) {
wl1271_warning("Set ht cap true failed %d",
ret);
rcu_read_unlock();
goto out;
}
ret = wl1271_acx_set_ht_information(wl,
bss_conf->ht_operation_mode);
if (ret < 0) {
wl1271_warning("Set ht information failed %d",
ret);
rcu_read_unlock();
goto out;
}
}
/* handle new association without HT and disassociation */
else if (changed & BSS_CHANGED_ASSOC) {
ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap,
false);
if (ret < 0) {
wl1271_warning("Set ht cap false failed %d",
ret);
rcu_read_unlock();
goto out;
}
}
}
rcu_read_unlock();
if (changed & BSS_CHANGED_ARP_FILTER) { if (changed & BSS_CHANGED_ARP_FILTER) {
__be32 addr = bss_conf->arp_addr_list[0]; __be32 addr = bss_conf->arp_addr_list[0];
WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
@ -3313,7 +3309,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
wl->basic_rate = CONF_TX_RATE_MASK_BASIC; wl->basic_rate = CONF_TX_RATE_MASK_BASIC;
wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->rate_set = CONF_TX_RATE_MASK_BASIC;
wl->sta_rate_set = 0;
wl->band = IEEE80211_BAND_2GHZ; wl->band = IEEE80211_BAND_2GHZ;
wl->vif = NULL; wl->vif = NULL;
wl->flags = 0; wl->flags = 0;

View File

@ -139,8 +139,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
return ret; return ret;
} }
ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
rates, send);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -163,8 +162,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
rates, send);
if (ret < 0) if (ret < 0)
return ret; return ret;

View File

@ -29,14 +29,14 @@
#include "rx.h" #include "rx.h"
#include "io.h" #include "io.h"
static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status,
u32 drv_rx_counter) u32 drv_rx_counter)
{ {
return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
RX_MEM_BLOCK_MASK; RX_MEM_BLOCK_MASK;
} }
static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status,
u32 drv_rx_counter) u32 drv_rx_counter)
{ {
return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
@ -134,7 +134,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
return 0; return 0;
} }
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
{ {
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
u32 buf_size; u32 buf_size;

View File

@ -119,7 +119,7 @@ struct wl1271_rx_descriptor {
u8 reserved; u8 reserved;
} __packed; } __packed;
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
void wl1271_set_default_filters(struct wl1271 *wl); void wl1271_set_default_filters(struct wl1271 *wl);

View File

@ -334,35 +334,13 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
{ {
struct sk_buff *skb; struct sk_buff *skb;
bool woken_up = false; bool woken_up = false;
u32 sta_rates = 0;
u32 buf_offset = 0; u32 buf_offset = 0;
bool sent_packets = false; bool sent_packets = false;
int ret; int ret;
/* check if the rates supported by the AP have changed */
if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED,
&wl->flags))) {
unsigned long flags;
spin_lock_irqsave(&wl->wl_lock, flags);
sta_rates = wl->sta_rate_set;
spin_unlock_irqrestore(&wl->wl_lock, flags);
}
if (unlikely(wl->state == WL1271_STATE_OFF)) if (unlikely(wl->state == WL1271_STATE_OFF))
goto out; goto out;
/* if rates have changed, re-configure the rate policy */
if (unlikely(sta_rates)) {
ret = wl1271_ps_elp_wakeup(wl, false);
if (ret < 0)
goto out;
woken_up = true;
wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
wl1271_acx_sta_rate_policies(wl);
}
while ((skb = wl1271_skb_dequeue(wl))) { while ((skb = wl1271_skb_dequeue(wl))) {
if (!woken_up) { if (!woken_up) {
ret = wl1271_ps_elp_wakeup(wl, false); ret = wl1271_ps_elp_wakeup(wl, false);

View File

@ -130,7 +130,7 @@ extern u32 wl12xx_debug_level;
#define WL1271_FW_NAME "wl1271-fw.bin" #define WL1271_FW_NAME "wl1271-fw-2.bin"
#define WL1271_AP_FW_NAME "wl1271-fw-ap.bin" #define WL1271_AP_FW_NAME "wl1271-fw-ap.bin"
#define WL1271_NVS_NAME "wl1271-nvs.bin" #define WL1271_NVS_NAME "wl1271-nvs.bin"
@ -214,8 +214,8 @@ struct wl1271_stats {
/* Broadcast and Global links + links to stations */ /* Broadcast and Global links + links to stations */
#define AP_MAX_LINKS (AP_MAX_STATIONS + 2) #define AP_MAX_LINKS (AP_MAX_STATIONS + 2)
/* FW status registers */ /* FW status registers common for AP/STA */
struct wl1271_fw_status { struct wl1271_fw_common_status {
__le32 intr; __le32 intr;
u8 fw_rx_counter; u8 fw_rx_counter;
u8 drv_rx_counter; u8 drv_rx_counter;
@ -224,6 +224,11 @@ struct wl1271_fw_status {
__le32 rx_pkt_descs[NUM_RX_PKT_DESC]; __le32 rx_pkt_descs[NUM_RX_PKT_DESC];
__le32 tx_released_blks[NUM_TX_QUEUES]; __le32 tx_released_blks[NUM_TX_QUEUES];
__le32 fw_localtime; __le32 fw_localtime;
} __packed;
/* FW status registers for AP */
struct wl1271_fw_ap_status {
struct wl1271_fw_common_status common;
/* Next fields valid only in AP FW */ /* Next fields valid only in AP FW */
@ -238,6 +243,24 @@ struct wl1271_fw_status {
u8 padding_1[1]; u8 padding_1[1];
} __packed; } __packed;
/* FW status registers for STA */
struct wl1271_fw_sta_status {
struct wl1271_fw_common_status common;
u8 tx_total;
u8 reserved1;
__le16 reserved2;
} __packed;
struct wl1271_fw_full_status {
union {
struct wl1271_fw_common_status common;
struct wl1271_fw_sta_status sta;
struct wl1271_fw_ap_status ap;
};
} __packed;
struct wl1271_rx_mem_pool_addr { struct wl1271_rx_mem_pool_addr {
u32 addr; u32 addr;
u32 addr_extra; u32 addr_extra;
@ -278,6 +301,24 @@ struct wl1271_ap_key {
u16 tx_seq_16; u16 tx_seq_16;
}; };
enum wl12xx_flags {
WL1271_FLAG_STA_ASSOCIATED,
WL1271_FLAG_JOINED,
WL1271_FLAG_GPIO_POWER,
WL1271_FLAG_TX_QUEUE_STOPPED,
WL1271_FLAG_IN_ELP,
WL1271_FLAG_PSM,
WL1271_FLAG_PSM_REQUESTED,
WL1271_FLAG_IRQ_PENDING,
WL1271_FLAG_IRQ_RUNNING,
WL1271_FLAG_IDLE,
WL1271_FLAG_IDLE_REQUESTED,
WL1271_FLAG_PSPOLL_FAILURE,
WL1271_FLAG_STA_STATE_SENT,
WL1271_FLAG_FW_TX_BUSY,
WL1271_FLAG_AP_STARTED
};
struct wl1271 { struct wl1271 {
struct platform_device *plat_dev; struct platform_device *plat_dev;
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
@ -296,22 +337,6 @@ struct wl1271 {
enum wl1271_state state; enum wl1271_state state;
struct mutex mutex; struct mutex mutex;
#define WL1271_FLAG_STA_RATES_CHANGED (0)
#define WL1271_FLAG_STA_ASSOCIATED (1)
#define WL1271_FLAG_JOINED (2)
#define WL1271_FLAG_GPIO_POWER (3)
#define WL1271_FLAG_TX_QUEUE_STOPPED (4)
#define WL1271_FLAG_IN_ELP (5)
#define WL1271_FLAG_PSM (6)
#define WL1271_FLAG_PSM_REQUESTED (7)
#define WL1271_FLAG_IRQ_PENDING (8)
#define WL1271_FLAG_IRQ_RUNNING (9)
#define WL1271_FLAG_IDLE (10)
#define WL1271_FLAG_IDLE_REQUESTED (11)
#define WL1271_FLAG_PSPOLL_FAILURE (12)
#define WL1271_FLAG_STA_STATE_SENT (13)
#define WL1271_FLAG_FW_TX_BUSY (14)
#define WL1271_FLAG_AP_STARTED (15)
unsigned long flags; unsigned long flags;
struct wl1271_partition_set part; struct wl1271_partition_set part;
@ -405,7 +430,6 @@ struct wl1271 {
* bits 16-23 - 802.11n MCS index mask * bits 16-23 - 802.11n MCS index mask
* support only 1 stream, thus only 8 bits for the MCS rates (0-7). * support only 1 stream, thus only 8 bits for the MCS rates (0-7).
*/ */
u32 sta_rate_set;
u32 basic_rate_set; u32 basic_rate_set;
u32 basic_rate; u32 basic_rate;
u32 rate_set; u32 rate_set;
@ -445,7 +469,7 @@ struct wl1271 {
u32 buffer_cmd; u32 buffer_cmd;
u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
struct wl1271_fw_status *fw_status; struct wl1271_fw_full_status *fw_status;
struct wl1271_tx_hw_res_if *tx_res_if; struct wl1271_tx_hw_res_if *tx_res_if;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;