]>
git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/block/blkcache.c
2 * Copyright (C) Nelson Integration, LLC 2016
3 * Author: Eric Nelson<eric@nelint.com>
5 * SPDX-License-Identifier: GPL-2.0+
12 #include <linux/ctype.h>
13 #include <linux/list.h>
15 struct block_cache_node
{
25 static LIST_HEAD(block_cache
);
27 static struct block_cache_stats _stats
= {
28 .max_blocks_per_entry
= 2,
32 static struct block_cache_node
*cache_find(int iftype
, int devnum
,
33 lbaint_t start
, lbaint_t blkcnt
,
36 struct block_cache_node
*node
;
38 list_for_each_entry(node
, &block_cache
, lh
)
39 if ((node
->iftype
== iftype
) &&
40 (node
->devnum
== devnum
) &&
41 (node
->blksz
== blksz
) &&
42 (node
->start
<= start
) &&
43 (node
->start
+ node
->blkcnt
>= start
+ blkcnt
)) {
44 if (block_cache
.next
!= &node
->lh
) {
45 /* maintain MRU ordering */
47 list_add(&node
->lh
, &block_cache
);
54 int blkcache_read(int iftype
, int devnum
,
55 lbaint_t start
, lbaint_t blkcnt
,
56 unsigned long blksz
, void *buffer
)
58 struct block_cache_node
*node
= cache_find(iftype
, devnum
, start
,
61 const char *src
= node
->cache
+ (start
- node
->start
) * blksz
;
62 memcpy(buffer
, src
, blksz
* blkcnt
);
63 debug("hit: start " LBAF
", count " LBAFU
"\n",
69 debug("miss: start " LBAF
", count " LBAFU
"\n",
75 void blkcache_fill(int iftype
, int devnum
,
76 lbaint_t start
, lbaint_t blkcnt
,
77 unsigned long blksz
, void const *buffer
)
80 struct block_cache_node
*node
;
82 /* don't cache big stuff */
83 if (blkcnt
> _stats
.max_blocks_per_entry
)
86 if (_stats
.max_entries
== 0)
89 bytes
= blksz
* blkcnt
;
90 if (_stats
.max_entries
<= _stats
.entries
) {
92 node
= (struct block_cache_node
*)block_cache
.prev
;
95 debug("drop: start " LBAF
", count " LBAFU
"\n",
96 node
->start
, node
->blkcnt
);
97 if (node
->blkcnt
* node
->blksz
< bytes
) {
102 node
= malloc(sizeof(*node
));
109 node
->cache
= malloc(bytes
);
116 debug("fill: start " LBAF
", count " LBAFU
"\n",
119 node
->iftype
= iftype
;
120 node
->devnum
= devnum
;
122 node
->blkcnt
= blkcnt
;
124 memcpy(node
->cache
, buffer
, bytes
);
125 list_add(&node
->lh
, &block_cache
);
129 void blkcache_invalidate(int iftype
, int devnum
)
131 struct list_head
*entry
, *n
;
132 struct block_cache_node
*node
;
134 list_for_each_safe(entry
, n
, &block_cache
) {
135 node
= (struct block_cache_node
*)entry
;
136 if ((node
->iftype
== iftype
) &&
137 (node
->devnum
== devnum
)) {
146 void blkcache_configure(unsigned blocks
, unsigned entries
)
148 struct block_cache_node
*node
;
149 if ((blocks
!= _stats
.max_blocks_per_entry
) ||
150 (entries
!= _stats
.max_entries
)) {
151 /* invalidate cache */
152 while (!list_empty(&block_cache
)) {
153 node
= (struct block_cache_node
*)block_cache
.next
;
161 _stats
.max_blocks_per_entry
= blocks
;
162 _stats
.max_entries
= entries
;
168 void blkcache_stats(struct block_cache_stats
*stats
)
170 memcpy(stats
, &_stats
, sizeof(*stats
));