mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-02-10 05:45:08 +07:00
wil6210: fix remaining use of non-cached copy of tx/rx descriptors
- Introduce common code for Tx/Rx descriptor physical address set/parse - Fix endianness for address fields - consistent descriptor naming: '_d' for non-cached memory, 'd' for cached copy - wil_tx_desc_map now modify cached copy, no need for 'volatile' Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
e0287c4ab8
commit
68ada71e33
@ -90,8 +90,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);
|
||||
d->dma.status = TX_DMA_STATUS_DU;
|
||||
volatile struct vring_tx_desc *_d = &(vring->va[i].tx);
|
||||
_d->dma.status = TX_DMA_STATUS_DU;
|
||||
}
|
||||
|
||||
wil_dbg_misc(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size,
|
||||
@ -107,14 +107,19 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
|
||||
size_t sz = vring->size * sizeof(vring->va[0]);
|
||||
|
||||
while (!wil_vring_is_empty(vring)) {
|
||||
dma_addr_t pa;
|
||||
struct sk_buff *skb;
|
||||
u16 dmalen;
|
||||
|
||||
if (tx) {
|
||||
volatile struct vring_tx_desc *d =
|
||||
struct vring_tx_desc dd, *d = ⅆ
|
||||
volatile struct vring_tx_desc *_d =
|
||||
&vring->va[vring->swtail].tx;
|
||||
dma_addr_t pa = d->dma.addr_low |
|
||||
((u64)d->dma.addr_high << 32);
|
||||
struct sk_buff *skb = vring->ctx[vring->swtail];
|
||||
|
||||
*d = *_d;
|
||||
pa = wil_desc_addr(&d->dma.addr);
|
||||
dmalen = le16_to_cpu(d->dma.length);
|
||||
skb = vring->ctx[vring->swtail];
|
||||
if (skb) {
|
||||
dma_unmap_single(dev, pa, dmalen,
|
||||
DMA_TO_DEVICE);
|
||||
@ -126,12 +131,14 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
|
||||
}
|
||||
vring->swtail = wil_vring_next_tail(vring);
|
||||
} else { /* rx */
|
||||
volatile struct vring_rx_desc *d =
|
||||
struct vring_rx_desc dd, *d = ⅆ
|
||||
volatile struct vring_rx_desc *_d =
|
||||
&vring->va[vring->swtail].rx;
|
||||
dma_addr_t pa = d->dma.addr_low |
|
||||
((u64)d->dma.addr_high << 32);
|
||||
struct sk_buff *skb = vring->ctx[vring->swhead];
|
||||
|
||||
*d = *_d;
|
||||
pa = wil_desc_addr(&d->dma.addr);
|
||||
dmalen = le16_to_cpu(d->dma.length);
|
||||
skb = vring->ctx[vring->swhead];
|
||||
dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE);
|
||||
kfree_skb(skb);
|
||||
wil_vring_advance_head(vring, 1);
|
||||
@ -154,7 +161,8 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
|
||||
{
|
||||
struct device *dev = wil_to_dev(wil);
|
||||
unsigned int sz = RX_BUF_LEN;
|
||||
volatile struct vring_rx_desc *d = &(vring->va[i].rx);
|
||||
struct vring_rx_desc dd, *d = ⅆ
|
||||
volatile struct vring_rx_desc *_d = &(vring->va[i].rx);
|
||||
dma_addr_t pa;
|
||||
|
||||
/* TODO align */
|
||||
@ -172,13 +180,13 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
|
||||
}
|
||||
|
||||
d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT;
|
||||
d->dma.addr_low = lower_32_bits(pa);
|
||||
d->dma.addr_high = (u16)upper_32_bits(pa);
|
||||
wil_desc_addr_set(&d->dma.addr, pa);
|
||||
/* ip_length don't care */
|
||||
/* b11 don't care */
|
||||
/* error don't care */
|
||||
d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
|
||||
d->dma.length = cpu_to_le16(sz);
|
||||
*_d = *d;
|
||||
vring->ctx[i] = skb;
|
||||
|
||||
return 0;
|
||||
@ -324,8 +332,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
{
|
||||
struct device *dev = wil_to_dev(wil);
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
volatile struct vring_rx_desc *d;
|
||||
struct vring_rx_desc *d1;
|
||||
volatile struct vring_rx_desc *_d;
|
||||
struct vring_rx_desc *d;
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t pa;
|
||||
unsigned int sz = RX_BUF_LEN;
|
||||
@ -338,20 +346,27 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
if (wil_vring_is_empty(vring))
|
||||
return NULL;
|
||||
|
||||
d = &(vring->va[vring->swhead].rx);
|
||||
if (!(d->dma.status & RX_DMA_STATUS_DU)) {
|
||||
_d = &(vring->va[vring->swhead].rx);
|
||||
if (!(_d->dma.status & RX_DMA_STATUS_DU)) {
|
||||
/* it is not error, we just reached end of Rx done area */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
|
||||
skb = vring->ctx[vring->swhead];
|
||||
dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
|
||||
|
||||
d1 = wil_skb_rxdesc(skb);
|
||||
*d1 = *d;
|
||||
d = wil_skb_rxdesc(skb);
|
||||
*d = *_d;
|
||||
pa = wil_desc_addr(&d->dma.addr);
|
||||
vring->ctx[vring->swhead] = NULL;
|
||||
wil_vring_advance_head(vring, 1);
|
||||
dmalen = le16_to_cpu(d1->dma.length);
|
||||
|
||||
dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
|
||||
dmalen = le16_to_cpu(d->dma.length);
|
||||
|
||||
trace_wil6210_rx(vring->swhead, d);
|
||||
wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead, dmalen);
|
||||
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
|
||||
if (dmalen > sz) {
|
||||
wil_err(wil, "Rx size too large: %d bytes!\n", dmalen);
|
||||
kfree(skb);
|
||||
@ -363,18 +378,12 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
skb->data, skb_headlen(skb), false);
|
||||
|
||||
|
||||
wil->stats.last_mcs_rx = wil_rxdesc_mcs(d1);
|
||||
wil->stats.last_mcs_rx = wil_rxdesc_mcs(d);
|
||||
|
||||
/* use radiotap header only if required */
|
||||
if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
|
||||
wil_rx_add_radiotap_header(wil, skb);
|
||||
|
||||
trace_wil6210_rx(vring->swhead, d1);
|
||||
wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", vring->swhead,
|
||||
d1->dma.length);
|
||||
wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d1, sizeof(*d1), false);
|
||||
|
||||
/* no extra checks if in sniffer mode */
|
||||
if (ndev->type != ARPHRD_ETHER)
|
||||
return skb;
|
||||
@ -383,7 +392,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
* Driver should recognize it by frame type, that is found
|
||||
* in Rx descriptor. If type is not data, it is 802.11 frame as is
|
||||
*/
|
||||
ftype = wil_rxdesc_ftype(d1) << 2;
|
||||
ftype = wil_rxdesc_ftype(d) << 2;
|
||||
if (ftype != IEEE80211_FTYPE_DATA) {
|
||||
wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype);
|
||||
/* TODO: process it */
|
||||
@ -398,7 +407,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ds_bits = wil_rxdesc_ds_bits(d1);
|
||||
ds_bits = wil_rxdesc_ds_bits(d);
|
||||
if (ds_bits == 1) {
|
||||
/*
|
||||
* HW bug - in ToDS mode, i.e. Rx on AP side,
|
||||
@ -612,11 +621,9 @@ static struct vring *wil_find_tx_vring(struct wil6210_priv *wil,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int wil_tx_desc_map(volatile struct vring_tx_desc *d,
|
||||
dma_addr_t pa, u32 len)
|
||||
static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len)
|
||||
{
|
||||
d->dma.addr_low = lower_32_bits(pa);
|
||||
d->dma.addr_high = (u16)upper_32_bits(pa);
|
||||
wil_desc_addr_set(&d->dma.addr, pa);
|
||||
d->dma.ip_length = 0;
|
||||
/* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/
|
||||
d->dma.b11 = 0/*14 | BIT(7)*/;
|
||||
@ -642,7 +649,8 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct device *dev = wil_to_dev(wil);
|
||||
volatile struct vring_tx_desc *d;
|
||||
struct vring_tx_desc dd, *d = ⅆ
|
||||
volatile struct vring_tx_desc *_d;
|
||||
u32 swhead = vring->swhead;
|
||||
int avail = wil_vring_avail_tx(vring);
|
||||
int nr_frags = skb_shinfo(skb)->nr_frags;
|
||||
@ -660,7 +668,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
1 + nr_frags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
d = &(vring->va[i].tx);
|
||||
_d = &(vring->va[i].tx);
|
||||
|
||||
/* FIXME FW can accept only unicast frames for the peer */
|
||||
memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN);
|
||||
@ -679,25 +687,30 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
wil_tx_desc_map(d, pa, skb_headlen(skb));
|
||||
d->mac.d[2] |= ((nr_frags + 1) <<
|
||||
MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
|
||||
if (nr_frags)
|
||||
*_d = *d;
|
||||
|
||||
/* middle segments */
|
||||
for (f = 0; f < nr_frags; f++) {
|
||||
const struct skb_frag_struct *frag =
|
||||
&skb_shinfo(skb)->frags[f];
|
||||
int len = skb_frag_size(frag);
|
||||
i = (swhead + f + 1) % vring->size;
|
||||
d = &(vring->va[i].tx);
|
||||
_d = &(vring->va[i].tx);
|
||||
pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag),
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev, pa)))
|
||||
goto dma_error;
|
||||
wil_tx_desc_map(d, pa, len);
|
||||
vring->ctx[i] = NULL;
|
||||
*_d = *d;
|
||||
}
|
||||
/* for the last seg only */
|
||||
d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS);
|
||||
d->dma.d0 |= BIT(9); /* BUG: undocumented bit */
|
||||
d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
|
||||
d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS);
|
||||
*_d = *d;
|
||||
|
||||
wil_hex_dump_txrx("Tx ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
@ -721,9 +734,10 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
u16 dmalen;
|
||||
|
||||
i = (swhead + f) % vring->size;
|
||||
d = &(vring->va[i].tx);
|
||||
d->dma.status = TX_DMA_STATUS_DU;
|
||||
pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
|
||||
_d = &(vring->va[i].tx);
|
||||
*d = *_d;
|
||||
_d->dma.status = TX_DMA_STATUS_DU;
|
||||
pa = wil_desc_addr(&d->dma.addr);
|
||||
dmalen = le16_to_cpu(d->dma.length);
|
||||
if (vring->ctx[i])
|
||||
dma_unmap_single(dev, pa, dmalen, DMA_TO_DEVICE);
|
||||
@ -806,14 +820,14 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
|
||||
|
||||
while (!wil_vring_is_empty(vring)) {
|
||||
volatile struct vring_tx_desc *d1 =
|
||||
volatile struct vring_tx_desc *_d =
|
||||
&vring->va[vring->swtail].tx;
|
||||
struct vring_tx_desc dd, *d = ⅆ
|
||||
dma_addr_t pa;
|
||||
struct sk_buff *skb;
|
||||
u16 dmalen;
|
||||
|
||||
dd = *d1;
|
||||
*d = *_d;
|
||||
|
||||
if (!(d->dma.status & TX_DMA_STATUS_DU))
|
||||
break;
|
||||
@ -828,7 +842,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
wil_hex_dump_txrx("TxC ", DUMP_PREFIX_NONE, 32, 4,
|
||||
(const void *)d, sizeof(*d), false);
|
||||
|
||||
pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
|
||||
pa = wil_desc_addr(&d->dma.addr);
|
||||
skb = vring->ctx[vring->swtail];
|
||||
if (skb) {
|
||||
if (d->dma.error == 0) {
|
||||
@ -844,8 +858,8 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
||||
} else {
|
||||
dma_unmap_page(dev, pa, dmalen, DMA_TO_DEVICE);
|
||||
}
|
||||
d->dma.addr_low = 0;
|
||||
d->dma.addr_high = 0;
|
||||
d->dma.addr.addr_low = 0;
|
||||
d->dma.addr.addr_high = 0;
|
||||
d->dma.length = 0;
|
||||
d->dma.status = TX_DMA_STATUS_DU;
|
||||
vring->swtail = wil_vring_next_tail(vring);
|
||||
|
@ -27,6 +27,28 @@
|
||||
#define WIL6210_RTAP_SIZE (128)
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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,
|
||||
dma_addr_t pa)
|
||||
{
|
||||
addr->addr_low = cpu_to_le32(lower_32_bits(pa));
|
||||
addr->addr_high = cpu_to_le16((u16)upper_32_bits(pa));
|
||||
}
|
||||
|
||||
/*
|
||||
* Tx descriptor - MAC part
|
||||
* [dword 0]
|
||||
@ -216,8 +238,7 @@ struct vring_tx_mac {
|
||||
|
||||
struct vring_tx_dma {
|
||||
u32 d0;
|
||||
u32 addr_low;
|
||||
u16 addr_high;
|
||||
struct vring_dma_addr addr;
|
||||
u8 ip_length;
|
||||
u8 b11; /* 0..6: mac_length; 7:ip_version */
|
||||
u8 error; /* 0..2: err; 3..7: reserved; */
|
||||
@ -315,8 +336,7 @@ struct vring_rx_mac {
|
||||
|
||||
struct vring_rx_dma {
|
||||
u32 d0;
|
||||
u32 addr_low;
|
||||
u16 addr_high;
|
||||
struct vring_dma_addr addr;
|
||||
u8 ip_length;
|
||||
u8 b11;
|
||||
u8 error;
|
||||
|
Loading…
Reference in New Issue
Block a user