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 x.xx\n");
142 rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp));
144 printf("Cannot allocate ib device\n");
147 rnicp->rdev.ulp = rnicp;
148 rnicp->rdev.t3cdev_p = tdev;
150 mtx_lock(&dev_mutex);
152 if (cxio_rdev_open(&rnicp->rdev)) {
153 mtx_unlock(&dev_mutex);
154 printf("Unable to open CXIO rdev\n");
155 ib_dealloc_device(&rnicp->ibdev);
161 TAILQ_INSERT_TAIL(&dev_list, rnicp, entry);
162 mtx_unlock(&dev_mutex);
164 if (iwch_register_device(rnicp)) {
165 printf("Unable to register device\n");
166 close_rnic_dev(tdev);
169 printf("Initialized device %s\n",
170 pci_name(rnicp->rdev.rnic_info.pdev));
176 close_rnic_dev(struct t3cdev *tdev)
178 struct iwch_dev *dev, *tmp;
179 CTR2(KTR_IW_CXGB, "%s t3cdev %p", __FUNCTION__, tdev);
180 mtx_lock(&dev_mutex);
182 TAILQ_FOREACH_SAFE(dev, &dev_list, entry, tmp) {
183 if (dev->rdev.t3cdev_p == tdev) {
185 list_del(&dev->entry);
186 iwch_unregister_device(dev);
187 cxio_rdev_close(&dev->rdev);
188 idr_destroy(&dev->cqidr);
189 idr_destroy(&dev->qpidr);
190 idr_destroy(&dev->mmidr);
191 ib_dealloc_device(&dev->ibdev);
196 mtx_unlock(&dev_mutex);
199 static ifaddr_event_handler_t
200 ifaddr_event_handler(void *arg, struct ifnet *ifp)
202 printf("%s if name %s \n", __FUNCTION__, ifp->if_xname);
203 if (ifp->if_capabilities & IFCAP_TOE4) {
204 KASSERT(T3CDEV(ifp) != NULL, ("null t3cdev ptr!"));
205 if (cxio_hal_find_rdev_by_t3cdev(T3CDEV(ifp)) == NULL)
206 open_rnic_dev(T3CDEV(ifp));
213 iwch_init_module(void)
215 VNET_ITERATOR_DECL(vnet_iter);
219 printf("%s enter\n", __FUNCTION__);
220 TAILQ_INIT(&dev_list);
221 mtx_init(&dev_mutex, "iwch dev_list lock", NULL, MTX_DEF);
223 err = cxio_hal_init();
226 err = iwch_cm_init();
229 cxio_register_ev_cb(iwch_ev_dispatch);
231 /* Register for ifaddr events to dynamically add TOE devs */
232 event_tag = EVENTHANDLER_REGISTER(ifaddr_event, ifaddr_event_handler,
233 NULL, EVENTHANDLER_PRI_ANY);
235 /* Register existing TOE interfaces by walking the ifnet chain */
238 VNET_FOREACH(vnet_iter) {
239 CURVNET_SET(vnet_iter); /* XXX CURVNET_SET_QUIET() ? */
240 TAILQ_FOREACH(ifp, &V_ifnet, if_link)
241 (void)ifaddr_event_handler(NULL, ifp);
250 iwch_exit_module(void)
252 EVENTHANDLER_DEREGISTER(ifaddr_event, event_tag);
253 cxio_unregister_ev_cb(iwch_ev_dispatch);
259 iwch_load(module_t mod, int cmd, void *arg)
265 printf("Loading iw_cxgb.\n");
272 printf("Unloading iw_cxgb.\n");
285 static moduledata_t mod_data = {
291 MODULE_VERSION(iw_cxgb, 1);
292 DECLARE_MODULE(iw_cxgb, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);
293 MODULE_DEPEND(iw_cxgb, rdma_core, 1, 1, 1);
294 MODULE_DEPEND(iw_cxgb, if_cxgb, 1, 1, 1);
295 MODULE_DEPEND(iw_cxgb, t3_tom, 1, 1, 1);