aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k/rc.c
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2009-03-02 02:59:45 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-03-05 14:39:39 -0500
commit9331ec8060da5783307a565792ded33bfb9e54fc (patch)
treee5de7ce16432d7cf3aa742a34800e611767bc459 /drivers/net/wireless/ath9k/rc.c
parent25c9c8752849212a25bf7f38b40b64b3958d619b (diff)
ath9k: Fill in rate_update mac80211 callback
This callback can be used to handle dynamic 20/40, and changes in the operating channel's HT parameters. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k/rc.c')
-rw-r--r--drivers/net/wireless/ath9k/rc.c121
1 files changed, 92 insertions, 29 deletions
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index 18d19c394475..6d7e636054ed 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -1387,42 +1387,18 @@ static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
1387static void ath_rc_init(struct ath_softc *sc, 1387static void ath_rc_init(struct ath_softc *sc,
1388 struct ath_rate_priv *ath_rc_priv, 1388 struct ath_rate_priv *ath_rc_priv,
1389 struct ieee80211_supported_band *sband, 1389 struct ieee80211_supported_band *sband,
1390 struct ieee80211_sta *sta) 1390 struct ieee80211_sta *sta,
1391 struct ath_rate_table *rate_table)
1391{ 1392{
1392 struct ath_rate_table *rate_table = NULL;
1393 struct ath_rateset *rateset = &ath_rc_priv->neg_rates; 1393 struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
1394 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; 1394 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
1395 u8 i, j, k, hi = 0, hthi = 0; 1395 u8 i, j, k, hi = 0, hthi = 0;
1396 struct ath_hw *ah = sc->sc_ah;
1397
1398 /* FIXME: Adhoc */
1399 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
1400 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
1401 bool is_cw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
1402 rate_table = ath_choose_rate_table(sc, sband->band,
1403 sta->ht_cap.ht_supported,
1404 is_cw_40);
1405 } else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
1406 /* cur_rate_table would be set on init through config() */
1407 rate_table = sc->cur_rate_table;
1408 }
1409 1396
1410 if (!rate_table) { 1397 if (!rate_table) {
1411 DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n"); 1398 DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n");
1412 return; 1399 return;
1413 } 1400 }
1414 1401
1415 if (sta->ht_cap.ht_supported) {
1416 ath_rc_priv->ht_cap = WLAN_RC_HT_FLAG;
1417 if (sc->sc_ah->caps.tx_chainmask != 1 &&
1418 ath9k_hw_getcapability(ah, ATH9K_CAP_DS, 0, NULL))
1419 ath_rc_priv->ht_cap |= WLAN_RC_DS_FLAG;
1420 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
1421 ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG;
1422 if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
1423 ath_rc_priv->ht_cap |= WLAN_RC_SGI_FLAG;
1424 }
1425
1426 /* Initial rate table size. Will change depending 1402 /* Initial rate table size. Will change depending
1427 * on the working rate set */ 1403 * on the working rate set */
1428 ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; 1404 ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
@@ -1442,7 +1418,7 @@ static void ath_rc_init(struct ath_softc *sc,
1442 ath_rc_priv->valid_phy_rateidx[i][j] = 0; 1418 ath_rc_priv->valid_phy_rateidx[i][j] = 0;
1443 ath_rc_priv->valid_phy_ratecnt[i] = 0; 1419 ath_rc_priv->valid_phy_ratecnt[i] = 0;
1444 } 1420 }
1445 ath_rc_priv->rc_phy_mode = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG); 1421 ath_rc_priv->rc_phy_mode = ath_rc_priv->ht_cap & WLAN_RC_40_FLAG;
1446 1422
1447 /* Set stream capability */ 1423 /* Set stream capability */
1448 ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1; 1424 ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1;
@@ -1487,9 +1463,34 @@ static void ath_rc_init(struct ath_softc *sc,
1487 ath_rc_sort_validrates(rate_table, ath_rc_priv); 1463 ath_rc_sort_validrates(rate_table, ath_rc_priv);
1488 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; 1464 ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
1489 sc->cur_rate_table = rate_table; 1465 sc->cur_rate_table = rate_table;
1466
1467 DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n",
1468 ath_rc_priv->ht_cap);
1490} 1469}
1491 1470
1492/* Rate Control callbacks */ 1471static u8 ath_rc_build_ht_caps(struct ath_softc *sc, bool is_ht, bool is_cw40,
1472 bool is_sgi40)
1473{
1474 u8 caps = 0;
1475
1476 if (is_ht) {
1477 caps = WLAN_RC_HT_FLAG;
1478 if (sc->sc_ah->caps.tx_chainmask != 1 &&
1479 ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL))
1480 caps |= WLAN_RC_DS_FLAG;
1481 if (is_cw40)
1482 caps |= WLAN_RC_40_FLAG;
1483 if (is_sgi40)
1484 caps |= WLAN_RC_SGI_FLAG;
1485 }
1486
1487 return caps;
1488}
1489
1490/***********************************/
1491/* mac80211 Rate Control callbacks */
1492/***********************************/
1493
1493static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, 1494static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
1494 struct ieee80211_sta *sta, void *priv_sta, 1495 struct ieee80211_sta *sta, void *priv_sta,
1495 struct sk_buff *skb) 1496 struct sk_buff *skb)
@@ -1585,6 +1586,8 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
1585{ 1586{
1586 struct ath_softc *sc = priv; 1587 struct ath_softc *sc = priv;
1587 struct ath_rate_priv *ath_rc_priv = priv_sta; 1588 struct ath_rate_priv *ath_rc_priv = priv_sta;
1589 struct ath_rate_table *rate_table = NULL;
1590 bool is_cw40, is_sgi40;
1588 int i, j = 0; 1591 int i, j = 0;
1589 1592
1590 for (i = 0; i < sband->n_bitrates; i++) { 1593 for (i = 0; i < sband->n_bitrates; i++) {
@@ -1606,7 +1609,66 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
1606 ath_rc_priv->neg_ht_rates.rs_nrates = j; 1609 ath_rc_priv->neg_ht_rates.rs_nrates = j;
1607 } 1610 }
1608 1611
1609 ath_rc_init(sc, priv_sta, sband, sta); 1612 is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
1613 is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
1614
1615 /* Choose rate table first */
1616
1617 if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
1618 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
1619 rate_table = ath_choose_rate_table(sc, sband->band,
1620 sta->ht_cap.ht_supported,
1621 is_cw40);
1622 } else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
1623 /* cur_rate_table would be set on init through config() */
1624 rate_table = sc->cur_rate_table;
1625 }
1626
1627 ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta->ht_cap.ht_supported,
1628 is_cw40, is_sgi40);
1629 ath_rc_init(sc, priv_sta, sband, sta, rate_table);
1630}
1631
1632static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
1633 struct ieee80211_sta *sta, void *priv_sta,
1634 u32 changed)
1635{
1636 struct ath_softc *sc = priv;
1637 struct ath_rate_priv *ath_rc_priv = priv_sta;
1638 struct ath_rate_table *rate_table = NULL;
1639 bool oper_cw40 = false, oper_sgi40;
1640 bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
1641 true : false;
1642 bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
1643 true : false;
1644
1645 /* FIXME: Handle AP mode later when we support CWM */
1646
1647 if (changed & IEEE80211_RC_HT_CHANGED) {
1648 if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
1649 return;
1650
1651 if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS ||
1652 sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS)
1653 oper_cw40 = true;
1654
1655 oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ?
1656 true : false;
1657
1658 if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) {
1659 rate_table = ath_choose_rate_table(sc, sband->band,
1660 sta->ht_cap.ht_supported,
1661 oper_cw40);
1662 ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc,
1663 sta->ht_cap.ht_supported,
1664 oper_cw40, oper_sgi40);
1665 ath_rc_init(sc, priv_sta, sband, sta, rate_table);
1666
1667 DPRINTF(sc, ATH_DBG_CONFIG,
1668 "Operating HT Bandwidth changed to: %d\n",
1669 sc->hw->conf.channel_type);
1670 }
1671 }
1610} 1672}
1611 1673
1612static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) 1674static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
@@ -1650,6 +1712,7 @@ static struct rate_control_ops ath_rate_ops = {
1650 .tx_status = ath_tx_status, 1712 .tx_status = ath_tx_status,
1651 .get_rate = ath_get_rate, 1713 .get_rate = ath_get_rate,
1652 .rate_init = ath_rate_init, 1714 .rate_init = ath_rate_init,
1715 .rate_update = ath_rate_update,
1653 .alloc = ath_rate_alloc, 1716 .alloc = ath_rate_alloc,
1654 .free = ath_rate_free, 1717 .free = ath_rate_free,
1655 .alloc_sta = ath_rate_alloc_sta, 1718 .alloc_sta = ath_rate_alloc_sta,