stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Chris Rorvick <chris@rorvick.com>,
	Paul Bolle <pebolle@tiscali.nl>,
	Luca Coelho <luciano.coelho@intel.com>
Subject: [PATCH 4.4 19/31] iwlwifi: pcie: fix SPLC structure parsing
Date: Thu, 24 Nov 2016 15:55:40 +0100	[thread overview]
Message-ID: <20161124145447.970156533@linuxfoundation.org> (raw)
In-Reply-To: <20161124145446.993225208@linuxfoundation.org>

4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Luca Coelho <luciano.coelho@intel.com>

commit e0d9727c111a5917a1184c71c1a8e6f78c7fc41d upstream.

The SPLC data parsing is too restrictive and was not trying find the
correct element for WiFi.  This causes problems with some BIOSes where
the SPLC method exists, but doesn't have a WiFi entry on the first
element of the list.  The domain type values are also incorrect
according to the specification.

Fix this by complying with the actual specification.

Additionally, replace all occurrences of SPLX to SPLC, since SPLX is
only a structure internal to the ACPI tables, and may not even exist.

Fixes: bcb079a14d75 ("iwlwifi: pcie: retrieve and parse ACPI power limitations")
Reported-by: Chris Rorvick <chris@rorvick.com>
Tested-by: Paul Bolle <pebolle@tiscali.nl>
Tested-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 drivers/net/wireless/iwlwifi/pcie/drv.c |   77 +++++++++++++++++++-------------
 1 file changed, 47 insertions(+), 30 deletions(-)

--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -475,48 +475,64 @@ static const struct pci_device_id iwl_hw
 MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
 
 #ifdef CONFIG_ACPI
-#define SPL_METHOD		"SPLC"
-#define SPL_DOMAINTYPE_MODULE	BIT(0)
-#define SPL_DOMAINTYPE_WIFI	BIT(1)
-#define SPL_DOMAINTYPE_WIGIG	BIT(2)
-#define SPL_DOMAINTYPE_RFEM	BIT(3)
+#define ACPI_SPLC_METHOD	"SPLC"
+#define ACPI_SPLC_DOMAIN_WIFI	(0x07)
 
-static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx)
+static u64 splc_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splc)
 {
-	union acpi_object *limits, *domain_type, *power_limit;
+	union acpi_object *data_pkg, *dflt_pwr_limit;
+	int i;
 
-	if (splx->type != ACPI_TYPE_PACKAGE ||
-	    splx->package.count != 2 ||
-	    splx->package.elements[0].type != ACPI_TYPE_INTEGER ||
-	    splx->package.elements[0].integer.value != 0) {
-		IWL_ERR(trans, "Unsupported splx structure\n");
+	/* We need at least two elements, one for the revision and one
+	 * for the data itself.  Also check that the revision is
+	 * supported (currently only revision 0).
+	*/
+	if (splc->type != ACPI_TYPE_PACKAGE ||
+	    splc->package.count < 2 ||
+	    splc->package.elements[0].type != ACPI_TYPE_INTEGER ||
+	    splc->package.elements[0].integer.value != 0) {
+		IWL_DEBUG_INFO(trans,
+			       "Unsupported structure returned by the SPLC method.  Ignoring.\n");
 		return 0;
 	}
 
-	limits = &splx->package.elements[1];
-	if (limits->type != ACPI_TYPE_PACKAGE ||
-	    limits->package.count < 2 ||
-	    limits->package.elements[0].type != ACPI_TYPE_INTEGER ||
-	    limits->package.elements[1].type != ACPI_TYPE_INTEGER) {
-		IWL_ERR(trans, "Invalid limits element\n");
-		return 0;
+	/* loop through all the packages to find the one for WiFi */
+	for (i = 1; i < splc->package.count; i++) {
+		union acpi_object *domain;
+
+		data_pkg = &splc->package.elements[i];
+
+		/* Skip anything that is not a package with the right
+		 * amount of elements (i.e. at least 2 integers).
+		 */
+		if (data_pkg->type != ACPI_TYPE_PACKAGE ||
+		    data_pkg->package.count < 2 ||
+		    data_pkg->package.elements[0].type != ACPI_TYPE_INTEGER ||
+		    data_pkg->package.elements[1].type != ACPI_TYPE_INTEGER)
+			continue;
+
+		domain = &data_pkg->package.elements[0];
+		if (domain->integer.value == ACPI_SPLC_DOMAIN_WIFI)
+			break;
+
+		data_pkg = NULL;
 	}
 
-	domain_type = &limits->package.elements[0];
-	power_limit = &limits->package.elements[1];
-	if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) {
-		IWL_DEBUG_INFO(trans, "WiFi power is not limited\n");
+	if (!data_pkg) {
+		IWL_DEBUG_INFO(trans,
+			       "No element for the WiFi domain returned by the SPLC method.\n");
 		return 0;
 	}
 
-	return power_limit->integer.value;
+	dflt_pwr_limit = &data_pkg->package.elements[1];
+	return dflt_pwr_limit->integer.value;
 }
 
 static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev)
 {
 	acpi_handle pxsx_handle;
 	acpi_handle handle;
-	struct acpi_buffer splx = {ACPI_ALLOCATE_BUFFER, NULL};
+	struct acpi_buffer splc = {ACPI_ALLOCATE_BUFFER, NULL};
 	acpi_status status;
 
 	pxsx_handle = ACPI_HANDLE(&pdev->dev);
@@ -527,23 +543,24 @@ static void set_dflt_pwr_limit(struct iw
 	}
 
 	/* Get the method's handle */
-	status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle);
+	status = acpi_get_handle(pxsx_handle, (acpi_string)ACPI_SPLC_METHOD,
+				 &handle);
 	if (ACPI_FAILURE(status)) {
-		IWL_DEBUG_INFO(trans, "SPL method not found\n");
+		IWL_DEBUG_INFO(trans, "SPLC method not found\n");
 		return;
 	}
 
 	/* Call SPLC with no arguments */
-	status = acpi_evaluate_object(handle, NULL, NULL, &splx);
+	status = acpi_evaluate_object(handle, NULL, NULL, &splc);
 	if (ACPI_FAILURE(status)) {
 		IWL_ERR(trans, "SPLC invocation failed (0x%x)\n", status);
 		return;
 	}
 
-	trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer);
+	trans->dflt_pwr_limit = splc_get_pwr_limit(trans, splc.pointer);
 	IWL_DEBUG_INFO(trans, "Default power limit set to %lld\n",
 		       trans->dflt_pwr_limit);
