diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath/wil6210/cfg80211.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/debugfs.c | 111 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/netdev.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/rx_reorder.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.c | 356 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx.h | 68 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/txrx_edma.h | 290 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 110 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wmi.c | 24 |
10 files changed, 696 insertions, 319 deletions
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 78946f28d0c7..dfe64b06654f 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 ebfdff4d328c..55e03e9b49eb 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 const struct { 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 const struct dbg_off dbg_wil_off[] = { 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 const struct dbg_off dbg_wil_regs[] = { /* 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 1282e1a63f92..bfe628481e22 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -219,9 +219,9 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) 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 @@ out: 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 eb6c14ed65a4..3c6a59fd08df 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 76f8084c1fd8..a586929f72d4 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 b9a9fa828961..55946dec5110 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 @@ again: 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 @@ again: 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 @@ found: /* 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 @@ mem_error: 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 @@ err_exit: } 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 5f07717acc2c..66217f815726 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 000000000000..14e0b6ce6dc4 --- /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 4cd8e4030fe9..810ed5b8e558 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 wil_rx_fini(struct wil6210_priv *wil); /* 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 @@ void wil_bcast_fini(struct wil6210_vif *vif); 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 5509f9474f9c..1cf802101dd9 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 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) 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 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) 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; |