From: Sriman Achanta <srimanachanta@gmail.com>
To: Jiri Kosina <jikos@kernel.org>, Benjamin Tissoires <bentiss@kernel.org>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
Bastien Nocera <hadess@hadess.net>,
Simon Wood <simon@mungewell.org>,
Christian Mayer <git@mayer-bgk.de>,
Sriman Achanta <srimanachanta@gmail.com>
Subject: [PATCH v6 7/9] HID: steelseries: Manage battery lifetime with refcounting
Date: Wed, 8 Jul 2026 23:23:14 -0400 [thread overview]
Message-ID: <20260709032316.1908460-8-68172138+srimanachanta@users.noreply.github.com> (raw)
In-Reply-To: <20260709032316.1908460-1-68172138+srimanachanta@users.noreply.github.com>
From: Sriman Achanta <srimanachanta@gmail.com>
The next change shares one steelseries_device between two HID
interfaces, so the state can outlive either interface. Stop using devm
for it. Reference count the struct with a kref and free it from
steelseries_device_release(). Register and unregister the power supply
explicitly, and clear sd->battery under sd->lock in remove() so it is
not touched after it is unregistered.
Drop the global atomic battery counter and name the power supply after
the device (hdev->uniq, or dev_name() when empty), as hid-input and the
other HID battery drivers do.
No functional change for the current single-interface devices.
Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
---
drivers/hid/hid-steelseries-arctis.c | 47 +++++++++++++++++++++-------
1 file changed, 36 insertions(+), 11 deletions(-)
diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index b54f20f081a2..e534aa44e70a 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -8,6 +8,8 @@
#include <linux/device.h>
#include <linux/hid.h>
+#include <linux/kref.h>
+#include <linux/slab.h>
#include <linux/module.h>
#include <linux/power_supply.h>
#include <linux/spinlock.h>
@@ -30,6 +32,8 @@ struct steelseries_device_info {
};
struct steelseries_device {
+ struct kref refcnt;
+
struct hid_device *hdev;
const struct steelseries_device_info *info;
@@ -45,6 +49,14 @@ struct steelseries_device {
bool removed;
};
+static void steelseries_device_release(struct kref *ref)
+{
+ struct steelseries_device *sd =
+ container_of(ref, struct steelseries_device, refcnt);
+
+ kfree(sd);
+}
+
/*
* Headset report helpers
*/
@@ -267,9 +279,8 @@ static void steelseries_status_timer_work_handler(struct work_struct *work)
static int steelseries_battery_register(struct steelseries_device *sd)
{
- static atomic_t battery_no = ATOMIC_INIT(0);
struct power_supply_config battery_cfg = { .drv_data = sd, };
- unsigned long n;
+ struct power_supply *battery;
int ret;
sd->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
@@ -277,9 +288,10 @@ static int steelseries_battery_register(struct steelseries_device *sd)
sd->battery_desc.num_properties = ARRAY_SIZE(steelseries_battery_props);
sd->battery_desc.get_property = steelseries_battery_get_property;
sd->battery_desc.use_for_apm = 0;
- n = atomic_inc_return(&battery_no) - 1;
sd->battery_desc.name = devm_kasprintf(&sd->hdev->dev, GFP_KERNEL,
- "steelseries_headset_battery_%ld", n);
+ "steelseries_headset_battery_%s",
+ sd->hdev->uniq[0] ? sd->hdev->uniq :
+ dev_name(&sd->hdev->dev));
if (!sd->battery_desc.name)
return -ENOMEM;
@@ -289,17 +301,19 @@ static int steelseries_battery_register(struct steelseries_device *sd)
sd->headset_connected = false;
steelseries_headset_set_wireless_status(sd->hdev, false);
- sd->battery = devm_power_supply_register(&sd->hdev->dev,
+ battery = power_supply_register(&sd->hdev->dev,
&sd->battery_desc, &battery_cfg);
- if (IS_ERR(sd->battery)) {
- ret = PTR_ERR(sd->battery);
- sd->battery = NULL;
+ if (IS_ERR(battery)) {
+ ret = PTR_ERR(battery);
hid_err(sd->hdev,
"%s:power_supply_register failed with error %d\n",
__func__, ret);
return ret;
}
- power_supply_powers(sd->battery, &sd->hdev->dev);
+ power_supply_powers(battery, &sd->hdev->dev);
+
+ /* Assign on success only, so a concurrent raw_event never sees an ERR_PTR. */
+ sd->battery = battery;
return 0;
}
@@ -329,10 +343,11 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
if (interface_num != info->sync_interface)
return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);
+ sd = kzalloc_obj(*sd, GFP_KERNEL);
if (!sd)
return -ENOMEM;
+ kref_init(&sd->refcnt);
sd->hdev = hdev;
sd->info = info;
spin_lock_init(&sd->lock);
@@ -341,7 +356,7 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret)
- return ret;
+ goto err_put;
ret = hid_hw_open(hdev);
if (ret)
@@ -360,12 +375,15 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
err_stop:
hid_hw_stop(hdev);
+err_put:
+ kref_put(&sd->refcnt, steelseries_device_release);
return ret;
}
static void steelseries_arctis_remove(struct hid_device *hdev)
{
struct steelseries_device *sd;
+ struct power_supply *battery;
unsigned long flags;
struct usb_interface *intf;
u8 interface_num;
@@ -387,13 +405,20 @@ static void steelseries_arctis_remove(struct hid_device *hdev)
if (interface_num == sd->info->sync_interface) {
spin_lock_irqsave(&sd->lock, flags);
sd->removed = true;
+ battery = sd->battery;
+ sd->battery = NULL;
spin_unlock_irqrestore(&sd->lock, flags);
cancel_delayed_work_sync(&sd->status_work);
+
+ if (battery)
+ power_supply_unregister(battery);
}
hid_hw_close(hdev);
hid_hw_stop(hdev);
+
+ kref_put(&sd->refcnt, steelseries_device_release);
}
static int steelseries_arctis_raw_event(struct hid_device *hdev,
--
2.55.0
next prev parent reply other threads:[~2026-07-09 3:23 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-09 3:23 [PATCH v6 0/9] HID: steelseries: split out Arctis driver and add Nova 5X/Nova 7 support Sriman Achanta
2026-07-09 3:23 ` [PATCH v6 1/9] HID: steelseries: Fix ARCTIS_1_X device mislabeling Sriman Achanta
2026-07-09 3:36 ` sashiko-bot
2026-07-09 3:23 ` [PATCH v6 2/9] HID: steelseries: Split Arctis headset driver into separate module Sriman Achanta
2026-07-09 3:34 ` sashiko-bot
2026-07-09 3:23 ` [PATCH v6 3/9] HID: steelseries: Inline and simplify SRWS1 wheel driver Sriman Achanta
2026-07-09 3:23 ` [PATCH v6 4/9] HID: steelseries: Refactor Arctis driver to use device_info framework Sriman Achanta
2026-07-09 3:33 ` sashiko-bot
2026-07-09 3:23 ` [PATCH v6 5/9] HID: steelseries: Report POWER_SUPPLY_STATUS_FULL when full Sriman Achanta
2026-07-09 3:23 ` [PATCH v6 6/9] HID: steelseries: Correct Arctis 9 battery calibration range Sriman Achanta
2026-07-09 3:23 ` Sriman Achanta [this message]
2026-07-09 3:38 ` [PATCH v6 7/9] HID: steelseries: Manage battery lifetime with refcounting sashiko-bot
2026-07-09 3:23 ` [PATCH v6 8/9] HID: steelseries: Add async status interface support Sriman Achanta
2026-07-09 3:37 ` sashiko-bot
2026-07-09 3:23 ` [PATCH v6 9/9] HID: steelseries: Add support for Arctis Nova 5X and Nova 7 families Sriman Achanta
2026-07-10 12:02 ` [PATCH v6 0/9] HID: steelseries: split out Arctis driver and add Nova 5X/Nova 7 support Bastien Nocera
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260709032316.1908460-8-68172138+srimanachanta@users.noreply.github.com \
--to=srimanachanta@gmail.com \
--cc=bentiss@kernel.org \
--cc=git@mayer-bgk.de \
--cc=hadess@hadess.net \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=simon@mungewell.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox