diff options
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/txrx_edma.c')
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx_edma.c | 68 |
1 files changed, 40 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c index dc040cd4ab06..7bfe867c7509 100644 --- a/drivers/net/wireless/ath/wil6210/txrx_edma.c +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c @@ -1,17 +1,6 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <linux/etherdevice.h> @@ -221,10 +210,17 @@ static int wil_ring_alloc_skb_edma(struct wil6210_priv *wil, } static inline -void wil_get_next_rx_status_msg(struct wil_status_ring *sring, void *msg) +void wil_get_next_rx_status_msg(struct wil_status_ring *sring, u8 *dr_bit, + void *msg) { - memcpy(msg, (void *)(sring->va + (sring->elem_size * sring->swhead)), - sring->elem_size); + struct wil_rx_status_compressed *_msg; + + _msg = (struct wil_rx_status_compressed *) + (sring->va + (sring->elem_size * sring->swhead)); + *dr_bit = WIL_GET_BITS(_msg->d0, 31, 31); + /* make sure dr_bit is read before the rest of status msg */ + rmb(); + memcpy(msg, (void *)_msg, sring->elem_size); } static inline void wil_sring_advance_swhead(struct wil_status_ring *sring) @@ -587,8 +583,7 @@ static bool wil_is_rx_idle_edma(struct wil6210_priv *wil) if (!sring->va) continue; - wil_get_next_rx_status_msg(sring, msg); - dr_bit = wil_rx_status_get_desc_rdy_bit(msg); + wil_get_next_rx_status_msg(sring, &dr_bit, msg); /* Check if there are unhandled RX status messages */ if (dr_bit == sring->desc_rdy_pol) @@ -874,12 +869,12 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil, u8 data_offset; struct wil_rx_status_extended *s; u16 sring_idx = sring - wil->srings; + int invalid_buff_id_retry; BUILD_BUG_ON(sizeof(struct wil_rx_status_extended) > sizeof(skb->cb)); again: - wil_get_next_rx_status_msg(sring, msg); - dr_bit = wil_rx_status_get_desc_rdy_bit(msg); + wil_get_next_rx_status_msg(sring, &dr_bit, msg); /* Completed handling all the ready status messages */ if (dr_bit != sring->desc_rdy_pol) @@ -888,9 +883,9 @@ again: /* Extract the buffer ID from the status message */ buff_id = le16_to_cpu(wil_rx_status_get_buff_id(msg)); + invalid_buff_id_retry = 0; while (!buff_id) { struct wil_rx_status_extended *s; - int invalid_buff_id_retry = 0; wil_dbg_txrx(wil, "buff_id is not updated yet by HW, (swhead 0x%x)\n", @@ -908,6 +903,11 @@ again: if (unlikely(!wil_val_in_range(buff_id, 1, wil->rx_buff_mgmt.size))) { wil_err(wil, "Corrupt buff_id=%d, sring->swhead=%d\n", buff_id, sring->swhead); + print_hex_dump(KERN_ERR, "RxS ", DUMP_PREFIX_OFFSET, 16, 1, + msg, wil->use_compressed_rx_status ? + sizeof(struct wil_rx_status_compressed) : + sizeof(struct wil_rx_status_extended), false); + wil_rx_status_reset_buff_id(sring); wil_sring_advance_swhead(sring); sring->invalid_buff_id_cnt++; @@ -959,8 +959,8 @@ again: } stats = &wil->sta[cid].stats; - if (unlikely(skb->len < ETH_HLEN)) { - wil_dbg_txrx(wil, "Short frame, len = %d\n", skb->len); + if (unlikely(dmalen < ETH_HLEN)) { + wil_dbg_txrx(wil, "Short frame, len = %d\n", dmalen); stats->rx_short_frame++; rxdata->skipping = true; goto skipping; @@ -968,6 +968,11 @@ again: if (unlikely(dmalen > sz)) { wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); + print_hex_dump(KERN_ERR, "RxS ", DUMP_PREFIX_OFFSET, 16, 1, + msg, wil->use_compressed_rx_status ? + sizeof(struct wil_rx_status_compressed) : + sizeof(struct wil_rx_status_extended), false); + stats->rx_large_frame++; rxdata->skipping = true; } @@ -1023,6 +1028,8 @@ skipping: stats->last_mcs_rx = wil_rx_status_get_mcs(msg); if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) stats->rx_per_mcs[stats->last_mcs_rx]++; + + stats->last_cb_mode_rx = wil_rx_status_get_cb_mode(msg); } if (!wil->use_rx_hw_reordering && !wil->use_compressed_rx_status && @@ -1133,12 +1140,15 @@ static int wil_tx_desc_map_edma(union wil_tx_desc *desc, } static inline void -wil_get_next_tx_status_msg(struct wil_status_ring *sring, +wil_get_next_tx_status_msg(struct wil_status_ring *sring, u8 *dr_bit, struct wil_ring_tx_status *msg) { struct wil_ring_tx_status *_msg = (struct wil_ring_tx_status *) (sring->va + (sring->elem_size * sring->swhead)); + *dr_bit = _msg->desc_ready >> TX_STATUS_DESC_READY_POS; + /* make sure dr_bit is read before the rest of status msg */ + rmb(); *msg = *_msg; } @@ -1167,8 +1177,7 @@ int wil_tx_sring_handler(struct wil6210_priv *wil, int used_before_complete; int used_new; - wil_get_next_tx_status_msg(sring, &msg); - dr_bit = msg.desc_ready >> TX_STATUS_DESC_READY_POS; + wil_get_next_tx_status_msg(sring, &dr_bit, &msg); /* Process completion messages while DR bit has the expected polarity */ while (dr_bit == sring->desc_rdy_pol) { @@ -1255,6 +1264,10 @@ int wil_tx_sring_handler(struct wil6210_priv *wil, if (stats) stats->tx_errors++; } + + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) + wil_tx_complete_handle_eapol(vif, skb); + wil_consume_skb(skb, msg.status == 0); } memset(ctx, 0, sizeof(*ctx)); @@ -1287,8 +1300,7 @@ again: wil_sring_advance_swhead(sring); - wil_get_next_tx_status_msg(sring, &msg); - dr_bit = msg.desc_ready >> TX_STATUS_DESC_READY_POS; + wil_get_next_tx_status_msg(sring, &dr_bit, &msg); } /* shall we wake net queues? */ @@ -1471,7 +1483,7 @@ static int __wil_tx_ring_tso_edma(struct wil6210_priv *wil, /* Rest of the descriptors are from the SKB fragments */ for (f = 0; f < nr_frags; f++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; - int len = frag->size; + int len = skb_frag_size(frag); wil_dbg_txrx(wil, "TSO: frag[%d]: len %u, descs_used %d\n", f, len, descs_used); |