|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
This file is provided under a dual BSD/GPLv2 license. When using or
|
|
Packit |
961e70 |
redistributing this file, you may do so under either license.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
GPL LICENSE SUMMARY
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Copyright(c) 2015 Intel Corporation.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
961e70 |
it under the terms of version 2 of the GNU General Public License as
|
|
Packit |
961e70 |
published by the Free Software Foundation.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
This program is distributed in the hope that it will be useful, but
|
|
Packit |
961e70 |
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
961e70 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
961e70 |
General Public License for more details.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Contact Information:
|
|
Packit |
961e70 |
Intel Corporation, www.intel.com
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
BSD LICENSE
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Copyright(c) 2015 Intel Corporation.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
961e70 |
modification, are permitted provided that the following conditions
|
|
Packit |
961e70 |
are met:
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
* Redistributions of source code must retain the above copyright
|
|
Packit |
961e70 |
notice, this list of conditions and the following disclaimer.
|
|
Packit |
961e70 |
* Redistributions in binary form must reproduce the above copyright
|
|
Packit |
961e70 |
notice, this list of conditions and the following disclaimer in
|
|
Packit |
961e70 |
the documentation and/or other materials provided with the
|
|
Packit |
961e70 |
distribution.
|
|
Packit |
961e70 |
* Neither the name of Intel Corporation nor the names of its
|
|
Packit |
961e70 |
contributors may be used to endorse or promote products derived
|
|
Packit |
961e70 |
from this software without specific prior written permission.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
961e70 |
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
961e70 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
Packit |
961e70 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
Packit |
961e70 |
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
Packit |
961e70 |
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
Packit |
961e70 |
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
Packit |
961e70 |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
Packit |
961e70 |
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
Packit |
961e70 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
961e70 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Copyright (c) 2003-2014 Intel Corporation. All rights reserved. */
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* This file implements the PSM PTL for ips */
|
|
Packit |
961e70 |
#include "psm_user.h"
|
|
Packit |
961e70 |
#include "psm2_hal.h"
|
|
Packit |
961e70 |
#include "ptl_ips.h"
|
|
Packit |
961e70 |
#include "psm_mq_internal.h"
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
int ips_ptl_recvq_isempty(const struct ptl *ptl);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
int
|
|
Packit |
961e70 |
ips_subcontext_ignore(struct ips_recvhdrq_event *rcv_ev,
|
|
Packit |
961e70 |
uint32_t subcontext)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
return IPS_RECVHDRQ_CONTINUE;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
int
|
|
Packit |
961e70 |
ips_subcontext_process(struct ips_recvhdrq_event *rcv_ev,
|
|
Packit |
961e70 |
uint32_t subcontext)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_shared *recvshc = ((struct ptl_ips *)(rcv_ev->proto->ptl))->recvshc;
|
|
Packit |
961e70 |
if_pt(subcontext != recvshc->subcontext &&
|
|
Packit |
961e70 |
subcontext < recvshc->subcontext_cnt) {
|
|
Packit |
961e70 |
return psmi_hal_forward_packet_to_subcontext(&recvshc->writeq[subcontext],
|
|
Packit |
961e70 |
rcv_ev, subcontext,
|
|
Packit |
961e70 |
rcv_ev->recvq->context->psm_hw_ctxt);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
else {
|
|
Packit |
961e70 |
_HFI_VDBG
|
|
Packit |
961e70 |
("Drop pkt for subcontext %d out of %d (I am %d) : errors 0x%x\n",
|
|
Packit |
961e70 |
(int)subcontext, (int)recvshc->subcontext_cnt,
|
|
Packit |
961e70 |
(int)recvshc->subcontext, psmi_hal_rhf_get_all_err_flags(rcv_ev->psm_hal_rhf));
|
|
Packit |
961e70 |
return IPS_RECVHDRQ_BREAK;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static psm2_error_t shrecvq_init(ptl_t *ptl, const psmi_context_t *context);
|
|
Packit |
961e70 |
static psm2_error_t shrecvq_fini(ptl_t *ptl);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static size_t ips_ptl_sizeof(void)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
return sizeof(struct ptl_ips);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
int ips_ptl_epaddr_stats_num(void)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
return sizeof(struct ips_proto_epaddr_stats) / sizeof(uint64_t);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
int ips_ptl_epaddr_stats_init(char **desc, uint16_t *flags)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
int num_stats =
|
|
Packit |
961e70 |
sizeof(struct ips_proto_epaddr_stats) / sizeof(uint64_t);
|
|
Packit |
961e70 |
int i;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* All stats are uint64_t */
|
|
Packit |
961e70 |
for (i = 0; i < num_stats; i++)
|
|
Packit |
961e70 |
flags[i] = MPSPAWN_STATS_REDUCTION_ALL |
|
|
Packit |
961e70 |
MPSPAWN_STATS_SKIP_IF_ZERO;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
desc[0] = "errchecks sent";
|
|
Packit |
961e70 |
desc[1] = "errchecks recv";
|
|
Packit |
961e70 |
desc[2] = "naks sent";
|
|
Packit |
961e70 |
desc[3] = "naks recv";
|
|
Packit |
961e70 |
desc[4] = "connect reqs sent";
|
|
Packit |
961e70 |
desc[5] = "disconnect reqs sent";
|
|
Packit |
961e70 |
desc[6] = "tid grants sent";
|
|
Packit |
961e70 |
desc[7] = "tid grants recv";
|
|
Packit |
961e70 |
desc[8] = "send rexmit";
|
|
Packit |
961e70 |
desc[9] = "congestion packets";
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
return num_stats;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
int ips_ptl_epaddr_stats_get(psm2_epaddr_t epaddr, uint64_t *stats_o)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
int i, num_stats =
|
|
Packit |
961e70 |
sizeof(struct ips_proto_epaddr_stats) / sizeof(uint64_t);
|
|
Packit |
961e70 |
uint64_t *stats_i = (uint64_t *) &epaddr->proto->epaddr_stats;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
for (i = 0; i < num_stats; i++)
|
|
Packit |
961e70 |
stats_o[i] = stats_i[i];
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
return num_stats;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
psm2_error_t
|
|
Packit |
961e70 |
psmi_context_check_status_callback(struct psmi_timer *t, uint64_t current)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)t->context;
|
|
Packit |
961e70 |
const uint64_t current_count = get_cycles();
|
|
Packit |
961e70 |
psm2_error_t err;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
err = psmi_context_check_status(ptl->context);
|
|
Packit |
961e70 |
if (err == PSM2_OK || err == PSM2_OK_NO_PROGRESS)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
int rc = psmi_hal_spio_process_events((struct ptl *)ptl);
|
|
Packit |
961e70 |
err = rc >= 0 ? PSM2_OK : PSM2_INTERNAL_ERR;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
psmi_timer_request_always(&ptl->timerq, &ptl->status_timer,
|
|
Packit |
961e70 |
current_count + ptl->status_cyc_timeout);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
psm2_error_t ips_ptl_init(const psm2_ep_t ep, ptl_t *ptl_gen, ptl_ctl_t *ctl)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)ptl_gen;
|
|
Packit |
961e70 |
psm2_error_t err = PSM2_OK;
|
|
Packit |
961e70 |
uint32_t num_of_send_bufs = ep->hfi_num_sendbufs;
|
|
Packit |
961e70 |
uint32_t num_of_send_desc = ep->hfi_num_descriptors;
|
|
Packit |
961e70 |
uint32_t imm_size = ep->hfi_imm_size;
|
|
Packit |
961e70 |
const psmi_context_t *context = &ep->context;
|
|
Packit |
961e70 |
const int enable_shcontexts = (psmi_hal_get_subctxt_cnt(context->psm_hw_ctxt) > 0);
|
|
Packit |
961e70 |
const uint64_t current_count = get_cycles();
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Preconditions */
|
|
Packit |
961e70 |
psmi_assert_always(ep != NULL);
|
|
Packit |
961e70 |
psmi_assert_always(ep->epaddr != NULL);
|
|
Packit |
961e70 |
psmi_assert_always(ep->epid != 0);
|
|
Packit |
961e70 |
psmi_assert_always(ep->hfi_num_sendbufs > 0);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
memset(ptl, 0, sizeof(struct ptl_ips));
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
ptl->ep = ep; /* back pointer */
|
|
Packit |
961e70 |
ptl->epid = ep->epid; /* cache epid */
|
|
Packit |
961e70 |
ptl->epaddr = ep->epaddr; /* cache a copy */
|
|
Packit |
961e70 |
ptl->ctl = ctl;
|
|
Packit |
961e70 |
ptl->context = context;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
memset(ctl, 0, sizeof(*ctl));
|
|
Packit |
961e70 |
/* Fill in the control structure */
|
|
Packit |
961e70 |
ctl->ep = ep;
|
|
Packit |
961e70 |
ctl->ptl = ptl_gen;
|
|
Packit |
961e70 |
ctl->ep_poll = enable_shcontexts ? ips_ptl_shared_poll : ips_ptl_poll;
|
|
Packit |
961e70 |
ctl->ep_connect = ips_ptl_connect;
|
|
Packit |
961e70 |
ctl->ep_disconnect = ips_ptl_disconnect;
|
|
Packit |
961e70 |
ctl->mq_send = ips_proto_mq_send;
|
|
Packit |
961e70 |
ctl->mq_isend = ips_proto_mq_isend;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
ctl->am_get_parameters = ips_am_get_parameters;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
ctl->am_short_request = ips_am_short_request;
|
|
Packit |
961e70 |
ctl->am_short_reply = ips_am_short_reply;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
ctl->epaddr_stats_num = ips_ptl_epaddr_stats_num;
|
|
Packit |
961e70 |
ctl->epaddr_stats_init = ips_ptl_epaddr_stats_init;
|
|
Packit |
961e70 |
ctl->epaddr_stats_get = ips_ptl_epaddr_stats_get;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
ctl->msg_size_thresh_query = ips_proto_msg_size_thresh_query;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Runtime flags in 'ptl' are different from runtime flags in 'context'.
|
|
Packit |
961e70 |
* In 'context', runtime flags reflect what the driver is capable of.
|
|
Packit |
961e70 |
* In 'ptl', runtime flags reflect the features we can or want to use in
|
|
Packit |
961e70 |
* the driver's supported runtime flags.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* This timer is to be used to check the context's status at every
|
|
Packit |
961e70 |
* PSMI_CONTEXT_STATUS_CHECK_INTERVAL_MSECS. This is useful to detect when
|
|
Packit |
961e70 |
* the link transitions from the DOWN state to the UP state. We can thus
|
|
Packit |
961e70 |
* stop aggregating link failure messages once we detect that the link is
|
|
Packit |
961e70 |
* up.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
psmi_timer_entry_init(&ptl->status_timer,
|
|
Packit |
961e70 |
psmi_context_check_status_callback, ptl);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* cache the context's status timeout in cycles */
|
|
Packit |
961e70 |
ptl->status_cyc_timeout =
|
|
Packit |
961e70 |
ms_2_cycles(PSMI_CONTEXT_STATUS_CHECK_INTERVAL_MSECS);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Retransmissions and pending operations are kept in a timer structure
|
|
Packit |
961e70 |
* (queue). The timerq is shared to various internal IPS interfaces so
|
|
Packit |
961e70 |
* that they too may schedule events on the timer queue. The timerq is
|
|
Packit |
961e70 |
* drained in the progress function.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if ((err = psmi_timer_init(&ptl->timerq)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* start the context's status timer */
|
|
Packit |
961e70 |
psmi_timer_request_always(&ptl->timerq, &ptl->status_timer,
|
|
Packit |
961e70 |
current_count + ptl->status_cyc_timeout);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Epstate maps endpoint ids (epid integers) to ipsaddr (structs). Mappings
|
|
Packit |
961e70 |
* are added/removed by the connect portion of the ips protocol and lookup
|
|
Packit |
961e70 |
* is made by the receive queue processing component.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if ((err = ips_epstate_init(&ptl->epstate, context)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Context sharing, setup subcontext ureg page.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if (enable_shcontexts) {
|
|
Packit |
961e70 |
struct ptl_shared *recvshc;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
recvshc = (struct ptl_shared *)
|
|
Packit |
961e70 |
psmi_calloc(ep, UNDEFINED, 1, sizeof(struct ptl_shared));
|
|
Packit |
961e70 |
if (recvshc == NULL) {
|
|
Packit |
961e70 |
err = PSM2_NO_MEMORY;
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
ptl->recvshc = recvshc;
|
|
Packit |
961e70 |
recvshc->ptl = ptl_gen;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Initialize recvshc fields */
|
|
Packit |
961e70 |
recvshc->context = psmi_hal_get_context(context->psm_hw_ctxt);
|
|
Packit |
961e70 |
recvshc->subcontext = psmi_hal_get_subctxt(context->psm_hw_ctxt);
|
|
Packit |
961e70 |
recvshc->subcontext_cnt = psmi_hal_get_subctxt_cnt(context->psm_hw_ctxt);
|
|
Packit |
961e70 |
psmi_assert_always(recvshc->subcontext_cnt <=
|
|
Packit |
961e70 |
PSM_HAL_MAX_SHARED_CTXTS);
|
|
Packit |
961e70 |
psmi_assert_always(recvshc->subcontext <
|
|
Packit |
961e70 |
recvshc->subcontext_cnt);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Using ep->context to avoid const modifier since this function
|
|
Packit |
961e70 |
* will modify the content in ep->context.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if ((err = psmi_hal_subcontext_ureg_get(ptl_gen,
|
|
Packit |
961e70 |
recvshc->subcontext_ureg, context->psm_hw_ctxt)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Note that the GEN1 HAL instance initializes struct ips_subcontext_ureg
|
|
Packit |
961e70 |
during context open. */
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
recvshc->context_lock = &recvshc->hwcontext_ctrl->context_lock;
|
|
Packit |
961e70 |
if (recvshc->subcontext == 0) {
|
|
Packit |
961e70 |
if (pthread_spin_init(recvshc->context_lock,
|
|
Packit |
961e70 |
PTHREAD_PROCESS_SHARED) != 0) {
|
|
Packit |
961e70 |
err =
|
|
Packit |
961e70 |
psmi_handle_error(ptl->ep,
|
|
Packit |
961e70 |
PSM2_EP_DEVICE_FAILURE,
|
|
Packit |
961e70 |
"Couldn't initialize process-shared spin lock");
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Hardware send pio used by eager and control messages.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if ((err = psmi_hal_spio_init(context, ptl_gen, &ptl->spioc)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Actual ips protocol handling.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if ((err =
|
|
Packit |
961e70 |
ips_proto_init(context, ptl_gen, num_of_send_bufs, num_of_send_desc,
|
|
Packit |
961e70 |
imm_size, &ptl->timerq, &ptl->epstate, ptl->spioc,
|
|
Packit |
961e70 |
&ptl->proto)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Hardware receive hdr/egr queue, services incoming packets and issues
|
|
Packit |
961e70 |
* callbacks for protocol handling in proto_recv. It uses the epstate
|
|
Packit |
961e70 |
* interface to determine if a packet is known or unknown.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if (!enable_shcontexts) {
|
|
Packit |
961e70 |
struct ips_recvhdrq_callbacks recvq_callbacks;
|
|
Packit |
961e70 |
recvq_callbacks.callback_packet_unknown =
|
|
Packit |
961e70 |
ips_proto_process_unknown;
|
|
Packit |
961e70 |
recvq_callbacks.callback_subcontext = ips_subcontext_ignore;
|
|
Packit |
961e70 |
recvq_callbacks.callback_error = ips_proto_process_packet_error;
|
|
Packit |
961e70 |
if ((err =
|
|
Packit |
961e70 |
ips_recvhdrq_init(context, &ptl->epstate, &ptl->proto,
|
|
Packit |
961e70 |
&recvq_callbacks,
|
|
Packit |
961e70 |
0, &ptl->recvq,
|
|
Packit |
961e70 |
&ptl->recvq_state,
|
|
Packit |
961e70 |
PSM_HAL_CL_Q_RX_HDR_Q)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Software receive hdr/egr queue, used in shared contexts.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
else if ((err = shrecvq_init(ptl_gen, context)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Receive thread, always initialized but not necessary creates a
|
|
Packit |
961e70 |
* pthread.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if ((err = ips_ptl_rcvthread_init(ptl_gen, &ptl->recvq)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
fail:
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static psm2_error_t ips_ptl_fini(ptl_t *ptl_gen, int force, uint64_t timeout_in)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)ptl_gen;
|
|
Packit |
961e70 |
psm2_error_t err = PSM2_OK;
|
|
Packit |
961e70 |
const int enable_shcontexts = (psmi_hal_get_subctxt_cnt(ptl->context->psm_hw_ctxt) > 0);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if ((err = ips_proto_fini(&ptl->proto, force, timeout_in)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* We have to cancel the thread after terminating the protocol because
|
|
Packit |
961e70 |
* connect/disconnect packets use interrupts and the kernel doesn't
|
|
Packit |
961e70 |
* like to have no pollers waiting */
|
|
Packit |
961e70 |
if ((err = ips_ptl_rcvthread_fini(ptl_gen)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if ((err = ips_epstate_fini(&ptl->epstate)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if ((err = psmi_hal_spio_fini(&ptl->spioc, ptl->context->psm_hw_ctxt)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if ((err = psmi_timer_fini(&ptl->timerq)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (enable_shcontexts && (err = shrecvq_fini(ptl_gen)))
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
fail:
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
psm2_error_t
|
|
Packit |
961e70 |
ips_ptl_optctl(const void *core_obj, int optname,
|
|
Packit |
961e70 |
void *optval, uint64_t *optlen, int get)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
psm2_error_t err = PSM2_OK;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
switch (optname) {
|
|
Packit |
961e70 |
case PSM2_IB_OPT_EP_SL:
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
/* Core object is psm2_epaddr */
|
|
Packit |
961e70 |
psm2_epaddr_t epaddr = (psm2_epaddr_t) core_obj;
|
|
Packit |
961e70 |
ips_epaddr_t *ipsaddr = (ips_epaddr_t *) epaddr;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* If endpoint does not use IB ignore for set, complain for get */
|
|
Packit |
961e70 |
if (epaddr->ptlctl->ep_connect != ips_ptl_connect) {
|
|
Packit |
961e70 |
if (get)
|
|
Packit |
961e70 |
err =
|
|
Packit |
961e70 |
psmi_handle_error(PSMI_EP_LOGEVENT,
|
|
Packit |
961e70 |
PSM2_PARAM_ERR,
|
|
Packit |
961e70 |
"Invalid EP transport");
|
|
Packit |
961e70 |
goto exit_fn;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Sanity check option length */
|
|
Packit |
961e70 |
if (*optlen < sizeof(uint8_t)) {
|
|
Packit |
961e70 |
err =
|
|
Packit |
961e70 |
psmi_handle_error(PSMI_EP_LOGEVENT,
|
|
Packit |
961e70 |
PSM2_PARAM_ERR,
|
|
Packit |
961e70 |
"Option value length error");
|
|
Packit |
961e70 |
*optlen = sizeof(unsigned);
|
|
Packit |
961e70 |
goto exit_fn;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (get) {
|
|
Packit |
961e70 |
/* Get returns the SL for the PIO flow */
|
|
Packit |
961e70 |
*((uint8_t *) optval) =
|
|
Packit |
961e70 |
(uint8_t) ipsaddr->
|
|
Packit |
961e70 |
flows[EP_FLOW_GO_BACK_N_PIO].path->pr_sl;
|
|
Packit |
961e70 |
} else {
|
|
Packit |
961e70 |
uint16_t new_sl;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Sanity check if SL is within range */
|
|
Packit |
961e70 |
new_sl = (uint16_t) *(uint8_t *) optval;
|
|
Packit |
961e70 |
if (new_sl > PSMI_SL_MAX) {
|
|
Packit |
961e70 |
err =
|
|
Packit |
961e70 |
psmi_handle_error(PSMI_EP_LOGEVENT,
|
|
Packit |
961e70 |
PSM2_PARAM_ERR,
|
|
Packit |
961e70 |
"Invalid SL value %u. %d<= SL <=%d.",
|
|
Packit |
961e70 |
new_sl, PSMI_SL_MIN, PSMI_SL_MAX);
|
|
Packit |
961e70 |
goto exit_fn;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Set new SL for all flows */
|
|
Packit |
961e70 |
ipsaddr->flows[EP_FLOW_GO_BACK_N_PIO].path->
|
|
Packit |
961e70 |
pr_sl = new_sl;
|
|
Packit |
961e70 |
ipsaddr->flows[EP_FLOW_GO_BACK_N_DMA].path->
|
|
Packit |
961e70 |
pr_sl = new_sl;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
break;
|
|
Packit |
961e70 |
case PSM2_IB_OPT_DF_SL:
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
/* Set default SL to be used by an endpoint for all communication */
|
|
Packit |
961e70 |
/* Core object is psm2_epaddr */
|
|
Packit |
961e70 |
psm2_ep_t ep = (psm2_ep_t) core_obj;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Make sure ep is specified */
|
|
Packit |
961e70 |
if (!ep) {
|
|
Packit |
961e70 |
err =
|
|
Packit |
961e70 |
psmi_handle_error(PSMI_EP_LOGEVENT,
|
|
Packit |
961e70 |
PSM2_PARAM_ERR,
|
|
Packit |
961e70 |
"Invalid PSM Endpoint");
|
|
Packit |
961e70 |
goto exit_fn;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Sanity check option length */
|
|
Packit |
961e70 |
if (*optlen < sizeof(uint8_t)) {
|
|
Packit |
961e70 |
err =
|
|
Packit |
961e70 |
psmi_handle_error(PSMI_EP_LOGEVENT,
|
|
Packit |
961e70 |
PSM2_PARAM_ERR,
|
|
Packit |
961e70 |
"Option value length error");
|
|
Packit |
961e70 |
*optlen = sizeof(uint8_t);
|
|
Packit |
961e70 |
goto exit_fn;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (get) {
|
|
Packit |
961e70 |
*((uint8_t *) optval) =
|
|
Packit |
961e70 |
((struct ptl_ips *)(ep->ptl_ips.ptl))->proto.epinfo.ep_sl;
|
|
Packit |
961e70 |
} else {
|
|
Packit |
961e70 |
uint16_t new_sl;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Sanity check if SL is within range */
|
|
Packit |
961e70 |
new_sl = (uint16_t) *(uint8_t *) optval;
|
|
Packit |
961e70 |
if (new_sl > PSMI_SL_MAX) {
|
|
Packit |
961e70 |
err =
|
|
Packit |
961e70 |
psmi_handle_error(PSMI_EP_LOGEVENT,
|
|
Packit |
961e70 |
PSM2_PARAM_ERR,
|
|
Packit |
961e70 |
"Invalid SL value %u. %d<= SL <=%d.",
|
|
Packit |
961e70 |
new_sl, PSMI_SL_MIN, PSMI_SL_MAX);
|
|
Packit |
961e70 |
goto exit_fn;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
((struct ptl_ips *)(ep->ptl_ips.ptl))->proto.epinfo.ep_sl =
|
|
Packit |
961e70 |
(uint8_t) new_sl;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
break;
|
|
Packit |
961e70 |
default:
|
|
Packit |
961e70 |
err =
|
|
Packit |
961e70 |
psmi_handle_error(NULL, PSM2_PARAM_ERR,
|
|
Packit |
961e70 |
"Unknown PSM2_IB option %u.", optname);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
exit_fn:
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
psm2_error_t
|
|
Packit |
961e70 |
ips_ptl_setopt(const void *component_obj, int optname,
|
|
Packit |
961e70 |
const void *optval, uint64_t optlen)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
return ips_ptl_optctl(component_obj, optname, (void *)optval, &optlen,
|
|
Packit |
961e70 |
0);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
psm2_error_t
|
|
Packit |
961e70 |
ips_ptl_getopt(const void *component_obj, int optname,
|
|
Packit |
961e70 |
void *optval, uint64_t *optlen)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
return ips_ptl_optctl(component_obj, optname, optval, optlen, 1);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static
|
|
Packit |
961e70 |
uint32_t
|
|
Packit |
961e70 |
ips_ptl_rcvthread_is_enabled(const ptl_t *ptl)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
return psmi_hal_has_sw_status(PSM_HAL_PSMI_RUNTIME_RX_THREAD_STARTED);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psm2_error_t ips_ptl_poll(ptl_t *ptl_gen, int _ignored)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)ptl_gen;
|
|
Packit |
961e70 |
const uint64_t current_count = get_cycles();
|
|
Packit |
961e70 |
const int do_lock = PSMI_LOCK_DISABLED &&
|
|
Packit |
961e70 |
psmi_hal_has_sw_status(PSM_HAL_PSMI_RUNTIME_RX_THREAD_STARTED);
|
|
Packit |
961e70 |
psm2_error_t err = PSM2_OK_NO_PROGRESS;
|
|
Packit |
961e70 |
psm2_error_t err2;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (!ips_recvhdrq_isempty(&ptl->recvq)) {
|
|
Packit |
961e70 |
if (do_lock && !ips_recvhdrq_trylock(&ptl->recvq))
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
if (ptl->recvq.proto->flags & IPS_PROTO_FLAG_CCA_PRESCAN) {
|
|
Packit |
961e70 |
ips_recvhdrq_scan_cca(&ptl->recvq);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
err = ips_recvhdrq_progress(&ptl->recvq);
|
|
Packit |
961e70 |
if (do_lock)
|
|
Packit |
961e70 |
ips_recvhdrq_unlock(&ptl->recvq);
|
|
Packit |
961e70 |
if_pf(err > PSM2_OK_NO_PROGRESS)
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
err2 =
|
|
Packit |
961e70 |
psmi_timer_process_if_expired(&(ptl->timerq),
|
|
Packit |
961e70 |
current_count);
|
|
Packit |
961e70 |
if (err2 != PSM2_OK_NO_PROGRESS)
|
|
Packit |
961e70 |
return err2;
|
|
Packit |
961e70 |
else
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Process timer expirations after servicing receive queues (some packets
|
|
Packit |
961e70 |
* may have been acked, some requests-to-send may have been queued).
|
|
Packit |
961e70 |
*
|
|
Packit |
961e70 |
* It's safe to look at the timer without holding the lock because it's not
|
|
Packit |
961e70 |
* incorrect to be wrong some of the time.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
if (psmi_timer_is_expired(&(ptl->timerq), current_count)) {
|
|
Packit |
961e70 |
if (do_lock)
|
|
Packit |
961e70 |
ips_recvhdrq_lock(&ptl->recvq);
|
|
Packit |
961e70 |
err = psmi_timer_process_expired(&(ptl->timerq), current_count);
|
|
Packit |
961e70 |
if (do_lock)
|
|
Packit |
961e70 |
ips_recvhdrq_unlock(&ptl->recvq);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
PSMI_INLINE(int ips_try_lock_shared_context(struct ptl_shared *recvshc))
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
return pthread_spin_trylock(recvshc->context_lock);
|
|
Packit |
961e70 |
}
|
|
Packit Service |
7ed5cc |
/* Unused
|
|
Packit |
961e70 |
PSMI_INLINE(void ips_lock_shared_context(struct ptl_shared *recvshc))
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
pthread_spin_lock(recvshc->context_lock);
|
|
Packit |
961e70 |
}
|
|
Packit Service |
7ed5cc |
*/
|
|
Packit |
961e70 |
PSMI_INLINE(void ips_unlock_shared_context(struct ptl_shared *recvshc))
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
pthread_spin_unlock(recvshc->context_lock);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psm2_error_t ips_ptl_shared_poll(ptl_t *ptl_gen, int _ignored)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)ptl_gen;
|
|
Packit |
961e70 |
const uint64_t current_count = get_cycles();
|
|
Packit |
961e70 |
psm2_error_t err = PSM2_OK_NO_PROGRESS;
|
|
Packit |
961e70 |
psm2_error_t err2;
|
|
Packit |
961e70 |
struct ptl_shared *recvshc = ptl->recvshc;
|
|
Packit |
961e70 |
psmi_assert(recvshc != NULL);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* The following header queue checks are speculative (but safe)
|
|
Packit |
961e70 |
* until this process has acquired the lock. The idea is to
|
|
Packit |
961e70 |
* minimize lock contention due to processes spinning on the
|
|
Packit |
961e70 |
* shared context. */
|
|
Packit |
961e70 |
if (ips_recvhdrq_isempty(&recvshc->recvq)) {
|
|
Packit |
961e70 |
if (!ips_recvhdrq_isempty(&ptl->recvq) &&
|
|
Packit |
961e70 |
ips_try_lock_shared_context(recvshc) == 0) {
|
|
Packit |
961e70 |
/* check that subcontext is empty while under lock to avoid
|
|
Packit |
961e70 |
* re-ordering of incoming packets (since packets from
|
|
Packit |
961e70 |
* hardware context will be processed immediately). */
|
|
Packit |
961e70 |
if_pt(ips_recvhdrq_isempty(&recvshc->recvq)) {
|
|
Packit |
961e70 |
if (ptl->recvq.proto->flags & IPS_PROTO_FLAG_CCA_PRESCAN) {
|
|
Packit |
961e70 |
ips_recvhdrq_scan_cca(&ptl->recvq);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
err = ips_recvhdrq_progress(&ptl->recvq);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
ips_unlock_shared_context(recvshc);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if_pf(err > PSM2_OK_NO_PROGRESS)
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (!ips_recvhdrq_isempty(&recvshc->recvq)) {
|
|
Packit |
961e70 |
if (recvshc->recvq.proto->flags & IPS_PROTO_FLAG_CCA_PRESCAN) {
|
|
Packit |
961e70 |
ips_recvhdrq_scan_cca(&recvshc->recvq);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
err2 = ips_recvhdrq_progress(&recvshc->recvq);
|
|
Packit |
961e70 |
if (err2 != PSM2_OK_NO_PROGRESS) {
|
|
Packit |
961e70 |
err = err2;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if_pf(err > PSM2_OK_NO_PROGRESS)
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Process timer expirations after servicing receive queues (some packets
|
|
Packit |
961e70 |
* may have been acked, some requests-to-send may have been queued).
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
err2 = psmi_timer_process_if_expired(&(ptl->timerq), current_count);
|
|
Packit |
961e70 |
if (err2 != PSM2_OK_NO_PROGRESS)
|
|
Packit |
961e70 |
err = err2;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
int ips_ptl_recvq_isempty(const ptl_t *ptl_gen)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)ptl_gen;
|
|
Packit |
961e70 |
struct ptl_shared *recvshc = ptl->recvshc;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (recvshc != NULL && !ips_recvhdrq_isempty(&recvshc->recvq))
|
|
Packit |
961e70 |
return 0;
|
|
Packit |
961e70 |
return ips_recvhdrq_isempty(&ptl->recvq);
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Legacy ips_get_stat -- do nothing.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
int ips_get_stat(psm2_epaddr_t epaddr, ips_sess_stat *stats)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
memset(stats, 0, sizeof(ips_sess_stat));
|
|
Packit |
961e70 |
return 0;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static psm2_error_t shrecvq_init(ptl_t *ptl_gen, const psmi_context_t *context)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)ptl_gen;
|
|
Packit |
961e70 |
struct ptl_shared *recvshc = ptl->recvshc;
|
|
Packit |
961e70 |
struct ips_recvhdrq_callbacks recvq_callbacks;
|
|
Packit |
961e70 |
psm2_error_t err = PSM2_OK;
|
|
Packit |
961e70 |
int i;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Initialize (shared) hardware context recvq (ptl->recvq) */
|
|
Packit |
961e70 |
/* NOTE: uses recvq in ptl structure for shared h/w context */
|
|
Packit |
961e70 |
recvq_callbacks.callback_packet_unknown = ips_proto_process_unknown;
|
|
Packit |
961e70 |
recvq_callbacks.callback_subcontext = ips_subcontext_process;
|
|
Packit |
961e70 |
recvq_callbacks.callback_error = ips_proto_process_packet_error;
|
|
Packit |
961e70 |
if ((err = ips_recvhdrq_init(context, &ptl->epstate, &ptl->proto,
|
|
Packit |
961e70 |
&recvq_callbacks,
|
|
Packit |
961e70 |
recvshc->subcontext,
|
|
Packit |
961e70 |
&ptl->recvq,
|
|
Packit |
961e70 |
&recvshc->hwcontext_ctrl->recvq_state,
|
|
Packit |
961e70 |
PSM_HAL_CL_Q_RX_HDR_Q))) {
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Initialize software subcontext (recvshc->recvq). Subcontexts do */
|
|
Packit |
961e70 |
/* not require the rcvhdr copy feature. */
|
|
Packit |
961e70 |
recvq_callbacks.callback_subcontext = ips_subcontext_ignore;
|
|
Packit |
961e70 |
if ((err = ips_recvhdrq_init(context, &ptl->epstate, &ptl->proto,
|
|
Packit |
961e70 |
&recvq_callbacks,
|
|
Packit |
961e70 |
recvshc->subcontext,
|
|
Packit |
961e70 |
&recvshc->recvq, &recvshc->recvq_state,
|
|
Packit |
961e70 |
PSM_HAL_GET_SC_CL_Q_RX_HDR_Q(recvshc->subcontext)))) {
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Initialize each recvshc->writeq for shared contexts */
|
|
Packit |
961e70 |
for (i = 0; i < recvshc->subcontext_cnt; i++) {
|
|
Packit |
961e70 |
if ((err = ips_writehdrq_init(context,
|
|
Packit |
961e70 |
&recvshc->writeq[i],
|
|
Packit |
961e70 |
&recvshc->subcontext_ureg[i]->
|
|
Packit |
961e70 |
writeq_state,
|
|
Packit |
961e70 |
i))) {
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
if (err == PSM2_OK)
|
|
Packit |
961e70 |
_HFI_DBG
|
|
Packit |
961e70 |
("Context sharing in use: lid %d, context %d, sub-context %d\n",
|
|
Packit |
961e70 |
(int)psm2_epid_nid(ptl->epid), recvshc->context,
|
|
Packit |
961e70 |
recvshc->subcontext);
|
|
Packit |
961e70 |
fail:
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
static psm2_error_t shrecvq_fini(ptl_t *ptl_gen)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)ptl_gen;
|
|
Packit |
961e70 |
psm2_error_t err = PSM2_OK;
|
|
Packit |
961e70 |
int i;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* disable my write header queue before deallocation */
|
|
Packit |
961e70 |
i = ptl->recvshc->subcontext;
|
|
Packit |
961e70 |
ptl->recvshc->subcontext_ureg[i]->writeq_state.enabled = 0;
|
|
Packit |
961e70 |
psmi_free(ptl->recvshc);
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psm2_error_t
|
|
Packit |
961e70 |
ips_ptl_connect(ptl_t *ptl_gen, int numep, const psm2_epid_t *array_of_epid,
|
|
Packit |
961e70 |
const int *array_of_epid_mask, psm2_error_t *array_of_errors,
|
|
Packit |
961e70 |
psm2_epaddr_t *array_of_epaddr, uint64_t timeout_in)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)ptl_gen;
|
|
Packit |
961e70 |
psm2_error_t err;
|
|
Packit |
961e70 |
psm2_ep_t ep;
|
|
Packit |
961e70 |
psm2_epid_t *epid_array = NULL;
|
|
Packit |
961e70 |
psm2_error_t *error_array = NULL;
|
|
Packit |
961e70 |
psm2_epaddr_t *epaddr_array = NULL;
|
|
Packit |
961e70 |
ips_epaddr_t *ipsaddr_master, *ipsaddr;
|
|
Packit |
961e70 |
int *mask_array = NULL;
|
|
Packit |
961e70 |
int i;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
PSMI_LOCK_ASSERT(ptl->ep->mq->progress_lock);
|
|
Packit |
961e70 |
err = ips_proto_connect(&ptl->proto, numep, array_of_epid,
|
|
Packit |
961e70 |
array_of_epid_mask, array_of_errors,
|
|
Packit |
961e70 |
array_of_epaddr, timeout_in);
|
|
Packit |
961e70 |
if (err)
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psmi_assert_always(ptl->ep->mctxt_master == ptl->ep);
|
|
Packit |
961e70 |
if (ptl->ep->mctxt_next == ptl->ep)
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* make the additional mutil-context connections. */
|
|
Packit |
961e70 |
epid_array = (psm2_epid_t *)
|
|
Packit |
961e70 |
psmi_malloc(ptl->ep, UNDEFINED, sizeof(psm2_epid_t) * numep);
|
|
Packit |
961e70 |
mask_array = (int *)
|
|
Packit |
961e70 |
psmi_malloc(ptl->ep, UNDEFINED, sizeof(int) * numep);
|
|
Packit |
961e70 |
error_array = (psm2_error_t *)
|
|
Packit |
961e70 |
psmi_malloc(ptl->ep, UNDEFINED, sizeof(psm2_error_t) * numep);
|
|
Packit |
961e70 |
epaddr_array = (psm2_epaddr_t *)
|
|
Packit |
961e70 |
psmi_malloc(ptl->ep, UNDEFINED, sizeof(psm2_epaddr_t) * numep);
|
|
Packit |
961e70 |
if (!epid_array || !mask_array || !error_array || !epaddr_array) {
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
ep = ptl->ep->mctxt_next;
|
|
Packit |
961e70 |
while (ep != ep->mctxt_master) {
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Setup the mask array and epid array. */
|
|
Packit |
961e70 |
for (i = 0; i < numep; i++) {
|
|
Packit |
961e70 |
if (array_of_epid_mask[i]
|
|
Packit |
961e70 |
&& array_of_errors[i] == PSM2_OK) {
|
|
Packit |
961e70 |
ipsaddr_master =
|
|
Packit |
961e70 |
(ips_epaddr_t *) array_of_epaddr[i];
|
|
Packit |
961e70 |
ipsaddr = ipsaddr_master->next;
|
|
Packit |
961e70 |
mask_array[i] = 0;
|
|
Packit |
961e70 |
while (ipsaddr != ipsaddr_master) {
|
|
Packit |
961e70 |
if (((psm2_epaddr_t) ipsaddr)->proto->
|
|
Packit |
961e70 |
ep == ep) {
|
|
Packit |
961e70 |
mask_array[i] = 1;
|
|
Packit |
961e70 |
epid_array[i] =
|
|
Packit |
961e70 |
((psm2_epaddr_t) ipsaddr)->
|
|
Packit |
961e70 |
epid;
|
|
Packit |
961e70 |
break;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
ipsaddr = ipsaddr->next;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
} else {
|
|
Packit |
961e70 |
mask_array[i] = 0;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Make the real protocol connections. */
|
|
Packit |
961e70 |
err =
|
|
Packit |
961e70 |
ips_proto_connect(&((struct ptl_ips *)(ep->ptl_ips.ptl))->proto,
|
|
Packit |
961e70 |
numep, epid_array, mask_array, error_array,
|
|
Packit |
961e70 |
epaddr_array, timeout_in);
|
|
Packit |
961e70 |
if (err)
|
|
Packit |
961e70 |
goto fail;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
ep = ep->mctxt_next;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
fail:
|
|
Packit |
961e70 |
if (epid_array)
|
|
Packit |
961e70 |
psmi_free(epid_array);
|
|
Packit |
961e70 |
if (mask_array)
|
|
Packit |
961e70 |
psmi_free(mask_array);
|
|
Packit |
961e70 |
if (error_array)
|
|
Packit |
961e70 |
psmi_free(error_array);
|
|
Packit |
961e70 |
if (epaddr_array)
|
|
Packit |
961e70 |
psmi_free(epaddr_array);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psm2_error_t
|
|
Packit |
961e70 |
ips_ptl_disconnect(ptl_t *ptl_gen, int force, int numep,
|
|
Packit |
961e70 |
psm2_epaddr_t array_of_epaddr[],
|
|
Packit |
961e70 |
const int array_of_epaddr_mask[],
|
|
Packit |
961e70 |
psm2_error_t array_of_errors[], uint64_t timeout_in)
|
|
Packit |
961e70 |
{
|
|
Packit |
961e70 |
struct ptl_ips *ptl = (struct ptl_ips *)ptl_gen;
|
|
Packit |
961e70 |
int *array_of_epaddr_mask_internal, i;
|
|
Packit |
961e70 |
psm2_error_t err;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/*
|
|
Packit |
961e70 |
* Copy true values from array_of_epaddr_mask, provided that their
|
|
Packit |
961e70 |
* respective epaddr is an ips one.
|
|
Packit |
961e70 |
* Newly created mask will be used for the protocol disconnect call
|
|
Packit |
961e70 |
* instead.
|
|
Packit |
961e70 |
*/
|
|
Packit |
961e70 |
PSMI_LOCK_ASSERT(ptl->ep->mq->progress_lock);
|
|
Packit |
961e70 |
array_of_epaddr_mask_internal = psmi_calloc(ptl->ep, UNDEFINED,
|
|
Packit |
961e70 |
sizeof(int), numep);
|
|
Packit |
961e70 |
if (!array_of_epaddr_mask_internal)
|
|
Packit |
961e70 |
return PSM2_NO_MEMORY;
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
for (i = 0; i < numep; ++i) {
|
|
Packit |
961e70 |
if (array_of_epaddr_mask[i] && array_of_epaddr[i]
|
|
Packit |
961e70 |
&& array_of_epaddr[i]->ptlctl->ptl == ptl_gen) {
|
|
Packit |
961e70 |
array_of_epaddr_mask_internal[i] = 1;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
err = ips_proto_disconnect(&ptl->proto, force, numep, array_of_epaddr,
|
|
Packit |
961e70 |
array_of_epaddr_mask_internal,
|
|
Packit |
961e70 |
array_of_errors, timeout_in);
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
psmi_free(array_of_epaddr_mask_internal);
|
|
Packit |
961e70 |
return err;
|
|
Packit |
961e70 |
}
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
/* Only symbol we expose out of here */
|
|
Packit |
961e70 |
struct ptl_ctl_init
|
|
Packit |
961e70 |
psmi_ptl_ips = {
|
|
Packit |
961e70 |
ips_ptl_sizeof, ips_ptl_init, ips_ptl_fini, ips_ptl_setopt,
|
|
Packit |
961e70 |
ips_ptl_getopt
|
|
Packit |
961e70 |
};
|
|
Packit |
961e70 |
|
|
Packit |
961e70 |
struct ptl_ctl_rcvthread
|
|
Packit |
961e70 |
psmi_ptl_ips_rcvthread = {
|
|
Packit |
961e70 |
ips_ptl_rcvthread_is_enabled,
|
|
Packit |
961e70 |
ips_ptl_rcvthread_transfer_ownership,
|
|
Packit |
961e70 |
};
|