diff options
author | Nishant Sarmukadam <nishants@marvell.com> | 2011-03-17 14:58:43 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-03-30 14:15:13 -0400 |
commit | 5faa1aff08ef8d82b98ac2dfd7beb62ae6eda5e5 (patch) | |
tree | 3b984311fb21200ca6ee7fa3ac0602de779a8500 /drivers/net/wireless/mwl8k.c | |
parent | 8a7a578c2e3ac463a17fe30b11ada0509658a952 (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.c | 156 |
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 | ||
138 | struct 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 | |||
138 | struct mwl8k_priv { | 146 | struct 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 | ||
364 | static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) | 373 | static 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 | |||
3198 | enum { | ||
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 | |||
3207 | struct 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 | |||
3223 | struct mwl8k_destroy_ba_stream { | ||
3224 | __le32 flags; | ||
3225 | __le32 ba_context; | ||
3226 | } __packed; | ||
3227 | |||
3228 | struct 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 | |||
3237 | static int | ||
3238 | mwl8k_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 | |||
3268 | static int | ||
3269 | mwl8k_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 | |||
3313 | static 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 | */ |
3181 | struct mwl8k_cmd_set_new_stn { | 3337 | struct mwl8k_cmd_set_new_stn { |