Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/arm_scmi/bus.c
26428 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* System Control and Management Interface (SCMI) Message Protocol bus layer
4
*
5
* Copyright (C) 2018-2021 ARM Ltd.
6
*/
7
8
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9
10
#include <linux/atomic.h>
11
#include <linux/types.h>
12
#include <linux/module.h>
13
#include <linux/of.h>
14
#include <linux/kernel.h>
15
#include <linux/slab.h>
16
#include <linux/device.h>
17
18
#include "common.h"
19
20
#define SCMI_UEVENT_MODALIAS_FMT "%s:%02x:%s"
21
22
BLOCKING_NOTIFIER_HEAD(scmi_requested_devices_nh);
23
EXPORT_SYMBOL_GPL(scmi_requested_devices_nh);
24
25
static DEFINE_IDA(scmi_bus_id);
26
27
static DEFINE_IDR(scmi_requested_devices);
28
/* Protect access to scmi_requested_devices */
29
static DEFINE_MUTEX(scmi_requested_devices_mtx);
30
31
struct scmi_requested_dev {
32
const struct scmi_device_id *id_table;
33
struct list_head node;
34
};
35
36
/* Track globally the creation of SCMI SystemPower related devices */
37
static atomic_t scmi_syspower_registered = ATOMIC_INIT(0);
38
39
/**
40
* scmi_protocol_device_request - Helper to request a device
41
*
42
* @id_table: A protocol/name pair descriptor for the device to be created.
43
*
44
* This helper let an SCMI driver request specific devices identified by the
45
* @id_table to be created for each active SCMI instance.
46
*
47
* The requested device name MUST NOT be already existent for this protocol;
48
* at first the freshly requested @id_table is annotated in the IDR table
49
* @scmi_requested_devices and then the requested device is advertised to any
50
* registered party via the @scmi_requested_devices_nh notification chain.
51
*
52
* Return: 0 on Success
53
*/
54
static int scmi_protocol_device_request(const struct scmi_device_id *id_table)
55
{
56
int ret = 0;
57
struct list_head *head, *phead = NULL;
58
struct scmi_requested_dev *rdev;
59
60
pr_debug("Requesting SCMI device (%s) for protocol %x\n",
61
id_table->name, id_table->protocol_id);
62
63
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT) &&
64
!IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX)) {
65
pr_warn("SCMI Raw mode active. Rejecting '%s'/0x%02X\n",
66
id_table->name, id_table->protocol_id);
67
return -EINVAL;
68
}
69
70
/*
71
* Find the matching protocol rdev list and then search of any
72
* existent equally named device...fails if any duplicate found.
73
*/
74
mutex_lock(&scmi_requested_devices_mtx);
75
phead = idr_find(&scmi_requested_devices, id_table->protocol_id);
76
if (phead) {
77
head = phead;
78
list_for_each_entry(rdev, head, node) {
79
if (!strcmp(rdev->id_table->name, id_table->name)) {
80
pr_err("Ignoring duplicate request [%d] %s\n",
81
rdev->id_table->protocol_id,
82
rdev->id_table->name);
83
ret = -EINVAL;
84
goto out;
85
}
86
}
87
}
88
89
/*
90
* No duplicate found for requested id_table, so let's create a new
91
* requested device entry for this new valid request.
92
*/
93
rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
94
if (!rdev) {
95
ret = -ENOMEM;
96
goto out;
97
}
98
rdev->id_table = id_table;
99
100
/*
101
* Append the new requested device table descriptor to the head of the
102
* related protocol list, eventually creating such head if not already
103
* there.
104
*/
105
if (!phead) {
106
phead = kzalloc(sizeof(*phead), GFP_KERNEL);
107
if (!phead) {
108
kfree(rdev);
109
ret = -ENOMEM;
110
goto out;
111
}
112
INIT_LIST_HEAD(phead);
113
114
ret = idr_alloc(&scmi_requested_devices, (void *)phead,
115
id_table->protocol_id,
116
id_table->protocol_id + 1, GFP_KERNEL);
117
if (ret != id_table->protocol_id) {
118
pr_err("Failed to save SCMI device - ret:%d\n", ret);
119
kfree(rdev);
120
kfree(phead);
121
ret = -EINVAL;
122
goto out;
123
}
124
ret = 0;
125
}
126
list_add(&rdev->node, phead);
127
128
out:
129
mutex_unlock(&scmi_requested_devices_mtx);
130
131
if (!ret)
132
blocking_notifier_call_chain(&scmi_requested_devices_nh,
133
SCMI_BUS_NOTIFY_DEVICE_REQUEST,
134
(void *)rdev->id_table);
135
136
return ret;
137
}
138
139
static int scmi_protocol_table_register(const struct scmi_device_id *id_table)
140
{
141
int ret = 0;
142
const struct scmi_device_id *entry;
143
144
for (entry = id_table; entry->name && ret == 0; entry++)
145
ret = scmi_protocol_device_request(entry);
146
147
return ret;
148
}
149
150
/**
151
* scmi_protocol_device_unrequest - Helper to unrequest a device
152
*
153
* @id_table: A protocol/name pair descriptor for the device to be unrequested.
154
*
155
* The unrequested device, described by the provided id_table, is at first
156
* removed from the IDR @scmi_requested_devices and then the removal is
157
* advertised to any registered party via the @scmi_requested_devices_nh
158
* notification chain.
159
*/
160
static void scmi_protocol_device_unrequest(const struct scmi_device_id *id_table)
161
{
162
struct list_head *phead;
163
164
pr_debug("Unrequesting SCMI device (%s) for protocol %x\n",
165
id_table->name, id_table->protocol_id);
166
167
mutex_lock(&scmi_requested_devices_mtx);
168
phead = idr_find(&scmi_requested_devices, id_table->protocol_id);
169
if (phead) {
170
struct scmi_requested_dev *victim, *tmp;
171
172
list_for_each_entry_safe(victim, tmp, phead, node) {
173
if (!strcmp(victim->id_table->name, id_table->name)) {
174
list_del(&victim->node);
175
176
mutex_unlock(&scmi_requested_devices_mtx);
177
blocking_notifier_call_chain(&scmi_requested_devices_nh,
178
SCMI_BUS_NOTIFY_DEVICE_UNREQUEST,
179
(void *)victim->id_table);
180
kfree(victim);
181
mutex_lock(&scmi_requested_devices_mtx);
182
break;
183
}
184
}
185
186
if (list_empty(phead)) {
187
idr_remove(&scmi_requested_devices,
188
id_table->protocol_id);
189
kfree(phead);
190
}
191
}
192
mutex_unlock(&scmi_requested_devices_mtx);
193
}
194
195
static void
196
scmi_protocol_table_unregister(const struct scmi_device_id *id_table)
197
{
198
const struct scmi_device_id *entry;
199
200
for (entry = id_table; entry->name; entry++)
201
scmi_protocol_device_unrequest(entry);
202
}
203
204
static int scmi_dev_match_by_id_table(struct scmi_device *scmi_dev,
205
const struct scmi_device_id *id_table)
206
{
207
if (!id_table || !id_table->name)
208
return 0;
209
210
/* Always skip transport devices from matching */
211
for (; id_table->protocol_id && id_table->name; id_table++)
212
if (id_table->protocol_id == scmi_dev->protocol_id &&
213
strncmp(scmi_dev->name, "__scmi_transport_device", 23) &&
214
!strcmp(id_table->name, scmi_dev->name))
215
return 1;
216
return 0;
217
}
218
219
static int scmi_dev_match_id(struct scmi_device *scmi_dev,
220
const struct scmi_driver *scmi_drv)
221
{
222
return scmi_dev_match_by_id_table(scmi_dev, scmi_drv->id_table);
223
}
224
225
static int scmi_dev_match(struct device *dev, const struct device_driver *drv)
226
{
227
const struct scmi_driver *scmi_drv = to_scmi_driver(drv);
228
struct scmi_device *scmi_dev = to_scmi_dev(dev);
229
230
return scmi_dev_match_id(scmi_dev, scmi_drv);
231
}
232
233
static int scmi_match_by_id_table(struct device *dev, const void *data)
234
{
235
struct scmi_device *scmi_dev = to_scmi_dev(dev);
236
const struct scmi_device_id *id_table = data;
237
238
return scmi_dev_match_by_id_table(scmi_dev, id_table);
239
}
240
241
static struct scmi_device *scmi_child_dev_find(struct device *parent,
242
int prot_id, const char *name)
243
{
244
struct scmi_device_id id_table[2] = { 0 };
245
struct device *dev;
246
247
id_table[0].protocol_id = prot_id;
248
id_table[0].name = name;
249
250
dev = device_find_child(parent, &id_table, scmi_match_by_id_table);
251
if (!dev)
252
return NULL;
253
254
/* Drop the refcnt bumped implicitly by device_find_child */
255
put_device(dev);
256
257
return to_scmi_dev(dev);
258
}
259
260
static int scmi_dev_probe(struct device *dev)
261
{
262
struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
263
struct scmi_device *scmi_dev = to_scmi_dev(dev);
264
265
if (!scmi_dev->handle)
266
return -EPROBE_DEFER;
267
268
return scmi_drv->probe(scmi_dev);
269
}
270
271
static void scmi_dev_remove(struct device *dev)
272
{
273
struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver);
274
struct scmi_device *scmi_dev = to_scmi_dev(dev);
275
276
if (scmi_drv->remove)
277
scmi_drv->remove(scmi_dev);
278
}
279
280
static int scmi_device_uevent(const struct device *dev, struct kobj_uevent_env *env)
281
{
282
const struct scmi_device *scmi_dev = to_scmi_dev(dev);
283
284
return add_uevent_var(env, "MODALIAS=" SCMI_UEVENT_MODALIAS_FMT,
285
dev_name(&scmi_dev->dev), scmi_dev->protocol_id,
286
scmi_dev->name);
287
}
288
289
static ssize_t modalias_show(struct device *dev,
290
struct device_attribute *attr, char *buf)
291
{
292
struct scmi_device *scmi_dev = to_scmi_dev(dev);
293
294
return sysfs_emit(buf, SCMI_UEVENT_MODALIAS_FMT,
295
dev_name(&scmi_dev->dev), scmi_dev->protocol_id,
296
scmi_dev->name);
297
}
298
static DEVICE_ATTR_RO(modalias);
299
300
static ssize_t protocol_id_show(struct device *dev,
301
struct device_attribute *attr, char *buf)
302
{
303
struct scmi_device *scmi_dev = to_scmi_dev(dev);
304
305
return sprintf(buf, "0x%02x\n", scmi_dev->protocol_id);
306
}
307
static DEVICE_ATTR_RO(protocol_id);
308
309
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
310
char *buf)
311
{
312
struct scmi_device *scmi_dev = to_scmi_dev(dev);
313
314
return sprintf(buf, "%s\n", scmi_dev->name);
315
}
316
static DEVICE_ATTR_RO(name);
317
318
static struct attribute *scmi_device_attributes_attrs[] = {
319
&dev_attr_protocol_id.attr,
320
&dev_attr_name.attr,
321
&dev_attr_modalias.attr,
322
NULL,
323
};
324
ATTRIBUTE_GROUPS(scmi_device_attributes);
325
326
static int scmi_pm_suspend(struct device *dev)
327
{
328
const struct device_driver *drv = dev->driver;
329
330
if (drv && drv->pm && drv->pm->suspend)
331
return drv->pm->suspend(dev);
332
333
return 0;
334
}
335
336
static int scmi_pm_resume(struct device *dev)
337
{
338
const struct device_driver *drv = dev->driver;
339
340
if (drv && drv->pm && drv->pm->resume)
341
return drv->pm->resume(dev);
342
343
return 0;
344
}
345
346
static const struct dev_pm_ops scmi_dev_pm_ops = {
347
.suspend = pm_sleep_ptr(scmi_pm_suspend),
348
.resume = pm_sleep_ptr(scmi_pm_resume),
349
};
350
351
const struct bus_type scmi_bus_type = {
352
.name = "scmi_protocol",
353
.match = scmi_dev_match,
354
.probe = scmi_dev_probe,
355
.remove = scmi_dev_remove,
356
.uevent = scmi_device_uevent,
357
.dev_groups = scmi_device_attributes_groups,
358
.pm = &scmi_dev_pm_ops,
359
};
360
EXPORT_SYMBOL_GPL(scmi_bus_type);
361
362
int scmi_driver_register(struct scmi_driver *driver, struct module *owner,
363
const char *mod_name)
364
{
365
int retval;
366
367
if (!driver->probe)
368
return -EINVAL;
369
370
retval = scmi_protocol_table_register(driver->id_table);
371
if (retval)
372
return retval;
373
374
driver->driver.bus = &scmi_bus_type;
375
driver->driver.name = driver->name;
376
driver->driver.owner = owner;
377
driver->driver.mod_name = mod_name;
378
379
retval = driver_register(&driver->driver);
380
if (!retval)
381
pr_debug("Registered new scmi driver %s\n", driver->name);
382
383
return retval;
384
}
385
EXPORT_SYMBOL_GPL(scmi_driver_register);
386
387
void scmi_driver_unregister(struct scmi_driver *driver)
388
{
389
driver_unregister(&driver->driver);
390
scmi_protocol_table_unregister(driver->id_table);
391
}
392
EXPORT_SYMBOL_GPL(scmi_driver_unregister);
393
394
static void scmi_device_release(struct device *dev)
395
{
396
struct scmi_device *scmi_dev = to_scmi_dev(dev);
397
398
kfree_const(scmi_dev->name);
399
kfree(scmi_dev);
400
}
401
402
static void __scmi_device_destroy(struct scmi_device *scmi_dev)
403
{
404
pr_debug("(%s) Destroying SCMI device '%s' for protocol 0x%x (%s)\n",
405
of_node_full_name(scmi_dev->dev.parent->of_node),
406
dev_name(&scmi_dev->dev), scmi_dev->protocol_id,
407
scmi_dev->name);
408
409
if (scmi_dev->protocol_id == SCMI_PROTOCOL_SYSTEM)
410
atomic_set(&scmi_syspower_registered, 0);
411
412
ida_free(&scmi_bus_id, scmi_dev->id);
413
device_unregister(&scmi_dev->dev);
414
}
415
416
static struct scmi_device *
417
__scmi_device_create(struct device_node *np, struct device *parent,
418
int protocol, const char *name)
419
{
420
int id, retval;
421
struct scmi_device *scmi_dev;
422
423
/*
424
* If the same protocol/name device already exist under the same parent
425
* (i.e. SCMI instance) just return the existent device.
426
* This avoids any race between the SCMI driver, creating devices for
427
* each DT defined protocol at probe time, and the concurrent
428
* registration of SCMI drivers.
429
*/
430
scmi_dev = scmi_child_dev_find(parent, protocol, name);
431
if (scmi_dev)
432
return scmi_dev;
433
434
/*
435
* Ignore any possible subsequent failures while creating the device
436
* since we are doomed anyway at that point; not using a mutex which
437
* spans across this whole function to keep things simple and to avoid
438
* to serialize all the __scmi_device_create calls across possibly
439
* different SCMI server instances (parent)
440
*/
441
if (protocol == SCMI_PROTOCOL_SYSTEM &&
442
atomic_cmpxchg(&scmi_syspower_registered, 0, 1)) {
443
dev_warn(parent,
444
"SCMI SystemPower protocol device must be unique !\n");
445
return NULL;
446
}
447
448
scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL);
449
if (!scmi_dev)
450
return NULL;
451
452
scmi_dev->name = kstrdup_const(name ?: "unknown", GFP_KERNEL);
453
if (!scmi_dev->name) {
454
kfree(scmi_dev);
455
return NULL;
456
}
457
458
id = ida_alloc_min(&scmi_bus_id, 1, GFP_KERNEL);
459
if (id < 0) {
460
kfree_const(scmi_dev->name);
461
kfree(scmi_dev);
462
return NULL;
463
}
464
465
scmi_dev->id = id;
466
scmi_dev->protocol_id = protocol;
467
scmi_dev->dev.parent = parent;
468
device_set_node(&scmi_dev->dev, of_fwnode_handle(np));
469
scmi_dev->dev.bus = &scmi_bus_type;
470
scmi_dev->dev.release = scmi_device_release;
471
dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
472
473
retval = device_register(&scmi_dev->dev);
474
if (retval)
475
goto put_dev;
476
477
pr_debug("(%s) Created SCMI device '%s' for protocol 0x%x (%s)\n",
478
of_node_full_name(parent->of_node),
479
dev_name(&scmi_dev->dev), protocol, name);
480
481
return scmi_dev;
482
put_dev:
483
put_device(&scmi_dev->dev);
484
ida_free(&scmi_bus_id, id);
485
return NULL;
486
}
487
488
static struct scmi_device *
489
_scmi_device_create(struct device_node *np, struct device *parent,
490
int protocol, const char *name)
491
{
492
struct scmi_device *sdev;
493
494
sdev = __scmi_device_create(np, parent, protocol, name);
495
if (!sdev)
496
pr_err("(%s) Failed to create device for protocol 0x%x (%s)\n",
497
of_node_full_name(parent->of_node), protocol, name);
498
499
return sdev;
500
}
501
502
/**
503
* scmi_device_create - A method to create one or more SCMI devices
504
*
505
* @np: A reference to the device node to use for the new device(s)
506
* @parent: The parent device to use identifying a specific SCMI instance
507
* @protocol: The SCMI protocol to be associated with this device
508
* @name: The requested-name of the device to be created; this is optional
509
* and if no @name is provided, all the devices currently known to
510
* be requested on the SCMI bus for @protocol will be created.
511
*
512
* This method can be invoked to create a single well-defined device (like
513
* a transport device or a device requested by an SCMI driver loaded after
514
* the core SCMI stack has been probed), or to create all the devices currently
515
* known to have been requested by the loaded SCMI drivers for a specific
516
* protocol (typically during SCMI core protocol enumeration at probe time).
517
*
518
* Return: The created device (or one of them if @name was NOT provided and
519
* multiple devices were created) or NULL if no device was created;
520
* note that NULL indicates an error ONLY in case a specific @name
521
* was provided: when @name param was not provided, a number of devices
522
* could have been potentially created for a whole protocol, unless no
523
* device was found to have been requested for that specific protocol.
524
*/
525
struct scmi_device *scmi_device_create(struct device_node *np,
526
struct device *parent, int protocol,
527
const char *name)
528
{
529
struct list_head *phead;
530
struct scmi_requested_dev *rdev;
531
struct scmi_device *scmi_dev = NULL;
532
533
if (name)
534
return _scmi_device_create(np, parent, protocol, name);
535
536
mutex_lock(&scmi_requested_devices_mtx);
537
phead = idr_find(&scmi_requested_devices, protocol);
538
/* Nothing to do. */
539
if (!phead) {
540
mutex_unlock(&scmi_requested_devices_mtx);
541
return NULL;
542
}
543
544
/* Walk the list of requested devices for protocol and create them */
545
list_for_each_entry(rdev, phead, node) {
546
struct scmi_device *sdev;
547
548
sdev = _scmi_device_create(np, parent,
549
rdev->id_table->protocol_id,
550
rdev->id_table->name);
551
if (sdev)
552
scmi_dev = sdev;
553
}
554
555
mutex_unlock(&scmi_requested_devices_mtx);
556
557
return scmi_dev;
558
}
559
EXPORT_SYMBOL_GPL(scmi_device_create);
560
561
void scmi_device_destroy(struct device *parent, int protocol, const char *name)
562
{
563
struct scmi_device *scmi_dev;
564
565
scmi_dev = scmi_child_dev_find(parent, protocol, name);
566
if (scmi_dev)
567
__scmi_device_destroy(scmi_dev);
568
}
569
EXPORT_SYMBOL_GPL(scmi_device_destroy);
570
571
static int __scmi_devices_unregister(struct device *dev, void *data)
572
{
573
struct scmi_device *scmi_dev = to_scmi_dev(dev);
574
575
__scmi_device_destroy(scmi_dev);
576
return 0;
577
}
578
579
static void scmi_devices_unregister(void)
580
{
581
bus_for_each_dev(&scmi_bus_type, NULL, NULL, __scmi_devices_unregister);
582
}
583
584
static int __init scmi_bus_init(void)
585
{
586
int retval;
587
588
retval = bus_register(&scmi_bus_type);
589
if (retval)
590
pr_err("SCMI protocol bus register failed (%d)\n", retval);
591
592
pr_info("SCMI protocol bus registered\n");
593
594
return retval;
595
}
596
subsys_initcall(scmi_bus_init);
597
598
static void __exit scmi_bus_exit(void)
599
{
600
/*
601
* Destroy all remaining devices: just in case the drivers were
602
* manually unbound and at first and then the modules unloaded.
603
*/
604
scmi_devices_unregister();
605
bus_unregister(&scmi_bus_type);
606
ida_destroy(&scmi_bus_id);
607
}
608
module_exit(scmi_bus_exit);
609
610
MODULE_ALIAS("scmi-core");
611
MODULE_AUTHOR("Sudeep Holla <[email protected]>");
612
MODULE_DESCRIPTION("ARM SCMI protocol bus");
613
MODULE_LICENSE("GPL");
614
615