]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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 <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/bus.h>
36 #include <sys/module.h>
37 #include <sys/pciio.h>
38 #include <sys/conf.h>
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41 #include <sys/bus_dma.h>
42 #include <sys/rman.h>
43 #include <sys/ioccom.h>
44 #include <sys/mbuf.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>
50 #include <sys/smp.h>
51 #include <sys/sysctl.h>
52 #include <sys/queue.h>
53 #include <sys/taskqueue.h>
54 #include <sys/proc.h>
55 #include <sys/eventhandler.h>
56
57 #if __FreeBSD_version < 800044
58 #define V_ifnet ifnet
59 #endif
60
61 #include <net/if.h>
62 #include <net/if_var.h>
63 #if __FreeBSD_version >= 800056
64 #include <net/vnet.h>
65 #endif
66
67 #include <netinet/in.h>
68
69 #include <contrib/rdma/ib_verbs.h>
70
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>
77
78 /*
79  * XXX :-/
80  * 
81  */
82
83 #define idr_init(x)
84
85 cxgb_cpl_handler_func t3c_handlers[NUM_CPL_CMDS];
86
87 static void open_rnic_dev(struct t3cdev *);
88 static void close_rnic_dev(struct t3cdev *);
89
90 static TAILQ_HEAD( ,iwch_dev) dev_list;
91 static struct mtx dev_mutex;
92 static eventhandler_tag event_tag;
93
94 static void
95 rnic_init(struct iwch_dev *rnicp)
96 {
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);
102
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;
130         return;
131 }
132
133 static void
134 open_rnic_dev(struct t3cdev *tdev)
135 {
136         struct iwch_dev *rnicp;
137         static int vers_printed;
138
139         CTR2(KTR_IW_CXGB, "%s t3cdev %p", __FUNCTION__,  tdev);
140         if (!vers_printed++)
141                 printf("Chelsio T3 RDMA Driver - version x.xx\n");
142         rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp));
143         if (!rnicp) {
144                 printf("Cannot allocate ib device\n");
145                 return;
146         }
147         rnicp->rdev.ulp = rnicp;
148         rnicp->rdev.t3cdev_p = tdev;
149
150         mtx_lock(&dev_mutex);
151
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);
156                 return;
157         }
158
159         rnic_init(rnicp);
160
161         TAILQ_INSERT_TAIL(&dev_list, rnicp, entry);
162         mtx_unlock(&dev_mutex);
163
164         if (iwch_register_device(rnicp)) {
165                 printf("Unable to register device\n");
166                 close_rnic_dev(tdev);
167         }
168 #ifdef notyet   
169         printf("Initialized device %s\n",
170                pci_name(rnicp->rdev.rnic_info.pdev));
171 #endif  
172         return;
173 }
174
175 static void
176 close_rnic_dev(struct t3cdev *tdev)
177 {
178         struct iwch_dev *dev, *tmp;
179         CTR2(KTR_IW_CXGB, "%s t3cdev %p", __FUNCTION__,  tdev);
180         mtx_lock(&dev_mutex);
181
182         TAILQ_FOREACH_SAFE(dev, &dev_list, entry, tmp) {
183                 if (dev->rdev.t3cdev_p == tdev) {
184 #ifdef notyet                   
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);
192 #endif                  
193                         break;
194                 }
195         }
196         mtx_unlock(&dev_mutex);
197 }
198
199 static ifaddr_event_handler_t
200 ifaddr_event_handler(void *arg, struct ifnet *ifp)
201 {
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));
207         }
208         return 0;
209 }
210
211
212 static int
213 iwch_init_module(void)
214 {
215         VNET_ITERATOR_DECL(vnet_iter);
216         int err;
217         struct ifnet *ifp;
218
219         printf("%s enter\n", __FUNCTION__);
220         TAILQ_INIT(&dev_list);
221         mtx_init(&dev_mutex, "iwch dev_list lock", NULL, MTX_DEF);
222         
223         err = cxio_hal_init();
224         if (err)
225                 return err;
226         err = iwch_cm_init();
227         if (err)
228                 return err;
229         cxio_register_ev_cb(iwch_ev_dispatch);
230
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);
234
235         /* Register existing TOE interfaces by walking the ifnet chain */
236         IFNET_RLOCK();
237         VNET_LIST_RLOCK();
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);
242                 CURVNET_RESTORE();
243         }
244         VNET_LIST_RUNLOCK();
245         IFNET_RUNLOCK();
246         return 0;
247 }
248
249 static void
250 iwch_exit_module(void)
251 {
252         EVENTHANDLER_DEREGISTER(ifaddr_event, event_tag);
253         cxio_unregister_ev_cb(iwch_ev_dispatch);
254         iwch_cm_term();
255         cxio_hal_exit();
256 }
257
258 static int 
259 iwch_load(module_t mod, int cmd, void *arg)
260 {
261         int err = 0;
262
263         switch (cmd) {
264         case MOD_LOAD:
265                 printf("Loading iw_cxgb.\n");
266
267                 iwch_init_module();
268                 break;
269         case MOD_QUIESCE:
270                 break;
271         case MOD_UNLOAD:
272                 printf("Unloading iw_cxgb.\n");
273                 iwch_exit_module();
274                 break;
275         case MOD_SHUTDOWN:
276                 break;
277         default:
278                 err = EOPNOTSUPP;
279                 break;
280         }
281
282         return (err);
283 }
284
285 static moduledata_t mod_data = {
286         "iw_cxgb",
287         iwch_load,
288         0
289 };
290
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);
296