Skip to content

Commit

Permalink
wl12xx: BA initiator support
Browse files Browse the repository at this point in the history
Add 80211n BA initiator session support wl1271 driver.
Include BA supported FW version auto detection mechanism.
BA initiator session management included in FW independently.

Signed-off-by: Shahar Levi <shahar_levi@ti.com>
Reviewed-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
  • Loading branch information
Levi, Shahar authored and Luciano Coelho committed Jan 24, 2011
1 parent 6c89b7b commit 4b7fac7
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 10 deletions.
51 changes: 51 additions & 0 deletions drivers/net/wireless/wl12xx/acx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1342,6 +1342,57 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
return ret;
}

/* Configure BA session initiator/receiver parameters setting in the FW. */
int wl1271_acx_set_ba_session(struct wl1271 *wl,
enum ieee80211_back_parties direction,
u8 tid_index, u8 policy)
{
struct wl1271_acx_ba_session_policy *acx;
int ret;

wl1271_debug(DEBUG_ACX, "acx ba session setting");

acx = kzalloc(sizeof(*acx), GFP_KERNEL);
if (!acx) {
ret = -ENOMEM;
goto out;
}

/* ANY role */
acx->role_id = 0xff;
acx->tid = tid_index;
acx->enable = policy;
acx->ba_direction = direction;

switch (direction) {
case WLAN_BACK_INITIATOR:
acx->win_size = wl->conf.ht.tx_ba_win_size;
acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
break;
case WLAN_BACK_RECIPIENT:
acx->win_size = RX_BA_WIN_SIZE;
acx->inactivity_timeout = 0;
break;
default:
wl1271_error("Incorrect acx command id=%x\n", direction);
ret = -EINVAL;
goto out;
}

ret = wl1271_cmd_configure(wl,
ACX_BA_SESSION_POLICY_CFG,
acx,
sizeof(*acx));
if (ret < 0) {
wl1271_warning("acx ba session setting failed: %d", ret);
goto out;
}

out:
kfree(acx);
return ret;
}

int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
{
struct wl1271_acx_fw_tsf_information *tsf_info;
Expand Down
41 changes: 39 additions & 2 deletions drivers/net/wireless/wl12xx/acx.h
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,40 @@ struct wl1271_acx_ht_information {
u8 padding[3];
} __packed;

#define RX_BA_WIN_SIZE 8

struct wl1271_acx_ba_session_policy {
struct acx_header header;
/*
* Specifies role Id, Range 0-7, 0xFF means ANY role.
* Future use. For now this field is irrelevant
*/
u8 role_id;
/*
* Specifies Link Id, Range 0-31, 0xFF means ANY Link Id.
* Not applicable if Role Id is set to ANY.
*/
u8 link_id;

u8 tid;

u8 enable;

/* Windows size in number of packets */
u16 win_size;

/*
* As initiator inactivity timeout in time units(TU) of 1024us.
* As receiver reserved
*/
u16 inactivity_timeout;

/* Initiator = 1/Receiver = 0 */
u8 ba_direction;

u8 padding[3];
} __packed;

struct wl1271_acx_fw_tsf_information {
struct acx_header header;

Expand Down Expand Up @@ -1134,8 +1168,8 @@ enum {
ACX_RSSI_SNR_WEIGHTS = 0x0052,
ACX_KEEP_ALIVE_MODE = 0x0053,
ACX_SET_KEEP_ALIVE_CONFIG = 0x0054,
ACX_BA_SESSION_RESPONDER_POLICY = 0x0055,
ACX_BA_SESSION_INITIATOR_POLICY = 0x0056,
ACX_BA_SESSION_POLICY_CFG = 0x0055,
ACX_BA_SESSION_RX_SETUP = 0x0056,
ACX_PEER_HT_CAP = 0x0057,
ACX_HT_BSS_OPERATION = 0x0058,
ACX_COEX_ACTIVITY = 0x0059,
Expand Down Expand Up @@ -1209,6 +1243,9 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
bool allow_ht_operation);
int wl1271_acx_set_ht_information(struct wl1271 *wl,
u16 ht_operation_mode);
int wl1271_acx_set_ba_session(struct wl1271 *wl,
enum ieee80211_back_parties direction,
u8 tid_index, u8 policy);
int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
int wl1271_acx_max_tx_retry(struct wl1271 *wl);

Expand Down
24 changes: 21 additions & 3 deletions drivers/net/wireless/wl12xx/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,36 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
}

static void wl1271_parse_fw_ver(struct wl1271 *wl)
{
int ret;

ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u",
&wl->chip.fw_ver[0], &wl->chip.fw_ver[1],
&wl->chip.fw_ver[2], &wl->chip.fw_ver[3],
&wl->chip.fw_ver[4]);

if (ret != 5) {
wl1271_warning("fw version incorrect value");
memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
return;
}
}

static void wl1271_boot_fw_version(struct wl1271 *wl)
{
struct wl1271_static_data static_data;

wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data),
false);

