mt76: mt7921: add awake and doze time accounting
authorLorenzo Bianconi <lorenzo@kernel.org>
Sun, 18 Apr 2021 16:45:44 +0000 (18:45 +0200)
committerFelix Fietkau <nbd@nbd.name>
Wed, 21 Apr 2021 18:55:53 +0000 (20:55 +0200)
Introduce awake and doze time accounting for runtime pm.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76_connac.h
drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
drivers/net/wireless/mediatek/mt76/mt7921/init.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c

index e3937f6..9e61c10 100644 (file)
@@ -64,6 +64,12 @@ struct mt76_connac_pm {
        struct delayed_work ps_work;
        unsigned long last_activity;
        unsigned long idle_timeout;
+       struct {
+               unsigned long last_wake_event;
+               unsigned long awake_time;
+               unsigned long last_doze_event;
+               unsigned long doze_time;
+       } stats;
 };
 
 struct mt76_connac_coredump {
index 5a54cd8..f398257 100644 (file)
@@ -230,11 +230,19 @@ static int
 mt7921_pm_set(void *data, u64 val)
 {
        struct mt7921_dev *dev = data;
+       struct mt76_connac_pm *pm = &dev->pm;
        struct mt76_phy *mphy = dev->phy.mt76;
 
+       if (val == pm->enable)
+               return 0;
+
        mt7921_mutex_acquire(dev);
 
-       dev->pm.enable = val;
+       if (!pm->enable) {
+               pm->stats.last_wake_event = jiffies;
+               pm->stats.last_doze_event = jiffies;
+       }
+       pm->enable = val;
 
        ieee80211_iterate_active_interfaces(mphy->hw,
                                            IEEE80211_IFACE_ITER_RESUME_ALL,
@@ -257,6 +265,26 @@ mt7921_pm_get(void *data, u64 *val)
 DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n");
 
 static int
+mt7921_pm_stats(struct seq_file *s, void *data)
+{
+       struct mt7921_dev *dev = dev_get_drvdata(s->private);
+       struct mt76_connac_pm *pm = &dev->pm;
+       unsigned long awake_time = pm->stats.awake_time;
+       unsigned long doze_time = pm->stats.doze_time;
+
+       if (!test_bit(MT76_STATE_PM, &dev->mphy.state))
+               awake_time += jiffies - pm->stats.last_wake_event;
+       else
+               doze_time += jiffies - pm->stats.last_doze_event;
+
+       seq_printf(s, "awake time: %14u\ndoze time: %15u\n",
+                  jiffies_to_msecs(awake_time),
+                  jiffies_to_msecs(doze_time));
+
+       return 0;
+}
+
+static int
 mt7921_pm_idle_timeout_set(void *data, u64 val)
 {
        struct mt7921_dev *dev = data;
@@ -322,6 +350,8 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
        debugfs_create_file("idle-timeout", 0600, dir, dev,
                            &fops_pm_idle_timeout);
        debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset);
+       debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
+                                   mt7921_pm_stats);
 
        return 0;
 }
index 2d8dba0..cec17a2 100644 (file)
@@ -239,12 +239,15 @@ int mt7921_register_device(struct mt7921_dev *dev)
 
        INIT_WORK(&dev->reset_work, mt7921_mac_reset_work);
 
+       dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
+       dev->pm.stats.last_wake_event = jiffies;
+       dev->pm.stats.last_doze_event = jiffies;
+
        ret = mt7921_init_hardware(dev);
        if (ret)
                return ret;
 
        mt7921_init_wiphy(hw);
-       dev->pm.idle_timeout = MT7921_PM_TIMEOUT;
        dev->mphy.sband_2g.sband.ht_cap.cap |=
                        IEEE80211_HT_CAP_LDPC_CODING |
                        IEEE80211_HT_CAP_MAX_AMSDU;
index 1204f5d..c00295b 100644 (file)
@@ -1267,9 +1267,10 @@ int mt7921_mcu_set_bss_pm(struct mt7921_dev *dev, struct ieee80211_vif *vif,
 int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
 {
        struct mt76_phy *mphy = &dev->mt76.phy;
+       struct mt76_connac_pm *pm = &dev->pm;
        int i, err = 0;
 
-       mutex_lock(&dev->pm.mutex);
+       mutex_lock(&pm->mutex);
 
        if (!test_bit(MT76_STATE_PM, &mphy->state))
                goto out;
@@ -1288,8 +1289,11 @@ int mt7921_mcu_drv_pmctrl(struct mt7921_dev *dev)
        }
        clear_bit(MT76_STATE_PM, &mphy->state);
 
+       pm->stats.last_wake_event = jiffies;
+       pm->stats.doze_time += pm->stats.last_wake_event -
+                              pm->stats.last_doze_event;
 out:
-       mutex_unlock(&dev->pm.mutex);
+       mutex_unlock(&pm->mutex);
 
        if (err)
                mt7921_reset(&dev->mt76);
@@ -1300,11 +1304,12 @@ out:
 int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev)
 {
        struct mt76_phy *mphy = &dev->mt76.phy;
+       struct mt76_connac_pm *pm = &dev->pm;
        int i, err = 0;
 
-       mutex_lock(&dev->pm.mutex);
+       mutex_lock(&pm->mutex);
 
-       if (mt76_connac_skip_fw_pmctrl(mphy, &dev->pm))
+       if (mt76_connac_skip_fw_pmctrl(mphy, pm))
                goto out;
 
        for (i = 0; i < MT7921_DRV_OWN_RETRY_COUNT; i++) {
@@ -1319,8 +1324,12 @@ int mt7921_mcu_fw_pmctrl(struct mt7921_dev *dev)
                clear_bit(MT76_STATE_PM, &mphy->state);
                err = -EIO;
        }
+
+       pm->stats.last_doze_event = jiffies;
+       pm->stats.awake_time += pm->stats.last_doze_event -
+                               pm->stats.last_wake_event;
 out:
-       mutex_unlock(&dev->pm.mutex);
+       mutex_unlock(&pm->mutex);
 
        if (err)
                mt7921_reset(&dev->mt76);