18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2016 CNEX Labs 48c2ecf20Sopenharmony_ci * Initial release: Javier Gonzalez <javier@cnexlabs.com> 58c2ecf20Sopenharmony_ci * Matias Bjorling <matias@cnexlabs.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or 88c2ecf20Sopenharmony_ci * modify it under the terms of the GNU General Public License version 98c2ecf20Sopenharmony_ci * 2 as published by the Free Software Foundation. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but 128c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 138c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 148c2ecf20Sopenharmony_ci * General Public License for more details. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * pblk-read.c - pblk's read path 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "pblk.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* 228c2ecf20Sopenharmony_ci * There is no guarantee that the value read from cache has not been updated and 238c2ecf20Sopenharmony_ci * resides at another location in the cache. We guarantee though that if the 248c2ecf20Sopenharmony_ci * value is read from the cache, it belongs to the mapped lba. In order to 258c2ecf20Sopenharmony_ci * guarantee and order between writes and reads are ordered, a flush must be 268c2ecf20Sopenharmony_ci * issued. 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_cistatic int pblk_read_from_cache(struct pblk *pblk, struct bio *bio, 298c2ecf20Sopenharmony_ci sector_t lba, struct ppa_addr ppa) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 328c2ecf20Sopenharmony_ci /* Callers must ensure that the ppa points to a cache address */ 338c2ecf20Sopenharmony_ci BUG_ON(pblk_ppa_empty(ppa)); 348c2ecf20Sopenharmony_ci BUG_ON(!pblk_addr_in_cache(ppa)); 358c2ecf20Sopenharmony_ci#endif 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci return pblk_rb_copy_to_bio(&pblk->rwb, bio, lba, ppa); 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic int pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd, 418c2ecf20Sopenharmony_ci struct bio *bio, sector_t blba, 428c2ecf20Sopenharmony_ci bool *from_cache) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci void *meta_list = rqd->meta_list; 458c2ecf20Sopenharmony_ci int nr_secs, i; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ciretry: 488c2ecf20Sopenharmony_ci nr_secs = pblk_lookup_l2p_seq(pblk, rqd->ppa_list, blba, rqd->nr_ppas, 498c2ecf20Sopenharmony_ci from_cache); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (!*from_cache) 528c2ecf20Sopenharmony_ci goto end; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci for (i = 0; i < nr_secs; i++) { 558c2ecf20Sopenharmony_ci struct pblk_sec_meta *meta = pblk_get_meta(pblk, meta_list, i); 568c2ecf20Sopenharmony_ci sector_t lba = blba + i; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (pblk_ppa_empty(rqd->ppa_list[i])) { 598c2ecf20Sopenharmony_ci __le64 addr_empty = cpu_to_le64(ADDR_EMPTY); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci meta->lba = addr_empty; 628c2ecf20Sopenharmony_ci } else if (pblk_addr_in_cache(rqd->ppa_list[i])) { 638c2ecf20Sopenharmony_ci /* 648c2ecf20Sopenharmony_ci * Try to read from write buffer. The address is later 658c2ecf20Sopenharmony_ci * checked on the write buffer to prevent retrieving 668c2ecf20Sopenharmony_ci * overwritten data. 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci if (!pblk_read_from_cache(pblk, bio, lba, 698c2ecf20Sopenharmony_ci rqd->ppa_list[i])) { 708c2ecf20Sopenharmony_ci if (i == 0) { 718c2ecf20Sopenharmony_ci /* 728c2ecf20Sopenharmony_ci * We didn't call with bio_advance() 738c2ecf20Sopenharmony_ci * yet, so we can just retry. 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_ci goto retry; 768c2ecf20Sopenharmony_ci } else { 778c2ecf20Sopenharmony_ci /* 788c2ecf20Sopenharmony_ci * We already call bio_advance() 798c2ecf20Sopenharmony_ci * so we cannot retry and we need 808c2ecf20Sopenharmony_ci * to quit that function in order 818c2ecf20Sopenharmony_ci * to allow caller to handle the bio 828c2ecf20Sopenharmony_ci * splitting in the current sector 838c2ecf20Sopenharmony_ci * position. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ci nr_secs = i; 868c2ecf20Sopenharmony_ci goto end; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci meta->lba = cpu_to_le64(lba); 908c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 918c2ecf20Sopenharmony_ci atomic_long_inc(&pblk->cache_reads); 928c2ecf20Sopenharmony_ci#endif 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ciend: 988c2ecf20Sopenharmony_ci if (pblk_io_aligned(pblk, nr_secs)) 998c2ecf20Sopenharmony_ci rqd->is_seq = 1; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 1028c2ecf20Sopenharmony_ci atomic_long_add(nr_secs, &pblk->inflight_reads); 1038c2ecf20Sopenharmony_ci#endif 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci return nr_secs; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic void pblk_read_check_seq(struct pblk *pblk, struct nvm_rq *rqd, 1108c2ecf20Sopenharmony_ci sector_t blba) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci void *meta_list = rqd->meta_list; 1138c2ecf20Sopenharmony_ci int nr_lbas = rqd->nr_ppas; 1148c2ecf20Sopenharmony_ci int i; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (!pblk_is_oob_meta_supported(pblk)) 1178c2ecf20Sopenharmony_ci return; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci for (i = 0; i < nr_lbas; i++) { 1208c2ecf20Sopenharmony_ci struct pblk_sec_meta *meta = pblk_get_meta(pblk, meta_list, i); 1218c2ecf20Sopenharmony_ci u64 lba = le64_to_cpu(meta->lba); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (lba == ADDR_EMPTY) 1248c2ecf20Sopenharmony_ci continue; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (lba != blba + i) { 1278c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 1288c2ecf20Sopenharmony_ci struct ppa_addr *ppa_list = nvm_rq_to_ppa_list(rqd); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci print_ppa(pblk, &ppa_list[i], "seq", i); 1318c2ecf20Sopenharmony_ci#endif 1328c2ecf20Sopenharmony_ci pblk_err(pblk, "corrupted read LBA (%llu/%llu)\n", 1338c2ecf20Sopenharmony_ci lba, (u64)blba + i); 1348c2ecf20Sopenharmony_ci WARN_ON(1); 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/* 1408c2ecf20Sopenharmony_ci * There can be holes in the lba list. 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_cistatic void pblk_read_check_rand(struct pblk *pblk, struct nvm_rq *rqd, 1438c2ecf20Sopenharmony_ci u64 *lba_list, int nr_lbas) 1448c2ecf20Sopenharmony_ci{ 1458c2ecf20Sopenharmony_ci void *meta_lba_list = rqd->meta_list; 1468c2ecf20Sopenharmony_ci int i, j; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (!pblk_is_oob_meta_supported(pblk)) 1498c2ecf20Sopenharmony_ci return; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci for (i = 0, j = 0; i < nr_lbas; i++) { 1528c2ecf20Sopenharmony_ci struct pblk_sec_meta *meta = pblk_get_meta(pblk, 1538c2ecf20Sopenharmony_ci meta_lba_list, j); 1548c2ecf20Sopenharmony_ci u64 lba = lba_list[i]; 1558c2ecf20Sopenharmony_ci u64 meta_lba; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (lba == ADDR_EMPTY) 1588c2ecf20Sopenharmony_ci continue; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci meta_lba = le64_to_cpu(meta->lba); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (lba != meta_lba) { 1638c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 1648c2ecf20Sopenharmony_ci struct ppa_addr *ppa_list = nvm_rq_to_ppa_list(rqd); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci print_ppa(pblk, &ppa_list[j], "rnd", j); 1678c2ecf20Sopenharmony_ci#endif 1688c2ecf20Sopenharmony_ci pblk_err(pblk, "corrupted read LBA (%llu/%llu)\n", 1698c2ecf20Sopenharmony_ci meta_lba, lba); 1708c2ecf20Sopenharmony_ci WARN_ON(1); 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci j++; 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci WARN_ONCE(j != rqd->nr_ppas, "pblk: corrupted random request\n"); 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic void pblk_end_user_read(struct bio *bio, int error) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci if (error && error != NVM_RSP_WARN_HIGHECC) 1828c2ecf20Sopenharmony_ci bio_io_error(bio); 1838c2ecf20Sopenharmony_ci else 1848c2ecf20Sopenharmony_ci bio_endio(bio); 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic void __pblk_end_io_read(struct pblk *pblk, struct nvm_rq *rqd, 1888c2ecf20Sopenharmony_ci bool put_line) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci struct pblk_g_ctx *r_ctx = nvm_rq_to_pdu(rqd); 1918c2ecf20Sopenharmony_ci struct bio *int_bio = rqd->bio; 1928c2ecf20Sopenharmony_ci unsigned long start_time = r_ctx->start_time; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci bio_end_io_acct(int_bio, start_time); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (rqd->error) 1978c2ecf20Sopenharmony_ci pblk_log_read_err(pblk, rqd); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci pblk_read_check_seq(pblk, rqd, r_ctx->lba); 2008c2ecf20Sopenharmony_ci bio_put(int_bio); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if (put_line) 2038c2ecf20Sopenharmony_ci pblk_rq_to_line_put(pblk, rqd); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 2068c2ecf20Sopenharmony_ci atomic_long_add(rqd->nr_ppas, &pblk->sync_reads); 2078c2ecf20Sopenharmony_ci atomic_long_sub(rqd->nr_ppas, &pblk->inflight_reads); 2088c2ecf20Sopenharmony_ci#endif 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci pblk_free_rqd(pblk, rqd, PBLK_READ); 2118c2ecf20Sopenharmony_ci atomic_dec(&pblk->inflight_io); 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic void pblk_end_io_read(struct nvm_rq *rqd) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci struct pblk *pblk = rqd->private; 2178c2ecf20Sopenharmony_ci struct pblk_g_ctx *r_ctx = nvm_rq_to_pdu(rqd); 2188c2ecf20Sopenharmony_ci struct bio *bio = (struct bio *)r_ctx->private; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci pblk_end_user_read(bio, rqd->error); 2218c2ecf20Sopenharmony_ci __pblk_end_io_read(pblk, rqd, true); 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic void pblk_read_rq(struct pblk *pblk, struct nvm_rq *rqd, struct bio *bio, 2258c2ecf20Sopenharmony_ci sector_t lba, bool *from_cache) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci struct pblk_sec_meta *meta = pblk_get_meta(pblk, rqd->meta_list, 0); 2288c2ecf20Sopenharmony_ci struct ppa_addr ppa; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci pblk_lookup_l2p_seq(pblk, &ppa, lba, 1, from_cache); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 2338c2ecf20Sopenharmony_ci atomic_long_inc(&pblk->inflight_reads); 2348c2ecf20Sopenharmony_ci#endif 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ciretry: 2378c2ecf20Sopenharmony_ci if (pblk_ppa_empty(ppa)) { 2388c2ecf20Sopenharmony_ci __le64 addr_empty = cpu_to_le64(ADDR_EMPTY); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci meta->lba = addr_empty; 2418c2ecf20Sopenharmony_ci return; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* Try to read from write buffer. The address is later checked on the 2458c2ecf20Sopenharmony_ci * write buffer to prevent retrieving overwritten data. 2468c2ecf20Sopenharmony_ci */ 2478c2ecf20Sopenharmony_ci if (pblk_addr_in_cache(ppa)) { 2488c2ecf20Sopenharmony_ci if (!pblk_read_from_cache(pblk, bio, lba, ppa)) { 2498c2ecf20Sopenharmony_ci pblk_lookup_l2p_seq(pblk, &ppa, lba, 1, from_cache); 2508c2ecf20Sopenharmony_ci goto retry; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci meta->lba = cpu_to_le64(lba); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 2568c2ecf20Sopenharmony_ci atomic_long_inc(&pblk->cache_reads); 2578c2ecf20Sopenharmony_ci#endif 2588c2ecf20Sopenharmony_ci } else { 2598c2ecf20Sopenharmony_ci rqd->ppa_addr = ppa; 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_civoid pblk_submit_read(struct pblk *pblk, struct bio *bio) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci sector_t blba = pblk_get_lba(bio); 2668c2ecf20Sopenharmony_ci unsigned int nr_secs = pblk_get_secs(bio); 2678c2ecf20Sopenharmony_ci bool from_cache; 2688c2ecf20Sopenharmony_ci struct pblk_g_ctx *r_ctx; 2698c2ecf20Sopenharmony_ci struct nvm_rq *rqd; 2708c2ecf20Sopenharmony_ci struct bio *int_bio, *split_bio; 2718c2ecf20Sopenharmony_ci unsigned long start_time; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci start_time = bio_start_io_acct(bio); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci rqd = pblk_alloc_rqd(pblk, PBLK_READ); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci rqd->opcode = NVM_OP_PREAD; 2788c2ecf20Sopenharmony_ci rqd->nr_ppas = nr_secs; 2798c2ecf20Sopenharmony_ci rqd->private = pblk; 2808c2ecf20Sopenharmony_ci rqd->end_io = pblk_end_io_read; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci r_ctx = nvm_rq_to_pdu(rqd); 2838c2ecf20Sopenharmony_ci r_ctx->start_time = start_time; 2848c2ecf20Sopenharmony_ci r_ctx->lba = blba; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci if (pblk_alloc_rqd_meta(pblk, rqd)) { 2878c2ecf20Sopenharmony_ci bio_io_error(bio); 2888c2ecf20Sopenharmony_ci pblk_free_rqd(pblk, rqd, PBLK_READ); 2898c2ecf20Sopenharmony_ci return; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci /* Clone read bio to deal internally with: 2938c2ecf20Sopenharmony_ci * -read errors when reading from drive 2948c2ecf20Sopenharmony_ci * -bio_advance() calls during cache reads 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci int_bio = bio_clone_fast(bio, GFP_KERNEL, &pblk_bio_set); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (nr_secs > 1) 2998c2ecf20Sopenharmony_ci nr_secs = pblk_read_ppalist_rq(pblk, rqd, int_bio, blba, 3008c2ecf20Sopenharmony_ci &from_cache); 3018c2ecf20Sopenharmony_ci else 3028c2ecf20Sopenharmony_ci pblk_read_rq(pblk, rqd, int_bio, blba, &from_cache); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cisplit_retry: 3058c2ecf20Sopenharmony_ci r_ctx->private = bio; /* original bio */ 3068c2ecf20Sopenharmony_ci rqd->bio = int_bio; /* internal bio */ 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (from_cache && nr_secs == rqd->nr_ppas) { 3098c2ecf20Sopenharmony_ci /* All data was read from cache, we can complete the IO. */ 3108c2ecf20Sopenharmony_ci pblk_end_user_read(bio, 0); 3118c2ecf20Sopenharmony_ci atomic_inc(&pblk->inflight_io); 3128c2ecf20Sopenharmony_ci __pblk_end_io_read(pblk, rqd, false); 3138c2ecf20Sopenharmony_ci } else if (nr_secs != rqd->nr_ppas) { 3148c2ecf20Sopenharmony_ci /* The read bio request could be partially filled by the write 3158c2ecf20Sopenharmony_ci * buffer, but there are some holes that need to be read from 3168c2ecf20Sopenharmony_ci * the drive. In order to handle this, we will use block layer 3178c2ecf20Sopenharmony_ci * mechanism to split this request in to smaller ones and make 3188c2ecf20Sopenharmony_ci * a chain of it. 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_ci split_bio = bio_split(bio, nr_secs * NR_PHY_IN_LOG, GFP_KERNEL, 3218c2ecf20Sopenharmony_ci &pblk_bio_set); 3228c2ecf20Sopenharmony_ci bio_chain(split_bio, bio); 3238c2ecf20Sopenharmony_ci submit_bio_noacct(bio); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* New bio contains first N sectors of the previous one, so 3268c2ecf20Sopenharmony_ci * we can continue to use existing rqd, but we need to shrink 3278c2ecf20Sopenharmony_ci * the number of PPAs in it. New bio is also guaranteed that 3288c2ecf20Sopenharmony_ci * it contains only either data from cache or from drive, newer 3298c2ecf20Sopenharmony_ci * mix of them. 3308c2ecf20Sopenharmony_ci */ 3318c2ecf20Sopenharmony_ci bio = split_bio; 3328c2ecf20Sopenharmony_ci rqd->nr_ppas = nr_secs; 3338c2ecf20Sopenharmony_ci if (rqd->nr_ppas == 1) 3348c2ecf20Sopenharmony_ci rqd->ppa_addr = rqd->ppa_list[0]; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci /* Recreate int_bio - existing might have some needed internal 3378c2ecf20Sopenharmony_ci * fields modified already. 3388c2ecf20Sopenharmony_ci */ 3398c2ecf20Sopenharmony_ci bio_put(int_bio); 3408c2ecf20Sopenharmony_ci int_bio = bio_clone_fast(bio, GFP_KERNEL, &pblk_bio_set); 3418c2ecf20Sopenharmony_ci goto split_retry; 3428c2ecf20Sopenharmony_ci } else if (pblk_submit_io(pblk, rqd, NULL)) { 3438c2ecf20Sopenharmony_ci /* Submitting IO to drive failed, let's report an error */ 3448c2ecf20Sopenharmony_ci rqd->error = -ENODEV; 3458c2ecf20Sopenharmony_ci pblk_end_io_read(rqd); 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cistatic int read_ppalist_rq_gc(struct pblk *pblk, struct nvm_rq *rqd, 3508c2ecf20Sopenharmony_ci struct pblk_line *line, u64 *lba_list, 3518c2ecf20Sopenharmony_ci u64 *paddr_list_gc, unsigned int nr_secs) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci struct ppa_addr ppa_list_l2p[NVM_MAX_VLBA]; 3548c2ecf20Sopenharmony_ci struct ppa_addr ppa_gc; 3558c2ecf20Sopenharmony_ci int valid_secs = 0; 3568c2ecf20Sopenharmony_ci int i; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci pblk_lookup_l2p_rand(pblk, ppa_list_l2p, lba_list, nr_secs); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci for (i = 0; i < nr_secs; i++) { 3618c2ecf20Sopenharmony_ci if (lba_list[i] == ADDR_EMPTY) 3628c2ecf20Sopenharmony_ci continue; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci ppa_gc = addr_to_gen_ppa(pblk, paddr_list_gc[i], line->id); 3658c2ecf20Sopenharmony_ci if (!pblk_ppa_comp(ppa_list_l2p[i], ppa_gc)) { 3668c2ecf20Sopenharmony_ci paddr_list_gc[i] = lba_list[i] = ADDR_EMPTY; 3678c2ecf20Sopenharmony_ci continue; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci rqd->ppa_list[valid_secs++] = ppa_list_l2p[i]; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 3748c2ecf20Sopenharmony_ci atomic_long_add(valid_secs, &pblk->inflight_reads); 3758c2ecf20Sopenharmony_ci#endif 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci return valid_secs; 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic int read_rq_gc(struct pblk *pblk, struct nvm_rq *rqd, 3818c2ecf20Sopenharmony_ci struct pblk_line *line, sector_t lba, 3828c2ecf20Sopenharmony_ci u64 paddr_gc) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci struct ppa_addr ppa_l2p, ppa_gc; 3858c2ecf20Sopenharmony_ci int valid_secs = 0; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci if (lba == ADDR_EMPTY) 3888c2ecf20Sopenharmony_ci goto out; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci /* logic error: lba out-of-bounds */ 3918c2ecf20Sopenharmony_ci if (lba >= pblk->capacity) { 3928c2ecf20Sopenharmony_ci WARN(1, "pblk: read lba out of bounds\n"); 3938c2ecf20Sopenharmony_ci goto out; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci spin_lock(&pblk->trans_lock); 3978c2ecf20Sopenharmony_ci ppa_l2p = pblk_trans_map_get(pblk, lba); 3988c2ecf20Sopenharmony_ci spin_unlock(&pblk->trans_lock); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci ppa_gc = addr_to_gen_ppa(pblk, paddr_gc, line->id); 4018c2ecf20Sopenharmony_ci if (!pblk_ppa_comp(ppa_l2p, ppa_gc)) 4028c2ecf20Sopenharmony_ci goto out; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci rqd->ppa_addr = ppa_l2p; 4058c2ecf20Sopenharmony_ci valid_secs = 1; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 4088c2ecf20Sopenharmony_ci atomic_long_inc(&pblk->inflight_reads); 4098c2ecf20Sopenharmony_ci#endif 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ciout: 4128c2ecf20Sopenharmony_ci return valid_secs; 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ciint pblk_submit_read_gc(struct pblk *pblk, struct pblk_gc_rq *gc_rq) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci struct nvm_rq rqd; 4188c2ecf20Sopenharmony_ci int ret = NVM_IO_OK; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci memset(&rqd, 0, sizeof(struct nvm_rq)); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci ret = pblk_alloc_rqd_meta(pblk, &rqd); 4238c2ecf20Sopenharmony_ci if (ret) 4248c2ecf20Sopenharmony_ci return ret; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if (gc_rq->nr_secs > 1) { 4278c2ecf20Sopenharmony_ci gc_rq->secs_to_gc = read_ppalist_rq_gc(pblk, &rqd, gc_rq->line, 4288c2ecf20Sopenharmony_ci gc_rq->lba_list, 4298c2ecf20Sopenharmony_ci gc_rq->paddr_list, 4308c2ecf20Sopenharmony_ci gc_rq->nr_secs); 4318c2ecf20Sopenharmony_ci if (gc_rq->secs_to_gc == 1) 4328c2ecf20Sopenharmony_ci rqd.ppa_addr = rqd.ppa_list[0]; 4338c2ecf20Sopenharmony_ci } else { 4348c2ecf20Sopenharmony_ci gc_rq->secs_to_gc = read_rq_gc(pblk, &rqd, gc_rq->line, 4358c2ecf20Sopenharmony_ci gc_rq->lba_list[0], 4368c2ecf20Sopenharmony_ci gc_rq->paddr_list[0]); 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci if (!(gc_rq->secs_to_gc)) 4408c2ecf20Sopenharmony_ci goto out; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci rqd.opcode = NVM_OP_PREAD; 4438c2ecf20Sopenharmony_ci rqd.nr_ppas = gc_rq->secs_to_gc; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci if (pblk_submit_io_sync(pblk, &rqd, gc_rq->data)) { 4468c2ecf20Sopenharmony_ci ret = -EIO; 4478c2ecf20Sopenharmony_ci goto err_free_dma; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci pblk_read_check_rand(pblk, &rqd, gc_rq->lba_list, gc_rq->nr_secs); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci atomic_dec(&pblk->inflight_io); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci if (rqd.error) { 4558c2ecf20Sopenharmony_ci atomic_long_inc(&pblk->read_failed_gc); 4568c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 4578c2ecf20Sopenharmony_ci pblk_print_failed_rqd(pblk, &rqd, rqd.error); 4588c2ecf20Sopenharmony_ci#endif 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci#ifdef CONFIG_NVM_PBLK_DEBUG 4628c2ecf20Sopenharmony_ci atomic_long_add(gc_rq->secs_to_gc, &pblk->sync_reads); 4638c2ecf20Sopenharmony_ci atomic_long_add(gc_rq->secs_to_gc, &pblk->recov_gc_reads); 4648c2ecf20Sopenharmony_ci atomic_long_sub(gc_rq->secs_to_gc, &pblk->inflight_reads); 4658c2ecf20Sopenharmony_ci#endif 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ciout: 4688c2ecf20Sopenharmony_ci pblk_free_rqd_meta(pblk, &rqd); 4698c2ecf20Sopenharmony_ci return ret; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_cierr_free_dma: 4728c2ecf20Sopenharmony_ci pblk_free_rqd_meta(pblk, &rqd); 4738c2ecf20Sopenharmony_ci return ret; 4748c2ecf20Sopenharmony_ci} 475