[ofw] [RFC] [PATCH 1/3] winmad kernel filter driver
Smith, Stan
stan.smith at intel.com
Wed Jul 2 09:11:05 PDT 2008
Does this interface handle MAD SAR, such that a read retrieves an entire
MAD?
Sean Hefty wrote:
> The WinMad driver is an upper filter driver for Infiniband HCAs. It
> uses the
> kernel IBAL MAD interfaces for access to qp 0 and 1. It exposes a
> simple file
> system interface to userspace for registering and deregistering MAD
> agents,
> and supports file read/write operations to send receive MADs.
>
> WinMad does not implement SMI or GSI interfaces. It only exposes a
> userspace
> interface to MAD services that is optimized for Windows.
>
> The driver supports asynchronous reads and writes using overlapped
> I/O, and
> handles PnP device removal events with active userspace clients.
>
> File writes results in sending MADs using a specified MAD agent.
> File read
> operations receive MADs across all registered agents for a single
> user.
>
> Signed-off-by: Sean Hefty <sean.hefty at intel.com>
> ---
> The following source code implements the WinMad driver. Additional
> files needed
> to build and install the driver are not shown, but will be available
> once the
> files are checked into an SVN branch.
>
> /*
> * Copyright (c) 2008 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 AWV
> * 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 <ntddk.h>
> #include <wdf.h>
> #include <wdmsec.h>
> #include <ntstatus.h>
> #include <initguid.h>
>
> #include "wm_ioctl.h"
> #include "wm_driver.h"
> #include "wm_provider.h"
> #include "wm_reg.h"
>
> WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WM_IB_DEVICE, WmIbDeviceGetContext)
> WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WM_PROVIDER, WmProviderGetContext)
>
> WDFDEVICE ControlDevice;
> static LIST_ENTRY DevList;
> static LIST_ENTRY ProvList;
> static KGUARDED_MUTEX Lock;
>
> static EVT_WDF_DRIVER_DEVICE_ADD WmIbDeviceAdd;
> static EVT_WDF_OBJECT_CONTEXT_CLEANUP WmIbDeviceCleanup;
> static EVT_WDF_DEVICE_D0_ENTRY
WmPowerD0Entry;
> static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL WmIoDeviceControl;
> static EVT_WDF_IO_QUEUE_IO_READ
WmIoRead;
> static EVT_WDF_IO_QUEUE_IO_WRITE WmIoWrite;
> static EVT_WDF_DEVICE_FILE_CREATE WmFileCreate;
> static EVT_WDF_FILE_CLEANUP
WmFileCleanup;
> static EVT_WDF_FILE_CLOSE
WmFileClose;
>
> WM_IB_DEVICE *WmIbDeviceGet(UINT64 Guid)
> {
> WM_IB_DEVICE *cur_dev, *dev = NULL;
> LIST_ENTRY *entry;
>
> KeAcquireGuardedMutex(&Lock);
> for (entry = DevList.Flink; entry != &DevList; entry =
entry->Flink)
> { cur_dev = CONTAINING_RECORD(entry, WM_IB_DEVICE,
Entry);
> if (cur_dev->Guid == Guid) {
> InterlockedIncrement(&cur_dev->Ref);
> dev = cur_dev;
> break;
> }
> }
> KeReleaseGuardedMutex(&Lock);
> return dev;
> }
>
> void WmIbDevicePut(WM_IB_DEVICE *pDevice)
> {
> if (InterlockedDecrement(&pDevice->Ref) == 0) {
> KeSetEvent(&pDevice->Event, 0, FALSE);
> }
> }
>
> static VOID WmIoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request,
> size_t OutLen,
size_t InLen, ULONG IoControlCode)
> {
> WDFFILEOBJECT file;
> WM_PROVIDER *prov;
> UNREFERENCED_PARAMETER(OutLen);
> UNREFERENCED_PARAMETER(InLen);
> UNREFERENCED_PARAMETER(Queue);
>
> file = WdfRequestGetFileObject(Request);
> prov = WmProviderGetContext(file);
>
> switch (IoControlCode) {
> case WM_IOCTL_REGISTER:
> WmRegister(prov, Request);
> break;
> case WM_IOCTL_DEREGISTER:
> WmDeregister(prov, Request);
> break;
> case WM_IOCTL_CANCEL:
> // TODO!!!
> WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
> break;
> default:
> WdfRequestComplete(Request, STATUS_PROCEDURE_NOT_FOUND);
> break;
> }
> }
>
> static VOID WmIoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t
> Length) {
> WDFFILEOBJECT file;
> WM_PROVIDER *prov;
> UNREFERENCED_PARAMETER(Queue);
>
> file = WdfRequestGetFileObject(Request);
> prov = WmProviderGetContext(file);
>
> WmProviderRead(prov, Request);
> }
>
> static VOID WmIoWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t
> Length) {
> WDFFILEOBJECT file;
> WM_PROVIDER *prov;
> UNREFERENCED_PARAMETER(Queue);
>
> file = WdfRequestGetFileObject(Request);
> prov = WmProviderGetContext(file);
>
> WmProviderWrite(prov, Request);
> }
>
> static VOID WmFileCreate(WDFDEVICE Device, WDFREQUEST Request,
> WDFFILEOBJECT
FileObject)
> {
> WM_PROVIDER *prov = WmProviderGetContext(FileObject);
> UNREFERENCED_PARAMETER(Device);
>
> WmProviderInit(prov);
> KeAcquireGuardedMutex(&Lock);
> InsertHeadList(&ProvList, &prov->Entry);
> KeReleaseGuardedMutex(&Lock);
> WdfRequestComplete(Request, STATUS_SUCCESS);
> }
>
> static VOID WmFileCleanup(WDFFILEOBJECT FileObject)
> {
> WM_PROVIDER *prov = WmProviderGetContext(FileObject);
>
> KeAcquireGuardedMutex(&Lock);
> RemoveEntryList(&prov->Entry);
> KeReleaseGuardedMutex(&Lock);
> WmProviderCleanup(prov);
> }
>
> static VOID WmFileClose(WDFFILEOBJECT FileObject)
> {
> UNREFERENCED_PARAMETER(FileObject);
> }
>
> static VOID WmCreateControlDevice(WDFDRIVER Driver)
> {
> PWDFDEVICE_INIT pinit;
> WDF_FILEOBJECT_CONFIG fileconfig;
> WDF_OBJECT_ATTRIBUTES attr;
> WDF_IO_QUEUE_CONFIG ioconfig;
> NTSTATUS status;
> WDFQUEUE queue;
> DECLARE_CONST_UNICODE_STRING(name, L"\\Device\\WinMad");
> DECLARE_CONST_UNICODE_STRING(symlink, L"\\DosDevices\\WinMad");
>
> pinit = WdfControlDeviceInitAllocate(Driver,
>
> &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R);
> if (pinit == NULL) {
> return;
> }
>
> WdfDeviceInitSetExclusive(pinit, FALSE);
> status = WdfDeviceInitAssignName(pinit, &name);
> if (!NT_SUCCESS(status)) {
> goto err1;
> }
>
> WDF_FILEOBJECT_CONFIG_INIT(&fileconfig, WmFileCreate,
WmFileClose,
>
WmFileCleanup);
> WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, WM_PROVIDER);
> WdfDeviceInitSetFileObjectConfig(pinit, &fileconfig, &attr);
>
> WDF_OBJECT_ATTRIBUTES_INIT(&attr);
> status = WdfDeviceCreate(&pinit, &attr, &ControlDevice);
> if (!NT_SUCCESS(status)) {
> goto err1;
> }
>
> status = WdfDeviceCreateSymbolicLink(ControlDevice, &symlink);
> if (!NT_SUCCESS(status)) {
> goto err2;
> }
>
> WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioconfig,
> WdfIoQueueDispatchParallel); ioconfig.EvtIoDeviceControl =
> WmIoDeviceControl; ioconfig.EvtIoRead = WmIoRead;
> ioconfig.EvtIoWrite = WmIoWrite;
> status = WdfIoQueueCreate(ControlDevice, &ioconfig,
>
WDF_NO_OBJECT_ATTRIBUTES, &queue);
> if (!NT_SUCCESS(status)) {
> goto err2;
> }
>
> WdfControlFinishInitializing(ControlDevice);
> return;
>
> err2:
> WdfObjectDelete(ControlDevice);
> return;
> err1:
> WdfDeviceInitFree(pinit);
> }
>
> static NTSTATUS WmInitIbPorts(WM_IB_DEVICE *pDevice)
> {
> NTSTATUS status;
> ib_api_status_t ib_status;
> ib_ca_attr_t *attr;
> UINT32 size;
> UINT8 i;
>
> size = 0;
> ib_status = pDevice->IbInterface.query_ca(pDevice->hDevice,
NULL,
> &size); if (ib_status != IB_INSUFFICIENT_MEMORY) {
> return STATUS_UNSUCCESSFUL;
> }
>
> attr = ExAllocatePoolWithTag(PagedPool, size, 'acmw');
> if (attr == NULL) {
> return STATUS_NO_MEMORY;
> }
>
> ib_status = pDevice->IbInterface.query_ca(pDevice->hDevice,
attr,
> &size); if (ib_status != IB_SUCCESS) {
> status = STATUS_UNSUCCESSFUL;
> goto out;
> }
>
> size = sizeof(WM_IB_PORT) * attr->num_ports;
> pDevice->pPortArray = ExAllocatePoolWithTag(PagedPool, size,
'pimw');
> if (pDevice->pPortArray == NULL) {
> status = STATUS_NO_MEMORY;
> goto out;
> }
>
> for (i = 0; i < attr->num_ports; i++) {
> pDevice->pPortArray[i].Guid =
attr->p_port_attr[i].port_guid;
> }
> pDevice->PortCount = attr->num_ports;
>
> status = STATUS_SUCCESS;
> out:
> ExFreePool(attr);
> return status;
> }
>
> static NTSTATUS WmInitIbDevice(WDFDEVICE Device, WM_IB_DEVICE
> *pDevice) {
> NTSTATUS status;
> ib_api_status_t ib_status;
>
> status = WdfFdoQueryForInterface(Device, &GUID_IB_AL_INTERFACE,
>
(PINTERFACE) &pDevice->IbInterface,
>
sizeof(pDevice->IbInterface),
>
AL_INTERFACE_VERSION, NULL);
> if (!NT_SUCCESS(status)) {
> return status;
> }
>
> ib_status = pDevice->IbInterface.open_al(&pDevice->hIbal);
> if (ib_status != IB_SUCCESS) {
> goto err1;
> }
>
> ib_status = pDevice->IbInterface.open_ca(pDevice->hIbal,
>
pDevice->Guid, NULL, pDevice,
> &pDevice->hDevice);
> if (ib_status != IB_SUCCESS) {
> goto err2;
> }
>
> ib_status = pDevice->IbInterface.alloc_pd(pDevice->hDevice,
>
IB_PDT_ALIAS, pDevice, &pDevice->hPd);
> if (ib_status != IB_SUCCESS) {
> goto err3;
> }
>
> status = WmInitIbPorts(pDevice);
> if (!NT_SUCCESS(status)) {
> goto err4;
> }
>
> return STATUS_SUCCESS;
>
> err4:
> pDevice->IbInterface.dealloc_pd(pDevice->hPd, NULL);
> err3:
> pDevice->IbInterface.close_ca(pDevice->hDevice, NULL);
> err2:
> pDevice->IbInterface.close_al(pDevice->hIbal);
> pDevice->hIbal = NULL;
> err1:
>
pDevice->IbInterface.wdm.InterfaceDereference(pDevice->IbInterface.wdm.C
ontext);
> return STATUS_UNSUCCESSFUL;
> }
>
> static NTSTATUS WmPowerD0Entry(WDFDEVICE Device,
> WDF_POWER_DEVICE_STATE PreviousState) {
> WM_IB_DEVICE *dev;
> BOOLEAN create;
> NTSTATUS status;
>
> dev = WmIbDeviceGetContext(Device);
> if (dev->hIbal != NULL) {
> return STATUS_SUCCESS;
> }
>
> status = WdfFdoQueryForInterface(Device,
&GUID_RDMA_INTERFACE_VERBS,
>
(PINTERFACE) &dev->VerbsInterface,
>
sizeof(dev->VerbsInterface), VerbsVersion(2,
> 0),
>
NULL);
> if (!NT_SUCCESS(status)) {
> return status;
> }
>
> dev->Guid = dev->VerbsInterface.Verbs.guid;
>
dev->IbInterface.wdm.InterfaceDereference(dev->IbInterface.wdm.Context);
>
> status = WmInitIbDevice(Device, dev);
> if (!NT_SUCCESS(status)) {
> return status;
> }
>
> KeAcquireGuardedMutex(&Lock);
> create = IsListEmpty(&DevList);
> InsertHeadList(&DevList, &dev->Entry);
> KeReleaseGuardedMutex(&Lock);
>
> if (create) {
> WmCreateControlDevice(WdfGetDriver());
> }
>
> return STATUS_SUCCESS;
> }
>
> static NTSTATUS WmIbDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT
> DeviceInit) {
> WDF_OBJECT_ATTRIBUTES attr;
> WDF_PNPPOWER_EVENT_CALLBACKS power;
> WDFDEVICE dev;
> WM_IB_DEVICE *pdev;
> NTSTATUS status;
>
> WdfFdoInitSetFilter(DeviceInit);
>
> WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, WM_IB_DEVICE);
> attr.EvtCleanupCallback = WmIbDeviceCleanup;
>
> WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&power);
> power.EvtDeviceD0Entry = WmPowerD0Entry;
> WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &power);
>
> status = WdfDeviceCreate(&DeviceInit, &attr, &dev);
> if (!NT_SUCCESS(status)) {
> return status;
> }
>
> pdev = WmIbDeviceGetContext(dev);
> RtlZeroMemory(pdev, sizeof *pdev);
> pdev->Ref = 1;
> KeInitializeEvent(&pdev->Event, NotificationEvent, FALSE);
>
> return STATUS_SUCCESS;
> }
>
> static VOID WmIbDeviceCleanup(WDFDEVICE Device)
> {
> WM_PROVIDER *prov;
> WM_IB_DEVICE *pdev;
> WM_REGISTRATION *reg;
> LIST_ENTRY *entry;
> BOOLEAN destroy;
> WDFDEVICE ctrldev;
>
> pdev = WmIbDeviceGetContext(Device);
> if (pdev->hIbal == NULL) {
> return;
> }
>
> KeAcquireGuardedMutex(&Lock);
> RemoveEntryList(&pdev->Entry);
> destroy = IsListEmpty(&DevList);
> ctrldev = ControlDevice;
>
> for (entry = ProvList.Flink; entry != &ProvList; entry =
> entry->Flink) { prov = CONTAINING_RECORD(entry,
WM_PROVIDER, Entry);
> WmProviderRemoveHandler(prov, pdev);
> }
>
> KeReleaseGuardedMutex(&Lock);
>
> if (InterlockedDecrement(&pdev->Ref) > 0) {
> KeWaitForSingleObject(&pdev->Event, Executive,
KernelMode, FALSE,
> NULL); }
>
> ExFreePool(pdev->pPortArray);
> pdev->IbInterface.dealloc_pd(pdev->hPd, NULL);
> pdev->IbInterface.close_ca(pdev->hDevice, NULL);
> pdev->IbInterface.close_al(pdev->hIbal);
>
pdev->IbInterface.wdm.InterfaceDereference(pdev->IbInterface.wdm.Context
);
>
> if (destroy) {
> WdfObjectDelete(ctrldev);
> }
> }
>
> NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING
> RegistryPath) {
> WDF_DRIVER_CONFIG config;
> NTSTATUS status;
> WDFDRIVER driv;
>
> InitializeListHead(&DevList);
> InitializeListHead(&ProvList);
> KeInitializeGuardedMutex(&Lock);
>
> WDF_DRIVER_CONFIG_INIT(&config, WmIbDeviceAdd);
> status = WdfDriverCreate(DriverObject, RegistryPath,
>
WDF_NO_OBJECT_ATTRIBUTES, &config, &driv);
> if (!NT_SUCCESS(status)) {
> return status;
> }
>
> return STATUS_SUCCESS;
> }
> /*
> * Copyright (c) 2008 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 AWV
> * 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 _WM_DRIVER_H_
> #define _WM_DRIVER_H_
>
> #include <ntddk.h>
> #include <wdm.h>
> #include <wdf.h>
>
> #include <rdma\verbs.h>
> #include <iba\ib_al_ifc.h>
>
> extern WDFDEVICE ControlDevice;
>
> typedef struct _WM_IB_PORT
> {
> UINT64 Guid;
>
> } WM_IB_PORT;
>
> typedef struct _WM_IB_DEVICE
> {
> LIST_ENTRY Entry;
> LONG Ref;
> KEVENT Event;
> UINT64 Guid; //
Network byte order
> union
> {
> RDMA_INTERFACE_VERBS VerbsInterface;
> ib_al_ifc_t IbInterface;
> };
> ib_al_handle_t hIbal;
> ib_ca_handle_t hDevice;
> ib_pd_handle_t hPd;
> int PortCount;
> WM_IB_PORT *pPortArray;
>
> } WM_IB_DEVICE;
>
> WM_IB_DEVICE *WmIbDeviceGet(UINT64 Guid);
> void WmIbDevicePut(WM_IB_DEVICE *pDevice);
>
> #endif // _WM_DRIVER_H_
> /*
> * Copyright (c) 2008 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 AWV
> * 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 "index_list.c"
> #include "wm_driver.h"
> #include "wm_ioctl.h"
> #include "wm_provider.h"
> #include "wm_reg.h"
>
> void WmProviderGet(WM_PROVIDER *pProvider)
> {
> InterlockedIncrement(&pProvider->Ref);
> }
>
> void WmProviderPut(WM_PROVIDER *pProvider)
> {
> if (InterlockedDecrement(&pProvider->Ref) == 0) {
> KeSetEvent(&pProvider->Event, 0, FALSE);
> }
> }
>
> NTSTATUS WmProviderInit(WM_PROVIDER *pProvider)
> {
> WDF_IO_QUEUE_CONFIG config;
> NTSTATUS status;
>
> IndexListInit(&pProvider->RegIndex);
> pProvider->MadHead = NULL;
> pProvider->MadTail = NULL;
>
> KeInitializeGuardedMutex(&pProvider->Lock);
> pProvider->Ref = 1;
> KeInitializeEvent(&pProvider->Event, NotificationEvent, FALSE);
>
> pProvider->Pending = 0;
> pProvider->Active = 0;
> KeInitializeEvent(&pProvider->SharedEvent, NotificationEvent,
FALSE);
> pProvider->Exclusive = 0;
> KeInitializeEvent(&pProvider->ExclusiveEvent,
SynchronizationEvent,
> FALSE);
>
> WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);
> status = WdfIoQueueCreate(ControlDevice, &config,
>
WDF_NO_OBJECT_ATTRIBUTES, &pProvider->ReadQueue);
> return status;
> }
>
> static void WmInsertMad(WM_PROVIDER *pProvider, ib_mad_element_t
> *pMad) {
> if (pProvider->MadHead == NULL) {
> pProvider->MadHead = pMad;
> } else {
> pProvider->MadTail->p_next = pMad;
> }
> pProvider->MadTail = pMad;
> }
>
> static ib_mad_element_t *WmRemoveMad(WM_PROVIDER *pProvider)
> {
> ib_mad_element_t *mad;
>
> mad = pProvider->MadHead;
> if (mad != NULL) {
> pProvider->MadHead = (ib_mad_element_t *) mad->p_next;
> mad->p_next = NULL;
> }
>
> return mad;
> }
>
> void WmProviderFlushReceives(WM_PROVIDER *pProvider, WM_REGISTRATION
> *pRegistration) {
> ib_mad_element_t *mad, *next, *list;
>
> WdfObjectAcquireLock(pProvider->ReadQueue);
> list = pProvider->MadHead;
> pProvider->MadHead = NULL;
>
> for (mad = list; mad != NULL; mad = next) {
> next = mad->p_next;
> mad->p_next = NULL;
>
> if (mad->context1 == pRegistration) {
>
pRegistration->pDevice->IbInterface.put_mad(mad);
> } else {
> WmInsertMad(pProvider, mad);
> }
> }
> WdfObjectReleaseLock(pProvider->ReadQueue);
> }
>
> void WmProviderCleanup(WM_PROVIDER *pProvider)
> {
> WM_REGISTRATION *reg;
>
> while ((reg = IndexListRemoveHead(&pProvider->RegIndex)) !=
NULL) {
> RemoveEntryList(®->Entry);
> WmRegFree(reg);
> }
>
> if (InterlockedDecrement(&pProvider->Ref) > 0) {
> KeWaitForSingleObject(&pProvider->Event, Executive,
KernelMode,
> FALSE, NULL); }
>
> WdfIoQueuePurgeSynchronously(pProvider->ReadQueue);
> WdfObjectDelete(pProvider->ReadQueue);
>
> IndexListDestroy(&pProvider->RegIndex);
> }
>
> // See comment above WmProviderRemoveHandler.
> static void WmProviderLockRemove(WM_PROVIDER *pProvider)
> {
> KeAcquireGuardedMutex(&pProvider->Lock);
> pProvider->Exclusive++;
> KeClearEvent(&pProvider->SharedEvent);
> while (pProvider->Active > 0) {
> KeReleaseGuardedMutex(&pProvider->Lock);
> KeWaitForSingleObject(&pProvider->ExclusiveEvent,
Executive,
> KernelMode,
FALSE, NULL);
> KeAcquireGuardedMutex(&pProvider->Lock);
> }
> pProvider->Active++;
> KeReleaseGuardedMutex(&pProvider->Lock);
> }
>
> // See comment above WmProviderRemoveHandler.
> static void WmProviderUnlockRemove(WM_PROVIDER *pProvider)
> {
> KeAcquireGuardedMutex(&pProvider->Lock);
> pProvider->Exclusive--;
> pProvider->Active--;
> if (pProvider->Exclusive > 0) {
> KeSetEvent(&pProvider->ExclusiveEvent, 0, FALSE);
> } else if (pProvider->Pending > 0) {
> KeSetEvent(&pProvider->SharedEvent, 0, FALSE);
> }
> KeReleaseGuardedMutex(&pProvider->Lock);
> }
>
> /*
> * Must hold pProvider->Lock. Function may release and re-acquire.
> * See comment above WmProviderRemoveHandler.
> */
> void WmProviderDisableRemove(WM_PROVIDER *pProvider)
> {
> while (pProvider->Exclusive > 0) {
> pProvider->Pending++;
> KeReleaseGuardedMutex(&pProvider->Lock);
> KeWaitForSingleObject(&pProvider->SharedEvent,
Executive,
> KernelMode,
FALSE, NULL);
> KeAcquireGuardedMutex(&pProvider->Lock);
> pProvider->Pending--;
> }
> InterlockedIncrement(&pProvider->Active);
> }
>
> /*
> * No need to hold pProvider->Lock when releasing.
> * See comment above WmProviderRemoveHandler.
> */
> void WmProviderEnableRemove(WM_PROVIDER *pProvider)
> {
> InterlockedDecrement(&pProvider->Active);
> if (pProvider->Exclusive > 0) {
> KeSetEvent(&pProvider->ExclusiveEvent, 0, FALSE);
> }
> }
>
> /*
> * The remove handler blocks all other threads executing through this
> * provider until the remove has been processed. Because device
> removal is
> * rare, we want a simple, optimized code path for all calls that
> access
> * the underlying hardware device, making use of any locks that we
> would
> * have to acquire anyway. The locking for exclusive access can be
> * as ugly and slow as needed.
> */
> void WmProviderRemoveHandler(WM_PROVIDER *pProvider, WM_IB_DEVICE
> *pDevice) {
> WM_REGISTRATION *reg;
> SIZE_T i;
>
> WmProviderLockRemove(pProvider);
> IndexListForEach(&pProvider->RegIndex, i) {
> reg = IndexListAt(&pProvider->RegIndex, i);
> if (reg->pDevice == pDevice) {
> WmRegRemoveHandler(reg);
> }
> }
> WmProviderUnlockRemove(pProvider);
> }
>
> static NTSTATUS WmCopyRead(WM_PROVIDER *pProvider, WM_IO_MAD *pIoMad,
> ib_mad_element_t
*pMad, size_t *pLen)
> {
> WM_REGISTRATION *reg;
>
> reg = (WM_REGISTRATION *) pMad->context1;
> pIoMad->Id = reg->Id;
>
> pIoMad->Status = pMad->status;
> pIoMad->Timeout = pMad->timeout_ms;
> pIoMad->Retries = pMad->retry_cnt;
> pIoMad->Length = pMad->size;
>
> pIoMad->Address.Qpn = pMad->remote_qp;
> pIoMad->Address.Qkey = pMad->remote_qkey;
> pIoMad->Address.PkeyIndex = pMad->pkey_index;
>
> if ((pIoMad->Address.GrhValid = (UINT16) pMad->grh_valid)) {
> pIoMad->Address.VersionClassFlow =
pMad->p_grh->ver_class_flow;
> pIoMad->Address.HopLimit = pMad->p_grh->hop_limit;
> pIoMad->Address.GidIndex = 0; // TODO: update IBAL to
use SGID index
> RtlCopyMemory(pIoMad->Address.Gid,
pMad->p_grh->dest_gid.raw, 16);
> }
>
> pIoMad->Address.Lid = pMad->remote_lid;
> pIoMad->Address.ServiceLevel = pMad->remote_sl;
> pIoMad->Address.PathBits = pMad->path_bits;
> pIoMad->Address.StaticRate = 0;
> pIoMad->Address.Reserved = 0;
>
> if (*pLen >= sizeof(WM_IO_MAD) + pMad->size) {
> RtlCopyMemory(pIoMad + 1, pMad->p_mad_buf, pMad->size);
> *pLen = sizeof(WM_IO_MAD) + pMad->size;
> return STATUS_SUCCESS;
> } else {
> *pLen = sizeof(WM_IO_MAD);
> return STATUS_MORE_ENTRIES;
> }
> }
>
> void WmProviderRead(WM_PROVIDER *pProvider, WDFREQUEST Request)
> {
> WM_REGISTRATION *reg;
> NTSTATUS status;
> WM_IO_MAD *wmad;
> size_t outlen, len = 0;
>
> status = WdfRequestRetrieveOutputBuffer(Request,
sizeof(WM_IO_MAD),
> &wmad, &outlen); if (!NT_SUCCESS(status)) {
> goto out;
> }
>
> WdfObjectAcquireLock(pProvider->ReadQueue);
> if (pProvider->MadHead == NULL) {
> status = WdfRequestForwardToIoQueue(Request,
pProvider->ReadQueue);
> WdfObjectReleaseLock(pProvider->ReadQueue);
> if (NT_SUCCESS(status)) {
> return;
> }
> goto out;
> }
>
> len = outlen;
> status = WmCopyRead(pProvider, wmad, pProvider->MadHead, &len);
> if (NT_SUCCESS(status)) {
> reg = (WM_REGISTRATION *) pProvider->MadHead->context1;
>
reg->pDevice->IbInterface.put_mad(WmRemoveMad(pProvider));
> }
> WdfObjectReleaseLock(pProvider->ReadQueue);
>
> out:
> WdfRequestCompleteWithInformation(Request, status, len);
> }
>
> static NTSTATUS WmSendMad(WM_REGISTRATION *pRegistration, WM_IO_MAD
> *pIoMad, UINT32 size) {
> ib_al_ifc_t *pifc;
> NTSTATUS status;
> ib_mad_element_t *mad;
> ib_api_status_t ib_status;
>
> pifc = &pRegistration->pDevice->IbInterface;
> ib_status = pifc->get_mad(pRegistration->hMadPool, size, &mad);
> if (ib_status != IB_SUCCESS) {
> return STATUS_NO_MEMORY;
> }
>
> mad->context1 = pRegistration;
> RtlCopyMemory(mad->p_mad_buf, pIoMad + 1, size);
> mad->size = size;
> mad->remote_qp = pIoMad->Address.Qpn;
> mad->remote_qkey = pIoMad->Address.Qkey;
> mad->resp_expected = (pIoMad->Timeout > 0);
> mad->timeout_ms = pIoMad->Timeout;
> mad->retry_cnt = pIoMad->Retries;
>
> if ((mad->grh_valid = pIoMad->Address.GrhValid)) {
> mad->p_grh->ver_class_flow =
pIoMad->Address.VersionClassFlow;
> mad->p_grh->hop_limit = pIoMad->Address.HopLimit;
> // TODO: update IBAL to use SGID index
> // mad->p_grh->src_gid_index = pIoMad->Address.GidIndex;
> RtlCopyMemory(mad->p_grh->dest_gid.raw,
pIoMad->Address.Gid, 16);
> }
>
> mad->remote_lid = pIoMad->Address.Lid;
> mad->remote_sl = pIoMad->Address.ServiceLevel;
> mad->pkey_index = pIoMad->Address.PkeyIndex;
> mad->path_bits = pIoMad->Address.PathBits;
>
> ib_status = pifc->send_mad(pRegistration->hService, mad, NULL);
> if (ib_status != IB_SUCCESS) {
> status = STATUS_UNSUCCESSFUL;
> goto err;
> }
>
> return STATUS_SUCCESS;
>
> err:
> pRegistration->pDevice->IbInterface.put_mad(mad);
> return status;
> }
>
> void WmProviderWrite(WM_PROVIDER *pProvider, WDFREQUEST Request)
> {
> WM_REGISTRATION *reg;
> NTSTATUS status;
> WM_IO_MAD *wmad;
> size_t inlen;
>
> status = WdfRequestRetrieveInputBuffer(Request,
sizeof(WM_IO_MAD) +
>
256, &wmad, &inlen);
> if (!NT_SUCCESS(status)) {
> goto out;
> }
>
> reg = WmRegAcquire(pProvider, wmad->Id);
> if (reg == NULL) {
> status = STATUS_NOT_FOUND;
> goto out;
> }
>
> status = WmSendMad(reg, wmad, (UINT32) (inlen -
sizeof(WM_IO_MAD)));
> WmRegRelease(reg);
>
> out:
> WdfRequestComplete(Request, status);
> }
>
> void WmReceiveHandler(ib_mad_svc_handle_t hService, void *Context,
> ib_mad_element_t *pMad)
> {
> WM_REGISTRATION *reg;
> WM_PROVIDER *prov = Context;
> WDFREQUEST request;
> NTSTATUS status;
> WM_IO_MAD *wmad;
> size_t len = 0;
>
> UNREFERENCED_PARAMETER(hService);
>
> WdfObjectAcquireLock(prov->ReadQueue);
> status = WdfIoQueueRetrieveNextRequest(prov->ReadQueue,
&request);
> if (!NT_SUCCESS(status)) {
> WmInsertMad(prov, pMad);
> WdfObjectReleaseLock(prov->ReadQueue);
> return;
> }
>
> status = WdfRequestRetrieveOutputBuffer(request,
sizeof(WM_IO_MAD),
> &wmad, &len); if (!NT_SUCCESS(status)) {
> reg = (WM_REGISTRATION *) pMad->context1;
> reg->pDevice->IbInterface.put_mad(pMad);
> goto out;
> }
>
> status = WmCopyRead(prov, wmad, pMad, &len);
> if (NT_SUCCESS(status)) {
> reg = (WM_REGISTRATION *) pMad->context1;
> reg->pDevice->IbInterface.put_mad(pMad);
> } else {
> WmInsertMad(prov, pMad);
> }
> WdfObjectReleaseLock(prov->ReadQueue);
>
> out:
> WdfRequestCompleteWithInformation(request, status, len);
> }
>
> void WmSendHandler(ib_mad_svc_handle_t hService, void *Context,
> ib_mad_element_t *pMad)
> {
> WM_PROVIDER *prov = Context;
> UNREFERENCED_PARAMETER(hService);
> pMad;
> }
>
> void WmProviderCancel(WM_PROVIDER *pProvider, WDFREQUEST Request)
> {
> WDFREQUEST request;
> NTSTATUS status;
>
> WdfObjectAcquireLock(pProvider->ReadQueue);
> status = WdfIoQueueRetrieveNextRequest(pProvider->ReadQueue,
> &request);
>
> while (NT_SUCCESS(status)) {
> WdfRequestComplete(request, STATUS_CANCELLED);
> status =
WdfIoQueueRetrieveNextRequest(pProvider->ReadQueue,
> &request); }
> WdfObjectReleaseLock(pProvider->ReadQueue);
>
> WdfRequestComplete(Request, status);
> }
> /*
> * Copyright (c) 2008 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 AWV
> * 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 _WM_PROVIDER_H_
> #define _WM_PROVIDER_H_
>
> #include <ntddk.h>
> #include <wdf.h>
> #include <wdm.h>
>
> #include <iba\ib_al.h>
> #include "wm_driver.h"
> #include "index_list.h"
>
> typedef struct _WM_PROVIDER
> {
> LIST_ENTRY Entry;
> INDEX_LIST RegIndex;
> WDFQUEUE ReadQueue;
>
> ib_mad_element_t *MadHead;
> ib_mad_element_t *MadTail;
>
> KGUARDED_MUTEX Lock;
> LONG Ref;
> KEVENT Event;
> LONG Pending;
> LONG Active;
> KEVENT SharedEvent;
> LONG Exclusive;
> KEVENT ExclusiveEvent;
>
> } WM_PROVIDER;
>
> void WmProviderGet(WM_PROVIDER *pProvider);
> void WmProviderPut(WM_PROVIDER *pProvider);
> NTSTATUS WmProviderInit(WM_PROVIDER *pProvider);
> void WmProviderCleanup(WM_PROVIDER *pProvider);
>
> void WmProviderRemoveHandler(WM_PROVIDER *pProvider, WM_IB_DEVICE
> *pDevice);
> void WmProviderDisableRemove(WM_PROVIDER *pProvider);
> void WmProviderEnableRemove(WM_PROVIDER *pProvider);
>
> void WmProviderRead(WM_PROVIDER *pProvider, WDFREQUEST Request);
> void WmProviderWrite(WM_PROVIDER *pProvider, WDFREQUEST Request);
> void WmReceiveHandler(ib_mad_svc_handle_t hService, void *Context,
> ib_mad_element_t *pMad);
> void WmSendHandler(ib_mad_svc_handle_t hService, void *Context,
> ib_mad_element_t *pMad);
> void WmProviderFlushReceives(WM_PROVIDER *pProvider,
> struct
_WM_REGISTRATION *pRegistration);
>
> #endif // _WM_PROVIDER_H_
> /*
> * Copyright (c) 2008 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 AWV
> * 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 <iba\ib_al.h>
> #include "wm_driver.h"
> #include "wm_reg.h"
> #include "wm_ioctl.h"
>
> WM_REGISTRATION *WmRegAcquire(WM_PROVIDER *pProvider, UINT64 Id)
> {
> WM_REGISTRATION *reg;
>
> KeAcquireGuardedMutex(&pProvider->Lock);
> WmProviderDisableRemove(pProvider);
> reg = IndexListAt(&pProvider->RegIndex, (SIZE_T) Id);
> if (reg != NULL && reg->pDevice != NULL) {
> InterlockedIncrement(®->Ref);
> } else {
> reg = NULL;
> WmProviderEnableRemove(pProvider);
> }
> KeReleaseGuardedMutex(&pProvider->Lock);
>
> return reg;
> }
>
> void WmRegRelease(WM_REGISTRATION *pRegistration)
> {
> WmProviderEnableRemove(pRegistration->pProvider);
> InterlockedDecrement(&pRegistration->Ref);
> }
>
> static WM_REGISTRATION *WmRegAlloc(WM_PROVIDER *pProvider)
> {
> WM_REGISTRATION *reg;
>
> reg = ExAllocatePoolWithTag(PagedPool, sizeof(WM_REGISTRATION),
> 'grmw'); if (reg == NULL) {
> return NULL;
> }
>
> RtlZeroMemory(reg, sizeof(WM_REGISTRATION));
> reg->Ref = 1;
>
> reg->pProvider = pProvider;
> WmProviderGet(pProvider);
> return reg;
> }
>
> static int WmConvertMethods(ib_mad_svc_t *svc, WM_IO_REGISTER
> *pAttributes) {
> int i, j, unsolicited = 0;
>
> for (i = 0; i < 16; i++) {
> for (j = 0; j < 8; j++) {
> if (((pAttributes->Methods[i] >> j) & 0x01) !=
0) {
> svc->method_array[i * 8 + j] = 1;
> unsolicited = 1;
> }
> }
> }
>
> return unsolicited;
> }
>
> static NTSTATUS WmRegInit(WM_REGISTRATION *pRegistration,
> WM_IO_REGISTER *pAttributes) {
> WM_IB_DEVICE *dev;
> ib_qp_create_t attr;
> ib_mad_svc_t svc;
> ib_api_status_t ib_status;
> NTSTATUS status;
>
> if (pAttributes->Qpn == 0) {
> attr.qp_type = IB_QPT_QP0_ALIAS;
> } else if (pAttributes->Qpn == IB_QP1) {
> attr.qp_type = IB_QPT_QP1_ALIAS;
> } else {
> return STATUS_BAD_NETWORK_PATH;
> }
>
> dev = WmIbDeviceGet(pAttributes->Guid);
> if (dev == NULL) {
> return STATUS_NO_SUCH_DEVICE;
> }
>
> if (--pAttributes->Port > dev->PortCount) {
> status = STATUS_INVALID_PORT_HANDLE;
> goto err1;
> }
>
> RtlZeroMemory(&attr, sizeof attr);
> attr.sq_depth = attr.rq_depth = 1;
> attr.sq_sge = attr.rq_sge = 1;
> attr.sq_signaled = 1;
>
> ib_status = dev->IbInterface.get_spl_qp(dev->hPd,
>
> dev->pPortArray[pAttributes->Port].Guid,
>
&attr, pRegistration, NULL,
>
&pRegistration->hMadPool,
>
&pRegistration->hQp);
> if (ib_status != IB_SUCCESS) {
> status = STATUS_UNSUCCESSFUL;
> goto err1;
> }
>
> svc.mad_svc_context = pRegistration->pProvider;
> svc.pfn_mad_send_cb = WmSendHandler;
> svc.pfn_mad_recv_cb = WmReceiveHandler;
> svc.support_unsol = WmConvertMethods(&svc, pAttributes);
> svc.mgmt_class = pAttributes->Class;
> svc.mgmt_version = pAttributes->Version;
> svc.svc_type = IB_MAD_SVC_DEFAULT;
>
> ib_status = dev->IbInterface.reg_mad_svc(pRegistration->hQp,
&svc,
>
&pRegistration->hService);
> if (ib_status != IB_SUCCESS) {
> status = STATUS_UNSUCCESSFUL;
> goto err2;
> }
>
> pRegistration->pDevice = dev;
> return STATUS_SUCCESS;
>
> err2:
> dev->IbInterface.destroy_qp(pRegistration->hQp, NULL);
> err1:
> WmIbDevicePut(dev);
> pRegistration->pDevice = NULL;
> return status;
> }
>
> void WmRegister(WM_PROVIDER *pProvider, WDFREQUEST Request)
> {
> WM_REGISTRATION *reg;
> WM_IO_REGISTER *attr;
> UINT64 *id;
> NTSTATUS status;
>
> status = WdfRequestRetrieveInputBuffer(Request,
> sizeof(WM_IO_REGISTER), &attr, NULL); if (!NT_SUCCESS(status)) {
> goto err1;
> }
> status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT64),
> &id, NULL); if (!NT_SUCCESS(status)) {
> goto err1;
> }
>
> reg = WmRegAlloc(pProvider);
> if (reg == NULL) {
> status = STATUS_NO_MEMORY;
> goto err1;
> }
>
> KeAcquireGuardedMutex(&pProvider->Lock);
> WmProviderDisableRemove(pProvider);
> KeReleaseGuardedMutex(&pProvider->Lock);
>
> status = WmRegInit(reg, attr);
> if (!NT_SUCCESS(status)) {
> goto err2;
> }
>
> KeAcquireGuardedMutex(&pProvider->Lock);
> reg->Id = IndexListInsertHead(&pProvider->RegIndex, reg);
> if (reg->Id == 0) {
> status = STATUS_NO_MEMORY;
> goto err2;
> }
> KeReleaseGuardedMutex(&pProvider->Lock);
>
> WmProviderEnableRemove(pProvider);
> *id = reg->Id;
> WdfRequestCompleteWithInformation(Request, status,
sizeof(UINT64));
> return;
>
> err2:
> WmRegFree(reg);
> WmProviderEnableRemove(pProvider);
> err1:
> WdfRequestComplete(Request, status);
> }
>
> void WmDeregister(WM_PROVIDER *pProvider, WDFREQUEST Request)
> {
> WM_REGISTRATION *reg;
> UINT64 *id;
> NTSTATUS status;
>
> status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64),
&id,
> NULL); if (!NT_SUCCESS(status)) {
> goto out;
> }
>
> KeAcquireGuardedMutex(&pProvider->Lock);
> WmProviderDisableRemove(pProvider);
> reg = IndexListAt(&pProvider->RegIndex, (SIZE_T) *id);
> if (reg == NULL) {
> status = STATUS_NO_SUCH_DEVICE;
> } else if (reg->Ref > 1) {
> status = STATUS_ACCESS_DENIED;
> } else {
> IndexListRemove(&pProvider->RegIndex, (SIZE_T) *id);
> status = STATUS_SUCCESS;
> }
> KeReleaseGuardedMutex(&pProvider->Lock);
>
> if (NT_SUCCESS(status)) {
> WmRegFree(reg);
> }
> WmProviderEnableRemove(pProvider);
> out:
> WdfRequestComplete(Request, status);
> }
>
> void WmRegFree(WM_REGISTRATION *pRegistatration)
> {
> WmRegRemoveHandler(pRegistatration);
> WmProviderPut(pRegistatration->pProvider);
> ExFreePool(pRegistatration);
> }
>
> void WmRegRemoveHandler(WM_REGISTRATION *pRegistration)
> {
> if (pRegistration->pDevice == NULL) {
> return;
> }
>
>
pRegistration->pDevice->IbInterface.destroy_qp(pRegistration->hQp,
> NULL); WmProviderFlushReceives(pRegistration->pProvider,
> pRegistration); WmIbDevicePut(pRegistration->pDevice);
> pRegistration->pDevice = NULL;
> }
> /*
> * Copyright (c) 2008 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 AWV
> * 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 _WM_REG_H_
> #define _WM_REG_H_
>
> #include <ntddk.h>
> #include <wdm.h>
> #include <iba\ib_types.h>
>
> #include "wm_driver.h"
> #include "wm_provider.h"
>
> typedef struct _WM_REGISTRATION
> {
> WM_PROVIDER *pProvider;
> WM_IB_DEVICE *pDevice;
> LIST_ENTRY Entry;
>
> ib_qp_handle_t hQp;
> ib_pool_key_t hMadPool;
> ib_mad_svc_handle_t hService;
> //UINT8 Port;
>
> SIZE_T Id;
> LONG Ref;
>
> } WM_REGISTRATION;
>
> void WmRegister(WM_PROVIDER *pProvider, WDFREQUEST Request);
> void WmDeregister(WM_PROVIDER *pProvider, WDFREQUEST Request);
> void WmRegFree(WM_REGISTRATION *pRegistration);
> void WmRegRemoveHandler(WM_REGISTRATION *pRegistration);
>
> WM_REGISTRATION *WmRegAcquire(WM_PROVIDER *pProvider, UINT64 Id);
> void WmRegRelease(WM_REGISTRATION *pRegistration);
>
> #endif // __WM_REG_H_
>
>
> _______________________________________________
> ofw mailing list
> ofw at lists.openfabrics.org
> http://lists.openfabrics.org/cgi-bin/mailman/listinfo/ofw
More information about the ofw
mailing list