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