mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-08 16:22:41 -04:00
iommufd: Folio subroutines
Add subroutines for copying folios to a batch. Link: https://patch.msgid.link/r/1729861919-234514-6-git-send-email-steven.sistare@oracle.com Signed-off-by: Steve Sistare <steven.sistare@oracle.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
committed by
Jason Gunthorpe
parent
c27f0a606c
commit
ed9178fbfd
@@ -346,25 +346,39 @@ static void batch_destroy(struct pfn_batch *batch, void *backup)
|
||||
kfree(batch->pfns);
|
||||
}
|
||||
|
||||
static bool batch_add_pfn_num(struct pfn_batch *batch, unsigned long pfn,
|
||||
u32 nr)
|
||||
{
|
||||
const unsigned int MAX_NPFNS = type_max(typeof(*batch->npfns));
|
||||
unsigned int end = batch->end;
|
||||
|
||||
if (end && pfn == batch->pfns[end - 1] + batch->npfns[end - 1] &&
|
||||
nr <= MAX_NPFNS - batch->npfns[end - 1]) {
|
||||
batch->npfns[end - 1] += nr;
|
||||
} else if (end < batch->array_size) {
|
||||
batch->pfns[end] = pfn;
|
||||
batch->npfns[end] = nr;
|
||||
batch->end++;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
batch->total_pfns += nr;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void batch_remove_pfn_num(struct pfn_batch *batch, unsigned long nr)
|
||||
{
|
||||
batch->npfns[batch->end - 1] -= nr;
|
||||
if (batch->npfns[batch->end - 1] == 0)
|
||||
batch->end--;
|
||||
batch->total_pfns -= nr;
|
||||
}
|
||||
|
||||
/* true if the pfn was added, false otherwise */
|
||||
static bool batch_add_pfn(struct pfn_batch *batch, unsigned long pfn)
|
||||
{
|
||||
const unsigned int MAX_NPFNS = type_max(typeof(*batch->npfns));
|
||||
|
||||
if (batch->end &&
|
||||
pfn == batch->pfns[batch->end - 1] + batch->npfns[batch->end - 1] &&
|
||||
batch->npfns[batch->end - 1] != MAX_NPFNS) {
|
||||
batch->npfns[batch->end - 1]++;
|
||||
batch->total_pfns++;
|
||||
return true;
|
||||
}
|
||||
if (batch->end == batch->array_size)
|
||||
return false;
|
||||
batch->total_pfns++;
|
||||
batch->pfns[batch->end] = pfn;
|
||||
batch->npfns[batch->end] = 1;
|
||||
batch->end++;
|
||||
return true;
|
||||
return batch_add_pfn_num(batch, pfn, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -622,6 +636,41 @@ static void batch_from_pages(struct pfn_batch *batch, struct page **pages,
|
||||
break;
|
||||
}
|
||||
|
||||
static int batch_from_folios(struct pfn_batch *batch, struct folio ***folios_p,
|
||||
unsigned long *offset_p, unsigned long npages)
|
||||
{
|
||||
int rc = 0;
|
||||
struct folio **folios = *folios_p;
|
||||
unsigned long offset = *offset_p;
|
||||
|
||||
while (npages) {
|
||||
struct folio *folio = *folios;
|
||||
unsigned long nr = folio_nr_pages(folio) - offset;
|
||||
unsigned long pfn = page_to_pfn(folio_page(folio, offset));
|
||||
|
||||
nr = min(nr, npages);
|
||||
npages -= nr;
|
||||
|
||||
if (!batch_add_pfn_num(batch, pfn, nr))
|
||||
break;
|
||||
if (nr > 1) {
|
||||
rc = folio_add_pins(folio, nr - 1);
|
||||
if (rc) {
|
||||
batch_remove_pfn_num(batch, nr);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
folios++;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
*folios_p = folios;
|
||||
*offset_p = offset;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void batch_unpin(struct pfn_batch *batch, struct iopt_pages *pages,
|
||||
unsigned int first_page_off, size_t npages)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user