1 /**************************************************************************
3 Copyright (c) 2007, Chelsio Inc.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
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.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY OF SUCH DAMAGE.
28 ***************************************************************************/
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
36 #include <sys/module.h>
37 #include <sys/pciio.h>
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41 #include <sys/bus_dma.h>
43 #include <sys/ioccom.h>
45 #include <sys/rwlock.h>
46 #include <sys/linker.h>
47 #include <sys/firmware.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
51 #include <sys/sysctl.h>
52 #include <sys/queue.h>
53 #include <sys/taskqueue.h>
55 #include <sys/eventhandler.h>
57 #if __FreeBSD_version < 800044
62 #include <net/if_var.h>
63 #if __FreeBSD_version >= 800056
67 #include <netinet/in.h>
69 #include <contrib/rdma/ib_verbs.h>
71 #include <cxgb_include.h>
72 #include <ulp/iw_cxgb/iw_cxgb_wr.h>
73 #include <ulp/iw_cxgb/iw_cxgb_hal.h>
74 #include <ulp/iw_cxgb/iw_cxgb_provider.h>
75 #include <ulp/iw_cxgb/iw_cxgb_cm.h>
76 #include <ulp/iw_cxgb/iw_cxgb.h>
85 cxgb_cpl_handler_func t3c_handlers[NUM_CPL_CMDS];
87 static void open_rnic_dev(struct t3cdev *);
88 static void close_rnic_dev(struct t3cdev *);
90 static TAILQ_HEAD( ,iwch_dev) dev_list;
91 static struct mtx dev_mutex;
92 static eventhandler_tag event_tag;
95 rnic_init(struct iwch_dev *rnicp)
97 CTR2(KTR_IW_CXGB, "%s iwch_dev %p", __FUNCTION__, rnicp);
98 idr_init(&rnicp->cqidr);
99 idr_init(&rnicp->qpidr);
100 idr_init(&rnicp->mmidr);
101 mtx_init(&rnicp->lock, "iwch rnic lock", NULL, MTX_DEF|MTX_DUPOK);
103 rnicp->attr.vendor_id = 0x168;
104 rnicp->attr.vendor_part_id = 7;
105 rnicp->attr.max_qps = T3_MAX_NUM_QP - 32;
106 rnicp->attr.max_wrs = (1UL << 24) - 1;
107 rnicp->attr.max_sge_per_wr = T3_MAX_SGE;
108 rnicp->attr.max_sge_per_rdma_write_wr = T3_MAX_SGE;
109 rnicp->attr.max_cqs = T3_MAX_NUM_CQ - 1;
110 rnicp->attr.max_cqes_per_cq = (1UL << 24) - 1;
111 rnicp->attr.max_mem_regs = cxio_num_stags(&rnicp->rdev);
112 rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE;
113 rnicp->attr.max_pds = T3_MAX_NUM_PD - 1;
114 rnicp->attr.mem_pgsizes_bitmask = 0x7FFF; /* 4KB-128MB */
115 rnicp->attr.can_resize_wq = 0;
116 rnicp->attr.max_rdma_reads_per_qp = 8;
117 rnicp->attr.max_rdma_read_resources =
118 rnicp->attr.max_rdma_reads_per_qp * rnicp->attr.max_qps;
119 rnicp->attr.max_rdma_read_qp_depth = 8; /* IRD */
120 rnicp->attr.max_rdma_read_depth =
121 rnicp->attr.max_rdma_read_qp_depth * rnicp->attr.max_qps;
122 rnicp->attr.rq_overflow_handled = 0;
123 rnicp->attr.can_modify_ird = 0;
124 rnicp->attr.can_modify_ord = 0;
125 rnicp->attr.max_mem_windows = rnicp->attr.max_mem_regs - 1;
126 rnicp->attr.stag0_value = 1;
127 rnicp->attr.zbva_support = 1;
128 rnicp->attr.local_invalidate_fence = 1;
129 rnicp->attr.cq_overflow_detection = 1;
134 open_rnic_dev(struct t3cdev *tdev)
136 struct iwch_dev *rnicp;
137 static int vers_printed;
139 CTR2(KTR_IW_CXGB, "%s t3cdev %p", __FUNCTION__, tdev);
141 printf("Chelsio T3 RDMA Driver - version %s\n",
143 rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp));
145 printf("Cannot allocate ib device\n");
148 rnicp->rdev.ulp = rnicp;
149 rnicp->rdev.t3cdev_p = tdev;
151 mtx_lock(&dev_mutex);
153 if (cxio_rdev_open(&rnicp->rdev)) {
154 mtx_unlock(&dev_mutex);
155 printf("Unable to open CXIO rdev\n");
156 ib_dealloc_device(&rnicp->ibdev);
162 TAILQ_INSERT_TAIL(&dev_list, rnicp, entry);
163 mtx_unlock(&dev_mutex);
165 if (iwch_register_device(rnicp)) {
166 printf("Unable to register device\n");
167 close_rnic_dev(tdev);
170 printf("Initialized device %s\n",
171 pci_name(rnicp->rdev.rnic_info.pdev));
177 close_rnic_dev(struct t3cdev *tdev)
179 struct iwch_dev *dev, *tmp;
180 CTR2(KTR_IW_CXGB, "%s t3cdev %p", __FUNCTION__, tdev);
181 mtx_lock(&dev_mutex);
183 TAILQ_FOREACH_SAFE(dev, &dev_list, entry, tmp) {
184 if (dev->rdev.t3cdev_p == tdev) {
186 list_del(&dev->entry);
187 iwch_unregister_device(dev);
188 cxio_rdev_close(&dev->rdev);
189 idr_destroy(&dev->cqidr);
190 idr_destroy(&dev->qpidr);
191 idr_destroy(&dev->mmidr);
192 ib_dealloc_device(&dev->ibdev);
197 mtx_unlock(&dev_mutex);
200 static ifaddr_event_handler_t
201 ifaddr_event_handler(void *arg, struct ifnet *ifp)
203 printf("%s if name %s \n", __FUNCTION__, ifp->if_xname);
204 if (ifp->if_capabilities & IFCAP_TOE4) {
205 KASSERT(T3CDEV(ifp) != NULL, ("null t3cdev ptr!"));
206 if (cxio_hal_find_rdev_by_t3cdev(T3CDEV(ifp)) == NULL)
207 open_rnic_dev(T3CDEV(ifp));
214 iwch_init_module(void)
216 VNET_ITERATOR_DECL(vnet_iter);
220 printf("%s enter\n", __FUNCTION__);
221 TAILQ_INIT(&dev_list);
222 mtx_init(&dev_mutex, "iwch dev_list lock", NULL, MTX_DEF);
224 err = cxio_hal_init();
227 err = iwch_cm_init();
230 cxio_register_ev_cb(iwch_ev_dispatch);
232 /* Register for ifaddr events to dynamically add TOE devs */
233 event_tag = EVENTHANDLER_REGISTER(ifaddr_event, ifaddr_event_handler,
234 NULL, EVENTHANDLER_PRI_ANY);
236 /* Register existing TOE interfaces by walking the ifnet chain */
239 VNET_FOREACH(vnet_iter) {
240 CURVNET_SET(vnet_iter); /* XXX CURVNET_SET_QUIET() ? */
241 TAILQ_FOREACH(ifp, &V_ifnet, if_link)
242 (void)ifaddr_event_handler(NULL, ifp);
251 iwch_exit_module(void)
253 EVENTHANDLER_DEREGISTER(ifaddr_event, event_tag);
254 cxio_unregister_ev_cb(iwch_ev_dispatch);
260 iwch_load(module_t mod, int cmd, void *arg)
266 printf("Loading iw_cxgb.\n");
273 printf("Unloading iw_cxgb.\n");
286 static moduledata_t mod_data = {
292 MODULE_VERSION(iw_cxgb, 1);
293 DECLARE_MODULE(iw_cxgb, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);
294 MODULE_DEPEND(iw_cxgb, rdma_core, 1, 1, 1);
295 MODULE_DEPEND(iw_cxgb, if_cxgb, 1, 1, 1);
296 MODULE_DEPEND(iw_cxgb, t3_tom, 1, 1, 1);