| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: ISC |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. |
|---|
| 3 | | - * Copyright (c) 2018, The Linux Foundation. All rights reserved. |
|---|
| 4 | | - * |
|---|
| 5 | | - * Permission to use, copy, modify, and/or distribute this software for any |
|---|
| 6 | | - * purpose with or without fee is hereby granted, provided that the above |
|---|
| 7 | | - * copyright notice and this permission notice appear in all copies. |
|---|
| 8 | | - * |
|---|
| 9 | | - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|---|
| 10 | | - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|---|
| 11 | | - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|---|
| 12 | | - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|---|
| 13 | | - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|---|
| 14 | | - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|---|
| 15 | | - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|---|
| 4 | + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
|---|
| 16 | 5 | */ |
|---|
| 17 | 6 | |
|---|
| 18 | 7 | #include "wil6210.h" |
|---|
| .. | .. |
|---|
| 260 | 249 | r->reorder_buf = |
|---|
| 261 | 250 | kcalloc(size, sizeof(struct sk_buff *), GFP_KERNEL); |
|---|
| 262 | 251 | if (!r->reorder_buf) { |
|---|
| 263 | | - kfree(r->reorder_buf); |
|---|
| 264 | 252 | kfree(r); |
|---|
| 265 | 253 | return NULL; |
|---|
| 266 | 254 | } |
|---|
| .. | .. |
|---|
| 307 | 295 | } |
|---|
| 308 | 296 | |
|---|
| 309 | 297 | /* Block Ack - Rx side (recipient) */ |
|---|
| 310 | | -int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, |
|---|
| 311 | | - u8 cidxtid, u8 dialog_token, __le16 ba_param_set, |
|---|
| 298 | +int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid, u8 cid, u8 tid, |
|---|
| 299 | + u8 dialog_token, __le16 ba_param_set, |
|---|
| 312 | 300 | __le16 ba_timeout, __le16 ba_seq_ctrl) |
|---|
| 313 | 301 | __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) |
|---|
| 314 | 302 | { |
|---|
| .. | .. |
|---|
| 316 | 304 | u16 agg_timeout = le16_to_cpu(ba_timeout); |
|---|
| 317 | 305 | u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl); |
|---|
| 318 | 306 | struct wil_sta_info *sta; |
|---|
| 319 | | - u8 cid, tid; |
|---|
| 320 | | - u16 agg_wsize = 0; |
|---|
| 307 | + u16 agg_wsize; |
|---|
| 321 | 308 | /* bit 0: A-MSDU supported |
|---|
| 322 | 309 | * bit 1: policy (should be 0 for us) |
|---|
| 323 | 310 | * bits 2..5: TID |
|---|
| .. | .. |
|---|
| 329 | 316 | test_bit(WMI_FW_CAPABILITY_AMSDU, wil->fw_capabilities) && |
|---|
| 330 | 317 | wil->amsdu_en && (param_set & BIT(0)); |
|---|
| 331 | 318 | int ba_policy = param_set & BIT(1); |
|---|
| 332 | | - u16 status = WLAN_STATUS_SUCCESS; |
|---|
| 333 | 319 | u16 ssn = seq_ctrl >> 4; |
|---|
| 334 | 320 | struct wil_tid_ampdu_rx *r; |
|---|
| 335 | 321 | int rc = 0; |
|---|
| 336 | 322 | |
|---|
| 337 | 323 | might_sleep(); |
|---|
| 338 | | - parse_cidxtid(cidxtid, &cid, &tid); |
|---|
| 339 | 324 | |
|---|
| 340 | 325 | /* sanity checks */ |
|---|
| 341 | | - if (cid >= WIL6210_MAX_CID) { |
|---|
| 326 | + if (cid >= wil->max_assoc_sta) { |
|---|
| 342 | 327 | wil_err(wil, "BACK: invalid CID %d\n", cid); |
|---|
| 343 | 328 | rc = -EINVAL; |
|---|
| 344 | 329 | goto out; |
|---|
| .. | .. |
|---|
| 357 | 342 | agg_amsdu ? "+" : "-", !!ba_policy, dialog_token, ssn); |
|---|
| 358 | 343 | |
|---|
| 359 | 344 | /* apply policies */ |
|---|
| 360 | | - if (ba_policy) { |
|---|
| 361 | | - wil_err(wil, "BACK requested unsupported ba_policy == 1\n"); |
|---|
| 362 | | - status = WLAN_STATUS_INVALID_QOS_PARAM; |
|---|
| 363 | | - } |
|---|
| 364 | | - if (status == WLAN_STATUS_SUCCESS) { |
|---|
| 365 | | - if (req_agg_wsize == 0) { |
|---|
| 366 | | - wil_dbg_misc(wil, "Suggest BACK wsize %d\n", |
|---|
| 367 | | - wil->max_agg_wsize); |
|---|
| 368 | | - agg_wsize = wil->max_agg_wsize; |
|---|
| 369 | | - } else { |
|---|
| 370 | | - agg_wsize = min_t(u16, |
|---|
| 371 | | - wil->max_agg_wsize, req_agg_wsize); |
|---|
| 372 | | - } |
|---|
| 345 | + if (req_agg_wsize == 0) { |
|---|
| 346 | + wil_dbg_misc(wil, "Suggest BACK wsize %d\n", |
|---|
| 347 | + wil->max_agg_wsize); |
|---|
| 348 | + agg_wsize = wil->max_agg_wsize; |
|---|
| 349 | + } else { |
|---|
| 350 | + agg_wsize = min_t(u16, wil->max_agg_wsize, req_agg_wsize); |
|---|
| 373 | 351 | } |
|---|
| 374 | 352 | |
|---|
| 375 | 353 | rc = wil->txrx_ops.wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token, |
|---|
| 376 | | - status, agg_amsdu, agg_wsize, |
|---|
| 377 | | - agg_timeout); |
|---|
| 378 | | - if (rc || (status != WLAN_STATUS_SUCCESS)) { |
|---|
| 379 | | - wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc, |
|---|
| 380 | | - status); |
|---|
| 354 | + WLAN_STATUS_SUCCESS, agg_amsdu, |
|---|
| 355 | + agg_wsize, agg_timeout); |
|---|
| 356 | + if (rc) { |
|---|
| 357 | + wil_err(wil, "do not apply ba, rc(%d)\n", rc); |
|---|
| 381 | 358 | goto out; |
|---|
| 382 | 359 | } |
|---|
| 383 | 360 | |
|---|
| 384 | 361 | /* apply */ |
|---|
| 385 | | - r = wil_tid_ampdu_rx_alloc(wil, agg_wsize, ssn); |
|---|
| 386 | | - spin_lock_bh(&sta->tid_rx_lock); |
|---|
| 387 | | - wil_tid_ampdu_rx_free(wil, sta->tid_rx[tid]); |
|---|
| 388 | | - sta->tid_rx[tid] = r; |
|---|
| 389 | | - spin_unlock_bh(&sta->tid_rx_lock); |
|---|
| 362 | + if (!wil->use_rx_hw_reordering) { |
|---|
| 363 | + r = wil_tid_ampdu_rx_alloc(wil, agg_wsize, ssn); |
|---|
| 364 | + spin_lock_bh(&sta->tid_rx_lock); |
|---|
| 365 | + wil_tid_ampdu_rx_free(wil, sta->tid_rx[tid]); |
|---|
| 366 | + sta->tid_rx[tid] = r; |
|---|
| 367 | + spin_unlock_bh(&sta->tid_rx_lock); |
|---|
| 368 | + } |
|---|
| 390 | 369 | |
|---|
| 391 | 370 | out: |
|---|
| 392 | 371 | return rc; |
|---|