1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26#ifndef	_SYS_IB_CLIENTS_OF_SOL_UMAD_SOL_UMAD_H
27#define	_SYS_IB_CLIENTS_OF_SOL_UMAD_SOL_UMAD_H
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33/*
34 * map between minor node #s and HCA indexes and Port #s. This leaves
35 * room for 16 boards with up to 16 ports each.
36 */
37#define	GET_UMAD_MINOR(node, port)   ((node << 4) | port)
38#define	GET_ISSM_MINOR(node, port)   ((node << 4) | port | 0x8000)
39#define	GET_NODE(minor) ((minor >> 4) & 0xf)
40#define	GET_PORT(minor) ((minor) & 0xf)
41#define	ISSM_MINOR(minor) (minor & 0x8000)
42#define	GET_UCTX(minor) (minor >> 8)
43#define	GET_NEW_UCTX_MINOR(minor, uctxnum) ((uctxnum << 8) | minor)
44
45/* UMAD KA instance, only one instance allowed */
46#define	UMAD_INSTANCE	0
47
48#define	MAX_UCTX	16	/* Maximum number of contexts. */
49
50typedef struct umad_port_info_s umad_port_info_t;
51
52/*
53 * User context. One per open file descriptor.
54 */
55typedef struct umad_uctx_s {
56	kmutex_t		uctx_lock;	/* protects agent_list */
57	umad_port_info_t	*uctx_port;
58	struct pollhead		uctx_pollhead;
59	llist_head_t		uctx_agent_list; /* list of agents registered */
60	kmutex_t		uctx_recv_lock; /* protects recv_list below */
61	genlist_t		uctx_recv_list; /* Queue of received MADs */
62	kcondvar_t		uctx_recv_cv;	/* wait on for received data */
63} umad_uctx_t;
64
65typedef struct umad_agent_s {
66	llist_head_t		agent_list;
67	struct ib_user_mad_reg_req agent_req;	/* Params given during */
68						/* registration */
69	struct ibmf_reg_info	*agent_reg;	/* IBMF information */
70	umad_uctx_t		*agent_uctx;	/* User context to which */
71						/* this agent belongs. */
72	int			agent_outstanding_msgs; /* # of msgs waiting */
73							/* for a response */
74	kmutex_t		agent_lock;	/* protects this structure */
75	int			agent_flags;
76	kcondvar_t		agent_cv;	/* used to wake up unregister */
77} umad_agent_t;
78
79enum umad_agent_flags {
80	UMAD_AGENT_UNREGISTERING	= 1 << 0,
81	UMAD_HANDLING_ASYNC		= 1 << 1
82};
83
84typedef struct umad_hca_info_s {
85	ib_guid_t		hca_guid;
86	ibt_hca_hdl_t		hca_handle;
87	ibt_hca_attr_t		hca_attr;
88	uint8_t			hca_nports;
89	umad_port_info_t	*hca_ports;
90} umad_hca_info_t;
91
92struct umad_port_info_s {
93	kmutex_t		port_lock;
94	const umad_hca_info_t	*port_hca;	/* backpointer to hca */
95	unsigned int		port_minor_name; /* number in device name. */
96	uint8_t			port_num;
97	ib_guid_t		port_guid;
98	int			port_issm_open_cnt;
99	ib_lid_t		port_lid;
100	bool			port_has_umad_minor_node;
101	bool			port_has_issm_minor_node;
102	llist_head_t		port_ibmf_regs;
103};
104
105typedef struct umad_info_s {
106	dev_info_t		*info_dip;	/* back pointer to devinfo */
107	kmutex_t		info_mutex;	/* protects this device */
108	ibt_clnt_hdl_t		info_clnt_hdl;
109	uint32_t		info_hca_count;
110	ib_guid_t		*info_hca_guids;
111	umad_hca_info_t		*info_hcas;	/* hca list */
112	umad_uctx_t		*info_uctx[MAX_UCTX];
113} umad_info_t;
114
115
116typedef struct ib_umad_msg_s {
117	struct ib_user_mad_hdr	umad_msg_hdr;
118	ibmf_msg_t		*umad_msg_ibmf_msg;
119} ib_umad_msg_t;
120
121/*
122 * A UMAD we send is linked to a user context.
123 */
124struct umad_send {
125	struct umad_agent_s	*send_agent;    /* agent that sent the MAD */
126	size_t			send_len;
127	uint8_t			send_umad[];    /* MAD from userspace */
128};
129
130struct ibmf_reg_info {
131	ibmf_handle_t	ibmf_reg_handle;
132	unsigned int	ibmf_reg_refcnt;
133	umad_uctx_t	*ibmf_reg_uctx;
134	kmutex_t	ibmf_reg_lock;
135	kcondvar_t	ibmf_cv;
136	unsigned int	ibmf_flags;
137	enum _ibmf_client_type_t	ibmf_class;
138};
139
140/* Flags values for ibmf_flags above */
141enum ibmf_flag_values {
142	UMAD_IBMF_UNREGISTERING = 1 << 0
143};
144
145static inline int
146is_supported_mad_method(int nr, void *addr)
147{
148	return (1 & (((uint32_t *)addr)[nr >> 5] >> (nr & 31)));
149}
150
151static int umad_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
152static int umad_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
153static int umad_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
154			void **resultp);
155static int umad_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
156			int flags, char *name, caddr_t valuep,
157			int *lengthp);
158static int umad_open(dev_t *devp, int flag, int otyp, cred_t *cred);
159static int umad_close(dev_t dev, int flag, int otyp, cred_t *cred);
160static int umad_read(dev_t dev, struct uio *uiop, cred_t *credp);
161static int umad_write(dev_t dev, struct uio *uiop, cred_t *credp);
162static int umad_poll(dev_t dev, short events, int anyyet,
163			short *reventsp, struct pollhead **phpp);
164static int umad_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
165			cred_t *credp, int *rvalp);
166
167static void umad_async_handler(void *private, ibt_hca_hdl_t hca_hdl,
168			ibt_async_code_t code,
169			ibt_async_event_t *event);
170static int umad_register(struct ib_user_mad_reg_req *req,
171					umad_uctx_t *uctx);
172static int umad_unregister(struct ib_user_mad_reg_req *agent,
173					umad_uctx_t *uctx);
174static void umad_unsolicited_cb(ibmf_handle_t ibmf_handle,
175					ibmf_msg_t *msgp, void *args);
176#ifdef __cplusplus
177}
178#endif
179
180#endif /* _SYS_IB_CLIENTS_OF_SOL_UMAD_SOL_UMAD_H */
181