wrsm_session.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Session management module of the Wildcat RSM driver. This module sets
* up sessions with remote drivers. If communication is lost, it notifies
* interested registered modules so they can invalidate any existing
* communication paths.
*/
#include <sys/wrsm_session.h>
#include <sys/wrsm_config.h>
#include <sys/wrsm_transport.h>
#include <sys/wrsm_cmmu.h>
#include <sys/wrsm_sess_impl.h>
#include <sys/wrsm_intr.h>
#include <sys/wrsm_memseg.h>
/*
* The following macros define a DPRINTF macro which can be used to enable
* or disable various levels of logging for this module.
*/
#ifdef DEBUG
#define SESSDBG 0x1
#define SESSWARN 0x2
#define SESSERR 0x4
#define SESSTRACE 0x8
static const char *sess_state_txt[] = {
"SESS_STATE_UNREACH",
"SESS_STATE_DOWN",
"SESS_STATE_ESTAB",
"SESS_STATE_UP"};
#else /* DEBUG */
#define DPRINTF(a, b)
#endif /* DEBUG */
/*
* Local function prototypes
*/
static void node_fini(wrsm_node_session_t *);
static void msg_init(wrsm_network_t *);
static void msg_fini(wrsm_network_t *);
/*
* Local functions
*/
/* Distributes callbacks to all clients */
static int
{
uint_t i;
int dereferences_needed = 0;
net->rsm_ctlr_id));
for (i = 0; i < MAX_CLIENTS; i++) {
if (fn) {
}
}
}
return (dereferences_needed);
}
/*
* Node related functions
*/
/* Initializes node structure */
static void
{
node->last_session_id = 0;
}
/* Cleans up node structure */
static void
{
}
/*
* Changes state of node, performing callback if required.
* NOTE: Releases the node->mutex lock during callbacks.
*/
static void
{
int err;
"node_new_state(ctrl=%u, cnode=%u, state=%s, sess_id=%u)",
while (node->state_changing) {
}
}
"node %d dereferences_needed %d\n",
/* Unmap remote barrier page */
&node->barrier_page,
/* Map remote barrier page */
/*
* Node is claiming it exports an ncslice it doesn't!
* Something must be wrong with connection.
*/
"bad ncslice %d from node %d\n",
} else {
&node->barrier_page,
if (err) {
} else {
}
}
}
/* Re-enter the node->mutex lock */
}
/*
* Message related functions
*/
/* Regiseters message handling functions */
static void
{
}
/* Removes message handling functions */
static void
{
}
/* Handles session start message */
static boolean_t
{
DTRC("msg_session_start");
case SESS_STATE_UNREACH:
break;
case SESS_STATE_DOWN:
} else {
}
break;
case SESS_STATE_ESTAB:
/* If we have lower cnodeid, ignore them */
} else {
/* If they have lower cnodeid, then they win */
}
break;
case SESS_STATE_UP:
/* New session request. Go down then back up */
break;
}
/* Only send response if this is not loopback */
(wrsm_message_t *)response);
}
return (B_TRUE);
}
static boolean_t
{
DTRC("msg_session_start_rsp");
"sess_start_rsp from cnode %u to ctlr %u:"
"bad result = %d",
} else {
node->session_id);
}
/* LINTED: E_NOP_ELSE_STMT */
} else {
"unexpected sess_start_rsp from cnode %u to ctlr %u: "
"result %d, wrong state %s",
}
return (B_TRUE);
}
static boolean_t
{
DTRC("msg_session_end");
case SESS_STATE_ESTAB:
case SESS_STATE_UP:
break;
}
return (B_TRUE);
}
/*
* Interface Functions
*/
/* Init function. */
void
{
uint_t i;
DTRC("wrsm_sess_init");
/* Add session structure to the net structure. */
/* Initialize client callback structure to all NULL */
for (i = 0; i < MAX_CLIENTS; i++) {
}
/* Initialize cnode-specific structures */
for (i = 0; i < WRSM_MAX_CNODES; i++) {
}
/* Tell transport about our message handlers */
/* Publish! */
}
/* Fini function. */
void
{
uint_t i;
DTRC("wrsm_sess_fini");
/* Remove our transport message handlers */
/* Clean-up per node session structures */
for (i = 0; i < WRSM_MAX_CNODES; i++) {
}
}
/* Informs session that a new cnode is reachable */
void
{
unsigned num_tuples;
int err;
cnodeid));
/* First, allocate a cmmu entry */
if (err != WRSM_SUCCESS) {
return;
}
/*
* Fix up the ncslice in the tuple to use the ncslice the
* remote node imports.
*/
/* Allocate enough memory to create an aligned page */
/* Find page-aligned address */
aligned_vaddr = (caddr_t)
/* Write CMMU entry */
/* Update the CMMU */
/* Start the process of establishing a new session */
}
/* Informs session that a cnode is no longer reachable */
void
{
cnodeid));
/* Set CMMU to invalid */
/* Free barrier page memory */
}
/*
* Functions for client use.
*/
/* Establishes a session with a remote cnode, if enabled. */
{
cnodeid));
return (SESS_ID_INVALID);
}
/* If the session is currently down or being established... */
/* Queue an event to the event thread, if necessary */
if (!node->event_queued) {
}
/* Wait for session to be established, or timeout */
timeout);
}
/* If the session came up, return the session id */
}
return (session_id);
}
/* Establishes a session with a remote cnode, if enabled. */
void
{
"cnodeid = %u", cnodeid));
/* Deal with disabled nodes */
return;
}
/* Get a new session id and set state to establishing */
node->last_session_id++;
node->last_session_id++;
}
/* Create and send session start message */
/* Wait for msg_session_start_rsp */
timeout);
/* Don't care why cv was signaled, just check state... */
}
}
}
void
{
case SESS_STATE_UNREACH:
case SESS_STATE_DOWN:
break;
case SESS_STATE_ESTAB:
case SESS_STATE_UP:
}
}
/* Asynchronously tears down a session to a cnode. */
void
{
DTRC("wrsm_sess_teardown");
}
/* Returns the current session. */
{
/*
* We don't need node->mutex here, because reading one int
* is atomic. Also, since the session_is is set to INVALID
* any time the session is not in the UP state, we don't need
* to check which state we're in now.
*/
}
/* Allows user to register for callbacks. */
void
{
uint_t i;
DTRC("wrsm_sess_register");
for (i = 0; i < MAX_CLIENTS; i++) {
break;
}
}
ASSERT(i < MAX_CLIENTS);
}
/* Removes a user callback registration. */
void
{
uint_t i;
DTRC("wrsm_sess_unregister");
for (i = 0; i < MAX_CLIENTS; i++) {
return;
}
}
ASSERT(0);
}
/*
* Functions for use by some session control software entitiy.
*/
/* Enables communication with a cnode. */
void
{
cnodeid));
/*
* A sess disable is in progress. Wait for it to complete
* or fail before enabling.
*/
timeout);
}
}
/* Disables communication with a cnode. May cause a teardown. */
int
{
cnodeid));
}
if (node->dereferences_needed) {
timeout) == -1) {
/* timed out waiting for dereferences - fail */
return (EBUSY);
}
}
return (WRSM_SUCCESS);
}
/* Returns a cnode bitmask indicating which cnodes have valid sessions */
void
{
uint_t i;
DTRC("wrsm_sess_get_cnodes");
for (i = 0; i < WRSM_MAX_CNODES; i++) {
WRSMSET_ADD(*cnodes, i);
}
}
}
/*
* Clients call this when all references to node with invalid session
* are truly freed
*/
void
{
if (node->dereferences_needed) {
"wrsm_sess_unreferenced dereferences needed now %d\n",
if (node->dereferences_needed == 0) {
}
}
}
int
{
int str;
"wrsm_sess_touch_node(cnode=%d,stripes=0x%X)",
membar_sync();
WARN("wrsm_sess_touch_node: session not up");
return (RSMERR_CONN_ABORTED);
}
WARN("wrsm_sess_touch_node: NULL barrier_page pointer");
return (RSMERR_CONN_ABORTED);
}
/* If multiple stripes, get all the writes going in parallel... */
if (str & 1) {
}
}
membar_sync();
/* Now read back. If we get an error, data will be 0. */
if (str & 1) {
WARN("wrsm_sess_touch_node: pattern mismatch");
return (RSMERR_BARRIER_FAILURE);
}
}
}
return (RSM_SUCCESS);
}