@@ -37,13 +37,15 @@ struct i2c_atr_alias_pair {
37
37
/**
38
38
* struct i2c_atr_alias_pool - Pool of client aliases available for an ATR.
39
39
* @size: Total number of aliases
40
+ * @shared: Indicates if this alias pool is shared by multiple channels
40
41
*
41
42
* @lock: Lock protecting @aliases and @use_mask
42
43
* @aliases: Array of aliases, must hold exactly @size elements
43
44
* @use_mask: Mask of used aliases
44
45
*/
45
46
struct i2c_atr_alias_pool {
46
47
size_t size ;
48
+ bool shared ;
47
49
48
50
/* Protects aliases and use_mask */
49
51
spinlock_t lock ;
@@ -58,6 +60,8 @@ struct i2c_atr_alias_pool {
58
60
* @chan_id: The ID of this channel
59
61
* @alias_pairs: List of @struct i2c_atr_alias_pair containing the
60
62
* assigned aliases
63
+ * @alias_pool: Pool of available client aliases
64
+ *
61
65
* @orig_addrs_lock: Mutex protecting @orig_addrs
62
66
* @orig_addrs: Buffer used to store the original addresses during transmit
63
67
* @orig_addrs_size: Size of @orig_addrs
@@ -68,6 +72,7 @@ struct i2c_atr_chan {
68
72
u32 chan_id ;
69
73
70
74
struct list_head alias_pairs ;
75
+ struct i2c_atr_alias_pool * alias_pool ;
71
76
72
77
/* Lock orig_addrs during xfer */
73
78
struct mutex orig_addrs_lock ;
@@ -84,7 +89,7 @@ struct i2c_atr_chan {
84
89
* @algo: The &struct i2c_algorithm for adapters
85
90
* @lock: Lock for the I2C bus segment (see &struct i2c_lock_operations)
86
91
* @max_adapters: Maximum number of adapters this I2C ATR can have
87
- * @alias_pool: Pool of available client aliases
92
+ * @alias_pool: Optional common pool of available client aliases
88
93
* @i2c_nb: Notifier for remote client add & del events
89
94
* @adapter: Array of adapters
90
95
*/
@@ -107,7 +112,7 @@ struct i2c_atr {
107
112
struct i2c_adapter * adapter [] __counted_by (max_adapters );
108
113
};
109
114
110
- static struct i2c_atr_alias_pool * i2c_atr_alloc_alias_pool (size_t num_aliases )
115
+ static struct i2c_atr_alias_pool * i2c_atr_alloc_alias_pool (size_t num_aliases , bool shared )
111
116
{
112
117
struct i2c_atr_alias_pool * alias_pool ;
113
118
int ret ;
@@ -130,6 +135,8 @@ static struct i2c_atr_alias_pool *i2c_atr_alloc_alias_pool(size_t num_aliases)
130
135
goto err_free_aliases ;
131
136
}
132
137
138
+ alias_pool -> shared = shared ;
139
+
133
140
spin_lock_init (& alias_pool -> lock );
134
141
135
142
return alias_pool ;
@@ -357,7 +364,7 @@ static int i2c_atr_attach_addr(struct i2c_adapter *adapter,
357
364
u16 alias ;
358
365
int ret ;
359
366
360
- ret = i2c_atr_reserve_alias (atr -> alias_pool );
367
+ ret = i2c_atr_reserve_alias (chan -> alias_pool );
361
368
if (ret < 0 ) {
362
369
dev_err (atr -> dev , "failed to find a free alias\n" );
363
370
return ret ;
@@ -387,7 +394,7 @@ static int i2c_atr_attach_addr(struct i2c_adapter *adapter,
387
394
err_free :
388
395
kfree (c2a );
389
396
err_release_alias :
390
- i2c_atr_release_alias (atr -> alias_pool , alias );
397
+ i2c_atr_release_alias (chan -> alias_pool , alias );
391
398
392
399
return ret ;
393
400
}
@@ -408,7 +415,7 @@ static void i2c_atr_detach_addr(struct i2c_adapter *adapter,
408
415
return ;
409
416
}
410
417
411
- i2c_atr_release_alias (atr -> alias_pool , c2a -> alias );
418
+ i2c_atr_release_alias (chan -> alias_pool , c2a -> alias );
412
419
413
420
dev_dbg (atr -> dev ,
414
421
"chan%u: detached alias 0x%02x from addr 0x%02x\n" ,
@@ -469,16 +476,20 @@ static int i2c_atr_parse_alias_pool(struct i2c_atr *atr)
469
476
u32 * aliases32 ;
470
477
int ret ;
471
478
472
- ret = fwnode_property_count_u32 (dev_fwnode (dev ), "i2c-alias-pool" );
473
- if (ret < 0 ) {
474
- dev_err (dev , "Failed to count 'i2c-alias-pool' property: %d\n" ,
475
- ret );
476
- return ret ;
477
- }
479
+ if (!fwnode_property_present (dev_fwnode (dev ), "i2c-alias-pool" )) {
480
+ num_aliases = 0 ;
481
+ } else {
482
+ ret = fwnode_property_count_u32 (dev_fwnode (dev ), "i2c-alias-pool" );
483
+ if (ret < 0 ) {
484
+ dev_err (dev , "Failed to count 'i2c-alias-pool' property: %d\n" ,
485
+ ret );
486
+ return ret ;
487
+ }
478
488
479
- num_aliases = ret ;
489
+ num_aliases = ret ;
490
+ }
480
491
481
- alias_pool = i2c_atr_alloc_alias_pool (num_aliases );
492
+ alias_pool = i2c_atr_alloc_alias_pool (num_aliases , true );
482
493
if (IS_ERR (alias_pool )) {
483
494
ret = PTR_ERR (alias_pool );
484
495
dev_err (dev , "Failed to allocate alias pool, err %d\n" , ret );
@@ -592,15 +603,15 @@ void i2c_atr_delete(struct i2c_atr *atr)
592
603
}
593
604
EXPORT_SYMBOL_NS_GPL (i2c_atr_delete , "I2C_ATR" );
594
605
595
- int i2c_atr_add_adapter (struct i2c_atr * atr , u32 chan_id ,
596
- struct device * adapter_parent ,
597
- struct fwnode_handle * bus_handle )
606
+ int i2c_atr_add_adapter (struct i2c_atr * atr , struct i2c_atr_adap_desc * desc )
598
607
{
608
+ struct fwnode_handle * bus_handle = desc -> bus_handle ;
599
609
struct i2c_adapter * parent = atr -> parent ;
610
+ char symlink_name [ATR_MAX_SYMLINK_LEN ];
600
611
struct device * dev = atr -> dev ;
612
+ u32 chan_id = desc -> chan_id ;
601
613
struct i2c_atr_chan * chan ;
602
- char symlink_name [ATR_MAX_SYMLINK_LEN ];
603
- int ret ;
614
+ int ret , idx ;
604
615
605
616
if (chan_id >= atr -> max_adapters ) {
606
617
dev_err (dev , "No room for more i2c-atr adapters\n" );
@@ -616,8 +627,8 @@ int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
616
627
if (!chan )
617
628
return - ENOMEM ;
618
629
619
- if (!adapter_parent )
620
- adapter_parent = dev ;
630
+ if (!desc -> parent )
631
+ desc -> parent = dev ;
621
632
622
633
chan -> atr = atr ;
623
634
chan -> chan_id = chan_id ;
@@ -629,7 +640,7 @@ int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
629
640
chan -> adap .owner = THIS_MODULE ;
630
641
chan -> adap .algo = & atr -> algo ;
631
642
chan -> adap .algo_data = chan ;
632
- chan -> adap .dev .parent = adapter_parent ;
643
+ chan -> adap .dev .parent = desc -> parent ;
633
644
chan -> adap .retries = parent -> retries ;
634
645
chan -> adap .timeout = parent -> timeout ;
635
646
chan -> adap .quirks = parent -> quirks ;
@@ -656,13 +667,26 @@ int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
656
667
fwnode_handle_put (atr_node );
657
668
}
658
669
670
+ if (desc -> num_aliases > 0 ) {
671
+ chan -> alias_pool = i2c_atr_alloc_alias_pool (desc -> num_aliases , false);
672
+ if (IS_ERR (chan -> alias_pool )) {
673
+ ret = PTR_ERR (chan -> alias_pool );
674
+ goto err_fwnode_put ;
675
+ }
676
+
677
+ for (idx = 0 ; idx < desc -> num_aliases ; idx ++ )
678
+ chan -> alias_pool -> aliases [idx ] = desc -> aliases [idx ];
679
+ } else {
680
+ chan -> alias_pool = atr -> alias_pool ;
681
+ }
682
+
659
683
atr -> adapter [chan_id ] = & chan -> adap ;
660
684
661
685
ret = i2c_add_adapter (& chan -> adap );
662
686
if (ret ) {
663
687
dev_err (dev , "failed to add atr-adapter %u (error=%d)\n" ,
664
688
chan_id , ret );
665
- goto err_fwnode_put ;
689
+ goto err_free_alias_pool ;
666
690
}
667
691
668
692
snprintf (symlink_name , sizeof (symlink_name ), "channel-%u" ,
@@ -679,6 +703,9 @@ int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
679
703
680
704
return 0 ;
681
705
706
+ err_free_alias_pool :
707
+ if (!chan -> alias_pool -> shared )
708
+ i2c_atr_free_alias_pool (chan -> alias_pool );
682
709
err_fwnode_put :
683
710
fwnode_handle_put (dev_fwnode (& chan -> adap .dev ));
684
711
mutex_destroy (& chan -> orig_addrs_lock );
@@ -711,6 +738,9 @@ void i2c_atr_del_adapter(struct i2c_atr *atr, u32 chan_id)
711
738
712
739
i2c_del_adapter (adap );
713
740
741
+ if (!chan -> alias_pool -> shared )
742
+ i2c_atr_free_alias_pool (chan -> alias_pool );
743
+
714
744
atr -> adapter [chan_id ] = NULL ;
715
745
716
746
fwnode_handle_put (fwnode );
0 commit comments