-	kfree(splx.pointer);
+	kfree(splc.pointer);
 }
 
 #else /* CONFIG_ACPI */



  parent reply	other threads:[~2016-11-24 15:04 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20161124145446.993225208@linuxfoundation.org>
2016-11-24 14:55 ` [PATCH 4.4 01/31] x86/cpu/AMD: Fix cpu_llc_id for AMD Fam17h systems Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 04/31] fuse: fix fuse_write_end() if zero bytes were copied Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 05/31] mfd: intel-lpss: Do not put device in reset state on suspend Greg Kroah-Hartman
2016-11-24 15:25   ` Shaikh, Azhar
2016-11-24 14:55 ` [PATCH 4.4 06/31] can: bcm: fix warning in bcm_connect/proc_register Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 07/31] i2c: mux: fix up dependencies Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 09/31] scripts/has-stack-protector: add -fno-PIE Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 10/31] x86/kexec: " Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 11/31] kbuild: Steal gccs pie from the very beginning Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 12/31] ext4: sanity check the block and cluster size at mount time Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 15/31] clk: mmp: pxa910: fix return value check in pxa910_clk_init() Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 16/31] clk: mmp: pxa168: fix return value check in pxa168_clk_init() Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 17/31] clk: mmp: mmp2: fix return value check in mmp2_clk_init() Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 18/31] rtc: omap: Fix selecting external osc Greg Kroah-Hartman
2016-11-24 14:55 ` Greg Kroah-Hartman [this message]
2016-11-24 14:55 ` [PATCH 4.4 20/31] mfd: core: Fix device reference leak in mfd_clone_cell Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 21/31] uwb: fix device reference leaks Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 22/31] PM / sleep: fix device reference leak in test_suspend Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 23/31] PM / sleep: dont suspend parent when async child suspend_{noirq, late} fails Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 24/31] IB/mlx4: Check gid_index return value Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 25/31] IB/mlx4: Fix create CQ error flow Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 26/31] IB/mlx5: Use cache line size to select CQE stride Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 27/31] IB/mlx5: Fix fatal error dispatching Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 28/31] IB/core: Avoid unsigned int overflow in sg_alloc_table Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 29/31] IB/uverbs: Fix leak of XRC target QPs Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 30/31] IB/cm: Mark stale CM ids whenever the mad agent was unregistered Greg Kroah-Hartman
2016-11-24 14:55 ` [PATCH 4.4 31/31] netfilter: nft_dynset: fix element timeout for HZ != 1000 Greg Kroah-Hartman
2016-11-24 23:13 ` [PATCH 4.4 00/31] 4.4.35-stable review Guenter Roeck
     [not found] ` <5837c0c8.54161c0a.7b168.f7d1@mx.google.com>
2016-11-25  9:47   ` Greg Kroah-Hartman

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=20161124145447.970156533@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=chris@rorvick.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luciano.coelho@intel.com \
    --cc=pebolle@tiscali.nl \
    --cc=stable@vger.kernel.org \
    /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;
as well as URLs for NNTP newsgroup(s).