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 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