aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath5k/base.c')
-rw-r--r--drivers/net/wireless/ath5k/base.c95
1 files changed, 62 insertions, 33 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 8ef87356e083..1d77ee9d6e99 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1028,6 +1028,8 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
1028 * it's done by reseting the chip. To accomplish this we must 1028 * it's done by reseting the chip. To accomplish this we must
1029 * first cleanup any pending DMA, then restart stuff after a la 1029 * first cleanup any pending DMA, then restart stuff after a la
1030 * ath5k_init. 1030 * ath5k_init.
1031 *
1032 * Called with sc->lock.
1031 */ 1033 */
1032static int 1034static int
1033ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) 1035ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
@@ -1096,6 +1098,42 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
1096* Buffers setup * 1098* Buffers setup *
1097\***************/ 1099\***************/
1098 1100
1101static
1102struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
1103{
1104 struct sk_buff *skb;
1105 unsigned int off;
1106
1107 /*
1108 * Allocate buffer with headroom_needed space for the
1109 * fake physical layer header at the start.
1110 */
1111 skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
1112
1113 if (!skb) {
1114 ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
1115 sc->rxbufsize + sc->cachelsz - 1);
1116 return NULL;
1117 }
1118 /*
1119 * Cache-line-align. This is important (for the
1120 * 5210 at least) as not doing so causes bogus data
1121 * in rx'd frames.
1122 */
1123 off = ((unsigned long)skb->data) % sc->cachelsz;
1124 if (off != 0)
1125 skb_reserve(skb, sc->cachelsz - off);
1126
1127 *skb_addr = pci_map_single(sc->pdev,
1128 skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
1129 if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
1130 ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
1131 dev_kfree_skb(skb);
1132 return NULL;
1133 }
1134 return skb;
1135}
1136
1099static int 1137static int
1100ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) 1138ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
1101{ 1139{
@@ -1103,37 +1141,11 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
1103 struct sk_buff *skb = bf->skb; 1141 struct sk_buff *skb = bf->skb;
1104 struct ath5k_desc *ds; 1142 struct ath5k_desc *ds;
1105 1143
1106 if (likely(skb == NULL)) { 1144 if (!skb) {
1107 unsigned int off; 1145 skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
1108 1146 if (!skb)
1109 /*
1110 * Allocate buffer with headroom_needed space for the
1111 * fake physical layer header at the start.
1112 */
1113 skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
1114 if (unlikely(skb == NULL)) {
1115 ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
1116 sc->rxbufsize + sc->cachelsz - 1);
1117 return -ENOMEM; 1147 return -ENOMEM;
1118 }
1119 /*
1120 * Cache-line-align. This is important (for the
1121 * 5210 at least) as not doing so causes bogus data
1122 * in rx'd frames.
1123 */
1124 off = ((unsigned long)skb->data) % sc->cachelsz;
1125 if (off != 0)
1126 skb_reserve(skb, sc->cachelsz - off);
1127
1128 bf->skb = skb; 1148 bf->skb = skb;
1129 bf->skbaddr = pci_map_single(sc->pdev,
1130 skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
1131 if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) {
1132 ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
1133 dev_kfree_skb(skb);
1134 bf->skb = NULL;
1135 return -ENOMEM;
1136 }
1137 } 1149 }
1138 1150
1139 /* 1151 /*
@@ -1662,7 +1674,8 @@ ath5k_tasklet_rx(unsigned long data)
1662{ 1674{
1663 struct ieee80211_rx_status rxs = {}; 1675 struct ieee80211_rx_status rxs = {};
1664 struct ath5k_rx_status rs = {}; 1676 struct ath5k_rx_status rs = {};
1665 struct sk_buff *skb; 1677 struct sk_buff *skb, *next_skb;
1678 dma_addr_t next_skb_addr;
1666 struct ath5k_softc *sc = (void *)data; 1679 struct ath5k_softc *sc = (void *)data;
1667 struct ath5k_buf *bf, *bf_last; 1680 struct ath5k_buf *bf, *bf_last;
1668 struct ath5k_desc *ds; 1681 struct ath5k_desc *ds;
@@ -1747,10 +1760,17 @@ ath5k_tasklet_rx(unsigned long data)
1747 goto next; 1760 goto next;
1748 } 1761 }
1749accept: 1762accept:
1763 next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
1764
1765 /*
1766 * If we can't replace bf->skb with a new skb under memory
1767 * pressure, just skip this packet
1768 */
1769 if (!next_skb)
1770 goto next;
1771
1750 pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, 1772 pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
1751 PCI_DMA_FROMDEVICE); 1773 PCI_DMA_FROMDEVICE);
1752 bf->skb = NULL;
1753
1754 skb_put(skb, rs.rs_datalen); 1774 skb_put(skb, rs.rs_datalen);
1755 1775
1756 /* The MAC header is padded to have 32-bit boundary if the 1776 /* The MAC header is padded to have 32-bit boundary if the
@@ -1823,6 +1843,9 @@ accept:
1823 ath5k_check_ibss_tsf(sc, skb, &rxs); 1843 ath5k_check_ibss_tsf(sc, skb, &rxs);
1824 1844
1825 __ieee80211_rx(sc->hw, skb, &rxs); 1845 __ieee80211_rx(sc->hw, skb, &rxs);
1846
1847 bf->skb = next_skb;
1848 bf->skbaddr = next_skb_addr;
1826next: 1849next:
1827 list_move_tail(&bf->list, &sc->rxbuf); 1850 list_move_tail(&bf->list, &sc->rxbuf);
1828 } while (ath5k_rxbuf_setup(sc, bf) == 0); 1851 } while (ath5k_rxbuf_setup(sc, bf) == 0);
@@ -2814,11 +2837,17 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
2814{ 2837{
2815 struct ath5k_softc *sc = hw->priv; 2838 struct ath5k_softc *sc = hw->priv;
2816 struct ieee80211_conf *conf = &hw->conf; 2839 struct ieee80211_conf *conf = &hw->conf;
2840 int ret;
2841
2842 mutex_lock(&sc->lock);
2817 2843
2818 sc->bintval = conf->beacon_int; 2844 sc->bintval = conf->beacon_int;
2819 sc->power_level = conf->power_level; 2845 sc->power_level = conf->power_level;
2820 2846
2821 return ath5k_chan_set(sc, conf->channel); 2847 ret = ath5k_chan_set(sc, conf->channel);
2848
2849 mutex_unlock(&sc->lock);
2850 return ret;
2822} 2851}
2823 2852
2824static int 2853static int