iw_cxgb_mem.c revision 178786
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 178786 2008-05-05 18:46:18Z 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 67#ifdef CONFIG_DEFINED 68#include <cxgb_include.h> 69#include <ulp/iw_cxgb/iw_cxgb_wr.h> 70#include <ulp/iw_cxgb/iw_cxgb_hal.h> 71#include <ulp/iw_cxgb/iw_cxgb_provider.h> 72#include <ulp/iw_cxgb/iw_cxgb_cm.h> 73#include <ulp/iw_cxgb/iw_cxgb.h> 74#include <ulp/iw_cxgb/iw_cxgb_resource.h> 75#include <ulp/iw_cxgb/iw_cxgb_user.h> 76#else 77#include <dev/cxgb/cxgb_include.h> 78#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_wr.h> 79#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_hal.h> 80#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_provider.h> 81#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_cm.h> 82#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb.h> 83#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_resource.h> 84#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_user.h> 85#endif 86 87 88int iwch_register_mem(struct iwch_dev *rhp, struct iwch_pd *php, 89 struct iwch_mr *mhp, 90 int shift, 91 __be64 *page_list) 92{ 93 u32 stag; 94 u32 mmid; 95 96 97 if (cxio_register_phys_mem(&rhp->rdev, 98 &stag, mhp->attr.pdid, 99 mhp->attr.perms, 100 mhp->attr.zbva, 101 mhp->attr.va_fbo, 102 mhp->attr.len, 103 shift-12, 104 page_list, 105 &mhp->attr.pbl_size, &mhp->attr.pbl_addr)) 106 return (-ENOMEM); 107 mhp->attr.state = 1; 108 mhp->attr.stag = stag; 109 mmid = stag >> 8; 110 mhp->ibmr.rkey = mhp->ibmr.lkey = stag; 111 insert_handle(rhp, &rhp->mmidr, mhp, mmid); 112 CTR3(KTR_IW_CXGB, "%s mmid 0x%x mhp %p", __FUNCTION__, mmid, mhp); 113 return 0; 114} 115 116int iwch_reregister_mem(struct iwch_dev *rhp, struct iwch_pd *php, 117 struct iwch_mr *mhp, 118 int shift, 119 __be64 *page_list, 120 int npages) 121{ 122 u32 stag; 123 u32 mmid; 124 125 126 /* We could support this... */ 127 if (npages > mhp->attr.pbl_size) 128 return (-ENOMEM); 129 130 stag = mhp->attr.stag; 131 if (cxio_reregister_phys_mem(&rhp->rdev, 132 &stag, mhp->attr.pdid, 133 mhp->attr.perms, 134 mhp->attr.zbva, 135 mhp->attr.va_fbo, 136 mhp->attr.len, 137 shift-12, 138 page_list, 139 &mhp->attr.pbl_size, &mhp->attr.pbl_addr)) 140 return (-ENOMEM); 141 mhp->attr.state = 1; 142 mhp->attr.stag = stag; 143 mmid = stag >> 8; 144 mhp->ibmr.rkey = mhp->ibmr.lkey = stag; 145 insert_handle(rhp, &rhp->mmidr, mhp, mmid); 146 CTR3(KTR_IW_CXGB, "%s mmid 0x%x mhp %p", __FUNCTION__, mmid, mhp); 147 return 0; 148} 149 150int build_phys_page_list(struct ib_phys_buf *buffer_list, 151 int num_phys_buf, 152 u64 *iova_start, 153 u64 *total_size, 154 int *npages, 155 int *shift, 156 __be64 **page_list) 157{ 158 u64 mask; 159 int i, j, n; 160 161 mask = 0; 162 *total_size = 0; 163 for (i = 0; i < num_phys_buf; ++i) { 164 if (i != 0 && buffer_list[i].addr & ~PAGE_MASK) 165 return (-EINVAL); 166 if (i != 0 && i != num_phys_buf - 1 && 167 (buffer_list[i].size & ~PAGE_MASK)) 168 return (-EINVAL); 169 *total_size += buffer_list[i].size; 170 if (i > 0) 171 mask |= buffer_list[i].addr; 172 else 173 mask |= buffer_list[i].addr & PAGE_MASK; 174 if (i != num_phys_buf - 1) 175 mask |= buffer_list[i].addr + buffer_list[i].size; 176 else 177 mask |= (buffer_list[i].addr + buffer_list[i].size + 178 PAGE_SIZE - 1) & PAGE_MASK; 179 } 180 181 if (*total_size > 0xFFFFFFFFULL) 182 return (-ENOMEM); 183 184 /* Find largest page shift we can use to cover buffers */ 185 for (*shift = PAGE_SHIFT; *shift < 27; ++(*shift)) 186 if ((1ULL << *shift) & mask) 187 break; 188 189 buffer_list[0].size += buffer_list[0].addr & ((1ULL << *shift) - 1); 190 buffer_list[0].addr &= ~0ull << *shift; 191 192 *npages = 0; 193 for (i = 0; i < num_phys_buf; ++i) 194 *npages += (buffer_list[i].size + 195 (1ULL << *shift) - 1) >> *shift; 196 197 if (!*npages) 198 return (-EINVAL); 199 200 *page_list = kmalloc(sizeof(u64) * *npages, M_NOWAIT); 201 if (!*page_list) 202 return (-ENOMEM); 203 204 n = 0; 205 for (i = 0; i < num_phys_buf; ++i) 206 for (j = 0; 207 j < (buffer_list[i].size + (1ULL << *shift) - 1) >> *shift; 208 ++j) 209 (*page_list)[n++] = htobe64(buffer_list[i].addr + 210 ((u64) j << *shift)); 211 212 CTR6(KTR_IW_CXGB, "%s va 0x%llx mask 0x%llx shift %d len %lld pbl_size %d", 213 __FUNCTION__, (unsigned long long) *iova_start, 214 (unsigned long long) mask, *shift, (unsigned long long) *total_size, 215 *npages); 216 217 return 0; 218 219} 220