aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath5k/base.c59
1 files changed, 45 insertions, 14 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 5eacc7cdd9e3..b5c0a0d7a81c 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1715,8 +1715,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
1715 1715
1716 1716
1717static void 1717static void
1718ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb) 1718ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
1719 struct ieee80211_rx_status *rxs)
1719{ 1720{
1721 u64 tsf, bc_tstamp;
1720 u32 hw_tu; 1722 u32 hw_tu;
1721 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; 1723 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
1722 1724
@@ -1727,16 +1729,45 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
1727 le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && 1729 le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
1728 memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { 1730 memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
1729 /* 1731 /*
1730 * Received an IBSS beacon with the same BSSID. Hardware might 1732 * Received an IBSS beacon with the same BSSID. Hardware *must*
1731 * have updated the TSF, check if we need to update timers. 1733 * have updated the local TSF. We have to work around various
1734 * hardware bugs, though...
1732 */ 1735 */
1733 hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah)); 1736 tsf = ath5k_hw_get_tsf64(sc->ah);
1734 if (hw_tu >= sc->nexttbtt) { 1737 bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
1735 ath5k_beacon_update_timers(sc, 1738 hw_tu = TSF_TO_TU(tsf);
1736 le64_to_cpu(mgmt->u.beacon.timestamp)); 1739
1740 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
1741 "beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
1742 bc_tstamp, rxs->mactime,
1743 (rxs->mactime - bc_tstamp), tsf);
1744
1745 /*
1746 * Sometimes the HW will give us a wrong tstamp in the rx
1747 * status, causing the timestamp extension to go wrong.
1748 * (This seems to happen especially with beacon frames bigger
1749 * than 78 byte (incl. FCS))
1750 * But we know that the receive timestamp must be later than the
1751 * timestamp of the beacon since HW must have synced to that.
1752 *
1753 * NOTE: here we assume mactime to be after the frame was
1754 * received, not like mac80211 which defines it at the start.
1755 */
1756 if (bc_tstamp > rxs->mactime) {
1737 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, 1757 ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
1738 "detected HW merge from received beacon\n"); 1758 "fixing mactime from %llx to %llx\n",
1759 rxs->mactime, tsf);
1760 rxs->mactime = tsf;
1739 } 1761 }
1762
1763 /*
1764 * Local TSF might have moved higher than our beacon timers,
1765 * in that case we have to update them to continue sending
1766 * beacons. This also takes care of synchronizing beacon sending
1767 * times with other stations.
1768 */
1769 if (hw_tu >= sc->nexttbtt)
1770 ath5k_beacon_update_timers(sc, bc_tstamp);
1740 } 1771 }
1741} 1772}
1742 1773
@@ -1885,7 +1916,7 @@ accept:
1885 1916
1886 /* check beacons in IBSS mode */ 1917 /* check beacons in IBSS mode */
1887 if (sc->opmode == IEEE80211_IF_TYPE_IBSS) 1918 if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
1888 ath5k_check_ibss_hw_merge(sc, skb); 1919 ath5k_check_ibss_tsf(sc, skb, &rxs);
1889 1920
1890 __ieee80211_rx(sc->hw, skb, &rxs); 1921 __ieee80211_rx(sc->hw, skb, &rxs);
1891 sc->led_rxrate = rs.rs_rate; 1922 sc->led_rxrate = rs.rs_rate;
@@ -2118,7 +2149,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
2118 * beacon timer registers. 2149 * beacon timer registers.
2119 * 2150 *
2120 * This is called in a variety of situations, e.g. when a beacon is received, 2151 * This is called in a variety of situations, e.g. when a beacon is received,
2121 * when a HW merge has been detected, but also when an new IBSS is created or 2152 * when a TSF update has been detected, but also when an new IBSS is created or
2122 * when we otherwise know we have to update the timers, but we keep it in this 2153 * when we otherwise know we have to update the timers, but we keep it in this
2123 * function to have it all together in one place. 2154 * function to have it all together in one place.
2124 */ 2155 */
@@ -2218,7 +2249,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
2218 * another AP to associate with. 2249 * another AP to associate with.
2219 * 2250 *
2220 * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA 2251 * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
2221 * interrupts to detect HW merges only. 2252 * interrupts to detect TSF updates only.
2222 * 2253 *
2223 * AP mode is missing. 2254 * AP mode is missing.
2224 */ 2255 */
@@ -2238,7 +2269,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
2238 * hardware send the beacons automatically. We have to load it 2269 * hardware send the beacons automatically. We have to load it
2239 * only once here. 2270 * only once here.
2240 * We use the SWBA interrupt only to keep track of the beacon 2271 * We use the SWBA interrupt only to keep track of the beacon
2241 * timers in order to detect HW merges (automatic TSF updates). 2272 * timers in order to detect automatic TSF updates.
2242 */ 2273 */
2243 ath5k_beaconq_config(sc); 2274 ath5k_beaconq_config(sc);
2244 2275
@@ -2451,8 +2482,8 @@ ath5k_intr(int irq, void *dev_id)
2451 * 2482 *
2452 * In IBSS mode we use this interrupt just to 2483 * In IBSS mode we use this interrupt just to
2453 * keep track of the next TBTT (target beacon 2484 * keep track of the next TBTT (target beacon
2454 * transmission time) in order to detect hardware 2485 * transmission time) in order to detect wether
2455 * merges (TSF updates). 2486 * automatic TSF updates happened.
2456 */ 2487 */
2457 if (sc->opmode == IEEE80211_IF_TYPE_IBSS) { 2488 if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
2458 /* XXX: only if VEOL suppported */ 2489 /* XXX: only if VEOL suppported */