1178786Skmacy/************************************************************************** 2178786Skmacy 3178786SkmacyCopyright (c) 2007, Chelsio Inc. 4178786SkmacyAll rights reserved. 5178786Skmacy 6178786SkmacyRedistribution and use in source and binary forms, with or without 7178786Skmacymodification, are permitted provided that the following conditions are met: 8178786Skmacy 9178786Skmacy 1. Redistributions of source code must retain the above copyright notice, 10178786Skmacy this list of conditions and the following disclaimer. 11178786Skmacy 12178786Skmacy 2. Neither the name of the Chelsio Corporation nor the names of its 13178786Skmacy contributors may be used to endorse or promote products derived from 14178786Skmacy this software without specific prior written permission. 15178786Skmacy 16178786SkmacyTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17178786SkmacyAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18178786SkmacyIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19178786SkmacyARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20178786SkmacyLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21178786SkmacyCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22178786SkmacySUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23178786SkmacyINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24178786SkmacyCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25178786SkmacyARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26178786SkmacyPOSSIBILITY OF SUCH DAMAGE. 27178786Skmacy 28178786Skmacy***************************************************************************/ 29178786Skmacy#include <sys/cdefs.h> 30178786Skmacy__FBSDID("$FreeBSD$"); 31178786Skmacy 32237263Snp#include "opt_inet.h" 33237263Snp 34178786Skmacy#include <sys/param.h> 35178786Skmacy#include <sys/systm.h> 36178786Skmacy#include <sys/kernel.h> 37178786Skmacy#include <sys/bus.h> 38178786Skmacy#include <sys/pciio.h> 39178786Skmacy#include <sys/conf.h> 40178786Skmacy#include <machine/bus.h> 41178786Skmacy#include <machine/resource.h> 42178786Skmacy#include <sys/bus_dma.h> 43178786Skmacy#include <sys/rman.h> 44178786Skmacy#include <sys/ioccom.h> 45178786Skmacy#include <sys/mbuf.h> 46178786Skmacy#include <sys/rwlock.h> 47178786Skmacy#include <sys/linker.h> 48178786Skmacy#include <sys/firmware.h> 49178786Skmacy#include <sys/socket.h> 50178786Skmacy#include <sys/sockio.h> 51178786Skmacy#include <sys/smp.h> 52178786Skmacy#include <sys/sysctl.h> 53178786Skmacy#include <sys/queue.h> 54178786Skmacy#include <sys/taskqueue.h> 55178786Skmacy#include <sys/proc.h> 56178786Skmacy#include <sys/eventhandler.h> 57183289Skmacy 58178786Skmacy#include <netinet/in.h> 59237263Snp#include <netinet/toecore.h> 60178786Skmacy 61237263Snp#include <rdma/ib_verbs.h> 62237263Snp#include <linux/idr.h> 63237263Snp#include <ulp/iw_cxgb/iw_cxgb_ib_intfc.h> 64178786Skmacy 65237263Snp#ifdef TCP_OFFLOAD 66178786Skmacy#include <cxgb_include.h> 67178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_wr.h> 68178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_hal.h> 69178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_provider.h> 70178786Skmacy#include <ulp/iw_cxgb/iw_cxgb_cm.h> 71178786Skmacy#include <ulp/iw_cxgb/iw_cxgb.h> 72178786Skmacy 73237263Snpstatic int iwch_mod_load(void); 74237263Snpstatic int iwch_mod_unload(void); 75237263Snpstatic int iwch_activate(struct adapter *); 76237263Snpstatic int iwch_deactivate(struct adapter *); 77178786Skmacy 78237263Snpstatic struct uld_info iwch_uld_info = { 79237263Snp .uld_id = ULD_IWARP, 80237263Snp .activate = iwch_activate, 81237263Snp .deactivate = iwch_deactivate, 82237263Snp}; 83178786Skmacy 84178786Skmacystatic void 85178786Skmacyrnic_init(struct iwch_dev *rnicp) 86178786Skmacy{ 87237263Snp 88178786Skmacy idr_init(&rnicp->cqidr); 89178786Skmacy idr_init(&rnicp->qpidr); 90178786Skmacy idr_init(&rnicp->mmidr); 91178786Skmacy mtx_init(&rnicp->lock, "iwch rnic lock", NULL, MTX_DEF|MTX_DUPOK); 92178786Skmacy 93178786Skmacy rnicp->attr.vendor_id = 0x168; 94178786Skmacy rnicp->attr.vendor_part_id = 7; 95178786Skmacy rnicp->attr.max_qps = T3_MAX_NUM_QP - 32; 96237263Snp rnicp->attr.max_wrs = T3_MAX_QP_DEPTH; 97178786Skmacy rnicp->attr.max_sge_per_wr = T3_MAX_SGE; 98178786Skmacy rnicp->attr.max_sge_per_rdma_write_wr = T3_MAX_SGE; 99178786Skmacy rnicp->attr.max_cqs = T3_MAX_NUM_CQ - 1; 100237263Snp rnicp->attr.max_cqes_per_cq = T3_MAX_CQ_DEPTH; 101178786Skmacy rnicp->attr.max_mem_regs = cxio_num_stags(&rnicp->rdev); 102178786Skmacy rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE; 103178786Skmacy rnicp->attr.max_pds = T3_MAX_NUM_PD - 1; 104237263Snp rnicp->attr.mem_pgsizes_bitmask = T3_PAGESIZE_MASK; 105237263Snp rnicp->attr.max_mr_size = T3_MAX_MR_SIZE; 106178786Skmacy rnicp->attr.can_resize_wq = 0; 107178786Skmacy rnicp->attr.max_rdma_reads_per_qp = 8; 108178786Skmacy rnicp->attr.max_rdma_read_resources = 109178786Skmacy rnicp->attr.max_rdma_reads_per_qp * rnicp->attr.max_qps; 110178786Skmacy rnicp->attr.max_rdma_read_qp_depth = 8; /* IRD */ 111178786Skmacy rnicp->attr.max_rdma_read_depth = 112178786Skmacy rnicp->attr.max_rdma_read_qp_depth * rnicp->attr.max_qps; 113178786Skmacy rnicp->attr.rq_overflow_handled = 0; 114178786Skmacy rnicp->attr.can_modify_ird = 0; 115178786Skmacy rnicp->attr.can_modify_ord = 0; 116178786Skmacy rnicp->attr.max_mem_windows = rnicp->attr.max_mem_regs - 1; 117178786Skmacy rnicp->attr.stag0_value = 1; 118178786Skmacy rnicp->attr.zbva_support = 1; 119178786Skmacy rnicp->attr.local_invalidate_fence = 1; 120178786Skmacy rnicp->attr.cq_overflow_detection = 1; 121237263Snp 122178786Skmacy return; 123178786Skmacy} 124178786Skmacy 125178786Skmacystatic void 126237263Snprnic_uninit(struct iwch_dev *rnicp) 127178786Skmacy{ 128237263Snp idr_destroy(&rnicp->cqidr); 129237263Snp idr_destroy(&rnicp->qpidr); 130237263Snp idr_destroy(&rnicp->mmidr); 131237263Snp mtx_destroy(&rnicp->lock); 132237263Snp} 133237263Snp 134237263Snpstatic int 135237263Snpiwch_activate(struct adapter *sc) 136237263Snp{ 137178786Skmacy struct iwch_dev *rnicp; 138237263Snp int rc; 139178786Skmacy 140237263Snp KASSERT(!isset(&sc->offload_map, MAX_NPORTS), 141237263Snp ("%s: iWARP already activated on %s", __func__, 142237263Snp device_get_nameunit(sc->dev))); 143237263Snp 144178786Skmacy rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp)); 145237263Snp if (rnicp == NULL) 146237263Snp return (ENOMEM); 147178786Skmacy 148237263Snp sc->iwarp_softc = rnicp; 149237263Snp rnicp->rdev.adap = sc; 150178786Skmacy 151237263Snp cxio_hal_init(sc); 152237263Snp iwch_cm_init_cpl(sc); 153237263Snp 154237263Snp rc = cxio_rdev_open(&rnicp->rdev); 155237263Snp if (rc != 0) { 156178786Skmacy printf("Unable to open CXIO rdev\n"); 157237263Snp goto err1; 158178786Skmacy } 159178786Skmacy 160178786Skmacy rnic_init(rnicp); 161178786Skmacy 162237263Snp rc = iwch_register_device(rnicp); 163237263Snp if (rc != 0) { 164178786Skmacy printf("Unable to register device\n"); 165237263Snp goto err2; 166178786Skmacy } 167237263Snp 168237263Snp return (0); 169237263Snp 170237263Snperr2: 171237263Snp rnic_uninit(rnicp); 172237263Snp cxio_rdev_close(&rnicp->rdev); 173237263Snperr1: 174237263Snp cxio_hal_uninit(sc); 175237263Snp iwch_cm_term_cpl(sc); 176237263Snp sc->iwarp_softc = NULL; 177237263Snp 178237263Snp return (rc); 179178786Skmacy} 180178786Skmacy 181237263Snpstatic int 182237263Snpiwch_deactivate(struct adapter *sc) 183178786Skmacy{ 184237263Snp struct iwch_dev *rnicp; 185178786Skmacy 186237263Snp rnicp = sc->iwarp_softc; 187237263Snp 188237263Snp iwch_unregister_device(rnicp); 189237263Snp rnic_uninit(rnicp); 190237263Snp cxio_rdev_close(&rnicp->rdev); 191237263Snp cxio_hal_uninit(sc); 192237263Snp iwch_cm_term_cpl(sc); 193237263Snp ib_dealloc_device(&rnicp->ibdev); 194237263Snp 195237263Snp sc->iwarp_softc = NULL; 196237263Snp 197237263Snp return (0); 198178786Skmacy} 199178786Skmacy 200237263Snpstatic void 201237263Snpiwch_activate_all(struct adapter *sc, void *arg __unused) 202178786Skmacy{ 203237263Snp ADAPTER_LOCK(sc); 204237263Snp if ((sc->open_device_map & sc->offload_map) != 0 && 205237263Snp t3_activate_uld(sc, ULD_IWARP) == 0) 206237263Snp setbit(&sc->offload_map, MAX_NPORTS); 207237263Snp ADAPTER_UNLOCK(sc); 208178786Skmacy} 209178786Skmacy 210237263Snpstatic void 211237263Snpiwch_deactivate_all(struct adapter *sc, void *arg __unused) 212237263Snp{ 213237263Snp ADAPTER_LOCK(sc); 214237263Snp if (isset(&sc->offload_map, MAX_NPORTS) && 215237263Snp t3_deactivate_uld(sc, ULD_IWARP) == 0) 216237263Snp clrbit(&sc->offload_map, MAX_NPORTS); 217237263Snp ADAPTER_UNLOCK(sc); 218237263Snp} 219178786Skmacy 220178786Skmacystatic int 221237263Snpiwch_mod_load(void) 222178786Skmacy{ 223237263Snp int rc; 224178786Skmacy 225237263Snp rc = iwch_cm_init(); 226237263Snp if (rc != 0) 227237263Snp return (rc); 228178786Skmacy 229237263Snp rc = t3_register_uld(&iwch_uld_info); 230237263Snp if (rc != 0) { 231237263Snp iwch_cm_term(); 232237263Snp return (rc); 233237263Snp } 234178786Skmacy 235237263Snp t3_iterate(iwch_activate_all, NULL); 236237263Snp 237237263Snp return (rc); 238178786Skmacy} 239178786Skmacy 240237263Snpstatic int 241237263Snpiwch_mod_unload(void) 242178786Skmacy{ 243237263Snp t3_iterate(iwch_deactivate_all, NULL); 244237263Snp 245178786Skmacy iwch_cm_term(); 246237263Snp 247237263Snp if (t3_unregister_uld(&iwch_uld_info) == EBUSY) 248237263Snp return (EBUSY); 249237263Snp 250237263Snp return (0); 251178786Skmacy} 252237263Snp#endif /* TCP_OFFLOAD */ 253178786Skmacy 254237263Snp#undef MODULE_VERSION 255237263Snp#include <sys/module.h> 256237263Snp 257237263Snpstatic int 258237263Snpiwch_modevent(module_t mod, int cmd, void *arg) 259178786Skmacy{ 260237263Snp int rc = 0; 261178786Skmacy 262237263Snp#ifdef TCP_OFFLOAD 263237263Snp switch (cmd) { 264237263Snp case MOD_LOAD: 265237263Snp rc = iwch_mod_load(); 266237263Snp if(rc) 267237263Snp printf("iw_cxgb: Chelsio T3 RDMA Driver failed to load\n"); 268237263Snp else 269237263Snp printf("iw_cxgb: Chelsio T3 RDMA Driver loaded\n"); 270237263Snp break; 271178786Skmacy 272237263Snp case MOD_UNLOAD: 273237263Snp rc = iwch_mod_unload(); 274237263Snp if(rc) 275237263Snp printf("iw_cxgb: Chelsio T3 RDMA Driver failed to unload\n"); 276237263Snp else 277237263Snp printf("iw_cxgb: Chelsio T3 RDMA Driver unloaded\n"); 278237263Snp break; 279178786Skmacy 280237263Snp default: 281237263Snp rc = EINVAL; 282237263Snp } 283237263Snp#else 284237263Snp printf("iw_cxgb: compiled without TCP_OFFLOAD support.\n"); 285237263Snp rc = EOPNOTSUPP; 286237263Snp#endif 287237263Snp return (rc); 288178786Skmacy} 289178786Skmacy 290237263Snpstatic moduledata_t iwch_mod_data = { 291178786Skmacy "iw_cxgb", 292237263Snp iwch_modevent, 293241394Skevlo 0 294178786Skmacy}; 295178786Skmacy 296178786SkmacyMODULE_VERSION(iw_cxgb, 1); 297237263SnpDECLARE_MODULE(iw_cxgb, iwch_mod_data, SI_SUB_EXEC, SI_ORDER_ANY); 298237263SnpMODULE_DEPEND(t3_tom, cxgbc, 1, 1, 1); 299237263SnpMODULE_DEPEND(iw_cxgb, toecore, 1, 1, 1); 300178786SkmacyMODULE_DEPEND(iw_cxgb, t3_tom, 1, 1, 1); 301256303SnpMODULE_DEPEND(iw_cxgb, ibcore, 1, 1, 1); 302