diff options
Diffstat (limited to 'drivers/net/wireless/ath5k')
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/ath5k/base.h | 2 |
2 files changed, 26 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index d9769c527346..ed51c4a69d43 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -1682,20 +1682,21 @@ ath5k_tasklet_rx(unsigned long data) | |||
1682 | struct ath5k_rx_status rs = {}; | 1682 | struct ath5k_rx_status rs = {}; |
1683 | struct sk_buff *skb; | 1683 | struct sk_buff *skb; |
1684 | struct ath5k_softc *sc = (void *)data; | 1684 | struct ath5k_softc *sc = (void *)data; |
1685 | struct ath5k_buf *bf; | 1685 | struct ath5k_buf *bf, *bf_last; |
1686 | struct ath5k_desc *ds; | 1686 | struct ath5k_desc *ds; |
1687 | int ret; | 1687 | int ret; |
1688 | int hdrlen; | 1688 | int hdrlen; |
1689 | int pad; | 1689 | int pad; |
1690 | 1690 | ||
1691 | spin_lock(&sc->rxbuflock); | 1691 | spin_lock(&sc->rxbuflock); |
1692 | if (list_empty(&sc->rxbuf)) { | ||
1693 | ATH5K_WARN(sc, "empty rx buf pool\n"); | ||
1694 | goto unlock; | ||
1695 | } | ||
1696 | bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list); | ||
1692 | do { | 1697 | do { |
1693 | rxs.flag = 0; | 1698 | rxs.flag = 0; |
1694 | 1699 | ||
1695 | if (unlikely(list_empty(&sc->rxbuf))) { | ||
1696 | ATH5K_WARN(sc, "empty rx buf pool\n"); | ||
1697 | break; | ||
1698 | } | ||
1699 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); | 1700 | bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); |
1700 | BUG_ON(bf->skb == NULL); | 1701 | BUG_ON(bf->skb == NULL); |
1701 | skb = bf->skb; | 1702 | skb = bf->skb; |
@@ -1705,8 +1706,24 @@ ath5k_tasklet_rx(unsigned long data) | |||
1705 | pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, | 1706 | pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, |
1706 | sc->desc_len, PCI_DMA_FROMDEVICE); | 1707 | sc->desc_len, PCI_DMA_FROMDEVICE); |
1707 | 1708 | ||
1708 | if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */ | 1709 | /* |
1709 | break; | 1710 | * last buffer must not be freed to ensure proper hardware |
1711 | * function. When the hardware finishes also a packet next to | ||
1712 | * it, we are sure, it doesn't use it anymore and we can go on. | ||
1713 | */ | ||
1714 | if (bf_last == bf) | ||
1715 | bf->flags |= 1; | ||
1716 | if (bf->flags) { | ||
1717 | struct ath5k_buf *bf_next = list_entry(bf->list.next, | ||
1718 | struct ath5k_buf, list); | ||
1719 | ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc, | ||
1720 | &rs); | ||
1721 | if (ret) | ||
1722 | break; | ||
1723 | bf->flags &= ~1; | ||
1724 | /* skip the overwritten one (even status is martian) */ | ||
1725 | goto next; | ||
1726 | } | ||
1710 | 1727 | ||
1711 | ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); | 1728 | ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); |
1712 | if (unlikely(ret == -EINPROGRESS)) | 1729 | if (unlikely(ret == -EINPROGRESS)) |
@@ -1816,6 +1833,7 @@ accept: | |||
1816 | next: | 1833 | next: |
1817 | list_move_tail(&bf->list, &sc->rxbuf); | 1834 | list_move_tail(&bf->list, &sc->rxbuf); |
1818 | } while (ath5k_rxbuf_setup(sc, bf) == 0); | 1835 | } while (ath5k_rxbuf_setup(sc, bf) == 0); |
1836 | unlock: | ||
1819 | spin_unlock(&sc->rxbuflock); | 1837 | spin_unlock(&sc->rxbuflock); |
1820 | } | 1838 | } |
1821 | 1839 | ||
diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index 47f414b09e67..d7e03e6b8271 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h | |||
@@ -56,7 +56,7 @@ | |||
56 | 56 | ||
57 | struct ath5k_buf { | 57 | struct ath5k_buf { |
58 | struct list_head list; | 58 | struct list_head list; |
59 | unsigned int flags; /* tx descriptor flags */ | 59 | unsigned int flags; /* rx descriptor flags */ |
60 | struct ath5k_desc *desc; /* virtual addr of desc */ | 60 | struct ath5k_desc *desc; /* virtual addr of desc */ |
61 | dma_addr_t daddr; /* physical addr of desc */ | 61 | dma_addr_t daddr; /* physical addr of desc */ |
62 | struct sk_buff *skb; /* skbuff for buf */ | 62 | struct sk_buff *skb; /* skbuff for buf */ |