Skip to content

Commit 4a4ab61

Browse files
qzedjwrdegoede
authored andcommitted
platform/surface: aggregator: Move device registry helper functions to core module
Move helper functions for client device registration to the core module. This simplifies addition of future DT/OF support and also allows us to split out the device hub drivers into their own module. At the same time, also improve device node validation a bit by not silently skipping devices with invalid device UID specifiers. Further, ensure proper lifetime management for the firmware/software nodes associated with the added devices. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com> Link: https://lore.kernel.org/r/20220624205800.1355621-2-luzmaximilian@gmail.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 parent 70e85eb commit 4a4ab61

File tree

3 files changed

+187
-89
lines changed

3 files changed

+187
-89
lines changed

drivers/platform/surface/aggregator/bus.c

Lines changed: 133 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include <linux/device.h>
9+
#include <linux/property.h>
910
#include <linux/slab.h>
1011

1112
#include <linux/surface_aggregator/controller.h>
@@ -14,6 +15,9 @@
1415
#include "bus.h"
1516
#include "controller.h"
1617

18+
19+
/* -- Device and bus functions. --------------------------------------------- */
20+
1721
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
1822
char *buf)
1923
{
@@ -46,6 +50,7 @@ static void ssam_device_release(struct device *dev)
4650
struct ssam_device *sdev = to_ssam_device(dev);
4751

4852
ssam_controller_put(sdev->ctrl);
53+
fwnode_handle_put(sdev->dev.fwnode);
4954
kfree(sdev);
5055
}
5156

@@ -363,6 +368,134 @@ void ssam_device_driver_unregister(struct ssam_device_driver *sdrv)
363368
}
364369
EXPORT_SYMBOL_GPL(ssam_device_driver_unregister);
365370

371+
372+
/* -- Bus registration. ----------------------------------------------------- */
373+
374+
/**
375+
* ssam_bus_register() - Register and set-up the SSAM client device bus.
376+
*/
377+
int ssam_bus_register(void)
378+
{
379+
return bus_register(&ssam_bus_type);
380+
}
381+
382+
/**
383+
* ssam_bus_unregister() - Unregister the SSAM client device bus.
384+
*/
385+
void ssam_bus_unregister(void)
386+
{
387+
return bus_unregister(&ssam_bus_type);
388+
}
389+
390+
391+
/* -- Helpers for controller and hub devices. ------------------------------- */
392+
393+
static int ssam_device_uid_from_string(const char *str, struct ssam_device_uid *uid)
394+
{
395+
u8 d, tc, tid, iid, fn;
396+
int n;
397+
398+
n = sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
399+
if (n != 5)
400+
return -EINVAL;
401+
402+
uid->domain = d;
403+
uid->category = tc;
404+
uid->target = tid;
405+
uid->instance = iid;
406+
uid->function = fn;
407+
408+
return 0;
409+
}
410+
411+
static int ssam_get_uid_for_node(struct fwnode_handle *node, struct ssam_device_uid *uid)
412+
{
413+
const char *str = fwnode_get_name(node);
414+
415+
/*
416+
* To simplify definitions of firmware nodes, we set the device name
417+
* based on the UID of the device, prefixed with "ssam:".
418+
*/
419+
if (strncmp(str, "ssam:", strlen("ssam:")) != 0)
420+
return -ENODEV;
421+
422+
str += strlen("ssam:");
423+
return ssam_device_uid_from_string(str, uid);
424+
}
425+
426+
static int ssam_add_client_device(struct device *parent, struct ssam_controller *ctrl,
427+
struct fwnode_handle *node)
428+
{
429+
struct ssam_device_uid uid;
430+
struct ssam_device *sdev;
431+
int status;
432+
433+
status = ssam_get_uid_for_node(node, &uid);
434+
if (status)
435+
return status;
436+
437+
sdev = ssam_device_alloc(ctrl, uid);
438+
if (!sdev)
439+
return -ENOMEM;
440+
441+
sdev->dev.parent = parent;
442+
sdev->dev.fwnode = fwnode_handle_get(node);
443+
444+
status = ssam_device_add(sdev);
445+
if (status)
446+
ssam_device_put(sdev);
447+
448+
return status;
449+
}
450+
451+
/**
452+
* __ssam_register_clients() - Register client devices defined under the
453+
* given firmware node as children of the given device.
454+
* @parent: The parent device under which clients should be registered.
455+
* @ctrl: The controller with which client should be registered.
456+
* @node: The firmware node holding definitions of the devices to be added.
457+
*
458+
* Register all clients that have been defined as children of the given root
459+
* firmware node as children of the given parent device. The respective child
460+
* firmware nodes will be associated with the correspondingly created child
461+
* devices.
462+
*
463+
* The given controller will be used to instantiate the new devices. See
464+
* ssam_device_add() for details.
465+
*
466+
* Note that, generally, the use of either ssam_device_register_clients() or
467+
* ssam_register_clients() should be preferred as they directly use the
468+
* firmware node and/or controller associated with the given device. This
469+
* function is only intended for use when different device specifications (e.g.
470+
* ACPI and firmware nodes) need to be combined (as is done in the platform hub
471+
* of the device registry).
472+
*
473+
* Return: Returns zero on success, nonzero on failure.
474+
*/
475+
int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
476+
struct fwnode_handle *node)
477+
{
478+
struct fwnode_handle *child;
479+
int status;
480+
481+
fwnode_for_each_child_node(node, child) {
482+
/*
483+
* Try to add the device specified in the firmware node. If
484+
* this fails with -ENODEV, the node does not specify any SSAM
485+
* device, so ignore it and continue with the next one.
486+
*/
487+
status = ssam_add_client_device(parent, ctrl, child);
488+
if (status && status != -ENODEV)
489+
goto err;
490+
}
491+
492+
return 0;
493+
err:
494+
ssam_remove_clients(parent);
495+
return status;
496+
}
497+
EXPORT_SYMBOL_GPL(__ssam_register_clients);
498+
366499
static int ssam_remove_device(struct device *dev, void *_data)
367500
{
368501
struct ssam_device *sdev = to_ssam_device(dev);
@@ -387,19 +520,3 @@ void ssam_remove_clients(struct device *dev)
387520
device_for_each_child_reverse(dev, NULL, ssam_remove_device);
388521
}
389522
EXPORT_SYMBOL_GPL(ssam_remove_clients);
390-
391-
/**
392-
* ssam_bus_register() - Register and set-up the SSAM client device bus.
393-
*/
394-
int ssam_bus_register(void)
395-
{
396-
return bus_register(&ssam_bus_type);
397-
}
398-
399-
/**
400-
* ssam_bus_unregister() - Unregister the SSAM client device bus.
401-
*/
402-
void ssam_bus_unregister(void)
403-
{
404-
return bus_unregister(&ssam_bus_type);
405-
}

