]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / cxgb / ulp / iw_cxgb / iw_cxgb.c
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$");
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
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
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
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
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
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
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
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
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
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 MODULE_DEPEND(iw_cxgb, ibcore, 1, 1, 1);