scatterlist.h revision 219820
1/*-
2 * Copyright (c) 2010 Isilon Systems, Inc.
3 * Copyright (c) 2010 iX Systems, Inc.
4 * Copyright (c) 2010 Panasas, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice unmodified, this list of conditions, and the following
12 *    disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28#ifndef	_LINUX_SCATTERLIST_H_
29#define	_LINUX_SCATTERLIST_H_
30
31#include <linux/string.h>
32#include <linux/page.h>
33
34struct scatterlist {
35	union {
36		struct page		*page;
37		struct scatterlist	*sg;
38	} sl_un;
39	unsigned long	address;
40	unsigned long	offset;
41	uint32_t	length;
42	uint32_t	flags;
43};
44
45#define	sg_dma_address(sg)	(sg)->address
46#define	sg_dma_len(sg)		(sg)->length
47#define	sg_page(sg)		(sg)->sl_un.page
48#define	sg_scatternext(sg)	(sg)->sl_un.sg
49
50#define	SG_END		0x01
51#define	SG_CHAIN	0x02
52
53static inline void
54sg_set_page(struct scatterlist *sg, struct page *page, unsigned int len,
55    unsigned int offset)
56{
57	sg_page(sg) = page;
58	sg_dma_len(sg) = len;
59	sg->offset = offset;
60	if (offset > PAGE_SIZE)
61		panic("sg_set_page: Invalid offset %d\n", offset);
62}
63
64static inline void
65sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen)
66{
67	sg_set_page(sg, virt_to_page(buf), buflen,
68	    ((uintptr_t)buf) & ~PAGE_MASK);
69}
70
71static inline void
72sg_init_table(struct scatterlist *sg, unsigned int nents)
73{
74	bzero(sg, sizeof(*sg) * nents);
75	sg[nents - 1].flags = SG_END;
76}
77
78static inline struct scatterlist *
79sg_next(struct scatterlist *sg)
80{
81	if (sg->flags & SG_END)
82		return (NULL);
83	sg++;
84	if (sg->flags & SG_CHAIN)
85		sg = sg_scatternext(sg);
86	return (sg);
87}
88
89static inline vm_paddr_t
90sg_phys(struct scatterlist *sg)
91{
92	return sg_page(sg)->phys_addr + sg->offset;
93}
94
95#define	for_each_sg(sglist, sg, sgmax, _itr)				\
96	for (_itr = 0, sg = (sglist); _itr < (sgmax); _itr++, sg = sg_next(sg))
97
98#endif	/* _LINUX_SCATTERLIST_H_ */
99