[ofw] [ND 2/7] ND: adapter APIs

Sean Hefty sean.hefty at intel.com
Mon Apr 6 10:20:16 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_ADAPTER_H_
#define _ND_ADAPTER_H_

#include <ndspi.h>
#include "nd_base.h"
#include "nd_provider.h"
#include <dlist.h>


typedef struct _ND_MR
{
	DLIST_ENTRY			Entry;
	WV_MEMORY_KEYS		Keys;
	void				*Context;

}	ND_MR;


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

	// INDOverlapped methods
	STDMETHODIMP CancelOverlappedRequests();
	STDMETHODIMP GetOverlappedResult(OVERLAPPED *pOverlapped,
									 SIZE_T *pNumberOfBytesTransferred, BOOL bWait);

	// INDDevice methods
	STDMETHODIMP_(HANDLE) GetFileHandle();
	STDMETHODIMP Query(DWORD VersionRequested, ND_ADAPTER_INFO* pInfo,
					   SIZE_T* pBufferSize);
	STDMETHODIMP Control(DWORD IoControlCode,
						 const void* pInBuffer, SIZE_T InBufferSize,
						 void* pOutBuffer, SIZE_T OutBufferSize,
						 SIZE_T* pBytesReturned, OVERLAPPED* pOverlapped);
	STDMETHODIMP CreateCompletionQueue(SIZE_T nEntries, INDCompletionQueue** ppCq);
	STDMETHODIMP RegisterMemory(const void* pBuffer, SIZE_T BufferSize,
								OVERLAPPED* pOverlapped, ND_MR_HANDLE* phMr);
	STDMETHODIMP DeregisterMemory(ND_MR_HANDLE hMr, OVERLAPPED* pOverlapped);
	STDMETHODIMP CreateMemoryWindow(ND_RESULT* pInvalidateResult,
									INDMemoryWindow** ppMw);
	STDMETHODIMP CreateConnector(INDConnector** ppConnector);
	STDMETHODIMP Listen(SIZE_T Backlog, INT Protocol, USHORT Port,
						USHORT* pAssignedPort, INDListen** ppListen);

	CNDAdapter(CNDProvider *pProvider);
	~CNDAdapter();
	void Delete() {delete this;}
	static STDMETHODIMP
	CreateInstance(CNDProvider *pProvider, const struct sockaddr *pAddress,
				   SIZE_T AddressLength, INDAdapter** ppAdapter)
	{
		HRESULT hr;
		CNDAdapter *adapter;

		adapter = new CNDAdapter(pProvider);
		if (adapter == NULL) {
			hr = ND_NO_MEMORY;
			goto err1;
		}

		hr = adapter->Init(pAddress, AddressLength);
		if (FAILED(hr)) {
			goto err2;
		}

		*ppAdapter = adapter;
		return ND_SUCCESS;

	err2:
		adapter->Release();
	err1:
		*ppAdapter = NULL;
		return hr;
	}

	IWVProvider			*m_pWvProvider;
	IWVDevice			*m_pWvDevice;
	IWVProtectionDomain	*m_pWvPd;
	SOCKADDR_STORAGE	m_Address;
	WV_DEVICE_ADDRESS	m_DevAddress;

protected:
	CNDProvider			*m_pProvider;
	DLIST_ENTRY			m_MrList;
	CRITICAL_SECTION	m_Lock;

	STDMETHODIMP		Init(const struct sockaddr *pAddress, SIZE_T AddressLength);
	void				CleanupMr(ND_MR *pMr);
};

#endif // _ND_ADAPTER_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_adapter.h"
#include "nd_cq.h"
#include "nd_listen.h"
#include "nd_connect.h"
#include "nd_mw.h"
#include "nd_ep.h"


CNDAdapter::CNDAdapter(CNDProvider *pProvider)
{
	pProvider->AddRef();
	m_pProvider = pProvider;
	m_pWvProvider = NULL;
	m_pWvDevice = NULL;
	m_pWvPd = NULL;
	DListInit(&m_MrList);
	InitializeCriticalSection(&m_Lock);
}

STDMETHODIMP CNDAdapter::
Init(const struct sockaddr *pAddress, SIZE_T AddressLength)
{
	HRESULT hr;

	hr = WvGetObject(IID_IWVProvider, (LPVOID *) &m_pWvProvider);
	if (FAILED(hr)) {
		return hr;
	}

	hr = m_pWvProvider->TranslateAddress(pAddress, &m_DevAddress);
	if (FAILED(hr)) {
		return hr;
	}

	hr = m_pWvProvider->OpenDevice(m_DevAddress.DeviceGuid, &m_pWvDevice);
	if (FAILED(hr)) {
		return hr;
	}

	hr = m_pWvDevice->AllocateProtectionDomain(&m_pWvPd);
	if (FAILED(hr)) {
		return hr;
	}

	RtlCopyMemory(&m_Address, pAddress, AddressLength);
	return ND_SUCCESS;
}

CNDAdapter::~CNDAdapter(void)
{
	ND_MR	*mr;

	while (!DListEmpty(&m_MrList)) {
		mr = CONTAINING_RECORD(m_MrList.Next, ND_MR, Entry);
		DListRemove(&mr->Entry);
		m_pWvPd->DeregisterMemory(mr->Keys.Lkey, NULL);
		delete mr;
	}

	if (m_pWvPd != NULL) {
		m_pWvPd->Release();
	}
	if (m_pWvDevice != NULL) {
		m_pWvDevice->Release();
	}
	if (m_pWvProvider != NULL) {
		m_pWvProvider->Release();
	}
	m_pProvider->Release();
}

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

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

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

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

STDMETHODIMP CNDAdapter::
CancelOverlappedRequests(void)
{
	// TODO: add CancelOverlappedRequests to IWVProtectionDomain for MR
	return ND_SUCCESS;
}

STDMETHODIMP CNDAdapter::
GetOverlappedResult(OVERLAPPED *pOverlapped,
					SIZE_T *pNumberOfBytesTransferred, BOOL bWait)
{
	DLIST_ENTRY *entry;
	ND_MR *mr;
	HRESULT hr;

	::GetOverlappedResult(GetFileHandle(), pOverlapped,
						  (LPDWORD) pNumberOfBytesTransferred, bWait);
	hr = (HRESULT) pOverlapped->Internal;

	if (FAILED(hr)) {
		EnterCriticalSection(&m_Lock);
		for (entry = m_MrList.Next; entry != &m_MrList; entry = entry->Next) {
			mr = CONTAINING_RECORD(entry, ND_MR, Entry);
			if (mr->Context == pOverlapped) {
				DListRemove(entry);
				delete mr;
				break;
			}
		}
		LeaveCriticalSection(&m_Lock);
	}

	return hr;
}

STDMETHODIMP_(HANDLE) CNDAdapter::
GetFileHandle(void)
{
	return m_pWvProvider->GetFileHandle();
}

STDMETHODIMP CNDAdapter::
Query(DWORD VersionRequested, ND_ADAPTER_INFO* pInfo, SIZE_T* pBufferSize)
{
	WV_DEVICE_ATTRIBUTES attr;
	HRESULT hr;

	if (VersionRequested != 1) {
		return ND_NOT_SUPPORTED;
	}

	if (*pBufferSize < sizeof(ND_ADAPTER_INFO)) {
		hr = ND_BUFFER_OVERFLOW;
		goto out;
	}

	hr = m_pWvDevice->Query(&attr);
	if (FAILED(hr)) {
		goto out;
	}

	pInfo->VendorId					= attr.VendorId;
	pInfo->DeviceId					= attr.VendorPartId;
	pInfo->MaxInboundSge			= min(attr.MaxSge, ND_MAX_SGE);
	pInfo->MaxInboundRequests		= attr.MaxQpWr;
	pInfo->MaxInboundLength			= 1 << 31;
	pInfo->MaxOutboundSge			= min(attr.MaxSge, ND_MAX_SGE);
	pInfo->MaxOutboundRequests		= attr.MaxQpWr;
	pInfo->MaxOutboundLength		= 1 << 31;
	pInfo->MaxInlineData			= attr.MaxInlineSend;
	pInfo->MaxInboundReadLimit		= attr.MaxQpResponderResources;
	pInfo->MaxOutboundReadLimit		= attr.MaxQpInitiatorDepth;
	pInfo->MaxCqEntries				= attr.MaxCqEntries;
	pInfo->MaxRegistrationSize		= attr.MaxMrSize;
	pInfo->MaxWindowSize			= attr.MaxMrSize;
	pInfo->LargeRequestThreshold	= 0;
	pInfo->MaxCallerData			= ND_PRIVATE_DATA_SIZE;
	pInfo->MaxCalleeData			= ND_PRIVATE_DATA_SIZE;

out:
	*pBufferSize = sizeof(ND_ADAPTER_INFO);
	return hr;
}

