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>
58 #include <net/if_var.h>
60 #include <netinet/in.h>
62 #include <contrib/rdma/ib_verbs.h>
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>
73 #include <dev/cxgb/cxgb_include.h>
74 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_wr.h>
75 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_hal.h>
76 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_provider.h>
77 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_cm.h>
78 #include <dev/cxgb/ulp/iw_cxgb/iw_cxgb.h>
88 cxgb_cpl_handler_func t3c_handlers[NUM_CPL_CMDS];
90 static void open_rnic_dev(struct t3cdev *);
91 static void close_rnic_dev(struct t3cdev *);
93 static TAILQ_HEAD( ,iwch_dev) dev_list;
94 static struct mtx dev_mutex;
95 static eventhandler_tag event_tag;
98 rnic_init(struct iwch_dev *rnicp)
100 CTR2(KTR_IW_CXGB, "%s iwch_dev %p", __FUNCTION__, rnicp);
101 idr_init(&rnicp->cqidr);
102 idr_init(&rnicp->qpidr);
103 idr_init(&rnicp->mmidr);
104 mtx_init(&rnicp->lock, "iwch rnic lock", NULL, MTX_DEF|MTX_DUPOK);
106 rnicp->attr.vendor_id = 0x168;
107 rnicp->attr.vendor_part_id = 7;
108 rnicp->attr.max_qps = T3_MAX_NUM_QP - 32;
109 rnicp->attr.max_wrs = (1UL << 24) - 1;
110 rnicp->attr.max_sge_per_wr = T3_MAX_SGE;
111 rnicp->attr.max_sge_per_rdma_write_wr = T3_MAX_SGE;
112 rnicp->attr.max_cqs = T3_MAX_NUM_CQ - 1;
113 rnicp->attr.max_cqes_per_cq = (1UL << 24) - 1;
114 rnicp->attr.max_mem_regs = cxio_num_stags(&rnicp->rdev);
115 rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE;
116 rnicp->attr.max_pds = T3_MAX_NUM_PD - 1;
117 rnicp->attr.mem_pgsizes_bitmask = 0x7FFF; /* 4KB-128MB */
118 rnicp->attr.can_resize_wq = 0;
119 rnicp->attr.max_rdma_reads_per_qp = 8;
120 rnicp->attr.max_rdma_read_resources =
121 rnicp->attr.max_rdma_reads_per_qp * rnicp->attr.max_qps;
122 rnicp->attr.max_rdma_read_qp_depth = 8; /* IRD */
123 rnicp->attr.max_rdma_read_depth =
124 rnicp->attr.max_rdma_read_qp_depth * rnicp->attr.max_qps;
125 rnicp->attr.rq_overflow_handled = 0;
126 rnicp->attr.can_modify_ird = 0;
127 rnicp->attr.can_modify_ord = 0;
128 rnicp->attr.max_mem_windows = rnicp->attr.max_mem_regs - 1;
129 rnicp->attr.stag0_value = 1;
130 rnicp->attr.zbva_support = 1;
131 rnicp->attr.local_invalidate_fence = 1;
132 rnicp->attr.cq_overflow_detection = 1;
137 open_rnic_dev(struct t3cdev *tdev)
139 struct iwch_dev *rnicp;
140 static int vers_printed;
142 CTR2(KTR_IW_CXGB, "%s t3cdev %p", __FUNCTION__, tdev);
144 printf("Chelsio T3 RDMA Driver - version %s\n",
146 rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp));
148 printf("Cannot allocate ib device\n");
151 rnicp->rdev.ulp = rnicp;
152 rnicp->rdev.t3cdev_p = tdev;
154 mtx_lock(&dev_mutex);
156 if (cxio_rdev_open(&rnicp->rdev)) {
157 mtx_unlock(&dev_mutex);
158 printf("Unable to open CXIO rdev\n");
159 ib_dealloc_device(&rnicp->ibdev);
165 TAILQ_INSERT_TAIL(&dev_list, rnicp, entry);
166 mtx_unlock(&dev_mutex);
168 if (iwch_register_device(rnicp)) {
169 printf("Unable to register device\n");
170 close_rnic_dev(tdev);
173 printf("Initialized device %s\n",
174 pci_name(rnicp->rdev.rnic_info.pdev));
180 close_rnic_dev(struct t3cdev *tdev)
182 struct iwch_dev *dev, *tmp;
183 CTR2(KTR_IW_CXGB, "%s t3cdev %p", __FUNCTION__, tdev);
184 mtx_lock(&dev_mutex);
186 TAILQ_FOREACH_SAFE(dev, &dev_list, entry, tmp) {
187 if (dev->rdev.t3cdev_p == tdev) {
189 list_del(&dev->entry);
190 iwch_unregister_device(dev);
191 cxio_rdev_close(&dev->rdev);
192 idr_destroy(&dev->cqidr);
193 idr_destroy(&dev->qpidr);
194 idr_destroy(&dev->mmidr);
195 ib_dealloc_device(&dev->ibdev);
200 mtx_unlock(&dev_mutex);
203 static ifaddr_event_handler_t
204 ifaddr_event_handler(void *arg, struct ifnet *ifp)
206 printf("%s if name %s \n", __FUNCTION__, ifp->if_xname);
207 if (ifp->if_capabilities & IFCAP_TOE4) {
208 KASSERT(T3CDEV(ifp) != NULL, ("null t3cdev ptr!"));
209 if (cxio_hal_find_rdev_by_t3cdev(T3CDEV(ifp)) == NULL)
210 open_rnic_dev(T3CDEV(ifp));
217 iwch_init_module(void)
222 printf("%s enter\n", __FUNCTION__);
223 TAILQ_INIT(&dev_list);
224 mtx_init(&dev_mutex, "iwch dev_list lock", NULL, MTX_DEF);
226 err = cxio_hal_init();
229 err = iwch_cm_init();
232 cxio_register_ev_cb(iwch_ev_dispatch);
234 /* Register for ifaddr events to dynamically add TOE devs */
235 event_tag = EVENTHANDLER_REGISTER(ifaddr_event, ifaddr_event_handler,
236 NULL, EVENTHANDLER_PRI_ANY);
238 /* Register existing TOE interfaces by walking the ifnet chain */
240 TAILQ_FOREACH(ifp, &ifnet, if_link) {
241 (void)ifaddr_event_handler(NULL, ifp);
248 iwch_exit_module(void)
250 EVENTHANDLER_DEREGISTER(ifaddr_event, event_tag);
251 cxio_unregister_ev_cb(iwch_ev_dispatch);
257 iwch_load(module_t mod, int cmd, void *arg)
263 printf("Loading iw_cxgb.\n");
270 printf("Unloading iw_cxgb.\n");
283 static moduledata_t mod_data = {
289 MODULE_VERSION(iw_cxgb, 1);
290 DECLARE_MODULE(iw_cxgb, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);
291 MODULE_DEPEND(iw_cxgb, rdma_core, 1, 1, 1);
292 MODULE_DEPEND(iw_cxgb, if_cxgb, 1, 1, 1);
293 MODULE_DEPEND(iw_cxgb, t3_tom, 1, 1, 1);