2 * Copyright (c) 2008 Intel Corporation. All rights reserved.
\r
4 * This software is available to you under the OpenIB.org BSD license
\r
7 * Redistribution and use in source and binary forms, with or
\r
8 * without modification, are permitted provided that the following
\r
9 * conditions are met:
\r
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\r
15 * - Redistributions in binary form must reproduce the above
\r
16 * copyright notice, this list of conditions and the following
\r
17 * disclaimer in the documentation and/or other materials
\r
18 * provided with the distribution.
\r
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
\r
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
30 #include "wv_device.h"
\r
33 #include "wv_ioctl.h"
\r
35 void WvDeviceGet(WV_DEVICE *pDevice)
\r
37 InterlockedIncrement(&pDevice->Ref);
\r
40 void WvDevicePut(WV_DEVICE *pDevice)
\r
42 if (InterlockedDecrement(&pDevice->Ref) == 0) {
\r
43 KeSetEvent(&pDevice->Event, 0, FALSE);
\r
47 WV_DEVICE *WvDeviceAcquire(WV_PROVIDER *pProvider, UINT64 Id)
\r
51 KeAcquireGuardedMutex(&pProvider->Lock);
\r
52 WvProviderDisableRemove(pProvider);
\r
53 dev = IndexListAt(&pProvider->DevIndex, (SIZE_T) Id);
\r
54 if (dev != NULL && dev->hVerbsDevice != NULL) {
\r
58 WvProviderEnableRemove(pProvider);
\r
60 KeReleaseGuardedMutex(&pProvider->Lock);
\r
65 void WvDeviceRelease(WV_DEVICE *pDevice)
\r
67 WvProviderEnableRemove(pDevice->pProvider);
\r
68 WvDevicePut(pDevice);
\r
71 static UINT32 WvDeviceConvertEvent(ib_async_event_t event)
\r
74 case IB_AE_LOCAL_FATAL:
\r
75 return WV_IO_EVENT_ERROR;
\r
76 case IB_AE_PORT_ACTIVE:
\r
77 case IB_AE_PORT_DOWN:
\r
78 return WV_IO_EVENT_STATE;
\r
79 case IB_AE_CLIENT_REREGISTER:
\r
80 case IB_AE_SM_CHANGE:
\r
81 return WV_IO_EVENT_MANAGEMENT;
\r
82 case IB_AE_GID_CHANGE:
\r
83 return WV_IO_EVENT_ADDRESS;
\r
84 case IB_AE_LID_CHANGE:
\r
85 return WV_IO_EVENT_LINK_ADDRESS;
\r
86 case IB_AE_PKEY_CHANGE:
\r
87 return WV_IO_EVENT_PARTITION;
\r
93 static void WvDeviceCompleteRequests(WV_PORT *pPort, NTSTATUS ReqStatus, UINT32 Event)
\r
99 WdfObjectAcquireLock(pPort->Queue);
\r
100 pPort->Flags |= Event;
\r
101 Event = pPort->Flags;
\r
103 status = WdfIoQueueRetrieveNextRequest(pPort->Queue, &request);
\r
104 while (NT_SUCCESS(status)) {
\r
107 status = WdfRequestRetrieveOutputBuffer(request, sizeof(UINT32), &flags, NULL);
\r
108 if (NT_SUCCESS(status)) {
\r
110 WdfRequestCompleteWithInformation(request, ReqStatus, sizeof(UINT32));
\r
112 WdfRequestComplete(request, status);
\r
114 status = WdfIoQueueRetrieveNextRequest(pPort->Queue, &request);
\r
117 WdfObjectReleaseLock(pPort->Queue);
\r
120 static void WvDeviceEventHandler(ib_event_rec_t *pEvent)
\r
126 event = WvDeviceConvertEvent(pEvent->type);
\r
131 dev = CONTAINING_RECORD(pEvent->context, WV_DEVICE, EventHandler);
\r
133 if (event == WV_IO_EVENT_ERROR) {
\r
134 for (i = 0; i < dev->PortCount; i++) {
\r
135 WvDeviceCompleteRequests(&dev->pPorts[i], STATUS_SUCCESS, event);
\r
138 WvDeviceCompleteRequests(&dev->pPorts[pEvent->port_number - 1],
\r
139 STATUS_SUCCESS, event);
\r
143 static WV_DEVICE *WvDeviceAlloc(WV_PROVIDER *pProvider)
\r
147 dev = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_DEVICE), 'cdvw');
\r
152 dev->pDevice = NULL;
\r
153 dev->pVerbs = NULL;
\r
154 dev->hVerbsDevice = NULL;
\r
155 dev->pPorts = NULL;
\r
156 dev->PortCount = 0;
\r
158 InitializeListHead(&dev->PdList);
\r
159 InitializeListHead(&dev->CqList);
\r
160 KeInitializeEvent(&dev->Event, NotificationEvent, FALSE);
\r
161 dev->EventHandler.pfn_async_event_cb = WvDeviceEventHandler;
\r
163 dev->pProvider = pProvider;
\r
164 WvProviderGet(pProvider);
\r
168 static ib_ca_attr_t *WvQueryCaAttributes(WV_DEVICE *pDevice)
\r
170 ib_ca_attr_t *attr;
\r
172 ib_api_status_t ib_status;
\r
175 ib_status = pDevice->pVerbs->query_ca(pDevice->pDevice->hDevice, NULL,
\r
177 if (ib_status != IB_INSUFFICIENT_MEMORY) {
\r
182 attr = ExAllocatePoolWithTag(PagedPool, size, 'acvw');
\r
183 if (attr == NULL) {
\r
187 ib_status = pDevice->pVerbs->query_ca(pDevice->pDevice->hDevice, attr,
\r
189 if (ib_status != IB_SUCCESS) {
\r
190 ExFreePoolWithTag(attr, 'acvw');
\r
198 static NTSTATUS WvDeviceCreatePorts(WV_DEVICE *pDevice)
\r
200 WDF_IO_QUEUE_CONFIG config;
\r
201 ib_ca_attr_t *attr;
\r
205 attr = WvQueryCaAttributes(pDevice);
\r
206 if (attr == NULL) {
\r
207 return STATUS_NO_MEMORY;
\r
210 pDevice->PortCount = attr->num_ports;
\r
211 ExFreePoolWithTag(attr, 'acvw');
\r
213 pDevice->pPorts = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_PORT) *
\r
214 pDevice->PortCount, 'cpvw');
\r
215 if (pDevice->pPorts == NULL) {
\r
216 return STATUS_NO_MEMORY;
\r
219 WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);
\r
220 for (i = 0; i < pDevice->PortCount; i++) {
\r
221 pDevice->pPorts[i].Flags = 0;
\r
222 status = WdfIoQueueCreate(ControlDevice, &config, WDF_NO_OBJECT_ATTRIBUTES,
\r
223 &pDevice->pPorts[i].Queue);
\r
224 if (!NT_SUCCESS(status)) {
\r
229 return STATUS_SUCCESS;
\r
233 WdfObjectDelete(pDevice->pPorts[i].Queue);
\r
235 pDevice->PortCount = 0;
\r
239 static NTSTATUS WvDeviceInit(WV_DEVICE *pDevice, NET64 Guid,
\r
240 ci_umv_buf_t *pVerbsData)
\r
242 WV_RDMA_DEVICE *dev;
\r
243 ib_api_status_t ib_status;
\r
246 dev = WvRdmaDeviceGet(Guid);
\r
248 return STATUS_NO_SUCH_DEVICE;
\r
251 pDevice->pDevice = dev;
\r
252 pDevice->pVerbs = &dev->Interface.Verbs;
\r
254 ib_status = pDevice->pVerbs->um_open_ca(dev->hDevice, pVerbsData,
\r
255 &pDevice->hVerbsDevice);
\r
256 if (ib_status != IB_SUCCESS) {
\r
260 status = WvDeviceCreatePorts(pDevice);
\r
261 if (!NT_SUCCESS(status)) {
\r
265 pDevice->pVerbs->register_event_handler(dev->hDevice, &pDevice->EventHandler);
\r
266 return STATUS_SUCCESS;
\r
269 pDevice->pVerbs->um_close_ca(dev->hDevice, pDevice->hVerbsDevice);
\r
271 WvRdmaDevicePut(dev);
\r
272 pDevice->hVerbsDevice = NULL;
\r
273 return STATUS_UNSUCCESSFUL;
\r
276 void WvDeviceOpen(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
278 WV_IO_ID *inid, *outid;
\r
279 size_t inlen, outlen;
\r
282 ci_umv_buf_t verbsData;
\r
284 status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &inid, &inlen);
\r
285 if (!NT_SUCCESS(status)) {
\r
288 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_ID), &outid, &outlen);
\r
289 if (!NT_SUCCESS(status)) {
\r
293 dev = WvDeviceAlloc(pProvider);
\r
295 status = STATUS_NO_MEMORY;
\r
299 KeAcquireGuardedMutex(&pProvider->Lock);
\r
300 WvProviderDisableRemove(pProvider);
\r
301 KeReleaseGuardedMutex(&pProvider->Lock);
\r
303 WvInitVerbsData(&verbsData, inid->VerbInfo, inlen - sizeof(WV_IO_ID),
\r
304 outlen - sizeof(WV_IO_ID), inid + 1);
\r
305 status = WvDeviceInit(dev, inid->Id, &verbsData);
\r
306 if (!NT_SUCCESS(status)) {
\r
310 KeAcquireGuardedMutex(&pProvider->Lock);
\r
311 outid->Id = IndexListInsertHead(&pProvider->DevIndex, dev);
\r
312 if (outid->Id == 0) {
\r
313 status = STATUS_NO_MEMORY;
\r
316 KeReleaseGuardedMutex(&pProvider->Lock);
\r
318 WvProviderEnableRemove(pProvider);
\r
319 outid->VerbInfo = verbsData.status;
\r
320 WdfRequestCompleteWithInformation(Request, status, outlen);
\r
325 WvProviderEnableRemove(pProvider);
\r
327 WdfRequestComplete(Request, status);
\r
330 void WvDeviceClose(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
336 status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);
\r
337 if (!NT_SUCCESS(status)) {
\r
341 KeAcquireGuardedMutex(&pProvider->Lock);
\r
342 WvProviderDisableRemove(pProvider);
\r
343 dev = IndexListAt(&pProvider->DevIndex, (SIZE_T) *id);
\r
345 status = STATUS_NO_SUCH_DEVICE;
\r
346 } else if (dev->Ref > 1) {
\r
347 status = STATUS_ACCESS_DENIED;
\r
349 IndexListRemove(&pProvider->DevIndex, (SIZE_T) *id);
\r
350 status = STATUS_SUCCESS;
\r
352 KeReleaseGuardedMutex(&pProvider->Lock);
\r
354 if (NT_SUCCESS(status)) {
\r
357 WvProviderEnableRemove(pProvider);
\r
359 WdfRequestComplete(Request, status);
\r
362 static void WvDeviceFreePorts(WV_DEVICE *pDevice)
\r
366 for (i = 0; i < pDevice->PortCount; i++) {
\r
367 WdfIoQueuePurgeSynchronously(pDevice->pPorts[i].Queue);
\r
368 WdfObjectDelete(pDevice->pPorts[i].Queue);
\r
370 if (pDevice->pPorts != NULL) {
\r
371 ExFreePoolWithTag(pDevice->pPorts, 'cpvw');
\r
375 void WvDeviceFree(WV_DEVICE *pDevice)
\r
377 if (InterlockedDecrement(&pDevice->Ref) > 0) {
\r
378 KeWaitForSingleObject(&pDevice->Event, Executive, KernelMode, FALSE, NULL);
\r
381 if (pDevice->hVerbsDevice != NULL) {
\r
382 pDevice->pVerbs->unregister_event_handler(pDevice->pDevice->hDevice,
\r
383 &pDevice->EventHandler);
\r
384 pDevice->pVerbs->um_close_ca(pDevice->pDevice->hDevice,
\r
385 pDevice->hVerbsDevice);
\r
386 WvRdmaDevicePut(pDevice->pDevice);
\r
389 WvDeviceFreePorts(pDevice);
\r
390 WvProviderPut(pDevice->pProvider);
\r
391 ExFreePoolWithTag(pDevice, 'cdvw');
\r
394 void WvDeviceRemoveHandler(WV_DEVICE *pDevice)
\r
397 WV_PROTECTION_DOMAIN *pd;
\r
398 WV_COMPLETION_QUEUE *cq;
\r
400 for (entry = pDevice->PdList.Flink; entry != &pDevice->PdList;
\r
401 entry = entry->Flink) {
\r
402 pd = CONTAINING_RECORD(entry, WV_PROTECTION_DOMAIN, Entry);
\r
403 WvPdRemoveHandler(pd);
\r
406 for (entry = pDevice->CqList.Flink; entry != &pDevice->CqList;
\r
407 entry = entry->Flink) {
\r
408 cq = CONTAINING_RECORD(entry, WV_COMPLETION_QUEUE, Entry);
\r
409 pDevice->pVerbs->destroy_cq(cq->hVerbsCq);
\r
410 cq->hVerbsCq = NULL;
\r
414 pDevice->pVerbs->um_close_ca(pDevice->pDevice->hDevice,
\r
415 pDevice->hVerbsDevice);
\r
416 WvRdmaDevicePut(pDevice->pDevice);
\r
417 pDevice->pDevice = NULL;
\r
418 pDevice->pVerbs = NULL;
\r
419 pDevice->hVerbsDevice = NULL;
\r
422 static void WvSetDeviceCap(UINT32 *pFlags, ib_ca_attr_t *pCaAttr)
\r
426 *pFlags |= pCaAttr->bad_pkey_ctr_support ? WV_IO_BAD_PKEY_COUNTER : 0;
\r
427 *pFlags |= pCaAttr->bad_qkey_ctr_support ? WV_IO_BAD_QKEY_COUNTER : 0;
\r
428 *pFlags |= pCaAttr->apm_support ? WV_IO_PATH_MIGRATION : 0;
\r
429 *pFlags |= pCaAttr->av_port_check ? WV_IO_AH_PORT_CHECKING : 0;
\r
430 *pFlags |= pCaAttr->change_primary_port ? WV_IO_CHANGE_PHYSICAL_PORT : 0;
\r
431 *pFlags |= pCaAttr->modify_wr_depth ? WV_IO_RESIZE_MAX_WR : 0;
\r
432 *pFlags |= pCaAttr->modify_srq_depth ? WV_IO_SRQ_RESIZE : 0;
\r
433 *pFlags |= pCaAttr->current_qp_state_support ? WV_IO_QP_STATE_MODIFIER : 0;
\r
434 *pFlags |= pCaAttr->shutdown_port_capability ? WV_IO_SHUTDOWN_PORT : 0;
\r
435 *pFlags |= pCaAttr->init_type_support ? WV_IO_INIT_TYPE : 0;
\r
436 *pFlags |= pCaAttr->port_active_event_support ? WV_IO_PORT_ACTIVE_EVENT : 0;
\r
437 *pFlags |= pCaAttr->system_image_guid_support ? WV_IO_SYSTEM_IMAGE_GUID : 0;
\r
438 *pFlags |= WV_IO_RC_RNR_NAK_GENERATION;
\r
439 *pFlags |= WV_IO_BATCH_NOTIFY_CQ;
\r
442 static void WvSetDevicePages(UINT32 *pFlags, ib_ca_attr_t *pCaAttr)
\r
449 for (i = 0; i < pCaAttr->num_page_sizes; i++) {
\r
450 size = pCaAttr->p_page_size[i];
\r
451 *pFlags |= (size & (size - 1)) ? 0 : size;
\r
455 static void WvConvertDevAttr(WV_IO_DEVICE_ATTRIBUTES* pAttributes,
\r
456 ib_ca_attr_t *pCaAttr)
\r
458 pAttributes->FwVersion = pCaAttr->fw_ver;
\r
459 pAttributes->NodeGuid = pCaAttr->ca_guid;
\r
460 pAttributes->SystemImageGuid = pCaAttr->system_image_guid;
\r
461 pAttributes->VendorId = pCaAttr->vend_id;
\r
462 pAttributes->VendorPartId = pCaAttr->dev_id;
\r
463 pAttributes->HwVersion = pCaAttr->revision;
\r
465 WvSetDeviceCap(&pAttributes->CapabilityFlags, pCaAttr);
\r
466 pAttributes->AtomicCapability = (UINT32) pCaAttr->atomicity;
\r
467 WvSetDevicePages(&pAttributes->PageSizeCapabilityFlags, pCaAttr);
\r
469 pAttributes->MaxMrSize = pCaAttr->init_region_size;
\r
470 pAttributes->MaxQp = pCaAttr->max_qps;
\r
471 pAttributes->MaxQpWr = pCaAttr->max_wrs;
\r
472 pAttributes->MaxSge = pCaAttr->max_sges;
\r
473 pAttributes->MaxCq = pCaAttr->max_cqs;
\r
474 pAttributes->MaxCqEntries = pCaAttr->max_cqes;
\r
475 pAttributes->MaxMr = pCaAttr->init_regions;
\r
476 pAttributes->MaxPd = pCaAttr->max_pds;
\r
477 pAttributes->MaxQpResponderResources = pCaAttr->max_qp_resp_res;
\r
478 pAttributes->MaxResponderResources = pCaAttr->max_resp_res;
\r
479 pAttributes->MaxQpInitiatorDepth = pCaAttr->max_qp_init_depth;
\r
480 pAttributes->MaxMw = pCaAttr->init_windows;
\r
481 pAttributes->MaxMulticast = pCaAttr->max_mcast_grps;
\r
482 pAttributes->MaxQpAttach = pCaAttr->max_qps_per_mcast_grp;
\r
483 pAttributes->MaxMulticastQp = pCaAttr->max_mcast_qps;
\r
484 pAttributes->MaxAh = (UINT32) pCaAttr->max_addr_handles;
\r
485 pAttributes->MaxFmr = pCaAttr->max_fmr;
\r
486 pAttributes->MaxMapPerFmr = pCaAttr->max_map_per_fmr;
\r
487 pAttributes->MaxSrq = pCaAttr->max_srq;
\r
488 pAttributes->MaxSrqWr = pCaAttr->max_srq_wrs;
\r
489 pAttributes->MaxSrqSge = pCaAttr->max_srq_sges;
\r
490 pAttributes->MaxPkeys = pCaAttr->max_partitions;
\r
491 pAttributes->DeviceType = WV_DEVICE_INFINIBAND; // TODO: missing in ib_ca_attr_t
\r
492 pAttributes->LocalAckDelay = pCaAttr->local_ack_delay;
\r
493 pAttributes->PhysPortCount = pCaAttr->num_ports;
\r
496 static void WvConvertPortCap(UINT32 *pFlags, ib_port_cap_t *pCap)
\r
500 *pFlags |= pCap->qkey_ctr ? WV_IO_BAD_QKEY_COUNTER : 0;
\r
501 *pFlags |= pCap->pkey_ctr ? WV_IO_BAD_PKEY_COUNTER : 0;
\r
502 *pFlags |= pCap->apm ? WV_IO_PATH_MIGRATION : 0;
\r
503 *pFlags |= pCap->sysguid ? WV_IO_SYSTEM_IMAGE_GUID : 0;
\r
504 *pFlags |= pCap->port_active ? WV_IO_PORT_ACTIVE_EVENT : 0;
\r
506 // TODO: missing in ib_port_attr_t:
\r
507 // WV_IO_RESIZE_MAX_WR
\r
508 // WV_IO_CHANGE_PHYSICAL_PORT
\r
509 // WV_IO_AH_PORT_CHECKING
\r
510 *pFlags |= WV_IO_QP_STATE_MODIFIER;
\r
511 // WV_IO_SHUTDOWN_PORT
\r
513 *pFlags |= WV_IO_RC_RNR_NAK_GENERATION;
\r
514 // WV_IO_SRQ_RESIZE
\r
515 *pFlags |= WV_IO_BATCH_NOTIFY_CQ;
\r
518 static void WvConvertPortAttr(WV_IO_PORT_ATTRIBUTES *pAttributes,
\r
519 ib_port_attr_t *pPortAttr)
\r
521 WvConvertPortCap(&pAttributes->PortCabilityFlags, &pPortAttr->cap);
\r
522 pAttributes->State = pPortAttr->link_state;
\r
523 pAttributes->MaxMtu = 0x80 << pPortAttr->mtu;
\r
524 pAttributes->ActiveMtu = 0x80 << pPortAttr->mtu;
\r
525 pAttributes->GidTableLength = pPortAttr->num_gids;
\r
526 pAttributes->MaxMessageSize = (UINT32) pPortAttr->max_msg_size;
\r
527 pAttributes->BadPkeyCounter = pPortAttr->pkey_ctr;
\r
528 pAttributes->QkeyViolationCounter = pPortAttr->qkey_ctr;
\r
529 pAttributes->PkeyTableLength = pPortAttr->num_pkeys;
\r
530 pAttributes->Lid = pPortAttr->lid;
\r
531 pAttributes->SmLid = pPortAttr->sm_lid;
\r
532 pAttributes->Lmc = pPortAttr->lmc;
\r
533 pAttributes->MaxVls = (UINT8) pPortAttr->max_vls;
\r
534 pAttributes->SmSl = pPortAttr->sm_sl;
\r
535 pAttributes->SubnetTimeout = pPortAttr->subnet_timeout;
\r
536 pAttributes->InitTypeReply = pPortAttr->init_type_reply;
\r
537 pAttributes->ActiveWidth = pPortAttr->active_width;
\r
538 pAttributes->ActiveSpeed = pPortAttr->active_speed;
\r
539 pAttributes->PhysicalState = pPortAttr->phys_state;
\r
540 pAttributes->Reserved[0] = 0;
\r
541 pAttributes->Reserved[1] = 0;
\r
544 void WvDeviceQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
547 WV_IO_DEVICE_ATTRIBUTES *attr;
\r
549 ib_ca_attr_t *ca_attr;
\r
553 status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);
\r
554 if (!NT_SUCCESS(status)) {
\r
557 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_DEVICE_ATTRIBUTES),
\r
559 if (!NT_SUCCESS(status)) {
\r
563 dev = WvDeviceAcquire(pProvider, *id);
\r
565 status = STATUS_NO_SUCH_DEVICE;
\r
569 ca_attr = WvQueryCaAttributes(dev);
\r
570 WvDeviceRelease(dev);
\r
572 if (ca_attr == NULL) {
\r
573 status = STATUS_NO_MEMORY;
\r
577 WvConvertDevAttr(attr, ca_attr);
\r
578 outlen = sizeof(WV_IO_DEVICE_ATTRIBUTES);
\r
579 ExFreePoolWithTag(ca_attr, 'acvw');
\r
582 WdfRequestCompleteWithInformation(Request, status, outlen);
\r
585 void WvDevicePortQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
587 WV_IO_DEVICE_PORT_QUERY *query;
\r
588 WV_IO_PORT_ATTRIBUTES *attr;
\r
590 ib_ca_attr_t *ca_attr;
\r
594 status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_DEVICE_PORT_QUERY),
\r
596 if (!NT_SUCCESS(status)) {
\r
599 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_PORT_ATTRIBUTES),
\r
601 if (!NT_SUCCESS(status)) {
\r
605 dev = WvDeviceAcquire(pProvider, query->Id);
\r
607 status = STATUS_NO_SUCH_DEVICE;
\r
611 ca_attr = WvQueryCaAttributes(dev);
\r
612 WvDeviceRelease(dev);
\r
614 if (ca_attr == NULL) {
\r
615 status = STATUS_NO_MEMORY;
\r
619 if (--query->PortNumber >= ca_attr->num_ports) {
\r
620 status = STATUS_INVALID_PORT_HANDLE;
\r
624 WvConvertPortAttr(attr, &ca_attr->p_port_attr[query->PortNumber]);
\r
625 outlen = sizeof(WV_IO_PORT_ATTRIBUTES);
\r
628 ExFreePoolWithTag(ca_attr, 'acvw');
\r
630 WdfRequestCompleteWithInformation(Request, status, outlen);
\r
633 void WvDeviceGidQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
635 WV_IO_DEVICE_PORT_QUERY *query;
\r
638 ib_ca_attr_t *ca_attr;
\r
639 ib_port_attr_t *port_attr;
\r
641 size_t i, size, outlen = 0;
\r
643 status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_DEVICE_PORT_QUERY),
\r
645 if (!NT_SUCCESS(status)) {
\r
648 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_GID), &gid, &size);
\r
649 if (!NT_SUCCESS(status)) {
\r
653 dev = WvDeviceAcquire(pProvider, query->Id);
\r
655 status = STATUS_NO_SUCH_DEVICE;
\r
659 ca_attr = WvQueryCaAttributes(dev);
\r
660 WvDeviceRelease(dev);
\r
662 if (ca_attr == NULL) {
\r
663 status = STATUS_NO_MEMORY;
\r
667 if (--query->PortNumber >= ca_attr->num_ports) {
\r
668 status = STATUS_INVALID_PORT_HANDLE;
\r
672 size /= sizeof(WV_IO_GID);
\r
673 port_attr = &ca_attr->p_port_attr[query->PortNumber];
\r
674 for (i = 0; i < size && i < port_attr->num_gids; i++) {
\r
675 RtlCopyMemory(&gid[i], &port_attr->p_gid_table[i], sizeof(WV_IO_GID));
\r
678 outlen = i * sizeof(WV_IO_GID);
\r
679 if (i < port_attr->num_gids) {
\r
680 status = STATUS_MORE_ENTRIES;
\r
684 ExFreePoolWithTag(ca_attr, 'acvw');
\r
686 WdfRequestCompleteWithInformation(Request, status, outlen);
\r
689 void WvDevicePkeyQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
691 WV_IO_DEVICE_PORT_QUERY *query;
\r
694 ib_ca_attr_t *ca_attr;
\r
695 ib_port_attr_t *port_attr;
\r
697 size_t i, size, outlen = 0;
\r
699 status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_DEVICE_PORT_QUERY),
\r
701 if (!NT_SUCCESS(status)) {
\r
704 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(NET16), &pkey, &size);
\r
705 if (!NT_SUCCESS(status)) {
\r
709 dev = WvDeviceAcquire(pProvider, query->Id);
\r
711 status = STATUS_NO_SUCH_DEVICE;
\r
715 ca_attr = WvQueryCaAttributes(dev);
\r
716 WvDeviceRelease(dev);
\r
718 if (ca_attr == NULL) {
\r
719 status = STATUS_NO_MEMORY;
\r
723 if (--query->PortNumber >= ca_attr->num_ports) {
\r
724 status = STATUS_INVALID_PORT_HANDLE;
\r
728 size /= sizeof(NET16);
\r
729 port_attr = &ca_attr->p_port_attr[query->PortNumber];
\r
730 for (i = 0; i < size && i < port_attr->num_pkeys; i++) {
\r
731 pkey[i] = port_attr->p_pkey_table[i];
\r
734 outlen = i * sizeof(NET16);
\r
735 if (i < port_attr->num_pkeys) {
\r
736 status = STATUS_MORE_ENTRIES;
\r
740 ExFreePoolWithTag(ca_attr, 'acvw');
\r
742 WdfRequestCompleteWithInformation(Request, status, outlen);
\r
745 void WvDeviceNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
753 status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &id, NULL);
\r
754 if (!NT_SUCCESS(status)) {
\r
758 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT32), &flags, NULL);
\r
759 if (!NT_SUCCESS(status)) {
\r
763 dev = WvDeviceAcquire(pProvider, id->Id);
\r
765 status = STATUS_NOT_FOUND;
\r
769 if (--id->Data >= dev->PortCount) {
\r
770 status = STATUS_INVALID_PORT_HANDLE;
\r
774 port = &dev->pPorts[id->Data];
\r
775 WdfObjectAcquireLock(port->Queue);
\r
777 if (port->Flags == 0) {
\r
778 status = WdfRequestForwardToIoQueue(Request, port->Queue);
\r
780 *flags = port->Flags;
\r
781 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, sizeof(UINT32));
\r
785 WdfObjectReleaseLock(port->Queue);
\r
787 WvDeviceRelease(dev);
\r
789 if (!NT_SUCCESS(status)) {
\r
790 WdfRequestComplete(Request, status);
\r
794 void WvDeviceCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
801 status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);
\r
802 if (!NT_SUCCESS(status)) {
\r
806 dev = WvDeviceAcquire(pProvider, *id);
\r
808 status = STATUS_NOT_FOUND;
\r
812 for (i = 0; i < dev->PortCount; i++) {
\r
813 WvDeviceCompleteRequests(&dev->pPorts[i], STATUS_CANCELLED, 0);
\r
815 WvDeviceRelease(dev);
\r
818 WdfRequestComplete(Request, status);
\r