Re: [PATCH 3/7] OPP: Rework _set_required_devs() to manage a single device per call
From: Viresh Kumar <viresh.kumar@linaro.org>
Date: 2024-06-26 06:33:25
Also in:
linux-pm, lkml
On 19-06-24, 16:08, Ulf Hansson wrote:
quoted hunk ↗ jump to hunk
@@ -2494,36 +2495,68 @@ static int _opp_set_required_devs(struct opp_table *opp_table, return -EINVAL; } - /* Another device that shares the OPP table has set the required devs ? */ - if (opp_table->required_devs[0]) - return 0; + /* Genpd core takes care of propagation to parent genpd */ + if (opp_table->is_genpd) {
A genpd can have non-genpd devices in the required OPPs and so this isn't sufficient. What we were ignoring earlier was genpd having another genpd as required opp.
+ dev_err(dev, "%s: Operation not supported for genpds\n", __func__);
+ return -EOPNOTSUPP;
+ }
for (i = 0; i < opp_table->required_opp_count; i++) {
- /* Genpd core takes care of propagation to parent genpd */
- if (required_devs[i] && opp_table->is_genpd &&
- opp_table->required_opp_tables[i]->is_genpd) {
- dev_err(dev, "%s: Operation not supported for genpds\n", __func__);
- return -EOPNOTSUPP;
- }
+ struct opp_table *table = opp_table->required_opp_tables[i];
+
+ /*
+ * The OPP table should be available at this point. If not, it's
+ * not the one we are looking for.
+ */
+ if (IS_ERR(table))
+ continue;
+
+ /* Move to the next available index. */
+ if (opp_table->required_devs[i])
+ continue;
- opp_table->required_devs[i] = required_devs[i];
+ /*
+ * We need to compare the nodes for the OPP tables, rather than
+ * the OPP tables themselves, as we may have separate instances.
+ */
+ if (required_opp_table->np == table->np) {
+We don't keep such empty lines in OPP core generally at this place.
+ /* Cross check the OPP tables and fix it if needed. */
Copy the bigger comment from_opp_attach_genpd() here too. It helps understanding why required_opp_tables entry is getting replaced.
+ if (required_opp_table != table) {
+ dev_pm_opp_put_opp_table(table);
+ _get_opp_table_kref(required_opp_table);
+ opp_table->required_opp_tables[i] = required_opp_table;
+ }
+
+ opp_table->required_devs[i] = required_dev;
+
+ /*
+ * Add the required_dev as a user of the OPP table, so
+ * we can call dev_pm_opp_set_opp() on it directly.
+ */
+ if (!_add_opp_dev(required_dev, required_opp_table)) {
+ dev_err(dev, "Failed to add the device to the required OPP table\n");
+ return -ENOMEM;
+ }
+
+ return i;
+ }
}-- viresh