Skip to content

Commit 24960bd

Browse files
rgantoisWolfram Sang
authored andcommitted
i2c: move ATR alias pool to a separate struct
Each I2C address translator (ATR) has a pool of client aliases which can be used as translation targets. Some ATRs have a single alias pool shared by all downstream channels, while others have a separate alias pool for each channel. Currently, this alias pool is represented by the "aliases", "num_aliases", and "use_mask" fields of struct i2c_atr. In preparation for adding per-channel alias pool support, move the "aliases", "num_aliases", "use_mask" and associated lock to a new struct called "struct alias_pool". Tested-by: Tomi Valkeinen <[email protected]> Signed-off-by: Romain Gantois <[email protected]> Acked-by: Andi Shyti <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 818bd48 commit 24960bd

File tree

1 file changed

+107
-65
lines changed

1 file changed

+107
-65
lines changed

drivers/i2c/i2c-atr.c

Lines changed: 107 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@ struct i2c_atr_alias_pair {
3434
u16 alias;
3535
};
3636

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+
3754
/**
3855
* struct i2c_atr_chan - Data for a channel.
3956
* @adap: The &struct i2c_adapter for the channel
@@ -67,10 +84,7 @@ struct i2c_atr_chan {
6784
* @algo: The &struct i2c_algorithm for adapters
6885
* @lock: Lock for the I2C bus segment (see &struct i2c_lock_operations)
6986
* @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
7488
* @i2c_nb: Notifier for remote client add & del events
7589
* @adapter: Array of adapters
7690
*/
@@ -86,17 +100,54 @@ struct i2c_atr {
86100
struct mutex lock;
87101
int max_adapters;
88102

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;
94104

95105
struct notifier_block i2c_nb;
96106

97107
struct i2c_adapter *adapter[] __counted_by(max_adapters);
98108
};
99109

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+
100151
static struct i2c_atr_alias_pair *
101152
i2c_atr_find_mapping_by_addr(const struct list_head *list, u16 phys_addr)
102153
{
@@ -259,44 +310,42 @@ static const struct i2c_lock_operations i2c_atr_lock_ops = {
259310
.unlock_bus = i2c_atr_unlock_bus,
260311
};
261312

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)
263314
{
264315
unsigned long idx;
316+
u16 alias;
265317

266-
spin_lock(&atr->alias_mask_lock);
318+
spin_lock(&alias_pool->lock);
267319

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);
272323
return -EBUSY;
273324
}
274325

275-
set_bit(idx, atr->alias_use_mask);
326+
set_bit(idx, alias_pool->use_mask);
276327

277-
spin_unlock(&atr->alias_mask_lock);
328+
alias = alias_pool->aliases[idx];
278329

279-
return atr->aliases[idx];
330+
spin_unlock(&alias_pool->lock);
331+
return alias;
280332
}
281333

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)
283335
{
284336
unsigned int idx;
285337

286-
spin_lock(&atr->alias_mask_lock);
338+
spin_lock(&alias_pool->lock);
287339

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);
292344
return;
293345
}
294346
}
295347

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);
300349
}
301350

302351
static int i2c_atr_attach_addr(struct i2c_adapter *adapter,
@@ -308,9 +357,11 @@ static int i2c_atr_attach_addr(struct i2c_adapter *adapter,
308357
u16 alias;
309358
int ret;
310359

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");
313363
return ret;
364+
}
314365

315366
alias = ret;
316367

@@ -336,7 +387,7 @@ static int i2c_atr_attach_addr(struct i2c_adapter *adapter,
336387
err_free:
337388
kfree(c2a);
338389
err_release_alias:
339-
i2c_atr_release_alias(atr, alias);
390+
i2c_atr_release_alias(atr->alias_pool, alias);
340391

341392
return ret;
342393
}
@@ -357,7 +408,7 @@ static void i2c_atr_detach_addr(struct i2c_adapter *adapter,
357408
return;
358409
}
359410

360-
i2c_atr_release_alias(atr, c2a->alias);
411+
i2c_atr_release_alias(atr->alias_pool, c2a->alias);
361412

362413
dev_dbg(atr->dev,
363414
"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,
411462

412463
static int i2c_atr_parse_alias_pool(struct i2c_atr *atr)
413464
{
465+
struct i2c_atr_alias_pool *alias_pool;
414466
struct device *dev = atr->dev;
415-
unsigned long *alias_use_mask;
416467
size_t num_aliases;
417468
unsigned int i;
418469
u32 *aliases32;
419-
u16 *aliases16;
420470
int ret;
421471

422472
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)
428478

429479
num_aliases = ret;
430480

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)
432491
return 0;
433492

434493
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+
}
437498

438499
ret = fwnode_property_read_u32_array(dev_fwnode(dev), "i2c-alias-pool",
439500
aliases32, num_aliases);
@@ -443,43 +504,27 @@ static int i2c_atr_parse_alias_pool(struct i2c_atr *atr)
443504
goto err_free_aliases32;
444505
}
445506

446-
aliases16 = kcalloc(num_aliases, sizeof(*aliases16), GFP_KERNEL);
447-
if (!aliases16) {
448-
ret = -ENOMEM;
449-
goto err_free_aliases32;
450-
}
451-
452507
for (i = 0; i < num_aliases; i++) {
453508
if (!(aliases32[i] & 0xffff0000)) {
454-
aliases16[i] = aliases32[i];
509+
alias_pool->aliases[i] = aliases32[i];
455510
continue;
456511
}
457512

458513
dev_err(dev, "Failed to parse 'i2c-alias-pool' property: I2C flags are not supported\n");
459514
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;
467516
}
468517

469518
kfree(aliases32);
470519

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);
476521

477522
return 0;
478523

479-
err_free_aliases16:
480-
kfree(aliases16);
481524
err_free_aliases32:
482525
kfree(aliases32);
526+
err_free_alias_pool:
527+
i2c_atr_free_alias_pool(alias_pool);
483528
return ret;
484529
}
485530

@@ -500,7 +545,6 @@ struct i2c_atr *i2c_atr_new(struct i2c_adapter *parent, struct device *dev,
500545
return ERR_PTR(-ENOMEM);
501546

502547
mutex_init(&atr->lock);
503-
spin_lock_init(&atr->alias_mask_lock);
504548

505549
atr->parent = parent;
506550
atr->dev = dev;
@@ -520,13 +564,12 @@ struct i2c_atr *i2c_atr_new(struct i2c_adapter *parent, struct device *dev,
520564
atr->i2c_nb.notifier_call = i2c_atr_bus_notifier_call;
521565
ret = bus_register_notifier(&i2c_bus_type, &atr->i2c_nb);
522566
if (ret)
523-
goto err_free_aliases;
567+
goto err_free_alias_pool;
524568

525569
return atr;
526570

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);
530573
err_destroy_mutex:
531574
mutex_destroy(&atr->lock);
532575
kfree(atr);
@@ -543,8 +586,7 @@ void i2c_atr_delete(struct i2c_atr *atr)
543586
WARN_ON(atr->adapter[i]);
544587

545588
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);
548590
mutex_destroy(&atr->lock);
549591
kfree(atr);
550592
}

0 commit comments

Comments
 (0)