* 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
*/
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.
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
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.
*/
*/
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.
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);
}