aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2011-08-15 13:50:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-24 14:41:42 -0400
commitacf1771221f2877ab5d36487930cd6a2ecaa73e6 (patch)
treecbe4f29eb2b7c5a78a63f99bdffdbaaac141ef33
parentf5e2289a142c714732aef67cadbb0a8843565507 (diff)
carl9170: improve site survey
The firmware keeps track of channel usage. This data can be used by the automatic channel selection to find the *best* channel. Survey data from wlan22 frequency: 2412 MHz [in use] noise: -86 dBm channel active time: 3339608 ms channel busy time: 270982 ms channel transmit time: 121515 ms Survey data from wlan22 frequency: 2417 MHz noise: -86 dBm channel active time: 70 ms channel busy time: 2 ms channel transmit time: 1 ms Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h11
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.c31
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.h1
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c118
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c7
5 files changed, 153 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index f7dbdaa74c63..74350d63f686 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -151,6 +151,7 @@ struct carl9170_sta_tid {
151#define CARL9170_TX_TIMEOUT 2500 151#define CARL9170_TX_TIMEOUT 2500
152#define CARL9170_JANITOR_DELAY 128 152#define CARL9170_JANITOR_DELAY 128
153#define CARL9170_QUEUE_STUCK_TIMEOUT 5500 153#define CARL9170_QUEUE_STUCK_TIMEOUT 5500
154#define CARL9170_STAT_WORK 30000
154 155
155#define CARL9170_NUM_TX_AGG_MAX 30 156#define CARL9170_NUM_TX_AGG_MAX 30
156 157
@@ -332,11 +333,21 @@ struct ar9170 {
332 333
333 /* PHY */ 334 /* PHY */
334 struct ieee80211_channel *channel; 335 struct ieee80211_channel *channel;
336 unsigned int num_channels;
335 int noise[4]; 337 int noise[4];
336 unsigned int chan_fail; 338 unsigned int chan_fail;
337 unsigned int total_chan_fail; 339 unsigned int total_chan_fail;
338 u8 heavy_clip; 340 u8 heavy_clip;
339 u8 ht_settings; 341 u8 ht_settings;
342 struct {
343 u64 active; /* usec */
344 u64 cca; /* usec */
345 u64 tx_time; /* usec */
346 u64 rx_total;
347 u64 rx_overrun;
348 } tally;
349 struct delayed_work stat_work;
350 struct survey_info *survey;
340 351
341 /* power calibration data */ 352 /* power calibration data */
342 u8 power_5G_leg[4]; 353 u8 power_5G_leg[4];
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c
index cdfc94c371b4..9970bf8edc40 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.c
+++ b/drivers/net/wireless/ath/carl9170/cmd.c
@@ -165,6 +165,37 @@ int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
165 return __carl9170_exec_cmd(ar, cmd, true); 165 return __carl9170_exec_cmd(ar, cmd, true);
166} 166}
167 167
168int carl9170_collect_tally(struct ar9170 *ar)
169{
170 struct carl9170_tally_rsp tally;
171 struct survey_info *info;
172 unsigned int tick;
173 int err;
174
175 err = carl9170_exec_cmd(ar, CARL9170_CMD_TALLY, 0, NULL,
176 sizeof(tally), (u8 *)&tally);
177 if (err)
178 return err;
179
180 tick = le32_to_cpu(tally.tick);
181 if (tick) {
182 ar->tally.active += le32_to_cpu(tally.active) / tick;
183 ar->tally.cca += le32_to_cpu(tally.cca) / tick;
184 ar->tally.tx_time += le32_to_cpu(tally.tx_time) / tick;
185 ar->tally.rx_total += le32_to_cpu(tally.rx_total);
186 ar->tally.rx_overrun += le32_to_cpu(tally.rx_overrun);
187
188 if (ar->channel) {
189 info = &ar->survey[ar->channel->hw_value];
190
191 info->channel_time = ar->tally.active / 1000;
192 info->channel_time_busy = ar->tally.cca / 1000;
193 info->channel_time_tx = ar->tally.tx_time / 1000;
194 }
195 }
196 return 0;
197}
198
168int carl9170_powersave(struct ar9170 *ar, const bool ps) 199int carl9170_powersave(struct ar9170 *ar, const bool ps)
169{ 200{
170 struct carl9170_cmd *cmd; 201 struct carl9170_cmd *cmd;
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h
index d5f95bdc75c1..885c42778b8b 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.h
+++ b/drivers/net/wireless/ath/carl9170/cmd.h
@@ -50,6 +50,7 @@ int carl9170_echo_test(struct ar9170 *ar, u32 v);
50int carl9170_reboot(struct ar9170 *ar); 50int carl9170_reboot(struct ar9170 *ar);
51int carl9170_mac_reset(struct ar9170 *ar); 51int carl9170_mac_reset(struct ar9170 *ar);
52int carl9170_powersave(struct ar9170 *ar, const bool power_on); 52int carl9170_powersave(struct ar9170 *ar, const bool power_on);
53int carl9170_collect_tally(struct ar9170 *ar);
53int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, 54int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
54 const u32 mode, const u32 addr, const u32 len); 55 const u32 mode, const u32 addr, const u32 len);
55 56
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 0122930b14c7..85cb1bdebaaa 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -413,6 +413,9 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
413 413
414 carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED); 414 carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED);
415 415
416 ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
417 round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
418
416 ieee80211_wake_queues(ar->hw); 419 ieee80211_wake_queues(ar->hw);
417 err = 0; 420 err = 0;
418 421
@@ -423,6 +426,7 @@ out:
423 426
424static void carl9170_cancel_worker(struct ar9170 *ar) 427static void carl9170_cancel_worker(struct ar9170 *ar)
425{ 428{
429 cancel_delayed_work_sync(&ar->stat_work);
426 cancel_delayed_work_sync(&ar->tx_janitor); 430 cancel_delayed_work_sync(&ar->tx_janitor);
427#ifdef CONFIG_CARL9170_LEDS 431#ifdef CONFIG_CARL9170_LEDS
428 cancel_delayed_work_sync(&ar->led_work); 432 cancel_delayed_work_sync(&ar->led_work);
@@ -794,6 +798,43 @@ static void carl9170_ps_work(struct work_struct *work)
794 mutex_unlock(&ar->mutex); 798 mutex_unlock(&ar->mutex);
795} 799}
796 800
801static int carl9170_update_survey(struct ar9170 *ar, bool flush, bool noise)
802{
803 int err;
804
805 if (noise) {
806 err = carl9170_get_noisefloor(ar);
807 if (err)
808 return err;
809 }
810
811 if (ar->fw.hw_counters) {
812 err = carl9170_collect_tally(ar);
813 if (err)
814 return err;
815 }
816
817 if (flush)
818 memset(&ar->tally, 0, sizeof(ar->tally));
819
820 return 0;
821}
822
823static void carl9170_stat_work(struct work_struct *work)
824{
825 struct ar9170 *ar = container_of(work, struct ar9170, stat_work.work);
826 int err;
827
828 mutex_lock(&ar->mutex);
829 err = carl9170_update_survey(ar, false, true);
830 mutex_unlock(&ar->mutex);
831
832 if (err)
833 return;
834
835 ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
836 round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
837}
797 838
798static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) 839static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
799{ 840{
@@ -828,11 +869,19 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
828 if (err) 869 if (err)
829 goto out; 870 goto out;
830 871
872 err = carl9170_update_survey(ar, true, false);
873 if (err)
874 goto out;
875
831 err = carl9170_set_channel(ar, hw->conf.channel, 876 err = carl9170_set_channel(ar, hw->conf.channel,
832 hw->conf.channel_type, CARL9170_RFI_NONE); 877 hw->conf.channel_type, CARL9170_RFI_NONE);
833 if (err) 878 if (err)
834 goto out; 879 goto out;
835 880
881 err = carl9170_update_survey(ar, false, true);
882 if (err)
883 goto out;
884
836 err = carl9170_set_dyn_sifs_ack(ar); 885 err = carl9170_set_dyn_sifs_ack(ar);
837 if (err) 886 if (err)
838 goto out; 887 goto out;
@@ -1423,20 +1472,52 @@ static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
1423 struct survey_info *survey) 1472 struct survey_info *survey)
1424{ 1473{
1425 struct ar9170 *ar = hw->priv; 1474 struct ar9170 *ar = hw->priv;
1426 int err; 1475 struct ieee80211_channel *chan;
1476 struct ieee80211_supported_band *band;
1477 int err, b, i;
1427 1478
1428 if (idx != 0) 1479 chan = ar->channel;
1429 return -ENOENT; 1480 if (!chan)
1481 return -ENODEV;
1430 1482
1431 mutex_lock(&ar->mutex); 1483 if (idx == chan->hw_value) {
1432 err = carl9170_get_noisefloor(ar); 1484 mutex_lock(&ar->mutex);
1433 mutex_unlock(&ar->mutex); 1485 err = carl9170_update_survey(ar, false, true);
1434 if (err) 1486 mutex_unlock(&ar->mutex);
1435 return err; 1487 if (err)
1488 return err;
1489 }
1436 1490
1437 survey->channel = ar->channel; 1491 for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
1492 band = ar->hw->wiphy->bands[b];
1493
1494 if (!band)
1495 continue;
1496
1497 for (i = 0; i < band->n_channels; i++) {
1498 if (band->channels[i].hw_value == idx) {
1499 chan = &band->channels[i];
1500 goto found;
1501 }
1502 }
1503 }
1504 return -ENOENT;
1505
1506found:
1507 memcpy(survey, &ar->survey[idx], sizeof(*survey));
1508
1509 survey->channel = chan;
1438 survey->filled = SURVEY_INFO_NOISE_DBM; 1510 survey->filled = SURVEY_INFO_NOISE_DBM;
1439 survey->noise = ar->noise[0]; 1511
1512 if (ar->channel == chan)
1513 survey->filled |= SURVEY_INFO_IN_USE;
1514
1515 if (ar->fw.hw_counters) {
1516 survey->filled |= SURVEY_INFO_CHANNEL_TIME |
1517 SURVEY_INFO_CHANNEL_TIME_BUSY |
1518 SURVEY_INFO_CHANNEL_TIME_TX;
1519 }
1520
1440 return 0; 1521 return 0;
1441} 1522}
1442 1523
@@ -1569,6 +1650,7 @@ void *carl9170_alloc(size_t priv_size)
1569 INIT_WORK(&ar->ping_work, carl9170_ping_work); 1650 INIT_WORK(&ar->ping_work, carl9170_ping_work);
1570 INIT_WORK(&ar->restart_work, carl9170_restart_work); 1651 INIT_WORK(&ar->restart_work, carl9170_restart_work);
1571 INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work); 1652 INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
1653 INIT_DELAYED_WORK(&ar->stat_work, carl9170_stat_work);
1572 INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor); 1654 INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
1573 INIT_LIST_HEAD(&ar->tx_ampdu_list); 1655 INIT_LIST_HEAD(&ar->tx_ampdu_list);
1574 rcu_assign_pointer(ar->tx_ampdu_iter, 1656 rcu_assign_pointer(ar->tx_ampdu_iter,
@@ -1652,6 +1734,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
1652 struct ath_regulatory *regulatory = &ar->common.regulatory; 1734 struct ath_regulatory *regulatory = &ar->common.regulatory;
1653 unsigned int rx_streams, tx_streams, tx_params = 0; 1735 unsigned int rx_streams, tx_streams, tx_params = 0;
1654 int bands = 0; 1736 int bands = 0;
1737 int chans = 0;
1655 1738
1656 if (ar->eeprom.length == cpu_to_le16(0xffff)) 1739 if (ar->eeprom.length == cpu_to_le16(0xffff))
1657 return -ENODATA; 1740 return -ENODATA;
@@ -1675,14 +1758,24 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
1675 if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { 1758 if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
1676 ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = 1759 ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
1677 &carl9170_band_2GHz; 1760 &carl9170_band_2GHz;
1761 chans += carl9170_band_2GHz.n_channels;
1678 bands++; 1762 bands++;
1679 } 1763 }
1680 if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { 1764 if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
1681 ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = 1765 ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
1682 &carl9170_band_5GHz; 1766 &carl9170_band_5GHz;
1767 chans += carl9170_band_5GHz.n_channels;
1683 bands++; 1768 bands++;
1684 } 1769 }
1685 1770
1771 if (!bands)
1772 return -EINVAL;
1773
1774 ar->survey = kzalloc(sizeof(struct survey_info) * chans, GFP_KERNEL);
1775 if (!ar->survey)
1776 return -ENOMEM;
1777 ar->num_channels = chans;
1778
1686 /* 1779 /*
1687 * I measured this, a bandswitch takes roughly 1780 * I measured this, a bandswitch takes roughly
1688 * 135 ms and a frequency switch about 80. 1781 * 135 ms and a frequency switch about 80.
@@ -1701,7 +1794,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
1701 /* second part of wiphy init */ 1794 /* second part of wiphy init */
1702 SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address); 1795 SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
1703 1796
1704 return bands ? 0 : -EINVAL; 1797 return 0;
1705} 1798}
1706 1799
1707static int carl9170_reg_notifier(struct wiphy *wiphy, 1800static int carl9170_reg_notifier(struct wiphy *wiphy,
@@ -1834,6 +1927,9 @@ void carl9170_free(struct ar9170 *ar)
1834 kfree(ar->mem_bitmap); 1927 kfree(ar->mem_bitmap);
1835 ar->mem_bitmap = NULL; 1928 ar->mem_bitmap = NULL;
1836 1929
1930 kfree(ar->survey);
1931 ar->survey = NULL;
1932
1837 mutex_destroy(&ar->mutex); 1933 mutex_destroy(&ar->mutex);
1838 1934
1839 ieee80211_free_hw(ar->hw); 1935 ieee80211_free_hw(ar->hw);
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index 8635c5c8463c..472efc7e3402 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1573,6 +1573,9 @@ int carl9170_get_noisefloor(struct ar9170 *ar)
1573 AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8); 1573 AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);
1574 } 1574 }
1575 1575
1576 if (ar->channel)
1577 ar->survey[ar->channel->hw_value].noise = ar->noise[0];
1578
1576 return 0; 1579 return 0;
1577} 1580}
1578 1581
@@ -1765,10 +1768,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
1765 ar->chan_fail = 0; 1768 ar->chan_fail = 0;
1766 } 1769 }
1767 1770
1768 err = carl9170_get_noisefloor(ar);
1769 if (err)
1770 return err;
1771
1772 if (ar->heavy_clip) { 1771 if (ar->heavy_clip) {
1773 err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE, 1772 err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,
1774 0x200 | ar->heavy_clip); 1773 0x200 | ar->heavy_clip);