mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-18 17:54:13 +08:00
ath9k: get rid of double queueing of rx frames on EDMA
Process rx status directly instead of separating the completion test from the actual rx status processing. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
fc16fd8808
commit
3a2923e83c
@ -436,20 +436,14 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
|
|||||||
struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
|
struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
|
||||||
unsigned int phyerr;
|
unsigned int phyerr;
|
||||||
|
|
||||||
/* TODO: byte swap on big endian for ar9300_10 */
|
if ((rxsp->status11 & AR_RxDone) == 0)
|
||||||
|
return -EINPROGRESS;
|
||||||
|
|
||||||
if (!rxs) {
|
if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
|
||||||
if ((rxsp->status11 & AR_RxDone) == 0)
|
return -EINVAL;
|
||||||
return -EINPROGRESS;
|
|
||||||
|
|
||||||
if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
|
if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
|
||||||
return -EINVAL;
|
return -EINPROGRESS;
|
||||||
|
|
||||||
if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
|
|
||||||
return -EINPROGRESS;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rxs->rs_status = 0;
|
rxs->rs_status = 0;
|
||||||
rxs->rs_flags = 0;
|
rxs->rs_flags = 0;
|
||||||
|
@ -299,7 +299,6 @@ struct ath_tx {
|
|||||||
|
|
||||||
struct ath_rx_edma {
|
struct ath_rx_edma {
|
||||||
struct sk_buff_head rx_fifo;
|
struct sk_buff_head rx_fifo;
|
||||||
struct sk_buff_head rx_buffers;
|
|
||||||
u32 rx_fifo_hwsize;
|
u32 rx_fifo_hwsize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -227,7 +227,6 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc)
|
|||||||
static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
|
static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
|
||||||
{
|
{
|
||||||
skb_queue_head_init(&rx_edma->rx_fifo);
|
skb_queue_head_init(&rx_edma->rx_fifo);
|
||||||
skb_queue_head_init(&rx_edma->rx_buffers);
|
|
||||||
rx_edma->rx_fifo_hwsize = size;
|
rx_edma->rx_fifo_hwsize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,7 +652,9 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool ath_edma_get_buffers(struct ath_softc *sc,
|
static bool ath_edma_get_buffers(struct ath_softc *sc,
|
||||||
enum ath9k_rx_qtype qtype)
|
enum ath9k_rx_qtype qtype,
|
||||||
|
struct ath_rx_status *rs,
|
||||||
|
struct ath_buf **dest)
|
||||||
{
|
{
|
||||||
struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
|
struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
|
||||||
struct ath_hw *ah = sc->sc_ah;
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
@ -672,7 +673,7 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
|
|||||||
dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
|
dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
|
||||||
common->rx_bufsize, DMA_FROM_DEVICE);
|
common->rx_bufsize, DMA_FROM_DEVICE);
|
||||||
|
|
||||||
ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data);
|
ret = ath9k_hw_process_rxdesc_edma(ah, rs, skb->data);
|
||||||
if (ret == -EINPROGRESS) {
|
if (ret == -EINPROGRESS) {
|
||||||
/*let device gain the buffer again*/
|
/*let device gain the buffer again*/
|
||||||
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
|
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
|
||||||
@ -685,20 +686,21 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
|
|||||||
/* corrupt descriptor, skip this one and the following one */
|
/* corrupt descriptor, skip this one and the following one */
|
||||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||||
ath_rx_edma_buf_link(sc, qtype);
|
ath_rx_edma_buf_link(sc, qtype);
|
||||||
|
|
||||||
skb = skb_peek(&rx_edma->rx_fifo);
|
skb = skb_peek(&rx_edma->rx_fifo);
|
||||||
if (!skb)
|
if (skb) {
|
||||||
return true;
|
bf = SKB_CB_ATHBUF(skb);
|
||||||
|
BUG_ON(!bf);
|
||||||
|
|
||||||
bf = SKB_CB_ATHBUF(skb);
|
__skb_unlink(skb, &rx_edma->rx_fifo);
|
||||||
BUG_ON(!bf);
|
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||||
|
ath_rx_edma_buf_link(sc, qtype);
|
||||||
__skb_unlink(skb, &rx_edma->rx_fifo);
|
} else {
|
||||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
bf = NULL;
|
||||||
ath_rx_edma_buf_link(sc, qtype);
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
skb_queue_tail(&rx_edma->rx_buffers, skb);
|
|
||||||
|
|
||||||
|
*dest = bf;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,18 +708,15 @@ static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc,
|
|||||||
struct ath_rx_status *rs,
|
struct ath_rx_status *rs,
|
||||||
enum ath9k_rx_qtype qtype)
|
enum ath9k_rx_qtype qtype)
|
||||||
{
|
{
|
||||||
struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
|
struct ath_buf *bf = NULL;
|
||||||
struct sk_buff *skb;
|
|
||||||
struct ath_buf *bf;
|
|
||||||
|
|
||||||
while (ath_edma_get_buffers(sc, qtype));
|
while (ath_edma_get_buffers(sc, qtype, rs, &bf)) {
|
||||||
skb = __skb_dequeue(&rx_edma->rx_buffers);
|
if (!bf)
|
||||||
if (!skb)
|
continue;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
bf = SKB_CB_ATHBUF(skb);
|
return bf;
|
||||||
ath9k_hw_process_rxdesc_edma(sc->sc_ah, rs, skb->data);
|
}
|
||||||
return bf;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
|
static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
|
||||||
|
Loading…
Reference in New Issue
Block a user