Commit d9632470 authored by Stanislaw Gruszka's avatar Stanislaw Gruszka Committed by Kalle Valo

rt2x00: merge agc and vco works with link tuner

We need to perform different actions (AGC and VCO calibrations and VGC
tuning) periodically at different intervals. We don't need separate
works for those, we can use link tuner work and just check for proper
interval on it.

This fixes performing AGC and VCO calibration when scanning on STA
mode. We need to be on-channel to perform those calibrations.
Signed-off-by: default avatarStanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 24d42ef3
......@@ -87,9 +87,6 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
*/
rt2x00queue_start_queues(rt2x00dev);
rt2x00link_start_tuner(rt2x00dev);
rt2x00link_start_agc(rt2x00dev);
if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
rt2x00link_start_vcocal(rt2x00dev);
/*
* Start watchdog monitoring.
......@@ -112,9 +109,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Stop all queues
*/
rt2x00link_stop_agc(rt2x00dev);
if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
rt2x00link_stop_vcocal(rt2x00dev);
rt2x00link_stop_tuner(rt2x00dev);
rt2x00queue_stop_queues(rt2x00dev);
rt2x00queue_flush_queues(rt2x00dev, true);
......
......@@ -29,9 +29,10 @@
* Interval defines
*/
#define WATCHDOG_INTERVAL round_jiffies_relative(HZ)
#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ)
#define AGC_INTERVAL round_jiffies_relative(4 * HZ)
#define VCO_INTERVAL round_jiffies_relative(10 * HZ) /* 10 sec */
#define LINK_TUNE_SECONDS 1
#define LINK_TUNE_INTERVAL round_jiffies_relative(LINK_TUNE_SECONDS * HZ)
#define AGC_SECONDS 4
#define VCO_SECONDS 10
/*
* rt2x00_rate: Per rate device information
......@@ -270,30 +271,6 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev);
*/
void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00link_start_agc - Start periodic gain calibration
* @rt2x00dev: Pointer to &struct rt2x00_dev.
*/
void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00link_start_vcocal - Start periodic VCO calibration
* @rt2x00dev: Pointer to &struct rt2x00_dev.
*/
void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00link_stop_agc - Stop periodic gain calibration
* @rt2x00dev: Pointer to &struct rt2x00_dev.
*/
void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00link_stop_vcocal - Stop periodic VCO calibration
* @rt2x00dev: Pointer to &struct rt2x00_dev.
*/
void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00link_register - Initialize link tuning & watchdog functionality
* @rt2x00dev: Pointer to &struct rt2x00_dev.
......
......@@ -233,15 +233,13 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
struct link *link = &rt2x00dev->link;
/*
* Link tuning should only be performed when
* an active sta interface exists. AP interfaces
* don't need link tuning and monitor mode interfaces
* should never have to work with link tuners.
* Single monitor mode interfaces should never have
* work with link tuners.
*/
if (!rt2x00dev->intf_sta_count)
if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)
return;
/**
/*
* While scanning, link tuning is disabled. By default
* the most sensitive settings will be used to make sure
* that all beacons and probe responses will be received
......@@ -308,21 +306,10 @@ static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev)
qual->tx_failed = 0;
}
static void rt2x00link_tuner(struct work_struct *work)
static void rt2x00link_tuner_sta(struct rt2x00_dev *rt2x00dev, struct link *link)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, link.work.work);
struct link *link = &rt2x00dev->link;
struct link_qual *qual = &rt2x00dev->link.qual;
/*
* When the radio is shutting down we should
* immediately cease all link tuning.
*/
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
return;
/*
* Update statistics.
*/
......@@ -360,6 +347,33 @@ static void rt2x00link_tuner(struct work_struct *work)
*/
if (rt2x00lib_antenna_diversity(rt2x00dev))
rt2x00link_reset_qual(rt2x00dev);
}
static void rt2x00link_tuner(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, link.work.work);
struct link *link = &rt2x00dev->link;
/*
* When the radio is shutting down we should
* immediately cease all link tuning.
*/
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) ||
test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
return;
if (rt2x00dev->intf_sta_count)
rt2x00link_tuner_sta(rt2x00dev, link);
if (rt2x00dev->ops->lib->gain_calibration &&
(link->count % (AGC_SECONDS / LINK_TUNE_SECONDS)) == 0)
rt2x00dev->ops->lib->gain_calibration(rt2x00dev);
if (rt2x00dev->ops->lib->vco_calibration &&
rt2x00_has_cap_vco_recalibration(rt2x00dev) &&
(link->count % (VCO_SECONDS / LINK_TUNE_SECONDS)) == 0)
rt2x00dev->ops->lib->vco_calibration(rt2x00dev);
/*
* Increase tuner counter, and reschedule the next link tuner run.
......@@ -408,85 +422,8 @@ static void rt2x00link_watchdog(struct work_struct *work)
WATCHDOG_INTERVAL);
}
void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev)
{
struct link *link = &rt2x00dev->link;
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
rt2x00dev->ops->lib->gain_calibration)
ieee80211_queue_delayed_work(rt2x00dev->hw,
&link->agc_work,
AGC_INTERVAL);
}
void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev)
{
struct link *link = &rt2x00dev->link;
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
rt2x00dev->ops->lib->vco_calibration)
ieee80211_queue_delayed_work(rt2x00dev->hw,
&link->vco_work,
VCO_INTERVAL);
}
void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev)
{
cancel_delayed_work_sync(&rt2x00dev->link.agc_work);
}
void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev)
{
cancel_delayed_work_sync(&rt2x00dev->link.vco_work);
}
static void rt2x00link_agc(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, link.agc_work.work);
struct link *link = &rt2x00dev->link;
/*
* When the radio is shutting down we should
* immediately cease the watchdog monitoring.
*/
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
rt2x00dev->ops->lib->gain_calibration(rt2x00dev);
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
ieee80211_queue_delayed_work(rt2x00dev->hw,
&link->agc_work,
AGC_INTERVAL);
}
static void rt2x00link_vcocal(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, link.vco_work.work);
struct link *link = &rt2x00dev->link;
/*
* When the radio is shutting down we should
* immediately cease the VCO calibration.
*/
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
rt2x00dev->ops->lib->vco_calibration(rt2x00dev);
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
ieee80211_queue_delayed_work(rt2x00dev->hw,
&link->vco_work,
VCO_INTERVAL);
}
void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
{
INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc);
if (rt2x00_has_cap_vco_recalibration(rt2x00dev))
INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal);
INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment