Skip to content

Commit c6b570d

Browse files
pH5broonie
authored andcommitted
regmap: introduce regmap_name to fix syscon regmap trace events
This patch fixes a NULL pointer dereference when enabling regmap event tracing in the presence of a syscon regmap, introduced by commit bdb0066 ("mfd: syscon: Decouple syscon interface from platform devices"). That patch introduced syscon regmaps that have their dev field set to NULL. The regmap trace events expect it to point to a valid struct device and feed it to dev_name(): $ echo 1 > /sys/kernel/debug/tracing/events/regmap/enable Unable to handle kernel NULL pointer dereference at virtual address 0000002c pgd = 80004000 [0000002c] *pgd=00000000 Internal error: Oops: 17 [#1] SMP ARM Modules linked in: coda videobuf2_vmalloc CPU: 0 PID: 304 Comm: kworker/0:2 Not tainted 4.0.0-rc2+ #9197 Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) Workqueue: events_freezable thermal_zone_device_check task: 9f25a200 ti: 9f1ee000 task.ti: 9f1ee000 PC is at ftrace_raw_event_regmap_block+0x3c/0xe4 LR is at _regmap_raw_read+0x1bc/0x1cc pc : [<803636e8>] lr : [<80365f2c>] psr: 600f0093 sp : 9f1efd78 ip : 9f1efdb8 fp : 9f1efdb4 r10: 00000004 r9 : 00000001 r8 : 00000001 r7 : 00000180 r6 : 00000000 r5 : 9f00e3c0 r4 : 00000003 r3 : 00000001 r2 : 00000180 r1 : 00000000 r0 : 9f00e3c0 Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel Control: 10c5387d Table: 2d91004a DAC: 00000015 Process kworker/0:2 (pid: 304, stack limit = 0x9f1ee210) Stack: (0x9f1efd78 to 0x9f1f0000) fd60: 9f1efda4 9f1efd88 fd80: 800708c0 805f9510 80927140 800f0013 9f1fc800 9eb2f490 00000000 00000180 fda0: 808e3840 00000001 9f1efdfc 9f1efdb8 80365f2c 803636b8 805f8958 800708e0 fdc0: a00f0013 803636ac 9f16de00 00000180 80927140 9f1fc800 9f1fc800 9f1efe6c fde0: 9f1efe6c 9f732400 00000000 00000000 9f1efe1c 9f1efe00 80365f70 80365d7c fe00: 80365f3c 9f1fc800 9f1fc800 00000180 9f1efe44 9f1efe20 803656a4 80365f48 fe20: 9f1fc800 00000180 9f1efe6c 9f1efe6c 9f732400 00000000 9f1efe64 9f1efe48 fe40: 803657bc 80365634 00000001 9e95f910 9f1fc800 9f1efeb4 9f1efe8c 9f1efe68 fe60: 80452ac0 80365778 9f1efe8c 9f1efe78 9e93d400 9e93d5e8 9f1efeb4 9f72ef40 fe80: 9f1efeac 9f1efe90 8044e11c 80452998 8045298c 9e93d608 9e93d400 808e1978 fea0: 9f1efecc 9f1efeb0 8044fd14 8044e0d0 ffffffff 9f25a200 9e93d608 9e481380 fec0: 9f1efedc 9f1efed0 8044fde8 8044fcec 9f1eff1c 9f1efee0 80038d50 8044fdd8 fee0: 9f1ee020 9f72ef40 9e481398 00000000 00000008 9f72ef54 9f1ee020 9f72ef40 ff00: 9e481398 9e481380 00000008 9f72ef40 9f1eff5c 9f1eff20 80039754 80038bfc ff20: 00000000 9e481380 80894100 808e1662 00000000 9e4f2ec0 00000000 9e481380 ff40: 800396f8 00000000 00000000 00000000 9f1effac 9f1eff60 8003e020 80039704 ff60: ffffffff 00000000 ffffffff 9e481380 00000000 00000000 9f1eff78 9f1eff78 ff80: 00000000 00000000 9f1eff88 9f1eff88 9e4f2ec0 8003df30 00000000 00000000 ffa0: 00000000 9f1effb0 8000eb60 8003df3c 00000000 00000000 00000000 00000000 ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 ffffffff ffffffff Backtrace: [<803636ac>] (ftrace_raw_event_regmap_block) from [<80365f2c>] (_regmap_raw_read+0x1bc/0x1cc) r9:00000001 r8:808e3840 r7:00000180 r6:00000000 r5:9eb2f490 r4:9f1fc800 [<80365d70>] (_regmap_raw_read) from [<80365f70>] (_regmap_bus_read+0x34/0x6c) r10:00000000 r9:00000000 r8:9f732400 r7:9f1efe6c r6:9f1efe6c r5:9f1fc800 r4:9f1fc800 [<80365f3c>] (_regmap_bus_read) from [<803656a4>] (_regmap_read+0x7c/0x144) r6:00000180 r5:9f1fc800 r4:9f1fc800 r3:80365f3c [<80365628>] (_regmap_read) from [<803657bc>] (regmap_read+0x50/0x70) r9:00000000 r8:9f732400 r7:9f1efe6c r6:9f1efe6c r5:00000180 r4:9f1fc800 [<8036576c>] (regmap_read) from [<80452ac0>] (imx_get_temp+0x134/0x1a4) r6:9f1efeb4 r5:9f1fc800 r4:9e95f910 r3:00000001 [<8045298c>] (imx_get_temp) from [<8044e11c>] (thermal_zone_get_temp+0x58/0x74) r7:9f72ef40 r6:9f1efeb4 r5:9e93d5e8 r4:9e93d400 [<8044e0c4>] (thermal_zone_get_temp) from [<8044fd14>] (thermal_zone_device_update+0x34/0xec) r6:808e1978 r5:9e93d400 r4:9e93d608 r3:8045298c [<8044fce0>] (thermal_zone_device_update) from [<8044fde8>] (thermal_zone_device_check+0x1c/0x20) r5:9e481380 r4:9e93d608 [<8044fdcc>] (thermal_zone_device_check) from [<80038d50>] (process_one_work+0x160/0x3d4) [<80038bf0>] (process_one_work) from [<80039754>] (worker_thread+0x5c/0x4f4) r10:9f72ef40 r9:00000008 r8:9e481380 r7:9e481398 r6:9f72ef40 r5:9f1ee020 r4:9f72ef54 [<800396f8>] (worker_thread) from [<8003e020>] (kthread+0xf0/0x108) r10:00000000 r9:00000000 r8:00000000 r7:800396f8 r6:9e481380 r5:00000000 r4:9e4f2ec0 [<8003df30>] (kthread) from [<8000eb60>] (ret_from_fork+0x14/0x34) r7:00000000 r6:00000000 r5:8003df30 r4:9e4f2ec0 Code: e3140040 1a00001a e3140020 1a00001 (e596002c) ---[ end trace 193c15c2494ec960 ]--- Fixes: bdb0066 (mfd: syscon: Decouple syscon interface from platform devices) Signed-off-by: Philipp Zabel <[email protected]> Signed-off-by: Mark Brown <[email protected]> Cc: [email protected]
1 parent c517d83 commit c6b570d

File tree

4 files changed

+91
-88
lines changed

4 files changed

+91
-88
lines changed

drivers/base/regmap/internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,4 +243,12 @@ extern struct regcache_ops regcache_rbtree_ops;
243243
extern struct regcache_ops regcache_lzo_ops;
244244
extern struct regcache_ops regcache_flat_ops;
245245

246+
static inline const char *regmap_name(const struct regmap *map)
247+
{
248+
if (map->dev)
249+
return dev_name(map->dev);
250+
251+
return map->name;
252+
}
253+
246254
#endif

drivers/base/regmap/regcache.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ int regcache_read(struct regmap *map,
218218
ret = map->cache_ops->read(map, reg, value);
219219

220220
if (ret == 0)
221-
trace_regmap_reg_read_cache(map->dev, reg, *value);
221+
trace_regmap_reg_read_cache(map, reg, *value);
222222

223223
return ret;
224224
}
@@ -311,7 +311,7 @@ int regcache_sync(struct regmap *map)
311311
dev_dbg(map->dev, "Syncing %s cache\n",
312312
map->cache_ops->name);
313313
name = map->cache_ops->name;
314-
trace_regcache_sync(map->dev, name, "start");
314+
trace_regcache_sync(map, name, "start");
315315

316316
if (!map->cache_dirty)
317317
goto out;
@@ -346,7 +346,7 @@ int regcache_sync(struct regmap *map)
346346

347347
regmap_async_complete(map);
348348

349-
trace_regcache_sync(map->dev, name, "stop");
349+
trace_regcache_sync(map, name, "stop");
350350

351351
return ret;
352352
}
@@ -381,7 +381,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
381381
name = map->cache_ops->name;
382382
dev_dbg(map->dev, "Syncing %s cache from %d-%d\n", name, min, max);
383383

384-
trace_regcache_sync(map->dev, name, "start region");
384+
trace_regcache_sync(map, name, "start region");
385385

386386
if (!map->cache_dirty)
387387
goto out;
@@ -401,7 +401,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
401401

402402
regmap_async_complete(map);
403403

404-
trace_regcache_sync(map->dev, name, "stop region");
404+
trace_regcache_sync(map, name, "stop region");
405405

406406
return ret;
407407
}
@@ -428,7 +428,7 @@ int regcache_drop_region(struct regmap *map, unsigned int min,
428428

429429
map->lock(map->lock_arg);
430430

431-
trace_regcache_drop_region(map->dev, min, max);
431+
trace_regcache_drop_region(map, min, max);
432432

433433
ret = map->cache_ops->drop(map, min, max);
434434

@@ -455,7 +455,7 @@ void regcache_cache_only(struct regmap *map, bool enable)
455455
map->lock(map->lock_arg);
456456
WARN_ON(map->cache_bypass && enable);
457457
map->cache_only = enable;
458-
trace_regmap_cache_only(map->dev, enable);
458+
trace_regmap_cache_only(map, enable);
459459
map->unlock(map->lock_arg);
460460
}
461461
EXPORT_SYMBOL_GPL(regcache_cache_only);
@@ -493,7 +493,7 @@ void regcache_cache_bypass(struct regmap *map, bool enable)
493493
map->lock(map->lock_arg);
494494
WARN_ON(map->cache_only && enable);
495495
map->cache_bypass = enable;
496-
trace_regmap_cache_bypass(map->dev, enable);
496+
trace_regmap_cache_bypass(map, enable);
497497
map->unlock(map->lock_arg);
498498
}
499499
EXPORT_SYMBOL_GPL(regcache_cache_bypass);

