[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