| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: ISC |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2012-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 <linux/etherdevice.h> |
|---|
| .. | .. |
|---|
| 21 | 10 | #include <linux/moduleparam.h> |
|---|
| 22 | 11 | #include <linux/ip.h> |
|---|
| 23 | 12 | #include <linux/ipv6.h> |
|---|
| 13 | +#include <linux/if_vlan.h> |
|---|
| 24 | 14 | #include <net/ipv6.h> |
|---|
| 25 | 15 | #include <linux/prefetch.h> |
|---|
| 26 | 16 | |
|---|
| .. | .. |
|---|
| 30 | 20 | #include "trace.h" |
|---|
| 31 | 21 | #include "txrx_edma.h" |
|---|
| 32 | 22 | |
|---|
| 33 | | -static bool rtap_include_phy_info; |
|---|
| 34 | | -module_param(rtap_include_phy_info, bool, 0444); |
|---|
| 35 | | -MODULE_PARM_DESC(rtap_include_phy_info, |
|---|
| 36 | | - " Include PHY info in the radiotap header, default - no"); |
|---|
| 37 | | - |
|---|
| 38 | 23 | bool rx_align_2; |
|---|
| 39 | 24 | module_param(rx_align_2, bool, 0444); |
|---|
| 40 | 25 | MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no"); |
|---|
| .. | .. |
|---|
| 42 | 27 | bool rx_large_buf; |
|---|
| 43 | 28 | module_param(rx_large_buf, bool, 0444); |
|---|
| 44 | 29 | MODULE_PARM_DESC(rx_large_buf, " allocate 8KB RX buffers, default - no"); |
|---|
| 30 | + |
|---|
| 31 | +/* Drop Tx packets in case Tx ring is full */ |
|---|
| 32 | +bool drop_if_ring_full; |
|---|
| 45 | 33 | |
|---|
| 46 | 34 | static inline uint wil_rx_snaplen(void) |
|---|
| 47 | 35 | { |
|---|
| .. | .. |
|---|
| 261 | 249 | vring->ctx = NULL; |
|---|
| 262 | 250 | } |
|---|
| 263 | 251 | |
|---|
| 264 | | -/** |
|---|
| 265 | | - * Allocate one skb for Rx VRING |
|---|
| 252 | +/* Allocate one skb for Rx VRING |
|---|
| 266 | 253 | * |
|---|
| 267 | 254 | * Safe to call from IRQ |
|---|
| 268 | 255 | */ |
|---|
| .. | .. |
|---|
| 307 | 294 | return 0; |
|---|
| 308 | 295 | } |
|---|
| 309 | 296 | |
|---|
| 310 | | -/** |
|---|
| 311 | | - * Adds radiotap header |
|---|
| 297 | +/* Adds radiotap header |
|---|
| 312 | 298 | * |
|---|
| 313 | 299 | * Any error indicated as "Bad FCS" |
|---|
| 314 | 300 | * |
|---|
| .. | .. |
|---|
| 332 | 318 | u8 mcs_flags; |
|---|
| 333 | 319 | u8 mcs_index; |
|---|
| 334 | 320 | } __packed; |
|---|
| 335 | | - struct wil6210_rtap_vendor { |
|---|
| 336 | | - struct wil6210_rtap rtap; |
|---|
| 337 | | - /* vendor */ |
|---|
| 338 | | - u8 vendor_oui[3] __aligned(2); |
|---|
| 339 | | - u8 vendor_ns; |
|---|
| 340 | | - __le16 vendor_skip; |
|---|
| 341 | | - u8 vendor_data[0]; |
|---|
| 342 | | - } __packed; |
|---|
| 343 | 321 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
|---|
| 344 | | - struct wil6210_rtap_vendor *rtap_vendor; |
|---|
| 322 | + struct wil6210_rtap *rtap; |
|---|
| 345 | 323 | int rtap_len = sizeof(struct wil6210_rtap); |
|---|
| 346 | | - int phy_length = 0; /* phy info header size, bytes */ |
|---|
| 347 | | - static char phy_data[128]; |
|---|
| 348 | 324 | struct ieee80211_channel *ch = wil->monitor_chandef.chan; |
|---|
| 349 | | - |
|---|
| 350 | | - if (rtap_include_phy_info) { |
|---|
| 351 | | - rtap_len = sizeof(*rtap_vendor) + sizeof(*d); |
|---|
| 352 | | - /* calculate additional length */ |
|---|
| 353 | | - if (d->dma.status & RX_DMA_STATUS_PHY_INFO) { |
|---|
| 354 | | - /** |
|---|
| 355 | | - * PHY info starts from 8-byte boundary |
|---|
| 356 | | - * there are 8-byte lines, last line may be partially |
|---|
| 357 | | - * written (HW bug), thus FW configures for last line |
|---|
| 358 | | - * to be excessive. Driver skips this last line. |
|---|
| 359 | | - */ |
|---|
| 360 | | - int len = min_t(int, 8 + sizeof(phy_data), |
|---|
| 361 | | - wil_rxdesc_phy_length(d)); |
|---|
| 362 | | - |
|---|
| 363 | | - if (len > 8) { |
|---|
| 364 | | - void *p = skb_tail_pointer(skb); |
|---|
| 365 | | - void *pa = PTR_ALIGN(p, 8); |
|---|
| 366 | | - |
|---|
| 367 | | - if (skb_tailroom(skb) >= len + (pa - p)) { |
|---|
| 368 | | - phy_length = len - 8; |
|---|
| 369 | | - memcpy(phy_data, pa, phy_length); |
|---|
| 370 | | - } |
|---|
| 371 | | - } |
|---|
| 372 | | - } |
|---|
| 373 | | - rtap_len += phy_length; |
|---|
| 374 | | - } |
|---|
| 375 | 325 | |
|---|
| 376 | 326 | if (skb_headroom(skb) < rtap_len && |
|---|
| 377 | 327 | pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { |
|---|
| .. | .. |
|---|
| 379 | 329 | return; |
|---|
| 380 | 330 | } |
|---|
| 381 | 331 | |
|---|
| 382 | | - rtap_vendor = skb_push(skb, rtap_len); |
|---|
| 383 | | - memset(rtap_vendor, 0, rtap_len); |
|---|
| 332 | + rtap = skb_push(skb, rtap_len); |
|---|
| 333 | + memset(rtap, 0, rtap_len); |
|---|
| 384 | 334 | |
|---|
| 385 | | - rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION; |
|---|
| 386 | | - rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len); |
|---|
| 387 | | - rtap_vendor->rtap.rthdr.it_present = cpu_to_le32( |
|---|
| 388 | | - (1 << IEEE80211_RADIOTAP_FLAGS) | |
|---|
| 335 | + rtap->rthdr.it_version = PKTHDR_RADIOTAP_VERSION; |
|---|
| 336 | + rtap->rthdr.it_len = cpu_to_le16(rtap_len); |
|---|
| 337 | + rtap->rthdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | |
|---|
| 389 | 338 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
|---|
| 390 | 339 | (1 << IEEE80211_RADIOTAP_MCS)); |
|---|
| 391 | 340 | if (d->dma.status & RX_DMA_STATUS_ERROR) |
|---|
| 392 | | - rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS; |
|---|
| 341 | + rtap->flags |= IEEE80211_RADIOTAP_F_BADFCS; |
|---|
| 393 | 342 | |
|---|
| 394 | | - rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); |
|---|
| 395 | | - rtap_vendor->rtap.chnl_flags = cpu_to_le16(0); |
|---|
| 343 | + rtap->chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); |
|---|
| 344 | + rtap->chnl_flags = cpu_to_le16(0); |
|---|
| 396 | 345 | |
|---|
| 397 | | - rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; |
|---|
| 398 | | - rtap_vendor->rtap.mcs_flags = 0; |
|---|
| 399 | | - rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d); |
|---|
| 400 | | - |
|---|
| 401 | | - if (rtap_include_phy_info) { |
|---|
| 402 | | - rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 << |
|---|
| 403 | | - IEEE80211_RADIOTAP_VENDOR_NAMESPACE); |
|---|
| 404 | | - /* OUI for Wilocity 04:ce:14 */ |
|---|
| 405 | | - rtap_vendor->vendor_oui[0] = 0x04; |
|---|
| 406 | | - rtap_vendor->vendor_oui[1] = 0xce; |
|---|
| 407 | | - rtap_vendor->vendor_oui[2] = 0x14; |
|---|
| 408 | | - rtap_vendor->vendor_ns = 1; |
|---|
| 409 | | - /* Rx descriptor + PHY data */ |
|---|
| 410 | | - rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) + |
|---|
| 411 | | - phy_length); |
|---|
| 412 | | - memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d)); |
|---|
| 413 | | - memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data, |
|---|
| 414 | | - phy_length); |
|---|
| 415 | | - } |
|---|
| 346 | + rtap->mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; |
|---|
| 347 | + rtap->mcs_flags = 0; |
|---|
| 348 | + rtap->mcs_index = wil_rxdesc_mcs(d); |
|---|
| 416 | 349 | } |
|---|
| 417 | 350 | |
|---|
| 418 | 351 | static bool wil_is_rx_idle(struct wil6210_priv *wil) |
|---|
| .. | .. |
|---|
| 427 | 360 | return true; |
|---|
| 428 | 361 | } |
|---|
| 429 | 362 | |
|---|
| 430 | | -/** |
|---|
| 431 | | - * reap 1 frame from @swhead |
|---|
| 363 | +static int wil_rx_get_cid_by_skb(struct wil6210_priv *wil, struct sk_buff *skb) |
|---|
| 364 | +{ |
|---|
| 365 | + struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
|---|
| 366 | + int mid = wil_rxdesc_mid(d); |
|---|
| 367 | + struct wil6210_vif *vif = wil->vifs[mid]; |
|---|
| 368 | + /* cid from DMA descriptor is limited to 3 bits. |
|---|
| 369 | + * In case of cid>=8, the value would be cid modulo 8 and we need to |
|---|
| 370 | + * find real cid by locating the transmitter (ta) inside sta array |
|---|
| 371 | + */ |
|---|
| 372 | + int cid = wil_rxdesc_cid(d); |
|---|
| 373 | + unsigned int snaplen = wil_rx_snaplen(); |
|---|
| 374 | + struct ieee80211_hdr_3addr *hdr; |
|---|
| 375 | + int i; |
|---|
| 376 | + unsigned char *ta; |
|---|
| 377 | + u8 ftype; |
|---|
| 378 | + |
|---|
| 379 | + /* in monitor mode there are no connections */ |
|---|
| 380 | + if (vif->wdev.iftype == NL80211_IFTYPE_MONITOR) |
|---|
| 381 | + return cid; |
|---|
| 382 | + |
|---|
| 383 | + ftype = wil_rxdesc_ftype(d) << 2; |
|---|
| 384 | + if (likely(ftype == IEEE80211_FTYPE_DATA)) { |
|---|
| 385 | + if (unlikely(skb->len < ETH_HLEN + snaplen)) { |
|---|
| 386 | + wil_err_ratelimited(wil, |
|---|
| 387 | + "Short data frame, len = %d\n", |
|---|
| 388 | + skb->len); |
|---|
| 389 | + return -ENOENT; |
|---|
| 390 | + } |
|---|
| 391 | + ta = wil_skb_get_sa(skb); |
|---|
| 392 | + } else { |
|---|
| 393 | + if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { |
|---|
| 394 | + wil_err_ratelimited(wil, "Short frame, len = %d\n", |
|---|
| 395 | + skb->len); |
|---|
| 396 | + return -ENOENT; |
|---|
| 397 | + } |
|---|
| 398 | + hdr = (void *)skb->data; |
|---|
| 399 | + ta = hdr->addr2; |
|---|
| 400 | + } |
|---|
| 401 | + |
|---|
| 402 | + if (wil->max_assoc_sta <= WIL6210_RX_DESC_MAX_CID) |
|---|
| 403 | + return cid; |
|---|
| 404 | + |
|---|
| 405 | + /* assuming no concurrency between AP interfaces and STA interfaces. |
|---|
| 406 | + * multista is used only in P2P_GO or AP mode. In other modes return |
|---|
| 407 | + * cid from the rx descriptor |
|---|
| 408 | + */ |
|---|
| 409 | + if (vif->wdev.iftype != NL80211_IFTYPE_P2P_GO && |
|---|
| 410 | + vif->wdev.iftype != NL80211_IFTYPE_AP) |
|---|
| 411 | + return cid; |
|---|
| 412 | + |
|---|
| 413 | + /* For Rx packets cid from rx descriptor is limited to 3 bits (0..7), |
|---|
| 414 | + * to find the real cid, compare transmitter address with the stored |
|---|
| 415 | + * stations mac address in the driver sta array |
|---|
| 416 | + */ |
|---|
| 417 | + for (i = cid; i < wil->max_assoc_sta; i += WIL6210_RX_DESC_MAX_CID) { |
|---|
| 418 | + if (wil->sta[i].status != wil_sta_unused && |
|---|
| 419 | + ether_addr_equal(wil->sta[i].addr, ta)) { |
|---|
| 420 | + cid = i; |
|---|
| 421 | + break; |
|---|
| 422 | + } |
|---|
| 423 | + } |
|---|
| 424 | + if (i >= wil->max_assoc_sta) { |
|---|
| 425 | + wil_err_ratelimited(wil, "Could not find cid for frame with transmit addr = %pM, iftype = %d, frametype = %d, len = %d\n", |
|---|
| 426 | + ta, vif->wdev.iftype, ftype, skb->len); |
|---|
| 427 | + cid = -ENOENT; |
|---|
| 428 | + } |
|---|
| 429 | + |
|---|
| 430 | + return cid; |
|---|
| 431 | +} |
|---|
| 432 | + |
|---|
| 433 | +/* reap 1 frame from @swhead |
|---|
| 432 | 434 | * |
|---|
| 433 | 435 | * Rx descriptor copied to skb->cb |
|---|
| 434 | 436 | * |
|---|
| .. | .. |
|---|
| 452 | 454 | int i; |
|---|
| 453 | 455 | struct wil_net_stats *stats; |
|---|
| 454 | 456 | |
|---|
| 455 | | - BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); |
|---|
| 457 | + BUILD_BUG_ON(sizeof(struct skb_rx_info) > sizeof(skb->cb)); |
|---|
| 456 | 458 | |
|---|
| 457 | 459 | again: |
|---|
| 458 | 460 | if (unlikely(wil_ring_is_empty(vring))) |
|---|
| .. | .. |
|---|
| 484 | 486 | wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, |
|---|
| 485 | 487 | (const void *)d, sizeof(*d), false); |
|---|
| 486 | 488 | |
|---|
| 487 | | - cid = wil_rxdesc_cid(d); |
|---|
| 488 | 489 | mid = wil_rxdesc_mid(d); |
|---|
| 489 | 490 | vif = wil->vifs[mid]; |
|---|
| 490 | 491 | |
|---|
| .. | .. |
|---|
| 495 | 496 | goto again; |
|---|
| 496 | 497 | } |
|---|
| 497 | 498 | ndev = vif_to_ndev(vif); |
|---|
| 498 | | - stats = &wil->sta[cid].stats; |
|---|
| 499 | | - |
|---|
| 500 | 499 | if (unlikely(dmalen > sz)) { |
|---|
| 501 | | - wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); |
|---|
| 502 | | - stats->rx_large_frame++; |
|---|
| 500 | + wil_err_ratelimited(wil, "Rx size too large: %d bytes!\n", |
|---|
| 501 | + dmalen); |
|---|
| 503 | 502 | kfree_skb(skb); |
|---|
| 504 | 503 | goto again; |
|---|
| 505 | 504 | } |
|---|
| .. | .. |
|---|
| 509 | 508 | |
|---|
| 510 | 509 | wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, |
|---|
| 511 | 510 | skb->data, skb_headlen(skb), false); |
|---|
| 511 | + |
|---|
| 512 | + cid = wil_rx_get_cid_by_skb(wil, skb); |
|---|
| 513 | + if (cid == -ENOENT) { |
|---|
| 514 | + kfree_skb(skb); |
|---|
| 515 | + goto again; |
|---|
| 516 | + } |
|---|
| 517 | + wil_skb_set_cid(skb, (u8)cid); |
|---|
| 518 | + stats = &wil->sta[cid].stats; |
|---|
| 512 | 519 | |
|---|
| 513 | 520 | stats->last_mcs_rx = wil_rxdesc_mcs(d); |
|---|
| 514 | 521 | if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) |
|---|
| .. | .. |
|---|
| 556 | 563 | goto again; |
|---|
| 557 | 564 | } |
|---|
| 558 | 565 | |
|---|
| 559 | | - if (unlikely(skb->len < ETH_HLEN + snaplen)) { |
|---|
| 560 | | - wil_err(wil, "Short frame, len = %d\n", skb->len); |
|---|
| 561 | | - stats->rx_short_frame++; |
|---|
| 562 | | - kfree_skb(skb); |
|---|
| 563 | | - goto again; |
|---|
| 564 | | - } |
|---|
| 565 | | - |
|---|
| 566 | 566 | /* L4 IDENT is on when HW calculated checksum, check status |
|---|
| 567 | 567 | * and in case of error drop the packet |
|---|
| 568 | 568 | * higher stack layers will handle retransmission (if required) |
|---|
| .. | .. |
|---|
| 594 | 594 | return skb; |
|---|
| 595 | 595 | } |
|---|
| 596 | 596 | |
|---|
| 597 | | -/** |
|---|
| 598 | | - * allocate and fill up to @count buffers in rx ring |
|---|
| 597 | +/* allocate and fill up to @count buffers in rx ring |
|---|
| 599 | 598 | * buffers posted at @swtail |
|---|
| 600 | 599 | * Note: we have a single RX queue for servicing all VIFs, but we |
|---|
| 601 | 600 | * allocate skbs with headroom according to main interface only. This |
|---|
| .. | .. |
|---|
| 659 | 658 | static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb) |
|---|
| 660 | 659 | { |
|---|
| 661 | 660 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
|---|
| 662 | | - int cid = wil_rxdesc_cid(d); |
|---|
| 661 | + int cid = wil_skb_get_cid(skb); |
|---|
| 663 | 662 | int tid = wil_rxdesc_tid(d); |
|---|
| 664 | 663 | int key_id = wil_rxdesc_key_id(d); |
|---|
| 665 | 664 | int mc = wil_rxdesc_mcast(d); |
|---|
| .. | .. |
|---|
| 667 | 666 | struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx : |
|---|
| 668 | 667 | &s->tid_crypto_rx[tid]; |
|---|
| 669 | 668 | struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id]; |
|---|
| 670 | | - const u8 *pn = (u8 *)&d->mac.pn_15_0; |
|---|
| 669 | + const u8 *pn = (u8 *)&d->mac.pn; |
|---|
| 671 | 670 | |
|---|
| 672 | 671 | if (!cc->key_set) { |
|---|
| 673 | 672 | wil_err_ratelimited(wil, |
|---|
| .. | .. |
|---|
| 707 | 706 | { |
|---|
| 708 | 707 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
|---|
| 709 | 708 | |
|---|
| 710 | | - *cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */ |
|---|
| 709 | + *cid = wil_skb_get_cid(skb); |
|---|
| 711 | 710 | *security = wil_rxdesc_security(d); |
|---|
| 711 | +} |
|---|
| 712 | + |
|---|
| 713 | +/* |
|---|
| 714 | + * Check if skb is ptk eapol key message |
|---|
| 715 | + * |
|---|
| 716 | + * returns a pointer to the start of the eapol key structure, NULL |
|---|
| 717 | + * if frame is not PTK eapol key |
|---|
| 718 | + */ |
|---|
| 719 | +static struct wil_eapol_key *wil_is_ptk_eapol_key(struct wil6210_priv *wil, |
|---|
| 720 | + struct sk_buff *skb) |
|---|
| 721 | +{ |
|---|
| 722 | + u8 *buf; |
|---|
| 723 | + const struct wil_1x_hdr *hdr; |
|---|
| 724 | + struct wil_eapol_key *key; |
|---|
| 725 | + u16 key_info; |
|---|
| 726 | + int len = skb->len; |
|---|
| 727 | + |
|---|
| 728 | + if (!skb_mac_header_was_set(skb)) { |
|---|
| 729 | + wil_err(wil, "mac header was not set\n"); |
|---|
| 730 | + return NULL; |
|---|
| 731 | + } |
|---|
| 732 | + |
|---|
| 733 | + len -= skb_mac_offset(skb); |
|---|
| 734 | + |
|---|
| 735 | + if (len < sizeof(struct ethhdr) + sizeof(struct wil_1x_hdr) + |
|---|
| 736 | + sizeof(struct wil_eapol_key)) |
|---|
| 737 | + return NULL; |
|---|
| 738 | + |
|---|
| 739 | + buf = skb_mac_header(skb) + sizeof(struct ethhdr); |
|---|
| 740 | + |
|---|
| 741 | + hdr = (const struct wil_1x_hdr *)buf; |
|---|
| 742 | + if (hdr->type != WIL_1X_TYPE_EAPOL_KEY) |
|---|
| 743 | + return NULL; |
|---|
| 744 | + |
|---|
| 745 | + key = (struct wil_eapol_key *)(buf + sizeof(struct wil_1x_hdr)); |
|---|
| 746 | + if (key->type != WIL_EAPOL_KEY_TYPE_WPA && |
|---|
| 747 | + key->type != WIL_EAPOL_KEY_TYPE_RSN) |
|---|
| 748 | + return NULL; |
|---|
| 749 | + |
|---|
| 750 | + key_info = be16_to_cpu(key->key_info); |
|---|
| 751 | + if (!(key_info & WIL_KEY_INFO_KEY_TYPE)) /* check if pairwise */ |
|---|
| 752 | + return NULL; |
|---|
| 753 | + |
|---|
| 754 | + return key; |
|---|
| 755 | +} |
|---|
| 756 | + |
|---|
| 757 | +static bool wil_skb_is_eap_3(struct wil6210_priv *wil, struct sk_buff *skb) |
|---|
| 758 | +{ |
|---|
| 759 | + struct wil_eapol_key *key; |
|---|
| 760 | + u16 key_info; |
|---|
| 761 | + |
|---|
| 762 | + key = wil_is_ptk_eapol_key(wil, skb); |
|---|
| 763 | + if (!key) |
|---|
| 764 | + return false; |
|---|
| 765 | + |
|---|
| 766 | + key_info = be16_to_cpu(key->key_info); |
|---|
| 767 | + if (key_info & (WIL_KEY_INFO_MIC | |
|---|
| 768 | + WIL_KEY_INFO_ENCR_KEY_DATA)) { |
|---|
| 769 | + /* 3/4 of 4-Way Handshake */ |
|---|
| 770 | + wil_dbg_misc(wil, "EAPOL key message 3\n"); |
|---|
| 771 | + return true; |
|---|
| 772 | + } |
|---|
| 773 | + /* 1/4 of 4-Way Handshake */ |
|---|
| 774 | + wil_dbg_misc(wil, "EAPOL key message 1\n"); |
|---|
| 775 | + |
|---|
| 776 | + return false; |
|---|
| 777 | +} |
|---|
| 778 | + |
|---|
| 779 | +static bool wil_skb_is_eap_4(struct wil6210_priv *wil, struct sk_buff *skb) |
|---|
| 780 | +{ |
|---|
| 781 | + struct wil_eapol_key *key; |
|---|
| 782 | + u32 *nonce, i; |
|---|
| 783 | + |
|---|
| 784 | + key = wil_is_ptk_eapol_key(wil, skb); |
|---|
| 785 | + if (!key) |
|---|
| 786 | + return false; |
|---|
| 787 | + |
|---|
| 788 | + nonce = (u32 *)key->key_nonce; |
|---|
| 789 | + for (i = 0; i < WIL_EAP_NONCE_LEN / sizeof(u32); i++, nonce++) { |
|---|
| 790 | + if (*nonce != 0) { |
|---|
| 791 | + /* message 2/4 */ |
|---|
| 792 | + wil_dbg_misc(wil, "EAPOL key message 2\n"); |
|---|
| 793 | + return false; |
|---|
| 794 | + } |
|---|
| 795 | + } |
|---|
| 796 | + wil_dbg_misc(wil, "EAPOL key message 4\n"); |
|---|
| 797 | + |
|---|
| 798 | + return true; |
|---|
| 799 | +} |
|---|
| 800 | + |
|---|
| 801 | +void wil_enable_tx_key_worker(struct work_struct *work) |
|---|
| 802 | +{ |
|---|
| 803 | + struct wil6210_vif *vif = container_of(work, |
|---|
| 804 | + struct wil6210_vif, enable_tx_key_worker); |
|---|
| 805 | + struct wil6210_priv *wil = vif_to_wil(vif); |
|---|
| 806 | + int rc, cid; |
|---|
| 807 | + |
|---|
| 808 | + rtnl_lock(); |
|---|
| 809 | + if (vif->ptk_rekey_state != WIL_REKEY_WAIT_M4_SENT) { |
|---|
| 810 | + wil_dbg_misc(wil, "Invalid rekey state = %d\n", |
|---|
| 811 | + vif->ptk_rekey_state); |
|---|
| 812 | + rtnl_unlock(); |
|---|
| 813 | + return; |
|---|
| 814 | + } |
|---|
| 815 | + |
|---|
| 816 | + cid = wil_find_cid_by_idx(wil, vif->mid, 0); |
|---|
| 817 | + if (!wil_cid_valid(wil, cid)) { |
|---|
| 818 | + wil_err(wil, "Invalid cid = %d\n", cid); |
|---|
| 819 | + rtnl_unlock(); |
|---|
| 820 | + return; |
|---|
| 821 | + } |
|---|
| 822 | + |
|---|
| 823 | + wil_dbg_misc(wil, "Apply PTK key after eapol was sent out\n"); |
|---|
| 824 | + rc = wmi_add_cipher_key(vif, 0, wil->sta[cid].addr, 0, NULL, |
|---|
| 825 | + WMI_KEY_USE_APPLY_PTK); |
|---|
| 826 | + |
|---|
| 827 | + vif->ptk_rekey_state = WIL_REKEY_IDLE; |
|---|
| 828 | + rtnl_unlock(); |
|---|
| 829 | + |
|---|
| 830 | + if (rc) |
|---|
| 831 | + wil_err(wil, "Apply PTK key failed %d\n", rc); |
|---|
| 832 | +} |
|---|
| 833 | + |
|---|
| 834 | +void wil_tx_complete_handle_eapol(struct wil6210_vif *vif, struct sk_buff *skb) |
|---|
| 835 | +{ |
|---|
| 836 | + struct wil6210_priv *wil = vif_to_wil(vif); |
|---|
| 837 | + struct wireless_dev *wdev = vif_to_wdev(vif); |
|---|
| 838 | + bool q = false; |
|---|
| 839 | + |
|---|
| 840 | + if (wdev->iftype != NL80211_IFTYPE_STATION || |
|---|
| 841 | + !test_bit(WMI_FW_CAPABILITY_SPLIT_REKEY, wil->fw_capabilities)) |
|---|
| 842 | + return; |
|---|
| 843 | + |
|---|
| 844 | + /* check if skb is an EAP message 4/4 */ |
|---|
| 845 | + if (!wil_skb_is_eap_4(wil, skb)) |
|---|
| 846 | + return; |
|---|
| 847 | + |
|---|
| 848 | + spin_lock_bh(&wil->eap_lock); |
|---|
| 849 | + switch (vif->ptk_rekey_state) { |
|---|
| 850 | + case WIL_REKEY_IDLE: |
|---|
| 851 | + /* ignore idle state, can happen due to M4 retransmission */ |
|---|
| 852 | + break; |
|---|
| 853 | + case WIL_REKEY_M3_RECEIVED: |
|---|
| 854 | + vif->ptk_rekey_state = WIL_REKEY_IDLE; |
|---|
| 855 | + break; |
|---|
| 856 | + case WIL_REKEY_WAIT_M4_SENT: |
|---|
| 857 | + q = true; |
|---|
| 858 | + break; |
|---|
| 859 | + default: |
|---|
| 860 | + wil_err(wil, "Unknown rekey state = %d", |
|---|
| 861 | + vif->ptk_rekey_state); |
|---|
| 862 | + } |
|---|
| 863 | + spin_unlock_bh(&wil->eap_lock); |
|---|
| 864 | + |
|---|
| 865 | + if (q) { |
|---|
| 866 | + q = queue_work(wil->wmi_wq, &vif->enable_tx_key_worker); |
|---|
| 867 | + wil_dbg_misc(wil, "queue_work of enable_tx_key_worker -> %d\n", |
|---|
| 868 | + q); |
|---|
| 869 | + } |
|---|
| 870 | +} |
|---|
| 871 | + |
|---|
| 872 | +static void wil_rx_handle_eapol(struct wil6210_vif *vif, struct sk_buff *skb) |
|---|
| 873 | +{ |
|---|
| 874 | + struct wil6210_priv *wil = vif_to_wil(vif); |
|---|
| 875 | + struct wireless_dev *wdev = vif_to_wdev(vif); |
|---|
| 876 | + |
|---|
| 877 | + if (wdev->iftype != NL80211_IFTYPE_STATION || |
|---|
| 878 | + !test_bit(WMI_FW_CAPABILITY_SPLIT_REKEY, wil->fw_capabilities)) |
|---|
| 879 | + return; |
|---|
| 880 | + |
|---|
| 881 | + /* check if skb is a EAP message 3/4 */ |
|---|
| 882 | + if (!wil_skb_is_eap_3(wil, skb)) |
|---|
| 883 | + return; |
|---|
| 884 | + |
|---|
| 885 | + if (vif->ptk_rekey_state == WIL_REKEY_IDLE) |
|---|
| 886 | + vif->ptk_rekey_state = WIL_REKEY_M3_RECEIVED; |
|---|
| 712 | 887 | } |
|---|
| 713 | 888 | |
|---|
| 714 | 889 | /* |
|---|
| 715 | 890 | * Pass Rx packet to the netif. Update statistics. |
|---|
| 716 | 891 | * Called in softirq context (NAPI poll). |
|---|
| 717 | 892 | */ |
|---|
| 718 | | -void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) |
|---|
| 893 | +void wil_netif_rx(struct sk_buff *skb, struct net_device *ndev, int cid, |
|---|
| 894 | + struct wil_net_stats *stats, bool gro) |
|---|
| 719 | 895 | { |
|---|
| 720 | | - gro_result_t rc = GRO_NORMAL; |
|---|
| 721 | 896 | struct wil6210_vif *vif = ndev_to_vif(ndev); |
|---|
| 722 | 897 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
|---|
| 723 | 898 | struct wireless_dev *wdev = vif_to_wdev(vif); |
|---|
| 724 | 899 | unsigned int len = skb->len; |
|---|
| 725 | | - int cid; |
|---|
| 726 | | - int security; |
|---|
| 727 | | - struct ethhdr *eth = (void *)skb->data; |
|---|
| 900 | + u8 *sa, *da = wil_skb_get_da(skb); |
|---|
| 728 | 901 | /* here looking for DA, not A1, thus Rxdesc's 'mcast' indication |
|---|
| 729 | 902 | * is not suitable, need to look at data |
|---|
| 730 | 903 | */ |
|---|
| 731 | | - int mcast = is_multicast_ether_addr(eth->h_dest); |
|---|
| 732 | | - struct wil_net_stats *stats; |
|---|
| 904 | + int mcast = is_multicast_ether_addr(da); |
|---|
| 733 | 905 | struct sk_buff *xmit_skb = NULL; |
|---|
| 734 | | - static const char * const gro_res_str[] = { |
|---|
| 735 | | - [GRO_MERGED] = "GRO_MERGED", |
|---|
| 736 | | - [GRO_MERGED_FREE] = "GRO_MERGED_FREE", |
|---|
| 737 | | - [GRO_HELD] = "GRO_HELD", |
|---|
| 738 | | - [GRO_NORMAL] = "GRO_NORMAL", |
|---|
| 739 | | - [GRO_DROP] = "GRO_DROP", |
|---|
| 740 | | - [GRO_CONSUMED] = "GRO_CONSUMED", |
|---|
| 741 | | - }; |
|---|
| 742 | | - |
|---|
| 743 | | - wil->txrx_ops.get_netif_rx_params(skb, &cid, &security); |
|---|
| 744 | | - |
|---|
| 745 | | - stats = &wil->sta[cid].stats; |
|---|
| 746 | | - |
|---|
| 747 | | - if (ndev->features & NETIF_F_RXHASH) |
|---|
| 748 | | - /* fake L4 to ensure it won't be re-calculated later |
|---|
| 749 | | - * set hash to any non-zero value to activate rps |
|---|
| 750 | | - * mechanism, core will be chosen according |
|---|
| 751 | | - * to user-level rps configuration. |
|---|
| 752 | | - */ |
|---|
| 753 | | - skb_set_hash(skb, 1, PKT_HASH_TYPE_L4); |
|---|
| 754 | | - |
|---|
| 755 | | - skb_orphan(skb); |
|---|
| 756 | | - |
|---|
| 757 | | - if (security && (wil->txrx_ops.rx_crypto_check(wil, skb) != 0)) { |
|---|
| 758 | | - rc = GRO_DROP; |
|---|
| 759 | | - dev_kfree_skb(skb); |
|---|
| 760 | | - stats->rx_replay++; |
|---|
| 761 | | - goto stats; |
|---|
| 762 | | - } |
|---|
| 763 | | - |
|---|
| 764 | | - /* check errors reported by HW and update statistics */ |
|---|
| 765 | | - if (unlikely(wil->txrx_ops.rx_error_check(wil, skb, stats))) { |
|---|
| 766 | | - dev_kfree_skb(skb); |
|---|
| 767 | | - return; |
|---|
| 768 | | - } |
|---|
| 769 | 906 | |
|---|
| 770 | 907 | if (wdev->iftype == NL80211_IFTYPE_STATION) { |
|---|
| 771 | | - if (mcast && ether_addr_equal(eth->h_source, ndev->dev_addr)) { |
|---|
| 908 | + sa = wil_skb_get_sa(skb); |
|---|
| 909 | + if (mcast && ether_addr_equal(sa, ndev->dev_addr)) { |
|---|
| 772 | 910 | /* mcast packet looped back to us */ |
|---|
| 773 | | - rc = GRO_DROP; |
|---|
| 774 | 911 | dev_kfree_skb(skb); |
|---|
| 775 | | - goto stats; |
|---|
| 912 | + ndev->stats.rx_dropped++; |
|---|
| 913 | + stats->rx_dropped++; |
|---|
| 914 | + wil_dbg_txrx(wil, "Rx drop %d bytes\n", len); |
|---|
| 915 | + return; |
|---|
| 776 | 916 | } |
|---|
| 777 | 917 | } else if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate) { |
|---|
| 778 | 918 | if (mcast) { |
|---|
| .. | .. |
|---|
| 781 | 921 | */ |
|---|
| 782 | 922 | xmit_skb = skb_copy(skb, GFP_ATOMIC); |
|---|
| 783 | 923 | } else { |
|---|
| 784 | | - int xmit_cid = wil_find_cid(wil, vif->mid, |
|---|
| 785 | | - eth->h_dest); |
|---|
| 924 | + int xmit_cid = wil_find_cid(wil, vif->mid, da); |
|---|
| 786 | 925 | |
|---|
| 787 | 926 | if (xmit_cid >= 0) { |
|---|
| 788 | 927 | /* The destination station is associated to |
|---|
| .. | .. |
|---|
| 812 | 951 | if (skb) { /* deliver to local stack */ |
|---|
| 813 | 952 | skb->protocol = eth_type_trans(skb, ndev); |
|---|
| 814 | 953 | skb->dev = ndev; |
|---|
| 815 | | - rc = napi_gro_receive(&wil->napi_rx, skb); |
|---|
| 816 | | - wil_dbg_txrx(wil, "Rx complete %d bytes => %s\n", |
|---|
| 817 | | - len, gro_res_str[rc]); |
|---|
| 954 | + |
|---|
| 955 | + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) |
|---|
| 956 | + wil_rx_handle_eapol(vif, skb); |
|---|
| 957 | + |
|---|
| 958 | + if (gro) |
|---|
| 959 | + napi_gro_receive(&wil->napi_rx, skb); |
|---|
| 960 | + else |
|---|
| 961 | + netif_rx_ni(skb); |
|---|
| 818 | 962 | } |
|---|
| 819 | | -stats: |
|---|
| 820 | | - /* statistics. rc set to GRO_NORMAL for AP bridging */ |
|---|
| 821 | | - if (unlikely(rc == GRO_DROP)) { |
|---|
| 822 | | - ndev->stats.rx_dropped++; |
|---|
| 823 | | - stats->rx_dropped++; |
|---|
| 824 | | - wil_dbg_txrx(wil, "Rx drop %d bytes\n", len); |
|---|
| 825 | | - } else { |
|---|
| 826 | | - ndev->stats.rx_packets++; |
|---|
| 827 | | - stats->rx_packets++; |
|---|
| 828 | | - ndev->stats.rx_bytes += len; |
|---|
| 829 | | - stats->rx_bytes += len; |
|---|
| 830 | | - if (mcast) |
|---|
| 831 | | - ndev->stats.multicast++; |
|---|
| 832 | | - } |
|---|
| 963 | + ndev->stats.rx_packets++; |
|---|
| 964 | + stats->rx_packets++; |
|---|
| 965 | + ndev->stats.rx_bytes += len; |
|---|
| 966 | + stats->rx_bytes += len; |
|---|
| 967 | + if (mcast) |
|---|
| 968 | + ndev->stats.multicast++; |
|---|
| 833 | 969 | } |
|---|
| 834 | 970 | |
|---|
| 835 | | -/** |
|---|
| 836 | | - * Proceed all completed skb's from Rx VRING |
|---|
| 971 | +void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) |
|---|
| 972 | +{ |
|---|
| 973 | + int cid, security; |
|---|
| 974 | + struct wil6210_priv *wil = ndev_to_wil(ndev); |
|---|
| 975 | + struct wil_net_stats *stats; |
|---|
| 976 | + |
|---|
| 977 | + wil->txrx_ops.get_netif_rx_params(skb, &cid, &security); |
|---|
| 978 | + |
|---|
| 979 | + stats = &wil->sta[cid].stats; |
|---|
| 980 | + |
|---|
| 981 | + skb_orphan(skb); |
|---|
| 982 | + |
|---|
| 983 | + if (security && (wil->txrx_ops.rx_crypto_check(wil, skb) != 0)) { |
|---|
| 984 | + wil_dbg_txrx(wil, "Rx drop %d bytes\n", skb->len); |
|---|
| 985 | + dev_kfree_skb(skb); |
|---|
| 986 | + ndev->stats.rx_dropped++; |
|---|
| 987 | + stats->rx_replay++; |
|---|
| 988 | + stats->rx_dropped++; |
|---|
| 989 | + return; |
|---|
| 990 | + } |
|---|
| 991 | + |
|---|
| 992 | + /* check errors reported by HW and update statistics */ |
|---|
| 993 | + if (unlikely(wil->txrx_ops.rx_error_check(wil, skb, stats))) { |
|---|
| 994 | + dev_kfree_skb(skb); |
|---|
| 995 | + return; |
|---|
| 996 | + } |
|---|
| 997 | + |
|---|
| 998 | + wil_netif_rx(skb, ndev, cid, stats, true); |
|---|
| 999 | +} |
|---|
| 1000 | + |
|---|
| 1001 | +/* Proceed all completed skb's from Rx VRING |
|---|
| 837 | 1002 | * |
|---|
| 838 | 1003 | * Safe to call from NAPI poll, i.e. softirq with interrupts enabled |
|---|
| 839 | 1004 | */ |
|---|
| .. | .. |
|---|
| 953 | 1118 | void wil_tx_data_init(struct wil_ring_tx_data *txdata) |
|---|
| 954 | 1119 | { |
|---|
| 955 | 1120 | spin_lock_bh(&txdata->lock); |
|---|
| 956 | | - txdata->dot1x_open = 0; |
|---|
| 1121 | + txdata->dot1x_open = false; |
|---|
| 957 | 1122 | txdata->enabled = 0; |
|---|
| 958 | 1123 | txdata->idle = 0; |
|---|
| 959 | 1124 | txdata->last_idle = 0; |
|---|
| .. | .. |
|---|
| 980 | 1145 | .ring_size = cpu_to_le16(size), |
|---|
| 981 | 1146 | }, |
|---|
| 982 | 1147 | .ringid = id, |
|---|
| 983 | | - .cidxtid = mk_cidxtid(cid, tid), |
|---|
| 984 | 1148 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, |
|---|
| 985 | 1149 | .mac_ctrl = 0, |
|---|
| 986 | 1150 | .to_resolution = 0, |
|---|
| .. | .. |
|---|
| 999 | 1163 | }; |
|---|
| 1000 | 1164 | struct wil_ring *vring = &wil->ring_tx[id]; |
|---|
| 1001 | 1165 | struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id]; |
|---|
| 1166 | + |
|---|
| 1167 | + if (cid >= WIL6210_RX_DESC_MAX_CID) { |
|---|
| 1168 | + cmd.vring_cfg.cidxtid = CIDXTID_EXTENDED_CID_TID; |
|---|
| 1169 | + cmd.vring_cfg.cid = cid; |
|---|
| 1170 | + cmd.vring_cfg.tid = tid; |
|---|
| 1171 | + } else { |
|---|
| 1172 | + cmd.vring_cfg.cidxtid = mk_cidxtid(cid, tid); |
|---|
| 1173 | + } |
|---|
| 1002 | 1174 | |
|---|
| 1003 | 1175 | wil_dbg_misc(wil, "vring_init_tx: max_mpdu_size %d\n", |
|---|
| 1004 | 1176 | cmd.vring_cfg.tx_sw_ring.max_mpdu_size); |
|---|
| .. | .. |
|---|
| 1025 | 1197 | if (!vif->privacy) |
|---|
| 1026 | 1198 | txdata->dot1x_open = true; |
|---|
| 1027 | 1199 | rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), |
|---|
| 1028 | | - WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); |
|---|
| 1200 | + WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), |
|---|
| 1201 | + WIL_WMI_CALL_GENERAL_TO_MS); |
|---|
| 1029 | 1202 | if (rc) |
|---|
| 1030 | 1203 | goto out_free; |
|---|
| 1031 | 1204 | |
|---|
| .. | .. |
|---|
| 1052 | 1225 | txdata->enabled = 0; |
|---|
| 1053 | 1226 | spin_unlock_bh(&txdata->lock); |
|---|
| 1054 | 1227 | wil_vring_free(wil, vring); |
|---|
| 1055 | | - wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; |
|---|
| 1228 | + wil->ring2cid_tid[id][0] = wil->max_assoc_sta; |
|---|
| 1056 | 1229 | wil->ring2cid_tid[id][1] = 0; |
|---|
| 1057 | 1230 | |
|---|
| 1058 | 1231 | out: |
|---|
| 1059 | 1232 | |
|---|
| 1233 | + return rc; |
|---|
| 1234 | +} |
|---|
| 1235 | + |
|---|
| 1236 | +static int wil_tx_vring_modify(struct wil6210_vif *vif, int ring_id, int cid, |
|---|
| 1237 | + int tid) |
|---|
| 1238 | +{ |
|---|
| 1239 | + struct wil6210_priv *wil = vif_to_wil(vif); |
|---|
| 1240 | + int rc; |
|---|
| 1241 | + struct wmi_vring_cfg_cmd cmd = { |
|---|
| 1242 | + .action = cpu_to_le32(WMI_VRING_CMD_MODIFY), |
|---|
| 1243 | + .vring_cfg = { |
|---|
| 1244 | + .tx_sw_ring = { |
|---|
| 1245 | + .max_mpdu_size = |
|---|
| 1246 | + cpu_to_le16(wil_mtu2macbuf(mtu_max)), |
|---|
| 1247 | + .ring_size = 0, |
|---|
| 1248 | + }, |
|---|
| 1249 | + .ringid = ring_id, |
|---|
| 1250 | + .cidxtid = mk_cidxtid(cid, tid), |
|---|
| 1251 | + .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, |
|---|
| 1252 | + .mac_ctrl = 0, |
|---|
| 1253 | + .to_resolution = 0, |
|---|
| 1254 | + .agg_max_wsize = 0, |
|---|
| 1255 | + .schd_params = { |
|---|
| 1256 | + .priority = cpu_to_le16(0), |
|---|
| 1257 | + .timeslot_us = cpu_to_le16(0xfff), |
|---|
| 1258 | + }, |
|---|
| 1259 | + }, |
|---|
| 1260 | + }; |
|---|
| 1261 | + struct { |
|---|
| 1262 | + struct wmi_cmd_hdr wmi; |
|---|
| 1263 | + struct wmi_vring_cfg_done_event cmd; |
|---|
| 1264 | + } __packed reply = { |
|---|
| 1265 | + .cmd = {.status = WMI_FW_STATUS_FAILURE}, |
|---|
| 1266 | + }; |
|---|
| 1267 | + struct wil_ring *vring = &wil->ring_tx[ring_id]; |
|---|
| 1268 | + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id]; |
|---|
| 1269 | + |
|---|
| 1270 | + wil_dbg_misc(wil, "vring_modify: ring %d cid %d tid %d\n", ring_id, |
|---|
| 1271 | + cid, tid); |
|---|
| 1272 | + lockdep_assert_held(&wil->mutex); |
|---|
| 1273 | + |
|---|
| 1274 | + if (!vring->va) { |
|---|
| 1275 | + wil_err(wil, "Tx ring [%d] not allocated\n", ring_id); |
|---|
| 1276 | + return -EINVAL; |
|---|
| 1277 | + } |
|---|
| 1278 | + |
|---|
| 1279 | + if (wil->ring2cid_tid[ring_id][0] != cid || |
|---|
| 1280 | + wil->ring2cid_tid[ring_id][1] != tid) { |
|---|
| 1281 | + wil_err(wil, "ring info does not match cid=%u tid=%u\n", |
|---|
| 1282 | + wil->ring2cid_tid[ring_id][0], |
|---|
| 1283 | + wil->ring2cid_tid[ring_id][1]); |
|---|
| 1284 | + } |
|---|
| 1285 | + |
|---|
| 1286 | + cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); |
|---|
| 1287 | + |
|---|
| 1288 | + rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), |
|---|
| 1289 | + WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), |
|---|
| 1290 | + WIL_WMI_CALL_GENERAL_TO_MS); |
|---|
| 1291 | + if (rc) |
|---|
| 1292 | + goto fail; |
|---|
| 1293 | + |
|---|
| 1294 | + if (reply.cmd.status != WMI_FW_STATUS_SUCCESS) { |
|---|
| 1295 | + wil_err(wil, "Tx modify failed, status 0x%02x\n", |
|---|
| 1296 | + reply.cmd.status); |
|---|
| 1297 | + rc = -EINVAL; |
|---|
| 1298 | + goto fail; |
|---|
| 1299 | + } |
|---|
| 1300 | + |
|---|
| 1301 | + /* set BA aggregation window size to 0 to force a new BA with the |
|---|
| 1302 | + * new AP |
|---|
| 1303 | + */ |
|---|
| 1304 | + txdata->agg_wsize = 0; |
|---|
| 1305 | + if (txdata->dot1x_open && agg_wsize >= 0) |
|---|
| 1306 | + wil_addba_tx_request(wil, ring_id, agg_wsize); |
|---|
| 1307 | + |
|---|
| 1308 | + return 0; |
|---|
| 1309 | +fail: |
|---|
| 1310 | + spin_lock_bh(&txdata->lock); |
|---|
| 1311 | + txdata->dot1x_open = false; |
|---|
| 1312 | + txdata->enabled = 0; |
|---|
| 1313 | + spin_unlock_bh(&txdata->lock); |
|---|
| 1314 | + wil->ring2cid_tid[ring_id][0] = wil->max_assoc_sta; |
|---|
| 1315 | + wil->ring2cid_tid[ring_id][1] = 0; |
|---|
| 1060 | 1316 | return rc; |
|---|
| 1061 | 1317 | } |
|---|
| 1062 | 1318 | |
|---|
| .. | .. |
|---|
| 1102 | 1358 | if (rc) |
|---|
| 1103 | 1359 | goto out; |
|---|
| 1104 | 1360 | |
|---|
| 1105 | | - wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; /* CID */ |
|---|
| 1361 | + wil->ring2cid_tid[id][0] = wil->max_assoc_sta; /* CID */ |
|---|
| 1106 | 1362 | wil->ring2cid_tid[id][1] = 0; /* TID */ |
|---|
| 1107 | 1363 | |
|---|
| 1108 | 1364 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); |
|---|
| .. | .. |
|---|
| 1111 | 1367 | txdata->dot1x_open = true; |
|---|
| 1112 | 1368 | rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, vif->mid, |
|---|
| 1113 | 1369 | &cmd, sizeof(cmd), |
|---|
| 1114 | | - WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); |
|---|
| 1370 | + WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), |
|---|
| 1371 | + WIL_WMI_CALL_GENERAL_TO_MS); |
|---|
| 1115 | 1372 | if (rc) |
|---|
| 1116 | 1373 | goto out_free; |
|---|
| 1117 | 1374 | |
|---|
| .. | .. |
|---|
| 1144 | 1401 | struct wil6210_vif *vif, |
|---|
| 1145 | 1402 | struct sk_buff *skb) |
|---|
| 1146 | 1403 | { |
|---|
| 1147 | | - int i; |
|---|
| 1148 | | - struct ethhdr *eth = (void *)skb->data; |
|---|
| 1149 | | - int cid = wil_find_cid(wil, vif->mid, eth->h_dest); |
|---|
| 1404 | + int i, cid; |
|---|
| 1405 | + const u8 *da = wil_skb_get_da(skb); |
|---|
| 1150 | 1406 | int min_ring_id = wil_get_min_tx_ring_id(wil); |
|---|
| 1151 | 1407 | |
|---|
| 1152 | | - if (cid < 0) |
|---|
| 1408 | + cid = wil_find_cid(wil, vif->mid, da); |
|---|
| 1409 | + |
|---|
| 1410 | + if (cid < 0 || cid >= wil->max_assoc_sta) |
|---|
| 1153 | 1411 | return NULL; |
|---|
| 1154 | 1412 | |
|---|
| 1155 | 1413 | /* TODO: fix for multiple TID */ |
|---|
| .. | .. |
|---|
| 1162 | 1420 | struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i]; |
|---|
| 1163 | 1421 | |
|---|
| 1164 | 1422 | wil_dbg_txrx(wil, "find_tx_ucast: (%pM) -> [%d]\n", |
|---|
| 1165 | | - eth->h_dest, i); |
|---|
| 1423 | + da, i); |
|---|
| 1166 | 1424 | if (v->va && txdata->enabled) { |
|---|
| 1167 | 1425 | return v; |
|---|
| 1168 | 1426 | } else { |
|---|
| .. | .. |
|---|
| 1201 | 1459 | continue; |
|---|
| 1202 | 1460 | |
|---|
| 1203 | 1461 | cid = wil->ring2cid_tid[i][0]; |
|---|
| 1204 | | - if (cid >= WIL6210_MAX_CID) /* skip BCAST */ |
|---|
| 1462 | + if (cid >= wil->max_assoc_sta) /* skip BCAST */ |
|---|
| 1205 | 1463 | continue; |
|---|
| 1206 | 1464 | |
|---|
| 1207 | 1465 | if (!wil->ring_tx_data[i].dot1x_open && |
|---|
| .. | .. |
|---|
| 1250 | 1508 | return v; |
|---|
| 1251 | 1509 | } |
|---|
| 1252 | 1510 | |
|---|
| 1511 | +/* apply multicast to unicast only for ARP and IP packets |
|---|
| 1512 | + * (see NL80211_CMD_SET_MULTICAST_TO_UNICAST for more info) |
|---|
| 1513 | + */ |
|---|
| 1514 | +static bool wil_check_multicast_to_unicast(struct wil6210_priv *wil, |
|---|
| 1515 | + struct sk_buff *skb) |
|---|
| 1516 | +{ |
|---|
| 1517 | + const struct ethhdr *eth = (void *)skb->data; |
|---|
| 1518 | + const struct vlan_ethhdr *ethvlan = (void *)skb->data; |
|---|
| 1519 | + __be16 ethertype; |
|---|
| 1520 | + |
|---|
| 1521 | + if (!wil->multicast_to_unicast) |
|---|
| 1522 | + return false; |
|---|
| 1523 | + |
|---|
| 1524 | + /* multicast to unicast conversion only for some payload */ |
|---|
| 1525 | + ethertype = eth->h_proto; |
|---|
| 1526 | + if (ethertype == htons(ETH_P_8021Q) && skb->len >= VLAN_ETH_HLEN) |
|---|
| 1527 | + ethertype = ethvlan->h_vlan_encapsulated_proto; |
|---|
| 1528 | + switch (ethertype) { |
|---|
| 1529 | + case htons(ETH_P_ARP): |
|---|
| 1530 | + case htons(ETH_P_IP): |
|---|
| 1531 | + case htons(ETH_P_IPV6): |
|---|
| 1532 | + break; |
|---|
| 1533 | + default: |
|---|
| 1534 | + return false; |
|---|
| 1535 | + } |
|---|
| 1536 | + |
|---|
| 1537 | + return true; |
|---|
| 1538 | +} |
|---|
| 1539 | + |
|---|
| 1253 | 1540 | static void wil_set_da_for_vring(struct wil6210_priv *wil, |
|---|
| 1254 | 1541 | struct sk_buff *skb, int vring_index) |
|---|
| 1255 | 1542 | { |
|---|
| 1256 | | - struct ethhdr *eth = (void *)skb->data; |
|---|
| 1543 | + u8 *da = wil_skb_get_da(skb); |
|---|
| 1257 | 1544 | int cid = wil->ring2cid_tid[vring_index][0]; |
|---|
| 1258 | 1545 | |
|---|
| 1259 | | - ether_addr_copy(eth->h_dest, wil->sta[cid].addr); |
|---|
| 1546 | + ether_addr_copy(da, wil->sta[cid].addr); |
|---|
| 1260 | 1547 | } |
|---|
| 1261 | 1548 | |
|---|
| 1262 | 1549 | static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil, |
|---|
| .. | .. |
|---|
| 1267 | 1554 | struct sk_buff *skb2; |
|---|
| 1268 | 1555 | int i; |
|---|
| 1269 | 1556 | u8 cid; |
|---|
| 1270 | | - struct ethhdr *eth = (void *)skb->data; |
|---|
| 1271 | | - char *src = eth->h_source; |
|---|
| 1557 | + const u8 *src = wil_skb_get_sa(skb); |
|---|
| 1272 | 1558 | struct wil_ring_tx_data *txdata, *txdata2; |
|---|
| 1273 | 1559 | int min_ring_id = wil_get_min_tx_ring_id(wil); |
|---|
| 1274 | 1560 | |
|---|
| .. | .. |
|---|
| 1280 | 1566 | continue; |
|---|
| 1281 | 1567 | |
|---|
| 1282 | 1568 | cid = wil->ring2cid_tid[i][0]; |
|---|
| 1283 | | - if (cid >= WIL6210_MAX_CID) /* skip BCAST */ |
|---|
| 1569 | + if (cid >= wil->max_assoc_sta) /* skip BCAST */ |
|---|
| 1284 | 1570 | continue; |
|---|
| 1285 | 1571 | if (!wil->ring_tx_data[i].dot1x_open && |
|---|
| 1286 | 1572 | skb->protocol != cpu_to_be16(ETH_P_PAE)) |
|---|
| .. | .. |
|---|
| 1308 | 1594 | if (!v2->va || txdata2->mid != vif->mid) |
|---|
| 1309 | 1595 | continue; |
|---|
| 1310 | 1596 | cid = wil->ring2cid_tid[i][0]; |
|---|
| 1311 | | - if (cid >= WIL6210_MAX_CID) /* skip BCAST */ |
|---|
| 1597 | + if (cid >= wil->max_assoc_sta) /* skip BCAST */ |
|---|
| 1312 | 1598 | continue; |
|---|
| 1313 | 1599 | if (!wil->ring_tx_data[i].dot1x_open && |
|---|
| 1314 | 1600 | skb->protocol != cpu_to_be16(ETH_P_PAE)) |
|---|
| .. | .. |
|---|
| 1338 | 1624 | d->mac.d[2] |= (nr_frags << MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); |
|---|
| 1339 | 1625 | } |
|---|
| 1340 | 1626 | |
|---|
| 1341 | | -/** |
|---|
| 1342 | | - * Sets the descriptor @d up for csum and/or TSO offloading. The corresponding |
|---|
| 1627 | +/* Sets the descriptor @d up for csum and/or TSO offloading. The corresponding |
|---|
| 1343 | 1628 | * @skb is used to obtain the protocol and headers length. |
|---|
| 1344 | 1629 | * @tso_desc_type is a descriptor type for TSO: 0 - a header, 1 - first data, |
|---|
| 1345 | 1630 | * 2 - middle, 3 - last descriptor. |
|---|
| .. | .. |
|---|
| 1369 | 1654 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS); |
|---|
| 1370 | 1655 | } |
|---|
| 1371 | 1656 | |
|---|
| 1372 | | -/** |
|---|
| 1373 | | - * Sets the descriptor @d up for csum. The corresponding |
|---|
| 1657 | +/* Sets the descriptor @d up for csum. The corresponding |
|---|
| 1374 | 1658 | * @skb is used to obtain the protocol and headers length. |
|---|
| 1375 | 1659 | * Returns the protocol: 0 - not TCP, 1 - TCPv4, 2 - TCPv6. |
|---|
| 1376 | 1660 | * Note, if d==NULL, the function only returns the protocol result. |
|---|
| .. | .. |
|---|
| 1560 | 1844 | len); |
|---|
| 1561 | 1845 | } else { |
|---|
| 1562 | 1846 | frag = &skb_shinfo(skb)->frags[f]; |
|---|
| 1563 | | - len = frag->size; |
|---|
| 1847 | + len = skb_frag_size(frag); |
|---|
| 1564 | 1848 | wil_dbg_txrx(wil, "TSO: frag[%d]: len %u\n", f, len); |
|---|
| 1565 | 1849 | } |
|---|
| 1566 | 1850 | |
|---|
| .. | .. |
|---|
| 1581 | 1865 | |
|---|
| 1582 | 1866 | if (!headlen) { |
|---|
| 1583 | 1867 | pa = skb_frag_dma_map(dev, frag, |
|---|
| 1584 | | - frag->size - len, lenmss, |
|---|
| 1585 | | - DMA_TO_DEVICE); |
|---|
| 1868 | + skb_frag_size(frag) - len, |
|---|
| 1869 | + lenmss, DMA_TO_DEVICE); |
|---|
| 1586 | 1870 | vring->ctx[i].mapped_as = wil_mapped_as_page; |
|---|
| 1587 | 1871 | } else { |
|---|
| 1588 | 1872 | pa = dma_map_single(dev, |
|---|
| .. | .. |
|---|
| 1666 | 1950 | *_desc = *d; |
|---|
| 1667 | 1951 | } |
|---|
| 1668 | 1952 | } |
|---|
| 1953 | + |
|---|
| 1954 | + if (!_desc) |
|---|
| 1955 | + goto mem_error; |
|---|
| 1669 | 1956 | |
|---|
| 1670 | 1957 | /* first descriptor may also be the last. |
|---|
| 1671 | 1958 | * in this case d pointer is invalid |
|---|
| .. | .. |
|---|
| 1800 | 2087 | |
|---|
| 1801 | 2088 | /* middle segments */ |
|---|
| 1802 | 2089 | for (; f < nr_frags; f++) { |
|---|
| 1803 | | - const struct skb_frag_struct *frag = |
|---|
| 1804 | | - &skb_shinfo(skb)->frags[f]; |
|---|
| 2090 | + const skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; |
|---|
| 1805 | 2091 | int len = skb_frag_size(frag); |
|---|
| 1806 | 2092 | |
|---|
| 1807 | 2093 | *_d = *d; |
|---|
| .. | .. |
|---|
| 1923 | 2209 | return rc; |
|---|
| 1924 | 2210 | } |
|---|
| 1925 | 2211 | |
|---|
| 1926 | | -/** |
|---|
| 1927 | | - * Check status of tx vrings and stop/wake net queues if needed |
|---|
| 2212 | +/* Check status of tx vrings and stop/wake net queues if needed |
|---|
| 1928 | 2213 | * It will start/stop net queues of a specific VIF net_device. |
|---|
| 1929 | 2214 | * |
|---|
| 1930 | 2215 | * This function does one of two checks: |
|---|
| .. | .. |
|---|
| 1958 | 2243 | else |
|---|
| 1959 | 2244 | wil_dbg_txrx(wil, "check_stop=%d, mid=%d, stopped=%d", |
|---|
| 1960 | 2245 | check_stop, vif->mid, vif->net_queue_stopped); |
|---|
| 2246 | + |
|---|
| 2247 | + if (ring && drop_if_ring_full) |
|---|
| 2248 | + /* no need to stop/wake net queues */ |
|---|
| 2249 | + return; |
|---|
| 1961 | 2250 | |
|---|
| 1962 | 2251 | if (check_stop == vif->net_queue_stopped) |
|---|
| 1963 | 2252 | /* net queues already in desired state */ |
|---|
| .. | .. |
|---|
| 2022 | 2311 | { |
|---|
| 2023 | 2312 | struct wil6210_vif *vif = ndev_to_vif(ndev); |
|---|
| 2024 | 2313 | struct wil6210_priv *wil = vif_to_wil(vif); |
|---|
| 2025 | | - struct ethhdr *eth = (void *)skb->data; |
|---|
| 2026 | | - bool bcast = is_multicast_ether_addr(eth->h_dest); |
|---|
| 2314 | + const u8 *da = wil_skb_get_da(skb); |
|---|
| 2315 | + bool bcast = is_multicast_ether_addr(da); |
|---|
| 2027 | 2316 | struct wil_ring *ring; |
|---|
| 2028 | 2317 | static bool pr_once_fw; |
|---|
| 2029 | 2318 | int rc; |
|---|
| .. | .. |
|---|
| 2052 | 2341 | /* in STA mode (ESS), all to same VRING (to AP) */ |
|---|
| 2053 | 2342 | ring = wil_find_tx_ring_sta(wil, vif, skb); |
|---|
| 2054 | 2343 | } else if (bcast) { |
|---|
| 2055 | | - if (vif->pbss) |
|---|
| 2344 | + if (vif->pbss || wil_check_multicast_to_unicast(wil, skb)) |
|---|
| 2056 | 2345 | /* in pbss, no bcast VRING - duplicate skb in |
|---|
| 2057 | 2346 | * all stations VRINGs |
|---|
| 2058 | 2347 | */ |
|---|
| .. | .. |
|---|
| 2070 | 2359 | ring = wil_find_tx_ucast(wil, vif, skb); |
|---|
| 2071 | 2360 | } |
|---|
| 2072 | 2361 | if (unlikely(!ring)) { |
|---|
| 2073 | | - wil_dbg_txrx(wil, "No Tx RING found for %pM\n", eth->h_dest); |
|---|
| 2362 | + wil_dbg_txrx(wil, "No Tx RING found for %pM\n", da); |
|---|
| 2074 | 2363 | goto drop; |
|---|
| 2075 | 2364 | } |
|---|
| 2076 | 2365 | /* set up vring entry */ |
|---|
| .. | .. |
|---|
| 2084 | 2373 | dev_kfree_skb_any(skb); |
|---|
| 2085 | 2374 | return NETDEV_TX_OK; |
|---|
| 2086 | 2375 | case -ENOMEM: |
|---|
| 2376 | + if (drop_if_ring_full) |
|---|
| 2377 | + goto drop; |
|---|
| 2087 | 2378 | return NETDEV_TX_BUSY; |
|---|
| 2088 | 2379 | default: |
|---|
| 2089 | 2380 | break; /* goto drop; */ |
|---|
| .. | .. |
|---|
| 2120 | 2411 | sta->stats.tx_latency_max_us = skb_time_us; |
|---|
| 2121 | 2412 | } |
|---|
| 2122 | 2413 | |
|---|
| 2123 | | -/** |
|---|
| 2124 | | - * Clean up transmitted skb's from the Tx VRING |
|---|
| 2414 | +/* Clean up transmitted skb's from the Tx VRING |
|---|
| 2125 | 2415 | * |
|---|
| 2126 | 2416 | * Return number of descriptors cleared |
|---|
| 2127 | 2417 | * |
|---|
| .. | .. |
|---|
| 2155 | 2445 | |
|---|
| 2156 | 2446 | used_before_complete = wil_ring_used_tx(vring); |
|---|
| 2157 | 2447 | |
|---|
| 2158 | | - if (cid < WIL6210_MAX_CID) |
|---|
| 2448 | + if (cid < wil->max_assoc_sta) |
|---|
| 2159 | 2449 | stats = &wil->sta[cid].stats; |
|---|
| 2160 | 2450 | |
|---|
| 2161 | 2451 | while (!wil_ring_is_empty(vring)) { |
|---|
| 2162 | 2452 | int new_swtail; |
|---|
| 2163 | 2453 | struct wil_ctx *ctx = &vring->ctx[vring->swtail]; |
|---|
| 2164 | | - /** |
|---|
| 2165 | | - * For the fragmented skb, HW will set DU bit only for the |
|---|
| 2454 | + /* For the fragmented skb, HW will set DU bit only for the |
|---|
| 2166 | 2455 | * last fragment. look for it. |
|---|
| 2167 | 2456 | * In TSO the first DU will include hdr desc |
|---|
| 2168 | 2457 | */ |
|---|
| .. | .. |
|---|
| 2215 | 2504 | if (stats) |
|---|
| 2216 | 2505 | stats->tx_errors++; |
|---|
| 2217 | 2506 | } |
|---|
| 2507 | + |
|---|
| 2508 | + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) |
|---|
| 2509 | + wil_tx_complete_handle_eapol(vif, skb); |
|---|
| 2510 | + |
|---|
| 2218 | 2511 | wil_consume_skb(skb, d->dma.error == 0); |
|---|
| 2219 | 2512 | } |
|---|
| 2220 | 2513 | memset(ctx, 0, sizeof(*ctx)); |
|---|
| .. | .. |
|---|
| 2264 | 2557 | struct vring_rx_desc *d = wil_skb_rxdesc(skb); |
|---|
| 2265 | 2558 | |
|---|
| 2266 | 2559 | *tid = wil_rxdesc_tid(d); |
|---|
| 2267 | | - *cid = wil_rxdesc_cid(d); |
|---|
| 2560 | + *cid = wil_skb_get_cid(skb); |
|---|
| 2268 | 2561 | *mid = wil_rxdesc_mid(d); |
|---|
| 2269 | 2562 | *seq = wil_rxdesc_seq(d); |
|---|
| 2270 | 2563 | *mcast = wil_rxdesc_mcast(d); |
|---|
| .. | .. |
|---|
| 2284 | 2577 | wil->txrx_ops.ring_init_bcast = wil_vring_init_bcast; |
|---|
| 2285 | 2578 | wil->txrx_ops.tx_init = wil_tx_init; |
|---|
| 2286 | 2579 | wil->txrx_ops.tx_fini = wil_tx_fini; |
|---|
| 2580 | + wil->txrx_ops.tx_ring_modify = wil_tx_vring_modify; |
|---|
| 2287 | 2581 | /* RX ops */ |
|---|
| 2288 | 2582 | wil->txrx_ops.rx_init = wil_rx_init; |
|---|
| 2289 | 2583 | wil->txrx_ops.wmi_addba_rx_resp = wmi_addba_rx_resp; |
|---|