diff options
author | Whi copybara merger <whitechapel-automerger@google.com> | 2022-05-02 15:20:48 +0530 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-05-10 17:46:31 -0700 |
commit | 92144428553ca6654e4e6f4e963f116244ecbb2a (patch) | |
tree | 8c67db4395ad075de6967f955351fc703b150340 | |
parent | af622a86fc1cec1d75575c92d49b502d2be1cf21 (diff) | |
download | janeiro-92144428553ca6654e4e6f4e963f116244ecbb2a.tar.gz |
[Copybara Auto Merge] Merge branch 'pro' into android13-gs-pixel-5.10
edgetpu: add support for all dvfs frequencies
Bug: 230582743
edgetpu: fetch hw ctx region from device tree
Bug: 230236668
GitOrigin-RevId: e60acf09440d62f96d1a047d2f70b76e0dbd6863
Change-Id: Id187c2635cc2de627bedf168c0fefb2f4a9411c2
-rw-r--r-- | drivers/edgetpu/edgetpu-core.c | 2 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-internal.h | 4 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-mobile-platform.c | 32 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-usage-stats.c | 87 | ||||
-rw-r--r-- | drivers/edgetpu/edgetpu-usage-stats.h | 2 | ||||
-rw-r--r-- | drivers/edgetpu/janeiro-platform.c | 28 |
6 files changed, 121 insertions, 34 deletions
diff --git a/drivers/edgetpu/edgetpu-core.c b/drivers/edgetpu/edgetpu-core.c index b84d626..81c54a6 100644 --- a/drivers/edgetpu/edgetpu-core.c +++ b/drivers/edgetpu/edgetpu-core.c @@ -434,6 +434,8 @@ int edgetpu_device_add(struct edgetpu_dev *etdev, etdev->vcid_pool = (1u << EDGETPU_NUM_VCIDS) - 1; mutex_init(&etdev->state_lock); etdev->state = ETDEV_STATE_NOFW; + etdev->freq_count = 0; + mutex_init(&etdev->freq_lock); ret = edgetpu_fs_add(etdev, iface_params, num_ifaces); if (ret) { diff --git a/drivers/edgetpu/edgetpu-internal.h b/drivers/edgetpu/edgetpu-internal.h index 122a3e7..37ea27f 100644 --- a/drivers/edgetpu/edgetpu-internal.h +++ b/drivers/edgetpu/edgetpu-internal.h @@ -226,6 +226,10 @@ struct edgetpu_dev { /* debug dump handlers */ edgetpu_debug_dump_handlers *debug_dump_handlers; struct work_struct debug_dump_work; + + struct mutex freq_lock; /* protects below freq_* variables */ + uint32_t *freq_table; /* Array to record reported frequencies by f/w */ + uint32_t freq_count; /* Number of entries in freq_table */ }; struct edgetpu_dev_iface { diff --git a/drivers/edgetpu/edgetpu-mobile-platform.c b/drivers/edgetpu/edgetpu-mobile-platform.c index 4e9cac0..af6bcb7 100644 --- a/drivers/edgetpu/edgetpu-mobile-platform.c +++ b/drivers/edgetpu/edgetpu-mobile-platform.c @@ -279,6 +279,38 @@ static void edgetpu_platform_remove_irq(struct edgetpu_mobile_platform_dev *etmd edgetpu_unregister_irq(etdev, etmdev->irq[i]); } +/* + * Fetch and set the firmware context region from device tree. + * + * Maybe be unused since not all chips need this. + */ +static int __maybe_unused +edgetpu_mobile_platform_set_fw_ctx_memory(struct edgetpu_mobile_platform_dev *etmdev) +{ + struct edgetpu_dev *etdev = &etmdev->edgetpu_dev; + struct device *dev = etdev->dev; + struct resource r; + struct device_node *np; + int ret; + + np = of_parse_phandle(dev->of_node, "memory-region", 1); + if (!np) { + etdev_warn(etdev, "No memory for firmware contexts"); + return -ENODEV; + } + + ret = of_address_to_resource(np, 0, &r); + of_node_put(np); + if (ret) { + etdev_warn(etdev, "No memory address for firmware contexts"); + return ret; + } + + etmdev->fw_ctx_paddr = r.start; + etmdev->fw_ctx_size = resource_size(&r); + return 0; +} + static int edgetpu_mobile_platform_probe(struct platform_device *pdev, struct edgetpu_mobile_platform_dev *etmdev) { diff --git a/drivers/edgetpu/edgetpu-usage-stats.c b/drivers/edgetpu/edgetpu-usage-stats.c index 41d149d..ba93d49 100644 --- a/drivers/edgetpu/edgetpu-usage-stats.c +++ b/drivers/edgetpu/edgetpu-usage-stats.c @@ -13,16 +13,36 @@ #include "edgetpu-kci.h" #include "edgetpu-usage-stats.h" +/* Max number of frequencies to support */ +#define EDGETPU_MAX_STATES 10 + struct uid_entry { int32_t uid; - uint64_t time_in_state[EDGETPU_NUM_STATES]; + uint64_t time_in_state[EDGETPU_MAX_STATES]; struct hlist_node node; }; -static int tpu_state_map(uint32_t state) +static int tpu_state_map(struct edgetpu_dev *etdev, uint32_t state) { - int i; + int i, idx = 0; + + mutex_lock(&etdev->freq_lock); + /* Use frequency table if f/w already reported via usage_stats */ + if (etdev->freq_table) { + for (i = etdev->freq_count - 1; i >= 0; i--) { + if (state == etdev->freq_table[i]) + idx = i; + } + mutex_unlock(&etdev->freq_lock); + return idx; + } + + mutex_unlock(&etdev->freq_lock); + /* + * use predefined state table in case of no f/w reported supported + * frequencies. + */ for (i = (EDGETPU_NUM_STATES - 1); i >= 0; i--) { if (state >= edgetpu_active_states[i]) return i; @@ -49,7 +69,7 @@ int edgetpu_usage_add(struct edgetpu_dev *etdev, struct tpu_usage *tpu_usage) { struct edgetpu_usage_stats *ustats = etdev->usage_stats; struct uid_entry *uid_entry; - int state = tpu_state_map(tpu_usage->power_state); + int state = tpu_state_map(etdev, tpu_usage->power_state); if (!ustats) return 0; @@ -186,6 +206,39 @@ static void edgetpu_thread_stats_update( mutex_unlock(&ustats->usage_stats_lock); } +/* Record new supported frequencies if reported by firmware */ +static void edgetpu_dvfs_frequency_update(struct edgetpu_dev *etdev, uint32_t frequency) +{ + uint32_t *freq_table, i; + + mutex_lock(&etdev->freq_lock); + if (!etdev->freq_table) { + freq_table = kvmalloc(EDGETPU_MAX_STATES * sizeof(uint32_t), GFP_KERNEL); + if (!freq_table) { + etdev_warn(etdev, "Unable to create supported frequencies table"); + goto out; + } + etdev->freq_count = 0; + etdev->freq_table = freq_table; + } + + freq_table = etdev->freq_table; + + for (i = 0; i < etdev->freq_count; i++) { + if (freq_table[i] == frequency) + goto out; + } + + if (etdev->freq_count >= EDGETPU_MAX_STATES) { + etdev_warn(etdev, "Unable to record supported frequencies"); + goto out; + } + + freq_table[etdev->freq_count++] = frequency; +out: + mutex_unlock(&etdev->freq_lock); +} + void edgetpu_usage_stats_process_buffer(struct edgetpu_dev *etdev, void *buf) { struct edgetpu_usage_header *header = buf; @@ -221,6 +274,10 @@ void edgetpu_usage_stats_process_buffer(struct edgetpu_dev *etdev, void *buf) edgetpu_thread_stats_update( etdev, &metric->thread_stats); break; + case EDGETPU_METRIC_TYPE_DVFS_FREQUENCY_INFO: + edgetpu_dvfs_frequency_update( + etdev, metric->dvfs_frequency_info); + break; default: etdev_dbg(etdev, "%s: %d: skip unknown type=%u", __func__, i, metric->type); @@ -294,9 +351,18 @@ static ssize_t tpu_usage_show(struct device *dev, /* uid: state0speed state1speed ... */ ret += scnprintf(buf, PAGE_SIZE, "uid:"); - for (i = 0; i < EDGETPU_NUM_STATES; i++) - ret += scnprintf(buf + ret, PAGE_SIZE - ret, " %d", - edgetpu_states_display[i]); + mutex_lock(&etdev->freq_lock); + if (!etdev->freq_table) { + mutex_unlock(&etdev->freq_lock); + for (i = 0; i < EDGETPU_NUM_STATES; i++) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, " %d", + edgetpu_states_display[i]); + } else { + for (i = 0; i < etdev->freq_count; i++) + ret += scnprintf(buf + ret, PAGE_SIZE - ret, " %d", + etdev->freq_table[i]); + mutex_unlock(&etdev->freq_lock); + } ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); @@ -877,6 +943,13 @@ void edgetpu_usage_stats_exit(struct edgetpu_dev *etdev) if (ustats) { usage_stats_remove_uids(ustats); device_remove_group(etdev->dev, &usage_stats_attr_group); + /* free the frequency table if allocated */ + mutex_lock(&etdev->freq_lock); + if (etdev->freq_table) + kvfree(etdev->freq_table); + etdev->freq_table = NULL; + etdev->freq_count = 0; + mutex_unlock(&etdev->freq_lock); } etdev_dbg(etdev, "%s exit\n", __func__); diff --git a/drivers/edgetpu/edgetpu-usage-stats.h b/drivers/edgetpu/edgetpu-usage-stats.h index 6b5d612..a60b107 100644 --- a/drivers/edgetpu/edgetpu-usage-stats.h +++ b/drivers/edgetpu/edgetpu-usage-stats.h @@ -150,6 +150,7 @@ enum edgetpu_usage_metric_type { EDGETPU_METRIC_TYPE_COUNTER = 3, EDGETPU_METRIC_TYPE_THREAD_STATS = 4, EDGETPU_METRIC_TYPE_MAX_WATERMARK = 5, + EDGETPU_METRIC_TYPE_DVFS_FREQUENCY_INFO = 6, }; /* @@ -165,6 +166,7 @@ struct edgetpu_usage_metric { struct edgetpu_usage_counter counter; struct edgetpu_thread_stats thread_stats; struct edgetpu_usage_max_watermark max_watermark; + uint32_t dvfs_frequency_info; }; }; diff --git a/drivers/edgetpu/janeiro-platform.c b/drivers/edgetpu/janeiro-platform.c index d17aa9c..a618a18 100644 --- a/drivers/edgetpu/janeiro-platform.c +++ b/drivers/edgetpu/janeiro-platform.c @@ -47,32 +47,6 @@ static int janeiro_mmu_set_shareability(struct device *dev, u32 reg_base) return 0; } -static int janeiro_set_fw_ctx_memory(struct edgetpu_mobile_platform_dev *etmdev) -{ - struct edgetpu_dev *etdev = &etmdev->edgetpu_dev; - struct device *dev = etdev->dev; - struct resource r; - struct device_node *np; - int ret; - - np = of_parse_phandle(dev->of_node, "memory-region", 1); - if (!np) { - etdev_warn(etdev, "No memory for firmware contexts"); - return -ENODEV; - } - - ret = of_address_to_resource(np, 0, &r); - of_node_put(np); - if (ret) { - etdev_warn(etdev, "No memory address for firmware contexts"); - return ret; - } - - etmdev->fw_ctx_paddr = r.start; - etmdev->fw_ctx_size = resource_size(&r); - return 0; -} - static int janeiro_parse_set_dt_property(struct edgetpu_mobile_platform_dev *etmdev) { int ret; @@ -80,7 +54,7 @@ static int janeiro_parse_set_dt_property(struct edgetpu_mobile_platform_dev *etm struct edgetpu_dev *etdev = &etmdev->edgetpu_dev; struct device *dev = etdev->dev; - ret = janeiro_set_fw_ctx_memory(etmdev); + ret = edgetpu_mobile_platform_set_fw_ctx_memory(etmdev); if (ret) { etdev_err(etdev, "Failed to initialize fw context memory: %d", ret); return ret; |