scatterlist
linux-dash
A beautiful web dashboard for Linux
项目地址:https://gitcode.com/gh_mirrors/li/linux-dash
免费下载资源
·
Author: Yang Honggang (Joseph) <eagle.rtlinux@gmail.com>
Dslab lzu
Last Modified: 12-03-2011
NOTE: Kernel Version linux-2.6.38.8
-----------------------------------------------------------------------
This article just explain how to use scatterlist and the initializtion
of scatterlist. As to How to Use the Scatter/Gather APIs, you can
refer Documentation/DMA* for more information.
----------------------------------------------------------------------
contents:
1> structure explanation
2> How to init the scatterlist
3> Find the next scatterlist entry
===============================================
1> structure explanation
struct scatterlist {
...
/* User input members */
unsigned long page_link;// pointer to a page, but the bit0 and bit1 have special info.[1]
unsigned int offset; / / Offset of data buffer in page referred by @page_link
unsigned int length; //Length of data
/* Output value */
dma_addr_t dma_address; // this address can be used by device to do DMA
...
};
[1]: Explanation of 'page_link' in struct scatterlist
If bit 0 is set, then the page_link contains a pointer to the next sg
table list. Otherwise the next entry is at sg + 1.
If bit 1 is set, then this sg entry is the last element in a list.
/*
* We overload the LSB of the page pointer to indicate whether it's
* a valid sg entry, or whether it points to the start of a new scatterlist.
* Those low bits are there for everyone! (thanks mason :-)
*/
#define sg_is_chain(sg) ((sg)->page_link & 0x01)
#define sg_is_last(sg) ((sg)->page_link & 0x02)
#define sg_chain_ptr(sg) \
((struct scatterlist *) ((sg)->page_link & ~0x03))
2> How to init the scatterlist
/**
* sg_assign_page - Assign a given page to an SG entry
* @sg: SG entry
* @page: The page
*
* Description:
* Assign page to sg entry. Also see sg_set_page(), the most commonly used
* variant.
*
**/
static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
{
unsigned long page_link = sg->page_link & 0x3;
/*
* In order for the low bit stealing approach to work, pages
* must be aligned at a 32-bit boundary as a minimum.
*/
BUG_ON((unsigned long) page & 0x03);
...
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 // Offset in 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;
}
/**
* sg_set_buf - Set sg entry to point at given data
* @sg: SG entry
* @buf: Data
* @buflen: Data length
*
**/
static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
unsigned int buflen)
{
/* offset_in_page(buf) will get the offset in a page */
sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
}
// ~PAGE_MASK = 0xfff
#define offset_in_page(p) ((unsigned long )(p) & ~PAGE_MASK)// Get the lowest 12bits.
// That's the offset in a page.
3> Find the next scatterlist entry
/**
* sg_next - return the next scatterlist entry in a list
* @sg: The current sg entry
*
* Description:
* Usually the next entry will be @sg@ + 1, but if this sg element is part
* of a chained scatterlist, it could jump to the start of a new
* scatterlist array.
*
**/
struct scatterlist *sg_next(struct scatterlist *sg)
{
...
if (sg_is_last(sg))
return NULL;
sg++;
if (unlikely(sg_is_chain(sg)))
sg = sg_chain_ptr(sg);
return sg;
}
EXPORT_SYMBOL(sg_next);
Dslab lzu
Last Modified: 12-03-2011
NOTE: Kernel Version linux-2.6.38.8
-----------------------------------------------------------------------
This article just explain how to use scatterlist and the initializtion
of scatterlist. As to How to Use the Scatter/Gather APIs, you can
refer Documentation/DMA* for more information.
----------------------------------------------------------------------
contents:
1> structure explanation
2> How to init the scatterlist
3> Find the next scatterlist entry
===============================================
1> structure explanation
struct scatterlist {
...
/* User input members */
unsigned long page_link;// pointer to a page, but the bit0 and bit1 have special info.[1]
unsigned int offset; / / Offset of data buffer in page referred by @page_link
unsigned int length; //Length of data
/* Output value */
dma_addr_t dma_address; // this address can be used by device to do DMA
...
};
[1]: Explanation of 'page_link' in struct scatterlist
If bit 0 is set, then the page_link contains a pointer to the next sg
table list. Otherwise the next entry is at sg + 1.
If bit 1 is set, then this sg entry is the last element in a list.
/*
* We overload the LSB of the page pointer to indicate whether it's
* a valid sg entry, or whether it points to the start of a new scatterlist.
* Those low bits are there for everyone! (thanks mason :-)
*/
#define sg_is_chain(sg) ((sg)->page_link & 0x01)
#define sg_is_last(sg) ((sg)->page_link & 0x02)
#define sg_chain_ptr(sg) \
((struct scatterlist *) ((sg)->page_link & ~0x03))
2> How to init the scatterlist
/**
* sg_assign_page - Assign a given page to an SG entry
* @sg: SG entry
* @page: The page
*
* Description:
* Assign page to sg entry. Also see sg_set_page(), the most commonly used
* variant.
*
**/
static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
{
unsigned long page_link = sg->page_link & 0x3;
/*
* In order for the low bit stealing approach to work, pages
* must be aligned at a 32-bit boundary as a minimum.
*/
BUG_ON((unsigned long) page & 0x03);
...
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 // Offset in 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;
}
/**
* sg_set_buf - Set sg entry to point at given data
* @sg: SG entry
* @buf: Data
* @buflen: Data length
*
**/
static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
unsigned int buflen)
{
/* offset_in_page(buf) will get the offset in a page */
sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
}
// ~PAGE_MASK = 0xfff
#define offset_in_page(p) ((unsigned long )(p) & ~PAGE_MASK)// Get the lowest 12bits.
// That's the offset in a page.
3> Find the next scatterlist entry
/**
* sg_next - return the next scatterlist entry in a list
* @sg: The current sg entry
*
* Description:
* Usually the next entry will be @sg@ + 1, but if this sg element is part
* of a chained scatterlist, it could jump to the start of a new
* scatterlist array.
*
**/
struct scatterlist *sg_next(struct scatterlist *sg)
{
...
if (sg_is_last(sg))
return NULL;
sg++;
if (unlikely(sg_is_chain(sg)))
sg = sg_chain_ptr(sg);
return sg;
}
EXPORT_SYMBOL(sg_next);
GitHub 加速计划 / li / linux-dash
6
1
下载
A beautiful web dashboard for Linux
最近提交(Master分支:3 个月前 )
186a802e
added ecosystem file for PM2 4 年前
5def40a3
Add host customization support for the NodeJS version 4 年前
更多推荐
已为社区贡献9条内容
所有评论(0)