STDMETHODIMP CNDAdapter::
Control(DWORD IoControlCode, const void* pInBuffer, SIZE_T InBufferSize,
		void* pOutBuffer, SIZE_T OutBufferSize, SIZE_T* pBytesReturned,
		OVERLAPPED* pOverlapped)
{
	return DeviceIoControl(GetFileHandle(), IoControlCode,
						   (LPVOID) pInBuffer, (DWORD) InBufferSize,
						   pOutBuffer, (DWORD) OutBufferSize,
						   (LPDWORD) pBytesReturned, pOverlapped) ?
						   ND_SUCCESS : HRESULT_FROM_WIN32(GetLastError());
}

STDMETHODIMP CNDAdapter::
CreateCompletionQueue(SIZE_T nEntries, INDCompletionQueue** ppCq)
{
	return CNDCompletionQueue::CreateInstance(this, nEntries, ppCq);
}

STDMETHODIMP CNDAdapter::
RegisterMemory(const void* pBuffer, SIZE_T BufferSize,
			   OVERLAPPED* pOverlapped, ND_MR_HANDLE* phMr)
{
	ND_MR *mr;
	HRESULT hr;
	DWORD flags;

	mr = new ND_MR;
	if (mr == NULL) {
		return ND_NO_MEMORY;
	}

	mr->Context = pOverlapped;
	EnterCriticalSection(&m_Lock);
	DListInsertHead(&mr->Entry, &m_MrList);
	LeaveCriticalSection(&m_Lock);

	// TODO: restrict access when MWs are implemented
	flags = WV_ACCESS_REMOTE_READ | WV_ACCESS_REMOTE_WRITE |
			WV_ACCESS_REMOTE_ATOMIC | WV_ACCESS_LOCAL_WRITE | WV_ACCESS_MW_BIND;
	hr = m_pWvPd->RegisterMemory(pBuffer, BufferSize, flags, pOverlapped, &mr->Keys);
	if (FAILED(hr)) {
		CleanupMr(mr);
	} else {
		*phMr = (ND_MR_HANDLE) mr;
	}

	return hr;
}

STDMETHODIMP CNDAdapter::
DeregisterMemory(ND_MR_HANDLE hMr, OVERLAPPED* pOverlapped)
{
	ND_MR *mr;
	HRESULT hr;

	mr = (ND_MR *) hMr;
	hr = m_pWvPd->DeregisterMemory(mr->Keys.Lkey, pOverlapped);
	if (SUCCEEDED(hr) || hr == WV_IO_PENDING) {
		CleanupMr(mr);
	}
	return hr;
}

void CNDAdapter::
CleanupMr(ND_MR *pMr)
{
	EnterCriticalSection(&m_Lock);
	DListRemove(&pMr->Entry);
	LeaveCriticalSection(&m_Lock);
	delete pMr;
}

STDMETHODIMP CNDAdapter::
CreateMemoryWindow(ND_RESULT* pInvalidateResult, INDMemoryWindow** ppMw)
{
	// TODO: do something with pInvalidateResult
	return CNDMemoryWindow::CreateInstance(this, ppMw);
}

STDMETHODIMP CNDAdapter::
CreateConnector(INDConnector** ppConnector)
{
	return CNDConnector::CreateInstance(this, ppConnector);
}

STDMETHODIMP CNDAdapter::
Listen(SIZE_T Backlog, INT Protocol, USHORT Port,
	   USHORT* pAssignedPort, INDListen** ppListen)
{
	return CNDListen::CreateInstance(this, Backlog, Protocol, Port,
									 pAssignedPort, ppListen);
}




More information about the ofw mailing list