@@ -34,6 +34,23 @@ struct i2c_atr_alias_pair {
34
34
u16 alias ;
35
35
};
36
36
37
+ /**
38
+ * struct i2c_atr_alias_pool - Pool of client aliases available for an ATR.
39
+ * @size: Total number of aliases
40
+ *
41
+ * @lock: Lock protecting @aliases and @use_mask
42
+ * @aliases: Array of aliases, must hold exactly @size elements
43
+ * @use_mask: Mask of used aliases
44
+ */
45
+ struct i2c_atr_alias_pool {
46
+ size_t size ;
47
+
48
+ /* Protects aliases and use_mask */
49
+ spinlock_t lock ;
50
+ u16 * aliases ;
51
+ unsigned long * use_mask ;
52
+ };
53
+
37
54
/**
38
55
* struct i2c_atr_chan - Data for a channel.
39
56
* @adap: The &struct i2c_adapter for the channel
@@ -67,10 +84,7 @@ struct i2c_atr_chan {
67
84
* @algo: The &struct i2c_algorithm for adapters
68
85
* @lock: Lock for the I2C bus segment (see &struct i2c_lock_operations)
69
86
* @max_adapters: Maximum number of adapters this I2C ATR can have
70
- * @num_aliases: Number of aliases in the aliases array
71
- * @aliases: The aliases array
72
- * @alias_mask_lock: Lock protecting alias_use_mask
73
- * @alias_use_mask: Bitmask for used aliases in aliases array
87
+ * @alias_pool: Pool of available client aliases
74
88
* @i2c_nb: Notifier for remote client add & del events
75
89
* @adapter: Array of adapters
76
90
*/
@@ -86,17 +100,54 @@ struct i2c_atr {
86
100
struct mutex lock ;
87
101
int max_adapters ;
88
102
89
- size_t num_aliases ;
90
- const u16 * aliases ;
91
- /* Protects alias_use_mask */
92
- spinlock_t alias_mask_lock ;
93
- unsigned long * alias_use_mask ;
103
+ struct i2c_atr_alias_pool * alias_pool ;
94
104
95
105
struct notifier_block i2c_nb ;
96
106
97
107
struct i2c_adapter * adapter [] __counted_by (max_adapters );
98
108
};
99
109
110
+ static struct i2c_atr_alias_pool * i2c_atr_alloc_alias_pool (size_t num_aliases )
111
+ {
112
+ struct i2c_atr_alias_pool * alias_pool ;
113
+ int ret ;
114
+
115
+ alias_pool = kzalloc (sizeof (* alias_pool ), GFP_KERNEL );
116
+ if (!alias_pool )
117
+ return ERR_PTR (- ENOMEM );
118
+
119
+ alias_pool -> size = num_aliases ;
120
+
121
+ alias_pool -> aliases = kcalloc (num_aliases , sizeof (* alias_pool -> aliases ), GFP_KERNEL );
122
+ if (!alias_pool -> aliases ) {
123
+ ret = - ENOMEM ;
124
+ goto err_free_alias_pool ;
125
+ }
126
+
127
+ alias_pool -> use_mask = bitmap_zalloc (num_aliases , GFP_KERNEL );
128
+ if (!alias_pool -> use_mask ) {
129
+ ret = - ENOMEM ;
130
+ goto err_free_aliases ;
131
+ }
132
+
133
+ spin_lock_init (& alias_pool -> lock );
134
+
135
+ return alias_pool ;
136
+
137
+ err_free_aliases :
138
+ kfree (alias_pool -> aliases );
139
+ err_free_alias_pool :
140
+ kfree (alias_pool );
141
+ return ERR_PTR (ret );
142
+ }
143
+
144
+ static void i2c_atr_free_alias_pool (struct i2c_atr_alias_pool * alias_pool )
145
+ {
146
+ bitmap_free (alias_pool -> use_mask );
147
+ kfree (alias_pool -> aliases );
148
+ kfree (alias_pool );
149
+ }
150
+
100
151
static struct i2c_atr_alias_pair *
101
152
i2c_atr_find_mapping_by_addr (const struct list_head * list , u16 phys_addr )
102
153
{
@@ -259,44 +310,42 @@ static const struct i2c_lock_operations i2c_atr_lock_ops = {
259
310
.unlock_bus = i2c_atr_unlock_bus ,
260
311
};
261
312
262
- static int i2c_atr_reserve_alias (struct i2c_atr * atr )
313
+ static int i2c_atr_reserve_alias (struct i2c_atr_alias_pool * alias_pool )
263
314
{
264
315
unsigned long idx ;
316
+ u16 alias ;
265
317
266
- spin_lock (& atr -> alias_mask_lock );
318
+ spin_lock (& alias_pool -> lock );
267
319
268
- idx = find_first_zero_bit (atr -> alias_use_mask , atr -> num_aliases );
269
- if (idx >= atr -> num_aliases ) {
270
- spin_unlock (& atr -> alias_mask_lock );
271
- dev_err (atr -> dev , "failed to find a free alias\n" );
320
+ idx = find_first_zero_bit (alias_pool -> use_mask , alias_pool -> size );
321
+ if (idx >= alias_pool -> size ) {
322
+ spin_unlock (& alias_pool -> lock );
272
323
return - EBUSY ;
273
324
}
274
325
275
- set_bit (idx , atr -> alias_use_mask );
326
+ set_bit (idx , alias_pool -> use_mask );
276
327
277
- spin_unlock ( & atr -> alias_mask_lock ) ;
328
+ alias = alias_pool -> aliases [ idx ] ;
278
329
279
- return atr -> aliases [idx ];
330
+ spin_unlock (& alias_pool -> lock );
331
+ return alias ;
280
332
}
281
333
282
- static void i2c_atr_release_alias (struct i2c_atr * atr , u16 alias )
334
+ static void i2c_atr_release_alias (struct i2c_atr_alias_pool * alias_pool , u16 alias )
283
335
{
284
336
unsigned int idx ;
285
337
286
- spin_lock (& atr -> alias_mask_lock );
338
+ spin_lock (& alias_pool -> lock );
287
339
288
- for (idx = 0 ; idx < atr -> num_aliases ; ++ idx ) {
289
- if (atr -> aliases [idx ] == alias ) {
290
- clear_bit (idx , atr -> alias_use_mask );
291
- spin_unlock (& atr -> alias_mask_lock );
340
+ for (idx = 0 ; idx < alias_pool -> size ; ++ idx ) {
341
+ if (alias_pool -> aliases [idx ] == alias ) {
342
+ clear_bit (idx , alias_pool -> use_mask );
343
+ spin_unlock (& alias_pool -> lock );
292
344
return ;
293
345
}
294
346
}
295
347
296
- spin_unlock (& atr -> alias_mask_lock );
297
-
298
- /* This should never happen */
299
- dev_warn (atr -> dev , "Unable to find mapped alias\n" );
348
+ spin_unlock (& alias_pool -> lock );
300
349
}
301
350
302
351
static int i2c_atr_attach_addr (struct i2c_adapter * adapter ,
@@ -308,9 +357,11 @@ static int i2c_atr_attach_addr(struct i2c_adapter *adapter,
308
357
u16 alias ;
309
358
int ret ;
310
359
311
- ret = i2c_atr_reserve_alias (atr );
312
- if (ret < 0 )
360
+ ret = i2c_atr_reserve_alias (atr -> alias_pool );
361
+ if (ret < 0 ) {
362
+ dev_err (atr -> dev , "failed to find a free alias\n" );
313
363
return ret ;
364
+ }
314
365
315
366
alias = ret ;
316
367
@@ -336,7 +387,7 @@ static int i2c_atr_attach_addr(struct i2c_adapter *adapter,
336
387
err_free :
337
388
kfree (c2a );
338
389
err_release_alias :
339
- i2c_atr_release_alias (atr , alias );
390
+ i2c_atr_release_alias (atr -> alias_pool , alias );
340
391
341
392
return ret ;
342
393
}
@@ -357,7 +408,7 @@ static void i2c_atr_detach_addr(struct i2c_adapter *adapter,
357
408
return ;
358
409
}
359
410
360
- i2c_atr_release_alias (atr , c2a -> alias );
411
+ i2c_atr_release_alias (atr -> alias_pool , c2a -> alias );
361
412
362
413
dev_dbg (atr -> dev ,
363
414
"chan%u: detached alias 0x%02x from addr 0x%02x\n" ,
@@ -411,12 +462,11 @@ static int i2c_atr_bus_notifier_call(struct notifier_block *nb,
411
462
412
463
static int i2c_atr_parse_alias_pool (struct i2c_atr * atr )
413
464
{
465
+ struct i2c_atr_alias_pool * alias_pool ;
414
466
struct device * dev = atr -> dev ;
415
- unsigned long * alias_use_mask ;
416
467
size_t num_aliases ;
417
468
unsigned int i ;
418
469
u32 * aliases32 ;
419
- u16 * aliases16 ;
420
470
int ret ;
421
471
422
472
ret = fwnode_property_count_u32 (dev_fwnode (dev ), "i2c-alias-pool" );
@@ -428,12 +478,23 @@ static int i2c_atr_parse_alias_pool(struct i2c_atr *atr)
428
478
429
479
num_aliases = ret ;
430
480
431
- if (!num_aliases )
481
+ alias_pool = i2c_atr_alloc_alias_pool (num_aliases );
482
+ if (IS_ERR (alias_pool )) {
483
+ ret = PTR_ERR (alias_pool );
484
+ dev_err (dev , "Failed to allocate alias pool, err %d\n" , ret );
485
+ return ret ;
486
+ }
487
+
488
+ atr -> alias_pool = alias_pool ;
489
+
490
+ if (!alias_pool -> size )
432
491
return 0 ;
433
492
434
493
aliases32 = kcalloc (num_aliases , sizeof (* aliases32 ), GFP_KERNEL );
435
- if (!aliases32 )
436
- return - ENOMEM ;
494
+ if (!aliases32 ) {
495
+ ret = - ENOMEM ;
496
+ goto err_free_alias_pool ;
497
+ }
437
498
438
499
ret = fwnode_property_read_u32_array (dev_fwnode (dev ), "i2c-alias-pool" ,
439
500
aliases32 , num_aliases );
@@ -443,43 +504,27 @@ static int i2c_atr_parse_alias_pool(struct i2c_atr *atr)
443
504
goto err_free_aliases32 ;
444
505
}
445
506
446
- aliases16 = kcalloc (num_aliases , sizeof (* aliases16 ), GFP_KERNEL );
447
- if (!aliases16 ) {
448
- ret = - ENOMEM ;
449
- goto err_free_aliases32 ;
450
- }
451
-
452
507
for (i = 0 ; i < num_aliases ; i ++ ) {
453
508
if (!(aliases32 [i ] & 0xffff0000 )) {
454
- aliases16 [i ] = aliases32 [i ];
509
+ alias_pool -> aliases [i ] = aliases32 [i ];
455
510
continue ;
456
511
}
457
512
458
513
dev_err (dev , "Failed to parse 'i2c-alias-pool' property: I2C flags are not supported\n" );
459
514
ret = - EINVAL ;
460
- goto err_free_aliases16 ;
461
- }
462
-
463
- alias_use_mask = bitmap_zalloc (num_aliases , GFP_KERNEL );
464
- if (!alias_use_mask ) {
465
- ret = - ENOMEM ;
466
- goto err_free_aliases16 ;
515
+ goto err_free_aliases32 ;
467
516
}
468
517
469
518
kfree (aliases32 );
470
519
471
- atr -> num_aliases = num_aliases ;
472
- atr -> aliases = aliases16 ;
473
- atr -> alias_use_mask = alias_use_mask ;
474
-
475
- dev_dbg (dev , "i2c-alias-pool has %zu aliases" , atr -> num_aliases );
520
+ dev_dbg (dev , "i2c-alias-pool has %zu aliases\n" , alias_pool -> size );
476
521
477
522
return 0 ;
478
523
479
- err_free_aliases16 :
480
- kfree (aliases16 );
481
524
err_free_aliases32 :
482
525
kfree (aliases32 );
526
+ err_free_alias_pool :
527
+ i2c_atr_free_alias_pool (alias_pool );
483
528
return ret ;
484
529
}
485
530
@@ -500,7 +545,6 @@ struct i2c_atr *i2c_atr_new(struct i2c_adapter *parent, struct device *dev,
500
545
return ERR_PTR (- ENOMEM );
501
546
502
547
mutex_init (& atr -> lock );
503
- spin_lock_init (& atr -> alias_mask_lock );
504
548
505
549
atr -> parent = parent ;
506
550
atr -> dev = dev ;
@@ -520,13 +564,12 @@ struct i2c_atr *i2c_atr_new(struct i2c_adapter *parent, struct device *dev,
520
564
atr -> i2c_nb .notifier_call = i2c_atr_bus_notifier_call ;
521
565
ret = bus_register_notifier (& i2c_bus_type , & atr -> i2c_nb );
522
566
if (ret )
523
- goto err_free_aliases ;
567
+ goto err_free_alias_pool ;
524
568
525
569
return atr ;
526
570
527
- err_free_aliases :
528
- bitmap_free (atr -> alias_use_mask );
529
- kfree (atr -> aliases );
571
+ err_free_alias_pool :
572
+ i2c_atr_free_alias_pool (atr -> alias_pool );
530
573
err_destroy_mutex :
531
574
mutex_destroy (& atr -> lock );
532
575
kfree (atr );
@@ -543,8 +586,7 @@ void i2c_atr_delete(struct i2c_atr *atr)
543
586
WARN_ON (atr -> adapter [i ]);
544
587
545
588
bus_unregister_notifier (& i2c_bus_type , & atr -> i2c_nb );
546
- bitmap_free (atr -> alias_use_mask );
547
- kfree (atr -> aliases );
589
+ i2c_atr_free_alias_pool (atr -> alias_pool );
548
590
mutex_destroy (& atr -> lock );
549
591
kfree (atr );
550
592
}
0 commit comments