[ofw] [ND 5/7] ND: endpoint APIs

Sean Hefty sean.hefty at intel.com
Mon Apr 6 10:23:46 PDT 2009


/*
 * Copyright (c) 2009 Intel Corporation. All rights reserved.
 *
 * This software is available to you under the OpenIB.org BSD license
 * below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#pragma once

#ifndef _ND_ENDPOINT_H_
#define _ND_ENDPOINT_H_

#include <initguid.h>
#include <ndspi.h>
#include "nd_base.h"
#include "nd_connect.h"
#include "nd_cq.h"
#include "nd_adapter.h"


#define ND_MAX_SGE	8


class CNDEndpoint : INDEndpoint, public CNDBase
{
public:
	// IUnknown methods
	STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR* ppvObj);
	STDMETHODIMP_(ULONG) AddRef();
	STDMETHODIMP_(ULONG) Release();

	// INDEndpoint methods
	STDMETHODIMP Flush();
	STDMETHODIMP_(void) StartRequestBatch();
	STDMETHODIMP_(void) SubmitRequestBatch();
	STDMETHODIMP Send(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge, DWORD Flags);
	STDMETHODIMP SendAndInvalidate(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge,
								   const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,
								   DWORD Flags);
	STDMETHODIMP Receive(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge);
	STDMETHODIMP Bind(ND_RESULT* pResult, ND_MR_HANDLE hMr, INDMemoryWindow* pMw,
					  const void* pBuffer, SIZE_T BufferSize, DWORD Flags,
					  ND_MW_DESCRIPTOR* pMwDescriptor);
	STDMETHODIMP Invalidate(ND_RESULT* pResult, INDMemoryWindow* pMw, DWORD Flags);
	STDMETHODIMP Read(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge,
					  const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,
					  ULONGLONG Offset, DWORD Flags);
	STDMETHODIMP Write(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge,
					   const ND_MW_DESCRIPTOR* pRemoteMwDescriptor,
					   ULONGLONG Offset, DWORD Flags);
	
	CNDEndpoint(CNDConnector *pConnector);
	~CNDEndpoint();
	void Delete() {delete this;}
	static STDMETHODIMP
	CreateInstance(CNDConnector *pConnector,
				   CNDCompletionQueue* pInboundCq, CNDCompletionQueue* pOutboundCq,
				   SIZE_T nInboundEntries, SIZE_T nOutboundEntries,
				   SIZE_T nInboundSge, SIZE_T nOutboundSge,
				   SIZE_T InboundReadLimit, SIZE_T OutboundReadLimit,
				   SIZE_T* pMaxInlineData, INDEndpoint** ppEndpoint)
	{
		HRESULT hr;
		CNDEndpoint *ep;

		ep = new CNDEndpoint(pConnector);
		if (ep == NULL) {
			hr = ND_NO_MEMORY;
			goto err1;
		}

		hr = ep->Init(pInboundCq, pOutboundCq, nInboundEntries, nOutboundEntries,
					  nInboundSge, nOutboundSge, InboundReadLimit, OutboundReadLimit,
					  pMaxInlineData);
		if (FAILED(hr)) {
			goto err2;
		}

		*ppEndpoint = ep;
		return ND_SUCCESS;

	err2:
		ep->Release();
	err1:
		*ppEndpoint = NULL;
		return hr;
	}

protected:
	CNDConnector		*m_pConnector;
	CNDCompletionQueue	*m_pInboundCq;
	CNDCompletionQueue	*m_pOutboundCq;
	IWVConnectQueuePair	*m_pWvQp;

	STDMETHODIMP Init(CNDCompletionQueue* pInboundCq, CNDCompletionQueue* pOutboundCq,
					  SIZE_T nInboundEntries, SIZE_T nOutboundEntries,
					  SIZE_T nInboundSge, SIZE_T nOutboundSge,
					  SIZE_T InboundReadLimit, SIZE_T OutboundReadLimit,
					  SIZE_T* pMaxInlineData);
	STDMETHODIMP_(void)	ConvertSgl(const ND_SGE* pSgl, SIZE_T nSge, WV_SGE *pWvSgl);
	STDMETHODIMP_(DWORD) ConvertSendFlags(DWORD Flags);
};

#endif // _ND_ENDPOINT_H_

/*
 * Copyright (c) 2009 Intel Corporation. All rights reserved.
 *
 * This software is available to you under the OpenIB.org BSD license
 * below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "nd_ep.h"
#include "nd_adapter.h"
#include "nd_connect.h"
#include "nd_cq.h"
#include <netinet/in.h>


CNDEndpoint::CNDEndpoint(CNDConnector *pConnector)
{
	pConnector->AddRef();
	m_pConnector = pConnector;
	m_pWvQp = NULL;
	m_pInboundCq = NULL;
	m_pOutboundCq = NULL;
}

STDMETHODIMP CNDEndpoint::
Init(CNDCompletionQueue* pInboundCq, CNDCompletionQueue* pOutboundCq,
	 SIZE_T nInboundEntries, SIZE_T nOutboundEntries,
	 SIZE_T nInboundSge, SIZE_T nOutboundSge,
	 SIZE_T InboundReadLimit, SIZE_T OutboundReadLimit,
	 SIZE_T* pMaxInlineData)
{
	WV_QP_CREATE create;
	WV_QP_ATTRIBUTES attr;
	WV_DEVICE_ADDRESS *addr;
	DWORD opts;
	HRESULT hr;

	m_pInboundCq->AddRef();
	m_pOutboundCq->AddRef();

	RtlZeroMemory(&create, sizeof create);
	create.pSendCq = pOutboundCq->m_pWvCq;
	create.pReceiveCq = pInboundCq->m_pWvCq;
	create.Context = this;
	create.SendDepth = nOutboundEntries;
	create.SendSge = nOutboundSge;
	create.ReceiveDepth = nInboundEntries;
	create.ReceiveSge = nInboundSge;
	create.InitiatorDepth = OutboundReadLimit;
	create.ResponderResources = InboundReadLimit;
	create.QpType = WvQpTypeRc;
	
	hr = m_pConnector->m_pAdapter->m_pWvPd->CreateConnectQueuePair(&create, &m_pWvQp);
	if (FAILED(hr)) {
		return hr;
	}

	opts = WV_QP_ATTR_STATE | WV_QP_ATTR_PORT_NUMBER | WV_QP_ATTR_PKEY_INDEX;
	attr.QpState = WvQpStateInit;
	addr = &m_pConnector->m_pAdapter->m_DevAddress;
	attr.AddressVector.PortNumber = addr->PortNumber;
	hr = m_pConnector->m_pAdapter->m_pWvDevice->FindPkey(addr->PortNumber, addr->Pkey,
														 &attr.PkeyIndex);
	if (FAILED(hr)) {
		return hr;
	}

	hr = m_pWvQp->Modify(&attr, opts, NULL);
	if (FAILED(hr)) {
		return hr;
	}

	*pMaxInlineData = 0;
	return ND_SUCCESS;
}

CNDEndpoint::~CNDEndpoint()
{
	if (m_pWvQp != NULL) {
		m_pWvQp->Release();
	}
	if (m_pInboundCq != NULL) {
		m_pInboundCq->Release();
	}
	if (m_pOutboundCq != NULL) {
		m_pOutboundCq->Release();
	}
	m_pConnector->Release();
}

STDMETHODIMP CNDEndpoint::
QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
{
	if (riid != IID_IUnknown && riid != IID_INDEndpoint) {
		*ppvObj = NULL;
		return E_NOINTERFACE;
	}

	*ppvObj = this;
	AddRef();
	return ND_SUCCESS;
}

STDMETHODIMP_(ULONG) CNDEndpoint::
AddRef(void)
{
	return CNDBase::AddRef();
}

STDMETHODIMP_(ULONG) CNDEndpoint::
Release(void)
{
	return CNDBase::Release();
}

STDMETHODIMP CNDEndpoint::
Flush(void)
{
	return ND_SUCCESS;
}

STDMETHODIMP_(void) CNDEndpoint::
StartRequestBatch(void)
{
	// no-op
}

STDMETHODIMP_(void) CNDEndpoint::
SubmitRequestBatch(void)
{
	// no-op
}

STDMETHODIMP_(void) CNDEndpoint::
ConvertSgl(const ND_SGE* pSgl, SIZE_T nSge, WV_SGE* pWvSgl)
{
	SIZE_T i;

	for (i = 0; i < nSge; i++) {
		pWvSgl[i].pAddress = pSgl[i].pAddr;
		pWvSgl[i].Length = (UINT32) pSgl[i].Length;
		pWvSgl[i].Lkey = pSgl[i].hMr ? ((ND_MR *) pSgl[i].hMr)->Keys.Lkey : 0;
	}
}

STDMETHODIMP_(DWORD) CNDEndpoint::
ConvertSendFlags(DWORD Flags)
{
	DWORD opts = 0;

	if (!(Flags & ND_OP_FLAG_SILENT_SUCCESS)) {
		opts |= WV_SEND_SIGNALED;
	}
	if (Flags & ND_OP_FLAG_READ_FENCE) {
		opts |= WV_SEND_FENCE;
	}
	if (Flags & ND_OP_FLAG_SEND_AND_SOLICIT_EVENT) {
		opts |= WV_SEND_SOLICITED;
	}
	return opts;
}

STDMETHODIMP CNDEndpoint::
Send(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge, DWORD Flags)
{
	WV_SGE sgl[ND_MAX_SGE];
	DWORD opts;

	ConvertSgl(pSgl, nSge, sgl);
	opts = ConvertSendFlags(Flags) | (pSgl[0].hMr ? 0 : WV_SEND_INLINE);
	return m_pWvQp->Send((UINT64) pResult, sgl, nSge, opts, 0);
}

STDMETHODIMP CNDEndpoint::
SendAndInvalidate(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge,
				  const ND_MW_DESCRIPTOR* pRemoteMwDescriptor, DWORD Flags)
{
	// TODO: MW not supported
	return ND_NOT_SUPPORTED;
}

STDMETHODIMP CNDEndpoint::
Receive(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge)
{
	WV_SGE sgl[ND_MAX_SGE];

	ConvertSgl(pSgl, nSge, sgl);
	return m_pWvQp->PostReceive((UINT64) pResult, sgl, nSge);
}

STDMETHODIMP CNDEndpoint::
Bind(ND_RESULT* pResult, ND_MR_HANDLE hMr, INDMemoryWindow* pMw,
	 const void* pBuffer, SIZE_T BufferSize, DWORD Flags,
	 ND_MW_DESCRIPTOR* pMwDescriptor)
{
	// TODO: MW not supported
	return ND_NOT_SUPPORTED;
}

STDMETHODIMP CNDEndpoint::
Invalidate(ND_RESULT* pResult, INDMemoryWindow* pMw, DWORD Flags)
{
	// TODO: MW not supported
	return ND_NOT_SUPPORTED;
}

STDMETHODIMP CNDEndpoint::
Read(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge,
	 const ND_MW_DESCRIPTOR* pRemoteMwDescriptor, ULONGLONG Offset, DWORD Flags)
{
	WV_SGE sgl[ND_MAX_SGE];
	DWORD opts;

	ConvertSgl(pSgl, nSge, sgl);
	opts = ConvertSendFlags(Flags) | (pSgl[0].hMr ? 0 : WV_SEND_INLINE);
	return m_pWvQp->Read((UINT64) pResult, sgl, nSge, opts,
						 pRemoteMwDescriptor->Base + htonll(Offset),
						 pRemoteMwDescriptor->Token);
}

STDMETHODIMP CNDEndpoint::
Write(ND_RESULT* pResult, const ND_SGE* pSgl, SIZE_T nSge,
	  const ND_MW_DESCRIPTOR* pRemoteMwDescriptor, ULONGLONG Offset, DWORD Flags)
{
	WV_SGE sgl[ND_MAX_SGE];
	DWORD opts;

	ConvertSgl(pSgl, nSge, sgl);
	opts = ConvertSendFlags(Flags) | (pSgl[0].hMr ? 0 : WV_SEND_INLINE);
	return m_pWvQp->Write((UINT64) pResult, sgl, nSge, opts, 0,
						  pRemoteMwDescriptor->Base + htonll(Offset),
						  pRemoteMwDescriptor->Token);
}




More information about the ofw mailing list