switch (cmd) { case GUP_FAST_BENCHMARK: case GUP_BASIC_TEST: for (i = 0; i < nr_pages; i++)
put_page(pages[i]); break;
case PIN_FAST_BENCHMARK: case PIN_BASIC_TEST: case PIN_LONGTERM_BENCHMARK:
unpin_user_pages(pages, nr_pages); break; case DUMP_USER_PAGES_TEST: if (gup_test_flags & GUP_TEST_FLAG_DUMP_PAGES_USE_PIN) {
unpin_user_pages(pages, nr_pages);
} else { for (i = 0; i < nr_pages; i++)
put_page(pages[i]);
switch (cmd) { case PIN_FAST_BENCHMARK: case PIN_BASIC_TEST: case PIN_LONGTERM_BENCHMARK: for (i = 0; i < nr_pages; i++) {
folio = page_folio(pages[i]);
if (WARN(!folio_maybe_dma_pinned(folio), "pages[%lu] is NOT dma-pinned\n", i)) {
dump_page(&folio->page, "gup_test failure"); break;
} elseif (cmd == PIN_LONGTERM_BENCHMARK &&
WARN(!folio_is_longterm_pinnable(folio), "pages[%lu] is NOT pinnable but pinned\n",
i)) {
dump_page(&folio->page, "gup_test failure"); break;
}
} break;
}
}
/* * Zero out any user-supplied page index that is out of range. Remember: * .which_pages[] contains a 1-based set of page indices.
*/ for (i = 0; i < GUP_TEST_MAX_PAGES_TO_DUMP; i++) { if (gup->which_pages[i] > nr_pages) {
pr_warn("ZEROING due to out of range: .which_pages[%u]: %u\n",
i, gup->which_pages[i]);
gup->which_pages[i] = 0;
}
}
for (i = 0; i < GUP_TEST_MAX_PAGES_TO_DUMP; i++) {
index_to_dump = gup->which_pages[i];
if (index_to_dump) {
index_to_dump--; // Decode from 1-based, to 0-based
pr_info("---- page #%u, starting from user virt addr: 0x%llx\n",
index_to_dump, gup->addr);
dump_page(pages[index_to_dump], "gup_test: dump_pages() test");
}
}
}
staticint __gup_test_ioctl(unsignedint cmd, struct gup_test *gup)
{
ktime_t start_time, end_time; unsignedlong i, nr_pages, addr, next; long nr; struct page **pages; int ret = 0; bool needs_mmap_lock =
cmd != GUP_FAST_BENCHMARK && cmd != PIN_FAST_BENCHMARK;
/* * Take an un-benchmark-timed moment to verify DMA pinned * state: print a warning if any non-dma-pinned pages are found:
*/
verify_dma_pinned(cmd, pages, nr_pages);
if (cmd == DUMP_USER_PAGES_TEST)
dump_pages_test(gup, pages, nr_pages);
if (copy_from_user(&user_addr, (void __user *)arg, sizeof(user_addr))) return -EFAULT;
for (i = 0; i < pin_longterm_test_nr_pages; i++) { void *addr = kmap_local_page(pin_longterm_test_pages[i]); unsignedlong ret;
ret = copy_to_user((void __user *)(unsignedlong)user_addr, addr,
PAGE_SIZE);
kunmap_local(addr); if (ret) return -EFAULT;
user_addr += PAGE_SIZE;
} return 0;
}
staticlong pin_longterm_test_ioctl(struct file *filep, unsignedint cmd, unsignedlong arg)
{ int ret = -EINVAL;
if (mutex_lock_killable(&pin_longterm_test_mutex)) return -EINTR;
switch (cmd) { case PIN_LONGTERM_TEST_START:
ret = pin_longterm_test_start(arg); break; case PIN_LONGTERM_TEST_STOP:
pin_longterm_test_stop();
ret = 0; break; case PIN_LONGTERM_TEST_READ:
ret = pin_longterm_test_read(arg); break;
}
switch (cmd) { case GUP_FAST_BENCHMARK: case PIN_FAST_BENCHMARK: case PIN_LONGTERM_BENCHMARK: case GUP_BASIC_TEST: case PIN_BASIC_TEST: case DUMP_USER_PAGES_TEST: break; case PIN_LONGTERM_TEST_START: case PIN_LONGTERM_TEST_STOP: case PIN_LONGTERM_TEST_READ: return pin_longterm_test_ioctl(filep, cmd, arg); default: return -EINVAL;
}
if (copy_from_user(&gup, (void __user *)arg, sizeof(gup))) return -EFAULT;
ret = __gup_test_ioctl(cmd, &gup); if (ret) return ret;
if (copy_to_user((void __user *)arg, &gup, sizeof(gup))) return -EFAULT;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.