Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/linuxkpi/common/include/linux/scatterlist.h
Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | struct sg_page_iter { | ||||
unsigned int sg_pgoffset; | unsigned int sg_pgoffset; | ||||
unsigned int maxents; | unsigned int maxents; | ||||
struct { | struct { | ||||
unsigned int nents; | unsigned int nents; | ||||
int pg_advance; | int pg_advance; | ||||
} internal; | } internal; | ||||
}; | }; | ||||
#define SCATTERLIST_MAX_SEGMENT (UINT_MAX & PAGE_MASK) | |||||
hselasky: Can you use PAGE_SIZE here to derive the PAGE_MASK instead of PAGE_MASK? PAGE_MASK is redefined… | |||||
#define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) | #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) | ||||
#define SG_MAGIC 0x87654321UL | #define SG_MAGIC 0x87654321UL | ||||
#define sg_is_chain(sg) ((sg)->page_link & SG_PAGE_LINK_CHAIN) | #define sg_is_chain(sg) ((sg)->page_link & SG_PAGE_LINK_CHAIN) | ||||
#define sg_is_last(sg) ((sg)->page_link & SG_PAGE_LINK_LAST) | #define sg_is_last(sg) ((sg)->page_link & SG_PAGE_LINK_LAST) | ||||
#define sg_chain_ptr(sg) \ | #define sg_chain_ptr(sg) \ | ||||
((struct scatterlist *) ((sg)->page_link & ~SG_PAGE_LINK_MASK)) | ((struct scatterlist *) ((sg)->page_link & ~SG_PAGE_LINK_MASK)) | ||||
▲ Show 20 Lines • Show All 206 Lines • ▼ Show 20 Lines | ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC, | ||||
NULL, gfp_mask, sg_kmalloc); | NULL, gfp_mask, sg_kmalloc); | ||||
if (unlikely(ret)) | if (unlikely(ret)) | ||||
__sg_free_table(table, SG_MAX_SINGLE_ALLOC, 0, sg_kfree); | __sg_free_table(table, SG_MAX_SINGLE_ALLOC, 0, sg_kfree); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static inline int | static inline int | ||||
sg_alloc_table_from_pages(struct sg_table *sgt, | __sg_alloc_table_from_pages(struct sg_table *sgt, | ||||
struct page **pages, unsigned int count, | struct page **pages, unsigned int count, | ||||
unsigned long off, unsigned long size, | unsigned long off, unsigned long size, | ||||
gfp_t gfp_mask) | unsigned int max_segment, gfp_t gfp_mask) | ||||
{ | { | ||||
unsigned int i, segs, cur; | unsigned int i, segs, cur, len; | ||||
int rc; | int rc; | ||||
struct scatterlist *s; | struct scatterlist *s; | ||||
if (WARN_ON(!max_segment || offset_in_page(max_segment))) | |||||
return -EINVAL; | |||||
len = 0; | |||||
for (segs = i = 1; i < count; ++i) { | for (segs = i = 1; i < count; ++i) { | ||||
if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1) | len += PAGE_SIZE; | ||||
if (len >= max_segment || | |||||
page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1) { | |||||
++segs; | ++segs; | ||||
len = 0; | |||||
} | } | ||||
} | |||||
if (__predict_false((rc = sg_alloc_table(sgt, segs, gfp_mask)))) | if (__predict_false((rc = sg_alloc_table(sgt, segs, gfp_mask)))) | ||||
return (rc); | return (rc); | ||||
cur = 0; | cur = 0; | ||||
for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { | for_each_sg(sgt->sgl, s, sgt->orig_nents, i) { | ||||
unsigned long seg_size; | unsigned long seg_size; | ||||
unsigned int j; | unsigned int j; | ||||
for (j = cur + 1; j < count; ++j) | len = 0; | ||||
if (page_to_pfn(pages[j]) != | for (j = cur + 1; j < count; ++j) { | ||||
len += PAGE_SIZE; | |||||
if (len >= max_segment || page_to_pfn(pages[j]) != | |||||
page_to_pfn(pages[j - 1]) + 1) | page_to_pfn(pages[j - 1]) + 1) | ||||
break; | break; | ||||
} | |||||
seg_size = ((j - cur) << PAGE_SHIFT) - off; | seg_size = ((j - cur) << PAGE_SHIFT) - off; | ||||
sg_set_page(s, pages[cur], min(size, seg_size), off); | sg_set_page(s, pages[cur], min(size, seg_size), off); | ||||
size -= seg_size; | size -= seg_size; | ||||
off = 0; | off = 0; | ||||
cur = j; | cur = j; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static inline int | |||||
sg_alloc_table_from_pages(struct sg_table *sgt, | |||||
struct page **pages, unsigned int count, | |||||
unsigned long off, unsigned long size, | |||||
gfp_t gfp_mask) | |||||
{ | |||||
return __sg_alloc_table_from_pages(sgt, pages, count, off, size, | |||||
SCATTERLIST_MAX_SEGMENT, gfp_mask); | |||||
} | |||||
static inline int | static inline int | ||||
sg_nents(struct scatterlist *sg) | sg_nents(struct scatterlist *sg) | ||||
{ | { | ||||
int nents; | int nents; | ||||
for (nents = 0; sg; sg = sg_next(sg)) | for (nents = 0; sg; sg = sg_next(sg)) | ||||
nents++; | nents++; | ||||
▲ Show 20 Lines • Show All 94 Lines • Show Last 20 Lines |
Can you use PAGE_SIZE here to derive the PAGE_MASK instead of PAGE_MASK? PAGE_MASK is redefined by the LinuxKPI and might make the code difficult to understand.