strncpy(wl->chip.fw_ver, static_data.fw_version,
sizeof(wl->chip.fw_ver));
strncpy(wl->chip.fw_ver_str, static_data.fw_version,
sizeof(wl->chip.fw_ver_str));

/* make sure the string is NULL-terminated */
wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0';
wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0';

wl1271_parse_fw_ver(wl);
}

static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/wireless/wl12xx/conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,11 @@ struct conf_rf_settings {
u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
};

struct conf_ht_setting {
u16 tx_ba_win_size;
u16 inactivity_timeout;
};

struct conf_drv_settings {
struct conf_sg_settings sg;
struct conf_rx_settings rx;
Expand All @@ -1148,6 +1153,7 @@ struct conf_drv_settings {
struct conf_roam_trigger_settings roam_trigger;
struct conf_scan_settings scan;
struct conf_rf_settings rf;
struct conf_ht_setting ht;
};

#endif
42 changes: 42 additions & 0 deletions drivers/net/wireless/wl12xx/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,43 @@ static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
return 0;
}

static void wl1271_check_ba_support(struct wl1271 *wl)
{
/* validate FW cose ver x.x.x.50-60.x */
if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
(wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
wl->ba_support = true;
return;
}

wl->ba_support = false;
}

static int wl1271_set_ba_policies(struct wl1271 *wl)
{
u8 tid_index;
u8 ret = 0;

/* Reset the BA RX indicators */
wl->ba_allowed = true;
wl->ba_rx_bitmap = 0;

/* validate that FW support BA */
wl1271_check_ba_support(wl);

if (wl->ba_support)
/* 802.11n initiator BA session setting */
for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
++tid_index) {
ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
tid_index, true);
if (ret < 0)
break;
}

return ret;
}

int wl1271_hw_init(struct wl1271 *wl)
{
struct conf_tx_ac_category *conf_ac;
Expand Down Expand Up @@ -568,6 +605,11 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;

/* Configure initiator BA sessions policies */
ret = wl1271_set_ba_policies(wl);
if (ret < 0)
goto out_free_memmap;

return 0;

out_free_memmap:
Expand Down
12 changes: 8 additions & 4 deletions drivers/net/wireless/wl12xx/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ static struct conf_drv_settings default_conf = {
.avg_weight_rssi_beacon = 20,
.avg_weight_rssi_data = 10,
.avg_weight_snr_beacon = 20,
.avg_weight_snr_data = 10
.avg_weight_snr_data = 10,
},
.scan = {
.min_dwell_time_active = 7500,
Expand All @@ -293,6 +293,10 @@ static struct conf_drv_settings default_conf = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
.ht = {
.tx_ba_win_size = 64,
.inactivity_timeout = 10000,
},
};

static void __wl1271_op_remove_interface(struct wl1271 *wl);
Expand Down Expand Up @@ -890,7 +894,7 @@ int wl1271_plt_start(struct wl1271 *wl)

wl->state = WL1271_STATE_PLT;
wl1271_notice("firmware booted in PLT mode (%s)",
wl->chip.fw_ver);
wl->chip.fw_ver_str);
goto out;

irq_disable:
Expand Down Expand Up @@ -1138,11 +1142,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,

wl->vif = vif;
wl->state = WL1271_STATE_ON;
wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str);

/* update hw/fw version info in wiphy struct */
wiphy->hw_version = wl->chip.id;
strncpy(wiphy->fw_version, wl->chip.fw_ver,
strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
sizeof(wiphy->fw_version));

/*
Expand Down
17 changes: 16 additions & 1 deletion drivers/net/wireless/wl12xx/wl12xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@
#define DRIVER_NAME "wl1271"
#define DRIVER_PREFIX DRIVER_NAME ": "

/*
* FW versions support BA 11n
* versions marks x.x.x.50-60.x
*/
#define WL12XX_BA_SUPPORT_FW_COST_VER2_START 50
#define WL12XX_BA_SUPPORT_FW_COST_VER2_END 60

enum {
DEBUG_NONE = 0,
DEBUG_IRQ = BIT(0),
Expand Down Expand Up @@ -182,10 +189,13 @@ struct wl1271_partition_set {

struct wl1271;

#define WL12XX_NUM_FW_VER 5

/* FIXME: I'm not sure about this structure name */
struct wl1271_chip {
u32 id;
char fw_ver[21];
char fw_ver_str[ETHTOOL_BUSINFO_LEN];
unsigned int fw_ver[WL12XX_NUM_FW_VER];
};

struct wl1271_stats {
Expand Down Expand Up @@ -460,6 +470,11 @@ struct wl1271 {

/* bands supported by this instance of wl12xx */
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];

/* RX BA constraint value */
bool ba_support;
u8 ba_allowed;
u8 ba_rx_bitmap;
};

struct wl1271_station {
Expand Down

0 comments on commit 4b7fac7

Please sign in to comment.