From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B0EF9393DF5 for ; Mon, 14 Sep 2026 22:53:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426392; cv=none; b=lBz0gqT3QtkZOKlzjlqi6NqkkDuJuL2ORUZZ9sE9djV97MBhd51OnuhgYtzOmAvQP9k9SN9FBYAyMIx1QSDLtscN2z1mvYk2geKlX3HoMsM0Ufy7weV+rnWgK94rwxXstKqs2srVikKpgyRJAbk949mWQ3246J4plxEfyrsR0EA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426392; c=relaxed/simple; bh=B5NcsJqiM6ca6zoKCCSiRnmiGiK51EUO/f+42QeBqzI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PNKsjMWR+Ap+VsSXwOog+WAF0TOH+2wZSJ17UeW+cm4uGuvZ6AmdNij6/5OussXJyNrY2+iLg5IQG7yRUh6JU0Vwzk03ARMcBWO9GQ9ADPrkY4Z4f//uENmtfn9ysJ8xM18Nrxi1dZxek5f9n9fyAdXKmi9upIjl6FxyrfyMtg0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=fPRZmjAZ; arc=none smtp.client-ip=209.85.215.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="fPRZmjAZ" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-cc147d86bebso420442a12.0 for ; Mon, 14 Sep 2026 15:53:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426390; x=1790031190; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=cket7DPZv1j5YnyOIveBa4NpPNYaScJjvnuFzxjWh88=; b=fPRZmjAZsPsmNpwQY3WlqF6D4LWwNE4X1Z3K4VbTZwv/KOC1Gh2wqMK9IE8jVWZTaV izthCVBd9+kVlO+nuylxmOYUxuZkWX//HIAs/pJpXAXHXy6VnuGJ1MM8i4g+tzrelmv0 2natDsx+Dl2kL8YdNhVmxvGVt8uSHFIgDVT3OPKT2iO15alDvYNhPZSoInE0vG+66V0m lBCIChItBTP4CzfG4mBO87o/3H85VHNjXxkxTnBtpPy1mhxOp1c1hZIzXaC7ACKQGRZt aurg6TgmvfDG7U7z/a5C6Z4qCHCBtbmicep1LOXimuaoCyO9MAoPvFKkNYvhEQO9I9tR rcBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426390; x=1790031190; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=cket7DPZv1j5YnyOIveBa4NpPNYaScJjvnuFzxjWh88=; b=iIKIsCE12Bol/VB5fcrE3kutosToRpQT9bzKeKgzQrd6z+Ij81X1KzQfkpVLam05uY 5MrMsPT2BXWaWB1leQXNOzsFRR88r7EHRnQOHZMHz6s139PQkjGCCdtpJAD+GrUOUhmS yArM7RxQHkdde7SyFS7xTKVEBZlV8u7ScjtMKXn6tUse/nbteASSe9FGx7HgUbO5lJ7g SzM7LQAQh7aH1JHW6hRn99rHjbwGejgp4hTP7m6G4UlqLpG3vtB31BaN9kmKpvFy+s17 95fGIdLh+sNrJOarKVHVqibZK3IoEm1qXCtfqdoxer3LLuNBRRCMm7wqc4swmjjpR9mu JDvg== X-Forwarded-Encrypted: i=1; AKwUvByR5OicpFQfXGmqjIGijhqi97MjvjgRpzvcHOLhaqySF+TPgA3BWAxKTZTe/Kauzmj/G2rJMU91pMAweGE=@vger.kernel.org X-Gm-Message-State: AFuF++m08EHw3FfEmUCRqKpd+ZWq36zYkQBZEE+F6S+iLiKyUEkXh/ii SZUoYp95KeiaV0wxGwvyXfJ+my6pf0dIWGb+nVBYGJn51ofJW4Xkdc3t X-Gm-Gg: AYBFou1VYReeRhiL3uoxpzoFek8946LfTuJwAtpE2T2JInC+5Z4ivdUoDt8C7ExLud5 yiCnKyAoblGA+pZ9dX0GgRaY9hEF5KZljDFxtTob0HR5S/Faz29tGf7JGRmY6huYv6pAXBc+Twy 5cjTrsBE3QHZsvDNAk0Q5Zdphie/AguBiw3RWnxp8H9TEX24k1TgSCtUzCG+R6kLxzyGLi5cAGv 0zbWcN45sdJTkdcehGqGRf8VEJpAjdPz7d7RGxBjVvaS6VDnjVFi5EO4yRJHcyQAtbw9BtCyyg5 UAPZBDXcqUf6ngB8W3jA1ktl42lW+pc8xlUjZEeuOB+DDC4PBNyGzL2/6K/I7Hq6uIllrwo43Kl VATaNZQYksWhi6S+lA4Cjm4gekOI/zqEUu3S6tlkU2enYBLfDjR0POaHTjHSS3lTNzZO6X+ZwOx uGUWuLIWymkAgGsL1ynWIBZNDsQ3p8p1fuRZ9Yu2neR3Vd25U/6vQKaf6YwvUE64OHmB1jko0t3 Zme57gDVujduECM8JuDIup1qXhFIkSd5xEiAE0Aok5w48rYZSaa X-Received: by 2002:a05:6a20:4310:b0:3d3:aed2:6f20 with SMTP id adf61e73a8af0-3db50019fa8mr1791026637.20.1789426389991; Mon, 14 Sep 2026 15:53:09 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:09 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 01/10] HID: hid-lenovo-go-s: Return ret instead of 0 in mcu_property_out() Date: Mon, 14 Sep 2026 15:52:54 -0700 Message-ID: <20260914225303.868569-2-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" Currently mcu_property_out() blanket returns 0, discarding the ret value and any errors with it. Wait completion returns a positive value when it is not timed out, which would error on all successes, so if it is positive return the ret value from the raw event handler. Only if it is 0 set it to -EBUSY, otherwise pass the actual error. Fixes: a23f3497bf208c59ad ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Se= ries HID Driver") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index a72f7f748cb5..68301d4c762a 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -38,6 +38,7 @@ static struct hid_gos_cfg { struct led_classdev *led_cdev; struct hid_device *hdev; struct mutex cfg_mutex; /*ensure single synchronous output report*/ + int cmd_status; u8 gp_auto_sleep_time; u8 gp_dpad_mode; u8 gp_mode; @@ -435,7 +436,9 @@ static int hid_gos_raw_event(struct hid_device *hdev, s= truct hid_report *report, dev_dbg(&hdev->dev, "Rx data as raw input report: [%*ph]\n", GO_S_PACKET_SIZE, data); =20 + drvdata.cmd_status =3D ret; complete(&drvdata.send_cmd_complete); + return ret; } =20 @@ -474,12 +477,10 @@ static int mcu_property_out(struct hid_device *hdev, = u8 command, u8 index, timeout =3D (command =3D=3D GET_PL_TEST) ? 200 : 5; ret =3D wait_for_completion_interruptible_timeout(&drvdata.send_cmd_compl= ete, msecs_to_jiffies(timeout)); - - if (ret =3D=3D 0) /* timeout occurred */ - ret =3D -EBUSY; + ret =3D ret > 0 ? drvdata.cmd_status : ret ?: -EBUSY; =20 reinit_completion(&drvdata.send_cmd_complete); - return 0; + return ret; } =20 static ssize_t gamepad_property_store(struct device *dev, --=20 2.55.0 From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pz2-f12.google.com (mail-pz2-f12.google.com [74.125.228.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B7A93BB9FE for ; Mon, 14 Sep 2026 22:53:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426392; cv=none; b=WVDWPc1+zcwpxUQ2UMLKcTqzNvNiek5XxIYWk7l8de/MyKb1fn+Qu0bLNzluHqT4XqyCdNRs5IcT1L2oHdiNsUJnWZQ24ju0YkoBHjHq1tK5fV++FI43nCokvirRSYr2HDrKDRIAR3Y7TU67IB+JFcN5Dbr5htStExZQgaS8RTs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426392; c=relaxed/simple; bh=sQJ/u2rNyU4WncAchMkJyd33mci0D0EaX8SmWcggEZU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Pu38Uai1EBuxZnZaR4Nc9Y/4T8SX7viq/AlmCH+4cl2JSgL9wSHKLfeIejmplYRMvqBw9i2/WEh3pWO6yyIoGilmZ5LT5+DP9ZeDwpwn9cRpbDbBXPRAtUsul1gAh0NjrSDtoVR8Pz/Wjo007BvCVq5uTD1SXCWS8lAGvOdtYc4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=qt+vZ2ap; arc=none smtp.client-ip=74.125.228.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qt+vZ2ap" Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc4c08393dfso1801587a12.3 for ; Mon, 14 Sep 2026 15:53:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426391; x=1790031191; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=8UwDJJPT/BxnAm3lVbun062kxESY5uvQ+2QAo4pBXeo=; b=qt+vZ2apH6fkvr4RlVP9L2UE0yV9X4g8qRG+Ox8I4T5WkYLisWJAq1rbUBEI76h8db /DbbNVHlFzKmOwl7/9E9yEt9HZMqBWWRVT2kbdbpoPi67SM1Xx/ZB+QIHbmcYUh/L2Y6 ezQ2ImBfYByerusbSz6kUEXsUKk/4IxFr8j4MoTYMhSyLvFhH/D5CW1EoY8fw/5Iu8Uy MPuLxzpVEV+WdGl07W0EvQmVtRxNFDYFBmyfUFWzPfaDkpAbuAIe+xUjwD4ZMXtWa5ZE mioU3rDi50xGe8mNhfAPefbk1lMZ02koX+IcpvsynjU5k1xUjxjOif1anZvMhljpEs5X J4/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426391; x=1790031191; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=8UwDJJPT/BxnAm3lVbun062kxESY5uvQ+2QAo4pBXeo=; b=EtYethjVC2RDT/n5KtlCIkhd4m6k8YKyYmknqOxNJC+YC0LD1ygNWXR5HqZqCJdxqu v6R3Y76460WXV+uVtWNkh0TNtuhQ0Fj3DS15hpqGcK7H+uEhZFh6Ah7Fy7t7FL7iXldk F3ZtrIl81vUT9gMbwiRSqeOCvlBgn338FhQmcvyu1CkNBWLgv4k2DYYiDZB4cY9yDE4V c186LOBwJCMtytQ4pAcb8H8rbEGlvOk2zhGijmHC9eA/RNo7eU593xTJwZoHjALCu1a/ caq9CKkK4ikUYxSHbKW+y7uDGOaO5368yz0/phNtzJY9y8ExtMCKSJ7A2O73A0xWchKf HrbQ== X-Forwarded-Encrypted: i=1; AKwUvBwAOP8h0hlXIExM8BU7USJiK9uSH8k3p2VYVGCjAuuWb0Irnm48gbDVyqSx2+wrqQq3daU3u29B4qofPLU=@vger.kernel.org X-Gm-Message-State: AFuF++lBhUwou6yNE2TiIXIZPuZgMLbqOuZ9e+sl8wd/iiz4Xo1QW2JZ dR59Yia/HcYVs4VC08hdJJ7BeINg/jtFlOIwxr9K2r7YMADvILypC+MK X-Gm-Gg: AYBFou39m5E85fI1pEIsg1+yibwGCFNrRvVXg+3ap64Byo2UStGY1Hsr0hdG6mQF73W EKXl4bh5rspe/KbHKquKa9nCeAGDDt4HGXQUaJ5K46U5eprWrGB9f41t6QzKh+20esfdLTrTKCv SfhU0zmnMz8e3Wz6lNSwE9vwTVQD/ROI2kT8I7mdKTg+S2B/EJ1EHsOUrojRLgR/PIZJwSKbzpe 0xZv8G0+6bAlVGWEHjgeR2fiv2s9cxAKaNwL2dUF9dw0+VwMMv+bX4vB1YBp/LOkCCe1wq6o41T eWR8b1+ZIRvCdmPdwBrKqjqEr1Ncyj9TrSWX7vJwP6x+16wQpaPnOSYZC/FA2PWiuWz6lxRI3yd SYVfHXPqGqbWS9dKdV2cr3MUzQSBTBU0yyxRHNKmLfxivvFMWrx23PzkNw9D+dMqXVGQBwnAE9N yvBd55C0RUs0/46kmfNXRHdSrd0TDvwk1/QAm06RjXaVjgsLPIYzhxqCyUBkdXwSTAiMmbIQGWz 32ZReQlDe+dfPTzKJ3y2SNK+y3V114WWsAI1rZVKUoS9qk+xSLY X-Received: by 2002:a05:6a20:d28b:b0:3d3:ae0f:5269 with SMTP id adf61e73a8af0-3db406d1734mr9636215637.21.1789426390747; Mon, 14 Sep 2026 15:53:10 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:10 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 02/10] HID: hid-lenovo-go-s: Bound stale reply window before reusing send_cmd_complete Date: Mon, 14 Sep 2026 15:52:55 -0700 Message-ID: <20260914225303.868569-3-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" mcu_property_out() reinits send_cmd_complete immediately after a timeout is detected, before the next command that reuses it is sent. If the MCU's reply to the timed-out command arrives after this reinit but before the next command's wait begins, it silently satisfies the next, unrelated command's wait instead of the one it actually answers, handing that caller stale data with no way to detect the mismatch. Track when a command has timed out via cmd_orphaned. Before the next command reuses the completion, wait a bounded 25ms for a stale reply to arrive and be consumed, then unconditionally clear the flag and reinit the completion. This does not fully eliminate the window in which an unrelated reply could still be received, but bounds it to a short interval right before a new command is sent. Behavior matches the solution to the same problem in hid-msi. Fixes: a23f3497bf208c59ad ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Se= ries HID Driver") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index 68301d4c762a..36505d8402ff 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -37,6 +37,7 @@ static struct hid_gos_cfg { struct completion send_cmd_complete; struct led_classdev *led_cdev; struct hid_device *hdev; + bool orphan_ack_pending; struct mutex cfg_mutex; /*ensure single synchronous output report*/ int cmd_status; u8 gp_auto_sleep_time; @@ -454,6 +455,19 @@ static int mcu_property_out(struct hid_device *hdev, u= 8 command, u8 index, return -EINVAL; =20 guard(mutex)(&drvdata.cfg_mutex); + + /* + * A reply to the previous command may still be in flight. Give it a + * short window to arrive and be consumed before this call reinits the + * completion, so a late reply can't be mistaken for this command's. + */ + if (drvdata.orphan_ack_pending) { + wait_for_completion_timeout(&drvdata.send_cmd_complete, msecs_to_jiffies= (25)); + drvdata.orphan_ack_pending =3D false; + drvdata.cmd_status =3D -ETIMEDOUT; + } + reinit_completion(&drvdata.send_cmd_complete); + /* We can't use a devm_alloc reusable buffer without side effects during = suspend */ dmabuf =3D kzalloc(GO_S_PACKET_SIZE, GFP_KERNEL); if (!dmabuf) @@ -479,7 +493,9 @@ static int mcu_property_out(struct hid_device *hdev, u8= command, u8 index, msecs_to_jiffies(timeout)); ret =3D ret > 0 ? drvdata.cmd_status : ret ?: -EBUSY; =20 - reinit_completion(&drvdata.send_cmd_complete); + if (ret) + drvdata.orphan_ack_pending =3D true; + return ret; } =20 --=20 2.55.0 From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pj2-f12.google.com (mail-pj2-f12.google.com [74.125.227.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2F1CA3F65F7 for ; Mon, 14 Sep 2026 22:53:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426393; cv=none; b=QVwkOffkK47J7KVC4mGRgghsg95iwNp53lELa1syA71awPkWOepwHb/Q+cbtfgA9UgsMqwOaLQx5PLDRGnfRlPTlDtsDB4ec7ivWII2lcBkfGfNa+4sVAfNhJ+wkdDVFqJDPRnRR+V+l/bZ7lnjb8eANc9o7NIL+Ofu9Sywkjoo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426393; c=relaxed/simple; bh=ZuOq9RLAaVoK2JQN1iRsIvHe30yGLSunUDOxw5csnQE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GBfYo0dOQw0ydHepsAeUTtTs/qTRNBoiUcP4oqTDkSc6mSdDCT3UJ/PA/ylgifhPPZ3yoEJMu0yD37GkYYWP1FFMK7NhEqZrWeS0CLbW9HpJlIod0AdxWsHzgw1S/L6uFe7BIS3mqsvWAVVDnwN7fR6jUiAaqhSAeJZqIr2M4XA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KOdYmtPr; arc=none smtp.client-ip=74.125.227.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KOdYmtPr" Received: by mail-pj2-f12.google.com with SMTP id d9443c01a7336-2d747ed1368so25043085ad.1 for ; Mon, 14 Sep 2026 15:53:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426391; x=1790031191; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=SXpVCxEknnDOBO2wgTMiDMSPtQ3J/1cRefmdmIu8XSU=; b=KOdYmtPrPd0p5M2Ao1rK3dJUTCUCQv7Ie+HD3s8ML2u9XtrWwSp4kU2LFz2Xd2M86K bnVaW4/8K5J1kLWOT6KFZn8z9FhIfIqHVCWQPDISifiFOxA0A1KRhUv5KJPtUtPcd3dA xRo6zMiVLhKIg8+LrCWhtXVjYHWS8lprCT65JtSq+BrMn1XdWLES1BkoQOh8Znyq11BD eQnnCRpYn+cd64S/ohSj147bWxgNx1J8XydzzHz1Qd4ZxbG1XmQSUIx0fkhJCkimv9UF 7Y0ZLPFfIxSf24DK3xAXqoBPAyV74euO1t239CLMvkAPSwsnU5t75lGZ3fYe1SFmx5Yf qsPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426391; x=1790031191; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=SXpVCxEknnDOBO2wgTMiDMSPtQ3J/1cRefmdmIu8XSU=; b=fDnc30VozKaL2DylwbJpbSJVgXVRLUybwxRP8kLUPKqj+QnJY1HXt64xMOaEUMrm3M +Qj5V/j7YKXGsjMuBl0pB77eYJdSSYwARcT4FIRGvZlhW3p+Viw86zmWzaHkH145N61H iKZkEI9RfX7TbIiEEvfbg9Yi9SBZFq1m+6JX6Q0hnJZDiDicxeWTUc1DjLv3mbPCNseM ZxIE+dQd2K2E9I0famBDBti9pqhtMT/Ko4NwFsRxhjPMTi3ETNvBRJ7WuLFIHwObbZOX TxU4IuNVe+e0uCt9XjegN62h9alb1d9yIoF2PZhBO6atnvGtGmBaMYLz4FY+a/LE95Zi ofLA== X-Forwarded-Encrypted: i=1; AKwUvBy7hDZIGdWWGvYn70iUFZg6FzPuGs7hMCAG9+QQdgYXRd1lznsZM8GYSJGoiklH7ifbV3AEpQ6fMW2UA2k=@vger.kernel.org X-Gm-Message-State: AFuF++k8UQdtCBLKYJtmQRd101zt79c3b3MtshKLRb2mhzpCINjLQVsv T0AkMsL/5X4YxW427DnhV4W1Zokv9B1lAf9oAukwNZVsv9+Kyz8FsmVx X-Gm-Gg: AYBFou2l49qCsXP5LWt6nMcJUOKZKtahsNNI2zi68yFI4tWFtBsAyB2R7Xh+q4PurL3 rcgGnFQ/QSc2xq3hQc/WjWBjEIN1F+FG19xOPAPYQrHEGvWda8hCwQbUabt81pvSK0DI1FwF/QD m/AqMWPy4PxRpYlHWOGnPPWnlM4F1/KWmWzVrQvHNJ5Mki/SGWfO7cAwbRdctWjJHKI3FAnaXHG gxncWLcRIr31a8gOIlEBWBsnUvkl1VPtMs8Zmk2mA7rTAIgl+/LfbEbI/R+MNZHuakVtTaQggq0 VesDedhpcZCsHG52dJHZoRMpZn3SNAJcSwTPtoY1hKWF+VoX7WJo+7nobdi14b80pnlHsMpc1q2 FRuUmCMes6tCZm8govmfgxXSqTmJJn5Wv/SkE/Jq+F/o+HWYyGvgUOMSzL3Vq3k79/gA1uzZ7Nk q8B11mEQzijkShXk0ClRsUZTt3eouP2mcMG/On0jdAUKnKYZAF5hdm2bKYuSstPzpDQ5aFFjj07 0b6TzgVJ2enGtwddmsW8Ej+OpqjFR4USkqAbrRxNDosx9VnwK+Yy8VbsacSB94= X-Received: by 2002:a17:902:d485:b0:2dd:78d1:65c9 with SMTP id d9443c01a7336-2dd78d16661mr9457075ad.19.1789426391520; Mon, 14 Sep 2026 15:53:11 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:11 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 03/10] HID: hid-lenovo-go-s: Prevent deadlock if device removed during setup Date: Mon, 14 Sep 2026 15:52:56 -0700 Message-ID: <20260914225303.868569-4-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" hid_gos_cfg_remove() calls a mutex before canceling delayed work. That delayed work function calls mcu_property_out(), which holds the same mutex. Prevent deadlock my removing the mutex prior to stopping the work. Additionally, since cancel_delayed_work has the potential to re-arm, switch to disable_delayed_work. Fixes: a23f3497bf208c59ad ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Se= ries HID Driver") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index 36505d8402ff..8b16fc7d151e 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -1442,8 +1442,7 @@ static int hid_gos_cfg_probe(struct hid_device *hdev, =20 static void hid_gos_cfg_remove(struct hid_device *hdev) { - guard(mutex)(&drvdata.cfg_mutex); - cancel_delayed_work_sync(&drvdata.gos_cfg_setup); + disable_delayed_work_sync(&drvdata.gos_cfg_setup); sysfs_remove_groups(&hdev->dev.kobj, top_level_attr_groups); hid_hw_close(hdev); hid_hw_stop(hdev); --=20 2.55.0 From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pz2-f43.google.com (mail-pz2-f43.google.com [74.125.228.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2062C3CFF44 for ; Mon, 14 Sep 2026 22:53:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426394; cv=none; b=COVNavfwWZGGsmxlhzh3ax81LNm4RUXR15q8Je3knMCQnB4ODA6AlJQ8JGDe6v3HomZpU5m/bc+FUJVt4LxnKXc0gzqrtT1xSUftZpy8lxf9lZg51aTf/zytHVvVPPJujtf341Ge+s4FFE2riaIssYPFBi65zcgFAGJ9DH7VAWU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426394; c=relaxed/simple; bh=BiHA2LT7VXF4lmqoIJBRziOH8CBF0C2zrU9LI3lG4Ck=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pLEW9zF6/8fEnxFUChOHZGehkh4nwFR8HNbUdbEFmS+trjVwC1jR7+Ia2FcH1MdBdlqRh/y9pUkIGihVucgdmI8lV+zQdB/NM5qkIRJKImfzNj1zqHg5yJlYEMAnruIczNq8gEjTIQ4eDBY0kJa8th4uaeTCsj9TlcJ3cS1JsTk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Du2cWIiF; arc=none smtp.client-ip=74.125.228.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Du2cWIiF" Received: by mail-pz2-f43.google.com with SMTP id 41be03b00d2f7-cc1cea4ae2dso1779582a12.3 for ; Mon, 14 Sep 2026 15:53:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426392; x=1790031192; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=T1HiEFknvKCDeWKiMrML1PicHIEUqaWiAMUs85FKMew=; b=Du2cWIiFsr4HicHADRWDlAtd9D8PjVL9lUtzdW28DrgZabvAPYG42IodBGVI82I7YD 9exlAMfIm1Smf0GskSm13WkEAb5Ztn+2VcexeQJTeD3xbz2yAYjSuPseX6xW2hSMsXLe qONYSKEtvH7ZONJjPtq89+lyKhI3bGfddD+Bb4UQncz/+TlmlApvo9S5pTAuGHXsrVwJ mUSK71amq4K+lxI5C3kep+BQmBzow8h3HeaXQH5o6KwzWO8snT7z7bkbxCha2YmZcP8v MMo9+2A2fevRuxr6dI24aNTwQSdvHsSZTZBqTQo7TVM+X9EicScmv+LdmCBaWmOFjsLW S2vg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426392; x=1790031192; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=T1HiEFknvKCDeWKiMrML1PicHIEUqaWiAMUs85FKMew=; b=fvTyI0dJclDaMVIuHC5xJgcPZ6W2nXcumYq47AuNIzXv4vtAT6Kwl7js06RsNnyUVg pZycmX64ClasG4ui85E5FbGNHd8bzwNSrbxvvj4M1QyTB3e2buxcfGzbv50w1KIZmq1S VogACKhnh8ARWHVsxi/2eqQ3+arGh63bpDmYv5p1m+/DdpAGBChdVrT2TUWcp+8Dfsrn nvU4IP8vA4YNXaCCKTig4go1UvthjuuUN9wDabG1lu+UqOi+QnEHxRl+lZ3WUUAkJJZ6 jp5bm26Rz5lKXnbhR0qC48TIFUzkJjix34dy8dbz1wgwitBraKyyzFkvEgDn/yyLvHrq Ziug== X-Forwarded-Encrypted: i=1; AKwUvByThjacSlJtDrn3xOgd7fCWPFp/5gN9ddkeYrm5mvMPCuSDDnPOiGwS5c0yMqHqb+VKW6dcx/IoLlVyqJ8=@vger.kernel.org X-Gm-Message-State: AFuF++lSMc7mzOz8r7HQVuJ5Q3XypYsRW0XgRfa9Ha69HpBt+60MsrH0 jQpZ3UD+VOCeLgKVsLtHX/mVL2TfKy0NzFcu3HdRLq5ApZWCehyaolFd X-Gm-Gg: AYBFou2KC3npLdWfynyr2sfqLcB4p+UleN9nhufGwQ+7fD7cJf/YmtU2icTghP+iTr/ 3Gs8ugV8ciaZEdqVEub1YDNPhgLZg5GHVPVcZiF3Bjzx0oHXsz9luj00dhW6sAkGApNusGow4bF XAb1jfUVyrUjMUH0wDAmAfSrOVJc41sXJrr5tvux7O/Q4PAbl1IddC0LUh3XHK7B037Fhqm3BN/ t0PzUEpENIzLp+AJ97kiMuBPRUhgHzI371baSdcOmCuayawcLz+LTU3RS1bxK8e6wcW01qHoydL 8KLqf9VJhsOFgS1HpL3ZNGySmg7NZJRAEDbKFOieXc/qHla5ks5Z5jEPAzZGCmM33+WaUKzX5YP KstoqJ2xP0BqatIRMD6+wkLWcWfkEBPz3MdzY/SRsHbeTeMFwu4uxNlwEloPDTqmIIfKQzy5Cmg 25o67JpXaUybZjdWON19r/sywwKnwWT8Xa8fKYdZzBmWlLrHbeeGsT+12pG0n3ugYa0nU0uoT24 P6+JqmlZvmOusbRub0ZTYo6curUw5XESiaYYy5H02lTJO4+6FEg X-Received: by 2002:a05:6a21:b94:b0:3cc:8f53:26c0 with SMTP id adf61e73a8af0-3db405220aemr10555230637.17.1789426392490; Mon, 14 Sep 2026 15:53:12 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:11 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 04/10] HID: hid-lenovo-go-s: Use pm_ptr for reset_resume callback Date: Mon, 14 Sep 2026 15:52:57 -0700 Message-ID: <20260914225303.868569-5-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" Adds missing pm_ptr to the .reset_resume callback for hid-lenovo-go-s Fixes: 3524900cc571bd922a ("HID: hid-lenovo-go-s: restore OS_TYPE after res= ume from s2idle") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index 8b16fc7d151e..b6850cf2c029 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -1556,7 +1556,7 @@ static struct hid_driver hid_lenovo_go_s =3D { .probe =3D hid_gos_probe, .remove =3D hid_gos_remove, .raw_event =3D hid_gos_raw_event, - .reset_resume =3D hid_gos_reset_resume, + .reset_resume =3D pm_ptr(hid_gos_reset_resume), }; module_hid_driver(hid_lenovo_go_s); =20 --=20 2.55.0 From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pj2-f12.google.com (mail-pj2-f12.google.com [74.125.227.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0FCF73EC822 for ; Mon, 14 Sep 2026 22:53:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426395; cv=none; b=Q/d2HvtZpWhHFDvDG2eOoCEZeCYJPZGGOY3iBryt2CCi8d7M+Jb3mP3dQkTCAdNK4+aeE3yU3kSssAYGaAAXuned9ViE2AVUcmbmgZZ0RmLUDZt9tdZvvB2mZMf5s/mDndTwv88FWkq92vDJlQwhsgkMXRQUu3CYQ9IwmXxp+Bc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426395; c=relaxed/simple; bh=v9W246k4i5nC9ZdyWZi1OCDWQVULW5oh4JWWhuxaeuo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P9D7wYiled6QWJ6+w/2I/b8BtuAZEJ6BCn08vgvH5HGuiU1b0C/R1P0N6mviFDWuRyzsAAkQ1TixH8YPwvZNELvISuXRyDutQhaQGo+iAxBEE2NEaWhTS9OPyDWFqW1boOoLeVWouiTXDSmpFeMQMPsjxYX9DpcfvAwB6R3mKTY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dohM/q/L; arc=none smtp.client-ip=74.125.227.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dohM/q/L" Received: by mail-pj2-f12.google.com with SMTP id 98e67ed59e1d1-39dacf053eeso1665294a91.2 for ; Mon, 14 Sep 2026 15:53:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426393; x=1790031193; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BN8kNGGOstdu3D+3MzZhZpT0mSPpKY6fG+DlEioFUuE=; b=dohM/q/LJrug23wvrlKE9g6q5ylcIts8vsVeDy+4lQjcALywDDRVvFZxop2mzLr6vK o6nCS15ea0aMk+8b1ONVpHUFGtT9ef2Pzwr/0te32027H27PXL8j3PERSyY3LJvGgGvJ evAzZWdrGBk/Bp2y5zCeS5RO7T0shNFkoH8/0Rwo+W3rMsfXdSknhKIOulHxp7M4p8sG xh8hdt58+HON/OTWKwtvsRCwEZ+6M34bDA/XWqUlAyteHMTDTQ0XZ9i1T0Eu+s4cP7t4 d0/8/a3K8q83fr0qhRpscYfT7XNaQQYY1GwI7Dzxd7Vo54c3mCvD62E4FGitCAU24jfd aVwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426393; x=1790031193; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=BN8kNGGOstdu3D+3MzZhZpT0mSPpKY6fG+DlEioFUuE=; b=lmqeuqj1dYQ/fJkCAvRULvXUWlNXU7QzVcWsbwAlNzWSLJkRd6fViVB1XPGIXvij0F 2Ddy+UuAeRRgppSjQoK2QwJ9/ldG5oko3Y+X5lY5nOy4lMWvFOcuYvIGt+KUPSSCyTjU hNy9eq/92aCLThliqKeJGNlhasj+I6bBQpm9vf6FIsMd//KMXQMZvvnoSdNuJq6iP7wZ xNXGL0WZjZmDp8ePTd1gBBki8NNoF7FUn19rjyGkB4ikUlOrSlJYYX/gGpCNoVAntxMw Cr6y0OlIgYZqDJXUuxyqKMmUDCWMOmzJ7XpFAgB+Xp+fHG99CwLx7LNrOB9PLRGR5q+H NPpQ== X-Forwarded-Encrypted: i=1; AKwUvBxRF5AIKTRYvM+FirugvS9OKXLfisp0lRqAYA6g34dcbp16jlOPwLHaSXfkfIDBM8TioGai3qL8OhkPuCg=@vger.kernel.org X-Gm-Message-State: AFuF++lthn0v7m//5J8uDZ8N8Rm6Pt7pZxma+Ygm88uRzKNH1dsM7hnZ nP2znh0U4/xak0dx2NyS+VvZiM4SP9NykVddQrFPH8a1Q0/BFRnIGrdW X-Gm-Gg: AYBFou1Rww+6Ftd2Uups6Euy+SW0zQ5WGJS3oBfNSIsG6tgQRRN2/Z66HxeFZEl5vvS 7mOj9sKmKi8sdKYKJIG0rzHdLNb68QmOhZwjGaQhKrWSgRzWjxUrtvHd0ZxTUDK6dqtBZkiPah3 oMxVGJ/Lx9rD+Wkit6Dxq99FpfGvQCL7tnYvNmxT5+aq6EyjlepqLYL6noH8THSfV64ivxeNm8H 7V8gMhWYBuJOSLHf6KjmNUOKlcVCgkqhR2YO2xYs9gJENducau0AWy/8E3bdWHLvEPglBcai3eA QmEsYmWGD4rUjQqHOrBXMWBDSYxeRVbmvnnu/VExAla/lN2sloQmJxjKqYnbGoHcKkbMHCimPQf aCUPevuxy9KQePrh3DEBRVxh69WP1+1F0dtQGgMmaRWH013InQCG+IJUYCwhwUzKglVznr34EEC FVgW3fzhZDHGwlD4dhQ0B8xMULYavihSEN4SUBY0qtkuHZrRuEreMK4JtBzmL4m5xXupRFqGin0 2l2t5QQoZmQFFwhPPebETL0i+s3B5WX6t7z0vnjV7BO+zdoRuCo X-Received: by 2002:a17:90a:1056:b0:39d:ec9a:8f8e with SMTP id 98e67ed59e1d1-39dec9a90b5mr6114824a91.8.1789426393321; Mon, 14 Sep 2026 15:53:13 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:12 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 05/10] HID: hid-lenovo-go-s: Add kobject_uevent notify during reset-resume Date: Mon, 14 Sep 2026 15:52:58 -0700 Message-ID: <20260914225303.868569-6-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" Adds kobject_uevent notification after setting os_mode attribute on resume. Fixes: 3524900cc571bd922a ("HID: hid-lenovo-go-s: restore OS_TYPE after res= ume from s2idle") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index b6850cf2c029..712823e22bea 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -1467,6 +1467,7 @@ static int hid_gos_cfg_reset_resume(struct hid_device= *hdev) if (drvdata.os_mode !=3D os_mode) return -ENODEV; =20 + kobject_uevent(&drvdata.hdev->dev.kobj, KOBJ_CHANGE); return 0; } =20 --=20 2.55.0 From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pj2-f13.google.com (mail-pj2-f13.google.com [74.125.227.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1DFEC42E425 for ; Mon, 14 Sep 2026 22:53:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426404; cv=none; b=IGqTGCTNIpwksKBiVPPlMELJKYmCPVmljiW4Gdlw1wyCdoE7AkXtr2CBPbcjbuS90V5e+Oa1s8E/gLNU01Fd2StcRm/s9H8728nSQcfyARDIocoHKqFNFTZukAyVaFNPE6IIRUuP5mu19xBBa5uLJ+UT7B33BQl6s8o5HxClks4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426404; c=relaxed/simple; bh=dVhByGe/R2Ltv+gLa/s9pmWMXmW9Mf4W3MMuoMAtBuc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pdAI1FesJiAWcQ+y9A3VBNMA4z+M/5iHtXhPiTbxMDrdLZHQphpGJI0CKXtlw/Jn/kPZfZv+yu7UPJ2AeLHo/mmOfwWaNyL+Krzimgmo649lZ0uu8nFMCC8bIU4pMNwyzW+D9y495tPWB9bGlESz5vE+w0bw5XNSQ4MCjc2S7bM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=flKwQxKw; arc=none smtp.client-ip=74.125.227.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="flKwQxKw" Received: by mail-pj2-f13.google.com with SMTP id 98e67ed59e1d1-396ccafb752so2647743a91.0 for ; Mon, 14 Sep 2026 15:53:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426394; x=1790031194; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=x4I3Z8i7r4FjC6E4wBF2wiO14cWOcQrrX+u+7iuw0Ek=; b=flKwQxKwyR9j6vwU7hdegZGYqmXgdHvAnVQIzioAbiq2doeQJuhOmq9nW4lvUXqpAX hxgGBO/WnTvTPmrbF/+wUubEf+0PfO2b2gSe3XwtMfCBS66V07krkJiG/OvJf2KX3PcH /yMHqYd/mtphxDmeZxEfXLfCNYBpnqI3OMHpaNlIUEhAltqzC6QsviMcOVhxY4wf67ev Uqv02UNP8MC9pLHbV41qY9NeGgZbXGnooEBsdtySWJYrQhxgbhOzEnoF7ptOEwwSliYG +5FuColNousJhPVj6Q5j4vLf6C99urO3QxkrBfvAFXjonL2AB6tU8gFeQAJVpqv2jM4x sJCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426394; x=1790031194; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=x4I3Z8i7r4FjC6E4wBF2wiO14cWOcQrrX+u+7iuw0Ek=; b=gvy28RJ70VmWEog1ZyS+cJnv7kyO2eZ2/ohiI4sE+uXC0Jt6+omzt3X4T2SY2RZ+/v 12NveBOG6DFbTKUDHyiZDgPswfw7fobme2AElzRjgWdMZIy8Psao5cr2YDFePLv75bBd vgq7Ffvlna3xobIBX3hKix9MnyC7DcO1FbxeSfIojQEowCF2YpMXGPd7CBDFEgWjLeAy 1JEHN9X3NKriBrNylLOe3Zj1NQPwkuramJPDWJXwnJjSK1U5wOqAzQVKIBp78A5UvWlP +jkyJ5HML+FjMxkR8NeYoN2OfCY2m/3tYhJaAOxOSNrL/WAkPZBHFu0hfeAqeZ/Ffeuk 0gmw== X-Forwarded-Encrypted: i=1; AKwUvBynP/KELK22BgvTX9vYnLughgaSvozADlrdthXkNo7cRmIcJH6H7TJRTBU9k2Y9E1pQdKgpooNb2LZiBnQ=@vger.kernel.org X-Gm-Message-State: AFuF++kagBaMnhIVKIBaM6faJp6ViMddzfgFaxDl773f/THM5hA7jWou y3ZpK548sKIRXgHex8mfiQOCrzY++GQpdlyR+wnBMSSBKlX1alu5CWsd X-Gm-Gg: AYBFou3GdNq4lSbaaMLjl4xDPWBVg84h+nx4fARPrGzsoa7U3acaglLC/Bpktw55kV4 L2cU2WJVhsRw0orEKOFtMJQ1i8wbNRg9SfLxPIysD7KapxvMnarhOskJjZKphWzg49/uNjtFJ3I Xzh7ILlEzJ8xa9W5A1D10RL6+I6x6g8Gm0h6/r3+G42/U/XD+03QthCtILGKU6J9cVaLfvbPuvH YiAWYm8vueKX3YWiBhVzp12LSJGD1+655lZtYlqRCUWD4L74q2r/jAHY+WdZc6ZXu5oY9PQLsVi Zok20qzzQdd6Vqq5zBaY1nXhDpYb/2Ko4nEs+NVVYJ72QE/GFT7qj2R+U/W6It8dKVFpHQ+2xOL gA21RQmZVvZBXqGzZYB+dd/kBd8rs+Pcz5LWvcHXjxvZbWlAzmVQmq50YVyAO3YFrKOkpB+1AoT ALWZmo3afIw4lXiZUlN2OcBE+HQd3nl8fQEyLq043am7YA3ykDEjjtBM11EuhUrxZBe6o0EIt8z nYWMNG+a++HnVpBY7DjKe9DCVFSc/d4deszlM+yZvUx8LssABON X-Received: by 2002:a17:90b:57cb:b0:39d:f130:f8fd with SMTP id 98e67ed59e1d1-39df13108cdmr8639486a91.11.1789426394397; Mon, 14 Sep 2026 15:53:14 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:13 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 06/10] HID: hid-lenovo-go-s: Add suspend function and gate access under bool. Date: Mon, 14 Sep 2026 15:52:59 -0700 Message-ID: <20260914225303.868569-7-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" Currently a device can suspend while delayed work is pending or executing. Cancel delayed work if it was pending and restart it if it hasn't run yet. Gate access to show/store functions behind a bool to prevent access prior to cfg_setup() being completed. Fixes: a23f3497bf208c59ad ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Se= ries HID Driver") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 149 ++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index 712823e22bea..6d98fff6d987 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -39,6 +39,8 @@ static struct hid_gos_cfg { struct hid_device *hdev; bool orphan_ack_pending; struct mutex cfg_mutex; /*ensure single synchronous output report*/ + bool gp_registered; + bool rgb_registered; int cmd_status; u8 gp_auto_sleep_time; u8 gp_dpad_mode; @@ -504,10 +506,22 @@ static ssize_t gamepad_property_store(struct device *= dev, const char *buf, size_t count, enum feature_status_index index) { + bool dev_registered; size_t size =3D 1; u8 val =3D 0; int ret; =20 + /* rgb_enabled is attached to led_classdev, not hid_device */ + if (index =3D=3D FEATURE_RGB_ENABLE) + /* Pairs with smp_store_release from gos_cfg_setup */ + dev_registered =3D smp_load_acquire(&drvdata.rgb_registered); + else + /* Pairs with smp_store_release from gos_cfg_setup */ + dev_registered =3D smp_load_acquire(&drvdata.gp_registered); + + if (!dev_registered) + return -ENODEV; + switch (index) { case FEATURE_GAMEPAD_MODE: ret =3D sysfs_match_string(gamepad_mode_text, buf); @@ -588,9 +602,21 @@ static ssize_t gamepad_property_show(struct device *de= v, struct device_attribute *attr, char *buf, enum feature_status_index index) { + bool dev_registered; ssize_t count =3D 0; u8 i; =20 + /* rgb_enabled is attached to led_classdev, not hid_device */ + if (index =3D=3D FEATURE_RGB_ENABLE) + /* Pairs with smp_store_release from gos_cfg_setup */ + dev_registered =3D smp_load_acquire(&drvdata.rgb_registered); + else + /* Pairs with smp_store_release from gos_cfg_setup */ + dev_registered =3D smp_load_acquire(&drvdata.gp_registered); + + if (!dev_registered) + return -ENODEV; + count =3D mcu_property_out(drvdata.hdev, GET_GAMEPAD_CFG, index, NULL, 0); if (count < 0) return count; @@ -726,10 +752,16 @@ static ssize_t touchpad_property_store(struct device = *dev, const char *buf, size_t count, enum touchpad_config_index index) { + bool gp_registered; size_t size =3D 1; u8 val =3D 0; int ret; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + gp_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (!gp_registered) + return -ENODEV; + switch (index) { case CFG_WINDOWS_MODE: ret =3D sysfs_match_string(touchpad_mode_text, buf); @@ -760,9 +792,15 @@ static ssize_t touchpad_property_show(struct device *d= ev, struct device_attribute *attr, char *buf, enum touchpad_config_index index) { + bool gp_registered; int ret =3D 0; u8 i; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + gp_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (!gp_registered) + return -ENODEV; + ret =3D mcu_property_out(drvdata.hdev, GET_TP_PARAM, index, NULL, 0); if (ret < 0) return ret; @@ -789,9 +827,15 @@ static ssize_t touchpad_property_options(struct device= *dev, char *buf, enum touchpad_config_index index) { + bool gp_registered; size_t count =3D 0; unsigned int i; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + gp_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (!gp_registered) + return -ENODEV; + switch (index) { case CFG_WINDOWS_MODE: case CFG_LINUX_MODE: @@ -814,9 +858,15 @@ static ssize_t test_property_show(struct device *dev, struct device_attribute *attr, char *buf, enum test_command_index index) { + bool gp_registered; size_t count =3D 0; u8 i; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + gp_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (!gp_registered) + return -ENODEV; + switch (index) { case TEST_TP_MFR: i =3D drvdata.tp_manufacturer; @@ -874,9 +924,15 @@ static ssize_t rgb_effect_store(struct device *dev, { struct led_classdev_mc *mc_cdev =3D lcdev_to_mccdev(drvdata.led_cdev); enum rgb_config_index index; + bool rgb_registered; u8 effect; int ret; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!rgb_registered) + return -ENODEV; + ret =3D sysfs_match_string(rgb_effect_text, buf); if (ret < 0) return ret; @@ -901,8 +957,14 @@ static ssize_t rgb_effect_store(struct device *dev, static ssize_t rgb_effect_show(struct device *dev, struct device_attribute *attr, char *buf) { + bool rgb_registered; int ret; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!rgb_registered) + return -ENODEV; + ret =3D rgb_attr_show(); if (ret) return ret; @@ -934,9 +996,15 @@ static ssize_t rgb_speed_store(struct device *dev, { struct led_classdev_mc *mc_cdev =3D lcdev_to_mccdev(drvdata.led_cdev); enum rgb_config_index index; + bool rgb_registered; int val =3D 0; int ret; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!rgb_registered) + return -ENODEV; + ret =3D kstrtoint(buf, 10, &val); if (ret) return ret; @@ -964,8 +1032,14 @@ static ssize_t rgb_speed_store(struct device *dev, static ssize_t rgb_speed_show(struct device *dev, struct device_attribute = *attr, char *buf) { + bool rgb_registered; int ret; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!rgb_registered) + return -ENODEV; + ret =3D rgb_attr_show(); if (ret) return ret; @@ -985,9 +1059,15 @@ static ssize_t rgb_speed_range_show(struct device *de= v, static ssize_t rgb_mode_store(struct device *dev, struct device_attribute = *attr, const char *buf, size_t count) { + bool rgb_registered; int ret; u8 val; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!rgb_registered) + return -ENODEV; + ret =3D sysfs_match_string(rgb_mode_text, buf); if (ret <=3D 0) return ret; @@ -1007,8 +1087,14 @@ static ssize_t rgb_mode_store(struct device *dev, st= ruct device_attribute *attr, static ssize_t rgb_mode_show(struct device *dev, struct device_attribute *= attr, char *buf) { + bool rgb_registered; int ret; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!rgb_registered) + return -ENODEV; + ret =3D rgb_cfg_call(drvdata.hdev, GET_RGB_CFG, LIGHT_MODE_SEL, NULL, 0); if (ret) return ret; @@ -1038,10 +1124,16 @@ static ssize_t rgb_profile_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + bool rgb_registered; size_t size =3D 1; int ret; u8 val; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!rgb_registered) + return -ENODEV; + ret =3D kstrtou8(buf, 10, &val); if (ret < 0) return ret; @@ -1061,8 +1153,14 @@ static ssize_t rgb_profile_store(struct device *dev, static ssize_t rgb_profile_show(struct device *dev, struct device_attribute *attr, char *buf) { + bool rgb_registered; int ret; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!rgb_registered) + return -ENODEV; + ret =3D rgb_cfg_call(drvdata.hdev, GET_RGB_CFG, LIGHT_PROFILE_SEL, NULL, = 0); if (ret) return ret; @@ -1084,8 +1182,14 @@ static void hid_gos_brightness_set(struct led_classd= ev *led_cdev, { struct led_classdev_mc *mc_cdev =3D lcdev_to_mccdev(drvdata.led_cdev); enum rgb_config_index index; + bool rgb_registered; int ret; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!rgb_registered) + return; + if (brightness > led_cdev->max_brightness) { dev_err(led_cdev->dev, "Invalid argument\n"); return; @@ -1392,6 +1496,11 @@ static void cfg_setup(struct work_struct *work) "Failed to retrieve OS Mode: %i\n", ret); return; } + + /* Pairs with smp_load_acquire in attribute show/store functions */ + smp_store_release(&drvdata.gp_registered, true); + /* Pairs with smp_load_acquire in attribute show/store functions */ + smp_store_release(&drvdata.rgb_registered, true); } =20 static int hid_gos_cfg_probe(struct hid_device *hdev, @@ -1451,9 +1560,24 @@ static void hid_gos_cfg_remove(struct hid_device *hd= ev) =20 static int hid_gos_cfg_reset_resume(struct hid_device *hdev) { + bool gp_registered, rgb_registered; u8 os_mode =3D drvdata.os_mode; int ret; =20 + /* Pairs with smp_store_release from gos_cfg_setup */ + gp_registered =3D smp_load_acquire(&drvdata.gp_registered); + /* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!gp_registered || !rgb_registered) { + ret =3D schedule_delayed_work(&drvdata.gos_cfg_setup, msecs_to_jiffies(2= )); + if (!ret) { + dev_err(&hdev->dev, "Failed to schedule startup delayed work\n"); + return -ENODEV; + } + + return 0; + } + ret =3D mcu_property_out(drvdata.hdev, SET_GAMEPAD_CFG, FEATURE_OS_MODE, &os_mode, 1); if (ret < 0) @@ -1542,6 +1666,30 @@ static int hid_gos_reset_resume(struct hid_device *h= dev) return 0; } =20 +static int hid_gos_cfg_suspend(void) +{ + disable_delayed_work_sync(&drvdata.gos_cfg_setup); + + return 0; +} + +static int hid_gos_suspend(struct hid_device *hdev, pm_message_t msg) +{ + int ret; + u8 ep; + + /* Safe assumption. SET_INTERFACE ioctl can't be used while driver is bou= nd */ + ret =3D get_endpoint_address(hdev); + if (ret <=3D 0) + return 0; + + ep =3D ret; + if (ep =3D=3D GO_S_CFG_INTF_IN) + return hid_gos_cfg_suspend(); + + return 0; +} + static const struct hid_device_id hid_gos_devices[] =3D { { HID_USB_DEVICE(USB_VENDOR_ID_QHE, USB_DEVICE_ID_LENOVO_LEGION_GO_S_XINPUT) }, @@ -1558,6 +1706,7 @@ static struct hid_driver hid_lenovo_go_s =3D { .remove =3D hid_gos_remove, .raw_event =3D hid_gos_raw_event, .reset_resume =3D pm_ptr(hid_gos_reset_resume), + .suspend =3D pm_ptr(hid_gos_suspend), }; module_hid_driver(hid_lenovo_go_s); =20 --=20 2.55.0 From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pf1-f181.google.com (mail-pf1-f181.google.com [209.85.210.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05BDF3EEAEA for ; Mon, 14 Sep 2026 22:53:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426400; cv=none; b=d9gp7v9siCDyPL9tQNKzV6Yz3Cek12OWEwMIquYpm/MWF66bhN0U+FA55qxF2Xo4V4WclHYhWG7YaEjOhlk8dOm/yLnjMgR2l5u3axYvq4inwTeOj7q7uK0KHxYon6w+sizE9AbvlXQeNub1tq9/I6uO2iqaTHFYbsCWLSysb1E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426400; c=relaxed/simple; bh=xIajdwp3UXaS5EFZENA7x4jgBGOmg59ClMsUOv8AQMs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZD5bkSwXUvQAH/NXv34UBIIlJo8AydTR9dE0LcJLoYVFrSQJeG5loU78J0vXDj0O+/mhuIOQgDfnIC3giLzBehm6OgKYiJ+qO6Lo/HRqn//hfF4d4+Pz+e/rUw1Td8/mg0zQcrsMUMj00hp/6ab2AamF9ULxF4PWSI0eBy9wDUc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=FLCpnCnA; arc=none smtp.client-ip=209.85.210.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FLCpnCnA" Received: by mail-pf1-f181.google.com with SMTP id d2e1a72fcca58-86959a6f7f6so3110387b3a.2 for ; Mon, 14 Sep 2026 15:53:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426395; x=1790031195; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=4fkv1qRouOwCooBcv9E2ZIq98f5GRAhZGGtxGx4jV5A=; b=FLCpnCnANbRXTJfa/C9vR8x5W6mFDjIU94tHAD1GyfgYxOjHd6QBIW4ZG2y/2AAtYP 5zqlYNRlv1B/Hj/sk6LPJ40FH46FwKnSO3slCpPIrmJtwptZvpEsDV0u7HQ5ly/nCqOD wmRUt380RbdILETUGenksR9kyz+p/hC05AY1Ctfz6deh9F/gC66VLFnfrIKNIeumFsJ3 3bshzR9yYdtICAuD71AXtYAkfrl39ACGhBvmLCrCp13bmA6gMB7SIkMedejZ3O1i5gzj CDb24ZSlQ4i+N3TqFeQD8df2XgxpiV7WYeJMG9LodCSje47ahgK16yNK7ZuPc5FDorqN r+gA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426395; x=1790031195; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=4fkv1qRouOwCooBcv9E2ZIq98f5GRAhZGGtxGx4jV5A=; b=PrN4Clz568gjF/DFFDnMKi3BIPIsvJINqwgeOLI2tfiGGCu/+7S/XVl2jJfpdO0M71 Brmp3SeFgd0hDU3B18tYrfY4TKdar2DixF6J0FY+W0GVouE3FEnwWt0LfkQQ6KhLzRv9 7MuVR+c4oicMJJtf3yHWZ1EyvuBEXObXmtdfS31COHJ2TG50Huo62xDM6PGY1mldgFlC N7Xo9iWYju+WwKrCjajL0BeeQ+obw63dg6UYH1vIzhaKeAcLGM9fFG8bYYNN+G/2T5Jx +QI4UQeMwAKFNx1tK8q9nsM92EzIs4CLqIWMfkfDcIiet+ecNbyqxWX3bkQGAfsXZ8jp gpAg== X-Forwarded-Encrypted: i=1; AKwUvBziLTDGoIcBqRt5VWAFvEn3nRFCH6kzUt+lkk2NU8zACGnXnLBg/Zqht8lohES7mIq9wHp/46kqXwrGlIg=@vger.kernel.org X-Gm-Message-State: AFuF++ku/OvfMZ7w1Xd3DqKVhtB6PPnqZ0KhT3OXi/T+dRBCf8RXMB2H kzIMb/tghXORhIvTsgwaSK4yp4um/bhqlENaPzBLcyfdphRpLiRqWDZdR8sT7w== X-Gm-Gg: AYBFou2AaQMkm9LyEPxZC3PKFiKmsFUu5zHkraCDs+NWla/KRa4mYNuEWL2fbB8TkI9 KuxSAXaLhLw4HGdiIvJ11K548UCG/OA6o/EHFD7tZM3lmr3JuUsrftlhKe0+hw5O0D6s8OLlaii OaBCPx/f/UiCjXHfDYKC+zlwi7rCr9dMIqkWt3OTPco1zz/+KhV0JCa7x3VtCv0dNnrU7Hdq25U YHGkdyYidExCe7mXqlciHf8XE8DpDKvcoP6jPrbzeA+GGuLawz6qhcIuGen7lkBA9239BIdWv8Q S4fIX/p+wG01hvDMMKpMVD0V6XYUKdHNsPMnXLNcTxPv8hUM9mdWX8eKrKCKk2ZWfrqzB1yX2WB ZLLSQDeho+tWAfGnXGGPM4SJuuZngjq7R9gzyZw1hFa4D00SdpturC7ZdMXD7AI3kL54t64JdWd nZ3GWblP+zpauVCTiTJ7M31Qnq81zP6W0W1XdqxV0/W5q5JY56zPW2mzmNpXHW240umIiVzeY2w teAYvsuUpgWXVlJPMuhVt6N25DXb3FTETaaSC+Q1TNCD2/0ZU1+ X-Received: by 2002:a05:6a20:3951:b0:3d3:af85:eb98 with SMTP id adf61e73a8af0-3db40694c9fmr9691158637.26.1789426395459; Mon, 14 Sep 2026 15:53:15 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:15 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 07/10] HID: hid-lenovo-go-s: Move attribute init to after device query Date: Mon, 14 Sep 2026 15:53:00 -0700 Message-ID: <20260914225303.868569-8-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" Currently this driver registers attributes before the MCU is ready to accept commands. This can lead to attribute access that blocks the MCU in some rare cases. Move attribute construction to gos_cfg_setup, after the device has been queried. Gate creation to drvdata.gp_registered and drvdata.rgb_registered so a resume before setup has run doesn't prevent attribute creation or attempt to re-register the same attributes. Fixes: a23f3497bf208c59ad ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Se= ries HID Driver") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 68 +++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index 6d98fff6d987..f1a0bcfcdb71 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -1452,6 +1452,7 @@ static struct led_classdev_mc gos_cdev_rgb =3D { =20 static void cfg_setup(struct work_struct *work) { + bool gp_registered, rgb_registered; int ret; =20 /* MCU */ @@ -1497,10 +1498,53 @@ static void cfg_setup(struct work_struct *work) return; } =20 + /* Pairs with smp_store_release from below */ + gp_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (gp_registered) + goto try_rgb; + + ret =3D sysfs_create_groups(&drvdata.hdev->dev.kobj, top_level_attr_group= s); + if (ret) { + dev_err(&drvdata.hdev->dev, + "Failed to create gamepad configuration attributes: %i\n", ret); + goto try_rgb; + } + /* Pairs with smp_load_acquire in attribute show/store functions */ smp_store_release(&drvdata.gp_registered, true); + gp_registered =3D true; + +try_rgb: + /* Pairs with smp_store_release from below */ + rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (rgb_registered) + goto update_kobjects; + + ret =3D devm_led_classdev_multicolor_register(&drvdata.hdev->dev, &gos_cd= ev_rgb); + if (ret) { + dev_err(&drvdata.hdev->dev, + "Failed to create RGB device: %i\n", ret); + goto update_kobjects; + } + + ret =3D devm_device_add_group(gos_cdev_rgb.led_cdev.dev, &rgb_attr_group); + if (ret) { + dev_err(&drvdata.hdev->dev, + "Failed to create RGB configuration attributes: %i\n", ret); + goto update_kobjects; + } + + drvdata.led_cdev =3D &gos_cdev_rgb.led_cdev; + /* Pairs with smp_load_acquire in attribute show/store functions */ smp_store_release(&drvdata.rgb_registered, true); + rgb_registered =3D true; + +update_kobjects: + if (gp_registered) + kobject_uevent(&drvdata.hdev->dev.kobj, KOBJ_CHANGE); + if (rgb_registered) + kobject_uevent(&drvdata.led_cdev->dev->kobj, KOBJ_CHANGE); } =20 static int hid_gos_cfg_probe(struct hid_device *hdev, @@ -1510,30 +1554,8 @@ static int hid_gos_cfg_probe(struct hid_device *hdev, =20 hid_set_drvdata(hdev, &drvdata); drvdata.hdev =3D hdev; - mutex_init(&drvdata.cfg_mutex); - - ret =3D sysfs_create_groups(&hdev->dev.kobj, top_level_attr_groups); - if (ret) { - dev_err_probe(&hdev->dev, ret, - "Failed to create gamepad configuration attributes\n"); - return ret; - } - - ret =3D devm_led_classdev_multicolor_register(&hdev->dev, &gos_cdev_rgb); - if (ret) { - dev_err_probe(&hdev->dev, ret, "Failed to create RGB device\n"); - return ret; - } - - ret =3D devm_device_add_group(gos_cdev_rgb.led_cdev.dev, &rgb_attr_group); - if (ret) { - dev_err_probe(&hdev->dev, ret, - "Failed to create RGB configuration attributes\n"); - return ret; - } - - drvdata.led_cdev =3D &gos_cdev_rgb.led_cdev; =20 + mutex_init(&drvdata.cfg_mutex); init_completion(&drvdata.send_cmd_complete); =20 /* Executing calls prior to returning from probe will lock the MCU. Sched= ule --=20 2.55.0 From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pz2-f12.google.com (mail-pz2-f12.google.com [74.125.228.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0822429013 for ; Mon, 14 Sep 2026 22:53:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426400; cv=none; b=nvVw3/Rqnbia7rT/ZqPLEldDOREf1Q6SF7UHGUA7v+2i3joou59YvllZ+MLwOoPh2XMTjnlcRiJJhui2Lx0VJnHSltsm9k5MpBto/9J3xa4Fo/6MsYFCP06WgmQqd9MeJSRjVqNRPr1tc8AgKGouvobK7DUN0Z5F19apgOXOX0Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426400; c=relaxed/simple; bh=0jdbcgi1ucObaWyrq260b9mGv8DVXuvEllXpVv7pX28=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZSfNB5ScCUqPq+BwB+RX5Fn7RZGgMNWQbbbedl1gZ8Fvki8bTj0F1GfFBIafiOrHW5DceLo9lKDm8pMYetvGbz9nbMXYFBcwtWNMPaW6buQI0tDqpoBeydw/7MTjU1hmqrII9wdf6WUbK/tbKB5xqhXJsocegvzYppMJ8UnDygg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=mvOA9TOK; arc=none smtp.client-ip=74.125.228.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mvOA9TOK" Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc4c08393b0so1885235a12.0 for ; Mon, 14 Sep 2026 15:53:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426396; x=1790031196; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=nkBmBi2M3bokC0woUyxYsBDQw2qjDISAFTNktCCOhv4=; b=mvOA9TOKWN3eiYeqor4FiDATUPvX0/ncCeigFm4H8jYfCAthYQwQ1ZhYK8M/32UlYz Xf4TzMmVHt/EEolpPmyN2eVM8dfuvTXkYUb5IL8zFQyF61vN2X559SjcnyW5fymO0tYd 8o/q+42chTrVI+Rm1t+V3WRXw1hszJlkYozVhP7VO+Cira3GekGWC4mmz/DIly3MkswX K41QyMPbM8VVQp0yAeN/fqNGj4Ufljd3wx4t14Y+WSHbeiv+XcAc7gKiU0K10kIrVMvG TK4YaoIlhxF9qe9d2ZWwjc0aoOBvcoO8pvoegvHSnQZSZy1//ti607n9T1M2u46DOM2r VlIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426396; x=1790031196; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=nkBmBi2M3bokC0woUyxYsBDQw2qjDISAFTNktCCOhv4=; b=nWAGQJKrxQyMlcSRZu0RkUDkI6Tp6/hWTJLB2CQU22uS/m0aj+T71Euq8NnO/0SsAu Boy40x9dGpo6VpoYRqeYIpGz9P1578vsI4cafaaILwUG9q6izqnAh7T2+b6JU6aagGlB rd9Hjw9yGxPG/MFxouAtBy2oiAk6kqU6jw3/QSN8QEi/L2APXJDpH9tPYRs3mhx3xPZH YKN/KZo4m/pOaFpgffGZ0FpKYxOomnP2zhFEKW8nY8o5tGPLpZv3jOENqozvZfPsVQGz VCkC45NP6TsU6SGJ9GvLS6RY7Azlv46skObhuXstSGKx8icjoqIYAL/pnhzyXVKn4/aP IjPQ== X-Forwarded-Encrypted: i=1; AKwUvByGyroufKLK5DHgSM0ecCVZtUGNGSTHsvDfqtURoOg0Y1++4DHn4iIGjx7dA83715hIZHI43zBkp7J17TQ=@vger.kernel.org X-Gm-Message-State: AFuF++ln/46x87Bq1jEOUK3sURL+/ELAF1euK6+mYJ+Ty94LAhMyCyE8 vpVNHb34m0Pn2FAlaNSFtwYs5fQEbKdXl20LXPCjpxIc7dMTurideV5M X-Gm-Gg: AYBFou1UVT7SQb3k0gcJhCG0BLt296kYOhse/lYqxiaqLy+YDd2T7ttyuQeHv5xH53A /msfHgtwNlzdZgPTD19sOGHaWFE0EggwseHqsFN5b4A4RgS15pvgH/PmrbtmNlb65hgBcNKvzgy 1xeDO1NDA/AryF22n697t7/j+/qRNjYWuX15FlZDeWclLqTBOmu7hGBz8D1rwMVsf8wbOoFLVmM W/yQAQ2fb2ImmecNXjNtoWYaTGPqJV7utxNs+InxU+4fZOJOhC5RT65HR9NZXaR8M1PQmYrlsfV xfEssHOiL1HyLcjRp4LCJSjgyYCV0UYMInNnyzmztTTBMJAl4IdXkmBIfCoykEFMzQsETOPwT0X bKwVVQaGrxHQsWIZFdHlU6PKDBa36PrOJTU1VW4b89DQhOAQDDrAw8OAm49OyzSYJE7PF/qQy7k CUtoi5Qbws/6gOJ32jFFocQuE0zL+bamQ1Gsu5KXzuebAmVbTb6SF1pGdFZjb8F2mlDHj8RExeJ yQLpgDDXai0rVVwO3RNAS8NDdY+3xw+hyXzYLkp3gM/eaGW/ZqF X-Received: by 2002:a05:6a20:72a6:b0:3d3:ae40:51e4 with SMTP id adf61e73a8af0-3db405e637fmr8959185637.24.1789426396151; Mon, 14 Sep 2026 15:53:16 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:15 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 08/10] HID: hid-lenovo-go-s: Reorganize and rename hid_gos_cfg Date: Mon, 14 Sep 2026 15:53:01 -0700 Message-ID: <20260914225303.868569-9-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" Renames hid_gos_cfg struct to gos_cfg_drvdata in preparation for later fixes. This is a prerequisite for later fixes. No functional change intended. Fixes: a23f3497bf208c59ad ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Se= ries HID Driver") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 39 ++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index f1a0bcfcdb71..e5c4104a3adb 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -32,36 +32,41 @@ #define GO_S_CFG_INTF_IN 0x84 #define GO_S_PACKET_SIZE 64 =20 -static struct hid_gos_cfg { - struct delayed_work gos_cfg_setup; +static struct gos_cfg_drvdata { + /* MCU General Variables */ struct completion send_cmd_complete; - struct led_classdev *led_cdev; + struct delayed_work gos_cfg_setup; struct hid_device *hdev; bool orphan_ack_pending; struct mutex cfg_mutex; /*ensure single synchronous output report*/ - bool gp_registered; - bool rgb_registered; int cmd_status; + + /* Gamepad Variables */ u8 gp_auto_sleep_time; - u8 gp_dpad_mode; - u8 gp_mode; - u8 gp_poll_rate; - u8 imu_bypass_en; u8 imu_manufacturer; + bool gp_registered; + u8 tp_windows_mode; + u8 tp_manufacturer; + u8 tp_linux_mode; + u8 imu_bypass_en; u8 imu_sensor_en; + u8 gp_dpad_mode; + u8 gp_poll_rate; u8 mcu_id[12]; u8 mouse_step; + u8 tp_version; + u8 gp_mode; u8 os_mode; - u8 rgb_effect; - u8 rgb_en; - u8 rgb_mode; + u8 tp_en; + + /* RGB Variables */ + struct led_classdev *led_cdev; + bool rgb_registered; u8 rgb_profile; + u8 rgb_effect; u8 rgb_speed; - u8 tp_en; - u8 tp_linux_mode; - u8 tp_windows_mode; - u8 tp_version; - u8 tp_manufacturer; + u8 rgb_mode; + u8 rgb_en; } drvdata; =20 struct gos_cfg_attr { --=20 2.55.0 From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pj2-f13.google.com (mail-pj2-f13.google.com [74.125.227.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 000684252BC for ; Mon, 14 Sep 2026 22:53:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.141 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426408; cv=none; b=IuPNkb+QlHtI0kvqrmEQurDm2jll7mBXz2ZSanHJ0mwOAU2xyXA1+YUnh4IrwqoWoE9Y7C/sPPj5tDL7Mp/BNUYPlOM6N/c1DMwO6VQTn6AYhnLYGndzL1FFMW9rG5Qb0cR3vaC4rznfBtLoaP/s0gTHXKIBh9l4oE/0SPXpms4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426408; c=relaxed/simple; bh=eyt+ppwhkUqrSgeJN9x9DLCKQamEARKPRcmwmhUJpd4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=i4bKHf1cPltxKYRqg9fhJ9BtmBQaOI2aWwUJA/dJaEiggzWuXll3wYPllblXT6h494Ifib8j32dPyGo/l1YqGud9uQaKu4WT7dNJVhMA3QH8N+sA62PRF6K8wskrbl7PQb5dXeGIkKeOUfYbyhIDxFEYYEilbPRp0f3YwYr666M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=DLdj//LK; arc=none smtp.client-ip=74.125.227.141 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DLdj//LK" Received: by mail-pj2-f13.google.com with SMTP id 98e67ed59e1d1-39dacf053eeso1665331a91.2 for ; Mon, 14 Sep 2026 15:53:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426397; x=1790031197; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=35j8vQkkYqsz76V+DGGdzZvbead1bZhTtdILBUHQZCY=; b=DLdj//LKcTKnXKIHAaV4WkjHyDyhd7rdVbWgjYcY7nf5sqxdJJhSLWkwz/o9a2NiOx /9wr8C6Q0OO/mxhhpn8Lic3RC0rZ5h9m0bIGyu/H8yf34lLxtI1J0gbimmNV4RbOXFBA eF2XHs1tod/mBQ/ZvjFk24XAiqCX+Kvp0e2vSoHPnPr9GtW8uMjsOWDPjs0uz4qH1u4e 0AV5OWfVR3tAWqjL0g3Y+wXwGgXSUUqQBPs7W/DWWw0xu7iCS96y+XjZ/PO/qhHa1ml+ xKulXVeIhWowTfU66GIkVeoQajvE/ThbeUYGPtK353n3ZlsnU7yky5I4J+37EfCx7fWd uIUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426397; x=1790031197; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=35j8vQkkYqsz76V+DGGdzZvbead1bZhTtdILBUHQZCY=; b=JiQTHQ1vZjmQgMGiDbUACyMRLnG2FTpXJJWhy5AvIrU/bMlciYt/KwiEFPuoqxyw3E tSERCtw8deSK+V5wOWRocmYgvEfIuYn1qAZSePfnsHVC5Ks8h6eSEKyyyJsmkPAQUSQ8 L7wNBhTd8YrpW6OXGPX6hlgKUoksKd1VrYU7jGO+SJj58I6B3wgna9UWSgKXuJ5gitW3 tTC9Y6l/B9pgoWm1OJlIhGGAe83py9K0lUcVatL49e2aohSkeBPfNIxdp0dr8/9BMv0Z M937dJG9xeR/0SD3Rt3ZeHSDKUCyT4Bk+qYtvr5XGpB7J+tq5yPNTFinhoa85I4Y7UZf B+Bw== X-Forwarded-Encrypted: i=1; AKwUvBx3cohBjE39aTaKNdTj8CiG9+bDrHTKzfvSmxpj44/SU3zSbEvaM369KYr6miv7LoJhsmLYhznb22PiTwU=@vger.kernel.org X-Gm-Message-State: AFuF++kf5OzL7bPT41pLPLMmSekhfQCXyGpcwFXeLBvgGFGi7LToG2cV w6Faqv3wADcBWHL8uQsnJMecO51iSpMzgHyhoguylz9Xl3IpXB5IK7Af X-Gm-Gg: AYBFou23AvkpEfmM8BjlshrUJPEM/wkloJ9NKO2QXqj8wUXOmdEIPm+St/EYs3d6vmT DnA4HuiST+2kIFGYCZzCcM9D9blg2rY1vT46LGP+e3OXIloWwqcO0qHnaq8aEUfUAQK653iEo2Q Fje8kimkKQPQIK9QVUEJRb10VR6MU+NSEtHZrUvuIjy22oflS3fGsySaDa8SltAukS4EI8En6Ia zU55XF4CuNo6BRWI4O5fraq1J3S5/Ogit6weMWfJBy5xzmq+12IBOnbylRoF3m4+CLPT6feb5W7 SUYONWmPvV+x+vJX0R6JaAfzt3VAmSsQtot7bzEWAyHROg21ZhejQ0JqfjxxOrfJPwGDXefPVh/ L6DVmMydd0za26rnC41AAEIxzCJQ8ADYJ/q24t4JAvRxTZBMWbFSponl6383+PWSntDLHZxjXjJ BbFAK8oMzbIWJpX0aGGDROeysKLNGRzNCJgu7FeDyE0docdOUCo1cNUyxe9PkJ6KQQudO5eVfXW 2bvC0aogR+on+4OCiCdsAgeNaGURzxRydlYDRAAo//Bc+eC0FdK08eAWGkOojc= X-Received: by 2002:a17:90b:17c3:b0:39d:eda9:fac2 with SMTP id 98e67ed59e1d1-39dedaa0e10mr8126543a91.18.1789426397299; Mon, 14 Sep 2026 15:53:17 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:16 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 09/10] HID: hid-lenovo-go-s: Move static led_classdev_mc to drvdata struct Date: Mon, 14 Sep 2026 15:53:02 -0700 Message-ID: <20260914225303.868569-10-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" In the next patch I will switch drvdata from static global to a devm_kzalloc struct. In preparation for that, move the led_classdev_mc to be a member of the gos_cfg_drvdata struct. As part of that effort, provide a constant name when accessing it and access the led_classdev through the led_classdev_mc. Fixes: be6d7dbb368ba840d7 ("HID: hid-lenovo-go-s: Add RGB LED control inter= face") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 73 +++++++++++++++++------------------ 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index e5c4104a3adb..c77c297a04cb 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -60,7 +60,7 @@ static struct gos_cfg_drvdata { u8 tp_en; =20 /* RGB Variables */ - struct led_classdev *led_cdev; + struct led_classdev_mc led_mc; bool rgb_registered; u8 rgb_profile; u8 rgb_effect; @@ -347,7 +347,7 @@ static int hid_gos_pl_test_event(struct command_report = *cmd_rep) =20 static int hid_gos_light_event(struct command_report *cmd_rep) { - struct led_classdev_mc *mc_cdev; + struct led_classdev_mc *led_mc; int ret =3D 0; =20 switch (cmd_rep->sub_cmd) { @@ -362,12 +362,12 @@ static int hid_gos_light_event(struct command_report = *cmd_rep) case USR_LIGHT_PROFILE_1: case USR_LIGHT_PROFILE_2: case USR_LIGHT_PROFILE_3: - mc_cdev =3D lcdev_to_mccdev(drvdata.led_cdev); + led_mc =3D &drvdata.led_mc; drvdata.rgb_effect =3D cmd_rep->data[0]; - mc_cdev->subled_info[0].intensity =3D cmd_rep->data[1]; - mc_cdev->subled_info[1].intensity =3D cmd_rep->data[2]; - mc_cdev->subled_info[2].intensity =3D cmd_rep->data[3]; - drvdata.led_cdev->brightness =3D cmd_rep->data[4]; + led_mc->subled_info[0].intensity =3D cmd_rep->data[1]; + led_mc->subled_info[1].intensity =3D cmd_rep->data[2]; + led_mc->subled_info[2].intensity =3D cmd_rep->data[3]; + led_mc->led_cdev.brightness =3D cmd_rep->data[4]; drvdata.rgb_speed =3D cmd_rep->data[5]; ret =3D 0; break; @@ -927,7 +927,7 @@ static ssize_t rgb_effect_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct led_classdev_mc *mc_cdev =3D lcdev_to_mccdev(drvdata.led_cdev); + struct led_classdev_mc *led_mc =3D &drvdata.led_mc; enum rgb_config_index index; bool rgb_registered; u8 effect; @@ -945,10 +945,10 @@ static ssize_t rgb_effect_store(struct device *dev, effect =3D ret; index =3D drvdata.rgb_profile + 2; u8 rgb_profile[6] =3D { effect, - mc_cdev->subled_info[0].intensity, - mc_cdev->subled_info[1].intensity, - mc_cdev->subled_info[2].intensity, - drvdata.led_cdev->brightness, + led_mc->subled_info[0].intensity, + led_mc->subled_info[1].intensity, + led_mc->subled_info[2].intensity, + led_mc->led_cdev.brightness, drvdata.rgb_speed }; =20 ret =3D rgb_cfg_call(drvdata.hdev, SET_RGB_CFG, index, rgb_profile, 6); @@ -999,7 +999,7 @@ static ssize_t rgb_speed_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct led_classdev_mc *mc_cdev =3D lcdev_to_mccdev(drvdata.led_cdev); + struct led_classdev_mc *led_mc =3D &drvdata.led_mc; enum rgb_config_index index; bool rgb_registered; int val =3D 0; @@ -1019,10 +1019,10 @@ static ssize_t rgb_speed_store(struct device *dev, =20 index =3D drvdata.rgb_profile + 2; u8 rgb_profile[6] =3D { drvdata.rgb_effect, - mc_cdev->subled_info[0].intensity, - mc_cdev->subled_info[1].intensity, - mc_cdev->subled_info[2].intensity, - drvdata.led_cdev->brightness, + led_mc->subled_info[0].intensity, + led_mc->subled_info[1].intensity, + led_mc->subled_info[2].intensity, + led_mc->led_cdev.brightness, val }; =20 ret =3D rgb_cfg_call(drvdata.hdev, SET_RGB_CFG, index, rgb_profile, 6); @@ -1185,7 +1185,7 @@ static ssize_t rgb_profile_range_show(struct device *= dev, static void hid_gos_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct led_classdev_mc *mc_cdev =3D lcdev_to_mccdev(drvdata.led_cdev); + struct led_classdev_mc *led_mc =3D &drvdata.led_mc; enum rgb_config_index index; bool rgb_registered; int ret; @@ -1202,9 +1202,9 @@ static void hid_gos_brightness_set(struct led_classde= v *led_cdev, =20 index =3D drvdata.rgb_profile + 2; u8 rgb_profile[6] =3D { drvdata.rgb_effect, - mc_cdev->subled_info[0].intensity, - mc_cdev->subled_info[1].intensity, - mc_cdev->subled_info[2].intensity, + led_mc->subled_info[0].intensity, + led_mc->subled_info[1].intensity, + led_mc->subled_info[2].intensity, brightness, drvdata.rgb_speed }; =20 @@ -1444,17 +1444,6 @@ static struct mc_subled gos_rgb_subled_info[] =3D { }, }; =20 -static struct led_classdev_mc gos_cdev_rgb =3D { - .led_cdev =3D { - .name =3D "go_s:rgb:joystick_rings", - .brightness =3D 0x50, - .max_brightness =3D 0x64, - .brightness_set =3D hid_gos_brightness_set, - }, - .num_colors =3D ARRAY_SIZE(gos_rgb_subled_info), - .subled_info =3D gos_rgb_subled_info, -}; - static void cfg_setup(struct work_struct *work) { bool gp_registered, rgb_registered; @@ -1525,22 +1514,20 @@ static void cfg_setup(struct work_struct *work) if (rgb_registered) goto update_kobjects; =20 - ret =3D devm_led_classdev_multicolor_register(&drvdata.hdev->dev, &gos_cd= ev_rgb); + ret =3D devm_led_classdev_multicolor_register(&drvdata.hdev->dev, &drvdat= a.led_mc); if (ret) { dev_err(&drvdata.hdev->dev, "Failed to create RGB device: %i\n", ret); goto update_kobjects; } =20 - ret =3D devm_device_add_group(gos_cdev_rgb.led_cdev.dev, &rgb_attr_group); + ret =3D devm_device_add_group(drvdata.led_mc.led_cdev.dev, &rgb_attr_grou= p); if (ret) { dev_err(&drvdata.hdev->dev, "Failed to create RGB configuration attributes: %i\n", ret); goto update_kobjects; } =20 - drvdata.led_cdev =3D &gos_cdev_rgb.led_cdev; - /* Pairs with smp_load_acquire in attribute show/store functions */ smp_store_release(&drvdata.rgb_registered, true); rgb_registered =3D true; @@ -1549,7 +1536,7 @@ static void cfg_setup(struct work_struct *work) if (gp_registered) kobject_uevent(&drvdata.hdev->dev.kobj, KOBJ_CHANGE); if (rgb_registered) - kobject_uevent(&drvdata.led_cdev->dev->kobj, KOBJ_CHANGE); + kobject_uevent(&drvdata.led_mc.led_cdev.dev->kobj, KOBJ_CHANGE); } =20 static int hid_gos_cfg_probe(struct hid_device *hdev, @@ -1563,6 +1550,18 @@ static int hid_gos_cfg_probe(struct hid_device *hdev, mutex_init(&drvdata.cfg_mutex); init_completion(&drvdata.send_cmd_complete); =20 + /* Device is hardwired and name is guaranteed to be unique */ + drvdata.led_mc.led_cdev.name =3D "go_s:rgb:joystick_rings"; + drvdata.led_mc.led_cdev.brightness =3D 0x50; + drvdata.led_mc.led_cdev.max_brightness =3D 0x64; + drvdata.led_mc.led_cdev.color =3D LED_COLOR_ID_RGB; + drvdata.led_mc.led_cdev.brightness_set =3D hid_gos_brightness_set; + drvdata.led_mc.num_colors =3D 3; + drvdata.led_mc.subled_info =3D devm_kmemdup(&hdev->dev, gos_rgb_subled_in= fo, + sizeof(gos_rgb_subled_info), GFP_KERNEL); + if (!drvdata.led_mc.subled_info) + return -ENOMEM; + /* Executing calls prior to returning from probe will lock the MCU. Sched= ule * initial data call after probe has completed and MCU can accept calls. */ --=20 2.55.0 From nobody Fri Sep 25 09:19:48 2026 Received: from mail-pg1-f169.google.com (mail-pg1-f169.google.com [209.85.215.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2A31C3FA5CC for ; Mon, 14 Sep 2026 22:53:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426410; cv=none; b=N/myj8x9ijMOfz2Ri1mDx5SvzlWelJ19Pp6rya6p+6DdmaTQ8Xw4x6rljeutSva+WtL8xZE14nNzw+UiID6epfezST6AC8g3R9/KMVZLd0S7iEzRy61iN2bLJpAeBPI9wg5K3reQjJ/jaY/3f026sYFUFp1Svck6rwXQHy3etWI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789426410; c=relaxed/simple; bh=tkIfivyTYoxHKBOzibniPiV2TwcF4fNe4fZKIcg1JC0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y+snhfUDXlOv8ZGFqIi+XxoePldq/PCxhvHw1Ni9LmYjK79UMvXeXC53nmGmKQPb3W4WTb8Q5kKa8HQKpnfWnacRmrmNFhF/rxvH4pfk6ZKmpWajCyj4bPnA6d0/vepn16Y5K86DQcVQWjWizTIQguuy/6LEvKCQL474IXEq0kQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=MFGI/ztE; arc=none smtp.client-ip=209.85.215.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MFGI/ztE" Received: by mail-pg1-f169.google.com with SMTP id 41be03b00d2f7-cc4be0e5351so2694092a12.0 for ; Mon, 14 Sep 2026 15:53:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789426398; x=1790031198; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=3vLjx8LXjFQReo7QQwjhK79a0k/QvCQ2dyWt9mb+auM=; b=MFGI/ztEbRyrbhxV4MSEMrxYo1T2N2lSQsn9XpAayOJJO5CL/dncLuIA6c/h/JAjzH f/g5UxVZr5yYvrys0f5rrzKzTG/aEUtRJM08lwsfBZ6I3YRin3JdmUSpC9IT7q1dFAlJ nvPPCjBaKfmwmGC87zBEsmrD1Tc4l35gA7LeAerPoFQ6yVO2tGL4xAJG/sl8U1OtcgFu vRtC4sF5pG/qOalJc0Ed3/AlsR4gG9zZlXTPoqDUSnotaC/6BM/I8IBWGKHLs8mj2VTC SwOq2OJgdeXzUTCT/3Itv93+C/1FURpOlZa9wLJJWr0RgtGQiuySymIDvBF5vJjETb6O xAMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789426398; x=1790031198; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=3vLjx8LXjFQReo7QQwjhK79a0k/QvCQ2dyWt9mb+auM=; b=T8UdLeY33fFm2dhS629u1YN5Lmawj5EoiG/aJ/gKsO0gmjn08qNDG1DpthNU4rrF3b IV3DNF5IC+JNxoIPrqzHXqp3P3nhqHRqX90PaStY0v6r2fOcGzV0N0fCyVHgfKODRUat Tm4lE+AvbgtuqZ6MFth/RmqWsqjMSYqA3AXIEw5+bfZEmOG4O7iQwG/fVdDkIG5q40iR 2QRWAFLiLuxnMSkqfj0Bif3S57smQG5BjQN4vzxo0p5TTc4UZ/GuivVMQvOts2S81DMa EvsZx/7dN110mX5/EFZtlC/+SilVCV4WMTQ8RGsDs/lSswKKnEiaVWO4DAAEoKpesnkZ ClXw== X-Forwarded-Encrypted: i=1; AKwUvByx9B3Y/bQOoadHQnTaoiTxLPZJwPh4bS1bg+u/bpktPYNhNRT2Lj0e0l6sdYgL6bdCgDUGiibWwD8mKfw=@vger.kernel.org X-Gm-Message-State: AFuF++mGhlGAfYtVCtC9hmdpBCEusL36gZQN/Gn2L4Belz2YudCIlaA9 MsxtIaHjyAThLuds1V+oKxqxKAGkRUQKzEqAhDXlbQZBxxEEp/EUhoxR X-Gm-Gg: AYBFou1rhvmlkYZDu+t9Y4wirBETB9Hxm3NjYZyAWgF2V//Z8py1I5aXVOjNRZTd3r6 rN3KK/ziF4cDeaiSHuoLdSbLqwVhcBMLw/nDK4H9CF4dwA024kcFGu6oQOHVhGDSASmYSjHEbzs 0AXD8Pun5YIFfFwe7bXxqLgQK6I7jNs0Hc1ezUr8NmB3Bhr41QO2ZnzQFb9s8/obVZxkmPr5pG0 RQE0To/AniafRk4Y+4vEI4+U9TdFy+4oR6zNzuyiBWwmqrZpB4wG94bOncphkbLkAGa9NK8Z9rl z2XIDz3/WBMouQANiDkBOvd2Yxmgky1N//QFGvVEO8T/smnL5hvPYXlZlKU9rJGE7agGBvYQMF6 udrBhDcwKOGQlOzN3HVL9Zm/fV/lAGbmEF2IK1V6JTwblO475hcUvwKE41Ls3o15xzuPROA3QWl iwCMWiqKPvoT/KAuF4SqI+Op81EA4HXscI6vtqJimeCcThpsuWMuYYFlEMOxRvbk5uB4ft+39u8 TrwEbmboBgvJnvnhH0PPq3644FNfFOWRE0ytNz/vwnK/DrDZfhN X-Received: by 2002:a05:6a20:7344:b0:3bf:6d96:ac40 with SMTP id adf61e73a8af0-3db40480717mr9677494637.12.1789426398188; Mon, 14 Sep 2026 15:53:18 -0700 (PDT) Received: from lappy (108-228-232-20.lightspeed.sndgca.sbcglobal.net. [108.228.232.20]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33bbeb053a5sm14924296eec.27.2026.09.14.15.53.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2026 15:53:17 -0700 (PDT) From: "Derek J. Clark" To: Jiri Kosina , Benjamin Tissoires Cc: "Pierre-Loup A . Griffais" , "Derek J . Clark" , linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, kernel@lists.opengamingcollective.org, stable@vger.kernel.org Subject: [PATCH 10/10] HID: hid-lenovo-go-s: Use devm_kzalloc for drvdata Date: Mon, 14 Sep 2026 15:53:03 -0700 Message-ID: <20260914225303.868569-11-derekjohn.clark@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260914225303.868569-1-derekjohn.clark@gmail.com> References: <20260914225303.868569-1-derekjohn.clark@gmail.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 Content-Type: text/plain; charset="utf-8" Changes drvdata from static global to devm allocation per device. Fixes: a23f3497bf208c59ad ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Se= ries HID Driver") Cc: stable@vger.kernel.org Signed-off-by: Derek J. Clark --- drivers/hid/hid-lenovo-go-s.c | 501 ++++++++++++++++++++-------------- 1 file changed, 300 insertions(+), 201 deletions(-) diff --git a/drivers/hid/hid-lenovo-go-s.c b/drivers/hid/hid-lenovo-go-s.c index c77c297a04cb..7102786ce124 100644 --- a/drivers/hid/hid-lenovo-go-s.c +++ b/drivers/hid/hid-lenovo-go-s.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,7 @@ #define GO_S_CFG_INTF_IN 0x84 #define GO_S_PACKET_SIZE 64 =20 -static struct gos_cfg_drvdata { +struct gos_cfg_drvdata { /* MCU General Variables */ struct completion send_cmd_complete; struct delayed_work gos_cfg_setup; @@ -67,7 +68,7 @@ static struct gos_cfg_drvdata { u8 rgb_speed; u8 rgb_mode; u8 rgb_en; -} drvdata; +}; =20 struct gos_cfg_attr { u8 index; @@ -243,56 +244,57 @@ static const char *const imu_manufacturer_text[] =3D { [IMU_ST] =3D "ST", }; =20 -static int hid_gos_version_event(u8 *data) +static int hid_gos_version_event(struct gos_cfg_drvdata *drvdata, u8 *data) { struct version_report *ver_rep =3D (struct version_report *)data; =20 - drvdata.hdev->firmware_version =3D get_unaligned_le32(&ver_rep->version); + drvdata->hdev->firmware_version =3D get_unaligned_le32(&ver_rep->version); return 0; } =20 -static int hid_gos_mcu_id_event(struct command_report *cmd_rep) +static int hid_gos_mcu_id_event(struct gos_cfg_drvdata *drvdata, struct co= mmand_report *cmd_rep) { - drvdata.mcu_id[0] =3D cmd_rep->sub_cmd; - memcpy(&drvdata.mcu_id[1], cmd_rep->data, 11); + drvdata->mcu_id[0] =3D cmd_rep->sub_cmd; + memcpy(&drvdata->mcu_id[1], cmd_rep->data, 11); =20 return 0; } =20 -static int hid_gos_gamepad_cfg_event(struct command_report *cmd_rep) +static int hid_gos_gamepad_cfg_event(struct gos_cfg_drvdata *drvdata, + struct command_report *cmd_rep) { int ret =3D 0; =20 switch (cmd_rep->sub_cmd) { case FEATURE_GAMEPAD_MODE: - drvdata.gp_mode =3D cmd_rep->data[0]; + drvdata->gp_mode =3D cmd_rep->data[0]; break; case FEATURE_AUTO_SLEEP_TIME: - drvdata.gp_auto_sleep_time =3D cmd_rep->data[0]; + drvdata->gp_auto_sleep_time =3D cmd_rep->data[0]; break; case FEATURE_IMU_BYPASS: - drvdata.imu_bypass_en =3D cmd_rep->data[0]; + drvdata->imu_bypass_en =3D cmd_rep->data[0]; break; case FEATURE_RGB_ENABLE: - drvdata.rgb_en =3D cmd_rep->data[0]; + drvdata->rgb_en =3D cmd_rep->data[0]; break; case FEATURE_IMU_ENABLE: - drvdata.imu_sensor_en =3D cmd_rep->data[0]; + drvdata->imu_sensor_en =3D cmd_rep->data[0]; break; case FEATURE_TOUCHPAD_ENABLE: - drvdata.tp_en =3D cmd_rep->data[0]; + drvdata->tp_en =3D cmd_rep->data[0]; break; case FEATURE_OS_MODE: - drvdata.os_mode =3D cmd_rep->data[0]; + drvdata->os_mode =3D cmd_rep->data[0]; break; case FEATURE_POLL_RATE: - drvdata.gp_poll_rate =3D cmd_rep->data[0]; + drvdata->gp_poll_rate =3D cmd_rep->data[0]; break; case FEATURE_DPAD_MODE: - drvdata.gp_dpad_mode =3D cmd_rep->data[0]; + drvdata->gp_dpad_mode =3D cmd_rep->data[0]; break; case FEATURE_MOUSE_WHEEL_STEP: - drvdata.mouse_step =3D cmd_rep->data[0]; + drvdata->mouse_step =3D cmd_rep->data[0]; break; default: ret =3D -EINVAL; @@ -302,16 +304,16 @@ static int hid_gos_gamepad_cfg_event(struct command_r= eport *cmd_rep) return ret; } =20 -static int hid_gos_touchpad_event(struct command_report *cmd_rep) +static int hid_gos_touchpad_event(struct gos_cfg_drvdata *drvdata, struct = command_report *cmd_rep) { int ret =3D 0; =20 switch (cmd_rep->sub_cmd) { case CFG_LINUX_MODE: - drvdata.tp_linux_mode =3D cmd_rep->data[0]; + drvdata->tp_linux_mode =3D cmd_rep->data[0]; break; case CFG_WINDOWS_MODE: - drvdata.tp_windows_mode =3D cmd_rep->data[0]; + drvdata->tp_windows_mode =3D cmd_rep->data[0]; break; default: ret =3D -EINVAL; @@ -321,21 +323,21 @@ static int hid_gos_touchpad_event(struct command_repo= rt *cmd_rep) return ret; } =20 -static int hid_gos_pl_test_event(struct command_report *cmd_rep) +static int hid_gos_pl_test_event(struct gos_cfg_drvdata *drvdata, struct c= ommand_report *cmd_rep) { int ret =3D 0; =20 switch (cmd_rep->sub_cmd) { case TEST_TP_MFR: - drvdata.tp_manufacturer =3D cmd_rep->data[0]; + drvdata->tp_manufacturer =3D cmd_rep->data[0]; ret =3D 0; break; case TEST_IMU_MFR: - drvdata.imu_manufacturer =3D cmd_rep->data[0]; + drvdata->imu_manufacturer =3D cmd_rep->data[0]; ret =3D 0; break; case TEST_TP_VER: - drvdata.tp_version =3D cmd_rep->data[0]; + drvdata->tp_version =3D cmd_rep->data[0]; ret =3D 0; break; default: @@ -345,30 +347,30 @@ static int hid_gos_pl_test_event(struct command_repor= t *cmd_rep) return ret; } =20 -static int hid_gos_light_event(struct command_report *cmd_rep) +static int hid_gos_light_event(struct gos_cfg_drvdata *drvdata, struct com= mand_report *cmd_rep) { struct led_classdev_mc *led_mc; int ret =3D 0; =20 switch (cmd_rep->sub_cmd) { case LIGHT_MODE_SEL: - drvdata.rgb_mode =3D cmd_rep->data[0]; + drvdata->rgb_mode =3D cmd_rep->data[0]; ret =3D 0; break; case LIGHT_PROFILE_SEL: - drvdata.rgb_profile =3D cmd_rep->data[0]; + drvdata->rgb_profile =3D cmd_rep->data[0]; ret =3D 0; break; case USR_LIGHT_PROFILE_1: case USR_LIGHT_PROFILE_2: case USR_LIGHT_PROFILE_3: - led_mc =3D &drvdata.led_mc; - drvdata.rgb_effect =3D cmd_rep->data[0]; + led_mc =3D &drvdata->led_mc; + drvdata->rgb_effect =3D cmd_rep->data[0]; led_mc->subled_info[0].intensity =3D cmd_rep->data[1]; led_mc->subled_info[1].intensity =3D cmd_rep->data[2]; led_mc->subled_info[2].intensity =3D cmd_rep->data[3]; led_mc->led_cdev.brightness =3D cmd_rep->data[4]; - drvdata.rgb_speed =3D cmd_rep->data[5]; + drvdata->rgb_speed =3D cmd_rep->data[5]; ret =3D 0; break; default: @@ -401,6 +403,7 @@ static int get_endpoint_address(struct hid_device *hdev) static int hid_gos_raw_event(struct hid_device *hdev, struct hid_report *r= eport, u8 *data, int size) { + struct gos_cfg_drvdata *drvdata =3D hid_get_drvdata(hdev); struct command_report *cmd_rep; int ep, ret; =20 @@ -408,6 +411,9 @@ static int hid_gos_raw_event(struct hid_device *hdev, s= truct hid_report *report, if (ep !=3D GO_S_CFG_INTF_IN) return 0; =20 + if (!drvdata) + return -ENODEV; + if (size !=3D GO_S_PACKET_SIZE) return -EINVAL; =20 @@ -415,22 +421,22 @@ static int hid_gos_raw_event(struct hid_device *hdev,= struct hid_report *report, =20 switch (cmd_rep->cmd) { case GET_VERSION: - ret =3D hid_gos_version_event(data); + ret =3D hid_gos_version_event(drvdata, data); break; case GET_MCU_ID: - ret =3D hid_gos_mcu_id_event(cmd_rep); + ret =3D hid_gos_mcu_id_event(drvdata, cmd_rep); break; case GET_GAMEPAD_CFG: - ret =3D hid_gos_gamepad_cfg_event(cmd_rep); + ret =3D hid_gos_gamepad_cfg_event(drvdata, cmd_rep); break; case GET_TP_PARAM: - ret =3D hid_gos_touchpad_event(cmd_rep); + ret =3D hid_gos_touchpad_event(drvdata, cmd_rep); break; case GET_PL_TEST: - ret =3D hid_gos_pl_test_event(cmd_rep); + ret =3D hid_gos_pl_test_event(drvdata, cmd_rep); break; case GET_RGB_CFG: - ret =3D hid_gos_light_event(cmd_rep); + ret =3D hid_gos_light_event(drvdata, cmd_rep); break; case SET_GAMEPAD_CFG: case SET_RGB_CFG: @@ -444,8 +450,8 @@ static int hid_gos_raw_event(struct hid_device *hdev, s= truct hid_report *report, dev_dbg(&hdev->dev, "Rx data as raw input report: [%*ph]\n", GO_S_PACKET_SIZE, data); =20 - drvdata.cmd_status =3D ret; - complete(&drvdata.send_cmd_complete); + drvdata->cmd_status =3D ret; + complete(&drvdata->send_cmd_complete); =20 return ret; } @@ -453,27 +459,31 @@ static int hid_gos_raw_event(struct hid_device *hdev,= struct hid_report *report, static int mcu_property_out(struct hid_device *hdev, u8 command, u8 index, u8 *data, size_t len) { + struct gos_cfg_drvdata *drvdata =3D hid_get_drvdata(hdev); unsigned char *dmabuf __free(kfree) =3D NULL; u8 header[] =3D { command, index }; size_t header_size =3D ARRAY_SIZE(header); int timeout, ret; =20 + if (!drvdata) + return -ENODEV; + if (header_size + len > GO_S_PACKET_SIZE) return -EINVAL; =20 - guard(mutex)(&drvdata.cfg_mutex); + guard(mutex)(&drvdata->cfg_mutex); =20 /* * A reply to the previous command may still be in flight. Give it a * short window to arrive and be consumed before this call reinits the * completion, so a late reply can't be mistaken for this command's. */ - if (drvdata.orphan_ack_pending) { - wait_for_completion_timeout(&drvdata.send_cmd_complete, msecs_to_jiffies= (25)); - drvdata.orphan_ack_pending =3D false; - drvdata.cmd_status =3D -ETIMEDOUT; + if (drvdata->orphan_ack_pending) { + wait_for_completion_timeout(&drvdata->send_cmd_complete, msecs_to_jiffie= s(25)); + drvdata->orphan_ack_pending =3D false; + drvdata->cmd_status =3D -ETIMEDOUT; } - reinit_completion(&drvdata.send_cmd_complete); + reinit_completion(&drvdata->send_cmd_complete); =20 /* We can't use a devm_alloc reusable buffer without side effects during = suspend */ dmabuf =3D kzalloc(GO_S_PACKET_SIZE, GFP_KERNEL); @@ -496,12 +506,12 @@ static int mcu_property_out(struct hid_device *hdev, = u8 command, u8 index, =20 /* PL_TEST commands can take longer because they go out to another device= */ timeout =3D (command =3D=3D GET_PL_TEST) ? 200 : 5; - ret =3D wait_for_completion_interruptible_timeout(&drvdata.send_cmd_compl= ete, + ret =3D wait_for_completion_interruptible_timeout(&drvdata->send_cmd_comp= lete, msecs_to_jiffies(timeout)); - ret =3D ret > 0 ? drvdata.cmd_status : ret ?: -EBUSY; + ret =3D ret > 0 ? drvdata->cmd_status : ret ?: -EBUSY; =20 if (ret) - drvdata.orphan_ack_pending =3D true; + drvdata->orphan_ack_pending =3D true; =20 return ret; } @@ -511,18 +521,30 @@ static ssize_t gamepad_property_store(struct device *= dev, const char *buf, size_t count, enum feature_status_index index) { + struct gos_cfg_drvdata *drvdata; + struct led_classdev_mc *led_mc; + struct led_classdev *led_cdev; + struct hid_device *hdev; bool dev_registered; size_t size =3D 1; u8 val =3D 0; int ret; =20 /* rgb_enabled is attached to led_classdev, not hid_device */ - if (index =3D=3D FEATURE_RGB_ENABLE) - /* Pairs with smp_store_release from gos_cfg_setup */ - dev_registered =3D smp_load_acquire(&drvdata.rgb_registered); - else - /* Pairs with smp_store_release from gos_cfg_setup */ - dev_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (index =3D=3D FEATURE_RGB_ENABLE) { + led_cdev =3D dev_get_drvdata(dev); + led_mc =3D lcdev_to_mccdev(led_cdev); + drvdata =3D container_of(led_mc, struct gos_cfg_drvdata, led_mc); + hdev =3D drvdata->hdev; + /* Pairs with smp_store_release from gos_cfg_setup */ + dev_registered =3D smp_load_acquire(&drvdata->rgb_registered); + + } else { + hdev =3D to_hid_device(dev); + drvdata =3D hid_get_drvdata(hdev); + /* Pairs with smp_store_release from gos_cfg_setup */ + dev_registered =3D smp_load_acquire(&drvdata->gp_registered); + } =20 if (!dev_registered) return -ENODEV; @@ -595,7 +617,7 @@ static ssize_t gamepad_property_store(struct device *de= v, if (!val) size =3D 0; =20 - ret =3D mcu_property_out(drvdata.hdev, SET_GAMEPAD_CFG, index, &val, + ret =3D mcu_property_out(hdev, SET_GAMEPAD_CFG, index, &val, size); if (ret < 0) return ret; @@ -607,79 +629,92 @@ static ssize_t gamepad_property_show(struct device *d= ev, struct device_attribute *attr, char *buf, enum feature_status_index index) { + struct gos_cfg_drvdata *drvdata; + struct led_classdev_mc *led_mc; + struct led_classdev *led_cdev; + struct hid_device *hdev; bool dev_registered; + ssize_t count =3D 0; u8 i; =20 /* rgb_enabled is attached to led_classdev, not hid_device */ - if (index =3D=3D FEATURE_RGB_ENABLE) - /* Pairs with smp_store_release from gos_cfg_setup */ - dev_registered =3D smp_load_acquire(&drvdata.rgb_registered); - else - /* Pairs with smp_store_release from gos_cfg_setup */ - dev_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (index =3D=3D FEATURE_RGB_ENABLE) { + led_cdev =3D dev_get_drvdata(dev); + led_mc =3D lcdev_to_mccdev(led_cdev); + drvdata =3D container_of(led_mc, struct gos_cfg_drvdata, led_mc); + hdev =3D drvdata->hdev; + /* Pairs with smp_store_release from gos_cfg_setup */ + dev_registered =3D smp_load_acquire(&drvdata->rgb_registered); + + } else { + hdev =3D to_hid_device(dev); + drvdata =3D hid_get_drvdata(hdev); + /* Pairs with smp_store_release from gos_cfg_setup */ + dev_registered =3D smp_load_acquire(&drvdata->gp_registered); + } =20 if (!dev_registered) return -ENODEV; =20 - count =3D mcu_property_out(drvdata.hdev, GET_GAMEPAD_CFG, index, NULL, 0); + count =3D mcu_property_out(hdev, GET_GAMEPAD_CFG, index, NULL, 0); if (count < 0) return count; =20 switch (index) { case FEATURE_GAMEPAD_MODE: - i =3D drvdata.gp_mode; + i =3D drvdata->gp_mode; if (i >=3D ARRAY_SIZE(gamepad_mode_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", gamepad_mode_text[i]); break; case FEATURE_AUTO_SLEEP_TIME: - count =3D sysfs_emit(buf, "%u\n", drvdata.gp_auto_sleep_time); + count =3D sysfs_emit(buf, "%u\n", drvdata->gp_auto_sleep_time); break; case FEATURE_IMU_ENABLE: - i =3D drvdata.imu_sensor_en; + i =3D drvdata->imu_sensor_en; if (i >=3D ARRAY_SIZE(feature_enabled_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", feature_enabled_text[i]); break; case FEATURE_IMU_BYPASS: - i =3D drvdata.imu_bypass_en; + i =3D drvdata->imu_bypass_en; if (i >=3D ARRAY_SIZE(feature_enabled_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", feature_enabled_text[i]); break; case FEATURE_RGB_ENABLE: - i =3D drvdata.rgb_en; + i =3D drvdata->rgb_en; if (i >=3D ARRAY_SIZE(feature_enabled_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", feature_enabled_text[i]); break; case FEATURE_TOUCHPAD_ENABLE: - i =3D drvdata.tp_en; + i =3D drvdata->tp_en; if (i >=3D ARRAY_SIZE(feature_enabled_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", feature_enabled_text[i]); break; case FEATURE_OS_MODE: - i =3D drvdata.os_mode; + i =3D drvdata->os_mode; if (i >=3D ARRAY_SIZE(os_type_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", os_type_text[i]); break; case FEATURE_POLL_RATE: - i =3D drvdata.gp_poll_rate; + i =3D drvdata->gp_poll_rate; if (i >=3D ARRAY_SIZE(poll_rate_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", poll_rate_text[i]); break; case FEATURE_DPAD_MODE: - i =3D drvdata.gp_dpad_mode; + i =3D drvdata->gp_dpad_mode; if (i >=3D ARRAY_SIZE(dpad_mode_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", dpad_mode_text[i]); break; case FEATURE_MOUSE_WHEEL_STEP: - i =3D drvdata.mouse_step; + i =3D drvdata->mouse_step; if (i < 1 || i > 127) return -EINVAL; count =3D sysfs_emit(buf, "%u\n", i); @@ -757,13 +792,18 @@ static ssize_t touchpad_property_store(struct device = *dev, const char *buf, size_t count, enum touchpad_config_index index) { + struct hid_device *hdev =3D to_hid_device(dev); + struct gos_cfg_drvdata *drvdata =3D hid_get_drvdata(hdev); bool gp_registered; size_t size =3D 1; u8 val =3D 0; int ret; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - gp_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (!drvdata) + return -ENODEV; + +/* Pairs with smp_store_release from gos_cfg_setup */ + gp_registered =3D smp_load_acquire(&drvdata->gp_registered); if (!gp_registered) return -ENODEV; =20 @@ -786,7 +826,7 @@ static ssize_t touchpad_property_store(struct device *d= ev, if (!val) size =3D 0; =20 - ret =3D mcu_property_out(drvdata.hdev, SET_TP_PARAM, index, &val, size); + ret =3D mcu_property_out(hdev, SET_TP_PARAM, index, &val, size); if (ret < 0) return ret; =20 @@ -797,25 +837,30 @@ static ssize_t touchpad_property_show(struct device *= dev, struct device_attribute *attr, char *buf, enum touchpad_config_index index) { + struct hid_device *hdev =3D to_hid_device(dev); + struct gos_cfg_drvdata *drvdata =3D hid_get_drvdata(hdev); bool gp_registered; int ret =3D 0; u8 i; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - gp_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (!drvdata) + return -ENODEV; + +/* Pairs with smp_store_release from gos_cfg_setup */ + gp_registered =3D smp_load_acquire(&drvdata->gp_registered); if (!gp_registered) return -ENODEV; =20 - ret =3D mcu_property_out(drvdata.hdev, GET_TP_PARAM, index, NULL, 0); + ret =3D mcu_property_out(hdev, GET_TP_PARAM, index, NULL, 0); if (ret < 0) return ret; =20 switch (index) { case CFG_WINDOWS_MODE: - i =3D drvdata.tp_windows_mode; + i =3D drvdata->tp_windows_mode; break; case CFG_LINUX_MODE: - i =3D drvdata.tp_linux_mode; + i =3D drvdata->tp_linux_mode; break; default: return -EINVAL; @@ -832,15 +877,9 @@ static ssize_t touchpad_property_options(struct device= *dev, char *buf, enum touchpad_config_index index) { - bool gp_registered; size_t count =3D 0; unsigned int i; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - gp_registered =3D smp_load_acquire(&drvdata.gp_registered); - if (!gp_registered) - return -ENODEV; - switch (index) { case CFG_WINDOWS_MODE: case CFG_LINUX_MODE: @@ -863,30 +902,35 @@ static ssize_t test_property_show(struct device *dev, struct device_attribute *attr, char *buf, enum test_command_index index) { + struct hid_device *hdev =3D to_hid_device(dev); + struct gos_cfg_drvdata *drvdata =3D hid_get_drvdata(hdev); bool gp_registered; size_t count =3D 0; u8 i; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - gp_registered =3D smp_load_acquire(&drvdata.gp_registered); + if (!drvdata) + return -ENODEV; + +/* Pairs with smp_store_release from gos_cfg_setup */ + gp_registered =3D smp_load_acquire(&drvdata->gp_registered); if (!gp_registered) return -ENODEV; =20 switch (index) { case TEST_TP_MFR: - i =3D drvdata.tp_manufacturer; + i =3D drvdata->tp_manufacturer; if (i >=3D ARRAY_SIZE(touchpad_manufacturer_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", touchpad_manufacturer_text[i]); break; case TEST_IMU_MFR: - i =3D drvdata.imu_manufacturer; + i =3D drvdata->imu_manufacturer; if (i >=3D ARRAY_SIZE(imu_manufacturer_text)) return -EINVAL; count =3D sysfs_emit(buf, "%s\n", imu_manufacturer_text[i]); break; case TEST_TP_VER: - count =3D sysfs_emit(buf, "%u\n", drvdata.tp_version); + count =3D sysfs_emit(buf, "%u\n", drvdata->tp_version); break; default: count =3D -EINVAL; @@ -899,7 +943,13 @@ static ssize_t test_property_show(struct device *dev, static ssize_t mcu_id_show(struct device *dev, struct device_attribute *at= tr, char *buf) { - return sysfs_emit(buf, "%*phN\n", 12, &drvdata.mcu_id); + struct hid_device *hdev =3D to_hid_device(dev); + struct gos_cfg_drvdata *drvdata =3D hid_get_drvdata(hdev); + + if (!drvdata) + return -ENODEV; + + return sysfs_emit(buf, "%*phN\n", 12, &drvdata->mcu_id); } =20 static int rgb_cfg_call(struct hid_device *hdev, enum mcu_command_index cm= d, @@ -914,27 +964,29 @@ static int rgb_cfg_call(struct hid_device *hdev, enum= mcu_command_index cmd, return mcu_property_out(hdev, cmd, index, val, size); } =20 -static int rgb_attr_show(void) +static int rgb_attr_show(struct gos_cfg_drvdata *drvdata) { enum rgb_config_index index; =20 - index =3D drvdata.rgb_profile + 2; + index =3D drvdata->rgb_profile + 2; =20 - return rgb_cfg_call(drvdata.hdev, GET_RGB_CFG, index, NULL, 0); + return rgb_cfg_call(drvdata->hdev, GET_RGB_CFG, index, NULL, 0); }; =20 static ssize_t rgb_effect_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct led_classdev_mc *led_mc =3D &drvdata.led_mc; + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + struct led_classdev_mc *led_mc =3D lcdev_to_mccdev(led_cdev); + struct gos_cfg_drvdata *drvdata =3D container_of(led_mc, struct gos_cfg_d= rvdata, led_mc); enum rgb_config_index index; bool rgb_registered; u8 effect; int ret; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!rgb_registered) return -ENODEV; =20 @@ -943,41 +995,44 @@ static ssize_t rgb_effect_store(struct device *dev, return ret; =20 effect =3D ret; - index =3D drvdata.rgb_profile + 2; + index =3D drvdata->rgb_profile + 2; u8 rgb_profile[6] =3D { effect, led_mc->subled_info[0].intensity, led_mc->subled_info[1].intensity, led_mc->subled_info[2].intensity, led_mc->led_cdev.brightness, - drvdata.rgb_speed }; + drvdata->rgb_speed }; =20 - ret =3D rgb_cfg_call(drvdata.hdev, SET_RGB_CFG, index, rgb_profile, 6); + ret =3D rgb_cfg_call(drvdata->hdev, SET_RGB_CFG, index, rgb_profile, 6); if (ret) return ret; =20 - drvdata.rgb_effect =3D effect; + drvdata->rgb_effect =3D effect; return count; }; =20 static ssize_t rgb_effect_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + struct led_classdev_mc *led_mc =3D lcdev_to_mccdev(led_cdev); + struct gos_cfg_drvdata *drvdata =3D container_of(led_mc, struct gos_cfg_d= rvdata, led_mc); bool rgb_registered; int ret; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!rgb_registered) return -ENODEV; =20 - ret =3D rgb_attr_show(); + ret =3D rgb_attr_show(drvdata); if (ret) return ret; =20 - if (drvdata.rgb_effect >=3D ARRAY_SIZE(rgb_effect_text)) + if (drvdata->rgb_effect >=3D ARRAY_SIZE(rgb_effect_text)) return -EINVAL; =20 - return sysfs_emit(buf, "%s\n", rgb_effect_text[drvdata.rgb_effect]); + return sysfs_emit(buf, "%s\n", rgb_effect_text[drvdata->rgb_effect]); } =20 static ssize_t rgb_effect_index_show(struct device *dev, @@ -999,14 +1054,16 @@ static ssize_t rgb_speed_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct led_classdev_mc *led_mc =3D &drvdata.led_mc; + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + struct led_classdev_mc *led_mc =3D lcdev_to_mccdev(led_cdev); + struct gos_cfg_drvdata *drvdata =3D container_of(led_mc, struct gos_cfg_d= rvdata, led_mc); enum rgb_config_index index; bool rgb_registered; int val =3D 0; int ret; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!rgb_registered) return -ENODEV; =20 @@ -1017,19 +1074,19 @@ static ssize_t rgb_speed_store(struct device *dev, if (val < 0 || val > 100) return -EINVAL; =20 - index =3D drvdata.rgb_profile + 2; - u8 rgb_profile[6] =3D { drvdata.rgb_effect, + index =3D drvdata->rgb_profile + 2; + u8 rgb_profile[6] =3D { drvdata->rgb_effect, led_mc->subled_info[0].intensity, led_mc->subled_info[1].intensity, led_mc->subled_info[2].intensity, led_mc->led_cdev.brightness, val }; =20 - ret =3D rgb_cfg_call(drvdata.hdev, SET_RGB_CFG, index, rgb_profile, 6); + ret =3D rgb_cfg_call(drvdata->hdev, SET_RGB_CFG, index, rgb_profile, 6); if (ret) return ret; =20 - drvdata.rgb_speed =3D val; + drvdata->rgb_speed =3D val; =20 return count; }; @@ -1037,22 +1094,25 @@ static ssize_t rgb_speed_store(struct device *dev, static ssize_t rgb_speed_show(struct device *dev, struct device_attribute = *attr, char *buf) { + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + struct led_classdev_mc *led_mc =3D lcdev_to_mccdev(led_cdev); + struct gos_cfg_drvdata *drvdata =3D container_of(led_mc, struct gos_cfg_d= rvdata, led_mc); bool rgb_registered; int ret; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!rgb_registered) return -ENODEV; =20 - ret =3D rgb_attr_show(); + ret =3D rgb_attr_show(drvdata); if (ret) return ret; =20 - if (drvdata.rgb_speed > 100) + if (drvdata->rgb_speed > 100) return -EINVAL; =20 - return sysfs_emit(buf, "%hhu\n", drvdata.rgb_speed); + return sysfs_emit(buf, "%hhu\n", drvdata->rgb_speed); } =20 static ssize_t rgb_speed_range_show(struct device *dev, @@ -1064,12 +1124,15 @@ static ssize_t rgb_speed_range_show(struct device *= dev, static ssize_t rgb_mode_store(struct device *dev, struct device_attribute = *attr, const char *buf, size_t count) { + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + struct led_classdev_mc *led_mc =3D lcdev_to_mccdev(led_cdev); + struct gos_cfg_drvdata *drvdata =3D container_of(led_mc, struct gos_cfg_d= rvdata, led_mc); bool rgb_registered; int ret; u8 val; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!rgb_registered) return -ENODEV; =20 @@ -1079,12 +1142,12 @@ static ssize_t rgb_mode_store(struct device *dev, s= truct device_attribute *attr, =20 val =3D ret; =20 - ret =3D rgb_cfg_call(drvdata.hdev, SET_RGB_CFG, LIGHT_MODE_SEL, &val, + ret =3D rgb_cfg_call(drvdata->hdev, SET_RGB_CFG, LIGHT_MODE_SEL, &val, 1); if (ret) return ret; =20 - drvdata.rgb_mode =3D val; + drvdata->rgb_mode =3D val; =20 return count; }; @@ -1092,22 +1155,25 @@ static ssize_t rgb_mode_store(struct device *dev, s= truct device_attribute *attr, static ssize_t rgb_mode_show(struct device *dev, struct device_attribute *= attr, char *buf) { + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + struct led_classdev_mc *led_mc =3D lcdev_to_mccdev(led_cdev); + struct gos_cfg_drvdata *drvdata =3D container_of(led_mc, struct gos_cfg_d= rvdata, led_mc); bool rgb_registered; int ret; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!rgb_registered) return -ENODEV; =20 - ret =3D rgb_cfg_call(drvdata.hdev, GET_RGB_CFG, LIGHT_MODE_SEL, NULL, 0); + ret =3D rgb_cfg_call(drvdata->hdev, GET_RGB_CFG, LIGHT_MODE_SEL, NULL, 0); if (ret) return ret; =20 - if (drvdata.rgb_mode >=3D ARRAY_SIZE(rgb_mode_text)) + if (drvdata->rgb_mode >=3D ARRAY_SIZE(rgb_mode_text)) return -EINVAL; =20 - return sysfs_emit(buf, "%s\n", rgb_mode_text[drvdata.rgb_mode]); + return sysfs_emit(buf, "%s\n", rgb_mode_text[drvdata->rgb_mode]); }; =20 static ssize_t rgb_mode_index_show(struct device *dev, @@ -1129,13 +1195,16 @@ static ssize_t rgb_profile_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + struct led_classdev_mc *led_mc =3D lcdev_to_mccdev(led_cdev); + struct gos_cfg_drvdata *drvdata =3D container_of(led_mc, struct gos_cfg_d= rvdata, led_mc); bool rgb_registered; size_t size =3D 1; int ret; u8 val; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!rgb_registered) return -ENODEV; =20 @@ -1146,11 +1215,11 @@ static ssize_t rgb_profile_store(struct device *dev, if (val < 1 || val > 3) return -EINVAL; =20 - ret =3D rgb_cfg_call(drvdata.hdev, SET_RGB_CFG, LIGHT_PROFILE_SEL, &val, = size); + ret =3D rgb_cfg_call(drvdata->hdev, SET_RGB_CFG, LIGHT_PROFILE_SEL, &val,= size); if (ret) return ret; =20 - drvdata.rgb_profile =3D val; + drvdata->rgb_profile =3D val; =20 return count; }; @@ -1158,22 +1227,25 @@ static ssize_t rgb_profile_store(struct device *dev, static ssize_t rgb_profile_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct led_classdev *led_cdev =3D dev_get_drvdata(dev); + struct led_classdev_mc *led_mc =3D lcdev_to_mccdev(led_cdev); + struct gos_cfg_drvdata *drvdata =3D container_of(led_mc, struct gos_cfg_d= rvdata, led_mc); bool rgb_registered; int ret; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!rgb_registered) return -ENODEV; =20 - ret =3D rgb_cfg_call(drvdata.hdev, GET_RGB_CFG, LIGHT_PROFILE_SEL, NULL, = 0); + ret =3D rgb_cfg_call(drvdata->hdev, GET_RGB_CFG, LIGHT_PROFILE_SEL, NULL,= 0); if (ret) return ret; =20 - if (drvdata.rgb_profile < 1 || drvdata.rgb_profile > 3) + if (drvdata->rgb_profile < 1 || drvdata->rgb_profile > 3) return -EINVAL; =20 - return sysfs_emit(buf, "%hhu\n", drvdata.rgb_profile); + return sysfs_emit(buf, "%hhu\n", drvdata->rgb_profile); }; =20 static ssize_t rgb_profile_range_show(struct device *dev, @@ -1185,13 +1257,14 @@ static ssize_t rgb_profile_range_show(struct device= *dev, static void hid_gos_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { - struct led_classdev_mc *led_mc =3D &drvdata.led_mc; + struct led_classdev_mc *led_mc =3D lcdev_to_mccdev(led_cdev); + struct gos_cfg_drvdata *drvdata =3D container_of(led_mc, struct gos_cfg_d= rvdata, led_mc); enum rgb_config_index index; bool rgb_registered; int ret; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!rgb_registered) return; =20 @@ -1200,15 +1273,15 @@ static void hid_gos_brightness_set(struct led_class= dev *led_cdev, return; } =20 - index =3D drvdata.rgb_profile + 2; - u8 rgb_profile[6] =3D { drvdata.rgb_effect, + index =3D drvdata->rgb_profile + 2; + u8 rgb_profile[6] =3D { drvdata->rgb_effect, led_mc->subled_info[0].intensity, led_mc->subled_info[1].intensity, led_mc->subled_info[2].intensity, brightness, - drvdata.rgb_speed }; + drvdata->rgb_speed }; =20 - ret =3D rgb_cfg_call(drvdata.hdev, SET_RGB_CFG, index, rgb_profile, 6); + ret =3D rgb_cfg_call(drvdata->hdev, SET_RGB_CFG, index, rgb_profile, 6); switch (ret) { case 0: led_cdev->brightness =3D brightness; @@ -1446,127 +1519,138 @@ static struct mc_subled gos_rgb_subled_info[] =3D= { =20 static void cfg_setup(struct work_struct *work) { + struct delayed_work *dwork =3D container_of(work, struct delayed_work, wo= rk); + struct gos_cfg_drvdata *drvdata =3D container_of(dwork, struct gos_cfg_dr= vdata, + gos_cfg_setup); bool gp_registered, rgb_registered; int ret; =20 + if (!drvdata) + return; + /* MCU */ - ret =3D mcu_property_out(drvdata.hdev, GET_MCU_ID, FEATURE_NONE, NULL, 0); + ret =3D mcu_property_out(drvdata->hdev, GET_MCU_ID, FEATURE_NONE, NULL, 0= ); if (ret) { - dev_err(&drvdata.hdev->dev, "Failed to retrieve MCU ID: %i\n", + dev_err(&drvdata->hdev->dev, "Failed to retrieve MCU ID: %i\n", ret); return; } =20 - ret =3D mcu_property_out(drvdata.hdev, GET_VERSION, FEATURE_NONE, NULL, 0= ); + ret =3D mcu_property_out(drvdata->hdev, GET_VERSION, FEATURE_NONE, NULL, = 0); if (ret) { - dev_err(&drvdata.hdev->dev, "Failed to retrieve MCU Version: %i\n", ret); + dev_err(&drvdata->hdev->dev, "Failed to retrieve MCU Version: %i\n", ret= ); return; } =20 - ret =3D mcu_property_out(drvdata.hdev, GET_PL_TEST, TEST_TP_MFR, NULL, 0); + ret =3D mcu_property_out(drvdata->hdev, GET_PL_TEST, TEST_TP_MFR, NULL, 0= ); if (ret) { - dev_err(&drvdata.hdev->dev, + dev_err(&drvdata->hdev->dev, "Failed to retrieve Touchpad Manufacturer: %i\n", ret); return; } =20 - ret =3D mcu_property_out(drvdata.hdev, GET_PL_TEST, TEST_TP_VER, NULL, 0); + ret =3D mcu_property_out(drvdata->hdev, GET_PL_TEST, TEST_TP_VER, NULL, 0= ); if (ret) { - dev_err(&drvdata.hdev->dev, + dev_err(&drvdata->hdev->dev, "Failed to retrieve Touchpad Firmware Version: %i\n", ret); return; } =20 - ret =3D mcu_property_out(drvdata.hdev, GET_PL_TEST, TEST_IMU_MFR, NULL, 0= ); + ret =3D mcu_property_out(drvdata->hdev, GET_PL_TEST, TEST_IMU_MFR, NULL, = 0); if (ret) { - dev_err(&drvdata.hdev->dev, + dev_err(&drvdata->hdev->dev, "Failed to retrieve IMU Manufacturer: %i\n", ret); return; } =20 - ret =3D mcu_property_out(drvdata.hdev, GET_GAMEPAD_CFG, FEATURE_OS_MODE, + ret =3D mcu_property_out(drvdata->hdev, GET_GAMEPAD_CFG, FEATURE_OS_MODE, NULL, 0); if (ret) { - dev_err(&drvdata.hdev->dev, + dev_err(&drvdata->hdev->dev, "Failed to retrieve OS Mode: %i\n", ret); return; } =20 - /* Pairs with smp_store_release from below */ - gp_registered =3D smp_load_acquire(&drvdata.gp_registered); +/* Pairs with smp_store_release from below */ + gp_registered =3D smp_load_acquire(&drvdata->gp_registered); if (gp_registered) goto try_rgb; =20 - ret =3D sysfs_create_groups(&drvdata.hdev->dev.kobj, top_level_attr_group= s); + ret =3D sysfs_create_groups(&drvdata->hdev->dev.kobj, top_level_attr_grou= ps); if (ret) { - dev_err(&drvdata.hdev->dev, + dev_err(&drvdata->hdev->dev, "Failed to create gamepad configuration attributes: %i\n", ret); goto try_rgb; } =20 - /* Pairs with smp_load_acquire in attribute show/store functions */ - smp_store_release(&drvdata.gp_registered, true); +/* Pairs with smp_load_acquire in attribute show/store functions */ + smp_store_release(&drvdata->gp_registered, true); gp_registered =3D true; =20 try_rgb: - /* Pairs with smp_store_release from below */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); +/* Pairs with smp_store_release from below */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (rgb_registered) goto update_kobjects; =20 - ret =3D devm_led_classdev_multicolor_register(&drvdata.hdev->dev, &drvdat= a.led_mc); + ret =3D devm_led_classdev_multicolor_register(&drvdata->hdev->dev, &drvda= ta->led_mc); if (ret) { - dev_err(&drvdata.hdev->dev, + dev_err(&drvdata->hdev->dev, "Failed to create RGB device: %i\n", ret); goto update_kobjects; } =20 - ret =3D devm_device_add_group(drvdata.led_mc.led_cdev.dev, &rgb_attr_grou= p); + ret =3D devm_device_add_group(drvdata->led_mc.led_cdev.dev, &rgb_attr_gro= up); if (ret) { - dev_err(&drvdata.hdev->dev, + dev_err(&drvdata->hdev->dev, "Failed to create RGB configuration attributes: %i\n", ret); goto update_kobjects; } =20 - /* Pairs with smp_load_acquire in attribute show/store functions */ - smp_store_release(&drvdata.rgb_registered, true); +/* Pairs with smp_load_acquire in attribute show/store functions */ + smp_store_release(&drvdata->rgb_registered, true); rgb_registered =3D true; =20 update_kobjects: if (gp_registered) - kobject_uevent(&drvdata.hdev->dev.kobj, KOBJ_CHANGE); + kobject_uevent(&drvdata->hdev->dev.kobj, KOBJ_CHANGE); if (rgb_registered) - kobject_uevent(&drvdata.led_mc.led_cdev.dev->kobj, KOBJ_CHANGE); + kobject_uevent(&drvdata->led_mc.led_cdev.dev->kobj, KOBJ_CHANGE); } =20 static int hid_gos_cfg_probe(struct hid_device *hdev, const struct hid_device_id *_id) { + struct gos_cfg_drvdata *drvdata; int ret; =20 - hid_set_drvdata(hdev, &drvdata); - drvdata.hdev =3D hdev; + drvdata =3D devm_kzalloc(&hdev->dev, sizeof(struct gos_cfg_drvdata), GFP_= KERNEL); + if (!drvdata) + return -ENOMEM; + + hid_set_drvdata(hdev, drvdata); + drvdata->hdev =3D hdev; =20 - mutex_init(&drvdata.cfg_mutex); - init_completion(&drvdata.send_cmd_complete); + mutex_init(&drvdata->cfg_mutex); + init_completion(&drvdata->send_cmd_complete); =20 /* Device is hardwired and name is guaranteed to be unique */ - drvdata.led_mc.led_cdev.name =3D "go_s:rgb:joystick_rings"; - drvdata.led_mc.led_cdev.brightness =3D 0x50; - drvdata.led_mc.led_cdev.max_brightness =3D 0x64; - drvdata.led_mc.led_cdev.color =3D LED_COLOR_ID_RGB; - drvdata.led_mc.led_cdev.brightness_set =3D hid_gos_brightness_set; - drvdata.led_mc.num_colors =3D 3; - drvdata.led_mc.subled_info =3D devm_kmemdup(&hdev->dev, gos_rgb_subled_in= fo, - sizeof(gos_rgb_subled_info), GFP_KERNEL); - if (!drvdata.led_mc.subled_info) + drvdata->led_mc.led_cdev.name =3D "go_s:rgb:joystick_rings"; + drvdata->led_mc.led_cdev.brightness =3D 0x50; + drvdata->led_mc.led_cdev.max_brightness =3D 0x64; + drvdata->led_mc.led_cdev.color =3D LED_COLOR_ID_RGB; + drvdata->led_mc.led_cdev.brightness_set =3D hid_gos_brightness_set; + drvdata->led_mc.num_colors =3D 3; + drvdata->led_mc.subled_info =3D devm_kmemdup(&hdev->dev, gos_rgb_subled_i= nfo, + sizeof(gos_rgb_subled_info), GFP_KERNEL); + if (!drvdata->led_mc.subled_info) return -ENOMEM; =20 /* Executing calls prior to returning from probe will lock the MCU. Sched= ule * initial data call after probe has completed and MCU can accept calls. */ - INIT_DELAYED_WORK(&drvdata.gos_cfg_setup, &cfg_setup); - ret =3D schedule_delayed_work(&drvdata.gos_cfg_setup, msecs_to_jiffies(2)= ); + INIT_DELAYED_WORK(&drvdata->gos_cfg_setup, &cfg_setup); + ret =3D schedule_delayed_work(&drvdata->gos_cfg_setup, msecs_to_jiffies(2= )); if (!ret) { dev_err(&hdev->dev, "Failed to schedule startup delayed work\n"); return -ENODEV; @@ -1577,7 +1661,12 @@ static int hid_gos_cfg_probe(struct hid_device *hdev, =20 static void hid_gos_cfg_remove(struct hid_device *hdev) { - disable_delayed_work_sync(&drvdata.gos_cfg_setup); + struct gos_cfg_drvdata *drvdata =3D hid_get_drvdata(hdev); + + if (!drvdata) + return; + + disable_delayed_work_sync(&drvdata->gos_cfg_setup); sysfs_remove_groups(&hdev->dev.kobj, top_level_attr_groups); hid_hw_close(hdev); hid_hw_stop(hdev); @@ -1586,16 +1675,21 @@ static void hid_gos_cfg_remove(struct hid_device *h= dev) =20 static int hid_gos_cfg_reset_resume(struct hid_device *hdev) { + struct gos_cfg_drvdata *drvdata =3D hid_get_drvdata(hdev); bool gp_registered, rgb_registered; - u8 os_mode =3D drvdata.os_mode; + u8 os_mode; int ret; =20 - /* Pairs with smp_store_release from gos_cfg_setup */ - gp_registered =3D smp_load_acquire(&drvdata.gp_registered); - /* Pairs with smp_store_release from gos_cfg_setup */ - rgb_registered =3D smp_load_acquire(&drvdata.rgb_registered); + if (!drvdata) + return -ENODEV; + + os_mode =3D drvdata->os_mode; +/* Pairs with smp_store_release from gos_cfg_setup */ + gp_registered =3D smp_load_acquire(&drvdata->gp_registered); +/* Pairs with smp_store_release from gos_cfg_setup */ + rgb_registered =3D smp_load_acquire(&drvdata->rgb_registered); if (!gp_registered || !rgb_registered) { - ret =3D schedule_delayed_work(&drvdata.gos_cfg_setup, msecs_to_jiffies(2= )); + ret =3D schedule_delayed_work(&drvdata->gos_cfg_setup, msecs_to_jiffies(= 2)); if (!ret) { dev_err(&hdev->dev, "Failed to schedule startup delayed work\n"); return -ENODEV; @@ -1604,20 +1698,20 @@ static int hid_gos_cfg_reset_resume(struct hid_devi= ce *hdev) return 0; } =20 - ret =3D mcu_property_out(drvdata.hdev, SET_GAMEPAD_CFG, + ret =3D mcu_property_out(drvdata->hdev, SET_GAMEPAD_CFG, FEATURE_OS_MODE, &os_mode, 1); if (ret < 0) return ret; =20 - ret =3D mcu_property_out(drvdata.hdev, GET_GAMEPAD_CFG, + ret =3D mcu_property_out(drvdata->hdev, GET_GAMEPAD_CFG, FEATURE_OS_MODE, NULL, 0); if (ret < 0) return ret; =20 - if (drvdata.os_mode !=3D os_mode) + if (drvdata->os_mode !=3D os_mode) return -ENODEV; =20 - kobject_uevent(&drvdata.hdev->dev.kobj, KOBJ_CHANGE); + kobject_uevent(&drvdata->hdev->dev.kobj, KOBJ_CHANGE); return 0; } =20 @@ -1692,9 +1786,14 @@ static int hid_gos_reset_resume(struct hid_device *h= dev) return 0; } =20 -static int hid_gos_cfg_suspend(void) +static int hid_gos_cfg_suspend(struct hid_device *hdev) { - disable_delayed_work_sync(&drvdata.gos_cfg_setup); + struct gos_cfg_drvdata *drvdata =3D hid_get_drvdata(hdev); + + if (!drvdata) + return -ENODEV; + + disable_delayed_work_sync(&drvdata->gos_cfg_setup); =20 return 0; } @@ -1711,7 +1810,7 @@ static int hid_gos_suspend(struct hid_device *hdev, p= m_message_t msg) =20 ep =3D ret; if (ep =3D=3D GO_S_CFG_INTF_IN) - return hid_gos_cfg_suspend(); + return hid_gos_cfg_suspend(hdev); =20 return 0; } --=20 2.55.0