iw_cxgb_mem.c revision 183292
1/************************************************************************** 2 3Copyright (c) 2007, Chelsio Inc. 4All rights reserved. 5 6Redistribution and use in source and binary forms, with or without 7modification, are permitted provided that the following conditions are met: 8 9 1. Redistributions of source code must retain the above copyright notice, 10 this list of conditions and the following disclaimer. 11 12 2. Neither the name of the Chelsio Corporation nor the names of its 13 contributors may be used to endorse or promote products derived from 14 this software without specific prior written permission. 15 16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26POSSIBILITY OF SUCH DAMAGE. 27 28***************************************************************************/ 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: head/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb_mem.c 183292 2008-09-23 03:16:54Z kmacy $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/kernel.h> 35#include <sys/bus.h> 36#include <sys/module.h> 37#include <sys/pciio.h> 38#include <sys/conf.h> 39#include <machine/bus.h> 40#include <machine/resource.h> 41#include <sys/bus_dma.h> 42#include <sys/rman.h> 43#include <sys/ioccom.h> 44#include <sys/mbuf.h> 45#include <sys/mutex.h> 46#include <sys/rwlock.h> 47#include <sys/linker.h> 48#include <sys/firmware.h> 49#include <sys/socket.h> 50#include <sys/sockio.h> 51#include <sys/smp.h> 52#include <sys/sysctl.h> 53#include <sys/syslog.h> 54#include <sys/queue.h> 55#include <sys/taskqueue.h> 56#include <sys/proc.h> 57#include <sys/queue.h> 58#include <sys/libkern.h> 59 60#include <netinet/in.h> 61 62#include <contrib/rdma/ib_verbs.h> 63#include <contrib/rdma/ib_umem.h> 64#include <contrib/rdma/ib_user_verbs.h> 65 66#include <cxgb_include.h> 67#include <ulp/iw_cxgb/iw_cxgb_wr.h> 68#include <ulp/iw_cxgb/iw_cxgb_hal.h> 69#include <ulp/iw_cxgb/iw_cxgb_provider.h> 70#include <ulp/iw_cxgb/iw_cxgb_cm.h> 71#include <ulp/iw_cxgb/iw_cxgb.h> 72#include <ulp/iw_cxgb/iw_cxgb_resource.h> 73#include <ulp/iw_cxgb/iw_cxgb_user.h> 74 75int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php, 76 struct iwch_mr *mhp, 77 int shift, 78 __be64 *page_list) 79{ 80 u32 stag; 81 u32 mmid; 82 83 84 if (cxio_register_phys_mem(&rhp->rdev, 85 &stag, mhp->attr.pdid, 86 mhp->attr.perms, 87 mhp->attr.zbva, 88 mhp->attr.va_fbo, 89 mhp->attr.len, 90 shift-12, 91 page_list, 92 &mhp->attr.pbl_size, &mhp->attr.pbl_addr)) 93 return (-ENOMEM); 94 mhp->attr.state = 1; 95 mhp->attr.stag = stag; 96 mmid = stag >> 8; 97 mhp->ibmr.rkey = mhp->ibmr.lkey = stag; 98 insert_handle(rhp, &rhp->mmidr, mhp, mmid); 99 CTR3(KTR_IW_CXGB, "%s mmid 0x%x mhp %p", __FUNCTION__, mmid, mhp); 100 return 0; 101} 102 103int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php, 104 struct iwch_mr *mhp, 105 int shift, 106 __be64 *page_list, 107 int npages) 108{ 109 u32 stag; 110 u32 mmid; 111 112 113 /* We could support this... */ 114 if (npages > mhp->attr.pbl_size) 115 return (-ENOMEM); 116 117 stag = mhp->attr.stag; 118 if (cxio_reregister_phys_mem(&rhp->rdev, 119 &stag, mhp->attr.pdid, 120 mhp->attr.perms, 121 mhp->attr.zbva, 122 mhp->attr.va_fbo, 123 mhp->attr.len, 124 shift-12, 125 page_list, 126 &mhp->attr.pbl_size, &mhp->attr.pbl_addr)) 127 return (-ENOMEM); 128 mhp->attr.state = 1; 129 mhp->attr.stag = stag; 130 mmid = stag >> 8; 131 mhp->ibmr.rkey = mhp->ibmr.lkey = stag; 132 insert_handle(rhp, &rhp->mmidr, mhp, mmid); 133 CTR3(KTR_IW_CXGB, "%s mmid 0x%x mhp %p", __FUNCTION__, mmid, mhp); 134 return 0; 135} 136 137int build_phys_page_list(struct ib_phys_buf *buffer_list, 138 int num_phys_buf, 139 u64 *iova_start, 140 u64 *total_size, 141 int *npages, 142 int *shift, 143 __be64 **page_list) 144{ 145 u64 mask; 146 int i, j, n; 147 148 mask = 0; 149 *total_size = 0; 150 for (i = 0; i < num_phys_buf; ++i) { 151 if (i != 0 && buffer_list[i].addr & ~PAGE_MASK) 152 return (-EINVAL); 153 if (i != 0 && i != num_phys_buf - 1 && 154 (buffer_list[i].size & ~PAGE_MASK)) 155 return (-EINVAL); 156 *total_size += buffer_list[i].size; 157 if (i > 0) 158 mask |= buffer_list[i].addr; 159 else 160 mask |= buffer_list[i].addr & PAGE_MASK; 161 if (i != num_phys_buf - 1) 162 mask |= buffer_list[i].addr + buffer_list[i].size; 163 else 164 mask |= (buffer_list[i].addr + buffer_list[i].size + 165 PAGE_SIZE - 1) & PAGE_MASK; 166 } 167 168 if (*total_size > 0xFFFFFFFFULL) 169 return (-ENOMEM); 170 171 /* Find largest page shift we can use to cover buffers */ 172 for (*shift = PAGE_SHIFT; *shift < 27; ++(*shift)) 173 if ((1ULL << *shift) & mask) 174 break; 175 176 buffer_list[0].size += buffer_list[0].addr & ((1ULL << *shift) - 1); 177 buffer_list[0].addr &= ~0ull << *shift; 178 179 *npages = 0; 180 for (i = 0; i < num_phys_buf; ++i) 181 *npages += (buffer_list[i].size + 182 (1ULL << *shift) - 1) >> *shift; 183 184 if (!*npages) 185 return (-EINVAL); 186 187 *page_list = kmalloc(sizeof(u64) * *npages, M_NOWAIT); 188 if (!*page_list) 189 return (-ENOMEM); 190 191 n = 0; 192 for (i = 0; i < num_phys_buf; ++i) 193 for (j = 0; 194 j < (buffer_list[i].size + (1ULL << *shift) - 1) >> *shift; 195 ++j) 196 (*page_list)[n++] = htobe64(buffer_list[i].addr + 197 ((u64) j << *shift)); 198 199 CTR6(KTR_IW_CXGB, "%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d", 200 __FUNCTION__, (unsigned long long) *iova_start, 201 (unsigned long long) mask, *shift, (unsigned long long) *total_size, 202 *npages); 203 204 return 0; 205 206} 207