2 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include <linux/list.h>
23 #include <linux/rbtree.h>
25 /* AMAP Configuration Variable */
26 #define SMART_ALLOC_N_HOT_AU (5)
28 /* Allocating Destination (for smart allocator):
32 * #define ALLOC_COLD_ALIGNED (1)
33 * #define ALLOC_COLD_PACKING (2)
34 * #define ALLOC_COLD_SEQ (4)
37 /* Minimum sectors for support AMAP create */
38 #define AMAP_MIN_SUPPORT_SECTORS (1048576)
40 #define amap_add_hot_au(amap, au) amap_insert_to_list(au, &amap->slist_hot)
42 /* singly linked list */
44 struct slist_head
*next
;
45 struct slist_head
*head
;
49 typedef struct __AU_INFO_T
{
50 uint16_t idx
; /* the index of the AU (0, 1, 2, ... ) */
51 uint16_t free_clusters
; /* # of available cluster */
53 struct list_head head
;
54 struct slist_head shead
;/* singly linked list head for hot list */
59 /* Allocation Target AU */
60 typedef struct __TARGET_AU_T
{
61 AU_INFO_T
*au
; /* Working AU */
62 uint16_t idx
; /* Intra-AU cluster index */
63 uint16_t clu_to_skip
; /* Clusters to skip */
67 /* AMAP free-clusters-based node */
69 struct list_head head
; /* the list of AUs */
75 unsigned int packing_ratio
; /* Tunable packing ratio */
76 unsigned int au_size
; /* AU size in sectors */
77 unsigned int au_align_factor
; /* Hidden sectors % au_size */
80 typedef struct __AMAP_T
{
81 spinlock_t amap_lock
; /* obsolete */
82 struct super_block
*sb
;
85 int n_clean_au
, n_full_au
;
87 uint16_t clusters_per_au
;
88 AU_INFO_T
**au_table
; /* An array of AU_INFO entries */
91 /* Size-based AU management pool (cold) */
92 FCLU_NODE_T
*fclu_nodes
; /* An array of listheads */
93 int fclu_order
; /* Page order that fclu_nodes needs */
94 int fclu_hint
; /* maximum # of free clusters in an AU */
97 int total_fclu_hot
; /* Free clusters in hot list */
98 struct slist_head slist_hot
; /* Hot AU list */
100 /* Ignored AU list */
101 struct slist_head slist_ignored
;
103 /* Allocator variables (keep 2 AUs at maximum) */
104 TARGET_AU_T cur_cold
;
111 #define N_AU_PER_TABLE (int)(PAGE_SIZE / sizeof(AU_INFO_T))
112 #define GET_AU(amap, i_AU) (amap->au_table[(i_AU) / N_AU_PER_TABLE] + ((i_AU) % N_AU_PER_TABLE))
113 //#define MAX_CLU_PER_AU (int)(PAGE_SIZE / sizeof(FCLU_NODE_T))
114 #define MAX_CLU_PER_AU (1024)
116 /* Cold AU bucket <-> # of freeclusters */
117 #define NODE_CLEAN(amap) (&amap->fclu_nodes[amap->clusters_per_au - 1])
118 #define NODE(fclu, amap) (&amap->fclu_nodes[fclu - 1])
119 #define FREE_CLUSTERS(node, amap) ((int)(node - amap->fclu_nodes) + 1)
122 #define MAGIC_WORKING ((struct slist_head *)0xFFFF5091)
123 #define IS_AU_HOT(au, amap) (au->shead.head == &amap->slist_hot)
124 #define IS_AU_IGNORED(au, amap) (au->shead.head == &amap->slist_ignored)
125 #define IS_AU_WORKING(au, amap) (au->shead.head == MAGIC_WORKING)
126 #define SET_AU_WORKING(au) (au->shead.head = MAGIC_WORKING)
129 #define i_AU_of_CLU(amap, clu) ((amap->clu_align_bias + clu) / amap->clusters_per_au)
130 #define CLU_of_i_AU(amap, i_au, idx) \
131 ((uint32_t)(i_au) * (uint32_t)amap->clusters_per_au + (idx) - amap->clu_align_bias)
134 * NOTE : AMAP internal functions are moved to core.h
137 #endif /* _SDFAT_AMAP_H */