diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/carl9170/carl9170.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/cmd.c | 31 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/cmd.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/main.c | 118 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/phy.c | 7 |
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 | ||
168 | int 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 | |||
168 | int carl9170_powersave(struct ar9170 *ar, const bool ps) | 199 | int 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); | |||
50 | int carl9170_reboot(struct ar9170 *ar); | 50 | int carl9170_reboot(struct ar9170 *ar); |
51 | int carl9170_mac_reset(struct ar9170 *ar); | 51 | int carl9170_mac_reset(struct ar9170 *ar); |
52 | int carl9170_powersave(struct ar9170 *ar, const bool power_on); | 52 | int carl9170_powersave(struct ar9170 *ar, const bool power_on); |
53 | int carl9170_collect_tally(struct ar9170 *ar); | ||
53 | int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id, | 54 | int 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 | ||
424 | static void carl9170_cancel_worker(struct ar9170 *ar) | 427 | static 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 | ||
801 | static 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 | |||
823 | static 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 | ||
798 | static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed) | 839 | static 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 | |||
1506 | found: | ||
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 | ||
1707 | static int carl9170_reg_notifier(struct wiphy *wiphy, | 1800 | static 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); |