Return-path: Received: from alexa-out-ams-02.qualcomm.com ([185.23.61.163]:51990 "EHLO alexa-out-ams-02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S937882AbeFSNMC (ORCPT ); Tue, 19 Jun 2018 09:12:02 -0400 From: Maya Erez To: Kalle Valo Cc: Gidon Studinski , linux-wireless@vger.kernel.org, wil6210@qti.qualcomm.com, Maya Erez Subject: [PATCH v3 2/8] wil6210: add support for enhanced DMA structures Date: Tue, 19 Jun 2018 16:11:47 +0300 Message-Id: <1529413913-22224-3-git-send-email-merez@codeaurora.org> (sfid-20180619_151230_334917_BC0A59AE) In-Reply-To: <1529413913-22224-1-git-send-email-merez@codeaurora.org> References: <1529413913-22224-1-git-send-email-merez@codeaurora.org> Sender: linux-wireless-owner@vger.kernel.org List-ID: From: Gidon Studinski In enhanced DMA the vrings are handled internally by the FW and are not exposed to the driver. Instead, the driver handles descriptor rings, which are mapped by the FW to vrings. The completions of the TX and RX descriptors are notified to the driver using status rings. Each status ring descriptor includes information of the completed descriptors and the ring id of their descriptor ring. This patch changes struct vring to generic wil_ring to allow its reuse for enhanced DMA descriptor rings and adds the descriptor and status rings specific descriptors. The vring debugfs entries have changed as follows: - dbg_vring_index has changed to dbg_ring_index - vrings has changed to rings - vring_idle_trsh has changed to ring_idle_trsh - vring_index has changed to ring_index Signed-off-by: Gidon Studinski Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/cfg80211.c | 12 +- drivers/net/wireless/ath/wil6210/debugfs.c | 111 ++++---- drivers/net/wireless/ath/wil6210/main.c | 34 +-- drivers/net/wireless/ath/wil6210/netdev.c | 8 +- drivers/net/wireless/ath/wil6210/rx_reorder.c | 2 +- drivers/net/wireless/ath/wil6210/txrx.c | 356 ++++++++++++-------------- drivers/net/wireless/ath/wil6210/txrx.h | 68 ++++- drivers/net/wireless/ath/wil6210/txrx_edma.h | 290 +++++++++++++++++++++ drivers/net/wireless/ath/wil6210/wil6210.h | 110 ++++++-- drivers/net/wireless/ath/wil6210/wmi.c | 24 +- 10 files changed, 696 insertions(+), 319 deletions(-) create mode 100644 drivers/net/wireless/ath/wil6210/txrx_edma.h diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 78946f2..dfe64b0 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1726,7 +1726,7 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, struct wil6210_priv *wil = wiphy_to_wil(wiphy); int authorize; int cid, i; - struct vring_tx_data *txdata = NULL; + struct wil_ring_tx_data *txdata = NULL; wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x mid %d\n", mac, params->sta_flags_mask, params->sta_flags_set, @@ -1746,20 +1746,20 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy, return -ENOLINK; } - for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) - if (wil->vring2cid_tid[i][0] == cid) { - txdata = &wil->vring_tx_data[i]; + for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++) + if (wil->ring2cid_tid[i][0] == cid) { + txdata = &wil->ring_tx_data[i]; break; } if (!txdata) { - wil_err(wil, "vring data not found\n"); + wil_err(wil, "ring data not found\n"); return -ENOLINK; } authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED); txdata->dot1x_open = authorize ? 1 : 0; - wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i, + wil_dbg_misc(wil, "cid %d ring %d authorize %d\n", cid, i, txdata->dot1x_open); return 0; diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index ebfdff4..55e03e9b 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -29,7 +29,7 @@ /* Nasty hack. Better have per device instances */ static u32 mem_addr; static u32 dbg_txdesc_index; -static u32 dbg_vring_index; /* 24+ for Rx, 0..23 for Tx */ +static u32 dbg_ring_index; /* 24+ for Rx, 0..23 for Tx */ enum dbg_off_type { doff_u32 = 0, @@ -47,20 +47,20 @@ struct dbg_off { enum dbg_off_type type; }; -static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, - const char *name, struct vring *vring, - char _s, char _h) +static void wil_print_ring(struct seq_file *s, struct wil6210_priv *wil, + const char *name, struct wil_ring *ring, + char _s, char _h) { - void __iomem *x = wmi_addr(wil, vring->hwtail); + void __iomem *x = wmi_addr(wil, ring->hwtail); u32 v; - seq_printf(s, "VRING %s = {\n", name); - seq_printf(s, " pa = %pad\n", &vring->pa); - seq_printf(s, " va = 0x%p\n", vring->va); - seq_printf(s, " size = %d\n", vring->size); - seq_printf(s, " swtail = %d\n", vring->swtail); - seq_printf(s, " swhead = %d\n", vring->swhead); - seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail); + seq_printf(s, "RING %s = {\n", name); + seq_printf(s, " pa = %pad\n", &ring->pa); + seq_printf(s, " va = 0x%p\n", ring->va); + seq_printf(s, " size = %d\n", ring->size); + seq_printf(s, " swtail = %d\n", ring->swtail); + seq_printf(s, " swhead = %d\n", ring->swhead); + seq_printf(s, " hwtail = [0x%08x] -> ", ring->hwtail); if (x) { v = readl(x); seq_printf(s, "0x%08x = %d\n", v, v); @@ -68,41 +68,42 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, seq_puts(s, "???\n"); } - if (vring->va && (vring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) { + if (ring->va && (ring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) { uint i; - for (i = 0; i < vring->size; i++) { - volatile struct vring_tx_desc *d = &vring->va[i].tx; + for (i = 0; i < ring->size; i++) { + volatile struct vring_tx_desc *d = + &ring->va[i].tx.legacy; if ((i % 128) == 0 && (i != 0)) seq_puts(s, "\n"); seq_printf(s, "%c", (d->dma.status & BIT(0)) ? - _s : (vring->ctx[i].skb ? _h : 'h')); + _s : (ring->ctx[i].skb ? _h : 'h')); } seq_puts(s, "\n"); } seq_puts(s, "}\n"); } -static int wil_vring_debugfs_show(struct seq_file *s, void *data) +static int wil_ring_debugfs_show(struct seq_file *s, void *data) { uint i; struct wil6210_priv *wil = s->private; - wil_print_vring(s, wil, "rx", &wil->vring_rx, 'S', '_'); + wil_print_ring(s, wil, "rx", &wil->ring_rx, 'S', '_'); - for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { - struct vring *vring = &wil->vring_tx[i]; - struct vring_tx_data *txdata = &wil->vring_tx_data[i]; + for (i = 0; i < ARRAY_SIZE(wil->ring_tx); i++) { + struct wil_ring *ring = &wil->ring_tx[i]; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i]; - if (vring->va) { - int cid = wil->vring2cid_tid[i][0]; - int tid = wil->vring2cid_tid[i][1]; - u32 swhead = vring->swhead; - u32 swtail = vring->swtail; - int used = (vring->size + swhead - swtail) - % vring->size; - int avail = vring->size - used - 1; + if (ring->va) { + int cid = wil->ring2cid_tid[i][0]; + int tid = wil->ring2cid_tid[i][1]; + u32 swhead = ring->swhead; + u32 swtail = ring->swtail; + int used = (ring->size + swhead - swtail) + % ring->size; + int avail = ring->size - used - 1; char name[10]; char sidle[10]; /* performance monitoring */ @@ -137,20 +138,20 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data) txdata->dot1x_open ? "+" : "-", used, avail, sidle); - wil_print_vring(s, wil, name, vring, '_', 'H'); + wil_print_ring(s, wil, name, ring, '_', 'H'); } } return 0; } -static int wil_vring_seq_open(struct inode *inode, struct file *file) +static int wil_ring_seq_open(struct inode *inode, struct file *file) { - return single_open(file, wil_vring_debugfs_show, inode->i_private); + return single_open(file, wil_ring_debugfs_show, inode->i_private); } -static const struct file_operations fops_vring = { - .open = wil_vring_seq_open, +static const struct file_operations fops_ring = { + .open = wil_ring_seq_open, .release = single_release, .read = seq_read, .llseek = seq_lseek, @@ -162,8 +163,8 @@ static void wil_seq_hexdump(struct seq_file *s, void *p, int len, seq_hex_dump(s, prefix, DUMP_PREFIX_NONE, 16, 1, p, len, false); } -static void wil_print_ring(struct seq_file *s, const char *prefix, - void __iomem *off) +static void wil_print_mbox_ring(struct seq_file *s, const char *prefix, + void __iomem *off) { struct wil6210_priv *wil = s->private; struct wil6210_mbox_ring r; @@ -249,9 +250,9 @@ static int wil_mbox_debugfs_show(struct seq_file *s, void *data) if (ret < 0) return ret; - wil_print_ring(s, "tx", wil->csr + HOST_MBOX + + wil_print_mbox_ring(s, "tx", wil->csr + HOST_MBOX + offsetof(struct wil6210_mbox_ctl, tx)); - wil_print_ring(s, "rx", wil->csr + HOST_MBOX + + wil_print_mbox_ring(s, "rx", wil->csr + HOST_MBOX + offsetof(struct wil6210_mbox_ctl, rx)); wil_pm_runtime_put(wil); @@ -719,13 +720,13 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf, if ((strcmp(cmd, "add") == 0) || (strcmp(cmd, "del_tx") == 0)) { - struct vring_tx_data *txdata; + struct wil_ring_tx_data *txdata; if (p1 < 0 || p1 >= WIL6210_MAX_TX_RINGS) { wil_err(wil, "BACK: invalid ring id %d\n", p1); return -EINVAL; } - txdata = &wil->vring_tx_data[p1]; + txdata = &wil->ring_tx_data[p1]; if (strcmp(cmd, "add") == 0) { if (rc < 3) { wil_err(wil, "BACK: add require at least 2 params\n"); @@ -972,30 +973,30 @@ static void wil_seq_print_skb(struct seq_file *s, struct sk_buff *skb) static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; - struct vring *vring; - bool tx = (dbg_vring_index < WIL6210_MAX_TX_RINGS); + struct wil_ring *ring; + bool tx = (dbg_ring_index < WIL6210_MAX_TX_RINGS); - vring = tx ? &wil->vring_tx[dbg_vring_index] : &wil->vring_rx; + ring = tx ? &wil->ring_tx[dbg_ring_index] : &wil->ring_rx; - if (!vring->va) { + if (!ring->va) { if (tx) - seq_printf(s, "No Tx[%2d] VRING\n", dbg_vring_index); + seq_printf(s, "No Tx[%2d] VRING\n", dbg_ring_index); else seq_puts(s, "No Rx VRING\n"); return 0; } - if (dbg_txdesc_index < vring->size) { + if (dbg_txdesc_index < ring->size) { /* use struct vring_tx_desc for Rx as well, * only field used, .dma.length, is the same */ volatile struct vring_tx_desc *d = - &vring->va[dbg_txdesc_index].tx; + &ring->va[dbg_txdesc_index].tx.legacy; volatile u32 *u = (volatile u32 *)d; - struct sk_buff *skb = vring->ctx[dbg_txdesc_index].skb; + struct sk_buff *skb = ring->ctx[dbg_txdesc_index].skb; if (tx) - seq_printf(s, "Tx[%2d][%3d] = {\n", dbg_vring_index, + seq_printf(s, "Tx[%2d][%3d] = {\n", dbg_ring_index, dbg_txdesc_index); else seq_printf(s, "Rx[%3d] = {\n", dbg_txdesc_index); @@ -1014,11 +1015,11 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) } else { if (tx) seq_printf(s, "[%2d] TxDesc index (%d) >= size (%d)\n", - dbg_vring_index, dbg_txdesc_index, - vring->size); + dbg_ring_index, dbg_txdesc_index, + ring->size); else seq_printf(s, "RxDesc index (%d) >= size (%d)\n", - dbg_txdesc_index, vring->size); + dbg_txdesc_index, ring->size); } return 0; @@ -1790,7 +1791,7 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, const struct file_operations *fops; } dbg_files[] = { {"mbox", 0444, &fops_mbox}, - {"vrings", 0444, &fops_vring}, + {"rings", 0444, &fops_ring}, {"stations", 0444, &fops_sta}, {"mids", 0444, &fops_mids}, {"desc", 0444, &fops_txdesc}, @@ -1858,7 +1859,7 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, WIL_FIELD(chip_revision, 0444, doff_u8), WIL_FIELD(abft_len, 0644, doff_u8), WIL_FIELD(wakeup_trigger, 0644, doff_u8), - WIL_FIELD(vring_idle_trsh, 0644, doff_u32), + WIL_FIELD(ring_idle_trsh, 0644, doff_u32), {}, }; @@ -1872,7 +1873,7 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, /* static parameters */ static const struct dbg_off dbg_statics[] = { {"desc_index", 0644, (ulong)&dbg_txdesc_index, doff_u32}, - {"vring_index", 0644, (ulong)&dbg_vring_index, doff_u32}, + {"ring_index", 0644, (ulong)&dbg_ring_index, doff_u32}, {"mem_addr", 0644, (ulong)&mem_addr, doff_u32}, {"led_polarity", 0644, (ulong)&led_polarity, doff_u8}, {}, diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 1282e1a..bfe6284 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -219,9 +219,9 @@ static void wil_disconnect_cid(struct wil6210_vif *vif, int cid, memset(sta->tid_crypto_rx, 0, sizeof(sta->tid_crypto_rx)); memset(&sta->group_crypto_rx, 0, sizeof(sta->group_crypto_rx)); /* release vrings */ - for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { - if (wil->vring2cid_tid[i][0] == cid) - wil_vring_fini_tx(wil, i); + for (i = 0; i < ARRAY_SIZE(wil->ring_tx); i++) { + if (wil->ring2cid_tid[i][0] == cid) + wil_ring_fini_tx(wil, i); } /* statistics */ memset(&sta->stats, 0, sizeof(sta->stats)); @@ -453,12 +453,12 @@ static void wil_fw_error_worker(struct work_struct *work) mutex_unlock(&wil->mutex); } -static int wil_find_free_vring(struct wil6210_priv *wil) +static int wil_find_free_ring(struct wil6210_priv *wil) { int i; for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { - if (!wil->vring_tx[i].va) + if (!wil->ring_tx[i].va) return i; } return -EINVAL; @@ -473,13 +473,13 @@ int wil_tx_init(struct wil6210_vif *vif, int cid) wil_err(wil, "No connection pending\n"); goto out; } - ringid = wil_find_free_vring(wil); + ringid = wil_find_free_ring(wil); if (ringid < 0) { wil_err(wil, "No free vring found\n"); goto out; } - wil_dbg_wmi(wil, "Configure for connection CID %d MID %d vring %d\n", + wil_dbg_wmi(wil, "Configure for connection CID %d MID %d ring %d\n", cid, vif->mid, ringid); rc = wil_vring_init_tx(vif, ringid, 1 << tx_ring_order, cid, 0); @@ -494,19 +494,19 @@ int wil_tx_init(struct wil6210_vif *vif, int cid) int wil_bcast_init(struct wil6210_vif *vif) { struct wil6210_priv *wil = vif_to_wil(vif); - int ri = vif->bcast_vring, rc; + int ri = vif->bcast_ring, rc; - if ((ri >= 0) && wil->vring_tx[ri].va) + if (ri >= 0 && wil->ring_tx[ri].va) return 0; - ri = wil_find_free_vring(wil); + ri = wil_find_free_ring(wil); if (ri < 0) return ri; - vif->bcast_vring = ri; + vif->bcast_ring = ri; rc = wil_vring_init_bcast(vif, ri, 1 << bcast_ring_order); if (rc) - vif->bcast_vring = -1; + vif->bcast_ring = -1; return rc; } @@ -514,13 +514,13 @@ int wil_bcast_init(struct wil6210_vif *vif) void wil_bcast_fini(struct wil6210_vif *vif) { struct wil6210_priv *wil = vif_to_wil(vif); - int ri = vif->bcast_vring; + int ri = vif->bcast_ring; if (ri < 0) return; - vif->bcast_vring = -1; - wil_vring_fini_tx(wil, ri); + vif->bcast_ring = -1; + wil_ring_fini_tx(wil, ri); } void wil_bcast_fini_all(struct wil6210_priv *wil) @@ -548,7 +548,7 @@ int wil_priv_init(struct wil6210_priv *wil) } for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) - spin_lock_init(&wil->vring_tx_data[i].lock); + spin_lock_init(&wil->ring_tx_data[i].lock); mutex_init(&wil->mutex); mutex_init(&wil->vif_mutex); @@ -589,7 +589,7 @@ int wil_priv_init(struct wil6210_priv *wil) wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST | WMI_WAKEUP_TRIGGER_BCAST; memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats)); - wil->vring_idle_trsh = 16; + wil->ring_idle_trsh = 16; wil->reply_mid = U8_MAX; wil->max_vifs = 1; diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index eb6c14ed..3c6a59f 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -129,11 +129,11 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) /* always process ALL Tx complete, regardless budget - it is fast */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { - struct vring *vring = &wil->vring_tx[i]; - struct vring_tx_data *txdata = &wil->vring_tx_data[i]; + struct wil_ring *ring = &wil->ring_tx[i]; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i]; struct wil6210_vif *vif; - if (!vring->va || !txdata->enabled || + if (!ring->va || !txdata->enabled || txdata->mid >= wil->max_vifs) continue; @@ -228,7 +228,7 @@ static void wil_p2p_discovery_timer_fn(struct timer_list *t) static void wil_vif_init(struct wil6210_vif *vif) { - vif->bcast_vring = -1; + vif->bcast_ring = -1; mutex_init(&vif->probe_client_mutex); diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 76f8084..a586929 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -384,7 +384,7 @@ int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize) { u8 agg_wsize = wil_agg_size(wil, wsize); u16 agg_timeout = 0; - struct vring_tx_data *txdata = &wil->vring_tx_data[ringid]; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ringid]; int rc = 0; if (txdata->addba_in_progress) { diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index b9a9fa8..55946de 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -47,62 +47,28 @@ static inline uint wil_rx_snaplen(void) return rx_align_2 ? 6 : 0; } -static inline int wil_vring_is_empty(struct vring *vring) +/* wil_ring_wmark_low - low watermark for available descriptor space */ +static inline int wil_ring_wmark_low(struct wil_ring *ring) { - return vring->swhead == vring->swtail; + return ring->size / 8; } -static inline u32 wil_vring_next_tail(struct vring *vring) +/* wil_ring_wmark_high - high watermark for available descriptor space */ +static inline int wil_ring_wmark_high(struct wil_ring *ring) { - return (vring->swtail + 1) % vring->size; -} - -static inline void wil_vring_advance_head(struct vring *vring, int n) -{ - vring->swhead = (vring->swhead + n) % vring->size; -} - -static inline int wil_vring_is_full(struct vring *vring) -{ - return wil_vring_next_tail(vring) == vring->swhead; -} - -/* Used space in Tx Vring */ -static inline int wil_vring_used_tx(struct vring *vring) -{ - u32 swhead = vring->swhead; - u32 swtail = vring->swtail; - return (vring->size + swhead - swtail) % vring->size; -} - -/* Available space in Tx Vring */ -static inline int wil_vring_avail_tx(struct vring *vring) -{ - return vring->size - wil_vring_used_tx(vring) - 1; -} - -/* wil_vring_wmark_low - low watermark for available descriptor space */ -static inline int wil_vring_wmark_low(struct vring *vring) -{ - return vring->size/8; -} - -/* wil_vring_wmark_high - high watermark for available descriptor space */ -static inline int wil_vring_wmark_high(struct vring *vring) -{ - return vring->size/4; + return ring->size / 4; } /* returns true if num avail descriptors is lower than wmark_low */ -static inline int wil_vring_avail_low(struct vring *vring) +static inline int wil_ring_avail_low(struct wil_ring *ring) { - return wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring); + return wil_ring_avail_tx(ring) < wil_ring_wmark_low(ring); } /* returns true if num avail descriptors is higher than wmark_high */ -static inline int wil_vring_avail_high(struct vring *vring) +static inline int wil_ring_avail_high(struct wil_ring *ring) { - return wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring); + return wil_ring_avail_tx(ring) > wil_ring_wmark_high(ring); } /* returns true when all tx vrings are empty */ @@ -112,9 +78,10 @@ bool wil_is_tx_idle(struct wil6210_priv *wil) unsigned long data_comp_to; for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { - struct vring *vring = &wil->vring_tx[i]; - int vring_index = vring - wil->vring_tx; - struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index]; + struct wil_ring *vring = &wil->ring_tx[i]; + int vring_index = vring - wil->ring_tx; + struct wil_ring_tx_data *txdata = + &wil->ring_tx_data[vring_index]; spin_lock(&txdata->lock); @@ -126,7 +93,7 @@ bool wil_is_tx_idle(struct wil6210_priv *wil) data_comp_to = jiffies + msecs_to_jiffies( WIL_DATA_COMPLETION_TO_MS); if (test_bit(wil_status_napi_en, wil->status)) { - while (!wil_vring_is_empty(vring)) { + while (!wil_ring_is_empty(vring)) { if (time_after(jiffies, data_comp_to)) { wil_dbg_pm(wil, "TO waiting for idle tx\n"); @@ -156,7 +123,7 @@ static inline bool wil_val_in_range(int val, int min, int max) return val >= min && val < max; } -static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) +static int wil_vring_alloc(struct wil6210_priv *wil, struct wil_ring *vring) { struct device *dev = wil_to_dev(wil); size_t sz = vring->size * sizeof(vring->va[0]); @@ -205,7 +172,8 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) * we can use any */ for (i = 0; i < vring->size; i++) { - volatile struct vring_tx_desc *_d = &vring->va[i].tx; + volatile struct vring_tx_desc *_d = + &vring->va[i].tx.legacy; _d->dma.status = TX_DMA_STATUS_DU; } @@ -234,7 +202,7 @@ static void wil_txdesc_unmap(struct device *dev, struct vring_tx_desc *d, } } -static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, +static void wil_vring_free(struct wil6210_priv *wil, struct wil_ring *vring, int tx) { struct device *dev = wil_to_dev(wil); @@ -242,7 +210,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, lockdep_assert_held(&wil->mutex); if (tx) { - int vring_index = vring - wil->vring_tx; + int vring_index = vring - wil->ring_tx; wil_dbg_misc(wil, "free Tx vring %d [%d] 0x%p:%pad 0x%p\n", vring_index, vring->size, vring->va, @@ -253,7 +221,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, &vring->pa, vring->ctx); } - while (!wil_vring_is_empty(vring)) { + while (!wil_ring_is_empty(vring)) { dma_addr_t pa; u16 dmalen; struct wil_ctx *ctx; @@ -261,25 +229,25 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, if (tx) { struct vring_tx_desc dd, *d = ⅆ volatile struct vring_tx_desc *_d = - &vring->va[vring->swtail].tx; + &vring->va[vring->swtail].tx.legacy; ctx = &vring->ctx[vring->swtail]; if (!ctx) { wil_dbg_txrx(wil, "ctx(%d) was already completed\n", vring->swtail); - vring->swtail = wil_vring_next_tail(vring); + vring->swtail = wil_ring_next_tail(vring); continue; } *d = *_d; wil_txdesc_unmap(dev, d, ctx); if (ctx->skb) dev_kfree_skb_any(ctx->skb); - vring->swtail = wil_vring_next_tail(vring); + vring->swtail = wil_ring_next_tail(vring); } else { /* rx */ struct vring_rx_desc dd, *d = ⅆ volatile struct vring_rx_desc *_d = - &vring->va[vring->swhead].rx; + &vring->va[vring->swhead].rx.legacy; ctx = &vring->ctx[vring->swhead]; *d = *_d; @@ -287,7 +255,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, dmalen = le16_to_cpu(d->dma.length); dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE); kfree_skb(ctx->skb); - wil_vring_advance_head(vring, 1); + wil_ring_advance_head(vring, 1); } } dma_free_coherent(dev, sz, (void *)vring->va, vring->pa); @@ -302,13 +270,13 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, * * Safe to call from IRQ */ -static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, +static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct wil_ring *vring, u32 i, int headroom) { struct device *dev = wil_to_dev(wil); unsigned int sz = wil->rx_buf_len + ETH_HLEN + wil_rx_snaplen(); struct vring_rx_desc dd, *d = ⅆ - volatile struct vring_rx_desc *_d = &vring->va[i].rx; + volatile struct vring_rx_desc *_d = &vring->va[i].rx.legacy; dma_addr_t pa; struct sk_buff *skb = dev_alloc_skb(sz + headroom); @@ -455,9 +423,9 @@ static inline int wil_is_back_req(u8 fc) bool wil_is_rx_idle(struct wil6210_priv *wil) { struct vring_rx_desc *_d; - struct vring *vring = &wil->vring_rx; + struct wil_ring *ring = &wil->ring_rx; - _d = (struct vring_rx_desc *)&vring->va[vring->swhead].rx; + _d = (struct vring_rx_desc *)&ring->va[ring->swhead].rx.legacy; if (_d->dma.status & RX_DMA_STATUS_DU) return false; @@ -472,7 +440,7 @@ bool wil_is_rx_idle(struct wil6210_priv *wil) * Safe to call from IRQ */ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, - struct vring *vring) + struct wil_ring *vring) { struct device *dev = wil_to_dev(wil); struct wil6210_vif *vif; @@ -492,11 +460,11 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); again: - if (unlikely(wil_vring_is_empty(vring))) + if (unlikely(wil_ring_is_empty(vring))) return NULL; i = (int)vring->swhead; - _d = &vring->va[i].rx; + _d = &vring->va[i].rx.legacy; if (unlikely(!(_d->dma.status & RX_DMA_STATUS_DU))) { /* it is not error, we just reached end of Rx done area */ return NULL; @@ -504,7 +472,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, skb = vring->ctx[i].skb; vring->ctx[i].skb = NULL; - wil_vring_advance_head(vring, 1); + wil_ring_advance_head(vring, 1); if (!skb) { wil_err(wil, "No Rx skb at [%d]\n", i); goto again; @@ -641,15 +609,15 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, static int wil_rx_refill(struct wil6210_priv *wil, int count) { struct net_device *ndev = wil->main_ndev; - struct vring *v = &wil->vring_rx; + struct wil_ring *v = &wil->ring_rx; u32 next_tail; int rc = 0; int headroom = ndev->type == ARPHRD_IEEE80211_RADIOTAP ? WIL6210_RTAP_SIZE : 0; - for (; next_tail = wil_vring_next_tail(v), - (next_tail != v->swhead) && (count-- > 0); - v->swtail = next_tail) { + for (; next_tail = wil_ring_next_tail(v), + (next_tail != v->swhead) && (count-- > 0); + v->swtail = next_tail) { rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); if (unlikely(rc)) { wil_err_ratelimited(wil, "Error %d in rx refill[%d]\n", @@ -835,7 +803,7 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota) { struct net_device *ndev = wil->main_ndev; struct wireless_dev *wdev = ndev->ieee80211_ptr; - struct vring *v = &wil->vring_rx; + struct wil_ring *v = &wil->ring_rx; struct sk_buff *skb; if (unlikely(!v->va)) { @@ -877,7 +845,7 @@ static void wil_rx_buf_len_init(struct wil6210_priv *wil) int wil_rx_init(struct wil6210_priv *wil, u16 size) { - struct vring *vring = &wil->vring_rx; + struct wil_ring *vring = &wil->ring_rx; int rc; wil_dbg_misc(wil, "rx_init\n"); @@ -911,7 +879,7 @@ int wil_rx_init(struct wil6210_priv *wil, u16 size) void wil_rx_fini(struct wil6210_priv *wil) { - struct vring *vring = &wil->vring_rx; + struct wil_ring *vring = &wil->ring_rx; wil_dbg_misc(wil, "rx_fini\n"); @@ -919,7 +887,7 @@ void wil_rx_fini(struct wil6210_priv *wil) wil_vring_free(wil, vring, 0); } -static inline void wil_tx_data_init(struct vring_tx_data *txdata) +static inline void wil_tx_data_init(struct wil_ring_tx_data *txdata) { spin_lock_bh(&txdata->lock); txdata->dot1x_open = 0; @@ -966,8 +934,8 @@ int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, } __packed reply = { .cmd = {.status = WMI_FW_STATUS_FAILURE}, }; - struct vring *vring = &wil->vring_tx[id]; - struct vring_tx_data *txdata = &wil->vring_tx_data[id]; + struct wil_ring *vring = &wil->ring_tx[id]; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id]; wil_dbg_misc(wil, "vring_init_tx: max_mpdu_size %d\n", cmd.vring_cfg.tx_sw_ring.max_mpdu_size); @@ -985,8 +953,8 @@ int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, if (rc) goto out; - wil->vring2cid_tid[id][0] = cid; - wil->vring2cid_tid[id][1] = tid; + wil->ring2cid_tid[id][0] = cid; + wil->ring2cid_tid[id][1] = tid; cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); @@ -1020,8 +988,8 @@ int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, txdata->enabled = 0; spin_unlock_bh(&txdata->lock); wil_vring_free(wil, vring, 1); - wil->vring2cid_tid[id][0] = WIL6210_MAX_CID; - wil->vring2cid_tid[id][1] = 0; + wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; + wil->ring2cid_tid[id][1] = 0; out: @@ -1050,8 +1018,8 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) } __packed reply = { .cmd = {.status = WMI_FW_STATUS_FAILURE}, }; - struct vring *vring = &wil->vring_tx[id]; - struct vring_tx_data *txdata = &wil->vring_tx_data[id]; + struct wil_ring *vring = &wil->ring_tx[id]; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id]; wil_dbg_misc(wil, "vring_init_bcast: max_mpdu_size %d\n", cmd.vring_cfg.tx_sw_ring.max_mpdu_size); @@ -1069,8 +1037,8 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) if (rc) goto out; - wil->vring2cid_tid[id][0] = WIL6210_MAX_CID; /* CID */ - wil->vring2cid_tid[id][1] = 0; /* TID */ + wil->ring2cid_tid[id][0] = WIL6210_MAX_CID; /* CID */ + wil->ring2cid_tid[id][1] = 0; /* TID */ cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); @@ -1107,10 +1075,10 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) return rc; } -void wil_vring_fini_tx(struct wil6210_priv *wil, int id) +void wil_ring_fini_tx(struct wil6210_priv *wil, int id) { - struct vring *vring = &wil->vring_tx[id]; - struct vring_tx_data *txdata = &wil->vring_tx_data[id]; + struct wil_ring *vring = &wil->ring_tx[id]; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[id]; lockdep_assert_held(&wil->mutex); @@ -1138,9 +1106,9 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) wil_vring_free(wil, vring, 1); } -static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, - struct wil6210_vif *vif, - struct sk_buff *skb) +static struct wil_ring *wil_find_tx_ucast(struct wil6210_priv *wil, + struct wil6210_vif *vif, + struct sk_buff *skb) { int i; struct ethhdr *eth = (void *)skb->data; @@ -1150,13 +1118,13 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, return NULL; /* TODO: fix for multiple TID */ - for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) { - if (!wil->vring_tx_data[i].dot1x_open && - (skb->protocol != cpu_to_be16(ETH_P_PAE))) + for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++) { + if (!wil->ring_tx_data[i].dot1x_open && + skb->protocol != cpu_to_be16(ETH_P_PAE)) continue; - if (wil->vring2cid_tid[i][0] == cid) { - struct vring *v = &wil->vring_tx[i]; - struct vring_tx_data *txdata = &wil->vring_tx_data[i]; + if (wil->ring2cid_tid[i][0] == cid) { + struct wil_ring *v = &wil->ring_tx[i]; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i]; wil_dbg_txrx(wil, "find_tx_ucast: (%pM) -> [%d]\n", eth->h_dest, i); @@ -1175,41 +1143,41 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, } static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, - struct vring *vring, struct sk_buff *skb); + struct wil_ring *vring, struct sk_buff *skb); -static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, - struct wil6210_vif *vif, - struct sk_buff *skb) +static struct wil_ring *wil_find_tx_ring_sta(struct wil6210_priv *wil, + struct wil6210_vif *vif, + struct sk_buff *skb) { - struct vring *v; + struct wil_ring *ring; int i; u8 cid; - struct vring_tx_data *txdata; + struct wil_ring_tx_data *txdata; /* In the STA mode, it is expected to have only 1 VRING * for the AP we connected to. * find 1-st vring eligible for this skb and use it. */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { - v = &wil->vring_tx[i]; - txdata = &wil->vring_tx_data[i]; - if (!v->va || !txdata->enabled || txdata->mid != vif->mid) + ring = &wil->ring_tx[i]; + txdata = &wil->ring_tx_data[i]; + if (!ring->va || !txdata->enabled || txdata->mid != vif->mid) continue; - cid = wil->vring2cid_tid[i][0]; + cid = wil->ring2cid_tid[i][0]; if (cid >= WIL6210_MAX_CID) /* skip BCAST */ continue; - if (!wil->vring_tx_data[i].dot1x_open && - (skb->protocol != cpu_to_be16(ETH_P_PAE))) + if (!wil->ring_tx_data[i].dot1x_open && + skb->protocol != cpu_to_be16(ETH_P_PAE)) continue; wil_dbg_txrx(wil, "Tx -> ring %d\n", i); - return v; + return ring; } - wil_dbg_txrx(wil, "Tx while no vrings active?\n"); + wil_dbg_txrx(wil, "Tx while no rings active?\n"); return NULL; } @@ -1225,22 +1193,22 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, * Use old strategy when new is not supported yet: * - for PBSS */ -static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil, - struct wil6210_vif *vif, - struct sk_buff *skb) +static struct wil_ring *wil_find_tx_bcast_1(struct wil6210_priv *wil, + struct wil6210_vif *vif, + struct sk_buff *skb) { - struct vring *v; - struct vring_tx_data *txdata; - int i = vif->bcast_vring; + struct wil_ring *v; + struct wil_ring_tx_data *txdata; + int i = vif->bcast_ring; if (i < 0) return NULL; - v = &wil->vring_tx[i]; - txdata = &wil->vring_tx_data[i]; + v = &wil->ring_tx[i]; + txdata = &wil->ring_tx_data[i]; if (!v->va || !txdata->enabled) return NULL; - if (!wil->vring_tx_data[i].dot1x_open && - (skb->protocol != cpu_to_be16(ETH_P_PAE))) + if (!wil->ring_tx_data[i].dot1x_open && + skb->protocol != cpu_to_be16(ETH_P_PAE)) return NULL; return v; @@ -1250,35 +1218,35 @@ static void wil_set_da_for_vring(struct wil6210_priv *wil, struct sk_buff *skb, int vring_index) { struct ethhdr *eth = (void *)skb->data; - int cid = wil->vring2cid_tid[vring_index][0]; + int cid = wil->ring2cid_tid[vring_index][0]; ether_addr_copy(eth->h_dest, wil->sta[cid].addr); } -static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, - struct wil6210_vif *vif, - struct sk_buff *skb) +static struct wil_ring *wil_find_tx_bcast_2(struct wil6210_priv *wil, + struct wil6210_vif *vif, + struct sk_buff *skb) { - struct vring *v, *v2; + struct wil_ring *v, *v2; struct sk_buff *skb2; int i; u8 cid; struct ethhdr *eth = (void *)skb->data; char *src = eth->h_source; - struct vring_tx_data *txdata, *txdata2; + struct wil_ring_tx_data *txdata, *txdata2; /* find 1-st vring eligible for data */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { - v = &wil->vring_tx[i]; - txdata = &wil->vring_tx_data[i]; + v = &wil->ring_tx[i]; + txdata = &wil->ring_tx_data[i]; if (!v->va || !txdata->enabled || txdata->mid != vif->mid) continue; - cid = wil->vring2cid_tid[i][0]; + cid = wil->ring2cid_tid[i][0]; if (cid >= WIL6210_MAX_CID) /* skip BCAST */ continue; - if (!wil->vring_tx_data[i].dot1x_open && - (skb->protocol != cpu_to_be16(ETH_P_PAE))) + if (!wil->ring_tx_data[i].dot1x_open && + skb->protocol != cpu_to_be16(ETH_P_PAE)) continue; /* don't Tx back to source when re-routing Rx->Tx at the AP */ @@ -1298,15 +1266,15 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, /* find other active vrings and duplicate skb for each */ for (i++; i < WIL6210_MAX_TX_RINGS; i++) { - v2 = &wil->vring_tx[i]; - txdata2 = &wil->vring_tx_data[i]; + v2 = &wil->ring_tx[i]; + txdata2 = &wil->ring_tx_data[i]; if (!v2->va || txdata2->mid != vif->mid) continue; - cid = wil->vring2cid_tid[i][0]; + cid = wil->ring2cid_tid[i][0]; if (cid >= WIL6210_MAX_CID) /* skip BCAST */ continue; - if (!wil->vring_tx_data[i].dot1x_open && - (skb->protocol != cpu_to_be16(ETH_P_PAE))) + if (!wil->ring_tx_data[i].dot1x_open && + skb->protocol != cpu_to_be16(ETH_P_PAE)) continue; if (0 == memcmp(wil->sta[cid].addr, src, ETH_ALEN)) @@ -1454,7 +1422,7 @@ static inline void wil_set_tx_desc_last_tso(volatile struct vring_tx_desc *d) } static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, - struct vring *vring, struct sk_buff *skb) + struct wil_ring *vring, struct sk_buff *skb) { struct device *dev = wil_to_dev(wil); @@ -1474,13 +1442,13 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, int sg_desc_cnt = 0; /* number of descriptors for current mss*/ u32 swhead = vring->swhead; - int used, avail = wil_vring_avail_tx(vring); + int used, avail = wil_ring_avail_tx(vring); int nr_frags = skb_shinfo(skb)->nr_frags; int min_desc_required = nr_frags + 1; int mss = skb_shinfo(skb)->gso_size; /* payload size w/o headers */ int f, len, hdrlen, headlen; - int vring_index = vring - wil->vring_tx; - struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index]; + int vring_index = vring - wil->ring_tx; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[vring_index]; uint i = swhead; dma_addr_t pa; const skb_frag_t *frag = NULL; @@ -1548,7 +1516,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, tcp_hdr_len = tcp_hdrlen(skb); skb_net_hdr_len = skb_network_header_len(skb); - _hdr_desc = &vring->va[i].tx; + _hdr_desc = &vring->va[i].tx.legacy; pa = dma_map_single(dev, skb->data, hdrlen, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, pa))) { @@ -1613,7 +1581,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, goto mem_error; } - _desc = &vring->va[i].tx; + _desc = &vring->va[i].tx.legacy; if (!_first_desc) { _first_desc = _desc; @@ -1701,8 +1669,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, vring->ctx[i].skb = skb_get(skb); /* performance monitoring */ - used = wil_vring_used_tx(vring); - if (wil_val_in_range(wil->vring_idle_trsh, + used = wil_ring_used_tx(vring); + if (wil_val_in_range(wil->ring_idle_trsh, used, used + descs_used)) { txdata->idle += get_cycles() - txdata->last_idle; wil_dbg_txrx(wil, "Ring[%2d] not idle %d -> %d\n", @@ -1717,7 +1685,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, wmb(); /* advance swhead */ - wil_vring_advance_head(vring, descs_used); + wil_ring_advance_head(vring, descs_used); wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead); /* make sure all writes to descriptors (shared memory) are done before @@ -1733,8 +1701,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, struct wil_ctx *ctx; i = (swhead + descs_used - 1) % vring->size; - d = (struct vring_tx_desc *)&vring->va[i].tx; - _desc = &vring->va[i].tx; + d = (struct vring_tx_desc *)&vring->va[i].tx.legacy; + _desc = &vring->va[i].tx.legacy; *d = *_desc; _desc->dma.status = TX_DMA_STATUS_DU; ctx = &vring->ctx[i]; @@ -1747,25 +1715,25 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif, } static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, - struct vring *vring, struct sk_buff *skb) + struct wil_ring *vring, struct sk_buff *skb) { struct device *dev = wil_to_dev(wil); struct vring_tx_desc dd, *d = ⅆ volatile struct vring_tx_desc *_d; u32 swhead = vring->swhead; - int avail = wil_vring_avail_tx(vring); + int avail = wil_ring_avail_tx(vring); int nr_frags = skb_shinfo(skb)->nr_frags; uint f = 0; - int vring_index = vring - wil->vring_tx; - struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index]; + int vring_index = vring - wil->ring_tx; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[vring_index]; uint i = swhead; dma_addr_t pa; int used; - bool mcast = (vring_index == vif->bcast_vring); + bool mcast = (vring_index == vif->bcast_ring); uint len = skb_headlen(skb); - wil_dbg_txrx(wil, "tx_vring: %d bytes to vring %d\n", skb->len, - vring_index); + wil_dbg_txrx(wil, "tx_ring: %d bytes to ring %d, nr_frags %d\n", + skb->len, vring_index, nr_frags); if (unlikely(!txdata->enabled)) return -EINVAL; @@ -1776,7 +1744,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, vring_index, 1 + nr_frags); return -ENOMEM; } - _d = &vring->va[i].tx; + _d = &vring->va[i].tx.legacy; pa = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); @@ -1816,7 +1784,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, wil_hex_dump_txrx("TxD ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); i = (swhead + f + 1) % vring->size; - _d = &vring->va[i].tx; + _d = &vring->va[i].tx.legacy; pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); if (unlikely(dma_mapping_error(dev, pa))) { @@ -1848,8 +1816,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, vring->ctx[i].skb = skb_get(skb); /* performance monitoring */ - used = wil_vring_used_tx(vring); - if (wil_val_in_range(wil->vring_idle_trsh, + used = wil_ring_used_tx(vring); + if (wil_val_in_range(wil->ring_idle_trsh, used, used + nr_frags + 1)) { txdata->idle += get_cycles() - txdata->last_idle; wil_dbg_txrx(wil, "Ring[%2d] not idle %d -> %d\n", @@ -1864,7 +1832,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, wmb(); /* advance swhead */ - wil_vring_advance_head(vring, nr_frags + 1); + wil_ring_advance_head(vring, nr_frags + 1); wil_dbg_txrx(wil, "Tx[%2d] swhead %d -> %d\n", vring_index, swhead, vring->swhead); trace_wil6210_tx(vring_index, swhead, skb->len, nr_frags); @@ -1885,7 +1853,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, i = (swhead + f) % vring->size; ctx = &vring->ctx[i]; - _d = &vring->va[i].tx; + _d = &vring->va[i].tx.legacy; *d = *_d; _d->dma.status = TX_DMA_STATUS_DU; wil_txdesc_unmap(dev, d, ctx); @@ -1897,10 +1865,10 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, } static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, - struct vring *vring, struct sk_buff *skb) + struct wil_ring *vring, struct sk_buff *skb) { - int vring_index = vring - wil->vring_tx; - struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index]; + int ring_index = vring - wil->ring_tx; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_index]; int rc; spin_lock(&txdata->lock); @@ -1941,7 +1909,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif, */ static inline void __wil_update_net_queues(struct wil6210_priv *wil, struct wil6210_vif *vif, - struct vring *vring, + struct wil_ring *ring, bool check_stop) { int i; @@ -1949,9 +1917,9 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, if (unlikely(!vif)) return; - if (vring) + if (ring) wil_dbg_txrx(wil, "vring %d, mid %d, check_stop=%d, stopped=%d", - (int)(vring - wil->vring_tx), vif->mid, check_stop, + (int)(ring - wil->ring_tx), vif->mid, check_stop, vif->net_queue_stopped); else wil_dbg_txrx(wil, "check_stop=%d, mid=%d, stopped=%d", @@ -1962,7 +1930,7 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, return; if (check_stop) { - if (!vring || unlikely(wil_vring_avail_low(vring))) { + if (!ring || unlikely(wil_ring_avail_low(ring))) { /* not enough room in the vring */ netif_tx_stop_all_queues(vif_to_ndev(vif)); vif->net_queue_stopped = true; @@ -1978,22 +1946,22 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, /* check wake */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { - struct vring *cur_vring = &wil->vring_tx[i]; - struct vring_tx_data *txdata = &wil->vring_tx_data[i]; + struct wil_ring *cur_ring = &wil->ring_tx[i]; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[i]; - if (txdata->mid != vif->mid || !cur_vring->va || - !txdata->enabled || cur_vring == vring) + if (txdata->mid != vif->mid || !cur_ring->va || + !txdata->enabled || cur_ring == ring) continue; - if (wil_vring_avail_low(cur_vring)) { - wil_dbg_txrx(wil, "vring %d full, can't wake\n", - (int)(cur_vring - wil->vring_tx)); + if (wil_ring_avail_low(cur_ring)) { + wil_dbg_txrx(wil, "ring %d full, can't wake\n", + (int)(cur_ring - wil->ring_tx)); return; } } - if (!vring || wil_vring_avail_high(vring)) { - /* enough room in the vring */ + if (!ring || wil_ring_avail_high(ring)) { + /* enough room in the ring */ wil_dbg_txrx(wil, "calling netif_tx_wake\n"); netif_tx_wake_all_queues(vif_to_ndev(vif)); vif->net_queue_stopped = false; @@ -2001,18 +1969,18 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil, } void wil_update_net_queues(struct wil6210_priv *wil, struct wil6210_vif *vif, - struct vring *vring, bool check_stop) + struct wil_ring *ring, bool check_stop) { spin_lock(&wil->net_queue_lock); - __wil_update_net_queues(wil, vif, vring, check_stop); + __wil_update_net_queues(wil, vif, ring, check_stop); spin_unlock(&wil->net_queue_lock); } void wil_update_net_queues_bh(struct wil6210_priv *wil, struct wil6210_vif *vif, - struct vring *vring, bool check_stop) + struct wil_ring *ring, bool check_stop) { spin_lock_bh(&wil->net_queue_lock); - __wil_update_net_queues(wil, vif, vring, check_stop); + __wil_update_net_queues(wil, vif, ring, check_stop); spin_unlock_bh(&wil->net_queue_lock); } @@ -2022,7 +1990,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct wil6210_priv *wil = vif_to_wil(vif); struct ethhdr *eth = (void *)skb->data; bool bcast = is_multicast_ether_addr(eth->h_dest); - struct vring *vring; + struct wil_ring *vring; static bool pr_once_fw; int rc; @@ -2048,7 +2016,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) /* find vring */ if (vif->wdev.iftype == NL80211_IFTYPE_STATION && !vif->pbss) { /* in STA mode (ESS), all to same VRING (to AP) */ - vring = wil_find_tx_vring_sta(wil, vif, skb); + vring = wil_find_tx_ring_sta(wil, vif, skb); } else if (bcast) { if (vif->pbss) /* in pbss, no bcast VRING - duplicate skb in @@ -2068,7 +2036,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) vring = wil_find_tx_ucast(wil, vif, skb); } if (unlikely(!vring)) { - wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); + wil_dbg_txrx(wil, "No Tx RING found for %pM\n", eth->h_dest); goto drop; } /* set up vring entry */ @@ -2121,10 +2089,10 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid) struct wil6210_priv *wil = vif_to_wil(vif); struct net_device *ndev = vif_to_ndev(vif); struct device *dev = wil_to_dev(wil); - struct vring *vring = &wil->vring_tx[ringid]; - struct vring_tx_data *txdata = &wil->vring_tx_data[ringid]; + struct wil_ring *vring = &wil->ring_tx[ringid]; + struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ringid]; int done = 0; - int cid = wil->vring2cid_tid[ringid][0]; + int cid = wil->ring2cid_tid[ringid][0]; struct wil_net_stats *stats = NULL; volatile struct vring_tx_desc *_d; int used_before_complete; @@ -2142,12 +2110,12 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid) wil_dbg_txrx(wil, "tx_complete: (%d)\n", ringid); - used_before_complete = wil_vring_used_tx(vring); + used_before_complete = wil_ring_used_tx(vring); if (cid < WIL6210_MAX_CID) stats = &wil->sta[cid].stats; - while (!wil_vring_is_empty(vring)) { + while (!wil_ring_is_empty(vring)) { int new_swtail; struct wil_ctx *ctx = &vring->ctx[vring->swtail]; /** @@ -2158,7 +2126,7 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid) int lf = (vring->swtail + ctx->nr_frags) % vring->size; /* TODO: check we are not past head */ - _d = &vring->va[lf].tx; + _d = &vring->va[lf].tx.legacy; if (unlikely(!(_d->dma.status & TX_DMA_STATUS_DU))) break; @@ -2170,7 +2138,7 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid) ctx = &vring->ctx[vring->swtail]; skb = ctx->skb; - _d = &vring->va[vring->swtail].tx; + _d = &vring->va[vring->swtail].tx.legacy; *d = *_d; @@ -2203,7 +2171,7 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid) } memset(ctx, 0, sizeof(*ctx)); /* Make sure the ctx is zeroed before updating the tail - * to prevent a case where wil_tx_vring will see + * to prevent a case where wil_tx_ring will see * this descriptor as used and handle it before ctx zero * is completed. */ @@ -2213,14 +2181,14 @@ int wil_tx_complete(struct wil6210_vif *vif, int ringid) * so hardware will not try to process this desc., * - rest of descriptor will be initialized on Tx. */ - vring->swtail = wil_vring_next_tail(vring); + vring->swtail = wil_ring_next_tail(vring); done++; } } /* performance monitoring */ - used_new = wil_vring_used_tx(vring); - if (wil_val_in_range(wil->vring_idle_trsh, + used_new = wil_ring_used_tx(vring); + if (wil_val_in_range(wil->ring_idle_trsh, used_new, used_before_complete)) { wil_dbg_txrx(wil, "Ring[%2d] idle %d -> %d\n", ringid, used_before_complete, used_new); diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 5f07717..66217f8 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -18,6 +18,9 @@ #ifndef WIL6210_TXRX_H #define WIL6210_TXRX_H +#include "wil6210.h" +#include "txrx_edma.h" + #define BUF_SW_OWNED (1) #define BUF_HW_OWNED (0) @@ -29,19 +32,13 @@ /* Tx/Rx path */ -/* Common representation of physical address in Vring */ -struct vring_dma_addr { - __le32 addr_low; - __le16 addr_high; -} __packed; - -static inline dma_addr_t wil_desc_addr(struct vring_dma_addr *addr) +static inline dma_addr_t wil_desc_addr(struct wil_ring_dma_addr *addr) { return le32_to_cpu(addr->addr_low) | ((u64)le16_to_cpu(addr->addr_high) << 32); } -static inline void wil_desc_addr_set(struct vring_dma_addr *addr, +static inline void wil_desc_addr_set(struct wil_ring_dma_addr *addr, dma_addr_t pa) { addr->addr_low = cpu_to_le32(lower_32_bits(pa)); @@ -294,7 +291,7 @@ struct vring_tx_mac { */ struct vring_tx_dma { u32 d0; - struct vring_dma_addr addr; + struct wil_ring_dma_addr addr; u8 ip_length; u8 b11; /* 0..6: mac_length; 7:ip_version */ u8 error; /* 0..2: err; 3..7: reserved; */ @@ -428,7 +425,7 @@ struct vring_rx_mac { struct vring_rx_dma { u32 d0; - struct vring_dma_addr addr; + struct wil_ring_dma_addr addr; u8 ip_length; u8 b11; u8 error; @@ -441,14 +438,24 @@ struct vring_tx_desc { struct vring_tx_dma dma; } __packed; +union wil_tx_desc { + struct vring_tx_desc legacy; + struct wil_tx_enhanced_desc enhanced; +} __packed; + struct vring_rx_desc { struct vring_rx_mac mac; struct vring_rx_dma dma; } __packed; -union vring_desc { - struct vring_tx_desc tx; - struct vring_rx_desc rx; +union wil_rx_desc { + struct vring_rx_desc legacy; + struct wil_rx_enhanced_desc enhanced; +} __packed; + +union wil_ring_desc { + union wil_tx_desc tx; + union wil_rx_desc rx; } __packed; static inline int wil_rxdesc_tid(struct vring_rx_desc *d) @@ -528,6 +535,41 @@ static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) return (void *)skb->cb; } +static inline int wil_ring_is_empty(struct wil_ring *ring) +{ + return ring->swhead == ring->swtail; +} + +static inline u32 wil_ring_next_tail(struct wil_ring *ring) +{ + return (ring->swtail + 1) % ring->size; +} + +static inline void wil_ring_advance_head(struct wil_ring *ring, int n) +{ + ring->swhead = (ring->swhead + n) % ring->size; +} + +static inline int wil_ring_is_full(struct wil_ring *ring) +{ + return wil_ring_next_tail(ring) == ring->swhead; +} + +/* Used space in Tx ring */ +static inline int wil_ring_used_tx(struct wil_ring *ring) +{ + u32 swhead = ring->swhead; + u32 swtail = ring->swtail; + + return (ring->size + swhead - swtail) % ring->size; +} + +/* Available space in Tx ring */ +static inline int wil_ring_avail_tx(struct wil_ring *ring) +{ + return ring->size - wil_ring_used_tx(ring) - 1; +} + 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, struct wil6210_vif *vif, diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h new file mode 100644 index 0000000..14e0b6c --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2012-2016,2018, 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. + */ + +#ifndef WIL6210_TXRX_EDMA_H +#define WIL6210_TXRX_EDMA_H + +#include "wil6210.h" + +/* Enhanced Rx descriptor - MAC part + * [dword 0] : Reserved + * [dword 1] : Reserved + * [dword 2] : Reserved + * [dword 3] + * bit 0..15 : Buffer ID + * bit 16..31 : Reserved + */ +struct wil_ring_rx_enhanced_mac { + u32 d[3]; + __le16 buff_id; + u16 reserved; +} __packed; + +/* Enhanced Rx descriptor - DMA part + * [dword 0] - Reserved + * [dword 1] + * bit 0..31 : addr_low:32 The payload buffer address, bits 0-31 + * [dword 2] + * bit 0..15 : addr_high_low:16 The payload buffer address, bits 32-47 + * bit 16..31 : Reserved + * [dword 3] + * bit 0..15 : addr_high_high:16 The payload buffer address, bits 48-63 + * bit 16..31 : length + */ +struct wil_ring_rx_enhanced_dma { + u32 d0; + struct wil_ring_dma_addr addr; + u16 w5; + __le16 addr_high_high; + __le16 length; +} __packed; + +struct wil_rx_enhanced_desc { + struct wil_ring_rx_enhanced_mac mac; + struct wil_ring_rx_enhanced_dma dma; +} __packed; + +/* Enhanced Tx descriptor - DMA part + * [dword 0] + * Same as legacy + * [dword 1] + * bit 0..31 : addr_low:32 The payload buffer address, bits 0-31 + * [dword 2] + * bit 0..15 : addr_high_low:16 The payload buffer address, bits 32-47 + * bit 16..23 : ip_length:8 The IP header length for the TX IP checksum + * offload feature + * bit 24..30 : mac_length:7 + * bit 31 : ip_version:1 1 - IPv4, 0 - IPv6 + * [dword 3] + * bit 0..15 : addr_high_high:16 The payload buffer address, bits 48-63 + * bit 16..31 : length + */ +struct wil_ring_tx_enhanced_dma { + u8 l4_hdr_len; + u8 cmd; + u16 w1; + struct wil_ring_dma_addr addr; + u8 ip_length; + u8 b11; /* 0..6: mac_length; 7:ip_version */ + __le16 addr_high_high; + __le16 length; +} __packed; + +/* Enhanced Tx descriptor - MAC part + * [dword 0] + * bit 0.. 9 : lifetime_expiry_value:10 + * bit 10 : interrupt_en:1 + * bit 11 : status_en:1 + * bit 12..13 : txss_override:2 + * bit 14 : timestamp_insertion:1 + * bit 15 : duration_preserve:1 + * bit 16..21 : reserved0:6 + * bit 22..26 : mcs_index:5 + * bit 27 : mcs_en:1 + * bit 28..30 : reserved1:3 + * bit 31 : sn_preserved:1 + * [dword 1] + * bit 0.. 3 : pkt_mode:4 + * bit 4 : pkt_mode_en:1 + * bit 5..14 : reserved0:10 + * bit 15 : ack_policy_en:1 + * bit 16..19 : dst_index:4 + * bit 20 : dst_index_en:1 + * bit 21..22 : ack_policy:2 + * bit 23 : lifetime_en:1 + * bit 24..30 : max_retry:7 + * bit 31 : max_retry_en:1 + * [dword 2] + * bit 0.. 7 : num_of_descriptors:8 + * bit 8..17 : reserved:10 + * bit 18..19 : l2_translation_type:2 00 - bypass, 01 - 802.3, 10 - 802.11 + * bit 20 : snap_hdr_insertion_en:1 + * bit 21 : vlan_removal_en:1 + * bit 22..23 : reserved0:2 + * bit 24 : Dest ID extension:1 + * bit 25..31 : reserved0:7 + * [dword 3] + * bit 0..15 : tso_mss:16 + * bit 16..31 : descriptor_scratchpad:16 - mailbox between driver and ucode + */ +struct wil_ring_tx_enhanced_mac { + u32 d[3]; + __le16 tso_mss; + u16 scratchpad; +} __packed; + +struct wil_tx_enhanced_desc { + struct wil_ring_tx_enhanced_mac mac; + struct wil_ring_tx_enhanced_dma dma; +} __packed; + +#define TX_STATUS_DESC_READY_POS 7 + +/* Enhanced TX status message + * [dword 0] + * bit 0.. 7 : Number of Descriptor:8 - The number of descriptors that + * are used to form the packets. It is needed for WB when + * releasing the packet + * bit 8..15 : tx_ring_id:8 The transmission ring ID that is related to + * the message + * bit 16..23 : Status:8 - The TX status Code + * 0x0 - A successful transmission + * 0x1 - Retry expired + * 0x2 - Lifetime Expired + * 0x3 - Released + * 0x4-0xFF - Reserved + * bit 24..30 : Reserved:7 + * bit 31 : Descriptor Ready bit:1 - It is initiated to + * zero by the driver when the ring is created. It is set by the HW + * to one for each completed status message. Each wrap around, + * the DR bit value is flipped. + * [dword 1] + * bit 0..31 : timestamp:32 - Set when MPDU is transmitted. + * [dword 2] + * bit 0.. 4 : MCS:5 - The transmitted MCS value + * bit 5 : Reserved:1 + * bit 6.. 7 : CB mode:2 - 0-DMG 1-EDMG 2-Wide + * bit 8..12 : QID:5 - The QID that was used for the transmission + * bit 13..15 : Reserved:3 + * bit 16..20 : Num of MSDUs:5 - Number of MSDUs in the aggregation + * bit 21..22 : Reserved:2 + * bit 23 : Retry:1 - An indication that the transmission was retried + * bit 24..31 : TX-Sector:8 - the antenna sector that was used for + * transmission + * [dword 3] + * bit 0..11 : Sequence number:12 - The Sequence Number that was used + * for the MPDU transmission + * bit 12..31 : Reserved:20 + */ +struct wil_ring_tx_status { + u8 num_descriptors; + u8 ring_id; + u8 status; + u8 desc_ready; /* Only the last bit should be set */ + u32 timestamp; + u32 d2; + u16 seq_number; /* Only the first 12 bits */ + u16 w7; +} __packed; + +/* Enhanced Rx status message - compressed part + * [dword 0] + * bit 0.. 2 : L2 Rx Status:3 - The L2 packet reception Status + * 0-Success, 1-MIC Error, 2-Key Error, 3-Replay Error, + * 4-A-MSDU Error, 5-Reserved, 6-Reserved, 7-FCS Error + * bit 3.. 4 : L3 Rx Status:2 - Bit0 - L3I - L3 identified and checksum + * calculated, Bit1- L3Err - IPv4 Checksum Error + * bit 5.. 6 : L4 Rx Status:2 - Bit0 - L4I - L4 identified and checksum + * calculated, Bit1- L4Err - TCP/UDP Checksum Error + * bit 7 : Reserved:1 + * bit 8..19 : Flow ID:12 - MSDU flow ID + * bit 20..21 : MID:2 - The MAC ID + * bit 22 : MID_V:1 - The MAC ID field is valid + * bit 23 : L3T:1 - IP types: 0-IPv6, 1-IPv4 + * bit 24 : L4T:1 - Layer 4 Type: 0-UDP, 1-TCP + * bit 25 : BC:1 - The received MPDU is broadcast + * bit 26 : MC:1 - The received MPDU is multicast + * bit 27 : Raw:1 - The MPDU received with no translation + * bit 28 : Sec:1 - The FC control (b14) - Frame Protected + * bit 29 : Error:1 - An error is set when (L2 status != 0) || + * (L3 status == 3) || (L4 status == 3) + * bit 30 : EOP:1 - End of MSDU signaling. It is set to mark the end + * of the transfer, otherwise the status indicates buffer + * only completion. + * bit 31 : Descriptor Ready bit:1 - It is initiated to + * zero by the driver when the ring is created. It is set + * by the HW to one for each completed status message. + * Each wrap around, the DR bit value is flipped. + * [dword 1] + * bit 0.. 5 : MAC Len:6 - The number of bytes that are used for L2 header + * bit 6..11 : IPLEN:6 - The number of DW that are used for L3 header + * bit 12..15 : I4Len:4 - The number of DW that are used for L4 header + * bit 16..21 : MCS:6 - The received MCS field from the PLCP Header + * bit 22..23 : CB mode:2 - The CB Mode: 0-DMG, 1-EDMG, 2-Wide + * bit 24..27 : Data Offset:4 - The data offset, a code that describe the + * payload shift from the beginning of the buffer: + * 0 - 0 Bytes, 1 - 2 Bytes, 2 - 6 Bytes + * bit 28 : A-MSDU Present:1 - The QoS (b7) A-MSDU present field + * bit 29 : A-MSDU Type:1 The QoS (b8) A-MSDU Type field + * bit 30 : A-MPDU:1 - Packet is part of aggregated MPDU + * bit 31 : Key ID:1 - The extracted Key ID from the encryption header + * [dword 2] + * bit 0..15 : Buffer ID:16 - The Buffer Identifier + * bit 16..31 : Length:16 - It indicates the valid bytes that are stored + * in the current descriptor buffer. For multiple buffer + * descriptor, SW need to sum the total descriptor length + * in all buffers to produce the packet length + * [dword 3] + * bit 0..31 : timestamp:32 - The MPDU Timestamp. + */ +struct wil_rx_status_compressed { + u32 d0; + u32 d1; + __le16 buff_id; + __le16 length; + u32 timestamp; +} __packed; + +/* Enhanced Rx status message - extension part + * [dword 0] + * bit 0.. 4 : QID:5 - The Queue Identifier that the packet is received + * from + * bit 5.. 7 : Reserved:3 + * bit 8..11 : TID:4 - The QoS (b3-0) TID Field + * bit 12..15 Source index:4 - The Source index that was found + during Parsing the TA. This field is used to define the + source of the packet + * bit 16..18 : Destination index:3 - The Destination index that + was found during Parsing the RA. + * bit 19..20 : DS Type:2 - The FC Control (b9-8) - From / To DS + * bit 21..22 : MIC ICR:2 - this signal tells the DMA to assert an + interrupt after it writes the packet + * bit 23 : ESOP:1 - The QoS (b4) ESOP field + * bit 24 : RDG:1 + * bit 25..31 : Reserved:7 + * [dword 1] + * bit 0.. 1 : Frame Type:2 - The FC Control (b3-2) - MPDU Type + (management, data, control and extension) + * bit 2.. 5 : Syb type:4 - The FC Control (b7-4) - Frame Subtype + * bit 6..11 : Ext sub type:6 - The FC Control (b11-8) - Frame Extended + * Subtype + * bit 12..13 : ACK Policy:2 - The QoS (b6-5) ACK Policy fields + * bit 14 : DECRYPT_BYP:1 - The MPDU is bypass by the decryption unit + * bit 15..23 : Reserved:9 + * bit 24..31 : RSSI/SNR:8 - The RSSI / SNR measurement for the received + * MPDU + * [dword 2] + * bit 0..11 : SN:12 - The received Sequence number field + * bit 12..15 : Reserved:4 + * bit 16..31 : PN bits [15:0]:16 + * [dword 3] + * bit 0..31 : PN bits [47:16]:32 + */ +struct wil_rx_status_extension { + u32 d0; + u32 d1; + __le16 seq_num; /* only lower 12 bits */ + u16 pn_15_0; + u32 pn_47_16; +} __packed; + +struct wil_rx_status_extended { + struct wil_rx_status_compressed comp; + struct wil_rx_status_extension ext; +}; + +#endif /* WIL6210_TXRX_EDMA_H */ + diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 4cd8e40..810ed5b 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -80,6 +80,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ #define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */ #define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */ +#define WIL6210_MAX_STATUS_RINGS (8) + /* Hardware offload block adds the following: * 26 bytes - 3-address QoS data header * 8 bytes - IV + EIV (for GCMP) @@ -359,6 +361,12 @@ enum { #define TALYN_MB_FW_MAPPING_TABLE_SIZE 19 #define MAX_FW_MAPPING_TABLE_SIZE 19 +/* Common representation of physical address in wil ring */ +struct wil_ring_dma_addr { + __le32 addr_low; + __le16 addr_high; +} __packed; + struct fw_map { u32 from; /* linker address - from, inclusive */ u32 to; /* linker address - to, exclusive */ @@ -447,7 +455,7 @@ enum { /* for wil_ctx.mapped_as */ }; /** - * struct wil_ctx - software context for Vring descriptor + * struct wil_ctx - software context for ring descriptor */ struct wil_ctx { struct sk_buff *skb; @@ -455,22 +463,59 @@ struct wil_ctx { u8 mapped_as; }; -union vring_desc; +struct wil_desc_ring_rx_swtail { /* relevant for enhanced DMA only */ + u32 *va; + dma_addr_t pa; +}; -struct vring { +/** + * A general ring structure, used for RX and TX. + * In legacy DMA it represents the vring, + * In enahnced DMA it represents the descriptor ring (vrings are handled by FW) + */ +struct wil_ring { dma_addr_t pa; - volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */ - u16 size; /* number of vring_desc elements */ + volatile union wil_ring_desc *va; + u16 size; /* number of wil_ring_desc elements */ u32 swtail; u32 swhead; u32 hwtail; /* write here to inform hw */ struct wil_ctx *ctx; /* ctx[size] - software context */ + struct wil_desc_ring_rx_swtail edma_rx_swtail; + bool is_rx; }; /** - * Additional data for Tx Vring + * Additional data for Rx ring. + * Used for enhanced DMA RX chaining. */ -struct vring_tx_data { +struct wil_ring_rx_data { + /* the skb being assembled */ + struct sk_buff *skb; + /* true if we are skipping a bad fragmented packet */ + bool skipping; + u16 buff_size; +}; + +/** + * Status ring structure, used for enhanced DMA completions for RX and TX. + */ +struct wil_status_ring { + dma_addr_t pa; + void *va; /* pointer to ring_[tr]x_status elements */ + u16 size; /* number of status elements */ + size_t elem_size; /* status element size in bytes */ + u32 swhead; + u32 hwtail; /* write here to inform hw */ + bool is_rx; + u8 desc_rdy_pol; /* Expected descriptor ready bit polarity */ + struct wil_ring_rx_data rx_data; +}; + +/** + * Additional data for Tx ring + */ +struct wil_ring_tx_data { bool dot1x_open; int enabled; cycles_t idle, last_idle, begin; @@ -573,6 +618,9 @@ struct wil_net_stats { unsigned long rx_short_frame; unsigned long rx_large_frame; unsigned long rx_replay; + unsigned long rx_mic_error; /* eDMA specific */ + unsigned long rx_key_error; /* eDMA specific */ + unsigned long rx_amsdu_error; /* eDMA specific */ u16 last_mcs_rx; u64 rx_per_mcs[WIL_MCS_MAX + 1]; }; @@ -690,7 +738,7 @@ struct wil6210_vif { u8 hidden_ssid; /* relevant in AP mode */ u32 ap_isolate; /* no intra-BSS communication */ bool pbss; - int bcast_vring; + int bcast_ring; struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */ int locally_generated_disc; /* relevant in STA mode */ struct timer_list connect_timer; @@ -706,6 +754,31 @@ struct wil6210_vif { int net_queue_stopped; /* netif_tx_stop_all_queues invoked */ }; +/** + * RX buffer allocated for enhanced DMA RX descriptors + */ +struct wil_rx_buff { + struct sk_buff *skb; + struct list_head list; + int id; +}; + +/** + * During Rx completion processing, the driver extracts a buffer ID which + * is used as an index to the rx_buff_mgmt.buff_arr array and then the SKB + * is given to the network stack and the buffer is moved from the 'active' + * list to the 'free' list. + * During Rx refill, SKBs are attached to free buffers and moved to the + * 'active' list. + */ +struct wil_rx_buff_mgmt { + struct wil_rx_buff *buff_arr; + size_t size; /* number of items in buff_arr */ + struct list_head active; + struct list_head free; + unsigned long free_list_empty_cnt; /* statistics */ +}; + struct wil6210_priv { struct pci_dev *pdev; u32 bar_size; @@ -770,14 +843,17 @@ struct wil6210_priv { struct net_device napi_ndev; /* dummy net_device serving all VIFs */ /* DMA related */ - struct vring vring_rx; + struct wil_ring ring_rx; unsigned int rx_buf_len; - struct vring vring_tx[WIL6210_MAX_TX_RINGS]; - struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS]; - u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */ + struct wil_ring ring_tx[WIL6210_MAX_TX_RINGS]; + struct wil_ring_tx_data ring_tx_data[WIL6210_MAX_TX_RINGS]; + struct wil_status_ring srings[WIL6210_MAX_STATUS_RINGS]; + int num_rx_status_rings; + u8 ring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */ struct wil_sta_info sta[WIL6210_MAX_CID]; - u32 vring_idle_trsh; /* HW fetches up to 16 descriptors at once */ + u32 ring_idle_trsh; /* HW fetches up to 16 descriptors at once */ u32 dma_addr_size; /* indicates dma addr size */ + struct wil_rx_buff_mgmt rx_buff_mgmt; struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ /* statistics */ @@ -999,7 +1075,7 @@ int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index, int key_usage); int wmi_echo(struct wil6210_priv *wil); int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie); -int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); +int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring); int wmi_rxon(struct wil6210_priv *wil, bool on); int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, @@ -1098,7 +1174,7 @@ void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid, /* TX API */ int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, int cid, int tid); -void wil_vring_fini_tx(struct wil6210_priv *wil, int id); +void wil_ring_fini_tx(struct wil6210_priv *wil, int id); int wil_tx_init(struct wil6210_vif *vif, int cid); int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size); int wil_bcast_init(struct wil6210_vif *vif); @@ -1106,9 +1182,9 @@ int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, void wil_bcast_fini_all(struct wil6210_priv *wil); void wil_update_net_queues(struct wil6210_priv *wil, struct wil6210_vif *vif, - struct vring *vring, bool should_stop); + struct wil_ring *ring, bool should_stop); void wil_update_net_queues_bh(struct wil6210_priv *wil, struct wil6210_vif *vif, - struct vring *vring, bool check_stop); + struct wil_ring *ring, bool check_stop); netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); int wil_tx_complete(struct wil6210_vif *vif, int ringid); void wil6210_unmask_irq_tx(struct wil6210_priv *wil); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 5509f94..1cf8021 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1127,7 +1127,7 @@ static void wmi_evt_vring_en(struct wil6210_vif *vif, int id, void *d, int len) wil_dbg_wmi(wil, "Enable vring %d MID %d\n", vri, vif->mid); - if (vri >= ARRAY_SIZE(wil->vring_tx)) { + if (vri >= ARRAY_SIZE(wil->ring_tx)) { wil_err(wil, "Enable for invalid vring %d\n", vri); return; } @@ -1136,8 +1136,8 @@ static void wmi_evt_vring_en(struct wil6210_vif *vif, int id, void *d, int len) /* in AP mode with disable_ap_sme, this is done by * wil_cfg80211_change_station() */ - wil->vring_tx_data[vri].dot1x_open = true; - if (vri == vif->bcast_vring) /* no BA for bcast */ + wil->ring_tx_data[vri].dot1x_open = true; + if (vri == vif->bcast_ring) /* no BA for bcast */ return; if (agg_wsize >= 0) wil_addba_tx_request(wil, vri, agg_wsize); @@ -1148,7 +1148,7 @@ static void wmi_evt_ba_status(struct wil6210_vif *vif, int id, { struct wil6210_priv *wil = vif_to_wil(vif); struct wmi_ba_status_event *evt = d; - struct vring_tx_data *txdata; + struct wil_ring_tx_data *txdata; wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n", evt->ringid, @@ -1167,7 +1167,7 @@ static void wmi_evt_ba_status(struct wil6210_vif *vif, int id, evt->amsdu = 0; } - txdata = &wil->vring_tx_data[evt->ringid]; + txdata = &wil->ring_tx_data[evt->ringid]; txdata->agg_timeout = le16_to_cpu(evt->ba_timeout); txdata->agg_wsize = evt->agg_wsize; @@ -1205,11 +1205,11 @@ static void wmi_evt_delba(struct wil6210_vif *vif, int id, void *d, int len) if (!evt->from_initiator) { int i; /* find Tx vring it belongs to */ - for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) { - if ((wil->vring2cid_tid[i][0] == cid) && - (wil->vring2cid_tid[i][1] == tid)) { - struct vring_tx_data *txdata = - &wil->vring_tx_data[i]; + for (i = 0; i < ARRAY_SIZE(wil->ring2cid_tid); i++) { + if (wil->ring2cid_tid[i][0] == cid && + wil->ring2cid_tid[i][1] == tid) { + struct wil_ring_tx_data *txdata = + &wil->ring_tx_data[i]; wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i); txdata->agg_timeout = 0; @@ -1219,7 +1219,7 @@ static void wmi_evt_delba(struct wil6210_vif *vif, int id, void *d, int len) break; /* max. 1 matching ring */ } } - if (i >= ARRAY_SIZE(wil->vring2cid_tid)) + if (i >= ARRAY_SIZE(wil->ring2cid_tid)) wil_err(wil, "DELBA: unable to find Tx vring\n"); return; } @@ -1964,7 +1964,7 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) return rc; } -int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) +int wmi_rx_chain_add(struct wil6210_priv *wil, struct wil_ring *vring) { struct net_device *ndev = wil->main_ndev; struct wireless_dev *wdev = ndev->ieee80211_ptr; -- 1.9.1