Skip to content

Commit 8a5b38c

Browse files
mmindlag-linaro
authored andcommitted
HID: hid-sensor-hub: don't use stale platform-data on remove
The hid-sensor-hub creates the individual device structs and transfers them to the created mfd platform-devices via the platform_data in the mfd_cell. Before e651a1d ("HID: hid-sensor-hub: Allow parallel synchronous reads") the sensor-hub was managing access centrally, with one "completion" in the hub's data structure, which needed to be finished on removal at the latest. The mentioned commit then moved this central management to each hid sensor device, resulting on a completion in each struct hid_sensor_hub_device. The remove procedure was adapted to go through all sensor devices and finish any pending "completion". What this didn't take into account was, platform_device_add_data() that is used by mfd_add{_hotplug}_devices() does a kmemdup on the submitted platform-data. So the data the platform-device gets is a copy of the original data, meaning that the device worked on a different completion than what sensor_hub_remove() currently wants to access. To fix that, use device_for_each_child() to go through each child-device similar to how mfd_remove_devices() unregisters the devices later and with that get the live platform_data to finalize the correct completion. Fixes: e651a1d ("HID: hid-sensor-hub: Allow parallel synchronous reads") Cc: [email protected] Signed-off-by: Heiko Stuebner <[email protected]> Acked-by: Benjamin Tissoires <[email protected]> Acked-by: Srinivas Pandruvada <[email protected]> Acked-by: Jiri Kosina <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Lee Jones <[email protected]>
1 parent 40384c8 commit 8a5b38c

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

drivers/hid/hid-sensor-hub.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -730,23 +730,30 @@ static int sensor_hub_probe(struct hid_device *hdev,
730730
return ret;
731731
}
732732

733+
static int sensor_hub_finalize_pending_fn(struct device *dev, void *data)
734+
{
735+
struct hid_sensor_hub_device *hsdev = dev->platform_data;
736+
737+
if (hsdev->pending.status)
738+
complete(&hsdev->pending.ready);
739+
740+
return 0;
741+
}
742+
733743
static void sensor_hub_remove(struct hid_device *hdev)
734744
{
735745
struct sensor_hub_data *data = hid_get_drvdata(hdev);
736746
unsigned long flags;
737-
int i;
738747

739748
hid_dbg(hdev, " hardware removed\n");
740749
hid_hw_close(hdev);
741750
hid_hw_stop(hdev);
751+
742752
spin_lock_irqsave(&data->lock, flags);
743-
for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
744-
struct hid_sensor_hub_device *hsdev =
745-
data->hid_sensor_hub_client_devs[i].platform_data;
746-
if (hsdev->pending.status)
747-
complete(&hsdev->pending.ready);
748-
}
753+
device_for_each_child(&hdev->dev, NULL,
754+
sensor_hub_finalize_pending_fn);
749755
spin_unlock_irqrestore(&data->lock, flags);
756+
750757
mfd_remove_devices(&hdev->dev);
751758
mutex_destroy(&data->mutex);
752759
}

0 commit comments

Comments
 (0)