iw_cxgb.c revision 183289
1/**************************************************************************
2
3Copyright (c) 2007, Chelsio Inc.
4All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26POSSIBILITY OF SUCH DAMAGE.
27
28***************************************************************************/
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/dev/cxgb/ulp/iw_cxgb/iw_cxgb.c 183289 2008-09-23 02:22:24Z kmacy $");
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#include <sys/vimage.h>
59#else
60#define V_ifnet ifnet
61#endif
62
63#include <net/if.h>
64#include <net/if_var.h>
65
66#include <netinet/in.h>
67
68#include <contrib/rdma/ib_verbs.h>
69
70
71#ifdef CONFIG_DEFINED
72#include <cxgb_include.h>
73#include <ulp/iw_cxgb/iw_cxgb_wr.h>
74#include <ulp/iw_cxgb/iw_cxgb_hal.h>
75#include <ulp/iw_cxgb/iw_cxgb_provider.h>
76#include <ulp/iw_cxgb/iw_cxgb_cm.h>
77#include <ulp/iw_cxgb/iw_cxgb.h>
78#else
79#include <dev/cxgb/cxgb_include.h>
80#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_wr.h>
81#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_hal.h>
82#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_provider.h>
83#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb_cm.h>
84#include <dev/cxgb/ulp/iw_cxgb/iw_cxgb.h>
85#endif
86
87/*
88 * XXX :-/
89 *
90 */
91
92#define idr_init(x)
93
94cxgb_cpl_handler_func t3c_handlers[NUM_CPL_CMDS];
95
96static void open_rnic_dev(struct t3cdev *);
97static void close_rnic_dev(struct t3cdev *);
98
99static TAILQ_HEAD( ,iwch_dev) dev_list;
100static struct mtx dev_mutex;
101static eventhandler_tag event_tag;
102
103static void
104rnic_init(struct iwch_dev *rnicp)
105{
106	CTR2(KTR_IW_CXGB, "%s iwch_dev %p", __FUNCTION__,  rnicp);
107	idr_init(&rnicp->cqidr);
108	idr_init(&rnicp->qpidr);
109	idr_init(&rnicp->mmidr);
110	mtx_init(&rnicp->lock, "iwch rnic lock", NULL, MTX_DEF|MTX_DUPOK);
111
112	rnicp->attr.vendor_id = 0x168;
113	rnicp->attr.vendor_part_id = 7;
114	rnicp->attr.max_qps = T3_MAX_NUM_QP - 32;
115	rnicp->attr.max_wrs = (1UL << 24) - 1;
116	rnicp->attr.max_sge_per_wr = T3_MAX_SGE;
117	rnicp->attr.max_sge_per_rdma_write_wr = T3_MAX_SGE;
118	rnicp->attr.max_cqs = T3_MAX_NUM_CQ - 1;
119	rnicp->attr.max_cqes_per_cq = (1UL << 24) - 1;
120	rnicp->attr.max_mem_regs = cxio_num_stags(&rnicp->rdev);
121	rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE;
122	rnicp->attr.max_pds = T3_MAX_NUM_PD - 1;
123	rnicp->attr.mem_pgsizes_bitmask = 0x7FFF;	/* 4KB-128MB */
124	rnicp->attr.can_resize_wq = 0;
125	rnicp->attr.max_rdma_reads_per_qp = 8;
126	rnicp->attr.max_rdma_read_resources =
127	    rnicp->attr.max_rdma_reads_per_qp * rnicp->attr.max_qps;
128	rnicp->attr.max_rdma_read_qp_depth = 8;	/* IRD */
129	rnicp->attr.max_rdma_read_depth =
130	    rnicp->attr.max_rdma_read_qp_depth * rnicp->attr.max_qps;
131	rnicp->attr.rq_overflow_handled = 0;
132	rnicp->attr.can_modify_ird = 0;
133	rnicp->attr.can_modify_ord = 0;
134	rnicp->attr.max_mem_windows = rnicp->attr.max_mem_regs - 1;
135	rnicp->attr.stag0_value = 1;
136	rnicp->attr.zbva_support = 1;
137	rnicp->attr.local_invalidate_fence = 1;
138	rnicp->attr.cq_overflow_detection = 1;
139	return;
140}
141
142static void
143open_rnic_dev(struct t3cdev *tdev)
144{
145	struct iwch_dev *rnicp;
146	static int vers_printed;
147
148	CTR2(KTR_IW_CXGB, "%s t3cdev %p", __FUNCTION__,  tdev);
149	if (!vers_printed++)
150		printf("Chelsio T3 RDMA Driver - version %s\n",
151		       DRV_VERSION);
152	rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp));
153	if (!rnicp) {
154		printf("Cannot allocate ib device\n");
155		return;
156	}
157	rnicp->rdev.ulp = rnicp;
158	rnicp->rdev.t3cdev_p = tdev;
159
160	mtx_lock(&dev_mutex);
161
162	if (cxio_rdev_open(&rnicp->rdev)) {
163		mtx_unlock(&dev_mutex);
164		printf("Unable to open CXIO rdev\n");
165		ib_dealloc_device(&rnicp->ibdev);
166		return;
167	}
168
169	rnic_init(rnicp);
170
171	TAILQ_INSERT_TAIL(&dev_list, rnicp, entry);
172	mtx_unlock(&dev_mutex);
173
174	if (iwch_register_device(rnicp)) {
175		printf("Unable to register device\n");
176		close_rnic_dev(tdev);
177	}
178#ifdef notyet
179	printf("Initialized device %s\n",
180	       pci_name(rnicp->rdev.rnic_info.pdev));
181#endif
182	return;
183}
184
185static void
186close_rnic_dev(struct t3cdev *tdev)
187{
188	struct iwch_dev *dev, *tmp;
189	CTR2(KTR_IW_CXGB, "%s t3cdev %p", __FUNCTION__,  tdev);
190	mtx_lock(&dev_mutex);
191
192	TAILQ_FOREACH_SAFE(dev, &dev_list, entry, tmp) {
193		if (dev->rdev.t3cdev_p == tdev) {
194#ifdef notyet
195			list_del(&dev->entry);
196			iwch_unregister_device(dev);
197			cxio_rdev_close(&dev->rdev);
198			idr_destroy(&dev->cqidr);
199			idr_destroy(&dev->qpidr);
200			idr_destroy(&dev->mmidr);
201			ib_dealloc_device(&dev->ibdev);
202#endif
203			break;
204		}
205	}
206	mtx_unlock(&dev_mutex);
207}
208
209static ifaddr_event_handler_t
210ifaddr_event_handler(void *arg, struct ifnet *ifp)
211{
212	printf("%s if name %s \n", __FUNCTION__, ifp->if_xname);
213	if (ifp->if_capabilities & IFCAP_TOE4) {
214		KASSERT(T3CDEV(ifp) != NULL, ("null t3cdev ptr!"));
215		if (cxio_hal_find_rdev_by_t3cdev(T3CDEV(ifp)) == NULL)
216			open_rnic_dev(T3CDEV(ifp));
217	}
218	return 0;
219}
220
221
222static int
223iwch_init_module(void)
224{
225	int err;
226	struct ifnet *ifp;
227
228	printf("%s enter\n", __FUNCTION__);
229	TAILQ_INIT(&dev_list);
230	mtx_init(&dev_mutex, "iwch dev_list lock", NULL, MTX_DEF);
231
232	err = cxio_hal_init();
233	if (err)
234		return err;
235	err = iwch_cm_init();
236	if (err)
237		return err;
238	cxio_register_ev_cb(iwch_ev_dispatch);
239
240	/* Register for ifaddr events to dynamically add TOE devs */
241	event_tag = EVENTHANDLER_REGISTER(ifaddr_event, ifaddr_event_handler,
242			NULL, EVENTHANDLER_PRI_ANY);
243
244	/* Register existing TOE interfaces by walking the ifnet chain */
245	IFNET_RLOCK();
246	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
247		(void)ifaddr_event_handler(NULL, ifp);
248	}
249	IFNET_RUNLOCK();
250	return 0;
251}
252
253static void
254iwch_exit_module(void)
255{
256	EVENTHANDLER_DEREGISTER(ifaddr_event, event_tag);
257	cxio_unregister_ev_cb(iwch_ev_dispatch);
258	iwch_cm_term();
259	cxio_hal_exit();
260}
261
262static int
263iwch_load(module_t mod, int cmd, void *arg)
264{
265        int err = 0;
266
267        switch (cmd) {
268        case MOD_LOAD:
269                printf("Loading iw_cxgb.\n");
270
271                iwch_init_module();
272                break;
273        case MOD_QUIESCE:
274                break;
275        case MOD_UNLOAD:
276                printf("Unloading iw_cxgb.\n");
277		iwch_exit_module();
278                break;
279        case MOD_SHUTDOWN:
280                break;
281        default:
282                err = EOPNOTSUPP;
283                break;
284        }
285
286        return (err);
287}
288
289static moduledata_t mod_data = {
290	"iw_cxgb",
291	iwch_load,
292	0
293};
294
295MODULE_VERSION(iw_cxgb, 1);
296DECLARE_MODULE(iw_cxgb, mod_data, SI_SUB_EXEC, SI_ORDER_ANY);
297MODULE_DEPEND(iw_cxgb, rdma_core, 1, 1, 1);
298MODULE_DEPEND(iw_cxgb, if_cxgb, 1, 1, 1);
299MODULE_DEPEND(iw_cxgb, t3_tom, 1, 1, 1);
300
301