[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(&reg->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(&reg->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