regcache-rbtree.c (c0cc6fe1d09e3f1baecbdf8922473c8e7d3a5317) regcache-rbtree.c (f01ee60fffa4dc6c77122121233a793f7f696e67)
1/*
2 * Register cache access API - rbtree caching support
3 *
4 * Copyright 2011 Wolfson Microelectronics plc
5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify

--- 25 unchanged lines hidden (view full) ---

34} __attribute__ ((packed));
35
36struct regcache_rbtree_ctx {
37 struct rb_root root;
38 struct regcache_rbtree_node *cached_rbnode;
39};
40
41static inline void regcache_rbtree_get_base_top_reg(
1/*
2 * Register cache access API - rbtree caching support
3 *
4 * Copyright 2011 Wolfson Microelectronics plc
5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify

--- 25 unchanged lines hidden (view full) ---

34} __attribute__ ((packed));
35
36struct regcache_rbtree_ctx {
37 struct rb_root root;
38 struct regcache_rbtree_node *cached_rbnode;
39};
40
41static inline void regcache_rbtree_get_base_top_reg(
42 struct regmap *map,
42 struct regcache_rbtree_node *rbnode,
43 unsigned int *base, unsigned int *top)
44{
45 *base = rbnode->base_reg;
43 struct regcache_rbtree_node *rbnode,
44 unsigned int *base, unsigned int *top)
45{
46 *base = rbnode->base_reg;
46 *top = rbnode->base_reg + rbnode->blklen - 1;
47 *top = rbnode->base_reg + ((rbnode->blklen - 1) * map->reg_stride);
47}
48
49static unsigned int regcache_rbtree_get_register(
50 struct regcache_rbtree_node *rbnode, unsigned int idx,
51 unsigned int word_size)
52{
53 return regcache_get_val(rbnode->block, idx, word_size);
54}

--- 10 unchanged lines hidden (view full) ---

65{
66 struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
67 struct rb_node *node;
68 struct regcache_rbtree_node *rbnode;
69 unsigned int base_reg, top_reg;
70
71 rbnode = rbtree_ctx->cached_rbnode;
72 if (rbnode) {
48}
49
50static unsigned int regcache_rbtree_get_register(
51 struct regcache_rbtree_node *rbnode, unsigned int idx,
52 unsigned int word_size)
53{
54 return regcache_get_val(rbnode->block, idx, word_size);
55}

--- 10 unchanged lines hidden (view full) ---

66{
67 struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
68 struct rb_node *node;
69 struct regcache_rbtree_node *rbnode;
70 unsigned int base_reg, top_reg;
71
72 rbnode = rbtree_ctx->cached_rbnode;
73 if (rbnode) {
73 regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
74 regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
75 &top_reg);
74 if (reg >= base_reg && reg <= top_reg)
75 return rbnode;
76 }
77
78 node = rbtree_ctx->root.rb_node;
79 while (node) {
80 rbnode = container_of(node, struct regcache_rbtree_node, node);
76 if (reg >= base_reg && reg <= top_reg)
77 return rbnode;
78 }
79
80 node = rbtree_ctx->root.rb_node;
81 while (node) {
82 rbnode = container_of(node, struct regcache_rbtree_node, node);
81 regcache_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
83 regcache_rbtree_get_base_top_reg(map, rbnode, &base_reg,
84 &top_reg);
82 if (reg >= base_reg && reg <= top_reg) {
83 rbtree_ctx->cached_rbnode = rbnode;
84 return rbnode;
85 } else if (reg > top_reg) {
86 node = node->rb_right;
87 } else if (reg < base_reg) {
88 node = node->rb_left;
89 }
90 }
91
92 return NULL;
93}
94
85 if (reg >= base_reg && reg <= top_reg) {
86 rbtree_ctx->cached_rbnode = rbnode;
87 return rbnode;
88 } else if (reg > top_reg) {
89 node = node->rb_right;
90 } else if (reg < base_reg) {
91 node = node->rb_left;
92 }
93 }
94
95 return NULL;
96}
97
95static int regcache_rbtree_insert(struct rb_root *root,
98static int regcache_rbtree_insert(struct regmap *map, struct rb_root *root,
96 struct regcache_rbtree_node *rbnode)
97{
98 struct rb_node **new, *parent;
99 struct regcache_rbtree_node *rbnode_tmp;
100 unsigned int base_reg_tmp, top_reg_tmp;
101 unsigned int base_reg;
102
103 parent = NULL;
104 new = &root->rb_node;
105 while (*new) {
106 rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
107 node);
108 /* base and top registers of the current rbnode */
99 struct regcache_rbtree_node *rbnode)
100{
101 struct rb_node **new, *parent;
102 struct regcache_rbtree_node *rbnode_tmp;
103 unsigned int base_reg_tmp, top_reg_tmp;
104 unsigned int base_reg;
105
106 parent = NULL;
107 new = &root->rb_node;
108 while (*new) {
109 rbnode_tmp = container_of(*new, struct regcache_rbtree_node,
110 node);
111 /* base and top registers of the current rbnode */
109 regcache_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
112 regcache_rbtree_get_base_top_reg(map, rbnode_tmp, &base_reg_tmp,
110 &top_reg_tmp);
111 /* base register of the rbnode to be added */
112 base_reg = rbnode->base_reg;
113 parent = *new;
114 /* if this register has already been inserted, just return */
115 if (base_reg >= base_reg_tmp &&
116 base_reg <= top_reg_tmp)
117 return 0;

--- 15 unchanged lines hidden (view full) ---

133{
134 struct regmap *map = s->private;
135 struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
136 struct regcache_rbtree_node *n;
137 struct rb_node *node;
138 unsigned int base, top;
139 int nodes = 0;
140 int registers = 0;
113 &top_reg_tmp);
114 /* base register of the rbnode to be added */
115 base_reg = rbnode->base_reg;
116 parent = *new;
117 /* if this register has already been inserted, just return */
118 if (base_reg >= base_reg_tmp &&
119 base_reg <= top_reg_tmp)
120 return 0;

--- 15 unchanged lines hidden (view full) ---

136{
137 struct regmap *map = s->private;
138 struct regcache_rbtree_ctx *rbtree_ctx = map->cache;
139 struct regcache_rbtree_node *n;
140 struct rb_node *node;
141 unsigned int base, top;
142 int nodes = 0;
143 int registers = 0;
141 int average;
144 int this_registers, average;
142
143 map->lock(map);
144
145 for (node = rb_first(&rbtree_ctx->root); node != NULL;
146 node = rb_next(node)) {
147 n = container_of(node, struct regcache_rbtree_node, node);
148
145
146 map->lock(map);
147
148 for (node = rb_first(&rbtree_ctx->root); node != NULL;
149 node = rb_next(node)) {
150 n = container_of(node, struct regcache_rbtree_node, node);
151
149 regcache_rbtree_get_base_top_reg(n, &base, &top);
150 seq_printf(s, "%x-%x (%d)\n", base, top, top - base + 1);
152 regcache_rbtree_get_base_top_reg(map, n, &base, &top);
153 this_registers = ((top - base) / map->reg_stride) + 1;
154 seq_printf(s, "%x-%x (%d)\n", base, top, this_registers);
151
152 nodes++;
155
156 nodes++;
153 registers += top - base + 1;
157 registers += this_registers;
154 }
155
156 if (nodes)
157 average = registers / nodes;
158 else
159 average = 0;
160
161 seq_printf(s, "%d nodes, %d registers, average %d registers\n",

--- 88 unchanged lines hidden (view full) ---

250static int regcache_rbtree_read(struct regmap *map,
251 unsigned int reg, unsigned int *value)
252{
253 struct regcache_rbtree_node *rbnode;
254 unsigned int reg_tmp;
255
256 rbnode = regcache_rbtree_lookup(map, reg);
257 if (rbnode) {
158 }
159
160 if (nodes)
161 average = registers / nodes;
162 else
163 average = 0;
164
165 seq_printf(s, "%d nodes, %d registers, average %d registers\n",

--- 88 unchanged lines hidden (view full) ---

254static int regcache_rbtree_read(struct regmap *map,
255 unsigned int reg, unsigned int *value)
256{
257 struct regcache_rbtree_node *rbnode;
258 unsigned int reg_tmp;
259
260 rbnode = regcache_rbtree_lookup(map, reg);
261 if (rbnode) {
258 reg_tmp = reg - rbnode->base_reg;
262 reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
259 *value = regcache_rbtree_get_register(rbnode, reg_tmp,
260 map->cache_word_size);
261 } else {
262 return -ENOENT;
263 }
264
265 return 0;
266}

--- 38 unchanged lines hidden (view full) ---

305 int ret;
306
307 rbtree_ctx = map->cache;
308 /* if we can't locate it in the cached rbnode we'll have
309 * to traverse the rbtree looking for it.
310 */
311 rbnode = regcache_rbtree_lookup(map, reg);
312 if (rbnode) {
263 *value = regcache_rbtree_get_register(rbnode, reg_tmp,
264 map->cache_word_size);
265 } else {
266 return -ENOENT;
267 }
268
269 return 0;
270}

--- 38 unchanged lines hidden (view full) ---

309 int ret;
310
311 rbtree_ctx = map->cache;
312 /* if we can't locate it in the cached rbnode we'll have
313 * to traverse the rbtree looking for it.
314 */
315 rbnode = regcache_rbtree_lookup(map, reg);
316 if (rbnode) {
313 reg_tmp = reg - rbnode->base_reg;
317 reg_tmp = (reg - rbnode->base_reg) / map->reg_stride;
314 val = regcache_rbtree_get_register(rbnode, reg_tmp,
315 map->cache_word_size);
316 if (val == value)
317 return 0;
318 regcache_rbtree_set_register(rbnode, reg_tmp, value,
319 map->cache_word_size);
320 } else {
321 /* look for an adjacent register to the one we are about to add */
322 for (node = rb_first(&rbtree_ctx->root); node;
323 node = rb_next(node)) {
318 val = regcache_rbtree_get_register(rbnode, reg_tmp,
319 map->cache_word_size);
320 if (val == value)
321 return 0;
322 regcache_rbtree_set_register(rbnode, reg_tmp, value,
323 map->cache_word_size);
324 } else {
325 /* look for an adjacent register to the one we are about to add */
326 for (node = rb_first(&rbtree_ctx->root); node;
327 node = rb_next(node)) {
324 rbnode_tmp = rb_entry(node, struct regcache_rbtree_node, node);
328 rbnode_tmp = rb_entry(node, struct regcache_rbtree_node,
329 node);
325 for (i = 0; i < rbnode_tmp->blklen; i++) {
330 for (i = 0; i < rbnode_tmp->blklen; i++) {
326 reg_tmp = rbnode_tmp->base_reg + i;
327 if (abs(reg_tmp - reg) != 1)
331 reg_tmp = rbnode_tmp->base_reg +
332 (i * map->reg_stride);
333 if (abs(reg_tmp - reg) != map->reg_stride)
328 continue;
329 /* decide where in the block to place our register */
334 continue;
335 /* decide where in the block to place our register */
330 if (reg_tmp + 1 == reg)
336 if (reg_tmp + map->reg_stride == reg)
331 pos = i + 1;
332 else
333 pos = i;
334 ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos,
335 reg, value,
336 map->cache_word_size);
337 if (ret)
338 return ret;

--- 13 unchanged lines hidden (view full) ---

352 rbnode->base_reg = reg;
353 rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
354 GFP_KERNEL);
355 if (!rbnode->block) {
356 kfree(rbnode);
357 return -ENOMEM;
358 }
359 regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
337 pos = i + 1;
338 else
339 pos = i;
340 ret = regcache_rbtree_insert_to_block(rbnode_tmp, pos,
341 reg, value,
342 map->cache_word_size);
343 if (ret)
344 return ret;

--- 13 unchanged lines hidden (view full) ---

358 rbnode->base_reg = reg;
359 rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
360 GFP_KERNEL);
361 if (!rbnode->block) {
362 kfree(rbnode);
363 return -ENOMEM;
364 }
365 regcache_rbtree_set_register(rbnode, 0, value, map->cache_word_size);
360 regcache_rbtree_insert(&rbtree_ctx->root, rbnode);
366 regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
361 rbtree_ctx->cached_rbnode = rbnode;
362 }
363
364 return 0;
365}
366
367static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
368 unsigned int max)

--- 23 unchanged lines hidden (view full) ---

392 base = 0;
393
394 if (max < rbnode->base_reg + rbnode->blklen)
395 end = rbnode->base_reg + rbnode->blklen - max;
396 else
397 end = rbnode->blklen;
398
399 for (i = base; i < end; i++) {
367 rbtree_ctx->cached_rbnode = rbnode;
368 }
369
370 return 0;
371}
372
373static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
374 unsigned int max)

--- 23 unchanged lines hidden (view full) ---

398 base = 0;
399
400 if (max < rbnode->base_reg + rbnode->blklen)
401 end = rbnode->base_reg + rbnode->blklen - max;
402 else
403 end = rbnode->blklen;
404
405 for (i = base; i < end; i++) {
400 regtmp = rbnode->base_reg + i;
406 regtmp = rbnode->base_reg + (i * map->reg_stride);
401 val = regcache_rbtree_get_register(rbnode, i,
402 map->cache_word_size);
403
404 /* Is this the hardware default? If so skip. */
405 ret = regcache_lookup_reg(map, regtmp);
406 if (ret >= 0 && val == map->reg_defaults[ret].def)
407 continue;
408

--- 22 unchanged lines hidden ---
407 val = regcache_rbtree_get_register(rbnode, i,
408 map->cache_word_size);
409
410 /* Is this the hardware default? If so skip. */
411 ret = regcache_lookup_reg(map, regtmp);
412 if (ret >= 0 && val == map->reg_defaults[ret].def)
413 continue;
414

--- 22 unchanged lines hidden ---