Changeset View
Standalone View
sys/compat/linuxkpi/common/src/linux_page.c
Show First 20 Lines • Show All 423 Lines • ▼ Show 20 Lines | #ifdef __i386__ | ||||
mrdesc = idr_find(&mtrr_idr, reg - __MTRR_ID_BASE); | mrdesc = idr_find(&mtrr_idr, reg - __MTRR_ID_BASE); | ||||
MPASS(mrdesc != NULL); | MPASS(mrdesc != NULL); | ||||
idr_remove(&mtrr_idr, reg - __MTRR_ID_BASE); | idr_remove(&mtrr_idr, reg - __MTRR_ID_BASE); | ||||
act = MEMRANGE_SET_REMOVE; | act = MEMRANGE_SET_REMOVE; | ||||
mem_range_attr_set(mrdesc, &act); | mem_range_attr_set(mrdesc, &act); | ||||
free(mrdesc, M_LKMTRR); | free(mrdesc, M_LKMTRR); | ||||
#endif | #endif | ||||
} | } | ||||
/* | |||||
* This is a highly simplified version of the Linux page_frag_cache. | |||||
* We only support up-to 1 single page as fragment size and we will | |||||
* always return a full page. This may be wasteful on small objects | |||||
* but the only known consumer (mt76) is either asking for a half-page | |||||
* or a full page. If this was to become a problem we can implement | |||||
* a more elaborate version. | |||||
*/ | |||||
void * | |||||
linuxkpi_page_frag_alloc(struct page_frag_cache *pfc, | |||||
size_t fragsz, gfp_t gfp) | |||||
{ | |||||
vm_page_t pages; | |||||
if (fragsz == 0) | |||||
return (NULL); | |||||
KASSERT(fragsz <= PAGE_SIZE, ("%s: fragsz %zu > PAGE_SIZE not yet " | |||||
"supported", __func__, fragsz)); | |||||
pages = alloc_pages(gfp, flsl(howmany(fragsz, PAGE_SIZE) - 1)); | |||||
hselasky: Doesn't fls() take an integer. While fragsz is size_t ? Not that it matters, but maybe check… | |||||
Done Inline ActionsWell with the KASSERT above and the 0 check I think the input is pretty limited into fls. bz: Well with the KASSERT above and the 0 check I think the input is pretty limited into fls. | |||||
Done Inline ActionsCan you change that KASSERT() into if (fragsz == 0 || fragsz > PAGE_SIZE) return (NULL); ? I mean try to avoid panicing? hselasky: Can you change that KASSERT() into if (fragsz == 0 || fragsz > PAGE_SIZE) return (NULL); ?
I… | |||||
Done Inline ActionsThe panic is on purpose as if we "hide" the implementation limitation we might have spurious errors one day which may take hours to debug only to find this. bz: The panic is on purpose as if we "hide" the implementation limitation we might have spurious… | |||||
Not Done Inline ActionsWell, only panic if gfp & M_WAITOK && fragsz > PAGE_SIZE ? Else clients will handle and print failures on NULL allocations? I'm worried that user-space input may be passed directly to fragsz, which is not good. --HPS hselasky: Well, only panic if gfp & M_WAITOK && fragsz > PAGE_SIZE ? Else clients will handle and print… | |||||
Not Done Inline ActionsI'd still argue for using flsl() here. Or just don't bother with it at all, i.e., just write pages = alloc_pages(gfp, 1);, since it will take a lot more work to support fragsz > PAGE_SIZE. markj: I'd still argue for using flsl() here. Or just don't bother with it at all, i.e., just write… | |||||
Done Inline ActionsIt's alloc_pages(gfp, 0); I now understand what @hselasky meant above. Would changing it to flsl() work for both of you? bz: It's alloc_pages(gfp, 0); I now understand what @hselasky meant above. Would changing it to… | |||||
Not Done Inline ActionsThat's fine with me. markj: That's fine with me. | |||||
pfc->va = linux_page_address(pages); | |||||
/* Passed in as "count" to __page_frag_cache_drain(). Unused by us. */ | |||||
pfc->pagecnt_bias = 0; | |||||
return (pfc->va); | |||||
} | |||||
void | |||||
linuxkpi_page_frag_free(void *addr) | |||||
{ | |||||
vm_page_t page; | |||||
page = PHYS_TO_VM_PAGE(vtophys(addr)); | |||||
linux_free_pages(page, 0); | |||||
} | |||||
void | |||||
linuxkpi__page_frag_cache_drain(struct page *page, size_t count __unused) | |||||
{ | |||||
linux_free_pages(page, 0); | |||||
} |
Doesn't fls() take an integer. While fragsz is size_t ? Not that it matters, but maybe check the valid range?