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
30 extern "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
50 typedef struct umad_port_info_s umad_port_info_t;
51
52 /*
53 * User context. One per open file descriptor.
54 */
55 typedef 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
65 typedef 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
79 enum umad_agent_flags {
80 UMAD_AGENT_UNREGISTERING = 1 << 0,
81 UMAD_HANDLING_ASYNC = 1 << 1
82 };
83
84 typedef 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
92 struct 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
105 typedef 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
116 typedef 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 */
124 struct 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
130 struct 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 */
141 enum ibmf_flag_values {
142 UMAD_IBMF_UNREGISTERING = 1 << 0
143 };
144
145 static inline int
is_supported_mad_method(int nr,void * addr)146 is_supported_mad_method(int nr, void *addr)
147 {
148 return (1 & (((uint32_t *)addr)[nr >> 5] >> (nr & 31)));
149 }
150
151 static int umad_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
152 static int umad_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
153 static int umad_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
154 void **resultp);
155 static 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);
158 static int umad_open(dev_t *devp, int flag, int otyp, cred_t *cred);
159 static int umad_close(dev_t dev, int flag, int otyp, cred_t *cred);
160 static int umad_read(dev_t dev, struct uio *uiop, cred_t *credp);
161 static int umad_write(dev_t dev, struct uio *uiop, cred_t *credp);
162 static int umad_poll(dev_t dev, short events, int anyyet,
163 short *reventsp, struct pollhead **phpp);
164 static int umad_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
165 cred_t *credp, int *rvalp);
166
167 static void umad_async_handler(void *private, ibt_hca_hdl_t hca_hdl,
168 ibt_async_code_t code,
169 ibt_async_event_t *event);
170 static int umad_register(struct ib_user_mad_reg_req *req,
171 umad_uctx_t *uctx);
172 static int umad_unregister(struct ib_user_mad_reg_req *agent,
173 umad_uctx_t *uctx);
174 static 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