From nobody Fri Sep 25 18:21:37 2026 Received: from outbound.st.icloud.com (st-2002k-snip4-1.eps.apple.com [57.103.78.84]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04C3732A3D7 for ; Wed, 9 Sep 2026 16:53:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=57.103.78.84 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788972795; cv=none; b=KHAauJrY00b6OkfvIvu/8FdnDelBrDdCE+DJtvMvU7jI1EKxl054t9qfNs+KyXtQ07i0bjle1dIyId3sbn5K3v9rzyilzjitvXqb9DQ3gs0f5yiXX0/auiZ8LVGAsrpnLPx9VGZNqIAI8e6j6blA6gOpYOW04i9OiObcnhOtajA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788972795; c=relaxed/simple; bh=uv/g6EUW5+U2gpXil3A3lf30+AJKvqs4xHE015zQNhk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hE13oBhGibiewyIA0v4KwLMZgZ9LycU5afSYgKn94xPDppEmwl9dVCwL02QwPy/nkedbLo4+ZyQKOqfS7nQl4MgJnYh1sjKBt2QZ0fhoC9lygSy7pzxGdIl7+d2gnTIAuPlGGdPQzStGwaf+Mow6PSivF2yPDFPggnSPrrhmvzw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com; spf=pass smtp.mailfrom=icloud.com; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b=rf3RBYNP; arc=none smtp.client-ip=57.103.78.84 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=icloud.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b="rf3RBYNP" Received: from outbound.st.icloud.com (unknown [127.0.0.2]) by p00-icloudmta-asmtp-us-east-1a-60-percent-11 (Postfix) with ESMTPS id A9A8E180086C; Wed, 09 Sep 2026 16:53:10 +0000 (UTC) X-ICL-RepId: 01a08716-7351-77d8-b53f-69730d6fbade X-ICL-Out-Info: HUtFAUMEWwJACUgBTUQeDx5WFlZNRAJCTQBOHVUZWQdDF0kFWRcOVk1aFV4MTRFdMFAbXwJCDxwTVhUTC1NWWxNVF0YJGQhdHRkKUFAPS1oVVRcOAkIfUB9MFldDRB8cGVoUXBhTRVEfVFhDGUVWaUELTx1dGVscQmRYVwkKAlEcVg1XQ1QEX1BUEVdQC1kCQg9ICl0OWgRFC00EQwReAEUATx5fGghfHVgCSQJ3AlEcVg1XQ1QEX04ZDEodUlZbE1UXRgk= Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1788972792; x=1791564792; bh=qnVrBJiY48IaSqAOtBEpASh9ORjwYDMwWTdB413PECw=; h=From:To:Subject:Date:Message-ID:MIME-Version:x-icloud-hme; b=rf3RBYNPo+0fABRVB0JjSnpKICZ0HJRL7PnlFz/trj3Jrjxovod/MYxXaQuH6f2yXssSb59h5p2tdY/g4Re6GaR26cCdikd1ZNr9+s0ptGqrgeVy7B2hJ8aKN7MTNZYi5nq2TAoTsqXqhMkAye61Vz9piSfZSa1rWiYwXoli5bXK85efKmKo7gk35ykRnRqc3GSjzZRM+bIJhlSkBFUvT4ldHN6q+augU+85AS1wyEDZmvygv/CLOAIH8MKvi6Ee7frjJP21PYvZz86sxjfdEsgn1gRA8x9bvoU5M4RGkKkA232uZhL5h7KmwfbsY2K7iQgJmzYdRE78AvV76rfGrw== Received: from komputa (unknown [17.156.216.30]) by p00-icloudmta-asmtp-us-east-1a-60-percent-11 (Postfix) with ESMTPSA id 0ABFE1800C34; Wed, 09 Sep 2026 16:53:08 +0000 (UTC) From: Cristian Mazzotta To: aer@tuxedocomputers.com Cc: W_Armin@gmx.de, bentiss@kernel.org, jikos@kernel.org, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, wse@tuxedocomputers.com, Cristian Mazzotta Subject: [PATCH 1/4] HID: lamparray: read attribute reports synchronously Date: Wed, 9 Sep 2026 11:52:54 -0500 Message-ID: <20260909165257.352597-2-cmmazzo@icloud.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909165257.352597-1-cmmazzo@icloud.com> References: <20260909165257.352597-1-cmmazzo@icloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: Cms9kZ3q-3pIhPhEaEG0UmGQBL01n60r X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTA5MDE4OCBTYWx0ZWRfXyVvWoY6L9+Fj 1aeIDldB5vEwP0UMLoklI5jV2C7atb+HdqnOKv32n56aiv4vfz4EnkoO5zr3bayTT/+BfaEy7DE ml1uMlIf6m2OE3i4hPWS55LezkLixwRqOV+Io0ye2sip6FPT/nZvJkd9A/H+t+WCXd6bOqz4W8n DmG4s3eF++JF0njM8UxTutjjm3Z3oz29R4KC9+30BNNnpMqcblxxAt3h21qa0XXgrd4YuWgO7wZ f6Krxsmxukg8ADiKb+XJQn43yom9BFUMkS7k/6L/yuwiPAgpOyKTmI3mWD0UP9qKzE9VjoRffOZ 1HGlBR9Ix3YHwLiqDJ9Zx3GkyU20ksHlhlu4zGluHnDtOdH1qYIUwhMXI0g+8Q= X-Proofpoint-GUID: Cms9kZ3q-3pIhPhEaEG0UmGQBL01n60r X-Authority-Info-Out: v=2.4 cv=Z9bh3XRA c=1 sm=1 tr=0 ts=6aa18ef7 cx=c_apl:c_pps:t_out a=oyWFxbOnq+dmhQrAPgaJYA==:117 a=oyWFxbOnq+dmhQrAPgaJYA==:17 a=VdqzKS8jKosA:10 a=x7bEGLp0ZPQA:10 a=zMoZyIPnO1cA:10 a=VkNPw1HP01LnGYTKEx00:22 a=v3ZZPjhaAAAA:8 a=VAzw7L_s2ESeolZuby8A:9 a=Uh4tPsEYL5Xn7yYgV4Nn:22 a=djM25Df-3sMe0xqo8c8Q:22 X-JNJ: AAAAAAAB1ZBuRfgRtGRBNNKWrtfZ6tF6V6zkz+oqA+qc6/TymMtbkEPLwRqjAxJ5jX2vHNUlz+1t81j7hW9/zGvRITiUPuii0T79keCng2uG5BExvuwYnn1n7DAz280mvBwDuVnVJ1UiMx4hrEPyrn9xDcaHQlPwUCCpV/5hTcxEtbBL7ggFVZ76Qbu44oEEGyoBWMYypkRADLF4QWXPO/hQ58Pk3j98pX4GtB3mLCg2bU6ZYRDe//hwoadLPAo1tdz5jKxZfG+xSgO/h9Uugb0qkCbVU0xW1a+BjbiHfIEWfDgU2EBRJ58eDrxXHU79z+xDgpE5GooITJdU7nZF7dXesHWLqXuDJDDazaaR2usIvTMbeAVP8CnWiXZBAVnRGhv9v4bafjJW3h7dijaVzDo65eQMLuf5vukjsuKZrFrHFxWYMuhnIfhzNXOmm2v2ZTj1uj9gMLCOHg/DDWxi8ZHQpmfSiTh91Rxih6z1eXVi8AlxamgvPJP1r0+1kz43rtqvg/YnCPXHax39PjuuyMs3mD/Za2Q2v4BQZQ7bMNml6eBgbe3dTKZENlhFODCaxtcD24rLFPSPHo78j8QmtTKc2niohuQgyFtmfkBPtgfuLExwo1UzB1Ev7xoLeoB1ccf1Zu6DBMpeMnR/2w9IcICcaEyhBjx1/DABdscUpX3yCZAC3y5XLk9DcJGsrMHvXX5EM/0rQOe5REdJUSGuVwBgBnv28j2NFwDWBnTG1LgAcaRzAnsV7/WuDK9WZOFrpHxBLrRl5dfRbwjB8pOherYDN4MCNnWW7Q== Content-Type: text/plain; charset="utf-8" lamparray_read_attributes_report() and lamparray_get_lamp_attributes() use hid_hw_request(HID_REQ_GET_REPORT) followed by hid_hw_wait(), then read the results out of field->value[]. hid_hw_request() is asynchronous and hid_hw_wait() only clears the output queue, so the values are still read before the transfer has completed. On an Acer Predator PT14-52T (USB keyboard 05AF:767A), this returns zero for LampCount, and then zero for red, green, blue, and intensity counts. The last one is evil: max_brightness is passed to led_mc_calc_color_components() as a divisor during lamparray_register_led(), resulting in a divide by zero during probe: Oops: divide error: 0000 [#1] SMP NOPTI RIP: 0010:led_mc_calc_color_components+0x58/0x70 Call Trace: lamparray_register_led+0x119/0x1e0 lamparray_register+0x502/0x820 hid_generic_probe+0x5e/0xc0 The fault kills the kworker running hub_event() while it holds the USB and HID device locks, which stalls further probing on that bus. Use hid_hw_raw_request() with a hid_report_len()-sized buffer and hand the result to hid_report_raw_event() so the HID core parses it into field->value[] before the values are read. Validate the level counts after reading them and fail with -EINVAL if any is zero, so a device reporting no levels cannot reach led_mc_calc_color_components() at all. The four level fields are also required to share one report, since a single GET_REPORT is used to fetch them. Signed-off-by: Cristian Mazzotta --- drivers/hid/hid-lamparray.c | 73 ++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/drivers/hid/hid-lamparray.c b/drivers/hid/hid-lamparray.c index 9a438aa2d305..f169929aecd6 100644 --- a/drivers/hid/hid-lamparray.c +++ b/drivers/hid/hid-lamparray.c @@ -164,6 +164,9 @@ static int lamparray_read_attributes_report(struct lamp= array_device *ldev) { struct hid_device *hdev =3D ldev->hdev; struct hid_report *report; + int ret; + u8 *buf; + size_t len; =20 if (!ldev->lamp_count.field) { hid_dbg(hdev, "No LampCount field found\n"); @@ -182,25 +185,37 @@ static int lamparray_read_attributes_report(struct la= mparray_device *ldev) return -ENODEV; } =20 + len =3D hid_report_len(report); + buf =3D kmalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + mutex_lock(&ldev->dev_lock); =20 /* Update values */ - hid_hw_request(hdev, report, HID_REQ_GET_REPORT); - hid_hw_wait(hdev); + ret =3D hid_hw_raw_request(hdev, report->id, buf, len, + HID_FEATURE_REPORT, HID_REQ_GET_REPORT); + if (ret < 0) { + hid_dbg(hdev, "Failed to get LampCount value from device: %d\n", ret); + goto out; + } =20 - ldev->lamp_count_value =3D get_field_value(&ldev->lamp_count); + hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, len, ret, 0); =20 - if (ldev->lamp_count_value =3D=3D 0) { - mutex_unlock(&ldev->dev_lock); - hid_dbg(hdev, "LampCount is %d (invalid)\n", ldev->lamp_count_value); - return -EINVAL; + ldev->lamp_count_value =3D get_field_value(&ldev->lamp_count); + if (!ldev->lamp_count_value) { + hid_dbg(hdev, "LampCount is 0 (invalid)\n"); + ret =3D -EINVAL; + goto out; } =20 ldev->lamparray_kind_value =3D get_field_value(&ldev->lamparray_kind); + ret =3D 0; =20 +out: mutex_unlock(&ldev->dev_lock); - - return 0; + kfree(buf); + return ret; } =20 static int lamparray_parse_update_report(struct lamparray_device *ldev) @@ -371,28 +386,58 @@ static int lamparray_get_lamp_attributes(struct lampa= rray_device *ldev) { struct hid_device *hdev =3D ldev->hdev; struct hid_report *report; + int ret; + u8 *buf; + size_t len; =20 if (!lamparray_color_fields_is_complete(&ldev->color_levels)) return -ENODEV; =20 /* - * Get value of any lamp. + * All four fields must share the same report since the + * attributes are fetched with a single GET_REPORT below. */ report =3D ldev->color_levels.red.field->report; + if (!report || + ldev->color_levels.green.field->report !=3D report || + ldev->color_levels.blue.field->report !=3D report || + ldev->color_levels.intensity.field->report !=3D report) + return -ENODEV; + + len =3D hid_report_len(report); + buf =3D kmalloc(len, GFP_KERNEL); + if (!buf) + return -ENOMEM; =20 mutex_lock(&ldev->dev_lock); =20 - hid_hw_request(hdev, report, HID_REQ_GET_REPORT); - hid_hw_wait(hdev); + /* Update values */ + ret =3D hid_hw_raw_request(hdev, report->id, buf, len, + HID_FEATURE_REPORT, HID_REQ_GET_REPORT); + if (ret < 0) { + hid_dbg(hdev, "Failed to read LampAttributesResponseReport: %d\n", ret); + goto out; + } + + hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, len, ret, 0); =20 ldev->max_r =3D get_field_value_as_u8(&ldev->color_levels.red); ldev->max_g =3D get_field_value_as_u8(&ldev->color_levels.green); ldev->max_b =3D get_field_value_as_u8(&ldev->color_levels.blue); ldev->max_brightness =3D get_field_value_as_u8(&ldev->color_levels.intens= ity); =20 - mutex_unlock(&ldev->dev_lock); + if (!ldev->max_r || !ldev->max_g || !ldev->max_b || !ldev->max_brightness= ) { + hid_dbg(hdev, "LampArray device has no color levels\n"); + ret =3D -EINVAL; + goto out; + } =20 - return 0; + ret =3D 0; + +out: + mutex_unlock(&ldev->dev_lock); + kfree(buf); + return ret; } =20 /* Helper functions */ --=20 2.55.0 From nobody Fri Sep 25 18:21:37 2026 Received: from outbound.st.icloud.com (st-2002j-snip4-2.eps.apple.com [57.103.78.75]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6F6D6569F39 for ; Wed, 9 Sep 2026 16:53:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=57.103.78.75 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788972795; cv=none; b=sr729gtH49ds5nIGGV7Bg8XWp6rkE/sA3KhXgaAXYhDvvchpqXV2KZ1QSH9tesZkgAc91gFL+F4AspqolQw5hmpC5jX0y+whqJbQobdS9e8oUjPEnfKadE63KX/kExziyPaVUA6I+vy6j33vQIexD/IkMMdNvhbME7fyqpkLED0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788972795; c=relaxed/simple; bh=0ITZ1ASi0mvOfyjVjAVE4u6M8L3rvcDLINGU1i/Fjbg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AVltlQ1BBFcnDYNHsSbYslhojlmpbziGl1xp5ntfTyWyJpE21yj9iE81OeYEBnlib3PV8OTHAzY1OrHqD8C5d22C/WspTDmIKPhoUNVhSFgeCwa6Z72WnB+p7GcDh55zo/2ZayqoHiPNsvcM1xlXfFOr1WgL1J/sRd8MYa3rSRI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com; spf=pass smtp.mailfrom=icloud.com; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b=PLT2LSbJ; arc=none smtp.client-ip=57.103.78.75 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=icloud.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b="PLT2LSbJ" Received: from outbound.st.icloud.com (unknown [127.0.0.2]) by p00-icloudmta-asmtp-us-east-1a-60-percent-11 (Postfix) with ESMTPS id 797AF1800865; Wed, 09 Sep 2026 16:53:11 +0000 (UTC) X-ICL-RepId: 01a08716-76b4-7790-bec6-8bdbba58e1da X-ICL-Out-Info: HUtFAUMEWwJACUgBTUQeDx5WFlZNRAJCTQBOHVUZWQdDF0kFWRcOVk1aFV4MTRFdMFAbXwJCDxwTVhUTC1NWWxNVF0YJGQhdHRkKUFAPS1oVVRcOAkIfUB9MFldDRB8cGVoUXBhTRVEfVFhDGUVWaUELTx1dGVscQmRYVwkKAlEcVg1XQ1QEX1BUEVdQC1kCQg9ICl0OWgRFC00EQwReAEUATx5eGghfHVgCSQJ3AlEcVg1XQ1QEX04ZDEodUlZbE1UXRgk= Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1788972792; x=1791564792; bh=LlfAGzzk1PxPEr+/sSo/yReT1GRA92Hn+vVgdwb6p+Q=; h=From:To:Subject:Date:Message-ID:MIME-Version:x-icloud-hme; b=PLT2LSbJ2PqHs49WVYZ4GDIN5/AM1w54tscGBH1nntoQI6olsPa37OTnDlJD94yBpWw7NxhwpCOwluGklRUVzL4IB9QqOM8eUMmxDXN9xOL5+krkEbg0HkwnUjReYKJK9gmW87iLh7lBvRr61BvX7DrLzkMvNPodROHgnnKorifaC+MzWnJ7wU9MUvlFtVOnn+zg9PkZqT/H3sypZA86Kvnl6HzdbAdkgA04gEGIfy3D7Xzn3yc4OhdFm7FNFKKyGeqeYhQ5oQFwZIghhAMQflr/3XCyZaFpNA6gc3fQlhY41Mp+z2avd36UC7TWRviHo9D6cka6ZTcgswCb0qZAEA== Received: from komputa (unknown [17.156.216.30]) by p00-icloudmta-asmtp-us-east-1a-60-percent-11 (Postfix) with ESMTPSA id 428121801E94; Wed, 09 Sep 2026 16:53:10 +0000 (UTC) From: Cristian Mazzotta To: aer@tuxedocomputers.com Cc: W_Armin@gmx.de, bentiss@kernel.org, jikos@kernel.org, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, wse@tuxedocomputers.com, Cristian Mazzotta Subject: [PATCH 2/4] HID: lamparray: raise log level of fatal probe errors Date: Wed, 9 Sep 2026 11:52:55 -0500 Message-ID: <20260909165257.352597-3-cmmazzo@icloud.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909165257.352597-1-cmmazzo@icloud.com> References: <20260909165257.352597-1-cmmazzo@icloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: me6n274eeFFweZhdYNSQD1N5c8C_LQqW X-Authority-Info-Out: v=2.4 cv=d5P4CBjE c=1 sm=1 tr=0 ts=6aa18ef7 cx=c_apl:c_pps:t_out a=oyWFxbOnq+dmhQrAPgaJYA==:117 a=oyWFxbOnq+dmhQrAPgaJYA==:17 a=VdqzKS8jKosA:10 a=x7bEGLp0ZPQA:10 a=zMoZyIPnO1cA:10 a=VkNPw1HP01LnGYTKEx00:22 a=v3ZZPjhaAAAA:8 a=MPtH9Rw9gXh03n2V8fYA:9 a=Uh4tPsEYL5Xn7yYgV4Nn:22 a=djM25Df-3sMe0xqo8c8Q:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTA5MDE4OCBTYWx0ZWRfX2j+f8e6pRj63 q6+HCFXZcFr+HkWm+j01Ky7Nk4LO1L120uexgXONsK774jXiIAu4eVPhLMPzSc9Oko1Ye/XdzUj z7K/keaiB0FlRH3tpzPrKqe2QsaHa+u0QK6IgQRiX4vKpkqmqc0MLo4WNjRZW42rB1pafaeBVP0 Ninicl1JGxTYMLixYSoscHuzEaFq1yqCo6lp0Be3M+rWWOJdxworATjtfM2031myQSaXG3dl41r Tr3YSjAqY5jp3kHHt6cVGYpteq3zFCc3MSXX73xLOCpqiBClg3eMShdTd6XWjCZxwPTKPHgg6Vm 8vngycZ2WxAtFdGMiHxON8vy+q/fSyTVa+pzO1nDuVoVj6Y49rGlMs9ssQymw4= X-Proofpoint-GUID: me6n274eeFFweZhdYNSQD1N5c8C_LQqW X-JNJ: AAAAAAAB+4QizMdxTcw3tnHa5YqdAJinsHMPeDRO/MfVgmXWMDIBjwuiQHp2LIFzpIinDTSUBPAJbX/ZiWqtJzfp4yEO5iXBwOyFuiyncODrvhXxO9jityrV1M2mfkk316UBnfslK2s2wiA2iqaJT+fStvd4jTYjwDDGBde+ZrxsXd5G+p2r/krybax9zaxK1OnpvMkddo6FVFCO+DoF//5RRTNsrtCTvgxAuSUGTDvo0jOtuYNuF42nbGHJWcwZlv7/QAadaKE9DQiXPa3Gi/+sMKgUIBWdcRdErJckIB1eBkRbz5Be406kFUnVN1RO9H9vmm8/1fTY5OsY8vsSbYah3mckYoBieRBYOH0dy1nORGhf59vXPw8nRAxqoERXGgp6bueMlgEFYz73XxPmwWzP67WPAm8Uei1qEgMfToOCMFWsomSylwD+3RazZfYij5Xr28lGzbc6E5Ijvt+ZBaCk4zXgM3rZMALeWhx7FKHlRqKGV13+utsD1AKhiJnuuQ1a8NNRSGhNWFqENXpnSxG4BT7/HoJqaWGr4i1CAZfSU0IK18l/lYbmXwz7H1rohPSxwjU7rYWdt88jxLV+dkFXC2o4w7Bwh0W8cPlzzjyDbK6ZVYjDds1UI7wVKYaICQXL2LGV7/sFmsund3S5HSnD3efGebNjAn+NPMdnwNcv28/31NU8Z8T0FAlJZ+jwAh7t6UpL5xLwJjPkZ7n17a64bUVuW4ASWrOsuzQ12R9lhbMangoIpdzrHc5Rdyqgf96fXhSyVO1TtZizYDzlIZMn89V/X0aslMJuOA== Content-Type: text/plain; charset="utf-8" The failure paths in lamparray_read_attributes_report() and lamparray_get_lamp_attributes() use hid_dbg(), so on a device that cannot be driven the driver declines to register with no output unless dynamic debug is enabled for the module. Use hid_warn() for these, since they leave the device without LED support and the reason is useful to anyone diagnosing why a LampArray device did not appear under /sys/class/leds. Signed-off-by: Cristian Mazzotta --- drivers/hid/hid-lamparray.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-lamparray.c b/drivers/hid/hid-lamparray.c index f169929aecd6..70c596f292a2 100644 --- a/drivers/hid/hid-lamparray.c +++ b/drivers/hid/hid-lamparray.c @@ -169,19 +169,19 @@ static int lamparray_read_attributes_report(struct la= mparray_device *ldev) size_t len; =20 if (!ldev->lamp_count.field) { - hid_dbg(hdev, "No LampCount field found\n"); + hid_warn(hdev, "No LampCount field found\n"); return -ENODEV; } =20 if (!ldev->lamparray_kind.field) { - hid_dbg(hdev, "No LampArrayKind field found\n"); + hid_warn(hdev, "No LampArrayKind field found\n"); return -ENODEV; } =20 report =3D ldev->lamp_count.field->report; =20 if (!report) { - hid_dbg(hdev, "LampCount field has no report\n"); + hid_warn(hdev, "LampCount field has no report\n"); return -ENODEV; } =20 @@ -196,7 +196,7 @@ static int lamparray_read_attributes_report(struct lamp= array_device *ldev) ret =3D hid_hw_raw_request(hdev, report->id, buf, len, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) { - hid_dbg(hdev, "Failed to get LampCount value from device: %d\n", ret); + hid_warn(hdev, "Failed to get LampCount value from device: %d\n", ret); goto out; } =20 @@ -204,7 +204,7 @@ static int lamparray_read_attributes_report(struct lamp= array_device *ldev) =20 ldev->lamp_count_value =3D get_field_value(&ldev->lamp_count); if (!ldev->lamp_count_value) { - hid_dbg(hdev, "LampCount is 0 (invalid)\n"); + hid_warn(hdev, "LampCount is 0 (invalid)\n"); ret =3D -EINVAL; goto out; } @@ -415,7 +415,7 @@ static int lamparray_get_lamp_attributes(struct lamparr= ay_device *ldev) ret =3D hid_hw_raw_request(hdev, report->id, buf, len, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) { - hid_dbg(hdev, "Failed to read LampAttributesResponseReport: %d\n", ret); + hid_warn(hdev, "Failed to read LampAttributesResponseReport: %d\n", ret); goto out; } =20 @@ -427,7 +427,7 @@ static int lamparray_get_lamp_attributes(struct lamparr= ay_device *ldev) ldev->max_brightness =3D get_field_value_as_u8(&ldev->color_levels.intens= ity); =20 if (!ldev->max_r || !ldev->max_g || !ldev->max_b || !ldev->max_brightness= ) { - hid_dbg(hdev, "LampArray device has no color levels\n"); + hid_warn(hdev, "LampArray device has no color levels\n"); ret =3D -EINVAL; goto out; } --=20 2.55.0 From nobody Fri Sep 25 18:21:37 2026 Received: from outbound.st.icloud.com (st-2002g-snip4-10.eps.apple.com [57.103.78.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E2577569F0F for ; Wed, 9 Sep 2026 16:53:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=57.103.78.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788972796; cv=none; b=rqd13xdKIP+ENrdB0m2XQv7KSWXJwtQbHc+VaCLzncw3xTbYflDJMadAtfcBYAqgQAciFW5SaVFDeINwXvJrhLByfr7VNo+fL3qgQo9UtC/9j/oHiw/6Z06dgHp8q90dVbCs5gGZXfSV94mCEPQ1DNfpOHKTE579PnTgYVVTE6E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788972796; c=relaxed/simple; bh=ClxCZ+U5uBVjSXjXT29fkb98pvhYMY8loT5OeY8e7GY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UxwC97bNSdbnw8iuugWB97XoPY9Yn9Bkw9RkuZ8Enwozpux4X5sFVJ60IkMEi5TZZMxjMX1AOhz7ZpR6tCzV0JYHBUgIH/VLY3VVnoCUWVBcL4e1Q3bNGNOpTwpiMK+teH9ZDEMFfJyG0TnCmaotofAkmORVPbUv8eD4HPAO0Ok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com; spf=pass smtp.mailfrom=icloud.com; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b=Rq3KOKPX; arc=none smtp.client-ip=57.103.78.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=icloud.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b="Rq3KOKPX" Received: from outbound.st.icloud.com (unknown [127.0.0.2]) by p00-icloudmta-asmtp-us-east-1a-60-percent-11 (Postfix) with ESMTPS id 79C581800230; Wed, 09 Sep 2026 16:53:12 +0000 (UTC) X-ICL-RepId: 01a08716-7a91-7950-af9b-d9babe76472c X-ICL-Out-Info: HUtFAUMEWwJACUgBTUQeDx5WFlZNRAJCTQBOHVUZWQdDF0kFWRcOVk1aFV4MTRFdMFAbXwJCDxwTVhUTC1NWWxNVF0YJGQhdHRkKUFAPS1oVVRcOAkIfUB9MFldDRB8cGVoUXBhTRVEfVFhDGUVWaUELTx1dGVscQmRYVwkKAlEcVg1XQ1QEX1BUEVdQC1kCQg9ICl0OWgRFC00EQwReAEUATx5ZGghfHVgCSQJ3AlEcVg1XQ1QEX04ZDEodUlZbE1UXRgk= Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1788972793; x=1791564793; bh=V+1PgNjD/RjNsANywNjm7teD8U9b9ihSOKxgbsyAB6I=; h=From:To:Subject:Date:Message-ID:MIME-Version:x-icloud-hme; b=Rq3KOKPXlgU5jAcJnDNKzKNoDw76k39jNzNc/mXJVSfFIvvMuyedO3vHJCzOZfidzysuNZEMkRs3Dr/Rm8rWc3smVCpJla76FhbyQ6vWvR6d0zL1xsJfKk0qy+spQcfbOjph4lTUdvHEskg4tuDY/tP3MF8AlWcmKEgk6ICgYSLONLgWvGa6QH5At3L2QieL2Xgq6/b9GSgLaVhIXdlSud2nyx5WFikduzeV5TeVo/aip6odGE4YDdn0tjpYxGwMxx0l5PTFH3N6siBgdmepr2SkInV6yV4qkVOaHFtiMCPn40Kd+Xc61TiUFbzalkL/x1tR7I3T2/jMX8tYjVnhSg== Received: from komputa (unknown [17.156.216.30]) by p00-icloudmta-asmtp-us-east-1a-60-percent-11 (Postfix) with ESMTPSA id 7AB1B1801E97; Wed, 09 Sep 2026 16:53:11 +0000 (UTC) From: Cristian Mazzotta To: aer@tuxedocomputers.com Cc: W_Armin@gmx.de, bentiss@kernel.org, jikos@kernel.org, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, wse@tuxedocomputers.com, Cristian Mazzotta Subject: [PATCH 3/4] HID: lamparray: transfer control when use_leds_uapi changes Date: Wed, 9 Sep 2026 11:52:56 -0500 Message-ID: <20260909165257.352597-4-cmmazzo@icloud.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909165257.352597-1-cmmazzo@icloud.com> References: <20260909165257.352597-1-cmmazzo@icloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-GUID: kmqvgm5wbnTPgxJ97kpo-lxZeAnMVDKH X-Authority-Info-Out: v=2.4 cv=c9mmgB9l c=1 sm=1 tr=0 ts=6aa18ef8 cx=c_apl:c_pps:t_out a=oyWFxbOnq+dmhQrAPgaJYA==:117 a=oyWFxbOnq+dmhQrAPgaJYA==:17 a=VdqzKS8jKosA:10 a=x7bEGLp0ZPQA:10 a=zMoZyIPnO1cA:10 a=VkNPw1HP01LnGYTKEx00:22 a=v3ZZPjhaAAAA:8 a=AIMLDBJ1DqCETsLGAtUA:9 a=Uh4tPsEYL5Xn7yYgV4Nn:22 a=djM25Df-3sMe0xqo8c8Q:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTA5MDE4OCBTYWx0ZWRfX8B+tqO8YtYSm ovPQB3OQge3+fQIM7NmAQV/q0pVY2iafLcLxgyIqFK9L5/DP3h9jfAc/WVh7mCmfq2OiJMiMqAd EqEzNPMOn2LXAHPeN4f88LvYFM1uCLF4BN0Ud0cpqMhEXbNoaBMOF2wwomT2qNlRDOxwlYAp3Kx 43MlLKUf5MmIbgdNKlfwOyT6OY1RikD/39w6jSR1EKMz/CCbuH/ZndMITvZd4QIxKbeB/NxaxC/ y8fWShAfk/c2qYxk8NgzEBGxBv0rfup4kz+nGiA6RtY2BjsYJKaUbW8AJmOm8D39caSfh/8cbBK 6QHi8gWbWr4l5HUga4dfZ58Rpiua+Tkk7ygu6IYuux4i8uaIs5OrIJ8H3eKYtQ= X-Proofpoint-ORIG-GUID: kmqvgm5wbnTPgxJ97kpo-lxZeAnMVDKH X-JNJ: AAAAAAABp2YrVvI5J3fKL1i2q2l5GYnNg3tASUjztMli2waEPmHj8UR0tvWMFn8GJdvrNYEmNe0+o2XYtvFiphIL377En+3FWgJgoN3xcPqPp7NRjnrPKivLL2+BBg1vN/PQCgbeQ6JQTofoa2TJMM56MbKACo128uunKSKuZG1Ut74btyjhEl5LEt6pdO7WUYU4dNVsdfwrHEGEM3Hy79zC4auQfhD/NB2ek3XGR/liuylpvgmaX0bRhY/VYNqwU7zqYtmI1w9uy/OzRNiSFR9p+S1aFzmKDnY6JY0Jy1+zDj2XoH6BYnFPS5VvXflZ+s5w6hgSaFc+3CJfaroskxyzc4BKMRd9vwK6VuylJVwCoenM20Mk8lzidCN6UiYAsagWXDjxjCnJiiCRe2g/9h5UJPqHTUXt4Jvij66v0hTCKPFi1fN2c6MDbxtfNwE9+ofx2I8rtKjDoqzNLuI1MW+dmhLL9ur9muwQljxUicLiMhzMYCRD9mgPxVfp+QcRqYrvpGEPgFHTM8++XJiculDgPVHCmn63KNI0z/EuoEai3UbV2q9ZBEadVmo5efOkjKCOrhIDL1wONFx3l+f1trbBvEvGtRG+iq/YlZp2glUzRV0CZMcbfhslwiYtoAlJVtQQzym2t6q6SlJyIRU4u1hbmlqEQ8qgofH2eaCLzDjpSqqNuiuFAX3FVGdtK7BkrswUivvFJ8RniV0nnb57hzp0V4Q/hyXNgQ5VoP3hKuzHYMkk356KLw8ttoJW39WXLmvadUD/lF3nQvxQnY+KpOCgqRc9YWhXqx2Ipg== Content-Type: text/plain; charset="utf-8" Autonomous mode is disabled once in lamparray_register() and never changed again. Writing 0 to use_leds_uapi unregisters the LED class device but leaves the device under host control, and writing 1 re-registers the class device without taking the device back, so lamp updates sent afterwards are ignored. On an Acer Predator PT14-52T (USB keyboard 05AF:767A) the device stays with whatever last drove it: after writing 0, running a userspace tool that sets a hardware effect, then writing 1, the LED class device reports the cached values despite the hardware still running an effect. Reading AutonomousMode back returns the last value written by the host rather than the state the device is actually in, so the driver cannot detect this. Disable autonomous mode before registering the LED class device and re-enable it after unregistering, so control is handed over in both directions. Unregister the class device before handing the hardware back, so userspace cannot write lamp updates to a device that is no longer accepting them. Failure to re-enable autonomous mode on the disable path is logged but not propagated since the class device is already gone and the write has otherwise succeeded. The restore failure path drops back to hid_warn() for the same reason: it is recoverable, and the attribute reverts to its previous value. Signed-off-by: Cristian Mazzotta --- drivers/hid/hid-lamparray.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-lamparray.c b/drivers/hid/hid-lamparray.c index 70c596f292a2..bbde006d119b 100644 --- a/drivers/hid/hid-lamparray.c +++ b/drivers/hid/hid-lamparray.c @@ -659,25 +659,43 @@ static ssize_t use_leds_uapi_store(struct device *dev, ldev->use_leds_uapi =3D val; mutex_unlock(&ldev->dev_lock); =20 + /* + * Take the device out of autonomous mode before exposing the LED + * class device, and hand it back afterwards, so that control is + * transferred in both directions rather than only at probe. + */ if (val =3D=3D 1) { + ret =3D lamparray_hw_set_autonomous(ldev, false); + if (ret) + goto err_revert; ret =3D lamparray_register_led(ldev); if (ret) { - mutex_lock(&ldev->dev_lock); - ldev->use_leds_uapi =3D old_val; - mutex_unlock(&ldev->dev_lock); - return ret; + lamparray_hw_set_autonomous(ldev, true); + goto err_revert; } ret =3D lamparray_restore_state(ldev); if (ret) { - hid_err(ldev->hdev, "Could not restore state: %d\n", ret); - return ret; + hid_warn(ldev->hdev, "Could not restore state: %d\n", ret); + lamparray_unregister_led(ldev); + lamparray_hw_set_autonomous(ldev, true); + goto err_revert; } - } else { lamparray_unregister_led(ldev); + ret =3D lamparray_hw_set_autonomous(ldev, true); + if (ret) { + hid_warn(ldev->hdev, "Could not enable autonomous mode: %d\n", ret); + return count; + } } =20 return count; + +err_revert: + mutex_lock(&ldev->dev_lock); + ldev->use_leds_uapi =3D old_val; + mutex_unlock(&ldev->dev_lock); + return ret; } static DEVICE_ATTR_RW(use_leds_uapi); =20 --=20 2.55.0 From nobody Fri Sep 25 18:21:37 2026 Received: from outbound.st.icloud.com (st-2002j-snip4-10.eps.apple.com [57.103.78.82]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C6FD582BB9 for ; Wed, 9 Sep 2026 16:53:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=57.103.78.82 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788972799; cv=none; b=cjo/xqOxj1C2Y6hbiSdoCi98F8huGD0lA3YW91rOfZA150036aFVQBkwkqGxumVtbMrX4j4rVz5pYvEyiearU6dGiZNGFRogwTkRy9iWRIXcUWUcoj4t09O3g6ckaGyCdq8iUQbpacMe6jVsTRqEWwLlO36xELn6UClgv4kYfuk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788972799; c=relaxed/simple; bh=TH7xiUmPiRN2Ke2LH9Q18r641ZzoWsOEoevLvCJWrWw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ky/bDfPH/To+L/XdCuulGfEG/KrfY5V0DBu6Ho+ZytZ/xe+dN4a4eTSceB6p+ieu7yP9lsMUF85HJtM8CcUI4oIt/4LpALxiCuA8HfzcgPs3D6etWp2j9/VA993p844CEdrbnRxRoq7+6fr0RagxZnJaH4XoPmt48dRxlsEwAG0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com; spf=pass smtp.mailfrom=icloud.com; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b=lg97nVUJ; arc=none smtp.client-ip=57.103.78.82 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=icloud.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=icloud.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=icloud.com header.i=@icloud.com header.b="lg97nVUJ" Received: from outbound.st.icloud.com (unknown [127.0.0.2]) by p00-icloudmta-asmtp-us-east-1a-60-percent-11 (Postfix) with ESMTPS id 6D50B180193A; Wed, 09 Sep 2026 16:53:13 +0000 (UTC) X-ICL-RepId: 01a08716-7e14-70f4-8ead-51da4714811b X-ICL-Out-Info: HUtFAUMEWwJACUgATUQeDx5WFlZNRAJCTQBOHVUZWQdDF0kFWRcOVk1aFV4MTRFdMFAbXwJCDxwTVhUTC1NWWxNVF0YJGQhdHRkKUFAPS1oVVRcOAkIfUB9MFldDRB8cGVoUXBhTRVEfVFhDGUVWaUELTx1dGVscQmRYVwkKAlEcVg1XQ1QEX1BUEVdQC1kCQg9ICl0OWgRFC00EQwReAEUATx5YGghfHVgCSQJ3AlEcVg1XQ1QEX04ZDEodUlZbE1UXRgk= Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=icloud.com; s=1a1hai; t=1788972795; x=1791564795; bh=FV9k8NWb+dh8I3nrEsWiD0bNBM7jwcON6rQ4XazRym4=; h=From:To:Subject:Date:Message-ID:MIME-Version:x-icloud-hme; b=lg97nVUJvkg48regGbqooOsgBppdtdYYj2cpsAJ2NIhxbXPnSkltfn66M5RBi9nrgrPwdTUqydz7sZu2LSMxxoSbZ2dWwiaAowLmzOJ+XiCxkoGQzhZ23sN/lPzPI4+I9zZlcr3hq981eCGwWGChZrngderBzJdt4KzsRhnU5kySI6JKEJigpbjO6IBtwbYn9rE8hwzwEjM9sVJdX6YsYp89T2z5nkl8EqhfsRGY7JbTHLZU/erCxDIGmdV8/BkmcT3SD2s0IqXu7w2G9267pbF0zxQRPNNQ/cIYGBytSFPcpInD9L8DS9c2c9saSt8xLH4iPr/sSpI9h91Pisr+pQ== Received: from komputa (unknown [17.156.216.30]) by p00-icloudmta-asmtp-us-east-1a-60-percent-11 (Postfix) with ESMTPSA id 53D6818000BD; Wed, 09 Sep 2026 16:53:12 +0000 (UTC) From: Cristian Mazzotta To: aer@tuxedocomputers.com Cc: W_Armin@gmx.de, bentiss@kernel.org, jikos@kernel.org, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, wse@tuxedocomputers.com, Cristian Mazzotta Subject: [PATCH 4/4] HID: lamparray: blank lamps across suspend and restore on resume Date: Wed, 9 Sep 2026 11:52:57 -0500 Message-ID: <20260909165257.352597-5-cmmazzo@icloud.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909165257.352597-1-cmmazzo@icloud.com> References: <20260909165257.352597-1-cmmazzo@icloud.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTA5MDE4OCBTYWx0ZWRfX6/o8zzYFgiGw ojEWaaZ+7HWWhLMi5gxq2M62220esYGETSpkwkLSoQRb5EHnvF+pd1kobSYETnH5o0/lvr97TsK vEWzfDwun6WNBvSfqzS+AhcN0v45w38WXtuKlKzOp8AznxmbPtQ0bj5QmCuuy+BJwj19alkAIKq o3MKKYCIiki+ZIS4s5fhkDMqm1O4R9obLzM5WUeCEtxr5tlyRz94FmA87XD2Wf4r00VCkqsGy3g ItliDMdlS7dJKAIW4W/fr+/w5ZkjKbyNOXcdPGOjfaWiv/rXZiC038gXNN4YfC3wFByBkDudkEU JsN4UoVOSOXKh0RgkBD+7bMgEeZ5XWzFWWjfhC2yVKueVqFJtOjLsv/cKrMKBo= X-Proofpoint-GUID: X5w_crjx1FW4-3r6q5OJwPs9w8vCZW7b X-Authority-Info-Out: v=2.4 cv=KrNAGGWN c=1 sm=1 tr=0 ts=6aa18efa cx=c_apl:c_pps:t_out a=oyWFxbOnq+dmhQrAPgaJYA==:117 a=oyWFxbOnq+dmhQrAPgaJYA==:17 a=VdqzKS8jKosA:10 a=x7bEGLp0ZPQA:10 a=zMoZyIPnO1cA:10 a=VkNPw1HP01LnGYTKEx00:22 a=v3ZZPjhaAAAA:8 a=yDUiu3_GAAAA:8 a=9EF4LWCgBoztrZfFWooA:9 a=gafEeHOdjwYkg5oUpzAY:22 a=Uh4tPsEYL5Xn7yYgV4Nn:22 a=djM25Df-3sMe0xqo8c8Q:22 X-Proofpoint-ORIG-GUID: X5w_crjx1FW4-3r6q5OJwPs9w8vCZW7b X-JNJ: AAAAAAABboOgikKWHLMsBtHh+szyrlpvO5Z8rJb46l+uTOS8CYs8LUgogpJFw6bqXwq8AsB8MuabKY0YFf76X4MJrW1KdZDfl7tHJGvFpK4ww6Bbo4fzL2RR/wawGABPWlIjc335ZMPXXVKNhxHAbdY0lPxY4AVsxkBd/Wly4peebCBesqD87XECjSPzOlWfv5ueHf63vORLgcJ4ew61qqe4nvzqKSRZxLn9lQkAbkXOQog/R919v6BXgRxjQoJmskp+7xRGVOtoNU25ng+86cKYI0eMjySIjtrTVST4zoF/7rnJcINHO5FAd/32ZdD53RuXo+4uHB063pNNfpX69yy0sYFNDV2aKYiR+f959oIAcSfB3hHCGWodvhJ4c84oecmobvLN+9Z1mO6a3XhT6xyjpPdIRkR/vOXsDbOyKEAN+3nuXWQYLdqYaPiT4DSj5oKVYIP3vFJsac2K0OaLPFYdRO6t9W5l8snAYsKr7bfAhGwRI60kRPVFcdV9qZXhuoeMf/Rg+e+pEkJjchhGyfFEneYX7Ji+PKaVfwD7XEhUx1MFCMDcXjeWSaI9YTmw9oR86Bch53fAJjPC8Mmh3xSn6bwUPsOaij/C6HoIhgqTPk61jivKR5PV6DlJb3X3chqQCDgK4ngXqLmP1qZnuM3fMuaL1QYxuit30fgmJvPMP8PAaQyuXdBiMGmWyFfjLnfGMK37Gjvj9TXe41/nRvcU3C8NNq/HMqeFgwdnA0Q4kmfRwfaUuVNiWzKIXnhW6hujrYI2TsizgVkSoc86SXqP8M4QJaUvEP2vBsAJf2NnX5xDj+18AhZWvSAzKe/bcJfMUM/Ehg9DcTkpMawibKNn Content-Type: text/plain; charset="utf-8" The helper installs no PM callbacks, so lamps keep their last state across suspend. Firmware is not required to turn them off in low power states, and on devices where it does not, they stay lit for the whole suspend. On an Acer Predator PT14-52T, system power draw during s2idle is 12.35W with the lamps lit and 3.14W with them blanked, measured at the charger. Add lamparray_suspend(), which writes zeroes to the color channels while leaving the cached RGB and brightness untouched, and lamparray_resume(), which restores that cache. Both return early when use_leds_uapi is 0 so a userspace driver keeps full control. hid-generic gains suspend and resume callbacks to drive them, and calls lamparray_resume() from reset_resume as well. Some devices return to firmware control across a hibernate transition while still reporting AutonomousMode =3D 0, and ignore host lamp updates until the value genuinely transitions. Force a 1 -> 0 on resume before restoring state. Signed-off-by: Cristian Mazzotta --- drivers/hid/hid-generic.c | 27 +++++++++++++++++++ drivers/hid/hid-lamparray.c | 51 +++++++++++++++++++++++++++++++++++ include/linux/hid-lamparray.h | 35 ++++++++++++++++++++++++ 3 files changed, 113 insertions(+) diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c index c3d2283198e8..dc1cca45d599 100644 --- a/drivers/hid/hid-generic.c +++ b/drivers/hid/hid-generic.c @@ -99,9 +99,34 @@ static int hid_generic_probe(struct hid_device *hdev, =20 static int hid_generic_reset_resume(struct hid_device *hdev) { + struct lamparray *la =3D hid_get_drvdata(hdev); + if (hdev->claimed & HID_CLAIMED_INPUT) hidinput_reset_resume(hdev); =20 + if (IS_ENABLED(CONFIG_HID_LAMPARRAY) && la) + lamparray_resume(la); + + return 0; +} + +static int hid_generic_suspend(struct hid_device *hdev, pm_message_t messa= ge) +{ + struct lamparray *la =3D hid_get_drvdata(hdev); + + if (IS_ENABLED(CONFIG_HID_LAMPARRAY) && la) + lamparray_suspend(la); + + return 0; +} + +static int hid_generic_resume(struct hid_device *hdev) +{ + struct lamparray *la =3D hid_get_drvdata(hdev); + + if (IS_ENABLED(CONFIG_HID_LAMPARRAY) && la) + lamparray_resume(la); + return 0; } =20 @@ -127,6 +152,8 @@ static struct hid_driver hid_generic =3D { .match =3D hid_generic_match, .probe =3D hid_generic_probe, .reset_resume =3D hid_generic_reset_resume, + .suspend =3D hid_generic_suspend, + .resume =3D hid_generic_resume, .remove =3D hid_generic_remove, }; module_hid_driver(hid_generic); diff --git a/drivers/hid/hid-lamparray.c b/drivers/hid/hid-lamparray.c index bbde006d119b..dec9d7883887 100644 --- a/drivers/hid/hid-lamparray.c +++ b/drivers/hid/hid-lamparray.c @@ -869,6 +869,57 @@ void lamparray_unregister(struct lamparray *la) } EXPORT_SYMBOL_GPL(lamparray_unregister); =20 +/* + * Blank all lamps on suspend rather than handing control back to the firm= ware, + * which may not turn them off in low power states. On an Acer Predator PT= 14-52T, + * system power draw during s2idle was ~12.35W with lamps lit, and ~2.84W = with + * them blanked; the lighting accounted for ~77% of the power draw during = suspend. + * Since writing zeroes is well defined on all lamparray devices, always d= o it. + * This is ignored if use_leds_uapi is 0; let userspace keep full control. + * + * Lamps are written to without holding the lock because PM will freeze us= erspace + * first, which makes concurrent writes impossible. + */ +int lamparray_suspend(struct lamparray *la) +{ + if (!la) + return 0; + + struct lamparray_device *ldev =3D &la->ldev; + + if (!ldev->use_leds_uapi) + return 0; + + lamparray_hw_set_state(ldev, 0, 0, 0, ldev->last_brightness); + + return 0; +} +EXPORT_SYMBOL_GPL(lamparray_suspend); + +int lamparray_resume(struct lamparray *la) +{ + if (!la) + return 0; + + struct lamparray_device *ldev =3D &la->ldev; + + if (!ldev->use_leds_uapi) + return 0; + + /* + * After a S4 transition, some devices report + * AutonomousMode =3D 0 while still ignoring host lamp updates. + * Writing 0 again does nothing; forcing a 1 -> 0 + * will guarantee the device will update. + */ + lamparray_hw_set_autonomous(ldev, true); + lamparray_hw_set_autonomous(ldev, false); + lamparray_restore_state(ldev); + + return 0; +} +EXPORT_SYMBOL_GPL(lamparray_resume); + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Tim Guttzeit "); MODULE_AUTHOR("Aaron Erhardt "); diff --git a/include/linux/hid-lamparray.h b/include/linux/hid-lamparray.h index a77869728d12..a9f827743baa 100644 --- a/include/linux/hid-lamparray.h +++ b/include/linux/hid-lamparray.h @@ -65,6 +65,31 @@ struct lamparray *lamparray_register(struct hid_device *= hdev, */ void lamparray_unregister(struct lamparray *la); =20 +/** + * lamparray_suspend() - blank all lamps ahead of sleep transition + * @la: LampArray handle returned by lamparray_register() + * + * Writes zeroes to the rgb values only, keeping the brightness, unless the + * use_leds_uapi sysfs attribute is 0, in which case, it will return early + * before writing anything. The cached state is left untouched so + * lamparray_resume() can restore it. + * + * Return: 0 + */ +int lamparray_suspend(struct lamparray *la); + +/** + * lamparray_resume() - restore host control and LampArray state + * @la: LampArray handle returned by lamparray_register() + * + * Disables autonomous mode (in case device returns to firmware control af= ter suspend) + * and restores the cached state of the device. If the use_leds_uapi attri= bute is 0, + * it will return early and prevent any unwanted writing. + * + * Return: 0 + */ +int lamparray_resume(struct lamparray *la); + #else /* !CONFIG_HID_LAMPARRAY */ =20 static inline bool lamparray_is_supported_device(struct hid_device *hdev) @@ -83,6 +108,16 @@ static inline void lamparray_unregister(struct lamparra= y *la) { } =20 +static inline int lamparray_suspend(struct lamparray *la) +{ + return 0; +} + +static inline int lamparray_resume(struct lamparray *la) +{ + return 0; +} + #endif /* CONFIG_HID_LAMPARRAY */ =20 #endif /* _HID_LAMPARRAY_H */ --=20 2.55.0