[IBAL] Only route GET/SET IB_MCLASS_PERF requests to the HW - all other
[mirror/winof/.git] / core / iou / kernel / iou_pnp.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\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
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\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
19  *\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 AND\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
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 \r
34 /*\r
35  * Implemenation of all PnP functionality for FDO (power policy owners).\r
36  */\r
37 \r
38 \r
39 #include "iou_pnp.h"\r
40 #include "iou_ioc_mgr.h"\r
41 #include <complib/cl_memory.h>\r
42 #include <complib/cl_bus_ifc.h>\r
43 #include <initguid.h>\r
44 #include <iba/iou_ifc.h>\r
45 \r
46 \r
47 static NTSTATUS\r
48 fdo_start(\r
49         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
50         IN                                      IRP* const                              p_irp, \r
51                 OUT                             cl_irp_action_t* const  p_action );\r
52 \r
53 static void\r
54 fdo_release_resources(\r
55         IN                                      DEVICE_OBJECT* const    p_dev_obj );\r
56 \r
57 static NTSTATUS\r
58 fdo_query_remove(\r
59         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
60         IN                                      IRP* const                              p_irp, \r
61                 OUT                             cl_irp_action_t* const  p_action );\r
62 \r
63 static NTSTATUS\r
64 fdo_query_capabilities(\r
65         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
66         IN                                      IRP* const                              p_irp, \r
67                 OUT                             cl_irp_action_t* const  p_action );\r
68 \r
69 static NTSTATUS\r
70 fdo_query_iou_relations(\r
71         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
72         IN                                      IRP* const                              p_irp, \r
73                 OUT                             cl_irp_action_t* const  p_action );\r
74 \r
75 static NTSTATUS\r
76 fdo_query_interface(\r
77         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
78         IN                              IRP* const                                      p_irp, \r
79                 OUT                     cl_irp_action_t* const          p_action );\r
80 \r
81 static NTSTATUS\r
82 __fdo_query_power(\r
83         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
84         IN                              IRP* const                                      p_irp,\r
85                 OUT                     cl_irp_action_t* const          p_action );\r
86 \r
87 static NTSTATUS\r
88 __fdo_set_power(\r
89         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
90         IN                              IRP* const                                      p_irp,\r
91                 OUT                     cl_irp_action_t* const          p_action );\r
92 \r
93 \r
94 /* All PnP code is called at passive, so it can all be paged out. */\r
95 #ifdef ALLOC_PRAGMA\r
96 #pragma alloc_text (PAGE, iou_add_device)\r
97 #pragma alloc_text (PAGE, fdo_start)\r
98 #pragma alloc_text (PAGE, fdo_query_remove)\r
99 #pragma alloc_text (PAGE, fdo_release_resources)\r
100 #pragma alloc_text (PAGE, fdo_query_capabilities)\r
101 #pragma alloc_text (PAGE, fdo_query_iou_relations)\r
102 #pragma alloc_text (PAGE_PNP, __fdo_query_power)\r
103 #pragma alloc_text (PAGE_PNP, __fdo_set_power)\r
104 #endif\r
105 \r
106 \r
107 /* Global virtual function pointer tables shared between all instances of FDO. */\r
108 static const cl_vfptr_pnp_po_t          vfptr_fdo_pnp = {\r
109         "IB IOU",\r
110         fdo_start,\r
111         cl_irp_skip,\r
112         cl_irp_skip,\r
113         cl_do_sync_pnp,\r
114         fdo_query_remove,\r
115         fdo_release_resources,\r
116         cl_do_remove,\r
117         cl_do_sync_pnp,\r
118         cl_irp_skip,\r
119         fdo_query_capabilities,\r
120         cl_irp_skip,\r
121         cl_irp_skip,\r
122         cl_do_sync_pnp,\r
123         fdo_query_iou_relations,\r
124         cl_irp_ignore,\r
125         cl_irp_ignore,\r
126         cl_irp_ignore,\r
127         cl_irp_ignore,\r
128         cl_irp_ignore,\r
129         cl_irp_ignore,\r
130         cl_irp_ignore,\r
131         cl_irp_ignore,                  /* QueryInterface */\r
132         cl_irp_ignore,\r
133         cl_irp_ignore,\r
134         cl_irp_ignore,\r
135         cl_irp_ignore,\r
136         __fdo_query_power,              /* QueryPower */\r
137         __fdo_set_power,                /* SetPower */\r
138         cl_irp_ignore,                  /* PowerSequence */\r
139         cl_irp_ignore                   /* WaitWake */\r
140 };\r
141 /*\r
142  * NOTE: The QueryInterface entry point is not used because we only enable/disable\r
143  * our interface so that user-mode AL can find a device to perform IOCTLs to.\r
144  */\r
145 \r
146 \r
147 NTSTATUS\r
148 iou_add_device(\r
149         IN                              DRIVER_OBJECT                           *p_driver_obj,\r
150         IN                              DEVICE_OBJECT                           *p_pdo )\r
151 {\r
152         NTSTATUS                status;\r
153         DEVICE_OBJECT   *p_dev_obj, *p_next_do;\r
154         iou_fdo_ext_t   *p_ext;\r
155 \r
156         IOU_ENTER( IOU_DBG_PNP );\r
157 \r
158         /* Create the FDO device object to attach to the stack. */\r
159         status = IoCreateDevice( p_driver_obj, sizeof(iou_fdo_ext_t),\r
160                 NULL, FILE_DEVICE_BUS_EXTENDER,\r
161                 FILE_DEVICE_SECURE_OPEN, FALSE, &p_dev_obj );\r
162         if( !NT_SUCCESS(status) )\r
163         {\r
164                 IOU_TRACE_EXIT( IOU_DBG_ERROR, \r
165                         ("Failed to create bus root FDO device.\n") );\r
166                 return status;\r
167         }\r
168 \r
169         p_ext = p_dev_obj->DeviceExtension;\r
170 \r
171         ioc_mgr_construct( &p_ext->ioc_mgr );\r
172 \r
173         p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
174         if( !p_next_do )\r
175         {\r
176                 IoDeleteDevice( p_dev_obj );\r
177                 IOU_TRACE_EXIT( IOU_DBG_ERROR, ("IoAttachToDeviceStack failed.\n") );\r
178                 return STATUS_NO_SUCH_DEVICE;\r
179         }\r
180 \r
181         cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, iou_globals.dbg_lvl,\r
182                 &vfptr_fdo_pnp, NULL );\r
183 \r
184         IOU_EXIT( IOU_DBG_PNP );\r
185         return STATUS_SUCCESS;\r
186 }\r
187 \r
188 \r
189 static NTSTATUS\r
190 __get_iou_ifc(\r
191         IN                                      iou_fdo_ext_t* const    p_ext )\r
192 {\r
193         NTSTATUS                        status;\r
194         IO_STACK_LOCATION       io_stack;\r
195         ib_al_ifc_data_t        data;\r
196 \r
197         IOU_ENTER( IOU_DBG_PNP );\r
198 \r
199         data.type = &GUID_IOU_INTERFACE_DATA;\r
200         data.version = IOU_INTERFACE_DATA_VERSION;\r
201         data.size = sizeof(iou_ifc_data_t);\r
202         data.p_data = &p_ext->ioc_mgr.info;\r
203 \r
204         io_stack.MinorFunction = IRP_MN_QUERY_INTERFACE;\r
205         io_stack.Parameters.QueryInterface.Version = AL_INTERFACE_VERSION;\r
206         io_stack.Parameters.QueryInterface.Size = sizeof(ib_al_ifc_t);\r
207         io_stack.Parameters.QueryInterface.Interface =\r
208                 (INTERFACE*)&p_ext->ioc_mgr.ifc;\r
209         io_stack.Parameters.QueryInterface.InterfaceSpecificData =\r
210                 &data;\r
211         io_stack.Parameters.QueryInterface.InterfaceType = &GUID_IB_AL_INTERFACE;\r
212 \r
213         status = cl_fwd_query_ifc( p_ext->cl_ext.p_next_do, &io_stack );\r
214 \r
215         /*\r
216          * Dereference the interface now so that the bus driver doesn't fail a\r
217          * query remove IRP.  We will always get unloaded before the bus driver\r
218          * since we're a child device.\r
219          */\r
220         if( NT_SUCCESS( status ) )\r
221         {\r
222                 p_ext->ioc_mgr.ifc.wdm.InterfaceDereference(\r
223                         p_ext->ioc_mgr.ifc.wdm.Context );\r
224         }\r
225 \r
226         IOU_EXIT( IOU_DBG_PNP );\r
227         return status;\r
228 }\r
229 \r
230 \r
231 static NTSTATUS\r
232 fdo_start(\r
233         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
234         IN                                      IRP* const                              p_irp, \r
235                 OUT                             cl_irp_action_t* const  p_action )\r
236 {\r
237         NTSTATUS                status;\r
238         iou_fdo_ext_t   *p_ext;\r
239         ib_api_status_t ib_status;\r
240 \r
241         IOU_ENTER( IOU_DBG_PNP );\r
242 \r
243         p_ext = p_dev_obj->DeviceExtension;\r
244 \r
245         /* Handled on the way up. */\r
246         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
247         if( !NT_SUCCESS( status ) )\r
248         {\r
249                 IOU_TRACE_EXIT( IOU_DBG_ERROR, \r
250                         ("Lower drivers failed IRP_MN_START_DEVICE.\n") );\r
251                 return status;\r
252         }\r
253 \r
254         status = __get_iou_ifc( p_ext );\r
255         if( !NT_SUCCESS( status ) )\r
256         {\r
257                 IOU_TRACE_EXIT( IOU_DBG_ERROR,\r
258                         ("Failed to get IOU interface.\n") );\r
259                 return status;\r
260         }\r
261 \r
262         /* Initialize the IOU manager. */\r
263         ib_status = ioc_mgr_init( &p_ext->ioc_mgr );\r
264         if( ib_status != IB_SUCCESS )\r
265         {\r
266                 IOU_TRACE_EXIT( IOU_DBG_ERROR, ("ioc_mgr_init returned %s.\n",\r
267                         p_ext->ioc_mgr.ifc.get_err_str(ib_status)) );\r
268                 return STATUS_UNSUCCESSFUL;\r
269         }\r
270 \r
271         IOU_EXIT( IOU_DBG_PNP );\r
272         return status;\r
273 }\r
274 \r
275 \r
276 static NTSTATUS\r
277 fdo_query_remove(\r
278         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
279         IN                                      IRP* const                              p_irp, \r
280                 OUT                             cl_irp_action_t* const  p_action )\r
281 {\r
282         iou_fdo_ext_t   *p_ext;\r
283 \r
284         IOU_ENTER( IOU_DBG_PNP );\r
285 \r
286         p_ext = p_dev_obj->DeviceExtension;\r
287 \r
288         *p_action = IrpSkip;\r
289         /* The FDO driver must set the status even when passing down. */\r
290         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
291         IOU_EXIT( IOU_DBG_PNP );\r
292         return STATUS_SUCCESS;\r
293 }\r
294 \r
295 \r
296 /*\r
297  * This function gets called after releasing the remove lock and waiting\r
298  * for all other threads to release the lock.  No more modifications will\r
299  * occur to the PDO pointer vectors.\r
300  */\r
301 static void\r
302 fdo_release_resources(\r
303         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
304 {\r
305         iou_fdo_ext_t   *p_ext;\r
306 \r
307         IOU_ENTER( IOU_DBG_PNP );\r
308 \r
309         p_ext = p_dev_obj->DeviceExtension;\r
310 \r
311         //TODO: Fail outstanding I/O operations.\r
312         cl_obj_destroy( &p_ext->ioc_mgr.obj );\r
313 \r
314         IOU_EXIT( IOU_DBG_PNP );\r
315 }\r
316 \r
317 \r
318 static NTSTATUS\r
319 fdo_query_capabilities(\r
320         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
321         IN                                      IRP* const                              p_irp, \r
322                 OUT                             cl_irp_action_t* const  p_action )\r
323 {\r
324         NTSTATUS                        status;\r
325         iou_fdo_ext_t           *p_ext;\r
326         IO_STACK_LOCATION       *p_io_stack;\r
327 \r
328         IOU_ENTER( IOU_DBG_PNP );\r
329 \r
330         p_ext = p_dev_obj->DeviceExtension;\r
331 \r
332         /* Process on the way up. */\r
333         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
334 \r
335         if( !NT_SUCCESS( status ) )\r
336         {\r
337                 IOU_TRACE_EXIT( IOU_DBG_ERROR, \r
338                         ("cl_do_sync_pnp returned %08x.\n", status) );\r
339                 return status;\r
340         }\r
341 \r
342         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
343 \r
344         /*\r
345          * Store the device power maping into our extension since we're\r
346          * the power policy owner.  The mapping is used when handling\r
347          * IRP_MN_SET_POWER IRPs.\r
348          */\r
349         cl_memcpy( p_ext->po_state, \r
350                 p_io_stack->Parameters.DeviceCapabilities.Capabilities->DeviceState,\r
351                 sizeof( p_ext->po_state ) );\r
352 \r
353         IOU_EXIT( IOU_DBG_PNP );\r
354         return status;\r
355 }\r
356 \r
357 \r
358 static NTSTATUS\r
359 fdo_query_iou_relations(\r
360         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
361         IN                              IRP* const                                      p_irp, \r
362                 OUT                     cl_irp_action_t* const          p_action )\r
363 {\r
364         iou_fdo_ext_t   *p_ext;\r
365         NTSTATUS                status;\r
366 \r
367         IOU_ENTER( IOU_DBG_PNP );\r
368 \r
369         p_ext = p_dev_obj->DeviceExtension;\r
370 \r
371         status = ioc_mgr_get_iou_relations( &p_ext->ioc_mgr, p_irp );\r
372         switch( status )\r
373         {\r
374         case STATUS_NO_SUCH_DEVICE:\r
375                 *p_action = IrpSkip;\r
376                 status = STATUS_SUCCESS;\r
377                 break;\r
378 \r
379         case STATUS_SUCCESS:\r
380                 *p_action = IrpPassDown;\r
381                 break;\r
382 \r
383         default:\r
384                 *p_action = IrpComplete;\r
385                 break;\r
386         }\r
387 \r
388         IOU_EXIT( IOU_DBG_PNP );\r
389         return status;\r
390 }\r
391 \r
392 \r
393 static NTSTATUS\r
394 __fdo_query_power(\r
395         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
396         IN                              IRP* const                                      p_irp,\r
397                 OUT                     cl_irp_action_t* const          p_action )\r
398 {\r
399         NTSTATUS                        status = STATUS_SUCCESS;\r
400         IO_STACK_LOCATION       *p_io_stack;\r
401 \r
402         IOU_ENTER( IOU_DBG_POWER );\r
403 \r
404         UNUSED_PARAM( p_dev_obj );\r
405 \r
406         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
407 \r
408         switch( p_io_stack->Parameters.Power.Type )\r
409         {\r
410         case SystemPowerState:\r
411                 /* Fail any requests to hibernate or sleep the system. */\r
412                 switch( p_io_stack->Parameters.Power.State.SystemState )\r
413                 {\r
414                         case PowerSystemWorking:\r
415                         case PowerSystemShutdown:\r
416                                 /* We only support fully working and shutdown system states. */\r
417                                 break;\r
418 \r
419                         default:\r
420                                 status = STATUS_NOT_SUPPORTED;\r
421                 }\r
422                 break;\r
423 \r
424         case DevicePowerState:\r
425                 /* Fail any query for low power states. */\r
426                 switch( p_io_stack->Parameters.Power.State.DeviceState )\r
427                 {\r
428                 case PowerDeviceD0:\r
429                 case PowerDeviceD3:\r
430                         /* We only support fully powered or off power states. */\r
431                         break;\r
432 \r
433                 default:\r
434                         status = STATUS_NOT_SUPPORTED;\r
435                 }\r
436                 break;\r
437         }\r
438 \r
439         if( status == STATUS_NOT_SUPPORTED )\r
440                 *p_action = IrpComplete;\r
441         else\r
442                 *p_action = IrpSkip;\r
443 \r
444         IOU_EXIT( IOU_DBG_POWER );\r
445         return status;\r
446 }\r
447 \r
448 \r
449 static void\r
450 __request_power_completion(\r
451         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
452         IN                              UCHAR                                           minor_function,\r
453         IN                              POWER_STATE                                     power_state,\r
454         IN                              void                                            *context,\r
455         IN                              IO_STATUS_BLOCK                         *p_io_status )\r
456 {\r
457         IRP                                     *p_irp;\r
458         cl_pnp_po_ext_t         *p_ext;\r
459 \r
460         IOU_ENTER( IOU_DBG_PNP );\r
461 \r
462         UNUSED_PARAM( minor_function );\r
463         UNUSED_PARAM( power_state );\r
464 \r
465         p_irp = (IRP*)context;\r
466         p_ext = p_dev_obj->DeviceExtension;\r
467 \r
468         /* Propagate the device IRP status to the system IRP status. */\r
469         p_irp->IoStatus.Status = p_io_status->Status;\r
470 \r
471         /* Continue Power IRP processing. */\r
472         PoStartNextPowerIrp( p_irp );\r
473         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
474         IoReleaseRemoveLock( &p_ext->remove_lock, p_irp );\r
475         IOU_EXIT( IOU_DBG_PNP );\r
476 }\r
477 \r
478 \r
479 /*NOTE: Completion routines must NEVER be pageable. */\r
480 static NTSTATUS\r
481 __set_power_completion(\r
482         IN                              DEVICE_OBJECT                           *p_dev_obj,\r
483         IN                              IRP                                                     *p_irp,\r
484         IN                              void                                            *context )\r
485 {\r
486         NTSTATUS                        status;\r
487         POWER_STATE                     state;\r
488         iou_fdo_ext_t           *p_ext;\r
489         IO_STACK_LOCATION       *p_io_stack;\r
490 \r
491         IOU_ENTER( IOU_DBG_PNP );\r
492 \r
493         UNUSED_PARAM( context );\r
494 \r
495         p_ext = p_dev_obj->DeviceExtension;\r
496         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
497 \r
498         if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
499         {\r
500                 PoStartNextPowerIrp( p_irp );\r
501                 IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
502                 IOU_TRACE_EXIT( IOU_DBG_ERROR, \r
503                         ("IRP_MN_SET_POWER for system failed by lower driver with %08x.\n",\r
504                         p_irp->IoStatus.Status) );\r
505                 return STATUS_SUCCESS;\r
506         }\r
507 \r
508         state.DeviceState = \r
509                 p_ext->po_state[p_io_stack->Parameters.Power.State.SystemState];\r
510 \r
511         /*\r
512          * Send a device power IRP to our devnode.  Using our device object will\r
513          * only work on win2k and other NT based systems.\r
514          */\r
515         status = PoRequestPowerIrp( p_dev_obj, IRP_MN_SET_POWER, state,\r
516                 __request_power_completion, p_irp, NULL );\r
517 \r
518         if( !NT_SUCCESS( p_irp->IoStatus.Status ) )\r
519         {\r
520                 PoStartNextPowerIrp( p_irp );\r
521                 /* Propagate the failure. */\r
522                 p_irp->IoStatus.Status = status;\r
523                 IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
524                 IoReleaseRemoveLock( &p_ext->cl_ext.remove_lock, p_irp );\r
525                 IOU_TRACE( IOU_DBG_ERROR,\r
526                         ("PoRequestPowerIrp returned %08x.\n", status) );\r
527         }\r
528 \r
529         IOU_EXIT( IOU_DBG_PNP );\r
530         return STATUS_MORE_PROCESSING_REQUIRED;\r
531 }\r
532 \r
533 \r
534 static NTSTATUS\r
535 __fdo_set_power(\r
536         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
537         IN                              IRP* const                                      p_irp,\r
538                 OUT                     cl_irp_action_t* const          p_action )\r
539 {\r
540         NTSTATUS                        status;\r
541         IO_STACK_LOCATION       *p_io_stack;\r
542         iou_fdo_ext_t           *p_ext;\r
543 \r
544         IOU_ENTER( IOU_DBG_POWER );\r
545 \r
546         p_ext = p_dev_obj->DeviceExtension;\r
547         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
548 \r
549         switch( p_io_stack->Parameters.Power.Type )\r
550         {\r
551         case SystemPowerState:\r
552                 /*\r
553                  * Process on the way up the stack.  We cannot block since the \r
554                  * power dispatch function can be called at elevated IRQL if the\r
555                  * device is in a paging/hibernation/crash dump path.\r
556                  */\r
557                 IoMarkIrpPending( p_irp );\r
558                 IoCopyCurrentIrpStackLocationToNext( p_irp );\r
559 #pragma warning( push, 3 )\r
560                 IoSetCompletionRoutine( p_irp, __set_power_completion, NULL, \r
561                         TRUE, TRUE, TRUE );\r
562 #pragma warning( pop )\r
563                 PoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
564 \r
565                 *p_action = IrpDoNothing;\r
566                 status = STATUS_PENDING;\r
567                 break;\r
568 \r
569         case DevicePowerState:\r
570         default:\r
571                 /* Pass down and let the PDO driver handle it. */\r
572                 *p_action = IrpIgnore;\r
573                 status = STATUS_SUCCESS;\r
574                 break;\r
575         }\r
576 \r
577         IOU_EXIT( IOU_DBG_POWER );\r
578         return status;\r
579 }\r
580 \r
581 \r
582 void\r
583 update_relations(\r
584         IN                              cl_qlist_t*     const                   p_pdo_list,\r
585         IN      OUT                     DEVICE_RELATIONS* const         p_rel )\r
586 {\r
587         cl_list_item_t  *p_list_item;\r
588         iou_pdo_ext_t   *p_pdo_ext;\r
589 \r
590         IOU_ENTER( IOU_DBG_PNP );\r
591 \r
592         p_list_item = cl_qlist_head( p_pdo_list );\r
593         while( p_list_item != cl_qlist_end( p_pdo_list ) )\r
594         {\r
595                 p_pdo_ext = PARENT_STRUCT( p_list_item, iou_pdo_ext_t, list_item );\r
596 \r
597                 /* Move the list item to the next object. */\r
598                 p_list_item = cl_qlist_next( p_list_item );\r
599 \r
600                 if( !p_pdo_ext->b_present )\r
601                 {\r
602                         /*\r
603                          * We don't report a PDO that is no longer present.  This is how\r
604                          * the PDO will get cleaned up.\r
605                          */\r
606                         p_pdo_ext->b_reported_missing = TRUE;\r
607                         continue;\r
608                 }\r
609                 p_rel->Objects[p_rel->Count] = p_pdo_ext->cl_ext.p_pdo;\r
610                 ObReferenceObject( p_rel->Objects[p_rel->Count++] );\r
611         }\r
612 \r
613         IOU_EXIT( IOU_DBG_PNP );\r
614 }\r