Loading drivers/net/wireless/ath/wil6210/debugfs.c +6 −0 Original line number Diff line number Diff line Loading @@ -1394,6 +1394,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) } } spin_unlock_bh(&p->tid_rx_lock); seq_printf(s, "Rx invalid frame: non-data %lu, short %lu, large %lu\n", p->stats.rx_non_data_frame, p->stats.rx_short_frame, p->stats.rx_large_frame); seq_puts(s, "Rx/MCS:"); for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs); mcs++) Loading drivers/net/wireless/ath/wil6210/interrupt.c +6 −1 Original line number Diff line number Diff line Loading @@ -347,7 +347,12 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) wil6210_mask_irq_misc(wil); if (isr & ISR_MISC_FW_ERROR) { wil_err(wil, "Firmware error detected\n"); u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE); u32 ucode_assert_code = wil_r(wil, RGF_UCODE_ASSERT_CODE); wil_err(wil, "Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n", fw_assert_code, ucode_assert_code); clear_bit(wil_status_fwready, wil->status); /* * do not clear @isr here - we do 2-nd part in thread Loading drivers/net/wireless/ath/wil6210/rx_reorder.c +26 −0 Original line number Diff line number Diff line Loading @@ -205,6 +205,32 @@ out: spin_unlock(&sta->tid_rx_lock); } /* process BAR frame, called in NAPI context */ void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq) { struct wil_sta_info *sta = &wil->sta[cid]; struct wil_tid_ampdu_rx *r; spin_lock(&sta->tid_rx_lock); r = sta->tid_rx[tid]; if (!r) { wil_err(wil, "BAR for non-existing CID %d TID %d\n", cid, tid); goto out; } if (seq_less(seq, r->head_seq_num)) { wil_err(wil, "BAR Seq 0x%03x preceding head 0x%03x\n", seq, r->head_seq_num); goto out; } wil_dbg_txrx(wil, "BAR: CID %d TID %d Seq 0x%03x head 0x%03x\n", cid, tid, seq, r->head_seq_num); wil_release_reorder_frames(wil, r, seq); out: spin_unlock(&sta->tid_rx_lock); } struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, int size, u16 ssn) { Loading drivers/net/wireless/ath/wil6210/txrx.c +47 −13 Original line number Diff line number Diff line Loading @@ -358,6 +358,13 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, } } /* similar to ieee80211_ version, but FC contain only 1-st byte */ static inline int wil_is_back_req(u8 fc) { return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); } /** * reap 1 frame from @swhead * Loading @@ -379,14 +386,16 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, u16 dmalen; u8 ftype; int cid; int i = (int)vring->swhead; int i; struct wil_net_stats *stats; BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); again: if (unlikely(wil_vring_is_empty(vring))) return NULL; i = (int)vring->swhead; _d = &vring->va[i].rx; if (unlikely(!(_d->dma.status & RX_DMA_STATUS_DU))) { /* it is not error, we just reached end of Rx done area */ Loading @@ -398,7 +407,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_vring_advance_head(vring, 1); if (!skb) { wil_err(wil, "No Rx skb at [%d]\n", i); return NULL; goto again; } d = wil_skb_rxdesc(skb); *d = *_d; Loading @@ -409,13 +418,17 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, trace_wil6210_rx(i, d); wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", i, dmalen); wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); cid = wil_rxdesc_cid(d); stats = &wil->sta[cid].stats; if (unlikely(dmalen > sz)) { wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); stats->rx_large_frame++; kfree_skb(skb); return NULL; goto again; } skb_trim(skb, dmalen); Loading @@ -424,8 +437,6 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb_headlen(skb), false); cid = wil_rxdesc_cid(d); stats = &wil->sta[cid].stats; stats->last_mcs_rx = wil_rxdesc_mcs(d); if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) stats->rx_per_mcs[stats->last_mcs_rx]++; Loading @@ -437,24 +448,47 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, /* no extra checks if in sniffer mode */ if (ndev->type != ARPHRD_ETHER) return skb; /* * Non-data frames may be delivered through Rx DMA channel (ex: BAR) /* Non-data frames may be delivered through Rx DMA channel (ex: BAR) * Driver should recognize it by frame type, that is found * in Rx descriptor. If type is not data, it is 802.11 frame as is */ ftype = wil_rxdesc_ftype(d) << 2; if (unlikely(ftype != IEEE80211_FTYPE_DATA)) { wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype); /* TODO: process it */ u8 fc1 = wil_rxdesc_fc1(d); int mid = wil_rxdesc_mid(d); int tid = wil_rxdesc_tid(d); u16 seq = wil_rxdesc_seq(d); wil_dbg_txrx(wil, "Non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n", fc1, mid, cid, tid, seq); stats->rx_non_data_frame++; if (wil_is_back_req(fc1)) { wil_dbg_txrx(wil, "BAR: MID %d CID %d TID %d Seq 0x%03x\n", mid, cid, tid, seq); wil_rx_bar(wil, cid, tid, seq); } else { /* print again all info. One can enable only this * without overhead for printing every Rx frame */ wil_dbg_txrx(wil, "Unhandled non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n", fc1, mid, cid, tid, seq); wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb_headlen(skb), false); } kfree_skb(skb); return NULL; goto again; } if (unlikely(skb->len < ETH_HLEN + snaplen)) { wil_err(wil, "Short frame, len = %d\n", skb->len); /* TODO: process it (i.e. BAR) */ stats->rx_short_frame++; kfree_skb(skb); return NULL; goto again; } /* L4 IDENT is on when HW calculated checksum, check status Loading drivers/net/wireless/ath/wil6210/txrx.h +7 −0 Original line number Diff line number Diff line Loading @@ -464,6 +464,12 @@ static inline int wil_rxdesc_subtype(struct vring_rx_desc *d) return WIL_GET_BITS(d->mac.d0, 12, 15); } /* 1-st byte (with frame type/subtype) of FC field */ static inline u8 wil_rxdesc_fc1(struct vring_rx_desc *d) { return (u8)(WIL_GET_BITS(d->mac.d0, 10, 15) << 2); } static inline int wil_rxdesc_seq(struct vring_rx_desc *d) { return WIL_GET_BITS(d->mac.d0, 16, 27); Loading Loading @@ -501,6 +507,7 @@ static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq); struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, int size, u16 ssn); void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, Loading Loading
drivers/net/wireless/ath/wil6210/debugfs.c +6 −0 Original line number Diff line number Diff line Loading @@ -1394,6 +1394,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) } } spin_unlock_bh(&p->tid_rx_lock); seq_printf(s, "Rx invalid frame: non-data %lu, short %lu, large %lu\n", p->stats.rx_non_data_frame, p->stats.rx_short_frame, p->stats.rx_large_frame); seq_puts(s, "Rx/MCS:"); for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs); mcs++) Loading
drivers/net/wireless/ath/wil6210/interrupt.c +6 −1 Original line number Diff line number Diff line Loading @@ -347,7 +347,12 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) wil6210_mask_irq_misc(wil); if (isr & ISR_MISC_FW_ERROR) { wil_err(wil, "Firmware error detected\n"); u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE); u32 ucode_assert_code = wil_r(wil, RGF_UCODE_ASSERT_CODE); wil_err(wil, "Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n", fw_assert_code, ucode_assert_code); clear_bit(wil_status_fwready, wil->status); /* * do not clear @isr here - we do 2-nd part in thread Loading
drivers/net/wireless/ath/wil6210/rx_reorder.c +26 −0 Original line number Diff line number Diff line Loading @@ -205,6 +205,32 @@ out: spin_unlock(&sta->tid_rx_lock); } /* process BAR frame, called in NAPI context */ void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq) { struct wil_sta_info *sta = &wil->sta[cid]; struct wil_tid_ampdu_rx *r; spin_lock(&sta->tid_rx_lock); r = sta->tid_rx[tid]; if (!r) { wil_err(wil, "BAR for non-existing CID %d TID %d\n", cid, tid); goto out; } if (seq_less(seq, r->head_seq_num)) { wil_err(wil, "BAR Seq 0x%03x preceding head 0x%03x\n", seq, r->head_seq_num); goto out; } wil_dbg_txrx(wil, "BAR: CID %d TID %d Seq 0x%03x head 0x%03x\n", cid, tid, seq, r->head_seq_num); wil_release_reorder_frames(wil, r, seq); out: spin_unlock(&sta->tid_rx_lock); } struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, int size, u16 ssn) { Loading
drivers/net/wireless/ath/wil6210/txrx.c +47 −13 Original line number Diff line number Diff line Loading @@ -358,6 +358,13 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, } } /* similar to ieee80211_ version, but FC contain only 1-st byte */ static inline int wil_is_back_req(u8 fc) { return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); } /** * reap 1 frame from @swhead * Loading @@ -379,14 +386,16 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, u16 dmalen; u8 ftype; int cid; int i = (int)vring->swhead; int i; struct wil_net_stats *stats; BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); again: if (unlikely(wil_vring_is_empty(vring))) return NULL; i = (int)vring->swhead; _d = &vring->va[i].rx; if (unlikely(!(_d->dma.status & RX_DMA_STATUS_DU))) { /* it is not error, we just reached end of Rx done area */ Loading @@ -398,7 +407,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_vring_advance_head(vring, 1); if (!skb) { wil_err(wil, "No Rx skb at [%d]\n", i); return NULL; goto again; } d = wil_skb_rxdesc(skb); *d = *_d; Loading @@ -409,13 +418,17 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, trace_wil6210_rx(i, d); wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", i, dmalen); wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); cid = wil_rxdesc_cid(d); stats = &wil->sta[cid].stats; if (unlikely(dmalen > sz)) { wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); stats->rx_large_frame++; kfree_skb(skb); return NULL; goto again; } skb_trim(skb, dmalen); Loading @@ -424,8 +437,6 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb_headlen(skb), false); cid = wil_rxdesc_cid(d); stats = &wil->sta[cid].stats; stats->last_mcs_rx = wil_rxdesc_mcs(d); if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) stats->rx_per_mcs[stats->last_mcs_rx]++; Loading @@ -437,24 +448,47 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, /* no extra checks if in sniffer mode */ if (ndev->type != ARPHRD_ETHER) return skb; /* * Non-data frames may be delivered through Rx DMA channel (ex: BAR) /* Non-data frames may be delivered through Rx DMA channel (ex: BAR) * Driver should recognize it by frame type, that is found * in Rx descriptor. If type is not data, it is 802.11 frame as is */ ftype = wil_rxdesc_ftype(d) << 2; if (unlikely(ftype != IEEE80211_FTYPE_DATA)) { wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype); /* TODO: process it */ u8 fc1 = wil_rxdesc_fc1(d); int mid = wil_rxdesc_mid(d); int tid = wil_rxdesc_tid(d); u16 seq = wil_rxdesc_seq(d); wil_dbg_txrx(wil, "Non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n", fc1, mid, cid, tid, seq); stats->rx_non_data_frame++; if (wil_is_back_req(fc1)) { wil_dbg_txrx(wil, "BAR: MID %d CID %d TID %d Seq 0x%03x\n", mid, cid, tid, seq); wil_rx_bar(wil, cid, tid, seq); } else { /* print again all info. One can enable only this * without overhead for printing every Rx frame */ wil_dbg_txrx(wil, "Unhandled non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n", fc1, mid, cid, tid, seq); wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb_headlen(skb), false); } kfree_skb(skb); return NULL; goto again; } if (unlikely(skb->len < ETH_HLEN + snaplen)) { wil_err(wil, "Short frame, len = %d\n", skb->len); /* TODO: process it (i.e. BAR) */ stats->rx_short_frame++; kfree_skb(skb); return NULL; goto again; } /* L4 IDENT is on when HW calculated checksum, check status Loading
drivers/net/wireless/ath/wil6210/txrx.h +7 −0 Original line number Diff line number Diff line Loading @@ -464,6 +464,12 @@ static inline int wil_rxdesc_subtype(struct vring_rx_desc *d) return WIL_GET_BITS(d->mac.d0, 12, 15); } /* 1-st byte (with frame type/subtype) of FC field */ static inline u8 wil_rxdesc_fc1(struct vring_rx_desc *d) { return (u8)(WIL_GET_BITS(d->mac.d0, 10, 15) << 2); } static inline int wil_rxdesc_seq(struct vring_rx_desc *d) { return WIL_GET_BITS(d->mac.d0, 16, 27); Loading Loading @@ -501,6 +507,7 @@ static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq); struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, int size, u16 ssn); void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, Loading