drivers/base/regmap/regmap.c

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
12811281
if (map->async && map->bus->async_write) {
12821282
struct regmap_async *async;
12831283

1284-
trace_regmap_async_write_start(map->dev, reg, val_len);
1284+
trace_regmap_async_write_start(map, reg, val_len);
12851285

12861286
spin_lock_irqsave(&map->async_lock, flags);
12871287
async = list_first_entry_or_null(&map->async_free,
@@ -1339,8 +1339,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
13391339
return ret;
13401340
}
13411341

1342-
trace_regmap_hw_write_start(map->dev, reg,
1343-
val_len / map->format.val_bytes);
1342+
trace_regmap_hw_write_start(map, reg, val_len / map->format.val_bytes);
13441343

13451344
/* If we're doing a single register write we can probably just
13461345
* send the work_buf directly, otherwise try to do a gather
@@ -1372,8 +1371,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
13721371
kfree(buf);
13731372
}
13741373

1375-
trace_regmap_hw_write_done(map->dev, reg,
1376-
val_len / map->format.val_bytes);
1374+
trace_regmap_hw_write_done(map, reg, val_len / map->format.val_bytes);
13771375

13781376
return ret;
13791377
}
@@ -1407,12 +1405,12 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
14071405

14081406
map->format.format_write(map, reg, val);
14091407

1410-
trace_regmap_hw_write_start(map->dev, reg, 1);
1408+
trace_regmap_hw_write_start(map, reg, 1);
14111409

14121410
ret = map->bus->write(map->bus_context, map->work_buf,
14131411
map->format.buf_size);
14141412

1415-
trace_regmap_hw_write_done(map->dev, reg, 1);
1413+
trace_regmap_hw_write_done(map, reg, 1);
14161414

14171415
return ret;
14181416
}
@@ -1470,7 +1468,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
14701468
dev_info(map->dev, "%x <= %x\n", reg, val);
14711469
#endif
14721470

1473-
trace_regmap_reg_write(map->dev, reg, val);
1471+
trace_regmap_reg_write(map, reg, val);
14741472

14751473
return map->reg_write(context, reg, val);
14761474
}
@@ -1773,7 +1771,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
17731771
for (i = 0; i < num_regs; i++) {
17741772
int reg = regs[i].reg;
17751773
int val = regs[i].def;
1776-
trace_regmap_hw_write_start(map->dev, reg, 1);
1774+
trace_regmap_hw_write_start(map, reg, 1);
17771775
map->format.format_reg(u8, reg, map->reg_shift);
17781776
u8 += reg_bytes + pad_bytes;
17791777
map->format.format_val(u8, val, 0);
@@ -1788,7 +1786,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
17881786

17891787
for (i = 0; i < num_regs; i++) {
17901788
int reg = regs[i].reg;
1791-
trace_regmap_hw_write_done(map->dev, reg, 1);
1789+
trace_regmap_hw_write_done(map, reg, 1);
17921790
}
17931791
return ret;
17941792
}
@@ -2059,15 +2057,13 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
20592057
*/
20602058
u8[0] |= map->read_flag_mask;
20612059

2062-
trace_regmap_hw_read_start(map->dev, reg,
2063-
val_len / map->format.val_bytes);
2060+
trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
20642061

20652062
ret = map->bus->read(map->bus_context, map->work_buf,
20662063
map->format.reg_bytes + map->format.pad_bytes,
20672064
val, val_len);
20682065

2069-
trace_regmap_hw_read_done(map->dev, reg,
2070-
val_len / map->format.val_bytes);
2066+
trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes);
20712067

