mwl8k: add support for block ack commands

Signed-off-by: Pradeep Nemavat <pnemavat@marvell.com>
Signed-off-by: Brian Cavagnolo <brian@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Nishant Sarmukadam 2011-03-17 11:58:43 -07:00 committed by John W. Linville
parent 8a7a578c2e
commit 5faa1aff08

View File

@ -135,6 +135,14 @@ struct mwl8k_tx_queue {
struct sk_buff **skb;
};
struct mwl8k_ampdu_stream {
struct ieee80211_sta *sta;
u8 tid;
u8 state;
u8 idx;
u8 txq_idx; /* index of this stream in priv->txq */
};
struct mwl8k_priv {
struct ieee80211_hw *hw;
struct pci_dev *pdev;
@ -360,6 +368,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
#define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */
#define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */
#define MWL8K_CMD_UPDATE_STADB 0x1123
#define MWL8K_CMD_BASTREAM 0x1125
static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
{
@ -399,6 +408,7 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
MWL8K_CMDNAME(SET_NEW_STN);
MWL8K_CMDNAME(UPDATE_ENCRYPTION);
MWL8K_CMDNAME(UPDATE_STADB);
MWL8K_CMDNAME(BASTREAM);
default:
snprintf(buf, bufsize, "0x%x", cmd);
}
@ -3175,6 +3185,152 @@ static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw,
return rc;
}
/*
* CMD_BASTREAM.
*/
/*
* UPSTREAM is tx direction
*/
#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00
#define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01
enum {
MWL8K_BA_CREATE,
MWL8K_BA_UPDATE,
MWL8K_BA_DESTROY,
MWL8K_BA_FLUSH,
MWL8K_BA_CHECK,
} ba_stream_action_type;
struct mwl8k_create_ba_stream {
__le32 flags;
__le32 idle_thrs;
__le32 bar_thrs;
__le32 window_size;
u8 peer_mac_addr[6];
u8 dialog_token;
u8 tid;
u8 queue_id;
u8 param_info;
__le32 ba_context;
u8 reset_seq_no_flag;
__le16 curr_seq_no;
u8 sta_src_mac_addr[6];
} __packed;
struct mwl8k_destroy_ba_stream {
__le32 flags;
__le32 ba_context;
} __packed;
struct mwl8k_cmd_bastream {
struct mwl8k_cmd_pkt header;
__le32 action;
union {
struct mwl8k_create_ba_stream create_params;
struct mwl8k_destroy_ba_stream destroy_params;
};
} __packed;
static int
mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
{
struct mwl8k_cmd_bastream *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le32(MWL8K_BA_CHECK);
cmd->create_params.queue_id = stream->idx;
memcpy(&cmd->create_params.peer_mac_addr[0], stream->sta->addr,
ETH_ALEN);
cmd->create_params.tid = stream->tid;
cmd->create_params.flags =
cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE) |
cpu_to_le32(BASTREAM_FLAG_DIRECTION_UPSTREAM);
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
return rc;
}
static int
mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
u8 buf_size)
{
struct mwl8k_cmd_bastream *cmd;
int rc;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return -ENOMEM;
cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le32(MWL8K_BA_CREATE);
cmd->create_params.bar_thrs = cpu_to_le32((u32)buf_size);
cmd->create_params.window_size = cpu_to_le32((u32)buf_size);
cmd->create_params.queue_id = stream->idx;
memcpy(cmd->create_params.peer_mac_addr, stream->sta->addr, ETH_ALEN);
cmd->create_params.tid = stream->tid;
cmd->create_params.curr_seq_no = cpu_to_le16(0);
cmd->create_params.reset_seq_no_flag = 1;
cmd->create_params.param_info =
(stream->sta->ht_cap.ampdu_factor &
IEEE80211_HT_AMPDU_PARM_FACTOR) |
((stream->sta->ht_cap.ampdu_density << 2) &
IEEE80211_HT_AMPDU_PARM_DENSITY);
cmd->create_params.flags =
cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE |
BASTREAM_FLAG_DIRECTION_UPSTREAM);
rc = mwl8k_post_cmd(hw, &cmd->header);
wiphy_debug(hw->wiphy, "Created a BA stream for %pM : tid %d\n",
stream->sta->addr, stream->tid);
kfree(cmd);
return rc;
}
static void mwl8k_destroy_ba(struct ieee80211_hw *hw,
struct mwl8k_ampdu_stream *stream)
{
struct mwl8k_cmd_bastream *cmd;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (cmd == NULL)
return;
cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le32(MWL8K_BA_DESTROY);
cmd->destroy_params.ba_context = cpu_to_le32(stream->idx);
mwl8k_post_cmd(hw, &cmd->header);
wiphy_debug(hw->wiphy, "Deleted BA stream index %d\n", stream->idx);
kfree(cmd);
}
/*
* CMD_SET_NEW_STN.
*/