ath5k: use rx hw descriptor pointer for self-linked check
This patch simplifies the code used to detect when the self-linked DMA buffer is still in use by hardware, by checking the hardware's rxdp register instead of looking at the software buffer list. Signed-off-by: Bob Copeland <me@bobcopeland.com> Acked-by: Nick Kossifidis <mickflemm@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
46802a4f07
commit
c57ca81576
@@ -1780,7 +1780,7 @@ ath5k_tasklet_rx(unsigned long data)
|
|||||||
struct sk_buff *skb, *next_skb;
|
struct sk_buff *skb, *next_skb;
|
||||||
dma_addr_t next_skb_addr;
|
dma_addr_t next_skb_addr;
|
||||||
struct ath5k_softc *sc = (void *)data;
|
struct ath5k_softc *sc = (void *)data;
|
||||||
struct ath5k_buf *bf, *bf_last;
|
struct ath5k_buf *bf;
|
||||||
struct ath5k_desc *ds;
|
struct ath5k_desc *ds;
|
||||||
int ret;
|
int ret;
|
||||||
int hdrlen;
|
int hdrlen;
|
||||||
@@ -1791,7 +1791,6 @@ ath5k_tasklet_rx(unsigned long data)
|
|||||||
ATH5K_WARN(sc, "empty rx buf pool\n");
|
ATH5K_WARN(sc, "empty rx buf pool\n");
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
|
|
||||||
do {
|
do {
|
||||||
rxs.flag = 0;
|
rxs.flag = 0;
|
||||||
|
|
||||||
@@ -1800,24 +1799,9 @@ ath5k_tasklet_rx(unsigned long data)
|
|||||||
skb = bf->skb;
|
skb = bf->skb;
|
||||||
ds = bf->desc;
|
ds = bf->desc;
|
||||||
|
|
||||||
/*
|
/* bail if HW is still using self-linked descriptor */
|
||||||
* last buffer must not be freed to ensure proper hardware
|
if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr)
|
||||||
* function. When the hardware finishes also a packet next to
|
break;
|
||||||
* it, we are sure, it doesn't use it anymore and we can go on.
|
|
||||||
*/
|
|
||||||
if (bf_last == bf)
|
|
||||||
bf->flags |= 1;
|
|
||||||
if (bf->flags) {
|
|
||||||
struct ath5k_buf *bf_next = list_entry(bf->list.next,
|
|
||||||
struct ath5k_buf, list);
|
|
||||||
ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
|
|
||||||
&rs);
|
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
bf->flags &= ~1;
|
|
||||||
/* skip the overwritten one (even status is martian) */
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
|
ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
|
||||||
if (unlikely(ret == -EINPROGRESS))
|
if (unlikely(ret == -EINPROGRESS))
|
||||||
|
@@ -56,7 +56,6 @@
|
|||||||
|
|
||||||
struct ath5k_buf {
|
struct ath5k_buf {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
unsigned int flags; /* rx descriptor flags */
|
|
||||||
struct ath5k_desc *desc; /* virtual addr of desc */
|
struct ath5k_desc *desc; /* virtual addr of desc */
|
||||||
dma_addr_t daddr; /* physical addr of desc */
|
dma_addr_t daddr; /* physical addr of desc */
|
||||||
struct sk_buff *skb; /* skbuff for buf */
|
struct sk_buff *skb; /* skbuff for buf */
|
||||||
|
@@ -80,8 +80,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
|
|||||||
* ath5k_hw_get_rxdp - Get RX Descriptor's address
|
* ath5k_hw_get_rxdp - Get RX Descriptor's address
|
||||||
*
|
*
|
||||||
* @ah: The &struct ath5k_hw
|
* @ah: The &struct ath5k_hw
|
||||||
*
|
|
||||||
* XXX: Is RXDP read and clear ?
|
|
||||||
*/
|
*/
|
||||||
u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
|
u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user