@@ -262,3 +262,234 @@ struct device *rpmsg_find_device(struct device *parent,
262
262
263
263
}
264
264
EXPORT_SYMBOL (rpmsg_find_device );
265
+
266
+ /* sysfs show configuration fields */
267
+ #define rpmsg_show_attr (field , path , format_string ) \
268
+ static ssize_t \
269
+ field##_show(struct device *dev, \
270
+ struct device_attribute *attr, char *buf) \
271
+ { \
272
+ struct rpmsg_device *rpdev = to_rpmsg_device(dev); \
273
+ \
274
+ return sprintf(buf, format_string, rpdev->path); \
275
+ }
276
+
277
+ /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
278
+ rpmsg_show_attr (name , id .name , "%s\n" );
279
+ rpmsg_show_attr (src , src , "0x%x\n" );
280
+ rpmsg_show_attr (dst , dst , "0x%x\n" );
281
+ rpmsg_show_attr (announce , announce ? "true" : "false" , "%s\n" );
282
+
283
+ static ssize_t modalias_show (struct device * dev ,
284
+ struct device_attribute * attr , char * buf )
285
+ {
286
+ struct rpmsg_device * rpdev = to_rpmsg_device (dev );
287
+
288
+ return sprintf (buf , RPMSG_DEVICE_MODALIAS_FMT "\n" , rpdev -> id .name );
289
+ }
290
+
291
+ static struct device_attribute rpmsg_dev_attrs [] = {
292
+ __ATTR_RO (name ),
293
+ __ATTR_RO (modalias ),
294
+ __ATTR_RO (dst ),
295
+ __ATTR_RO (src ),
296
+ __ATTR_RO (announce ),
297
+ __ATTR_NULL
298
+ };
299
+
300
+ /* rpmsg devices and drivers are matched using the service name */
301
+ static inline int rpmsg_id_match (const struct rpmsg_device * rpdev ,
302
+ const struct rpmsg_device_id * id )
303
+ {
304
+ return strncmp (id -> name , rpdev -> id .name , RPMSG_NAME_SIZE ) == 0 ;
305
+ }
306
+
307
+ /* match rpmsg channel and rpmsg driver */
308
+ static int rpmsg_dev_match (struct device * dev , struct device_driver * drv )
309
+ {
310
+ struct rpmsg_device * rpdev = to_rpmsg_device (dev );
311
+ struct rpmsg_driver * rpdrv = to_rpmsg_driver (drv );
312
+ const struct rpmsg_device_id * ids = rpdrv -> id_table ;
313
+ unsigned int i ;
314
+
315
+ if (ids )
316
+ for (i = 0 ; ids [i ].name [0 ]; i ++ )
317
+ if (rpmsg_id_match (rpdev , & ids [i ]))
318
+ return 1 ;
319
+
320
+ return of_driver_match_device (dev , drv );
321
+ }
322
+
323
+ static int rpmsg_uevent (struct device * dev , struct kobj_uevent_env * env )
324
+ {
325
+ struct rpmsg_device * rpdev = to_rpmsg_device (dev );
326
+
327
+ return add_uevent_var (env , "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT ,
328
+ rpdev -> id .name );
329
+ }
330
+
331
+ /*
332
+ * when an rpmsg driver is probed with a channel, we seamlessly create
333
+ * it an endpoint, binding its rx callback to a unique local rpmsg
334
+ * address.
335
+ *
336
+ * if we need to, we also announce about this channel to the remote
337
+ * processor (needed in case the driver is exposing an rpmsg service).
338
+ */
339
+ static int rpmsg_dev_probe (struct device * dev )
340
+ {
341
+ struct rpmsg_device * rpdev = to_rpmsg_device (dev );
342
+ struct rpmsg_driver * rpdrv = to_rpmsg_driver (rpdev -> dev .driver );
343
+ struct rpmsg_channel_info chinfo = {};
344
+ struct rpmsg_endpoint * ept ;
345
+ int err ;
346
+
347
+ strncpy (chinfo .name , rpdev -> id .name , RPMSG_NAME_SIZE );
348
+ chinfo .src = rpdev -> src ;
349
+ chinfo .dst = RPMSG_ADDR_ANY ;
350
+
351
+ ept = rpmsg_create_ept (rpdev , rpdrv -> callback , NULL , chinfo );
352
+ if (!ept ) {
353
+ dev_err (dev , "failed to create endpoint\n" );
354
+ err = - ENOMEM ;
355
+ goto out ;
356
+ }
357
+
358
+ rpdev -> ept = ept ;
359
+ rpdev -> src = ept -> addr ;
360
+
361
+ err = rpdrv -> probe (rpdev );
362
+ if (err ) {
363
+ dev_err (dev , "%s: failed: %d\n" , __func__ , err );
364
+ rpmsg_destroy_ept (ept );
365
+ goto out ;
366
+ }
367
+
368
+ if (rpdev -> ops -> announce_create )
369
+ err = rpdev -> ops -> announce_create (rpdev );
370
+ out :
371
+ return err ;
372
+ }
373
+
374
+ static int rpmsg_dev_remove (struct device * dev )
375
+ {
376
+ struct rpmsg_device * rpdev = to_rpmsg_device (dev );
377
+ struct rpmsg_driver * rpdrv = to_rpmsg_driver (rpdev -> dev .driver );
378
+ int err = 0 ;
379
+
380
+ if (rpdev -> ops -> announce_destroy )
381
+ err = rpdev -> ops -> announce_destroy (rpdev );
382
+
383
+ rpdrv -> remove (rpdev );
384
+
385
+ rpmsg_destroy_ept (rpdev -> ept );
386
+
387
+ return err ;
388
+ }
389
+
390
+ static struct bus_type rpmsg_bus = {
391
+ .name = "rpmsg" ,
392
+ .match = rpmsg_dev_match ,
393
+ .dev_attrs = rpmsg_dev_attrs ,
394
+ .uevent = rpmsg_uevent ,
395
+ .probe = rpmsg_dev_probe ,
396
+ .remove = rpmsg_dev_remove ,
397
+ };
398
+
399
+ static void rpmsg_release_device (struct device * dev )
400
+ {
401
+ struct rpmsg_device * rpdev = to_rpmsg_device (dev );
402
+
403
+ kfree (rpdev );
404
+ }
405
+
406
+ int rpmsg_register_device (struct rpmsg_device * rpdev )
407
+ {
408
+ struct device * dev = & rpdev -> dev ;
409
+ int ret ;
410
+
411
+ dev_set_name (& rpdev -> dev , "%s:%s" ,
412
+ dev_name (dev -> parent ), rpdev -> id .name );
413
+
414
+ rpdev -> dev .bus = & rpmsg_bus ;
415
+ rpdev -> dev .release = rpmsg_release_device ;
416
+
417
+ ret = device_register (& rpdev -> dev );
418
+ if (ret ) {
419
+ dev_err (dev , "device_register failed: %d\n" , ret );
420
+ put_device (& rpdev -> dev );
421
+ }
422
+
423
+ return ret ;
424
+ }
425
+ EXPORT_SYMBOL (rpmsg_register_device );
426
+
427
+ /*
428
+ * find an existing channel using its name + address properties,
429
+ * and destroy it
430
+ */
431
+ int rpmsg_unregister_device (struct device * parent ,
432
+ struct rpmsg_channel_info * chinfo )
433
+ {
434
+ struct device * dev ;
435
+
436
+ dev = rpmsg_find_device (parent , chinfo );
437
+ if (!dev )
438
+ return - EINVAL ;
439
+
440
+ device_unregister (dev );
441
+
442
+ put_device (dev );
443
+
444
+ return 0 ;
445
+ }
446
+ EXPORT_SYMBOL (rpmsg_unregister_device );
447
+
448
+ /**
449
+ * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
450
+ * @rpdrv: pointer to a struct rpmsg_driver
451
+ * @owner: owning module/driver
452
+ *
453
+ * Returns 0 on success, and an appropriate error value on failure.
454
+ */
455
+ int __register_rpmsg_driver (struct rpmsg_driver * rpdrv , struct module * owner )
456
+ {
457
+ rpdrv -> drv .bus = & rpmsg_bus ;
458
+ rpdrv -> drv .owner = owner ;
459
+ return driver_register (& rpdrv -> drv );
460
+ }
461
+ EXPORT_SYMBOL (__register_rpmsg_driver );
462
+
463
+ /**
464
+ * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus
465
+ * @rpdrv: pointer to a struct rpmsg_driver
466
+ *
467
+ * Returns 0 on success, and an appropriate error value on failure.
468
+ */
469
+ void unregister_rpmsg_driver (struct rpmsg_driver * rpdrv )
470
+ {
471
+ driver_unregister (& rpdrv -> drv );
472
+ }
473
+ EXPORT_SYMBOL (unregister_rpmsg_driver );
474
+
475
+
476
+ static int __init rpmsg_init (void )
477
+ {
478
+ int ret ;
479
+
480
+ ret = bus_register (& rpmsg_bus );
481
+ if (ret )
482
+ pr_err ("failed to register rpmsg bus: %d\n" , ret );
483
+
484
+ return ret ;
485
+ }
486
+ postcore_initcall (rpmsg_init );
487
+
488
+ static void __exit rpmsg_fini (void )
489
+ {
490
+ bus_unregister (& rpmsg_bus );
491
+ }
492
+ module_exit (rpmsg_fini );
493
+
494
+ MODULE_DESCRIPTION ("remote processor messaging bus" );
495
+ MODULE_LICENSE ("GPL v2" );
0 commit comments