1 /**************************************************************************
2
3 Copyright (c) 2007, Chelsio Inc.
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, 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
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.
27
28 ***************************************************************************/
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD: stable/9/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb.c 237920 2012-07-01 12:00:36Z 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
73 static int iwch_mod_load(void);
74 static int iwch_mod_unload(void);
75 static int iwch_activate(struct adapter *);
76 static int iwch_deactivate(struct adapter *);
77
78 static struct uld_info iwch_uld_info = {
79 .uld_id = ULD_IWARP,
80 .activate = iwch_activate,
81 .deactivate = iwch_deactivate,
82 };
83
84 static void
rnic_init(struct iwch_dev * rnicp)85 rnic_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
125 static void
rnic_uninit(struct iwch_dev * rnicp)126 rnic_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
134 static int
iwch_activate(struct adapter * sc)135 iwch_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
170 err2:
171 rnic_uninit(rnicp);
172 cxio_rdev_close(&rnicp->rdev);
173 err1:
174 cxio_hal_uninit(sc);
175 iwch_cm_term_cpl(sc);
176 sc->iwarp_softc = NULL;
177
178 return (rc);
179 }
180
181 static int
iwch_deactivate(struct adapter * sc)182 iwch_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
200 static void
iwch_activate_all(struct adapter * sc,void * arg __unused)201 iwch_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
210 static void
iwch_deactivate_all(struct adapter * sc,void * arg __unused)211 iwch_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
220 static int
iwch_mod_load(void)221 iwch_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
240 static int
iwch_mod_unload(void)241 iwch_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
257 static int
iwch_modevent(module_t mod,int cmd,void * arg)258 iwch_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
290 static moduledata_t iwch_mod_data = {
291 "iw_cxgb",
292 iwch_modevent,
293 0
294 };
295
296 MODULE_VERSION(iw_cxgb, 1);
297 DECLARE_MODULE(iw_cxgb, iwch_mod_data, SI_SUB_EXEC, SI_ORDER_ANY);
298 MODULE_DEPEND(t3_tom, cxgbc, 1, 1, 1);
299 MODULE_DEPEND(iw_cxgb, toecore, 1, 1, 1);
300 MODULE_DEPEND(iw_cxgb, t3_tom, 1, 1, 1);
301