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
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
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
372 void WvDeviceFree(WV_DEVICE *pDevice)
\r
374 if (InterlockedDecrement(&pDevice->Ref) > 0) {
\r
375 KeWaitForSingleObject(&pDevice->Event, Executive, KernelMode, FALSE, NULL);
\r
378 if (pDevice->hVerbsDevice != NULL) {
\r
379 pDevice->pVerbs->unregister_event_handler(pDevice->pDevice->hDevice,
\r
380 &pDevice->EventHandler);
\r
381 pDevice->pVerbs->um_close_ca(pDevice->pDevice->hDevice,
\r
382 pDevice->hVerbsDevice);
\r
383 WvRdmaDevicePut(pDevice->pDevice);
\r
386 WvDeviceFreePorts(pDevice);
\r
387 WvProviderPut(pDevice->pProvider);
\r
388 ExFreePool(pDevice);
\r
391 void WvDeviceRemoveHandler(WV_DEVICE *pDevice)
\r
394 WV_PROTECTION_DOMAIN *pd;
\r
395 WV_COMPLETION_QUEUE *cq;
\r
397 for (entry = pDevice->PdList.Flink; entry != &pDevice->PdList;
\r
398 entry = entry->Flink) {
\r
399 pd = CONTAINING_RECORD(entry, WV_PROTECTION_DOMAIN, Entry);
\r
400 WvPdRemoveHandler(pd);
\r
403 for (entry = pDevice->CqList.Flink; entry != &pDevice->CqList;
\r
404 entry = entry->Flink) {
\r
405 cq = CONTAINING_RECORD(entry, WV_COMPLETION_QUEUE, Entry);
\r
406 pDevice->pVerbs->destroy_cq(cq->hVerbsCq);
\r
407 cq->hVerbsCq = NULL;
\r
411 pDevice->pVerbs->um_close_ca(pDevice->pDevice->hDevice,
\r
412 pDevice->hVerbsDevice);
\r
413 WvRdmaDevicePut(pDevice->pDevice);
\r
414 pDevice->pDevice = NULL;
\r
415 pDevice->pVerbs = NULL;
\r
416 pDevice->hVerbsDevice = NULL;
\r
419 static void WvSetDeviceCap(UINT32 *pFlags, ib_ca_attr_t *pCaAttr)
\r
423 *pFlags |= pCaAttr->bad_pkey_ctr_support ? WV_IO_BAD_PKEY_COUNTER : 0;
\r
424 *pFlags |= pCaAttr->bad_qkey_ctr_support ? WV_IO_BAD_QKEY_COUNTER : 0;
\r
425 *pFlags |= pCaAttr->apm_support ? WV_IO_PATH_MIGRATION : 0;
\r
426 *pFlags |= pCaAttr->av_port_check ? WV_IO_AH_PORT_CHECKING : 0;
\r
427 *pFlags |= pCaAttr->change_primary_port ? WV_IO_CHANGE_PHYSICAL_PORT : 0;
\r
428 *pFlags |= pCaAttr->modify_wr_depth ? WV_IO_RESIZE_MAX_WR : 0;
\r
429 *pFlags |= pCaAttr->modify_srq_depth ? WV_IO_SRQ_RESIZE : 0;
\r
430 *pFlags |= pCaAttr->current_qp_state_support ? WV_IO_QP_STATE_MODIFIER : 0;
\r
431 *pFlags |= pCaAttr->shutdown_port_capability ? WV_IO_SHUTDOWN_PORT : 0;
\r
432 *pFlags |= pCaAttr->init_type_support ? WV_IO_INIT_TYPE : 0;
\r
433 *pFlags |= pCaAttr->port_active_event_support ? WV_IO_PORT_ACTIVE_EVENT : 0;
\r
434 *pFlags |= pCaAttr->system_image_guid_support ? WV_IO_SYSTEM_IMAGE_GUID : 0;
\r
435 *pFlags |= WV_IO_RC_RNR_NAK_GENERATION;
\r
436 *pFlags |= WV_IO_BATCH_NOTIFY_CQ;
\r
439 static void WvSetDevicePages(UINT32 *pFlags, ib_ca_attr_t *pCaAttr)
\r
446 for (i = 0; i < pCaAttr->num_page_sizes; i++) {
\r
447 size = pCaAttr->p_page_size[i];
\r
448 *pFlags |= (size & (size - 1)) ? 0 : size;
\r
452 static void WvConvertDevAttr(WV_IO_DEVICE_ATTRIBUTES* pAttributes,
\r
453 ib_ca_attr_t *pCaAttr)
\r
455 pAttributes->FwVersion = pCaAttr->fw_ver;
\r
456 pAttributes->NodeGuid = pCaAttr->ca_guid;
\r
457 pAttributes->SystemImageGuid = pCaAttr->system_image_guid;
\r
458 pAttributes->VendorId = pCaAttr->vend_id;
\r
459 pAttributes->VendorPartId = pCaAttr->dev_id;
\r
460 pAttributes->HwVersion = pCaAttr->revision;
\r
462 WvSetDeviceCap(&pAttributes->CapabilityFlags, pCaAttr);
\r
463 pAttributes->AtomicCapability = (UINT32) pCaAttr->atomicity;
\r
464 WvSetDevicePages(&pAttributes->PageSizeCapabilityFlags, pCaAttr);
\r
466 pAttributes->MaxMrSize = pCaAttr->init_region_size;
\r
467 pAttributes->MaxQp = pCaAttr->max_qps;
\r
468 pAttributes->MaxQpWr = pCaAttr->max_wrs;
\r
469 pAttributes->MaxSge = pCaAttr->max_sges;
\r
470 pAttributes->MaxCq = pCaAttr->max_cqs;
\r
471 pAttributes->MaxCqEntries = pCaAttr->max_cqes;
\r
472 pAttributes->MaxMr = pCaAttr->init_regions;
\r
473 pAttributes->MaxPd = pCaAttr->max_pds;
\r
474 pAttributes->MaxQpResponderResources = pCaAttr->max_qp_resp_res;
\r
475 pAttributes->MaxResponderResources = pCaAttr->max_resp_res;
\r
476 pAttributes->MaxQpInitiatorDepth = pCaAttr->max_qp_init_depth;
\r
477 pAttributes->MaxMw = pCaAttr->init_windows;
\r
478 pAttributes->MaxMulticast = pCaAttr->max_mcast_grps;
\r
479 pAttributes->MaxQpAttach = pCaAttr->max_qps_per_mcast_grp;
\r
480 pAttributes->MaxMulticastQp = pCaAttr->max_mcast_qps;
\r
481 pAttributes->MaxAh = (UINT32) pCaAttr->max_addr_handles;
\r
482 pAttributes->MaxFmr = pCaAttr->max_fmr;
\r
483 pAttributes->MaxMapPerFmr = pCaAttr->max_map_per_fmr;
\r
484 pAttributes->MaxSrq = pCaAttr->max_srq;
\r
485 pAttributes->MaxSrqWr = pCaAttr->max_srq_wrs;
\r
486 pAttributes->MaxSrqSge = pCaAttr->max_srq_sges;
\r
487 pAttributes->MaxPkeys = pCaAttr->max_partitions;
\r
488 pAttributes->DeviceType = WV_DEVICE_INFINIBAND; // TODO: missing in ib_ca_attr_t
\r
489 pAttributes->LocalAckDelay = pCaAttr->local_ack_delay;
\r
490 pAttributes->PhysPortCount = pCaAttr->num_ports;
\r
493 static void WvConvertPortCap(UINT32 *pFlags, ib_port_cap_t *pCap)
\r
497 *pFlags |= pCap->qkey_ctr ? WV_IO_BAD_QKEY_COUNTER : 0;
\r
498 *pFlags |= pCap->pkey_ctr ? WV_IO_BAD_PKEY_COUNTER : 0;
\r
499 *pFlags |= pCap->apm ? WV_IO_PATH_MIGRATION : 0;
\r
500 *pFlags |= pCap->sysguid ? WV_IO_SYSTEM_IMAGE_GUID : 0;
\r
501 *pFlags |= pCap->port_active ? WV_IO_PORT_ACTIVE_EVENT : 0;
\r
503 // TODO: missing in ib_port_attr_t:
\r
504 // WV_IO_RESIZE_MAX_WR
\r
505 // WV_IO_CHANGE_PHYSICAL_PORT
\r
506 // WV_IO_AH_PORT_CHECKING
\r
507 *pFlags |= WV_IO_QP_STATE_MODIFIER;
\r
508 // WV_IO_SHUTDOWN_PORT
\r
510 *pFlags |= WV_IO_RC_RNR_NAK_GENERATION;
\r
511 // WV_IO_SRQ_RESIZE
\r
512 *pFlags |= WV_IO_BATCH_NOTIFY_CQ;
\r
515 static void WvConvertPortAttr(WV_IO_PORT_ATTRIBUTES *pAttributes,
\r
516 ib_port_attr_t *pPortAttr)
\r
518 WvConvertPortCap(&pAttributes->PortCabilityFlags, &pPortAttr->cap);
\r
519 pAttributes->State = pPortAttr->link_state;
\r
520 pAttributes->MaxMtu = 0x80 << pPortAttr->mtu;
\r
521 pAttributes->ActiveMtu = 0x80 << pPortAttr->mtu;
\r
522 pAttributes->GidTableLength = pPortAttr->num_gids;
\r
523 pAttributes->MaxMessageSize = (UINT32) pPortAttr->max_msg_size;
\r
524 pAttributes->BadPkeyCounter = pPortAttr->pkey_ctr;
\r
525 pAttributes->QkeyViolationCounter = pPortAttr->qkey_ctr;
\r
526 pAttributes->PkeyTableLength = pPortAttr->num_pkeys;
\r
527 pAttributes->Lid = pPortAttr->lid;
\r
528 pAttributes->SmLid = pPortAttr->sm_lid;
\r
529 pAttributes->Lmc = pPortAttr->lmc;
\r
530 pAttributes->MaxVls = (UINT8) pPortAttr->max_vls;
\r
531 pAttributes->SmSl = pPortAttr->sm_sl;
\r
532 pAttributes->SubnetTimeout = pPortAttr->subnet_timeout;
\r
533 pAttributes->InitTypeReply = pPortAttr->init_type_reply;
\r
534 pAttributes->ActiveWidth = pPortAttr->active_width;
\r
535 pAttributes->ActiveSpeed = pPortAttr->active_speed;
\r
536 pAttributes->PhysicalState = pPortAttr->phys_state;
\r
537 pAttributes->Reserved[0] = 0;
\r
538 pAttributes->Reserved[1] = 0;
\r
541 void WvDeviceQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
544 WV_IO_DEVICE_ATTRIBUTES *attr;
\r
546 ib_ca_attr_t *ca_attr;
\r
550 status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);
\r
551 if (!NT_SUCCESS(status)) {
\r
554 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_DEVICE_ATTRIBUTES),
\r
556 if (!NT_SUCCESS(status)) {
\r
560 dev = WvDeviceAcquire(pProvider, *id);
\r
562 status = STATUS_NO_SUCH_DEVICE;
\r
566 ca_attr = WvQueryCaAttributes(dev);
\r
567 WvDeviceRelease(dev);
\r
569 if (ca_attr == NULL) {
\r
570 status = STATUS_NO_MEMORY;
\r
574 WvConvertDevAttr(attr, ca_attr);
\r
575 outlen = sizeof(WV_IO_DEVICE_ATTRIBUTES);
\r
576 ExFreePool(ca_attr);
\r
579 WdfRequestCompleteWithInformation(Request, status, outlen);
\r
582 void WvDevicePortQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
584 WV_IO_DEVICE_PORT_QUERY *query;
\r
585 WV_IO_PORT_ATTRIBUTES *attr;
\r
587 ib_ca_attr_t *ca_attr;
\r
591 status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_DEVICE_PORT_QUERY),
\r
593 if (!NT_SUCCESS(status)) {
\r
596 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_PORT_ATTRIBUTES),
\r
598 if (!NT_SUCCESS(status)) {
\r
602 dev = WvDeviceAcquire(pProvider, query->Id);
\r
604 status = STATUS_NO_SUCH_DEVICE;
\r
608 ca_attr = WvQueryCaAttributes(dev);
\r
609 WvDeviceRelease(dev);
\r
611 if (ca_attr == NULL) {
\r
612 status = STATUS_NO_MEMORY;
\r
616 if (--query->PortNumber >= ca_attr->num_ports) {
\r
617 status = STATUS_INVALID_PORT_HANDLE;
\r
621 WvConvertPortAttr(attr, &ca_attr->p_port_attr[query->PortNumber]);
\r
622 outlen = sizeof(WV_IO_PORT_ATTRIBUTES);
\r
625 ExFreePool(ca_attr);
\r
627 WdfRequestCompleteWithInformation(Request, status, outlen);
\r
630 void WvDeviceGidQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
632 WV_IO_DEVICE_PORT_QUERY *query;
\r
635 ib_ca_attr_t *ca_attr;
\r
636 ib_port_attr_t *port_attr;
\r
638 size_t i, size, outlen = 0;
\r
640 status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_DEVICE_PORT_QUERY),
\r
642 if (!NT_SUCCESS(status)) {
\r
645 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_GID), &gid, &size);
\r
646 if (!NT_SUCCESS(status)) {
\r
650 dev = WvDeviceAcquire(pProvider, query->Id);
\r
652 status = STATUS_NO_SUCH_DEVICE;
\r
656 ca_attr = WvQueryCaAttributes(dev);
\r
657 WvDeviceRelease(dev);
\r
659 if (ca_attr == NULL) {
\r
660 status = STATUS_NO_MEMORY;
\r
664 if (--query->PortNumber >= ca_attr->num_ports) {
\r
665 status = STATUS_INVALID_PORT_HANDLE;
\r
669 size /= sizeof(WV_IO_GID);
\r
670 port_attr = &ca_attr->p_port_attr[query->PortNumber];
\r
671 for (i = 0; i < size && i < port_attr->num_gids; i++) {
\r
672 RtlCopyMemory(&gid[i], &port_attr->p_gid_table[i], sizeof(WV_IO_GID));
\r
675 outlen = i * sizeof(WV_IO_GID);
\r
676 if (i < port_attr->num_gids) {
\r
677 status = STATUS_MORE_ENTRIES;
\r
681 ExFreePool(ca_attr);
\r
683 WdfRequestCompleteWithInformation(Request, status, outlen);
\r
686 void WvDevicePkeyQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
688 WV_IO_DEVICE_PORT_QUERY *query;
\r
691 ib_ca_attr_t *ca_attr;
\r
692 ib_port_attr_t *port_attr;
\r
694 size_t i, size, outlen = 0;
\r
696 status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_DEVICE_PORT_QUERY),
\r
698 if (!NT_SUCCESS(status)) {
\r
701 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(NET16), &pkey, &size);
\r
702 if (!NT_SUCCESS(status)) {
\r
706 dev = WvDeviceAcquire(pProvider, query->Id);
\r
708 status = STATUS_NO_SUCH_DEVICE;
\r
712 ca_attr = WvQueryCaAttributes(dev);
\r
713 WvDeviceRelease(dev);
\r
715 if (ca_attr == NULL) {
\r
716 status = STATUS_NO_MEMORY;
\r
720 if (--query->PortNumber >= ca_attr->num_ports) {
\r
721 status = STATUS_INVALID_PORT_HANDLE;
\r
725 size /= sizeof(NET16);
\r
726 port_attr = &ca_attr->p_port_attr[query->PortNumber];
\r
727 for (i = 0; i < size && i < port_attr->num_pkeys; i++) {
\r
728 pkey[i] = port_attr->p_pkey_table[i];
\r
731 outlen = i * sizeof(NET16);
\r
732 if (i < port_attr->num_pkeys) {
\r
733 status = STATUS_MORE_ENTRIES;
\r
737 ExFreePool(ca_attr);
\r
739 WdfRequestCompleteWithInformation(Request, status, outlen);
\r
742 void WvDeviceNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
750 status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &id, NULL);
\r
751 if (!NT_SUCCESS(status)) {
\r
755 status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT32), &flags, NULL);
\r
756 if (!NT_SUCCESS(status)) {
\r
760 dev = WvDeviceAcquire(pProvider, id->Id);
\r
762 status = STATUS_NOT_FOUND;
\r
766 if (--id->Data >= dev->PortCount) {
\r
767 status = STATUS_INVALID_PORT_HANDLE;
\r
771 port = &dev->pPorts[id->Data];
\r
772 WdfObjectAcquireLock(port->Queue);
\r
774 if (port->Flags == 0) {
\r
775 status = WdfRequestForwardToIoQueue(Request, port->Queue);
\r
777 *flags = port->Flags;
\r
778 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, sizeof(UINT32));
\r
782 WdfObjectReleaseLock(port->Queue);
\r
784 WvDeviceRelease(dev);
\r
786 if (!NT_SUCCESS(status)) {
\r
787 WdfRequestComplete(Request, status);
\r
791 void WvDeviceCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)
\r
798 status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);
\r
799 if (!NT_SUCCESS(status)) {
\r
803 dev = WvDeviceAcquire(pProvider, *id);
\r
805 status = STATUS_NOT_FOUND;
\r
809 for (i = 0; i < dev->PortCount; i++) {
\r
810 WvDeviceCompleteRequests(&dev->pPorts[i], STATUS_CANCELLED, 0);
\r
812 WvDeviceRelease(dev);
\r
815 WdfRequestComplete(Request, status);
\r