diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/base.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 150 |
1 files changed, 118 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 8dce0077b023..b142a78ed1e5 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -198,7 +198,7 @@ static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | |||
198 | static int ath5k_pci_suspend(struct device *dev); | 198 | static int ath5k_pci_suspend(struct device *dev); |
199 | static int ath5k_pci_resume(struct device *dev); | 199 | static int ath5k_pci_resume(struct device *dev); |
200 | 200 | ||
201 | SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | 201 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); |
202 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | 202 | #define ATH5K_PM_OPS (&ath5k_pm_ops) |
203 | #else | 203 | #else |
204 | #define ATH5K_PM_OPS NULL | 204 | #define ATH5K_PM_OPS NULL |
@@ -307,7 +307,7 @@ static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | |||
307 | struct ath5k_buf *bf); | 307 | struct ath5k_buf *bf); |
308 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | 308 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, |
309 | struct ath5k_buf *bf, | 309 | struct ath5k_buf *bf, |
310 | struct ath5k_txq *txq); | 310 | struct ath5k_txq *txq, int padsize); |
311 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | 311 | static inline void ath5k_txbuf_free(struct ath5k_softc *sc, |
312 | struct ath5k_buf *bf) | 312 | struct ath5k_buf *bf) |
313 | { | 313 | { |
@@ -1137,8 +1137,6 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
1137 | struct ath5k_hw *ah = sc->ah; | 1137 | struct ath5k_hw *ah = sc->ah; |
1138 | u32 rfilt; | 1138 | u32 rfilt; |
1139 | 1139 | ||
1140 | ah->ah_op_mode = sc->opmode; | ||
1141 | |||
1142 | /* configure rx filter */ | 1140 | /* configure rx filter */ |
1143 | rfilt = sc->filter_flags; | 1141 | rfilt = sc->filter_flags; |
1144 | ath5k_hw_set_rx_filter(ah, rfilt); | 1142 | ath5k_hw_set_rx_filter(ah, rfilt); |
@@ -1147,8 +1145,9 @@ ath5k_mode_setup(struct ath5k_softc *sc) | |||
1147 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); | 1145 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); |
1148 | 1146 | ||
1149 | /* configure operational mode */ | 1147 | /* configure operational mode */ |
1150 | ath5k_hw_set_opmode(ah); | 1148 | ath5k_hw_set_opmode(ah, sc->opmode); |
1151 | 1149 | ||
1150 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode); | ||
1152 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); | 1151 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); |
1153 | } | 1152 | } |
1154 | 1153 | ||
@@ -1271,7 +1270,7 @@ static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) | |||
1271 | 1270 | ||
1272 | static int | 1271 | static int |
1273 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | 1272 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, |
1274 | struct ath5k_txq *txq) | 1273 | struct ath5k_txq *txq, int padsize) |
1275 | { | 1274 | { |
1276 | struct ath5k_hw *ah = sc->ah; | 1275 | struct ath5k_hw *ah = sc->ah; |
1277 | struct ath5k_desc *ds = bf->desc; | 1276 | struct ath5k_desc *ds = bf->desc; |
@@ -1323,7 +1322,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1323 | sc->vif, pktlen, info)); | 1322 | sc->vif, pktlen, info)); |
1324 | } | 1323 | } |
1325 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1324 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1326 | ieee80211_get_hdrlen_from_skb(skb), | 1325 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
1327 | get_hw_packet_type(skb), | 1326 | get_hw_packet_type(skb), |
1328 | (sc->power_level * 2), | 1327 | (sc->power_level * 2), |
1329 | hw_rate, | 1328 | hw_rate, |
@@ -1805,6 +1804,67 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1805 | } | 1804 | } |
1806 | } | 1805 | } |
1807 | 1806 | ||
1807 | /* | ||
1808 | * Compute padding position. skb must contains an IEEE 802.11 frame | ||
1809 | */ | ||
1810 | static int ath5k_common_padpos(struct sk_buff *skb) | ||
1811 | { | ||
1812 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; | ||
1813 | __le16 frame_control = hdr->frame_control; | ||
1814 | int padpos = 24; | ||
1815 | |||
1816 | if (ieee80211_has_a4(frame_control)) { | ||
1817 | padpos += ETH_ALEN; | ||
1818 | } | ||
1819 | if (ieee80211_is_data_qos(frame_control)) { | ||
1820 | padpos += IEEE80211_QOS_CTL_LEN; | ||
1821 | } | ||
1822 | |||
1823 | return padpos; | ||
1824 | } | ||
1825 | |||
1826 | /* | ||
1827 | * This function expects a 802.11 frame and returns the number of | ||
1828 | * bytes added, or -1 if we don't have enought header room. | ||
1829 | */ | ||
1830 | |||
1831 | static int ath5k_add_padding(struct sk_buff *skb) | ||
1832 | { | ||
1833 | int padpos = ath5k_common_padpos(skb); | ||
1834 | int padsize = padpos & 3; | ||
1835 | |||
1836 | if (padsize && skb->len>padpos) { | ||
1837 | |||
1838 | if (skb_headroom(skb) < padsize) | ||
1839 | return -1; | ||
1840 | |||
1841 | skb_push(skb, padsize); | ||
1842 | memmove(skb->data, skb->data+padsize, padpos); | ||
1843 | return padsize; | ||
1844 | } | ||
1845 | |||
1846 | return 0; | ||
1847 | } | ||
1848 | |||
1849 | /* | ||
1850 | * This function expects a 802.11 frame and returns the number of | ||
1851 | * bytes removed | ||
1852 | */ | ||
1853 | |||
1854 | static int ath5k_remove_padding(struct sk_buff *skb) | ||
1855 | { | ||
1856 | int padpos = ath5k_common_padpos(skb); | ||
1857 | int padsize = padpos & 3; | ||
1858 | |||
1859 | if (padsize && skb->len>=padpos+padsize) { | ||
1860 | memmove(skb->data + padsize, skb->data, padpos); | ||
1861 | skb_pull(skb, padsize); | ||
1862 | return padsize; | ||
1863 | } | ||
1864 | |||
1865 | return 0; | ||
1866 | } | ||
1867 | |||
1808 | static void | 1868 | static void |
1809 | ath5k_tasklet_rx(unsigned long data) | 1869 | ath5k_tasklet_rx(unsigned long data) |
1810 | { | 1870 | { |
@@ -1818,8 +1878,6 @@ ath5k_tasklet_rx(unsigned long data) | |||
1818 | struct ath5k_buf *bf; | 1878 | struct ath5k_buf *bf; |
1819 | struct ath5k_desc *ds; | 1879 | struct ath5k_desc *ds; |
1820 | int ret; | 1880 | int ret; |
1821 | int hdrlen; | ||
1822 | int padsize; | ||
1823 | int rx_flag; | 1881 | int rx_flag; |
1824 | 1882 | ||
1825 | spin_lock(&sc->rxbuflock); | 1883 | spin_lock(&sc->rxbuflock); |
@@ -1844,18 +1902,28 @@ ath5k_tasklet_rx(unsigned long data) | |||
1844 | break; | 1902 | break; |
1845 | else if (unlikely(ret)) { | 1903 | else if (unlikely(ret)) { |
1846 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); | 1904 | ATH5K_ERR(sc, "error in processing rx descriptor\n"); |
1905 | sc->stats.rxerr_proc++; | ||
1847 | spin_unlock(&sc->rxbuflock); | 1906 | spin_unlock(&sc->rxbuflock); |
1848 | return; | 1907 | return; |
1849 | } | 1908 | } |
1850 | 1909 | ||
1910 | sc->stats.rx_all_count++; | ||
1911 | |||
1851 | if (unlikely(rs.rs_more)) { | 1912 | if (unlikely(rs.rs_more)) { |
1852 | ATH5K_WARN(sc, "unsupported jumbo\n"); | 1913 | ATH5K_WARN(sc, "unsupported jumbo\n"); |
1914 | sc->stats.rxerr_jumbo++; | ||
1853 | goto next; | 1915 | goto next; |
1854 | } | 1916 | } |
1855 | 1917 | ||
1856 | if (unlikely(rs.rs_status)) { | 1918 | if (unlikely(rs.rs_status)) { |
1857 | if (rs.rs_status & AR5K_RXERR_PHY) | 1919 | if (rs.rs_status & AR5K_RXERR_CRC) |
1920 | sc->stats.rxerr_crc++; | ||
1921 | if (rs.rs_status & AR5K_RXERR_FIFO) | ||
1922 | sc->stats.rxerr_fifo++; | ||
1923 | if (rs.rs_status & AR5K_RXERR_PHY) { | ||
1924 | sc->stats.rxerr_phy++; | ||
1858 | goto next; | 1925 | goto next; |
1926 | } | ||
1859 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { | 1927 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { |
1860 | /* | 1928 | /* |
1861 | * Decrypt error. If the error occurred | 1929 | * Decrypt error. If the error occurred |
@@ -1867,12 +1935,14 @@ ath5k_tasklet_rx(unsigned long data) | |||
1867 | * | 1935 | * |
1868 | * XXX do key cache faulting | 1936 | * XXX do key cache faulting |
1869 | */ | 1937 | */ |
1938 | sc->stats.rxerr_decrypt++; | ||
1870 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && | 1939 | if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && |
1871 | !(rs.rs_status & AR5K_RXERR_CRC)) | 1940 | !(rs.rs_status & AR5K_RXERR_CRC)) |
1872 | goto accept; | 1941 | goto accept; |
1873 | } | 1942 | } |
1874 | if (rs.rs_status & AR5K_RXERR_MIC) { | 1943 | if (rs.rs_status & AR5K_RXERR_MIC) { |
1875 | rx_flag |= RX_FLAG_MMIC_ERROR; | 1944 | rx_flag |= RX_FLAG_MMIC_ERROR; |
1945 | sc->stats.rxerr_mic++; | ||
1876 | goto accept; | 1946 | goto accept; |
1877 | } | 1947 | } |
1878 | 1948 | ||
@@ -1904,12 +1974,8 @@ accept: | |||
1904 | * bytes and we can optimize this a bit. In addition, we must | 1974 | * bytes and we can optimize this a bit. In addition, we must |
1905 | * not try to remove padding from short control frames that do | 1975 | * not try to remove padding from short control frames that do |
1906 | * not have payload. */ | 1976 | * not have payload. */ |
1907 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1977 | ath5k_remove_padding(skb); |
1908 | padsize = ath5k_pad_size(hdrlen); | 1978 | |
1909 | if (padsize) { | ||
1910 | memmove(skb->data + padsize, skb->data, hdrlen); | ||
1911 | skb_pull(skb, padsize); | ||
1912 | } | ||
1913 | rxs = IEEE80211_SKB_RXCB(skb); | 1979 | rxs = IEEE80211_SKB_RXCB(skb); |
1914 | 1980 | ||
1915 | /* | 1981 | /* |
@@ -1942,6 +2008,12 @@ accept: | |||
1942 | rxs->signal = rxs->noise + rs.rs_rssi; | 2008 | rxs->signal = rxs->noise + rs.rs_rssi; |
1943 | 2009 | ||
1944 | rxs->antenna = rs.rs_antenna; | 2010 | rxs->antenna = rs.rs_antenna; |
2011 | |||
2012 | if (rs.rs_antenna > 0 && rs.rs_antenna < 5) | ||
2013 | sc->stats.antenna_rx[rs.rs_antenna]++; | ||
2014 | else | ||
2015 | sc->stats.antenna_rx[0]++; /* invalid */ | ||
2016 | |||
1945 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); | 2017 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); |
1946 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); | 2018 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); |
1947 | 2019 | ||
@@ -1996,6 +2068,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1996 | break; | 2068 | break; |
1997 | } | 2069 | } |
1998 | 2070 | ||
2071 | sc->stats.tx_all_count++; | ||
1999 | skb = bf->skb; | 2072 | skb = bf->skb; |
2000 | info = IEEE80211_SKB_CB(skb); | 2073 | info = IEEE80211_SKB_CB(skb); |
2001 | bf->skb = NULL; | 2074 | bf->skb = NULL; |
@@ -2022,13 +2095,30 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
2022 | 2095 | ||
2023 | if (unlikely(ts.ts_status)) { | 2096 | if (unlikely(ts.ts_status)) { |
2024 | sc->ll_stats.dot11ACKFailureCount++; | 2097 | sc->ll_stats.dot11ACKFailureCount++; |
2025 | if (ts.ts_status & AR5K_TXERR_FILT) | 2098 | if (ts.ts_status & AR5K_TXERR_FILT) { |
2026 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 2099 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
2100 | sc->stats.txerr_filt++; | ||
2101 | } | ||
2102 | if (ts.ts_status & AR5K_TXERR_XRETRY) | ||
2103 | sc->stats.txerr_retry++; | ||
2104 | if (ts.ts_status & AR5K_TXERR_FIFO) | ||
2105 | sc->stats.txerr_fifo++; | ||
2027 | } else { | 2106 | } else { |
2028 | info->flags |= IEEE80211_TX_STAT_ACK; | 2107 | info->flags |= IEEE80211_TX_STAT_ACK; |
2029 | info->status.ack_signal = ts.ts_rssi; | 2108 | info->status.ack_signal = ts.ts_rssi; |
2030 | } | 2109 | } |
2031 | 2110 | ||
2111 | /* | ||
2112 | * Remove MAC header padding before giving the frame | ||
2113 | * back to mac80211. | ||
2114 | */ | ||
2115 | ath5k_remove_padding(skb); | ||
2116 | |||
2117 | if (ts.ts_antenna > 0 && ts.ts_antenna < 5) | ||
2118 | sc->stats.antenna_tx[ts.ts_antenna]++; | ||
2119 | else | ||
2120 | sc->stats.antenna_tx[0]++; /* invalid */ | ||
2121 | |||
2032 | ieee80211_tx_status(sc->hw, skb); | 2122 | ieee80211_tx_status(sc->hw, skb); |
2033 | 2123 | ||
2034 | spin_lock(&sc->txbuflock); | 2124 | spin_lock(&sc->txbuflock); |
@@ -2072,6 +2162,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2072 | int ret = 0; | 2162 | int ret = 0; |
2073 | u8 antenna; | 2163 | u8 antenna; |
2074 | u32 flags; | 2164 | u32 flags; |
2165 | const int padsize = 0; | ||
2075 | 2166 | ||
2076 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | 2167 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, |
2077 | PCI_DMA_TODEVICE); | 2168 | PCI_DMA_TODEVICE); |
@@ -2119,7 +2210,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2119 | * from tx power (value is in dB units already) */ | 2210 | * from tx power (value is in dB units already) */ |
2120 | ds->ds_data = bf->skbaddr; | 2211 | ds->ds_data = bf->skbaddr; |
2121 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, | 2212 | ret = ah->ah_setup_tx_desc(ah, ds, skb->len, |
2122 | ieee80211_get_hdrlen_from_skb(skb), | 2213 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
2123 | AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), | 2214 | AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), |
2124 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, | 2215 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, |
2125 | 1, AR5K_TXKEYIX_INVALID, | 2216 | 1, AR5K_TXKEYIX_INVALID, |
@@ -2679,7 +2770,6 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2679 | struct ath5k_softc *sc = hw->priv; | 2770 | struct ath5k_softc *sc = hw->priv; |
2680 | struct ath5k_buf *bf; | 2771 | struct ath5k_buf *bf; |
2681 | unsigned long flags; | 2772 | unsigned long flags; |
2682 | int hdrlen; | ||
2683 | int padsize; | 2773 | int padsize; |
2684 | 2774 | ||
2685 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | 2775 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); |
@@ -2691,17 +2781,11 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2691 | * the hardware expects the header padded to 4 byte boundaries | 2781 | * the hardware expects the header padded to 4 byte boundaries |
2692 | * if this is not the case we add the padding after the header | 2782 | * if this is not the case we add the padding after the header |
2693 | */ | 2783 | */ |
2694 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 2784 | padsize = ath5k_add_padding(skb); |
2695 | padsize = ath5k_pad_size(hdrlen); | 2785 | if (padsize < 0) { |
2696 | if (padsize) { | 2786 | ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" |
2697 | 2787 | " headroom to pad"); | |
2698 | if (skb_headroom(skb) < padsize) { | 2788 | goto drop_packet; |
2699 | ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" | ||
2700 | " headroom to pad %d\n", hdrlen, padsize); | ||
2701 | goto drop_packet; | ||
2702 | } | ||
2703 | skb_push(skb, padsize); | ||
2704 | memmove(skb->data, skb->data+padsize, hdrlen); | ||
2705 | } | 2789 | } |
2706 | 2790 | ||
2707 | spin_lock_irqsave(&sc->txbuflock, flags); | 2791 | spin_lock_irqsave(&sc->txbuflock, flags); |
@@ -2720,7 +2804,7 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2720 | 2804 | ||
2721 | bf->skb = skb; | 2805 | bf->skb = skb; |
2722 | 2806 | ||
2723 | if (ath5k_txbuf_setup(sc, bf, txq)) { | 2807 | if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { |
2724 | bf->skb = NULL; | 2808 | bf->skb = NULL; |
2725 | spin_lock_irqsave(&sc->txbuflock, flags); | 2809 | spin_lock_irqsave(&sc->txbuflock, flags); |
2726 | list_add_tail(&bf->list, &sc->txbuf); | 2810 | list_add_tail(&bf->list, &sc->txbuf); |
@@ -2835,6 +2919,8 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2835 | goto end; | 2919 | goto end; |
2836 | } | 2920 | } |
2837 | 2921 | ||
2922 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode); | ||
2923 | |||
2838 | ath5k_hw_set_lladdr(sc->ah, vif->addr); | 2924 | ath5k_hw_set_lladdr(sc->ah, vif->addr); |
2839 | ath5k_mode_setup(sc); | 2925 | ath5k_mode_setup(sc); |
2840 | 2926 | ||
@@ -2905,7 +2991,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed) | |||
2905 | * then we must allow the user to set how many tx antennas we | 2991 | * then we must allow the user to set how many tx antennas we |
2906 | * have available | 2992 | * have available |
2907 | */ | 2993 | */ |
2908 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); | 2994 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); |
2909 | 2995 | ||
2910 | unlock: | 2996 | unlock: |
2911 | mutex_unlock(&sc->lock); | 2997 | mutex_unlock(&sc->lock); |