From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
To: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: lenb@kernel.org, linux-pm@vger.kernel.org,
mario.limonciello@dell.com, linux-kernel@vger.kernel.org,
linux-acpi@vger.kernel.org
Subject: Re: [PATCH v3] ACPI / Sleep: Check low power idle constraints for debug only
Date: Sat, 12 Aug 2017 08:59:16 -0700 [thread overview]
Message-ID: <1502553556.20268.47.camel@linux.intel.com> (raw)
In-Reply-To: <18796717.B6iU8dePCh@aspire.rjw.lan>
On Sat, 2017-08-12 at 16:27 +0200, Rafael J. Wysocki wrote:
[...]
> > +
> > +struct lpi_constraints {
> > + char *name;
> > + int min_dstate;
> If you store the handle here as well, you won't need to
> look it up every time _check_constraints() is called.
The reason I didn't keep handle here, I thought handle can be stale or
change for PnP device on plug in and out. Is this not true?
> >
> > +};
> > +
> > +static struct lpi_constraints *lpi_constraints_table;
> > +static int lpi_constraints_table_size;
> > +
> > +static void lpi_device_get_constraints(void)
> > +{
> > + union acpi_object *out_obj;
> > + int i;
> > +
> > + out_obj = acpi_evaluate_dsm_typed(lps0_device_handle,
> > &lps0_dsm_guid,
> > + 1,
> > ACPI_LPS0_GET_DEVICE_CONSTRAINTS,
> > + NULL,
> > ACPI_TYPE_PACKAGE);
> > +
> > + acpi_handle_debug(lps0_device_handle, "_DSM function 1
> > eval %s\n",
> > + out_obj ? "successful" : "failed");
> > +
> > + if (!out_obj)
> > + return;
> > +
> > + lpi_constraints_table = kcalloc(out_obj->package.count,
> > + sizeof(*lpi_constraints_ta
> > ble),
> > + GFP_KERNEL);
> > + if (!lpi_constraints_table)
> > + goto free_acpi_buffer;
> > +
> > + pr_debug("LPI: constraints dump begin\n");
> Please add an empty line after this. Also something like
> "constraints
> list begin" would sound better IMO.
>
OK.
> >
> > + for (i = 0; i < out_obj->package.count; i++) {
> > + union acpi_object *package = &out_obj-
> > >package.elements[i];
> > + struct lpi_device_info info = { };
> > + int package_count = 0, j;
> > +
> > + if (!package)
> > + continue;
> > +
> > + for (j = 0; j < package->package.count; ++j) {
> > + union acpi_object *element =
> > + &(package-
> > >package.elements[j]);
> > +
> > + switch (element->type) {
> > + case ACPI_TYPE_INTEGER:
> > + info.enabled = element-
> > >integer.value;
> > + break;
> > + case ACPI_TYPE_STRING:
> > + info.name = element-
> > >string.pointer;
> > + break;
> > + case ACPI_TYPE_PACKAGE:
> > + package_count = element-
> > >package.count;
> > + info.package = element-
> > >package.elements;
> > + break;
> > + }
> > + }
> > +
> > + if (!info.enabled || !info.package || !info.name)
> > + continue;
> > +
> I would evaluate acpi_get_handle() here and store the handle in the
> constraints table (if persent). And you can skip the entry
> altogether
> if not present, because you won't be printing it anyway.
>
> >
> > + lpi_constraints_table[lpi_constraints_table_size].
> > name =
> > + kstrdup(info.name,
> > GFP_KERNEL);
> > + if
> > (!lpi_constraints_table[lpi_constraints_table_size].name)
> > + goto free_constraints;
> > +
> > + pr_debug("index:%d Name:%s\n", i, info.name);
> > +
> > + for (j = 0; j < package_count; ++j) {
> > + union acpi_object *info_obj =
> > &info.package[j];
> > + union acpi_object *cnstr_pkg;
> > + union acpi_object *obj;
> > + struct lpi_device_constraint dev_info;
> > +
> > + switch (info_obj->type) {
> > + case ACPI_TYPE_INTEGER:
> > + /* version */
> > + break;
> > + case ACPI_TYPE_PACKAGE:
> > + if (info_obj->package.count < 2)
> > + break;
> > +
> > + cnstr_pkg = info_obj-
> > >package.elements;
> > + obj = &cnstr_pkg[0];
> > + dev_info.uid = obj->integer.value;
> > + obj = &cnstr_pkg[1];
> > + dev_info.min_dstate = obj-
> > >integer.value;
> > + pr_debug("uid %d min_dstate %d\n",
> > + dev_info.uid,
> > + dev_info.min_dstate);
> > + lpi_constraints_table[
> > + lpi_constraints_table_size
> > ].min_dstate =
> > + dev_info.min_dstat
> > e;
> > + break;
> > + }
> > + }
> > +
> > + lpi_constraints_table_size++;
> > + }
> > +
> > + pr_debug("LPI: constraints dump end\n");
> > +free_acpi_buffer:
> > + ACPI_FREE(out_obj);
> > + return;
> > +
> > +free_constraints:
> > + ACPI_FREE(out_obj);
> > + for (i = 0; i < lpi_constraints_table_size; ++i)
> > + kfree(lpi_constraints_table[i].name);
> > + kfree(lpi_constraints_table);
> > + lpi_constraints_table_size = 0;
> > +}
> > +
> > +static void lpi_check_constraints(void)
> > +{
> > + int i;
> > +
> > + for (i = 0; i < lpi_constraints_table_size; ++i) {
> > + acpi_handle handle;
> > + struct acpi_device *adev;
> > + int state, ret;
> > +
> > + if (ACPI_FAILURE(acpi_get_handle(NULL,
> > + lpi_constraints_t
> > able[i].name,
> > + &handle)))
> > + continue;
> So if you store the handle, the above won't be necessary.
>
> >
> > +
> > + if (acpi_bus_get_device(handle, &adev))
> > + continue;
> > +
> > + ret = acpi_device_get_power(adev, &state);
> > + if (ret)
> > + pr_debug("LPI: %s required min power state
> > %d, current power state %d, real power state [ERROR]\n",
> > + lpi_constraints_table[i].name,
> > + lpi_constraints_table[i].min_dsta
> > te,
> > + adev->power.state);
> > + else
> > + pr_debug("LPI: %s required min power state
> > %d, current power state %d, real power state %d\n",
> > + lpi_constraints_table[i].name,
> > + lpi_constraints_table[i].min_dsta
> > te,
> > + adev->power.state, state);
> I'm not convinced about the value of the above TBH.
>
> Also in theory _PSC may go and access things like PCI config spaces
> of devices
> which isn't a good idea for devices in D3_cold, so maybe skip this?
OK.
>
> >
> > +
> > + if (adev->flags.power_manageable && adev-
> > >power.state <
> > + lpi_constraints_table[i].m
> > in_dstate)
> > + pr_info("LPI: Constraint [%s] not
> > matched\n",
> "Constrant [%s] not met"?
>
> Also I'd use acpi_handle_info(adev->handle, ...) to print this.
>
> >
> > + lpi_constraints_table[i].name);
> I would print a message if !flags.power_manageable, because it means
> we
> can't get the constraint right in general.
>
> Also I would print both power.state and min_state (possibly using
> acpi_power_state_string()) in this message as that is valuable for
> debugging.
OK.
Thanks,
Srinivas
next prev parent reply other threads:[~2017-08-12 15:59 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-11 18:23 [PATCH v3] ACPI / Sleep: Check low power idle constraints for debug only Srinivas Pandruvada
2017-08-12 14:27 ` Rafael J. Wysocki
2017-08-12 15:59 ` Srinivas Pandruvada [this message]
2017-08-12 22:37 ` Rafael J. Wysocki
2017-08-13 0:00 ` Srinivas Pandruvada
2017-08-13 0:54 ` Rafael J. Wysocki
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1502553556.20268.47.camel@linux.intel.com \
--to=srinivas.pandruvada@linux.intel.com \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=mario.limonciello@dell.com \
--cc=rjw@rjwysocki.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox