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