Changeset View
Standalone View
sys/compat/linuxkpi/common/include/linux/scatterlist.h
Show First 20 Lines • Show All 60 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; | ||||
}; | }; | ||||
struct sg_dma_page_iter { | |||||
hselasky: Could we simply do:
```
#define sg_dma_page_iter sg_page_iter
``` | |||||
ashafer_badland.ioAuthorUnsubmitted Not Done Inline ActionsWe could, but it would require changing certain parts of drm to be FreeBSD specific, as they expect to be able to do sg_dma_page_iter->base. https://github.com/amshafer/kms-drm/blob/drm-v5.1/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c#L320 At the moment there are only two such cases in 5.1, but my guess is the number will increase over time and not decrease. Although casting the function argument isn't ideal, the current patch will allow future drm code to be imported unchanged. ashafer_badland.io: We could, but it would require changing certain parts of drm to be FreeBSD specific, as they… | |||||
struct sg_page_iter base; | |||||
}; | |||||
#define SCATTERLIST_MAX_SEGMENT (-1U & ~(PAGE_SIZE - 1)) | #define SCATTERLIST_MAX_SEGMENT (-1U & ~(PAGE_SIZE - 1)) | ||||
#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_CHAIN SG_PAGE_LINK_CHAIN | #define SG_CHAIN SG_PAGE_LINK_CHAIN | ||||
#define SG_END SG_PAGE_LINK_LAST | #define SG_END SG_PAGE_LINK_LAST | ||||
#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)) | ||||
#define sg_dma_address(sg) (sg)->dma_address | #define sg_dma_address(sg) (sg)->dma_address | ||||
#define sg_dma_len(sg) (sg)->length | #define sg_dma_len(sg) (sg)->length | ||||
#define for_each_sg_page(sgl, iter, nents, pgoffset) \ | #define for_each_sg_page(sgl, iter, nents, pgoffset) \ | ||||
for (_sg_iter_init(sgl, iter, nents, pgoffset); \ | for (_sg_iter_init(sgl, iter, nents, pgoffset); \ | ||||
(iter)->sg; _sg_iter_next(iter)) | (iter)->sg; _sg_iter_next(iter)) | ||||
#define for_each_sg_dma_page(sgl, iter, nents, pgoffset) \ | |||||
for_each_sg_page(sgl, &(iter)->base, nents, pgoffset) | |||||
#define for_each_sg(sglist, sg, sgmax, iter) \ | #define for_each_sg(sglist, sg, sgmax, iter) \ | ||||
Not Done Inline ActionsI think we need to do a simple cast here. hselasky: I think we need to do a simple cast here. | |||||
Not Done Inline ActionsI'm not sure I see what you mean. What part do you want to cast? Are you talking about casting iter and passing it to for_each_sg_page to avoid code duplication? ashafer_badland.io: I'm not sure I see what you mean. What part do you want to cast?
Are you talking about… | |||||
Not Done Inline ActionsI mean, how can we make this work w/o breaking any APIs? hselasky: I mean, how can we make this work w/o breaking any APIs? | |||||
for (iter = 0, sg = (sglist); iter < (sgmax); iter++, sg = sg_next(sg)) | for (iter = 0, sg = (sglist); iter < (sgmax); iter++, sg = sg_next(sg)) | ||||
typedef struct scatterlist *(sg_alloc_fn) (unsigned int, gfp_t); | typedef struct scatterlist *(sg_alloc_fn) (unsigned int, gfp_t); | ||||
typedef void (sg_free_fn) (struct scatterlist *, unsigned int); | typedef void (sg_free_fn) (struct scatterlist *, unsigned int); | ||||
static inline void | static inline void | ||||
sg_assign_page(struct scatterlist *sg, struct page *page) | sg_assign_page(struct scatterlist *sg, struct page *page) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 324 Lines • ▼ Show 20 Lines | while (piter->sg_pgoffset >= sg_page_count(piter->sg)) { | ||||
if (--piter->internal.nents == 0) | if (--piter->internal.nents == 0) | ||||
return (0); | return (0); | ||||
if (piter->sg == NULL) | if (piter->sg == NULL) | ||||
return (0); | return (0); | ||||
} | } | ||||
return (1); | return (1); | ||||
} | } | ||||
static int | |||||
sg_dma_page_count(struct scatterlist *sg) | |||||
{ | |||||
return PAGE_ALIGN(sg->offset + sg_dma_len(sg)) >> PAGE_SHIFT; | |||||
} | |||||
static inline bool | |||||
__sg_page_iter_dma_next(struct sg_dma_page_iter *dma_iter) | |||||
{ | |||||
struct sg_page_iter *piter = &dma_iter->base; | |||||
if (piter->internal.nents == 0) | |||||
return (0); | |||||
if (piter->sg == NULL) | |||||
return (0); | |||||
piter->sg_pgoffset += piter->internal.pg_advance; | |||||
piter->internal.pg_advance = 1; | |||||
while (piter->sg_pgoffset >= sg_dma_page_count(piter->sg)) { | |||||
piter->sg_pgoffset -= sg_dma_page_count(piter->sg); | |||||
piter->sg = sg_next(piter->sg); | |||||
if (--piter->internal.nents == 0) | |||||
return (0); | |||||
if (piter->sg == NULL) | |||||
return (0); | |||||
} | |||||
return (true); | |||||
Not Done Inline ActionsStyle: hselasky: Style:
return (true); | |||||
} | |||||
static inline void | static inline void | ||||
_sg_iter_init(struct scatterlist *sgl, struct sg_page_iter *iter, | _sg_iter_init(struct scatterlist *sgl, struct sg_page_iter *iter, | ||||
unsigned int nents, unsigned long pgoffset) | unsigned int nents, unsigned long pgoffset) | ||||
{ | { | ||||
if (nents) { | if (nents) { | ||||
iter->sg = sgl; | iter->sg = sgl; | ||||
iter->sg_pgoffset = pgoffset - 1; | iter->sg_pgoffset = pgoffset - 1; | ||||
iter->maxents = nents; | iter->maxents = nents; | ||||
_sg_iter_next(iter); | _sg_iter_next(iter); | ||||
} else { | } else { | ||||
iter->sg = NULL; | iter->sg = NULL; | ||||
iter->sg_pgoffset = 0; | iter->sg_pgoffset = 0; | ||||
iter->maxents = 0; | iter->maxents = 0; | ||||
} | } | ||||
} | } | ||||
/* | |||||
* Prevent api breakage by casting the itr | |||||
* argument to sg_page_iter. Newer drm code uses | |||||
* sg_dma_page_iter. This works because sg_dma_page_itr | |||||
* just wraps sg_page_iter. | |||||
*/ | |||||
#define sg_page_iter_dma_address(itr) \ | |||||
_sg_page_iter_dma_address((struct sg_page_iter *)itr) | |||||
static inline dma_addr_t | static inline dma_addr_t | ||||
sg_page_iter_dma_address(struct sg_page_iter *spi) | _sg_page_iter_dma_address(struct sg_page_iter *spi) | ||||
{ | { | ||||
return (spi->sg->dma_address + (spi->sg_pgoffset << PAGE_SHIFT)); | return (spi->sg->dma_address + (spi->sg_pgoffset << PAGE_SHIFT)); | ||||
} | } | ||||
static inline struct page * | static inline struct page * | ||||
sg_page_iter_page(struct sg_page_iter *piter) | sg_page_iter_page(struct sg_page_iter *piter) | ||||
{ | { | ||||
return (nth_page(sg_page(piter->sg), piter->sg_pgoffset)); | return (nth_page(sg_page(piter->sg), piter->sg_pgoffset)); | ||||
} | } | ||||
#endif /* _LINUX_SCATTERLIST_H_ */ | #endif /* _LINUX_SCATTERLIST_H_ */ |
Could we simply do: