diff options
Diffstat (limited to 'include/linux/scatterlist.h')
-rw-r--r-- | include/linux/scatterlist.h | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index df7ddce..32326c2 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -1,6 +1,7 @@ #ifndef _LINUX_SCATTERLIST_H #define _LINUX_SCATTERLIST_H +#include <asm/types.h> #include <asm/scatterlist.h> #include <linux/mm.h> #include <linux/string.h> @@ -26,18 +27,16 @@ #define SG_MAGIC 0x87654321 /** - * sg_set_page - Set sg entry to point at given page - * @sg: SG entry - * @page: The page + * sg_assign_page - Assign a given page to an SG entry + * @sg: SG entry + * @page: The page * * Description: - * Use this function to set an sg entry pointing at a page, never assign - * the page directly. We encode sg table information in the lower bits - * of the page pointer. See sg_page() for looking up the page belonging - * to an sg entry. + * Assign page to sg entry. Also see sg_set_page(), the most commonly used + * variant. * **/ -static inline void sg_set_page(struct scatterlist *sg, struct page *page) +static inline void sg_assign_page(struct scatterlist *sg, struct page *page) { unsigned long page_link = sg->page_link & 0x3; @@ -52,6 +51,28 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page) sg->page_link = page_link | (unsigned long) page; } +/** + * sg_set_page - Set sg entry to point at given page + * @sg: SG entry + * @page: The page + * @len: Length of data + * @offset: Offset into page + * + * Description: + * Use this function to set an sg entry pointing at a page, never assign + * the page directly. We encode sg table information in the lower bits + * of the page pointer. See sg_page() for looking up the page belonging + * to an sg entry. + * + **/ +static inline void sg_set_page(struct scatterlist *sg, struct page *page, + unsigned int len, unsigned int offset) +{ + sg_assign_page(sg, page); + sg->offset = offset; + sg->length = len; +} + #define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3)) /** @@ -64,9 +85,7 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page) static inline void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen) { - sg_set_page(sg, virt_to_page(buf)); - sg->offset = offset_in_page(buf); - sg->length = buflen; + sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); } /* @@ -131,7 +150,7 @@ static inline struct scatterlist *sg_last(struct scatterlist *sgl, struct scatterlist *ret = &sgl[nents - 1]; #else struct scatterlist *sg, *ret = NULL; - int i; + unsigned int i; for_each_sg(sgl, sg, nents, i) ret = sg; @@ -160,7 +179,11 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, #ifndef ARCH_HAS_SG_CHAIN BUG(); #endif - prv[prv_nents - 1].page_link = (unsigned long) sgl | 0x01; + /* + * Set lowest bit to indicate a link pointer, and make sure to clear + * the termination bit if it happens to be set. + */ + prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02; } /** @@ -220,7 +243,7 @@ static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) sg_mark_end(sgl, nents); #ifdef CONFIG_DEBUG_SG { - int i; + unsigned int i; for (i = 0; i < nents; i++) sgl[i].sg_magic = SG_MAGIC; } @@ -237,7 +260,7 @@ static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) * on the sg page. * **/ -static inline unsigned long sg_phys(struct scatterlist *sg) +static inline dma_addr_t sg_phys(struct scatterlist *sg) { return page_to_phys(sg_page(sg)) + sg->offset; } |