112198SEiji.Ota@Sun.COM /*
212198SEiji.Ota@Sun.COM * CDDL HEADER START
312198SEiji.Ota@Sun.COM *
412198SEiji.Ota@Sun.COM * The contents of this file are subject to the terms of the
512198SEiji.Ota@Sun.COM * Common Development and Distribution License (the "License").
612198SEiji.Ota@Sun.COM * You may not use this file except in compliance with the License.
712198SEiji.Ota@Sun.COM *
812198SEiji.Ota@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
912198SEiji.Ota@Sun.COM * or http://www.opensolaris.org/os/licensing.
1012198SEiji.Ota@Sun.COM * See the License for the specific language governing permissions
1112198SEiji.Ota@Sun.COM * and limitations under the License.
1212198SEiji.Ota@Sun.COM *
1312198SEiji.Ota@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1412198SEiji.Ota@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1512198SEiji.Ota@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1612198SEiji.Ota@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1712198SEiji.Ota@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1812198SEiji.Ota@Sun.COM *
1912198SEiji.Ota@Sun.COM * CDDL HEADER END
2012198SEiji.Ota@Sun.COM */
2112198SEiji.Ota@Sun.COM /*
2212198SEiji.Ota@Sun.COM * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2312198SEiji.Ota@Sun.COM */
2412198SEiji.Ota@Sun.COM #include <sys/types.h>
2512198SEiji.Ota@Sun.COM #include <sys/stat.h>
2612198SEiji.Ota@Sun.COM #include <sys/conf.h>
2712198SEiji.Ota@Sun.COM #include <sys/ddi.h>
2812198SEiji.Ota@Sun.COM #include <sys/sunddi.h>
2912198SEiji.Ota@Sun.COM #include <sys/modctl.h>
3012198SEiji.Ota@Sun.COM #include <sys/strsubr.h>
3112198SEiji.Ota@Sun.COM #include <sys/socketvar.h>
3212198SEiji.Ota@Sun.COM #include <sys/rds.h>
3312198SEiji.Ota@Sun.COM
3412198SEiji.Ota@Sun.COM #include <sys/ib/ibtl/ibti.h>
3512198SEiji.Ota@Sun.COM #include <sys/ib/clients/rdsv3/rdsv3.h>
3612198SEiji.Ota@Sun.COM #include <sys/ib/clients/rdsv3/rdsv3_debug.h>
3712676SEiji.Ota@Sun.COM #include <sys/ib/clients/rdsv3/rdsv3_af_thr.h>
3812198SEiji.Ota@Sun.COM
3912198SEiji.Ota@Sun.COM extern int rdsv3_init(void);
4012198SEiji.Ota@Sun.COM extern void rdsv3_exit(void);
4112198SEiji.Ota@Sun.COM extern void rdsv3_cong_init(void);
4212198SEiji.Ota@Sun.COM extern void rdsv3_cong_exit(void);
4312198SEiji.Ota@Sun.COM extern void rdsv3_trans_init(void);
4412198SEiji.Ota@Sun.COM extern void rdsv3_trans_exit(void);
4512198SEiji.Ota@Sun.COM extern int rdsv3_sock_init(void);
4612198SEiji.Ota@Sun.COM extern void rdsv3_sock_exit(void);
4712198SEiji.Ota@Sun.COM
4812198SEiji.Ota@Sun.COM /* global */
4912198SEiji.Ota@Sun.COM dev_info_t *rdsv3_dev_info = NULL;
5012198SEiji.Ota@Sun.COM kmem_cache_t *rdsv3_alloc_cache = NULL;
5112198SEiji.Ota@Sun.COM
5212198SEiji.Ota@Sun.COM extern kmutex_t rdsv3_rdma_listen_id_lock;
5312198SEiji.Ota@Sun.COM extern struct rdma_cm_id *rdsv3_rdma_listen_id;
5412198SEiji.Ota@Sun.COM
5512198SEiji.Ota@Sun.COM extern kmutex_t rdsv3_sock_lock;
5612198SEiji.Ota@Sun.COM extern list_t rdsv3_sock_list;
5712198SEiji.Ota@Sun.COM
58*12895SGiri.Adari@Sun.COM extern void rdsv3_bind_init();
59*12895SGiri.Adari@Sun.COM extern void rdsv3_bind_exit();
6012198SEiji.Ota@Sun.COM
6112198SEiji.Ota@Sun.COM int
rdsv3_sock_init()6212198SEiji.Ota@Sun.COM rdsv3_sock_init()
6312198SEiji.Ota@Sun.COM {
6412198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_sock_init", "Enter");
6512198SEiji.Ota@Sun.COM
6612198SEiji.Ota@Sun.COM rdsv3_alloc_cache = kmem_cache_create("rdsv3_alloc_cache",
6712198SEiji.Ota@Sun.COM sizeof (struct rsock) + sizeof (struct rdsv3_sock), 0, NULL,
6812198SEiji.Ota@Sun.COM NULL, NULL, NULL, NULL, 0);
6912198SEiji.Ota@Sun.COM if (rdsv3_alloc_cache == NULL) {
7012320SGiri.Adari@Sun.COM RDSV3_DPRINTF2("rdsv3_alloc_cache",
7112198SEiji.Ota@Sun.COM "kmem_cache_create(rdsv3_alloc_cache) failed");
7212198SEiji.Ota@Sun.COM return (-1);
7312198SEiji.Ota@Sun.COM }
74*12895SGiri.Adari@Sun.COM rdsv3_bind_init();
7512198SEiji.Ota@Sun.COM
7612198SEiji.Ota@Sun.COM mutex_init(&rdsv3_sock_lock, NULL, MUTEX_DRIVER, NULL);
7712198SEiji.Ota@Sun.COM list_create(&rdsv3_sock_list, sizeof (struct rdsv3_sock),
7812198SEiji.Ota@Sun.COM offsetof(struct rdsv3_sock, rs_item));
7912198SEiji.Ota@Sun.COM
8012198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_sock_init", "Return");
8112198SEiji.Ota@Sun.COM
8212198SEiji.Ota@Sun.COM return (0);
8312198SEiji.Ota@Sun.COM }
8412198SEiji.Ota@Sun.COM
8512198SEiji.Ota@Sun.COM void
rdsv3_sock_exit()8612198SEiji.Ota@Sun.COM rdsv3_sock_exit()
8712198SEiji.Ota@Sun.COM {
8812198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_sock_exit", "Enter");
8912198SEiji.Ota@Sun.COM
90*12895SGiri.Adari@Sun.COM rdsv3_bind_exit();
9112198SEiji.Ota@Sun.COM
9212198SEiji.Ota@Sun.COM kmem_cache_destroy(rdsv3_alloc_cache);
9312198SEiji.Ota@Sun.COM
9412198SEiji.Ota@Sun.COM list_destroy(&rdsv3_sock_list);
9512198SEiji.Ota@Sun.COM mutex_destroy(&rdsv3_sock_lock);
9612198SEiji.Ota@Sun.COM
9712198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_sock_exit", "Return");
9812198SEiji.Ota@Sun.COM }
9912198SEiji.Ota@Sun.COM
10012198SEiji.Ota@Sun.COM static int
rdsv3_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)10112198SEiji.Ota@Sun.COM rdsv3_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
10212198SEiji.Ota@Sun.COM {
10312198SEiji.Ota@Sun.COM int ret;
10412198SEiji.Ota@Sun.COM
10512198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_attach", "Enter (dip: %p)", dip);
10612198SEiji.Ota@Sun.COM
10712198SEiji.Ota@Sun.COM if (cmd != DDI_ATTACH)
10812198SEiji.Ota@Sun.COM return (DDI_FAILURE);
10912198SEiji.Ota@Sun.COM
11012198SEiji.Ota@Sun.COM if (rdsv3_dev_info != NULL) {
11112320SGiri.Adari@Sun.COM RDSV3_DPRINTF2("rdsv3_attach", "Multiple RDS instances are"
11212198SEiji.Ota@Sun.COM " not supported (rdsv3_dev_info: 0x%p)", rdsv3_dev_info);
11312198SEiji.Ota@Sun.COM return (DDI_FAILURE);
11412198SEiji.Ota@Sun.COM }
11512198SEiji.Ota@Sun.COM rdsv3_dev_info = dip;
11612198SEiji.Ota@Sun.COM
11712198SEiji.Ota@Sun.COM mutex_init(&rdsv3_rdma_listen_id_lock, NULL, MUTEX_DRIVER, NULL);
11812198SEiji.Ota@Sun.COM rdsv3_rdma_listen_id = NULL;
11912198SEiji.Ota@Sun.COM
12012676SEiji.Ota@Sun.COM rdsv3_af_init(dip);
12112198SEiji.Ota@Sun.COM rdsv3_trans_init();
12212198SEiji.Ota@Sun.COM ret = rdsv3_init();
12312198SEiji.Ota@Sun.COM if (ret) {
12412320SGiri.Adari@Sun.COM RDSV3_DPRINTF2("rdsv3_attach", "rdsv3_init failed: %d", ret);
12512198SEiji.Ota@Sun.COM rdsv3_trans_exit();
12612198SEiji.Ota@Sun.COM mutex_destroy(&rdsv3_rdma_listen_id_lock);
12712198SEiji.Ota@Sun.COM rdsv3_dev_info = NULL;
12812198SEiji.Ota@Sun.COM return (DDI_FAILURE);
12912198SEiji.Ota@Sun.COM }
13012198SEiji.Ota@Sun.COM
13112198SEiji.Ota@Sun.COM ret = rdsv3_sock_init();
13212198SEiji.Ota@Sun.COM if (ret) {
13312198SEiji.Ota@Sun.COM rdsv3_exit();
13412198SEiji.Ota@Sun.COM rdsv3_trans_exit();
13512198SEiji.Ota@Sun.COM mutex_destroy(&rdsv3_rdma_listen_id_lock);
13612198SEiji.Ota@Sun.COM rdsv3_dev_info = NULL;
13712198SEiji.Ota@Sun.COM return (DDI_FAILURE);
13812198SEiji.Ota@Sun.COM }
13912198SEiji.Ota@Sun.COM
14012198SEiji.Ota@Sun.COM ret = ddi_create_minor_node(dip, "rdsv3", S_IFCHR, 0, DDI_PSEUDO, 0);
14112198SEiji.Ota@Sun.COM if (ret != DDI_SUCCESS) {
14212198SEiji.Ota@Sun.COM cmn_err(CE_CONT, "ddi_create_minor_node failed: %d", ret);
14312198SEiji.Ota@Sun.COM rdsv3_sock_exit();
14412198SEiji.Ota@Sun.COM rdsv3_exit();
14512198SEiji.Ota@Sun.COM rdsv3_trans_exit();
14612198SEiji.Ota@Sun.COM mutex_destroy(&rdsv3_rdma_listen_id_lock);
14712198SEiji.Ota@Sun.COM rdsv3_dev_info = NULL;
14812198SEiji.Ota@Sun.COM return (DDI_FAILURE);
14912198SEiji.Ota@Sun.COM }
15012198SEiji.Ota@Sun.COM
15112198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_attach", "Return");
15212198SEiji.Ota@Sun.COM
15312198SEiji.Ota@Sun.COM return (DDI_SUCCESS);
15412198SEiji.Ota@Sun.COM }
15512198SEiji.Ota@Sun.COM
15612198SEiji.Ota@Sun.COM static int
rdsv3_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)15712198SEiji.Ota@Sun.COM rdsv3_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
15812198SEiji.Ota@Sun.COM {
15912198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_detach", "Enter (dip: %p)", dip);
16012198SEiji.Ota@Sun.COM
16112198SEiji.Ota@Sun.COM if (cmd != DDI_DETACH)
16212198SEiji.Ota@Sun.COM return (DDI_FAILURE);
16312198SEiji.Ota@Sun.COM
16412198SEiji.Ota@Sun.COM rdsv3_sock_exit();
16512198SEiji.Ota@Sun.COM rdsv3_exit();
16612198SEiji.Ota@Sun.COM rdsv3_trans_exit();
16712198SEiji.Ota@Sun.COM ddi_remove_minor_node(dip, "rdsv3");
16812198SEiji.Ota@Sun.COM rdsv3_dev_info = NULL;
16912198SEiji.Ota@Sun.COM
17012198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_detach", "Return");
17112198SEiji.Ota@Sun.COM
17212198SEiji.Ota@Sun.COM return (DDI_SUCCESS);
17312198SEiji.Ota@Sun.COM }
17412198SEiji.Ota@Sun.COM
17512198SEiji.Ota@Sun.COM /* ARGSUSED */
17612198SEiji.Ota@Sun.COM static int
rdsv3_info(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)17712198SEiji.Ota@Sun.COM rdsv3_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
17812198SEiji.Ota@Sun.COM {
17912198SEiji.Ota@Sun.COM int ret = DDI_FAILURE;
18012198SEiji.Ota@Sun.COM
18112198SEiji.Ota@Sun.COM RDSV3_DPRINTF2("rdsv3_info", "Enter (dip: %p, cmd: %d)", dip, cmd);
18212198SEiji.Ota@Sun.COM
18312198SEiji.Ota@Sun.COM switch (cmd) {
18412198SEiji.Ota@Sun.COM case DDI_INFO_DEVT2DEVINFO:
18512198SEiji.Ota@Sun.COM if (rdsv3_dev_info != NULL) {
18612198SEiji.Ota@Sun.COM *result = (void *)rdsv3_dev_info;
18712198SEiji.Ota@Sun.COM ret = DDI_SUCCESS;
18812198SEiji.Ota@Sun.COM }
18912198SEiji.Ota@Sun.COM break;
19012198SEiji.Ota@Sun.COM
19112198SEiji.Ota@Sun.COM case DDI_INFO_DEVT2INSTANCE:
19212198SEiji.Ota@Sun.COM *result = NULL;
19312198SEiji.Ota@Sun.COM ret = DDI_SUCCESS;
19412198SEiji.Ota@Sun.COM break;
19512198SEiji.Ota@Sun.COM
19612198SEiji.Ota@Sun.COM default:
19712198SEiji.Ota@Sun.COM break;
19812198SEiji.Ota@Sun.COM }
19912198SEiji.Ota@Sun.COM
20012198SEiji.Ota@Sun.COM RDSV3_DPRINTF4("rdsv3_info", "Return");
20112198SEiji.Ota@Sun.COM
20212198SEiji.Ota@Sun.COM return (ret);
20312198SEiji.Ota@Sun.COM }
20412198SEiji.Ota@Sun.COM
20512198SEiji.Ota@Sun.COM /* Driver entry points */
20612198SEiji.Ota@Sun.COM static struct cb_ops rdsv3_cb_ops = {
20712198SEiji.Ota@Sun.COM nulldev, /* open */
20812198SEiji.Ota@Sun.COM nulldev, /* close */
20912198SEiji.Ota@Sun.COM nodev, /* strategy */
21012198SEiji.Ota@Sun.COM nodev, /* print */
21112198SEiji.Ota@Sun.COM nodev, /* dump */
21212198SEiji.Ota@Sun.COM nodev, /* read */
21312198SEiji.Ota@Sun.COM nodev, /* write */
21412198SEiji.Ota@Sun.COM nodev, /* ioctl */
21512198SEiji.Ota@Sun.COM nodev, /* devmap */
21612198SEiji.Ota@Sun.COM nodev, /* mmap */
21712198SEiji.Ota@Sun.COM nodev, /* segmap */
21812198SEiji.Ota@Sun.COM nochpoll, /* poll */
21912198SEiji.Ota@Sun.COM ddi_prop_op, /* prop_op */
22012198SEiji.Ota@Sun.COM NULL, /* stream */
22112198SEiji.Ota@Sun.COM D_MP, /* cb_flag */
22212198SEiji.Ota@Sun.COM CB_REV, /* rev */
22312198SEiji.Ota@Sun.COM nodev, /* int (*cb_aread)() */
22412198SEiji.Ota@Sun.COM nodev, /* int (*cb_awrite)() */
22512198SEiji.Ota@Sun.COM };
22612198SEiji.Ota@Sun.COM
22712198SEiji.Ota@Sun.COM /* Device options */
22812198SEiji.Ota@Sun.COM static struct dev_ops rdsv3_ops = {
22912198SEiji.Ota@Sun.COM DEVO_REV, /* devo_rev, */
23012198SEiji.Ota@Sun.COM 0, /* refcnt */
23112198SEiji.Ota@Sun.COM rdsv3_info, /* info */
23212198SEiji.Ota@Sun.COM nulldev, /* identify */
23312198SEiji.Ota@Sun.COM nulldev, /* probe */
23412198SEiji.Ota@Sun.COM rdsv3_attach, /* attach */
23512198SEiji.Ota@Sun.COM rdsv3_detach, /* detach */
23612198SEiji.Ota@Sun.COM nodev, /* reset */
23712198SEiji.Ota@Sun.COM &rdsv3_cb_ops, /* driver ops - devctl interfaces */
23812198SEiji.Ota@Sun.COM NULL, /* bus operations */
23912198SEiji.Ota@Sun.COM NULL, /* power */
24012198SEiji.Ota@Sun.COM ddi_quiesce_not_needed /* quiesce */
24112198SEiji.Ota@Sun.COM };
24212198SEiji.Ota@Sun.COM
24312198SEiji.Ota@Sun.COM /*
24412198SEiji.Ota@Sun.COM * Module linkage information.
24512198SEiji.Ota@Sun.COM */
24612198SEiji.Ota@Sun.COM #define RDSV3_DEVDESC "RDSv3 IB transport driver"
24712198SEiji.Ota@Sun.COM static struct modldrv rdsv3_modldrv = {
24812198SEiji.Ota@Sun.COM &mod_driverops, /* Driver module */
24912198SEiji.Ota@Sun.COM RDSV3_DEVDESC, /* Driver name and version */
25012198SEiji.Ota@Sun.COM &rdsv3_ops, /* Driver ops */
25112198SEiji.Ota@Sun.COM };
25212198SEiji.Ota@Sun.COM
25312198SEiji.Ota@Sun.COM static struct modlinkage rdsv3_modlinkage = {
25412198SEiji.Ota@Sun.COM MODREV_1,
25512198SEiji.Ota@Sun.COM (void *)&rdsv3_modldrv,
25612198SEiji.Ota@Sun.COM NULL
25712198SEiji.Ota@Sun.COM };
25812198SEiji.Ota@Sun.COM
25912198SEiji.Ota@Sun.COM int
_init(void)26012198SEiji.Ota@Sun.COM _init(void)
26112198SEiji.Ota@Sun.COM {
26212198SEiji.Ota@Sun.COM int ret;
26312198SEiji.Ota@Sun.COM
26412198SEiji.Ota@Sun.COM if (ibt_hw_is_present() == 0) {
26512198SEiji.Ota@Sun.COM return (ENODEV);
26612198SEiji.Ota@Sun.COM }
26712198SEiji.Ota@Sun.COM
26812198SEiji.Ota@Sun.COM /* Initialize logging */
26912198SEiji.Ota@Sun.COM rdsv3_logging_initialization();
27012198SEiji.Ota@Sun.COM
27112198SEiji.Ota@Sun.COM ret = mod_install(&rdsv3_modlinkage);
27212198SEiji.Ota@Sun.COM if (ret != 0) {
27312198SEiji.Ota@Sun.COM /*
27412198SEiji.Ota@Sun.COM * Could not load module
27512198SEiji.Ota@Sun.COM */
27612198SEiji.Ota@Sun.COM rdsv3_logging_destroy();
27712198SEiji.Ota@Sun.COM return (ret);
27812198SEiji.Ota@Sun.COM }
27912198SEiji.Ota@Sun.COM
28012198SEiji.Ota@Sun.COM return (0);
28112198SEiji.Ota@Sun.COM }
28212198SEiji.Ota@Sun.COM
28312198SEiji.Ota@Sun.COM int
_fini()28412198SEiji.Ota@Sun.COM _fini()
28512198SEiji.Ota@Sun.COM {
28612198SEiji.Ota@Sun.COM int ret;
28712198SEiji.Ota@Sun.COM
28812198SEiji.Ota@Sun.COM /*
28912198SEiji.Ota@Sun.COM * Remove module
29012198SEiji.Ota@Sun.COM */
29112198SEiji.Ota@Sun.COM if ((ret = mod_remove(&rdsv3_modlinkage)) != 0) {
29212198SEiji.Ota@Sun.COM return (ret);
29312198SEiji.Ota@Sun.COM }
29412198SEiji.Ota@Sun.COM
29512198SEiji.Ota@Sun.COM /* Stop logging */
29612198SEiji.Ota@Sun.COM rdsv3_logging_destroy();
29712198SEiji.Ota@Sun.COM
29812198SEiji.Ota@Sun.COM return (0);
29912198SEiji.Ota@Sun.COM }
30012198SEiji.Ota@Sun.COM
30112198SEiji.Ota@Sun.COM int
_info(struct modinfo * modinfop)30212198SEiji.Ota@Sun.COM _info(struct modinfo *modinfop)
30312198SEiji.Ota@Sun.COM {
30412198SEiji.Ota@Sun.COM return (mod_info(&rdsv3_modlinkage, modinfop));
30512198SEiji.Ota@Sun.COM }
306