#include <sys/ib/mgt/ibmf/ibmf_saa_impl.h>
#define IBMF_SAA_SET_CLIENT_SIGNATURE(clientp) { \
(clientp)->saa_client_sig = (void *)0xACEDFACE; \
}
#define IBMF_SAA_VERIFY_CLIENT_SIGNATURE(clientp) \
(((clientp) != NULL && (clientp)->saa_client_sig == \
(void *)0xACEDFACE) ? B_TRUE: B_FALSE)
#define IBMF_SAA_CLEAR_CLIENT_SIGNATURE(clientp) { \
(clientp)->saa_client_sig = 0; \
}
extern saa_state_t *saa_statep;
extern int ibmf_trace_level;
int
ibmf_sa_session_open(ib_guid_t port_guid, ib_smkey_t sm_key,
ibmf_saa_subnet_event_args_t *event_args, uint_t ibmf_version,
uint_t flags, ibmf_saa_handle_t *ibmf_saa_handle)
{
saa_port_t *saa_portp = NULL;
int status = IBMF_SUCCESS;
saa_client_data_t *saa_client = NULL;
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_sa_session_open_start, IBMF_TNF_TRACE, "",
"ibmf_sa_session_open() enter\n");
if (ibmf_version != IBMF_VERSION) {
IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_session_open_err, IBMF_TNF_ERROR, "",
"ibmf_sa_session_open: Bad Version\n");
status = IBMF_BAD_VERSION;
goto bail;
}
if (ibmf_saa_handle == NULL) {
IBMF_TRACE_0(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_session_open_err, IBMF_TNF_ERROR, "",
"ibmf_sa_session_open: invalid argument, null pointer\n");
status = IBMF_INVALID_ARG;
goto bail;
}
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_open, IBMF_TNF_TRACE, "",
"ibmf_sa_session_open: %s, guid = %016" PRIx64 ", prefix = %016"
PRIx64 "\n", tnf_string, msg, "opening session",
tnf_opaque, guid, port_guid);
mutex_enter(&saa_statep->saa_port_list_mutex);
saa_portp = saa_statep->saa_port_list;
while (saa_portp != NULL) {
if (saa_portp->saa_pt_port_guid == port_guid &&
ibmf_saa_is_valid(saa_portp, B_TRUE) == B_TRUE) {
break;
}
saa_portp = saa_portp->next;
}
if (saa_portp != NULL) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_open, IBMF_TNF_TRACE, "",
"ibmf_sa_session_open(): %s\n",
tnf_string, msg, "port exists\n");
mutex_exit(&saa_statep->saa_port_list_mutex);
status = ibmf_saa_impl_add_client(saa_portp);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_session_open_err, IBMF_TNF_ERROR, "",
"ibmf_sa_session_open: %s, status = %d\n",
tnf_string, msg, "ibmf_saa_impl_add_client()"
" failed", tnf_int, status, status);
goto bail;
}
} else {
status = ibmf_saa_impl_create_port(port_guid, &saa_portp);
if (status != IBMF_SUCCESS) {
mutex_exit(&saa_statep->saa_port_list_mutex);
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_session_open_err, IBMF_TNF_ERROR, "",
"ibmf_sa_session_open: %s, status = %d\n",
tnf_string, msg, "ibmf_saa_impl_create_port()"
" failed", tnf_int, status, status);
goto bail;
}
saa_portp->next = saa_statep->saa_port_list;
saa_statep->saa_port_list = saa_portp;
mutex_exit(&saa_statep->saa_port_list_mutex);
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(saa_portp->saa_pt_kstatp))
status = ibmf_saa_impl_init_kstats(saa_portp);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_session_open_err, IBMF_TNF_ERROR, "",
"ibmf_sa_session_open: %s, status = %d\n",
tnf_string, msg, "could not initialize kstats",
tnf_int, status, status);
ibmf_saa_impl_register_failed(saa_portp);
goto bail;
}
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*saa_portp))
status = ibmf_saa_impl_register_port(saa_portp);
if (status != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_session_open_err, IBMF_TNF_ERROR, "",
"ibmf_sa_session_open: %s, ibmf_status = %d\n",
tnf_string, msg,
"ibmf_saa_impl_register_port failed",
tnf_int, ibmf_status, status);
ibmf_saa_impl_register_failed(saa_portp);
goto bail;
}
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_open, IBMF_TNF_TRACE, "",
"ibmf_sa_session_open: %s, prefix = %016" PRIx64
"\n", tnf_string, msg, "successfully initialized port");
mutex_enter(&saa_portp->saa_pt_mutex);
saa_portp->saa_pt_reference_count++;
saa_portp->saa_pt_state = IBMF_SAA_PORT_STATE_READY;
_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*saa_portp))
cv_broadcast(&saa_portp->saa_pt_ibmf_reg_cv);
mutex_exit(&saa_portp->saa_pt_mutex);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_open, IBMF_TNF_TRACE, "",
"ibmf_sa_session_open: %s\n", tnf_string, msg,
"port is up. Sending classportinfo request");
ibmf_saa_impl_get_classportinfo(saa_portp);
}
mutex_enter(&saa_portp->saa_pt_kstat_mutex);
IBMF_SAA_ADD32_KSTATS(saa_portp, clients_registered, 1);
mutex_exit(&saa_portp->saa_pt_kstat_mutex);
saa_client = kmem_zalloc(sizeof (saa_client_data_t), KM_SLEEP);
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*saa_client))
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_open, IBMF_TNF_TRACE, "",
"ibmf_sa_session_open: clientp = %p, subnetp = %p\n",
tnf_opaque, clientp, saa_client,
tnf_opaque, subnetp, saa_portp);
saa_client->saa_client_port = saa_portp;
mutex_init(&saa_client->saa_client_mutex, NULL, MUTEX_DRIVER,
NULL);
cv_init(&saa_client->saa_client_state_cv, NULL, CV_DRIVER, NULL);
cv_init(&saa_client->saa_client_event_cb_cv, NULL, CV_DRIVER, NULL);
IBMF_SAA_SET_CLIENT_SIGNATURE(saa_client);
saa_client->saa_client_state = SAA_CLIENT_STATE_ACTIVE;
saa_client->saa_client_sm_key = sm_key;
*ibmf_saa_handle = (ibmf_saa_handle_t)saa_client;
if (event_args != NULL) {
ibmf_saa_add_event_subscriber(saa_client, event_args);
}
_NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*saa_client))
bail:
ibmf_saa_impl_purge();
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_sa_session_open_end,
IBMF_TNF_TRACE, "", "ibmf_sa_session_open() exit\n");
return (status);
}
int
ibmf_sa_session_close(ibmf_saa_handle_t *ibmf_saa_handle, uint_t flags)
{
saa_client_data_t *client_data = NULL;
saa_port_t *saa_portp = NULL;
int status = IBMF_SUCCESS;
saa_client_data_t *curr_clientp, *prev_clientp;
uint8_t port_state;
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_sa_session_close_start, IBMF_TNF_TRACE, "",
"ibmf_sa_session_close() enter\n");
if (ibmf_saa_handle == NULL) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_session_close_err, IBMF_TNF_ERROR, "",
"ibmf_sa_session_close: %s\n",
tnf_string, msg, "invalid argument, NULL pointer argument");
status = IBMF_INVALID_ARG;
goto bail;
}
client_data = (saa_client_data_t *)*ibmf_saa_handle;
if (IBMF_SAA_VERIFY_CLIENT_SIGNATURE(client_data) == B_FALSE) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_session_close_err, IBMF_TNF_ERROR, "",
"ibmf_sa_session_close: %s\n",
tnf_string, msg, "bad handle");
status = IBMF_BAD_HANDLE;
goto bail;
}
saa_portp = client_data->saa_client_port;
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_close, IBMF_TNF_TRACE,
"", "ibmf_sa_session_close: saa_portp = %p\n",
tnf_opaque, saa_portp, saa_portp);
mutex_enter(&saa_portp->saa_pt_mutex);
port_state = saa_portp->saa_pt_state;
mutex_exit(&saa_portp->saa_pt_mutex);
mutex_enter(&client_data->saa_client_mutex);
if ((client_data->saa_client_num_pending_trans > 0) &&
(port_state == IBMF_SAA_PORT_STATE_READY)) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_close, IBMF_TNF_TRACE,
"", "ibmf_sa_session_close: %s, num_pending_trans = %d\n",
tnf_string, msg, "waiting for async callbacks",
tnf_uint, num_pending_trans,
client_data->saa_client_num_pending_trans);
client_data->saa_client_state = SAA_CLIENT_STATE_WAITING;
cv_wait(&client_data->saa_client_state_cv,
&client_data->saa_client_mutex);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_sa_session_close,
IBMF_TNF_TRACE, "", "ibmf_sa_session_close: %s\n",
tnf_string, msg, "done waiting");
}
client_data->saa_client_state = SAA_CLIENT_STATE_CLOSED;
if (client_data->saa_client_event_cb_num_active > 0) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_close, IBMF_TNF_TRACE,
"", "ibmf_sa_session_close: %s, num_active_cb = %d\n",
tnf_string, msg, "waiting for event callbacks",
tnf_uint, num_active_cb,
client_data->saa_client_event_cb_num_active);
cv_wait(&client_data->saa_client_event_cb_cv,
&client_data->saa_client_mutex);
}
mutex_exit(&client_data->saa_client_mutex);
mutex_enter(&saa_portp->saa_pt_kstat_mutex);
IBMF_SAA_SUB32_KSTATS(saa_portp, clients_registered, 1);
mutex_exit(&saa_portp->saa_pt_kstat_mutex);
if (client_data->saa_client_event_cb != NULL) {
mutex_enter(&saa_portp->saa_pt_event_sub_mutex);
curr_clientp = saa_portp->saa_pt_event_sub_client_list;
prev_clientp = NULL;
while (curr_clientp != NULL) {
if (curr_clientp == client_data) {
break;
}
prev_clientp = curr_clientp;
curr_clientp = curr_clientp->next;
}
ASSERT(curr_clientp != NULL);
if (curr_clientp == NULL) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_session_close, IBMF_TNF_ERROR, "",
"ibmf_sa_session_close: %s. ref_count = %d\n",
tnf_string, msg, "could not find client in list",
tnf_opaque, client, client_data);
} else {
if (prev_clientp == NULL) {
saa_portp->saa_pt_event_sub_client_list =
curr_clientp->next;
} else
prev_clientp->next = curr_clientp->next;
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_close, IBMF_TNF_TRACE, "",
"ibmf_sa_session_close: %s\n", tnf_string, msg,
"Removed client from event subscriber list");
}
mutex_exit(&saa_portp->saa_pt_event_sub_mutex);
}
mutex_enter(&saa_portp->saa_pt_mutex);
ASSERT(saa_portp->saa_pt_reference_count > 0);
saa_portp->saa_pt_reference_count--;
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_sa_session_close,
IBMF_TNF_TRACE, "",
"ibmf_sa_session_close: ref_count = %d\n",
tnf_uint, port_ref_count,
saa_portp->saa_pt_reference_count);
mutex_exit(&saa_portp->saa_pt_mutex);
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_session_close, IBMF_TNF_TRACE, "",
"ibmf_sa_session_close: %s, clientp = %p\n", tnf_string, msg,
"freeing client memory", tnf_opaque, clientp, *ibmf_saa_handle);
_NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*client_data))
mutex_destroy(&client_data->saa_client_mutex);
cv_destroy(&client_data->saa_client_state_cv);
cv_destroy(&client_data->saa_client_event_cb_cv);
IBMF_SAA_CLEAR_CLIENT_SIGNATURE(client_data);
kmem_free(*ibmf_saa_handle, sizeof (saa_client_data_t));
*ibmf_saa_handle = NULL;
bail:
ibmf_saa_impl_purge();
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4, ibmf_sa_session_close_end,
IBMF_TNF_TRACE, "", "ibmf_sa_session_close() exit\n");
return (status);
}
int
ibmf_sa_access(ibmf_saa_handle_t ibmf_saa_handle,
ibmf_saa_access_args_t *access_args, uint_t flags, size_t *length,
void **result)
{
int res = IBMF_SUCCESS;
saa_impl_trans_info_t *trans_info;
saa_client_data_t *clientp;
saa_port_t *saa_portp;
IBMF_TRACE_3(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_sa_access_start, IBMF_TNF_TRACE, "",
"ibmf_sa_access_start() enter. attr_id = 0x%x, access_type ="
" 0x%x, comp_mask = %016" PRIx64 "\n",
tnf_opaque, attr_id, access_args->sq_attr_id,
tnf_opaque, access_type, access_args->sq_access_type,
tnf_opaque, comp_mask, access_args->sq_component_mask);
if ((access_args == NULL) || (length == NULL) || (result == NULL)) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_access_err, IBMF_TNF_ERROR, "",
"ibmf_sa_access: %s\n",
tnf_string, msg, "invalid argument, NULL pointer argument");
res = IBMF_INVALID_ARG;
goto bail;
}
if (IBMF_SAA_VERIFY_CLIENT_SIGNATURE(
(saa_client_data_t *)ibmf_saa_handle) == B_FALSE) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_access_err, IBMF_TNF_ERROR, "",
"ibmf_sa_access: %s\n",
tnf_string, msg, "bad handle");
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_sa_access_end, IBMF_TNF_TRACE,
"", "ibmf_sa_access() exit\n");
res = IBMF_BAD_HANDLE;
goto bail;
}
if (access_args->sq_callback == NULL) {
trans_info = kmem_zalloc(sizeof (saa_impl_trans_info_t),
KM_SLEEP);
} else {
trans_info = kmem_zalloc(sizeof (saa_impl_trans_info_t),
KM_NOSLEEP);
if (trans_info == NULL) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_access_err, IBMF_TNF_ERROR, "",
"ibmf_sa_access: %s\n", tnf_string, msg,
"could not allocate memory for trans_info");
res = IBMF_NO_MEMORY;
goto bail;
}
}
clientp = (saa_client_data_t *)ibmf_saa_handle;
saa_portp = clientp->saa_client_port;
trans_info->si_trans_client_data = clientp;
trans_info->si_trans_port = saa_portp;
if (access_args->sq_attr_id == SA_MULTIPATHRECORD_ATTRID) {
if (access_args->sq_access_type != IBMF_SAA_RETRIEVE) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_access_err, IBMF_TNF_ERROR, "",
"ibmf_sa_access: %s, access_type = 0x%x\n",
tnf_string, msg, "access_type for multi-path"
" records must be IBMF_SAA_RETRIEVE",
tnf_opaque, access_type,
access_args->sq_access_type);
kmem_free(trans_info, sizeof (saa_impl_trans_info_t));
res = IBMF_REQ_INVALID;
goto bail;
}
trans_info->si_trans_method = SA_SUBN_ADM_GET_MULTI;
} else if (access_args->sq_attr_id == SA_TRACERECORD_ATTRID) {
if (access_args->sq_access_type != IBMF_SAA_RETRIEVE) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_access_err, IBMF_TNF_ERROR, "",
"ibmf_sa_access: %s, access_type = 0x%x\n",
tnf_string, msg, "access_type for trace"
" records must be IBMF_SAA_RETRIEVE",
tnf_opaque, access_type,
access_args->sq_access_type);
kmem_free(trans_info, sizeof (saa_impl_trans_info_t));
res = IBMF_REQ_INVALID;
goto bail;
}
trans_info->si_trans_method = SA_SUBN_ADM_GET_TRACE_TABLE;
} else {
switch (access_args->sq_access_type) {
case IBMF_SAA_RETRIEVE:
trans_info->si_trans_method =
SA_SUBN_ADM_GET_TABLE;
break;
case IBMF_SAA_UPDATE:
trans_info->si_trans_method = SA_SUBN_ADM_SET;
break;
case IBMF_SAA_DELETE:
trans_info->si_trans_method =
SA_SUBN_ADM_DELETE;
break;
default:
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_access_err, IBMF_TNF_ERROR, "",
"ibmf_sa_access: %s, access_type = 0x%x\n",
tnf_string, msg, "unknown access_type",
tnf_opaque, access_type,
access_args->sq_access_type);
kmem_free(trans_info,
sizeof (saa_impl_trans_info_t));
res = IBMF_REQ_INVALID;
goto bail;
}
}
trans_info->si_trans_attr_id = access_args->sq_attr_id;
trans_info->si_trans_component_mask = access_args->sq_component_mask;
trans_info->si_trans_template = access_args->sq_template;
trans_info->si_trans_template_length = access_args->sq_template_length;
trans_info->si_trans_callback = access_args->sq_callback;
trans_info->si_trans_callback_arg = access_args->sq_callback_arg;
mutex_enter(&saa_portp->saa_pt_kstat_mutex);
IBMF_SAA_ADD32_KSTATS(saa_portp, outstanding_requests, 1);
IBMF_SAA_ADD32_KSTATS(saa_portp, total_requests, 1);
mutex_exit(&saa_portp->saa_pt_kstat_mutex);
res = ibmf_saa_impl_send_request(trans_info);
if (res != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_sa_access_err, IBMF_TNF_ERROR, "",
"ibmf_sa_access: %s, ibmf_status = %d\n",
tnf_string, msg, "ibmf_saa_impl_send_request() failed",
tnf_int, ibmf_status, res);
*length = 0;
*result = NULL;
kmem_free(trans_info, sizeof (saa_impl_trans_info_t));
mutex_enter(&saa_portp->saa_pt_kstat_mutex);
IBMF_SAA_SUB32_KSTATS(saa_portp, outstanding_requests, 1);
IBMF_SAA_ADD32_KSTATS(saa_portp, failed_requests, 1);
if (res == IBMF_TRANS_TIMEOUT)
IBMF_SAA_ADD32_KSTATS(saa_portp, requests_timedout,
1);
mutex_exit(&saa_portp->saa_pt_kstat_mutex);
goto bail;
}
if (access_args->sq_callback == NULL) {
*length = trans_info->si_trans_length;
*result = trans_info->si_trans_result;
res = trans_info->si_trans_status;
mutex_enter(&saa_portp->saa_pt_kstat_mutex);
IBMF_SAA_SUB32_KSTATS(saa_portp, outstanding_requests, 1);
if (res != IBMF_SUCCESS)
IBMF_SAA_ADD32_KSTATS(saa_portp, failed_requests,
1);
if (res == IBMF_TRANS_TIMEOUT)
IBMF_SAA_ADD32_KSTATS(saa_portp, requests_timedout,
1);
mutex_exit(&saa_portp->saa_pt_kstat_mutex);
kmem_free(trans_info, sizeof (saa_impl_trans_info_t));
}
bail:
if (res != IBMF_SUCCESS) {
if (length != NULL)
*length = 0;
if (result != NULL)
*result = NULL;
}
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3, ibmf_sa_access, IBMF_TNF_TRACE,
"", "ibmf_sa_access() exit: result = 0x%x\n",
tnf_opaque, result, res);
return (res);
}
int
ibmf_saa_gid_to_pathrecords(ibmf_saa_handle_t ibmf_saa_handle, ib_gid_t sgid,
ib_gid_t dgid, ib_pkey_t p_key, ib_mtu_t mtu, boolean_t reversible,
uint8_t *num_paths, uint_t flags, size_t *length, sa_path_record_t **result)
{
sa_path_record_t path_record;
uint64_t comp_mask;
int res;
ibmf_saa_access_args_t access_args;
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_saa_gid_to_pathrecords_start, IBMF_TNF_TRACE, "",
"ibmf_saa_gid_to_pathrecords() enter\n");
if (num_paths == NULL) {
IBMF_TRACE_1(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_saa_gid_to_pathrecords_err, IBMF_TNF_ERROR, "",
"ibmf_saa_gid_to_pathrecords: %s\n",
tnf_string, msg, "invalid argument, NULL pointer argument");
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_saa_gid_to_pathrecords_end, IBMF_TNF_TRACE,
"", "ibmf_saa_gid_to_pathrecords() exit\n");
if (length != NULL)
*length = 0;
if (result != NULL)
*result = NULL;
return (IBMF_INVALID_ARG);
}
ASSERT(ibmf_saa_handle != NULL);
ASSERT(length != NULL);
ASSERT(result != NULL);
*length = 0;
*result = NULL;
comp_mask = SA_PR_COMPMASK_SGID | SA_PR_COMPMASK_DGID |
SA_PR_COMPMASK_NUMBPATH;
bzero(&path_record, sizeof (sa_path_record_t));
path_record.SGID = sgid;
path_record.DGID = dgid;
path_record.NumbPath = *num_paths;
if (reversible == B_TRUE) {
path_record.Reversible = 1;
comp_mask |= SA_PR_COMPMASK_REVERSIBLE;
}
if (p_key != IBMF_SAA_PKEY_WC) {
path_record.P_Key = p_key;
comp_mask |= SA_PR_COMPMASK_PKEY;
}
if ((mtu != IBMF_SAA_MTU_WC) && (mtu > IB_MTU_256)) {
path_record.MtuSelector = SA_PR_MTU_SEL_GREATER;
path_record.Mtu = (mtu - 1);
comp_mask |= SA_PR_COMPMASK_MTUSELECTOR | SA_PR_COMPMASK_MTU;
}
access_args.sq_attr_id = SA_PATHRECORD_ATTRID;
access_args.sq_access_type = IBMF_SAA_RETRIEVE;
access_args.sq_component_mask = comp_mask;
access_args.sq_template = &path_record;
access_args.sq_callback = NULL;
access_args.sq_callback_arg = NULL;
res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, length,
(void **)result);
if (res != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_saa_gid_to_pathrecords, IBMF_TNF_TRACE, "",
"ibmf_saa_gid_to_pathrecords: %s, ibmf_status = %d\n",
tnf_string, msg, "ibmf_sa_access() failed",
tnf_int, ibmf_status, res);
}
*num_paths = *length / sizeof (sa_path_record_t);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_saa_gid_to_pathrecords_end, IBMF_TNF_TRACE, "",
"ibmf_saa_gid_to_pathrecords() exit: result = 0x%x\n",
tnf_opaque, result, res);
return (res);
}
int
ibmf_saa_paths_from_gid(ibmf_saa_handle_t ibmf_saa_handle, ib_gid_t sgid,
ib_pkey_t p_key, boolean_t reversible, uint_t flags, uint_t *num_paths,
size_t *length, sa_path_record_t **result)
{
sa_path_record_t path_record;
uint64_t comp_mask;
int res;
ibmf_saa_access_args_t access_args;
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_saa_paths_from_gid_start, IBMF_TNF_TRACE, "",
"ibmf_saa_paths_from_gid() enter\n");
ASSERT(ibmf_saa_handle != NULL);
ASSERT(length != NULL);
ASSERT(result != NULL);
comp_mask = SA_PR_COMPMASK_SGID | SA_PR_COMPMASK_NUMBPATH;
bzero(&path_record, sizeof (sa_path_record_t));
path_record.SGID = sgid;
path_record.NumbPath = 1;
if (reversible == B_TRUE) {
path_record.Reversible = 1;
comp_mask |= SA_PR_COMPMASK_REVERSIBLE;
}
if (p_key != IBMF_SAA_PKEY_WC) {
path_record.P_Key = p_key;
comp_mask |= SA_PR_COMPMASK_PKEY;
}
access_args.sq_attr_id = SA_PATHRECORD_ATTRID;
access_args.sq_access_type = IBMF_SAA_RETRIEVE;
access_args.sq_component_mask = comp_mask;
access_args.sq_template = &path_record;
access_args.sq_callback = NULL;
access_args.sq_callback_arg = NULL;
res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, length,
(void **)result);
if (res != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_saa_gid_to_pathrecords, IBMF_TNF_TRACE, "",
"ibmf_saa_gid_to_pathrecords: %s, ibmf_status = %d\n",
tnf_string, msg, "ibmf_sa_access() failed",
tnf_int, ibmf_status, res);
}
*num_paths = *length / sizeof (sa_path_record_t);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_saa_paths_from_gid_end, IBMF_TNF_TRACE, "",
"ibmf_saa_paths_from_gid() exit: result = 0x%x\n",
tnf_opaque, result, res);
return (res);
}
int
ibmf_saa_name_to_service_record(ibmf_saa_handle_t ibmf_saa_handle,
char *service_name, ib_pkey_t p_key, uint_t flags,
uint_t *num_records, size_t *length, sa_service_record_t **result)
{
sa_service_record_t service_record;
int res;
ibmf_saa_access_args_t access_args;
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_saa_name_to_service_record_start, IBMF_TNF_TRACE, "",
"ibmf_saa_name_to_service_record() enter\n");
ASSERT(ibmf_saa_handle != NULL);
ASSERT(num_records != NULL);
ASSERT(length != NULL);
ASSERT(result != NULL);
bzero((void *)&service_record, sizeof (sa_service_record_t));
if (strlen(service_name) >= IB_SVC_NAME_LEN) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_saa_name_to_service_record_err, IBMF_TNF_ERROR, "",
"ibmf_saa_gid_to_pathrecords: %s, service_name = %s\n",
tnf_string, msg, "service name too long",
tnf_string, service_name, service_name);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_saa_name_to_service_record_end, IBMF_TNF_TRACE, "",
"ibmf_saa_name_to_service_record() exit\n");
*num_records = 0;
*length = 0;
*result = NULL;
return (IBMF_REQ_INVALID);
}
(void) strncpy((char *)(service_record.ServiceName), service_name,
IB_SVC_NAME_LEN-1);
if (p_key != IBMF_SAA_PKEY_WC) {
service_record.ServiceP_Key = p_key;
access_args.sq_component_mask = SA_SR_COMPMASK_NAME |
SA_SR_COMPMASK_PKEY;
} else
access_args.sq_component_mask = SA_SR_COMPMASK_NAME;
access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
access_args.sq_access_type = IBMF_SAA_RETRIEVE;
access_args.sq_template = &service_record;
access_args.sq_callback = NULL;
access_args.sq_callback_arg = NULL;
res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, length,
(void *)result);
if (res != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_saa_name_to_service_record, IBMF_TNF_TRACE, "",
"ibmf_saa_name_to_service_record: %s, ibmf_status = %d\n",
tnf_string, msg, "ibmf_sa_access() failed",
tnf_int, ibmf_status, res);
}
*num_records = *length / sizeof (sa_service_record_t);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_saa_name_to_service_record_end, IBMF_TNF_TRACE, "",
"ibmf_saa_name_to_service_record() exit: result = 0x%x\n",
tnf_opaque, result, res);
return (res);
}
int
ibmf_saa_id_to_service_record(ibmf_saa_handle_t ibmf_saa_handle,
ib_svc_id_t service_id, ib_pkey_t p_key, uint_t flags, uint_t *num_records,
size_t *length, sa_service_record_t **result)
{
sa_service_record_t service_record;
int res;
ibmf_saa_access_args_t access_args;
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_saa_id_to_service_record_start, IBMF_TNF_TRACE, "",
"ibmf_saa_id_to_service_record() enter\n");
ASSERT(ibmf_saa_handle != NULL);
ASSERT(num_records != NULL);
ASSERT(length != NULL);
ASSERT(result != NULL);
bzero((void *)&service_record, sizeof (sa_service_record_t));
service_record.ServiceID = service_id;
if (p_key != IBMF_SAA_PKEY_WC) {
service_record.ServiceP_Key = p_key;
access_args.sq_component_mask = SA_SR_COMPMASK_ID |
SA_SR_COMPMASK_PKEY;
} else
access_args.sq_component_mask = SA_SR_COMPMASK_ID;
access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
access_args.sq_access_type = IBMF_SAA_RETRIEVE;
access_args.sq_template = &service_record;
access_args.sq_callback = NULL;
access_args.sq_callback_arg = NULL;
res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, length,
(void **)result);
if (res != IBMF_SUCCESS) {
IBMF_TRACE_2(IBMF_TNF_DEBUG, DPRINT_L2,
ibmf_saa_id_to_service_record, IBMF_TNF_TRACE, "",
"ibmf_saa_id_to_service_record: %s, ibmf_status = %d\n",
tnf_string, msg, "ibmf_sa_access() failed",
tnf_int, ibmf_status, res);
}
*num_records = *length / sizeof (sa_service_record_t);
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_saa_id_to_service_record_end, IBMF_TNF_TRACE, "",
"ibmf_saa_id_to_service_record() exit: result = 0x%x\n",
tnf_opaque, result, res);
return (res);
}
int
ibmf_saa_update_service_record(ibmf_saa_handle_t ibmf_saa_handle,
sa_service_record_t *service_record, ibmf_saa_access_type_t access_type,
uint_t flags)
{
size_t length;
void *result;
int res;
uint64_t comp_mask;
ibmf_saa_access_args_t access_args;
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_saa_update_service_record_start, IBMF_TNF_TRACE, "",
"ibmf_saa_update_service_record() enter\n");
ASSERT(ibmf_saa_handle != NULL);
if ((access_type != IBMF_SAA_UPDATE) &&
(access_type != IBMF_SAA_DELETE)) {
IBMF_TRACE_2(IBMF_TNF_NODEBUG, DPRINT_L1,
ibmf_saa_update_service_record_err, IBMF_TNF_ERROR, "",
"ibmf_saa_update_service_record: %s, access_type = 0x%x\n",
tnf_string, msg, "invalid query type",
tnf_opaque, access_type, access_type);
IBMF_TRACE_0(IBMF_TNF_DEBUG, DPRINT_L4,
ibmf_saa_update_service_record_end, IBMF_TNF_TRACE, "",
"ibmf_saa_update_service_record() exit\n");
return (IBMF_REQ_INVALID);
}
comp_mask = SA_SR_COMPMASK_ID | SA_SR_COMPMASK_GID |
SA_SR_COMPMASK_PKEY | SA_SR_COMPMASK_KEY;
access_args.sq_attr_id = SA_SERVICERECORD_ATTRID;
access_args.sq_access_type = access_type;
access_args.sq_component_mask = comp_mask;
access_args.sq_template = service_record;
access_args.sq_callback = NULL;
access_args.sq_callback_arg = NULL;
res = ibmf_sa_access(ibmf_saa_handle, &access_args, 0, &length,
&result);
if (res == IBMF_SUCCESS && length > 0) {
if (length > sizeof (sa_service_record_t)) {
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L1,
ibmf_saa_update_service_record, IBMF_TNF_TRACE, "",
"ibmf_saa_update_service_record: %s\n",
tnf_string, msg,
"SA returned more than one record");
}
kmem_free(result, length);
}
IBMF_TRACE_1(IBMF_TNF_DEBUG, DPRINT_L3,
ibmf_saa_update_service_record_end, IBMF_TNF_TRACE, "",
"ibmf_saa_update_service_record() exit: result = 0x%x\n",
tnf_opaque, result, res);
return (res);
}