2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
2N/A */
2N/A
2N/A/*
2N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A/*
2N/A *
2N/A * MODULE: dapl_evd_connection_callback.c
2N/A *
2N/A * PURPOSE: implements connection callbacks
2N/A *
2N/A * Description: Accepts asynchronous callbacks from the Communications Manager
2N/A * for EVDs that have been specified as the connection_evd.
2N/A *
2N/A * $Id: dapl_evd_connection_callb.c,v 1.33 2003/07/30 18:13:38 hobie16 Exp $
2N/A */
2N/A
2N/A#include "dapl.h"
2N/A#include "dapl_evd_util.h"
2N/A#include "dapl_ep_util.h"
2N/A
2N/A
2N/A/*
2N/A * dapl_evd_connection_callback
2N/A *
2N/A * Connection callback function for ACTIVE connection requests; callbacks
2N/A * generated by the Connection Manager in response to issuing a
2N/A * connect call.
2N/A *
2N/A * Input:
2N/A * ib_cm_handle,
2N/A * ib_cm_event
2N/A * private_data_ptr
2N/A * context (evd)
2N/A * cr_pp
2N/A *
2N/A * Output:
2N/A * None
2N/A *
2N/A */
2N/A
2N/Avoid
2N/Adapl_evd_connection_callback(
2N/A IN ib_cm_handle_t ib_cm_handle,
2N/A IN const ib_cm_events_t ib_cm_event,
2N/A IN const void *private_data_ptr,
2N/A IN const void *context)
2N/A{
2N/A DAPL_EP *ep_ptr;
2N/A DAPL_EVD *evd_ptr;
2N/A DAPL_PRIVATE *prd_ptr;
2N/A DAT_EVENT_NUMBER event_type;
2N/A
2N/A dapl_dbg_log(
2N/A DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
2N/A "--> dapl_evd_connection_callback: ctxt: %p event: %x"
2N/A " cm_handle %p\n",
2N/A context,
2N/A ib_cm_event,
2N/A ib_cm_handle);
2N/A
2N/A /*
2N/A * Determine the type of handle passed back to us in the context
2N/A * and sort out key parameters.
2N/A */
2N/A dapl_os_assert(((DAPL_HEADER *)context)->magic == DAPL_MAGIC_EP ||
2N/A ((DAPL_HEADER *)context)->magic == DAPL_MAGIC_EP_EXIT);
2N/A /*
2N/A * Active side of the connection, context is an EP and
2N/A * PSP is irrelevant.
2N/A */
2N/A ep_ptr = (DAPL_EP *)context;
2N/A evd_ptr = (DAPL_EVD *)ep_ptr->param.connect_evd_handle;
2N/A
2N/A prd_ptr = (DAPL_PRIVATE *)private_data_ptr;
2N/A
2N/A switch (ib_cm_event) {
2N/A case IB_CME_CONNECTED:
2N/A {
2N/A /*
2N/A * If we don't have an EP at this point we are very screwed
2N/A * up
2N/A */
2N/A DAT_RETURN dat_status;
2N/A
2N/A if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING) {
2N/A /*
2N/A * If someone pulled the plug on the connection, just
2N/A * exit
2N/A */
2N/A break;
2N/A }
2N/A dapls_ib_connected(ep_ptr);
2N/A ep_ptr->param.ep_state = DAT_EP_STATE_CONNECTED;
2N/A ep_ptr->cm_handle = ib_cm_handle;
2N/A /* copy in the private data */
2N/A (void) dapl_os_memcpy(ep_ptr->private_data,
2N/A prd_ptr->private_data,
2N/A IB_MAX_REQ_PDATA_SIZE);
2N/A
2N/A dat_status = dapls_evd_post_connection_event(
2N/A evd_ptr,
2N/A DAT_CONNECTION_EVENT_ESTABLISHED,
2N/A (DAT_HANDLE) ep_ptr,
2N/A IB_MAX_REQ_PDATA_SIZE,
2N/A ep_ptr->private_data);
2N/A
2N/A if (dat_status != DAT_SUCCESS) {
2N/A (void) dapls_ib_disconnect(ep_ptr,
2N/A DAT_CLOSE_ABRUPT_FLAG);
2N/A ep_ptr->param.ep_state =
2N/A DAT_EP_STATE_DISCONNECT_PENDING;
2N/A }
2N/A
2N/A /*
2N/A * If we received any premature DTO completions and
2N/A * post them to the recv evd now.
2N/A * there is a race here - if events arrive after we change
2N/A * the ep state to connected and before we process premature
2N/A * events
2N/A */
2N/A dapls_evd_post_premature_events(ep_ptr);
2N/A
2N/A break;
2N/A }
2N/A case IB_CME_DISCONNECTED:
2N/A case IB_CME_DISCONNECTED_ON_LINK_DOWN:
2N/A {
2N/A /*
2N/A * EP is now fully disconnected; initiate any post processing
2N/A * to reset the underlying QP and get the EP ready for
2N/A * another connection
2N/A */
2N/A if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED) {
2N/A /* DTO error caused this */
2N/A event_type = DAT_CONNECTION_EVENT_BROKEN;
2N/A } else {
2N/A ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
2N/A dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE,
2N/A ib_cm_event);
2N/A event_type = DAT_CONNECTION_EVENT_DISCONNECTED;
2N/A }
2N/A
2N/A /* If the EP has been freed, the evd_ptr will be NULL */
2N/A if (evd_ptr != NULL) {
2N/A (void) dapls_evd_post_connection_event(
2N/A evd_ptr, event_type, (DAT_HANDLE) ep_ptr, 0, 0);
2N/A }
2N/A
2N/A /*
2N/A * If the user has done an ep_free of the EP, we have been
2N/A * waiting for the disconnect event; just clean it up now.
2N/A */
2N/A if (ep_ptr->header.magic == DAPL_MAGIC_EP_EXIT) {
2N/A (void) dapl_ep_free(ep_ptr);
2N/A }
2N/A break;
2N/A }
2N/A case IB_CME_DESTINATION_REJECT_PRIVATE_DATA:
2N/A {
2N/A ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
2N/A dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
2N/A (void) dapls_evd_post_connection_event(
2N/A evd_ptr,
2N/A DAT_CONNECTION_EVENT_PEER_REJECTED,
2N/A (DAT_HANDLE) ep_ptr,
2N/A 0,
2N/A 0);
2N/A break;
2N/A }
2N/A case IB_CME_DESTINATION_UNREACHABLE:
2N/A {
2N/A ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
2N/A dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
2N/A (void) dapls_evd_post_connection_event(
2N/A evd_ptr,
2N/A DAT_CONNECTION_EVENT_UNREACHABLE,
2N/A (DAT_HANDLE) ep_ptr,
2N/A 0,
2N/A 0);
2N/A break;
2N/A }
2N/A case IB_CME_DESTINATION_REJECT:
2N/A case IB_CME_TOO_MANY_CONNECTION_REQUESTS:
2N/A case IB_CME_LOCAL_FAILURE:
2N/A {
2N/A ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
2N/A dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
2N/A (void) dapls_evd_post_connection_event(
2N/A evd_ptr,
2N/A DAT_CONNECTION_EVENT_NON_PEER_REJECTED,
2N/A (DAT_HANDLE) ep_ptr,
2N/A 0,
2N/A 0);
2N/A break;
2N/A }
2N/A case IB_CME_TIMED_OUT:
2N/A {
2N/A ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
2N/A dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
2N/A (void) dapls_evd_post_connection_event(
2N/A evd_ptr,
2N/A DAT_CONNECTION_EVENT_TIMED_OUT,
2N/A (DAT_HANDLE) ep_ptr,
2N/A 0,
2N/A 0);
2N/A break;
2N/A }
2N/A case IB_CME_CONNECTION_REQUEST_PENDING:
2N/A case IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA:
2N/A default:
2N/A {
2N/A dapl_os_assert(0); /* shouldn't happen */
2N/A break;
2N/A }
2N/A }
2N/A
2N/A dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
2N/A "dapl_evd_connection_callback () returns\n");
2N/A
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Local variables:
2N/A * c-indent-level: 4
2N/A * c-basic-offset: 4
2N/A * tab-width: 8
2N/A * End:
2N/A */