aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorNishant Sarmukadam <nishants@marvell.com>2011-03-17 14:58:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-03-30 14:15:13 -0400
commit5faa1aff08ef8d82b98ac2dfd7beb62ae6eda5e5 (patch)
tree3b984311fb21200ca6ee7fa3ac0602de779a8500 /drivers/net/wireless/mwl8k.c
parent8a7a578c2e3ac463a17fe30b11ada0509658a952 (diff)
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>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 9db66d58f0ef..944ad030e4dd 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -135,6 +135,14 @@ struct mwl8k_tx_queue {
135 struct sk_buff **skb; 135 struct sk_buff **skb;
136}; 136};
137 137
138struct mwl8k_ampdu_stream {
139 struct ieee80211_sta *sta;
140 u8 tid;
141 u8 state;
142 u8 idx;
143 u8 txq_idx; /* index of this stream in priv->txq */
144};
145
138struct mwl8k_priv { 146struct mwl8k_priv {
139 struct ieee80211_hw *hw; 147 struct ieee80211_hw *hw;
140 struct pci_dev *pdev; 148 struct pci_dev *pdev;
@@ -360,6 +368,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
360#define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ 368#define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */
361#define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ 369#define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */
362#define MWL8K_CMD_UPDATE_STADB 0x1123 370#define MWL8K_CMD_UPDATE_STADB 0x1123
371#define MWL8K_CMD_BASTREAM 0x1125
363 372
364static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) 373static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
365{ 374{
@@ -399,6 +408,7 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
399 MWL8K_CMDNAME(SET_NEW_STN); 408 MWL8K_CMDNAME(SET_NEW_STN);
400 MWL8K_CMDNAME(UPDATE_ENCRYPTION); 409 MWL8K_CMDNAME(UPDATE_ENCRYPTION);
401 MWL8K_CMDNAME(UPDATE_STADB); 410 MWL8K_CMDNAME(UPDATE_STADB);
411 MWL8K_CMDNAME(BASTREAM);
402 default: 412 default:
403 snprintf(buf, bufsize, "0x%x", cmd); 413 snprintf(buf, bufsize, "0x%x", cmd);
404 } 414 }
@@ -3176,6 +3186,152 @@ static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw,
3176} 3186}
3177 3187
3178/* 3188/*
3189 * CMD_BASTREAM.
3190 */
3191
3192/*
3193 * UPSTREAM is tx direction
3194 */
3195#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00
3196#define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01
3197
3198enum {
3199 MWL8K_BA_CREATE,
3200 MWL8K_BA_UPDATE,
3201 MWL8K_BA_DESTROY,
3202 MWL8K_BA_FLUSH,
3203 MWL8K_BA_CHECK,
3204} ba_stream_action_type;
3205
3206
3207struct mwl8k_create_ba_stream {
3208 __le32 flags;
3209 __le32 idle_thrs;
3210 __le32 bar_thrs;
3211 __le32 window_size;
3212 u8 peer_mac_addr[6];
3213 u8 dialog_token;
3214 u8 tid;
3215 u8 queue_id;
3216 u8 param_info;
3217 __le32 ba_context;
3218 u8 reset_seq_no_flag;
3219 __le16 curr_seq_no;
3220 u8 sta_src_mac_addr[6];
3221} __packed;
3222
3223struct mwl8k_destroy_ba_stream {
3224 __le32 flags;
3225 __le32 ba_context;
3226} __packed;
3227
3228struct mwl8k_cmd_bastream {
3229 struct mwl8k_cmd_pkt header;
3230 __le32 action;
3231 union {
3232 struct mwl8k_create_ba_stream create_params;
3233 struct mwl8k_destroy_ba_stream destroy_params;
3234 };
3235} __packed;
3236
3237static int
3238mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
3239{
3240 struct mwl8k_cmd_bastream *cmd;
3241 int rc;
3242
3243 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3244 if (cmd == NULL)
3245 return -ENOMEM;
3246
3247 cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
3248 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3249
3250 cmd->action = cpu_to_le32(MWL8K_BA_CHECK);
3251
3252 cmd->create_params.queue_id = stream->idx;
3253 memcpy(&cmd->create_params.peer_mac_addr[0], stream->sta->addr,
3254 ETH_ALEN);
3255 cmd->create_params.tid = stream->tid;
3256
3257 cmd->create_params.flags =
3258 cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE) |
3259 cpu_to_le32(BASTREAM_FLAG_DIRECTION_UPSTREAM);
3260
3261 rc = mwl8k_post_cmd(hw, &cmd->header);
3262
3263 kfree(cmd);
3264
3265 return rc;
3266}
3267
3268static int
3269mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
3270 u8 buf_size)
3271{
3272 struct mwl8k_cmd_bastream *cmd;
3273 int rc;
3274
3275 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3276 if (cmd == NULL)
3277 return -ENOMEM;
3278
3279
3280 cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
3281 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3282
3283 cmd->action = cpu_to_le32(MWL8K_BA_CREATE);
3284
3285 cmd->create_params.bar_thrs = cpu_to_le32((u32)buf_size);
3286 cmd->create_params.window_size = cpu_to_le32((u32)buf_size);
3287 cmd->create_params.queue_id = stream->idx;
3288
3289 memcpy(cmd->create_params.peer_mac_addr, stream->sta->addr, ETH_ALEN);
3290 cmd->create_params.tid = stream->tid;
3291 cmd->create_params.curr_seq_no = cpu_to_le16(0);
3292 cmd->create_params.reset_seq_no_flag = 1;
3293
3294 cmd->create_params.param_info =
3295 (stream->sta->ht_cap.ampdu_factor &
3296 IEEE80211_HT_AMPDU_PARM_FACTOR) |
3297 ((stream->sta->ht_cap.ampdu_density << 2) &
3298 IEEE80211_HT_AMPDU_PARM_DENSITY);
3299
3300 cmd->create_params.flags =
3301 cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE |
3302 BASTREAM_FLAG_DIRECTION_UPSTREAM);
3303
3304 rc = mwl8k_post_cmd(hw, &cmd->header);
3305
3306 wiphy_debug(hw->wiphy, "Created a BA stream for %pM : tid %d\n",
3307 stream->sta->addr, stream->tid);
3308 kfree(cmd);
3309
3310 return rc;
3311}
3312
3313static void mwl8k_destroy_ba(struct ieee80211_hw *hw,
3314 struct mwl8k_ampdu_stream *stream)
3315{
3316 struct mwl8k_cmd_bastream *cmd;
3317
3318 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3319 if (cmd == NULL)
3320 return;
3321
3322 cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
3323 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3324 cmd->action = cpu_to_le32(MWL8K_BA_DESTROY);
3325
3326 cmd->destroy_params.ba_context = cpu_to_le32(stream->idx);
3327 mwl8k_post_cmd(hw, &cmd->header);
3328
3329 wiphy_debug(hw->wiphy, "Deleted BA stream index %d\n", stream->idx);
3330
3331 kfree(cmd);
3332}
3333
3334/*
3179 * CMD_SET_NEW_STN. 3335 * CMD_SET_NEW_STN.
3180 */ 3336 */
3181struct mwl8k_cmd_set_new_stn { 3337struct mwl8k_cmd_set_new_stn {