iw_cxgb.c revision 256303
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: stable/10/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb.c 256303 2013-10-10 22:44:29Z np $"); 31 32#include "opt_inet.h" 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/kernel.h> 37#include <sys/bus.h> 38#include <sys/pciio.h> 39#include <sys/conf.h> 40#include <machine/bus.h> 41#include <machine/resource.h> 42#include <sys/bus_dma.h> 43#include <sys/rman.h> 44#include <sys/ioccom.h> 45#include <sys/mbuf.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/queue.h> 54#include <sys/taskqueue.h> 55#include <sys/proc.h> 56#include <sys/eventhandler.h> 57 58#include <netinet/in.h> 59#include <netinet/toecore.h> 60 61#include <rdma/ib_verbs.h> 62#include <linux/idr.h> 63#include <ulp/iw_cxgb/iw_cxgb_ib_intfc.h> 64 65#ifdef TCP_OFFLOAD 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 73static int iwch_mod_load(void); 74static int iwch_mod_unload(void); 75static int iwch_activate(struct adapter *); 76static int iwch_deactivate(struct adapter *); 77 78static struct uld_info iwch_uld_info = { 79 .uld_id = ULD_IWARP, 80 .activate = iwch_activate, 81 .deactivate = iwch_deactivate, 82}; 83 84static void 85rnic_init(struct iwch_dev *rnicp) 86{ 87 88 idr_init(&rnicp->cqidr); 89 idr_init(&rnicp->qpidr); 90 idr_init(&rnicp->mmidr); 91 mtx_init(&rnicp->lock, "iwch rnic lock", NULL, MTX_DEF|MTX_DUPOK); 92 93 rnicp->attr.vendor_id = 0x168; 94 rnicp->attr.vendor_part_id = 7; 95 rnicp->attr.max_qps = T3_MAX_NUM_QP - 32; 96 rnicp->attr.max_wrs = T3_MAX_QP_DEPTH; 97 rnicp->attr.max_sge_per_wr = T3_MAX_SGE; 98 rnicp->attr.max_sge_per_rdma_write_wr = T3_MAX_SGE; 99 rnicp->attr.max_cqs = T3_MAX_NUM_CQ - 1; 100 rnicp->attr.max_cqes_per_cq = T3_MAX_CQ_DEPTH; 101 rnicp->attr.max_mem_regs = cxio_num_stags(&rnicp->rdev); 102 rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE; 103 rnicp->attr.max_pds = T3_MAX_NUM_PD - 1; 104 rnicp->attr.mem_pgsizes_bitmask = T3_PAGESIZE_MASK; 105 rnicp->attr.max_mr_size = T3_MAX_MR_SIZE; 106 rnicp->attr.can_resize_wq = 0; 107 rnicp->attr.max_rdma_reads_per_qp = 8; 108 rnicp->attr.max_rdma_read_resources = 109 rnicp->attr.max_rdma_reads_per_qp * rnicp->attr.max_qps; 110 rnicp->attr.max_rdma_read_qp_depth = 8; /* IRD */ 111 rnicp->attr.max_rdma_read_depth = 112 rnicp->attr.max_rdma_read_qp_depth * rnicp->attr.max_qps; 113 rnicp->attr.rq_overflow_handled = 0; 114 rnicp->attr.can_modify_ird = 0; 115 rnicp->attr.can_modify_ord = 0; 116 rnicp->attr.max_mem_windows = rnicp->attr.max_mem_regs - 1; 117 rnicp->attr.stag0_value = 1; 118 rnicp->attr.zbva_support = 1; 119 rnicp->attr.local_invalidate_fence = 1; 120 rnicp->attr.cq_overflow_detection = 1; 121 122 return; 123} 124 125static void 126rnic_uninit(struct iwch_dev *rnicp) 127{ 128 idr_destroy(&rnicp->cqidr); 129 idr_destroy(&rnicp->qpidr); 130 idr_destroy(&rnicp->mmidr); 131 mtx_destroy(&rnicp->lock); 132} 133 134static int 135iwch_activate(struct adapter *sc) 136{ 137 struct iwch_dev *rnicp; 138 int rc; 139 140 KASSERT(!isset(&sc->offload_map, MAX_NPORTS), 141 ("%s: iWARP already activated on %s", __func__, 142 device_get_nameunit(sc->dev))); 143 144 rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp)); 145 if (rnicp == NULL) 146 return (ENOMEM); 147 148 sc->iwarp_softc = rnicp; 149 rnicp->rdev.adap = sc; 150 151 cxio_hal_init(sc); 152 iwch_cm_init_cpl(sc); 153 154 rc = cxio_rdev_open(&rnicp->rdev); 155 if (rc != 0) { 156 printf("Unable to open CXIO rdev\n"); 157 goto err1; 158 } 159 160 rnic_init(rnicp); 161 162 rc = iwch_register_device(rnicp); 163 if (rc != 0) { 164 printf("Unable to register device\n"); 165 goto err2; 166 } 167 168 return (0); 169 170err2: 171 rnic_uninit(rnicp); 172 cxio_rdev_close(&rnicp->rdev); 173err1: 174 cxio_hal_uninit(sc); 175 iwch_cm_term_cpl(sc); 176 sc->iwarp_softc = NULL; 177 178 return (rc); 179} 180 181static int 182iwch_deactivate(struct adapter *sc) 183{ 184 struct iwch_dev *rnicp; 185 186 rnicp = sc->iwarp_softc; 187 188 iwch_unregister_device(rnicp); 189 rnic_uninit(rnicp); 190 cxio_rdev_close(&rnicp->rdev); 191 cxio_hal_uninit(sc); 192 iwch_cm_term_cpl(sc); 193 ib_dealloc_device(&rnicp->ibdev); 194 195 sc->iwarp_softc = NULL; 196 197 return (0); 198} 199 200static void 201iwch_activate_all(struct adapter *sc, void *arg __unused) 202{ 203 ADAPTER_LOCK(sc); 204 if ((sc->open_device_map & sc->offload_map) != 0 && 205 t3_activate_uld(sc, ULD_IWARP) == 0) 206 setbit(&sc->offload_map, MAX_NPORTS); 207 ADAPTER_UNLOCK(sc); 208} 209 210static void 211iwch_deactivate_all(struct adapter *sc, void *arg __unused) 212{ 213 ADAPTER_LOCK(sc); 214 if (isset(&sc->offload_map, MAX_NPORTS) && 215 t3_deactivate_uld(sc, ULD_IWARP) == 0) 216 clrbit(&sc->offload_map, MAX_NPORTS); 217 ADAPTER_UNLOCK(sc); 218} 219 220static int 221iwch_mod_load(void) 222{ 223 int rc; 224 225 rc = iwch_cm_init(); 226 if (rc != 0) 227 return (rc); 228 229 rc = t3_register_uld(&iwch_uld_info); 230 if (rc != 0) { 231 iwch_cm_term(); 232 return (rc); 233 } 234 235 t3_iterate(iwch_activate_all, NULL); 236 237 return (rc); 238} 239 240static int 241iwch_mod_unload(void) 242{ 243 t3_iterate(iwch_deactivate_all, NULL); 244 245 iwch_cm_term(); 246 247 if (t3_unregister_uld(&iwch_uld_info) == EBUSY) 248 return (EBUSY); 249 250 return (0); 251} 252#endif /* TCP_OFFLOAD */ 253 254#undef MODULE_VERSION 255#include <sys/module.h> 256 257static int 258iwch_modevent(module_t mod, int cmd, void *arg) 259{ 260 int rc = 0; 261 262#ifdef TCP_OFFLOAD 263 switch (cmd) { 264 case MOD_LOAD: 265 rc = iwch_mod_load(); 266 if(rc) 267 printf("iw_cxgb: Chelsio T3 RDMA Driver failed to load\n"); 268 else 269 printf("iw_cxgb: Chelsio T3 RDMA Driver loaded\n"); 270 break; 271 272 case MOD_UNLOAD: 273 rc = iwch_mod_unload(); 274 if(rc) 275 printf("iw_cxgb: Chelsio T3 RDMA Driver failed to unload\n"); 276 else 277 printf("iw_cxgb: Chelsio T3 RDMA Driver unloaded\n"); 278 break; 279 280 default: 281 rc = EINVAL; 282 } 283#else 284 printf("iw_cxgb: compiled without TCP_OFFLOAD support.\n"); 285 rc = EOPNOTSUPP; 286#endif 287 return (rc); 288} 289 290static moduledata_t iwch_mod_data = { 291 "iw_cxgb", 292 iwch_modevent, 293 0 294}; 295 296MODULE_VERSION(iw_cxgb, 1); 297DECLARE_MODULE(iw_cxgb, iwch_mod_data, SI_SUB_EXEC, SI_ORDER_ANY); 298MODULE_DEPEND(t3_tom, cxgbc, 1, 1, 1); 299MODULE_DEPEND(iw_cxgb, toecore, 1, 1, 1); 300MODULE_DEPEND(iw_cxgb, t3_tom, 1, 1, 1); 301MODULE_DEPEND(iw_cxgb, ibcore, 1, 1, 1); 302