20722068
return ret;
20732069
}
@@ -2123,7 +2119,7 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
21232119
dev_info(map->dev, "%x => %x\n", reg, *val);
21242120
#endif
21252121

2126-
trace_regmap_reg_read(map->dev, reg, *val);
2122+
trace_regmap_reg_read(map, reg, *val);
21272123

21282124
if (!map->cache_bypass)
21292125
regcache_write(map, reg, *val);
@@ -2480,7 +2476,7 @@ void regmap_async_complete_cb(struct regmap_async *async, int ret)
24802476
struct regmap *map = async->map;
24812477
bool wake;
24822478

2483-
trace_regmap_async_io_complete(map->dev);
2479+
trace_regmap_async_io_complete(map);
24842480

24852481
spin_lock(&map->async_lock);
24862482
list_move(&async->list, &map->async_free);
@@ -2525,7 +2521,7 @@ int regmap_async_complete(struct regmap *map)
25252521
if (!map->bus || !map->bus->async_write)
25262522
return 0;
25272523

2528-
trace_regmap_async_complete_start(map->dev);
2524+
trace_regmap_async_complete_start(map);
25292525

25302526
wait_event(map->async_waitq, regmap_async_is_done(map));
25312527

@@ -2534,7 +2530,7 @@ int regmap_async_complete(struct regmap *map)
25342530
map->async_ret = 0;
25352531
spin_unlock_irqrestore(&map->async_lock, flags);
25362532

2537-
trace_regmap_async_complete_done(map->dev);
2533+
trace_regmap_async_complete_done(map);
25382534

25392535
return ret;
25402536
}

0 commit comments

Comments
 (0)