diff options
Diffstat (limited to 'drivers/lightnvm/rrpc.c')
-rw-r--r-- | drivers/lightnvm/rrpc.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index 7ba64c87ba1c..134e4faba482 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c | |||
@@ -123,12 +123,42 @@ static u64 block_to_addr(struct rrpc *rrpc, struct rrpc_block *rblk) | |||
123 | return blk->id * rrpc->dev->pgs_per_blk; | 123 | return blk->id * rrpc->dev->pgs_per_blk; |
124 | } | 124 | } |
125 | 125 | ||
126 | static struct ppa_addr linear_to_generic_addr(struct nvm_dev *dev, | ||
127 | struct ppa_addr r) | ||
128 | { | ||
129 | struct ppa_addr l; | ||
130 | int secs, pgs, blks, luns; | ||
131 | sector_t ppa = r.ppa; | ||
132 | |||
133 | l.ppa = 0; | ||
134 | |||
135 | div_u64_rem(ppa, dev->sec_per_pg, &secs); | ||
136 | l.g.sec = secs; | ||
137 | |||
138 | sector_div(ppa, dev->sec_per_pg); | ||
139 | div_u64_rem(ppa, dev->sec_per_blk, &pgs); | ||
140 | l.g.pg = pgs; | ||
141 | |||
142 | sector_div(ppa, dev->pgs_per_blk); | ||
143 | div_u64_rem(ppa, dev->blks_per_lun, &blks); | ||
144 | l.g.blk = blks; | ||
145 | |||
146 | sector_div(ppa, dev->blks_per_lun); | ||
147 | div_u64_rem(ppa, dev->luns_per_chnl, &luns); | ||
148 | l.g.lun = luns; | ||
149 | |||
150 | sector_div(ppa, dev->luns_per_chnl); | ||
151 | l.g.ch = ppa; | ||
152 | |||
153 | return l; | ||
154 | } | ||
155 | |||
126 | static struct ppa_addr rrpc_ppa_to_gaddr(struct nvm_dev *dev, u64 addr) | 156 | static struct ppa_addr rrpc_ppa_to_gaddr(struct nvm_dev *dev, u64 addr) |
127 | { | 157 | { |
128 | struct ppa_addr paddr; | 158 | struct ppa_addr paddr; |
129 | 159 | ||
130 | paddr.ppa = addr; | 160 | paddr.ppa = addr; |
131 | return __linear_to_generic_addr(dev, paddr); | 161 | return linear_to_generic_addr(dev, paddr); |
132 | } | 162 | } |
133 | 163 | ||
134 | /* requires lun->lock taken */ | 164 | /* requires lun->lock taken */ |
@@ -152,7 +182,7 @@ static struct rrpc_block *rrpc_get_blk(struct rrpc *rrpc, struct rrpc_lun *rlun, | |||
152 | struct nvm_block *blk; | 182 | struct nvm_block *blk; |
153 | struct rrpc_block *rblk; | 183 | struct rrpc_block *rblk; |
154 | 184 | ||
155 | blk = nvm_get_blk(rrpc->dev, rlun->parent, 0); | 185 | blk = nvm_get_blk(rrpc->dev, rlun->parent, flags); |
156 | if (!blk) | 186 | if (!blk) |
157 | return NULL; | 187 | return NULL; |
158 | 188 | ||
@@ -172,6 +202,20 @@ static void rrpc_put_blk(struct rrpc *rrpc, struct rrpc_block *rblk) | |||
172 | nvm_put_blk(rrpc->dev, rblk->parent); | 202 | nvm_put_blk(rrpc->dev, rblk->parent); |
173 | } | 203 | } |
174 | 204 | ||
205 | static void rrpc_put_blks(struct rrpc *rrpc) | ||
206 | { | ||
207 | struct rrpc_lun *rlun; | ||
208 | int i; | ||
209 | |||
210 | for (i = 0; i < rrpc->nr_luns; i++) { | ||
211 | rlun = &rrpc->luns[i]; | ||
212 | if (rlun->cur) | ||
213 | rrpc_put_blk(rrpc, rlun->cur); | ||
214 | if (rlun->gc_cur) | ||
215 | rrpc_put_blk(rrpc, rlun->gc_cur); | ||
216 | } | ||
217 | } | ||
218 | |||
175 | static struct rrpc_lun *get_next_lun(struct rrpc *rrpc) | 219 | static struct rrpc_lun *get_next_lun(struct rrpc *rrpc) |
176 | { | 220 | { |
177 | int next = atomic_inc_return(&rrpc->next_lun); | 221 | int next = atomic_inc_return(&rrpc->next_lun); |
@@ -972,7 +1016,7 @@ static int rrpc_map_init(struct rrpc *rrpc) | |||
972 | return 0; | 1016 | return 0; |
973 | 1017 | ||
974 | /* Bring up the mapping table from device */ | 1018 | /* Bring up the mapping table from device */ |
975 | ret = dev->ops->get_l2p_tbl(dev->q, 0, dev->total_pages, | 1019 | ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_pages, |
976 | rrpc_l2p_update, rrpc); | 1020 | rrpc_l2p_update, rrpc); |
977 | if (ret) { | 1021 | if (ret) { |
978 | pr_err("nvm: rrpc: could not read L2P table.\n"); | 1022 | pr_err("nvm: rrpc: could not read L2P table.\n"); |
@@ -1194,18 +1238,21 @@ static int rrpc_luns_configure(struct rrpc *rrpc) | |||
1194 | 1238 | ||
1195 | rblk = rrpc_get_blk(rrpc, rlun, 0); | 1239 | rblk = rrpc_get_blk(rrpc, rlun, 0); |
1196 | if (!rblk) | 1240 | if (!rblk) |
1197 | return -EINVAL; | 1241 | goto err; |
1198 | 1242 | ||
1199 | rrpc_set_lun_cur(rlun, rblk); | 1243 | rrpc_set_lun_cur(rlun, rblk); |
1200 | 1244 | ||
1201 | /* Emergency gc block */ | 1245 | /* Emergency gc block */ |
1202 | rblk = rrpc_get_blk(rrpc, rlun, 1); | 1246 | rblk = rrpc_get_blk(rrpc, rlun, 1); |
1203 | if (!rblk) | 1247 | if (!rblk) |
1204 | return -EINVAL; | 1248 | goto err; |
1205 | rlun->gc_cur = rblk; | 1249 | rlun->gc_cur = rblk; |
1206 | } | 1250 | } |
1207 | 1251 | ||
1208 | return 0; | 1252 | return 0; |
1253 | err: | ||
1254 | rrpc_put_blks(rrpc); | ||
1255 | return -EINVAL; | ||
1209 | } | 1256 | } |
1210 | 1257 | ||
1211 | static struct nvm_tgt_type tt_rrpc; | 1258 | static struct nvm_tgt_type tt_rrpc; |