drivers/platform/surface/surface_aggregator_registry.c

Lines changed: 2 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -286,76 +286,6 @@ static const struct software_node *ssam_node_group_sp8[] = {
286286
};
287287

288288

289-
/* -- Device registry helper functions. ------------------------------------- */
290-
291-
static int ssam_uid_from_string(const char *str, struct ssam_device_uid *uid)
292-
{
293-
u8 d, tc, tid, iid, fn;
294-
int n;
295-
296-
n = sscanf(str, "ssam:%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
297-
if (n != 5)
298-
return -EINVAL;
299-
300-
uid->domain = d;
301-
uid->category = tc;
302-
uid->target = tid;
303-
uid->instance = iid;
304-
uid->function = fn;
305-
306-
return 0;
307-
}
308-
309-
static int ssam_hub_add_device(struct device *parent, struct ssam_controller *ctrl,
310-
struct fwnode_handle *node)
311-
{
312-
struct ssam_device_uid uid;
313-
struct ssam_device *sdev;
314-
int status;
315-
316-
status = ssam_uid_from_string(fwnode_get_name(node), &uid);
317-
if (status)
318-
return status;
319-
320-
sdev = ssam_device_alloc(ctrl, uid);
321-
if (!sdev)
322-
return -ENOMEM;
323-
324-
sdev->dev.parent = parent;
325-
sdev->dev.fwnode = node;
326-
327-
status = ssam_device_add(sdev);
328-
if (status)
329-
ssam_device_put(sdev);
330-
331-
return status;
332-
}
333-
334-
static int ssam_hub_register_clients(struct device *parent, struct ssam_controller *ctrl,
335-
struct fwnode_handle *node)
336-
{
337-
struct fwnode_handle *child;
338-
int status;
339-
340-
fwnode_for_each_child_node(node, child) {
341-
/*
342-
* Try to add the device specified in the firmware node. If
343-
* this fails with -EINVAL, the node does not specify any SSAM
344-
* device, so ignore it and continue with the next one.
345-
*/
346-
347-
status = ssam_hub_add_device(parent, ctrl, child);
348-
if (status && status != -EINVAL)
349-
goto err;
350-
}
351-
352-
return 0;
353-
err:
354-
ssam_remove_clients(parent);
355-
return status;
356-
}
357-
358-
359289
/* -- SSAM generic subsystem hub driver framework. -------------------------- */
360290

361291
enum ssam_hub_state {
@@ -385,7 +315,6 @@ struct ssam_hub {
385315
static void ssam_hub_update_workfn(struct work_struct *work)
386316
{
387317
struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
388-
struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
389318
enum ssam_hub_state state;
390319
int status = 0;
391320

@@ -425,7 +354,7 @@ static void ssam_hub_update_workfn(struct work_struct *work)
425354
hub->state = state;
426355

427356
if (hub->state == SSAM_HUB_CONNECTED)
428-
status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
357+
status = ssam_device_register_clients(hub->sdev);
429358
else
430359
ssam_remove_clients(&hub->sdev->dev);
431360

@@ -769,7 +698,7 @@ static int ssam_platform_hub_probe(struct platform_device *pdev)
769698

770699
set_secondary_fwnode(&pdev->dev, root);
771700

772-
status = ssam_hub_register_clients(&pdev->dev, ctrl, root);
701+
status = __ssam_register_clients(&pdev->dev, ctrl, root);
773702
if (status) {
774703
set_secondary_fwnode(&pdev->dev, NULL);
775704
software_node_unregister_node_group(nodes);

include/linux/surface_aggregator/device.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include <linux/device.h>
1717
#include <linux/mod_devicetable.h>
18+
#include <linux/property.h>
1819
#include <linux/types.h>
1920

2021
#include <linux/surface_aggregator/controller.h>
@@ -375,11 +376,62 @@ void ssam_device_driver_unregister(struct ssam_device_driver *d);
375376
/* -- Helpers for controller and hub devices. ------------------------------- */
376377

377378
#ifdef CONFIG_SURFACE_AGGREGATOR_BUS
379+
380+
int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
381+
struct fwnode_handle *node);
378382
void ssam_remove_clients(struct device *dev);
383+
379384
#else /* CONFIG_SURFACE_AGGREGATOR_BUS */
385+
386+
static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
387+
struct fwnode_handle *node)
388+
{
389+
return 0;
390+
}
391+
380392
static inline void ssam_remove_clients(struct device *dev) {}
393+
381394
#endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
382395

396+
/**
397+
* ssam_register_clients() - Register all client devices defined under the
398+
* given parent device.
399+
* @dev: The parent device under which clients should be registered.
400+
* @ctrl: The controller with which client should be registered.
401+
*
402+
* Register all clients that have via firmware nodes been defined as children
403+
* of the given (parent) device. The respective child firmware nodes will be
404+
* associated with the correspondingly created child devices.
405+
*
406+
* The given controller will be used to instantiate the new devices. See
407+
* ssam_device_add() for details.
408+
*
409+
* Return: Returns zero on success, nonzero on failure.
410+
*/
411+
static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
412+
{
413+
return __ssam_register_clients(dev, ctrl, dev_fwnode(dev));
414+
}
415+
416+
/**
417+
* ssam_device_register_clients() - Register all client devices defined under
418+
* the given SSAM parent device.
419+
* @sdev: The parent device under which clients should be registered.
420+
*
421+
* Register all clients that have via firmware nodes been defined as children
422+
* of the given (parent) device. The respective child firmware nodes will be
423+
* associated with the correspondingly created child devices.
424+
*
425+
* The controller used by the parent device will be used to instantiate the new
426+
* devices. See ssam_device_add() for details.
427+
*
428+
* Return: Returns zero on success, nonzero on failure.
429+
*/
430+
static inline int ssam_device_register_clients(struct ssam_device *sdev)
431+
{
432+
return ssam_register_clients(&sdev->dev, sdev->ctrl);
433+
}
434+
383435

384436
/* -- Helpers for client-device requests. ----------------------------------- */
385437

0 commit comments

Comments
 (0)